From 7018e493e3828cc9b45bea8bd87c171fa2198492 Mon Sep 17 00:00:00 2001 From: Aaron Lebahn Date: Sun, 10 Feb 2013 01:31:30 -0700 Subject: [PATCH 001/335] implemented dmpGetGyro(VectorInt16*,const uint8_t*) bassed off of dmpGetAccel(). --- Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h index f85aaaf7..2c77b7ef 100644 --- a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h +++ b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h @@ -603,6 +603,14 @@ uint8_t MPU6050::dmpGetGyro(int16_t *data, const uint8_t* packet) { data[2] = (packet[24] << 8) + packet[25]; return 0; } +uint8_t MPU6050::dmpGetGyro(VectorInt16 *v, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + v -> x = (packet[16] << 8) + packet[17]; + v -> y = (packet[20] << 8) + packet[21]; + v -> z = (packet[24] << 8) + packet[25]; + return 0; +} // uint8_t MPU6050::dmpSetLinearAccelFilterCoefficient(float coef); // uint8_t MPU6050::dmpGetLinearAccel(long *data, const uint8_t* packet); uint8_t MPU6050::dmpGetLinearAccel(VectorInt16 *v, VectorInt16 *vRaw, VectorFloat *gravity) { From f51a38ce3704ba2f737fbd22bf1da223a298e94d Mon Sep 17 00:00:00 2001 From: Eric Wieser Date: Mon, 25 Nov 2013 14:34:49 +0000 Subject: [PATCH 002/335] Handle error codes in derived measurement functions Since `getRawTemperature` and `getRawPressure()` return 0 on failure, the corresponding high-level functions should return `NaN`, rather than processing 0 and emitting a meaningless value. --- Arduino/BMP085/BMP085.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Arduino/BMP085/BMP085.cpp b/Arduino/BMP085/BMP085.cpp index 2119ae1a..a17e45d8 100644 --- a/Arduino/BMP085/BMP085.cpp +++ b/Arduino/BMP085/BMP085.cpp @@ -31,6 +31,7 @@ THE SOFTWARE. */ #include "BMP085.h" +#include /** * Default constructor, uses default I2C device address. @@ -207,6 +208,7 @@ float BMP085::getTemperatureC() { T = (B5 + 8) / 2^4 */ int32_t ut = getRawTemperature(); + if(ut == 0) return NAN; int32_t x1 = ((ut - (int32_t)ac6) * (int32_t)ac5) >> 15; int32_t x2 = ((int32_t)mc << 11) / (x1 + md); b5 = x1 + x2; @@ -244,6 +246,7 @@ float BMP085::getPressure() { p = p + (X1 + X2 + 3791) / 2^4 */ uint32_t up = getRawPressure(); + if(up == 0) return NAN; uint8_t oss = (measureMode & 0xC0) >> 6; int32_t p; int32_t b6 = b5 - 4000; @@ -269,4 +272,4 @@ float BMP085::getPressure() { float BMP085::getAltitude(float pressure, float seaLevelPressure) { return 44330 * (1.0 - pow(pressure / seaLevelPressure, 0.1903)); -} \ No newline at end of file +} From 5f59d75ce01ad0fa2e7c07300eb88f3a1a36a044 Mon Sep 17 00:00:00 2001 From: udawat Date: Tue, 21 Jan 2014 14:54:37 +0530 Subject: [PATCH 003/335] PROGMEM compatibility for ARM Processors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gets rid of ‘pgm_read_byte’ errors on ARM processors. Tested to be working with Texas Instruments’ Tiva C Series Launchpad. Backwards compatible with Arduino Uno (tested and working). --- Arduino/MPU6050/MPU6050.h | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Arduino/MPU6050/MPU6050.h b/Arduino/MPU6050/MPU6050.h index adfbb5d5..7761de8f 100644 --- a/Arduino/MPU6050/MPU6050.h +++ b/Arduino/MPU6050/MPU6050.h @@ -38,8 +38,18 @@ THE SOFTWARE. #define _MPU6050_H_ #include "I2Cdev.h" -//#include +// supporting link: http://forum.arduino.cc/index.php?&topic=143444.msg1079517#msg1079517 +// also: http://forum.arduino.cc/index.php?&topic=141571.msg1062899#msg1062899s +#ifndef __arm__ +#include +#else +#define PROGMEM /* empty */ +#define pgm_read_byte(x) (*(x)) +#define pgm_read_word(x) (*(x)) +#define pgm_read_float(x) (*(x)) +#define PSTR(STR) STR +#endif #define MPU6050_ADDRESS_AD0_LOW 0x68 // address pin low (GND), default for InvenSense evaluation board From f279f6d2e2f6726734fc3e2bc46097199c7651ae Mon Sep 17 00:00:00 2001 From: Cedric Honnet Date: Thu, 13 Feb 2014 16:21:23 -0800 Subject: [PATCH 004/335] Start from a copy of MPU6050 folder. --- .../Examples/MPU6050_DMP6/MPU6050_DMP6.ino | 372 ++ .../MPU6050_DMP6/Processing/MPUTeapot.pde | 247 ++ .../Examples/MPU6050_raw/MPU6050_raw.ino | 151 + Arduino/MPU9150/MPU6050.cpp | 3142 +++++++++++++++++ Arduino/MPU9150/MPU6050.h | 997 ++++++ Arduino/MPU9150/MPU6050_6Axis_MotionApps20.h | 741 ++++ Arduino/MPU9150/MPU6050_9Axis_MotionApps41.h | 852 +++++ Arduino/MPU9150/helper_3dmath.h | 216 ++ 8 files changed, 6718 insertions(+) create mode 100644 Arduino/MPU9150/Examples/MPU6050_DMP6/MPU6050_DMP6.ino create mode 100644 Arduino/MPU9150/Examples/MPU6050_DMP6/Processing/MPUTeapot.pde create mode 100644 Arduino/MPU9150/Examples/MPU6050_raw/MPU6050_raw.ino create mode 100644 Arduino/MPU9150/MPU6050.cpp create mode 100644 Arduino/MPU9150/MPU6050.h create mode 100644 Arduino/MPU9150/MPU6050_6Axis_MotionApps20.h create mode 100644 Arduino/MPU9150/MPU6050_9Axis_MotionApps41.h create mode 100644 Arduino/MPU9150/helper_3dmath.h diff --git a/Arduino/MPU9150/Examples/MPU6050_DMP6/MPU6050_DMP6.ino b/Arduino/MPU9150/Examples/MPU6050_DMP6/MPU6050_DMP6.ino new file mode 100644 index 00000000..be24ffd5 --- /dev/null +++ b/Arduino/MPU9150/Examples/MPU6050_DMP6/MPU6050_DMP6.ino @@ -0,0 +1,372 @@ +// I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class using DMP (MotionApps v2.0) +// 6/21/2012 by Jeff Rowberg +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// 2013-05-08 - added seamless Fastwire support +// - added note about gyro calibration +// 2012-06-21 - added note about Arduino 1.0.1 + Leonardo compatibility error +// 2012-06-20 - improved FIFO overflow handling and simplified read process +// 2012-06-19 - completely rearranged DMP initialization code and simplification +// 2012-06-13 - pull gyro and accel data from FIFO packet instead of reading directly +// 2012-06-09 - fix broken FIFO read sequence and change interrupt detection to RISING +// 2012-06-05 - add gravity-compensated initial reference frame acceleration output +// - add 3D math helper file to DMP6 example sketch +// - add Euler output and Yaw/Pitch/Roll output formats +// 2012-06-04 - remove accel offset clearing for better results (thanks Sungon Lee) +// 2012-06-01 - fixed gyro sensitivity to be 2000 deg/sec instead of 250 +// 2012-05-30 - basic DMP initialization working + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2012 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +// I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files +// for both classes must be in the include path of your project +#include "I2Cdev.h" + +#include "MPU6050_6Axis_MotionApps20.h" +//#include "MPU6050.h" // not necessary if using MotionApps include file + +// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation +// is used in I2Cdev.h +#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE + #include "Wire.h" +#endif + +// class default I2C address is 0x68 +// specific I2C addresses may be passed as a parameter here +// AD0 low = 0x68 (default for SparkFun breakout and InvenSense evaluation board) +// AD0 high = 0x69 +MPU6050 mpu; +//MPU6050 mpu(0x69); // <-- use for AD0 high + +/* ========================================================================= + NOTE: In addition to connection 3.3v, GND, SDA, and SCL, this sketch + depends on the MPU-6050's INT pin being connected to the Arduino's + external interrupt #0 pin. On the Arduino Uno and Mega 2560, this is + digital I/O pin 2. + * ========================================================================= */ + +/* ========================================================================= + NOTE: Arduino v1.0.1 with the Leonardo board generates a compile error + when using Serial.write(buf, len). The Teapot output uses this method. + The solution requires a modification to the Arduino USBAPI.h file, which + is fortunately simple, but annoying. This will be fixed in the next IDE + release. For more info, see these links: + + http://arduino.cc/forum/index.php/topic,109987.0.html + http://code.google.com/p/arduino/issues/detail?id=958 + * ========================================================================= */ + + + +// uncomment "OUTPUT_READABLE_QUATERNION" if you want to see the actual +// quaternion components in a [w, x, y, z] format (not best for parsing +// on a remote host such as Processing or something though) +//#define OUTPUT_READABLE_QUATERNION + +// uncomment "OUTPUT_READABLE_EULER" if you want to see Euler angles +// (in degrees) calculated from the quaternions coming from the FIFO. +// Note that Euler angles suffer from gimbal lock (for more info, see +// http://en.wikipedia.org/wiki/Gimbal_lock) +//#define OUTPUT_READABLE_EULER + +// uncomment "OUTPUT_READABLE_YAWPITCHROLL" if you want to see the yaw/ +// pitch/roll angles (in degrees) calculated from the quaternions coming +// from the FIFO. Note this also requires gravity vector calculations. +// Also note that yaw/pitch/roll angles suffer from gimbal lock (for +// more info, see: http://en.wikipedia.org/wiki/Gimbal_lock) +#define OUTPUT_READABLE_YAWPITCHROLL + +// uncomment "OUTPUT_READABLE_REALACCEL" if you want to see acceleration +// components with gravity removed. This acceleration reference frame is +// not compensated for orientation, so +X is always +X according to the +// sensor, just without the effects of gravity. If you want acceleration +// compensated for orientation, us OUTPUT_READABLE_WORLDACCEL instead. +//#define OUTPUT_READABLE_REALACCEL + +// uncomment "OUTPUT_READABLE_WORLDACCEL" if you want to see acceleration +// components with gravity removed and adjusted for the world frame of +// reference (yaw is relative to initial orientation, since no magnetometer +// is present in this case). Could be quite handy in some cases. +//#define OUTPUT_READABLE_WORLDACCEL + +// uncomment "OUTPUT_TEAPOT" if you want output that matches the +// format used for the InvenSense teapot demo +//#define OUTPUT_TEAPOT + + + +#define LED_PIN 13 // (Arduino is 13, Teensy is 11, Teensy++ is 6) +bool blinkState = false; + +// MPU control/status vars +bool dmpReady = false; // set true if DMP init was successful +uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU +uint8_t devStatus; // return status after each device operation (0 = success, !0 = error) +uint16_t packetSize; // expected DMP packet size (default is 42 bytes) +uint16_t fifoCount; // count of all bytes currently in FIFO +uint8_t fifoBuffer[64]; // FIFO storage buffer + +// orientation/motion vars +Quaternion q; // [w, x, y, z] quaternion container +VectorInt16 aa; // [x, y, z] accel sensor measurements +VectorInt16 aaReal; // [x, y, z] gravity-free accel sensor measurements +VectorInt16 aaWorld; // [x, y, z] world-frame accel sensor measurements +VectorFloat gravity; // [x, y, z] gravity vector +float euler[3]; // [psi, theta, phi] Euler angle container +float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector + +// packet structure for InvenSense teapot demo +uint8_t teapotPacket[14] = { '$', 0x02, 0,0, 0,0, 0,0, 0,0, 0x00, 0x00, '\r', '\n' }; + + + +// ================================================================ +// === INTERRUPT DETECTION ROUTINE === +// ================================================================ + +volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high +void dmpDataReady() { + mpuInterrupt = true; +} + + + +// ================================================================ +// === INITIAL SETUP === +// ================================================================ + +void setup() { + // join I2C bus (I2Cdev library doesn't do this automatically) + #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE + Wire.begin(); + TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz) + #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE + Fastwire::setup(400, true); + #endif + + // initialize serial communication + // (115200 chosen because it is required for Teapot Demo output, but it's + // really up to you depending on your project) + Serial.begin(115200); + while (!Serial); // wait for Leonardo enumeration, others continue immediately + + // NOTE: 8MHz or slower host processors, like the Teensy @ 3.3v or Ardunio + // Pro Mini running at 3.3v, cannot handle this baud rate reliably due to + // the baud timing being too misaligned with processor ticks. You must use + // 38400 or slower in these cases, or use some kind of external separate + // crystal solution for the UART timer. + + // initialize device + Serial.println(F("Initializing I2C devices...")); + mpu.initialize(); + + // verify connection + Serial.println(F("Testing device connections...")); + Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed")); + + // wait for ready + Serial.println(F("\nSend any character to begin DMP programming and demo: ")); + while (Serial.available() && Serial.read()); // empty buffer + while (!Serial.available()); // wait for data + while (Serial.available() && Serial.read()); // empty buffer again + + // load and configure the DMP + Serial.println(F("Initializing DMP...")); + devStatus = mpu.dmpInitialize(); + + // supply your own gyro offsets here, scaled for min sensitivity + mpu.setXGyroOffset(220); + mpu.setYGyroOffset(76); + mpu.setZGyroOffset(-85); + mpu.setZAccelOffset(1788); // 1688 factory default for my test chip + + // make sure it worked (returns 0 if so) + if (devStatus == 0) { + // turn on the DMP, now that it's ready + Serial.println(F("Enabling DMP...")); + mpu.setDMPEnabled(true); + + // enable Arduino interrupt detection + Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)...")); + attachInterrupt(0, dmpDataReady, RISING); + mpuIntStatus = mpu.getIntStatus(); + + // set our DMP Ready flag so the main loop() function knows it's okay to use it + Serial.println(F("DMP ready! Waiting for first interrupt...")); + dmpReady = true; + + // get expected DMP packet size for later comparison + packetSize = mpu.dmpGetFIFOPacketSize(); + } else { + // ERROR! + // 1 = initial memory load failed + // 2 = DMP configuration updates failed + // (if it's going to break, usually the code will be 1) + Serial.print(F("DMP Initialization failed (code ")); + Serial.print(devStatus); + Serial.println(F(")")); + } + + // configure LED for output + pinMode(LED_PIN, OUTPUT); +} + + + +// ================================================================ +// === MAIN PROGRAM LOOP === +// ================================================================ + +void loop() { + // if programming failed, don't try to do anything + if (!dmpReady) return; + + // wait for MPU interrupt or extra packet(s) available + while (!mpuInterrupt && fifoCount < packetSize) { + // other program behavior stuff here + // . + // . + // . + // if you are really paranoid you can frequently test in between other + // stuff to see if mpuInterrupt is true, and if so, "break;" from the + // while() loop to immediately process the MPU data + // . + // . + // . + } + + // reset interrupt flag and get INT_STATUS byte + mpuInterrupt = false; + mpuIntStatus = mpu.getIntStatus(); + + // get current FIFO count + fifoCount = mpu.getFIFOCount(); + + // check for overflow (this should never happen unless our code is too inefficient) + if ((mpuIntStatus & 0x10) || fifoCount == 1024) { + // reset so we can continue cleanly + mpu.resetFIFO(); + Serial.println(F("FIFO overflow!")); + + // otherwise, check for DMP data ready interrupt (this should happen frequently) + } else if (mpuIntStatus & 0x02) { + // wait for correct available data length, should be a VERY short wait + while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount(); + + // read a packet from FIFO + mpu.getFIFOBytes(fifoBuffer, packetSize); + + // track FIFO count here in case there is > 1 packet available + // (this lets us immediately read more without waiting for an interrupt) + fifoCount -= packetSize; + + #ifdef OUTPUT_READABLE_QUATERNION + // display quaternion values in easy matrix form: w x y z + mpu.dmpGetQuaternion(&q, fifoBuffer); + Serial.print("quat\t"); + Serial.print(q.w); + Serial.print("\t"); + Serial.print(q.x); + Serial.print("\t"); + Serial.print(q.y); + Serial.print("\t"); + Serial.println(q.z); + #endif + + #ifdef OUTPUT_READABLE_EULER + // display Euler angles in degrees + mpu.dmpGetQuaternion(&q, fifoBuffer); + mpu.dmpGetEuler(euler, &q); + Serial.print("euler\t"); + Serial.print(euler[0] * 180/M_PI); + Serial.print("\t"); + Serial.print(euler[1] * 180/M_PI); + Serial.print("\t"); + Serial.println(euler[2] * 180/M_PI); + #endif + + #ifdef OUTPUT_READABLE_YAWPITCHROLL + // display Euler angles in degrees + mpu.dmpGetQuaternion(&q, fifoBuffer); + mpu.dmpGetGravity(&gravity, &q); + mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); + Serial.print("ypr\t"); + Serial.print(ypr[0] * 180/M_PI); + Serial.print("\t"); + Serial.print(ypr[1] * 180/M_PI); + Serial.print("\t"); + Serial.println(ypr[2] * 180/M_PI); + #endif + + #ifdef OUTPUT_READABLE_REALACCEL + // display real acceleration, adjusted to remove gravity + mpu.dmpGetQuaternion(&q, fifoBuffer); + mpu.dmpGetAccel(&aa, fifoBuffer); + mpu.dmpGetGravity(&gravity, &q); + mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity); + Serial.print("areal\t"); + Serial.print(aaReal.x); + Serial.print("\t"); + Serial.print(aaReal.y); + Serial.print("\t"); + Serial.println(aaReal.z); + #endif + + #ifdef OUTPUT_READABLE_WORLDACCEL + // display initial world-frame acceleration, adjusted to remove gravity + // and rotated based on known orientation from quaternion + mpu.dmpGetQuaternion(&q, fifoBuffer); + mpu.dmpGetAccel(&aa, fifoBuffer); + mpu.dmpGetGravity(&gravity, &q); + mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity); + mpu.dmpGetLinearAccelInWorld(&aaWorld, &aaReal, &q); + Serial.print("aworld\t"); + Serial.print(aaWorld.x); + Serial.print("\t"); + Serial.print(aaWorld.y); + Serial.print("\t"); + Serial.println(aaWorld.z); + #endif + + #ifdef OUTPUT_TEAPOT + // display quaternion values in InvenSense Teapot demo format: + teapotPacket[2] = fifoBuffer[0]; + teapotPacket[3] = fifoBuffer[1]; + teapotPacket[4] = fifoBuffer[4]; + teapotPacket[5] = fifoBuffer[5]; + teapotPacket[6] = fifoBuffer[8]; + teapotPacket[7] = fifoBuffer[9]; + teapotPacket[8] = fifoBuffer[12]; + teapotPacket[9] = fifoBuffer[13]; + Serial.write(teapotPacket, 14); + teapotPacket[11]++; // packetCount, loops at 0xFF on purpose + #endif + + // blink LED to indicate activity + blinkState = !blinkState; + digitalWrite(LED_PIN, blinkState); + } +} diff --git a/Arduino/MPU9150/Examples/MPU6050_DMP6/Processing/MPUTeapot.pde b/Arduino/MPU9150/Examples/MPU6050_DMP6/Processing/MPUTeapot.pde new file mode 100644 index 00000000..d4c32daf --- /dev/null +++ b/Arduino/MPU9150/Examples/MPU6050_DMP6/Processing/MPUTeapot.pde @@ -0,0 +1,247 @@ +// I2C device class (I2Cdev) demonstration Processing sketch for MPU6050 DMP output +// 6/20/2012 by Jeff Rowberg +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// 2012-06-20 - initial release + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2012 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +import processing.serial.*; +import processing.opengl.*; +import toxi.geom.*; +import toxi.processing.*; + +// NOTE: requires ToxicLibs to be installed in order to run properly. +// 1. Download from http://toxiclibs.org/downloads +// 2. Extract into [userdir]/Processing/libraries +// (location may be different on Mac/Linux) +// 3. Run and bask in awesomeness + +ToxiclibsSupport gfx; + +Serial port; // The serial port +char[] teapotPacket = new char[14]; // InvenSense Teapot packet +int serialCount = 0; // current packet byte position +int aligned = 0; +int interval = 0; + +float[] q = new float[4]; +Quaternion quat = new Quaternion(1, 0, 0, 0); + +float[] gravity = new float[3]; +float[] euler = new float[3]; +float[] ypr = new float[3]; + +void setup() { + // 300px square viewport using OpenGL rendering + size(300, 300, OPENGL); + gfx = new ToxiclibsSupport(this); + + // setup lights and antialiasing + lights(); + smooth(); + + // display serial port list for debugging/clarity + println(Serial.list()); + + // get the first available port (use EITHER this OR the specific port code below) + String portName = Serial.list()[0]; + + // get a specific serial port (use EITHER this OR the first-available code above) + //String portName = "COM4"; + + // open the serial port + port = new Serial(this, portName, 115200); + + // send single character to trigger DMP init/start + // (expected by MPU6050_DMP6 example Arduino sketch) + port.write('r'); +} + +void draw() { + if (millis() - interval > 1000) { + // resend single character to trigger DMP init/start + // in case the MPU is halted/reset while applet is running + port.write('r'); + interval = millis(); + } + + // black background + background(0); + + // translate everything to the middle of the viewport + pushMatrix(); + translate(width / 2, height / 2); + + // 3-step rotation from yaw/pitch/roll angles (gimbal lock!) + // ...and other weirdness I haven't figured out yet + //rotateY(-ypr[0]); + //rotateZ(-ypr[1]); + //rotateX(-ypr[2]); + + // toxiclibs direct angle/axis rotation from quaternion (NO gimbal lock!) + // (axis order [1, 3, 2] and inversion [-1, +1, +1] is a consequence of + // different coordinate system orientation assumptions between Processing + // and InvenSense DMP) + float[] axis = quat.toAxisAngle(); + rotate(axis[0], -axis[1], axis[3], axis[2]); + + // draw main body in red + fill(255, 0, 0, 200); + box(10, 10, 200); + + // draw front-facing tip in blue + fill(0, 0, 255, 200); + pushMatrix(); + translate(0, 0, -120); + rotateX(PI/2); + drawCylinder(0, 20, 20, 8); + popMatrix(); + + // draw wings and tail fin in green + fill(0, 255, 0, 200); + beginShape(TRIANGLES); + vertex(-100, 2, 30); vertex(0, 2, -80); vertex(100, 2, 30); // wing top layer + vertex(-100, -2, 30); vertex(0, -2, -80); vertex(100, -2, 30); // wing bottom layer + vertex(-2, 0, 98); vertex(-2, -30, 98); vertex(-2, 0, 70); // tail left layer + vertex( 2, 0, 98); vertex( 2, -30, 98); vertex( 2, 0, 70); // tail right layer + endShape(); + beginShape(QUADS); + vertex(-100, 2, 30); vertex(-100, -2, 30); vertex( 0, -2, -80); vertex( 0, 2, -80); + vertex( 100, 2, 30); vertex( 100, -2, 30); vertex( 0, -2, -80); vertex( 0, 2, -80); + vertex(-100, 2, 30); vertex(-100, -2, 30); vertex(100, -2, 30); vertex(100, 2, 30); + vertex(-2, 0, 98); vertex(2, 0, 98); vertex(2, -30, 98); vertex(-2, -30, 98); + vertex(-2, 0, 98); vertex(2, 0, 98); vertex(2, 0, 70); vertex(-2, 0, 70); + vertex(-2, -30, 98); vertex(2, -30, 98); vertex(2, 0, 70); vertex(-2, 0, 70); + endShape(); + + popMatrix(); +} + +void serialEvent(Serial port) { + interval = millis(); + while (port.available() > 0) { + int ch = port.read(); + print((char)ch); + if (ch == '$') {serialCount = 0;} // this will help with alignment + if (aligned < 4) { + // make sure we are properly aligned on a 14-byte packet + if (serialCount == 0) { + if (ch == '$') aligned++; else aligned = 0; + } else if (serialCount == 1) { + if (ch == 2) aligned++; else aligned = 0; + } else if (serialCount == 12) { + if (ch == '\r') aligned++; else aligned = 0; + } else if (serialCount == 13) { + if (ch == '\n') aligned++; else aligned = 0; + } + //println(ch + " " + aligned + " " + serialCount); + serialCount++; + if (serialCount == 14) serialCount = 0; + } else { + if (serialCount > 0 || ch == '$') { + teapotPacket[serialCount++] = (char)ch; + if (serialCount == 14) { + serialCount = 0; // restart packet byte position + + // get quaternion from data packet + q[0] = ((teapotPacket[2] << 8) | teapotPacket[3]) / 16384.0f; + q[1] = ((teapotPacket[4] << 8) | teapotPacket[5]) / 16384.0f; + q[2] = ((teapotPacket[6] << 8) | teapotPacket[7]) / 16384.0f; + q[3] = ((teapotPacket[8] << 8) | teapotPacket[9]) / 16384.0f; + for (int i = 0; i < 4; i++) if (q[i] >= 2) q[i] = -4 + q[i]; + + // set our toxilibs quaternion to new data + quat.set(q[0], q[1], q[2], q[3]); + + /* + // below calculations unnecessary for orientation only using toxilibs + + // calculate gravity vector + gravity[0] = 2 * (q[1]*q[3] - q[0]*q[2]); + gravity[1] = 2 * (q[0]*q[1] + q[2]*q[3]); + gravity[2] = q[0]*q[0] - q[1]*q[1] - q[2]*q[2] + q[3]*q[3]; + + // calculate Euler angles + euler[0] = atan2(2*q[1]*q[2] - 2*q[0]*q[3], 2*q[0]*q[0] + 2*q[1]*q[1] - 1); + euler[1] = -asin(2*q[1]*q[3] + 2*q[0]*q[2]); + euler[2] = atan2(2*q[2]*q[3] - 2*q[0]*q[1], 2*q[0]*q[0] + 2*q[3]*q[3] - 1); + + // calculate yaw/pitch/roll angles + ypr[0] = atan2(2*q[1]*q[2] - 2*q[0]*q[3], 2*q[0]*q[0] + 2*q[1]*q[1] - 1); + ypr[1] = atan(gravity[0] / sqrt(gravity[1]*gravity[1] + gravity[2]*gravity[2])); + ypr[2] = atan(gravity[1] / sqrt(gravity[0]*gravity[0] + gravity[2]*gravity[2])); + + // output various components for debugging + //println("q:\t" + round(q[0]*100.0f)/100.0f + "\t" + round(q[1]*100.0f)/100.0f + "\t" + round(q[2]*100.0f)/100.0f + "\t" + round(q[3]*100.0f)/100.0f); + //println("euler:\t" + euler[0]*180.0f/PI + "\t" + euler[1]*180.0f/PI + "\t" + euler[2]*180.0f/PI); + //println("ypr:\t" + ypr[0]*180.0f/PI + "\t" + ypr[1]*180.0f/PI + "\t" + ypr[2]*180.0f/PI); + */ + } + } + } + } +} + +void drawCylinder(float topRadius, float bottomRadius, float tall, int sides) { + float angle = 0; + float angleIncrement = TWO_PI / sides; + beginShape(QUAD_STRIP); + for (int i = 0; i < sides + 1; ++i) { + vertex(topRadius*cos(angle), 0, topRadius*sin(angle)); + vertex(bottomRadius*cos(angle), tall, bottomRadius*sin(angle)); + angle += angleIncrement; + } + endShape(); + + // If it is not a cone, draw the circular top cap + if (topRadius != 0) { + angle = 0; + beginShape(TRIANGLE_FAN); + + // Center point + vertex(0, 0, 0); + for (int i = 0; i < sides + 1; i++) { + vertex(topRadius * cos(angle), 0, topRadius * sin(angle)); + angle += angleIncrement; + } + endShape(); + } + + // If it is not a cone, draw the circular bottom cap + if (bottomRadius != 0) { + angle = 0; + beginShape(TRIANGLE_FAN); + + // Center point + vertex(0, tall, 0); + for (int i = 0; i < sides + 1; i++) { + vertex(bottomRadius * cos(angle), tall, bottomRadius * sin(angle)); + angle += angleIncrement; + } + endShape(); + } +} diff --git a/Arduino/MPU9150/Examples/MPU6050_raw/MPU6050_raw.ino b/Arduino/MPU9150/Examples/MPU6050_raw/MPU6050_raw.ino new file mode 100644 index 00000000..28418a96 --- /dev/null +++ b/Arduino/MPU9150/Examples/MPU6050_raw/MPU6050_raw.ino @@ -0,0 +1,151 @@ +// I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class +// 10/7/2011 by Jeff Rowberg +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// 2013-05-08 - added multiple output formats +// - added seamless Fastwire support +// 2011-10-07 - initial release + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2011 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +// I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files +// for both classes must be in the include path of your project +#include "I2Cdev.h" +#include "MPU6050.h" + +// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation +// is used in I2Cdev.h +#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE + #include "Wire.h" +#endif + +// class default I2C address is 0x68 +// specific I2C addresses may be passed as a parameter here +// AD0 low = 0x68 (default for InvenSense evaluation board) +// AD0 high = 0x69 +MPU6050 accelgyro; +//MPU6050 accelgyro(0x69); // <-- use for AD0 high + +int16_t ax, ay, az; +int16_t gx, gy, gz; + + + +// uncomment "OUTPUT_READABLE_ACCELGYRO" if you want to see a tab-separated +// list of the accel X/Y/Z and then gyro X/Y/Z values in decimal. Easy to read, +// not so easy to parse, and slow(er) over UART. +#define OUTPUT_READABLE_ACCELGYRO + +// uncomment "OUTPUT_BINARY_ACCELGYRO" to send all 6 axes of data as 16-bit +// binary, one right after the other. This is very fast (as fast as possible +// without compression or data loss), and easy to parse, but impossible to read +// for a human. +//#define OUTPUT_BINARY_ACCELGYRO + + +#define LED_PIN 13 +bool blinkState = false; + +void setup() { + // join I2C bus (I2Cdev library doesn't do this automatically) + #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE + Wire.begin(); + #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE + Fastwire::setup(400, true); + #endif + + // initialize serial communication + // (38400 chosen because it works as well at 8MHz as it does at 16MHz, but + // it's really up to you depending on your project) + Serial.begin(38400); + + // initialize device + Serial.println("Initializing I2C devices..."); + accelgyro.initialize(); + + // verify connection + Serial.println("Testing device connections..."); + Serial.println(accelgyro.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed"); + + // use the code below to change accel/gyro offset values + /* + Serial.println("Updating internal sensor offsets..."); + // -76 -2359 1688 0 0 0 + Serial.print(accelgyro.getXAccelOffset()); Serial.print("\t"); // -76 + Serial.print(accelgyro.getYAccelOffset()); Serial.print("\t"); // -2359 + Serial.print(accelgyro.getZAccelOffset()); Serial.print("\t"); // 1688 + Serial.print(accelgyro.getXGyroOffset()); Serial.print("\t"); // 0 + Serial.print(accelgyro.getYGyroOffset()); Serial.print("\t"); // 0 + Serial.print(accelgyro.getZGyroOffset()); Serial.print("\t"); // 0 + Serial.print("\n"); + accelgyro.setXGyroOffset(220); + accelgyro.setYGyroOffset(76); + accelgyro.setZGyroOffset(-85); + Serial.print(accelgyro.getXAccelOffset()); Serial.print("\t"); // -76 + Serial.print(accelgyro.getYAccelOffset()); Serial.print("\t"); // -2359 + Serial.print(accelgyro.getZAccelOffset()); Serial.print("\t"); // 1688 + Serial.print(accelgyro.getXGyroOffset()); Serial.print("\t"); // 0 + Serial.print(accelgyro.getYGyroOffset()); Serial.print("\t"); // 0 + Serial.print(accelgyro.getZGyroOffset()); Serial.print("\t"); // 0 + Serial.print("\n"); + */ + + // configure Arduino LED for + pinMode(LED_PIN, OUTPUT); +} + +void loop() { + // read raw accel/gyro measurements from device + accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz); + + // these methods (and a few others) are also available + //accelgyro.getAcceleration(&ax, &ay, &az); + //accelgyro.getRotation(&gx, &gy, &gz); + + #ifdef OUTPUT_READABLE_ACCELGYRO + // display tab-separated accel/gyro x/y/z values + Serial.print("a/g:\t"); + Serial.print(ax); Serial.print("\t"); + Serial.print(ay); Serial.print("\t"); + Serial.print(az); Serial.print("\t"); + Serial.print(gx); Serial.print("\t"); + Serial.print(gy); Serial.print("\t"); + Serial.println(gz); + #endif + + #ifdef OUTPUT_BINARY_ACCELGYRO + Serial.write((uint8_t)(ax >> 8)); Serial.write((uint8_t)(ax & 0xFF)); + Serial.write((uint8_t)(ay >> 8)); Serial.write((uint8_t)(ay & 0xFF)); + Serial.write((uint8_t)(az >> 8)); Serial.write((uint8_t)(az & 0xFF)); + Serial.write((uint8_t)(gx >> 8)); Serial.write((uint8_t)(gx & 0xFF)); + Serial.write((uint8_t)(gy >> 8)); Serial.write((uint8_t)(gy & 0xFF)); + Serial.write((uint8_t)(gz >> 8)); Serial.write((uint8_t)(gz & 0xFF)); + #endif + + // blink LED to indicate activity + blinkState = !blinkState; + digitalWrite(LED_PIN, blinkState); +} diff --git a/Arduino/MPU9150/MPU6050.cpp b/Arduino/MPU9150/MPU6050.cpp new file mode 100644 index 00000000..3f531efc --- /dev/null +++ b/Arduino/MPU9150/MPU6050.cpp @@ -0,0 +1,3142 @@ +// I2Cdev library collection - MPU6050 I2C device class +// Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00) +// 8/24/2011 by Jeff Rowberg +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// ... - ongoing debug release + +// NOTE: THIS IS ONLY A PARIAL RELEASE. THIS DEVICE CLASS IS CURRENTLY UNDERGOING ACTIVE +// DEVELOPMENT AND IS STILL MISSING SOME IMPORTANT FEATURES. PLEASE KEEP THIS IN MIND IF +// YOU DECIDE TO USE THIS PARTICULAR CODE FOR ANYTHING. + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2012 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#include "MPU6050.h" + +/** Default constructor, uses default I2C address. + * @see MPU6050_DEFAULT_ADDRESS + */ +MPU6050::MPU6050() { + devAddr = MPU6050_DEFAULT_ADDRESS; +} + +/** Specific address constructor. + * @param address I2C address + * @see MPU6050_DEFAULT_ADDRESS + * @see MPU6050_ADDRESS_AD0_LOW + * @see MPU6050_ADDRESS_AD0_HIGH + */ +MPU6050::MPU6050(uint8_t address) { + devAddr = address; +} + +/** Power on and prepare for general usage. + * This will activate the device and take it out of sleep mode (which must be done + * after start-up). This function also sets both the accelerometer and the gyroscope + * to their most sensitive settings, namely +/- 2g and +/- 250 degrees/sec, and sets + * the clock source to use the X Gyro for reference, which is slightly better than + * the default internal clock source. + */ +void MPU6050::initialize() { + setClockSource(MPU6050_CLOCK_PLL_XGYRO); + setFullScaleGyroRange(MPU6050_GYRO_FS_250); + setFullScaleAccelRange(MPU6050_ACCEL_FS_2); + setSleepEnabled(false); // thanks to Jack Elston for pointing this one out! +} + +/** Verify the I2C connection. + * Make sure the device is connected and responds as expected. + * @return True if connection is valid, false otherwise + */ +bool MPU6050::testConnection() { + return getDeviceID() == 0x34; +} + +// AUX_VDDIO register (InvenSense demo code calls this RA_*G_OFFS_TC) + +/** Get the auxiliary I2C supply voltage level. + * When set to 1, the auxiliary I2C bus high logic level is VDD. When cleared to + * 0, the auxiliary I2C bus high logic level is VLOGIC. This does not apply to + * the MPU-6000, which does not have a VLOGIC pin. + * @return I2C supply voltage level (0=VLOGIC, 1=VDD) + */ +uint8_t MPU6050::getAuxVDDIOLevel() { + I2Cdev::readBit(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_PWR_MODE_BIT, buffer); + return buffer[0]; +} +/** Set the auxiliary I2C supply voltage level. + * When set to 1, the auxiliary I2C bus high logic level is VDD. When cleared to + * 0, the auxiliary I2C bus high logic level is VLOGIC. This does not apply to + * the MPU-6000, which does not have a VLOGIC pin. + * @param level I2C supply voltage level (0=VLOGIC, 1=VDD) + */ +void MPU6050::setAuxVDDIOLevel(uint8_t level) { + I2Cdev::writeBit(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_PWR_MODE_BIT, level); +} + +// SMPLRT_DIV register + +/** Get gyroscope output rate divider. + * The sensor register output, FIFO output, DMP sampling, Motion detection, Zero + * Motion detection, and Free Fall detection are all based on the Sample Rate. + * The Sample Rate is generated by dividing the gyroscope output rate by + * SMPLRT_DIV: + * + * Sample Rate = Gyroscope Output Rate / (1 + SMPLRT_DIV) + * + * where Gyroscope Output Rate = 8kHz when the DLPF is disabled (DLPF_CFG = 0 or + * 7), and 1kHz when the DLPF is enabled (see Register 26). + * + * Note: The accelerometer output rate is 1kHz. This means that for a Sample + * Rate greater than 1kHz, the same accelerometer sample may be output to the + * FIFO, DMP, and sensor registers more than once. + * + * For a diagram of the gyroscope and accelerometer signal paths, see Section 8 + * of the MPU-6000/MPU-6050 Product Specification document. + * + * @return Current sample rate + * @see MPU6050_RA_SMPLRT_DIV + */ +uint8_t MPU6050::getRate() { + I2Cdev::readByte(devAddr, MPU6050_RA_SMPLRT_DIV, buffer); + return buffer[0]; +} +/** Set gyroscope sample rate divider. + * @param rate New sample rate divider + * @see getRate() + * @see MPU6050_RA_SMPLRT_DIV + */ +void MPU6050::setRate(uint8_t rate) { + I2Cdev::writeByte(devAddr, MPU6050_RA_SMPLRT_DIV, rate); +} + +// CONFIG register + +/** Get external FSYNC configuration. + * Configures the external Frame Synchronization (FSYNC) pin sampling. An + * external signal connected to the FSYNC pin can be sampled by configuring + * EXT_SYNC_SET. Signal changes to the FSYNC pin are latched so that short + * strobes may be captured. The latched FSYNC signal will be sampled at the + * Sampling Rate, as defined in register 25. After sampling, the latch will + * reset to the current FSYNC signal state. + * + * The sampled value will be reported in place of the least significant bit in + * a sensor data register determined by the value of EXT_SYNC_SET according to + * the following table. + * + *
+ * EXT_SYNC_SET | FSYNC Bit Location
+ * -------------+-------------------
+ * 0            | Input disabled
+ * 1            | TEMP_OUT_L[0]
+ * 2            | GYRO_XOUT_L[0]
+ * 3            | GYRO_YOUT_L[0]
+ * 4            | GYRO_ZOUT_L[0]
+ * 5            | ACCEL_XOUT_L[0]
+ * 6            | ACCEL_YOUT_L[0]
+ * 7            | ACCEL_ZOUT_L[0]
+ * 
+ * + * @return FSYNC configuration value + */ +uint8_t MPU6050::getExternalFrameSync() { + I2Cdev::readBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_EXT_SYNC_SET_BIT, MPU6050_CFG_EXT_SYNC_SET_LENGTH, buffer); + return buffer[0]; +} +/** Set external FSYNC configuration. + * @see getExternalFrameSync() + * @see MPU6050_RA_CONFIG + * @param sync New FSYNC configuration value + */ +void MPU6050::setExternalFrameSync(uint8_t sync) { + I2Cdev::writeBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_EXT_SYNC_SET_BIT, MPU6050_CFG_EXT_SYNC_SET_LENGTH, sync); +} +/** Get digital low-pass filter configuration. + * The DLPF_CFG parameter sets the digital low pass filter configuration. It + * also determines the internal sampling rate used by the device as shown in + * the table below. + * + * Note: The accelerometer output rate is 1kHz. This means that for a Sample + * Rate greater than 1kHz, the same accelerometer sample may be output to the + * FIFO, DMP, and sensor registers more than once. + * + *
+ *          |   ACCELEROMETER    |           GYROSCOPE
+ * DLPF_CFG | Bandwidth | Delay  | Bandwidth | Delay  | Sample Rate
+ * ---------+-----------+--------+-----------+--------+-------------
+ * 0        | 260Hz     | 0ms    | 256Hz     | 0.98ms | 8kHz
+ * 1        | 184Hz     | 2.0ms  | 188Hz     | 1.9ms  | 1kHz
+ * 2        | 94Hz      | 3.0ms  | 98Hz      | 2.8ms  | 1kHz
+ * 3        | 44Hz      | 4.9ms  | 42Hz      | 4.8ms  | 1kHz
+ * 4        | 21Hz      | 8.5ms  | 20Hz      | 8.3ms  | 1kHz
+ * 5        | 10Hz      | 13.8ms | 10Hz      | 13.4ms | 1kHz
+ * 6        | 5Hz       | 19.0ms | 5Hz       | 18.6ms | 1kHz
+ * 7        |   -- Reserved --   |   -- Reserved --   | Reserved
+ * 
+ * + * @return DLFP configuration + * @see MPU6050_RA_CONFIG + * @see MPU6050_CFG_DLPF_CFG_BIT + * @see MPU6050_CFG_DLPF_CFG_LENGTH + */ +uint8_t MPU6050::getDLPFMode() { + I2Cdev::readBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_DLPF_CFG_BIT, MPU6050_CFG_DLPF_CFG_LENGTH, buffer); + return buffer[0]; +} +/** Set digital low-pass filter configuration. + * @param mode New DLFP configuration setting + * @see getDLPFBandwidth() + * @see MPU6050_DLPF_BW_256 + * @see MPU6050_RA_CONFIG + * @see MPU6050_CFG_DLPF_CFG_BIT + * @see MPU6050_CFG_DLPF_CFG_LENGTH + */ +void MPU6050::setDLPFMode(uint8_t mode) { + I2Cdev::writeBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_DLPF_CFG_BIT, MPU6050_CFG_DLPF_CFG_LENGTH, mode); +} + +// GYRO_CONFIG register + +/** Get full-scale gyroscope range. + * The FS_SEL parameter allows setting the full-scale range of the gyro sensors, + * as described in the table below. + * + *
+ * 0 = +/- 250 degrees/sec
+ * 1 = +/- 500 degrees/sec
+ * 2 = +/- 1000 degrees/sec
+ * 3 = +/- 2000 degrees/sec
+ * 
+ * + * @return Current full-scale gyroscope range setting + * @see MPU6050_GYRO_FS_250 + * @see MPU6050_RA_GYRO_CONFIG + * @see MPU6050_GCONFIG_FS_SEL_BIT + * @see MPU6050_GCONFIG_FS_SEL_LENGTH + */ +uint8_t MPU6050::getFullScaleGyroRange() { + I2Cdev::readBits(devAddr, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, buffer); + return buffer[0]; +} +/** Set full-scale gyroscope range. + * @param range New full-scale gyroscope range value + * @see getFullScaleRange() + * @see MPU6050_GYRO_FS_250 + * @see MPU6050_RA_GYRO_CONFIG + * @see MPU6050_GCONFIG_FS_SEL_BIT + * @see MPU6050_GCONFIG_FS_SEL_LENGTH + */ +void MPU6050::setFullScaleGyroRange(uint8_t range) { + I2Cdev::writeBits(devAddr, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, range); +} + +// ACCEL_CONFIG register + +/** Get self-test enabled setting for accelerometer X axis. + * @return Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +bool MPU6050::getAccelXSelfTest() { + I2Cdev::readBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_XA_ST_BIT, buffer); + return buffer[0]; +} +/** Get self-test enabled setting for accelerometer X axis. + * @param enabled Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050::setAccelXSelfTest(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_XA_ST_BIT, enabled); +} +/** Get self-test enabled value for accelerometer Y axis. + * @return Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +bool MPU6050::getAccelYSelfTest() { + I2Cdev::readBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_YA_ST_BIT, buffer); + return buffer[0]; +} +/** Get self-test enabled value for accelerometer Y axis. + * @param enabled Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050::setAccelYSelfTest(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_YA_ST_BIT, enabled); +} +/** Get self-test enabled value for accelerometer Z axis. + * @return Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +bool MPU6050::getAccelZSelfTest() { + I2Cdev::readBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ZA_ST_BIT, buffer); + return buffer[0]; +} +/** Set self-test enabled value for accelerometer Z axis. + * @param enabled Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050::setAccelZSelfTest(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ZA_ST_BIT, enabled); +} +/** Get full-scale accelerometer range. + * The FS_SEL parameter allows setting the full-scale range of the accelerometer + * sensors, as described in the table below. + * + *
+ * 0 = +/- 2g
+ * 1 = +/- 4g
+ * 2 = +/- 8g
+ * 3 = +/- 16g
+ * 
+ * + * @return Current full-scale accelerometer range setting + * @see MPU6050_ACCEL_FS_2 + * @see MPU6050_RA_ACCEL_CONFIG + * @see MPU6050_ACONFIG_AFS_SEL_BIT + * @see MPU6050_ACONFIG_AFS_SEL_LENGTH + */ +uint8_t MPU6050::getFullScaleAccelRange() { + I2Cdev::readBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, buffer); + return buffer[0]; +} +/** Set full-scale accelerometer range. + * @param range New full-scale accelerometer range setting + * @see getFullScaleAccelRange() + */ +void MPU6050::setFullScaleAccelRange(uint8_t range) { + I2Cdev::writeBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, range); +} +/** Get the high-pass filter configuration. + * The DHPF is a filter module in the path leading to motion detectors (Free + * Fall, Motion threshold, and Zero Motion). The high pass filter output is not + * available to the data registers (see Figure in Section 8 of the MPU-6000/ + * MPU-6050 Product Specification document). + * + * The high pass filter has three modes: + * + *
+ *    Reset: The filter output settles to zero within one sample. This
+ *           effectively disables the high pass filter. This mode may be toggled
+ *           to quickly settle the filter.
+ *
+ *    On:    The high pass filter will pass signals above the cut off frequency.
+ *
+ *    Hold:  When triggered, the filter holds the present sample. The filter
+ *           output will be the difference between the input sample and the held
+ *           sample.
+ * 
+ * + *
+ * ACCEL_HPF | Filter Mode | Cut-off Frequency
+ * ----------+-------------+------------------
+ * 0         | Reset       | None
+ * 1         | On          | 5Hz
+ * 2         | On          | 2.5Hz
+ * 3         | On          | 1.25Hz
+ * 4         | On          | 0.63Hz
+ * 7         | Hold        | None
+ * 
+ * + * @return Current high-pass filter configuration + * @see MPU6050_DHPF_RESET + * @see MPU6050_RA_ACCEL_CONFIG + */ +uint8_t MPU6050::getDHPFMode() { + I2Cdev::readBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ACCEL_HPF_BIT, MPU6050_ACONFIG_ACCEL_HPF_LENGTH, buffer); + return buffer[0]; +} +/** Set the high-pass filter configuration. + * @param bandwidth New high-pass filter configuration + * @see setDHPFMode() + * @see MPU6050_DHPF_RESET + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050::setDHPFMode(uint8_t bandwidth) { + I2Cdev::writeBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ACCEL_HPF_BIT, MPU6050_ACONFIG_ACCEL_HPF_LENGTH, bandwidth); +} + +// FF_THR register + +/** Get free-fall event acceleration threshold. + * This register configures the detection threshold for Free Fall event + * detection. The unit of FF_THR is 1LSB = 2mg. Free Fall is detected when the + * absolute value of the accelerometer measurements for the three axes are each + * less than the detection threshold. This condition increments the Free Fall + * duration counter (Register 30). The Free Fall interrupt is triggered when the + * Free Fall duration counter reaches the time specified in FF_DUR. + * + * For more details on the Free Fall detection interrupt, see Section 8.2 of the + * MPU-6000/MPU-6050 Product Specification document as well as Registers 56 and + * 58 of this document. + * + * @return Current free-fall acceleration threshold value (LSB = 2mg) + * @see MPU6050_RA_FF_THR + */ +uint8_t MPU6050::getFreefallDetectionThreshold() { + I2Cdev::readByte(devAddr, MPU6050_RA_FF_THR, buffer); + return buffer[0]; +} +/** Get free-fall event acceleration threshold. + * @param threshold New free-fall acceleration threshold value (LSB = 2mg) + * @see getFreefallDetectionThreshold() + * @see MPU6050_RA_FF_THR + */ +void MPU6050::setFreefallDetectionThreshold(uint8_t threshold) { + I2Cdev::writeByte(devAddr, MPU6050_RA_FF_THR, threshold); +} + +// FF_DUR register + +/** Get free-fall event duration threshold. + * This register configures the duration counter threshold for Free Fall event + * detection. The duration counter ticks at 1kHz, therefore FF_DUR has a unit + * of 1 LSB = 1 ms. + * + * The Free Fall duration counter increments while the absolute value of the + * accelerometer measurements are each less than the detection threshold + * (Register 29). The Free Fall interrupt is triggered when the Free Fall + * duration counter reaches the time specified in this register. + * + * For more details on the Free Fall detection interrupt, see Section 8.2 of + * the MPU-6000/MPU-6050 Product Specification document as well as Registers 56 + * and 58 of this document. + * + * @return Current free-fall duration threshold value (LSB = 1ms) + * @see MPU6050_RA_FF_DUR + */ +uint8_t MPU6050::getFreefallDetectionDuration() { + I2Cdev::readByte(devAddr, MPU6050_RA_FF_DUR, buffer); + return buffer[0]; +} +/** Get free-fall event duration threshold. + * @param duration New free-fall duration threshold value (LSB = 1ms) + * @see getFreefallDetectionDuration() + * @see MPU6050_RA_FF_DUR + */ +void MPU6050::setFreefallDetectionDuration(uint8_t duration) { + I2Cdev::writeByte(devAddr, MPU6050_RA_FF_DUR, duration); +} + +// MOT_THR register + +/** Get motion detection event acceleration threshold. + * This register configures the detection threshold for Motion interrupt + * generation. The unit of MOT_THR is 1LSB = 2mg. Motion is detected when the + * absolute value of any of the accelerometer measurements exceeds this Motion + * detection threshold. This condition increments the Motion detection duration + * counter (Register 32). The Motion detection interrupt is triggered when the + * Motion Detection counter reaches the time count specified in MOT_DUR + * (Register 32). + * + * The Motion interrupt will indicate the axis and polarity of detected motion + * in MOT_DETECT_STATUS (Register 97). + * + * For more details on the Motion detection interrupt, see Section 8.3 of the + * MPU-6000/MPU-6050 Product Specification document as well as Registers 56 and + * 58 of this document. + * + * @return Current motion detection acceleration threshold value (LSB = 2mg) + * @see MPU6050_RA_MOT_THR + */ +uint8_t MPU6050::getMotionDetectionThreshold() { + I2Cdev::readByte(devAddr, MPU6050_RA_MOT_THR, buffer); + return buffer[0]; +} +/** Set free-fall event acceleration threshold. + * @param threshold New motion detection acceleration threshold value (LSB = 2mg) + * @see getMotionDetectionThreshold() + * @see MPU6050_RA_MOT_THR + */ +void MPU6050::setMotionDetectionThreshold(uint8_t threshold) { + I2Cdev::writeByte(devAddr, MPU6050_RA_MOT_THR, threshold); +} + +// MOT_DUR register + +/** Get motion detection event duration threshold. + * This register configures the duration counter threshold for Motion interrupt + * generation. The duration counter ticks at 1 kHz, therefore MOT_DUR has a unit + * of 1LSB = 1ms. The Motion detection duration counter increments when the + * absolute value of any of the accelerometer measurements exceeds the Motion + * detection threshold (Register 31). The Motion detection interrupt is + * triggered when the Motion detection counter reaches the time count specified + * in this register. + * + * For more details on the Motion detection interrupt, see Section 8.3 of the + * MPU-6000/MPU-6050 Product Specification document. + * + * @return Current motion detection duration threshold value (LSB = 1ms) + * @see MPU6050_RA_MOT_DUR + */ +uint8_t MPU6050::getMotionDetectionDuration() { + I2Cdev::readByte(devAddr, MPU6050_RA_MOT_DUR, buffer); + return buffer[0]; +} +/** Set motion detection event duration threshold. + * @param duration New motion detection duration threshold value (LSB = 1ms) + * @see getMotionDetectionDuration() + * @see MPU6050_RA_MOT_DUR + */ +void MPU6050::setMotionDetectionDuration(uint8_t duration) { + I2Cdev::writeByte(devAddr, MPU6050_RA_MOT_DUR, duration); +} + +// ZRMOT_THR register + +/** Get zero motion detection event acceleration threshold. + * This register configures the detection threshold for Zero Motion interrupt + * generation. The unit of ZRMOT_THR is 1LSB = 2mg. Zero Motion is detected when + * the absolute value of the accelerometer measurements for the 3 axes are each + * less than the detection threshold. This condition increments the Zero Motion + * duration counter (Register 34). The Zero Motion interrupt is triggered when + * the Zero Motion duration counter reaches the time count specified in + * ZRMOT_DUR (Register 34). + * + * Unlike Free Fall or Motion detection, Zero Motion detection triggers an + * interrupt both when Zero Motion is first detected and when Zero Motion is no + * longer detected. + * + * When a zero motion event is detected, a Zero Motion Status will be indicated + * in the MOT_DETECT_STATUS register (Register 97). When a motion-to-zero-motion + * condition is detected, the status bit is set to 1. When a zero-motion-to- + * motion condition is detected, the status bit is set to 0. + * + * For more details on the Zero Motion detection interrupt, see Section 8.4 of + * the MPU-6000/MPU-6050 Product Specification document as well as Registers 56 + * and 58 of this document. + * + * @return Current zero motion detection acceleration threshold value (LSB = 2mg) + * @see MPU6050_RA_ZRMOT_THR + */ +uint8_t MPU6050::getZeroMotionDetectionThreshold() { + I2Cdev::readByte(devAddr, MPU6050_RA_ZRMOT_THR, buffer); + return buffer[0]; +} +/** Set zero motion detection event acceleration threshold. + * @param threshold New zero motion detection acceleration threshold value (LSB = 2mg) + * @see getZeroMotionDetectionThreshold() + * @see MPU6050_RA_ZRMOT_THR + */ +void MPU6050::setZeroMotionDetectionThreshold(uint8_t threshold) { + I2Cdev::writeByte(devAddr, MPU6050_RA_ZRMOT_THR, threshold); +} + +// ZRMOT_DUR register + +/** Get zero motion detection event duration threshold. + * This register configures the duration counter threshold for Zero Motion + * interrupt generation. The duration counter ticks at 16 Hz, therefore + * ZRMOT_DUR has a unit of 1 LSB = 64 ms. The Zero Motion duration counter + * increments while the absolute value of the accelerometer measurements are + * each less than the detection threshold (Register 33). The Zero Motion + * interrupt is triggered when the Zero Motion duration counter reaches the time + * count specified in this register. + * + * For more details on the Zero Motion detection interrupt, see Section 8.4 of + * the MPU-6000/MPU-6050 Product Specification document, as well as Registers 56 + * and 58 of this document. + * + * @return Current zero motion detection duration threshold value (LSB = 64ms) + * @see MPU6050_RA_ZRMOT_DUR + */ +uint8_t MPU6050::getZeroMotionDetectionDuration() { + I2Cdev::readByte(devAddr, MPU6050_RA_ZRMOT_DUR, buffer); + return buffer[0]; +} +/** Set zero motion detection event duration threshold. + * @param duration New zero motion detection duration threshold value (LSB = 1ms) + * @see getZeroMotionDetectionDuration() + * @see MPU6050_RA_ZRMOT_DUR + */ +void MPU6050::setZeroMotionDetectionDuration(uint8_t duration) { + I2Cdev::writeByte(devAddr, MPU6050_RA_ZRMOT_DUR, duration); +} + +// FIFO_EN register + +/** Get temperature FIFO enabled value. + * When set to 1, this bit enables TEMP_OUT_H and TEMP_OUT_L (Registers 65 and + * 66) to be written into the FIFO buffer. + * @return Current temperature FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050::getTempFIFOEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_TEMP_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set temperature FIFO enabled value. + * @param enabled New temperature FIFO enabled value + * @see getTempFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050::setTempFIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_TEMP_FIFO_EN_BIT, enabled); +} +/** Get gyroscope X-axis FIFO enabled value. + * When set to 1, this bit enables GYRO_XOUT_H and GYRO_XOUT_L (Registers 67 and + * 68) to be written into the FIFO buffer. + * @return Current gyroscope X-axis FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050::getXGyroFIFOEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_XG_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set gyroscope X-axis FIFO enabled value. + * @param enabled New gyroscope X-axis FIFO enabled value + * @see getXGyroFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050::setXGyroFIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_XG_FIFO_EN_BIT, enabled); +} +/** Get gyroscope Y-axis FIFO enabled value. + * When set to 1, this bit enables GYRO_YOUT_H and GYRO_YOUT_L (Registers 69 and + * 70) to be written into the FIFO buffer. + * @return Current gyroscope Y-axis FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050::getYGyroFIFOEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_YG_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set gyroscope Y-axis FIFO enabled value. + * @param enabled New gyroscope Y-axis FIFO enabled value + * @see getYGyroFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050::setYGyroFIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_YG_FIFO_EN_BIT, enabled); +} +/** Get gyroscope Z-axis FIFO enabled value. + * When set to 1, this bit enables GYRO_ZOUT_H and GYRO_ZOUT_L (Registers 71 and + * 72) to be written into the FIFO buffer. + * @return Current gyroscope Z-axis FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050::getZGyroFIFOEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ZG_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set gyroscope Z-axis FIFO enabled value. + * @param enabled New gyroscope Z-axis FIFO enabled value + * @see getZGyroFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050::setZGyroFIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ZG_FIFO_EN_BIT, enabled); +} +/** Get accelerometer FIFO enabled value. + * When set to 1, this bit enables ACCEL_XOUT_H, ACCEL_XOUT_L, ACCEL_YOUT_H, + * ACCEL_YOUT_L, ACCEL_ZOUT_H, and ACCEL_ZOUT_L (Registers 59 to 64) to be + * written into the FIFO buffer. + * @return Current accelerometer FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050::getAccelFIFOEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ACCEL_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set accelerometer FIFO enabled value. + * @param enabled New accelerometer FIFO enabled value + * @see getAccelFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050::setAccelFIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ACCEL_FIFO_EN_BIT, enabled); +} +/** Get Slave 2 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 2 to be written into the FIFO buffer. + * @return Current Slave 2 FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050::getSlave2FIFOEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV2_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set Slave 2 FIFO enabled value. + * @param enabled New Slave 2 FIFO enabled value + * @see getSlave2FIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050::setSlave2FIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV2_FIFO_EN_BIT, enabled); +} +/** Get Slave 1 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 1 to be written into the FIFO buffer. + * @return Current Slave 1 FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050::getSlave1FIFOEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV1_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set Slave 1 FIFO enabled value. + * @param enabled New Slave 1 FIFO enabled value + * @see getSlave1FIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050::setSlave1FIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV1_FIFO_EN_BIT, enabled); +} +/** Get Slave 0 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 0 to be written into the FIFO buffer. + * @return Current Slave 0 FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050::getSlave0FIFOEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV0_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set Slave 0 FIFO enabled value. + * @param enabled New Slave 0 FIFO enabled value + * @see getSlave0FIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050::setSlave0FIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV0_FIFO_EN_BIT, enabled); +} + +// I2C_MST_CTRL register + +/** Get multi-master enabled value. + * Multi-master capability allows multiple I2C masters to operate on the same + * bus. In circuits where multi-master capability is required, set MULT_MST_EN + * to 1. This will increase current drawn by approximately 30uA. + * + * In circuits where multi-master capability is required, the state of the I2C + * bus must always be monitored by each separate I2C Master. Before an I2C + * Master can assume arbitration of the bus, it must first confirm that no other + * I2C Master has arbitration of the bus. When MULT_MST_EN is set to 1, the + * MPU-60X0's bus arbitration detection logic is turned on, enabling it to + * detect when the bus is available. + * + * @return Current multi-master enabled value + * @see MPU6050_RA_I2C_MST_CTRL + */ +bool MPU6050::getMultiMasterEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_MULT_MST_EN_BIT, buffer); + return buffer[0]; +} +/** Set multi-master enabled value. + * @param enabled New multi-master enabled value + * @see getMultiMasterEnabled() + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050::setMultiMasterEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_MULT_MST_EN_BIT, enabled); +} +/** Get wait-for-external-sensor-data enabled value. + * When the WAIT_FOR_ES bit is set to 1, the Data Ready interrupt will be + * delayed until External Sensor data from the Slave Devices are loaded into the + * EXT_SENS_DATA registers. This is used to ensure that both the internal sensor + * data (i.e. from gyro and accel) and external sensor data have been loaded to + * their respective data registers (i.e. the data is synced) when the Data Ready + * interrupt is triggered. + * + * @return Current wait-for-external-sensor-data enabled value + * @see MPU6050_RA_I2C_MST_CTRL + */ +bool MPU6050::getWaitForExternalSensorEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_WAIT_FOR_ES_BIT, buffer); + return buffer[0]; +} +/** Set wait-for-external-sensor-data enabled value. + * @param enabled New wait-for-external-sensor-data enabled value + * @see getWaitForExternalSensorEnabled() + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050::setWaitForExternalSensorEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_WAIT_FOR_ES_BIT, enabled); +} +/** Get Slave 3 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 3 to be written into the FIFO buffer. + * @return Current Slave 3 FIFO enabled value + * @see MPU6050_RA_MST_CTRL + */ +bool MPU6050::getSlave3FIFOEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_SLV_3_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set Slave 3 FIFO enabled value. + * @param enabled New Slave 3 FIFO enabled value + * @see getSlave3FIFOEnabled() + * @see MPU6050_RA_MST_CTRL + */ +void MPU6050::setSlave3FIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_SLV_3_FIFO_EN_BIT, enabled); +} +/** Get slave read/write transition enabled value. + * The I2C_MST_P_NSR bit configures the I2C Master's transition from one slave + * read to the next slave read. If the bit equals 0, there will be a restart + * between reads. If the bit equals 1, there will be a stop followed by a start + * of the following read. When a write transaction follows a read transaction, + * the stop followed by a start of the successive write will be always used. + * + * @return Current slave read/write transition enabled value + * @see MPU6050_RA_I2C_MST_CTRL + */ +bool MPU6050::getSlaveReadWriteTransitionEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_P_NSR_BIT, buffer); + return buffer[0]; +} +/** Set slave read/write transition enabled value. + * @param enabled New slave read/write transition enabled value + * @see getSlaveReadWriteTransitionEnabled() + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050::setSlaveReadWriteTransitionEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_P_NSR_BIT, enabled); +} +/** Get I2C master clock speed. + * I2C_MST_CLK is a 4 bit unsigned value which configures a divider on the + * MPU-60X0 internal 8MHz clock. It sets the I2C master clock speed according to + * the following table: + * + *
+ * I2C_MST_CLK | I2C Master Clock Speed | 8MHz Clock Divider
+ * ------------+------------------------+-------------------
+ * 0           | 348kHz                 | 23
+ * 1           | 333kHz                 | 24
+ * 2           | 320kHz                 | 25
+ * 3           | 308kHz                 | 26
+ * 4           | 296kHz                 | 27
+ * 5           | 286kHz                 | 28
+ * 6           | 276kHz                 | 29
+ * 7           | 267kHz                 | 30
+ * 8           | 258kHz                 | 31
+ * 9           | 500kHz                 | 16
+ * 10          | 471kHz                 | 17
+ * 11          | 444kHz                 | 18
+ * 12          | 421kHz                 | 19
+ * 13          | 400kHz                 | 20
+ * 14          | 381kHz                 | 21
+ * 15          | 364kHz                 | 22
+ * 
+ * + * @return Current I2C master clock speed + * @see MPU6050_RA_I2C_MST_CTRL + */ +uint8_t MPU6050::getMasterClockSpeed() { + I2Cdev::readBits(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_CLK_BIT, MPU6050_I2C_MST_CLK_LENGTH, buffer); + return buffer[0]; +} +/** Set I2C master clock speed. + * @reparam speed Current I2C master clock speed + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050::setMasterClockSpeed(uint8_t speed) { + I2Cdev::writeBits(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_CLK_BIT, MPU6050_I2C_MST_CLK_LENGTH, speed); +} + +// I2C_SLV* registers (Slave 0-3) + +/** Get the I2C address of the specified slave (0-3). + * Note that Bit 7 (MSB) controls read/write mode. If Bit 7 is set, it's a read + * operation, and if it is cleared, then it's a write operation. The remaining + * bits (6-0) are the 7-bit device address of the slave device. + * + * In read mode, the result of the read is placed in the lowest available + * EXT_SENS_DATA register. For further information regarding the allocation of + * read results, please refer to the EXT_SENS_DATA register description + * (Registers 73 - 96). + * + * The MPU-6050 supports a total of five slaves, but Slave 4 has unique + * characteristics, and so it has its own functions (getSlave4* and setSlave4*). + * + * I2C data transactions are performed at the Sample Rate, as defined in + * Register 25. The user is responsible for ensuring that I2C data transactions + * to and from each enabled Slave can be completed within a single period of the + * Sample Rate. + * + * The I2C slave access rate can be reduced relative to the Sample Rate. This + * reduced access rate is determined by I2C_MST_DLY (Register 52). Whether a + * slave's access rate is reduced relative to the Sample Rate is determined by + * I2C_MST_DELAY_CTRL (Register 103). + * + * The processing order for the slaves is fixed. The sequence followed for + * processing the slaves is Slave 0, Slave 1, Slave 2, Slave 3 and Slave 4. If a + * particular Slave is disabled it will be skipped. + * + * Each slave can either be accessed at the sample rate or at a reduced sample + * rate. In a case where some slaves are accessed at the Sample Rate and some + * slaves are accessed at the reduced rate, the sequence of accessing the slaves + * (Slave 0 to Slave 4) is still followed. However, the reduced rate slaves will + * be skipped if their access rate dictates that they should not be accessed + * during that particular cycle. For further information regarding the reduced + * access rate, please refer to Register 52. Whether a slave is accessed at the + * Sample Rate or at the reduced rate is determined by the Delay Enable bits in + * Register 103. + * + * @param num Slave number (0-3) + * @return Current address for specified slave + * @see MPU6050_RA_I2C_SLV0_ADDR + */ +uint8_t MPU6050::getSlaveAddress(uint8_t num) { + if (num > 3) return 0; + I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV0_ADDR + num*3, buffer); + return buffer[0]; +} +/** Set the I2C address of the specified slave (0-3). + * @param num Slave number (0-3) + * @param address New address for specified slave + * @see getSlaveAddress() + * @see MPU6050_RA_I2C_SLV0_ADDR + */ +void MPU6050::setSlaveAddress(uint8_t num, uint8_t address) { + if (num > 3) return; + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV0_ADDR + num*3, address); +} +/** Get the active internal register for the specified slave (0-3). + * Read/write operations for this slave will be done to whatever internal + * register address is stored in this MPU register. + * + * The MPU-6050 supports a total of five slaves, but Slave 4 has unique + * characteristics, and so it has its own functions. + * + * @param num Slave number (0-3) + * @return Current active register for specified slave + * @see MPU6050_RA_I2C_SLV0_REG + */ +uint8_t MPU6050::getSlaveRegister(uint8_t num) { + if (num > 3) return 0; + I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV0_REG + num*3, buffer); + return buffer[0]; +} +/** Set the active internal register for the specified slave (0-3). + * @param num Slave number (0-3) + * @param reg New active register for specified slave + * @see getSlaveRegister() + * @see MPU6050_RA_I2C_SLV0_REG + */ +void MPU6050::setSlaveRegister(uint8_t num, uint8_t reg) { + if (num > 3) return; + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV0_REG + num*3, reg); +} +/** Get the enabled value for the specified slave (0-3). + * When set to 1, this bit enables Slave 0 for data transfer operations. When + * cleared to 0, this bit disables Slave 0 from data transfer operations. + * @param num Slave number (0-3) + * @return Current enabled value for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +bool MPU6050::getSlaveEnabled(uint8_t num) { + if (num > 3) return 0; + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_EN_BIT, buffer); + return buffer[0]; +} +/** Set the enabled value for the specified slave (0-3). + * @param num Slave number (0-3) + * @param enabled New enabled value for specified slave + * @see getSlaveEnabled() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050::setSlaveEnabled(uint8_t num, bool enabled) { + if (num > 3) return; + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_EN_BIT, enabled); +} +/** Get word pair byte-swapping enabled for the specified slave (0-3). + * When set to 1, this bit enables byte swapping. When byte swapping is enabled, + * the high and low bytes of a word pair are swapped. Please refer to + * I2C_SLV0_GRP for the pairing convention of the word pairs. When cleared to 0, + * bytes transferred to and from Slave 0 will be written to EXT_SENS_DATA + * registers in the order they were transferred. + * + * @param num Slave number (0-3) + * @return Current word pair byte-swapping enabled value for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +bool MPU6050::getSlaveWordByteSwap(uint8_t num) { + if (num > 3) return 0; + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_BYTE_SW_BIT, buffer); + return buffer[0]; +} +/** Set word pair byte-swapping enabled for the specified slave (0-3). + * @param num Slave number (0-3) + * @param enabled New word pair byte-swapping enabled value for specified slave + * @see getSlaveWordByteSwap() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050::setSlaveWordByteSwap(uint8_t num, bool enabled) { + if (num > 3) return; + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_BYTE_SW_BIT, enabled); +} +/** Get write mode for the specified slave (0-3). + * When set to 1, the transaction will read or write data only. When cleared to + * 0, the transaction will write a register address prior to reading or writing + * data. This should equal 0 when specifying the register address within the + * Slave device to/from which the ensuing data transaction will take place. + * + * @param num Slave number (0-3) + * @return Current write mode for specified slave (0 = register address + data, 1 = data only) + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +bool MPU6050::getSlaveWriteMode(uint8_t num) { + if (num > 3) return 0; + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_REG_DIS_BIT, buffer); + return buffer[0]; +} +/** Set write mode for the specified slave (0-3). + * @param num Slave number (0-3) + * @param mode New write mode for specified slave (0 = register address + data, 1 = data only) + * @see getSlaveWriteMode() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050::setSlaveWriteMode(uint8_t num, bool mode) { + if (num > 3) return; + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_REG_DIS_BIT, mode); +} +/** Get word pair grouping order offset for the specified slave (0-3). + * This sets specifies the grouping order of word pairs received from registers. + * When cleared to 0, bytes from register addresses 0 and 1, 2 and 3, etc (even, + * then odd register addresses) are paired to form a word. When set to 1, bytes + * from register addresses are paired 1 and 2, 3 and 4, etc. (odd, then even + * register addresses) are paired to form a word. + * + * @param num Slave number (0-3) + * @return Current word pair grouping order offset for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +bool MPU6050::getSlaveWordGroupOffset(uint8_t num) { + if (num > 3) return 0; + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_GRP_BIT, buffer); + return buffer[0]; +} +/** Set word pair grouping order offset for the specified slave (0-3). + * @param num Slave number (0-3) + * @param enabled New word pair grouping order offset for specified slave + * @see getSlaveWordGroupOffset() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050::setSlaveWordGroupOffset(uint8_t num, bool enabled) { + if (num > 3) return; + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_GRP_BIT, enabled); +} +/** Get number of bytes to read for the specified slave (0-3). + * Specifies the number of bytes transferred to and from Slave 0. Clearing this + * bit to 0 is equivalent to disabling the register by writing 0 to I2C_SLV0_EN. + * @param num Slave number (0-3) + * @return Number of bytes to read for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +uint8_t MPU6050::getSlaveDataLength(uint8_t num) { + if (num > 3) return 0; + I2Cdev::readBits(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_LEN_BIT, MPU6050_I2C_SLV_LEN_LENGTH, buffer); + return buffer[0]; +} +/** Set number of bytes to read for the specified slave (0-3). + * @param num Slave number (0-3) + * @param length Number of bytes to read for specified slave + * @see getSlaveDataLength() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050::setSlaveDataLength(uint8_t num, uint8_t length) { + if (num > 3) return; + I2Cdev::writeBits(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_LEN_BIT, MPU6050_I2C_SLV_LEN_LENGTH, length); +} + +// I2C_SLV* registers (Slave 4) + +/** Get the I2C address of Slave 4. + * Note that Bit 7 (MSB) controls read/write mode. If Bit 7 is set, it's a read + * operation, and if it is cleared, then it's a write operation. The remaining + * bits (6-0) are the 7-bit device address of the slave device. + * + * @return Current address for Slave 4 + * @see getSlaveAddress() + * @see MPU6050_RA_I2C_SLV4_ADDR + */ +uint8_t MPU6050::getSlave4Address() { + I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV4_ADDR, buffer); + return buffer[0]; +} +/** Set the I2C address of Slave 4. + * @param address New address for Slave 4 + * @see getSlave4Address() + * @see MPU6050_RA_I2C_SLV4_ADDR + */ +void MPU6050::setSlave4Address(uint8_t address) { + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV4_ADDR, address); +} +/** Get the active internal register for the Slave 4. + * Read/write operations for this slave will be done to whatever internal + * register address is stored in this MPU register. + * + * @return Current active register for Slave 4 + * @see MPU6050_RA_I2C_SLV4_REG + */ +uint8_t MPU6050::getSlave4Register() { + I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV4_REG, buffer); + return buffer[0]; +} +/** Set the active internal register for Slave 4. + * @param reg New active register for Slave 4 + * @see getSlave4Register() + * @see MPU6050_RA_I2C_SLV4_REG + */ +void MPU6050::setSlave4Register(uint8_t reg) { + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV4_REG, reg); +} +/** Set new byte to write to Slave 4. + * This register stores the data to be written into the Slave 4. If I2C_SLV4_RW + * is set 1 (set to read), this register has no effect. + * @param data New byte to write to Slave 4 + * @see MPU6050_RA_I2C_SLV4_DO + */ +void MPU6050::setSlave4OutputByte(uint8_t data) { + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV4_DO, data); +} +/** Get the enabled value for the Slave 4. + * When set to 1, this bit enables Slave 4 for data transfer operations. When + * cleared to 0, this bit disables Slave 4 from data transfer operations. + * @return Current enabled value for Slave 4 + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +bool MPU6050::getSlave4Enabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_EN_BIT, buffer); + return buffer[0]; +} +/** Set the enabled value for Slave 4. + * @param enabled New enabled value for Slave 4 + * @see getSlave4Enabled() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050::setSlave4Enabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_EN_BIT, enabled); +} +/** Get the enabled value for Slave 4 transaction interrupts. + * When set to 1, this bit enables the generation of an interrupt signal upon + * completion of a Slave 4 transaction. When cleared to 0, this bit disables the + * generation of an interrupt signal upon completion of a Slave 4 transaction. + * The interrupt status can be observed in Register 54. + * + * @return Current enabled value for Slave 4 transaction interrupts. + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +bool MPU6050::getSlave4InterruptEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_INT_EN_BIT, buffer); + return buffer[0]; +} +/** Set the enabled value for Slave 4 transaction interrupts. + * @param enabled New enabled value for Slave 4 transaction interrupts. + * @see getSlave4InterruptEnabled() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050::setSlave4InterruptEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_INT_EN_BIT, enabled); +} +/** Get write mode for Slave 4. + * When set to 1, the transaction will read or write data only. When cleared to + * 0, the transaction will write a register address prior to reading or writing + * data. This should equal 0 when specifying the register address within the + * Slave device to/from which the ensuing data transaction will take place. + * + * @return Current write mode for Slave 4 (0 = register address + data, 1 = data only) + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +bool MPU6050::getSlave4WriteMode() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_REG_DIS_BIT, buffer); + return buffer[0]; +} +/** Set write mode for the Slave 4. + * @param mode New write mode for Slave 4 (0 = register address + data, 1 = data only) + * @see getSlave4WriteMode() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050::setSlave4WriteMode(bool mode) { + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_REG_DIS_BIT, mode); +} +/** Get Slave 4 master delay value. + * This configures the reduced access rate of I2C slaves relative to the Sample + * Rate. When a slave's access rate is decreased relative to the Sample Rate, + * the slave is accessed every: + * + * 1 / (1 + I2C_MST_DLY) samples + * + * This base Sample Rate in turn is determined by SMPLRT_DIV (register 25) and + * DLPF_CFG (register 26). Whether a slave's access rate is reduced relative to + * the Sample Rate is determined by I2C_MST_DELAY_CTRL (register 103). For + * further information regarding the Sample Rate, please refer to register 25. + * + * @return Current Slave 4 master delay value + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +uint8_t MPU6050::getSlave4MasterDelay() { + I2Cdev::readBits(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_MST_DLY_BIT, MPU6050_I2C_SLV4_MST_DLY_LENGTH, buffer); + return buffer[0]; +} +/** Set Slave 4 master delay value. + * @param delay New Slave 4 master delay value + * @see getSlave4MasterDelay() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050::setSlave4MasterDelay(uint8_t delay) { + I2Cdev::writeBits(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_MST_DLY_BIT, MPU6050_I2C_SLV4_MST_DLY_LENGTH, delay); +} +/** Get last available byte read from Slave 4. + * This register stores the data read from Slave 4. This field is populated + * after a read transaction. + * @return Last available byte read from to Slave 4 + * @see MPU6050_RA_I2C_SLV4_DI + */ +uint8_t MPU6050::getSlate4InputByte() { + I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV4_DI, buffer); + return buffer[0]; +} + +// I2C_MST_STATUS register + +/** Get FSYNC interrupt status. + * This bit reflects the status of the FSYNC interrupt from an external device + * into the MPU-60X0. This is used as a way to pass an external interrupt + * through the MPU-60X0 to the host application processor. When set to 1, this + * bit will cause an interrupt if FSYNC_INT_EN is asserted in INT_PIN_CFG + * (Register 55). + * @return FSYNC interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050::getPassthroughStatus() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_PASS_THROUGH_BIT, buffer); + return buffer[0]; +} +/** Get Slave 4 transaction done status. + * Automatically sets to 1 when a Slave 4 transaction has completed. This + * triggers an interrupt if the I2C_MST_INT_EN bit in the INT_ENABLE register + * (Register 56) is asserted and if the SLV_4_DONE_INT bit is asserted in the + * I2C_SLV4_CTRL register (Register 52). + * @return Slave 4 transaction done status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050::getSlave4IsDone() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV4_DONE_BIT, buffer); + return buffer[0]; +} +/** Get master arbitration lost status. + * This bit automatically sets to 1 when the I2C Master has lost arbitration of + * the auxiliary I2C bus (an error condition). This triggers an interrupt if the + * I2C_MST_INT_EN bit in the INT_ENABLE register (Register 56) is asserted. + * @return Master arbitration lost status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050::getLostArbitration() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_LOST_ARB_BIT, buffer); + return buffer[0]; +} +/** Get Slave 4 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 4. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 4 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050::getSlave4Nack() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV4_NACK_BIT, buffer); + return buffer[0]; +} +/** Get Slave 3 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 3. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 3 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050::getSlave3Nack() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV3_NACK_BIT, buffer); + return buffer[0]; +} +/** Get Slave 2 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 2. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 2 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050::getSlave2Nack() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV2_NACK_BIT, buffer); + return buffer[0]; +} +/** Get Slave 1 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 1. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 1 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050::getSlave1Nack() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV1_NACK_BIT, buffer); + return buffer[0]; +} +/** Get Slave 0 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 0. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 0 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050::getSlave0Nack() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV0_NACK_BIT, buffer); + return buffer[0]; +} + +// INT_PIN_CFG register + +/** Get interrupt logic level mode. + * Will be set 0 for active-high, 1 for active-low. + * @return Current interrupt mode (0=active-high, 1=active-low) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_LEVEL_BIT + */ +bool MPU6050::getInterruptMode() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_LEVEL_BIT, buffer); + return buffer[0]; +} +/** Set interrupt logic level mode. + * @param mode New interrupt mode (0=active-high, 1=active-low) + * @see getInterruptMode() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_LEVEL_BIT + */ +void MPU6050::setInterruptMode(bool mode) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_LEVEL_BIT, mode); +} +/** Get interrupt drive mode. + * Will be set 0 for push-pull, 1 for open-drain. + * @return Current interrupt drive mode (0=push-pull, 1=open-drain) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_OPEN_BIT + */ +bool MPU6050::getInterruptDrive() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_OPEN_BIT, buffer); + return buffer[0]; +} +/** Set interrupt drive mode. + * @param drive New interrupt drive mode (0=push-pull, 1=open-drain) + * @see getInterruptDrive() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_OPEN_BIT + */ +void MPU6050::setInterruptDrive(bool drive) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_OPEN_BIT, drive); +} +/** Get interrupt latch mode. + * Will be set 0 for 50us-pulse, 1 for latch-until-int-cleared. + * @return Current latch mode (0=50us-pulse, 1=latch-until-int-cleared) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_LATCH_INT_EN_BIT + */ +bool MPU6050::getInterruptLatch() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_LATCH_INT_EN_BIT, buffer); + return buffer[0]; +} +/** Set interrupt latch mode. + * @param latch New latch mode (0=50us-pulse, 1=latch-until-int-cleared) + * @see getInterruptLatch() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_LATCH_INT_EN_BIT + */ +void MPU6050::setInterruptLatch(bool latch) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_LATCH_INT_EN_BIT, latch); +} +/** Get interrupt latch clear mode. + * Will be set 0 for status-read-only, 1 for any-register-read. + * @return Current latch clear mode (0=status-read-only, 1=any-register-read) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_RD_CLEAR_BIT + */ +bool MPU6050::getInterruptLatchClear() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_RD_CLEAR_BIT, buffer); + return buffer[0]; +} +/** Set interrupt latch clear mode. + * @param clear New latch clear mode (0=status-read-only, 1=any-register-read) + * @see getInterruptLatchClear() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_RD_CLEAR_BIT + */ +void MPU6050::setInterruptLatchClear(bool clear) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_RD_CLEAR_BIT, clear); +} +/** Get FSYNC interrupt logic level mode. + * @return Current FSYNC interrupt mode (0=active-high, 1=active-low) + * @see getFSyncInterruptMode() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT + */ +bool MPU6050::getFSyncInterruptLevel() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT, buffer); + return buffer[0]; +} +/** Set FSYNC interrupt logic level mode. + * @param mode New FSYNC interrupt mode (0=active-high, 1=active-low) + * @see getFSyncInterruptMode() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT + */ +void MPU6050::setFSyncInterruptLevel(bool level) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT, level); +} +/** Get FSYNC pin interrupt enabled setting. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled setting + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_EN_BIT + */ +bool MPU6050::getFSyncInterruptEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_EN_BIT, buffer); + return buffer[0]; +} +/** Set FSYNC pin interrupt enabled setting. + * @param enabled New FSYNC pin interrupt enabled setting + * @see getFSyncInterruptEnabled() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_EN_BIT + */ +void MPU6050::setFSyncInterruptEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_EN_BIT, enabled); +} +/** Get I2C bypass enabled status. + * When this bit is equal to 1 and I2C_MST_EN (Register 106 bit[5]) is equal to + * 0, the host application processor will be able to directly access the + * auxiliary I2C bus of the MPU-60X0. When this bit is equal to 0, the host + * application processor will not be able to directly access the auxiliary I2C + * bus of the MPU-60X0 regardless of the state of I2C_MST_EN (Register 106 + * bit[5]). + * @return Current I2C bypass enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_I2C_BYPASS_EN_BIT + */ +bool MPU6050::getI2CBypassEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_I2C_BYPASS_EN_BIT, buffer); + return buffer[0]; +} +/** Set I2C bypass enabled status. + * When this bit is equal to 1 and I2C_MST_EN (Register 106 bit[5]) is equal to + * 0, the host application processor will be able to directly access the + * auxiliary I2C bus of the MPU-60X0. When this bit is equal to 0, the host + * application processor will not be able to directly access the auxiliary I2C + * bus of the MPU-60X0 regardless of the state of I2C_MST_EN (Register 106 + * bit[5]). + * @param enabled New I2C bypass enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_I2C_BYPASS_EN_BIT + */ +void MPU6050::setI2CBypassEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_I2C_BYPASS_EN_BIT, enabled); +} +/** Get reference clock output enabled status. + * When this bit is equal to 1, a reference clock output is provided at the + * CLKOUT pin. When this bit is equal to 0, the clock output is disabled. For + * further information regarding CLKOUT, please refer to the MPU-60X0 Product + * Specification document. + * @return Current reference clock output enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_CLKOUT_EN_BIT + */ +bool MPU6050::getClockOutputEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_CLKOUT_EN_BIT, buffer); + return buffer[0]; +} +/** Set reference clock output enabled status. + * When this bit is equal to 1, a reference clock output is provided at the + * CLKOUT pin. When this bit is equal to 0, the clock output is disabled. For + * further information regarding CLKOUT, please refer to the MPU-60X0 Product + * Specification document. + * @param enabled New reference clock output enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_CLKOUT_EN_BIT + */ +void MPU6050::setClockOutputEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_CLKOUT_EN_BIT, enabled); +} + +// INT_ENABLE register + +/** Get full interrupt enabled status. + * Full register byte for all interrupts, for quick reading. Each bit will be + * set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +uint8_t MPU6050::getIntEnabled() { + I2Cdev::readByte(devAddr, MPU6050_RA_INT_ENABLE, buffer); + return buffer[0]; +} +/** Set full interrupt enabled status. + * Full register byte for all interrupts, for quick reading. Each bit should be + * set 0 for disabled, 1 for enabled. + * @param enabled New interrupt enabled status + * @see getIntFreefallEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +void MPU6050::setIntEnabled(uint8_t enabled) { + I2Cdev::writeByte(devAddr, MPU6050_RA_INT_ENABLE, enabled); +} +/** Get Free Fall interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +bool MPU6050::getIntFreefallEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FF_BIT, buffer); + return buffer[0]; +} +/** Set Free Fall interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntFreefallEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +void MPU6050::setIntFreefallEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FF_BIT, enabled); +} +/** Get Motion Detection interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_MOT_BIT + **/ +bool MPU6050::getIntMotionEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_MOT_BIT, buffer); + return buffer[0]; +} +/** Set Motion Detection interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntMotionEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_MOT_BIT + **/ +void MPU6050::setIntMotionEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_MOT_BIT, enabled); +} +/** Get Zero Motion Detection interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_ZMOT_BIT + **/ +bool MPU6050::getIntZeroMotionEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_ZMOT_BIT, buffer); + return buffer[0]; +} +/** Set Zero Motion Detection interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntZeroMotionEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_ZMOT_BIT + **/ +void MPU6050::setIntZeroMotionEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_ZMOT_BIT, enabled); +} +/** Get FIFO Buffer Overflow interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT + **/ +bool MPU6050::getIntFIFOBufferOverflowEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, buffer); + return buffer[0]; +} +/** Set FIFO Buffer Overflow interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntFIFOBufferOverflowEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT + **/ +void MPU6050::setIntFIFOBufferOverflowEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, enabled); +} +/** Get I2C Master interrupt enabled status. + * This enables any of the I2C Master interrupt sources to generate an + * interrupt. Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT + **/ +bool MPU6050::getIntI2CMasterEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_I2C_MST_INT_BIT, buffer); + return buffer[0]; +} +/** Set I2C Master interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntI2CMasterEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT + **/ +void MPU6050::setIntI2CMasterEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_I2C_MST_INT_BIT, enabled); +} +/** Get Data Ready interrupt enabled setting. + * This event occurs each time a write operation to all of the sensor registers + * has been completed. Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_DATA_RDY_BIT + */ +bool MPU6050::getIntDataReadyEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DATA_RDY_BIT, buffer); + return buffer[0]; +} +/** Set Data Ready interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntDataReadyEnabled() + * @see MPU6050_RA_INT_CFG + * @see MPU6050_INTERRUPT_DATA_RDY_BIT + */ +void MPU6050::setIntDataReadyEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DATA_RDY_BIT, enabled); +} + +// INT_STATUS register + +/** Get full set of interrupt status bits. + * These bits clear to 0 after the register has been read. Very useful + * for getting multiple INT statuses, since each single bit read clears + * all of them because it has to read the whole byte. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + */ +uint8_t MPU6050::getIntStatus() { + I2Cdev::readByte(devAddr, MPU6050_RA_INT_STATUS, buffer); + return buffer[0]; +} +/** Get Free Fall interrupt status. + * This bit automatically sets to 1 when a Free Fall interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_FF_BIT + */ +bool MPU6050::getIntFreefallStatus() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_FF_BIT, buffer); + return buffer[0]; +} +/** Get Motion Detection interrupt status. + * This bit automatically sets to 1 when a Motion Detection interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_MOT_BIT + */ +bool MPU6050::getIntMotionStatus() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_MOT_BIT, buffer); + return buffer[0]; +} +/** Get Zero Motion Detection interrupt status. + * This bit automatically sets to 1 when a Zero Motion Detection interrupt has + * been generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_ZMOT_BIT + */ +bool MPU6050::getIntZeroMotionStatus() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_ZMOT_BIT, buffer); + return buffer[0]; +} +/** Get FIFO Buffer Overflow interrupt status. + * This bit automatically sets to 1 when a Free Fall interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT + */ +bool MPU6050::getIntFIFOBufferOverflowStatus() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, buffer); + return buffer[0]; +} +/** Get I2C Master interrupt status. + * This bit automatically sets to 1 when an I2C Master interrupt has been + * generated. For a list of I2C Master interrupts, please refer to Register 54. + * The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT + */ +bool MPU6050::getIntI2CMasterStatus() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_I2C_MST_INT_BIT, buffer); + return buffer[0]; +} +/** Get Data Ready interrupt status. + * This bit automatically sets to 1 when a Data Ready interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_DATA_RDY_BIT + */ +bool MPU6050::getIntDataReadyStatus() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_DATA_RDY_BIT, buffer); + return buffer[0]; +} + +// ACCEL_*OUT_* registers + +/** Get raw 9-axis motion sensor readings (accel/gyro/compass). + * FUNCTION NOT FULLY IMPLEMENTED YET. + * @param ax 16-bit signed integer container for accelerometer X-axis value + * @param ay 16-bit signed integer container for accelerometer Y-axis value + * @param az 16-bit signed integer container for accelerometer Z-axis value + * @param gx 16-bit signed integer container for gyroscope X-axis value + * @param gy 16-bit signed integer container for gyroscope Y-axis value + * @param gz 16-bit signed integer container for gyroscope Z-axis value + * @param mx 16-bit signed integer container for magnetometer X-axis value + * @param my 16-bit signed integer container for magnetometer Y-axis value + * @param mz 16-bit signed integer container for magnetometer Z-axis value + * @see getMotion6() + * @see getAcceleration() + * @see getRotation() + * @see MPU6050_RA_ACCEL_XOUT_H + */ +void MPU6050::getMotion9(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz, int16_t* mx, int16_t* my, int16_t* mz) { + getMotion6(ax, ay, az, gx, gy, gz); + // TODO: magnetometer integration +} +/** Get raw 6-axis motion sensor readings (accel/gyro). + * Retrieves all currently available motion sensor values. + * @param ax 16-bit signed integer container for accelerometer X-axis value + * @param ay 16-bit signed integer container for accelerometer Y-axis value + * @param az 16-bit signed integer container for accelerometer Z-axis value + * @param gx 16-bit signed integer container for gyroscope X-axis value + * @param gy 16-bit signed integer container for gyroscope Y-axis value + * @param gz 16-bit signed integer container for gyroscope Z-axis value + * @see getAcceleration() + * @see getRotation() + * @see MPU6050_RA_ACCEL_XOUT_H + */ +void MPU6050::getMotion6(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz) { + I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_XOUT_H, 14, buffer); + *ax = (((int16_t)buffer[0]) << 8) | buffer[1]; + *ay = (((int16_t)buffer[2]) << 8) | buffer[3]; + *az = (((int16_t)buffer[4]) << 8) | buffer[5]; + *gx = (((int16_t)buffer[8]) << 8) | buffer[9]; + *gy = (((int16_t)buffer[10]) << 8) | buffer[11]; + *gz = (((int16_t)buffer[12]) << 8) | buffer[13]; +} +/** Get 3-axis accelerometer readings. + * These registers store the most recent accelerometer measurements. + * Accelerometer measurements are written to these registers at the Sample Rate + * as defined in Register 25. + * + * The accelerometer measurement registers, along with the temperature + * measurement registers, gyroscope measurement registers, and external sensor + * data registers, are composed of two sets of registers: an internal register + * set and a user-facing read register set. + * + * The data within the accelerometer sensors' internal register set is always + * updated at the Sample Rate. Meanwhile, the user-facing read register set + * duplicates the internal register set's data values whenever the serial + * interface is idle. This guarantees that a burst read of sensor registers will + * read measurements from the same sampling instant. Note that if burst reads + * are not used, the user is responsible for ensuring a set of single byte reads + * correspond to a single sampling instant by checking the Data Ready interrupt. + * + * Each 16-bit accelerometer measurement has a full scale defined in ACCEL_FS + * (Register 28). For each full scale setting, the accelerometers' sensitivity + * per LSB in ACCEL_xOUT is shown in the table below: + * + *
+ * AFS_SEL | Full Scale Range | LSB Sensitivity
+ * --------+------------------+----------------
+ * 0       | +/- 2g           | 8192 LSB/mg
+ * 1       | +/- 4g           | 4096 LSB/mg
+ * 2       | +/- 8g           | 2048 LSB/mg
+ * 3       | +/- 16g          | 1024 LSB/mg
+ * 
+ * + * @param x 16-bit signed integer container for X-axis acceleration + * @param y 16-bit signed integer container for Y-axis acceleration + * @param z 16-bit signed integer container for Z-axis acceleration + * @see MPU6050_RA_GYRO_XOUT_H + */ +void MPU6050::getAcceleration(int16_t* x, int16_t* y, int16_t* z) { + I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_XOUT_H, 6, buffer); + *x = (((int16_t)buffer[0]) << 8) | buffer[1]; + *y = (((int16_t)buffer[2]) << 8) | buffer[3]; + *z = (((int16_t)buffer[4]) << 8) | buffer[5]; +} +/** Get X-axis accelerometer reading. + * @return X-axis acceleration measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_ACCEL_XOUT_H + */ +int16_t MPU6050::getAccelerationX() { + I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_XOUT_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +/** Get Y-axis accelerometer reading. + * @return Y-axis acceleration measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_ACCEL_YOUT_H + */ +int16_t MPU6050::getAccelerationY() { + I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_YOUT_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +/** Get Z-axis accelerometer reading. + * @return Z-axis acceleration measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_ACCEL_ZOUT_H + */ +int16_t MPU6050::getAccelerationZ() { + I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_ZOUT_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} + +// TEMP_OUT_* registers + +/** Get current internal temperature. + * @return Temperature reading in 16-bit 2's complement format + * @see MPU6050_RA_TEMP_OUT_H + */ +int16_t MPU6050::getTemperature() { + I2Cdev::readBytes(devAddr, MPU6050_RA_TEMP_OUT_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} + +// GYRO_*OUT_* registers + +/** Get 3-axis gyroscope readings. + * These gyroscope measurement registers, along with the accelerometer + * measurement registers, temperature measurement registers, and external sensor + * data registers, are composed of two sets of registers: an internal register + * set and a user-facing read register set. + * The data within the gyroscope sensors' internal register set is always + * updated at the Sample Rate. Meanwhile, the user-facing read register set + * duplicates the internal register set's data values whenever the serial + * interface is idle. This guarantees that a burst read of sensor registers will + * read measurements from the same sampling instant. Note that if burst reads + * are not used, the user is responsible for ensuring a set of single byte reads + * correspond to a single sampling instant by checking the Data Ready interrupt. + * + * Each 16-bit gyroscope measurement has a full scale defined in FS_SEL + * (Register 27). For each full scale setting, the gyroscopes' sensitivity per + * LSB in GYRO_xOUT is shown in the table below: + * + *
+ * FS_SEL | Full Scale Range   | LSB Sensitivity
+ * -------+--------------------+----------------
+ * 0      | +/- 250 degrees/s  | 131 LSB/deg/s
+ * 1      | +/- 500 degrees/s  | 65.5 LSB/deg/s
+ * 2      | +/- 1000 degrees/s | 32.8 LSB/deg/s
+ * 3      | +/- 2000 degrees/s | 16.4 LSB/deg/s
+ * 
+ * + * @param x 16-bit signed integer container for X-axis rotation + * @param y 16-bit signed integer container for Y-axis rotation + * @param z 16-bit signed integer container for Z-axis rotation + * @see getMotion6() + * @see MPU6050_RA_GYRO_XOUT_H + */ +void MPU6050::getRotation(int16_t* x, int16_t* y, int16_t* z) { + I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_XOUT_H, 6, buffer); + *x = (((int16_t)buffer[0]) << 8) | buffer[1]; + *y = (((int16_t)buffer[2]) << 8) | buffer[3]; + *z = (((int16_t)buffer[4]) << 8) | buffer[5]; +} +/** Get X-axis gyroscope reading. + * @return X-axis rotation measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_GYRO_XOUT_H + */ +int16_t MPU6050::getRotationX() { + I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_XOUT_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +/** Get Y-axis gyroscope reading. + * @return Y-axis rotation measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_GYRO_YOUT_H + */ +int16_t MPU6050::getRotationY() { + I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_YOUT_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +/** Get Z-axis gyroscope reading. + * @return Z-axis rotation measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_GYRO_ZOUT_H + */ +int16_t MPU6050::getRotationZ() { + I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_ZOUT_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} + +// EXT_SENS_DATA_* registers + +/** Read single byte from external sensor data register. + * These registers store data read from external sensors by the Slave 0, 1, 2, + * and 3 on the auxiliary I2C interface. Data read by Slave 4 is stored in + * I2C_SLV4_DI (Register 53). + * + * External sensor data is written to these registers at the Sample Rate as + * defined in Register 25. This access rate can be reduced by using the Slave + * Delay Enable registers (Register 103). + * + * External sensor data registers, along with the gyroscope measurement + * registers, accelerometer measurement registers, and temperature measurement + * registers, are composed of two sets of registers: an internal register set + * and a user-facing read register set. + * + * The data within the external sensors' internal register set is always updated + * at the Sample Rate (or the reduced access rate) whenever the serial interface + * is idle. This guarantees that a burst read of sensor registers will read + * measurements from the same sampling instant. Note that if burst reads are not + * used, the user is responsible for ensuring a set of single byte reads + * correspond to a single sampling instant by checking the Data Ready interrupt. + * + * Data is placed in these external sensor data registers according to + * I2C_SLV0_CTRL, I2C_SLV1_CTRL, I2C_SLV2_CTRL, and I2C_SLV3_CTRL (Registers 39, + * 42, 45, and 48). When more than zero bytes are read (I2C_SLVx_LEN > 0) from + * an enabled slave (I2C_SLVx_EN = 1), the slave is read at the Sample Rate (as + * defined in Register 25) or delayed rate (if specified in Register 52 and + * 103). During each Sample cycle, slave reads are performed in order of Slave + * number. If all slaves are enabled with more than zero bytes to be read, the + * order will be Slave 0, followed by Slave 1, Slave 2, and Slave 3. + * + * Each enabled slave will have EXT_SENS_DATA registers associated with it by + * number of bytes read (I2C_SLVx_LEN) in order of slave number, starting from + * EXT_SENS_DATA_00. Note that this means enabling or disabling a slave may + * change the higher numbered slaves' associated registers. Furthermore, if + * fewer total bytes are being read from the external sensors as a result of + * such a change, then the data remaining in the registers which no longer have + * an associated slave device (i.e. high numbered registers) will remain in + * these previously allocated registers unless reset. + * + * If the sum of the read lengths of all SLVx transactions exceed the number of + * available EXT_SENS_DATA registers, the excess bytes will be dropped. There + * are 24 EXT_SENS_DATA registers and hence the total read lengths between all + * the slaves cannot be greater than 24 or some bytes will be lost. + * + * Note: Slave 4's behavior is distinct from that of Slaves 0-3. For further + * information regarding the characteristics of Slave 4, please refer to + * Registers 49 to 53. + * + * EXAMPLE: + * Suppose that Slave 0 is enabled with 4 bytes to be read (I2C_SLV0_EN = 1 and + * I2C_SLV0_LEN = 4) while Slave 1 is enabled with 2 bytes to be read so that + * I2C_SLV1_EN = 1 and I2C_SLV1_LEN = 2. In such a situation, EXT_SENS_DATA _00 + * through _03 will be associated with Slave 0, while EXT_SENS_DATA _04 and 05 + * will be associated with Slave 1. If Slave 2 is enabled as well, registers + * starting from EXT_SENS_DATA_06 will be allocated to Slave 2. + * + * If Slave 2 is disabled while Slave 3 is enabled in this same situation, then + * registers starting from EXT_SENS_DATA_06 will be allocated to Slave 3 + * instead. + * + * REGISTER ALLOCATION FOR DYNAMIC DISABLE VS. NORMAL DISABLE: + * If a slave is disabled at any time, the space initially allocated to the + * slave in the EXT_SENS_DATA register, will remain associated with that slave. + * This is to avoid dynamic adjustment of the register allocation. + * + * The allocation of the EXT_SENS_DATA registers is recomputed only when (1) all + * slaves are disabled, or (2) the I2C_MST_RST bit is set (Register 106). + * + * This above is also true if one of the slaves gets NACKed and stops + * functioning. + * + * @param position Starting position (0-23) + * @return Byte read from register + */ +uint8_t MPU6050::getExternalSensorByte(int position) { + I2Cdev::readByte(devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, buffer); + return buffer[0]; +} +/** Read word (2 bytes) from external sensor data registers. + * @param position Starting position (0-21) + * @return Word read from register + * @see getExternalSensorByte() + */ +uint16_t MPU6050::getExternalSensorWord(int position) { + I2Cdev::readBytes(devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, 2, buffer); + return (((uint16_t)buffer[0]) << 8) | buffer[1]; +} +/** Read double word (4 bytes) from external sensor data registers. + * @param position Starting position (0-20) + * @return Double word read from registers + * @see getExternalSensorByte() + */ +uint32_t MPU6050::getExternalSensorDWord(int position) { + I2Cdev::readBytes(devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, 4, buffer); + return (((uint32_t)buffer[0]) << 24) | (((uint32_t)buffer[1]) << 16) | (((uint16_t)buffer[2]) << 8) | buffer[3]; +} + +// MOT_DETECT_STATUS register + +/** Get X-axis negative motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_XNEG_BIT + */ +bool MPU6050::getXNegMotionDetected() { + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_XNEG_BIT, buffer); + return buffer[0]; +} +/** Get X-axis positive motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_XPOS_BIT + */ +bool MPU6050::getXPosMotionDetected() { + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_XPOS_BIT, buffer); + return buffer[0]; +} +/** Get Y-axis negative motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_YNEG_BIT + */ +bool MPU6050::getYNegMotionDetected() { + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_YNEG_BIT, buffer); + return buffer[0]; +} +/** Get Y-axis positive motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_YPOS_BIT + */ +bool MPU6050::getYPosMotionDetected() { + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_YPOS_BIT, buffer); + return buffer[0]; +} +/** Get Z-axis negative motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_ZNEG_BIT + */ +bool MPU6050::getZNegMotionDetected() { + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZNEG_BIT, buffer); + return buffer[0]; +} +/** Get Z-axis positive motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_ZPOS_BIT + */ +bool MPU6050::getZPosMotionDetected() { + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZPOS_BIT, buffer); + return buffer[0]; +} +/** Get zero motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_ZRMOT_BIT + */ +bool MPU6050::getZeroMotionDetected() { + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZRMOT_BIT, buffer); + return buffer[0]; +} + +// I2C_SLV*_DO register + +/** Write byte to Data Output container for specified slave. + * This register holds the output data written into Slave when Slave is set to + * write mode. For further information regarding Slave control, please + * refer to Registers 37 to 39 and immediately following. + * @param num Slave number (0-3) + * @param data Byte to write + * @see MPU6050_RA_I2C_SLV0_DO + */ +void MPU6050::setSlaveOutputByte(uint8_t num, uint8_t data) { + if (num > 3) return; + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV0_DO + num, data); +} + +// I2C_MST_DELAY_CTRL register + +/** Get external data shadow delay enabled status. + * This register is used to specify the timing of external sensor data + * shadowing. When DELAY_ES_SHADOW is set to 1, shadowing of external + * sensor data is delayed until all data has been received. + * @return Current external data shadow delay enabled status. + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT + */ +bool MPU6050::getExternalShadowDelayEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT, buffer); + return buffer[0]; +} +/** Set external data shadow delay enabled status. + * @param enabled New external data shadow delay enabled status. + * @see getExternalShadowDelayEnabled() + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT + */ +void MPU6050::setExternalShadowDelayEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT, enabled); +} +/** Get slave delay enabled status. + * When a particular slave delay is enabled, the rate of access for the that + * slave device is reduced. When a slave's access rate is decreased relative to + * the Sample Rate, the slave is accessed every: + * + * 1 / (1 + I2C_MST_DLY) Samples + * + * This base Sample Rate in turn is determined by SMPLRT_DIV (register * 25) + * and DLPF_CFG (register 26). + * + * For further information regarding I2C_MST_DLY, please refer to register 52. + * For further information regarding the Sample Rate, please refer to register 25. + * + * @param num Slave number (0-4) + * @return Current slave delay enabled status. + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT + */ +bool MPU6050::getSlaveDelayEnabled(uint8_t num) { + // MPU6050_DELAYCTRL_I2C_SLV4_DLY_EN_BIT is 4, SLV3 is 3, etc. + if (num > 4) return 0; + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, num, buffer); + return buffer[0]; +} +/** Set slave delay enabled status. + * @param num Slave number (0-4) + * @param enabled New slave delay enabled status. + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT + */ +void MPU6050::setSlaveDelayEnabled(uint8_t num, bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, num, enabled); +} + +// SIGNAL_PATH_RESET register + +/** Reset gyroscope signal path. + * The reset will revert the signal path analog to digital converters and + * filters to their power up configurations. + * @see MPU6050_RA_SIGNAL_PATH_RESET + * @see MPU6050_PATHRESET_GYRO_RESET_BIT + */ +void MPU6050::resetGyroscopePath() { + I2Cdev::writeBit(devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_GYRO_RESET_BIT, true); +} +/** Reset accelerometer signal path. + * The reset will revert the signal path analog to digital converters and + * filters to their power up configurations. + * @see MPU6050_RA_SIGNAL_PATH_RESET + * @see MPU6050_PATHRESET_ACCEL_RESET_BIT + */ +void MPU6050::resetAccelerometerPath() { + I2Cdev::writeBit(devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_ACCEL_RESET_BIT, true); +} +/** Reset temperature sensor signal path. + * The reset will revert the signal path analog to digital converters and + * filters to their power up configurations. + * @see MPU6050_RA_SIGNAL_PATH_RESET + * @see MPU6050_PATHRESET_TEMP_RESET_BIT + */ +void MPU6050::resetTemperaturePath() { + I2Cdev::writeBit(devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_TEMP_RESET_BIT, true); +} + +// MOT_DETECT_CTRL register + +/** Get accelerometer power-on delay. + * The accelerometer data path provides samples to the sensor registers, Motion + * detection, Zero Motion detection, and Free Fall detection modules. The + * signal path contains filters which must be flushed on wake-up with new + * samples before the detection modules begin operations. The default wake-up + * delay, of 4ms can be lengthened by up to 3ms. This additional delay is + * specified in ACCEL_ON_DELAY in units of 1 LSB = 1 ms. The user may select + * any value above zero unless instructed otherwise by InvenSense. Please refer + * to Section 8 of the MPU-6000/MPU-6050 Product Specification document for + * further information regarding the detection modules. + * @return Current accelerometer power-on delay + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_ACCEL_ON_DELAY_BIT + */ +uint8_t MPU6050::getAccelerometerPowerOnDelay() { + I2Cdev::readBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_ACCEL_ON_DELAY_BIT, MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH, buffer); + return buffer[0]; +} +/** Set accelerometer power-on delay. + * @param delay New accelerometer power-on delay (0-3) + * @see getAccelerometerPowerOnDelay() + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_ACCEL_ON_DELAY_BIT + */ +void MPU6050::setAccelerometerPowerOnDelay(uint8_t delay) { + I2Cdev::writeBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_ACCEL_ON_DELAY_BIT, MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH, delay); +} +/** Get Free Fall detection counter decrement configuration. + * Detection is registered by the Free Fall detection module after accelerometer + * measurements meet their respective threshold conditions over a specified + * number of samples. When the threshold conditions are met, the corresponding + * detection counter increments by 1. The user may control the rate at which the + * detection counter decrements when the threshold condition is not met by + * configuring FF_COUNT. The decrement rate can be set according to the + * following table: + * + *
+ * FF_COUNT | Counter Decrement
+ * ---------+------------------
+ * 0        | Reset
+ * 1        | 1
+ * 2        | 2
+ * 3        | 4
+ * 
+ * + * When FF_COUNT is configured to 0 (reset), any non-qualifying sample will + * reset the counter to 0. For further information on Free Fall detection, + * please refer to Registers 29 to 32. + * + * @return Current decrement configuration + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_FF_COUNT_BIT + */ +uint8_t MPU6050::getFreefallDetectionCounterDecrement() { + I2Cdev::readBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_FF_COUNT_BIT, MPU6050_DETECT_FF_COUNT_LENGTH, buffer); + return buffer[0]; +} +/** Set Free Fall detection counter decrement configuration. + * @param decrement New decrement configuration value + * @see getFreefallDetectionCounterDecrement() + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_FF_COUNT_BIT + */ +void MPU6050::setFreefallDetectionCounterDecrement(uint8_t decrement) { + I2Cdev::writeBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_FF_COUNT_BIT, MPU6050_DETECT_FF_COUNT_LENGTH, decrement); +} +/** Get Motion detection counter decrement configuration. + * Detection is registered by the Motion detection module after accelerometer + * measurements meet their respective threshold conditions over a specified + * number of samples. When the threshold conditions are met, the corresponding + * detection counter increments by 1. The user may control the rate at which the + * detection counter decrements when the threshold condition is not met by + * configuring MOT_COUNT. The decrement rate can be set according to the + * following table: + * + *
+ * MOT_COUNT | Counter Decrement
+ * ----------+------------------
+ * 0         | Reset
+ * 1         | 1
+ * 2         | 2
+ * 3         | 4
+ * 
+ * + * When MOT_COUNT is configured to 0 (reset), any non-qualifying sample will + * reset the counter to 0. For further information on Motion detection, + * please refer to Registers 29 to 32. + * + */ +uint8_t MPU6050::getMotionDetectionCounterDecrement() { + I2Cdev::readBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_MOT_COUNT_BIT, MPU6050_DETECT_MOT_COUNT_LENGTH, buffer); + return buffer[0]; +} +/** Set Motion detection counter decrement configuration. + * @param decrement New decrement configuration value + * @see getMotionDetectionCounterDecrement() + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_MOT_COUNT_BIT + */ +void MPU6050::setMotionDetectionCounterDecrement(uint8_t decrement) { + I2Cdev::writeBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_MOT_COUNT_BIT, MPU6050_DETECT_MOT_COUNT_LENGTH, decrement); +} + +// USER_CTRL register + +/** Get FIFO enabled status. + * When this bit is set to 0, the FIFO buffer is disabled. The FIFO buffer + * cannot be written to or read from while disabled. The FIFO buffer's state + * does not change unless the MPU-60X0 is power cycled. + * @return Current FIFO enabled status + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_FIFO_EN_BIT + */ +bool MPU6050::getFIFOEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set FIFO enabled status. + * @param enabled New FIFO enabled status + * @see getFIFOEnabled() + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_FIFO_EN_BIT + */ +void MPU6050::setFIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_EN_BIT, enabled); +} +/** Get I2C Master Mode enabled status. + * When this mode is enabled, the MPU-60X0 acts as the I2C Master to the + * external sensor slave devices on the auxiliary I2C bus. When this bit is + * cleared to 0, the auxiliary I2C bus lines (AUX_DA and AUX_CL) are logically + * driven by the primary I2C bus (SDA and SCL). This is a precondition to + * enabling Bypass Mode. For further information regarding Bypass Mode, please + * refer to Register 55. + * @return Current I2C Master Mode enabled status + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_I2C_MST_EN_BIT + */ +bool MPU6050::getI2CMasterModeEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_EN_BIT, buffer); + return buffer[0]; +} +/** Set I2C Master Mode enabled status. + * @param enabled New I2C Master Mode enabled status + * @see getI2CMasterModeEnabled() + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_I2C_MST_EN_BIT + */ +void MPU6050::setI2CMasterModeEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_EN_BIT, enabled); +} +/** Switch from I2C to SPI mode (MPU-6000 only) + * If this is set, the primary SPI interface will be enabled in place of the + * disabled primary I2C interface. + */ +void MPU6050::switchSPIEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_IF_DIS_BIT, enabled); +} +/** Reset the FIFO. + * This bit resets the FIFO buffer when set to 1 while FIFO_EN equals 0. This + * bit automatically clears to 0 after the reset has been triggered. + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_FIFO_RESET_BIT + */ +void MPU6050::resetFIFO() { + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_RESET_BIT, true); +} +/** Reset the I2C Master. + * This bit resets the I2C Master when set to 1 while I2C_MST_EN equals 0. + * This bit automatically clears to 0 after the reset has been triggered. + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_I2C_MST_RESET_BIT + */ +void MPU6050::resetI2CMaster() { + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_RESET_BIT, true); +} +/** Reset all sensor registers and signal paths. + * When set to 1, this bit resets the signal paths for all sensors (gyroscopes, + * accelerometers, and temperature sensor). This operation will also clear the + * sensor registers. This bit automatically clears to 0 after the reset has been + * triggered. + * + * When resetting only the signal path (and not the sensor registers), please + * use Register 104, SIGNAL_PATH_RESET. + * + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_SIG_COND_RESET_BIT + */ +void MPU6050::resetSensors() { + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_SIG_COND_RESET_BIT, true); +} + +// PWR_MGMT_1 register + +/** Trigger a full device reset. + * A small delay of ~50ms may be desirable after triggering a reset. + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_DEVICE_RESET_BIT + */ +void MPU6050::reset() { + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_DEVICE_RESET_BIT, true); +} +/** Get sleep mode status. + * Setting the SLEEP bit in the register puts the device into very low power + * sleep mode. In this mode, only the serial interface and internal registers + * remain active, allowing for a very low standby current. Clearing this bit + * puts the device back into normal mode. To save power, the individual standby + * selections for each of the gyros should be used if any gyro axis is not used + * by the application. + * @return Current sleep mode enabled status + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_SLEEP_BIT + */ +bool MPU6050::getSleepEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, buffer); + return buffer[0]; +} +/** Set sleep mode status. + * @param enabled New sleep mode enabled status + * @see getSleepEnabled() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_SLEEP_BIT + */ +void MPU6050::setSleepEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, enabled); +} +/** Get wake cycle enabled status. + * When this bit is set to 1 and SLEEP is disabled, the MPU-60X0 will cycle + * between sleep mode and waking up to take a single sample of data from active + * sensors at a rate determined by LP_WAKE_CTRL (register 108). + * @return Current sleep mode enabled status + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CYCLE_BIT + */ +bool MPU6050::getWakeCycleEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CYCLE_BIT, buffer); + return buffer[0]; +} +/** Set wake cycle enabled status. + * @param enabled New sleep mode enabled status + * @see getWakeCycleEnabled() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CYCLE_BIT + */ +void MPU6050::setWakeCycleEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CYCLE_BIT, enabled); +} +/** Get temperature sensor enabled status. + * Control the usage of the internal temperature sensor. + * + * Note: this register stores the *disabled* value, but for consistency with the + * rest of the code, the function is named and used with standard true/false + * values to indicate whether the sensor is enabled or disabled, respectively. + * + * @return Current temperature sensor enabled status + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_TEMP_DIS_BIT + */ +bool MPU6050::getTempSensorEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_TEMP_DIS_BIT, buffer); + return buffer[0] == 0; // 1 is actually disabled here +} +/** Set temperature sensor enabled status. + * Note: this register stores the *disabled* value, but for consistency with the + * rest of the code, the function is named and used with standard true/false + * values to indicate whether the sensor is enabled or disabled, respectively. + * + * @param enabled New temperature sensor enabled status + * @see getTempSensorEnabled() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_TEMP_DIS_BIT + */ +void MPU6050::setTempSensorEnabled(bool enabled) { + // 1 is actually disabled here + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_TEMP_DIS_BIT, !enabled); +} +/** Get clock source setting. + * @return Current clock source setting + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CLKSEL_BIT + * @see MPU6050_PWR1_CLKSEL_LENGTH + */ +uint8_t MPU6050::getClockSource() { + I2Cdev::readBits(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, buffer); + return buffer[0]; +} +/** Set clock source setting. + * An internal 8MHz oscillator, gyroscope based clock, or external sources can + * be selected as the MPU-60X0 clock source. When the internal 8 MHz oscillator + * or an external source is chosen as the clock source, the MPU-60X0 can operate + * in low power modes with the gyroscopes disabled. + * + * Upon power up, the MPU-60X0 clock source defaults to the internal oscillator. + * However, it is highly recommended that the device be configured to use one of + * the gyroscopes (or an external clock source) as the clock reference for + * improved stability. The clock source can be selected according to the following table: + * + *
+ * CLK_SEL | Clock Source
+ * --------+--------------------------------------
+ * 0       | Internal oscillator
+ * 1       | PLL with X Gyro reference
+ * 2       | PLL with Y Gyro reference
+ * 3       | PLL with Z Gyro reference
+ * 4       | PLL with external 32.768kHz reference
+ * 5       | PLL with external 19.2MHz reference
+ * 6       | Reserved
+ * 7       | Stops the clock and keeps the timing generator in reset
+ * 
+ * + * @param source New clock source setting + * @see getClockSource() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CLKSEL_BIT + * @see MPU6050_PWR1_CLKSEL_LENGTH + */ +void MPU6050::setClockSource(uint8_t source) { + I2Cdev::writeBits(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, source); +} + +// PWR_MGMT_2 register + +/** Get wake frequency in Accel-Only Low Power Mode. + * The MPU-60X0 can be put into Accerlerometer Only Low Power Mode by setting + * PWRSEL to 1 in the Power Management 1 register (Register 107). In this mode, + * the device will power off all devices except for the primary I2C interface, + * waking only the accelerometer at fixed intervals to take a single + * measurement. The frequency of wake-ups can be configured with LP_WAKE_CTRL + * as shown below: + * + *
+ * LP_WAKE_CTRL | Wake-up Frequency
+ * -------------+------------------
+ * 0            | 1.25 Hz
+ * 1            | 2.5 Hz
+ * 2            | 5 Hz
+ * 3            | 10 Hz
+ * 
+ *
+ * For further information regarding the MPU-60X0's power modes, please refer to
+ * Register 107.
+ *
+ * @return Current wake frequency
+ * @see MPU6050_RA_PWR_MGMT_2
+ */
+uint8_t MPU6050::getWakeFrequency() {
+    I2Cdev::readBits(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_LP_WAKE_CTRL_BIT, MPU6050_PWR2_LP_WAKE_CTRL_LENGTH, buffer);
+    return buffer[0];
+}
+/** Set wake frequency in Accel-Only Low Power Mode.
+ * @param frequency New wake frequency
+ * @see MPU6050_RA_PWR_MGMT_2
+ */
+void MPU6050::setWakeFrequency(uint8_t frequency) {
+    I2Cdev::writeBits(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_LP_WAKE_CTRL_BIT, MPU6050_PWR2_LP_WAKE_CTRL_LENGTH, frequency);
+}
+
+/** Get X-axis accelerometer standby enabled status.
+ * If enabled, the X-axis will not gather or report data (or use power).
+ * @return Current X-axis standby enabled status
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_XA_BIT
+ */
+bool MPU6050::getStandbyXAccelEnabled() {
+    I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XA_BIT, buffer);
+    return buffer[0];
+}
+/** Set X-axis accelerometer standby enabled status.
+ * @param New X-axis standby enabled status
+ * @see getStandbyXAccelEnabled()
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_XA_BIT
+ */
+void MPU6050::setStandbyXAccelEnabled(bool enabled) {
+    I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XA_BIT, enabled);
+}
+/** Get Y-axis accelerometer standby enabled status.
+ * If enabled, the Y-axis will not gather or report data (or use power).
+ * @return Current Y-axis standby enabled status
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_YA_BIT
+ */
+bool MPU6050::getStandbyYAccelEnabled() {
+    I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YA_BIT, buffer);
+    return buffer[0];
+}
+/** Set Y-axis accelerometer standby enabled status.
+ * @param New Y-axis standby enabled status
+ * @see getStandbyYAccelEnabled()
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_YA_BIT
+ */
+void MPU6050::setStandbyYAccelEnabled(bool enabled) {
+    I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YA_BIT, enabled);
+}
+/** Get Z-axis accelerometer standby enabled status.
+ * If enabled, the Z-axis will not gather or report data (or use power).
+ * @return Current Z-axis standby enabled status
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_ZA_BIT
+ */
+bool MPU6050::getStandbyZAccelEnabled() {
+    I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZA_BIT, buffer);
+    return buffer[0];
+}
+/** Set Z-axis accelerometer standby enabled status.
+ * @param New Z-axis standby enabled status
+ * @see getStandbyZAccelEnabled()
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_ZA_BIT
+ */
+void MPU6050::setStandbyZAccelEnabled(bool enabled) {
+    I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZA_BIT, enabled);
+}
+/** Get X-axis gyroscope standby enabled status.
+ * If enabled, the X-axis will not gather or report data (or use power).
+ * @return Current X-axis standby enabled status
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_XG_BIT
+ */
+bool MPU6050::getStandbyXGyroEnabled() {
+    I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XG_BIT, buffer);
+    return buffer[0];
+}
+/** Set X-axis gyroscope standby enabled status.
+ * @param New X-axis standby enabled status
+ * @see getStandbyXGyroEnabled()
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_XG_BIT
+ */
+void MPU6050::setStandbyXGyroEnabled(bool enabled) {
+    I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XG_BIT, enabled);
+}
+/** Get Y-axis gyroscope standby enabled status.
+ * If enabled, the Y-axis will not gather or report data (or use power).
+ * @return Current Y-axis standby enabled status
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_YG_BIT
+ */
+bool MPU6050::getStandbyYGyroEnabled() {
+    I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YG_BIT, buffer);
+    return buffer[0];
+}
+/** Set Y-axis gyroscope standby enabled status.
+ * @param New Y-axis standby enabled status
+ * @see getStandbyYGyroEnabled()
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_YG_BIT
+ */
+void MPU6050::setStandbyYGyroEnabled(bool enabled) {
+    I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YG_BIT, enabled);
+}
+/** Get Z-axis gyroscope standby enabled status.
+ * If enabled, the Z-axis will not gather or report data (or use power).
+ * @return Current Z-axis standby enabled status
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_ZG_BIT
+ */
+bool MPU6050::getStandbyZGyroEnabled() {
+    I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZG_BIT, buffer);
+    return buffer[0];
+}
+/** Set Z-axis gyroscope standby enabled status.
+ * @param New Z-axis standby enabled status
+ * @see getStandbyZGyroEnabled()
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_ZG_BIT
+ */
+void MPU6050::setStandbyZGyroEnabled(bool enabled) {
+    I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZG_BIT, enabled);
+}
+
+// FIFO_COUNT* registers
+
+/** Get current FIFO buffer size.
+ * This value indicates the number of bytes stored in the FIFO buffer. This
+ * number is in turn the number of bytes that can be read from the FIFO buffer
+ * and it is directly proportional to the number of samples available given the
+ * set of sensor data bound to be stored in the FIFO (register 35 and 36).
+ * @return Current FIFO buffer size
+ */
+uint16_t MPU6050::getFIFOCount() {
+    I2Cdev::readBytes(devAddr, MPU6050_RA_FIFO_COUNTH, 2, buffer);
+    return (((uint16_t)buffer[0]) << 8) | buffer[1];
+}
+
+// FIFO_R_W register
+
+/** Get byte from FIFO buffer.
+ * This register is used to read and write data from the FIFO buffer. Data is
+ * written to the FIFO in order of register number (from lowest to highest). If
+ * all the FIFO enable flags (see below) are enabled and all External Sensor
+ * Data registers (Registers 73 to 96) are associated with a Slave device, the
+ * contents of registers 59 through 96 will be written in order at the Sample
+ * Rate.
+ *
+ * The contents of the sensor data registers (Registers 59 to 96) are written
+ * into the FIFO buffer when their corresponding FIFO enable flags are set to 1
+ * in FIFO_EN (Register 35). An additional flag for the sensor data registers
+ * associated with I2C Slave 3 can be found in I2C_MST_CTRL (Register 36).
+ *
+ * If the FIFO buffer has overflowed, the status bit FIFO_OFLOW_INT is
+ * automatically set to 1. This bit is located in INT_STATUS (Register 58).
+ * When the FIFO buffer has overflowed, the oldest data will be lost and new
+ * data will be written to the FIFO.
+ *
+ * If the FIFO buffer is empty, reading this register will return the last byte
+ * that was previously read from the FIFO until new data is available. The user
+ * should check FIFO_COUNT to ensure that the FIFO buffer is not read when
+ * empty.
+ *
+ * @return Byte from FIFO buffer
+ */
+uint8_t MPU6050::getFIFOByte() {
+    I2Cdev::readByte(devAddr, MPU6050_RA_FIFO_R_W, buffer);
+    return buffer[0];
+}
+void MPU6050::getFIFOBytes(uint8_t *data, uint8_t length) {
+    I2Cdev::readBytes(devAddr, MPU6050_RA_FIFO_R_W, length, data);
+}
+/** Write byte to FIFO buffer.
+ * @see getFIFOByte()
+ * @see MPU6050_RA_FIFO_R_W
+ */
+void MPU6050::setFIFOByte(uint8_t data) {
+    I2Cdev::writeByte(devAddr, MPU6050_RA_FIFO_R_W, data);
+}
+
+// WHO_AM_I register
+
+/** Get Device ID.
+ * This register is used to verify the identity of the device (0b110100, 0x34).
+ * @return Device ID (6 bits only! should be 0x34)
+ * @see MPU6050_RA_WHO_AM_I
+ * @see MPU6050_WHO_AM_I_BIT
+ * @see MPU6050_WHO_AM_I_LENGTH
+ */
+uint8_t MPU6050::getDeviceID() {
+    I2Cdev::readBits(devAddr, MPU6050_RA_WHO_AM_I, MPU6050_WHO_AM_I_BIT, MPU6050_WHO_AM_I_LENGTH, buffer);
+    return buffer[0];
+}
+/** Set Device ID.
+ * Write a new ID into the WHO_AM_I register (no idea why this should ever be
+ * necessary though).
+ * @param id New device ID to set.
+ * @see getDeviceID()
+ * @see MPU6050_RA_WHO_AM_I
+ * @see MPU6050_WHO_AM_I_BIT
+ * @see MPU6050_WHO_AM_I_LENGTH
+ */
+void MPU6050::setDeviceID(uint8_t id) {
+    I2Cdev::writeBits(devAddr, MPU6050_RA_WHO_AM_I, MPU6050_WHO_AM_I_BIT, MPU6050_WHO_AM_I_LENGTH, id);
+}
+
+// ======== UNDOCUMENTED/DMP REGISTERS/METHODS ========
+
+// XG_OFFS_TC register
+
+uint8_t MPU6050::getOTPBankValid() {
+    I2Cdev::readBit(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OTP_BNK_VLD_BIT, buffer);
+    return buffer[0];
+}
+void MPU6050::setOTPBankValid(bool enabled) {
+    I2Cdev::writeBit(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OTP_BNK_VLD_BIT, enabled);
+}
+int8_t MPU6050::getXGyroOffsetTC() {
+    I2Cdev::readBits(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, buffer);
+    return buffer[0];
+}
+void MPU6050::setXGyroOffsetTC(int8_t offset) {
+    I2Cdev::writeBits(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset);
+}
+
+// YG_OFFS_TC register
+
+int8_t MPU6050::getYGyroOffsetTC() {
+    I2Cdev::readBits(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, buffer);
+    return buffer[0];
+}
+void MPU6050::setYGyroOffsetTC(int8_t offset) {
+    I2Cdev::writeBits(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset);
+}
+
+// ZG_OFFS_TC register
+
+int8_t MPU6050::getZGyroOffsetTC() {
+    I2Cdev::readBits(devAddr, MPU6050_RA_ZG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, buffer);
+    return buffer[0];
+}
+void MPU6050::setZGyroOffsetTC(int8_t offset) {
+    I2Cdev::writeBits(devAddr, MPU6050_RA_ZG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset);
+}
+
+// X_FINE_GAIN register
+
+int8_t MPU6050::getXFineGain() {
+    I2Cdev::readByte(devAddr, MPU6050_RA_X_FINE_GAIN, buffer);
+    return buffer[0];
+}
+void MPU6050::setXFineGain(int8_t gain) {
+    I2Cdev::writeByte(devAddr, MPU6050_RA_X_FINE_GAIN, gain);
+}
+
+// Y_FINE_GAIN register
+
+int8_t MPU6050::getYFineGain() {
+    I2Cdev::readByte(devAddr, MPU6050_RA_Y_FINE_GAIN, buffer);
+    return buffer[0];
+}
+void MPU6050::setYFineGain(int8_t gain) {
+    I2Cdev::writeByte(devAddr, MPU6050_RA_Y_FINE_GAIN, gain);
+}
+
+// Z_FINE_GAIN register
+
+int8_t MPU6050::getZFineGain() {
+    I2Cdev::readByte(devAddr, MPU6050_RA_Z_FINE_GAIN, buffer);
+    return buffer[0];
+}
+void MPU6050::setZFineGain(int8_t gain) {
+    I2Cdev::writeByte(devAddr, MPU6050_RA_Z_FINE_GAIN, gain);
+}
+
+// XA_OFFS_* registers
+
+int16_t MPU6050::getXAccelOffset() {
+    I2Cdev::readBytes(devAddr, MPU6050_RA_XA_OFFS_H, 2, buffer);
+    return (((int16_t)buffer[0]) << 8) | buffer[1];
+}
+void MPU6050::setXAccelOffset(int16_t offset) {
+    I2Cdev::writeWord(devAddr, MPU6050_RA_XA_OFFS_H, offset);
+}
+
+// YA_OFFS_* register
+
+int16_t MPU6050::getYAccelOffset() {
+    I2Cdev::readBytes(devAddr, MPU6050_RA_YA_OFFS_H, 2, buffer);
+    return (((int16_t)buffer[0]) << 8) | buffer[1];
+}
+void MPU6050::setYAccelOffset(int16_t offset) {
+    I2Cdev::writeWord(devAddr, MPU6050_RA_YA_OFFS_H, offset);
+}
+
+// ZA_OFFS_* register
+
+int16_t MPU6050::getZAccelOffset() {
+    I2Cdev::readBytes(devAddr, MPU6050_RA_ZA_OFFS_H, 2, buffer);
+    return (((int16_t)buffer[0]) << 8) | buffer[1];
+}
+void MPU6050::setZAccelOffset(int16_t offset) {
+    I2Cdev::writeWord(devAddr, MPU6050_RA_ZA_OFFS_H, offset);
+}
+
+// XG_OFFS_USR* registers
+
+int16_t MPU6050::getXGyroOffset() {
+    I2Cdev::readBytes(devAddr, MPU6050_RA_XG_OFFS_USRH, 2, buffer);
+    return (((int16_t)buffer[0]) << 8) | buffer[1];
+}
+void MPU6050::setXGyroOffset(int16_t offset) {
+    I2Cdev::writeWord(devAddr, MPU6050_RA_XG_OFFS_USRH, offset);
+}
+
+// YG_OFFS_USR* register
+
+int16_t MPU6050::getYGyroOffset() {
+    I2Cdev::readBytes(devAddr, MPU6050_RA_YG_OFFS_USRH, 2, buffer);
+    return (((int16_t)buffer[0]) << 8) | buffer[1];
+}
+void MPU6050::setYGyroOffset(int16_t offset) {
+    I2Cdev::writeWord(devAddr, MPU6050_RA_YG_OFFS_USRH, offset);
+}
+
+// ZG_OFFS_USR* register
+
+int16_t MPU6050::getZGyroOffset() {
+    I2Cdev::readBytes(devAddr, MPU6050_RA_ZG_OFFS_USRH, 2, buffer);
+    return (((int16_t)buffer[0]) << 8) | buffer[1];
+}
+void MPU6050::setZGyroOffset(int16_t offset) {
+    I2Cdev::writeWord(devAddr, MPU6050_RA_ZG_OFFS_USRH, offset);
+}
+
+// INT_ENABLE register (DMP functions)
+
+bool MPU6050::getIntPLLReadyEnabled() {
+    I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, buffer);
+    return buffer[0];
+}
+void MPU6050::setIntPLLReadyEnabled(bool enabled) {
+    I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, enabled);
+}
+bool MPU6050::getIntDMPEnabled() {
+    I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DMP_INT_BIT, buffer);
+    return buffer[0];
+}
+void MPU6050::setIntDMPEnabled(bool enabled) {
+    I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DMP_INT_BIT, enabled);
+}
+
+// DMP_INT_STATUS
+
+bool MPU6050::getDMPInt5Status() {
+    I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_5_BIT, buffer);
+    return buffer[0];
+}
+bool MPU6050::getDMPInt4Status() {
+    I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_4_BIT, buffer);
+    return buffer[0];
+}
+bool MPU6050::getDMPInt3Status() {
+    I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_3_BIT, buffer);
+    return buffer[0];
+}
+bool MPU6050::getDMPInt2Status() {
+    I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_2_BIT, buffer);
+    return buffer[0];
+}
+bool MPU6050::getDMPInt1Status() {
+    I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_1_BIT, buffer);
+    return buffer[0];
+}
+bool MPU6050::getDMPInt0Status() {
+    I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_0_BIT, buffer);
+    return buffer[0];
+}
+
+// INT_STATUS register (DMP functions)
+
+bool MPU6050::getIntPLLReadyStatus() {
+    I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, buffer);
+    return buffer[0];
+}
+bool MPU6050::getIntDMPStatus() {
+    I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_DMP_INT_BIT, buffer);
+    return buffer[0];
+}
+
+// USER_CTRL register (DMP functions)
+
+bool MPU6050::getDMPEnabled() {
+    I2Cdev::readBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_EN_BIT, buffer);
+    return buffer[0];
+}
+void MPU6050::setDMPEnabled(bool enabled) {
+    I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_EN_BIT, enabled);
+}
+void MPU6050::resetDMP() {
+    I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_RESET_BIT, true);
+}
+
+// BANK_SEL register
+
+void MPU6050::setMemoryBank(uint8_t bank, bool prefetchEnabled, bool userBank) {
+    bank &= 0x1F;
+    if (userBank) bank |= 0x20;
+    if (prefetchEnabled) bank |= 0x40;
+    I2Cdev::writeByte(devAddr, MPU6050_RA_BANK_SEL, bank);
+}
+
+// MEM_START_ADDR register
+
+void MPU6050::setMemoryStartAddress(uint8_t address) {
+    I2Cdev::writeByte(devAddr, MPU6050_RA_MEM_START_ADDR, address);
+}
+
+// MEM_R_W register
+
+uint8_t MPU6050::readMemoryByte() {
+    I2Cdev::readByte(devAddr, MPU6050_RA_MEM_R_W, buffer);
+    return buffer[0];
+}
+void MPU6050::writeMemoryByte(uint8_t data) {
+    I2Cdev::writeByte(devAddr, MPU6050_RA_MEM_R_W, data);
+}
+void MPU6050::readMemoryBlock(uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address) {
+    setMemoryBank(bank);
+    setMemoryStartAddress(address);
+    uint8_t chunkSize;
+    for (uint16_t i = 0; i < dataSize;) {
+        // determine correct chunk size according to bank position and data size
+        chunkSize = MPU6050_DMP_MEMORY_CHUNK_SIZE;
+
+        // make sure we don't go past the data size
+        if (i + chunkSize > dataSize) chunkSize = dataSize - i;
+
+        // make sure this chunk doesn't go past the bank boundary (256 bytes)
+        if (chunkSize > 256 - address) chunkSize = 256 - address;
+
+        // read the chunk of data as specified
+        I2Cdev::readBytes(devAddr, MPU6050_RA_MEM_R_W, chunkSize, data + i);
+        
+        // increase byte index by [chunkSize]
+        i += chunkSize;
+
+        // uint8_t automatically wraps to 0 at 256
+        address += chunkSize;
+
+        // if we aren't done, update bank (if necessary) and address
+        if (i < dataSize) {
+            if (address == 0) bank++;
+            setMemoryBank(bank);
+            setMemoryStartAddress(address);
+        }
+    }
+}
+bool MPU6050::writeMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address, bool verify, bool useProgMem) {
+    setMemoryBank(bank);
+    setMemoryStartAddress(address);
+    uint8_t chunkSize;
+    uint8_t *verifyBuffer;
+    uint8_t *progBuffer;
+    uint16_t i;
+    uint8_t j;
+    if (verify) verifyBuffer = (uint8_t *)malloc(MPU6050_DMP_MEMORY_CHUNK_SIZE);
+    if (useProgMem) progBuffer = (uint8_t *)malloc(MPU6050_DMP_MEMORY_CHUNK_SIZE);
+    for (i = 0; i < dataSize;) {
+        // determine correct chunk size according to bank position and data size
+        chunkSize = MPU6050_DMP_MEMORY_CHUNK_SIZE;
+
+        // make sure we don't go past the data size
+        if (i + chunkSize > dataSize) chunkSize = dataSize - i;
+
+        // make sure this chunk doesn't go past the bank boundary (256 bytes)
+        if (chunkSize > 256 - address) chunkSize = 256 - address;
+        
+        if (useProgMem) {
+            // write the chunk of data as specified
+            for (j = 0; j < chunkSize; j++) progBuffer[j] = pgm_read_byte(data + i + j);
+        } else {
+            // write the chunk of data as specified
+            progBuffer = (uint8_t *)data + i;
+        }
+
+        I2Cdev::writeBytes(devAddr, MPU6050_RA_MEM_R_W, chunkSize, progBuffer);
+
+        // verify data if needed
+        if (verify && verifyBuffer) {
+            setMemoryBank(bank);
+            setMemoryStartAddress(address);
+            I2Cdev::readBytes(devAddr, MPU6050_RA_MEM_R_W, chunkSize, verifyBuffer);
+            if (memcmp(progBuffer, verifyBuffer, chunkSize) != 0) {
+                /*Serial.print("Block write verification error, bank ");
+                Serial.print(bank, DEC);
+                Serial.print(", address ");
+                Serial.print(address, DEC);
+                Serial.print("!\nExpected:");
+                for (j = 0; j < chunkSize; j++) {
+                    Serial.print(" 0x");
+                    if (progBuffer[j] < 16) Serial.print("0");
+                    Serial.print(progBuffer[j], HEX);
+                }
+                Serial.print("\nReceived:");
+                for (uint8_t j = 0; j < chunkSize; j++) {
+                    Serial.print(" 0x");
+                    if (verifyBuffer[i + j] < 16) Serial.print("0");
+                    Serial.print(verifyBuffer[i + j], HEX);
+                }
+                Serial.print("\n");*/
+                free(verifyBuffer);
+                if (useProgMem) free(progBuffer);
+                return false; // uh oh.
+            }
+        }
+
+        // increase byte index by [chunkSize]
+        i += chunkSize;
+
+        // uint8_t automatically wraps to 0 at 256
+        address += chunkSize;
+
+        // if we aren't done, update bank (if necessary) and address
+        if (i < dataSize) {
+            if (address == 0) bank++;
+            setMemoryBank(bank);
+            setMemoryStartAddress(address);
+        }
+    }
+    if (verify) free(verifyBuffer);
+    if (useProgMem) free(progBuffer);
+    return true;
+}
+bool MPU6050::writeProgMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address, bool verify) {
+    return writeMemoryBlock(data, dataSize, bank, address, verify, true);
+}
+bool MPU6050::writeDMPConfigurationSet(const uint8_t *data, uint16_t dataSize, bool useProgMem) {
+    uint8_t *progBuffer, success, special;
+    uint16_t i, j;
+    if (useProgMem) {
+        progBuffer = (uint8_t *)malloc(8); // assume 8-byte blocks, realloc later if necessary
+    }
+
+    // config set data is a long string of blocks with the following structure:
+    // [bank] [offset] [length] [byte[0], byte[1], ..., byte[length]]
+    uint8_t bank, offset, length;
+    for (i = 0; i < dataSize;) {
+        if (useProgMem) {
+            bank = pgm_read_byte(data + i++);
+            offset = pgm_read_byte(data + i++);
+            length = pgm_read_byte(data + i++);
+        } else {
+            bank = data[i++];
+            offset = data[i++];
+            length = data[i++];
+        }
+
+        // write data or perform special action
+        if (length > 0) {
+            // regular block of data to write
+            /*Serial.print("Writing config block to bank ");
+            Serial.print(bank);
+            Serial.print(", offset ");
+            Serial.print(offset);
+            Serial.print(", length=");
+            Serial.println(length);*/
+            if (useProgMem) {
+                if (sizeof(progBuffer) < length) progBuffer = (uint8_t *)realloc(progBuffer, length);
+                for (j = 0; j < length; j++) progBuffer[j] = pgm_read_byte(data + i + j);
+            } else {
+                progBuffer = (uint8_t *)data + i;
+            }
+            success = writeMemoryBlock(progBuffer, length, bank, offset, true);
+            i += length;
+        } else {
+            // special instruction
+            // NOTE: this kind of behavior (what and when to do certain things)
+            // is totally undocumented. This code is in here based on observed
+            // behavior only, and exactly why (or even whether) it has to be here
+            // is anybody's guess for now.
+            if (useProgMem) {
+                special = pgm_read_byte(data + i++);
+            } else {
+                special = data[i++];
+            }
+            /*Serial.print("Special command code ");
+            Serial.print(special, HEX);
+            Serial.println(" found...");*/
+            if (special == 0x01) {
+                // enable DMP-related interrupts
+                
+                //setIntZeroMotionEnabled(true);
+                //setIntFIFOBufferOverflowEnabled(true);
+                //setIntDMPEnabled(true);
+                I2Cdev::writeByte(devAddr, MPU6050_RA_INT_ENABLE, 0x32);  // single operation
+
+                success = true;
+            } else {
+                // unknown special command
+                success = false;
+            }
+        }
+        
+        if (!success) {
+            if (useProgMem) free(progBuffer);
+            return false; // uh oh
+        }
+    }
+    if (useProgMem) free(progBuffer);
+    return true;
+}
+bool MPU6050::writeProgDMPConfigurationSet(const uint8_t *data, uint16_t dataSize) {
+    return writeDMPConfigurationSet(data, dataSize, true);
+}
+
+// DMP_CFG_1 register
+
+uint8_t MPU6050::getDMPConfig1() {
+    I2Cdev::readByte(devAddr, MPU6050_RA_DMP_CFG_1, buffer);
+    return buffer[0];
+}
+void MPU6050::setDMPConfig1(uint8_t config) {
+    I2Cdev::writeByte(devAddr, MPU6050_RA_DMP_CFG_1, config);
+}
+
+// DMP_CFG_2 register
+
+uint8_t MPU6050::getDMPConfig2() {
+    I2Cdev::readByte(devAddr, MPU6050_RA_DMP_CFG_2, buffer);
+    return buffer[0];
+}
+void MPU6050::setDMPConfig2(uint8_t config) {
+    I2Cdev::writeByte(devAddr, MPU6050_RA_DMP_CFG_2, config);
+}
\ No newline at end of file
diff --git a/Arduino/MPU9150/MPU6050.h b/Arduino/MPU9150/MPU6050.h
new file mode 100644
index 00000000..7761de8f
--- /dev/null
+++ b/Arduino/MPU9150/MPU6050.h
@@ -0,0 +1,997 @@
+// I2Cdev library collection - MPU6050 I2C device class
+// Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00)
+// 10/3/2011 by Jeff Rowberg 
+// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
+//
+// Changelog:
+//     ... - ongoing debug release
+
+// NOTE: THIS IS ONLY A PARIAL RELEASE. THIS DEVICE CLASS IS CURRENTLY UNDERGOING ACTIVE
+// DEVELOPMENT AND IS STILL MISSING SOME IMPORTANT FEATURES. PLEASE KEEP THIS IN MIND IF
+// YOU DECIDE TO USE THIS PARTICULAR CODE FOR ANYTHING.
+
+/* ============================================
+I2Cdev device library code is placed under the MIT license
+Copyright (c) 2012 Jeff Rowberg
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+===============================================
+*/
+
+#ifndef _MPU6050_H_
+#define _MPU6050_H_
+
+#include "I2Cdev.h"
+
+// supporting link:  http://forum.arduino.cc/index.php?&topic=143444.msg1079517#msg1079517
+// also: http://forum.arduino.cc/index.php?&topic=141571.msg1062899#msg1062899s
+#ifndef __arm__
+#include 
+#else
+#define PROGMEM /* empty */
+#define pgm_read_byte(x) (*(x))
+#define pgm_read_word(x) (*(x))
+#define pgm_read_float(x) (*(x))
+#define PSTR(STR) STR
+#endif
+
+
+#define MPU6050_ADDRESS_AD0_LOW     0x68 // address pin low (GND), default for InvenSense evaluation board
+#define MPU6050_ADDRESS_AD0_HIGH    0x69 // address pin high (VCC)
+#define MPU6050_DEFAULT_ADDRESS     MPU6050_ADDRESS_AD0_LOW
+
+#define MPU6050_RA_XG_OFFS_TC       0x00 //[7] PWR_MODE, [6:1] XG_OFFS_TC, [0] OTP_BNK_VLD
+#define MPU6050_RA_YG_OFFS_TC       0x01 //[7] PWR_MODE, [6:1] YG_OFFS_TC, [0] OTP_BNK_VLD
+#define MPU6050_RA_ZG_OFFS_TC       0x02 //[7] PWR_MODE, [6:1] ZG_OFFS_TC, [0] OTP_BNK_VLD
+#define MPU6050_RA_X_FINE_GAIN      0x03 //[7:0] X_FINE_GAIN
+#define MPU6050_RA_Y_FINE_GAIN      0x04 //[7:0] Y_FINE_GAIN
+#define MPU6050_RA_Z_FINE_GAIN      0x05 //[7:0] Z_FINE_GAIN
+#define MPU6050_RA_XA_OFFS_H        0x06 //[15:0] XA_OFFS
+#define MPU6050_RA_XA_OFFS_L_TC     0x07
+#define MPU6050_RA_YA_OFFS_H        0x08 //[15:0] YA_OFFS
+#define MPU6050_RA_YA_OFFS_L_TC     0x09
+#define MPU6050_RA_ZA_OFFS_H        0x0A //[15:0] ZA_OFFS
+#define MPU6050_RA_ZA_OFFS_L_TC     0x0B
+#define MPU6050_RA_XG_OFFS_USRH     0x13 //[15:0] XG_OFFS_USR
+#define MPU6050_RA_XG_OFFS_USRL     0x14
+#define MPU6050_RA_YG_OFFS_USRH     0x15 //[15:0] YG_OFFS_USR
+#define MPU6050_RA_YG_OFFS_USRL     0x16
+#define MPU6050_RA_ZG_OFFS_USRH     0x17 //[15:0] ZG_OFFS_USR
+#define MPU6050_RA_ZG_OFFS_USRL     0x18
+#define MPU6050_RA_SMPLRT_DIV       0x19
+#define MPU6050_RA_CONFIG           0x1A
+#define MPU6050_RA_GYRO_CONFIG      0x1B
+#define MPU6050_RA_ACCEL_CONFIG     0x1C
+#define MPU6050_RA_FF_THR           0x1D
+#define MPU6050_RA_FF_DUR           0x1E
+#define MPU6050_RA_MOT_THR          0x1F
+#define MPU6050_RA_MOT_DUR          0x20
+#define MPU6050_RA_ZRMOT_THR        0x21
+#define MPU6050_RA_ZRMOT_DUR        0x22
+#define MPU6050_RA_FIFO_EN          0x23
+#define MPU6050_RA_I2C_MST_CTRL     0x24
+#define MPU6050_RA_I2C_SLV0_ADDR    0x25
+#define MPU6050_RA_I2C_SLV0_REG     0x26
+#define MPU6050_RA_I2C_SLV0_CTRL    0x27
+#define MPU6050_RA_I2C_SLV1_ADDR    0x28
+#define MPU6050_RA_I2C_SLV1_REG     0x29
+#define MPU6050_RA_I2C_SLV1_CTRL    0x2A
+#define MPU6050_RA_I2C_SLV2_ADDR    0x2B
+#define MPU6050_RA_I2C_SLV2_REG     0x2C
+#define MPU6050_RA_I2C_SLV2_CTRL    0x2D
+#define MPU6050_RA_I2C_SLV3_ADDR    0x2E
+#define MPU6050_RA_I2C_SLV3_REG     0x2F
+#define MPU6050_RA_I2C_SLV3_CTRL    0x30
+#define MPU6050_RA_I2C_SLV4_ADDR    0x31
+#define MPU6050_RA_I2C_SLV4_REG     0x32
+#define MPU6050_RA_I2C_SLV4_DO      0x33
+#define MPU6050_RA_I2C_SLV4_CTRL    0x34
+#define MPU6050_RA_I2C_SLV4_DI      0x35
+#define MPU6050_RA_I2C_MST_STATUS   0x36
+#define MPU6050_RA_INT_PIN_CFG      0x37
+#define MPU6050_RA_INT_ENABLE       0x38
+#define MPU6050_RA_DMP_INT_STATUS   0x39
+#define MPU6050_RA_INT_STATUS       0x3A
+#define MPU6050_RA_ACCEL_XOUT_H     0x3B
+#define MPU6050_RA_ACCEL_XOUT_L     0x3C
+#define MPU6050_RA_ACCEL_YOUT_H     0x3D
+#define MPU6050_RA_ACCEL_YOUT_L     0x3E
+#define MPU6050_RA_ACCEL_ZOUT_H     0x3F
+#define MPU6050_RA_ACCEL_ZOUT_L     0x40
+#define MPU6050_RA_TEMP_OUT_H       0x41
+#define MPU6050_RA_TEMP_OUT_L       0x42
+#define MPU6050_RA_GYRO_XOUT_H      0x43
+#define MPU6050_RA_GYRO_XOUT_L      0x44
+#define MPU6050_RA_GYRO_YOUT_H      0x45
+#define MPU6050_RA_GYRO_YOUT_L      0x46
+#define MPU6050_RA_GYRO_ZOUT_H      0x47
+#define MPU6050_RA_GYRO_ZOUT_L      0x48
+#define MPU6050_RA_EXT_SENS_DATA_00 0x49
+#define MPU6050_RA_EXT_SENS_DATA_01 0x4A
+#define MPU6050_RA_EXT_SENS_DATA_02 0x4B
+#define MPU6050_RA_EXT_SENS_DATA_03 0x4C
+#define MPU6050_RA_EXT_SENS_DATA_04 0x4D
+#define MPU6050_RA_EXT_SENS_DATA_05 0x4E
+#define MPU6050_RA_EXT_SENS_DATA_06 0x4F
+#define MPU6050_RA_EXT_SENS_DATA_07 0x50
+#define MPU6050_RA_EXT_SENS_DATA_08 0x51
+#define MPU6050_RA_EXT_SENS_DATA_09 0x52
+#define MPU6050_RA_EXT_SENS_DATA_10 0x53
+#define MPU6050_RA_EXT_SENS_DATA_11 0x54
+#define MPU6050_RA_EXT_SENS_DATA_12 0x55
+#define MPU6050_RA_EXT_SENS_DATA_13 0x56
+#define MPU6050_RA_EXT_SENS_DATA_14 0x57
+#define MPU6050_RA_EXT_SENS_DATA_15 0x58
+#define MPU6050_RA_EXT_SENS_DATA_16 0x59
+#define MPU6050_RA_EXT_SENS_DATA_17 0x5A
+#define MPU6050_RA_EXT_SENS_DATA_18 0x5B
+#define MPU6050_RA_EXT_SENS_DATA_19 0x5C
+#define MPU6050_RA_EXT_SENS_DATA_20 0x5D
+#define MPU6050_RA_EXT_SENS_DATA_21 0x5E
+#define MPU6050_RA_EXT_SENS_DATA_22 0x5F
+#define MPU6050_RA_EXT_SENS_DATA_23 0x60
+#define MPU6050_RA_MOT_DETECT_STATUS    0x61
+#define MPU6050_RA_I2C_SLV0_DO      0x63
+#define MPU6050_RA_I2C_SLV1_DO      0x64
+#define MPU6050_RA_I2C_SLV2_DO      0x65
+#define MPU6050_RA_I2C_SLV3_DO      0x66
+#define MPU6050_RA_I2C_MST_DELAY_CTRL   0x67
+#define MPU6050_RA_SIGNAL_PATH_RESET    0x68
+#define MPU6050_RA_MOT_DETECT_CTRL      0x69
+#define MPU6050_RA_USER_CTRL        0x6A
+#define MPU6050_RA_PWR_MGMT_1       0x6B
+#define MPU6050_RA_PWR_MGMT_2       0x6C
+#define MPU6050_RA_BANK_SEL         0x6D
+#define MPU6050_RA_MEM_START_ADDR   0x6E
+#define MPU6050_RA_MEM_R_W          0x6F
+#define MPU6050_RA_DMP_CFG_1        0x70
+#define MPU6050_RA_DMP_CFG_2        0x71
+#define MPU6050_RA_FIFO_COUNTH      0x72
+#define MPU6050_RA_FIFO_COUNTL      0x73
+#define MPU6050_RA_FIFO_R_W         0x74
+#define MPU6050_RA_WHO_AM_I         0x75
+
+#define MPU6050_TC_PWR_MODE_BIT     7
+#define MPU6050_TC_OFFSET_BIT       6
+#define MPU6050_TC_OFFSET_LENGTH    6
+#define MPU6050_TC_OTP_BNK_VLD_BIT  0
+
+#define MPU6050_VDDIO_LEVEL_VLOGIC  0
+#define MPU6050_VDDIO_LEVEL_VDD     1
+
+#define MPU6050_CFG_EXT_SYNC_SET_BIT    5
+#define MPU6050_CFG_EXT_SYNC_SET_LENGTH 3
+#define MPU6050_CFG_DLPF_CFG_BIT    2
+#define MPU6050_CFG_DLPF_CFG_LENGTH 3
+
+#define MPU6050_EXT_SYNC_DISABLED       0x0
+#define MPU6050_EXT_SYNC_TEMP_OUT_L     0x1
+#define MPU6050_EXT_SYNC_GYRO_XOUT_L    0x2
+#define MPU6050_EXT_SYNC_GYRO_YOUT_L    0x3
+#define MPU6050_EXT_SYNC_GYRO_ZOUT_L    0x4
+#define MPU6050_EXT_SYNC_ACCEL_XOUT_L   0x5
+#define MPU6050_EXT_SYNC_ACCEL_YOUT_L   0x6
+#define MPU6050_EXT_SYNC_ACCEL_ZOUT_L   0x7
+
+#define MPU6050_DLPF_BW_256         0x00
+#define MPU6050_DLPF_BW_188         0x01
+#define MPU6050_DLPF_BW_98          0x02
+#define MPU6050_DLPF_BW_42          0x03
+#define MPU6050_DLPF_BW_20          0x04
+#define MPU6050_DLPF_BW_10          0x05
+#define MPU6050_DLPF_BW_5           0x06
+
+#define MPU6050_GCONFIG_FS_SEL_BIT      4
+#define MPU6050_GCONFIG_FS_SEL_LENGTH   2
+
+#define MPU6050_GYRO_FS_250         0x00
+#define MPU6050_GYRO_FS_500         0x01
+#define MPU6050_GYRO_FS_1000        0x02
+#define MPU6050_GYRO_FS_2000        0x03
+
+#define MPU6050_ACONFIG_XA_ST_BIT           7
+#define MPU6050_ACONFIG_YA_ST_BIT           6
+#define MPU6050_ACONFIG_ZA_ST_BIT           5
+#define MPU6050_ACONFIG_AFS_SEL_BIT         4
+#define MPU6050_ACONFIG_AFS_SEL_LENGTH      2
+#define MPU6050_ACONFIG_ACCEL_HPF_BIT       2
+#define MPU6050_ACONFIG_ACCEL_HPF_LENGTH    3
+
+#define MPU6050_ACCEL_FS_2          0x00
+#define MPU6050_ACCEL_FS_4          0x01
+#define MPU6050_ACCEL_FS_8          0x02
+#define MPU6050_ACCEL_FS_16         0x03
+
+#define MPU6050_DHPF_RESET          0x00
+#define MPU6050_DHPF_5              0x01
+#define MPU6050_DHPF_2P5            0x02
+#define MPU6050_DHPF_1P25           0x03
+#define MPU6050_DHPF_0P63           0x04
+#define MPU6050_DHPF_HOLD           0x07
+
+#define MPU6050_TEMP_FIFO_EN_BIT    7
+#define MPU6050_XG_FIFO_EN_BIT      6
+#define MPU6050_YG_FIFO_EN_BIT      5
+#define MPU6050_ZG_FIFO_EN_BIT      4
+#define MPU6050_ACCEL_FIFO_EN_BIT   3
+#define MPU6050_SLV2_FIFO_EN_BIT    2
+#define MPU6050_SLV1_FIFO_EN_BIT    1
+#define MPU6050_SLV0_FIFO_EN_BIT    0
+
+#define MPU6050_MULT_MST_EN_BIT     7
+#define MPU6050_WAIT_FOR_ES_BIT     6
+#define MPU6050_SLV_3_FIFO_EN_BIT   5
+#define MPU6050_I2C_MST_P_NSR_BIT   4
+#define MPU6050_I2C_MST_CLK_BIT     3
+#define MPU6050_I2C_MST_CLK_LENGTH  4
+
+#define MPU6050_CLOCK_DIV_348       0x0
+#define MPU6050_CLOCK_DIV_333       0x1
+#define MPU6050_CLOCK_DIV_320       0x2
+#define MPU6050_CLOCK_DIV_308       0x3
+#define MPU6050_CLOCK_DIV_296       0x4
+#define MPU6050_CLOCK_DIV_286       0x5
+#define MPU6050_CLOCK_DIV_276       0x6
+#define MPU6050_CLOCK_DIV_267       0x7
+#define MPU6050_CLOCK_DIV_258       0x8
+#define MPU6050_CLOCK_DIV_500       0x9
+#define MPU6050_CLOCK_DIV_471       0xA
+#define MPU6050_CLOCK_DIV_444       0xB
+#define MPU6050_CLOCK_DIV_421       0xC
+#define MPU6050_CLOCK_DIV_400       0xD
+#define MPU6050_CLOCK_DIV_381       0xE
+#define MPU6050_CLOCK_DIV_364       0xF
+
+#define MPU6050_I2C_SLV_RW_BIT      7
+#define MPU6050_I2C_SLV_ADDR_BIT    6
+#define MPU6050_I2C_SLV_ADDR_LENGTH 7
+#define MPU6050_I2C_SLV_EN_BIT      7
+#define MPU6050_I2C_SLV_BYTE_SW_BIT 6
+#define MPU6050_I2C_SLV_REG_DIS_BIT 5
+#define MPU6050_I2C_SLV_GRP_BIT     4
+#define MPU6050_I2C_SLV_LEN_BIT     3
+#define MPU6050_I2C_SLV_LEN_LENGTH  4
+
+#define MPU6050_I2C_SLV4_RW_BIT         7
+#define MPU6050_I2C_SLV4_ADDR_BIT       6
+#define MPU6050_I2C_SLV4_ADDR_LENGTH    7
+#define MPU6050_I2C_SLV4_EN_BIT         7
+#define MPU6050_I2C_SLV4_INT_EN_BIT     6
+#define MPU6050_I2C_SLV4_REG_DIS_BIT    5
+#define MPU6050_I2C_SLV4_MST_DLY_BIT    4
+#define MPU6050_I2C_SLV4_MST_DLY_LENGTH 5
+
+#define MPU6050_MST_PASS_THROUGH_BIT    7
+#define MPU6050_MST_I2C_SLV4_DONE_BIT   6
+#define MPU6050_MST_I2C_LOST_ARB_BIT    5
+#define MPU6050_MST_I2C_SLV4_NACK_BIT   4
+#define MPU6050_MST_I2C_SLV3_NACK_BIT   3
+#define MPU6050_MST_I2C_SLV2_NACK_BIT   2
+#define MPU6050_MST_I2C_SLV1_NACK_BIT   1
+#define MPU6050_MST_I2C_SLV0_NACK_BIT   0
+
+#define MPU6050_INTCFG_INT_LEVEL_BIT        7
+#define MPU6050_INTCFG_INT_OPEN_BIT         6
+#define MPU6050_INTCFG_LATCH_INT_EN_BIT     5
+#define MPU6050_INTCFG_INT_RD_CLEAR_BIT     4
+#define MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT  3
+#define MPU6050_INTCFG_FSYNC_INT_EN_BIT     2
+#define MPU6050_INTCFG_I2C_BYPASS_EN_BIT    1
+#define MPU6050_INTCFG_CLKOUT_EN_BIT        0
+
+#define MPU6050_INTMODE_ACTIVEHIGH  0x00
+#define MPU6050_INTMODE_ACTIVELOW   0x01
+
+#define MPU6050_INTDRV_PUSHPULL     0x00
+#define MPU6050_INTDRV_OPENDRAIN    0x01
+
+#define MPU6050_INTLATCH_50USPULSE  0x00
+#define MPU6050_INTLATCH_WAITCLEAR  0x01
+
+#define MPU6050_INTCLEAR_STATUSREAD 0x00
+#define MPU6050_INTCLEAR_ANYREAD    0x01
+
+#define MPU6050_INTERRUPT_FF_BIT            7
+#define MPU6050_INTERRUPT_MOT_BIT           6
+#define MPU6050_INTERRUPT_ZMOT_BIT          5
+#define MPU6050_INTERRUPT_FIFO_OFLOW_BIT    4
+#define MPU6050_INTERRUPT_I2C_MST_INT_BIT   3
+#define MPU6050_INTERRUPT_PLL_RDY_INT_BIT   2
+#define MPU6050_INTERRUPT_DMP_INT_BIT       1
+#define MPU6050_INTERRUPT_DATA_RDY_BIT      0
+
+// TODO: figure out what these actually do
+// UMPL source code is not very obivous
+#define MPU6050_DMPINT_5_BIT            5
+#define MPU6050_DMPINT_4_BIT            4
+#define MPU6050_DMPINT_3_BIT            3
+#define MPU6050_DMPINT_2_BIT            2
+#define MPU6050_DMPINT_1_BIT            1
+#define MPU6050_DMPINT_0_BIT            0
+
+#define MPU6050_MOTION_MOT_XNEG_BIT     7
+#define MPU6050_MOTION_MOT_XPOS_BIT     6
+#define MPU6050_MOTION_MOT_YNEG_BIT     5
+#define MPU6050_MOTION_MOT_YPOS_BIT     4
+#define MPU6050_MOTION_MOT_ZNEG_BIT     3
+#define MPU6050_MOTION_MOT_ZPOS_BIT     2
+#define MPU6050_MOTION_MOT_ZRMOT_BIT    0
+
+#define MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT   7
+#define MPU6050_DELAYCTRL_I2C_SLV4_DLY_EN_BIT   4
+#define MPU6050_DELAYCTRL_I2C_SLV3_DLY_EN_BIT   3
+#define MPU6050_DELAYCTRL_I2C_SLV2_DLY_EN_BIT   2
+#define MPU6050_DELAYCTRL_I2C_SLV1_DLY_EN_BIT   1
+#define MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT   0
+
+#define MPU6050_PATHRESET_GYRO_RESET_BIT    2
+#define MPU6050_PATHRESET_ACCEL_RESET_BIT   1
+#define MPU6050_PATHRESET_TEMP_RESET_BIT    0
+
+#define MPU6050_DETECT_ACCEL_ON_DELAY_BIT       5
+#define MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH    2
+#define MPU6050_DETECT_FF_COUNT_BIT             3
+#define MPU6050_DETECT_FF_COUNT_LENGTH          2
+#define MPU6050_DETECT_MOT_COUNT_BIT            1
+#define MPU6050_DETECT_MOT_COUNT_LENGTH         2
+
+#define MPU6050_DETECT_DECREMENT_RESET  0x0
+#define MPU6050_DETECT_DECREMENT_1      0x1
+#define MPU6050_DETECT_DECREMENT_2      0x2
+#define MPU6050_DETECT_DECREMENT_4      0x3
+
+#define MPU6050_USERCTRL_DMP_EN_BIT             7
+#define MPU6050_USERCTRL_FIFO_EN_BIT            6
+#define MPU6050_USERCTRL_I2C_MST_EN_BIT         5
+#define MPU6050_USERCTRL_I2C_IF_DIS_BIT         4
+#define MPU6050_USERCTRL_DMP_RESET_BIT          3
+#define MPU6050_USERCTRL_FIFO_RESET_BIT         2
+#define MPU6050_USERCTRL_I2C_MST_RESET_BIT      1
+#define MPU6050_USERCTRL_SIG_COND_RESET_BIT     0
+
+#define MPU6050_PWR1_DEVICE_RESET_BIT   7
+#define MPU6050_PWR1_SLEEP_BIT          6
+#define MPU6050_PWR1_CYCLE_BIT          5
+#define MPU6050_PWR1_TEMP_DIS_BIT       3
+#define MPU6050_PWR1_CLKSEL_BIT         2
+#define MPU6050_PWR1_CLKSEL_LENGTH      3
+
+#define MPU6050_CLOCK_INTERNAL          0x00
+#define MPU6050_CLOCK_PLL_XGYRO         0x01
+#define MPU6050_CLOCK_PLL_YGYRO         0x02
+#define MPU6050_CLOCK_PLL_ZGYRO         0x03
+#define MPU6050_CLOCK_PLL_EXT32K        0x04
+#define MPU6050_CLOCK_PLL_EXT19M        0x05
+#define MPU6050_CLOCK_KEEP_RESET        0x07
+
+#define MPU6050_PWR2_LP_WAKE_CTRL_BIT       7
+#define MPU6050_PWR2_LP_WAKE_CTRL_LENGTH    2
+#define MPU6050_PWR2_STBY_XA_BIT            5
+#define MPU6050_PWR2_STBY_YA_BIT            4
+#define MPU6050_PWR2_STBY_ZA_BIT            3
+#define MPU6050_PWR2_STBY_XG_BIT            2
+#define MPU6050_PWR2_STBY_YG_BIT            1
+#define MPU6050_PWR2_STBY_ZG_BIT            0
+
+#define MPU6050_WAKE_FREQ_1P25      0x0
+#define MPU6050_WAKE_FREQ_2P5       0x1
+#define MPU6050_WAKE_FREQ_5         0x2
+#define MPU6050_WAKE_FREQ_10        0x3
+
+#define MPU6050_BANKSEL_PRFTCH_EN_BIT       6
+#define MPU6050_BANKSEL_CFG_USER_BANK_BIT   5
+#define MPU6050_BANKSEL_MEM_SEL_BIT         4
+#define MPU6050_BANKSEL_MEM_SEL_LENGTH      5
+
+#define MPU6050_WHO_AM_I_BIT        6
+#define MPU6050_WHO_AM_I_LENGTH     6
+
+#define MPU6050_DMP_MEMORY_BANKS        8
+#define MPU6050_DMP_MEMORY_BANK_SIZE    256
+#define MPU6050_DMP_MEMORY_CHUNK_SIZE   16
+
+// note: DMP code memory blocks defined at end of header file
+
+class MPU6050 {
+    public:
+        MPU6050();
+        MPU6050(uint8_t address);
+
+        void initialize();
+        bool testConnection();
+
+        // AUX_VDDIO register
+        uint8_t getAuxVDDIOLevel();
+        void setAuxVDDIOLevel(uint8_t level);
+
+        // SMPLRT_DIV register
+        uint8_t getRate();
+        void setRate(uint8_t rate);
+
+        // CONFIG register
+        uint8_t getExternalFrameSync();
+        void setExternalFrameSync(uint8_t sync);
+        uint8_t getDLPFMode();
+        void setDLPFMode(uint8_t bandwidth);
+
+        // GYRO_CONFIG register
+        uint8_t getFullScaleGyroRange();
+        void setFullScaleGyroRange(uint8_t range);
+
+        // ACCEL_CONFIG register
+        bool getAccelXSelfTest();
+        void setAccelXSelfTest(bool enabled);
+        bool getAccelYSelfTest();
+        void setAccelYSelfTest(bool enabled);
+        bool getAccelZSelfTest();
+        void setAccelZSelfTest(bool enabled);
+        uint8_t getFullScaleAccelRange();
+        void setFullScaleAccelRange(uint8_t range);
+        uint8_t getDHPFMode();
+        void setDHPFMode(uint8_t mode);
+
+        // FF_THR register
+        uint8_t getFreefallDetectionThreshold();
+        void setFreefallDetectionThreshold(uint8_t threshold);
+
+        // FF_DUR register
+        uint8_t getFreefallDetectionDuration();
+        void setFreefallDetectionDuration(uint8_t duration);
+
+        // MOT_THR register
+        uint8_t getMotionDetectionThreshold();
+        void setMotionDetectionThreshold(uint8_t threshold);
+
+        // MOT_DUR register
+        uint8_t getMotionDetectionDuration();
+        void setMotionDetectionDuration(uint8_t duration);
+
+        // ZRMOT_THR register
+        uint8_t getZeroMotionDetectionThreshold();
+        void setZeroMotionDetectionThreshold(uint8_t threshold);
+
+        // ZRMOT_DUR register
+        uint8_t getZeroMotionDetectionDuration();
+        void setZeroMotionDetectionDuration(uint8_t duration);
+
+        // FIFO_EN register
+        bool getTempFIFOEnabled();
+        void setTempFIFOEnabled(bool enabled);
+        bool getXGyroFIFOEnabled();
+        void setXGyroFIFOEnabled(bool enabled);
+        bool getYGyroFIFOEnabled();
+        void setYGyroFIFOEnabled(bool enabled);
+        bool getZGyroFIFOEnabled();
+        void setZGyroFIFOEnabled(bool enabled);
+        bool getAccelFIFOEnabled();
+        void setAccelFIFOEnabled(bool enabled);
+        bool getSlave2FIFOEnabled();
+        void setSlave2FIFOEnabled(bool enabled);
+        bool getSlave1FIFOEnabled();
+        void setSlave1FIFOEnabled(bool enabled);
+        bool getSlave0FIFOEnabled();
+        void setSlave0FIFOEnabled(bool enabled);
+
+        // I2C_MST_CTRL register
+        bool getMultiMasterEnabled();
+        void setMultiMasterEnabled(bool enabled);
+        bool getWaitForExternalSensorEnabled();
+        void setWaitForExternalSensorEnabled(bool enabled);
+        bool getSlave3FIFOEnabled();
+        void setSlave3FIFOEnabled(bool enabled);
+        bool getSlaveReadWriteTransitionEnabled();
+        void setSlaveReadWriteTransitionEnabled(bool enabled);
+        uint8_t getMasterClockSpeed();
+        void setMasterClockSpeed(uint8_t speed);
+
+        // I2C_SLV* registers (Slave 0-3)
+        uint8_t getSlaveAddress(uint8_t num);
+        void setSlaveAddress(uint8_t num, uint8_t address);
+        uint8_t getSlaveRegister(uint8_t num);
+        void setSlaveRegister(uint8_t num, uint8_t reg);
+        bool getSlaveEnabled(uint8_t num);
+        void setSlaveEnabled(uint8_t num, bool enabled);
+        bool getSlaveWordByteSwap(uint8_t num);
+        void setSlaveWordByteSwap(uint8_t num, bool enabled);
+        bool getSlaveWriteMode(uint8_t num);
+        void setSlaveWriteMode(uint8_t num, bool mode);
+        bool getSlaveWordGroupOffset(uint8_t num);
+        void setSlaveWordGroupOffset(uint8_t num, bool enabled);
+        uint8_t getSlaveDataLength(uint8_t num);
+        void setSlaveDataLength(uint8_t num, uint8_t length);
+
+        // I2C_SLV* registers (Slave 4)
+        uint8_t getSlave4Address();
+        void setSlave4Address(uint8_t address);
+        uint8_t getSlave4Register();
+        void setSlave4Register(uint8_t reg);
+        void setSlave4OutputByte(uint8_t data);
+        bool getSlave4Enabled();
+        void setSlave4Enabled(bool enabled);
+        bool getSlave4InterruptEnabled();
+        void setSlave4InterruptEnabled(bool enabled);
+        bool getSlave4WriteMode();
+        void setSlave4WriteMode(bool mode);
+        uint8_t getSlave4MasterDelay();
+        void setSlave4MasterDelay(uint8_t delay);
+        uint8_t getSlate4InputByte();
+
+        // I2C_MST_STATUS register
+        bool getPassthroughStatus();
+        bool getSlave4IsDone();
+        bool getLostArbitration();
+        bool getSlave4Nack();
+        bool getSlave3Nack();
+        bool getSlave2Nack();
+        bool getSlave1Nack();
+        bool getSlave0Nack();
+
+        // INT_PIN_CFG register
+        bool getInterruptMode();
+        void setInterruptMode(bool mode);
+        bool getInterruptDrive();
+        void setInterruptDrive(bool drive);
+        bool getInterruptLatch();
+        void setInterruptLatch(bool latch);
+        bool getInterruptLatchClear();
+        void setInterruptLatchClear(bool clear);
+        bool getFSyncInterruptLevel();
+        void setFSyncInterruptLevel(bool level);
+        bool getFSyncInterruptEnabled();
+        void setFSyncInterruptEnabled(bool enabled);
+        bool getI2CBypassEnabled();
+        void setI2CBypassEnabled(bool enabled);
+        bool getClockOutputEnabled();
+        void setClockOutputEnabled(bool enabled);
+
+        // INT_ENABLE register
+        uint8_t getIntEnabled();
+        void setIntEnabled(uint8_t enabled);
+        bool getIntFreefallEnabled();
+        void setIntFreefallEnabled(bool enabled);
+        bool getIntMotionEnabled();
+        void setIntMotionEnabled(bool enabled);
+        bool getIntZeroMotionEnabled();
+        void setIntZeroMotionEnabled(bool enabled);
+        bool getIntFIFOBufferOverflowEnabled();
+        void setIntFIFOBufferOverflowEnabled(bool enabled);
+        bool getIntI2CMasterEnabled();
+        void setIntI2CMasterEnabled(bool enabled);
+        bool getIntDataReadyEnabled();
+        void setIntDataReadyEnabled(bool enabled);
+
+        // INT_STATUS register
+        uint8_t getIntStatus();
+        bool getIntFreefallStatus();
+        bool getIntMotionStatus();
+        bool getIntZeroMotionStatus();
+        bool getIntFIFOBufferOverflowStatus();
+        bool getIntI2CMasterStatus();
+        bool getIntDataReadyStatus();
+
+        // ACCEL_*OUT_* registers
+        void getMotion9(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz, int16_t* mx, int16_t* my, int16_t* mz);
+        void getMotion6(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz);
+        void getAcceleration(int16_t* x, int16_t* y, int16_t* z);
+        int16_t getAccelerationX();
+        int16_t getAccelerationY();
+        int16_t getAccelerationZ();
+
+        // TEMP_OUT_* registers
+        int16_t getTemperature();
+
+        // GYRO_*OUT_* registers
+        void getRotation(int16_t* x, int16_t* y, int16_t* z);
+        int16_t getRotationX();
+        int16_t getRotationY();
+        int16_t getRotationZ();
+
+        // EXT_SENS_DATA_* registers
+        uint8_t getExternalSensorByte(int position);
+        uint16_t getExternalSensorWord(int position);
+        uint32_t getExternalSensorDWord(int position);
+
+        // MOT_DETECT_STATUS register
+        bool getXNegMotionDetected();
+        bool getXPosMotionDetected();
+        bool getYNegMotionDetected();
+        bool getYPosMotionDetected();
+        bool getZNegMotionDetected();
+        bool getZPosMotionDetected();
+        bool getZeroMotionDetected();
+
+        // I2C_SLV*_DO register
+        void setSlaveOutputByte(uint8_t num, uint8_t data);
+
+        // I2C_MST_DELAY_CTRL register
+        bool getExternalShadowDelayEnabled();
+        void setExternalShadowDelayEnabled(bool enabled);
+        bool getSlaveDelayEnabled(uint8_t num);
+        void setSlaveDelayEnabled(uint8_t num, bool enabled);
+
+        // SIGNAL_PATH_RESET register
+        void resetGyroscopePath();
+        void resetAccelerometerPath();
+        void resetTemperaturePath();
+
+        // MOT_DETECT_CTRL register
+        uint8_t getAccelerometerPowerOnDelay();
+        void setAccelerometerPowerOnDelay(uint8_t delay);
+        uint8_t getFreefallDetectionCounterDecrement();
+        void setFreefallDetectionCounterDecrement(uint8_t decrement);
+        uint8_t getMotionDetectionCounterDecrement();
+        void setMotionDetectionCounterDecrement(uint8_t decrement);
+
+        // USER_CTRL register
+        bool getFIFOEnabled();
+        void setFIFOEnabled(bool enabled);
+        bool getI2CMasterModeEnabled();
+        void setI2CMasterModeEnabled(bool enabled);
+        void switchSPIEnabled(bool enabled);
+        void resetFIFO();
+        void resetI2CMaster();
+        void resetSensors();
+
+        // PWR_MGMT_1 register
+        void reset();
+        bool getSleepEnabled();
+        void setSleepEnabled(bool enabled);
+        bool getWakeCycleEnabled();
+        void setWakeCycleEnabled(bool enabled);
+        bool getTempSensorEnabled();
+        void setTempSensorEnabled(bool enabled);
+        uint8_t getClockSource();
+        void setClockSource(uint8_t source);
+
+        // PWR_MGMT_2 register
+        uint8_t getWakeFrequency();
+        void setWakeFrequency(uint8_t frequency);
+        bool getStandbyXAccelEnabled();
+        void setStandbyXAccelEnabled(bool enabled);
+        bool getStandbyYAccelEnabled();
+        void setStandbyYAccelEnabled(bool enabled);
+        bool getStandbyZAccelEnabled();
+        void setStandbyZAccelEnabled(bool enabled);
+        bool getStandbyXGyroEnabled();
+        void setStandbyXGyroEnabled(bool enabled);
+        bool getStandbyYGyroEnabled();
+        void setStandbyYGyroEnabled(bool enabled);
+        bool getStandbyZGyroEnabled();
+        void setStandbyZGyroEnabled(bool enabled);
+
+        // FIFO_COUNT_* registers
+        uint16_t getFIFOCount();
+
+        // FIFO_R_W register
+        uint8_t getFIFOByte();
+        void setFIFOByte(uint8_t data);
+        void getFIFOBytes(uint8_t *data, uint8_t length);
+
+        // WHO_AM_I register
+        uint8_t getDeviceID();
+        void setDeviceID(uint8_t id);
+        
+        // ======== UNDOCUMENTED/DMP REGISTERS/METHODS ========
+        
+        // XG_OFFS_TC register
+        uint8_t getOTPBankValid();
+        void setOTPBankValid(bool enabled);
+        int8_t getXGyroOffsetTC();
+        void setXGyroOffsetTC(int8_t offset);
+
+        // YG_OFFS_TC register
+        int8_t getYGyroOffsetTC();
+        void setYGyroOffsetTC(int8_t offset);
+
+        // ZG_OFFS_TC register
+        int8_t getZGyroOffsetTC();
+        void setZGyroOffsetTC(int8_t offset);
+
+        // X_FINE_GAIN register
+        int8_t getXFineGain();
+        void setXFineGain(int8_t gain);
+
+        // Y_FINE_GAIN register
+        int8_t getYFineGain();
+        void setYFineGain(int8_t gain);
+
+        // Z_FINE_GAIN register
+        int8_t getZFineGain();
+        void setZFineGain(int8_t gain);
+
+        // XA_OFFS_* registers
+        int16_t getXAccelOffset();
+        void setXAccelOffset(int16_t offset);
+
+        // YA_OFFS_* register
+        int16_t getYAccelOffset();
+        void setYAccelOffset(int16_t offset);
+
+        // ZA_OFFS_* register
+        int16_t getZAccelOffset();
+        void setZAccelOffset(int16_t offset);
+
+        // XG_OFFS_USR* registers
+        int16_t getXGyroOffset();
+        void setXGyroOffset(int16_t offset);
+
+        // YG_OFFS_USR* register
+        int16_t getYGyroOffset();
+        void setYGyroOffset(int16_t offset);
+
+        // ZG_OFFS_USR* register
+        int16_t getZGyroOffset();
+        void setZGyroOffset(int16_t offset);
+        
+        // INT_ENABLE register (DMP functions)
+        bool getIntPLLReadyEnabled();
+        void setIntPLLReadyEnabled(bool enabled);
+        bool getIntDMPEnabled();
+        void setIntDMPEnabled(bool enabled);
+        
+        // DMP_INT_STATUS
+        bool getDMPInt5Status();
+        bool getDMPInt4Status();
+        bool getDMPInt3Status();
+        bool getDMPInt2Status();
+        bool getDMPInt1Status();
+        bool getDMPInt0Status();
+
+        // INT_STATUS register (DMP functions)
+        bool getIntPLLReadyStatus();
+        bool getIntDMPStatus();
+        
+        // USER_CTRL register (DMP functions)
+        bool getDMPEnabled();
+        void setDMPEnabled(bool enabled);
+        void resetDMP();
+        
+        // BANK_SEL register
+        void setMemoryBank(uint8_t bank, bool prefetchEnabled=false, bool userBank=false);
+        
+        // MEM_START_ADDR register
+        void setMemoryStartAddress(uint8_t address);
+        
+        // MEM_R_W register
+        uint8_t readMemoryByte();
+        void writeMemoryByte(uint8_t data);
+        void readMemoryBlock(uint8_t *data, uint16_t dataSize, uint8_t bank=0, uint8_t address=0);
+        bool writeMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank=0, uint8_t address=0, bool verify=true, bool useProgMem=false);
+        bool writeProgMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank=0, uint8_t address=0, bool verify=true);
+
+        bool writeDMPConfigurationSet(const uint8_t *data, uint16_t dataSize, bool useProgMem=false);
+        bool writeProgDMPConfigurationSet(const uint8_t *data, uint16_t dataSize);
+
+        // DMP_CFG_1 register
+        uint8_t getDMPConfig1();
+        void setDMPConfig1(uint8_t config);
+
+        // DMP_CFG_2 register
+        uint8_t getDMPConfig2();
+        void setDMPConfig2(uint8_t config);
+
+        // special methods for MotionApps 2.0 implementation
+        #ifdef MPU6050_INCLUDE_DMP_MOTIONAPPS20
+            uint8_t *dmpPacketBuffer;
+            uint16_t dmpPacketSize;
+
+            uint8_t dmpInitialize();
+            bool dmpPacketAvailable();
+
+            uint8_t dmpSetFIFORate(uint8_t fifoRate);
+            uint8_t dmpGetFIFORate();
+            uint8_t dmpGetSampleStepSizeMS();
+            uint8_t dmpGetSampleFrequency();
+            int32_t dmpDecodeTemperature(int8_t tempReg);
+            
+            // Register callbacks after a packet of FIFO data is processed
+            //uint8_t dmpRegisterFIFORateProcess(inv_obj_func func, int16_t priority);
+            //uint8_t dmpUnregisterFIFORateProcess(inv_obj_func func);
+            uint8_t dmpRunFIFORateProcesses();
+            
+            // Setup FIFO for various output
+            uint8_t dmpSendQuaternion(uint_fast16_t accuracy);
+            uint8_t dmpSendGyro(uint_fast16_t elements, uint_fast16_t accuracy);
+            uint8_t dmpSendAccel(uint_fast16_t elements, uint_fast16_t accuracy);
+            uint8_t dmpSendLinearAccel(uint_fast16_t elements, uint_fast16_t accuracy);
+            uint8_t dmpSendLinearAccelInWorld(uint_fast16_t elements, uint_fast16_t accuracy);
+            uint8_t dmpSendControlData(uint_fast16_t elements, uint_fast16_t accuracy);
+            uint8_t dmpSendSensorData(uint_fast16_t elements, uint_fast16_t accuracy);
+            uint8_t dmpSendExternalSensorData(uint_fast16_t elements, uint_fast16_t accuracy);
+            uint8_t dmpSendGravity(uint_fast16_t elements, uint_fast16_t accuracy);
+            uint8_t dmpSendPacketNumber(uint_fast16_t accuracy);
+            uint8_t dmpSendQuantizedAccel(uint_fast16_t elements, uint_fast16_t accuracy);
+            uint8_t dmpSendEIS(uint_fast16_t elements, uint_fast16_t accuracy);
+
+            // Get Fixed Point data from FIFO
+            uint8_t dmpGetAccel(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetAccel(int16_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetAccel(VectorInt16 *v, const uint8_t* packet=0);
+            uint8_t dmpGetQuaternion(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetQuaternion(int16_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetQuaternion(Quaternion *q, const uint8_t* packet=0);
+            uint8_t dmpGet6AxisQuaternion(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGet6AxisQuaternion(int16_t *data, const uint8_t* packet=0);
+            uint8_t dmpGet6AxisQuaternion(Quaternion *q, const uint8_t* packet=0);
+            uint8_t dmpGetRelativeQuaternion(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetRelativeQuaternion(int16_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetRelativeQuaternion(Quaternion *data, const uint8_t* packet=0);
+            uint8_t dmpGetGyro(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetGyro(int16_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetGyro(VectorInt16 *v, const uint8_t* packet=0);
+            uint8_t dmpSetLinearAccelFilterCoefficient(float coef);
+            uint8_t dmpGetLinearAccel(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetLinearAccel(int16_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetLinearAccel(VectorInt16 *v, const uint8_t* packet=0);
+            uint8_t dmpGetLinearAccel(VectorInt16 *v, VectorInt16 *vRaw, VectorFloat *gravity);
+            uint8_t dmpGetLinearAccelInWorld(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetLinearAccelInWorld(int16_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetLinearAccelInWorld(VectorInt16 *v, const uint8_t* packet=0);
+            uint8_t dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Quaternion *q);
+            uint8_t dmpGetGyroAndAccelSensor(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetGyroAndAccelSensor(int16_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetGyroAndAccelSensor(VectorInt16 *g, VectorInt16 *a, const uint8_t* packet=0);
+            uint8_t dmpGetGyroSensor(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetGyroSensor(int16_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetGyroSensor(VectorInt16 *v, const uint8_t* packet=0);
+            uint8_t dmpGetControlData(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetTemperature(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetGravity(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetGravity(int16_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetGravity(VectorInt16 *v, const uint8_t* packet=0);
+            uint8_t dmpGetGravity(VectorFloat *v, Quaternion *q);
+            uint8_t dmpGetUnquantizedAccel(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetUnquantizedAccel(int16_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetUnquantizedAccel(VectorInt16 *v, const uint8_t* packet=0);
+            uint8_t dmpGetQuantizedAccel(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetQuantizedAccel(int16_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetQuantizedAccel(VectorInt16 *v, const uint8_t* packet=0);
+            uint8_t dmpGetExternalSensorData(int32_t *data, uint16_t size, const uint8_t* packet=0);
+            uint8_t dmpGetEIS(int32_t *data, const uint8_t* packet=0);
+            
+            uint8_t dmpGetEuler(float *data, Quaternion *q);
+            uint8_t dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity);
+
+            // Get Floating Point data from FIFO
+            uint8_t dmpGetAccelFloat(float *data, const uint8_t* packet=0);
+            uint8_t dmpGetQuaternionFloat(float *data, const uint8_t* packet=0);
+
+            uint8_t dmpProcessFIFOPacket(const unsigned char *dmpData);
+            uint8_t dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *processed=NULL);
+
+            uint8_t dmpSetFIFOProcessedCallback(void (*func) (void));
+
+            uint8_t dmpInitFIFOParam();
+            uint8_t dmpCloseFIFO();
+            uint8_t dmpSetGyroDataSource(uint8_t source);
+            uint8_t dmpDecodeQuantizedAccel();
+            uint32_t dmpGetGyroSumOfSquare();
+            uint32_t dmpGetAccelSumOfSquare();
+            void dmpOverrideQuaternion(long *q);
+            uint16_t dmpGetFIFOPacketSize();
+        #endif
+
+        // special methods for MotionApps 4.1 implementation
+        #ifdef MPU6050_INCLUDE_DMP_MOTIONAPPS41
+            uint8_t *dmpPacketBuffer;
+            uint16_t dmpPacketSize;
+
+            uint8_t dmpInitialize();
+            bool dmpPacketAvailable();
+
+            uint8_t dmpSetFIFORate(uint8_t fifoRate);
+            uint8_t dmpGetFIFORate();
+            uint8_t dmpGetSampleStepSizeMS();
+            uint8_t dmpGetSampleFrequency();
+            int32_t dmpDecodeTemperature(int8_t tempReg);
+            
+            // Register callbacks after a packet of FIFO data is processed
+            //uint8_t dmpRegisterFIFORateProcess(inv_obj_func func, int16_t priority);
+            //uint8_t dmpUnregisterFIFORateProcess(inv_obj_func func);
+            uint8_t dmpRunFIFORateProcesses();
+            
+            // Setup FIFO for various output
+            uint8_t dmpSendQuaternion(uint_fast16_t accuracy);
+            uint8_t dmpSendGyro(uint_fast16_t elements, uint_fast16_t accuracy);
+            uint8_t dmpSendAccel(uint_fast16_t elements, uint_fast16_t accuracy);
+            uint8_t dmpSendLinearAccel(uint_fast16_t elements, uint_fast16_t accuracy);
+            uint8_t dmpSendLinearAccelInWorld(uint_fast16_t elements, uint_fast16_t accuracy);
+            uint8_t dmpSendControlData(uint_fast16_t elements, uint_fast16_t accuracy);
+            uint8_t dmpSendSensorData(uint_fast16_t elements, uint_fast16_t accuracy);
+            uint8_t dmpSendExternalSensorData(uint_fast16_t elements, uint_fast16_t accuracy);
+            uint8_t dmpSendGravity(uint_fast16_t elements, uint_fast16_t accuracy);
+            uint8_t dmpSendPacketNumber(uint_fast16_t accuracy);
+            uint8_t dmpSendQuantizedAccel(uint_fast16_t elements, uint_fast16_t accuracy);
+            uint8_t dmpSendEIS(uint_fast16_t elements, uint_fast16_t accuracy);
+
+            // Get Fixed Point data from FIFO
+            uint8_t dmpGetAccel(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetAccel(int16_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetAccel(VectorInt16 *v, const uint8_t* packet=0);
+            uint8_t dmpGetQuaternion(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetQuaternion(int16_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetQuaternion(Quaternion *q, const uint8_t* packet=0);
+            uint8_t dmpGet6AxisQuaternion(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGet6AxisQuaternion(int16_t *data, const uint8_t* packet=0);
+            uint8_t dmpGet6AxisQuaternion(Quaternion *q, const uint8_t* packet=0);
+            uint8_t dmpGetRelativeQuaternion(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetRelativeQuaternion(int16_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetRelativeQuaternion(Quaternion *data, const uint8_t* packet=0);
+            uint8_t dmpGetGyro(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetGyro(int16_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetGyro(VectorInt16 *v, const uint8_t* packet=0);
+            uint8_t dmpGetMag(int16_t *data, const uint8_t* packet=0);
+            uint8_t dmpSetLinearAccelFilterCoefficient(float coef);
+            uint8_t dmpGetLinearAccel(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetLinearAccel(int16_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetLinearAccel(VectorInt16 *v, const uint8_t* packet=0);
+            uint8_t dmpGetLinearAccel(VectorInt16 *v, VectorInt16 *vRaw, VectorFloat *gravity);
+            uint8_t dmpGetLinearAccelInWorld(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetLinearAccelInWorld(int16_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetLinearAccelInWorld(VectorInt16 *v, const uint8_t* packet=0);
+            uint8_t dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Quaternion *q);
+            uint8_t dmpGetGyroAndAccelSensor(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetGyroAndAccelSensor(int16_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetGyroAndAccelSensor(VectorInt16 *g, VectorInt16 *a, const uint8_t* packet=0);
+            uint8_t dmpGetGyroSensor(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetGyroSensor(int16_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetGyroSensor(VectorInt16 *v, const uint8_t* packet=0);
+            uint8_t dmpGetControlData(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetTemperature(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetGravity(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetGravity(int16_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetGravity(VectorInt16 *v, const uint8_t* packet=0);
+            uint8_t dmpGetGravity(VectorFloat *v, Quaternion *q);
+            uint8_t dmpGetUnquantizedAccel(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetUnquantizedAccel(int16_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetUnquantizedAccel(VectorInt16 *v, const uint8_t* packet=0);
+            uint8_t dmpGetQuantizedAccel(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetQuantizedAccel(int16_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetQuantizedAccel(VectorInt16 *v, const uint8_t* packet=0);
+            uint8_t dmpGetExternalSensorData(int32_t *data, uint16_t size, const uint8_t* packet=0);
+            uint8_t dmpGetEIS(int32_t *data, const uint8_t* packet=0);
+            
+            uint8_t dmpGetEuler(float *data, Quaternion *q);
+            uint8_t dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity);
+
+            // Get Floating Point data from FIFO
+            uint8_t dmpGetAccelFloat(float *data, const uint8_t* packet=0);
+            uint8_t dmpGetQuaternionFloat(float *data, const uint8_t* packet=0);
+
+            uint8_t dmpProcessFIFOPacket(const unsigned char *dmpData);
+            uint8_t dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *processed=NULL);
+
+            uint8_t dmpSetFIFOProcessedCallback(void (*func) (void));
+
+            uint8_t dmpInitFIFOParam();
+            uint8_t dmpCloseFIFO();
+            uint8_t dmpSetGyroDataSource(uint8_t source);
+            uint8_t dmpDecodeQuantizedAccel();
+            uint32_t dmpGetGyroSumOfSquare();
+            uint32_t dmpGetAccelSumOfSquare();
+            void dmpOverrideQuaternion(long *q);
+            uint16_t dmpGetFIFOPacketSize();
+        #endif
+
+    private:
+        uint8_t devAddr;
+        uint8_t buffer[14];
+};
+
+#endif /* _MPU6050_H_ */
diff --git a/Arduino/MPU9150/MPU6050_6Axis_MotionApps20.h b/Arduino/MPU9150/MPU6050_6Axis_MotionApps20.h
new file mode 100644
index 00000000..0e699c47
--- /dev/null
+++ b/Arduino/MPU9150/MPU6050_6Axis_MotionApps20.h
@@ -0,0 +1,741 @@
+// I2Cdev library collection - MPU6050 I2C device class, 6-axis MotionApps 2.0 implementation
+// Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00)
+// 5/20/2013 by Jeff Rowberg 
+// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
+//
+// Changelog:
+//     ... - ongoing debug release
+
+/* ============================================
+I2Cdev device library code is placed under the MIT license
+Copyright (c) 2012 Jeff Rowberg
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+===============================================
+*/
+
+#ifndef _MPU6050_6AXIS_MOTIONAPPS20_H_
+#define _MPU6050_6AXIS_MOTIONAPPS20_H_
+
+#include "I2Cdev.h"
+#include "helper_3dmath.h"
+
+// MotionApps 2.0 DMP implementation, built using the MPU-6050EVB evaluation board
+#define MPU6050_INCLUDE_DMP_MOTIONAPPS20
+
+#include "MPU6050.h"
+
+// Tom Carpenter's conditional PROGMEM code
+// http://forum.arduino.cc/index.php?topic=129407.0
+#ifndef __arm__
+    #include 
+#else
+    // Teensy 3.0 library conditional PROGMEM code from Paul Stoffregen
+    #ifndef __PGMSPACE_H_
+        #define __PGMSPACE_H_ 1
+        #include 
+
+        #define PROGMEM
+        #define PGM_P  const char *
+        #define PSTR(str) (str)
+        #define F(x) x
+
+        typedef void prog_void;
+        typedef char prog_char;
+        typedef unsigned char prog_uchar;
+        typedef int8_t prog_int8_t;
+        typedef uint8_t prog_uint8_t;
+        typedef int16_t prog_int16_t;
+        typedef uint16_t prog_uint16_t;
+        typedef int32_t prog_int32_t;
+        typedef uint32_t prog_uint32_t;
+        
+        #define strcpy_P(dest, src) strcpy((dest), (src))
+        #define strcat_P(dest, src) strcat((dest), (src))
+        #define strcmp_P(a, b) strcmp((a), (b))
+        
+        #define pgm_read_byte(addr) (*(const unsigned char *)(addr))
+        #define pgm_read_word(addr) (*(const unsigned short *)(addr))
+        #define pgm_read_dword(addr) (*(const unsigned long *)(addr))
+        #define pgm_read_float(addr) (*(const float *)(addr))
+        
+        #define pgm_read_byte_near(addr) pgm_read_byte(addr)
+        #define pgm_read_word_near(addr) pgm_read_word(addr)
+        #define pgm_read_dword_near(addr) pgm_read_dword(addr)
+        #define pgm_read_float_near(addr) pgm_read_float(addr)
+        #define pgm_read_byte_far(addr) pgm_read_byte(addr)
+        #define pgm_read_word_far(addr) pgm_read_word(addr)
+        #define pgm_read_dword_far(addr) pgm_read_dword(addr)
+        #define pgm_read_float_far(addr) pgm_read_float(addr)
+    #endif
+#endif
+
+/* Source is from the InvenSense MotionApps v2 demo code. Original source is
+ * unavailable, unless you happen to be amazing as decompiling binary by
+ * hand (in which case, please contact me, and I'm totally serious).
+ *
+ * Also, I'd like to offer many, many thanks to Noah Zerkin for all of the
+ * DMP reverse-engineering he did to help make this bit of wizardry
+ * possible.
+ */
+
+// NOTE! Enabling DEBUG adds about 3.3kB to the flash program size.
+// Debug output is now working even on ATMega328P MCUs (e.g. Arduino Uno)
+// after moving string constants to flash memory storage using the F()
+// compiler macro (Arduino IDE 1.0+ required).
+
+//#define DEBUG
+#ifdef DEBUG
+    #define DEBUG_PRINT(x) Serial.print(x)
+    #define DEBUG_PRINTF(x, y) Serial.print(x, y)
+    #define DEBUG_PRINTLN(x) Serial.println(x)
+    #define DEBUG_PRINTLNF(x, y) Serial.println(x, y)
+#else
+    #define DEBUG_PRINT(x)
+    #define DEBUG_PRINTF(x, y)
+    #define DEBUG_PRINTLN(x)
+    #define DEBUG_PRINTLNF(x, y)
+#endif
+
+#define MPU6050_DMP_CODE_SIZE       1929    // dmpMemory[]
+#define MPU6050_DMP_CONFIG_SIZE     192     // dmpConfig[]
+#define MPU6050_DMP_UPDATES_SIZE    47      // dmpUpdates[]
+
+/* ================================================================================================ *
+ | Default MotionApps v2.0 42-byte FIFO packet structure:                                           |
+ |                                                                                                  |
+ | [QUAT W][      ][QUAT X][      ][QUAT Y][      ][QUAT Z][      ][GYRO X][      ][GYRO Y][      ] |
+ |   0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18  19  20  21  22  23  |
+ |                                                                                                  |
+ | [GYRO Z][      ][ACC X ][      ][ACC Y ][      ][ACC Z ][      ][      ]                         |
+ |  24  25  26  27  28  29  30  31  32  33  34  35  36  37  38  39  40  41                          |
+ * ================================================================================================ */
+
+// this block of memory gets written to the MPU on start-up, and it seems
+// to be volatile memory, so it has to be done each time (it only takes ~1
+// second though)
+const unsigned char dmpMemory[MPU6050_DMP_CODE_SIZE] PROGMEM = {
+    // bank 0, 256 bytes
+    0xFB, 0x00, 0x00, 0x3E, 0x00, 0x0B, 0x00, 0x36, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00,
+    0x00, 0x65, 0x00, 0x54, 0xFF, 0xEF, 0x00, 0x00, 0xFA, 0x80, 0x00, 0x0B, 0x12, 0x82, 0x00, 0x01,
+    0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x28, 0x00, 0x00, 0xFF, 0xFF, 0x45, 0x81, 0xFF, 0xFF, 0xFA, 0x72, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x03, 0xE8, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x7F, 0xFF, 0xFF, 0xFE, 0x80, 0x01,
+    0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x3E, 0x03, 0x30, 0x40, 0x00, 0x00, 0x00, 0x02, 0xCA, 0xE3, 0x09, 0x3E, 0x80, 0x00, 0x00,
+    0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00,
+    0x41, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x2A, 0x00, 0x00, 0x16, 0x55, 0x00, 0x00, 0x21, 0x82,
+    0xFD, 0x87, 0x26, 0x50, 0xFD, 0x80, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x05, 0x80, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
+    0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x6F, 0x00, 0x02, 0x65, 0x32, 0x00, 0x00, 0x5E, 0xC0,
+    0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0xFB, 0x8C, 0x6F, 0x5D, 0xFD, 0x5D, 0x08, 0xD9, 0x00, 0x7C, 0x73, 0x3B, 0x00, 0x6C, 0x12, 0xCC,
+    0x32, 0x00, 0x13, 0x9D, 0x32, 0x00, 0xD0, 0xD6, 0x32, 0x00, 0x08, 0x00, 0x40, 0x00, 0x01, 0xF4,
+    0xFF, 0xE6, 0x80, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0xD6, 0x00, 0x00, 0x27, 0x10,
+
+    // bank 1, 256 bytes
+    0xFB, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0xFA, 0x36, 0xFF, 0xBC, 0x30, 0x8E, 0x00, 0x05, 0xFB, 0xF0, 0xFF, 0xD9, 0x5B, 0xC8,
+    0xFF, 0xD0, 0x9A, 0xBE, 0x00, 0x00, 0x10, 0xA9, 0xFF, 0xF4, 0x1E, 0xB2, 0x00, 0xCE, 0xBB, 0xF7,
+    0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x0C,
+    0xFF, 0xC2, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0xCF, 0x80, 0x00, 0x40, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x14,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x03, 0x3F, 0x68, 0xB6, 0x79, 0x35, 0x28, 0xBC, 0xC6, 0x7E, 0xD1, 0x6C,
+    0x80, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB2, 0x6A, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x30,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x25, 0x4D, 0x00, 0x2F, 0x70, 0x6D, 0x00, 0x00, 0x05, 0xAE, 0x00, 0x0C, 0x02, 0xD0,
+
+    // bank 2, 256 bytes
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x54, 0xFF, 0xEF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x01, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x01, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0xFF, 0xEF, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+    0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+    // bank 3, 256 bytes
+    0xD8, 0xDC, 0xBA, 0xA2, 0xF1, 0xDE, 0xB2, 0xB8, 0xB4, 0xA8, 0x81, 0x91, 0xF7, 0x4A, 0x90, 0x7F,
+    0x91, 0x6A, 0xF3, 0xF9, 0xDB, 0xA8, 0xF9, 0xB0, 0xBA, 0xA0, 0x80, 0xF2, 0xCE, 0x81, 0xF3, 0xC2,
+    0xF1, 0xC1, 0xF2, 0xC3, 0xF3, 0xCC, 0xA2, 0xB2, 0x80, 0xF1, 0xC6, 0xD8, 0x80, 0xBA, 0xA7, 0xDF,
+    0xDF, 0xDF, 0xF2, 0xA7, 0xC3, 0xCB, 0xC5, 0xB6, 0xF0, 0x87, 0xA2, 0x94, 0x24, 0x48, 0x70, 0x3C,
+    0x95, 0x40, 0x68, 0x34, 0x58, 0x9B, 0x78, 0xA2, 0xF1, 0x83, 0x92, 0x2D, 0x55, 0x7D, 0xD8, 0xB1,
+    0xB4, 0xB8, 0xA1, 0xD0, 0x91, 0x80, 0xF2, 0x70, 0xF3, 0x70, 0xF2, 0x7C, 0x80, 0xA8, 0xF1, 0x01,
+    0xB0, 0x98, 0x87, 0xD9, 0x43, 0xD8, 0x86, 0xC9, 0x88, 0xBA, 0xA1, 0xF2, 0x0E, 0xB8, 0x97, 0x80,
+    0xF1, 0xA9, 0xDF, 0xDF, 0xDF, 0xAA, 0xDF, 0xDF, 0xDF, 0xF2, 0xAA, 0xC5, 0xCD, 0xC7, 0xA9, 0x0C,
+    0xC9, 0x2C, 0x97, 0x97, 0x97, 0x97, 0xF1, 0xA9, 0x89, 0x26, 0x46, 0x66, 0xB0, 0xB4, 0xBA, 0x80,
+    0xAC, 0xDE, 0xF2, 0xCA, 0xF1, 0xB2, 0x8C, 0x02, 0xA9, 0xB6, 0x98, 0x00, 0x89, 0x0E, 0x16, 0x1E,
+    0xB8, 0xA9, 0xB4, 0x99, 0x2C, 0x54, 0x7C, 0xB0, 0x8A, 0xA8, 0x96, 0x36, 0x56, 0x76, 0xF1, 0xB9,
+    0xAF, 0xB4, 0xB0, 0x83, 0xC0, 0xB8, 0xA8, 0x97, 0x11, 0xB1, 0x8F, 0x98, 0xB9, 0xAF, 0xF0, 0x24,
+    0x08, 0x44, 0x10, 0x64, 0x18, 0xF1, 0xA3, 0x29, 0x55, 0x7D, 0xAF, 0x83, 0xB5, 0x93, 0xAF, 0xF0,
+    0x00, 0x28, 0x50, 0xF1, 0xA3, 0x86, 0x9F, 0x61, 0xA6, 0xDA, 0xDE, 0xDF, 0xD9, 0xFA, 0xA3, 0x86,
+    0x96, 0xDB, 0x31, 0xA6, 0xD9, 0xF8, 0xDF, 0xBA, 0xA6, 0x8F, 0xC2, 0xC5, 0xC7, 0xB2, 0x8C, 0xC1,
+    0xB8, 0xA2, 0xDF, 0xDF, 0xDF, 0xA3, 0xDF, 0xDF, 0xDF, 0xD8, 0xD8, 0xF1, 0xB8, 0xA8, 0xB2, 0x86,
+
+    // bank 4, 256 bytes
+    0xB4, 0x98, 0x0D, 0x35, 0x5D, 0xB8, 0xAA, 0x98, 0xB0, 0x87, 0x2D, 0x35, 0x3D, 0xB2, 0xB6, 0xBA,
+    0xAF, 0x8C, 0x96, 0x19, 0x8F, 0x9F, 0xA7, 0x0E, 0x16, 0x1E, 0xB4, 0x9A, 0xB8, 0xAA, 0x87, 0x2C,
+    0x54, 0x7C, 0xB9, 0xA3, 0xDE, 0xDF, 0xDF, 0xA3, 0xB1, 0x80, 0xF2, 0xC4, 0xCD, 0xC9, 0xF1, 0xB8,
+    0xA9, 0xB4, 0x99, 0x83, 0x0D, 0x35, 0x5D, 0x89, 0xB9, 0xA3, 0x2D, 0x55, 0x7D, 0xB5, 0x93, 0xA3,
+    0x0E, 0x16, 0x1E, 0xA9, 0x2C, 0x54, 0x7C, 0xB8, 0xB4, 0xB0, 0xF1, 0x97, 0x83, 0xA8, 0x11, 0x84,
+    0xA5, 0x09, 0x98, 0xA3, 0x83, 0xF0, 0xDA, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0xD8, 0xF1, 0xA5,
+    0x29, 0x55, 0x7D, 0xA5, 0x85, 0x95, 0x02, 0x1A, 0x2E, 0x3A, 0x56, 0x5A, 0x40, 0x48, 0xF9, 0xF3,
+    0xA3, 0xD9, 0xF8, 0xF0, 0x98, 0x83, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0x97, 0x82, 0xA8, 0xF1,
+    0x11, 0xF0, 0x98, 0xA2, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0xDA, 0xF3, 0xDE, 0xD8, 0x83, 0xA5,
+    0x94, 0x01, 0xD9, 0xA3, 0x02, 0xF1, 0xA2, 0xC3, 0xC5, 0xC7, 0xD8, 0xF1, 0x84, 0x92, 0xA2, 0x4D,
+    0xDA, 0x2A, 0xD8, 0x48, 0x69, 0xD9, 0x2A, 0xD8, 0x68, 0x55, 0xDA, 0x32, 0xD8, 0x50, 0x71, 0xD9,
+    0x32, 0xD8, 0x70, 0x5D, 0xDA, 0x3A, 0xD8, 0x58, 0x79, 0xD9, 0x3A, 0xD8, 0x78, 0x93, 0xA3, 0x4D,
+    0xDA, 0x2A, 0xD8, 0x48, 0x69, 0xD9, 0x2A, 0xD8, 0x68, 0x55, 0xDA, 0x32, 0xD8, 0x50, 0x71, 0xD9,
+    0x32, 0xD8, 0x70, 0x5D, 0xDA, 0x3A, 0xD8, 0x58, 0x79, 0xD9, 0x3A, 0xD8, 0x78, 0xA8, 0x8A, 0x9A,
+    0xF0, 0x28, 0x50, 0x78, 0x9E, 0xF3, 0x88, 0x18, 0xF1, 0x9F, 0x1D, 0x98, 0xA8, 0xD9, 0x08, 0xD8,
+    0xC8, 0x9F, 0x12, 0x9E, 0xF3, 0x15, 0xA8, 0xDA, 0x12, 0x10, 0xD8, 0xF1, 0xAF, 0xC8, 0x97, 0x87,
+
+    // bank 5, 256 bytes
+    0x34, 0xB5, 0xB9, 0x94, 0xA4, 0x21, 0xF3, 0xD9, 0x22, 0xD8, 0xF2, 0x2D, 0xF3, 0xD9, 0x2A, 0xD8,
+    0xF2, 0x35, 0xF3, 0xD9, 0x32, 0xD8, 0x81, 0xA4, 0x60, 0x60, 0x61, 0xD9, 0x61, 0xD8, 0x6C, 0x68,
+    0x69, 0xD9, 0x69, 0xD8, 0x74, 0x70, 0x71, 0xD9, 0x71, 0xD8, 0xB1, 0xA3, 0x84, 0x19, 0x3D, 0x5D,
+    0xA3, 0x83, 0x1A, 0x3E, 0x5E, 0x93, 0x10, 0x30, 0x81, 0x10, 0x11, 0xB8, 0xB0, 0xAF, 0x8F, 0x94,
+    0xF2, 0xDA, 0x3E, 0xD8, 0xB4, 0x9A, 0xA8, 0x87, 0x29, 0xDA, 0xF8, 0xD8, 0x87, 0x9A, 0x35, 0xDA,
+    0xF8, 0xD8, 0x87, 0x9A, 0x3D, 0xDA, 0xF8, 0xD8, 0xB1, 0xB9, 0xA4, 0x98, 0x85, 0x02, 0x2E, 0x56,
+    0xA5, 0x81, 0x00, 0x0C, 0x14, 0xA3, 0x97, 0xB0, 0x8A, 0xF1, 0x2D, 0xD9, 0x28, 0xD8, 0x4D, 0xD9,
+    0x48, 0xD8, 0x6D, 0xD9, 0x68, 0xD8, 0xB1, 0x84, 0x0D, 0xDA, 0x0E, 0xD8, 0xA3, 0x29, 0x83, 0xDA,
+    0x2C, 0x0E, 0xD8, 0xA3, 0x84, 0x49, 0x83, 0xDA, 0x2C, 0x4C, 0x0E, 0xD8, 0xB8, 0xB0, 0xA8, 0x8A,
+    0x9A, 0xF5, 0x20, 0xAA, 0xDA, 0xDF, 0xD8, 0xA8, 0x40, 0xAA, 0xD0, 0xDA, 0xDE, 0xD8, 0xA8, 0x60,
+    0xAA, 0xDA, 0xD0, 0xDF, 0xD8, 0xF1, 0x97, 0x86, 0xA8, 0x31, 0x9B, 0x06, 0x99, 0x07, 0xAB, 0x97,
+    0x28, 0x88, 0x9B, 0xF0, 0x0C, 0x20, 0x14, 0x40, 0xB8, 0xB0, 0xB4, 0xA8, 0x8C, 0x9C, 0xF0, 0x04,
+    0x28, 0x51, 0x79, 0x1D, 0x30, 0x14, 0x38, 0xB2, 0x82, 0xAB, 0xD0, 0x98, 0x2C, 0x50, 0x50, 0x78,
+    0x78, 0x9B, 0xF1, 0x1A, 0xB0, 0xF0, 0x8A, 0x9C, 0xA8, 0x29, 0x51, 0x79, 0x8B, 0x29, 0x51, 0x79,
+    0x8A, 0x24, 0x70, 0x59, 0x8B, 0x20, 0x58, 0x71, 0x8A, 0x44, 0x69, 0x38, 0x8B, 0x39, 0x40, 0x68,
+    0x8A, 0x64, 0x48, 0x31, 0x8B, 0x30, 0x49, 0x60, 0xA5, 0x88, 0x20, 0x09, 0x71, 0x58, 0x44, 0x68,
+
+    // bank 6, 256 bytes
+    0x11, 0x39, 0x64, 0x49, 0x30, 0x19, 0xF1, 0xAC, 0x00, 0x2C, 0x54, 0x7C, 0xF0, 0x8C, 0xA8, 0x04,
+    0x28, 0x50, 0x78, 0xF1, 0x88, 0x97, 0x26, 0xA8, 0x59, 0x98, 0xAC, 0x8C, 0x02, 0x26, 0x46, 0x66,
+    0xF0, 0x89, 0x9C, 0xA8, 0x29, 0x51, 0x79, 0x24, 0x70, 0x59, 0x44, 0x69, 0x38, 0x64, 0x48, 0x31,
+    0xA9, 0x88, 0x09, 0x20, 0x59, 0x70, 0xAB, 0x11, 0x38, 0x40, 0x69, 0xA8, 0x19, 0x31, 0x48, 0x60,
+    0x8C, 0xA8, 0x3C, 0x41, 0x5C, 0x20, 0x7C, 0x00, 0xF1, 0x87, 0x98, 0x19, 0x86, 0xA8, 0x6E, 0x76,
+    0x7E, 0xA9, 0x99, 0x88, 0x2D, 0x55, 0x7D, 0x9E, 0xB9, 0xA3, 0x8A, 0x22, 0x8A, 0x6E, 0x8A, 0x56,
+    0x8A, 0x5E, 0x9F, 0xB1, 0x83, 0x06, 0x26, 0x46, 0x66, 0x0E, 0x2E, 0x4E, 0x6E, 0x9D, 0xB8, 0xAD,
+    0x00, 0x2C, 0x54, 0x7C, 0xF2, 0xB1, 0x8C, 0xB4, 0x99, 0xB9, 0xA3, 0x2D, 0x55, 0x7D, 0x81, 0x91,
+    0xAC, 0x38, 0xAD, 0x3A, 0xB5, 0x83, 0x91, 0xAC, 0x2D, 0xD9, 0x28, 0xD8, 0x4D, 0xD9, 0x48, 0xD8,
+    0x6D, 0xD9, 0x68, 0xD8, 0x8C, 0x9D, 0xAE, 0x29, 0xD9, 0x04, 0xAE, 0xD8, 0x51, 0xD9, 0x04, 0xAE,
+    0xD8, 0x79, 0xD9, 0x04, 0xD8, 0x81, 0xF3, 0x9D, 0xAD, 0x00, 0x8D, 0xAE, 0x19, 0x81, 0xAD, 0xD9,
+    0x01, 0xD8, 0xF2, 0xAE, 0xDA, 0x26, 0xD8, 0x8E, 0x91, 0x29, 0x83, 0xA7, 0xD9, 0xAD, 0xAD, 0xAD,
+    0xAD, 0xF3, 0x2A, 0xD8, 0xD8, 0xF1, 0xB0, 0xAC, 0x89, 0x91, 0x3E, 0x5E, 0x76, 0xF3, 0xAC, 0x2E,
+    0x2E, 0xF1, 0xB1, 0x8C, 0x5A, 0x9C, 0xAC, 0x2C, 0x28, 0x28, 0x28, 0x9C, 0xAC, 0x30, 0x18, 0xA8,
+    0x98, 0x81, 0x28, 0x34, 0x3C, 0x97, 0x24, 0xA7, 0x28, 0x34, 0x3C, 0x9C, 0x24, 0xF2, 0xB0, 0x89,
+    0xAC, 0x91, 0x2C, 0x4C, 0x6C, 0x8A, 0x9B, 0x2D, 0xD9, 0xD8, 0xD8, 0x51, 0xD9, 0xD8, 0xD8, 0x79,
+
+    // bank 7, 138 bytes (remainder)
+    0xD9, 0xD8, 0xD8, 0xF1, 0x9E, 0x88, 0xA3, 0x31, 0xDA, 0xD8, 0xD8, 0x91, 0x2D, 0xD9, 0x28, 0xD8,
+    0x4D, 0xD9, 0x48, 0xD8, 0x6D, 0xD9, 0x68, 0xD8, 0xB1, 0x83, 0x93, 0x35, 0x3D, 0x80, 0x25, 0xDA,
+    0xD8, 0xD8, 0x85, 0x69, 0xDA, 0xD8, 0xD8, 0xB4, 0x93, 0x81, 0xA3, 0x28, 0x34, 0x3C, 0xF3, 0xAB,
+    0x8B, 0xF8, 0xA3, 0x91, 0xB6, 0x09, 0xB4, 0xD9, 0xAB, 0xDE, 0xFA, 0xB0, 0x87, 0x9C, 0xB9, 0xA3,
+    0xDD, 0xF1, 0xA3, 0xA3, 0xA3, 0xA3, 0x95, 0xF1, 0xA3, 0xA3, 0xA3, 0x9D, 0xF1, 0xA3, 0xA3, 0xA3,
+    0xA3, 0xF2, 0xA3, 0xB4, 0x90, 0x80, 0xF2, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3,
+    0xA3, 0xB2, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xB0, 0x87, 0xB5, 0x99, 0xF1, 0xA3, 0xA3, 0xA3,
+    0x98, 0xF1, 0xA3, 0xA3, 0xA3, 0xA3, 0x97, 0xA3, 0xA3, 0xA3, 0xA3, 0xF3, 0x9B, 0xA3, 0xA3, 0xDC,
+    0xB9, 0xA7, 0xF1, 0x26, 0x26, 0x26, 0xD8, 0xD8, 0xFF
+};
+
+// thanks to Noah Zerkin for piecing this stuff together!
+const unsigned char dmpConfig[MPU6050_DMP_CONFIG_SIZE] PROGMEM = {
+//  BANK    OFFSET  LENGTH  [DATA]
+    0x03,   0x7B,   0x03,   0x4C, 0xCD, 0x6C,         // FCFG_1 inv_set_gyro_calibration
+    0x03,   0xAB,   0x03,   0x36, 0x56, 0x76,         // FCFG_3 inv_set_gyro_calibration
+    0x00,   0x68,   0x04,   0x02, 0xCB, 0x47, 0xA2,   // D_0_104 inv_set_gyro_calibration
+    0x02,   0x18,   0x04,   0x00, 0x05, 0x8B, 0xC1,   // D_0_24 inv_set_gyro_calibration
+    0x01,   0x0C,   0x04,   0x00, 0x00, 0x00, 0x00,   // D_1_152 inv_set_accel_calibration
+    0x03,   0x7F,   0x06,   0x0C, 0xC9, 0x2C, 0x97, 0x97, 0x97, // FCFG_2 inv_set_accel_calibration
+    0x03,   0x89,   0x03,   0x26, 0x46, 0x66,         // FCFG_7 inv_set_accel_calibration
+    0x00,   0x6C,   0x02,   0x20, 0x00,               // D_0_108 inv_set_accel_calibration
+    0x02,   0x40,   0x04,   0x00, 0x00, 0x00, 0x00,   // CPASS_MTX_00 inv_set_compass_calibration
+    0x02,   0x44,   0x04,   0x00, 0x00, 0x00, 0x00,   // CPASS_MTX_01
+    0x02,   0x48,   0x04,   0x00, 0x00, 0x00, 0x00,   // CPASS_MTX_02
+    0x02,   0x4C,   0x04,   0x00, 0x00, 0x00, 0x00,   // CPASS_MTX_10
+    0x02,   0x50,   0x04,   0x00, 0x00, 0x00, 0x00,   // CPASS_MTX_11
+    0x02,   0x54,   0x04,   0x00, 0x00, 0x00, 0x00,   // CPASS_MTX_12
+    0x02,   0x58,   0x04,   0x00, 0x00, 0x00, 0x00,   // CPASS_MTX_20
+    0x02,   0x5C,   0x04,   0x00, 0x00, 0x00, 0x00,   // CPASS_MTX_21
+    0x02,   0xBC,   0x04,   0x00, 0x00, 0x00, 0x00,   // CPASS_MTX_22
+    0x01,   0xEC,   0x04,   0x00, 0x00, 0x40, 0x00,   // D_1_236 inv_apply_endian_accel
+    0x03,   0x7F,   0x06,   0x0C, 0xC9, 0x2C, 0x97, 0x97, 0x97, // FCFG_2 inv_set_mpu_sensors
+    0x04,   0x02,   0x03,   0x0D, 0x35, 0x5D,         // CFG_MOTION_BIAS inv_turn_on_bias_from_no_motion
+    0x04,   0x09,   0x04,   0x87, 0x2D, 0x35, 0x3D,   // FCFG_5 inv_set_bias_update
+    0x00,   0xA3,   0x01,   0x00,                     // D_0_163 inv_set_dead_zone
+                 // SPECIAL 0x01 = enable interrupts
+    0x00,   0x00,   0x00,   0x01, // SET INT_ENABLE at i=22, SPECIAL INSTRUCTION
+    0x07,   0x86,   0x01,   0xFE,                     // CFG_6 inv_set_fifo_interupt
+    0x07,   0x41,   0x05,   0xF1, 0x20, 0x28, 0x30, 0x38, // CFG_8 inv_send_quaternion
+    0x07,   0x7E,   0x01,   0x30,                     // CFG_16 inv_set_footer
+    0x07,   0x46,   0x01,   0x9A,                     // CFG_GYRO_SOURCE inv_send_gyro
+    0x07,   0x47,   0x04,   0xF1, 0x28, 0x30, 0x38,   // CFG_9 inv_send_gyro -> inv_construct3_fifo
+    0x07,   0x6C,   0x04,   0xF1, 0x28, 0x30, 0x38,   // CFG_12 inv_send_accel -> inv_construct3_fifo
+    0x02,   0x16,   0x02,   0x00, 0x01                // D_0_22 inv_set_fifo_rate
+
+    // This very last 0x01 WAS a 0x09, which drops the FIFO rate down to 20 Hz. 0x07 is 25 Hz,
+    // 0x01 is 100Hz. Going faster than 100Hz (0x00=200Hz) tends to result in very noisy data.
+    // DMP output frequency is calculated easily using this equation: (200Hz / (1 + value))
+
+    // It is important to make sure the host processor can keep up with reading and processing
+    // the FIFO output at the desired rate. Handling FIFO overflow cleanly is also a good idea.
+};
+
+const unsigned char dmpUpdates[MPU6050_DMP_UPDATES_SIZE] PROGMEM = {
+    0x01,   0xB2,   0x02,   0xFF, 0xFF,
+    0x01,   0x90,   0x04,   0x09, 0x23, 0xA1, 0x35,
+    0x01,   0x6A,   0x02,   0x06, 0x00,
+    0x01,   0x60,   0x08,   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00,   0x60,   0x04,   0x40, 0x00, 0x00, 0x00,
+    0x01,   0x62,   0x02,   0x00, 0x00,
+    0x00,   0x60,   0x04,   0x00, 0x40, 0x00, 0x00
+};
+
+uint8_t MPU6050::dmpInitialize() {
+    // reset device
+    DEBUG_PRINTLN(F("\n\nResetting MPU6050..."));
+    reset();
+    delay(30); // wait after reset
+
+    // enable sleep mode and wake cycle
+    /*Serial.println(F("Enabling sleep mode..."));
+    setSleepEnabled(true);
+    Serial.println(F("Enabling wake cycle..."));
+    setWakeCycleEnabled(true);*/
+
+    // disable sleep mode
+    DEBUG_PRINTLN(F("Disabling sleep mode..."));
+    setSleepEnabled(false);
+
+    // get MPU hardware revision
+    DEBUG_PRINTLN(F("Selecting user bank 16..."));
+    setMemoryBank(0x10, true, true);
+    DEBUG_PRINTLN(F("Selecting memory byte 6..."));
+    setMemoryStartAddress(0x06);
+    DEBUG_PRINTLN(F("Checking hardware revision..."));
+    uint8_t hwRevision = readMemoryByte();
+    DEBUG_PRINT(F("Revision @ user[16][6] = "));
+    DEBUG_PRINTLNF(hwRevision, HEX);
+    DEBUG_PRINTLN(F("Resetting memory bank selection to 0..."));
+    setMemoryBank(0, false, false);
+
+    // check OTP bank valid
+    DEBUG_PRINTLN(F("Reading OTP bank valid flag..."));
+    uint8_t otpValid = getOTPBankValid();
+    DEBUG_PRINT(F("OTP bank is "));
+    DEBUG_PRINTLN(otpValid ? F("valid!") : F("invalid!"));
+
+    // get X/Y/Z gyro offsets
+    DEBUG_PRINTLN(F("Reading gyro offset TC values..."));
+    int8_t xgOffsetTC = getXGyroOffsetTC();
+    int8_t ygOffsetTC = getYGyroOffsetTC();
+    int8_t zgOffsetTC = getZGyroOffsetTC();
+    DEBUG_PRINT(F("X gyro offset = "));
+    DEBUG_PRINTLN(xgOffset);
+    DEBUG_PRINT(F("Y gyro offset = "));
+    DEBUG_PRINTLN(ygOffset);
+    DEBUG_PRINT(F("Z gyro offset = "));
+    DEBUG_PRINTLN(zgOffset);
+
+    // setup weird slave stuff (?)
+    DEBUG_PRINTLN(F("Setting slave 0 address to 0x7F..."));
+    setSlaveAddress(0, 0x7F);
+    DEBUG_PRINTLN(F("Disabling I2C Master mode..."));
+    setI2CMasterModeEnabled(false);
+    DEBUG_PRINTLN(F("Setting slave 0 address to 0x68 (self)..."));
+    setSlaveAddress(0, 0x68);
+    DEBUG_PRINTLN(F("Resetting I2C Master control..."));
+    resetI2CMaster();
+    delay(20);
+
+    // load DMP code into memory banks
+    DEBUG_PRINT(F("Writing DMP code to MPU memory banks ("));
+    DEBUG_PRINT(MPU6050_DMP_CODE_SIZE);
+    DEBUG_PRINTLN(F(" bytes)"));
+    if (writeProgMemoryBlock(dmpMemory, MPU6050_DMP_CODE_SIZE)) {
+        DEBUG_PRINTLN(F("Success! DMP code written and verified."));
+
+        // write DMP configuration
+        DEBUG_PRINT(F("Writing DMP configuration to MPU memory banks ("));
+        DEBUG_PRINT(MPU6050_DMP_CONFIG_SIZE);
+        DEBUG_PRINTLN(F(" bytes in config def)"));
+        if (writeProgDMPConfigurationSet(dmpConfig, MPU6050_DMP_CONFIG_SIZE)) {
+            DEBUG_PRINTLN(F("Success! DMP configuration written and verified."));
+
+            DEBUG_PRINTLN(F("Setting clock source to Z Gyro..."));
+            setClockSource(MPU6050_CLOCK_PLL_ZGYRO);
+
+            DEBUG_PRINTLN(F("Setting DMP and FIFO_OFLOW interrupts enabled..."));
+            setIntEnabled(0x12);
+
+            DEBUG_PRINTLN(F("Setting sample rate to 200Hz..."));
+            setRate(4); // 1khz / (1 + 4) = 200 Hz
+
+            DEBUG_PRINTLN(F("Setting external frame sync to TEMP_OUT_L[0]..."));
+            setExternalFrameSync(MPU6050_EXT_SYNC_TEMP_OUT_L);
+
+            DEBUG_PRINTLN(F("Setting DLPF bandwidth to 42Hz..."));
+            setDLPFMode(MPU6050_DLPF_BW_42);
+
+            DEBUG_PRINTLN(F("Setting gyro sensitivity to +/- 2000 deg/sec..."));
+            setFullScaleGyroRange(MPU6050_GYRO_FS_2000);
+
+            DEBUG_PRINTLN(F("Setting DMP configuration bytes (function unknown)..."));
+            setDMPConfig1(0x03);
+            setDMPConfig2(0x00);
+
+            DEBUG_PRINTLN(F("Clearing OTP Bank flag..."));
+            setOTPBankValid(false);
+
+            DEBUG_PRINTLN(F("Setting X/Y/Z gyro offset TCs to previous values..."));
+            setXGyroOffsetTC(xgOffsetTC);
+            setYGyroOffsetTC(ygOffsetTC);
+            setZGyroOffsetTC(zgOffsetTC);
+
+            //DEBUG_PRINTLN(F("Setting X/Y/Z gyro user offsets to zero..."));
+            //setXGyroOffset(0);
+            //setYGyroOffset(0);
+            //setZGyroOffset(0);
+
+            DEBUG_PRINTLN(F("Writing final memory update 1/7 (function unknown)..."));
+            uint8_t dmpUpdate[16], j;
+            uint16_t pos = 0;
+            for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
+            writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
+
+            DEBUG_PRINTLN(F("Writing final memory update 2/7 (function unknown)..."));
+            for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
+            writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
+
+            DEBUG_PRINTLN(F("Resetting FIFO..."));
+            resetFIFO();
+
+            DEBUG_PRINTLN(F("Reading FIFO count..."));
+            uint16_t fifoCount = getFIFOCount();
+            uint8_t fifoBuffer[128];
+
+            DEBUG_PRINT(F("Current FIFO count="));
+            DEBUG_PRINTLN(fifoCount);
+            getFIFOBytes(fifoBuffer, fifoCount);
+
+            DEBUG_PRINTLN(F("Setting motion detection threshold to 2..."));
+            setMotionDetectionThreshold(2);
+
+            DEBUG_PRINTLN(F("Setting zero-motion detection threshold to 156..."));
+            setZeroMotionDetectionThreshold(156);
+
+            DEBUG_PRINTLN(F("Setting motion detection duration to 80..."));
+            setMotionDetectionDuration(80);
+
+            DEBUG_PRINTLN(F("Setting zero-motion detection duration to 0..."));
+            setZeroMotionDetectionDuration(0);
+
+            DEBUG_PRINTLN(F("Resetting FIFO..."));
+            resetFIFO();
+
+            DEBUG_PRINTLN(F("Enabling FIFO..."));
+            setFIFOEnabled(true);
+
+            DEBUG_PRINTLN(F("Enabling DMP..."));
+            setDMPEnabled(true);
+
+            DEBUG_PRINTLN(F("Resetting DMP..."));
+            resetDMP();
+
+            DEBUG_PRINTLN(F("Writing final memory update 3/7 (function unknown)..."));
+            for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
+            writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
+
+            DEBUG_PRINTLN(F("Writing final memory update 4/7 (function unknown)..."));
+            for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
+            writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
+
+            DEBUG_PRINTLN(F("Writing final memory update 5/7 (function unknown)..."));
+            for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
+            writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
+
+            DEBUG_PRINTLN(F("Waiting for FIFO count > 2..."));
+            while ((fifoCount = getFIFOCount()) < 3);
+
+            DEBUG_PRINT(F("Current FIFO count="));
+            DEBUG_PRINTLN(fifoCount);
+            DEBUG_PRINTLN(F("Reading FIFO data..."));
+            getFIFOBytes(fifoBuffer, fifoCount);
+
+            DEBUG_PRINTLN(F("Reading interrupt status..."));
+            uint8_t mpuIntStatus = getIntStatus();
+
+            DEBUG_PRINT(F("Current interrupt status="));
+            DEBUG_PRINTLNF(mpuIntStatus, HEX);
+
+            DEBUG_PRINTLN(F("Reading final memory update 6/7 (function unknown)..."));
+            for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
+            readMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
+
+            DEBUG_PRINTLN(F("Waiting for FIFO count > 2..."));
+            while ((fifoCount = getFIFOCount()) < 3);
+
+            DEBUG_PRINT(F("Current FIFO count="));
+            DEBUG_PRINTLN(fifoCount);
+
+            DEBUG_PRINTLN(F("Reading FIFO data..."));
+            getFIFOBytes(fifoBuffer, fifoCount);
+
+            DEBUG_PRINTLN(F("Reading interrupt status..."));
+            mpuIntStatus = getIntStatus();
+
+            DEBUG_PRINT(F("Current interrupt status="));
+            DEBUG_PRINTLNF(mpuIntStatus, HEX);
+
+            DEBUG_PRINTLN(F("Writing final memory update 7/7 (function unknown)..."));
+            for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
+            writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
+
+            DEBUG_PRINTLN(F("DMP is good to go! Finally."));
+
+            DEBUG_PRINTLN(F("Disabling DMP (you turn it on later)..."));
+            setDMPEnabled(false);
+
+            DEBUG_PRINTLN(F("Setting up internal 42-byte (default) DMP packet buffer..."));
+            dmpPacketSize = 42;
+            /*if ((dmpPacketBuffer = (uint8_t *)malloc(42)) == 0) {
+                return 3; // TODO: proper error code for no memory
+            }*/
+
+            DEBUG_PRINTLN(F("Resetting FIFO and clearing INT status one last time..."));
+            resetFIFO();
+            getIntStatus();
+        } else {
+            DEBUG_PRINTLN(F("ERROR! DMP configuration verification failed."));
+            return 2; // configuration block loading failed
+        }
+    } else {
+        DEBUG_PRINTLN(F("ERROR! DMP code verification failed."));
+        return 1; // main binary block loading failed
+    }
+    return 0; // success
+}
+
+bool MPU6050::dmpPacketAvailable() {
+    return getFIFOCount() >= dmpGetFIFOPacketSize();
+}
+
+// uint8_t MPU6050::dmpSetFIFORate(uint8_t fifoRate);
+// uint8_t MPU6050::dmpGetFIFORate();
+// uint8_t MPU6050::dmpGetSampleStepSizeMS();
+// uint8_t MPU6050::dmpGetSampleFrequency();
+// int32_t MPU6050::dmpDecodeTemperature(int8_t tempReg);
+
+//uint8_t MPU6050::dmpRegisterFIFORateProcess(inv_obj_func func, int16_t priority);
+//uint8_t MPU6050::dmpUnregisterFIFORateProcess(inv_obj_func func);
+//uint8_t MPU6050::dmpRunFIFORateProcesses();
+
+// uint8_t MPU6050::dmpSendQuaternion(uint_fast16_t accuracy);
+// uint8_t MPU6050::dmpSendGyro(uint_fast16_t elements, uint_fast16_t accuracy);
+// uint8_t MPU6050::dmpSendAccel(uint_fast16_t elements, uint_fast16_t accuracy);
+// uint8_t MPU6050::dmpSendLinearAccel(uint_fast16_t elements, uint_fast16_t accuracy);
+// uint8_t MPU6050::dmpSendLinearAccelInWorld(uint_fast16_t elements, uint_fast16_t accuracy);
+// uint8_t MPU6050::dmpSendControlData(uint_fast16_t elements, uint_fast16_t accuracy);
+// uint8_t MPU6050::dmpSendSensorData(uint_fast16_t elements, uint_fast16_t accuracy);
+// uint8_t MPU6050::dmpSendExternalSensorData(uint_fast16_t elements, uint_fast16_t accuracy);
+// uint8_t MPU6050::dmpSendGravity(uint_fast16_t elements, uint_fast16_t accuracy);
+// uint8_t MPU6050::dmpSendPacketNumber(uint_fast16_t accuracy);
+// uint8_t MPU6050::dmpSendQuantizedAccel(uint_fast16_t elements, uint_fast16_t accuracy);
+// uint8_t MPU6050::dmpSendEIS(uint_fast16_t elements, uint_fast16_t accuracy);
+
+uint8_t MPU6050::dmpGetAccel(int32_t *data, const uint8_t* packet) {
+    // TODO: accommodate different arrangements of sent data (ONLY default supported now)
+    if (packet == 0) packet = dmpPacketBuffer;
+    data[0] = ((packet[28] << 24) + (packet[29] << 16) + (packet[30] << 8) + packet[31]);
+    data[1] = ((packet[32] << 24) + (packet[33] << 16) + (packet[34] << 8) + packet[35]);
+    data[2] = ((packet[36] << 24) + (packet[37] << 16) + (packet[38] << 8) + packet[39]);
+    return 0;
+}
+uint8_t MPU6050::dmpGetAccel(int16_t *data, const uint8_t* packet) {
+    // TODO: accommodate different arrangements of sent data (ONLY default supported now)
+    if (packet == 0) packet = dmpPacketBuffer;
+    data[0] = (packet[28] << 8) + packet[29];
+    data[1] = (packet[32] << 8) + packet[33];
+    data[2] = (packet[36] << 8) + packet[37];
+    return 0;
+}
+uint8_t MPU6050::dmpGetAccel(VectorInt16 *v, const uint8_t* packet) {
+    // TODO: accommodate different arrangements of sent data (ONLY default supported now)
+    if (packet == 0) packet = dmpPacketBuffer;
+    v -> x = (packet[28] << 8) + packet[29];
+    v -> y = (packet[32] << 8) + packet[33];
+    v -> z = (packet[36] << 8) + packet[37];
+    return 0;
+}
+uint8_t MPU6050::dmpGetQuaternion(int32_t *data, const uint8_t* packet) {
+    // TODO: accommodate different arrangements of sent data (ONLY default supported now)
+    if (packet == 0) packet = dmpPacketBuffer;
+    data[0] = ((packet[0] << 24) + (packet[1] << 16) + (packet[2] << 8) + packet[3]);
+    data[1] = ((packet[4] << 24) + (packet[5] << 16) + (packet[6] << 8) + packet[7]);
+    data[2] = ((packet[8] << 24) + (packet[9] << 16) + (packet[10] << 8) + packet[11]);
+    data[3] = ((packet[12] << 24) + (packet[13] << 16) + (packet[14] << 8) + packet[15]);
+    return 0;
+}
+uint8_t MPU6050::dmpGetQuaternion(int16_t *data, const uint8_t* packet) {
+    // TODO: accommodate different arrangements of sent data (ONLY default supported now)
+    if (packet == 0) packet = dmpPacketBuffer;
+    data[0] = ((packet[0] << 8) + packet[1]);
+    data[1] = ((packet[4] << 8) + packet[5]);
+    data[2] = ((packet[8] << 8) + packet[9]);
+    data[3] = ((packet[12] << 8) + packet[13]);
+    return 0;
+}
+uint8_t MPU6050::dmpGetQuaternion(Quaternion *q, const uint8_t* packet) {
+    // TODO: accommodate different arrangements of sent data (ONLY default supported now)
+    int16_t qI[4];
+    uint8_t status = dmpGetQuaternion(qI, packet);
+    if (status == 0) {
+        q -> w = (float)qI[0] / 16384.0f;
+        q -> x = (float)qI[1] / 16384.0f;
+        q -> y = (float)qI[2] / 16384.0f;
+        q -> z = (float)qI[3] / 16384.0f;
+        return 0;
+    }
+    return status; // int16 return value, indicates error if this line is reached
+}
+// uint8_t MPU6050::dmpGet6AxisQuaternion(long *data, const uint8_t* packet);
+// uint8_t MPU6050::dmpGetRelativeQuaternion(long *data, const uint8_t* packet);
+uint8_t MPU6050::dmpGetGyro(int32_t *data, const uint8_t* packet) {
+    // TODO: accommodate different arrangements of sent data (ONLY default supported now)
+    if (packet == 0) packet = dmpPacketBuffer;
+    data[0] = ((packet[16] << 24) + (packet[17] << 16) + (packet[18] << 8) + packet[19]);
+    data[1] = ((packet[20] << 24) + (packet[21] << 16) + (packet[22] << 8) + packet[23]);
+    data[2] = ((packet[24] << 24) + (packet[25] << 16) + (packet[26] << 8) + packet[27]);
+    return 0;
+}
+uint8_t MPU6050::dmpGetGyro(int16_t *data, const uint8_t* packet) {
+    // TODO: accommodate different arrangements of sent data (ONLY default supported now)
+    if (packet == 0) packet = dmpPacketBuffer;
+    data[0] = (packet[16] << 8) + packet[17];
+    data[1] = (packet[20] << 8) + packet[21];
+    data[2] = (packet[24] << 8) + packet[25];
+    return 0;
+}
+// uint8_t MPU6050::dmpSetLinearAccelFilterCoefficient(float coef);
+// uint8_t MPU6050::dmpGetLinearAccel(long *data, const uint8_t* packet);
+uint8_t MPU6050::dmpGetLinearAccel(VectorInt16 *v, VectorInt16 *vRaw, VectorFloat *gravity) {
+    // get rid of the gravity component (+1g = +8192 in standard DMP FIFO packet, sensitivity is 2g)
+    v -> x = vRaw -> x - gravity -> x*8192;
+    v -> y = vRaw -> y - gravity -> y*8192;
+    v -> z = vRaw -> z - gravity -> z*8192;
+    return 0;
+}
+// uint8_t MPU6050::dmpGetLinearAccelInWorld(long *data, const uint8_t* packet);
+uint8_t MPU6050::dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Quaternion *q) {
+    // rotate measured 3D acceleration vector into original state
+    // frame of reference based on orientation quaternion
+    memcpy(v, vReal, sizeof(VectorInt16));
+    v -> rotate(q);
+    return 0;
+}
+// uint8_t MPU6050::dmpGetGyroAndAccelSensor(long *data, const uint8_t* packet);
+// uint8_t MPU6050::dmpGetGyroSensor(long *data, const uint8_t* packet);
+// uint8_t MPU6050::dmpGetControlData(long *data, const uint8_t* packet);
+// uint8_t MPU6050::dmpGetTemperature(long *data, const uint8_t* packet);
+// uint8_t MPU6050::dmpGetGravity(long *data, const uint8_t* packet);
+uint8_t MPU6050::dmpGetGravity(VectorFloat *v, Quaternion *q) {
+    v -> x = 2 * (q -> x*q -> z - q -> w*q -> y);
+    v -> y = 2 * (q -> w*q -> x + q -> y*q -> z);
+    v -> z = q -> w*q -> w - q -> x*q -> x - q -> y*q -> y + q -> z*q -> z;
+    return 0;
+}
+// uint8_t MPU6050::dmpGetUnquantizedAccel(long *data, const uint8_t* packet);
+// uint8_t MPU6050::dmpGetQuantizedAccel(long *data, const uint8_t* packet);
+// uint8_t MPU6050::dmpGetExternalSensorData(long *data, int size, const uint8_t* packet);
+// uint8_t MPU6050::dmpGetEIS(long *data, const uint8_t* packet);
+
+uint8_t MPU6050::dmpGetEuler(float *data, Quaternion *q) {
+    data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1);   // psi
+    data[1] = -asin(2*q -> x*q -> z + 2*q -> w*q -> y);                              // theta
+    data[2] = atan2(2*q -> y*q -> z - 2*q -> w*q -> x, 2*q -> w*q -> w + 2*q -> z*q -> z - 1);   // phi
+    return 0;
+}
+uint8_t MPU6050::dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity) {
+    // yaw: (about Z axis)
+    data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1);
+    // pitch: (nose up/down, about Y axis)
+    data[1] = atan(gravity -> x / sqrt(gravity -> y*gravity -> y + gravity -> z*gravity -> z));
+    // roll: (tilt left/right, about X axis)
+    data[2] = atan(gravity -> y / sqrt(gravity -> x*gravity -> x + gravity -> z*gravity -> z));
+    return 0;
+}
+
+// uint8_t MPU6050::dmpGetAccelFloat(float *data, const uint8_t* packet);
+// uint8_t MPU6050::dmpGetQuaternionFloat(float *data, const uint8_t* packet);
+
+uint8_t MPU6050::dmpProcessFIFOPacket(const unsigned char *dmpData) {
+    /*for (uint8_t k = 0; k < dmpPacketSize; k++) {
+        if (dmpData[k] < 0x10) Serial.print("0");
+        Serial.print(dmpData[k], HEX);
+        Serial.print(" ");
+    }
+    Serial.print("\n");*/
+    //Serial.println((uint16_t)dmpPacketBuffer);
+    return 0;
+}
+uint8_t MPU6050::dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *processed) {
+    uint8_t status;
+    uint8_t buf[dmpPacketSize];
+    for (uint8_t i = 0; i < numPackets; i++) {
+        // read packet from FIFO
+        getFIFOBytes(buf, dmpPacketSize);
+
+        // process packet
+        if ((status = dmpProcessFIFOPacket(buf)) > 0) return status;
+        
+        // increment external process count variable, if supplied
+        if (processed != 0) *processed++;
+    }
+    return 0;
+}
+
+// uint8_t MPU6050::dmpSetFIFOProcessedCallback(void (*func) (void));
+
+// uint8_t MPU6050::dmpInitFIFOParam();
+// uint8_t MPU6050::dmpCloseFIFO();
+// uint8_t MPU6050::dmpSetGyroDataSource(uint_fast8_t source);
+// uint8_t MPU6050::dmpDecodeQuantizedAccel();
+// uint32_t MPU6050::dmpGetGyroSumOfSquare();
+// uint32_t MPU6050::dmpGetAccelSumOfSquare();
+// void MPU6050::dmpOverrideQuaternion(long *q);
+uint16_t MPU6050::dmpGetFIFOPacketSize() {
+    return dmpPacketSize;
+}
+
+#endif /* _MPU6050_6AXIS_MOTIONAPPS20_H_ */
diff --git a/Arduino/MPU9150/MPU6050_9Axis_MotionApps41.h b/Arduino/MPU9150/MPU6050_9Axis_MotionApps41.h
new file mode 100644
index 00000000..14e280c0
--- /dev/null
+++ b/Arduino/MPU9150/MPU6050_9Axis_MotionApps41.h
@@ -0,0 +1,852 @@
+// I2Cdev library collection - MPU6050 I2C device class, 9-axis MotionApps 4.1 implementation
+// Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00)
+// 6/18/2012 by Jeff Rowberg 
+// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
+//
+// Changelog:
+//     ... - ongoing debug release
+
+/* ============================================
+I2Cdev device library code is placed under the MIT license
+Copyright (c) 2012 Jeff Rowberg
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+===============================================
+*/
+
+#ifndef _MPU6050_9AXIS_MOTIONAPPS41_H_
+#define _MPU6050_9AXIS_MOTIONAPPS41_H_
+
+#include "I2Cdev.h"
+#include "helper_3dmath.h"
+
+// MotionApps 4.1 DMP implementation, built using the MPU-9150 "MotionFit" board
+#define MPU6050_INCLUDE_DMP_MOTIONAPPS41
+
+#include "MPU6050.h"
+
+// Tom Carpenter's conditional PROGMEM code
+// http://forum.arduino.cc/index.php?topic=129407.0
+#ifndef __arm__
+    #include 
+#else
+    // Teensy 3.0 library conditional PROGMEM code from Paul Stoffregen
+    #ifndef __PGMSPACE_H_
+        #define __PGMSPACE_H_ 1
+        #include 
+
+        #define PROGMEM
+        #define PGM_P  const char *
+        #define PSTR(str) (str)
+        #define F(x) x
+
+        typedef void prog_void;
+        typedef char prog_char;
+        typedef unsigned char prog_uchar;
+        typedef int8_t prog_int8_t;
+        typedef uint8_t prog_uint8_t;
+        typedef int16_t prog_int16_t;
+        typedef uint16_t prog_uint16_t;
+        typedef int32_t prog_int32_t;
+        typedef uint32_t prog_uint32_t;
+        
+        #define strcpy_P(dest, src) strcpy((dest), (src))
+        #define strcat_P(dest, src) strcat((dest), (src))
+        #define strcmp_P(a, b) strcmp((a), (b))
+        
+        #define pgm_read_byte(addr) (*(const unsigned char *)(addr))
+        #define pgm_read_word(addr) (*(const unsigned short *)(addr))
+        #define pgm_read_dword(addr) (*(const unsigned long *)(addr))
+        #define pgm_read_float(addr) (*(const float *)(addr))
+        
+        #define pgm_read_byte_near(addr) pgm_read_byte(addr)
+        #define pgm_read_word_near(addr) pgm_read_word(addr)
+        #define pgm_read_dword_near(addr) pgm_read_dword(addr)
+        #define pgm_read_float_near(addr) pgm_read_float(addr)
+        #define pgm_read_byte_far(addr) pgm_read_byte(addr)
+        #define pgm_read_word_far(addr) pgm_read_word(addr)
+        #define pgm_read_dword_far(addr) pgm_read_dword(addr)
+        #define pgm_read_float_far(addr) pgm_read_float(addr)
+    #endif
+#endif
+
+// NOTE! Enabling DEBUG adds about 3.3kB to the flash program size.
+// Debug output is now working even on ATMega328P MCUs (e.g. Arduino Uno)
+// after moving string constants to flash memory storage using the F()
+// compiler macro (Arduino IDE 1.0+ required).
+
+//#define DEBUG
+#ifdef DEBUG
+    #define DEBUG_PRINT(x) Serial.print(x)
+    #define DEBUG_PRINTF(x, y) Serial.print(x, y)
+    #define DEBUG_PRINTLN(x) Serial.println(x)
+    #define DEBUG_PRINTLNF(x, y) Serial.println(x, y)
+#else
+    #define DEBUG_PRINT(x)
+    #define DEBUG_PRINTF(x, y)
+    #define DEBUG_PRINTLN(x)
+    #define DEBUG_PRINTLNF(x, y)
+#endif
+
+#define MPU6050_DMP_CODE_SIZE       1962    // dmpMemory[]
+#define MPU6050_DMP_CONFIG_SIZE     232     // dmpConfig[]
+#define MPU6050_DMP_UPDATES_SIZE    140     // dmpUpdates[]
+
+/* ================================================================================================ *
+ | Default MotionApps v4.1 48-byte FIFO packet structure:                                           |
+ |                                                                                                  |
+ | [QUAT W][      ][QUAT X][      ][QUAT Y][      ][QUAT Z][      ][GYRO X][      ][GYRO Y][      ] |
+ |   0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18  19  20  21  22  23  |
+ |                                                                                                  |
+ | [GYRO Z][      ][MAG X ][MAG Y ][MAG Z ][ACC X ][      ][ACC Y ][      ][ACC Z ][      ][      ] |
+ |  24  25  26  27  28  29  30  31  32  33  34  35  36  37  38  39  40  41  42  43  44  45  46  47  |
+ * ================================================================================================ */
+
+// this block of memory gets written to the MPU on start-up, and it seems
+// to be volatile memory, so it has to be done each time (it only takes ~1
+// second though)
+const prog_uchar dmpMemory[MPU6050_DMP_CODE_SIZE] PROGMEM = {
+    // bank 0, 256 bytes
+    0xFB, 0x00, 0x00, 0x3E, 0x00, 0x0B, 0x00, 0x36, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00,
+    0x00, 0x65, 0x00, 0x54, 0xFF, 0xEF, 0x00, 0x00, 0xFA, 0x80, 0x00, 0x0B, 0x12, 0x82, 0x00, 0x01,
+    0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x28, 0x00, 0x00, 0xFF, 0xFF, 0x45, 0x81, 0xFF, 0xFF, 0xFA, 0x72, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x03, 0xE8, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x7F, 0xFF, 0xFF, 0xFE, 0x80, 0x01,
+    0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x3E, 0x03, 0x30, 0x40, 0x00, 0x00, 0x00, 0x02, 0xCA, 0xE3, 0x09, 0x3E, 0x80, 0x00, 0x00,
+    0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00,
+    0x41, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x2A, 0x00, 0x00, 0x16, 0x55, 0x00, 0x00, 0x21, 0x82,
+    0xFD, 0x87, 0x26, 0x50, 0xFD, 0x80, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x05, 0x80, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
+    0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x6F, 0x00, 0x02, 0x65, 0x32, 0x00, 0x00, 0x5E, 0xC0,
+    0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0xFB, 0x8C, 0x6F, 0x5D, 0xFD, 0x5D, 0x08, 0xD9, 0x00, 0x7C, 0x73, 0x3B, 0x00, 0x6C, 0x12, 0xCC,
+    0x32, 0x00, 0x13, 0x9D, 0x32, 0x00, 0xD0, 0xD6, 0x32, 0x00, 0x08, 0x00, 0x40, 0x00, 0x01, 0xF4,
+    0xFF, 0xE6, 0x80, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0xD6, 0x00, 0x00, 0x27, 0x10,
+
+    // bank 1, 256 bytes
+    0xFB, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0xFA, 0x36, 0xFF, 0xBC, 0x30, 0x8E, 0x00, 0x05, 0xFB, 0xF0, 0xFF, 0xD9, 0x5B, 0xC8,
+    0xFF, 0xD0, 0x9A, 0xBE, 0x00, 0x00, 0x10, 0xA9, 0xFF, 0xF4, 0x1E, 0xB2, 0x00, 0xCE, 0xBB, 0xF7,
+    0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x0C,
+    0xFF, 0xC2, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0xCF, 0x80, 0x00, 0x40, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x14,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x03, 0x3F, 0x68, 0xB6, 0x79, 0x35, 0x28, 0xBC, 0xC6, 0x7E, 0xD1, 0x6C,
+    0x80, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB2, 0x6A, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x30,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x25, 0x4D, 0x00, 0x2F, 0x70, 0x6D, 0x00, 0x00, 0x05, 0xAE, 0x00, 0x0C, 0x02, 0xD0,
+    
+    // bank 2, 256 bytes
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x54, 0xFF, 0xEF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x01, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x01, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0xFF, 0xEF, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+    0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x78, 0xA2,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    
+    // bank 3, 256 bytes
+    0xD8, 0xDC, 0xF4, 0xD8, 0xB9, 0xAB, 0xF3, 0xF8, 0xFA, 0xF1, 0xBA, 0xA2, 0xDE, 0xB2, 0xB8, 0xB4,
+    0xA8, 0x81, 0x98, 0xF7, 0x4A, 0x90, 0x7F, 0x91, 0x6A, 0xF3, 0xF9, 0xDB, 0xA8, 0xF9, 0xB0, 0xBA,
+    0xA0, 0x80, 0xF2, 0xCE, 0x81, 0xF3, 0xC2, 0xF1, 0xC1, 0xF2, 0xC3, 0xF3, 0xCC, 0xA2, 0xB2, 0x80,
+    0xF1, 0xC6, 0xD8, 0x80, 0xBA, 0xA7, 0xDF, 0xDF, 0xDF, 0xF2, 0xA7, 0xC3, 0xCB, 0xC5, 0xB6, 0xF0,
+    0x87, 0xA2, 0x94, 0x24, 0x48, 0x70, 0x3C, 0x95, 0x40, 0x68, 0x34, 0x58, 0x9B, 0x78, 0xA2, 0xF1,
+    0x83, 0x92, 0x2D, 0x55, 0x7D, 0xD8, 0xB1, 0xB4, 0xB8, 0xA1, 0xD0, 0x91, 0x80, 0xF2, 0x70, 0xF3,
+    0x70, 0xF2, 0x7C, 0x80, 0xA8, 0xF1, 0x01, 0xB0, 0x98, 0x87, 0xD9, 0x43, 0xD8, 0x86, 0xC9, 0x88,
+    0xBA, 0xA1, 0xF2, 0x0E, 0xB8, 0x97, 0x80, 0xF1, 0xA9, 0xDF, 0xDF, 0xDF, 0xAA, 0xDF, 0xDF, 0xDF,
+    0xF2, 0xAA, 0xC5, 0xCD, 0xC7, 0xA9, 0x0C, 0xC9, 0x2C, 0x97, 0x97, 0x97, 0x97, 0xF1, 0xA9, 0x89,
+    0x26, 0x46, 0x66, 0xB0, 0xB4, 0xBA, 0x80, 0xAC, 0xDE, 0xF2, 0xCA, 0xF1, 0xB2, 0x8C, 0x02, 0xA9,
+    0xB6, 0x98, 0x00, 0x89, 0x0E, 0x16, 0x1E, 0xB8, 0xA9, 0xB4, 0x99, 0x2C, 0x54, 0x7C, 0xB0, 0x8A,
+    0xA8, 0x96, 0x36, 0x56, 0x76, 0xF1, 0xB9, 0xAF, 0xB4, 0xB0, 0x83, 0xC0, 0xB8, 0xA8, 0x97, 0x11,
+    0xB1, 0x8F, 0x98, 0xB9, 0xAF, 0xF0, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0xF1, 0xA3, 0x29, 0x55,
+    0x7D, 0xAF, 0x83, 0xB5, 0x93, 0xF0, 0x00, 0x28, 0x50, 0xF5, 0xBA, 0xAD, 0x8F, 0x9F, 0x28, 0x54,
+    0x7C, 0xB9, 0xF1, 0xA3, 0x86, 0x9F, 0x61, 0xA6, 0xDA, 0xDE, 0xDF, 0xDB, 0xB2, 0xB6, 0x8E, 0x9D,
+    0xAE, 0xF5, 0x60, 0x68, 0x70, 0xB1, 0xB5, 0xF1, 0xDA, 0xA6, 0xDF, 0xD9, 0xA6, 0xFA, 0xA3, 0x86,
+    
+    // bank 4, 256 bytes
+    0x96, 0xDB, 0x31, 0xA6, 0xD9, 0xF8, 0xDF, 0xBA, 0xA6, 0x8F, 0xC2, 0xC5, 0xC7, 0xB2, 0x8C, 0xC1,
+    0xB8, 0xA2, 0xDF, 0xDF, 0xDF, 0xA3, 0xDF, 0xDF, 0xDF, 0xD8, 0xD8, 0xF1, 0xB8, 0xA8, 0xB2, 0x86,
+    0xB4, 0x98, 0x0D, 0x35, 0x5D, 0xB8, 0xAA, 0x98, 0xB0, 0x87, 0x2D, 0x35, 0x3D, 0xB2, 0xB6, 0xBA,
+    0xAF, 0x8C, 0x96, 0x19, 0x8F, 0x9F, 0xA7, 0x0E, 0x16, 0x1E, 0xB4, 0x9A, 0xB8, 0xAA, 0x87, 0x2C,
+    0x54, 0x7C, 0xB9, 0xA3, 0xDE, 0xDF, 0xDF, 0xA3, 0xB1, 0x80, 0xF2, 0xC4, 0xCD, 0xC9, 0xF1, 0xB8,
+    0xA9, 0xB4, 0x99, 0x83, 0x0D, 0x35, 0x5D, 0x89, 0xB9, 0xA3, 0x2D, 0x55, 0x7D, 0xB5, 0x93, 0xA3,
+    0x0E, 0x16, 0x1E, 0xA9, 0x2C, 0x54, 0x7C, 0xB8, 0xB4, 0xB0, 0xF1, 0x97, 0x83, 0xA8, 0x11, 0x84,
+    0xA5, 0x09, 0x98, 0xA3, 0x83, 0xF0, 0xDA, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0xD8, 0xF1, 0xA5,
+    0x29, 0x55, 0x7D, 0xA5, 0x85, 0x95, 0x02, 0x1A, 0x2E, 0x3A, 0x56, 0x5A, 0x40, 0x48, 0xF9, 0xF3,
+    0xA3, 0xD9, 0xF8, 0xF0, 0x98, 0x83, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0x97, 0x82, 0xA8, 0xF1,
+    0x11, 0xF0, 0x98, 0xA2, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0xDA, 0xF3, 0xDE, 0xD8, 0x83, 0xA5,
+    0x94, 0x01, 0xD9, 0xA3, 0x02, 0xF1, 0xA2, 0xC3, 0xC5, 0xC7, 0xD8, 0xF1, 0x84, 0x92, 0xA2, 0x4D,
+    0xDA, 0x2A, 0xD8, 0x48, 0x69, 0xD9, 0x2A, 0xD8, 0x68, 0x55, 0xDA, 0x32, 0xD8, 0x50, 0x71, 0xD9,
+    0x32, 0xD8, 0x70, 0x5D, 0xDA, 0x3A, 0xD8, 0x58, 0x79, 0xD9, 0x3A, 0xD8, 0x78, 0x93, 0xA3, 0x4D,
+    0xDA, 0x2A, 0xD8, 0x48, 0x69, 0xD9, 0x2A, 0xD8, 0x68, 0x55, 0xDA, 0x32, 0xD8, 0x50, 0x71, 0xD9,
+    0x32, 0xD8, 0x70, 0x5D, 0xDA, 0x3A, 0xD8, 0x58, 0x79, 0xD9, 0x3A, 0xD8, 0x78, 0xA8, 0x8A, 0x9A,
+    
+    // bank 5, 256 bytes
+    0xF0, 0x28, 0x50, 0x78, 0x9E, 0xF3, 0x88, 0x18, 0xF1, 0x9F, 0x1D, 0x98, 0xA8, 0xD9, 0x08, 0xD8,
+    0xC8, 0x9F, 0x12, 0x9E, 0xF3, 0x15, 0xA8, 0xDA, 0x12, 0x10, 0xD8, 0xF1, 0xAF, 0xC8, 0x97, 0x87,
+    0x34, 0xB5, 0xB9, 0x94, 0xA4, 0x21, 0xF3, 0xD9, 0x22, 0xD8, 0xF2, 0x2D, 0xF3, 0xD9, 0x2A, 0xD8,
+    0xF2, 0x35, 0xF3, 0xD9, 0x32, 0xD8, 0x81, 0xA4, 0x60, 0x60, 0x61, 0xD9, 0x61, 0xD8, 0x6C, 0x68,
+    0x69, 0xD9, 0x69, 0xD8, 0x74, 0x70, 0x71, 0xD9, 0x71, 0xD8, 0xB1, 0xA3, 0x84, 0x19, 0x3D, 0x5D,
+    0xA3, 0x83, 0x1A, 0x3E, 0x5E, 0x93, 0x10, 0x30, 0x81, 0x10, 0x11, 0xB8, 0xB0, 0xAF, 0x8F, 0x94,
+    0xF2, 0xDA, 0x3E, 0xD8, 0xB4, 0x9A, 0xA8, 0x87, 0x29, 0xDA, 0xF8, 0xD8, 0x87, 0x9A, 0x35, 0xDA,
+    0xF8, 0xD8, 0x87, 0x9A, 0x3D, 0xDA, 0xF8, 0xD8, 0xB1, 0xB9, 0xA4, 0x98, 0x85, 0x02, 0x2E, 0x56,
+    0xA5, 0x81, 0x00, 0x0C, 0x14, 0xA3, 0x97, 0xB0, 0x8A, 0xF1, 0x2D, 0xD9, 0x28, 0xD8, 0x4D, 0xD9,
+    0x48, 0xD8, 0x6D, 0xD9, 0x68, 0xD8, 0xB1, 0x84, 0x0D, 0xDA, 0x0E, 0xD8, 0xA3, 0x29, 0x83, 0xDA,
+    0x2C, 0x0E, 0xD8, 0xA3, 0x84, 0x49, 0x83, 0xDA, 0x2C, 0x4C, 0x0E, 0xD8, 0xB8, 0xB0, 0x97, 0x86,
+    0xA8, 0x31, 0x9B, 0x06, 0x99, 0x07, 0xAB, 0x97, 0x28, 0x88, 0x9B, 0xF0, 0x0C, 0x20, 0x14, 0x40,
+    0xB9, 0xA3, 0x8A, 0xC3, 0xC5, 0xC7, 0x9A, 0xA3, 0x28, 0x50, 0x78, 0xF1, 0xB5, 0x93, 0x01, 0xD9,
+    0xDF, 0xDF, 0xDF, 0xD8, 0xB8, 0xB4, 0xA8, 0x8C, 0x9C, 0xF0, 0x04, 0x28, 0x51, 0x79, 0x1D, 0x30,
+    0x14, 0x38, 0xB2, 0x82, 0xAB, 0xD0, 0x98, 0x2C, 0x50, 0x50, 0x78, 0x78, 0x9B, 0xF1, 0x1A, 0xB0,
+    0xF0, 0xB1, 0x83, 0x9C, 0xA8, 0x29, 0x51, 0x79, 0xB0, 0x8B, 0x29, 0x51, 0x79, 0xB1, 0x83, 0x24,
+
+    // bank 6, 256 bytes
+    0x70, 0x59, 0xB0, 0x8B, 0x20, 0x58, 0x71, 0xB1, 0x83, 0x44, 0x69, 0x38, 0xB0, 0x8B, 0x39, 0x40,
+    0x68, 0xB1, 0x83, 0x64, 0x48, 0x31, 0xB0, 0x8B, 0x30, 0x49, 0x60, 0xA5, 0x88, 0x20, 0x09, 0x71,
+    0x58, 0x44, 0x68, 0x11, 0x39, 0x64, 0x49, 0x30, 0x19, 0xF1, 0xAC, 0x00, 0x2C, 0x54, 0x7C, 0xF0,
+    0x8C, 0xA8, 0x04, 0x28, 0x50, 0x78, 0xF1, 0x88, 0x97, 0x26, 0xA8, 0x59, 0x98, 0xAC, 0x8C, 0x02,
+    0x26, 0x46, 0x66, 0xF0, 0x89, 0x9C, 0xA8, 0x29, 0x51, 0x79, 0x24, 0x70, 0x59, 0x44, 0x69, 0x38,
+    0x64, 0x48, 0x31, 0xA9, 0x88, 0x09, 0x20, 0x59, 0x70, 0xAB, 0x11, 0x38, 0x40, 0x69, 0xA8, 0x19,
+    0x31, 0x48, 0x60, 0x8C, 0xA8, 0x3C, 0x41, 0x5C, 0x20, 0x7C, 0x00, 0xF1, 0x87, 0x98, 0x19, 0x86,
+    0xA8, 0x6E, 0x76, 0x7E, 0xA9, 0x99, 0x88, 0x2D, 0x55, 0x7D, 0x9E, 0xB9, 0xA3, 0x8A, 0x22, 0x8A,
+    0x6E, 0x8A, 0x56, 0x8A, 0x5E, 0x9F, 0xB1, 0x83, 0x06, 0x26, 0x46, 0x66, 0x0E, 0x2E, 0x4E, 0x6E,
+    0x9D, 0xB8, 0xAD, 0x00, 0x2C, 0x54, 0x7C, 0xF2, 0xB1, 0x8C, 0xB4, 0x99, 0xB9, 0xA3, 0x2D, 0x55,
+    0x7D, 0x81, 0x91, 0xAC, 0x38, 0xAD, 0x3A, 0xB5, 0x83, 0x91, 0xAC, 0x2D, 0xD9, 0x28, 0xD8, 0x4D,
+    0xD9, 0x48, 0xD8, 0x6D, 0xD9, 0x68, 0xD8, 0x8C, 0x9D, 0xAE, 0x29, 0xD9, 0x04, 0xAE, 0xD8, 0x51,
+    0xD9, 0x04, 0xAE, 0xD8, 0x79, 0xD9, 0x04, 0xD8, 0x81, 0xF3, 0x9D, 0xAD, 0x00, 0x8D, 0xAE, 0x19,
+    0x81, 0xAD, 0xD9, 0x01, 0xD8, 0xF2, 0xAE, 0xDA, 0x26, 0xD8, 0x8E, 0x91, 0x29, 0x83, 0xA7, 0xD9,
+    0xAD, 0xAD, 0xAD, 0xAD, 0xF3, 0x2A, 0xD8, 0xD8, 0xF1, 0xB0, 0xAC, 0x89, 0x91, 0x3E, 0x5E, 0x76,
+    0xF3, 0xAC, 0x2E, 0x2E, 0xF1, 0xB1, 0x8C, 0x5A, 0x9C, 0xAC, 0x2C, 0x28, 0x28, 0x28, 0x9C, 0xAC,
+    
+    // bank 7, 170 bytes (remainder)
+    0x30, 0x18, 0xA8, 0x98, 0x81, 0x28, 0x34, 0x3C, 0x97, 0x24, 0xA7, 0x28, 0x34, 0x3C, 0x9C, 0x24,
+    0xF2, 0xB0, 0x89, 0xAC, 0x91, 0x2C, 0x4C, 0x6C, 0x8A, 0x9B, 0x2D, 0xD9, 0xD8, 0xD8, 0x51, 0xD9,
+    0xD8, 0xD8, 0x79, 0xD9, 0xD8, 0xD8, 0xF1, 0x9E, 0x88, 0xA3, 0x31, 0xDA, 0xD8, 0xD8, 0x91, 0x2D,
+    0xD9, 0x28, 0xD8, 0x4D, 0xD9, 0x48, 0xD8, 0x6D, 0xD9, 0x68, 0xD8, 0xB1, 0x83, 0x93, 0x35, 0x3D,
+    0x80, 0x25, 0xDA, 0xD8, 0xD8, 0x85, 0x69, 0xDA, 0xD8, 0xD8, 0xB4, 0x93, 0x81, 0xA3, 0x28, 0x34,
+    0x3C, 0xF3, 0xAB, 0x8B, 0xA3, 0x91, 0xB6, 0x09, 0xB4, 0xD9, 0xAB, 0xDE, 0xB0, 0x87, 0x9C, 0xB9,
+    0xA3, 0xDD, 0xF1, 0xA3, 0xA3, 0xA3, 0xA3, 0x95, 0xF1, 0xA3, 0xA3, 0xA3, 0x9D, 0xF1, 0xA3, 0xA3,
+    0xA3, 0xA3, 0xF2, 0xA3, 0xB4, 0x90, 0x80, 0xF2, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3,
+    0xA3, 0xA3, 0xB2, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xB0, 0x87, 0xB5, 0x99, 0xF1, 0xA3, 0xA3,
+    0xA3, 0x98, 0xF1, 0xA3, 0xA3, 0xA3, 0xA3, 0x97, 0xA3, 0xA3, 0xA3, 0xA3, 0xF3, 0x9B, 0xA3, 0xA3,
+    0xDC, 0xB9, 0xA7, 0xF1, 0x26, 0x26, 0x26, 0xD8, 0xD8, 0xFF
+};
+
+const prog_uchar dmpConfig[MPU6050_DMP_CONFIG_SIZE] PROGMEM = {
+//  BANK    OFFSET  LENGTH  [DATA]
+    0x02,   0xEC,   0x04,   0x00, 0x47, 0x7D, 0x1A,   // ?
+    0x03,   0x82,   0x03,   0x4C, 0xCD, 0x6C,         // FCFG_1 inv_set_gyro_calibration
+    0x03,   0xB2,   0x03,   0x36, 0x56, 0x76,         // FCFG_3 inv_set_gyro_calibration
+    0x00,   0x68,   0x04,   0x02, 0xCA, 0xE3, 0x09,   // D_0_104 inv_set_gyro_calibration
+    0x01,   0x0C,   0x04,   0x00, 0x00, 0x00, 0x00,   // D_1_152 inv_set_accel_calibration
+    0x03,   0x86,   0x03,   0x0C, 0xC9, 0x2C,         // FCFG_2 inv_set_accel_calibration
+    0x03,   0x90,   0x03,   0x26, 0x46, 0x66,         //   (continued)...FCFG_2 inv_set_accel_calibration
+    0x00,   0x6C,   0x02,   0x40, 0x00,               // D_0_108 inv_set_accel_calibration
+
+    0x02,   0x40,   0x04,   0x00, 0x00, 0x00, 0x00,   // CPASS_MTX_00 inv_set_compass_calibration
+    0x02,   0x44,   0x04,   0x40, 0x00, 0x00, 0x00,   // CPASS_MTX_01
+    0x02,   0x48,   0x04,   0x00, 0x00, 0x00, 0x00,   // CPASS_MTX_02
+    0x02,   0x4C,   0x04,   0x40, 0x00, 0x00, 0x00,   // CPASS_MTX_10
+    0x02,   0x50,   0x04,   0x00, 0x00, 0x00, 0x00,   // CPASS_MTX_11
+    0x02,   0x54,   0x04,   0x00, 0x00, 0x00, 0x00,   // CPASS_MTX_12
+    0x02,   0x58,   0x04,   0x00, 0x00, 0x00, 0x00,   // CPASS_MTX_20
+    0x02,   0x5C,   0x04,   0x00, 0x00, 0x00, 0x00,   // CPASS_MTX_21
+    0x02,   0xBC,   0x04,   0xC0, 0x00, 0x00, 0x00,   // CPASS_MTX_22
+
+    0x01,   0xEC,   0x04,   0x00, 0x00, 0x40, 0x00,   // D_1_236 inv_apply_endian_accel
+    0x03,   0x86,   0x06,   0x0C, 0xC9, 0x2C, 0x97, 0x97, 0x97, // FCFG_2 inv_set_mpu_sensors
+    0x04,   0x22,   0x03,   0x0D, 0x35, 0x5D,         // CFG_MOTION_BIAS inv_turn_on_bias_from_no_motion
+    0x00,   0xA3,   0x01,   0x00,                     // ?
+    0x04,   0x29,   0x04,   0x87, 0x2D, 0x35, 0x3D,   // FCFG_5 inv_set_bias_update
+    0x07,   0x62,   0x05,   0xF1, 0x20, 0x28, 0x30, 0x38, // CFG_8 inv_send_quaternion
+    0x07,   0x9F,   0x01,   0x30,                     // CFG_16 inv_set_footer
+    0x07,   0x67,   0x01,   0x9A,                     // CFG_GYRO_SOURCE inv_send_gyro
+    0x07,   0x68,   0x04,   0xF1, 0x28, 0x30, 0x38,   // CFG_9 inv_send_gyro -> inv_construct3_fifo
+    0x07,   0x62,   0x05,   0xF1, 0x20, 0x28, 0x30, 0x38, // ?
+    0x02,   0x0C,   0x04,   0x00, 0x00, 0x00, 0x00,   // ?
+    0x07,   0x83,   0x06,   0xC2, 0xCA, 0xC4, 0xA3, 0xA3, 0xA3, // ?
+                 // SPECIAL 0x01 = enable interrupts
+    0x00,   0x00,   0x00,   0x01, // SET INT_ENABLE, SPECIAL INSTRUCTION
+    0x07,   0xA7,   0x01,   0xFE,                     // ?
+    0x07,   0x62,   0x05,   0xF1, 0x20, 0x28, 0x30, 0x38, // ?
+    0x07,   0x67,   0x01,   0x9A,                     // ?
+    0x07,   0x68,   0x04,   0xF1, 0x28, 0x30, 0x38,   // CFG_12 inv_send_accel -> inv_construct3_fifo
+    0x07,   0x8D,   0x04,   0xF1, 0x28, 0x30, 0x38,   // ??? CFG_12 inv_send_mag -> inv_construct3_fifo
+    0x02,   0x16,   0x02,   0x00, 0x03                // D_0_22 inv_set_fifo_rate
+
+    // This very last 0x01 WAS a 0x09, which drops the FIFO rate down to 20 Hz. 0x07 is 25 Hz,
+    // 0x01 is 100Hz. Going faster than 100Hz (0x00=200Hz) tends to result in very noisy data.
+    // DMP output frequency is calculated easily using this equation: (200Hz / (1 + value))
+
+    // It is important to make sure the host processor can keep up with reading and processing
+    // the FIFO output at the desired rate. Handling FIFO overflow cleanly is also a good idea.
+};
+
+const prog_uchar dmpUpdates[MPU6050_DMP_UPDATES_SIZE] PROGMEM = {
+    0x01,   0xB2,   0x02,   0xFF, 0xF5,
+    0x01,   0x90,   0x04,   0x0A, 0x0D, 0x97, 0xC0,
+    0x00,   0xA3,   0x01,   0x00,
+    0x04,   0x29,   0x04,   0x87, 0x2D, 0x35, 0x3D,
+    0x01,   0x6A,   0x02,   0x06, 0x00,
+    0x01,   0x60,   0x08,   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00,   0x60,   0x04,   0x40, 0x00, 0x00, 0x00,
+    0x02,   0x60,   0x0C,   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x01,   0x08,   0x02,   0x01, 0x20,
+    0x01,   0x0A,   0x02,   0x00, 0x4E,
+    0x01,   0x02,   0x02,   0xFE, 0xB3,
+    0x02,   0x6C,   0x04,   0x00, 0x00, 0x00, 0x00, // READ
+    0x02,   0x6C,   0x04,   0xFA, 0xFE, 0x00, 0x00,
+    0x02,   0x60,   0x0C,   0xFF, 0xFF, 0xCB, 0x4D, 0x00, 0x01, 0x08, 0xC1, 0xFF, 0xFF, 0xBC, 0x2C,
+    0x02,   0xF4,   0x04,   0x00, 0x00, 0x00, 0x00,
+    0x02,   0xF8,   0x04,   0x00, 0x00, 0x00, 0x00,
+    0x02,   0xFC,   0x04,   0x00, 0x00, 0x00, 0x00,
+    0x00,   0x60,   0x04,   0x40, 0x00, 0x00, 0x00,
+    0x00,   0x60,   0x04,   0x00, 0x40, 0x00, 0x00
+};
+
+uint8_t MPU6050::dmpInitialize() {
+    // reset device
+    DEBUG_PRINTLN(F("\n\nResetting MPU6050..."));
+    reset();
+    delay(30); // wait after reset
+
+    // disable sleep mode
+    DEBUG_PRINTLN(F("Disabling sleep mode..."));
+    setSleepEnabled(false);
+
+    // get MPU product ID
+    DEBUG_PRINTLN(F("Getting product ID..."));
+    //uint8_t productID = 0; //getProductID();
+    DEBUG_PRINT(F("Product ID = "));
+    DEBUG_PRINT(productID);
+
+    // get MPU hardware revision
+    DEBUG_PRINTLN(F("Selecting user bank 16..."));
+    setMemoryBank(0x10, true, true);
+    DEBUG_PRINTLN(F("Selecting memory byte 6..."));
+    setMemoryStartAddress(0x06);
+    DEBUG_PRINTLN(F("Checking hardware revision..."));
+    uint8_t hwRevision = readMemoryByte();
+    DEBUG_PRINT(F("Revision @ user[16][6] = "));
+    DEBUG_PRINTLNF(hwRevision, HEX);
+    DEBUG_PRINTLN(F("Resetting memory bank selection to 0..."));
+    setMemoryBank(0, false, false);
+
+    // check OTP bank valid
+    DEBUG_PRINTLN(F("Reading OTP bank valid flag..."));
+    uint8_t otpValid = getOTPBankValid();
+    DEBUG_PRINT(F("OTP bank is "));
+    DEBUG_PRINTLN(otpValid ? F("valid!") : F("invalid!"));
+
+    // get X/Y/Z gyro offsets
+    DEBUG_PRINTLN(F("Reading gyro offset values..."));
+    int8_t xgOffset = getXGyroOffset();
+    int8_t ygOffset = getYGyroOffset();
+    int8_t zgOffset = getZGyroOffset();
+    DEBUG_PRINT(F("X gyro offset = "));
+    DEBUG_PRINTLN(xgOffset);
+    DEBUG_PRINT(F("Y gyro offset = "));
+    DEBUG_PRINTLN(ygOffset);
+    DEBUG_PRINT(F("Z gyro offset = "));
+    DEBUG_PRINTLN(zgOffset);
+    
+    I2Cdev::readByte(devAddr, MPU6050_RA_USER_CTRL, buffer); // ?
+    
+    DEBUG_PRINTLN(F("Enabling interrupt latch, clear on any read, AUX bypass enabled"));
+    I2Cdev::writeByte(devAddr, MPU6050_RA_INT_PIN_CFG, 0x32);
+
+    // enable MPU AUX I2C bypass mode
+    //DEBUG_PRINTLN(F("Enabling AUX I2C bypass mode..."));
+    //setI2CBypassEnabled(true);
+
+    DEBUG_PRINTLN(F("Setting magnetometer mode to power-down..."));
+    //mag -> setMode(0);
+    I2Cdev::writeByte(0x0E, 0x0A, 0x00);
+
+    DEBUG_PRINTLN(F("Setting magnetometer mode to fuse access..."));
+    //mag -> setMode(0x0F);
+    I2Cdev::writeByte(0x0E, 0x0A, 0x0F);
+
+    DEBUG_PRINTLN(F("Reading mag magnetometer factory calibration..."));
+    int8_t asax, asay, asaz;
+    //mag -> getAdjustment(&asax, &asay, &asaz);
+    I2Cdev::readBytes(0x0E, 0x10, 3, buffer);
+    asax = (int8_t)buffer[0];
+    asay = (int8_t)buffer[1];
+    asaz = (int8_t)buffer[2];
+    DEBUG_PRINT(F("Adjustment X/Y/Z = "));
+    DEBUG_PRINT(asax);
+    DEBUG_PRINT(F(" / "));
+    DEBUG_PRINT(asay);
+    DEBUG_PRINT(F(" / "));
+    DEBUG_PRINTLN(asaz);
+
+    DEBUG_PRINTLN(F("Setting magnetometer mode to power-down..."));
+    //mag -> setMode(0);
+    I2Cdev::writeByte(0x0E, 0x0A, 0x00);
+
+    // load DMP code into memory banks
+    DEBUG_PRINT(F("Writing DMP code to MPU memory banks ("));
+    DEBUG_PRINT(MPU6050_DMP_CODE_SIZE);
+    DEBUG_PRINTLN(F(" bytes)"));
+    if (writeProgMemoryBlock(dmpMemory, MPU6050_DMP_CODE_SIZE)) {
+        DEBUG_PRINTLN(F("Success! DMP code written and verified."));
+
+        DEBUG_PRINTLN(F("Configuring DMP and related settings..."));
+
+        // write DMP configuration
+        DEBUG_PRINT(F("Writing DMP configuration to MPU memory banks ("));
+        DEBUG_PRINT(MPU6050_DMP_CONFIG_SIZE);
+        DEBUG_PRINTLN(F(" bytes in config def)"));
+        if (writeProgDMPConfigurationSet(dmpConfig, MPU6050_DMP_CONFIG_SIZE)) {
+            DEBUG_PRINTLN(F("Success! DMP configuration written and verified."));
+
+            DEBUG_PRINTLN(F("Setting DMP and FIFO_OFLOW interrupts enabled..."));
+            setIntEnabled(0x12);
+
+            DEBUG_PRINTLN(F("Setting sample rate to 200Hz..."));
+            setRate(4); // 1khz / (1 + 4) = 200 Hz
+
+            DEBUG_PRINTLN(F("Setting clock source to Z Gyro..."));
+            setClockSource(MPU6050_CLOCK_PLL_ZGYRO);
+
+            DEBUG_PRINTLN(F("Setting DLPF bandwidth to 42Hz..."));
+            setDLPFMode(MPU6050_DLPF_BW_42);
+
+            DEBUG_PRINTLN(F("Setting external frame sync to TEMP_OUT_L[0]..."));
+            setExternalFrameSync(MPU6050_EXT_SYNC_TEMP_OUT_L);
+
+            DEBUG_PRINTLN(F("Setting gyro sensitivity to +/- 2000 deg/sec..."));
+            setFullScaleGyroRange(MPU6050_GYRO_FS_2000);
+
+            DEBUG_PRINTLN(F("Setting DMP configuration bytes (function unknown)..."));
+            setDMPConfig1(0x03);
+            setDMPConfig2(0x00);
+
+            DEBUG_PRINTLN(F("Clearing OTP Bank flag..."));
+            setOTPBankValid(false);
+
+            DEBUG_PRINTLN(F("Setting X/Y/Z gyro offsets to previous values..."));
+            setXGyroOffset(xgOffset);
+            setYGyroOffset(ygOffset);
+            setZGyroOffset(zgOffset);
+
+            DEBUG_PRINTLN(F("Setting X/Y/Z gyro user offsets to zero..."));
+            setXGyroOffsetUser(0);
+            setYGyroOffsetUser(0);
+            setZGyroOffsetUser(0);
+
+            DEBUG_PRINTLN(F("Writing final memory update 1/19 (function unknown)..."));
+            uint8_t dmpUpdate[16], j;
+            uint16_t pos = 0;
+            for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
+            writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
+
+            DEBUG_PRINTLN(F("Writing final memory update 2/19 (function unknown)..."));
+            for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
+            writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
+
+            DEBUG_PRINTLN(F("Resetting FIFO..."));
+            resetFIFO();
+
+            DEBUG_PRINTLN(F("Reading FIFO count..."));
+            uint8_t fifoCount = getFIFOCount();
+
+            DEBUG_PRINT(F("Current FIFO count="));
+            DEBUG_PRINTLN(fifoCount);
+            uint8_t fifoBuffer[128];
+            //getFIFOBytes(fifoBuffer, fifoCount);
+
+            DEBUG_PRINTLN(F("Writing final memory update 3/19 (function unknown)..."));
+            for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
+            writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
+
+            DEBUG_PRINTLN(F("Writing final memory update 4/19 (function unknown)..."));
+            for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
+            writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
+
+            DEBUG_PRINTLN(F("Disabling all standby flags..."));
+            I2Cdev::writeByte(0x68, MPU6050_RA_PWR_MGMT_2, 0x00);
+
+            DEBUG_PRINTLN(F("Setting accelerometer sensitivity to +/- 2g..."));
+            I2Cdev::writeByte(0x68, MPU6050_RA_ACCEL_CONFIG, 0x00);
+
+            DEBUG_PRINTLN(F("Setting motion detection threshold to 2..."));
+            setMotionDetectionThreshold(2);
+
+            DEBUG_PRINTLN(F("Setting zero-motion detection threshold to 156..."));
+            setZeroMotionDetectionThreshold(156);
+
+            DEBUG_PRINTLN(F("Setting motion detection duration to 80..."));
+            setMotionDetectionDuration(80);
+
+            DEBUG_PRINTLN(F("Setting zero-motion detection duration to 0..."));
+            setZeroMotionDetectionDuration(0);
+
+            DEBUG_PRINTLN(F("Setting AK8975 to single measurement mode..."));
+            //mag -> setMode(1);
+            I2Cdev::writeByte(0x0E, 0x0A, 0x01);
+
+            // setup AK8975 (0x0E) as Slave 0 in read mode
+            DEBUG_PRINTLN(F("Setting up AK8975 read slave 0..."));
+            I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV0_ADDR, 0x8E);
+            I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV0_REG,  0x01);
+            I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV0_CTRL, 0xDA);
+
+            // setup AK8975 (0x0E) as Slave 2 in write mode
+            DEBUG_PRINTLN(F("Setting up AK8975 write slave 2..."));
+            I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV2_ADDR, 0x0E);
+            I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV2_REG,  0x0A);
+            I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV2_CTRL, 0x81);
+            I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV2_DO,   0x01);
+
+            // setup I2C timing/delay control
+            DEBUG_PRINTLN(F("Setting up slave access delay..."));
+            I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV4_CTRL, 0x18);
+            I2Cdev::writeByte(0x68, MPU6050_RA_I2C_MST_DELAY_CTRL, 0x05);
+
+            // enable interrupts
+            DEBUG_PRINTLN(F("Enabling default interrupt behavior/no bypass..."));
+            I2Cdev::writeByte(0x68, MPU6050_RA_INT_PIN_CFG, 0x00);
+
+            // enable I2C master mode and reset DMP/FIFO
+            DEBUG_PRINTLN(F("Enabling I2C master mode..."));
+            I2Cdev::writeByte(0x68, MPU6050_RA_USER_CTRL, 0x20);
+            DEBUG_PRINTLN(F("Resetting FIFO..."));
+            I2Cdev::writeByte(0x68, MPU6050_RA_USER_CTRL, 0x24);
+            DEBUG_PRINTLN(F("Rewriting I2C master mode enabled because...I don't know"));
+            I2Cdev::writeByte(0x68, MPU6050_RA_USER_CTRL, 0x20);
+            DEBUG_PRINTLN(F("Enabling and resetting DMP/FIFO..."));
+            I2Cdev::writeByte(0x68, MPU6050_RA_USER_CTRL, 0xE8);
+
+            DEBUG_PRINTLN(F("Writing final memory update 5/19 (function unknown)..."));
+            for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
+            writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
+            DEBUG_PRINTLN(F("Writing final memory update 6/19 (function unknown)..."));
+            for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
+            writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
+            DEBUG_PRINTLN(F("Writing final memory update 7/19 (function unknown)..."));
+            for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
+            writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
+            DEBUG_PRINTLN(F("Writing final memory update 8/19 (function unknown)..."));
+            for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
+            writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
+            DEBUG_PRINTLN(F("Writing final memory update 9/19 (function unknown)..."));
+            for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
+            writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
+            DEBUG_PRINTLN(F("Writing final memory update 10/19 (function unknown)..."));
+            for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
+            writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
+            DEBUG_PRINTLN(F("Writing final memory update 11/19 (function unknown)..."));
+            for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
+            writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
+            
+            DEBUG_PRINTLN(F("Reading final memory update 12/19 (function unknown)..."));
+            for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
+            readMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
+            #ifdef DEBUG
+                DEBUG_PRINT(F("Read bytes: "));
+                for (j = 0; j < 4; j++) {
+                    DEBUG_PRINTF(dmpUpdate[3 + j], HEX);
+                    DEBUG_PRINT(" ");
+                }
+                DEBUG_PRINTLN("");
+            #endif
+
+            DEBUG_PRINTLN(F("Writing final memory update 13/19 (function unknown)..."));
+            for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
+            writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
+            DEBUG_PRINTLN(F("Writing final memory update 14/19 (function unknown)..."));
+            for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
+            writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
+            DEBUG_PRINTLN(F("Writing final memory update 15/19 (function unknown)..."));
+            for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
+            writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
+            DEBUG_PRINTLN(F("Writing final memory update 16/19 (function unknown)..."));
+            for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
+            writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
+            DEBUG_PRINTLN(F("Writing final memory update 17/19 (function unknown)..."));
+            for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
+            writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
+
+            DEBUG_PRINTLN(F("Waiting for FIRO count >= 46..."));
+            while ((fifoCount = getFIFOCount()) < 46);
+            DEBUG_PRINTLN(F("Reading FIFO..."));
+            getFIFOBytes(fifoBuffer, min(fifoCount, 128)); // safeguard only 128 bytes
+            DEBUG_PRINTLN(F("Reading interrupt status..."));
+            getIntStatus();
+
+            DEBUG_PRINTLN(F("Writing final memory update 18/19 (function unknown)..."));
+            for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
+            writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
+
+            DEBUG_PRINTLN(F("Waiting for FIRO count >= 48..."));
+            while ((fifoCount = getFIFOCount()) < 48);
+            DEBUG_PRINTLN(F("Reading FIFO..."));
+            getFIFOBytes(fifoBuffer, min(fifoCount, 128)); // safeguard only 128 bytes
+            DEBUG_PRINTLN(F("Reading interrupt status..."));
+            getIntStatus();
+            DEBUG_PRINTLN(F("Waiting for FIRO count >= 48..."));
+            while ((fifoCount = getFIFOCount()) < 48);
+            DEBUG_PRINTLN(F("Reading FIFO..."));
+            getFIFOBytes(fifoBuffer, min(fifoCount, 128)); // safeguard only 128 bytes
+            DEBUG_PRINTLN(F("Reading interrupt status..."));
+            getIntStatus();
+
+            DEBUG_PRINTLN(F("Writing final memory update 19/19 (function unknown)..."));
+            for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
+            writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
+
+            DEBUG_PRINTLN(F("Disabling DMP (you turn it on later)..."));
+            setDMPEnabled(false);
+
+            DEBUG_PRINTLN(F("Setting up internal 48-byte (default) DMP packet buffer..."));
+            dmpPacketSize = 48;
+            /*if ((dmpPacketBuffer = (uint8_t *)malloc(42)) == 0) {
+                return 3; // TODO: proper error code for no memory
+            }*/
+
+            DEBUG_PRINTLN(F("Resetting FIFO and clearing INT status one last time..."));
+            resetFIFO();
+            getIntStatus();
+        } else {
+            DEBUG_PRINTLN(F("ERROR! DMP configuration verification failed."));
+            return 2; // configuration block loading failed
+        }
+    } else {
+        DEBUG_PRINTLN(F("ERROR! DMP code verification failed."));
+        return 1; // main binary block loading failed
+    }
+    return 0; // success
+}
+
+bool MPU6050::dmpPacketAvailable() {
+    return getFIFOCount() >= dmpGetFIFOPacketSize();
+}
+
+// uint8_t MPU6050::dmpSetFIFORate(uint8_t fifoRate);
+// uint8_t MPU6050::dmpGetFIFORate();
+// uint8_t MPU6050::dmpGetSampleStepSizeMS();
+// uint8_t MPU6050::dmpGetSampleFrequency();
+// int32_t MPU6050::dmpDecodeTemperature(int8_t tempReg);
+
+//uint8_t MPU6050::dmpRegisterFIFORateProcess(inv_obj_func func, int16_t priority);
+//uint8_t MPU6050::dmpUnregisterFIFORateProcess(inv_obj_func func);
+//uint8_t MPU6050::dmpRunFIFORateProcesses();
+
+// uint8_t MPU6050::dmpSendQuaternion(uint_fast16_t accuracy);
+// uint8_t MPU6050::dmpSendGyro(uint_fast16_t elements, uint_fast16_t accuracy);
+// uint8_t MPU6050::dmpSendAccel(uint_fast16_t elements, uint_fast16_t accuracy);
+// uint8_t MPU6050::dmpSendLinearAccel(uint_fast16_t elements, uint_fast16_t accuracy);
+// uint8_t MPU6050::dmpSendLinearAccelInWorld(uint_fast16_t elements, uint_fast16_t accuracy);
+// uint8_t MPU6050::dmpSendControlData(uint_fast16_t elements, uint_fast16_t accuracy);
+// uint8_t MPU6050::dmpSendSensorData(uint_fast16_t elements, uint_fast16_t accuracy);
+// uint8_t MPU6050::dmpSendExternalSensorData(uint_fast16_t elements, uint_fast16_t accuracy);
+// uint8_t MPU6050::dmpSendGravity(uint_fast16_t elements, uint_fast16_t accuracy);
+// uint8_t MPU6050::dmpSendPacketNumber(uint_fast16_t accuracy);
+// uint8_t MPU6050::dmpSendQuantizedAccel(uint_fast16_t elements, uint_fast16_t accuracy);
+// uint8_t MPU6050::dmpSendEIS(uint_fast16_t elements, uint_fast16_t accuracy);
+
+uint8_t MPU6050::dmpGetAccel(int32_t *data, const uint8_t* packet) {
+    // TODO: accommodate different arrangements of sent data (ONLY default supported now)
+    if (packet == 0) packet = dmpPacketBuffer;
+    data[0] = ((packet[34] << 24) + (packet[35] << 16) + (packet[36] << 8) + packet[37]);
+    data[1] = ((packet[38] << 24) + (packet[39] << 16) + (packet[40] << 8) + packet[41]);
+    data[2] = ((packet[42] << 24) + (packet[43] << 16) + (packet[44] << 8) + packet[45]);
+    return 0;
+}
+uint8_t MPU6050::dmpGetAccel(int16_t *data, const uint8_t* packet) {
+    // TODO: accommodate different arrangements of sent data (ONLY default supported now)
+    if (packet == 0) packet = dmpPacketBuffer;
+    data[0] = (packet[34] << 8) + packet[35];
+    data[1] = (packet[38] << 8) + packet[39];
+    data[2] = (packet[42] << 8) + packet[43];
+    return 0;
+}
+uint8_t MPU6050::dmpGetAccel(VectorInt16 *v, const uint8_t* packet) {
+    // TODO: accommodate different arrangements of sent data (ONLY default supported now)
+    if (packet == 0) packet = dmpPacketBuffer;
+    v -> x = (packet[34] << 8) + packet[35];
+    v -> y = (packet[38] << 8) + packet[39];
+    v -> z = (packet[42] << 8) + packet[43];
+    return 0;
+}
+uint8_t MPU6050::dmpGetQuaternion(int32_t *data, const uint8_t* packet) {
+    // TODO: accommodate different arrangements of sent data (ONLY default supported now)
+    if (packet == 0) packet = dmpPacketBuffer;
+    data[0] = ((packet[0] << 24) + (packet[1] << 16) + (packet[2] << 8) + packet[3]);
+    data[1] = ((packet[4] << 24) + (packet[5] << 16) + (packet[6] << 8) + packet[7]);
+    data[2] = ((packet[8] << 24) + (packet[9] << 16) + (packet[10] << 8) + packet[11]);
+    data[3] = ((packet[12] << 24) + (packet[13] << 16) + (packet[14] << 8) + packet[15]);
+    return 0;
+}
+uint8_t MPU6050::dmpGetQuaternion(int16_t *data, const uint8_t* packet) {
+    // TODO: accommodate different arrangements of sent data (ONLY default supported now)
+    if (packet == 0) packet = dmpPacketBuffer;
+    data[0] = ((packet[0] << 8) + packet[1]);
+    data[1] = ((packet[4] << 8) + packet[5]);
+    data[2] = ((packet[8] << 8) + packet[9]);
+    data[3] = ((packet[12] << 8) + packet[13]);
+    return 0;
+}
+uint8_t MPU6050::dmpGetQuaternion(Quaternion *q, const uint8_t* packet) {
+    // TODO: accommodate different arrangements of sent data (ONLY default supported now)
+    int16_t qI[4];
+    uint8_t status = dmpGetQuaternion(qI, packet);
+    if (status == 0) {
+        q -> w = (float)qI[0] / 16384.0f;
+        q -> x = (float)qI[1] / 16384.0f;
+        q -> y = (float)qI[2] / 16384.0f;
+        q -> z = (float)qI[3] / 16384.0f;
+        return 0;
+    }
+    return status; // int16 return value, indicates error if this line is reached
+}
+// uint8_t MPU6050::dmpGet6AxisQuaternion(long *data, const uint8_t* packet);
+// uint8_t MPU6050::dmpGetRelativeQuaternion(long *data, const uint8_t* packet);
+uint8_t MPU6050::dmpGetGyro(int32_t *data, const uint8_t* packet) {
+    // TODO: accommodate different arrangements of sent data (ONLY default supported now)
+    if (packet == 0) packet = dmpPacketBuffer;
+    data[0] = ((packet[16] << 24) + (packet[17] << 16) + (packet[18] << 8) + packet[19]);
+    data[1] = ((packet[20] << 24) + (packet[21] << 16) + (packet[22] << 8) + packet[23]);
+    data[2] = ((packet[24] << 24) + (packet[25] << 16) + (packet[26] << 8) + packet[27]);
+    return 0;
+}
+uint8_t MPU6050::dmpGetGyro(int16_t *data, const uint8_t* packet) {
+    // TODO: accommodate different arrangements of sent data (ONLY default supported now)
+    if (packet == 0) packet = dmpPacketBuffer;
+    data[0] = (packet[16] << 8) + packet[17];
+    data[1] = (packet[20] << 8) + packet[21];
+    data[2] = (packet[24] << 8) + packet[25];
+    return 0;
+}
+uint8_t MPU6050::dmpGetMag(int16_t *data, const uint8_t* packet) {
+    // TODO: accommodate different arrangements of sent data (ONLY default supported now)
+    if (packet == 0) packet = dmpPacketBuffer;
+    data[0] = (packet[28] << 8) + packet[29];
+    data[1] = (packet[30] << 8) + packet[31];
+    data[2] = (packet[32] << 8) + packet[33];
+    return 0;
+}
+// uint8_t MPU6050::dmpSetLinearAccelFilterCoefficient(float coef);
+// uint8_t MPU6050::dmpGetLinearAccel(long *data, const uint8_t* packet);
+uint8_t MPU6050::dmpGetLinearAccel(VectorInt16 *v, VectorInt16 *vRaw, VectorFloat *gravity) {
+    // get rid of the gravity component (+1g = +4096 in standard DMP FIFO packet)
+    v -> x = vRaw -> x - gravity -> x*4096;
+    v -> y = vRaw -> y - gravity -> y*4096;
+    v -> z = vRaw -> z - gravity -> z*4096;
+    return 0;
+}
+// uint8_t MPU6050::dmpGetLinearAccelInWorld(long *data, const uint8_t* packet);
+uint8_t MPU6050::dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Quaternion *q) {
+    // rotate measured 3D acceleration vector into original state
+    // frame of reference based on orientation quaternion
+    memcpy(v, vReal, sizeof(VectorInt16));
+    v -> rotate(q);
+    return 0;
+}
+// uint8_t MPU6050::dmpGetGyroAndAccelSensor(long *data, const uint8_t* packet);
+// uint8_t MPU6050::dmpGetGyroSensor(long *data, const uint8_t* packet);
+// uint8_t MPU6050::dmpGetControlData(long *data, const uint8_t* packet);
+// uint8_t MPU6050::dmpGetTemperature(long *data, const uint8_t* packet);
+// uint8_t MPU6050::dmpGetGravity(long *data, const uint8_t* packet);
+uint8_t MPU6050::dmpGetGravity(VectorFloat *v, Quaternion *q) {
+    v -> x = 2 * (q -> x*q -> z - q -> w*q -> y);
+    v -> y = 2 * (q -> w*q -> x + q -> y*q -> z);
+    v -> z = q -> w*q -> w - q -> x*q -> x - q -> y*q -> y + q -> z*q -> z;
+    return 0;
+}
+// uint8_t MPU6050::dmpGetUnquantizedAccel(long *data, const uint8_t* packet);
+// uint8_t MPU6050::dmpGetQuantizedAccel(long *data, const uint8_t* packet);
+// uint8_t MPU6050::dmpGetExternalSensorData(long *data, int size, const uint8_t* packet);
+// uint8_t MPU6050::dmpGetEIS(long *data, const uint8_t* packet);
+
+uint8_t MPU6050::dmpGetEuler(float *data, Quaternion *q) {
+    data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1);   // psi
+    data[1] = -asin(2*q -> x*q -> z + 2*q -> w*q -> y);                              // theta
+    data[2] = atan2(2*q -> y*q -> z - 2*q -> w*q -> x, 2*q -> w*q -> w + 2*q -> z*q -> z - 1);   // phi
+    return 0;
+}
+uint8_t MPU6050::dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity) {
+    // yaw: (about Z axis)
+    data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1);
+    // pitch: (nose up/down, about Y axis)
+    data[1] = atan(gravity -> x / sqrt(gravity -> y*gravity -> y + gravity -> z*gravity -> z));
+    // roll: (tilt left/right, about X axis)
+    data[2] = atan(gravity -> y / sqrt(gravity -> x*gravity -> x + gravity -> z*gravity -> z));
+    return 0;
+}
+
+// uint8_t MPU6050::dmpGetAccelFloat(float *data, const uint8_t* packet);
+// uint8_t MPU6050::dmpGetQuaternionFloat(float *data, const uint8_t* packet);
+
+uint8_t MPU6050::dmpProcessFIFOPacket(const unsigned char *dmpData) {
+    /*for (uint8_t k = 0; k < dmpPacketSize; k++) {
+        if (dmpData[k] < 0x10) Serial.print("0");
+        Serial.print(dmpData[k], HEX);
+        Serial.print(" ");
+    }
+    Serial.print("\n");*/
+    //Serial.println((uint16_t)dmpPacketBuffer);
+    return 0;
+}
+uint8_t MPU6050::dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *processed) {
+    uint8_t status;
+    uint8_t buf[dmpPacketSize];
+    for (uint8_t i = 0; i < numPackets; i++) {
+        // read packet from FIFO
+        getFIFOBytes(buf, dmpPacketSize);
+
+        // process packet
+        if ((status = dmpProcessFIFOPacket(buf)) > 0) return status;
+        
+        // increment external process count variable, if supplied
+        if (processed != 0) *processed++;
+    }
+    return 0;
+}
+
+// uint8_t MPU6050::dmpSetFIFOProcessedCallback(void (*func) (void));
+
+// uint8_t MPU6050::dmpInitFIFOParam();
+// uint8_t MPU6050::dmpCloseFIFO();
+// uint8_t MPU6050::dmpSetGyroDataSource(uint_fast8_t source);
+// uint8_t MPU6050::dmpDecodeQuantizedAccel();
+// uint32_t MPU6050::dmpGetGyroSumOfSquare();
+// uint32_t MPU6050::dmpGetAccelSumOfSquare();
+// void MPU6050::dmpOverrideQuaternion(long *q);
+uint16_t MPU6050::dmpGetFIFOPacketSize() {
+    return dmpPacketSize;
+}
+
+#endif /* _MPU6050_9AXIS_MOTIONAPPS41_H_ */
diff --git a/Arduino/MPU9150/helper_3dmath.h b/Arduino/MPU9150/helper_3dmath.h
new file mode 100644
index 00000000..9ed260ec
--- /dev/null
+++ b/Arduino/MPU9150/helper_3dmath.h
@@ -0,0 +1,216 @@
+// I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class, 3D math helper
+// 6/5/2012 by Jeff Rowberg 
+// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
+//
+// Changelog:
+//     2012-06-05 - add 3D math helper file to DMP6 example sketch
+
+/* ============================================
+I2Cdev device library code is placed under the MIT license
+Copyright (c) 2012 Jeff Rowberg
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+===============================================
+*/
+
+#ifndef _HELPER_3DMATH_H_
+#define _HELPER_3DMATH_H_
+
+class Quaternion {
+    public:
+        float w;
+        float x;
+        float y;
+        float z;
+        
+        Quaternion() {
+            w = 1.0f;
+            x = 0.0f;
+            y = 0.0f;
+            z = 0.0f;
+        }
+        
+        Quaternion(float nw, float nx, float ny, float nz) {
+            w = nw;
+            x = nx;
+            y = ny;
+            z = nz;
+        }
+
+        Quaternion getProduct(Quaternion q) {
+            // Quaternion multiplication is defined by:
+            //     (Q1 * Q2).w = (w1w2 - x1x2 - y1y2 - z1z2)
+            //     (Q1 * Q2).x = (w1x2 + x1w2 + y1z2 - z1y2)
+            //     (Q1 * Q2).y = (w1y2 - x1z2 + y1w2 + z1x2)
+            //     (Q1 * Q2).z = (w1z2 + x1y2 - y1x2 + z1w2
+            return Quaternion(
+                w*q.w - x*q.x - y*q.y - z*q.z,  // new w
+                w*q.x + x*q.w + y*q.z - z*q.y,  // new x
+                w*q.y - x*q.z + y*q.w + z*q.x,  // new y
+                w*q.z + x*q.y - y*q.x + z*q.w); // new z
+        }
+
+        Quaternion getConjugate() {
+            return Quaternion(w, -x, -y, -z);
+        }
+        
+        float getMagnitude() {
+            return sqrt(w*w + x*x + y*y + z*z);
+        }
+        
+        void normalize() {
+            float m = getMagnitude();
+            w /= m;
+            x /= m;
+            y /= m;
+            z /= m;
+        }
+        
+        Quaternion getNormalized() {
+            Quaternion r(w, x, y, z);
+            r.normalize();
+            return r;
+        }
+};
+
+class VectorInt16 {
+    public:
+        int16_t x;
+        int16_t y;
+        int16_t z;
+
+        VectorInt16() {
+            x = 0;
+            y = 0;
+            z = 0;
+        }
+        
+        VectorInt16(int16_t nx, int16_t ny, int16_t nz) {
+            x = nx;
+            y = ny;
+            z = nz;
+        }
+
+        float getMagnitude() {
+            return sqrt(x*x + y*y + z*z);
+        }
+
+        void normalize() {
+            float m = getMagnitude();
+            x /= m;
+            y /= m;
+            z /= m;
+        }
+        
+        VectorInt16 getNormalized() {
+            VectorInt16 r(x, y, z);
+            r.normalize();
+            return r;
+        }
+        
+        void rotate(Quaternion *q) {
+            // http://www.cprogramming.com/tutorial/3d/quaternions.html
+            // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/transforms/index.htm
+            // http://content.gpwiki.org/index.php/OpenGL:Tutorials:Using_Quaternions_to_represent_rotation
+            // ^ or: http://webcache.googleusercontent.com/search?q=cache:xgJAp3bDNhQJ:content.gpwiki.org/index.php/OpenGL:Tutorials:Using_Quaternions_to_represent_rotation&hl=en&gl=us&strip=1
+        
+            // P_out = q * P_in * conj(q)
+            // - P_out is the output vector
+            // - q is the orientation quaternion
+            // - P_in is the input vector (a*aReal)
+            // - conj(q) is the conjugate of the orientation quaternion (q=[w,x,y,z], q*=[w,-x,-y,-z])
+            Quaternion p(0, x, y, z);
+
+            // quaternion multiplication: q * p, stored back in p
+            p = q -> getProduct(p);
+
+            // quaternion multiplication: p * conj(q), stored back in p
+            p = p.getProduct(q -> getConjugate());
+
+            // p quaternion is now [0, x', y', z']
+            x = p.x;
+            y = p.y;
+            z = p.z;
+        }
+
+        VectorInt16 getRotated(Quaternion *q) {
+            VectorInt16 r(x, y, z);
+            r.rotate(q);
+            return r;
+        }
+};
+
+class VectorFloat {
+    public:
+        float x;
+        float y;
+        float z;
+
+        VectorFloat() {
+            x = 0;
+            y = 0;
+            z = 0;
+        }
+        
+        VectorFloat(float nx, float ny, float nz) {
+            x = nx;
+            y = ny;
+            z = nz;
+        }
+
+        float getMagnitude() {
+            return sqrt(x*x + y*y + z*z);
+        }
+
+        void normalize() {
+            float m = getMagnitude();
+            x /= m;
+            y /= m;
+            z /= m;
+        }
+        
+        VectorFloat getNormalized() {
+            VectorFloat r(x, y, z);
+            r.normalize();
+            return r;
+        }
+        
+        void rotate(Quaternion *q) {
+            Quaternion p(0, x, y, z);
+
+            // quaternion multiplication: q * p, stored back in p
+            p = q -> getProduct(p);
+
+            // quaternion multiplication: p * conj(q), stored back in p
+            p = p.getProduct(q -> getConjugate());
+
+            // p quaternion is now [0, x', y', z']
+            x = p.x;
+            y = p.y;
+            z = p.z;
+        }
+
+        VectorFloat getRotated(Quaternion *q) {
+            VectorFloat r(x, y, z);
+            r.rotate(q);
+            return r;
+        }
+};
+
+#endif /* _HELPER_3DMATH_H_ */
\ No newline at end of file

From 5cfbb3bbc6e011195b3073dbf6aea6cf999abddf Mon Sep 17 00:00:00 2001
From: Cedric Honnet 
Date: Thu, 13 Feb 2014 16:25:48 -0800
Subject: [PATCH 005/335] Add magnetometer capabilities (MPU-9150).

---
 .../Examples/MPU9150_raw/MPU9150_raw.ino      | 108 ++++++++++++++++++
 Arduino/MPU9150/MPU6050.cpp                   |  13 ++-
 Arduino/MPU9150/MPU6050.h                     |   8 ++
 3 files changed, 128 insertions(+), 1 deletion(-)
 create mode 100644 Arduino/MPU9150/Examples/MPU9150_raw/MPU9150_raw.ino

diff --git a/Arduino/MPU9150/Examples/MPU9150_raw/MPU9150_raw.ino b/Arduino/MPU9150/Examples/MPU9150_raw/MPU9150_raw.ino
new file mode 100644
index 00000000..f885cde1
--- /dev/null
+++ b/Arduino/MPU9150/Examples/MPU9150_raw/MPU9150_raw.ino
@@ -0,0 +1,108 @@
+// I2C device class (I2Cdev) demonstration Arduino sketch for MPU9150
+// 1/4/2013 original by Jeff Rowberg  at https://github.com/jrowberg/i2cdevlib
+//          modified by Aaron Weiss 
+//
+// Changelog:
+//     2011-10-07 - initial release
+//     2013-1-4 - added raw magnetometer output
+
+/* ============================================
+I2Cdev device library code is placed under the MIT license
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+===============================================
+*/
+
+// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation
+// is used in I2Cdev.h
+#include "Wire.h"
+
+// I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files
+// for both classes must be in the include path of your project
+#include "I2Cdev.h"
+#include "MPU6050.h"
+#include "helper_3dmath.h"
+
+// class default I2C address is 0x68
+// specific I2C addresses may be passed as a parameter here
+// AD0 low = 0x68 (default for InvenSense evaluation board)
+// AD0 high = 0x69
+MPU6050 accelGyroMag;
+
+int16_t ax, ay, az;
+int16_t gx, gy, gz;
+int16_t mx, my, mz;
+
+#define LED_PIN 13
+bool blinkState = false;
+
+void setup() {
+    // join I2C bus (I2Cdev library doesn't do this automatically)
+    Wire.begin();
+
+    // initialize serial communication
+    // (38400 chosen because it works as well at 8MHz as it does at 16MHz, but
+    // it's really up to you depending on your project)
+    Serial.begin(115200);
+
+    // initialize device
+    Serial.println("Initializing I2C devices...");
+    accelGyroMag.initialize();
+
+    // verify connection
+    Serial.println("Testing device connections...");
+    Serial.println(accelGyroMag.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed");
+
+    // configure Arduino LED for
+    pinMode(LED_PIN, OUTPUT);
+}
+
+void loop() {
+    // read raw accel/gyro/mag measurements from device
+    accelGyroMag.getMotion9(&ax, &ay, &az, &gx, &gy, &gz, &mx, &my, &mz);
+
+    // these methods (and a few others) are also available
+    //accelGyroMag.getAcceleration(&ax, &ay, &az);
+    //accelGyroMag.getRotation(&gx, &gy, &gz);
+
+    // display tab-separated accel/gyro/mag x/y/z values
+//  Serial.print("a/g/m:\t");
+//  Serial.print(ax); Serial.print("\t");
+//  Serial.print(ay); Serial.print("\t");
+//  Serial.print(az); Serial.print("\t");
+//  Serial.print(gx); Serial.print("\t");
+//  Serial.print(gy); Serial.print("\t");
+//  Serial.print(gz); Serial.print("\t");
+    Serial.print(int(mx)*int(mx)); Serial.print("\t");
+    Serial.print(int(my)*int(my)); Serial.print("\t");
+    Serial.print(int(mz)*int(mz)); Serial.print("\t | ");
+
+    const float N = 256;
+    float mag = mx*mx/N + my*my/N + mz*mz/N;
+
+    Serial.print(mag); Serial.print("\t");
+    for (int i=0; i
Date: Thu, 13 Feb 2014 16:35:27 -0800
Subject: [PATCH 006/335] WIP: Rename files MPU6050 -> MPU9150.

---
 .../Examples/MPU6050_raw/MPU6050_raw.ino      | 151 ------------------
 .../MPU9150_DMP6.ino}                         |   0
 .../Processing/MPUTeapot.pde                  |   0
 Arduino/MPU9150/{MPU6050.cpp => MPU9150.cpp}  |   0
 Arduino/MPU9150/{MPU6050.h => MPU9150.h}      |   0
 ...nApps20.h => MPU9150_6Axis_MotionApps20.h} |   0
 ...nApps41.h => MPU9150_9Axis_MotionApps41.h} |   0
 7 files changed, 151 deletions(-)
 delete mode 100644 Arduino/MPU9150/Examples/MPU6050_raw/MPU6050_raw.ino
 rename Arduino/MPU9150/Examples/{MPU6050_DMP6/MPU6050_DMP6.ino => MPU9150_DMP6/MPU9150_DMP6.ino} (100%)
 rename Arduino/MPU9150/Examples/{MPU6050_DMP6 => MPU9150_DMP6}/Processing/MPUTeapot.pde (100%)
 rename Arduino/MPU9150/{MPU6050.cpp => MPU9150.cpp} (100%)
 rename Arduino/MPU9150/{MPU6050.h => MPU9150.h} (100%)
 rename Arduino/MPU9150/{MPU6050_6Axis_MotionApps20.h => MPU9150_6Axis_MotionApps20.h} (100%)
 rename Arduino/MPU9150/{MPU6050_9Axis_MotionApps41.h => MPU9150_9Axis_MotionApps41.h} (100%)

diff --git a/Arduino/MPU9150/Examples/MPU6050_raw/MPU6050_raw.ino b/Arduino/MPU9150/Examples/MPU6050_raw/MPU6050_raw.ino
deleted file mode 100644
index 28418a96..00000000
--- a/Arduino/MPU9150/Examples/MPU6050_raw/MPU6050_raw.ino
+++ /dev/null
@@ -1,151 +0,0 @@
-// I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class
-// 10/7/2011 by Jeff Rowberg 
-// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
-//
-// Changelog:
-//      2013-05-08 - added multiple output formats
-//                 - added seamless Fastwire support
-//      2011-10-07 - initial release
-
-/* ============================================
-I2Cdev device library code is placed under the MIT license
-Copyright (c) 2011 Jeff Rowberg
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-===============================================
-*/
-
-// I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files
-// for both classes must be in the include path of your project
-#include "I2Cdev.h"
-#include "MPU6050.h"
-
-// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation
-// is used in I2Cdev.h
-#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
-    #include "Wire.h"
-#endif
-
-// class default I2C address is 0x68
-// specific I2C addresses may be passed as a parameter here
-// AD0 low = 0x68 (default for InvenSense evaluation board)
-// AD0 high = 0x69
-MPU6050 accelgyro;
-//MPU6050 accelgyro(0x69); // <-- use for AD0 high
-
-int16_t ax, ay, az;
-int16_t gx, gy, gz;
-
-
-
-// uncomment "OUTPUT_READABLE_ACCELGYRO" if you want to see a tab-separated
-// list of the accel X/Y/Z and then gyro X/Y/Z values in decimal. Easy to read,
-// not so easy to parse, and slow(er) over UART.
-#define OUTPUT_READABLE_ACCELGYRO
-
-// uncomment "OUTPUT_BINARY_ACCELGYRO" to send all 6 axes of data as 16-bit
-// binary, one right after the other. This is very fast (as fast as possible
-// without compression or data loss), and easy to parse, but impossible to read
-// for a human.
-//#define OUTPUT_BINARY_ACCELGYRO
-
-
-#define LED_PIN 13
-bool blinkState = false;
-
-void setup() {
-    // join I2C bus (I2Cdev library doesn't do this automatically)
-    #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
-        Wire.begin();
-    #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
-        Fastwire::setup(400, true);
-    #endif
-
-    // initialize serial communication
-    // (38400 chosen because it works as well at 8MHz as it does at 16MHz, but
-    // it's really up to you depending on your project)
-    Serial.begin(38400);
-
-    // initialize device
-    Serial.println("Initializing I2C devices...");
-    accelgyro.initialize();
-
-    // verify connection
-    Serial.println("Testing device connections...");
-    Serial.println(accelgyro.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed");
-
-    // use the code below to change accel/gyro offset values
-    /*
-    Serial.println("Updating internal sensor offsets...");
-    // -76	-2359	1688	0	0	0
-    Serial.print(accelgyro.getXAccelOffset()); Serial.print("\t"); // -76
-    Serial.print(accelgyro.getYAccelOffset()); Serial.print("\t"); // -2359
-    Serial.print(accelgyro.getZAccelOffset()); Serial.print("\t"); // 1688
-    Serial.print(accelgyro.getXGyroOffset()); Serial.print("\t"); // 0
-    Serial.print(accelgyro.getYGyroOffset()); Serial.print("\t"); // 0
-    Serial.print(accelgyro.getZGyroOffset()); Serial.print("\t"); // 0
-    Serial.print("\n");
-    accelgyro.setXGyroOffset(220);
-    accelgyro.setYGyroOffset(76);
-    accelgyro.setZGyroOffset(-85);
-    Serial.print(accelgyro.getXAccelOffset()); Serial.print("\t"); // -76
-    Serial.print(accelgyro.getYAccelOffset()); Serial.print("\t"); // -2359
-    Serial.print(accelgyro.getZAccelOffset()); Serial.print("\t"); // 1688
-    Serial.print(accelgyro.getXGyroOffset()); Serial.print("\t"); // 0
-    Serial.print(accelgyro.getYGyroOffset()); Serial.print("\t"); // 0
-    Serial.print(accelgyro.getZGyroOffset()); Serial.print("\t"); // 0
-    Serial.print("\n");
-    */
-
-    // configure Arduino LED for
-    pinMode(LED_PIN, OUTPUT);
-}
-
-void loop() {
-    // read raw accel/gyro measurements from device
-    accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
-
-    // these methods (and a few others) are also available
-    //accelgyro.getAcceleration(&ax, &ay, &az);
-    //accelgyro.getRotation(&gx, &gy, &gz);
-
-    #ifdef OUTPUT_READABLE_ACCELGYRO
-        // display tab-separated accel/gyro x/y/z values
-        Serial.print("a/g:\t");
-        Serial.print(ax); Serial.print("\t");
-        Serial.print(ay); Serial.print("\t");
-        Serial.print(az); Serial.print("\t");
-        Serial.print(gx); Serial.print("\t");
-        Serial.print(gy); Serial.print("\t");
-        Serial.println(gz);
-    #endif
-
-    #ifdef OUTPUT_BINARY_ACCELGYRO
-        Serial.write((uint8_t)(ax >> 8)); Serial.write((uint8_t)(ax & 0xFF));
-        Serial.write((uint8_t)(ay >> 8)); Serial.write((uint8_t)(ay & 0xFF));
-        Serial.write((uint8_t)(az >> 8)); Serial.write((uint8_t)(az & 0xFF));
-        Serial.write((uint8_t)(gx >> 8)); Serial.write((uint8_t)(gx & 0xFF));
-        Serial.write((uint8_t)(gy >> 8)); Serial.write((uint8_t)(gy & 0xFF));
-        Serial.write((uint8_t)(gz >> 8)); Serial.write((uint8_t)(gz & 0xFF));
-    #endif
-
-    // blink LED to indicate activity
-    blinkState = !blinkState;
-    digitalWrite(LED_PIN, blinkState);
-}
diff --git a/Arduino/MPU9150/Examples/MPU6050_DMP6/MPU6050_DMP6.ino b/Arduino/MPU9150/Examples/MPU9150_DMP6/MPU9150_DMP6.ino
similarity index 100%
rename from Arduino/MPU9150/Examples/MPU6050_DMP6/MPU6050_DMP6.ino
rename to Arduino/MPU9150/Examples/MPU9150_DMP6/MPU9150_DMP6.ino
diff --git a/Arduino/MPU9150/Examples/MPU6050_DMP6/Processing/MPUTeapot.pde b/Arduino/MPU9150/Examples/MPU9150_DMP6/Processing/MPUTeapot.pde
similarity index 100%
rename from Arduino/MPU9150/Examples/MPU6050_DMP6/Processing/MPUTeapot.pde
rename to Arduino/MPU9150/Examples/MPU9150_DMP6/Processing/MPUTeapot.pde
diff --git a/Arduino/MPU9150/MPU6050.cpp b/Arduino/MPU9150/MPU9150.cpp
similarity index 100%
rename from Arduino/MPU9150/MPU6050.cpp
rename to Arduino/MPU9150/MPU9150.cpp
diff --git a/Arduino/MPU9150/MPU6050.h b/Arduino/MPU9150/MPU9150.h
similarity index 100%
rename from Arduino/MPU9150/MPU6050.h
rename to Arduino/MPU9150/MPU9150.h
diff --git a/Arduino/MPU9150/MPU6050_6Axis_MotionApps20.h b/Arduino/MPU9150/MPU9150_6Axis_MotionApps20.h
similarity index 100%
rename from Arduino/MPU9150/MPU6050_6Axis_MotionApps20.h
rename to Arduino/MPU9150/MPU9150_6Axis_MotionApps20.h
diff --git a/Arduino/MPU9150/MPU6050_9Axis_MotionApps41.h b/Arduino/MPU9150/MPU9150_9Axis_MotionApps41.h
similarity index 100%
rename from Arduino/MPU9150/MPU6050_9Axis_MotionApps41.h
rename to Arduino/MPU9150/MPU9150_9Axis_MotionApps41.h

From 2e274737ba77984b9308bb29b179a3c9c00c5adc Mon Sep 17 00:00:00 2001
From: Cedric Honnet 
Date: Thu, 13 Feb 2014 16:41:12 -0800
Subject: [PATCH 007/335] Automatic sed substitute: MPU9150 -> MPU6050.

---
 .../Examples/MPU9150_DMP6/MPU9150_DMP6.ino    |   16 +-
 .../MPU9150_DMP6/Processing/MPUTeapot.pde     |    4 +-
 .../Examples/MPU9150_raw/MPU9150_raw.ino      |    8 +-
 Arduino/MPU9150/MPU9150.cpp                   | 1680 ++++++++---------
 Arduino/MPU9150/MPU9150.h                     |  720 +++----
 Arduino/MPU9150/MPU9150_6Axis_MotionApps20.h  |  176 +-
 Arduino/MPU9150/MPU9150_9Axis_MotionApps41.h  |  212 +--
 Arduino/MPU9150/helper_3dmath.h               |    2 +-
 8 files changed, 1409 insertions(+), 1409 deletions(-)

diff --git a/Arduino/MPU9150/Examples/MPU9150_DMP6/MPU9150_DMP6.ino b/Arduino/MPU9150/Examples/MPU9150_DMP6/MPU9150_DMP6.ino
index be24ffd5..ba2b0f48 100644
--- a/Arduino/MPU9150/Examples/MPU9150_DMP6/MPU9150_DMP6.ino
+++ b/Arduino/MPU9150/Examples/MPU9150_DMP6/MPU9150_DMP6.ino
@@ -1,4 +1,4 @@
-// I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class using DMP (MotionApps v2.0)
+// I2C device class (I2Cdev) demonstration Arduino sketch for MPU9150 class using DMP (MotionApps v2.0)
 // 6/21/2012 by Jeff Rowberg 
 // Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
 //
@@ -41,12 +41,12 @@ THE SOFTWARE.
 ===============================================
 */
 
-// I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files
+// I2Cdev and MPU9150 must be installed as libraries, or else the .cpp/.h files
 // for both classes must be in the include path of your project
 #include "I2Cdev.h"
 
-#include "MPU6050_6Axis_MotionApps20.h"
-//#include "MPU6050.h" // not necessary if using MotionApps include file
+#include "MPU9150_6Axis_MotionApps20.h"
+//#include "MPU9150.h" // not necessary if using MotionApps include file
 
 // Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation
 // is used in I2Cdev.h
@@ -58,12 +58,12 @@ THE SOFTWARE.
 // specific I2C addresses may be passed as a parameter here
 // AD0 low = 0x68 (default for SparkFun breakout and InvenSense evaluation board)
 // AD0 high = 0x69
-MPU6050 mpu;
-//MPU6050 mpu(0x69); // <-- use for AD0 high
+MPU9150 mpu;
+//MPU9150 mpu(0x69); // <-- use for AD0 high
 
 /* =========================================================================
    NOTE: In addition to connection 3.3v, GND, SDA, and SCL, this sketch
-   depends on the MPU-6050's INT pin being connected to the Arduino's
+   depends on the MPU-9150's INT pin being connected to the Arduino's
    external interrupt #0 pin. On the Arduino Uno and Mega 2560, this is
    digital I/O pin 2.
  * ========================================================================= */
@@ -185,7 +185,7 @@ void setup() {
 
     // verify connection
     Serial.println(F("Testing device connections..."));
-    Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));
+    Serial.println(mpu.testConnection() ? F("MPU9150 connection successful") : F("MPU9150 connection failed"));
 
     // wait for ready
     Serial.println(F("\nSend any character to begin DMP programming and demo: "));
diff --git a/Arduino/MPU9150/Examples/MPU9150_DMP6/Processing/MPUTeapot.pde b/Arduino/MPU9150/Examples/MPU9150_DMP6/Processing/MPUTeapot.pde
index d4c32daf..ed510f9b 100644
--- a/Arduino/MPU9150/Examples/MPU9150_DMP6/Processing/MPUTeapot.pde
+++ b/Arduino/MPU9150/Examples/MPU9150_DMP6/Processing/MPUTeapot.pde
@@ -1,4 +1,4 @@
-// I2C device class (I2Cdev) demonstration Processing sketch for MPU6050 DMP output
+// I2C device class (I2Cdev) demonstration Processing sketch for MPU9150 DMP output
 // 6/20/2012 by Jeff Rowberg 
 // Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
 //
@@ -77,7 +77,7 @@ void setup() {
     port = new Serial(this, portName, 115200);
     
     // send single character to trigger DMP init/start
-    // (expected by MPU6050_DMP6 example Arduino sketch)
+    // (expected by MPU9150_DMP6 example Arduino sketch)
     port.write('r');
 }
 
diff --git a/Arduino/MPU9150/Examples/MPU9150_raw/MPU9150_raw.ino b/Arduino/MPU9150/Examples/MPU9150_raw/MPU9150_raw.ino
index f885cde1..e2c9224c 100644
--- a/Arduino/MPU9150/Examples/MPU9150_raw/MPU9150_raw.ino
+++ b/Arduino/MPU9150/Examples/MPU9150_raw/MPU9150_raw.ino
@@ -33,17 +33,17 @@ THE SOFTWARE.
 // is used in I2Cdev.h
 #include "Wire.h"
 
-// I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files
+// I2Cdev and MPU9150 must be installed as libraries, or else the .cpp/.h files
 // for both classes must be in the include path of your project
 #include "I2Cdev.h"
-#include "MPU6050.h"
+#include "MPU9150.h"
 #include "helper_3dmath.h"
 
 // class default I2C address is 0x68
 // specific I2C addresses may be passed as a parameter here
 // AD0 low = 0x68 (default for InvenSense evaluation board)
 // AD0 high = 0x69
-MPU6050 accelGyroMag;
+MPU9150 accelGyroMag;
 
 int16_t ax, ay, az;
 int16_t gx, gy, gz;
@@ -67,7 +67,7 @@ void setup() {
 
     // verify connection
     Serial.println("Testing device connections...");
-    Serial.println(accelGyroMag.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed");
+    Serial.println(accelGyroMag.testConnection() ? "MPU9150 connection successful" : "MPU9150 connection failed");
 
     // configure Arduino LED for
     pinMode(LED_PIN, OUTPUT);
diff --git a/Arduino/MPU9150/MPU9150.cpp b/Arduino/MPU9150/MPU9150.cpp
index 1360fc24..09d10c78 100644
--- a/Arduino/MPU9150/MPU9150.cpp
+++ b/Arduino/MPU9150/MPU9150.cpp
@@ -1,5 +1,5 @@
-// I2Cdev library collection - MPU6050 I2C device class
-// Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00)
+// I2Cdev library collection - MPU9150 I2C device class
+// Based on InvenSense MPU-9150 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00)
 // 8/24/2011 by Jeff Rowberg 
 // Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
 //
@@ -34,22 +34,22 @@ THE SOFTWARE.
 ===============================================
 */
 
-#include "MPU6050.h"
+#include "MPU9150.h"
 
 /** Default constructor, uses default I2C address.
- * @see MPU6050_DEFAULT_ADDRESS
+ * @see MPU9150_DEFAULT_ADDRESS
  */
-MPU6050::MPU6050() {
-    devAddr = MPU6050_DEFAULT_ADDRESS;
+MPU9150::MPU9150() {
+    devAddr = MPU9150_DEFAULT_ADDRESS;
 }
 
 /** Specific address constructor.
  * @param address I2C address
- * @see MPU6050_DEFAULT_ADDRESS
- * @see MPU6050_ADDRESS_AD0_LOW
- * @see MPU6050_ADDRESS_AD0_HIGH
+ * @see MPU9150_DEFAULT_ADDRESS
+ * @see MPU9150_ADDRESS_AD0_LOW
+ * @see MPU9150_ADDRESS_AD0_HIGH
  */
-MPU6050::MPU6050(uint8_t address) {
+MPU9150::MPU9150(uint8_t address) {
     devAddr = address;
 }
 
@@ -60,10 +60,10 @@ MPU6050::MPU6050(uint8_t address) {
  * the clock source to use the X Gyro for reference, which is slightly better than
  * the default internal clock source.
  */
-void MPU6050::initialize() {
-    setClockSource(MPU6050_CLOCK_PLL_XGYRO);
-    setFullScaleGyroRange(MPU6050_GYRO_FS_250);
-    setFullScaleAccelRange(MPU6050_ACCEL_FS_2);
+void MPU9150::initialize() {
+    setClockSource(MPU9150_CLOCK_PLL_XGYRO);
+    setFullScaleGyroRange(MPU9150_GYRO_FS_250);
+    setFullScaleAccelRange(MPU9150_ACCEL_FS_2);
     setSleepEnabled(false); // thanks to Jack Elston for pointing this one out!
 }
 
@@ -71,7 +71,7 @@ void MPU6050::initialize() {
  * Make sure the device is connected and responds as expected.
  * @return True if connection is valid, false otherwise
  */
-bool MPU6050::testConnection() {
+bool MPU9150::testConnection() {
     return getDeviceID() == 0x34;
 }
 
@@ -83,8 +83,8 @@ bool MPU6050::testConnection() {
  * the MPU-6000, which does not have a VLOGIC pin.
  * @return I2C supply voltage level (0=VLOGIC, 1=VDD)
  */
-uint8_t MPU6050::getAuxVDDIOLevel() {
-    I2Cdev::readBit(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_PWR_MODE_BIT, buffer);
+uint8_t MPU9150::getAuxVDDIOLevel() {
+    I2Cdev::readBit(devAddr, MPU9150_RA_YG_OFFS_TC, MPU9150_TC_PWR_MODE_BIT, buffer);
     return buffer[0];
 }
 /** Set the auxiliary I2C supply voltage level.
@@ -93,8 +93,8 @@ uint8_t MPU6050::getAuxVDDIOLevel() {
  * the MPU-6000, which does not have a VLOGIC pin.
  * @param level I2C supply voltage level (0=VLOGIC, 1=VDD)
  */
-void MPU6050::setAuxVDDIOLevel(uint8_t level) {
-    I2Cdev::writeBit(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_PWR_MODE_BIT, level);
+void MPU9150::setAuxVDDIOLevel(uint8_t level) {
+    I2Cdev::writeBit(devAddr, MPU9150_RA_YG_OFFS_TC, MPU9150_TC_PWR_MODE_BIT, level);
 }
 
 // SMPLRT_DIV register
@@ -115,22 +115,22 @@ void MPU6050::setAuxVDDIOLevel(uint8_t level) {
  * FIFO, DMP, and sensor registers more than once.
  *
  * For a diagram of the gyroscope and accelerometer signal paths, see Section 8
- * of the MPU-6000/MPU-6050 Product Specification document.
+ * of the MPU-6000/MPU-9150 Product Specification document.
  *
  * @return Current sample rate
- * @see MPU6050_RA_SMPLRT_DIV
+ * @see MPU9150_RA_SMPLRT_DIV
  */
-uint8_t MPU6050::getRate() {
-    I2Cdev::readByte(devAddr, MPU6050_RA_SMPLRT_DIV, buffer);
+uint8_t MPU9150::getRate() {
+    I2Cdev::readByte(devAddr, MPU9150_RA_SMPLRT_DIV, buffer);
     return buffer[0];
 }
 /** Set gyroscope sample rate divider.
  * @param rate New sample rate divider
  * @see getRate()
- * @see MPU6050_RA_SMPLRT_DIV
+ * @see MPU9150_RA_SMPLRT_DIV
  */
-void MPU6050::setRate(uint8_t rate) {
-    I2Cdev::writeByte(devAddr, MPU6050_RA_SMPLRT_DIV, rate);
+void MPU9150::setRate(uint8_t rate) {
+    I2Cdev::writeByte(devAddr, MPU9150_RA_SMPLRT_DIV, rate);
 }
 
 // CONFIG register
@@ -162,17 +162,17 @@ void MPU6050::setRate(uint8_t rate) {
  *
  * @return FSYNC configuration value
  */
-uint8_t MPU6050::getExternalFrameSync() {
-    I2Cdev::readBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_EXT_SYNC_SET_BIT, MPU6050_CFG_EXT_SYNC_SET_LENGTH, buffer);
+uint8_t MPU9150::getExternalFrameSync() {
+    I2Cdev::readBits(devAddr, MPU9150_RA_CONFIG, MPU9150_CFG_EXT_SYNC_SET_BIT, MPU9150_CFG_EXT_SYNC_SET_LENGTH, buffer);
     return buffer[0];
 }
 /** Set external FSYNC configuration.
  * @see getExternalFrameSync()
- * @see MPU6050_RA_CONFIG
+ * @see MPU9150_RA_CONFIG
  * @param sync New FSYNC configuration value
  */
-void MPU6050::setExternalFrameSync(uint8_t sync) {
-    I2Cdev::writeBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_EXT_SYNC_SET_BIT, MPU6050_CFG_EXT_SYNC_SET_LENGTH, sync);
+void MPU9150::setExternalFrameSync(uint8_t sync) {
+    I2Cdev::writeBits(devAddr, MPU9150_RA_CONFIG, MPU9150_CFG_EXT_SYNC_SET_BIT, MPU9150_CFG_EXT_SYNC_SET_LENGTH, sync);
 }
 /** Get digital low-pass filter configuration.
  * The DLPF_CFG parameter sets the digital low pass filter configuration. It
@@ -198,24 +198,24 @@ void MPU6050::setExternalFrameSync(uint8_t sync) {
  * 
* * @return DLFP configuration - * @see MPU6050_RA_CONFIG - * @see MPU6050_CFG_DLPF_CFG_BIT - * @see MPU6050_CFG_DLPF_CFG_LENGTH + * @see MPU9150_RA_CONFIG + * @see MPU9150_CFG_DLPF_CFG_BIT + * @see MPU9150_CFG_DLPF_CFG_LENGTH */ -uint8_t MPU6050::getDLPFMode() { - I2Cdev::readBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_DLPF_CFG_BIT, MPU6050_CFG_DLPF_CFG_LENGTH, buffer); +uint8_t MPU9150::getDLPFMode() { + I2Cdev::readBits(devAddr, MPU9150_RA_CONFIG, MPU9150_CFG_DLPF_CFG_BIT, MPU9150_CFG_DLPF_CFG_LENGTH, buffer); return buffer[0]; } /** Set digital low-pass filter configuration. * @param mode New DLFP configuration setting * @see getDLPFBandwidth() - * @see MPU6050_DLPF_BW_256 - * @see MPU6050_RA_CONFIG - * @see MPU6050_CFG_DLPF_CFG_BIT - * @see MPU6050_CFG_DLPF_CFG_LENGTH + * @see MPU9150_DLPF_BW_256 + * @see MPU9150_RA_CONFIG + * @see MPU9150_CFG_DLPF_CFG_BIT + * @see MPU9150_CFG_DLPF_CFG_LENGTH */ -void MPU6050::setDLPFMode(uint8_t mode) { - I2Cdev::writeBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_DLPF_CFG_BIT, MPU6050_CFG_DLPF_CFG_LENGTH, mode); +void MPU9150::setDLPFMode(uint8_t mode) { + I2Cdev::writeBits(devAddr, MPU9150_RA_CONFIG, MPU9150_CFG_DLPF_CFG_BIT, MPU9150_CFG_DLPF_CFG_LENGTH, mode); } // GYRO_CONFIG register @@ -232,73 +232,73 @@ void MPU6050::setDLPFMode(uint8_t mode) { *
* * @return Current full-scale gyroscope range setting - * @see MPU6050_GYRO_FS_250 - * @see MPU6050_RA_GYRO_CONFIG - * @see MPU6050_GCONFIG_FS_SEL_BIT - * @see MPU6050_GCONFIG_FS_SEL_LENGTH + * @see MPU9150_GYRO_FS_250 + * @see MPU9150_RA_GYRO_CONFIG + * @see MPU9150_GCONFIG_FS_SEL_BIT + * @see MPU9150_GCONFIG_FS_SEL_LENGTH */ -uint8_t MPU6050::getFullScaleGyroRange() { - I2Cdev::readBits(devAddr, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, buffer); +uint8_t MPU9150::getFullScaleGyroRange() { + I2Cdev::readBits(devAddr, MPU9150_RA_GYRO_CONFIG, MPU9150_GCONFIG_FS_SEL_BIT, MPU9150_GCONFIG_FS_SEL_LENGTH, buffer); return buffer[0]; } /** Set full-scale gyroscope range. * @param range New full-scale gyroscope range value * @see getFullScaleRange() - * @see MPU6050_GYRO_FS_250 - * @see MPU6050_RA_GYRO_CONFIG - * @see MPU6050_GCONFIG_FS_SEL_BIT - * @see MPU6050_GCONFIG_FS_SEL_LENGTH + * @see MPU9150_GYRO_FS_250 + * @see MPU9150_RA_GYRO_CONFIG + * @see MPU9150_GCONFIG_FS_SEL_BIT + * @see MPU9150_GCONFIG_FS_SEL_LENGTH */ -void MPU6050::setFullScaleGyroRange(uint8_t range) { - I2Cdev::writeBits(devAddr, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, range); +void MPU9150::setFullScaleGyroRange(uint8_t range) { + I2Cdev::writeBits(devAddr, MPU9150_RA_GYRO_CONFIG, MPU9150_GCONFIG_FS_SEL_BIT, MPU9150_GCONFIG_FS_SEL_LENGTH, range); } // ACCEL_CONFIG register /** Get self-test enabled setting for accelerometer X axis. * @return Self-test enabled value - * @see MPU6050_RA_ACCEL_CONFIG + * @see MPU9150_RA_ACCEL_CONFIG */ -bool MPU6050::getAccelXSelfTest() { - I2Cdev::readBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_XA_ST_BIT, buffer); +bool MPU9150::getAccelXSelfTest() { + I2Cdev::readBit(devAddr, MPU9150_RA_ACCEL_CONFIG, MPU9150_ACONFIG_XA_ST_BIT, buffer); return buffer[0]; } /** Get self-test enabled setting for accelerometer X axis. * @param enabled Self-test enabled value - * @see MPU6050_RA_ACCEL_CONFIG + * @see MPU9150_RA_ACCEL_CONFIG */ -void MPU6050::setAccelXSelfTest(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_XA_ST_BIT, enabled); +void MPU9150::setAccelXSelfTest(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9150_RA_ACCEL_CONFIG, MPU9150_ACONFIG_XA_ST_BIT, enabled); } /** Get self-test enabled value for accelerometer Y axis. * @return Self-test enabled value - * @see MPU6050_RA_ACCEL_CONFIG + * @see MPU9150_RA_ACCEL_CONFIG */ -bool MPU6050::getAccelYSelfTest() { - I2Cdev::readBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_YA_ST_BIT, buffer); +bool MPU9150::getAccelYSelfTest() { + I2Cdev::readBit(devAddr, MPU9150_RA_ACCEL_CONFIG, MPU9150_ACONFIG_YA_ST_BIT, buffer); return buffer[0]; } /** Get self-test enabled value for accelerometer Y axis. * @param enabled Self-test enabled value - * @see MPU6050_RA_ACCEL_CONFIG + * @see MPU9150_RA_ACCEL_CONFIG */ -void MPU6050::setAccelYSelfTest(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_YA_ST_BIT, enabled); +void MPU9150::setAccelYSelfTest(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9150_RA_ACCEL_CONFIG, MPU9150_ACONFIG_YA_ST_BIT, enabled); } /** Get self-test enabled value for accelerometer Z axis. * @return Self-test enabled value - * @see MPU6050_RA_ACCEL_CONFIG + * @see MPU9150_RA_ACCEL_CONFIG */ -bool MPU6050::getAccelZSelfTest() { - I2Cdev::readBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ZA_ST_BIT, buffer); +bool MPU9150::getAccelZSelfTest() { + I2Cdev::readBit(devAddr, MPU9150_RA_ACCEL_CONFIG, MPU9150_ACONFIG_ZA_ST_BIT, buffer); return buffer[0]; } /** Set self-test enabled value for accelerometer Z axis. * @param enabled Self-test enabled value - * @see MPU6050_RA_ACCEL_CONFIG + * @see MPU9150_RA_ACCEL_CONFIG */ -void MPU6050::setAccelZSelfTest(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ZA_ST_BIT, enabled); +void MPU9150::setAccelZSelfTest(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9150_RA_ACCEL_CONFIG, MPU9150_ACONFIG_ZA_ST_BIT, enabled); } /** Get full-scale accelerometer range. * The FS_SEL parameter allows setting the full-scale range of the accelerometer @@ -312,27 +312,27 @@ void MPU6050::setAccelZSelfTest(bool enabled) { * * * @return Current full-scale accelerometer range setting - * @see MPU6050_ACCEL_FS_2 - * @see MPU6050_RA_ACCEL_CONFIG - * @see MPU6050_ACONFIG_AFS_SEL_BIT - * @see MPU6050_ACONFIG_AFS_SEL_LENGTH + * @see MPU9150_ACCEL_FS_2 + * @see MPU9150_RA_ACCEL_CONFIG + * @see MPU9150_ACONFIG_AFS_SEL_BIT + * @see MPU9150_ACONFIG_AFS_SEL_LENGTH */ -uint8_t MPU6050::getFullScaleAccelRange() { - I2Cdev::readBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, buffer); +uint8_t MPU9150::getFullScaleAccelRange() { + I2Cdev::readBits(devAddr, MPU9150_RA_ACCEL_CONFIG, MPU9150_ACONFIG_AFS_SEL_BIT, MPU9150_ACONFIG_AFS_SEL_LENGTH, buffer); return buffer[0]; } /** Set full-scale accelerometer range. * @param range New full-scale accelerometer range setting * @see getFullScaleAccelRange() */ -void MPU6050::setFullScaleAccelRange(uint8_t range) { - I2Cdev::writeBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, range); +void MPU9150::setFullScaleAccelRange(uint8_t range) { + I2Cdev::writeBits(devAddr, MPU9150_RA_ACCEL_CONFIG, MPU9150_ACONFIG_AFS_SEL_BIT, MPU9150_ACONFIG_AFS_SEL_LENGTH, range); } /** Get the high-pass filter configuration. * The DHPF is a filter module in the path leading to motion detectors (Free * Fall, Motion threshold, and Zero Motion). The high pass filter output is not * available to the data registers (see Figure in Section 8 of the MPU-6000/ - * MPU-6050 Product Specification document). + * MPU-9150 Product Specification document). * * The high pass filter has three modes: * @@ -360,21 +360,21 @@ void MPU6050::setFullScaleAccelRange(uint8_t range) { * * * @return Current high-pass filter configuration - * @see MPU6050_DHPF_RESET - * @see MPU6050_RA_ACCEL_CONFIG + * @see MPU9150_DHPF_RESET + * @see MPU9150_RA_ACCEL_CONFIG */ -uint8_t MPU6050::getDHPFMode() { - I2Cdev::readBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ACCEL_HPF_BIT, MPU6050_ACONFIG_ACCEL_HPF_LENGTH, buffer); +uint8_t MPU9150::getDHPFMode() { + I2Cdev::readBits(devAddr, MPU9150_RA_ACCEL_CONFIG, MPU9150_ACONFIG_ACCEL_HPF_BIT, MPU9150_ACONFIG_ACCEL_HPF_LENGTH, buffer); return buffer[0]; } /** Set the high-pass filter configuration. * @param bandwidth New high-pass filter configuration * @see setDHPFMode() - * @see MPU6050_DHPF_RESET - * @see MPU6050_RA_ACCEL_CONFIG + * @see MPU9150_DHPF_RESET + * @see MPU9150_RA_ACCEL_CONFIG */ -void MPU6050::setDHPFMode(uint8_t bandwidth) { - I2Cdev::writeBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ACCEL_HPF_BIT, MPU6050_ACONFIG_ACCEL_HPF_LENGTH, bandwidth); +void MPU9150::setDHPFMode(uint8_t bandwidth) { + I2Cdev::writeBits(devAddr, MPU9150_RA_ACCEL_CONFIG, MPU9150_ACONFIG_ACCEL_HPF_BIT, MPU9150_ACONFIG_ACCEL_HPF_LENGTH, bandwidth); } // FF_THR register @@ -388,23 +388,23 @@ void MPU6050::setDHPFMode(uint8_t bandwidth) { * Free Fall duration counter reaches the time specified in FF_DUR. * * For more details on the Free Fall detection interrupt, see Section 8.2 of the - * MPU-6000/MPU-6050 Product Specification document as well as Registers 56 and + * MPU-6000/MPU-9150 Product Specification document as well as Registers 56 and * 58 of this document. * * @return Current free-fall acceleration threshold value (LSB = 2mg) - * @see MPU6050_RA_FF_THR + * @see MPU9150_RA_FF_THR */ -uint8_t MPU6050::getFreefallDetectionThreshold() { - I2Cdev::readByte(devAddr, MPU6050_RA_FF_THR, buffer); +uint8_t MPU9150::getFreefallDetectionThreshold() { + I2Cdev::readByte(devAddr, MPU9150_RA_FF_THR, buffer); return buffer[0]; } /** Get free-fall event acceleration threshold. * @param threshold New free-fall acceleration threshold value (LSB = 2mg) * @see getFreefallDetectionThreshold() - * @see MPU6050_RA_FF_THR + * @see MPU9150_RA_FF_THR */ -void MPU6050::setFreefallDetectionThreshold(uint8_t threshold) { - I2Cdev::writeByte(devAddr, MPU6050_RA_FF_THR, threshold); +void MPU9150::setFreefallDetectionThreshold(uint8_t threshold) { + I2Cdev::writeByte(devAddr, MPU9150_RA_FF_THR, threshold); } // FF_DUR register @@ -420,23 +420,23 @@ void MPU6050::setFreefallDetectionThreshold(uint8_t threshold) { * duration counter reaches the time specified in this register. * * For more details on the Free Fall detection interrupt, see Section 8.2 of - * the MPU-6000/MPU-6050 Product Specification document as well as Registers 56 + * the MPU-6000/MPU-9150 Product Specification document as well as Registers 56 * and 58 of this document. * * @return Current free-fall duration threshold value (LSB = 1ms) - * @see MPU6050_RA_FF_DUR + * @see MPU9150_RA_FF_DUR */ -uint8_t MPU6050::getFreefallDetectionDuration() { - I2Cdev::readByte(devAddr, MPU6050_RA_FF_DUR, buffer); +uint8_t MPU9150::getFreefallDetectionDuration() { + I2Cdev::readByte(devAddr, MPU9150_RA_FF_DUR, buffer); return buffer[0]; } /** Get free-fall event duration threshold. * @param duration New free-fall duration threshold value (LSB = 1ms) * @see getFreefallDetectionDuration() - * @see MPU6050_RA_FF_DUR + * @see MPU9150_RA_FF_DUR */ -void MPU6050::setFreefallDetectionDuration(uint8_t duration) { - I2Cdev::writeByte(devAddr, MPU6050_RA_FF_DUR, duration); +void MPU9150::setFreefallDetectionDuration(uint8_t duration) { + I2Cdev::writeByte(devAddr, MPU9150_RA_FF_DUR, duration); } // MOT_THR register @@ -454,23 +454,23 @@ void MPU6050::setFreefallDetectionDuration(uint8_t duration) { * in MOT_DETECT_STATUS (Register 97). * * For more details on the Motion detection interrupt, see Section 8.3 of the - * MPU-6000/MPU-6050 Product Specification document as well as Registers 56 and + * MPU-6000/MPU-9150 Product Specification document as well as Registers 56 and * 58 of this document. * * @return Current motion detection acceleration threshold value (LSB = 2mg) - * @see MPU6050_RA_MOT_THR + * @see MPU9150_RA_MOT_THR */ -uint8_t MPU6050::getMotionDetectionThreshold() { - I2Cdev::readByte(devAddr, MPU6050_RA_MOT_THR, buffer); +uint8_t MPU9150::getMotionDetectionThreshold() { + I2Cdev::readByte(devAddr, MPU9150_RA_MOT_THR, buffer); return buffer[0]; } /** Set free-fall event acceleration threshold. * @param threshold New motion detection acceleration threshold value (LSB = 2mg) * @see getMotionDetectionThreshold() - * @see MPU6050_RA_MOT_THR + * @see MPU9150_RA_MOT_THR */ -void MPU6050::setMotionDetectionThreshold(uint8_t threshold) { - I2Cdev::writeByte(devAddr, MPU6050_RA_MOT_THR, threshold); +void MPU9150::setMotionDetectionThreshold(uint8_t threshold) { + I2Cdev::writeByte(devAddr, MPU9150_RA_MOT_THR, threshold); } // MOT_DUR register @@ -485,22 +485,22 @@ void MPU6050::setMotionDetectionThreshold(uint8_t threshold) { * in this register. * * For more details on the Motion detection interrupt, see Section 8.3 of the - * MPU-6000/MPU-6050 Product Specification document. + * MPU-6000/MPU-9150 Product Specification document. * * @return Current motion detection duration threshold value (LSB = 1ms) - * @see MPU6050_RA_MOT_DUR + * @see MPU9150_RA_MOT_DUR */ -uint8_t MPU6050::getMotionDetectionDuration() { - I2Cdev::readByte(devAddr, MPU6050_RA_MOT_DUR, buffer); +uint8_t MPU9150::getMotionDetectionDuration() { + I2Cdev::readByte(devAddr, MPU9150_RA_MOT_DUR, buffer); return buffer[0]; } /** Set motion detection event duration threshold. * @param duration New motion detection duration threshold value (LSB = 1ms) * @see getMotionDetectionDuration() - * @see MPU6050_RA_MOT_DUR + * @see MPU9150_RA_MOT_DUR */ -void MPU6050::setMotionDetectionDuration(uint8_t duration) { - I2Cdev::writeByte(devAddr, MPU6050_RA_MOT_DUR, duration); +void MPU9150::setMotionDetectionDuration(uint8_t duration) { + I2Cdev::writeByte(devAddr, MPU9150_RA_MOT_DUR, duration); } // ZRMOT_THR register @@ -524,23 +524,23 @@ void MPU6050::setMotionDetectionDuration(uint8_t duration) { * motion condition is detected, the status bit is set to 0. * * For more details on the Zero Motion detection interrupt, see Section 8.4 of - * the MPU-6000/MPU-6050 Product Specification document as well as Registers 56 + * the MPU-6000/MPU-9150 Product Specification document as well as Registers 56 * and 58 of this document. * * @return Current zero motion detection acceleration threshold value (LSB = 2mg) - * @see MPU6050_RA_ZRMOT_THR + * @see MPU9150_RA_ZRMOT_THR */ -uint8_t MPU6050::getZeroMotionDetectionThreshold() { - I2Cdev::readByte(devAddr, MPU6050_RA_ZRMOT_THR, buffer); +uint8_t MPU9150::getZeroMotionDetectionThreshold() { + I2Cdev::readByte(devAddr, MPU9150_RA_ZRMOT_THR, buffer); return buffer[0]; } /** Set zero motion detection event acceleration threshold. * @param threshold New zero motion detection acceleration threshold value (LSB = 2mg) * @see getZeroMotionDetectionThreshold() - * @see MPU6050_RA_ZRMOT_THR + * @see MPU9150_RA_ZRMOT_THR */ -void MPU6050::setZeroMotionDetectionThreshold(uint8_t threshold) { - I2Cdev::writeByte(devAddr, MPU6050_RA_ZRMOT_THR, threshold); +void MPU9150::setZeroMotionDetectionThreshold(uint8_t threshold) { + I2Cdev::writeByte(devAddr, MPU9150_RA_ZRMOT_THR, threshold); } // ZRMOT_DUR register @@ -555,23 +555,23 @@ void MPU6050::setZeroMotionDetectionThreshold(uint8_t threshold) { * count specified in this register. * * For more details on the Zero Motion detection interrupt, see Section 8.4 of - * the MPU-6000/MPU-6050 Product Specification document, as well as Registers 56 + * the MPU-6000/MPU-9150 Product Specification document, as well as Registers 56 * and 58 of this document. * * @return Current zero motion detection duration threshold value (LSB = 64ms) - * @see MPU6050_RA_ZRMOT_DUR + * @see MPU9150_RA_ZRMOT_DUR */ -uint8_t MPU6050::getZeroMotionDetectionDuration() { - I2Cdev::readByte(devAddr, MPU6050_RA_ZRMOT_DUR, buffer); +uint8_t MPU9150::getZeroMotionDetectionDuration() { + I2Cdev::readByte(devAddr, MPU9150_RA_ZRMOT_DUR, buffer); return buffer[0]; } /** Set zero motion detection event duration threshold. * @param duration New zero motion detection duration threshold value (LSB = 1ms) * @see getZeroMotionDetectionDuration() - * @see MPU6050_RA_ZRMOT_DUR + * @see MPU9150_RA_ZRMOT_DUR */ -void MPU6050::setZeroMotionDetectionDuration(uint8_t duration) { - I2Cdev::writeByte(devAddr, MPU6050_RA_ZRMOT_DUR, duration); +void MPU9150::setZeroMotionDetectionDuration(uint8_t duration) { + I2Cdev::writeByte(devAddr, MPU9150_RA_ZRMOT_DUR, duration); } // FIFO_EN register @@ -580,146 +580,146 @@ void MPU6050::setZeroMotionDetectionDuration(uint8_t duration) { * When set to 1, this bit enables TEMP_OUT_H and TEMP_OUT_L (Registers 65 and * 66) to be written into the FIFO buffer. * @return Current temperature FIFO enabled value - * @see MPU6050_RA_FIFO_EN + * @see MPU9150_RA_FIFO_EN */ -bool MPU6050::getTempFIFOEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_TEMP_FIFO_EN_BIT, buffer); +bool MPU9150::getTempFIFOEnabled() { + I2Cdev::readBit(devAddr, MPU9150_RA_FIFO_EN, MPU9150_TEMP_FIFO_EN_BIT, buffer); return buffer[0]; } /** Set temperature FIFO enabled value. * @param enabled New temperature FIFO enabled value * @see getTempFIFOEnabled() - * @see MPU6050_RA_FIFO_EN + * @see MPU9150_RA_FIFO_EN */ -void MPU6050::setTempFIFOEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_TEMP_FIFO_EN_BIT, enabled); +void MPU9150::setTempFIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9150_RA_FIFO_EN, MPU9150_TEMP_FIFO_EN_BIT, enabled); } /** Get gyroscope X-axis FIFO enabled value. * When set to 1, this bit enables GYRO_XOUT_H and GYRO_XOUT_L (Registers 67 and * 68) to be written into the FIFO buffer. * @return Current gyroscope X-axis FIFO enabled value - * @see MPU6050_RA_FIFO_EN + * @see MPU9150_RA_FIFO_EN */ -bool MPU6050::getXGyroFIFOEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_XG_FIFO_EN_BIT, buffer); +bool MPU9150::getXGyroFIFOEnabled() { + I2Cdev::readBit(devAddr, MPU9150_RA_FIFO_EN, MPU9150_XG_FIFO_EN_BIT, buffer); return buffer[0]; } /** Set gyroscope X-axis FIFO enabled value. * @param enabled New gyroscope X-axis FIFO enabled value * @see getXGyroFIFOEnabled() - * @see MPU6050_RA_FIFO_EN + * @see MPU9150_RA_FIFO_EN */ -void MPU6050::setXGyroFIFOEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_XG_FIFO_EN_BIT, enabled); +void MPU9150::setXGyroFIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9150_RA_FIFO_EN, MPU9150_XG_FIFO_EN_BIT, enabled); } /** Get gyroscope Y-axis FIFO enabled value. * When set to 1, this bit enables GYRO_YOUT_H and GYRO_YOUT_L (Registers 69 and * 70) to be written into the FIFO buffer. * @return Current gyroscope Y-axis FIFO enabled value - * @see MPU6050_RA_FIFO_EN + * @see MPU9150_RA_FIFO_EN */ -bool MPU6050::getYGyroFIFOEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_YG_FIFO_EN_BIT, buffer); +bool MPU9150::getYGyroFIFOEnabled() { + I2Cdev::readBit(devAddr, MPU9150_RA_FIFO_EN, MPU9150_YG_FIFO_EN_BIT, buffer); return buffer[0]; } /** Set gyroscope Y-axis FIFO enabled value. * @param enabled New gyroscope Y-axis FIFO enabled value * @see getYGyroFIFOEnabled() - * @see MPU6050_RA_FIFO_EN + * @see MPU9150_RA_FIFO_EN */ -void MPU6050::setYGyroFIFOEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_YG_FIFO_EN_BIT, enabled); +void MPU9150::setYGyroFIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9150_RA_FIFO_EN, MPU9150_YG_FIFO_EN_BIT, enabled); } /** Get gyroscope Z-axis FIFO enabled value. * When set to 1, this bit enables GYRO_ZOUT_H and GYRO_ZOUT_L (Registers 71 and * 72) to be written into the FIFO buffer. * @return Current gyroscope Z-axis FIFO enabled value - * @see MPU6050_RA_FIFO_EN + * @see MPU9150_RA_FIFO_EN */ -bool MPU6050::getZGyroFIFOEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ZG_FIFO_EN_BIT, buffer); +bool MPU9150::getZGyroFIFOEnabled() { + I2Cdev::readBit(devAddr, MPU9150_RA_FIFO_EN, MPU9150_ZG_FIFO_EN_BIT, buffer); return buffer[0]; } /** Set gyroscope Z-axis FIFO enabled value. * @param enabled New gyroscope Z-axis FIFO enabled value * @see getZGyroFIFOEnabled() - * @see MPU6050_RA_FIFO_EN + * @see MPU9150_RA_FIFO_EN */ -void MPU6050::setZGyroFIFOEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ZG_FIFO_EN_BIT, enabled); +void MPU9150::setZGyroFIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9150_RA_FIFO_EN, MPU9150_ZG_FIFO_EN_BIT, enabled); } /** Get accelerometer FIFO enabled value. * When set to 1, this bit enables ACCEL_XOUT_H, ACCEL_XOUT_L, ACCEL_YOUT_H, * ACCEL_YOUT_L, ACCEL_ZOUT_H, and ACCEL_ZOUT_L (Registers 59 to 64) to be * written into the FIFO buffer. * @return Current accelerometer FIFO enabled value - * @see MPU6050_RA_FIFO_EN + * @see MPU9150_RA_FIFO_EN */ -bool MPU6050::getAccelFIFOEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ACCEL_FIFO_EN_BIT, buffer); +bool MPU9150::getAccelFIFOEnabled() { + I2Cdev::readBit(devAddr, MPU9150_RA_FIFO_EN, MPU9150_ACCEL_FIFO_EN_BIT, buffer); return buffer[0]; } /** Set accelerometer FIFO enabled value. * @param enabled New accelerometer FIFO enabled value * @see getAccelFIFOEnabled() - * @see MPU6050_RA_FIFO_EN + * @see MPU9150_RA_FIFO_EN */ -void MPU6050::setAccelFIFOEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ACCEL_FIFO_EN_BIT, enabled); +void MPU9150::setAccelFIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9150_RA_FIFO_EN, MPU9150_ACCEL_FIFO_EN_BIT, enabled); } /** Get Slave 2 FIFO enabled value. * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) * associated with Slave 2 to be written into the FIFO buffer. * @return Current Slave 2 FIFO enabled value - * @see MPU6050_RA_FIFO_EN + * @see MPU9150_RA_FIFO_EN */ -bool MPU6050::getSlave2FIFOEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV2_FIFO_EN_BIT, buffer); +bool MPU9150::getSlave2FIFOEnabled() { + I2Cdev::readBit(devAddr, MPU9150_RA_FIFO_EN, MPU9150_SLV2_FIFO_EN_BIT, buffer); return buffer[0]; } /** Set Slave 2 FIFO enabled value. * @param enabled New Slave 2 FIFO enabled value * @see getSlave2FIFOEnabled() - * @see MPU6050_RA_FIFO_EN + * @see MPU9150_RA_FIFO_EN */ -void MPU6050::setSlave2FIFOEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV2_FIFO_EN_BIT, enabled); +void MPU9150::setSlave2FIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9150_RA_FIFO_EN, MPU9150_SLV2_FIFO_EN_BIT, enabled); } /** Get Slave 1 FIFO enabled value. * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) * associated with Slave 1 to be written into the FIFO buffer. * @return Current Slave 1 FIFO enabled value - * @see MPU6050_RA_FIFO_EN + * @see MPU9150_RA_FIFO_EN */ -bool MPU6050::getSlave1FIFOEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV1_FIFO_EN_BIT, buffer); +bool MPU9150::getSlave1FIFOEnabled() { + I2Cdev::readBit(devAddr, MPU9150_RA_FIFO_EN, MPU9150_SLV1_FIFO_EN_BIT, buffer); return buffer[0]; } /** Set Slave 1 FIFO enabled value. * @param enabled New Slave 1 FIFO enabled value * @see getSlave1FIFOEnabled() - * @see MPU6050_RA_FIFO_EN + * @see MPU9150_RA_FIFO_EN */ -void MPU6050::setSlave1FIFOEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV1_FIFO_EN_BIT, enabled); +void MPU9150::setSlave1FIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9150_RA_FIFO_EN, MPU9150_SLV1_FIFO_EN_BIT, enabled); } /** Get Slave 0 FIFO enabled value. * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) * associated with Slave 0 to be written into the FIFO buffer. * @return Current Slave 0 FIFO enabled value - * @see MPU6050_RA_FIFO_EN + * @see MPU9150_RA_FIFO_EN */ -bool MPU6050::getSlave0FIFOEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV0_FIFO_EN_BIT, buffer); +bool MPU9150::getSlave0FIFOEnabled() { + I2Cdev::readBit(devAddr, MPU9150_RA_FIFO_EN, MPU9150_SLV0_FIFO_EN_BIT, buffer); return buffer[0]; } /** Set Slave 0 FIFO enabled value. * @param enabled New Slave 0 FIFO enabled value * @see getSlave0FIFOEnabled() - * @see MPU6050_RA_FIFO_EN + * @see MPU9150_RA_FIFO_EN */ -void MPU6050::setSlave0FIFOEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV0_FIFO_EN_BIT, enabled); +void MPU9150::setSlave0FIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9150_RA_FIFO_EN, MPU9150_SLV0_FIFO_EN_BIT, enabled); } // I2C_MST_CTRL register @@ -737,19 +737,19 @@ void MPU6050::setSlave0FIFOEnabled(bool enabled) { * detect when the bus is available. * * @return Current multi-master enabled value - * @see MPU6050_RA_I2C_MST_CTRL + * @see MPU9150_RA_I2C_MST_CTRL */ -bool MPU6050::getMultiMasterEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_MULT_MST_EN_BIT, buffer); +bool MPU9150::getMultiMasterEnabled() { + I2Cdev::readBit(devAddr, MPU9150_RA_I2C_MST_CTRL, MPU9150_MULT_MST_EN_BIT, buffer); return buffer[0]; } /** Set multi-master enabled value. * @param enabled New multi-master enabled value * @see getMultiMasterEnabled() - * @see MPU6050_RA_I2C_MST_CTRL + * @see MPU9150_RA_I2C_MST_CTRL */ -void MPU6050::setMultiMasterEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_MULT_MST_EN_BIT, enabled); +void MPU9150::setMultiMasterEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9150_RA_I2C_MST_CTRL, MPU9150_MULT_MST_EN_BIT, enabled); } /** Get wait-for-external-sensor-data enabled value. * When the WAIT_FOR_ES bit is set to 1, the Data Ready interrupt will be @@ -760,37 +760,37 @@ void MPU6050::setMultiMasterEnabled(bool enabled) { * interrupt is triggered. * * @return Current wait-for-external-sensor-data enabled value - * @see MPU6050_RA_I2C_MST_CTRL + * @see MPU9150_RA_I2C_MST_CTRL */ -bool MPU6050::getWaitForExternalSensorEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_WAIT_FOR_ES_BIT, buffer); +bool MPU9150::getWaitForExternalSensorEnabled() { + I2Cdev::readBit(devAddr, MPU9150_RA_I2C_MST_CTRL, MPU9150_WAIT_FOR_ES_BIT, buffer); return buffer[0]; } /** Set wait-for-external-sensor-data enabled value. * @param enabled New wait-for-external-sensor-data enabled value * @see getWaitForExternalSensorEnabled() - * @see MPU6050_RA_I2C_MST_CTRL + * @see MPU9150_RA_I2C_MST_CTRL */ -void MPU6050::setWaitForExternalSensorEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_WAIT_FOR_ES_BIT, enabled); +void MPU9150::setWaitForExternalSensorEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9150_RA_I2C_MST_CTRL, MPU9150_WAIT_FOR_ES_BIT, enabled); } /** Get Slave 3 FIFO enabled value. * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) * associated with Slave 3 to be written into the FIFO buffer. * @return Current Slave 3 FIFO enabled value - * @see MPU6050_RA_MST_CTRL + * @see MPU9150_RA_MST_CTRL */ -bool MPU6050::getSlave3FIFOEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_SLV_3_FIFO_EN_BIT, buffer); +bool MPU9150::getSlave3FIFOEnabled() { + I2Cdev::readBit(devAddr, MPU9150_RA_I2C_MST_CTRL, MPU9150_SLV_3_FIFO_EN_BIT, buffer); return buffer[0]; } /** Set Slave 3 FIFO enabled value. * @param enabled New Slave 3 FIFO enabled value * @see getSlave3FIFOEnabled() - * @see MPU6050_RA_MST_CTRL + * @see MPU9150_RA_MST_CTRL */ -void MPU6050::setSlave3FIFOEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_SLV_3_FIFO_EN_BIT, enabled); +void MPU9150::setSlave3FIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9150_RA_I2C_MST_CTRL, MPU9150_SLV_3_FIFO_EN_BIT, enabled); } /** Get slave read/write transition enabled value. * The I2C_MST_P_NSR bit configures the I2C Master's transition from one slave @@ -800,19 +800,19 @@ void MPU6050::setSlave3FIFOEnabled(bool enabled) { * the stop followed by a start of the successive write will be always used. * * @return Current slave read/write transition enabled value - * @see MPU6050_RA_I2C_MST_CTRL + * @see MPU9150_RA_I2C_MST_CTRL */ -bool MPU6050::getSlaveReadWriteTransitionEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_P_NSR_BIT, buffer); +bool MPU9150::getSlaveReadWriteTransitionEnabled() { + I2Cdev::readBit(devAddr, MPU9150_RA_I2C_MST_CTRL, MPU9150_I2C_MST_P_NSR_BIT, buffer); return buffer[0]; } /** Set slave read/write transition enabled value. * @param enabled New slave read/write transition enabled value * @see getSlaveReadWriteTransitionEnabled() - * @see MPU6050_RA_I2C_MST_CTRL + * @see MPU9150_RA_I2C_MST_CTRL */ -void MPU6050::setSlaveReadWriteTransitionEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_P_NSR_BIT, enabled); +void MPU9150::setSlaveReadWriteTransitionEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9150_RA_I2C_MST_CTRL, MPU9150_I2C_MST_P_NSR_BIT, enabled); } /** Get I2C master clock speed. * I2C_MST_CLK is a 4 bit unsigned value which configures a divider on the @@ -841,18 +841,18 @@ void MPU6050::setSlaveReadWriteTransitionEnabled(bool enabled) { * * * @return Current I2C master clock speed - * @see MPU6050_RA_I2C_MST_CTRL + * @see MPU9150_RA_I2C_MST_CTRL */ -uint8_t MPU6050::getMasterClockSpeed() { - I2Cdev::readBits(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_CLK_BIT, MPU6050_I2C_MST_CLK_LENGTH, buffer); +uint8_t MPU9150::getMasterClockSpeed() { + I2Cdev::readBits(devAddr, MPU9150_RA_I2C_MST_CTRL, MPU9150_I2C_MST_CLK_BIT, MPU9150_I2C_MST_CLK_LENGTH, buffer); return buffer[0]; } /** Set I2C master clock speed. * @reparam speed Current I2C master clock speed - * @see MPU6050_RA_I2C_MST_CTRL + * @see MPU9150_RA_I2C_MST_CTRL */ -void MPU6050::setMasterClockSpeed(uint8_t speed) { - I2Cdev::writeBits(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_CLK_BIT, MPU6050_I2C_MST_CLK_LENGTH, speed); +void MPU9150::setMasterClockSpeed(uint8_t speed) { + I2Cdev::writeBits(devAddr, MPU9150_RA_I2C_MST_CTRL, MPU9150_I2C_MST_CLK_BIT, MPU9150_I2C_MST_CLK_LENGTH, speed); } // I2C_SLV* registers (Slave 0-3) @@ -867,7 +867,7 @@ void MPU6050::setMasterClockSpeed(uint8_t speed) { * read results, please refer to the EXT_SENS_DATA register description * (Registers 73 - 96). * - * The MPU-6050 supports a total of five slaves, but Slave 4 has unique + * The MPU-9150 supports a total of five slaves, but Slave 4 has unique * characteristics, and so it has its own functions (getSlave4* and setSlave4*). * * I2C data transactions are performed at the Sample Rate, as defined in @@ -896,70 +896,70 @@ void MPU6050::setMasterClockSpeed(uint8_t speed) { * * @param num Slave number (0-3) * @return Current address for specified slave - * @see MPU6050_RA_I2C_SLV0_ADDR + * @see MPU9150_RA_I2C_SLV0_ADDR */ -uint8_t MPU6050::getSlaveAddress(uint8_t num) { +uint8_t MPU9150::getSlaveAddress(uint8_t num) { if (num > 3) return 0; - I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV0_ADDR + num*3, buffer); + I2Cdev::readByte(devAddr, MPU9150_RA_I2C_SLV0_ADDR + num*3, buffer); return buffer[0]; } /** Set the I2C address of the specified slave (0-3). * @param num Slave number (0-3) * @param address New address for specified slave * @see getSlaveAddress() - * @see MPU6050_RA_I2C_SLV0_ADDR + * @see MPU9150_RA_I2C_SLV0_ADDR */ -void MPU6050::setSlaveAddress(uint8_t num, uint8_t address) { +void MPU9150::setSlaveAddress(uint8_t num, uint8_t address) { if (num > 3) return; - I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV0_ADDR + num*3, address); + I2Cdev::writeByte(devAddr, MPU9150_RA_I2C_SLV0_ADDR + num*3, address); } /** Get the active internal register for the specified slave (0-3). * Read/write operations for this slave will be done to whatever internal * register address is stored in this MPU register. * - * The MPU-6050 supports a total of five slaves, but Slave 4 has unique + * The MPU-9150 supports a total of five slaves, but Slave 4 has unique * characteristics, and so it has its own functions. * * @param num Slave number (0-3) * @return Current active register for specified slave - * @see MPU6050_RA_I2C_SLV0_REG + * @see MPU9150_RA_I2C_SLV0_REG */ -uint8_t MPU6050::getSlaveRegister(uint8_t num) { +uint8_t MPU9150::getSlaveRegister(uint8_t num) { if (num > 3) return 0; - I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV0_REG + num*3, buffer); + I2Cdev::readByte(devAddr, MPU9150_RA_I2C_SLV0_REG + num*3, buffer); return buffer[0]; } /** Set the active internal register for the specified slave (0-3). * @param num Slave number (0-3) * @param reg New active register for specified slave * @see getSlaveRegister() - * @see MPU6050_RA_I2C_SLV0_REG + * @see MPU9150_RA_I2C_SLV0_REG */ -void MPU6050::setSlaveRegister(uint8_t num, uint8_t reg) { +void MPU9150::setSlaveRegister(uint8_t num, uint8_t reg) { if (num > 3) return; - I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV0_REG + num*3, reg); + I2Cdev::writeByte(devAddr, MPU9150_RA_I2C_SLV0_REG + num*3, reg); } /** Get the enabled value for the specified slave (0-3). * When set to 1, this bit enables Slave 0 for data transfer operations. When * cleared to 0, this bit disables Slave 0 from data transfer operations. * @param num Slave number (0-3) * @return Current enabled value for specified slave - * @see MPU6050_RA_I2C_SLV0_CTRL + * @see MPU9150_RA_I2C_SLV0_CTRL */ -bool MPU6050::getSlaveEnabled(uint8_t num) { +bool MPU9150::getSlaveEnabled(uint8_t num) { if (num > 3) return 0; - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_EN_BIT, buffer); + I2Cdev::readBit(devAddr, MPU9150_RA_I2C_SLV0_CTRL + num*3, MPU9150_I2C_SLV_EN_BIT, buffer); return buffer[0]; } /** Set the enabled value for the specified slave (0-3). * @param num Slave number (0-3) * @param enabled New enabled value for specified slave * @see getSlaveEnabled() - * @see MPU6050_RA_I2C_SLV0_CTRL + * @see MPU9150_RA_I2C_SLV0_CTRL */ -void MPU6050::setSlaveEnabled(uint8_t num, bool enabled) { +void MPU9150::setSlaveEnabled(uint8_t num, bool enabled) { if (num > 3) return; - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_EN_BIT, enabled); + I2Cdev::writeBit(devAddr, MPU9150_RA_I2C_SLV0_CTRL + num*3, MPU9150_I2C_SLV_EN_BIT, enabled); } /** Get word pair byte-swapping enabled for the specified slave (0-3). * When set to 1, this bit enables byte swapping. When byte swapping is enabled, @@ -970,22 +970,22 @@ void MPU6050::setSlaveEnabled(uint8_t num, bool enabled) { * * @param num Slave number (0-3) * @return Current word pair byte-swapping enabled value for specified slave - * @see MPU6050_RA_I2C_SLV0_CTRL + * @see MPU9150_RA_I2C_SLV0_CTRL */ -bool MPU6050::getSlaveWordByteSwap(uint8_t num) { +bool MPU9150::getSlaveWordByteSwap(uint8_t num) { if (num > 3) return 0; - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_BYTE_SW_BIT, buffer); + I2Cdev::readBit(devAddr, MPU9150_RA_I2C_SLV0_CTRL + num*3, MPU9150_I2C_SLV_BYTE_SW_BIT, buffer); return buffer[0]; } /** Set word pair byte-swapping enabled for the specified slave (0-3). * @param num Slave number (0-3) * @param enabled New word pair byte-swapping enabled value for specified slave * @see getSlaveWordByteSwap() - * @see MPU6050_RA_I2C_SLV0_CTRL + * @see MPU9150_RA_I2C_SLV0_CTRL */ -void MPU6050::setSlaveWordByteSwap(uint8_t num, bool enabled) { +void MPU9150::setSlaveWordByteSwap(uint8_t num, bool enabled) { if (num > 3) return; - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_BYTE_SW_BIT, enabled); + I2Cdev::writeBit(devAddr, MPU9150_RA_I2C_SLV0_CTRL + num*3, MPU9150_I2C_SLV_BYTE_SW_BIT, enabled); } /** Get write mode for the specified slave (0-3). * When set to 1, the transaction will read or write data only. When cleared to @@ -995,22 +995,22 @@ void MPU6050::setSlaveWordByteSwap(uint8_t num, bool enabled) { * * @param num Slave number (0-3) * @return Current write mode for specified slave (0 = register address + data, 1 = data only) - * @see MPU6050_RA_I2C_SLV0_CTRL + * @see MPU9150_RA_I2C_SLV0_CTRL */ -bool MPU6050::getSlaveWriteMode(uint8_t num) { +bool MPU9150::getSlaveWriteMode(uint8_t num) { if (num > 3) return 0; - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_REG_DIS_BIT, buffer); + I2Cdev::readBit(devAddr, MPU9150_RA_I2C_SLV0_CTRL + num*3, MPU9150_I2C_SLV_REG_DIS_BIT, buffer); return buffer[0]; } /** Set write mode for the specified slave (0-3). * @param num Slave number (0-3) * @param mode New write mode for specified slave (0 = register address + data, 1 = data only) * @see getSlaveWriteMode() - * @see MPU6050_RA_I2C_SLV0_CTRL + * @see MPU9150_RA_I2C_SLV0_CTRL */ -void MPU6050::setSlaveWriteMode(uint8_t num, bool mode) { +void MPU9150::setSlaveWriteMode(uint8_t num, bool mode) { if (num > 3) return; - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_REG_DIS_BIT, mode); + I2Cdev::writeBit(devAddr, MPU9150_RA_I2C_SLV0_CTRL + num*3, MPU9150_I2C_SLV_REG_DIS_BIT, mode); } /** Get word pair grouping order offset for the specified slave (0-3). * This sets specifies the grouping order of word pairs received from registers. @@ -1021,44 +1021,44 @@ void MPU6050::setSlaveWriteMode(uint8_t num, bool mode) { * * @param num Slave number (0-3) * @return Current word pair grouping order offset for specified slave - * @see MPU6050_RA_I2C_SLV0_CTRL + * @see MPU9150_RA_I2C_SLV0_CTRL */ -bool MPU6050::getSlaveWordGroupOffset(uint8_t num) { +bool MPU9150::getSlaveWordGroupOffset(uint8_t num) { if (num > 3) return 0; - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_GRP_BIT, buffer); + I2Cdev::readBit(devAddr, MPU9150_RA_I2C_SLV0_CTRL + num*3, MPU9150_I2C_SLV_GRP_BIT, buffer); return buffer[0]; } /** Set word pair grouping order offset for the specified slave (0-3). * @param num Slave number (0-3) * @param enabled New word pair grouping order offset for specified slave * @see getSlaveWordGroupOffset() - * @see MPU6050_RA_I2C_SLV0_CTRL + * @see MPU9150_RA_I2C_SLV0_CTRL */ -void MPU6050::setSlaveWordGroupOffset(uint8_t num, bool enabled) { +void MPU9150::setSlaveWordGroupOffset(uint8_t num, bool enabled) { if (num > 3) return; - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_GRP_BIT, enabled); + I2Cdev::writeBit(devAddr, MPU9150_RA_I2C_SLV0_CTRL + num*3, MPU9150_I2C_SLV_GRP_BIT, enabled); } /** Get number of bytes to read for the specified slave (0-3). * Specifies the number of bytes transferred to and from Slave 0. Clearing this * bit to 0 is equivalent to disabling the register by writing 0 to I2C_SLV0_EN. * @param num Slave number (0-3) * @return Number of bytes to read for specified slave - * @see MPU6050_RA_I2C_SLV0_CTRL + * @see MPU9150_RA_I2C_SLV0_CTRL */ -uint8_t MPU6050::getSlaveDataLength(uint8_t num) { +uint8_t MPU9150::getSlaveDataLength(uint8_t num) { if (num > 3) return 0; - I2Cdev::readBits(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_LEN_BIT, MPU6050_I2C_SLV_LEN_LENGTH, buffer); + I2Cdev::readBits(devAddr, MPU9150_RA_I2C_SLV0_CTRL + num*3, MPU9150_I2C_SLV_LEN_BIT, MPU9150_I2C_SLV_LEN_LENGTH, buffer); return buffer[0]; } /** Set number of bytes to read for the specified slave (0-3). * @param num Slave number (0-3) * @param length Number of bytes to read for specified slave * @see getSlaveDataLength() - * @see MPU6050_RA_I2C_SLV0_CTRL + * @see MPU9150_RA_I2C_SLV0_CTRL */ -void MPU6050::setSlaveDataLength(uint8_t num, uint8_t length) { +void MPU9150::setSlaveDataLength(uint8_t num, uint8_t length) { if (num > 3) return; - I2Cdev::writeBits(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_LEN_BIT, MPU6050_I2C_SLV_LEN_LENGTH, length); + I2Cdev::writeBits(devAddr, MPU9150_RA_I2C_SLV0_CTRL + num*3, MPU9150_I2C_SLV_LEN_BIT, MPU9150_I2C_SLV_LEN_LENGTH, length); } // I2C_SLV* registers (Slave 4) @@ -1070,65 +1070,65 @@ void MPU6050::setSlaveDataLength(uint8_t num, uint8_t length) { * * @return Current address for Slave 4 * @see getSlaveAddress() - * @see MPU6050_RA_I2C_SLV4_ADDR + * @see MPU9150_RA_I2C_SLV4_ADDR */ -uint8_t MPU6050::getSlave4Address() { - I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV4_ADDR, buffer); +uint8_t MPU9150::getSlave4Address() { + I2Cdev::readByte(devAddr, MPU9150_RA_I2C_SLV4_ADDR, buffer); return buffer[0]; } /** Set the I2C address of Slave 4. * @param address New address for Slave 4 * @see getSlave4Address() - * @see MPU6050_RA_I2C_SLV4_ADDR + * @see MPU9150_RA_I2C_SLV4_ADDR */ -void MPU6050::setSlave4Address(uint8_t address) { - I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV4_ADDR, address); +void MPU9150::setSlave4Address(uint8_t address) { + I2Cdev::writeByte(devAddr, MPU9150_RA_I2C_SLV4_ADDR, address); } /** Get the active internal register for the Slave 4. * Read/write operations for this slave will be done to whatever internal * register address is stored in this MPU register. * * @return Current active register for Slave 4 - * @see MPU6050_RA_I2C_SLV4_REG + * @see MPU9150_RA_I2C_SLV4_REG */ -uint8_t MPU6050::getSlave4Register() { - I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV4_REG, buffer); +uint8_t MPU9150::getSlave4Register() { + I2Cdev::readByte(devAddr, MPU9150_RA_I2C_SLV4_REG, buffer); return buffer[0]; } /** Set the active internal register for Slave 4. * @param reg New active register for Slave 4 * @see getSlave4Register() - * @see MPU6050_RA_I2C_SLV4_REG + * @see MPU9150_RA_I2C_SLV4_REG */ -void MPU6050::setSlave4Register(uint8_t reg) { - I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV4_REG, reg); +void MPU9150::setSlave4Register(uint8_t reg) { + I2Cdev::writeByte(devAddr, MPU9150_RA_I2C_SLV4_REG, reg); } /** Set new byte to write to Slave 4. * This register stores the data to be written into the Slave 4. If I2C_SLV4_RW * is set 1 (set to read), this register has no effect. * @param data New byte to write to Slave 4 - * @see MPU6050_RA_I2C_SLV4_DO + * @see MPU9150_RA_I2C_SLV4_DO */ -void MPU6050::setSlave4OutputByte(uint8_t data) { - I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV4_DO, data); +void MPU9150::setSlave4OutputByte(uint8_t data) { + I2Cdev::writeByte(devAddr, MPU9150_RA_I2C_SLV4_DO, data); } /** Get the enabled value for the Slave 4. * When set to 1, this bit enables Slave 4 for data transfer operations. When * cleared to 0, this bit disables Slave 4 from data transfer operations. * @return Current enabled value for Slave 4 - * @see MPU6050_RA_I2C_SLV4_CTRL + * @see MPU9150_RA_I2C_SLV4_CTRL */ -bool MPU6050::getSlave4Enabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_EN_BIT, buffer); +bool MPU9150::getSlave4Enabled() { + I2Cdev::readBit(devAddr, MPU9150_RA_I2C_SLV4_CTRL, MPU9150_I2C_SLV4_EN_BIT, buffer); return buffer[0]; } /** Set the enabled value for Slave 4. * @param enabled New enabled value for Slave 4 * @see getSlave4Enabled() - * @see MPU6050_RA_I2C_SLV4_CTRL + * @see MPU9150_RA_I2C_SLV4_CTRL */ -void MPU6050::setSlave4Enabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_EN_BIT, enabled); +void MPU9150::setSlave4Enabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9150_RA_I2C_SLV4_CTRL, MPU9150_I2C_SLV4_EN_BIT, enabled); } /** Get the enabled value for Slave 4 transaction interrupts. * When set to 1, this bit enables the generation of an interrupt signal upon @@ -1137,19 +1137,19 @@ void MPU6050::setSlave4Enabled(bool enabled) { * The interrupt status can be observed in Register 54. * * @return Current enabled value for Slave 4 transaction interrupts. - * @see MPU6050_RA_I2C_SLV4_CTRL + * @see MPU9150_RA_I2C_SLV4_CTRL */ -bool MPU6050::getSlave4InterruptEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_INT_EN_BIT, buffer); +bool MPU9150::getSlave4InterruptEnabled() { + I2Cdev::readBit(devAddr, MPU9150_RA_I2C_SLV4_CTRL, MPU9150_I2C_SLV4_INT_EN_BIT, buffer); return buffer[0]; } /** Set the enabled value for Slave 4 transaction interrupts. * @param enabled New enabled value for Slave 4 transaction interrupts. * @see getSlave4InterruptEnabled() - * @see MPU6050_RA_I2C_SLV4_CTRL + * @see MPU9150_RA_I2C_SLV4_CTRL */ -void MPU6050::setSlave4InterruptEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_INT_EN_BIT, enabled); +void MPU9150::setSlave4InterruptEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9150_RA_I2C_SLV4_CTRL, MPU9150_I2C_SLV4_INT_EN_BIT, enabled); } /** Get write mode for Slave 4. * When set to 1, the transaction will read or write data only. When cleared to @@ -1158,19 +1158,19 @@ void MPU6050::setSlave4InterruptEnabled(bool enabled) { * Slave device to/from which the ensuing data transaction will take place. * * @return Current write mode for Slave 4 (0 = register address + data, 1 = data only) - * @see MPU6050_RA_I2C_SLV4_CTRL + * @see MPU9150_RA_I2C_SLV4_CTRL */ -bool MPU6050::getSlave4WriteMode() { - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_REG_DIS_BIT, buffer); +bool MPU9150::getSlave4WriteMode() { + I2Cdev::readBit(devAddr, MPU9150_RA_I2C_SLV4_CTRL, MPU9150_I2C_SLV4_REG_DIS_BIT, buffer); return buffer[0]; } /** Set write mode for the Slave 4. * @param mode New write mode for Slave 4 (0 = register address + data, 1 = data only) * @see getSlave4WriteMode() - * @see MPU6050_RA_I2C_SLV4_CTRL + * @see MPU9150_RA_I2C_SLV4_CTRL */ -void MPU6050::setSlave4WriteMode(bool mode) { - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_REG_DIS_BIT, mode); +void MPU9150::setSlave4WriteMode(bool mode) { + I2Cdev::writeBit(devAddr, MPU9150_RA_I2C_SLV4_CTRL, MPU9150_I2C_SLV4_REG_DIS_BIT, mode); } /** Get Slave 4 master delay value. * This configures the reduced access rate of I2C slaves relative to the Sample @@ -1185,28 +1185,28 @@ void MPU6050::setSlave4WriteMode(bool mode) { * further information regarding the Sample Rate, please refer to register 25. * * @return Current Slave 4 master delay value - * @see MPU6050_RA_I2C_SLV4_CTRL + * @see MPU9150_RA_I2C_SLV4_CTRL */ -uint8_t MPU6050::getSlave4MasterDelay() { - I2Cdev::readBits(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_MST_DLY_BIT, MPU6050_I2C_SLV4_MST_DLY_LENGTH, buffer); +uint8_t MPU9150::getSlave4MasterDelay() { + I2Cdev::readBits(devAddr, MPU9150_RA_I2C_SLV4_CTRL, MPU9150_I2C_SLV4_MST_DLY_BIT, MPU9150_I2C_SLV4_MST_DLY_LENGTH, buffer); return buffer[0]; } /** Set Slave 4 master delay value. * @param delay New Slave 4 master delay value * @see getSlave4MasterDelay() - * @see MPU6050_RA_I2C_SLV4_CTRL + * @see MPU9150_RA_I2C_SLV4_CTRL */ -void MPU6050::setSlave4MasterDelay(uint8_t delay) { - I2Cdev::writeBits(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_MST_DLY_BIT, MPU6050_I2C_SLV4_MST_DLY_LENGTH, delay); +void MPU9150::setSlave4MasterDelay(uint8_t delay) { + I2Cdev::writeBits(devAddr, MPU9150_RA_I2C_SLV4_CTRL, MPU9150_I2C_SLV4_MST_DLY_BIT, MPU9150_I2C_SLV4_MST_DLY_LENGTH, delay); } /** Get last available byte read from Slave 4. * This register stores the data read from Slave 4. This field is populated * after a read transaction. * @return Last available byte read from to Slave 4 - * @see MPU6050_RA_I2C_SLV4_DI + * @see MPU9150_RA_I2C_SLV4_DI */ -uint8_t MPU6050::getSlate4InputByte() { - I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV4_DI, buffer); +uint8_t MPU9150::getSlate4InputByte() { + I2Cdev::readByte(devAddr, MPU9150_RA_I2C_SLV4_DI, buffer); return buffer[0]; } @@ -1219,10 +1219,10 @@ uint8_t MPU6050::getSlate4InputByte() { * bit will cause an interrupt if FSYNC_INT_EN is asserted in INT_PIN_CFG * (Register 55). * @return FSYNC interrupt status - * @see MPU6050_RA_I2C_MST_STATUS + * @see MPU9150_RA_I2C_MST_STATUS */ -bool MPU6050::getPassthroughStatus() { - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_PASS_THROUGH_BIT, buffer); +bool MPU9150::getPassthroughStatus() { + I2Cdev::readBit(devAddr, MPU9150_RA_I2C_MST_STATUS, MPU9150_MST_PASS_THROUGH_BIT, buffer); return buffer[0]; } /** Get Slave 4 transaction done status. @@ -1231,10 +1231,10 @@ bool MPU6050::getPassthroughStatus() { * (Register 56) is asserted and if the SLV_4_DONE_INT bit is asserted in the * I2C_SLV4_CTRL register (Register 52). * @return Slave 4 transaction done status - * @see MPU6050_RA_I2C_MST_STATUS + * @see MPU9150_RA_I2C_MST_STATUS */ -bool MPU6050::getSlave4IsDone() { - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV4_DONE_BIT, buffer); +bool MPU9150::getSlave4IsDone() { + I2Cdev::readBit(devAddr, MPU9150_RA_I2C_MST_STATUS, MPU9150_MST_I2C_SLV4_DONE_BIT, buffer); return buffer[0]; } /** Get master arbitration lost status. @@ -1242,10 +1242,10 @@ bool MPU6050::getSlave4IsDone() { * the auxiliary I2C bus (an error condition). This triggers an interrupt if the * I2C_MST_INT_EN bit in the INT_ENABLE register (Register 56) is asserted. * @return Master arbitration lost status - * @see MPU6050_RA_I2C_MST_STATUS + * @see MPU9150_RA_I2C_MST_STATUS */ -bool MPU6050::getLostArbitration() { - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_LOST_ARB_BIT, buffer); +bool MPU9150::getLostArbitration() { + I2Cdev::readBit(devAddr, MPU9150_RA_I2C_MST_STATUS, MPU9150_MST_I2C_LOST_ARB_BIT, buffer); return buffer[0]; } /** Get Slave 4 NACK status. @@ -1253,10 +1253,10 @@ bool MPU6050::getLostArbitration() { * transaction with Slave 4. This triggers an interrupt if the I2C_MST_INT_EN * bit in the INT_ENABLE register (Register 56) is asserted. * @return Slave 4 NACK interrupt status - * @see MPU6050_RA_I2C_MST_STATUS + * @see MPU9150_RA_I2C_MST_STATUS */ -bool MPU6050::getSlave4Nack() { - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV4_NACK_BIT, buffer); +bool MPU9150::getSlave4Nack() { + I2Cdev::readBit(devAddr, MPU9150_RA_I2C_MST_STATUS, MPU9150_MST_I2C_SLV4_NACK_BIT, buffer); return buffer[0]; } /** Get Slave 3 NACK status. @@ -1264,10 +1264,10 @@ bool MPU6050::getSlave4Nack() { * transaction with Slave 3. This triggers an interrupt if the I2C_MST_INT_EN * bit in the INT_ENABLE register (Register 56) is asserted. * @return Slave 3 NACK interrupt status - * @see MPU6050_RA_I2C_MST_STATUS + * @see MPU9150_RA_I2C_MST_STATUS */ -bool MPU6050::getSlave3Nack() { - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV3_NACK_BIT, buffer); +bool MPU9150::getSlave3Nack() { + I2Cdev::readBit(devAddr, MPU9150_RA_I2C_MST_STATUS, MPU9150_MST_I2C_SLV3_NACK_BIT, buffer); return buffer[0]; } /** Get Slave 2 NACK status. @@ -1275,10 +1275,10 @@ bool MPU6050::getSlave3Nack() { * transaction with Slave 2. This triggers an interrupt if the I2C_MST_INT_EN * bit in the INT_ENABLE register (Register 56) is asserted. * @return Slave 2 NACK interrupt status - * @see MPU6050_RA_I2C_MST_STATUS + * @see MPU9150_RA_I2C_MST_STATUS */ -bool MPU6050::getSlave2Nack() { - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV2_NACK_BIT, buffer); +bool MPU9150::getSlave2Nack() { + I2Cdev::readBit(devAddr, MPU9150_RA_I2C_MST_STATUS, MPU9150_MST_I2C_SLV2_NACK_BIT, buffer); return buffer[0]; } /** Get Slave 1 NACK status. @@ -1286,10 +1286,10 @@ bool MPU6050::getSlave2Nack() { * transaction with Slave 1. This triggers an interrupt if the I2C_MST_INT_EN * bit in the INT_ENABLE register (Register 56) is asserted. * @return Slave 1 NACK interrupt status - * @see MPU6050_RA_I2C_MST_STATUS + * @see MPU9150_RA_I2C_MST_STATUS */ -bool MPU6050::getSlave1Nack() { - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV1_NACK_BIT, buffer); +bool MPU9150::getSlave1Nack() { + I2Cdev::readBit(devAddr, MPU9150_RA_I2C_MST_STATUS, MPU9150_MST_I2C_SLV1_NACK_BIT, buffer); return buffer[0]; } /** Get Slave 0 NACK status. @@ -1297,10 +1297,10 @@ bool MPU6050::getSlave1Nack() { * transaction with Slave 0. This triggers an interrupt if the I2C_MST_INT_EN * bit in the INT_ENABLE register (Register 56) is asserted. * @return Slave 0 NACK interrupt status - * @see MPU6050_RA_I2C_MST_STATUS + * @see MPU9150_RA_I2C_MST_STATUS */ -bool MPU6050::getSlave0Nack() { - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV0_NACK_BIT, buffer); +bool MPU9150::getSlave0Nack() { + I2Cdev::readBit(devAddr, MPU9150_RA_I2C_MST_STATUS, MPU9150_MST_I2C_SLV0_NACK_BIT, buffer); return buffer[0]; } @@ -1309,116 +1309,116 @@ bool MPU6050::getSlave0Nack() { /** Get interrupt logic level mode. * Will be set 0 for active-high, 1 for active-low. * @return Current interrupt mode (0=active-high, 1=active-low) - * @see MPU6050_RA_INT_PIN_CFG - * @see MPU6050_INTCFG_INT_LEVEL_BIT + * @see MPU9150_RA_INT_PIN_CFG + * @see MPU9150_INTCFG_INT_LEVEL_BIT */ -bool MPU6050::getInterruptMode() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_LEVEL_BIT, buffer); +bool MPU9150::getInterruptMode() { + I2Cdev::readBit(devAddr, MPU9150_RA_INT_PIN_CFG, MPU9150_INTCFG_INT_LEVEL_BIT, buffer); return buffer[0]; } /** Set interrupt logic level mode. * @param mode New interrupt mode (0=active-high, 1=active-low) * @see getInterruptMode() - * @see MPU6050_RA_INT_PIN_CFG - * @see MPU6050_INTCFG_INT_LEVEL_BIT + * @see MPU9150_RA_INT_PIN_CFG + * @see MPU9150_INTCFG_INT_LEVEL_BIT */ -void MPU6050::setInterruptMode(bool mode) { - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_LEVEL_BIT, mode); +void MPU9150::setInterruptMode(bool mode) { + I2Cdev::writeBit(devAddr, MPU9150_RA_INT_PIN_CFG, MPU9150_INTCFG_INT_LEVEL_BIT, mode); } /** Get interrupt drive mode. * Will be set 0 for push-pull, 1 for open-drain. * @return Current interrupt drive mode (0=push-pull, 1=open-drain) - * @see MPU6050_RA_INT_PIN_CFG - * @see MPU6050_INTCFG_INT_OPEN_BIT + * @see MPU9150_RA_INT_PIN_CFG + * @see MPU9150_INTCFG_INT_OPEN_BIT */ -bool MPU6050::getInterruptDrive() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_OPEN_BIT, buffer); +bool MPU9150::getInterruptDrive() { + I2Cdev::readBit(devAddr, MPU9150_RA_INT_PIN_CFG, MPU9150_INTCFG_INT_OPEN_BIT, buffer); return buffer[0]; } /** Set interrupt drive mode. * @param drive New interrupt drive mode (0=push-pull, 1=open-drain) * @see getInterruptDrive() - * @see MPU6050_RA_INT_PIN_CFG - * @see MPU6050_INTCFG_INT_OPEN_BIT + * @see MPU9150_RA_INT_PIN_CFG + * @see MPU9150_INTCFG_INT_OPEN_BIT */ -void MPU6050::setInterruptDrive(bool drive) { - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_OPEN_BIT, drive); +void MPU9150::setInterruptDrive(bool drive) { + I2Cdev::writeBit(devAddr, MPU9150_RA_INT_PIN_CFG, MPU9150_INTCFG_INT_OPEN_BIT, drive); } /** Get interrupt latch mode. * Will be set 0 for 50us-pulse, 1 for latch-until-int-cleared. * @return Current latch mode (0=50us-pulse, 1=latch-until-int-cleared) - * @see MPU6050_RA_INT_PIN_CFG - * @see MPU6050_INTCFG_LATCH_INT_EN_BIT + * @see MPU9150_RA_INT_PIN_CFG + * @see MPU9150_INTCFG_LATCH_INT_EN_BIT */ -bool MPU6050::getInterruptLatch() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_LATCH_INT_EN_BIT, buffer); +bool MPU9150::getInterruptLatch() { + I2Cdev::readBit(devAddr, MPU9150_RA_INT_PIN_CFG, MPU9150_INTCFG_LATCH_INT_EN_BIT, buffer); return buffer[0]; } /** Set interrupt latch mode. * @param latch New latch mode (0=50us-pulse, 1=latch-until-int-cleared) * @see getInterruptLatch() - * @see MPU6050_RA_INT_PIN_CFG - * @see MPU6050_INTCFG_LATCH_INT_EN_BIT + * @see MPU9150_RA_INT_PIN_CFG + * @see MPU9150_INTCFG_LATCH_INT_EN_BIT */ -void MPU6050::setInterruptLatch(bool latch) { - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_LATCH_INT_EN_BIT, latch); +void MPU9150::setInterruptLatch(bool latch) { + I2Cdev::writeBit(devAddr, MPU9150_RA_INT_PIN_CFG, MPU9150_INTCFG_LATCH_INT_EN_BIT, latch); } /** Get interrupt latch clear mode. * Will be set 0 for status-read-only, 1 for any-register-read. * @return Current latch clear mode (0=status-read-only, 1=any-register-read) - * @see MPU6050_RA_INT_PIN_CFG - * @see MPU6050_INTCFG_INT_RD_CLEAR_BIT + * @see MPU9150_RA_INT_PIN_CFG + * @see MPU9150_INTCFG_INT_RD_CLEAR_BIT */ -bool MPU6050::getInterruptLatchClear() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_RD_CLEAR_BIT, buffer); +bool MPU9150::getInterruptLatchClear() { + I2Cdev::readBit(devAddr, MPU9150_RA_INT_PIN_CFG, MPU9150_INTCFG_INT_RD_CLEAR_BIT, buffer); return buffer[0]; } /** Set interrupt latch clear mode. * @param clear New latch clear mode (0=status-read-only, 1=any-register-read) * @see getInterruptLatchClear() - * @see MPU6050_RA_INT_PIN_CFG - * @see MPU6050_INTCFG_INT_RD_CLEAR_BIT + * @see MPU9150_RA_INT_PIN_CFG + * @see MPU9150_INTCFG_INT_RD_CLEAR_BIT */ -void MPU6050::setInterruptLatchClear(bool clear) { - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_RD_CLEAR_BIT, clear); +void MPU9150::setInterruptLatchClear(bool clear) { + I2Cdev::writeBit(devAddr, MPU9150_RA_INT_PIN_CFG, MPU9150_INTCFG_INT_RD_CLEAR_BIT, clear); } /** Get FSYNC interrupt logic level mode. * @return Current FSYNC interrupt mode (0=active-high, 1=active-low) * @see getFSyncInterruptMode() - * @see MPU6050_RA_INT_PIN_CFG - * @see MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT + * @see MPU9150_RA_INT_PIN_CFG + * @see MPU9150_INTCFG_FSYNC_INT_LEVEL_BIT */ -bool MPU6050::getFSyncInterruptLevel() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT, buffer); +bool MPU9150::getFSyncInterruptLevel() { + I2Cdev::readBit(devAddr, MPU9150_RA_INT_PIN_CFG, MPU9150_INTCFG_FSYNC_INT_LEVEL_BIT, buffer); return buffer[0]; } /** Set FSYNC interrupt logic level mode. * @param mode New FSYNC interrupt mode (0=active-high, 1=active-low) * @see getFSyncInterruptMode() - * @see MPU6050_RA_INT_PIN_CFG - * @see MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT + * @see MPU9150_RA_INT_PIN_CFG + * @see MPU9150_INTCFG_FSYNC_INT_LEVEL_BIT */ -void MPU6050::setFSyncInterruptLevel(bool level) { - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT, level); +void MPU9150::setFSyncInterruptLevel(bool level) { + I2Cdev::writeBit(devAddr, MPU9150_RA_INT_PIN_CFG, MPU9150_INTCFG_FSYNC_INT_LEVEL_BIT, level); } /** Get FSYNC pin interrupt enabled setting. * Will be set 0 for disabled, 1 for enabled. * @return Current interrupt enabled setting - * @see MPU6050_RA_INT_PIN_CFG - * @see MPU6050_INTCFG_FSYNC_INT_EN_BIT + * @see MPU9150_RA_INT_PIN_CFG + * @see MPU9150_INTCFG_FSYNC_INT_EN_BIT */ -bool MPU6050::getFSyncInterruptEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_EN_BIT, buffer); +bool MPU9150::getFSyncInterruptEnabled() { + I2Cdev::readBit(devAddr, MPU9150_RA_INT_PIN_CFG, MPU9150_INTCFG_FSYNC_INT_EN_BIT, buffer); return buffer[0]; } /** Set FSYNC pin interrupt enabled setting. * @param enabled New FSYNC pin interrupt enabled setting * @see getFSyncInterruptEnabled() - * @see MPU6050_RA_INT_PIN_CFG - * @see MPU6050_INTCFG_FSYNC_INT_EN_BIT + * @see MPU9150_RA_INT_PIN_CFG + * @see MPU9150_INTCFG_FSYNC_INT_EN_BIT */ -void MPU6050::setFSyncInterruptEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_EN_BIT, enabled); +void MPU9150::setFSyncInterruptEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9150_RA_INT_PIN_CFG, MPU9150_INTCFG_FSYNC_INT_EN_BIT, enabled); } /** Get I2C bypass enabled status. * When this bit is equal to 1 and I2C_MST_EN (Register 106 bit[5]) is equal to @@ -1428,11 +1428,11 @@ void MPU6050::setFSyncInterruptEnabled(bool enabled) { * bus of the MPU-60X0 regardless of the state of I2C_MST_EN (Register 106 * bit[5]). * @return Current I2C bypass enabled status - * @see MPU6050_RA_INT_PIN_CFG - * @see MPU6050_INTCFG_I2C_BYPASS_EN_BIT + * @see MPU9150_RA_INT_PIN_CFG + * @see MPU9150_INTCFG_I2C_BYPASS_EN_BIT */ -bool MPU6050::getI2CBypassEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_I2C_BYPASS_EN_BIT, buffer); +bool MPU9150::getI2CBypassEnabled() { + I2Cdev::readBit(devAddr, MPU9150_RA_INT_PIN_CFG, MPU9150_INTCFG_I2C_BYPASS_EN_BIT, buffer); return buffer[0]; } /** Set I2C bypass enabled status. @@ -1443,11 +1443,11 @@ bool MPU6050::getI2CBypassEnabled() { * bus of the MPU-60X0 regardless of the state of I2C_MST_EN (Register 106 * bit[5]). * @param enabled New I2C bypass enabled status - * @see MPU6050_RA_INT_PIN_CFG - * @see MPU6050_INTCFG_I2C_BYPASS_EN_BIT + * @see MPU9150_RA_INT_PIN_CFG + * @see MPU9150_INTCFG_I2C_BYPASS_EN_BIT */ -void MPU6050::setI2CBypassEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_I2C_BYPASS_EN_BIT, enabled); +void MPU9150::setI2CBypassEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9150_RA_INT_PIN_CFG, MPU9150_INTCFG_I2C_BYPASS_EN_BIT, enabled); } /** Get reference clock output enabled status. * When this bit is equal to 1, a reference clock output is provided at the @@ -1455,11 +1455,11 @@ void MPU6050::setI2CBypassEnabled(bool enabled) { * further information regarding CLKOUT, please refer to the MPU-60X0 Product * Specification document. * @return Current reference clock output enabled status - * @see MPU6050_RA_INT_PIN_CFG - * @see MPU6050_INTCFG_CLKOUT_EN_BIT + * @see MPU9150_RA_INT_PIN_CFG + * @see MPU9150_INTCFG_CLKOUT_EN_BIT */ -bool MPU6050::getClockOutputEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_CLKOUT_EN_BIT, buffer); +bool MPU9150::getClockOutputEnabled() { + I2Cdev::readBit(devAddr, MPU9150_RA_INT_PIN_CFG, MPU9150_INTCFG_CLKOUT_EN_BIT, buffer); return buffer[0]; } /** Set reference clock output enabled status. @@ -1468,11 +1468,11 @@ bool MPU6050::getClockOutputEnabled() { * further information regarding CLKOUT, please refer to the MPU-60X0 Product * Specification document. * @param enabled New reference clock output enabled status - * @see MPU6050_RA_INT_PIN_CFG - * @see MPU6050_INTCFG_CLKOUT_EN_BIT + * @see MPU9150_RA_INT_PIN_CFG + * @see MPU9150_INTCFG_CLKOUT_EN_BIT */ -void MPU6050::setClockOutputEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_CLKOUT_EN_BIT, enabled); +void MPU9150::setClockOutputEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9150_RA_INT_PIN_CFG, MPU9150_INTCFG_CLKOUT_EN_BIT, enabled); } // INT_ENABLE register @@ -1481,11 +1481,11 @@ void MPU6050::setClockOutputEnabled(bool enabled) { * Full register byte for all interrupts, for quick reading. Each bit will be * set 0 for disabled, 1 for enabled. * @return Current interrupt enabled status - * @see MPU6050_RA_INT_ENABLE - * @see MPU6050_INTERRUPT_FF_BIT + * @see MPU9150_RA_INT_ENABLE + * @see MPU9150_INTERRUPT_FF_BIT **/ -uint8_t MPU6050::getIntEnabled() { - I2Cdev::readByte(devAddr, MPU6050_RA_INT_ENABLE, buffer); +uint8_t MPU9150::getIntEnabled() { + I2Cdev::readByte(devAddr, MPU9150_RA_INT_ENABLE, buffer); return buffer[0]; } /** Set full interrupt enabled status. @@ -1493,127 +1493,127 @@ uint8_t MPU6050::getIntEnabled() { * set 0 for disabled, 1 for enabled. * @param enabled New interrupt enabled status * @see getIntFreefallEnabled() - * @see MPU6050_RA_INT_ENABLE - * @see MPU6050_INTERRUPT_FF_BIT + * @see MPU9150_RA_INT_ENABLE + * @see MPU9150_INTERRUPT_FF_BIT **/ -void MPU6050::setIntEnabled(uint8_t enabled) { - I2Cdev::writeByte(devAddr, MPU6050_RA_INT_ENABLE, enabled); +void MPU9150::setIntEnabled(uint8_t enabled) { + I2Cdev::writeByte(devAddr, MPU9150_RA_INT_ENABLE, enabled); } /** Get Free Fall interrupt enabled status. * Will be set 0 for disabled, 1 for enabled. * @return Current interrupt enabled status - * @see MPU6050_RA_INT_ENABLE - * @see MPU6050_INTERRUPT_FF_BIT + * @see MPU9150_RA_INT_ENABLE + * @see MPU9150_INTERRUPT_FF_BIT **/ -bool MPU6050::getIntFreefallEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FF_BIT, buffer); +bool MPU9150::getIntFreefallEnabled() { + I2Cdev::readBit(devAddr, MPU9150_RA_INT_ENABLE, MPU9150_INTERRUPT_FF_BIT, buffer); return buffer[0]; } /** Set Free Fall interrupt enabled status. * @param enabled New interrupt enabled status * @see getIntFreefallEnabled() - * @see MPU6050_RA_INT_ENABLE - * @see MPU6050_INTERRUPT_FF_BIT + * @see MPU9150_RA_INT_ENABLE + * @see MPU9150_INTERRUPT_FF_BIT **/ -void MPU6050::setIntFreefallEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FF_BIT, enabled); +void MPU9150::setIntFreefallEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9150_RA_INT_ENABLE, MPU9150_INTERRUPT_FF_BIT, enabled); } /** Get Motion Detection interrupt enabled status. * Will be set 0 for disabled, 1 for enabled. * @return Current interrupt enabled status - * @see MPU6050_RA_INT_ENABLE - * @see MPU6050_INTERRUPT_MOT_BIT + * @see MPU9150_RA_INT_ENABLE + * @see MPU9150_INTERRUPT_MOT_BIT **/ -bool MPU6050::getIntMotionEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_MOT_BIT, buffer); +bool MPU9150::getIntMotionEnabled() { + I2Cdev::readBit(devAddr, MPU9150_RA_INT_ENABLE, MPU9150_INTERRUPT_MOT_BIT, buffer); return buffer[0]; } /** Set Motion Detection interrupt enabled status. * @param enabled New interrupt enabled status * @see getIntMotionEnabled() - * @see MPU6050_RA_INT_ENABLE - * @see MPU6050_INTERRUPT_MOT_BIT + * @see MPU9150_RA_INT_ENABLE + * @see MPU9150_INTERRUPT_MOT_BIT **/ -void MPU6050::setIntMotionEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_MOT_BIT, enabled); +void MPU9150::setIntMotionEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9150_RA_INT_ENABLE, MPU9150_INTERRUPT_MOT_BIT, enabled); } /** Get Zero Motion Detection interrupt enabled status. * Will be set 0 for disabled, 1 for enabled. * @return Current interrupt enabled status - * @see MPU6050_RA_INT_ENABLE - * @see MPU6050_INTERRUPT_ZMOT_BIT + * @see MPU9150_RA_INT_ENABLE + * @see MPU9150_INTERRUPT_ZMOT_BIT **/ -bool MPU6050::getIntZeroMotionEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_ZMOT_BIT, buffer); +bool MPU9150::getIntZeroMotionEnabled() { + I2Cdev::readBit(devAddr, MPU9150_RA_INT_ENABLE, MPU9150_INTERRUPT_ZMOT_BIT, buffer); return buffer[0]; } /** Set Zero Motion Detection interrupt enabled status. * @param enabled New interrupt enabled status * @see getIntZeroMotionEnabled() - * @see MPU6050_RA_INT_ENABLE - * @see MPU6050_INTERRUPT_ZMOT_BIT + * @see MPU9150_RA_INT_ENABLE + * @see MPU9150_INTERRUPT_ZMOT_BIT **/ -void MPU6050::setIntZeroMotionEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_ZMOT_BIT, enabled); +void MPU9150::setIntZeroMotionEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9150_RA_INT_ENABLE, MPU9150_INTERRUPT_ZMOT_BIT, enabled); } /** Get FIFO Buffer Overflow interrupt enabled status. * Will be set 0 for disabled, 1 for enabled. * @return Current interrupt enabled status - * @see MPU6050_RA_INT_ENABLE - * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT + * @see MPU9150_RA_INT_ENABLE + * @see MPU9150_INTERRUPT_FIFO_OFLOW_BIT **/ -bool MPU6050::getIntFIFOBufferOverflowEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, buffer); +bool MPU9150::getIntFIFOBufferOverflowEnabled() { + I2Cdev::readBit(devAddr, MPU9150_RA_INT_ENABLE, MPU9150_INTERRUPT_FIFO_OFLOW_BIT, buffer); return buffer[0]; } /** Set FIFO Buffer Overflow interrupt enabled status. * @param enabled New interrupt enabled status * @see getIntFIFOBufferOverflowEnabled() - * @see MPU6050_RA_INT_ENABLE - * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT + * @see MPU9150_RA_INT_ENABLE + * @see MPU9150_INTERRUPT_FIFO_OFLOW_BIT **/ -void MPU6050::setIntFIFOBufferOverflowEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, enabled); +void MPU9150::setIntFIFOBufferOverflowEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9150_RA_INT_ENABLE, MPU9150_INTERRUPT_FIFO_OFLOW_BIT, enabled); } /** Get I2C Master interrupt enabled status. * This enables any of the I2C Master interrupt sources to generate an * interrupt. Will be set 0 for disabled, 1 for enabled. * @return Current interrupt enabled status - * @see MPU6050_RA_INT_ENABLE - * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT + * @see MPU9150_RA_INT_ENABLE + * @see MPU9150_INTERRUPT_I2C_MST_INT_BIT **/ -bool MPU6050::getIntI2CMasterEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_I2C_MST_INT_BIT, buffer); +bool MPU9150::getIntI2CMasterEnabled() { + I2Cdev::readBit(devAddr, MPU9150_RA_INT_ENABLE, MPU9150_INTERRUPT_I2C_MST_INT_BIT, buffer); return buffer[0]; } /** Set I2C Master interrupt enabled status. * @param enabled New interrupt enabled status * @see getIntI2CMasterEnabled() - * @see MPU6050_RA_INT_ENABLE - * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT + * @see MPU9150_RA_INT_ENABLE + * @see MPU9150_INTERRUPT_I2C_MST_INT_BIT **/ -void MPU6050::setIntI2CMasterEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_I2C_MST_INT_BIT, enabled); +void MPU9150::setIntI2CMasterEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9150_RA_INT_ENABLE, MPU9150_INTERRUPT_I2C_MST_INT_BIT, enabled); } /** Get Data Ready interrupt enabled setting. * This event occurs each time a write operation to all of the sensor registers * has been completed. Will be set 0 for disabled, 1 for enabled. * @return Current interrupt enabled status - * @see MPU6050_RA_INT_ENABLE - * @see MPU6050_INTERRUPT_DATA_RDY_BIT + * @see MPU9150_RA_INT_ENABLE + * @see MPU9150_INTERRUPT_DATA_RDY_BIT */ -bool MPU6050::getIntDataReadyEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DATA_RDY_BIT, buffer); +bool MPU9150::getIntDataReadyEnabled() { + I2Cdev::readBit(devAddr, MPU9150_RA_INT_ENABLE, MPU9150_INTERRUPT_DATA_RDY_BIT, buffer); return buffer[0]; } /** Set Data Ready interrupt enabled status. * @param enabled New interrupt enabled status * @see getIntDataReadyEnabled() - * @see MPU6050_RA_INT_CFG - * @see MPU6050_INTERRUPT_DATA_RDY_BIT + * @see MPU9150_RA_INT_CFG + * @see MPU9150_INTERRUPT_DATA_RDY_BIT */ -void MPU6050::setIntDataReadyEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DATA_RDY_BIT, enabled); +void MPU9150::setIntDataReadyEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9150_RA_INT_ENABLE, MPU9150_INTERRUPT_DATA_RDY_BIT, enabled); } // INT_STATUS register @@ -1623,54 +1623,54 @@ void MPU6050::setIntDataReadyEnabled(bool enabled) { * for getting multiple INT statuses, since each single bit read clears * all of them because it has to read the whole byte. * @return Current interrupt status - * @see MPU6050_RA_INT_STATUS + * @see MPU9150_RA_INT_STATUS */ -uint8_t MPU6050::getIntStatus() { - I2Cdev::readByte(devAddr, MPU6050_RA_INT_STATUS, buffer); +uint8_t MPU9150::getIntStatus() { + I2Cdev::readByte(devAddr, MPU9150_RA_INT_STATUS, buffer); return buffer[0]; } /** Get Free Fall interrupt status. * This bit automatically sets to 1 when a Free Fall interrupt has been * generated. The bit clears to 0 after the register has been read. * @return Current interrupt status - * @see MPU6050_RA_INT_STATUS - * @see MPU6050_INTERRUPT_FF_BIT + * @see MPU9150_RA_INT_STATUS + * @see MPU9150_INTERRUPT_FF_BIT */ -bool MPU6050::getIntFreefallStatus() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_FF_BIT, buffer); +bool MPU9150::getIntFreefallStatus() { + I2Cdev::readBit(devAddr, MPU9150_RA_INT_STATUS, MPU9150_INTERRUPT_FF_BIT, buffer); return buffer[0]; } /** Get Motion Detection interrupt status. * This bit automatically sets to 1 when a Motion Detection interrupt has been * generated. The bit clears to 0 after the register has been read. * @return Current interrupt status - * @see MPU6050_RA_INT_STATUS - * @see MPU6050_INTERRUPT_MOT_BIT + * @see MPU9150_RA_INT_STATUS + * @see MPU9150_INTERRUPT_MOT_BIT */ -bool MPU6050::getIntMotionStatus() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_MOT_BIT, buffer); +bool MPU9150::getIntMotionStatus() { + I2Cdev::readBit(devAddr, MPU9150_RA_INT_STATUS, MPU9150_INTERRUPT_MOT_BIT, buffer); return buffer[0]; } /** Get Zero Motion Detection interrupt status. * This bit automatically sets to 1 when a Zero Motion Detection interrupt has * been generated. The bit clears to 0 after the register has been read. * @return Current interrupt status - * @see MPU6050_RA_INT_STATUS - * @see MPU6050_INTERRUPT_ZMOT_BIT + * @see MPU9150_RA_INT_STATUS + * @see MPU9150_INTERRUPT_ZMOT_BIT */ -bool MPU6050::getIntZeroMotionStatus() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_ZMOT_BIT, buffer); +bool MPU9150::getIntZeroMotionStatus() { + I2Cdev::readBit(devAddr, MPU9150_RA_INT_STATUS, MPU9150_INTERRUPT_ZMOT_BIT, buffer); return buffer[0]; } /** Get FIFO Buffer Overflow interrupt status. * This bit automatically sets to 1 when a Free Fall interrupt has been * generated. The bit clears to 0 after the register has been read. * @return Current interrupt status - * @see MPU6050_RA_INT_STATUS - * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT + * @see MPU9150_RA_INT_STATUS + * @see MPU9150_INTERRUPT_FIFO_OFLOW_BIT */ -bool MPU6050::getIntFIFOBufferOverflowStatus() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, buffer); +bool MPU9150::getIntFIFOBufferOverflowStatus() { + I2Cdev::readBit(devAddr, MPU9150_RA_INT_STATUS, MPU9150_INTERRUPT_FIFO_OFLOW_BIT, buffer); return buffer[0]; } /** Get I2C Master interrupt status. @@ -1678,22 +1678,22 @@ bool MPU6050::getIntFIFOBufferOverflowStatus() { * generated. For a list of I2C Master interrupts, please refer to Register 54. * The bit clears to 0 after the register has been read. * @return Current interrupt status - * @see MPU6050_RA_INT_STATUS - * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT + * @see MPU9150_RA_INT_STATUS + * @see MPU9150_INTERRUPT_I2C_MST_INT_BIT */ -bool MPU6050::getIntI2CMasterStatus() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_I2C_MST_INT_BIT, buffer); +bool MPU9150::getIntI2CMasterStatus() { + I2Cdev::readBit(devAddr, MPU9150_RA_INT_STATUS, MPU9150_INTERRUPT_I2C_MST_INT_BIT, buffer); return buffer[0]; } /** Get Data Ready interrupt status. * This bit automatically sets to 1 when a Data Ready interrupt has been * generated. The bit clears to 0 after the register has been read. * @return Current interrupt status - * @see MPU6050_RA_INT_STATUS - * @see MPU6050_INTERRUPT_DATA_RDY_BIT + * @see MPU9150_RA_INT_STATUS + * @see MPU9150_INTERRUPT_DATA_RDY_BIT */ -bool MPU6050::getIntDataReadyStatus() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_DATA_RDY_BIT, buffer); +bool MPU9150::getIntDataReadyStatus() { + I2Cdev::readBit(devAddr, MPU9150_RA_INT_STATUS, MPU9150_INTERRUPT_DATA_RDY_BIT, buffer); return buffer[0]; } @@ -1713,15 +1713,15 @@ bool MPU6050::getIntDataReadyStatus() { * @see getMotion6() * @see getAcceleration() * @see getRotation() - * @see MPU6050_RA_ACCEL_XOUT_H + * @see MPU9150_RA_ACCEL_XOUT_H */ -void MPU6050::getMotion9(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz, int16_t* mx, int16_t* my, int16_t* mz) { +void MPU9150::getMotion9(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz, int16_t* mx, int16_t* my, int16_t* mz) { //get accel and gyro getMotion6(ax, ay, az, gx, gy, gz); //read mag - I2Cdev::writeByte(devAddr, MPU6050_RA_INT_PIN_CFG, 0x02); //set i2c bypass enable pin to true to access magnetometer + I2Cdev::writeByte(devAddr, MPU9150_RA_INT_PIN_CFG, 0x02); //set i2c bypass enable pin to true to access magnetometer delay(10); I2Cdev::writeByte(MPU9150_RA_MAG_ADDRESS, 0x0A, 0x01); //enable the magnetometer delay(10); @@ -1740,10 +1740,10 @@ void MPU6050::getMotion9(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int * @param gz 16-bit signed integer container for gyroscope Z-axis value * @see getAcceleration() * @see getRotation() - * @see MPU6050_RA_ACCEL_XOUT_H + * @see MPU9150_RA_ACCEL_XOUT_H */ -void MPU6050::getMotion6(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz) { - I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_XOUT_H, 14, buffer); +void MPU9150::getMotion6(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz) { + I2Cdev::readBytes(devAddr, MPU9150_RA_ACCEL_XOUT_H, 14, buffer); *ax = (((int16_t)buffer[0]) << 8) | buffer[1]; *ay = (((int16_t)buffer[2]) << 8) | buffer[3]; *az = (((int16_t)buffer[4]) << 8) | buffer[5]; @@ -1785,10 +1785,10 @@ void MPU6050::getMotion6(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int * @param x 16-bit signed integer container for X-axis acceleration * @param y 16-bit signed integer container for Y-axis acceleration * @param z 16-bit signed integer container for Z-axis acceleration - * @see MPU6050_RA_GYRO_XOUT_H + * @see MPU9150_RA_GYRO_XOUT_H */ -void MPU6050::getAcceleration(int16_t* x, int16_t* y, int16_t* z) { - I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_XOUT_H, 6, buffer); +void MPU9150::getAcceleration(int16_t* x, int16_t* y, int16_t* z) { + I2Cdev::readBytes(devAddr, MPU9150_RA_ACCEL_XOUT_H, 6, buffer); *x = (((int16_t)buffer[0]) << 8) | buffer[1]; *y = (((int16_t)buffer[2]) << 8) | buffer[3]; *z = (((int16_t)buffer[4]) << 8) | buffer[5]; @@ -1796,28 +1796,28 @@ void MPU6050::getAcceleration(int16_t* x, int16_t* y, int16_t* z) { /** Get X-axis accelerometer reading. * @return X-axis acceleration measurement in 16-bit 2's complement format * @see getMotion6() - * @see MPU6050_RA_ACCEL_XOUT_H + * @see MPU9150_RA_ACCEL_XOUT_H */ -int16_t MPU6050::getAccelerationX() { - I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_XOUT_H, 2, buffer); +int16_t MPU9150::getAccelerationX() { + I2Cdev::readBytes(devAddr, MPU9150_RA_ACCEL_XOUT_H, 2, buffer); return (((int16_t)buffer[0]) << 8) | buffer[1]; } /** Get Y-axis accelerometer reading. * @return Y-axis acceleration measurement in 16-bit 2's complement format * @see getMotion6() - * @see MPU6050_RA_ACCEL_YOUT_H + * @see MPU9150_RA_ACCEL_YOUT_H */ -int16_t MPU6050::getAccelerationY() { - I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_YOUT_H, 2, buffer); +int16_t MPU9150::getAccelerationY() { + I2Cdev::readBytes(devAddr, MPU9150_RA_ACCEL_YOUT_H, 2, buffer); return (((int16_t)buffer[0]) << 8) | buffer[1]; } /** Get Z-axis accelerometer reading. * @return Z-axis acceleration measurement in 16-bit 2's complement format * @see getMotion6() - * @see MPU6050_RA_ACCEL_ZOUT_H + * @see MPU9150_RA_ACCEL_ZOUT_H */ -int16_t MPU6050::getAccelerationZ() { - I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_ZOUT_H, 2, buffer); +int16_t MPU9150::getAccelerationZ() { + I2Cdev::readBytes(devAddr, MPU9150_RA_ACCEL_ZOUT_H, 2, buffer); return (((int16_t)buffer[0]) << 8) | buffer[1]; } @@ -1825,10 +1825,10 @@ int16_t MPU6050::getAccelerationZ() { /** Get current internal temperature. * @return Temperature reading in 16-bit 2's complement format - * @see MPU6050_RA_TEMP_OUT_H + * @see MPU9150_RA_TEMP_OUT_H */ -int16_t MPU6050::getTemperature() { - I2Cdev::readBytes(devAddr, MPU6050_RA_TEMP_OUT_H, 2, buffer); +int16_t MPU9150::getTemperature() { + I2Cdev::readBytes(devAddr, MPU9150_RA_TEMP_OUT_H, 2, buffer); return (((int16_t)buffer[0]) << 8) | buffer[1]; } @@ -1864,10 +1864,10 @@ int16_t MPU6050::getTemperature() { * @param y 16-bit signed integer container for Y-axis rotation * @param z 16-bit signed integer container for Z-axis rotation * @see getMotion6() - * @see MPU6050_RA_GYRO_XOUT_H + * @see MPU9150_RA_GYRO_XOUT_H */ -void MPU6050::getRotation(int16_t* x, int16_t* y, int16_t* z) { - I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_XOUT_H, 6, buffer); +void MPU9150::getRotation(int16_t* x, int16_t* y, int16_t* z) { + I2Cdev::readBytes(devAddr, MPU9150_RA_GYRO_XOUT_H, 6, buffer); *x = (((int16_t)buffer[0]) << 8) | buffer[1]; *y = (((int16_t)buffer[2]) << 8) | buffer[3]; *z = (((int16_t)buffer[4]) << 8) | buffer[5]; @@ -1875,28 +1875,28 @@ void MPU6050::getRotation(int16_t* x, int16_t* y, int16_t* z) { /** Get X-axis gyroscope reading. * @return X-axis rotation measurement in 16-bit 2's complement format * @see getMotion6() - * @see MPU6050_RA_GYRO_XOUT_H + * @see MPU9150_RA_GYRO_XOUT_H */ -int16_t MPU6050::getRotationX() { - I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_XOUT_H, 2, buffer); +int16_t MPU9150::getRotationX() { + I2Cdev::readBytes(devAddr, MPU9150_RA_GYRO_XOUT_H, 2, buffer); return (((int16_t)buffer[0]) << 8) | buffer[1]; } /** Get Y-axis gyroscope reading. * @return Y-axis rotation measurement in 16-bit 2's complement format * @see getMotion6() - * @see MPU6050_RA_GYRO_YOUT_H + * @see MPU9150_RA_GYRO_YOUT_H */ -int16_t MPU6050::getRotationY() { - I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_YOUT_H, 2, buffer); +int16_t MPU9150::getRotationY() { + I2Cdev::readBytes(devAddr, MPU9150_RA_GYRO_YOUT_H, 2, buffer); return (((int16_t)buffer[0]) << 8) | buffer[1]; } /** Get Z-axis gyroscope reading. * @return Z-axis rotation measurement in 16-bit 2's complement format * @see getMotion6() - * @see MPU6050_RA_GYRO_ZOUT_H + * @see MPU9150_RA_GYRO_ZOUT_H */ -int16_t MPU6050::getRotationZ() { - I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_ZOUT_H, 2, buffer); +int16_t MPU9150::getRotationZ() { + I2Cdev::readBytes(devAddr, MPU9150_RA_GYRO_ZOUT_H, 2, buffer); return (((int16_t)buffer[0]) << 8) | buffer[1]; } @@ -1976,8 +1976,8 @@ int16_t MPU6050::getRotationZ() { * @param position Starting position (0-23) * @return Byte read from register */ -uint8_t MPU6050::getExternalSensorByte(int position) { - I2Cdev::readByte(devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, buffer); +uint8_t MPU9150::getExternalSensorByte(int position) { + I2Cdev::readByte(devAddr, MPU9150_RA_EXT_SENS_DATA_00 + position, buffer); return buffer[0]; } /** Read word (2 bytes) from external sensor data registers. @@ -1985,8 +1985,8 @@ uint8_t MPU6050::getExternalSensorByte(int position) { * @return Word read from register * @see getExternalSensorByte() */ -uint16_t MPU6050::getExternalSensorWord(int position) { - I2Cdev::readBytes(devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, 2, buffer); +uint16_t MPU9150::getExternalSensorWord(int position) { + I2Cdev::readBytes(devAddr, MPU9150_RA_EXT_SENS_DATA_00 + position, 2, buffer); return (((uint16_t)buffer[0]) << 8) | buffer[1]; } /** Read double word (4 bytes) from external sensor data registers. @@ -1994,8 +1994,8 @@ uint16_t MPU6050::getExternalSensorWord(int position) { * @return Double word read from registers * @see getExternalSensorByte() */ -uint32_t MPU6050::getExternalSensorDWord(int position) { - I2Cdev::readBytes(devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, 4, buffer); +uint32_t MPU9150::getExternalSensorDWord(int position) { + I2Cdev::readBytes(devAddr, MPU9150_RA_EXT_SENS_DATA_00 + position, 4, buffer); return (((uint32_t)buffer[0]) << 24) | (((uint32_t)buffer[1]) << 16) | (((uint16_t)buffer[2]) << 8) | buffer[3]; } @@ -2003,65 +2003,65 @@ uint32_t MPU6050::getExternalSensorDWord(int position) { /** Get X-axis negative motion detection interrupt status. * @return Motion detection status - * @see MPU6050_RA_MOT_DETECT_STATUS - * @see MPU6050_MOTION_MOT_XNEG_BIT + * @see MPU9150_RA_MOT_DETECT_STATUS + * @see MPU9150_MOTION_MOT_XNEG_BIT */ -bool MPU6050::getXNegMotionDetected() { - I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_XNEG_BIT, buffer); +bool MPU9150::getXNegMotionDetected() { + I2Cdev::readBit(devAddr, MPU9150_RA_MOT_DETECT_STATUS, MPU9150_MOTION_MOT_XNEG_BIT, buffer); return buffer[0]; } /** Get X-axis positive motion detection interrupt status. * @return Motion detection status - * @see MPU6050_RA_MOT_DETECT_STATUS - * @see MPU6050_MOTION_MOT_XPOS_BIT + * @see MPU9150_RA_MOT_DETECT_STATUS + * @see MPU9150_MOTION_MOT_XPOS_BIT */ -bool MPU6050::getXPosMotionDetected() { - I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_XPOS_BIT, buffer); +bool MPU9150::getXPosMotionDetected() { + I2Cdev::readBit(devAddr, MPU9150_RA_MOT_DETECT_STATUS, MPU9150_MOTION_MOT_XPOS_BIT, buffer); return buffer[0]; } /** Get Y-axis negative motion detection interrupt status. * @return Motion detection status - * @see MPU6050_RA_MOT_DETECT_STATUS - * @see MPU6050_MOTION_MOT_YNEG_BIT + * @see MPU9150_RA_MOT_DETECT_STATUS + * @see MPU9150_MOTION_MOT_YNEG_BIT */ -bool MPU6050::getYNegMotionDetected() { - I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_YNEG_BIT, buffer); +bool MPU9150::getYNegMotionDetected() { + I2Cdev::readBit(devAddr, MPU9150_RA_MOT_DETECT_STATUS, MPU9150_MOTION_MOT_YNEG_BIT, buffer); return buffer[0]; } /** Get Y-axis positive motion detection interrupt status. * @return Motion detection status - * @see MPU6050_RA_MOT_DETECT_STATUS - * @see MPU6050_MOTION_MOT_YPOS_BIT + * @see MPU9150_RA_MOT_DETECT_STATUS + * @see MPU9150_MOTION_MOT_YPOS_BIT */ -bool MPU6050::getYPosMotionDetected() { - I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_YPOS_BIT, buffer); +bool MPU9150::getYPosMotionDetected() { + I2Cdev::readBit(devAddr, MPU9150_RA_MOT_DETECT_STATUS, MPU9150_MOTION_MOT_YPOS_BIT, buffer); return buffer[0]; } /** Get Z-axis negative motion detection interrupt status. * @return Motion detection status - * @see MPU6050_RA_MOT_DETECT_STATUS - * @see MPU6050_MOTION_MOT_ZNEG_BIT + * @see MPU9150_RA_MOT_DETECT_STATUS + * @see MPU9150_MOTION_MOT_ZNEG_BIT */ -bool MPU6050::getZNegMotionDetected() { - I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZNEG_BIT, buffer); +bool MPU9150::getZNegMotionDetected() { + I2Cdev::readBit(devAddr, MPU9150_RA_MOT_DETECT_STATUS, MPU9150_MOTION_MOT_ZNEG_BIT, buffer); return buffer[0]; } /** Get Z-axis positive motion detection interrupt status. * @return Motion detection status - * @see MPU6050_RA_MOT_DETECT_STATUS - * @see MPU6050_MOTION_MOT_ZPOS_BIT + * @see MPU9150_RA_MOT_DETECT_STATUS + * @see MPU9150_MOTION_MOT_ZPOS_BIT */ -bool MPU6050::getZPosMotionDetected() { - I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZPOS_BIT, buffer); +bool MPU9150::getZPosMotionDetected() { + I2Cdev::readBit(devAddr, MPU9150_RA_MOT_DETECT_STATUS, MPU9150_MOTION_MOT_ZPOS_BIT, buffer); return buffer[0]; } /** Get zero motion detection interrupt status. * @return Motion detection status - * @see MPU6050_RA_MOT_DETECT_STATUS - * @see MPU6050_MOTION_MOT_ZRMOT_BIT + * @see MPU9150_RA_MOT_DETECT_STATUS + * @see MPU9150_MOTION_MOT_ZRMOT_BIT */ -bool MPU6050::getZeroMotionDetected() { - I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZRMOT_BIT, buffer); +bool MPU9150::getZeroMotionDetected() { + I2Cdev::readBit(devAddr, MPU9150_RA_MOT_DETECT_STATUS, MPU9150_MOTION_MOT_ZRMOT_BIT, buffer); return buffer[0]; } @@ -2073,11 +2073,11 @@ bool MPU6050::getZeroMotionDetected() { * refer to Registers 37 to 39 and immediately following. * @param num Slave number (0-3) * @param data Byte to write - * @see MPU6050_RA_I2C_SLV0_DO + * @see MPU9150_RA_I2C_SLV0_DO */ -void MPU6050::setSlaveOutputByte(uint8_t num, uint8_t data) { +void MPU9150::setSlaveOutputByte(uint8_t num, uint8_t data) { if (num > 3) return; - I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV0_DO + num, data); + I2Cdev::writeByte(devAddr, MPU9150_RA_I2C_SLV0_DO + num, data); } // I2C_MST_DELAY_CTRL register @@ -2087,21 +2087,21 @@ void MPU6050::setSlaveOutputByte(uint8_t num, uint8_t data) { * shadowing. When DELAY_ES_SHADOW is set to 1, shadowing of external * sensor data is delayed until all data has been received. * @return Current external data shadow delay enabled status. - * @see MPU6050_RA_I2C_MST_DELAY_CTRL - * @see MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT + * @see MPU9150_RA_I2C_MST_DELAY_CTRL + * @see MPU9150_DELAYCTRL_DELAY_ES_SHADOW_BIT */ -bool MPU6050::getExternalShadowDelayEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT, buffer); +bool MPU9150::getExternalShadowDelayEnabled() { + I2Cdev::readBit(devAddr, MPU9150_RA_I2C_MST_DELAY_CTRL, MPU9150_DELAYCTRL_DELAY_ES_SHADOW_BIT, buffer); return buffer[0]; } /** Set external data shadow delay enabled status. * @param enabled New external data shadow delay enabled status. * @see getExternalShadowDelayEnabled() - * @see MPU6050_RA_I2C_MST_DELAY_CTRL - * @see MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT + * @see MPU9150_RA_I2C_MST_DELAY_CTRL + * @see MPU9150_DELAYCTRL_DELAY_ES_SHADOW_BIT */ -void MPU6050::setExternalShadowDelayEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT, enabled); +void MPU9150::setExternalShadowDelayEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9150_RA_I2C_MST_DELAY_CTRL, MPU9150_DELAYCTRL_DELAY_ES_SHADOW_BIT, enabled); } /** Get slave delay enabled status. * When a particular slave delay is enabled, the rate of access for the that @@ -2118,23 +2118,23 @@ void MPU6050::setExternalShadowDelayEnabled(bool enabled) { * * @param num Slave number (0-4) * @return Current slave delay enabled status. - * @see MPU6050_RA_I2C_MST_DELAY_CTRL - * @see MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT + * @see MPU9150_RA_I2C_MST_DELAY_CTRL + * @see MPU9150_DELAYCTRL_I2C_SLV0_DLY_EN_BIT */ -bool MPU6050::getSlaveDelayEnabled(uint8_t num) { - // MPU6050_DELAYCTRL_I2C_SLV4_DLY_EN_BIT is 4, SLV3 is 3, etc. +bool MPU9150::getSlaveDelayEnabled(uint8_t num) { + // MPU9150_DELAYCTRL_I2C_SLV4_DLY_EN_BIT is 4, SLV3 is 3, etc. if (num > 4) return 0; - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, num, buffer); + I2Cdev::readBit(devAddr, MPU9150_RA_I2C_MST_DELAY_CTRL, num, buffer); return buffer[0]; } /** Set slave delay enabled status. * @param num Slave number (0-4) * @param enabled New slave delay enabled status. - * @see MPU6050_RA_I2C_MST_DELAY_CTRL - * @see MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT + * @see MPU9150_RA_I2C_MST_DELAY_CTRL + * @see MPU9150_DELAYCTRL_I2C_SLV0_DLY_EN_BIT */ -void MPU6050::setSlaveDelayEnabled(uint8_t num, bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, num, enabled); +void MPU9150::setSlaveDelayEnabled(uint8_t num, bool enabled) { + I2Cdev::writeBit(devAddr, MPU9150_RA_I2C_MST_DELAY_CTRL, num, enabled); } // SIGNAL_PATH_RESET register @@ -2142,29 +2142,29 @@ void MPU6050::setSlaveDelayEnabled(uint8_t num, bool enabled) { /** Reset gyroscope signal path. * The reset will revert the signal path analog to digital converters and * filters to their power up configurations. - * @see MPU6050_RA_SIGNAL_PATH_RESET - * @see MPU6050_PATHRESET_GYRO_RESET_BIT + * @see MPU9150_RA_SIGNAL_PATH_RESET + * @see MPU9150_PATHRESET_GYRO_RESET_BIT */ -void MPU6050::resetGyroscopePath() { - I2Cdev::writeBit(devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_GYRO_RESET_BIT, true); +void MPU9150::resetGyroscopePath() { + I2Cdev::writeBit(devAddr, MPU9150_RA_SIGNAL_PATH_RESET, MPU9150_PATHRESET_GYRO_RESET_BIT, true); } /** Reset accelerometer signal path. * The reset will revert the signal path analog to digital converters and * filters to their power up configurations. - * @see MPU6050_RA_SIGNAL_PATH_RESET - * @see MPU6050_PATHRESET_ACCEL_RESET_BIT + * @see MPU9150_RA_SIGNAL_PATH_RESET + * @see MPU9150_PATHRESET_ACCEL_RESET_BIT */ -void MPU6050::resetAccelerometerPath() { - I2Cdev::writeBit(devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_ACCEL_RESET_BIT, true); +void MPU9150::resetAccelerometerPath() { + I2Cdev::writeBit(devAddr, MPU9150_RA_SIGNAL_PATH_RESET, MPU9150_PATHRESET_ACCEL_RESET_BIT, true); } /** Reset temperature sensor signal path. * The reset will revert the signal path analog to digital converters and * filters to their power up configurations. - * @see MPU6050_RA_SIGNAL_PATH_RESET - * @see MPU6050_PATHRESET_TEMP_RESET_BIT + * @see MPU9150_RA_SIGNAL_PATH_RESET + * @see MPU9150_PATHRESET_TEMP_RESET_BIT */ -void MPU6050::resetTemperaturePath() { - I2Cdev::writeBit(devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_TEMP_RESET_BIT, true); +void MPU9150::resetTemperaturePath() { + I2Cdev::writeBit(devAddr, MPU9150_RA_SIGNAL_PATH_RESET, MPU9150_PATHRESET_TEMP_RESET_BIT, true); } // MOT_DETECT_CTRL register @@ -2177,24 +2177,24 @@ void MPU6050::resetTemperaturePath() { * delay, of 4ms can be lengthened by up to 3ms. This additional delay is * specified in ACCEL_ON_DELAY in units of 1 LSB = 1 ms. The user may select * any value above zero unless instructed otherwise by InvenSense. Please refer - * to Section 8 of the MPU-6000/MPU-6050 Product Specification document for + * to Section 8 of the MPU-6000/MPU-9150 Product Specification document for * further information regarding the detection modules. * @return Current accelerometer power-on delay - * @see MPU6050_RA_MOT_DETECT_CTRL - * @see MPU6050_DETECT_ACCEL_ON_DELAY_BIT + * @see MPU9150_RA_MOT_DETECT_CTRL + * @see MPU9150_DETECT_ACCEL_ON_DELAY_BIT */ -uint8_t MPU6050::getAccelerometerPowerOnDelay() { - I2Cdev::readBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_ACCEL_ON_DELAY_BIT, MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH, buffer); +uint8_t MPU9150::getAccelerometerPowerOnDelay() { + I2Cdev::readBits(devAddr, MPU9150_RA_MOT_DETECT_CTRL, MPU9150_DETECT_ACCEL_ON_DELAY_BIT, MPU9150_DETECT_ACCEL_ON_DELAY_LENGTH, buffer); return buffer[0]; } /** Set accelerometer power-on delay. * @param delay New accelerometer power-on delay (0-3) * @see getAccelerometerPowerOnDelay() - * @see MPU6050_RA_MOT_DETECT_CTRL - * @see MPU6050_DETECT_ACCEL_ON_DELAY_BIT + * @see MPU9150_RA_MOT_DETECT_CTRL + * @see MPU9150_DETECT_ACCEL_ON_DELAY_BIT */ -void MPU6050::setAccelerometerPowerOnDelay(uint8_t delay) { - I2Cdev::writeBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_ACCEL_ON_DELAY_BIT, MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH, delay); +void MPU9150::setAccelerometerPowerOnDelay(uint8_t delay) { + I2Cdev::writeBits(devAddr, MPU9150_RA_MOT_DETECT_CTRL, MPU9150_DETECT_ACCEL_ON_DELAY_BIT, MPU9150_DETECT_ACCEL_ON_DELAY_LENGTH, delay); } /** Get Free Fall detection counter decrement configuration. * Detection is registered by the Free Fall detection module after accelerometer @@ -2219,21 +2219,21 @@ void MPU6050::setAccelerometerPowerOnDelay(uint8_t delay) { * please refer to Registers 29 to 32. * * @return Current decrement configuration - * @see MPU6050_RA_MOT_DETECT_CTRL - * @see MPU6050_DETECT_FF_COUNT_BIT + * @see MPU9150_RA_MOT_DETECT_CTRL + * @see MPU9150_DETECT_FF_COUNT_BIT */ -uint8_t MPU6050::getFreefallDetectionCounterDecrement() { - I2Cdev::readBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_FF_COUNT_BIT, MPU6050_DETECT_FF_COUNT_LENGTH, buffer); +uint8_t MPU9150::getFreefallDetectionCounterDecrement() { + I2Cdev::readBits(devAddr, MPU9150_RA_MOT_DETECT_CTRL, MPU9150_DETECT_FF_COUNT_BIT, MPU9150_DETECT_FF_COUNT_LENGTH, buffer); return buffer[0]; } /** Set Free Fall detection counter decrement configuration. * @param decrement New decrement configuration value * @see getFreefallDetectionCounterDecrement() - * @see MPU6050_RA_MOT_DETECT_CTRL - * @see MPU6050_DETECT_FF_COUNT_BIT + * @see MPU9150_RA_MOT_DETECT_CTRL + * @see MPU9150_DETECT_FF_COUNT_BIT */ -void MPU6050::setFreefallDetectionCounterDecrement(uint8_t decrement) { - I2Cdev::writeBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_FF_COUNT_BIT, MPU6050_DETECT_FF_COUNT_LENGTH, decrement); +void MPU9150::setFreefallDetectionCounterDecrement(uint8_t decrement) { + I2Cdev::writeBits(devAddr, MPU9150_RA_MOT_DETECT_CTRL, MPU9150_DETECT_FF_COUNT_BIT, MPU9150_DETECT_FF_COUNT_LENGTH, decrement); } /** Get Motion detection counter decrement configuration. * Detection is registered by the Motion detection module after accelerometer @@ -2258,18 +2258,18 @@ void MPU6050::setFreefallDetectionCounterDecrement(uint8_t decrement) { * please refer to Registers 29 to 32. * */ -uint8_t MPU6050::getMotionDetectionCounterDecrement() { - I2Cdev::readBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_MOT_COUNT_BIT, MPU6050_DETECT_MOT_COUNT_LENGTH, buffer); +uint8_t MPU9150::getMotionDetectionCounterDecrement() { + I2Cdev::readBits(devAddr, MPU9150_RA_MOT_DETECT_CTRL, MPU9150_DETECT_MOT_COUNT_BIT, MPU9150_DETECT_MOT_COUNT_LENGTH, buffer); return buffer[0]; } /** Set Motion detection counter decrement configuration. * @param decrement New decrement configuration value * @see getMotionDetectionCounterDecrement() - * @see MPU6050_RA_MOT_DETECT_CTRL - * @see MPU6050_DETECT_MOT_COUNT_BIT + * @see MPU9150_RA_MOT_DETECT_CTRL + * @see MPU9150_DETECT_MOT_COUNT_BIT */ -void MPU6050::setMotionDetectionCounterDecrement(uint8_t decrement) { - I2Cdev::writeBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_MOT_COUNT_BIT, MPU6050_DETECT_MOT_COUNT_LENGTH, decrement); +void MPU9150::setMotionDetectionCounterDecrement(uint8_t decrement) { + I2Cdev::writeBits(devAddr, MPU9150_RA_MOT_DETECT_CTRL, MPU9150_DETECT_MOT_COUNT_BIT, MPU9150_DETECT_MOT_COUNT_LENGTH, decrement); } // USER_CTRL register @@ -2279,21 +2279,21 @@ void MPU6050::setMotionDetectionCounterDecrement(uint8_t decrement) { * cannot be written to or read from while disabled. The FIFO buffer's state * does not change unless the MPU-60X0 is power cycled. * @return Current FIFO enabled status - * @see MPU6050_RA_USER_CTRL - * @see MPU6050_USERCTRL_FIFO_EN_BIT + * @see MPU9150_RA_USER_CTRL + * @see MPU9150_USERCTRL_FIFO_EN_BIT */ -bool MPU6050::getFIFOEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_EN_BIT, buffer); +bool MPU9150::getFIFOEnabled() { + I2Cdev::readBit(devAddr, MPU9150_RA_USER_CTRL, MPU9150_USERCTRL_FIFO_EN_BIT, buffer); return buffer[0]; } /** Set FIFO enabled status. * @param enabled New FIFO enabled status * @see getFIFOEnabled() - * @see MPU6050_RA_USER_CTRL - * @see MPU6050_USERCTRL_FIFO_EN_BIT + * @see MPU9150_RA_USER_CTRL + * @see MPU9150_USERCTRL_FIFO_EN_BIT */ -void MPU6050::setFIFOEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_EN_BIT, enabled); +void MPU9150::setFIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9150_RA_USER_CTRL, MPU9150_USERCTRL_FIFO_EN_BIT, enabled); } /** Get I2C Master Mode enabled status. * When this mode is enabled, the MPU-60X0 acts as the I2C Master to the @@ -2303,46 +2303,46 @@ void MPU6050::setFIFOEnabled(bool enabled) { * enabling Bypass Mode. For further information regarding Bypass Mode, please * refer to Register 55. * @return Current I2C Master Mode enabled status - * @see MPU6050_RA_USER_CTRL - * @see MPU6050_USERCTRL_I2C_MST_EN_BIT + * @see MPU9150_RA_USER_CTRL + * @see MPU9150_USERCTRL_I2C_MST_EN_BIT */ -bool MPU6050::getI2CMasterModeEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_EN_BIT, buffer); +bool MPU9150::getI2CMasterModeEnabled() { + I2Cdev::readBit(devAddr, MPU9150_RA_USER_CTRL, MPU9150_USERCTRL_I2C_MST_EN_BIT, buffer); return buffer[0]; } /** Set I2C Master Mode enabled status. * @param enabled New I2C Master Mode enabled status * @see getI2CMasterModeEnabled() - * @see MPU6050_RA_USER_CTRL - * @see MPU6050_USERCTRL_I2C_MST_EN_BIT + * @see MPU9150_RA_USER_CTRL + * @see MPU9150_USERCTRL_I2C_MST_EN_BIT */ -void MPU6050::setI2CMasterModeEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_EN_BIT, enabled); +void MPU9150::setI2CMasterModeEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9150_RA_USER_CTRL, MPU9150_USERCTRL_I2C_MST_EN_BIT, enabled); } /** Switch from I2C to SPI mode (MPU-6000 only) * If this is set, the primary SPI interface will be enabled in place of the * disabled primary I2C interface. */ -void MPU6050::switchSPIEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_IF_DIS_BIT, enabled); +void MPU9150::switchSPIEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9150_RA_USER_CTRL, MPU9150_USERCTRL_I2C_IF_DIS_BIT, enabled); } /** Reset the FIFO. * This bit resets the FIFO buffer when set to 1 while FIFO_EN equals 0. This * bit automatically clears to 0 after the reset has been triggered. - * @see MPU6050_RA_USER_CTRL - * @see MPU6050_USERCTRL_FIFO_RESET_BIT + * @see MPU9150_RA_USER_CTRL + * @see MPU9150_USERCTRL_FIFO_RESET_BIT */ -void MPU6050::resetFIFO() { - I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_RESET_BIT, true); +void MPU9150::resetFIFO() { + I2Cdev::writeBit(devAddr, MPU9150_RA_USER_CTRL, MPU9150_USERCTRL_FIFO_RESET_BIT, true); } /** Reset the I2C Master. * This bit resets the I2C Master when set to 1 while I2C_MST_EN equals 0. * This bit automatically clears to 0 after the reset has been triggered. - * @see MPU6050_RA_USER_CTRL - * @see MPU6050_USERCTRL_I2C_MST_RESET_BIT + * @see MPU9150_RA_USER_CTRL + * @see MPU9150_USERCTRL_I2C_MST_RESET_BIT */ -void MPU6050::resetI2CMaster() { - I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_RESET_BIT, true); +void MPU9150::resetI2CMaster() { + I2Cdev::writeBit(devAddr, MPU9150_RA_USER_CTRL, MPU9150_USERCTRL_I2C_MST_RESET_BIT, true); } /** Reset all sensor registers and signal paths. * When set to 1, this bit resets the signal paths for all sensors (gyroscopes, @@ -2353,22 +2353,22 @@ void MPU6050::resetI2CMaster() { * When resetting only the signal path (and not the sensor registers), please * use Register 104, SIGNAL_PATH_RESET. * - * @see MPU6050_RA_USER_CTRL - * @see MPU6050_USERCTRL_SIG_COND_RESET_BIT + * @see MPU9150_RA_USER_CTRL + * @see MPU9150_USERCTRL_SIG_COND_RESET_BIT */ -void MPU6050::resetSensors() { - I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_SIG_COND_RESET_BIT, true); +void MPU9150::resetSensors() { + I2Cdev::writeBit(devAddr, MPU9150_RA_USER_CTRL, MPU9150_USERCTRL_SIG_COND_RESET_BIT, true); } // PWR_MGMT_1 register /** Trigger a full device reset. * A small delay of ~50ms may be desirable after triggering a reset. - * @see MPU6050_RA_PWR_MGMT_1 - * @see MPU6050_PWR1_DEVICE_RESET_BIT + * @see MPU9150_RA_PWR_MGMT_1 + * @see MPU9150_PWR1_DEVICE_RESET_BIT */ -void MPU6050::reset() { - I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_DEVICE_RESET_BIT, true); +void MPU9150::reset() { + I2Cdev::writeBit(devAddr, MPU9150_RA_PWR_MGMT_1, MPU9150_PWR1_DEVICE_RESET_BIT, true); } /** Get sleep mode status. * Setting the SLEEP bit in the register puts the device into very low power @@ -2378,42 +2378,42 @@ void MPU6050::reset() { * selections for each of the gyros should be used if any gyro axis is not used * by the application. * @return Current sleep mode enabled status - * @see MPU6050_RA_PWR_MGMT_1 - * @see MPU6050_PWR1_SLEEP_BIT + * @see MPU9150_RA_PWR_MGMT_1 + * @see MPU9150_PWR1_SLEEP_BIT */ -bool MPU6050::getSleepEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, buffer); +bool MPU9150::getSleepEnabled() { + I2Cdev::readBit(devAddr, MPU9150_RA_PWR_MGMT_1, MPU9150_PWR1_SLEEP_BIT, buffer); return buffer[0]; } /** Set sleep mode status. * @param enabled New sleep mode enabled status * @see getSleepEnabled() - * @see MPU6050_RA_PWR_MGMT_1 - * @see MPU6050_PWR1_SLEEP_BIT + * @see MPU9150_RA_PWR_MGMT_1 + * @see MPU9150_PWR1_SLEEP_BIT */ -void MPU6050::setSleepEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, enabled); +void MPU9150::setSleepEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9150_RA_PWR_MGMT_1, MPU9150_PWR1_SLEEP_BIT, enabled); } /** Get wake cycle enabled status. * When this bit is set to 1 and SLEEP is disabled, the MPU-60X0 will cycle * between sleep mode and waking up to take a single sample of data from active * sensors at a rate determined by LP_WAKE_CTRL (register 108). * @return Current sleep mode enabled status - * @see MPU6050_RA_PWR_MGMT_1 - * @see MPU6050_PWR1_CYCLE_BIT + * @see MPU9150_RA_PWR_MGMT_1 + * @see MPU9150_PWR1_CYCLE_BIT */ -bool MPU6050::getWakeCycleEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CYCLE_BIT, buffer); +bool MPU9150::getWakeCycleEnabled() { + I2Cdev::readBit(devAddr, MPU9150_RA_PWR_MGMT_1, MPU9150_PWR1_CYCLE_BIT, buffer); return buffer[0]; } /** Set wake cycle enabled status. * @param enabled New sleep mode enabled status * @see getWakeCycleEnabled() - * @see MPU6050_RA_PWR_MGMT_1 - * @see MPU6050_PWR1_CYCLE_BIT + * @see MPU9150_RA_PWR_MGMT_1 + * @see MPU9150_PWR1_CYCLE_BIT */ -void MPU6050::setWakeCycleEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CYCLE_BIT, enabled); +void MPU9150::setWakeCycleEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9150_RA_PWR_MGMT_1, MPU9150_PWR1_CYCLE_BIT, enabled); } /** Get temperature sensor enabled status. * Control the usage of the internal temperature sensor. @@ -2423,11 +2423,11 @@ void MPU6050::setWakeCycleEnabled(bool enabled) { * values to indicate whether the sensor is enabled or disabled, respectively. * * @return Current temperature sensor enabled status - * @see MPU6050_RA_PWR_MGMT_1 - * @see MPU6050_PWR1_TEMP_DIS_BIT + * @see MPU9150_RA_PWR_MGMT_1 + * @see MPU9150_PWR1_TEMP_DIS_BIT */ -bool MPU6050::getTempSensorEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_TEMP_DIS_BIT, buffer); +bool MPU9150::getTempSensorEnabled() { + I2Cdev::readBit(devAddr, MPU9150_RA_PWR_MGMT_1, MPU9150_PWR1_TEMP_DIS_BIT, buffer); return buffer[0] == 0; // 1 is actually disabled here } /** Set temperature sensor enabled status. @@ -2437,21 +2437,21 @@ bool MPU6050::getTempSensorEnabled() { * * @param enabled New temperature sensor enabled status * @see getTempSensorEnabled() - * @see MPU6050_RA_PWR_MGMT_1 - * @see MPU6050_PWR1_TEMP_DIS_BIT + * @see MPU9150_RA_PWR_MGMT_1 + * @see MPU9150_PWR1_TEMP_DIS_BIT */ -void MPU6050::setTempSensorEnabled(bool enabled) { +void MPU9150::setTempSensorEnabled(bool enabled) { // 1 is actually disabled here - I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_TEMP_DIS_BIT, !enabled); + I2Cdev::writeBit(devAddr, MPU9150_RA_PWR_MGMT_1, MPU9150_PWR1_TEMP_DIS_BIT, !enabled); } /** Get clock source setting. * @return Current clock source setting - * @see MPU6050_RA_PWR_MGMT_1 - * @see MPU6050_PWR1_CLKSEL_BIT - * @see MPU6050_PWR1_CLKSEL_LENGTH + * @see MPU9150_RA_PWR_MGMT_1 + * @see MPU9150_PWR1_CLKSEL_BIT + * @see MPU9150_PWR1_CLKSEL_LENGTH */ -uint8_t MPU6050::getClockSource() { - I2Cdev::readBits(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, buffer); +uint8_t MPU9150::getClockSource() { + I2Cdev::readBits(devAddr, MPU9150_RA_PWR_MGMT_1, MPU9150_PWR1_CLKSEL_BIT, MPU9150_PWR1_CLKSEL_LENGTH, buffer); return buffer[0]; } /** Set clock source setting. @@ -2480,12 +2480,12 @@ uint8_t MPU6050::getClockSource() { * * @param source New clock source setting * @see getClockSource() - * @see MPU6050_RA_PWR_MGMT_1 - * @see MPU6050_PWR1_CLKSEL_BIT - * @see MPU6050_PWR1_CLKSEL_LENGTH + * @see MPU9150_RA_PWR_MGMT_1 + * @see MPU9150_PWR1_CLKSEL_BIT + * @see MPU9150_PWR1_CLKSEL_LENGTH */ -void MPU6050::setClockSource(uint8_t source) { - I2Cdev::writeBits(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, source); +void MPU9150::setClockSource(uint8_t source) { + I2Cdev::writeBits(devAddr, MPU9150_RA_PWR_MGMT_1, MPU9150_PWR1_CLKSEL_BIT, MPU9150_PWR1_CLKSEL_LENGTH, source); } // PWR_MGMT_2 register @@ -2511,133 +2511,133 @@ void MPU6050::setClockSource(uint8_t source) { * Register 107. * * @return Current wake frequency - * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU9150_RA_PWR_MGMT_2 */ -uint8_t MPU6050::getWakeFrequency() { - I2Cdev::readBits(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_LP_WAKE_CTRL_BIT, MPU6050_PWR2_LP_WAKE_CTRL_LENGTH, buffer); +uint8_t MPU9150::getWakeFrequency() { + I2Cdev::readBits(devAddr, MPU9150_RA_PWR_MGMT_2, MPU9150_PWR2_LP_WAKE_CTRL_BIT, MPU9150_PWR2_LP_WAKE_CTRL_LENGTH, buffer); return buffer[0]; } /** Set wake frequency in Accel-Only Low Power Mode. * @param frequency New wake frequency - * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU9150_RA_PWR_MGMT_2 */ -void MPU6050::setWakeFrequency(uint8_t frequency) { - I2Cdev::writeBits(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_LP_WAKE_CTRL_BIT, MPU6050_PWR2_LP_WAKE_CTRL_LENGTH, frequency); +void MPU9150::setWakeFrequency(uint8_t frequency) { + I2Cdev::writeBits(devAddr, MPU9150_RA_PWR_MGMT_2, MPU9150_PWR2_LP_WAKE_CTRL_BIT, MPU9150_PWR2_LP_WAKE_CTRL_LENGTH, frequency); } /** Get X-axis accelerometer standby enabled status. * If enabled, the X-axis will not gather or report data (or use power). * @return Current X-axis standby enabled status - * @see MPU6050_RA_PWR_MGMT_2 - * @see MPU6050_PWR2_STBY_XA_BIT + * @see MPU9150_RA_PWR_MGMT_2 + * @see MPU9150_PWR2_STBY_XA_BIT */ -bool MPU6050::getStandbyXAccelEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XA_BIT, buffer); +bool MPU9150::getStandbyXAccelEnabled() { + I2Cdev::readBit(devAddr, MPU9150_RA_PWR_MGMT_2, MPU9150_PWR2_STBY_XA_BIT, buffer); return buffer[0]; } /** Set X-axis accelerometer standby enabled status. * @param New X-axis standby enabled status * @see getStandbyXAccelEnabled() - * @see MPU6050_RA_PWR_MGMT_2 - * @see MPU6050_PWR2_STBY_XA_BIT + * @see MPU9150_RA_PWR_MGMT_2 + * @see MPU9150_PWR2_STBY_XA_BIT */ -void MPU6050::setStandbyXAccelEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XA_BIT, enabled); +void MPU9150::setStandbyXAccelEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9150_RA_PWR_MGMT_2, MPU9150_PWR2_STBY_XA_BIT, enabled); } /** Get Y-axis accelerometer standby enabled status. * If enabled, the Y-axis will not gather or report data (or use power). * @return Current Y-axis standby enabled status - * @see MPU6050_RA_PWR_MGMT_2 - * @see MPU6050_PWR2_STBY_YA_BIT + * @see MPU9150_RA_PWR_MGMT_2 + * @see MPU9150_PWR2_STBY_YA_BIT */ -bool MPU6050::getStandbyYAccelEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YA_BIT, buffer); +bool MPU9150::getStandbyYAccelEnabled() { + I2Cdev::readBit(devAddr, MPU9150_RA_PWR_MGMT_2, MPU9150_PWR2_STBY_YA_BIT, buffer); return buffer[0]; } /** Set Y-axis accelerometer standby enabled status. * @param New Y-axis standby enabled status * @see getStandbyYAccelEnabled() - * @see MPU6050_RA_PWR_MGMT_2 - * @see MPU6050_PWR2_STBY_YA_BIT + * @see MPU9150_RA_PWR_MGMT_2 + * @see MPU9150_PWR2_STBY_YA_BIT */ -void MPU6050::setStandbyYAccelEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YA_BIT, enabled); +void MPU9150::setStandbyYAccelEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9150_RA_PWR_MGMT_2, MPU9150_PWR2_STBY_YA_BIT, enabled); } /** Get Z-axis accelerometer standby enabled status. * If enabled, the Z-axis will not gather or report data (or use power). * @return Current Z-axis standby enabled status - * @see MPU6050_RA_PWR_MGMT_2 - * @see MPU6050_PWR2_STBY_ZA_BIT + * @see MPU9150_RA_PWR_MGMT_2 + * @see MPU9150_PWR2_STBY_ZA_BIT */ -bool MPU6050::getStandbyZAccelEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZA_BIT, buffer); +bool MPU9150::getStandbyZAccelEnabled() { + I2Cdev::readBit(devAddr, MPU9150_RA_PWR_MGMT_2, MPU9150_PWR2_STBY_ZA_BIT, buffer); return buffer[0]; } /** Set Z-axis accelerometer standby enabled status. * @param New Z-axis standby enabled status * @see getStandbyZAccelEnabled() - * @see MPU6050_RA_PWR_MGMT_2 - * @see MPU6050_PWR2_STBY_ZA_BIT + * @see MPU9150_RA_PWR_MGMT_2 + * @see MPU9150_PWR2_STBY_ZA_BIT */ -void MPU6050::setStandbyZAccelEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZA_BIT, enabled); +void MPU9150::setStandbyZAccelEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9150_RA_PWR_MGMT_2, MPU9150_PWR2_STBY_ZA_BIT, enabled); } /** Get X-axis gyroscope standby enabled status. * If enabled, the X-axis will not gather or report data (or use power). * @return Current X-axis standby enabled status - * @see MPU6050_RA_PWR_MGMT_2 - * @see MPU6050_PWR2_STBY_XG_BIT + * @see MPU9150_RA_PWR_MGMT_2 + * @see MPU9150_PWR2_STBY_XG_BIT */ -bool MPU6050::getStandbyXGyroEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XG_BIT, buffer); +bool MPU9150::getStandbyXGyroEnabled() { + I2Cdev::readBit(devAddr, MPU9150_RA_PWR_MGMT_2, MPU9150_PWR2_STBY_XG_BIT, buffer); return buffer[0]; } /** Set X-axis gyroscope standby enabled status. * @param New X-axis standby enabled status * @see getStandbyXGyroEnabled() - * @see MPU6050_RA_PWR_MGMT_2 - * @see MPU6050_PWR2_STBY_XG_BIT + * @see MPU9150_RA_PWR_MGMT_2 + * @see MPU9150_PWR2_STBY_XG_BIT */ -void MPU6050::setStandbyXGyroEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XG_BIT, enabled); +void MPU9150::setStandbyXGyroEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9150_RA_PWR_MGMT_2, MPU9150_PWR2_STBY_XG_BIT, enabled); } /** Get Y-axis gyroscope standby enabled status. * If enabled, the Y-axis will not gather or report data (or use power). * @return Current Y-axis standby enabled status - * @see MPU6050_RA_PWR_MGMT_2 - * @see MPU6050_PWR2_STBY_YG_BIT + * @see MPU9150_RA_PWR_MGMT_2 + * @see MPU9150_PWR2_STBY_YG_BIT */ -bool MPU6050::getStandbyYGyroEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YG_BIT, buffer); +bool MPU9150::getStandbyYGyroEnabled() { + I2Cdev::readBit(devAddr, MPU9150_RA_PWR_MGMT_2, MPU9150_PWR2_STBY_YG_BIT, buffer); return buffer[0]; } /** Set Y-axis gyroscope standby enabled status. * @param New Y-axis standby enabled status * @see getStandbyYGyroEnabled() - * @see MPU6050_RA_PWR_MGMT_2 - * @see MPU6050_PWR2_STBY_YG_BIT + * @see MPU9150_RA_PWR_MGMT_2 + * @see MPU9150_PWR2_STBY_YG_BIT */ -void MPU6050::setStandbyYGyroEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YG_BIT, enabled); +void MPU9150::setStandbyYGyroEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9150_RA_PWR_MGMT_2, MPU9150_PWR2_STBY_YG_BIT, enabled); } /** Get Z-axis gyroscope standby enabled status. * If enabled, the Z-axis will not gather or report data (or use power). * @return Current Z-axis standby enabled status - * @see MPU6050_RA_PWR_MGMT_2 - * @see MPU6050_PWR2_STBY_ZG_BIT + * @see MPU9150_RA_PWR_MGMT_2 + * @see MPU9150_PWR2_STBY_ZG_BIT */ -bool MPU6050::getStandbyZGyroEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZG_BIT, buffer); +bool MPU9150::getStandbyZGyroEnabled() { + I2Cdev::readBit(devAddr, MPU9150_RA_PWR_MGMT_2, MPU9150_PWR2_STBY_ZG_BIT, buffer); return buffer[0]; } /** Set Z-axis gyroscope standby enabled status. * @param New Z-axis standby enabled status * @see getStandbyZGyroEnabled() - * @see MPU6050_RA_PWR_MGMT_2 - * @see MPU6050_PWR2_STBY_ZG_BIT + * @see MPU9150_RA_PWR_MGMT_2 + * @see MPU9150_PWR2_STBY_ZG_BIT */ -void MPU6050::setStandbyZGyroEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZG_BIT, enabled); +void MPU9150::setStandbyZGyroEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9150_RA_PWR_MGMT_2, MPU9150_PWR2_STBY_ZG_BIT, enabled); } // FIFO_COUNT* registers @@ -2649,8 +2649,8 @@ void MPU6050::setStandbyZGyroEnabled(bool enabled) { * set of sensor data bound to be stored in the FIFO (register 35 and 36). * @return Current FIFO buffer size */ -uint16_t MPU6050::getFIFOCount() { - I2Cdev::readBytes(devAddr, MPU6050_RA_FIFO_COUNTH, 2, buffer); +uint16_t MPU9150::getFIFOCount() { + I2Cdev::readBytes(devAddr, MPU9150_RA_FIFO_COUNTH, 2, buffer); return (((uint16_t)buffer[0]) << 8) | buffer[1]; } @@ -2681,19 +2681,19 @@ uint16_t MPU6050::getFIFOCount() { * * @return Byte from FIFO buffer */ -uint8_t MPU6050::getFIFOByte() { - I2Cdev::readByte(devAddr, MPU6050_RA_FIFO_R_W, buffer); +uint8_t MPU9150::getFIFOByte() { + I2Cdev::readByte(devAddr, MPU9150_RA_FIFO_R_W, buffer); return buffer[0]; } -void MPU6050::getFIFOBytes(uint8_t *data, uint8_t length) { - I2Cdev::readBytes(devAddr, MPU6050_RA_FIFO_R_W, length, data); +void MPU9150::getFIFOBytes(uint8_t *data, uint8_t length) { + I2Cdev::readBytes(devAddr, MPU9150_RA_FIFO_R_W, length, data); } /** Write byte to FIFO buffer. * @see getFIFOByte() - * @see MPU6050_RA_FIFO_R_W + * @see MPU9150_RA_FIFO_R_W */ -void MPU6050::setFIFOByte(uint8_t data) { - I2Cdev::writeByte(devAddr, MPU6050_RA_FIFO_R_W, data); +void MPU9150::setFIFOByte(uint8_t data) { + I2Cdev::writeByte(devAddr, MPU9150_RA_FIFO_R_W, data); } // WHO_AM_I register @@ -2701,12 +2701,12 @@ void MPU6050::setFIFOByte(uint8_t data) { /** Get Device ID. * This register is used to verify the identity of the device (0b110100, 0x34). * @return Device ID (6 bits only! should be 0x34) - * @see MPU6050_RA_WHO_AM_I - * @see MPU6050_WHO_AM_I_BIT - * @see MPU6050_WHO_AM_I_LENGTH + * @see MPU9150_RA_WHO_AM_I + * @see MPU9150_WHO_AM_I_BIT + * @see MPU9150_WHO_AM_I_LENGTH */ -uint8_t MPU6050::getDeviceID() { - I2Cdev::readBits(devAddr, MPU6050_RA_WHO_AM_I, MPU6050_WHO_AM_I_BIT, MPU6050_WHO_AM_I_LENGTH, buffer); +uint8_t MPU9150::getDeviceID() { + I2Cdev::readBits(devAddr, MPU9150_RA_WHO_AM_I, MPU9150_WHO_AM_I_BIT, MPU9150_WHO_AM_I_LENGTH, buffer); return buffer[0]; } /** Set Device ID. @@ -2714,242 +2714,242 @@ uint8_t MPU6050::getDeviceID() { * necessary though). * @param id New device ID to set. * @see getDeviceID() - * @see MPU6050_RA_WHO_AM_I - * @see MPU6050_WHO_AM_I_BIT - * @see MPU6050_WHO_AM_I_LENGTH + * @see MPU9150_RA_WHO_AM_I + * @see MPU9150_WHO_AM_I_BIT + * @see MPU9150_WHO_AM_I_LENGTH */ -void MPU6050::setDeviceID(uint8_t id) { - I2Cdev::writeBits(devAddr, MPU6050_RA_WHO_AM_I, MPU6050_WHO_AM_I_BIT, MPU6050_WHO_AM_I_LENGTH, id); +void MPU9150::setDeviceID(uint8_t id) { + I2Cdev::writeBits(devAddr, MPU9150_RA_WHO_AM_I, MPU9150_WHO_AM_I_BIT, MPU9150_WHO_AM_I_LENGTH, id); } // ======== UNDOCUMENTED/DMP REGISTERS/METHODS ======== // XG_OFFS_TC register -uint8_t MPU6050::getOTPBankValid() { - I2Cdev::readBit(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OTP_BNK_VLD_BIT, buffer); +uint8_t MPU9150::getOTPBankValid() { + I2Cdev::readBit(devAddr, MPU9150_RA_XG_OFFS_TC, MPU9150_TC_OTP_BNK_VLD_BIT, buffer); return buffer[0]; } -void MPU6050::setOTPBankValid(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OTP_BNK_VLD_BIT, enabled); +void MPU9150::setOTPBankValid(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9150_RA_XG_OFFS_TC, MPU9150_TC_OTP_BNK_VLD_BIT, enabled); } -int8_t MPU6050::getXGyroOffsetTC() { - I2Cdev::readBits(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, buffer); +int8_t MPU9150::getXGyroOffsetTC() { + I2Cdev::readBits(devAddr, MPU9150_RA_XG_OFFS_TC, MPU9150_TC_OFFSET_BIT, MPU9150_TC_OFFSET_LENGTH, buffer); return buffer[0]; } -void MPU6050::setXGyroOffsetTC(int8_t offset) { - I2Cdev::writeBits(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset); +void MPU9150::setXGyroOffsetTC(int8_t offset) { + I2Cdev::writeBits(devAddr, MPU9150_RA_XG_OFFS_TC, MPU9150_TC_OFFSET_BIT, MPU9150_TC_OFFSET_LENGTH, offset); } // YG_OFFS_TC register -int8_t MPU6050::getYGyroOffsetTC() { - I2Cdev::readBits(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, buffer); +int8_t MPU9150::getYGyroOffsetTC() { + I2Cdev::readBits(devAddr, MPU9150_RA_YG_OFFS_TC, MPU9150_TC_OFFSET_BIT, MPU9150_TC_OFFSET_LENGTH, buffer); return buffer[0]; } -void MPU6050::setYGyroOffsetTC(int8_t offset) { - I2Cdev::writeBits(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset); +void MPU9150::setYGyroOffsetTC(int8_t offset) { + I2Cdev::writeBits(devAddr, MPU9150_RA_YG_OFFS_TC, MPU9150_TC_OFFSET_BIT, MPU9150_TC_OFFSET_LENGTH, offset); } // ZG_OFFS_TC register -int8_t MPU6050::getZGyroOffsetTC() { - I2Cdev::readBits(devAddr, MPU6050_RA_ZG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, buffer); +int8_t MPU9150::getZGyroOffsetTC() { + I2Cdev::readBits(devAddr, MPU9150_RA_ZG_OFFS_TC, MPU9150_TC_OFFSET_BIT, MPU9150_TC_OFFSET_LENGTH, buffer); return buffer[0]; } -void MPU6050::setZGyroOffsetTC(int8_t offset) { - I2Cdev::writeBits(devAddr, MPU6050_RA_ZG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset); +void MPU9150::setZGyroOffsetTC(int8_t offset) { + I2Cdev::writeBits(devAddr, MPU9150_RA_ZG_OFFS_TC, MPU9150_TC_OFFSET_BIT, MPU9150_TC_OFFSET_LENGTH, offset); } // X_FINE_GAIN register -int8_t MPU6050::getXFineGain() { - I2Cdev::readByte(devAddr, MPU6050_RA_X_FINE_GAIN, buffer); +int8_t MPU9150::getXFineGain() { + I2Cdev::readByte(devAddr, MPU9150_RA_X_FINE_GAIN, buffer); return buffer[0]; } -void MPU6050::setXFineGain(int8_t gain) { - I2Cdev::writeByte(devAddr, MPU6050_RA_X_FINE_GAIN, gain); +void MPU9150::setXFineGain(int8_t gain) { + I2Cdev::writeByte(devAddr, MPU9150_RA_X_FINE_GAIN, gain); } // Y_FINE_GAIN register -int8_t MPU6050::getYFineGain() { - I2Cdev::readByte(devAddr, MPU6050_RA_Y_FINE_GAIN, buffer); +int8_t MPU9150::getYFineGain() { + I2Cdev::readByte(devAddr, MPU9150_RA_Y_FINE_GAIN, buffer); return buffer[0]; } -void MPU6050::setYFineGain(int8_t gain) { - I2Cdev::writeByte(devAddr, MPU6050_RA_Y_FINE_GAIN, gain); +void MPU9150::setYFineGain(int8_t gain) { + I2Cdev::writeByte(devAddr, MPU9150_RA_Y_FINE_GAIN, gain); } // Z_FINE_GAIN register -int8_t MPU6050::getZFineGain() { - I2Cdev::readByte(devAddr, MPU6050_RA_Z_FINE_GAIN, buffer); +int8_t MPU9150::getZFineGain() { + I2Cdev::readByte(devAddr, MPU9150_RA_Z_FINE_GAIN, buffer); return buffer[0]; } -void MPU6050::setZFineGain(int8_t gain) { - I2Cdev::writeByte(devAddr, MPU6050_RA_Z_FINE_GAIN, gain); +void MPU9150::setZFineGain(int8_t gain) { + I2Cdev::writeByte(devAddr, MPU9150_RA_Z_FINE_GAIN, gain); } // XA_OFFS_* registers -int16_t MPU6050::getXAccelOffset() { - I2Cdev::readBytes(devAddr, MPU6050_RA_XA_OFFS_H, 2, buffer); +int16_t MPU9150::getXAccelOffset() { + I2Cdev::readBytes(devAddr, MPU9150_RA_XA_OFFS_H, 2, buffer); return (((int16_t)buffer[0]) << 8) | buffer[1]; } -void MPU6050::setXAccelOffset(int16_t offset) { - I2Cdev::writeWord(devAddr, MPU6050_RA_XA_OFFS_H, offset); +void MPU9150::setXAccelOffset(int16_t offset) { + I2Cdev::writeWord(devAddr, MPU9150_RA_XA_OFFS_H, offset); } // YA_OFFS_* register -int16_t MPU6050::getYAccelOffset() { - I2Cdev::readBytes(devAddr, MPU6050_RA_YA_OFFS_H, 2, buffer); +int16_t MPU9150::getYAccelOffset() { + I2Cdev::readBytes(devAddr, MPU9150_RA_YA_OFFS_H, 2, buffer); return (((int16_t)buffer[0]) << 8) | buffer[1]; } -void MPU6050::setYAccelOffset(int16_t offset) { - I2Cdev::writeWord(devAddr, MPU6050_RA_YA_OFFS_H, offset); +void MPU9150::setYAccelOffset(int16_t offset) { + I2Cdev::writeWord(devAddr, MPU9150_RA_YA_OFFS_H, offset); } // ZA_OFFS_* register -int16_t MPU6050::getZAccelOffset() { - I2Cdev::readBytes(devAddr, MPU6050_RA_ZA_OFFS_H, 2, buffer); +int16_t MPU9150::getZAccelOffset() { + I2Cdev::readBytes(devAddr, MPU9150_RA_ZA_OFFS_H, 2, buffer); return (((int16_t)buffer[0]) << 8) | buffer[1]; } -void MPU6050::setZAccelOffset(int16_t offset) { - I2Cdev::writeWord(devAddr, MPU6050_RA_ZA_OFFS_H, offset); +void MPU9150::setZAccelOffset(int16_t offset) { + I2Cdev::writeWord(devAddr, MPU9150_RA_ZA_OFFS_H, offset); } // XG_OFFS_USR* registers -int16_t MPU6050::getXGyroOffset() { - I2Cdev::readBytes(devAddr, MPU6050_RA_XG_OFFS_USRH, 2, buffer); +int16_t MPU9150::getXGyroOffset() { + I2Cdev::readBytes(devAddr, MPU9150_RA_XG_OFFS_USRH, 2, buffer); return (((int16_t)buffer[0]) << 8) | buffer[1]; } -void MPU6050::setXGyroOffset(int16_t offset) { - I2Cdev::writeWord(devAddr, MPU6050_RA_XG_OFFS_USRH, offset); +void MPU9150::setXGyroOffset(int16_t offset) { + I2Cdev::writeWord(devAddr, MPU9150_RA_XG_OFFS_USRH, offset); } // YG_OFFS_USR* register -int16_t MPU6050::getYGyroOffset() { - I2Cdev::readBytes(devAddr, MPU6050_RA_YG_OFFS_USRH, 2, buffer); +int16_t MPU9150::getYGyroOffset() { + I2Cdev::readBytes(devAddr, MPU9150_RA_YG_OFFS_USRH, 2, buffer); return (((int16_t)buffer[0]) << 8) | buffer[1]; } -void MPU6050::setYGyroOffset(int16_t offset) { - I2Cdev::writeWord(devAddr, MPU6050_RA_YG_OFFS_USRH, offset); +void MPU9150::setYGyroOffset(int16_t offset) { + I2Cdev::writeWord(devAddr, MPU9150_RA_YG_OFFS_USRH, offset); } // ZG_OFFS_USR* register -int16_t MPU6050::getZGyroOffset() { - I2Cdev::readBytes(devAddr, MPU6050_RA_ZG_OFFS_USRH, 2, buffer); +int16_t MPU9150::getZGyroOffset() { + I2Cdev::readBytes(devAddr, MPU9150_RA_ZG_OFFS_USRH, 2, buffer); return (((int16_t)buffer[0]) << 8) | buffer[1]; } -void MPU6050::setZGyroOffset(int16_t offset) { - I2Cdev::writeWord(devAddr, MPU6050_RA_ZG_OFFS_USRH, offset); +void MPU9150::setZGyroOffset(int16_t offset) { + I2Cdev::writeWord(devAddr, MPU9150_RA_ZG_OFFS_USRH, offset); } // INT_ENABLE register (DMP functions) -bool MPU6050::getIntPLLReadyEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, buffer); +bool MPU9150::getIntPLLReadyEnabled() { + I2Cdev::readBit(devAddr, MPU9150_RA_INT_ENABLE, MPU9150_INTERRUPT_PLL_RDY_INT_BIT, buffer); return buffer[0]; } -void MPU6050::setIntPLLReadyEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, enabled); +void MPU9150::setIntPLLReadyEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9150_RA_INT_ENABLE, MPU9150_INTERRUPT_PLL_RDY_INT_BIT, enabled); } -bool MPU6050::getIntDMPEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DMP_INT_BIT, buffer); +bool MPU9150::getIntDMPEnabled() { + I2Cdev::readBit(devAddr, MPU9150_RA_INT_ENABLE, MPU9150_INTERRUPT_DMP_INT_BIT, buffer); return buffer[0]; } -void MPU6050::setIntDMPEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DMP_INT_BIT, enabled); +void MPU9150::setIntDMPEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9150_RA_INT_ENABLE, MPU9150_INTERRUPT_DMP_INT_BIT, enabled); } // DMP_INT_STATUS -bool MPU6050::getDMPInt5Status() { - I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_5_BIT, buffer); +bool MPU9150::getDMPInt5Status() { + I2Cdev::readBit(devAddr, MPU9150_RA_DMP_INT_STATUS, MPU9150_DMPINT_5_BIT, buffer); return buffer[0]; } -bool MPU6050::getDMPInt4Status() { - I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_4_BIT, buffer); +bool MPU9150::getDMPInt4Status() { + I2Cdev::readBit(devAddr, MPU9150_RA_DMP_INT_STATUS, MPU9150_DMPINT_4_BIT, buffer); return buffer[0]; } -bool MPU6050::getDMPInt3Status() { - I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_3_BIT, buffer); +bool MPU9150::getDMPInt3Status() { + I2Cdev::readBit(devAddr, MPU9150_RA_DMP_INT_STATUS, MPU9150_DMPINT_3_BIT, buffer); return buffer[0]; } -bool MPU6050::getDMPInt2Status() { - I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_2_BIT, buffer); +bool MPU9150::getDMPInt2Status() { + I2Cdev::readBit(devAddr, MPU9150_RA_DMP_INT_STATUS, MPU9150_DMPINT_2_BIT, buffer); return buffer[0]; } -bool MPU6050::getDMPInt1Status() { - I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_1_BIT, buffer); +bool MPU9150::getDMPInt1Status() { + I2Cdev::readBit(devAddr, MPU9150_RA_DMP_INT_STATUS, MPU9150_DMPINT_1_BIT, buffer); return buffer[0]; } -bool MPU6050::getDMPInt0Status() { - I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_0_BIT, buffer); +bool MPU9150::getDMPInt0Status() { + I2Cdev::readBit(devAddr, MPU9150_RA_DMP_INT_STATUS, MPU9150_DMPINT_0_BIT, buffer); return buffer[0]; } // INT_STATUS register (DMP functions) -bool MPU6050::getIntPLLReadyStatus() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, buffer); +bool MPU9150::getIntPLLReadyStatus() { + I2Cdev::readBit(devAddr, MPU9150_RA_INT_STATUS, MPU9150_INTERRUPT_PLL_RDY_INT_BIT, buffer); return buffer[0]; } -bool MPU6050::getIntDMPStatus() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_DMP_INT_BIT, buffer); +bool MPU9150::getIntDMPStatus() { + I2Cdev::readBit(devAddr, MPU9150_RA_INT_STATUS, MPU9150_INTERRUPT_DMP_INT_BIT, buffer); return buffer[0]; } // USER_CTRL register (DMP functions) -bool MPU6050::getDMPEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_EN_BIT, buffer); +bool MPU9150::getDMPEnabled() { + I2Cdev::readBit(devAddr, MPU9150_RA_USER_CTRL, MPU9150_USERCTRL_DMP_EN_BIT, buffer); return buffer[0]; } -void MPU6050::setDMPEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_EN_BIT, enabled); +void MPU9150::setDMPEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9150_RA_USER_CTRL, MPU9150_USERCTRL_DMP_EN_BIT, enabled); } -void MPU6050::resetDMP() { - I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_RESET_BIT, true); +void MPU9150::resetDMP() { + I2Cdev::writeBit(devAddr, MPU9150_RA_USER_CTRL, MPU9150_USERCTRL_DMP_RESET_BIT, true); } // BANK_SEL register -void MPU6050::setMemoryBank(uint8_t bank, bool prefetchEnabled, bool userBank) { +void MPU9150::setMemoryBank(uint8_t bank, bool prefetchEnabled, bool userBank) { bank &= 0x1F; if (userBank) bank |= 0x20; if (prefetchEnabled) bank |= 0x40; - I2Cdev::writeByte(devAddr, MPU6050_RA_BANK_SEL, bank); + I2Cdev::writeByte(devAddr, MPU9150_RA_BANK_SEL, bank); } // MEM_START_ADDR register -void MPU6050::setMemoryStartAddress(uint8_t address) { - I2Cdev::writeByte(devAddr, MPU6050_RA_MEM_START_ADDR, address); +void MPU9150::setMemoryStartAddress(uint8_t address) { + I2Cdev::writeByte(devAddr, MPU9150_RA_MEM_START_ADDR, address); } // MEM_R_W register -uint8_t MPU6050::readMemoryByte() { - I2Cdev::readByte(devAddr, MPU6050_RA_MEM_R_W, buffer); +uint8_t MPU9150::readMemoryByte() { + I2Cdev::readByte(devAddr, MPU9150_RA_MEM_R_W, buffer); return buffer[0]; } -void MPU6050::writeMemoryByte(uint8_t data) { - I2Cdev::writeByte(devAddr, MPU6050_RA_MEM_R_W, data); +void MPU9150::writeMemoryByte(uint8_t data) { + I2Cdev::writeByte(devAddr, MPU9150_RA_MEM_R_W, data); } -void MPU6050::readMemoryBlock(uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address) { +void MPU9150::readMemoryBlock(uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address) { setMemoryBank(bank); setMemoryStartAddress(address); uint8_t chunkSize; for (uint16_t i = 0; i < dataSize;) { // determine correct chunk size according to bank position and data size - chunkSize = MPU6050_DMP_MEMORY_CHUNK_SIZE; + chunkSize = MPU9150_DMP_MEMORY_CHUNK_SIZE; // make sure we don't go past the data size if (i + chunkSize > dataSize) chunkSize = dataSize - i; @@ -2958,7 +2958,7 @@ void MPU6050::readMemoryBlock(uint8_t *data, uint16_t dataSize, uint8_t bank, ui if (chunkSize > 256 - address) chunkSize = 256 - address; // read the chunk of data as specified - I2Cdev::readBytes(devAddr, MPU6050_RA_MEM_R_W, chunkSize, data + i); + I2Cdev::readBytes(devAddr, MPU9150_RA_MEM_R_W, chunkSize, data + i); // increase byte index by [chunkSize] i += chunkSize; @@ -2974,7 +2974,7 @@ void MPU6050::readMemoryBlock(uint8_t *data, uint16_t dataSize, uint8_t bank, ui } } } -bool MPU6050::writeMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address, bool verify, bool useProgMem) { +bool MPU9150::writeMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address, bool verify, bool useProgMem) { setMemoryBank(bank); setMemoryStartAddress(address); uint8_t chunkSize; @@ -2982,11 +2982,11 @@ bool MPU6050::writeMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t b uint8_t *progBuffer; uint16_t i; uint8_t j; - if (verify) verifyBuffer = (uint8_t *)malloc(MPU6050_DMP_MEMORY_CHUNK_SIZE); - if (useProgMem) progBuffer = (uint8_t *)malloc(MPU6050_DMP_MEMORY_CHUNK_SIZE); + if (verify) verifyBuffer = (uint8_t *)malloc(MPU9150_DMP_MEMORY_CHUNK_SIZE); + if (useProgMem) progBuffer = (uint8_t *)malloc(MPU9150_DMP_MEMORY_CHUNK_SIZE); for (i = 0; i < dataSize;) { // determine correct chunk size according to bank position and data size - chunkSize = MPU6050_DMP_MEMORY_CHUNK_SIZE; + chunkSize = MPU9150_DMP_MEMORY_CHUNK_SIZE; // make sure we don't go past the data size if (i + chunkSize > dataSize) chunkSize = dataSize - i; @@ -3002,13 +3002,13 @@ bool MPU6050::writeMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t b progBuffer = (uint8_t *)data + i; } - I2Cdev::writeBytes(devAddr, MPU6050_RA_MEM_R_W, chunkSize, progBuffer); + I2Cdev::writeBytes(devAddr, MPU9150_RA_MEM_R_W, chunkSize, progBuffer); // verify data if needed if (verify && verifyBuffer) { setMemoryBank(bank); setMemoryStartAddress(address); - I2Cdev::readBytes(devAddr, MPU6050_RA_MEM_R_W, chunkSize, verifyBuffer); + I2Cdev::readBytes(devAddr, MPU9150_RA_MEM_R_W, chunkSize, verifyBuffer); if (memcmp(progBuffer, verifyBuffer, chunkSize) != 0) { /*Serial.print("Block write verification error, bank "); Serial.print(bank, DEC); @@ -3050,10 +3050,10 @@ bool MPU6050::writeMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t b if (useProgMem) free(progBuffer); return true; } -bool MPU6050::writeProgMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address, bool verify) { +bool MPU9150::writeProgMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address, bool verify) { return writeMemoryBlock(data, dataSize, bank, address, verify, true); } -bool MPU6050::writeDMPConfigurationSet(const uint8_t *data, uint16_t dataSize, bool useProgMem) { +bool MPU9150::writeDMPConfigurationSet(const uint8_t *data, uint16_t dataSize, bool useProgMem) { uint8_t *progBuffer, success, special; uint16_t i, j; if (useProgMem) { @@ -3111,7 +3111,7 @@ bool MPU6050::writeDMPConfigurationSet(const uint8_t *data, uint16_t dataSize, b //setIntZeroMotionEnabled(true); //setIntFIFOBufferOverflowEnabled(true); //setIntDMPEnabled(true); - I2Cdev::writeByte(devAddr, MPU6050_RA_INT_ENABLE, 0x32); // single operation + I2Cdev::writeByte(devAddr, MPU9150_RA_INT_ENABLE, 0x32); // single operation success = true; } else { @@ -3128,26 +3128,26 @@ bool MPU6050::writeDMPConfigurationSet(const uint8_t *data, uint16_t dataSize, b if (useProgMem) free(progBuffer); return true; } -bool MPU6050::writeProgDMPConfigurationSet(const uint8_t *data, uint16_t dataSize) { +bool MPU9150::writeProgDMPConfigurationSet(const uint8_t *data, uint16_t dataSize) { return writeDMPConfigurationSet(data, dataSize, true); } // DMP_CFG_1 register -uint8_t MPU6050::getDMPConfig1() { - I2Cdev::readByte(devAddr, MPU6050_RA_DMP_CFG_1, buffer); +uint8_t MPU9150::getDMPConfig1() { + I2Cdev::readByte(devAddr, MPU9150_RA_DMP_CFG_1, buffer); return buffer[0]; } -void MPU6050::setDMPConfig1(uint8_t config) { - I2Cdev::writeByte(devAddr, MPU6050_RA_DMP_CFG_1, config); +void MPU9150::setDMPConfig1(uint8_t config) { + I2Cdev::writeByte(devAddr, MPU9150_RA_DMP_CFG_1, config); } // DMP_CFG_2 register -uint8_t MPU6050::getDMPConfig2() { - I2Cdev::readByte(devAddr, MPU6050_RA_DMP_CFG_2, buffer); +uint8_t MPU9150::getDMPConfig2() { + I2Cdev::readByte(devAddr, MPU9150_RA_DMP_CFG_2, buffer); return buffer[0]; } -void MPU6050::setDMPConfig2(uint8_t config) { - I2Cdev::writeByte(devAddr, MPU6050_RA_DMP_CFG_2, config); +void MPU9150::setDMPConfig2(uint8_t config) { + I2Cdev::writeByte(devAddr, MPU9150_RA_DMP_CFG_2, config); } \ No newline at end of file diff --git a/Arduino/MPU9150/MPU9150.h b/Arduino/MPU9150/MPU9150.h index 118da611..e4697db3 100644 --- a/Arduino/MPU9150/MPU9150.h +++ b/Arduino/MPU9150/MPU9150.h @@ -1,5 +1,5 @@ -// I2Cdev library collection - MPU6050 I2C device class -// Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00) +// I2Cdev library collection - MPU9150 I2C device class +// Based on InvenSense MPU-9150 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00) // 10/3/2011 by Jeff Rowberg // Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib // @@ -34,8 +34,8 @@ THE SOFTWARE. =============================================== */ -#ifndef _MPU6050_H_ -#define _MPU6050_H_ +#ifndef _MPU9150_H_ +#define _MPU9150_H_ #include "I2Cdev.h" @@ -60,366 +60,366 @@ THE SOFTWARE. #define MPU9150_RA_MAG_ZOUT_L 0x07 #define MPU9150_RA_MAG_ZOUT_H 0x08 -#define MPU6050_ADDRESS_AD0_LOW 0x68 // address pin low (GND), default for InvenSense evaluation board -#define MPU6050_ADDRESS_AD0_HIGH 0x69 // address pin high (VCC) -#define MPU6050_DEFAULT_ADDRESS MPU6050_ADDRESS_AD0_LOW - -#define MPU6050_RA_XG_OFFS_TC 0x00 //[7] PWR_MODE, [6:1] XG_OFFS_TC, [0] OTP_BNK_VLD -#define MPU6050_RA_YG_OFFS_TC 0x01 //[7] PWR_MODE, [6:1] YG_OFFS_TC, [0] OTP_BNK_VLD -#define MPU6050_RA_ZG_OFFS_TC 0x02 //[7] PWR_MODE, [6:1] ZG_OFFS_TC, [0] OTP_BNK_VLD -#define MPU6050_RA_X_FINE_GAIN 0x03 //[7:0] X_FINE_GAIN -#define MPU6050_RA_Y_FINE_GAIN 0x04 //[7:0] Y_FINE_GAIN -#define MPU6050_RA_Z_FINE_GAIN 0x05 //[7:0] Z_FINE_GAIN -#define MPU6050_RA_XA_OFFS_H 0x06 //[15:0] XA_OFFS -#define MPU6050_RA_XA_OFFS_L_TC 0x07 -#define MPU6050_RA_YA_OFFS_H 0x08 //[15:0] YA_OFFS -#define MPU6050_RA_YA_OFFS_L_TC 0x09 -#define MPU6050_RA_ZA_OFFS_H 0x0A //[15:0] ZA_OFFS -#define MPU6050_RA_ZA_OFFS_L_TC 0x0B -#define MPU6050_RA_XG_OFFS_USRH 0x13 //[15:0] XG_OFFS_USR -#define MPU6050_RA_XG_OFFS_USRL 0x14 -#define MPU6050_RA_YG_OFFS_USRH 0x15 //[15:0] YG_OFFS_USR -#define MPU6050_RA_YG_OFFS_USRL 0x16 -#define MPU6050_RA_ZG_OFFS_USRH 0x17 //[15:0] ZG_OFFS_USR -#define MPU6050_RA_ZG_OFFS_USRL 0x18 -#define MPU6050_RA_SMPLRT_DIV 0x19 -#define MPU6050_RA_CONFIG 0x1A -#define MPU6050_RA_GYRO_CONFIG 0x1B -#define MPU6050_RA_ACCEL_CONFIG 0x1C -#define MPU6050_RA_FF_THR 0x1D -#define MPU6050_RA_FF_DUR 0x1E -#define MPU6050_RA_MOT_THR 0x1F -#define MPU6050_RA_MOT_DUR 0x20 -#define MPU6050_RA_ZRMOT_THR 0x21 -#define MPU6050_RA_ZRMOT_DUR 0x22 -#define MPU6050_RA_FIFO_EN 0x23 -#define MPU6050_RA_I2C_MST_CTRL 0x24 -#define MPU6050_RA_I2C_SLV0_ADDR 0x25 -#define MPU6050_RA_I2C_SLV0_REG 0x26 -#define MPU6050_RA_I2C_SLV0_CTRL 0x27 -#define MPU6050_RA_I2C_SLV1_ADDR 0x28 -#define MPU6050_RA_I2C_SLV1_REG 0x29 -#define MPU6050_RA_I2C_SLV1_CTRL 0x2A -#define MPU6050_RA_I2C_SLV2_ADDR 0x2B -#define MPU6050_RA_I2C_SLV2_REG 0x2C -#define MPU6050_RA_I2C_SLV2_CTRL 0x2D -#define MPU6050_RA_I2C_SLV3_ADDR 0x2E -#define MPU6050_RA_I2C_SLV3_REG 0x2F -#define MPU6050_RA_I2C_SLV3_CTRL 0x30 -#define MPU6050_RA_I2C_SLV4_ADDR 0x31 -#define MPU6050_RA_I2C_SLV4_REG 0x32 -#define MPU6050_RA_I2C_SLV4_DO 0x33 -#define MPU6050_RA_I2C_SLV4_CTRL 0x34 -#define MPU6050_RA_I2C_SLV4_DI 0x35 -#define MPU6050_RA_I2C_MST_STATUS 0x36 -#define MPU6050_RA_INT_PIN_CFG 0x37 -#define MPU6050_RA_INT_ENABLE 0x38 -#define MPU6050_RA_DMP_INT_STATUS 0x39 -#define MPU6050_RA_INT_STATUS 0x3A -#define MPU6050_RA_ACCEL_XOUT_H 0x3B -#define MPU6050_RA_ACCEL_XOUT_L 0x3C -#define MPU6050_RA_ACCEL_YOUT_H 0x3D -#define MPU6050_RA_ACCEL_YOUT_L 0x3E -#define MPU6050_RA_ACCEL_ZOUT_H 0x3F -#define MPU6050_RA_ACCEL_ZOUT_L 0x40 -#define MPU6050_RA_TEMP_OUT_H 0x41 -#define MPU6050_RA_TEMP_OUT_L 0x42 -#define MPU6050_RA_GYRO_XOUT_H 0x43 -#define MPU6050_RA_GYRO_XOUT_L 0x44 -#define MPU6050_RA_GYRO_YOUT_H 0x45 -#define MPU6050_RA_GYRO_YOUT_L 0x46 -#define MPU6050_RA_GYRO_ZOUT_H 0x47 -#define MPU6050_RA_GYRO_ZOUT_L 0x48 -#define MPU6050_RA_EXT_SENS_DATA_00 0x49 -#define MPU6050_RA_EXT_SENS_DATA_01 0x4A -#define MPU6050_RA_EXT_SENS_DATA_02 0x4B -#define MPU6050_RA_EXT_SENS_DATA_03 0x4C -#define MPU6050_RA_EXT_SENS_DATA_04 0x4D -#define MPU6050_RA_EXT_SENS_DATA_05 0x4E -#define MPU6050_RA_EXT_SENS_DATA_06 0x4F -#define MPU6050_RA_EXT_SENS_DATA_07 0x50 -#define MPU6050_RA_EXT_SENS_DATA_08 0x51 -#define MPU6050_RA_EXT_SENS_DATA_09 0x52 -#define MPU6050_RA_EXT_SENS_DATA_10 0x53 -#define MPU6050_RA_EXT_SENS_DATA_11 0x54 -#define MPU6050_RA_EXT_SENS_DATA_12 0x55 -#define MPU6050_RA_EXT_SENS_DATA_13 0x56 -#define MPU6050_RA_EXT_SENS_DATA_14 0x57 -#define MPU6050_RA_EXT_SENS_DATA_15 0x58 -#define MPU6050_RA_EXT_SENS_DATA_16 0x59 -#define MPU6050_RA_EXT_SENS_DATA_17 0x5A -#define MPU6050_RA_EXT_SENS_DATA_18 0x5B -#define MPU6050_RA_EXT_SENS_DATA_19 0x5C -#define MPU6050_RA_EXT_SENS_DATA_20 0x5D -#define MPU6050_RA_EXT_SENS_DATA_21 0x5E -#define MPU6050_RA_EXT_SENS_DATA_22 0x5F -#define MPU6050_RA_EXT_SENS_DATA_23 0x60 -#define MPU6050_RA_MOT_DETECT_STATUS 0x61 -#define MPU6050_RA_I2C_SLV0_DO 0x63 -#define MPU6050_RA_I2C_SLV1_DO 0x64 -#define MPU6050_RA_I2C_SLV2_DO 0x65 -#define MPU6050_RA_I2C_SLV3_DO 0x66 -#define MPU6050_RA_I2C_MST_DELAY_CTRL 0x67 -#define MPU6050_RA_SIGNAL_PATH_RESET 0x68 -#define MPU6050_RA_MOT_DETECT_CTRL 0x69 -#define MPU6050_RA_USER_CTRL 0x6A -#define MPU6050_RA_PWR_MGMT_1 0x6B -#define MPU6050_RA_PWR_MGMT_2 0x6C -#define MPU6050_RA_BANK_SEL 0x6D -#define MPU6050_RA_MEM_START_ADDR 0x6E -#define MPU6050_RA_MEM_R_W 0x6F -#define MPU6050_RA_DMP_CFG_1 0x70 -#define MPU6050_RA_DMP_CFG_2 0x71 -#define MPU6050_RA_FIFO_COUNTH 0x72 -#define MPU6050_RA_FIFO_COUNTL 0x73 -#define MPU6050_RA_FIFO_R_W 0x74 -#define MPU6050_RA_WHO_AM_I 0x75 - -#define MPU6050_TC_PWR_MODE_BIT 7 -#define MPU6050_TC_OFFSET_BIT 6 -#define MPU6050_TC_OFFSET_LENGTH 6 -#define MPU6050_TC_OTP_BNK_VLD_BIT 0 - -#define MPU6050_VDDIO_LEVEL_VLOGIC 0 -#define MPU6050_VDDIO_LEVEL_VDD 1 - -#define MPU6050_CFG_EXT_SYNC_SET_BIT 5 -#define MPU6050_CFG_EXT_SYNC_SET_LENGTH 3 -#define MPU6050_CFG_DLPF_CFG_BIT 2 -#define MPU6050_CFG_DLPF_CFG_LENGTH 3 - -#define MPU6050_EXT_SYNC_DISABLED 0x0 -#define MPU6050_EXT_SYNC_TEMP_OUT_L 0x1 -#define MPU6050_EXT_SYNC_GYRO_XOUT_L 0x2 -#define MPU6050_EXT_SYNC_GYRO_YOUT_L 0x3 -#define MPU6050_EXT_SYNC_GYRO_ZOUT_L 0x4 -#define MPU6050_EXT_SYNC_ACCEL_XOUT_L 0x5 -#define MPU6050_EXT_SYNC_ACCEL_YOUT_L 0x6 -#define MPU6050_EXT_SYNC_ACCEL_ZOUT_L 0x7 - -#define MPU6050_DLPF_BW_256 0x00 -#define MPU6050_DLPF_BW_188 0x01 -#define MPU6050_DLPF_BW_98 0x02 -#define MPU6050_DLPF_BW_42 0x03 -#define MPU6050_DLPF_BW_20 0x04 -#define MPU6050_DLPF_BW_10 0x05 -#define MPU6050_DLPF_BW_5 0x06 - -#define MPU6050_GCONFIG_FS_SEL_BIT 4 -#define MPU6050_GCONFIG_FS_SEL_LENGTH 2 - -#define MPU6050_GYRO_FS_250 0x00 -#define MPU6050_GYRO_FS_500 0x01 -#define MPU6050_GYRO_FS_1000 0x02 -#define MPU6050_GYRO_FS_2000 0x03 - -#define MPU6050_ACONFIG_XA_ST_BIT 7 -#define MPU6050_ACONFIG_YA_ST_BIT 6 -#define MPU6050_ACONFIG_ZA_ST_BIT 5 -#define MPU6050_ACONFIG_AFS_SEL_BIT 4 -#define MPU6050_ACONFIG_AFS_SEL_LENGTH 2 -#define MPU6050_ACONFIG_ACCEL_HPF_BIT 2 -#define MPU6050_ACONFIG_ACCEL_HPF_LENGTH 3 - -#define MPU6050_ACCEL_FS_2 0x00 -#define MPU6050_ACCEL_FS_4 0x01 -#define MPU6050_ACCEL_FS_8 0x02 -#define MPU6050_ACCEL_FS_16 0x03 - -#define MPU6050_DHPF_RESET 0x00 -#define MPU6050_DHPF_5 0x01 -#define MPU6050_DHPF_2P5 0x02 -#define MPU6050_DHPF_1P25 0x03 -#define MPU6050_DHPF_0P63 0x04 -#define MPU6050_DHPF_HOLD 0x07 - -#define MPU6050_TEMP_FIFO_EN_BIT 7 -#define MPU6050_XG_FIFO_EN_BIT 6 -#define MPU6050_YG_FIFO_EN_BIT 5 -#define MPU6050_ZG_FIFO_EN_BIT 4 -#define MPU6050_ACCEL_FIFO_EN_BIT 3 -#define MPU6050_SLV2_FIFO_EN_BIT 2 -#define MPU6050_SLV1_FIFO_EN_BIT 1 -#define MPU6050_SLV0_FIFO_EN_BIT 0 - -#define MPU6050_MULT_MST_EN_BIT 7 -#define MPU6050_WAIT_FOR_ES_BIT 6 -#define MPU6050_SLV_3_FIFO_EN_BIT 5 -#define MPU6050_I2C_MST_P_NSR_BIT 4 -#define MPU6050_I2C_MST_CLK_BIT 3 -#define MPU6050_I2C_MST_CLK_LENGTH 4 - -#define MPU6050_CLOCK_DIV_348 0x0 -#define MPU6050_CLOCK_DIV_333 0x1 -#define MPU6050_CLOCK_DIV_320 0x2 -#define MPU6050_CLOCK_DIV_308 0x3 -#define MPU6050_CLOCK_DIV_296 0x4 -#define MPU6050_CLOCK_DIV_286 0x5 -#define MPU6050_CLOCK_DIV_276 0x6 -#define MPU6050_CLOCK_DIV_267 0x7 -#define MPU6050_CLOCK_DIV_258 0x8 -#define MPU6050_CLOCK_DIV_500 0x9 -#define MPU6050_CLOCK_DIV_471 0xA -#define MPU6050_CLOCK_DIV_444 0xB -#define MPU6050_CLOCK_DIV_421 0xC -#define MPU6050_CLOCK_DIV_400 0xD -#define MPU6050_CLOCK_DIV_381 0xE -#define MPU6050_CLOCK_DIV_364 0xF - -#define MPU6050_I2C_SLV_RW_BIT 7 -#define MPU6050_I2C_SLV_ADDR_BIT 6 -#define MPU6050_I2C_SLV_ADDR_LENGTH 7 -#define MPU6050_I2C_SLV_EN_BIT 7 -#define MPU6050_I2C_SLV_BYTE_SW_BIT 6 -#define MPU6050_I2C_SLV_REG_DIS_BIT 5 -#define MPU6050_I2C_SLV_GRP_BIT 4 -#define MPU6050_I2C_SLV_LEN_BIT 3 -#define MPU6050_I2C_SLV_LEN_LENGTH 4 - -#define MPU6050_I2C_SLV4_RW_BIT 7 -#define MPU6050_I2C_SLV4_ADDR_BIT 6 -#define MPU6050_I2C_SLV4_ADDR_LENGTH 7 -#define MPU6050_I2C_SLV4_EN_BIT 7 -#define MPU6050_I2C_SLV4_INT_EN_BIT 6 -#define MPU6050_I2C_SLV4_REG_DIS_BIT 5 -#define MPU6050_I2C_SLV4_MST_DLY_BIT 4 -#define MPU6050_I2C_SLV4_MST_DLY_LENGTH 5 - -#define MPU6050_MST_PASS_THROUGH_BIT 7 -#define MPU6050_MST_I2C_SLV4_DONE_BIT 6 -#define MPU6050_MST_I2C_LOST_ARB_BIT 5 -#define MPU6050_MST_I2C_SLV4_NACK_BIT 4 -#define MPU6050_MST_I2C_SLV3_NACK_BIT 3 -#define MPU6050_MST_I2C_SLV2_NACK_BIT 2 -#define MPU6050_MST_I2C_SLV1_NACK_BIT 1 -#define MPU6050_MST_I2C_SLV0_NACK_BIT 0 - -#define MPU6050_INTCFG_INT_LEVEL_BIT 7 -#define MPU6050_INTCFG_INT_OPEN_BIT 6 -#define MPU6050_INTCFG_LATCH_INT_EN_BIT 5 -#define MPU6050_INTCFG_INT_RD_CLEAR_BIT 4 -#define MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT 3 -#define MPU6050_INTCFG_FSYNC_INT_EN_BIT 2 -#define MPU6050_INTCFG_I2C_BYPASS_EN_BIT 1 -#define MPU6050_INTCFG_CLKOUT_EN_BIT 0 - -#define MPU6050_INTMODE_ACTIVEHIGH 0x00 -#define MPU6050_INTMODE_ACTIVELOW 0x01 - -#define MPU6050_INTDRV_PUSHPULL 0x00 -#define MPU6050_INTDRV_OPENDRAIN 0x01 - -#define MPU6050_INTLATCH_50USPULSE 0x00 -#define MPU6050_INTLATCH_WAITCLEAR 0x01 - -#define MPU6050_INTCLEAR_STATUSREAD 0x00 -#define MPU6050_INTCLEAR_ANYREAD 0x01 - -#define MPU6050_INTERRUPT_FF_BIT 7 -#define MPU6050_INTERRUPT_MOT_BIT 6 -#define MPU6050_INTERRUPT_ZMOT_BIT 5 -#define MPU6050_INTERRUPT_FIFO_OFLOW_BIT 4 -#define MPU6050_INTERRUPT_I2C_MST_INT_BIT 3 -#define MPU6050_INTERRUPT_PLL_RDY_INT_BIT 2 -#define MPU6050_INTERRUPT_DMP_INT_BIT 1 -#define MPU6050_INTERRUPT_DATA_RDY_BIT 0 +#define MPU9150_ADDRESS_AD0_LOW 0x68 // address pin low (GND), default for InvenSense evaluation board +#define MPU9150_ADDRESS_AD0_HIGH 0x69 // address pin high (VCC) +#define MPU9150_DEFAULT_ADDRESS MPU9150_ADDRESS_AD0_LOW + +#define MPU9150_RA_XG_OFFS_TC 0x00 //[7] PWR_MODE, [6:1] XG_OFFS_TC, [0] OTP_BNK_VLD +#define MPU9150_RA_YG_OFFS_TC 0x01 //[7] PWR_MODE, [6:1] YG_OFFS_TC, [0] OTP_BNK_VLD +#define MPU9150_RA_ZG_OFFS_TC 0x02 //[7] PWR_MODE, [6:1] ZG_OFFS_TC, [0] OTP_BNK_VLD +#define MPU9150_RA_X_FINE_GAIN 0x03 //[7:0] X_FINE_GAIN +#define MPU9150_RA_Y_FINE_GAIN 0x04 //[7:0] Y_FINE_GAIN +#define MPU9150_RA_Z_FINE_GAIN 0x05 //[7:0] Z_FINE_GAIN +#define MPU9150_RA_XA_OFFS_H 0x06 //[15:0] XA_OFFS +#define MPU9150_RA_XA_OFFS_L_TC 0x07 +#define MPU9150_RA_YA_OFFS_H 0x08 //[15:0] YA_OFFS +#define MPU9150_RA_YA_OFFS_L_TC 0x09 +#define MPU9150_RA_ZA_OFFS_H 0x0A //[15:0] ZA_OFFS +#define MPU9150_RA_ZA_OFFS_L_TC 0x0B +#define MPU9150_RA_XG_OFFS_USRH 0x13 //[15:0] XG_OFFS_USR +#define MPU9150_RA_XG_OFFS_USRL 0x14 +#define MPU9150_RA_YG_OFFS_USRH 0x15 //[15:0] YG_OFFS_USR +#define MPU9150_RA_YG_OFFS_USRL 0x16 +#define MPU9150_RA_ZG_OFFS_USRH 0x17 //[15:0] ZG_OFFS_USR +#define MPU9150_RA_ZG_OFFS_USRL 0x18 +#define MPU9150_RA_SMPLRT_DIV 0x19 +#define MPU9150_RA_CONFIG 0x1A +#define MPU9150_RA_GYRO_CONFIG 0x1B +#define MPU9150_RA_ACCEL_CONFIG 0x1C +#define MPU9150_RA_FF_THR 0x1D +#define MPU9150_RA_FF_DUR 0x1E +#define MPU9150_RA_MOT_THR 0x1F +#define MPU9150_RA_MOT_DUR 0x20 +#define MPU9150_RA_ZRMOT_THR 0x21 +#define MPU9150_RA_ZRMOT_DUR 0x22 +#define MPU9150_RA_FIFO_EN 0x23 +#define MPU9150_RA_I2C_MST_CTRL 0x24 +#define MPU9150_RA_I2C_SLV0_ADDR 0x25 +#define MPU9150_RA_I2C_SLV0_REG 0x26 +#define MPU9150_RA_I2C_SLV0_CTRL 0x27 +#define MPU9150_RA_I2C_SLV1_ADDR 0x28 +#define MPU9150_RA_I2C_SLV1_REG 0x29 +#define MPU9150_RA_I2C_SLV1_CTRL 0x2A +#define MPU9150_RA_I2C_SLV2_ADDR 0x2B +#define MPU9150_RA_I2C_SLV2_REG 0x2C +#define MPU9150_RA_I2C_SLV2_CTRL 0x2D +#define MPU9150_RA_I2C_SLV3_ADDR 0x2E +#define MPU9150_RA_I2C_SLV3_REG 0x2F +#define MPU9150_RA_I2C_SLV3_CTRL 0x30 +#define MPU9150_RA_I2C_SLV4_ADDR 0x31 +#define MPU9150_RA_I2C_SLV4_REG 0x32 +#define MPU9150_RA_I2C_SLV4_DO 0x33 +#define MPU9150_RA_I2C_SLV4_CTRL 0x34 +#define MPU9150_RA_I2C_SLV4_DI 0x35 +#define MPU9150_RA_I2C_MST_STATUS 0x36 +#define MPU9150_RA_INT_PIN_CFG 0x37 +#define MPU9150_RA_INT_ENABLE 0x38 +#define MPU9150_RA_DMP_INT_STATUS 0x39 +#define MPU9150_RA_INT_STATUS 0x3A +#define MPU9150_RA_ACCEL_XOUT_H 0x3B +#define MPU9150_RA_ACCEL_XOUT_L 0x3C +#define MPU9150_RA_ACCEL_YOUT_H 0x3D +#define MPU9150_RA_ACCEL_YOUT_L 0x3E +#define MPU9150_RA_ACCEL_ZOUT_H 0x3F +#define MPU9150_RA_ACCEL_ZOUT_L 0x40 +#define MPU9150_RA_TEMP_OUT_H 0x41 +#define MPU9150_RA_TEMP_OUT_L 0x42 +#define MPU9150_RA_GYRO_XOUT_H 0x43 +#define MPU9150_RA_GYRO_XOUT_L 0x44 +#define MPU9150_RA_GYRO_YOUT_H 0x45 +#define MPU9150_RA_GYRO_YOUT_L 0x46 +#define MPU9150_RA_GYRO_ZOUT_H 0x47 +#define MPU9150_RA_GYRO_ZOUT_L 0x48 +#define MPU9150_RA_EXT_SENS_DATA_00 0x49 +#define MPU9150_RA_EXT_SENS_DATA_01 0x4A +#define MPU9150_RA_EXT_SENS_DATA_02 0x4B +#define MPU9150_RA_EXT_SENS_DATA_03 0x4C +#define MPU9150_RA_EXT_SENS_DATA_04 0x4D +#define MPU9150_RA_EXT_SENS_DATA_05 0x4E +#define MPU9150_RA_EXT_SENS_DATA_06 0x4F +#define MPU9150_RA_EXT_SENS_DATA_07 0x50 +#define MPU9150_RA_EXT_SENS_DATA_08 0x51 +#define MPU9150_RA_EXT_SENS_DATA_09 0x52 +#define MPU9150_RA_EXT_SENS_DATA_10 0x53 +#define MPU9150_RA_EXT_SENS_DATA_11 0x54 +#define MPU9150_RA_EXT_SENS_DATA_12 0x55 +#define MPU9150_RA_EXT_SENS_DATA_13 0x56 +#define MPU9150_RA_EXT_SENS_DATA_14 0x57 +#define MPU9150_RA_EXT_SENS_DATA_15 0x58 +#define MPU9150_RA_EXT_SENS_DATA_16 0x59 +#define MPU9150_RA_EXT_SENS_DATA_17 0x5A +#define MPU9150_RA_EXT_SENS_DATA_18 0x5B +#define MPU9150_RA_EXT_SENS_DATA_19 0x5C +#define MPU9150_RA_EXT_SENS_DATA_20 0x5D +#define MPU9150_RA_EXT_SENS_DATA_21 0x5E +#define MPU9150_RA_EXT_SENS_DATA_22 0x5F +#define MPU9150_RA_EXT_SENS_DATA_23 0x60 +#define MPU9150_RA_MOT_DETECT_STATUS 0x61 +#define MPU9150_RA_I2C_SLV0_DO 0x63 +#define MPU9150_RA_I2C_SLV1_DO 0x64 +#define MPU9150_RA_I2C_SLV2_DO 0x65 +#define MPU9150_RA_I2C_SLV3_DO 0x66 +#define MPU9150_RA_I2C_MST_DELAY_CTRL 0x67 +#define MPU9150_RA_SIGNAL_PATH_RESET 0x68 +#define MPU9150_RA_MOT_DETECT_CTRL 0x69 +#define MPU9150_RA_USER_CTRL 0x6A +#define MPU9150_RA_PWR_MGMT_1 0x6B +#define MPU9150_RA_PWR_MGMT_2 0x6C +#define MPU9150_RA_BANK_SEL 0x6D +#define MPU9150_RA_MEM_START_ADDR 0x6E +#define MPU9150_RA_MEM_R_W 0x6F +#define MPU9150_RA_DMP_CFG_1 0x70 +#define MPU9150_RA_DMP_CFG_2 0x71 +#define MPU9150_RA_FIFO_COUNTH 0x72 +#define MPU9150_RA_FIFO_COUNTL 0x73 +#define MPU9150_RA_FIFO_R_W 0x74 +#define MPU9150_RA_WHO_AM_I 0x75 + +#define MPU9150_TC_PWR_MODE_BIT 7 +#define MPU9150_TC_OFFSET_BIT 6 +#define MPU9150_TC_OFFSET_LENGTH 6 +#define MPU9150_TC_OTP_BNK_VLD_BIT 0 + +#define MPU9150_VDDIO_LEVEL_VLOGIC 0 +#define MPU9150_VDDIO_LEVEL_VDD 1 + +#define MPU9150_CFG_EXT_SYNC_SET_BIT 5 +#define MPU9150_CFG_EXT_SYNC_SET_LENGTH 3 +#define MPU9150_CFG_DLPF_CFG_BIT 2 +#define MPU9150_CFG_DLPF_CFG_LENGTH 3 + +#define MPU9150_EXT_SYNC_DISABLED 0x0 +#define MPU9150_EXT_SYNC_TEMP_OUT_L 0x1 +#define MPU9150_EXT_SYNC_GYRO_XOUT_L 0x2 +#define MPU9150_EXT_SYNC_GYRO_YOUT_L 0x3 +#define MPU9150_EXT_SYNC_GYRO_ZOUT_L 0x4 +#define MPU9150_EXT_SYNC_ACCEL_XOUT_L 0x5 +#define MPU9150_EXT_SYNC_ACCEL_YOUT_L 0x6 +#define MPU9150_EXT_SYNC_ACCEL_ZOUT_L 0x7 + +#define MPU9150_DLPF_BW_256 0x00 +#define MPU9150_DLPF_BW_188 0x01 +#define MPU9150_DLPF_BW_98 0x02 +#define MPU9150_DLPF_BW_42 0x03 +#define MPU9150_DLPF_BW_20 0x04 +#define MPU9150_DLPF_BW_10 0x05 +#define MPU9150_DLPF_BW_5 0x06 + +#define MPU9150_GCONFIG_FS_SEL_BIT 4 +#define MPU9150_GCONFIG_FS_SEL_LENGTH 2 + +#define MPU9150_GYRO_FS_250 0x00 +#define MPU9150_GYRO_FS_500 0x01 +#define MPU9150_GYRO_FS_1000 0x02 +#define MPU9150_GYRO_FS_2000 0x03 + +#define MPU9150_ACONFIG_XA_ST_BIT 7 +#define MPU9150_ACONFIG_YA_ST_BIT 6 +#define MPU9150_ACONFIG_ZA_ST_BIT 5 +#define MPU9150_ACONFIG_AFS_SEL_BIT 4 +#define MPU9150_ACONFIG_AFS_SEL_LENGTH 2 +#define MPU9150_ACONFIG_ACCEL_HPF_BIT 2 +#define MPU9150_ACONFIG_ACCEL_HPF_LENGTH 3 + +#define MPU9150_ACCEL_FS_2 0x00 +#define MPU9150_ACCEL_FS_4 0x01 +#define MPU9150_ACCEL_FS_8 0x02 +#define MPU9150_ACCEL_FS_16 0x03 + +#define MPU9150_DHPF_RESET 0x00 +#define MPU9150_DHPF_5 0x01 +#define MPU9150_DHPF_2P5 0x02 +#define MPU9150_DHPF_1P25 0x03 +#define MPU9150_DHPF_0P63 0x04 +#define MPU9150_DHPF_HOLD 0x07 + +#define MPU9150_TEMP_FIFO_EN_BIT 7 +#define MPU9150_XG_FIFO_EN_BIT 6 +#define MPU9150_YG_FIFO_EN_BIT 5 +#define MPU9150_ZG_FIFO_EN_BIT 4 +#define MPU9150_ACCEL_FIFO_EN_BIT 3 +#define MPU9150_SLV2_FIFO_EN_BIT 2 +#define MPU9150_SLV1_FIFO_EN_BIT 1 +#define MPU9150_SLV0_FIFO_EN_BIT 0 + +#define MPU9150_MULT_MST_EN_BIT 7 +#define MPU9150_WAIT_FOR_ES_BIT 6 +#define MPU9150_SLV_3_FIFO_EN_BIT 5 +#define MPU9150_I2C_MST_P_NSR_BIT 4 +#define MPU9150_I2C_MST_CLK_BIT 3 +#define MPU9150_I2C_MST_CLK_LENGTH 4 + +#define MPU9150_CLOCK_DIV_348 0x0 +#define MPU9150_CLOCK_DIV_333 0x1 +#define MPU9150_CLOCK_DIV_320 0x2 +#define MPU9150_CLOCK_DIV_308 0x3 +#define MPU9150_CLOCK_DIV_296 0x4 +#define MPU9150_CLOCK_DIV_286 0x5 +#define MPU9150_CLOCK_DIV_276 0x6 +#define MPU9150_CLOCK_DIV_267 0x7 +#define MPU9150_CLOCK_DIV_258 0x8 +#define MPU9150_CLOCK_DIV_500 0x9 +#define MPU9150_CLOCK_DIV_471 0xA +#define MPU9150_CLOCK_DIV_444 0xB +#define MPU9150_CLOCK_DIV_421 0xC +#define MPU9150_CLOCK_DIV_400 0xD +#define MPU9150_CLOCK_DIV_381 0xE +#define MPU9150_CLOCK_DIV_364 0xF + +#define MPU9150_I2C_SLV_RW_BIT 7 +#define MPU9150_I2C_SLV_ADDR_BIT 6 +#define MPU9150_I2C_SLV_ADDR_LENGTH 7 +#define MPU9150_I2C_SLV_EN_BIT 7 +#define MPU9150_I2C_SLV_BYTE_SW_BIT 6 +#define MPU9150_I2C_SLV_REG_DIS_BIT 5 +#define MPU9150_I2C_SLV_GRP_BIT 4 +#define MPU9150_I2C_SLV_LEN_BIT 3 +#define MPU9150_I2C_SLV_LEN_LENGTH 4 + +#define MPU9150_I2C_SLV4_RW_BIT 7 +#define MPU9150_I2C_SLV4_ADDR_BIT 6 +#define MPU9150_I2C_SLV4_ADDR_LENGTH 7 +#define MPU9150_I2C_SLV4_EN_BIT 7 +#define MPU9150_I2C_SLV4_INT_EN_BIT 6 +#define MPU9150_I2C_SLV4_REG_DIS_BIT 5 +#define MPU9150_I2C_SLV4_MST_DLY_BIT 4 +#define MPU9150_I2C_SLV4_MST_DLY_LENGTH 5 + +#define MPU9150_MST_PASS_THROUGH_BIT 7 +#define MPU9150_MST_I2C_SLV4_DONE_BIT 6 +#define MPU9150_MST_I2C_LOST_ARB_BIT 5 +#define MPU9150_MST_I2C_SLV4_NACK_BIT 4 +#define MPU9150_MST_I2C_SLV3_NACK_BIT 3 +#define MPU9150_MST_I2C_SLV2_NACK_BIT 2 +#define MPU9150_MST_I2C_SLV1_NACK_BIT 1 +#define MPU9150_MST_I2C_SLV0_NACK_BIT 0 + +#define MPU9150_INTCFG_INT_LEVEL_BIT 7 +#define MPU9150_INTCFG_INT_OPEN_BIT 6 +#define MPU9150_INTCFG_LATCH_INT_EN_BIT 5 +#define MPU9150_INTCFG_INT_RD_CLEAR_BIT 4 +#define MPU9150_INTCFG_FSYNC_INT_LEVEL_BIT 3 +#define MPU9150_INTCFG_FSYNC_INT_EN_BIT 2 +#define MPU9150_INTCFG_I2C_BYPASS_EN_BIT 1 +#define MPU9150_INTCFG_CLKOUT_EN_BIT 0 + +#define MPU9150_INTMODE_ACTIVEHIGH 0x00 +#define MPU9150_INTMODE_ACTIVELOW 0x01 + +#define MPU9150_INTDRV_PUSHPULL 0x00 +#define MPU9150_INTDRV_OPENDRAIN 0x01 + +#define MPU9150_INTLATCH_50USPULSE 0x00 +#define MPU9150_INTLATCH_WAITCLEAR 0x01 + +#define MPU9150_INTCLEAR_STATUSREAD 0x00 +#define MPU9150_INTCLEAR_ANYREAD 0x01 + +#define MPU9150_INTERRUPT_FF_BIT 7 +#define MPU9150_INTERRUPT_MOT_BIT 6 +#define MPU9150_INTERRUPT_ZMOT_BIT 5 +#define MPU9150_INTERRUPT_FIFO_OFLOW_BIT 4 +#define MPU9150_INTERRUPT_I2C_MST_INT_BIT 3 +#define MPU9150_INTERRUPT_PLL_RDY_INT_BIT 2 +#define MPU9150_INTERRUPT_DMP_INT_BIT 1 +#define MPU9150_INTERRUPT_DATA_RDY_BIT 0 // TODO: figure out what these actually do // UMPL source code is not very obivous -#define MPU6050_DMPINT_5_BIT 5 -#define MPU6050_DMPINT_4_BIT 4 -#define MPU6050_DMPINT_3_BIT 3 -#define MPU6050_DMPINT_2_BIT 2 -#define MPU6050_DMPINT_1_BIT 1 -#define MPU6050_DMPINT_0_BIT 0 - -#define MPU6050_MOTION_MOT_XNEG_BIT 7 -#define MPU6050_MOTION_MOT_XPOS_BIT 6 -#define MPU6050_MOTION_MOT_YNEG_BIT 5 -#define MPU6050_MOTION_MOT_YPOS_BIT 4 -#define MPU6050_MOTION_MOT_ZNEG_BIT 3 -#define MPU6050_MOTION_MOT_ZPOS_BIT 2 -#define MPU6050_MOTION_MOT_ZRMOT_BIT 0 - -#define MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT 7 -#define MPU6050_DELAYCTRL_I2C_SLV4_DLY_EN_BIT 4 -#define MPU6050_DELAYCTRL_I2C_SLV3_DLY_EN_BIT 3 -#define MPU6050_DELAYCTRL_I2C_SLV2_DLY_EN_BIT 2 -#define MPU6050_DELAYCTRL_I2C_SLV1_DLY_EN_BIT 1 -#define MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT 0 - -#define MPU6050_PATHRESET_GYRO_RESET_BIT 2 -#define MPU6050_PATHRESET_ACCEL_RESET_BIT 1 -#define MPU6050_PATHRESET_TEMP_RESET_BIT 0 - -#define MPU6050_DETECT_ACCEL_ON_DELAY_BIT 5 -#define MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH 2 -#define MPU6050_DETECT_FF_COUNT_BIT 3 -#define MPU6050_DETECT_FF_COUNT_LENGTH 2 -#define MPU6050_DETECT_MOT_COUNT_BIT 1 -#define MPU6050_DETECT_MOT_COUNT_LENGTH 2 - -#define MPU6050_DETECT_DECREMENT_RESET 0x0 -#define MPU6050_DETECT_DECREMENT_1 0x1 -#define MPU6050_DETECT_DECREMENT_2 0x2 -#define MPU6050_DETECT_DECREMENT_4 0x3 - -#define MPU6050_USERCTRL_DMP_EN_BIT 7 -#define MPU6050_USERCTRL_FIFO_EN_BIT 6 -#define MPU6050_USERCTRL_I2C_MST_EN_BIT 5 -#define MPU6050_USERCTRL_I2C_IF_DIS_BIT 4 -#define MPU6050_USERCTRL_DMP_RESET_BIT 3 -#define MPU6050_USERCTRL_FIFO_RESET_BIT 2 -#define MPU6050_USERCTRL_I2C_MST_RESET_BIT 1 -#define MPU6050_USERCTRL_SIG_COND_RESET_BIT 0 - -#define MPU6050_PWR1_DEVICE_RESET_BIT 7 -#define MPU6050_PWR1_SLEEP_BIT 6 -#define MPU6050_PWR1_CYCLE_BIT 5 -#define MPU6050_PWR1_TEMP_DIS_BIT 3 -#define MPU6050_PWR1_CLKSEL_BIT 2 -#define MPU6050_PWR1_CLKSEL_LENGTH 3 - -#define MPU6050_CLOCK_INTERNAL 0x00 -#define MPU6050_CLOCK_PLL_XGYRO 0x01 -#define MPU6050_CLOCK_PLL_YGYRO 0x02 -#define MPU6050_CLOCK_PLL_ZGYRO 0x03 -#define MPU6050_CLOCK_PLL_EXT32K 0x04 -#define MPU6050_CLOCK_PLL_EXT19M 0x05 -#define MPU6050_CLOCK_KEEP_RESET 0x07 - -#define MPU6050_PWR2_LP_WAKE_CTRL_BIT 7 -#define MPU6050_PWR2_LP_WAKE_CTRL_LENGTH 2 -#define MPU6050_PWR2_STBY_XA_BIT 5 -#define MPU6050_PWR2_STBY_YA_BIT 4 -#define MPU6050_PWR2_STBY_ZA_BIT 3 -#define MPU6050_PWR2_STBY_XG_BIT 2 -#define MPU6050_PWR2_STBY_YG_BIT 1 -#define MPU6050_PWR2_STBY_ZG_BIT 0 - -#define MPU6050_WAKE_FREQ_1P25 0x0 -#define MPU6050_WAKE_FREQ_2P5 0x1 -#define MPU6050_WAKE_FREQ_5 0x2 -#define MPU6050_WAKE_FREQ_10 0x3 - -#define MPU6050_BANKSEL_PRFTCH_EN_BIT 6 -#define MPU6050_BANKSEL_CFG_USER_BANK_BIT 5 -#define MPU6050_BANKSEL_MEM_SEL_BIT 4 -#define MPU6050_BANKSEL_MEM_SEL_LENGTH 5 - -#define MPU6050_WHO_AM_I_BIT 6 -#define MPU6050_WHO_AM_I_LENGTH 6 - -#define MPU6050_DMP_MEMORY_BANKS 8 -#define MPU6050_DMP_MEMORY_BANK_SIZE 256 -#define MPU6050_DMP_MEMORY_CHUNK_SIZE 16 +#define MPU9150_DMPINT_5_BIT 5 +#define MPU9150_DMPINT_4_BIT 4 +#define MPU9150_DMPINT_3_BIT 3 +#define MPU9150_DMPINT_2_BIT 2 +#define MPU9150_DMPINT_1_BIT 1 +#define MPU9150_DMPINT_0_BIT 0 + +#define MPU9150_MOTION_MOT_XNEG_BIT 7 +#define MPU9150_MOTION_MOT_XPOS_BIT 6 +#define MPU9150_MOTION_MOT_YNEG_BIT 5 +#define MPU9150_MOTION_MOT_YPOS_BIT 4 +#define MPU9150_MOTION_MOT_ZNEG_BIT 3 +#define MPU9150_MOTION_MOT_ZPOS_BIT 2 +#define MPU9150_MOTION_MOT_ZRMOT_BIT 0 + +#define MPU9150_DELAYCTRL_DELAY_ES_SHADOW_BIT 7 +#define MPU9150_DELAYCTRL_I2C_SLV4_DLY_EN_BIT 4 +#define MPU9150_DELAYCTRL_I2C_SLV3_DLY_EN_BIT 3 +#define MPU9150_DELAYCTRL_I2C_SLV2_DLY_EN_BIT 2 +#define MPU9150_DELAYCTRL_I2C_SLV1_DLY_EN_BIT 1 +#define MPU9150_DELAYCTRL_I2C_SLV0_DLY_EN_BIT 0 + +#define MPU9150_PATHRESET_GYRO_RESET_BIT 2 +#define MPU9150_PATHRESET_ACCEL_RESET_BIT 1 +#define MPU9150_PATHRESET_TEMP_RESET_BIT 0 + +#define MPU9150_DETECT_ACCEL_ON_DELAY_BIT 5 +#define MPU9150_DETECT_ACCEL_ON_DELAY_LENGTH 2 +#define MPU9150_DETECT_FF_COUNT_BIT 3 +#define MPU9150_DETECT_FF_COUNT_LENGTH 2 +#define MPU9150_DETECT_MOT_COUNT_BIT 1 +#define MPU9150_DETECT_MOT_COUNT_LENGTH 2 + +#define MPU9150_DETECT_DECREMENT_RESET 0x0 +#define MPU9150_DETECT_DECREMENT_1 0x1 +#define MPU9150_DETECT_DECREMENT_2 0x2 +#define MPU9150_DETECT_DECREMENT_4 0x3 + +#define MPU9150_USERCTRL_DMP_EN_BIT 7 +#define MPU9150_USERCTRL_FIFO_EN_BIT 6 +#define MPU9150_USERCTRL_I2C_MST_EN_BIT 5 +#define MPU9150_USERCTRL_I2C_IF_DIS_BIT 4 +#define MPU9150_USERCTRL_DMP_RESET_BIT 3 +#define MPU9150_USERCTRL_FIFO_RESET_BIT 2 +#define MPU9150_USERCTRL_I2C_MST_RESET_BIT 1 +#define MPU9150_USERCTRL_SIG_COND_RESET_BIT 0 + +#define MPU9150_PWR1_DEVICE_RESET_BIT 7 +#define MPU9150_PWR1_SLEEP_BIT 6 +#define MPU9150_PWR1_CYCLE_BIT 5 +#define MPU9150_PWR1_TEMP_DIS_BIT 3 +#define MPU9150_PWR1_CLKSEL_BIT 2 +#define MPU9150_PWR1_CLKSEL_LENGTH 3 + +#define MPU9150_CLOCK_INTERNAL 0x00 +#define MPU9150_CLOCK_PLL_XGYRO 0x01 +#define MPU9150_CLOCK_PLL_YGYRO 0x02 +#define MPU9150_CLOCK_PLL_ZGYRO 0x03 +#define MPU9150_CLOCK_PLL_EXT32K 0x04 +#define MPU9150_CLOCK_PLL_EXT19M 0x05 +#define MPU9150_CLOCK_KEEP_RESET 0x07 + +#define MPU9150_PWR2_LP_WAKE_CTRL_BIT 7 +#define MPU9150_PWR2_LP_WAKE_CTRL_LENGTH 2 +#define MPU9150_PWR2_STBY_XA_BIT 5 +#define MPU9150_PWR2_STBY_YA_BIT 4 +#define MPU9150_PWR2_STBY_ZA_BIT 3 +#define MPU9150_PWR2_STBY_XG_BIT 2 +#define MPU9150_PWR2_STBY_YG_BIT 1 +#define MPU9150_PWR2_STBY_ZG_BIT 0 + +#define MPU9150_WAKE_FREQ_1P25 0x0 +#define MPU9150_WAKE_FREQ_2P5 0x1 +#define MPU9150_WAKE_FREQ_5 0x2 +#define MPU9150_WAKE_FREQ_10 0x3 + +#define MPU9150_BANKSEL_PRFTCH_EN_BIT 6 +#define MPU9150_BANKSEL_CFG_USER_BANK_BIT 5 +#define MPU9150_BANKSEL_MEM_SEL_BIT 4 +#define MPU9150_BANKSEL_MEM_SEL_LENGTH 5 + +#define MPU9150_WHO_AM_I_BIT 6 +#define MPU9150_WHO_AM_I_LENGTH 6 + +#define MPU9150_DMP_MEMORY_BANKS 8 +#define MPU9150_DMP_MEMORY_BANK_SIZE 256 +#define MPU9150_DMP_MEMORY_CHUNK_SIZE 16 // note: DMP code memory blocks defined at end of header file -class MPU6050 { +class MPU9150 { public: - MPU6050(); - MPU6050(uint8_t address); + MPU9150(); + MPU9150(uint8_t address); void initialize(); bool testConnection(); @@ -795,7 +795,7 @@ class MPU6050 { void setDMPConfig2(uint8_t config); // special methods for MotionApps 2.0 implementation - #ifdef MPU6050_INCLUDE_DMP_MOTIONAPPS20 + #ifdef MPU9150_INCLUDE_DMP_MOTIONAPPS20 uint8_t *dmpPacketBuffer; uint16_t dmpPacketSize; @@ -896,7 +896,7 @@ class MPU6050 { #endif // special methods for MotionApps 4.1 implementation - #ifdef MPU6050_INCLUDE_DMP_MOTIONAPPS41 + #ifdef MPU9150_INCLUDE_DMP_MOTIONAPPS41 uint8_t *dmpPacketBuffer; uint16_t dmpPacketSize; @@ -1002,4 +1002,4 @@ class MPU6050 { uint8_t buffer[14]; }; -#endif /* _MPU6050_H_ */ +#endif /* _MPU9150_H_ */ diff --git a/Arduino/MPU9150/MPU9150_6Axis_MotionApps20.h b/Arduino/MPU9150/MPU9150_6Axis_MotionApps20.h index 0e699c47..8cff9114 100644 --- a/Arduino/MPU9150/MPU9150_6Axis_MotionApps20.h +++ b/Arduino/MPU9150/MPU9150_6Axis_MotionApps20.h @@ -1,5 +1,5 @@ -// I2Cdev library collection - MPU6050 I2C device class, 6-axis MotionApps 2.0 implementation -// Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00) +// I2Cdev library collection - MPU9150 I2C device class, 6-axis MotionApps 2.0 implementation +// Based on InvenSense MPU-9150 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00) // 5/20/2013 by Jeff Rowberg // Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib // @@ -30,16 +30,16 @@ THE SOFTWARE. =============================================== */ -#ifndef _MPU6050_6AXIS_MOTIONAPPS20_H_ -#define _MPU6050_6AXIS_MOTIONAPPS20_H_ +#ifndef _MPU9150_6AXIS_MOTIONAPPS20_H_ +#define _MPU9150_6AXIS_MOTIONAPPS20_H_ #include "I2Cdev.h" #include "helper_3dmath.h" -// MotionApps 2.0 DMP implementation, built using the MPU-6050EVB evaluation board -#define MPU6050_INCLUDE_DMP_MOTIONAPPS20 +// MotionApps 2.0 DMP implementation, built using the MPU-9150EVB evaluation board +#define MPU9150_INCLUDE_DMP_MOTIONAPPS20 -#include "MPU6050.h" +#include "MPU9150.h" // Tom Carpenter's conditional PROGMEM code // http://forum.arduino.cc/index.php?topic=129407.0 @@ -113,9 +113,9 @@ THE SOFTWARE. #define DEBUG_PRINTLNF(x, y) #endif -#define MPU6050_DMP_CODE_SIZE 1929 // dmpMemory[] -#define MPU6050_DMP_CONFIG_SIZE 192 // dmpConfig[] -#define MPU6050_DMP_UPDATES_SIZE 47 // dmpUpdates[] +#define MPU9150_DMP_CODE_SIZE 1929 // dmpMemory[] +#define MPU9150_DMP_CONFIG_SIZE 192 // dmpConfig[] +#define MPU9150_DMP_UPDATES_SIZE 47 // dmpUpdates[] /* ================================================================================================ * | Default MotionApps v2.0 42-byte FIFO packet structure: | @@ -130,7 +130,7 @@ THE SOFTWARE. // this block of memory gets written to the MPU on start-up, and it seems // to be volatile memory, so it has to be done each time (it only takes ~1 // second though) -const unsigned char dmpMemory[MPU6050_DMP_CODE_SIZE] PROGMEM = { +const unsigned char dmpMemory[MPU9150_DMP_CODE_SIZE] PROGMEM = { // bank 0, 256 bytes 0xFB, 0x00, 0x00, 0x3E, 0x00, 0x0B, 0x00, 0x36, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, 0x00, 0x65, 0x00, 0x54, 0xFF, 0xEF, 0x00, 0x00, 0xFA, 0x80, 0x00, 0x0B, 0x12, 0x82, 0x00, 0x01, @@ -270,7 +270,7 @@ const unsigned char dmpMemory[MPU6050_DMP_CODE_SIZE] PROGMEM = { }; // thanks to Noah Zerkin for piecing this stuff together! -const unsigned char dmpConfig[MPU6050_DMP_CONFIG_SIZE] PROGMEM = { +const unsigned char dmpConfig[MPU9150_DMP_CONFIG_SIZE] PROGMEM = { // BANK OFFSET LENGTH [DATA] 0x03, 0x7B, 0x03, 0x4C, 0xCD, 0x6C, // FCFG_1 inv_set_gyro_calibration 0x03, 0xAB, 0x03, 0x36, 0x56, 0x76, // FCFG_3 inv_set_gyro_calibration @@ -312,7 +312,7 @@ const unsigned char dmpConfig[MPU6050_DMP_CONFIG_SIZE] PROGMEM = { // the FIFO output at the desired rate. Handling FIFO overflow cleanly is also a good idea. }; -const unsigned char dmpUpdates[MPU6050_DMP_UPDATES_SIZE] PROGMEM = { +const unsigned char dmpUpdates[MPU9150_DMP_UPDATES_SIZE] PROGMEM = { 0x01, 0xB2, 0x02, 0xFF, 0xFF, 0x01, 0x90, 0x04, 0x09, 0x23, 0xA1, 0x35, 0x01, 0x6A, 0x02, 0x06, 0x00, @@ -322,9 +322,9 @@ const unsigned char dmpUpdates[MPU6050_DMP_UPDATES_SIZE] PROGMEM = { 0x00, 0x60, 0x04, 0x00, 0x40, 0x00, 0x00 }; -uint8_t MPU6050::dmpInitialize() { +uint8_t MPU9150::dmpInitialize() { // reset device - DEBUG_PRINTLN(F("\n\nResetting MPU6050...")); + DEBUG_PRINTLN(F("\n\nResetting MPU9150...")); reset(); delay(30); // wait after reset @@ -381,20 +381,20 @@ uint8_t MPU6050::dmpInitialize() { // load DMP code into memory banks DEBUG_PRINT(F("Writing DMP code to MPU memory banks (")); - DEBUG_PRINT(MPU6050_DMP_CODE_SIZE); + DEBUG_PRINT(MPU9150_DMP_CODE_SIZE); DEBUG_PRINTLN(F(" bytes)")); - if (writeProgMemoryBlock(dmpMemory, MPU6050_DMP_CODE_SIZE)) { + if (writeProgMemoryBlock(dmpMemory, MPU9150_DMP_CODE_SIZE)) { DEBUG_PRINTLN(F("Success! DMP code written and verified.")); // write DMP configuration DEBUG_PRINT(F("Writing DMP configuration to MPU memory banks (")); - DEBUG_PRINT(MPU6050_DMP_CONFIG_SIZE); + DEBUG_PRINT(MPU9150_DMP_CONFIG_SIZE); DEBUG_PRINTLN(F(" bytes in config def)")); - if (writeProgDMPConfigurationSet(dmpConfig, MPU6050_DMP_CONFIG_SIZE)) { + if (writeProgDMPConfigurationSet(dmpConfig, MPU9150_DMP_CONFIG_SIZE)) { DEBUG_PRINTLN(F("Success! DMP configuration written and verified.")); DEBUG_PRINTLN(F("Setting clock source to Z Gyro...")); - setClockSource(MPU6050_CLOCK_PLL_ZGYRO); + setClockSource(MPU9150_CLOCK_PLL_ZGYRO); DEBUG_PRINTLN(F("Setting DMP and FIFO_OFLOW interrupts enabled...")); setIntEnabled(0x12); @@ -403,13 +403,13 @@ uint8_t MPU6050::dmpInitialize() { setRate(4); // 1khz / (1 + 4) = 200 Hz DEBUG_PRINTLN(F("Setting external frame sync to TEMP_OUT_L[0]...")); - setExternalFrameSync(MPU6050_EXT_SYNC_TEMP_OUT_L); + setExternalFrameSync(MPU9150_EXT_SYNC_TEMP_OUT_L); DEBUG_PRINTLN(F("Setting DLPF bandwidth to 42Hz...")); - setDLPFMode(MPU6050_DLPF_BW_42); + setDLPFMode(MPU9150_DLPF_BW_42); DEBUG_PRINTLN(F("Setting gyro sensitivity to +/- 2000 deg/sec...")); - setFullScaleGyroRange(MPU6050_GYRO_FS_2000); + setFullScaleGyroRange(MPU9150_GYRO_FS_2000); DEBUG_PRINTLN(F("Setting DMP configuration bytes (function unknown)...")); setDMPConfig1(0x03); @@ -547,34 +547,34 @@ uint8_t MPU6050::dmpInitialize() { return 0; // success } -bool MPU6050::dmpPacketAvailable() { +bool MPU9150::dmpPacketAvailable() { return getFIFOCount() >= dmpGetFIFOPacketSize(); } -// uint8_t MPU6050::dmpSetFIFORate(uint8_t fifoRate); -// uint8_t MPU6050::dmpGetFIFORate(); -// uint8_t MPU6050::dmpGetSampleStepSizeMS(); -// uint8_t MPU6050::dmpGetSampleFrequency(); -// int32_t MPU6050::dmpDecodeTemperature(int8_t tempReg); - -//uint8_t MPU6050::dmpRegisterFIFORateProcess(inv_obj_func func, int16_t priority); -//uint8_t MPU6050::dmpUnregisterFIFORateProcess(inv_obj_func func); -//uint8_t MPU6050::dmpRunFIFORateProcesses(); - -// uint8_t MPU6050::dmpSendQuaternion(uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendGyro(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendAccel(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendLinearAccel(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendLinearAccelInWorld(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendControlData(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendSensorData(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendExternalSensorData(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendGravity(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendPacketNumber(uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendQuantizedAccel(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendEIS(uint_fast16_t elements, uint_fast16_t accuracy); - -uint8_t MPU6050::dmpGetAccel(int32_t *data, const uint8_t* packet) { +// uint8_t MPU9150::dmpSetFIFORate(uint8_t fifoRate); +// uint8_t MPU9150::dmpGetFIFORate(); +// uint8_t MPU9150::dmpGetSampleStepSizeMS(); +// uint8_t MPU9150::dmpGetSampleFrequency(); +// int32_t MPU9150::dmpDecodeTemperature(int8_t tempReg); + +//uint8_t MPU9150::dmpRegisterFIFORateProcess(inv_obj_func func, int16_t priority); +//uint8_t MPU9150::dmpUnregisterFIFORateProcess(inv_obj_func func); +//uint8_t MPU9150::dmpRunFIFORateProcesses(); + +// uint8_t MPU9150::dmpSendQuaternion(uint_fast16_t accuracy); +// uint8_t MPU9150::dmpSendGyro(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU9150::dmpSendAccel(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU9150::dmpSendLinearAccel(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU9150::dmpSendLinearAccelInWorld(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU9150::dmpSendControlData(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU9150::dmpSendSensorData(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU9150::dmpSendExternalSensorData(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU9150::dmpSendGravity(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU9150::dmpSendPacketNumber(uint_fast16_t accuracy); +// uint8_t MPU9150::dmpSendQuantizedAccel(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU9150::dmpSendEIS(uint_fast16_t elements, uint_fast16_t accuracy); + +uint8_t MPU9150::dmpGetAccel(int32_t *data, const uint8_t* packet) { // TODO: accommodate different arrangements of sent data (ONLY default supported now) if (packet == 0) packet = dmpPacketBuffer; data[0] = ((packet[28] << 24) + (packet[29] << 16) + (packet[30] << 8) + packet[31]); @@ -582,7 +582,7 @@ uint8_t MPU6050::dmpGetAccel(int32_t *data, const uint8_t* packet) { data[2] = ((packet[36] << 24) + (packet[37] << 16) + (packet[38] << 8) + packet[39]); return 0; } -uint8_t MPU6050::dmpGetAccel(int16_t *data, const uint8_t* packet) { +uint8_t MPU9150::dmpGetAccel(int16_t *data, const uint8_t* packet) { // TODO: accommodate different arrangements of sent data (ONLY default supported now) if (packet == 0) packet = dmpPacketBuffer; data[0] = (packet[28] << 8) + packet[29]; @@ -590,7 +590,7 @@ uint8_t MPU6050::dmpGetAccel(int16_t *data, const uint8_t* packet) { data[2] = (packet[36] << 8) + packet[37]; return 0; } -uint8_t MPU6050::dmpGetAccel(VectorInt16 *v, const uint8_t* packet) { +uint8_t MPU9150::dmpGetAccel(VectorInt16 *v, const uint8_t* packet) { // TODO: accommodate different arrangements of sent data (ONLY default supported now) if (packet == 0) packet = dmpPacketBuffer; v -> x = (packet[28] << 8) + packet[29]; @@ -598,7 +598,7 @@ uint8_t MPU6050::dmpGetAccel(VectorInt16 *v, const uint8_t* packet) { v -> z = (packet[36] << 8) + packet[37]; return 0; } -uint8_t MPU6050::dmpGetQuaternion(int32_t *data, const uint8_t* packet) { +uint8_t MPU9150::dmpGetQuaternion(int32_t *data, const uint8_t* packet) { // TODO: accommodate different arrangements of sent data (ONLY default supported now) if (packet == 0) packet = dmpPacketBuffer; data[0] = ((packet[0] << 24) + (packet[1] << 16) + (packet[2] << 8) + packet[3]); @@ -607,7 +607,7 @@ uint8_t MPU6050::dmpGetQuaternion(int32_t *data, const uint8_t* packet) { data[3] = ((packet[12] << 24) + (packet[13] << 16) + (packet[14] << 8) + packet[15]); return 0; } -uint8_t MPU6050::dmpGetQuaternion(int16_t *data, const uint8_t* packet) { +uint8_t MPU9150::dmpGetQuaternion(int16_t *data, const uint8_t* packet) { // TODO: accommodate different arrangements of sent data (ONLY default supported now) if (packet == 0) packet = dmpPacketBuffer; data[0] = ((packet[0] << 8) + packet[1]); @@ -616,7 +616,7 @@ uint8_t MPU6050::dmpGetQuaternion(int16_t *data, const uint8_t* packet) { data[3] = ((packet[12] << 8) + packet[13]); return 0; } -uint8_t MPU6050::dmpGetQuaternion(Quaternion *q, const uint8_t* packet) { +uint8_t MPU9150::dmpGetQuaternion(Quaternion *q, const uint8_t* packet) { // TODO: accommodate different arrangements of sent data (ONLY default supported now) int16_t qI[4]; uint8_t status = dmpGetQuaternion(qI, packet); @@ -629,9 +629,9 @@ uint8_t MPU6050::dmpGetQuaternion(Quaternion *q, const uint8_t* packet) { } return status; // int16 return value, indicates error if this line is reached } -// uint8_t MPU6050::dmpGet6AxisQuaternion(long *data, const uint8_t* packet); -// uint8_t MPU6050::dmpGetRelativeQuaternion(long *data, const uint8_t* packet); -uint8_t MPU6050::dmpGetGyro(int32_t *data, const uint8_t* packet) { +// uint8_t MPU9150::dmpGet6AxisQuaternion(long *data, const uint8_t* packet); +// uint8_t MPU9150::dmpGetRelativeQuaternion(long *data, const uint8_t* packet); +uint8_t MPU9150::dmpGetGyro(int32_t *data, const uint8_t* packet) { // TODO: accommodate different arrangements of sent data (ONLY default supported now) if (packet == 0) packet = dmpPacketBuffer; data[0] = ((packet[16] << 24) + (packet[17] << 16) + (packet[18] << 8) + packet[19]); @@ -639,7 +639,7 @@ uint8_t MPU6050::dmpGetGyro(int32_t *data, const uint8_t* packet) { data[2] = ((packet[24] << 24) + (packet[25] << 16) + (packet[26] << 8) + packet[27]); return 0; } -uint8_t MPU6050::dmpGetGyro(int16_t *data, const uint8_t* packet) { +uint8_t MPU9150::dmpGetGyro(int16_t *data, const uint8_t* packet) { // TODO: accommodate different arrangements of sent data (ONLY default supported now) if (packet == 0) packet = dmpPacketBuffer; data[0] = (packet[16] << 8) + packet[17]; @@ -647,46 +647,46 @@ uint8_t MPU6050::dmpGetGyro(int16_t *data, const uint8_t* packet) { data[2] = (packet[24] << 8) + packet[25]; return 0; } -// uint8_t MPU6050::dmpSetLinearAccelFilterCoefficient(float coef); -// uint8_t MPU6050::dmpGetLinearAccel(long *data, const uint8_t* packet); -uint8_t MPU6050::dmpGetLinearAccel(VectorInt16 *v, VectorInt16 *vRaw, VectorFloat *gravity) { +// uint8_t MPU9150::dmpSetLinearAccelFilterCoefficient(float coef); +// uint8_t MPU9150::dmpGetLinearAccel(long *data, const uint8_t* packet); +uint8_t MPU9150::dmpGetLinearAccel(VectorInt16 *v, VectorInt16 *vRaw, VectorFloat *gravity) { // get rid of the gravity component (+1g = +8192 in standard DMP FIFO packet, sensitivity is 2g) v -> x = vRaw -> x - gravity -> x*8192; v -> y = vRaw -> y - gravity -> y*8192; v -> z = vRaw -> z - gravity -> z*8192; return 0; } -// uint8_t MPU6050::dmpGetLinearAccelInWorld(long *data, const uint8_t* packet); -uint8_t MPU6050::dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Quaternion *q) { +// uint8_t MPU9150::dmpGetLinearAccelInWorld(long *data, const uint8_t* packet); +uint8_t MPU9150::dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Quaternion *q) { // rotate measured 3D acceleration vector into original state // frame of reference based on orientation quaternion memcpy(v, vReal, sizeof(VectorInt16)); v -> rotate(q); return 0; } -// uint8_t MPU6050::dmpGetGyroAndAccelSensor(long *data, const uint8_t* packet); -// uint8_t MPU6050::dmpGetGyroSensor(long *data, const uint8_t* packet); -// uint8_t MPU6050::dmpGetControlData(long *data, const uint8_t* packet); -// uint8_t MPU6050::dmpGetTemperature(long *data, const uint8_t* packet); -// uint8_t MPU6050::dmpGetGravity(long *data, const uint8_t* packet); -uint8_t MPU6050::dmpGetGravity(VectorFloat *v, Quaternion *q) { +// uint8_t MPU9150::dmpGetGyroAndAccelSensor(long *data, const uint8_t* packet); +// uint8_t MPU9150::dmpGetGyroSensor(long *data, const uint8_t* packet); +// uint8_t MPU9150::dmpGetControlData(long *data, const uint8_t* packet); +// uint8_t MPU9150::dmpGetTemperature(long *data, const uint8_t* packet); +// uint8_t MPU9150::dmpGetGravity(long *data, const uint8_t* packet); +uint8_t MPU9150::dmpGetGravity(VectorFloat *v, Quaternion *q) { v -> x = 2 * (q -> x*q -> z - q -> w*q -> y); v -> y = 2 * (q -> w*q -> x + q -> y*q -> z); v -> z = q -> w*q -> w - q -> x*q -> x - q -> y*q -> y + q -> z*q -> z; return 0; } -// uint8_t MPU6050::dmpGetUnquantizedAccel(long *data, const uint8_t* packet); -// uint8_t MPU6050::dmpGetQuantizedAccel(long *data, const uint8_t* packet); -// uint8_t MPU6050::dmpGetExternalSensorData(long *data, int size, const uint8_t* packet); -// uint8_t MPU6050::dmpGetEIS(long *data, const uint8_t* packet); +// uint8_t MPU9150::dmpGetUnquantizedAccel(long *data, const uint8_t* packet); +// uint8_t MPU9150::dmpGetQuantizedAccel(long *data, const uint8_t* packet); +// uint8_t MPU9150::dmpGetExternalSensorData(long *data, int size, const uint8_t* packet); +// uint8_t MPU9150::dmpGetEIS(long *data, const uint8_t* packet); -uint8_t MPU6050::dmpGetEuler(float *data, Quaternion *q) { +uint8_t MPU9150::dmpGetEuler(float *data, Quaternion *q) { data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1); // psi data[1] = -asin(2*q -> x*q -> z + 2*q -> w*q -> y); // theta data[2] = atan2(2*q -> y*q -> z - 2*q -> w*q -> x, 2*q -> w*q -> w + 2*q -> z*q -> z - 1); // phi return 0; } -uint8_t MPU6050::dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity) { +uint8_t MPU9150::dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity) { // yaw: (about Z axis) data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1); // pitch: (nose up/down, about Y axis) @@ -696,10 +696,10 @@ uint8_t MPU6050::dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gra return 0; } -// uint8_t MPU6050::dmpGetAccelFloat(float *data, const uint8_t* packet); -// uint8_t MPU6050::dmpGetQuaternionFloat(float *data, const uint8_t* packet); +// uint8_t MPU9150::dmpGetAccelFloat(float *data, const uint8_t* packet); +// uint8_t MPU9150::dmpGetQuaternionFloat(float *data, const uint8_t* packet); -uint8_t MPU6050::dmpProcessFIFOPacket(const unsigned char *dmpData) { +uint8_t MPU9150::dmpProcessFIFOPacket(const unsigned char *dmpData) { /*for (uint8_t k = 0; k < dmpPacketSize; k++) { if (dmpData[k] < 0x10) Serial.print("0"); Serial.print(dmpData[k], HEX); @@ -709,7 +709,7 @@ uint8_t MPU6050::dmpProcessFIFOPacket(const unsigned char *dmpData) { //Serial.println((uint16_t)dmpPacketBuffer); return 0; } -uint8_t MPU6050::dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *processed) { +uint8_t MPU9150::dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *processed) { uint8_t status; uint8_t buf[dmpPacketSize]; for (uint8_t i = 0; i < numPackets; i++) { @@ -725,17 +725,17 @@ uint8_t MPU6050::dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *proces return 0; } -// uint8_t MPU6050::dmpSetFIFOProcessedCallback(void (*func) (void)); +// uint8_t MPU9150::dmpSetFIFOProcessedCallback(void (*func) (void)); -// uint8_t MPU6050::dmpInitFIFOParam(); -// uint8_t MPU6050::dmpCloseFIFO(); -// uint8_t MPU6050::dmpSetGyroDataSource(uint_fast8_t source); -// uint8_t MPU6050::dmpDecodeQuantizedAccel(); -// uint32_t MPU6050::dmpGetGyroSumOfSquare(); -// uint32_t MPU6050::dmpGetAccelSumOfSquare(); -// void MPU6050::dmpOverrideQuaternion(long *q); -uint16_t MPU6050::dmpGetFIFOPacketSize() { +// uint8_t MPU9150::dmpInitFIFOParam(); +// uint8_t MPU9150::dmpCloseFIFO(); +// uint8_t MPU9150::dmpSetGyroDataSource(uint_fast8_t source); +// uint8_t MPU9150::dmpDecodeQuantizedAccel(); +// uint32_t MPU9150::dmpGetGyroSumOfSquare(); +// uint32_t MPU9150::dmpGetAccelSumOfSquare(); +// void MPU9150::dmpOverrideQuaternion(long *q); +uint16_t MPU9150::dmpGetFIFOPacketSize() { return dmpPacketSize; } -#endif /* _MPU6050_6AXIS_MOTIONAPPS20_H_ */ +#endif /* _MPU9150_6AXIS_MOTIONAPPS20_H_ */ diff --git a/Arduino/MPU9150/MPU9150_9Axis_MotionApps41.h b/Arduino/MPU9150/MPU9150_9Axis_MotionApps41.h index 14e280c0..37e36ff2 100644 --- a/Arduino/MPU9150/MPU9150_9Axis_MotionApps41.h +++ b/Arduino/MPU9150/MPU9150_9Axis_MotionApps41.h @@ -1,5 +1,5 @@ -// I2Cdev library collection - MPU6050 I2C device class, 9-axis MotionApps 4.1 implementation -// Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00) +// I2Cdev library collection - MPU9150 I2C device class, 9-axis MotionApps 4.1 implementation +// Based on InvenSense MPU-9150 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00) // 6/18/2012 by Jeff Rowberg // Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib // @@ -30,16 +30,16 @@ THE SOFTWARE. =============================================== */ -#ifndef _MPU6050_9AXIS_MOTIONAPPS41_H_ -#define _MPU6050_9AXIS_MOTIONAPPS41_H_ +#ifndef _MPU9150_9AXIS_MOTIONAPPS41_H_ +#define _MPU9150_9AXIS_MOTIONAPPS41_H_ #include "I2Cdev.h" #include "helper_3dmath.h" // MotionApps 4.1 DMP implementation, built using the MPU-9150 "MotionFit" board -#define MPU6050_INCLUDE_DMP_MOTIONAPPS41 +#define MPU9150_INCLUDE_DMP_MOTIONAPPS41 -#include "MPU6050.h" +#include "MPU9150.h" // Tom Carpenter's conditional PROGMEM code // http://forum.arduino.cc/index.php?topic=129407.0 @@ -104,9 +104,9 @@ THE SOFTWARE. #define DEBUG_PRINTLNF(x, y) #endif -#define MPU6050_DMP_CODE_SIZE 1962 // dmpMemory[] -#define MPU6050_DMP_CONFIG_SIZE 232 // dmpConfig[] -#define MPU6050_DMP_UPDATES_SIZE 140 // dmpUpdates[] +#define MPU9150_DMP_CODE_SIZE 1962 // dmpMemory[] +#define MPU9150_DMP_CONFIG_SIZE 232 // dmpConfig[] +#define MPU9150_DMP_UPDATES_SIZE 140 // dmpUpdates[] /* ================================================================================================ * | Default MotionApps v4.1 48-byte FIFO packet structure: | @@ -121,7 +121,7 @@ THE SOFTWARE. // this block of memory gets written to the MPU on start-up, and it seems // to be volatile memory, so it has to be done each time (it only takes ~1 // second though) -const prog_uchar dmpMemory[MPU6050_DMP_CODE_SIZE] PROGMEM = { +const prog_uchar dmpMemory[MPU9150_DMP_CODE_SIZE] PROGMEM = { // bank 0, 256 bytes 0xFB, 0x00, 0x00, 0x3E, 0x00, 0x0B, 0x00, 0x36, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, 0x00, 0x65, 0x00, 0x54, 0xFF, 0xEF, 0x00, 0x00, 0xFA, 0x80, 0x00, 0x0B, 0x12, 0x82, 0x00, 0x01, @@ -262,7 +262,7 @@ const prog_uchar dmpMemory[MPU6050_DMP_CODE_SIZE] PROGMEM = { 0xDC, 0xB9, 0xA7, 0xF1, 0x26, 0x26, 0x26, 0xD8, 0xD8, 0xFF }; -const prog_uchar dmpConfig[MPU6050_DMP_CONFIG_SIZE] PROGMEM = { +const prog_uchar dmpConfig[MPU9150_DMP_CONFIG_SIZE] PROGMEM = { // BANK OFFSET LENGTH [DATA] 0x02, 0xEC, 0x04, 0x00, 0x47, 0x7D, 0x1A, // ? 0x03, 0x82, 0x03, 0x4C, 0xCD, 0x6C, // FCFG_1 inv_set_gyro_calibration @@ -312,7 +312,7 @@ const prog_uchar dmpConfig[MPU6050_DMP_CONFIG_SIZE] PROGMEM = { // the FIFO output at the desired rate. Handling FIFO overflow cleanly is also a good idea. }; -const prog_uchar dmpUpdates[MPU6050_DMP_UPDATES_SIZE] PROGMEM = { +const prog_uchar dmpUpdates[MPU9150_DMP_UPDATES_SIZE] PROGMEM = { 0x01, 0xB2, 0x02, 0xFF, 0xF5, 0x01, 0x90, 0x04, 0x0A, 0x0D, 0x97, 0xC0, 0x00, 0xA3, 0x01, 0x00, @@ -334,9 +334,9 @@ const prog_uchar dmpUpdates[MPU6050_DMP_UPDATES_SIZE] PROGMEM = { 0x00, 0x60, 0x04, 0x00, 0x40, 0x00, 0x00 }; -uint8_t MPU6050::dmpInitialize() { +uint8_t MPU9150::dmpInitialize() { // reset device - DEBUG_PRINTLN(F("\n\nResetting MPU6050...")); + DEBUG_PRINTLN(F("\n\nResetting MPU9150...")); reset(); delay(30); // wait after reset @@ -380,10 +380,10 @@ uint8_t MPU6050::dmpInitialize() { DEBUG_PRINT(F("Z gyro offset = ")); DEBUG_PRINTLN(zgOffset); - I2Cdev::readByte(devAddr, MPU6050_RA_USER_CTRL, buffer); // ? + I2Cdev::readByte(devAddr, MPU9150_RA_USER_CTRL, buffer); // ? DEBUG_PRINTLN(F("Enabling interrupt latch, clear on any read, AUX bypass enabled")); - I2Cdev::writeByte(devAddr, MPU6050_RA_INT_PIN_CFG, 0x32); + I2Cdev::writeByte(devAddr, MPU9150_RA_INT_PIN_CFG, 0x32); // enable MPU AUX I2C bypass mode //DEBUG_PRINTLN(F("Enabling AUX I2C bypass mode...")); @@ -417,18 +417,18 @@ uint8_t MPU6050::dmpInitialize() { // load DMP code into memory banks DEBUG_PRINT(F("Writing DMP code to MPU memory banks (")); - DEBUG_PRINT(MPU6050_DMP_CODE_SIZE); + DEBUG_PRINT(MPU9150_DMP_CODE_SIZE); DEBUG_PRINTLN(F(" bytes)")); - if (writeProgMemoryBlock(dmpMemory, MPU6050_DMP_CODE_SIZE)) { + if (writeProgMemoryBlock(dmpMemory, MPU9150_DMP_CODE_SIZE)) { DEBUG_PRINTLN(F("Success! DMP code written and verified.")); DEBUG_PRINTLN(F("Configuring DMP and related settings...")); // write DMP configuration DEBUG_PRINT(F("Writing DMP configuration to MPU memory banks (")); - DEBUG_PRINT(MPU6050_DMP_CONFIG_SIZE); + DEBUG_PRINT(MPU9150_DMP_CONFIG_SIZE); DEBUG_PRINTLN(F(" bytes in config def)")); - if (writeProgDMPConfigurationSet(dmpConfig, MPU6050_DMP_CONFIG_SIZE)) { + if (writeProgDMPConfigurationSet(dmpConfig, MPU9150_DMP_CONFIG_SIZE)) { DEBUG_PRINTLN(F("Success! DMP configuration written and verified.")); DEBUG_PRINTLN(F("Setting DMP and FIFO_OFLOW interrupts enabled...")); @@ -438,16 +438,16 @@ uint8_t MPU6050::dmpInitialize() { setRate(4); // 1khz / (1 + 4) = 200 Hz DEBUG_PRINTLN(F("Setting clock source to Z Gyro...")); - setClockSource(MPU6050_CLOCK_PLL_ZGYRO); + setClockSource(MPU9150_CLOCK_PLL_ZGYRO); DEBUG_PRINTLN(F("Setting DLPF bandwidth to 42Hz...")); - setDLPFMode(MPU6050_DLPF_BW_42); + setDLPFMode(MPU9150_DLPF_BW_42); DEBUG_PRINTLN(F("Setting external frame sync to TEMP_OUT_L[0]...")); - setExternalFrameSync(MPU6050_EXT_SYNC_TEMP_OUT_L); + setExternalFrameSync(MPU9150_EXT_SYNC_TEMP_OUT_L); DEBUG_PRINTLN(F("Setting gyro sensitivity to +/- 2000 deg/sec...")); - setFullScaleGyroRange(MPU6050_GYRO_FS_2000); + setFullScaleGyroRange(MPU9150_GYRO_FS_2000); DEBUG_PRINTLN(F("Setting DMP configuration bytes (function unknown)...")); setDMPConfig1(0x03); @@ -496,10 +496,10 @@ uint8_t MPU6050::dmpInitialize() { writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); DEBUG_PRINTLN(F("Disabling all standby flags...")); - I2Cdev::writeByte(0x68, MPU6050_RA_PWR_MGMT_2, 0x00); + I2Cdev::writeByte(0x68, MPU9150_RA_PWR_MGMT_2, 0x00); DEBUG_PRINTLN(F("Setting accelerometer sensitivity to +/- 2g...")); - I2Cdev::writeByte(0x68, MPU6050_RA_ACCEL_CONFIG, 0x00); + I2Cdev::writeByte(0x68, MPU9150_RA_ACCEL_CONFIG, 0x00); DEBUG_PRINTLN(F("Setting motion detection threshold to 2...")); setMotionDetectionThreshold(2); @@ -519,35 +519,35 @@ uint8_t MPU6050::dmpInitialize() { // setup AK8975 (0x0E) as Slave 0 in read mode DEBUG_PRINTLN(F("Setting up AK8975 read slave 0...")); - I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV0_ADDR, 0x8E); - I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV0_REG, 0x01); - I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV0_CTRL, 0xDA); + I2Cdev::writeByte(0x68, MPU9150_RA_I2C_SLV0_ADDR, 0x8E); + I2Cdev::writeByte(0x68, MPU9150_RA_I2C_SLV0_REG, 0x01); + I2Cdev::writeByte(0x68, MPU9150_RA_I2C_SLV0_CTRL, 0xDA); // setup AK8975 (0x0E) as Slave 2 in write mode DEBUG_PRINTLN(F("Setting up AK8975 write slave 2...")); - I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV2_ADDR, 0x0E); - I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV2_REG, 0x0A); - I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV2_CTRL, 0x81); - I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV2_DO, 0x01); + I2Cdev::writeByte(0x68, MPU9150_RA_I2C_SLV2_ADDR, 0x0E); + I2Cdev::writeByte(0x68, MPU9150_RA_I2C_SLV2_REG, 0x0A); + I2Cdev::writeByte(0x68, MPU9150_RA_I2C_SLV2_CTRL, 0x81); + I2Cdev::writeByte(0x68, MPU9150_RA_I2C_SLV2_DO, 0x01); // setup I2C timing/delay control DEBUG_PRINTLN(F("Setting up slave access delay...")); - I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV4_CTRL, 0x18); - I2Cdev::writeByte(0x68, MPU6050_RA_I2C_MST_DELAY_CTRL, 0x05); + I2Cdev::writeByte(0x68, MPU9150_RA_I2C_SLV4_CTRL, 0x18); + I2Cdev::writeByte(0x68, MPU9150_RA_I2C_MST_DELAY_CTRL, 0x05); // enable interrupts DEBUG_PRINTLN(F("Enabling default interrupt behavior/no bypass...")); - I2Cdev::writeByte(0x68, MPU6050_RA_INT_PIN_CFG, 0x00); + I2Cdev::writeByte(0x68, MPU9150_RA_INT_PIN_CFG, 0x00); // enable I2C master mode and reset DMP/FIFO DEBUG_PRINTLN(F("Enabling I2C master mode...")); - I2Cdev::writeByte(0x68, MPU6050_RA_USER_CTRL, 0x20); + I2Cdev::writeByte(0x68, MPU9150_RA_USER_CTRL, 0x20); DEBUG_PRINTLN(F("Resetting FIFO...")); - I2Cdev::writeByte(0x68, MPU6050_RA_USER_CTRL, 0x24); + I2Cdev::writeByte(0x68, MPU9150_RA_USER_CTRL, 0x24); DEBUG_PRINTLN(F("Rewriting I2C master mode enabled because...I don't know")); - I2Cdev::writeByte(0x68, MPU6050_RA_USER_CTRL, 0x20); + I2Cdev::writeByte(0x68, MPU9150_RA_USER_CTRL, 0x20); DEBUG_PRINTLN(F("Enabling and resetting DMP/FIFO...")); - I2Cdev::writeByte(0x68, MPU6050_RA_USER_CTRL, 0xE8); + I2Cdev::writeByte(0x68, MPU9150_RA_USER_CTRL, 0xE8); DEBUG_PRINTLN(F("Writing final memory update 5/19 (function unknown)...")); for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); @@ -650,34 +650,34 @@ uint8_t MPU6050::dmpInitialize() { return 0; // success } -bool MPU6050::dmpPacketAvailable() { +bool MPU9150::dmpPacketAvailable() { return getFIFOCount() >= dmpGetFIFOPacketSize(); } -// uint8_t MPU6050::dmpSetFIFORate(uint8_t fifoRate); -// uint8_t MPU6050::dmpGetFIFORate(); -// uint8_t MPU6050::dmpGetSampleStepSizeMS(); -// uint8_t MPU6050::dmpGetSampleFrequency(); -// int32_t MPU6050::dmpDecodeTemperature(int8_t tempReg); - -//uint8_t MPU6050::dmpRegisterFIFORateProcess(inv_obj_func func, int16_t priority); -//uint8_t MPU6050::dmpUnregisterFIFORateProcess(inv_obj_func func); -//uint8_t MPU6050::dmpRunFIFORateProcesses(); - -// uint8_t MPU6050::dmpSendQuaternion(uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendGyro(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendAccel(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendLinearAccel(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendLinearAccelInWorld(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendControlData(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendSensorData(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendExternalSensorData(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendGravity(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendPacketNumber(uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendQuantizedAccel(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendEIS(uint_fast16_t elements, uint_fast16_t accuracy); - -uint8_t MPU6050::dmpGetAccel(int32_t *data, const uint8_t* packet) { +// uint8_t MPU9150::dmpSetFIFORate(uint8_t fifoRate); +// uint8_t MPU9150::dmpGetFIFORate(); +// uint8_t MPU9150::dmpGetSampleStepSizeMS(); +// uint8_t MPU9150::dmpGetSampleFrequency(); +// int32_t MPU9150::dmpDecodeTemperature(int8_t tempReg); + +//uint8_t MPU9150::dmpRegisterFIFORateProcess(inv_obj_func func, int16_t priority); +//uint8_t MPU9150::dmpUnregisterFIFORateProcess(inv_obj_func func); +//uint8_t MPU9150::dmpRunFIFORateProcesses(); + +// uint8_t MPU9150::dmpSendQuaternion(uint_fast16_t accuracy); +// uint8_t MPU9150::dmpSendGyro(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU9150::dmpSendAccel(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU9150::dmpSendLinearAccel(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU9150::dmpSendLinearAccelInWorld(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU9150::dmpSendControlData(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU9150::dmpSendSensorData(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU9150::dmpSendExternalSensorData(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU9150::dmpSendGravity(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU9150::dmpSendPacketNumber(uint_fast16_t accuracy); +// uint8_t MPU9150::dmpSendQuantizedAccel(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU9150::dmpSendEIS(uint_fast16_t elements, uint_fast16_t accuracy); + +uint8_t MPU9150::dmpGetAccel(int32_t *data, const uint8_t* packet) { // TODO: accommodate different arrangements of sent data (ONLY default supported now) if (packet == 0) packet = dmpPacketBuffer; data[0] = ((packet[34] << 24) + (packet[35] << 16) + (packet[36] << 8) + packet[37]); @@ -685,7 +685,7 @@ uint8_t MPU6050::dmpGetAccel(int32_t *data, const uint8_t* packet) { data[2] = ((packet[42] << 24) + (packet[43] << 16) + (packet[44] << 8) + packet[45]); return 0; } -uint8_t MPU6050::dmpGetAccel(int16_t *data, const uint8_t* packet) { +uint8_t MPU9150::dmpGetAccel(int16_t *data, const uint8_t* packet) { // TODO: accommodate different arrangements of sent data (ONLY default supported now) if (packet == 0) packet = dmpPacketBuffer; data[0] = (packet[34] << 8) + packet[35]; @@ -693,7 +693,7 @@ uint8_t MPU6050::dmpGetAccel(int16_t *data, const uint8_t* packet) { data[2] = (packet[42] << 8) + packet[43]; return 0; } -uint8_t MPU6050::dmpGetAccel(VectorInt16 *v, const uint8_t* packet) { +uint8_t MPU9150::dmpGetAccel(VectorInt16 *v, const uint8_t* packet) { // TODO: accommodate different arrangements of sent data (ONLY default supported now) if (packet == 0) packet = dmpPacketBuffer; v -> x = (packet[34] << 8) + packet[35]; @@ -701,7 +701,7 @@ uint8_t MPU6050::dmpGetAccel(VectorInt16 *v, const uint8_t* packet) { v -> z = (packet[42] << 8) + packet[43]; return 0; } -uint8_t MPU6050::dmpGetQuaternion(int32_t *data, const uint8_t* packet) { +uint8_t MPU9150::dmpGetQuaternion(int32_t *data, const uint8_t* packet) { // TODO: accommodate different arrangements of sent data (ONLY default supported now) if (packet == 0) packet = dmpPacketBuffer; data[0] = ((packet[0] << 24) + (packet[1] << 16) + (packet[2] << 8) + packet[3]); @@ -710,7 +710,7 @@ uint8_t MPU6050::dmpGetQuaternion(int32_t *data, const uint8_t* packet) { data[3] = ((packet[12] << 24) + (packet[13] << 16) + (packet[14] << 8) + packet[15]); return 0; } -uint8_t MPU6050::dmpGetQuaternion(int16_t *data, const uint8_t* packet) { +uint8_t MPU9150::dmpGetQuaternion(int16_t *data, const uint8_t* packet) { // TODO: accommodate different arrangements of sent data (ONLY default supported now) if (packet == 0) packet = dmpPacketBuffer; data[0] = ((packet[0] << 8) + packet[1]); @@ -719,7 +719,7 @@ uint8_t MPU6050::dmpGetQuaternion(int16_t *data, const uint8_t* packet) { data[3] = ((packet[12] << 8) + packet[13]); return 0; } -uint8_t MPU6050::dmpGetQuaternion(Quaternion *q, const uint8_t* packet) { +uint8_t MPU9150::dmpGetQuaternion(Quaternion *q, const uint8_t* packet) { // TODO: accommodate different arrangements of sent data (ONLY default supported now) int16_t qI[4]; uint8_t status = dmpGetQuaternion(qI, packet); @@ -732,9 +732,9 @@ uint8_t MPU6050::dmpGetQuaternion(Quaternion *q, const uint8_t* packet) { } return status; // int16 return value, indicates error if this line is reached } -// uint8_t MPU6050::dmpGet6AxisQuaternion(long *data, const uint8_t* packet); -// uint8_t MPU6050::dmpGetRelativeQuaternion(long *data, const uint8_t* packet); -uint8_t MPU6050::dmpGetGyro(int32_t *data, const uint8_t* packet) { +// uint8_t MPU9150::dmpGet6AxisQuaternion(long *data, const uint8_t* packet); +// uint8_t MPU9150::dmpGetRelativeQuaternion(long *data, const uint8_t* packet); +uint8_t MPU9150::dmpGetGyro(int32_t *data, const uint8_t* packet) { // TODO: accommodate different arrangements of sent data (ONLY default supported now) if (packet == 0) packet = dmpPacketBuffer; data[0] = ((packet[16] << 24) + (packet[17] << 16) + (packet[18] << 8) + packet[19]); @@ -742,7 +742,7 @@ uint8_t MPU6050::dmpGetGyro(int32_t *data, const uint8_t* packet) { data[2] = ((packet[24] << 24) + (packet[25] << 16) + (packet[26] << 8) + packet[27]); return 0; } -uint8_t MPU6050::dmpGetGyro(int16_t *data, const uint8_t* packet) { +uint8_t MPU9150::dmpGetGyro(int16_t *data, const uint8_t* packet) { // TODO: accommodate different arrangements of sent data (ONLY default supported now) if (packet == 0) packet = dmpPacketBuffer; data[0] = (packet[16] << 8) + packet[17]; @@ -750,7 +750,7 @@ uint8_t MPU6050::dmpGetGyro(int16_t *data, const uint8_t* packet) { data[2] = (packet[24] << 8) + packet[25]; return 0; } -uint8_t MPU6050::dmpGetMag(int16_t *data, const uint8_t* packet) { +uint8_t MPU9150::dmpGetMag(int16_t *data, const uint8_t* packet) { // TODO: accommodate different arrangements of sent data (ONLY default supported now) if (packet == 0) packet = dmpPacketBuffer; data[0] = (packet[28] << 8) + packet[29]; @@ -758,46 +758,46 @@ uint8_t MPU6050::dmpGetMag(int16_t *data, const uint8_t* packet) { data[2] = (packet[32] << 8) + packet[33]; return 0; } -// uint8_t MPU6050::dmpSetLinearAccelFilterCoefficient(float coef); -// uint8_t MPU6050::dmpGetLinearAccel(long *data, const uint8_t* packet); -uint8_t MPU6050::dmpGetLinearAccel(VectorInt16 *v, VectorInt16 *vRaw, VectorFloat *gravity) { +// uint8_t MPU9150::dmpSetLinearAccelFilterCoefficient(float coef); +// uint8_t MPU9150::dmpGetLinearAccel(long *data, const uint8_t* packet); +uint8_t MPU9150::dmpGetLinearAccel(VectorInt16 *v, VectorInt16 *vRaw, VectorFloat *gravity) { // get rid of the gravity component (+1g = +4096 in standard DMP FIFO packet) v -> x = vRaw -> x - gravity -> x*4096; v -> y = vRaw -> y - gravity -> y*4096; v -> z = vRaw -> z - gravity -> z*4096; return 0; } -// uint8_t MPU6050::dmpGetLinearAccelInWorld(long *data, const uint8_t* packet); -uint8_t MPU6050::dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Quaternion *q) { +// uint8_t MPU9150::dmpGetLinearAccelInWorld(long *data, const uint8_t* packet); +uint8_t MPU9150::dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Quaternion *q) { // rotate measured 3D acceleration vector into original state // frame of reference based on orientation quaternion memcpy(v, vReal, sizeof(VectorInt16)); v -> rotate(q); return 0; } -// uint8_t MPU6050::dmpGetGyroAndAccelSensor(long *data, const uint8_t* packet); -// uint8_t MPU6050::dmpGetGyroSensor(long *data, const uint8_t* packet); -// uint8_t MPU6050::dmpGetControlData(long *data, const uint8_t* packet); -// uint8_t MPU6050::dmpGetTemperature(long *data, const uint8_t* packet); -// uint8_t MPU6050::dmpGetGravity(long *data, const uint8_t* packet); -uint8_t MPU6050::dmpGetGravity(VectorFloat *v, Quaternion *q) { +// uint8_t MPU9150::dmpGetGyroAndAccelSensor(long *data, const uint8_t* packet); +// uint8_t MPU9150::dmpGetGyroSensor(long *data, const uint8_t* packet); +// uint8_t MPU9150::dmpGetControlData(long *data, const uint8_t* packet); +// uint8_t MPU9150::dmpGetTemperature(long *data, const uint8_t* packet); +// uint8_t MPU9150::dmpGetGravity(long *data, const uint8_t* packet); +uint8_t MPU9150::dmpGetGravity(VectorFloat *v, Quaternion *q) { v -> x = 2 * (q -> x*q -> z - q -> w*q -> y); v -> y = 2 * (q -> w*q -> x + q -> y*q -> z); v -> z = q -> w*q -> w - q -> x*q -> x - q -> y*q -> y + q -> z*q -> z; return 0; } -// uint8_t MPU6050::dmpGetUnquantizedAccel(long *data, const uint8_t* packet); -// uint8_t MPU6050::dmpGetQuantizedAccel(long *data, const uint8_t* packet); -// uint8_t MPU6050::dmpGetExternalSensorData(long *data, int size, const uint8_t* packet); -// uint8_t MPU6050::dmpGetEIS(long *data, const uint8_t* packet); +// uint8_t MPU9150::dmpGetUnquantizedAccel(long *data, const uint8_t* packet); +// uint8_t MPU9150::dmpGetQuantizedAccel(long *data, const uint8_t* packet); +// uint8_t MPU9150::dmpGetExternalSensorData(long *data, int size, const uint8_t* packet); +// uint8_t MPU9150::dmpGetEIS(long *data, const uint8_t* packet); -uint8_t MPU6050::dmpGetEuler(float *data, Quaternion *q) { +uint8_t MPU9150::dmpGetEuler(float *data, Quaternion *q) { data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1); // psi data[1] = -asin(2*q -> x*q -> z + 2*q -> w*q -> y); // theta data[2] = atan2(2*q -> y*q -> z - 2*q -> w*q -> x, 2*q -> w*q -> w + 2*q -> z*q -> z - 1); // phi return 0; } -uint8_t MPU6050::dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity) { +uint8_t MPU9150::dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity) { // yaw: (about Z axis) data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1); // pitch: (nose up/down, about Y axis) @@ -807,10 +807,10 @@ uint8_t MPU6050::dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gra return 0; } -// uint8_t MPU6050::dmpGetAccelFloat(float *data, const uint8_t* packet); -// uint8_t MPU6050::dmpGetQuaternionFloat(float *data, const uint8_t* packet); +// uint8_t MPU9150::dmpGetAccelFloat(float *data, const uint8_t* packet); +// uint8_t MPU9150::dmpGetQuaternionFloat(float *data, const uint8_t* packet); -uint8_t MPU6050::dmpProcessFIFOPacket(const unsigned char *dmpData) { +uint8_t MPU9150::dmpProcessFIFOPacket(const unsigned char *dmpData) { /*for (uint8_t k = 0; k < dmpPacketSize; k++) { if (dmpData[k] < 0x10) Serial.print("0"); Serial.print(dmpData[k], HEX); @@ -820,7 +820,7 @@ uint8_t MPU6050::dmpProcessFIFOPacket(const unsigned char *dmpData) { //Serial.println((uint16_t)dmpPacketBuffer); return 0; } -uint8_t MPU6050::dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *processed) { +uint8_t MPU9150::dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *processed) { uint8_t status; uint8_t buf[dmpPacketSize]; for (uint8_t i = 0; i < numPackets; i++) { @@ -836,17 +836,17 @@ uint8_t MPU6050::dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *proces return 0; } -// uint8_t MPU6050::dmpSetFIFOProcessedCallback(void (*func) (void)); +// uint8_t MPU9150::dmpSetFIFOProcessedCallback(void (*func) (void)); -// uint8_t MPU6050::dmpInitFIFOParam(); -// uint8_t MPU6050::dmpCloseFIFO(); -// uint8_t MPU6050::dmpSetGyroDataSource(uint_fast8_t source); -// uint8_t MPU6050::dmpDecodeQuantizedAccel(); -// uint32_t MPU6050::dmpGetGyroSumOfSquare(); -// uint32_t MPU6050::dmpGetAccelSumOfSquare(); -// void MPU6050::dmpOverrideQuaternion(long *q); -uint16_t MPU6050::dmpGetFIFOPacketSize() { +// uint8_t MPU9150::dmpInitFIFOParam(); +// uint8_t MPU9150::dmpCloseFIFO(); +// uint8_t MPU9150::dmpSetGyroDataSource(uint_fast8_t source); +// uint8_t MPU9150::dmpDecodeQuantizedAccel(); +// uint32_t MPU9150::dmpGetGyroSumOfSquare(); +// uint32_t MPU9150::dmpGetAccelSumOfSquare(); +// void MPU9150::dmpOverrideQuaternion(long *q); +uint16_t MPU9150::dmpGetFIFOPacketSize() { return dmpPacketSize; } -#endif /* _MPU6050_9AXIS_MOTIONAPPS41_H_ */ +#endif /* _MPU9150_9AXIS_MOTIONAPPS41_H_ */ diff --git a/Arduino/MPU9150/helper_3dmath.h b/Arduino/MPU9150/helper_3dmath.h index 9ed260ec..e2dca7ad 100644 --- a/Arduino/MPU9150/helper_3dmath.h +++ b/Arduino/MPU9150/helper_3dmath.h @@ -1,4 +1,4 @@ -// I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class, 3D math helper +// I2C device class (I2Cdev) demonstration Arduino sketch for MPU9150 class, 3D math helper // 6/5/2012 by Jeff Rowberg // Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib // From 06a63aaae3b477602a151498a6b25c052cd3bc40 Mon Sep 17 00:00:00 2001 From: Cedric Honnet Date: Fri, 14 Feb 2014 01:40:19 -0800 Subject: [PATCH 008/335] Remove 6 axis related files. --- .../Examples/MPU9150_DMP6/MPU9150_DMP6.ino | 372 --------- .../MPU9150_DMP6/Processing/MPUTeapot.pde | 247 ------ Arduino/MPU9150/MPU9150_6Axis_MotionApps20.h | 741 ------------------ 3 files changed, 1360 deletions(-) delete mode 100644 Arduino/MPU9150/Examples/MPU9150_DMP6/MPU9150_DMP6.ino delete mode 100644 Arduino/MPU9150/Examples/MPU9150_DMP6/Processing/MPUTeapot.pde delete mode 100644 Arduino/MPU9150/MPU9150_6Axis_MotionApps20.h diff --git a/Arduino/MPU9150/Examples/MPU9150_DMP6/MPU9150_DMP6.ino b/Arduino/MPU9150/Examples/MPU9150_DMP6/MPU9150_DMP6.ino deleted file mode 100644 index ba2b0f48..00000000 --- a/Arduino/MPU9150/Examples/MPU9150_DMP6/MPU9150_DMP6.ino +++ /dev/null @@ -1,372 +0,0 @@ -// I2C device class (I2Cdev) demonstration Arduino sketch for MPU9150 class using DMP (MotionApps v2.0) -// 6/21/2012 by Jeff Rowberg -// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib -// -// Changelog: -// 2013-05-08 - added seamless Fastwire support -// - added note about gyro calibration -// 2012-06-21 - added note about Arduino 1.0.1 + Leonardo compatibility error -// 2012-06-20 - improved FIFO overflow handling and simplified read process -// 2012-06-19 - completely rearranged DMP initialization code and simplification -// 2012-06-13 - pull gyro and accel data from FIFO packet instead of reading directly -// 2012-06-09 - fix broken FIFO read sequence and change interrupt detection to RISING -// 2012-06-05 - add gravity-compensated initial reference frame acceleration output -// - add 3D math helper file to DMP6 example sketch -// - add Euler output and Yaw/Pitch/Roll output formats -// 2012-06-04 - remove accel offset clearing for better results (thanks Sungon Lee) -// 2012-06-01 - fixed gyro sensitivity to be 2000 deg/sec instead of 250 -// 2012-05-30 - basic DMP initialization working - -/* ============================================ -I2Cdev device library code is placed under the MIT license -Copyright (c) 2012 Jeff Rowberg - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -=============================================== -*/ - -// I2Cdev and MPU9150 must be installed as libraries, or else the .cpp/.h files -// for both classes must be in the include path of your project -#include "I2Cdev.h" - -#include "MPU9150_6Axis_MotionApps20.h" -//#include "MPU9150.h" // not necessary if using MotionApps include file - -// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation -// is used in I2Cdev.h -#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE - #include "Wire.h" -#endif - -// class default I2C address is 0x68 -// specific I2C addresses may be passed as a parameter here -// AD0 low = 0x68 (default for SparkFun breakout and InvenSense evaluation board) -// AD0 high = 0x69 -MPU9150 mpu; -//MPU9150 mpu(0x69); // <-- use for AD0 high - -/* ========================================================================= - NOTE: In addition to connection 3.3v, GND, SDA, and SCL, this sketch - depends on the MPU-9150's INT pin being connected to the Arduino's - external interrupt #0 pin. On the Arduino Uno and Mega 2560, this is - digital I/O pin 2. - * ========================================================================= */ - -/* ========================================================================= - NOTE: Arduino v1.0.1 with the Leonardo board generates a compile error - when using Serial.write(buf, len). The Teapot output uses this method. - The solution requires a modification to the Arduino USBAPI.h file, which - is fortunately simple, but annoying. This will be fixed in the next IDE - release. For more info, see these links: - - http://arduino.cc/forum/index.php/topic,109987.0.html - http://code.google.com/p/arduino/issues/detail?id=958 - * ========================================================================= */ - - - -// uncomment "OUTPUT_READABLE_QUATERNION" if you want to see the actual -// quaternion components in a [w, x, y, z] format (not best for parsing -// on a remote host such as Processing or something though) -//#define OUTPUT_READABLE_QUATERNION - -// uncomment "OUTPUT_READABLE_EULER" if you want to see Euler angles -// (in degrees) calculated from the quaternions coming from the FIFO. -// Note that Euler angles suffer from gimbal lock (for more info, see -// http://en.wikipedia.org/wiki/Gimbal_lock) -//#define OUTPUT_READABLE_EULER - -// uncomment "OUTPUT_READABLE_YAWPITCHROLL" if you want to see the yaw/ -// pitch/roll angles (in degrees) calculated from the quaternions coming -// from the FIFO. Note this also requires gravity vector calculations. -// Also note that yaw/pitch/roll angles suffer from gimbal lock (for -// more info, see: http://en.wikipedia.org/wiki/Gimbal_lock) -#define OUTPUT_READABLE_YAWPITCHROLL - -// uncomment "OUTPUT_READABLE_REALACCEL" if you want to see acceleration -// components with gravity removed. This acceleration reference frame is -// not compensated for orientation, so +X is always +X according to the -// sensor, just without the effects of gravity. If you want acceleration -// compensated for orientation, us OUTPUT_READABLE_WORLDACCEL instead. -//#define OUTPUT_READABLE_REALACCEL - -// uncomment "OUTPUT_READABLE_WORLDACCEL" if you want to see acceleration -// components with gravity removed and adjusted for the world frame of -// reference (yaw is relative to initial orientation, since no magnetometer -// is present in this case). Could be quite handy in some cases. -//#define OUTPUT_READABLE_WORLDACCEL - -// uncomment "OUTPUT_TEAPOT" if you want output that matches the -// format used for the InvenSense teapot demo -//#define OUTPUT_TEAPOT - - - -#define LED_PIN 13 // (Arduino is 13, Teensy is 11, Teensy++ is 6) -bool blinkState = false; - -// MPU control/status vars -bool dmpReady = false; // set true if DMP init was successful -uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU -uint8_t devStatus; // return status after each device operation (0 = success, !0 = error) -uint16_t packetSize; // expected DMP packet size (default is 42 bytes) -uint16_t fifoCount; // count of all bytes currently in FIFO -uint8_t fifoBuffer[64]; // FIFO storage buffer - -// orientation/motion vars -Quaternion q; // [w, x, y, z] quaternion container -VectorInt16 aa; // [x, y, z] accel sensor measurements -VectorInt16 aaReal; // [x, y, z] gravity-free accel sensor measurements -VectorInt16 aaWorld; // [x, y, z] world-frame accel sensor measurements -VectorFloat gravity; // [x, y, z] gravity vector -float euler[3]; // [psi, theta, phi] Euler angle container -float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector - -// packet structure for InvenSense teapot demo -uint8_t teapotPacket[14] = { '$', 0x02, 0,0, 0,0, 0,0, 0,0, 0x00, 0x00, '\r', '\n' }; - - - -// ================================================================ -// === INTERRUPT DETECTION ROUTINE === -// ================================================================ - -volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high -void dmpDataReady() { - mpuInterrupt = true; -} - - - -// ================================================================ -// === INITIAL SETUP === -// ================================================================ - -void setup() { - // join I2C bus (I2Cdev library doesn't do this automatically) - #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE - Wire.begin(); - TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz) - #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE - Fastwire::setup(400, true); - #endif - - // initialize serial communication - // (115200 chosen because it is required for Teapot Demo output, but it's - // really up to you depending on your project) - Serial.begin(115200); - while (!Serial); // wait for Leonardo enumeration, others continue immediately - - // NOTE: 8MHz or slower host processors, like the Teensy @ 3.3v or Ardunio - // Pro Mini running at 3.3v, cannot handle this baud rate reliably due to - // the baud timing being too misaligned with processor ticks. You must use - // 38400 or slower in these cases, or use some kind of external separate - // crystal solution for the UART timer. - - // initialize device - Serial.println(F("Initializing I2C devices...")); - mpu.initialize(); - - // verify connection - Serial.println(F("Testing device connections...")); - Serial.println(mpu.testConnection() ? F("MPU9150 connection successful") : F("MPU9150 connection failed")); - - // wait for ready - Serial.println(F("\nSend any character to begin DMP programming and demo: ")); - while (Serial.available() && Serial.read()); // empty buffer - while (!Serial.available()); // wait for data - while (Serial.available() && Serial.read()); // empty buffer again - - // load and configure the DMP - Serial.println(F("Initializing DMP...")); - devStatus = mpu.dmpInitialize(); - - // supply your own gyro offsets here, scaled for min sensitivity - mpu.setXGyroOffset(220); - mpu.setYGyroOffset(76); - mpu.setZGyroOffset(-85); - mpu.setZAccelOffset(1788); // 1688 factory default for my test chip - - // make sure it worked (returns 0 if so) - if (devStatus == 0) { - // turn on the DMP, now that it's ready - Serial.println(F("Enabling DMP...")); - mpu.setDMPEnabled(true); - - // enable Arduino interrupt detection - Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)...")); - attachInterrupt(0, dmpDataReady, RISING); - mpuIntStatus = mpu.getIntStatus(); - - // set our DMP Ready flag so the main loop() function knows it's okay to use it - Serial.println(F("DMP ready! Waiting for first interrupt...")); - dmpReady = true; - - // get expected DMP packet size for later comparison - packetSize = mpu.dmpGetFIFOPacketSize(); - } else { - // ERROR! - // 1 = initial memory load failed - // 2 = DMP configuration updates failed - // (if it's going to break, usually the code will be 1) - Serial.print(F("DMP Initialization failed (code ")); - Serial.print(devStatus); - Serial.println(F(")")); - } - - // configure LED for output - pinMode(LED_PIN, OUTPUT); -} - - - -// ================================================================ -// === MAIN PROGRAM LOOP === -// ================================================================ - -void loop() { - // if programming failed, don't try to do anything - if (!dmpReady) return; - - // wait for MPU interrupt or extra packet(s) available - while (!mpuInterrupt && fifoCount < packetSize) { - // other program behavior stuff here - // . - // . - // . - // if you are really paranoid you can frequently test in between other - // stuff to see if mpuInterrupt is true, and if so, "break;" from the - // while() loop to immediately process the MPU data - // . - // . - // . - } - - // reset interrupt flag and get INT_STATUS byte - mpuInterrupt = false; - mpuIntStatus = mpu.getIntStatus(); - - // get current FIFO count - fifoCount = mpu.getFIFOCount(); - - // check for overflow (this should never happen unless our code is too inefficient) - if ((mpuIntStatus & 0x10) || fifoCount == 1024) { - // reset so we can continue cleanly - mpu.resetFIFO(); - Serial.println(F("FIFO overflow!")); - - // otherwise, check for DMP data ready interrupt (this should happen frequently) - } else if (mpuIntStatus & 0x02) { - // wait for correct available data length, should be a VERY short wait - while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount(); - - // read a packet from FIFO - mpu.getFIFOBytes(fifoBuffer, packetSize); - - // track FIFO count here in case there is > 1 packet available - // (this lets us immediately read more without waiting for an interrupt) - fifoCount -= packetSize; - - #ifdef OUTPUT_READABLE_QUATERNION - // display quaternion values in easy matrix form: w x y z - mpu.dmpGetQuaternion(&q, fifoBuffer); - Serial.print("quat\t"); - Serial.print(q.w); - Serial.print("\t"); - Serial.print(q.x); - Serial.print("\t"); - Serial.print(q.y); - Serial.print("\t"); - Serial.println(q.z); - #endif - - #ifdef OUTPUT_READABLE_EULER - // display Euler angles in degrees - mpu.dmpGetQuaternion(&q, fifoBuffer); - mpu.dmpGetEuler(euler, &q); - Serial.print("euler\t"); - Serial.print(euler[0] * 180/M_PI); - Serial.print("\t"); - Serial.print(euler[1] * 180/M_PI); - Serial.print("\t"); - Serial.println(euler[2] * 180/M_PI); - #endif - - #ifdef OUTPUT_READABLE_YAWPITCHROLL - // display Euler angles in degrees - mpu.dmpGetQuaternion(&q, fifoBuffer); - mpu.dmpGetGravity(&gravity, &q); - mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); - Serial.print("ypr\t"); - Serial.print(ypr[0] * 180/M_PI); - Serial.print("\t"); - Serial.print(ypr[1] * 180/M_PI); - Serial.print("\t"); - Serial.println(ypr[2] * 180/M_PI); - #endif - - #ifdef OUTPUT_READABLE_REALACCEL - // display real acceleration, adjusted to remove gravity - mpu.dmpGetQuaternion(&q, fifoBuffer); - mpu.dmpGetAccel(&aa, fifoBuffer); - mpu.dmpGetGravity(&gravity, &q); - mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity); - Serial.print("areal\t"); - Serial.print(aaReal.x); - Serial.print("\t"); - Serial.print(aaReal.y); - Serial.print("\t"); - Serial.println(aaReal.z); - #endif - - #ifdef OUTPUT_READABLE_WORLDACCEL - // display initial world-frame acceleration, adjusted to remove gravity - // and rotated based on known orientation from quaternion - mpu.dmpGetQuaternion(&q, fifoBuffer); - mpu.dmpGetAccel(&aa, fifoBuffer); - mpu.dmpGetGravity(&gravity, &q); - mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity); - mpu.dmpGetLinearAccelInWorld(&aaWorld, &aaReal, &q); - Serial.print("aworld\t"); - Serial.print(aaWorld.x); - Serial.print("\t"); - Serial.print(aaWorld.y); - Serial.print("\t"); - Serial.println(aaWorld.z); - #endif - - #ifdef OUTPUT_TEAPOT - // display quaternion values in InvenSense Teapot demo format: - teapotPacket[2] = fifoBuffer[0]; - teapotPacket[3] = fifoBuffer[1]; - teapotPacket[4] = fifoBuffer[4]; - teapotPacket[5] = fifoBuffer[5]; - teapotPacket[6] = fifoBuffer[8]; - teapotPacket[7] = fifoBuffer[9]; - teapotPacket[8] = fifoBuffer[12]; - teapotPacket[9] = fifoBuffer[13]; - Serial.write(teapotPacket, 14); - teapotPacket[11]++; // packetCount, loops at 0xFF on purpose - #endif - - // blink LED to indicate activity - blinkState = !blinkState; - digitalWrite(LED_PIN, blinkState); - } -} diff --git a/Arduino/MPU9150/Examples/MPU9150_DMP6/Processing/MPUTeapot.pde b/Arduino/MPU9150/Examples/MPU9150_DMP6/Processing/MPUTeapot.pde deleted file mode 100644 index ed510f9b..00000000 --- a/Arduino/MPU9150/Examples/MPU9150_DMP6/Processing/MPUTeapot.pde +++ /dev/null @@ -1,247 +0,0 @@ -// I2C device class (I2Cdev) demonstration Processing sketch for MPU9150 DMP output -// 6/20/2012 by Jeff Rowberg -// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib -// -// Changelog: -// 2012-06-20 - initial release - -/* ============================================ -I2Cdev device library code is placed under the MIT license -Copyright (c) 2012 Jeff Rowberg - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -=============================================== -*/ - -import processing.serial.*; -import processing.opengl.*; -import toxi.geom.*; -import toxi.processing.*; - -// NOTE: requires ToxicLibs to be installed in order to run properly. -// 1. Download from http://toxiclibs.org/downloads -// 2. Extract into [userdir]/Processing/libraries -// (location may be different on Mac/Linux) -// 3. Run and bask in awesomeness - -ToxiclibsSupport gfx; - -Serial port; // The serial port -char[] teapotPacket = new char[14]; // InvenSense Teapot packet -int serialCount = 0; // current packet byte position -int aligned = 0; -int interval = 0; - -float[] q = new float[4]; -Quaternion quat = new Quaternion(1, 0, 0, 0); - -float[] gravity = new float[3]; -float[] euler = new float[3]; -float[] ypr = new float[3]; - -void setup() { - // 300px square viewport using OpenGL rendering - size(300, 300, OPENGL); - gfx = new ToxiclibsSupport(this); - - // setup lights and antialiasing - lights(); - smooth(); - - // display serial port list for debugging/clarity - println(Serial.list()); - - // get the first available port (use EITHER this OR the specific port code below) - String portName = Serial.list()[0]; - - // get a specific serial port (use EITHER this OR the first-available code above) - //String portName = "COM4"; - - // open the serial port - port = new Serial(this, portName, 115200); - - // send single character to trigger DMP init/start - // (expected by MPU9150_DMP6 example Arduino sketch) - port.write('r'); -} - -void draw() { - if (millis() - interval > 1000) { - // resend single character to trigger DMP init/start - // in case the MPU is halted/reset while applet is running - port.write('r'); - interval = millis(); - } - - // black background - background(0); - - // translate everything to the middle of the viewport - pushMatrix(); - translate(width / 2, height / 2); - - // 3-step rotation from yaw/pitch/roll angles (gimbal lock!) - // ...and other weirdness I haven't figured out yet - //rotateY(-ypr[0]); - //rotateZ(-ypr[1]); - //rotateX(-ypr[2]); - - // toxiclibs direct angle/axis rotation from quaternion (NO gimbal lock!) - // (axis order [1, 3, 2] and inversion [-1, +1, +1] is a consequence of - // different coordinate system orientation assumptions between Processing - // and InvenSense DMP) - float[] axis = quat.toAxisAngle(); - rotate(axis[0], -axis[1], axis[3], axis[2]); - - // draw main body in red - fill(255, 0, 0, 200); - box(10, 10, 200); - - // draw front-facing tip in blue - fill(0, 0, 255, 200); - pushMatrix(); - translate(0, 0, -120); - rotateX(PI/2); - drawCylinder(0, 20, 20, 8); - popMatrix(); - - // draw wings and tail fin in green - fill(0, 255, 0, 200); - beginShape(TRIANGLES); - vertex(-100, 2, 30); vertex(0, 2, -80); vertex(100, 2, 30); // wing top layer - vertex(-100, -2, 30); vertex(0, -2, -80); vertex(100, -2, 30); // wing bottom layer - vertex(-2, 0, 98); vertex(-2, -30, 98); vertex(-2, 0, 70); // tail left layer - vertex( 2, 0, 98); vertex( 2, -30, 98); vertex( 2, 0, 70); // tail right layer - endShape(); - beginShape(QUADS); - vertex(-100, 2, 30); vertex(-100, -2, 30); vertex( 0, -2, -80); vertex( 0, 2, -80); - vertex( 100, 2, 30); vertex( 100, -2, 30); vertex( 0, -2, -80); vertex( 0, 2, -80); - vertex(-100, 2, 30); vertex(-100, -2, 30); vertex(100, -2, 30); vertex(100, 2, 30); - vertex(-2, 0, 98); vertex(2, 0, 98); vertex(2, -30, 98); vertex(-2, -30, 98); - vertex(-2, 0, 98); vertex(2, 0, 98); vertex(2, 0, 70); vertex(-2, 0, 70); - vertex(-2, -30, 98); vertex(2, -30, 98); vertex(2, 0, 70); vertex(-2, 0, 70); - endShape(); - - popMatrix(); -} - -void serialEvent(Serial port) { - interval = millis(); - while (port.available() > 0) { - int ch = port.read(); - print((char)ch); - if (ch == '$') {serialCount = 0;} // this will help with alignment - if (aligned < 4) { - // make sure we are properly aligned on a 14-byte packet - if (serialCount == 0) { - if (ch == '$') aligned++; else aligned = 0; - } else if (serialCount == 1) { - if (ch == 2) aligned++; else aligned = 0; - } else if (serialCount == 12) { - if (ch == '\r') aligned++; else aligned = 0; - } else if (serialCount == 13) { - if (ch == '\n') aligned++; else aligned = 0; - } - //println(ch + " " + aligned + " " + serialCount); - serialCount++; - if (serialCount == 14) serialCount = 0; - } else { - if (serialCount > 0 || ch == '$') { - teapotPacket[serialCount++] = (char)ch; - if (serialCount == 14) { - serialCount = 0; // restart packet byte position - - // get quaternion from data packet - q[0] = ((teapotPacket[2] << 8) | teapotPacket[3]) / 16384.0f; - q[1] = ((teapotPacket[4] << 8) | teapotPacket[5]) / 16384.0f; - q[2] = ((teapotPacket[6] << 8) | teapotPacket[7]) / 16384.0f; - q[3] = ((teapotPacket[8] << 8) | teapotPacket[9]) / 16384.0f; - for (int i = 0; i < 4; i++) if (q[i] >= 2) q[i] = -4 + q[i]; - - // set our toxilibs quaternion to new data - quat.set(q[0], q[1], q[2], q[3]); - - /* - // below calculations unnecessary for orientation only using toxilibs - - // calculate gravity vector - gravity[0] = 2 * (q[1]*q[3] - q[0]*q[2]); - gravity[1] = 2 * (q[0]*q[1] + q[2]*q[3]); - gravity[2] = q[0]*q[0] - q[1]*q[1] - q[2]*q[2] + q[3]*q[3]; - - // calculate Euler angles - euler[0] = atan2(2*q[1]*q[2] - 2*q[0]*q[3], 2*q[0]*q[0] + 2*q[1]*q[1] - 1); - euler[1] = -asin(2*q[1]*q[3] + 2*q[0]*q[2]); - euler[2] = atan2(2*q[2]*q[3] - 2*q[0]*q[1], 2*q[0]*q[0] + 2*q[3]*q[3] - 1); - - // calculate yaw/pitch/roll angles - ypr[0] = atan2(2*q[1]*q[2] - 2*q[0]*q[3], 2*q[0]*q[0] + 2*q[1]*q[1] - 1); - ypr[1] = atan(gravity[0] / sqrt(gravity[1]*gravity[1] + gravity[2]*gravity[2])); - ypr[2] = atan(gravity[1] / sqrt(gravity[0]*gravity[0] + gravity[2]*gravity[2])); - - // output various components for debugging - //println("q:\t" + round(q[0]*100.0f)/100.0f + "\t" + round(q[1]*100.0f)/100.0f + "\t" + round(q[2]*100.0f)/100.0f + "\t" + round(q[3]*100.0f)/100.0f); - //println("euler:\t" + euler[0]*180.0f/PI + "\t" + euler[1]*180.0f/PI + "\t" + euler[2]*180.0f/PI); - //println("ypr:\t" + ypr[0]*180.0f/PI + "\t" + ypr[1]*180.0f/PI + "\t" + ypr[2]*180.0f/PI); - */ - } - } - } - } -} - -void drawCylinder(float topRadius, float bottomRadius, float tall, int sides) { - float angle = 0; - float angleIncrement = TWO_PI / sides; - beginShape(QUAD_STRIP); - for (int i = 0; i < sides + 1; ++i) { - vertex(topRadius*cos(angle), 0, topRadius*sin(angle)); - vertex(bottomRadius*cos(angle), tall, bottomRadius*sin(angle)); - angle += angleIncrement; - } - endShape(); - - // If it is not a cone, draw the circular top cap - if (topRadius != 0) { - angle = 0; - beginShape(TRIANGLE_FAN); - - // Center point - vertex(0, 0, 0); - for (int i = 0; i < sides + 1; i++) { - vertex(topRadius * cos(angle), 0, topRadius * sin(angle)); - angle += angleIncrement; - } - endShape(); - } - - // If it is not a cone, draw the circular bottom cap - if (bottomRadius != 0) { - angle = 0; - beginShape(TRIANGLE_FAN); - - // Center point - vertex(0, tall, 0); - for (int i = 0; i < sides + 1; i++) { - vertex(bottomRadius * cos(angle), tall, bottomRadius * sin(angle)); - angle += angleIncrement; - } - endShape(); - } -} diff --git a/Arduino/MPU9150/MPU9150_6Axis_MotionApps20.h b/Arduino/MPU9150/MPU9150_6Axis_MotionApps20.h deleted file mode 100644 index 8cff9114..00000000 --- a/Arduino/MPU9150/MPU9150_6Axis_MotionApps20.h +++ /dev/null @@ -1,741 +0,0 @@ -// I2Cdev library collection - MPU9150 I2C device class, 6-axis MotionApps 2.0 implementation -// Based on InvenSense MPU-9150 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00) -// 5/20/2013 by Jeff Rowberg -// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib -// -// Changelog: -// ... - ongoing debug release - -/* ============================================ -I2Cdev device library code is placed under the MIT license -Copyright (c) 2012 Jeff Rowberg - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -=============================================== -*/ - -#ifndef _MPU9150_6AXIS_MOTIONAPPS20_H_ -#define _MPU9150_6AXIS_MOTIONAPPS20_H_ - -#include "I2Cdev.h" -#include "helper_3dmath.h" - -// MotionApps 2.0 DMP implementation, built using the MPU-9150EVB evaluation board -#define MPU9150_INCLUDE_DMP_MOTIONAPPS20 - -#include "MPU9150.h" - -// Tom Carpenter's conditional PROGMEM code -// http://forum.arduino.cc/index.php?topic=129407.0 -#ifndef __arm__ - #include -#else - // Teensy 3.0 library conditional PROGMEM code from Paul Stoffregen - #ifndef __PGMSPACE_H_ - #define __PGMSPACE_H_ 1 - #include - - #define PROGMEM - #define PGM_P const char * - #define PSTR(str) (str) - #define F(x) x - - typedef void prog_void; - typedef char prog_char; - typedef unsigned char prog_uchar; - typedef int8_t prog_int8_t; - typedef uint8_t prog_uint8_t; - typedef int16_t prog_int16_t; - typedef uint16_t prog_uint16_t; - typedef int32_t prog_int32_t; - typedef uint32_t prog_uint32_t; - - #define strcpy_P(dest, src) strcpy((dest), (src)) - #define strcat_P(dest, src) strcat((dest), (src)) - #define strcmp_P(a, b) strcmp((a), (b)) - - #define pgm_read_byte(addr) (*(const unsigned char *)(addr)) - #define pgm_read_word(addr) (*(const unsigned short *)(addr)) - #define pgm_read_dword(addr) (*(const unsigned long *)(addr)) - #define pgm_read_float(addr) (*(const float *)(addr)) - - #define pgm_read_byte_near(addr) pgm_read_byte(addr) - #define pgm_read_word_near(addr) pgm_read_word(addr) - #define pgm_read_dword_near(addr) pgm_read_dword(addr) - #define pgm_read_float_near(addr) pgm_read_float(addr) - #define pgm_read_byte_far(addr) pgm_read_byte(addr) - #define pgm_read_word_far(addr) pgm_read_word(addr) - #define pgm_read_dword_far(addr) pgm_read_dword(addr) - #define pgm_read_float_far(addr) pgm_read_float(addr) - #endif -#endif - -/* Source is from the InvenSense MotionApps v2 demo code. Original source is - * unavailable, unless you happen to be amazing as decompiling binary by - * hand (in which case, please contact me, and I'm totally serious). - * - * Also, I'd like to offer many, many thanks to Noah Zerkin for all of the - * DMP reverse-engineering he did to help make this bit of wizardry - * possible. - */ - -// NOTE! Enabling DEBUG adds about 3.3kB to the flash program size. -// Debug output is now working even on ATMega328P MCUs (e.g. Arduino Uno) -// after moving string constants to flash memory storage using the F() -// compiler macro (Arduino IDE 1.0+ required). - -//#define DEBUG -#ifdef DEBUG - #define DEBUG_PRINT(x) Serial.print(x) - #define DEBUG_PRINTF(x, y) Serial.print(x, y) - #define DEBUG_PRINTLN(x) Serial.println(x) - #define DEBUG_PRINTLNF(x, y) Serial.println(x, y) -#else - #define DEBUG_PRINT(x) - #define DEBUG_PRINTF(x, y) - #define DEBUG_PRINTLN(x) - #define DEBUG_PRINTLNF(x, y) -#endif - -#define MPU9150_DMP_CODE_SIZE 1929 // dmpMemory[] -#define MPU9150_DMP_CONFIG_SIZE 192 // dmpConfig[] -#define MPU9150_DMP_UPDATES_SIZE 47 // dmpUpdates[] - -/* ================================================================================================ * - | Default MotionApps v2.0 42-byte FIFO packet structure: | - | | - | [QUAT W][ ][QUAT X][ ][QUAT Y][ ][QUAT Z][ ][GYRO X][ ][GYRO Y][ ] | - | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | - | | - | [GYRO Z][ ][ACC X ][ ][ACC Y ][ ][ACC Z ][ ][ ] | - | 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | - * ================================================================================================ */ - -// this block of memory gets written to the MPU on start-up, and it seems -// to be volatile memory, so it has to be done each time (it only takes ~1 -// second though) -const unsigned char dmpMemory[MPU9150_DMP_CODE_SIZE] PROGMEM = { - // bank 0, 256 bytes - 0xFB, 0x00, 0x00, 0x3E, 0x00, 0x0B, 0x00, 0x36, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, - 0x00, 0x65, 0x00, 0x54, 0xFF, 0xEF, 0x00, 0x00, 0xFA, 0x80, 0x00, 0x0B, 0x12, 0x82, 0x00, 0x01, - 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x28, 0x00, 0x00, 0xFF, 0xFF, 0x45, 0x81, 0xFF, 0xFF, 0xFA, 0x72, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x03, 0xE8, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x7F, 0xFF, 0xFF, 0xFE, 0x80, 0x01, - 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x3E, 0x03, 0x30, 0x40, 0x00, 0x00, 0x00, 0x02, 0xCA, 0xE3, 0x09, 0x3E, 0x80, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, - 0x41, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x2A, 0x00, 0x00, 0x16, 0x55, 0x00, 0x00, 0x21, 0x82, - 0xFD, 0x87, 0x26, 0x50, 0xFD, 0x80, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x05, 0x80, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x6F, 0x00, 0x02, 0x65, 0x32, 0x00, 0x00, 0x5E, 0xC0, - 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFB, 0x8C, 0x6F, 0x5D, 0xFD, 0x5D, 0x08, 0xD9, 0x00, 0x7C, 0x73, 0x3B, 0x00, 0x6C, 0x12, 0xCC, - 0x32, 0x00, 0x13, 0x9D, 0x32, 0x00, 0xD0, 0xD6, 0x32, 0x00, 0x08, 0x00, 0x40, 0x00, 0x01, 0xF4, - 0xFF, 0xE6, 0x80, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0xD6, 0x00, 0x00, 0x27, 0x10, - - // bank 1, 256 bytes - 0xFB, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xFA, 0x36, 0xFF, 0xBC, 0x30, 0x8E, 0x00, 0x05, 0xFB, 0xF0, 0xFF, 0xD9, 0x5B, 0xC8, - 0xFF, 0xD0, 0x9A, 0xBE, 0x00, 0x00, 0x10, 0xA9, 0xFF, 0xF4, 0x1E, 0xB2, 0x00, 0xCE, 0xBB, 0xF7, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x0C, - 0xFF, 0xC2, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0xCF, 0x80, 0x00, 0x40, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x14, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x3F, 0x68, 0xB6, 0x79, 0x35, 0x28, 0xBC, 0xC6, 0x7E, 0xD1, 0x6C, - 0x80, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB2, 0x6A, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x25, 0x4D, 0x00, 0x2F, 0x70, 0x6D, 0x00, 0x00, 0x05, 0xAE, 0x00, 0x0C, 0x02, 0xD0, - - // bank 2, 256 bytes - 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x54, 0xFF, 0xEF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0xFF, 0xEF, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, - 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - - // bank 3, 256 bytes - 0xD8, 0xDC, 0xBA, 0xA2, 0xF1, 0xDE, 0xB2, 0xB8, 0xB4, 0xA8, 0x81, 0x91, 0xF7, 0x4A, 0x90, 0x7F, - 0x91, 0x6A, 0xF3, 0xF9, 0xDB, 0xA8, 0xF9, 0xB0, 0xBA, 0xA0, 0x80, 0xF2, 0xCE, 0x81, 0xF3, 0xC2, - 0xF1, 0xC1, 0xF2, 0xC3, 0xF3, 0xCC, 0xA2, 0xB2, 0x80, 0xF1, 0xC6, 0xD8, 0x80, 0xBA, 0xA7, 0xDF, - 0xDF, 0xDF, 0xF2, 0xA7, 0xC3, 0xCB, 0xC5, 0xB6, 0xF0, 0x87, 0xA2, 0x94, 0x24, 0x48, 0x70, 0x3C, - 0x95, 0x40, 0x68, 0x34, 0x58, 0x9B, 0x78, 0xA2, 0xF1, 0x83, 0x92, 0x2D, 0x55, 0x7D, 0xD8, 0xB1, - 0xB4, 0xB8, 0xA1, 0xD0, 0x91, 0x80, 0xF2, 0x70, 0xF3, 0x70, 0xF2, 0x7C, 0x80, 0xA8, 0xF1, 0x01, - 0xB0, 0x98, 0x87, 0xD9, 0x43, 0xD8, 0x86, 0xC9, 0x88, 0xBA, 0xA1, 0xF2, 0x0E, 0xB8, 0x97, 0x80, - 0xF1, 0xA9, 0xDF, 0xDF, 0xDF, 0xAA, 0xDF, 0xDF, 0xDF, 0xF2, 0xAA, 0xC5, 0xCD, 0xC7, 0xA9, 0x0C, - 0xC9, 0x2C, 0x97, 0x97, 0x97, 0x97, 0xF1, 0xA9, 0x89, 0x26, 0x46, 0x66, 0xB0, 0xB4, 0xBA, 0x80, - 0xAC, 0xDE, 0xF2, 0xCA, 0xF1, 0xB2, 0x8C, 0x02, 0xA9, 0xB6, 0x98, 0x00, 0x89, 0x0E, 0x16, 0x1E, - 0xB8, 0xA9, 0xB4, 0x99, 0x2C, 0x54, 0x7C, 0xB0, 0x8A, 0xA8, 0x96, 0x36, 0x56, 0x76, 0xF1, 0xB9, - 0xAF, 0xB4, 0xB0, 0x83, 0xC0, 0xB8, 0xA8, 0x97, 0x11, 0xB1, 0x8F, 0x98, 0xB9, 0xAF, 0xF0, 0x24, - 0x08, 0x44, 0x10, 0x64, 0x18, 0xF1, 0xA3, 0x29, 0x55, 0x7D, 0xAF, 0x83, 0xB5, 0x93, 0xAF, 0xF0, - 0x00, 0x28, 0x50, 0xF1, 0xA3, 0x86, 0x9F, 0x61, 0xA6, 0xDA, 0xDE, 0xDF, 0xD9, 0xFA, 0xA3, 0x86, - 0x96, 0xDB, 0x31, 0xA6, 0xD9, 0xF8, 0xDF, 0xBA, 0xA6, 0x8F, 0xC2, 0xC5, 0xC7, 0xB2, 0x8C, 0xC1, - 0xB8, 0xA2, 0xDF, 0xDF, 0xDF, 0xA3, 0xDF, 0xDF, 0xDF, 0xD8, 0xD8, 0xF1, 0xB8, 0xA8, 0xB2, 0x86, - - // bank 4, 256 bytes - 0xB4, 0x98, 0x0D, 0x35, 0x5D, 0xB8, 0xAA, 0x98, 0xB0, 0x87, 0x2D, 0x35, 0x3D, 0xB2, 0xB6, 0xBA, - 0xAF, 0x8C, 0x96, 0x19, 0x8F, 0x9F, 0xA7, 0x0E, 0x16, 0x1E, 0xB4, 0x9A, 0xB8, 0xAA, 0x87, 0x2C, - 0x54, 0x7C, 0xB9, 0xA3, 0xDE, 0xDF, 0xDF, 0xA3, 0xB1, 0x80, 0xF2, 0xC4, 0xCD, 0xC9, 0xF1, 0xB8, - 0xA9, 0xB4, 0x99, 0x83, 0x0D, 0x35, 0x5D, 0x89, 0xB9, 0xA3, 0x2D, 0x55, 0x7D, 0xB5, 0x93, 0xA3, - 0x0E, 0x16, 0x1E, 0xA9, 0x2C, 0x54, 0x7C, 0xB8, 0xB4, 0xB0, 0xF1, 0x97, 0x83, 0xA8, 0x11, 0x84, - 0xA5, 0x09, 0x98, 0xA3, 0x83, 0xF0, 0xDA, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0xD8, 0xF1, 0xA5, - 0x29, 0x55, 0x7D, 0xA5, 0x85, 0x95, 0x02, 0x1A, 0x2E, 0x3A, 0x56, 0x5A, 0x40, 0x48, 0xF9, 0xF3, - 0xA3, 0xD9, 0xF8, 0xF0, 0x98, 0x83, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0x97, 0x82, 0xA8, 0xF1, - 0x11, 0xF0, 0x98, 0xA2, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0xDA, 0xF3, 0xDE, 0xD8, 0x83, 0xA5, - 0x94, 0x01, 0xD9, 0xA3, 0x02, 0xF1, 0xA2, 0xC3, 0xC5, 0xC7, 0xD8, 0xF1, 0x84, 0x92, 0xA2, 0x4D, - 0xDA, 0x2A, 0xD8, 0x48, 0x69, 0xD9, 0x2A, 0xD8, 0x68, 0x55, 0xDA, 0x32, 0xD8, 0x50, 0x71, 0xD9, - 0x32, 0xD8, 0x70, 0x5D, 0xDA, 0x3A, 0xD8, 0x58, 0x79, 0xD9, 0x3A, 0xD8, 0x78, 0x93, 0xA3, 0x4D, - 0xDA, 0x2A, 0xD8, 0x48, 0x69, 0xD9, 0x2A, 0xD8, 0x68, 0x55, 0xDA, 0x32, 0xD8, 0x50, 0x71, 0xD9, - 0x32, 0xD8, 0x70, 0x5D, 0xDA, 0x3A, 0xD8, 0x58, 0x79, 0xD9, 0x3A, 0xD8, 0x78, 0xA8, 0x8A, 0x9A, - 0xF0, 0x28, 0x50, 0x78, 0x9E, 0xF3, 0x88, 0x18, 0xF1, 0x9F, 0x1D, 0x98, 0xA8, 0xD9, 0x08, 0xD8, - 0xC8, 0x9F, 0x12, 0x9E, 0xF3, 0x15, 0xA8, 0xDA, 0x12, 0x10, 0xD8, 0xF1, 0xAF, 0xC8, 0x97, 0x87, - - // bank 5, 256 bytes - 0x34, 0xB5, 0xB9, 0x94, 0xA4, 0x21, 0xF3, 0xD9, 0x22, 0xD8, 0xF2, 0x2D, 0xF3, 0xD9, 0x2A, 0xD8, - 0xF2, 0x35, 0xF3, 0xD9, 0x32, 0xD8, 0x81, 0xA4, 0x60, 0x60, 0x61, 0xD9, 0x61, 0xD8, 0x6C, 0x68, - 0x69, 0xD9, 0x69, 0xD8, 0x74, 0x70, 0x71, 0xD9, 0x71, 0xD8, 0xB1, 0xA3, 0x84, 0x19, 0x3D, 0x5D, - 0xA3, 0x83, 0x1A, 0x3E, 0x5E, 0x93, 0x10, 0x30, 0x81, 0x10, 0x11, 0xB8, 0xB0, 0xAF, 0x8F, 0x94, - 0xF2, 0xDA, 0x3E, 0xD8, 0xB4, 0x9A, 0xA8, 0x87, 0x29, 0xDA, 0xF8, 0xD8, 0x87, 0x9A, 0x35, 0xDA, - 0xF8, 0xD8, 0x87, 0x9A, 0x3D, 0xDA, 0xF8, 0xD8, 0xB1, 0xB9, 0xA4, 0x98, 0x85, 0x02, 0x2E, 0x56, - 0xA5, 0x81, 0x00, 0x0C, 0x14, 0xA3, 0x97, 0xB0, 0x8A, 0xF1, 0x2D, 0xD9, 0x28, 0xD8, 0x4D, 0xD9, - 0x48, 0xD8, 0x6D, 0xD9, 0x68, 0xD8, 0xB1, 0x84, 0x0D, 0xDA, 0x0E, 0xD8, 0xA3, 0x29, 0x83, 0xDA, - 0x2C, 0x0E, 0xD8, 0xA3, 0x84, 0x49, 0x83, 0xDA, 0x2C, 0x4C, 0x0E, 0xD8, 0xB8, 0xB0, 0xA8, 0x8A, - 0x9A, 0xF5, 0x20, 0xAA, 0xDA, 0xDF, 0xD8, 0xA8, 0x40, 0xAA, 0xD0, 0xDA, 0xDE, 0xD8, 0xA8, 0x60, - 0xAA, 0xDA, 0xD0, 0xDF, 0xD8, 0xF1, 0x97, 0x86, 0xA8, 0x31, 0x9B, 0x06, 0x99, 0x07, 0xAB, 0x97, - 0x28, 0x88, 0x9B, 0xF0, 0x0C, 0x20, 0x14, 0x40, 0xB8, 0xB0, 0xB4, 0xA8, 0x8C, 0x9C, 0xF0, 0x04, - 0x28, 0x51, 0x79, 0x1D, 0x30, 0x14, 0x38, 0xB2, 0x82, 0xAB, 0xD0, 0x98, 0x2C, 0x50, 0x50, 0x78, - 0x78, 0x9B, 0xF1, 0x1A, 0xB0, 0xF0, 0x8A, 0x9C, 0xA8, 0x29, 0x51, 0x79, 0x8B, 0x29, 0x51, 0x79, - 0x8A, 0x24, 0x70, 0x59, 0x8B, 0x20, 0x58, 0x71, 0x8A, 0x44, 0x69, 0x38, 0x8B, 0x39, 0x40, 0x68, - 0x8A, 0x64, 0x48, 0x31, 0x8B, 0x30, 0x49, 0x60, 0xA5, 0x88, 0x20, 0x09, 0x71, 0x58, 0x44, 0x68, - - // bank 6, 256 bytes - 0x11, 0x39, 0x64, 0x49, 0x30, 0x19, 0xF1, 0xAC, 0x00, 0x2C, 0x54, 0x7C, 0xF0, 0x8C, 0xA8, 0x04, - 0x28, 0x50, 0x78, 0xF1, 0x88, 0x97, 0x26, 0xA8, 0x59, 0x98, 0xAC, 0x8C, 0x02, 0x26, 0x46, 0x66, - 0xF0, 0x89, 0x9C, 0xA8, 0x29, 0x51, 0x79, 0x24, 0x70, 0x59, 0x44, 0x69, 0x38, 0x64, 0x48, 0x31, - 0xA9, 0x88, 0x09, 0x20, 0x59, 0x70, 0xAB, 0x11, 0x38, 0x40, 0x69, 0xA8, 0x19, 0x31, 0x48, 0x60, - 0x8C, 0xA8, 0x3C, 0x41, 0x5C, 0x20, 0x7C, 0x00, 0xF1, 0x87, 0x98, 0x19, 0x86, 0xA8, 0x6E, 0x76, - 0x7E, 0xA9, 0x99, 0x88, 0x2D, 0x55, 0x7D, 0x9E, 0xB9, 0xA3, 0x8A, 0x22, 0x8A, 0x6E, 0x8A, 0x56, - 0x8A, 0x5E, 0x9F, 0xB1, 0x83, 0x06, 0x26, 0x46, 0x66, 0x0E, 0x2E, 0x4E, 0x6E, 0x9D, 0xB8, 0xAD, - 0x00, 0x2C, 0x54, 0x7C, 0xF2, 0xB1, 0x8C, 0xB4, 0x99, 0xB9, 0xA3, 0x2D, 0x55, 0x7D, 0x81, 0x91, - 0xAC, 0x38, 0xAD, 0x3A, 0xB5, 0x83, 0x91, 0xAC, 0x2D, 0xD9, 0x28, 0xD8, 0x4D, 0xD9, 0x48, 0xD8, - 0x6D, 0xD9, 0x68, 0xD8, 0x8C, 0x9D, 0xAE, 0x29, 0xD9, 0x04, 0xAE, 0xD8, 0x51, 0xD9, 0x04, 0xAE, - 0xD8, 0x79, 0xD9, 0x04, 0xD8, 0x81, 0xF3, 0x9D, 0xAD, 0x00, 0x8D, 0xAE, 0x19, 0x81, 0xAD, 0xD9, - 0x01, 0xD8, 0xF2, 0xAE, 0xDA, 0x26, 0xD8, 0x8E, 0x91, 0x29, 0x83, 0xA7, 0xD9, 0xAD, 0xAD, 0xAD, - 0xAD, 0xF3, 0x2A, 0xD8, 0xD8, 0xF1, 0xB0, 0xAC, 0x89, 0x91, 0x3E, 0x5E, 0x76, 0xF3, 0xAC, 0x2E, - 0x2E, 0xF1, 0xB1, 0x8C, 0x5A, 0x9C, 0xAC, 0x2C, 0x28, 0x28, 0x28, 0x9C, 0xAC, 0x30, 0x18, 0xA8, - 0x98, 0x81, 0x28, 0x34, 0x3C, 0x97, 0x24, 0xA7, 0x28, 0x34, 0x3C, 0x9C, 0x24, 0xF2, 0xB0, 0x89, - 0xAC, 0x91, 0x2C, 0x4C, 0x6C, 0x8A, 0x9B, 0x2D, 0xD9, 0xD8, 0xD8, 0x51, 0xD9, 0xD8, 0xD8, 0x79, - - // bank 7, 138 bytes (remainder) - 0xD9, 0xD8, 0xD8, 0xF1, 0x9E, 0x88, 0xA3, 0x31, 0xDA, 0xD8, 0xD8, 0x91, 0x2D, 0xD9, 0x28, 0xD8, - 0x4D, 0xD9, 0x48, 0xD8, 0x6D, 0xD9, 0x68, 0xD8, 0xB1, 0x83, 0x93, 0x35, 0x3D, 0x80, 0x25, 0xDA, - 0xD8, 0xD8, 0x85, 0x69, 0xDA, 0xD8, 0xD8, 0xB4, 0x93, 0x81, 0xA3, 0x28, 0x34, 0x3C, 0xF3, 0xAB, - 0x8B, 0xF8, 0xA3, 0x91, 0xB6, 0x09, 0xB4, 0xD9, 0xAB, 0xDE, 0xFA, 0xB0, 0x87, 0x9C, 0xB9, 0xA3, - 0xDD, 0xF1, 0xA3, 0xA3, 0xA3, 0xA3, 0x95, 0xF1, 0xA3, 0xA3, 0xA3, 0x9D, 0xF1, 0xA3, 0xA3, 0xA3, - 0xA3, 0xF2, 0xA3, 0xB4, 0x90, 0x80, 0xF2, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, - 0xA3, 0xB2, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xB0, 0x87, 0xB5, 0x99, 0xF1, 0xA3, 0xA3, 0xA3, - 0x98, 0xF1, 0xA3, 0xA3, 0xA3, 0xA3, 0x97, 0xA3, 0xA3, 0xA3, 0xA3, 0xF3, 0x9B, 0xA3, 0xA3, 0xDC, - 0xB9, 0xA7, 0xF1, 0x26, 0x26, 0x26, 0xD8, 0xD8, 0xFF -}; - -// thanks to Noah Zerkin for piecing this stuff together! -const unsigned char dmpConfig[MPU9150_DMP_CONFIG_SIZE] PROGMEM = { -// BANK OFFSET LENGTH [DATA] - 0x03, 0x7B, 0x03, 0x4C, 0xCD, 0x6C, // FCFG_1 inv_set_gyro_calibration - 0x03, 0xAB, 0x03, 0x36, 0x56, 0x76, // FCFG_3 inv_set_gyro_calibration - 0x00, 0x68, 0x04, 0x02, 0xCB, 0x47, 0xA2, // D_0_104 inv_set_gyro_calibration - 0x02, 0x18, 0x04, 0x00, 0x05, 0x8B, 0xC1, // D_0_24 inv_set_gyro_calibration - 0x01, 0x0C, 0x04, 0x00, 0x00, 0x00, 0x00, // D_1_152 inv_set_accel_calibration - 0x03, 0x7F, 0x06, 0x0C, 0xC9, 0x2C, 0x97, 0x97, 0x97, // FCFG_2 inv_set_accel_calibration - 0x03, 0x89, 0x03, 0x26, 0x46, 0x66, // FCFG_7 inv_set_accel_calibration - 0x00, 0x6C, 0x02, 0x20, 0x00, // D_0_108 inv_set_accel_calibration - 0x02, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_00 inv_set_compass_calibration - 0x02, 0x44, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_01 - 0x02, 0x48, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_02 - 0x02, 0x4C, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_10 - 0x02, 0x50, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_11 - 0x02, 0x54, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_12 - 0x02, 0x58, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_20 - 0x02, 0x5C, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_21 - 0x02, 0xBC, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_22 - 0x01, 0xEC, 0x04, 0x00, 0x00, 0x40, 0x00, // D_1_236 inv_apply_endian_accel - 0x03, 0x7F, 0x06, 0x0C, 0xC9, 0x2C, 0x97, 0x97, 0x97, // FCFG_2 inv_set_mpu_sensors - 0x04, 0x02, 0x03, 0x0D, 0x35, 0x5D, // CFG_MOTION_BIAS inv_turn_on_bias_from_no_motion - 0x04, 0x09, 0x04, 0x87, 0x2D, 0x35, 0x3D, // FCFG_5 inv_set_bias_update - 0x00, 0xA3, 0x01, 0x00, // D_0_163 inv_set_dead_zone - // SPECIAL 0x01 = enable interrupts - 0x00, 0x00, 0x00, 0x01, // SET INT_ENABLE at i=22, SPECIAL INSTRUCTION - 0x07, 0x86, 0x01, 0xFE, // CFG_6 inv_set_fifo_interupt - 0x07, 0x41, 0x05, 0xF1, 0x20, 0x28, 0x30, 0x38, // CFG_8 inv_send_quaternion - 0x07, 0x7E, 0x01, 0x30, // CFG_16 inv_set_footer - 0x07, 0x46, 0x01, 0x9A, // CFG_GYRO_SOURCE inv_send_gyro - 0x07, 0x47, 0x04, 0xF1, 0x28, 0x30, 0x38, // CFG_9 inv_send_gyro -> inv_construct3_fifo - 0x07, 0x6C, 0x04, 0xF1, 0x28, 0x30, 0x38, // CFG_12 inv_send_accel -> inv_construct3_fifo - 0x02, 0x16, 0x02, 0x00, 0x01 // D_0_22 inv_set_fifo_rate - - // This very last 0x01 WAS a 0x09, which drops the FIFO rate down to 20 Hz. 0x07 is 25 Hz, - // 0x01 is 100Hz. Going faster than 100Hz (0x00=200Hz) tends to result in very noisy data. - // DMP output frequency is calculated easily using this equation: (200Hz / (1 + value)) - - // It is important to make sure the host processor can keep up with reading and processing - // the FIFO output at the desired rate. Handling FIFO overflow cleanly is also a good idea. -}; - -const unsigned char dmpUpdates[MPU9150_DMP_UPDATES_SIZE] PROGMEM = { - 0x01, 0xB2, 0x02, 0xFF, 0xFF, - 0x01, 0x90, 0x04, 0x09, 0x23, 0xA1, 0x35, - 0x01, 0x6A, 0x02, 0x06, 0x00, - 0x01, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x60, 0x04, 0x40, 0x00, 0x00, 0x00, - 0x01, 0x62, 0x02, 0x00, 0x00, - 0x00, 0x60, 0x04, 0x00, 0x40, 0x00, 0x00 -}; - -uint8_t MPU9150::dmpInitialize() { - // reset device - DEBUG_PRINTLN(F("\n\nResetting MPU9150...")); - reset(); - delay(30); // wait after reset - - // enable sleep mode and wake cycle - /*Serial.println(F("Enabling sleep mode...")); - setSleepEnabled(true); - Serial.println(F("Enabling wake cycle...")); - setWakeCycleEnabled(true);*/ - - // disable sleep mode - DEBUG_PRINTLN(F("Disabling sleep mode...")); - setSleepEnabled(false); - - // get MPU hardware revision - DEBUG_PRINTLN(F("Selecting user bank 16...")); - setMemoryBank(0x10, true, true); - DEBUG_PRINTLN(F("Selecting memory byte 6...")); - setMemoryStartAddress(0x06); - DEBUG_PRINTLN(F("Checking hardware revision...")); - uint8_t hwRevision = readMemoryByte(); - DEBUG_PRINT(F("Revision @ user[16][6] = ")); - DEBUG_PRINTLNF(hwRevision, HEX); - DEBUG_PRINTLN(F("Resetting memory bank selection to 0...")); - setMemoryBank(0, false, false); - - // check OTP bank valid - DEBUG_PRINTLN(F("Reading OTP bank valid flag...")); - uint8_t otpValid = getOTPBankValid(); - DEBUG_PRINT(F("OTP bank is ")); - DEBUG_PRINTLN(otpValid ? F("valid!") : F("invalid!")); - - // get X/Y/Z gyro offsets - DEBUG_PRINTLN(F("Reading gyro offset TC values...")); - int8_t xgOffsetTC = getXGyroOffsetTC(); - int8_t ygOffsetTC = getYGyroOffsetTC(); - int8_t zgOffsetTC = getZGyroOffsetTC(); - DEBUG_PRINT(F("X gyro offset = ")); - DEBUG_PRINTLN(xgOffset); - DEBUG_PRINT(F("Y gyro offset = ")); - DEBUG_PRINTLN(ygOffset); - DEBUG_PRINT(F("Z gyro offset = ")); - DEBUG_PRINTLN(zgOffset); - - // setup weird slave stuff (?) - DEBUG_PRINTLN(F("Setting slave 0 address to 0x7F...")); - setSlaveAddress(0, 0x7F); - DEBUG_PRINTLN(F("Disabling I2C Master mode...")); - setI2CMasterModeEnabled(false); - DEBUG_PRINTLN(F("Setting slave 0 address to 0x68 (self)...")); - setSlaveAddress(0, 0x68); - DEBUG_PRINTLN(F("Resetting I2C Master control...")); - resetI2CMaster(); - delay(20); - - // load DMP code into memory banks - DEBUG_PRINT(F("Writing DMP code to MPU memory banks (")); - DEBUG_PRINT(MPU9150_DMP_CODE_SIZE); - DEBUG_PRINTLN(F(" bytes)")); - if (writeProgMemoryBlock(dmpMemory, MPU9150_DMP_CODE_SIZE)) { - DEBUG_PRINTLN(F("Success! DMP code written and verified.")); - - // write DMP configuration - DEBUG_PRINT(F("Writing DMP configuration to MPU memory banks (")); - DEBUG_PRINT(MPU9150_DMP_CONFIG_SIZE); - DEBUG_PRINTLN(F(" bytes in config def)")); - if (writeProgDMPConfigurationSet(dmpConfig, MPU9150_DMP_CONFIG_SIZE)) { - DEBUG_PRINTLN(F("Success! DMP configuration written and verified.")); - - DEBUG_PRINTLN(F("Setting clock source to Z Gyro...")); - setClockSource(MPU9150_CLOCK_PLL_ZGYRO); - - DEBUG_PRINTLN(F("Setting DMP and FIFO_OFLOW interrupts enabled...")); - setIntEnabled(0x12); - - DEBUG_PRINTLN(F("Setting sample rate to 200Hz...")); - setRate(4); // 1khz / (1 + 4) = 200 Hz - - DEBUG_PRINTLN(F("Setting external frame sync to TEMP_OUT_L[0]...")); - setExternalFrameSync(MPU9150_EXT_SYNC_TEMP_OUT_L); - - DEBUG_PRINTLN(F("Setting DLPF bandwidth to 42Hz...")); - setDLPFMode(MPU9150_DLPF_BW_42); - - DEBUG_PRINTLN(F("Setting gyro sensitivity to +/- 2000 deg/sec...")); - setFullScaleGyroRange(MPU9150_GYRO_FS_2000); - - DEBUG_PRINTLN(F("Setting DMP configuration bytes (function unknown)...")); - setDMPConfig1(0x03); - setDMPConfig2(0x00); - - DEBUG_PRINTLN(F("Clearing OTP Bank flag...")); - setOTPBankValid(false); - - DEBUG_PRINTLN(F("Setting X/Y/Z gyro offset TCs to previous values...")); - setXGyroOffsetTC(xgOffsetTC); - setYGyroOffsetTC(ygOffsetTC); - setZGyroOffsetTC(zgOffsetTC); - - //DEBUG_PRINTLN(F("Setting X/Y/Z gyro user offsets to zero...")); - //setXGyroOffset(0); - //setYGyroOffset(0); - //setZGyroOffset(0); - - DEBUG_PRINTLN(F("Writing final memory update 1/7 (function unknown)...")); - uint8_t dmpUpdate[16], j; - uint16_t pos = 0; - for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); - writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); - - DEBUG_PRINTLN(F("Writing final memory update 2/7 (function unknown)...")); - for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); - writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); - - DEBUG_PRINTLN(F("Resetting FIFO...")); - resetFIFO(); - - DEBUG_PRINTLN(F("Reading FIFO count...")); - uint16_t fifoCount = getFIFOCount(); - uint8_t fifoBuffer[128]; - - DEBUG_PRINT(F("Current FIFO count=")); - DEBUG_PRINTLN(fifoCount); - getFIFOBytes(fifoBuffer, fifoCount); - - DEBUG_PRINTLN(F("Setting motion detection threshold to 2...")); - setMotionDetectionThreshold(2); - - DEBUG_PRINTLN(F("Setting zero-motion detection threshold to 156...")); - setZeroMotionDetectionThreshold(156); - - DEBUG_PRINTLN(F("Setting motion detection duration to 80...")); - setMotionDetectionDuration(80); - - DEBUG_PRINTLN(F("Setting zero-motion detection duration to 0...")); - setZeroMotionDetectionDuration(0); - - DEBUG_PRINTLN(F("Resetting FIFO...")); - resetFIFO(); - - DEBUG_PRINTLN(F("Enabling FIFO...")); - setFIFOEnabled(true); - - DEBUG_PRINTLN(F("Enabling DMP...")); - setDMPEnabled(true); - - DEBUG_PRINTLN(F("Resetting DMP...")); - resetDMP(); - - DEBUG_PRINTLN(F("Writing final memory update 3/7 (function unknown)...")); - for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); - writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); - - DEBUG_PRINTLN(F("Writing final memory update 4/7 (function unknown)...")); - for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); - writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); - - DEBUG_PRINTLN(F("Writing final memory update 5/7 (function unknown)...")); - for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); - writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); - - DEBUG_PRINTLN(F("Waiting for FIFO count > 2...")); - while ((fifoCount = getFIFOCount()) < 3); - - DEBUG_PRINT(F("Current FIFO count=")); - DEBUG_PRINTLN(fifoCount); - DEBUG_PRINTLN(F("Reading FIFO data...")); - getFIFOBytes(fifoBuffer, fifoCount); - - DEBUG_PRINTLN(F("Reading interrupt status...")); - uint8_t mpuIntStatus = getIntStatus(); - - DEBUG_PRINT(F("Current interrupt status=")); - DEBUG_PRINTLNF(mpuIntStatus, HEX); - - DEBUG_PRINTLN(F("Reading final memory update 6/7 (function unknown)...")); - for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); - readMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); - - DEBUG_PRINTLN(F("Waiting for FIFO count > 2...")); - while ((fifoCount = getFIFOCount()) < 3); - - DEBUG_PRINT(F("Current FIFO count=")); - DEBUG_PRINTLN(fifoCount); - - DEBUG_PRINTLN(F("Reading FIFO data...")); - getFIFOBytes(fifoBuffer, fifoCount); - - DEBUG_PRINTLN(F("Reading interrupt status...")); - mpuIntStatus = getIntStatus(); - - DEBUG_PRINT(F("Current interrupt status=")); - DEBUG_PRINTLNF(mpuIntStatus, HEX); - - DEBUG_PRINTLN(F("Writing final memory update 7/7 (function unknown)...")); - for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); - writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); - - DEBUG_PRINTLN(F("DMP is good to go! Finally.")); - - DEBUG_PRINTLN(F("Disabling DMP (you turn it on later)...")); - setDMPEnabled(false); - - DEBUG_PRINTLN(F("Setting up internal 42-byte (default) DMP packet buffer...")); - dmpPacketSize = 42; - /*if ((dmpPacketBuffer = (uint8_t *)malloc(42)) == 0) { - return 3; // TODO: proper error code for no memory - }*/ - - DEBUG_PRINTLN(F("Resetting FIFO and clearing INT status one last time...")); - resetFIFO(); - getIntStatus(); - } else { - DEBUG_PRINTLN(F("ERROR! DMP configuration verification failed.")); - return 2; // configuration block loading failed - } - } else { - DEBUG_PRINTLN(F("ERROR! DMP code verification failed.")); - return 1; // main binary block loading failed - } - return 0; // success -} - -bool MPU9150::dmpPacketAvailable() { - return getFIFOCount() >= dmpGetFIFOPacketSize(); -} - -// uint8_t MPU9150::dmpSetFIFORate(uint8_t fifoRate); -// uint8_t MPU9150::dmpGetFIFORate(); -// uint8_t MPU9150::dmpGetSampleStepSizeMS(); -// uint8_t MPU9150::dmpGetSampleFrequency(); -// int32_t MPU9150::dmpDecodeTemperature(int8_t tempReg); - -//uint8_t MPU9150::dmpRegisterFIFORateProcess(inv_obj_func func, int16_t priority); -//uint8_t MPU9150::dmpUnregisterFIFORateProcess(inv_obj_func func); -//uint8_t MPU9150::dmpRunFIFORateProcesses(); - -// uint8_t MPU9150::dmpSendQuaternion(uint_fast16_t accuracy); -// uint8_t MPU9150::dmpSendGyro(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU9150::dmpSendAccel(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU9150::dmpSendLinearAccel(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU9150::dmpSendLinearAccelInWorld(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU9150::dmpSendControlData(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU9150::dmpSendSensorData(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU9150::dmpSendExternalSensorData(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU9150::dmpSendGravity(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU9150::dmpSendPacketNumber(uint_fast16_t accuracy); -// uint8_t MPU9150::dmpSendQuantizedAccel(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU9150::dmpSendEIS(uint_fast16_t elements, uint_fast16_t accuracy); - -uint8_t MPU9150::dmpGetAccel(int32_t *data, const uint8_t* packet) { - // TODO: accommodate different arrangements of sent data (ONLY default supported now) - if (packet == 0) packet = dmpPacketBuffer; - data[0] = ((packet[28] << 24) + (packet[29] << 16) + (packet[30] << 8) + packet[31]); - data[1] = ((packet[32] << 24) + (packet[33] << 16) + (packet[34] << 8) + packet[35]); - data[2] = ((packet[36] << 24) + (packet[37] << 16) + (packet[38] << 8) + packet[39]); - return 0; -} -uint8_t MPU9150::dmpGetAccel(int16_t *data, const uint8_t* packet) { - // TODO: accommodate different arrangements of sent data (ONLY default supported now) - if (packet == 0) packet = dmpPacketBuffer; - data[0] = (packet[28] << 8) + packet[29]; - data[1] = (packet[32] << 8) + packet[33]; - data[2] = (packet[36] << 8) + packet[37]; - return 0; -} -uint8_t MPU9150::dmpGetAccel(VectorInt16 *v, const uint8_t* packet) { - // TODO: accommodate different arrangements of sent data (ONLY default supported now) - if (packet == 0) packet = dmpPacketBuffer; - v -> x = (packet[28] << 8) + packet[29]; - v -> y = (packet[32] << 8) + packet[33]; - v -> z = (packet[36] << 8) + packet[37]; - return 0; -} -uint8_t MPU9150::dmpGetQuaternion(int32_t *data, const uint8_t* packet) { - // TODO: accommodate different arrangements of sent data (ONLY default supported now) - if (packet == 0) packet = dmpPacketBuffer; - data[0] = ((packet[0] << 24) + (packet[1] << 16) + (packet[2] << 8) + packet[3]); - data[1] = ((packet[4] << 24) + (packet[5] << 16) + (packet[6] << 8) + packet[7]); - data[2] = ((packet[8] << 24) + (packet[9] << 16) + (packet[10] << 8) + packet[11]); - data[3] = ((packet[12] << 24) + (packet[13] << 16) + (packet[14] << 8) + packet[15]); - return 0; -} -uint8_t MPU9150::dmpGetQuaternion(int16_t *data, const uint8_t* packet) { - // TODO: accommodate different arrangements of sent data (ONLY default supported now) - if (packet == 0) packet = dmpPacketBuffer; - data[0] = ((packet[0] << 8) + packet[1]); - data[1] = ((packet[4] << 8) + packet[5]); - data[2] = ((packet[8] << 8) + packet[9]); - data[3] = ((packet[12] << 8) + packet[13]); - return 0; -} -uint8_t MPU9150::dmpGetQuaternion(Quaternion *q, const uint8_t* packet) { - // TODO: accommodate different arrangements of sent data (ONLY default supported now) - int16_t qI[4]; - uint8_t status = dmpGetQuaternion(qI, packet); - if (status == 0) { - q -> w = (float)qI[0] / 16384.0f; - q -> x = (float)qI[1] / 16384.0f; - q -> y = (float)qI[2] / 16384.0f; - q -> z = (float)qI[3] / 16384.0f; - return 0; - } - return status; // int16 return value, indicates error if this line is reached -} -// uint8_t MPU9150::dmpGet6AxisQuaternion(long *data, const uint8_t* packet); -// uint8_t MPU9150::dmpGetRelativeQuaternion(long *data, const uint8_t* packet); -uint8_t MPU9150::dmpGetGyro(int32_t *data, const uint8_t* packet) { - // TODO: accommodate different arrangements of sent data (ONLY default supported now) - if (packet == 0) packet = dmpPacketBuffer; - data[0] = ((packet[16] << 24) + (packet[17] << 16) + (packet[18] << 8) + packet[19]); - data[1] = ((packet[20] << 24) + (packet[21] << 16) + (packet[22] << 8) + packet[23]); - data[2] = ((packet[24] << 24) + (packet[25] << 16) + (packet[26] << 8) + packet[27]); - return 0; -} -uint8_t MPU9150::dmpGetGyro(int16_t *data, const uint8_t* packet) { - // TODO: accommodate different arrangements of sent data (ONLY default supported now) - if (packet == 0) packet = dmpPacketBuffer; - data[0] = (packet[16] << 8) + packet[17]; - data[1] = (packet[20] << 8) + packet[21]; - data[2] = (packet[24] << 8) + packet[25]; - return 0; -} -// uint8_t MPU9150::dmpSetLinearAccelFilterCoefficient(float coef); -// uint8_t MPU9150::dmpGetLinearAccel(long *data, const uint8_t* packet); -uint8_t MPU9150::dmpGetLinearAccel(VectorInt16 *v, VectorInt16 *vRaw, VectorFloat *gravity) { - // get rid of the gravity component (+1g = +8192 in standard DMP FIFO packet, sensitivity is 2g) - v -> x = vRaw -> x - gravity -> x*8192; - v -> y = vRaw -> y - gravity -> y*8192; - v -> z = vRaw -> z - gravity -> z*8192; - return 0; -} -// uint8_t MPU9150::dmpGetLinearAccelInWorld(long *data, const uint8_t* packet); -uint8_t MPU9150::dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Quaternion *q) { - // rotate measured 3D acceleration vector into original state - // frame of reference based on orientation quaternion - memcpy(v, vReal, sizeof(VectorInt16)); - v -> rotate(q); - return 0; -} -// uint8_t MPU9150::dmpGetGyroAndAccelSensor(long *data, const uint8_t* packet); -// uint8_t MPU9150::dmpGetGyroSensor(long *data, const uint8_t* packet); -// uint8_t MPU9150::dmpGetControlData(long *data, const uint8_t* packet); -// uint8_t MPU9150::dmpGetTemperature(long *data, const uint8_t* packet); -// uint8_t MPU9150::dmpGetGravity(long *data, const uint8_t* packet); -uint8_t MPU9150::dmpGetGravity(VectorFloat *v, Quaternion *q) { - v -> x = 2 * (q -> x*q -> z - q -> w*q -> y); - v -> y = 2 * (q -> w*q -> x + q -> y*q -> z); - v -> z = q -> w*q -> w - q -> x*q -> x - q -> y*q -> y + q -> z*q -> z; - return 0; -} -// uint8_t MPU9150::dmpGetUnquantizedAccel(long *data, const uint8_t* packet); -// uint8_t MPU9150::dmpGetQuantizedAccel(long *data, const uint8_t* packet); -// uint8_t MPU9150::dmpGetExternalSensorData(long *data, int size, const uint8_t* packet); -// uint8_t MPU9150::dmpGetEIS(long *data, const uint8_t* packet); - -uint8_t MPU9150::dmpGetEuler(float *data, Quaternion *q) { - data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1); // psi - data[1] = -asin(2*q -> x*q -> z + 2*q -> w*q -> y); // theta - data[2] = atan2(2*q -> y*q -> z - 2*q -> w*q -> x, 2*q -> w*q -> w + 2*q -> z*q -> z - 1); // phi - return 0; -} -uint8_t MPU9150::dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity) { - // yaw: (about Z axis) - data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1); - // pitch: (nose up/down, about Y axis) - data[1] = atan(gravity -> x / sqrt(gravity -> y*gravity -> y + gravity -> z*gravity -> z)); - // roll: (tilt left/right, about X axis) - data[2] = atan(gravity -> y / sqrt(gravity -> x*gravity -> x + gravity -> z*gravity -> z)); - return 0; -} - -// uint8_t MPU9150::dmpGetAccelFloat(float *data, const uint8_t* packet); -// uint8_t MPU9150::dmpGetQuaternionFloat(float *data, const uint8_t* packet); - -uint8_t MPU9150::dmpProcessFIFOPacket(const unsigned char *dmpData) { - /*for (uint8_t k = 0; k < dmpPacketSize; k++) { - if (dmpData[k] < 0x10) Serial.print("0"); - Serial.print(dmpData[k], HEX); - Serial.print(" "); - } - Serial.print("\n");*/ - //Serial.println((uint16_t)dmpPacketBuffer); - return 0; -} -uint8_t MPU9150::dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *processed) { - uint8_t status; - uint8_t buf[dmpPacketSize]; - for (uint8_t i = 0; i < numPackets; i++) { - // read packet from FIFO - getFIFOBytes(buf, dmpPacketSize); - - // process packet - if ((status = dmpProcessFIFOPacket(buf)) > 0) return status; - - // increment external process count variable, if supplied - if (processed != 0) *processed++; - } - return 0; -} - -// uint8_t MPU9150::dmpSetFIFOProcessedCallback(void (*func) (void)); - -// uint8_t MPU9150::dmpInitFIFOParam(); -// uint8_t MPU9150::dmpCloseFIFO(); -// uint8_t MPU9150::dmpSetGyroDataSource(uint_fast8_t source); -// uint8_t MPU9150::dmpDecodeQuantizedAccel(); -// uint32_t MPU9150::dmpGetGyroSumOfSquare(); -// uint32_t MPU9150::dmpGetAccelSumOfSquare(); -// void MPU9150::dmpOverrideQuaternion(long *q); -uint16_t MPU9150::dmpGetFIFOPacketSize() { - return dmpPacketSize; -} - -#endif /* _MPU9150_6AXIS_MOTIONAPPS20_H_ */ From 1bdc2c08da017521f5027ea1efbb2c01d47ca57b Mon Sep 17 00:00:00 2001 From: Bartosz Kryza Date: Tue, 18 Feb 2014 00:55:44 +0100 Subject: [PATCH 009/335] Initial release of AT30TSE752/754/758 ATMEL temperature sensor library --- Arduino/AT30TSE75x/AT30TSE75x.cpp | 630 ++++++++++++++++++ Arduino/AT30TSE75x/AT30TSE75x.h | 272 ++++++++ .../AT30TSE75x_basic/AT30TSE75x_basic.ino | 113 ++++ 3 files changed, 1015 insertions(+) create mode 100644 Arduino/AT30TSE75x/AT30TSE75x.cpp create mode 100644 Arduino/AT30TSE75x/AT30TSE75x.h create mode 100644 Arduino/AT30TSE75x/Examples/AT30TSE75x_basic/AT30TSE75x_basic.ino diff --git a/Arduino/AT30TSE75x/AT30TSE75x.cpp b/Arduino/AT30TSE75x/AT30TSE75x.cpp new file mode 100644 index 00000000..acdfd4aa --- /dev/null +++ b/Arduino/AT30TSE75x/AT30TSE75x.cpp @@ -0,0 +1,630 @@ +// I2Cdev library collection - AT30TSE75x I2C device class +// Based on ATMEL AT30TSE75x datasheet, 2013 Rev. Atmel-8751F-DTS-AT30TSE752-754-758-Datasheet_092013 +// 2014-02-16 by Bartosz Kryza +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// 2014-02-16 - initial release + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2014 Bartosz Kryza, Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#include "AT30TSE75x.h" + +/** Default constructor, uses default I2C address. Assumes the device is + * AT30TSE752 and A2-A0 pins are connected to ground. + */ +AT30TSE75x::AT30TSE75x() { + devAddr = 0x00; + devType = AT30TSE75x_752; +} + +/** Specific address constructor. + * @param address 3 least significat bits of the address should be provided here + * depending on the A2-A0 connection + * @deviceType The type of device (AT30TSE75x_752, AT30TSE75x_754, AT30TSE75x_758) + */ +AT30TSE75x::AT30TSE75x(uint8_t address, uint8_t deviceType) { + // Here we only need the least significant 3 bits + devAddr = 0x07 & address; + devType = deviceType; +} + +/** Power on and prepare for general usage. + */ +void AT30TSE75x::initialize() { + // Nothing to do here +} + +/** Verify the I2C connection. + * Make sure the device is connected and responds as expected. + * @return True if connection is valid, false otherwise + */ +bool AT30TSE75x::testConnection() { + + if (I2Cdev::readWord(devAddr, AT30TSE75x_RA_TEMPERATURE, buffer) == 1) { + return true; + } + return false; + +} + +/** Get the current reading of temperature in Celcius degrees + * @return Current temperature measurement in Celcius degrees + */ +float AT30TSE75x::getTemperatureCelcius() { + + uint16_t rawTemperature = getTemperatureRaw(); + + float celciusTemperature = 0.0; + + if((rawTemperature & 0x8000) == 0) { + celciusTemperature = (rawTemperature>>8) + ((rawTemperature&0x00F0)>>4)*AT30TSE75x_STEP_12BIT; + } + else { + uint16_t twosComplement = (~rawTemperature) + 1; + celciusTemperature = - (twosComplement>>8) - ((twosComplement & 0x00F0)>>4)*AT30TSE75x_STEP_12BIT; + } + + return celciusTemperature; + +} + +/** Get the current reading of temperature in Fahrenheit degrees + * @return Current temperature measurement in Fahrenheit degrees + */ +float AT30TSE75x::getTemperatureFahrenheit() { + + return (getTemperatureCelcius()*9.0)/5.0 + 32.0; + +} + +/** Get the current contents of devices temperature register + * @return Current temperature register content + */ +uint16_t AT30TSE75x::getTemperatureRaw() { + + uint16_t temperatureValue = 0x0000; + I2Cdev::readWord(AT30TSE75x_ADDRESS_TEMP_SENSOR | devAddr, + AT30TSE75x_RA_TEMPERATURE, + &temperatureValue); + return temperatureValue; + +} + +/** Get the current configuration register content + * @return Current configuration register content + */ +uint16_t AT30TSE75x::getConfiguration() { + uint16_t config = 0x0000; + I2Cdev::readWord(AT30TSE75x_ADDRESS_TEMP_SENSOR | devAddr, AT30TSE75x_RA_CONFIGURATION, &config); + return config; +} + +/** Get the status of Non-volatile Busy flag (Read-only) + * @return Status of Non-volatile Busy flag + */ +bool AT30TSE75x::getNVRBusy() { + uint16_t config = getConfiguration(); + return (config>>AT30TSE75x_CONFIG_NVRBSY_BIT)&(0x0001); +} + +/** Get the status of shutdown mode flag + * @return Status of shutdown mode + */ +bool AT30TSE75x::getShutdownMode() { + uint16_t config = getConfiguration(); + return (config>>AT30TSE75x_CONFIG_SD_BIT)&(0x0001); +} + +/** Set the device shutdown mode + * @param true - shutdown active, false - normal operation + */ +void AT30TSE75x::setShutdownMode(bool shutdownMode) { + uint16_t config = getConfiguration()&(~(0x01<>AT30TSE75x_CONFIG_CMPINT_BIT)&(0x0001); +} + +/** Set the device shutdown mode + * @param false - comparator mode, true - interrupt mode + */ +void AT30TSE75x::setComparatorInterruptMode(bool comparatorOrInterrup) { + uint16_t config = getConfiguration()&(~(0x01<>AT30TSE75x_CONFIG_POL_BIT)&(0x0001); +} + +/** Set the alert polarity + * @param false - alert polarity low, true - alert polarity high + */ +void AT30TSE75x::setAlertPolarity(bool alertPolarity) { + uint16_t config = getConfiguration()&(~(0x01<>AT30TSE75x_CONFIG_FT_BIT)&(0x0003); +} + +/** Set the value of alert fault count + * @return Value of alert fault count + * @see AT30TSE75x_FAULT_COUNT_1 + * @see AT30TSE75x_FAULT_COUNT_2 + * @see AT30TSE75x_FAULT_COUNT_4 + * @see AT30TSE75x_FAULT_COUNT_6 + */ +void AT30TSE75x::setFaultToleranceQueue(uint8_t faultCount) { + uint16_t config = getConfiguration()&(~(0x03<>AT30TSE75x_CONFIG_RES_BIT)&(0x0003); +} + +/** Set the conversion resolution + * @param conversionResolution Value of the resolution + * @see AT30TSE75x_RES_9BIT + * @see AT30TSE75x_RES_10BIT + * @see AT30TSE75x_RES_11BIT + * @see AT30TSE75x_RES_12BIT + */ +void AT30TSE75x::setConversionResolution(uint8_t conversionResolution) { + uint16_t config = getConfiguration()&(~(0x03<>AT30TSE75x_CONFIG_FT_BIT)&(0x0001); +} + +/** Set the status of device one shot mode + * @param oneShotMode false - one shot mode disabled, true - one shot mode enabled + */ +void AT30TSE75x::setOneShotMode(bool oneShotMode) { + uint16_t config = getConfiguration()&(~(0x01<>AT30TSE75x_NVCONFIG_NVCMPINT_BIT)&(0x0001); +} + +/** Set the status of comparator/interrupt mode in non-volatile configuration register + * @param comparatorOrInterrupt false - comparator mode, true - interrupt mode + */ +void AT30TSE75x::setNVComparatorInterruptMode(bool comparatorOrInterrupt) { + uint16_t config = getNVConfiguration()&(~(0x01<>AT30TSE75x_NVCONFIG_RLCK_BIT)&(0x0001); +} + +/** Set the status of comparator/interrupt mode in non-volatile configuration register + * @param comparatorOrInterrupt false - comparator mode, true - interrupt mode + */ +void AT30TSE75x::setNVRegisterLock(bool registerLock) { + uint16_t config = getNVConfiguration()&(~(0x01<>AT30TSE75x_NVCONFIG_RLCKDWN_BIT)&(0x0001); +} + +/** Set the status of comparator/interrupt mode in non-volatile configuration register + * Warning! Calling this method with true param disables any further modifications of any registers. + * @param registerLockdown false - registers lockdown reset, true - registers lockdown set + */ +void AT30TSE75x::setNVRegisterLockdown(bool registerLockdown) { + uint16_t config = getNVConfiguration()&(~(0x01<>AT30TSE75x_NVCONFIG_NVSD_BIT)&(0x0001); +} + +/** Set the status of device shutdown mode from non-volatile configuration register. + * @param shutdownMode false - device shutdown unset, true - device shutdown set + */ +void AT30TSE75x::setNVShutdownMode(bool shutdownMode) { + uint16_t config = getNVConfiguration()&(~(0x01<>AT30TSE75x_NVCONFIG_NVPOL_BIT)&(0x0001); +} + +/** Set the alert polarity from non-volatile configuration register. + * @param alertPolarity false - alert polarity low, true - alert polarity high + */ +void AT30TSE75x::setNVAlertPolarity(bool alertPolarity) { + uint16_t config = getNVConfiguration()&(~(0x01<>AT30TSE75x_NVCONFIG_NVFT_BIT)&(0x0003); +} + + +/** Set the value of fault tolerance from non-volatile configuration register. + * @param comparatorOrInterrupt false - comparator mode, true - interrupt mode + * @see AT30TSE75x_FAULT_COUNT_1 + * @see AT30TSE75x_FAULT_COUNT_2 + * @see AT30TSE75x_FAULT_COUNT_4 + * @see AT30TSE75x_FAULT_COUNT_6 + */ +void AT30TSE75x::setNVFaultToleranceQueue(uint8_t faultCount) { + uint16_t config = getNVConfiguration()&(~(0x03<>AT30TSE75x_NVCONFIG_NVR_BIT)&(0x0003); +} + +/** Set the conversion resolution from non-volatile configuration register + * @param conversionResolution Conversion resolution setting + * @see AT30TSE75x_RES_9BIT + * @see AT30TSE75x_RES_10BIT + * @see AT30TSE75x_RES_11BIT + * @see AT30TSE75x_RES_12BIT + */ +void AT30TSE75x::setNVConversionResolution(uint8_t conversionResolution) { + uint16_t config = getNVConfiguration()&(~(0x03<>8)&0x01)); + } + else { + eepromDeviceAddress = AT30TSE75x_ADDRESS_SERIAL_EEPROM | ((devAddr&(~0x03))|((address>>8)&0x03)); + } + + byteAddress = 0x00FF&address; + + uint8_t result = 0x00; + + I2Cdev::readByte(eepromDeviceAddress, byteAddress, &result); + + return result; + +} + +/** Write single byte to EEPROM + * @param address Address of byte in EEPROM + * @param value Value to be stored at address + */ +void AT30TSE75x::writeEEPROMByte(uint16_t address, uint8_t value) { + + uint8_t eepromDeviceAddress = 0x00; + uint8_t byteAddress = 0x00; + + if(devType == AT30TSE75x_752) { + eepromDeviceAddress = AT30TSE75x_ADDRESS_SERIAL_EEPROM | devAddr; + } + else if(devType == AT30TSE75x_754) { + eepromDeviceAddress = AT30TSE75x_ADDRESS_SERIAL_EEPROM | ( (devAddr&(~0x01))|((address>>8)&0x01) ); + } + else { + eepromDeviceAddress = AT30TSE75x_ADDRESS_SERIAL_EEPROM | ( (devAddr&(~0x03))|((address>>8)&0x03) ); + } + + byteAddress = 0x00FF&address; + + I2Cdev::writeByte(eepromDeviceAddress, byteAddress, value); + +} + +/** Read entire page from EEPROM + * @param address Address of page in EEPROM (must be aligned to 0 byte in the requested page) + * @param value Pointer to where the data should be stored (must be at least 16 byte array) + */ +void AT30TSE75x::readEEPROMPage(uint16_t address, uint8_t* page) { + + uint8_t eepromDeviceAddress = 0x00; + uint8_t byteAddress = 0x00; + + if(devType == AT30TSE75x_752) { + eepromDeviceAddress = AT30TSE75x_ADDRESS_SERIAL_EEPROM | devAddr; + } + else if(devType == AT30TSE75x_754) { + eepromDeviceAddress = AT30TSE75x_ADDRESS_SERIAL_EEPROM | ((devAddr&(~0x01))|((address>>8)&0x01)); + } + else { + eepromDeviceAddress = AT30TSE75x_ADDRESS_SERIAL_EEPROM | ((devAddr&(~0x03))|((address>>8)&0x03)); + } + + byteAddress = 0x00FF&address; + + bool status = I2Cdev::readBytes(eepromDeviceAddress, byteAddress, 16, page); + +} + +/** Write entire page (16 bytes) to EEPROM + * After writing it is good to sleep for 5-10 ms as the bytes are buffered + * by the device before writing them to EEPROM. + * @param address Address of page in EEPROM (must be aligned to required pages' 0 byte) + * @param page Pointer to array of 16 bytes of data + */ +void AT30TSE75x::writeEEPROMPage(uint16_t address, uint8_t* page) { + + uint8_t eepromDeviceAddress = 0x00; + uint8_t byteAddress = 0x00; + + if(devType == AT30TSE75x_752) { + eepromDeviceAddress = AT30TSE75x_ADDRESS_SERIAL_EEPROM | devAddr; + } + else if(devType == AT30TSE75x_754) { + eepromDeviceAddress = AT30TSE75x_ADDRESS_SERIAL_EEPROM | ((devAddr&(~0x01))|((address>>8)&0x01)); + } + else { + Serial.println("Writing EEPROM page"); + eepromDeviceAddress = AT30TSE75x_ADDRESS_SERIAL_EEPROM | ((devAddr&(~0x03))|((address>>8)&0x03)); + } + + byteAddress = 0x00FF&address; + + I2Cdev::writeBytes(eepromDeviceAddress, byteAddress, 16, page); + +} + + +/** Sets the reversible software write protection + * Please note that the A2-A0 pins must be set to A2=GND, A1=GND, A0=HV(7V~10V) + */ +void AT30TSE75x::setReversibleSoftwareWriteProtect() { + I2Cdev::writeByte(AT30TSE75x_ADDRESS_WRITE_PROTECT|0x1, 0x00, 0x00); +} + +/** Clears the reversible software write protection + * Please note that the A2-A0 pins must be set to A2=GND, A1=VCC, A0=HV(7V~10V) + */ +void AT30TSE75x::clearReversibleSoftwareWriteProtect() { + I2Cdev::writeByte(AT30TSE75x_ADDRESS_WRITE_PROTECT|0x3, 0x00, 0x00); +} + +/** Reset the configuration register and temperature alert limits to default values. + * It won't change the non-volatile register. + */ +void AT30TSE75x::reset() { + setShutdownMode(false); + setComparatorInterruptMode(false); + setAlertPolarity(false); + setFaultToleranceQueue(AT30TSE75x_FAULT_COUNT_1); + setConversionResolution(AT30TSE75x_RES_9BIT); + setOneShotMode(false); + setTempLowLimit(0x4B00); + setTempHighLimit(0x5000); +} + diff --git a/Arduino/AT30TSE75x/AT30TSE75x.h b/Arduino/AT30TSE75x/AT30TSE75x.h new file mode 100644 index 00000000..289fcdf1 --- /dev/null +++ b/Arduino/AT30TSE75x/AT30TSE75x.h @@ -0,0 +1,272 @@ +// I2Cdev library collection - AT30TSE752/754/758 I2C device class header file +// Based on ATMEL AT30TSE75 datasheet, 2013 Rev. Atmel-8751F-DTS-AT30TSE752-754-758-Datasheet_092013 +// [current release date] by Bartosz Kryza +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// 2014-02-16 - initial release + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2014 Bartosz Kryza, Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#ifndef _AT30TSE75x_H_ +#define _AT30TSE75x_H_ + +#include "I2Cdev.h" + + +/** @defgroup devices Defines to distinguish between different AT30TSE752/754/758 variants + * @{ + */ +#define AT30TSE75x_752 1 /*!< ID of x752 variant (2Kb EEPROM) */ +#define AT30TSE75x_754 2 /*!< ID of x754 variant (4Kb EEPROM) */ +#define AT30TSE75x_758 3 /*!< ID of x758 variant (8Kb EEPROM) */ +/** @} */ + +/** @defgroup address Device addresses + * AT30TSE75 has 3 distinct subdevices with different I2C addresses: + * AT30TSE75x consist of 3 devices: + * - Temperature sensor + * - Serial EEPROM + * - Software Write Protection + * each with a separate I2C address. The 3 least significant bits + * of the 7-bit address are specified by wiring pins A2,A1,A0 to GND or VCC. + * The 4 most significant bits are predefined for each subdevice as below: + * @{ + */ +#define AT30TSE75x_ADDRESS_TEMP_SENSOR (0x9<<3) /*!< The 4 MSB of the 7-bit Temperature Sensor subdevice address */ +#define AT30TSE75x_ADDRESS_SERIAL_EEPROM (0xA<<3) /*!< The 4 MSB of the 7-bit Serial EEPROM subdevice address */ +#define AT30TSE75x_ADDRESS_WRITE_PROTECT (0x6<<3) /*!< The 4 MSB of the 7-bit Software Write Protect subdevice address */ + +#define AT30TSE75x_DEFAULT_ADDRESS 0x00 /*!< Assumes that the A2-A0 pins are grounded. */ +/** @} */ + + +/** @defgroup register Register addresses + * @{ + */ +#define AT30TSE75x_RA_TEMPERATURE 0x00 /*!< Address of Temperature register */ +#define AT30TSE75x_RA_CONFIGURATION 0x01 /*!< Address of Configuration register */ +#define AT30TSE75x_RA_TLOW_LIMIT 0x02 /*!< Address of alert temperature low limit */ +#define AT30TSE75x_RA_THIGH_LIMIT 0x03 /*!< Address of alert temperature high limit */ +#define AT30TSE75x_RA_NV_CONFIGURATION 0x11 /*!< Address of Non-volatile Configuration register */ +#define AT30TSE75x_RA_NV_TLOW_LIMIT 0x12 /*!< Address of Non-volatile alert temperature low limit */ +#define AT30TSE75x_RA_NV_THIGH_LIMIT 0x13 /*!< Address of Non-volatile alert temperature high limit */ +/** @} */ + + +/** @defgroup cfgstruct Configuration Register Structure + * @{ + */ +#define AT30TSE75x_CONFIG_NVRBSY_BIT 0 /*!< Configuration register Non-volatile Register Busy (NVRBSY) bit offset */ + +#define AT30TSE75x_CONFIG_RFU_BIT 1 /*!< Configuration register reserved bits segment offset (7 bits) */ +#define AT30TSE75x_CONFIG_RFU_LENGTH 7 + +#define AT30TSE75x_CONFIG_SD_BIT 8 /*!< Configuration register Shutdown mode (SD) bit offset */ + +#define AT30TSE75x_CONFIG_CMPINT_BIT 9 /*!< Configuration register ~Comparator/Interrupt mode bit offset */ + +#define AT30TSE75x_CONFIG_POL_BIT 10 /*!< Configuration register Alert polarity (POL) bit offset */ + +#define AT30TSE75x_CONFIG_FT_BIT 11 /*!< Configuration register alert fault count (FT) value (2 bits) offset */ +#define AT30TSE75x_CONFIG_FT_LENGTH 2 + +#define AT30TSE75x_CONFIG_RES_BIT 13 /*!< Configuration register conversion resolution (RES) value (2 bits) offset */ +#define AT30TSE75x_CONFIG_RES_LENGTH 2 + +#define AT30TSE75x_CONFIG_OS_BIT 15 /*!< Configuration register one shot mode bit offset */ +/** @} */ + + + +/** @defgroup nvcfgstruct Non-volatile Configuration Register Structure + * @{ + */ +#define AT30TSE75x_NVCONFIG_RFU_BIT 0 /*!< Non-volatile configuration register reserved bit offset */ + +#define AT30TSE75x_NVCONFIG_RLCK_BIT 1 /*!< Non-volatile configuration register register lock (RLCK) it offset */ + +#define AT30TSE75x_NVCONFIG_RLCKDWN_BIT 2 /*!< Non-volatile configuration register register lockdown (RLCKDWN) bit offset */ + +#define AT30TSE75x_NVCONFIG_RFU2_BIT 3 /*!< Non-volatile configuration register reserved bit segment offset (4 bits) */ +#define AT30TSE75x_NVCONFIG_RFU2_LENGTH 4 + +#define AT30TSE75x_NVCONFIG_NVSD_BIT 8 /*!< Non-volatile configuration register shutdown (NVSD) bit offset */ + +#define AT30TSE75x_NVCONFIG_NVCMPINT_BIT 9 /*!< Non-volatile configuration register ~comparator/interrupt (NVCMPINT) bit offset */ + +#define AT30TSE75x_NVCONFIG_NVPOL_BIT 10 /*!< Non-volatile configuration register alert polarity (NVPOL) bit offset */ + +#define AT30TSE75x_NVCONFIG_NVFT_BIT 11 /*!< Non-volatile configuration register alert fault count (NVFT) value offset (2 bits) */ +#define AT30TSE75x_NVCONFIG_NVFT_LENGTH 2 + +#define AT30TSE75x_NVCONFIG_NVR_BIT 13 /*!< Non-volatile configuration register resolution (NVR) value offset (2 bits) */ +#define AT30TSE75x_NVCONFIG_NVR_LENGTH 2 +/** @} */ + + + +/** @defgroup resolution Conversion resolution parameters + * Conversion resolution (9, 10, 11, or 12-bits) impacts both the resolution + * step (from 0.0625C to 0.5C) and conversion time (25ms, 50ms, 100ms, 200ms). + * @{ + */ +#define AT30TSE75x_RES_9BIT 0x00 /*!< 9-bit resolution configuration register value */ +#define AT30TSE75x_RES_10BIT 0x01 /*!< 10-bit resolution configuration register value */ +#define AT30TSE75x_RES_11BIT 0x02 /*!< 11-bit resolution configuration register value */ +#define AT30TSE75x_RES_12BIT 0x03 /*!< 12-bit resolution configuration register value */ + +#define AT30TSE75x_STEP_9BIT 0.5000 /*!< 9-bit resolution step */ +#define AT30TSE75x_STEP_10BIT 0.2500 /*!< 10-bit resolution step */ +#define AT30TSE75x_STEP_11BIT 0.1250 /*!< 11-bit resolution step */ +#define AT30TSE75x_STEP_12BIT 0.0625 /*!< 12-bit resolution step */ + +#define AT30TSE75x_CONVTIME_MS_9BIT 25 /*!< 9-bit resolution conversion time (ms) */ +#define AT30TSE75x_CONVTIME_MS_10BIT 50 /*!< 10-bit resolution conversion time (ms) */ +#define AT30TSE75x_CONVTIME_MS_11BIT 100 /*!< 11-bit resolution conversion time (ms) */ +#define AT30TSE75x_CONVTIME_MS_12BIT 200 /*!< 12-bit resolution conversion time (ms) */ +/** @} */ + +/** @defgroup resolution Conversion resolution parameters + * Conversion resolution (9, 10, 11, or 12-bits) impacts both the resolution + * step (from 0.0625C to 0.5C) and conversion time (25ms, 50ms, 100ms, 200ms). + * @{ + */ +#define AT30TSE75x_FAULT_COUNT_1 0x00 /*!< Alert fault count value - 1 fault */ +#define AT30TSE75x_FAULT_COUNT_2 0x01 /*!< Alert fault count value - 2 consecutive faults */ +#define AT30TSE75x_FAULT_COUNT_4 0x02 /*!< Alert fault count value - 4 consecutive faults */ +#define AT30TSE75x_FAULT_COUNT_6 0x03 /*!< Alert fault count value - 6 consecutive faults */ +/** @} */ + + + +class AT30TSE75x { + public: + + AT30TSE75x(); + + AT30TSE75x(uint8_t address, uint8_t deviceType); + + void initialize(); + bool testConnection(); + + + float getTemperatureCelcius(); + float getTemperatureFahrenheit(); + uint16_t getTemperatureRaw(); + + + // CONFIGURATION register + uint16_t getConfiguration(); + + bool getNVRBusy(); + + bool getShutdownMode(); + void setShutdownMode(bool shutdownMode); + + bool getComparatorInterruptMode(); + void setComparatorInterruptMode(bool comparatorOrInterrup); + + bool getAlertPolarity(); + void setAlertPolarity(bool alertPolarity); + + uint8_t getFaultToleranceQueue(); + void setFaultToleranceQueue(uint8_t faultCount); + + uint8_t getConversionResolution(); + void setConversionResolution(uint8_t conversionResolution); + + bool getOneShotMode(); + void setOneShotMode(bool oneShotMode); + + + // Temperature alert low limit register + void setTempLowLimit(uint16_t lowLimit); + uint16_t getTempLowLimit(); + + + // Temperature alert high limit register + void setTempHighLimit(uint16_t highLimit); + uint16_t getTempHighLimit(); + + + // Non-volatile Configuration register + uint16_t getNVConfiguration(); + + bool getNVComparatorInterruptMode(); + void setNVComparatorInterruptMode(bool comparatorOrInterrup); + + bool getNVRegisterLock(); + void setNVRegisterLock(bool registerLock); + + bool getNVRegisterLockdown(); + void setNVRegisterLockdown(bool registerLockdown); + + bool getNVShutdownMode(); + void setNVShutdownMode(bool shutdownMode); + + bool getNVAlertPolarity(); + void setNVAlertPolarity(bool alertPolarity); + + uint8_t getNVFaultToleranceQueue(); + void setNVFaultToleranceQueue(uint8_t faultCount); + + uint8_t geNVConversionResolution(); + void setNVConversionResolution(uint8_t conversionResolution); + + + // Temperature alert low limit non-volatile register + void setNVTempLowLimit(uint16_t lowLimit); + uint16_t getNVTempLowLimit(); + + + // Temperature alert high limit non-volatile register + void setNVTempHighLimit(uint16_t highLimit); + uint16_t getNVTempHighLimit(); + + + // EEPROM + uint8_t readEEPROMByte(uint16_t address); + void writeEEPROMByte(uint16_t address, uint8_t value); + + void readEEPROMPage(uint16_t address, uint8_t* page); + void writeEEPROMPage(uint16_t address, uint8_t* page); + + + // Software write protect + void setReversibleSoftwareWriteProtect(); + void clearReversibleSoftwareWriteProtect(); + + // Reset Non-volatile config to default values + void reset(); + + + private: + uint8_t devAddr; + uint8_t devType; + uint16_t buffer[6]; +}; + +#endif /* _AT30TSE75x_H_ */ diff --git a/Arduino/AT30TSE75x/Examples/AT30TSE75x_basic/AT30TSE75x_basic.ino b/Arduino/AT30TSE75x/Examples/AT30TSE75x_basic/AT30TSE75x_basic.ino new file mode 100644 index 00000000..adf617b7 --- /dev/null +++ b/Arduino/AT30TSE75x/Examples/AT30TSE75x_basic/AT30TSE75x_basic.ino @@ -0,0 +1,113 @@ +// I2Cdev library collection - AT30TSE752/754/758 I2C device class header file +// Based on ATMEL AT30TSE75 datasheet, 2013 Rev. Atmel-8751F-DTS-AT30TSE752-754-758-Datasheet_092013 +// [current release date] by Bartosz Kryza +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// 2014-02-16 - initial release + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2014 Bartosz Kryza, Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#include +#include "AT30TSE75x.h" + +// +// Initialize the sensor with A2-A0 pins grounded +// and variant with 8Kb of EEPROM memory. +// +AT30TSE75x tempSensor(0x00, AT30TSE75x_758); + +void setup() { + + // + // Initialize Wire and Serial + // + Wire.begin(); + Serial.begin(9600); + Serial.println("Initializing temp sensor"); + + // + // Initialize the sensor with 12 bit conversion resolution + // + tempSensor.initialize(); + tempSensor.setConversionResolution(AT30TSE75x_RES_12BIT); + +} + + + +void loop() { + + // + // Read Celcius temperature + // + float tempValue = tempSensor.getTemperatureCelcius(); + Serial.print("Current temperature: "); + Serial.print(tempValue); + Serial.println("C"); + + // + // Read Fahrenheit temperature + // + tempValue = tempSensor.getTemperatureFahrenheit(); + Serial.print("Current temperature: "); + Serial.print(tempValue); + Serial.println("F"); + + // + // Write/read EEPROM byte + // + uint8_t page = 16; + uint8_t byteInPage = 5; + tempSensor.writeEEPROMByte(16*page+byteInPage, 13); + uint8_t eepromValue = tempSensor.readEEPROMByte(16*page+byteInPage); + Serial.print("Read EEPROM byte: "); + Serial.println(eepromValue); + + // + // Write/read EEPROM page + // + uint8_t pageBytes[16] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}; + page = 3; + tempSensor.writeEEPROMPage(16*page, pageBytes); + + // AT30TSE buffers pages before writing them to the EEPROM thus + // delay is necessary between writing and reading a page from EEPROM + // to ensure we get new values + delay(10); + + uint8_t pageBytesRead[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + + tempSensor.readEEPROMPage(16*page, pageBytesRead); + + Serial.print("Read EEPROM page: "); + for(int i=0; i<16; i++) { + Serial.print(pageBytesRead[i]); Serial.print(" "); + } + Serial.println(""); + + delay(2000); + +} From 372078c1a2fd8e70f8405a16f2321cf72e7ea7c9 Mon Sep 17 00:00:00 2001 From: Bartosz Kryza Date: Tue, 18 Feb 2014 01:02:21 +0100 Subject: [PATCH 010/335] Updates release dates --- Arduino/AT30TSE75x/AT30TSE75x.h | 2 +- .../AT30TSE75x/Examples/AT30TSE75x_basic/AT30TSE75x_basic.ino | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Arduino/AT30TSE75x/AT30TSE75x.h b/Arduino/AT30TSE75x/AT30TSE75x.h index 289fcdf1..db0f1a79 100644 --- a/Arduino/AT30TSE75x/AT30TSE75x.h +++ b/Arduino/AT30TSE75x/AT30TSE75x.h @@ -1,6 +1,6 @@ // I2Cdev library collection - AT30TSE752/754/758 I2C device class header file // Based on ATMEL AT30TSE75 datasheet, 2013 Rev. Atmel-8751F-DTS-AT30TSE752-754-758-Datasheet_092013 -// [current release date] by Bartosz Kryza +// 2014-02-16 by Bartosz Kryza // Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib // // Changelog: diff --git a/Arduino/AT30TSE75x/Examples/AT30TSE75x_basic/AT30TSE75x_basic.ino b/Arduino/AT30TSE75x/Examples/AT30TSE75x_basic/AT30TSE75x_basic.ino index adf617b7..d9480606 100644 --- a/Arduino/AT30TSE75x/Examples/AT30TSE75x_basic/AT30TSE75x_basic.ino +++ b/Arduino/AT30TSE75x/Examples/AT30TSE75x_basic/AT30TSE75x_basic.ino @@ -1,6 +1,6 @@ // I2Cdev library collection - AT30TSE752/754/758 I2C device class header file // Based on ATMEL AT30TSE75 datasheet, 2013 Rev. Atmel-8751F-DTS-AT30TSE752-754-758-Datasheet_092013 -// [current release date] by Bartosz Kryza +// 2014-02-16 by Bartosz Kryza // Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib // // Changelog: From fff50eb6c64135862b8e3c26029c72d859dbad54 Mon Sep 17 00:00:00 2001 From: diegob94 Date: Mon, 7 Apr 2014 22:27:36 -0400 Subject: [PATCH 011/335] updated L3G4200D::getAngularVelocityN() functions I was trying to use this library but the raw values from the gyro where always positive, so I check the code and I found two mayor problems, first this call "if (getEndianMode() == L3G4200D_BIG_ENDIAN) {" re-use the buffer so the code below (where the function actually returns gyro values) produces values that are obiusly wrong, and the second thing I notice was that the I2Cdev::readBytes call just return the L3G4200D_RA_OUT_N_L register twice (L3G4200D_RA_OUT_N_H is was not being readed), so just half of the data was being received, so I try to fix it and it works, so if you could take a look and make something better it would be greate for people who are trying to use this gyro with this library. --- Arduino/L3G4200D/L3G4200D.cpp | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/Arduino/L3G4200D/L3G4200D.cpp b/Arduino/L3G4200D/L3G4200D.cpp index dd7b0326..04e10c5a 100644 --- a/Arduino/L3G4200D/L3G4200D.cpp +++ b/Arduino/L3G4200D/L3G4200D.cpp @@ -950,11 +950,14 @@ void L3G4200D::getAngularVelocity(int16_t* x, int16_t* y, int16_t* z) { * @see L3G4200D_RA_OUT_X_H */ int16_t L3G4200D::getAngularVelocityX() { - I2Cdev::readBytes(devAddr, L3G4200D_RA_OUT_X_L, 2, buffer); + uint8_t bufferL[6]; + uint8_t bufferH[6]; + I2Cdev::readBytes(devAddr, L3G4200D_RA_OUT_X_L, 1, bufferL); + I2Cdev::readBytes(devAddr, L3G4200D_RA_OUT_X_H, 1, bufferH); if (getEndianMode() == L3G4200D_BIG_ENDIAN) { - return (((int16_t)buffer[1]) << 8) | buffer[0]; + return (((int16_t) bufferL[0]) << 8) | bufferH[0]; } else { - return (((int16_t)buffer[0]) << 8) | buffer[1]; + return (((int16_t) bufferH[0]) << 8) | bufferL[0]; } } @@ -964,11 +967,14 @@ int16_t L3G4200D::getAngularVelocityX() { * @see L3G4200D_RA_OUT_Y_H */ int16_t L3G4200D::getAngularVelocityY() { - I2Cdev::readBytes(devAddr, L3G4200D_RA_OUT_Y_L, 2, buffer); + uint8_t bufferL[6]; + uint8_t bufferH[6]; + I2Cdev::readBytes(devAddr, L3G4200D_RA_OUT_Y_L, 1, bufferL); + I2Cdev::readBytes(devAddr, L3G4200D_RA_OUT_Y_H, 1, bufferH); if (getEndianMode() == L3G4200D_BIG_ENDIAN) { - return (((int16_t)buffer[1]) << 8) | buffer[0]; + return (((int16_t) bufferL[0]) << 8) | bufferH[0]; } else { - return (((int16_t)buffer[0]) << 8) | buffer[1]; + return (((int16_t) bufferH[0]) << 8) | bufferL[0]; } } @@ -978,11 +984,14 @@ int16_t L3G4200D::getAngularVelocityY() { * @see L3G4200D_RA_OUT_Z_H */ int16_t L3G4200D::getAngularVelocityZ() { - I2Cdev::readBytes(devAddr, L3G4200D_RA_OUT_Z_L, 2, buffer); + uint8_t bufferL[6]; + uint8_t bufferH[6]; + I2Cdev::readBytes(devAddr, L3G4200D_RA_OUT_Z_L, 1, bufferL); + I2Cdev::readBytes(devAddr, L3G4200D_RA_OUT_Z_H, 1, bufferH); if (getEndianMode() == L3G4200D_BIG_ENDIAN) { - return (((int16_t)buffer[1]) << 8) | buffer[0]; + return (((int16_t) bufferL[0]) << 8) | bufferH[0]; } else { - return (((int16_t)buffer[0]) << 8) | buffer[1]; + return (((int16_t) bufferH[0]) << 8) | bufferL[0]; } } From 30d180db0bdf6517feb87c3c019d84eebdc4f0e5 Mon Sep 17 00:00:00 2001 From: diegob94 Date: Mon, 7 Apr 2014 22:31:23 -0400 Subject: [PATCH 012/335] Update README --- README | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README b/README index 5eb328ba..095c8c2f 100644 --- a/README +++ b/README @@ -1,3 +1,5 @@ +L3G4200D gyro fix! + ============================================================================ Note: for details about this project, please visit: http://www.i2cdevlib.com ============================================================================ @@ -12,4 +14,4 @@ Documentation for each class is created using Doxygen-style comments placed in e To use the library, just place the I2Cdev .cpp/.h source files and any device library .cpp/.h source files in the same folder as your sketch (or a suitable place relative to your avr-gcc project), and include just the device library headers that you need. Arduino users will also need to include in your main sketch source file. Create a single device object (e.g. "ADXL345 accel();"), place any appropriate init function calls in your setup() routine (e.g. "accel.initialize();"), and off you go! See the example sketches inside many of the device class directories for reference. -Want a library for a device that isn't up on the repository? Request it, or fork the code and contribute! Better yet, send me a device on a breakout board to test the code during development. No guarantees on how fast I can get it done, but I'd love to make this the biggest consistent and well-documented I2C device library around. \ No newline at end of file +Want a library for a device that isn't up on the repository? Request it, or fork the code and contribute! Better yet, send me a device on a breakout board to test the code during development. No guarantees on how fast I can get it done, but I'd love to make this the biggest consistent and well-documented I2C device library around. From 95ddd29af0ab302e098fd4d862b7166899be34c9 Mon Sep 17 00:00:00 2001 From: ryanneve Date: Sat, 12 Apr 2014 16:38:10 -0400 Subject: [PATCH 013/335] Implement secondstime() already in header. secondstime() is in DS1307.h, but wasn't implemented here. I'm a very new C++ programmer, so just make sure I haven't messed up anything with unixtime() converting a long into a uint32_t. (?) --- Arduino/DS1307/DS1307.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Arduino/DS1307/DS1307.cpp b/Arduino/DS1307/DS1307.cpp index 7e125c58..87930e35 100644 --- a/Arduino/DS1307/DS1307.cpp +++ b/Arduino/DS1307/DS1307.cpp @@ -456,11 +456,13 @@ void DS1307::setDateTime24(uint16_t year, uint8_t month, uint8_t day, uint8_t ho } uint32_t DateTime::unixtime(void) const { + return secondstime() + SECONDS_FROM_1970_TO_2000; + } + + long DateTime::secondstime(void) const { uint32_t t; uint16_t days = date2days(yOff, m, d); - t = time2long(days, hh, mm, ss); - t += SECONDS_FROM_1970_TO_2000; // seconds from 1970 to 2000 - + t = time2long(days, hh, mm, ss); return t; } #endif From bbc79c19d6fa2f579e68d71845807116bebcbfc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frank=20B=C3=B6sing?= Date: Wed, 23 Apr 2014 20:14:18 +0200 Subject: [PATCH 014/335] Updated Register Map Update Register Map (see RM-MPU-6000A-00v4.2pdf) --- Arduino/MPU6050/MPU6050.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Arduino/MPU6050/MPU6050.h b/Arduino/MPU6050/MPU6050.h index 7761de8f..998526e3 100644 --- a/Arduino/MPU6050/MPU6050.h +++ b/Arduino/MPU6050/MPU6050.h @@ -67,7 +67,11 @@ THE SOFTWARE. #define MPU6050_RA_YA_OFFS_H 0x08 //[15:0] YA_OFFS #define MPU6050_RA_YA_OFFS_L_TC 0x09 #define MPU6050_RA_ZA_OFFS_H 0x0A //[15:0] ZA_OFFS -#define MPU6050_RA_ZA_OFFS_L_TC 0x0B +#define MPU6050_RA_ZA_OFFS_L_TC 0x0B +#define MPU6050_RA_SELF_TEST_X 0x0D //[7:5] XA_TEST[4-2], [4:0] XG_TEST[4-0] +#define MPU6050_RA_SELF_TEST_Y 0x0E //[7:5] YA_TEST[4-2], [4:0] YG_TEST[4-0] +#define MPU6050_RA_SELF_TEST_Z 0x0F //[7:5] ZA_TEST[4-2], [4:0] ZG_TEST[4-0] +#define MPU6050_RA_SELF_TEST_A 0x10 //[5:4] XA_TEST[1-0], [3:2] YA_TEST[1-0], [1:0] ZA_TEST[1-0] #define MPU6050_RA_XG_OFFS_USRH 0x13 //[15:0] XG_OFFS_USR #define MPU6050_RA_XG_OFFS_USRL 0x14 #define MPU6050_RA_YG_OFFS_USRH 0x15 //[15:0] YG_OFFS_USR From 852f56aec5e08e7ddada204ce5fc075ee0283192 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frank=20B=C3=B6sing?= Date: Wed, 23 Apr 2014 21:24:30 +0200 Subject: [PATCH 015/335] remove warnings progBuffer not initialized --- Arduino/MPU6050/MPU6050.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Arduino/MPU6050/MPU6050.cpp b/Arduino/MPU6050/MPU6050.cpp index 3f531efc..001af692 100644 --- a/Arduino/MPU6050/MPU6050.cpp +++ b/Arduino/MPU6050/MPU6050.cpp @@ -2968,7 +2968,7 @@ bool MPU6050::writeMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t b setMemoryStartAddress(address); uint8_t chunkSize; uint8_t *verifyBuffer; - uint8_t *progBuffer; + uint8_t *progBuffer=0; uint16_t i; uint8_t j; if (verify) verifyBuffer = (uint8_t *)malloc(MPU6050_DMP_MEMORY_CHUNK_SIZE); @@ -3043,7 +3043,8 @@ bool MPU6050::writeProgMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8 return writeMemoryBlock(data, dataSize, bank, address, verify, true); } bool MPU6050::writeDMPConfigurationSet(const uint8_t *data, uint16_t dataSize, bool useProgMem) { - uint8_t *progBuffer, success, special; + uint8_t *progBuffer = 0; + uint8_t success, special; uint16_t i, j; if (useProgMem) { progBuffer = (uint8_t *)malloc(8); // assume 8-byte blocks, realloc later if necessary From a934419051c4e13244815c2f46848eb5c3d8ad3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frank=20B=C3=B6sing?= Date: Wed, 23 Apr 2014 22:39:39 +0200 Subject: [PATCH 016/335] Added functions to get selftest values Added functions to get selftest values --- Arduino/MPU6050/MPU6050.cpp | 60 ++++++++++++++++++++++++++++++++++++- Arduino/MPU6050/MPU6050.h | 42 ++++++++++++++++++++++---- 2 files changed, 95 insertions(+), 7 deletions(-) diff --git a/Arduino/MPU6050/MPU6050.cpp b/Arduino/MPU6050/MPU6050.cpp index 001af692..daa562ec 100644 --- a/Arduino/MPU6050/MPU6050.cpp +++ b/Arduino/MPU6050/MPU6050.cpp @@ -253,6 +253,64 @@ void MPU6050::setFullScaleGyroRange(uint8_t range) { I2Cdev::writeBits(devAddr, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, range); } +// SELF TEST FACTORY TRIM VALUES + +/** Get self-test factory trim value for accelerometer X axis. + * @return factory trim value + * @see MPU6050_RA_SELF_TEST_X + */ +uint8_t MPU6050::getAccelXSelfTestFactoryTrim() { + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_X, &buffer[0]); + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_A, &buffer[1]); + return (buffer[0]>>3) || ((buffer[1]>>4) & 0x03); +} + +/** Get self-test factory trim value for accelerometer Y axis. + * @return factory trim value + * @see MPU6050_RA_SELF_TEST_Y + */ +uint8_t MPU6050::getAccelYSelfTestFactoryTrim() { + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_Y, &buffer[0]); + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_A, &buffer[1]); + return (buffer[0]>>3) || ((buffer[1]>>2) & 0x03); +} + +/** Get self-test factory trim value for accelerometer Z axis. + * @return factory trim value + * @see MPU6050_RA_SELF_TEST_Z + */ +uint8_t MPU6050::getAccelZSelfTestFactoryTrim() { + I2Cdev::readBytes(devAddr, MPU6050_RA_SELF_TEST_Z, 2, buffer); + return (buffer[0]>>3) || (buffer[1] & 0x03); +} + +/** Get self-test factory trim value for gyro X axis. + * @return factory trim value + * @see MPU6050_RA_SELF_TEST_X + */ +uint8_t MPU6050::getGyroXSelfTestFactoryTrim() { + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_X, buffer); + return (buffer[0] & 0x1F); +} + +/** Get self-test factory trim value for gyro Y axis. + * @return factory trim value + * @see MPU6050_RA_SELF_TEST_Y + */ +uint8_t MPU6050::getGyroYSelfTestFactoryTrim() { + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_Y, buffer); + return (buffer[0] & 0x1F); +} + +/** Get self-test factory trim value for gyro Z axis. + * @return factory trim value + * @see MPU6050_RA_SELF_TEST_Z + */ +uint8_t MPU6050::getGyroZSelfTestFactoryTrim() { + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_Z, buffer); + return (buffer[0] & 0x1F); +} + // ACCEL_CONFIG register /** Get self-test enabled setting for accelerometer X axis. @@ -3044,7 +3102,7 @@ bool MPU6050::writeProgMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8 } bool MPU6050::writeDMPConfigurationSet(const uint8_t *data, uint16_t dataSize, bool useProgMem) { uint8_t *progBuffer = 0; - uint8_t success, special; + uint8_t success, special; uint16_t i, j; if (useProgMem) { progBuffer = (uint8_t *)malloc(8); // assume 8-byte blocks, realloc later if necessary diff --git a/Arduino/MPU6050/MPU6050.h b/Arduino/MPU6050/MPU6050.h index 998526e3..c3fa7e18 100644 --- a/Arduino/MPU6050/MPU6050.h +++ b/Arduino/MPU6050/MPU6050.h @@ -41,14 +41,15 @@ THE SOFTWARE. // supporting link: http://forum.arduino.cc/index.php?&topic=143444.msg1079517#msg1079517 // also: http://forum.arduino.cc/index.php?&topic=141571.msg1062899#msg1062899s + #ifndef __arm__ #include #else -#define PROGMEM /* empty */ -#define pgm_read_byte(x) (*(x)) -#define pgm_read_word(x) (*(x)) -#define pgm_read_float(x) (*(x)) -#define PSTR(STR) STR +//#define PROGMEM /* empty */ +//#define pgm_read_byte(x) (*(x)) +//#define pgm_read_word(x) (*(x)) +//#define pgm_read_float(x) (*(x)) +//#define PSTR(STR) STR #endif @@ -67,7 +68,7 @@ THE SOFTWARE. #define MPU6050_RA_YA_OFFS_H 0x08 //[15:0] YA_OFFS #define MPU6050_RA_YA_OFFS_L_TC 0x09 #define MPU6050_RA_ZA_OFFS_H 0x0A //[15:0] ZA_OFFS -#define MPU6050_RA_ZA_OFFS_L_TC 0x0B +#define MPU6050_RA_ZA_OFFS_L_TC 0x0B #define MPU6050_RA_SELF_TEST_X 0x0D //[7:5] XA_TEST[4-2], [4:0] XG_TEST[4-0] #define MPU6050_RA_SELF_TEST_Y 0x0E //[7:5] YA_TEST[4-2], [4:0] YG_TEST[4-0] #define MPU6050_RA_SELF_TEST_Z 0x0F //[7:5] ZA_TEST[4-2], [4:0] ZG_TEST[4-0] @@ -171,6 +172,26 @@ THE SOFTWARE. #define MPU6050_RA_FIFO_R_W 0x74 #define MPU6050_RA_WHO_AM_I 0x75 +#define MPU6050_SELF_TEST_XA_1_BIT 0x07 +#define MPU6050_SELF_TEST_XA_1_LENGTH 0x03 +#define MPU6050_SELF_TEST_XA_2_BIT 0x05 +#define MPU6050_SELF_TEST_XA_2_LENGTH 0x02 +#define MPU6050_SELF_TEST_YA_1_BIT 0x07 +#define MPU6050_SELF_TEST_YA_1_LENGTH 0x03 +#define MPU6050_SELF_TEST_YA_2_BIT 0x03 +#define MPU6050_SELF_TEST_YA_2_LENGTH 0x02 +#define MPU6050_SELF_TEST_ZA_1_BIT 0x07 +#define MPU6050_SELF_TEST_ZA_1_LENGTH 0x03 +#define MPU6050_SELF_TEST_ZA_2_BIT 0x01 +#define MPU6050_SELF_TEST_ZA_2_LENGTH 0x02 + +#define MPU6050_SELF_TEST_XG_1_BIT 0x04 +#define MPU6050_SELF_TEST_XG_1_LENGTH 0x05 +#define MPU6050_SELF_TEST_YG_1_BIT 0x04 +#define MPU6050_SELF_TEST_YG_1_LENGTH 0x05 +#define MPU6050_SELF_TEST_ZG_1_BIT 0x04 +#define MPU6050_SELF_TEST_ZG_1_LENGTH 0x05 + #define MPU6050_TC_PWR_MODE_BIT 7 #define MPU6050_TC_OFFSET_BIT 6 #define MPU6050_TC_OFFSET_LENGTH 6 @@ -438,6 +459,15 @@ class MPU6050 { uint8_t getFullScaleGyroRange(); void setFullScaleGyroRange(uint8_t range); + // SELF_TEST registers + uint8_t getAccelXSelfTestFactoryTrim(); + uint8_t getAccelYSelfTestFactoryTrim(); + uint8_t getAccelZSelfTestFactoryTrim(); + + uint8_t getGyroXSelfTestFactoryTrim(); + uint8_t getGyroYSelfTestFactoryTrim(); + uint8_t getGyroZSelfTestFactoryTrim(); + // ACCEL_CONFIG register bool getAccelXSelfTest(); void setAccelXSelfTest(bool enabled); From e7436dedea465834cc440f88c4e5c882e31c5cfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frank=20B=C3=B6sing?= Date: Thu, 24 Apr 2014 08:12:51 +0200 Subject: [PATCH 017/335] typos --- Arduino/MPU6050/MPU6050.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Arduino/MPU6050/MPU6050.cpp b/Arduino/MPU6050/MPU6050.cpp index daa562ec..079e7fdd 100644 --- a/Arduino/MPU6050/MPU6050.cpp +++ b/Arduino/MPU6050/MPU6050.cpp @@ -262,7 +262,7 @@ void MPU6050::setFullScaleGyroRange(uint8_t range) { uint8_t MPU6050::getAccelXSelfTestFactoryTrim() { I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_X, &buffer[0]); I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_A, &buffer[1]); - return (buffer[0]>>3) || ((buffer[1]>>4) & 0x03); + return (buffer[0]>>3) | ((buffer[1]>>4) & 0x03); } /** Get self-test factory trim value for accelerometer Y axis. @@ -272,7 +272,7 @@ uint8_t MPU6050::getAccelXSelfTestFactoryTrim() { uint8_t MPU6050::getAccelYSelfTestFactoryTrim() { I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_Y, &buffer[0]); I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_A, &buffer[1]); - return (buffer[0]>>3) || ((buffer[1]>>2) & 0x03); + return (buffer[0]>>3) | ((buffer[1]>>2) & 0x03); } /** Get self-test factory trim value for accelerometer Z axis. @@ -281,7 +281,7 @@ uint8_t MPU6050::getAccelYSelfTestFactoryTrim() { */ uint8_t MPU6050::getAccelZSelfTestFactoryTrim() { I2Cdev::readBytes(devAddr, MPU6050_RA_SELF_TEST_Z, 2, buffer); - return (buffer[0]>>3) || (buffer[1] & 0x03); + return (buffer[0]>>3) | (buffer[1] & 0x03); } /** Get self-test factory trim value for gyro X axis. From 4d6cef63cfaf778628fd17aaf38ec17d4a0aa9b3 Mon Sep 17 00:00:00 2001 From: Chris Dearman Date: Mon, 23 Jun 2014 00:40:47 -0700 Subject: [PATCH 018/335] Set new mode immediately in HMC5843::setMode and HMC5883L::setMode --- Arduino/HMC5843/HMC5843.cpp | 2 +- Arduino/HMC5883L/HMC5883L.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Arduino/HMC5843/HMC5843.cpp b/Arduino/HMC5843/HMC5843.cpp index f1ff3a8d..a31ea5aa 100644 --- a/Arduino/HMC5843/HMC5843.cpp +++ b/Arduino/HMC5843/HMC5843.cpp @@ -227,7 +227,7 @@ void HMC5843::setMode(uint8_t newMode) { // use this method to guarantee that bits 7-2 are set to zero, which is a // requirement specified in the datasheet; it's actually more efficient than // using the I2Cdev.writeBits method - I2Cdev::writeByte(devAddr, HMC5843_RA_MODE, mode << (HMC5843_MODEREG_BIT - HMC5843_MODEREG_LENGTH + 1)); + I2Cdev::writeByte(devAddr, HMC5843_RA_MODE, newMode << (HMC5843_MODEREG_BIT - HMC5843_MODEREG_LENGTH + 1)); mode = newMode; // track to tell if we have to clear bit 7 after a read } diff --git a/Arduino/HMC5883L/HMC5883L.cpp b/Arduino/HMC5883L/HMC5883L.cpp index 7fad0462..29d8fb56 100644 --- a/Arduino/HMC5883L/HMC5883L.cpp +++ b/Arduino/HMC5883L/HMC5883L.cpp @@ -250,7 +250,7 @@ void HMC5883L::setMode(uint8_t newMode) { // use this method to guarantee that bits 7-2 are set to zero, which is a // requirement specified in the datasheet; it's actually more efficient than // using the I2Cdev.writeBits method - I2Cdev::writeByte(devAddr, HMC5883L_RA_MODE, mode << (HMC5883L_MODEREG_BIT - HMC5883L_MODEREG_LENGTH + 1)); + I2Cdev::writeByte(devAddr, HMC5883L_RA_MODE, newMode << (HMC5883L_MODEREG_BIT - HMC5883L_MODEREG_LENGTH + 1)); mode = newMode; // track to tell if we have to clear bit 7 after a read } From f7c1e22d7e54eb2f19d9fba46a40ff1cbdff95d3 Mon Sep 17 00:00:00 2001 From: whatnick Date: Thu, 4 Sep 2014 11:29:43 +0930 Subject: [PATCH 019/335] Change 9 Axis gyro offset method calls Changed to match new method names --- Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h b/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h index 14e280c0..e21c3e37 100644 --- a/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h +++ b/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h @@ -457,14 +457,14 @@ uint8_t MPU6050::dmpInitialize() { setOTPBankValid(false); DEBUG_PRINTLN(F("Setting X/Y/Z gyro offsets to previous values...")); - setXGyroOffset(xgOffset); - setYGyroOffset(ygOffset); - setZGyroOffset(zgOffset); - - DEBUG_PRINTLN(F("Setting X/Y/Z gyro user offsets to zero...")); - setXGyroOffsetUser(0); - setYGyroOffsetUser(0); - setZGyroOffsetUser(0); + setXGyroOffsetTC(xgOffset); + setYGyroOffsetTC(ygOffset); + setZGyroOffsetTC(zgOffset); + + //DEBUG_PRINTLN(F("Setting X/Y/Z gyro user offsets to zero...")); + //setXGyroOffset(0); + //setYGyroOffset(0); + //setZGyroOffset(0); DEBUG_PRINTLN(F("Writing final memory update 1/19 (function unknown)...")); uint8_t dmpUpdate[16], j; From 7cf631e6757309f37e388b64323918960e6a1a54 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Thu, 25 Sep 2014 14:35:27 +0300 Subject: [PATCH 020/335] PlatformIO-based manifest file Web: http://platformio.ikravets.com/#!/lib/show/i2cdevlib-Arduino-i2cdev Docs: http://docs.platformio.ikravets.com/en/latest/librarymanager/index.html --- Arduino/I2Cdev/library.json | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 Arduino/I2Cdev/library.json diff --git a/Arduino/I2Cdev/library.json b/Arduino/I2Cdev/library.json new file mode 100644 index 00000000..fc7a8992 --- /dev/null +++ b/Arduino/I2Cdev/library.json @@ -0,0 +1,11 @@ +{ + "name": "i2cdevlib-Arduino-i2cdev", + "keywords": "i2cdevlib, i2c", + "description": "The I2C Device Library (i2cdevlib) is a collection of uniform and well-documented classes to provide simple and intuitive interfaces to I2C devices.", + "include": "Arduino/I2Cdev", + "repository": + { + "type": "git", + "url": "https://github.com/jrowberg/i2cdevlib.git" + } +} From 9428f7e5c4760e5c4c27fe68011efb01784c7bfa Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Thu, 25 Sep 2014 14:36:48 +0300 Subject: [PATCH 021/335] PlatformIO-based manifest file Web: http://platformio.ikravets.com/#!/lib/show/i2cdevlib-Arduino-AK8975 Docs: http://docs.platformio.ikravets.com/en/latest/librarymanager/index.html --- Arduino/AK8975/library.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 Arduino/AK8975/library.json diff --git a/Arduino/AK8975/library.json b/Arduino/AK8975/library.json new file mode 100644 index 00000000..b576bcc7 --- /dev/null +++ b/Arduino/AK8975/library.json @@ -0,0 +1,15 @@ +{ + "name": "i2cdevlib-Arduino-AK8975", + "keywords": "i2cdevlib, i2c, ak8975, compass, sensor", + "description": "AK8975 is 3-axis electronic compass IC with high sensitive Hall sensor technology", + "include": "Arduino/AK8975", + "repository": + { + "type": "git", + "url": "https://github.com/jrowberg/i2cdevlib.git" + }, + "dependencies": + [ + "i2cdevlib-Arduino-i2cdev" + ] +} From 3faa16b1858822fb6d808d44840289c1847bc92e Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Sat, 25 Oct 2014 17:05:19 +0300 Subject: [PATCH 022/335] Avoid trademark issues with library name Added frameworks and platforms fields --- Arduino/I2Cdev/library.json | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Arduino/I2Cdev/library.json b/Arduino/I2Cdev/library.json index fc7a8992..d4560960 100644 --- a/Arduino/I2Cdev/library.json +++ b/Arduino/I2Cdev/library.json @@ -1,11 +1,13 @@ { - "name": "i2cdevlib-Arduino-i2cdev", + "name": "I2Cdevlib-Core", "keywords": "i2cdevlib, i2c", - "description": "The I2C Device Library (i2cdevlib) is a collection of uniform and well-documented classes to provide simple and intuitive interfaces to I2C devices.", + "description": "The I2C Device Library (I2Cdevlib) is a collection of uniform and well-documented classes to provide simple and intuitive interfaces to I2C devices.", "include": "Arduino/I2Cdev", "repository": { "type": "git", "url": "https://github.com/jrowberg/i2cdevlib.git" - } + }, + "frameworks": "arduino", + "platforms": "atmelavr" } From e235dd8dbaab0c48ae53681f466b3ac90adcc760 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Sat, 25 Oct 2014 17:11:07 +0300 Subject: [PATCH 023/335] Avoid trademark issues with library name --- Arduino/AK8975/library.json | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Arduino/AK8975/library.json b/Arduino/AK8975/library.json index b576bcc7..3c1300ba 100644 --- a/Arduino/AK8975/library.json +++ b/Arduino/AK8975/library.json @@ -1,5 +1,5 @@ { - "name": "i2cdevlib-Arduino-AK8975", + "name": "I2Cdevlib-AK8975", "keywords": "i2cdevlib, i2c, ak8975, compass, sensor", "description": "AK8975 is 3-axis electronic compass IC with high sensitive Hall sensor technology", "include": "Arduino/AK8975", @@ -9,7 +9,10 @@ "url": "https://github.com/jrowberg/i2cdevlib.git" }, "dependencies": - [ - "i2cdevlib-Arduino-i2cdev" - ] + { + "name": "I2Cdevlib-Core", + "frameworks": "arduino" + }, + "frameworks": "arduino", + "platforms": "atmelavr" } From c36f5da0e512db44998cb292866081e2e0dab775 Mon Sep 17 00:00:00 2001 From: Jeff Rowberg Date: Sat, 22 Nov 2014 12:02:52 -0500 Subject: [PATCH 024/335] Update MPUTeapot.pde with sync fixes from Doug Seaton --- .../Processing/{ => MPUTeapot}/MPUTeapot.pde | 64 +++++++++++++++---- 1 file changed, 53 insertions(+), 11 deletions(-) rename Arduino/MPU6050/Examples/MPU6050_DMP6/Processing/{ => MPUTeapot}/MPUTeapot.pde (75%) diff --git a/Arduino/MPU6050/Examples/MPU6050_DMP6/Processing/MPUTeapot.pde b/Arduino/MPU6050/Examples/MPU6050_DMP6/Processing/MPUTeapot/MPUTeapot.pde similarity index 75% rename from Arduino/MPU6050/Examples/MPU6050_DMP6/Processing/MPUTeapot.pde rename to Arduino/MPU6050/Examples/MPU6050_DMP6/Processing/MPUTeapot/MPUTeapot.pde index d4c32daf..6cc17349 100644 --- a/Arduino/MPU6050/Examples/MPU6050_DMP6/Processing/MPUTeapot.pde +++ b/Arduino/MPU6050/Examples/MPU6050_DMP6/Processing/MPUTeapot/MPUTeapot.pde @@ -45,7 +45,7 @@ ToxiclibsSupport gfx; Serial port; // The serial port char[] teapotPacket = new char[14]; // InvenSense Teapot packet int serialCount = 0; // current packet byte position -int aligned = 0; +int synced = 0; int interval = 0; float[] q = new float[4]; @@ -145,6 +145,9 @@ void serialEvent(Serial port) { interval = millis(); while (port.available() > 0) { int ch = port.read(); +<<<<<<< HEAD:Arduino/MPU6050/Examples/MPU6050_DMP6/Processing/MPUTeapot/MPUTeapot.pde + if (synced == 0 && ch != '$') return; // initial synchronization - also used to resync/realign if needed +======= print((char)ch); if (ch == '$') {serialCount = 0;} // this will help with alignment if (aligned < 4) { @@ -189,18 +192,57 @@ void serialEvent(Serial port) { euler[0] = atan2(2*q[1]*q[2] - 2*q[0]*q[3], 2*q[0]*q[0] + 2*q[1]*q[1] - 1); euler[1] = -asin(2*q[1]*q[3] + 2*q[0]*q[2]); euler[2] = atan2(2*q[2]*q[3] - 2*q[0]*q[1], 2*q[0]*q[0] + 2*q[3]*q[3] - 1); +>>>>>>> origin/master:Arduino/MPU6050/Examples/MPU6050_DMP6/Processing/MPUTeapot.pde - // calculate yaw/pitch/roll angles - ypr[0] = atan2(2*q[1]*q[2] - 2*q[0]*q[3], 2*q[0]*q[0] + 2*q[1]*q[1] - 1); - ypr[1] = atan(gravity[0] / sqrt(gravity[1]*gravity[1] + gravity[2]*gravity[2])); - ypr[2] = atan(gravity[1] / sqrt(gravity[0]*gravity[0] + gravity[2]*gravity[2])); + synced = 1; + print ((char)ch); + + if ((serialCount == 1 && ch != 2) + || (serialCount == 12 && ch != '\r') + || (serialCount == 13 && ch != '\n')) { + serialCount = 0; + synced = 0; + return; + } - // output various components for debugging - //println("q:\t" + round(q[0]*100.0f)/100.0f + "\t" + round(q[1]*100.0f)/100.0f + "\t" + round(q[2]*100.0f)/100.0f + "\t" + round(q[3]*100.0f)/100.0f); - //println("euler:\t" + euler[0]*180.0f/PI + "\t" + euler[1]*180.0f/PI + "\t" + euler[2]*180.0f/PI); - //println("ypr:\t" + ypr[0]*180.0f/PI + "\t" + ypr[1]*180.0f/PI + "\t" + ypr[2]*180.0f/PI); - */ - } + if (serialCount > 0 || ch == '$') { + teapotPacket[serialCount++] = (char)ch; + if (serialCount == 14) { + serialCount = 0; // restart packet byte position + + // get quaternion from data packet + q[0] = ((teapotPacket[2] << 8) | teapotPacket[3]) / 16384.0f; + q[1] = ((teapotPacket[4] << 8) | teapotPacket[5]) / 16384.0f; + q[2] = ((teapotPacket[6] << 8) | teapotPacket[7]) / 16384.0f; + q[3] = ((teapotPacket[8] << 8) | teapotPacket[9]) / 16384.0f; + for (int i = 0; i < 4; i++) if (q[i] >= 2) q[i] = -4 + q[i]; + + // set our toxilibs quaternion to new data + quat.set(q[0], q[1], q[2], q[3]); + + /* + // below calculations unnecessary for orientation only using toxilibs + + // calculate gravity vector + gravity[0] = 2 * (q[1]*q[3] - q[0]*q[2]); + gravity[1] = 2 * (q[0]*q[1] + q[2]*q[3]); + gravity[2] = q[0]*q[0] - q[1]*q[1] - q[2]*q[2] + q[3]*q[3]; + + // calculate Euler angles + euler[0] = atan2(2*q[1]*q[2] - 2*q[0]*q[3], 2*q[0]*q[0] + 2*q[1]*q[1] - 1); + euler[1] = -asin(2*q[1]*q[3] + 2*q[0]*q[2]); + euler[2] = atan2(2*q[2]*q[3] - 2*q[0]*q[1], 2*q[0]*q[0] + 2*q[3]*q[3] - 1); + + // calculate yaw/pitch/roll angles + ypr[0] = atan2(2*q[1]*q[2] - 2*q[0]*q[3], 2*q[0]*q[0] + 2*q[1]*q[1] - 1); + ypr[1] = atan(gravity[0] / sqrt(gravity[1]*gravity[1] + gravity[2]*gravity[2])); + ypr[2] = atan(gravity[1] / sqrt(gravity[0]*gravity[0] + gravity[2]*gravity[2])); + + // output various components for debugging + //println("q:\t" + round(q[0]*100.0f)/100.0f + "\t" + round(q[1]*100.0f)/100.0f + "\t" + round(q[2]*100.0f)/100.0f + "\t" + round(q[3]*100.0f)/100.0f); + //println("euler:\t" + euler[0]*180.0f/PI + "\t" + euler[1]*180.0f/PI + "\t" + euler[2]*180.0f/PI); + //println("ypr:\t" + ypr[0]*180.0f/PI + "\t" + ypr[1]*180.0f/PI + "\t" + ypr[2]*180.0f/PI); + */ } } } From cba206597f69219f4473ea4988f9a2d45a06b346 Mon Sep 17 00:00:00 2001 From: Jeff Rowberg Date: Sat, 22 Nov 2014 12:04:32 -0500 Subject: [PATCH 025/335] Remove incorrect merge/conflict lines from MPUTeapot.pde --- .../Examples/MPU6050_DMP6/Processing/MPUTeapot/MPUTeapot.pde | 2 -- 1 file changed, 2 deletions(-) diff --git a/Arduino/MPU6050/Examples/MPU6050_DMP6/Processing/MPUTeapot/MPUTeapot.pde b/Arduino/MPU6050/Examples/MPU6050_DMP6/Processing/MPUTeapot/MPUTeapot.pde index 6cc17349..673e3c43 100644 --- a/Arduino/MPU6050/Examples/MPU6050_DMP6/Processing/MPUTeapot/MPUTeapot.pde +++ b/Arduino/MPU6050/Examples/MPU6050_DMP6/Processing/MPUTeapot/MPUTeapot.pde @@ -145,9 +145,7 @@ void serialEvent(Serial port) { interval = millis(); while (port.available() > 0) { int ch = port.read(); -<<<<<<< HEAD:Arduino/MPU6050/Examples/MPU6050_DMP6/Processing/MPUTeapot/MPUTeapot.pde if (synced == 0 && ch != '$') return; // initial synchronization - also used to resync/realign if needed -======= print((char)ch); if (ch == '$') {serialCount = 0;} // this will help with alignment if (aligned < 4) { From acf90de3c9ae227a35f077c882dd5cecb702fa95 Mon Sep 17 00:00:00 2001 From: Jeff Rowberg Date: Sat, 22 Nov 2014 12:32:51 -0500 Subject: [PATCH 026/335] Remove incorrect merge/conflict lines from MPUTeapot.pde one more time --- .../Processing/MPUTeapot/MPUTeapot.pde | 49 +------------------ 1 file changed, 2 insertions(+), 47 deletions(-) diff --git a/Arduino/MPU6050/Examples/MPU6050_DMP6/Processing/MPUTeapot/MPUTeapot.pde b/Arduino/MPU6050/Examples/MPU6050_DMP6/Processing/MPUTeapot/MPUTeapot.pde index 673e3c43..130fc4dc 100644 --- a/Arduino/MPU6050/Examples/MPU6050_DMP6/Processing/MPUTeapot/MPUTeapot.pde +++ b/Arduino/MPU6050/Examples/MPU6050_DMP6/Processing/MPUTeapot/MPUTeapot.pde @@ -145,53 +145,8 @@ void serialEvent(Serial port) { interval = millis(); while (port.available() > 0) { int ch = port.read(); - if (synced == 0 && ch != '$') return; // initial synchronization - also used to resync/realign if needed - print((char)ch); - if (ch == '$') {serialCount = 0;} // this will help with alignment - if (aligned < 4) { - // make sure we are properly aligned on a 14-byte packet - if (serialCount == 0) { - if (ch == '$') aligned++; else aligned = 0; - } else if (serialCount == 1) { - if (ch == 2) aligned++; else aligned = 0; - } else if (serialCount == 12) { - if (ch == '\r') aligned++; else aligned = 0; - } else if (serialCount == 13) { - if (ch == '\n') aligned++; else aligned = 0; - } - //println(ch + " " + aligned + " " + serialCount); - serialCount++; - if (serialCount == 14) serialCount = 0; - } else { - if (serialCount > 0 || ch == '$') { - teapotPacket[serialCount++] = (char)ch; - if (serialCount == 14) { - serialCount = 0; // restart packet byte position - - // get quaternion from data packet - q[0] = ((teapotPacket[2] << 8) | teapotPacket[3]) / 16384.0f; - q[1] = ((teapotPacket[4] << 8) | teapotPacket[5]) / 16384.0f; - q[2] = ((teapotPacket[6] << 8) | teapotPacket[7]) / 16384.0f; - q[3] = ((teapotPacket[8] << 8) | teapotPacket[9]) / 16384.0f; - for (int i = 0; i < 4; i++) if (q[i] >= 2) q[i] = -4 + q[i]; - - // set our toxilibs quaternion to new data - quat.set(q[0], q[1], q[2], q[3]); - /* - // below calculations unnecessary for orientation only using toxilibs - - // calculate gravity vector - gravity[0] = 2 * (q[1]*q[3] - q[0]*q[2]); - gravity[1] = 2 * (q[0]*q[1] + q[2]*q[3]); - gravity[2] = q[0]*q[0] - q[1]*q[1] - q[2]*q[2] + q[3]*q[3]; - - // calculate Euler angles - euler[0] = atan2(2*q[1]*q[2] - 2*q[0]*q[3], 2*q[0]*q[0] + 2*q[1]*q[1] - 1); - euler[1] = -asin(2*q[1]*q[3] + 2*q[0]*q[2]); - euler[2] = atan2(2*q[2]*q[3] - 2*q[0]*q[1], 2*q[0]*q[0] + 2*q[3]*q[3] - 1); ->>>>>>> origin/master:Arduino/MPU6050/Examples/MPU6050_DMP6/Processing/MPUTeapot.pde - + if (synced == 0 && ch != '$') return; // initial synchronization - also used to resync/realign if needed synced = 1; print ((char)ch); @@ -202,7 +157,7 @@ void serialEvent(Serial port) { synced = 0; return; } - + if (serialCount > 0 || ch == '$') { teapotPacket[serialCount++] = (char)ch; if (serialCount == 14) { From 3c16d4c96bf83b76093258ccdf2865634bf7348b Mon Sep 17 00:00:00 2001 From: sstefanov Date: Wed, 26 Nov 2014 14:01:00 +0200 Subject: [PATCH 027/335] fixed TCA6424A default address --- Arduino/TCA6424A/TCA6424A.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Arduino/TCA6424A/TCA6424A.h b/Arduino/TCA6424A/TCA6424A.h index b255f04c..afcacc48 100644 --- a/Arduino/TCA6424A/TCA6424A.h +++ b/Arduino/TCA6424A/TCA6424A.h @@ -35,8 +35,8 @@ THE SOFTWARE. #include "I2Cdev.h" -#define TCA6424A_ADDRESS_ADDR_LOW 0x34 // address pin low (GND) -#define TCA6424A_ADDRESS_ADDR_HIGH 0x35 // address pin high (VCC) +#define TCA6424A_ADDRESS_ADDR_LOW 0x22 // address pin low (GND) +#define TCA6424A_ADDRESS_ADDR_HIGH 0x23 // address pin high (VCC) #define TCA6424A_DEFAULT_ADDRESS TCA6424A_ADDRESS_ADDR_LOW #define TCA6424A_RA_INPUT0 0x00 From 10855eb55bbae4e1fb57b46c05f5e64ef581d06e Mon Sep 17 00:00:00 2001 From: Marton Sebok Date: Fri, 28 Nov 2014 23:23:39 +0100 Subject: [PATCH 028/335] Initial commit. --- .gitignore | 3 + PIC18/I2Cdev/I2Cdev.c | 421 +++ PIC18/I2Cdev/I2Cdev.h | 64 + PIC18/MPU6050/Examples/MPU6050_raw.X/Makefile | 113 + PIC18/MPU6050/Examples/MPU6050_raw.X/funclist | 37 + PIC18/MPU6050/Examples/MPU6050_raw.X/l.obj | Bin 0 -> 24233 bytes PIC18/MPU6050/Examples/MPU6050_raw.X/main.c | 137 + .../nbproject/Makefile-default.mk | 172 + .../nbproject/Makefile-genesis.properties | 8 + .../MPU6050_raw.X/nbproject/Makefile-impl.mk | 69 + .../nbproject/Makefile-local-default.mk | 37 + .../nbproject/Makefile-variables.mk | 13 + .../nbproject/Package-default.bash | 73 + .../nbproject/configurations.xml | 173 + .../nbproject/project.properties | 0 .../MPU6050_raw.X/nbproject/project.xml | 16 + PIC18/MPU6050/MPU6050.c | 3141 +++++++++++++++++ PIC18/MPU6050/MPU6050.h | 786 +++++ PIC18/README | 14 + 19 files changed, 5277 insertions(+) create mode 100644 .gitignore create mode 100644 PIC18/I2Cdev/I2Cdev.c create mode 100644 PIC18/I2Cdev/I2Cdev.h create mode 100644 PIC18/MPU6050/Examples/MPU6050_raw.X/Makefile create mode 100644 PIC18/MPU6050/Examples/MPU6050_raw.X/funclist create mode 100644 PIC18/MPU6050/Examples/MPU6050_raw.X/l.obj create mode 100644 PIC18/MPU6050/Examples/MPU6050_raw.X/main.c create mode 100644 PIC18/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-default.mk create mode 100644 PIC18/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-genesis.properties create mode 100644 PIC18/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-impl.mk create mode 100644 PIC18/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-local-default.mk create mode 100644 PIC18/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-variables.mk create mode 100644 PIC18/MPU6050/Examples/MPU6050_raw.X/nbproject/Package-default.bash create mode 100644 PIC18/MPU6050/Examples/MPU6050_raw.X/nbproject/configurations.xml create mode 100644 PIC18/MPU6050/Examples/MPU6050_raw.X/nbproject/project.properties create mode 100644 PIC18/MPU6050/Examples/MPU6050_raw.X/nbproject/project.xml create mode 100644 PIC18/MPU6050/MPU6050.c create mode 100644 PIC18/MPU6050/MPU6050.h create mode 100644 PIC18/README diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..38ca2ec5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +PIC18/MPU6050/Examples/MPU6050_raw.X/dist/ +PIC18/MPU6050/Examples/MPU6050_raw.X/nbproject/private/ +PIC18/MPU6050/Examples/MPU6050_raw.X/build/ diff --git a/PIC18/I2Cdev/I2Cdev.c b/PIC18/I2Cdev/I2Cdev.c new file mode 100644 index 00000000..d8082e33 --- /dev/null +++ b/PIC18/I2Cdev/I2Cdev.c @@ -0,0 +1,421 @@ +// I2Cdev library collection - Main I2C device class +// Abstracts bit and byte I2C R/W functions into a convenient class +// 6/9/2012 by Jeff Rowberg +// 11/28/2014 by Marton Sebok +// +// Changelog: +// 2014-11-28 - ported to PIC18 peripheral library from Arduino code + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2013 Jeff Rowberg +Copyright (c) 2014 Marton Sebok + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#include "I2Cdev.h" + +/** Read multiple bytes from an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr First register regAddr to read from + * @param length Number of bytes to read + * @param data Buffer to store read data in + * @return Number of bytes read (-1 indicates failure) + */ +int8_t I2Cdev_readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data) { + int8_t count = 0; + + // S + IdleI2C(); + StartI2C(); + + // Device write address + IdleI2C(); + WriteI2C(devAddr << 1 | 0x00); + + // Register address + IdleI2C(); + WriteI2C(regAddr); + + // R + IdleI2C(); + RestartI2C(); + + // Device read address + IdleI2C(); + WriteI2C(devAddr << 1 | 0x01); + + for (count = 0; count < length; count++) { + // Data byte + IdleI2C(); + data[count] = ReadI2C(); + + if (count == length - 1) { + // NACK + IdleI2C(); + NotAckI2C(); + } else { + // ACK + IdleI2C(); + AckI2C(); + } + } + + // P + IdleI2C(); + StopI2C(); + + return count; +} + +/** Read single byte from an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param data Container for byte value read from device + * @return Status of read operation (true = success) + */ +int8_t I2Cdev_readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data) { + return I2Cdev_readBytes(devAddr, regAddr, 1, data); +} + +/** Read multiple words from a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr First register regAddr to read from + * @param length Number of words to read + * @param data Buffer to store read data in + * @return Number of words read (-1 indicates failure) + */ +int8_t I2Cdev_readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data) { + int8_t count = 0; + + // S + IdleI2C(); + StartI2C(); + + // Device write address + IdleI2C(); + WriteI2C(devAddr << 1 | 0x00); + + // Register address + IdleI2C(); + WriteI2C(regAddr); + + // R + IdleI2C(); + RestartI2C(); + + // Device read address + IdleI2C(); + WriteI2C(devAddr << 1 | 0x01); + + for (count = 0; count < length; count++) { + // First byte is bits 15-8 (MSb=15) + IdleI2C(); + data[count] = ReadI2C() << 8; + + // NACK + IdleI2C(); + NotAckI2C(); + + // Second byte is bits 7-0 (LSb=0) + IdleI2C(); + data[count] |= ReadI2C(); + + if (count == length - 1) { + // NACK + IdleI2C(); + NotAckI2C(); + } else { + // ACK + IdleI2C(); + AckI2C(); + } + } + + // P + IdleI2C(); + StopI2C(); + + return count; +} + +/** Read single word from a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param data Container for word value read from device + * @return Status of read operation (true = success) + */ +int8_t I2Cdev_readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data) { + return I2Cdev_readWords(devAddr, regAddr, 1, data); +} + +/** Read a single bit from an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param bitNum Bit position to read (0-7) + * @param data Container for single bit value + * @return Status of read operation (true = success) + */ +int8_t I2Cdev_readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data) { + uint8_t b; + uint8_t count = I2Cdev_readByte(devAddr, regAddr, &b); + *data = b & (1 << bitNum); + return count; +} + +/** Read a single bit from a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param bitNum Bit position to read (0-15) + * @param data Container for single bit value + * @return Status of read operation (true = success) + */ +int8_t I2Cdev_readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data) { + uint16_t b; + uint8_t count = I2Cdev_readWord(devAddr, regAddr, &b); + *data = b & (1 << bitNum); + return count; +} + +/** Read multiple bits from an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param bitStart First bit position to read (0-7) + * @param length Number of bits to read (not more than 8) + * @param data Container for right-aligned value (i.e. '101' read from any bitStart position will equal 0x05) + * @return Status of read operation (true = success) + */ +int8_t I2Cdev_readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data) { + // 01101001 read byte + // 76543210 bit numbers + // xxx args: bitStart=4, length=3 + // 010 masked + // -> 010 shifted + uint8_t count, b; + if ((count = I2Cdev_readByte(devAddr, regAddr, &b)) != 0) { + uint8_t mask = ((1 << length) - 1) << (bitStart - length + 1); + b &= mask; + b >>= (bitStart - length + 1); + *data = b; + } + return count; +} + +/** Read multiple bits from a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param bitStart First bit position to read (0-15) + * @param length Number of bits to read (not more than 16) + * @param data Container for right-aligned value (i.e. '101' read from any bitStart position will equal 0x05) + * @return Status of read operation (1 = success, 0 = failure, -1 = timeout) + */ +int8_t I2Cdev_readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t *data) { + // 1101011001101001 read byte + // fedcba9876543210 bit numbers + // xxx args: bitStart=12, length=3 + // 010 masked + // -> 010 shifted + uint8_t count; + uint16_t w; + if ((count = I2Cdev_readWord(devAddr, regAddr, &w)) != 0) { + uint16_t mask = ((1 << length) - 1) << (bitStart - length + 1); + w &= mask; + w >>= (bitStart - length + 1); + *data = w; + } + return count; +} + +/** Write multiple bytes to an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr First register address to write to + * @param length Number of bytes to write + * @param data Buffer to copy new data from + * @return Status of operation (true = success) + */ +bool I2Cdev_writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t* data) { + // S + IdleI2C(); + StartI2C(); + + // Device write address + IdleI2C(); + WriteI2C(devAddr << 1 | 0x00); + + // Register address + IdleI2C(); + WriteI2C(regAddr); + + for (uint8_t i = 0; i < length; i++) { + // Data byte + IdleI2C(); + WriteI2C(data[i]); + } + + // P + IdleI2C(); + StopI2C(); + + return true; +} + +/** Write single byte to an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register address to write to + * @param data New byte value to write + * @return Status of operation (true = success) + */ +bool I2Cdev_writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data) { + return I2Cdev_writeBytes(devAddr, regAddr, 1, &data); +} + +/** Write multiple words to a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr First register address to write to + * @param length Number of words to write + * @param data Buffer to copy new data from + * @return Status of operation (true = success) + */ +bool I2Cdev_writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t* data) { + // S + IdleI2C(); + StartI2C(); + + // Device write address + IdleI2C(); + WriteI2C(devAddr << 1 | 0x00); + + // Register address + IdleI2C(); + WriteI2C(regAddr); + + for (uint8_t i = 0; i < length; i++) { + // Send MSB + IdleI2C(); + WriteI2C(data[i] >> 8); + + // Send LSB + IdleI2C(); + WriteI2C(data[i] & 0xFF); + } + + // P + IdleI2C(); + StopI2C(); + + return true; +} + +/** Write single word to a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register address to write to + * @param data New word value to write + * @return Status of operation (true = success) + */ +bool I2Cdev_writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data) { + return I2Cdev_writeWords(devAddr, regAddr, 1, &data); +} + +/** write a single bit in an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to write to + * @param bitNum Bit position to write (0-7) + * @param value New bit value to write + * @return Status of operation (true = success) + */ +bool I2Cdev_writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t data) { + uint8_t b; + I2Cdev_readByte(devAddr, regAddr, &b); + b = (data != 0) ? (b | (1 << bitNum)) : (b & ~(1 << bitNum)); + return I2Cdev_writeByte(devAddr, regAddr, b); +} + +/** write a single bit in a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to write to + * @param bitNum Bit position to write (0-15) + * @param value New bit value to write + * @return Status of operation (true = success) + */ +bool I2Cdev_writeBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t data) { + uint16_t w; + I2Cdev_readWord(devAddr, regAddr, &w); + w = (data != 0) ? (w | (1 << bitNum)) : (w & ~(1 << bitNum)); + return I2Cdev_writeWord(devAddr, regAddr, w); +} + +/** Write multiple bits in an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to write to + * @param bitStart First bit position to write (0-7) + * @param length Number of bits to write (not more than 8) + * @param data Right-aligned value to write + * @return Status of operation (true = success) + */ +bool I2Cdev_writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data) { + // 010 value to write + // 76543210 bit numbers + // xxx args: bitStart=4, length=3 + // 00011100 mask byte + // 10101111 original value (sample) + // 10100011 original & ~mask + // 10101011 masked | value + uint8_t b; + if (I2Cdev_readByte(devAddr, regAddr, &b) != 0) { + uint8_t mask = ((1 << length) - 1) << (bitStart - length + 1); + data <<= (bitStart - length + 1); // shift data into correct position + data &= mask; // zero all non-important bits in data + b &= ~(mask); // zero all important bits in existing byte + b |= data; // combine data with existing byte + return I2Cdev_writeByte(devAddr, regAddr, b); + } else { + return false; + } +} + +/** Write multiple bits in a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to write to + * @param bitStart First bit position to write (0-15) + * @param length Number of bits to write (not more than 16) + * @param data Right-aligned value to write + * @return Status of operation (true = success) + */ +bool I2Cdev_writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t data) { + // 010 value to write + // fedcba9876543210 bit numbers + // xxx args: bitStart=12, length=3 + // 0001110000000000 mask word + // 1010111110010110 original value (sample) + // 1010001110010110 original & ~mask + // 1010101110010110 masked | value + uint16_t w; + if (I2Cdev_readWord(devAddr, regAddr, &w) != 0) { + uint16_t mask = ((1 << length) - 1) << (bitStart - length + 1); + data <<= (bitStart - length + 1); // shift data into correct position + data &= mask; // zero all non-important bits in data + w &= ~(mask); // zero all important bits in existing word + w |= data; // combine data with existing word + return I2Cdev_writeWord(devAddr, regAddr, w); + } else { + return false; + } +} diff --git a/PIC18/I2Cdev/I2Cdev.h b/PIC18/I2Cdev/I2Cdev.h new file mode 100644 index 00000000..f90d5d2e --- /dev/null +++ b/PIC18/I2Cdev/I2Cdev.h @@ -0,0 +1,64 @@ +// I2Cdev library collection - Main I2C device class header file +// Abstracts bit and byte I2C R/W functions into a convenient class +// 6/9/2012 by Jeff Rowberg +// 11/28/2014 by Marton Sebok +// +// Changelog: +// 2014-11-28 - ported to PIC18 peripheral library from Arduino code + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2013 Jeff Rowberg +Copyright (c) 2014 Marton Sebok + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#ifndef _I2CDEV_H_ +#define _I2CDEV_H_ + +#ifndef __XC8 + #error Use XC8 for compiling +#endif + +#include +#include +#include +#include + +int8_t I2Cdev_readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data); +int8_t I2Cdev_readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data); +int8_t I2Cdev_readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data); +int8_t I2Cdev_readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t *data); +int8_t I2Cdev_readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data); +int8_t I2Cdev_readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data); +int8_t I2Cdev_readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data); +int8_t I2Cdev_readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data); + +bool I2Cdev_writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t data); +bool I2Cdev_writeBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t data); +bool I2Cdev_writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data); +bool I2Cdev_writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t data); +bool I2Cdev_writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data); +bool I2Cdev_writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data); +bool I2Cdev_writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data); +bool I2Cdev_writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data); + +#endif /* _I2CDEV_H_ */ diff --git a/PIC18/MPU6050/Examples/MPU6050_raw.X/Makefile b/PIC18/MPU6050/Examples/MPU6050_raw.X/Makefile new file mode 100644 index 00000000..fca8e2cc --- /dev/null +++ b/PIC18/MPU6050/Examples/MPU6050_raw.X/Makefile @@ -0,0 +1,113 @@ +# +# There exist several targets which are by default empty and which can be +# used for execution of your targets. These targets are usually executed +# before and after some main targets. They are: +# +# .build-pre: called before 'build' target +# .build-post: called after 'build' target +# .clean-pre: called before 'clean' target +# .clean-post: called after 'clean' target +# .clobber-pre: called before 'clobber' target +# .clobber-post: called after 'clobber' target +# .all-pre: called before 'all' target +# .all-post: called after 'all' target +# .help-pre: called before 'help' target +# .help-post: called after 'help' target +# +# Targets beginning with '.' are not intended to be called on their own. +# +# Main targets can be executed directly, and they are: +# +# build build a specific configuration +# clean remove built files from a configuration +# clobber remove all built files +# all build all configurations +# help print help mesage +# +# Targets .build-impl, .clean-impl, .clobber-impl, .all-impl, and +# .help-impl are implemented in nbproject/makefile-impl.mk. +# +# Available make variables: +# +# CND_BASEDIR base directory for relative paths +# CND_DISTDIR default top distribution directory (build artifacts) +# CND_BUILDDIR default top build directory (object files, ...) +# CONF name of current configuration +# CND_ARTIFACT_DIR_${CONF} directory of build artifact (current configuration) +# CND_ARTIFACT_NAME_${CONF} name of build artifact (current configuration) +# CND_ARTIFACT_PATH_${CONF} path to build artifact (current configuration) +# CND_PACKAGE_DIR_${CONF} directory of package (current configuration) +# CND_PACKAGE_NAME_${CONF} name of package (current configuration) +# CND_PACKAGE_PATH_${CONF} path to package (current configuration) +# +# NOCDDL + + +# Environment +MKDIR=mkdir +CP=cp +CCADMIN=CCadmin +RANLIB=ranlib + + +# build +build: .build-post + +.build-pre: +# Add your pre 'build' code here... + +.build-post: .build-impl +# Add your post 'build' code here... + + +# clean +clean: .clean-post + +.clean-pre: +# Add your pre 'clean' code here... +# WARNING: the IDE does not call this target since it takes a long time to +# simply run make. Instead, the IDE removes the configuration directories +# under build and dist directly without calling make. +# This target is left here so people can do a clean when running a clean +# outside the IDE. + +.clean-post: .clean-impl +# Add your post 'clean' code here... + + +# clobber +clobber: .clobber-post + +.clobber-pre: +# Add your pre 'clobber' code here... + +.clobber-post: .clobber-impl +# Add your post 'clobber' code here... + + +# all +all: .all-post + +.all-pre: +# Add your pre 'all' code here... + +.all-post: .all-impl +# Add your post 'all' code here... + + +# help +help: .help-post + +.help-pre: +# Add your pre 'help' code here... + +.help-post: .help-impl +# Add your post 'help' code here... + + + +# include project implementation makefile +include nbproject/Makefile-impl.mk + +# include project make variables +include nbproject/Makefile-variables.mk diff --git a/PIC18/MPU6050/Examples/MPU6050_raw.X/funclist b/PIC18/MPU6050/Examples/MPU6050_raw.X/funclist new file mode 100644 index 00000000..bf32657d --- /dev/null +++ b/PIC18/MPU6050/Examples/MPU6050_raw.X/funclist @@ -0,0 +1,37 @@ +_MPU6050_initialize: CODE, 6334 0 24 +_I2Cdev_writeBytes: CODE, 5202 0 156 +_MPU6050_getDeviceID: CODE, 6310 0 24 +__stringdata: SMALLCONST, 3851 0 193 +_putch: CODE, 6552 0 12 +_MPU6050_getXGyroOffset: CODE, 6188 0 42 +_MPU6050_getYGyroOffset: CODE, 6104 0 42 +_MPU6050_getZGyroOffset: CODE, 6020 0 42 +_dpowers: SMALLCONST, 3841 0 10 +_I2Cdev_readByte: CODE, 6514 0 20 +_I2Cdev_writeBit: CODE, 5474 0 110 +_main: CODE, 4046 0 342 +_I2Cdev_readBits: CODE, 5584 0 108 +_MPU6050_setFullScaleGyroRange: CODE, 6358 0 24 +_MPU6050_setSleepEnabled: CODE, 6474 0 20 +_MPU6050: CODE, 6584 0 8 +_MPU6050_setClockSource: CODE, 6406 0 24 +__initialization: CODE, 6430 0 12 +___lwdiv: CODE, 5884 0 74 +_MPU6050_setFullScaleAccelRange: CODE, 6382 0 24 +_baud1USART: CODE, 6576 0 8 +_Write1USART: CODE, 6534 0 18 +_printf: CODE, 4706 0 294 +___lwmod: CODE, 5958 0 62 +_MPU6050_testConnection: CODE, 6564 0 12 +_ReadI2C1: CODE, 6272 0 38 +_MPU6050_getXAccelOffset: CODE, 6230 0 42 +_MPU6050_getYAccelOffset: CODE, 6146 0 42 +_MPU6050_getZAccelOffset: CODE, 6062 0 42 +_WriteI2C1: CODE, 5692 0 108 +_I2Cdev_writeByte: CODE, 6494 0 20 +_Open1USART: CODE, 5800 0 84 +_I2Cdev_readBytes: CODE, 4388 0 318 +_I2Cdev_writeBits: CODE, 5358 0 116 +_MPU6050_getMotion6: CODE, 5000 0 202 +_OpenI2C1: CODE, 6452 0 22 +Total: 2739 \ No newline at end of file diff --git a/PIC18/MPU6050/Examples/MPU6050_raw.X/l.obj b/PIC18/MPU6050/Examples/MPU6050_raw.X/l.obj new file mode 100644 index 0000000000000000000000000000000000000000..1734cc8674a5c31b28cd2bf0bf9b45b350e67c21 GIT binary patch literal 24233 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 +// 11/28/2014 by Marton Sebok +// +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// 2014-11-28 - ported to PIC18 peripheral library from Arduino code + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2011 Jeff Rowberg +Copyright (c) 2014 Marton Sebok + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +/* + * The project can be run without modification on Microchip's 8-bit Wireless + * Development Kit. Please set the type of your IC in project properties/Conf/ + * Device and change the code as needed. + */ + +// PLL Prescaler Selection bits (Divide by 2 (8 MHz oscillator input)) +#pragma config PLLDIV = 2 + +// Extended Instruction Set (Disabled) +#pragma config XINST = OFF + +// CPU System Clock Postscaler (CPU system clock divide by 2) +#pragma config CPUDIV = OSC2_PLL2 + +// Oscillator (HS+PLL, USB-HS+PLL) +#pragma config OSC = HSPLL + +#define USE_OR_MASKS +#define _XTAL_FREQ 24000000 + +#include +#include +#include +#include +#include + +/* + * You must add the I2Cdev and MPU6050 directories as include directories in + * project properties/Conf/General options/XC8 global option/XC8 compiler/ + * Preprocessing and messages/Include directories. + */ +#include "I2Cdev.h" +#include "MPU6050.h" + +#define LED_PIN LATBbits.LATB1 + +/** + * Write one char to USART + * @param data + */ +void putch(char data) { + while (Busy1USART()); + Write1USART(data); +} + +/** + * Main function + */ +int main() { + int16_t ax, ay, az, gx, gy, gz; + + // Initialize system + // PLL (24 MHz) + OSCTUNEbits.PLLEN = 1; + __delay_ms(25); + __delay_ms(25); + + // LED + LED_PIN = 0; + TRISBbits.TRISB1 = 0; + + // Serial (115200 kbps) + Open1USART(USART_TX_INT_OFF | USART_RX_INT_OFF | USART_ASYNCH_MODE | + USART_EIGHT_BIT | USART_CONT_RX | USART_BRGH_HIGH, 12); + baud1USART(BAUD_8_BIT_RATE | BAUD_AUTO_OFF); + + // I2C (400 kHz) + OpenI2C(MASTER, SLEW_OFF); + SSP1ADD = 14; + + // MPU6050 + MPU6050(MPU6050_ADDRESS_AD0_LOW); + + // Initialize device + printf("Initializing I2C devices...\r\n"); + MPU6050_initialize(); + + // Verify connection + printf("Testing device connections...\r\n"); + printf(MPU6050_testConnection() ? "MPU6050 connection successful\r\n" : + "MPU6050 connection failed\r\n"); + + printf("Reading internal sensor offsets...\r\n"); + printf("%d\t", MPU6050_getXAccelOffset()); + printf("%d\t", MPU6050_getYAccelOffset()); + printf("%d\t", MPU6050_getZAccelOffset()); + printf("%d\t", MPU6050_getXGyroOffset()); + printf("%d\t", MPU6050_getYGyroOffset()); + printf("%d\t\n", MPU6050_getZGyroOffset()); + + while (true) { + // Read raw accel/gyro measurements from device + MPU6050_getMotion6(&ax, &ay, &az, &gx, &gy, &gz); + + // Display tab-separated accel/gyro x/y/z values + printf("a/g:\t%d\t%d\t%d\t%d\t%d\t%d\r\n", ax, ay, az, gx, gy, gz); + + // Blink LED to indicate activity + LED_PIN ^= 1; + + __delay_ms(25); + __delay_ms(25); + } +} diff --git a/PIC18/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-default.mk b/PIC18/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-default.mk new file mode 100644 index 00000000..1c5f0ec6 --- /dev/null +++ b/PIC18/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-default.mk @@ -0,0 +1,172 @@ +# +# Generated Makefile - do not edit! +# +# Edit the Makefile in the project folder instead (../Makefile). Each target +# has a -pre and a -post target defined where you can add customized code. +# +# This makefile implements configuration specific macros and targets. + + +# Include project Makefile +ifeq "${IGNORE_LOCAL}" "TRUE" +# do not include local makefile. User is passing all local related variables already +else +include Makefile +# Include makefile containing local settings +ifeq "$(wildcard nbproject/Makefile-local-default.mk)" "nbproject/Makefile-local-default.mk" +include nbproject/Makefile-local-default.mk +endif +endif + +# Environment +MKDIR=gnumkdir -p +RM=rm -f +MV=mv +CP=cp + +# Macros +CND_CONF=default +ifeq ($(TYPE_IMAGE), DEBUG_RUN) +IMAGE_TYPE=debug +OUTPUT_SUFFIX=elf +DEBUGGABLE_SUFFIX=elf +FINAL_IMAGE=dist/${CND_CONF}/${IMAGE_TYPE}/MPU6050_raw.X.${IMAGE_TYPE}.${OUTPUT_SUFFIX} +else +IMAGE_TYPE=production +OUTPUT_SUFFIX=hex +DEBUGGABLE_SUFFIX=elf +FINAL_IMAGE=dist/${CND_CONF}/${IMAGE_TYPE}/MPU6050_raw.X.${IMAGE_TYPE}.${OUTPUT_SUFFIX} +endif + +# Object Directory +OBJECTDIR=build/${CND_CONF}/${IMAGE_TYPE} + +# Distribution Directory +DISTDIR=dist/${CND_CONF}/${IMAGE_TYPE} + +# Source Files Quoted if spaced +SOURCEFILES_QUOTED_IF_SPACED=../../MPU6050.c ../../../I2Cdev/I2Cdev.c main.c + +# Object Files Quoted if spaced +OBJECTFILES_QUOTED_IF_SPACED=${OBJECTDIR}/_ext/43898991/MPU6050.p1 ${OBJECTDIR}/_ext/105797386/I2Cdev.p1 ${OBJECTDIR}/main.p1 +POSSIBLE_DEPFILES=${OBJECTDIR}/_ext/43898991/MPU6050.p1.d ${OBJECTDIR}/_ext/105797386/I2Cdev.p1.d ${OBJECTDIR}/main.p1.d + +# Object Files +OBJECTFILES=${OBJECTDIR}/_ext/43898991/MPU6050.p1 ${OBJECTDIR}/_ext/105797386/I2Cdev.p1 ${OBJECTDIR}/main.p1 + +# Source Files +SOURCEFILES=../../MPU6050.c ../../../I2Cdev/I2Cdev.c main.c + + +CFLAGS= +ASFLAGS= +LDLIBSOPTIONS= + +############# Tool locations ########################################## +# If you copy a project from one host to another, the path where the # +# compiler is installed may be different. # +# If you open this project with MPLAB X in the new host, this # +# makefile will be regenerated and the paths will be corrected. # +####################################################################### +# fixDeps replaces a bunch of sed/cat/printf statements that slow down the build +FIXDEPS=fixDeps + +.build-conf: ${BUILD_SUBPROJECTS} + ${MAKE} -f nbproject/Makefile-default.mk dist/${CND_CONF}/${IMAGE_TYPE}/MPU6050_raw.X.${IMAGE_TYPE}.${OUTPUT_SUFFIX} + +MP_PROCESSOR_OPTION=18F46J50 +# ------------------------------------------------------------------------------------ +# Rules for buildStep: compile +ifeq ($(TYPE_IMAGE), DEBUG_RUN) +${OBJECTDIR}/_ext/43898991/MPU6050.p1: ../../MPU6050.c nbproject/Makefile-${CND_CONF}.mk + @${MKDIR} ${OBJECTDIR}/_ext/43898991 + @${RM} ${OBJECTDIR}/_ext/43898991/MPU6050.p1.d + @${RM} ${OBJECTDIR}/_ext/43898991/MPU6050.p1 + ${MP_CC} --pass1 $(MP_EXTRA_CC_PRE) --chip=$(MP_PROCESSOR_OPTION) -Q -G -D__DEBUG=1 --debugger=pickit3 --double=24 --float=24 --emi=wordwrite --opt=default,+asm,-asmfile,+speed,-space,-debug --addrqual=ignore --mode=pro -P -N255 -I"../../../I2Cdev" -I"../../" --warn=0 --asmlist --summary=default,-psect,-class,+mem,-hex,-file --output=default,-inhx032 --runtime=default,+clear,+init,-keep,-no_startup,-download,+config,+clib,+plib --output=-mcof,+elf:multilocs --stack=compiled:auto:auto:auto "--errformat=%f:%l: error: (%n) %s" "--warnformat=%f:%l: warning: (%n) %s" "--msgformat=%f:%l: advisory: (%n) %s" -o${OBJECTDIR}/_ext/43898991/MPU6050.p1 ../../MPU6050.c + @-${MV} ${OBJECTDIR}/_ext/43898991/MPU6050.d ${OBJECTDIR}/_ext/43898991/MPU6050.p1.d + @${FIXDEPS} ${OBJECTDIR}/_ext/43898991/MPU6050.p1.d $(SILENT) -rsi ${MP_CC_DIR}../ + +${OBJECTDIR}/_ext/105797386/I2Cdev.p1: ../../../I2Cdev/I2Cdev.c nbproject/Makefile-${CND_CONF}.mk + @${MKDIR} ${OBJECTDIR}/_ext/105797386 + @${RM} ${OBJECTDIR}/_ext/105797386/I2Cdev.p1.d + @${RM} ${OBJECTDIR}/_ext/105797386/I2Cdev.p1 + ${MP_CC} --pass1 $(MP_EXTRA_CC_PRE) --chip=$(MP_PROCESSOR_OPTION) -Q -G -D__DEBUG=1 --debugger=pickit3 --double=24 --float=24 --emi=wordwrite --opt=default,+asm,-asmfile,+speed,-space,-debug --addrqual=ignore --mode=pro -P -N255 -I"../../../I2Cdev" -I"../../" --warn=0 --asmlist --summary=default,-psect,-class,+mem,-hex,-file --output=default,-inhx032 --runtime=default,+clear,+init,-keep,-no_startup,-download,+config,+clib,+plib --output=-mcof,+elf:multilocs --stack=compiled:auto:auto:auto "--errformat=%f:%l: error: (%n) %s" "--warnformat=%f:%l: warning: (%n) %s" "--msgformat=%f:%l: advisory: (%n) %s" -o${OBJECTDIR}/_ext/105797386/I2Cdev.p1 ../../../I2Cdev/I2Cdev.c + @-${MV} ${OBJECTDIR}/_ext/105797386/I2Cdev.d ${OBJECTDIR}/_ext/105797386/I2Cdev.p1.d + @${FIXDEPS} ${OBJECTDIR}/_ext/105797386/I2Cdev.p1.d $(SILENT) -rsi ${MP_CC_DIR}../ + +${OBJECTDIR}/main.p1: main.c nbproject/Makefile-${CND_CONF}.mk + @${MKDIR} ${OBJECTDIR} + @${RM} ${OBJECTDIR}/main.p1.d + @${RM} ${OBJECTDIR}/main.p1 + ${MP_CC} --pass1 $(MP_EXTRA_CC_PRE) --chip=$(MP_PROCESSOR_OPTION) -Q -G -D__DEBUG=1 --debugger=pickit3 --double=24 --float=24 --emi=wordwrite --opt=default,+asm,-asmfile,+speed,-space,-debug --addrqual=ignore --mode=pro -P -N255 -I"../../../I2Cdev" -I"../../" --warn=0 --asmlist --summary=default,-psect,-class,+mem,-hex,-file --output=default,-inhx032 --runtime=default,+clear,+init,-keep,-no_startup,-download,+config,+clib,+plib --output=-mcof,+elf:multilocs --stack=compiled:auto:auto:auto "--errformat=%f:%l: error: (%n) %s" "--warnformat=%f:%l: warning: (%n) %s" "--msgformat=%f:%l: advisory: (%n) %s" -o${OBJECTDIR}/main.p1 main.c + @-${MV} ${OBJECTDIR}/main.d ${OBJECTDIR}/main.p1.d + @${FIXDEPS} ${OBJECTDIR}/main.p1.d $(SILENT) -rsi ${MP_CC_DIR}../ + +else +${OBJECTDIR}/_ext/43898991/MPU6050.p1: ../../MPU6050.c nbproject/Makefile-${CND_CONF}.mk + @${MKDIR} ${OBJECTDIR}/_ext/43898991 + @${RM} ${OBJECTDIR}/_ext/43898991/MPU6050.p1.d + @${RM} ${OBJECTDIR}/_ext/43898991/MPU6050.p1 + ${MP_CC} --pass1 $(MP_EXTRA_CC_PRE) --chip=$(MP_PROCESSOR_OPTION) -Q -G --double=24 --float=24 --emi=wordwrite --opt=default,+asm,-asmfile,+speed,-space,-debug --addrqual=ignore --mode=pro -P -N255 -I"../../../I2Cdev" -I"../../" --warn=0 --asmlist --summary=default,-psect,-class,+mem,-hex,-file --output=default,-inhx032 --runtime=default,+clear,+init,-keep,-no_startup,-download,+config,+clib,+plib --output=-mcof,+elf:multilocs --stack=compiled:auto:auto:auto "--errformat=%f:%l: error: (%n) %s" "--warnformat=%f:%l: warning: (%n) %s" "--msgformat=%f:%l: advisory: (%n) %s" -o${OBJECTDIR}/_ext/43898991/MPU6050.p1 ../../MPU6050.c + @-${MV} ${OBJECTDIR}/_ext/43898991/MPU6050.d ${OBJECTDIR}/_ext/43898991/MPU6050.p1.d + @${FIXDEPS} ${OBJECTDIR}/_ext/43898991/MPU6050.p1.d $(SILENT) -rsi ${MP_CC_DIR}../ + +${OBJECTDIR}/_ext/105797386/I2Cdev.p1: ../../../I2Cdev/I2Cdev.c nbproject/Makefile-${CND_CONF}.mk + @${MKDIR} ${OBJECTDIR}/_ext/105797386 + @${RM} ${OBJECTDIR}/_ext/105797386/I2Cdev.p1.d + @${RM} ${OBJECTDIR}/_ext/105797386/I2Cdev.p1 + ${MP_CC} --pass1 $(MP_EXTRA_CC_PRE) --chip=$(MP_PROCESSOR_OPTION) -Q -G --double=24 --float=24 --emi=wordwrite --opt=default,+asm,-asmfile,+speed,-space,-debug --addrqual=ignore --mode=pro -P -N255 -I"../../../I2Cdev" -I"../../" --warn=0 --asmlist --summary=default,-psect,-class,+mem,-hex,-file --output=default,-inhx032 --runtime=default,+clear,+init,-keep,-no_startup,-download,+config,+clib,+plib --output=-mcof,+elf:multilocs --stack=compiled:auto:auto:auto "--errformat=%f:%l: error: (%n) %s" "--warnformat=%f:%l: warning: (%n) %s" "--msgformat=%f:%l: advisory: (%n) %s" -o${OBJECTDIR}/_ext/105797386/I2Cdev.p1 ../../../I2Cdev/I2Cdev.c + @-${MV} ${OBJECTDIR}/_ext/105797386/I2Cdev.d ${OBJECTDIR}/_ext/105797386/I2Cdev.p1.d + @${FIXDEPS} ${OBJECTDIR}/_ext/105797386/I2Cdev.p1.d $(SILENT) -rsi ${MP_CC_DIR}../ + +${OBJECTDIR}/main.p1: main.c nbproject/Makefile-${CND_CONF}.mk + @${MKDIR} ${OBJECTDIR} + @${RM} ${OBJECTDIR}/main.p1.d + @${RM} ${OBJECTDIR}/main.p1 + ${MP_CC} --pass1 $(MP_EXTRA_CC_PRE) --chip=$(MP_PROCESSOR_OPTION) -Q -G --double=24 --float=24 --emi=wordwrite --opt=default,+asm,-asmfile,+speed,-space,-debug --addrqual=ignore --mode=pro -P -N255 -I"../../../I2Cdev" -I"../../" --warn=0 --asmlist --summary=default,-psect,-class,+mem,-hex,-file --output=default,-inhx032 --runtime=default,+clear,+init,-keep,-no_startup,-download,+config,+clib,+plib --output=-mcof,+elf:multilocs --stack=compiled:auto:auto:auto "--errformat=%f:%l: error: (%n) %s" "--warnformat=%f:%l: warning: (%n) %s" "--msgformat=%f:%l: advisory: (%n) %s" -o${OBJECTDIR}/main.p1 main.c + @-${MV} ${OBJECTDIR}/main.d ${OBJECTDIR}/main.p1.d + @${FIXDEPS} ${OBJECTDIR}/main.p1.d $(SILENT) -rsi ${MP_CC_DIR}../ + +endif + +# ------------------------------------------------------------------------------------ +# Rules for buildStep: assemble +ifeq ($(TYPE_IMAGE), DEBUG_RUN) +else +endif + +# ------------------------------------------------------------------------------------ +# Rules for buildStep: link +ifeq ($(TYPE_IMAGE), DEBUG_RUN) +dist/${CND_CONF}/${IMAGE_TYPE}/MPU6050_raw.X.${IMAGE_TYPE}.${OUTPUT_SUFFIX}: ${OBJECTFILES} nbproject/Makefile-${CND_CONF}.mk + @${MKDIR} dist/${CND_CONF}/${IMAGE_TYPE} + ${MP_CC} $(MP_EXTRA_LD_PRE) --chip=$(MP_PROCESSOR_OPTION) -G -mdist/${CND_CONF}/${IMAGE_TYPE}/MPU6050_raw.X.${IMAGE_TYPE}.map -D__DEBUG=1 --debugger=pickit3 --double=24 --float=24 --emi=wordwrite --opt=default,+asm,-asmfile,+speed,-space,-debug --addrqual=ignore --mode=pro -P -N255 -I"../../../I2Cdev" -I"../../" --warn=0 --asmlist --summary=default,-psect,-class,+mem,-hex,-file --output=default,-inhx032 --runtime=default,+clear,+init,-keep,-no_startup,-download,+config,+clib,+plib --output=-mcof,+elf:multilocs --stack=compiled:auto:auto:auto "--errformat=%f:%l: error: (%n) %s" "--warnformat=%f:%l: warning: (%n) %s" "--msgformat=%f:%l: advisory: (%n) %s" -odist/${CND_CONF}/${IMAGE_TYPE}/MPU6050_raw.X.${IMAGE_TYPE}.${DEBUGGABLE_SUFFIX} ${OBJECTFILES_QUOTED_IF_SPACED} + @${RM} dist/${CND_CONF}/${IMAGE_TYPE}/MPU6050_raw.X.${IMAGE_TYPE}.hex + +else +dist/${CND_CONF}/${IMAGE_TYPE}/MPU6050_raw.X.${IMAGE_TYPE}.${OUTPUT_SUFFIX}: ${OBJECTFILES} nbproject/Makefile-${CND_CONF}.mk + @${MKDIR} dist/${CND_CONF}/${IMAGE_TYPE} + ${MP_CC} $(MP_EXTRA_LD_PRE) --chip=$(MP_PROCESSOR_OPTION) -G -mdist/${CND_CONF}/${IMAGE_TYPE}/MPU6050_raw.X.${IMAGE_TYPE}.map --double=24 --float=24 --emi=wordwrite --opt=default,+asm,-asmfile,+speed,-space,-debug --addrqual=ignore --mode=pro -P -N255 -I"../../../I2Cdev" -I"../../" --warn=0 --asmlist --summary=default,-psect,-class,+mem,-hex,-file --output=default,-inhx032 --runtime=default,+clear,+init,-keep,-no_startup,-download,+config,+clib,+plib --output=-mcof,+elf:multilocs --stack=compiled:auto:auto:auto "--errformat=%f:%l: error: (%n) %s" "--warnformat=%f:%l: warning: (%n) %s" "--msgformat=%f:%l: advisory: (%n) %s" -odist/${CND_CONF}/${IMAGE_TYPE}/MPU6050_raw.X.${IMAGE_TYPE}.${DEBUGGABLE_SUFFIX} ${OBJECTFILES_QUOTED_IF_SPACED} + +endif + + +# Subprojects +.build-subprojects: + + +# Subprojects +.clean-subprojects: + +# Clean Targets +.clean-conf: ${CLEAN_SUBPROJECTS} + ${RM} -r build/default + ${RM} -r dist/default + +# Enable dependency checking +.dep.inc: .depcheck-impl + +DEPFILES=$(shell mplabwildcard ${POSSIBLE_DEPFILES}) +ifneq (${DEPFILES},) +include ${DEPFILES} +endif diff --git a/PIC18/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-genesis.properties b/PIC18/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-genesis.properties new file mode 100644 index 00000000..441f9906 --- /dev/null +++ b/PIC18/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-genesis.properties @@ -0,0 +1,8 @@ +# +#Fri Nov 28 22:55:53 CET 2014 +default.languagetoolchain.dir=C\:\\Program Files (x86)\\Microchip\\xc8\\v1.32\\bin +com-microchip-mplab-nbide-embedded-makeproject-MakeProject.md5=20b996ec0591c93034157100c3d90ac3 +default.languagetoolchain.version=1.32 +host.platform=windows +conf.ids=default +default.com-microchip-mplab-nbide-toolchainXC8-XC8LanguageToolchain.md5=533e5c34133c5d768bcb87ffcec948e1 diff --git a/PIC18/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-impl.mk b/PIC18/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-impl.mk new file mode 100644 index 00000000..8897f7f2 --- /dev/null +++ b/PIC18/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-impl.mk @@ -0,0 +1,69 @@ +# +# Generated Makefile - do not edit! +# +# Edit the Makefile in the project folder instead (../Makefile). Each target +# has a pre- and a post- target defined where you can add customization code. +# +# This makefile implements macros and targets common to all configurations. +# +# NOCDDL + + +# Building and Cleaning subprojects are done by default, but can be controlled with the SUB +# macro. If SUB=no, subprojects will not be built or cleaned. The following macro +# statements set BUILD_SUB-CONF and CLEAN_SUB-CONF to .build-reqprojects-conf +# and .clean-reqprojects-conf unless SUB has the value 'no' +SUB_no=NO +SUBPROJECTS=${SUB_${SUB}} +BUILD_SUBPROJECTS_=.build-subprojects +BUILD_SUBPROJECTS_NO= +BUILD_SUBPROJECTS=${BUILD_SUBPROJECTS_${SUBPROJECTS}} +CLEAN_SUBPROJECTS_=.clean-subprojects +CLEAN_SUBPROJECTS_NO= +CLEAN_SUBPROJECTS=${CLEAN_SUBPROJECTS_${SUBPROJECTS}} + + +# Project Name +PROJECTNAME=MPU6050_raw.X + +# Active Configuration +DEFAULTCONF=default +CONF=${DEFAULTCONF} + +# All Configurations +ALLCONFS=default + + +# build +.build-impl: .build-pre + ${MAKE} -f nbproject/Makefile-${CONF}.mk SUBPROJECTS=${SUBPROJECTS} .build-conf + + +# clean +.clean-impl: .clean-pre + ${MAKE} -f nbproject/Makefile-${CONF}.mk SUBPROJECTS=${SUBPROJECTS} .clean-conf + +# clobber +.clobber-impl: .clobber-pre .depcheck-impl + ${MAKE} SUBPROJECTS=${SUBPROJECTS} CONF=default clean + + + +# all +.all-impl: .all-pre .depcheck-impl + ${MAKE} SUBPROJECTS=${SUBPROJECTS} CONF=default build + + + +# dependency checking support +.depcheck-impl: +# @echo "# This code depends on make tool being used" >.dep.inc +# @if [ -n "${MAKE_VERSION}" ]; then \ +# echo "DEPFILES=\$$(wildcard \$$(addsuffix .d, \$${OBJECTFILES}))" >>.dep.inc; \ +# echo "ifneq (\$${DEPFILES},)" >>.dep.inc; \ +# echo "include \$${DEPFILES}" >>.dep.inc; \ +# echo "endif" >>.dep.inc; \ +# else \ +# echo ".KEEP_STATE:" >>.dep.inc; \ +# echo ".KEEP_STATE_FILE:.make.state.\$${CONF}" >>.dep.inc; \ +# fi diff --git a/PIC18/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-local-default.mk b/PIC18/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-local-default.mk new file mode 100644 index 00000000..dd484ed2 --- /dev/null +++ b/PIC18/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-local-default.mk @@ -0,0 +1,37 @@ +# +# Generated Makefile - do not edit! +# +# +# This file contains information about the location of compilers and other tools. +# If you commmit this file into your revision control server, you will be able to +# to checkout the project and build it from the command line with make. However, +# if more than one person works on the same project, then this file might show +# conflicts since different users are bound to have compilers in different places. +# In that case you might choose to not commit this file and let MPLAB X recreate this file +# for each user. The disadvantage of not commiting this file is that you must run MPLAB X at +# least once so the file gets created and the project can be built. Finally, you can also +# avoid using this file at all if you are only building from the command line with make. +# You can invoke make with the values of the macros: +# $ makeMP_CC="/opt/microchip/mplabc30/v3.30c/bin/pic30-gcc" ... +# +SHELL=cmd.exe +PATH_TO_IDE_BIN=C:/Program Files (x86)/Microchip/MPLABX/mplab_ide/mplab_ide/modules/../../bin/ +# Adding MPLAB X bin directory to path. +PATH:=C:/Program Files (x86)/Microchip/MPLABX/mplab_ide/mplab_ide/modules/../../bin/:$(PATH) +# Path to java used to run MPLAB X when this makefile was created +MP_JAVA_PATH="C:\Program Files (x86)\Microchip\MPLABX\sys\java\jre1.7.0_25-windows-x64\java-windows/bin/" +OS_CURRENT="$(shell uname -s)" +MP_CC="C:\Program Files (x86)\Microchip\xc8\v1.32\bin\xc8.exe" +# MP_CPPC is not defined +# MP_BC is not defined +MP_AS="C:\Program Files (x86)\Microchip\xc8\v1.32\bin\xc8.exe" +# MP_LD is not defined +# MP_AR is not defined +DEP_GEN=${MP_JAVA_PATH}java -jar "C:/Program Files (x86)/Microchip/MPLABX/mplab_ide/mplab_ide/modules/../../bin/extractobjectdependencies.jar" +MP_CC_DIR="C:\Program Files (x86)\Microchip\xc8\v1.32\bin" +# MP_CPPC_DIR is not defined +# MP_BC_DIR is not defined +MP_AS_DIR="C:\Program Files (x86)\Microchip\xc8\v1.32\bin" +# MP_LD_DIR is not defined +# MP_AR_DIR is not defined +# MP_BC_DIR is not defined diff --git a/PIC18/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-variables.mk b/PIC18/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-variables.mk new file mode 100644 index 00000000..623663b1 --- /dev/null +++ b/PIC18/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-variables.mk @@ -0,0 +1,13 @@ +# +# Generated - do not edit! +# +# NOCDDL +# +CND_BASEDIR=`pwd` +# default configuration +CND_ARTIFACT_DIR_default=dist/default/production +CND_ARTIFACT_NAME_default=MPU6050_raw.X.production.hex +CND_ARTIFACT_PATH_default=dist/default/production/MPU6050_raw.X.production.hex +CND_PACKAGE_DIR_default=${CND_DISTDIR}/default/package +CND_PACKAGE_NAME_default=mpu6050raw.x.tar +CND_PACKAGE_PATH_default=${CND_DISTDIR}/default/package/mpu6050raw.x.tar diff --git a/PIC18/MPU6050/Examples/MPU6050_raw.X/nbproject/Package-default.bash b/PIC18/MPU6050/Examples/MPU6050_raw.X/nbproject/Package-default.bash new file mode 100644 index 00000000..2b42e19c --- /dev/null +++ b/PIC18/MPU6050/Examples/MPU6050_raw.X/nbproject/Package-default.bash @@ -0,0 +1,73 @@ +#!/bin/bash -x + +# +# Generated - do not edit! +# + +# Macros +TOP=`pwd` +CND_CONF=default +CND_DISTDIR=dist +TMPDIR=build/${CND_CONF}/${IMAGE_TYPE}/tmp-packaging +TMPDIRNAME=tmp-packaging +OUTPUT_PATH=dist/${CND_CONF}/${IMAGE_TYPE}/MPU6050_raw.X.${IMAGE_TYPE}.${OUTPUT_SUFFIX} +OUTPUT_BASENAME=MPU6050_raw.X.${IMAGE_TYPE}.${OUTPUT_SUFFIX} +PACKAGE_TOP_DIR=mpu6050raw.x/ + +# Functions +function checkReturnCode +{ + rc=$? + if [ $rc != 0 ] + then + exit $rc + fi +} +function makeDirectory +# $1 directory path +# $2 permission (optional) +{ + mkdir -p "$1" + checkReturnCode + if [ "$2" != "" ] + then + chmod $2 "$1" + checkReturnCode + fi +} +function copyFileToTmpDir +# $1 from-file path +# $2 to-file path +# $3 permission +{ + cp "$1" "$2" + checkReturnCode + if [ "$3" != "" ] + then + chmod $3 "$2" + checkReturnCode + fi +} + +# Setup +cd "${TOP}" +mkdir -p ${CND_DISTDIR}/${CND_CONF}/package +rm -rf ${TMPDIR} +mkdir -p ${TMPDIR} + +# Copy files and create directories and links +cd "${TOP}" +makeDirectory ${TMPDIR}/mpu6050raw.x/bin +copyFileToTmpDir "${OUTPUT_PATH}" "${TMPDIR}/${PACKAGE_TOP_DIR}bin/${OUTPUT_BASENAME}" 0755 + + +# Generate tar file +cd "${TOP}" +rm -f ${CND_DISTDIR}/${CND_CONF}/package/mpu6050raw.x.tar +cd ${TMPDIR} +tar -vcf ../../../../${CND_DISTDIR}/${CND_CONF}/package/mpu6050raw.x.tar * +checkReturnCode + +# Cleanup +cd "${TOP}" +rm -rf ${TMPDIR} diff --git a/PIC18/MPU6050/Examples/MPU6050_raw.X/nbproject/configurations.xml b/PIC18/MPU6050/Examples/MPU6050_raw.X/nbproject/configurations.xml new file mode 100644 index 00000000..3b6fba66 --- /dev/null +++ b/PIC18/MPU6050/Examples/MPU6050_raw.X/nbproject/configurations.xml @@ -0,0 +1,173 @@ + + + + + ../../../I2Cdev/I2Cdev.h + ../../MPU6050.h + + + + + ../../MPU6050.c + ../../../I2Cdev/I2Cdev.c + main.c + + + Makefile + + + + C:\Users\sebokmarton\Documents\i2cdevlib\PIC18\I2Cdev + ../.. + + Makefile + + + + localhost + PIC18F46J50 + + + PICkit3PlatformTool + XC8 + 1.32 + 3 + + + + + + + + + + false + false + + + + + false + + false + + false + false + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PIC18/MPU6050/Examples/MPU6050_raw.X/nbproject/project.properties b/PIC18/MPU6050/Examples/MPU6050_raw.X/nbproject/project.properties new file mode 100644 index 00000000..e69de29b diff --git a/PIC18/MPU6050/Examples/MPU6050_raw.X/nbproject/project.xml b/PIC18/MPU6050/Examples/MPU6050_raw.X/nbproject/project.xml new file mode 100644 index 00000000..18806930 --- /dev/null +++ b/PIC18/MPU6050/Examples/MPU6050_raw.X/nbproject/project.xml @@ -0,0 +1,16 @@ + + com.microchip.mplab.nbide.embedded.makeproject + + + MPU6050_raw + 84892e89-df8e-441e-9542-2524d6b2dc5a + 0 + c + + h + + UTF-8 + + + + diff --git a/PIC18/MPU6050/MPU6050.c b/PIC18/MPU6050/MPU6050.c new file mode 100644 index 00000000..2683529a --- /dev/null +++ b/PIC18/MPU6050/MPU6050.c @@ -0,0 +1,3141 @@ +// I2Cdev library collection - MPU6050 I2C device class +// Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00) +// 8/24/2011 by Jeff Rowberg +// 11/28/2014 by Marton Sebok +// +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// ... - ongoing debug release +// 2014-11-28 - ported to PIC18 peripheral library from Arduino code + +// NOTE: THIS IS ONLY A PARIAL RELEASE. THIS DEVICE CLASS IS CURRENTLY UNDERGOING ACTIVE +// DEVELOPMENT AND IS STILL MISSING SOME IMPORTANT FEATURES. PLEASE KEEP THIS IN MIND IF +// YOU DECIDE TO USE THIS PARTICULAR CODE FOR ANYTHING. + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2012 Jeff Rowberg +Copyright (c) 2014 Marton Sebok + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#include "MPU6050.h" + +MPU6050_t mpu6050; + +/** Specific address constructor. + * @param address I2C address + * @see MPU6050_DEFAULT_ADDRESS + * @see MPU6050_ADDRESS_AD0_LOW + * @see MPU6050_ADDRESS_AD0_HIGH + */ +void MPU6050(uint8_t address) { + mpu6050.devAddr = address; +} + +/** Power on and prepare for general usage. + * This will activate the device and take it out of sleep mode (which must be done + * after start-up). This function also sets both the accelerometer and the gyroscope + * to their most sensitive settings, namely +/- 2g and +/- 250 degrees/sec, and sets + * the clock source to use the X Gyro for reference, which is slightly better than + * the default internal clock source. + */ +void MPU6050_initialize() { + MPU6050_setClockSource(MPU6050_CLOCK_PLL_XGYRO); + MPU6050_setFullScaleGyroRange(MPU6050_GYRO_FS_250); + MPU6050_setFullScaleAccelRange(MPU6050_ACCEL_FS_2); + MPU6050_setSleepEnabled(false); // thanks to Jack Elston for pointing this one out! +} + +/** Verify the I2C connection. + * Make sure the device is connected and responds as expected. + * @return True if connection is valid, false otherwise + */ +bool MPU6050_testConnection() { + return MPU6050_getDeviceID() == 0x34; +} + +// AUX_VDDIO register (InvenSense demo code calls this RA_*G_OFFS_TC) + +/** Get the auxiliary I2C supply voltage level. + * When set to 1, the auxiliary I2C bus high logic level is VDD. When cleared to + * 0, the auxiliary I2C bus high logic level is VLOGIC. This does not apply to + * the MPU-6000, which does not have a VLOGIC pin. + * @return I2C supply voltage level (0=VLOGIC, 1=VDD) + */ +uint8_t MPU6050_getAuxVDDIOLevel() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_PWR_MODE_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set the auxiliary I2C supply voltage level. + * When set to 1, the auxiliary I2C bus high logic level is VDD. When cleared to + * 0, the auxiliary I2C bus high logic level is VLOGIC. This does not apply to + * the MPU-6000, which does not have a VLOGIC pin. + * @param level I2C supply voltage level (0=VLOGIC, 1=VDD) + */ +void MPU6050_setAuxVDDIOLevel(uint8_t level) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_PWR_MODE_BIT, level); +} + +// SMPLRT_DIV register + +/** Get gyroscope output rate divider. + * The sensor register output, FIFO output, DMP sampling, Motion detection, Zero + * Motion detection, and Free Fall detection are all based on the Sample Rate. + * The Sample Rate is generated by dividing the gyroscope output rate by + * SMPLRT_DIV: + * + * Sample Rate = Gyroscope Output Rate / (1 + SMPLRT_DIV) + * + * where Gyroscope Output Rate = 8kHz when the DLPF is disabled (DLPF_CFG = 0 or + * 7), and 1kHz when the DLPF is enabled (see Register 26). + * + * Note: The accelerometer output rate is 1kHz. This means that for a Sample + * Rate greater than 1kHz, the same accelerometer sample may be output to the + * FIFO, DMP, and sensor registers more than once. + * + * For a diagram of the gyroscope and accelerometer signal paths, see Section 8 + * of the MPU-6000/MPU-6050 Product Specification document. + * + * @return Current sample rate + * @see MPU6050_RA_SMPLRT_DIV + */ +uint8_t MPU6050_getRate() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_SMPLRT_DIV, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set gyroscope sample rate divider. + * @param rate New sample rate divider + * @see getRate() + * @see MPU6050_RA_SMPLRT_DIV + */ +void MPU6050_setRate(uint8_t rate) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_SMPLRT_DIV, rate); +} + +// CONFIG register + +/** Get external FSYNC configuration. + * Configures the external Frame Synchronization (FSYNC) pin sampling. An + * external signal connected to the FSYNC pin can be sampled by configuring + * EXT_SYNC_SET. Signal changes to the FSYNC pin are latched so that short + * strobes may be captured. The latched FSYNC signal will be sampled at the + * Sampling Rate, as defined in register 25. After sampling, the latch will + * reset to the current FSYNC signal state. + * + * The sampled value will be reported in place of the least significant bit in + * a sensor data register determined by the value of EXT_SYNC_SET according to + * the following table. + * + *
+ * EXT_SYNC_SET | FSYNC Bit Location
+ * -------------+-------------------
+ * 0            | Input disabled
+ * 1            | TEMP_OUT_L[0]
+ * 2            | GYRO_XOUT_L[0]
+ * 3            | GYRO_YOUT_L[0]
+ * 4            | GYRO_ZOUT_L[0]
+ * 5            | ACCEL_XOUT_L[0]
+ * 6            | ACCEL_YOUT_L[0]
+ * 7            | ACCEL_ZOUT_L[0]
+ * 
+ * + * @return FSYNC configuration value + */ +uint8_t MPU6050_getExternalFrameSync() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_EXT_SYNC_SET_BIT, MPU6050_CFG_EXT_SYNC_SET_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set external FSYNC configuration. + * @see getExternalFrameSync() + * @see MPU6050_RA_CONFIG + * @param sync New FSYNC configuration value + */ +void MPU6050_setExternalFrameSync(uint8_t sync) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_EXT_SYNC_SET_BIT, MPU6050_CFG_EXT_SYNC_SET_LENGTH, sync); +} +/** Get digital low-pass filter configuration. + * The DLPF_CFG parameter sets the digital low pass filter configuration. It + * also determines the internal sampling rate used by the device as shown in + * the table below. + * + * Note: The accelerometer output rate is 1kHz. This means that for a Sample + * Rate greater than 1kHz, the same accelerometer sample may be output to the + * FIFO, DMP, and sensor registers more than once. + * + *
+ *          |   ACCELEROMETER    |           GYROSCOPE
+ * DLPF_CFG | Bandwidth | Delay  | Bandwidth | Delay  | Sample Rate
+ * ---------+-----------+--------+-----------+--------+-------------
+ * 0        | 260Hz     | 0ms    | 256Hz     | 0.98ms | 8kHz
+ * 1        | 184Hz     | 2.0ms  | 188Hz     | 1.9ms  | 1kHz
+ * 2        | 94Hz      | 3.0ms  | 98Hz      | 2.8ms  | 1kHz
+ * 3        | 44Hz      | 4.9ms  | 42Hz      | 4.8ms  | 1kHz
+ * 4        | 21Hz      | 8.5ms  | 20Hz      | 8.3ms  | 1kHz
+ * 5        | 10Hz      | 13.8ms | 10Hz      | 13.4ms | 1kHz
+ * 6        | 5Hz       | 19.0ms | 5Hz       | 18.6ms | 1kHz
+ * 7        |   -- Reserved --   |   -- Reserved --   | Reserved
+ * 
+ * + * @return DLFP configuration + * @see MPU6050_RA_CONFIG + * @see MPU6050_CFG_DLPF_CFG_BIT + * @see MPU6050_CFG_DLPF_CFG_LENGTH + */ +uint8_t MPU6050_getDLPFMode() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_DLPF_CFG_BIT, MPU6050_CFG_DLPF_CFG_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set digital low-pass filter configuration. + * @param mode New DLFP configuration setting + * @see getDLPFBandwidth() + * @see MPU6050_DLPF_BW_256 + * @see MPU6050_RA_CONFIG + * @see MPU6050_CFG_DLPF_CFG_BIT + * @see MPU6050_CFG_DLPF_CFG_LENGTH + */ +void MPU6050_setDLPFMode(uint8_t mode) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_DLPF_CFG_BIT, MPU6050_CFG_DLPF_CFG_LENGTH, mode); +} + +// GYRO_CONFIG register + +/** Get full-scale gyroscope range. + * The FS_SEL parameter allows setting the full-scale range of the gyro sensors, + * as described in the table below. + * + *
+ * 0 = +/- 250 degrees/sec
+ * 1 = +/- 500 degrees/sec
+ * 2 = +/- 1000 degrees/sec
+ * 3 = +/- 2000 degrees/sec
+ * 
+ * + * @return Current full-scale gyroscope range setting + * @see MPU6050_GYRO_FS_250 + * @see MPU6050_RA_GYRO_CONFIG + * @see MPU6050_GCONFIG_FS_SEL_BIT + * @see MPU6050_GCONFIG_FS_SEL_LENGTH + */ +uint8_t MPU6050_getFullScaleGyroRange() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set full-scale gyroscope range. + * @param range New full-scale gyroscope range value + * @see getFullScaleRange() + * @see MPU6050_GYRO_FS_250 + * @see MPU6050_RA_GYRO_CONFIG + * @see MPU6050_GCONFIG_FS_SEL_BIT + * @see MPU6050_GCONFIG_FS_SEL_LENGTH + */ +void MPU6050_setFullScaleGyroRange(uint8_t range) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, range); +} + +// ACCEL_CONFIG register + +/** Get self-test enabled setting for accelerometer X axis. + * @return Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +bool MPU6050_getAccelXSelfTest() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_XA_ST_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get self-test enabled setting for accelerometer X axis. + * @param enabled Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050_setAccelXSelfTest(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_XA_ST_BIT, enabled); +} +/** Get self-test enabled value for accelerometer Y axis. + * @return Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +bool MPU6050_getAccelYSelfTest() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_YA_ST_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get self-test enabled value for accelerometer Y axis. + * @param enabled Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050_setAccelYSelfTest(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_YA_ST_BIT, enabled); +} +/** Get self-test enabled value for accelerometer Z axis. + * @return Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +bool MPU6050_getAccelZSelfTest() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ZA_ST_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set self-test enabled value for accelerometer Z axis. + * @param enabled Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050_setAccelZSelfTest(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ZA_ST_BIT, enabled); +} +/** Get full-scale accelerometer range. + * The FS_SEL parameter allows setting the full-scale range of the accelerometer + * sensors, as described in the table below. + * + *
+ * 0 = +/- 2g
+ * 1 = +/- 4g
+ * 2 = +/- 8g
+ * 3 = +/- 16g
+ * 
+ * + * @return Current full-scale accelerometer range setting + * @see MPU6050_ACCEL_FS_2 + * @see MPU6050_RA_ACCEL_CONFIG + * @see MPU6050_ACONFIG_AFS_SEL_BIT + * @see MPU6050_ACONFIG_AFS_SEL_LENGTH + */ +uint8_t MPU6050_getFullScaleAccelRange() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set full-scale accelerometer range. + * @param range New full-scale accelerometer range setting + * @see getFullScaleAccelRange() + */ +void MPU6050_setFullScaleAccelRange(uint8_t range) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, range); +} +/** Get the high-pass filter configuration. + * The DHPF is a filter module in the path leading to motion detectors (Free + * Fall, Motion threshold, and Zero Motion). The high pass filter output is not + * available to the data registers (see Figure in Section 8 of the MPU-6000/ + * MPU-6050 Product Specification document). + * + * The high pass filter has three modes: + * + *
+ *    Reset: The filter output settles to zero within one sample. This
+ *           effectively disables the high pass filter. This mode may be toggled
+ *           to quickly settle the filter.
+ *
+ *    On:    The high pass filter will pass signals above the cut off frequency.
+ *
+ *    Hold:  When triggered, the filter holds the present sample. The filter
+ *           output will be the difference between the input sample and the held
+ *           sample.
+ * 
+ * + *
+ * ACCEL_HPF | Filter Mode | Cut-off Frequency
+ * ----------+-------------+------------------
+ * 0         | Reset       | None
+ * 1         | On          | 5Hz
+ * 2         | On          | 2.5Hz
+ * 3         | On          | 1.25Hz
+ * 4         | On          | 0.63Hz
+ * 7         | Hold        | None
+ * 
+ * + * @return Current high-pass filter configuration + * @see MPU6050_DHPF_RESET + * @see MPU6050_RA_ACCEL_CONFIG + */ +uint8_t MPU6050_getDHPFMode() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ACCEL_HPF_BIT, MPU6050_ACONFIG_ACCEL_HPF_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set the high-pass filter configuration. + * @param bandwidth New high-pass filter configuration + * @see setDHPFMode() + * @see MPU6050_DHPF_RESET + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050_setDHPFMode(uint8_t bandwidth) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ACCEL_HPF_BIT, MPU6050_ACONFIG_ACCEL_HPF_LENGTH, bandwidth); +} + +// FF_THR register + +/** Get free-fall event acceleration threshold. + * This register configures the detection threshold for Free Fall event + * detection. The unit of FF_THR is 1LSB = 2mg. Free Fall is detected when the + * absolute value of the accelerometer measurements for the three axes are each + * less than the detection threshold. This condition increments the Free Fall + * duration counter (Register 30). The Free Fall interrupt is triggered when the + * Free Fall duration counter reaches the time specified in FF_DUR. + * + * For more details on the Free Fall detection interrupt, see Section 8.2 of the + * MPU-6000/MPU-6050 Product Specification document as well as Registers 56 and + * 58 of this document. + * + * @return Current free-fall acceleration threshold value (LSB = 2mg) + * @see MPU6050_RA_FF_THR + */ +uint8_t MPU6050_getFreefallDetectionThreshold() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_FF_THR, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get free-fall event acceleration threshold. + * @param threshold New free-fall acceleration threshold value (LSB = 2mg) + * @see getFreefallDetectionThreshold() + * @see MPU6050_RA_FF_THR + */ +void MPU6050_setFreefallDetectionThreshold(uint8_t threshold) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_FF_THR, threshold); +} + +// FF_DUR register + +/** Get free-fall event duration threshold. + * This register configures the duration counter threshold for Free Fall event + * detection. The duration counter ticks at 1kHz, therefore FF_DUR has a unit + * of 1 LSB = 1 ms. + * + * The Free Fall duration counter increments while the absolute value of the + * accelerometer measurements are each less than the detection threshold + * (Register 29). The Free Fall interrupt is triggered when the Free Fall + * duration counter reaches the time specified in this register. + * + * For more details on the Free Fall detection interrupt, see Section 8.2 of + * the MPU-6000/MPU-6050 Product Specification document as well as Registers 56 + * and 58 of this document. + * + * @return Current free-fall duration threshold value (LSB = 1ms) + * @see MPU6050_RA_FF_DUR + */ +uint8_t MPU6050_getFreefallDetectionDuration() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_FF_DUR, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get free-fall event duration threshold. + * @param duration New free-fall duration threshold value (LSB = 1ms) + * @see getFreefallDetectionDuration() + * @see MPU6050_RA_FF_DUR + */ +void MPU6050_setFreefallDetectionDuration(uint8_t duration) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_FF_DUR, duration); +} + +// MOT_THR register + +/** Get motion detection event acceleration threshold. + * This register configures the detection threshold for Motion interrupt + * generation. The unit of MOT_THR is 1LSB = 2mg. Motion is detected when the + * absolute value of any of the accelerometer measurements exceeds this Motion + * detection threshold. This condition increments the Motion detection duration + * counter (Register 32). The Motion detection interrupt is triggered when the + * Motion Detection counter reaches the time count specified in MOT_DUR + * (Register 32). + * + * The Motion interrupt will indicate the axis and polarity of detected motion + * in MOT_DETECT_STATUS (Register 97). + * + * For more details on the Motion detection interrupt, see Section 8.3 of the + * MPU-6000/MPU-6050 Product Specification document as well as Registers 56 and + * 58 of this document. + * + * @return Current motion detection acceleration threshold value (LSB = 2mg) + * @see MPU6050_RA_MOT_THR + */ +uint8_t MPU6050_getMotionDetectionThreshold() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_MOT_THR, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set free-fall event acceleration threshold. + * @param threshold New motion detection acceleration threshold value (LSB = 2mg) + * @see getMotionDetectionThreshold() + * @see MPU6050_RA_MOT_THR + */ +void MPU6050_setMotionDetectionThreshold(uint8_t threshold) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_MOT_THR, threshold); +} + +// MOT_DUR register + +/** Get motion detection event duration threshold. + * This register configures the duration counter threshold for Motion interrupt + * generation. The duration counter ticks at 1 kHz, therefore MOT_DUR has a unit + * of 1LSB = 1ms. The Motion detection duration counter increments when the + * absolute value of any of the accelerometer measurements exceeds the Motion + * detection threshold (Register 31). The Motion detection interrupt is + * triggered when the Motion detection counter reaches the time count specified + * in this register. + * + * For more details on the Motion detection interrupt, see Section 8.3 of the + * MPU-6000/MPU-6050 Product Specification document. + * + * @return Current motion detection duration threshold value (LSB = 1ms) + * @see MPU6050_RA_MOT_DUR + */ +uint8_t MPU6050_getMotionDetectionDuration() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_MOT_DUR, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set motion detection event duration threshold. + * @param duration New motion detection duration threshold value (LSB = 1ms) + * @see getMotionDetectionDuration() + * @see MPU6050_RA_MOT_DUR + */ +void MPU6050_setMotionDetectionDuration(uint8_t duration) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_MOT_DUR, duration); +} + +// ZRMOT_THR register + +/** Get zero motion detection event acceleration threshold. + * This register configures the detection threshold for Zero Motion interrupt + * generation. The unit of ZRMOT_THR is 1LSB = 2mg. Zero Motion is detected when + * the absolute value of the accelerometer measurements for the 3 axes are each + * less than the detection threshold. This condition increments the Zero Motion + * duration counter (Register 34). The Zero Motion interrupt is triggered when + * the Zero Motion duration counter reaches the time count specified in + * ZRMOT_DUR (Register 34). + * + * Unlike Free Fall or Motion detection, Zero Motion detection triggers an + * interrupt both when Zero Motion is first detected and when Zero Motion is no + * longer detected. + * + * When a zero motion event is detected, a Zero Motion Status will be indicated + * in the MOT_DETECT_STATUS register (Register 97). When a motion-to-zero-motion + * condition is detected, the status bit is set to 1. When a zero-motion-to- + * motion condition is detected, the status bit is set to 0. + * + * For more details on the Zero Motion detection interrupt, see Section 8.4 of + * the MPU-6000/MPU-6050 Product Specification document as well as Registers 56 + * and 58 of this document. + * + * @return Current zero motion detection acceleration threshold value (LSB = 2mg) + * @see MPU6050_RA_ZRMOT_THR + */ +uint8_t MPU6050_getZeroMotionDetectionThreshold() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_ZRMOT_THR, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set zero motion detection event acceleration threshold. + * @param threshold New zero motion detection acceleration threshold value (LSB = 2mg) + * @see getZeroMotionDetectionThreshold() + * @see MPU6050_RA_ZRMOT_THR + */ +void MPU6050_setZeroMotionDetectionThreshold(uint8_t threshold) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_ZRMOT_THR, threshold); +} + +// ZRMOT_DUR register + +/** Get zero motion detection event duration threshold. + * This register configures the duration counter threshold for Zero Motion + * interrupt generation. The duration counter ticks at 16 Hz, therefore + * ZRMOT_DUR has a unit of 1 LSB = 64 ms. The Zero Motion duration counter + * increments while the absolute value of the accelerometer measurements are + * each less than the detection threshold (Register 33). The Zero Motion + * interrupt is triggered when the Zero Motion duration counter reaches the time + * count specified in this register. + * + * For more details on the Zero Motion detection interrupt, see Section 8.4 of + * the MPU-6000/MPU-6050 Product Specification document, as well as Registers 56 + * and 58 of this document. + * + * @return Current zero motion detection duration threshold value (LSB = 64ms) + * @see MPU6050_RA_ZRMOT_DUR + */ +uint8_t MPU6050_getZeroMotionDetectionDuration() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_ZRMOT_DUR, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set zero motion detection event duration threshold. + * @param duration New zero motion detection duration threshold value (LSB = 1ms) + * @see getZeroMotionDetectionDuration() + * @see MPU6050_RA_ZRMOT_DUR + */ +void MPU6050_setZeroMotionDetectionDuration(uint8_t duration) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_ZRMOT_DUR, duration); +} + +// FIFO_EN register + +/** Get temperature FIFO enabled value. + * When set to 1, this bit enables TEMP_OUT_H and TEMP_OUT_L (Registers 65 and + * 66) to be written into the FIFO mpu6050.buffer. + * @return Current temperature FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_getTempFIFOEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_TEMP_FIFO_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set temperature FIFO enabled value. + * @param enabled New temperature FIFO enabled value + * @see getTempFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setTempFIFOEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_TEMP_FIFO_EN_BIT, enabled); +} +/** Get gyroscope X-axis FIFO enabled value. + * When set to 1, this bit enables GYRO_XOUT_H and GYRO_XOUT_L (Registers 67 and + * 68) to be written into the FIFO mpu6050.buffer. + * @return Current gyroscope X-axis FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_getXGyroFIFOEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_XG_FIFO_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set gyroscope X-axis FIFO enabled value. + * @param enabled New gyroscope X-axis FIFO enabled value + * @see getXGyroFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setXGyroFIFOEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_XG_FIFO_EN_BIT, enabled); +} +/** Get gyroscope Y-axis FIFO enabled value. + * When set to 1, this bit enables GYRO_YOUT_H and GYRO_YOUT_L (Registers 69 and + * 70) to be written into the FIFO mpu6050.buffer. + * @return Current gyroscope Y-axis FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_getYGyroFIFOEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_YG_FIFO_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set gyroscope Y-axis FIFO enabled value. + * @param enabled New gyroscope Y-axis FIFO enabled value + * @see getYGyroFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setYGyroFIFOEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_YG_FIFO_EN_BIT, enabled); +} +/** Get gyroscope Z-axis FIFO enabled value. + * When set to 1, this bit enables GYRO_ZOUT_H and GYRO_ZOUT_L (Registers 71 and + * 72) to be written into the FIFO mpu6050.buffer. + * @return Current gyroscope Z-axis FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_getZGyroFIFOEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_ZG_FIFO_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set gyroscope Z-axis FIFO enabled value. + * @param enabled New gyroscope Z-axis FIFO enabled value + * @see getZGyroFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setZGyroFIFOEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_ZG_FIFO_EN_BIT, enabled); +} +/** Get accelerometer FIFO enabled value. + * When set to 1, this bit enables ACCEL_XOUT_H, ACCEL_XOUT_L, ACCEL_YOUT_H, + * ACCEL_YOUT_L, ACCEL_ZOUT_H, and ACCEL_ZOUT_L (Registers 59 to 64) to be + * written into the FIFO mpu6050.buffer. + * @return Current accelerometer FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_getAccelFIFOEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_ACCEL_FIFO_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set accelerometer FIFO enabled value. + * @param enabled New accelerometer FIFO enabled value + * @see getAccelFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setAccelFIFOEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_ACCEL_FIFO_EN_BIT, enabled); +} +/** Get Slave 2 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 2 to be written into the FIFO mpu6050.buffer. + * @return Current Slave 2 FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_getSlave2FIFOEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV2_FIFO_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Slave 2 FIFO enabled value. + * @param enabled New Slave 2 FIFO enabled value + * @see getSlave2FIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setSlave2FIFOEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV2_FIFO_EN_BIT, enabled); +} +/** Get Slave 1 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 1 to be written into the FIFO mpu6050.buffer. + * @return Current Slave 1 FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_getSlave1FIFOEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV1_FIFO_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Slave 1 FIFO enabled value. + * @param enabled New Slave 1 FIFO enabled value + * @see getSlave1FIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setSlave1FIFOEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV1_FIFO_EN_BIT, enabled); +} +/** Get Slave 0 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 0 to be written into the FIFO mpu6050.buffer. + * @return Current Slave 0 FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_getSlave0FIFOEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV0_FIFO_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Slave 0 FIFO enabled value. + * @param enabled New Slave 0 FIFO enabled value + * @see getSlave0FIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setSlave0FIFOEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV0_FIFO_EN_BIT, enabled); +} + +// I2C_MST_CTRL register + +/** Get multi-master enabled value. + * Multi-master capability allows multiple I2C masters to operate on the same + * bus. In circuits where multi-master capability is required, set MULT_MST_EN + * to 1. This will increase current drawn by approximately 30uA. + * + * In circuits where multi-master capability is required, the state of the I2C + * bus must always be monitored by each separate I2C Master. Before an I2C + * Master can assume arbitration of the bus, it must first confirm that no other + * I2C Master has arbitration of the bus. When MULT_MST_EN is set to 1, the + * MPU-60X0's bus arbitration detection logic is turned on, enabling it to + * detect when the bus is available. + * + * @return Current multi-master enabled value + * @see MPU6050_RA_I2C_MST_CTRL + */ +bool MPU6050_getMultiMasterEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_MULT_MST_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set multi-master enabled value. + * @param enabled New multi-master enabled value + * @see getMultiMasterEnabled() + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050_setMultiMasterEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_MULT_MST_EN_BIT, enabled); +} +/** Get wait-for-external-sensor-data enabled value. + * When the WAIT_FOR_ES bit is set to 1, the Data Ready interrupt will be + * delayed until External Sensor data from the Slave Devices are loaded into the + * EXT_SENS_DATA registers. This is used to ensure that both the internal sensor + * data (i.e. from gyro and accel) and external sensor data have been loaded to + * their respective data registers (i.e. the data is synced) when the Data Ready + * interrupt is triggered. + * + * @return Current wait-for-external-sensor-data enabled value + * @see MPU6050_RA_I2C_MST_CTRL + */ +bool MPU6050_getWaitForExternalSensorEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_WAIT_FOR_ES_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set wait-for-external-sensor-data enabled value. + * @param enabled New wait-for-external-sensor-data enabled value + * @see getWaitForExternalSensorEnabled() + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050_setWaitForExternalSensorEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_WAIT_FOR_ES_BIT, enabled); +} +/** Get Slave 3 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 3 to be written into the FIFO mpu6050.buffer. + * @return Current Slave 3 FIFO enabled value + * @see MPU6050_RA_MST_CTRL + */ +bool MPU6050_getSlave3FIFOEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_SLV_3_FIFO_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Slave 3 FIFO enabled value. + * @param enabled New Slave 3 FIFO enabled value + * @see getSlave3FIFOEnabled() + * @see MPU6050_RA_MST_CTRL + */ +void MPU6050_setSlave3FIFOEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_SLV_3_FIFO_EN_BIT, enabled); +} +/** Get slave read/write transition enabled value. + * The I2C_MST_P_NSR bit configures the I2C Master's transition from one slave + * read to the next slave read. If the bit equals 0, there will be a restart + * between reads. If the bit equals 1, there will be a stop followed by a start + * of the following read. When a write transaction follows a read transaction, + * the stop followed by a start of the successive write will be always used. + * + * @return Current slave read/write transition enabled value + * @see MPU6050_RA_I2C_MST_CTRL + */ +bool MPU6050_getSlaveReadWriteTransitionEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_P_NSR_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set slave read/write transition enabled value. + * @param enabled New slave read/write transition enabled value + * @see getSlaveReadWriteTransitionEnabled() + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050_setSlaveReadWriteTransitionEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_P_NSR_BIT, enabled); +} +/** Get I2C master clock speed. + * I2C_MST_CLK is a 4 bit unsigned value which configures a divider on the + * MPU-60X0 internal 8MHz clock. It sets the I2C master clock speed according to + * the following table: + * + *
+ * I2C_MST_CLK | I2C Master Clock Speed | 8MHz Clock Divider
+ * ------------+------------------------+-------------------
+ * 0           | 348kHz                 | 23
+ * 1           | 333kHz                 | 24
+ * 2           | 320kHz                 | 25
+ * 3           | 308kHz                 | 26
+ * 4           | 296kHz                 | 27
+ * 5           | 286kHz                 | 28
+ * 6           | 276kHz                 | 29
+ * 7           | 267kHz                 | 30
+ * 8           | 258kHz                 | 31
+ * 9           | 500kHz                 | 16
+ * 10          | 471kHz                 | 17
+ * 11          | 444kHz                 | 18
+ * 12          | 421kHz                 | 19
+ * 13          | 400kHz                 | 20
+ * 14          | 381kHz                 | 21
+ * 15          | 364kHz                 | 22
+ * 
+ * + * @return Current I2C master clock speed + * @see MPU6050_RA_I2C_MST_CTRL + */ +uint8_t MPU6050_getMasterClockSpeed() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_CLK_BIT, MPU6050_I2C_MST_CLK_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set I2C master clock speed. + * @reparam speed Current I2C master clock speed + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050_setMasterClockSpeed(uint8_t speed) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_CLK_BIT, MPU6050_I2C_MST_CLK_LENGTH, speed); +} + +// I2C_SLV* registers (Slave 0-3) + +/** Get the I2C address of the specified slave (0-3). + * Note that Bit 7 (MSB) controls read/write mode. If Bit 7 is set, it's a read + * operation, and if it is cleared, then it's a write operation. The remaining + * bits (6-0) are the 7-bit device address of the slave device. + * + * In read mode, the result of the read is placed in the lowest available + * EXT_SENS_DATA register. For further information regarding the allocation of + * read results, please refer to the EXT_SENS_DATA register description + * (Registers 73 - 96). + * + * The MPU-6050 supports a total of five slaves, but Slave 4 has unique + * characteristics, and so it has its own functions (getSlave4* and setSlave4*). + * + * I2C data transactions are performed at the Sample Rate, as defined in + * Register 25. The user is responsible for ensuring that I2C data transactions + * to and from each enabled Slave can be completed within a single period of the + * Sample Rate. + * + * The I2C slave access rate can be reduced relative to the Sample Rate. This + * reduced access rate is determined by I2C_MST_DLY (Register 52). Whether a + * slave's access rate is reduced relative to the Sample Rate is determined by + * I2C_MST_DELAY_CTRL (Register 103). + * + * The processing order for the slaves is fixed. The sequence followed for + * processing the slaves is Slave 0, Slave 1, Slave 2, Slave 3 and Slave 4. If a + * particular Slave is disabled it will be skipped. + * + * Each slave can either be accessed at the sample rate or at a reduced sample + * rate. In a case where some slaves are accessed at the Sample Rate and some + * slaves are accessed at the reduced rate, the sequence of accessing the slaves + * (Slave 0 to Slave 4) is still followed. However, the reduced rate slaves will + * be skipped if their access rate dictates that they should not be accessed + * during that particular cycle. For further information regarding the reduced + * access rate, please refer to Register 52. Whether a slave is accessed at the + * Sample Rate or at the reduced rate is determined by the Delay Enable bits in + * Register 103. + * + * @param num Slave number (0-3) + * @return Current address for specified slave + * @see MPU6050_RA_I2C_SLV0_ADDR + */ +uint8_t MPU6050_getSlaveAddress(uint8_t num) { + if (num > 3) return 0; + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_ADDR + num*3, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set the I2C address of the specified slave (0-3). + * @param num Slave number (0-3) + * @param address New address for specified slave + * @see getSlaveAddress() + * @see MPU6050_RA_I2C_SLV0_ADDR + */ +void MPU6050_setSlaveAddress(uint8_t num, uint8_t address) { + if (num > 3) return; + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_ADDR + num*3, address); +} +/** Get the active internal register for the specified slave (0-3). + * Read/write operations for this slave will be done to whatever internal + * register address is stored in this MPU register. + * + * The MPU-6050 supports a total of five slaves, but Slave 4 has unique + * characteristics, and so it has its own functions. + * + * @param num Slave number (0-3) + * @return Current active register for specified slave + * @see MPU6050_RA_I2C_SLV0_REG + */ +uint8_t MPU6050_getSlaveRegister(uint8_t num) { + if (num > 3) return 0; + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_REG + num*3, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set the active internal register for the specified slave (0-3). + * @param num Slave number (0-3) + * @param reg New active register for specified slave + * @see getSlaveRegister() + * @see MPU6050_RA_I2C_SLV0_REG + */ +void MPU6050_setSlaveRegister(uint8_t num, uint8_t reg) { + if (num > 3) return; + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_REG + num*3, reg); +} +/** Get the enabled value for the specified slave (0-3). + * When set to 1, this bit enables Slave 0 for data transfer operations. When + * cleared to 0, this bit disables Slave 0 from data transfer operations. + * @param num Slave number (0-3) + * @return Current enabled value for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +bool MPU6050_getSlaveEnabled(uint8_t num) { + if (num > 3) return 0; + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set the enabled value for the specified slave (0-3). + * @param num Slave number (0-3) + * @param enabled New enabled value for specified slave + * @see getSlaveEnabled() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050_setSlaveEnabled(uint8_t num, bool enabled) { + if (num > 3) return; + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_EN_BIT, enabled); +} +/** Get word pair byte-swapping enabled for the specified slave (0-3). + * When set to 1, this bit enables byte swapping. When byte swapping is enabled, + * the high and low bytes of a word pair are swapped. Please refer to + * I2C_SLV0_GRP for the pairing convention of the word pairs. When cleared to 0, + * bytes transferred to and from Slave 0 will be written to EXT_SENS_DATA + * registers in the order they were transferred. + * + * @param num Slave number (0-3) + * @return Current word pair byte-swapping enabled value for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +bool MPU6050_getSlaveWordByteSwap(uint8_t num) { + if (num > 3) return 0; + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_BYTE_SW_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set word pair byte-swapping enabled for the specified slave (0-3). + * @param num Slave number (0-3) + * @param enabled New word pair byte-swapping enabled value for specified slave + * @see getSlaveWordByteSwap() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050_setSlaveWordByteSwap(uint8_t num, bool enabled) { + if (num > 3) return; + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_BYTE_SW_BIT, enabled); +} +/** Get write mode for the specified slave (0-3). + * When set to 1, the transaction will read or write data only. When cleared to + * 0, the transaction will write a register address prior to reading or writing + * data. This should equal 0 when specifying the register address within the + * Slave device to/from which the ensuing data transaction will take place. + * + * @param num Slave number (0-3) + * @return Current write mode for specified slave (0 = register address + data, 1 = data only) + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +bool MPU6050_getSlaveWriteMode(uint8_t num) { + if (num > 3) return 0; + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_REG_DIS_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set write mode for the specified slave (0-3). + * @param num Slave number (0-3) + * @param mode New write mode for specified slave (0 = register address + data, 1 = data only) + * @see getSlaveWriteMode() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050_setSlaveWriteMode(uint8_t num, bool mode) { + if (num > 3) return; + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_REG_DIS_BIT, mode); +} +/** Get word pair grouping order offset for the specified slave (0-3). + * This sets specifies the grouping order of word pairs received from registers. + * When cleared to 0, bytes from register addresses 0 and 1, 2 and 3, etc (even, + * then odd register addresses) are paired to form a word. When set to 1, bytes + * from register addresses are paired 1 and 2, 3 and 4, etc. (odd, then even + * register addresses) are paired to form a word. + * + * @param num Slave number (0-3) + * @return Current word pair grouping order offset for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +bool MPU6050_getSlaveWordGroupOffset(uint8_t num) { + if (num > 3) return 0; + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_GRP_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set word pair grouping order offset for the specified slave (0-3). + * @param num Slave number (0-3) + * @param enabled New word pair grouping order offset for specified slave + * @see getSlaveWordGroupOffset() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050_setSlaveWordGroupOffset(uint8_t num, bool enabled) { + if (num > 3) return; + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_GRP_BIT, enabled); +} +/** Get number of bytes to read for the specified slave (0-3). + * Specifies the number of bytes transferred to and from Slave 0. Clearing this + * bit to 0 is equivalent to disabling the register by writing 0 to I2C_SLV0_EN. + * @param num Slave number (0-3) + * @return Number of bytes to read for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +uint8_t MPU6050_getSlaveDataLength(uint8_t num) { + if (num > 3) return 0; + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_LEN_BIT, MPU6050_I2C_SLV_LEN_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set number of bytes to read for the specified slave (0-3). + * @param num Slave number (0-3) + * @param length Number of bytes to read for specified slave + * @see getSlaveDataLength() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050_setSlaveDataLength(uint8_t num, uint8_t length) { + if (num > 3) return; + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_LEN_BIT, MPU6050_I2C_SLV_LEN_LENGTH, length); +} + +// I2C_SLV* registers (Slave 4) + +/** Get the I2C address of Slave 4. + * Note that Bit 7 (MSB) controls read/write mode. If Bit 7 is set, it's a read + * operation, and if it is cleared, then it's a write operation. The remaining + * bits (6-0) are the 7-bit device address of the slave device. + * + * @return Current address for Slave 4 + * @see getSlaveAddress() + * @see MPU6050_RA_I2C_SLV4_ADDR + */ +uint8_t MPU6050_getSlave4Address() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_ADDR, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set the I2C address of Slave 4. + * @param address New address for Slave 4 + * @see getSlave4Address() + * @see MPU6050_RA_I2C_SLV4_ADDR + */ +void MPU6050_setSlave4Address(uint8_t address) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_ADDR, address); +} +/** Get the active internal register for the Slave 4. + * Read/write operations for this slave will be done to whatever internal + * register address is stored in this MPU register. + * + * @return Current active register for Slave 4 + * @see MPU6050_RA_I2C_SLV4_REG + */ +uint8_t MPU6050_getSlave4Register() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_REG, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set the active internal register for Slave 4. + * @param reg New active register for Slave 4 + * @see getSlave4Register() + * @see MPU6050_RA_I2C_SLV4_REG + */ +void MPU6050_setSlave4Register(uint8_t reg) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_REG, reg); +} +/** Set new byte to write to Slave 4. + * This register stores the data to be written into the Slave 4. If I2C_SLV4_RW + * is set 1 (set to read), this register has no effect. + * @param data New byte to write to Slave 4 + * @see MPU6050_RA_I2C_SLV4_DO + */ +void MPU6050_setSlave4OutputByte(uint8_t data) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_DO, data); +} +/** Get the enabled value for the Slave 4. + * When set to 1, this bit enables Slave 4 for data transfer operations. When + * cleared to 0, this bit disables Slave 4 from data transfer operations. + * @return Current enabled value for Slave 4 + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +bool MPU6050_getSlave4Enabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set the enabled value for Slave 4. + * @param enabled New enabled value for Slave 4 + * @see getSlave4Enabled() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050_setSlave4Enabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_EN_BIT, enabled); +} +/** Get the enabled value for Slave 4 transaction interrupts. + * When set to 1, this bit enables the generation of an interrupt signal upon + * completion of a Slave 4 transaction. When cleared to 0, this bit disables the + * generation of an interrupt signal upon completion of a Slave 4 transaction. + * The interrupt status can be observed in Register 54. + * + * @return Current enabled value for Slave 4 transaction interrupts. + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +bool MPU6050_getSlave4InterruptEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_INT_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set the enabled value for Slave 4 transaction interrupts. + * @param enabled New enabled value for Slave 4 transaction interrupts. + * @see getSlave4InterruptEnabled() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050_setSlave4InterruptEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_INT_EN_BIT, enabled); +} +/** Get write mode for Slave 4. + * When set to 1, the transaction will read or write data only. When cleared to + * 0, the transaction will write a register address prior to reading or writing + * data. This should equal 0 when specifying the register address within the + * Slave device to/from which the ensuing data transaction will take place. + * + * @return Current write mode for Slave 4 (0 = register address + data, 1 = data only) + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +bool MPU6050_getSlave4WriteMode() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_REG_DIS_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set write mode for the Slave 4. + * @param mode New write mode for Slave 4 (0 = register address + data, 1 = data only) + * @see getSlave4WriteMode() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050_setSlave4WriteMode(bool mode) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_REG_DIS_BIT, mode); +} +/** Get Slave 4 master delay value. + * This configures the reduced access rate of I2C slaves relative to the Sample + * Rate. When a slave's access rate is decreased relative to the Sample Rate, + * the slave is accessed every: + * + * 1 / (1 + I2C_MST_DLY) samples + * + * This base Sample Rate in turn is determined by SMPLRT_DIV (register 25) and + * DLPF_CFG (register 26). Whether a slave's access rate is reduced relative to + * the Sample Rate is determined by I2C_MST_DELAY_CTRL (register 103). For + * further information regarding the Sample Rate, please refer to register 25. + * + * @return Current Slave 4 master delay value + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +uint8_t MPU6050_getSlave4MasterDelay() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_MST_DLY_BIT, MPU6050_I2C_SLV4_MST_DLY_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Slave 4 master delay value. + * @param delay New Slave 4 master delay value + * @see getSlave4MasterDelay() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050_setSlave4MasterDelay(uint8_t delay) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_MST_DLY_BIT, MPU6050_I2C_SLV4_MST_DLY_LENGTH, delay); +} +/** Get last available byte read from Slave 4. + * This register stores the data read from Slave 4. This field is populated + * after a read transaction. + * @return Last available byte read from to Slave 4 + * @see MPU6050_RA_I2C_SLV4_DI + */ +uint8_t MPU6050_getSlate4InputByte() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_DI, mpu6050.buffer); + return mpu6050.buffer[0]; +} + +// I2C_MST_STATUS register + +/** Get FSYNC interrupt status. + * This bit reflects the status of the FSYNC interrupt from an external device + * into the MPU-60X0. This is used as a way to pass an external interrupt + * through the MPU-60X0 to the host application processor. When set to 1, this + * bit will cause an interrupt if FSYNC_INT_EN is asserted in INT_PIN_CFG + * (Register 55). + * @return FSYNC interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_getPassthroughStatus() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_PASS_THROUGH_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Slave 4 transaction done status. + * Automatically sets to 1 when a Slave 4 transaction has completed. This + * triggers an interrupt if the I2C_MST_INT_EN bit in the INT_ENABLE register + * (Register 56) is asserted and if the SLV_4_DONE_INT bit is asserted in the + * I2C_SLV4_CTRL register (Register 52). + * @return Slave 4 transaction done status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_getSlave4IsDone() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV4_DONE_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get master arbitration lost status. + * This bit automatically sets to 1 when the I2C Master has lost arbitration of + * the auxiliary I2C bus (an error condition). This triggers an interrupt if the + * I2C_MST_INT_EN bit in the INT_ENABLE register (Register 56) is asserted. + * @return Master arbitration lost status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_getLostArbitration() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_LOST_ARB_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Slave 4 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 4. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 4 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_getSlave4Nack() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV4_NACK_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Slave 3 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 3. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 3 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_getSlave3Nack() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV3_NACK_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Slave 2 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 2. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 2 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_getSlave2Nack() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV2_NACK_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Slave 1 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 1. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 1 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_getSlave1Nack() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV1_NACK_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Slave 0 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 0. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 0 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_getSlave0Nack() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV0_NACK_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} + +// INT_PIN_CFG register + +/** Get interrupt logic level mode. + * Will be set 0 for active-high, 1 for active-low. + * @return Current interrupt mode (0=active-high, 1=active-low) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_LEVEL_BIT + */ +bool MPU6050_getInterruptMode() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_LEVEL_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set interrupt logic level mode. + * @param mode New interrupt mode (0=active-high, 1=active-low) + * @see getInterruptMode() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_LEVEL_BIT + */ +void MPU6050_setInterruptMode(bool mode) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_LEVEL_BIT, mode); +} +/** Get interrupt drive mode. + * Will be set 0 for push-pull, 1 for open-drain. + * @return Current interrupt drive mode (0=push-pull, 1=open-drain) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_OPEN_BIT + */ +bool MPU6050_getInterruptDrive() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_OPEN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set interrupt drive mode. + * @param drive New interrupt drive mode (0=push-pull, 1=open-drain) + * @see getInterruptDrive() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_OPEN_BIT + */ +void MPU6050_setInterruptDrive(bool drive) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_OPEN_BIT, drive); +} +/** Get interrupt latch mode. + * Will be set 0 for 50us-pulse, 1 for latch-until-int-cleared. + * @return Current latch mode (0=50us-pulse, 1=latch-until-int-cleared) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_LATCH_INT_EN_BIT + */ +bool MPU6050_getInterruptLatch() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_LATCH_INT_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set interrupt latch mode. + * @param latch New latch mode (0=50us-pulse, 1=latch-until-int-cleared) + * @see getInterruptLatch() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_LATCH_INT_EN_BIT + */ +void MPU6050_setInterruptLatch(bool latch) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_LATCH_INT_EN_BIT, latch); +} +/** Get interrupt latch clear mode. + * Will be set 0 for status-read-only, 1 for any-register-read. + * @return Current latch clear mode (0=status-read-only, 1=any-register-read) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_RD_CLEAR_BIT + */ +bool MPU6050_getInterruptLatchClear() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_RD_CLEAR_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set interrupt latch clear mode. + * @param clear New latch clear mode (0=status-read-only, 1=any-register-read) + * @see getInterruptLatchClear() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_RD_CLEAR_BIT + */ +void MPU6050_setInterruptLatchClear(bool clear) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_RD_CLEAR_BIT, clear); +} +/** Get FSYNC interrupt logic level mode. + * @return Current FSYNC interrupt mode (0=active-high, 1=active-low) + * @see getFSyncInterruptMode() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT + */ +bool MPU6050_getFSyncInterruptLevel() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set FSYNC interrupt logic level mode. + * @param mode New FSYNC interrupt mode (0=active-high, 1=active-low) + * @see getFSyncInterruptMode() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT + */ +void MPU6050_setFSyncInterruptLevel(bool level) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT, level); +} +/** Get FSYNC pin interrupt enabled setting. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled setting + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_EN_BIT + */ +bool MPU6050_getFSyncInterruptEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set FSYNC pin interrupt enabled setting. + * @param enabled New FSYNC pin interrupt enabled setting + * @see getFSyncInterruptEnabled() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_EN_BIT + */ +void MPU6050_setFSyncInterruptEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_EN_BIT, enabled); +} +/** Get I2C bypass enabled status. + * When this bit is equal to 1 and I2C_MST_EN (Register 106 bit[5]) is equal to + * 0, the host application processor will be able to directly access the + * auxiliary I2C bus of the MPU-60X0. When this bit is equal to 0, the host + * application processor will not be able to directly access the auxiliary I2C + * bus of the MPU-60X0 regardless of the state of I2C_MST_EN (Register 106 + * bit[5]). + * @return Current I2C bypass enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_I2C_BYPASS_EN_BIT + */ +bool MPU6050_getI2CBypassEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_I2C_BYPASS_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set I2C bypass enabled status. + * When this bit is equal to 1 and I2C_MST_EN (Register 106 bit[5]) is equal to + * 0, the host application processor will be able to directly access the + * auxiliary I2C bus of the MPU-60X0. When this bit is equal to 0, the host + * application processor will not be able to directly access the auxiliary I2C + * bus of the MPU-60X0 regardless of the state of I2C_MST_EN (Register 106 + * bit[5]). + * @param enabled New I2C bypass enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_I2C_BYPASS_EN_BIT + */ +void MPU6050_setI2CBypassEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_I2C_BYPASS_EN_BIT, enabled); +} +/** Get reference clock output enabled status. + * When this bit is equal to 1, a reference clock output is provided at the + * CLKOUT pin. When this bit is equal to 0, the clock output is disabled. For + * further information regarding CLKOUT, please refer to the MPU-60X0 Product + * Specification document. + * @return Current reference clock output enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_CLKOUT_EN_BIT + */ +bool MPU6050_getClockOutputEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_CLKOUT_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set reference clock output enabled status. + * When this bit is equal to 1, a reference clock output is provided at the + * CLKOUT pin. When this bit is equal to 0, the clock output is disabled. For + * further information regarding CLKOUT, please refer to the MPU-60X0 Product + * Specification document. + * @param enabled New reference clock output enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_CLKOUT_EN_BIT + */ +void MPU6050_setClockOutputEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_CLKOUT_EN_BIT, enabled); +} + +// INT_ENABLE register + +/** Get full interrupt enabled status. + * Full register byte for all interrupts, for quick reading. Each bit will be + * set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +uint8_t MPU6050_getIntEnabled() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set full interrupt enabled status. + * Full register byte for all interrupts, for quick reading. Each bit should be + * set 0 for disabled, 1 for enabled. + * @param enabled New interrupt enabled status + * @see getIntFreefallEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +void MPU6050_setIntEnabled(uint8_t enabled) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, enabled); +} +/** Get Free Fall interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +bool MPU6050_getIntFreefallEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FF_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Free Fall interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntFreefallEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +void MPU6050_setIntFreefallEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FF_BIT, enabled); +} +/** Get Motion Detection interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_MOT_BIT + **/ +bool MPU6050_getIntMotionEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_MOT_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Motion Detection interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntMotionEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_MOT_BIT + **/ +void MPU6050_setIntMotionEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_MOT_BIT, enabled); +} +/** Get Zero Motion Detection interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_ZMOT_BIT + **/ +bool MPU6050_getIntZeroMotionEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_ZMOT_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Zero Motion Detection interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntZeroMotionEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_ZMOT_BIT + **/ +void MPU6050_setIntZeroMotionEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_ZMOT_BIT, enabled); +} +/** Get FIFO Buffer Overflow interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT + **/ +bool MPU6050_getIntFIFOBufferOverflowEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set FIFO Buffer Overflow interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntFIFOBufferOverflowEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT + **/ +void MPU6050_setIntFIFOBufferOverflowEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, enabled); +} +/** Get I2C Master interrupt enabled status. + * This enables any of the I2C Master interrupt sources to generate an + * interrupt. Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT + **/ +bool MPU6050_getIntI2CMasterEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_I2C_MST_INT_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set I2C Master interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntI2CMasterEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT + **/ +void MPU6050_setIntI2CMasterEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_I2C_MST_INT_BIT, enabled); +} +/** Get Data Ready interrupt enabled setting. + * This event occurs each time a write operation to all of the sensor registers + * has been completed. Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_DATA_RDY_BIT + */ +bool MPU6050_getIntDataReadyEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DATA_RDY_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Data Ready interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntDataReadyEnabled() + * @see MPU6050_RA_INT_CFG + * @see MPU6050_INTERRUPT_DATA_RDY_BIT + */ +void MPU6050_setIntDataReadyEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DATA_RDY_BIT, enabled); +} + +// INT_STATUS register + +/** Get full set of interrupt status bits. + * These bits clear to 0 after the register has been read. Very useful + * for getting multiple INT statuses, since each single bit read clears + * all of them because it has to read the whole byte. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + */ +uint8_t MPU6050_getIntStatus() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_INT_STATUS, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Free Fall interrupt status. + * This bit automatically sets to 1 when a Free Fall interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_FF_BIT + */ +bool MPU6050_getIntFreefallStatus() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_FF_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Motion Detection interrupt status. + * This bit automatically sets to 1 when a Motion Detection interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_MOT_BIT + */ +bool MPU6050_getIntMotionStatus() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_MOT_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Zero Motion Detection interrupt status. + * This bit automatically sets to 1 when a Zero Motion Detection interrupt has + * been generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_ZMOT_BIT + */ +bool MPU6050_getIntZeroMotionStatus() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_ZMOT_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get FIFO Buffer Overflow interrupt status. + * This bit automatically sets to 1 when a Free Fall interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT + */ +bool MPU6050_getIntFIFOBufferOverflowStatus() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get I2C Master interrupt status. + * This bit automatically sets to 1 when an I2C Master interrupt has been + * generated. For a list of I2C Master interrupts, please refer to Register 54. + * The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT + */ +bool MPU6050_getIntI2CMasterStatus() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_I2C_MST_INT_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Data Ready interrupt status. + * This bit automatically sets to 1 when a Data Ready interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_DATA_RDY_BIT + */ +bool MPU6050_getIntDataReadyStatus() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_DATA_RDY_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} + +// ACCEL_*OUT_* registers + +/** Get raw 9-axis motion sensor readings (accel/gyro/compass). + * FUNCTION NOT FULLY IMPLEMENTED YET. + * @param ax 16-bit signed integer container for accelerometer X-axis value + * @param ay 16-bit signed integer container for accelerometer Y-axis value + * @param az 16-bit signed integer container for accelerometer Z-axis value + * @param gx 16-bit signed integer container for gyroscope X-axis value + * @param gy 16-bit signed integer container for gyroscope Y-axis value + * @param gz 16-bit signed integer container for gyroscope Z-axis value + * @param mx 16-bit signed integer container for magnetometer X-axis value + * @param my 16-bit signed integer container for magnetometer Y-axis value + * @param mz 16-bit signed integer container for magnetometer Z-axis value + * @see getMotion6() + * @see getAcceleration() + * @see getRotation() + * @see MPU6050_RA_ACCEL_XOUT_H + */ +void MPU6050_getMotion9(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz, int16_t* mx, int16_t* my, int16_t* mz) { + MPU6050_getMotion6(ax, ay, az, gx, gy, gz); + // TODO: magnetometer integration +} +/** Get raw 6-axis motion sensor readings (accel/gyro). + * Retrieves all currently available motion sensor values. + * @param ax 16-bit signed integer container for accelerometer X-axis value + * @param ay 16-bit signed integer container for accelerometer Y-axis value + * @param az 16-bit signed integer container for accelerometer Z-axis value + * @param gx 16-bit signed integer container for gyroscope X-axis value + * @param gy 16-bit signed integer container for gyroscope Y-axis value + * @param gz 16-bit signed integer container for gyroscope Z-axis value + * @see getAcceleration() + * @see getRotation() + * @see MPU6050_RA_ACCEL_XOUT_H + */ +void MPU6050_getMotion6(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz) { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ACCEL_XOUT_H, 14, mpu6050.buffer); + *ax = (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; + *ay = (((int16_t)mpu6050.buffer[2]) << 8) | mpu6050.buffer[3]; + *az = (((int16_t)mpu6050.buffer[4]) << 8) | mpu6050.buffer[5]; + *gx = (((int16_t)mpu6050.buffer[8]) << 8) | mpu6050.buffer[9]; + *gy = (((int16_t)mpu6050.buffer[10]) << 8) | mpu6050.buffer[11]; + *gz = (((int16_t)mpu6050.buffer[12]) << 8) | mpu6050.buffer[13]; +} +/** Get 3-axis accelerometer readings. + * These registers store the most recent accelerometer measurements. + * Accelerometer measurements are written to these registers at the Sample Rate + * as defined in Register 25. + * + * The accelerometer measurement registers, along with the temperature + * measurement registers, gyroscope measurement registers, and external sensor + * data registers, are composed of two sets of registers: an internal register + * set and a user-facing read register set. + * + * The data within the accelerometer sensors' internal register set is always + * updated at the Sample Rate. Meanwhile, the user-facing read register set + * duplicates the internal register set's data values whenever the serial + * interface is idle. This guarantees that a burst read of sensor registers will + * read measurements from the same sampling instant. Note that if burst reads + * are not used, the user is responsible for ensuring a set of single byte reads + * correspond to a single sampling instant by checking the Data Ready interrupt. + * + * Each 16-bit accelerometer measurement has a full scale defined in ACCEL_FS + * (Register 28). For each full scale setting, the accelerometers' sensitivity + * per LSB in ACCEL_xOUT is shown in the table below: + * + *
+ * AFS_SEL | Full Scale Range | LSB Sensitivity
+ * --------+------------------+----------------
+ * 0       | +/- 2g           | 8192 LSB/mg
+ * 1       | +/- 4g           | 4096 LSB/mg
+ * 2       | +/- 8g           | 2048 LSB/mg
+ * 3       | +/- 16g          | 1024 LSB/mg
+ * 
+ * + * @param x 16-bit signed integer container for X-axis acceleration + * @param y 16-bit signed integer container for Y-axis acceleration + * @param z 16-bit signed integer container for Z-axis acceleration + * @see MPU6050_RA_GYRO_XOUT_H + */ +void MPU6050_getAcceleration(int16_t* x, int16_t* y, int16_t* z) { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ACCEL_XOUT_H, 6, mpu6050.buffer); + *x = (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; + *y = (((int16_t)mpu6050.buffer[2]) << 8) | mpu6050.buffer[3]; + *z = (((int16_t)mpu6050.buffer[4]) << 8) | mpu6050.buffer[5]; +} +/** Get X-axis accelerometer reading. + * @return X-axis acceleration measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_ACCEL_XOUT_H + */ +int16_t MPU6050_getAccelerationX() { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ACCEL_XOUT_H, 2, mpu6050.buffer); + return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; +} +/** Get Y-axis accelerometer reading. + * @return Y-axis acceleration measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_ACCEL_YOUT_H + */ +int16_t MPU6050_getAccelerationY() { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ACCEL_YOUT_H, 2, mpu6050.buffer); + return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; +} +/** Get Z-axis accelerometer reading. + * @return Z-axis acceleration measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_ACCEL_ZOUT_H + */ +int16_t MPU6050_getAccelerationZ() { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ACCEL_ZOUT_H, 2, mpu6050.buffer); + return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; +} + +// TEMP_OUT_* registers + +/** Get current internal temperature. + * @return Temperature reading in 16-bit 2's complement format + * @see MPU6050_RA_TEMP_OUT_H + */ +int16_t MPU6050_getTemperature() { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_TEMP_OUT_H, 2, mpu6050.buffer); + return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; +} + +// GYRO_*OUT_* registers + +/** Get 3-axis gyroscope readings. + * These gyroscope measurement registers, along with the accelerometer + * measurement registers, temperature measurement registers, and external sensor + * data registers, are composed of two sets of registers: an internal register + * set and a user-facing read register set. + * The data within the gyroscope sensors' internal register set is always + * updated at the Sample Rate. Meanwhile, the user-facing read register set + * duplicates the internal register set's data values whenever the serial + * interface is idle. This guarantees that a burst read of sensor registers will + * read measurements from the same sampling instant. Note that if burst reads + * are not used, the user is responsible for ensuring a set of single byte reads + * correspond to a single sampling instant by checking the Data Ready interrupt. + * + * Each 16-bit gyroscope measurement has a full scale defined in FS_SEL + * (Register 27). For each full scale setting, the gyroscopes' sensitivity per + * LSB in GYRO_xOUT is shown in the table below: + * + *
+ * FS_SEL | Full Scale Range   | LSB Sensitivity
+ * -------+--------------------+----------------
+ * 0      | +/- 250 degrees/s  | 131 LSB/deg/s
+ * 1      | +/- 500 degrees/s  | 65.5 LSB/deg/s
+ * 2      | +/- 1000 degrees/s | 32.8 LSB/deg/s
+ * 3      | +/- 2000 degrees/s | 16.4 LSB/deg/s
+ * 
+ * + * @param x 16-bit signed integer container for X-axis rotation + * @param y 16-bit signed integer container for Y-axis rotation + * @param z 16-bit signed integer container for Z-axis rotation + * @see getMotion6() + * @see MPU6050_RA_GYRO_XOUT_H + */ +void MPU6050_getRotation(int16_t* x, int16_t* y, int16_t* z) { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_GYRO_XOUT_H, 6, mpu6050.buffer); + *x = (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; + *y = (((int16_t)mpu6050.buffer[2]) << 8) | mpu6050.buffer[3]; + *z = (((int16_t)mpu6050.buffer[4]) << 8) | mpu6050.buffer[5]; +} +/** Get X-axis gyroscope reading. + * @return X-axis rotation measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_GYRO_XOUT_H + */ +int16_t MPU6050_getRotationX() { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_GYRO_XOUT_H, 2, mpu6050.buffer); + return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; +} +/** Get Y-axis gyroscope reading. + * @return Y-axis rotation measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_GYRO_YOUT_H + */ +int16_t MPU6050_getRotationY() { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_GYRO_YOUT_H, 2, mpu6050.buffer); + return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; +} +/** Get Z-axis gyroscope reading. + * @return Z-axis rotation measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_GYRO_ZOUT_H + */ +int16_t MPU6050_getRotationZ() { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_GYRO_ZOUT_H, 2, mpu6050.buffer); + return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; +} + +// EXT_SENS_DATA_* registers + +/** Read single byte from external sensor data register. + * These registers store data read from external sensors by the Slave 0, 1, 2, + * and 3 on the auxiliary I2C interface. Data read by Slave 4 is stored in + * I2C_SLV4_DI (Register 53). + * + * External sensor data is written to these registers at the Sample Rate as + * defined in Register 25. This access rate can be reduced by using the Slave + * Delay Enable registers (Register 103). + * + * External sensor data registers, along with the gyroscope measurement + * registers, accelerometer measurement registers, and temperature measurement + * registers, are composed of two sets of registers: an internal register set + * and a user-facing read register set. + * + * The data within the external sensors' internal register set is always updated + * at the Sample Rate (or the reduced access rate) whenever the serial interface + * is idle. This guarantees that a burst read of sensor registers will read + * measurements from the same sampling instant. Note that if burst reads are not + * used, the user is responsible for ensuring a set of single byte reads + * correspond to a single sampling instant by checking the Data Ready interrupt. + * + * Data is placed in these external sensor data registers according to + * I2C_SLV0_CTRL, I2C_SLV1_CTRL, I2C_SLV2_CTRL, and I2C_SLV3_CTRL (Registers 39, + * 42, 45, and 48). When more than zero bytes are read (I2C_SLVx_LEN > 0) from + * an enabled slave (I2C_SLVx_EN = 1), the slave is read at the Sample Rate (as + * defined in Register 25) or delayed rate (if specified in Register 52 and + * 103). During each Sample cycle, slave reads are performed in order of Slave + * number. If all slaves are enabled with more than zero bytes to be read, the + * order will be Slave 0, followed by Slave 1, Slave 2, and Slave 3. + * + * Each enabled slave will have EXT_SENS_DATA registers associated with it by + * number of bytes read (I2C_SLVx_LEN) in order of slave number, starting from + * EXT_SENS_DATA_00. Note that this means enabling or disabling a slave may + * change the higher numbered slaves' associated registers. Furthermore, if + * fewer total bytes are being read from the external sensors as a result of + * such a change, then the data remaining in the registers which no longer have + * an associated slave device (i.e. high numbered registers) will remain in + * these previously allocated registers unless reset. + * + * If the sum of the read lengths of all SLVx transactions exceed the number of + * available EXT_SENS_DATA registers, the excess bytes will be dropped. There + * are 24 EXT_SENS_DATA registers and hence the total read lengths between all + * the slaves cannot be greater than 24 or some bytes will be lost. + * + * Note: Slave 4's behavior is distinct from that of Slaves 0-3. For further + * information regarding the characteristics of Slave 4, please refer to + * Registers 49 to 53. + * + * EXAMPLE: + * Suppose that Slave 0 is enabled with 4 bytes to be read (I2C_SLV0_EN = 1 and + * I2C_SLV0_LEN = 4) while Slave 1 is enabled with 2 bytes to be read so that + * I2C_SLV1_EN = 1 and I2C_SLV1_LEN = 2. In such a situation, EXT_SENS_DATA _00 + * through _03 will be associated with Slave 0, while EXT_SENS_DATA _04 and 05 + * will be associated with Slave 1. If Slave 2 is enabled as well, registers + * starting from EXT_SENS_DATA_06 will be allocated to Slave 2. + * + * If Slave 2 is disabled while Slave 3 is enabled in this same situation, then + * registers starting from EXT_SENS_DATA_06 will be allocated to Slave 3 + * instead. + * + * REGISTER ALLOCATION FOR DYNAMIC DISABLE VS. NORMAL DISABLE: + * If a slave is disabled at any time, the space initially allocated to the + * slave in the EXT_SENS_DATA register, will remain associated with that slave. + * This is to avoid dynamic adjustment of the register allocation. + * + * The allocation of the EXT_SENS_DATA registers is recomputed only when (1) all + * slaves are disabled, or (2) the I2C_MST_RST bit is set (Register 106). + * + * This above is also true if one of the slaves gets NACKed and stops + * functioning. + * + * @param position Starting position (0-23) + * @return Byte read from register + */ +uint8_t MPU6050_getExternalSensorByte(int position) { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Read word (2 bytes) from external sensor data registers. + * @param position Starting position (0-21) + * @return Word read from register + * @see getExternalSensorByte() + */ +uint16_t MPU6050_getExternalSensorWord(int position) { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, 2, mpu6050.buffer); + return (((uint16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; +} +/** Read double word (4 bytes) from external sensor data registers. + * @param position Starting position (0-20) + * @return Double word read from registers + * @see getExternalSensorByte() + */ +uint32_t MPU6050_getExternalSensorDWord(int position) { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, 4, mpu6050.buffer); + return (((uint32_t)mpu6050.buffer[0]) << 24) | (((uint32_t)mpu6050.buffer[1]) << 16) | (((uint16_t)mpu6050.buffer[2]) << 8) | mpu6050.buffer[3]; +} + +// MOT_DETECT_STATUS register + +/** Get X-axis negative motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_XNEG_BIT + */ +bool MPU6050_getXNegMotionDetected() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_XNEG_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get X-axis positive motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_XPOS_BIT + */ +bool MPU6050_getXPosMotionDetected() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_XPOS_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Y-axis negative motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_YNEG_BIT + */ +bool MPU6050_getYNegMotionDetected() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_YNEG_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Y-axis positive motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_YPOS_BIT + */ +bool MPU6050_getYPosMotionDetected() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_YPOS_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Z-axis negative motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_ZNEG_BIT + */ +bool MPU6050_getZNegMotionDetected() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZNEG_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Z-axis positive motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_ZPOS_BIT + */ +bool MPU6050_getZPosMotionDetected() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZPOS_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get zero motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_ZRMOT_BIT + */ +bool MPU6050_getZeroMotionDetected() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZRMOT_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} + +// I2C_SLV*_DO register + +/** Write byte to Data Output container for specified slave. + * This register holds the output data written into Slave when Slave is set to + * write mode. For further information regarding Slave control, please + * refer to Registers 37 to 39 and immediately following. + * @param num Slave number (0-3) + * @param data Byte to write + * @see MPU6050_RA_I2C_SLV0_DO + */ +void MPU6050_setSlaveOutputByte(uint8_t num, uint8_t data) { + if (num > 3) return; + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_DO + num, data); +} + +// I2C_MST_DELAY_CTRL register + +/** Get external data shadow delay enabled status. + * This register is used to specify the timing of external sensor data + * shadowing. When DELAY_ES_SHADOW is set to 1, shadowing of external + * sensor data is delayed until all data has been received. + * @return Current external data shadow delay enabled status. + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT + */ +bool MPU6050_getExternalShadowDelayEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set external data shadow delay enabled status. + * @param enabled New external data shadow delay enabled status. + * @see getExternalShadowDelayEnabled() + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT + */ +void MPU6050_setExternalShadowDelayEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT, enabled); +} +/** Get slave delay enabled status. + * When a particular slave delay is enabled, the rate of access for the that + * slave device is reduced. When a slave's access rate is decreased relative to + * the Sample Rate, the slave is accessed every: + * + * 1 / (1 + I2C_MST_DLY) Samples + * + * This base Sample Rate in turn is determined by SMPLRT_DIV (register * 25) + * and DLPF_CFG (register 26). + * + * For further information regarding I2C_MST_DLY, please refer to register 52. + * For further information regarding the Sample Rate, please refer to register 25. + * + * @param num Slave number (0-4) + * @return Current slave delay enabled status. + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT + */ +bool MPU6050_getSlaveDelayEnabled(uint8_t num) { + // MPU6050_DELAYCTRL_I2C_SLV4_DLY_EN_BIT is 4, SLV3 is 3, etc. + if (num > 4) return 0; + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, num, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set slave delay enabled status. + * @param num Slave number (0-4) + * @param enabled New slave delay enabled status. + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT + */ +void MPU6050_setSlaveDelayEnabled(uint8_t num, bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, num, enabled); +} + +// SIGNAL_PATH_RESET register + +/** Reset gyroscope signal path. + * The reset will revert the signal path analog to digital converters and + * filters to their power up configurations. + * @see MPU6050_RA_SIGNAL_PATH_RESET + * @see MPU6050_PATHRESET_GYRO_RESET_BIT + */ +void MPU6050_resetGyroscopePath() { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_GYRO_RESET_BIT, true); +} +/** Reset accelerometer signal path. + * The reset will revert the signal path analog to digital converters and + * filters to their power up configurations. + * @see MPU6050_RA_SIGNAL_PATH_RESET + * @see MPU6050_PATHRESET_ACCEL_RESET_BIT + */ +void MPU6050_resetAccelerometerPath() { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_ACCEL_RESET_BIT, true); +} +/** Reset temperature sensor signal path. + * The reset will revert the signal path analog to digital converters and + * filters to their power up configurations. + * @see MPU6050_RA_SIGNAL_PATH_RESET + * @see MPU6050_PATHRESET_TEMP_RESET_BIT + */ +void MPU6050_resetTemperaturePath() { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_TEMP_RESET_BIT, true); +} + +// MOT_DETECT_CTRL register + +/** Get accelerometer power-on delay. + * The accelerometer data path provides samples to the sensor registers, Motion + * detection, Zero Motion detection, and Free Fall detection modules. The + * signal path contains filters which must be flushed on wake-up with new + * samples before the detection modules begin operations. The default wake-up + * delay, of 4ms can be lengthened by up to 3ms. This additional delay is + * specified in ACCEL_ON_DELAY in units of 1 LSB = 1 ms. The user may select + * any value above zero unless instructed otherwise by InvenSense. Please refer + * to Section 8 of the MPU-6000/MPU-6050 Product Specification document for + * further information regarding the detection modules. + * @return Current accelerometer power-on delay + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_ACCEL_ON_DELAY_BIT + */ +uint8_t MPU6050_getAccelerometerPowerOnDelay() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_ACCEL_ON_DELAY_BIT, MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set accelerometer power-on delay. + * @param delay New accelerometer power-on delay (0-3) + * @see getAccelerometerPowerOnDelay() + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_ACCEL_ON_DELAY_BIT + */ +void MPU6050_setAccelerometerPowerOnDelay(uint8_t delay) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_ACCEL_ON_DELAY_BIT, MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH, delay); +} +/** Get Free Fall detection counter decrement configuration. + * Detection is registered by the Free Fall detection module after accelerometer + * measurements meet their respective threshold conditions over a specified + * number of samples. When the threshold conditions are met, the corresponding + * detection counter increments by 1. The user may control the rate at which the + * detection counter decrements when the threshold condition is not met by + * configuring FF_COUNT. The decrement rate can be set according to the + * following table: + * + *
+ * FF_COUNT | Counter Decrement
+ * ---------+------------------
+ * 0        | Reset
+ * 1        | 1
+ * 2        | 2
+ * 3        | 4
+ * 
+ * + * When FF_COUNT is configured to 0 (reset), any non-qualifying sample will + * reset the counter to 0. For further information on Free Fall detection, + * please refer to Registers 29 to 32. + * + * @return Current decrement configuration + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_FF_COUNT_BIT + */ +uint8_t MPU6050_getFreefallDetectionCounterDecrement() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_FF_COUNT_BIT, MPU6050_DETECT_FF_COUNT_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Free Fall detection counter decrement configuration. + * @param decrement New decrement configuration value + * @see getFreefallDetectionCounterDecrement() + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_FF_COUNT_BIT + */ +void MPU6050_setFreefallDetectionCounterDecrement(uint8_t decrement) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_FF_COUNT_BIT, MPU6050_DETECT_FF_COUNT_LENGTH, decrement); +} +/** Get Motion detection counter decrement configuration. + * Detection is registered by the Motion detection module after accelerometer + * measurements meet their respective threshold conditions over a specified + * number of samples. When the threshold conditions are met, the corresponding + * detection counter increments by 1. The user may control the rate at which the + * detection counter decrements when the threshold condition is not met by + * configuring MOT_COUNT. The decrement rate can be set according to the + * following table: + * + *
+ * MOT_COUNT | Counter Decrement
+ * ----------+------------------
+ * 0         | Reset
+ * 1         | 1
+ * 2         | 2
+ * 3         | 4
+ * 
+ * + * When MOT_COUNT is configured to 0 (reset), any non-qualifying sample will + * reset the counter to 0. For further information on Motion detection, + * please refer to Registers 29 to 32. + * + */ +uint8_t MPU6050_getMotionDetectionCounterDecrement() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_MOT_COUNT_BIT, MPU6050_DETECT_MOT_COUNT_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Motion detection counter decrement configuration. + * @param decrement New decrement configuration value + * @see getMotionDetectionCounterDecrement() + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_MOT_COUNT_BIT + */ +void MPU6050_setMotionDetectionCounterDecrement(uint8_t decrement) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_MOT_COUNT_BIT, MPU6050_DETECT_MOT_COUNT_LENGTH, decrement); +} + +// USER_CTRL register + +/** Get FIFO enabled status. + * When this bit is set to 0, the FIFO mpu6050.buffer is disabled. The FIFO mpu6050.buffer + * cannot be written to or read from while disabled. The FIFO mpu6050.buffer's state + * does not change unless the MPU-60X0 is power cycled. + * @return Current FIFO enabled status + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_FIFO_EN_BIT + */ +bool MPU6050_getFIFOEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set FIFO enabled status. + * @param enabled New FIFO enabled status + * @see getFIFOEnabled() + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_FIFO_EN_BIT + */ +void MPU6050_setFIFOEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_EN_BIT, enabled); +} +/** Get I2C Master Mode enabled status. + * When this mode is enabled, the MPU-60X0 acts as the I2C Master to the + * external sensor slave devices on the auxiliary I2C bus. When this bit is + * cleared to 0, the auxiliary I2C bus lines (AUX_DA and AUX_CL) are logically + * driven by the primary I2C bus (SDA and SCL). This is a precondition to + * enabling Bypass Mode. For further information regarding Bypass Mode, please + * refer to Register 55. + * @return Current I2C Master Mode enabled status + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_I2C_MST_EN_BIT + */ +bool MPU6050_getI2CMasterModeEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set I2C Master Mode enabled status. + * @param enabled New I2C Master Mode enabled status + * @see getI2CMasterModeEnabled() + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_I2C_MST_EN_BIT + */ +void MPU6050_setI2CMasterModeEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_EN_BIT, enabled); +} +/** Switch from I2C to SPI mode (MPU-6000 only) + * If this is set, the primary SPI interface will be enabled in place of the + * disabled primary I2C interface. + */ +void MPU6050_switchSPIEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_IF_DIS_BIT, enabled); +} +/** Reset the FIFO. + * This bit resets the FIFO mpu6050.buffer when set to 1 while FIFO_EN equals 0. This + * bit automatically clears to 0 after the reset has been triggered. + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_FIFO_RESET_BIT + */ +void MPU6050_resetFIFO() { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_RESET_BIT, true); +} +/** Reset the I2C Master. + * This bit resets the I2C Master when set to 1 while I2C_MST_EN equals 0. + * This bit automatically clears to 0 after the reset has been triggered. + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_I2C_MST_RESET_BIT + */ +void MPU6050_resetI2CMaster() { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_RESET_BIT, true); +} +/** Reset all sensor registers and signal paths. + * When set to 1, this bit resets the signal paths for all sensors (gyroscopes, + * accelerometers, and temperature sensor). This operation will also clear the + * sensor registers. This bit automatically clears to 0 after the reset has been + * triggered. + * + * When resetting only the signal path (and not the sensor registers), please + * use Register 104, SIGNAL_PATH_RESET. + * + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_SIG_COND_RESET_BIT + */ +void MPU6050_resetSensors() { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_SIG_COND_RESET_BIT, true); +} + +// PWR_MGMT_1 register + +/** Trigger a full device reset. + * A small delay of ~50ms may be desirable after triggering a reset. + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_DEVICE_RESET_BIT + */ +void MPU6050_reset() { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_DEVICE_RESET_BIT, true); +} +/** Get sleep mode status. + * Setting the SLEEP bit in the register puts the device into very low power + * sleep mode. In this mode, only the serial interface and internal registers + * remain active, allowing for a very low standby current. Clearing this bit + * puts the device back into normal mode. To save power, the individual standby + * selections for each of the gyros should be used if any gyro axis is not used + * by the application. + * @return Current sleep mode enabled status + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_SLEEP_BIT + */ +bool MPU6050_getSleepEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set sleep mode status. + * @param enabled New sleep mode enabled status + * @see getSleepEnabled() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_SLEEP_BIT + */ +void MPU6050_setSleepEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, enabled); +} +/** Get wake cycle enabled status. + * When this bit is set to 1 and SLEEP is disabled, the MPU-60X0 will cycle + * between sleep mode and waking up to take a single sample of data from active + * sensors at a rate determined by LP_WAKE_CTRL (register 108). + * @return Current sleep mode enabled status + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CYCLE_BIT + */ +bool MPU6050_getWakeCycleEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CYCLE_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set wake cycle enabled status. + * @param enabled New sleep mode enabled status + * @see getWakeCycleEnabled() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CYCLE_BIT + */ +void MPU6050_setWakeCycleEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CYCLE_BIT, enabled); +} +/** Get temperature sensor enabled status. + * Control the usage of the internal temperature sensor. + * + * Note: this register stores the *disabled* value, but for consistency with the + * rest of the code, the function is named and used with standard true/false + * values to indicate whether the sensor is enabled or disabled, respectively. + * + * @return Current temperature sensor enabled status + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_TEMP_DIS_BIT + */ +bool MPU6050_getTempSensorEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_TEMP_DIS_BIT, mpu6050.buffer); + return mpu6050.buffer[0] == 0; // 1 is actually disabled here +} +/** Set temperature sensor enabled status. + * Note: this register stores the *disabled* value, but for consistency with the + * rest of the code, the function is named and used with standard true/false + * values to indicate whether the sensor is enabled or disabled, respectively. + * + * @param enabled New temperature sensor enabled status + * @see getTempSensorEnabled() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_TEMP_DIS_BIT + */ +void MPU6050_setTempSensorEnabled(bool enabled) { + // 1 is actually disabled here + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_TEMP_DIS_BIT, !enabled); +} +/** Get clock source setting. + * @return Current clock source setting + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CLKSEL_BIT + * @see MPU6050_PWR1_CLKSEL_LENGTH + */ +uint8_t MPU6050_getClockSource() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set clock source setting. + * An internal 8MHz oscillator, gyroscope based clock, or external sources can + * be selected as the MPU-60X0 clock source. When the internal 8 MHz oscillator + * or an external source is chosen as the clock source, the MPU-60X0 can operate + * in low power modes with the gyroscopes disabled. + * + * Upon power up, the MPU-60X0 clock source defaults to the internal oscillator. + * However, it is highly recommended that the device be configured to use one of + * the gyroscopes (or an external clock source) as the clock reference for + * improved stability. The clock source can be selected according to the following table: + * + *
+ * CLK_SEL | Clock Source
+ * --------+--------------------------------------
+ * 0       | Internal oscillator
+ * 1       | PLL with X Gyro reference
+ * 2       | PLL with Y Gyro reference
+ * 3       | PLL with Z Gyro reference
+ * 4       | PLL with external 32.768kHz reference
+ * 5       | PLL with external 19.2MHz reference
+ * 6       | Reserved
+ * 7       | Stops the clock and keeps the timing generator in reset
+ * 
+ * + * @param source New clock source setting + * @see getClockSource() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CLKSEL_BIT + * @see MPU6050_PWR1_CLKSEL_LENGTH + */ +void MPU6050_setClockSource(uint8_t source) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, source); +} + +// PWR_MGMT_2 register + +/** Get wake frequency in Accel-Only Low Power Mode. + * The MPU-60X0 can be put into Accerlerometer Only Low Power Mode by setting + * PWRSEL to 1 in the Power Management 1 register (Register 107). In this mode, + * the device will power off all devices except for the primary I2C interface, + * waking only the accelerometer at fixed intervals to take a single + * measurement. The frequency of wake-ups can be configured with LP_WAKE_CTRL + * as shown below: + * + *
+ * LP_WAKE_CTRL | Wake-up Frequency
+ * -------------+------------------
+ * 0            | 1.25 Hz
+ * 1            | 2.5 Hz
+ * 2            | 5 Hz
+ * 3            | 10 Hz
+ * 
+ *
+ * For further information regarding the MPU-60X0's power modes, please refer to
+ * Register 107.
+ *
+ * @return Current wake frequency
+ * @see MPU6050_RA_PWR_MGMT_2
+ */
+uint8_t MPU6050_getWakeFrequency() {
+    I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_LP_WAKE_CTRL_BIT, MPU6050_PWR2_LP_WAKE_CTRL_LENGTH, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+/** Set wake frequency in Accel-Only Low Power Mode.
+ * @param frequency New wake frequency
+ * @see MPU6050_RA_PWR_MGMT_2
+ */
+void MPU6050_setWakeFrequency(uint8_t frequency) {
+    I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_LP_WAKE_CTRL_BIT, MPU6050_PWR2_LP_WAKE_CTRL_LENGTH, frequency);
+}
+
+/** Get X-axis accelerometer standby enabled status.
+ * If enabled, the X-axis will not gather or report data (or use power).
+ * @return Current X-axis standby enabled status
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_XA_BIT
+ */
+bool MPU6050_getStandbyXAccelEnabled() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XA_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+/** Set X-axis accelerometer standby enabled status.
+ * @param New X-axis standby enabled status
+ * @see getStandbyXAccelEnabled()
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_XA_BIT
+ */
+void MPU6050_setStandbyXAccelEnabled(bool enabled) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XA_BIT, enabled);
+}
+/** Get Y-axis accelerometer standby enabled status.
+ * If enabled, the Y-axis will not gather or report data (or use power).
+ * @return Current Y-axis standby enabled status
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_YA_BIT
+ */
+bool MPU6050_getStandbyYAccelEnabled() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YA_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+/** Set Y-axis accelerometer standby enabled status.
+ * @param New Y-axis standby enabled status
+ * @see getStandbyYAccelEnabled()
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_YA_BIT
+ */
+void MPU6050_setStandbyYAccelEnabled(bool enabled) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YA_BIT, enabled);
+}
+/** Get Z-axis accelerometer standby enabled status.
+ * If enabled, the Z-axis will not gather or report data (or use power).
+ * @return Current Z-axis standby enabled status
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_ZA_BIT
+ */
+bool MPU6050_getStandbyZAccelEnabled() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZA_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+/** Set Z-axis accelerometer standby enabled status.
+ * @param New Z-axis standby enabled status
+ * @see getStandbyZAccelEnabled()
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_ZA_BIT
+ */
+void MPU6050_setStandbyZAccelEnabled(bool enabled) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZA_BIT, enabled);
+}
+/** Get X-axis gyroscope standby enabled status.
+ * If enabled, the X-axis will not gather or report data (or use power).
+ * @return Current X-axis standby enabled status
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_XG_BIT
+ */
+bool MPU6050_getStandbyXGyroEnabled() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XG_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+/** Set X-axis gyroscope standby enabled status.
+ * @param New X-axis standby enabled status
+ * @see getStandbyXGyroEnabled()
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_XG_BIT
+ */
+void MPU6050_setStandbyXGyroEnabled(bool enabled) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XG_BIT, enabled);
+}
+/** Get Y-axis gyroscope standby enabled status.
+ * If enabled, the Y-axis will not gather or report data (or use power).
+ * @return Current Y-axis standby enabled status
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_YG_BIT
+ */
+bool MPU6050_getStandbyYGyroEnabled() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YG_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+/** Set Y-axis gyroscope standby enabled status.
+ * @param New Y-axis standby enabled status
+ * @see getStandbyYGyroEnabled()
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_YG_BIT
+ */
+void MPU6050_setStandbyYGyroEnabled(bool enabled) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YG_BIT, enabled);
+}
+/** Get Z-axis gyroscope standby enabled status.
+ * If enabled, the Z-axis will not gather or report data (or use power).
+ * @return Current Z-axis standby enabled status
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_ZG_BIT
+ */
+bool MPU6050_getStandbyZGyroEnabled() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZG_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+/** Set Z-axis gyroscope standby enabled status.
+ * @param New Z-axis standby enabled status
+ * @see getStandbyZGyroEnabled()
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_ZG_BIT
+ */
+void MPU6050_setStandbyZGyroEnabled(bool enabled) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZG_BIT, enabled);
+}
+
+// FIFO_COUNT* registers
+
+/** Get current FIFO mpu6050.buffer size.
+ * This value indicates the number of bytes stored in the FIFO mpu6050.buffer. This
+ * number is in turn the number of bytes that can be read from the FIFO mpu6050.buffer
+ * and it is directly proportional to the number of samples available given the
+ * set of sensor data bound to be stored in the FIFO (register 35 and 36).
+ * @return Current FIFO mpu6050.buffer size
+ */
+uint16_t MPU6050_getFIFOCount() {
+    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_FIFO_COUNTH, 2, mpu6050.buffer);
+    return (((uint16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+}
+
+// FIFO_R_W register
+
+/** Get byte from FIFO mpu6050.buffer.
+ * This register is used to read and write data from the FIFO mpu6050.buffer. Data is
+ * written to the FIFO in order of register number (from lowest to highest). If
+ * all the FIFO enable flags (see below) are enabled and all External Sensor
+ * Data registers (Registers 73 to 96) are associated with a Slave device, the
+ * contents of registers 59 through 96 will be written in order at the Sample
+ * Rate.
+ *
+ * The contents of the sensor data registers (Registers 59 to 96) are written
+ * into the FIFO mpu6050.buffer when their corresponding FIFO enable flags are set to 1
+ * in FIFO_EN (Register 35). An additional flag for the sensor data registers
+ * associated with I2C Slave 3 can be found in I2C_MST_CTRL (Register 36).
+ *
+ * If the FIFO mpu6050.buffer has overflowed, the status bit FIFO_OFLOW_INT is
+ * automatically set to 1. This bit is located in INT_STATUS (Register 58).
+ * When the FIFO mpu6050.buffer has overflowed, the oldest data will be lost and new
+ * data will be written to the FIFO.
+ *
+ * If the FIFO mpu6050.buffer is empty, reading this register will return the last byte
+ * that was previously read from the FIFO until new data is available. The user
+ * should check FIFO_COUNT to ensure that the FIFO mpu6050.buffer is not read when
+ * empty.
+ *
+ * @return Byte from FIFO mpu6050.buffer
+ */
+uint8_t MPU6050_getFIFOByte() {
+    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_FIFO_R_W, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_getFIFOBytes(uint8_t *data, uint8_t length) {
+    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_FIFO_R_W, length, data);
+}
+/** Write byte to FIFO mpu6050.buffer.
+ * @see getFIFOByte()
+ * @see MPU6050_RA_FIFO_R_W
+ */
+void MPU6050_setFIFOByte(uint8_t data) {
+    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_FIFO_R_W, data);
+}
+
+// WHO_AM_I register
+
+/** Get Device ID.
+ * This register is used to verify the identity of the device (0b110100, 0x34).
+ * @return Device ID (6 bits only! should be 0x34)
+ * @see MPU6050_RA_WHO_AM_I
+ * @see MPU6050_WHO_AM_I_BIT
+ * @see MPU6050_WHO_AM_I_LENGTH
+ */
+uint8_t MPU6050_getDeviceID() {
+    I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_WHO_AM_I, MPU6050_WHO_AM_I_BIT, MPU6050_WHO_AM_I_LENGTH, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+/** Set Device ID.
+ * Write a new ID into the WHO_AM_I register (no idea why this should ever be
+ * necessary though).
+ * @param id New device ID to set.
+ * @see getDeviceID()
+ * @see MPU6050_RA_WHO_AM_I
+ * @see MPU6050_WHO_AM_I_BIT
+ * @see MPU6050_WHO_AM_I_LENGTH
+ */
+void MPU6050_setDeviceID(uint8_t id) {
+    I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_WHO_AM_I, MPU6050_WHO_AM_I_BIT, MPU6050_WHO_AM_I_LENGTH, id);
+}
+
+// ======== UNDOCUMENTED/DMP REGISTERS/METHODS ========
+
+// XG_OFFS_TC register
+
+uint8_t MPU6050_getOTPBankValid() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OTP_BNK_VLD_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setOTPBankValid(bool enabled) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OTP_BNK_VLD_BIT, enabled);
+}
+int8_t MPU6050_getXGyroOffsetTC() {
+    I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setXGyroOffsetTC(int8_t offset) {
+    I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset);
+}
+
+// YG_OFFS_TC register
+
+int8_t MPU6050_getYGyroOffsetTC() {
+    I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setYGyroOffsetTC(int8_t offset) {
+    I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset);
+}
+
+// ZG_OFFS_TC register
+
+int8_t MPU6050_getZGyroOffsetTC() {
+    I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_ZG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setZGyroOffsetTC(int8_t offset) {
+    I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_ZG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset);
+}
+
+// X_FINE_GAIN register
+
+int8_t MPU6050_getXFineGain() {
+    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_X_FINE_GAIN, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setXFineGain(int8_t gain) {
+    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_X_FINE_GAIN, gain);
+}
+
+// Y_FINE_GAIN register
+
+int8_t MPU6050_getYFineGain() {
+    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_Y_FINE_GAIN, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setYFineGain(int8_t gain) {
+    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_Y_FINE_GAIN, gain);
+}
+
+// Z_FINE_GAIN register
+
+int8_t MPU6050_getZFineGain() {
+    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_Z_FINE_GAIN, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setZFineGain(int8_t gain) {
+    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_Z_FINE_GAIN, gain);
+}
+
+// XA_OFFS_* registers
+
+int16_t MPU6050_getXAccelOffset() {
+    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_XA_OFFS_H, 2, mpu6050.buffer);
+    return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+}
+void MPU6050_setXAccelOffset(int16_t offset) {
+    I2Cdev_writeWord(mpu6050.devAddr, MPU6050_RA_XA_OFFS_H, offset);
+}
+
+// YA_OFFS_* register
+
+int16_t MPU6050_getYAccelOffset() {
+    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_YA_OFFS_H, 2, mpu6050.buffer);
+    return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+}
+void MPU6050_setYAccelOffset(int16_t offset) {
+    I2Cdev_writeWord(mpu6050.devAddr, MPU6050_RA_YA_OFFS_H, offset);
+}
+
+// ZA_OFFS_* register
+
+int16_t MPU6050_getZAccelOffset() {
+    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ZA_OFFS_H, 2, mpu6050.buffer);
+    return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+}
+void MPU6050_setZAccelOffset(int16_t offset) {
+    I2Cdev_writeWord(mpu6050.devAddr, MPU6050_RA_ZA_OFFS_H, offset);
+}
+
+// XG_OFFS_USR* registers
+
+int16_t MPU6050_getXGyroOffset() {
+    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_XG_OFFS_USRH, 2, mpu6050.buffer);
+    return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+}
+void MPU6050_setXGyroOffset(int16_t offset) {
+    I2Cdev_writeWord(mpu6050.devAddr, MPU6050_RA_XG_OFFS_USRH, offset);
+}
+
+// YG_OFFS_USR* register
+
+int16_t MPU6050_getYGyroOffset() {
+    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_YG_OFFS_USRH, 2, mpu6050.buffer);
+    return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+}
+void MPU6050_setYGyroOffset(int16_t offset) {
+    I2Cdev_writeWord(mpu6050.devAddr, MPU6050_RA_YG_OFFS_USRH, offset);
+}
+
+// ZG_OFFS_USR* register
+
+int16_t MPU6050_getZGyroOffset() {
+    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ZG_OFFS_USRH, 2, mpu6050.buffer);
+    return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+}
+void MPU6050_setZGyroOffset(int16_t offset) {
+    I2Cdev_writeWord(mpu6050.devAddr, MPU6050_RA_ZG_OFFS_USRH, offset);
+}
+
+// INT_ENABLE register (DMP functions)
+
+bool MPU6050_getIntPLLReadyEnabled() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setIntPLLReadyEnabled(bool enabled) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, enabled);
+}
+bool MPU6050_getIntDMPEnabled() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DMP_INT_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setIntDMPEnabled(bool enabled) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DMP_INT_BIT, enabled);
+}
+
+// DMP_INT_STATUS
+
+bool MPU6050_getDMPInt5Status() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_5_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+bool MPU6050_getDMPInt4Status() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_4_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+bool MPU6050_getDMPInt3Status() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_3_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+bool MPU6050_getDMPInt2Status() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_2_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+bool MPU6050_getDMPInt1Status() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_1_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+bool MPU6050_getDMPInt0Status() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_0_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+
+// INT_STATUS register (DMP functions)
+
+bool MPU6050_getIntPLLReadyStatus() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+bool MPU6050_getIntDMPStatus() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_DMP_INT_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+
+// USER_CTRL register (DMP functions)
+
+bool MPU6050_getDMPEnabled() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_EN_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setDMPEnabled(bool enabled) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_EN_BIT, enabled);
+}
+void MPU6050_resetDMP() {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_RESET_BIT, true);
+}
+
+// BANK_SEL register
+
+void MPU6050_setMemoryBank(uint8_t bank, bool prefetchEnabled, bool userBank) {
+    bank &= 0x1F;
+    if (userBank) bank |= 0x20;
+    if (prefetchEnabled) bank |= 0x40;
+    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_BANK_SEL, bank);
+}
+
+// MEM_START_ADDR register
+
+void MPU6050_setMemoryStartAddress(uint8_t address) {
+    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_MEM_START_ADDR, address);
+}
+
+// MEM_R_W register
+
+uint8_t MPU6050_readMemoryByte() {
+    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_MEM_R_W, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_writeMemoryByte(uint8_t data) {
+    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_MEM_R_W, data);
+}
+void MPU6050_readMemoryBlock(uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address) {
+    MPU6050_setMemoryBank(bank, false, false);
+    MPU6050_setMemoryStartAddress(address);
+    uint8_t chunkSize;
+    for (uint16_t i = 0; i < dataSize;) {
+        // determine correct chunk size according to bank position and data size
+        chunkSize = MPU6050_DMP_MEMORY_CHUNK_SIZE;
+
+        // make sure we don't go past the data size
+        if (i + chunkSize > dataSize) chunkSize = dataSize - i;
+
+        // make sure this chunk doesn't go past the bank boundary (256 bytes)
+        if (chunkSize > 256 - address) chunkSize = 256 - address;
+
+        // read the chunk of data as specified
+        I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_MEM_R_W, chunkSize, data + i);
+        
+        // increase byte index by [chunkSize]
+        i += chunkSize;
+
+        // uint8_t automatically wraps to 0 at 256
+        address += chunkSize;
+
+        // if we aren't done, update bank (if necessary) and address
+        if (i < dataSize) {
+            if (address == 0) bank++;
+            MPU6050_setMemoryBank(bank, false, false);
+            MPU6050_setMemoryStartAddress(address);
+        }
+    }
+}
+/*bool MPU6050_writeMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address, bool verify, bool useProgMem) {
+    MPU6050_setMemoryBank(bank, false, false);
+    MPU6050_setMemoryStartAddress(address);
+    uint8_t chunkSize;
+    uint8_t *verifyBuffer;
+    uint8_t *progBuffer;
+    uint16_t i;
+    uint8_t j;
+    if (verify) verifyBuffer = (uint8_t *)malloc(MPU6050_DMP_MEMORY_CHUNK_SIZE);
+    if (useProgMem) progBuffer = (uint8_t *)malloc(MPU6050_DMP_MEMORY_CHUNK_SIZE);
+    for (i = 0; i < dataSize;) {
+        // determine correct chunk size according to bank position and data size
+        chunkSize = MPU6050_DMP_MEMORY_CHUNK_SIZE;
+
+        // make sure we don't go past the data size
+        if (i + chunkSize > dataSize) chunkSize = dataSize - i;
+
+        // make sure this chunk doesn't go past the bank boundary (256 bytes)
+        if (chunkSize > 256 - address) chunkSize = 256 - address;
+        
+        if (useProgMem) {
+            // write the chunk of data as specified
+            for (j = 0; j < chunkSize; j++) progBuffer[j] = pgm_read_byte(data + i + j);
+        } else {
+            // write the chunk of data as specified
+            progBuffer = (uint8_t *)data + i;
+        }
+
+        I2Cdev_writeBytes(mpu6050.devAddr, MPU6050_RA_MEM_R_W, chunkSize, progBuffer);
+
+        // verify data if needed
+        if (verify && verifyBuffer) {
+            MPU6050_setMemoryBank(bank, false, false);
+            MPU6050_setMemoryStartAddress(address);
+            I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_MEM_R_W, chunkSize, verifyBuffer);
+            if (memcmp(progBuffer, verifyBuffer, chunkSize) != 0) {
+                //Serial.print("Block write verification error, bank ");
+                //Serial.print(bank, DEC);
+                //Serial.print(", address ");
+                //Serial.print(address, DEC);
+                //Serial.print("!\nExpected:");
+                //for (j = 0; j < chunkSize; j++) {
+                //    Serial.print(" 0x");
+                //    if (progBuffer[j] < 16) Serial.print("0");
+                //    Serial.print(progBuffer[j], HEX);
+                //}
+                //Serial.print("\nReceived:");
+                //for (uint8_t j = 0; j < chunkSize; j++) {
+                //    Serial.print(" 0x");
+                //    if (verifyBuffer[i + j] < 16) Serial.print("0");
+                //    Serial.print(verifyBuffer[i + j], HEX);
+                //}
+                Serial.print("\n");
+                free(verifyBuffer);
+                if (useProgMem) free(progBuffer);
+                return false; // uh oh.
+            }
+        }
+
+        // increase byte index by [chunkSize]
+        i += chunkSize;
+
+        // uint8_t automatically wraps to 0 at 256
+        address += chunkSize;
+
+        // if we aren't done, update bank (if necessary) and address
+        if (i < dataSize) {
+            if (address == 0) bank++;
+            MPU6050_setMemoryBank(bank, false, false);
+            MPU6050_setMemoryStartAddress(address);
+        }
+    }
+    if (verify) free(verifyBuffer);
+    if (useProgMem) free(progBuffer);
+    return true;
+}
+bool MPU6050_writeProgMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address, bool verify) {
+    return MPU6050_writeMemoryBlock(data, dataSize, bank, address, verify, true);
+}
+bool MPU6050_writeDMPConfigurationSet(const uint8_t *data, uint16_t dataSize, bool useProgMem) {
+    uint8_t *progBuffer, success, special;
+    uint16_t i, j;
+    if (useProgMem) {
+        progBuffer = (uint8_t *)malloc(8); // assume 8-byte blocks, realloc later if necessary
+    }
+
+    // config set data is a long string of blocks with the following structure:
+    // [bank] [offset] [length] [byte[0], byte[1], ..., byte[length]]
+    uint8_t bank, offset, length;
+    for (i = 0; i < dataSize;) {
+        if (useProgMem) {
+            bank = pgm_read_byte(data + i++);
+            offset = pgm_read_byte(data + i++);
+            length = pgm_read_byte(data + i++);
+        } else {
+            bank = data[i++];
+            offset = data[i++];
+            length = data[i++];
+        }
+
+        // write data or perform special action
+        if (length > 0) {
+            // regular block of data to write
+            //Serial.print("Writing config block to bank ");
+            //Serial.print(bank);
+            //Serial.print(", offset ");
+            //Serial.print(offset);
+            //Serial.print(", length=");
+            //Serial.println(length);
+            if (useProgMem) {
+                if (sizeof(progBuffer) < length) progBuffer = (uint8_t *)realloc(progBuffer, length);
+                for (j = 0; j < length; j++) progBuffer[j] = pgm_read_byte(data + i + j);
+            } else {
+                progBuffer = (uint8_t *)data + i;
+            }
+            success = MPU6050_writeMemoryBlock(progBuffer, length, bank, offset, true);
+            i += length;
+        } else {
+            // special instruction
+            // NOTE: this kind of behavior (what and when to do certain things)
+            // is totally undocumented. This code is in here based on observed
+            // behavior only, and exactly why (or even whether) it has to be here
+            // is anybody's guess for now.
+            if (useProgMem) {
+                special = pgm_read_byte(data + i++);
+            } else {
+                special = data[i++];
+            }
+            //Serial.print("Special command code ");
+            //Serial.print(special, HEX);
+            //Serial.println(" found...");
+            if (special == 0x01) {
+                // enable DMP-related interrupts
+                
+                //setIntZeroMotionEnabled(true);
+                //setIntFIFOBufferOverflowEnabled(true);
+                //setIntDMPEnabled(true);
+                I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, 0x32);  // single operation
+
+                success = true;
+            } else {
+                // unknown special command
+                success = false;
+            }
+        }
+        
+        if (!success) {
+            if (useProgMem) free(progBuffer);
+            return false; // uh oh
+        }
+    }
+    if (useProgMem) free(progBuffer);
+    return true;
+}
+bool MPU6050_writeProgDMPConfigurationSet(const uint8_t *data, uint16_t dataSize) {
+    return MPU6050_writeDMPConfigurationSet(data, dataSize, true);
+}*/
+
+// DMP_CFG_1 register
+
+uint8_t MPU6050_getDMPConfig1() {
+    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_DMP_CFG_1, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setDMPConfig1(uint8_t config) {
+    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_DMP_CFG_1, config);
+}
+
+// DMP_CFG_2 register
+
+uint8_t MPU6050_getDMPConfig2() {
+    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_DMP_CFG_2, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setDMPConfig2(uint8_t config) {
+    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_DMP_CFG_2, config);
+}
\ No newline at end of file
diff --git a/PIC18/MPU6050/MPU6050.h b/PIC18/MPU6050/MPU6050.h
new file mode 100644
index 00000000..4f35e336
--- /dev/null
+++ b/PIC18/MPU6050/MPU6050.h
@@ -0,0 +1,786 @@
+// I2Cdev library collection - MPU6050 I2C device class
+// Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00)
+// 10/3/2011 by Jeff Rowberg 
+// 11/28/2014 by Marton Sebok 
+//
+// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
+//
+// Changelog:
+//     ...        - ongoing debug release
+//     2014-11-28 - ported to PIC18 peripheral library from Arduino code
+
+// NOTE: THIS IS ONLY A PARIAL RELEASE. THIS DEVICE CLASS IS CURRENTLY UNDERGOING ACTIVE
+// DEVELOPMENT AND IS STILL MISSING SOME IMPORTANT FEATURES. PLEASE KEEP THIS IN MIND IF
+// YOU DECIDE TO USE THIS PARTICULAR CODE FOR ANYTHING.
+
+/* ============================================
+I2Cdev device library code is placed under the MIT license
+Copyright (c) 2012 Jeff Rowberg
+Copyright (c) 2014 Marton Sebok
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+===============================================
+*/
+
+#ifndef _MPU6050_H_
+#define _MPU6050_H_
+
+#include "../I2Cdev/I2Cdev.h"
+
+#if ((defined MPU6050_INCLUDE_DMP_MOTIONAPPS20) || (defined MPU6050_INCLUDE_DMP_MOTIONAPPS41))
+    #error DMP is not supported yet
+#endif
+
+#define MPU6050_ADDRESS_AD0_LOW     0x68 // address pin low (GND), default for InvenSense evaluation board
+#define MPU6050_ADDRESS_AD0_HIGH    0x69 // address pin high (VCC)
+#define MPU6050_DEFAULT_ADDRESS     MPU6050_ADDRESS_AD0_LOW
+
+#define MPU6050_RA_XG_OFFS_TC       0x00 //[7] PWR_MODE, [6:1] XG_OFFS_TC, [0] OTP_BNK_VLD
+#define MPU6050_RA_YG_OFFS_TC       0x01 //[7] PWR_MODE, [6:1] YG_OFFS_TC, [0] OTP_BNK_VLD
+#define MPU6050_RA_ZG_OFFS_TC       0x02 //[7] PWR_MODE, [6:1] ZG_OFFS_TC, [0] OTP_BNK_VLD
+#define MPU6050_RA_X_FINE_GAIN      0x03 //[7:0] X_FINE_GAIN
+#define MPU6050_RA_Y_FINE_GAIN      0x04 //[7:0] Y_FINE_GAIN
+#define MPU6050_RA_Z_FINE_GAIN      0x05 //[7:0] Z_FINE_GAIN
+#define MPU6050_RA_XA_OFFS_H        0x06 //[15:0] XA_OFFS
+#define MPU6050_RA_XA_OFFS_L_TC     0x07
+#define MPU6050_RA_YA_OFFS_H        0x08 //[15:0] YA_OFFS
+#define MPU6050_RA_YA_OFFS_L_TC     0x09
+#define MPU6050_RA_ZA_OFFS_H        0x0A //[15:0] ZA_OFFS
+#define MPU6050_RA_ZA_OFFS_L_TC     0x0B
+#define MPU6050_RA_XG_OFFS_USRH     0x13 //[15:0] XG_OFFS_USR
+#define MPU6050_RA_XG_OFFS_USRL     0x14
+#define MPU6050_RA_YG_OFFS_USRH     0x15 //[15:0] YG_OFFS_USR
+#define MPU6050_RA_YG_OFFS_USRL     0x16
+#define MPU6050_RA_ZG_OFFS_USRH     0x17 //[15:0] ZG_OFFS_USR
+#define MPU6050_RA_ZG_OFFS_USRL     0x18
+#define MPU6050_RA_SMPLRT_DIV       0x19
+#define MPU6050_RA_CONFIG           0x1A
+#define MPU6050_RA_GYRO_CONFIG      0x1B
+#define MPU6050_RA_ACCEL_CONFIG     0x1C
+#define MPU6050_RA_FF_THR           0x1D
+#define MPU6050_RA_FF_DUR           0x1E
+#define MPU6050_RA_MOT_THR          0x1F
+#define MPU6050_RA_MOT_DUR          0x20
+#define MPU6050_RA_ZRMOT_THR        0x21
+#define MPU6050_RA_ZRMOT_DUR        0x22
+#define MPU6050_RA_FIFO_EN          0x23
+#define MPU6050_RA_I2C_MST_CTRL     0x24
+#define MPU6050_RA_I2C_SLV0_ADDR    0x25
+#define MPU6050_RA_I2C_SLV0_REG     0x26
+#define MPU6050_RA_I2C_SLV0_CTRL    0x27
+#define MPU6050_RA_I2C_SLV1_ADDR    0x28
+#define MPU6050_RA_I2C_SLV1_REG     0x29
+#define MPU6050_RA_I2C_SLV1_CTRL    0x2A
+#define MPU6050_RA_I2C_SLV2_ADDR    0x2B
+#define MPU6050_RA_I2C_SLV2_REG     0x2C
+#define MPU6050_RA_I2C_SLV2_CTRL    0x2D
+#define MPU6050_RA_I2C_SLV3_ADDR    0x2E
+#define MPU6050_RA_I2C_SLV3_REG     0x2F
+#define MPU6050_RA_I2C_SLV3_CTRL    0x30
+#define MPU6050_RA_I2C_SLV4_ADDR    0x31
+#define MPU6050_RA_I2C_SLV4_REG     0x32
+#define MPU6050_RA_I2C_SLV4_DO      0x33
+#define MPU6050_RA_I2C_SLV4_CTRL    0x34
+#define MPU6050_RA_I2C_SLV4_DI      0x35
+#define MPU6050_RA_I2C_MST_STATUS   0x36
+#define MPU6050_RA_INT_PIN_CFG      0x37
+#define MPU6050_RA_INT_ENABLE       0x38
+#define MPU6050_RA_DMP_INT_STATUS   0x39
+#define MPU6050_RA_INT_STATUS       0x3A
+#define MPU6050_RA_ACCEL_XOUT_H     0x3B
+#define MPU6050_RA_ACCEL_XOUT_L     0x3C
+#define MPU6050_RA_ACCEL_YOUT_H     0x3D
+#define MPU6050_RA_ACCEL_YOUT_L     0x3E
+#define MPU6050_RA_ACCEL_ZOUT_H     0x3F
+#define MPU6050_RA_ACCEL_ZOUT_L     0x40
+#define MPU6050_RA_TEMP_OUT_H       0x41
+#define MPU6050_RA_TEMP_OUT_L       0x42
+#define MPU6050_RA_GYRO_XOUT_H      0x43
+#define MPU6050_RA_GYRO_XOUT_L      0x44
+#define MPU6050_RA_GYRO_YOUT_H      0x45
+#define MPU6050_RA_GYRO_YOUT_L      0x46
+#define MPU6050_RA_GYRO_ZOUT_H      0x47
+#define MPU6050_RA_GYRO_ZOUT_L      0x48
+#define MPU6050_RA_EXT_SENS_DATA_00 0x49
+#define MPU6050_RA_EXT_SENS_DATA_01 0x4A
+#define MPU6050_RA_EXT_SENS_DATA_02 0x4B
+#define MPU6050_RA_EXT_SENS_DATA_03 0x4C
+#define MPU6050_RA_EXT_SENS_DATA_04 0x4D
+#define MPU6050_RA_EXT_SENS_DATA_05 0x4E
+#define MPU6050_RA_EXT_SENS_DATA_06 0x4F
+#define MPU6050_RA_EXT_SENS_DATA_07 0x50
+#define MPU6050_RA_EXT_SENS_DATA_08 0x51
+#define MPU6050_RA_EXT_SENS_DATA_09 0x52
+#define MPU6050_RA_EXT_SENS_DATA_10 0x53
+#define MPU6050_RA_EXT_SENS_DATA_11 0x54
+#define MPU6050_RA_EXT_SENS_DATA_12 0x55
+#define MPU6050_RA_EXT_SENS_DATA_13 0x56
+#define MPU6050_RA_EXT_SENS_DATA_14 0x57
+#define MPU6050_RA_EXT_SENS_DATA_15 0x58
+#define MPU6050_RA_EXT_SENS_DATA_16 0x59
+#define MPU6050_RA_EXT_SENS_DATA_17 0x5A
+#define MPU6050_RA_EXT_SENS_DATA_18 0x5B
+#define MPU6050_RA_EXT_SENS_DATA_19 0x5C
+#define MPU6050_RA_EXT_SENS_DATA_20 0x5D
+#define MPU6050_RA_EXT_SENS_DATA_21 0x5E
+#define MPU6050_RA_EXT_SENS_DATA_22 0x5F
+#define MPU6050_RA_EXT_SENS_DATA_23 0x60
+#define MPU6050_RA_MOT_DETECT_STATUS    0x61
+#define MPU6050_RA_I2C_SLV0_DO      0x63
+#define MPU6050_RA_I2C_SLV1_DO      0x64
+#define MPU6050_RA_I2C_SLV2_DO      0x65
+#define MPU6050_RA_I2C_SLV3_DO      0x66
+#define MPU6050_RA_I2C_MST_DELAY_CTRL   0x67
+#define MPU6050_RA_SIGNAL_PATH_RESET    0x68
+#define MPU6050_RA_MOT_DETECT_CTRL      0x69
+#define MPU6050_RA_USER_CTRL        0x6A
+#define MPU6050_RA_PWR_MGMT_1       0x6B
+#define MPU6050_RA_PWR_MGMT_2       0x6C
+#define MPU6050_RA_BANK_SEL         0x6D
+#define MPU6050_RA_MEM_START_ADDR   0x6E
+#define MPU6050_RA_MEM_R_W          0x6F
+#define MPU6050_RA_DMP_CFG_1        0x70
+#define MPU6050_RA_DMP_CFG_2        0x71
+#define MPU6050_RA_FIFO_COUNTH      0x72
+#define MPU6050_RA_FIFO_COUNTL      0x73
+#define MPU6050_RA_FIFO_R_W         0x74
+#define MPU6050_RA_WHO_AM_I         0x75
+
+#define MPU6050_TC_PWR_MODE_BIT     7
+#define MPU6050_TC_OFFSET_BIT       6
+#define MPU6050_TC_OFFSET_LENGTH    6
+#define MPU6050_TC_OTP_BNK_VLD_BIT  0
+
+#define MPU6050_VDDIO_LEVEL_VLOGIC  0
+#define MPU6050_VDDIO_LEVEL_VDD     1
+
+#define MPU6050_CFG_EXT_SYNC_SET_BIT    5
+#define MPU6050_CFG_EXT_SYNC_SET_LENGTH 3
+#define MPU6050_CFG_DLPF_CFG_BIT    2
+#define MPU6050_CFG_DLPF_CFG_LENGTH 3
+
+#define MPU6050_EXT_SYNC_DISABLED       0x0
+#define MPU6050_EXT_SYNC_TEMP_OUT_L     0x1
+#define MPU6050_EXT_SYNC_GYRO_XOUT_L    0x2
+#define MPU6050_EXT_SYNC_GYRO_YOUT_L    0x3
+#define MPU6050_EXT_SYNC_GYRO_ZOUT_L    0x4
+#define MPU6050_EXT_SYNC_ACCEL_XOUT_L   0x5
+#define MPU6050_EXT_SYNC_ACCEL_YOUT_L   0x6
+#define MPU6050_EXT_SYNC_ACCEL_ZOUT_L   0x7
+
+#define MPU6050_DLPF_BW_256         0x00
+#define MPU6050_DLPF_BW_188         0x01
+#define MPU6050_DLPF_BW_98          0x02
+#define MPU6050_DLPF_BW_42          0x03
+#define MPU6050_DLPF_BW_20          0x04
+#define MPU6050_DLPF_BW_10          0x05
+#define MPU6050_DLPF_BW_5           0x06
+
+#define MPU6050_GCONFIG_FS_SEL_BIT      4
+#define MPU6050_GCONFIG_FS_SEL_LENGTH   2
+
+#define MPU6050_GYRO_FS_250         0x00
+#define MPU6050_GYRO_FS_500         0x01
+#define MPU6050_GYRO_FS_1000        0x02
+#define MPU6050_GYRO_FS_2000        0x03
+
+#define MPU6050_ACONFIG_XA_ST_BIT           7
+#define MPU6050_ACONFIG_YA_ST_BIT           6
+#define MPU6050_ACONFIG_ZA_ST_BIT           5
+#define MPU6050_ACONFIG_AFS_SEL_BIT         4
+#define MPU6050_ACONFIG_AFS_SEL_LENGTH      2
+#define MPU6050_ACONFIG_ACCEL_HPF_BIT       2
+#define MPU6050_ACONFIG_ACCEL_HPF_LENGTH    3
+
+#define MPU6050_ACCEL_FS_2          0x00
+#define MPU6050_ACCEL_FS_4          0x01
+#define MPU6050_ACCEL_FS_8          0x02
+#define MPU6050_ACCEL_FS_16         0x03
+
+#define MPU6050_DHPF_RESET          0x00
+#define MPU6050_DHPF_5              0x01
+#define MPU6050_DHPF_2P5            0x02
+#define MPU6050_DHPF_1P25           0x03
+#define MPU6050_DHPF_0P63           0x04
+#define MPU6050_DHPF_HOLD           0x07
+
+#define MPU6050_TEMP_FIFO_EN_BIT    7
+#define MPU6050_XG_FIFO_EN_BIT      6
+#define MPU6050_YG_FIFO_EN_BIT      5
+#define MPU6050_ZG_FIFO_EN_BIT      4
+#define MPU6050_ACCEL_FIFO_EN_BIT   3
+#define MPU6050_SLV2_FIFO_EN_BIT    2
+#define MPU6050_SLV1_FIFO_EN_BIT    1
+#define MPU6050_SLV0_FIFO_EN_BIT    0
+
+#define MPU6050_MULT_MST_EN_BIT     7
+#define MPU6050_WAIT_FOR_ES_BIT     6
+#define MPU6050_SLV_3_FIFO_EN_BIT   5
+#define MPU6050_I2C_MST_P_NSR_BIT   4
+#define MPU6050_I2C_MST_CLK_BIT     3
+#define MPU6050_I2C_MST_CLK_LENGTH  4
+
+#define MPU6050_CLOCK_DIV_348       0x0
+#define MPU6050_CLOCK_DIV_333       0x1
+#define MPU6050_CLOCK_DIV_320       0x2
+#define MPU6050_CLOCK_DIV_308       0x3
+#define MPU6050_CLOCK_DIV_296       0x4
+#define MPU6050_CLOCK_DIV_286       0x5
+#define MPU6050_CLOCK_DIV_276       0x6
+#define MPU6050_CLOCK_DIV_267       0x7
+#define MPU6050_CLOCK_DIV_258       0x8
+#define MPU6050_CLOCK_DIV_500       0x9
+#define MPU6050_CLOCK_DIV_471       0xA
+#define MPU6050_CLOCK_DIV_444       0xB
+#define MPU6050_CLOCK_DIV_421       0xC
+#define MPU6050_CLOCK_DIV_400       0xD
+#define MPU6050_CLOCK_DIV_381       0xE
+#define MPU6050_CLOCK_DIV_364       0xF
+
+#define MPU6050_I2C_SLV_RW_BIT      7
+#define MPU6050_I2C_SLV_ADDR_BIT    6
+#define MPU6050_I2C_SLV_ADDR_LENGTH 7
+#define MPU6050_I2C_SLV_EN_BIT      7
+#define MPU6050_I2C_SLV_BYTE_SW_BIT 6
+#define MPU6050_I2C_SLV_REG_DIS_BIT 5
+#define MPU6050_I2C_SLV_GRP_BIT     4
+#define MPU6050_I2C_SLV_LEN_BIT     3
+#define MPU6050_I2C_SLV_LEN_LENGTH  4
+
+#define MPU6050_I2C_SLV4_RW_BIT         7
+#define MPU6050_I2C_SLV4_ADDR_BIT       6
+#define MPU6050_I2C_SLV4_ADDR_LENGTH    7
+#define MPU6050_I2C_SLV4_EN_BIT         7
+#define MPU6050_I2C_SLV4_INT_EN_BIT     6
+#define MPU6050_I2C_SLV4_REG_DIS_BIT    5
+#define MPU6050_I2C_SLV4_MST_DLY_BIT    4
+#define MPU6050_I2C_SLV4_MST_DLY_LENGTH 5
+
+#define MPU6050_MST_PASS_THROUGH_BIT    7
+#define MPU6050_MST_I2C_SLV4_DONE_BIT   6
+#define MPU6050_MST_I2C_LOST_ARB_BIT    5
+#define MPU6050_MST_I2C_SLV4_NACK_BIT   4
+#define MPU6050_MST_I2C_SLV3_NACK_BIT   3
+#define MPU6050_MST_I2C_SLV2_NACK_BIT   2
+#define MPU6050_MST_I2C_SLV1_NACK_BIT   1
+#define MPU6050_MST_I2C_SLV0_NACK_BIT   0
+
+#define MPU6050_INTCFG_INT_LEVEL_BIT        7
+#define MPU6050_INTCFG_INT_OPEN_BIT         6
+#define MPU6050_INTCFG_LATCH_INT_EN_BIT     5
+#define MPU6050_INTCFG_INT_RD_CLEAR_BIT     4
+#define MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT  3
+#define MPU6050_INTCFG_FSYNC_INT_EN_BIT     2
+#define MPU6050_INTCFG_I2C_BYPASS_EN_BIT    1
+#define MPU6050_INTCFG_CLKOUT_EN_BIT        0
+
+#define MPU6050_INTMODE_ACTIVEHIGH  0x00
+#define MPU6050_INTMODE_ACTIVELOW   0x01
+
+#define MPU6050_INTDRV_PUSHPULL     0x00
+#define MPU6050_INTDRV_OPENDRAIN    0x01
+
+#define MPU6050_INTLATCH_50USPULSE  0x00
+#define MPU6050_INTLATCH_WAITCLEAR  0x01
+
+#define MPU6050_INTCLEAR_STATUSREAD 0x00
+#define MPU6050_INTCLEAR_ANYREAD    0x01
+
+#define MPU6050_INTERRUPT_FF_BIT            7
+#define MPU6050_INTERRUPT_MOT_BIT           6
+#define MPU6050_INTERRUPT_ZMOT_BIT          5
+#define MPU6050_INTERRUPT_FIFO_OFLOW_BIT    4
+#define MPU6050_INTERRUPT_I2C_MST_INT_BIT   3
+#define MPU6050_INTERRUPT_PLL_RDY_INT_BIT   2
+#define MPU6050_INTERRUPT_DMP_INT_BIT       1
+#define MPU6050_INTERRUPT_DATA_RDY_BIT      0
+
+// TODO: figure out what these actually do
+// UMPL source code is not very obivous
+#define MPU6050_DMPINT_5_BIT            5
+#define MPU6050_DMPINT_4_BIT            4
+#define MPU6050_DMPINT_3_BIT            3
+#define MPU6050_DMPINT_2_BIT            2
+#define MPU6050_DMPINT_1_BIT            1
+#define MPU6050_DMPINT_0_BIT            0
+
+#define MPU6050_MOTION_MOT_XNEG_BIT     7
+#define MPU6050_MOTION_MOT_XPOS_BIT     6
+#define MPU6050_MOTION_MOT_YNEG_BIT     5
+#define MPU6050_MOTION_MOT_YPOS_BIT     4
+#define MPU6050_MOTION_MOT_ZNEG_BIT     3
+#define MPU6050_MOTION_MOT_ZPOS_BIT     2
+#define MPU6050_MOTION_MOT_ZRMOT_BIT    0
+
+#define MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT   7
+#define MPU6050_DELAYCTRL_I2C_SLV4_DLY_EN_BIT   4
+#define MPU6050_DELAYCTRL_I2C_SLV3_DLY_EN_BIT   3
+#define MPU6050_DELAYCTRL_I2C_SLV2_DLY_EN_BIT   2
+#define MPU6050_DELAYCTRL_I2C_SLV1_DLY_EN_BIT   1
+#define MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT   0
+
+#define MPU6050_PATHRESET_GYRO_RESET_BIT    2
+#define MPU6050_PATHRESET_ACCEL_RESET_BIT   1
+#define MPU6050_PATHRESET_TEMP_RESET_BIT    0
+
+#define MPU6050_DETECT_ACCEL_ON_DELAY_BIT       5
+#define MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH    2
+#define MPU6050_DETECT_FF_COUNT_BIT             3
+#define MPU6050_DETECT_FF_COUNT_LENGTH          2
+#define MPU6050_DETECT_MOT_COUNT_BIT            1
+#define MPU6050_DETECT_MOT_COUNT_LENGTH         2
+
+#define MPU6050_DETECT_DECREMENT_RESET  0x0
+#define MPU6050_DETECT_DECREMENT_1      0x1
+#define MPU6050_DETECT_DECREMENT_2      0x2
+#define MPU6050_DETECT_DECREMENT_4      0x3
+
+#define MPU6050_USERCTRL_DMP_EN_BIT             7
+#define MPU6050_USERCTRL_FIFO_EN_BIT            6
+#define MPU6050_USERCTRL_I2C_MST_EN_BIT         5
+#define MPU6050_USERCTRL_I2C_IF_DIS_BIT         4
+#define MPU6050_USERCTRL_DMP_RESET_BIT          3
+#define MPU6050_USERCTRL_FIFO_RESET_BIT         2
+#define MPU6050_USERCTRL_I2C_MST_RESET_BIT      1
+#define MPU6050_USERCTRL_SIG_COND_RESET_BIT     0
+
+#define MPU6050_PWR1_DEVICE_RESET_BIT   7
+#define MPU6050_PWR1_SLEEP_BIT          6
+#define MPU6050_PWR1_CYCLE_BIT          5
+#define MPU6050_PWR1_TEMP_DIS_BIT       3
+#define MPU6050_PWR1_CLKSEL_BIT         2
+#define MPU6050_PWR1_CLKSEL_LENGTH      3
+
+#define MPU6050_CLOCK_INTERNAL          0x00
+#define MPU6050_CLOCK_PLL_XGYRO         0x01
+#define MPU6050_CLOCK_PLL_YGYRO         0x02
+#define MPU6050_CLOCK_PLL_ZGYRO         0x03
+#define MPU6050_CLOCK_PLL_EXT32K        0x04
+#define MPU6050_CLOCK_PLL_EXT19M        0x05
+#define MPU6050_CLOCK_KEEP_RESET        0x07
+
+#define MPU6050_PWR2_LP_WAKE_CTRL_BIT       7
+#define MPU6050_PWR2_LP_WAKE_CTRL_LENGTH    2
+#define MPU6050_PWR2_STBY_XA_BIT            5
+#define MPU6050_PWR2_STBY_YA_BIT            4
+#define MPU6050_PWR2_STBY_ZA_BIT            3
+#define MPU6050_PWR2_STBY_XG_BIT            2
+#define MPU6050_PWR2_STBY_YG_BIT            1
+#define MPU6050_PWR2_STBY_ZG_BIT            0
+
+#define MPU6050_WAKE_FREQ_1P25      0x0
+#define MPU6050_WAKE_FREQ_2P5       0x1
+#define MPU6050_WAKE_FREQ_5         0x2
+#define MPU6050_WAKE_FREQ_10        0x3
+
+#define MPU6050_BANKSEL_PRFTCH_EN_BIT       6
+#define MPU6050_BANKSEL_CFG_USER_BANK_BIT   5
+#define MPU6050_BANKSEL_MEM_SEL_BIT         4
+#define MPU6050_BANKSEL_MEM_SEL_LENGTH      5
+
+#define MPU6050_WHO_AM_I_BIT        6
+#define MPU6050_WHO_AM_I_LENGTH     6
+
+#define MPU6050_DMP_MEMORY_BANKS        8
+#define MPU6050_DMP_MEMORY_BANK_SIZE    256
+#define MPU6050_DMP_MEMORY_CHUNK_SIZE   16
+
+// note: DMP code memory blocks defined at end of header file
+
+typedef struct MPU6050_t {
+    uint8_t devAddr;
+    uint8_t buffer[14];
+} MPU6050_t;
+
+void MPU6050(uint8_t address);
+
+void MPU6050_initialize();
+bool MPU6050_testConnection();
+
+// AUX_VDDIO register
+uint8_t MPU6050_getAuxVDDIOLevel();
+void MPU6050_setAuxVDDIOLevel(uint8_t level);
+
+// SMPLRT_DIV register
+uint8_t MPU6050_getRate();
+void MPU6050_setRate(uint8_t rate);
+
+// CONFIG register
+uint8_t MPU6050_getExternalFrameSync();
+void MPU6050_setExternalFrameSync(uint8_t sync);
+uint8_t MPU6050_getDLPFMode();
+void MPU6050_setDLPFMode(uint8_t bandwidth);
+
+// GYRO_CONFIG register
+uint8_t MPU6050_getFullScaleGyroRange();
+void MPU6050_setFullScaleGyroRange(uint8_t range);
+
+// ACCEL_CONFIG register
+bool MPU6050_getAccelXSelfTest();
+void MPU6050_setAccelXSelfTest(bool enabled);
+bool MPU6050_getAccelYSelfTest();
+void MPU6050_setAccelYSelfTest(bool enabled);
+bool MPU6050_getAccelZSelfTest();
+void MPU6050_setAccelZSelfTest(bool enabled);
+uint8_t MPU6050_getFullScaleAccelRange();
+void MPU6050_setFullScaleAccelRange(uint8_t range);
+uint8_t MPU6050_getDHPFMode();
+void MPU6050_setDHPFMode(uint8_t mode);
+
+// FF_THR register
+uint8_t MPU6050_getFreefallDetectionThreshold();
+void MPU6050_setFreefallDetectionThreshold(uint8_t threshold);
+
+// FF_DUR register
+uint8_t MPU6050_getFreefallDetectionDuration();
+void MPU6050_setFreefallDetectionDuration(uint8_t duration);
+
+// MOT_THR register
+uint8_t MPU6050_getMotionDetectionThreshold();
+void MPU6050_setMotionDetectionThreshold(uint8_t threshold);
+
+// MOT_DUR register
+uint8_t MPU6050_getMotionDetectionDuration();
+void MPU6050_setMotionDetectionDuration(uint8_t duration);
+
+// ZRMOT_THR register
+uint8_t MPU6050_getZeroMotionDetectionThreshold();
+void MPU6050_setZeroMotionDetectionThreshold(uint8_t threshold);
+
+// ZRMOT_DUR register
+uint8_t MPU6050_getZeroMotionDetectionDuration();
+void MPU6050_setZeroMotionDetectionDuration(uint8_t duration);
+
+// FIFO_EN register
+bool MPU6050_getTempFIFOEnabled();
+void MPU6050_setTempFIFOEnabled(bool enabled);
+bool MPU6050_getXGyroFIFOEnabled();
+void MPU6050_setXGyroFIFOEnabled(bool enabled);
+bool MPU6050_getYGyroFIFOEnabled();
+void MPU6050_setYGyroFIFOEnabled(bool enabled);
+bool MPU6050_getZGyroFIFOEnabled();
+void MPU6050_setZGyroFIFOEnabled(bool enabled);
+bool MPU6050_getAccelFIFOEnabled();
+void MPU6050_setAccelFIFOEnabled(bool enabled);
+bool MPU6050_getSlave2FIFOEnabled();
+void MPU6050_setSlave2FIFOEnabled(bool enabled);
+bool MPU6050_getSlave1FIFOEnabled();
+void MPU6050_setSlave1FIFOEnabled(bool enabled);
+bool MPU6050_getSlave0FIFOEnabled();
+void MPU6050_setSlave0FIFOEnabled(bool enabled);
+
+// I2C_MST_CTRL register
+bool MPU6050_getMultiMasterEnabled();
+void MPU6050_setMultiMasterEnabled(bool enabled);
+bool MPU6050_getWaitForExternalSensorEnabled();
+void MPU6050_setWaitForExternalSensorEnabled(bool enabled);
+bool MPU6050_getSlave3FIFOEnabled();
+void MPU6050_setSlave3FIFOEnabled(bool enabled);
+bool MPU6050_getSlaveReadWriteTransitionEnabled();
+void MPU6050_setSlaveReadWriteTransitionEnabled(bool enabled);
+uint8_t MPU6050_getMasterClockSpeed();
+void MPU6050_setMasterClockSpeed(uint8_t speed);
+
+// I2C_SLV* registers (Slave 0-3)
+uint8_t MPU6050_getSlaveAddress(uint8_t num);
+void MPU6050_setSlaveAddress(uint8_t num, uint8_t address);
+uint8_t MPU6050_getSlaveRegister(uint8_t num);
+void MPU6050_setSlaveRegister(uint8_t num, uint8_t reg);
+bool MPU6050_getSlaveEnabled(uint8_t num);
+void MPU6050_setSlaveEnabled(uint8_t num, bool enabled);
+bool MPU6050_getSlaveWordByteSwap(uint8_t num);
+void MPU6050_setSlaveWordByteSwap(uint8_t num, bool enabled);
+bool MPU6050_getSlaveWriteMode(uint8_t num);
+void MPU6050_setSlaveWriteMode(uint8_t num, bool mode);
+bool MPU6050_getSlaveWordGroupOffset(uint8_t num);
+void MPU6050_setSlaveWordGroupOffset(uint8_t num, bool enabled);
+uint8_t MPU6050_getSlaveDataLength(uint8_t num);
+void MPU6050_setSlaveDataLength(uint8_t num, uint8_t length);
+
+// I2C_SLV* registers (Slave 4)
+uint8_t MPU6050_getSlave4Address();
+void MPU6050_setSlave4Address(uint8_t address);
+uint8_t MPU6050_getSlave4Register();
+void MPU6050_setSlave4Register(uint8_t reg);
+void MPU6050_setSlave4OutputByte(uint8_t data);
+bool MPU6050_getSlave4Enabled();
+void MPU6050_setSlave4Enabled(bool enabled);
+bool MPU6050_getSlave4InterruptEnabled();
+void MPU6050_setSlave4InterruptEnabled(bool enabled);
+bool MPU6050_getSlave4WriteMode();
+void MPU6050_setSlave4WriteMode(bool mode);
+uint8_t MPU6050_getSlave4MasterDelay();
+void MPU6050_setSlave4MasterDelay(uint8_t delay);
+uint8_t MPU6050_getSlate4InputByte();
+
+// I2C_MST_STATUS register
+bool MPU6050_getPassthroughStatus();
+bool MPU6050_getSlave4IsDone();
+bool MPU6050_getLostArbitration();
+bool MPU6050_getSlave4Nack();
+bool MPU6050_getSlave3Nack();
+bool MPU6050_getSlave2Nack();
+bool MPU6050_getSlave1Nack();
+bool MPU6050_getSlave0Nack();
+
+// INT_PIN_CFG register
+bool MPU6050_getInterruptMode();
+void MPU6050_setInterruptMode(bool mode);
+bool MPU6050_getInterruptDrive();
+void MPU6050_setInterruptDrive(bool drive);
+bool MPU6050_getInterruptLatch();
+void MPU6050_setInterruptLatch(bool latch);
+bool MPU6050_getInterruptLatchClear();
+void MPU6050_setInterruptLatchClear(bool clear);
+bool MPU6050_getFSyncInterruptLevel();
+void MPU6050_setFSyncInterruptLevel(bool level);
+bool MPU6050_getFSyncInterruptEnabled();
+void MPU6050_setFSyncInterruptEnabled(bool enabled);
+bool MPU6050_getI2CBypassEnabled();
+void MPU6050_setI2CBypassEnabled(bool enabled);
+bool MPU6050_getClockOutputEnabled();
+void MPU6050_setClockOutputEnabled(bool enabled);
+
+// INT_ENABLE register
+uint8_t MPU6050_getIntEnabled();
+void MPU6050_setIntEnabled(uint8_t enabled);
+bool MPU6050_getIntFreefallEnabled();
+void MPU6050_setIntFreefallEnabled(bool enabled);
+bool MPU6050_getIntMotionEnabled();
+void MPU6050_setIntMotionEnabled(bool enabled);
+bool MPU6050_getIntZeroMotionEnabled();
+void MPU6050_setIntZeroMotionEnabled(bool enabled);
+bool MPU6050_getIntFIFOBufferOverflowEnabled();
+void MPU6050_setIntFIFOBufferOverflowEnabled(bool enabled);
+bool MPU6050_getIntI2CMasterEnabled();
+void MPU6050_setIntI2CMasterEnabled(bool enabled);
+bool MPU6050_getIntDataReadyEnabled();
+void MPU6050_setIntDataReadyEnabled(bool enabled);
+
+// INT_STATUS register
+uint8_t MPU6050_getIntStatus();
+bool MPU6050_getIntFreefallStatus();
+bool MPU6050_getIntMotionStatus();
+bool MPU6050_getIntZeroMotionStatus();
+bool MPU6050_getIntFIFOBufferOverflowStatus();
+bool MPU6050_getIntI2CMasterStatus();
+bool MPU6050_getIntDataReadyStatus();
+
+// ACCEL_*OUT_* registers
+void MPU6050_getMotion9(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz, int16_t* mx, int16_t* my, int16_t* mz);
+void MPU6050_getMotion6(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz);
+void MPU6050_getAcceleration(int16_t* x, int16_t* y, int16_t* z);
+int16_t MPU6050_getAccelerationX();
+int16_t MPU6050_getAccelerationY();
+int16_t MPU6050_getAccelerationZ();
+
+// TEMP_OUT_* registers
+int16_t MPU6050_getTemperature();
+
+// GYRO_*OUT_* registers
+void MPU6050_getRotation(int16_t* x, int16_t* y, int16_t* z);
+int16_t MPU6050_getRotationX();
+int16_t MPU6050_getRotationY();
+int16_t MPU6050_getRotationZ();
+
+// EXT_SENS_DATA_* registers
+uint8_t MPU6050_getExternalSensorByte(int position);
+uint16_t MPU6050_getExternalSensorWord(int position);
+uint32_t getExternalSensorDWord(int position);
+
+// MOT_DETECT_STATUS register
+bool MPU6050_getXNegMotionDetected();
+bool MPU6050_getXPosMotionDetected();
+bool MPU6050_getYNegMotionDetected();
+bool MPU6050_getYPosMotionDetected();
+bool MPU6050_getZNegMotionDetected();
+bool MPU6050_getZPosMotionDetected();
+bool MPU6050_getZeroMotionDetected();
+
+// I2C_SLV*_DO register
+void MPU6050_setSlaveOutputByte(uint8_t num, uint8_t data);
+
+// I2C_MST_DELAY_CTRL register
+bool MPU6050_getExternalShadowDelayEnabled();
+void MPU6050_setExternalShadowDelayEnabled(bool enabled);
+bool MPU6050_getSlaveDelayEnabled(uint8_t num);
+void MPU6050_setSlaveDelayEnabled(uint8_t num, bool enabled);
+
+// SIGNAL_PATH_RESET register
+void MPU6050_resetGyroscopePath();
+void MPU6050_resetAccelerometerPath();
+void MPU6050_resetTemperaturePath();
+
+// MOT_DETECT_CTRL register
+uint8_t MPU6050_getAccelerometerPowerOnDelay();
+void MPU6050_setAccelerometerPowerOnDelay(uint8_t delay);
+uint8_t MPU6050_getFreefallDetectionCounterDecrement();
+void MPU6050_setFreefallDetectionCounterDecrement(uint8_t decrement);
+uint8_t MPU6050_getMotionDetectionCounterDecrement();
+void MPU6050_setMotionDetectionCounterDecrement(uint8_t decrement);
+
+// USER_CTRL register
+bool MPU6050_getFIFOEnabled();
+void MPU6050_setFIFOEnabled(bool enabled);
+bool MPU6050_getI2CMasterModeEnabled();
+void MPU6050_setI2CMasterModeEnabled(bool enabled);
+void MPU6050_switchSPIEnabled(bool enabled);
+void MPU6050_resetFIFO();
+void MPU6050_resetI2CMaster();
+void MPU6050_resetSensors();
+
+// PWR_MGMT_1 register
+void MPU6050_reset();
+bool MPU6050_getSleepEnabled();
+void MPU6050_setSleepEnabled(bool enabled);
+bool MPU6050_getWakeCycleEnabled();
+void MPU6050_setWakeCycleEnabled(bool enabled);
+bool MPU6050_getTempSensorEnabled();
+void MPU6050_setTempSensorEnabled(bool enabled);
+uint8_t MPU6050_getClockSource();
+void MPU6050_setClockSource(uint8_t source);
+
+// PWR_MGMT_2 register
+uint8_t MPU6050_getWakeFrequency();
+void MPU6050_setWakeFrequency(uint8_t frequency);
+bool MPU6050_getStandbyXAccelEnabled();
+void MPU6050_setStandbyXAccelEnabled(bool enabled);
+bool MPU6050_getStandbyYAccelEnabled();
+void MPU6050_setStandbyYAccelEnabled(bool enabled);
+bool MPU6050_getStandbyZAccelEnabled();
+void MPU6050_setStandbyZAccelEnabled(bool enabled);
+bool MPU6050_getStandbyXGyroEnabled();
+void MPU6050_setStandbyXGyroEnabled(bool enabled);
+bool MPU6050_getStandbyYGyroEnabled();
+void MPU6050_setStandbyYGyroEnabled(bool enabled);
+bool MPU6050_getStandbyZGyroEnabled();
+void MPU6050_setStandbyZGyroEnabled(bool enabled);
+
+// FIFO_COUNT_* registers
+uint16_t MPU6050_getFIFOCount();
+
+// FIFO_R_W register
+uint8_t MPU6050_getFIFOByte();
+void MPU6050_setFIFOByte(uint8_t data);
+void MPU6050_getFIFOBytes(uint8_t *data, uint8_t length);
+
+// WHO_AM_I register
+uint8_t MPU6050_getDeviceID();
+void MPU6050_setDeviceID(uint8_t id);
+
+// ======== UNDOCUMENTED/DMP REGISTERS/METHODS ========
+
+// XG_OFFS_TC register
+uint8_t MPU6050_getOTPBankValid();
+void MPU6050_setOTPBankValid(bool enabled);
+int8_t getXGyroOffsetTC();
+void MPU6050_setXGyroOffsetTC(int8_t offset);
+
+// YG_OFFS_TC register
+int8_t getYGyroOffsetTC();
+void MPU6050_setYGyroOffsetTC(int8_t offset);
+
+// ZG_OFFS_TC register
+int8_t getZGyroOffsetTC();
+void MPU6050_setZGyroOffsetTC(int8_t offset);
+
+// X_FINE_GAIN register
+int8_t getXFineGain();
+void MPU6050_setXFineGain(int8_t gain);
+
+// Y_FINE_GAIN register
+int8_t getYFineGain();
+void MPU6050_setYFineGain(int8_t gain);
+
+// Z_FINE_GAIN register
+int8_t getZFineGain();
+void MPU6050_setZFineGain(int8_t gain);
+
+// XA_OFFS_* registers
+int16_t MPU6050_getXAccelOffset();
+void MPU6050_setXAccelOffset(int16_t offset);
+
+// YA_OFFS_* register
+int16_t MPU6050_getYAccelOffset();
+void MPU6050_setYAccelOffset(int16_t offset);
+
+// ZA_OFFS_* register
+int16_t MPU6050_getZAccelOffset();
+void MPU6050_setZAccelOffset(int16_t offset);
+
+// XG_OFFS_USR* registers
+int16_t MPU6050_getXGyroOffset();
+void MPU6050_setXGyroOffset(int16_t offset);
+
+// YG_OFFS_USR* register
+int16_t MPU6050_getYGyroOffset();
+void MPU6050_setYGyroOffset(int16_t offset);
+
+// ZG_OFFS_USR* register
+int16_t MPU6050_getZGyroOffset();
+void MPU6050_setZGyroOffset(int16_t offset);
+
+// INT_ENABLE register (DMP functions)
+bool MPU6050_getIntPLLReadyEnabled();
+void MPU6050_setIntPLLReadyEnabled(bool enabled);
+bool MPU6050_getIntDMPEnabled();
+void MPU6050_setIntDMPEnabled(bool enabled);
+
+// DMP_INT_STATUS
+bool MPU6050_getDMPInt5Status();
+bool MPU6050_getDMPInt4Status();
+bool MPU6050_getDMPInt3Status();
+bool MPU6050_getDMPInt2Status();
+bool MPU6050_getDMPInt1Status();
+bool MPU6050_getDMPInt0Status();
+
+// INT_STATUS register (DMP functions)
+bool MPU6050_getIntPLLReadyStatus();
+bool MPU6050_getIntDMPStatus();
+
+// USER_CTRL register (DMP functions)
+bool MPU6050_getDMPEnabled();
+void MPU6050_setDMPEnabled(bool enabled);
+void MPU6050_resetDMP();
+
+// BANK_SEL register
+void MPU6050_setMemoryBank(uint8_t bank, bool prefetchEnabled, bool userBank);
+
+// MEM_START_ADDR register
+void MPU6050_setMemoryStartAddress(uint8_t address);
+
+// MEM_R_W register
+uint8_t MPU6050_readMemoryByte();
+void MPU6050_writeMemoryByte(uint8_t data);
+void MPU6050_readMemoryBlock(uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address);
+//bool MPU6050_writeMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address, bool verify, bool useProgMem);
+//bool MPU6050_writeProgMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address, bool verify);
+
+//bool MPU6050_writeDMPConfigurationSet(const uint8_t *data, uint16_t dataSize, bool useProgMem);
+//bool MPU6050_writeProgDMPConfigurationSet(const uint8_t *data, uint16_t dataSize);
+
+// DMP_CFG_1 register
+uint8_t MPU6050_getDMPConfig1();
+void MPU6050_setDMPConfig1(uint8_t config);
+
+// DMP_CFG_2 register
+uint8_t MPU6050_getDMPConfig2();
+void MPU6050_setDMPConfig2(uint8_t config);
+
+#endif /* _MPU6050_H_ */
diff --git a/PIC18/README b/PIC18/README
new file mode 100644
index 00000000..858ae2bf
--- /dev/null
+++ b/PIC18/README
@@ -0,0 +1,14 @@
+# I2C Device Library for PIC18
+
+## I2Cdev
+We use XC8's peripheral libraries (_plib_), read timeout is not implemented.
+
+## Devices
+Currently only MPU6050 is supported without DMP functions. There's an example MPLABX project showing how to read raw data from the MPU.
+
+Adding more functions and devices should be straighforward after reading the source code.
+
+## Licence
+I2Cdev device library code is placed under the MIT license.
+
+_Copyright (c) 2011 Jeff Rowberg. Copyright (c) 2014 Marton Sebok._

From c16d179a6df90211a33984204a71496bb63118ff Mon Sep 17 00:00:00 2001
From: Marton Sebok 
Date: Fri, 28 Nov 2014 23:24:46 +0100
Subject: [PATCH 029/335] Changed readme to markdown.

---
 PIC18/{README => README.md} | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename PIC18/{README => README.md} (100%)

diff --git a/PIC18/README b/PIC18/README.md
similarity index 100%
rename from PIC18/README
rename to PIC18/README.md

From 80251bfd819bbd62b9b6bcf798850e706521d6ce Mon Sep 17 00:00:00 2001
From: Ivan Kravets 
Date: Sat, 6 Dec 2014 17:54:24 +0200
Subject: [PATCH 030/335] Correct keywords

---
 Arduino/AK8975/library.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Arduino/AK8975/library.json b/Arduino/AK8975/library.json
index 3c1300ba..b3585096 100644
--- a/Arduino/AK8975/library.json
+++ b/Arduino/AK8975/library.json
@@ -1,6 +1,6 @@
 {
   "name": "I2Cdevlib-AK8975",
-  "keywords": "i2cdevlib, i2c, ak8975, compass, sensor",
+  "keywords": "compass, sensor, i2cdevlib, i2c",
   "description": "AK8975 is 3-axis electronic compass IC with high sensitive Hall sensor technology",
   "include": "Arduino/AK8975",
   "repository":

From 61b8961e6e5021b606f3640d000675c905a2d800 Mon Sep 17 00:00:00 2001
From: Ivan Kravets 
Date: Sat, 6 Dec 2014 17:56:24 +0200
Subject: [PATCH 031/335] PLatformIO Library Registry manifest file

* This library in Web Registry: http://platformio.ikravets.com/#!/lib/show/94/I2Cdevlib-AD7746
* Specification: [PlatformIO Library Manager](http://docs.platformio.ikravets.com/en/latest/librarymanager/index.html)
* Integration: [IDE Integration](http://docs.platformio.ikravets.com/en/latest/ide.html)
---
 Arduino/AD7746/library.json | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)
 create mode 100644 Arduino/AD7746/library.json

diff --git a/Arduino/AD7746/library.json b/Arduino/AD7746/library.json
new file mode 100644
index 00000000..70940ff0
--- /dev/null
+++ b/Arduino/AD7746/library.json
@@ -0,0 +1,18 @@
+{
+  "name": "I2Cdevlib-AD7746",
+  "keywords": "capacitance, converter, sensor, i2cdevlib, i2c",
+  "description": "The AD7745/AD7746 are 24-Bit Capacitance-to-Digital Converter with Temperature Sensor",
+  "include": "Arduino/AD7746",
+  "repository":
+  {
+    "type": "git",
+    "url": "https://github.com/jrowberg/i2cdevlib.git"
+  },
+  "dependencies":
+  {
+    "name": "I2Cdevlib-Core",
+    "frameworks": "arduino"
+  },
+  "frameworks": "arduino",
+  "platforms": "atmelavr"
+}

From a8448c1809e3a44f5f18166bfa04dc555aa98031 Mon Sep 17 00:00:00 2001
From: Ivan Kravets 
Date: Sat, 6 Dec 2014 18:03:13 +0200
Subject: [PATCH 032/335] PlatformIO Library Registry manifest file

* This library in Web Registry: http://platformio.ikravets.com/#!/lib/show/95/I2Cdevlib-ADS1115
* Specification: [PlatformIO Library Manager](http://docs.platformio.ikravets.com/en/latest/librarymanager/index.html)
* Integration: [IDE Integration](http://docs.platformio.ikravets.com/en/latest/ide.html)
---
 Arduino/ADS1115/library.json | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)
 create mode 100644 Arduino/ADS1115/library.json

diff --git a/Arduino/ADS1115/library.json b/Arduino/ADS1115/library.json
new file mode 100644
index 00000000..e3e65531
--- /dev/null
+++ b/Arduino/ADS1115/library.json
@@ -0,0 +1,18 @@
+{
+  "name": "I2Cdevlib-ADS1115",
+  "keywords": "MUX, PGA, comparator, oscillator, reference, i2cdevlib, i2c",
+  "description": "ADS1115 is 16-Bit ADC with Integrated MUX, PGA, Comparator, Oscillator, and Reference",
+  "include": "Arduino/ADS1115",
+  "repository":
+  {
+    "type": "git",
+    "url": "https://github.com/jrowberg/i2cdevlib.git"
+  },
+  "dependencies":
+  {
+    "name": "I2Cdevlib-Core",
+    "frameworks": "arduino"
+  },
+  "frameworks": "arduino",
+  "platforms": "atmelavr"
+}

From 599cb9210736f0375ccff24152410cfc34364818 Mon Sep 17 00:00:00 2001
From: Ivan Kravets 
Date: Sat, 6 Dec 2014 18:07:54 +0200
Subject: [PATCH 033/335] PlatformIO Library Registry manifest file

* This library in Web Registry: http://platformio.ikravets.com/#!/lib/show/96/I2Cdevlib-ADXL345
* Specification: [PlatformIO Library Manager](http://docs.platformio.ikravets.com/en/latest/librarymanager/index.html)
* Integration: [IDE Integration](http://docs.platformio.ikravets.com/en/latest/ide.html)
---
 Arduino/ADXL345/library.json | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)
 create mode 100644 Arduino/ADXL345/library.json

diff --git a/Arduino/ADXL345/library.json b/Arduino/ADXL345/library.json
new file mode 100644
index 00000000..bb714182
--- /dev/null
+++ b/Arduino/ADXL345/library.json
@@ -0,0 +1,18 @@
+{
+  "name": "I2Cdevlib-ADXL345",
+  "keywords": "accelerometer, sensor, i2cdevlib, i2c",
+  "description": "The ADXL345 is a small, thin, ultralow power, 3-axis accelerometer with high resolution (13-bit) measurement",
+  "include": "Arduino/ADXL345",
+  "repository":
+  {
+    "type": "git",
+    "url": "https://github.com/jrowberg/i2cdevlib.git"
+  },
+  "dependencies":
+  {
+    "name": "I2Cdevlib-Core",
+    "frameworks": "arduino"
+  },
+  "frameworks": "arduino",
+  "platforms": "atmelavr"
+}

From a5aa49ccc5fd6d04c332d05866ee219572cd0aac Mon Sep 17 00:00:00 2001
From: Ivan Kravets 
Date: Sat, 6 Dec 2014 18:11:41 +0200
Subject: [PATCH 034/335] PlatformIO Library Registry manifest file

* This library in Web Registry: http://platformio.ikravets.com/#!/lib/show/97/I2Cdevlib-BMA150
* Specification: [PlatformIO Library Manager](http://docs.platformio.ikravets.com/en/latest/librarymanager/index.html)
* Integration: [IDE Integration](http://docs.platformio.ikravets.com/en/latest/ide.html)
---
 Arduino/BMA150/library.json | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)
 create mode 100644 Arduino/BMA150/library.json

diff --git a/Arduino/BMA150/library.json b/Arduino/BMA150/library.json
new file mode 100644
index 00000000..bd28c410
--- /dev/null
+++ b/Arduino/BMA150/library.json
@@ -0,0 +1,18 @@
+{
+  "name": "I2Cdevlib-BMA150",
+  "keywords": "accelerometer, sensor, i2cdevlib, i2c",
+  "description": "The BMA150 is a triaxial, low-g acceleration sensor IC with digital output for consumer market applications",
+  "include": "Arduino/BMA150",
+  "repository":
+  {
+    "type": "git",
+    "url": "https://github.com/jrowberg/i2cdevlib.git"
+  },
+  "dependencies":
+  {
+    "name": "I2Cdevlib-Core",
+    "frameworks": "arduino"
+  },
+  "frameworks": "arduino",
+  "platforms": "atmelavr"
+}

From 28bcd733b43e11274f1c2a94e628bcae735bf7f6 Mon Sep 17 00:00:00 2001
From: Ivan Kravets 
Date: Sat, 6 Dec 2014 19:08:43 +0200
Subject: [PATCH 035/335] PlatformIO Library Registry manifest file

* This library in Web Registry: http://platformio.ikravets.com/#!/lib/show/98/I2Cdevlib-BMP085
* Specification: [PlatformIO Library Manager](http://docs.platformio.ikravets.com/en/latest/librarymanager/index.html)
* Integration: [IDE Integration](http://docs.platformio.ikravets.com/en/latest/ide.html)
---
 Arduino/BMP085/library.json | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)
 create mode 100644 Arduino/BMP085/library.json

diff --git a/Arduino/BMP085/library.json b/Arduino/BMP085/library.json
new file mode 100644
index 00000000..a29ef252
--- /dev/null
+++ b/Arduino/BMP085/library.json
@@ -0,0 +1,18 @@
+{
+  "name": "I2Cdevlib-BMP085",
+  "keywords": "altimeter, altitude, barometer, pressure, temperature, sensor, i2cdevlib, i2c",
+  "description": "The BMP085 is barometric pressure, temperature and altitude sensor",
+  "include": "Arduino/BMP085",
+  "repository":
+  {
+    "type": "git",
+    "url": "https://github.com/jrowberg/i2cdevlib.git"
+  },
+  "dependencies":
+  {
+    "name": "I2Cdevlib-Core",
+    "frameworks": "arduino"
+  },
+  "frameworks": "arduino",
+  "platforms": "atmelavr"
+}

From d1681c1ffe6b79f184dd728112fdda6359556d5f Mon Sep 17 00:00:00 2001
From: Ivan Kravets 
Date: Sat, 6 Dec 2014 19:53:22 +0200
Subject: [PATCH 036/335] PlatformIO Library Registry manifest file

* This library in Web Registry: http://platformio.ikravets.com/#!/lib/show/99/I2Cdevlib-DS1307
* Specification: [PlatformIO Library Manager](http://docs.platformio.ikravets.com/en/latest/librarymanager/index.html)
* Integration: [IDE Integration](http://docs.platformio.ikravets.com/en/latest/ide.html)
---
 Arduino/DS1307/library.json | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)
 create mode 100644 Arduino/DS1307/library.json

diff --git a/Arduino/DS1307/library.json b/Arduino/DS1307/library.json
new file mode 100644
index 00000000..8dba5473
--- /dev/null
+++ b/Arduino/DS1307/library.json
@@ -0,0 +1,18 @@
+{
+  "name": "I2Cdevlib-DS1307",
+  "keywords": "rtc, time, clock, i2cdevlib, i2c",
+  "description": "The DS1307 serial real-time clock (RTC) is a low-power, full binary-coded decimal (BCD) clock/calendar plus 56 bytes of NV SRAM",
+  "include": "Arduino/DS1307",
+  "repository":
+  {
+    "type": "git",
+    "url": "https://github.com/jrowberg/i2cdevlib.git"
+  },
+  "dependencies":
+  {
+    "name": "I2Cdevlib-Core",
+    "frameworks": "arduino"
+  },
+  "frameworks": "arduino",
+  "platforms": "atmelavr"
+}

From 3373d6f1962d5d36260172c251234b9e58092686 Mon Sep 17 00:00:00 2001
From: Ivan Kravets 
Date: Sat, 6 Dec 2014 19:59:42 +0200
Subject: [PATCH 037/335] PlatformIO Library Registry manifest file

* This library in Web Registry: http://platformio.ikravets.com/#!/lib/show/100/I2Cdevlib-HMC5843
* Specification: [PlatformIO Library Manager](http://docs.platformio.ikravets.com/en/latest/librarymanager/index.html)
* Integration: [IDE Integration](http://docs.platformio.ikravets.com/en/latest/ide.html)
---
 Arduino/HMC5843/library.json | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)
 create mode 100644 Arduino/HMC5843/library.json

diff --git a/Arduino/HMC5843/library.json b/Arduino/HMC5843/library.json
new file mode 100644
index 00000000..51f6926e
--- /dev/null
+++ b/Arduino/HMC5843/library.json
@@ -0,0 +1,18 @@
+{
+  "name": "I2Cdevlib-HMC5843",
+  "keywords": "magnetometer, compass, sensor, i2cdevlib, i2c",
+  "description": "The HMC5843 is 3-Axis digital compass/magnetometer",
+  "include": "Arduino/HMC5843",
+  "repository":
+  {
+    "type": "git",
+    "url": "https://github.com/jrowberg/i2cdevlib.git"
+  },
+  "dependencies":
+  {
+    "name": "I2Cdevlib-Core",
+    "frameworks": "arduino"
+  },
+  "frameworks": "arduino",
+  "platforms": "atmelavr"
+}

From 3c788cb7b66eacb35cc4b2a1fd5794e2565d04fe Mon Sep 17 00:00:00 2001
From: Ivan Kravets 
Date: Sat, 6 Dec 2014 20:05:14 +0200
Subject: [PATCH 038/335] PlatformIO Library Registry manifest file

* This library in Web Registry: http://platformio.ikravets.com/#!/lib/show/101/HMC5883L
* Specification: [PlatformIO Library Manager](http://docs.platformio.ikravets.com/en/latest/librarymanager/index.html)
* Integration: [IDE Integration](http://docs.platformio.ikravets.com/en/latest/ide.html)
---
 Arduino/HMC5883L/library.json | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)
 create mode 100644 Arduino/HMC5883L/library.json

diff --git a/Arduino/HMC5883L/library.json b/Arduino/HMC5883L/library.json
new file mode 100644
index 00000000..14614e9b
--- /dev/null
+++ b/Arduino/HMC5883L/library.json
@@ -0,0 +1,18 @@
+{
+  "name": "I2Cdevlib-HMC5883L",
+  "keywords": "magnetometer, compass, sensor, i2cdevlib, i2c",
+  "description": "The HMC5883L is 3-Axis digital compass/magnetometer",
+  "include": "Arduino/HMC5883L",
+  "repository":
+  {
+    "type": "git",
+    "url": "https://github.com/jrowberg/i2cdevlib.git"
+  },
+  "dependencies":
+  {
+    "name": "I2Cdevlib-Core",
+    "frameworks": "arduino"
+  },
+  "frameworks": "arduino",
+  "platforms": "atmelavr"
+}

From d765b726a6dd57e8f1b16ef3394cdaf0c3fd8687 Mon Sep 17 00:00:00 2001
From: Ivan Kravets 
Date: Sat, 6 Dec 2014 20:21:00 +0200
Subject: [PATCH 039/335] PlatformIO Library Registry manifest file

* This library in Web Registry: http://platformio.ikravets.com/#!/lib/show/102/IAQ2000
* Specification: [PlatformIO Library Manager](http://docs.platformio.ikravets.com/en/latest/librarymanager/index.html)
* Integration: [IDE Integration](http://docs.platformio.ikravets.com/en/latest/ide.html)
---
 Arduino/IAQ2000/library.json | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)
 create mode 100644 Arduino/IAQ2000/library.json

diff --git a/Arduino/IAQ2000/library.json b/Arduino/IAQ2000/library.json
new file mode 100644
index 00000000..5eb15957
--- /dev/null
+++ b/Arduino/IAQ2000/library.json
@@ -0,0 +1,18 @@
+{
+  "name": "I2Cdevlib-IAQ2000",
+  "keywords": "co2, carbon, dioxide, sensor, i2cdevlib, i2c",
+  "description": "The iAQ-2000 Indoor Air Quality Module is a sensitive, low-cost solution for detecting poor air quality",
+  "include": "Arduino/IAQ2000",
+  "repository":
+  {
+    "type": "git",
+    "url": "https://github.com/jrowberg/i2cdevlib.git"
+  },
+  "dependencies":
+  {
+    "name": "I2Cdevlib-Core",
+    "frameworks": "arduino"
+  },
+  "frameworks": "arduino",
+  "platforms": "atmelavr"
+}

From 51be6c6d9bbf85baaf3bd0a06110fc106537df23 Mon Sep 17 00:00:00 2001
From: Ivan Kravets 
Date: Sat, 6 Dec 2014 20:41:33 +0200
Subject: [PATCH 040/335] PlatformIO Library Registry manifest file

* This library in Web Registry: http://platformio.ikravets.com/#!/lib/show/103/I2Cdevlib-ITG3200
* Specification: [PlatformIO Library Manager](http://docs.platformio.ikravets.com/en/latest/librarymanager/index.html)
* Integration: [IDE Integration](http://docs.platformio.ikravets.com/en/latest/ide.html)
---
 Arduino/ITG3200/library.json | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)
 create mode 100644 Arduino/ITG3200/library.json

diff --git a/Arduino/ITG3200/library.json b/Arduino/ITG3200/library.json
new file mode 100644
index 00000000..398dfcdf
--- /dev/null
+++ b/Arduino/ITG3200/library.json
@@ -0,0 +1,18 @@
+{
+  "name": "I2Cdevlib-ITG3200",
+  "keywords": "gyroscope, sensor, i2cdevlib, i2c",
+  "description": "The ITG-3200 is groundbreaking 3-axis, digital output MEMS gyroscope",
+  "include": "Arduino/ITG3200",
+  "repository":
+  {
+    "type": "git",
+    "url": "https://github.com/jrowberg/i2cdevlib.git"
+  },
+  "dependencies":
+  {
+    "name": "I2Cdevlib-Core",
+    "frameworks": "arduino"
+  },
+  "frameworks": "arduino",
+  "platforms": "atmelavr"
+}

From edfd3a309fade27fe5813719adfaab9f62acd92c Mon Sep 17 00:00:00 2001
From: Ivan Kravets 
Date: Sat, 6 Dec 2014 20:50:21 +0200
Subject: [PATCH 041/335] PlatformIO Library Registry manifest file

* This library in Web Registry: http://platformio.ikravets.com/#!/lib/show/104/I2Cdevlib-L3G4200D
* Specification: [PlatformIO Library Manager](http://docs.platformio.ikravets.com/en/latest/librarymanager/index.html)
* Integration: [IDE Integration](http://docs.platformio.ikravets.com/en/latest/ide.html)
---
 Arduino/L3G4200D/library.json | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)
 create mode 100644 Arduino/L3G4200D/library.json

diff --git a/Arduino/L3G4200D/library.json b/Arduino/L3G4200D/library.json
new file mode 100644
index 00000000..f899e316
--- /dev/null
+++ b/Arduino/L3G4200D/library.json
@@ -0,0 +1,18 @@
+{
+  "name": "I2Cdevlib-L3G4200D",
+  "keywords": "accelerometer, sensor, i2cdevlib, i2c",
+  "description": "The L3G4200D is a low-power three-axis angular rate sensor able to provide unprecedented stablility of zero rate level and sensitivity over temperature and time",
+  "include": "Arduino/L3G4200D",
+  "repository":
+  {
+    "type": "git",
+    "url": "https://github.com/jrowberg/i2cdevlib.git"
+  },
+  "dependencies":
+  {
+    "name": "I2Cdevlib-Core",
+    "frameworks": "arduino"
+  },
+  "frameworks": "arduino",
+  "platforms": "atmelavr"
+}

From dd3ce1d8a3bff9f735dadef7e70212025f2df81d Mon Sep 17 00:00:00 2001
From: Ivan Kravets 
Date: Sat, 6 Dec 2014 20:53:16 +0200
Subject: [PATCH 042/335] PlatformIO Library Registry manifest file

* This library in Web Registry: http://platformio.ikravets.com/#!/lib/show/105/I2Cdevlib-LM73
* Specification: [PlatformIO Library Manager](http://docs.platformio.ikravets.com/en/latest/librarymanager/index.html)
* Integration: [IDE Integration](http://docs.platformio.ikravets.com/en/latest/ide.html)
---
 Arduino/LM73/library.json | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)
 create mode 100644 Arduino/LM73/library.json

diff --git a/Arduino/LM73/library.json b/Arduino/LM73/library.json
new file mode 100644
index 00000000..f547a772
--- /dev/null
+++ b/Arduino/LM73/library.json
@@ -0,0 +1,18 @@
+{
+  "name": "I2Cdevlib-LM73",
+  "keywords": "temperature, sensor, i2cdevlib, i2c",
+  "description": "The LM73 is an integrated, digital-output temperature sensor featuring an incremental Delta-Sigma ADC",
+  "include": "Arduino/LM73",
+  "repository":
+  {
+    "type": "git",
+    "url": "https://github.com/jrowberg/i2cdevlib.git"
+  },
+  "dependencies":
+  {
+    "name": "I2Cdevlib-Core",
+    "frameworks": "arduino"
+  },
+  "frameworks": "arduino",
+  "platforms": "atmelavr"
+}

From 1cc9db7c918980797e97b9ec74de126884ffd38e Mon Sep 17 00:00:00 2001
From: Ivan Kravets 
Date: Sat, 6 Dec 2014 20:57:49 +0200
Subject: [PATCH 043/335] PlatformIO Library Registry manifest file

* This library in Web Registry: http://platformio.ikravets.com/#!/lib/show/106/I2Cdevlib-MPR121
* Specification: [PlatformIO Library Manager](http://docs.platformio.ikravets.com/en/latest/librarymanager/index.html)
* Integration: [IDE Integration](http://docs.platformio.ikravets.com/en/latest/ide.html)
---
 Arduino/MPR121/library.json | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)
 create mode 100644 Arduino/MPR121/library.json

diff --git a/Arduino/MPR121/library.json b/Arduino/MPR121/library.json
new file mode 100644
index 00000000..afce11bb
--- /dev/null
+++ b/Arduino/MPR121/library.json
@@ -0,0 +1,18 @@
+{
+  "name": "I2Cdevlib-MPR121",
+  "keywords": "touch, capacitance, proximity, sensor, i2cdevlib, i2c",
+  "description": "The MPR121 is a 12-bit proximity capacitive touch sensor",
+  "include": "Arduino/MPR121",
+  "repository":
+  {
+    "type": "git",
+    "url": "https://github.com/jrowberg/i2cdevlib.git"
+  },
+  "dependencies":
+  {
+    "name": "I2Cdevlib-Core",
+    "frameworks": "arduino"
+  },
+  "frameworks": "arduino",
+  "platforms": "atmelavr"
+}

From 2b18fc95411ec3fdcbb688ad823cacca8a46df35 Mon Sep 17 00:00:00 2001
From: Ivan Kravets 
Date: Sat, 6 Dec 2014 22:20:56 +0200
Subject: [PATCH 044/335] PlatformIO Library Registry manifest file

* This library in Web Registry: http://platformio.ikravets.com/#!/lib/show/107/I2Cdevlib-MPU6050
* Specification: [PlatformIO Library Manager](http://docs.platformio.ikravets.com/en/latest/librarymanager/index.html)
* Integration: [IDE Integration](http://docs.platformio.ikravets.com/en/latest/ide.html)
---
 Arduino/MPU6050/library.json | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)
 create mode 100644 Arduino/MPU6050/library.json

diff --git a/Arduino/MPU6050/library.json b/Arduino/MPU6050/library.json
new file mode 100644
index 00000000..174b4529
--- /dev/null
+++ b/Arduino/MPU6050/library.json
@@ -0,0 +1,18 @@
+{
+  "name": "I2Cdevlib-MPU6050",
+  "keywords": "gyroscope, accelerometer, sensor, i2cdevlib, i2c",
+  "description": "The MPU6050 combines a 3-axis gyroscope and a 3-axis accelerometer on the same silicon die together with an onboard Digital Motion Processor(DMP) which processes complex 6-axis MotionFusion algorithms",
+  "include": "Arduino/MPU6050",
+  "repository":
+  {
+    "type": "git",
+    "url": "https://github.com/jrowberg/i2cdevlib.git"
+  },
+  "dependencies":
+  {
+    "name": "I2Cdevlib-Core",
+    "frameworks": "arduino"
+  },
+  "frameworks": "arduino",
+  "platforms": "atmelavr"
+}

From 3ed56ac6bc61c0e4d37538daffdd697370512f29 Mon Sep 17 00:00:00 2001
From: Ivan Kravets 
Date: Sat, 6 Dec 2014 22:28:23 +0200
Subject: [PATCH 045/335] PlatformIO Library Registry manifest file

* This library in Web Registry: http://platformio.ikravets.com/#!/lib/show/108/I2Cdevlib-SSD1308
* Specification: [PlatformIO Library Manager](http://docs.platformio.ikravets.com/en/latest/librarymanager/index.html)
* Integration: [IDE Integration](http://docs.platformio.ikravets.com/en/latest/ide.html)
---
 Arduino/SSD1308/library.json | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)
 create mode 100644 Arduino/SSD1308/library.json

diff --git a/Arduino/SSD1308/library.json b/Arduino/SSD1308/library.json
new file mode 100644
index 00000000..9e0db1cd
--- /dev/null
+++ b/Arduino/SSD1308/library.json
@@ -0,0 +1,18 @@
+{
+  "name": "I2Cdevlib-SSD1308",
+  "keywords": "oled, pled, display, driver, i2cdevlib, i2c",
+  "description": "SSD1308 is a single-chip CMOS OLED/PLED driver with controller for organic / polymer light emitting diode dot-matrix graphic display system",
+  "include": "Arduino/SSD1308",
+  "repository":
+  {
+    "type": "git",
+    "url": "https://github.com/jrowberg/i2cdevlib.git"
+  },
+  "dependencies":
+  {
+    "name": "I2Cdevlib-Core",
+    "frameworks": "arduino"
+  },
+  "frameworks": "arduino",
+  "platforms": "atmelavr"
+}

From f9f9a1fddd83233fbd4ae403b5b577b334765adc Mon Sep 17 00:00:00 2001
From: Ivan Kravets 
Date: Sat, 6 Dec 2014 22:34:12 +0200
Subject: [PATCH 046/335] PlatformIO Library Registry manifest file

* This library in Web Registry: http://platformio.ikravets.com/#!/lib/show/109/I2Cdevlib-TCA6424A
* Specification: [PlatformIO Library Manager](http://docs.platformio.ikravets.com/en/latest/librarymanager/index.html)
* Integration: [IDE Integration](http://docs.platformio.ikravets.com/en/latest/ide.html)
---
 Arduino/TCA6424A/library.json | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)
 create mode 100644 Arduino/TCA6424A/library.json

diff --git a/Arduino/TCA6424A/library.json b/Arduino/TCA6424A/library.json
new file mode 100644
index 00000000..a0779dfb
--- /dev/null
+++ b/Arduino/TCA6424A/library.json
@@ -0,0 +1,18 @@
+{
+  "name": "I2Cdevlib-TCA6424A",
+  "keywords": "io, expander, i2cdevlib, i2c",
+  "description": "The TCA6424A is a low-voltage 24-Bit I2C and SMBus I/O expander with interrupt output, reset and configuration registers",
+  "include": "Arduino/TCA6424A",
+  "repository":
+  {
+    "type": "git",
+    "url": "https://github.com/jrowberg/i2cdevlib.git"
+  },
+  "dependencies":
+  {
+    "name": "I2Cdevlib-Core",
+    "frameworks": "arduino"
+  },
+  "frameworks": "arduino",
+  "platforms": "atmelavr"
+}

From 1a0135d3a6c9d8d91e53d33708d8bb6c9ee3000b Mon Sep 17 00:00:00 2001
From: Ivan Kravets 
Date: Sat, 6 Dec 2014 22:40:01 +0200
Subject: [PATCH 047/335] PlatformIO Library Registry manifest file

* This library in Web Registry: http://platformio.ikravets.com/#!/lib/show/110/I2Cdevlib-Core
* Specification: [PlatformIO Library Manager](http://docs.platformio.ikravets.com/en/latest/librarymanager/index.html)
* Integration: [IDE Integration](http://docs.platformio.ikravets.com/en/latest/ide.html)
---
 MSP430/I2Cdev/library.json | 13 +++++++++++++
 1 file changed, 13 insertions(+)
 create mode 100644 MSP430/I2Cdev/library.json

diff --git a/MSP430/I2Cdev/library.json b/MSP430/I2Cdev/library.json
new file mode 100644
index 00000000..98e0963f
--- /dev/null
+++ b/MSP430/I2Cdev/library.json
@@ -0,0 +1,13 @@
+{
+  "name": "I2Cdevlib-Core",
+  "keywords": "i2cdevlib, i2c",
+  "description": "The I2C Device Library (I2Cdevlib) is a collection of uniform and well-documented classes to provide simple and intuitive interfaces to I2C devices.",
+  "include": "MSP430/I2Cdev",
+  "repository":
+  {
+    "type": "git",
+    "url": "https://github.com/jrowberg/i2cdevlib.git"
+  },
+  "frameworks": "energia",
+  "platforms": "timsp430"
+}

From 2fcaabcd2d3f036fc60a05f8e74621564cc204cd Mon Sep 17 00:00:00 2001
From: Ivan Kravets 
Date: Sat, 6 Dec 2014 22:43:11 +0200
Subject: [PATCH 048/335] PlatformIO Library Registry manifest file

* This library in Web Registry: http://platformio.ikravets.com/#!/lib/show/111/I2Cdevlib-AK8975
* Specification: [PlatformIO Library Manager](http://docs.platformio.ikravets.com/en/latest/librarymanager/index.html)
* Integration: [IDE Integration](http://docs.platformio.ikravets.com/en/latest/ide.html)
---
 MSP430/AK8975/library.json | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)
 create mode 100644 MSP430/AK8975/library.json

diff --git a/MSP430/AK8975/library.json b/MSP430/AK8975/library.json
new file mode 100644
index 00000000..1c5bb422
--- /dev/null
+++ b/MSP430/AK8975/library.json
@@ -0,0 +1,18 @@
+{
+  "name": "I2Cdevlib-AK8975",
+  "keywords": "compass, sensor, i2cdevlib, i2c",
+  "description": "AK8975 is 3-axis electronic compass IC with high sensitive Hall sensor technology",
+  "include": "Arduino/AK8975",
+  "repository":
+  {
+    "type": "git",
+    "url": "https://github.com/jrowberg/i2cdevlib.git"
+  },
+  "dependencies":
+  {
+    "name": "I2Cdevlib-Core",
+    "platforms": "timsp430"
+  },
+  "frameworks": "energia",
+  "platforms": "timsp430"
+}

From 8e87970f07f20e37f6e83a592cf89b9d5199e392 Mon Sep 17 00:00:00 2001
From: Ivan Kravets 
Date: Sat, 6 Dec 2014 22:46:58 +0200
Subject: [PATCH 049/335] PlatformIO Library Registry manifest file

* This library in Web Registry: http://platformio.ikravets.com/#!/lib/show/112/I2Cdevlib-MPU6050
* Specification: [PlatformIO Library Manager](http://docs.platformio.ikravets.com/en/latest/librarymanager/index.html)
* Integration: [IDE Integration](http://docs.platformio.ikravets.com/en/latest/ide.html)
---
 MSP430/MPU6050/library.json | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)
 create mode 100644 MSP430/MPU6050/library.json

diff --git a/MSP430/MPU6050/library.json b/MSP430/MPU6050/library.json
new file mode 100644
index 00000000..a49379ef
--- /dev/null
+++ b/MSP430/MPU6050/library.json
@@ -0,0 +1,18 @@
+{
+  "name": "I2Cdevlib-MPU6050",
+  "keywords": "gyroscope, accelerometer, sensor, i2cdevlib, i2c",
+  "description": "The MPU6050 combines a 3-axis gyroscope and a 3-axis accelerometer on the same silicon die together with an onboard Digital Motion Processor(DMP) which processes complex 6-axis MotionFusion algorithms",
+  "include": "Arduino/MPU6050",
+  "repository":
+  {
+    "type": "git",
+    "url": "https://github.com/jrowberg/i2cdevlib.git"
+  },
+  "dependencies":
+  {
+    "name": "I2Cdevlib-Core",
+    "platforms": "timsp430"
+  },
+  "frameworks": "energia",
+  "platforms": "timsp430"
+}

From b87d06700eb630c3aa80908f15b0b8ead1c73162 Mon Sep 17 00:00:00 2001
From: Ivan Kravets 
Date: Sun, 7 Dec 2014 00:01:34 +0200
Subject: [PATCH 050/335] Add MPU6050 dependency

---
 Arduino/AK8975/library.json | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/Arduino/AK8975/library.json b/Arduino/AK8975/library.json
index b3585096..0010d1ef 100644
--- a/Arduino/AK8975/library.json
+++ b/Arduino/AK8975/library.json
@@ -9,10 +9,16 @@
     "url": "https://github.com/jrowberg/i2cdevlib.git"
   },
   "dependencies":
-  {
-    "name": "I2Cdevlib-Core",
-    "frameworks": "arduino"
-  },
+  [
+    {
+      "name": "I2Cdevlib-Core",
+      "frameworks": "arduino"
+    },
+    {
+      "name": "I2Cdevlib-MPU6050",
+      "frameworks": "arduino"
+    }    
+  ],
   "frameworks": "arduino",
   "platforms": "atmelavr"
 }

From 671eb559f82f3f5805a197b0e6780ad7db466c21 Mon Sep 17 00:00:00 2001
From: Ivan Kravets 
Date: Sun, 7 Dec 2014 00:02:39 +0200
Subject: [PATCH 051/335] Add MPU6050 dependency

---
 MSP430/AK8975/library.json | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/MSP430/AK8975/library.json b/MSP430/AK8975/library.json
index 1c5bb422..2e4d1a38 100644
--- a/MSP430/AK8975/library.json
+++ b/MSP430/AK8975/library.json
@@ -9,10 +9,16 @@
     "url": "https://github.com/jrowberg/i2cdevlib.git"
   },
   "dependencies":
-  {
-    "name": "I2Cdevlib-Core",
-    "platforms": "timsp430"
-  },
+  [
+    {
+      "name": "I2Cdevlib-Core",
+      "platforms": "timsp430"
+    },
+    {
+      "name": "I2Cdevlib-MPU6050",
+      "platforms": "timsp430"
+    }    
+  ],  
   "frameworks": "energia",
   "platforms": "timsp430"
 }

From 354e5175924c0a4f279e0f58e3fea0e355dfa0d3 Mon Sep 17 00:00:00 2001
From: Tom Beighley 
Date: Sat, 6 Dec 2014 23:03:44 -0600
Subject: [PATCH 052/335] Adding MAX6956

---
 Arduino/MAX6956/Doxyfile                      | 1781 +++++++++
 .../MAX6956_LED_FADE/MAX6956_LED_Fade.ino     |   61 +
 Arduino/MAX6956/MAX6956.cpp                   |  573 +++
 Arduino/MAX6956/MAX6956.h                     |  573 +++
 Arduino/MAX6956/comments.txt                  |   64 +
 Arduino/MAX6956/html/MAX6956_8cpp.html        |   99 +
 Arduino/MAX6956/html/MAX6956_8cpp_source.html |  463 +++
 Arduino/MAX6956/html/MAX6956_8h.html          | 3196 +++++++++++++++++
 Arduino/MAX6956/html/MAX6956_8h_source.html   |  446 +++
 Arduino/MAX6956/html/annotated.html           |  101 +
 Arduino/MAX6956/html/bc_s.png                 |  Bin 0 -> 676 bytes
 Arduino/MAX6956/html/bdwn.png                 |  Bin 0 -> 147 bytes
 Arduino/MAX6956/html/classMAX6956.html        | 1205 +++++++
 Arduino/MAX6956/html/classes.html             |  105 +
 Arduino/MAX6956/html/closed.png               |  Bin 0 -> 132 bytes
 Arduino/MAX6956/html/doxygen.css              | 1357 +++++++
 Arduino/MAX6956/html/doxygen.png              |  Bin 0 -> 3779 bytes
 Arduino/MAX6956/html/dynsections.js           |  104 +
 Arduino/MAX6956/html/files.html               |  102 +
 Arduino/MAX6956/html/ftv2blank.png            |  Bin 0 -> 86 bytes
 Arduino/MAX6956/html/ftv2cl.png               |  Bin 0 -> 453 bytes
 Arduino/MAX6956/html/ftv2doc.png              |  Bin 0 -> 746 bytes
 Arduino/MAX6956/html/ftv2folderclosed.png     |  Bin 0 -> 616 bytes
 Arduino/MAX6956/html/ftv2folderopen.png       |  Bin 0 -> 597 bytes
 Arduino/MAX6956/html/ftv2lastnode.png         |  Bin 0 -> 86 bytes
 Arduino/MAX6956/html/ftv2link.png             |  Bin 0 -> 746 bytes
 Arduino/MAX6956/html/ftv2mlastnode.png        |  Bin 0 -> 246 bytes
 Arduino/MAX6956/html/ftv2mnode.png            |  Bin 0 -> 246 bytes
 Arduino/MAX6956/html/ftv2mo.png               |  Bin 0 -> 403 bytes
 Arduino/MAX6956/html/ftv2node.png             |  Bin 0 -> 86 bytes
 Arduino/MAX6956/html/ftv2ns.png               |  Bin 0 -> 388 bytes
 Arduino/MAX6956/html/ftv2plastnode.png        |  Bin 0 -> 229 bytes
 Arduino/MAX6956/html/ftv2pnode.png            |  Bin 0 -> 229 bytes
 Arduino/MAX6956/html/ftv2splitbar.png         |  Bin 0 -> 314 bytes
 Arduino/MAX6956/html/ftv2vertline.png         |  Bin 0 -> 86 bytes
 Arduino/MAX6956/html/functions.html           |  266 ++
 Arduino/MAX6956/html/functions_func.html      |  182 +
 Arduino/MAX6956/html/functions_vars.html      |  128 +
 Arduino/MAX6956/html/globals.html             |  611 ++++
 Arduino/MAX6956/html/globals_defs.html        |  611 ++++
 Arduino/MAX6956/html/index.html               |   90 +
 Arduino/MAX6956/html/installdox               |  112 +
 Arduino/MAX6956/html/jquery.js                |   39 +
 Arduino/MAX6956/html/nav_f.png                |  Bin 0 -> 153 bytes
 Arduino/MAX6956/html/nav_g.png                |  Bin 0 -> 95 bytes
 Arduino/MAX6956/html/nav_h.png                |  Bin 0 -> 98 bytes
 Arduino/MAX6956/html/open.png                 |  Bin 0 -> 123 bytes
 Arduino/MAX6956/html/search/all_62.html       |   26 +
 Arduino/MAX6956/html/search/all_62.js         |    4 +
 Arduino/MAX6956/html/search/all_63.html       |   26 +
 Arduino/MAX6956/html/search/all_63.js         |    6 +
 Arduino/MAX6956/html/search/all_64.html       |   26 +
 Arduino/MAX6956/html/search/all_64.js         |    5 +
 Arduino/MAX6956/html/search/all_65.html       |   26 +
 Arduino/MAX6956/html/search/all_65.js         |    4 +
 Arduino/MAX6956/html/search/all_67.html       |   26 +
 Arduino/MAX6956/html/search/all_67.js         |   10 +
 Arduino/MAX6956/html/search/all_69.html       |   26 +
 Arduino/MAX6956/html/search/all_69.js         |    4 +
 Arduino/MAX6956/html/search/all_6d.html       |   26 +
 Arduino/MAX6956/html/search/all_6d.js         |  174 +
 Arduino/MAX6956/html/search/all_70.html       |   26 +
 Arduino/MAX6956/html/search/all_70.js         |   10 +
 Arduino/MAX6956/html/search/all_72.html       |   26 +
 Arduino/MAX6956/html/search/all_72.js         |    4 +
 Arduino/MAX6956/html/search/all_73.html       |   26 +
 Arduino/MAX6956/html/search/all_73.js         |   13 +
 Arduino/MAX6956/html/search/all_74.html       |   26 +
 Arduino/MAX6956/html/search/all_74.js         |    5 +
 Arduino/MAX6956/html/search/classes_6d.html   |   26 +
 Arduino/MAX6956/html/search/classes_6d.js     |    4 +
 Arduino/MAX6956/html/search/close.png         |  Bin 0 -> 273 bytes
 Arduino/MAX6956/html/search/defines_6d.html   |   26 +
 Arduino/MAX6956/html/search/defines_6d.js     |  171 +
 Arduino/MAX6956/html/search/files_6d.html     |   26 +
 Arduino/MAX6956/html/search/files_6d.js       |    5 +
 Arduino/MAX6956/html/search/functions_63.html |   26 +
 Arduino/MAX6956/html/search/functions_63.js   |    6 +
 Arduino/MAX6956/html/search/functions_64.html |   26 +
 Arduino/MAX6956/html/search/functions_64.js   |    4 +
 Arduino/MAX6956/html/search/functions_65.html |   26 +
 Arduino/MAX6956/html/search/functions_65.js   |    4 +
 Arduino/MAX6956/html/search/functions_67.html |   26 +
 Arduino/MAX6956/html/search/functions_67.js   |   10 +
 Arduino/MAX6956/html/search/functions_69.html |   26 +
 Arduino/MAX6956/html/search/functions_69.js   |    4 +
 Arduino/MAX6956/html/search/functions_6d.html |   26 +
 Arduino/MAX6956/html/search/functions_6d.js   |    4 +
 Arduino/MAX6956/html/search/functions_72.html |   26 +
 Arduino/MAX6956/html/search/functions_72.js   |    4 +
 Arduino/MAX6956/html/search/functions_73.html |   26 +
 Arduino/MAX6956/html/search/functions_73.js   |   13 +
 Arduino/MAX6956/html/search/functions_74.html |   26 +
 Arduino/MAX6956/html/search/functions_74.js   |    5 +
 Arduino/MAX6956/html/search/mag_sel.png       |  Bin 0 -> 563 bytes
 Arduino/MAX6956/html/search/nomatches.html    |   12 +
 Arduino/MAX6956/html/search/search.css        |  271 ++
 Arduino/MAX6956/html/search/search.js         |  805 +++++
 Arduino/MAX6956/html/search/search_l.png      |  Bin 0 -> 604 bytes
 Arduino/MAX6956/html/search/search_m.png      |  Bin 0 -> 158 bytes
 Arduino/MAX6956/html/search/search_r.png      |  Bin 0 -> 612 bytes
 Arduino/MAX6956/html/search/variables_62.html |   26 +
 Arduino/MAX6956/html/search/variables_62.js   |    4 +
 Arduino/MAX6956/html/search/variables_64.html |   26 +
 Arduino/MAX6956/html/search/variables_64.js   |    4 +
 Arduino/MAX6956/html/search/variables_70.html |   26 +
 Arduino/MAX6956/html/search/variables_70.js   |   10 +
 Arduino/MAX6956/html/sync_off.png             |  Bin 0 -> 853 bytes
 Arduino/MAX6956/html/sync_on.png              |  Bin 0 -> 845 bytes
 Arduino/MAX6956/html/tab_a.png                |  Bin 0 -> 142 bytes
 Arduino/MAX6956/html/tab_b.png                |  Bin 0 -> 169 bytes
 Arduino/MAX6956/html/tab_h.png                |  Bin 0 -> 177 bytes
 Arduino/MAX6956/html/tab_s.png                |  Bin 0 -> 184 bytes
 Arduino/MAX6956/html/tabs.css                 |   60 +
 Arduino/MAX6956/keywords.txt                  |   71 +
 Arduino/MAX6956/latex/MAX6956_8cpp.tex        |    4 +
 Arduino/MAX6956/latex/MAX6956_8h.tex          | 1937 ++++++++++
 Arduino/MAX6956/latex/Makefile                |   21 +
 Arduino/MAX6956/latex/annotated.tex           |    4 +
 Arduino/MAX6956/latex/classMAX6956.tex        |  825 +++++
 Arduino/MAX6956/latex/doxygen.sty             |  464 +++
 Arduino/MAX6956/latex/files.tex               |    5 +
 Arduino/MAX6956/latex/refman.tex              |  150 +
 123 files changed, 18065 insertions(+)
 create mode 100644 Arduino/MAX6956/Doxyfile
 create mode 100644 Arduino/MAX6956/Examples/MAX6956_LED_FADE/MAX6956_LED_Fade.ino
 create mode 100644 Arduino/MAX6956/MAX6956.cpp
 create mode 100644 Arduino/MAX6956/MAX6956.h
 create mode 100644 Arduino/MAX6956/comments.txt
 create mode 100644 Arduino/MAX6956/html/MAX6956_8cpp.html
 create mode 100644 Arduino/MAX6956/html/MAX6956_8cpp_source.html
 create mode 100644 Arduino/MAX6956/html/MAX6956_8h.html
 create mode 100644 Arduino/MAX6956/html/MAX6956_8h_source.html
 create mode 100644 Arduino/MAX6956/html/annotated.html
 create mode 100644 Arduino/MAX6956/html/bc_s.png
 create mode 100644 Arduino/MAX6956/html/bdwn.png
 create mode 100644 Arduino/MAX6956/html/classMAX6956.html
 create mode 100644 Arduino/MAX6956/html/classes.html
 create mode 100644 Arduino/MAX6956/html/closed.png
 create mode 100644 Arduino/MAX6956/html/doxygen.css
 create mode 100644 Arduino/MAX6956/html/doxygen.png
 create mode 100644 Arduino/MAX6956/html/dynsections.js
 create mode 100644 Arduino/MAX6956/html/files.html
 create mode 100644 Arduino/MAX6956/html/ftv2blank.png
 create mode 100644 Arduino/MAX6956/html/ftv2cl.png
 create mode 100644 Arduino/MAX6956/html/ftv2doc.png
 create mode 100644 Arduino/MAX6956/html/ftv2folderclosed.png
 create mode 100644 Arduino/MAX6956/html/ftv2folderopen.png
 create mode 100644 Arduino/MAX6956/html/ftv2lastnode.png
 create mode 100644 Arduino/MAX6956/html/ftv2link.png
 create mode 100644 Arduino/MAX6956/html/ftv2mlastnode.png
 create mode 100644 Arduino/MAX6956/html/ftv2mnode.png
 create mode 100644 Arduino/MAX6956/html/ftv2mo.png
 create mode 100644 Arduino/MAX6956/html/ftv2node.png
 create mode 100644 Arduino/MAX6956/html/ftv2ns.png
 create mode 100644 Arduino/MAX6956/html/ftv2plastnode.png
 create mode 100644 Arduino/MAX6956/html/ftv2pnode.png
 create mode 100644 Arduino/MAX6956/html/ftv2splitbar.png
 create mode 100644 Arduino/MAX6956/html/ftv2vertline.png
 create mode 100644 Arduino/MAX6956/html/functions.html
 create mode 100644 Arduino/MAX6956/html/functions_func.html
 create mode 100644 Arduino/MAX6956/html/functions_vars.html
 create mode 100644 Arduino/MAX6956/html/globals.html
 create mode 100644 Arduino/MAX6956/html/globals_defs.html
 create mode 100644 Arduino/MAX6956/html/index.html
 create mode 100755 Arduino/MAX6956/html/installdox
 create mode 100644 Arduino/MAX6956/html/jquery.js
 create mode 100644 Arduino/MAX6956/html/nav_f.png
 create mode 100644 Arduino/MAX6956/html/nav_g.png
 create mode 100644 Arduino/MAX6956/html/nav_h.png
 create mode 100644 Arduino/MAX6956/html/open.png
 create mode 100644 Arduino/MAX6956/html/search/all_62.html
 create mode 100644 Arduino/MAX6956/html/search/all_62.js
 create mode 100644 Arduino/MAX6956/html/search/all_63.html
 create mode 100644 Arduino/MAX6956/html/search/all_63.js
 create mode 100644 Arduino/MAX6956/html/search/all_64.html
 create mode 100644 Arduino/MAX6956/html/search/all_64.js
 create mode 100644 Arduino/MAX6956/html/search/all_65.html
 create mode 100644 Arduino/MAX6956/html/search/all_65.js
 create mode 100644 Arduino/MAX6956/html/search/all_67.html
 create mode 100644 Arduino/MAX6956/html/search/all_67.js
 create mode 100644 Arduino/MAX6956/html/search/all_69.html
 create mode 100644 Arduino/MAX6956/html/search/all_69.js
 create mode 100644 Arduino/MAX6956/html/search/all_6d.html
 create mode 100644 Arduino/MAX6956/html/search/all_6d.js
 create mode 100644 Arduino/MAX6956/html/search/all_70.html
 create mode 100644 Arduino/MAX6956/html/search/all_70.js
 create mode 100644 Arduino/MAX6956/html/search/all_72.html
 create mode 100644 Arduino/MAX6956/html/search/all_72.js
 create mode 100644 Arduino/MAX6956/html/search/all_73.html
 create mode 100644 Arduino/MAX6956/html/search/all_73.js
 create mode 100644 Arduino/MAX6956/html/search/all_74.html
 create mode 100644 Arduino/MAX6956/html/search/all_74.js
 create mode 100644 Arduino/MAX6956/html/search/classes_6d.html
 create mode 100644 Arduino/MAX6956/html/search/classes_6d.js
 create mode 100644 Arduino/MAX6956/html/search/close.png
 create mode 100644 Arduino/MAX6956/html/search/defines_6d.html
 create mode 100644 Arduino/MAX6956/html/search/defines_6d.js
 create mode 100644 Arduino/MAX6956/html/search/files_6d.html
 create mode 100644 Arduino/MAX6956/html/search/files_6d.js
 create mode 100644 Arduino/MAX6956/html/search/functions_63.html
 create mode 100644 Arduino/MAX6956/html/search/functions_63.js
 create mode 100644 Arduino/MAX6956/html/search/functions_64.html
 create mode 100644 Arduino/MAX6956/html/search/functions_64.js
 create mode 100644 Arduino/MAX6956/html/search/functions_65.html
 create mode 100644 Arduino/MAX6956/html/search/functions_65.js
 create mode 100644 Arduino/MAX6956/html/search/functions_67.html
 create mode 100644 Arduino/MAX6956/html/search/functions_67.js
 create mode 100644 Arduino/MAX6956/html/search/functions_69.html
 create mode 100644 Arduino/MAX6956/html/search/functions_69.js
 create mode 100644 Arduino/MAX6956/html/search/functions_6d.html
 create mode 100644 Arduino/MAX6956/html/search/functions_6d.js
 create mode 100644 Arduino/MAX6956/html/search/functions_72.html
 create mode 100644 Arduino/MAX6956/html/search/functions_72.js
 create mode 100644 Arduino/MAX6956/html/search/functions_73.html
 create mode 100644 Arduino/MAX6956/html/search/functions_73.js
 create mode 100644 Arduino/MAX6956/html/search/functions_74.html
 create mode 100644 Arduino/MAX6956/html/search/functions_74.js
 create mode 100644 Arduino/MAX6956/html/search/mag_sel.png
 create mode 100644 Arduino/MAX6956/html/search/nomatches.html
 create mode 100644 Arduino/MAX6956/html/search/search.css
 create mode 100644 Arduino/MAX6956/html/search/search.js
 create mode 100644 Arduino/MAX6956/html/search/search_l.png
 create mode 100644 Arduino/MAX6956/html/search/search_m.png
 create mode 100644 Arduino/MAX6956/html/search/search_r.png
 create mode 100644 Arduino/MAX6956/html/search/variables_62.html
 create mode 100644 Arduino/MAX6956/html/search/variables_62.js
 create mode 100644 Arduino/MAX6956/html/search/variables_64.html
 create mode 100644 Arduino/MAX6956/html/search/variables_64.js
 create mode 100644 Arduino/MAX6956/html/search/variables_70.html
 create mode 100644 Arduino/MAX6956/html/search/variables_70.js
 create mode 100644 Arduino/MAX6956/html/sync_off.png
 create mode 100644 Arduino/MAX6956/html/sync_on.png
 create mode 100644 Arduino/MAX6956/html/tab_a.png
 create mode 100644 Arduino/MAX6956/html/tab_b.png
 create mode 100644 Arduino/MAX6956/html/tab_h.png
 create mode 100644 Arduino/MAX6956/html/tab_s.png
 create mode 100644 Arduino/MAX6956/html/tabs.css
 create mode 100755 Arduino/MAX6956/keywords.txt
 create mode 100644 Arduino/MAX6956/latex/MAX6956_8cpp.tex
 create mode 100644 Arduino/MAX6956/latex/MAX6956_8h.tex
 create mode 100644 Arduino/MAX6956/latex/Makefile
 create mode 100644 Arduino/MAX6956/latex/annotated.tex
 create mode 100644 Arduino/MAX6956/latex/classMAX6956.tex
 create mode 100644 Arduino/MAX6956/latex/doxygen.sty
 create mode 100644 Arduino/MAX6956/latex/files.tex
 create mode 100644 Arduino/MAX6956/latex/refman.tex

diff --git a/Arduino/MAX6956/Doxyfile b/Arduino/MAX6956/Doxyfile
new file mode 100644
index 00000000..3dc611cf
--- /dev/null
+++ b/Arduino/MAX6956/Doxyfile
@@ -0,0 +1,1781 @@
+# Doxyfile 1.7.6.1
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a hash (#) is considered a comment and will be ignored.
+# The format is:
+#       TAG = value [value, ...]
+# For lists items can also be appended using:
+#       TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING      = UTF-8
+
+# The PROJECT_NAME tag is a single word (or sequence of words) that should
+# identify the project. Note that if you do not use Doxywizard you need
+# to put quotes around the project name if it contains spaces.
+
+PROJECT_NAME           = "MAX6956"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER         = 1.0
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer
+# a quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF          = MAX6956 i2C library
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is
+# included in the documentation. The maximum height of the logo should not
+# exceed 55 pixels and the maximum width should not exceed 200 pixels.
+# Doxygen will copy the logo to the output directory.
+
+PROJECT_LOGO           =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       =
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS         = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
+# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
+# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak,
+# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
+
+OUTPUT_LANGUAGE        = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF       =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES        = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH        =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH    =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful if your file system
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like regular Qt-style comments
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF      = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF           = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS           = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE               = 4
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES                =
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding
+# "class=itcl::class" will allow you to use the command class in the
+# itcl::class meaning.
+
+TCL_SUBST              =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C  = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for
+# Java. For instance, namespaces will be presented as packages, qualified
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources only. Doxygen will then generate output that is more tailored for
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN   = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL   = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given extension.
+# Doxygen has a built-in mapping, but you can override or extend it using this
+# tag. The format is ext=language, where ext is a file extension, and language
+# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C,
+# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make
+# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C
+# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions
+# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen.
+
+EXTENSION_MAPPING      =
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also makes the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT    = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT        = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
+# Doxygen will parse them like normal C++ but will assume all classes use public
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT            = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate getter
+# and setter methods for a property. Setting this option to YES (the default)
+# will make doxygen replace the get and set methods by a property in the
+# documentation. This will only work if the methods are indeed getting or
+# setting a simple type. If this is not the case, or you want to show the
+# methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT   = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING            = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and
+# unions are shown inside the group in which they are included (e.g. using
+# @ingroup) instead of on a separate page (for HTML and Man pages) or
+# section (for LaTeX and RTF).
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and
+# unions with only public data fields will be shown inline in the documentation
+# of the scope in which they are defined (i.e. file, namespace, or group
+# documentation), provided this scope is documented. If set to NO (the default),
+# structs, classes, and unions are shown on a separate page (for HTML and Man
+# pages) or section (for LaTeX and RTF).
+
+INLINE_SIMPLE_STRUCTS  = NO
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
+# is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically
+# be useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT   = NO
+
+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
+# determine which symbols to keep in memory and which to flush to disk.
+# When the cache is full, less often used symbols will be written to disk.
+# For small to medium size projects (<1000 input files) the default value is
+# probably good enough. For larger projects a too small cache size can cause
+# doxygen to be busy swapping symbols to and from disk most of the time
+# causing a significant performance penalty.
+# If the system has enough physical memory increasing the cache will improve the
+# performance by keeping more symbols in memory. Note that the value works on
+# a logarithmic scale so increasing the size by one will roughly double the
+# memory usage. The cache size is given by this formula:
+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols.
+
+SYMBOL_CACHE_SIZE      = 0
+
+# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be
+# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given
+# their name and scope. Since this can be an expensive process and often the
+# same symbol appear multiple times in the code, doxygen keeps a cache of
+# pre-resolved symbols. If the cache is too small doxygen will become slower.
+# If the cache is too large, memory is wasted. The cache size is given by this
+# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols.
+
+LOOKUP_CACHE_SIZE      = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL            = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE        = YES
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC         = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS  = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base
+# name of the file that contains the anonymous namespace. By default
+# anonymous namespaces are hidden.
+
+EXTRACT_ANON_NSPACES   = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES       = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen
+# will list include files with double quotes in the documentation
+# rather than with sharp brackets.
+
+FORCE_LOCAL_INCLUDES   = NO
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen
+# will sort the (brief and detailed) documentation of class members so that
+# constructors and destructors are listed first. If set to NO (the default)
+# the constructors will appear in the respective orders defined by
+# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS.
+# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO
+# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
+# hierarchy of group names into alphabetical order. If set to NO (the default)
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES       = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to
+# do proper type resolution of all parameters of a function it will reject a
+# match between the prototype and the implementation of a member function even
+# if there is only one candidate or it is obvious which candidate to choose
+# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen
+# will still accept a match between prototype and implementation in such cases.
+
+STRICT_PROTO_MATCHING  = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS       =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or macro consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and macros in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES        = YES
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES       = NO
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
+# This will remove the Files entry from the Quick Index and from the
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES             = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
+# Namespaces page.
+# This will remove the Namespaces entry from the Quick Index
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES        = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command  , where  is the value of
+# the FILE_VERSION_FILTER tag, and  is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER    =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. The create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option.
+# You can optionally specify a file name after the option, if omitted
+# DoxygenLayout.xml will be used as the name of the layout file.
+
+LAYOUT_FILE            =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files
+# containing the references data. This must be a list of .bib files. The
+# .bib extension is automatically appended if omitted. Using this command
+# requires the bibtex tool to be installed. See also
+# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style
+# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this
+# feature you need bibtex and perl available in the search path.
+
+CITE_BIB_FILES         =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS               = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR      = YES
+
+# The WARN_NO_PARAMDOC option can be enabled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC       = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE           = doxyerrors.log
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT                  =
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
+# also the default input encoding. Doxygen uses libiconv (or the iconv built
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
+# the list of possible encodings.
+
+INPUT_ENCODING         = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh
+# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py
+# *.f90 *.f *.for *.vhd *.vhdl
+
+FILE_PATTERNS          =
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE              = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE                =
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS       =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS        =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH           =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS       =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH             =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command  , where 
+# is the value of the INPUT_FILTER tag, and  is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.
+# If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER           =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis.
+# Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match.
+# The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty or if
+# non of the patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS        =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES    = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any)
+# and it is also possible to disable source filtering for a specific pattern
+# using *.ext= (so without naming a filter). This option only has effect when
+# FILTER_SOURCE_FILES is enabled.
+
+FILTER_SOURCE_PATTERNS =
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER         = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION    = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code.
+# Otherwise they will link to the documentation.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS       = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX     = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX          =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header. Note that when using a custom header you are responsible
+#  for the proper inclusion of any scripts and style sheets that doxygen
+# needs, which is dependent on the configuration options used.
+# It is advised to generate a default header using "doxygen -w html
+# header.html footer.html stylesheet.css YourConfigFile" and then modify
+# that header. Note that the header is subject to change so you typically
+# have to redo this when upgrading to a newer version of doxygen or when
+# changing the value of configuration settings such as GENERATE_TREEVIEW!
+
+HTML_HEADER            =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER            =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# style sheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET        =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that
+# the files will be copied as-is; there are no commands or markers available.
+
+HTML_EXTRA_FILES       =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
+# Doxygen will adjust the colors in the style sheet and background images
+# according to this color. Hue is specified as an angle on a colorwheel,
+# see http://en.wikipedia.org/wiki/Hue for more information.
+# For instance the value 0 represents red, 60 is yellow, 120 is green,
+# 180 is cyan, 240 is blue, 300 purple, and 360 is red again.
+# The allowed range is 0 to 359.
+
+HTML_COLORSTYLE_HUE    = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of
+# the colors in the HTML output. For a value of 0 the output will use
+# grayscales only. A value of 255 will produce the most vivid colors.
+
+HTML_COLORSTYLE_SAT    = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to
+# the luminance component of the colors in the HTML output. Values below
+# 100 gradually make the output lighter, whereas values above 100 make
+# the output darker. The value divided by 100 is the actual gamma applied,
+# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2,
+# and 100 does not change the gamma.
+
+HTML_COLORSTYLE_GAMMA  = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting
+# this to NO can help when comparing the output of multiple runs.
+
+HTML_TIMESTAMP         = YES
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS     = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded. For this to work a browser that supports
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS  = NO
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files
+# will be generated that can be used as input for Apple's Xcode 3
+# integrated development environment, introduced with OSX 10.5 (Leopard).
+# To create a documentation set, doxygen will generate a Makefile in the
+# HTML output directory. Running make will produce the docset in that
+# directory and running "make install" will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
+# it at startup.
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+
+GENERATE_DOCSET        = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
+# feed. A documentation feed provides an umbrella under which multiple
+# documentation sets from a single provider (such as a company or product suite)
+# can be grouped.
+
+DOCSET_FEEDNAME        = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
+# should uniquely identify the documentation set bundle. This should be a
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID       = org.doxygen.Project
+
+# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+
+DOCSET_PUBLISHER_ID    = org.doxygen.Publisher
+
+# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher.
+
+DOCSET_PUBLISHER_NAME  = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP      = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE               =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION           =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI           = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file
+# content.
+
+CHM_INDEX_ENCODING     =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND             = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated
+# that can be used as input for Qt's qhelpgenerator to generate a
+# Qt Compressed Help (.qch) of the generated HTML documentation.
+
+GENERATE_QHP           = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
+# be used to specify the file name of the resulting .qch file.
+# The path specified is relative to the HTML output folder.
+
+QCH_FILE               =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#namespace
+
+QHP_NAMESPACE          = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#virtual-folders
+
+QHP_VIRTUAL_FOLDER     = doc
+
+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to
+# add. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#custom-filters
+
+QHP_CUST_FILTER_NAME   =
+
+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see
+# 
+# Qt Help Project / Custom Filters.
+
+QHP_CUST_FILTER_ATTRS  =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's
+# filter section matches.
+# 
+# Qt Help Project / Filter Attributes.
+
+QHP_SECT_FILTER_ATTRS  =
+
+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
+# be used to specify the location of Qt's qhelpgenerator.
+# If non-empty doxygen will try to run qhelpgenerator on the generated
+# .qhp file.
+
+QHG_LOCATION           =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files
+#  will be generated, which together with the HTML files, form an Eclipse help
+# plugin. To install this plugin and make it available under the help contents
+# menu in Eclipse, the contents of the directory containing the HTML and XML
+# files needs to be copied into the plugins directory of eclipse. The name of
+# the directory within the plugins directory should be the same as
+# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before
+# the help appears.
+
+GENERATE_ECLIPSEHELP   = NO
+
+# A unique identifier for the eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have
+# this name.
+
+ECLIPSE_DOC_ID         = org.doxygen.Project
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs)
+# at top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it. Since the tabs have the same information as the
+# navigation tree you can set this option to NO if you already set
+# GENERATE_TREEVIEW to YES.
+
+DISABLE_INDEX          = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information.
+# If the tag value is set to YES, a side panel will be generated
+# containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
+# Windows users are probably better off using the HTML help feature.
+# Since the tree basically has the same information as the tab index you
+# could consider to set DISABLE_INDEX to NO when enabling this option.
+
+GENERATE_TREEVIEW      = NO
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values
+# (range [0,1..20]) that doxygen will group on one line in the generated HTML
+# documentation. Note that a value of 0 will completely suppress the enum
+# values from appearing in the overview section.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories,
+# and Class Hierarchy pages using a tree view instead of an ordered list.
+
+USE_INLINE_TREES       = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH         = 250
+
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open
+# links to external symbols imported via tag files in a separate window.
+
+EXT_LINKS_IN_WINDOW    = NO
+
+# Use this tag to change the font size of Latex formulas included
+# as images in the HTML documentation. The default is 10. Note that
+# when you change the font size after a successful doxygen run you need
+# to manually remove any form_*.png images from the HTML output directory
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE       = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are
+# not supported properly for IE 6.0, but are supported on all modern browsers.
+# Note that when changing this option you need to delete any form_*.png files
+# in the HTML output before the changes have effect.
+
+FORMULA_TRANSPARENT    = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax
+# (see http://www.mathjax.org) which uses client side Javascript for the
+# rendering instead of using prerendered bitmaps. Use this if you do not
+# have LaTeX installed or if you want to formulas look prettier in the HTML
+# output. When enabled you also need to install MathJax separately and
+# configure the path to it using the MATHJAX_RELPATH option.
+
+USE_MATHJAX            = NO
+
+# When MathJax is enabled you need to specify the location relative to the
+# HTML output directory using the MATHJAX_RELPATH option. The destination
+# directory should contain the MathJax.js script. For instance, if the mathjax
+# directory is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the
+# mathjax.org site, so you can quickly see the result without installing
+# MathJax, but it is strongly recommended to install a local copy of MathJax
+# before deployment.
+
+MATHJAX_RELPATH        = http://www.mathjax.org/mathjax
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension
+# names that should be enabled during MathJax rendering.
+
+MATHJAX_EXTENSIONS     =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box
+# for the HTML output. The underlying search engine uses javascript
+# and DHTML and should work on any modern browser. Note that when using
+# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets
+# (GENERATE_DOCSET) there is already a search function so this one should
+# typically be disabled. For large projects the javascript based search engine
+# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
+
+SEARCHENGINE           = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a PHP enabled web server instead of at the web client
+# using Javascript. Doxygen will generate the search PHP script and index
+# file to put on the web server. The advantage of the server
+# based approach is that it scales better to large projects and allows
+# full text search. The disadvantages are that it is more difficult to setup
+# and does not have live searching capabilities.
+
+SERVER_BASED_SEARCH    = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX         = YES
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+# Note that when enabling USE_PDFLATEX this option is only used for
+# generating bitmaps for formulas in the HTML output, but not in the
+# Makefile that is written to the output directory.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE             = a4
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES         =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER           =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for
+# the generated latex document. The footer should contain everything after
+# the last chapter. If it is left blank doxygen will generate a
+# standard footer. Notice: only use this tag if you know what you are doing!
+
+LATEX_FOOTER           =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS         = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX           = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE        = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES     = NO
+
+# If LATEX_SOURCE_CODE is set to YES then doxygen will include
+# source code with syntax highlighting in the LaTeX output.
+# Note that which sources are shown also depends on other settings
+# such as SOURCE_BROWSER.
+
+LATEX_SOURCE_CODE      = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See
+# http://en.wikipedia.org/wiki/BibTeX for more info.
+
+LATEX_BIB_STYLE        = plain
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS         = NO
+
+# Load style sheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE    =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE    =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION          = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT             = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA             =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD                =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader.
+# This is useful
+# if you want to understand what is going on.
+# On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# pointed to by INCLUDE_PATH will be searched when a #include is found.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH           =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS  =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED             =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition that
+# overrules the definition found in the source code.
+
+EXPAND_AS_DEFINED      =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all references to function-like macros
+# that are alone on a line, have an all uppercase name, and do not end with a
+# semicolon, because these will confuse the parser if not removed.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+#
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+#
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES               =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE       =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS        = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option also works with HAVE_DOT disabled, but it is recommended to
+# install and use dot, since it yields more powerful graphs.
+
+CLASS_DIAGRAMS         = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH            =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT               = NO
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is
+# allowed to run in parallel. When set to 0 (the default) doxygen will
+# base this on the number of processors available in the system. You can set it
+# explicitly to a value larger than 0 to get control over the balance
+# between CPU load and processing speed.
+
+DOT_NUM_THREADS        = 0
+
+# By default doxygen will use the Helvetica font for all dot files that
+# doxygen generates. When you want a differently looking font you can specify
+# the font name using DOT_FONTNAME. You need to make sure dot is able to find
+# the font, which can be done by putting it in a standard location or by setting
+# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the
+# directory containing the font.
+
+DOT_FONTNAME           = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
+# The default size is 10pt.
+
+DOT_FONTSIZE           = 10
+
+# By default doxygen will tell dot to use the Helvetica font.
+# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to
+# set the path where dot can find it.
+
+DOT_FONTPATH           =
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK               = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH          = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then
+# doxygen will generate a call dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable call graphs
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH             = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
+# doxygen will generate a caller dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable caller
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH           = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will generate a graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are svg, png, jpg, or gif.
+# If left blank png will be used. If you choose svg you need to set
+# HTML_FILE_EXTENSION to xhtml in order to make the SVG files
+# visible in IE 9+ (other browsers do not have this requirement).
+
+DOT_IMAGE_FORMAT       = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+# Note that this requires a modern browser other than Internet Explorer.
+# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you
+# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files
+# visible. Older versions of IE do not have SVG support.
+
+INTERACTIVE_SVG        = NO
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH               =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS           =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the
+# \mscfile command).
+
+MSCFILE_DIRS           =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the
+# number of direct children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES    = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not
+# seem to support this out of the box. Warning: Depending on the platform used,
+# enabling this option may lead to badly anti-aliased labels on the edges of
+# a graph (i.e. they become hard to read).
+
+DOT_TRANSPARENT        = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS      = YES
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP            = YES
diff --git a/Arduino/MAX6956/Examples/MAX6956_LED_FADE/MAX6956_LED_Fade.ino b/Arduino/MAX6956/Examples/MAX6956_LED_FADE/MAX6956_LED_Fade.ino
new file mode 100644
index 00000000..3f0c5afc
--- /dev/null
+++ b/Arduino/MAX6956/Examples/MAX6956_LED_FADE/MAX6956_LED_Fade.ino
@@ -0,0 +1,61 @@
+
+#include "I2Cdev.h"
+#include "MAX6956.h"
+
+int led = 13;
+int globalCurrent = 15; // 15-0, 15 the max
+
+MAX6956 ledDriver;
+
+void setup()
+{ 
+  // initialize the digital pin as an output.
+  pinMode(led, OUTPUT);     
+  
+  // initialize serial communication
+  Serial.begin(9600);
+
+  // initialize device
+  Serial.println("Initializing I2C devices...");
+  ledDriver.initialize();
+
+  // verify connection
+  Serial.println("Testing device connections...");
+  if (ledDriver.testConnection()) {
+    Serial.println("Connection successful");
+  } else { 
+    Serial.println("Connection failed");
+    while (true) {
+        delay(1000);
+    }
+  }
+  
+  ledDriver.setGlobalCurrent(globalCurrent);
+  ledDriver.configAllPorts(MAX6956_OUTPUT_LED); // Set all ports as led drivers
+  ledDriver.enableAllPorts(); // Enable all ports
+  ledDriver.setTestMode(true);
+  delay(1000); // wait
+  ledDriver.setTestMode(false);
+  delay(1000); // wait
+  ledDriver.setPower(true);
+}
+
+
+void loop()
+{
+  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
+  // Ramp brightness down
+  for (int x = 15; x >= 0; x--) { 
+      ledDriver.setGlobalCurrent(globalCurrent); // Set global current
+      globalCurrent = x;
+      delay(80); 
+  }
+  
+  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
+  // Ramp brightness up
+  for (int x = 0; x <= 15; x++) { 
+      ledDriver.setGlobalCurrent(globalCurrent); // Set global current
+      globalCurrent = x;
+      delay(80);
+  }
+}
diff --git a/Arduino/MAX6956/MAX6956.cpp b/Arduino/MAX6956/MAX6956.cpp
new file mode 100644
index 00000000..1fd21159
--- /dev/null
+++ b/Arduino/MAX6956/MAX6956.cpp
@@ -0,0 +1,573 @@
+// I2Cdev library collection - MAX6956 I2C device class
+// Based on Maxim MAX6956 datasheet 19-2414; Rev 4; 6/10
+//
+// 2013-12-15 by Tom Beighley 
+// I2C Device Library hosted at http://www.i2cdevlib.com
+//
+// Changelog:
+//     2013-12-15 - initial release
+//
+
+/* ============================================
+I2Cdev device library code is placed under the MIT license
+Copyright (c) 2013 Tom Beighley
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+===============================================
+*/
+
+#include "MAX6956.h"
+
+/** Default constructor, uses default I2C address.
+ * @see MAX6956_DEFAULT_ADDRESS
+ */
+MAX6956::MAX6956() {
+    devAddr = MAX6956_DEFAULT_ADDRESS;
+}
+
+/** Specific address constructor.
+ * @param address I2C address
+ * @see MAX6956_DEFAULT_ADDRESS
+ * @see MAX6956_ADDRESS
+ */
+MAX6956::MAX6956(uint8_t address) {
+    devAddr = address;
+}
+
+/** Power on and prepare for general usage. */
+void MAX6956::initialize() {
+    // Need this in setup() or here.
+    // Fastwire::setup(400, false);
+    reset();
+    
+    /** The 28-pin MAX6956ANI and MAX6956AAI make only 20 ports available, P12 to P31.
+    The eight unused ports should be configured as outputs on power-up by writing 0x55 to registers 0x09 and 0x0A. 
+    If this is not done,the eight unused ports remain as unconnected inputs and quiescent supply current rises, 
+    although there is no damage to the part.
+    */
+    I2Cdev::writeByte(devAddr, MAX6956_RA_CONFIG_P7P6P5P4, 0x55);
+    I2Cdev::writeByte(devAddr, MAX6956_RA_CONFIG_P11P10P9P8, 0x55);
+}
+
+/** Verify the I2C connection.
+ * Make sure the device is connected and responds as expected.
+ * @return True if connection is valid, false otherwise
+ */
+bool MAX6956::testConnection() {
+    if (I2Cdev::readByte(devAddr, MAX6956_RA_CONFIGURATION, buffer) == 1) {
+        return true;
+    }
+    return false;
+}
+
+/** Set registers back to Power-up Configuration */
+void MAX6956::reset() {
+    disableAllPorts(); // set Port RA 0x2C-0x3F to 0
+    setGlobalCurrent(0x00);  // Set global current to minimum on
+    setConfigReg(0x00); // Shutdown Enabled,Current Control = Global, Transition Detection Disabled 
+    setInputMask(0x00); // Set Input register mask to 0
+    setTestMode(false); // disable test mode
+    configAllPorts(MAX6956_INPUT_WO_PULL); // Configure all inputs as MAX6956_INPUT_WO_PULL
+    setAllPortsCurrent(0x00); // Set current RA 0x16-01F to 0
+}
+
+/** Config register
+@return uint8_t value of register
+@see MAX6956_RA_CONFIGURATION
+*/
+uint8_t MAX6956::getConfigReg() {
+    I2Cdev::readByte(devAddr, MAX6956_RA_CONFIGURATION, buffer);
+    return buffer[0];
+}
+/**	Set config register
+@param config uint8_t value to set register
+@see MAX6956_RA_CONFIGURATION
+*/
+void MAX6956::setConfigReg(uint8_t config) {
+    I2Cdev::writeByte(devAddr, MAX6956_RA_CONFIGURATION, config);
+}
+
+/**	Get power configuration bit 
+@return Boolean value if power is enabled or not
+@see MAX6956_RA_CONFIGURATION
+*/
+bool MAX6956::getPower() {
+    I2Cdev::readBit(devAddr, MAX6956_RA_CONFIGURATION, MAX6956_CONFIG_POWER_BIT, buffer);
+    return buffer[0];
+}
+/**	Enable or disable power
+@param power Boolean value, true enables, false disables power
+@see MAX6956_RA_CONFIGURATION
+*/
+void MAX6956::setPower(bool power) {
+    I2Cdev::writeBit(devAddr, MAX6956_RA_CONFIGURATION, MAX6956_CONFIG_POWER_BIT, power);
+}
+/**	Toggle power
+@see MAX6956_RA_CONFIGURATION
+*/
+void MAX6956::togglePower() {
+    I2Cdev::readBit(devAddr, MAX6956_RA_CONFIGURATION, MAX6956_CONFIG_POWER_BIT, buffer);
+    buffer[0] = !(buffer[0]);
+    I2Cdev::writeBit(devAddr, MAX6956_RA_CONFIGURATION, MAX6956_CONFIG_POWER_BIT, buffer[0]);
+}
+
+/**	Get transition detection configuration bit 
+@return Boolean value if global current is enabled or not
+@see MAX6956_RA_CONFIGURATION
+*/
+bool MAX6956::getEnableIndividualCurrent() {
+    I2Cdev::readBit(devAddr, MAX6956_RA_CONFIGURATION, MAX6956_CONFIG_GLOBAL_CURRENT_BIT, buffer);
+    return buffer[0];
+}
+/**	Enable or disable global current
+@param global Boolean value, true enables, false disables individual current
+@see MAX6956_RA_CONFIGURATION
+@see getGlobalCurrent()
+@see setGlobalCurrent()
+*/
+void MAX6956::setEnableIndividualCurrent(bool global) {
+    I2Cdev::writeBit(devAddr, MAX6956_RA_CONFIGURATION, MAX6956_CONFIG_GLOBAL_CURRENT_BIT, global);
+}
+
+/**	Get transition detection configuration bit 
+@return Boolean value if transition detection is enabled or not
+@see MAX6956_RA_CONFIGURATION
+*/
+bool MAX6956::getEnableTransitionDetection() {
+    I2Cdev::readBit(devAddr, MAX6956_RA_CONFIGURATION, MAX6956_CONFIG_TRANSITION_BIT, buffer);
+    return buffer[0];
+}
+/**	Enable or disable transition detection. Must be reset after every mask read.
+@param transition Boolean value, true enables, false disables transition detection
+@see MAX6956_RA_CONFIGURATION
+@see getInputMask()
+@see setInputMask()
+*/
+void MAX6956::setEnableTransitionDetection(bool transition) {
+    I2Cdev::writeBit(devAddr, MAX6956_RA_CONFIGURATION, MAX6956_CONFIG_TRANSITION_BIT, transition);
+}
+
+// Global Current
+/**	Get global current 
+@return uint8_t value of register
+@see MAX6956_RA_GLOBAL_CURRENT
+*/
+uint8_t MAX6956::getGlobalCurrent() {
+    I2Cdev::readBits(devAddr, MAX6956_RA_GLOBAL_CURRENT, MAX6956_GLOBAL_CURRENT_BIT, MAX6956_GLOBAL_CURRENT_LENGTH, buffer);
+    return buffer[0];
+}
+/**	Set current globally
+@param current uint8_t 0-15, 0 = min, 15 = max brightness
+@see MAX6956_RA_GLOBAL_CURRENT
+*/
+void MAX6956::setGlobalCurrent(uint8_t current) {
+    I2Cdev::writeByte(devAddr, MAX6956_RA_GLOBAL_CURRENT, current);
+}
+
+// Test mode
+/**	Returns true if test mode is enabled. 
+@return uint8_t value of register
+@see MAX6956_RA_DISPLAY_TEST
+*/
+bool MAX6956::getTestMode() {
+    I2Cdev::readBit(devAddr, MAX6956_RA_DISPLAY_TEST, MAX6956_DISPLAY_TEST_BIT, buffer);
+    return buffer[0];
+}
+/**	Enable or disable test mode
+@param test Boolean, true enables, false disables
+@see MAX6956_RA_DISPLAY_TEST
+*/
+void MAX6956::setTestMode(bool test) {
+    I2Cdev::writeByte(devAddr, MAX6956_RA_DISPLAY_TEST, test);
+}
+
+// Input mask register
+/**	Get the input mask to see which ports have changed. MSB is cleared after every read.
+@return uint8_t value of register
+@see MAX6956_RA_TRANSITION_DETECT
+*/
+uint8_t MAX6956::getInputMask() {
+    I2Cdev::readByte(devAddr, MAX6956_RA_TRANSITION_DETECT, buffer);
+    return buffer[0];
+}
+
+/**	Set the input mask for which ports to monitor with transition detection
+@param mask 8 bit value. MSB is ignored.
+@see MAX6956_RA_TRANSITION_DETECT
+*/
+void MAX6956::setInputMask(uint8_t mask) {
+    I2Cdev::writeByte(devAddr, MAX6956_RA_TRANSITION_DETECT, mask);
+}
+
+
+/**	Takes an INDIVIDUAL port register address (MAX6956_RA_PORT12, ect)
+	and configures it as: MAX6956_OUTPUT_LED, MAX6956_OUTPUT_GPIO,
+    MAX6956_INPUT_WO_PULL, or MAX6956_INPUT_W_PULL
+
+Port registers
+--------------    
+
+Addr. | Name
+:----:|:------------------------------:
+0x09  | MAX6956_RA_CONFIG_P7P6P5P4				
+0x0A  | MAX6956_RA_CONFIG_P11P10P9P8			
+0x0B  | MAX6956_RA_CONFIG_P15P14P13P12			
+0x0C  | MAX6956_RA_CONFIG_P19P18P17P16			
+0x0D  | MAX6956_RA_CONFIG_P23P22P21P20			
+0x0E  | MAX6956_RA_CONFIG_P27P26P25P24			
+0x0F  | MAX6956_RA_CONFIG_P31P30P29P28			
+
+Num|Dec|Hex |Prt|Port Status Array|Ports Config Array
+:-:|:-:|:--:|:-:|:---------------:|:-----------------:
+00 |44 |0x2C|P12|portsStatus[0][0]|portsConfig[0][1-0]     
+01 |45 |0x2D|P13|portsStatus[0][1]|portsConfig[0][3-2]        
+02 |46 |0x2E|P14|portsStatus[0][2]|portsConfig[0][5-4]
+03 |47 |0x2F|P15|portsStatus[0][3]|portsConfig[0][7-6]
+04 |48 |0x30|P16|portsStatus[0][4]|portsConfig[1][1-0]
+05 |49 |0x31|P17|portsStatus[0][5]|portsConfig[1][3-2]
+06 |50 |0x32|P18|portsStatus[0][6]|portsConfig[1][5-4]
+07 |51 |0x33|P19|portsStatus[0][7]|portsConfig[1][7-6]
+08 |52 |0x34|P20|portsStatus[1][0]|portsConfig[2][1-0]                         
+09 |53 |0x35|P21|portsStatus[1][1]|portsConfig[2][3-2]
+10 |54 |0x36|P22|portsStatus[1][2]|portsConfig[2][5-4]
+11 |55 |0x37|P23|portsStatus[1][3]|portsConfig[2][7-6]                
+12 |56 |0x38|P24|portsStatus[1][4]|portsConfig[3][1-0]
+13 |57 |0x39|P25|portsStatus[1][5]|portsConfig[3][3-2]
+14 |58 |0x3A|P26|portsStatus[1][6]|portsConfig[3][5-4]
+15 |59 |0x3B|P27|portsStatus[1][7]|portsConfig[3][7-6]
+16 |60 |0x3C|P28|portsStatus[2][0]|portsConfig[4][1-0]    
+17 |61 |0x3D|P29|portsStatus[2][1]|portsConfig[4][3-2]
+18 |62 |0x3E|P30|portsStatus[2][2]|portsConfig[4][5-4]
+19 |63 |0x3F|P31|portsStatus[2][3]|portsConfig[4][7-6]
+ 
+ @param port Port register address (MAX6956_RA_PORT12, ect)
+ @param portConfig Valid options are: MAX6956_OUTPUT_LED, MAX6956_OUTPUT_GPIO, MAX6956_INPUT_WO_PULL, MAX6956_INPUT_W_PULL
+ @see MAX6956_RA_PORT12 MAX6956_RA_PORT13 MAX6956_RA_PORT14 MAX6956_RA_PORT15 MAX6956_RA_PORT16 MAX6956_RA_PORT17 MAX6956_RA_PORT18 MAX6956_RA_PORT19 MAX6956_RA_PORT20 MAX6956_RA_PORT21
+      MAX6956_RA_PORT22 MAX6956_RA_PORT23 MAX6956_RA_PORT24 MAX6956_RA_PORT25 MAX6956_RA_PORT26 MAX6956_RA_PORT27 MAX6956_RA_PORT28 MAX6956_RA_PORT29 MAX6956_RA_PORT30 MAX6956_RA_PORT31
+ @see MAX6956_OUTPUT_LED MAX6956_OUTPUT_GPIO MAX6956_INPUT_WO_PULL MAX6956_INPUT_W_PULL
+*/
+void MAX6956::configPort(uint8_t port, uint8_t portConfig) {
+    uint8_t bitPosition = (((port - 44) % 4) * 2) + 1; // bit position to start flipping 
+    uint8_t pcArrayIndex = (port - 44) / 4; // array index
+    uint8_t portConfigRA = pcArrayIndex + 11; // port config register
+	I2Cdev::writeBits(devAddr, portConfigRA, bitPosition, 2, portConfig);
+    // Update portConfig array
+    bitPosition--; // Remove 1 bit offset
+    portsConfig[pcArrayIndex] &=  ~(3 << bitPosition);
+    portsConfig[pcArrayIndex] |=  portConfig << bitPosition;   
+}
+
+/** Configure consecutive range of ports
+ * @param lower Lower port register address (MAX6956_RA_PORT12, ect)
+ * @param upper Upper port register address (MAX6956_RA_PORT12, ect)
+ * @param portConfig Valid options are: MAX6956_OUTPUT_LED, MAX6956_OUTPUT_GPIO, MAX6956_INPUT_WO_PULL, MAX6956_INPUT_W_PULL
+ * @see MAX6956_OUTPUT_LED
+ * @see MAX6956_OUTPUT_GPIO
+ * @see MAX6956_INPUT_WO_PULL
+ * @see MAX6956_INPUT_W_PULL
+*/
+void MAX6956::configPorts(uint8_t lower, uint8_t upper, uint8_t portConfig) {
+
+    #ifdef MAX6956_SERIAL_DEBUG
+        Serial.print("lower ");
+        Serial.print(lower, HEX);
+        Serial.print(" upper ");
+        Serial.print(upper, HEX);
+        Serial.print(" portConfig ");
+        Serial.println(portConfig, BIN);
+    #endif
+    
+    uint8_t bitPosition = 0;
+    uint8_t pcArrayIndex = 0;
+    uint8_t portConfigRA = 0;
+    uint8_t i = lower;
+    
+    while ( i <= upper ) { 
+        bitPosition = (((i - 44) % 4) * 2) + 1; // bit position to start flipping 
+        pcArrayIndex = (i - 44) / 4; // array index
+        portConfigRA = pcArrayIndex + 11; // port config register
+        
+        #ifdef MAX6956_SERIAL_DEBUG
+            Serial.print("i ");
+            Serial.print(i);
+            Serial.print(" bitPosition ");
+            Serial.print(bitPosition);
+            Serial.print(" pcArrayIndex");
+            Serial.print(pcArrayIndex);
+            Serial.print(" portConfigRA ");
+            Serial.println(portConfigRA, HEX);
+        #endif
+        
+        I2Cdev::writeBits(devAddr, portConfigRA, bitPosition, 2, portConfig);
+        
+        #ifdef MAX6956_SERIAL_DEBUG
+            Serial.print("portsConfig ");
+            Serial.print(portsConfig[pcArrayIndex], BIN);
+        #endif
+        
+        // Update portConfig array
+        bitPosition--; // Remove 1 bit offset
+        portsConfig[pcArrayIndex] &=  ~(3 << bitPosition); //3 == B00000011 Shift over correct number of bits then invert to create the mask
+        portsConfig[pcArrayIndex] |=  portConfig << bitPosition; 
+        
+        #ifdef MAX6956_SERIAL_DEBUG
+            Serial.print(" >> ");
+            Serial.println(portsConfig[pcArrayIndex], BIN);
+        #endif
+        
+        i++;
+    }
+  
+}
+
+/**	Configure all ports the same
+ @param portConfig Valid options are: MAX6956_OUTPUT_LED, MAX6956_OUTPUT_GPIO, MAX6956_INPUT_WO_PULL, MAX6956_INPUT_W_PULL
+ @see MAX6956_OUTPUT_LED
+ @see MAX6956_OUTPUT_GPIO
+ @see MAX6956_INPUT_WO_PULL
+ @see MAX6956_INPUT_W_PULL
+*/
+void MAX6956::configAllPorts(uint8_t portConfig) {
+    // build byte with config bits shifted to all 4 slots
+    portConfig = portConfig << 6 + portConfig << 4 + portConfig << 2 + portConfig;
+    // copy byte to portsConfig array slots
+    memset (portsConfig, portConfig, 5);
+    // write bytes all at once to device
+    I2Cdev::writeBytes(devAddr, MAX6956_RA_CONFIG_P15P14P13P12, 5, portsConfig);
+}
+
+/** Write 1's to all port registers. This enables ports set as outputs and 
+*   they will always have some brightness, port must be disabled to 
+*   turn off completely. */
+void MAX6956::enableAllPorts() {
+    // set portStatus array to all 1's
+    memset (portsStatus, 0xFF, 3);
+    // write bytes
+    I2Cdev::writeByte(devAddr, MAX6956_RA_PORTS12_19, portsStatus[0]);
+    I2Cdev::writeByte(devAddr, MAX6956_RA_PORTS20_27, portsStatus[1]);
+    I2Cdev::writeByte(devAddr, MAX6956_RA_PORTS28_31, portsStatus[2]);
+}
+
+/** Write 0's to all port registers. */
+void MAX6956::disableAllPorts() {
+    // set portStatus array to all 0's
+    memset (portsStatus, 0x00, 3);
+    // write bytes
+    I2Cdev::writeByte(devAddr, MAX6956_RA_PORTS12_19, portsStatus[0]);
+    I2Cdev::writeByte(devAddr, MAX6956_RA_PORTS20_27, portsStatus[1]);
+    I2Cdev::writeByte(devAddr, MAX6956_RA_PORTS28_31, portsStatus[2]);
+}
+
+      
+/** Enables/Disables any port.set as a LED driver 
+*/
+void MAX6956::toggleLEDs() {
+  // Toggle power on all pins set as LED drivers
+  for (int i = 0; i < sizeof(portsConfig); i++){
+    uint8_t portRA = 0;
+    uint8_t bitPosition = 0;
+    uint8_t psArrayIndex = 0;
+    for (int j = 3; j >= 0; j--){
+      if (((portsConfig[i] >> (j * 2)) & B00000011) == 0) {
+        portRA = j+(i*4);
+        bitPosition = portRA % 8; // bit position to flip 
+        psArrayIndex = portRA / 8; // array index
+        portRA += 44; // Finally adjust portRA for actual offset.
+        if (portsStatus[psArrayIndex] & (1 << bitPosition )) {
+        setPort(portRA, false);
+        } else {
+        setPort(portRA, true);
+        }
+      }
+    }
+  }
+}      
+      
+/** Enables/Disables indiviual port. 
+ @param port Port register address (MAX6956_RA_PORT12, ect)
+ @param enabled true or false
+ @see MAX6956_RA_PORT12 MAX6956_RA_PORT13 MAX6956_RA_PORT14 MAX6956_RA_PORT15 MAX6956_RA_PORT16 MAX6956_RA_PORT17 MAX6956_RA_PORT18 MAX6956_RA_PORT19 MAX6956_RA_PORT20 MAX6956_RA_PORT21
+      MAX6956_RA_PORT22 MAX6956_RA_PORT23 MAX6956_RA_PORT24 MAX6956_RA_PORT25 MAX6956_RA_PORT26 MAX6956_RA_PORT27 MAX6956_RA_PORT28 MAX6956_RA_PORT29 MAX6956_RA_PORT30 MAX6956_RA_PORT31
+*/
+void MAX6956::setPort(uint8_t port, bool enabled) {
+    if ( port >= 44 && port <= 63) { 
+        I2Cdev::writeByte(devAddr, port, enabled);
+        
+        #ifdef MAX6956_SERIAL_DEBUG
+            Serial.print("port ");
+            Serial.print(port, HEX);
+            Serial.print(" is ");
+            Serial.println(enabled);
+        #endif
+        
+        // Update portConfig array
+        uint8_t bitPosition = (port - 44) % 8; // bit position to flip 
+        uint8_t psArrayIndex = (port - 44) / 8; // array index
+        portsStatus[psArrayIndex] &=  ~(1 << bitPosition);
+        portsStatus[psArrayIndex] |=  enabled << bitPosition;
+    }
+}
+
+/**	Takes an individual port register address (MAX6956_RA_PORT12, ect)
+	and returns the value of the port (data bit D0; D7–D1 read as 0) .
+	Returns 129 for out of bounds requests.
+ * @return data bit D0; D7–D1 read as 0. D7 set to 1 on out of bounds.
+ * @param port Port register address (MAX6956_RA_PORT12, ect)
+*/
+uint8_t MAX6956::getPort(uint8_t port) {
+    if ( port >= 44 && port <= 63) { 
+        I2Cdev::readByte(devAddr, port, buffer); // read port
+        
+        #ifdef MAX6956_SERIAL_DEBUG
+            Serial.print("port ");
+            Serial.print(port);
+            Serial.print(" is ");
+            Serial.println(buffer[0]);
+        #endif
+        
+        return buffer[0];
+	} else 
+	    return 129;
+}
+
+/**	Reads the value of the transition detection ports (24-30) all at once.
+ * @return uint8_t value of ports
+*/
+uint8_t MAX6956::getTransitionPorts() {
+    I2Cdev::readByte(devAddr, 0x58, buffer); // read ports
+
+    #ifdef MAX6956_SERIAL_DEBUG
+        Serial.print("Transition ports: ");
+        Serial.println(buffer[0], BIN);
+    #endif
+    
+    return buffer[0];
+}
+
+/**	Takes an individual port register address (MAX6956_RA_PORT12, ect)
+	and sets it to a power scale where 0 = off. 
+ * @param port Port register address (MAX6956_RA_PORT12, ect)
+ * @param power 0 is off, 15 is max brightness.
+*/
+void MAX6956::setPortLevel(uint8_t port, uint8_t power) {
+  if ( port >= 44 && port <= 63 && power >= 0 && power <= 15 ) { 
+    //power = sqrt(2) * power; // Convert linear to log scale
+  
+    psArrayIndex = (port - 44) / 8; // array index
+    psBitPosition = (port - 44) % 8; // bit position to flip 
+  
+    if ( power > 0 ) { 
+      // When not at 100% power decrement power by one because 0 is 
+      // really an "on" power level and the lower levels are more important.
+      if ( power < 15 ) power--;
+      
+      // Calculate current register from port address
+      // set current bit offset
+      if ( port % 2 ) { //port is odd
+        portCurrentRA = (port - 1) / 2;
+        portCurrentBit = 7;
+      } 
+            else {
+        portCurrentRA = port / 2;
+        portCurrentBit = 3;
+      }
+      
+      // Write changes
+      I2Cdev::writeBits(devAddr, portCurrentRA, portCurrentBit, 4, power); // Write changes
+      I2Cdev::writeByte(devAddr, port, MAX6956_ON); // turn on port
+  
+      #ifdef MAX6956_SERIAL_DEBUG
+          Serial.print("port ");
+          Serial.print(port);
+          Serial.print(" portCurrentBit ");
+          Serial.print(portCurrentBit);
+          Serial.print(" portCurrentRA ");
+          Serial.print(portCurrentRA, HEX);
+          Serial.print(" power ");
+          Serial.println(power	);
+      #endif
+      
+      // Update portStatus array
+      portsStatus[psArrayIndex] |=  1 << psBitPosition;   
+    
+    } else {
+      I2Cdev::writeByte(devAddr, port, MAX6956_OFF); // turn off port
+      portsStatus[psArrayIndex] &=  ~(1 << psBitPosition);   // Update portStatus array
+  
+      #ifdef MAX6956_SERIAL_DEBUG
+          Serial.print("port ");
+          Serial.print(port);
+          Serial.println(" is off");
+      #endif
+    }
+	} 
+}
+
+
+/**	Takes an INDIVIDUAL port register address (MAX6956_RA_PORT12, ect)
+	and sets it to a power level 0-15. 0 is min, 15 is max brightness. 
+ * @param port Port register address (MAX6956_RA_PORT12, ect)
+ * @param power 0 is min, 15 is max brightness.
+*/
+void MAX6956::setPortCurrent(uint8_t port, uint8_t power) {
+    if ( port >= 44 && port <= 63 && power >= 0 && power <= 15 ) { 
+		//power = sqrt(2) * power; /** TODO Convert linear to log scale */
+
+	    psArrayIndex = (port - 44) / 8; // array index
+        psBitPosition = (port - 44) % 8; // bit position to flip 
+
+        // Calculate current register from port address
+        // set current bit offset
+        if ( port % 2 ) { //port is odd
+            portCurrentRA = (port - 1) / 2;
+            portCurrentBit = 7;
+        } 
+        else {
+            portCurrentRA = port / 2;
+            portCurrentBit = 3;
+        }
+        
+        // Write changes
+        I2Cdev::writeBits(devAddr, portCurrentRA, portCurrentBit, 4, power); // Write changes
+        I2Cdev::writeByte(devAddr, port, MAX6956_ON); // turn on port
+
+        #ifdef MAX6956_SERIAL_DEBUG
+            Serial.print("port ");
+            Serial.print(port);
+            Serial.print(" portCurrentBit ");
+            Serial.print(portCurrentBit);
+            Serial.print(" portCurrentRA ");
+            Serial.print(portCurrentRA, HEX);
+            Serial.print(" power ");
+            Serial.println(power	);
+        #endif
+        // Update portStatus array
+        portsStatus[psArrayIndex] |=  1 << psBitPosition;   
+	} 
+}
+
+/**	Set ALL port current registers (MAX6956_RA_PORT12, ect) to 
+    the SAME power level 0-15. 0 min brightness, 15 is max brightness.
+    @param power 0 is min, 15 is max brightness.
+*/
+void MAX6956::setAllPortsCurrent(uint8_t power) {
+   for (int portCurrentRA=MAX6956_RA_CURRENT_0xP13P12; portCurrentRA <= MAX6956_RA_CURRENT_0xP31P30; portCurrentRA++){
+    I2Cdev::writeByte(devAddr, portCurrentRA, power);
+   } 
+}
diff --git a/Arduino/MAX6956/MAX6956.h b/Arduino/MAX6956/MAX6956.h
new file mode 100644
index 00000000..0beaa366
--- /dev/null
+++ b/Arduino/MAX6956/MAX6956.h
@@ -0,0 +1,573 @@
+// I2Cdev library collection - MAX6956 I2C device class header file
+// Based on Maxim MAX6956 datasheet 19-2414; Rev 4; 6/10
+//
+// 2013-12-15 by Tom Beighley 
+// I2C Device Library hosted at http://www.i2cdevlib.com
+//
+// Changelog:
+//     2013-12-15 - initial release
+//
+
+/* ============================================
+I2Cdev device library code is placed under the MIT license
+Copyright (c) 2013 Tom Beighley
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+===============================================
+*/
+
+
+/*! \mainpage Maxim Integrated Products
+
+The MAX6956 compact, serial-interfaced LED display driver/I/O expander provide microprocessors with up to 28 ports. Each port is individually user configurable to either a logic input, logic output, or common-anode (CA) LED constant-current segment driver. Each port configured as an LED segment driver behaves as a digitally controlled constant-current sink, with 16 equal current steps from 1.5mA to 24mA. The LED drivers are suitable for both discrete LEDs and CA numeric and alphanumeric LED digits.
+
+Each port configured as a general-purpose I/O (GPIO) can be either a push-pull logic output capable of sink- ing 10mA and sourcing 4.5mA, or a Schmitt logic input with optional internal pullup. Seven ports feature config- urable transition detection logic, which generates an interrupt upon change of port logic level. The MAX6956 is controlled through an I2C-compatible 2-wire serial interface, and uses four-level logic to allow 16 I 2C addresses from only 2 select pins.
+
+The MAX6956AAX and MAX6956ATL have 28 ports and are available in 36-pin SSOP and 40-pin thin QFN packages, respectively. The MAX6956AAI and MAX6956ANI have 20 ports and are available in 28-pin SSOP and 28-pin DIP packages, respectively.
+
+For an SPI-interfaced version, refer to the MAX6957 data sheet. For a lower cost pin-compatible port expander without the constant-current LED drive capa- bility, refer to the MAX7300 data sheet.
+
+- 400kbps I2C-Compatible Serial Interface
+- 2.5V to 5.5V Operation
+- -40°C to +125°C Temperature Range
+- 20 or 28 I/O Ports, Each Configurable as
+ - Constant-Current LED Driver
+ - Push-Pull Logic Output
+ - Schmitt Logic Input
+ - Schmitt Logic Input with Internal Pullup
+- 11μA (max) Shutdown Current
+- 16-Step Individually Programmable Current
+- Control for Each LED
+- Logic Transition Detection for Seven I/O Ports
+
+*/
+
+#ifndef _MAX6956_H_
+#define _MAX6956_H_
+
+#include "I2Cdev.h"
+
+// -----------------------------------------------------------------------------
+// Arduino-style "Serial.print" debug constant (uncomment to enable)
+// -----------------------------------------------------------------------------
+// #define MAX6956_SERIAL_DEBUG
+
+/**
+Table 3. I2C Address Map
+========================
+
+Pin|Pin|DEVICE ADDRESS                 |
+:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:--:   
+AD1|AD0|A7 |A6 |A5 |A4 |A3 |A2 |A1 |A0 |HEX
+GND|GND|1  |0  |0  |0  |0  |0  |0  |RW |0x40
+GND|V+ |1  |0  |0  |0  |0  |0  |1  |RW |0x41
+GND|SDA|1  |0  |0  |0  |0  |1  |0  |RW |0x42
+GND|SCL|1  |0  |0  |0  |0  |1  |1  |RW |0x43
+V+ |GND|1  |0  |0  |0  |1  |0  |0  |RW |0x44
+V+ |V+ |1  |0  |0  |0  |1  |0  |1  |RW |0x45
+V+ |SDA|1  |0  |0  |0  |1  |1  |0  |RW |0x46
+V+ |SCL|1  |0  |0  |0  |1  |1  |1  |RW |0x47
+SDA|GND|1  |0  |0  |1  |0  |0  |0  |RW |0x48
+SDA|V+ |1  |0  |0  |1  |0  |0  |1  |RW |0x49
+SDA|SDA|1  |0  |0  |1  |0  |1  |0  |RW |0x50
+SDA|SCL|1  |0  |0  |1  |0  |1  |1  |RW |0x51
+SCL|GND|1  |0  |0  |1  |1  |0  |0  |RW |0x52
+SCL|V+ |1  |0  |0  |1  |1  |0  |1  |RW |0x53
+SCL|SDA|1  |0  |0  |1  |1  |1  |0  |RW |0x54
+SCL|SCL|1  |0  |0  |1  |1  |1  |1  |RW |0x55
+                           
+RW bit 0 = Write 1 = Read
+*/
+#define MAX6956_ADDRESS					0x40 // See table 3 
+#define MAX6956_DEFAULT_ADDRESS			0x40 // AD0 and AD1 at ground.
+
+//==========Registers==========
+
+#define MAX6956_RA_NO_OP				0x00 ///< No-op
+
+/**
+Table 11. Global Segment Current Register Format
+================================================
+
+LED DRIVE |TYPICAL SEGMENT | ADDRESS    |
+FRACTION  |  CURRENT(mA)   |CODE (HEX)  |D7 |D6 |D5 |D4 |D3 |D2 |D1 |D0 |HEX CODE
+:--------:|:--------------:|:----------:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:------:
+1/16      |     1.5        |   0x02     |x  |x  |x  |x  |0  |0  |0  |0  |0xX0
+2/16      |      3         |   0x02     |x  |x  |x  |x  |0  |0  |0  |1  |0xX1
+3/16      |     4.5        |   0x02     |x  |x  |x  |x  |0  |0  |1  |0  |0xX2
+4/16      |      6         |   0x02     |x  |x  |x  |x  |0  |0  |1  |1  |0xX3
+5/16      |     7.5        |   0x02     |x  |x  |x  |x  |0  |1  |0  |0  |0xX4
+6/16      |      9         |   0x02     |x  |x  |x  |x  |0  |1  |0  |1  |0xX5
+7/16      |    10.5        |   0x02     |x  |x  |x  |x  |0  |1  |1  |0  |0xX6
+8/16      |     12         |   0x02     |x  |x  |x  |x  |0  |1  |1  |1  |0xX7
+9/16      |    13.5        |   0x02     |x  |x  |x  |x  |1  |0  |0  |0  |0xX8
+10/16     |     15         |   0x02     |x  |x  |x  |x  |1  |0  |0  |1  |0xX9
+11/16     |    16.5        |   0x02     |x  |x  |x  |x  |1  |0  |1  |0  |0xXA
+12/16     |     18         |   0x02     |x  |x  |x  |x  |1  |0  |1  |1  |0xXB
+13/16     |    19.5        |   0x02     |x  |x  |x  |x  |1  |1  |0  |0  |0xXC
+14/16     |     21         |   0x02     |x  |x  |x  |x  |1  |1  |0  |1  |0xXD
+15/16     |    22.5        |   0x02     |x  |x  |x  |x  |1  |1  |1  |0  |0xXE
+16/16     |     24         |   0x02     |x  |x  |x  |x  |1  |1  |1  |1  |0xXF
+*/                                                      
+#define MAX6956_RA_GLOBAL_CURRENT		0x02
+
+/**
+Table 7. Configuration Register Format
+======================================
+
+ADDRESS |D7 |D6 |D5 |D4 |D3 |D2 |D1 |D0
+:------:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:
+0x04    |M  |I  |x  |x  |x  |x  |x  |S
+
+Table 8. Shutdown Control (S Data Bit D0) Format
+================================================
+
+FUNCTION        |ADDRESS|D7 |D6 |D5 |D4 |D3 |D2 |D1 |D0
+:--------------:|:-----:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:
+Shutdown        |0x04   |M  |I  |x  |x  |x  |x  |x  |0
+Normal Operation|0x04   |M  |I  |x  |x  |x  |x  |x  |1
+
+Table 9. Global Current Control (I Data Bit D6) Format
+======================================================
+
+FUNCTION          |ADDRESS|D7 |D6 |D5 |D4 |D3 |D2 |D1 |D0
+:----------------:|:-----:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:
+Global            |0x04   |M  |0  |x  |x  |x  |x  |x  |S
+Individual Segment|0x04   |M  |1  |x  |x  |x  |x  |x  |S 
+
+Table 10. Transition Detection Control (M-Data Bit D7) Format
+=============================================================
+
+FUNCTION  |ADDRESS|D7 |D6 |D5 |D4 |D3 |D2 |D1 |D0
+:--------:|:-----:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:
+Disabled  | 0x04  |0  |I  |x  |x  |x  |x  |x  |S
+Enabled   | 0x04  |1  |I  |x  |x  |x  |x  |x  |S
+
+*/
+#define MAX6956_RA_CONFIGURATION		0x04
+
+/**
+Table 15. Transition Detection Mask Register
+============================================
+
+|FUNCTION       |REGISTER ADDRESS |READ/WRITE | D7         |D6  |D5  |D4  |D3  |D2  |D1  |D0  |
+|---------------|-----------------|-----------|------------|----|----|----|----|----|----|----|
+|Mask Register  | 0x06            | Read      | INT Status*|Port|Port|Port|Port|Port|Port|Port|
+|               |                 |           |            |30  |29  |28  |27  |26  |25  |24  |
+|               |                 |Write      | Unchanged  |mask|mask|mask|mask|mask|mask|mask|
+
+*INT is automatically cleared after it is read.
+
+*/
+#define MAX6956_RA_TRANSITION_DETECT	0x06
+
+/**
+Table 16. Display Test Register
+===============================
+
+                 |ADDR |
+MODE             |CODE |D7 |D6 |D5 |D4 |D3 |D2 |D1 |D0
+:-------------  :|:---:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:
+Normal Operation |0x07 |x  |x  |x  |x  |x  |x  |x  |0
+Display Test Mode|0x07 |x  |x  |x  |x  |x  |x  |x  |1
+
+*/
+#define MAX6956_RA_DISPLAY_TEST			0x07
+
+/**
+Table 1. Port Configuration Map
+===============================
+
+REGISTER                                 |ADDRESS|D7 D6|D5 D4|D3 D2|D1 D0
+-----------------------------------------|-------|-----|-----|-----|-----
+Port Configuration for P7, P6, P5, P4    |  0x09 |  P7 |  P6 |  P5 |  P4
+Port Configuration for P11, P10, P9, P8  |  0x0A | P11 | P10 |  P9 |  P8
+Port Configuration for P15, P14, P13, P12|  0x0B | P15 | P14 | P13 | P12
+Port Configuration for P19, P18, P17, P16|  0x0C | P19 | P18 | P17 | P16
+Port Configuration for P23, P22, P21, P20|  0x0D | P23 | P22 | P21 | P20
+Port Configuration for P27, P26, P25, P24|  0x0E | P27 | P26 | P25 | P24
+Port Configuration for P31, P30, P29, P28|  0x0F | P31 | P30 | P29 | P28
+
+Table 2. P4-P31 configuration bit pairs
+=======================================
+
+
+    00 - Output, LED Segment Driver
+             Controlled  using port registers 0x20-0x5F. 
+             0 = High impedance
+             1 = Open-drain current sink, with sink current (up to 24mA) 
+                 determined by the appropriate current register
+    01 - Output, GPIO Output
+             Controlled  using port registers 0x20-0x5F. 
+             0 = Active-low logic output
+             1 = Active-high logic output
+    10 - Input, GPIO Input Without Pullup
+             Read port registers 0x20-0x5F.
+             Schmitt logic input 
+    11 - Input, GPIO Input with Pullup
+             Read port registers 0x20-0x5F.
+             Schmitt logic input with pullup
+
+ +*/ +#define MAX6956_RA_CONFIG_P7P6P5P4 0x09 +#define MAX6956_RA_CONFIG_P11P10P9P8 0x0A +#define MAX6956_RA_CONFIG_P15P14P13P12 0x0B +#define MAX6956_RA_CONFIG_P19P18P17P16 0x0C +#define MAX6956_RA_CONFIG_P23P22P21P20 0x0D +#define MAX6956_RA_CONFIG_P27P26P25P24 0x0E +#define MAX6956_RA_CONFIG_P31P30P29P28 0x0F + +/** +Constant-current limit for each digit is +individually controlled by the settings in the +Current054 through Current1FE registers + +Table 12. Individual Port Current Registers +=========================================== + + | ADDRESS | | +FUNCTION |CODE(HEX)|D7 D6 D5 D4 | D3 D2 D1 D0 +--------------------|---------|------------|-------------- +Current054 register | 0x12 | Segment 5 | Segment 4 +Current076 register | 0x13 | Segment 7 | Segment 6 +Current098 register | 0x14 | Segment 9 | Segment 8 +Current0BA register | 0x15 | Segment 11 | Segment 10 +Current0DC register | 0x16 | Segment 13 | Segment 12 +Current0FE register | 0x17 | Segment 15 | Segment 14 +Current110 register | 0x18 | Segment 17 | Segment 16 +Current132 register | 0x19 | Segment 19 | Segment 18 +Current154 register | 0x1A | Segment 21 | Segment 20 +Current176 register | 0x1B | Segment 23 | Segment 22 +Current198 register | 0x1C | Segment 25 | Segment 24 +Current1BA register | 0x1D | Segment 27 | Segment 26 +Current1DC register | 0x1E | Segment 29 | Segment 28 +Current1FE register | 0x1F | Segment 31 | Segment 30 + +Register data is 0-Fx0-F for 1-16(0-F) brightness levels. +To completely blank an output turn it off (0) using port +configuration registers. +*/ +#define MAX6956_RA_CURRENT_0xP5P4 0x12 +#define MAX6956_RA_CURRENT_0xP7P6 0x13 +#define MAX6956_RA_CURRENT_0xP9P8 0x14 +#define MAX6956_RA_CURRENT_0xP11P10 0x15 +#define MAX6956_RA_CURRENT_0xP13P12 0x16 +#define MAX6956_RA_CURRENT_0xP15P14 0x17 +#define MAX6956_RA_CURRENT_0xP17P16 0x18 +#define MAX6956_RA_CURRENT_0xP19P18 0x19 +#define MAX6956_RA_CURRENT_0xP21P20 0x1A +#define MAX6956_RA_CURRENT_0xP23P22 0x1B +#define MAX6956_RA_CURRENT_0xP25P24 0x1C +#define MAX6956_RA_CURRENT_0xP27P26 0x1D +#define MAX6956_RA_CURRENT_0xP29P28 0x1E +#define MAX6956_RA_CURRENT_0xP31P30 0x1F + +/** +Individiual Port Registers +========================== + + data bit D0; D7-D1 read as 0 +*/ +#define MAX6956_RA_PORT0 0x20 ///< (virtual port, no action) +#define MAX6956_RA_PORT1 0x21 ///< (virtual port, no action) +#define MAX6956_RA_PORT2 0x22 ///< (virtual port, no action) +#define MAX6956_RA_PORT3 0x23 ///< (virtual port, no action) + +#define MAX6956_RA_PORT4 0x24 +#define MAX6956_RA_PORT5 0x25 +#define MAX6956_RA_PORT6 0x26 +#define MAX6956_RA_PORT7 0x27 +#define MAX6956_RA_PORT8 0x28 +#define MAX6956_RA_PORT9 0x29 +#define MAX6956_RA_PORT10 0x2A +#define MAX6956_RA_PORT11 0x2B + +#define MAX6956_RA_PORT12 0x2C +#define MAX6956_RA_PORT13 0x2D +#define MAX6956_RA_PORT14 0x2E +#define MAX6956_RA_PORT15 0x2F +#define MAX6956_RA_PORT16 0x30 +#define MAX6956_RA_PORT17 0x31 +#define MAX6956_RA_PORT18 0x32 +#define MAX6956_RA_PORT19 0x33 + +#define MAX6956_RA_PORT20 0x34 +#define MAX6956_RA_PORT21 0x35 +#define MAX6956_RA_PORT22 0x36 +#define MAX6956_RA_PORT23 0x37 +#define MAX6956_RA_PORT24 0x38 +#define MAX6956_RA_PORT25 0x39 +#define MAX6956_RA_PORT26 0x3A +#define MAX6956_RA_PORT27 0x3B + +#define MAX6956_RA_PORT28 0x3C +#define MAX6956_RA_PORT29 0x3D +#define MAX6956_RA_PORT30 0x3E +#define MAX6956_RA_PORT31 0x3F +/* + Lower port groups +*/ +#define MAX6956_RA_PORTS4_7 0x40 ///< data bits D0-D3; D4-D7 read as 0 +#define MAX6956_RA_PORTS4_8 0x41 ///< data bits D0-D4; D5-D7 read as 0 +#define MAX6956_RA_PORTS4_9 0x42 ///< data bits D0-D5; D6-D7 read as 0 +#define MAX6956_RA_PORTS4_10 0x43 ///< data bits D0-D6; D7 reads as 0 + +/* + 8 port registers. Data bits D0-D7 +*/ +#define MAX6956_RA_PORTS4_11 0x44 +#define MAX6956_RA_PORTS5_12 0x45 +#define MAX6956_RA_PORTS6_13 0x46 +#define MAX6956_RA_PORTS7_14 0x47 +#define MAX6956_RA_PORTS8_15 0x48 +#define MAX6956_RA_PORTS9_16 0x49 +#define MAX6956_RA_PORTS10_17 0x4A +#define MAX6956_RA_PORTS11_18 0x4B +#define MAX6956_RA_PORTS12_19 0x4C +#define MAX6956_RA_PORTS13_20 0x4D +#define MAX6956_RA_PORTS14_21 0x4E +#define MAX6956_RA_PORTS15_22 0x4F +#define MAX6956_RA_PORTS16_23 0x50 +#define MAX6956_RA_PORTS17_24 0x51 +#define MAX6956_RA_PORTS18_25 0x52 +#define MAX6956_RA_PORTS19_26 0x53 +#define MAX6956_RA_PORTS20_27 0x54 +#define MAX6956_RA_PORTS21_28 0x55 +#define MAX6956_RA_PORTS22_29 0x56 +#define MAX6956_RA_PORTS23_30 0x57 +#define MAX6956_RA_PORTS24_31 0x58 +/* + Upper port groups +*/ +#define MAX6956_RA_PORTS25_31 0x59 ///< data bits D0-D6; D7 reads as 0 +#define MAX6956_RA_PORTS26_31 0x5A ///< data bits D0-D5; D6-D7 read as 0 +#define MAX6956_RA_PORTS27_31 0x5B ///< data bits D0-D4; D5-D7 read as 0 +#define MAX6956_RA_PORTS28_31 0x5C ///< data bits D0-D3; D4-D7 read as 0 +#define MAX6956_RA_PORTS29_31 0x5D ///< data bits D0-D2; D3-D7 read as 0 +#define MAX6956_RA_PORTS30_31 0x5E ///< data bits D0-D1; D2-D7 read as 0 +#define MAX6956_RA_PORTS31_31 0x5F ///< data bit D0; D1-D7 read as 0. Port 31 only. + +//=========Config bits========= + +#define MAX6956_CONFIG_POWER_BIT 0 ///< 0 = Shutdown, 1 = Normal operation +#define MAX6956_CONFIG_GLOBAL_CURRENT_BIT 6 ///< 0 = Global control, 1 = Individual control +#define MAX6956_CONFIG_TRANSITION_BIT 7 ///< 0 = Disabled, 1 = Enabled + +#define MAX6956_GLOBAL_CURRENT_BIT 0 ///< Global current start bit +#define MAX6956_GLOBAL_CURRENT_LENGTH 4 ///< nybble long + +#define MAX6956_PORT12_CURRENT_BIT 3 ///< LSNybble +#define MAX6956_PORT12_CURRENT_LENGTH 4 ///< nybble long +#define MAX6956_PORT13_CURRENT_BIT 7 ///< MSNybble +#define MAX6956_PORT13_CURRENT_LENGTH 4 ///< nybble long +#define MAX6956_PORT14_CURRENT_BIT 3 ///< LSNybble +#define MAX6956_PORT14_CURRENT_LENGTH 4 ///< nybble long +#define MAX6956_PORT15_CURRENT_BIT 7 ///< MSNybble +#define MAX6956_PORT15_CURRENT_LENGTH 4 ///< nybble long +#define MAX6956_PORT16_CURRENT_BIT 3 ///< LSNybble +#define MAX6956_PORT16_CURRENT_LENGTH 4 ///< nybble long +#define MAX6956_PORT17_CURRENT_BIT 7 ///< MSNybble +#define MAX6956_PORT17_CURRENT_LENGTH 4 ///< nybble long +#define MAX6956_PORT18_CURRENT_BIT 3 ///< LSNybble +#define MAX6956_PORT18_CURRENT_LENGTH 4 ///< nybble long +#define MAX6956_PORT19_CURRENT_BIT 7 ///< MSNybble +#define MAX6956_PORT19_CURRENT_LENGTH 4 ///< nybble long +#define MAX6956_PORT23_CURRENT_BIT 3 ///< LSNybble +#define MAX6956_PORT23_CURRENT_LENGTH 4 ///< nybble long +#define MAX6956_PORT21_CURRENT_BIT 7 ///< MSNybble +#define MAX6956_PORT21_CURRENT_LENGTH 4 ///< nybble long +#define MAX6956_PORT22_CURRENT_BIT 3 ///< LSNybble +#define MAX6956_PORT22_CURRENT_LENGTH 4 ///< nybble long +#define MAX6956_PORT23_CURRENT_BIT 7 ///< MSNybble +#define MAX6956_PORT23_CURRENT_LENGTH 4 ///< nybble long +#define MAX6956_PORT24_CURRENT_BIT 3 ///< LSNybble +#define MAX6956_PORT24_CURRENT_LENGTH 4 ///< nybble long +#define MAX6956_PORT25_CURRENT_BIT 7 ///< MSNybble +#define MAX6956_PORT25_CURRENT_LENGTH 4 ///< nybble long +#define MAX6956_PORT26_CURRENT_BIT 3 ///< LSNybble +#define MAX6956_PORT26_CURRENT_LENGTH 4 ///< nybble long +#define MAX6956_PORT27_CURRENT_BIT 7 ///< MSNybble +#define MAX6956_PORT27_CURRENT_LENGTH 4 ///< nybble long +#define MAX6956_PORT28_CURRENT_BIT 3 ///< LSNybble +#define MAX6956_PORT28_CURRENT_LENGTH 4 ///< nybble long +#define MAX6956_PORT29_CURRENT_BIT 7 ///< MSNybble +#define MAX6956_PORT29_CURRENT_LENGTH 4 ///< nybble long +#define MAX6956_PORT33_CURRENT_BIT 3 ///< LSNybble +#define MAX6956_PORT33_CURRENT_LENGTH 4 ///< nybble long +#define MAX6956_PORT31_CURRENT_BIT 7 ///< MSNybble +#define MAX6956_PORT31_CURRENT_LENGTH 4 ///< nybble long + +#define MAX6956_DISPLAY_TEST_BIT 0 ///< 0 = Normal operation, 1 = Display test + +#define MAX6956_TRANSITION_STATUS_BIT 7 ///< INT Status, INT is automatically cleared after it is read. +#define MAX6956_TRANSITION_MASK_BIT 0 ///< Ports 24-30 +#define MAX6956_TRANSITION_MASK_LENGTH 7 +#define MAX6956_TRANSITION_MASK_PORT30_BIT 6 +#define MAX6956_TRANSITION_MASK_PORT29_BIT 5 +#define MAX6956_TRANSITION_MASK_PORT28_BIT 4 +#define MAX6956_TRANSITION_MASK_PORT27_BIT 3 +#define MAX6956_TRANSITION_MASK_PORT26_BIT 2 +#define MAX6956_TRANSITION_MASK_PORT25_BIT 1 +#define MAX6956_TRANSITION_MASK_PORT24_BIT 0 + +//=========Values========= + +#define MAX6956_OUTPUT_LED 0x00 +#define MAX6956_OUTPUT_GPIO 0x01 +#define MAX6956_INPUT_WO_PULL 0x02 +#define MAX6956_INPUT_W_PULL 0x03 + +#define MAX6956_OFF 0x00 +#define MAX6956_ON 0x01 + +#define MAX6956_CURRENT_0 0x00 +#define MAX6956_CURRENT_1 0x01 +#define MAX6956_CURRENT_2 0x02 +#define MAX6956_CURRENT_3 0x03 +#define MAX6956_CURRENT_4 0x04 +#define MAX6956_CURRENT_5 0x05 +#define MAX6956_CURRENT_6 0x06 +#define MAX6956_CURRENT_7 0x07 +#define MAX6956_CURRENT_8 0x08 +#define MAX6956_CURRENT_9 0x09 +#define MAX6956_CURRENT_10 0x0A +#define MAX6956_CURRENT_11 0x0B +#define MAX6956_CURRENT_12 0x0C +#define MAX6956_CURRENT_13 0x0D +#define MAX6956_CURRENT_14 0x0E +#define MAX6956_CURRENT_15 0x0F + +/*! +A library for controlling the MAX6956 using i2C. +*/ +class MAX6956 { + public: + MAX6956(); + MAX6956(uint8_t address); + + void initialize(); + bool testConnection(); + + void reset(); + + // Config register + uint8_t getConfigReg(); + void setConfigReg(uint8_t config); + + bool getPower(); + void togglePower(); + void setPower(bool power); + + bool getEnableIndividualCurrent(); + void setEnableIndividualCurrent(bool global); + + bool getEnableTransitionDetection(); + void setEnableTransitionDetection(bool transition); + + // Global current + uint8_t getGlobalCurrent(); + void setGlobalCurrent(uint8_t current); + + // Test mode + bool getTestMode(); + void setTestMode(bool test); + + // Input mask + uint8_t getInputMask(); + void setInputMask(uint8_t mask); + + // Port config + void configPort(uint8_t port, uint8_t portConfig); + void configPorts(uint8_t lower, uint8_t upper, uint8_t portConfig); + void configAllPorts(uint8_t portConfig); + + void enableAllPorts(); + void disableAllPorts(); + void toggleLEDs(); + void setPort(uint8_t port, bool enabled); ///< enabled = true, disabled = false + uint8_t getPort(uint8_t port); ///< Value of port, 0 or 1 + uint8_t getTransitionPorts(); ///< Reads the value of the transition detection ports (24-30) all at once. + + void setPortLevel(uint8_t port, uint8_t power); ///< 0 = off, 1-15 brightness levels. + void setPortCurrent(uint8_t port, uint8_t power); ///< 0-15 brightness levels. + void setAllPortsCurrent(uint8_t power); ///< 0-15, 0 = min brightness (not off) 15 = max + + /** + Array that mirrors the configuration of all the ports. + + P12 = portsConfig[0][1-0] + P13 = portsConfig[0][3-2] + P14 = portsConfig[0][5-4] + P15 = portsConfig[0][7-6] + P16 = portsConfig[1][1-0] + P17 = portsConfig[1][3-2] + P18 = portsConfig[1][5-4] + P19 = portsConfig[1][7-6] + P20 = portsConfig[2][1-0] + P21 = portsConfig[2][3-2] + P22 = portsConfig[2][5-4] + P23 = portsConfig[2][7-6] + P24 = portsConfig[3][1-0] + P25 = portsConfig[3][3-2] + P26 = portsConfig[3][5-4] + P27 = portsConfig[3][7-6] + P28 = portsConfig[4][1-0] + P29 = portsConfig[4][3-2] + P30 = portsConfig[4][5-4] + P31 = portsConfig[4][7-6] + */ + uint8_t portsConfig[5]; + /** + Array that mirrors the on/off status of all the ports. + + P12 = portsStatus[0][0] + P13 = portsStatus[0][1] + P14 = portsStatus[0][2] + P15 = portsStatus[0][3] + P16 = portsStatus[0][4] + P17 = portsStatus[0][5] + P18 = portsStatus[0][6] + P19 = portsStatus[0][7] + P20 = portsStatus[1][0] + P21 = portsStatus[1][1] + P22 = portsStatus[1][2] + P23 = portsStatus[1][3] + P24 = portsStatus[1][4] + P25 = portsStatus[1][5] + P26 = portsStatus[1][6] + P27 = portsStatus[1][7] + P28 = portsStatus[2][0] + P29 = portsStatus[2][1] + P30 = portsStatus[2][2] + P31 = portsStatus[2][3] + */ + uint8_t portsStatus[3]; + + private: + uint8_t devAddr; ///< Holds the current device address + uint8_t buffer[1]; ///< Buffer for reading data from the device + uint8_t portConfig; ///< Holder for port config bit pair + uint8_t portCurrentRA; ///< Holder for port current register + uint8_t portCurrentBit; ///< Holder for the current bit offset + uint8_t psArrayIndex; ///< array index + uint8_t psBitPosition; ///< bit position +}; + +#endif /* _MAX6956_H_ */ diff --git a/Arduino/MAX6956/comments.txt b/Arduino/MAX6956/comments.txt new file mode 100644 index 00000000..3a9e0526 --- /dev/null +++ b/Arduino/MAX6956/comments.txt @@ -0,0 +1,64 @@ +/** + +void MAX6956::configPort(uint8_t port, uint8_t portConfig) example math + + 0x0B 11 MAX6956_RA_CONFIG_P15P14P13P12 + 0x0C 12 MAX6956_RA_CONFIG_P19P18P17P16 + 0x0D 13 MAX6956_RA_CONFIG_P23P22P21P20 + 0x0E 14 MAX6956_RA_CONFIG_P27P26P25P24 + 0x0F 15 MAX6956_RA_CONFIG_P31P30P29P28 + + (56, 2) port 24, input without pullup + bitPosition = (((56 - 44) % 4) * 2) + 1 + ((12 % 4) * 2) + 1 + ( 0 * 2 ) + 1 + 0 + 1 + 1 + + pcArrayIndex = ((56 - 44) / 4) + (12 / 4) + 3 (any remainder is dropped when stored as an int ... I think) + + portConfigRA = pcArrayIndex + 11 + 14 + + bitPosition = 0 + mask = 0000 0011 + 0000 0011 << 0 + 0000 0011 + ~1111 1100 + 0011 1111 & portsConfig[x] + + portConfig = 0000 0010 << 0 + 0000 0010 + + xxxx xx00 | 0000 0010 + xxxx xx10 + + (63, 2) port 31, input without pullup + bitPosition = (((63 - 44) % 4) * 2) + 1 + ((19 % 4) * 2) + 1 + ( 3 * 2 ) + 1 + 6 + 1 + 7 + + pcArrayIndex = ((63 - 44) / 4) + (19 / 4) + 4.75 (any remainder is dropped when stored as an int ... I think) + + portConfigRA = pcArrayIndex + 11 + 15 + + bitPosition = 07 + mask = 0000 0011 + 0000 0011 << 6 + 1100 0000 + ~0011 1111 + 0011 1111 & portsConfig[x] + + portConfig = 0000 0010 << 6 + 1000 0000 + + 00xx xxxx | 1000 0000 + 10xx xxxx +*/ diff --git a/Arduino/MAX6956/html/MAX6956_8cpp.html b/Arduino/MAX6956/html/MAX6956_8cpp.html new file mode 100644 index 00000000..e5d937a0 --- /dev/null +++ b/Arduino/MAX6956/html/MAX6956_8cpp.html @@ -0,0 +1,99 @@ + + + + + + +MAX6956: MAX6956.cpp File Reference + + + + + + + + + +
+
+ + + + + + +
+
MAX6956 +  1.0 +
+
MAX6956i2Clibrary
+
+
+ + + + + + + + + +
+ +
+ +
+
+
+
MAX6956.cpp File Reference
+
+ + + + + diff --git a/Arduino/MAX6956/html/MAX6956_8cpp_source.html b/Arduino/MAX6956/html/MAX6956_8cpp_source.html new file mode 100644 index 00000000..cc2f649b --- /dev/null +++ b/Arduino/MAX6956/html/MAX6956_8cpp_source.html @@ -0,0 +1,463 @@ + + + + + + +MAX6956: MAX6956.cpp Source File + + + + + + + + + +
+
+ + + + + + +
+
MAX6956 +  1.0 +
+
MAX6956i2Clibrary
+
+
+ + + + + +
+ + + + +
+ +
+ +
+
+
MAX6956.cpp
+
+
+Go to the documentation of this file.
1 // I2Cdev library collection - MAX6956 I2C device class
+
2 // Based on Maxim MAX6956 datasheet 19-2414; Rev 4; 6/10
+
3 //
+
4 // 2013-12-15 by Tom Beighley <tomthegeek@gmail.com>
+
5 // I2C Device Library hosted at http://www.i2cdevlib.com
+
6 //
+
7 // Changelog:
+
8 // 2013-12-15 - initial release
+
9 //
+
10 
+
11 /* ============================================
+
12 I2Cdev device library code is placed under the MIT license
+
13 Copyright (c) 2013 Tom Beighley
+
14 
+
15 Permission is hereby granted, free of charge, to any person obtaining a copy
+
16 of this software and associated documentation files (the "Software"), to deal
+
17 in the Software without restriction, including without limitation the rights
+
18 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+
19 copies of the Software, and to permit persons to whom the Software is
+
20 furnished to do so, subject to the following conditions:
+
21 
+
22 The above copyright notice and this permission notice shall be included in
+
23 all copies or substantial portions of the Software.
+
24 
+
25 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+
26 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+
27 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+
28 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+
29 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+
30 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+
31 THE SOFTWARE.
+
32 ===============================================
+
33 */
+
34 
+
35 #include "MAX6956.h"
+
36 
+ + +
42 }
+
43 
+
49 MAX6956::MAX6956(uint8_t address) {
+
50  devAddr = address;
+
51 }
+
52 
+ +
55  // Need this in setup() or here.
+
56  // Fastwire::setup(400, false);
+
57  reset();
+
58 
+
64  I2Cdev::writeByte(devAddr, MAX6956_RA_CONFIG_P7P6P5P4, 0x55);
+
65  I2Cdev::writeByte(devAddr, MAX6956_RA_CONFIG_P11P10P9P8, 0x55);
+
66 }
+
67 
+ +
73  if (I2Cdev::readByte(devAddr, MAX6956_RA_CONFIGURATION, buffer) == 1) {
+
74  return true;
+
75  }
+
76  return false;
+
77 }
+
78 
+ +
81  disableAllPorts(); // set Port RA 0x2C-0x3F to 0
+
82  setGlobalCurrent(0x00); // Set global current to minimum on
+
83  setConfigReg(0x00); // Shutdown Enabled,Current Control = Global, Transition Detection Disabled
+
84  setInputMask(0x00); // Set Input register mask to 0
+
85  setTestMode(false); // disable test mode
+
86  configAllPorts(MAX6956_INPUT_WO_PULL); // Configure all inputs as MAX6956_INPUT_WO_PULL
+
87  setAllPortsCurrent(0x00); // Set current RA 0x16-01F to 0
+
88 }
+
89 
+ +
95  I2Cdev::readByte(devAddr, MAX6956_RA_CONFIGURATION, buffer);
+
96  return buffer[0];
+
97 }
+
102 void MAX6956::setConfigReg(uint8_t config) {
+
103  I2Cdev::writeByte(devAddr, MAX6956_RA_CONFIGURATION, config);
+
104 }
+
105 
+ + +
112  return buffer[0];
+
113 }
+
118 void MAX6956::setPower(bool power) {
+
119  I2Cdev::writeBit(devAddr, MAX6956_RA_CONFIGURATION, MAX6956_CONFIG_POWER_BIT, power);
+
120 }
+ + +
126  buffer[0] = !(buffer[0]);
+ +
128 }
+
129 
+ + +
136  return buffer[0];
+
137 }
+ + +
146 }
+
147 
+ + +
154  return buffer[0];
+
155 }
+ +
163  I2Cdev::writeBit(devAddr, MAX6956_RA_CONFIGURATION, MAX6956_CONFIG_TRANSITION_BIT, transition);
+
164 }
+
165 
+
166 // Global Current
+ + +
173  return buffer[0];
+
174 }
+
179 void MAX6956::setGlobalCurrent(uint8_t current) {
+
180  I2Cdev::writeByte(devAddr, MAX6956_RA_GLOBAL_CURRENT, current);
+
181 }
+
182 
+
183 // Test mode
+ + +
190  return buffer[0];
+
191 }
+
196 void MAX6956::setTestMode(bool test) {
+
197  I2Cdev::writeByte(devAddr, MAX6956_RA_DISPLAY_TEST, test);
+
198 }
+
199 
+
200 // Input mask register
+ +
206  I2Cdev::readByte(devAddr, MAX6956_RA_TRANSITION_DETECT, buffer);
+
207  return buffer[0];
+
208 }
+
209 
+
214 void MAX6956::setInputMask(uint8_t mask) {
+
215  I2Cdev::writeByte(devAddr, MAX6956_RA_TRANSITION_DETECT, mask);
+
216 }
+
217 
+
218 
+
265 void MAX6956::configPort(uint8_t port, uint8_t portConfig) {
+
266  uint8_t bitPosition = (((port - 44) % 4) * 2) + 1; // bit position to start flipping
+
267  uint8_t pcArrayIndex = (port - 44) / 4; // array index
+
268  uint8_t portConfigRA = pcArrayIndex + 11; // port config register
+
269  I2Cdev::writeBits(devAddr, portConfigRA, bitPosition, 2, portConfig);
+
270  // Update portConfig array
+
271  bitPosition--; // Remove 1 bit offset
+
272  portsConfig[pcArrayIndex] &= ~(3 << bitPosition);
+
273  portsConfig[pcArrayIndex] |= portConfig << bitPosition;
+
274 }
+
275 
+
285 void MAX6956::configPorts(uint8_t lower, uint8_t upper, uint8_t portConfig) {
+
286 
+
287  Serial.print("lower ");
+
288  Serial.print(lower, HEX);
+
289  Serial.print(" upper ");
+
290  Serial.print(upper, HEX);
+
291  Serial.print(" portConfig ");
+
292  Serial.println(portConfig, BIN);
+
293 
+
294  uint8_t bitPosition = 0;
+
295  uint8_t pcArrayIndex = 0;
+
296  uint8_t portConfigRA = 0;
+
297  uint8_t i = lower;
+
298 
+
299  while ( i <= upper ) {
+
300  bitPosition = (((i - 44) % 4) * 2) + 1; // bit position to start flipping
+
301  pcArrayIndex = (i - 44) / 4; // array index
+
302  portConfigRA = pcArrayIndex + 11; // port config register
+
303  Serial.print("i ");
+
304  Serial.print(i);
+
305  Serial.print(" bitPosition ");
+
306  Serial.print(bitPosition);
+
307  Serial.print(" pcArrayIndex");
+
308  Serial.print(pcArrayIndex);
+
309  Serial.print(" portConfigRA ");
+
310  Serial.println(portConfigRA, HEX);
+
311  I2Cdev::writeBits(devAddr, portConfigRA, bitPosition, 2, portConfig);
+
312  // Update portConfig array
+
313  Serial.print("portsConfig ");
+
314  Serial.print(portsConfig[pcArrayIndex], BIN);
+
315  bitPosition--; // Remove 1 bit offset
+
316  portsConfig[pcArrayIndex] &= ~(3 << bitPosition); //3 == B00000011 Shift over correct number of bits then invert to create the mask
+
317  portsConfig[pcArrayIndex] |= portConfig << bitPosition;
+
318  Serial.print(" >> ");
+
319  Serial.println(portsConfig[pcArrayIndex], BIN);
+
320  i++;
+
321  }
+
322 
+
323 }
+
324 
+
332 void MAX6956::configAllPorts(uint8_t portConfig) {
+
333  // build byte with config bits shifted to all 4 slots
+
334  portConfig = portConfig << 6 + portConfig << 4 + portConfig << 2 + portConfig;
+
335  // copy byte to portsConfig array slots
+
336  memset (portsConfig, portConfig, 5);
+
337  // write bytes all at once to device
+
338  I2Cdev::writeBytes(devAddr, MAX6956_RA_CONFIG_P15P14P13P12, 5, portsConfig);
+
339 }
+
340 
+
346 void MAX6956::setPortLevel(uint8_t port, uint8_t power) {
+
347  if ( port >= 44 && port <= 63 && power >= 0 && power <= 15 ) {
+
348  //power = sqrt(2) * power; // Convert linear to log scale
+
349 
+
350  psArrayIndex = (port - 44) / 8; // array index
+
351  psBitPosition = (port - 44) % 8; // bit position to flip
+
352 
+
353  if ( power > 0 ) {
+
354  // When not at 100% power decrement power by one because 0 is
+
355  // really an "on" power level and the lower levels are more important.
+
356  if ( power < 15 ) power--;
+
357 
+
358  // Calculate current register from port address
+
359  // set current bit offset
+
360  if ( port % 2 ) { //port is odd
+
361  portCurrentRA = (port - 1) / 2;
+
362  portCurrentBit = 7;
+
363  }
+
364  else {
+
365  portCurrentRA = port / 2;
+
366  portCurrentBit = 3;
+
367  }
+
368 
+
369  // Write changes
+
370  I2Cdev::writeBits(devAddr, portCurrentRA, portCurrentBit, 4, power); // Write changes
+
371  I2Cdev::writeByte(devAddr, port, MAX6956_ON); // turn on port
+
372 
+
373  #ifdef MAX6956_SERIAL_DEBUG
+
374  Serial.print("port ");
+
375  Serial.print(port);
+
376  Serial.print(" portCurrentBit ");
+
377  Serial.print(portCurrentBit);
+
378  Serial.print(" portCurrentRA ");
+
379  Serial.print(portCurrentRA, HEX);
+
380  Serial.print(" power ");
+
381  Serial.println(power );
+
382  #endif
+
383  // Update portStatus array
+ +
385  } else {
+
386  I2Cdev::writeByte(devAddr, port, MAX6956_OFF); // turn off port
+
387  portsStatus[psArrayIndex] &= ~(1 << psBitPosition); // Update portStatus array
+
388 
+
389  #ifdef MAX6956_SERIAL_DEBUG
+
390  Serial.print("port ");
+
391  Serial.print(port);
+
392  Serial.println(" is off");
+
393  #endif
+
394  }
+
395  }
+
396 }
+
397 
+
398 
+
404 void MAX6956::setPortCurrent(uint8_t port, uint8_t power) {
+
405  if ( port >= 44 && port <= 63 && power >= 0 && power <= 15 ) {
+
406  //power = sqrt(2) * power; /** TODO Convert linear to log scale */
+
407 
+
408  psArrayIndex = (port - 44) / 8; // array index
+
409  psBitPosition = (port - 44) % 8; // bit position to flip
+
410 
+
411  // Calculate current register from port address
+
412  // set current bit offset
+
413  if ( port % 2 ) { //port is odd
+
414  portCurrentRA = (port - 1) / 2;
+
415  portCurrentBit = 7;
+
416  }
+
417  else {
+
418  portCurrentRA = port / 2;
+
419  portCurrentBit = 3;
+
420  }
+
421 
+
422  // Write changes
+
423  I2Cdev::writeBits(devAddr, portCurrentRA, portCurrentBit, 4, power); // Write changes
+
424  I2Cdev::writeByte(devAddr, port, MAX6956_ON); // turn on port
+
425 
+
426  #ifdef MAX6956_SERIAL_DEBUG
+
427  Serial.print("port ");
+
428  Serial.print(port);
+
429  Serial.print(" portCurrentBit ");
+
430  Serial.print(portCurrentBit);
+
431  Serial.print(" portCurrentRA ");
+
432  Serial.print(portCurrentRA, HEX);
+
433  Serial.print(" power ");
+
434  Serial.println(power );
+
435  #endif
+
436  // Update portStatus array
+ +
438  }
+
439 }
+
444 void MAX6956::setAllPortsCurrent(uint8_t power) {
+ +
446  I2Cdev::writeByte(devAddr, portCurrentRA, power);
+
447  }
+
448 }
+
449 
+ +
454  // set portStatus array to all 1's
+
455  memset (portsStatus, 0xFF, 3);
+
456  // write bytes
+
457  I2Cdev::writeByte(devAddr, MAX6956_RA_PORTS12_19, portsStatus[0]);
+
458  I2Cdev::writeByte(devAddr, MAX6956_RA_PORTS20_27, portsStatus[1]);
+
459  I2Cdev::writeByte(devAddr, MAX6956_RA_PORTS28_31, portsStatus[2]);
+
460 }
+
461 
+ +
464  // set portStatus array to all 0's
+
465  memset (portsStatus, 0x00, 3);
+
466  // write bytes
+
467  I2Cdev::writeByte(devAddr, MAX6956_RA_PORTS12_19, portsStatus[0]);
+
468  I2Cdev::writeByte(devAddr, MAX6956_RA_PORTS20_27, portsStatus[1]);
+
469  I2Cdev::writeByte(devAddr, MAX6956_RA_PORTS28_31, portsStatus[2]);
+
470 }
+
uint8_t devAddr
Holds the current device address.
Definition: MAX6956.h:555
+
uint8_t portCurrentRA
Holder for port current register.
Definition: MAX6956.h:558
+
uint8_t psArrayIndex
array index
Definition: MAX6956.h:560
+
void enableAllPorts()
Definition: MAX6956.cpp:453
+
bool getEnableTransitionDetection()
Definition: MAX6956.cpp:152
+
#define MAX6956_RA_GLOBAL_CURRENT
Definition: MAX6956.h:102
+
uint8_t getInputMask()
Definition: MAX6956.cpp:205
+
void disableAllPorts()
Definition: MAX6956.cpp:463
+
bool getEnableIndividualCurrent()
Definition: MAX6956.cpp:134
+
#define MAX6956_RA_DISPLAY_TEST
Definition: MAX6956.h:165
+
void setPower(bool power)
Definition: MAX6956.cpp:118
+
#define MAX6956_INPUT_WO_PULL
Definition: MAX6956.h:408
+
#define MAX6956_ON
Definition: MAX6956.h:412
+
#define MAX6956_OFF
Definition: MAX6956.h:411
+
#define MAX6956_CONFIG_POWER_BIT
0 = Shutdown, 1 = Normal operation
Definition: MAX6956.h:343
+
void configPort(uint8_t port, uint8_t portConfig)
Definition: MAX6956.cpp:265
+
void setAllPortsCurrent(uint8_t power)
0-15, 0 = min brightness (not off) 15 = max
Definition: MAX6956.cpp:444
+
#define MAX6956_RA_CONFIG_P15P14P13P12
Definition: MAX6956.h:205
+
void configPorts(uint8_t lower, uint8_t upper, uint8_t portConfig)
Definition: MAX6956.cpp:285
+
uint8_t portsConfig[5]
Definition: MAX6956.h:527
+
uint8_t getGlobalCurrent()
Definition: MAX6956.cpp:171
+
#define MAX6956_DISPLAY_TEST_BIT
0 = Normal operation, 1 = Display test
Definition: MAX6956.h:391
+
#define MAX6956_RA_CONFIGURATION
Definition: MAX6956.h:137
+
bool getTestMode()
Definition: MAX6956.cpp:188
+
uint8_t psBitPosition
bit position
Definition: MAX6956.h:561
+
#define MAX6956_RA_PORTS20_27
Definition: MAX6956.h:325
+
#define MAX6956_RA_PORTS28_31
data bits D0-D3; D4-D7 read as 0
Definition: MAX6956.h:336
+
#define MAX6956_RA_PORTS12_19
Definition: MAX6956.h:317
+
uint8_t portsStatus[3]
Definition: MAX6956.h:552
+
void initialize()
Definition: MAX6956.cpp:54
+
void setConfigReg(uint8_t config)
Definition: MAX6956.cpp:102
+
bool getPower()
Definition: MAX6956.cpp:110
+
void configAllPorts(uint8_t portConfig)
Definition: MAX6956.cpp:332
+ +
void setEnableTransitionDetection(bool transition)
Definition: MAX6956.cpp:162
+
#define MAX6956_RA_CURRENT_0xP31P30
Definition: MAX6956.h:254
+
void setEnableIndividualCurrent(bool global)
Definition: MAX6956.cpp:144
+
void setPortCurrent(uint8_t port, uint8_t power)
0-15 brightness levels.
Definition: MAX6956.cpp:404
+
#define MAX6956_GLOBAL_CURRENT_LENGTH
nybble long
Definition: MAX6956.h:348
+
uint8_t portCurrentBit
Holder for the current bit offset.
Definition: MAX6956.h:559
+
#define MAX6956_RA_CURRENT_0xP13P12
Definition: MAX6956.h:245
+
void setPortLevel(uint8_t port, uint8_t power)
0 = off, 1-15 brightness levels.
Definition: MAX6956.cpp:346
+
MAX6956()
Definition: MAX6956.cpp:40
+
#define MAX6956_GLOBAL_CURRENT_BIT
Global current start bit.
Definition: MAX6956.h:347
+
#define MAX6956_CONFIG_TRANSITION_BIT
0 = Disabled, 1 = Enabled
Definition: MAX6956.h:345
+
#define MAX6956_RA_CONFIG_P11P10P9P8
Definition: MAX6956.h:204
+
#define MAX6956_RA_CONFIG_P7P6P5P4
Definition: MAX6956.h:203
+
uint8_t buffer[1]
Buffer for reading data from the device.
Definition: MAX6956.h:556
+
void setGlobalCurrent(uint8_t current)
Definition: MAX6956.cpp:179
+
void reset()
Definition: MAX6956.cpp:80
+
bool testConnection()
Definition: MAX6956.cpp:72
+
void setTestMode(bool test)
Definition: MAX6956.cpp:196
+
void togglePower()
Definition: MAX6956.cpp:124
+
uint8_t portConfig
Holder for port config bit pair.
Definition: MAX6956.h:557
+
#define MAX6956_RA_TRANSITION_DETECT
Definition: MAX6956.h:152
+
void setInputMask(uint8_t mask)
Definition: MAX6956.cpp:214
+
#define MAX6956_DEFAULT_ADDRESS
Definition: MAX6956.h:72
+
#define MAX6956_CONFIG_GLOBAL_CURRENT_BIT
0 = Global control, 1 = Individual control
Definition: MAX6956.h:344
+
uint8_t getConfigReg()
Definition: MAX6956.cpp:94
+
+ + + + diff --git a/Arduino/MAX6956/html/MAX6956_8h.html b/Arduino/MAX6956/html/MAX6956_8h.html new file mode 100644 index 00000000..46464b88 --- /dev/null +++ b/Arduino/MAX6956/html/MAX6956_8h.html @@ -0,0 +1,3196 @@ + + + + + + +MAX6956: MAX6956.h File Reference + + + + + + + + + +
+
+ + + + + + +
+
MAX6956 +  1.0 +
+
MAX6956i2Clibrary
+
+
+ + + + + + + + + +
+ +
+ +
+
+ +
+
MAX6956.h File Reference
+
+
+
#include "I2Cdev.h"
+
+

Go to the source code of this file.

+ + + + +

+Data Structures

class  MAX6956
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Macros

#define MAX6956_ADDRESS   0x40
 
#define MAX6956_DEFAULT_ADDRESS   0x40
 
#define MAX6956_RA_NO_OP   0x00
 No-op. More...
 
#define MAX6956_RA_GLOBAL_CURRENT   0x02
 
#define MAX6956_RA_CONFIGURATION   0x04
 
#define MAX6956_RA_TRANSITION_DETECT   0x06
 
#define MAX6956_RA_DISPLAY_TEST   0x07
 
#define MAX6956_RA_CONFIG_P7P6P5P4   0x09
 
#define MAX6956_RA_CONFIG_P11P10P9P8   0x0A
 
#define MAX6956_RA_CONFIG_P15P14P13P12   0x0B
 
#define MAX6956_RA_CONFIG_P19P18P17P16   0x0C
 
#define MAX6956_RA_CONFIG_P23P22P21P20   0x0D
 
#define MAX6956_RA_CONFIG_P27P26P25P24   0x0E
 
#define MAX6956_RA_CONFIG_P31P30P29P28   0x0F
 
#define MAX6956_RA_CURRENT_0xP5P4   0x12
 
#define MAX6956_RA_CURRENT_0xP7P6   0x13
 
#define MAX6956_RA_CURRENT_0xP9P8   0x14
 
#define MAX6956_RA_CURRENT_0xP11P10   0x15
 
#define MAX6956_RA_CURRENT_0xP13P12   0x16
 
#define MAX6956_RA_CURRENT_0xP15P14   0x17
 
#define MAX6956_RA_CURRENT_0xP17P16   0x18
 
#define MAX6956_RA_CURRENT_0xP19P18   0x19
 
#define MAX6956_RA_CURRENT_0xP21P20   0x1A
 
#define MAX6956_RA_CURRENT_0xP23P22   0x1B
 
#define MAX6956_RA_CURRENT_0xP25P24   0x1C
 
#define MAX6956_RA_CURRENT_0xP27P26   0x1D
 
#define MAX6956_RA_CURRENT_0xP29P28   0x1E
 
#define MAX6956_RA_CURRENT_0xP31P30   0x1F
 
#define MAX6956_RA_PORT0   0x20
 (virtual port, no action) More...
 
#define MAX6956_RA_PORT1   0x21
 (virtual port, no action) More...
 
#define MAX6956_RA_PORT2   0x22
 (virtual port, no action) More...
 
#define MAX6956_RA_PORT3   0x23
 (virtual port, no action) More...
 
#define MAX6956_RA_PORT4   0x24
 
#define MAX6956_RA_PORT5   0x25
 
#define MAX6956_RA_PORT6   0x26
 
#define MAX6956_RA_PORT7   0x27
 
#define MAX6956_RA_PORT8   0x28
 
#define MAX6956_RA_PORT9   0x29
 
#define MAX6956_RA_PORT10   0x2A
 
#define MAX6956_RA_PORT11   0x2B
 
#define MAX6956_RA_PORT12   0x2C
 
#define MAX6956_RA_PORT13   0x2D
 
#define MAX6956_RA_PORT14   0x2E
 
#define MAX6956_RA_PORT15   0x2F
 
#define MAX6956_RA_PORT16   0x30
 
#define MAX6956_RA_PORT17   0x31
 
#define MAX6956_RA_PORT18   0x32
 
#define MAX6956_RA_PORT19   0x33
 
#define MAX6956_RA_PORT20   0x34
 
#define MAX6956_RA_PORT21   0x35
 
#define MAX6956_RA_PORT22   0x36
 
#define MAX6956_RA_PORT23   0x37
 
#define MAX6956_RA_PORT24   0x38
 
#define MAX6956_RA_PORT25   0x39
 
#define MAX6956_RA_PORT26   0x3A
 
#define MAX6956_RA_PORT27   0x3B
 
#define MAX6956_RA_PORT28   0x3C
 
#define MAX6956_RA_PORT29   0x3D
 
#define MAX6956_RA_PORT30   0x3E
 
#define MAX6956_RA_PORT31   0x3F
 
#define MAX6956_RA_PORTS4_7   0x40
 data bits D0-D3; D4-D7 read as 0 More...
 
#define MAX6956_RA_PORTS4_8   0x41
 data bits D0-D4; D5-D7 read as 0 More...
 
#define MAX6956_RA_PORTS4_9   0x42
 data bits D0-D5; D6-D7 read as 0 More...
 
#define MAX6956_RA_PORTS4_10   0x43
 data bits D0-D6; D7 reads as 0 More...
 
#define MAX6956_RA_PORTS4_11   0x44
 
#define MAX6956_RA_PORTS5_12   0x45
 
#define MAX6956_RA_PORTS6_13   0x46
 
#define MAX6956_RA_PORTS7_14   0x47
 
#define MAX6956_RA_PORTS8_15   0x48
 
#define MAX6956_RA_PORTS9_16   0x49
 
#define MAX6956_RA_PORTS10_17   0x4A
 
#define MAX6956_RA_PORTS11_18   0x4B
 
#define MAX6956_RA_PORTS12_19   0x4C
 
#define MAX6956_RA_PORTS13_20   0x4D
 
#define MAX6956_RA_PORTS14_21   0x4E
 
#define MAX6956_RA_PORTS15_22   0x4F
 
#define MAX6956_RA_PORTS16_23   0x50
 
#define MAX6956_RA_PORTS17_24   0x51
 
#define MAX6956_RA_PORTS18_25   0x52
 
#define MAX6956_RA_PORTS19_26   0x53
 
#define MAX6956_RA_PORTS20_27   0x54
 
#define MAX6956_RA_PORTS21_28   0x55
 
#define MAX6956_RA_PORTS22_29   0x56
 
#define MAX6956_RA_PORTS23_30   0x57
 
#define MAX6956_RA_PORTS24_31   0x58
 
#define MAX6956_RA_PORTS25_31   0x59
 data bits D0-D6; D7 reads as 0 More...
 
#define MAX6956_RA_PORTS26_31   0x5A
 data bits D0-D5; D6-D7 read as 0 More...
 
#define MAX6956_RA_PORTS27_31   0x5B
 data bits D0-D4; D5-D7 read as 0 More...
 
#define MAX6956_RA_PORTS28_31   0x5C
 data bits D0-D3; D4-D7 read as 0 More...
 
#define MAX6956_RA_PORTS29_31   0x5D
 data bits D0-D2; D3-D7 read as 0 More...
 
#define MAX6956_RA_PORTS30_31   0x5E
 data bits D0-D1; D2-D7 read as 0 More...
 
#define MAX6956_RA_PORTS31_31   0x5F
 data bit D0; D1-D7 read as 0. Port 31 only. More...
 
#define MAX6956_CONFIG_POWER_BIT   0
 0 = Shutdown, 1 = Normal operation More...
 
#define MAX6956_CONFIG_GLOBAL_CURRENT_BIT   6
 0 = Global control, 1 = Individual control More...
 
#define MAX6956_CONFIG_TRANSITION_BIT   7
 0 = Disabled, 1 = Enabled More...
 
#define MAX6956_GLOBAL_CURRENT_BIT   0
 Global current start bit. More...
 
#define MAX6956_GLOBAL_CURRENT_LENGTH   4
 nybble long More...
 
#define MAX6956_PORT12_CURRENT_BIT   3
 LSNybble. More...
 
#define MAX6956_PORT12_CURRENT_LENGTH   4
 nybble long More...
 
#define MAX6956_PORT13_CURRENT_BIT   7
 MSNybble. More...
 
#define MAX6956_PORT13_CURRENT_LENGTH   4
 nybble long More...
 
#define MAX6956_PORT14_CURRENT_BIT   3
 LSNybble. More...
 
#define MAX6956_PORT14_CURRENT_LENGTH   4
 nybble long More...
 
#define MAX6956_PORT15_CURRENT_BIT   7
 MSNybble. More...
 
#define MAX6956_PORT15_CURRENT_LENGTH   4
 nybble long More...
 
#define MAX6956_PORT16_CURRENT_BIT   3
 LSNybble. More...
 
#define MAX6956_PORT16_CURRENT_LENGTH   4
 nybble long More...
 
#define MAX6956_PORT17_CURRENT_BIT   7
 MSNybble. More...
 
#define MAX6956_PORT17_CURRENT_LENGTH   4
 nybble long More...
 
#define MAX6956_PORT18_CURRENT_BIT   3
 LSNybble. More...
 
#define MAX6956_PORT18_CURRENT_LENGTH   4
 nybble long More...
 
#define MAX6956_PORT19_CURRENT_BIT   7
 MSNybble. More...
 
#define MAX6956_PORT19_CURRENT_LENGTH   4
 nybble long More...
 
#define MAX6956_PORT23_CURRENT_BIT   3
 LSNybble. More...
 
#define MAX6956_PORT23_CURRENT_LENGTH   4
 nybble long More...
 
#define MAX6956_PORT21_CURRENT_BIT   7
 MSNybble. More...
 
#define MAX6956_PORT21_CURRENT_LENGTH   4
 nybble long More...
 
#define MAX6956_PORT22_CURRENT_BIT   3
 LSNybble. More...
 
#define MAX6956_PORT22_CURRENT_LENGTH   4
 nybble long More...
 
#define MAX6956_PORT23_CURRENT_BIT   7
 LSNybble. More...
 
#define MAX6956_PORT23_CURRENT_LENGTH   4
 nybble long More...
 
#define MAX6956_PORT24_CURRENT_BIT   3
 LSNybble. More...
 
#define MAX6956_PORT24_CURRENT_LENGTH   4
 nybble long More...
 
#define MAX6956_PORT25_CURRENT_BIT   7
 MSNybble. More...
 
#define MAX6956_PORT25_CURRENT_LENGTH   4
 nybble long More...
 
#define MAX6956_PORT26_CURRENT_BIT   3
 LSNybble. More...
 
#define MAX6956_PORT26_CURRENT_LENGTH   4
 nybble long More...
 
#define MAX6956_PORT27_CURRENT_BIT   7
 MSNybble. More...
 
#define MAX6956_PORT27_CURRENT_LENGTH   4
 nybble long More...
 
#define MAX6956_PORT28_CURRENT_BIT   3
 LSNybble. More...
 
#define MAX6956_PORT28_CURRENT_LENGTH   4
 nybble long More...
 
#define MAX6956_PORT29_CURRENT_BIT   7
 MSNybble. More...
 
#define MAX6956_PORT29_CURRENT_LENGTH   4
 nybble long More...
 
#define MAX6956_PORT33_CURRENT_BIT   3
 LSNybble. More...
 
#define MAX6956_PORT33_CURRENT_LENGTH   4
 nybble long More...
 
#define MAX6956_PORT31_CURRENT_BIT   7
 MSNybble. More...
 
#define MAX6956_PORT31_CURRENT_LENGTH   4
 nybble long More...
 
#define MAX6956_DISPLAY_TEST_BIT   0
 0 = Normal operation, 1 = Display test More...
 
#define MAX6956_TRANSITION_STATUS_BIT   7
 INT Status, INT is automatically cleared after it is read. More...
 
#define MAX6956_TRANSITION_MASK_BIT   0
 Ports 24-30. More...
 
#define MAX6956_TRANSITION_MASK_LENGTH   7
 
#define MAX6956_TRANSITION_MASK_PORT30_BIT   6
 
#define MAX6956_TRANSITION_MASK_PORT29_BIT   5
 
#define MAX6956_TRANSITION_MASK_PORT28_BIT   4
 
#define MAX6956_TRANSITION_MASK_PORT27_BIT   3
 
#define MAX6956_TRANSITION_MASK_PORT26_BIT   2
 
#define MAX6956_TRANSITION_MASK_PORT25_BIT   1
 
#define MAX6956_TRANSITION_MASK_PORT24_BIT   0
 
#define MAX6956_OUTPUT_LED   0x00
 
#define MAX6956_OUTPUT_GPIO   0x01
 
#define MAX6956_INPUT_WO_PULL   0x02
 
#define MAX6956_INPUT_W_PULL   0x03
 
#define MAX6956_OFF   0x00
 
#define MAX6956_ON   0x01
 
#define MAX6956_CURRENT_0   0x00
 
#define MAX6956_CURRENT_1   0x01
 
#define MAX6956_CURRENT_2   0x02
 
#define MAX6956_CURRENT_3   0x03
 
#define MAX6956_CURRENT_4   0x04
 
#define MAX6956_CURRENT_5   0x05
 
#define MAX6956_CURRENT_6   0x06
 
#define MAX6956_CURRENT_7   0x07
 
#define MAX6956_CURRENT_8   0x08
 
#define MAX6956_CURRENT_9   0x09
 
#define MAX6956_CURRENT_10   0x0A
 
#define MAX6956_CURRENT_11   0x0B
 
#define MAX6956_CURRENT_12   0x0C
 
#define MAX6956_CURRENT_13   0x0D
 
#define MAX6956_CURRENT_14   0x0E
 
#define MAX6956_CURRENT_15   0x0F
 
+

Macro Definition Documentation

+ +
+
+ + + + +
#define MAX6956_ADDRESS   0x40
+
+

Table 3. I2C Address Map

+

Pin|Pin|DEVICE ADDRESS | :-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:–: AD1|AD0|A7 |A6 |A5 |A4 |A3 |A2 |A1 |A0 |HEX GND|GND|1 |0 |0 |0 |0 |0 |0 |RW |0x40 GND|V+ |1 |0 |0 |0 |0 |0 |1 |RW |0x41 GND|SDA|1 |0 |0 |0 |0 |1 |0 |RW |0x42 GND|SCL|1 |0 |0 |0 |0 |1 |1 |RW |0x43 V+ |GND|1 |0 |0 |0 |1 |0 |0 |RW |0x44 V+ |V+ |1 |0 |0 |0 |1 |0 |1 |RW |0x45 V+ |SDA|1 |0 |0 |0 |1 |1 |0 |RW |0x46 V+ |SCL|1 |0 |0 |0 |1 |1 |1 |RW |0x47 SDA|GND|1 |0 |0 |1 |0 |0 |0 |RW |0x48 SDA|V+ |1 |0 |0 |1 |0 |0 |1 |RW |0x49 SDA|SDA|1 |0 |0 |1 |0 |1 |0 |RW |0x50 SDA|SCL|1 |0 |0 |1 |0 |1 |1 |RW |0x51 SCL|GND|1 |0 |0 |1 |1 |0 |0 |RW |0x52 SCL|V+ |1 |0 |0 |1 |1 |0 |1 |RW |0x53 SCL|SDA|1 |0 |0 |1 |1 |1 |0 |RW |0x54 SCL|SCL|1 |0 |0 |1 |1 |1 |1 |RW |0x55

+

RW bit 0 = Write 1 = Read

+ +

Definition at line 71 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_CONFIG_GLOBAL_CURRENT_BIT   6
+
+ +

0 = Global control, 1 = Individual control

+ +

Definition at line 344 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_CONFIG_POWER_BIT   0
+
+ +

0 = Shutdown, 1 = Normal operation

+ +

Definition at line 343 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_CONFIG_TRANSITION_BIT   7
+
+ +

0 = Disabled, 1 = Enabled

+ +

Definition at line 345 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_CURRENT_0   0x00
+
+ +

Definition at line 414 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_CURRENT_1   0x01
+
+ +

Definition at line 415 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_CURRENT_10   0x0A
+
+ +

Definition at line 424 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_CURRENT_11   0x0B
+
+ +

Definition at line 425 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_CURRENT_12   0x0C
+
+ +

Definition at line 426 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_CURRENT_13   0x0D
+
+ +

Definition at line 427 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_CURRENT_14   0x0E
+
+ +

Definition at line 428 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_CURRENT_15   0x0F
+
+ +

Definition at line 429 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_CURRENT_2   0x02
+
+ +

Definition at line 416 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_CURRENT_3   0x03
+
+ +

Definition at line 417 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_CURRENT_4   0x04
+
+ +

Definition at line 418 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_CURRENT_5   0x05
+
+ +

Definition at line 419 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_CURRENT_6   0x06
+
+ +

Definition at line 420 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_CURRENT_7   0x07
+
+ +

Definition at line 421 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_CURRENT_8   0x08
+
+ +

Definition at line 422 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_CURRENT_9   0x09
+
+ +

Definition at line 423 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_DEFAULT_ADDRESS   0x40
+
+ +

Definition at line 72 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_DISPLAY_TEST_BIT   0
+
+ +

0 = Normal operation, 1 = Display test

+ +

Definition at line 391 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_GLOBAL_CURRENT_BIT   0
+
+ +

Global current start bit.

+ +

Definition at line 347 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_GLOBAL_CURRENT_LENGTH   4
+
+ +

nybble long

+ +

Definition at line 348 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_INPUT_W_PULL   0x03
+
+ +

Definition at line 409 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_INPUT_WO_PULL   0x02
+
+ +

Definition at line 408 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_OFF   0x00
+
+ +

Definition at line 411 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_ON   0x01
+
+ +

Definition at line 412 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_OUTPUT_GPIO   0x01
+
+ +

Definition at line 407 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_OUTPUT_LED   0x00
+
+ +

Definition at line 406 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_PORT12_CURRENT_BIT   3
+
+ +

LSNybble.

+ +

Definition at line 350 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_PORT12_CURRENT_LENGTH   4
+
+ +

nybble long

+ +

Definition at line 351 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_PORT13_CURRENT_BIT   7
+
+ +

MSNybble.

+ +

Definition at line 352 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_PORT13_CURRENT_LENGTH   4
+
+ +

nybble long

+ +

Definition at line 353 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_PORT14_CURRENT_BIT   3
+
+ +

LSNybble.

+ +

Definition at line 354 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_PORT14_CURRENT_LENGTH   4
+
+ +

nybble long

+ +

Definition at line 355 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_PORT15_CURRENT_BIT   7
+
+ +

MSNybble.

+ +

Definition at line 356 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_PORT15_CURRENT_LENGTH   4
+
+ +

nybble long

+ +

Definition at line 357 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_PORT16_CURRENT_BIT   3
+
+ +

LSNybble.

+ +

Definition at line 358 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_PORT16_CURRENT_LENGTH   4
+
+ +

nybble long

+ +

Definition at line 359 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_PORT17_CURRENT_BIT   7
+
+ +

MSNybble.

+ +

Definition at line 360 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_PORT17_CURRENT_LENGTH   4
+
+ +

nybble long

+ +

Definition at line 361 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_PORT18_CURRENT_BIT   3
+
+ +

LSNybble.

+ +

Definition at line 362 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_PORT18_CURRENT_LENGTH   4
+
+ +

nybble long

+ +

Definition at line 363 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_PORT19_CURRENT_BIT   7
+
+ +

MSNybble.

+ +

Definition at line 364 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_PORT19_CURRENT_LENGTH   4
+
+ +

nybble long

+ +

Definition at line 365 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_PORT21_CURRENT_BIT   7
+
+ +

MSNybble.

+ +

Definition at line 368 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_PORT21_CURRENT_LENGTH   4
+
+ +

nybble long

+ +

Definition at line 369 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_PORT22_CURRENT_BIT   3
+
+ +

LSNybble.

+ +

Definition at line 370 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_PORT22_CURRENT_LENGTH   4
+
+ +

nybble long

+ +

Definition at line 371 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_PORT23_CURRENT_BIT   3
+
+ +

LSNybble.

+

MSNybble.

+ +

Definition at line 372 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_PORT23_CURRENT_BIT   7
+
+ +

LSNybble.

+

MSNybble.

+ +

Definition at line 372 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_PORT23_CURRENT_LENGTH   4
+
+ +

nybble long

+ +

Definition at line 373 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_PORT23_CURRENT_LENGTH   4
+
+ +

nybble long

+ +

Definition at line 373 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_PORT24_CURRENT_BIT   3
+
+ +

LSNybble.

+ +

Definition at line 374 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_PORT24_CURRENT_LENGTH   4
+
+ +

nybble long

+ +

Definition at line 375 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_PORT25_CURRENT_BIT   7
+
+ +

MSNybble.

+ +

Definition at line 376 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_PORT25_CURRENT_LENGTH   4
+
+ +

nybble long

+ +

Definition at line 377 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_PORT26_CURRENT_BIT   3
+
+ +

LSNybble.

+ +

Definition at line 378 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_PORT26_CURRENT_LENGTH   4
+
+ +

nybble long

+ +

Definition at line 379 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_PORT27_CURRENT_BIT   7
+
+ +

MSNybble.

+ +

Definition at line 380 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_PORT27_CURRENT_LENGTH   4
+
+ +

nybble long

+ +

Definition at line 381 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_PORT28_CURRENT_BIT   3
+
+ +

LSNybble.

+ +

Definition at line 382 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_PORT28_CURRENT_LENGTH   4
+
+ +

nybble long

+ +

Definition at line 383 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_PORT29_CURRENT_BIT   7
+
+ +

MSNybble.

+ +

Definition at line 384 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_PORT29_CURRENT_LENGTH   4
+
+ +

nybble long

+ +

Definition at line 385 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_PORT31_CURRENT_BIT   7
+
+ +

MSNybble.

+ +

Definition at line 388 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_PORT31_CURRENT_LENGTH   4
+
+ +

nybble long

+ +

Definition at line 389 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_PORT33_CURRENT_BIT   3
+
+ +

LSNybble.

+ +

Definition at line 386 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_PORT33_CURRENT_LENGTH   4
+
+ +

nybble long

+ +

Definition at line 387 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_CONFIG_P11P10P9P8   0x0A
+
+ +

Definition at line 204 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_CONFIG_P15P14P13P12   0x0B
+
+ +

Definition at line 205 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_CONFIG_P19P18P17P16   0x0C
+
+ +

Definition at line 206 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_CONFIG_P23P22P21P20   0x0D
+
+ +

Definition at line 207 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_CONFIG_P27P26P25P24   0x0E
+
+ +

Definition at line 208 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_CONFIG_P31P30P29P28   0x0F
+
+ +

Definition at line 209 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_CONFIG_P7P6P5P4   0x09
+
+

Table 1. Port Configuration Map

+ + + + + + + + + + + + + + + + + +
REGISTER ADDRESSD7 D6D5 D4D3 D2D1 D0
Port Configuration for P7, P6, P5, P4 0x09 P7 P6 P5 P4
Port Configuration for P11, P10, P9, P8 0x0A P11 P10 P9 P8
Port Configuration for P15, P14, P13, P120x0B P15 P14 P13 P12
Port Configuration for P19, P18, P17, P160x0C P19 P18 P17 P16
Port Configuration for P23, P22, P21, P200x0D P23 P22 P21 P20
Port Configuration for P27, P26, P25, P240x0E P27 P26 P25 P24
Port Configuration for P31, P30, P29, P280x0F P31 P30 P29 P28
+

Table 2. P4-P31 configuration bit pairs

+
+    00 - Output, LED Segment Driver
+             Controlled  using port registers 0x20-0x5F. 
+             0 = High impedance
+             1 = Open-drain current sink, with sink current (up to 24mA) 
+                 determined by the appropriate current register
+    01 - Output, GPIO Output
+             Controlled  using port registers 0x20-0x5F. 
+             0 = Active-low logic output
+             1 = Active-high logic output
+    10 - Input, GPIO Input Without Pullup
+             Read port registers 0x20-0x5F.
+             Schmitt logic input 
+    11 - Input, GPIO Input with Pullup
+             Read port registers 0x20-0x5F.
+             Schmitt logic input with pullup
+
+

Definition at line 203 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_CONFIGURATION   0x04
+
+

Table 7. Configuration Register Format

+ + + + + +
ADDRESS D7 D6 D5 D4 D3 D2 D1 D0
0x04 M I x x x x x S
+

Table 8. Shutdown Control (S Data Bit D0) Format

+ + + + + + + +
FUNCTION ADDRESSD7 D6 D5 D4 D3 D2 D1 D0
Shutdown 0x04 M I x x x x x 0
Normal Operation0x04 M I x x x x x 1
+

Table 9. Global Current Control (I Data Bit D6) Format

+ + + + + + + +
FUNCTION ADDRESSD7 D6 D5 D4 D3 D2 D1 D0
Global 0x04 M 0 x x x x x S
Individual Segment0x04 M 1 x x x x x S
+

Table 10. Transition Detection Control (M-Data Bit D7) Format

+ + + + + + + +
FUNCTION ADDRESSD7 D6 D5 D4 D3 D2 D1 D0
Disabled 0x04 0 I x x x x x S
Enabled 0x04 1 I x x x x x S
+ +

Definition at line 137 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_CURRENT_0xP11P10   0x15
+
+ +

Definition at line 244 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_CURRENT_0xP13P12   0x16
+
+ +

Definition at line 245 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_CURRENT_0xP15P14   0x17
+
+ +

Definition at line 246 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_CURRENT_0xP17P16   0x18
+
+ +

Definition at line 247 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_CURRENT_0xP19P18   0x19
+
+ +

Definition at line 248 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_CURRENT_0xP21P20   0x1A
+
+ +

Definition at line 249 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_CURRENT_0xP23P22   0x1B
+
+ +

Definition at line 250 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_CURRENT_0xP25P24   0x1C
+
+ +

Definition at line 251 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_CURRENT_0xP27P26   0x1D
+
+ +

Definition at line 252 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_CURRENT_0xP29P28   0x1E
+
+ +

Definition at line 253 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_CURRENT_0xP31P30   0x1F
+
+ +

Definition at line 254 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_CURRENT_0xP5P4   0x12
+
+

Constant-current limit for each digit is individually controlled by the settings in the Current054 through Current1FE registers

+

Table 12. Individual Port Current Registers

+
                | ADDRESS |            |
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FUNCTION CODE(HEX)D7 D6 D5 D4 D3 D2 D1 D0
Current054 register 0x12 Segment 5 Segment 4
Current076 register 0x13 Segment 7 Segment 6
Current098 register 0x14 Segment 9 Segment 8
Current0BA register 0x15 Segment 11 Segment 10
Current0DC register 0x16 Segment 13 Segment 12
Current0FE register 0x17 Segment 15 Segment 14
Current110 register 0x18 Segment 17 Segment 16
Current132 register 0x19 Segment 19 Segment 18
Current154 register 0x1A Segment 21 Segment 20
Current176 register 0x1B Segment 23 Segment 22
Current198 register 0x1C Segment 25 Segment 24
Current1BA register 0x1D Segment 27 Segment 26
Current1DC register 0x1E Segment 29 Segment 28
Current1FE register 0x1F Segment 31 Segment 30
+

Register data is 0-Fx0-F for 1-16(0-F) brightness levels. To completely blank an output turn it off (0) using port configuration registers.

+ +

Definition at line 241 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_CURRENT_0xP7P6   0x13
+
+ +

Definition at line 242 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_CURRENT_0xP9P8   0x14
+
+ +

Definition at line 243 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_DISPLAY_TEST   0x07
+
+

Table 16. Display Test Register

+
             |ADDR |
+
+ + + + + + +
MODE CODE D7 D6 D5 D4 D3 D2 D1 D0
Normal Operation 0x07 x x x x x x x 0
Display Test Mode0x07 x x x x x x x 1
+ +

Definition at line 165 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_GLOBAL_CURRENT   0x02
+
+

Table 11. Global Segment Current Register Format

+

LED DRIVE |TYPICAL SEGMENT | ADDRESS |

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FRACTION CURRENT(mA) CODE (HEX) D7 D6 D5 D4 D3 D2 D1 D0 HEX CODE
1/16 1.5 0x02 x x x x 0 0 0 0 0xX0
2/16 3 0x02 x x x x 0 0 0 1 0xX1
3/16 4.5 0x02 x x x x 0 0 1 0 0xX2
4/16 6 0x02 x x x x 0 0 1 1 0xX3
5/16 7.5 0x02 x x x x 0 1 0 0 0xX4
6/16 9 0x02 x x x x 0 1 0 1 0xX5
7/16 10.5 0x02 x x x x 0 1 1 0 0xX6
8/16 12 0x02 x x x x 0 1 1 1 0xX7
9/16 13.5 0x02 x x x x 1 0 0 0 0xX8
10/16 15 0x02 x x x x 1 0 0 1 0xX9
11/16 16.5 0x02 x x x x 1 0 1 0 0xXA
12/16 18 0x02 x x x x 1 0 1 1 0xXB
13/16 19.5 0x02 x x x x 1 1 0 0 0xXC
14/16 21 0x02 x x x x 1 1 0 1 0xXD
15/16 22.5 0x02 x x x x 1 1 1 0 0xXE
16/16 24 0x02 x x x x 1 1 1 1 0xXF
+ +

Definition at line 102 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_NO_OP   0x00
+
+ +

No-op.

+ +

Definition at line 76 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORT0   0x20
+
+ +

(virtual port, no action)

+

Individiual Port Registers

+
data bit D0; D7-D1 read as 0
+

Definition at line 262 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORT1   0x21
+
+ +

(virtual port, no action)

+ +

Definition at line 263 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORT10   0x2A
+
+ +

Definition at line 273 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORT11   0x2B
+
+ +

Definition at line 274 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORT12   0x2C
+
+ +

Definition at line 276 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORT13   0x2D
+
+ +

Definition at line 277 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORT14   0x2E
+
+ +

Definition at line 278 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORT15   0x2F
+
+ +

Definition at line 279 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORT16   0x30
+
+ +

Definition at line 280 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORT17   0x31
+
+ +

Definition at line 281 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORT18   0x32
+
+ +

Definition at line 282 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORT19   0x33
+
+ +

Definition at line 283 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORT2   0x22
+
+ +

(virtual port, no action)

+ +

Definition at line 264 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORT20   0x34
+
+ +

Definition at line 285 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORT21   0x35
+
+ +

Definition at line 286 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORT22   0x36
+
+ +

Definition at line 287 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORT23   0x37
+
+ +

Definition at line 288 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORT24   0x38
+
+ +

Definition at line 289 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORT25   0x39
+
+ +

Definition at line 290 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORT26   0x3A
+
+ +

Definition at line 291 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORT27   0x3B
+
+ +

Definition at line 292 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORT28   0x3C
+
+ +

Definition at line 294 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORT29   0x3D
+
+ +

Definition at line 295 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORT3   0x23
+
+ +

(virtual port, no action)

+ +

Definition at line 265 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORT30   0x3E
+
+ +

Definition at line 296 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORT31   0x3F
+
+ +

Definition at line 297 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORT4   0x24
+
+ +

Definition at line 267 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORT5   0x25
+
+ +

Definition at line 268 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORT6   0x26
+
+ +

Definition at line 269 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORT7   0x27
+
+ +

Definition at line 270 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORT8   0x28
+
+ +

Definition at line 271 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORT9   0x29
+
+ +

Definition at line 272 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORTS10_17   0x4A
+
+ +

Definition at line 315 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORTS11_18   0x4B
+
+ +

Definition at line 316 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORTS12_19   0x4C
+
+ +

Definition at line 317 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORTS13_20   0x4D
+
+ +

Definition at line 318 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORTS14_21   0x4E
+
+ +

Definition at line 319 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORTS15_22   0x4F
+
+ +

Definition at line 320 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORTS16_23   0x50
+
+ +

Definition at line 321 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORTS17_24   0x51
+
+ +

Definition at line 322 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORTS18_25   0x52
+
+ +

Definition at line 323 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORTS19_26   0x53
+
+ +

Definition at line 324 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORTS20_27   0x54
+
+ +

Definition at line 325 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORTS21_28   0x55
+
+ +

Definition at line 326 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORTS22_29   0x56
+
+ +

Definition at line 327 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORTS23_30   0x57
+
+ +

Definition at line 328 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORTS24_31   0x58
+
+ +

Definition at line 329 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORTS25_31   0x59
+
+ +

data bits D0-D6; D7 reads as 0

+ +

Definition at line 333 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORTS26_31   0x5A
+
+ +

data bits D0-D5; D6-D7 read as 0

+ +

Definition at line 334 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORTS27_31   0x5B
+
+ +

data bits D0-D4; D5-D7 read as 0

+ +

Definition at line 335 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORTS28_31   0x5C
+
+ +

data bits D0-D3; D4-D7 read as 0

+ +

Definition at line 336 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORTS29_31   0x5D
+
+ +

data bits D0-D2; D3-D7 read as 0

+ +

Definition at line 337 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORTS30_31   0x5E
+
+ +

data bits D0-D1; D2-D7 read as 0

+ +

Definition at line 338 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORTS31_31   0x5F
+
+ +

data bit D0; D1-D7 read as 0. Port 31 only.

+ +

Definition at line 339 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORTS4_10   0x43
+
+ +

data bits D0-D6; D7 reads as 0

+ +

Definition at line 304 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORTS4_11   0x44
+
+ +

Definition at line 309 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORTS4_7   0x40
+
+ +

data bits D0-D3; D4-D7 read as 0

+ +

Definition at line 301 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORTS4_8   0x41
+
+ +

data bits D0-D4; D5-D7 read as 0

+ +

Definition at line 302 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORTS4_9   0x42
+
+ +

data bits D0-D5; D6-D7 read as 0

+ +

Definition at line 303 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORTS5_12   0x45
+
+ +

Definition at line 310 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORTS6_13   0x46
+
+ +

Definition at line 311 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORTS7_14   0x47
+
+ +

Definition at line 312 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORTS8_15   0x48
+
+ +

Definition at line 313 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_PORTS9_16   0x49
+
+ +

Definition at line 314 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_RA_TRANSITION_DETECT   0x06
+
+

Table 15. Transition Detection Mask Register

+ + + + + + + + + +
FUNCTION REGISTER ADDRESS READ/WRITE D7 D6 D5 D4 D3 D2 D1 D0
Mask Register 0x06 Read INT Status*PortPortPortPortPortPortPort
30 29 28 27 26 25 24
Write Unchanged maskmaskmaskmaskmaskmaskmask
+

INT is automatically cleared after it is read.

+ +

Definition at line 152 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_TRANSITION_MASK_BIT   0
+
+ +

Ports 24-30.

+ +

Definition at line 394 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_TRANSITION_MASK_LENGTH   7
+
+ +

Definition at line 395 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_TRANSITION_MASK_PORT24_BIT   0
+
+ +

Definition at line 402 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_TRANSITION_MASK_PORT25_BIT   1
+
+ +

Definition at line 401 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_TRANSITION_MASK_PORT26_BIT   2
+
+ +

Definition at line 400 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_TRANSITION_MASK_PORT27_BIT   3
+
+ +

Definition at line 399 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_TRANSITION_MASK_PORT28_BIT   4
+
+ +

Definition at line 398 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_TRANSITION_MASK_PORT29_BIT   5
+
+ +

Definition at line 397 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_TRANSITION_MASK_PORT30_BIT   6
+
+ +

Definition at line 396 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
#define MAX6956_TRANSITION_STATUS_BIT   7
+
+ +

INT Status, INT is automatically cleared after it is read.

+ +

Definition at line 393 of file MAX6956.h.

+ +
+
+
+ + + + diff --git a/Arduino/MAX6956/html/MAX6956_8h_source.html b/Arduino/MAX6956/html/MAX6956_8h_source.html new file mode 100644 index 00000000..e9f7f927 --- /dev/null +++ b/Arduino/MAX6956/html/MAX6956_8h_source.html @@ -0,0 +1,446 @@ + + + + + + +MAX6956: MAX6956.h Source File + + + + + + + + + +
+
+ + + + + + +
+
MAX6956 +  1.0 +
+
MAX6956i2Clibrary
+
+
+ + + + + +
+ + + + +
+ +
+ +
+
+
MAX6956.h
+
+
+Go to the documentation of this file.
1 // I2Cdev library collection - MAX6956 I2C device class header file
+
2 // Based on Maxim MAX6956 datasheet 19-2414; Rev 4; 6/10
+
3 //
+
4 // 2013-12-15 by Tom Beighley <tomthegeek@gmail.com>
+
5 // I2C Device Library hosted at http://www.i2cdevlib.com
+
6 //
+
7 // Changelog:
+
8 // 2013-12-15 - initial release
+
9 //
+
10 
+
11 /* ============================================
+
12 I2Cdev device library code is placed under the MIT license
+
13 Copyright (c) 2013 Tom Beighley
+
14 
+
15 Permission is hereby granted, free of charge, to any person obtaining a copy
+
16 of this software and associated documentation files (the "Software"), to deal
+
17 in the Software without restriction, including without limitation the rights
+
18 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+
19 copies of the Software, and to permit persons to whom the Software is
+
20 furnished to do so, subject to the following conditions:
+
21 
+
22 The above copyright notice and this permission notice shall be included in
+
23 all copies or substantial portions of the Software.
+
24 
+
25 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+
26 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+
27 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+
28 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+
29 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+
30 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+
31 THE SOFTWARE.
+
32 ===============================================
+
33 */
+
34 
+
35 #ifndef _MAX6956_H_
+
36 #define _MAX6956_H_
+
37 
+
38 #include "I2Cdev.h"
+
39 
+
40 // -----------------------------------------------------------------------------
+
41 // Arduino-style "Serial.print" debug constant (uncomment to enable)
+
42 // -----------------------------------------------------------------------------
+
43 // #define MAX6956_SERIAL_DEBUG
+
44 
+
71 #define MAX6956_ADDRESS 0x40 // See table 3
+
72 #define MAX6956_DEFAULT_ADDRESS 0x40 // AD0 and AD1 at ground.
+
73 
+
74 //==========Registers==========
+
75 
+
76 #define MAX6956_RA_NO_OP 0x00
+
77 
+
78 
+
102 #define MAX6956_RA_GLOBAL_CURRENT 0x02
+
103 
+
137 #define MAX6956_RA_CONFIGURATION 0x04
+
138 
+
152 #define MAX6956_RA_TRANSITION_DETECT 0x06
+
153 
+
165 #define MAX6956_RA_DISPLAY_TEST 0x07
+
166 
+
203 #define MAX6956_RA_CONFIG_P7P6P5P4 0x09
+
204 #define MAX6956_RA_CONFIG_P11P10P9P8 0x0A
+
205 #define MAX6956_RA_CONFIG_P15P14P13P12 0x0B
+
206 #define MAX6956_RA_CONFIG_P19P18P17P16 0x0C
+
207 #define MAX6956_RA_CONFIG_P23P22P21P20 0x0D
+
208 #define MAX6956_RA_CONFIG_P27P26P25P24 0x0E
+
209 #define MAX6956_RA_CONFIG_P31P30P29P28 0x0F
+
210 
+
241 #define MAX6956_RA_CURRENT_0xP5P4 0x12
+
242 #define MAX6956_RA_CURRENT_0xP7P6 0x13
+
243 #define MAX6956_RA_CURRENT_0xP9P8 0x14
+
244 #define MAX6956_RA_CURRENT_0xP11P10 0x15
+
245 #define MAX6956_RA_CURRENT_0xP13P12 0x16
+
246 #define MAX6956_RA_CURRENT_0xP15P14 0x17
+
247 #define MAX6956_RA_CURRENT_0xP17P16 0x18
+
248 #define MAX6956_RA_CURRENT_0xP19P18 0x19
+
249 #define MAX6956_RA_CURRENT_0xP21P20 0x1A
+
250 #define MAX6956_RA_CURRENT_0xP23P22 0x1B
+
251 #define MAX6956_RA_CURRENT_0xP25P24 0x1C
+
252 #define MAX6956_RA_CURRENT_0xP27P26 0x1D
+
253 #define MAX6956_RA_CURRENT_0xP29P28 0x1E
+
254 #define MAX6956_RA_CURRENT_0xP31P30 0x1F
+
255 
+
262 #define MAX6956_RA_PORT0 0x20
+
263 #define MAX6956_RA_PORT1 0x21
+
264 #define MAX6956_RA_PORT2 0x22
+
265 #define MAX6956_RA_PORT3 0x23
+
266 
+
267 #define MAX6956_RA_PORT4 0x24
+
268 #define MAX6956_RA_PORT5 0x25
+
269 #define MAX6956_RA_PORT6 0x26
+
270 #define MAX6956_RA_PORT7 0x27
+
271 #define MAX6956_RA_PORT8 0x28
+
272 #define MAX6956_RA_PORT9 0x29
+
273 #define MAX6956_RA_PORT10 0x2A
+
274 #define MAX6956_RA_PORT11 0x2B
+
275 
+
276 #define MAX6956_RA_PORT12 0x2C
+
277 #define MAX6956_RA_PORT13 0x2D
+
278 #define MAX6956_RA_PORT14 0x2E
+
279 #define MAX6956_RA_PORT15 0x2F
+
280 #define MAX6956_RA_PORT16 0x30
+
281 #define MAX6956_RA_PORT17 0x31
+
282 #define MAX6956_RA_PORT18 0x32
+
283 #define MAX6956_RA_PORT19 0x33
+
284 
+
285 #define MAX6956_RA_PORT20 0x34
+
286 #define MAX6956_RA_PORT21 0x35
+
287 #define MAX6956_RA_PORT22 0x36
+
288 #define MAX6956_RA_PORT23 0x37
+
289 #define MAX6956_RA_PORT24 0x38
+
290 #define MAX6956_RA_PORT25 0x39
+
291 #define MAX6956_RA_PORT26 0x3A
+
292 #define MAX6956_RA_PORT27 0x3B
+
293 
+
294 #define MAX6956_RA_PORT28 0x3C
+
295 #define MAX6956_RA_PORT29 0x3D
+
296 #define MAX6956_RA_PORT30 0x3E
+
297 #define MAX6956_RA_PORT31 0x3F
+
298 /*
+
299  Lower port groups
+
300 */
+
301 #define MAX6956_RA_PORTS4_7 0x40
+
302 #define MAX6956_RA_PORTS4_8 0x41
+
303 #define MAX6956_RA_PORTS4_9 0x42
+
304 #define MAX6956_RA_PORTS4_10 0x43
+
305 
+
306 /*
+
307  8 port registers. Data bits D0-D7
+
308 */
+
309 #define MAX6956_RA_PORTS4_11 0x44
+
310 #define MAX6956_RA_PORTS5_12 0x45
+
311 #define MAX6956_RA_PORTS6_13 0x46
+
312 #define MAX6956_RA_PORTS7_14 0x47
+
313 #define MAX6956_RA_PORTS8_15 0x48
+
314 #define MAX6956_RA_PORTS9_16 0x49
+
315 #define MAX6956_RA_PORTS10_17 0x4A
+
316 #define MAX6956_RA_PORTS11_18 0x4B
+
317 #define MAX6956_RA_PORTS12_19 0x4C
+
318 #define MAX6956_RA_PORTS13_20 0x4D
+
319 #define MAX6956_RA_PORTS14_21 0x4E
+
320 #define MAX6956_RA_PORTS15_22 0x4F
+
321 #define MAX6956_RA_PORTS16_23 0x50
+
322 #define MAX6956_RA_PORTS17_24 0x51
+
323 #define MAX6956_RA_PORTS18_25 0x52
+
324 #define MAX6956_RA_PORTS19_26 0x53
+
325 #define MAX6956_RA_PORTS20_27 0x54
+
326 #define MAX6956_RA_PORTS21_28 0x55
+
327 #define MAX6956_RA_PORTS22_29 0x56
+
328 #define MAX6956_RA_PORTS23_30 0x57
+
329 #define MAX6956_RA_PORTS24_31 0x58
+
330 /*
+
331  Upper port groups
+
332 */
+
333 #define MAX6956_RA_PORTS25_31 0x59
+
334 #define MAX6956_RA_PORTS26_31 0x5A
+
335 #define MAX6956_RA_PORTS27_31 0x5B
+
336 #define MAX6956_RA_PORTS28_31 0x5C
+
337 #define MAX6956_RA_PORTS29_31 0x5D
+
338 #define MAX6956_RA_PORTS30_31 0x5E
+
339 #define MAX6956_RA_PORTS31_31 0x5F
+
340 
+
341 //=========Config bits=========
+
342 
+
343 #define MAX6956_CONFIG_POWER_BIT 0
+
344 #define MAX6956_CONFIG_GLOBAL_CURRENT_BIT 6
+
345 #define MAX6956_CONFIG_TRANSITION_BIT 7
+
346 
+
347 #define MAX6956_GLOBAL_CURRENT_BIT 0
+
348 #define MAX6956_GLOBAL_CURRENT_LENGTH 4
+
349 
+
350 #define MAX6956_PORT12_CURRENT_BIT 3
+
351 #define MAX6956_PORT12_CURRENT_LENGTH 4
+
352 #define MAX6956_PORT13_CURRENT_BIT 7
+
353 #define MAX6956_PORT13_CURRENT_LENGTH 4
+
354 #define MAX6956_PORT14_CURRENT_BIT 3
+
355 #define MAX6956_PORT14_CURRENT_LENGTH 4
+
356 #define MAX6956_PORT15_CURRENT_BIT 7
+
357 #define MAX6956_PORT15_CURRENT_LENGTH 4
+
358 #define MAX6956_PORT16_CURRENT_BIT 3
+
359 #define MAX6956_PORT16_CURRENT_LENGTH 4
+
360 #define MAX6956_PORT17_CURRENT_BIT 7
+
361 #define MAX6956_PORT17_CURRENT_LENGTH 4
+
362 #define MAX6956_PORT18_CURRENT_BIT 3
+
363 #define MAX6956_PORT18_CURRENT_LENGTH 4
+
364 #define MAX6956_PORT19_CURRENT_BIT 7
+
365 #define MAX6956_PORT19_CURRENT_LENGTH 4
+
366 #define MAX6956_PORT23_CURRENT_BIT 3
+
367 #define MAX6956_PORT23_CURRENT_LENGTH 4
+
368 #define MAX6956_PORT21_CURRENT_BIT 7
+
369 #define MAX6956_PORT21_CURRENT_LENGTH 4
+
370 #define MAX6956_PORT22_CURRENT_BIT 3
+
371 #define MAX6956_PORT22_CURRENT_LENGTH 4
+
372 #define MAX6956_PORT23_CURRENT_BIT 7
+
373 #define MAX6956_PORT23_CURRENT_LENGTH 4
+
374 #define MAX6956_PORT24_CURRENT_BIT 3
+
375 #define MAX6956_PORT24_CURRENT_LENGTH 4
+
376 #define MAX6956_PORT25_CURRENT_BIT 7
+
377 #define MAX6956_PORT25_CURRENT_LENGTH 4
+
378 #define MAX6956_PORT26_CURRENT_BIT 3
+
379 #define MAX6956_PORT26_CURRENT_LENGTH 4
+
380 #define MAX6956_PORT27_CURRENT_BIT 7
+
381 #define MAX6956_PORT27_CURRENT_LENGTH 4
+
382 #define MAX6956_PORT28_CURRENT_BIT 3
+
383 #define MAX6956_PORT28_CURRENT_LENGTH 4
+
384 #define MAX6956_PORT29_CURRENT_BIT 7
+
385 #define MAX6956_PORT29_CURRENT_LENGTH 4
+
386 #define MAX6956_PORT33_CURRENT_BIT 3
+
387 #define MAX6956_PORT33_CURRENT_LENGTH 4
+
388 #define MAX6956_PORT31_CURRENT_BIT 7
+
389 #define MAX6956_PORT31_CURRENT_LENGTH 4
+
390 
+
391 #define MAX6956_DISPLAY_TEST_BIT 0
+
392 
+
393 #define MAX6956_TRANSITION_STATUS_BIT 7
+
394 #define MAX6956_TRANSITION_MASK_BIT 0
+
395 #define MAX6956_TRANSITION_MASK_LENGTH 7
+
396 #define MAX6956_TRANSITION_MASK_PORT30_BIT 6
+
397 #define MAX6956_TRANSITION_MASK_PORT29_BIT 5
+
398 #define MAX6956_TRANSITION_MASK_PORT28_BIT 4
+
399 #define MAX6956_TRANSITION_MASK_PORT27_BIT 3
+
400 #define MAX6956_TRANSITION_MASK_PORT26_BIT 2
+
401 #define MAX6956_TRANSITION_MASK_PORT25_BIT 1
+
402 #define MAX6956_TRANSITION_MASK_PORT24_BIT 0
+
403 
+
404 //=========Values=========
+
405 
+
406 #define MAX6956_OUTPUT_LED 0x00
+
407 #define MAX6956_OUTPUT_GPIO 0x01
+
408 #define MAX6956_INPUT_WO_PULL 0x02
+
409 #define MAX6956_INPUT_W_PULL 0x03
+
410 
+
411 #define MAX6956_OFF 0x00
+
412 #define MAX6956_ON 0x01
+
413 
+
414 #define MAX6956_CURRENT_0 0x00
+
415 #define MAX6956_CURRENT_1 0x01
+
416 #define MAX6956_CURRENT_2 0x02
+
417 #define MAX6956_CURRENT_3 0x03
+
418 #define MAX6956_CURRENT_4 0x04
+
419 #define MAX6956_CURRENT_5 0x05
+
420 #define MAX6956_CURRENT_6 0x06
+
421 #define MAX6956_CURRENT_7 0x07
+
422 #define MAX6956_CURRENT_8 0x08
+
423 #define MAX6956_CURRENT_9 0x09
+
424 #define MAX6956_CURRENT_10 0x0A
+
425 #define MAX6956_CURRENT_11 0x0B
+
426 #define MAX6956_CURRENT_12 0x0C
+
427 #define MAX6956_CURRENT_13 0x0D
+
428 #define MAX6956_CURRENT_14 0x0E
+
429 #define MAX6956_CURRENT_15 0x0F
+
430 
+
456 class MAX6956 {
+
457  public:
+
458  MAX6956();
+
459  MAX6956(uint8_t address);
+
460 
+
461  void initialize();
+
462  bool testConnection();
+
463 
+
464  void reset();
+
465 
+
466  // Config register
+
467  uint8_t getConfigReg();
+
468  void setConfigReg(uint8_t config);
+
469 
+
470  bool getPower();
+
471  void togglePower();
+
472  void setPower(bool power);
+
473 
+ +
475  void setEnableIndividualCurrent(bool global);
+
476 
+ +
478  void setEnableTransitionDetection(bool transition);
+
479 
+
480  // Global current
+
481  uint8_t getGlobalCurrent();
+
482  void setGlobalCurrent(uint8_t current);
+
483 
+
484  // Test mode
+
485  bool getTestMode();
+
486  void setTestMode(bool test);
+
487 
+
488  // Input mask
+
489  uint8_t getInputMask();
+
490  void setInputMask(uint8_t mask);
+
491 
+
492  // Port config
+
493  void configPort(uint8_t port, uint8_t portConfig);
+
494  void configPorts(uint8_t lower, uint8_t upper, uint8_t portConfig);
+
495  void configAllPorts(uint8_t portConfig);
+
496 
+
497  void setPortLevel(uint8_t port, uint8_t power);
+
498  void setPortCurrent(uint8_t port, uint8_t power);
+
499  void setAllPortsCurrent(uint8_t power);
+
500  void enableAllPorts();
+
501  void disableAllPorts();
+
502 
+
527  uint8_t portsConfig[5];
+
552  uint8_t portsStatus[3];
+
553 
+
554  private:
+
555  uint8_t devAddr;
+
556  uint8_t buffer[1];
+
557  uint8_t portConfig;
+
558  uint8_t portCurrentRA;
+
559  uint8_t portCurrentBit;
+
560  uint8_t psArrayIndex;
+
561  uint8_t psBitPosition;
+
562 };
+
563 
+
564 #endif /* _MAX6956_H_ */
+
uint8_t devAddr
Holds the current device address.
Definition: MAX6956.h:555
+
uint8_t portCurrentRA
Holder for port current register.
Definition: MAX6956.h:558
+
uint8_t psArrayIndex
array index
Definition: MAX6956.h:560
+
void enableAllPorts()
Definition: MAX6956.cpp:453
+
bool getEnableTransitionDetection()
Definition: MAX6956.cpp:152
+
uint8_t getInputMask()
Definition: MAX6956.cpp:205
+
void disableAllPorts()
Definition: MAX6956.cpp:463
+
bool getEnableIndividualCurrent()
Definition: MAX6956.cpp:134
+
void setPower(bool power)
Definition: MAX6956.cpp:118
+
void configPort(uint8_t port, uint8_t portConfig)
Definition: MAX6956.cpp:265
+
void setAllPortsCurrent(uint8_t power)
0-15, 0 = min brightness (not off) 15 = max
Definition: MAX6956.cpp:444
+
void configPorts(uint8_t lower, uint8_t upper, uint8_t portConfig)
Definition: MAX6956.cpp:285
+
uint8_t portsConfig[5]
Definition: MAX6956.h:527
+
uint8_t getGlobalCurrent()
Definition: MAX6956.cpp:171
+
bool getTestMode()
Definition: MAX6956.cpp:188
+
uint8_t psBitPosition
bit position
Definition: MAX6956.h:561
+
uint8_t portsStatus[3]
Definition: MAX6956.h:552
+
void initialize()
Definition: MAX6956.cpp:54
+
void setConfigReg(uint8_t config)
Definition: MAX6956.cpp:102
+
bool getPower()
Definition: MAX6956.cpp:110
+
void configAllPorts(uint8_t portConfig)
Definition: MAX6956.cpp:332
+
void setEnableTransitionDetection(bool transition)
Definition: MAX6956.cpp:162
+
void setEnableIndividualCurrent(bool global)
Definition: MAX6956.cpp:144
+
void setPortCurrent(uint8_t port, uint8_t power)
0-15 brightness levels.
Definition: MAX6956.cpp:404
+
uint8_t portCurrentBit
Holder for the current bit offset.
Definition: MAX6956.h:559
+
void setPortLevel(uint8_t port, uint8_t power)
0 = off, 1-15 brightness levels.
Definition: MAX6956.cpp:346
+
MAX6956()
Definition: MAX6956.cpp:40
+
uint8_t buffer[1]
Buffer for reading data from the device.
Definition: MAX6956.h:556
+
void setGlobalCurrent(uint8_t current)
Definition: MAX6956.cpp:179
+
void reset()
Definition: MAX6956.cpp:80
+
bool testConnection()
Definition: MAX6956.cpp:72
+
void setTestMode(bool test)
Definition: MAX6956.cpp:196
+
void togglePower()
Definition: MAX6956.cpp:124
+
uint8_t portConfig
Holder for port config bit pair.
Definition: MAX6956.h:557
+ +
void setInputMask(uint8_t mask)
Definition: MAX6956.cpp:214
+
uint8_t getConfigReg()
Definition: MAX6956.cpp:94
+
+ + + + diff --git a/Arduino/MAX6956/html/annotated.html b/Arduino/MAX6956/html/annotated.html new file mode 100644 index 00000000..6f25f18e --- /dev/null +++ b/Arduino/MAX6956/html/annotated.html @@ -0,0 +1,101 @@ + + + + + + +MAX6956: Data Structures + + + + + + + + + +
+
+ + + + + + +
+
MAX6956 +  1.0 +
+
MAX6956i2Clibrary
+
+
+ + + + + +
+ + + + +
+ +
+ +
+
+
Data Structures
+
+
+
Here are the data structures with brief descriptions:
+ + +
\CMAX6956
+
+
+ + + + diff --git a/Arduino/MAX6956/html/bc_s.png b/Arduino/MAX6956/html/bc_s.png new file mode 100644 index 0000000000000000000000000000000000000000..224b29aa9847d5a4b3902efd602b7ddf7d33e6c2 GIT binary patch literal 676 zcmV;V0$crwP)y__>=_9%My z{n931IS})GlGUF8K#6VIbs%684A^L3@%PlP2>_sk`UWPq@f;rU*V%rPy_ekbhXT&s z(GN{DxFv}*vZp`F>S!r||M`I*nOwwKX+BC~3P5N3-)Y{65c;ywYiAh-1*hZcToLHK ztpl1xomJ+Yb}K(cfbJr2=GNOnT!UFA7Vy~fBz8?J>XHsbZoDad^8PxfSa0GDgENZS zuLCEqzb*xWX2CG*b&5IiO#NzrW*;`VC9455M`o1NBh+(k8~`XCEEoC1Ybwf;vr4K3 zg|EB<07?SOqHp9DhLpS&bzgo70I+ghB_#)K7H%AMU3v}xuyQq9&Bm~++VYhF09a+U zl7>n7Jjm$K#b*FONz~fj;I->Bf;ule1prFN9FovcDGBkpg>)O*-}eLnC{6oZHZ$o% zXKW$;0_{8hxHQ>l;_*HATI(`7t#^{$(zLe}h*mqwOc*nRY9=?Sx4OOeVIfI|0V(V2 zBrW#G7Ss9wvzr@>H*`r>zE z+e8bOBgqIgldUJlG(YUDviMB`9+DH8n-s9SXRLyJHO1!=wY^79WYZMTa(wiZ!zP66 zA~!21vmF3H2{ngD;+`6j#~6j;$*f*G_2ZD1E;9(yaw7d-QnSCpK(cR1zU3qU0000< KMNUMnLSTYoA~SLT literal 0 HcmV?d00001 diff --git a/Arduino/MAX6956/html/bdwn.png b/Arduino/MAX6956/html/bdwn.png new file mode 100644 index 0000000000000000000000000000000000000000..940a0b950443a0bb1b216ac03c45b8a16c955452 GIT binary patch literal 147 zcmeAS@N?(olHy`uVBq!ia0vp^>_E)H!3HEvS)PKZC{Gv1kP61Pb5HX&C2wk~_T + + + + + +MAX6956: MAX6956 Class Reference + + + + + + + + + +
+
+ + + + + + +
+
MAX6956 +  1.0 +
+
MAX6956i2Clibrary
+
+
+ + + + + + + + + +
+ +
+ +
+
+ +
+
MAX6956 Class Reference
+
+
+ +

#include <MAX6956.h>

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 MAX6956 ()
 
 MAX6956 (uint8_t address)
 
void initialize ()
 
bool testConnection ()
 
void reset ()
 
uint8_t getConfigReg ()
 
void setConfigReg (uint8_t config)
 
bool getPower ()
 
void togglePower ()
 
void setPower (bool power)
 
bool getEnableIndividualCurrent ()
 
void setEnableIndividualCurrent (bool global)
 
bool getEnableTransitionDetection ()
 
void setEnableTransitionDetection (bool transition)
 
uint8_t getGlobalCurrent ()
 
void setGlobalCurrent (uint8_t current)
 
bool getTestMode ()
 
void setTestMode (bool test)
 
uint8_t getInputMask ()
 
void setInputMask (uint8_t mask)
 
void configPort (uint8_t port, uint8_t portConfig)
 
void configPorts (uint8_t lower, uint8_t upper, uint8_t portConfig)
 
void configAllPorts (uint8_t portConfig)
 
void setPortLevel (uint8_t port, uint8_t power)
 0 = off, 1-15 brightness levels. More...
 
void setPortCurrent (uint8_t port, uint8_t power)
 0-15 brightness levels. More...
 
void setAllPortsCurrent (uint8_t power)
 0-15, 0 = min brightness (not off) 15 = max More...
 
void enableAllPorts ()
 
void disableAllPorts ()
 
+ + + + + +

+Data Fields

uint8_t portsConfig [5]
 
uint8_t portsStatus [3]
 
+ + + + + + + + + + + + + + + + + + + + + + +

+Private Attributes

uint8_t devAddr
 Holds the current device address. More...
 
uint8_t buffer [1]
 Buffer for reading data from the device. More...
 
uint8_t portConfig
 Holder for port config bit pair. More...
 
uint8_t portCurrentRA
 Holder for port current register. More...
 
uint8_t portCurrentBit
 Holder for the current bit offset. More...
 
uint8_t psArrayIndex
 array index More...
 
uint8_t psBitPosition
 bit position More...
 
+

Detailed Description

+

A library for controlling the MAX6956 using i2C.

+

The MAX6956 compact, serial-interfaced LED display driver/I/O expander provide microprocessors with up to 28 ports. Each port is individually user configurable to either a logic input, logic output, or common-anode (CA) LED constant-current segment driver. Each port configured as an LED segment driver behaves as a digitally controlled constant-current sink, with 16 equal current steps from 1.5mA to 24mA. The LED drivers are suitable for both discrete LEDs and CA numeric and alphanumeric LED digits.

+

Each port configured as a general-purpose I/O (GPIO) can be either a push-pull logic output capable of sink- ing 10mA and sourcing 4.5mA, or a Schmitt logic input with optional internal pullup. Seven ports feature config- urable transition detection logic, which generates an interrupt upon change of port logic level. The MAX6956 is controlled through an I2C-compatible 2-wire serial interface, and uses four-level logic to allow 16 I 2C addresses from only 2 select pins.

+

The MAX6956AAX and MAX6956ATL have 28 ports and are available in 36-pin SSOP and 40-pin thin QFN packages, respectively. The MAX6956AAI and MAX6956ANI have 20 ports and are available in 28-pin SSOP and 28-pin DIP packages, respectively.

+

For an SPI-interfaced version, refer to the MAX6957 data sheet. For a lower cost pin-compatible port expander without the constant-current LED drive capa- bility, refer to the MAX7300 data sheet.

+
    +
  • 400kbps I2C-Compatible Serial Interface
  • +
  • 2.5V to 5.5V Operation
  • +
  • -40°C to +125°C Temperature Range
  • +
  • 20 or 28 I/O Ports, Each Configurable as
  • +
  • Constant-Current LED Driver
  • +
  • Push-Pull Logic Output
  • +
  • Schmitt Logic Input
  • +
  • Schmitt Logic Input with Internal Pullup
  • +
  • 11μA (max) Shutdown Current
  • +
  • 16-Step Individually Programmable Current
  • +
  • Control for Each LED
  • +
  • Logic Transition Detection for Seven I/O Ports
  • +
+ +

Definition at line 456 of file MAX6956.h.

+

Constructor & Destructor Documentation

+ +
+
+ + + + + + + +
MAX6956::MAX6956 ()
+
+

Default constructor, uses default I2C address.

+
See Also
MAX6956_DEFAULT_ADDRESS
+ +

Definition at line 40 of file MAX6956.cpp.

+ +
+
+ +
+
+ + + + + + + + +
MAX6956::MAX6956 (uint8_t address)
+
+

Specific address constructor.

+
Parameters
+ + +
addressI2C address
+
+
+
See Also
MAX6956_DEFAULT_ADDRESS
+
+MAX6956_ADDRESS
+ +

Definition at line 49 of file MAX6956.cpp.

+ +
+
+

Member Function Documentation

+ +
+
+ + + + + + + + +
void MAX6956::configAllPorts (uint8_t portConfig)
+
+
Configure all ports the same
+
Parameters
+ + +
portConfigValid options are: MAX6956_OUTPUT_LED, MAX6956_OUTPUT_GPIO, MAX6956_INPUT_WO_PULL, MAX6956_INPUT_W_PULL
+
+
+
See Also
MAX6956_OUTPUT_LED
+
+MAX6956_OUTPUT_GPIO
+
+MAX6956_INPUT_WO_PULL
+
+MAX6956_INPUT_W_PULL
+ +

Definition at line 332 of file MAX6956.cpp.

+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
void MAX6956::configPort (uint8_t port,
uint8_t portConfig 
)
+
+
Takes an INDIVIDUAL port register address (MAX6956_RA_PORT12, ect)
+and configures it as: MAX6956_OUTPUT_LED, MAX6956_OUTPUT_GPIO,
+MAX6956_INPUT_WO_PULL, or MAX6956_INPUT_W_PULL
+

Port registers

+ + + + + + + + + + + + + + + + + +
Addr. Name
0x09 MAX6956_RA_CONFIG_P7P6P5P4
0x0A MAX6956_RA_CONFIG_P11P10P9P8
0x0B MAX6956_RA_CONFIG_P15P14P13P12
0x0C MAX6956_RA_CONFIG_P19P18P17P16
0x0D MAX6956_RA_CONFIG_P23P22P21P20
0x0E MAX6956_RA_CONFIG_P27P26P25P24
0x0F MAX6956_RA_CONFIG_P31P30P29P28
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NumDecHex PrtPort Status ArrayPorts Config Array
00 44 0x2CP12portsStatus[0][0]portsConfig[0][1-0]
01 45 0x2DP13portsStatus[0][1]portsConfig[0][3-2]
02 46 0x2EP14portsStatus[0][2]portsConfig[0][5-4]
03 47 0x2FP15portsStatus[0][3]portsConfig[0][7-6]
04 48 0x30P16portsStatus[0][4]portsConfig[1][1-0]
05 49 0x31P17portsStatus[0][5]portsConfig[1][3-2]
06 50 0x32P18portsStatus[0][6]portsConfig[1][5-4]
07 51 0x33P19portsStatus[0][7]portsConfig[1][7-6]
08 52 0x34P20portsStatus[1][0]portsConfig[2][1-0]
09 53 0x35P21portsStatus[1][1]portsConfig[2][3-2]
10 54 0x36P22portsStatus[1][2]portsConfig[2][5-4]
11 55 0x37P23portsStatus[1][3]portsConfig[2][7-6]
12 56 0x38P24portsStatus[1][4]portsConfig[3][1-0]
13 57 0x39P25portsStatus[1][5]portsConfig[3][3-2]
14 58 0x3AP26portsStatus[1][6]portsConfig[3][5-4]
15 59 0x3BP27portsStatus[1][7]portsConfig[3][7-6]
16 60 0x3CP28portsStatus[2][0]portsConfig[4][1-0]
17 61 0x3DP29portsStatus[2][1]portsConfig[4][3-2]
18 62 0x3EP30portsStatus[2][2]portsConfig[4][5-4]
19 63 0x3FP31portsStatus[2][3]portsConfig[4][7-6]
+
Parameters
+ + + +
portPort register address (MAX6956_RA_PORT12, ect)
portConfigValid options are: MAX6956_OUTPUT_LED, MAX6956_OUTPUT_GPIO, MAX6956_INPUT_WO_PULL, MAX6956_INPUT_W_PULL
+
+
+
See Also
MAX6956_RA_PORT12 MAX6956_RA_PORT13 MAX6956_RA_PORT14 MAX6956_RA_PORT15 MAX6956_RA_PORT16 MAX6956_RA_PORT17 MAX6956_RA_PORT18 MAX6956_RA_PORT19 MAX6956_RA_PORT20 MAX6956_RA_PORT21 MAX6956_RA_PORT22 MAX6956_RA_PORT23 MAX6956_RA_PORT24 MAX6956_RA_PORT25 MAX6956_RA_PORT26 MAX6956_RA_PORT27 MAX6956_RA_PORT28 MAX6956_RA_PORT29 MAX6956_RA_PORT30 MAX6956_RA_PORT31
+
+MAX6956_OUTPUT_LED MAX6956_OUTPUT_GPIO MAX6956_INPUT_WO_PULL MAX6956_INPUT_W_PULL
+ +

Definition at line 265 of file MAX6956.cpp.

+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void MAX6956::configPorts (uint8_t lower,
uint8_t upper,
uint8_t portConfig 
)
+
+

Configure consecutive range of ports

+
Parameters
+ + + + +
lowerLower port register address (MAX6956_RA_PORT12, ect)
upperUpper port register address (MAX6956_RA_PORT12, ect)
portConfigValid options are: MAX6956_OUTPUT_LED, MAX6956_OUTPUT_GPIO, MAX6956_INPUT_WO_PULL, MAX6956_INPUT_W_PULL
+
+
+
See Also
MAX6956_OUTPUT_LED
+
+MAX6956_OUTPUT_GPIO
+
+MAX6956_INPUT_WO_PULL
+
+MAX6956_INPUT_W_PULL
+ +

Definition at line 285 of file MAX6956.cpp.

+ +
+
+ +
+
+ + + + + + + +
void MAX6956::disableAllPorts ()
+
+

Write 0's to all port registers.

+ +

Definition at line 463 of file MAX6956.cpp.

+ +
+
+ +
+
+ + + + + + + +
void MAX6956::enableAllPorts ()
+
+

Write 1's to all port registers. This enables ports set as outputs and they will always have some brightness, port must be disabled to turn off completely.

+ +

Definition at line 453 of file MAX6956.cpp.

+ +
+
+ +
+
+ + + + + + + +
uint8_t MAX6956::getConfigReg ()
+
+
Config register
+
Returns
uint8_t value of register
+
See Also
MAX6956_RA_CONFIGURATION
+ +

Definition at line 94 of file MAX6956.cpp.

+ +
+
+ +
+
+ + + + + + + +
bool MAX6956::getEnableIndividualCurrent ()
+
+
Get transition detection configuration bit 
+
Returns
Boolean value if global current is enabled or not
+
See Also
MAX6956_RA_CONFIGURATION
+ +

Definition at line 134 of file MAX6956.cpp.

+ +
+
+ +
+
+ + + + + + + +
bool MAX6956::getEnableTransitionDetection ()
+
+
Get transition detection configuration bit 
+
Returns
Boolean value if transition detection is enabled or not
+
See Also
MAX6956_RA_CONFIGURATION
+ +

Definition at line 152 of file MAX6956.cpp.

+ +
+
+ +
+
+ + + + + + + +
uint8_t MAX6956::getGlobalCurrent ()
+
+
Get global current 
+
Returns
uint8_t value of register
+
See Also
MAX6956_RA_GLOBAL_CURRENT
+ +

Definition at line 171 of file MAX6956.cpp.

+ +
+
+ +
+
+ + + + + + + +
uint8_t MAX6956::getInputMask ()
+
+
Get the input mask to see which ports have changed. MSB is cleared after every read.
+
Returns
uint8_t value of register
+
See Also
MAX6956_RA_TRANSITION_DETECT
+ +

Definition at line 205 of file MAX6956.cpp.

+ +
+
+ +
+
+ + + + + + + +
bool MAX6956::getPower ()
+
+
Get power configuration bit 
+
Returns
Boolean value if power is enabled or not
+
See Also
MAX6956_RA_CONFIGURATION
+ +

Definition at line 110 of file MAX6956.cpp.

+ +
+
+ +
+
+ + + + + + + +
bool MAX6956::getTestMode ()
+
+
Returns true if test mode is enabled. 
+
Returns
uint8_t value of register
+
See Also
MAX6956_RA_DISPLAY_TEST
+ +

Definition at line 188 of file MAX6956.cpp.

+ +
+
+ +
+
+ + + + + + + +
void MAX6956::initialize ()
+
+

Power on and prepare for general usage.

+
The 28-pin MAX6956ANI and MAX6956AAI make only 20 ports available, P12 to P31.
+

The eight unused ports should be configured as outputs on power-up by writing 0x55 to registers 0x09 and 0x0A. If this is not done,the eight unused ports remain as unconnected inputs and quiescent supply current rises, although there is no damage to the part.

+ +

Definition at line 54 of file MAX6956.cpp.

+ +
+
+ +
+
+ + + + + + + +
void MAX6956::reset ()
+
+

Set registers back to Power-up Configuration

+ +

Definition at line 80 of file MAX6956.cpp.

+ +
+
+ +
+
+ + + + + + + + +
void MAX6956::setAllPortsCurrent (uint8_t power)
+
+ +

0-15, 0 = min brightness (not off) 15 = max

+

Set ALL port current registers (MAX6956_RA_PORT12, ect) to the SAME power level 0-15. 0 is off, 15 is max brightness.

+
Parameters
+ + +
power0 is min, 15 is max brightness.
+
+
+ +

Definition at line 444 of file MAX6956.cpp.

+ +
+
+ +
+
+ + + + + + + + +
void MAX6956::setConfigReg (uint8_t config)
+
+
Set config register
+
Parameters
+ + +
configuint8_t value to set register
+
+
+
See Also
MAX6956_RA_CONFIGURATION
+ +

Definition at line 102 of file MAX6956.cpp.

+ +
+
+ +
+
+ + + + + + + + +
void MAX6956::setEnableIndividualCurrent (bool global)
+
+
Enable or disable global current
+
Parameters
+ + +
globalBoolean value, true enables, false disables individual current
+
+
+
See Also
MAX6956_RA_CONFIGURATION
+
+getGlobalCurrent()
+
+setGlobalCurrent()
+ +

Definition at line 144 of file MAX6956.cpp.

+ +
+
+ +
+
+ + + + + + + + +
void MAX6956::setEnableTransitionDetection (bool transition)
+
+
Enable or disable transition detection. Must be reset after every mask read.
+
Parameters
+ + +
transitionBoolean value, true enables, false disables transition detection
+
+
+
See Also
MAX6956_RA_CONFIGURATION
+
+getInputMask()
+
+setInputMask()
+ +

Definition at line 162 of file MAX6956.cpp.

+ +
+
+ +
+
+ + + + + + + + +
void MAX6956::setGlobalCurrent (uint8_t current)
+
+
Set current globally
+
Parameters
+ + +
currentuint8_t 0-15, 0 = min, 15 = max brightness
+
+
+
See Also
MAX6956_RA_GLOBAL_CURRENT
+ +

Definition at line 179 of file MAX6956.cpp.

+ +
+
+ +
+
+ + + + + + + + +
void MAX6956::setInputMask (uint8_t mask)
+
+
Set the input mask for which ports to monitor with transition detection
+
Parameters
+ + +
mask8 bit value. MSB is ignored.
+
+
+
See Also
MAX6956_RA_TRANSITION_DETECT
+ +

Definition at line 214 of file MAX6956.cpp.

+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
void MAX6956::setPortCurrent (uint8_t port,
uint8_t power 
)
+
+ +

0-15 brightness levels.

+
Takes an INDIVIDUAL port register address (MAX6956_RA_PORT12, ect)
+

and sets it to a power level 0-15. 0 is min, 15 is max brightness.

+
Parameters
+ + + +
portPort register address (MAX6956_RA_PORT12, ect)
power0 is min, 15 is max brightness.
+
+
+ +

Definition at line 404 of file MAX6956.cpp.

+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
void MAX6956::setPortLevel (uint8_t port,
uint8_t power 
)
+
+ +

0 = off, 1-15 brightness levels.

+
Takes an individual port register address (MAX6956_RA_PORT12, ect)
+

and sets it to a power scale where 0 = off.

+
Parameters
+ + + +
portPort register address (MAX6956_RA_PORT12, ect)
power0 is off, 15 is max brightness.
+
+
+ +

Definition at line 346 of file MAX6956.cpp.

+ +
+
+ +
+
+ + + + + + + + +
void MAX6956::setPower (bool power)
+
+
Enable or disable power
+
Parameters
+ + +
powerBoolean value, true enables, false disables power
+
+
+
See Also
MAX6956_RA_CONFIGURATION
+ +

Definition at line 118 of file MAX6956.cpp.

+ +
+
+ +
+
+ + + + + + + + +
void MAX6956::setTestMode (bool test)
+
+
Enable or disable test mode
+
Parameters
+ + +
testBoolean, true enables, false disables
+
+
+
See Also
MAX6956_RA_DISPLAY_TEST
+ +

Definition at line 196 of file MAX6956.cpp.

+ +
+
+ +
+
+ + + + + + + +
bool MAX6956::testConnection ()
+
+

Verify the I2C connection. Make sure the device is connected and responds as expected.

+
Returns
True if connection is valid, false otherwise
+ +

Definition at line 72 of file MAX6956.cpp.

+ +
+
+ +
+
+ + + + + + + +
void MAX6956::togglePower ()
+
+
Toggle power
+
See Also
MAX6956_RA_CONFIGURATION
+ +

Definition at line 124 of file MAX6956.cpp.

+ +
+
+

Field Documentation

+ +
+
+ + + + + +
+ + + + +
uint8_t MAX6956::buffer[1]
+
+private
+
+ +

Buffer for reading data from the device.

+ +

Definition at line 556 of file MAX6956.h.

+ +
+
+ +
+
+ + + + + +
+ + + + +
uint8_t MAX6956::devAddr
+
+private
+
+ +

Holds the current device address.

+ +

Definition at line 555 of file MAX6956.h.

+ +
+
+ +
+
+ + + + + +
+ + + + +
uint8_t MAX6956::portConfig
+
+private
+
+ +

Holder for port config bit pair.

+ +

Definition at line 557 of file MAX6956.h.

+ +
+
+ +
+
+ + + + + +
+ + + + +
uint8_t MAX6956::portCurrentBit
+
+private
+
+ +

Holder for the current bit offset.

+ +

Definition at line 559 of file MAX6956.h.

+ +
+
+ +
+
+ + + + + +
+ + + + +
uint8_t MAX6956::portCurrentRA
+
+private
+
+ +

Holder for port current register.

+ +

Definition at line 558 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
uint8_t MAX6956::portsConfig[5]
+
+

Array that mirrors the configuration of all the ports.

+

P12 = portsConfig[0][1-0] P13 = portsConfig[0][3-2] P14 = portsConfig[0][5-4] P15 = portsConfig[0][7-6] P16 = portsConfig[1][1-0] P17 = portsConfig[1][3-2] P18 = portsConfig[1][5-4] P19 = portsConfig[1][7-6] P20 = portsConfig[2][1-0] P21 = portsConfig[2][3-2] P22 = portsConfig[2][5-4] P23 = portsConfig[2][7-6] P24 = portsConfig[3][1-0] P25 = portsConfig[3][3-2] P26 = portsConfig[3][5-4] P27 = portsConfig[3][7-6] P28 = portsConfig[4][1-0] P29 = portsConfig[4][3-2] P30 = portsConfig[4][5-4] P31 = portsConfig[4][7-6]

+ +

Definition at line 527 of file MAX6956.h.

+ +
+
+ +
+
+ + + + +
uint8_t MAX6956::portsStatus[3]
+
+

Array that mirrors the on/off status of all the ports.

+

P12 = portsStatus[0][0] P13 = portsStatus[0][1] P14 = portsStatus[0][2] P15 = portsStatus[0][3] P16 = portsStatus[0][4] P17 = portsStatus[0][5] P18 = portsStatus[0][6] P19 = portsStatus[0][7] P20 = portsStatus[1][0] P21 = portsStatus[1][1] P22 = portsStatus[1][2] P23 = portsStatus[1][3] P24 = portsStatus[1][4] P25 = portsStatus[1][5] P26 = portsStatus[1][6] P27 = portsStatus[1][7] P28 = portsStatus[2][0] P29 = portsStatus[2][1] P30 = portsStatus[2][2] P31 = portsStatus[2][3]

+ +

Definition at line 552 of file MAX6956.h.

+ +
+
+ +
+
+ + + + + +
+ + + + +
uint8_t MAX6956::psArrayIndex
+
+private
+
+ +

array index

+ +

Definition at line 560 of file MAX6956.h.

+ +
+
+ +
+
+ + + + + +
+ + + + +
uint8_t MAX6956::psBitPosition
+
+private
+
+ +

bit position

+ +

Definition at line 561 of file MAX6956.h.

+ +
+
+
The documentation for this class was generated from the following files: +
+ + + + diff --git a/Arduino/MAX6956/html/classes.html b/Arduino/MAX6956/html/classes.html new file mode 100644 index 00000000..8aab2b55 --- /dev/null +++ b/Arduino/MAX6956/html/classes.html @@ -0,0 +1,105 @@ + + + + + + +MAX6956: Data Structure Index + + + + + + + + + +
+
+ + + + + + +
+
MAX6956 +  1.0 +
+
MAX6956i2Clibrary
+
+
+ + + + + +
+ + + + +
+ +
+ +
+
+
Data Structure Index
+
+
+ + + + + + +
  M  
+
MAX6956   
+ +
+ + + + diff --git a/Arduino/MAX6956/html/closed.png b/Arduino/MAX6956/html/closed.png new file mode 100644 index 0000000000000000000000000000000000000000..98cc2c909da37a6df914fbf67780eebd99c597f5 GIT binary patch literal 132 zcmeAS@N?(olHy`uVBq!ia0vp^oFL4>1|%O$WD@{V-kvUwAr*{o@8{^CZMh(5KoB^r_<4^zF@3)Cp&&t3hdujKf f*?bjBoY!V+E))@{xMcbjXe@)LtDnm{r-UW|*e5JT literal 0 HcmV?d00001 diff --git a/Arduino/MAX6956/html/doxygen.css b/Arduino/MAX6956/html/doxygen.css new file mode 100644 index 00000000..4699e697 --- /dev/null +++ b/Arduino/MAX6956/html/doxygen.css @@ -0,0 +1,1357 @@ +/* The standard CSS for doxygen 1.8.5 */ + +body, table, div, p, dl { + font: 400 14px/22px Roboto,sans-serif; +} + +/* @group Heading Levels */ + +h1.groupheader { + font-size: 150%; +} + +.title { + font: 400 14px/28px Roboto,sans-serif; + font-size: 150%; + font-weight: bold; + margin: 10px 2px; +} + +h2.groupheader { + border-bottom: 1px solid #879ECB; + color: #354C7B; + font-size: 150%; + font-weight: normal; + margin-top: 1.75em; + padding-top: 8px; + padding-bottom: 4px; + width: 100%; +} + +h3.groupheader { + font-size: 100%; +} + +h1, h2, h3, h4, h5, h6 { + -webkit-transition: text-shadow 0.5s linear; + -moz-transition: text-shadow 0.5s linear; + -ms-transition: text-shadow 0.5s linear; + -o-transition: text-shadow 0.5s linear; + transition: text-shadow 0.5s linear; + margin-right: 15px; +} + +h1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow { + text-shadow: 0 0 15px cyan; +} + +dt { + font-weight: bold; +} + +div.multicol { + -moz-column-gap: 1em; + -webkit-column-gap: 1em; + -moz-column-count: 3; + -webkit-column-count: 3; +} + +p.startli, p.startdd, p.starttd { + margin-top: 2px; +} + +p.endli { + margin-bottom: 0px; +} + +p.enddd { + margin-bottom: 4px; +} + +p.endtd { + margin-bottom: 2px; +} + +/* @end */ + +caption { + font-weight: bold; +} + +span.legend { + font-size: 70%; + text-align: center; +} + +h3.version { + font-size: 90%; + text-align: center; +} + +div.qindex, div.navtab{ + background-color: #EBEFF6; + border: 1px solid #A3B4D7; + text-align: center; +} + +div.qindex, div.navpath { + width: 100%; + line-height: 140%; +} + +div.navtab { + margin-right: 15px; +} + +/* @group Link Styling */ + +a { + color: #3D578C; + font-weight: normal; + text-decoration: none; +} + +.contents a:visited { + color: #4665A2; +} + +a:hover { + text-decoration: underline; +} + +a.qindex { + font-weight: bold; +} + +a.qindexHL { + font-weight: bold; + background-color: #9CAFD4; + color: #ffffff; + border: 1px double #869DCA; +} + +.contents a.qindexHL:visited { + color: #ffffff; +} + +a.el { + font-weight: bold; +} + +a.elRef { +} + +a.code, a.code:visited, a.line, a.line:visited { + color: #4665A2; +} + +a.codeRef, a.codeRef:visited, a.lineRef, a.lineRef:visited { + color: #4665A2; +} + +/* @end */ + +dl.el { + margin-left: -1cm; +} + +pre.fragment { + border: 1px solid #C4CFE5; + background-color: #FBFCFD; + padding: 4px 6px; + margin: 4px 8px 4px 2px; + overflow: auto; + word-wrap: break-word; + font-size: 9pt; + line-height: 125%; + font-family: monospace, fixed; + font-size: 105%; +} + +div.fragment { + padding: 0px; + margin: 0px; + background-color: #FBFCFD; + border: 1px solid #C4CFE5; +} + +div.line { + font-family: monospace, fixed; + font-size: 13px; + min-height: 13px; + line-height: 1.0; + text-wrap: unrestricted; + white-space: -moz-pre-wrap; /* Moz */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: -o-pre-wrap; /* Opera 7 */ + white-space: pre-wrap; /* CSS3 */ + word-wrap: break-word; /* IE 5.5+ */ + text-indent: -53px; + padding-left: 53px; + padding-bottom: 0px; + margin: 0px; + -webkit-transition-property: background-color, box-shadow; + -webkit-transition-duration: 0.5s; + -moz-transition-property: background-color, box-shadow; + -moz-transition-duration: 0.5s; + -ms-transition-property: background-color, box-shadow; + -ms-transition-duration: 0.5s; + -o-transition-property: background-color, box-shadow; + -o-transition-duration: 0.5s; + transition-property: background-color, box-shadow; + transition-duration: 0.5s; +} + +div.line.glow { + background-color: cyan; + box-shadow: 0 0 10px cyan; +} + + +span.lineno { + padding-right: 4px; + text-align: right; + border-right: 2px solid #0F0; + background-color: #E8E8E8; + white-space: pre; +} +span.lineno a { + background-color: #D8D8D8; +} + +span.lineno a:hover { + background-color: #C8C8C8; +} + +div.ah { + background-color: black; + font-weight: bold; + color: #ffffff; + margin-bottom: 3px; + margin-top: 3px; + padding: 0.2em; + border: solid thin #333; + border-radius: 0.5em; + -webkit-border-radius: .5em; + -moz-border-radius: .5em; + box-shadow: 2px 2px 3px #999; + -webkit-box-shadow: 2px 2px 3px #999; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; + background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#000),color-stop(0.3, #444)); + background-image: -moz-linear-gradient(center top, #eee 0%, #444 40%, #000); +} + +div.groupHeader { + margin-left: 16px; + margin-top: 12px; + font-weight: bold; +} + +div.groupText { + margin-left: 16px; + font-style: italic; +} + +body { + background-color: white; + color: black; + margin: 0; +} + +div.contents { + margin-top: 10px; + margin-left: 12px; + margin-right: 8px; +} + +td.indexkey { + background-color: #EBEFF6; + font-weight: bold; + border: 1px solid #C4CFE5; + margin: 2px 0px 2px 0; + padding: 2px 10px; + white-space: nowrap; + vertical-align: top; +} + +td.indexvalue { + background-color: #EBEFF6; + border: 1px solid #C4CFE5; + padding: 2px 10px; + margin: 2px 0px; +} + +tr.memlist { + background-color: #EEF1F7; +} + +p.formulaDsp { + text-align: center; +} + +img.formulaDsp { + +} + +img.formulaInl { + vertical-align: middle; +} + +div.center { + text-align: center; + margin-top: 0px; + margin-bottom: 0px; + padding: 0px; +} + +div.center img { + border: 0px; +} + +address.footer { + text-align: right; + padding-right: 12px; +} + +img.footer { + border: 0px; + vertical-align: middle; +} + +/* @group Code Colorization */ + +span.keyword { + color: #008000 +} + +span.keywordtype { + color: #604020 +} + +span.keywordflow { + color: #e08000 +} + +span.comment { + color: #800000 +} + +span.preprocessor { + color: #806020 +} + +span.stringliteral { + color: #002080 +} + +span.charliteral { + color: #008080 +} + +span.vhdldigit { + color: #ff00ff +} + +span.vhdlchar { + color: #000000 +} + +span.vhdlkeyword { + color: #700070 +} + +span.vhdllogic { + color: #ff0000 +} + +blockquote { + background-color: #F7F8FB; + border-left: 2px solid #9CAFD4; + margin: 0 24px 0 4px; + padding: 0 12px 0 16px; +} + +/* @end */ + +/* +.search { + color: #003399; + font-weight: bold; +} + +form.search { + margin-bottom: 0px; + margin-top: 0px; +} + +input.search { + font-size: 75%; + color: #000080; + font-weight: normal; + background-color: #e8eef2; +} +*/ + +td.tiny { + font-size: 75%; +} + +.dirtab { + padding: 4px; + border-collapse: collapse; + border: 1px solid #A3B4D7; +} + +th.dirtab { + background: #EBEFF6; + font-weight: bold; +} + +hr { + height: 0px; + border: none; + border-top: 1px solid #4A6AAA; +} + +hr.footer { + height: 1px; +} + +/* @group Member Descriptions */ + +table.memberdecls { + border-spacing: 0px; + padding: 0px; +} + +.memberdecls td, .fieldtable tr { + -webkit-transition-property: background-color, box-shadow; + -webkit-transition-duration: 0.5s; + -moz-transition-property: background-color, box-shadow; + -moz-transition-duration: 0.5s; + -ms-transition-property: background-color, box-shadow; + -ms-transition-duration: 0.5s; + -o-transition-property: background-color, box-shadow; + -o-transition-duration: 0.5s; + transition-property: background-color, box-shadow; + transition-duration: 0.5s; +} + +.memberdecls td.glow, .fieldtable tr.glow { + background-color: cyan; + box-shadow: 0 0 15px cyan; +} + +.mdescLeft, .mdescRight, +.memItemLeft, .memItemRight, +.memTemplItemLeft, .memTemplItemRight, .memTemplParams { + background-color: #F9FAFC; + border: none; + margin: 4px; + padding: 1px 0 0 8px; +} + +.mdescLeft, .mdescRight { + padding: 0px 8px 4px 8px; + color: #555; +} + +.memSeparator { + border-bottom: 1px solid #DEE4F0; + line-height: 1px; + margin: 0px; + padding: 0px; +} + +.memItemLeft, .memTemplItemLeft { + white-space: nowrap; +} + +.memItemRight { + width: 100%; +} + +.memTemplParams { + color: #4665A2; + white-space: nowrap; + font-size: 80%; +} + +/* @end */ + +/* @group Member Details */ + +/* Styles for detailed member documentation */ + +.memtemplate { + font-size: 80%; + color: #4665A2; + font-weight: normal; + margin-left: 9px; +} + +.memnav { + background-color: #EBEFF6; + border: 1px solid #A3B4D7; + text-align: center; + margin: 2px; + margin-right: 15px; + padding: 2px; +} + +.mempage { + width: 100%; +} + +.memitem { + padding: 0; + margin-bottom: 10px; + margin-right: 5px; + -webkit-transition: box-shadow 0.5s linear; + -moz-transition: box-shadow 0.5s linear; + -ms-transition: box-shadow 0.5s linear; + -o-transition: box-shadow 0.5s linear; + transition: box-shadow 0.5s linear; + display: table !important; + width: 100%; +} + +.memitem.glow { + box-shadow: 0 0 15px cyan; +} + +.memname { + font-weight: bold; + margin-left: 6px; +} + +.memname td { + vertical-align: bottom; +} + +.memproto, dl.reflist dt { + border-top: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + padding: 6px 0px 6px 0px; + color: #253555; + font-weight: bold; + text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); + background-image:url('http://github.com/nav_f.png'); + background-repeat:repeat-x; + background-color: #E2E8F2; + /* opera specific markup */ + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + border-top-right-radius: 4px; + border-top-left-radius: 4px; + /* firefox specific markup */ + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + -moz-border-radius-topright: 4px; + -moz-border-radius-topleft: 4px; + /* webkit specific markup */ + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + -webkit-border-top-right-radius: 4px; + -webkit-border-top-left-radius: 4px; + +} + +.memdoc, dl.reflist dd { + border-bottom: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + padding: 6px 10px 2px 10px; + background-color: #FBFCFD; + border-top-width: 0; + background-image:url('http://github.com/nav_g.png'); + background-repeat:repeat-x; + background-color: #FFFFFF; + /* opera specific markup */ + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + /* firefox specific markup */ + -moz-border-radius-bottomleft: 4px; + -moz-border-radius-bottomright: 4px; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + /* webkit specific markup */ + -webkit-border-bottom-left-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); +} + +dl.reflist dt { + padding: 5px; +} + +dl.reflist dd { + margin: 0px 0px 10px 0px; + padding: 5px; +} + +.paramkey { + text-align: right; +} + +.paramtype { + white-space: nowrap; +} + +.paramname { + color: #602020; + white-space: nowrap; +} +.paramname em { + font-style: normal; +} +.paramname code { + line-height: 14px; +} + +.params, .retval, .exception, .tparams { + margin-left: 0px; + padding-left: 0px; +} + +.params .paramname, .retval .paramname { + font-weight: bold; + vertical-align: top; +} + +.params .paramtype { + font-style: italic; + vertical-align: top; +} + +.params .paramdir { + font-family: "courier new",courier,monospace; + vertical-align: top; +} + +table.mlabels { + border-spacing: 0px; +} + +td.mlabels-left { + width: 100%; + padding: 0px; +} + +td.mlabels-right { + vertical-align: bottom; + padding: 0px; + white-space: nowrap; +} + +span.mlabels { + margin-left: 8px; +} + +span.mlabel { + background-color: #728DC1; + border-top:1px solid #5373B4; + border-left:1px solid #5373B4; + border-right:1px solid #C4CFE5; + border-bottom:1px solid #C4CFE5; + text-shadow: none; + color: white; + margin-right: 4px; + padding: 2px 3px; + border-radius: 3px; + font-size: 7pt; + white-space: nowrap; + vertical-align: middle; +} + + + +/* @end */ + +/* these are for tree view when not used as main index */ + +div.directory { + margin: 10px 0px; + border-top: 1px solid #A8B8D9; + border-bottom: 1px solid #A8B8D9; + width: 100%; +} + +.directory table { + border-collapse:collapse; +} + +.directory td { + margin: 0px; + padding: 0px; + vertical-align: top; +} + +.directory td.entry { + white-space: nowrap; + padding-right: 6px; + padding-top: 3px; +} + +.directory td.entry a { + outline:none; +} + +.directory td.entry a img { + border: none; +} + +.directory td.desc { + width: 100%; + padding-left: 6px; + padding-right: 6px; + padding-top: 3px; + border-left: 1px solid rgba(0,0,0,0.05); +} + +.directory tr.even { + padding-left: 6px; + background-color: #F7F8FB; +} + +.directory img { + vertical-align: -30%; +} + +.directory .levels { + white-space: nowrap; + width: 100%; + text-align: right; + font-size: 9pt; +} + +.directory .levels span { + cursor: pointer; + padding-left: 2px; + padding-right: 2px; + color: #3D578C; +} + +div.dynheader { + margin-top: 8px; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +address { + font-style: normal; + color: #2A3D61; +} + +table.doxtable { + border-collapse:collapse; + margin-top: 4px; + margin-bottom: 4px; +} + +table.doxtable td, table.doxtable th { + border: 1px solid #2D4068; + padding: 3px 7px 2px; +} + +table.doxtable th { + background-color: #374F7F; + color: #FFFFFF; + font-size: 110%; + padding-bottom: 4px; + padding-top: 5px; +} + +table.fieldtable { + /*width: 100%;*/ + margin-bottom: 10px; + border: 1px solid #A8B8D9; + border-spacing: 0px; + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + border-radius: 4px; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; + -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); + box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); +} + +.fieldtable td, .fieldtable th { + padding: 3px 7px 2px; +} + +.fieldtable td.fieldtype, .fieldtable td.fieldname { + white-space: nowrap; + border-right: 1px solid #A8B8D9; + border-bottom: 1px solid #A8B8D9; + vertical-align: top; +} + +.fieldtable td.fieldname { + padding-top: 3px; +} + +.fieldtable td.fielddoc { + border-bottom: 1px solid #A8B8D9; + /*width: 100%;*/ +} + +.fieldtable td.fielddoc p:first-child { + margin-top: 0px; +} + +.fieldtable td.fielddoc p:last-child { + margin-bottom: 2px; +} + +.fieldtable tr:last-child td { + border-bottom: none; +} + +.fieldtable th { + background-image:url('http://github.com/nav_f.png'); + background-repeat:repeat-x; + background-color: #E2E8F2; + font-size: 90%; + color: #253555; + padding-bottom: 4px; + padding-top: 5px; + text-align:left; + -moz-border-radius-topleft: 4px; + -moz-border-radius-topright: 4px; + -webkit-border-top-left-radius: 4px; + -webkit-border-top-right-radius: 4px; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + border-bottom: 1px solid #A8B8D9; +} + + +.tabsearch { + top: 0px; + left: 10px; + height: 36px; + background-image: url('http://github.com/tab_b.png'); + z-index: 101; + overflow: hidden; + font-size: 13px; +} + +.navpath ul +{ + font-size: 11px; + background-image:url('http://github.com/tab_b.png'); + background-repeat:repeat-x; + background-position: 0 -5px; + height:30px; + line-height:30px; + color:#8AA0CC; + border:solid 1px #C2CDE4; + overflow:hidden; + margin:0px; + padding:0px; +} + +.navpath li +{ + list-style-type:none; + float:left; + padding-left:10px; + padding-right:15px; + background-image:url('http://github.com/bc_s.png'); + background-repeat:no-repeat; + background-position:right; + color:#364D7C; +} + +.navpath li.navelem a +{ + height:32px; + display:block; + text-decoration: none; + outline: none; + color: #283A5D; + font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; + text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); + text-decoration: none; +} + +.navpath li.navelem a:hover +{ + color:#6884BD; +} + +.navpath li.footer +{ + list-style-type:none; + float:right; + padding-left:10px; + padding-right:15px; + background-image:none; + background-repeat:no-repeat; + background-position:right; + color:#364D7C; + font-size: 8pt; +} + + +div.summary +{ + float: right; + font-size: 8pt; + padding-right: 5px; + width: 50%; + text-align: right; +} + +div.summary a +{ + white-space: nowrap; +} + +div.ingroups +{ + font-size: 8pt; + width: 50%; + text-align: left; +} + +div.ingroups a +{ + white-space: nowrap; +} + +div.header +{ + background-image:url('http://github.com/nav_h.png'); + background-repeat:repeat-x; + background-color: #F9FAFC; + margin: 0px; + border-bottom: 1px solid #C4CFE5; +} + +div.headertitle +{ + padding: 5px 5px 5px 10px; +} + +dl +{ + padding: 0 0 0 10px; +} + +/* dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug */ +dl.section +{ + margin-left: 0px; + padding-left: 0px; +} + +dl.note +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #D0C000; +} + +dl.warning, dl.attention +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #FF0000; +} + +dl.pre, dl.post, dl.invariant +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #00D000; +} + +dl.deprecated +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #505050; +} + +dl.todo +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #00C0E0; +} + +dl.test +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #3030E0; +} + +dl.bug +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #C08050; +} + +dl.section dd { + margin-bottom: 6px; +} + + +#projectlogo +{ + text-align: center; + vertical-align: bottom; + border-collapse: separate; +} + +#projectlogo img +{ + border: 0px none; +} + +#projectname +{ + font: 300% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 2px 0px; +} + +#projectbrief +{ + font: 120% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 0px; +} + +#projectnumber +{ + font: 50% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 0px; +} + +#titlearea +{ + padding: 0px; + margin: 0px; + width: 100%; + border-bottom: 1px solid #5373B4; +} + +.image +{ + text-align: center; +} + +.dotgraph +{ + text-align: center; +} + +.mscgraph +{ + text-align: center; +} + +.caption +{ + font-weight: bold; +} + +div.zoom +{ + border: 1px solid #90A5CE; +} + +dl.citelist { + margin-bottom:50px; +} + +dl.citelist dt { + color:#334975; + float:left; + font-weight:bold; + margin-right:10px; + padding:5px; +} + +dl.citelist dd { + margin:2px 0; + padding:5px 0; +} + +div.toc { + padding: 14px 25px; + background-color: #F4F6FA; + border: 1px solid #D8DFEE; + border-radius: 7px 7px 7px 7px; + float: right; + height: auto; + margin: 0 20px 10px 10px; + width: 200px; +} + +div.toc li { + background: url("http://github.com/bdwn.png") no-repeat scroll 0 5px transparent; + font: 10px/1.2 Verdana,DejaVu Sans,Geneva,sans-serif; + margin-top: 5px; + padding-left: 10px; + padding-top: 2px; +} + +div.toc h3 { + font: bold 12px/1.2 Arial,FreeSans,sans-serif; + color: #4665A2; + border-bottom: 0 none; + margin: 0; +} + +div.toc ul { + list-style: none outside none; + border: medium none; + padding: 0px; +} + +div.toc li.level1 { + margin-left: 0px; +} + +div.toc li.level2 { + margin-left: 15px; +} + +div.toc li.level3 { + margin-left: 30px; +} + +div.toc li.level4 { + margin-left: 45px; +} + +.inherit_header { + font-weight: bold; + color: gray; + cursor: pointer; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.inherit_header td { + padding: 6px 0px 2px 5px; +} + +.inherit { + display: none; +} + +tr.heading h2 { + margin-top: 12px; + margin-bottom: 4px; +} + +/* tooltip related style info */ + +.ttc { + position: absolute; + display: none; +} + +#powerTip { + cursor: default; + white-space: nowrap; + background-color: white; + border: 1px solid gray; + border-radius: 4px 4px 4px 4px; + box-shadow: 1px 1px 7px gray; + display: none; + font-size: smaller; + max-width: 80%; + opacity: 0.9; + padding: 1ex 1em 1em; + position: absolute; + z-index: 2147483647; +} + +#powerTip div.ttdoc { + color: grey; + font-style: italic; +} + +#powerTip div.ttname a { + font-weight: bold; +} + +#powerTip div.ttname { + font-weight: bold; +} + +#powerTip div.ttdeci { + color: #006318; +} + +#powerTip div { + margin: 0px; + padding: 0px; + font: 12px/16px Roboto,sans-serif; +} + +#powerTip:before, #powerTip:after { + content: ""; + position: absolute; + margin: 0px; +} + +#powerTip.n:after, #powerTip.n:before, +#powerTip.s:after, #powerTip.s:before, +#powerTip.w:after, #powerTip.w:before, +#powerTip.e:after, #powerTip.e:before, +#powerTip.ne:after, #powerTip.ne:before, +#powerTip.se:after, #powerTip.se:before, +#powerTip.nw:after, #powerTip.nw:before, +#powerTip.sw:after, #powerTip.sw:before { + border: solid transparent; + content: " "; + height: 0; + width: 0; + position: absolute; +} + +#powerTip.n:after, #powerTip.s:after, +#powerTip.w:after, #powerTip.e:after, +#powerTip.nw:after, #powerTip.ne:after, +#powerTip.sw:after, #powerTip.se:after { + border-color: rgba(255, 255, 255, 0); +} + +#powerTip.n:before, #powerTip.s:before, +#powerTip.w:before, #powerTip.e:before, +#powerTip.nw:before, #powerTip.ne:before, +#powerTip.sw:before, #powerTip.se:before { + border-color: rgba(128, 128, 128, 0); +} + +#powerTip.n:after, #powerTip.n:before, +#powerTip.ne:after, #powerTip.ne:before, +#powerTip.nw:after, #powerTip.nw:before { + top: 100%; +} + +#powerTip.n:after, #powerTip.ne:after, #powerTip.nw:after { + border-top-color: #ffffff; + border-width: 10px; + margin: 0px -10px; +} +#powerTip.n:before { + border-top-color: #808080; + border-width: 11px; + margin: 0px -11px; +} +#powerTip.n:after, #powerTip.n:before { + left: 50%; +} + +#powerTip.nw:after, #powerTip.nw:before { + right: 14px; +} + +#powerTip.ne:after, #powerTip.ne:before { + left: 14px; +} + +#powerTip.s:after, #powerTip.s:before, +#powerTip.se:after, #powerTip.se:before, +#powerTip.sw:after, #powerTip.sw:before { + bottom: 100%; +} + +#powerTip.s:after, #powerTip.se:after, #powerTip.sw:after { + border-bottom-color: #ffffff; + border-width: 10px; + margin: 0px -10px; +} + +#powerTip.s:before, #powerTip.se:before, #powerTip.sw:before { + border-bottom-color: #808080; + border-width: 11px; + margin: 0px -11px; +} + +#powerTip.s:after, #powerTip.s:before { + left: 50%; +} + +#powerTip.sw:after, #powerTip.sw:before { + right: 14px; +} + +#powerTip.se:after, #powerTip.se:before { + left: 14px; +} + +#powerTip.e:after, #powerTip.e:before { + left: 100%; +} +#powerTip.e:after { + border-left-color: #ffffff; + border-width: 10px; + top: 50%; + margin-top: -10px; +} +#powerTip.e:before { + border-left-color: #808080; + border-width: 11px; + top: 50%; + margin-top: -11px; +} + +#powerTip.w:after, #powerTip.w:before { + right: 100%; +} +#powerTip.w:after { + border-right-color: #ffffff; + border-width: 10px; + top: 50%; + margin-top: -10px; +} +#powerTip.w:before { + border-right-color: #808080; + border-width: 11px; + top: 50%; + margin-top: -11px; +} + +@media print +{ + #top { display: none; } + #side-nav { display: none; } + #nav-path { display: none; } + body { overflow:visible; } + h1, h2, h3, h4, h5, h6 { page-break-after: avoid; } + .summary { display: none; } + .memitem { page-break-inside: avoid; } + #doc-content + { + margin-left:0 !important; + height:auto !important; + width:auto !important; + overflow:inherit; + display:inline; + } +} + diff --git a/Arduino/MAX6956/html/doxygen.png b/Arduino/MAX6956/html/doxygen.png new file mode 100644 index 0000000000000000000000000000000000000000..3ff17d807fd8aa003bed8bb2a69e8f0909592fd1 GIT binary patch literal 3779 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 literal 0 HcmV?d00001 diff --git a/Arduino/MAX6956/html/dynsections.js b/Arduino/MAX6956/html/dynsections.js new file mode 100644 index 00000000..2f15470d --- /dev/null +++ b/Arduino/MAX6956/html/dynsections.js @@ -0,0 +1,104 @@ +function toggleVisibility(linkObj) +{ + var base = $(linkObj).attr('id'); + var summary = $('#'+base+'-summary'); + var content = $('#'+base+'-content'); + var trigger = $('#'+base+'-trigger'); + var src=$(trigger).attr('src'); + if (content.is(':visible')===true) { + content.hide(); + summary.show(); + $(linkObj).addClass('closed').removeClass('opened'); + $(trigger).attr('src',src.substring(0,src.length-8)+'closed.png'); + } else { + content.show(); + summary.hide(); + $(linkObj).removeClass('closed').addClass('opened'); + $(trigger).attr('src',src.substring(0,src.length-10)+'open.png'); + } + return false; +} + +function updateStripes() +{ + $('table.directory tr'). + removeClass('even').filter(':visible:even').addClass('even'); +} +function toggleLevel(level) +{ + $('table.directory tr').each(function(){ + var l = this.id.split('_').length-1; + var i = $('#img'+this.id.substring(3)); + var a = $('#arr'+this.id.substring(3)); + if (l + + + + + +MAX6956: File List + + + + + + + + + +
+
+ + + + + + +
+
MAX6956 +  1.0 +
+
MAX6956i2Clibrary
+
+
+ + + + + +
+ + + + +
+ +
+ +
+
+
File List
+
+
+
Here is a list of all files with brief descriptions:
+
+ + + + diff --git a/Arduino/MAX6956/html/ftv2blank.png b/Arduino/MAX6956/html/ftv2blank.png new file mode 100644 index 0000000000000000000000000000000000000000..63c605bb4c3d941c921a4b6cfa74951e946bcb48 GIT binary patch literal 86 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRr!3HExu9B$%QnH>djv*C{Z|`mdau^P8_z}#X h?B8GEpdi4(BFDx$je&7RrDQEg&ePS;Wt~$(69Dh@6T1Ka literal 0 HcmV?d00001 diff --git a/Arduino/MAX6956/html/ftv2cl.png b/Arduino/MAX6956/html/ftv2cl.png new file mode 100644 index 0000000000000000000000000000000000000000..132f6577bf7f085344904602815a260d29f55d9b GIT binary patch literal 453 zcmV;$0XqJPP)VBF;ev;toEj8_OB0EQg5eYilIj#JZG_m^33l3^k4mtzx!TVD?g)Y$ zrvwRDSqT!wLIM$dWCIa$vtxE|mzbTzu-y&$FvF6WA2a{Wr1g}`WdPT-0JzEZ0IxAv z-Z+ejZc&H;I5-pb_SUB}04j0^V)3t{`z<7asDl2Tw3w3sP%)0^8$bhEg)IOTBcRXv zFfq~3&gvJ$F-U7mpBW8z1GY~HK&7h4^YI~Orv~wLnC0PP_dAkv;nzX{9Q|8Gv=2ca z@v)c9T;D#h`TZ2X&&$ff2wedmot995de~-s3I)yauahg;7qn*?1n?F$e+PwP37}~; z1NKUk7reVK^7A;$QRW7qAx40HHUZ<|k3U%nz(Ec`#i+q9K!dgcROAlCS?`L= v>#=f?wF5ZND!1uAfQsk;KN^4&*8~0npJiJ%2dj9(00000NkvXXu0mjfWVFf_ literal 0 HcmV?d00001 diff --git a/Arduino/MAX6956/html/ftv2doc.png b/Arduino/MAX6956/html/ftv2doc.png new file mode 100644 index 0000000000000000000000000000000000000000..17edabff95f7b8da13c9516a04efe05493c29501 GIT binary patch literal 746 zcmV7=@pnbNXRFEm&G8P!&WHG=d)>K?YZ1bzou)2{$)) zumDct!>4SyxL;zgaG>wy`^Hv*+}0kUfCrz~BCOViSb$_*&;{TGGn2^x9K*!Sf0=lV zpP=7O;GA0*Jm*tTYj$IoXvimpnV4S1Z5f$p*f$Db2iq2zrVGQUz~yq`ahn7ck(|CE z7Gz;%OP~J6)tEZWDzjhL9h2hdfoU2)Nd%T<5Kt;Y0XLt&<@6pQx!nw*5`@bq#?l*?3z{Hlzoc=Pr>oB5(9i6~_&-}A(4{Q$>c>%rV&E|a(r&;?i5cQB=} zYSDU5nXG)NS4HEs0it2AHe2>shCyr7`6@4*6{r@8fXRbTA?=IFVWAQJL&H5H{)DpM#{W(GL+Idzf^)uRV@oB8u$ z8v{MfJbTiiRg4bza<41NAzrl{=3fl_D+$t+^!xlQ8S}{UtY`e z;;&9UhyZqQRN%2pot{*Ei0*4~hSF_3AH2@fKU!$NSflS>{@tZpDT4`M2WRTTVH+D? z)GFlEGGHe?koB}i|1w45!BF}N_q&^HJ&-tyR{(afC6H7|aml|tBBbv}55C5DNP8p3 z)~jLEO4Z&2hZmP^i-e%(@d!(E|KRafiU8Q5u(wU((j8un3OR*Hvj+t literal 0 HcmV?d00001 diff --git a/Arduino/MAX6956/html/ftv2folderclosed.png b/Arduino/MAX6956/html/ftv2folderclosed.png new file mode 100644 index 0000000000000000000000000000000000000000..bb8ab35edce8e97554e360005ee9fc5bffb36e66 GIT binary patch literal 616 zcmV-u0+;=XP)a9#ETzayK)T~Jw&MMH>OIr#&;dC}is*2Mqdf&akCc=O@`qC+4i z5Iu3w#1M@KqXCz8TIZd1wli&kkl2HVcAiZ8PUn5z_kG@-y;?yK06=cA0U%H0PH+kU zl6dp}OR(|r8-RG+YLu`zbI}5TlOU6ToR41{9=uz^?dGTNL;wIMf|V3`d1Wj3y!#6` zBLZ?xpKR~^2x}?~zA(_NUu3IaDB$tKma*XUdOZN~c=dLt_h_k!dbxm_*ibDM zlFX`g{k$X}yIe%$N)cn1LNu=q9_CS)*>A zsX_mM4L@`(cSNQKMFc$RtYbx{79#j-J7hk*>*+ZZhM4Hw?I?rsXCi#mRWJ=-0LGV5a-WR0Qgt<|Nqf)C-@80`5gIz45^_20000IqP)X=#(TiCT&PiIIVc55T}TU}EUh*{q$|`3@{d>{Tc9Bo>e= zfmF3!f>fbI9#GoEHh0f`i5)wkLpva0ztf%HpZneK?w-7AK@b4Itw{y|Zd3k!fH?q2 zlhckHd_V2M_X7+)U&_Xcfvtw60l;--DgZmLSw-Y?S>)zIqMyJ1#FwLU*%bl38ok+! zh78H87n`ZTS;uhzAR$M`zZ`bVhq=+%u9^$5jDplgxd44}9;IRqUH1YHH|@6oFe%z( zo4)_>E$F&^P-f(#)>(TrnbE>Pefs9~@iN=|)Rz|V`sGfHNrJ)0gJb8xx+SBmRf@1l zvuzt=vGfI)<-F9!o&3l?>9~0QbUDT(wFdnQPv%xdD)m*g%!20>Bc9iYmGAp<9YAa( z0QgYgTWqf1qN++Gqp z8@AYPTB3E|6s=WLG?xw0tm|U!o=&zd+H0oRYE;Dbx+Na9s^STqX|Gnq%H8s(nGDGJ j8vwW|`Ts`)fSK|Kx=IK@RG@g200000NkvXXu0mjfauFEA literal 0 HcmV?d00001 diff --git a/Arduino/MAX6956/html/ftv2lastnode.png b/Arduino/MAX6956/html/ftv2lastnode.png new file mode 100644 index 0000000000000000000000000000000000000000..63c605bb4c3d941c921a4b6cfa74951e946bcb48 GIT binary patch literal 86 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRr!3HExu9B$%QnH>djv*C{Z|`mdau^P8_z}#X h?B8GEpdi4(BFDx$je&7RrDQEg&ePS;Wt~$(69Dh@6T1Ka literal 0 HcmV?d00001 diff --git a/Arduino/MAX6956/html/ftv2link.png b/Arduino/MAX6956/html/ftv2link.png new file mode 100644 index 0000000000000000000000000000000000000000..17edabff95f7b8da13c9516a04efe05493c29501 GIT binary patch literal 746 zcmV7=@pnbNXRFEm&G8P!&WHG=d)>K?YZ1bzou)2{$)) zumDct!>4SyxL;zgaG>wy`^Hv*+}0kUfCrz~BCOViSb$_*&;{TGGn2^x9K*!Sf0=lV zpP=7O;GA0*Jm*tTYj$IoXvimpnV4S1Z5f$p*f$Db2iq2zrVGQUz~yq`ahn7ck(|CE z7Gz;%OP~J6)tEZWDzjhL9h2hdfoU2)Nd%T<5Kt;Y0XLt&<@6pQx!nw*5`@bq#?l*?3z{Hlzoc=Pr>oB5(9i6~_&-}A(4{Q$>c>%rV&E|a(r&;?i5cQB=} zYSDU5nXG)NS4HEs0it2AHe2>shCyr7`6@4*6{r@8fXRbTA?=IFVWAQJL&H5H{)DpM#{W(GL+Idzf^)uRV@oB8u$ z8v{MfJbTiiRg4bza<41NAzrl{=3fl_D+$t+^!xlQ8S}{UtY`e z;;&9UhyZqQRN%2pot{*Ei0*4~hSF_3AH2@fKU!$NSflS>{@tZpDT4`M2WRTTVH+D? z)GFlEGGHe?koB}i|1w45!BF}N_q&^HJ&-tyR{(afC6H7|aml|tBBbv}55C5DNP8p3 z)~jLEO4Z&2hZmP^i-e%(@d!(E|KRafiU8Q5u(wU((j8un3OR*Hvj+t literal 0 HcmV?d00001 diff --git a/Arduino/MAX6956/html/ftv2mlastnode.png b/Arduino/MAX6956/html/ftv2mlastnode.png new file mode 100644 index 0000000000000000000000000000000000000000..0b63f6d38c4b9ec907b820192ebe9724ed6eca22 GIT binary patch literal 246 zcmVkw!R34#Lv2LOS^S2tZA31X++9RY}n zChwn@Z)Wz*WWHH{)HDtJnq&A2hk$b-y(>?@z0iHr41EKCGp#T5?07*qoM6N<$f(V3Pvj6}9 literal 0 HcmV?d00001 diff --git a/Arduino/MAX6956/html/ftv2mnode.png b/Arduino/MAX6956/html/ftv2mnode.png new file mode 100644 index 0000000000000000000000000000000000000000..0b63f6d38c4b9ec907b820192ebe9724ed6eca22 GIT binary patch literal 246 zcmVkw!R34#Lv2LOS^S2tZA31X++9RY}n zChwn@Z)Wz*WWHH{)HDtJnq&A2hk$b-y(>?@z0iHr41EKCGp#T5?07*qoM6N<$f(V3Pvj6}9 literal 0 HcmV?d00001 diff --git a/Arduino/MAX6956/html/ftv2mo.png b/Arduino/MAX6956/html/ftv2mo.png new file mode 100644 index 0000000000000000000000000000000000000000..4bfb80f76e65815989a9350ad79d8ce45380e2b1 GIT binary patch literal 403 zcmV;E0c`$>P)${!fXv7NWJ%@%u4(KapRY>T6_x;E zxE7kt!}Tiw8@d9Sd`rTGum>z#Q14vIm`wm1#-byD1muMi02@YNO5LRF0o!Y{`a!Ya z{^&p0Su|s705&2QxmqdexG+-zNKL3f@8gTQSJrKByfo+oNJ^-{|Mn||Q5SDwjQVsS zr1}7o5-QMs>gYIMD>GRw@$lT`z4r-_m{5U#cR{urD_)TOeY)(UD|qZ^&y`IVijqk~ xs(9-kWFr7E^!lgi8GsFK5kOY_{Xbgf0^etEU%fLevs?fG002ovPDHLkV1nB&vX1}& literal 0 HcmV?d00001 diff --git a/Arduino/MAX6956/html/ftv2node.png b/Arduino/MAX6956/html/ftv2node.png new file mode 100644 index 0000000000000000000000000000000000000000..63c605bb4c3d941c921a4b6cfa74951e946bcb48 GIT binary patch literal 86 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRr!3HExu9B$%QnH>djv*C{Z|`mdau^P8_z}#X h?B8GEpdi4(BFDx$je&7RrDQEg&ePS;Wt~$(69Dh@6T1Ka literal 0 HcmV?d00001 diff --git a/Arduino/MAX6956/html/ftv2ns.png b/Arduino/MAX6956/html/ftv2ns.png new file mode 100644 index 0000000000000000000000000000000000000000..72e3d71c2892d6f00e259facebc88b45f6db2e35 GIT binary patch literal 388 zcmV-~0ek+5P)f+++#cT|!CkD&4pnIkeMEUEM*>`*9>+Juji$!h-mW%M^8s9957{3nvbrz^&=u<~TAUrFROkmt%^F~Ez+-c53Lv%iH3d38!Rv?K zrb&MYAhp;Gf<}wS;9ZZq2@;!uYG;=Z>~GKE^{HD4keu}lnyqhc>kWX^tQn|warJ~h zT+rtMkdz6aHoN%z(o|&wpu@@OpJnF_z{PA)6(FHw02iHslz^(N{4*+K9)QJHR87wT iTyp>aXaF{u2lxRou|^4tux6eB0000^P)R?RzRoKvklcaQ%HF6%rK2&ZgO(-ihJ_C zzrKgp4jgO( fd_(yg|3PpEQb#9`a?Pz_00000NkvXXu0mjftR`5K literal 0 HcmV?d00001 diff --git a/Arduino/MAX6956/html/ftv2pnode.png b/Arduino/MAX6956/html/ftv2pnode.png new file mode 100644 index 0000000000000000000000000000000000000000..c6ee22f937a07d1dbfc27c669d11f8ed13e2f152 GIT binary patch literal 229 zcmV^P)R?RzRoKvklcaQ%HF6%rK2&ZgO(-ihJ_C zzrKgp4jgO( fd_(yg|3PpEQb#9`a?Pz_00000NkvXXu0mjftR`5K literal 0 HcmV?d00001 diff --git a/Arduino/MAX6956/html/ftv2splitbar.png b/Arduino/MAX6956/html/ftv2splitbar.png new file mode 100644 index 0000000000000000000000000000000000000000..fe895f2c58179b471a22d8320b39a4bd7312ec8e GIT binary patch literal 314 zcmeAS@N?(olHy`uVBq!ia0vp^Yzz!63>-{AmhX=Jf(#6djGiuzAr*{o?=JLmPLyc> z_*`QK&+BH@jWrYJ7>r6%keRM@)Qyv8R=enp0jiI>aWlGyB58O zFVR20d+y`K7vDw(hJF3;>dD*3-?v=<8M)@x|EEGLnJsniYK!2U1 Y!`|5biEc?d1`HDhPgg&ebxsLQ02F6;9RL6T literal 0 HcmV?d00001 diff --git a/Arduino/MAX6956/html/ftv2vertline.png b/Arduino/MAX6956/html/ftv2vertline.png new file mode 100644 index 0000000000000000000000000000000000000000..63c605bb4c3d941c921a4b6cfa74951e946bcb48 GIT binary patch literal 86 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRr!3HExu9B$%QnH>djv*C{Z|`mdau^P8_z}#X h?B8GEpdi4(BFDx$je&7RrDQEg&ePS;Wt~$(69Dh@6T1Ka literal 0 HcmV?d00001 diff --git a/Arduino/MAX6956/html/functions.html b/Arduino/MAX6956/html/functions.html new file mode 100644 index 00000000..daef3340 --- /dev/null +++ b/Arduino/MAX6956/html/functions.html @@ -0,0 +1,266 @@ + + + + + + +MAX6956: Data Fields + + + + + + + + + +
+
+ + + + + + +
+
MAX6956 +  1.0 +
+
MAX6956i2Clibrary
+
+
+ + + + + + + +
+ + + + +
+ +
+ +
+
Here is a list of all struct and union fields with links to the structures/unions they belong to:
+ +

- b -

+ + +

- c -

+ + +

- d -

+ + +

- e -

+ + +

- g -

+ + +

- i -

+ + +

- m -

+ + +

- p -

+ + +

- r -

+ + +

- s -

+ + +

- t -

+
+ + + + diff --git a/Arduino/MAX6956/html/functions_func.html b/Arduino/MAX6956/html/functions_func.html new file mode 100644 index 00000000..bc5c6198 --- /dev/null +++ b/Arduino/MAX6956/html/functions_func.html @@ -0,0 +1,182 @@ + + + + + + +MAX6956: Data Fields - Functions + + + + + + + + + +
+
+ + + + + + +
+
MAX6956 +  1.0 +
+
MAX6956i2Clibrary
+
+
+ + + + + + +
+ + + + +
+ +
+ +
+
+ + + + diff --git a/Arduino/MAX6956/html/functions_vars.html b/Arduino/MAX6956/html/functions_vars.html new file mode 100644 index 00000000..124d87d7 --- /dev/null +++ b/Arduino/MAX6956/html/functions_vars.html @@ -0,0 +1,128 @@ + + + + + + +MAX6956: Data Fields - Variables + + + + + + + + + +
+
+ + + + + + +
+
MAX6956 +  1.0 +
+
MAX6956i2Clibrary
+
+
+ + + + + + +
+ + + + +
+ +
+ +
+
+ + + + diff --git a/Arduino/MAX6956/html/globals.html b/Arduino/MAX6956/html/globals.html new file mode 100644 index 00000000..016fc9d2 --- /dev/null +++ b/Arduino/MAX6956/html/globals.html @@ -0,0 +1,611 @@ + + + + + + +MAX6956: Globals + + + + + + + + + +
+
+ + + + + + +
+
MAX6956 +  1.0 +
+
MAX6956i2Clibrary
+
+
+ + + + + + + +
+ + + + +
+ +
+ +
+
Here is a list of all functions, variables, defines, enums, and typedefs with links to the files they belong to:
+ +

- m -

+
+ + + + diff --git a/Arduino/MAX6956/html/globals_defs.html b/Arduino/MAX6956/html/globals_defs.html new file mode 100644 index 00000000..b98fc9ed --- /dev/null +++ b/Arduino/MAX6956/html/globals_defs.html @@ -0,0 +1,611 @@ + + + + + + +MAX6956: Globals + + + + + + + + + +
+
+ + + + + + +
+
MAX6956 +  1.0 +
+
MAX6956i2Clibrary
+
+
+ + + + + + + +
+ + + + +
+ +
+ +
+  + +

- m -

+
+ + + + diff --git a/Arduino/MAX6956/html/index.html b/Arduino/MAX6956/html/index.html new file mode 100644 index 00000000..11992c78 --- /dev/null +++ b/Arduino/MAX6956/html/index.html @@ -0,0 +1,90 @@ + + + + + + +MAX6956: Main Page + + + + + + + + + +
+
+ + + + + + +
+
MAX6956 +  1.0 +
+
MAX6956i2Clibrary
+
+
+ + + + +
+ + + + +
+ +
+ +
+
+
MAX6956 Documentation
+
+
+
+ + + + diff --git a/Arduino/MAX6956/html/installdox b/Arduino/MAX6956/html/installdox new file mode 100755 index 00000000..edf5bbfe --- /dev/null +++ b/Arduino/MAX6956/html/installdox @@ -0,0 +1,112 @@ +#!/usr/bin/perl + +%subst = ( ); +$quiet = 0; + +while ( @ARGV ) { + $_ = shift @ARGV; + if ( s/^-// ) { + if ( /^l(.*)/ ) { + $v = ($1 eq "") ? shift @ARGV : $1; + ($v =~ /\/$/) || ($v .= "/"); + $_ = $v; + if ( /(.+)\@(.+)/ ) { + if ( exists $subst{$1} ) { + $subst{$1} = $2; + } else { + print STDERR "Unknown tag file $1 given with option -l\n"; + &usage(); + } + } else { + print STDERR "Argument $_ is invalid for option -l\n"; + &usage(); + } + } + elsif ( /^q/ ) { + $quiet = 1; + } + elsif ( /^\?|^h/ ) { + &usage(); + } + else { + print STDERR "Illegal option -$_\n"; + &usage(); + } + } + else { + push (@files, $_ ); + } +} + +foreach $sub (keys %subst) +{ + if ( $subst{$sub} eq "" ) + { + print STDERR "No substitute given for tag file `$sub'\n"; + &usage(); + } + elsif ( ! $quiet && $sub ne "_doc" && $sub ne "_cgi" ) + { + print "Substituting $subst{$sub} for each occurrence of tag file $sub\n"; + } +} + +if ( ! @files ) { + if (opendir(D,".")) { + foreach $file ( readdir(D) ) { + $match = ".html"; + next if ( $file =~ /^\.\.?$/ ); + ($file =~ /$match/) && (push @files, $file); + ($file =~ /\.svg/) && (push @files, $file); + ($file =~ "navtree.js") && (push @files, $file); + } + closedir(D); + } +} + +if ( ! @files ) { + print STDERR "Warning: No input files given and none found!\n"; +} + +foreach $f (@files) +{ + if ( ! $quiet ) { + print "Editing: $f...\n"; + } + $oldf = $f; + $f .= ".bak"; + unless (rename $oldf,$f) { + print STDERR "Error: cannot rename file $oldf\n"; + exit 1; + } + if (open(F,"<$f")) { + unless (open(G,">$oldf")) { + print STDERR "Error: opening file $oldf for writing\n"; + exit 1; + } + if ($oldf ne "tree.js") { + while () { + s/doxygen\=\"([^ \"\:\t\>\<]*)\:([^ \"\t\>\<]*)\" (xlink:href|href|src)=\"\2/doxygen\=\"$1:$subst{$1}\" \3=\"$subst{$1}/g; + print G "$_"; + } + } + else { + while () { + s/\"([^ \"\:\t\>\<]*)\:([^ \"\t\>\<]*)\", \"\2/\"$1:$subst{$1}\" ,\"$subst{$1}/g; + print G "$_"; + } + } + } + else { + print STDERR "Warning file $f does not exist\n"; + } + unlink $f; +} + +sub usage { + print STDERR "Usage: installdox [options] [html-file [html-file ...]]\n"; + print STDERR "Options:\n"; + print STDERR " -l tagfile\@linkName tag file + URL or directory \n"; + print STDERR " -q Quiet mode\n\n"; + exit 1; +} diff --git a/Arduino/MAX6956/html/jquery.js b/Arduino/MAX6956/html/jquery.js new file mode 100644 index 00000000..6aa2e4c2 --- /dev/null +++ b/Arduino/MAX6956/html/jquery.js @@ -0,0 +1,39 @@ +/*! + * jQuery JavaScript Library v1.7.1 + * http://jquery.com/ + * + * Copyright 2011, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Mon Nov 21 21:11:03 2011 -0500 + */ +(function(bb,L){var av=bb.document,bu=bb.navigator,bl=bb.location;var b=(function(){var bF=function(b0,b1){return new bF.fn.init(b0,b1,bD)},bU=bb.jQuery,bH=bb.$,bD,bY=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,bM=/\S/,bI=/^\s+/,bE=/\s+$/,bA=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,bN=/^[\],:{}\s]*$/,bW=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,bP=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,bJ=/(?:^|:|,)(?:\s*\[)+/g,by=/(webkit)[ \/]([\w.]+)/,bR=/(opera)(?:.*version)?[ \/]([\w.]+)/,bQ=/(msie) ([\w.]+)/,bS=/(mozilla)(?:.*? rv:([\w.]+))?/,bB=/-([a-z]|[0-9])/ig,bZ=/^-ms-/,bT=function(b0,b1){return(b1+"").toUpperCase()},bX=bu.userAgent,bV,bC,e,bL=Object.prototype.toString,bG=Object.prototype.hasOwnProperty,bz=Array.prototype.push,bK=Array.prototype.slice,bO=String.prototype.trim,bv=Array.prototype.indexOf,bx={};bF.fn=bF.prototype={constructor:bF,init:function(b0,b4,b3){var b2,b5,b1,b6;if(!b0){return this}if(b0.nodeType){this.context=this[0]=b0;this.length=1;return this}if(b0==="body"&&!b4&&av.body){this.context=av;this[0]=av.body;this.selector=b0;this.length=1;return this}if(typeof b0==="string"){if(b0.charAt(0)==="<"&&b0.charAt(b0.length-1)===">"&&b0.length>=3){b2=[null,b0,null]}else{b2=bY.exec(b0)}if(b2&&(b2[1]||!b4)){if(b2[1]){b4=b4 instanceof bF?b4[0]:b4;b6=(b4?b4.ownerDocument||b4:av);b1=bA.exec(b0);if(b1){if(bF.isPlainObject(b4)){b0=[av.createElement(b1[1])];bF.fn.attr.call(b0,b4,true)}else{b0=[b6.createElement(b1[1])]}}else{b1=bF.buildFragment([b2[1]],[b6]);b0=(b1.cacheable?bF.clone(b1.fragment):b1.fragment).childNodes}return bF.merge(this,b0)}else{b5=av.getElementById(b2[2]);if(b5&&b5.parentNode){if(b5.id!==b2[2]){return b3.find(b0)}this.length=1;this[0]=b5}this.context=av;this.selector=b0;return this}}else{if(!b4||b4.jquery){return(b4||b3).find(b0)}else{return this.constructor(b4).find(b0)}}}else{if(bF.isFunction(b0)){return b3.ready(b0)}}if(b0.selector!==L){this.selector=b0.selector;this.context=b0.context}return bF.makeArray(b0,this)},selector:"",jquery:"1.7.1",length:0,size:function(){return this.length},toArray:function(){return bK.call(this,0)},get:function(b0){return b0==null?this.toArray():(b0<0?this[this.length+b0]:this[b0])},pushStack:function(b1,b3,b0){var b2=this.constructor();if(bF.isArray(b1)){bz.apply(b2,b1)}else{bF.merge(b2,b1)}b2.prevObject=this;b2.context=this.context;if(b3==="find"){b2.selector=this.selector+(this.selector?" ":"")+b0}else{if(b3){b2.selector=this.selector+"."+b3+"("+b0+")"}}return b2},each:function(b1,b0){return bF.each(this,b1,b0)},ready:function(b0){bF.bindReady();bC.add(b0);return this},eq:function(b0){b0=+b0;return b0===-1?this.slice(b0):this.slice(b0,b0+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(bK.apply(this,arguments),"slice",bK.call(arguments).join(","))},map:function(b0){return this.pushStack(bF.map(this,function(b2,b1){return b0.call(b2,b1,b2)}))},end:function(){return this.prevObject||this.constructor(null)},push:bz,sort:[].sort,splice:[].splice};bF.fn.init.prototype=bF.fn;bF.extend=bF.fn.extend=function(){var b9,b2,b0,b1,b6,b7,b5=arguments[0]||{},b4=1,b3=arguments.length,b8=false;if(typeof b5==="boolean"){b8=b5;b5=arguments[1]||{};b4=2}if(typeof b5!=="object"&&!bF.isFunction(b5)){b5={}}if(b3===b4){b5=this;--b4}for(;b40){return}bC.fireWith(av,[bF]);if(bF.fn.trigger){bF(av).trigger("ready").off("ready")}}},bindReady:function(){if(bC){return}bC=bF.Callbacks("once memory");if(av.readyState==="complete"){return setTimeout(bF.ready,1)}if(av.addEventListener){av.addEventListener("DOMContentLoaded",e,false);bb.addEventListener("load",bF.ready,false)}else{if(av.attachEvent){av.attachEvent("onreadystatechange",e);bb.attachEvent("onload",bF.ready);var b0=false;try{b0=bb.frameElement==null}catch(b1){}if(av.documentElement.doScroll&&b0){bw()}}}},isFunction:function(b0){return bF.type(b0)==="function"},isArray:Array.isArray||function(b0){return bF.type(b0)==="array"},isWindow:function(b0){return b0&&typeof b0==="object"&&"setInterval" in b0},isNumeric:function(b0){return !isNaN(parseFloat(b0))&&isFinite(b0)},type:function(b0){return b0==null?String(b0):bx[bL.call(b0)]||"object"},isPlainObject:function(b2){if(!b2||bF.type(b2)!=="object"||b2.nodeType||bF.isWindow(b2)){return false}try{if(b2.constructor&&!bG.call(b2,"constructor")&&!bG.call(b2.constructor.prototype,"isPrototypeOf")){return false}}catch(b1){return false}var b0;for(b0 in b2){}return b0===L||bG.call(b2,b0)},isEmptyObject:function(b1){for(var b0 in b1){return false}return true},error:function(b0){throw new Error(b0)},parseJSON:function(b0){if(typeof b0!=="string"||!b0){return null}b0=bF.trim(b0);if(bb.JSON&&bb.JSON.parse){return bb.JSON.parse(b0)}if(bN.test(b0.replace(bW,"@").replace(bP,"]").replace(bJ,""))){return(new Function("return "+b0))()}bF.error("Invalid JSON: "+b0)},parseXML:function(b2){var b0,b1;try{if(bb.DOMParser){b1=new DOMParser();b0=b1.parseFromString(b2,"text/xml")}else{b0=new ActiveXObject("Microsoft.XMLDOM");b0.async="false";b0.loadXML(b2)}}catch(b3){b0=L}if(!b0||!b0.documentElement||b0.getElementsByTagName("parsererror").length){bF.error("Invalid XML: "+b2)}return b0},noop:function(){},globalEval:function(b0){if(b0&&bM.test(b0)){(bb.execScript||function(b1){bb["eval"].call(bb,b1)})(b0)}},camelCase:function(b0){return b0.replace(bZ,"ms-").replace(bB,bT)},nodeName:function(b1,b0){return b1.nodeName&&b1.nodeName.toUpperCase()===b0.toUpperCase()},each:function(b3,b6,b2){var b1,b4=0,b5=b3.length,b0=b5===L||bF.isFunction(b3);if(b2){if(b0){for(b1 in b3){if(b6.apply(b3[b1],b2)===false){break}}}else{for(;b40&&b0[0]&&b0[b1-1])||b1===0||bF.isArray(b0));if(b3){for(;b21?aJ.call(arguments,0):bG;if(!(--bw)){bC.resolveWith(bC,bx)}}}function bz(bF){return function(bG){bB[bF]=arguments.length>1?aJ.call(arguments,0):bG;bC.notifyWith(bE,bB)}}if(e>1){for(;bv
a";bI=bv.getElementsByTagName("*");bF=bv.getElementsByTagName("a")[0];if(!bI||!bI.length||!bF){return{}}bG=av.createElement("select");bx=bG.appendChild(av.createElement("option"));bE=bv.getElementsByTagName("input")[0];bJ={leadingWhitespace:(bv.firstChild.nodeType===3),tbody:!bv.getElementsByTagName("tbody").length,htmlSerialize:!!bv.getElementsByTagName("link").length,style:/top/.test(bF.getAttribute("style")),hrefNormalized:(bF.getAttribute("href")==="/a"),opacity:/^0.55/.test(bF.style.opacity),cssFloat:!!bF.style.cssFloat,checkOn:(bE.value==="on"),optSelected:bx.selected,getSetAttribute:bv.className!=="t",enctype:!!av.createElement("form").enctype,html5Clone:av.createElement("nav").cloneNode(true).outerHTML!=="<:nav>",submitBubbles:true,changeBubbles:true,focusinBubbles:false,deleteExpando:true,noCloneEvent:true,inlineBlockNeedsLayout:false,shrinkWrapBlocks:false,reliableMarginRight:true};bE.checked=true;bJ.noCloneChecked=bE.cloneNode(true).checked;bG.disabled=true;bJ.optDisabled=!bx.disabled;try{delete bv.test}catch(bC){bJ.deleteExpando=false}if(!bv.addEventListener&&bv.attachEvent&&bv.fireEvent){bv.attachEvent("onclick",function(){bJ.noCloneEvent=false});bv.cloneNode(true).fireEvent("onclick")}bE=av.createElement("input");bE.value="t";bE.setAttribute("type","radio");bJ.radioValue=bE.value==="t";bE.setAttribute("checked","checked");bv.appendChild(bE);bD=av.createDocumentFragment();bD.appendChild(bv.lastChild);bJ.checkClone=bD.cloneNode(true).cloneNode(true).lastChild.checked;bJ.appendChecked=bE.checked;bD.removeChild(bE);bD.appendChild(bv);bv.innerHTML="";if(bb.getComputedStyle){bA=av.createElement("div");bA.style.width="0";bA.style.marginRight="0";bv.style.width="2px";bv.appendChild(bA);bJ.reliableMarginRight=(parseInt((bb.getComputedStyle(bA,null)||{marginRight:0}).marginRight,10)||0)===0}if(bv.attachEvent){for(by in {submit:1,change:1,focusin:1}){bB="on"+by;bw=(bB in bv);if(!bw){bv.setAttribute(bB,"return;");bw=(typeof bv[bB]==="function")}bJ[by+"Bubbles"]=bw}}bD.removeChild(bv);bD=bG=bx=bA=bv=bE=null;b(function(){var bM,bU,bV,bT,bN,bO,bL,bS,bR,e,bP,bQ=av.getElementsByTagName("body")[0];if(!bQ){return}bL=1;bS="position:absolute;top:0;left:0;width:1px;height:1px;margin:0;";bR="visibility:hidden;border:0;";e="style='"+bS+"border:5px solid #000;padding:0;'";bP="
";bM=av.createElement("div");bM.style.cssText=bR+"width:0;height:0;position:static;top:0;margin-top:"+bL+"px";bQ.insertBefore(bM,bQ.firstChild);bv=av.createElement("div");bM.appendChild(bv);bv.innerHTML="
t
";bz=bv.getElementsByTagName("td");bw=(bz[0].offsetHeight===0);bz[0].style.display="";bz[1].style.display="none";bJ.reliableHiddenOffsets=bw&&(bz[0].offsetHeight===0);bv.innerHTML="";bv.style.width=bv.style.paddingLeft="1px";b.boxModel=bJ.boxModel=bv.offsetWidth===2;if(typeof bv.style.zoom!=="undefined"){bv.style.display="inline";bv.style.zoom=1;bJ.inlineBlockNeedsLayout=(bv.offsetWidth===2);bv.style.display="";bv.innerHTML="
";bJ.shrinkWrapBlocks=(bv.offsetWidth!==2)}bv.style.cssText=bS+bR;bv.innerHTML=bP;bU=bv.firstChild;bV=bU.firstChild;bN=bU.nextSibling.firstChild.firstChild;bO={doesNotAddBorder:(bV.offsetTop!==5),doesAddBorderForTableAndCells:(bN.offsetTop===5)};bV.style.position="fixed";bV.style.top="20px";bO.fixedPosition=(bV.offsetTop===20||bV.offsetTop===15);bV.style.position=bV.style.top="";bU.style.overflow="hidden";bU.style.position="relative";bO.subtractsBorderForOverflowNotVisible=(bV.offsetTop===-5);bO.doesNotIncludeMarginInBodyOffset=(bQ.offsetTop!==bL);bQ.removeChild(bM);bv=bM=null;b.extend(bJ,bO)});return bJ})();var aS=/^(?:\{.*\}|\[.*\])$/,aA=/([A-Z])/g;b.extend({cache:{},uuid:0,expando:"jQuery"+(b.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:true,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:true},hasData:function(e){e=e.nodeType?b.cache[e[b.expando]]:e[b.expando];return !!e&&!S(e)},data:function(bx,bv,bz,by){if(!b.acceptData(bx)){return}var bG,bA,bD,bE=b.expando,bC=typeof bv==="string",bF=bx.nodeType,e=bF?b.cache:bx,bw=bF?bx[bE]:bx[bE]&&bE,bB=bv==="events";if((!bw||!e[bw]||(!bB&&!by&&!e[bw].data))&&bC&&bz===L){return}if(!bw){if(bF){bx[bE]=bw=++b.uuid}else{bw=bE}}if(!e[bw]){e[bw]={};if(!bF){e[bw].toJSON=b.noop}}if(typeof bv==="object"||typeof bv==="function"){if(by){e[bw]=b.extend(e[bw],bv)}else{e[bw].data=b.extend(e[bw].data,bv)}}bG=bA=e[bw];if(!by){if(!bA.data){bA.data={}}bA=bA.data}if(bz!==L){bA[b.camelCase(bv)]=bz}if(bB&&!bA[bv]){return bG.events}if(bC){bD=bA[bv];if(bD==null){bD=bA[b.camelCase(bv)]}}else{bD=bA}return bD},removeData:function(bx,bv,by){if(!b.acceptData(bx)){return}var bB,bA,bz,bC=b.expando,bD=bx.nodeType,e=bD?b.cache:bx,bw=bD?bx[bC]:bC;if(!e[bw]){return}if(bv){bB=by?e[bw]:e[bw].data;if(bB){if(!b.isArray(bv)){if(bv in bB){bv=[bv]}else{bv=b.camelCase(bv);if(bv in bB){bv=[bv]}else{bv=bv.split(" ")}}}for(bA=0,bz=bv.length;bA-1){return true}}return false},val:function(bx){var e,bv,by,bw=this[0];if(!arguments.length){if(bw){e=b.valHooks[bw.nodeName.toLowerCase()]||b.valHooks[bw.type];if(e&&"get" in e&&(bv=e.get(bw,"value"))!==L){return bv}bv=bw.value;return typeof bv==="string"?bv.replace(aU,""):bv==null?"":bv}return}by=b.isFunction(bx);return this.each(function(bA){var bz=b(this),bB;if(this.nodeType!==1){return}if(by){bB=bx.call(this,bA,bz.val())}else{bB=bx}if(bB==null){bB=""}else{if(typeof bB==="number"){bB+=""}else{if(b.isArray(bB)){bB=b.map(bB,function(bC){return bC==null?"":bC+""})}}}e=b.valHooks[this.nodeName.toLowerCase()]||b.valHooks[this.type];if(!e||!("set" in e)||e.set(this,bB,"value")===L){this.value=bB}})}});b.extend({valHooks:{option:{get:function(e){var bv=e.attributes.value;return !bv||bv.specified?e.value:e.text}},select:{get:function(e){var bA,bv,bz,bx,by=e.selectedIndex,bB=[],bC=e.options,bw=e.type==="select-one";if(by<0){return null}bv=bw?by:0;bz=bw?by+1:bC.length;for(;bv=0});if(!e.length){bv.selectedIndex=-1}return e}}},attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(bA,bx,bB,bz){var bw,e,by,bv=bA.nodeType; +if(!bA||bv===3||bv===8||bv===2){return}if(bz&&bx in b.attrFn){return b(bA)[bx](bB)}if(typeof bA.getAttribute==="undefined"){return b.prop(bA,bx,bB)}by=bv!==1||!b.isXMLDoc(bA);if(by){bx=bx.toLowerCase();e=b.attrHooks[bx]||(ao.test(bx)?aY:be)}if(bB!==L){if(bB===null){b.removeAttr(bA,bx);return}else{if(e&&"set" in e&&by&&(bw=e.set(bA,bB,bx))!==L){return bw}else{bA.setAttribute(bx,""+bB);return bB}}}else{if(e&&"get" in e&&by&&(bw=e.get(bA,bx))!==null){return bw}else{bw=bA.getAttribute(bx);return bw===null?L:bw}}},removeAttr:function(bx,bz){var by,bA,bv,e,bw=0;if(bz&&bx.nodeType===1){bA=bz.toLowerCase().split(af);e=bA.length;for(;bw=0)}}})});var bd=/^(?:textarea|input|select)$/i,n=/^([^\.]*)?(?:\.(.+))?$/,J=/\bhover(\.\S+)?\b/,aO=/^key/,bf=/^(?:mouse|contextmenu)|click/,T=/^(?:focusinfocus|focusoutblur)$/,U=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,Y=function(e){var bv=U.exec(e);if(bv){bv[1]=(bv[1]||"").toLowerCase();bv[3]=bv[3]&&new RegExp("(?:^|\\s)"+bv[3]+"(?:\\s|$)")}return bv},j=function(bw,e){var bv=bw.attributes||{};return((!e[1]||bw.nodeName.toLowerCase()===e[1])&&(!e[2]||(bv.id||{}).value===e[2])&&(!e[3]||e[3].test((bv["class"]||{}).value)))},bt=function(e){return b.event.special.hover?e:e.replace(J,"mouseenter$1 mouseleave$1")};b.event={add:function(bx,bC,bJ,bA,by){var bD,bB,bK,bI,bH,bF,e,bG,bv,bz,bw,bE;if(bx.nodeType===3||bx.nodeType===8||!bC||!bJ||!(bD=b._data(bx))){return}if(bJ.handler){bv=bJ;bJ=bv.handler}if(!bJ.guid){bJ.guid=b.guid++}bK=bD.events;if(!bK){bD.events=bK={}}bB=bD.handle;if(!bB){bD.handle=bB=function(bL){return typeof b!=="undefined"&&(!bL||b.event.triggered!==bL.type)?b.event.dispatch.apply(bB.elem,arguments):L};bB.elem=bx}bC=b.trim(bt(bC)).split(" ");for(bI=0;bI=0){bG=bG.slice(0,-1);bw=true}if(bG.indexOf(".")>=0){bx=bG.split(".");bG=bx.shift();bx.sort()}if((!bA||b.event.customEvent[bG])&&!b.event.global[bG]){return}bv=typeof bv==="object"?bv[b.expando]?bv:new b.Event(bG,bv):new b.Event(bG);bv.type=bG;bv.isTrigger=true;bv.exclusive=bw;bv.namespace=bx.join(".");bv.namespace_re=bv.namespace?new RegExp("(^|\\.)"+bx.join("\\.(?:.*\\.)?")+"(\\.|$)"):null;by=bG.indexOf(":")<0?"on"+bG:"";if(!bA){e=b.cache;for(bC in e){if(e[bC].events&&e[bC].events[bG]){b.event.trigger(bv,bD,e[bC].handle.elem,true)}}return}bv.result=L;if(!bv.target){bv.target=bA}bD=bD!=null?b.makeArray(bD):[];bD.unshift(bv);bF=b.event.special[bG]||{};if(bF.trigger&&bF.trigger.apply(bA,bD)===false){return}bB=[[bA,bF.bindType||bG]];if(!bJ&&!bF.noBubble&&!b.isWindow(bA)){bI=bF.delegateType||bG;bH=T.test(bI+bG)?bA:bA.parentNode;bz=null;for(;bH;bH=bH.parentNode){bB.push([bH,bI]);bz=bH}if(bz&&bz===bA.ownerDocument){bB.push([bz.defaultView||bz.parentWindow||bb,bI])}}for(bC=0;bCbA){bH.push({elem:this,matches:bz.slice(bA)})}for(bC=0;bC0?this.on(e,null,bx,bw):this.trigger(e)};if(b.attrFn){b.attrFn[e]=true}if(aO.test(e)){b.event.fixHooks[e]=b.event.keyHooks}if(bf.test(e)){b.event.fixHooks[e]=b.event.mouseHooks}}); +/*! + * Sizzle CSS Selector Engine + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){var bH=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,bC="sizcache"+(Math.random()+"").replace(".",""),bI=0,bL=Object.prototype.toString,bB=false,bA=true,bK=/\\/g,bO=/\r\n/g,bQ=/\W/;[0,0].sort(function(){bA=false;return 0});var by=function(bV,e,bY,bZ){bY=bY||[];e=e||av;var b1=e;if(e.nodeType!==1&&e.nodeType!==9){return[]}if(!bV||typeof bV!=="string"){return bY}var bS,b3,b6,bR,b2,b5,b4,bX,bU=true,bT=by.isXML(e),bW=[],b0=bV;do{bH.exec("");bS=bH.exec(b0);if(bS){b0=bS[3];bW.push(bS[1]);if(bS[2]){bR=bS[3];break}}}while(bS);if(bW.length>1&&bD.exec(bV)){if(bW.length===2&&bE.relative[bW[0]]){b3=bM(bW[0]+bW[1],e,bZ)}else{b3=bE.relative[bW[0]]?[e]:by(bW.shift(),e);while(bW.length){bV=bW.shift();if(bE.relative[bV]){bV+=bW.shift()}b3=bM(bV,b3,bZ)}}}else{if(!bZ&&bW.length>1&&e.nodeType===9&&!bT&&bE.match.ID.test(bW[0])&&!bE.match.ID.test(bW[bW.length-1])){b2=by.find(bW.shift(),e,bT);e=b2.expr?by.filter(b2.expr,b2.set)[0]:b2.set[0]}if(e){b2=bZ?{expr:bW.pop(),set:bF(bZ)}:by.find(bW.pop(),bW.length===1&&(bW[0]==="~"||bW[0]==="+")&&e.parentNode?e.parentNode:e,bT);b3=b2.expr?by.filter(b2.expr,b2.set):b2.set;if(bW.length>0){b6=bF(b3)}else{bU=false}while(bW.length){b5=bW.pop();b4=b5;if(!bE.relative[b5]){b5=""}else{b4=bW.pop()}if(b4==null){b4=e}bE.relative[b5](b6,b4,bT)}}else{b6=bW=[]}}if(!b6){b6=b3}if(!b6){by.error(b5||bV)}if(bL.call(b6)==="[object Array]"){if(!bU){bY.push.apply(bY,b6)}else{if(e&&e.nodeType===1){for(bX=0;b6[bX]!=null;bX++){if(b6[bX]&&(b6[bX]===true||b6[bX].nodeType===1&&by.contains(e,b6[bX]))){bY.push(b3[bX])}}}else{for(bX=0;b6[bX]!=null;bX++){if(b6[bX]&&b6[bX].nodeType===1){bY.push(b3[bX])}}}}}else{bF(b6,bY)}if(bR){by(bR,b1,bY,bZ);by.uniqueSort(bY)}return bY};by.uniqueSort=function(bR){if(bJ){bB=bA;bR.sort(bJ);if(bB){for(var e=1;e0};by.find=function(bX,e,bY){var bW,bS,bU,bT,bV,bR;if(!bX){return[]}for(bS=0,bU=bE.order.length;bS":function(bW,bR){var bV,bU=typeof bR==="string",bS=0,e=bW.length;if(bU&&!bQ.test(bR)){bR=bR.toLowerCase();for(;bS=0)){if(!bS){e.push(bV)}}else{if(bS){bR[bU]=false}}}}return false},ID:function(e){return e[1].replace(bK,"")},TAG:function(bR,e){return bR[1].replace(bK,"").toLowerCase()},CHILD:function(e){if(e[1]==="nth"){if(!e[2]){by.error(e[0])}e[2]=e[2].replace(/^\+|\s*/g,"");var bR=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(e[2]==="even"&&"2n"||e[2]==="odd"&&"2n+1"||!/\D/.test(e[2])&&"0n+"+e[2]||e[2]);e[2]=(bR[1]+(bR[2]||1))-0;e[3]=bR[3]-0}else{if(e[2]){by.error(e[0])}}e[0]=bI++;return e},ATTR:function(bU,bR,bS,e,bV,bW){var bT=bU[1]=bU[1].replace(bK,"");if(!bW&&bE.attrMap[bT]){bU[1]=bE.attrMap[bT]}bU[4]=(bU[4]||bU[5]||"").replace(bK,"");if(bU[2]==="~="){bU[4]=" "+bU[4]+" "}return bU},PSEUDO:function(bU,bR,bS,e,bV){if(bU[1]==="not"){if((bH.exec(bU[3])||"").length>1||/^\w/.test(bU[3])){bU[3]=by(bU[3],null,null,bR)}else{var bT=by.filter(bU[3],bR,bS,true^bV);if(!bS){e.push.apply(e,bT)}return false}}else{if(bE.match.POS.test(bU[0])||bE.match.CHILD.test(bU[0])){return true}}return bU},POS:function(e){e.unshift(true);return e}},filters:{enabled:function(e){return e.disabled===false&&e.type!=="hidden"},disabled:function(e){return e.disabled===true},checked:function(e){return e.checked===true},selected:function(e){if(e.parentNode){e.parentNode.selectedIndex}return e.selected===true},parent:function(e){return !!e.firstChild},empty:function(e){return !e.firstChild},has:function(bS,bR,e){return !!by(e[3],bS).length},header:function(e){return(/h\d/i).test(e.nodeName)},text:function(bS){var e=bS.getAttribute("type"),bR=bS.type;return bS.nodeName.toLowerCase()==="input"&&"text"===bR&&(e===bR||e===null)},radio:function(e){return e.nodeName.toLowerCase()==="input"&&"radio"===e.type},checkbox:function(e){return e.nodeName.toLowerCase()==="input"&&"checkbox"===e.type},file:function(e){return e.nodeName.toLowerCase()==="input"&&"file"===e.type},password:function(e){return e.nodeName.toLowerCase()==="input"&&"password"===e.type},submit:function(bR){var e=bR.nodeName.toLowerCase();return(e==="input"||e==="button")&&"submit"===bR.type},image:function(e){return e.nodeName.toLowerCase()==="input"&&"image"===e.type},reset:function(bR){var e=bR.nodeName.toLowerCase();return(e==="input"||e==="button")&&"reset"===bR.type},button:function(bR){var e=bR.nodeName.toLowerCase();return e==="input"&&"button"===bR.type||e==="button"},input:function(e){return(/input|select|textarea|button/i).test(e.nodeName)},focus:function(e){return e===e.ownerDocument.activeElement}},setFilters:{first:function(bR,e){return e===0},last:function(bS,bR,e,bT){return bR===bT.length-1},even:function(bR,e){return e%2===0},odd:function(bR,e){return e%2===1 +},lt:function(bS,bR,e){return bRe[3]-0},nth:function(bS,bR,e){return e[3]-0===bR},eq:function(bS,bR,e){return e[3]-0===bR}},filter:{PSEUDO:function(bS,bX,bW,bY){var e=bX[1],bR=bE.filters[e];if(bR){return bR(bS,bW,bX,bY)}else{if(e==="contains"){return(bS.textContent||bS.innerText||bw([bS])||"").indexOf(bX[3])>=0}else{if(e==="not"){var bT=bX[3];for(var bV=0,bU=bT.length;bV=0)}}},ID:function(bR,e){return bR.nodeType===1&&bR.getAttribute("id")===e},TAG:function(bR,e){return(e==="*"&&bR.nodeType===1)||!!bR.nodeName&&bR.nodeName.toLowerCase()===e},CLASS:function(bR,e){return(" "+(bR.className||bR.getAttribute("class"))+" ").indexOf(e)>-1},ATTR:function(bV,bT){var bS=bT[1],e=by.attr?by.attr(bV,bS):bE.attrHandle[bS]?bE.attrHandle[bS](bV):bV[bS]!=null?bV[bS]:bV.getAttribute(bS),bW=e+"",bU=bT[2],bR=bT[4];return e==null?bU==="!=":!bU&&by.attr?e!=null:bU==="="?bW===bR:bU==="*="?bW.indexOf(bR)>=0:bU==="~="?(" "+bW+" ").indexOf(bR)>=0:!bR?bW&&e!==false:bU==="!="?bW!==bR:bU==="^="?bW.indexOf(bR)===0:bU==="$="?bW.substr(bW.length-bR.length)===bR:bU==="|="?bW===bR||bW.substr(0,bR.length+1)===bR+"-":false},POS:function(bU,bR,bS,bV){var e=bR[2],bT=bE.setFilters[e];if(bT){return bT(bU,bS,bR,bV)}}}};var bD=bE.match.POS,bx=function(bR,e){return"\\"+(e-0+1)};for(var bz in bE.match){bE.match[bz]=new RegExp(bE.match[bz].source+(/(?![^\[]*\])(?![^\(]*\))/.source));bE.leftMatch[bz]=new RegExp(/(^(?:.|\r|\n)*?)/.source+bE.match[bz].source.replace(/\\(\d+)/g,bx))}var bF=function(bR,e){bR=Array.prototype.slice.call(bR,0);if(e){e.push.apply(e,bR);return e}return bR};try{Array.prototype.slice.call(av.documentElement.childNodes,0)[0].nodeType}catch(bP){bF=function(bU,bT){var bS=0,bR=bT||[];if(bL.call(bU)==="[object Array]"){Array.prototype.push.apply(bR,bU)}else{if(typeof bU.length==="number"){for(var e=bU.length;bS";e.insertBefore(bR,e.firstChild);if(av.getElementById(bS)){bE.find.ID=function(bU,bV,bW){if(typeof bV.getElementById!=="undefined"&&!bW){var bT=bV.getElementById(bU[1]);return bT?bT.id===bU[1]||typeof bT.getAttributeNode!=="undefined"&&bT.getAttributeNode("id").nodeValue===bU[1]?[bT]:L:[]}};bE.filter.ID=function(bV,bT){var bU=typeof bV.getAttributeNode!=="undefined"&&bV.getAttributeNode("id");return bV.nodeType===1&&bU&&bU.nodeValue===bT}}e.removeChild(bR);e=bR=null})();(function(){var e=av.createElement("div");e.appendChild(av.createComment(""));if(e.getElementsByTagName("*").length>0){bE.find.TAG=function(bR,bV){var bU=bV.getElementsByTagName(bR[1]);if(bR[1]==="*"){var bT=[];for(var bS=0;bU[bS];bS++){if(bU[bS].nodeType===1){bT.push(bU[bS])}}bU=bT}return bU}}e.innerHTML="";if(e.firstChild&&typeof e.firstChild.getAttribute!=="undefined"&&e.firstChild.getAttribute("href")!=="#"){bE.attrHandle.href=function(bR){return bR.getAttribute("href",2)}}e=null})();if(av.querySelectorAll){(function(){var e=by,bT=av.createElement("div"),bS="__sizzle__";bT.innerHTML="

";if(bT.querySelectorAll&&bT.querySelectorAll(".TEST").length===0){return}by=function(b4,bV,bZ,b3){bV=bV||av;if(!b3&&!by.isXML(bV)){var b2=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b4);if(b2&&(bV.nodeType===1||bV.nodeType===9)){if(b2[1]){return bF(bV.getElementsByTagName(b4),bZ)}else{if(b2[2]&&bE.find.CLASS&&bV.getElementsByClassName){return bF(bV.getElementsByClassName(b2[2]),bZ)}}}if(bV.nodeType===9){if(b4==="body"&&bV.body){return bF([bV.body],bZ)}else{if(b2&&b2[3]){var bY=bV.getElementById(b2[3]);if(bY&&bY.parentNode){if(bY.id===b2[3]){return bF([bY],bZ)}}else{return bF([],bZ)}}}try{return bF(bV.querySelectorAll(b4),bZ)}catch(b0){}}else{if(bV.nodeType===1&&bV.nodeName.toLowerCase()!=="object"){var bW=bV,bX=bV.getAttribute("id"),bU=bX||bS,b6=bV.parentNode,b5=/^\s*[+~]/.test(b4);if(!bX){bV.setAttribute("id",bU)}else{bU=bU.replace(/'/g,"\\$&")}if(b5&&b6){bV=bV.parentNode}try{if(!b5||b6){return bF(bV.querySelectorAll("[id='"+bU+"'] "+b4),bZ)}}catch(b1){}finally{if(!bX){bW.removeAttribute("id")}}}}}return e(b4,bV,bZ,b3)};for(var bR in e){by[bR]=e[bR]}bT=null})()}(function(){var e=av.documentElement,bS=e.matchesSelector||e.mozMatchesSelector||e.webkitMatchesSelector||e.msMatchesSelector;if(bS){var bU=!bS.call(av.createElement("div"),"div"),bR=false;try{bS.call(av.documentElement,"[test!='']:sizzle")}catch(bT){bR=true}by.matchesSelector=function(bW,bY){bY=bY.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!by.isXML(bW)){try{if(bR||!bE.match.PSEUDO.test(bY)&&!/!=/.test(bY)){var bV=bS.call(bW,bY);if(bV||!bU||bW.document&&bW.document.nodeType!==11){return bV}}}catch(bX){}}return by(bY,null,null,[bW]).length>0}}})();(function(){var e=av.createElement("div");e.innerHTML="
";if(!e.getElementsByClassName||e.getElementsByClassName("e").length===0){return}e.lastChild.className="e";if(e.getElementsByClassName("e").length===1){return}bE.order.splice(1,0,"CLASS");bE.find.CLASS=function(bR,bS,bT){if(typeof bS.getElementsByClassName!=="undefined"&&!bT){return bS.getElementsByClassName(bR[1])}};e=null})();function bv(bR,bW,bV,bZ,bX,bY){for(var bT=0,bS=bZ.length;bT0){bU=e;break}}}e=e[bR]}bZ[bT]=bU}}}if(av.documentElement.contains){by.contains=function(bR,e){return bR!==e&&(bR.contains?bR.contains(e):true)}}else{if(av.documentElement.compareDocumentPosition){by.contains=function(bR,e){return !!(bR.compareDocumentPosition(e)&16)}}else{by.contains=function(){return false}}}by.isXML=function(e){var bR=(e?e.ownerDocument||e:0).documentElement;return bR?bR.nodeName!=="HTML":false};var bM=function(bS,e,bW){var bV,bX=[],bU="",bY=e.nodeType?[e]:e;while((bV=bE.match.PSEUDO.exec(bS))){bU+=bV[0];bS=bS.replace(bE.match.PSEUDO,"")}bS=bE.relative[bS]?bS+"*":bS;for(var bT=0,bR=bY.length;bT0){for(bB=bA;bB=0:b.filter(e,this).length>0:this.filter(e).length>0)},closest:function(by,bx){var bv=[],bw,e,bz=this[0];if(b.isArray(by)){var bB=1;while(bz&&bz.ownerDocument&&bz!==bx){for(bw=0;bw-1:b.find.matchesSelector(bz,by)){bv.push(bz);break}else{bz=bz.parentNode;if(!bz||!bz.ownerDocument||bz===bx||bz.nodeType===11){break}}}}bv=bv.length>1?b.unique(bv):bv;return this.pushStack(bv,"closest",by)},index:function(e){if(!e){return(this[0]&&this[0].parentNode)?this.prevAll().length:-1}if(typeof e==="string"){return b.inArray(this[0],b(e))}return b.inArray(e.jquery?e[0]:e,this)},add:function(e,bv){var bx=typeof e==="string"?b(e,bv):b.makeArray(e&&e.nodeType?[e]:e),bw=b.merge(this.get(),bx);return this.pushStack(C(bx[0])||C(bw[0])?bw:b.unique(bw))},andSelf:function(){return this.add(this.prevObject)}});function C(e){return !e||!e.parentNode||e.parentNode.nodeType===11}b.each({parent:function(bv){var e=bv.parentNode;return e&&e.nodeType!==11?e:null},parents:function(e){return b.dir(e,"parentNode")},parentsUntil:function(bv,e,bw){return b.dir(bv,"parentNode",bw)},next:function(e){return b.nth(e,2,"nextSibling")},prev:function(e){return b.nth(e,2,"previousSibling")},nextAll:function(e){return b.dir(e,"nextSibling")},prevAll:function(e){return b.dir(e,"previousSibling")},nextUntil:function(bv,e,bw){return b.dir(bv,"nextSibling",bw)},prevUntil:function(bv,e,bw){return b.dir(bv,"previousSibling",bw)},siblings:function(e){return b.sibling(e.parentNode.firstChild,e)},children:function(e){return b.sibling(e.firstChild)},contents:function(e){return b.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:b.makeArray(e.childNodes)}},function(e,bv){b.fn[e]=function(by,bw){var bx=b.map(this,bv,by);if(!ab.test(e)){bw=by}if(bw&&typeof bw==="string"){bx=b.filter(bw,bx)}bx=this.length>1&&!ay[e]?b.unique(bx):bx;if((this.length>1||a9.test(bw))&&aq.test(e)){bx=bx.reverse()}return this.pushStack(bx,e,P.call(arguments).join(","))}});b.extend({filter:function(bw,e,bv){if(bv){bw=":not("+bw+")"}return e.length===1?b.find.matchesSelector(e[0],bw)?[e[0]]:[]:b.find.matches(bw,e)},dir:function(bw,bv,by){var e=[],bx=bw[bv];while(bx&&bx.nodeType!==9&&(by===L||bx.nodeType!==1||!b(bx).is(by))){if(bx.nodeType===1){e.push(bx)}bx=bx[bv]}return e},nth:function(by,e,bw,bx){e=e||1;var bv=0;for(;by;by=by[bw]){if(by.nodeType===1&&++bv===e){break}}return by},sibling:function(bw,bv){var e=[];for(;bw;bw=bw.nextSibling){if(bw.nodeType===1&&bw!==bv){e.push(bw)}}return e}});function aG(bx,bw,e){bw=bw||0;if(b.isFunction(bw)){return b.grep(bx,function(bz,by){var bA=!!bw.call(bz,by,bz);return bA===e})}else{if(bw.nodeType){return b.grep(bx,function(bz,by){return(bz===bw)===e})}else{if(typeof bw==="string"){var bv=b.grep(bx,function(by){return by.nodeType===1});if(bp.test(bw)){return b.filter(bw,bv,!e)}else{bw=b.filter(bw,bv)}}}}return b.grep(bx,function(bz,by){return(b.inArray(bz,bw)>=0)===e})}function a(e){var bw=aR.split("|"),bv=e.createDocumentFragment();if(bv.createElement){while(bw.length){bv.createElement(bw.pop())}}return bv}var aR="abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",ag=/ jQuery\d+="(?:\d+|null)"/g,ar=/^\s+/,R=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,d=/<([\w:]+)/,w=/",""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]},ac=a(av); +ax.optgroup=ax.option;ax.tbody=ax.tfoot=ax.colgroup=ax.caption=ax.thead;ax.th=ax.td;if(!b.support.htmlSerialize){ax._default=[1,"div
","
"]}b.fn.extend({text:function(e){if(b.isFunction(e)){return this.each(function(bw){var bv=b(this);bv.text(e.call(this,bw,bv.text()))})}if(typeof e!=="object"&&e!==L){return this.empty().append((this[0]&&this[0].ownerDocument||av).createTextNode(e))}return b.text(this)},wrapAll:function(e){if(b.isFunction(e)){return this.each(function(bw){b(this).wrapAll(e.call(this,bw))})}if(this[0]){var bv=b(e,this[0].ownerDocument).eq(0).clone(true);if(this[0].parentNode){bv.insertBefore(this[0])}bv.map(function(){var bw=this;while(bw.firstChild&&bw.firstChild.nodeType===1){bw=bw.firstChild}return bw}).append(this)}return this},wrapInner:function(e){if(b.isFunction(e)){return this.each(function(bv){b(this).wrapInner(e.call(this,bv))})}return this.each(function(){var bv=b(this),bw=bv.contents();if(bw.length){bw.wrapAll(e)}else{bv.append(e)}})},wrap:function(e){var bv=b.isFunction(e);return this.each(function(bw){b(this).wrapAll(bv?e.call(this,bw):e)})},unwrap:function(){return this.parent().each(function(){if(!b.nodeName(this,"body")){b(this).replaceWith(this.childNodes)}}).end()},append:function(){return this.domManip(arguments,true,function(e){if(this.nodeType===1){this.appendChild(e)}})},prepend:function(){return this.domManip(arguments,true,function(e){if(this.nodeType===1){this.insertBefore(e,this.firstChild)}})},before:function(){if(this[0]&&this[0].parentNode){return this.domManip(arguments,false,function(bv){this.parentNode.insertBefore(bv,this)})}else{if(arguments.length){var e=b.clean(arguments);e.push.apply(e,this.toArray());return this.pushStack(e,"before",arguments)}}},after:function(){if(this[0]&&this[0].parentNode){return this.domManip(arguments,false,function(bv){this.parentNode.insertBefore(bv,this.nextSibling)})}else{if(arguments.length){var e=this.pushStack(this,"after",arguments);e.push.apply(e,b.clean(arguments));return e}}},remove:function(e,bx){for(var bv=0,bw;(bw=this[bv])!=null;bv++){if(!e||b.filter(e,[bw]).length){if(!bx&&bw.nodeType===1){b.cleanData(bw.getElementsByTagName("*"));b.cleanData([bw])}if(bw.parentNode){bw.parentNode.removeChild(bw)}}}return this},empty:function(){for(var e=0,bv;(bv=this[e])!=null;e++){if(bv.nodeType===1){b.cleanData(bv.getElementsByTagName("*"))}while(bv.firstChild){bv.removeChild(bv.firstChild)}}return this},clone:function(bv,e){bv=bv==null?false:bv;e=e==null?bv:e;return this.map(function(){return b.clone(this,bv,e)})},html:function(bx){if(bx===L){return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(ag,""):null}else{if(typeof bx==="string"&&!ae.test(bx)&&(b.support.leadingWhitespace||!ar.test(bx))&&!ax[(d.exec(bx)||["",""])[1].toLowerCase()]){bx=bx.replace(R,"<$1>");try{for(var bw=0,bv=this.length;bw1&&bw0?this.clone(true):this).get();b(bC[bA])[bv](by);bz=bz.concat(by)}return this.pushStack(bz,e,bC.selector)}}});function bg(e){if(typeof e.getElementsByTagName!=="undefined"){return e.getElementsByTagName("*")}else{if(typeof e.querySelectorAll!=="undefined"){return e.querySelectorAll("*")}else{return[]}}}function az(e){if(e.type==="checkbox"||e.type==="radio"){e.defaultChecked=e.checked}}function E(e){var bv=(e.nodeName||"").toLowerCase();if(bv==="input"){az(e)}else{if(bv!=="script"&&typeof e.getElementsByTagName!=="undefined"){b.grep(e.getElementsByTagName("input"),az)}}}function al(e){var bv=av.createElement("div");ac.appendChild(bv);bv.innerHTML=e.outerHTML;return bv.firstChild}b.extend({clone:function(by,bA,bw){var e,bv,bx,bz=b.support.html5Clone||!ah.test("<"+by.nodeName)?by.cloneNode(true):al(by);if((!b.support.noCloneEvent||!b.support.noCloneChecked)&&(by.nodeType===1||by.nodeType===11)&&!b.isXMLDoc(by)){ai(by,bz);e=bg(by);bv=bg(bz);for(bx=0;e[bx];++bx){if(bv[bx]){ai(e[bx],bv[bx])}}}if(bA){t(by,bz);if(bw){e=bg(by);bv=bg(bz);for(bx=0;e[bx];++bx){t(e[bx],bv[bx])}}}e=bv=null;return bz},clean:function(bw,by,bH,bA){var bF;by=by||av;if(typeof by.createElement==="undefined"){by=by.ownerDocument||by[0]&&by[0].ownerDocument||av}var bI=[],bB;for(var bE=0,bz;(bz=bw[bE])!=null;bE++){if(typeof bz==="number"){bz+=""}if(!bz){continue}if(typeof bz==="string"){if(!W.test(bz)){bz=by.createTextNode(bz)}else{bz=bz.replace(R,"<$1>");var bK=(d.exec(bz)||["",""])[1].toLowerCase(),bx=ax[bK]||ax._default,bD=bx[0],bv=by.createElement("div");if(by===av){ac.appendChild(bv)}else{a(by).appendChild(bv)}bv.innerHTML=bx[1]+bz+bx[2];while(bD--){bv=bv.lastChild}if(!b.support.tbody){var e=w.test(bz),bC=bK==="table"&&!e?bv.firstChild&&bv.firstChild.childNodes:bx[1]===""&&!e?bv.childNodes:[];for(bB=bC.length-1;bB>=0;--bB){if(b.nodeName(bC[bB],"tbody")&&!bC[bB].childNodes.length){bC[bB].parentNode.removeChild(bC[bB])}}}if(!b.support.leadingWhitespace&&ar.test(bz)){bv.insertBefore(by.createTextNode(ar.exec(bz)[0]),bv.firstChild)}bz=bv.childNodes}}var bG;if(!b.support.appendChecked){if(bz[0]&&typeof(bG=bz.length)==="number"){for(bB=0;bB=0){return bx+"px"}}else{return bx}}}});if(!b.support.opacity){b.cssHooks.opacity={get:function(bv,e){return au.test((e&&bv.currentStyle?bv.currentStyle.filter:bv.style.filter)||"")?(parseFloat(RegExp.$1)/100)+"":e?"1":""},set:function(by,bz){var bx=by.style,bv=by.currentStyle,e=b.isNumeric(bz)?"alpha(opacity="+bz*100+")":"",bw=bv&&bv.filter||bx.filter||"";bx.zoom=1;if(bz>=1&&b.trim(bw.replace(ak,""))===""){bx.removeAttribute("filter");if(bv&&!bv.filter){return}}bx.filter=ak.test(bw)?bw.replace(ak,e):bw+" "+e}}}b(function(){if(!b.support.reliableMarginRight){b.cssHooks.marginRight={get:function(bw,bv){var e;b.swap(bw,{display:"inline-block"},function(){if(bv){e=Z(bw,"margin-right","marginRight")}else{e=bw.style.marginRight}});return e}}}});if(av.defaultView&&av.defaultView.getComputedStyle){aI=function(by,bw){var bv,bx,e;bw=bw.replace(z,"-$1").toLowerCase();if((bx=by.ownerDocument.defaultView)&&(e=bx.getComputedStyle(by,null))){bv=e.getPropertyValue(bw);if(bv===""&&!b.contains(by.ownerDocument.documentElement,by)){bv=b.style(by,bw)}}return bv}}if(av.documentElement.currentStyle){aX=function(bz,bw){var bA,e,by,bv=bz.currentStyle&&bz.currentStyle[bw],bx=bz.style;if(bv===null&&bx&&(by=bx[bw])){bv=by}if(!bc.test(bv)&&bn.test(bv)){bA=bx.left;e=bz.runtimeStyle&&bz.runtimeStyle.left;if(e){bz.runtimeStyle.left=bz.currentStyle.left}bx.left=bw==="fontSize"?"1em":(bv||0);bv=bx.pixelLeft+"px";bx.left=bA;if(e){bz.runtimeStyle.left=e}}return bv===""?"auto":bv}}Z=aI||aX;function p(by,bw,bv){var bA=bw==="width"?by.offsetWidth:by.offsetHeight,bz=bw==="width"?an:a1,bx=0,e=bz.length; +if(bA>0){if(bv!=="border"){for(;bx)<[^<]*)*<\/script>/gi,q=/^(?:select|textarea)/i,h=/\s+/,br=/([?&])_=[^&]*/,K=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,A=b.fn.load,aa={},r={},aE,s,aV=["*/"]+["*"];try{aE=bl.href}catch(aw){aE=av.createElement("a");aE.href="";aE=aE.href}s=K.exec(aE.toLowerCase())||[];function f(e){return function(by,bA){if(typeof by!=="string"){bA=by;by="*"}if(b.isFunction(bA)){var bx=by.toLowerCase().split(h),bw=0,bz=bx.length,bv,bB,bC;for(;bw=0){var e=bw.slice(by,bw.length);bw=bw.slice(0,by)}var bx="GET";if(bz){if(b.isFunction(bz)){bA=bz;bz=L}else{if(typeof bz==="object"){bz=b.param(bz,b.ajaxSettings.traditional);bx="POST"}}}var bv=this;b.ajax({url:bw,type:bx,dataType:"html",data:bz,complete:function(bC,bB,bD){bD=bC.responseText;if(bC.isResolved()){bC.done(function(bE){bD=bE});bv.html(e?b("
").append(bD.replace(a6,"")).find(e):bD)}if(bA){bv.each(bA,[bD,bB,bC])}}});return this},serialize:function(){return b.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?b.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||q.test(this.nodeName)||aZ.test(this.type))}).map(function(e,bv){var bw=b(this).val();return bw==null?null:b.isArray(bw)?b.map(bw,function(by,bx){return{name:bv.name,value:by.replace(bs,"\r\n")}}):{name:bv.name,value:bw.replace(bs,"\r\n")}}).get()}});b.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(e,bv){b.fn[bv]=function(bw){return this.on(bv,bw)}});b.each(["get","post"],function(e,bv){b[bv]=function(bw,by,bz,bx){if(b.isFunction(by)){bx=bx||bz;bz=by;by=L}return b.ajax({type:bv,url:bw,data:by,success:bz,dataType:bx})}});b.extend({getScript:function(e,bv){return b.get(e,L,bv,"script")},getJSON:function(e,bv,bw){return b.get(e,bv,bw,"json")},ajaxSetup:function(bv,e){if(e){am(bv,b.ajaxSettings)}else{e=bv;bv=b.ajaxSettings}am(bv,e);return bv},ajaxSettings:{url:aE,isLocal:aM.test(s[1]),global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":aV},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":bb.String,"text html":true,"text json":b.parseJSON,"text xml":b.parseXML},flatOptions:{context:true,url:true}},ajaxPrefilter:f(aa),ajaxTransport:f(r),ajax:function(bz,bx){if(typeof bz==="object"){bx=bz;bz=L}bx=bx||{};var bD=b.ajaxSetup({},bx),bS=bD.context||bD,bG=bS!==bD&&(bS.nodeType||bS instanceof b)?b(bS):b.event,bR=b.Deferred(),bN=b.Callbacks("once memory"),bB=bD.statusCode||{},bC,bH={},bO={},bQ,by,bL,bE,bI,bA=0,bw,bK,bJ={readyState:0,setRequestHeader:function(bT,bU){if(!bA){var e=bT.toLowerCase();bT=bO[e]=bO[e]||bT;bH[bT]=bU}return this},getAllResponseHeaders:function(){return bA===2?bQ:null},getResponseHeader:function(bT){var e;if(bA===2){if(!by){by={};while((e=aD.exec(bQ))){by[e[1].toLowerCase()]=e[2]}}e=by[bT.toLowerCase()]}return e===L?null:e},overrideMimeType:function(e){if(!bA){bD.mimeType=e}return this},abort:function(e){e=e||"abort";if(bL){bL.abort(e)}bF(0,e);return this}};function bF(bZ,bU,b0,bW){if(bA===2){return}bA=2;if(bE){clearTimeout(bE)}bL=L;bQ=bW||"";bJ.readyState=bZ>0?4:0;var bT,b4,b3,bX=bU,bY=b0?bj(bD,bJ,b0):L,bV,b2;if(bZ>=200&&bZ<300||bZ===304){if(bD.ifModified){if((bV=bJ.getResponseHeader("Last-Modified"))){b.lastModified[bC]=bV}if((b2=bJ.getResponseHeader("Etag"))){b.etag[bC]=b2}}if(bZ===304){bX="notmodified";bT=true}else{try{b4=G(bD,bY);bX="success";bT=true}catch(b1){bX="parsererror";b3=b1}}}else{b3=bX;if(!bX||bZ){bX="error";if(bZ<0){bZ=0}}}bJ.status=bZ;bJ.statusText=""+(bU||bX);if(bT){bR.resolveWith(bS,[b4,bX,bJ])}else{bR.rejectWith(bS,[bJ,bX,b3])}bJ.statusCode(bB);bB=L;if(bw){bG.trigger("ajax"+(bT?"Success":"Error"),[bJ,bD,bT?b4:b3])}bN.fireWith(bS,[bJ,bX]);if(bw){bG.trigger("ajaxComplete",[bJ,bD]);if(!(--b.active)){b.event.trigger("ajaxStop")}}}bR.promise(bJ);bJ.success=bJ.done;bJ.error=bJ.fail;bJ.complete=bN.add;bJ.statusCode=function(bT){if(bT){var e;if(bA<2){for(e in bT){bB[e]=[bB[e],bT[e]]}}else{e=bT[bJ.status];bJ.then(e,e)}}return this};bD.url=((bz||bD.url)+"").replace(bq,"").replace(c,s[1]+"//");bD.dataTypes=b.trim(bD.dataType||"*").toLowerCase().split(h);if(bD.crossDomain==null){bI=K.exec(bD.url.toLowerCase());bD.crossDomain=!!(bI&&(bI[1]!=s[1]||bI[2]!=s[2]||(bI[3]||(bI[1]==="http:"?80:443))!=(s[3]||(s[1]==="http:"?80:443))))}if(bD.data&&bD.processData&&typeof bD.data!=="string"){bD.data=b.param(bD.data,bD.traditional)}aW(aa,bD,bx,bJ);if(bA===2){return false}bw=bD.global;bD.type=bD.type.toUpperCase();bD.hasContent=!aQ.test(bD.type);if(bw&&b.active++===0){b.event.trigger("ajaxStart")}if(!bD.hasContent){if(bD.data){bD.url+=(M.test(bD.url)?"&":"?")+bD.data;delete bD.data}bC=bD.url;if(bD.cache===false){var bv=b.now(),bP=bD.url.replace(br,"$1_="+bv);bD.url=bP+((bP===bD.url)?(M.test(bD.url)?"&":"?")+"_="+bv:"")}}if(bD.data&&bD.hasContent&&bD.contentType!==false||bx.contentType){bJ.setRequestHeader("Content-Type",bD.contentType)}if(bD.ifModified){bC=bC||bD.url;if(b.lastModified[bC]){bJ.setRequestHeader("If-Modified-Since",b.lastModified[bC])}if(b.etag[bC]){bJ.setRequestHeader("If-None-Match",b.etag[bC])}}bJ.setRequestHeader("Accept",bD.dataTypes[0]&&bD.accepts[bD.dataTypes[0]]?bD.accepts[bD.dataTypes[0]]+(bD.dataTypes[0]!=="*"?", "+aV+"; q=0.01":""):bD.accepts["*"]);for(bK in bD.headers){bJ.setRequestHeader(bK,bD.headers[bK])}if(bD.beforeSend&&(bD.beforeSend.call(bS,bJ,bD)===false||bA===2)){bJ.abort();return false}for(bK in {success:1,error:1,complete:1}){bJ[bK](bD[bK])}bL=aW(r,bD,bx,bJ);if(!bL){bF(-1,"No Transport")}else{bJ.readyState=1;if(bw){bG.trigger("ajaxSend",[bJ,bD])}if(bD.async&&bD.timeout>0){bE=setTimeout(function(){bJ.abort("timeout")},bD.timeout)}try{bA=1;bL.send(bH,bF)}catch(bM){if(bA<2){bF(-1,bM)}else{throw bM}}}return bJ},param:function(e,bw){var bv=[],by=function(bz,bA){bA=b.isFunction(bA)?bA():bA;bv[bv.length]=encodeURIComponent(bz)+"="+encodeURIComponent(bA)};if(bw===L){bw=b.ajaxSettings.traditional}if(b.isArray(e)||(e.jquery&&!b.isPlainObject(e))){b.each(e,function(){by(this.name,this.value)})}else{for(var bx in e){v(bx,e[bx],bw,by)}}return bv.join("&").replace(k,"+")}});function v(bw,by,bv,bx){if(b.isArray(by)){b.each(by,function(bA,bz){if(bv||ap.test(bw)){bx(bw,bz)}else{v(bw+"["+(typeof bz==="object"||b.isArray(bz)?bA:"")+"]",bz,bv,bx)}})}else{if(!bv&&by!=null&&typeof by==="object"){for(var e in by){v(bw+"["+e+"]",by[e],bv,bx)}}else{bx(bw,by)}}}b.extend({active:0,lastModified:{},etag:{}});function bj(bD,bC,bz){var bv=bD.contents,bB=bD.dataTypes,bw=bD.responseFields,by,bA,bx,e;for(bA in bw){if(bA in bz){bC[bw[bA]]=bz[bA]}}while(bB[0]==="*"){bB.shift();if(by===L){by=bD.mimeType||bC.getResponseHeader("content-type")}}if(by){for(bA in bv){if(bv[bA]&&bv[bA].test(by)){bB.unshift(bA);break}}}if(bB[0] in bz){bx=bB[0]}else{for(bA in bz){if(!bB[0]||bD.converters[bA+" "+bB[0]]){bx=bA;break}if(!e){e=bA}}bx=bx||e}if(bx){if(bx!==bB[0]){bB.unshift(bx)}return bz[bx]}}function G(bH,bz){if(bH.dataFilter){bz=bH.dataFilter(bz,bH.dataType)}var bD=bH.dataTypes,bG={},bA,bE,bw=bD.length,bB,bC=bD[0],bx,by,bF,bv,e;for(bA=1;bA=bw.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();bw.animatedProperties[this.prop]=true;for(bA in bw.animatedProperties){if(bw.animatedProperties[bA]!==true){e=false}}if(e){if(bw.overflow!=null&&!b.support.shrinkWrapBlocks){b.each(["","X","Y"],function(bC,bD){bz.style["overflow"+bD]=bw.overflow[bC]})}if(bw.hide){b(bz).hide()}if(bw.hide||bw.show){for(bA in bw.animatedProperties){b.style(bz,bA,bw.orig[bA]);b.removeData(bz,"fxshow"+bA,true);b.removeData(bz,"toggle"+bA,true)}}bv=bw.complete;if(bv){bw.complete=false;bv.call(bz)}}return false}else{if(bw.duration==Infinity){this.now=bx}else{bB=bx-this.startTime;this.state=bB/bw.duration;this.pos=b.easing[bw.animatedProperties[this.prop]](this.state,bB,0,1,bw.duration);this.now=this.start+((this.end-this.start)*this.pos)}this.update()}return true}};b.extend(b.fx,{tick:function(){var bw,bv=b.timers,e=0;for(;e").appendTo(e),bw=bv.css("display");bv.remove();if(bw==="none"||bw===""){if(!a8){a8=av.createElement("iframe");a8.frameBorder=a8.width=a8.height=0}e.appendChild(a8);if(!m||!a8.createElement){m=(a8.contentWindow||a8.contentDocument).document;m.write((av.compatMode==="CSS1Compat"?"":"")+"");m.close()}bv=m.createElement(bx);m.body.appendChild(bv);bw=b.css(bv,"display");e.removeChild(a8)}Q[bx]=bw}return Q[bx]}var V=/^t(?:able|d|h)$/i,ad=/^(?:body|html)$/i;if("getBoundingClientRect" in av.documentElement){b.fn.offset=function(bI){var by=this[0],bB;if(bI){return this.each(function(e){b.offset.setOffset(this,bI,e)})}if(!by||!by.ownerDocument){return null}if(by===by.ownerDocument.body){return b.offset.bodyOffset(by)}try{bB=by.getBoundingClientRect()}catch(bF){}var bH=by.ownerDocument,bw=bH.documentElement;if(!bB||!b.contains(bw,by)){return bB?{top:bB.top,left:bB.left}:{top:0,left:0}}var bC=bH.body,bD=aK(bH),bA=bw.clientTop||bC.clientTop||0,bE=bw.clientLeft||bC.clientLeft||0,bv=bD.pageYOffset||b.support.boxModel&&bw.scrollTop||bC.scrollTop,bz=bD.pageXOffset||b.support.boxModel&&bw.scrollLeft||bC.scrollLeft,bG=bB.top+bv-bA,bx=bB.left+bz-bE;return{top:bG,left:bx}}}else{b.fn.offset=function(bF){var bz=this[0];if(bF){return this.each(function(bG){b.offset.setOffset(this,bF,bG)})}if(!bz||!bz.ownerDocument){return null}if(bz===bz.ownerDocument.body){return b.offset.bodyOffset(bz)}var bC,bw=bz.offsetParent,bv=bz,bE=bz.ownerDocument,bx=bE.documentElement,bA=bE.body,bB=bE.defaultView,e=bB?bB.getComputedStyle(bz,null):bz.currentStyle,bD=bz.offsetTop,by=bz.offsetLeft;while((bz=bz.parentNode)&&bz!==bA&&bz!==bx){if(b.support.fixedPosition&&e.position==="fixed"){break}bC=bB?bB.getComputedStyle(bz,null):bz.currentStyle;bD-=bz.scrollTop;by-=bz.scrollLeft;if(bz===bw){bD+=bz.offsetTop;by+=bz.offsetLeft;if(b.support.doesNotAddBorder&&!(b.support.doesAddBorderForTableAndCells&&V.test(bz.nodeName))){bD+=parseFloat(bC.borderTopWidth)||0;by+=parseFloat(bC.borderLeftWidth)||0}bv=bw;bw=bz.offsetParent}if(b.support.subtractsBorderForOverflowNotVisible&&bC.overflow!=="visible"){bD+=parseFloat(bC.borderTopWidth)||0;by+=parseFloat(bC.borderLeftWidth)||0}e=bC}if(e.position==="relative"||e.position==="static"){bD+=bA.offsetTop;by+=bA.offsetLeft}if(b.support.fixedPosition&&e.position==="fixed"){bD+=Math.max(bx.scrollTop,bA.scrollTop);by+=Math.max(bx.scrollLeft,bA.scrollLeft)}return{top:bD,left:by}}}b.offset={bodyOffset:function(e){var bw=e.offsetTop,bv=e.offsetLeft;if(b.support.doesNotIncludeMarginInBodyOffset){bw+=parseFloat(b.css(e,"marginTop"))||0;bv+=parseFloat(b.css(e,"marginLeft"))||0}return{top:bw,left:bv}},setOffset:function(bx,bG,bA){var bB=b.css(bx,"position");if(bB==="static"){bx.style.position="relative"}var bz=b(bx),bv=bz.offset(),e=b.css(bx,"top"),bE=b.css(bx,"left"),bF=(bB==="absolute"||bB==="fixed")&&b.inArray("auto",[e,bE])>-1,bD={},bC={},bw,by;if(bF){bC=bz.position();bw=bC.top;by=bC.left}else{bw=parseFloat(e)||0;by=parseFloat(bE)||0}if(b.isFunction(bG)){bG=bG.call(bx,bA,bv)}if(bG.top!=null){bD.top=(bG.top-bv.top)+bw}if(bG.left!=null){bD.left=(bG.left-bv.left)+by}if("using" in bG){bG.using.call(bx,bD)}else{bz.css(bD)}}};b.fn.extend({position:function(){if(!this[0]){return null}var bw=this[0],bv=this.offsetParent(),bx=this.offset(),e=ad.test(bv[0].nodeName)?{top:0,left:0}:bv.offset();bx.top-=parseFloat(b.css(bw,"marginTop"))||0;bx.left-=parseFloat(b.css(bw,"marginLeft"))||0;e.top+=parseFloat(b.css(bv[0],"borderTopWidth"))||0;e.left+=parseFloat(b.css(bv[0],"borderLeftWidth"))||0;return{top:bx.top-e.top,left:bx.left-e.left}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||av.body;while(e&&(!ad.test(e.nodeName)&&b.css(e,"position")==="static")){e=e.offsetParent}return e})}});b.each(["Left","Top"],function(bv,e){var bw="scroll"+e;b.fn[bw]=function(bz){var bx,by;if(bz===L){bx=this[0];if(!bx){return null}by=aK(bx);return by?("pageXOffset" in by)?by[bv?"pageYOffset":"pageXOffset"]:b.support.boxModel&&by.document.documentElement[bw]||by.document.body[bw]:bx[bw]}return this.each(function(){by=aK(this);if(by){by.scrollTo(!bv?bz:b(by).scrollLeft(),bv?bz:b(by).scrollTop())}else{this[bw]=bz}})}});function aK(e){return b.isWindow(e)?e:e.nodeType===9?e.defaultView||e.parentWindow:false}b.each(["Height","Width"],function(bv,e){var bw=e.toLowerCase();b.fn["inner"+e]=function(){var bx=this[0];return bx?bx.style?parseFloat(b.css(bx,bw,"padding")):this[bw]():null};b.fn["outer"+e]=function(by){var bx=this[0];return bx?bx.style?parseFloat(b.css(bx,bw,by?"margin":"border")):this[bw]():null};b.fn[bw]=function(bz){var bA=this[0];if(!bA){return bz==null?null:this}if(b.isFunction(bz)){return this.each(function(bE){var bD=b(this);bD[bw](bz.call(this,bE,bD[bw]()))})}if(b.isWindow(bA)){var bB=bA.document.documentElement["client"+e],bx=bA.document.body;return bA.document.compatMode==="CSS1Compat"&&bB||bx&&bx["client"+e]||bB}else{if(bA.nodeType===9){return Math.max(bA.documentElement["client"+e],bA.body["scroll"+e],bA.documentElement["scroll"+e],bA.body["offset"+e],bA.documentElement["offset"+e])}else{if(bz===L){var bC=b.css(bA,bw),by=parseFloat(bC);return b.isNumeric(by)?by:bC}else{return this.css(bw,typeof bz==="string"?bz:bz+"px")}}}}});bb.jQuery=bb.$=b;if(typeof define==="function"&&define.amd&&define.amd.jQuery){define("jquery",[],function(){return b +})}})(window); +/*! + PowerTip - v1.2.0 - 2013-04-03 + http://stevenbenner.github.com/jquery-powertip/ + Copyright (c) 2013 Steven Benner (http://stevenbenner.com/). + Released under MIT license. + https://raw.github.com/stevenbenner/jquery-powertip/master/LICENSE.txt +*/ +(function(a){if(typeof define==="function"&&define.amd){define(["jquery"],a)}else{a(jQuery)}}(function(k){var A=k(document),s=k(window),w=k("body");var n="displayController",e="hasActiveHover",d="forcedOpen",u="hasMouseMove",f="mouseOnToPopup",g="originalTitle",y="powertip",o="powertipjq",l="powertiptarget",E=180/Math.PI;var c={isTipOpen:false,isFixedTipOpen:false,isClosing:false,tipOpenImminent:false,activeHover:null,currentX:0,currentY:0,previousX:0,previousY:0,desyncTimeout:null,mouseTrackingActive:false,delayInProgress:false,windowWidth:0,windowHeight:0,scrollTop:0,scrollLeft:0};var p={none:0,top:1,bottom:2,left:4,right:8};k.fn.powerTip=function(F,N){if(!this.length){return this}if(k.type(F)==="string"&&k.powerTip[F]){return k.powerTip[F].call(this,this,N)}var O=k.extend({},k.fn.powerTip.defaults,F),G=new x(O);h();this.each(function M(){var R=k(this),Q=R.data(y),P=R.data(o),T=R.data(l),S;if(R.data(n)){k.powerTip.destroy(R)}S=R.attr("title");if(!Q&&!T&&!P&&S){R.data(y,S);R.data(g,S);R.removeAttr("title")}R.data(n,new t(R,O,G))});if(!O.manual){this.on({"mouseenter.powertip":function J(P){k.powerTip.show(this,P)},"mouseleave.powertip":function L(){k.powerTip.hide(this)},"focus.powertip":function K(){k.powerTip.show(this)},"blur.powertip":function H(){k.powerTip.hide(this,true)},"keydown.powertip":function I(P){if(P.keyCode===27){k.powerTip.hide(this,true)}}})}return this};k.fn.powerTip.defaults={fadeInTime:200,fadeOutTime:100,followMouse:false,popupId:"powerTip",intentSensitivity:7,intentPollInterval:100,closeDelay:100,placement:"n",smartPlacement:false,offset:10,mouseOnToPopup:false,manual:false};k.fn.powerTip.smartPlacementLists={n:["n","ne","nw","s"],e:["e","ne","se","w","nw","sw","n","s","e"],s:["s","se","sw","n"],w:["w","nw","sw","e","ne","se","n","s","w"],nw:["nw","w","sw","n","s","se","nw"],ne:["ne","e","se","n","s","sw","ne"],sw:["sw","w","nw","s","n","ne","sw"],se:["se","e","ne","s","n","nw","se"],"nw-alt":["nw-alt","n","ne-alt","sw-alt","s","se-alt","w","e"],"ne-alt":["ne-alt","n","nw-alt","se-alt","s","sw-alt","e","w"],"sw-alt":["sw-alt","s","se-alt","nw-alt","n","ne-alt","w","e"],"se-alt":["se-alt","s","sw-alt","ne-alt","n","nw-alt","e","w"]};k.powerTip={show:function z(F,G){if(G){i(G);c.previousX=G.pageX;c.previousY=G.pageY;k(F).data(n).show()}else{k(F).first().data(n).show(true,true)}return F},reposition:function r(F){k(F).first().data(n).resetPosition();return F},hide:function D(G,F){if(G){k(G).first().data(n).hide(F)}else{if(c.activeHover){c.activeHover.data(n).hide(true)}}return G},destroy:function C(G){k(G).off(".powertip").each(function F(){var I=k(this),H=[g,n,e,d];if(I.data(g)){I.attr("title",I.data(g));H.push(y)}I.removeData(H)});return G}};k.powerTip.showTip=k.powerTip.show;k.powerTip.closeTip=k.powerTip.hide;function b(){var F=this;F.top="auto";F.left="auto";F.right="auto";F.bottom="auto";F.set=function(H,G){if(k.isNumeric(G)){F[H]=Math.round(G)}}}function t(K,N,F){var J=null;function L(P,Q){M();if(!K.data(e)){if(!P){c.tipOpenImminent=true;J=setTimeout(function O(){J=null;I()},N.intentPollInterval)}else{if(Q){K.data(d,true)}F.showTip(K)}}}function G(P){M();c.tipOpenImminent=false;if(K.data(e)){K.data(d,false);if(!P){c.delayInProgress=true;J=setTimeout(function O(){J=null;F.hideTip(K);c.delayInProgress=false},N.closeDelay)}else{F.hideTip(K)}}}function I(){var Q=Math.abs(c.previousX-c.currentX),O=Math.abs(c.previousY-c.currentY),P=Q+O;if(P",{id:Q.popupId});if(w.length===0){w=k("body")}w.append(O)}if(Q.followMouse){if(!O.data(u)){A.on("mousemove",M);s.on("scroll",M);O.data(u,true)}}if(Q.mouseOnToPopup){O.on({mouseenter:function L(){if(O.data(f)){if(c.activeHover){c.activeHover.data(n).cancel()}}},mouseleave:function N(){if(c.activeHover){c.activeHover.data(n).hide()}}})}function I(S){S.data(e,true);O.queue(function R(T){H(S);T()})}function H(S){var U;if(!S.data(e)){return}if(c.isTipOpen){if(!c.isClosing){K(c.activeHover)}O.delay(100).queue(function R(V){H(S);V()});return}S.trigger("powerTipPreRender");U=B(S);if(U){O.empty().append(U)}else{return}S.trigger("powerTipRender");c.activeHover=S;c.isTipOpen=true;O.data(f,Q.mouseOnToPopup);if(!Q.followMouse){G(S);c.isFixedTipOpen=true}else{M()}O.fadeIn(Q.fadeInTime,function T(){if(!c.desyncTimeout){c.desyncTimeout=setInterval(J,500)}S.trigger("powerTipOpen")})}function K(R){c.isClosing=true;c.activeHover=null;c.isTipOpen=false;c.desyncTimeout=clearInterval(c.desyncTimeout);R.data(e,false);R.data(d,false);O.fadeOut(Q.fadeOutTime,function S(){var T=new b();c.isClosing=false;c.isFixedTipOpen=false;O.removeClass();T.set("top",c.currentY+Q.offset);T.set("left",c.currentX+Q.offset);O.css(T);R.trigger("powerTipClose")})}function M(){if(!c.isFixedTipOpen&&(c.isTipOpen||(c.tipOpenImminent&&O.data(u)))){var R=O.outerWidth(),V=O.outerHeight(),U=new b(),S,T;U.set("top",c.currentY+Q.offset);U.set("left",c.currentX+Q.offset);S=m(U,R,V);if(S!==p.none){T=a(S);if(T===1){if(S===p.right){U.set("left",c.windowWidth-R)}else{if(S===p.bottom){U.set("top",c.scrollTop+c.windowHeight-V)}}}else{U.set("left",c.currentX-R-Q.offset);U.set("top",c.currentY-V-Q.offset)}}O.css(U)}}function G(S){var R,T;if(Q.smartPlacement){R=k.fn.powerTip.smartPlacementLists[Q.placement];k.each(R,function(U,W){var V=m(F(S,W),O.outerWidth(),O.outerHeight());T=W;if(V===p.none){return false}})}else{F(S,Q.placement);T=Q.placement}O.addClass(T)}function F(U,T){var R=0,S,W,V=new b();V.set("top",0);V.set("left",0);O.css(V);do{S=O.outerWidth();W=O.outerHeight();V=P.compute(U,T,S,W,Q.offset);O.css(V)}while(++R<=5&&(S!==O.outerWidth()||W!==O.outerHeight()));return V}function J(){var R=false;if(c.isTipOpen&&!c.isClosing&&!c.delayInProgress){if(c.activeHover.data(e)===false||c.activeHover.is(":disabled")){R=true}else{if(!v(c.activeHover)&&!c.activeHover.is(":focus")&&!c.activeHover.data(d)){if(O.data(f)){if(!v(O)){R=true}}else{R=true}}}if(R){K(c.activeHover)}}}this.showTip=I;this.hideTip=K;this.resetPosition=G}function q(F){return window.SVGElement&&F[0] instanceof SVGElement}function h(){if(!c.mouseTrackingActive){c.mouseTrackingActive=true;k(function H(){c.scrollLeft=s.scrollLeft();c.scrollTop=s.scrollTop();c.windowWidth=s.width();c.windowHeight=s.height()});A.on("mousemove",i);s.on({resize:function G(){c.windowWidth=s.width();c.windowHeight=s.height()},scroll:function F(){var I=s.scrollLeft(),J=s.scrollTop();if(I!==c.scrollLeft){c.currentX+=I-c.scrollLeft;c.scrollLeft=I}if(J!==c.scrollTop){c.currentY+=J-c.scrollTop;c.scrollTop=J}}})}}function i(F){c.currentX=F.pageX;c.currentY=F.pageY}function v(F){var H=F.offset(),J=F[0].getBoundingClientRect(),I=J.right-J.left,G=J.bottom-J.top;return c.currentX>=H.left&&c.currentX<=H.left+I&&c.currentY>=H.top&&c.currentY<=H.top+G}function B(I){var G=I.data(y),F=I.data(o),K=I.data(l),H,J;if(G){if(k.isFunction(G)){G=G.call(I[0])}J=G}else{if(F){if(k.isFunction(F)){F=F.call(I[0])}if(F.length>0){J=F.clone(true,true)}}else{if(K){H=k("#"+K);if(H.length>0){J=H.html()}}}}return J}function m(M,L,K){var G=c.scrollTop,J=c.scrollLeft,I=G+c.windowHeight,F=J+c.windowWidth,H=p.none;if(M.topI||Math.abs(M.bottom-c.windowHeight)>I){H|=p.bottom}if(M.leftF){H|=p.left}if(M.left+L>F||M.right_z8U literal 0 HcmV?d00001 diff --git a/Arduino/MAX6956/html/nav_g.png b/Arduino/MAX6956/html/nav_g.png new file mode 100644 index 0000000000000000000000000000000000000000..2093a237a94f6c83e19ec6e5fd42f7ddabdafa81 GIT binary patch literal 95 zcmeAS@N?(olHy`uVBq!ia0vp^j6lrB!3HFm1ilyoDK$?Q$B+ufw|5PB85lU25BhtE tr?otc=hd~V+ws&_A@j8Fiv!KF$B+ufw|5=67#uj90@pIL wZ=Q8~_Ju`#59=RjDrmm`tMD@M=!-l18IR?&vFVdQ&MBb@0HFXL1|%O$WD@{VPM$7~Ar*{o?;hlAFyLXmaDC0y znK1_#cQqJWPES%4Uujug^TE?jMft$}Eq^WaR~)%f)vSNs&gek&x%A9X9sM + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/Arduino/MAX6956/html/search/all_62.js b/Arduino/MAX6956/html/search/all_62.js new file mode 100644 index 00000000..b44b09cd --- /dev/null +++ b/Arduino/MAX6956/html/search/all_62.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['buffer',['buffer',['../classMAX6956.html#a9f4597436b10ee86a02c96c2b0605851',1,'MAX6956']]] +]; diff --git a/Arduino/MAX6956/html/search/all_63.html b/Arduino/MAX6956/html/search/all_63.html new file mode 100644 index 00000000..a8fe36da --- /dev/null +++ b/Arduino/MAX6956/html/search/all_63.html @@ -0,0 +1,26 @@ + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/Arduino/MAX6956/html/search/all_63.js b/Arduino/MAX6956/html/search/all_63.js new file mode 100644 index 00000000..6abd3d20 --- /dev/null +++ b/Arduino/MAX6956/html/search/all_63.js @@ -0,0 +1,6 @@ +var searchData= +[ + ['configallports',['configAllPorts',['../classMAX6956.html#a9e9f11c46bdc86d8e882ed8bb5efabdf',1,'MAX6956']]], + ['configport',['configPort',['../classMAX6956.html#a5e05bead41c585c68de79bbfed971d19',1,'MAX6956']]], + ['configports',['configPorts',['../classMAX6956.html#a400393e30fbe196aef43d8edea890228',1,'MAX6956']]] +]; diff --git a/Arduino/MAX6956/html/search/all_64.html b/Arduino/MAX6956/html/search/all_64.html new file mode 100644 index 00000000..b415c0ed --- /dev/null +++ b/Arduino/MAX6956/html/search/all_64.html @@ -0,0 +1,26 @@ + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/Arduino/MAX6956/html/search/all_64.js b/Arduino/MAX6956/html/search/all_64.js new file mode 100644 index 00000000..6e8f44cc --- /dev/null +++ b/Arduino/MAX6956/html/search/all_64.js @@ -0,0 +1,5 @@ +var searchData= +[ + ['devaddr',['devAddr',['../classMAX6956.html#a6ba2f8011914df50d6022ab54b27748d',1,'MAX6956']]], + ['disableallports',['disableAllPorts',['../classMAX6956.html#a93a81ff86316f63ee1ada3529da2a95b',1,'MAX6956']]] +]; diff --git a/Arduino/MAX6956/html/search/all_65.html b/Arduino/MAX6956/html/search/all_65.html new file mode 100644 index 00000000..49e2caeb --- /dev/null +++ b/Arduino/MAX6956/html/search/all_65.html @@ -0,0 +1,26 @@ + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/Arduino/MAX6956/html/search/all_65.js b/Arduino/MAX6956/html/search/all_65.js new file mode 100644 index 00000000..25d17ecc --- /dev/null +++ b/Arduino/MAX6956/html/search/all_65.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['enableallports',['enableAllPorts',['../classMAX6956.html#a51a47c1f69532e96c6caa357889004e3',1,'MAX6956']]] +]; diff --git a/Arduino/MAX6956/html/search/all_67.html b/Arduino/MAX6956/html/search/all_67.html new file mode 100644 index 00000000..a6568a3a --- /dev/null +++ b/Arduino/MAX6956/html/search/all_67.html @@ -0,0 +1,26 @@ + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/Arduino/MAX6956/html/search/all_67.js b/Arduino/MAX6956/html/search/all_67.js new file mode 100644 index 00000000..400e6433 --- /dev/null +++ b/Arduino/MAX6956/html/search/all_67.js @@ -0,0 +1,10 @@ +var searchData= +[ + ['getconfigreg',['getConfigReg',['../classMAX6956.html#a5e787204b3f7bf8750376f5bdf77a971',1,'MAX6956']]], + ['getenableindividualcurrent',['getEnableIndividualCurrent',['../classMAX6956.html#abcfe81dd0ffc90284f19503b6366dcfb',1,'MAX6956']]], + ['getenabletransitiondetection',['getEnableTransitionDetection',['../classMAX6956.html#a76e9ab35769854b3e4224499897601ec',1,'MAX6956']]], + ['getglobalcurrent',['getGlobalCurrent',['../classMAX6956.html#a1926760b263588314fd759d129091940',1,'MAX6956']]], + ['getinputmask',['getInputMask',['../classMAX6956.html#a56245915d7d4cd8fd34629bd91695147',1,'MAX6956']]], + ['getpower',['getPower',['../classMAX6956.html#acdc18c36735d8015651d4e3c75da4300',1,'MAX6956']]], + ['gettestmode',['getTestMode',['../classMAX6956.html#ad4f99f08d1cf08c5a0097215e680a80a',1,'MAX6956']]] +]; diff --git a/Arduino/MAX6956/html/search/all_69.html b/Arduino/MAX6956/html/search/all_69.html new file mode 100644 index 00000000..676651ef --- /dev/null +++ b/Arduino/MAX6956/html/search/all_69.html @@ -0,0 +1,26 @@ + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/Arduino/MAX6956/html/search/all_69.js b/Arduino/MAX6956/html/search/all_69.js new file mode 100644 index 00000000..47c8e9d4 --- /dev/null +++ b/Arduino/MAX6956/html/search/all_69.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['initialize',['initialize',['../classMAX6956.html#ad63e927adc2427b4b661f2422ddd40d8',1,'MAX6956']]] +]; diff --git a/Arduino/MAX6956/html/search/all_6d.html b/Arduino/MAX6956/html/search/all_6d.html new file mode 100644 index 00000000..82ceec77 --- /dev/null +++ b/Arduino/MAX6956/html/search/all_6d.html @@ -0,0 +1,26 @@ + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/Arduino/MAX6956/html/search/all_6d.js b/Arduino/MAX6956/html/search/all_6d.js new file mode 100644 index 00000000..ee74e50d --- /dev/null +++ b/Arduino/MAX6956/html/search/all_6d.js @@ -0,0 +1,174 @@ +var searchData= +[ + ['max6956',['MAX6956',['../classMAX6956.html',1,'MAX6956'],['../classMAX6956.html#a210d9e95978d61357db757cb80475bde',1,'MAX6956::MAX6956()'],['../classMAX6956.html#a1a7b33190871a09d81c5bec741b645b7',1,'MAX6956::MAX6956(uint8_t address)']]], + ['max6956_2ecpp',['MAX6956.cpp',['../MAX6956_8cpp.html',1,'']]], + ['max6956_2eh',['MAX6956.h',['../MAX6956_8h.html',1,'']]], + ['max6956_5faddress',['MAX6956_ADDRESS',['../MAX6956_8h.html#a33e60623a4c5b483d4604fe2c9b91be7',1,'MAX6956.h']]], + ['max6956_5fconfig_5fglobal_5fcurrent_5fbit',['MAX6956_CONFIG_GLOBAL_CURRENT_BIT',['../MAX6956_8h.html#a4288d838d55461c66c0ba2e904f588a7',1,'MAX6956.h']]], + ['max6956_5fconfig_5fpower_5fbit',['MAX6956_CONFIG_POWER_BIT',['../MAX6956_8h.html#a03faf0490eddbb2f0405616ad6ac4052',1,'MAX6956.h']]], + ['max6956_5fconfig_5ftransition_5fbit',['MAX6956_CONFIG_TRANSITION_BIT',['../MAX6956_8h.html#af1d61c00ae2e56dd5e7f04dc4b0c1663',1,'MAX6956.h']]], + ['max6956_5fcurrent_5f0',['MAX6956_CURRENT_0',['../MAX6956_8h.html#a930221b73d0e7327ffce1e3072ed69e3',1,'MAX6956.h']]], + ['max6956_5fcurrent_5f1',['MAX6956_CURRENT_1',['../MAX6956_8h.html#afd6a3c0f560b7b7190805416e1ad00f5',1,'MAX6956.h']]], + ['max6956_5fcurrent_5f10',['MAX6956_CURRENT_10',['../MAX6956_8h.html#a62f09fbe807ce97d3558748808ed3a11',1,'MAX6956.h']]], + ['max6956_5fcurrent_5f11',['MAX6956_CURRENT_11',['../MAX6956_8h.html#a5b97f8927dd861189567ad1fda6d692a',1,'MAX6956.h']]], + ['max6956_5fcurrent_5f12',['MAX6956_CURRENT_12',['../MAX6956_8h.html#a8fb88850c74ecc2080971984c817b860',1,'MAX6956.h']]], + ['max6956_5fcurrent_5f13',['MAX6956_CURRENT_13',['../MAX6956_8h.html#a8bfeeb7d88d4284dec7174b65724877d',1,'MAX6956.h']]], + ['max6956_5fcurrent_5f14',['MAX6956_CURRENT_14',['../MAX6956_8h.html#aad136273ced9dea0ef4a8821f4a5f368',1,'MAX6956.h']]], + ['max6956_5fcurrent_5f15',['MAX6956_CURRENT_15',['../MAX6956_8h.html#a4c0ac1cc939ecfb7992dac2834521eb6',1,'MAX6956.h']]], + ['max6956_5fcurrent_5f2',['MAX6956_CURRENT_2',['../MAX6956_8h.html#ab7558038e4f723efa4b406e988a93990',1,'MAX6956.h']]], + ['max6956_5fcurrent_5f3',['MAX6956_CURRENT_3',['../MAX6956_8h.html#a8b8800a153cf4869a6c4d399f8d46035',1,'MAX6956.h']]], + ['max6956_5fcurrent_5f4',['MAX6956_CURRENT_4',['../MAX6956_8h.html#a2678f20d0e18e036e13ff5f422fcf609',1,'MAX6956.h']]], + ['max6956_5fcurrent_5f5',['MAX6956_CURRENT_5',['../MAX6956_8h.html#af808e1e791b9a640d6b6c62cb145f169',1,'MAX6956.h']]], + ['max6956_5fcurrent_5f6',['MAX6956_CURRENT_6',['../MAX6956_8h.html#a0c97726477caef4c0f54eb1beaffbdff',1,'MAX6956.h']]], + ['max6956_5fcurrent_5f7',['MAX6956_CURRENT_7',['../MAX6956_8h.html#a55c66763c65c8554d12a71a4c20e35a6',1,'MAX6956.h']]], + ['max6956_5fcurrent_5f8',['MAX6956_CURRENT_8',['../MAX6956_8h.html#a11c425ee14938c667e63e7df4cf8afa2',1,'MAX6956.h']]], + ['max6956_5fcurrent_5f9',['MAX6956_CURRENT_9',['../MAX6956_8h.html#a4da9aedd07982408005da31fda78463a',1,'MAX6956.h']]], + ['max6956_5fdefault_5faddress',['MAX6956_DEFAULT_ADDRESS',['../MAX6956_8h.html#a4ca90873afdfdacaa730ed5db53e2f5b',1,'MAX6956.h']]], + ['max6956_5fdisplay_5ftest_5fbit',['MAX6956_DISPLAY_TEST_BIT',['../MAX6956_8h.html#a7e110f7b5949bf63dd7c5b4e9a59a5b0',1,'MAX6956.h']]], + ['max6956_5fglobal_5fcurrent_5fbit',['MAX6956_GLOBAL_CURRENT_BIT',['../MAX6956_8h.html#a85368204ba368978f814d46d81335c35',1,'MAX6956.h']]], + ['max6956_5fglobal_5fcurrent_5flength',['MAX6956_GLOBAL_CURRENT_LENGTH',['../MAX6956_8h.html#afbcb8bf5ecc4e5afada48446f8dac809',1,'MAX6956.h']]], + ['max6956_5finput_5fw_5fpull',['MAX6956_INPUT_W_PULL',['../MAX6956_8h.html#a68fc1bc750b7959fbab7e64f79589b83',1,'MAX6956.h']]], + ['max6956_5finput_5fwo_5fpull',['MAX6956_INPUT_WO_PULL',['../MAX6956_8h.html#ab05f3186e2515bab3a536ad9f1cbb7db',1,'MAX6956.h']]], + ['max6956_5foff',['MAX6956_OFF',['../MAX6956_8h.html#a003fe60fa8da81e67da2ad7900d1196f',1,'MAX6956.h']]], + ['max6956_5fon',['MAX6956_ON',['../MAX6956_8h.html#a4e151161e190a9f45aebfd712064b034',1,'MAX6956.h']]], + ['max6956_5foutput_5fgpio',['MAX6956_OUTPUT_GPIO',['../MAX6956_8h.html#a27f6ca524d4c18623762c722d9993c10',1,'MAX6956.h']]], + ['max6956_5foutput_5fled',['MAX6956_OUTPUT_LED',['../MAX6956_8h.html#ad6490a909085059c4300a51dcebbf7bc',1,'MAX6956.h']]], + ['max6956_5fport12_5fcurrent_5fbit',['MAX6956_PORT12_CURRENT_BIT',['../MAX6956_8h.html#ae1cb8088b95a2e19f293dbeee7ef7892',1,'MAX6956.h']]], + ['max6956_5fport12_5fcurrent_5flength',['MAX6956_PORT12_CURRENT_LENGTH',['../MAX6956_8h.html#a8b0c452aa9a3f66de931d4a226f865e6',1,'MAX6956.h']]], + ['max6956_5fport13_5fcurrent_5fbit',['MAX6956_PORT13_CURRENT_BIT',['../MAX6956_8h.html#a0c413303648e14359c311fb9478cfce7',1,'MAX6956.h']]], + ['max6956_5fport13_5fcurrent_5flength',['MAX6956_PORT13_CURRENT_LENGTH',['../MAX6956_8h.html#abaee1f6920a6a6770468cb7def42bff7',1,'MAX6956.h']]], + ['max6956_5fport14_5fcurrent_5fbit',['MAX6956_PORT14_CURRENT_BIT',['../MAX6956_8h.html#a0fcb35fa292905862765e99dd03e63b2',1,'MAX6956.h']]], + ['max6956_5fport14_5fcurrent_5flength',['MAX6956_PORT14_CURRENT_LENGTH',['../MAX6956_8h.html#aa98b4176c22631122a00948e5a54e91f',1,'MAX6956.h']]], + ['max6956_5fport15_5fcurrent_5fbit',['MAX6956_PORT15_CURRENT_BIT',['../MAX6956_8h.html#a659a1777dac35a14930720029b786aed',1,'MAX6956.h']]], + ['max6956_5fport15_5fcurrent_5flength',['MAX6956_PORT15_CURRENT_LENGTH',['../MAX6956_8h.html#ab377c2d0463246bfc66c9df01087285d',1,'MAX6956.h']]], + ['max6956_5fport16_5fcurrent_5fbit',['MAX6956_PORT16_CURRENT_BIT',['../MAX6956_8h.html#a977fb8ce0e696e764ae098dce361e446',1,'MAX6956.h']]], + ['max6956_5fport16_5fcurrent_5flength',['MAX6956_PORT16_CURRENT_LENGTH',['../MAX6956_8h.html#a04c2dcf166214a43fbdd9ae5f7a0ca00',1,'MAX6956.h']]], + ['max6956_5fport17_5fcurrent_5fbit',['MAX6956_PORT17_CURRENT_BIT',['../MAX6956_8h.html#ab59b7f618ff0788a6bd21313bf14673f',1,'MAX6956.h']]], + ['max6956_5fport17_5fcurrent_5flength',['MAX6956_PORT17_CURRENT_LENGTH',['../MAX6956_8h.html#adf0428deb9192d621f837d7951e539be',1,'MAX6956.h']]], + ['max6956_5fport18_5fcurrent_5fbit',['MAX6956_PORT18_CURRENT_BIT',['../MAX6956_8h.html#ab0d4c28bc6747482ab33a027fd93b5d7',1,'MAX6956.h']]], + ['max6956_5fport18_5fcurrent_5flength',['MAX6956_PORT18_CURRENT_LENGTH',['../MAX6956_8h.html#a9bb781fca7fadebb28918c05d2f1605c',1,'MAX6956.h']]], + ['max6956_5fport19_5fcurrent_5fbit',['MAX6956_PORT19_CURRENT_BIT',['../MAX6956_8h.html#aea0128f7b979e68785b78cfc7e480a32',1,'MAX6956.h']]], + ['max6956_5fport19_5fcurrent_5flength',['MAX6956_PORT19_CURRENT_LENGTH',['../MAX6956_8h.html#a5c2f25a82e8b442abb28a9544a3d4088',1,'MAX6956.h']]], + ['max6956_5fport21_5fcurrent_5fbit',['MAX6956_PORT21_CURRENT_BIT',['../MAX6956_8h.html#abd855e00543729cc87ab4a48e3d98649',1,'MAX6956.h']]], + ['max6956_5fport21_5fcurrent_5flength',['MAX6956_PORT21_CURRENT_LENGTH',['../MAX6956_8h.html#a65cd02d7f498266b224c035a3809126a',1,'MAX6956.h']]], + ['max6956_5fport22_5fcurrent_5fbit',['MAX6956_PORT22_CURRENT_BIT',['../MAX6956_8h.html#a061947a1484a8449fd4301a1022cafe5',1,'MAX6956.h']]], + ['max6956_5fport22_5fcurrent_5flength',['MAX6956_PORT22_CURRENT_LENGTH',['../MAX6956_8h.html#aa64238ebb3bf6d8ee2d0d368992e7613',1,'MAX6956.h']]], + ['max6956_5fport23_5fcurrent_5fbit',['MAX6956_PORT23_CURRENT_BIT',['../MAX6956_8h.html#a95789ffe1e677c75090556342763c6ac',1,'MAX6956_PORT23_CURRENT_BIT(): MAX6956.h'],['../MAX6956_8h.html#a95789ffe1e677c75090556342763c6ac',1,'MAX6956_PORT23_CURRENT_BIT(): MAX6956.h']]], + ['max6956_5fport23_5fcurrent_5flength',['MAX6956_PORT23_CURRENT_LENGTH',['../MAX6956_8h.html#a0f492bea7bf9e0906ba13f447327d5a8',1,'MAX6956_PORT23_CURRENT_LENGTH(): MAX6956.h'],['../MAX6956_8h.html#a0f492bea7bf9e0906ba13f447327d5a8',1,'MAX6956_PORT23_CURRENT_LENGTH(): MAX6956.h']]], + ['max6956_5fport24_5fcurrent_5fbit',['MAX6956_PORT24_CURRENT_BIT',['../MAX6956_8h.html#a50e41ea8c3ec1bb3d55e5a4eb03563a2',1,'MAX6956.h']]], + ['max6956_5fport24_5fcurrent_5flength',['MAX6956_PORT24_CURRENT_LENGTH',['../MAX6956_8h.html#a11ee583606d04516bc2fc5812b05cd3d',1,'MAX6956.h']]], + ['max6956_5fport25_5fcurrent_5fbit',['MAX6956_PORT25_CURRENT_BIT',['../MAX6956_8h.html#a75f6b93cf7558a38adba5bb4a91d05f8',1,'MAX6956.h']]], + ['max6956_5fport25_5fcurrent_5flength',['MAX6956_PORT25_CURRENT_LENGTH',['../MAX6956_8h.html#a3b1a7a5f82da6b43bd5a24d2297a2f75',1,'MAX6956.h']]], + ['max6956_5fport26_5fcurrent_5fbit',['MAX6956_PORT26_CURRENT_BIT',['../MAX6956_8h.html#abd400d2f356832d21b1787e2501a8644',1,'MAX6956.h']]], + ['max6956_5fport26_5fcurrent_5flength',['MAX6956_PORT26_CURRENT_LENGTH',['../MAX6956_8h.html#a28bf5ca7da83928eeec3f4f302d12c45',1,'MAX6956.h']]], + ['max6956_5fport27_5fcurrent_5fbit',['MAX6956_PORT27_CURRENT_BIT',['../MAX6956_8h.html#a62bf02cd8e4d8a9dfa975d0e319f68f5',1,'MAX6956.h']]], + ['max6956_5fport27_5fcurrent_5flength',['MAX6956_PORT27_CURRENT_LENGTH',['../MAX6956_8h.html#a0a0f99c166b5a60d7e6c6c7d99306b45',1,'MAX6956.h']]], + ['max6956_5fport28_5fcurrent_5fbit',['MAX6956_PORT28_CURRENT_BIT',['../MAX6956_8h.html#ab6135c4105c3b39625e7361a438e1511',1,'MAX6956.h']]], + ['max6956_5fport28_5fcurrent_5flength',['MAX6956_PORT28_CURRENT_LENGTH',['../MAX6956_8h.html#ac2bcdc199d348dba281a4371675bd428',1,'MAX6956.h']]], + ['max6956_5fport29_5fcurrent_5fbit',['MAX6956_PORT29_CURRENT_BIT',['../MAX6956_8h.html#ae98448e4aa991d16d9b1d9d6071078d8',1,'MAX6956.h']]], + ['max6956_5fport29_5fcurrent_5flength',['MAX6956_PORT29_CURRENT_LENGTH',['../MAX6956_8h.html#a6b0d8a1c63777d016e1cb22076b91377',1,'MAX6956.h']]], + ['max6956_5fport31_5fcurrent_5fbit',['MAX6956_PORT31_CURRENT_BIT',['../MAX6956_8h.html#a1cdbea93ca621e5fc4c747286bdf90e1',1,'MAX6956.h']]], + ['max6956_5fport31_5fcurrent_5flength',['MAX6956_PORT31_CURRENT_LENGTH',['../MAX6956_8h.html#a40a075605dfcfc2736aab5ffa10e3e2c',1,'MAX6956.h']]], + ['max6956_5fport33_5fcurrent_5fbit',['MAX6956_PORT33_CURRENT_BIT',['../MAX6956_8h.html#aa5acefc0723ea8d2b804aa7eccae705b',1,'MAX6956.h']]], + ['max6956_5fport33_5fcurrent_5flength',['MAX6956_PORT33_CURRENT_LENGTH',['../MAX6956_8h.html#a2fb02a7e77abefcbf7c194ff6b994ae9',1,'MAX6956.h']]], + ['max6956_5fra_5fconfig_5fp11p10p9p8',['MAX6956_RA_CONFIG_P11P10P9P8',['../MAX6956_8h.html#a3a2fa6f7cc985cfeea00ebd1dd64ae8c',1,'MAX6956.h']]], + ['max6956_5fra_5fconfig_5fp15p14p13p12',['MAX6956_RA_CONFIG_P15P14P13P12',['../MAX6956_8h.html#a119a0a92d4ccdb0e8f27fd565b1220bd',1,'MAX6956.h']]], + ['max6956_5fra_5fconfig_5fp19p18p17p16',['MAX6956_RA_CONFIG_P19P18P17P16',['../MAX6956_8h.html#a8f199d21b14cf933d5093d3001d0400d',1,'MAX6956.h']]], + ['max6956_5fra_5fconfig_5fp23p22p21p20',['MAX6956_RA_CONFIG_P23P22P21P20',['../MAX6956_8h.html#a025ce0245fb957ef58afc5f4920e19f3',1,'MAX6956.h']]], + ['max6956_5fra_5fconfig_5fp27p26p25p24',['MAX6956_RA_CONFIG_P27P26P25P24',['../MAX6956_8h.html#a4e813aab18cbd7462e1ac5a59b0a53ab',1,'MAX6956.h']]], + ['max6956_5fra_5fconfig_5fp31p30p29p28',['MAX6956_RA_CONFIG_P31P30P29P28',['../MAX6956_8h.html#a98b5c2d8359fbb7e07eb2eade7e8870a',1,'MAX6956.h']]], + ['max6956_5fra_5fconfig_5fp7p6p5p4',['MAX6956_RA_CONFIG_P7P6P5P4',['../MAX6956_8h.html#a1c4db4957c22f8767b2f1a06e5cb9a32',1,'MAX6956.h']]], + ['max6956_5fra_5fconfiguration',['MAX6956_RA_CONFIGURATION',['../MAX6956_8h.html#a5c3d1c00491596887e211bfa630c1b94',1,'MAX6956.h']]], + ['max6956_5fra_5fcurrent_5f0xp11p10',['MAX6956_RA_CURRENT_0xP11P10',['../MAX6956_8h.html#aa2304dec8420451a881876948e1cba43',1,'MAX6956.h']]], + ['max6956_5fra_5fcurrent_5f0xp13p12',['MAX6956_RA_CURRENT_0xP13P12',['../MAX6956_8h.html#add5533d08bfa791cf8cf95d7dd3f16d3',1,'MAX6956.h']]], + ['max6956_5fra_5fcurrent_5f0xp15p14',['MAX6956_RA_CURRENT_0xP15P14',['../MAX6956_8h.html#ae51b720b2bd4868c1986e2d314822778',1,'MAX6956.h']]], + ['max6956_5fra_5fcurrent_5f0xp17p16',['MAX6956_RA_CURRENT_0xP17P16',['../MAX6956_8h.html#a77820b1e4acee07a338e179ab35a7836',1,'MAX6956.h']]], + ['max6956_5fra_5fcurrent_5f0xp19p18',['MAX6956_RA_CURRENT_0xP19P18',['../MAX6956_8h.html#aa84fef4207af57fddf6468ae84ebd829',1,'MAX6956.h']]], + ['max6956_5fra_5fcurrent_5f0xp21p20',['MAX6956_RA_CURRENT_0xP21P20',['../MAX6956_8h.html#a11974f06951fb9051f9dd1d154d7c530',1,'MAX6956.h']]], + ['max6956_5fra_5fcurrent_5f0xp23p22',['MAX6956_RA_CURRENT_0xP23P22',['../MAX6956_8h.html#aa971a2bb392832476e3b91970f7fffe7',1,'MAX6956.h']]], + ['max6956_5fra_5fcurrent_5f0xp25p24',['MAX6956_RA_CURRENT_0xP25P24',['../MAX6956_8h.html#a040daea6fe73e819adcbcaed7cd3ceaf',1,'MAX6956.h']]], + ['max6956_5fra_5fcurrent_5f0xp27p26',['MAX6956_RA_CURRENT_0xP27P26',['../MAX6956_8h.html#ac5e5f779975977348022381487c2dfa2',1,'MAX6956.h']]], + ['max6956_5fra_5fcurrent_5f0xp29p28',['MAX6956_RA_CURRENT_0xP29P28',['../MAX6956_8h.html#a32623717f92442a1acfd42cdd3253302',1,'MAX6956.h']]], + ['max6956_5fra_5fcurrent_5f0xp31p30',['MAX6956_RA_CURRENT_0xP31P30',['../MAX6956_8h.html#a64f61d29f7ede042a397c21f33cf6124',1,'MAX6956.h']]], + ['max6956_5fra_5fcurrent_5f0xp5p4',['MAX6956_RA_CURRENT_0xP5P4',['../MAX6956_8h.html#adebbf4c1afdeb688bf5d3887b80c75b2',1,'MAX6956.h']]], + ['max6956_5fra_5fcurrent_5f0xp7p6',['MAX6956_RA_CURRENT_0xP7P6',['../MAX6956_8h.html#a42db4570a3f848d62f3f906a920161b6',1,'MAX6956.h']]], + ['max6956_5fra_5fcurrent_5f0xp9p8',['MAX6956_RA_CURRENT_0xP9P8',['../MAX6956_8h.html#a51eb40018dff593fa84c319832a1a957',1,'MAX6956.h']]], + ['max6956_5fra_5fdisplay_5ftest',['MAX6956_RA_DISPLAY_TEST',['../MAX6956_8h.html#a709a5193fd2aa9274997dfc22ef73a19',1,'MAX6956.h']]], + ['max6956_5fra_5fglobal_5fcurrent',['MAX6956_RA_GLOBAL_CURRENT',['../MAX6956_8h.html#a6a6c2bfe9bfbe4930731829baae7c8f6',1,'MAX6956.h']]], + ['max6956_5fra_5fno_5fop',['MAX6956_RA_NO_OP',['../MAX6956_8h.html#a0f205428de0679650e54dbe8250d57b4',1,'MAX6956.h']]], + ['max6956_5fra_5fport0',['MAX6956_RA_PORT0',['../MAX6956_8h.html#a7e8973b61716ae09a84b95ea2f2f5914',1,'MAX6956.h']]], + ['max6956_5fra_5fport1',['MAX6956_RA_PORT1',['../MAX6956_8h.html#a1e4fdb2886a119328bdd6807f3720eea',1,'MAX6956.h']]], + ['max6956_5fra_5fport10',['MAX6956_RA_PORT10',['../MAX6956_8h.html#a2528a76a2e91cd1dfd11b8aefda01473',1,'MAX6956.h']]], + ['max6956_5fra_5fport11',['MAX6956_RA_PORT11',['../MAX6956_8h.html#a3a6abf1d9e71015255d821419e3ffa5a',1,'MAX6956.h']]], + ['max6956_5fra_5fport12',['MAX6956_RA_PORT12',['../MAX6956_8h.html#a3c089b77cbd25ffa27e3cd46af415a9c',1,'MAX6956.h']]], + ['max6956_5fra_5fport13',['MAX6956_RA_PORT13',['../MAX6956_8h.html#a2d6ee01536f1fb0ec843479948141cbc',1,'MAX6956.h']]], + ['max6956_5fra_5fport14',['MAX6956_RA_PORT14',['../MAX6956_8h.html#aba5e5ff9b4aea95fedff9f6421c5f47c',1,'MAX6956.h']]], + ['max6956_5fra_5fport15',['MAX6956_RA_PORT15',['../MAX6956_8h.html#ad366a7c1b65fb3496f5b9ba392d6ba9c',1,'MAX6956.h']]], + ['max6956_5fra_5fport16',['MAX6956_RA_PORT16',['../MAX6956_8h.html#ac483e6007b4e6a780c14c7a78ff7a134',1,'MAX6956.h']]], + ['max6956_5fra_5fport17',['MAX6956_RA_PORT17',['../MAX6956_8h.html#ab6f3b8bbd8ac56bacf4a57691eb41aaf',1,'MAX6956.h']]], + ['max6956_5fra_5fport18',['MAX6956_RA_PORT18',['../MAX6956_8h.html#a082486ab9eace7838acd56b6ac6301df',1,'MAX6956.h']]], + ['max6956_5fra_5fport19',['MAX6956_RA_PORT19',['../MAX6956_8h.html#a04e65b34862a48ae022c994bbc5968dd',1,'MAX6956.h']]], + ['max6956_5fra_5fport2',['MAX6956_RA_PORT2',['../MAX6956_8h.html#ac4cc75132151b2f662b7c54128391187',1,'MAX6956.h']]], + ['max6956_5fra_5fport20',['MAX6956_RA_PORT20',['../MAX6956_8h.html#aed99f35f5ba961711c4e5bed769aa369',1,'MAX6956.h']]], + ['max6956_5fra_5fport21',['MAX6956_RA_PORT21',['../MAX6956_8h.html#a361dcd71b3da6c5fb57d33951c9e4c54',1,'MAX6956.h']]], + ['max6956_5fra_5fport22',['MAX6956_RA_PORT22',['../MAX6956_8h.html#a67c57767c9f6eda6124ff7368df4293b',1,'MAX6956.h']]], + ['max6956_5fra_5fport23',['MAX6956_RA_PORT23',['../MAX6956_8h.html#a29699b356f81b9fc971a29fc04e68a59',1,'MAX6956.h']]], + ['max6956_5fra_5fport24',['MAX6956_RA_PORT24',['../MAX6956_8h.html#ad053ff9eac065beaa10ad52dcc3d1e3e',1,'MAX6956.h']]], + ['max6956_5fra_5fport25',['MAX6956_RA_PORT25',['../MAX6956_8h.html#a367103a7d8364b916a70f37d0880e334',1,'MAX6956.h']]], + ['max6956_5fra_5fport26',['MAX6956_RA_PORT26',['../MAX6956_8h.html#ae0c19d326ab47406a138d4b66c601de0',1,'MAX6956.h']]], + ['max6956_5fra_5fport27',['MAX6956_RA_PORT27',['../MAX6956_8h.html#ae1219ad62d3ea1b3a86c52736d347618',1,'MAX6956.h']]], + ['max6956_5fra_5fport28',['MAX6956_RA_PORT28',['../MAX6956_8h.html#a07ff69092b95f43595762554c3e35329',1,'MAX6956.h']]], + ['max6956_5fra_5fport29',['MAX6956_RA_PORT29',['../MAX6956_8h.html#a6be82fa185d6c3dd272200727c15f4ac',1,'MAX6956.h']]], + ['max6956_5fra_5fport3',['MAX6956_RA_PORT3',['../MAX6956_8h.html#aa3e011deb16e7054e78e6f71ac33fcba',1,'MAX6956.h']]], + ['max6956_5fra_5fport30',['MAX6956_RA_PORT30',['../MAX6956_8h.html#a34c02dca8e8a97488eb0be51f682cf73',1,'MAX6956.h']]], + ['max6956_5fra_5fport31',['MAX6956_RA_PORT31',['../MAX6956_8h.html#a891d2a47a2fe5a4da056a7732fb6098b',1,'MAX6956.h']]], + ['max6956_5fra_5fport4',['MAX6956_RA_PORT4',['../MAX6956_8h.html#a68339cee27681486c99dabf398f487a0',1,'MAX6956.h']]], + ['max6956_5fra_5fport5',['MAX6956_RA_PORT5',['../MAX6956_8h.html#a92c4653a42f8400a30aa13a60dbc056f',1,'MAX6956.h']]], + ['max6956_5fra_5fport6',['MAX6956_RA_PORT6',['../MAX6956_8h.html#a5af96fba8e40466303a2bcec16df6c6f',1,'MAX6956.h']]], + ['max6956_5fra_5fport7',['MAX6956_RA_PORT7',['../MAX6956_8h.html#a20de98d6d2102960000a70b4bcf6007c',1,'MAX6956.h']]], + ['max6956_5fra_5fport8',['MAX6956_RA_PORT8',['../MAX6956_8h.html#ad0ea7dd1027b558df290150b664b0222',1,'MAX6956.h']]], + ['max6956_5fra_5fport9',['MAX6956_RA_PORT9',['../MAX6956_8h.html#a7d31adbda8965d0d7df0c521571e135c',1,'MAX6956.h']]], + ['max6956_5fra_5fports10_5f17',['MAX6956_RA_PORTS10_17',['../MAX6956_8h.html#aa9837d30cb5f9c9badf20fe50ea3ba26',1,'MAX6956.h']]], + ['max6956_5fra_5fports11_5f18',['MAX6956_RA_PORTS11_18',['../MAX6956_8h.html#a40bf1528e6a7345e0aaa3b86869f3af3',1,'MAX6956.h']]], + ['max6956_5fra_5fports12_5f19',['MAX6956_RA_PORTS12_19',['../MAX6956_8h.html#ab3e1f8d0b913acae6d73f9b5b0d491ff',1,'MAX6956.h']]], + ['max6956_5fra_5fports13_5f20',['MAX6956_RA_PORTS13_20',['../MAX6956_8h.html#ad33d71fa8457fcdb444179768a6376e9',1,'MAX6956.h']]], + ['max6956_5fra_5fports14_5f21',['MAX6956_RA_PORTS14_21',['../MAX6956_8h.html#aeae655678f9a39b8a7f6e9de1a09c59e',1,'MAX6956.h']]], + ['max6956_5fra_5fports15_5f22',['MAX6956_RA_PORTS15_22',['../MAX6956_8h.html#a853b18f366e225131135f6576268a461',1,'MAX6956.h']]], + ['max6956_5fra_5fports16_5f23',['MAX6956_RA_PORTS16_23',['../MAX6956_8h.html#a39c1bb286953031fad9c101604d6f56e',1,'MAX6956.h']]], + ['max6956_5fra_5fports17_5f24',['MAX6956_RA_PORTS17_24',['../MAX6956_8h.html#a8a4536b80e588a3ed6bb2f487499efeb',1,'MAX6956.h']]], + ['max6956_5fra_5fports18_5f25',['MAX6956_RA_PORTS18_25',['../MAX6956_8h.html#a1ae324a27c0648b831978991a44ee33f',1,'MAX6956.h']]], + ['max6956_5fra_5fports19_5f26',['MAX6956_RA_PORTS19_26',['../MAX6956_8h.html#a981a54414024fdd2877704d4d242b748',1,'MAX6956.h']]], + ['max6956_5fra_5fports20_5f27',['MAX6956_RA_PORTS20_27',['../MAX6956_8h.html#abd2280465476a9e3cae302d5e9bf7b62',1,'MAX6956.h']]], + ['max6956_5fra_5fports21_5f28',['MAX6956_RA_PORTS21_28',['../MAX6956_8h.html#adfca6218829cec2697e0975fc7965008',1,'MAX6956.h']]], + ['max6956_5fra_5fports22_5f29',['MAX6956_RA_PORTS22_29',['../MAX6956_8h.html#aa190f6504c585b64f355ce45a24057f1',1,'MAX6956.h']]], + ['max6956_5fra_5fports23_5f30',['MAX6956_RA_PORTS23_30',['../MAX6956_8h.html#a9ae64dcdc091a17982f4888bcd7b1981',1,'MAX6956.h']]], + ['max6956_5fra_5fports24_5f31',['MAX6956_RA_PORTS24_31',['../MAX6956_8h.html#a5054da2b077f91e7f6106373a84476ed',1,'MAX6956.h']]], + ['max6956_5fra_5fports25_5f31',['MAX6956_RA_PORTS25_31',['../MAX6956_8h.html#a38a7fe545ab1b4ca108dabcef50d015f',1,'MAX6956.h']]], + ['max6956_5fra_5fports26_5f31',['MAX6956_RA_PORTS26_31',['../MAX6956_8h.html#ac804c8074d5a6baf79b0595415ae0679',1,'MAX6956.h']]], + ['max6956_5fra_5fports27_5f31',['MAX6956_RA_PORTS27_31',['../MAX6956_8h.html#a5307d28ebcae5028fc482c914eecf48f',1,'MAX6956.h']]], + ['max6956_5fra_5fports28_5f31',['MAX6956_RA_PORTS28_31',['../MAX6956_8h.html#a7554adf2b4214f33584001f4e7c81053',1,'MAX6956.h']]], + ['max6956_5fra_5fports29_5f31',['MAX6956_RA_PORTS29_31',['../MAX6956_8h.html#ab278f8cb075460b9318c029bca24e68a',1,'MAX6956.h']]], + ['max6956_5fra_5fports30_5f31',['MAX6956_RA_PORTS30_31',['../MAX6956_8h.html#ae5873266ac57220286709a468781c3ff',1,'MAX6956.h']]], + ['max6956_5fra_5fports31_5f31',['MAX6956_RA_PORTS31_31',['../MAX6956_8h.html#ad12b528f7fa63249d37126a8d4049aab',1,'MAX6956.h']]], + ['max6956_5fra_5fports4_5f10',['MAX6956_RA_PORTS4_10',['../MAX6956_8h.html#ac32650edffdebee3cfeb90c9daece88b',1,'MAX6956.h']]], + ['max6956_5fra_5fports4_5f11',['MAX6956_RA_PORTS4_11',['../MAX6956_8h.html#a4b0cc79ee765d2f477953a890b2f6209',1,'MAX6956.h']]], + ['max6956_5fra_5fports4_5f7',['MAX6956_RA_PORTS4_7',['../MAX6956_8h.html#a00bff40ca66a7c82b7093536c5047da4',1,'MAX6956.h']]], + ['max6956_5fra_5fports4_5f8',['MAX6956_RA_PORTS4_8',['../MAX6956_8h.html#a3d1cd4727f1748e42a0426c0b70d9c2c',1,'MAX6956.h']]], + ['max6956_5fra_5fports4_5f9',['MAX6956_RA_PORTS4_9',['../MAX6956_8h.html#ad1b71a2b24de60a4d0128576c0e1278b',1,'MAX6956.h']]], + ['max6956_5fra_5fports5_5f12',['MAX6956_RA_PORTS5_12',['../MAX6956_8h.html#a13b8eb94b73c20a02397e50c81bccb57',1,'MAX6956.h']]], + ['max6956_5fra_5fports6_5f13',['MAX6956_RA_PORTS6_13',['../MAX6956_8h.html#af01fef127c33b806d570f1d46a90362f',1,'MAX6956.h']]], + ['max6956_5fra_5fports7_5f14',['MAX6956_RA_PORTS7_14',['../MAX6956_8h.html#ae0f37de2a929dc6f37733c3f112e0fa7',1,'MAX6956.h']]], + ['max6956_5fra_5fports8_5f15',['MAX6956_RA_PORTS8_15',['../MAX6956_8h.html#ae2bd6458f4aa0271d7fb9c8c8fdd0e4f',1,'MAX6956.h']]], + ['max6956_5fra_5fports9_5f16',['MAX6956_RA_PORTS9_16',['../MAX6956_8h.html#aedb8b7ecadabaf8290ac1eacde7db918',1,'MAX6956.h']]], + ['max6956_5fra_5ftransition_5fdetect',['MAX6956_RA_TRANSITION_DETECT',['../MAX6956_8h.html#a4a2b4c395e47e0ec9ef49d3236b8a465',1,'MAX6956.h']]], + ['max6956_5ftransition_5fmask_5fbit',['MAX6956_TRANSITION_MASK_BIT',['../MAX6956_8h.html#abc801853bdfe66591265d04865aba78f',1,'MAX6956.h']]], + ['max6956_5ftransition_5fmask_5flength',['MAX6956_TRANSITION_MASK_LENGTH',['../MAX6956_8h.html#a332868e8a1596e785072ddb8c4a2b4c1',1,'MAX6956.h']]], + ['max6956_5ftransition_5fmask_5fport24_5fbit',['MAX6956_TRANSITION_MASK_PORT24_BIT',['../MAX6956_8h.html#a0a2eb488b9b8d16b5c076d25790ec28e',1,'MAX6956.h']]], + ['max6956_5ftransition_5fmask_5fport25_5fbit',['MAX6956_TRANSITION_MASK_PORT25_BIT',['../MAX6956_8h.html#a04d331f867fa51822f5910ce2b6b891c',1,'MAX6956.h']]], + ['max6956_5ftransition_5fmask_5fport26_5fbit',['MAX6956_TRANSITION_MASK_PORT26_BIT',['../MAX6956_8h.html#ac4f63f4afc199c41dd9b1445259b8d50',1,'MAX6956.h']]], + ['max6956_5ftransition_5fmask_5fport27_5fbit',['MAX6956_TRANSITION_MASK_PORT27_BIT',['../MAX6956_8h.html#a282091cda715bb27f96266f5ae22b492',1,'MAX6956.h']]], + ['max6956_5ftransition_5fmask_5fport28_5fbit',['MAX6956_TRANSITION_MASK_PORT28_BIT',['../MAX6956_8h.html#a927e5369f33337fdea8d89ccc3b3919d',1,'MAX6956.h']]], + ['max6956_5ftransition_5fmask_5fport29_5fbit',['MAX6956_TRANSITION_MASK_PORT29_BIT',['../MAX6956_8h.html#a74adf7234472da3287cb98af583750c9',1,'MAX6956.h']]], + ['max6956_5ftransition_5fmask_5fport30_5fbit',['MAX6956_TRANSITION_MASK_PORT30_BIT',['../MAX6956_8h.html#a0e7f62a1c7d77019ca8ca2c2511f2644',1,'MAX6956.h']]], + ['max6956_5ftransition_5fstatus_5fbit',['MAX6956_TRANSITION_STATUS_BIT',['../MAX6956_8h.html#a29bd01905e66b503151e6d9cdfb035a1',1,'MAX6956.h']]] +]; diff --git a/Arduino/MAX6956/html/search/all_70.html b/Arduino/MAX6956/html/search/all_70.html new file mode 100644 index 00000000..a279cb2a --- /dev/null +++ b/Arduino/MAX6956/html/search/all_70.html @@ -0,0 +1,26 @@ + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/Arduino/MAX6956/html/search/all_70.js b/Arduino/MAX6956/html/search/all_70.js new file mode 100644 index 00000000..21d9faa9 --- /dev/null +++ b/Arduino/MAX6956/html/search/all_70.js @@ -0,0 +1,10 @@ +var searchData= +[ + ['portconfig',['portConfig',['../classMAX6956.html#a9799e7684546e3e9b24506d436586a09',1,'MAX6956']]], + ['portcurrentbit',['portCurrentBit',['../classMAX6956.html#ad3057b6b21ae712acb0129270da63334',1,'MAX6956']]], + ['portcurrentra',['portCurrentRA',['../classMAX6956.html#ab0d382db3afe7930d1b95311bfd90164',1,'MAX6956']]], + ['portsconfig',['portsConfig',['../classMAX6956.html#a8b915615042c5ef96fbf3a5c260d4716',1,'MAX6956']]], + ['portsstatus',['portsStatus',['../classMAX6956.html#ae8da9a65da74dce7eb907319b0198847',1,'MAX6956']]], + ['psarrayindex',['psArrayIndex',['../classMAX6956.html#a967e25fac00c0ab59be854289eb36353',1,'MAX6956']]], + ['psbitposition',['psBitPosition',['../classMAX6956.html#a92b5dc05a1483c49c150db13dcd1f283',1,'MAX6956']]] +]; diff --git a/Arduino/MAX6956/html/search/all_72.html b/Arduino/MAX6956/html/search/all_72.html new file mode 100644 index 00000000..315ac4f0 --- /dev/null +++ b/Arduino/MAX6956/html/search/all_72.html @@ -0,0 +1,26 @@ + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/Arduino/MAX6956/html/search/all_72.js b/Arduino/MAX6956/html/search/all_72.js new file mode 100644 index 00000000..64daaea0 --- /dev/null +++ b/Arduino/MAX6956/html/search/all_72.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['reset',['reset',['../classMAX6956.html#a3b9166eee826a876bbf29bc63b090fe7',1,'MAX6956']]] +]; diff --git a/Arduino/MAX6956/html/search/all_73.html b/Arduino/MAX6956/html/search/all_73.html new file mode 100644 index 00000000..09f8ce8b --- /dev/null +++ b/Arduino/MAX6956/html/search/all_73.html @@ -0,0 +1,26 @@ + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/Arduino/MAX6956/html/search/all_73.js b/Arduino/MAX6956/html/search/all_73.js new file mode 100644 index 00000000..74b221f6 --- /dev/null +++ b/Arduino/MAX6956/html/search/all_73.js @@ -0,0 +1,13 @@ +var searchData= +[ + ['setallportscurrent',['setAllPortsCurrent',['../classMAX6956.html#a9a27a32611fa05766946c33850510644',1,'MAX6956']]], + ['setconfigreg',['setConfigReg',['../classMAX6956.html#ad06b9ed9f6e18f81d8379a6e10391ea4',1,'MAX6956']]], + ['setenableindividualcurrent',['setEnableIndividualCurrent',['../classMAX6956.html#a35bc5701a290409144929e640cad1748',1,'MAX6956']]], + ['setenabletransitiondetection',['setEnableTransitionDetection',['../classMAX6956.html#a67b65b80e09a3225dd4f6413bfab2844',1,'MAX6956']]], + ['setglobalcurrent',['setGlobalCurrent',['../classMAX6956.html#a4669dcc0f2f89f8fe73a0fa9b97dae21',1,'MAX6956']]], + ['setinputmask',['setInputMask',['../classMAX6956.html#a7ce45652fb0490af0ecb4eaebc230419',1,'MAX6956']]], + ['setportcurrent',['setPortCurrent',['../classMAX6956.html#a76a617f3b8982bb3855c5152b480097a',1,'MAX6956']]], + ['setportlevel',['setPortLevel',['../classMAX6956.html#a98fa3831a47355fe0856caa74a9cf810',1,'MAX6956']]], + ['setpower',['setPower',['../classMAX6956.html#ae10ac505e3857d31ca3823225983a697',1,'MAX6956']]], + ['settestmode',['setTestMode',['../classMAX6956.html#ad1b4e5cafd91acd2be2b6fb8197afef0',1,'MAX6956']]] +]; diff --git a/Arduino/MAX6956/html/search/all_74.html b/Arduino/MAX6956/html/search/all_74.html new file mode 100644 index 00000000..c2cd0954 --- /dev/null +++ b/Arduino/MAX6956/html/search/all_74.html @@ -0,0 +1,26 @@ + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/Arduino/MAX6956/html/search/all_74.js b/Arduino/MAX6956/html/search/all_74.js new file mode 100644 index 00000000..fb321603 --- /dev/null +++ b/Arduino/MAX6956/html/search/all_74.js @@ -0,0 +1,5 @@ +var searchData= +[ + ['testconnection',['testConnection',['../classMAX6956.html#a60bd352328d77e59a4d51a3c55d38a25',1,'MAX6956']]], + ['togglepower',['togglePower',['../classMAX6956.html#a993f35d31d1f2489f9d2965c3886f848',1,'MAX6956']]] +]; diff --git a/Arduino/MAX6956/html/search/classes_6d.html b/Arduino/MAX6956/html/search/classes_6d.html new file mode 100644 index 00000000..aa835903 --- /dev/null +++ b/Arduino/MAX6956/html/search/classes_6d.html @@ -0,0 +1,26 @@ + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/Arduino/MAX6956/html/search/classes_6d.js b/Arduino/MAX6956/html/search/classes_6d.js new file mode 100644 index 00000000..b2ca9eca --- /dev/null +++ b/Arduino/MAX6956/html/search/classes_6d.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['max6956',['MAX6956',['../classMAX6956.html',1,'']]] +]; diff --git a/Arduino/MAX6956/html/search/close.png b/Arduino/MAX6956/html/search/close.png new file mode 100644 index 0000000000000000000000000000000000000000..9342d3dfeea7b7c4ee610987e717804b5a42ceb9 GIT binary patch literal 273 zcmV+s0q*{ZP)4(RlMby96)VwnbG{ zbe&}^BDn7x>$<{ck4zAK-=nT;=hHG)kmplIF${xqm8db3oX6wT3bvp`TE@m0cg;b) zBuSL}5?N7O(iZLdAlz@)b)Rd~DnSsSX&P5qC`XwuFwcAYLC+d2>+1(8on;wpt8QIC X2MT$R4iQDd00000NkvXXu0mjfia~GN literal 0 HcmV?d00001 diff --git a/Arduino/MAX6956/html/search/defines_6d.html b/Arduino/MAX6956/html/search/defines_6d.html new file mode 100644 index 00000000..5c949e4a --- /dev/null +++ b/Arduino/MAX6956/html/search/defines_6d.html @@ -0,0 +1,26 @@ + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/Arduino/MAX6956/html/search/defines_6d.js b/Arduino/MAX6956/html/search/defines_6d.js new file mode 100644 index 00000000..468186e0 --- /dev/null +++ b/Arduino/MAX6956/html/search/defines_6d.js @@ -0,0 +1,171 @@ +var searchData= +[ + ['max6956_5faddress',['MAX6956_ADDRESS',['../MAX6956_8h.html#a33e60623a4c5b483d4604fe2c9b91be7',1,'MAX6956.h']]], + ['max6956_5fconfig_5fglobal_5fcurrent_5fbit',['MAX6956_CONFIG_GLOBAL_CURRENT_BIT',['../MAX6956_8h.html#a4288d838d55461c66c0ba2e904f588a7',1,'MAX6956.h']]], + ['max6956_5fconfig_5fpower_5fbit',['MAX6956_CONFIG_POWER_BIT',['../MAX6956_8h.html#a03faf0490eddbb2f0405616ad6ac4052',1,'MAX6956.h']]], + ['max6956_5fconfig_5ftransition_5fbit',['MAX6956_CONFIG_TRANSITION_BIT',['../MAX6956_8h.html#af1d61c00ae2e56dd5e7f04dc4b0c1663',1,'MAX6956.h']]], + ['max6956_5fcurrent_5f0',['MAX6956_CURRENT_0',['../MAX6956_8h.html#a930221b73d0e7327ffce1e3072ed69e3',1,'MAX6956.h']]], + ['max6956_5fcurrent_5f1',['MAX6956_CURRENT_1',['../MAX6956_8h.html#afd6a3c0f560b7b7190805416e1ad00f5',1,'MAX6956.h']]], + ['max6956_5fcurrent_5f10',['MAX6956_CURRENT_10',['../MAX6956_8h.html#a62f09fbe807ce97d3558748808ed3a11',1,'MAX6956.h']]], + ['max6956_5fcurrent_5f11',['MAX6956_CURRENT_11',['../MAX6956_8h.html#a5b97f8927dd861189567ad1fda6d692a',1,'MAX6956.h']]], + ['max6956_5fcurrent_5f12',['MAX6956_CURRENT_12',['../MAX6956_8h.html#a8fb88850c74ecc2080971984c817b860',1,'MAX6956.h']]], + ['max6956_5fcurrent_5f13',['MAX6956_CURRENT_13',['../MAX6956_8h.html#a8bfeeb7d88d4284dec7174b65724877d',1,'MAX6956.h']]], + ['max6956_5fcurrent_5f14',['MAX6956_CURRENT_14',['../MAX6956_8h.html#aad136273ced9dea0ef4a8821f4a5f368',1,'MAX6956.h']]], + ['max6956_5fcurrent_5f15',['MAX6956_CURRENT_15',['../MAX6956_8h.html#a4c0ac1cc939ecfb7992dac2834521eb6',1,'MAX6956.h']]], + ['max6956_5fcurrent_5f2',['MAX6956_CURRENT_2',['../MAX6956_8h.html#ab7558038e4f723efa4b406e988a93990',1,'MAX6956.h']]], + ['max6956_5fcurrent_5f3',['MAX6956_CURRENT_3',['../MAX6956_8h.html#a8b8800a153cf4869a6c4d399f8d46035',1,'MAX6956.h']]], + ['max6956_5fcurrent_5f4',['MAX6956_CURRENT_4',['../MAX6956_8h.html#a2678f20d0e18e036e13ff5f422fcf609',1,'MAX6956.h']]], + ['max6956_5fcurrent_5f5',['MAX6956_CURRENT_5',['../MAX6956_8h.html#af808e1e791b9a640d6b6c62cb145f169',1,'MAX6956.h']]], + ['max6956_5fcurrent_5f6',['MAX6956_CURRENT_6',['../MAX6956_8h.html#a0c97726477caef4c0f54eb1beaffbdff',1,'MAX6956.h']]], + ['max6956_5fcurrent_5f7',['MAX6956_CURRENT_7',['../MAX6956_8h.html#a55c66763c65c8554d12a71a4c20e35a6',1,'MAX6956.h']]], + ['max6956_5fcurrent_5f8',['MAX6956_CURRENT_8',['../MAX6956_8h.html#a11c425ee14938c667e63e7df4cf8afa2',1,'MAX6956.h']]], + ['max6956_5fcurrent_5f9',['MAX6956_CURRENT_9',['../MAX6956_8h.html#a4da9aedd07982408005da31fda78463a',1,'MAX6956.h']]], + ['max6956_5fdefault_5faddress',['MAX6956_DEFAULT_ADDRESS',['../MAX6956_8h.html#a4ca90873afdfdacaa730ed5db53e2f5b',1,'MAX6956.h']]], + ['max6956_5fdisplay_5ftest_5fbit',['MAX6956_DISPLAY_TEST_BIT',['../MAX6956_8h.html#a7e110f7b5949bf63dd7c5b4e9a59a5b0',1,'MAX6956.h']]], + ['max6956_5fglobal_5fcurrent_5fbit',['MAX6956_GLOBAL_CURRENT_BIT',['../MAX6956_8h.html#a85368204ba368978f814d46d81335c35',1,'MAX6956.h']]], + ['max6956_5fglobal_5fcurrent_5flength',['MAX6956_GLOBAL_CURRENT_LENGTH',['../MAX6956_8h.html#afbcb8bf5ecc4e5afada48446f8dac809',1,'MAX6956.h']]], + ['max6956_5finput_5fw_5fpull',['MAX6956_INPUT_W_PULL',['../MAX6956_8h.html#a68fc1bc750b7959fbab7e64f79589b83',1,'MAX6956.h']]], + ['max6956_5finput_5fwo_5fpull',['MAX6956_INPUT_WO_PULL',['../MAX6956_8h.html#ab05f3186e2515bab3a536ad9f1cbb7db',1,'MAX6956.h']]], + ['max6956_5foff',['MAX6956_OFF',['../MAX6956_8h.html#a003fe60fa8da81e67da2ad7900d1196f',1,'MAX6956.h']]], + ['max6956_5fon',['MAX6956_ON',['../MAX6956_8h.html#a4e151161e190a9f45aebfd712064b034',1,'MAX6956.h']]], + ['max6956_5foutput_5fgpio',['MAX6956_OUTPUT_GPIO',['../MAX6956_8h.html#a27f6ca524d4c18623762c722d9993c10',1,'MAX6956.h']]], + ['max6956_5foutput_5fled',['MAX6956_OUTPUT_LED',['../MAX6956_8h.html#ad6490a909085059c4300a51dcebbf7bc',1,'MAX6956.h']]], + ['max6956_5fport12_5fcurrent_5fbit',['MAX6956_PORT12_CURRENT_BIT',['../MAX6956_8h.html#ae1cb8088b95a2e19f293dbeee7ef7892',1,'MAX6956.h']]], + ['max6956_5fport12_5fcurrent_5flength',['MAX6956_PORT12_CURRENT_LENGTH',['../MAX6956_8h.html#a8b0c452aa9a3f66de931d4a226f865e6',1,'MAX6956.h']]], + ['max6956_5fport13_5fcurrent_5fbit',['MAX6956_PORT13_CURRENT_BIT',['../MAX6956_8h.html#a0c413303648e14359c311fb9478cfce7',1,'MAX6956.h']]], + ['max6956_5fport13_5fcurrent_5flength',['MAX6956_PORT13_CURRENT_LENGTH',['../MAX6956_8h.html#abaee1f6920a6a6770468cb7def42bff7',1,'MAX6956.h']]], + ['max6956_5fport14_5fcurrent_5fbit',['MAX6956_PORT14_CURRENT_BIT',['../MAX6956_8h.html#a0fcb35fa292905862765e99dd03e63b2',1,'MAX6956.h']]], + ['max6956_5fport14_5fcurrent_5flength',['MAX6956_PORT14_CURRENT_LENGTH',['../MAX6956_8h.html#aa98b4176c22631122a00948e5a54e91f',1,'MAX6956.h']]], + ['max6956_5fport15_5fcurrent_5fbit',['MAX6956_PORT15_CURRENT_BIT',['../MAX6956_8h.html#a659a1777dac35a14930720029b786aed',1,'MAX6956.h']]], + ['max6956_5fport15_5fcurrent_5flength',['MAX6956_PORT15_CURRENT_LENGTH',['../MAX6956_8h.html#ab377c2d0463246bfc66c9df01087285d',1,'MAX6956.h']]], + ['max6956_5fport16_5fcurrent_5fbit',['MAX6956_PORT16_CURRENT_BIT',['../MAX6956_8h.html#a977fb8ce0e696e764ae098dce361e446',1,'MAX6956.h']]], + ['max6956_5fport16_5fcurrent_5flength',['MAX6956_PORT16_CURRENT_LENGTH',['../MAX6956_8h.html#a04c2dcf166214a43fbdd9ae5f7a0ca00',1,'MAX6956.h']]], + ['max6956_5fport17_5fcurrent_5fbit',['MAX6956_PORT17_CURRENT_BIT',['../MAX6956_8h.html#ab59b7f618ff0788a6bd21313bf14673f',1,'MAX6956.h']]], + ['max6956_5fport17_5fcurrent_5flength',['MAX6956_PORT17_CURRENT_LENGTH',['../MAX6956_8h.html#adf0428deb9192d621f837d7951e539be',1,'MAX6956.h']]], + ['max6956_5fport18_5fcurrent_5fbit',['MAX6956_PORT18_CURRENT_BIT',['../MAX6956_8h.html#ab0d4c28bc6747482ab33a027fd93b5d7',1,'MAX6956.h']]], + ['max6956_5fport18_5fcurrent_5flength',['MAX6956_PORT18_CURRENT_LENGTH',['../MAX6956_8h.html#a9bb781fca7fadebb28918c05d2f1605c',1,'MAX6956.h']]], + ['max6956_5fport19_5fcurrent_5fbit',['MAX6956_PORT19_CURRENT_BIT',['../MAX6956_8h.html#aea0128f7b979e68785b78cfc7e480a32',1,'MAX6956.h']]], + ['max6956_5fport19_5fcurrent_5flength',['MAX6956_PORT19_CURRENT_LENGTH',['../MAX6956_8h.html#a5c2f25a82e8b442abb28a9544a3d4088',1,'MAX6956.h']]], + ['max6956_5fport21_5fcurrent_5fbit',['MAX6956_PORT21_CURRENT_BIT',['../MAX6956_8h.html#abd855e00543729cc87ab4a48e3d98649',1,'MAX6956.h']]], + ['max6956_5fport21_5fcurrent_5flength',['MAX6956_PORT21_CURRENT_LENGTH',['../MAX6956_8h.html#a65cd02d7f498266b224c035a3809126a',1,'MAX6956.h']]], + ['max6956_5fport22_5fcurrent_5fbit',['MAX6956_PORT22_CURRENT_BIT',['../MAX6956_8h.html#a061947a1484a8449fd4301a1022cafe5',1,'MAX6956.h']]], + ['max6956_5fport22_5fcurrent_5flength',['MAX6956_PORT22_CURRENT_LENGTH',['../MAX6956_8h.html#aa64238ebb3bf6d8ee2d0d368992e7613',1,'MAX6956.h']]], + ['max6956_5fport23_5fcurrent_5fbit',['MAX6956_PORT23_CURRENT_BIT',['../MAX6956_8h.html#a95789ffe1e677c75090556342763c6ac',1,'MAX6956_PORT23_CURRENT_BIT(): MAX6956.h'],['../MAX6956_8h.html#a95789ffe1e677c75090556342763c6ac',1,'MAX6956_PORT23_CURRENT_BIT(): MAX6956.h']]], + ['max6956_5fport23_5fcurrent_5flength',['MAX6956_PORT23_CURRENT_LENGTH',['../MAX6956_8h.html#a0f492bea7bf9e0906ba13f447327d5a8',1,'MAX6956_PORT23_CURRENT_LENGTH(): MAX6956.h'],['../MAX6956_8h.html#a0f492bea7bf9e0906ba13f447327d5a8',1,'MAX6956_PORT23_CURRENT_LENGTH(): MAX6956.h']]], + ['max6956_5fport24_5fcurrent_5fbit',['MAX6956_PORT24_CURRENT_BIT',['../MAX6956_8h.html#a50e41ea8c3ec1bb3d55e5a4eb03563a2',1,'MAX6956.h']]], + ['max6956_5fport24_5fcurrent_5flength',['MAX6956_PORT24_CURRENT_LENGTH',['../MAX6956_8h.html#a11ee583606d04516bc2fc5812b05cd3d',1,'MAX6956.h']]], + ['max6956_5fport25_5fcurrent_5fbit',['MAX6956_PORT25_CURRENT_BIT',['../MAX6956_8h.html#a75f6b93cf7558a38adba5bb4a91d05f8',1,'MAX6956.h']]], + ['max6956_5fport25_5fcurrent_5flength',['MAX6956_PORT25_CURRENT_LENGTH',['../MAX6956_8h.html#a3b1a7a5f82da6b43bd5a24d2297a2f75',1,'MAX6956.h']]], + ['max6956_5fport26_5fcurrent_5fbit',['MAX6956_PORT26_CURRENT_BIT',['../MAX6956_8h.html#abd400d2f356832d21b1787e2501a8644',1,'MAX6956.h']]], + ['max6956_5fport26_5fcurrent_5flength',['MAX6956_PORT26_CURRENT_LENGTH',['../MAX6956_8h.html#a28bf5ca7da83928eeec3f4f302d12c45',1,'MAX6956.h']]], + ['max6956_5fport27_5fcurrent_5fbit',['MAX6956_PORT27_CURRENT_BIT',['../MAX6956_8h.html#a62bf02cd8e4d8a9dfa975d0e319f68f5',1,'MAX6956.h']]], + ['max6956_5fport27_5fcurrent_5flength',['MAX6956_PORT27_CURRENT_LENGTH',['../MAX6956_8h.html#a0a0f99c166b5a60d7e6c6c7d99306b45',1,'MAX6956.h']]], + ['max6956_5fport28_5fcurrent_5fbit',['MAX6956_PORT28_CURRENT_BIT',['../MAX6956_8h.html#ab6135c4105c3b39625e7361a438e1511',1,'MAX6956.h']]], + ['max6956_5fport28_5fcurrent_5flength',['MAX6956_PORT28_CURRENT_LENGTH',['../MAX6956_8h.html#ac2bcdc199d348dba281a4371675bd428',1,'MAX6956.h']]], + ['max6956_5fport29_5fcurrent_5fbit',['MAX6956_PORT29_CURRENT_BIT',['../MAX6956_8h.html#ae98448e4aa991d16d9b1d9d6071078d8',1,'MAX6956.h']]], + ['max6956_5fport29_5fcurrent_5flength',['MAX6956_PORT29_CURRENT_LENGTH',['../MAX6956_8h.html#a6b0d8a1c63777d016e1cb22076b91377',1,'MAX6956.h']]], + ['max6956_5fport31_5fcurrent_5fbit',['MAX6956_PORT31_CURRENT_BIT',['../MAX6956_8h.html#a1cdbea93ca621e5fc4c747286bdf90e1',1,'MAX6956.h']]], + ['max6956_5fport31_5fcurrent_5flength',['MAX6956_PORT31_CURRENT_LENGTH',['../MAX6956_8h.html#a40a075605dfcfc2736aab5ffa10e3e2c',1,'MAX6956.h']]], + ['max6956_5fport33_5fcurrent_5fbit',['MAX6956_PORT33_CURRENT_BIT',['../MAX6956_8h.html#aa5acefc0723ea8d2b804aa7eccae705b',1,'MAX6956.h']]], + ['max6956_5fport33_5fcurrent_5flength',['MAX6956_PORT33_CURRENT_LENGTH',['../MAX6956_8h.html#a2fb02a7e77abefcbf7c194ff6b994ae9',1,'MAX6956.h']]], + ['max6956_5fra_5fconfig_5fp11p10p9p8',['MAX6956_RA_CONFIG_P11P10P9P8',['../MAX6956_8h.html#a3a2fa6f7cc985cfeea00ebd1dd64ae8c',1,'MAX6956.h']]], + ['max6956_5fra_5fconfig_5fp15p14p13p12',['MAX6956_RA_CONFIG_P15P14P13P12',['../MAX6956_8h.html#a119a0a92d4ccdb0e8f27fd565b1220bd',1,'MAX6956.h']]], + ['max6956_5fra_5fconfig_5fp19p18p17p16',['MAX6956_RA_CONFIG_P19P18P17P16',['../MAX6956_8h.html#a8f199d21b14cf933d5093d3001d0400d',1,'MAX6956.h']]], + ['max6956_5fra_5fconfig_5fp23p22p21p20',['MAX6956_RA_CONFIG_P23P22P21P20',['../MAX6956_8h.html#a025ce0245fb957ef58afc5f4920e19f3',1,'MAX6956.h']]], + ['max6956_5fra_5fconfig_5fp27p26p25p24',['MAX6956_RA_CONFIG_P27P26P25P24',['../MAX6956_8h.html#a4e813aab18cbd7462e1ac5a59b0a53ab',1,'MAX6956.h']]], + ['max6956_5fra_5fconfig_5fp31p30p29p28',['MAX6956_RA_CONFIG_P31P30P29P28',['../MAX6956_8h.html#a98b5c2d8359fbb7e07eb2eade7e8870a',1,'MAX6956.h']]], + ['max6956_5fra_5fconfig_5fp7p6p5p4',['MAX6956_RA_CONFIG_P7P6P5P4',['../MAX6956_8h.html#a1c4db4957c22f8767b2f1a06e5cb9a32',1,'MAX6956.h']]], + ['max6956_5fra_5fconfiguration',['MAX6956_RA_CONFIGURATION',['../MAX6956_8h.html#a5c3d1c00491596887e211bfa630c1b94',1,'MAX6956.h']]], + ['max6956_5fra_5fcurrent_5f0xp11p10',['MAX6956_RA_CURRENT_0xP11P10',['../MAX6956_8h.html#aa2304dec8420451a881876948e1cba43',1,'MAX6956.h']]], + ['max6956_5fra_5fcurrent_5f0xp13p12',['MAX6956_RA_CURRENT_0xP13P12',['../MAX6956_8h.html#add5533d08bfa791cf8cf95d7dd3f16d3',1,'MAX6956.h']]], + ['max6956_5fra_5fcurrent_5f0xp15p14',['MAX6956_RA_CURRENT_0xP15P14',['../MAX6956_8h.html#ae51b720b2bd4868c1986e2d314822778',1,'MAX6956.h']]], + ['max6956_5fra_5fcurrent_5f0xp17p16',['MAX6956_RA_CURRENT_0xP17P16',['../MAX6956_8h.html#a77820b1e4acee07a338e179ab35a7836',1,'MAX6956.h']]], + ['max6956_5fra_5fcurrent_5f0xp19p18',['MAX6956_RA_CURRENT_0xP19P18',['../MAX6956_8h.html#aa84fef4207af57fddf6468ae84ebd829',1,'MAX6956.h']]], + ['max6956_5fra_5fcurrent_5f0xp21p20',['MAX6956_RA_CURRENT_0xP21P20',['../MAX6956_8h.html#a11974f06951fb9051f9dd1d154d7c530',1,'MAX6956.h']]], + ['max6956_5fra_5fcurrent_5f0xp23p22',['MAX6956_RA_CURRENT_0xP23P22',['../MAX6956_8h.html#aa971a2bb392832476e3b91970f7fffe7',1,'MAX6956.h']]], + ['max6956_5fra_5fcurrent_5f0xp25p24',['MAX6956_RA_CURRENT_0xP25P24',['../MAX6956_8h.html#a040daea6fe73e819adcbcaed7cd3ceaf',1,'MAX6956.h']]], + ['max6956_5fra_5fcurrent_5f0xp27p26',['MAX6956_RA_CURRENT_0xP27P26',['../MAX6956_8h.html#ac5e5f779975977348022381487c2dfa2',1,'MAX6956.h']]], + ['max6956_5fra_5fcurrent_5f0xp29p28',['MAX6956_RA_CURRENT_0xP29P28',['../MAX6956_8h.html#a32623717f92442a1acfd42cdd3253302',1,'MAX6956.h']]], + ['max6956_5fra_5fcurrent_5f0xp31p30',['MAX6956_RA_CURRENT_0xP31P30',['../MAX6956_8h.html#a64f61d29f7ede042a397c21f33cf6124',1,'MAX6956.h']]], + ['max6956_5fra_5fcurrent_5f0xp5p4',['MAX6956_RA_CURRENT_0xP5P4',['../MAX6956_8h.html#adebbf4c1afdeb688bf5d3887b80c75b2',1,'MAX6956.h']]], + ['max6956_5fra_5fcurrent_5f0xp7p6',['MAX6956_RA_CURRENT_0xP7P6',['../MAX6956_8h.html#a42db4570a3f848d62f3f906a920161b6',1,'MAX6956.h']]], + ['max6956_5fra_5fcurrent_5f0xp9p8',['MAX6956_RA_CURRENT_0xP9P8',['../MAX6956_8h.html#a51eb40018dff593fa84c319832a1a957',1,'MAX6956.h']]], + ['max6956_5fra_5fdisplay_5ftest',['MAX6956_RA_DISPLAY_TEST',['../MAX6956_8h.html#a709a5193fd2aa9274997dfc22ef73a19',1,'MAX6956.h']]], + ['max6956_5fra_5fglobal_5fcurrent',['MAX6956_RA_GLOBAL_CURRENT',['../MAX6956_8h.html#a6a6c2bfe9bfbe4930731829baae7c8f6',1,'MAX6956.h']]], + ['max6956_5fra_5fno_5fop',['MAX6956_RA_NO_OP',['../MAX6956_8h.html#a0f205428de0679650e54dbe8250d57b4',1,'MAX6956.h']]], + ['max6956_5fra_5fport0',['MAX6956_RA_PORT0',['../MAX6956_8h.html#a7e8973b61716ae09a84b95ea2f2f5914',1,'MAX6956.h']]], + ['max6956_5fra_5fport1',['MAX6956_RA_PORT1',['../MAX6956_8h.html#a1e4fdb2886a119328bdd6807f3720eea',1,'MAX6956.h']]], + ['max6956_5fra_5fport10',['MAX6956_RA_PORT10',['../MAX6956_8h.html#a2528a76a2e91cd1dfd11b8aefda01473',1,'MAX6956.h']]], + ['max6956_5fra_5fport11',['MAX6956_RA_PORT11',['../MAX6956_8h.html#a3a6abf1d9e71015255d821419e3ffa5a',1,'MAX6956.h']]], + ['max6956_5fra_5fport12',['MAX6956_RA_PORT12',['../MAX6956_8h.html#a3c089b77cbd25ffa27e3cd46af415a9c',1,'MAX6956.h']]], + ['max6956_5fra_5fport13',['MAX6956_RA_PORT13',['../MAX6956_8h.html#a2d6ee01536f1fb0ec843479948141cbc',1,'MAX6956.h']]], + ['max6956_5fra_5fport14',['MAX6956_RA_PORT14',['../MAX6956_8h.html#aba5e5ff9b4aea95fedff9f6421c5f47c',1,'MAX6956.h']]], + ['max6956_5fra_5fport15',['MAX6956_RA_PORT15',['../MAX6956_8h.html#ad366a7c1b65fb3496f5b9ba392d6ba9c',1,'MAX6956.h']]], + ['max6956_5fra_5fport16',['MAX6956_RA_PORT16',['../MAX6956_8h.html#ac483e6007b4e6a780c14c7a78ff7a134',1,'MAX6956.h']]], + ['max6956_5fra_5fport17',['MAX6956_RA_PORT17',['../MAX6956_8h.html#ab6f3b8bbd8ac56bacf4a57691eb41aaf',1,'MAX6956.h']]], + ['max6956_5fra_5fport18',['MAX6956_RA_PORT18',['../MAX6956_8h.html#a082486ab9eace7838acd56b6ac6301df',1,'MAX6956.h']]], + ['max6956_5fra_5fport19',['MAX6956_RA_PORT19',['../MAX6956_8h.html#a04e65b34862a48ae022c994bbc5968dd',1,'MAX6956.h']]], + ['max6956_5fra_5fport2',['MAX6956_RA_PORT2',['../MAX6956_8h.html#ac4cc75132151b2f662b7c54128391187',1,'MAX6956.h']]], + ['max6956_5fra_5fport20',['MAX6956_RA_PORT20',['../MAX6956_8h.html#aed99f35f5ba961711c4e5bed769aa369',1,'MAX6956.h']]], + ['max6956_5fra_5fport21',['MAX6956_RA_PORT21',['../MAX6956_8h.html#a361dcd71b3da6c5fb57d33951c9e4c54',1,'MAX6956.h']]], + ['max6956_5fra_5fport22',['MAX6956_RA_PORT22',['../MAX6956_8h.html#a67c57767c9f6eda6124ff7368df4293b',1,'MAX6956.h']]], + ['max6956_5fra_5fport23',['MAX6956_RA_PORT23',['../MAX6956_8h.html#a29699b356f81b9fc971a29fc04e68a59',1,'MAX6956.h']]], + ['max6956_5fra_5fport24',['MAX6956_RA_PORT24',['../MAX6956_8h.html#ad053ff9eac065beaa10ad52dcc3d1e3e',1,'MAX6956.h']]], + ['max6956_5fra_5fport25',['MAX6956_RA_PORT25',['../MAX6956_8h.html#a367103a7d8364b916a70f37d0880e334',1,'MAX6956.h']]], + ['max6956_5fra_5fport26',['MAX6956_RA_PORT26',['../MAX6956_8h.html#ae0c19d326ab47406a138d4b66c601de0',1,'MAX6956.h']]], + ['max6956_5fra_5fport27',['MAX6956_RA_PORT27',['../MAX6956_8h.html#ae1219ad62d3ea1b3a86c52736d347618',1,'MAX6956.h']]], + ['max6956_5fra_5fport28',['MAX6956_RA_PORT28',['../MAX6956_8h.html#a07ff69092b95f43595762554c3e35329',1,'MAX6956.h']]], + ['max6956_5fra_5fport29',['MAX6956_RA_PORT29',['../MAX6956_8h.html#a6be82fa185d6c3dd272200727c15f4ac',1,'MAX6956.h']]], + ['max6956_5fra_5fport3',['MAX6956_RA_PORT3',['../MAX6956_8h.html#aa3e011deb16e7054e78e6f71ac33fcba',1,'MAX6956.h']]], + ['max6956_5fra_5fport30',['MAX6956_RA_PORT30',['../MAX6956_8h.html#a34c02dca8e8a97488eb0be51f682cf73',1,'MAX6956.h']]], + ['max6956_5fra_5fport31',['MAX6956_RA_PORT31',['../MAX6956_8h.html#a891d2a47a2fe5a4da056a7732fb6098b',1,'MAX6956.h']]], + ['max6956_5fra_5fport4',['MAX6956_RA_PORT4',['../MAX6956_8h.html#a68339cee27681486c99dabf398f487a0',1,'MAX6956.h']]], + ['max6956_5fra_5fport5',['MAX6956_RA_PORT5',['../MAX6956_8h.html#a92c4653a42f8400a30aa13a60dbc056f',1,'MAX6956.h']]], + ['max6956_5fra_5fport6',['MAX6956_RA_PORT6',['../MAX6956_8h.html#a5af96fba8e40466303a2bcec16df6c6f',1,'MAX6956.h']]], + ['max6956_5fra_5fport7',['MAX6956_RA_PORT7',['../MAX6956_8h.html#a20de98d6d2102960000a70b4bcf6007c',1,'MAX6956.h']]], + ['max6956_5fra_5fport8',['MAX6956_RA_PORT8',['../MAX6956_8h.html#ad0ea7dd1027b558df290150b664b0222',1,'MAX6956.h']]], + ['max6956_5fra_5fport9',['MAX6956_RA_PORT9',['../MAX6956_8h.html#a7d31adbda8965d0d7df0c521571e135c',1,'MAX6956.h']]], + ['max6956_5fra_5fports10_5f17',['MAX6956_RA_PORTS10_17',['../MAX6956_8h.html#aa9837d30cb5f9c9badf20fe50ea3ba26',1,'MAX6956.h']]], + ['max6956_5fra_5fports11_5f18',['MAX6956_RA_PORTS11_18',['../MAX6956_8h.html#a40bf1528e6a7345e0aaa3b86869f3af3',1,'MAX6956.h']]], + ['max6956_5fra_5fports12_5f19',['MAX6956_RA_PORTS12_19',['../MAX6956_8h.html#ab3e1f8d0b913acae6d73f9b5b0d491ff',1,'MAX6956.h']]], + ['max6956_5fra_5fports13_5f20',['MAX6956_RA_PORTS13_20',['../MAX6956_8h.html#ad33d71fa8457fcdb444179768a6376e9',1,'MAX6956.h']]], + ['max6956_5fra_5fports14_5f21',['MAX6956_RA_PORTS14_21',['../MAX6956_8h.html#aeae655678f9a39b8a7f6e9de1a09c59e',1,'MAX6956.h']]], + ['max6956_5fra_5fports15_5f22',['MAX6956_RA_PORTS15_22',['../MAX6956_8h.html#a853b18f366e225131135f6576268a461',1,'MAX6956.h']]], + ['max6956_5fra_5fports16_5f23',['MAX6956_RA_PORTS16_23',['../MAX6956_8h.html#a39c1bb286953031fad9c101604d6f56e',1,'MAX6956.h']]], + ['max6956_5fra_5fports17_5f24',['MAX6956_RA_PORTS17_24',['../MAX6956_8h.html#a8a4536b80e588a3ed6bb2f487499efeb',1,'MAX6956.h']]], + ['max6956_5fra_5fports18_5f25',['MAX6956_RA_PORTS18_25',['../MAX6956_8h.html#a1ae324a27c0648b831978991a44ee33f',1,'MAX6956.h']]], + ['max6956_5fra_5fports19_5f26',['MAX6956_RA_PORTS19_26',['../MAX6956_8h.html#a981a54414024fdd2877704d4d242b748',1,'MAX6956.h']]], + ['max6956_5fra_5fports20_5f27',['MAX6956_RA_PORTS20_27',['../MAX6956_8h.html#abd2280465476a9e3cae302d5e9bf7b62',1,'MAX6956.h']]], + ['max6956_5fra_5fports21_5f28',['MAX6956_RA_PORTS21_28',['../MAX6956_8h.html#adfca6218829cec2697e0975fc7965008',1,'MAX6956.h']]], + ['max6956_5fra_5fports22_5f29',['MAX6956_RA_PORTS22_29',['../MAX6956_8h.html#aa190f6504c585b64f355ce45a24057f1',1,'MAX6956.h']]], + ['max6956_5fra_5fports23_5f30',['MAX6956_RA_PORTS23_30',['../MAX6956_8h.html#a9ae64dcdc091a17982f4888bcd7b1981',1,'MAX6956.h']]], + ['max6956_5fra_5fports24_5f31',['MAX6956_RA_PORTS24_31',['../MAX6956_8h.html#a5054da2b077f91e7f6106373a84476ed',1,'MAX6956.h']]], + ['max6956_5fra_5fports25_5f31',['MAX6956_RA_PORTS25_31',['../MAX6956_8h.html#a38a7fe545ab1b4ca108dabcef50d015f',1,'MAX6956.h']]], + ['max6956_5fra_5fports26_5f31',['MAX6956_RA_PORTS26_31',['../MAX6956_8h.html#ac804c8074d5a6baf79b0595415ae0679',1,'MAX6956.h']]], + ['max6956_5fra_5fports27_5f31',['MAX6956_RA_PORTS27_31',['../MAX6956_8h.html#a5307d28ebcae5028fc482c914eecf48f',1,'MAX6956.h']]], + ['max6956_5fra_5fports28_5f31',['MAX6956_RA_PORTS28_31',['../MAX6956_8h.html#a7554adf2b4214f33584001f4e7c81053',1,'MAX6956.h']]], + ['max6956_5fra_5fports29_5f31',['MAX6956_RA_PORTS29_31',['../MAX6956_8h.html#ab278f8cb075460b9318c029bca24e68a',1,'MAX6956.h']]], + ['max6956_5fra_5fports30_5f31',['MAX6956_RA_PORTS30_31',['../MAX6956_8h.html#ae5873266ac57220286709a468781c3ff',1,'MAX6956.h']]], + ['max6956_5fra_5fports31_5f31',['MAX6956_RA_PORTS31_31',['../MAX6956_8h.html#ad12b528f7fa63249d37126a8d4049aab',1,'MAX6956.h']]], + ['max6956_5fra_5fports4_5f10',['MAX6956_RA_PORTS4_10',['../MAX6956_8h.html#ac32650edffdebee3cfeb90c9daece88b',1,'MAX6956.h']]], + ['max6956_5fra_5fports4_5f11',['MAX6956_RA_PORTS4_11',['../MAX6956_8h.html#a4b0cc79ee765d2f477953a890b2f6209',1,'MAX6956.h']]], + ['max6956_5fra_5fports4_5f7',['MAX6956_RA_PORTS4_7',['../MAX6956_8h.html#a00bff40ca66a7c82b7093536c5047da4',1,'MAX6956.h']]], + ['max6956_5fra_5fports4_5f8',['MAX6956_RA_PORTS4_8',['../MAX6956_8h.html#a3d1cd4727f1748e42a0426c0b70d9c2c',1,'MAX6956.h']]], + ['max6956_5fra_5fports4_5f9',['MAX6956_RA_PORTS4_9',['../MAX6956_8h.html#ad1b71a2b24de60a4d0128576c0e1278b',1,'MAX6956.h']]], + ['max6956_5fra_5fports5_5f12',['MAX6956_RA_PORTS5_12',['../MAX6956_8h.html#a13b8eb94b73c20a02397e50c81bccb57',1,'MAX6956.h']]], + ['max6956_5fra_5fports6_5f13',['MAX6956_RA_PORTS6_13',['../MAX6956_8h.html#af01fef127c33b806d570f1d46a90362f',1,'MAX6956.h']]], + ['max6956_5fra_5fports7_5f14',['MAX6956_RA_PORTS7_14',['../MAX6956_8h.html#ae0f37de2a929dc6f37733c3f112e0fa7',1,'MAX6956.h']]], + ['max6956_5fra_5fports8_5f15',['MAX6956_RA_PORTS8_15',['../MAX6956_8h.html#ae2bd6458f4aa0271d7fb9c8c8fdd0e4f',1,'MAX6956.h']]], + ['max6956_5fra_5fports9_5f16',['MAX6956_RA_PORTS9_16',['../MAX6956_8h.html#aedb8b7ecadabaf8290ac1eacde7db918',1,'MAX6956.h']]], + ['max6956_5fra_5ftransition_5fdetect',['MAX6956_RA_TRANSITION_DETECT',['../MAX6956_8h.html#a4a2b4c395e47e0ec9ef49d3236b8a465',1,'MAX6956.h']]], + ['max6956_5ftransition_5fmask_5fbit',['MAX6956_TRANSITION_MASK_BIT',['../MAX6956_8h.html#abc801853bdfe66591265d04865aba78f',1,'MAX6956.h']]], + ['max6956_5ftransition_5fmask_5flength',['MAX6956_TRANSITION_MASK_LENGTH',['../MAX6956_8h.html#a332868e8a1596e785072ddb8c4a2b4c1',1,'MAX6956.h']]], + ['max6956_5ftransition_5fmask_5fport24_5fbit',['MAX6956_TRANSITION_MASK_PORT24_BIT',['../MAX6956_8h.html#a0a2eb488b9b8d16b5c076d25790ec28e',1,'MAX6956.h']]], + ['max6956_5ftransition_5fmask_5fport25_5fbit',['MAX6956_TRANSITION_MASK_PORT25_BIT',['../MAX6956_8h.html#a04d331f867fa51822f5910ce2b6b891c',1,'MAX6956.h']]], + ['max6956_5ftransition_5fmask_5fport26_5fbit',['MAX6956_TRANSITION_MASK_PORT26_BIT',['../MAX6956_8h.html#ac4f63f4afc199c41dd9b1445259b8d50',1,'MAX6956.h']]], + ['max6956_5ftransition_5fmask_5fport27_5fbit',['MAX6956_TRANSITION_MASK_PORT27_BIT',['../MAX6956_8h.html#a282091cda715bb27f96266f5ae22b492',1,'MAX6956.h']]], + ['max6956_5ftransition_5fmask_5fport28_5fbit',['MAX6956_TRANSITION_MASK_PORT28_BIT',['../MAX6956_8h.html#a927e5369f33337fdea8d89ccc3b3919d',1,'MAX6956.h']]], + ['max6956_5ftransition_5fmask_5fport29_5fbit',['MAX6956_TRANSITION_MASK_PORT29_BIT',['../MAX6956_8h.html#a74adf7234472da3287cb98af583750c9',1,'MAX6956.h']]], + ['max6956_5ftransition_5fmask_5fport30_5fbit',['MAX6956_TRANSITION_MASK_PORT30_BIT',['../MAX6956_8h.html#a0e7f62a1c7d77019ca8ca2c2511f2644',1,'MAX6956.h']]], + ['max6956_5ftransition_5fstatus_5fbit',['MAX6956_TRANSITION_STATUS_BIT',['../MAX6956_8h.html#a29bd01905e66b503151e6d9cdfb035a1',1,'MAX6956.h']]] +]; diff --git a/Arduino/MAX6956/html/search/files_6d.html b/Arduino/MAX6956/html/search/files_6d.html new file mode 100644 index 00000000..6fdcbe37 --- /dev/null +++ b/Arduino/MAX6956/html/search/files_6d.html @@ -0,0 +1,26 @@ + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/Arduino/MAX6956/html/search/files_6d.js b/Arduino/MAX6956/html/search/files_6d.js new file mode 100644 index 00000000..76d89075 --- /dev/null +++ b/Arduino/MAX6956/html/search/files_6d.js @@ -0,0 +1,5 @@ +var searchData= +[ + ['max6956_2ecpp',['MAX6956.cpp',['../MAX6956_8cpp.html',1,'']]], + ['max6956_2eh',['MAX6956.h',['../MAX6956_8h.html',1,'']]] +]; diff --git a/Arduino/MAX6956/html/search/functions_63.html b/Arduino/MAX6956/html/search/functions_63.html new file mode 100644 index 00000000..98924d8a --- /dev/null +++ b/Arduino/MAX6956/html/search/functions_63.html @@ -0,0 +1,26 @@ + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/Arduino/MAX6956/html/search/functions_63.js b/Arduino/MAX6956/html/search/functions_63.js new file mode 100644 index 00000000..6abd3d20 --- /dev/null +++ b/Arduino/MAX6956/html/search/functions_63.js @@ -0,0 +1,6 @@ +var searchData= +[ + ['configallports',['configAllPorts',['../classMAX6956.html#a9e9f11c46bdc86d8e882ed8bb5efabdf',1,'MAX6956']]], + ['configport',['configPort',['../classMAX6956.html#a5e05bead41c585c68de79bbfed971d19',1,'MAX6956']]], + ['configports',['configPorts',['../classMAX6956.html#a400393e30fbe196aef43d8edea890228',1,'MAX6956']]] +]; diff --git a/Arduino/MAX6956/html/search/functions_64.html b/Arduino/MAX6956/html/search/functions_64.html new file mode 100644 index 00000000..bcfb550b --- /dev/null +++ b/Arduino/MAX6956/html/search/functions_64.html @@ -0,0 +1,26 @@ + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/Arduino/MAX6956/html/search/functions_64.js b/Arduino/MAX6956/html/search/functions_64.js new file mode 100644 index 00000000..3d8d8d03 --- /dev/null +++ b/Arduino/MAX6956/html/search/functions_64.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['disableallports',['disableAllPorts',['../classMAX6956.html#a93a81ff86316f63ee1ada3529da2a95b',1,'MAX6956']]] +]; diff --git a/Arduino/MAX6956/html/search/functions_65.html b/Arduino/MAX6956/html/search/functions_65.html new file mode 100644 index 00000000..f81fa7b6 --- /dev/null +++ b/Arduino/MAX6956/html/search/functions_65.html @@ -0,0 +1,26 @@ + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/Arduino/MAX6956/html/search/functions_65.js b/Arduino/MAX6956/html/search/functions_65.js new file mode 100644 index 00000000..25d17ecc --- /dev/null +++ b/Arduino/MAX6956/html/search/functions_65.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['enableallports',['enableAllPorts',['../classMAX6956.html#a51a47c1f69532e96c6caa357889004e3',1,'MAX6956']]] +]; diff --git a/Arduino/MAX6956/html/search/functions_67.html b/Arduino/MAX6956/html/search/functions_67.html new file mode 100644 index 00000000..39cc96de --- /dev/null +++ b/Arduino/MAX6956/html/search/functions_67.html @@ -0,0 +1,26 @@ + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/Arduino/MAX6956/html/search/functions_67.js b/Arduino/MAX6956/html/search/functions_67.js new file mode 100644 index 00000000..400e6433 --- /dev/null +++ b/Arduino/MAX6956/html/search/functions_67.js @@ -0,0 +1,10 @@ +var searchData= +[ + ['getconfigreg',['getConfigReg',['../classMAX6956.html#a5e787204b3f7bf8750376f5bdf77a971',1,'MAX6956']]], + ['getenableindividualcurrent',['getEnableIndividualCurrent',['../classMAX6956.html#abcfe81dd0ffc90284f19503b6366dcfb',1,'MAX6956']]], + ['getenabletransitiondetection',['getEnableTransitionDetection',['../classMAX6956.html#a76e9ab35769854b3e4224499897601ec',1,'MAX6956']]], + ['getglobalcurrent',['getGlobalCurrent',['../classMAX6956.html#a1926760b263588314fd759d129091940',1,'MAX6956']]], + ['getinputmask',['getInputMask',['../classMAX6956.html#a56245915d7d4cd8fd34629bd91695147',1,'MAX6956']]], + ['getpower',['getPower',['../classMAX6956.html#acdc18c36735d8015651d4e3c75da4300',1,'MAX6956']]], + ['gettestmode',['getTestMode',['../classMAX6956.html#ad4f99f08d1cf08c5a0097215e680a80a',1,'MAX6956']]] +]; diff --git a/Arduino/MAX6956/html/search/functions_69.html b/Arduino/MAX6956/html/search/functions_69.html new file mode 100644 index 00000000..954ac84b --- /dev/null +++ b/Arduino/MAX6956/html/search/functions_69.html @@ -0,0 +1,26 @@ + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/Arduino/MAX6956/html/search/functions_69.js b/Arduino/MAX6956/html/search/functions_69.js new file mode 100644 index 00000000..47c8e9d4 --- /dev/null +++ b/Arduino/MAX6956/html/search/functions_69.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['initialize',['initialize',['../classMAX6956.html#ad63e927adc2427b4b661f2422ddd40d8',1,'MAX6956']]] +]; diff --git a/Arduino/MAX6956/html/search/functions_6d.html b/Arduino/MAX6956/html/search/functions_6d.html new file mode 100644 index 00000000..f721e116 --- /dev/null +++ b/Arduino/MAX6956/html/search/functions_6d.html @@ -0,0 +1,26 @@ + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/Arduino/MAX6956/html/search/functions_6d.js b/Arduino/MAX6956/html/search/functions_6d.js new file mode 100644 index 00000000..87049491 --- /dev/null +++ b/Arduino/MAX6956/html/search/functions_6d.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['max6956',['MAX6956',['../classMAX6956.html#a210d9e95978d61357db757cb80475bde',1,'MAX6956::MAX6956()'],['../classMAX6956.html#a1a7b33190871a09d81c5bec741b645b7',1,'MAX6956::MAX6956(uint8_t address)']]] +]; diff --git a/Arduino/MAX6956/html/search/functions_72.html b/Arduino/MAX6956/html/search/functions_72.html new file mode 100644 index 00000000..de10844f --- /dev/null +++ b/Arduino/MAX6956/html/search/functions_72.html @@ -0,0 +1,26 @@ + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/Arduino/MAX6956/html/search/functions_72.js b/Arduino/MAX6956/html/search/functions_72.js new file mode 100644 index 00000000..64daaea0 --- /dev/null +++ b/Arduino/MAX6956/html/search/functions_72.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['reset',['reset',['../classMAX6956.html#a3b9166eee826a876bbf29bc63b090fe7',1,'MAX6956']]] +]; diff --git a/Arduino/MAX6956/html/search/functions_73.html b/Arduino/MAX6956/html/search/functions_73.html new file mode 100644 index 00000000..a8952453 --- /dev/null +++ b/Arduino/MAX6956/html/search/functions_73.html @@ -0,0 +1,26 @@ + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/Arduino/MAX6956/html/search/functions_73.js b/Arduino/MAX6956/html/search/functions_73.js new file mode 100644 index 00000000..74b221f6 --- /dev/null +++ b/Arduino/MAX6956/html/search/functions_73.js @@ -0,0 +1,13 @@ +var searchData= +[ + ['setallportscurrent',['setAllPortsCurrent',['../classMAX6956.html#a9a27a32611fa05766946c33850510644',1,'MAX6956']]], + ['setconfigreg',['setConfigReg',['../classMAX6956.html#ad06b9ed9f6e18f81d8379a6e10391ea4',1,'MAX6956']]], + ['setenableindividualcurrent',['setEnableIndividualCurrent',['../classMAX6956.html#a35bc5701a290409144929e640cad1748',1,'MAX6956']]], + ['setenabletransitiondetection',['setEnableTransitionDetection',['../classMAX6956.html#a67b65b80e09a3225dd4f6413bfab2844',1,'MAX6956']]], + ['setglobalcurrent',['setGlobalCurrent',['../classMAX6956.html#a4669dcc0f2f89f8fe73a0fa9b97dae21',1,'MAX6956']]], + ['setinputmask',['setInputMask',['../classMAX6956.html#a7ce45652fb0490af0ecb4eaebc230419',1,'MAX6956']]], + ['setportcurrent',['setPortCurrent',['../classMAX6956.html#a76a617f3b8982bb3855c5152b480097a',1,'MAX6956']]], + ['setportlevel',['setPortLevel',['../classMAX6956.html#a98fa3831a47355fe0856caa74a9cf810',1,'MAX6956']]], + ['setpower',['setPower',['../classMAX6956.html#ae10ac505e3857d31ca3823225983a697',1,'MAX6956']]], + ['settestmode',['setTestMode',['../classMAX6956.html#ad1b4e5cafd91acd2be2b6fb8197afef0',1,'MAX6956']]] +]; diff --git a/Arduino/MAX6956/html/search/functions_74.html b/Arduino/MAX6956/html/search/functions_74.html new file mode 100644 index 00000000..8b138f02 --- /dev/null +++ b/Arduino/MAX6956/html/search/functions_74.html @@ -0,0 +1,26 @@ + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/Arduino/MAX6956/html/search/functions_74.js b/Arduino/MAX6956/html/search/functions_74.js new file mode 100644 index 00000000..fb321603 --- /dev/null +++ b/Arduino/MAX6956/html/search/functions_74.js @@ -0,0 +1,5 @@ +var searchData= +[ + ['testconnection',['testConnection',['../classMAX6956.html#a60bd352328d77e59a4d51a3c55d38a25',1,'MAX6956']]], + ['togglepower',['togglePower',['../classMAX6956.html#a993f35d31d1f2489f9d2965c3886f848',1,'MAX6956']]] +]; diff --git a/Arduino/MAX6956/html/search/mag_sel.png b/Arduino/MAX6956/html/search/mag_sel.png new file mode 100644 index 0000000000000000000000000000000000000000..81f6040a2092402b4d98f9ffa8855d12a0d4ca17 GIT binary patch literal 563 zcmV-30?hr1P)zxx&tqG15pu7)IiiXFflOc2k;dXd>%13GZAy? zRz!q0=|E6a6vV)&ZBS~G9oe0kbqyw1*gvY`{Pop2oKq#FlzgXt@Xh-7fxh>}`Fxg> z$%N%{$!4=5nM{(;=c!aG1Ofr^Do{u%Ih{^&Fc@H2)+a-?TBXrw5DW&z%Nb6mQ!L9O zl}b@6mB?f=tX3;#vl)}ggh(Vpyh(IK z(Mb0D{l{U$FsRjP;!{($+bsaaVi8T#1c0V#qEIOCYa9@UVLV`f__E81L;?WEaRA;Y zUH;rZ;vb;mk7JX|$=i3O~&If0O@oZfLg8gfIjW=dcBsz;gI=!{-r4# z4%6v$&~;q^j7Fo67yJ(NJWuX+I~I!tj^nW3?}^9bq|<3^+vapS5sgM^x7!cs(+mMT z&y%j};&~po+YO)3hoUH4E*E;e9>?R6SS&`X)p`njycAVcg{rEb41T{~Hk(bl-7eSb zmFxA2uIqo#@R?lKm50ND`~6Nfn|-b1|L6O98vt3Tx@gKz#isxO002ovPDHLkV1kyW B_l^Jn literal 0 HcmV?d00001 diff --git a/Arduino/MAX6956/html/search/nomatches.html b/Arduino/MAX6956/html/search/nomatches.html new file mode 100644 index 00000000..b1ded27e --- /dev/null +++ b/Arduino/MAX6956/html/search/nomatches.html @@ -0,0 +1,12 @@ + + + + + + + +
+
No Matches
+
+ + diff --git a/Arduino/MAX6956/html/search/search.css b/Arduino/MAX6956/html/search/search.css new file mode 100644 index 00000000..4d7612ff --- /dev/null +++ b/Arduino/MAX6956/html/search/search.css @@ -0,0 +1,271 @@ +/*---------------- Search Box */ + +#FSearchBox { + float: left; +} + +#MSearchBox { + white-space : nowrap; + position: absolute; + float: none; + display: inline; + margin-top: 8px; + right: 0px; + width: 170px; + z-index: 102; + background-color: white; +} + +#MSearchBox .left +{ + display:block; + position:absolute; + left:10px; + width:20px; + height:19px; + background:url('http://github.com/search_l.png') no-repeat; + background-position:right; +} + +#MSearchSelect { + display:block; + position:absolute; + width:20px; + height:19px; +} + +.left #MSearchSelect { + left:4px; +} + +.right #MSearchSelect { + right:5px; +} + +#MSearchField { + display:block; + position:absolute; + height:19px; + background:url('http://github.com/search_m.png') repeat-x; + border:none; + width:111px; + margin-left:20px; + padding-left:4px; + color: #909090; + outline: none; + font: 9pt Arial, Verdana, sans-serif; +} + +#FSearchBox #MSearchField { + margin-left:15px; +} + +#MSearchBox .right { + display:block; + position:absolute; + right:10px; + top:0px; + width:20px; + height:19px; + background:url('http://github.com/search_r.png') no-repeat; + background-position:left; +} + +#MSearchClose { + display: none; + position: absolute; + top: 4px; + background : none; + border: none; + margin: 0px 4px 0px 0px; + padding: 0px 0px; + outline: none; +} + +.left #MSearchClose { + left: 6px; +} + +.right #MSearchClose { + right: 2px; +} + +.MSearchBoxActive #MSearchField { + color: #000000; +} + +/*---------------- Search filter selection */ + +#MSearchSelectWindow { + display: none; + position: absolute; + left: 0; top: 0; + border: 1px solid #90A5CE; + background-color: #F9FAFC; + z-index: 1; + padding-top: 4px; + padding-bottom: 4px; + -moz-border-radius: 4px; + -webkit-border-top-left-radius: 4px; + -webkit-border-top-right-radius: 4px; + -webkit-border-bottom-left-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); +} + +.SelectItem { + font: 8pt Arial, Verdana, sans-serif; + padding-left: 2px; + padding-right: 12px; + border: 0px; +} + +span.SelectionMark { + margin-right: 4px; + font-family: monospace; + outline-style: none; + text-decoration: none; +} + +a.SelectItem { + display: block; + outline-style: none; + color: #000000; + text-decoration: none; + padding-left: 6px; + padding-right: 12px; +} + +a.SelectItem:focus, +a.SelectItem:active { + color: #000000; + outline-style: none; + text-decoration: none; +} + +a.SelectItem:hover { + color: #FFFFFF; + background-color: #3D578C; + outline-style: none; + text-decoration: none; + cursor: pointer; + display: block; +} + +/*---------------- Search results window */ + +iframe#MSearchResults { + width: 60ex; + height: 15em; +} + +#MSearchResultsWindow { + display: none; + position: absolute; + left: 0; top: 0; + border: 1px solid #000; + background-color: #EEF1F7; +} + +/* ----------------------------------- */ + + +#SRIndex { + clear:both; + padding-bottom: 15px; +} + +.SREntry { + font-size: 10pt; + padding-left: 1ex; +} + +.SRPage .SREntry { + font-size: 8pt; + padding: 1px 5px; +} + +body.SRPage { + margin: 5px 2px; +} + +.SRChildren { + padding-left: 3ex; padding-bottom: .5em +} + +.SRPage .SRChildren { + display: none; +} + +.SRSymbol { + font-weight: bold; + color: #425E97; + font-family: Arial, Verdana, sans-serif; + text-decoration: none; + outline: none; +} + +a.SRScope { + display: block; + color: #425E97; + font-family: Arial, Verdana, sans-serif; + text-decoration: none; + outline: none; +} + +a.SRSymbol:focus, a.SRSymbol:active, +a.SRScope:focus, a.SRScope:active { + text-decoration: underline; +} + +span.SRScope { + padding-left: 4px; +} + +.SRPage .SRStatus { + padding: 2px 5px; + font-size: 8pt; + font-style: italic; +} + +.SRResult { + display: none; +} + +DIV.searchresults { + margin-left: 10px; + margin-right: 10px; +} + +/*---------------- External search page results */ + +.searchresult { + background-color: #F0F3F8; +} + +.pages b { + color: white; + padding: 5px 5px 3px 5px; + background-image: url("http://github.com/tab_a.png"); + background-repeat: repeat-x; + text-shadow: 0 1px 1px #000000; +} + +.pages { + line-height: 17px; + margin-left: 4px; + text-decoration: none; +} + +.hl { + font-weight: bold; +} + +#searchresults { + margin-bottom: 20px; +} + +.searchpages { + margin-top: 10px; +} + diff --git a/Arduino/MAX6956/html/search/search.js b/Arduino/MAX6956/html/search/search.js new file mode 100644 index 00000000..223ccae5 --- /dev/null +++ b/Arduino/MAX6956/html/search/search.js @@ -0,0 +1,805 @@ +// Search script generated by doxygen +// Copyright (C) 2009 by Dimitri van Heesch. + +// The code in this file is loosly based on main.js, part of Natural Docs, +// which is Copyright (C) 2003-2008 Greg Valure +// Natural Docs is licensed under the GPL. + +var indexSectionsWithContent = +{ + 0: "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011110101000100101110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + 1: "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + 2: "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + 3: "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001110101000100001110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + 4: "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010100000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + 5: "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" +}; + +var indexSectionNames = +{ + 0: "all", + 1: "classes", + 2: "files", + 3: "functions", + 4: "variables", + 5: "defines" +}; + +function convertToId(search) +{ + var result = ''; + for (i=0;i do a search + { + this.Search(); + } + } + + this.OnSearchSelectKey = function(evt) + { + var e = (evt) ? evt : window.event; // for IE + if (e.keyCode==40 && this.searchIndex0) // Up + { + this.searchIndex--; + this.OnSelectItem(this.searchIndex); + } + else if (e.keyCode==13 || e.keyCode==27) + { + this.OnSelectItem(this.searchIndex); + this.CloseSelectionWindow(); + this.DOMSearchField().focus(); + } + return false; + } + + // --------- Actions + + // Closes the results window. + this.CloseResultsWindow = function() + { + this.DOMPopupSearchResultsWindow().style.display = 'none'; + this.DOMSearchClose().style.display = 'none'; + this.Activate(false); + } + + this.CloseSelectionWindow = function() + { + this.DOMSearchSelectWindow().style.display = 'none'; + } + + // Performs a search. + this.Search = function() + { + this.keyTimeout = 0; + + // strip leading whitespace + var searchValue = this.DOMSearchField().value.replace(/^ +/, ""); + + var code = searchValue.toLowerCase().charCodeAt(0); + var hexCode; + if (code<16) + { + hexCode="0"+code.toString(16); + } + else + { + hexCode=code.toString(16); + } + + var resultsPage; + var resultsPageWithSearch; + var hasResultsPage; + + if (indexSectionsWithContent[this.searchIndex].charAt(code) == '1') + { + resultsPage = this.resultsPath + '/' + indexSectionNames[this.searchIndex] + '_' + hexCode + '.html'; + resultsPageWithSearch = resultsPage+'?'+escape(searchValue); + hasResultsPage = true; + } + else // nothing available for this search term + { + resultsPage = this.resultsPath + '/nomatches.html'; + resultsPageWithSearch = resultsPage; + hasResultsPage = false; + } + + window.frames.MSearchResults.location = resultsPageWithSearch; + var domPopupSearchResultsWindow = this.DOMPopupSearchResultsWindow(); + + if (domPopupSearchResultsWindow.style.display!='block') + { + var domSearchBox = this.DOMSearchBox(); + this.DOMSearchClose().style.display = 'inline'; + if (this.insideFrame) + { + var domPopupSearchResults = this.DOMPopupSearchResults(); + domPopupSearchResultsWindow.style.position = 'relative'; + domPopupSearchResultsWindow.style.display = 'block'; + var width = document.body.clientWidth - 8; // the -8 is for IE :-( + domPopupSearchResultsWindow.style.width = width + 'px'; + domPopupSearchResults.style.width = width + 'px'; + } + else + { + var domPopupSearchResults = this.DOMPopupSearchResults(); + var left = getXPos(domSearchBox) + 150; // domSearchBox.offsetWidth; + var top = getYPos(domSearchBox) + 20; // domSearchBox.offsetHeight + 1; + domPopupSearchResultsWindow.style.display = 'block'; + left -= domPopupSearchResults.offsetWidth; + domPopupSearchResultsWindow.style.top = top + 'px'; + domPopupSearchResultsWindow.style.left = left + 'px'; + } + } + + this.lastSearchValue = searchValue; + this.lastResultsPage = resultsPage; + } + + // -------- Activation Functions + + // Activates or deactivates the search panel, resetting things to + // their default values if necessary. + this.Activate = function(isActive) + { + if (isActive || // open it + this.DOMPopupSearchResultsWindow().style.display == 'block' + ) + { + this.DOMSearchBox().className = 'MSearchBoxActive'; + + var searchField = this.DOMSearchField(); + + if (searchField.value == this.searchLabel) // clear "Search" term upon entry + { + searchField.value = ''; + this.searchActive = true; + } + } + else if (!isActive) // directly remove the panel + { + this.DOMSearchBox().className = 'MSearchBoxInactive'; + this.DOMSearchField().value = this.searchLabel; + this.searchActive = false; + this.lastSearchValue = '' + this.lastResultsPage = ''; + } + } +} + +// ----------------------------------------------------------------------- + +// The class that handles everything on the search results page. +function SearchResults(name) +{ + // The number of matches from the last run of . + this.lastMatchCount = 0; + this.lastKey = 0; + this.repeatOn = false; + + // Toggles the visibility of the passed element ID. + this.FindChildElement = function(id) + { + var parentElement = document.getElementById(id); + var element = parentElement.firstChild; + + while (element && element!=parentElement) + { + if (element.nodeName == 'DIV' && element.className == 'SRChildren') + { + return element; + } + + if (element.nodeName == 'DIV' && element.hasChildNodes()) + { + element = element.firstChild; + } + else if (element.nextSibling) + { + element = element.nextSibling; + } + else + { + do + { + element = element.parentNode; + } + while (element && element!=parentElement && !element.nextSibling); + + if (element && element!=parentElement) + { + element = element.nextSibling; + } + } + } + } + + this.Toggle = function(id) + { + var element = this.FindChildElement(id); + if (element) + { + if (element.style.display == 'block') + { + element.style.display = 'none'; + } + else + { + element.style.display = 'block'; + } + } + } + + // Searches for the passed string. If there is no parameter, + // it takes it from the URL query. + // + // Always returns true, since other documents may try to call it + // and that may or may not be possible. + this.Search = function(search) + { + if (!search) // get search word from URL + { + search = window.location.search; + search = search.substring(1); // Remove the leading '?' + search = unescape(search); + } + + search = search.replace(/^ +/, ""); // strip leading spaces + search = search.replace(/ +$/, ""); // strip trailing spaces + search = search.toLowerCase(); + search = convertToId(search); + + var resultRows = document.getElementsByTagName("div"); + var matches = 0; + + var i = 0; + while (i < resultRows.length) + { + var row = resultRows.item(i); + if (row.className == "SRResult") + { + var rowMatchName = row.id.toLowerCase(); + rowMatchName = rowMatchName.replace(/^sr\d*_/, ''); // strip 'sr123_' + + if (search.length<=rowMatchName.length && + rowMatchName.substr(0, search.length)==search) + { + row.style.display = 'block'; + matches++; + } + else + { + row.style.display = 'none'; + } + } + i++; + } + document.getElementById("Searching").style.display='none'; + if (matches == 0) // no results + { + document.getElementById("NoMatches").style.display='block'; + } + else // at least one result + { + document.getElementById("NoMatches").style.display='none'; + } + this.lastMatchCount = matches; + return true; + } + + // return the first item with index index or higher that is visible + this.NavNext = function(index) + { + var focusItem; + while (1) + { + var focusName = 'Item'+index; + focusItem = document.getElementById(focusName); + if (focusItem && focusItem.parentNode.parentNode.style.display=='block') + { + break; + } + else if (!focusItem) // last element + { + break; + } + focusItem=null; + index++; + } + return focusItem; + } + + this.NavPrev = function(index) + { + var focusItem; + while (1) + { + var focusName = 'Item'+index; + focusItem = document.getElementById(focusName); + if (focusItem && focusItem.parentNode.parentNode.style.display=='block') + { + break; + } + else if (!focusItem) // last element + { + break; + } + focusItem=null; + index--; + } + return focusItem; + } + + this.ProcessKeys = function(e) + { + if (e.type == "keydown") + { + this.repeatOn = false; + this.lastKey = e.keyCode; + } + else if (e.type == "keypress") + { + if (!this.repeatOn) + { + if (this.lastKey) this.repeatOn = true; + return false; // ignore first keypress after keydown + } + } + else if (e.type == "keyup") + { + this.lastKey = 0; + this.repeatOn = false; + } + return this.lastKey!=0; + } + + this.Nav = function(evt,itemIndex) + { + var e = (evt) ? evt : window.event; // for IE + if (e.keyCode==13) return true; + if (!this.ProcessKeys(e)) return false; + + if (this.lastKey==38) // Up + { + var newIndex = itemIndex-1; + var focusItem = this.NavPrev(newIndex); + if (focusItem) + { + var child = this.FindChildElement(focusItem.parentNode.parentNode.id); + if (child && child.style.display == 'block') // children visible + { + var n=0; + var tmpElem; + while (1) // search for last child + { + tmpElem = document.getElementById('Item'+newIndex+'_c'+n); + if (tmpElem) + { + focusItem = tmpElem; + } + else // found it! + { + break; + } + n++; + } + } + } + if (focusItem) + { + focusItem.focus(); + } + else // return focus to search field + { + parent.document.getElementById("MSearchField").focus(); + } + } + else if (this.lastKey==40) // Down + { + var newIndex = itemIndex+1; + var focusItem; + var item = document.getElementById('Item'+itemIndex); + var elem = this.FindChildElement(item.parentNode.parentNode.id); + if (elem && elem.style.display == 'block') // children visible + { + focusItem = document.getElementById('Item'+itemIndex+'_c0'); + } + if (!focusItem) focusItem = this.NavNext(newIndex); + if (focusItem) focusItem.focus(); + } + else if (this.lastKey==39) // Right + { + var item = document.getElementById('Item'+itemIndex); + var elem = this.FindChildElement(item.parentNode.parentNode.id); + if (elem) elem.style.display = 'block'; + } + else if (this.lastKey==37) // Left + { + var item = document.getElementById('Item'+itemIndex); + var elem = this.FindChildElement(item.parentNode.parentNode.id); + if (elem) elem.style.display = 'none'; + } + else if (this.lastKey==27) // Escape + { + parent.searchBox.CloseResultsWindow(); + parent.document.getElementById("MSearchField").focus(); + } + else if (this.lastKey==13) // Enter + { + return true; + } + return false; + } + + this.NavChild = function(evt,itemIndex,childIndex) + { + var e = (evt) ? evt : window.event; // for IE + if (e.keyCode==13) return true; + if (!this.ProcessKeys(e)) return false; + + if (this.lastKey==38) // Up + { + if (childIndex>0) + { + var newIndex = childIndex-1; + document.getElementById('Item'+itemIndex+'_c'+newIndex).focus(); + } + else // already at first child, jump to parent + { + document.getElementById('Item'+itemIndex).focus(); + } + } + else if (this.lastKey==40) // Down + { + var newIndex = childIndex+1; + var elem = document.getElementById('Item'+itemIndex+'_c'+newIndex); + if (!elem) // last child, jump to parent next parent + { + elem = this.NavNext(itemIndex+1); + } + if (elem) + { + elem.focus(); + } + } + else if (this.lastKey==27) // Escape + { + parent.searchBox.CloseResultsWindow(); + parent.document.getElementById("MSearchField").focus(); + } + else if (this.lastKey==13) // Enter + { + return true; + } + return false; + } +} + +function setKeyActions(elem,action) +{ + elem.setAttribute('onkeydown',action); + elem.setAttribute('onkeypress',action); + elem.setAttribute('onkeyup',action); +} + +function setClassAttr(elem,attr) +{ + elem.setAttribute('class',attr); + elem.setAttribute('className',attr); +} + +function createResults() +{ + var results = document.getElementById("SRResults"); + for (var e=0; ek7RCwB~R6VQOP#AvB$vH7i{6H{96zot$7cZT<7246EF5Np6N}+$IbiG6W zg#87A+NFaX+=_^xM1#gCtshC=E{%9^uQX_%?YwXvo{#q&MnpJ8uh(O?ZRc&~_1%^SsPxG@rfElJg-?U zm!Cz-IOn(qJP3kDp-^~qt+FGbl=5jNli^Wj_xIBG{Rc0en{!oFvyoNC7{V~T8}b>| z=jL2WIReZzX(YN(_9fV;BBD$VXQIxNasAL8ATvEu822WQ%mvv4FO#qs` BFGc_W literal 0 HcmV?d00001 diff --git a/Arduino/MAX6956/html/search/search_r.png b/Arduino/MAX6956/html/search/search_r.png new file mode 100644 index 0000000000000000000000000000000000000000..97ee8b439687084201b79c6f776a41f495c6392a GIT binary patch literal 612 zcmV-q0-ODbP)PbXFRCwB?)W514K@j&X?z2*SxFI6-@HT2E2K=9X9%Pb zEK*!TBw&g(DMC;|A)uGlRkOS9vd-?zNs%bR4d$w+ox_iFnE8fvIvv7^5<(>Te12Li z7C)9srCzmK{ZcNM{YIl9j{DePFgOWiS%xG@5CnnnJa4nvY<^glbz7^|-ZY!dUkAwd z{gaTC@_>b5h~;ug#R0wRL0>o5!hxm*s0VW?8dr}O#zXTRTnrQm_Z7z1Mrnx>&p zD4qifUjzLvbVVWi?l?rUzwt^sdb~d!f_LEhsRVIXZtQ=qSxuxqm zEX#tf>$?M_Y1-LSDT)HqG?`%-%ZpY!#{N!rcNIiL;G7F0`l?)mNGTD9;f9F5Up3Kg zw}a<-JylhG&;=!>B+fZaCX+?C+kHYrP%c?X2!Zu_olK|GcS4A70HEy;vn)I0>0kLH z`jc(WIaaHc7!HS@f*^R^Znx8W=_jIl2oWJoQ*h1^$FX!>*PqR1J8k|fw}w_y}TpE>7m8DqDO<3z`OzXt$ccSejbEZCg@0000 + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/Arduino/MAX6956/html/search/variables_62.js b/Arduino/MAX6956/html/search/variables_62.js new file mode 100644 index 00000000..b44b09cd --- /dev/null +++ b/Arduino/MAX6956/html/search/variables_62.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['buffer',['buffer',['../classMAX6956.html#a9f4597436b10ee86a02c96c2b0605851',1,'MAX6956']]] +]; diff --git a/Arduino/MAX6956/html/search/variables_64.html b/Arduino/MAX6956/html/search/variables_64.html new file mode 100644 index 00000000..89296ec7 --- /dev/null +++ b/Arduino/MAX6956/html/search/variables_64.html @@ -0,0 +1,26 @@ + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/Arduino/MAX6956/html/search/variables_64.js b/Arduino/MAX6956/html/search/variables_64.js new file mode 100644 index 00000000..dc8bc0a7 --- /dev/null +++ b/Arduino/MAX6956/html/search/variables_64.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['devaddr',['devAddr',['../classMAX6956.html#a6ba2f8011914df50d6022ab54b27748d',1,'MAX6956']]] +]; diff --git a/Arduino/MAX6956/html/search/variables_70.html b/Arduino/MAX6956/html/search/variables_70.html new file mode 100644 index 00000000..e36abe96 --- /dev/null +++ b/Arduino/MAX6956/html/search/variables_70.html @@ -0,0 +1,26 @@ + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/Arduino/MAX6956/html/search/variables_70.js b/Arduino/MAX6956/html/search/variables_70.js new file mode 100644 index 00000000..21d9faa9 --- /dev/null +++ b/Arduino/MAX6956/html/search/variables_70.js @@ -0,0 +1,10 @@ +var searchData= +[ + ['portconfig',['portConfig',['../classMAX6956.html#a9799e7684546e3e9b24506d436586a09',1,'MAX6956']]], + ['portcurrentbit',['portCurrentBit',['../classMAX6956.html#ad3057b6b21ae712acb0129270da63334',1,'MAX6956']]], + ['portcurrentra',['portCurrentRA',['../classMAX6956.html#ab0d382db3afe7930d1b95311bfd90164',1,'MAX6956']]], + ['portsconfig',['portsConfig',['../classMAX6956.html#a8b915615042c5ef96fbf3a5c260d4716',1,'MAX6956']]], + ['portsstatus',['portsStatus',['../classMAX6956.html#ae8da9a65da74dce7eb907319b0198847',1,'MAX6956']]], + ['psarrayindex',['psArrayIndex',['../classMAX6956.html#a967e25fac00c0ab59be854289eb36353',1,'MAX6956']]], + ['psbitposition',['psBitPosition',['../classMAX6956.html#a92b5dc05a1483c49c150db13dcd1f283',1,'MAX6956']]] +]; diff --git a/Arduino/MAX6956/html/sync_off.png b/Arduino/MAX6956/html/sync_off.png new file mode 100644 index 0000000000000000000000000000000000000000..3b443fc62892114406e3d399421b2a881b897acc GIT binary patch literal 853 zcmV-b1FHOqP)oT|#XixUYy%lpuf3i8{fX!o zUyDD0jOrAiT^tq>fLSOOABs-#u{dV^F$b{L9&!2=9&RmV;;8s^x&UqB$PCj4FdKbh zoB1WTskPUPu05XzFbA}=KZ-GP1fPpAfSs>6AHb12UlR%-i&uOlTpFNS7{jm@mkU1V zh`nrXr~+^lsV-s1dkZOaI|kYyVj3WBpPCY{n~yd%u%e+d=f%`N0FItMPtdgBb@py; zq@v6NVArhyTC7)ULw-Jy8y42S1~4n(3LkrW8mW(F-4oXUP3E`e#g**YyqI7h-J2zK zK{m9##m4ri!7N>CqQqCcnI3hqo1I;Yh&QLNY4T`*ptiQGozK>FF$!$+84Z`xwmeMh zJ0WT+OH$WYFALEaGj2_l+#DC3t7_S`vHpSivNeFbP6+r50cO8iu)`7i%Z4BTPh@_m3Tk!nAm^)5Bqnr%Ov|Baunj#&RPtRuK& z4RGz|D5HNrW83-#ydk}tVKJrNmyYt-sTxLGlJY5nc&Re zU4SgHNPx8~Yxwr$bsju?4q&%T1874xxzq+_%?h8_ofw~(bld=o3iC)LUNR*BY%c0y zWd_jX{Y8`l%z+ol1$@Qa?Cy!(0CVIEeYpKZ`(9{z>3$CIe;pJDQk$m3p}$>xBm4lb zKo{4S)`wdU9Ba9jJbVJ0C=SOefZe%d$8=2r={nu<_^a3~>c#t_U6dye5)JrR(_a^E f@}b6j1K9lwFJq@>o)+Ry00000NkvXXu0mjfWa5j* literal 0 HcmV?d00001 diff --git a/Arduino/MAX6956/html/sync_on.png b/Arduino/MAX6956/html/sync_on.png new file mode 100644 index 0000000000000000000000000000000000000000..e08320fb64e6fa33b573005ed6d8fe294e19db76 GIT binary patch literal 845 zcmV-T1G4;yP)Y;xxyHF2B5Wzm| zOOGupOTn@c(JmBOl)e;XMNnZuiTJP>rM8<|Q`7I_))aP?*T)ow&n59{}X4$3Goat zgjs?*aasfbrokzG5cT4K=uG`E14xZl@z)F={P0Y^?$4t z>v!teRnNZym<6h{7sLyF1V0HsfEl+l6TrZpsfr1}luH~F7L}ktXu|*uVX^RG$L0`K zWs3j|0tIvVe(N%_?2{(iCPFGf#B6Hjy6o&}D$A%W%jfO8_W%ZO#-mh}EM$LMn7joJ z05dHr!5Y92g+31l<%i1(=L1a1pXX+OYnalY>31V4K}BjyRe3)9n#;-cCVRD_IG1fT zOKGeNY8q;TL@K{dj@D^scf&VCs*-Jb>8b>|`b*osv52-!A?BpbYtTQBns5EAU**$m zSnVSm(teh>tQi*S*A>#ySc=n;`BHz`DuG4&g4Kf8lLhca+zvZ7t7RflD6-i-mcK=M z!=^P$*u2)bkY5asG4gsss!Hn%u~>}kIW`vMs%lJLH+u*9<4PaV_c6U`KqWXQH%+Nu zTv41O(^ZVi@qhjQdG!fbZw&y+2o!iYymO^?ud3{P*HdoX83YV*Uu_HB=?U&W9%AU# z80}k1SS-CXTU7dcQlsm<^oYLxVSseqY6NO}dc`Nj?8vrhNuCdm@^{a3AQ_>6myOj+ z`1RsLUXF|dm|3k7s2jD(B{rzE>WI2scH8i1;=O5Cc9xB3^aJk%fQjqsu+kH#0=_5a z0nCE8@dbQa-|YIuUVvG0L_IwHMEhOj$Mj4Uq05 X8=0q~qBNan00000NkvXXu0mjfptF>5 literal 0 HcmV?d00001 diff --git a/Arduino/MAX6956/html/tab_a.png b/Arduino/MAX6956/html/tab_a.png new file mode 100644 index 0000000000000000000000000000000000000000..3b725c41c5a527a3a3e40097077d0e206a681247 GIT binary patch literal 142 zcmeAS@N?(olHy`uVBq!ia0vp^j6kfy!2~3aiye;!QlXwMjv*C{Z|8b*H5dputLHD# z=<0|*y7z(Vor?d;H&?EG&cXR}?!j-Lm&u1OOI7AIF5&c)RFE;&p0MYK>*Kl@eiymD r@|NpwKX@^z+;{u_Z~trSBfrMKa%3`zocFjEXaR$#tDnm{r-UW|TZ1%4 literal 0 HcmV?d00001 diff --git a/Arduino/MAX6956/html/tab_b.png b/Arduino/MAX6956/html/tab_b.png new file mode 100644 index 0000000000000000000000000000000000000000..e2b4a8638cb3496a016eaed9e16ffc12846dea18 GIT binary patch literal 169 zcmeAS@N?(olHy`uVBq!ia0vp^j6kfy!2~3aiye;!QU#tajv*C{Z}0l@H7kg?K0Lnr z!j&C6_(~HV9oQ0Pa6x{-v0AGV_E?vLn=ZI-;YrdjIl`U`uzuDWSP?o#Dmo{%SgM#oan kX~E1%D-|#H#QbHoIja2U-MgvsK&LQxy85}Sb4q9e0Efg%P5=M^ literal 0 HcmV?d00001 diff --git a/Arduino/MAX6956/html/tabs.css b/Arduino/MAX6956/html/tabs.css new file mode 100644 index 00000000..9cf578f2 --- /dev/null +++ b/Arduino/MAX6956/html/tabs.css @@ -0,0 +1,60 @@ +.tabs, .tabs2, .tabs3 { + background-image: url('http://github.com/tab_b.png'); + width: 100%; + z-index: 101; + font-size: 13px; + font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; +} + +.tabs2 { + font-size: 10px; +} +.tabs3 { + font-size: 9px; +} + +.tablist { + margin: 0; + padding: 0; + display: table; +} + +.tablist li { + float: left; + display: table-cell; + background-image: url('http://github.com/tab_b.png'); + line-height: 36px; + list-style: none; +} + +.tablist a { + display: block; + padding: 0 20px; + font-weight: bold; + background-image:url('http://github.com/tab_s.png'); + background-repeat:no-repeat; + background-position:right; + color: #283A5D; + text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); + text-decoration: none; + outline: none; +} + +.tabs3 .tablist a { + padding: 0 10px; +} + +.tablist a:hover { + background-image: url('http://github.com/tab_h.png'); + background-repeat:repeat-x; + color: #fff; + text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0); + text-decoration: none; +} + +.tablist li.current a { + background-image: url('http://github.com/tab_a.png'); + background-repeat:repeat-x; + color: #fff; + text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0); +} diff --git a/Arduino/MAX6956/keywords.txt b/Arduino/MAX6956/keywords.txt new file mode 100755 index 00000000..20591618 --- /dev/null +++ b/Arduino/MAX6956/keywords.txt @@ -0,0 +1,71 @@ +####################################### +# Syntax Coloring Map For MAX6956 +####################################### + +####################################### +# Classes, datatypes, and C++ keywords (KEYWORD1) +####################################### + +MAX6956 KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +reset KEYWORD2 +getConfigReg KEYWORD2 +setConfigReg KEYWORD2 +getPower KEYWORD2 +togglePower KEYWORD2 +setPower KEYWORD2 +getEnableIndividualCurrent KEYWORD2 +setEnableIndividualCurrent KEYWORD2 +getEnableTransitionDetection KEYWORD2 +setEnableTransitionDetection KEYWORD2 +getGlobalCurrent KEYWORD2 +setGlobalCurrent KEYWORD2 +getTestMode KEYWORD2 +setTestMode KEYWORD2 +getInputMask KEYWORD2 +setInputMask KEYWORD2 +configPort KEYWORD2 +configPorts KEYWORD2 +configAllPorts KEYWORD2 +setPortLevel KEYWORD2 +setPortCurrent KEYWORD2 +setAllPortsCurrent KEYWORD2 +enableAllPorts KEYWORD2 +disableAllPorts KEYWORD2 + + +####################################### +# InstancesKEYWORD3 setup and loop functions, +# as well as the Serial keywords (KEYWORD3) +####################################### + +####################################### +# Constants (LITERAL1) +####################################### + + +MAX6956_OUTPUT_LED LITERAL1 +MAX6956_OUTPUT_GPIO LITERAL1 +MAX6956_INPUT_WO_PULL LITERAL1 +MAX6956_INPUT_W_PULL LITERAL1 + +MAX6956_OFF LITERAL1 +MAX6956_CURRENT_1 LITERAL1 +MAX6956_CURRENT_2 LITERAL1 +MAX6956_CURRENT_3 LITERAL1 +MAX6956_CURRENT_4 LITERAL1 +MAX6956_CURRENT_5 LITERAL1 +MAX6956_CURRENT_6 LITERAL1 +MAX6956_CURRENT_7 LITERAL1 +MAX6956_CURRENT_8 LITERAL1 +MAX6956_CURRENT_9 LITERAL1 +MAX6956_CURRENT_10 LITERAL1 +MAX6956_CURRENT_11 LITERAL1 +MAX6956_CURRENT_12 LITERAL1 +MAX6956_CURRENT_13 LITERAL1 +MAX6956_CURRENT_14 LITERAL1 +MAX6956_CURRENT_15 LITERAL1 diff --git a/Arduino/MAX6956/latex/MAX6956_8cpp.tex b/Arduino/MAX6956/latex/MAX6956_8cpp.tex new file mode 100644 index 00000000..97fe62e6 --- /dev/null +++ b/Arduino/MAX6956/latex/MAX6956_8cpp.tex @@ -0,0 +1,4 @@ +\hypertarget{MAX6956_8cpp}{\section{M\-A\-X6956.\-cpp File Reference} +\label{MAX6956_8cpp}\index{M\-A\-X6956.\-cpp@{M\-A\-X6956.\-cpp}} +} +{\ttfamily \#include \char`\"{}M\-A\-X6956.\-h\char`\"{}}\\* diff --git a/Arduino/MAX6956/latex/MAX6956_8h.tex b/Arduino/MAX6956/latex/MAX6956_8h.tex new file mode 100644 index 00000000..2826e34d --- /dev/null +++ b/Arduino/MAX6956/latex/MAX6956_8h.tex @@ -0,0 +1,1937 @@ +\hypertarget{MAX6956_8h}{\section{M\-A\-X6956.\-h File Reference} +\label{MAX6956_8h}\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}} +} +{\ttfamily \#include \char`\"{}I2\-Cdev.\-h\char`\"{}}\\* +\subsection*{Data Structures} +\begin{DoxyCompactItemize} +\item +class \hyperlink{classMAX6956}{M\-A\-X6956} +\end{DoxyCompactItemize} +\subsection*{Macros} +\begin{DoxyCompactItemize} +\item +\#define \hyperlink{MAX6956_8h_a33e60623a4c5b483d4604fe2c9b91be7}{M\-A\-X6956\-\_\-\-A\-D\-D\-R\-E\-S\-S}~0x40 +\item +\#define \hyperlink{MAX6956_8h_a4ca90873afdfdacaa730ed5db53e2f5b}{M\-A\-X6956\-\_\-\-D\-E\-F\-A\-U\-L\-T\-\_\-\-A\-D\-D\-R\-E\-S\-S}~0x40 +\item +\#define \hyperlink{MAX6956_8h_a0f205428de0679650e54dbe8250d57b4}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-N\-O\-\_\-\-O\-P}~0x00 +\begin{DoxyCompactList}\small\item\em No-\/op. \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_a6a6c2bfe9bfbe4930731829baae7c8f6}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T}~0x02 +\item +\#define \hyperlink{MAX6956_8h_a5c3d1c00491596887e211bfa630c1b94}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-U\-R\-A\-T\-I\-O\-N}~0x04 +\item +\#define \hyperlink{MAX6956_8h_a4a2b4c395e47e0ec9ef49d3236b8a465}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-D\-E\-T\-E\-C\-T}~0x06 +\item +\#define \hyperlink{MAX6956_8h_a709a5193fd2aa9274997dfc22ef73a19}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-D\-I\-S\-P\-L\-A\-Y\-\_\-\-T\-E\-S\-T}~0x07 +\item +\#define \hyperlink{MAX6956_8h_a1c4db4957c22f8767b2f1a06e5cb9a32}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P7\-P6\-P5\-P4}~0x09 +\item +\#define \hyperlink{MAX6956_8h_a3a2fa6f7cc985cfeea00ebd1dd64ae8c}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P11\-P10\-P9\-P8}~0x0\-A +\item +\#define \hyperlink{MAX6956_8h_a119a0a92d4ccdb0e8f27fd565b1220bd}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P15\-P14\-P13\-P12}~0x0\-B +\item +\#define \hyperlink{MAX6956_8h_a8f199d21b14cf933d5093d3001d0400d}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P19\-P18\-P17\-P16}~0x0\-C +\item +\#define \hyperlink{MAX6956_8h_a025ce0245fb957ef58afc5f4920e19f3}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P23\-P22\-P21\-P20}~0x0\-D +\item +\#define \hyperlink{MAX6956_8h_a4e813aab18cbd7462e1ac5a59b0a53ab}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P27\-P26\-P25\-P24}~0x0\-E +\item +\#define \hyperlink{MAX6956_8h_a98b5c2d8359fbb7e07eb2eade7e8870a}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P31\-P30\-P29\-P28}~0x0\-F +\item +\#define \hyperlink{MAX6956_8h_adebbf4c1afdeb688bf5d3887b80c75b2}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P5\-P4}~0x12 +\item +\#define \hyperlink{MAX6956_8h_a42db4570a3f848d62f3f906a920161b6}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P7\-P6}~0x13 +\item +\#define \hyperlink{MAX6956_8h_a51eb40018dff593fa84c319832a1a957}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P9\-P8}~0x14 +\item +\#define \hyperlink{MAX6956_8h_aa2304dec8420451a881876948e1cba43}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P11\-P10}~0x15 +\item +\#define \hyperlink{MAX6956_8h_add5533d08bfa791cf8cf95d7dd3f16d3}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P13\-P12}~0x16 +\item +\#define \hyperlink{MAX6956_8h_ae51b720b2bd4868c1986e2d314822778}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P15\-P14}~0x17 +\item +\#define \hyperlink{MAX6956_8h_a77820b1e4acee07a338e179ab35a7836}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P17\-P16}~0x18 +\item +\#define \hyperlink{MAX6956_8h_aa84fef4207af57fddf6468ae84ebd829}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P19\-P18}~0x19 +\item +\#define \hyperlink{MAX6956_8h_a11974f06951fb9051f9dd1d154d7c530}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P21\-P20}~0x1\-A +\item +\#define \hyperlink{MAX6956_8h_aa971a2bb392832476e3b91970f7fffe7}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P23\-P22}~0x1\-B +\item +\#define \hyperlink{MAX6956_8h_a040daea6fe73e819adcbcaed7cd3ceaf}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P25\-P24}~0x1\-C +\item +\#define \hyperlink{MAX6956_8h_ac5e5f779975977348022381487c2dfa2}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P27\-P26}~0x1\-D +\item +\#define \hyperlink{MAX6956_8h_a32623717f92442a1acfd42cdd3253302}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P29\-P28}~0x1\-E +\item +\#define \hyperlink{MAX6956_8h_a64f61d29f7ede042a397c21f33cf6124}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P31\-P30}~0x1\-F +\item +\#define \hyperlink{MAX6956_8h_a7e8973b61716ae09a84b95ea2f2f5914}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T0}~0x20 +\begin{DoxyCompactList}\small\item\em (virtual port, no action) \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_a1e4fdb2886a119328bdd6807f3720eea}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T1}~0x21 +\begin{DoxyCompactList}\small\item\em (virtual port, no action) \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_ac4cc75132151b2f662b7c54128391187}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T2}~0x22 +\begin{DoxyCompactList}\small\item\em (virtual port, no action) \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_aa3e011deb16e7054e78e6f71ac33fcba}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T3}~0x23 +\begin{DoxyCompactList}\small\item\em (virtual port, no action) \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_a68339cee27681486c99dabf398f487a0}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T4}~0x24 +\item +\#define \hyperlink{MAX6956_8h_a92c4653a42f8400a30aa13a60dbc056f}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T5}~0x25 +\item +\#define \hyperlink{MAX6956_8h_a5af96fba8e40466303a2bcec16df6c6f}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T6}~0x26 +\item +\#define \hyperlink{MAX6956_8h_a20de98d6d2102960000a70b4bcf6007c}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T7}~0x27 +\item +\#define \hyperlink{MAX6956_8h_ad0ea7dd1027b558df290150b664b0222}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T8}~0x28 +\item +\#define \hyperlink{MAX6956_8h_a7d31adbda8965d0d7df0c521571e135c}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T9}~0x29 +\item +\#define \hyperlink{MAX6956_8h_a2528a76a2e91cd1dfd11b8aefda01473}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T10}~0x2\-A +\item +\#define \hyperlink{MAX6956_8h_a3a6abf1d9e71015255d821419e3ffa5a}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T11}~0x2\-B +\item +\#define \hyperlink{MAX6956_8h_a3c089b77cbd25ffa27e3cd46af415a9c}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T12}~0x2\-C +\item +\#define \hyperlink{MAX6956_8h_a2d6ee01536f1fb0ec843479948141cbc}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T13}~0x2\-D +\item +\#define \hyperlink{MAX6956_8h_aba5e5ff9b4aea95fedff9f6421c5f47c}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T14}~0x2\-E +\item +\#define \hyperlink{MAX6956_8h_ad366a7c1b65fb3496f5b9ba392d6ba9c}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T15}~0x2\-F +\item +\#define \hyperlink{MAX6956_8h_ac483e6007b4e6a780c14c7a78ff7a134}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T16}~0x30 +\item +\#define \hyperlink{MAX6956_8h_ab6f3b8bbd8ac56bacf4a57691eb41aaf}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T17}~0x31 +\item +\#define \hyperlink{MAX6956_8h_a082486ab9eace7838acd56b6ac6301df}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T18}~0x32 +\item +\#define \hyperlink{MAX6956_8h_a04e65b34862a48ae022c994bbc5968dd}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T19}~0x33 +\item +\#define \hyperlink{MAX6956_8h_aed99f35f5ba961711c4e5bed769aa369}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T20}~0x34 +\item +\#define \hyperlink{MAX6956_8h_a361dcd71b3da6c5fb57d33951c9e4c54}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T21}~0x35 +\item +\#define \hyperlink{MAX6956_8h_a67c57767c9f6eda6124ff7368df4293b}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T22}~0x36 +\item +\#define \hyperlink{MAX6956_8h_a29699b356f81b9fc971a29fc04e68a59}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T23}~0x37 +\item +\#define \hyperlink{MAX6956_8h_ad053ff9eac065beaa10ad52dcc3d1e3e}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T24}~0x38 +\item +\#define \hyperlink{MAX6956_8h_a367103a7d8364b916a70f37d0880e334}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T25}~0x39 +\item +\#define \hyperlink{MAX6956_8h_ae0c19d326ab47406a138d4b66c601de0}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T26}~0x3\-A +\item +\#define \hyperlink{MAX6956_8h_ae1219ad62d3ea1b3a86c52736d347618}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T27}~0x3\-B +\item +\#define \hyperlink{MAX6956_8h_a07ff69092b95f43595762554c3e35329}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T28}~0x3\-C +\item +\#define \hyperlink{MAX6956_8h_a6be82fa185d6c3dd272200727c15f4ac}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T29}~0x3\-D +\item +\#define \hyperlink{MAX6956_8h_a34c02dca8e8a97488eb0be51f682cf73}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T30}~0x3\-E +\item +\#define \hyperlink{MAX6956_8h_a891d2a47a2fe5a4da056a7732fb6098b}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T31}~0x3\-F +\item +\#define \hyperlink{MAX6956_8h_a00bff40ca66a7c82b7093536c5047da4}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-7}~0x40 +\begin{DoxyCompactList}\small\item\em data bits D0-\/\-D3; D4-\/\-D7 read as 0 \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_a3d1cd4727f1748e42a0426c0b70d9c2c}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-8}~0x41 +\begin{DoxyCompactList}\small\item\em data bits D0-\/\-D4; D5-\/\-D7 read as 0 \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_ad1b71a2b24de60a4d0128576c0e1278b}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-9}~0x42 +\begin{DoxyCompactList}\small\item\em data bits D0-\/\-D5; D6-\/\-D7 read as 0 \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_ac32650edffdebee3cfeb90c9daece88b}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-10}~0x43 +\begin{DoxyCompactList}\small\item\em data bits D0-\/\-D6; D7 reads as 0 \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_a4b0cc79ee765d2f477953a890b2f6209}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-11}~0x44 +\item +\#define \hyperlink{MAX6956_8h_a13b8eb94b73c20a02397e50c81bccb57}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S5\-\_\-12}~0x45 +\item +\#define \hyperlink{MAX6956_8h_af01fef127c33b806d570f1d46a90362f}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S6\-\_\-13}~0x46 +\item +\#define \hyperlink{MAX6956_8h_ae0f37de2a929dc6f37733c3f112e0fa7}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S7\-\_\-14}~0x47 +\item +\#define \hyperlink{MAX6956_8h_ae2bd6458f4aa0271d7fb9c8c8fdd0e4f}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S8\-\_\-15}~0x48 +\item +\#define \hyperlink{MAX6956_8h_aedb8b7ecadabaf8290ac1eacde7db918}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S9\-\_\-16}~0x49 +\item +\#define \hyperlink{MAX6956_8h_aa9837d30cb5f9c9badf20fe50ea3ba26}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S10\-\_\-17}~0x4\-A +\item +\#define \hyperlink{MAX6956_8h_a40bf1528e6a7345e0aaa3b86869f3af3}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S11\-\_\-18}~0x4\-B +\item +\#define \hyperlink{MAX6956_8h_ab3e1f8d0b913acae6d73f9b5b0d491ff}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S12\-\_\-19}~0x4\-C +\item +\#define \hyperlink{MAX6956_8h_ad33d71fa8457fcdb444179768a6376e9}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S13\-\_\-20}~0x4\-D +\item +\#define \hyperlink{MAX6956_8h_aeae655678f9a39b8a7f6e9de1a09c59e}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S14\-\_\-21}~0x4\-E +\item +\#define \hyperlink{MAX6956_8h_a853b18f366e225131135f6576268a461}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S15\-\_\-22}~0x4\-F +\item +\#define \hyperlink{MAX6956_8h_a39c1bb286953031fad9c101604d6f56e}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S16\-\_\-23}~0x50 +\item +\#define \hyperlink{MAX6956_8h_a8a4536b80e588a3ed6bb2f487499efeb}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S17\-\_\-24}~0x51 +\item +\#define \hyperlink{MAX6956_8h_a1ae324a27c0648b831978991a44ee33f}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S18\-\_\-25}~0x52 +\item +\#define \hyperlink{MAX6956_8h_a981a54414024fdd2877704d4d242b748}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S19\-\_\-26}~0x53 +\item +\#define \hyperlink{MAX6956_8h_abd2280465476a9e3cae302d5e9bf7b62}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S20\-\_\-27}~0x54 +\item +\#define \hyperlink{MAX6956_8h_adfca6218829cec2697e0975fc7965008}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S21\-\_\-28}~0x55 +\item +\#define \hyperlink{MAX6956_8h_aa190f6504c585b64f355ce45a24057f1}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S22\-\_\-29}~0x56 +\item +\#define \hyperlink{MAX6956_8h_a9ae64dcdc091a17982f4888bcd7b1981}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S23\-\_\-30}~0x57 +\item +\#define \hyperlink{MAX6956_8h_a5054da2b077f91e7f6106373a84476ed}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S24\-\_\-31}~0x58 +\item +\#define \hyperlink{MAX6956_8h_a38a7fe545ab1b4ca108dabcef50d015f}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S25\-\_\-31}~0x59 +\begin{DoxyCompactList}\small\item\em data bits D0-\/\-D6; D7 reads as 0 \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_ac804c8074d5a6baf79b0595415ae0679}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S26\-\_\-31}~0x5\-A +\begin{DoxyCompactList}\small\item\em data bits D0-\/\-D5; D6-\/\-D7 read as 0 \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_a5307d28ebcae5028fc482c914eecf48f}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S27\-\_\-31}~0x5\-B +\begin{DoxyCompactList}\small\item\em data bits D0-\/\-D4; D5-\/\-D7 read as 0 \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_a7554adf2b4214f33584001f4e7c81053}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S28\-\_\-31}~0x5\-C +\begin{DoxyCompactList}\small\item\em data bits D0-\/\-D3; D4-\/\-D7 read as 0 \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_ab278f8cb075460b9318c029bca24e68a}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S29\-\_\-31}~0x5\-D +\begin{DoxyCompactList}\small\item\em data bits D0-\/\-D2; D3-\/\-D7 read as 0 \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_ae5873266ac57220286709a468781c3ff}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S30\-\_\-31}~0x5\-E +\begin{DoxyCompactList}\small\item\em data bits D0-\/\-D1; D2-\/\-D7 read as 0 \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_ad12b528f7fa63249d37126a8d4049aab}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S31\-\_\-31}~0x5\-F +\begin{DoxyCompactList}\small\item\em data bit D0; D1-\/\-D7 read as 0. Port 31 only. \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_a03faf0490eddbb2f0405616ad6ac4052}{M\-A\-X6956\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P\-O\-W\-E\-R\-\_\-\-B\-I\-T}~0 +\begin{DoxyCompactList}\small\item\em 0 = Shutdown, 1 = Normal operation \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_a4288d838d55461c66c0ba2e904f588a7}{M\-A\-X6956\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}~6 +\begin{DoxyCompactList}\small\item\em 0 = Global control, 1 = Individual control \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_af1d61c00ae2e56dd5e7f04dc4b0c1663}{M\-A\-X6956\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-B\-I\-T}~7 +\begin{DoxyCompactList}\small\item\em 0 = Disabled, 1 = Enabled \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_a85368204ba368978f814d46d81335c35}{M\-A\-X6956\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}~0 +\begin{DoxyCompactList}\small\item\em Global current start bit. \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_afbcb8bf5ecc4e5afada48446f8dac809}{M\-A\-X6956\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}~4 +\begin{DoxyCompactList}\small\item\em nybble long \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_ae1cb8088b95a2e19f293dbeee7ef7892}{M\-A\-X6956\-\_\-\-P\-O\-R\-T12\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}~3 +\begin{DoxyCompactList}\small\item\em L\-S\-Nybble. \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_a8b0c452aa9a3f66de931d4a226f865e6}{M\-A\-X6956\-\_\-\-P\-O\-R\-T12\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}~4 +\begin{DoxyCompactList}\small\item\em nybble long \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_a0c413303648e14359c311fb9478cfce7}{M\-A\-X6956\-\_\-\-P\-O\-R\-T13\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}~7 +\begin{DoxyCompactList}\small\item\em M\-S\-Nybble. \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_abaee1f6920a6a6770468cb7def42bff7}{M\-A\-X6956\-\_\-\-P\-O\-R\-T13\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}~4 +\begin{DoxyCompactList}\small\item\em nybble long \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_a0fcb35fa292905862765e99dd03e63b2}{M\-A\-X6956\-\_\-\-P\-O\-R\-T14\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}~3 +\begin{DoxyCompactList}\small\item\em L\-S\-Nybble. \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_aa98b4176c22631122a00948e5a54e91f}{M\-A\-X6956\-\_\-\-P\-O\-R\-T14\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}~4 +\begin{DoxyCompactList}\small\item\em nybble long \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_a659a1777dac35a14930720029b786aed}{M\-A\-X6956\-\_\-\-P\-O\-R\-T15\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}~7 +\begin{DoxyCompactList}\small\item\em M\-S\-Nybble. \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_ab377c2d0463246bfc66c9df01087285d}{M\-A\-X6956\-\_\-\-P\-O\-R\-T15\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}~4 +\begin{DoxyCompactList}\small\item\em nybble long \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_a977fb8ce0e696e764ae098dce361e446}{M\-A\-X6956\-\_\-\-P\-O\-R\-T16\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}~3 +\begin{DoxyCompactList}\small\item\em L\-S\-Nybble. \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_a04c2dcf166214a43fbdd9ae5f7a0ca00}{M\-A\-X6956\-\_\-\-P\-O\-R\-T16\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}~4 +\begin{DoxyCompactList}\small\item\em nybble long \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_ab59b7f618ff0788a6bd21313bf14673f}{M\-A\-X6956\-\_\-\-P\-O\-R\-T17\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}~7 +\begin{DoxyCompactList}\small\item\em M\-S\-Nybble. \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_adf0428deb9192d621f837d7951e539be}{M\-A\-X6956\-\_\-\-P\-O\-R\-T17\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}~4 +\begin{DoxyCompactList}\small\item\em nybble long \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_ab0d4c28bc6747482ab33a027fd93b5d7}{M\-A\-X6956\-\_\-\-P\-O\-R\-T18\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}~3 +\begin{DoxyCompactList}\small\item\em L\-S\-Nybble. \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_a9bb781fca7fadebb28918c05d2f1605c}{M\-A\-X6956\-\_\-\-P\-O\-R\-T18\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}~4 +\begin{DoxyCompactList}\small\item\em nybble long \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_aea0128f7b979e68785b78cfc7e480a32}{M\-A\-X6956\-\_\-\-P\-O\-R\-T19\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}~7 +\begin{DoxyCompactList}\small\item\em M\-S\-Nybble. \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_a5c2f25a82e8b442abb28a9544a3d4088}{M\-A\-X6956\-\_\-\-P\-O\-R\-T19\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}~4 +\begin{DoxyCompactList}\small\item\em nybble long \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_a95789ffe1e677c75090556342763c6ac}{M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}~3 +\begin{DoxyCompactList}\small\item\em L\-S\-Nybble. \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_a0f492bea7bf9e0906ba13f447327d5a8}{M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}~4 +\begin{DoxyCompactList}\small\item\em nybble long \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_abd855e00543729cc87ab4a48e3d98649}{M\-A\-X6956\-\_\-\-P\-O\-R\-T21\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}~7 +\begin{DoxyCompactList}\small\item\em M\-S\-Nybble. \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_a65cd02d7f498266b224c035a3809126a}{M\-A\-X6956\-\_\-\-P\-O\-R\-T21\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}~4 +\begin{DoxyCompactList}\small\item\em nybble long \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_a061947a1484a8449fd4301a1022cafe5}{M\-A\-X6956\-\_\-\-P\-O\-R\-T22\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}~3 +\begin{DoxyCompactList}\small\item\em L\-S\-Nybble. \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_aa64238ebb3bf6d8ee2d0d368992e7613}{M\-A\-X6956\-\_\-\-P\-O\-R\-T22\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}~4 +\begin{DoxyCompactList}\small\item\em nybble long \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_a95789ffe1e677c75090556342763c6ac}{M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}~7 +\begin{DoxyCompactList}\small\item\em L\-S\-Nybble. \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_a0f492bea7bf9e0906ba13f447327d5a8}{M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}~4 +\begin{DoxyCompactList}\small\item\em nybble long \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_a50e41ea8c3ec1bb3d55e5a4eb03563a2}{M\-A\-X6956\-\_\-\-P\-O\-R\-T24\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}~3 +\begin{DoxyCompactList}\small\item\em L\-S\-Nybble. \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_a11ee583606d04516bc2fc5812b05cd3d}{M\-A\-X6956\-\_\-\-P\-O\-R\-T24\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}~4 +\begin{DoxyCompactList}\small\item\em nybble long \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_a75f6b93cf7558a38adba5bb4a91d05f8}{M\-A\-X6956\-\_\-\-P\-O\-R\-T25\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}~7 +\begin{DoxyCompactList}\small\item\em M\-S\-Nybble. \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_a3b1a7a5f82da6b43bd5a24d2297a2f75}{M\-A\-X6956\-\_\-\-P\-O\-R\-T25\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}~4 +\begin{DoxyCompactList}\small\item\em nybble long \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_abd400d2f356832d21b1787e2501a8644}{M\-A\-X6956\-\_\-\-P\-O\-R\-T26\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}~3 +\begin{DoxyCompactList}\small\item\em L\-S\-Nybble. \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_a28bf5ca7da83928eeec3f4f302d12c45}{M\-A\-X6956\-\_\-\-P\-O\-R\-T26\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}~4 +\begin{DoxyCompactList}\small\item\em nybble long \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_a62bf02cd8e4d8a9dfa975d0e319f68f5}{M\-A\-X6956\-\_\-\-P\-O\-R\-T27\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}~7 +\begin{DoxyCompactList}\small\item\em M\-S\-Nybble. \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_a0a0f99c166b5a60d7e6c6c7d99306b45}{M\-A\-X6956\-\_\-\-P\-O\-R\-T27\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}~4 +\begin{DoxyCompactList}\small\item\em nybble long \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_ab6135c4105c3b39625e7361a438e1511}{M\-A\-X6956\-\_\-\-P\-O\-R\-T28\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}~3 +\begin{DoxyCompactList}\small\item\em L\-S\-Nybble. \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_ac2bcdc199d348dba281a4371675bd428}{M\-A\-X6956\-\_\-\-P\-O\-R\-T28\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}~4 +\begin{DoxyCompactList}\small\item\em nybble long \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_ae98448e4aa991d16d9b1d9d6071078d8}{M\-A\-X6956\-\_\-\-P\-O\-R\-T29\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}~7 +\begin{DoxyCompactList}\small\item\em M\-S\-Nybble. \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_a6b0d8a1c63777d016e1cb22076b91377}{M\-A\-X6956\-\_\-\-P\-O\-R\-T29\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}~4 +\begin{DoxyCompactList}\small\item\em nybble long \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_aa5acefc0723ea8d2b804aa7eccae705b}{M\-A\-X6956\-\_\-\-P\-O\-R\-T33\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}~3 +\begin{DoxyCompactList}\small\item\em L\-S\-Nybble. \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_a2fb02a7e77abefcbf7c194ff6b994ae9}{M\-A\-X6956\-\_\-\-P\-O\-R\-T33\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}~4 +\begin{DoxyCompactList}\small\item\em nybble long \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_a1cdbea93ca621e5fc4c747286bdf90e1}{M\-A\-X6956\-\_\-\-P\-O\-R\-T31\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}~7 +\begin{DoxyCompactList}\small\item\em M\-S\-Nybble. \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_a40a075605dfcfc2736aab5ffa10e3e2c}{M\-A\-X6956\-\_\-\-P\-O\-R\-T31\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}~4 +\begin{DoxyCompactList}\small\item\em nybble long \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_a7e110f7b5949bf63dd7c5b4e9a59a5b0}{M\-A\-X6956\-\_\-\-D\-I\-S\-P\-L\-A\-Y\-\_\-\-T\-E\-S\-T\-\_\-\-B\-I\-T}~0 +\begin{DoxyCompactList}\small\item\em 0 = Normal operation, 1 = Display test \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_a29bd01905e66b503151e6d9cdfb035a1}{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-S\-T\-A\-T\-U\-S\-\_\-\-B\-I\-T}~7 +\begin{DoxyCompactList}\small\item\em I\-N\-T Status, I\-N\-T is automatically cleared after it is read. \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_abc801853bdfe66591265d04865aba78f}{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-B\-I\-T}~0 +\begin{DoxyCompactList}\small\item\em Ports 24-\/30. \end{DoxyCompactList}\item +\#define \hyperlink{MAX6956_8h_a332868e8a1596e785072ddb8c4a2b4c1}{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-L\-E\-N\-G\-T\-H}~7 +\item +\#define \hyperlink{MAX6956_8h_a0e7f62a1c7d77019ca8ca2c2511f2644}{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T30\-\_\-\-B\-I\-T}~6 +\item +\#define \hyperlink{MAX6956_8h_a74adf7234472da3287cb98af583750c9}{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T29\-\_\-\-B\-I\-T}~5 +\item +\#define \hyperlink{MAX6956_8h_a927e5369f33337fdea8d89ccc3b3919d}{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T28\-\_\-\-B\-I\-T}~4 +\item +\#define \hyperlink{MAX6956_8h_a282091cda715bb27f96266f5ae22b492}{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T27\-\_\-\-B\-I\-T}~3 +\item +\#define \hyperlink{MAX6956_8h_ac4f63f4afc199c41dd9b1445259b8d50}{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T26\-\_\-\-B\-I\-T}~2 +\item +\#define \hyperlink{MAX6956_8h_a04d331f867fa51822f5910ce2b6b891c}{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T25\-\_\-\-B\-I\-T}~1 +\item +\#define \hyperlink{MAX6956_8h_a0a2eb488b9b8d16b5c076d25790ec28e}{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T24\-\_\-\-B\-I\-T}~0 +\item +\#define \hyperlink{MAX6956_8h_ad6490a909085059c4300a51dcebbf7bc}{M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-L\-E\-D}~0x00 +\item +\#define \hyperlink{MAX6956_8h_a27f6ca524d4c18623762c722d9993c10}{M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-G\-P\-I\-O}~0x01 +\item +\#define \hyperlink{MAX6956_8h_ab05f3186e2515bab3a536ad9f1cbb7db}{M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-O\-\_\-\-P\-U\-L\-L}~0x02 +\item +\#define \hyperlink{MAX6956_8h_a68fc1bc750b7959fbab7e64f79589b83}{M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-\_\-\-P\-U\-L\-L}~0x03 +\item +\#define \hyperlink{MAX6956_8h_a003fe60fa8da81e67da2ad7900d1196f}{M\-A\-X6956\-\_\-\-O\-F\-F}~0x00 +\item +\#define \hyperlink{MAX6956_8h_a4e151161e190a9f45aebfd712064b034}{M\-A\-X6956\-\_\-\-O\-N}~0x01 +\item +\#define \hyperlink{MAX6956_8h_a930221b73d0e7327ffce1e3072ed69e3}{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0}~0x00 +\item +\#define \hyperlink{MAX6956_8h_afd6a3c0f560b7b7190805416e1ad00f5}{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-1}~0x01 +\item +\#define \hyperlink{MAX6956_8h_ab7558038e4f723efa4b406e988a93990}{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-2}~0x02 +\item +\#define \hyperlink{MAX6956_8h_a8b8800a153cf4869a6c4d399f8d46035}{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-3}~0x03 +\item +\#define \hyperlink{MAX6956_8h_a2678f20d0e18e036e13ff5f422fcf609}{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-4}~0x04 +\item +\#define \hyperlink{MAX6956_8h_af808e1e791b9a640d6b6c62cb145f169}{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-5}~0x05 +\item +\#define \hyperlink{MAX6956_8h_a0c97726477caef4c0f54eb1beaffbdff}{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-6}~0x06 +\item +\#define \hyperlink{MAX6956_8h_a55c66763c65c8554d12a71a4c20e35a6}{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-7}~0x07 +\item +\#define \hyperlink{MAX6956_8h_a11c425ee14938c667e63e7df4cf8afa2}{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-8}~0x08 +\item +\#define \hyperlink{MAX6956_8h_a4da9aedd07982408005da31fda78463a}{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-9}~0x09 +\item +\#define \hyperlink{MAX6956_8h_a62f09fbe807ce97d3558748808ed3a11}{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-10}~0x0\-A +\item +\#define \hyperlink{MAX6956_8h_a5b97f8927dd861189567ad1fda6d692a}{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-11}~0x0\-B +\item +\#define \hyperlink{MAX6956_8h_a8fb88850c74ecc2080971984c817b860}{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-12}~0x0\-C +\item +\#define \hyperlink{MAX6956_8h_a8bfeeb7d88d4284dec7174b65724877d}{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-13}~0x0\-D +\item +\#define \hyperlink{MAX6956_8h_aad136273ced9dea0ef4a8821f4a5f368}{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-14}~0x0\-E +\item +\#define \hyperlink{MAX6956_8h_a4c0ac1cc939ecfb7992dac2834521eb6}{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-15}~0x0\-F +\end{DoxyCompactItemize} + + +\subsection{Macro Definition Documentation} +\hypertarget{MAX6956_8h_a33e60623a4c5b483d4604fe2c9b91be7}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-A\-D\-D\-R\-E\-S\-S@{M\-A\-X6956\-\_\-\-A\-D\-D\-R\-E\-S\-S}} +\index{M\-A\-X6956\-\_\-\-A\-D\-D\-R\-E\-S\-S@{M\-A\-X6956\-\_\-\-A\-D\-D\-R\-E\-S\-S}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-A\-D\-D\-R\-E\-S\-S}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-A\-D\-D\-R\-E\-S\-S~0x40}}\label{MAX6956_8h_a33e60623a4c5b483d4604fe2c9b91be7} +\subsection*{Table 3. I2\-C Address Map } + +Pin$|$\-Pin$|$\-D\-E\-V\-I\-C\-E A\-D\-D\-R\-E\-S\-S $|$ \-:-\/\-:$|$\-:-\/\-:$|$\-:-\/\-:$|$\-:-\/\-:$|$\-:-\/\-:$|$\-:-\/\-:$|$\-:-\/\-:$|$\-:-\/\-:$|$\-:-\/\-:$|$\-:-\/\-:$|$\-:--\-: A\-D1$|$\-A\-D0$|$\-A7 $|$\-A6 $|$\-A5 $|$\-A4 $|$\-A3 $|$\-A2 $|$\-A1 $|$\-A0 $|$\-H\-E\-X G\-N\-D$|$\-G\-N\-D$|$1 $|$0 $|$0 $|$0 $|$0 $|$0 $|$0 $|$\-R\-W $|$0x40 G\-N\-D$|$\-V+ $|$1 $|$0 $|$0 $|$0 $|$0 $|$0 $|$1 $|$\-R\-W $|$0x41 G\-N\-D$|$\-S\-D\-A$|$1 $|$0 $|$0 $|$0 $|$0 $|$1 $|$0 $|$\-R\-W $|$0x42 G\-N\-D$|$\-S\-C\-L$|$1 $|$0 $|$0 $|$0 $|$0 $|$1 $|$1 $|$\-R\-W $|$0x43 V+ $|$\-G\-N\-D$|$1 $|$0 $|$0 $|$0 $|$1 $|$0 $|$0 $|$\-R\-W $|$0x44 V+ $|$\-V+ $|$1 $|$0 $|$0 $|$0 $|$1 $|$0 $|$1 $|$\-R\-W $|$0x45 V+ $|$\-S\-D\-A$|$1 $|$0 $|$0 $|$0 $|$1 $|$1 $|$0 $|$\-R\-W $|$0x46 V+ $|$\-S\-C\-L$|$1 $|$0 $|$0 $|$0 $|$1 $|$1 $|$1 $|$\-R\-W $|$0x47 S\-D\-A$|$\-G\-N\-D$|$1 $|$0 $|$0 $|$1 $|$0 $|$0 $|$0 $|$\-R\-W $|$0x48 S\-D\-A$|$\-V+ $|$1 $|$0 $|$0 $|$1 $|$0 $|$0 $|$1 $|$\-R\-W $|$0x49 S\-D\-A$|$\-S\-D\-A$|$1 $|$0 $|$0 $|$1 $|$0 $|$1 $|$0 $|$\-R\-W $|$0x50 S\-D\-A$|$\-S\-C\-L$|$1 $|$0 $|$0 $|$1 $|$0 $|$1 $|$1 $|$\-R\-W $|$0x51 S\-C\-L$|$\-G\-N\-D$|$1 $|$0 $|$0 $|$1 $|$1 $|$0 $|$0 $|$\-R\-W $|$0x52 S\-C\-L$|$\-V+ $|$1 $|$0 $|$0 $|$1 $|$1 $|$0 $|$1 $|$\-R\-W $|$0x53 S\-C\-L$|$\-S\-D\-A$|$1 $|$0 $|$0 $|$1 $|$1 $|$1 $|$0 $|$\-R\-W $|$0x54 S\-C\-L$|$\-S\-C\-L$|$1 $|$0 $|$0 $|$1 $|$1 $|$1 $|$1 $|$\-R\-W $|$0x55 + +R\-W bit 0 = Write 1 = Read + +Definition at line 71 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a4288d838d55461c66c0ba2e904f588a7}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}} +\index{M\-A\-X6956\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T~6}}\label{MAX6956_8h_a4288d838d55461c66c0ba2e904f588a7} + + +0 = Global control, 1 = Individual control + + + +Definition at line 344 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a03faf0490eddbb2f0405616ad6ac4052}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P\-O\-W\-E\-R\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P\-O\-W\-E\-R\-\_\-\-B\-I\-T}} +\index{M\-A\-X6956\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P\-O\-W\-E\-R\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P\-O\-W\-E\-R\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P\-O\-W\-E\-R\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P\-O\-W\-E\-R\-\_\-\-B\-I\-T~0}}\label{MAX6956_8h_a03faf0490eddbb2f0405616ad6ac4052} + + +0 = Shutdown, 1 = Normal operation + + + +Definition at line 343 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_af1d61c00ae2e56dd5e7f04dc4b0c1663}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-B\-I\-T}} +\index{M\-A\-X6956\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-B\-I\-T~7}}\label{MAX6956_8h_af1d61c00ae2e56dd5e7f04dc4b0c1663} + + +0 = Disabled, 1 = Enabled + + + +Definition at line 345 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a930221b73d0e7327ffce1e3072ed69e3}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0}} +\index{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0~0x00}}\label{MAX6956_8h_a930221b73d0e7327ffce1e3072ed69e3} + + +Definition at line 414 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_afd6a3c0f560b7b7190805416e1ad00f5}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-1@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-1}} +\index{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-1@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-1}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-1}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-1~0x01}}\label{MAX6956_8h_afd6a3c0f560b7b7190805416e1ad00f5} + + +Definition at line 415 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a62f09fbe807ce97d3558748808ed3a11}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-10@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-10}} +\index{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-10@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-10}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-10}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-10~0x0\-A}}\label{MAX6956_8h_a62f09fbe807ce97d3558748808ed3a11} + + +Definition at line 424 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a5b97f8927dd861189567ad1fda6d692a}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-11@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-11}} +\index{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-11@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-11}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-11}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-11~0x0\-B}}\label{MAX6956_8h_a5b97f8927dd861189567ad1fda6d692a} + + +Definition at line 425 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a8fb88850c74ecc2080971984c817b860}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-12@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-12}} +\index{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-12@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-12}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-12}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-12~0x0\-C}}\label{MAX6956_8h_a8fb88850c74ecc2080971984c817b860} + + +Definition at line 426 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a8bfeeb7d88d4284dec7174b65724877d}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-13@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-13}} +\index{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-13@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-13}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-13}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-13~0x0\-D}}\label{MAX6956_8h_a8bfeeb7d88d4284dec7174b65724877d} + + +Definition at line 427 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_aad136273ced9dea0ef4a8821f4a5f368}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-14@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-14}} +\index{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-14@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-14}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-14}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-14~0x0\-E}}\label{MAX6956_8h_aad136273ced9dea0ef4a8821f4a5f368} + + +Definition at line 428 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a4c0ac1cc939ecfb7992dac2834521eb6}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-15@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-15}} +\index{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-15@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-15}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-15}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-15~0x0\-F}}\label{MAX6956_8h_a4c0ac1cc939ecfb7992dac2834521eb6} + + +Definition at line 429 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_ab7558038e4f723efa4b406e988a93990}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-2@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-2}} +\index{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-2@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-2}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-2}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-2~0x02}}\label{MAX6956_8h_ab7558038e4f723efa4b406e988a93990} + + +Definition at line 416 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a8b8800a153cf4869a6c4d399f8d46035}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-3@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-3}} +\index{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-3@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-3}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-3}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-3~0x03}}\label{MAX6956_8h_a8b8800a153cf4869a6c4d399f8d46035} + + +Definition at line 417 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a2678f20d0e18e036e13ff5f422fcf609}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-4@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-4}} +\index{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-4@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-4}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-4}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-4~0x04}}\label{MAX6956_8h_a2678f20d0e18e036e13ff5f422fcf609} + + +Definition at line 418 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_af808e1e791b9a640d6b6c62cb145f169}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-5@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-5}} +\index{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-5@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-5}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-5}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-5~0x05}}\label{MAX6956_8h_af808e1e791b9a640d6b6c62cb145f169} + + +Definition at line 419 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a0c97726477caef4c0f54eb1beaffbdff}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-6@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-6}} +\index{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-6@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-6}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-6}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-6~0x06}}\label{MAX6956_8h_a0c97726477caef4c0f54eb1beaffbdff} + + +Definition at line 420 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a55c66763c65c8554d12a71a4c20e35a6}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-7@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-7}} +\index{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-7@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-7}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-7}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-7~0x07}}\label{MAX6956_8h_a55c66763c65c8554d12a71a4c20e35a6} + + +Definition at line 421 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a11c425ee14938c667e63e7df4cf8afa2}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-8@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-8}} +\index{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-8@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-8}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-8}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-8~0x08}}\label{MAX6956_8h_a11c425ee14938c667e63e7df4cf8afa2} + + +Definition at line 422 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a4da9aedd07982408005da31fda78463a}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-9@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-9}} +\index{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-9@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-9}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-9}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-9~0x09}}\label{MAX6956_8h_a4da9aedd07982408005da31fda78463a} + + +Definition at line 423 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a4ca90873afdfdacaa730ed5db53e2f5b}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-D\-E\-F\-A\-U\-L\-T\-\_\-\-A\-D\-D\-R\-E\-S\-S@{M\-A\-X6956\-\_\-\-D\-E\-F\-A\-U\-L\-T\-\_\-\-A\-D\-D\-R\-E\-S\-S}} +\index{M\-A\-X6956\-\_\-\-D\-E\-F\-A\-U\-L\-T\-\_\-\-A\-D\-D\-R\-E\-S\-S@{M\-A\-X6956\-\_\-\-D\-E\-F\-A\-U\-L\-T\-\_\-\-A\-D\-D\-R\-E\-S\-S}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-D\-E\-F\-A\-U\-L\-T\-\_\-\-A\-D\-D\-R\-E\-S\-S}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-D\-E\-F\-A\-U\-L\-T\-\_\-\-A\-D\-D\-R\-E\-S\-S~0x40}}\label{MAX6956_8h_a4ca90873afdfdacaa730ed5db53e2f5b} + + +Definition at line 72 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a7e110f7b5949bf63dd7c5b4e9a59a5b0}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-D\-I\-S\-P\-L\-A\-Y\-\_\-\-T\-E\-S\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-D\-I\-S\-P\-L\-A\-Y\-\_\-\-T\-E\-S\-T\-\_\-\-B\-I\-T}} +\index{M\-A\-X6956\-\_\-\-D\-I\-S\-P\-L\-A\-Y\-\_\-\-T\-E\-S\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-D\-I\-S\-P\-L\-A\-Y\-\_\-\-T\-E\-S\-T\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-D\-I\-S\-P\-L\-A\-Y\-\_\-\-T\-E\-S\-T\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-D\-I\-S\-P\-L\-A\-Y\-\_\-\-T\-E\-S\-T\-\_\-\-B\-I\-T~0}}\label{MAX6956_8h_a7e110f7b5949bf63dd7c5b4e9a59a5b0} + + +0 = Normal operation, 1 = Display test + + + +Definition at line 391 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a85368204ba368978f814d46d81335c35}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}} +\index{M\-A\-X6956\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T~0}}\label{MAX6956_8h_a85368204ba368978f814d46d81335c35} + + +Global current start bit. + + + +Definition at line 347 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_afbcb8bf5ecc4e5afada48446f8dac809}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}} +\index{M\-A\-X6956\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H~4}}\label{MAX6956_8h_afbcb8bf5ecc4e5afada48446f8dac809} + + +nybble long + + + +Definition at line 348 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a68fc1bc750b7959fbab7e64f79589b83}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-\_\-\-P\-U\-L\-L@{M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-\_\-\-P\-U\-L\-L}} +\index{M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-\_\-\-P\-U\-L\-L@{M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-\_\-\-P\-U\-L\-L}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-\_\-\-P\-U\-L\-L}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-\_\-\-P\-U\-L\-L~0x03}}\label{MAX6956_8h_a68fc1bc750b7959fbab7e64f79589b83} + + +Definition at line 409 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_ab05f3186e2515bab3a536ad9f1cbb7db}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-O\-\_\-\-P\-U\-L\-L@{M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-O\-\_\-\-P\-U\-L\-L}} +\index{M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-O\-\_\-\-P\-U\-L\-L@{M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-O\-\_\-\-P\-U\-L\-L}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-O\-\_\-\-P\-U\-L\-L}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-O\-\_\-\-P\-U\-L\-L~0x02}}\label{MAX6956_8h_ab05f3186e2515bab3a536ad9f1cbb7db} + + +Definition at line 408 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a003fe60fa8da81e67da2ad7900d1196f}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-O\-F\-F@{M\-A\-X6956\-\_\-\-O\-F\-F}} +\index{M\-A\-X6956\-\_\-\-O\-F\-F@{M\-A\-X6956\-\_\-\-O\-F\-F}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-O\-F\-F}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-O\-F\-F~0x00}}\label{MAX6956_8h_a003fe60fa8da81e67da2ad7900d1196f} + + +Definition at line 411 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a4e151161e190a9f45aebfd712064b034}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-O\-N@{M\-A\-X6956\-\_\-\-O\-N}} +\index{M\-A\-X6956\-\_\-\-O\-N@{M\-A\-X6956\-\_\-\-O\-N}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-O\-N}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-O\-N~0x01}}\label{MAX6956_8h_a4e151161e190a9f45aebfd712064b034} + + +Definition at line 412 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a27f6ca524d4c18623762c722d9993c10}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-G\-P\-I\-O@{M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-G\-P\-I\-O}} +\index{M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-G\-P\-I\-O@{M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-G\-P\-I\-O}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-G\-P\-I\-O}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-G\-P\-I\-O~0x01}}\label{MAX6956_8h_a27f6ca524d4c18623762c722d9993c10} + + +Definition at line 407 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_ad6490a909085059c4300a51dcebbf7bc}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-L\-E\-D@{M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-L\-E\-D}} +\index{M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-L\-E\-D@{M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-L\-E\-D}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-L\-E\-D}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-L\-E\-D~0x00}}\label{MAX6956_8h_ad6490a909085059c4300a51dcebbf7bc} + + +Definition at line 406 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_ae1cb8088b95a2e19f293dbeee7ef7892}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T12\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T12\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}} +\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T12\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T12\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T12\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T12\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T~3}}\label{MAX6956_8h_ae1cb8088b95a2e19f293dbeee7ef7892} + + +L\-S\-Nybble. + + + +Definition at line 350 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a8b0c452aa9a3f66de931d4a226f865e6}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T12\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T12\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}} +\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T12\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T12\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T12\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T12\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H~4}}\label{MAX6956_8h_a8b0c452aa9a3f66de931d4a226f865e6} + + +nybble long + + + +Definition at line 351 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a0c413303648e14359c311fb9478cfce7}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T13\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T13\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}} +\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T13\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T13\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T13\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T13\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T~7}}\label{MAX6956_8h_a0c413303648e14359c311fb9478cfce7} + + +M\-S\-Nybble. + + + +Definition at line 352 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_abaee1f6920a6a6770468cb7def42bff7}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T13\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T13\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}} +\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T13\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T13\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T13\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T13\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H~4}}\label{MAX6956_8h_abaee1f6920a6a6770468cb7def42bff7} + + +nybble long + + + +Definition at line 353 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a0fcb35fa292905862765e99dd03e63b2}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T14\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T14\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}} +\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T14\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T14\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T14\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T14\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T~3}}\label{MAX6956_8h_a0fcb35fa292905862765e99dd03e63b2} + + +L\-S\-Nybble. + + + +Definition at line 354 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_aa98b4176c22631122a00948e5a54e91f}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T14\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T14\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}} +\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T14\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T14\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T14\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T14\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H~4}}\label{MAX6956_8h_aa98b4176c22631122a00948e5a54e91f} + + +nybble long + + + +Definition at line 355 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a659a1777dac35a14930720029b786aed}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T15\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T15\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}} +\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T15\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T15\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T15\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T15\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T~7}}\label{MAX6956_8h_a659a1777dac35a14930720029b786aed} + + +M\-S\-Nybble. + + + +Definition at line 356 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_ab377c2d0463246bfc66c9df01087285d}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T15\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T15\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}} +\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T15\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T15\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T15\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T15\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H~4}}\label{MAX6956_8h_ab377c2d0463246bfc66c9df01087285d} + + +nybble long + + + +Definition at line 357 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a977fb8ce0e696e764ae098dce361e446}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T16\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T16\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}} +\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T16\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T16\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T16\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T16\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T~3}}\label{MAX6956_8h_a977fb8ce0e696e764ae098dce361e446} + + +L\-S\-Nybble. + + + +Definition at line 358 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a04c2dcf166214a43fbdd9ae5f7a0ca00}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T16\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T16\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}} +\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T16\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T16\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T16\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T16\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H~4}}\label{MAX6956_8h_a04c2dcf166214a43fbdd9ae5f7a0ca00} + + +nybble long + + + +Definition at line 359 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_ab59b7f618ff0788a6bd21313bf14673f}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T17\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T17\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}} +\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T17\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T17\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T17\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T17\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T~7}}\label{MAX6956_8h_ab59b7f618ff0788a6bd21313bf14673f} + + +M\-S\-Nybble. + + + +Definition at line 360 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_adf0428deb9192d621f837d7951e539be}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T17\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T17\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}} +\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T17\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T17\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T17\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T17\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H~4}}\label{MAX6956_8h_adf0428deb9192d621f837d7951e539be} + + +nybble long + + + +Definition at line 361 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_ab0d4c28bc6747482ab33a027fd93b5d7}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T18\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T18\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}} +\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T18\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T18\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T18\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T18\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T~3}}\label{MAX6956_8h_ab0d4c28bc6747482ab33a027fd93b5d7} + + +L\-S\-Nybble. + + + +Definition at line 362 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a9bb781fca7fadebb28918c05d2f1605c}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T18\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T18\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}} +\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T18\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T18\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T18\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T18\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H~4}}\label{MAX6956_8h_a9bb781fca7fadebb28918c05d2f1605c} + + +nybble long + + + +Definition at line 363 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_aea0128f7b979e68785b78cfc7e480a32}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T19\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T19\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}} +\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T19\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T19\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T19\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T19\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T~7}}\label{MAX6956_8h_aea0128f7b979e68785b78cfc7e480a32} + + +M\-S\-Nybble. + + + +Definition at line 364 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a5c2f25a82e8b442abb28a9544a3d4088}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T19\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T19\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}} +\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T19\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T19\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T19\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T19\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H~4}}\label{MAX6956_8h_a5c2f25a82e8b442abb28a9544a3d4088} + + +nybble long + + + +Definition at line 365 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_abd855e00543729cc87ab4a48e3d98649}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T21\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T21\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}} +\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T21\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T21\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T21\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T21\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T~7}}\label{MAX6956_8h_abd855e00543729cc87ab4a48e3d98649} + + +M\-S\-Nybble. + + + +Definition at line 368 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a65cd02d7f498266b224c035a3809126a}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T21\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T21\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}} +\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T21\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T21\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T21\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T21\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H~4}}\label{MAX6956_8h_a65cd02d7f498266b224c035a3809126a} + + +nybble long + + + +Definition at line 369 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a061947a1484a8449fd4301a1022cafe5}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T22\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T22\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}} +\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T22\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T22\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T22\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T22\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T~3}}\label{MAX6956_8h_a061947a1484a8449fd4301a1022cafe5} + + +L\-S\-Nybble. + + + +Definition at line 370 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_aa64238ebb3bf6d8ee2d0d368992e7613}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T22\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T22\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}} +\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T22\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T22\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T22\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T22\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H~4}}\label{MAX6956_8h_aa64238ebb3bf6d8ee2d0d368992e7613} + + +nybble long + + + +Definition at line 371 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a95789ffe1e677c75090556342763c6ac}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}} +\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T~3}}\label{MAX6956_8h_a95789ffe1e677c75090556342763c6ac} + + +L\-S\-Nybble. + +M\-S\-Nybble. + +Definition at line 372 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a95789ffe1e677c75090556342763c6ac}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}} +\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T~7}}\label{MAX6956_8h_a95789ffe1e677c75090556342763c6ac} + + +L\-S\-Nybble. + +M\-S\-Nybble. + +Definition at line 372 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a0f492bea7bf9e0906ba13f447327d5a8}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}} +\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H~4}}\label{MAX6956_8h_a0f492bea7bf9e0906ba13f447327d5a8} + + +nybble long + + + +Definition at line 373 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a0f492bea7bf9e0906ba13f447327d5a8}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}} +\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H~4}}\label{MAX6956_8h_a0f492bea7bf9e0906ba13f447327d5a8} + + +nybble long + + + +Definition at line 373 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a50e41ea8c3ec1bb3d55e5a4eb03563a2}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T24\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T24\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}} +\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T24\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T24\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T24\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T24\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T~3}}\label{MAX6956_8h_a50e41ea8c3ec1bb3d55e5a4eb03563a2} + + +L\-S\-Nybble. + + + +Definition at line 374 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a11ee583606d04516bc2fc5812b05cd3d}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T24\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T24\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}} +\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T24\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T24\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T24\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T24\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H~4}}\label{MAX6956_8h_a11ee583606d04516bc2fc5812b05cd3d} + + +nybble long + + + +Definition at line 375 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a75f6b93cf7558a38adba5bb4a91d05f8}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T25\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T25\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}} +\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T25\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T25\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T25\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T25\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T~7}}\label{MAX6956_8h_a75f6b93cf7558a38adba5bb4a91d05f8} + + +M\-S\-Nybble. + + + +Definition at line 376 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a3b1a7a5f82da6b43bd5a24d2297a2f75}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T25\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T25\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}} +\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T25\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T25\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T25\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T25\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H~4}}\label{MAX6956_8h_a3b1a7a5f82da6b43bd5a24d2297a2f75} + + +nybble long + + + +Definition at line 377 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_abd400d2f356832d21b1787e2501a8644}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T26\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T26\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}} +\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T26\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T26\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T26\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T26\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T~3}}\label{MAX6956_8h_abd400d2f356832d21b1787e2501a8644} + + +L\-S\-Nybble. + + + +Definition at line 378 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a28bf5ca7da83928eeec3f4f302d12c45}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T26\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T26\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}} +\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T26\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T26\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T26\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T26\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H~4}}\label{MAX6956_8h_a28bf5ca7da83928eeec3f4f302d12c45} + + +nybble long + + + +Definition at line 379 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a62bf02cd8e4d8a9dfa975d0e319f68f5}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T27\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T27\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}} +\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T27\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T27\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T27\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T27\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T~7}}\label{MAX6956_8h_a62bf02cd8e4d8a9dfa975d0e319f68f5} + + +M\-S\-Nybble. + + + +Definition at line 380 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a0a0f99c166b5a60d7e6c6c7d99306b45}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T27\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T27\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}} +\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T27\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T27\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T27\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T27\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H~4}}\label{MAX6956_8h_a0a0f99c166b5a60d7e6c6c7d99306b45} + + +nybble long + + + +Definition at line 381 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_ab6135c4105c3b39625e7361a438e1511}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T28\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T28\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}} +\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T28\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T28\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T28\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T28\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T~3}}\label{MAX6956_8h_ab6135c4105c3b39625e7361a438e1511} + + +L\-S\-Nybble. + + + +Definition at line 382 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_ac2bcdc199d348dba281a4371675bd428}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T28\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T28\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}} +\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T28\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T28\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T28\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T28\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H~4}}\label{MAX6956_8h_ac2bcdc199d348dba281a4371675bd428} + + +nybble long + + + +Definition at line 383 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_ae98448e4aa991d16d9b1d9d6071078d8}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T29\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T29\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}} +\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T29\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T29\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T29\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T29\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T~7}}\label{MAX6956_8h_ae98448e4aa991d16d9b1d9d6071078d8} + + +M\-S\-Nybble. + + + +Definition at line 384 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a6b0d8a1c63777d016e1cb22076b91377}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T29\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T29\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}} +\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T29\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T29\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T29\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T29\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H~4}}\label{MAX6956_8h_a6b0d8a1c63777d016e1cb22076b91377} + + +nybble long + + + +Definition at line 385 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a1cdbea93ca621e5fc4c747286bdf90e1}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T31\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T31\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}} +\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T31\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T31\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T31\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T31\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T~7}}\label{MAX6956_8h_a1cdbea93ca621e5fc4c747286bdf90e1} + + +M\-S\-Nybble. + + + +Definition at line 388 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a40a075605dfcfc2736aab5ffa10e3e2c}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T31\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T31\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}} +\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T31\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T31\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T31\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T31\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H~4}}\label{MAX6956_8h_a40a075605dfcfc2736aab5ffa10e3e2c} + + +nybble long + + + +Definition at line 389 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_aa5acefc0723ea8d2b804aa7eccae705b}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T33\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T33\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}} +\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T33\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T33\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T33\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T33\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T~3}}\label{MAX6956_8h_aa5acefc0723ea8d2b804aa7eccae705b} + + +L\-S\-Nybble. + + + +Definition at line 386 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a2fb02a7e77abefcbf7c194ff6b994ae9}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T33\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T33\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}} +\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T33\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T33\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T33\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T33\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H~4}}\label{MAX6956_8h_a2fb02a7e77abefcbf7c194ff6b994ae9} + + +nybble long + + + +Definition at line 387 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a3a2fa6f7cc985cfeea00ebd1dd64ae8c}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P11\-P10\-P9\-P8@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P11\-P10\-P9\-P8}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P11\-P10\-P9\-P8@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P11\-P10\-P9\-P8}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P11\-P10\-P9\-P8}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P11\-P10\-P9\-P8~0x0\-A}}\label{MAX6956_8h_a3a2fa6f7cc985cfeea00ebd1dd64ae8c} + + +Definition at line 204 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a119a0a92d4ccdb0e8f27fd565b1220bd}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P15\-P14\-P13\-P12@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P15\-P14\-P13\-P12}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P15\-P14\-P13\-P12@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P15\-P14\-P13\-P12}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P15\-P14\-P13\-P12}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P15\-P14\-P13\-P12~0x0\-B}}\label{MAX6956_8h_a119a0a92d4ccdb0e8f27fd565b1220bd} + + +Definition at line 205 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a8f199d21b14cf933d5093d3001d0400d}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P19\-P18\-P17\-P16@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P19\-P18\-P17\-P16}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P19\-P18\-P17\-P16@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P19\-P18\-P17\-P16}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P19\-P18\-P17\-P16}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P19\-P18\-P17\-P16~0x0\-C}}\label{MAX6956_8h_a8f199d21b14cf933d5093d3001d0400d} + + +Definition at line 206 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a025ce0245fb957ef58afc5f4920e19f3}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P23\-P22\-P21\-P20@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P23\-P22\-P21\-P20}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P23\-P22\-P21\-P20@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P23\-P22\-P21\-P20}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P23\-P22\-P21\-P20}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P23\-P22\-P21\-P20~0x0\-D}}\label{MAX6956_8h_a025ce0245fb957ef58afc5f4920e19f3} + + +Definition at line 207 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a4e813aab18cbd7462e1ac5a59b0a53ab}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P27\-P26\-P25\-P24@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P27\-P26\-P25\-P24}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P27\-P26\-P25\-P24@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P27\-P26\-P25\-P24}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P27\-P26\-P25\-P24}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P27\-P26\-P25\-P24~0x0\-E}}\label{MAX6956_8h_a4e813aab18cbd7462e1ac5a59b0a53ab} + + +Definition at line 208 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a98b5c2d8359fbb7e07eb2eade7e8870a}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P31\-P30\-P29\-P28@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P31\-P30\-P29\-P28}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P31\-P30\-P29\-P28@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P31\-P30\-P29\-P28}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P31\-P30\-P29\-P28}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P31\-P30\-P29\-P28~0x0\-F}}\label{MAX6956_8h_a98b5c2d8359fbb7e07eb2eade7e8870a} + + +Definition at line 209 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a1c4db4957c22f8767b2f1a06e5cb9a32}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P7\-P6\-P5\-P4@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P7\-P6\-P5\-P4}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P7\-P6\-P5\-P4@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P7\-P6\-P5\-P4}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P7\-P6\-P5\-P4}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P7\-P6\-P5\-P4~0x09}}\label{MAX6956_8h_a1c4db4957c22f8767b2f1a06e5cb9a32} +\subsection*{Table 1. Port Configuration Map } + +\begin{TabularC}{6} +\hline +\rowcolor{lightgray}{\bf R\-E\-G\-I\-S\-T\-E\-R }&{\bf A\-D\-D\-R\-E\-S\-S}&{\bf D7 D6}&{\bf D5 D4}&{\bf D3 D2}&{\bf D1 D0 }\\\cline{1-6} +Port Configuration for P7, P6, P5, P4 &0x09 &P7 &P6 &P5 &P4 \\\cline{1-6} +Port Configuration for P11, P10, P9, P8 &0x0\-A &P11 &P10 &P9 &P8 \\\cline{1-6} +Port Configuration for P15, P14, P13, P12&0x0\-B &P15 &P14 &P13 &P12 \\\cline{1-6} +Port Configuration for P19, P18, P17, P16&0x0\-C &P19 &P18 &P17 &P16 \\\cline{1-6} +Port Configuration for P23, P22, P21, P20&0x0\-D &P23 &P22 &P21 &P20 \\\cline{1-6} +Port Configuration for P27, P26, P25, P24&0x0\-E &P27 &P26 &P25 &P24 \\\cline{1-6} +Port Configuration for P31, P30, P29, P28&0x0\-F &P31 &P30 &P29 &P28 \\\cline{1-6} +\end{TabularC} +\subsection*{Table 2. P4-\/\-P31 configuration bit pairs } + + +\begin{DoxyPre} + 00 - Output, LED Segment Driver + Controlled using port registers 0x20-0x5F. + 0 = High impedance + 1 = Open-drain current sink, with sink current (up to 24mA) + determined by the appropriate current register + 01 - Output, GPIO Output + Controlled using port registers 0x20-0x5F. + 0 = Active-low logic output + 1 = Active-high logic output + 10 - Input, GPIO Input Without Pullup + Read port registers 0x20-0x5F. + Schmitt logic input + 11 - Input, GPIO Input with Pullup + Read port registers 0x20-0x5F. + Schmitt logic input with pullup +\end{DoxyPre} + + +Definition at line 203 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a5c3d1c00491596887e211bfa630c1b94}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-U\-R\-A\-T\-I\-O\-N@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-U\-R\-A\-T\-I\-O\-N}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-U\-R\-A\-T\-I\-O\-N@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-U\-R\-A\-T\-I\-O\-N}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-U\-R\-A\-T\-I\-O\-N}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-U\-R\-A\-T\-I\-O\-N~0x04}}\label{MAX6956_8h_a5c3d1c00491596887e211bfa630c1b94} +\subsection*{Table 7. Configuration Register Format } + +\begin{TabularC}{9} +\hline +\rowcolor{lightgray}\PBS\centering {\bf A\-D\-D\-R\-E\-S\-S }&\PBS\centering {\bf D7 }&\PBS\centering {\bf D6 }&\PBS\centering {\bf D5 }&\PBS\centering {\bf D4 }&\PBS\centering {\bf D3 }&\PBS\centering {\bf D2 }&\PBS\centering {\bf D1 }&\PBS\centering {\bf D0 }\\\cline{1-9} +\PBS\centering 0x04 &\PBS\centering M &\PBS\centering I &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering S \\\cline{1-9} +\end{TabularC} +\subsection*{Table 8. Shutdown Control (S Data Bit D0) Format } + +\begin{TabularC}{10} +\hline +\rowcolor{lightgray}\PBS\centering {\bf F\-U\-N\-C\-T\-I\-O\-N }&\PBS\centering {\bf A\-D\-D\-R\-E\-S\-S}&\PBS\centering {\bf D7 }&\PBS\centering {\bf D6 }&\PBS\centering {\bf D5 }&\PBS\centering {\bf D4 }&\PBS\centering {\bf D3 }&\PBS\centering {\bf D2 }&\PBS\centering {\bf D1 }&\PBS\centering {\bf D0 }\\\cline{1-10} +\PBS\centering Shutdown &\PBS\centering 0x04 &\PBS\centering M &\PBS\centering I &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering 0 \\\cline{1-10} +\PBS\centering Normal Operation&\PBS\centering 0x04 &\PBS\centering M &\PBS\centering I &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering 1 \\\cline{1-10} +\end{TabularC} +\subsection*{Table 9. Global Current Control (I Data Bit D6) Format } + +\begin{TabularC}{10} +\hline +\rowcolor{lightgray}\PBS\centering {\bf F\-U\-N\-C\-T\-I\-O\-N }&\PBS\centering {\bf A\-D\-D\-R\-E\-S\-S}&\PBS\centering {\bf D7 }&\PBS\centering {\bf D6 }&\PBS\centering {\bf D5 }&\PBS\centering {\bf D4 }&\PBS\centering {\bf D3 }&\PBS\centering {\bf D2 }&\PBS\centering {\bf D1 }&\PBS\centering {\bf D0 }\\\cline{1-10} +\PBS\centering Global &\PBS\centering 0x04 &\PBS\centering M &\PBS\centering 0 &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering S \\\cline{1-10} +\PBS\centering Individual Segment&\PBS\centering 0x04 &\PBS\centering M &\PBS\centering 1 &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering S \\\cline{1-10} +\end{TabularC} +\subsection*{Table 10. Transition Detection Control (M-\/\-Data Bit D7) Format } + +\begin{TabularC}{10} +\hline +\rowcolor{lightgray}\PBS\centering {\bf F\-U\-N\-C\-T\-I\-O\-N }&\PBS\centering {\bf A\-D\-D\-R\-E\-S\-S}&\PBS\centering {\bf D7 }&\PBS\centering {\bf D6 }&\PBS\centering {\bf D5 }&\PBS\centering {\bf D4 }&\PBS\centering {\bf D3 }&\PBS\centering {\bf D2 }&\PBS\centering {\bf D1 }&\PBS\centering {\bf D0 }\\\cline{1-10} +\PBS\centering Disabled &\PBS\centering 0x04 &\PBS\centering 0 &\PBS\centering I &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering S \\\cline{1-10} +\PBS\centering Enabled &\PBS\centering 0x04 &\PBS\centering 1 &\PBS\centering I &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering S \\\cline{1-10} +\end{TabularC} + + +Definition at line 137 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_aa2304dec8420451a881876948e1cba43}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P11\-P10@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P11\-P10}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P11\-P10@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P11\-P10}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P11\-P10}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P11\-P10~0x15}}\label{MAX6956_8h_aa2304dec8420451a881876948e1cba43} + + +Definition at line 244 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_add5533d08bfa791cf8cf95d7dd3f16d3}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P13\-P12@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P13\-P12}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P13\-P12@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P13\-P12}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P13\-P12}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P13\-P12~0x16}}\label{MAX6956_8h_add5533d08bfa791cf8cf95d7dd3f16d3} + + +Definition at line 245 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_ae51b720b2bd4868c1986e2d314822778}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P15\-P14@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P15\-P14}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P15\-P14@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P15\-P14}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P15\-P14}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P15\-P14~0x17}}\label{MAX6956_8h_ae51b720b2bd4868c1986e2d314822778} + + +Definition at line 246 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a77820b1e4acee07a338e179ab35a7836}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P17\-P16@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P17\-P16}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P17\-P16@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P17\-P16}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P17\-P16}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P17\-P16~0x18}}\label{MAX6956_8h_a77820b1e4acee07a338e179ab35a7836} + + +Definition at line 247 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_aa84fef4207af57fddf6468ae84ebd829}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P19\-P18@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P19\-P18}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P19\-P18@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P19\-P18}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P19\-P18}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P19\-P18~0x19}}\label{MAX6956_8h_aa84fef4207af57fddf6468ae84ebd829} + + +Definition at line 248 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a11974f06951fb9051f9dd1d154d7c530}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P21\-P20@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P21\-P20}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P21\-P20@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P21\-P20}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P21\-P20}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P21\-P20~0x1\-A}}\label{MAX6956_8h_a11974f06951fb9051f9dd1d154d7c530} + + +Definition at line 249 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_aa971a2bb392832476e3b91970f7fffe7}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P23\-P22@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P23\-P22}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P23\-P22@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P23\-P22}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P23\-P22}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P23\-P22~0x1\-B}}\label{MAX6956_8h_aa971a2bb392832476e3b91970f7fffe7} + + +Definition at line 250 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a040daea6fe73e819adcbcaed7cd3ceaf}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P25\-P24@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P25\-P24}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P25\-P24@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P25\-P24}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P25\-P24}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P25\-P24~0x1\-C}}\label{MAX6956_8h_a040daea6fe73e819adcbcaed7cd3ceaf} + + +Definition at line 251 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_ac5e5f779975977348022381487c2dfa2}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P27\-P26@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P27\-P26}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P27\-P26@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P27\-P26}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P27\-P26}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P27\-P26~0x1\-D}}\label{MAX6956_8h_ac5e5f779975977348022381487c2dfa2} + + +Definition at line 252 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a32623717f92442a1acfd42cdd3253302}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P29\-P28@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P29\-P28}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P29\-P28@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P29\-P28}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P29\-P28}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P29\-P28~0x1\-E}}\label{MAX6956_8h_a32623717f92442a1acfd42cdd3253302} + + +Definition at line 253 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a64f61d29f7ede042a397c21f33cf6124}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P31\-P30@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P31\-P30}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P31\-P30@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P31\-P30}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P31\-P30}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P31\-P30~0x1\-F}}\label{MAX6956_8h_a64f61d29f7ede042a397c21f33cf6124} + + +Definition at line 254 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_adebbf4c1afdeb688bf5d3887b80c75b2}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P5\-P4@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P5\-P4}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P5\-P4@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P5\-P4}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P5\-P4}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P5\-P4~0x12}}\label{MAX6956_8h_adebbf4c1afdeb688bf5d3887b80c75b2} +Constant-\/current limit for each digit is individually controlled by the settings in the Current054 through Current1\-F\-E registers + +\subsection*{Table 12. Individual Port Current Registers } + +\begin{DoxyVerb} | ADDRESS | | +\end{DoxyVerb} + \begin{TabularC}{4} +\hline +\rowcolor{lightgray}{\bf F\-U\-N\-C\-T\-I\-O\-N }&{\bf C\-O\-D\-E(\-H\-E\-X)}&{\bf D7 D6 D5 D4 }&{\bf D3 D2 D1 D0 }\\\cline{1-4} +Current054 register &0x12 &Segment 5 &Segment 4 \\\cline{1-4} +Current076 register &0x13 &Segment 7 &Segment 6 \\\cline{1-4} +Current098 register &0x14 &Segment 9 &Segment 8 \\\cline{1-4} +Current0\-B\-A register &0x15 &Segment 11 &Segment 10 \\\cline{1-4} +Current0\-D\-C register &0x16 &Segment 13 &Segment 12 \\\cline{1-4} +Current0\-F\-E register &0x17 &Segment 15 &Segment 14 \\\cline{1-4} +Current110 register &0x18 &Segment 17 &Segment 16 \\\cline{1-4} +Current132 register &0x19 &Segment 19 &Segment 18 \\\cline{1-4} +Current154 register &0x1\-A &Segment 21 &Segment 20 \\\cline{1-4} +Current176 register &0x1\-B &Segment 23 &Segment 22 \\\cline{1-4} +Current198 register &0x1\-C &Segment 25 &Segment 24 \\\cline{1-4} +Current1\-B\-A register &0x1\-D &Segment 27 &Segment 26 \\\cline{1-4} +Current1\-D\-C register &0x1\-E &Segment 29 &Segment 28 \\\cline{1-4} +Current1\-F\-E register &0x1\-F &Segment 31 &Segment 30 \\\cline{1-4} +\end{TabularC} +Register data is 0-\/\-Fx0-\/\-F for 1-\/16(0-\/\-F) brightness levels. To completely blank an output turn it off (0) using port configuration registers. + +Definition at line 241 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a42db4570a3f848d62f3f906a920161b6}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P7\-P6@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P7\-P6}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P7\-P6@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P7\-P6}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P7\-P6}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P7\-P6~0x13}}\label{MAX6956_8h_a42db4570a3f848d62f3f906a920161b6} + + +Definition at line 242 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a51eb40018dff593fa84c319832a1a957}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P9\-P8@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P9\-P8}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P9\-P8@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P9\-P8}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P9\-P8}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P9\-P8~0x14}}\label{MAX6956_8h_a51eb40018dff593fa84c319832a1a957} + + +Definition at line 243 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a709a5193fd2aa9274997dfc22ef73a19}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-D\-I\-S\-P\-L\-A\-Y\-\_\-\-T\-E\-S\-T@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-D\-I\-S\-P\-L\-A\-Y\-\_\-\-T\-E\-S\-T}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-D\-I\-S\-P\-L\-A\-Y\-\_\-\-T\-E\-S\-T@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-D\-I\-S\-P\-L\-A\-Y\-\_\-\-T\-E\-S\-T}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-D\-I\-S\-P\-L\-A\-Y\-\_\-\-T\-E\-S\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-D\-I\-S\-P\-L\-A\-Y\-\_\-\-T\-E\-S\-T~0x07}}\label{MAX6956_8h_a709a5193fd2aa9274997dfc22ef73a19} +\subsection*{Table 16. Display Test Register } + +\begin{DoxyVerb} |ADDR | +\end{DoxyVerb} + \begin{TabularC}{10} +\hline +\rowcolor{lightgray}\PBS\centering {\bf M\-O\-D\-E }&\PBS\centering {\bf C\-O\-D\-E }&\PBS\centering {\bf D7 }&\PBS\centering {\bf D6 }&\PBS\centering {\bf D5 }&\PBS\centering {\bf D4 }&\PBS\centering {\bf D3 }&\PBS\centering {\bf D2 }&\PBS\centering {\bf D1 }&\PBS\centering {\bf D0 }\\\cline{1-10} +\PBS\centering Normal Operation &\PBS\centering 0x07 &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering 0 \\\cline{1-10} +\PBS\centering Display Test Mode&\PBS\centering 0x07 &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering 1 \\\cline{1-10} +\end{TabularC} + + +Definition at line 165 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a6a6c2bfe9bfbe4930731829baae7c8f6}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T~0x02}}\label{MAX6956_8h_a6a6c2bfe9bfbe4930731829baae7c8f6} +\subsection*{Table 11. Global Segment Current Register Format } + +L\-E\-D D\-R\-I\-V\-E $|$\-T\-Y\-P\-I\-C\-A\-L S\-E\-G\-M\-E\-N\-T $|$ A\-D\-D\-R\-E\-S\-S $|$ \begin{TabularC}{12} +\hline +\rowcolor{lightgray}\PBS\centering {\bf F\-R\-A\-C\-T\-I\-O\-N }&\PBS\centering {\bf C\-U\-R\-R\-E\-N\-T(m\-A) }&\PBS\centering {\bf C\-O\-D\-E (H\-E\-X) }&\PBS\centering {\bf D7 }&\PBS\centering {\bf D6 }&\PBS\centering {\bf D5 }&\PBS\centering {\bf D4 }&\PBS\centering {\bf D3 }&\PBS\centering {\bf D2 }&\PBS\centering {\bf D1 }&\PBS\centering {\bf D0 }&\PBS\centering {\bf H\-E\-X C\-O\-D\-E }\\\cline{1-12} +\PBS\centering 1/16 &\PBS\centering 1.\-5 &\PBS\centering 0x02 &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering 0 &\PBS\centering 0 &\PBS\centering 0 &\PBS\centering 0 &\PBS\centering 0x\-X0 \\\cline{1-12} +\PBS\centering 2/16 &\PBS\centering 3 &\PBS\centering 0x02 &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering 0 &\PBS\centering 0 &\PBS\centering 0 &\PBS\centering 1 &\PBS\centering 0x\-X1 \\\cline{1-12} +\PBS\centering 3/16 &\PBS\centering 4.\-5 &\PBS\centering 0x02 &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering 0 &\PBS\centering 0 &\PBS\centering 1 &\PBS\centering 0 &\PBS\centering 0x\-X2 \\\cline{1-12} +\PBS\centering 4/16 &\PBS\centering 6 &\PBS\centering 0x02 &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering 0 &\PBS\centering 0 &\PBS\centering 1 &\PBS\centering 1 &\PBS\centering 0x\-X3 \\\cline{1-12} +\PBS\centering 5/16 &\PBS\centering 7.\-5 &\PBS\centering 0x02 &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering 0 &\PBS\centering 1 &\PBS\centering 0 &\PBS\centering 0 &\PBS\centering 0x\-X4 \\\cline{1-12} +\PBS\centering 6/16 &\PBS\centering 9 &\PBS\centering 0x02 &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering 0 &\PBS\centering 1 &\PBS\centering 0 &\PBS\centering 1 &\PBS\centering 0x\-X5 \\\cline{1-12} +\PBS\centering 7/16 &\PBS\centering 10.\-5 &\PBS\centering 0x02 &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering 0 &\PBS\centering 1 &\PBS\centering 1 &\PBS\centering 0 &\PBS\centering 0x\-X6 \\\cline{1-12} +\PBS\centering 8/16 &\PBS\centering 12 &\PBS\centering 0x02 &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering 0 &\PBS\centering 1 &\PBS\centering 1 &\PBS\centering 1 &\PBS\centering 0x\-X7 \\\cline{1-12} +\PBS\centering 9/16 &\PBS\centering 13.\-5 &\PBS\centering 0x02 &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering 1 &\PBS\centering 0 &\PBS\centering 0 &\PBS\centering 0 &\PBS\centering 0x\-X8 \\\cline{1-12} +\PBS\centering 10/16 &\PBS\centering 15 &\PBS\centering 0x02 &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering 1 &\PBS\centering 0 &\PBS\centering 0 &\PBS\centering 1 &\PBS\centering 0x\-X9 \\\cline{1-12} +\PBS\centering 11/16 &\PBS\centering 16.\-5 &\PBS\centering 0x02 &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering 1 &\PBS\centering 0 &\PBS\centering 1 &\PBS\centering 0 &\PBS\centering 0x\-X\-A \\\cline{1-12} +\PBS\centering 12/16 &\PBS\centering 18 &\PBS\centering 0x02 &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering 1 &\PBS\centering 0 &\PBS\centering 1 &\PBS\centering 1 &\PBS\centering 0x\-X\-B \\\cline{1-12} +\PBS\centering 13/16 &\PBS\centering 19.\-5 &\PBS\centering 0x02 &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering 1 &\PBS\centering 1 &\PBS\centering 0 &\PBS\centering 0 &\PBS\centering 0x\-X\-C \\\cline{1-12} +\PBS\centering 14/16 &\PBS\centering 21 &\PBS\centering 0x02 &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering 1 &\PBS\centering 1 &\PBS\centering 0 &\PBS\centering 1 &\PBS\centering 0x\-X\-D \\\cline{1-12} +\PBS\centering 15/16 &\PBS\centering 22.\-5 &\PBS\centering 0x02 &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering 1 &\PBS\centering 1 &\PBS\centering 1 &\PBS\centering 0 &\PBS\centering 0x\-X\-E \\\cline{1-12} +\PBS\centering 16/16 &\PBS\centering 24 &\PBS\centering 0x02 &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering 1 &\PBS\centering 1 &\PBS\centering 1 &\PBS\centering 1 &\PBS\centering 0x\-X\-F \\\cline{1-12} +\end{TabularC} + + +Definition at line 102 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a0f205428de0679650e54dbe8250d57b4}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-N\-O\-\_\-\-O\-P@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-N\-O\-\_\-\-O\-P}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-N\-O\-\_\-\-O\-P@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-N\-O\-\_\-\-O\-P}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-N\-O\-\_\-\-O\-P}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-N\-O\-\_\-\-O\-P~0x00}}\label{MAX6956_8h_a0f205428de0679650e54dbe8250d57b4} + + +No-\/op. + + + +Definition at line 76 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a7e8973b61716ae09a84b95ea2f2f5914}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T0@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T0}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T0@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T0}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T0}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T0~0x20}}\label{MAX6956_8h_a7e8973b61716ae09a84b95ea2f2f5914} + + +(virtual port, no action) + +\subsection*{Individiual Port Registers } + +\begin{DoxyVerb}data bit D0; D7-D1 read as 0\end{DoxyVerb} + + +Definition at line 262 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a1e4fdb2886a119328bdd6807f3720eea}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T1@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T1}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T1@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T1}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T1}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T1~0x21}}\label{MAX6956_8h_a1e4fdb2886a119328bdd6807f3720eea} + + +(virtual port, no action) + + + +Definition at line 263 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a2528a76a2e91cd1dfd11b8aefda01473}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T10@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T10}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T10@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T10}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T10}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T10~0x2\-A}}\label{MAX6956_8h_a2528a76a2e91cd1dfd11b8aefda01473} + + +Definition at line 273 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a3a6abf1d9e71015255d821419e3ffa5a}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T11@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T11}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T11@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T11}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T11}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T11~0x2\-B}}\label{MAX6956_8h_a3a6abf1d9e71015255d821419e3ffa5a} + + +Definition at line 274 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a3c089b77cbd25ffa27e3cd46af415a9c}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T12@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T12}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T12@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T12}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T12}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T12~0x2\-C}}\label{MAX6956_8h_a3c089b77cbd25ffa27e3cd46af415a9c} + + +Definition at line 276 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a2d6ee01536f1fb0ec843479948141cbc}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T13@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T13}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T13@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T13}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T13}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T13~0x2\-D}}\label{MAX6956_8h_a2d6ee01536f1fb0ec843479948141cbc} + + +Definition at line 277 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_aba5e5ff9b4aea95fedff9f6421c5f47c}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T14@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T14}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T14@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T14}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T14}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T14~0x2\-E}}\label{MAX6956_8h_aba5e5ff9b4aea95fedff9f6421c5f47c} + + +Definition at line 278 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_ad366a7c1b65fb3496f5b9ba392d6ba9c}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T15@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T15}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T15@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T15}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T15}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T15~0x2\-F}}\label{MAX6956_8h_ad366a7c1b65fb3496f5b9ba392d6ba9c} + + +Definition at line 279 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_ac483e6007b4e6a780c14c7a78ff7a134}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T16@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T16}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T16@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T16}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T16}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T16~0x30}}\label{MAX6956_8h_ac483e6007b4e6a780c14c7a78ff7a134} + + +Definition at line 280 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_ab6f3b8bbd8ac56bacf4a57691eb41aaf}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T17@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T17}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T17@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T17}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T17}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T17~0x31}}\label{MAX6956_8h_ab6f3b8bbd8ac56bacf4a57691eb41aaf} + + +Definition at line 281 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a082486ab9eace7838acd56b6ac6301df}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T18@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T18}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T18@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T18}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T18}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T18~0x32}}\label{MAX6956_8h_a082486ab9eace7838acd56b6ac6301df} + + +Definition at line 282 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a04e65b34862a48ae022c994bbc5968dd}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T19@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T19}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T19@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T19}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T19}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T19~0x33}}\label{MAX6956_8h_a04e65b34862a48ae022c994bbc5968dd} + + +Definition at line 283 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_ac4cc75132151b2f662b7c54128391187}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T2@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T2}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T2@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T2}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T2}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T2~0x22}}\label{MAX6956_8h_ac4cc75132151b2f662b7c54128391187} + + +(virtual port, no action) + + + +Definition at line 264 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_aed99f35f5ba961711c4e5bed769aa369}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T20@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T20}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T20@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T20}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T20}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T20~0x34}}\label{MAX6956_8h_aed99f35f5ba961711c4e5bed769aa369} + + +Definition at line 285 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a361dcd71b3da6c5fb57d33951c9e4c54}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T21@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T21}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T21@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T21}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T21}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T21~0x35}}\label{MAX6956_8h_a361dcd71b3da6c5fb57d33951c9e4c54} + + +Definition at line 286 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a67c57767c9f6eda6124ff7368df4293b}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T22@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T22}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T22@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T22}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T22}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T22~0x36}}\label{MAX6956_8h_a67c57767c9f6eda6124ff7368df4293b} + + +Definition at line 287 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a29699b356f81b9fc971a29fc04e68a59}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T23@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T23}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T23@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T23}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T23}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T23~0x37}}\label{MAX6956_8h_a29699b356f81b9fc971a29fc04e68a59} + + +Definition at line 288 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_ad053ff9eac065beaa10ad52dcc3d1e3e}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T24@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T24}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T24@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T24}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T24}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T24~0x38}}\label{MAX6956_8h_ad053ff9eac065beaa10ad52dcc3d1e3e} + + +Definition at line 289 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a367103a7d8364b916a70f37d0880e334}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T25@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T25}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T25@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T25}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T25}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T25~0x39}}\label{MAX6956_8h_a367103a7d8364b916a70f37d0880e334} + + +Definition at line 290 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_ae0c19d326ab47406a138d4b66c601de0}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T26@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T26}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T26@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T26}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T26}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T26~0x3\-A}}\label{MAX6956_8h_ae0c19d326ab47406a138d4b66c601de0} + + +Definition at line 291 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_ae1219ad62d3ea1b3a86c52736d347618}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T27@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T27}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T27@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T27}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T27}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T27~0x3\-B}}\label{MAX6956_8h_ae1219ad62d3ea1b3a86c52736d347618} + + +Definition at line 292 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a07ff69092b95f43595762554c3e35329}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T28@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T28}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T28@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T28}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T28}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T28~0x3\-C}}\label{MAX6956_8h_a07ff69092b95f43595762554c3e35329} + + +Definition at line 294 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a6be82fa185d6c3dd272200727c15f4ac}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T29@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T29}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T29@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T29}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T29}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T29~0x3\-D}}\label{MAX6956_8h_a6be82fa185d6c3dd272200727c15f4ac} + + +Definition at line 295 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_aa3e011deb16e7054e78e6f71ac33fcba}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T3@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T3}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T3@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T3}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T3}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T3~0x23}}\label{MAX6956_8h_aa3e011deb16e7054e78e6f71ac33fcba} + + +(virtual port, no action) + + + +Definition at line 265 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a34c02dca8e8a97488eb0be51f682cf73}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T30@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T30}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T30@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T30}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T30}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T30~0x3\-E}}\label{MAX6956_8h_a34c02dca8e8a97488eb0be51f682cf73} + + +Definition at line 296 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a891d2a47a2fe5a4da056a7732fb6098b}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T31@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T31}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T31@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T31}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T31}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T31~0x3\-F}}\label{MAX6956_8h_a891d2a47a2fe5a4da056a7732fb6098b} + + +Definition at line 297 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a68339cee27681486c99dabf398f487a0}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T4@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T4}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T4@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T4}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T4}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T4~0x24}}\label{MAX6956_8h_a68339cee27681486c99dabf398f487a0} + + +Definition at line 267 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a92c4653a42f8400a30aa13a60dbc056f}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T5@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T5}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T5@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T5}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T5}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T5~0x25}}\label{MAX6956_8h_a92c4653a42f8400a30aa13a60dbc056f} + + +Definition at line 268 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a5af96fba8e40466303a2bcec16df6c6f}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T6@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T6}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T6@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T6}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T6}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T6~0x26}}\label{MAX6956_8h_a5af96fba8e40466303a2bcec16df6c6f} + + +Definition at line 269 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a20de98d6d2102960000a70b4bcf6007c}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T7@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T7}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T7@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T7}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T7}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T7~0x27}}\label{MAX6956_8h_a20de98d6d2102960000a70b4bcf6007c} + + +Definition at line 270 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_ad0ea7dd1027b558df290150b664b0222}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T8@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T8}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T8@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T8}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T8}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T8~0x28}}\label{MAX6956_8h_ad0ea7dd1027b558df290150b664b0222} + + +Definition at line 271 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a7d31adbda8965d0d7df0c521571e135c}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T9@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T9}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T9@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T9}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T9}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T9~0x29}}\label{MAX6956_8h_a7d31adbda8965d0d7df0c521571e135c} + + +Definition at line 272 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_aa9837d30cb5f9c9badf20fe50ea3ba26}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S10\-\_\-17@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S10\-\_\-17}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S10\-\_\-17@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S10\-\_\-17}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S10\-\_\-17}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S10\-\_\-17~0x4\-A}}\label{MAX6956_8h_aa9837d30cb5f9c9badf20fe50ea3ba26} + + +Definition at line 315 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a40bf1528e6a7345e0aaa3b86869f3af3}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S11\-\_\-18@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S11\-\_\-18}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S11\-\_\-18@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S11\-\_\-18}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S11\-\_\-18}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S11\-\_\-18~0x4\-B}}\label{MAX6956_8h_a40bf1528e6a7345e0aaa3b86869f3af3} + + +Definition at line 316 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_ab3e1f8d0b913acae6d73f9b5b0d491ff}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S12\-\_\-19@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S12\-\_\-19}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S12\-\_\-19@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S12\-\_\-19}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S12\-\_\-19}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S12\-\_\-19~0x4\-C}}\label{MAX6956_8h_ab3e1f8d0b913acae6d73f9b5b0d491ff} + + +Definition at line 317 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_ad33d71fa8457fcdb444179768a6376e9}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S13\-\_\-20@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S13\-\_\-20}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S13\-\_\-20@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S13\-\_\-20}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S13\-\_\-20}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S13\-\_\-20~0x4\-D}}\label{MAX6956_8h_ad33d71fa8457fcdb444179768a6376e9} + + +Definition at line 318 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_aeae655678f9a39b8a7f6e9de1a09c59e}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S14\-\_\-21@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S14\-\_\-21}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S14\-\_\-21@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S14\-\_\-21}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S14\-\_\-21}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S14\-\_\-21~0x4\-E}}\label{MAX6956_8h_aeae655678f9a39b8a7f6e9de1a09c59e} + + +Definition at line 319 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a853b18f366e225131135f6576268a461}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S15\-\_\-22@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S15\-\_\-22}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S15\-\_\-22@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S15\-\_\-22}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S15\-\_\-22}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S15\-\_\-22~0x4\-F}}\label{MAX6956_8h_a853b18f366e225131135f6576268a461} + + +Definition at line 320 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a39c1bb286953031fad9c101604d6f56e}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S16\-\_\-23@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S16\-\_\-23}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S16\-\_\-23@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S16\-\_\-23}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S16\-\_\-23}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S16\-\_\-23~0x50}}\label{MAX6956_8h_a39c1bb286953031fad9c101604d6f56e} + + +Definition at line 321 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a8a4536b80e588a3ed6bb2f487499efeb}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S17\-\_\-24@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S17\-\_\-24}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S17\-\_\-24@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S17\-\_\-24}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S17\-\_\-24}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S17\-\_\-24~0x51}}\label{MAX6956_8h_a8a4536b80e588a3ed6bb2f487499efeb} + + +Definition at line 322 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a1ae324a27c0648b831978991a44ee33f}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S18\-\_\-25@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S18\-\_\-25}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S18\-\_\-25@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S18\-\_\-25}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S18\-\_\-25}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S18\-\_\-25~0x52}}\label{MAX6956_8h_a1ae324a27c0648b831978991a44ee33f} + + +Definition at line 323 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a981a54414024fdd2877704d4d242b748}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S19\-\_\-26@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S19\-\_\-26}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S19\-\_\-26@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S19\-\_\-26}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S19\-\_\-26}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S19\-\_\-26~0x53}}\label{MAX6956_8h_a981a54414024fdd2877704d4d242b748} + + +Definition at line 324 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_abd2280465476a9e3cae302d5e9bf7b62}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S20\-\_\-27@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S20\-\_\-27}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S20\-\_\-27@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S20\-\_\-27}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S20\-\_\-27}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S20\-\_\-27~0x54}}\label{MAX6956_8h_abd2280465476a9e3cae302d5e9bf7b62} + + +Definition at line 325 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_adfca6218829cec2697e0975fc7965008}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S21\-\_\-28@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S21\-\_\-28}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S21\-\_\-28@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S21\-\_\-28}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S21\-\_\-28}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S21\-\_\-28~0x55}}\label{MAX6956_8h_adfca6218829cec2697e0975fc7965008} + + +Definition at line 326 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_aa190f6504c585b64f355ce45a24057f1}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S22\-\_\-29@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S22\-\_\-29}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S22\-\_\-29@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S22\-\_\-29}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S22\-\_\-29}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S22\-\_\-29~0x56}}\label{MAX6956_8h_aa190f6504c585b64f355ce45a24057f1} + + +Definition at line 327 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a9ae64dcdc091a17982f4888bcd7b1981}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S23\-\_\-30@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S23\-\_\-30}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S23\-\_\-30@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S23\-\_\-30}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S23\-\_\-30}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S23\-\_\-30~0x57}}\label{MAX6956_8h_a9ae64dcdc091a17982f4888bcd7b1981} + + +Definition at line 328 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a5054da2b077f91e7f6106373a84476ed}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S24\-\_\-31@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S24\-\_\-31}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S24\-\_\-31@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S24\-\_\-31}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S24\-\_\-31}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S24\-\_\-31~0x58}}\label{MAX6956_8h_a5054da2b077f91e7f6106373a84476ed} + + +Definition at line 329 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a38a7fe545ab1b4ca108dabcef50d015f}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S25\-\_\-31@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S25\-\_\-31}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S25\-\_\-31@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S25\-\_\-31}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S25\-\_\-31}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S25\-\_\-31~0x59}}\label{MAX6956_8h_a38a7fe545ab1b4ca108dabcef50d015f} + + +data bits D0-\/\-D6; D7 reads as 0 + + + +Definition at line 333 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_ac804c8074d5a6baf79b0595415ae0679}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S26\-\_\-31@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S26\-\_\-31}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S26\-\_\-31@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S26\-\_\-31}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S26\-\_\-31}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S26\-\_\-31~0x5\-A}}\label{MAX6956_8h_ac804c8074d5a6baf79b0595415ae0679} + + +data bits D0-\/\-D5; D6-\/\-D7 read as 0 + + + +Definition at line 334 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a5307d28ebcae5028fc482c914eecf48f}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S27\-\_\-31@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S27\-\_\-31}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S27\-\_\-31@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S27\-\_\-31}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S27\-\_\-31}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S27\-\_\-31~0x5\-B}}\label{MAX6956_8h_a5307d28ebcae5028fc482c914eecf48f} + + +data bits D0-\/\-D4; D5-\/\-D7 read as 0 + + + +Definition at line 335 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a7554adf2b4214f33584001f4e7c81053}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S28\-\_\-31@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S28\-\_\-31}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S28\-\_\-31@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S28\-\_\-31}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S28\-\_\-31}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S28\-\_\-31~0x5\-C}}\label{MAX6956_8h_a7554adf2b4214f33584001f4e7c81053} + + +data bits D0-\/\-D3; D4-\/\-D7 read as 0 + + + +Definition at line 336 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_ab278f8cb075460b9318c029bca24e68a}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S29\-\_\-31@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S29\-\_\-31}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S29\-\_\-31@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S29\-\_\-31}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S29\-\_\-31}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S29\-\_\-31~0x5\-D}}\label{MAX6956_8h_ab278f8cb075460b9318c029bca24e68a} + + +data bits D0-\/\-D2; D3-\/\-D7 read as 0 + + + +Definition at line 337 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_ae5873266ac57220286709a468781c3ff}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S30\-\_\-31@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S30\-\_\-31}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S30\-\_\-31@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S30\-\_\-31}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S30\-\_\-31}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S30\-\_\-31~0x5\-E}}\label{MAX6956_8h_ae5873266ac57220286709a468781c3ff} + + +data bits D0-\/\-D1; D2-\/\-D7 read as 0 + + + +Definition at line 338 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_ad12b528f7fa63249d37126a8d4049aab}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S31\-\_\-31@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S31\-\_\-31}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S31\-\_\-31@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S31\-\_\-31}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S31\-\_\-31}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S31\-\_\-31~0x5\-F}}\label{MAX6956_8h_ad12b528f7fa63249d37126a8d4049aab} + + +data bit D0; D1-\/\-D7 read as 0. Port 31 only. + + + +Definition at line 339 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_ac32650edffdebee3cfeb90c9daece88b}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-10@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-10}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-10@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-10}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-10}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-10~0x43}}\label{MAX6956_8h_ac32650edffdebee3cfeb90c9daece88b} + + +data bits D0-\/\-D6; D7 reads as 0 + + + +Definition at line 304 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a4b0cc79ee765d2f477953a890b2f6209}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-11@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-11}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-11@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-11}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-11}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-11~0x44}}\label{MAX6956_8h_a4b0cc79ee765d2f477953a890b2f6209} + + +Definition at line 309 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a00bff40ca66a7c82b7093536c5047da4}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-7@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-7}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-7@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-7}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-7}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-7~0x40}}\label{MAX6956_8h_a00bff40ca66a7c82b7093536c5047da4} + + +data bits D0-\/\-D3; D4-\/\-D7 read as 0 + + + +Definition at line 301 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a3d1cd4727f1748e42a0426c0b70d9c2c}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-8@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-8}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-8@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-8}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-8}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-8~0x41}}\label{MAX6956_8h_a3d1cd4727f1748e42a0426c0b70d9c2c} + + +data bits D0-\/\-D4; D5-\/\-D7 read as 0 + + + +Definition at line 302 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_ad1b71a2b24de60a4d0128576c0e1278b}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-9@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-9}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-9@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-9}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-9}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-9~0x42}}\label{MAX6956_8h_ad1b71a2b24de60a4d0128576c0e1278b} + + +data bits D0-\/\-D5; D6-\/\-D7 read as 0 + + + +Definition at line 303 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a13b8eb94b73c20a02397e50c81bccb57}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S5\-\_\-12@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S5\-\_\-12}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S5\-\_\-12@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S5\-\_\-12}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S5\-\_\-12}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S5\-\_\-12~0x45}}\label{MAX6956_8h_a13b8eb94b73c20a02397e50c81bccb57} + + +Definition at line 310 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_af01fef127c33b806d570f1d46a90362f}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S6\-\_\-13@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S6\-\_\-13}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S6\-\_\-13@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S6\-\_\-13}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S6\-\_\-13}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S6\-\_\-13~0x46}}\label{MAX6956_8h_af01fef127c33b806d570f1d46a90362f} + + +Definition at line 311 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_ae0f37de2a929dc6f37733c3f112e0fa7}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S7\-\_\-14@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S7\-\_\-14}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S7\-\_\-14@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S7\-\_\-14}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S7\-\_\-14}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S7\-\_\-14~0x47}}\label{MAX6956_8h_ae0f37de2a929dc6f37733c3f112e0fa7} + + +Definition at line 312 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_ae2bd6458f4aa0271d7fb9c8c8fdd0e4f}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S8\-\_\-15@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S8\-\_\-15}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S8\-\_\-15@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S8\-\_\-15}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S8\-\_\-15}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S8\-\_\-15~0x48}}\label{MAX6956_8h_ae2bd6458f4aa0271d7fb9c8c8fdd0e4f} + + +Definition at line 313 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_aedb8b7ecadabaf8290ac1eacde7db918}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S9\-\_\-16@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S9\-\_\-16}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S9\-\_\-16@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S9\-\_\-16}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S9\-\_\-16}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S9\-\_\-16~0x49}}\label{MAX6956_8h_aedb8b7ecadabaf8290ac1eacde7db918} + + +Definition at line 314 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a4a2b4c395e47e0ec9ef49d3236b8a465}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-D\-E\-T\-E\-C\-T@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-D\-E\-T\-E\-C\-T}} +\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-D\-E\-T\-E\-C\-T@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-D\-E\-T\-E\-C\-T}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-D\-E\-T\-E\-C\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-D\-E\-T\-E\-C\-T~0x06}}\label{MAX6956_8h_a4a2b4c395e47e0ec9ef49d3236b8a465} +\subsection*{Table 15. Transition Detection Mask Register } + +\begin{TabularC}{11} +\hline +\rowcolor{lightgray}{\bf F\-U\-N\-C\-T\-I\-O\-N }&{\bf R\-E\-G\-I\-S\-T\-E\-R A\-D\-D\-R\-E\-S\-S }&{\bf R\-E\-A\-D/\-W\-R\-I\-T\-E }&{\bf D7 }&{\bf D6 }&{\bf D5 }&{\bf D4 }&{\bf D3 }&{\bf D2 }&{\bf D1 }&{\bf D0 }\\\cline{1-11} +Mask Register &0x06 &Read &I\-N\-T Status$\ast$&Port&Port&Port&Port&Port&Port&Port \\\cline{1-11} +&&&&30 &29 &28 &27 &26 &25 &24 \\\cline{1-11} +&&Write &Unchanged &mask&mask&mask&mask&mask&mask&mask \\\cline{1-11} +\end{TabularC} +I\-N\-T is automatically cleared after it is read. + +Definition at line 152 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_abc801853bdfe66591265d04865aba78f}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-B\-I\-T}} +\index{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-B\-I\-T~0}}\label{MAX6956_8h_abc801853bdfe66591265d04865aba78f} + + +Ports 24-\/30. + + + +Definition at line 394 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a332868e8a1596e785072ddb8c4a2b4c1}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-L\-E\-N\-G\-T\-H}} +\index{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-L\-E\-N\-G\-T\-H}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-L\-E\-N\-G\-T\-H}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-L\-E\-N\-G\-T\-H~7}}\label{MAX6956_8h_a332868e8a1596e785072ddb8c4a2b4c1} + + +Definition at line 395 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a0a2eb488b9b8d16b5c076d25790ec28e}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T24\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T24\-\_\-\-B\-I\-T}} +\index{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T24\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T24\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T24\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T24\-\_\-\-B\-I\-T~0}}\label{MAX6956_8h_a0a2eb488b9b8d16b5c076d25790ec28e} + + +Definition at line 402 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a04d331f867fa51822f5910ce2b6b891c}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T25\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T25\-\_\-\-B\-I\-T}} +\index{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T25\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T25\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T25\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T25\-\_\-\-B\-I\-T~1}}\label{MAX6956_8h_a04d331f867fa51822f5910ce2b6b891c} + + +Definition at line 401 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_ac4f63f4afc199c41dd9b1445259b8d50}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T26\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T26\-\_\-\-B\-I\-T}} +\index{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T26\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T26\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T26\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T26\-\_\-\-B\-I\-T~2}}\label{MAX6956_8h_ac4f63f4afc199c41dd9b1445259b8d50} + + +Definition at line 400 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a282091cda715bb27f96266f5ae22b492}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T27\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T27\-\_\-\-B\-I\-T}} +\index{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T27\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T27\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T27\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T27\-\_\-\-B\-I\-T~3}}\label{MAX6956_8h_a282091cda715bb27f96266f5ae22b492} + + +Definition at line 399 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a927e5369f33337fdea8d89ccc3b3919d}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T28\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T28\-\_\-\-B\-I\-T}} +\index{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T28\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T28\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T28\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T28\-\_\-\-B\-I\-T~4}}\label{MAX6956_8h_a927e5369f33337fdea8d89ccc3b3919d} + + +Definition at line 398 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a74adf7234472da3287cb98af583750c9}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T29\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T29\-\_\-\-B\-I\-T}} +\index{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T29\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T29\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T29\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T29\-\_\-\-B\-I\-T~5}}\label{MAX6956_8h_a74adf7234472da3287cb98af583750c9} + + +Definition at line 397 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a0e7f62a1c7d77019ca8ca2c2511f2644}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T30\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T30\-\_\-\-B\-I\-T}} +\index{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T30\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T30\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T30\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T30\-\_\-\-B\-I\-T~6}}\label{MAX6956_8h_a0e7f62a1c7d77019ca8ca2c2511f2644} + + +Definition at line 396 of file M\-A\-X6956.\-h. + +\hypertarget{MAX6956_8h_a29bd01905e66b503151e6d9cdfb035a1}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-S\-T\-A\-T\-U\-S\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-S\-T\-A\-T\-U\-S\-\_\-\-B\-I\-T}} +\index{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-S\-T\-A\-T\-U\-S\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-S\-T\-A\-T\-U\-S\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} +\subsubsection[{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-S\-T\-A\-T\-U\-S\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-S\-T\-A\-T\-U\-S\-\_\-\-B\-I\-T~7}}\label{MAX6956_8h_a29bd01905e66b503151e6d9cdfb035a1} + + +I\-N\-T Status, I\-N\-T is automatically cleared after it is read. + + + +Definition at line 393 of file M\-A\-X6956.\-h. + diff --git a/Arduino/MAX6956/latex/Makefile b/Arduino/MAX6956/latex/Makefile new file mode 100644 index 00000000..3cc085fe --- /dev/null +++ b/Arduino/MAX6956/latex/Makefile @@ -0,0 +1,21 @@ +all: refman.pdf + +pdf: refman.pdf + +refman.pdf: clean refman.tex + pdflatex refman + makeindex refman.idx + pdflatex refman + latex_count=5 ; \ + while egrep -s 'Rerun (LaTeX|to get cross-references right)' refman.log && [ $$latex_count -gt 0 ] ;\ + do \ + echo "Rerunning latex...." ;\ + pdflatex refman ;\ + latex_count=`expr $$latex_count - 1` ;\ + done + makeindex refman.idx + pdflatex refman + + +clean: + rm -f *.ps *.dvi *.aux *.toc *.idx *.ind *.ilg *.log *.out *.brf *.blg *.bbl refman.pdf diff --git a/Arduino/MAX6956/latex/annotated.tex b/Arduino/MAX6956/latex/annotated.tex new file mode 100644 index 00000000..3409b9d9 --- /dev/null +++ b/Arduino/MAX6956/latex/annotated.tex @@ -0,0 +1,4 @@ +\section{Data Structures} +Here are the data structures with brief descriptions\-:\begin{DoxyCompactList} +\item\contentsline{section}{\hyperlink{classMAX6956}{M\-A\-X6956} }{\pageref{classMAX6956}}{} +\end{DoxyCompactList} diff --git a/Arduino/MAX6956/latex/classMAX6956.tex b/Arduino/MAX6956/latex/classMAX6956.tex new file mode 100644 index 00000000..8b4ad093 --- /dev/null +++ b/Arduino/MAX6956/latex/classMAX6956.tex @@ -0,0 +1,825 @@ +\hypertarget{classMAX6956}{\section{M\-A\-X6956 Class Reference} +\label{classMAX6956}\index{M\-A\-X6956@{M\-A\-X6956}} +} + + +{\ttfamily \#include $<$M\-A\-X6956.\-h$>$} + +\subsection*{Public Member Functions} +\begin{DoxyCompactItemize} +\item +\hyperlink{classMAX6956_a210d9e95978d61357db757cb80475bde}{M\-A\-X6956} () +\item +\hyperlink{classMAX6956_a1a7b33190871a09d81c5bec741b645b7}{M\-A\-X6956} (uint8\-\_\-t address) +\item +void \hyperlink{classMAX6956_ad63e927adc2427b4b661f2422ddd40d8}{initialize} () +\item +bool \hyperlink{classMAX6956_a60bd352328d77e59a4d51a3c55d38a25}{test\-Connection} () +\item +void \hyperlink{classMAX6956_a3b9166eee826a876bbf29bc63b090fe7}{reset} () +\item +uint8\-\_\-t \hyperlink{classMAX6956_a5e787204b3f7bf8750376f5bdf77a971}{get\-Config\-Reg} () +\item +void \hyperlink{classMAX6956_ad06b9ed9f6e18f81d8379a6e10391ea4}{set\-Config\-Reg} (uint8\-\_\-t config) +\item +bool \hyperlink{classMAX6956_acdc18c36735d8015651d4e3c75da4300}{get\-Power} () +\item +void \hyperlink{classMAX6956_a993f35d31d1f2489f9d2965c3886f848}{toggle\-Power} () +\item +void \hyperlink{classMAX6956_ae10ac505e3857d31ca3823225983a697}{set\-Power} (bool power) +\item +bool \hyperlink{classMAX6956_abcfe81dd0ffc90284f19503b6366dcfb}{get\-Enable\-Individual\-Current} () +\item +void \hyperlink{classMAX6956_a35bc5701a290409144929e640cad1748}{set\-Enable\-Individual\-Current} (bool global) +\item +bool \hyperlink{classMAX6956_a76e9ab35769854b3e4224499897601ec}{get\-Enable\-Transition\-Detection} () +\item +void \hyperlink{classMAX6956_a67b65b80e09a3225dd4f6413bfab2844}{set\-Enable\-Transition\-Detection} (bool transition) +\item +uint8\-\_\-t \hyperlink{classMAX6956_a1926760b263588314fd759d129091940}{get\-Global\-Current} () +\item +void \hyperlink{classMAX6956_a4669dcc0f2f89f8fe73a0fa9b97dae21}{set\-Global\-Current} (uint8\-\_\-t current) +\item +bool \hyperlink{classMAX6956_ad4f99f08d1cf08c5a0097215e680a80a}{get\-Test\-Mode} () +\item +void \hyperlink{classMAX6956_ad1b4e5cafd91acd2be2b6fb8197afef0}{set\-Test\-Mode} (bool test) +\item +uint8\-\_\-t \hyperlink{classMAX6956_a56245915d7d4cd8fd34629bd91695147}{get\-Input\-Mask} () +\item +void \hyperlink{classMAX6956_a7ce45652fb0490af0ecb4eaebc230419}{set\-Input\-Mask} (uint8\-\_\-t mask) +\item +void \hyperlink{classMAX6956_a5e05bead41c585c68de79bbfed971d19}{config\-Port} (uint8\-\_\-t port, uint8\-\_\-t \hyperlink{classMAX6956_a9799e7684546e3e9b24506d436586a09}{port\-Config}) +\item +void \hyperlink{classMAX6956_a400393e30fbe196aef43d8edea890228}{config\-Ports} (uint8\-\_\-t lower, uint8\-\_\-t upper, uint8\-\_\-t \hyperlink{classMAX6956_a9799e7684546e3e9b24506d436586a09}{port\-Config}) +\item +void \hyperlink{classMAX6956_a9e9f11c46bdc86d8e882ed8bb5efabdf}{config\-All\-Ports} (uint8\-\_\-t \hyperlink{classMAX6956_a9799e7684546e3e9b24506d436586a09}{port\-Config}) +\item +void \hyperlink{classMAX6956_a98fa3831a47355fe0856caa74a9cf810}{set\-Port\-Level} (uint8\-\_\-t port, uint8\-\_\-t power) +\begin{DoxyCompactList}\small\item\em 0 = off, 1-\/15 brightness levels. \end{DoxyCompactList}\item +void \hyperlink{classMAX6956_a76a617f3b8982bb3855c5152b480097a}{set\-Port\-Current} (uint8\-\_\-t port, uint8\-\_\-t power) +\begin{DoxyCompactList}\small\item\em 0-\/15 brightness levels. \end{DoxyCompactList}\item +void \hyperlink{classMAX6956_a9a27a32611fa05766946c33850510644}{set\-All\-Ports\-Current} (uint8\-\_\-t power) +\begin{DoxyCompactList}\small\item\em 0-\/15, 0 = min brightness (not off) 15 = max \end{DoxyCompactList}\item +void \hyperlink{classMAX6956_a51a47c1f69532e96c6caa357889004e3}{enable\-All\-Ports} () +\item +void \hyperlink{classMAX6956_a93a81ff86316f63ee1ada3529da2a95b}{disable\-All\-Ports} () +\end{DoxyCompactItemize} +\subsection*{Data Fields} +\begin{DoxyCompactItemize} +\item +uint8\-\_\-t \hyperlink{classMAX6956_a8b915615042c5ef96fbf3a5c260d4716}{ports\-Config} \mbox{[}5\mbox{]} +\item +uint8\-\_\-t \hyperlink{classMAX6956_ae8da9a65da74dce7eb907319b0198847}{ports\-Status} \mbox{[}3\mbox{]} +\end{DoxyCompactItemize} +\subsection*{Private Attributes} +\begin{DoxyCompactItemize} +\item +uint8\-\_\-t \hyperlink{classMAX6956_a6ba2f8011914df50d6022ab54b27748d}{dev\-Addr} +\begin{DoxyCompactList}\small\item\em Holds the current device address. \end{DoxyCompactList}\item +uint8\-\_\-t \hyperlink{classMAX6956_a9f4597436b10ee86a02c96c2b0605851}{buffer} \mbox{[}1\mbox{]} +\begin{DoxyCompactList}\small\item\em Buffer for reading data from the device. \end{DoxyCompactList}\item +uint8\-\_\-t \hyperlink{classMAX6956_a9799e7684546e3e9b24506d436586a09}{port\-Config} +\begin{DoxyCompactList}\small\item\em Holder for port config bit pair. \end{DoxyCompactList}\item +uint8\-\_\-t \hyperlink{classMAX6956_ab0d382db3afe7930d1b95311bfd90164}{port\-Current\-R\-A} +\begin{DoxyCompactList}\small\item\em Holder for port current register. \end{DoxyCompactList}\item +uint8\-\_\-t \hyperlink{classMAX6956_ad3057b6b21ae712acb0129270da63334}{port\-Current\-Bit} +\begin{DoxyCompactList}\small\item\em Holder for the current bit offset. \end{DoxyCompactList}\item +uint8\-\_\-t \hyperlink{classMAX6956_a967e25fac00c0ab59be854289eb36353}{ps\-Array\-Index} +\begin{DoxyCompactList}\small\item\em array index \end{DoxyCompactList}\item +uint8\-\_\-t \hyperlink{classMAX6956_a92b5dc05a1483c49c150db13dcd1f283}{ps\-Bit\-Position} +\begin{DoxyCompactList}\small\item\em bit position \end{DoxyCompactList}\end{DoxyCompactItemize} + + +\subsection{Detailed Description} +A library for controlling the \hyperlink{classMAX6956}{M\-A\-X6956} using i2\-C. + +The \hyperlink{classMAX6956}{M\-A\-X6956} compact, serial-\/interfaced L\-E\-D display driver/\-I/\-O expander provide microprocessors with up to 28 ports. Each port is individually user configurable to either a logic input, logic output, or common-\/anode (C\-A) L\-E\-D constant-\/current segment driver. Each port configured as an L\-E\-D segment driver behaves as a digitally controlled constant-\/current sink, with 16 equal current steps from 1.\-5m\-A to 24m\-A. The L\-E\-D drivers are suitable for both discrete L\-E\-Ds and C\-A numeric and alphanumeric L\-E\-D digits. + +Each port configured as a general-\/purpose I/\-O (G\-P\-I\-O) can be either a push-\/pull logic output capable of sink-\/ ing 10m\-A and sourcing 4.\-5m\-A, or a Schmitt logic input with optional internal pullup. Seven ports feature config-\/ urable transition detection logic, which generates an interrupt upon change of port logic level. The \hyperlink{classMAX6956}{M\-A\-X6956} is controlled through an I2\-C-\/compatible 2-\/wire serial interface, and uses four-\/level logic to allow 16 I 2\-C addresses from only 2 select pins. + +The M\-A\-X6956\-A\-A\-X and M\-A\-X6956\-A\-T\-L have 28 ports and are available in 36-\/pin S\-S\-O\-P and 40-\/pin thin Q\-F\-N packages, respectively. The M\-A\-X6956\-A\-A\-I and M\-A\-X6956\-A\-N\-I have 20 ports and are available in 28-\/pin S\-S\-O\-P and 28-\/pin D\-I\-P packages, respectively. + +For an S\-P\-I-\/interfaced version, refer to the M\-A\-X6957 data sheet. For a lower cost pin-\/compatible port expander without the constant-\/current L\-E\-D drive capa-\/ bility, refer to the M\-A\-X7300 data sheet. + + +\begin{DoxyItemize} +\item 400kbps I2\-C-\/\-Compatible Serial Interface +\item 2.\-5\-V to 5.\-5\-V Operation +\item -\/40°\-C to +125°\-C Temperature Range +\item 20 or 28 I/\-O Ports, Each Configurable as +\item Constant-\/\-Current L\-E\-D Driver +\item Push-\/\-Pull Logic Output +\item Schmitt Logic Input +\item Schmitt Logic Input with Internal Pullup +\item 11μ\-A (max) Shutdown Current +\item 16-\/\-Step Individually Programmable Current +\item Control for Each L\-E\-D +\item Logic Transition Detection for Seven I/\-O Ports +\end{DoxyItemize} + +Definition at line 456 of file M\-A\-X6956.\-h. + + + +\subsection{Constructor \& Destructor Documentation} +\hypertarget{classMAX6956_a210d9e95978d61357db757cb80475bde}{\index{M\-A\-X6956@{M\-A\-X6956}!M\-A\-X6956@{M\-A\-X6956}} +\index{M\-A\-X6956@{M\-A\-X6956}!MAX6956@{M\-A\-X6956}} +\subsubsection[{M\-A\-X6956}]{\setlength{\rightskip}{0pt plus 5cm}M\-A\-X6956\-::\-M\-A\-X6956 ( +\begin{DoxyParamCaption} +{} +\end{DoxyParamCaption} +)}}\label{classMAX6956_a210d9e95978d61357db757cb80475bde} +Default constructor, uses default I2\-C address. \begin{DoxySeeAlso}{See Also} +\hyperlink{MAX6956_8h_a4ca90873afdfdacaa730ed5db53e2f5b}{M\-A\-X6956\-\_\-\-D\-E\-F\-A\-U\-L\-T\-\_\-\-A\-D\-D\-R\-E\-S\-S} +\end{DoxySeeAlso} + + +Definition at line 40 of file M\-A\-X6956.\-cpp. + +\hypertarget{classMAX6956_a1a7b33190871a09d81c5bec741b645b7}{\index{M\-A\-X6956@{M\-A\-X6956}!M\-A\-X6956@{M\-A\-X6956}} +\index{M\-A\-X6956@{M\-A\-X6956}!MAX6956@{M\-A\-X6956}} +\subsubsection[{M\-A\-X6956}]{\setlength{\rightskip}{0pt plus 5cm}M\-A\-X6956\-::\-M\-A\-X6956 ( +\begin{DoxyParamCaption} +\item[{uint8\-\_\-t}]{address} +\end{DoxyParamCaption} +)}}\label{classMAX6956_a1a7b33190871a09d81c5bec741b645b7} +Specific address constructor. +\begin{DoxyParams}{Parameters} +{\em address} & I2\-C address \\ +\hline +\end{DoxyParams} +\begin{DoxySeeAlso}{See Also} +\hyperlink{MAX6956_8h_a4ca90873afdfdacaa730ed5db53e2f5b}{M\-A\-X6956\-\_\-\-D\-E\-F\-A\-U\-L\-T\-\_\-\-A\-D\-D\-R\-E\-S\-S} + +\hyperlink{MAX6956_8h_a33e60623a4c5b483d4604fe2c9b91be7}{M\-A\-X6956\-\_\-\-A\-D\-D\-R\-E\-S\-S} +\end{DoxySeeAlso} + + +Definition at line 49 of file M\-A\-X6956.\-cpp. + + + +\subsection{Member Function Documentation} +\hypertarget{classMAX6956_a9e9f11c46bdc86d8e882ed8bb5efabdf}{\index{M\-A\-X6956@{M\-A\-X6956}!config\-All\-Ports@{config\-All\-Ports}} +\index{config\-All\-Ports@{config\-All\-Ports}!MAX6956@{M\-A\-X6956}} +\subsubsection[{config\-All\-Ports}]{\setlength{\rightskip}{0pt plus 5cm}void M\-A\-X6956\-::config\-All\-Ports ( +\begin{DoxyParamCaption} +\item[{uint8\-\_\-t}]{port\-Config} +\end{DoxyParamCaption} +)}}\label{classMAX6956_a9e9f11c46bdc86d8e882ed8bb5efabdf} +\begin{DoxyVerb}Configure all ports the same +\end{DoxyVerb} + +\begin{DoxyParams}{Parameters} +{\em port\-Config} & Valid options are\-: M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-L\-E\-D, M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-G\-P\-I\-O, M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-O\-\_\-\-P\-U\-L\-L, M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-\_\-\-P\-U\-L\-L \\ +\hline +\end{DoxyParams} +\begin{DoxySeeAlso}{See Also} +\hyperlink{MAX6956_8h_ad6490a909085059c4300a51dcebbf7bc}{M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-L\-E\-D} + +\hyperlink{MAX6956_8h_a27f6ca524d4c18623762c722d9993c10}{M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-G\-P\-I\-O} + +\hyperlink{MAX6956_8h_ab05f3186e2515bab3a536ad9f1cbb7db}{M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-O\-\_\-\-P\-U\-L\-L} + +\hyperlink{MAX6956_8h_a68fc1bc750b7959fbab7e64f79589b83}{M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-\_\-\-P\-U\-L\-L} +\end{DoxySeeAlso} + + +Definition at line 332 of file M\-A\-X6956.\-cpp. + +\hypertarget{classMAX6956_a5e05bead41c585c68de79bbfed971d19}{\index{M\-A\-X6956@{M\-A\-X6956}!config\-Port@{config\-Port}} +\index{config\-Port@{config\-Port}!MAX6956@{M\-A\-X6956}} +\subsubsection[{config\-Port}]{\setlength{\rightskip}{0pt plus 5cm}void M\-A\-X6956\-::config\-Port ( +\begin{DoxyParamCaption} +\item[{uint8\-\_\-t}]{port, } +\item[{uint8\-\_\-t}]{port\-Config} +\end{DoxyParamCaption} +)}}\label{classMAX6956_a5e05bead41c585c68de79bbfed971d19} +\begin{DoxyVerb}Takes an INDIVIDUAL port register address (MAX6956_RA_PORT12, ect) +and configures it as: MAX6956_OUTPUT_LED, MAX6956_OUTPUT_GPIO, +MAX6956_INPUT_WO_PULL, or MAX6956_INPUT_W_PULL +\end{DoxyVerb} + + +\subsubsection*{Port registers } + +\begin{TabularC}{2} +\hline +\rowcolor{lightgray}\PBS\centering {\bf Addr. }&\PBS\centering {\bf Name }\\\cline{1-2} +\PBS\centering 0x09 &\PBS\centering M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P7\-P6\-P5\-P4 \\\cline{1-2} +\PBS\centering 0x0\-A &\PBS\centering M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P11\-P10\-P9\-P8 \\\cline{1-2} +\PBS\centering 0x0\-B &\PBS\centering M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P15\-P14\-P13\-P12 \\\cline{1-2} +\PBS\centering 0x0\-C &\PBS\centering M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P19\-P18\-P17\-P16 \\\cline{1-2} +\PBS\centering 0x0\-D &\PBS\centering M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P23\-P22\-P21\-P20 \\\cline{1-2} +\PBS\centering 0x0\-E &\PBS\centering M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P27\-P26\-P25\-P24 \\\cline{1-2} +\PBS\centering 0x0\-F &\PBS\centering M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P31\-P30\-P29\-P28 \\\cline{1-2} +\end{TabularC} +\begin{TabularC}{6} +\hline +\rowcolor{lightgray}\PBS\centering {\bf Num}&\PBS\centering {\bf Dec}&\PBS\centering {\bf Hex }&\PBS\centering {\bf Prt}&\PBS\centering {\bf Port Status Array}&\PBS\centering {\bf Ports Config Array }\\\cline{1-6} +\PBS\centering 00 &\PBS\centering 44 &\PBS\centering 0x2\-C&\PBS\centering P12&\PBS\centering ports\-Status\mbox{[}0\mbox{]}\mbox{[}0\mbox{]}&\PBS\centering ports\-Config\mbox{[}0\mbox{]}\mbox{[}1-\/0\mbox{]} \\\cline{1-6} +\PBS\centering 01 &\PBS\centering 45 &\PBS\centering 0x2\-D&\PBS\centering P13&\PBS\centering ports\-Status\mbox{[}0\mbox{]}\mbox{[}1\mbox{]}&\PBS\centering ports\-Config\mbox{[}0\mbox{]}\mbox{[}3-\/2\mbox{]} \\\cline{1-6} +\PBS\centering 02 &\PBS\centering 46 &\PBS\centering 0x2\-E&\PBS\centering P14&\PBS\centering ports\-Status\mbox{[}0\mbox{]}\mbox{[}2\mbox{]}&\PBS\centering ports\-Config\mbox{[}0\mbox{]}\mbox{[}5-\/4\mbox{]} \\\cline{1-6} +\PBS\centering 03 &\PBS\centering 47 &\PBS\centering 0x2\-F&\PBS\centering P15&\PBS\centering ports\-Status\mbox{[}0\mbox{]}\mbox{[}3\mbox{]}&\PBS\centering ports\-Config\mbox{[}0\mbox{]}\mbox{[}7-\/6\mbox{]} \\\cline{1-6} +\PBS\centering 04 &\PBS\centering 48 &\PBS\centering 0x30&\PBS\centering P16&\PBS\centering ports\-Status\mbox{[}0\mbox{]}\mbox{[}4\mbox{]}&\PBS\centering ports\-Config\mbox{[}1\mbox{]}\mbox{[}1-\/0\mbox{]} \\\cline{1-6} +\PBS\centering 05 &\PBS\centering 49 &\PBS\centering 0x31&\PBS\centering P17&\PBS\centering ports\-Status\mbox{[}0\mbox{]}\mbox{[}5\mbox{]}&\PBS\centering ports\-Config\mbox{[}1\mbox{]}\mbox{[}3-\/2\mbox{]} \\\cline{1-6} +\PBS\centering 06 &\PBS\centering 50 &\PBS\centering 0x32&\PBS\centering P18&\PBS\centering ports\-Status\mbox{[}0\mbox{]}\mbox{[}6\mbox{]}&\PBS\centering ports\-Config\mbox{[}1\mbox{]}\mbox{[}5-\/4\mbox{]} \\\cline{1-6} +\PBS\centering 07 &\PBS\centering 51 &\PBS\centering 0x33&\PBS\centering P19&\PBS\centering ports\-Status\mbox{[}0\mbox{]}\mbox{[}7\mbox{]}&\PBS\centering ports\-Config\mbox{[}1\mbox{]}\mbox{[}7-\/6\mbox{]} \\\cline{1-6} +\PBS\centering 08 &\PBS\centering 52 &\PBS\centering 0x34&\PBS\centering P20&\PBS\centering ports\-Status\mbox{[}1\mbox{]}\mbox{[}0\mbox{]}&\PBS\centering ports\-Config\mbox{[}2\mbox{]}\mbox{[}1-\/0\mbox{]} \\\cline{1-6} +\PBS\centering 09 &\PBS\centering 53 &\PBS\centering 0x35&\PBS\centering P21&\PBS\centering ports\-Status\mbox{[}1\mbox{]}\mbox{[}1\mbox{]}&\PBS\centering ports\-Config\mbox{[}2\mbox{]}\mbox{[}3-\/2\mbox{]} \\\cline{1-6} +\PBS\centering 10 &\PBS\centering 54 &\PBS\centering 0x36&\PBS\centering P22&\PBS\centering ports\-Status\mbox{[}1\mbox{]}\mbox{[}2\mbox{]}&\PBS\centering ports\-Config\mbox{[}2\mbox{]}\mbox{[}5-\/4\mbox{]} \\\cline{1-6} +\PBS\centering 11 &\PBS\centering 55 &\PBS\centering 0x37&\PBS\centering P23&\PBS\centering ports\-Status\mbox{[}1\mbox{]}\mbox{[}3\mbox{]}&\PBS\centering ports\-Config\mbox{[}2\mbox{]}\mbox{[}7-\/6\mbox{]} \\\cline{1-6} +\PBS\centering 12 &\PBS\centering 56 &\PBS\centering 0x38&\PBS\centering P24&\PBS\centering ports\-Status\mbox{[}1\mbox{]}\mbox{[}4\mbox{]}&\PBS\centering ports\-Config\mbox{[}3\mbox{]}\mbox{[}1-\/0\mbox{]} \\\cline{1-6} +\PBS\centering 13 &\PBS\centering 57 &\PBS\centering 0x39&\PBS\centering P25&\PBS\centering ports\-Status\mbox{[}1\mbox{]}\mbox{[}5\mbox{]}&\PBS\centering ports\-Config\mbox{[}3\mbox{]}\mbox{[}3-\/2\mbox{]} \\\cline{1-6} +\PBS\centering 14 &\PBS\centering 58 &\PBS\centering 0x3\-A&\PBS\centering P26&\PBS\centering ports\-Status\mbox{[}1\mbox{]}\mbox{[}6\mbox{]}&\PBS\centering ports\-Config\mbox{[}3\mbox{]}\mbox{[}5-\/4\mbox{]} \\\cline{1-6} +\PBS\centering 15 &\PBS\centering 59 &\PBS\centering 0x3\-B&\PBS\centering P27&\PBS\centering ports\-Status\mbox{[}1\mbox{]}\mbox{[}7\mbox{]}&\PBS\centering ports\-Config\mbox{[}3\mbox{]}\mbox{[}7-\/6\mbox{]} \\\cline{1-6} +\PBS\centering 16 &\PBS\centering 60 &\PBS\centering 0x3\-C&\PBS\centering P28&\PBS\centering ports\-Status\mbox{[}2\mbox{]}\mbox{[}0\mbox{]}&\PBS\centering ports\-Config\mbox{[}4\mbox{]}\mbox{[}1-\/0\mbox{]} \\\cline{1-6} +\PBS\centering 17 &\PBS\centering 61 &\PBS\centering 0x3\-D&\PBS\centering P29&\PBS\centering ports\-Status\mbox{[}2\mbox{]}\mbox{[}1\mbox{]}&\PBS\centering ports\-Config\mbox{[}4\mbox{]}\mbox{[}3-\/2\mbox{]} \\\cline{1-6} +\PBS\centering 18 &\PBS\centering 62 &\PBS\centering 0x3\-E&\PBS\centering P30&\PBS\centering ports\-Status\mbox{[}2\mbox{]}\mbox{[}2\mbox{]}&\PBS\centering ports\-Config\mbox{[}4\mbox{]}\mbox{[}5-\/4\mbox{]} \\\cline{1-6} +\PBS\centering 19 &\PBS\centering 63 &\PBS\centering 0x3\-F&\PBS\centering P31&\PBS\centering ports\-Status\mbox{[}2\mbox{]}\mbox{[}3\mbox{]}&\PBS\centering ports\-Config\mbox{[}4\mbox{]}\mbox{[}7-\/6\mbox{]} \\\cline{1-6} +\end{TabularC} + +\begin{DoxyParams}{Parameters} +{\em port} & Port register address (M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T12, ect) \\ +\hline +{\em port\-Config} & Valid options are\-: M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-L\-E\-D, M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-G\-P\-I\-O, M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-O\-\_\-\-P\-U\-L\-L, M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-\_\-\-P\-U\-L\-L \\ +\hline +\end{DoxyParams} +\begin{DoxySeeAlso}{See Also} +\hyperlink{MAX6956_8h_a3c089b77cbd25ffa27e3cd46af415a9c}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T12} \hyperlink{MAX6956_8h_a2d6ee01536f1fb0ec843479948141cbc}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T13} \hyperlink{MAX6956_8h_aba5e5ff9b4aea95fedff9f6421c5f47c}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T14} \hyperlink{MAX6956_8h_ad366a7c1b65fb3496f5b9ba392d6ba9c}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T15} \hyperlink{MAX6956_8h_ac483e6007b4e6a780c14c7a78ff7a134}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T16} \hyperlink{MAX6956_8h_ab6f3b8bbd8ac56bacf4a57691eb41aaf}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T17} \hyperlink{MAX6956_8h_a082486ab9eace7838acd56b6ac6301df}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T18} \hyperlink{MAX6956_8h_a04e65b34862a48ae022c994bbc5968dd}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T19} \hyperlink{MAX6956_8h_aed99f35f5ba961711c4e5bed769aa369}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T20} \hyperlink{MAX6956_8h_a361dcd71b3da6c5fb57d33951c9e4c54}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T21} \hyperlink{MAX6956_8h_a67c57767c9f6eda6124ff7368df4293b}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T22} \hyperlink{MAX6956_8h_a29699b356f81b9fc971a29fc04e68a59}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T23} \hyperlink{MAX6956_8h_ad053ff9eac065beaa10ad52dcc3d1e3e}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T24} \hyperlink{MAX6956_8h_a367103a7d8364b916a70f37d0880e334}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T25} \hyperlink{MAX6956_8h_ae0c19d326ab47406a138d4b66c601de0}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T26} \hyperlink{MAX6956_8h_ae1219ad62d3ea1b3a86c52736d347618}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T27} \hyperlink{MAX6956_8h_a07ff69092b95f43595762554c3e35329}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T28} \hyperlink{MAX6956_8h_a6be82fa185d6c3dd272200727c15f4ac}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T29} \hyperlink{MAX6956_8h_a34c02dca8e8a97488eb0be51f682cf73}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T30} \hyperlink{MAX6956_8h_a891d2a47a2fe5a4da056a7732fb6098b}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T31} + +\hyperlink{MAX6956_8h_ad6490a909085059c4300a51dcebbf7bc}{M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-L\-E\-D} \hyperlink{MAX6956_8h_a27f6ca524d4c18623762c722d9993c10}{M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-G\-P\-I\-O} \hyperlink{MAX6956_8h_ab05f3186e2515bab3a536ad9f1cbb7db}{M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-O\-\_\-\-P\-U\-L\-L} \hyperlink{MAX6956_8h_a68fc1bc750b7959fbab7e64f79589b83}{M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-\_\-\-P\-U\-L\-L} +\end{DoxySeeAlso} + + +Definition at line 265 of file M\-A\-X6956.\-cpp. + +\hypertarget{classMAX6956_a400393e30fbe196aef43d8edea890228}{\index{M\-A\-X6956@{M\-A\-X6956}!config\-Ports@{config\-Ports}} +\index{config\-Ports@{config\-Ports}!MAX6956@{M\-A\-X6956}} +\subsubsection[{config\-Ports}]{\setlength{\rightskip}{0pt plus 5cm}void M\-A\-X6956\-::config\-Ports ( +\begin{DoxyParamCaption} +\item[{uint8\-\_\-t}]{lower, } +\item[{uint8\-\_\-t}]{upper, } +\item[{uint8\-\_\-t}]{port\-Config} +\end{DoxyParamCaption} +)}}\label{classMAX6956_a400393e30fbe196aef43d8edea890228} +Configure consecutive range of ports +\begin{DoxyParams}{Parameters} +{\em lower} & Lower port register address (M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T12, ect) \\ +\hline +{\em upper} & Upper port register address (M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T12, ect) \\ +\hline +{\em port\-Config} & Valid options are\-: M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-L\-E\-D, M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-G\-P\-I\-O, M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-O\-\_\-\-P\-U\-L\-L, M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-\_\-\-P\-U\-L\-L \\ +\hline +\end{DoxyParams} +\begin{DoxySeeAlso}{See Also} +\hyperlink{MAX6956_8h_ad6490a909085059c4300a51dcebbf7bc}{M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-L\-E\-D} + +\hyperlink{MAX6956_8h_a27f6ca524d4c18623762c722d9993c10}{M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-G\-P\-I\-O} + +\hyperlink{MAX6956_8h_ab05f3186e2515bab3a536ad9f1cbb7db}{M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-O\-\_\-\-P\-U\-L\-L} + +\hyperlink{MAX6956_8h_a68fc1bc750b7959fbab7e64f79589b83}{M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-\_\-\-P\-U\-L\-L} +\end{DoxySeeAlso} + + +Definition at line 285 of file M\-A\-X6956.\-cpp. + +\hypertarget{classMAX6956_a93a81ff86316f63ee1ada3529da2a95b}{\index{M\-A\-X6956@{M\-A\-X6956}!disable\-All\-Ports@{disable\-All\-Ports}} +\index{disable\-All\-Ports@{disable\-All\-Ports}!MAX6956@{M\-A\-X6956}} +\subsubsection[{disable\-All\-Ports}]{\setlength{\rightskip}{0pt plus 5cm}void M\-A\-X6956\-::disable\-All\-Ports ( +\begin{DoxyParamCaption} +{} +\end{DoxyParamCaption} +)}}\label{classMAX6956_a93a81ff86316f63ee1ada3529da2a95b} +Write 0's to all port registers. + +Definition at line 463 of file M\-A\-X6956.\-cpp. + +\hypertarget{classMAX6956_a51a47c1f69532e96c6caa357889004e3}{\index{M\-A\-X6956@{M\-A\-X6956}!enable\-All\-Ports@{enable\-All\-Ports}} +\index{enable\-All\-Ports@{enable\-All\-Ports}!MAX6956@{M\-A\-X6956}} +\subsubsection[{enable\-All\-Ports}]{\setlength{\rightskip}{0pt plus 5cm}void M\-A\-X6956\-::enable\-All\-Ports ( +\begin{DoxyParamCaption} +{} +\end{DoxyParamCaption} +)}}\label{classMAX6956_a51a47c1f69532e96c6caa357889004e3} +Write 1's to all port registers. This enables ports set as outputs and they will always have some brightness, port must be disabled to turn off completely. + +Definition at line 453 of file M\-A\-X6956.\-cpp. + +\hypertarget{classMAX6956_a5e787204b3f7bf8750376f5bdf77a971}{\index{M\-A\-X6956@{M\-A\-X6956}!get\-Config\-Reg@{get\-Config\-Reg}} +\index{get\-Config\-Reg@{get\-Config\-Reg}!MAX6956@{M\-A\-X6956}} +\subsubsection[{get\-Config\-Reg}]{\setlength{\rightskip}{0pt plus 5cm}uint8\-\_\-t M\-A\-X6956\-::get\-Config\-Reg ( +\begin{DoxyParamCaption} +{} +\end{DoxyParamCaption} +)}}\label{classMAX6956_a5e787204b3f7bf8750376f5bdf77a971} +\begin{DoxyVerb}Config register +\end{DoxyVerb} + \begin{DoxyReturn}{Returns} +uint8\-\_\-t value of register +\end{DoxyReturn} +\begin{DoxySeeAlso}{See Also} +\hyperlink{MAX6956_8h_a5c3d1c00491596887e211bfa630c1b94}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-U\-R\-A\-T\-I\-O\-N} +\end{DoxySeeAlso} + + +Definition at line 94 of file M\-A\-X6956.\-cpp. + +\hypertarget{classMAX6956_abcfe81dd0ffc90284f19503b6366dcfb}{\index{M\-A\-X6956@{M\-A\-X6956}!get\-Enable\-Individual\-Current@{get\-Enable\-Individual\-Current}} +\index{get\-Enable\-Individual\-Current@{get\-Enable\-Individual\-Current}!MAX6956@{M\-A\-X6956}} +\subsubsection[{get\-Enable\-Individual\-Current}]{\setlength{\rightskip}{0pt plus 5cm}bool M\-A\-X6956\-::get\-Enable\-Individual\-Current ( +\begin{DoxyParamCaption} +{} +\end{DoxyParamCaption} +)}}\label{classMAX6956_abcfe81dd0ffc90284f19503b6366dcfb} +\begin{DoxyVerb}Get transition detection configuration bit +\end{DoxyVerb} + \begin{DoxyReturn}{Returns} +Boolean value if global current is enabled or not +\end{DoxyReturn} +\begin{DoxySeeAlso}{See Also} +\hyperlink{MAX6956_8h_a5c3d1c00491596887e211bfa630c1b94}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-U\-R\-A\-T\-I\-O\-N} +\end{DoxySeeAlso} + + +Definition at line 134 of file M\-A\-X6956.\-cpp. + +\hypertarget{classMAX6956_a76e9ab35769854b3e4224499897601ec}{\index{M\-A\-X6956@{M\-A\-X6956}!get\-Enable\-Transition\-Detection@{get\-Enable\-Transition\-Detection}} +\index{get\-Enable\-Transition\-Detection@{get\-Enable\-Transition\-Detection}!MAX6956@{M\-A\-X6956}} +\subsubsection[{get\-Enable\-Transition\-Detection}]{\setlength{\rightskip}{0pt plus 5cm}bool M\-A\-X6956\-::get\-Enable\-Transition\-Detection ( +\begin{DoxyParamCaption} +{} +\end{DoxyParamCaption} +)}}\label{classMAX6956_a76e9ab35769854b3e4224499897601ec} +\begin{DoxyVerb}Get transition detection configuration bit +\end{DoxyVerb} + \begin{DoxyReturn}{Returns} +Boolean value if transition detection is enabled or not +\end{DoxyReturn} +\begin{DoxySeeAlso}{See Also} +\hyperlink{MAX6956_8h_a5c3d1c00491596887e211bfa630c1b94}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-U\-R\-A\-T\-I\-O\-N} +\end{DoxySeeAlso} + + +Definition at line 152 of file M\-A\-X6956.\-cpp. + +\hypertarget{classMAX6956_a1926760b263588314fd759d129091940}{\index{M\-A\-X6956@{M\-A\-X6956}!get\-Global\-Current@{get\-Global\-Current}} +\index{get\-Global\-Current@{get\-Global\-Current}!MAX6956@{M\-A\-X6956}} +\subsubsection[{get\-Global\-Current}]{\setlength{\rightskip}{0pt plus 5cm}uint8\-\_\-t M\-A\-X6956\-::get\-Global\-Current ( +\begin{DoxyParamCaption} +{} +\end{DoxyParamCaption} +)}}\label{classMAX6956_a1926760b263588314fd759d129091940} +\begin{DoxyVerb}Get global current +\end{DoxyVerb} + \begin{DoxyReturn}{Returns} +uint8\-\_\-t value of register +\end{DoxyReturn} +\begin{DoxySeeAlso}{See Also} +\hyperlink{MAX6956_8h_a6a6c2bfe9bfbe4930731829baae7c8f6}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T} +\end{DoxySeeAlso} + + +Definition at line 171 of file M\-A\-X6956.\-cpp. + +\hypertarget{classMAX6956_a56245915d7d4cd8fd34629bd91695147}{\index{M\-A\-X6956@{M\-A\-X6956}!get\-Input\-Mask@{get\-Input\-Mask}} +\index{get\-Input\-Mask@{get\-Input\-Mask}!MAX6956@{M\-A\-X6956}} +\subsubsection[{get\-Input\-Mask}]{\setlength{\rightskip}{0pt plus 5cm}uint8\-\_\-t M\-A\-X6956\-::get\-Input\-Mask ( +\begin{DoxyParamCaption} +{} +\end{DoxyParamCaption} +)}}\label{classMAX6956_a56245915d7d4cd8fd34629bd91695147} +\begin{DoxyVerb}Get the input mask to see which ports have changed. MSB is cleared after every read. +\end{DoxyVerb} + \begin{DoxyReturn}{Returns} +uint8\-\_\-t value of register +\end{DoxyReturn} +\begin{DoxySeeAlso}{See Also} +\hyperlink{MAX6956_8h_a4a2b4c395e47e0ec9ef49d3236b8a465}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-D\-E\-T\-E\-C\-T} +\end{DoxySeeAlso} + + +Definition at line 205 of file M\-A\-X6956.\-cpp. + +\hypertarget{classMAX6956_acdc18c36735d8015651d4e3c75da4300}{\index{M\-A\-X6956@{M\-A\-X6956}!get\-Power@{get\-Power}} +\index{get\-Power@{get\-Power}!MAX6956@{M\-A\-X6956}} +\subsubsection[{get\-Power}]{\setlength{\rightskip}{0pt plus 5cm}bool M\-A\-X6956\-::get\-Power ( +\begin{DoxyParamCaption} +{} +\end{DoxyParamCaption} +)}}\label{classMAX6956_acdc18c36735d8015651d4e3c75da4300} +\begin{DoxyVerb}Get power configuration bit +\end{DoxyVerb} + \begin{DoxyReturn}{Returns} +Boolean value if power is enabled or not +\end{DoxyReturn} +\begin{DoxySeeAlso}{See Also} +\hyperlink{MAX6956_8h_a5c3d1c00491596887e211bfa630c1b94}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-U\-R\-A\-T\-I\-O\-N} +\end{DoxySeeAlso} + + +Definition at line 110 of file M\-A\-X6956.\-cpp. + +\hypertarget{classMAX6956_ad4f99f08d1cf08c5a0097215e680a80a}{\index{M\-A\-X6956@{M\-A\-X6956}!get\-Test\-Mode@{get\-Test\-Mode}} +\index{get\-Test\-Mode@{get\-Test\-Mode}!MAX6956@{M\-A\-X6956}} +\subsubsection[{get\-Test\-Mode}]{\setlength{\rightskip}{0pt plus 5cm}bool M\-A\-X6956\-::get\-Test\-Mode ( +\begin{DoxyParamCaption} +{} +\end{DoxyParamCaption} +)}}\label{classMAX6956_ad4f99f08d1cf08c5a0097215e680a80a} +\begin{DoxyVerb}Returns true if test mode is enabled. +\end{DoxyVerb} + \begin{DoxyReturn}{Returns} +uint8\-\_\-t value of register +\end{DoxyReturn} +\begin{DoxySeeAlso}{See Also} +\hyperlink{MAX6956_8h_a709a5193fd2aa9274997dfc22ef73a19}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-D\-I\-S\-P\-L\-A\-Y\-\_\-\-T\-E\-S\-T} +\end{DoxySeeAlso} + + +Definition at line 188 of file M\-A\-X6956.\-cpp. + +\hypertarget{classMAX6956_ad63e927adc2427b4b661f2422ddd40d8}{\index{M\-A\-X6956@{M\-A\-X6956}!initialize@{initialize}} +\index{initialize@{initialize}!MAX6956@{M\-A\-X6956}} +\subsubsection[{initialize}]{\setlength{\rightskip}{0pt plus 5cm}void M\-A\-X6956\-::initialize ( +\begin{DoxyParamCaption} +{} +\end{DoxyParamCaption} +)}}\label{classMAX6956_ad63e927adc2427b4b661f2422ddd40d8} +Power on and prepare for general usage. \begin{DoxyVerb}The 28-pin MAX6956ANI and MAX6956AAI make only 20 ports available, P12 to P31. +\end{DoxyVerb} + The eight unused ports should be configured as outputs on power-\/up by writing 0x55 to registers 0x09 and 0x0\-A. If this is not done,the eight unused ports remain as unconnected inputs and quiescent supply current rises, although there is no damage to the part. + +Definition at line 54 of file M\-A\-X6956.\-cpp. + +\hypertarget{classMAX6956_a3b9166eee826a876bbf29bc63b090fe7}{\index{M\-A\-X6956@{M\-A\-X6956}!reset@{reset}} +\index{reset@{reset}!MAX6956@{M\-A\-X6956}} +\subsubsection[{reset}]{\setlength{\rightskip}{0pt plus 5cm}void M\-A\-X6956\-::reset ( +\begin{DoxyParamCaption} +{} +\end{DoxyParamCaption} +)}}\label{classMAX6956_a3b9166eee826a876bbf29bc63b090fe7} +Set registers back to Power-\/up Configuration + +Definition at line 80 of file M\-A\-X6956.\-cpp. + +\hypertarget{classMAX6956_a9a27a32611fa05766946c33850510644}{\index{M\-A\-X6956@{M\-A\-X6956}!set\-All\-Ports\-Current@{set\-All\-Ports\-Current}} +\index{set\-All\-Ports\-Current@{set\-All\-Ports\-Current}!MAX6956@{M\-A\-X6956}} +\subsubsection[{set\-All\-Ports\-Current}]{\setlength{\rightskip}{0pt plus 5cm}void M\-A\-X6956\-::set\-All\-Ports\-Current ( +\begin{DoxyParamCaption} +\item[{uint8\-\_\-t}]{power} +\end{DoxyParamCaption} +)}}\label{classMAX6956_a9a27a32611fa05766946c33850510644} + + +0-\/15, 0 = min brightness (not off) 15 = max + +Set A\-L\-L port current registers (M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T12, ect) to the S\-A\-M\-E power level 0-\/15. 0 is off, 15 is max brightness. +\begin{DoxyParams}{Parameters} +{\em power} & 0 is min, 15 is max brightness. \\ +\hline +\end{DoxyParams} + + +Definition at line 444 of file M\-A\-X6956.\-cpp. + +\hypertarget{classMAX6956_ad06b9ed9f6e18f81d8379a6e10391ea4}{\index{M\-A\-X6956@{M\-A\-X6956}!set\-Config\-Reg@{set\-Config\-Reg}} +\index{set\-Config\-Reg@{set\-Config\-Reg}!MAX6956@{M\-A\-X6956}} +\subsubsection[{set\-Config\-Reg}]{\setlength{\rightskip}{0pt plus 5cm}void M\-A\-X6956\-::set\-Config\-Reg ( +\begin{DoxyParamCaption} +\item[{uint8\-\_\-t}]{config} +\end{DoxyParamCaption} +)}}\label{classMAX6956_ad06b9ed9f6e18f81d8379a6e10391ea4} +\begin{DoxyVerb}Set config register +\end{DoxyVerb} + +\begin{DoxyParams}{Parameters} +{\em config} & uint8\-\_\-t value to set register \\ +\hline +\end{DoxyParams} +\begin{DoxySeeAlso}{See Also} +\hyperlink{MAX6956_8h_a5c3d1c00491596887e211bfa630c1b94}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-U\-R\-A\-T\-I\-O\-N} +\end{DoxySeeAlso} + + +Definition at line 102 of file M\-A\-X6956.\-cpp. + +\hypertarget{classMAX6956_a35bc5701a290409144929e640cad1748}{\index{M\-A\-X6956@{M\-A\-X6956}!set\-Enable\-Individual\-Current@{set\-Enable\-Individual\-Current}} +\index{set\-Enable\-Individual\-Current@{set\-Enable\-Individual\-Current}!MAX6956@{M\-A\-X6956}} +\subsubsection[{set\-Enable\-Individual\-Current}]{\setlength{\rightskip}{0pt plus 5cm}void M\-A\-X6956\-::set\-Enable\-Individual\-Current ( +\begin{DoxyParamCaption} +\item[{bool}]{global} +\end{DoxyParamCaption} +)}}\label{classMAX6956_a35bc5701a290409144929e640cad1748} +\begin{DoxyVerb}Enable or disable global current +\end{DoxyVerb} + +\begin{DoxyParams}{Parameters} +{\em global} & Boolean value, true enables, false disables individual current \\ +\hline +\end{DoxyParams} +\begin{DoxySeeAlso}{See Also} +\hyperlink{MAX6956_8h_a5c3d1c00491596887e211bfa630c1b94}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-U\-R\-A\-T\-I\-O\-N} + +\hyperlink{classMAX6956_a1926760b263588314fd759d129091940}{get\-Global\-Current()} + +\hyperlink{classMAX6956_a4669dcc0f2f89f8fe73a0fa9b97dae21}{set\-Global\-Current()} +\end{DoxySeeAlso} + + +Definition at line 144 of file M\-A\-X6956.\-cpp. + +\hypertarget{classMAX6956_a67b65b80e09a3225dd4f6413bfab2844}{\index{M\-A\-X6956@{M\-A\-X6956}!set\-Enable\-Transition\-Detection@{set\-Enable\-Transition\-Detection}} +\index{set\-Enable\-Transition\-Detection@{set\-Enable\-Transition\-Detection}!MAX6956@{M\-A\-X6956}} +\subsubsection[{set\-Enable\-Transition\-Detection}]{\setlength{\rightskip}{0pt plus 5cm}void M\-A\-X6956\-::set\-Enable\-Transition\-Detection ( +\begin{DoxyParamCaption} +\item[{bool}]{transition} +\end{DoxyParamCaption} +)}}\label{classMAX6956_a67b65b80e09a3225dd4f6413bfab2844} +\begin{DoxyVerb}Enable or disable transition detection. Must be reset after every mask read. +\end{DoxyVerb} + +\begin{DoxyParams}{Parameters} +{\em transition} & Boolean value, true enables, false disables transition detection \\ +\hline +\end{DoxyParams} +\begin{DoxySeeAlso}{See Also} +\hyperlink{MAX6956_8h_a5c3d1c00491596887e211bfa630c1b94}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-U\-R\-A\-T\-I\-O\-N} + +\hyperlink{classMAX6956_a56245915d7d4cd8fd34629bd91695147}{get\-Input\-Mask()} + +\hyperlink{classMAX6956_a7ce45652fb0490af0ecb4eaebc230419}{set\-Input\-Mask()} +\end{DoxySeeAlso} + + +Definition at line 162 of file M\-A\-X6956.\-cpp. + +\hypertarget{classMAX6956_a4669dcc0f2f89f8fe73a0fa9b97dae21}{\index{M\-A\-X6956@{M\-A\-X6956}!set\-Global\-Current@{set\-Global\-Current}} +\index{set\-Global\-Current@{set\-Global\-Current}!MAX6956@{M\-A\-X6956}} +\subsubsection[{set\-Global\-Current}]{\setlength{\rightskip}{0pt plus 5cm}void M\-A\-X6956\-::set\-Global\-Current ( +\begin{DoxyParamCaption} +\item[{uint8\-\_\-t}]{current} +\end{DoxyParamCaption} +)}}\label{classMAX6956_a4669dcc0f2f89f8fe73a0fa9b97dae21} +\begin{DoxyVerb}Set current globally +\end{DoxyVerb} + +\begin{DoxyParams}{Parameters} +{\em current} & uint8\-\_\-t 0-\/15, 0 = min, 15 = max brightness \\ +\hline +\end{DoxyParams} +\begin{DoxySeeAlso}{See Also} +\hyperlink{MAX6956_8h_a6a6c2bfe9bfbe4930731829baae7c8f6}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T} +\end{DoxySeeAlso} + + +Definition at line 179 of file M\-A\-X6956.\-cpp. + +\hypertarget{classMAX6956_a7ce45652fb0490af0ecb4eaebc230419}{\index{M\-A\-X6956@{M\-A\-X6956}!set\-Input\-Mask@{set\-Input\-Mask}} +\index{set\-Input\-Mask@{set\-Input\-Mask}!MAX6956@{M\-A\-X6956}} +\subsubsection[{set\-Input\-Mask}]{\setlength{\rightskip}{0pt plus 5cm}void M\-A\-X6956\-::set\-Input\-Mask ( +\begin{DoxyParamCaption} +\item[{uint8\-\_\-t}]{mask} +\end{DoxyParamCaption} +)}}\label{classMAX6956_a7ce45652fb0490af0ecb4eaebc230419} +\begin{DoxyVerb}Set the input mask for which ports to monitor with transition detection +\end{DoxyVerb} + +\begin{DoxyParams}{Parameters} +{\em mask} & 8 bit value. M\-S\-B is ignored. \\ +\hline +\end{DoxyParams} +\begin{DoxySeeAlso}{See Also} +\hyperlink{MAX6956_8h_a4a2b4c395e47e0ec9ef49d3236b8a465}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-D\-E\-T\-E\-C\-T} +\end{DoxySeeAlso} + + +Definition at line 214 of file M\-A\-X6956.\-cpp. + +\hypertarget{classMAX6956_a76a617f3b8982bb3855c5152b480097a}{\index{M\-A\-X6956@{M\-A\-X6956}!set\-Port\-Current@{set\-Port\-Current}} +\index{set\-Port\-Current@{set\-Port\-Current}!MAX6956@{M\-A\-X6956}} +\subsubsection[{set\-Port\-Current}]{\setlength{\rightskip}{0pt plus 5cm}void M\-A\-X6956\-::set\-Port\-Current ( +\begin{DoxyParamCaption} +\item[{uint8\-\_\-t}]{port, } +\item[{uint8\-\_\-t}]{power} +\end{DoxyParamCaption} +)}}\label{classMAX6956_a76a617f3b8982bb3855c5152b480097a} + + +0-\/15 brightness levels. + +\begin{DoxyVerb}Takes an INDIVIDUAL port register address (MAX6956_RA_PORT12, ect) +\end{DoxyVerb} + and sets it to a power level 0-\/15. 0 is min, 15 is max brightness. +\begin{DoxyParams}{Parameters} +{\em port} & Port register address (M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T12, ect) \\ +\hline +{\em power} & 0 is min, 15 is max brightness. \\ +\hline +\end{DoxyParams} + + +Definition at line 404 of file M\-A\-X6956.\-cpp. + +\hypertarget{classMAX6956_a98fa3831a47355fe0856caa74a9cf810}{\index{M\-A\-X6956@{M\-A\-X6956}!set\-Port\-Level@{set\-Port\-Level}} +\index{set\-Port\-Level@{set\-Port\-Level}!MAX6956@{M\-A\-X6956}} +\subsubsection[{set\-Port\-Level}]{\setlength{\rightskip}{0pt plus 5cm}void M\-A\-X6956\-::set\-Port\-Level ( +\begin{DoxyParamCaption} +\item[{uint8\-\_\-t}]{port, } +\item[{uint8\-\_\-t}]{power} +\end{DoxyParamCaption} +)}}\label{classMAX6956_a98fa3831a47355fe0856caa74a9cf810} + + +0 = off, 1-\/15 brightness levels. + +\begin{DoxyVerb}Takes an individual port register address (MAX6956_RA_PORT12, ect) +\end{DoxyVerb} + and sets it to a power scale where 0 = off. +\begin{DoxyParams}{Parameters} +{\em port} & Port register address (M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T12, ect) \\ +\hline +{\em power} & 0 is off, 15 is max brightness. \\ +\hline +\end{DoxyParams} + + +Definition at line 346 of file M\-A\-X6956.\-cpp. + +\hypertarget{classMAX6956_ae10ac505e3857d31ca3823225983a697}{\index{M\-A\-X6956@{M\-A\-X6956}!set\-Power@{set\-Power}} +\index{set\-Power@{set\-Power}!MAX6956@{M\-A\-X6956}} +\subsubsection[{set\-Power}]{\setlength{\rightskip}{0pt plus 5cm}void M\-A\-X6956\-::set\-Power ( +\begin{DoxyParamCaption} +\item[{bool}]{power} +\end{DoxyParamCaption} +)}}\label{classMAX6956_ae10ac505e3857d31ca3823225983a697} +\begin{DoxyVerb}Enable or disable power +\end{DoxyVerb} + +\begin{DoxyParams}{Parameters} +{\em power} & Boolean value, true enables, false disables power \\ +\hline +\end{DoxyParams} +\begin{DoxySeeAlso}{See Also} +\hyperlink{MAX6956_8h_a5c3d1c00491596887e211bfa630c1b94}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-U\-R\-A\-T\-I\-O\-N} +\end{DoxySeeAlso} + + +Definition at line 118 of file M\-A\-X6956.\-cpp. + +\hypertarget{classMAX6956_ad1b4e5cafd91acd2be2b6fb8197afef0}{\index{M\-A\-X6956@{M\-A\-X6956}!set\-Test\-Mode@{set\-Test\-Mode}} +\index{set\-Test\-Mode@{set\-Test\-Mode}!MAX6956@{M\-A\-X6956}} +\subsubsection[{set\-Test\-Mode}]{\setlength{\rightskip}{0pt plus 5cm}void M\-A\-X6956\-::set\-Test\-Mode ( +\begin{DoxyParamCaption} +\item[{bool}]{test} +\end{DoxyParamCaption} +)}}\label{classMAX6956_ad1b4e5cafd91acd2be2b6fb8197afef0} +\begin{DoxyVerb}Enable or disable test mode +\end{DoxyVerb} + +\begin{DoxyParams}{Parameters} +{\em test} & Boolean, true enables, false disables \\ +\hline +\end{DoxyParams} +\begin{DoxySeeAlso}{See Also} +\hyperlink{MAX6956_8h_a709a5193fd2aa9274997dfc22ef73a19}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-D\-I\-S\-P\-L\-A\-Y\-\_\-\-T\-E\-S\-T} +\end{DoxySeeAlso} + + +Definition at line 196 of file M\-A\-X6956.\-cpp. + +\hypertarget{classMAX6956_a60bd352328d77e59a4d51a3c55d38a25}{\index{M\-A\-X6956@{M\-A\-X6956}!test\-Connection@{test\-Connection}} +\index{test\-Connection@{test\-Connection}!MAX6956@{M\-A\-X6956}} +\subsubsection[{test\-Connection}]{\setlength{\rightskip}{0pt plus 5cm}bool M\-A\-X6956\-::test\-Connection ( +\begin{DoxyParamCaption} +{} +\end{DoxyParamCaption} +)}}\label{classMAX6956_a60bd352328d77e59a4d51a3c55d38a25} +Verify the I2\-C connection. Make sure the device is connected and responds as expected. \begin{DoxyReturn}{Returns} +True if connection is valid, false otherwise +\end{DoxyReturn} + + +Definition at line 72 of file M\-A\-X6956.\-cpp. + +\hypertarget{classMAX6956_a993f35d31d1f2489f9d2965c3886f848}{\index{M\-A\-X6956@{M\-A\-X6956}!toggle\-Power@{toggle\-Power}} +\index{toggle\-Power@{toggle\-Power}!MAX6956@{M\-A\-X6956}} +\subsubsection[{toggle\-Power}]{\setlength{\rightskip}{0pt plus 5cm}void M\-A\-X6956\-::toggle\-Power ( +\begin{DoxyParamCaption} +{} +\end{DoxyParamCaption} +)}}\label{classMAX6956_a993f35d31d1f2489f9d2965c3886f848} +\begin{DoxyVerb}Toggle power +\end{DoxyVerb} + \begin{DoxySeeAlso}{See Also} +\hyperlink{MAX6956_8h_a5c3d1c00491596887e211bfa630c1b94}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-U\-R\-A\-T\-I\-O\-N} +\end{DoxySeeAlso} + + +Definition at line 124 of file M\-A\-X6956.\-cpp. + + + +\subsection{Field Documentation} +\hypertarget{classMAX6956_a9f4597436b10ee86a02c96c2b0605851}{\index{M\-A\-X6956@{M\-A\-X6956}!buffer@{buffer}} +\index{buffer@{buffer}!MAX6956@{M\-A\-X6956}} +\subsubsection[{buffer}]{\setlength{\rightskip}{0pt plus 5cm}uint8\-\_\-t M\-A\-X6956\-::buffer\mbox{[}1\mbox{]}\hspace{0.3cm}{\ttfamily [private]}}}\label{classMAX6956_a9f4597436b10ee86a02c96c2b0605851} + + +Buffer for reading data from the device. + + + +Definition at line 556 of file M\-A\-X6956.\-h. + +\hypertarget{classMAX6956_a6ba2f8011914df50d6022ab54b27748d}{\index{M\-A\-X6956@{M\-A\-X6956}!dev\-Addr@{dev\-Addr}} +\index{dev\-Addr@{dev\-Addr}!MAX6956@{M\-A\-X6956}} +\subsubsection[{dev\-Addr}]{\setlength{\rightskip}{0pt plus 5cm}uint8\-\_\-t M\-A\-X6956\-::dev\-Addr\hspace{0.3cm}{\ttfamily [private]}}}\label{classMAX6956_a6ba2f8011914df50d6022ab54b27748d} + + +Holds the current device address. + + + +Definition at line 555 of file M\-A\-X6956.\-h. + +\hypertarget{classMAX6956_a9799e7684546e3e9b24506d436586a09}{\index{M\-A\-X6956@{M\-A\-X6956}!port\-Config@{port\-Config}} +\index{port\-Config@{port\-Config}!MAX6956@{M\-A\-X6956}} +\subsubsection[{port\-Config}]{\setlength{\rightskip}{0pt plus 5cm}uint8\-\_\-t M\-A\-X6956\-::port\-Config\hspace{0.3cm}{\ttfamily [private]}}}\label{classMAX6956_a9799e7684546e3e9b24506d436586a09} + + +Holder for port config bit pair. + + + +Definition at line 557 of file M\-A\-X6956.\-h. + +\hypertarget{classMAX6956_ad3057b6b21ae712acb0129270da63334}{\index{M\-A\-X6956@{M\-A\-X6956}!port\-Current\-Bit@{port\-Current\-Bit}} +\index{port\-Current\-Bit@{port\-Current\-Bit}!MAX6956@{M\-A\-X6956}} +\subsubsection[{port\-Current\-Bit}]{\setlength{\rightskip}{0pt plus 5cm}uint8\-\_\-t M\-A\-X6956\-::port\-Current\-Bit\hspace{0.3cm}{\ttfamily [private]}}}\label{classMAX6956_ad3057b6b21ae712acb0129270da63334} + + +Holder for the current bit offset. + + + +Definition at line 559 of file M\-A\-X6956.\-h. + +\hypertarget{classMAX6956_ab0d382db3afe7930d1b95311bfd90164}{\index{M\-A\-X6956@{M\-A\-X6956}!port\-Current\-R\-A@{port\-Current\-R\-A}} +\index{port\-Current\-R\-A@{port\-Current\-R\-A}!MAX6956@{M\-A\-X6956}} +\subsubsection[{port\-Current\-R\-A}]{\setlength{\rightskip}{0pt plus 5cm}uint8\-\_\-t M\-A\-X6956\-::port\-Current\-R\-A\hspace{0.3cm}{\ttfamily [private]}}}\label{classMAX6956_ab0d382db3afe7930d1b95311bfd90164} + + +Holder for port current register. + + + +Definition at line 558 of file M\-A\-X6956.\-h. + +\hypertarget{classMAX6956_a8b915615042c5ef96fbf3a5c260d4716}{\index{M\-A\-X6956@{M\-A\-X6956}!ports\-Config@{ports\-Config}} +\index{ports\-Config@{ports\-Config}!MAX6956@{M\-A\-X6956}} +\subsubsection[{ports\-Config}]{\setlength{\rightskip}{0pt plus 5cm}uint8\-\_\-t M\-A\-X6956\-::ports\-Config\mbox{[}5\mbox{]}}}\label{classMAX6956_a8b915615042c5ef96fbf3a5c260d4716} +Array that mirrors the configuration of all the ports. + +P12 = ports\-Config\mbox{[}0\mbox{]}\mbox{[}1-\/0\mbox{]} P13 = ports\-Config\mbox{[}0\mbox{]}\mbox{[}3-\/2\mbox{]} P14 = ports\-Config\mbox{[}0\mbox{]}\mbox{[}5-\/4\mbox{]} P15 = ports\-Config\mbox{[}0\mbox{]}\mbox{[}7-\/6\mbox{]} P16 = ports\-Config\mbox{[}1\mbox{]}\mbox{[}1-\/0\mbox{]} P17 = ports\-Config\mbox{[}1\mbox{]}\mbox{[}3-\/2\mbox{]} P18 = ports\-Config\mbox{[}1\mbox{]}\mbox{[}5-\/4\mbox{]} P19 = ports\-Config\mbox{[}1\mbox{]}\mbox{[}7-\/6\mbox{]} P20 = ports\-Config\mbox{[}2\mbox{]}\mbox{[}1-\/0\mbox{]} P21 = ports\-Config\mbox{[}2\mbox{]}\mbox{[}3-\/2\mbox{]} P22 = ports\-Config\mbox{[}2\mbox{]}\mbox{[}5-\/4\mbox{]} P23 = ports\-Config\mbox{[}2\mbox{]}\mbox{[}7-\/6\mbox{]} P24 = ports\-Config\mbox{[}3\mbox{]}\mbox{[}1-\/0\mbox{]} P25 = ports\-Config\mbox{[}3\mbox{]}\mbox{[}3-\/2\mbox{]} P26 = ports\-Config\mbox{[}3\mbox{]}\mbox{[}5-\/4\mbox{]} P27 = ports\-Config\mbox{[}3\mbox{]}\mbox{[}7-\/6\mbox{]} P28 = ports\-Config\mbox{[}4\mbox{]}\mbox{[}1-\/0\mbox{]} P29 = ports\-Config\mbox{[}4\mbox{]}\mbox{[}3-\/2\mbox{]} P30 = ports\-Config\mbox{[}4\mbox{]}\mbox{[}5-\/4\mbox{]} P31 = ports\-Config\mbox{[}4\mbox{]}\mbox{[}7-\/6\mbox{]} + +Definition at line 527 of file M\-A\-X6956.\-h. + +\hypertarget{classMAX6956_ae8da9a65da74dce7eb907319b0198847}{\index{M\-A\-X6956@{M\-A\-X6956}!ports\-Status@{ports\-Status}} +\index{ports\-Status@{ports\-Status}!MAX6956@{M\-A\-X6956}} +\subsubsection[{ports\-Status}]{\setlength{\rightskip}{0pt plus 5cm}uint8\-\_\-t M\-A\-X6956\-::ports\-Status\mbox{[}3\mbox{]}}}\label{classMAX6956_ae8da9a65da74dce7eb907319b0198847} +Array that mirrors the on/off status of all the ports. + +P12 = ports\-Status\mbox{[}0\mbox{]}\mbox{[}0\mbox{]} P13 = ports\-Status\mbox{[}0\mbox{]}\mbox{[}1\mbox{]} P14 = ports\-Status\mbox{[}0\mbox{]}\mbox{[}2\mbox{]} P15 = ports\-Status\mbox{[}0\mbox{]}\mbox{[}3\mbox{]} P16 = ports\-Status\mbox{[}0\mbox{]}\mbox{[}4\mbox{]} P17 = ports\-Status\mbox{[}0\mbox{]}\mbox{[}5\mbox{]} P18 = ports\-Status\mbox{[}0\mbox{]}\mbox{[}6\mbox{]} P19 = ports\-Status\mbox{[}0\mbox{]}\mbox{[}7\mbox{]} P20 = ports\-Status\mbox{[}1\mbox{]}\mbox{[}0\mbox{]} P21 = ports\-Status\mbox{[}1\mbox{]}\mbox{[}1\mbox{]} P22 = ports\-Status\mbox{[}1\mbox{]}\mbox{[}2\mbox{]} P23 = ports\-Status\mbox{[}1\mbox{]}\mbox{[}3\mbox{]} P24 = ports\-Status\mbox{[}1\mbox{]}\mbox{[}4\mbox{]} P25 = ports\-Status\mbox{[}1\mbox{]}\mbox{[}5\mbox{]} P26 = ports\-Status\mbox{[}1\mbox{]}\mbox{[}6\mbox{]} P27 = ports\-Status\mbox{[}1\mbox{]}\mbox{[}7\mbox{]} P28 = ports\-Status\mbox{[}2\mbox{]}\mbox{[}0\mbox{]} P29 = ports\-Status\mbox{[}2\mbox{]}\mbox{[}1\mbox{]} P30 = ports\-Status\mbox{[}2\mbox{]}\mbox{[}2\mbox{]} P31 = ports\-Status\mbox{[}2\mbox{]}\mbox{[}3\mbox{]} + +Definition at line 552 of file M\-A\-X6956.\-h. + +\hypertarget{classMAX6956_a967e25fac00c0ab59be854289eb36353}{\index{M\-A\-X6956@{M\-A\-X6956}!ps\-Array\-Index@{ps\-Array\-Index}} +\index{ps\-Array\-Index@{ps\-Array\-Index}!MAX6956@{M\-A\-X6956}} +\subsubsection[{ps\-Array\-Index}]{\setlength{\rightskip}{0pt plus 5cm}uint8\-\_\-t M\-A\-X6956\-::ps\-Array\-Index\hspace{0.3cm}{\ttfamily [private]}}}\label{classMAX6956_a967e25fac00c0ab59be854289eb36353} + + +array index + + + +Definition at line 560 of file M\-A\-X6956.\-h. + +\hypertarget{classMAX6956_a92b5dc05a1483c49c150db13dcd1f283}{\index{M\-A\-X6956@{M\-A\-X6956}!ps\-Bit\-Position@{ps\-Bit\-Position}} +\index{ps\-Bit\-Position@{ps\-Bit\-Position}!MAX6956@{M\-A\-X6956}} +\subsubsection[{ps\-Bit\-Position}]{\setlength{\rightskip}{0pt plus 5cm}uint8\-\_\-t M\-A\-X6956\-::ps\-Bit\-Position\hspace{0.3cm}{\ttfamily [private]}}}\label{classMAX6956_a92b5dc05a1483c49c150db13dcd1f283} + + +bit position + + + +Definition at line 561 of file M\-A\-X6956.\-h. + + + +The documentation for this class was generated from the following files\-:\begin{DoxyCompactItemize} +\item +\hyperlink{MAX6956_8h}{M\-A\-X6956.\-h}\item +\hyperlink{MAX6956_8cpp}{M\-A\-X6956.\-cpp}\end{DoxyCompactItemize} diff --git a/Arduino/MAX6956/latex/doxygen.sty b/Arduino/MAX6956/latex/doxygen.sty new file mode 100644 index 00000000..199abf8d --- /dev/null +++ b/Arduino/MAX6956/latex/doxygen.sty @@ -0,0 +1,464 @@ +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{doxygen} + +% Packages used by this style file +\RequirePackage{alltt} +\RequirePackage{array} +\RequirePackage{calc} +\RequirePackage{float} +\RequirePackage{ifthen} +\RequirePackage{verbatim} +\RequirePackage[table]{xcolor} +\RequirePackage{xtab} + +%---------- Internal commands used in this style file ---------------- + +\newcommand{\ensurespace}[1]{% + \begingroup% + \setlength{\dimen@}{#1}% + \vskip\z@\@plus\dimen@% + \penalty -100\vskip\z@\@plus -\dimen@% + \vskip\dimen@% + \penalty 9999% + \vskip -\dimen@% + \vskip\z@skip% hide the previous |\vskip| from |\addvspace| + \endgroup% +} + +\newcommand{\DoxyLabelFont}{} +\newcommand{\entrylabel}[1]{% + {% + \parbox[b]{\labelwidth-4pt}{% + \makebox[0pt][l]{\DoxyLabelFont#1}% + \vspace{1.5\baselineskip}% + }% + }% +} + +\newenvironment{DoxyDesc}[1]{% + \ensurespace{4\baselineskip}% + \begin{list}{}{% + \settowidth{\labelwidth}{20pt}% + \setlength{\parsep}{0pt}% + \setlength{\itemsep}{0pt}% + \setlength{\leftmargin}{\labelwidth+\labelsep}% + \renewcommand{\makelabel}{\entrylabel}% + }% + \item[#1]% +}{% + \end{list}% +} + +\newsavebox{\xrefbox} +\newlength{\xreflength} +\newcommand{\xreflabel}[1]{% + \sbox{\xrefbox}{#1}% + \setlength{\xreflength}{\wd\xrefbox}% + \ifthenelse{\xreflength>\labelwidth}{% + \begin{minipage}{\textwidth}% + \setlength{\parindent}{0pt}% + \hangindent=15pt\bfseries #1\vspace{1.2\itemsep}% + \end{minipage}% + }{% + \parbox[b]{\labelwidth}{\makebox[0pt][l]{\textbf{#1}}}% + }% +} + +%---------- Commands used by doxygen LaTeX output generator ---------- + +% Used by
 ... 
+\newenvironment{DoxyPre}{% + \small% + \begin{alltt}% +}{% + \end{alltt}% + \normalsize% +} + +% Used by @code ... @endcode +\newenvironment{DoxyCode}{% + \par% + \scriptsize% + \begin{alltt}% +}{% + \end{alltt}% + \normalsize% +} + +% Used by @example, @include, @includelineno and @dontinclude +\newenvironment{DoxyCodeInclude}{% + \DoxyCode% +}{% + \endDoxyCode% +} + +% Used by @verbatim ... @endverbatim +\newenvironment{DoxyVerb}{% + \footnotesize% + \verbatim% +}{% + \endverbatim% + \normalsize% +} + +% Used by @verbinclude +\newenvironment{DoxyVerbInclude}{% + \DoxyVerb% +}{% + \endDoxyVerb% +} + +% Used by numbered lists (using '-#' or
    ...
) +\newenvironment{DoxyEnumerate}{% + \enumerate% +}{% + \endenumerate% +} + +% Used by bullet lists (using '-', @li, @arg, or
    ...
) +\newenvironment{DoxyItemize}{% + \itemize% +}{% + \enditemize% +} + +% Used by description lists (using
...
) +\newenvironment{DoxyDescription}{% + \description% +}{% + \enddescription% +} + +% Used by @image, @dotfile, @dot ... @enddot, and @msc ... @endmsc +% (only if caption is specified) +\newenvironment{DoxyImage}{% + \begin{figure}[H]% + \begin{center}% +}{% + \end{center}% + \end{figure}% +} + +% Used by @image, @dotfile, @dot ... @enddot, and @msc ... @endmsc +% (only if no caption is specified) +\newenvironment{DoxyImageNoCaption}{% +}{% +} + +% Used by @attention +\newenvironment{DoxyAttention}[1]{% + \begin{DoxyDesc}{#1}% +}{% + \end{DoxyDesc}% +} + +% Used by @author and @authors +\newenvironment{DoxyAuthor}[1]{% + \begin{DoxyDesc}{#1}% +}{% + \end{DoxyDesc}% +} + +% Used by @date +\newenvironment{DoxyDate}[1]{% + \begin{DoxyDesc}{#1}% +}{% + \end{DoxyDesc}% +} + +% Used by @invariant +\newenvironment{DoxyInvariant}[1]{% + \begin{DoxyDesc}{#1}% +}{% + \end{DoxyDesc}% +} + +% Used by @note +\newenvironment{DoxyNote}[1]{% + \begin{DoxyDesc}{#1}% +}{% + \end{DoxyDesc}% +} + +% Used by @post +\newenvironment{DoxyPostcond}[1]{% + \begin{DoxyDesc}{#1}% +}{% + \end{DoxyDesc}% +} + +% Used by @pre +\newenvironment{DoxyPrecond}[1]{% + \begin{DoxyDesc}{#1}% +}{% + \end{DoxyDesc}% +} + +% Used by @copyright +\newenvironment{DoxyCopyright}[1]{% + \begin{DoxyDesc}{#1}% +}{% + \end{DoxyDesc}% +} + +% Used by @remark +\newenvironment{DoxyRemark}[1]{% + \begin{DoxyDesc}{#1}% +}{% + \end{DoxyDesc}% +} + +% Used by @return and @returns +\newenvironment{DoxyReturn}[1]{% + \begin{DoxyDesc}{#1}% +}{% + \end{DoxyDesc}% +} + +% Used by @since +\newenvironment{DoxySince}[1]{% + \begin{DoxyDesc}{#1}% +}{% + \end{DoxyDesc}% +} + +% Used by @see +\newenvironment{DoxySeeAlso}[1]{% + \begin{DoxyDesc}{#1}% +}{% + \end{DoxyDesc}% +} + +% Used by @version +\newenvironment{DoxyVersion}[1]{% + \begin{DoxyDesc}{#1}% +}{% + \end{DoxyDesc}% +} + +% Used by @warning +\newenvironment{DoxyWarning}[1]{% + \begin{DoxyDesc}{#1}% +}{% + \end{DoxyDesc}% +} + +% Used by @internal +\newenvironment{DoxyInternal}[1]{% + \paragraph*{#1}% +}{% +} + +% Used by @par and @paragraph +\newenvironment{DoxyParagraph}[1]{% + \begin{list}{}{% + \settowidth{\labelwidth}{40pt}% + \setlength{\leftmargin}{\labelwidth}% + \setlength{\parsep}{0pt}% + \setlength{\itemsep}{-4pt}% + \renewcommand{\makelabel}{\entrylabel}% + }% + \item[#1]% +}{% + \end{list}% +} + +% Used by parameter lists +\newenvironment{DoxyParams}[2][]{% + \par% + \tabletail{\hline}% + \tablelasttail{\hline}% + \tablefirsthead{}% + \tablehead{}% + \ifthenelse{\equal{#1}{}}% + {\tablefirsthead{\multicolumn{2}{l}{\hspace{-6pt}\bfseries\fontseries{bc}\selectfont\color{darkgray} #2}\\[1ex]}% + \begin{xtabular}{|>{\raggedleft\hspace{0pt}}p{0.15\textwidth}|% + p{0.805\textwidth}|}}% + {\ifthenelse{\equal{#1}{1}}% + {\tablefirsthead{\multicolumn{2}{l}{\hspace{-6pt}\bfseries\fontseries{bc}\selectfont\color{darkgray} #2}\\[1ex]}% + \begin{xtabular}{|>{\centering}p{0.10\textwidth}|% + >{\raggedleft\hspace{0pt}}p{0.15\textwidth}|% + p{0.678\textwidth}|}}% + {\tablefirsthead{\multicolumn{2}{l}{\hspace{-6pt}\bfseries\fontseries{bc}\selectfont\color{darkgray} #2}\\[1ex]}% + \begin{xtabular}{|>{\centering}p{0.10\textwidth}|% + >{\centering\hspace{0pt}}p{0.15\textwidth}|% + >{\raggedleft\hspace{0pt}}p{0.15\textwidth}|% + p{0.501\textwidth}|}}% + }\hline% +}{% + \end{xtabular}% + \tablefirsthead{}% + \vspace{6pt}% +} + +% Used for fields of simple structs +\newenvironment{DoxyFields}[1]{% + \par% + \tabletail{\hline}% + \tablelasttail{\hline}% + \tablehead{}% + \tablefirsthead{\multicolumn{2}{l}{\hspace{-6pt}\bfseries\fontseries{bc}\selectfont\color{darkgray} #1}\\[1ex]}% + \begin{xtabular}{|>{\raggedleft\hspace{0pt}}p{0.15\textwidth}|% + p{0.15\textwidth}|% + p{0.63\textwidth}|}% + \hline% +}{% + \end{xtabular}% + \tablefirsthead{}% + \vspace{6pt}% +} + +% Used for parameters within a detailed function description +\newenvironment{DoxyParamCaption}{% + \renewcommand{\item}[2][]{##1 {\em ##2}}% +}{% +} + +% Used by return value lists +\newenvironment{DoxyRetVals}[1]{% + \par% + \tabletail{\hline}% + \tablelasttail{\hline}% + \tablehead{}% + \tablefirsthead{\multicolumn{2}{l}{\hspace{-6pt}\bfseries\fontseries{bc}\selectfont\color{darkgray} #1}\\[1ex]}% + \begin{xtabular}{|>{\raggedleft\hspace{0pt}}p{0.25\textwidth}|% + p{0.705\textwidth}|}% + \hline% +}{% + \end{xtabular}% + \tablefirsthead{}% + \vspace{6pt}% +} + +% Used by exception lists +\newenvironment{DoxyExceptions}[1]{% + \par% + \tabletail{\hline}% + \tablelasttail{\hline}% + \tablehead{}% + \tablefirsthead{\multicolumn{2}{l}{\hspace{-6pt}\bfseries\fontseries{bc}\selectfont\color{darkgray} #1}\\[1ex]}% + \begin{xtabular}{|>{\raggedleft\hspace{0pt}}p{0.25\textwidth}|% + p{0.705\textwidth}|}% + \hline% +}{% + \end{xtabular}% + \tablefirsthead{}% + \vspace{6pt}% +} + +% Used by template parameter lists +\newenvironment{DoxyTemplParams}[1]{% + \par% + \tabletail{\hline}% + \tablelasttail{\hline}% + \tablehead{}% + \tablefirsthead{\multicolumn{2}{l}{\hspace{-6pt}\bfseries\fontseries{bc}\selectfont\color{darkgray} #1}\\[1ex]}% + \begin{xtabular}{|>{\raggedleft\hspace{0pt}}p{0.25\textwidth}|% + p{0.705\textwidth}|}% + \hline% +}{% + \end{xtabular}% + \tablefirsthead{}% + \vspace{6pt}% +} + +% Used for member lists +\newenvironment{DoxyCompactItemize}{% + \begin{itemize}% + \setlength{\itemsep}{-3pt}% + \setlength{\parsep}{0pt}% + \setlength{\topsep}{0pt}% + \setlength{\partopsep}{0pt}% +}{% + \end{itemize}% +} + +% Used for member descriptions +\newenvironment{DoxyCompactList}{% + \begin{list}{}{% + \setlength{\leftmargin}{0.5cm}% + \setlength{\itemsep}{0pt}% + \setlength{\parsep}{0pt}% + \setlength{\topsep}{0pt}% + \renewcommand{\makelabel}{\hfill}% + }% +}{% + \end{list}% +} + +% Used for reference lists (@bug, @deprecated, @todo, etc.) +\newenvironment{DoxyRefList}{% + \begin{list}{}{% + \setlength{\labelwidth}{10pt}% + \setlength{\leftmargin}{\labelwidth}% + \addtolength{\leftmargin}{\labelsep}% + \renewcommand{\makelabel}{\xreflabel}% + }% +}{% + \end{list}% +} + +% Used by @bug, @deprecated, @todo, etc. +\newenvironment{DoxyRefDesc}[1]{% + \begin{list}{}{% + \renewcommand\makelabel[1]{\textbf{##1}}% + \settowidth\labelwidth{\makelabel{#1}}% + \setlength\leftmargin{\labelwidth+\labelsep}% + }% +}{% + \end{list}% +} + +% Used by parameter lists and simple sections +\newenvironment{Desc} +{\begin{list}{}{% + \settowidth{\labelwidth}{40pt}% + \setlength{\leftmargin}{\labelwidth}% + \setlength{\parsep}{0pt}% + \setlength{\itemsep}{-4pt}% + \renewcommand{\makelabel}{\entrylabel}% + } +}{% + \end{list}% +} + +% Used by tables +\newcommand{\PBS}[1]{\let\temp=\\#1\let\\=\temp}% +\newlength{\tmplength}% +\newenvironment{TabularC}[1]% +{% +\setlength{\tmplength}% + {\linewidth/(#1)-\tabcolsep*2-\arrayrulewidth*(#1+1)/(#1)}% + \par\begin{xtabular*}{\linewidth}% + {*{#1}{|>{\PBS\raggedright\hspace{0pt}}p{\the\tmplength}}|}% +}% +{\end{xtabular*}\par}% + +% Used for member group headers +\newenvironment{Indent}{% + \begin{list}{}{% + \setlength{\leftmargin}{0.5cm}% + }% + \item[]\ignorespaces% +}{% + \unskip% + \end{list}% +} + +% Used when hyperlinks are turned off +\newcommand{\doxyref}[3]{% + \textbf{#1} (\textnormal{#2}\,\pageref{#3})% +} + +% Used for syntax highlighting +\definecolor{comment}{rgb}{0.5,0.0,0.0} +\definecolor{keyword}{rgb}{0.0,0.5,0.0} +\definecolor{keywordtype}{rgb}{0.38,0.25,0.125} +\definecolor{keywordflow}{rgb}{0.88,0.5,0.0} +\definecolor{preprocessor}{rgb}{0.5,0.38,0.125} +\definecolor{stringliteral}{rgb}{0.0,0.125,0.25} +\definecolor{charliteral}{rgb}{0.0,0.5,0.5} +\definecolor{vhdldigit}{rgb}{1.0,0.0,1.0} +\definecolor{vhdlkeyword}{rgb}{0.43,0.0,0.43} +\definecolor{vhdllogic}{rgb}{1.0,0.0,0.0} +\definecolor{vhdlchar}{rgb}{0.0,0.0,0.0} diff --git a/Arduino/MAX6956/latex/files.tex b/Arduino/MAX6956/latex/files.tex new file mode 100644 index 00000000..ccbdd5a2 --- /dev/null +++ b/Arduino/MAX6956/latex/files.tex @@ -0,0 +1,5 @@ +\section{File List} +Here is a list of all files with brief descriptions\-:\begin{DoxyCompactList} +\item\contentsline{section}{\hyperlink{MAX6956_8cpp}{M\-A\-X6956.\-cpp} }{\pageref{MAX6956_8cpp}}{} +\item\contentsline{section}{\hyperlink{MAX6956_8h}{M\-A\-X6956.\-h} }{\pageref{MAX6956_8h}}{} +\end{DoxyCompactList} diff --git a/Arduino/MAX6956/latex/refman.tex b/Arduino/MAX6956/latex/refman.tex new file mode 100644 index 00000000..6cc814ab --- /dev/null +++ b/Arduino/MAX6956/latex/refman.tex @@ -0,0 +1,150 @@ +\documentclass[twoside]{book} + +% Packages required by doxygen +\usepackage{calc} +\usepackage{doxygen} +\usepackage{graphicx} +\usepackage[utf8]{inputenc} +\usepackage{makeidx} +\usepackage{multicol} +\usepackage{multirow} +\usepackage{textcomp} +\usepackage[table]{xcolor} + +% Font selection +\usepackage[T1]{fontenc} +\usepackage{mathptmx} +\usepackage[scaled=.90]{helvet} +\usepackage{courier} +\usepackage{amssymb} +\usepackage{sectsty} +\renewcommand{\familydefault}{\sfdefault} +\allsectionsfont{% + \fontseries{bc}\selectfont% + \color{darkgray}% +} +\renewcommand{\DoxyLabelFont}{% + \fontseries{bc}\selectfont% + \color{darkgray}% +} + +% Page & text layout +\usepackage{geometry} +\geometry{% + a4paper,% + top=2.5cm,% + bottom=2.5cm,% + left=2.5cm,% + right=2.5cm% +} +\tolerance=750 +\hfuzz=15pt +\hbadness=750 +\setlength{\emergencystretch}{15pt} +\setlength{\parindent}{0cm} +\setlength{\parskip}{0.2cm} +\makeatletter +\renewcommand{\paragraph}{% + \@startsection{paragraph}{4}{0ex}{-1.0ex}{1.0ex}{% + \normalfont\normalsize\bfseries\SS@parafont% + }% +} +\renewcommand{\subparagraph}{% + \@startsection{subparagraph}{5}{0ex}{-1.0ex}{1.0ex}{% + \normalfont\normalsize\bfseries\SS@subparafont% + }% +} +\makeatother + +% Headers & footers +\usepackage{fancyhdr} +\pagestyle{fancyplain} +\fancyhead[LE]{\fancyplain{}{\bfseries\thepage}} +\fancyhead[CE]{\fancyplain{}{}} +\fancyhead[RE]{\fancyplain{}{\bfseries\leftmark}} +\fancyhead[LO]{\fancyplain{}{\bfseries\rightmark}} +\fancyhead[CO]{\fancyplain{}{}} +\fancyhead[RO]{\fancyplain{}{\bfseries\thepage}} +\fancyfoot[LE]{\fancyplain{}{}} +\fancyfoot[CE]{\fancyplain{}{}} +\fancyfoot[RE]{\fancyplain{}{\bfseries\scriptsize Generated on Tue Jan 21 2014 23\-:33\-:12 for M\-A\-X6956 by Doxygen }} +\fancyfoot[LO]{\fancyplain{}{\bfseries\scriptsize Generated on Tue Jan 21 2014 23\-:33\-:12 for M\-A\-X6956 by Doxygen }} +\fancyfoot[CO]{\fancyplain{}{}} +\fancyfoot[RO]{\fancyplain{}{}} +\renewcommand{\footrulewidth}{0.4pt} +\renewcommand{\chaptermark}[1]{% + \markboth{#1}{}% +} +\renewcommand{\sectionmark}[1]{% + \markright{\thesection\ #1}% +} + +% Indices & bibliography +\usepackage{natbib} +\usepackage[titles]{tocloft} +\setcounter{tocdepth}{3} +\setcounter{secnumdepth}{5} +\makeindex + +% Hyperlinks (required, but should be loaded last) +\usepackage{ifpdf} +\ifpdf + \usepackage[pdftex,pagebackref=true]{hyperref} +\else + \usepackage[ps2pdf,pagebackref=true]{hyperref} +\fi +\hypersetup{% + colorlinks=true,% + linkcolor=blue,% + citecolor=blue,% + unicode% +} + +% Custom commands +\newcommand{\clearemptydoublepage}{% + \newpage{\pagestyle{empty}\cleardoublepage}% +} + + +%===== C O N T E N T S ===== + +\begin{document} + +% Titlepage & ToC +\hypersetup{pageanchor=false} +\pagenumbering{roman} +\begin{titlepage} +\vspace*{7cm} +\begin{center}% +{\Large M\-A\-X6956 \\[1ex]\large 1.\-0 }\\ +\vspace*{1cm} +{\large Generated by Doxygen 1.8.5}\\ +\vspace*{0.5cm} +{\small Tue Jan 21 2014 23:33:12}\\ +\end{center} +\end{titlepage} +\clearemptydoublepage +\tableofcontents +\clearemptydoublepage +\pagenumbering{arabic} +\hypersetup{pageanchor=true} + +%--- Begin generated contents --- +\chapter{Data Structure Index} +\input{annotated} +\chapter{File Index} +\input{files} +\chapter{Data Structure Documentation} +\input{classMAX6956} +\chapter{File Documentation} +\input{MAX6956_8cpp} +\input{MAX6956_8h} +%--- End generated contents --- + +% Index +\newpage +\phantomsection +\addcontentsline{toc}{part}{Index} +\printindex + +\end{document} From 310ce87a4ece150531ee02660ab1c378813c70a5 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Sun, 7 Dec 2014 18:18:22 +0200 Subject: [PATCH 053/335] Fix source location for MSP430 --- MSP430/AK8975/library.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MSP430/AK8975/library.json b/MSP430/AK8975/library.json index 2e4d1a38..09f3e41a 100644 --- a/MSP430/AK8975/library.json +++ b/MSP430/AK8975/library.json @@ -2,7 +2,7 @@ "name": "I2Cdevlib-AK8975", "keywords": "compass, sensor, i2cdevlib, i2c", "description": "AK8975 is 3-axis electronic compass IC with high sensitive Hall sensor technology", - "include": "Arduino/AK8975", + "include": "MSP430/AK8975", "repository": { "type": "git", From 5207a77bbea781c563f898d34421bfdd54eb6784 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Sun, 7 Dec 2014 19:15:40 +0200 Subject: [PATCH 054/335] Fix source location for MSP430 --- MSP430/MPU6050/library.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MSP430/MPU6050/library.json b/MSP430/MPU6050/library.json index a49379ef..d77b98e4 100644 --- a/MSP430/MPU6050/library.json +++ b/MSP430/MPU6050/library.json @@ -2,7 +2,7 @@ "name": "I2Cdevlib-MPU6050", "keywords": "gyroscope, accelerometer, sensor, i2cdevlib, i2c", "description": "The MPU6050 combines a 3-axis gyroscope and a 3-axis accelerometer on the same silicon die together with an onboard Digital Motion Processor(DMP) which processes complex 6-axis MotionFusion algorithms", - "include": "Arduino/MPU6050", + "include": "MSP430/MPU6050", "repository": { "type": "git", From 0117434affd76512702144a4ab58148becd8cf9f Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Sun, 7 Dec 2014 19:21:27 +0200 Subject: [PATCH 055/335] PlatformIO Library Registry manifest file * This library in Web Registry: http://platformio.ikravets.com/#!/lib/show/113/I2Cdevlib-MPU9150 * Specification: [PlatformIO Library Manager](http://docs.platformio.ikravets.com/en/latest/librarymanager/index.html) * Integration: [IDE Integration](http://docs.platformio.ikravets.com/en/latest/ide.html) --- Arduino/MPU9150/library.json | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 Arduino/MPU9150/library.json diff --git a/Arduino/MPU9150/library.json b/Arduino/MPU9150/library.json new file mode 100644 index 00000000..e8786313 --- /dev/null +++ b/Arduino/MPU9150/library.json @@ -0,0 +1,18 @@ +{ + "name": "I2Cdevlib-MPU9150", + "keywords": "gyroscope, accelerometer, compass, sensor, i2cdevlib, i2c", + "description": "The MPU-9150 is a System in Package (SiP) that combines two chips: the MPU-6050, which contains a 3-axis gyroscope, 3-axis accelerometer, and an onboard Digital Motion Processor(DMP) capable of processing complex MotionFusion algorithms; and the AK8975, a 3-axis digital compass", + "include": "Arduino/MPU9150", + "repository": + { + "type": "git", + "url": "https://github.com/jrowberg/i2cdevlib.git" + }, + "dependencies": + { + "name": "I2Cdevlib-Core", + "frameworks": "arduino" + }, + "frameworks": "arduino", + "platforms": "atmelavr" +} From 17e83392a9aab8e4e0b1f1e03f2ab06d5b0e6265 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Sun, 7 Dec 2014 19:24:06 +0200 Subject: [PATCH 056/335] Shorten description --- Arduino/MPU9150/library.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Arduino/MPU9150/library.json b/Arduino/MPU9150/library.json index e8786313..38cde7e1 100644 --- a/Arduino/MPU9150/library.json +++ b/Arduino/MPU9150/library.json @@ -1,7 +1,7 @@ { "name": "I2Cdevlib-MPU9150", "keywords": "gyroscope, accelerometer, compass, sensor, i2cdevlib, i2c", - "description": "The MPU-9150 is a System in Package (SiP) that combines two chips: the MPU-6050, which contains a 3-axis gyroscope, 3-axis accelerometer, and an onboard Digital Motion Processor(DMP) capable of processing complex MotionFusion algorithms; and the AK8975, a 3-axis digital compass", + "description": "The MPU-9150 combines two chips: the MPU-6050, which contains a 3-axis gyroscope, 3-axis accelerometer and the AK8975, a 3-axis digital compass", "include": "Arduino/MPU9150", "repository": { From 684825577668fb3fa55927375db532f1e4f7771c Mon Sep 17 00:00:00 2001 From: youngchul Date: Sat, 27 Dec 2014 04:59:27 -0600 Subject: [PATCH 057/335] Revert "MAX6956 20 or 28-Port LED Display Driver and I/O Expander" --- Arduino/MAX6956/Doxyfile | 1781 --------- .../MAX6956_LED_FADE/MAX6956_LED_Fade.ino | 61 - Arduino/MAX6956/MAX6956.cpp | 573 --- Arduino/MAX6956/MAX6956.h | 573 --- Arduino/MAX6956/comments.txt | 64 - Arduino/MAX6956/html/MAX6956_8cpp.html | 99 - Arduino/MAX6956/html/MAX6956_8cpp_source.html | 463 --- Arduino/MAX6956/html/MAX6956_8h.html | 3196 ----------------- Arduino/MAX6956/html/MAX6956_8h_source.html | 446 --- Arduino/MAX6956/html/annotated.html | 101 - Arduino/MAX6956/html/bc_s.png | Bin 676 -> 0 bytes Arduino/MAX6956/html/bdwn.png | Bin 147 -> 0 bytes Arduino/MAX6956/html/classMAX6956.html | 1205 ------- Arduino/MAX6956/html/classes.html | 105 - Arduino/MAX6956/html/closed.png | Bin 132 -> 0 bytes Arduino/MAX6956/html/doxygen.css | 1357 ------- Arduino/MAX6956/html/doxygen.png | Bin 3779 -> 0 bytes Arduino/MAX6956/html/dynsections.js | 104 - Arduino/MAX6956/html/files.html | 102 - Arduino/MAX6956/html/ftv2blank.png | Bin 86 -> 0 bytes Arduino/MAX6956/html/ftv2cl.png | Bin 453 -> 0 bytes Arduino/MAX6956/html/ftv2doc.png | Bin 746 -> 0 bytes Arduino/MAX6956/html/ftv2folderclosed.png | Bin 616 -> 0 bytes Arduino/MAX6956/html/ftv2folderopen.png | Bin 597 -> 0 bytes Arduino/MAX6956/html/ftv2lastnode.png | Bin 86 -> 0 bytes Arduino/MAX6956/html/ftv2link.png | Bin 746 -> 0 bytes Arduino/MAX6956/html/ftv2mlastnode.png | Bin 246 -> 0 bytes Arduino/MAX6956/html/ftv2mnode.png | Bin 246 -> 0 bytes Arduino/MAX6956/html/ftv2mo.png | Bin 403 -> 0 bytes Arduino/MAX6956/html/ftv2node.png | Bin 86 -> 0 bytes Arduino/MAX6956/html/ftv2ns.png | Bin 388 -> 0 bytes Arduino/MAX6956/html/ftv2plastnode.png | Bin 229 -> 0 bytes Arduino/MAX6956/html/ftv2pnode.png | Bin 229 -> 0 bytes Arduino/MAX6956/html/ftv2splitbar.png | Bin 314 -> 0 bytes Arduino/MAX6956/html/ftv2vertline.png | Bin 86 -> 0 bytes Arduino/MAX6956/html/functions.html | 266 -- Arduino/MAX6956/html/functions_func.html | 182 - Arduino/MAX6956/html/functions_vars.html | 128 - Arduino/MAX6956/html/globals.html | 611 ---- Arduino/MAX6956/html/globals_defs.html | 611 ---- Arduino/MAX6956/html/index.html | 90 - Arduino/MAX6956/html/installdox | 112 - Arduino/MAX6956/html/jquery.js | 39 - Arduino/MAX6956/html/nav_f.png | Bin 153 -> 0 bytes Arduino/MAX6956/html/nav_g.png | Bin 95 -> 0 bytes Arduino/MAX6956/html/nav_h.png | Bin 98 -> 0 bytes Arduino/MAX6956/html/open.png | Bin 123 -> 0 bytes Arduino/MAX6956/html/search/all_62.html | 26 - Arduino/MAX6956/html/search/all_62.js | 4 - Arduino/MAX6956/html/search/all_63.html | 26 - Arduino/MAX6956/html/search/all_63.js | 6 - Arduino/MAX6956/html/search/all_64.html | 26 - Arduino/MAX6956/html/search/all_64.js | 5 - Arduino/MAX6956/html/search/all_65.html | 26 - Arduino/MAX6956/html/search/all_65.js | 4 - Arduino/MAX6956/html/search/all_67.html | 26 - Arduino/MAX6956/html/search/all_67.js | 10 - Arduino/MAX6956/html/search/all_69.html | 26 - Arduino/MAX6956/html/search/all_69.js | 4 - Arduino/MAX6956/html/search/all_6d.html | 26 - Arduino/MAX6956/html/search/all_6d.js | 174 - Arduino/MAX6956/html/search/all_70.html | 26 - Arduino/MAX6956/html/search/all_70.js | 10 - Arduino/MAX6956/html/search/all_72.html | 26 - Arduino/MAX6956/html/search/all_72.js | 4 - Arduino/MAX6956/html/search/all_73.html | 26 - Arduino/MAX6956/html/search/all_73.js | 13 - Arduino/MAX6956/html/search/all_74.html | 26 - Arduino/MAX6956/html/search/all_74.js | 5 - Arduino/MAX6956/html/search/classes_6d.html | 26 - Arduino/MAX6956/html/search/classes_6d.js | 4 - Arduino/MAX6956/html/search/close.png | Bin 273 -> 0 bytes Arduino/MAX6956/html/search/defines_6d.html | 26 - Arduino/MAX6956/html/search/defines_6d.js | 171 - Arduino/MAX6956/html/search/files_6d.html | 26 - Arduino/MAX6956/html/search/files_6d.js | 5 - Arduino/MAX6956/html/search/functions_63.html | 26 - Arduino/MAX6956/html/search/functions_63.js | 6 - Arduino/MAX6956/html/search/functions_64.html | 26 - Arduino/MAX6956/html/search/functions_64.js | 4 - Arduino/MAX6956/html/search/functions_65.html | 26 - Arduino/MAX6956/html/search/functions_65.js | 4 - Arduino/MAX6956/html/search/functions_67.html | 26 - Arduino/MAX6956/html/search/functions_67.js | 10 - Arduino/MAX6956/html/search/functions_69.html | 26 - Arduino/MAX6956/html/search/functions_69.js | 4 - Arduino/MAX6956/html/search/functions_6d.html | 26 - Arduino/MAX6956/html/search/functions_6d.js | 4 - Arduino/MAX6956/html/search/functions_72.html | 26 - Arduino/MAX6956/html/search/functions_72.js | 4 - Arduino/MAX6956/html/search/functions_73.html | 26 - Arduino/MAX6956/html/search/functions_73.js | 13 - Arduino/MAX6956/html/search/functions_74.html | 26 - Arduino/MAX6956/html/search/functions_74.js | 5 - Arduino/MAX6956/html/search/mag_sel.png | Bin 563 -> 0 bytes Arduino/MAX6956/html/search/nomatches.html | 12 - Arduino/MAX6956/html/search/search.css | 271 -- Arduino/MAX6956/html/search/search.js | 805 ----- Arduino/MAX6956/html/search/search_l.png | Bin 604 -> 0 bytes Arduino/MAX6956/html/search/search_m.png | Bin 158 -> 0 bytes Arduino/MAX6956/html/search/search_r.png | Bin 612 -> 0 bytes Arduino/MAX6956/html/search/variables_62.html | 26 - Arduino/MAX6956/html/search/variables_62.js | 4 - Arduino/MAX6956/html/search/variables_64.html | 26 - Arduino/MAX6956/html/search/variables_64.js | 4 - Arduino/MAX6956/html/search/variables_70.html | 26 - Arduino/MAX6956/html/search/variables_70.js | 10 - Arduino/MAX6956/html/sync_off.png | Bin 853 -> 0 bytes Arduino/MAX6956/html/sync_on.png | Bin 845 -> 0 bytes Arduino/MAX6956/html/tab_a.png | Bin 142 -> 0 bytes Arduino/MAX6956/html/tab_b.png | Bin 169 -> 0 bytes Arduino/MAX6956/html/tab_h.png | Bin 177 -> 0 bytes Arduino/MAX6956/html/tab_s.png | Bin 184 -> 0 bytes Arduino/MAX6956/html/tabs.css | 60 - Arduino/MAX6956/keywords.txt | 71 - Arduino/MAX6956/latex/MAX6956_8cpp.tex | 4 - Arduino/MAX6956/latex/MAX6956_8h.tex | 1937 ---------- Arduino/MAX6956/latex/Makefile | 21 - Arduino/MAX6956/latex/annotated.tex | 4 - Arduino/MAX6956/latex/classMAX6956.tex | 825 ----- Arduino/MAX6956/latex/doxygen.sty | 464 --- Arduino/MAX6956/latex/files.tex | 5 - Arduino/MAX6956/latex/refman.tex | 150 - 123 files changed, 18065 deletions(-) delete mode 100644 Arduino/MAX6956/Doxyfile delete mode 100644 Arduino/MAX6956/Examples/MAX6956_LED_FADE/MAX6956_LED_Fade.ino delete mode 100644 Arduino/MAX6956/MAX6956.cpp delete mode 100644 Arduino/MAX6956/MAX6956.h delete mode 100644 Arduino/MAX6956/comments.txt delete mode 100644 Arduino/MAX6956/html/MAX6956_8cpp.html delete mode 100644 Arduino/MAX6956/html/MAX6956_8cpp_source.html delete mode 100644 Arduino/MAX6956/html/MAX6956_8h.html delete mode 100644 Arduino/MAX6956/html/MAX6956_8h_source.html delete mode 100644 Arduino/MAX6956/html/annotated.html delete mode 100644 Arduino/MAX6956/html/bc_s.png delete mode 100644 Arduino/MAX6956/html/bdwn.png delete mode 100644 Arduino/MAX6956/html/classMAX6956.html delete mode 100644 Arduino/MAX6956/html/classes.html delete mode 100644 Arduino/MAX6956/html/closed.png delete mode 100644 Arduino/MAX6956/html/doxygen.css delete mode 100644 Arduino/MAX6956/html/doxygen.png delete mode 100644 Arduino/MAX6956/html/dynsections.js delete mode 100644 Arduino/MAX6956/html/files.html delete mode 100644 Arduino/MAX6956/html/ftv2blank.png delete mode 100644 Arduino/MAX6956/html/ftv2cl.png delete mode 100644 Arduino/MAX6956/html/ftv2doc.png delete mode 100644 Arduino/MAX6956/html/ftv2folderclosed.png delete mode 100644 Arduino/MAX6956/html/ftv2folderopen.png delete mode 100644 Arduino/MAX6956/html/ftv2lastnode.png delete mode 100644 Arduino/MAX6956/html/ftv2link.png delete mode 100644 Arduino/MAX6956/html/ftv2mlastnode.png delete mode 100644 Arduino/MAX6956/html/ftv2mnode.png delete mode 100644 Arduino/MAX6956/html/ftv2mo.png delete mode 100644 Arduino/MAX6956/html/ftv2node.png delete mode 100644 Arduino/MAX6956/html/ftv2ns.png delete mode 100644 Arduino/MAX6956/html/ftv2plastnode.png delete mode 100644 Arduino/MAX6956/html/ftv2pnode.png delete mode 100644 Arduino/MAX6956/html/ftv2splitbar.png delete mode 100644 Arduino/MAX6956/html/ftv2vertline.png delete mode 100644 Arduino/MAX6956/html/functions.html delete mode 100644 Arduino/MAX6956/html/functions_func.html delete mode 100644 Arduino/MAX6956/html/functions_vars.html delete mode 100644 Arduino/MAX6956/html/globals.html delete mode 100644 Arduino/MAX6956/html/globals_defs.html delete mode 100644 Arduino/MAX6956/html/index.html delete mode 100755 Arduino/MAX6956/html/installdox delete mode 100644 Arduino/MAX6956/html/jquery.js delete mode 100644 Arduino/MAX6956/html/nav_f.png delete mode 100644 Arduino/MAX6956/html/nav_g.png delete mode 100644 Arduino/MAX6956/html/nav_h.png delete mode 100644 Arduino/MAX6956/html/open.png delete mode 100644 Arduino/MAX6956/html/search/all_62.html delete mode 100644 Arduino/MAX6956/html/search/all_62.js delete mode 100644 Arduino/MAX6956/html/search/all_63.html delete mode 100644 Arduino/MAX6956/html/search/all_63.js delete mode 100644 Arduino/MAX6956/html/search/all_64.html delete mode 100644 Arduino/MAX6956/html/search/all_64.js delete mode 100644 Arduino/MAX6956/html/search/all_65.html delete mode 100644 Arduino/MAX6956/html/search/all_65.js delete mode 100644 Arduino/MAX6956/html/search/all_67.html delete mode 100644 Arduino/MAX6956/html/search/all_67.js delete mode 100644 Arduino/MAX6956/html/search/all_69.html delete mode 100644 Arduino/MAX6956/html/search/all_69.js delete mode 100644 Arduino/MAX6956/html/search/all_6d.html delete mode 100644 Arduino/MAX6956/html/search/all_6d.js delete mode 100644 Arduino/MAX6956/html/search/all_70.html delete mode 100644 Arduino/MAX6956/html/search/all_70.js delete mode 100644 Arduino/MAX6956/html/search/all_72.html delete mode 100644 Arduino/MAX6956/html/search/all_72.js delete mode 100644 Arduino/MAX6956/html/search/all_73.html delete mode 100644 Arduino/MAX6956/html/search/all_73.js delete mode 100644 Arduino/MAX6956/html/search/all_74.html delete mode 100644 Arduino/MAX6956/html/search/all_74.js delete mode 100644 Arduino/MAX6956/html/search/classes_6d.html delete mode 100644 Arduino/MAX6956/html/search/classes_6d.js delete mode 100644 Arduino/MAX6956/html/search/close.png delete mode 100644 Arduino/MAX6956/html/search/defines_6d.html delete mode 100644 Arduino/MAX6956/html/search/defines_6d.js delete mode 100644 Arduino/MAX6956/html/search/files_6d.html delete mode 100644 Arduino/MAX6956/html/search/files_6d.js delete mode 100644 Arduino/MAX6956/html/search/functions_63.html delete mode 100644 Arduino/MAX6956/html/search/functions_63.js delete mode 100644 Arduino/MAX6956/html/search/functions_64.html delete mode 100644 Arduino/MAX6956/html/search/functions_64.js delete mode 100644 Arduino/MAX6956/html/search/functions_65.html delete mode 100644 Arduino/MAX6956/html/search/functions_65.js delete mode 100644 Arduino/MAX6956/html/search/functions_67.html delete mode 100644 Arduino/MAX6956/html/search/functions_67.js delete mode 100644 Arduino/MAX6956/html/search/functions_69.html delete mode 100644 Arduino/MAX6956/html/search/functions_69.js delete mode 100644 Arduino/MAX6956/html/search/functions_6d.html delete mode 100644 Arduino/MAX6956/html/search/functions_6d.js delete mode 100644 Arduino/MAX6956/html/search/functions_72.html delete mode 100644 Arduino/MAX6956/html/search/functions_72.js delete mode 100644 Arduino/MAX6956/html/search/functions_73.html delete mode 100644 Arduino/MAX6956/html/search/functions_73.js delete mode 100644 Arduino/MAX6956/html/search/functions_74.html delete mode 100644 Arduino/MAX6956/html/search/functions_74.js delete mode 100644 Arduino/MAX6956/html/search/mag_sel.png delete mode 100644 Arduino/MAX6956/html/search/nomatches.html delete mode 100644 Arduino/MAX6956/html/search/search.css delete mode 100644 Arduino/MAX6956/html/search/search.js delete mode 100644 Arduino/MAX6956/html/search/search_l.png delete mode 100644 Arduino/MAX6956/html/search/search_m.png delete mode 100644 Arduino/MAX6956/html/search/search_r.png delete mode 100644 Arduino/MAX6956/html/search/variables_62.html delete mode 100644 Arduino/MAX6956/html/search/variables_62.js delete mode 100644 Arduino/MAX6956/html/search/variables_64.html delete mode 100644 Arduino/MAX6956/html/search/variables_64.js delete mode 100644 Arduino/MAX6956/html/search/variables_70.html delete mode 100644 Arduino/MAX6956/html/search/variables_70.js delete mode 100644 Arduino/MAX6956/html/sync_off.png delete mode 100644 Arduino/MAX6956/html/sync_on.png delete mode 100644 Arduino/MAX6956/html/tab_a.png delete mode 100644 Arduino/MAX6956/html/tab_b.png delete mode 100644 Arduino/MAX6956/html/tab_h.png delete mode 100644 Arduino/MAX6956/html/tab_s.png delete mode 100644 Arduino/MAX6956/html/tabs.css delete mode 100755 Arduino/MAX6956/keywords.txt delete mode 100644 Arduino/MAX6956/latex/MAX6956_8cpp.tex delete mode 100644 Arduino/MAX6956/latex/MAX6956_8h.tex delete mode 100644 Arduino/MAX6956/latex/Makefile delete mode 100644 Arduino/MAX6956/latex/annotated.tex delete mode 100644 Arduino/MAX6956/latex/classMAX6956.tex delete mode 100644 Arduino/MAX6956/latex/doxygen.sty delete mode 100644 Arduino/MAX6956/latex/files.tex delete mode 100644 Arduino/MAX6956/latex/refman.tex diff --git a/Arduino/MAX6956/Doxyfile b/Arduino/MAX6956/Doxyfile deleted file mode 100644 index 3dc611cf..00000000 --- a/Arduino/MAX6956/Doxyfile +++ /dev/null @@ -1,1781 +0,0 @@ -# Doxyfile 1.7.6.1 - -# This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project. -# -# All text after a hash (#) is considered a comment and will be ignored. -# The format is: -# TAG = value [value, ...] -# For lists items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (" "). - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- - -# This tag specifies the encoding used for all characters in the config file -# that follow. The default is UTF-8 which is also the encoding used for all -# text before the first occurrence of this tag. Doxygen uses libiconv (or the -# iconv built into libc) for the transcoding. See -# http://www.gnu.org/software/libiconv for the list of possible encodings. - -DOXYFILE_ENCODING = UTF-8 - -# The PROJECT_NAME tag is a single word (or sequence of words) that should -# identify the project. Note that if you do not use Doxywizard you need -# to put quotes around the project name if it contains spaces. - -PROJECT_NAME = "MAX6956" - -# The PROJECT_NUMBER tag can be used to enter a project or revision number. -# This could be handy for archiving the generated documentation or -# if some version control system is used. - -PROJECT_NUMBER = 1.0 - -# Using the PROJECT_BRIEF tag one can provide an optional one line description -# for a project that appears at the top of each page and should give viewer -# a quick idea about the purpose of the project. Keep the description short. - -PROJECT_BRIEF = MAX6956 i2C library - -# With the PROJECT_LOGO tag one can specify an logo or icon that is -# included in the documentation. The maximum height of the logo should not -# exceed 55 pixels and the maximum width should not exceed 200 pixels. -# Doxygen will copy the logo to the output directory. - -PROJECT_LOGO = - -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) -# base path where the generated documentation will be put. -# If a relative path is entered, it will be relative to the location -# where doxygen was started. If left blank the current directory will be used. - -OUTPUT_DIRECTORY = - -# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create -# 4096 sub-directories (in 2 levels) under the output directory of each output -# format and will distribute the generated files over these directories. -# Enabling this option can be useful when feeding doxygen a huge amount of -# source files, where putting all generated files in the same directory would -# otherwise cause performance problems for the file system. - -CREATE_SUBDIRS = NO - -# The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all constant output in the proper language. -# The default language is English, other supported languages are: -# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, -# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, -# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English -# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, -# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, -# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. - -OUTPUT_LANGUAGE = English - -# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will -# include brief member descriptions after the members that are listed in -# the file and class documentation (similar to JavaDoc). -# Set to NO to disable this. - -BRIEF_MEMBER_DESC = YES - -# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend -# the brief description of a member or function before the detailed description. -# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the -# brief descriptions will be completely suppressed. - -REPEAT_BRIEF = YES - -# This tag implements a quasi-intelligent brief description abbreviator -# that is used to form the text in various listings. Each string -# in this list, if found as the leading text of the brief description, will be -# stripped from the text and the result after processing the whole list, is -# used as the annotated text. Otherwise, the brief description is used as-is. -# If left blank, the following values are used ("$name" is automatically -# replaced with the name of the entity): "The $name class" "The $name widget" -# "The $name file" "is" "provides" "specifies" "contains" -# "represents" "a" "an" "the" - -ABBREVIATE_BRIEF = - -# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# Doxygen will generate a detailed section even if there is only a brief -# description. - -ALWAYS_DETAILED_SEC = NO - -# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all -# inherited members of a class in the documentation of that class as if those -# members were ordinary class members. Constructors, destructors and assignment -# operators of the base classes will not be shown. - -INLINE_INHERITED_MEMB = NO - -# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full -# path before files name in the file list and in the header files. If set -# to NO the shortest path that makes the file name unique will be used. - -FULL_PATH_NAMES = YES - -# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag -# can be used to strip a user-defined part of the path. Stripping is -# only done if one of the specified strings matches the left-hand part of -# the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which doxygen is run is used as the -# path to strip. - -STRIP_FROM_PATH = - -# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of -# the path mentioned in the documentation of a class, which tells -# the reader which header file to include in order to use a class. -# If left blank only the name of the header file containing the class -# definition is used. Otherwise one should specify the include paths that -# are normally passed to the compiler using the -I flag. - -STRIP_FROM_INC_PATH = - -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter -# (but less readable) file names. This can be useful if your file system -# doesn't support long names like on DOS, Mac, or CD-ROM. - -SHORT_NAMES = NO - -# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen -# will interpret the first line (until the first dot) of a JavaDoc-style -# comment as the brief description. If set to NO, the JavaDoc -# comments will behave just like regular Qt-style comments -# (thus requiring an explicit @brief command for a brief description.) - -JAVADOC_AUTOBRIEF = NO - -# If the QT_AUTOBRIEF tag is set to YES then Doxygen will -# interpret the first line (until the first dot) of a Qt-style -# comment as the brief description. If set to NO, the comments -# will behave just like regular Qt-style comments (thus requiring -# an explicit \brief command for a brief description.) - -QT_AUTOBRIEF = NO - -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen -# treat a multi-line C++ special comment block (i.e. a block of //! or /// -# comments) as a brief description. This used to be the default behaviour. -# The new default is to treat a multi-line C++ comment block as a detailed -# description. Set this tag to YES if you prefer the old behaviour instead. - -MULTILINE_CPP_IS_BRIEF = NO - -# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented -# member inherits the documentation from any documented member that it -# re-implements. - -INHERIT_DOCS = YES - -# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce -# a new page for each member. If set to NO, the documentation of a member will -# be part of the file/class/namespace that contains it. - -SEPARATE_MEMBER_PAGES = NO - -# The TAB_SIZE tag can be used to set the number of spaces in a tab. -# Doxygen uses this value to replace tabs by spaces in code fragments. - -TAB_SIZE = 4 - -# This tag can be used to specify a number of aliases that acts -# as commands in the documentation. An alias has the form "name=value". -# For example adding "sideeffect=\par Side Effects:\n" will allow you to -# put the command \sideeffect (or @sideeffect) in the documentation, which -# will result in a user-defined paragraph with heading "Side Effects:". -# You can put \n's in the value part of an alias to insert newlines. - -ALIASES = - -# This tag can be used to specify a number of word-keyword mappings (TCL only). -# A mapping has the form "name=value". For example adding -# "class=itcl::class" will allow you to use the command class in the -# itcl::class meaning. - -TCL_SUBST = - -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C -# sources only. Doxygen will then generate output that is more tailored for C. -# For instance, some of the names that are used will be different. The list -# of all members will be omitted, etc. - -OPTIMIZE_OUTPUT_FOR_C = YES - -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java -# sources only. Doxygen will then generate output that is more tailored for -# Java. For instance, namespaces will be presented as packages, qualified -# scopes will look different, etc. - -OPTIMIZE_OUTPUT_JAVA = NO - -# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran -# sources only. Doxygen will then generate output that is more tailored for -# Fortran. - -OPTIMIZE_FOR_FORTRAN = NO - -# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL -# sources. Doxygen will then generate output that is tailored for -# VHDL. - -OPTIMIZE_OUTPUT_VHDL = NO - -# Doxygen selects the parser to use depending on the extension of the files it -# parses. With this tag you can assign which parser to use for a given extension. -# Doxygen has a built-in mapping, but you can override or extend it using this -# tag. The format is ext=language, where ext is a file extension, and language -# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, -# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make -# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C -# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions -# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. - -EXTENSION_MAPPING = - -# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want -# to include (a tag file for) the STL sources as input, then you should -# set this tag to YES in order to let doxygen match functions declarations and -# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. -# func(std::string) {}). This also makes the inheritance and collaboration -# diagrams that involve STL classes more complete and accurate. - -BUILTIN_STL_SUPPORT = NO - -# If you use Microsoft's C++/CLI language, you should set this option to YES to -# enable parsing support. - -CPP_CLI_SUPPORT = NO - -# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. -# Doxygen will parse them like normal C++ but will assume all classes use public -# instead of private inheritance when no explicit protection keyword is present. - -SIP_SUPPORT = NO - -# For Microsoft's IDL there are propget and propput attributes to indicate getter -# and setter methods for a property. Setting this option to YES (the default) -# will make doxygen replace the get and set methods by a property in the -# documentation. This will only work if the methods are indeed getting or -# setting a simple type. If this is not the case, or you want to show the -# methods anyway, you should set this option to NO. - -IDL_PROPERTY_SUPPORT = YES - -# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES, then doxygen will reuse the documentation of the first -# member in the group (if any) for the other members of the group. By default -# all members of a group must be documented explicitly. - -DISTRIBUTE_GROUP_DOC = NO - -# Set the SUBGROUPING tag to YES (the default) to allow class member groups of -# the same type (for instance a group of public functions) to be put as a -# subgroup of that type (e.g. under the Public Functions section). Set it to -# NO to prevent subgrouping. Alternatively, this can be done per class using -# the \nosubgrouping command. - -SUBGROUPING = YES - -# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and -# unions are shown inside the group in which they are included (e.g. using -# @ingroup) instead of on a separate page (for HTML and Man pages) or -# section (for LaTeX and RTF). - -INLINE_GROUPED_CLASSES = NO - -# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and -# unions with only public data fields will be shown inline in the documentation -# of the scope in which they are defined (i.e. file, namespace, or group -# documentation), provided this scope is documented. If set to NO (the default), -# structs, classes, and unions are shown on a separate page (for HTML and Man -# pages) or section (for LaTeX and RTF). - -INLINE_SIMPLE_STRUCTS = NO - -# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum -# is documented as struct, union, or enum with the name of the typedef. So -# typedef struct TypeS {} TypeT, will appear in the documentation as a struct -# with name TypeT. When disabled the typedef will appear as a member of a file, -# namespace, or class. And the struct will be named TypeS. This can typically -# be useful for C code in case the coding convention dictates that all compound -# types are typedef'ed and only the typedef is referenced, never the tag name. - -TYPEDEF_HIDES_STRUCT = NO - -# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to -# determine which symbols to keep in memory and which to flush to disk. -# When the cache is full, less often used symbols will be written to disk. -# For small to medium size projects (<1000 input files) the default value is -# probably good enough. For larger projects a too small cache size can cause -# doxygen to be busy swapping symbols to and from disk most of the time -# causing a significant performance penalty. -# If the system has enough physical memory increasing the cache will improve the -# performance by keeping more symbols in memory. Note that the value works on -# a logarithmic scale so increasing the size by one will roughly double the -# memory usage. The cache size is given by this formula: -# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, -# corresponding to a cache size of 2^16 = 65536 symbols. - -SYMBOL_CACHE_SIZE = 0 - -# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be -# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given -# their name and scope. Since this can be an expensive process and often the -# same symbol appear multiple times in the code, doxygen keeps a cache of -# pre-resolved symbols. If the cache is too small doxygen will become slower. -# If the cache is too large, memory is wasted. The cache size is given by this -# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0, -# corresponding to a cache size of 2^16 = 65536 symbols. - -LOOKUP_CACHE_SIZE = 0 - -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- - -# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in -# documentation are documented, even if no documentation was available. -# Private class members and static file members will be hidden unless -# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES - -EXTRACT_ALL = YES - -# If the EXTRACT_PRIVATE tag is set to YES all private members of a class -# will be included in the documentation. - -EXTRACT_PRIVATE = YES - -# If the EXTRACT_STATIC tag is set to YES all static members of a file -# will be included in the documentation. - -EXTRACT_STATIC = YES - -# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) -# defined locally in source files will be included in the documentation. -# If set to NO only classes defined in header files are included. - -EXTRACT_LOCAL_CLASSES = YES - -# This flag is only useful for Objective-C code. When set to YES local -# methods, which are defined in the implementation section but not in -# the interface are included in the documentation. -# If set to NO (the default) only methods in the interface are included. - -EXTRACT_LOCAL_METHODS = NO - -# If this flag is set to YES, the members of anonymous namespaces will be -# extracted and appear in the documentation as a namespace called -# 'anonymous_namespace{file}', where file will be replaced with the base -# name of the file that contains the anonymous namespace. By default -# anonymous namespaces are hidden. - -EXTRACT_ANON_NSPACES = NO - -# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all -# undocumented members of documented classes, files or namespaces. -# If set to NO (the default) these members will be included in the -# various overviews, but no documentation section is generated. -# This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_MEMBERS = NO - -# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. -# If set to NO (the default) these classes will be included in the various -# overviews. This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_CLASSES = NO - -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all -# friend (class|struct|union) declarations. -# If set to NO (the default) these declarations will be included in the -# documentation. - -HIDE_FRIEND_COMPOUNDS = NO - -# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any -# documentation blocks found inside the body of a function. -# If set to NO (the default) these blocks will be appended to the -# function's detailed documentation block. - -HIDE_IN_BODY_DOCS = NO - -# The INTERNAL_DOCS tag determines if documentation -# that is typed after a \internal command is included. If the tag is set -# to NO (the default) then the documentation will be excluded. -# Set it to YES to include the internal documentation. - -INTERNAL_DOCS = NO - -# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate -# file names in lower-case letters. If set to YES upper-case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows -# and Mac users are advised to set this option to NO. - -CASE_SENSE_NAMES = YES - -# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen -# will show members with their full class and namespace scopes in the -# documentation. If set to YES the scope will be hidden. - -HIDE_SCOPE_NAMES = NO - -# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen -# will put a list of the files that are included by a file in the documentation -# of that file. - -SHOW_INCLUDE_FILES = YES - -# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen -# will list include files with double quotes in the documentation -# rather than with sharp brackets. - -FORCE_LOCAL_INCLUDES = NO - -# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] -# is inserted in the documentation for inline members. - -INLINE_INFO = YES - -# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen -# will sort the (detailed) documentation of file and class members -# alphabetically by member name. If set to NO the members will appear in -# declaration order. - -SORT_MEMBER_DOCS = YES - -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the -# brief documentation of file, namespace and class members alphabetically -# by member name. If set to NO (the default) the members will appear in -# declaration order. - -SORT_BRIEF_DOCS = NO - -# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen -# will sort the (brief and detailed) documentation of class members so that -# constructors and destructors are listed first. If set to NO (the default) -# the constructors will appear in the respective orders defined by -# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. -# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO -# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. - -SORT_MEMBERS_CTORS_1ST = NO - -# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the -# hierarchy of group names into alphabetical order. If set to NO (the default) -# the group names will appear in their defined order. - -SORT_GROUP_NAMES = NO - -# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be -# sorted by fully-qualified names, including namespaces. If set to -# NO (the default), the class list will be sorted only by class name, -# not including the namespace part. -# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. -# Note: This option applies only to the class list, not to the -# alphabetical list. - -SORT_BY_SCOPE_NAME = NO - -# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to -# do proper type resolution of all parameters of a function it will reject a -# match between the prototype and the implementation of a member function even -# if there is only one candidate or it is obvious which candidate to choose -# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen -# will still accept a match between prototype and implementation in such cases. - -STRICT_PROTO_MATCHING = NO - -# The GENERATE_TODOLIST tag can be used to enable (YES) or -# disable (NO) the todo list. This list is created by putting \todo -# commands in the documentation. - -GENERATE_TODOLIST = YES - -# The GENERATE_TESTLIST tag can be used to enable (YES) or -# disable (NO) the test list. This list is created by putting \test -# commands in the documentation. - -GENERATE_TESTLIST = YES - -# The GENERATE_BUGLIST tag can be used to enable (YES) or -# disable (NO) the bug list. This list is created by putting \bug -# commands in the documentation. - -GENERATE_BUGLIST = YES - -# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or -# disable (NO) the deprecated list. This list is created by putting -# \deprecated commands in the documentation. - -GENERATE_DEPRECATEDLIST= YES - -# The ENABLED_SECTIONS tag can be used to enable conditional -# documentation sections, marked by \if sectionname ... \endif. - -ENABLED_SECTIONS = - -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines -# the initial value of a variable or macro consists of for it to appear in -# the documentation. If the initializer consists of more lines than specified -# here it will be hidden. Use a value of 0 to hide initializers completely. -# The appearance of the initializer of individual variables and macros in the -# documentation can be controlled using \showinitializer or \hideinitializer -# command in the documentation regardless of this setting. - -MAX_INITIALIZER_LINES = 30 - -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated -# at the bottom of the documentation of classes and structs. If set to YES the -# list will mention the files that were used to generate the documentation. - -SHOW_USED_FILES = YES - -# If the sources in your project are distributed over multiple directories -# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy -# in the documentation. The default is NO. - -SHOW_DIRECTORIES = NO - -# Set the SHOW_FILES tag to NO to disable the generation of the Files page. -# This will remove the Files entry from the Quick Index and from the -# Folder Tree View (if specified). The default is YES. - -SHOW_FILES = YES - -# Set the SHOW_NAMESPACES tag to NO to disable the generation of the -# Namespaces page. -# This will remove the Namespaces entry from the Quick Index -# and from the Folder Tree View (if specified). The default is YES. - -SHOW_NAMESPACES = YES - -# The FILE_VERSION_FILTER tag can be used to specify a program or script that -# doxygen should invoke to get the current version for each file (typically from -# the version control system). Doxygen will invoke the program by executing (via -# popen()) the command , where is the value of -# the FILE_VERSION_FILTER tag, and is the name of an input file -# provided by doxygen. Whatever the program writes to standard output -# is used as the file version. See the manual for examples. - -FILE_VERSION_FILTER = - -# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed -# by doxygen. The layout file controls the global structure of the generated -# output files in an output format independent way. The create the layout file -# that represents doxygen's defaults, run doxygen with the -l option. -# You can optionally specify a file name after the option, if omitted -# DoxygenLayout.xml will be used as the name of the layout file. - -LAYOUT_FILE = - -# The CITE_BIB_FILES tag can be used to specify one or more bib files -# containing the references data. This must be a list of .bib files. The -# .bib extension is automatically appended if omitted. Using this command -# requires the bibtex tool to be installed. See also -# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style -# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this -# feature you need bibtex and perl available in the search path. - -CITE_BIB_FILES = - -#--------------------------------------------------------------------------- -# configuration options related to warning and progress messages -#--------------------------------------------------------------------------- - -# The QUIET tag can be used to turn on/off the messages that are generated -# by doxygen. Possible values are YES and NO. If left blank NO is used. - -QUIET = NO - -# The WARNINGS tag can be used to turn on/off the warning messages that are -# generated by doxygen. Possible values are YES and NO. If left blank -# NO is used. - -WARNINGS = YES - -# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings -# for undocumented members. If EXTRACT_ALL is set to YES then this flag will -# automatically be disabled. - -WARN_IF_UNDOCUMENTED = YES - -# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some -# parameters in a documented function, or documenting parameters that -# don't exist or using markup commands wrongly. - -WARN_IF_DOC_ERROR = YES - -# The WARN_NO_PARAMDOC option can be enabled to get warnings for -# functions that are documented, but have no documentation for their parameters -# or return value. If set to NO (the default) doxygen will only warn about -# wrong or incomplete parameter documentation, but not about the absence of -# documentation. - -WARN_NO_PARAMDOC = NO - -# The WARN_FORMAT tag determines the format of the warning messages that -# doxygen can produce. The string should contain the $file, $line, and $text -# tags, which will be replaced by the file and line number from which the -# warning originated and the warning text. Optionally the format may contain -# $version, which will be replaced by the version of the file (if it could -# be obtained via FILE_VERSION_FILTER) - -WARN_FORMAT = "$file:$line: $text" - -# The WARN_LOGFILE tag can be used to specify a file to which warning -# and error messages should be written. If left blank the output is written -# to stderr. - -WARN_LOGFILE = doxyerrors.log - -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- - -# The INPUT tag can be used to specify the files and/or directories that contain -# documented source files. You may enter file names like "myfile.cpp" or -# directories like "/usr/src/myproject". Separate the files or directories -# with spaces. - -INPUT = - -# This tag can be used to specify the character encoding of the source files -# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is -# also the default input encoding. Doxygen uses libiconv (or the iconv built -# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for -# the list of possible encodings. - -INPUT_ENCODING = UTF-8 - -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank the following patterns are tested: -# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh -# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py -# *.f90 *.f *.for *.vhd *.vhdl - -FILE_PATTERNS = - -# The RECURSIVE tag can be used to turn specify whether or not subdirectories -# should be searched for input files as well. Possible values are YES and NO. -# If left blank NO is used. - -RECURSIVE = YES - -# The EXCLUDE tag can be used to specify files and/or directories that should be -# excluded from the INPUT source files. This way you can easily exclude a -# subdirectory from a directory tree whose root is specified with the INPUT tag. -# Note that relative paths are relative to the directory from which doxygen is -# run. - -EXCLUDE = - -# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or -# directories that are symbolic links (a Unix file system feature) are excluded -# from the input. - -EXCLUDE_SYMLINKS = NO - -# If the value of the INPUT tag contains directories, you can use the -# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. Note that the wildcards are matched -# against the file with absolute path, so to exclude all test directories -# for example use the pattern */test/* - -EXCLUDE_PATTERNS = - -# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names -# (namespaces, classes, functions, etc.) that should be excluded from the -# output. The symbol name can be a fully qualified name, a word, or if the -# wildcard * is used, a substring. Examples: ANamespace, AClass, -# AClass::ANamespace, ANamespace::*Test - -EXCLUDE_SYMBOLS = - -# The EXAMPLE_PATH tag can be used to specify one or more files or -# directories that contain example code fragments that are included (see -# the \include command). - -EXAMPLE_PATH = - -# If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank all files are included. - -EXAMPLE_PATTERNS = - -# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude -# commands irrespective of the value of the RECURSIVE tag. -# Possible values are YES and NO. If left blank NO is used. - -EXAMPLE_RECURSIVE = NO - -# The IMAGE_PATH tag can be used to specify one or more files or -# directories that contain image that are included in the documentation (see -# the \image command). - -IMAGE_PATH = - -# The INPUT_FILTER tag can be used to specify a program that doxygen should -# invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command , where -# is the value of the INPUT_FILTER tag, and is the name of an -# input file. Doxygen will then use the output that the filter program writes -# to standard output. -# If FILTER_PATTERNS is specified, this tag will be -# ignored. - -INPUT_FILTER = - -# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern -# basis. -# Doxygen will compare the file name with each pattern and apply the -# filter if there is a match. -# The filters are a list of the form: -# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further -# info on how filters are used. If FILTER_PATTERNS is empty or if -# non of the patterns match the file name, INPUT_FILTER is applied. - -FILTER_PATTERNS = - -# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will be used to filter the input files when producing source -# files to browse (i.e. when SOURCE_BROWSER is set to YES). - -FILTER_SOURCE_FILES = NO - -# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file -# pattern. A pattern will override the setting for FILTER_PATTERN (if any) -# and it is also possible to disable source filtering for a specific pattern -# using *.ext= (so without naming a filter). This option only has effect when -# FILTER_SOURCE_FILES is enabled. - -FILTER_SOURCE_PATTERNS = - -#--------------------------------------------------------------------------- -# configuration options related to source browsing -#--------------------------------------------------------------------------- - -# If the SOURCE_BROWSER tag is set to YES then a list of source files will -# be generated. Documented entities will be cross-referenced with these sources. -# Note: To get rid of all source code in the generated output, make sure also -# VERBATIM_HEADERS is set to NO. - -SOURCE_BROWSER = YES - -# Setting the INLINE_SOURCES tag to YES will include the body -# of functions and classes directly in the documentation. - -INLINE_SOURCES = NO - -# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct -# doxygen to hide any special comment blocks from generated source code -# fragments. Normal C and C++ comments will always remain visible. - -STRIP_CODE_COMMENTS = YES - -# If the REFERENCED_BY_RELATION tag is set to YES -# then for each documented function all documented -# functions referencing it will be listed. - -REFERENCED_BY_RELATION = NO - -# If the REFERENCES_RELATION tag is set to YES -# then for each documented function all documented entities -# called/used by that function will be listed. - -REFERENCES_RELATION = NO - -# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) -# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from -# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will -# link to the source code. -# Otherwise they will link to the documentation. - -REFERENCES_LINK_SOURCE = YES - -# If the USE_HTAGS tag is set to YES then the references to source code -# will point to the HTML generated by the htags(1) tool instead of doxygen -# built-in source browser. The htags tool is part of GNU's global source -# tagging system (see http://www.gnu.org/software/global/global.html). You -# will need version 4.8.6 or higher. - -USE_HTAGS = NO - -# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen -# will generate a verbatim copy of the header file for each class for -# which an include is specified. Set to NO to disable this. - -VERBATIM_HEADERS = YES - -#--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- - -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index -# of all compounds will be generated. Enable this if the project -# contains a lot of classes, structs, unions or interfaces. - -ALPHABETICAL_INDEX = NO - -# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then -# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns -# in which this list will be split (can be a number in the range [1..20]) - -COLS_IN_ALPHA_INDEX = 5 - -# In case all classes in a project start with a common prefix, all -# classes will be put under the same header in the alphabetical index. -# The IGNORE_PREFIX tag can be used to specify one or more prefixes that -# should be ignored while generating the index headers. - -IGNORE_PREFIX = - -#--------------------------------------------------------------------------- -# configuration options related to the HTML output -#--------------------------------------------------------------------------- - -# If the GENERATE_HTML tag is set to YES (the default) Doxygen will -# generate HTML output. - -GENERATE_HTML = YES - -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `html' will be used as the default path. - -HTML_OUTPUT = html - -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for -# each generated HTML page (for example: .htm,.php,.asp). If it is left blank -# doxygen will generate files with .html extension. - -HTML_FILE_EXTENSION = .html - -# The HTML_HEADER tag can be used to specify a personal HTML header for -# each generated HTML page. If it is left blank doxygen will generate a -# standard header. Note that when using a custom header you are responsible -# for the proper inclusion of any scripts and style sheets that doxygen -# needs, which is dependent on the configuration options used. -# It is advised to generate a default header using "doxygen -w html -# header.html footer.html stylesheet.css YourConfigFile" and then modify -# that header. Note that the header is subject to change so you typically -# have to redo this when upgrading to a newer version of doxygen or when -# changing the value of configuration settings such as GENERATE_TREEVIEW! - -HTML_HEADER = - -# The HTML_FOOTER tag can be used to specify a personal HTML footer for -# each generated HTML page. If it is left blank doxygen will generate a -# standard footer. - -HTML_FOOTER = - -# The HTML_STYLESHEET tag can be used to specify a user-defined cascading -# style sheet that is used by each HTML page. It can be used to -# fine-tune the look of the HTML output. If the tag is left blank doxygen -# will generate a default style sheet. Note that doxygen will try to copy -# the style sheet file to the HTML output directory, so don't put your own -# style sheet in the HTML output directory as well, or it will be erased! - -HTML_STYLESHEET = - -# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or -# other source files which should be copied to the HTML output directory. Note -# that these files will be copied to the base HTML output directory. Use the -# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these -# files. In the HTML_STYLESHEET file, use the file name only. Also note that -# the files will be copied as-is; there are no commands or markers available. - -HTML_EXTRA_FILES = - -# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. -# Doxygen will adjust the colors in the style sheet and background images -# according to this color. Hue is specified as an angle on a colorwheel, -# see http://en.wikipedia.org/wiki/Hue for more information. -# For instance the value 0 represents red, 60 is yellow, 120 is green, -# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. -# The allowed range is 0 to 359. - -HTML_COLORSTYLE_HUE = 220 - -# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of -# the colors in the HTML output. For a value of 0 the output will use -# grayscales only. A value of 255 will produce the most vivid colors. - -HTML_COLORSTYLE_SAT = 100 - -# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to -# the luminance component of the colors in the HTML output. Values below -# 100 gradually make the output lighter, whereas values above 100 make -# the output darker. The value divided by 100 is the actual gamma applied, -# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, -# and 100 does not change the gamma. - -HTML_COLORSTYLE_GAMMA = 80 - -# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML -# page will contain the date and time when the page was generated. Setting -# this to NO can help when comparing the output of multiple runs. - -HTML_TIMESTAMP = YES - -# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, -# files or namespaces will be aligned in HTML using tables. If set to -# NO a bullet list will be used. - -HTML_ALIGN_MEMBERS = YES - -# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML -# documentation will contain sections that can be hidden and shown after the -# page has loaded. For this to work a browser that supports -# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox -# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). - -HTML_DYNAMIC_SECTIONS = NO - -# If the GENERATE_DOCSET tag is set to YES, additional index files -# will be generated that can be used as input for Apple's Xcode 3 -# integrated development environment, introduced with OSX 10.5 (Leopard). -# To create a documentation set, doxygen will generate a Makefile in the -# HTML output directory. Running make will produce the docset in that -# directory and running "make install" will install the docset in -# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find -# it at startup. -# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html -# for more information. - -GENERATE_DOCSET = NO - -# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the -# feed. A documentation feed provides an umbrella under which multiple -# documentation sets from a single provider (such as a company or product suite) -# can be grouped. - -DOCSET_FEEDNAME = "Doxygen generated docs" - -# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that -# should uniquely identify the documentation set bundle. This should be a -# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen -# will append .docset to the name. - -DOCSET_BUNDLE_ID = org.doxygen.Project - -# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify -# the documentation publisher. This should be a reverse domain-name style -# string, e.g. com.mycompany.MyDocSet.documentation. - -DOCSET_PUBLISHER_ID = org.doxygen.Publisher - -# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. - -DOCSET_PUBLISHER_NAME = Publisher - -# If the GENERATE_HTMLHELP tag is set to YES, additional index files -# will be generated that can be used as input for tools like the -# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) -# of the generated HTML documentation. - -GENERATE_HTMLHELP = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can -# be used to specify the file name of the resulting .chm file. You -# can add a path in front of the file if the result should not be -# written to the html output directory. - -CHM_FILE = - -# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can -# be used to specify the location (absolute path including file name) of -# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run -# the HTML help compiler on the generated index.hhp. - -HHC_LOCATION = - -# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag -# controls if a separate .chi index file is generated (YES) or that -# it should be included in the master .chm file (NO). - -GENERATE_CHI = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING -# is used to encode HtmlHelp index (hhk), content (hhc) and project file -# content. - -CHM_INDEX_ENCODING = - -# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag -# controls whether a binary table of contents is generated (YES) or a -# normal table of contents (NO) in the .chm file. - -BINARY_TOC = NO - -# The TOC_EXPAND flag can be set to YES to add extra items for group members -# to the contents of the HTML help documentation and to the tree view. - -TOC_EXPAND = NO - -# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and -# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated -# that can be used as input for Qt's qhelpgenerator to generate a -# Qt Compressed Help (.qch) of the generated HTML documentation. - -GENERATE_QHP = NO - -# If the QHG_LOCATION tag is specified, the QCH_FILE tag can -# be used to specify the file name of the resulting .qch file. -# The path specified is relative to the HTML output folder. - -QCH_FILE = - -# The QHP_NAMESPACE tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#namespace - -QHP_NAMESPACE = org.doxygen.Project - -# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#virtual-folders - -QHP_VIRTUAL_FOLDER = doc - -# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to -# add. For more information please see -# http://doc.trolltech.com/qthelpproject.html#custom-filters - -QHP_CUST_FILTER_NAME = - -# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the -# custom filter to add. For more information please see -# -# Qt Help Project / Custom Filters. - -QHP_CUST_FILTER_ATTRS = - -# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this -# project's -# filter section matches. -# -# Qt Help Project / Filter Attributes. - -QHP_SECT_FILTER_ATTRS = - -# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can -# be used to specify the location of Qt's qhelpgenerator. -# If non-empty doxygen will try to run qhelpgenerator on the generated -# .qhp file. - -QHG_LOCATION = - -# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files -# will be generated, which together with the HTML files, form an Eclipse help -# plugin. To install this plugin and make it available under the help contents -# menu in Eclipse, the contents of the directory containing the HTML and XML -# files needs to be copied into the plugins directory of eclipse. The name of -# the directory within the plugins directory should be the same as -# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before -# the help appears. - -GENERATE_ECLIPSEHELP = NO - -# A unique identifier for the eclipse help plugin. When installing the plugin -# the directory name containing the HTML and XML files should also have -# this name. - -ECLIPSE_DOC_ID = org.doxygen.Project - -# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) -# at top of each HTML page. The value NO (the default) enables the index and -# the value YES disables it. Since the tabs have the same information as the -# navigation tree you can set this option to NO if you already set -# GENERATE_TREEVIEW to YES. - -DISABLE_INDEX = NO - -# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index -# structure should be generated to display hierarchical information. -# If the tag value is set to YES, a side panel will be generated -# containing a tree-like index structure (just like the one that -# is generated for HTML Help). For this to work a browser that supports -# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). -# Windows users are probably better off using the HTML help feature. -# Since the tree basically has the same information as the tab index you -# could consider to set DISABLE_INDEX to NO when enabling this option. - -GENERATE_TREEVIEW = NO - -# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values -# (range [0,1..20]) that doxygen will group on one line in the generated HTML -# documentation. Note that a value of 0 will completely suppress the enum -# values from appearing in the overview section. - -ENUM_VALUES_PER_LINE = 4 - -# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, -# and Class Hierarchy pages using a tree view instead of an ordered list. - -USE_INLINE_TREES = NO - -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be -# used to set the initial width (in pixels) of the frame in which the tree -# is shown. - -TREEVIEW_WIDTH = 250 - -# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open -# links to external symbols imported via tag files in a separate window. - -EXT_LINKS_IN_WINDOW = NO - -# Use this tag to change the font size of Latex formulas included -# as images in the HTML documentation. The default is 10. Note that -# when you change the font size after a successful doxygen run you need -# to manually remove any form_*.png images from the HTML output directory -# to force them to be regenerated. - -FORMULA_FONTSIZE = 10 - -# Use the FORMULA_TRANPARENT tag to determine whether or not the images -# generated for formulas are transparent PNGs. Transparent PNGs are -# not supported properly for IE 6.0, but are supported on all modern browsers. -# Note that when changing this option you need to delete any form_*.png files -# in the HTML output before the changes have effect. - -FORMULA_TRANSPARENT = YES - -# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax -# (see http://www.mathjax.org) which uses client side Javascript for the -# rendering instead of using prerendered bitmaps. Use this if you do not -# have LaTeX installed or if you want to formulas look prettier in the HTML -# output. When enabled you also need to install MathJax separately and -# configure the path to it using the MATHJAX_RELPATH option. - -USE_MATHJAX = NO - -# When MathJax is enabled you need to specify the location relative to the -# HTML output directory using the MATHJAX_RELPATH option. The destination -# directory should contain the MathJax.js script. For instance, if the mathjax -# directory is located at the same level as the HTML output directory, then -# MATHJAX_RELPATH should be ../mathjax. The default value points to the -# mathjax.org site, so you can quickly see the result without installing -# MathJax, but it is strongly recommended to install a local copy of MathJax -# before deployment. - -MATHJAX_RELPATH = http://www.mathjax.org/mathjax - -# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension -# names that should be enabled during MathJax rendering. - -MATHJAX_EXTENSIONS = - -# When the SEARCHENGINE tag is enabled doxygen will generate a search box -# for the HTML output. The underlying search engine uses javascript -# and DHTML and should work on any modern browser. Note that when using -# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets -# (GENERATE_DOCSET) there is already a search function so this one should -# typically be disabled. For large projects the javascript based search engine -# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. - -SEARCHENGINE = YES - -# When the SERVER_BASED_SEARCH tag is enabled the search engine will be -# implemented using a PHP enabled web server instead of at the web client -# using Javascript. Doxygen will generate the search PHP script and index -# file to put on the web server. The advantage of the server -# based approach is that it scales better to large projects and allows -# full text search. The disadvantages are that it is more difficult to setup -# and does not have live searching capabilities. - -SERVER_BASED_SEARCH = NO - -#--------------------------------------------------------------------------- -# configuration options related to the LaTeX output -#--------------------------------------------------------------------------- - -# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will -# generate Latex output. - -GENERATE_LATEX = YES - -# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `latex' will be used as the default path. - -LATEX_OUTPUT = latex - -# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be -# invoked. If left blank `latex' will be used as the default command name. -# Note that when enabling USE_PDFLATEX this option is only used for -# generating bitmaps for formulas in the HTML output, but not in the -# Makefile that is written to the output directory. - -LATEX_CMD_NAME = latex - -# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to -# generate index for LaTeX. If left blank `makeindex' will be used as the -# default command name. - -MAKEINDEX_CMD_NAME = makeindex - -# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact -# LaTeX documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_LATEX = NO - -# The PAPER_TYPE tag can be used to set the paper type that is used -# by the printer. Possible values are: a4, letter, legal and -# executive. If left blank a4wide will be used. - -PAPER_TYPE = a4 - -# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX -# packages that should be included in the LaTeX output. - -EXTRA_PACKAGES = - -# The LATEX_HEADER tag can be used to specify a personal LaTeX header for -# the generated latex document. The header should contain everything until -# the first chapter. If it is left blank doxygen will generate a -# standard header. Notice: only use this tag if you know what you are doing! - -LATEX_HEADER = - -# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for -# the generated latex document. The footer should contain everything after -# the last chapter. If it is left blank doxygen will generate a -# standard footer. Notice: only use this tag if you know what you are doing! - -LATEX_FOOTER = - -# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated -# is prepared for conversion to pdf (using ps2pdf). The pdf file will -# contain links (just like the HTML output) instead of page references -# This makes the output suitable for online browsing using a pdf viewer. - -PDF_HYPERLINKS = YES - -# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of -# plain latex in the generated Makefile. Set this option to YES to get a -# higher quality PDF documentation. - -USE_PDFLATEX = YES - -# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. -# command to the generated LaTeX files. This will instruct LaTeX to keep -# running if errors occur, instead of asking the user for help. -# This option is also used when generating formulas in HTML. - -LATEX_BATCHMODE = NO - -# If LATEX_HIDE_INDICES is set to YES then doxygen will not -# include the index chapters (such as File Index, Compound Index, etc.) -# in the output. - -LATEX_HIDE_INDICES = NO - -# If LATEX_SOURCE_CODE is set to YES then doxygen will include -# source code with syntax highlighting in the LaTeX output. -# Note that which sources are shown also depends on other settings -# such as SOURCE_BROWSER. - -LATEX_SOURCE_CODE = NO - -# The LATEX_BIB_STYLE tag can be used to specify the style to use for the -# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See -# http://en.wikipedia.org/wiki/BibTeX for more info. - -LATEX_BIB_STYLE = plain - -#--------------------------------------------------------------------------- -# configuration options related to the RTF output -#--------------------------------------------------------------------------- - -# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output -# The RTF output is optimized for Word 97 and may not look very pretty with -# other RTF readers or editors. - -GENERATE_RTF = NO - -# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `rtf' will be used as the default path. - -RTF_OUTPUT = rtf - -# If the COMPACT_RTF tag is set to YES Doxygen generates more compact -# RTF documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_RTF = NO - -# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated -# will contain hyperlink fields. The RTF file will -# contain links (just like the HTML output) instead of page references. -# This makes the output suitable for online browsing using WORD or other -# programs which support those fields. -# Note: wordpad (write) and others do not support links. - -RTF_HYPERLINKS = NO - -# Load style sheet definitions from file. Syntax is similar to doxygen's -# config file, i.e. a series of assignments. You only have to provide -# replacements, missing definitions are set to their default value. - -RTF_STYLESHEET_FILE = - -# Set optional variables used in the generation of an rtf document. -# Syntax is similar to doxygen's config file. - -RTF_EXTENSIONS_FILE = - -#--------------------------------------------------------------------------- -# configuration options related to the man page output -#--------------------------------------------------------------------------- - -# If the GENERATE_MAN tag is set to YES (the default) Doxygen will -# generate man pages - -GENERATE_MAN = NO - -# The MAN_OUTPUT tag is used to specify where the man pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `man' will be used as the default path. - -MAN_OUTPUT = man - -# The MAN_EXTENSION tag determines the extension that is added to -# the generated man pages (default is the subroutine's section .3) - -MAN_EXTENSION = .3 - -# If the MAN_LINKS tag is set to YES and Doxygen generates man output, -# then it will generate one additional man file for each entity -# documented in the real man page(s). These additional files -# only source the real man page, but without them the man command -# would be unable to find the correct page. The default is NO. - -MAN_LINKS = NO - -#--------------------------------------------------------------------------- -# configuration options related to the XML output -#--------------------------------------------------------------------------- - -# If the GENERATE_XML tag is set to YES Doxygen will -# generate an XML file that captures the structure of -# the code including all documentation. - -GENERATE_XML = NO - -# The XML_OUTPUT tag is used to specify where the XML pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `xml' will be used as the default path. - -XML_OUTPUT = xml - -# The XML_SCHEMA tag can be used to specify an XML schema, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_SCHEMA = - -# The XML_DTD tag can be used to specify an XML DTD, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_DTD = - -# If the XML_PROGRAMLISTING tag is set to YES Doxygen will -# dump the program listings (including syntax highlighting -# and cross-referencing information) to the XML output. Note that -# enabling this will significantly increase the size of the XML output. - -XML_PROGRAMLISTING = YES - -#--------------------------------------------------------------------------- -# configuration options for the AutoGen Definitions output -#--------------------------------------------------------------------------- - -# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will -# generate an AutoGen Definitions (see autogen.sf.net) file -# that captures the structure of the code including all -# documentation. Note that this feature is still experimental -# and incomplete at the moment. - -GENERATE_AUTOGEN_DEF = NO - -#--------------------------------------------------------------------------- -# configuration options related to the Perl module output -#--------------------------------------------------------------------------- - -# If the GENERATE_PERLMOD tag is set to YES Doxygen will -# generate a Perl module file that captures the structure of -# the code including all documentation. Note that this -# feature is still experimental and incomplete at the -# moment. - -GENERATE_PERLMOD = NO - -# If the PERLMOD_LATEX tag is set to YES Doxygen will generate -# the necessary Makefile rules, Perl scripts and LaTeX code to be able -# to generate PDF and DVI output from the Perl module output. - -PERLMOD_LATEX = NO - -# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be -# nicely formatted so it can be parsed by a human reader. -# This is useful -# if you want to understand what is going on. -# On the other hand, if this -# tag is set to NO the size of the Perl module output will be much smaller -# and Perl will parse it just the same. - -PERLMOD_PRETTY = YES - -# The names of the make variables in the generated doxyrules.make file -# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. -# This is useful so different doxyrules.make files included by the same -# Makefile don't overwrite each other's variables. - -PERLMOD_MAKEVAR_PREFIX = - -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- - -# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will -# evaluate all C-preprocessor directives found in the sources and include -# files. - -ENABLE_PREPROCESSING = YES - -# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro -# names in the source code. If set to NO (the default) only conditional -# compilation will be performed. Macro expansion can be done in a controlled -# way by setting EXPAND_ONLY_PREDEF to YES. - -MACRO_EXPANSION = NO - -# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES -# then the macro expansion is limited to the macros specified with the -# PREDEFINED and EXPAND_AS_DEFINED tags. - -EXPAND_ONLY_PREDEF = NO - -# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files -# pointed to by INCLUDE_PATH will be searched when a #include is found. - -SEARCH_INCLUDES = YES - -# The INCLUDE_PATH tag can be used to specify one or more directories that -# contain include files that are not input files but should be processed by -# the preprocessor. - -INCLUDE_PATH = - -# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard -# patterns (like *.h and *.hpp) to filter out the header-files in the -# directories. If left blank, the patterns specified with FILE_PATTERNS will -# be used. - -INCLUDE_FILE_PATTERNS = - -# The PREDEFINED tag can be used to specify one or more macro names that -# are defined before the preprocessor is started (similar to the -D option of -# gcc). The argument of the tag is a list of macros of the form: name -# or name=definition (no spaces). If the definition and the = are -# omitted =1 is assumed. To prevent a macro definition from being -# undefined via #undef or recursively expanded use the := operator -# instead of the = operator. - -PREDEFINED = - -# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then -# this tag can be used to specify a list of macro names that should be expanded. -# The macro definition that is found in the sources will be used. -# Use the PREDEFINED tag if you want to use a different macro definition that -# overrules the definition found in the source code. - -EXPAND_AS_DEFINED = - -# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then -# doxygen's preprocessor will remove all references to function-like macros -# that are alone on a line, have an all uppercase name, and do not end with a -# semicolon, because these will confuse the parser if not removed. - -SKIP_FUNCTION_MACROS = YES - -#--------------------------------------------------------------------------- -# Configuration::additions related to external references -#--------------------------------------------------------------------------- - -# The TAGFILES option can be used to specify one or more tagfiles. -# Optionally an initial location of the external documentation -# can be added for each tagfile. The format of a tag file without -# this location is as follows: -# -# TAGFILES = file1 file2 ... -# Adding location for the tag files is done as follows: -# -# TAGFILES = file1=loc1 "file2 = loc2" ... -# where "loc1" and "loc2" can be relative or absolute paths or -# URLs. If a location is present for each tag, the installdox tool -# does not have to be run to correct the links. -# Note that each tag file must have a unique name -# (where the name does NOT include the path) -# If a tag file is not located in the directory in which doxygen -# is run, you must also specify the path to the tagfile here. - -TAGFILES = - -# When a file name is specified after GENERATE_TAGFILE, doxygen will create -# a tag file that is based on the input files it reads. - -GENERATE_TAGFILE = - -# If the ALLEXTERNALS tag is set to YES all external classes will be listed -# in the class index. If set to NO only the inherited external classes -# will be listed. - -ALLEXTERNALS = NO - -# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed -# in the modules index. If set to NO, only the current project's groups will -# be listed. - -EXTERNAL_GROUPS = YES - -# The PERL_PATH should be the absolute path and name of the perl script -# interpreter (i.e. the result of `which perl'). - -PERL_PATH = /usr/bin/perl - -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- - -# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will -# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base -# or super classes. Setting the tag to NO turns the diagrams off. Note that -# this option also works with HAVE_DOT disabled, but it is recommended to -# install and use dot, since it yields more powerful graphs. - -CLASS_DIAGRAMS = YES - -# You can define message sequence charts within doxygen comments using the \msc -# command. Doxygen will then run the mscgen tool (see -# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the -# documentation. The MSCGEN_PATH tag allows you to specify the directory where -# the mscgen tool resides. If left empty the tool is assumed to be found in the -# default search path. - -MSCGEN_PATH = - -# If set to YES, the inheritance and collaboration graphs will hide -# inheritance and usage relations if the target is undocumented -# or is not a class. - -HIDE_UNDOC_RELATIONS = YES - -# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is -# available from the path. This tool is part of Graphviz, a graph visualization -# toolkit from AT&T and Lucent Bell Labs. The other options in this section -# have no effect if this option is set to NO (the default) - -HAVE_DOT = NO - -# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is -# allowed to run in parallel. When set to 0 (the default) doxygen will -# base this on the number of processors available in the system. You can set it -# explicitly to a value larger than 0 to get control over the balance -# between CPU load and processing speed. - -DOT_NUM_THREADS = 0 - -# By default doxygen will use the Helvetica font for all dot files that -# doxygen generates. When you want a differently looking font you can specify -# the font name using DOT_FONTNAME. You need to make sure dot is able to find -# the font, which can be done by putting it in a standard location or by setting -# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the -# directory containing the font. - -DOT_FONTNAME = Helvetica - -# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. -# The default size is 10pt. - -DOT_FONTSIZE = 10 - -# By default doxygen will tell dot to use the Helvetica font. -# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to -# set the path where dot can find it. - -DOT_FONTPATH = - -# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect inheritance relations. Setting this tag to YES will force the -# CLASS_DIAGRAMS tag to NO. - -CLASS_GRAPH = YES - -# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect implementation dependencies (inheritance, containment, and -# class references variables) of the class with other documented classes. - -COLLABORATION_GRAPH = YES - -# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for groups, showing the direct groups dependencies - -GROUP_GRAPHS = YES - -# If the UML_LOOK tag is set to YES doxygen will generate inheritance and -# collaboration diagrams in a style similar to the OMG's Unified Modeling -# Language. - -UML_LOOK = NO - -# If set to YES, the inheritance and collaboration graphs will show the -# relations between templates and their instances. - -TEMPLATE_RELATIONS = NO - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT -# tags are set to YES then doxygen will generate a graph for each documented -# file showing the direct and indirect include dependencies of the file with -# other documented files. - -INCLUDE_GRAPH = YES - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and -# HAVE_DOT tags are set to YES then doxygen will generate a graph for each -# documented header file showing the documented files that directly or -# indirectly include this file. - -INCLUDED_BY_GRAPH = YES - -# If the CALL_GRAPH and HAVE_DOT options are set to YES then -# doxygen will generate a call dependency graph for every global function -# or class method. Note that enabling this option will significantly increase -# the time of a run. So in most cases it will be better to enable call graphs -# for selected functions only using the \callgraph command. - -CALL_GRAPH = NO - -# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then -# doxygen will generate a caller dependency graph for every global function -# or class method. Note that enabling this option will significantly increase -# the time of a run. So in most cases it will be better to enable caller -# graphs for selected functions only using the \callergraph command. - -CALLER_GRAPH = NO - -# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen -# will generate a graphical hierarchy of all classes instead of a textual one. - -GRAPHICAL_HIERARCHY = YES - -# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES -# then doxygen will show the dependencies a directory has on other directories -# in a graphical way. The dependency relations are determined by the #include -# relations between the files in the directories. - -DIRECTORY_GRAPH = YES - -# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images -# generated by dot. Possible values are svg, png, jpg, or gif. -# If left blank png will be used. If you choose svg you need to set -# HTML_FILE_EXTENSION to xhtml in order to make the SVG files -# visible in IE 9+ (other browsers do not have this requirement). - -DOT_IMAGE_FORMAT = png - -# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to -# enable generation of interactive SVG images that allow zooming and panning. -# Note that this requires a modern browser other than Internet Explorer. -# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you -# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files -# visible. Older versions of IE do not have SVG support. - -INTERACTIVE_SVG = NO - -# The tag DOT_PATH can be used to specify the path where the dot tool can be -# found. If left blank, it is assumed the dot tool can be found in the path. - -DOT_PATH = - -# The DOTFILE_DIRS tag can be used to specify one or more directories that -# contain dot files that are included in the documentation (see the -# \dotfile command). - -DOTFILE_DIRS = - -# The MSCFILE_DIRS tag can be used to specify one or more directories that -# contain msc files that are included in the documentation (see the -# \mscfile command). - -MSCFILE_DIRS = - -# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of -# nodes that will be shown in the graph. If the number of nodes in a graph -# becomes larger than this value, doxygen will truncate the graph, which is -# visualized by representing a node as a red box. Note that doxygen if the -# number of direct children of the root node in a graph is already larger than -# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note -# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. - -DOT_GRAPH_MAX_NODES = 50 - -# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the -# graphs generated by dot. A depth value of 3 means that only nodes reachable -# from the root by following a path via at most 3 edges will be shown. Nodes -# that lay further from the root node will be omitted. Note that setting this -# option to 1 or 2 may greatly reduce the computation time needed for large -# code bases. Also note that the size of a graph can be further restricted by -# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. - -MAX_DOT_GRAPH_DEPTH = 0 - -# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent -# background. This is disabled by default, because dot on Windows does not -# seem to support this out of the box. Warning: Depending on the platform used, -# enabling this option may lead to badly anti-aliased labels on the edges of -# a graph (i.e. they become hard to read). - -DOT_TRANSPARENT = NO - -# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output -# files in one run (i.e. multiple -o and -T options on the command line). This -# makes dot run faster, but since only newer versions of dot (>1.8.10) -# support this, this feature is disabled by default. - -DOT_MULTI_TARGETS = YES - -# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will -# generate a legend page explaining the meaning of the various boxes and -# arrows in the dot generated graphs. - -GENERATE_LEGEND = YES - -# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will -# remove the intermediate dot files that are used to generate -# the various graphs. - -DOT_CLEANUP = YES diff --git a/Arduino/MAX6956/Examples/MAX6956_LED_FADE/MAX6956_LED_Fade.ino b/Arduino/MAX6956/Examples/MAX6956_LED_FADE/MAX6956_LED_Fade.ino deleted file mode 100644 index 3f0c5afc..00000000 --- a/Arduino/MAX6956/Examples/MAX6956_LED_FADE/MAX6956_LED_Fade.ino +++ /dev/null @@ -1,61 +0,0 @@ - -#include "I2Cdev.h" -#include "MAX6956.h" - -int led = 13; -int globalCurrent = 15; // 15-0, 15 the max - -MAX6956 ledDriver; - -void setup() -{ - // initialize the digital pin as an output. - pinMode(led, OUTPUT); - - // initialize serial communication - Serial.begin(9600); - - // initialize device - Serial.println("Initializing I2C devices..."); - ledDriver.initialize(); - - // verify connection - Serial.println("Testing device connections..."); - if (ledDriver.testConnection()) { - Serial.println("Connection successful"); - } else { - Serial.println("Connection failed"); - while (true) { - delay(1000); - } - } - - ledDriver.setGlobalCurrent(globalCurrent); - ledDriver.configAllPorts(MAX6956_OUTPUT_LED); // Set all ports as led drivers - ledDriver.enableAllPorts(); // Enable all ports - ledDriver.setTestMode(true); - delay(1000); // wait - ledDriver.setTestMode(false); - delay(1000); // wait - ledDriver.setPower(true); -} - - -void loop() -{ - digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level) - // Ramp brightness down - for (int x = 15; x >= 0; x--) { - ledDriver.setGlobalCurrent(globalCurrent); // Set global current - globalCurrent = x; - delay(80); - } - - digitalWrite(led, LOW); // turn the LED off by making the voltage LOW - // Ramp brightness up - for (int x = 0; x <= 15; x++) { - ledDriver.setGlobalCurrent(globalCurrent); // Set global current - globalCurrent = x; - delay(80); - } -} diff --git a/Arduino/MAX6956/MAX6956.cpp b/Arduino/MAX6956/MAX6956.cpp deleted file mode 100644 index 1fd21159..00000000 --- a/Arduino/MAX6956/MAX6956.cpp +++ /dev/null @@ -1,573 +0,0 @@ -// I2Cdev library collection - MAX6956 I2C device class -// Based on Maxim MAX6956 datasheet 19-2414; Rev 4; 6/10 -// -// 2013-12-15 by Tom Beighley -// I2C Device Library hosted at http://www.i2cdevlib.com -// -// Changelog: -// 2013-12-15 - initial release -// - -/* ============================================ -I2Cdev device library code is placed under the MIT license -Copyright (c) 2013 Tom Beighley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -=============================================== -*/ - -#include "MAX6956.h" - -/** Default constructor, uses default I2C address. - * @see MAX6956_DEFAULT_ADDRESS - */ -MAX6956::MAX6956() { - devAddr = MAX6956_DEFAULT_ADDRESS; -} - -/** Specific address constructor. - * @param address I2C address - * @see MAX6956_DEFAULT_ADDRESS - * @see MAX6956_ADDRESS - */ -MAX6956::MAX6956(uint8_t address) { - devAddr = address; -} - -/** Power on and prepare for general usage. */ -void MAX6956::initialize() { - // Need this in setup() or here. - // Fastwire::setup(400, false); - reset(); - - /** The 28-pin MAX6956ANI and MAX6956AAI make only 20 ports available, P12 to P31. - The eight unused ports should be configured as outputs on power-up by writing 0x55 to registers 0x09 and 0x0A. - If this is not done,the eight unused ports remain as unconnected inputs and quiescent supply current rises, - although there is no damage to the part. - */ - I2Cdev::writeByte(devAddr, MAX6956_RA_CONFIG_P7P6P5P4, 0x55); - I2Cdev::writeByte(devAddr, MAX6956_RA_CONFIG_P11P10P9P8, 0x55); -} - -/** Verify the I2C connection. - * Make sure the device is connected and responds as expected. - * @return True if connection is valid, false otherwise - */ -bool MAX6956::testConnection() { - if (I2Cdev::readByte(devAddr, MAX6956_RA_CONFIGURATION, buffer) == 1) { - return true; - } - return false; -} - -/** Set registers back to Power-up Configuration */ -void MAX6956::reset() { - disableAllPorts(); // set Port RA 0x2C-0x3F to 0 - setGlobalCurrent(0x00); // Set global current to minimum on - setConfigReg(0x00); // Shutdown Enabled,Current Control = Global, Transition Detection Disabled - setInputMask(0x00); // Set Input register mask to 0 - setTestMode(false); // disable test mode - configAllPorts(MAX6956_INPUT_WO_PULL); // Configure all inputs as MAX6956_INPUT_WO_PULL - setAllPortsCurrent(0x00); // Set current RA 0x16-01F to 0 -} - -/** Config register -@return uint8_t value of register -@see MAX6956_RA_CONFIGURATION -*/ -uint8_t MAX6956::getConfigReg() { - I2Cdev::readByte(devAddr, MAX6956_RA_CONFIGURATION, buffer); - return buffer[0]; -} -/** Set config register -@param config uint8_t value to set register -@see MAX6956_RA_CONFIGURATION -*/ -void MAX6956::setConfigReg(uint8_t config) { - I2Cdev::writeByte(devAddr, MAX6956_RA_CONFIGURATION, config); -} - -/** Get power configuration bit -@return Boolean value if power is enabled or not -@see MAX6956_RA_CONFIGURATION -*/ -bool MAX6956::getPower() { - I2Cdev::readBit(devAddr, MAX6956_RA_CONFIGURATION, MAX6956_CONFIG_POWER_BIT, buffer); - return buffer[0]; -} -/** Enable or disable power -@param power Boolean value, true enables, false disables power -@see MAX6956_RA_CONFIGURATION -*/ -void MAX6956::setPower(bool power) { - I2Cdev::writeBit(devAddr, MAX6956_RA_CONFIGURATION, MAX6956_CONFIG_POWER_BIT, power); -} -/** Toggle power -@see MAX6956_RA_CONFIGURATION -*/ -void MAX6956::togglePower() { - I2Cdev::readBit(devAddr, MAX6956_RA_CONFIGURATION, MAX6956_CONFIG_POWER_BIT, buffer); - buffer[0] = !(buffer[0]); - I2Cdev::writeBit(devAddr, MAX6956_RA_CONFIGURATION, MAX6956_CONFIG_POWER_BIT, buffer[0]); -} - -/** Get transition detection configuration bit -@return Boolean value if global current is enabled or not -@see MAX6956_RA_CONFIGURATION -*/ -bool MAX6956::getEnableIndividualCurrent() { - I2Cdev::readBit(devAddr, MAX6956_RA_CONFIGURATION, MAX6956_CONFIG_GLOBAL_CURRENT_BIT, buffer); - return buffer[0]; -} -/** Enable or disable global current -@param global Boolean value, true enables, false disables individual current -@see MAX6956_RA_CONFIGURATION -@see getGlobalCurrent() -@see setGlobalCurrent() -*/ -void MAX6956::setEnableIndividualCurrent(bool global) { - I2Cdev::writeBit(devAddr, MAX6956_RA_CONFIGURATION, MAX6956_CONFIG_GLOBAL_CURRENT_BIT, global); -} - -/** Get transition detection configuration bit -@return Boolean value if transition detection is enabled or not -@see MAX6956_RA_CONFIGURATION -*/ -bool MAX6956::getEnableTransitionDetection() { - I2Cdev::readBit(devAddr, MAX6956_RA_CONFIGURATION, MAX6956_CONFIG_TRANSITION_BIT, buffer); - return buffer[0]; -} -/** Enable or disable transition detection. Must be reset after every mask read. -@param transition Boolean value, true enables, false disables transition detection -@see MAX6956_RA_CONFIGURATION -@see getInputMask() -@see setInputMask() -*/ -void MAX6956::setEnableTransitionDetection(bool transition) { - I2Cdev::writeBit(devAddr, MAX6956_RA_CONFIGURATION, MAX6956_CONFIG_TRANSITION_BIT, transition); -} - -// Global Current -/** Get global current -@return uint8_t value of register -@see MAX6956_RA_GLOBAL_CURRENT -*/ -uint8_t MAX6956::getGlobalCurrent() { - I2Cdev::readBits(devAddr, MAX6956_RA_GLOBAL_CURRENT, MAX6956_GLOBAL_CURRENT_BIT, MAX6956_GLOBAL_CURRENT_LENGTH, buffer); - return buffer[0]; -} -/** Set current globally -@param current uint8_t 0-15, 0 = min, 15 = max brightness -@see MAX6956_RA_GLOBAL_CURRENT -*/ -void MAX6956::setGlobalCurrent(uint8_t current) { - I2Cdev::writeByte(devAddr, MAX6956_RA_GLOBAL_CURRENT, current); -} - -// Test mode -/** Returns true if test mode is enabled. -@return uint8_t value of register -@see MAX6956_RA_DISPLAY_TEST -*/ -bool MAX6956::getTestMode() { - I2Cdev::readBit(devAddr, MAX6956_RA_DISPLAY_TEST, MAX6956_DISPLAY_TEST_BIT, buffer); - return buffer[0]; -} -/** Enable or disable test mode -@param test Boolean, true enables, false disables -@see MAX6956_RA_DISPLAY_TEST -*/ -void MAX6956::setTestMode(bool test) { - I2Cdev::writeByte(devAddr, MAX6956_RA_DISPLAY_TEST, test); -} - -// Input mask register -/** Get the input mask to see which ports have changed. MSB is cleared after every read. -@return uint8_t value of register -@see MAX6956_RA_TRANSITION_DETECT -*/ -uint8_t MAX6956::getInputMask() { - I2Cdev::readByte(devAddr, MAX6956_RA_TRANSITION_DETECT, buffer); - return buffer[0]; -} - -/** Set the input mask for which ports to monitor with transition detection -@param mask 8 bit value. MSB is ignored. -@see MAX6956_RA_TRANSITION_DETECT -*/ -void MAX6956::setInputMask(uint8_t mask) { - I2Cdev::writeByte(devAddr, MAX6956_RA_TRANSITION_DETECT, mask); -} - - -/** Takes an INDIVIDUAL port register address (MAX6956_RA_PORT12, ect) - and configures it as: MAX6956_OUTPUT_LED, MAX6956_OUTPUT_GPIO, - MAX6956_INPUT_WO_PULL, or MAX6956_INPUT_W_PULL - -Port registers --------------- - -Addr. | Name -:----:|:------------------------------: -0x09 | MAX6956_RA_CONFIG_P7P6P5P4 -0x0A | MAX6956_RA_CONFIG_P11P10P9P8 -0x0B | MAX6956_RA_CONFIG_P15P14P13P12 -0x0C | MAX6956_RA_CONFIG_P19P18P17P16 -0x0D | MAX6956_RA_CONFIG_P23P22P21P20 -0x0E | MAX6956_RA_CONFIG_P27P26P25P24 -0x0F | MAX6956_RA_CONFIG_P31P30P29P28 - -Num|Dec|Hex |Prt|Port Status Array|Ports Config Array -:-:|:-:|:--:|:-:|:---------------:|:-----------------: -00 |44 |0x2C|P12|portsStatus[0][0]|portsConfig[0][1-0] -01 |45 |0x2D|P13|portsStatus[0][1]|portsConfig[0][3-2] -02 |46 |0x2E|P14|portsStatus[0][2]|portsConfig[0][5-4] -03 |47 |0x2F|P15|portsStatus[0][3]|portsConfig[0][7-6] -04 |48 |0x30|P16|portsStatus[0][4]|portsConfig[1][1-0] -05 |49 |0x31|P17|portsStatus[0][5]|portsConfig[1][3-2] -06 |50 |0x32|P18|portsStatus[0][6]|portsConfig[1][5-4] -07 |51 |0x33|P19|portsStatus[0][7]|portsConfig[1][7-6] -08 |52 |0x34|P20|portsStatus[1][0]|portsConfig[2][1-0] -09 |53 |0x35|P21|portsStatus[1][1]|portsConfig[2][3-2] -10 |54 |0x36|P22|portsStatus[1][2]|portsConfig[2][5-4] -11 |55 |0x37|P23|portsStatus[1][3]|portsConfig[2][7-6] -12 |56 |0x38|P24|portsStatus[1][4]|portsConfig[3][1-0] -13 |57 |0x39|P25|portsStatus[1][5]|portsConfig[3][3-2] -14 |58 |0x3A|P26|portsStatus[1][6]|portsConfig[3][5-4] -15 |59 |0x3B|P27|portsStatus[1][7]|portsConfig[3][7-6] -16 |60 |0x3C|P28|portsStatus[2][0]|portsConfig[4][1-0] -17 |61 |0x3D|P29|portsStatus[2][1]|portsConfig[4][3-2] -18 |62 |0x3E|P30|portsStatus[2][2]|portsConfig[4][5-4] -19 |63 |0x3F|P31|portsStatus[2][3]|portsConfig[4][7-6] - - @param port Port register address (MAX6956_RA_PORT12, ect) - @param portConfig Valid options are: MAX6956_OUTPUT_LED, MAX6956_OUTPUT_GPIO, MAX6956_INPUT_WO_PULL, MAX6956_INPUT_W_PULL - @see MAX6956_RA_PORT12 MAX6956_RA_PORT13 MAX6956_RA_PORT14 MAX6956_RA_PORT15 MAX6956_RA_PORT16 MAX6956_RA_PORT17 MAX6956_RA_PORT18 MAX6956_RA_PORT19 MAX6956_RA_PORT20 MAX6956_RA_PORT21 - MAX6956_RA_PORT22 MAX6956_RA_PORT23 MAX6956_RA_PORT24 MAX6956_RA_PORT25 MAX6956_RA_PORT26 MAX6956_RA_PORT27 MAX6956_RA_PORT28 MAX6956_RA_PORT29 MAX6956_RA_PORT30 MAX6956_RA_PORT31 - @see MAX6956_OUTPUT_LED MAX6956_OUTPUT_GPIO MAX6956_INPUT_WO_PULL MAX6956_INPUT_W_PULL -*/ -void MAX6956::configPort(uint8_t port, uint8_t portConfig) { - uint8_t bitPosition = (((port - 44) % 4) * 2) + 1; // bit position to start flipping - uint8_t pcArrayIndex = (port - 44) / 4; // array index - uint8_t portConfigRA = pcArrayIndex + 11; // port config register - I2Cdev::writeBits(devAddr, portConfigRA, bitPosition, 2, portConfig); - // Update portConfig array - bitPosition--; // Remove 1 bit offset - portsConfig[pcArrayIndex] &= ~(3 << bitPosition); - portsConfig[pcArrayIndex] |= portConfig << bitPosition; -} - -/** Configure consecutive range of ports - * @param lower Lower port register address (MAX6956_RA_PORT12, ect) - * @param upper Upper port register address (MAX6956_RA_PORT12, ect) - * @param portConfig Valid options are: MAX6956_OUTPUT_LED, MAX6956_OUTPUT_GPIO, MAX6956_INPUT_WO_PULL, MAX6956_INPUT_W_PULL - * @see MAX6956_OUTPUT_LED - * @see MAX6956_OUTPUT_GPIO - * @see MAX6956_INPUT_WO_PULL - * @see MAX6956_INPUT_W_PULL -*/ -void MAX6956::configPorts(uint8_t lower, uint8_t upper, uint8_t portConfig) { - - #ifdef MAX6956_SERIAL_DEBUG - Serial.print("lower "); - Serial.print(lower, HEX); - Serial.print(" upper "); - Serial.print(upper, HEX); - Serial.print(" portConfig "); - Serial.println(portConfig, BIN); - #endif - - uint8_t bitPosition = 0; - uint8_t pcArrayIndex = 0; - uint8_t portConfigRA = 0; - uint8_t i = lower; - - while ( i <= upper ) { - bitPosition = (((i - 44) % 4) * 2) + 1; // bit position to start flipping - pcArrayIndex = (i - 44) / 4; // array index - portConfigRA = pcArrayIndex + 11; // port config register - - #ifdef MAX6956_SERIAL_DEBUG - Serial.print("i "); - Serial.print(i); - Serial.print(" bitPosition "); - Serial.print(bitPosition); - Serial.print(" pcArrayIndex"); - Serial.print(pcArrayIndex); - Serial.print(" portConfigRA "); - Serial.println(portConfigRA, HEX); - #endif - - I2Cdev::writeBits(devAddr, portConfigRA, bitPosition, 2, portConfig); - - #ifdef MAX6956_SERIAL_DEBUG - Serial.print("portsConfig "); - Serial.print(portsConfig[pcArrayIndex], BIN); - #endif - - // Update portConfig array - bitPosition--; // Remove 1 bit offset - portsConfig[pcArrayIndex] &= ~(3 << bitPosition); //3 == B00000011 Shift over correct number of bits then invert to create the mask - portsConfig[pcArrayIndex] |= portConfig << bitPosition; - - #ifdef MAX6956_SERIAL_DEBUG - Serial.print(" >> "); - Serial.println(portsConfig[pcArrayIndex], BIN); - #endif - - i++; - } - -} - -/** Configure all ports the same - @param portConfig Valid options are: MAX6956_OUTPUT_LED, MAX6956_OUTPUT_GPIO, MAX6956_INPUT_WO_PULL, MAX6956_INPUT_W_PULL - @see MAX6956_OUTPUT_LED - @see MAX6956_OUTPUT_GPIO - @see MAX6956_INPUT_WO_PULL - @see MAX6956_INPUT_W_PULL -*/ -void MAX6956::configAllPorts(uint8_t portConfig) { - // build byte with config bits shifted to all 4 slots - portConfig = portConfig << 6 + portConfig << 4 + portConfig << 2 + portConfig; - // copy byte to portsConfig array slots - memset (portsConfig, portConfig, 5); - // write bytes all at once to device - I2Cdev::writeBytes(devAddr, MAX6956_RA_CONFIG_P15P14P13P12, 5, portsConfig); -} - -/** Write 1's to all port registers. This enables ports set as outputs and -* they will always have some brightness, port must be disabled to -* turn off completely. */ -void MAX6956::enableAllPorts() { - // set portStatus array to all 1's - memset (portsStatus, 0xFF, 3); - // write bytes - I2Cdev::writeByte(devAddr, MAX6956_RA_PORTS12_19, portsStatus[0]); - I2Cdev::writeByte(devAddr, MAX6956_RA_PORTS20_27, portsStatus[1]); - I2Cdev::writeByte(devAddr, MAX6956_RA_PORTS28_31, portsStatus[2]); -} - -/** Write 0's to all port registers. */ -void MAX6956::disableAllPorts() { - // set portStatus array to all 0's - memset (portsStatus, 0x00, 3); - // write bytes - I2Cdev::writeByte(devAddr, MAX6956_RA_PORTS12_19, portsStatus[0]); - I2Cdev::writeByte(devAddr, MAX6956_RA_PORTS20_27, portsStatus[1]); - I2Cdev::writeByte(devAddr, MAX6956_RA_PORTS28_31, portsStatus[2]); -} - - -/** Enables/Disables any port.set as a LED driver -*/ -void MAX6956::toggleLEDs() { - // Toggle power on all pins set as LED drivers - for (int i = 0; i < sizeof(portsConfig); i++){ - uint8_t portRA = 0; - uint8_t bitPosition = 0; - uint8_t psArrayIndex = 0; - for (int j = 3; j >= 0; j--){ - if (((portsConfig[i] >> (j * 2)) & B00000011) == 0) { - portRA = j+(i*4); - bitPosition = portRA % 8; // bit position to flip - psArrayIndex = portRA / 8; // array index - portRA += 44; // Finally adjust portRA for actual offset. - if (portsStatus[psArrayIndex] & (1 << bitPosition )) { - setPort(portRA, false); - } else { - setPort(portRA, true); - } - } - } - } -} - -/** Enables/Disables indiviual port. - @param port Port register address (MAX6956_RA_PORT12, ect) - @param enabled true or false - @see MAX6956_RA_PORT12 MAX6956_RA_PORT13 MAX6956_RA_PORT14 MAX6956_RA_PORT15 MAX6956_RA_PORT16 MAX6956_RA_PORT17 MAX6956_RA_PORT18 MAX6956_RA_PORT19 MAX6956_RA_PORT20 MAX6956_RA_PORT21 - MAX6956_RA_PORT22 MAX6956_RA_PORT23 MAX6956_RA_PORT24 MAX6956_RA_PORT25 MAX6956_RA_PORT26 MAX6956_RA_PORT27 MAX6956_RA_PORT28 MAX6956_RA_PORT29 MAX6956_RA_PORT30 MAX6956_RA_PORT31 -*/ -void MAX6956::setPort(uint8_t port, bool enabled) { - if ( port >= 44 && port <= 63) { - I2Cdev::writeByte(devAddr, port, enabled); - - #ifdef MAX6956_SERIAL_DEBUG - Serial.print("port "); - Serial.print(port, HEX); - Serial.print(" is "); - Serial.println(enabled); - #endif - - // Update portConfig array - uint8_t bitPosition = (port - 44) % 8; // bit position to flip - uint8_t psArrayIndex = (port - 44) / 8; // array index - portsStatus[psArrayIndex] &= ~(1 << bitPosition); - portsStatus[psArrayIndex] |= enabled << bitPosition; - } -} - -/** Takes an individual port register address (MAX6956_RA_PORT12, ect) - and returns the value of the port (data bit D0; D7–D1 read as 0) . - Returns 129 for out of bounds requests. - * @return data bit D0; D7–D1 read as 0. D7 set to 1 on out of bounds. - * @param port Port register address (MAX6956_RA_PORT12, ect) -*/ -uint8_t MAX6956::getPort(uint8_t port) { - if ( port >= 44 && port <= 63) { - I2Cdev::readByte(devAddr, port, buffer); // read port - - #ifdef MAX6956_SERIAL_DEBUG - Serial.print("port "); - Serial.print(port); - Serial.print(" is "); - Serial.println(buffer[0]); - #endif - - return buffer[0]; - } else - return 129; -} - -/** Reads the value of the transition detection ports (24-30) all at once. - * @return uint8_t value of ports -*/ -uint8_t MAX6956::getTransitionPorts() { - I2Cdev::readByte(devAddr, 0x58, buffer); // read ports - - #ifdef MAX6956_SERIAL_DEBUG - Serial.print("Transition ports: "); - Serial.println(buffer[0], BIN); - #endif - - return buffer[0]; -} - -/** Takes an individual port register address (MAX6956_RA_PORT12, ect) - and sets it to a power scale where 0 = off. - * @param port Port register address (MAX6956_RA_PORT12, ect) - * @param power 0 is off, 15 is max brightness. -*/ -void MAX6956::setPortLevel(uint8_t port, uint8_t power) { - if ( port >= 44 && port <= 63 && power >= 0 && power <= 15 ) { - //power = sqrt(2) * power; // Convert linear to log scale - - psArrayIndex = (port - 44) / 8; // array index - psBitPosition = (port - 44) % 8; // bit position to flip - - if ( power > 0 ) { - // When not at 100% power decrement power by one because 0 is - // really an "on" power level and the lower levels are more important. - if ( power < 15 ) power--; - - // Calculate current register from port address - // set current bit offset - if ( port % 2 ) { //port is odd - portCurrentRA = (port - 1) / 2; - portCurrentBit = 7; - } - else { - portCurrentRA = port / 2; - portCurrentBit = 3; - } - - // Write changes - I2Cdev::writeBits(devAddr, portCurrentRA, portCurrentBit, 4, power); // Write changes - I2Cdev::writeByte(devAddr, port, MAX6956_ON); // turn on port - - #ifdef MAX6956_SERIAL_DEBUG - Serial.print("port "); - Serial.print(port); - Serial.print(" portCurrentBit "); - Serial.print(portCurrentBit); - Serial.print(" portCurrentRA "); - Serial.print(portCurrentRA, HEX); - Serial.print(" power "); - Serial.println(power ); - #endif - - // Update portStatus array - portsStatus[psArrayIndex] |= 1 << psBitPosition; - - } else { - I2Cdev::writeByte(devAddr, port, MAX6956_OFF); // turn off port - portsStatus[psArrayIndex] &= ~(1 << psBitPosition); // Update portStatus array - - #ifdef MAX6956_SERIAL_DEBUG - Serial.print("port "); - Serial.print(port); - Serial.println(" is off"); - #endif - } - } -} - - -/** Takes an INDIVIDUAL port register address (MAX6956_RA_PORT12, ect) - and sets it to a power level 0-15. 0 is min, 15 is max brightness. - * @param port Port register address (MAX6956_RA_PORT12, ect) - * @param power 0 is min, 15 is max brightness. -*/ -void MAX6956::setPortCurrent(uint8_t port, uint8_t power) { - if ( port >= 44 && port <= 63 && power >= 0 && power <= 15 ) { - //power = sqrt(2) * power; /** TODO Convert linear to log scale */ - - psArrayIndex = (port - 44) / 8; // array index - psBitPosition = (port - 44) % 8; // bit position to flip - - // Calculate current register from port address - // set current bit offset - if ( port % 2 ) { //port is odd - portCurrentRA = (port - 1) / 2; - portCurrentBit = 7; - } - else { - portCurrentRA = port / 2; - portCurrentBit = 3; - } - - // Write changes - I2Cdev::writeBits(devAddr, portCurrentRA, portCurrentBit, 4, power); // Write changes - I2Cdev::writeByte(devAddr, port, MAX6956_ON); // turn on port - - #ifdef MAX6956_SERIAL_DEBUG - Serial.print("port "); - Serial.print(port); - Serial.print(" portCurrentBit "); - Serial.print(portCurrentBit); - Serial.print(" portCurrentRA "); - Serial.print(portCurrentRA, HEX); - Serial.print(" power "); - Serial.println(power ); - #endif - // Update portStatus array - portsStatus[psArrayIndex] |= 1 << psBitPosition; - } -} - -/** Set ALL port current registers (MAX6956_RA_PORT12, ect) to - the SAME power level 0-15. 0 min brightness, 15 is max brightness. - @param power 0 is min, 15 is max brightness. -*/ -void MAX6956::setAllPortsCurrent(uint8_t power) { - for (int portCurrentRA=MAX6956_RA_CURRENT_0xP13P12; portCurrentRA <= MAX6956_RA_CURRENT_0xP31P30; portCurrentRA++){ - I2Cdev::writeByte(devAddr, portCurrentRA, power); - } -} diff --git a/Arduino/MAX6956/MAX6956.h b/Arduino/MAX6956/MAX6956.h deleted file mode 100644 index 0beaa366..00000000 --- a/Arduino/MAX6956/MAX6956.h +++ /dev/null @@ -1,573 +0,0 @@ -// I2Cdev library collection - MAX6956 I2C device class header file -// Based on Maxim MAX6956 datasheet 19-2414; Rev 4; 6/10 -// -// 2013-12-15 by Tom Beighley -// I2C Device Library hosted at http://www.i2cdevlib.com -// -// Changelog: -// 2013-12-15 - initial release -// - -/* ============================================ -I2Cdev device library code is placed under the MIT license -Copyright (c) 2013 Tom Beighley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -=============================================== -*/ - - -/*! \mainpage Maxim Integrated Products - -The MAX6956 compact, serial-interfaced LED display driver/I/O expander provide microprocessors with up to 28 ports. Each port is individually user configurable to either a logic input, logic output, or common-anode (CA) LED constant-current segment driver. Each port configured as an LED segment driver behaves as a digitally controlled constant-current sink, with 16 equal current steps from 1.5mA to 24mA. The LED drivers are suitable for both discrete LEDs and CA numeric and alphanumeric LED digits. - -Each port configured as a general-purpose I/O (GPIO) can be either a push-pull logic output capable of sink- ing 10mA and sourcing 4.5mA, or a Schmitt logic input with optional internal pullup. Seven ports feature config- urable transition detection logic, which generates an interrupt upon change of port logic level. The MAX6956 is controlled through an I2C-compatible 2-wire serial interface, and uses four-level logic to allow 16 I 2C addresses from only 2 select pins. - -The MAX6956AAX and MAX6956ATL have 28 ports and are available in 36-pin SSOP and 40-pin thin QFN packages, respectively. The MAX6956AAI and MAX6956ANI have 20 ports and are available in 28-pin SSOP and 28-pin DIP packages, respectively. - -For an SPI-interfaced version, refer to the MAX6957 data sheet. For a lower cost pin-compatible port expander without the constant-current LED drive capa- bility, refer to the MAX7300 data sheet. - -- 400kbps I2C-Compatible Serial Interface -- 2.5V to 5.5V Operation -- -40°C to +125°C Temperature Range -- 20 or 28 I/O Ports, Each Configurable as - - Constant-Current LED Driver - - Push-Pull Logic Output - - Schmitt Logic Input - - Schmitt Logic Input with Internal Pullup -- 11μA (max) Shutdown Current -- 16-Step Individually Programmable Current -- Control for Each LED -- Logic Transition Detection for Seven I/O Ports - -*/ - -#ifndef _MAX6956_H_ -#define _MAX6956_H_ - -#include "I2Cdev.h" - -// ----------------------------------------------------------------------------- -// Arduino-style "Serial.print" debug constant (uncomment to enable) -// ----------------------------------------------------------------------------- -// #define MAX6956_SERIAL_DEBUG - -/** -Table 3. I2C Address Map -======================== - -Pin|Pin|DEVICE ADDRESS | -:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:--: -AD1|AD0|A7 |A6 |A5 |A4 |A3 |A2 |A1 |A0 |HEX -GND|GND|1 |0 |0 |0 |0 |0 |0 |RW |0x40 -GND|V+ |1 |0 |0 |0 |0 |0 |1 |RW |0x41 -GND|SDA|1 |0 |0 |0 |0 |1 |0 |RW |0x42 -GND|SCL|1 |0 |0 |0 |0 |1 |1 |RW |0x43 -V+ |GND|1 |0 |0 |0 |1 |0 |0 |RW |0x44 -V+ |V+ |1 |0 |0 |0 |1 |0 |1 |RW |0x45 -V+ |SDA|1 |0 |0 |0 |1 |1 |0 |RW |0x46 -V+ |SCL|1 |0 |0 |0 |1 |1 |1 |RW |0x47 -SDA|GND|1 |0 |0 |1 |0 |0 |0 |RW |0x48 -SDA|V+ |1 |0 |0 |1 |0 |0 |1 |RW |0x49 -SDA|SDA|1 |0 |0 |1 |0 |1 |0 |RW |0x50 -SDA|SCL|1 |0 |0 |1 |0 |1 |1 |RW |0x51 -SCL|GND|1 |0 |0 |1 |1 |0 |0 |RW |0x52 -SCL|V+ |1 |0 |0 |1 |1 |0 |1 |RW |0x53 -SCL|SDA|1 |0 |0 |1 |1 |1 |0 |RW |0x54 -SCL|SCL|1 |0 |0 |1 |1 |1 |1 |RW |0x55 - -RW bit 0 = Write 1 = Read -*/ -#define MAX6956_ADDRESS 0x40 // See table 3 -#define MAX6956_DEFAULT_ADDRESS 0x40 // AD0 and AD1 at ground. - -//==========Registers========== - -#define MAX6956_RA_NO_OP 0x00 ///< No-op - -/** -Table 11. Global Segment Current Register Format -================================================ - -LED DRIVE |TYPICAL SEGMENT | ADDRESS | -FRACTION | CURRENT(mA) |CODE (HEX) |D7 |D6 |D5 |D4 |D3 |D2 |D1 |D0 |HEX CODE -:--------:|:--------------:|:----------:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:------: -1/16 | 1.5 | 0x02 |x |x |x |x |0 |0 |0 |0 |0xX0 -2/16 | 3 | 0x02 |x |x |x |x |0 |0 |0 |1 |0xX1 -3/16 | 4.5 | 0x02 |x |x |x |x |0 |0 |1 |0 |0xX2 -4/16 | 6 | 0x02 |x |x |x |x |0 |0 |1 |1 |0xX3 -5/16 | 7.5 | 0x02 |x |x |x |x |0 |1 |0 |0 |0xX4 -6/16 | 9 | 0x02 |x |x |x |x |0 |1 |0 |1 |0xX5 -7/16 | 10.5 | 0x02 |x |x |x |x |0 |1 |1 |0 |0xX6 -8/16 | 12 | 0x02 |x |x |x |x |0 |1 |1 |1 |0xX7 -9/16 | 13.5 | 0x02 |x |x |x |x |1 |0 |0 |0 |0xX8 -10/16 | 15 | 0x02 |x |x |x |x |1 |0 |0 |1 |0xX9 -11/16 | 16.5 | 0x02 |x |x |x |x |1 |0 |1 |0 |0xXA -12/16 | 18 | 0x02 |x |x |x |x |1 |0 |1 |1 |0xXB -13/16 | 19.5 | 0x02 |x |x |x |x |1 |1 |0 |0 |0xXC -14/16 | 21 | 0x02 |x |x |x |x |1 |1 |0 |1 |0xXD -15/16 | 22.5 | 0x02 |x |x |x |x |1 |1 |1 |0 |0xXE -16/16 | 24 | 0x02 |x |x |x |x |1 |1 |1 |1 |0xXF -*/ -#define MAX6956_RA_GLOBAL_CURRENT 0x02 - -/** -Table 7. Configuration Register Format -====================================== - -ADDRESS |D7 |D6 |D5 |D4 |D3 |D2 |D1 |D0 -:------:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-: -0x04 |M |I |x |x |x |x |x |S - -Table 8. Shutdown Control (S Data Bit D0) Format -================================================ - -FUNCTION |ADDRESS|D7 |D6 |D5 |D4 |D3 |D2 |D1 |D0 -:--------------:|:-----:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-: -Shutdown |0x04 |M |I |x |x |x |x |x |0 -Normal Operation|0x04 |M |I |x |x |x |x |x |1 - -Table 9. Global Current Control (I Data Bit D6) Format -====================================================== - -FUNCTION |ADDRESS|D7 |D6 |D5 |D4 |D3 |D2 |D1 |D0 -:----------------:|:-----:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-: -Global |0x04 |M |0 |x |x |x |x |x |S -Individual Segment|0x04 |M |1 |x |x |x |x |x |S - -Table 10. Transition Detection Control (M-Data Bit D7) Format -============================================================= - -FUNCTION |ADDRESS|D7 |D6 |D5 |D4 |D3 |D2 |D1 |D0 -:--------:|:-----:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-: -Disabled | 0x04 |0 |I |x |x |x |x |x |S -Enabled | 0x04 |1 |I |x |x |x |x |x |S - -*/ -#define MAX6956_RA_CONFIGURATION 0x04 - -/** -Table 15. Transition Detection Mask Register -============================================ - -|FUNCTION |REGISTER ADDRESS |READ/WRITE | D7 |D6 |D5 |D4 |D3 |D2 |D1 |D0 | -|---------------|-----------------|-----------|------------|----|----|----|----|----|----|----| -|Mask Register | 0x06 | Read | INT Status*|Port|Port|Port|Port|Port|Port|Port| -| | | | |30 |29 |28 |27 |26 |25 |24 | -| | |Write | Unchanged |mask|mask|mask|mask|mask|mask|mask| - -*INT is automatically cleared after it is read. - -*/ -#define MAX6956_RA_TRANSITION_DETECT 0x06 - -/** -Table 16. Display Test Register -=============================== - - |ADDR | -MODE |CODE |D7 |D6 |D5 |D4 |D3 |D2 |D1 |D0 -:------------- :|:---:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-: -Normal Operation |0x07 |x |x |x |x |x |x |x |0 -Display Test Mode|0x07 |x |x |x |x |x |x |x |1 - -*/ -#define MAX6956_RA_DISPLAY_TEST 0x07 - -/** -Table 1. Port Configuration Map -=============================== - -REGISTER |ADDRESS|D7 D6|D5 D4|D3 D2|D1 D0 ------------------------------------------|-------|-----|-----|-----|----- -Port Configuration for P7, P6, P5, P4 | 0x09 | P7 | P6 | P5 | P4 -Port Configuration for P11, P10, P9, P8 | 0x0A | P11 | P10 | P9 | P8 -Port Configuration for P15, P14, P13, P12| 0x0B | P15 | P14 | P13 | P12 -Port Configuration for P19, P18, P17, P16| 0x0C | P19 | P18 | P17 | P16 -Port Configuration for P23, P22, P21, P20| 0x0D | P23 | P22 | P21 | P20 -Port Configuration for P27, P26, P25, P24| 0x0E | P27 | P26 | P25 | P24 -Port Configuration for P31, P30, P29, P28| 0x0F | P31 | P30 | P29 | P28 - -Table 2. P4-P31 configuration bit pairs -======================================= - -
-    00 - Output, LED Segment Driver
-             Controlled  using port registers 0x20-0x5F. 
-             0 = High impedance
-             1 = Open-drain current sink, with sink current (up to 24mA) 
-                 determined by the appropriate current register
-    01 - Output, GPIO Output
-             Controlled  using port registers 0x20-0x5F. 
-             0 = Active-low logic output
-             1 = Active-high logic output
-    10 - Input, GPIO Input Without Pullup
-             Read port registers 0x20-0x5F.
-             Schmitt logic input 
-    11 - Input, GPIO Input with Pullup
-             Read port registers 0x20-0x5F.
-             Schmitt logic input with pullup
-
- -*/ -#define MAX6956_RA_CONFIG_P7P6P5P4 0x09 -#define MAX6956_RA_CONFIG_P11P10P9P8 0x0A -#define MAX6956_RA_CONFIG_P15P14P13P12 0x0B -#define MAX6956_RA_CONFIG_P19P18P17P16 0x0C -#define MAX6956_RA_CONFIG_P23P22P21P20 0x0D -#define MAX6956_RA_CONFIG_P27P26P25P24 0x0E -#define MAX6956_RA_CONFIG_P31P30P29P28 0x0F - -/** -Constant-current limit for each digit is -individually controlled by the settings in the -Current054 through Current1FE registers - -Table 12. Individual Port Current Registers -=========================================== - - | ADDRESS | | -FUNCTION |CODE(HEX)|D7 D6 D5 D4 | D3 D2 D1 D0 ---------------------|---------|------------|-------------- -Current054 register | 0x12 | Segment 5 | Segment 4 -Current076 register | 0x13 | Segment 7 | Segment 6 -Current098 register | 0x14 | Segment 9 | Segment 8 -Current0BA register | 0x15 | Segment 11 | Segment 10 -Current0DC register | 0x16 | Segment 13 | Segment 12 -Current0FE register | 0x17 | Segment 15 | Segment 14 -Current110 register | 0x18 | Segment 17 | Segment 16 -Current132 register | 0x19 | Segment 19 | Segment 18 -Current154 register | 0x1A | Segment 21 | Segment 20 -Current176 register | 0x1B | Segment 23 | Segment 22 -Current198 register | 0x1C | Segment 25 | Segment 24 -Current1BA register | 0x1D | Segment 27 | Segment 26 -Current1DC register | 0x1E | Segment 29 | Segment 28 -Current1FE register | 0x1F | Segment 31 | Segment 30 - -Register data is 0-Fx0-F for 1-16(0-F) brightness levels. -To completely blank an output turn it off (0) using port -configuration registers. -*/ -#define MAX6956_RA_CURRENT_0xP5P4 0x12 -#define MAX6956_RA_CURRENT_0xP7P6 0x13 -#define MAX6956_RA_CURRENT_0xP9P8 0x14 -#define MAX6956_RA_CURRENT_0xP11P10 0x15 -#define MAX6956_RA_CURRENT_0xP13P12 0x16 -#define MAX6956_RA_CURRENT_0xP15P14 0x17 -#define MAX6956_RA_CURRENT_0xP17P16 0x18 -#define MAX6956_RA_CURRENT_0xP19P18 0x19 -#define MAX6956_RA_CURRENT_0xP21P20 0x1A -#define MAX6956_RA_CURRENT_0xP23P22 0x1B -#define MAX6956_RA_CURRENT_0xP25P24 0x1C -#define MAX6956_RA_CURRENT_0xP27P26 0x1D -#define MAX6956_RA_CURRENT_0xP29P28 0x1E -#define MAX6956_RA_CURRENT_0xP31P30 0x1F - -/** -Individiual Port Registers -========================== - - data bit D0; D7-D1 read as 0 -*/ -#define MAX6956_RA_PORT0 0x20 ///< (virtual port, no action) -#define MAX6956_RA_PORT1 0x21 ///< (virtual port, no action) -#define MAX6956_RA_PORT2 0x22 ///< (virtual port, no action) -#define MAX6956_RA_PORT3 0x23 ///< (virtual port, no action) - -#define MAX6956_RA_PORT4 0x24 -#define MAX6956_RA_PORT5 0x25 -#define MAX6956_RA_PORT6 0x26 -#define MAX6956_RA_PORT7 0x27 -#define MAX6956_RA_PORT8 0x28 -#define MAX6956_RA_PORT9 0x29 -#define MAX6956_RA_PORT10 0x2A -#define MAX6956_RA_PORT11 0x2B - -#define MAX6956_RA_PORT12 0x2C -#define MAX6956_RA_PORT13 0x2D -#define MAX6956_RA_PORT14 0x2E -#define MAX6956_RA_PORT15 0x2F -#define MAX6956_RA_PORT16 0x30 -#define MAX6956_RA_PORT17 0x31 -#define MAX6956_RA_PORT18 0x32 -#define MAX6956_RA_PORT19 0x33 - -#define MAX6956_RA_PORT20 0x34 -#define MAX6956_RA_PORT21 0x35 -#define MAX6956_RA_PORT22 0x36 -#define MAX6956_RA_PORT23 0x37 -#define MAX6956_RA_PORT24 0x38 -#define MAX6956_RA_PORT25 0x39 -#define MAX6956_RA_PORT26 0x3A -#define MAX6956_RA_PORT27 0x3B - -#define MAX6956_RA_PORT28 0x3C -#define MAX6956_RA_PORT29 0x3D -#define MAX6956_RA_PORT30 0x3E -#define MAX6956_RA_PORT31 0x3F -/* - Lower port groups -*/ -#define MAX6956_RA_PORTS4_7 0x40 ///< data bits D0-D3; D4-D7 read as 0 -#define MAX6956_RA_PORTS4_8 0x41 ///< data bits D0-D4; D5-D7 read as 0 -#define MAX6956_RA_PORTS4_9 0x42 ///< data bits D0-D5; D6-D7 read as 0 -#define MAX6956_RA_PORTS4_10 0x43 ///< data bits D0-D6; D7 reads as 0 - -/* - 8 port registers. Data bits D0-D7 -*/ -#define MAX6956_RA_PORTS4_11 0x44 -#define MAX6956_RA_PORTS5_12 0x45 -#define MAX6956_RA_PORTS6_13 0x46 -#define MAX6956_RA_PORTS7_14 0x47 -#define MAX6956_RA_PORTS8_15 0x48 -#define MAX6956_RA_PORTS9_16 0x49 -#define MAX6956_RA_PORTS10_17 0x4A -#define MAX6956_RA_PORTS11_18 0x4B -#define MAX6956_RA_PORTS12_19 0x4C -#define MAX6956_RA_PORTS13_20 0x4D -#define MAX6956_RA_PORTS14_21 0x4E -#define MAX6956_RA_PORTS15_22 0x4F -#define MAX6956_RA_PORTS16_23 0x50 -#define MAX6956_RA_PORTS17_24 0x51 -#define MAX6956_RA_PORTS18_25 0x52 -#define MAX6956_RA_PORTS19_26 0x53 -#define MAX6956_RA_PORTS20_27 0x54 -#define MAX6956_RA_PORTS21_28 0x55 -#define MAX6956_RA_PORTS22_29 0x56 -#define MAX6956_RA_PORTS23_30 0x57 -#define MAX6956_RA_PORTS24_31 0x58 -/* - Upper port groups -*/ -#define MAX6956_RA_PORTS25_31 0x59 ///< data bits D0-D6; D7 reads as 0 -#define MAX6956_RA_PORTS26_31 0x5A ///< data bits D0-D5; D6-D7 read as 0 -#define MAX6956_RA_PORTS27_31 0x5B ///< data bits D0-D4; D5-D7 read as 0 -#define MAX6956_RA_PORTS28_31 0x5C ///< data bits D0-D3; D4-D7 read as 0 -#define MAX6956_RA_PORTS29_31 0x5D ///< data bits D0-D2; D3-D7 read as 0 -#define MAX6956_RA_PORTS30_31 0x5E ///< data bits D0-D1; D2-D7 read as 0 -#define MAX6956_RA_PORTS31_31 0x5F ///< data bit D0; D1-D7 read as 0. Port 31 only. - -//=========Config bits========= - -#define MAX6956_CONFIG_POWER_BIT 0 ///< 0 = Shutdown, 1 = Normal operation -#define MAX6956_CONFIG_GLOBAL_CURRENT_BIT 6 ///< 0 = Global control, 1 = Individual control -#define MAX6956_CONFIG_TRANSITION_BIT 7 ///< 0 = Disabled, 1 = Enabled - -#define MAX6956_GLOBAL_CURRENT_BIT 0 ///< Global current start bit -#define MAX6956_GLOBAL_CURRENT_LENGTH 4 ///< nybble long - -#define MAX6956_PORT12_CURRENT_BIT 3 ///< LSNybble -#define MAX6956_PORT12_CURRENT_LENGTH 4 ///< nybble long -#define MAX6956_PORT13_CURRENT_BIT 7 ///< MSNybble -#define MAX6956_PORT13_CURRENT_LENGTH 4 ///< nybble long -#define MAX6956_PORT14_CURRENT_BIT 3 ///< LSNybble -#define MAX6956_PORT14_CURRENT_LENGTH 4 ///< nybble long -#define MAX6956_PORT15_CURRENT_BIT 7 ///< MSNybble -#define MAX6956_PORT15_CURRENT_LENGTH 4 ///< nybble long -#define MAX6956_PORT16_CURRENT_BIT 3 ///< LSNybble -#define MAX6956_PORT16_CURRENT_LENGTH 4 ///< nybble long -#define MAX6956_PORT17_CURRENT_BIT 7 ///< MSNybble -#define MAX6956_PORT17_CURRENT_LENGTH 4 ///< nybble long -#define MAX6956_PORT18_CURRENT_BIT 3 ///< LSNybble -#define MAX6956_PORT18_CURRENT_LENGTH 4 ///< nybble long -#define MAX6956_PORT19_CURRENT_BIT 7 ///< MSNybble -#define MAX6956_PORT19_CURRENT_LENGTH 4 ///< nybble long -#define MAX6956_PORT23_CURRENT_BIT 3 ///< LSNybble -#define MAX6956_PORT23_CURRENT_LENGTH 4 ///< nybble long -#define MAX6956_PORT21_CURRENT_BIT 7 ///< MSNybble -#define MAX6956_PORT21_CURRENT_LENGTH 4 ///< nybble long -#define MAX6956_PORT22_CURRENT_BIT 3 ///< LSNybble -#define MAX6956_PORT22_CURRENT_LENGTH 4 ///< nybble long -#define MAX6956_PORT23_CURRENT_BIT 7 ///< MSNybble -#define MAX6956_PORT23_CURRENT_LENGTH 4 ///< nybble long -#define MAX6956_PORT24_CURRENT_BIT 3 ///< LSNybble -#define MAX6956_PORT24_CURRENT_LENGTH 4 ///< nybble long -#define MAX6956_PORT25_CURRENT_BIT 7 ///< MSNybble -#define MAX6956_PORT25_CURRENT_LENGTH 4 ///< nybble long -#define MAX6956_PORT26_CURRENT_BIT 3 ///< LSNybble -#define MAX6956_PORT26_CURRENT_LENGTH 4 ///< nybble long -#define MAX6956_PORT27_CURRENT_BIT 7 ///< MSNybble -#define MAX6956_PORT27_CURRENT_LENGTH 4 ///< nybble long -#define MAX6956_PORT28_CURRENT_BIT 3 ///< LSNybble -#define MAX6956_PORT28_CURRENT_LENGTH 4 ///< nybble long -#define MAX6956_PORT29_CURRENT_BIT 7 ///< MSNybble -#define MAX6956_PORT29_CURRENT_LENGTH 4 ///< nybble long -#define MAX6956_PORT33_CURRENT_BIT 3 ///< LSNybble -#define MAX6956_PORT33_CURRENT_LENGTH 4 ///< nybble long -#define MAX6956_PORT31_CURRENT_BIT 7 ///< MSNybble -#define MAX6956_PORT31_CURRENT_LENGTH 4 ///< nybble long - -#define MAX6956_DISPLAY_TEST_BIT 0 ///< 0 = Normal operation, 1 = Display test - -#define MAX6956_TRANSITION_STATUS_BIT 7 ///< INT Status, INT is automatically cleared after it is read. -#define MAX6956_TRANSITION_MASK_BIT 0 ///< Ports 24-30 -#define MAX6956_TRANSITION_MASK_LENGTH 7 -#define MAX6956_TRANSITION_MASK_PORT30_BIT 6 -#define MAX6956_TRANSITION_MASK_PORT29_BIT 5 -#define MAX6956_TRANSITION_MASK_PORT28_BIT 4 -#define MAX6956_TRANSITION_MASK_PORT27_BIT 3 -#define MAX6956_TRANSITION_MASK_PORT26_BIT 2 -#define MAX6956_TRANSITION_MASK_PORT25_BIT 1 -#define MAX6956_TRANSITION_MASK_PORT24_BIT 0 - -//=========Values========= - -#define MAX6956_OUTPUT_LED 0x00 -#define MAX6956_OUTPUT_GPIO 0x01 -#define MAX6956_INPUT_WO_PULL 0x02 -#define MAX6956_INPUT_W_PULL 0x03 - -#define MAX6956_OFF 0x00 -#define MAX6956_ON 0x01 - -#define MAX6956_CURRENT_0 0x00 -#define MAX6956_CURRENT_1 0x01 -#define MAX6956_CURRENT_2 0x02 -#define MAX6956_CURRENT_3 0x03 -#define MAX6956_CURRENT_4 0x04 -#define MAX6956_CURRENT_5 0x05 -#define MAX6956_CURRENT_6 0x06 -#define MAX6956_CURRENT_7 0x07 -#define MAX6956_CURRENT_8 0x08 -#define MAX6956_CURRENT_9 0x09 -#define MAX6956_CURRENT_10 0x0A -#define MAX6956_CURRENT_11 0x0B -#define MAX6956_CURRENT_12 0x0C -#define MAX6956_CURRENT_13 0x0D -#define MAX6956_CURRENT_14 0x0E -#define MAX6956_CURRENT_15 0x0F - -/*! -A library for controlling the MAX6956 using i2C. -*/ -class MAX6956 { - public: - MAX6956(); - MAX6956(uint8_t address); - - void initialize(); - bool testConnection(); - - void reset(); - - // Config register - uint8_t getConfigReg(); - void setConfigReg(uint8_t config); - - bool getPower(); - void togglePower(); - void setPower(bool power); - - bool getEnableIndividualCurrent(); - void setEnableIndividualCurrent(bool global); - - bool getEnableTransitionDetection(); - void setEnableTransitionDetection(bool transition); - - // Global current - uint8_t getGlobalCurrent(); - void setGlobalCurrent(uint8_t current); - - // Test mode - bool getTestMode(); - void setTestMode(bool test); - - // Input mask - uint8_t getInputMask(); - void setInputMask(uint8_t mask); - - // Port config - void configPort(uint8_t port, uint8_t portConfig); - void configPorts(uint8_t lower, uint8_t upper, uint8_t portConfig); - void configAllPorts(uint8_t portConfig); - - void enableAllPorts(); - void disableAllPorts(); - void toggleLEDs(); - void setPort(uint8_t port, bool enabled); ///< enabled = true, disabled = false - uint8_t getPort(uint8_t port); ///< Value of port, 0 or 1 - uint8_t getTransitionPorts(); ///< Reads the value of the transition detection ports (24-30) all at once. - - void setPortLevel(uint8_t port, uint8_t power); ///< 0 = off, 1-15 brightness levels. - void setPortCurrent(uint8_t port, uint8_t power); ///< 0-15 brightness levels. - void setAllPortsCurrent(uint8_t power); ///< 0-15, 0 = min brightness (not off) 15 = max - - /** - Array that mirrors the configuration of all the ports. - - P12 = portsConfig[0][1-0] - P13 = portsConfig[0][3-2] - P14 = portsConfig[0][5-4] - P15 = portsConfig[0][7-6] - P16 = portsConfig[1][1-0] - P17 = portsConfig[1][3-2] - P18 = portsConfig[1][5-4] - P19 = portsConfig[1][7-6] - P20 = portsConfig[2][1-0] - P21 = portsConfig[2][3-2] - P22 = portsConfig[2][5-4] - P23 = portsConfig[2][7-6] - P24 = portsConfig[3][1-0] - P25 = portsConfig[3][3-2] - P26 = portsConfig[3][5-4] - P27 = portsConfig[3][7-6] - P28 = portsConfig[4][1-0] - P29 = portsConfig[4][3-2] - P30 = portsConfig[4][5-4] - P31 = portsConfig[4][7-6] - */ - uint8_t portsConfig[5]; - /** - Array that mirrors the on/off status of all the ports. - - P12 = portsStatus[0][0] - P13 = portsStatus[0][1] - P14 = portsStatus[0][2] - P15 = portsStatus[0][3] - P16 = portsStatus[0][4] - P17 = portsStatus[0][5] - P18 = portsStatus[0][6] - P19 = portsStatus[0][7] - P20 = portsStatus[1][0] - P21 = portsStatus[1][1] - P22 = portsStatus[1][2] - P23 = portsStatus[1][3] - P24 = portsStatus[1][4] - P25 = portsStatus[1][5] - P26 = portsStatus[1][6] - P27 = portsStatus[1][7] - P28 = portsStatus[2][0] - P29 = portsStatus[2][1] - P30 = portsStatus[2][2] - P31 = portsStatus[2][3] - */ - uint8_t portsStatus[3]; - - private: - uint8_t devAddr; ///< Holds the current device address - uint8_t buffer[1]; ///< Buffer for reading data from the device - uint8_t portConfig; ///< Holder for port config bit pair - uint8_t portCurrentRA; ///< Holder for port current register - uint8_t portCurrentBit; ///< Holder for the current bit offset - uint8_t psArrayIndex; ///< array index - uint8_t psBitPosition; ///< bit position -}; - -#endif /* _MAX6956_H_ */ diff --git a/Arduino/MAX6956/comments.txt b/Arduino/MAX6956/comments.txt deleted file mode 100644 index 3a9e0526..00000000 --- a/Arduino/MAX6956/comments.txt +++ /dev/null @@ -1,64 +0,0 @@ -/** - -void MAX6956::configPort(uint8_t port, uint8_t portConfig) example math - - 0x0B 11 MAX6956_RA_CONFIG_P15P14P13P12 - 0x0C 12 MAX6956_RA_CONFIG_P19P18P17P16 - 0x0D 13 MAX6956_RA_CONFIG_P23P22P21P20 - 0x0E 14 MAX6956_RA_CONFIG_P27P26P25P24 - 0x0F 15 MAX6956_RA_CONFIG_P31P30P29P28 - - (56, 2) port 24, input without pullup - bitPosition = (((56 - 44) % 4) * 2) + 1 - ((12 % 4) * 2) + 1 - ( 0 * 2 ) + 1 - 0 + 1 - 1 - - pcArrayIndex = ((56 - 44) / 4) - (12 / 4) - 3 (any remainder is dropped when stored as an int ... I think) - - portConfigRA = pcArrayIndex + 11 - 14 - - bitPosition = 0 - mask = 0000 0011 - 0000 0011 << 0 - 0000 0011 - ~1111 1100 - 0011 1111 & portsConfig[x] - - portConfig = 0000 0010 << 0 - 0000 0010 - - xxxx xx00 | 0000 0010 - xxxx xx10 - - (63, 2) port 31, input without pullup - bitPosition = (((63 - 44) % 4) * 2) + 1 - ((19 % 4) * 2) + 1 - ( 3 * 2 ) + 1 - 6 + 1 - 7 - - pcArrayIndex = ((63 - 44) / 4) - (19 / 4) - 4.75 (any remainder is dropped when stored as an int ... I think) - - portConfigRA = pcArrayIndex + 11 - 15 - - bitPosition = 07 - mask = 0000 0011 - 0000 0011 << 6 - 1100 0000 - ~0011 1111 - 0011 1111 & portsConfig[x] - - portConfig = 0000 0010 << 6 - 1000 0000 - - 00xx xxxx | 1000 0000 - 10xx xxxx -*/ diff --git a/Arduino/MAX6956/html/MAX6956_8cpp.html b/Arduino/MAX6956/html/MAX6956_8cpp.html deleted file mode 100644 index e5d937a0..00000000 --- a/Arduino/MAX6956/html/MAX6956_8cpp.html +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - -MAX6956: MAX6956.cpp File Reference - - - - - - - - - -
-
-
- - - - - -
-
MAX6956 -  1.0 -
-
MAX6956i2Clibrary
-
- - - - - - - - - - -
- -
- - -
-
-
MAX6956.cpp File Reference
-
- - - - - diff --git a/Arduino/MAX6956/html/MAX6956_8cpp_source.html b/Arduino/MAX6956/html/MAX6956_8cpp_source.html deleted file mode 100644 index cc2f649b..00000000 --- a/Arduino/MAX6956/html/MAX6956_8cpp_source.html +++ /dev/null @@ -1,463 +0,0 @@ - - - - - - -MAX6956: MAX6956.cpp Source File - - - - - - - - - -
-
- - - - - - -
-
MAX6956 -  1.0 -
-
MAX6956i2Clibrary
-
-
- - - - - -
- - - - -
- -
- -
-
-
MAX6956.cpp
-
-
-Go to the documentation of this file.
1 // I2Cdev library collection - MAX6956 I2C device class
-
2 // Based on Maxim MAX6956 datasheet 19-2414; Rev 4; 6/10
-
3 //
-
4 // 2013-12-15 by Tom Beighley <tomthegeek@gmail.com>
-
5 // I2C Device Library hosted at http://www.i2cdevlib.com
-
6 //
-
7 // Changelog:
-
8 // 2013-12-15 - initial release
-
9 //
-
10 
-
11 /* ============================================
-
12 I2Cdev device library code is placed under the MIT license
-
13 Copyright (c) 2013 Tom Beighley
-
14 
-
15 Permission is hereby granted, free of charge, to any person obtaining a copy
-
16 of this software and associated documentation files (the "Software"), to deal
-
17 in the Software without restriction, including without limitation the rights
-
18 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-
19 copies of the Software, and to permit persons to whom the Software is
-
20 furnished to do so, subject to the following conditions:
-
21 
-
22 The above copyright notice and this permission notice shall be included in
-
23 all copies or substantial portions of the Software.
-
24 
-
25 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-
26 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-
27 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-
28 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-
29 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-
30 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-
31 THE SOFTWARE.
-
32 ===============================================
-
33 */
-
34 
-
35 #include "MAX6956.h"
-
36 
- - -
42 }
-
43 
-
49 MAX6956::MAX6956(uint8_t address) {
-
50  devAddr = address;
-
51 }
-
52 
- -
55  // Need this in setup() or here.
-
56  // Fastwire::setup(400, false);
-
57  reset();
-
58 
-
64  I2Cdev::writeByte(devAddr, MAX6956_RA_CONFIG_P7P6P5P4, 0x55);
-
65  I2Cdev::writeByte(devAddr, MAX6956_RA_CONFIG_P11P10P9P8, 0x55);
-
66 }
-
67 
- -
73  if (I2Cdev::readByte(devAddr, MAX6956_RA_CONFIGURATION, buffer) == 1) {
-
74  return true;
-
75  }
-
76  return false;
-
77 }
-
78 
- -
81  disableAllPorts(); // set Port RA 0x2C-0x3F to 0
-
82  setGlobalCurrent(0x00); // Set global current to minimum on
-
83  setConfigReg(0x00); // Shutdown Enabled,Current Control = Global, Transition Detection Disabled
-
84  setInputMask(0x00); // Set Input register mask to 0
-
85  setTestMode(false); // disable test mode
-
86  configAllPorts(MAX6956_INPUT_WO_PULL); // Configure all inputs as MAX6956_INPUT_WO_PULL
-
87  setAllPortsCurrent(0x00); // Set current RA 0x16-01F to 0
-
88 }
-
89 
- -
95  I2Cdev::readByte(devAddr, MAX6956_RA_CONFIGURATION, buffer);
-
96  return buffer[0];
-
97 }
-
102 void MAX6956::setConfigReg(uint8_t config) {
-
103  I2Cdev::writeByte(devAddr, MAX6956_RA_CONFIGURATION, config);
-
104 }
-
105 
- - -
112  return buffer[0];
-
113 }
-
118 void MAX6956::setPower(bool power) {
-
119  I2Cdev::writeBit(devAddr, MAX6956_RA_CONFIGURATION, MAX6956_CONFIG_POWER_BIT, power);
-
120 }
- - -
126  buffer[0] = !(buffer[0]);
- -
128 }
-
129 
- - -
136  return buffer[0];
-
137 }
- - -
146 }
-
147 
- - -
154  return buffer[0];
-
155 }
- -
163  I2Cdev::writeBit(devAddr, MAX6956_RA_CONFIGURATION, MAX6956_CONFIG_TRANSITION_BIT, transition);
-
164 }
-
165 
-
166 // Global Current
- - -
173  return buffer[0];
-
174 }
-
179 void MAX6956::setGlobalCurrent(uint8_t current) {
-
180  I2Cdev::writeByte(devAddr, MAX6956_RA_GLOBAL_CURRENT, current);
-
181 }
-
182 
-
183 // Test mode
- - -
190  return buffer[0];
-
191 }
-
196 void MAX6956::setTestMode(bool test) {
-
197  I2Cdev::writeByte(devAddr, MAX6956_RA_DISPLAY_TEST, test);
-
198 }
-
199 
-
200 // Input mask register
- -
206  I2Cdev::readByte(devAddr, MAX6956_RA_TRANSITION_DETECT, buffer);
-
207  return buffer[0];
-
208 }
-
209 
-
214 void MAX6956::setInputMask(uint8_t mask) {
-
215  I2Cdev::writeByte(devAddr, MAX6956_RA_TRANSITION_DETECT, mask);
-
216 }
-
217 
-
218 
-
265 void MAX6956::configPort(uint8_t port, uint8_t portConfig) {
-
266  uint8_t bitPosition = (((port - 44) % 4) * 2) + 1; // bit position to start flipping
-
267  uint8_t pcArrayIndex = (port - 44) / 4; // array index
-
268  uint8_t portConfigRA = pcArrayIndex + 11; // port config register
-
269  I2Cdev::writeBits(devAddr, portConfigRA, bitPosition, 2, portConfig);
-
270  // Update portConfig array
-
271  bitPosition--; // Remove 1 bit offset
-
272  portsConfig[pcArrayIndex] &= ~(3 << bitPosition);
-
273  portsConfig[pcArrayIndex] |= portConfig << bitPosition;
-
274 }
-
275 
-
285 void MAX6956::configPorts(uint8_t lower, uint8_t upper, uint8_t portConfig) {
-
286 
-
287  Serial.print("lower ");
-
288  Serial.print(lower, HEX);
-
289  Serial.print(" upper ");
-
290  Serial.print(upper, HEX);
-
291  Serial.print(" portConfig ");
-
292  Serial.println(portConfig, BIN);
-
293 
-
294  uint8_t bitPosition = 0;
-
295  uint8_t pcArrayIndex = 0;
-
296  uint8_t portConfigRA = 0;
-
297  uint8_t i = lower;
-
298 
-
299  while ( i <= upper ) {
-
300  bitPosition = (((i - 44) % 4) * 2) + 1; // bit position to start flipping
-
301  pcArrayIndex = (i - 44) / 4; // array index
-
302  portConfigRA = pcArrayIndex + 11; // port config register
-
303  Serial.print("i ");
-
304  Serial.print(i);
-
305  Serial.print(" bitPosition ");
-
306  Serial.print(bitPosition);
-
307  Serial.print(" pcArrayIndex");
-
308  Serial.print(pcArrayIndex);
-
309  Serial.print(" portConfigRA ");
-
310  Serial.println(portConfigRA, HEX);
-
311  I2Cdev::writeBits(devAddr, portConfigRA, bitPosition, 2, portConfig);
-
312  // Update portConfig array
-
313  Serial.print("portsConfig ");
-
314  Serial.print(portsConfig[pcArrayIndex], BIN);
-
315  bitPosition--; // Remove 1 bit offset
-
316  portsConfig[pcArrayIndex] &= ~(3 << bitPosition); //3 == B00000011 Shift over correct number of bits then invert to create the mask
-
317  portsConfig[pcArrayIndex] |= portConfig << bitPosition;
-
318  Serial.print(" >> ");
-
319  Serial.println(portsConfig[pcArrayIndex], BIN);
-
320  i++;
-
321  }
-
322 
-
323 }
-
324 
-
332 void MAX6956::configAllPorts(uint8_t portConfig) {
-
333  // build byte with config bits shifted to all 4 slots
-
334  portConfig = portConfig << 6 + portConfig << 4 + portConfig << 2 + portConfig;
-
335  // copy byte to portsConfig array slots
-
336  memset (portsConfig, portConfig, 5);
-
337  // write bytes all at once to device
-
338  I2Cdev::writeBytes(devAddr, MAX6956_RA_CONFIG_P15P14P13P12, 5, portsConfig);
-
339 }
-
340 
-
346 void MAX6956::setPortLevel(uint8_t port, uint8_t power) {
-
347  if ( port >= 44 && port <= 63 && power >= 0 && power <= 15 ) {
-
348  //power = sqrt(2) * power; // Convert linear to log scale
-
349 
-
350  psArrayIndex = (port - 44) / 8; // array index
-
351  psBitPosition = (port - 44) % 8; // bit position to flip
-
352 
-
353  if ( power > 0 ) {
-
354  // When not at 100% power decrement power by one because 0 is
-
355  // really an "on" power level and the lower levels are more important.
-
356  if ( power < 15 ) power--;
-
357 
-
358  // Calculate current register from port address
-
359  // set current bit offset
-
360  if ( port % 2 ) { //port is odd
-
361  portCurrentRA = (port - 1) / 2;
-
362  portCurrentBit = 7;
-
363  }
-
364  else {
-
365  portCurrentRA = port / 2;
-
366  portCurrentBit = 3;
-
367  }
-
368 
-
369  // Write changes
-
370  I2Cdev::writeBits(devAddr, portCurrentRA, portCurrentBit, 4, power); // Write changes
-
371  I2Cdev::writeByte(devAddr, port, MAX6956_ON); // turn on port
-
372 
-
373  #ifdef MAX6956_SERIAL_DEBUG
-
374  Serial.print("port ");
-
375  Serial.print(port);
-
376  Serial.print(" portCurrentBit ");
-
377  Serial.print(portCurrentBit);
-
378  Serial.print(" portCurrentRA ");
-
379  Serial.print(portCurrentRA, HEX);
-
380  Serial.print(" power ");
-
381  Serial.println(power );
-
382  #endif
-
383  // Update portStatus array
- -
385  } else {
-
386  I2Cdev::writeByte(devAddr, port, MAX6956_OFF); // turn off port
-
387  portsStatus[psArrayIndex] &= ~(1 << psBitPosition); // Update portStatus array
-
388 
-
389  #ifdef MAX6956_SERIAL_DEBUG
-
390  Serial.print("port ");
-
391  Serial.print(port);
-
392  Serial.println(" is off");
-
393  #endif
-
394  }
-
395  }
-
396 }
-
397 
-
398 
-
404 void MAX6956::setPortCurrent(uint8_t port, uint8_t power) {
-
405  if ( port >= 44 && port <= 63 && power >= 0 && power <= 15 ) {
-
406  //power = sqrt(2) * power; /** TODO Convert linear to log scale */
-
407 
-
408  psArrayIndex = (port - 44) / 8; // array index
-
409  psBitPosition = (port - 44) % 8; // bit position to flip
-
410 
-
411  // Calculate current register from port address
-
412  // set current bit offset
-
413  if ( port % 2 ) { //port is odd
-
414  portCurrentRA = (port - 1) / 2;
-
415  portCurrentBit = 7;
-
416  }
-
417  else {
-
418  portCurrentRA = port / 2;
-
419  portCurrentBit = 3;
-
420  }
-
421 
-
422  // Write changes
-
423  I2Cdev::writeBits(devAddr, portCurrentRA, portCurrentBit, 4, power); // Write changes
-
424  I2Cdev::writeByte(devAddr, port, MAX6956_ON); // turn on port
-
425 
-
426  #ifdef MAX6956_SERIAL_DEBUG
-
427  Serial.print("port ");
-
428  Serial.print(port);
-
429  Serial.print(" portCurrentBit ");
-
430  Serial.print(portCurrentBit);
-
431  Serial.print(" portCurrentRA ");
-
432  Serial.print(portCurrentRA, HEX);
-
433  Serial.print(" power ");
-
434  Serial.println(power );
-
435  #endif
-
436  // Update portStatus array
- -
438  }
-
439 }
-
444 void MAX6956::setAllPortsCurrent(uint8_t power) {
- -
446  I2Cdev::writeByte(devAddr, portCurrentRA, power);
-
447  }
-
448 }
-
449 
- -
454  // set portStatus array to all 1's
-
455  memset (portsStatus, 0xFF, 3);
-
456  // write bytes
-
457  I2Cdev::writeByte(devAddr, MAX6956_RA_PORTS12_19, portsStatus[0]);
-
458  I2Cdev::writeByte(devAddr, MAX6956_RA_PORTS20_27, portsStatus[1]);
-
459  I2Cdev::writeByte(devAddr, MAX6956_RA_PORTS28_31, portsStatus[2]);
-
460 }
-
461 
- -
464  // set portStatus array to all 0's
-
465  memset (portsStatus, 0x00, 3);
-
466  // write bytes
-
467  I2Cdev::writeByte(devAddr, MAX6956_RA_PORTS12_19, portsStatus[0]);
-
468  I2Cdev::writeByte(devAddr, MAX6956_RA_PORTS20_27, portsStatus[1]);
-
469  I2Cdev::writeByte(devAddr, MAX6956_RA_PORTS28_31, portsStatus[2]);
-
470 }
-
uint8_t devAddr
Holds the current device address.
Definition: MAX6956.h:555
-
uint8_t portCurrentRA
Holder for port current register.
Definition: MAX6956.h:558
-
uint8_t psArrayIndex
array index
Definition: MAX6956.h:560
-
void enableAllPorts()
Definition: MAX6956.cpp:453
-
bool getEnableTransitionDetection()
Definition: MAX6956.cpp:152
-
#define MAX6956_RA_GLOBAL_CURRENT
Definition: MAX6956.h:102
-
uint8_t getInputMask()
Definition: MAX6956.cpp:205
-
void disableAllPorts()
Definition: MAX6956.cpp:463
-
bool getEnableIndividualCurrent()
Definition: MAX6956.cpp:134
-
#define MAX6956_RA_DISPLAY_TEST
Definition: MAX6956.h:165
-
void setPower(bool power)
Definition: MAX6956.cpp:118
-
#define MAX6956_INPUT_WO_PULL
Definition: MAX6956.h:408
-
#define MAX6956_ON
Definition: MAX6956.h:412
-
#define MAX6956_OFF
Definition: MAX6956.h:411
-
#define MAX6956_CONFIG_POWER_BIT
0 = Shutdown, 1 = Normal operation
Definition: MAX6956.h:343
-
void configPort(uint8_t port, uint8_t portConfig)
Definition: MAX6956.cpp:265
-
void setAllPortsCurrent(uint8_t power)
0-15, 0 = min brightness (not off) 15 = max
Definition: MAX6956.cpp:444
-
#define MAX6956_RA_CONFIG_P15P14P13P12
Definition: MAX6956.h:205
-
void configPorts(uint8_t lower, uint8_t upper, uint8_t portConfig)
Definition: MAX6956.cpp:285
-
uint8_t portsConfig[5]
Definition: MAX6956.h:527
-
uint8_t getGlobalCurrent()
Definition: MAX6956.cpp:171
-
#define MAX6956_DISPLAY_TEST_BIT
0 = Normal operation, 1 = Display test
Definition: MAX6956.h:391
-
#define MAX6956_RA_CONFIGURATION
Definition: MAX6956.h:137
-
bool getTestMode()
Definition: MAX6956.cpp:188
-
uint8_t psBitPosition
bit position
Definition: MAX6956.h:561
-
#define MAX6956_RA_PORTS20_27
Definition: MAX6956.h:325
-
#define MAX6956_RA_PORTS28_31
data bits D0-D3; D4-D7 read as 0
Definition: MAX6956.h:336
-
#define MAX6956_RA_PORTS12_19
Definition: MAX6956.h:317
-
uint8_t portsStatus[3]
Definition: MAX6956.h:552
-
void initialize()
Definition: MAX6956.cpp:54
-
void setConfigReg(uint8_t config)
Definition: MAX6956.cpp:102
-
bool getPower()
Definition: MAX6956.cpp:110
-
void configAllPorts(uint8_t portConfig)
Definition: MAX6956.cpp:332
- -
void setEnableTransitionDetection(bool transition)
Definition: MAX6956.cpp:162
-
#define MAX6956_RA_CURRENT_0xP31P30
Definition: MAX6956.h:254
-
void setEnableIndividualCurrent(bool global)
Definition: MAX6956.cpp:144
-
void setPortCurrent(uint8_t port, uint8_t power)
0-15 brightness levels.
Definition: MAX6956.cpp:404
-
#define MAX6956_GLOBAL_CURRENT_LENGTH
nybble long
Definition: MAX6956.h:348
-
uint8_t portCurrentBit
Holder for the current bit offset.
Definition: MAX6956.h:559
-
#define MAX6956_RA_CURRENT_0xP13P12
Definition: MAX6956.h:245
-
void setPortLevel(uint8_t port, uint8_t power)
0 = off, 1-15 brightness levels.
Definition: MAX6956.cpp:346
-
MAX6956()
Definition: MAX6956.cpp:40
-
#define MAX6956_GLOBAL_CURRENT_BIT
Global current start bit.
Definition: MAX6956.h:347
-
#define MAX6956_CONFIG_TRANSITION_BIT
0 = Disabled, 1 = Enabled
Definition: MAX6956.h:345
-
#define MAX6956_RA_CONFIG_P11P10P9P8
Definition: MAX6956.h:204
-
#define MAX6956_RA_CONFIG_P7P6P5P4
Definition: MAX6956.h:203
-
uint8_t buffer[1]
Buffer for reading data from the device.
Definition: MAX6956.h:556
-
void setGlobalCurrent(uint8_t current)
Definition: MAX6956.cpp:179
-
void reset()
Definition: MAX6956.cpp:80
-
bool testConnection()
Definition: MAX6956.cpp:72
-
void setTestMode(bool test)
Definition: MAX6956.cpp:196
-
void togglePower()
Definition: MAX6956.cpp:124
-
uint8_t portConfig
Holder for port config bit pair.
Definition: MAX6956.h:557
-
#define MAX6956_RA_TRANSITION_DETECT
Definition: MAX6956.h:152
-
void setInputMask(uint8_t mask)
Definition: MAX6956.cpp:214
-
#define MAX6956_DEFAULT_ADDRESS
Definition: MAX6956.h:72
-
#define MAX6956_CONFIG_GLOBAL_CURRENT_BIT
0 = Global control, 1 = Individual control
Definition: MAX6956.h:344
-
uint8_t getConfigReg()
Definition: MAX6956.cpp:94
-
- - - - diff --git a/Arduino/MAX6956/html/MAX6956_8h.html b/Arduino/MAX6956/html/MAX6956_8h.html deleted file mode 100644 index 46464b88..00000000 --- a/Arduino/MAX6956/html/MAX6956_8h.html +++ /dev/null @@ -1,3196 +0,0 @@ - - - - - - -MAX6956: MAX6956.h File Reference - - - - - - - - - -
-
- - - - - - -
-
MAX6956 -  1.0 -
-
MAX6956i2Clibrary
-
-
- - - - - - - - - -
- -
- -
-
- -
-
MAX6956.h File Reference
-
-
-
#include "I2Cdev.h"
-
-

Go to the source code of this file.

- - - - -

-Data Structures

class  MAX6956
 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

-Macros

#define MAX6956_ADDRESS   0x40
 
#define MAX6956_DEFAULT_ADDRESS   0x40
 
#define MAX6956_RA_NO_OP   0x00
 No-op. More...
 
#define MAX6956_RA_GLOBAL_CURRENT   0x02
 
#define MAX6956_RA_CONFIGURATION   0x04
 
#define MAX6956_RA_TRANSITION_DETECT   0x06
 
#define MAX6956_RA_DISPLAY_TEST   0x07
 
#define MAX6956_RA_CONFIG_P7P6P5P4   0x09
 
#define MAX6956_RA_CONFIG_P11P10P9P8   0x0A
 
#define MAX6956_RA_CONFIG_P15P14P13P12   0x0B
 
#define MAX6956_RA_CONFIG_P19P18P17P16   0x0C
 
#define MAX6956_RA_CONFIG_P23P22P21P20   0x0D
 
#define MAX6956_RA_CONFIG_P27P26P25P24   0x0E
 
#define MAX6956_RA_CONFIG_P31P30P29P28   0x0F
 
#define MAX6956_RA_CURRENT_0xP5P4   0x12
 
#define MAX6956_RA_CURRENT_0xP7P6   0x13
 
#define MAX6956_RA_CURRENT_0xP9P8   0x14
 
#define MAX6956_RA_CURRENT_0xP11P10   0x15
 
#define MAX6956_RA_CURRENT_0xP13P12   0x16
 
#define MAX6956_RA_CURRENT_0xP15P14   0x17
 
#define MAX6956_RA_CURRENT_0xP17P16   0x18
 
#define MAX6956_RA_CURRENT_0xP19P18   0x19
 
#define MAX6956_RA_CURRENT_0xP21P20   0x1A
 
#define MAX6956_RA_CURRENT_0xP23P22   0x1B
 
#define MAX6956_RA_CURRENT_0xP25P24   0x1C
 
#define MAX6956_RA_CURRENT_0xP27P26   0x1D
 
#define MAX6956_RA_CURRENT_0xP29P28   0x1E
 
#define MAX6956_RA_CURRENT_0xP31P30   0x1F
 
#define MAX6956_RA_PORT0   0x20
 (virtual port, no action) More...
 
#define MAX6956_RA_PORT1   0x21
 (virtual port, no action) More...
 
#define MAX6956_RA_PORT2   0x22
 (virtual port, no action) More...
 
#define MAX6956_RA_PORT3   0x23
 (virtual port, no action) More...
 
#define MAX6956_RA_PORT4   0x24
 
#define MAX6956_RA_PORT5   0x25
 
#define MAX6956_RA_PORT6   0x26
 
#define MAX6956_RA_PORT7   0x27
 
#define MAX6956_RA_PORT8   0x28
 
#define MAX6956_RA_PORT9   0x29
 
#define MAX6956_RA_PORT10   0x2A
 
#define MAX6956_RA_PORT11   0x2B
 
#define MAX6956_RA_PORT12   0x2C
 
#define MAX6956_RA_PORT13   0x2D
 
#define MAX6956_RA_PORT14   0x2E
 
#define MAX6956_RA_PORT15   0x2F
 
#define MAX6956_RA_PORT16   0x30
 
#define MAX6956_RA_PORT17   0x31
 
#define MAX6956_RA_PORT18   0x32
 
#define MAX6956_RA_PORT19   0x33
 
#define MAX6956_RA_PORT20   0x34
 
#define MAX6956_RA_PORT21   0x35
 
#define MAX6956_RA_PORT22   0x36
 
#define MAX6956_RA_PORT23   0x37
 
#define MAX6956_RA_PORT24   0x38
 
#define MAX6956_RA_PORT25   0x39
 
#define MAX6956_RA_PORT26   0x3A
 
#define MAX6956_RA_PORT27   0x3B
 
#define MAX6956_RA_PORT28   0x3C
 
#define MAX6956_RA_PORT29   0x3D
 
#define MAX6956_RA_PORT30   0x3E
 
#define MAX6956_RA_PORT31   0x3F
 
#define MAX6956_RA_PORTS4_7   0x40
 data bits D0-D3; D4-D7 read as 0 More...
 
#define MAX6956_RA_PORTS4_8   0x41
 data bits D0-D4; D5-D7 read as 0 More...
 
#define MAX6956_RA_PORTS4_9   0x42
 data bits D0-D5; D6-D7 read as 0 More...
 
#define MAX6956_RA_PORTS4_10   0x43
 data bits D0-D6; D7 reads as 0 More...
 
#define MAX6956_RA_PORTS4_11   0x44
 
#define MAX6956_RA_PORTS5_12   0x45
 
#define MAX6956_RA_PORTS6_13   0x46
 
#define MAX6956_RA_PORTS7_14   0x47
 
#define MAX6956_RA_PORTS8_15   0x48
 
#define MAX6956_RA_PORTS9_16   0x49
 
#define MAX6956_RA_PORTS10_17   0x4A
 
#define MAX6956_RA_PORTS11_18   0x4B
 
#define MAX6956_RA_PORTS12_19   0x4C
 
#define MAX6956_RA_PORTS13_20   0x4D
 
#define MAX6956_RA_PORTS14_21   0x4E
 
#define MAX6956_RA_PORTS15_22   0x4F
 
#define MAX6956_RA_PORTS16_23   0x50
 
#define MAX6956_RA_PORTS17_24   0x51
 
#define MAX6956_RA_PORTS18_25   0x52
 
#define MAX6956_RA_PORTS19_26   0x53
 
#define MAX6956_RA_PORTS20_27   0x54
 
#define MAX6956_RA_PORTS21_28   0x55
 
#define MAX6956_RA_PORTS22_29   0x56
 
#define MAX6956_RA_PORTS23_30   0x57
 
#define MAX6956_RA_PORTS24_31   0x58
 
#define MAX6956_RA_PORTS25_31   0x59
 data bits D0-D6; D7 reads as 0 More...
 
#define MAX6956_RA_PORTS26_31   0x5A
 data bits D0-D5; D6-D7 read as 0 More...
 
#define MAX6956_RA_PORTS27_31   0x5B
 data bits D0-D4; D5-D7 read as 0 More...
 
#define MAX6956_RA_PORTS28_31   0x5C
 data bits D0-D3; D4-D7 read as 0 More...
 
#define MAX6956_RA_PORTS29_31   0x5D
 data bits D0-D2; D3-D7 read as 0 More...
 
#define MAX6956_RA_PORTS30_31   0x5E
 data bits D0-D1; D2-D7 read as 0 More...
 
#define MAX6956_RA_PORTS31_31   0x5F
 data bit D0; D1-D7 read as 0. Port 31 only. More...
 
#define MAX6956_CONFIG_POWER_BIT   0
 0 = Shutdown, 1 = Normal operation More...
 
#define MAX6956_CONFIG_GLOBAL_CURRENT_BIT   6
 0 = Global control, 1 = Individual control More...
 
#define MAX6956_CONFIG_TRANSITION_BIT   7
 0 = Disabled, 1 = Enabled More...
 
#define MAX6956_GLOBAL_CURRENT_BIT   0
 Global current start bit. More...
 
#define MAX6956_GLOBAL_CURRENT_LENGTH   4
 nybble long More...
 
#define MAX6956_PORT12_CURRENT_BIT   3
 LSNybble. More...
 
#define MAX6956_PORT12_CURRENT_LENGTH   4
 nybble long More...
 
#define MAX6956_PORT13_CURRENT_BIT   7
 MSNybble. More...
 
#define MAX6956_PORT13_CURRENT_LENGTH   4
 nybble long More...
 
#define MAX6956_PORT14_CURRENT_BIT   3
 LSNybble. More...
 
#define MAX6956_PORT14_CURRENT_LENGTH   4
 nybble long More...
 
#define MAX6956_PORT15_CURRENT_BIT   7
 MSNybble. More...
 
#define MAX6956_PORT15_CURRENT_LENGTH   4
 nybble long More...
 
#define MAX6956_PORT16_CURRENT_BIT   3
 LSNybble. More...
 
#define MAX6956_PORT16_CURRENT_LENGTH   4
 nybble long More...
 
#define MAX6956_PORT17_CURRENT_BIT   7
 MSNybble. More...
 
#define MAX6956_PORT17_CURRENT_LENGTH   4
 nybble long More...
 
#define MAX6956_PORT18_CURRENT_BIT   3
 LSNybble. More...
 
#define MAX6956_PORT18_CURRENT_LENGTH   4
 nybble long More...
 
#define MAX6956_PORT19_CURRENT_BIT   7
 MSNybble. More...
 
#define MAX6956_PORT19_CURRENT_LENGTH   4
 nybble long More...
 
#define MAX6956_PORT23_CURRENT_BIT   3
 LSNybble. More...
 
#define MAX6956_PORT23_CURRENT_LENGTH   4
 nybble long More...
 
#define MAX6956_PORT21_CURRENT_BIT   7
 MSNybble. More...
 
#define MAX6956_PORT21_CURRENT_LENGTH   4
 nybble long More...
 
#define MAX6956_PORT22_CURRENT_BIT   3
 LSNybble. More...
 
#define MAX6956_PORT22_CURRENT_LENGTH   4
 nybble long More...
 
#define MAX6956_PORT23_CURRENT_BIT   7
 LSNybble. More...
 
#define MAX6956_PORT23_CURRENT_LENGTH   4
 nybble long More...
 
#define MAX6956_PORT24_CURRENT_BIT   3
 LSNybble. More...
 
#define MAX6956_PORT24_CURRENT_LENGTH   4
 nybble long More...
 
#define MAX6956_PORT25_CURRENT_BIT   7
 MSNybble. More...
 
#define MAX6956_PORT25_CURRENT_LENGTH   4
 nybble long More...
 
#define MAX6956_PORT26_CURRENT_BIT   3
 LSNybble. More...
 
#define MAX6956_PORT26_CURRENT_LENGTH   4
 nybble long More...
 
#define MAX6956_PORT27_CURRENT_BIT   7
 MSNybble. More...
 
#define MAX6956_PORT27_CURRENT_LENGTH   4
 nybble long More...
 
#define MAX6956_PORT28_CURRENT_BIT   3
 LSNybble. More...
 
#define MAX6956_PORT28_CURRENT_LENGTH   4
 nybble long More...
 
#define MAX6956_PORT29_CURRENT_BIT   7
 MSNybble. More...
 
#define MAX6956_PORT29_CURRENT_LENGTH   4
 nybble long More...
 
#define MAX6956_PORT33_CURRENT_BIT   3
 LSNybble. More...
 
#define MAX6956_PORT33_CURRENT_LENGTH   4
 nybble long More...
 
#define MAX6956_PORT31_CURRENT_BIT   7
 MSNybble. More...
 
#define MAX6956_PORT31_CURRENT_LENGTH   4
 nybble long More...
 
#define MAX6956_DISPLAY_TEST_BIT   0
 0 = Normal operation, 1 = Display test More...
 
#define MAX6956_TRANSITION_STATUS_BIT   7
 INT Status, INT is automatically cleared after it is read. More...
 
#define MAX6956_TRANSITION_MASK_BIT   0
 Ports 24-30. More...
 
#define MAX6956_TRANSITION_MASK_LENGTH   7
 
#define MAX6956_TRANSITION_MASK_PORT30_BIT   6
 
#define MAX6956_TRANSITION_MASK_PORT29_BIT   5
 
#define MAX6956_TRANSITION_MASK_PORT28_BIT   4
 
#define MAX6956_TRANSITION_MASK_PORT27_BIT   3
 
#define MAX6956_TRANSITION_MASK_PORT26_BIT   2
 
#define MAX6956_TRANSITION_MASK_PORT25_BIT   1
 
#define MAX6956_TRANSITION_MASK_PORT24_BIT   0
 
#define MAX6956_OUTPUT_LED   0x00
 
#define MAX6956_OUTPUT_GPIO   0x01
 
#define MAX6956_INPUT_WO_PULL   0x02
 
#define MAX6956_INPUT_W_PULL   0x03
 
#define MAX6956_OFF   0x00
 
#define MAX6956_ON   0x01
 
#define MAX6956_CURRENT_0   0x00
 
#define MAX6956_CURRENT_1   0x01
 
#define MAX6956_CURRENT_2   0x02
 
#define MAX6956_CURRENT_3   0x03
 
#define MAX6956_CURRENT_4   0x04
 
#define MAX6956_CURRENT_5   0x05
 
#define MAX6956_CURRENT_6   0x06
 
#define MAX6956_CURRENT_7   0x07
 
#define MAX6956_CURRENT_8   0x08
 
#define MAX6956_CURRENT_9   0x09
 
#define MAX6956_CURRENT_10   0x0A
 
#define MAX6956_CURRENT_11   0x0B
 
#define MAX6956_CURRENT_12   0x0C
 
#define MAX6956_CURRENT_13   0x0D
 
#define MAX6956_CURRENT_14   0x0E
 
#define MAX6956_CURRENT_15   0x0F
 
-

Macro Definition Documentation

- -
-
- - - - -
#define MAX6956_ADDRESS   0x40
-
-

Table 3. I2C Address Map

-

Pin|Pin|DEVICE ADDRESS | :-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:–: AD1|AD0|A7 |A6 |A5 |A4 |A3 |A2 |A1 |A0 |HEX GND|GND|1 |0 |0 |0 |0 |0 |0 |RW |0x40 GND|V+ |1 |0 |0 |0 |0 |0 |1 |RW |0x41 GND|SDA|1 |0 |0 |0 |0 |1 |0 |RW |0x42 GND|SCL|1 |0 |0 |0 |0 |1 |1 |RW |0x43 V+ |GND|1 |0 |0 |0 |1 |0 |0 |RW |0x44 V+ |V+ |1 |0 |0 |0 |1 |0 |1 |RW |0x45 V+ |SDA|1 |0 |0 |0 |1 |1 |0 |RW |0x46 V+ |SCL|1 |0 |0 |0 |1 |1 |1 |RW |0x47 SDA|GND|1 |0 |0 |1 |0 |0 |0 |RW |0x48 SDA|V+ |1 |0 |0 |1 |0 |0 |1 |RW |0x49 SDA|SDA|1 |0 |0 |1 |0 |1 |0 |RW |0x50 SDA|SCL|1 |0 |0 |1 |0 |1 |1 |RW |0x51 SCL|GND|1 |0 |0 |1 |1 |0 |0 |RW |0x52 SCL|V+ |1 |0 |0 |1 |1 |0 |1 |RW |0x53 SCL|SDA|1 |0 |0 |1 |1 |1 |0 |RW |0x54 SCL|SCL|1 |0 |0 |1 |1 |1 |1 |RW |0x55

-

RW bit 0 = Write 1 = Read

- -

Definition at line 71 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_CONFIG_GLOBAL_CURRENT_BIT   6
-
- -

0 = Global control, 1 = Individual control

- -

Definition at line 344 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_CONFIG_POWER_BIT   0
-
- -

0 = Shutdown, 1 = Normal operation

- -

Definition at line 343 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_CONFIG_TRANSITION_BIT   7
-
- -

0 = Disabled, 1 = Enabled

- -

Definition at line 345 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_CURRENT_0   0x00
-
- -

Definition at line 414 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_CURRENT_1   0x01
-
- -

Definition at line 415 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_CURRENT_10   0x0A
-
- -

Definition at line 424 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_CURRENT_11   0x0B
-
- -

Definition at line 425 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_CURRENT_12   0x0C
-
- -

Definition at line 426 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_CURRENT_13   0x0D
-
- -

Definition at line 427 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_CURRENT_14   0x0E
-
- -

Definition at line 428 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_CURRENT_15   0x0F
-
- -

Definition at line 429 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_CURRENT_2   0x02
-
- -

Definition at line 416 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_CURRENT_3   0x03
-
- -

Definition at line 417 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_CURRENT_4   0x04
-
- -

Definition at line 418 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_CURRENT_5   0x05
-
- -

Definition at line 419 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_CURRENT_6   0x06
-
- -

Definition at line 420 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_CURRENT_7   0x07
-
- -

Definition at line 421 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_CURRENT_8   0x08
-
- -

Definition at line 422 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_CURRENT_9   0x09
-
- -

Definition at line 423 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_DEFAULT_ADDRESS   0x40
-
- -

Definition at line 72 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_DISPLAY_TEST_BIT   0
-
- -

0 = Normal operation, 1 = Display test

- -

Definition at line 391 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_GLOBAL_CURRENT_BIT   0
-
- -

Global current start bit.

- -

Definition at line 347 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_GLOBAL_CURRENT_LENGTH   4
-
- -

nybble long

- -

Definition at line 348 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_INPUT_W_PULL   0x03
-
- -

Definition at line 409 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_INPUT_WO_PULL   0x02
-
- -

Definition at line 408 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_OFF   0x00
-
- -

Definition at line 411 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_ON   0x01
-
- -

Definition at line 412 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_OUTPUT_GPIO   0x01
-
- -

Definition at line 407 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_OUTPUT_LED   0x00
-
- -

Definition at line 406 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_PORT12_CURRENT_BIT   3
-
- -

LSNybble.

- -

Definition at line 350 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_PORT12_CURRENT_LENGTH   4
-
- -

nybble long

- -

Definition at line 351 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_PORT13_CURRENT_BIT   7
-
- -

MSNybble.

- -

Definition at line 352 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_PORT13_CURRENT_LENGTH   4
-
- -

nybble long

- -

Definition at line 353 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_PORT14_CURRENT_BIT   3
-
- -

LSNybble.

- -

Definition at line 354 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_PORT14_CURRENT_LENGTH   4
-
- -

nybble long

- -

Definition at line 355 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_PORT15_CURRENT_BIT   7
-
- -

MSNybble.

- -

Definition at line 356 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_PORT15_CURRENT_LENGTH   4
-
- -

nybble long

- -

Definition at line 357 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_PORT16_CURRENT_BIT   3
-
- -

LSNybble.

- -

Definition at line 358 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_PORT16_CURRENT_LENGTH   4
-
- -

nybble long

- -

Definition at line 359 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_PORT17_CURRENT_BIT   7
-
- -

MSNybble.

- -

Definition at line 360 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_PORT17_CURRENT_LENGTH   4
-
- -

nybble long

- -

Definition at line 361 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_PORT18_CURRENT_BIT   3
-
- -

LSNybble.

- -

Definition at line 362 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_PORT18_CURRENT_LENGTH   4
-
- -

nybble long

- -

Definition at line 363 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_PORT19_CURRENT_BIT   7
-
- -

MSNybble.

- -

Definition at line 364 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_PORT19_CURRENT_LENGTH   4
-
- -

nybble long

- -

Definition at line 365 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_PORT21_CURRENT_BIT   7
-
- -

MSNybble.

- -

Definition at line 368 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_PORT21_CURRENT_LENGTH   4
-
- -

nybble long

- -

Definition at line 369 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_PORT22_CURRENT_BIT   3
-
- -

LSNybble.

- -

Definition at line 370 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_PORT22_CURRENT_LENGTH   4
-
- -

nybble long

- -

Definition at line 371 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_PORT23_CURRENT_BIT   3
-
- -

LSNybble.

-

MSNybble.

- -

Definition at line 372 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_PORT23_CURRENT_BIT   7
-
- -

LSNybble.

-

MSNybble.

- -

Definition at line 372 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_PORT23_CURRENT_LENGTH   4
-
- -

nybble long

- -

Definition at line 373 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_PORT23_CURRENT_LENGTH   4
-
- -

nybble long

- -

Definition at line 373 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_PORT24_CURRENT_BIT   3
-
- -

LSNybble.

- -

Definition at line 374 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_PORT24_CURRENT_LENGTH   4
-
- -

nybble long

- -

Definition at line 375 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_PORT25_CURRENT_BIT   7
-
- -

MSNybble.

- -

Definition at line 376 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_PORT25_CURRENT_LENGTH   4
-
- -

nybble long

- -

Definition at line 377 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_PORT26_CURRENT_BIT   3
-
- -

LSNybble.

- -

Definition at line 378 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_PORT26_CURRENT_LENGTH   4
-
- -

nybble long

- -

Definition at line 379 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_PORT27_CURRENT_BIT   7
-
- -

MSNybble.

- -

Definition at line 380 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_PORT27_CURRENT_LENGTH   4
-
- -

nybble long

- -

Definition at line 381 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_PORT28_CURRENT_BIT   3
-
- -

LSNybble.

- -

Definition at line 382 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_PORT28_CURRENT_LENGTH   4
-
- -

nybble long

- -

Definition at line 383 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_PORT29_CURRENT_BIT   7
-
- -

MSNybble.

- -

Definition at line 384 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_PORT29_CURRENT_LENGTH   4
-
- -

nybble long

- -

Definition at line 385 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_PORT31_CURRENT_BIT   7
-
- -

MSNybble.

- -

Definition at line 388 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_PORT31_CURRENT_LENGTH   4
-
- -

nybble long

- -

Definition at line 389 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_PORT33_CURRENT_BIT   3
-
- -

LSNybble.

- -

Definition at line 386 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_PORT33_CURRENT_LENGTH   4
-
- -

nybble long

- -

Definition at line 387 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_CONFIG_P11P10P9P8   0x0A
-
- -

Definition at line 204 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_CONFIG_P15P14P13P12   0x0B
-
- -

Definition at line 205 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_CONFIG_P19P18P17P16   0x0C
-
- -

Definition at line 206 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_CONFIG_P23P22P21P20   0x0D
-
- -

Definition at line 207 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_CONFIG_P27P26P25P24   0x0E
-
- -

Definition at line 208 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_CONFIG_P31P30P29P28   0x0F
-
- -

Definition at line 209 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_CONFIG_P7P6P5P4   0x09
-
-

Table 1. Port Configuration Map

- - - - - - - - - - - - - - - - - -
REGISTER ADDRESSD7 D6D5 D4D3 D2D1 D0
Port Configuration for P7, P6, P5, P4 0x09 P7 P6 P5 P4
Port Configuration for P11, P10, P9, P8 0x0A P11 P10 P9 P8
Port Configuration for P15, P14, P13, P120x0B P15 P14 P13 P12
Port Configuration for P19, P18, P17, P160x0C P19 P18 P17 P16
Port Configuration for P23, P22, P21, P200x0D P23 P22 P21 P20
Port Configuration for P27, P26, P25, P240x0E P27 P26 P25 P24
Port Configuration for P31, P30, P29, P280x0F P31 P30 P29 P28
-

Table 2. P4-P31 configuration bit pairs

-
-    00 - Output, LED Segment Driver
-             Controlled  using port registers 0x20-0x5F. 
-             0 = High impedance
-             1 = Open-drain current sink, with sink current (up to 24mA) 
-                 determined by the appropriate current register
-    01 - Output, GPIO Output
-             Controlled  using port registers 0x20-0x5F. 
-             0 = Active-low logic output
-             1 = Active-high logic output
-    10 - Input, GPIO Input Without Pullup
-             Read port registers 0x20-0x5F.
-             Schmitt logic input 
-    11 - Input, GPIO Input with Pullup
-             Read port registers 0x20-0x5F.
-             Schmitt logic input with pullup
-
-

Definition at line 203 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_CONFIGURATION   0x04
-
-

Table 7. Configuration Register Format

- - - - - -
ADDRESS D7 D6 D5 D4 D3 D2 D1 D0
0x04 M I x x x x x S
-

Table 8. Shutdown Control (S Data Bit D0) Format

- - - - - - - -
FUNCTION ADDRESSD7 D6 D5 D4 D3 D2 D1 D0
Shutdown 0x04 M I x x x x x 0
Normal Operation0x04 M I x x x x x 1
-

Table 9. Global Current Control (I Data Bit D6) Format

- - - - - - - -
FUNCTION ADDRESSD7 D6 D5 D4 D3 D2 D1 D0
Global 0x04 M 0 x x x x x S
Individual Segment0x04 M 1 x x x x x S
-

Table 10. Transition Detection Control (M-Data Bit D7) Format

- - - - - - - -
FUNCTION ADDRESSD7 D6 D5 D4 D3 D2 D1 D0
Disabled 0x04 0 I x x x x x S
Enabled 0x04 1 I x x x x x S
- -

Definition at line 137 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_CURRENT_0xP11P10   0x15
-
- -

Definition at line 244 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_CURRENT_0xP13P12   0x16
-
- -

Definition at line 245 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_CURRENT_0xP15P14   0x17
-
- -

Definition at line 246 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_CURRENT_0xP17P16   0x18
-
- -

Definition at line 247 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_CURRENT_0xP19P18   0x19
-
- -

Definition at line 248 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_CURRENT_0xP21P20   0x1A
-
- -

Definition at line 249 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_CURRENT_0xP23P22   0x1B
-
- -

Definition at line 250 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_CURRENT_0xP25P24   0x1C
-
- -

Definition at line 251 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_CURRENT_0xP27P26   0x1D
-
- -

Definition at line 252 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_CURRENT_0xP29P28   0x1E
-
- -

Definition at line 253 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_CURRENT_0xP31P30   0x1F
-
- -

Definition at line 254 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_CURRENT_0xP5P4   0x12
-
-

Constant-current limit for each digit is individually controlled by the settings in the Current054 through Current1FE registers

-

Table 12. Individual Port Current Registers

-
                | ADDRESS |            |
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FUNCTION CODE(HEX)D7 D6 D5 D4 D3 D2 D1 D0
Current054 register 0x12 Segment 5 Segment 4
Current076 register 0x13 Segment 7 Segment 6
Current098 register 0x14 Segment 9 Segment 8
Current0BA register 0x15 Segment 11 Segment 10
Current0DC register 0x16 Segment 13 Segment 12
Current0FE register 0x17 Segment 15 Segment 14
Current110 register 0x18 Segment 17 Segment 16
Current132 register 0x19 Segment 19 Segment 18
Current154 register 0x1A Segment 21 Segment 20
Current176 register 0x1B Segment 23 Segment 22
Current198 register 0x1C Segment 25 Segment 24
Current1BA register 0x1D Segment 27 Segment 26
Current1DC register 0x1E Segment 29 Segment 28
Current1FE register 0x1F Segment 31 Segment 30
-

Register data is 0-Fx0-F for 1-16(0-F) brightness levels. To completely blank an output turn it off (0) using port configuration registers.

- -

Definition at line 241 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_CURRENT_0xP7P6   0x13
-
- -

Definition at line 242 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_CURRENT_0xP9P8   0x14
-
- -

Definition at line 243 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_DISPLAY_TEST   0x07
-
-

Table 16. Display Test Register

-
             |ADDR |
-
- - - - - - -
MODE CODE D7 D6 D5 D4 D3 D2 D1 D0
Normal Operation 0x07 x x x x x x x 0
Display Test Mode0x07 x x x x x x x 1
- -

Definition at line 165 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_GLOBAL_CURRENT   0x02
-
-

Table 11. Global Segment Current Register Format

-

LED DRIVE |TYPICAL SEGMENT | ADDRESS |

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FRACTION CURRENT(mA) CODE (HEX) D7 D6 D5 D4 D3 D2 D1 D0 HEX CODE
1/16 1.5 0x02 x x x x 0 0 0 0 0xX0
2/16 3 0x02 x x x x 0 0 0 1 0xX1
3/16 4.5 0x02 x x x x 0 0 1 0 0xX2
4/16 6 0x02 x x x x 0 0 1 1 0xX3
5/16 7.5 0x02 x x x x 0 1 0 0 0xX4
6/16 9 0x02 x x x x 0 1 0 1 0xX5
7/16 10.5 0x02 x x x x 0 1 1 0 0xX6
8/16 12 0x02 x x x x 0 1 1 1 0xX7
9/16 13.5 0x02 x x x x 1 0 0 0 0xX8
10/16 15 0x02 x x x x 1 0 0 1 0xX9
11/16 16.5 0x02 x x x x 1 0 1 0 0xXA
12/16 18 0x02 x x x x 1 0 1 1 0xXB
13/16 19.5 0x02 x x x x 1 1 0 0 0xXC
14/16 21 0x02 x x x x 1 1 0 1 0xXD
15/16 22.5 0x02 x x x x 1 1 1 0 0xXE
16/16 24 0x02 x x x x 1 1 1 1 0xXF
- -

Definition at line 102 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_NO_OP   0x00
-
- -

No-op.

- -

Definition at line 76 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORT0   0x20
-
- -

(virtual port, no action)

-

Individiual Port Registers

-
data bit D0; D7-D1 read as 0
-

Definition at line 262 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORT1   0x21
-
- -

(virtual port, no action)

- -

Definition at line 263 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORT10   0x2A
-
- -

Definition at line 273 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORT11   0x2B
-
- -

Definition at line 274 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORT12   0x2C
-
- -

Definition at line 276 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORT13   0x2D
-
- -

Definition at line 277 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORT14   0x2E
-
- -

Definition at line 278 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORT15   0x2F
-
- -

Definition at line 279 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORT16   0x30
-
- -

Definition at line 280 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORT17   0x31
-
- -

Definition at line 281 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORT18   0x32
-
- -

Definition at line 282 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORT19   0x33
-
- -

Definition at line 283 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORT2   0x22
-
- -

(virtual port, no action)

- -

Definition at line 264 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORT20   0x34
-
- -

Definition at line 285 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORT21   0x35
-
- -

Definition at line 286 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORT22   0x36
-
- -

Definition at line 287 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORT23   0x37
-
- -

Definition at line 288 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORT24   0x38
-
- -

Definition at line 289 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORT25   0x39
-
- -

Definition at line 290 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORT26   0x3A
-
- -

Definition at line 291 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORT27   0x3B
-
- -

Definition at line 292 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORT28   0x3C
-
- -

Definition at line 294 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORT29   0x3D
-
- -

Definition at line 295 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORT3   0x23
-
- -

(virtual port, no action)

- -

Definition at line 265 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORT30   0x3E
-
- -

Definition at line 296 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORT31   0x3F
-
- -

Definition at line 297 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORT4   0x24
-
- -

Definition at line 267 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORT5   0x25
-
- -

Definition at line 268 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORT6   0x26
-
- -

Definition at line 269 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORT7   0x27
-
- -

Definition at line 270 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORT8   0x28
-
- -

Definition at line 271 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORT9   0x29
-
- -

Definition at line 272 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORTS10_17   0x4A
-
- -

Definition at line 315 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORTS11_18   0x4B
-
- -

Definition at line 316 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORTS12_19   0x4C
-
- -

Definition at line 317 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORTS13_20   0x4D
-
- -

Definition at line 318 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORTS14_21   0x4E
-
- -

Definition at line 319 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORTS15_22   0x4F
-
- -

Definition at line 320 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORTS16_23   0x50
-
- -

Definition at line 321 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORTS17_24   0x51
-
- -

Definition at line 322 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORTS18_25   0x52
-
- -

Definition at line 323 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORTS19_26   0x53
-
- -

Definition at line 324 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORTS20_27   0x54
-
- -

Definition at line 325 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORTS21_28   0x55
-
- -

Definition at line 326 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORTS22_29   0x56
-
- -

Definition at line 327 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORTS23_30   0x57
-
- -

Definition at line 328 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORTS24_31   0x58
-
- -

Definition at line 329 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORTS25_31   0x59
-
- -

data bits D0-D6; D7 reads as 0

- -

Definition at line 333 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORTS26_31   0x5A
-
- -

data bits D0-D5; D6-D7 read as 0

- -

Definition at line 334 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORTS27_31   0x5B
-
- -

data bits D0-D4; D5-D7 read as 0

- -

Definition at line 335 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORTS28_31   0x5C
-
- -

data bits D0-D3; D4-D7 read as 0

- -

Definition at line 336 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORTS29_31   0x5D
-
- -

data bits D0-D2; D3-D7 read as 0

- -

Definition at line 337 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORTS30_31   0x5E
-
- -

data bits D0-D1; D2-D7 read as 0

- -

Definition at line 338 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORTS31_31   0x5F
-
- -

data bit D0; D1-D7 read as 0. Port 31 only.

- -

Definition at line 339 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORTS4_10   0x43
-
- -

data bits D0-D6; D7 reads as 0

- -

Definition at line 304 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORTS4_11   0x44
-
- -

Definition at line 309 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORTS4_7   0x40
-
- -

data bits D0-D3; D4-D7 read as 0

- -

Definition at line 301 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORTS4_8   0x41
-
- -

data bits D0-D4; D5-D7 read as 0

- -

Definition at line 302 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORTS4_9   0x42
-
- -

data bits D0-D5; D6-D7 read as 0

- -

Definition at line 303 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORTS5_12   0x45
-
- -

Definition at line 310 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORTS6_13   0x46
-
- -

Definition at line 311 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORTS7_14   0x47
-
- -

Definition at line 312 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORTS8_15   0x48
-
- -

Definition at line 313 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_PORTS9_16   0x49
-
- -

Definition at line 314 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_RA_TRANSITION_DETECT   0x06
-
-

Table 15. Transition Detection Mask Register

- - - - - - - - - -
FUNCTION REGISTER ADDRESS READ/WRITE D7 D6 D5 D4 D3 D2 D1 D0
Mask Register 0x06 Read INT Status*PortPortPortPortPortPortPort
30 29 28 27 26 25 24
Write Unchanged maskmaskmaskmaskmaskmaskmask
-

INT is automatically cleared after it is read.

- -

Definition at line 152 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_TRANSITION_MASK_BIT   0
-
- -

Ports 24-30.

- -

Definition at line 394 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_TRANSITION_MASK_LENGTH   7
-
- -

Definition at line 395 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_TRANSITION_MASK_PORT24_BIT   0
-
- -

Definition at line 402 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_TRANSITION_MASK_PORT25_BIT   1
-
- -

Definition at line 401 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_TRANSITION_MASK_PORT26_BIT   2
-
- -

Definition at line 400 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_TRANSITION_MASK_PORT27_BIT   3
-
- -

Definition at line 399 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_TRANSITION_MASK_PORT28_BIT   4
-
- -

Definition at line 398 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_TRANSITION_MASK_PORT29_BIT   5
-
- -

Definition at line 397 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_TRANSITION_MASK_PORT30_BIT   6
-
- -

Definition at line 396 of file MAX6956.h.

- -
-
- -
-
- - - - -
#define MAX6956_TRANSITION_STATUS_BIT   7
-
- -

INT Status, INT is automatically cleared after it is read.

- -

Definition at line 393 of file MAX6956.h.

- -
-
-
- - - - diff --git a/Arduino/MAX6956/html/MAX6956_8h_source.html b/Arduino/MAX6956/html/MAX6956_8h_source.html deleted file mode 100644 index e9f7f927..00000000 --- a/Arduino/MAX6956/html/MAX6956_8h_source.html +++ /dev/null @@ -1,446 +0,0 @@ - - - - - - -MAX6956: MAX6956.h Source File - - - - - - - - - -
-
- - - - - - -
-
MAX6956 -  1.0 -
-
MAX6956i2Clibrary
-
-
- - - - - -
- - - - -
- -
- -
-
-
MAX6956.h
-
-
-Go to the documentation of this file.
1 // I2Cdev library collection - MAX6956 I2C device class header file
-
2 // Based on Maxim MAX6956 datasheet 19-2414; Rev 4; 6/10
-
3 //
-
4 // 2013-12-15 by Tom Beighley <tomthegeek@gmail.com>
-
5 // I2C Device Library hosted at http://www.i2cdevlib.com
-
6 //
-
7 // Changelog:
-
8 // 2013-12-15 - initial release
-
9 //
-
10 
-
11 /* ============================================
-
12 I2Cdev device library code is placed under the MIT license
-
13 Copyright (c) 2013 Tom Beighley
-
14 
-
15 Permission is hereby granted, free of charge, to any person obtaining a copy
-
16 of this software and associated documentation files (the "Software"), to deal
-
17 in the Software without restriction, including without limitation the rights
-
18 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-
19 copies of the Software, and to permit persons to whom the Software is
-
20 furnished to do so, subject to the following conditions:
-
21 
-
22 The above copyright notice and this permission notice shall be included in
-
23 all copies or substantial portions of the Software.
-
24 
-
25 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-
26 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-
27 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-
28 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-
29 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-
30 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-
31 THE SOFTWARE.
-
32 ===============================================
-
33 */
-
34 
-
35 #ifndef _MAX6956_H_
-
36 #define _MAX6956_H_
-
37 
-
38 #include "I2Cdev.h"
-
39 
-
40 // -----------------------------------------------------------------------------
-
41 // Arduino-style "Serial.print" debug constant (uncomment to enable)
-
42 // -----------------------------------------------------------------------------
-
43 // #define MAX6956_SERIAL_DEBUG
-
44 
-
71 #define MAX6956_ADDRESS 0x40 // See table 3
-
72 #define MAX6956_DEFAULT_ADDRESS 0x40 // AD0 and AD1 at ground.
-
73 
-
74 //==========Registers==========
-
75 
-
76 #define MAX6956_RA_NO_OP 0x00
-
77 
-
78 
-
102 #define MAX6956_RA_GLOBAL_CURRENT 0x02
-
103 
-
137 #define MAX6956_RA_CONFIGURATION 0x04
-
138 
-
152 #define MAX6956_RA_TRANSITION_DETECT 0x06
-
153 
-
165 #define MAX6956_RA_DISPLAY_TEST 0x07
-
166 
-
203 #define MAX6956_RA_CONFIG_P7P6P5P4 0x09
-
204 #define MAX6956_RA_CONFIG_P11P10P9P8 0x0A
-
205 #define MAX6956_RA_CONFIG_P15P14P13P12 0x0B
-
206 #define MAX6956_RA_CONFIG_P19P18P17P16 0x0C
-
207 #define MAX6956_RA_CONFIG_P23P22P21P20 0x0D
-
208 #define MAX6956_RA_CONFIG_P27P26P25P24 0x0E
-
209 #define MAX6956_RA_CONFIG_P31P30P29P28 0x0F
-
210 
-
241 #define MAX6956_RA_CURRENT_0xP5P4 0x12
-
242 #define MAX6956_RA_CURRENT_0xP7P6 0x13
-
243 #define MAX6956_RA_CURRENT_0xP9P8 0x14
-
244 #define MAX6956_RA_CURRENT_0xP11P10 0x15
-
245 #define MAX6956_RA_CURRENT_0xP13P12 0x16
-
246 #define MAX6956_RA_CURRENT_0xP15P14 0x17
-
247 #define MAX6956_RA_CURRENT_0xP17P16 0x18
-
248 #define MAX6956_RA_CURRENT_0xP19P18 0x19
-
249 #define MAX6956_RA_CURRENT_0xP21P20 0x1A
-
250 #define MAX6956_RA_CURRENT_0xP23P22 0x1B
-
251 #define MAX6956_RA_CURRENT_0xP25P24 0x1C
-
252 #define MAX6956_RA_CURRENT_0xP27P26 0x1D
-
253 #define MAX6956_RA_CURRENT_0xP29P28 0x1E
-
254 #define MAX6956_RA_CURRENT_0xP31P30 0x1F
-
255 
-
262 #define MAX6956_RA_PORT0 0x20
-
263 #define MAX6956_RA_PORT1 0x21
-
264 #define MAX6956_RA_PORT2 0x22
-
265 #define MAX6956_RA_PORT3 0x23
-
266 
-
267 #define MAX6956_RA_PORT4 0x24
-
268 #define MAX6956_RA_PORT5 0x25
-
269 #define MAX6956_RA_PORT6 0x26
-
270 #define MAX6956_RA_PORT7 0x27
-
271 #define MAX6956_RA_PORT8 0x28
-
272 #define MAX6956_RA_PORT9 0x29
-
273 #define MAX6956_RA_PORT10 0x2A
-
274 #define MAX6956_RA_PORT11 0x2B
-
275 
-
276 #define MAX6956_RA_PORT12 0x2C
-
277 #define MAX6956_RA_PORT13 0x2D
-
278 #define MAX6956_RA_PORT14 0x2E
-
279 #define MAX6956_RA_PORT15 0x2F
-
280 #define MAX6956_RA_PORT16 0x30
-
281 #define MAX6956_RA_PORT17 0x31
-
282 #define MAX6956_RA_PORT18 0x32
-
283 #define MAX6956_RA_PORT19 0x33
-
284 
-
285 #define MAX6956_RA_PORT20 0x34
-
286 #define MAX6956_RA_PORT21 0x35
-
287 #define MAX6956_RA_PORT22 0x36
-
288 #define MAX6956_RA_PORT23 0x37
-
289 #define MAX6956_RA_PORT24 0x38
-
290 #define MAX6956_RA_PORT25 0x39
-
291 #define MAX6956_RA_PORT26 0x3A
-
292 #define MAX6956_RA_PORT27 0x3B
-
293 
-
294 #define MAX6956_RA_PORT28 0x3C
-
295 #define MAX6956_RA_PORT29 0x3D
-
296 #define MAX6956_RA_PORT30 0x3E
-
297 #define MAX6956_RA_PORT31 0x3F
-
298 /*
-
299  Lower port groups
-
300 */
-
301 #define MAX6956_RA_PORTS4_7 0x40
-
302 #define MAX6956_RA_PORTS4_8 0x41
-
303 #define MAX6956_RA_PORTS4_9 0x42
-
304 #define MAX6956_RA_PORTS4_10 0x43
-
305 
-
306 /*
-
307  8 port registers. Data bits D0-D7
-
308 */
-
309 #define MAX6956_RA_PORTS4_11 0x44
-
310 #define MAX6956_RA_PORTS5_12 0x45
-
311 #define MAX6956_RA_PORTS6_13 0x46
-
312 #define MAX6956_RA_PORTS7_14 0x47
-
313 #define MAX6956_RA_PORTS8_15 0x48
-
314 #define MAX6956_RA_PORTS9_16 0x49
-
315 #define MAX6956_RA_PORTS10_17 0x4A
-
316 #define MAX6956_RA_PORTS11_18 0x4B
-
317 #define MAX6956_RA_PORTS12_19 0x4C
-
318 #define MAX6956_RA_PORTS13_20 0x4D
-
319 #define MAX6956_RA_PORTS14_21 0x4E
-
320 #define MAX6956_RA_PORTS15_22 0x4F
-
321 #define MAX6956_RA_PORTS16_23 0x50
-
322 #define MAX6956_RA_PORTS17_24 0x51
-
323 #define MAX6956_RA_PORTS18_25 0x52
-
324 #define MAX6956_RA_PORTS19_26 0x53
-
325 #define MAX6956_RA_PORTS20_27 0x54
-
326 #define MAX6956_RA_PORTS21_28 0x55
-
327 #define MAX6956_RA_PORTS22_29 0x56
-
328 #define MAX6956_RA_PORTS23_30 0x57
-
329 #define MAX6956_RA_PORTS24_31 0x58
-
330 /*
-
331  Upper port groups
-
332 */
-
333 #define MAX6956_RA_PORTS25_31 0x59
-
334 #define MAX6956_RA_PORTS26_31 0x5A
-
335 #define MAX6956_RA_PORTS27_31 0x5B
-
336 #define MAX6956_RA_PORTS28_31 0x5C
-
337 #define MAX6956_RA_PORTS29_31 0x5D
-
338 #define MAX6956_RA_PORTS30_31 0x5E
-
339 #define MAX6956_RA_PORTS31_31 0x5F
-
340 
-
341 //=========Config bits=========
-
342 
-
343 #define MAX6956_CONFIG_POWER_BIT 0
-
344 #define MAX6956_CONFIG_GLOBAL_CURRENT_BIT 6
-
345 #define MAX6956_CONFIG_TRANSITION_BIT 7
-
346 
-
347 #define MAX6956_GLOBAL_CURRENT_BIT 0
-
348 #define MAX6956_GLOBAL_CURRENT_LENGTH 4
-
349 
-
350 #define MAX6956_PORT12_CURRENT_BIT 3
-
351 #define MAX6956_PORT12_CURRENT_LENGTH 4
-
352 #define MAX6956_PORT13_CURRENT_BIT 7
-
353 #define MAX6956_PORT13_CURRENT_LENGTH 4
-
354 #define MAX6956_PORT14_CURRENT_BIT 3
-
355 #define MAX6956_PORT14_CURRENT_LENGTH 4
-
356 #define MAX6956_PORT15_CURRENT_BIT 7
-
357 #define MAX6956_PORT15_CURRENT_LENGTH 4
-
358 #define MAX6956_PORT16_CURRENT_BIT 3
-
359 #define MAX6956_PORT16_CURRENT_LENGTH 4
-
360 #define MAX6956_PORT17_CURRENT_BIT 7
-
361 #define MAX6956_PORT17_CURRENT_LENGTH 4
-
362 #define MAX6956_PORT18_CURRENT_BIT 3
-
363 #define MAX6956_PORT18_CURRENT_LENGTH 4
-
364 #define MAX6956_PORT19_CURRENT_BIT 7
-
365 #define MAX6956_PORT19_CURRENT_LENGTH 4
-
366 #define MAX6956_PORT23_CURRENT_BIT 3
-
367 #define MAX6956_PORT23_CURRENT_LENGTH 4
-
368 #define MAX6956_PORT21_CURRENT_BIT 7
-
369 #define MAX6956_PORT21_CURRENT_LENGTH 4
-
370 #define MAX6956_PORT22_CURRENT_BIT 3
-
371 #define MAX6956_PORT22_CURRENT_LENGTH 4
-
372 #define MAX6956_PORT23_CURRENT_BIT 7
-
373 #define MAX6956_PORT23_CURRENT_LENGTH 4
-
374 #define MAX6956_PORT24_CURRENT_BIT 3
-
375 #define MAX6956_PORT24_CURRENT_LENGTH 4
-
376 #define MAX6956_PORT25_CURRENT_BIT 7
-
377 #define MAX6956_PORT25_CURRENT_LENGTH 4
-
378 #define MAX6956_PORT26_CURRENT_BIT 3
-
379 #define MAX6956_PORT26_CURRENT_LENGTH 4
-
380 #define MAX6956_PORT27_CURRENT_BIT 7
-
381 #define MAX6956_PORT27_CURRENT_LENGTH 4
-
382 #define MAX6956_PORT28_CURRENT_BIT 3
-
383 #define MAX6956_PORT28_CURRENT_LENGTH 4
-
384 #define MAX6956_PORT29_CURRENT_BIT 7
-
385 #define MAX6956_PORT29_CURRENT_LENGTH 4
-
386 #define MAX6956_PORT33_CURRENT_BIT 3
-
387 #define MAX6956_PORT33_CURRENT_LENGTH 4
-
388 #define MAX6956_PORT31_CURRENT_BIT 7
-
389 #define MAX6956_PORT31_CURRENT_LENGTH 4
-
390 
-
391 #define MAX6956_DISPLAY_TEST_BIT 0
-
392 
-
393 #define MAX6956_TRANSITION_STATUS_BIT 7
-
394 #define MAX6956_TRANSITION_MASK_BIT 0
-
395 #define MAX6956_TRANSITION_MASK_LENGTH 7
-
396 #define MAX6956_TRANSITION_MASK_PORT30_BIT 6
-
397 #define MAX6956_TRANSITION_MASK_PORT29_BIT 5
-
398 #define MAX6956_TRANSITION_MASK_PORT28_BIT 4
-
399 #define MAX6956_TRANSITION_MASK_PORT27_BIT 3
-
400 #define MAX6956_TRANSITION_MASK_PORT26_BIT 2
-
401 #define MAX6956_TRANSITION_MASK_PORT25_BIT 1
-
402 #define MAX6956_TRANSITION_MASK_PORT24_BIT 0
-
403 
-
404 //=========Values=========
-
405 
-
406 #define MAX6956_OUTPUT_LED 0x00
-
407 #define MAX6956_OUTPUT_GPIO 0x01
-
408 #define MAX6956_INPUT_WO_PULL 0x02
-
409 #define MAX6956_INPUT_W_PULL 0x03
-
410 
-
411 #define MAX6956_OFF 0x00
-
412 #define MAX6956_ON 0x01
-
413 
-
414 #define MAX6956_CURRENT_0 0x00
-
415 #define MAX6956_CURRENT_1 0x01
-
416 #define MAX6956_CURRENT_2 0x02
-
417 #define MAX6956_CURRENT_3 0x03
-
418 #define MAX6956_CURRENT_4 0x04
-
419 #define MAX6956_CURRENT_5 0x05
-
420 #define MAX6956_CURRENT_6 0x06
-
421 #define MAX6956_CURRENT_7 0x07
-
422 #define MAX6956_CURRENT_8 0x08
-
423 #define MAX6956_CURRENT_9 0x09
-
424 #define MAX6956_CURRENT_10 0x0A
-
425 #define MAX6956_CURRENT_11 0x0B
-
426 #define MAX6956_CURRENT_12 0x0C
-
427 #define MAX6956_CURRENT_13 0x0D
-
428 #define MAX6956_CURRENT_14 0x0E
-
429 #define MAX6956_CURRENT_15 0x0F
-
430 
-
456 class MAX6956 {
-
457  public:
-
458  MAX6956();
-
459  MAX6956(uint8_t address);
-
460 
-
461  void initialize();
-
462  bool testConnection();
-
463 
-
464  void reset();
-
465 
-
466  // Config register
-
467  uint8_t getConfigReg();
-
468  void setConfigReg(uint8_t config);
-
469 
-
470  bool getPower();
-
471  void togglePower();
-
472  void setPower(bool power);
-
473 
- -
475  void setEnableIndividualCurrent(bool global);
-
476 
- -
478  void setEnableTransitionDetection(bool transition);
-
479 
-
480  // Global current
-
481  uint8_t getGlobalCurrent();
-
482  void setGlobalCurrent(uint8_t current);
-
483 
-
484  // Test mode
-
485  bool getTestMode();
-
486  void setTestMode(bool test);
-
487 
-
488  // Input mask
-
489  uint8_t getInputMask();
-
490  void setInputMask(uint8_t mask);
-
491 
-
492  // Port config
-
493  void configPort(uint8_t port, uint8_t portConfig);
-
494  void configPorts(uint8_t lower, uint8_t upper, uint8_t portConfig);
-
495  void configAllPorts(uint8_t portConfig);
-
496 
-
497  void setPortLevel(uint8_t port, uint8_t power);
-
498  void setPortCurrent(uint8_t port, uint8_t power);
-
499  void setAllPortsCurrent(uint8_t power);
-
500  void enableAllPorts();
-
501  void disableAllPorts();
-
502 
-
527  uint8_t portsConfig[5];
-
552  uint8_t portsStatus[3];
-
553 
-
554  private:
-
555  uint8_t devAddr;
-
556  uint8_t buffer[1];
-
557  uint8_t portConfig;
-
558  uint8_t portCurrentRA;
-
559  uint8_t portCurrentBit;
-
560  uint8_t psArrayIndex;
-
561  uint8_t psBitPosition;
-
562 };
-
563 
-
564 #endif /* _MAX6956_H_ */
-
uint8_t devAddr
Holds the current device address.
Definition: MAX6956.h:555
-
uint8_t portCurrentRA
Holder for port current register.
Definition: MAX6956.h:558
-
uint8_t psArrayIndex
array index
Definition: MAX6956.h:560
-
void enableAllPorts()
Definition: MAX6956.cpp:453
-
bool getEnableTransitionDetection()
Definition: MAX6956.cpp:152
-
uint8_t getInputMask()
Definition: MAX6956.cpp:205
-
void disableAllPorts()
Definition: MAX6956.cpp:463
-
bool getEnableIndividualCurrent()
Definition: MAX6956.cpp:134
-
void setPower(bool power)
Definition: MAX6956.cpp:118
-
void configPort(uint8_t port, uint8_t portConfig)
Definition: MAX6956.cpp:265
-
void setAllPortsCurrent(uint8_t power)
0-15, 0 = min brightness (not off) 15 = max
Definition: MAX6956.cpp:444
-
void configPorts(uint8_t lower, uint8_t upper, uint8_t portConfig)
Definition: MAX6956.cpp:285
-
uint8_t portsConfig[5]
Definition: MAX6956.h:527
-
uint8_t getGlobalCurrent()
Definition: MAX6956.cpp:171
-
bool getTestMode()
Definition: MAX6956.cpp:188
-
uint8_t psBitPosition
bit position
Definition: MAX6956.h:561
-
uint8_t portsStatus[3]
Definition: MAX6956.h:552
-
void initialize()
Definition: MAX6956.cpp:54
-
void setConfigReg(uint8_t config)
Definition: MAX6956.cpp:102
-
bool getPower()
Definition: MAX6956.cpp:110
-
void configAllPorts(uint8_t portConfig)
Definition: MAX6956.cpp:332
-
void setEnableTransitionDetection(bool transition)
Definition: MAX6956.cpp:162
-
void setEnableIndividualCurrent(bool global)
Definition: MAX6956.cpp:144
-
void setPortCurrent(uint8_t port, uint8_t power)
0-15 brightness levels.
Definition: MAX6956.cpp:404
-
uint8_t portCurrentBit
Holder for the current bit offset.
Definition: MAX6956.h:559
-
void setPortLevel(uint8_t port, uint8_t power)
0 = off, 1-15 brightness levels.
Definition: MAX6956.cpp:346
-
MAX6956()
Definition: MAX6956.cpp:40
-
uint8_t buffer[1]
Buffer for reading data from the device.
Definition: MAX6956.h:556
-
void setGlobalCurrent(uint8_t current)
Definition: MAX6956.cpp:179
-
void reset()
Definition: MAX6956.cpp:80
-
bool testConnection()
Definition: MAX6956.cpp:72
-
void setTestMode(bool test)
Definition: MAX6956.cpp:196
-
void togglePower()
Definition: MAX6956.cpp:124
-
uint8_t portConfig
Holder for port config bit pair.
Definition: MAX6956.h:557
- -
void setInputMask(uint8_t mask)
Definition: MAX6956.cpp:214
-
uint8_t getConfigReg()
Definition: MAX6956.cpp:94
-
- - - - diff --git a/Arduino/MAX6956/html/annotated.html b/Arduino/MAX6956/html/annotated.html deleted file mode 100644 index 6f25f18e..00000000 --- a/Arduino/MAX6956/html/annotated.html +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - -MAX6956: Data Structures - - - - - - - - - -
-
- - - - - - -
-
MAX6956 -  1.0 -
-
MAX6956i2Clibrary
-
-
- - - - - -
- - - - -
- -
- -
-
-
Data Structures
-
-
-
Here are the data structures with brief descriptions:
- - -
\CMAX6956
-
-
- - - - diff --git a/Arduino/MAX6956/html/bc_s.png b/Arduino/MAX6956/html/bc_s.png deleted file mode 100644 index 224b29aa9847d5a4b3902efd602b7ddf7d33e6c2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 676 zcmV;V0$crwP)y__>=_9%My z{n931IS})GlGUF8K#6VIbs%684A^L3@%PlP2>_sk`UWPq@f;rU*V%rPy_ekbhXT&s z(GN{DxFv}*vZp`F>S!r||M`I*nOwwKX+BC~3P5N3-)Y{65c;ywYiAh-1*hZcToLHK ztpl1xomJ+Yb}K(cfbJr2=GNOnT!UFA7Vy~fBz8?J>XHsbZoDad^8PxfSa0GDgENZS zuLCEqzb*xWX2CG*b&5IiO#NzrW*;`VC9455M`o1NBh+(k8~`XCEEoC1Ybwf;vr4K3 zg|EB<07?SOqHp9DhLpS&bzgo70I+ghB_#)K7H%AMU3v}xuyQq9&Bm~++VYhF09a+U zl7>n7Jjm$K#b*FONz~fj;I->Bf;ule1prFN9FovcDGBkpg>)O*-}eLnC{6oZHZ$o% zXKW$;0_{8hxHQ>l;_*HATI(`7t#^{$(zLe}h*mqwOc*nRY9=?Sx4OOeVIfI|0V(V2 zBrW#G7Ss9wvzr@>H*`r>zE z+e8bOBgqIgldUJlG(YUDviMB`9+DH8n-s9SXRLyJHO1!=wY^79WYZMTa(wiZ!zP66 zA~!21vmF3H2{ngD;+`6j#~6j;$*f*G_2ZD1E;9(yaw7d-QnSCpK(cR1zU3qU0000< KMNUMnLSTYoA~SLT diff --git a/Arduino/MAX6956/html/bdwn.png b/Arduino/MAX6956/html/bdwn.png deleted file mode 100644 index 940a0b950443a0bb1b216ac03c45b8a16c955452..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 147 zcmeAS@N?(olHy`uVBq!ia0vp^>_E)H!3HEvS)PKZC{Gv1kP61Pb5HX&C2wk~_T - - - - - -MAX6956: MAX6956 Class Reference - - - - - - - - - -
-
- - - - - - -
-
MAX6956 -  1.0 -
-
MAX6956i2Clibrary
-
-
- - - - - - - - - -
- -
- -
-
- -
-
MAX6956 Class Reference
-
-
- -

#include <MAX6956.h>

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

-Public Member Functions

 MAX6956 ()
 
 MAX6956 (uint8_t address)
 
void initialize ()
 
bool testConnection ()
 
void reset ()
 
uint8_t getConfigReg ()
 
void setConfigReg (uint8_t config)
 
bool getPower ()
 
void togglePower ()
 
void setPower (bool power)
 
bool getEnableIndividualCurrent ()
 
void setEnableIndividualCurrent (bool global)
 
bool getEnableTransitionDetection ()
 
void setEnableTransitionDetection (bool transition)
 
uint8_t getGlobalCurrent ()
 
void setGlobalCurrent (uint8_t current)
 
bool getTestMode ()
 
void setTestMode (bool test)
 
uint8_t getInputMask ()
 
void setInputMask (uint8_t mask)
 
void configPort (uint8_t port, uint8_t portConfig)
 
void configPorts (uint8_t lower, uint8_t upper, uint8_t portConfig)
 
void configAllPorts (uint8_t portConfig)
 
void setPortLevel (uint8_t port, uint8_t power)
 0 = off, 1-15 brightness levels. More...
 
void setPortCurrent (uint8_t port, uint8_t power)
 0-15 brightness levels. More...
 
void setAllPortsCurrent (uint8_t power)
 0-15, 0 = min brightness (not off) 15 = max More...
 
void enableAllPorts ()
 
void disableAllPorts ()
 
- - - - - -

-Data Fields

uint8_t portsConfig [5]
 
uint8_t portsStatus [3]
 
- - - - - - - - - - - - - - - - - - - - - - -

-Private Attributes

uint8_t devAddr
 Holds the current device address. More...
 
uint8_t buffer [1]
 Buffer for reading data from the device. More...
 
uint8_t portConfig
 Holder for port config bit pair. More...
 
uint8_t portCurrentRA
 Holder for port current register. More...
 
uint8_t portCurrentBit
 Holder for the current bit offset. More...
 
uint8_t psArrayIndex
 array index More...
 
uint8_t psBitPosition
 bit position More...
 
-

Detailed Description

-

A library for controlling the MAX6956 using i2C.

-

The MAX6956 compact, serial-interfaced LED display driver/I/O expander provide microprocessors with up to 28 ports. Each port is individually user configurable to either a logic input, logic output, or common-anode (CA) LED constant-current segment driver. Each port configured as an LED segment driver behaves as a digitally controlled constant-current sink, with 16 equal current steps from 1.5mA to 24mA. The LED drivers are suitable for both discrete LEDs and CA numeric and alphanumeric LED digits.

-

Each port configured as a general-purpose I/O (GPIO) can be either a push-pull logic output capable of sink- ing 10mA and sourcing 4.5mA, or a Schmitt logic input with optional internal pullup. Seven ports feature config- urable transition detection logic, which generates an interrupt upon change of port logic level. The MAX6956 is controlled through an I2C-compatible 2-wire serial interface, and uses four-level logic to allow 16 I 2C addresses from only 2 select pins.

-

The MAX6956AAX and MAX6956ATL have 28 ports and are available in 36-pin SSOP and 40-pin thin QFN packages, respectively. The MAX6956AAI and MAX6956ANI have 20 ports and are available in 28-pin SSOP and 28-pin DIP packages, respectively.

-

For an SPI-interfaced version, refer to the MAX6957 data sheet. For a lower cost pin-compatible port expander without the constant-current LED drive capa- bility, refer to the MAX7300 data sheet.

-
    -
  • 400kbps I2C-Compatible Serial Interface
  • -
  • 2.5V to 5.5V Operation
  • -
  • -40°C to +125°C Temperature Range
  • -
  • 20 or 28 I/O Ports, Each Configurable as
  • -
  • Constant-Current LED Driver
  • -
  • Push-Pull Logic Output
  • -
  • Schmitt Logic Input
  • -
  • Schmitt Logic Input with Internal Pullup
  • -
  • 11μA (max) Shutdown Current
  • -
  • 16-Step Individually Programmable Current
  • -
  • Control for Each LED
  • -
  • Logic Transition Detection for Seven I/O Ports
  • -
- -

Definition at line 456 of file MAX6956.h.

-

Constructor & Destructor Documentation

- -
-
- - - - - - - -
MAX6956::MAX6956 ()
-
-

Default constructor, uses default I2C address.

-
See Also
MAX6956_DEFAULT_ADDRESS
- -

Definition at line 40 of file MAX6956.cpp.

- -
-
- -
-
- - - - - - - - -
MAX6956::MAX6956 (uint8_t address)
-
-

Specific address constructor.

-
Parameters
- - -
addressI2C address
-
-
-
See Also
MAX6956_DEFAULT_ADDRESS
-
-MAX6956_ADDRESS
- -

Definition at line 49 of file MAX6956.cpp.

- -
-
-

Member Function Documentation

- -
-
- - - - - - - - -
void MAX6956::configAllPorts (uint8_t portConfig)
-
-
Configure all ports the same
-
Parameters
- - -
portConfigValid options are: MAX6956_OUTPUT_LED, MAX6956_OUTPUT_GPIO, MAX6956_INPUT_WO_PULL, MAX6956_INPUT_W_PULL
-
-
-
See Also
MAX6956_OUTPUT_LED
-
-MAX6956_OUTPUT_GPIO
-
-MAX6956_INPUT_WO_PULL
-
-MAX6956_INPUT_W_PULL
- -

Definition at line 332 of file MAX6956.cpp.

- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
void MAX6956::configPort (uint8_t port,
uint8_t portConfig 
)
-
-
Takes an INDIVIDUAL port register address (MAX6956_RA_PORT12, ect)
-and configures it as: MAX6956_OUTPUT_LED, MAX6956_OUTPUT_GPIO,
-MAX6956_INPUT_WO_PULL, or MAX6956_INPUT_W_PULL
-

Port registers

- - - - - - - - - - - - - - - - - -
Addr. Name
0x09 MAX6956_RA_CONFIG_P7P6P5P4
0x0A MAX6956_RA_CONFIG_P11P10P9P8
0x0B MAX6956_RA_CONFIG_P15P14P13P12
0x0C MAX6956_RA_CONFIG_P19P18P17P16
0x0D MAX6956_RA_CONFIG_P23P22P21P20
0x0E MAX6956_RA_CONFIG_P27P26P25P24
0x0F MAX6956_RA_CONFIG_P31P30P29P28
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NumDecHex PrtPort Status ArrayPorts Config Array
00 44 0x2CP12portsStatus[0][0]portsConfig[0][1-0]
01 45 0x2DP13portsStatus[0][1]portsConfig[0][3-2]
02 46 0x2EP14portsStatus[0][2]portsConfig[0][5-4]
03 47 0x2FP15portsStatus[0][3]portsConfig[0][7-6]
04 48 0x30P16portsStatus[0][4]portsConfig[1][1-0]
05 49 0x31P17portsStatus[0][5]portsConfig[1][3-2]
06 50 0x32P18portsStatus[0][6]portsConfig[1][5-4]
07 51 0x33P19portsStatus[0][7]portsConfig[1][7-6]
08 52 0x34P20portsStatus[1][0]portsConfig[2][1-0]
09 53 0x35P21portsStatus[1][1]portsConfig[2][3-2]
10 54 0x36P22portsStatus[1][2]portsConfig[2][5-4]
11 55 0x37P23portsStatus[1][3]portsConfig[2][7-6]
12 56 0x38P24portsStatus[1][4]portsConfig[3][1-0]
13 57 0x39P25portsStatus[1][5]portsConfig[3][3-2]
14 58 0x3AP26portsStatus[1][6]portsConfig[3][5-4]
15 59 0x3BP27portsStatus[1][7]portsConfig[3][7-6]
16 60 0x3CP28portsStatus[2][0]portsConfig[4][1-0]
17 61 0x3DP29portsStatus[2][1]portsConfig[4][3-2]
18 62 0x3EP30portsStatus[2][2]portsConfig[4][5-4]
19 63 0x3FP31portsStatus[2][3]portsConfig[4][7-6]
-
Parameters
- - - -
portPort register address (MAX6956_RA_PORT12, ect)
portConfigValid options are: MAX6956_OUTPUT_LED, MAX6956_OUTPUT_GPIO, MAX6956_INPUT_WO_PULL, MAX6956_INPUT_W_PULL
-
-
-
See Also
MAX6956_RA_PORT12 MAX6956_RA_PORT13 MAX6956_RA_PORT14 MAX6956_RA_PORT15 MAX6956_RA_PORT16 MAX6956_RA_PORT17 MAX6956_RA_PORT18 MAX6956_RA_PORT19 MAX6956_RA_PORT20 MAX6956_RA_PORT21 MAX6956_RA_PORT22 MAX6956_RA_PORT23 MAX6956_RA_PORT24 MAX6956_RA_PORT25 MAX6956_RA_PORT26 MAX6956_RA_PORT27 MAX6956_RA_PORT28 MAX6956_RA_PORT29 MAX6956_RA_PORT30 MAX6956_RA_PORT31
-
-MAX6956_OUTPUT_LED MAX6956_OUTPUT_GPIO MAX6956_INPUT_WO_PULL MAX6956_INPUT_W_PULL
- -

Definition at line 265 of file MAX6956.cpp.

- -
-
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void MAX6956::configPorts (uint8_t lower,
uint8_t upper,
uint8_t portConfig 
)
-
-

Configure consecutive range of ports

-
Parameters
- - - - -
lowerLower port register address (MAX6956_RA_PORT12, ect)
upperUpper port register address (MAX6956_RA_PORT12, ect)
portConfigValid options are: MAX6956_OUTPUT_LED, MAX6956_OUTPUT_GPIO, MAX6956_INPUT_WO_PULL, MAX6956_INPUT_W_PULL
-
-
-
See Also
MAX6956_OUTPUT_LED
-
-MAX6956_OUTPUT_GPIO
-
-MAX6956_INPUT_WO_PULL
-
-MAX6956_INPUT_W_PULL
- -

Definition at line 285 of file MAX6956.cpp.

- -
-
- -
-
- - - - - - - -
void MAX6956::disableAllPorts ()
-
-

Write 0's to all port registers.

- -

Definition at line 463 of file MAX6956.cpp.

- -
-
- -
-
- - - - - - - -
void MAX6956::enableAllPorts ()
-
-

Write 1's to all port registers. This enables ports set as outputs and they will always have some brightness, port must be disabled to turn off completely.

- -

Definition at line 453 of file MAX6956.cpp.

- -
-
- -
-
- - - - - - - -
uint8_t MAX6956::getConfigReg ()
-
-
Config register
-
Returns
uint8_t value of register
-
See Also
MAX6956_RA_CONFIGURATION
- -

Definition at line 94 of file MAX6956.cpp.

- -
-
- -
-
- - - - - - - -
bool MAX6956::getEnableIndividualCurrent ()
-
-
Get transition detection configuration bit 
-
Returns
Boolean value if global current is enabled or not
-
See Also
MAX6956_RA_CONFIGURATION
- -

Definition at line 134 of file MAX6956.cpp.

- -
-
- -
-
- - - - - - - -
bool MAX6956::getEnableTransitionDetection ()
-
-
Get transition detection configuration bit 
-
Returns
Boolean value if transition detection is enabled or not
-
See Also
MAX6956_RA_CONFIGURATION
- -

Definition at line 152 of file MAX6956.cpp.

- -
-
- -
-
- - - - - - - -
uint8_t MAX6956::getGlobalCurrent ()
-
-
Get global current 
-
Returns
uint8_t value of register
-
See Also
MAX6956_RA_GLOBAL_CURRENT
- -

Definition at line 171 of file MAX6956.cpp.

- -
-
- -
-
- - - - - - - -
uint8_t MAX6956::getInputMask ()
-
-
Get the input mask to see which ports have changed. MSB is cleared after every read.
-
Returns
uint8_t value of register
-
See Also
MAX6956_RA_TRANSITION_DETECT
- -

Definition at line 205 of file MAX6956.cpp.

- -
-
- -
-
- - - - - - - -
bool MAX6956::getPower ()
-
-
Get power configuration bit 
-
Returns
Boolean value if power is enabled or not
-
See Also
MAX6956_RA_CONFIGURATION
- -

Definition at line 110 of file MAX6956.cpp.

- -
-
- -
-
- - - - - - - -
bool MAX6956::getTestMode ()
-
-
Returns true if test mode is enabled. 
-
Returns
uint8_t value of register
-
See Also
MAX6956_RA_DISPLAY_TEST
- -

Definition at line 188 of file MAX6956.cpp.

- -
-
- -
-
- - - - - - - -
void MAX6956::initialize ()
-
-

Power on and prepare for general usage.

-
The 28-pin MAX6956ANI and MAX6956AAI make only 20 ports available, P12 to P31.
-

The eight unused ports should be configured as outputs on power-up by writing 0x55 to registers 0x09 and 0x0A. If this is not done,the eight unused ports remain as unconnected inputs and quiescent supply current rises, although there is no damage to the part.

- -

Definition at line 54 of file MAX6956.cpp.

- -
-
- -
-
- - - - - - - -
void MAX6956::reset ()
-
-

Set registers back to Power-up Configuration

- -

Definition at line 80 of file MAX6956.cpp.

- -
-
- -
-
- - - - - - - - -
void MAX6956::setAllPortsCurrent (uint8_t power)
-
- -

0-15, 0 = min brightness (not off) 15 = max

-

Set ALL port current registers (MAX6956_RA_PORT12, ect) to the SAME power level 0-15. 0 is off, 15 is max brightness.

-
Parameters
- - -
power0 is min, 15 is max brightness.
-
-
- -

Definition at line 444 of file MAX6956.cpp.

- -
-
- -
-
- - - - - - - - -
void MAX6956::setConfigReg (uint8_t config)
-
-
Set config register
-
Parameters
- - -
configuint8_t value to set register
-
-
-
See Also
MAX6956_RA_CONFIGURATION
- -

Definition at line 102 of file MAX6956.cpp.

- -
-
- -
-
- - - - - - - - -
void MAX6956::setEnableIndividualCurrent (bool global)
-
-
Enable or disable global current
-
Parameters
- - -
globalBoolean value, true enables, false disables individual current
-
-
-
See Also
MAX6956_RA_CONFIGURATION
-
-getGlobalCurrent()
-
-setGlobalCurrent()
- -

Definition at line 144 of file MAX6956.cpp.

- -
-
- -
-
- - - - - - - - -
void MAX6956::setEnableTransitionDetection (bool transition)
-
-
Enable or disable transition detection. Must be reset after every mask read.
-
Parameters
- - -
transitionBoolean value, true enables, false disables transition detection
-
-
-
See Also
MAX6956_RA_CONFIGURATION
-
-getInputMask()
-
-setInputMask()
- -

Definition at line 162 of file MAX6956.cpp.

- -
-
- -
-
- - - - - - - - -
void MAX6956::setGlobalCurrent (uint8_t current)
-
-
Set current globally
-
Parameters
- - -
currentuint8_t 0-15, 0 = min, 15 = max brightness
-
-
-
See Also
MAX6956_RA_GLOBAL_CURRENT
- -

Definition at line 179 of file MAX6956.cpp.

- -
-
- -
-
- - - - - - - - -
void MAX6956::setInputMask (uint8_t mask)
-
-
Set the input mask for which ports to monitor with transition detection
-
Parameters
- - -
mask8 bit value. MSB is ignored.
-
-
-
See Also
MAX6956_RA_TRANSITION_DETECT
- -

Definition at line 214 of file MAX6956.cpp.

- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
void MAX6956::setPortCurrent (uint8_t port,
uint8_t power 
)
-
- -

0-15 brightness levels.

-
Takes an INDIVIDUAL port register address (MAX6956_RA_PORT12, ect)
-

and sets it to a power level 0-15. 0 is min, 15 is max brightness.

-
Parameters
- - - -
portPort register address (MAX6956_RA_PORT12, ect)
power0 is min, 15 is max brightness.
-
-
- -

Definition at line 404 of file MAX6956.cpp.

- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
void MAX6956::setPortLevel (uint8_t port,
uint8_t power 
)
-
- -

0 = off, 1-15 brightness levels.

-
Takes an individual port register address (MAX6956_RA_PORT12, ect)
-

and sets it to a power scale where 0 = off.

-
Parameters
- - - -
portPort register address (MAX6956_RA_PORT12, ect)
power0 is off, 15 is max brightness.
-
-
- -

Definition at line 346 of file MAX6956.cpp.

- -
-
- -
-
- - - - - - - - -
void MAX6956::setPower (bool power)
-
-
Enable or disable power
-
Parameters
- - -
powerBoolean value, true enables, false disables power
-
-
-
See Also
MAX6956_RA_CONFIGURATION
- -

Definition at line 118 of file MAX6956.cpp.

- -
-
- -
-
- - - - - - - - -
void MAX6956::setTestMode (bool test)
-
-
Enable or disable test mode
-
Parameters
- - -
testBoolean, true enables, false disables
-
-
-
See Also
MAX6956_RA_DISPLAY_TEST
- -

Definition at line 196 of file MAX6956.cpp.

- -
-
- -
-
- - - - - - - -
bool MAX6956::testConnection ()
-
-

Verify the I2C connection. Make sure the device is connected and responds as expected.

-
Returns
True if connection is valid, false otherwise
- -

Definition at line 72 of file MAX6956.cpp.

- -
-
- -
-
- - - - - - - -
void MAX6956::togglePower ()
-
-
Toggle power
-
See Also
MAX6956_RA_CONFIGURATION
- -

Definition at line 124 of file MAX6956.cpp.

- -
-
-

Field Documentation

- -
-
- - - - - -
- - - - -
uint8_t MAX6956::buffer[1]
-
-private
-
- -

Buffer for reading data from the device.

- -

Definition at line 556 of file MAX6956.h.

- -
-
- -
-
- - - - - -
- - - - -
uint8_t MAX6956::devAddr
-
-private
-
- -

Holds the current device address.

- -

Definition at line 555 of file MAX6956.h.

- -
-
- -
-
- - - - - -
- - - - -
uint8_t MAX6956::portConfig
-
-private
-
- -

Holder for port config bit pair.

- -

Definition at line 557 of file MAX6956.h.

- -
-
- -
-
- - - - - -
- - - - -
uint8_t MAX6956::portCurrentBit
-
-private
-
- -

Holder for the current bit offset.

- -

Definition at line 559 of file MAX6956.h.

- -
-
- -
-
- - - - - -
- - - - -
uint8_t MAX6956::portCurrentRA
-
-private
-
- -

Holder for port current register.

- -

Definition at line 558 of file MAX6956.h.

- -
-
- -
-
- - - - -
uint8_t MAX6956::portsConfig[5]
-
-

Array that mirrors the configuration of all the ports.

-

P12 = portsConfig[0][1-0] P13 = portsConfig[0][3-2] P14 = portsConfig[0][5-4] P15 = portsConfig[0][7-6] P16 = portsConfig[1][1-0] P17 = portsConfig[1][3-2] P18 = portsConfig[1][5-4] P19 = portsConfig[1][7-6] P20 = portsConfig[2][1-0] P21 = portsConfig[2][3-2] P22 = portsConfig[2][5-4] P23 = portsConfig[2][7-6] P24 = portsConfig[3][1-0] P25 = portsConfig[3][3-2] P26 = portsConfig[3][5-4] P27 = portsConfig[3][7-6] P28 = portsConfig[4][1-0] P29 = portsConfig[4][3-2] P30 = portsConfig[4][5-4] P31 = portsConfig[4][7-6]

- -

Definition at line 527 of file MAX6956.h.

- -
-
- -
-
- - - - -
uint8_t MAX6956::portsStatus[3]
-
-

Array that mirrors the on/off status of all the ports.

-

P12 = portsStatus[0][0] P13 = portsStatus[0][1] P14 = portsStatus[0][2] P15 = portsStatus[0][3] P16 = portsStatus[0][4] P17 = portsStatus[0][5] P18 = portsStatus[0][6] P19 = portsStatus[0][7] P20 = portsStatus[1][0] P21 = portsStatus[1][1] P22 = portsStatus[1][2] P23 = portsStatus[1][3] P24 = portsStatus[1][4] P25 = portsStatus[1][5] P26 = portsStatus[1][6] P27 = portsStatus[1][7] P28 = portsStatus[2][0] P29 = portsStatus[2][1] P30 = portsStatus[2][2] P31 = portsStatus[2][3]

- -

Definition at line 552 of file MAX6956.h.

- -
-
- -
-
- - - - - -
- - - - -
uint8_t MAX6956::psArrayIndex
-
-private
-
- -

array index

- -

Definition at line 560 of file MAX6956.h.

- -
-
- -
-
- - - - - -
- - - - -
uint8_t MAX6956::psBitPosition
-
-private
-
- -

bit position

- -

Definition at line 561 of file MAX6956.h.

- -
-
-
The documentation for this class was generated from the following files: -
- - - - diff --git a/Arduino/MAX6956/html/classes.html b/Arduino/MAX6956/html/classes.html deleted file mode 100644 index 8aab2b55..00000000 --- a/Arduino/MAX6956/html/classes.html +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - -MAX6956: Data Structure Index - - - - - - - - - -
-
- - - - - - -
-
MAX6956 -  1.0 -
-
MAX6956i2Clibrary
-
-
- - - - - -
- - - - -
- -
- -
-
-
Data Structure Index
-
-
- - - - - - -
  M  
-
MAX6956   
- -
- - - - diff --git a/Arduino/MAX6956/html/closed.png b/Arduino/MAX6956/html/closed.png deleted file mode 100644 index 98cc2c909da37a6df914fbf67780eebd99c597f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 132 zcmeAS@N?(olHy`uVBq!ia0vp^oFL4>1|%O$WD@{V-kvUwAr*{o@8{^CZMh(5KoB^r_<4^zF@3)Cp&&t3hdujKf f*?bjBoY!V+E))@{xMcbjXe@)LtDnm{r-UW|*e5JT diff --git a/Arduino/MAX6956/html/doxygen.css b/Arduino/MAX6956/html/doxygen.css deleted file mode 100644 index 4699e697..00000000 --- a/Arduino/MAX6956/html/doxygen.css +++ /dev/null @@ -1,1357 +0,0 @@ -/* The standard CSS for doxygen 1.8.5 */ - -body, table, div, p, dl { - font: 400 14px/22px Roboto,sans-serif; -} - -/* @group Heading Levels */ - -h1.groupheader { - font-size: 150%; -} - -.title { - font: 400 14px/28px Roboto,sans-serif; - font-size: 150%; - font-weight: bold; - margin: 10px 2px; -} - -h2.groupheader { - border-bottom: 1px solid #879ECB; - color: #354C7B; - font-size: 150%; - font-weight: normal; - margin-top: 1.75em; - padding-top: 8px; - padding-bottom: 4px; - width: 100%; -} - -h3.groupheader { - font-size: 100%; -} - -h1, h2, h3, h4, h5, h6 { - -webkit-transition: text-shadow 0.5s linear; - -moz-transition: text-shadow 0.5s linear; - -ms-transition: text-shadow 0.5s linear; - -o-transition: text-shadow 0.5s linear; - transition: text-shadow 0.5s linear; - margin-right: 15px; -} - -h1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow { - text-shadow: 0 0 15px cyan; -} - -dt { - font-weight: bold; -} - -div.multicol { - -moz-column-gap: 1em; - -webkit-column-gap: 1em; - -moz-column-count: 3; - -webkit-column-count: 3; -} - -p.startli, p.startdd, p.starttd { - margin-top: 2px; -} - -p.endli { - margin-bottom: 0px; -} - -p.enddd { - margin-bottom: 4px; -} - -p.endtd { - margin-bottom: 2px; -} - -/* @end */ - -caption { - font-weight: bold; -} - -span.legend { - font-size: 70%; - text-align: center; -} - -h3.version { - font-size: 90%; - text-align: center; -} - -div.qindex, div.navtab{ - background-color: #EBEFF6; - border: 1px solid #A3B4D7; - text-align: center; -} - -div.qindex, div.navpath { - width: 100%; - line-height: 140%; -} - -div.navtab { - margin-right: 15px; -} - -/* @group Link Styling */ - -a { - color: #3D578C; - font-weight: normal; - text-decoration: none; -} - -.contents a:visited { - color: #4665A2; -} - -a:hover { - text-decoration: underline; -} - -a.qindex { - font-weight: bold; -} - -a.qindexHL { - font-weight: bold; - background-color: #9CAFD4; - color: #ffffff; - border: 1px double #869DCA; -} - -.contents a.qindexHL:visited { - color: #ffffff; -} - -a.el { - font-weight: bold; -} - -a.elRef { -} - -a.code, a.code:visited, a.line, a.line:visited { - color: #4665A2; -} - -a.codeRef, a.codeRef:visited, a.lineRef, a.lineRef:visited { - color: #4665A2; -} - -/* @end */ - -dl.el { - margin-left: -1cm; -} - -pre.fragment { - border: 1px solid #C4CFE5; - background-color: #FBFCFD; - padding: 4px 6px; - margin: 4px 8px 4px 2px; - overflow: auto; - word-wrap: break-word; - font-size: 9pt; - line-height: 125%; - font-family: monospace, fixed; - font-size: 105%; -} - -div.fragment { - padding: 0px; - margin: 0px; - background-color: #FBFCFD; - border: 1px solid #C4CFE5; -} - -div.line { - font-family: monospace, fixed; - font-size: 13px; - min-height: 13px; - line-height: 1.0; - text-wrap: unrestricted; - white-space: -moz-pre-wrap; /* Moz */ - white-space: -pre-wrap; /* Opera 4-6 */ - white-space: -o-pre-wrap; /* Opera 7 */ - white-space: pre-wrap; /* CSS3 */ - word-wrap: break-word; /* IE 5.5+ */ - text-indent: -53px; - padding-left: 53px; - padding-bottom: 0px; - margin: 0px; - -webkit-transition-property: background-color, box-shadow; - -webkit-transition-duration: 0.5s; - -moz-transition-property: background-color, box-shadow; - -moz-transition-duration: 0.5s; - -ms-transition-property: background-color, box-shadow; - -ms-transition-duration: 0.5s; - -o-transition-property: background-color, box-shadow; - -o-transition-duration: 0.5s; - transition-property: background-color, box-shadow; - transition-duration: 0.5s; -} - -div.line.glow { - background-color: cyan; - box-shadow: 0 0 10px cyan; -} - - -span.lineno { - padding-right: 4px; - text-align: right; - border-right: 2px solid #0F0; - background-color: #E8E8E8; - white-space: pre; -} -span.lineno a { - background-color: #D8D8D8; -} - -span.lineno a:hover { - background-color: #C8C8C8; -} - -div.ah { - background-color: black; - font-weight: bold; - color: #ffffff; - margin-bottom: 3px; - margin-top: 3px; - padding: 0.2em; - border: solid thin #333; - border-radius: 0.5em; - -webkit-border-radius: .5em; - -moz-border-radius: .5em; - box-shadow: 2px 2px 3px #999; - -webkit-box-shadow: 2px 2px 3px #999; - -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; - background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#000),color-stop(0.3, #444)); - background-image: -moz-linear-gradient(center top, #eee 0%, #444 40%, #000); -} - -div.groupHeader { - margin-left: 16px; - margin-top: 12px; - font-weight: bold; -} - -div.groupText { - margin-left: 16px; - font-style: italic; -} - -body { - background-color: white; - color: black; - margin: 0; -} - -div.contents { - margin-top: 10px; - margin-left: 12px; - margin-right: 8px; -} - -td.indexkey { - background-color: #EBEFF6; - font-weight: bold; - border: 1px solid #C4CFE5; - margin: 2px 0px 2px 0; - padding: 2px 10px; - white-space: nowrap; - vertical-align: top; -} - -td.indexvalue { - background-color: #EBEFF6; - border: 1px solid #C4CFE5; - padding: 2px 10px; - margin: 2px 0px; -} - -tr.memlist { - background-color: #EEF1F7; -} - -p.formulaDsp { - text-align: center; -} - -img.formulaDsp { - -} - -img.formulaInl { - vertical-align: middle; -} - -div.center { - text-align: center; - margin-top: 0px; - margin-bottom: 0px; - padding: 0px; -} - -div.center img { - border: 0px; -} - -address.footer { - text-align: right; - padding-right: 12px; -} - -img.footer { - border: 0px; - vertical-align: middle; -} - -/* @group Code Colorization */ - -span.keyword { - color: #008000 -} - -span.keywordtype { - color: #604020 -} - -span.keywordflow { - color: #e08000 -} - -span.comment { - color: #800000 -} - -span.preprocessor { - color: #806020 -} - -span.stringliteral { - color: #002080 -} - -span.charliteral { - color: #008080 -} - -span.vhdldigit { - color: #ff00ff -} - -span.vhdlchar { - color: #000000 -} - -span.vhdlkeyword { - color: #700070 -} - -span.vhdllogic { - color: #ff0000 -} - -blockquote { - background-color: #F7F8FB; - border-left: 2px solid #9CAFD4; - margin: 0 24px 0 4px; - padding: 0 12px 0 16px; -} - -/* @end */ - -/* -.search { - color: #003399; - font-weight: bold; -} - -form.search { - margin-bottom: 0px; - margin-top: 0px; -} - -input.search { - font-size: 75%; - color: #000080; - font-weight: normal; - background-color: #e8eef2; -} -*/ - -td.tiny { - font-size: 75%; -} - -.dirtab { - padding: 4px; - border-collapse: collapse; - border: 1px solid #A3B4D7; -} - -th.dirtab { - background: #EBEFF6; - font-weight: bold; -} - -hr { - height: 0px; - border: none; - border-top: 1px solid #4A6AAA; -} - -hr.footer { - height: 1px; -} - -/* @group Member Descriptions */ - -table.memberdecls { - border-spacing: 0px; - padding: 0px; -} - -.memberdecls td, .fieldtable tr { - -webkit-transition-property: background-color, box-shadow; - -webkit-transition-duration: 0.5s; - -moz-transition-property: background-color, box-shadow; - -moz-transition-duration: 0.5s; - -ms-transition-property: background-color, box-shadow; - -ms-transition-duration: 0.5s; - -o-transition-property: background-color, box-shadow; - -o-transition-duration: 0.5s; - transition-property: background-color, box-shadow; - transition-duration: 0.5s; -} - -.memberdecls td.glow, .fieldtable tr.glow { - background-color: cyan; - box-shadow: 0 0 15px cyan; -} - -.mdescLeft, .mdescRight, -.memItemLeft, .memItemRight, -.memTemplItemLeft, .memTemplItemRight, .memTemplParams { - background-color: #F9FAFC; - border: none; - margin: 4px; - padding: 1px 0 0 8px; -} - -.mdescLeft, .mdescRight { - padding: 0px 8px 4px 8px; - color: #555; -} - -.memSeparator { - border-bottom: 1px solid #DEE4F0; - line-height: 1px; - margin: 0px; - padding: 0px; -} - -.memItemLeft, .memTemplItemLeft { - white-space: nowrap; -} - -.memItemRight { - width: 100%; -} - -.memTemplParams { - color: #4665A2; - white-space: nowrap; - font-size: 80%; -} - -/* @end */ - -/* @group Member Details */ - -/* Styles for detailed member documentation */ - -.memtemplate { - font-size: 80%; - color: #4665A2; - font-weight: normal; - margin-left: 9px; -} - -.memnav { - background-color: #EBEFF6; - border: 1px solid #A3B4D7; - text-align: center; - margin: 2px; - margin-right: 15px; - padding: 2px; -} - -.mempage { - width: 100%; -} - -.memitem { - padding: 0; - margin-bottom: 10px; - margin-right: 5px; - -webkit-transition: box-shadow 0.5s linear; - -moz-transition: box-shadow 0.5s linear; - -ms-transition: box-shadow 0.5s linear; - -o-transition: box-shadow 0.5s linear; - transition: box-shadow 0.5s linear; - display: table !important; - width: 100%; -} - -.memitem.glow { - box-shadow: 0 0 15px cyan; -} - -.memname { - font-weight: bold; - margin-left: 6px; -} - -.memname td { - vertical-align: bottom; -} - -.memproto, dl.reflist dt { - border-top: 1px solid #A8B8D9; - border-left: 1px solid #A8B8D9; - border-right: 1px solid #A8B8D9; - padding: 6px 0px 6px 0px; - color: #253555; - font-weight: bold; - text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); - background-image:url('http://github.com/nav_f.png'); - background-repeat:repeat-x; - background-color: #E2E8F2; - /* opera specific markup */ - box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); - border-top-right-radius: 4px; - border-top-left-radius: 4px; - /* firefox specific markup */ - -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; - -moz-border-radius-topright: 4px; - -moz-border-radius-topleft: 4px; - /* webkit specific markup */ - -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); - -webkit-border-top-right-radius: 4px; - -webkit-border-top-left-radius: 4px; - -} - -.memdoc, dl.reflist dd { - border-bottom: 1px solid #A8B8D9; - border-left: 1px solid #A8B8D9; - border-right: 1px solid #A8B8D9; - padding: 6px 10px 2px 10px; - background-color: #FBFCFD; - border-top-width: 0; - background-image:url('http://github.com/nav_g.png'); - background-repeat:repeat-x; - background-color: #FFFFFF; - /* opera specific markup */ - border-bottom-left-radius: 4px; - border-bottom-right-radius: 4px; - box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); - /* firefox specific markup */ - -moz-border-radius-bottomleft: 4px; - -moz-border-radius-bottomright: 4px; - -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; - /* webkit specific markup */ - -webkit-border-bottom-left-radius: 4px; - -webkit-border-bottom-right-radius: 4px; - -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); -} - -dl.reflist dt { - padding: 5px; -} - -dl.reflist dd { - margin: 0px 0px 10px 0px; - padding: 5px; -} - -.paramkey { - text-align: right; -} - -.paramtype { - white-space: nowrap; -} - -.paramname { - color: #602020; - white-space: nowrap; -} -.paramname em { - font-style: normal; -} -.paramname code { - line-height: 14px; -} - -.params, .retval, .exception, .tparams { - margin-left: 0px; - padding-left: 0px; -} - -.params .paramname, .retval .paramname { - font-weight: bold; - vertical-align: top; -} - -.params .paramtype { - font-style: italic; - vertical-align: top; -} - -.params .paramdir { - font-family: "courier new",courier,monospace; - vertical-align: top; -} - -table.mlabels { - border-spacing: 0px; -} - -td.mlabels-left { - width: 100%; - padding: 0px; -} - -td.mlabels-right { - vertical-align: bottom; - padding: 0px; - white-space: nowrap; -} - -span.mlabels { - margin-left: 8px; -} - -span.mlabel { - background-color: #728DC1; - border-top:1px solid #5373B4; - border-left:1px solid #5373B4; - border-right:1px solid #C4CFE5; - border-bottom:1px solid #C4CFE5; - text-shadow: none; - color: white; - margin-right: 4px; - padding: 2px 3px; - border-radius: 3px; - font-size: 7pt; - white-space: nowrap; - vertical-align: middle; -} - - - -/* @end */ - -/* these are for tree view when not used as main index */ - -div.directory { - margin: 10px 0px; - border-top: 1px solid #A8B8D9; - border-bottom: 1px solid #A8B8D9; - width: 100%; -} - -.directory table { - border-collapse:collapse; -} - -.directory td { - margin: 0px; - padding: 0px; - vertical-align: top; -} - -.directory td.entry { - white-space: nowrap; - padding-right: 6px; - padding-top: 3px; -} - -.directory td.entry a { - outline:none; -} - -.directory td.entry a img { - border: none; -} - -.directory td.desc { - width: 100%; - padding-left: 6px; - padding-right: 6px; - padding-top: 3px; - border-left: 1px solid rgba(0,0,0,0.05); -} - -.directory tr.even { - padding-left: 6px; - background-color: #F7F8FB; -} - -.directory img { - vertical-align: -30%; -} - -.directory .levels { - white-space: nowrap; - width: 100%; - text-align: right; - font-size: 9pt; -} - -.directory .levels span { - cursor: pointer; - padding-left: 2px; - padding-right: 2px; - color: #3D578C; -} - -div.dynheader { - margin-top: 8px; - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} - -address { - font-style: normal; - color: #2A3D61; -} - -table.doxtable { - border-collapse:collapse; - margin-top: 4px; - margin-bottom: 4px; -} - -table.doxtable td, table.doxtable th { - border: 1px solid #2D4068; - padding: 3px 7px 2px; -} - -table.doxtable th { - background-color: #374F7F; - color: #FFFFFF; - font-size: 110%; - padding-bottom: 4px; - padding-top: 5px; -} - -table.fieldtable { - /*width: 100%;*/ - margin-bottom: 10px; - border: 1px solid #A8B8D9; - border-spacing: 0px; - -moz-border-radius: 4px; - -webkit-border-radius: 4px; - border-radius: 4px; - -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; - -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); - box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); -} - -.fieldtable td, .fieldtable th { - padding: 3px 7px 2px; -} - -.fieldtable td.fieldtype, .fieldtable td.fieldname { - white-space: nowrap; - border-right: 1px solid #A8B8D9; - border-bottom: 1px solid #A8B8D9; - vertical-align: top; -} - -.fieldtable td.fieldname { - padding-top: 3px; -} - -.fieldtable td.fielddoc { - border-bottom: 1px solid #A8B8D9; - /*width: 100%;*/ -} - -.fieldtable td.fielddoc p:first-child { - margin-top: 0px; -} - -.fieldtable td.fielddoc p:last-child { - margin-bottom: 2px; -} - -.fieldtable tr:last-child td { - border-bottom: none; -} - -.fieldtable th { - background-image:url('http://github.com/nav_f.png'); - background-repeat:repeat-x; - background-color: #E2E8F2; - font-size: 90%; - color: #253555; - padding-bottom: 4px; - padding-top: 5px; - text-align:left; - -moz-border-radius-topleft: 4px; - -moz-border-radius-topright: 4px; - -webkit-border-top-left-radius: 4px; - -webkit-border-top-right-radius: 4px; - border-top-left-radius: 4px; - border-top-right-radius: 4px; - border-bottom: 1px solid #A8B8D9; -} - - -.tabsearch { - top: 0px; - left: 10px; - height: 36px; - background-image: url('http://github.com/tab_b.png'); - z-index: 101; - overflow: hidden; - font-size: 13px; -} - -.navpath ul -{ - font-size: 11px; - background-image:url('http://github.com/tab_b.png'); - background-repeat:repeat-x; - background-position: 0 -5px; - height:30px; - line-height:30px; - color:#8AA0CC; - border:solid 1px #C2CDE4; - overflow:hidden; - margin:0px; - padding:0px; -} - -.navpath li -{ - list-style-type:none; - float:left; - padding-left:10px; - padding-right:15px; - background-image:url('http://github.com/bc_s.png'); - background-repeat:no-repeat; - background-position:right; - color:#364D7C; -} - -.navpath li.navelem a -{ - height:32px; - display:block; - text-decoration: none; - outline: none; - color: #283A5D; - font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; - text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); - text-decoration: none; -} - -.navpath li.navelem a:hover -{ - color:#6884BD; -} - -.navpath li.footer -{ - list-style-type:none; - float:right; - padding-left:10px; - padding-right:15px; - background-image:none; - background-repeat:no-repeat; - background-position:right; - color:#364D7C; - font-size: 8pt; -} - - -div.summary -{ - float: right; - font-size: 8pt; - padding-right: 5px; - width: 50%; - text-align: right; -} - -div.summary a -{ - white-space: nowrap; -} - -div.ingroups -{ - font-size: 8pt; - width: 50%; - text-align: left; -} - -div.ingroups a -{ - white-space: nowrap; -} - -div.header -{ - background-image:url('http://github.com/nav_h.png'); - background-repeat:repeat-x; - background-color: #F9FAFC; - margin: 0px; - border-bottom: 1px solid #C4CFE5; -} - -div.headertitle -{ - padding: 5px 5px 5px 10px; -} - -dl -{ - padding: 0 0 0 10px; -} - -/* dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug */ -dl.section -{ - margin-left: 0px; - padding-left: 0px; -} - -dl.note -{ - margin-left:-7px; - padding-left: 3px; - border-left:4px solid; - border-color: #D0C000; -} - -dl.warning, dl.attention -{ - margin-left:-7px; - padding-left: 3px; - border-left:4px solid; - border-color: #FF0000; -} - -dl.pre, dl.post, dl.invariant -{ - margin-left:-7px; - padding-left: 3px; - border-left:4px solid; - border-color: #00D000; -} - -dl.deprecated -{ - margin-left:-7px; - padding-left: 3px; - border-left:4px solid; - border-color: #505050; -} - -dl.todo -{ - margin-left:-7px; - padding-left: 3px; - border-left:4px solid; - border-color: #00C0E0; -} - -dl.test -{ - margin-left:-7px; - padding-left: 3px; - border-left:4px solid; - border-color: #3030E0; -} - -dl.bug -{ - margin-left:-7px; - padding-left: 3px; - border-left:4px solid; - border-color: #C08050; -} - -dl.section dd { - margin-bottom: 6px; -} - - -#projectlogo -{ - text-align: center; - vertical-align: bottom; - border-collapse: separate; -} - -#projectlogo img -{ - border: 0px none; -} - -#projectname -{ - font: 300% Tahoma, Arial,sans-serif; - margin: 0px; - padding: 2px 0px; -} - -#projectbrief -{ - font: 120% Tahoma, Arial,sans-serif; - margin: 0px; - padding: 0px; -} - -#projectnumber -{ - font: 50% Tahoma, Arial,sans-serif; - margin: 0px; - padding: 0px; -} - -#titlearea -{ - padding: 0px; - margin: 0px; - width: 100%; - border-bottom: 1px solid #5373B4; -} - -.image -{ - text-align: center; -} - -.dotgraph -{ - text-align: center; -} - -.mscgraph -{ - text-align: center; -} - -.caption -{ - font-weight: bold; -} - -div.zoom -{ - border: 1px solid #90A5CE; -} - -dl.citelist { - margin-bottom:50px; -} - -dl.citelist dt { - color:#334975; - float:left; - font-weight:bold; - margin-right:10px; - padding:5px; -} - -dl.citelist dd { - margin:2px 0; - padding:5px 0; -} - -div.toc { - padding: 14px 25px; - background-color: #F4F6FA; - border: 1px solid #D8DFEE; - border-radius: 7px 7px 7px 7px; - float: right; - height: auto; - margin: 0 20px 10px 10px; - width: 200px; -} - -div.toc li { - background: url("http://github.com/bdwn.png") no-repeat scroll 0 5px transparent; - font: 10px/1.2 Verdana,DejaVu Sans,Geneva,sans-serif; - margin-top: 5px; - padding-left: 10px; - padding-top: 2px; -} - -div.toc h3 { - font: bold 12px/1.2 Arial,FreeSans,sans-serif; - color: #4665A2; - border-bottom: 0 none; - margin: 0; -} - -div.toc ul { - list-style: none outside none; - border: medium none; - padding: 0px; -} - -div.toc li.level1 { - margin-left: 0px; -} - -div.toc li.level2 { - margin-left: 15px; -} - -div.toc li.level3 { - margin-left: 30px; -} - -div.toc li.level4 { - margin-left: 45px; -} - -.inherit_header { - font-weight: bold; - color: gray; - cursor: pointer; - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} - -.inherit_header td { - padding: 6px 0px 2px 5px; -} - -.inherit { - display: none; -} - -tr.heading h2 { - margin-top: 12px; - margin-bottom: 4px; -} - -/* tooltip related style info */ - -.ttc { - position: absolute; - display: none; -} - -#powerTip { - cursor: default; - white-space: nowrap; - background-color: white; - border: 1px solid gray; - border-radius: 4px 4px 4px 4px; - box-shadow: 1px 1px 7px gray; - display: none; - font-size: smaller; - max-width: 80%; - opacity: 0.9; - padding: 1ex 1em 1em; - position: absolute; - z-index: 2147483647; -} - -#powerTip div.ttdoc { - color: grey; - font-style: italic; -} - -#powerTip div.ttname a { - font-weight: bold; -} - -#powerTip div.ttname { - font-weight: bold; -} - -#powerTip div.ttdeci { - color: #006318; -} - -#powerTip div { - margin: 0px; - padding: 0px; - font: 12px/16px Roboto,sans-serif; -} - -#powerTip:before, #powerTip:after { - content: ""; - position: absolute; - margin: 0px; -} - -#powerTip.n:after, #powerTip.n:before, -#powerTip.s:after, #powerTip.s:before, -#powerTip.w:after, #powerTip.w:before, -#powerTip.e:after, #powerTip.e:before, -#powerTip.ne:after, #powerTip.ne:before, -#powerTip.se:after, #powerTip.se:before, -#powerTip.nw:after, #powerTip.nw:before, -#powerTip.sw:after, #powerTip.sw:before { - border: solid transparent; - content: " "; - height: 0; - width: 0; - position: absolute; -} - -#powerTip.n:after, #powerTip.s:after, -#powerTip.w:after, #powerTip.e:after, -#powerTip.nw:after, #powerTip.ne:after, -#powerTip.sw:after, #powerTip.se:after { - border-color: rgba(255, 255, 255, 0); -} - -#powerTip.n:before, #powerTip.s:before, -#powerTip.w:before, #powerTip.e:before, -#powerTip.nw:before, #powerTip.ne:before, -#powerTip.sw:before, #powerTip.se:before { - border-color: rgba(128, 128, 128, 0); -} - -#powerTip.n:after, #powerTip.n:before, -#powerTip.ne:after, #powerTip.ne:before, -#powerTip.nw:after, #powerTip.nw:before { - top: 100%; -} - -#powerTip.n:after, #powerTip.ne:after, #powerTip.nw:after { - border-top-color: #ffffff; - border-width: 10px; - margin: 0px -10px; -} -#powerTip.n:before { - border-top-color: #808080; - border-width: 11px; - margin: 0px -11px; -} -#powerTip.n:after, #powerTip.n:before { - left: 50%; -} - -#powerTip.nw:after, #powerTip.nw:before { - right: 14px; -} - -#powerTip.ne:after, #powerTip.ne:before { - left: 14px; -} - -#powerTip.s:after, #powerTip.s:before, -#powerTip.se:after, #powerTip.se:before, -#powerTip.sw:after, #powerTip.sw:before { - bottom: 100%; -} - -#powerTip.s:after, #powerTip.se:after, #powerTip.sw:after { - border-bottom-color: #ffffff; - border-width: 10px; - margin: 0px -10px; -} - -#powerTip.s:before, #powerTip.se:before, #powerTip.sw:before { - border-bottom-color: #808080; - border-width: 11px; - margin: 0px -11px; -} - -#powerTip.s:after, #powerTip.s:before { - left: 50%; -} - -#powerTip.sw:after, #powerTip.sw:before { - right: 14px; -} - -#powerTip.se:after, #powerTip.se:before { - left: 14px; -} - -#powerTip.e:after, #powerTip.e:before { - left: 100%; -} -#powerTip.e:after { - border-left-color: #ffffff; - border-width: 10px; - top: 50%; - margin-top: -10px; -} -#powerTip.e:before { - border-left-color: #808080; - border-width: 11px; - top: 50%; - margin-top: -11px; -} - -#powerTip.w:after, #powerTip.w:before { - right: 100%; -} -#powerTip.w:after { - border-right-color: #ffffff; - border-width: 10px; - top: 50%; - margin-top: -10px; -} -#powerTip.w:before { - border-right-color: #808080; - border-width: 11px; - top: 50%; - margin-top: -11px; -} - -@media print -{ - #top { display: none; } - #side-nav { display: none; } - #nav-path { display: none; } - body { overflow:visible; } - h1, h2, h3, h4, h5, h6 { page-break-after: avoid; } - .summary { display: none; } - .memitem { page-break-inside: avoid; } - #doc-content - { - margin-left:0 !important; - height:auto !important; - width:auto !important; - overflow:inherit; - display:inline; - } -} - diff --git a/Arduino/MAX6956/html/doxygen.png b/Arduino/MAX6956/html/doxygen.png deleted file mode 100644 index 3ff17d807fd8aa003bed8bb2a69e8f0909592fd1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3779 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 diff --git a/Arduino/MAX6956/html/dynsections.js b/Arduino/MAX6956/html/dynsections.js deleted file mode 100644 index 2f15470d..00000000 --- a/Arduino/MAX6956/html/dynsections.js +++ /dev/null @@ -1,104 +0,0 @@ -function toggleVisibility(linkObj) -{ - var base = $(linkObj).attr('id'); - var summary = $('#'+base+'-summary'); - var content = $('#'+base+'-content'); - var trigger = $('#'+base+'-trigger'); - var src=$(trigger).attr('src'); - if (content.is(':visible')===true) { - content.hide(); - summary.show(); - $(linkObj).addClass('closed').removeClass('opened'); - $(trigger).attr('src',src.substring(0,src.length-8)+'closed.png'); - } else { - content.show(); - summary.hide(); - $(linkObj).removeClass('closed').addClass('opened'); - $(trigger).attr('src',src.substring(0,src.length-10)+'open.png'); - } - return false; -} - -function updateStripes() -{ - $('table.directory tr'). - removeClass('even').filter(':visible:even').addClass('even'); -} -function toggleLevel(level) -{ - $('table.directory tr').each(function(){ - var l = this.id.split('_').length-1; - var i = $('#img'+this.id.substring(3)); - var a = $('#arr'+this.id.substring(3)); - if (l - - - - - -MAX6956: File List - - - - - - - - - -
-
- - - - - - -
-
MAX6956 -  1.0 -
-
MAX6956i2Clibrary
-
-
- - - - - -
- - - - -
- -
- -
-
-
File List
-
-
-
Here is a list of all files with brief descriptions:
-
- - - - diff --git a/Arduino/MAX6956/html/ftv2blank.png b/Arduino/MAX6956/html/ftv2blank.png deleted file mode 100644 index 63c605bb4c3d941c921a4b6cfa74951e946bcb48..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 86 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRr!3HExu9B$%QnH>djv*C{Z|`mdau^P8_z}#X h?B8GEpdi4(BFDx$je&7RrDQEg&ePS;Wt~$(69Dh@6T1Ka diff --git a/Arduino/MAX6956/html/ftv2cl.png b/Arduino/MAX6956/html/ftv2cl.png deleted file mode 100644 index 132f6577bf7f085344904602815a260d29f55d9b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 453 zcmV;$0XqJPP)VBF;ev;toEj8_OB0EQg5eYilIj#JZG_m^33l3^k4mtzx!TVD?g)Y$ zrvwRDSqT!wLIM$dWCIa$vtxE|mzbTzu-y&$FvF6WA2a{Wr1g}`WdPT-0JzEZ0IxAv z-Z+ejZc&H;I5-pb_SUB}04j0^V)3t{`z<7asDl2Tw3w3sP%)0^8$bhEg)IOTBcRXv zFfq~3&gvJ$F-U7mpBW8z1GY~HK&7h4^YI~Orv~wLnC0PP_dAkv;nzX{9Q|8Gv=2ca z@v)c9T;D#h`TZ2X&&$ff2wedmot995de~-s3I)yauahg;7qn*?1n?F$e+PwP37}~; z1NKUk7reVK^7A;$QRW7qAx40HHUZ<|k3U%nz(Ec`#i+q9K!dgcROAlCS?`L= v>#=f?wF5ZND!1uAfQsk;KN^4&*8~0npJiJ%2dj9(00000NkvXXu0mjfWVFf_ diff --git a/Arduino/MAX6956/html/ftv2doc.png b/Arduino/MAX6956/html/ftv2doc.png deleted file mode 100644 index 17edabff95f7b8da13c9516a04efe05493c29501..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 746 zcmV7=@pnbNXRFEm&G8P!&WHG=d)>K?YZ1bzou)2{$)) zumDct!>4SyxL;zgaG>wy`^Hv*+}0kUfCrz~BCOViSb$_*&;{TGGn2^x9K*!Sf0=lV zpP=7O;GA0*Jm*tTYj$IoXvimpnV4S1Z5f$p*f$Db2iq2zrVGQUz~yq`ahn7ck(|CE z7Gz;%OP~J6)tEZWDzjhL9h2hdfoU2)Nd%T<5Kt;Y0XLt&<@6pQx!nw*5`@bq#?l*?3z{Hlzoc=Pr>oB5(9i6~_&-}A(4{Q$>c>%rV&E|a(r&;?i5cQB=} zYSDU5nXG)NS4HEs0it2AHe2>shCyr7`6@4*6{r@8fXRbTA?=IFVWAQJL&H5H{)DpM#{W(GL+Idzf^)uRV@oB8u$ z8v{MfJbTiiRg4bza<41NAzrl{=3fl_D+$t+^!xlQ8S}{UtY`e z;;&9UhyZqQRN%2pot{*Ei0*4~hSF_3AH2@fKU!$NSflS>{@tZpDT4`M2WRTTVH+D? z)GFlEGGHe?koB}i|1w45!BF}N_q&^HJ&-tyR{(afC6H7|aml|tBBbv}55C5DNP8p3 z)~jLEO4Z&2hZmP^i-e%(@d!(E|KRafiU8Q5u(wU((j8un3OR*Hvj+t diff --git a/Arduino/MAX6956/html/ftv2folderclosed.png b/Arduino/MAX6956/html/ftv2folderclosed.png deleted file mode 100644 index bb8ab35edce8e97554e360005ee9fc5bffb36e66..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 616 zcmV-u0+;=XP)a9#ETzayK)T~Jw&MMH>OIr#&;dC}is*2Mqdf&akCc=O@`qC+4i z5Iu3w#1M@KqXCz8TIZd1wli&kkl2HVcAiZ8PUn5z_kG@-y;?yK06=cA0U%H0PH+kU zl6dp}OR(|r8-RG+YLu`zbI}5TlOU6ToR41{9=uz^?dGTNL;wIMf|V3`d1Wj3y!#6` zBLZ?xpKR~^2x}?~zA(_NUu3IaDB$tKma*XUdOZN~c=dLt_h_k!dbxm_*ibDM zlFX`g{k$X}yIe%$N)cn1LNu=q9_CS)*>A zsX_mM4L@`(cSNQKMFc$RtYbx{79#j-J7hk*>*+ZZhM4Hw?I?rsXCi#mRWJ=-0LGV5a-WR0Qgt<|Nqf)C-@80`5gIz45^_20000IqP)X=#(TiCT&PiIIVc55T}TU}EUh*{q$|`3@{d>{Tc9Bo>e= zfmF3!f>fbI9#GoEHh0f`i5)wkLpva0ztf%HpZneK?w-7AK@b4Itw{y|Zd3k!fH?q2 zlhckHd_V2M_X7+)U&_Xcfvtw60l;--DgZmLSw-Y?S>)zIqMyJ1#FwLU*%bl38ok+! zh78H87n`ZTS;uhzAR$M`zZ`bVhq=+%u9^$5jDplgxd44}9;IRqUH1YHH|@6oFe%z( zo4)_>E$F&^P-f(#)>(TrnbE>Pefs9~@iN=|)Rz|V`sGfHNrJ)0gJb8xx+SBmRf@1l zvuzt=vGfI)<-F9!o&3l?>9~0QbUDT(wFdnQPv%xdD)m*g%!20>Bc9iYmGAp<9YAa( z0QgYgTWqf1qN++Gqp z8@AYPTB3E|6s=WLG?xw0tm|U!o=&zd+H0oRYE;Dbx+Na9s^STqX|Gnq%H8s(nGDGJ j8vwW|`Ts`)fSK|Kx=IK@RG@g200000NkvXXu0mjfauFEA diff --git a/Arduino/MAX6956/html/ftv2lastnode.png b/Arduino/MAX6956/html/ftv2lastnode.png deleted file mode 100644 index 63c605bb4c3d941c921a4b6cfa74951e946bcb48..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 86 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRr!3HExu9B$%QnH>djv*C{Z|`mdau^P8_z}#X h?B8GEpdi4(BFDx$je&7RrDQEg&ePS;Wt~$(69Dh@6T1Ka diff --git a/Arduino/MAX6956/html/ftv2link.png b/Arduino/MAX6956/html/ftv2link.png deleted file mode 100644 index 17edabff95f7b8da13c9516a04efe05493c29501..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 746 zcmV7=@pnbNXRFEm&G8P!&WHG=d)>K?YZ1bzou)2{$)) zumDct!>4SyxL;zgaG>wy`^Hv*+}0kUfCrz~BCOViSb$_*&;{TGGn2^x9K*!Sf0=lV zpP=7O;GA0*Jm*tTYj$IoXvimpnV4S1Z5f$p*f$Db2iq2zrVGQUz~yq`ahn7ck(|CE z7Gz;%OP~J6)tEZWDzjhL9h2hdfoU2)Nd%T<5Kt;Y0XLt&<@6pQx!nw*5`@bq#?l*?3z{Hlzoc=Pr>oB5(9i6~_&-}A(4{Q$>c>%rV&E|a(r&;?i5cQB=} zYSDU5nXG)NS4HEs0it2AHe2>shCyr7`6@4*6{r@8fXRbTA?=IFVWAQJL&H5H{)DpM#{W(GL+Idzf^)uRV@oB8u$ z8v{MfJbTiiRg4bza<41NAzrl{=3fl_D+$t+^!xlQ8S}{UtY`e z;;&9UhyZqQRN%2pot{*Ei0*4~hSF_3AH2@fKU!$NSflS>{@tZpDT4`M2WRTTVH+D? z)GFlEGGHe?koB}i|1w45!BF}N_q&^HJ&-tyR{(afC6H7|aml|tBBbv}55C5DNP8p3 z)~jLEO4Z&2hZmP^i-e%(@d!(E|KRafiU8Q5u(wU((j8un3OR*Hvj+t diff --git a/Arduino/MAX6956/html/ftv2mlastnode.png b/Arduino/MAX6956/html/ftv2mlastnode.png deleted file mode 100644 index 0b63f6d38c4b9ec907b820192ebe9724ed6eca22..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 246 zcmVkw!R34#Lv2LOS^S2tZA31X++9RY}n zChwn@Z)Wz*WWHH{)HDtJnq&A2hk$b-y(>?@z0iHr41EKCGp#T5?07*qoM6N<$f(V3Pvj6}9 diff --git a/Arduino/MAX6956/html/ftv2mnode.png b/Arduino/MAX6956/html/ftv2mnode.png deleted file mode 100644 index 0b63f6d38c4b9ec907b820192ebe9724ed6eca22..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 246 zcmVkw!R34#Lv2LOS^S2tZA31X++9RY}n zChwn@Z)Wz*WWHH{)HDtJnq&A2hk$b-y(>?@z0iHr41EKCGp#T5?07*qoM6N<$f(V3Pvj6}9 diff --git a/Arduino/MAX6956/html/ftv2mo.png b/Arduino/MAX6956/html/ftv2mo.png deleted file mode 100644 index 4bfb80f76e65815989a9350ad79d8ce45380e2b1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 403 zcmV;E0c`$>P)${!fXv7NWJ%@%u4(KapRY>T6_x;E zxE7kt!}Tiw8@d9Sd`rTGum>z#Q14vIm`wm1#-byD1muMi02@YNO5LRF0o!Y{`a!Ya z{^&p0Su|s705&2QxmqdexG+-zNKL3f@8gTQSJrKByfo+oNJ^-{|Mn||Q5SDwjQVsS zr1}7o5-QMs>gYIMD>GRw@$lT`z4r-_m{5U#cR{urD_)TOeY)(UD|qZ^&y`IVijqk~ xs(9-kWFr7E^!lgi8GsFK5kOY_{Xbgf0^etEU%fLevs?fG002ovPDHLkV1nB&vX1}& diff --git a/Arduino/MAX6956/html/ftv2node.png b/Arduino/MAX6956/html/ftv2node.png deleted file mode 100644 index 63c605bb4c3d941c921a4b6cfa74951e946bcb48..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 86 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRr!3HExu9B$%QnH>djv*C{Z|`mdau^P8_z}#X h?B8GEpdi4(BFDx$je&7RrDQEg&ePS;Wt~$(69Dh@6T1Ka diff --git a/Arduino/MAX6956/html/ftv2ns.png b/Arduino/MAX6956/html/ftv2ns.png deleted file mode 100644 index 72e3d71c2892d6f00e259facebc88b45f6db2e35..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 388 zcmV-~0ek+5P)f+++#cT|!CkD&4pnIkeMEUEM*>`*9>+Juji$!h-mW%M^8s9957{3nvbrz^&=u<~TAUrFROkmt%^F~Ez+-c53Lv%iH3d38!Rv?K zrb&MYAhp;Gf<}wS;9ZZq2@;!uYG;=Z>~GKE^{HD4keu}lnyqhc>kWX^tQn|warJ~h zT+rtMkdz6aHoN%z(o|&wpu@@OpJnF_z{PA)6(FHw02iHslz^(N{4*+K9)QJHR87wT iTyp>aXaF{u2lxRou|^4tux6eB0000^P)R?RzRoKvklcaQ%HF6%rK2&ZgO(-ihJ_C zzrKgp4jgO( fd_(yg|3PpEQb#9`a?Pz_00000NkvXXu0mjftR`5K diff --git a/Arduino/MAX6956/html/ftv2pnode.png b/Arduino/MAX6956/html/ftv2pnode.png deleted file mode 100644 index c6ee22f937a07d1dbfc27c669d11f8ed13e2f152..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 229 zcmV^P)R?RzRoKvklcaQ%HF6%rK2&ZgO(-ihJ_C zzrKgp4jgO( fd_(yg|3PpEQb#9`a?Pz_00000NkvXXu0mjftR`5K diff --git a/Arduino/MAX6956/html/ftv2splitbar.png b/Arduino/MAX6956/html/ftv2splitbar.png deleted file mode 100644 index fe895f2c58179b471a22d8320b39a4bd7312ec8e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 314 zcmeAS@N?(olHy`uVBq!ia0vp^Yzz!63>-{AmhX=Jf(#6djGiuzAr*{o?=JLmPLyc> z_*`QK&+BH@jWrYJ7>r6%keRM@)Qyv8R=enp0jiI>aWlGyB58O zFVR20d+y`K7vDw(hJF3;>dD*3-?v=<8M)@x|EEGLnJsniYK!2U1 Y!`|5biEc?d1`HDhPgg&ebxsLQ02F6;9RL6T diff --git a/Arduino/MAX6956/html/ftv2vertline.png b/Arduino/MAX6956/html/ftv2vertline.png deleted file mode 100644 index 63c605bb4c3d941c921a4b6cfa74951e946bcb48..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 86 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRr!3HExu9B$%QnH>djv*C{Z|`mdau^P8_z}#X h?B8GEpdi4(BFDx$je&7RrDQEg&ePS;Wt~$(69Dh@6T1Ka diff --git a/Arduino/MAX6956/html/functions.html b/Arduino/MAX6956/html/functions.html deleted file mode 100644 index daef3340..00000000 --- a/Arduino/MAX6956/html/functions.html +++ /dev/null @@ -1,266 +0,0 @@ - - - - - - -MAX6956: Data Fields - - - - - - - - - -
-
- - - - - - -
-
MAX6956 -  1.0 -
-
MAX6956i2Clibrary
-
-
- - - - - - - -
- - - - -
- -
- -
-
Here is a list of all struct and union fields with links to the structures/unions they belong to:
- -

- b -

- - -

- c -

- - -

- d -

- - -

- e -

- - -

- g -

- - -

- i -

- - -

- m -

- - -

- p -

- - -

- r -

- - -

- s -

- - -

- t -

-
- - - - diff --git a/Arduino/MAX6956/html/functions_func.html b/Arduino/MAX6956/html/functions_func.html deleted file mode 100644 index bc5c6198..00000000 --- a/Arduino/MAX6956/html/functions_func.html +++ /dev/null @@ -1,182 +0,0 @@ - - - - - - -MAX6956: Data Fields - Functions - - - - - - - - - -
-
- - - - - - -
-
MAX6956 -  1.0 -
-
MAX6956i2Clibrary
-
-
- - - - - - -
- - - - -
- -
- -
-
- - - - diff --git a/Arduino/MAX6956/html/functions_vars.html b/Arduino/MAX6956/html/functions_vars.html deleted file mode 100644 index 124d87d7..00000000 --- a/Arduino/MAX6956/html/functions_vars.html +++ /dev/null @@ -1,128 +0,0 @@ - - - - - - -MAX6956: Data Fields - Variables - - - - - - - - - -
-
- - - - - - -
-
MAX6956 -  1.0 -
-
MAX6956i2Clibrary
-
-
- - - - - - -
- - - - -
- -
- -
-
- - - - diff --git a/Arduino/MAX6956/html/globals.html b/Arduino/MAX6956/html/globals.html deleted file mode 100644 index 016fc9d2..00000000 --- a/Arduino/MAX6956/html/globals.html +++ /dev/null @@ -1,611 +0,0 @@ - - - - - - -MAX6956: Globals - - - - - - - - - -
-
- - - - - - -
-
MAX6956 -  1.0 -
-
MAX6956i2Clibrary
-
-
- - - - - - - -
- - - - -
- -
- -
-
Here is a list of all functions, variables, defines, enums, and typedefs with links to the files they belong to:
- -

- m -

-
- - - - diff --git a/Arduino/MAX6956/html/globals_defs.html b/Arduino/MAX6956/html/globals_defs.html deleted file mode 100644 index b98fc9ed..00000000 --- a/Arduino/MAX6956/html/globals_defs.html +++ /dev/null @@ -1,611 +0,0 @@ - - - - - - -MAX6956: Globals - - - - - - - - - -
-
- - - - - - -
-
MAX6956 -  1.0 -
-
MAX6956i2Clibrary
-
-
- - - - - - - -
- - - - -
- -
- -
-  - -

- m -

-
- - - - diff --git a/Arduino/MAX6956/html/index.html b/Arduino/MAX6956/html/index.html deleted file mode 100644 index 11992c78..00000000 --- a/Arduino/MAX6956/html/index.html +++ /dev/null @@ -1,90 +0,0 @@ - - - - - - -MAX6956: Main Page - - - - - - - - - -
-
- - - - - - -
-
MAX6956 -  1.0 -
-
MAX6956i2Clibrary
-
-
- - - - -
- - - - -
- -
- -
-
-
MAX6956 Documentation
-
-
-
- - - - diff --git a/Arduino/MAX6956/html/installdox b/Arduino/MAX6956/html/installdox deleted file mode 100755 index edf5bbfe..00000000 --- a/Arduino/MAX6956/html/installdox +++ /dev/null @@ -1,112 +0,0 @@ -#!/usr/bin/perl - -%subst = ( ); -$quiet = 0; - -while ( @ARGV ) { - $_ = shift @ARGV; - if ( s/^-// ) { - if ( /^l(.*)/ ) { - $v = ($1 eq "") ? shift @ARGV : $1; - ($v =~ /\/$/) || ($v .= "/"); - $_ = $v; - if ( /(.+)\@(.+)/ ) { - if ( exists $subst{$1} ) { - $subst{$1} = $2; - } else { - print STDERR "Unknown tag file $1 given with option -l\n"; - &usage(); - } - } else { - print STDERR "Argument $_ is invalid for option -l\n"; - &usage(); - } - } - elsif ( /^q/ ) { - $quiet = 1; - } - elsif ( /^\?|^h/ ) { - &usage(); - } - else { - print STDERR "Illegal option -$_\n"; - &usage(); - } - } - else { - push (@files, $_ ); - } -} - -foreach $sub (keys %subst) -{ - if ( $subst{$sub} eq "" ) - { - print STDERR "No substitute given for tag file `$sub'\n"; - &usage(); - } - elsif ( ! $quiet && $sub ne "_doc" && $sub ne "_cgi" ) - { - print "Substituting $subst{$sub} for each occurrence of tag file $sub\n"; - } -} - -if ( ! @files ) { - if (opendir(D,".")) { - foreach $file ( readdir(D) ) { - $match = ".html"; - next if ( $file =~ /^\.\.?$/ ); - ($file =~ /$match/) && (push @files, $file); - ($file =~ /\.svg/) && (push @files, $file); - ($file =~ "navtree.js") && (push @files, $file); - } - closedir(D); - } -} - -if ( ! @files ) { - print STDERR "Warning: No input files given and none found!\n"; -} - -foreach $f (@files) -{ - if ( ! $quiet ) { - print "Editing: $f...\n"; - } - $oldf = $f; - $f .= ".bak"; - unless (rename $oldf,$f) { - print STDERR "Error: cannot rename file $oldf\n"; - exit 1; - } - if (open(F,"<$f")) { - unless (open(G,">$oldf")) { - print STDERR "Error: opening file $oldf for writing\n"; - exit 1; - } - if ($oldf ne "tree.js") { - while () { - s/doxygen\=\"([^ \"\:\t\>\<]*)\:([^ \"\t\>\<]*)\" (xlink:href|href|src)=\"\2/doxygen\=\"$1:$subst{$1}\" \3=\"$subst{$1}/g; - print G "$_"; - } - } - else { - while () { - s/\"([^ \"\:\t\>\<]*)\:([^ \"\t\>\<]*)\", \"\2/\"$1:$subst{$1}\" ,\"$subst{$1}/g; - print G "$_"; - } - } - } - else { - print STDERR "Warning file $f does not exist\n"; - } - unlink $f; -} - -sub usage { - print STDERR "Usage: installdox [options] [html-file [html-file ...]]\n"; - print STDERR "Options:\n"; - print STDERR " -l tagfile\@linkName tag file + URL or directory \n"; - print STDERR " -q Quiet mode\n\n"; - exit 1; -} diff --git a/Arduino/MAX6956/html/jquery.js b/Arduino/MAX6956/html/jquery.js deleted file mode 100644 index 6aa2e4c2..00000000 --- a/Arduino/MAX6956/html/jquery.js +++ /dev/null @@ -1,39 +0,0 @@ -/*! - * jQuery JavaScript Library v1.7.1 - * http://jquery.com/ - * - * Copyright 2011, John Resig - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * Includes Sizzle.js - * http://sizzlejs.com/ - * Copyright 2011, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * - * Date: Mon Nov 21 21:11:03 2011 -0500 - */ -(function(bb,L){var av=bb.document,bu=bb.navigator,bl=bb.location;var b=(function(){var bF=function(b0,b1){return new bF.fn.init(b0,b1,bD)},bU=bb.jQuery,bH=bb.$,bD,bY=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,bM=/\S/,bI=/^\s+/,bE=/\s+$/,bA=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,bN=/^[\],:{}\s]*$/,bW=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,bP=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,bJ=/(?:^|:|,)(?:\s*\[)+/g,by=/(webkit)[ \/]([\w.]+)/,bR=/(opera)(?:.*version)?[ \/]([\w.]+)/,bQ=/(msie) ([\w.]+)/,bS=/(mozilla)(?:.*? rv:([\w.]+))?/,bB=/-([a-z]|[0-9])/ig,bZ=/^-ms-/,bT=function(b0,b1){return(b1+"").toUpperCase()},bX=bu.userAgent,bV,bC,e,bL=Object.prototype.toString,bG=Object.prototype.hasOwnProperty,bz=Array.prototype.push,bK=Array.prototype.slice,bO=String.prototype.trim,bv=Array.prototype.indexOf,bx={};bF.fn=bF.prototype={constructor:bF,init:function(b0,b4,b3){var b2,b5,b1,b6;if(!b0){return this}if(b0.nodeType){this.context=this[0]=b0;this.length=1;return this}if(b0==="body"&&!b4&&av.body){this.context=av;this[0]=av.body;this.selector=b0;this.length=1;return this}if(typeof b0==="string"){if(b0.charAt(0)==="<"&&b0.charAt(b0.length-1)===">"&&b0.length>=3){b2=[null,b0,null]}else{b2=bY.exec(b0)}if(b2&&(b2[1]||!b4)){if(b2[1]){b4=b4 instanceof bF?b4[0]:b4;b6=(b4?b4.ownerDocument||b4:av);b1=bA.exec(b0);if(b1){if(bF.isPlainObject(b4)){b0=[av.createElement(b1[1])];bF.fn.attr.call(b0,b4,true)}else{b0=[b6.createElement(b1[1])]}}else{b1=bF.buildFragment([b2[1]],[b6]);b0=(b1.cacheable?bF.clone(b1.fragment):b1.fragment).childNodes}return bF.merge(this,b0)}else{b5=av.getElementById(b2[2]);if(b5&&b5.parentNode){if(b5.id!==b2[2]){return b3.find(b0)}this.length=1;this[0]=b5}this.context=av;this.selector=b0;return this}}else{if(!b4||b4.jquery){return(b4||b3).find(b0)}else{return this.constructor(b4).find(b0)}}}else{if(bF.isFunction(b0)){return b3.ready(b0)}}if(b0.selector!==L){this.selector=b0.selector;this.context=b0.context}return bF.makeArray(b0,this)},selector:"",jquery:"1.7.1",length:0,size:function(){return this.length},toArray:function(){return bK.call(this,0)},get:function(b0){return b0==null?this.toArray():(b0<0?this[this.length+b0]:this[b0])},pushStack:function(b1,b3,b0){var b2=this.constructor();if(bF.isArray(b1)){bz.apply(b2,b1)}else{bF.merge(b2,b1)}b2.prevObject=this;b2.context=this.context;if(b3==="find"){b2.selector=this.selector+(this.selector?" ":"")+b0}else{if(b3){b2.selector=this.selector+"."+b3+"("+b0+")"}}return b2},each:function(b1,b0){return bF.each(this,b1,b0)},ready:function(b0){bF.bindReady();bC.add(b0);return this},eq:function(b0){b0=+b0;return b0===-1?this.slice(b0):this.slice(b0,b0+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(bK.apply(this,arguments),"slice",bK.call(arguments).join(","))},map:function(b0){return this.pushStack(bF.map(this,function(b2,b1){return b0.call(b2,b1,b2)}))},end:function(){return this.prevObject||this.constructor(null)},push:bz,sort:[].sort,splice:[].splice};bF.fn.init.prototype=bF.fn;bF.extend=bF.fn.extend=function(){var b9,b2,b0,b1,b6,b7,b5=arguments[0]||{},b4=1,b3=arguments.length,b8=false;if(typeof b5==="boolean"){b8=b5;b5=arguments[1]||{};b4=2}if(typeof b5!=="object"&&!bF.isFunction(b5)){b5={}}if(b3===b4){b5=this;--b4}for(;b40){return}bC.fireWith(av,[bF]);if(bF.fn.trigger){bF(av).trigger("ready").off("ready")}}},bindReady:function(){if(bC){return}bC=bF.Callbacks("once memory");if(av.readyState==="complete"){return setTimeout(bF.ready,1)}if(av.addEventListener){av.addEventListener("DOMContentLoaded",e,false);bb.addEventListener("load",bF.ready,false)}else{if(av.attachEvent){av.attachEvent("onreadystatechange",e);bb.attachEvent("onload",bF.ready);var b0=false;try{b0=bb.frameElement==null}catch(b1){}if(av.documentElement.doScroll&&b0){bw()}}}},isFunction:function(b0){return bF.type(b0)==="function"},isArray:Array.isArray||function(b0){return bF.type(b0)==="array"},isWindow:function(b0){return b0&&typeof b0==="object"&&"setInterval" in b0},isNumeric:function(b0){return !isNaN(parseFloat(b0))&&isFinite(b0)},type:function(b0){return b0==null?String(b0):bx[bL.call(b0)]||"object"},isPlainObject:function(b2){if(!b2||bF.type(b2)!=="object"||b2.nodeType||bF.isWindow(b2)){return false}try{if(b2.constructor&&!bG.call(b2,"constructor")&&!bG.call(b2.constructor.prototype,"isPrototypeOf")){return false}}catch(b1){return false}var b0;for(b0 in b2){}return b0===L||bG.call(b2,b0)},isEmptyObject:function(b1){for(var b0 in b1){return false}return true},error:function(b0){throw new Error(b0)},parseJSON:function(b0){if(typeof b0!=="string"||!b0){return null}b0=bF.trim(b0);if(bb.JSON&&bb.JSON.parse){return bb.JSON.parse(b0)}if(bN.test(b0.replace(bW,"@").replace(bP,"]").replace(bJ,""))){return(new Function("return "+b0))()}bF.error("Invalid JSON: "+b0)},parseXML:function(b2){var b0,b1;try{if(bb.DOMParser){b1=new DOMParser();b0=b1.parseFromString(b2,"text/xml")}else{b0=new ActiveXObject("Microsoft.XMLDOM");b0.async="false";b0.loadXML(b2)}}catch(b3){b0=L}if(!b0||!b0.documentElement||b0.getElementsByTagName("parsererror").length){bF.error("Invalid XML: "+b2)}return b0},noop:function(){},globalEval:function(b0){if(b0&&bM.test(b0)){(bb.execScript||function(b1){bb["eval"].call(bb,b1)})(b0)}},camelCase:function(b0){return b0.replace(bZ,"ms-").replace(bB,bT)},nodeName:function(b1,b0){return b1.nodeName&&b1.nodeName.toUpperCase()===b0.toUpperCase()},each:function(b3,b6,b2){var b1,b4=0,b5=b3.length,b0=b5===L||bF.isFunction(b3);if(b2){if(b0){for(b1 in b3){if(b6.apply(b3[b1],b2)===false){break}}}else{for(;b40&&b0[0]&&b0[b1-1])||b1===0||bF.isArray(b0));if(b3){for(;b21?aJ.call(arguments,0):bG;if(!(--bw)){bC.resolveWith(bC,bx)}}}function bz(bF){return function(bG){bB[bF]=arguments.length>1?aJ.call(arguments,0):bG;bC.notifyWith(bE,bB)}}if(e>1){for(;bv
a";bI=bv.getElementsByTagName("*");bF=bv.getElementsByTagName("a")[0];if(!bI||!bI.length||!bF){return{}}bG=av.createElement("select");bx=bG.appendChild(av.createElement("option"));bE=bv.getElementsByTagName("input")[0];bJ={leadingWhitespace:(bv.firstChild.nodeType===3),tbody:!bv.getElementsByTagName("tbody").length,htmlSerialize:!!bv.getElementsByTagName("link").length,style:/top/.test(bF.getAttribute("style")),hrefNormalized:(bF.getAttribute("href")==="/a"),opacity:/^0.55/.test(bF.style.opacity),cssFloat:!!bF.style.cssFloat,checkOn:(bE.value==="on"),optSelected:bx.selected,getSetAttribute:bv.className!=="t",enctype:!!av.createElement("form").enctype,html5Clone:av.createElement("nav").cloneNode(true).outerHTML!=="<:nav>",submitBubbles:true,changeBubbles:true,focusinBubbles:false,deleteExpando:true,noCloneEvent:true,inlineBlockNeedsLayout:false,shrinkWrapBlocks:false,reliableMarginRight:true};bE.checked=true;bJ.noCloneChecked=bE.cloneNode(true).checked;bG.disabled=true;bJ.optDisabled=!bx.disabled;try{delete bv.test}catch(bC){bJ.deleteExpando=false}if(!bv.addEventListener&&bv.attachEvent&&bv.fireEvent){bv.attachEvent("onclick",function(){bJ.noCloneEvent=false});bv.cloneNode(true).fireEvent("onclick")}bE=av.createElement("input");bE.value="t";bE.setAttribute("type","radio");bJ.radioValue=bE.value==="t";bE.setAttribute("checked","checked");bv.appendChild(bE);bD=av.createDocumentFragment();bD.appendChild(bv.lastChild);bJ.checkClone=bD.cloneNode(true).cloneNode(true).lastChild.checked;bJ.appendChecked=bE.checked;bD.removeChild(bE);bD.appendChild(bv);bv.innerHTML="";if(bb.getComputedStyle){bA=av.createElement("div");bA.style.width="0";bA.style.marginRight="0";bv.style.width="2px";bv.appendChild(bA);bJ.reliableMarginRight=(parseInt((bb.getComputedStyle(bA,null)||{marginRight:0}).marginRight,10)||0)===0}if(bv.attachEvent){for(by in {submit:1,change:1,focusin:1}){bB="on"+by;bw=(bB in bv);if(!bw){bv.setAttribute(bB,"return;");bw=(typeof bv[bB]==="function")}bJ[by+"Bubbles"]=bw}}bD.removeChild(bv);bD=bG=bx=bA=bv=bE=null;b(function(){var bM,bU,bV,bT,bN,bO,bL,bS,bR,e,bP,bQ=av.getElementsByTagName("body")[0];if(!bQ){return}bL=1;bS="position:absolute;top:0;left:0;width:1px;height:1px;margin:0;";bR="visibility:hidden;border:0;";e="style='"+bS+"border:5px solid #000;padding:0;'";bP="
";bM=av.createElement("div");bM.style.cssText=bR+"width:0;height:0;position:static;top:0;margin-top:"+bL+"px";bQ.insertBefore(bM,bQ.firstChild);bv=av.createElement("div");bM.appendChild(bv);bv.innerHTML="
t
";bz=bv.getElementsByTagName("td");bw=(bz[0].offsetHeight===0);bz[0].style.display="";bz[1].style.display="none";bJ.reliableHiddenOffsets=bw&&(bz[0].offsetHeight===0);bv.innerHTML="";bv.style.width=bv.style.paddingLeft="1px";b.boxModel=bJ.boxModel=bv.offsetWidth===2;if(typeof bv.style.zoom!=="undefined"){bv.style.display="inline";bv.style.zoom=1;bJ.inlineBlockNeedsLayout=(bv.offsetWidth===2);bv.style.display="";bv.innerHTML="
";bJ.shrinkWrapBlocks=(bv.offsetWidth!==2)}bv.style.cssText=bS+bR;bv.innerHTML=bP;bU=bv.firstChild;bV=bU.firstChild;bN=bU.nextSibling.firstChild.firstChild;bO={doesNotAddBorder:(bV.offsetTop!==5),doesAddBorderForTableAndCells:(bN.offsetTop===5)};bV.style.position="fixed";bV.style.top="20px";bO.fixedPosition=(bV.offsetTop===20||bV.offsetTop===15);bV.style.position=bV.style.top="";bU.style.overflow="hidden";bU.style.position="relative";bO.subtractsBorderForOverflowNotVisible=(bV.offsetTop===-5);bO.doesNotIncludeMarginInBodyOffset=(bQ.offsetTop!==bL);bQ.removeChild(bM);bv=bM=null;b.extend(bJ,bO)});return bJ})();var aS=/^(?:\{.*\}|\[.*\])$/,aA=/([A-Z])/g;b.extend({cache:{},uuid:0,expando:"jQuery"+(b.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:true,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:true},hasData:function(e){e=e.nodeType?b.cache[e[b.expando]]:e[b.expando];return !!e&&!S(e)},data:function(bx,bv,bz,by){if(!b.acceptData(bx)){return}var bG,bA,bD,bE=b.expando,bC=typeof bv==="string",bF=bx.nodeType,e=bF?b.cache:bx,bw=bF?bx[bE]:bx[bE]&&bE,bB=bv==="events";if((!bw||!e[bw]||(!bB&&!by&&!e[bw].data))&&bC&&bz===L){return}if(!bw){if(bF){bx[bE]=bw=++b.uuid}else{bw=bE}}if(!e[bw]){e[bw]={};if(!bF){e[bw].toJSON=b.noop}}if(typeof bv==="object"||typeof bv==="function"){if(by){e[bw]=b.extend(e[bw],bv)}else{e[bw].data=b.extend(e[bw].data,bv)}}bG=bA=e[bw];if(!by){if(!bA.data){bA.data={}}bA=bA.data}if(bz!==L){bA[b.camelCase(bv)]=bz}if(bB&&!bA[bv]){return bG.events}if(bC){bD=bA[bv];if(bD==null){bD=bA[b.camelCase(bv)]}}else{bD=bA}return bD},removeData:function(bx,bv,by){if(!b.acceptData(bx)){return}var bB,bA,bz,bC=b.expando,bD=bx.nodeType,e=bD?b.cache:bx,bw=bD?bx[bC]:bC;if(!e[bw]){return}if(bv){bB=by?e[bw]:e[bw].data;if(bB){if(!b.isArray(bv)){if(bv in bB){bv=[bv]}else{bv=b.camelCase(bv);if(bv in bB){bv=[bv]}else{bv=bv.split(" ")}}}for(bA=0,bz=bv.length;bA-1){return true}}return false},val:function(bx){var e,bv,by,bw=this[0];if(!arguments.length){if(bw){e=b.valHooks[bw.nodeName.toLowerCase()]||b.valHooks[bw.type];if(e&&"get" in e&&(bv=e.get(bw,"value"))!==L){return bv}bv=bw.value;return typeof bv==="string"?bv.replace(aU,""):bv==null?"":bv}return}by=b.isFunction(bx);return this.each(function(bA){var bz=b(this),bB;if(this.nodeType!==1){return}if(by){bB=bx.call(this,bA,bz.val())}else{bB=bx}if(bB==null){bB=""}else{if(typeof bB==="number"){bB+=""}else{if(b.isArray(bB)){bB=b.map(bB,function(bC){return bC==null?"":bC+""})}}}e=b.valHooks[this.nodeName.toLowerCase()]||b.valHooks[this.type];if(!e||!("set" in e)||e.set(this,bB,"value")===L){this.value=bB}})}});b.extend({valHooks:{option:{get:function(e){var bv=e.attributes.value;return !bv||bv.specified?e.value:e.text}},select:{get:function(e){var bA,bv,bz,bx,by=e.selectedIndex,bB=[],bC=e.options,bw=e.type==="select-one";if(by<0){return null}bv=bw?by:0;bz=bw?by+1:bC.length;for(;bv=0});if(!e.length){bv.selectedIndex=-1}return e}}},attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(bA,bx,bB,bz){var bw,e,by,bv=bA.nodeType; -if(!bA||bv===3||bv===8||bv===2){return}if(bz&&bx in b.attrFn){return b(bA)[bx](bB)}if(typeof bA.getAttribute==="undefined"){return b.prop(bA,bx,bB)}by=bv!==1||!b.isXMLDoc(bA);if(by){bx=bx.toLowerCase();e=b.attrHooks[bx]||(ao.test(bx)?aY:be)}if(bB!==L){if(bB===null){b.removeAttr(bA,bx);return}else{if(e&&"set" in e&&by&&(bw=e.set(bA,bB,bx))!==L){return bw}else{bA.setAttribute(bx,""+bB);return bB}}}else{if(e&&"get" in e&&by&&(bw=e.get(bA,bx))!==null){return bw}else{bw=bA.getAttribute(bx);return bw===null?L:bw}}},removeAttr:function(bx,bz){var by,bA,bv,e,bw=0;if(bz&&bx.nodeType===1){bA=bz.toLowerCase().split(af);e=bA.length;for(;bw=0)}}})});var bd=/^(?:textarea|input|select)$/i,n=/^([^\.]*)?(?:\.(.+))?$/,J=/\bhover(\.\S+)?\b/,aO=/^key/,bf=/^(?:mouse|contextmenu)|click/,T=/^(?:focusinfocus|focusoutblur)$/,U=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,Y=function(e){var bv=U.exec(e);if(bv){bv[1]=(bv[1]||"").toLowerCase();bv[3]=bv[3]&&new RegExp("(?:^|\\s)"+bv[3]+"(?:\\s|$)")}return bv},j=function(bw,e){var bv=bw.attributes||{};return((!e[1]||bw.nodeName.toLowerCase()===e[1])&&(!e[2]||(bv.id||{}).value===e[2])&&(!e[3]||e[3].test((bv["class"]||{}).value)))},bt=function(e){return b.event.special.hover?e:e.replace(J,"mouseenter$1 mouseleave$1")};b.event={add:function(bx,bC,bJ,bA,by){var bD,bB,bK,bI,bH,bF,e,bG,bv,bz,bw,bE;if(bx.nodeType===3||bx.nodeType===8||!bC||!bJ||!(bD=b._data(bx))){return}if(bJ.handler){bv=bJ;bJ=bv.handler}if(!bJ.guid){bJ.guid=b.guid++}bK=bD.events;if(!bK){bD.events=bK={}}bB=bD.handle;if(!bB){bD.handle=bB=function(bL){return typeof b!=="undefined"&&(!bL||b.event.triggered!==bL.type)?b.event.dispatch.apply(bB.elem,arguments):L};bB.elem=bx}bC=b.trim(bt(bC)).split(" ");for(bI=0;bI=0){bG=bG.slice(0,-1);bw=true}if(bG.indexOf(".")>=0){bx=bG.split(".");bG=bx.shift();bx.sort()}if((!bA||b.event.customEvent[bG])&&!b.event.global[bG]){return}bv=typeof bv==="object"?bv[b.expando]?bv:new b.Event(bG,bv):new b.Event(bG);bv.type=bG;bv.isTrigger=true;bv.exclusive=bw;bv.namespace=bx.join(".");bv.namespace_re=bv.namespace?new RegExp("(^|\\.)"+bx.join("\\.(?:.*\\.)?")+"(\\.|$)"):null;by=bG.indexOf(":")<0?"on"+bG:"";if(!bA){e=b.cache;for(bC in e){if(e[bC].events&&e[bC].events[bG]){b.event.trigger(bv,bD,e[bC].handle.elem,true)}}return}bv.result=L;if(!bv.target){bv.target=bA}bD=bD!=null?b.makeArray(bD):[];bD.unshift(bv);bF=b.event.special[bG]||{};if(bF.trigger&&bF.trigger.apply(bA,bD)===false){return}bB=[[bA,bF.bindType||bG]];if(!bJ&&!bF.noBubble&&!b.isWindow(bA)){bI=bF.delegateType||bG;bH=T.test(bI+bG)?bA:bA.parentNode;bz=null;for(;bH;bH=bH.parentNode){bB.push([bH,bI]);bz=bH}if(bz&&bz===bA.ownerDocument){bB.push([bz.defaultView||bz.parentWindow||bb,bI])}}for(bC=0;bCbA){bH.push({elem:this,matches:bz.slice(bA)})}for(bC=0;bC0?this.on(e,null,bx,bw):this.trigger(e)};if(b.attrFn){b.attrFn[e]=true}if(aO.test(e)){b.event.fixHooks[e]=b.event.keyHooks}if(bf.test(e)){b.event.fixHooks[e]=b.event.mouseHooks}}); -/*! - * Sizzle CSS Selector Engine - * Copyright 2011, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * More information: http://sizzlejs.com/ - */ -(function(){var bH=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,bC="sizcache"+(Math.random()+"").replace(".",""),bI=0,bL=Object.prototype.toString,bB=false,bA=true,bK=/\\/g,bO=/\r\n/g,bQ=/\W/;[0,0].sort(function(){bA=false;return 0});var by=function(bV,e,bY,bZ){bY=bY||[];e=e||av;var b1=e;if(e.nodeType!==1&&e.nodeType!==9){return[]}if(!bV||typeof bV!=="string"){return bY}var bS,b3,b6,bR,b2,b5,b4,bX,bU=true,bT=by.isXML(e),bW=[],b0=bV;do{bH.exec("");bS=bH.exec(b0);if(bS){b0=bS[3];bW.push(bS[1]);if(bS[2]){bR=bS[3];break}}}while(bS);if(bW.length>1&&bD.exec(bV)){if(bW.length===2&&bE.relative[bW[0]]){b3=bM(bW[0]+bW[1],e,bZ)}else{b3=bE.relative[bW[0]]?[e]:by(bW.shift(),e);while(bW.length){bV=bW.shift();if(bE.relative[bV]){bV+=bW.shift()}b3=bM(bV,b3,bZ)}}}else{if(!bZ&&bW.length>1&&e.nodeType===9&&!bT&&bE.match.ID.test(bW[0])&&!bE.match.ID.test(bW[bW.length-1])){b2=by.find(bW.shift(),e,bT);e=b2.expr?by.filter(b2.expr,b2.set)[0]:b2.set[0]}if(e){b2=bZ?{expr:bW.pop(),set:bF(bZ)}:by.find(bW.pop(),bW.length===1&&(bW[0]==="~"||bW[0]==="+")&&e.parentNode?e.parentNode:e,bT);b3=b2.expr?by.filter(b2.expr,b2.set):b2.set;if(bW.length>0){b6=bF(b3)}else{bU=false}while(bW.length){b5=bW.pop();b4=b5;if(!bE.relative[b5]){b5=""}else{b4=bW.pop()}if(b4==null){b4=e}bE.relative[b5](b6,b4,bT)}}else{b6=bW=[]}}if(!b6){b6=b3}if(!b6){by.error(b5||bV)}if(bL.call(b6)==="[object Array]"){if(!bU){bY.push.apply(bY,b6)}else{if(e&&e.nodeType===1){for(bX=0;b6[bX]!=null;bX++){if(b6[bX]&&(b6[bX]===true||b6[bX].nodeType===1&&by.contains(e,b6[bX]))){bY.push(b3[bX])}}}else{for(bX=0;b6[bX]!=null;bX++){if(b6[bX]&&b6[bX].nodeType===1){bY.push(b3[bX])}}}}}else{bF(b6,bY)}if(bR){by(bR,b1,bY,bZ);by.uniqueSort(bY)}return bY};by.uniqueSort=function(bR){if(bJ){bB=bA;bR.sort(bJ);if(bB){for(var e=1;e0};by.find=function(bX,e,bY){var bW,bS,bU,bT,bV,bR;if(!bX){return[]}for(bS=0,bU=bE.order.length;bS":function(bW,bR){var bV,bU=typeof bR==="string",bS=0,e=bW.length;if(bU&&!bQ.test(bR)){bR=bR.toLowerCase();for(;bS=0)){if(!bS){e.push(bV)}}else{if(bS){bR[bU]=false}}}}return false},ID:function(e){return e[1].replace(bK,"")},TAG:function(bR,e){return bR[1].replace(bK,"").toLowerCase()},CHILD:function(e){if(e[1]==="nth"){if(!e[2]){by.error(e[0])}e[2]=e[2].replace(/^\+|\s*/g,"");var bR=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(e[2]==="even"&&"2n"||e[2]==="odd"&&"2n+1"||!/\D/.test(e[2])&&"0n+"+e[2]||e[2]);e[2]=(bR[1]+(bR[2]||1))-0;e[3]=bR[3]-0}else{if(e[2]){by.error(e[0])}}e[0]=bI++;return e},ATTR:function(bU,bR,bS,e,bV,bW){var bT=bU[1]=bU[1].replace(bK,"");if(!bW&&bE.attrMap[bT]){bU[1]=bE.attrMap[bT]}bU[4]=(bU[4]||bU[5]||"").replace(bK,"");if(bU[2]==="~="){bU[4]=" "+bU[4]+" "}return bU},PSEUDO:function(bU,bR,bS,e,bV){if(bU[1]==="not"){if((bH.exec(bU[3])||"").length>1||/^\w/.test(bU[3])){bU[3]=by(bU[3],null,null,bR)}else{var bT=by.filter(bU[3],bR,bS,true^bV);if(!bS){e.push.apply(e,bT)}return false}}else{if(bE.match.POS.test(bU[0])||bE.match.CHILD.test(bU[0])){return true}}return bU},POS:function(e){e.unshift(true);return e}},filters:{enabled:function(e){return e.disabled===false&&e.type!=="hidden"},disabled:function(e){return e.disabled===true},checked:function(e){return e.checked===true},selected:function(e){if(e.parentNode){e.parentNode.selectedIndex}return e.selected===true},parent:function(e){return !!e.firstChild},empty:function(e){return !e.firstChild},has:function(bS,bR,e){return !!by(e[3],bS).length},header:function(e){return(/h\d/i).test(e.nodeName)},text:function(bS){var e=bS.getAttribute("type"),bR=bS.type;return bS.nodeName.toLowerCase()==="input"&&"text"===bR&&(e===bR||e===null)},radio:function(e){return e.nodeName.toLowerCase()==="input"&&"radio"===e.type},checkbox:function(e){return e.nodeName.toLowerCase()==="input"&&"checkbox"===e.type},file:function(e){return e.nodeName.toLowerCase()==="input"&&"file"===e.type},password:function(e){return e.nodeName.toLowerCase()==="input"&&"password"===e.type},submit:function(bR){var e=bR.nodeName.toLowerCase();return(e==="input"||e==="button")&&"submit"===bR.type},image:function(e){return e.nodeName.toLowerCase()==="input"&&"image"===e.type},reset:function(bR){var e=bR.nodeName.toLowerCase();return(e==="input"||e==="button")&&"reset"===bR.type},button:function(bR){var e=bR.nodeName.toLowerCase();return e==="input"&&"button"===bR.type||e==="button"},input:function(e){return(/input|select|textarea|button/i).test(e.nodeName)},focus:function(e){return e===e.ownerDocument.activeElement}},setFilters:{first:function(bR,e){return e===0},last:function(bS,bR,e,bT){return bR===bT.length-1},even:function(bR,e){return e%2===0},odd:function(bR,e){return e%2===1 -},lt:function(bS,bR,e){return bRe[3]-0},nth:function(bS,bR,e){return e[3]-0===bR},eq:function(bS,bR,e){return e[3]-0===bR}},filter:{PSEUDO:function(bS,bX,bW,bY){var e=bX[1],bR=bE.filters[e];if(bR){return bR(bS,bW,bX,bY)}else{if(e==="contains"){return(bS.textContent||bS.innerText||bw([bS])||"").indexOf(bX[3])>=0}else{if(e==="not"){var bT=bX[3];for(var bV=0,bU=bT.length;bV=0)}}},ID:function(bR,e){return bR.nodeType===1&&bR.getAttribute("id")===e},TAG:function(bR,e){return(e==="*"&&bR.nodeType===1)||!!bR.nodeName&&bR.nodeName.toLowerCase()===e},CLASS:function(bR,e){return(" "+(bR.className||bR.getAttribute("class"))+" ").indexOf(e)>-1},ATTR:function(bV,bT){var bS=bT[1],e=by.attr?by.attr(bV,bS):bE.attrHandle[bS]?bE.attrHandle[bS](bV):bV[bS]!=null?bV[bS]:bV.getAttribute(bS),bW=e+"",bU=bT[2],bR=bT[4];return e==null?bU==="!=":!bU&&by.attr?e!=null:bU==="="?bW===bR:bU==="*="?bW.indexOf(bR)>=0:bU==="~="?(" "+bW+" ").indexOf(bR)>=0:!bR?bW&&e!==false:bU==="!="?bW!==bR:bU==="^="?bW.indexOf(bR)===0:bU==="$="?bW.substr(bW.length-bR.length)===bR:bU==="|="?bW===bR||bW.substr(0,bR.length+1)===bR+"-":false},POS:function(bU,bR,bS,bV){var e=bR[2],bT=bE.setFilters[e];if(bT){return bT(bU,bS,bR,bV)}}}};var bD=bE.match.POS,bx=function(bR,e){return"\\"+(e-0+1)};for(var bz in bE.match){bE.match[bz]=new RegExp(bE.match[bz].source+(/(?![^\[]*\])(?![^\(]*\))/.source));bE.leftMatch[bz]=new RegExp(/(^(?:.|\r|\n)*?)/.source+bE.match[bz].source.replace(/\\(\d+)/g,bx))}var bF=function(bR,e){bR=Array.prototype.slice.call(bR,0);if(e){e.push.apply(e,bR);return e}return bR};try{Array.prototype.slice.call(av.documentElement.childNodes,0)[0].nodeType}catch(bP){bF=function(bU,bT){var bS=0,bR=bT||[];if(bL.call(bU)==="[object Array]"){Array.prototype.push.apply(bR,bU)}else{if(typeof bU.length==="number"){for(var e=bU.length;bS";e.insertBefore(bR,e.firstChild);if(av.getElementById(bS)){bE.find.ID=function(bU,bV,bW){if(typeof bV.getElementById!=="undefined"&&!bW){var bT=bV.getElementById(bU[1]);return bT?bT.id===bU[1]||typeof bT.getAttributeNode!=="undefined"&&bT.getAttributeNode("id").nodeValue===bU[1]?[bT]:L:[]}};bE.filter.ID=function(bV,bT){var bU=typeof bV.getAttributeNode!=="undefined"&&bV.getAttributeNode("id");return bV.nodeType===1&&bU&&bU.nodeValue===bT}}e.removeChild(bR);e=bR=null})();(function(){var e=av.createElement("div");e.appendChild(av.createComment(""));if(e.getElementsByTagName("*").length>0){bE.find.TAG=function(bR,bV){var bU=bV.getElementsByTagName(bR[1]);if(bR[1]==="*"){var bT=[];for(var bS=0;bU[bS];bS++){if(bU[bS].nodeType===1){bT.push(bU[bS])}}bU=bT}return bU}}e.innerHTML="";if(e.firstChild&&typeof e.firstChild.getAttribute!=="undefined"&&e.firstChild.getAttribute("href")!=="#"){bE.attrHandle.href=function(bR){return bR.getAttribute("href",2)}}e=null})();if(av.querySelectorAll){(function(){var e=by,bT=av.createElement("div"),bS="__sizzle__";bT.innerHTML="

";if(bT.querySelectorAll&&bT.querySelectorAll(".TEST").length===0){return}by=function(b4,bV,bZ,b3){bV=bV||av;if(!b3&&!by.isXML(bV)){var b2=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b4);if(b2&&(bV.nodeType===1||bV.nodeType===9)){if(b2[1]){return bF(bV.getElementsByTagName(b4),bZ)}else{if(b2[2]&&bE.find.CLASS&&bV.getElementsByClassName){return bF(bV.getElementsByClassName(b2[2]),bZ)}}}if(bV.nodeType===9){if(b4==="body"&&bV.body){return bF([bV.body],bZ)}else{if(b2&&b2[3]){var bY=bV.getElementById(b2[3]);if(bY&&bY.parentNode){if(bY.id===b2[3]){return bF([bY],bZ)}}else{return bF([],bZ)}}}try{return bF(bV.querySelectorAll(b4),bZ)}catch(b0){}}else{if(bV.nodeType===1&&bV.nodeName.toLowerCase()!=="object"){var bW=bV,bX=bV.getAttribute("id"),bU=bX||bS,b6=bV.parentNode,b5=/^\s*[+~]/.test(b4);if(!bX){bV.setAttribute("id",bU)}else{bU=bU.replace(/'/g,"\\$&")}if(b5&&b6){bV=bV.parentNode}try{if(!b5||b6){return bF(bV.querySelectorAll("[id='"+bU+"'] "+b4),bZ)}}catch(b1){}finally{if(!bX){bW.removeAttribute("id")}}}}}return e(b4,bV,bZ,b3)};for(var bR in e){by[bR]=e[bR]}bT=null})()}(function(){var e=av.documentElement,bS=e.matchesSelector||e.mozMatchesSelector||e.webkitMatchesSelector||e.msMatchesSelector;if(bS){var bU=!bS.call(av.createElement("div"),"div"),bR=false;try{bS.call(av.documentElement,"[test!='']:sizzle")}catch(bT){bR=true}by.matchesSelector=function(bW,bY){bY=bY.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!by.isXML(bW)){try{if(bR||!bE.match.PSEUDO.test(bY)&&!/!=/.test(bY)){var bV=bS.call(bW,bY);if(bV||!bU||bW.document&&bW.document.nodeType!==11){return bV}}}catch(bX){}}return by(bY,null,null,[bW]).length>0}}})();(function(){var e=av.createElement("div");e.innerHTML="
";if(!e.getElementsByClassName||e.getElementsByClassName("e").length===0){return}e.lastChild.className="e";if(e.getElementsByClassName("e").length===1){return}bE.order.splice(1,0,"CLASS");bE.find.CLASS=function(bR,bS,bT){if(typeof bS.getElementsByClassName!=="undefined"&&!bT){return bS.getElementsByClassName(bR[1])}};e=null})();function bv(bR,bW,bV,bZ,bX,bY){for(var bT=0,bS=bZ.length;bT0){bU=e;break}}}e=e[bR]}bZ[bT]=bU}}}if(av.documentElement.contains){by.contains=function(bR,e){return bR!==e&&(bR.contains?bR.contains(e):true)}}else{if(av.documentElement.compareDocumentPosition){by.contains=function(bR,e){return !!(bR.compareDocumentPosition(e)&16)}}else{by.contains=function(){return false}}}by.isXML=function(e){var bR=(e?e.ownerDocument||e:0).documentElement;return bR?bR.nodeName!=="HTML":false};var bM=function(bS,e,bW){var bV,bX=[],bU="",bY=e.nodeType?[e]:e;while((bV=bE.match.PSEUDO.exec(bS))){bU+=bV[0];bS=bS.replace(bE.match.PSEUDO,"")}bS=bE.relative[bS]?bS+"*":bS;for(var bT=0,bR=bY.length;bT0){for(bB=bA;bB=0:b.filter(e,this).length>0:this.filter(e).length>0)},closest:function(by,bx){var bv=[],bw,e,bz=this[0];if(b.isArray(by)){var bB=1;while(bz&&bz.ownerDocument&&bz!==bx){for(bw=0;bw-1:b.find.matchesSelector(bz,by)){bv.push(bz);break}else{bz=bz.parentNode;if(!bz||!bz.ownerDocument||bz===bx||bz.nodeType===11){break}}}}bv=bv.length>1?b.unique(bv):bv;return this.pushStack(bv,"closest",by)},index:function(e){if(!e){return(this[0]&&this[0].parentNode)?this.prevAll().length:-1}if(typeof e==="string"){return b.inArray(this[0],b(e))}return b.inArray(e.jquery?e[0]:e,this)},add:function(e,bv){var bx=typeof e==="string"?b(e,bv):b.makeArray(e&&e.nodeType?[e]:e),bw=b.merge(this.get(),bx);return this.pushStack(C(bx[0])||C(bw[0])?bw:b.unique(bw))},andSelf:function(){return this.add(this.prevObject)}});function C(e){return !e||!e.parentNode||e.parentNode.nodeType===11}b.each({parent:function(bv){var e=bv.parentNode;return e&&e.nodeType!==11?e:null},parents:function(e){return b.dir(e,"parentNode")},parentsUntil:function(bv,e,bw){return b.dir(bv,"parentNode",bw)},next:function(e){return b.nth(e,2,"nextSibling")},prev:function(e){return b.nth(e,2,"previousSibling")},nextAll:function(e){return b.dir(e,"nextSibling")},prevAll:function(e){return b.dir(e,"previousSibling")},nextUntil:function(bv,e,bw){return b.dir(bv,"nextSibling",bw)},prevUntil:function(bv,e,bw){return b.dir(bv,"previousSibling",bw)},siblings:function(e){return b.sibling(e.parentNode.firstChild,e)},children:function(e){return b.sibling(e.firstChild)},contents:function(e){return b.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:b.makeArray(e.childNodes)}},function(e,bv){b.fn[e]=function(by,bw){var bx=b.map(this,bv,by);if(!ab.test(e)){bw=by}if(bw&&typeof bw==="string"){bx=b.filter(bw,bx)}bx=this.length>1&&!ay[e]?b.unique(bx):bx;if((this.length>1||a9.test(bw))&&aq.test(e)){bx=bx.reverse()}return this.pushStack(bx,e,P.call(arguments).join(","))}});b.extend({filter:function(bw,e,bv){if(bv){bw=":not("+bw+")"}return e.length===1?b.find.matchesSelector(e[0],bw)?[e[0]]:[]:b.find.matches(bw,e)},dir:function(bw,bv,by){var e=[],bx=bw[bv];while(bx&&bx.nodeType!==9&&(by===L||bx.nodeType!==1||!b(bx).is(by))){if(bx.nodeType===1){e.push(bx)}bx=bx[bv]}return e},nth:function(by,e,bw,bx){e=e||1;var bv=0;for(;by;by=by[bw]){if(by.nodeType===1&&++bv===e){break}}return by},sibling:function(bw,bv){var e=[];for(;bw;bw=bw.nextSibling){if(bw.nodeType===1&&bw!==bv){e.push(bw)}}return e}});function aG(bx,bw,e){bw=bw||0;if(b.isFunction(bw)){return b.grep(bx,function(bz,by){var bA=!!bw.call(bz,by,bz);return bA===e})}else{if(bw.nodeType){return b.grep(bx,function(bz,by){return(bz===bw)===e})}else{if(typeof bw==="string"){var bv=b.grep(bx,function(by){return by.nodeType===1});if(bp.test(bw)){return b.filter(bw,bv,!e)}else{bw=b.filter(bw,bv)}}}}return b.grep(bx,function(bz,by){return(b.inArray(bz,bw)>=0)===e})}function a(e){var bw=aR.split("|"),bv=e.createDocumentFragment();if(bv.createElement){while(bw.length){bv.createElement(bw.pop())}}return bv}var aR="abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",ag=/ jQuery\d+="(?:\d+|null)"/g,ar=/^\s+/,R=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,d=/<([\w:]+)/,w=/",""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]},ac=a(av); -ax.optgroup=ax.option;ax.tbody=ax.tfoot=ax.colgroup=ax.caption=ax.thead;ax.th=ax.td;if(!b.support.htmlSerialize){ax._default=[1,"div
","
"]}b.fn.extend({text:function(e){if(b.isFunction(e)){return this.each(function(bw){var bv=b(this);bv.text(e.call(this,bw,bv.text()))})}if(typeof e!=="object"&&e!==L){return this.empty().append((this[0]&&this[0].ownerDocument||av).createTextNode(e))}return b.text(this)},wrapAll:function(e){if(b.isFunction(e)){return this.each(function(bw){b(this).wrapAll(e.call(this,bw))})}if(this[0]){var bv=b(e,this[0].ownerDocument).eq(0).clone(true);if(this[0].parentNode){bv.insertBefore(this[0])}bv.map(function(){var bw=this;while(bw.firstChild&&bw.firstChild.nodeType===1){bw=bw.firstChild}return bw}).append(this)}return this},wrapInner:function(e){if(b.isFunction(e)){return this.each(function(bv){b(this).wrapInner(e.call(this,bv))})}return this.each(function(){var bv=b(this),bw=bv.contents();if(bw.length){bw.wrapAll(e)}else{bv.append(e)}})},wrap:function(e){var bv=b.isFunction(e);return this.each(function(bw){b(this).wrapAll(bv?e.call(this,bw):e)})},unwrap:function(){return this.parent().each(function(){if(!b.nodeName(this,"body")){b(this).replaceWith(this.childNodes)}}).end()},append:function(){return this.domManip(arguments,true,function(e){if(this.nodeType===1){this.appendChild(e)}})},prepend:function(){return this.domManip(arguments,true,function(e){if(this.nodeType===1){this.insertBefore(e,this.firstChild)}})},before:function(){if(this[0]&&this[0].parentNode){return this.domManip(arguments,false,function(bv){this.parentNode.insertBefore(bv,this)})}else{if(arguments.length){var e=b.clean(arguments);e.push.apply(e,this.toArray());return this.pushStack(e,"before",arguments)}}},after:function(){if(this[0]&&this[0].parentNode){return this.domManip(arguments,false,function(bv){this.parentNode.insertBefore(bv,this.nextSibling)})}else{if(arguments.length){var e=this.pushStack(this,"after",arguments);e.push.apply(e,b.clean(arguments));return e}}},remove:function(e,bx){for(var bv=0,bw;(bw=this[bv])!=null;bv++){if(!e||b.filter(e,[bw]).length){if(!bx&&bw.nodeType===1){b.cleanData(bw.getElementsByTagName("*"));b.cleanData([bw])}if(bw.parentNode){bw.parentNode.removeChild(bw)}}}return this},empty:function(){for(var e=0,bv;(bv=this[e])!=null;e++){if(bv.nodeType===1){b.cleanData(bv.getElementsByTagName("*"))}while(bv.firstChild){bv.removeChild(bv.firstChild)}}return this},clone:function(bv,e){bv=bv==null?false:bv;e=e==null?bv:e;return this.map(function(){return b.clone(this,bv,e)})},html:function(bx){if(bx===L){return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(ag,""):null}else{if(typeof bx==="string"&&!ae.test(bx)&&(b.support.leadingWhitespace||!ar.test(bx))&&!ax[(d.exec(bx)||["",""])[1].toLowerCase()]){bx=bx.replace(R,"<$1>");try{for(var bw=0,bv=this.length;bw1&&bw0?this.clone(true):this).get();b(bC[bA])[bv](by);bz=bz.concat(by)}return this.pushStack(bz,e,bC.selector)}}});function bg(e){if(typeof e.getElementsByTagName!=="undefined"){return e.getElementsByTagName("*")}else{if(typeof e.querySelectorAll!=="undefined"){return e.querySelectorAll("*")}else{return[]}}}function az(e){if(e.type==="checkbox"||e.type==="radio"){e.defaultChecked=e.checked}}function E(e){var bv=(e.nodeName||"").toLowerCase();if(bv==="input"){az(e)}else{if(bv!=="script"&&typeof e.getElementsByTagName!=="undefined"){b.grep(e.getElementsByTagName("input"),az)}}}function al(e){var bv=av.createElement("div");ac.appendChild(bv);bv.innerHTML=e.outerHTML;return bv.firstChild}b.extend({clone:function(by,bA,bw){var e,bv,bx,bz=b.support.html5Clone||!ah.test("<"+by.nodeName)?by.cloneNode(true):al(by);if((!b.support.noCloneEvent||!b.support.noCloneChecked)&&(by.nodeType===1||by.nodeType===11)&&!b.isXMLDoc(by)){ai(by,bz);e=bg(by);bv=bg(bz);for(bx=0;e[bx];++bx){if(bv[bx]){ai(e[bx],bv[bx])}}}if(bA){t(by,bz);if(bw){e=bg(by);bv=bg(bz);for(bx=0;e[bx];++bx){t(e[bx],bv[bx])}}}e=bv=null;return bz},clean:function(bw,by,bH,bA){var bF;by=by||av;if(typeof by.createElement==="undefined"){by=by.ownerDocument||by[0]&&by[0].ownerDocument||av}var bI=[],bB;for(var bE=0,bz;(bz=bw[bE])!=null;bE++){if(typeof bz==="number"){bz+=""}if(!bz){continue}if(typeof bz==="string"){if(!W.test(bz)){bz=by.createTextNode(bz)}else{bz=bz.replace(R,"<$1>");var bK=(d.exec(bz)||["",""])[1].toLowerCase(),bx=ax[bK]||ax._default,bD=bx[0],bv=by.createElement("div");if(by===av){ac.appendChild(bv)}else{a(by).appendChild(bv)}bv.innerHTML=bx[1]+bz+bx[2];while(bD--){bv=bv.lastChild}if(!b.support.tbody){var e=w.test(bz),bC=bK==="table"&&!e?bv.firstChild&&bv.firstChild.childNodes:bx[1]===""&&!e?bv.childNodes:[];for(bB=bC.length-1;bB>=0;--bB){if(b.nodeName(bC[bB],"tbody")&&!bC[bB].childNodes.length){bC[bB].parentNode.removeChild(bC[bB])}}}if(!b.support.leadingWhitespace&&ar.test(bz)){bv.insertBefore(by.createTextNode(ar.exec(bz)[0]),bv.firstChild)}bz=bv.childNodes}}var bG;if(!b.support.appendChecked){if(bz[0]&&typeof(bG=bz.length)==="number"){for(bB=0;bB=0){return bx+"px"}}else{return bx}}}});if(!b.support.opacity){b.cssHooks.opacity={get:function(bv,e){return au.test((e&&bv.currentStyle?bv.currentStyle.filter:bv.style.filter)||"")?(parseFloat(RegExp.$1)/100)+"":e?"1":""},set:function(by,bz){var bx=by.style,bv=by.currentStyle,e=b.isNumeric(bz)?"alpha(opacity="+bz*100+")":"",bw=bv&&bv.filter||bx.filter||"";bx.zoom=1;if(bz>=1&&b.trim(bw.replace(ak,""))===""){bx.removeAttribute("filter");if(bv&&!bv.filter){return}}bx.filter=ak.test(bw)?bw.replace(ak,e):bw+" "+e}}}b(function(){if(!b.support.reliableMarginRight){b.cssHooks.marginRight={get:function(bw,bv){var e;b.swap(bw,{display:"inline-block"},function(){if(bv){e=Z(bw,"margin-right","marginRight")}else{e=bw.style.marginRight}});return e}}}});if(av.defaultView&&av.defaultView.getComputedStyle){aI=function(by,bw){var bv,bx,e;bw=bw.replace(z,"-$1").toLowerCase();if((bx=by.ownerDocument.defaultView)&&(e=bx.getComputedStyle(by,null))){bv=e.getPropertyValue(bw);if(bv===""&&!b.contains(by.ownerDocument.documentElement,by)){bv=b.style(by,bw)}}return bv}}if(av.documentElement.currentStyle){aX=function(bz,bw){var bA,e,by,bv=bz.currentStyle&&bz.currentStyle[bw],bx=bz.style;if(bv===null&&bx&&(by=bx[bw])){bv=by}if(!bc.test(bv)&&bn.test(bv)){bA=bx.left;e=bz.runtimeStyle&&bz.runtimeStyle.left;if(e){bz.runtimeStyle.left=bz.currentStyle.left}bx.left=bw==="fontSize"?"1em":(bv||0);bv=bx.pixelLeft+"px";bx.left=bA;if(e){bz.runtimeStyle.left=e}}return bv===""?"auto":bv}}Z=aI||aX;function p(by,bw,bv){var bA=bw==="width"?by.offsetWidth:by.offsetHeight,bz=bw==="width"?an:a1,bx=0,e=bz.length; -if(bA>0){if(bv!=="border"){for(;bx)<[^<]*)*<\/script>/gi,q=/^(?:select|textarea)/i,h=/\s+/,br=/([?&])_=[^&]*/,K=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,A=b.fn.load,aa={},r={},aE,s,aV=["*/"]+["*"];try{aE=bl.href}catch(aw){aE=av.createElement("a");aE.href="";aE=aE.href}s=K.exec(aE.toLowerCase())||[];function f(e){return function(by,bA){if(typeof by!=="string"){bA=by;by="*"}if(b.isFunction(bA)){var bx=by.toLowerCase().split(h),bw=0,bz=bx.length,bv,bB,bC;for(;bw=0){var e=bw.slice(by,bw.length);bw=bw.slice(0,by)}var bx="GET";if(bz){if(b.isFunction(bz)){bA=bz;bz=L}else{if(typeof bz==="object"){bz=b.param(bz,b.ajaxSettings.traditional);bx="POST"}}}var bv=this;b.ajax({url:bw,type:bx,dataType:"html",data:bz,complete:function(bC,bB,bD){bD=bC.responseText;if(bC.isResolved()){bC.done(function(bE){bD=bE});bv.html(e?b("
").append(bD.replace(a6,"")).find(e):bD)}if(bA){bv.each(bA,[bD,bB,bC])}}});return this},serialize:function(){return b.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?b.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||q.test(this.nodeName)||aZ.test(this.type))}).map(function(e,bv){var bw=b(this).val();return bw==null?null:b.isArray(bw)?b.map(bw,function(by,bx){return{name:bv.name,value:by.replace(bs,"\r\n")}}):{name:bv.name,value:bw.replace(bs,"\r\n")}}).get()}});b.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(e,bv){b.fn[bv]=function(bw){return this.on(bv,bw)}});b.each(["get","post"],function(e,bv){b[bv]=function(bw,by,bz,bx){if(b.isFunction(by)){bx=bx||bz;bz=by;by=L}return b.ajax({type:bv,url:bw,data:by,success:bz,dataType:bx})}});b.extend({getScript:function(e,bv){return b.get(e,L,bv,"script")},getJSON:function(e,bv,bw){return b.get(e,bv,bw,"json")},ajaxSetup:function(bv,e){if(e){am(bv,b.ajaxSettings)}else{e=bv;bv=b.ajaxSettings}am(bv,e);return bv},ajaxSettings:{url:aE,isLocal:aM.test(s[1]),global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":aV},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":bb.String,"text html":true,"text json":b.parseJSON,"text xml":b.parseXML},flatOptions:{context:true,url:true}},ajaxPrefilter:f(aa),ajaxTransport:f(r),ajax:function(bz,bx){if(typeof bz==="object"){bx=bz;bz=L}bx=bx||{};var bD=b.ajaxSetup({},bx),bS=bD.context||bD,bG=bS!==bD&&(bS.nodeType||bS instanceof b)?b(bS):b.event,bR=b.Deferred(),bN=b.Callbacks("once memory"),bB=bD.statusCode||{},bC,bH={},bO={},bQ,by,bL,bE,bI,bA=0,bw,bK,bJ={readyState:0,setRequestHeader:function(bT,bU){if(!bA){var e=bT.toLowerCase();bT=bO[e]=bO[e]||bT;bH[bT]=bU}return this},getAllResponseHeaders:function(){return bA===2?bQ:null},getResponseHeader:function(bT){var e;if(bA===2){if(!by){by={};while((e=aD.exec(bQ))){by[e[1].toLowerCase()]=e[2]}}e=by[bT.toLowerCase()]}return e===L?null:e},overrideMimeType:function(e){if(!bA){bD.mimeType=e}return this},abort:function(e){e=e||"abort";if(bL){bL.abort(e)}bF(0,e);return this}};function bF(bZ,bU,b0,bW){if(bA===2){return}bA=2;if(bE){clearTimeout(bE)}bL=L;bQ=bW||"";bJ.readyState=bZ>0?4:0;var bT,b4,b3,bX=bU,bY=b0?bj(bD,bJ,b0):L,bV,b2;if(bZ>=200&&bZ<300||bZ===304){if(bD.ifModified){if((bV=bJ.getResponseHeader("Last-Modified"))){b.lastModified[bC]=bV}if((b2=bJ.getResponseHeader("Etag"))){b.etag[bC]=b2}}if(bZ===304){bX="notmodified";bT=true}else{try{b4=G(bD,bY);bX="success";bT=true}catch(b1){bX="parsererror";b3=b1}}}else{b3=bX;if(!bX||bZ){bX="error";if(bZ<0){bZ=0}}}bJ.status=bZ;bJ.statusText=""+(bU||bX);if(bT){bR.resolveWith(bS,[b4,bX,bJ])}else{bR.rejectWith(bS,[bJ,bX,b3])}bJ.statusCode(bB);bB=L;if(bw){bG.trigger("ajax"+(bT?"Success":"Error"),[bJ,bD,bT?b4:b3])}bN.fireWith(bS,[bJ,bX]);if(bw){bG.trigger("ajaxComplete",[bJ,bD]);if(!(--b.active)){b.event.trigger("ajaxStop")}}}bR.promise(bJ);bJ.success=bJ.done;bJ.error=bJ.fail;bJ.complete=bN.add;bJ.statusCode=function(bT){if(bT){var e;if(bA<2){for(e in bT){bB[e]=[bB[e],bT[e]]}}else{e=bT[bJ.status];bJ.then(e,e)}}return this};bD.url=((bz||bD.url)+"").replace(bq,"").replace(c,s[1]+"//");bD.dataTypes=b.trim(bD.dataType||"*").toLowerCase().split(h);if(bD.crossDomain==null){bI=K.exec(bD.url.toLowerCase());bD.crossDomain=!!(bI&&(bI[1]!=s[1]||bI[2]!=s[2]||(bI[3]||(bI[1]==="http:"?80:443))!=(s[3]||(s[1]==="http:"?80:443))))}if(bD.data&&bD.processData&&typeof bD.data!=="string"){bD.data=b.param(bD.data,bD.traditional)}aW(aa,bD,bx,bJ);if(bA===2){return false}bw=bD.global;bD.type=bD.type.toUpperCase();bD.hasContent=!aQ.test(bD.type);if(bw&&b.active++===0){b.event.trigger("ajaxStart")}if(!bD.hasContent){if(bD.data){bD.url+=(M.test(bD.url)?"&":"?")+bD.data;delete bD.data}bC=bD.url;if(bD.cache===false){var bv=b.now(),bP=bD.url.replace(br,"$1_="+bv);bD.url=bP+((bP===bD.url)?(M.test(bD.url)?"&":"?")+"_="+bv:"")}}if(bD.data&&bD.hasContent&&bD.contentType!==false||bx.contentType){bJ.setRequestHeader("Content-Type",bD.contentType)}if(bD.ifModified){bC=bC||bD.url;if(b.lastModified[bC]){bJ.setRequestHeader("If-Modified-Since",b.lastModified[bC])}if(b.etag[bC]){bJ.setRequestHeader("If-None-Match",b.etag[bC])}}bJ.setRequestHeader("Accept",bD.dataTypes[0]&&bD.accepts[bD.dataTypes[0]]?bD.accepts[bD.dataTypes[0]]+(bD.dataTypes[0]!=="*"?", "+aV+"; q=0.01":""):bD.accepts["*"]);for(bK in bD.headers){bJ.setRequestHeader(bK,bD.headers[bK])}if(bD.beforeSend&&(bD.beforeSend.call(bS,bJ,bD)===false||bA===2)){bJ.abort();return false}for(bK in {success:1,error:1,complete:1}){bJ[bK](bD[bK])}bL=aW(r,bD,bx,bJ);if(!bL){bF(-1,"No Transport")}else{bJ.readyState=1;if(bw){bG.trigger("ajaxSend",[bJ,bD])}if(bD.async&&bD.timeout>0){bE=setTimeout(function(){bJ.abort("timeout")},bD.timeout)}try{bA=1;bL.send(bH,bF)}catch(bM){if(bA<2){bF(-1,bM)}else{throw bM}}}return bJ},param:function(e,bw){var bv=[],by=function(bz,bA){bA=b.isFunction(bA)?bA():bA;bv[bv.length]=encodeURIComponent(bz)+"="+encodeURIComponent(bA)};if(bw===L){bw=b.ajaxSettings.traditional}if(b.isArray(e)||(e.jquery&&!b.isPlainObject(e))){b.each(e,function(){by(this.name,this.value)})}else{for(var bx in e){v(bx,e[bx],bw,by)}}return bv.join("&").replace(k,"+")}});function v(bw,by,bv,bx){if(b.isArray(by)){b.each(by,function(bA,bz){if(bv||ap.test(bw)){bx(bw,bz)}else{v(bw+"["+(typeof bz==="object"||b.isArray(bz)?bA:"")+"]",bz,bv,bx)}})}else{if(!bv&&by!=null&&typeof by==="object"){for(var e in by){v(bw+"["+e+"]",by[e],bv,bx)}}else{bx(bw,by)}}}b.extend({active:0,lastModified:{},etag:{}});function bj(bD,bC,bz){var bv=bD.contents,bB=bD.dataTypes,bw=bD.responseFields,by,bA,bx,e;for(bA in bw){if(bA in bz){bC[bw[bA]]=bz[bA]}}while(bB[0]==="*"){bB.shift();if(by===L){by=bD.mimeType||bC.getResponseHeader("content-type")}}if(by){for(bA in bv){if(bv[bA]&&bv[bA].test(by)){bB.unshift(bA);break}}}if(bB[0] in bz){bx=bB[0]}else{for(bA in bz){if(!bB[0]||bD.converters[bA+" "+bB[0]]){bx=bA;break}if(!e){e=bA}}bx=bx||e}if(bx){if(bx!==bB[0]){bB.unshift(bx)}return bz[bx]}}function G(bH,bz){if(bH.dataFilter){bz=bH.dataFilter(bz,bH.dataType)}var bD=bH.dataTypes,bG={},bA,bE,bw=bD.length,bB,bC=bD[0],bx,by,bF,bv,e;for(bA=1;bA=bw.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();bw.animatedProperties[this.prop]=true;for(bA in bw.animatedProperties){if(bw.animatedProperties[bA]!==true){e=false}}if(e){if(bw.overflow!=null&&!b.support.shrinkWrapBlocks){b.each(["","X","Y"],function(bC,bD){bz.style["overflow"+bD]=bw.overflow[bC]})}if(bw.hide){b(bz).hide()}if(bw.hide||bw.show){for(bA in bw.animatedProperties){b.style(bz,bA,bw.orig[bA]);b.removeData(bz,"fxshow"+bA,true);b.removeData(bz,"toggle"+bA,true)}}bv=bw.complete;if(bv){bw.complete=false;bv.call(bz)}}return false}else{if(bw.duration==Infinity){this.now=bx}else{bB=bx-this.startTime;this.state=bB/bw.duration;this.pos=b.easing[bw.animatedProperties[this.prop]](this.state,bB,0,1,bw.duration);this.now=this.start+((this.end-this.start)*this.pos)}this.update()}return true}};b.extend(b.fx,{tick:function(){var bw,bv=b.timers,e=0;for(;e").appendTo(e),bw=bv.css("display");bv.remove();if(bw==="none"||bw===""){if(!a8){a8=av.createElement("iframe");a8.frameBorder=a8.width=a8.height=0}e.appendChild(a8);if(!m||!a8.createElement){m=(a8.contentWindow||a8.contentDocument).document;m.write((av.compatMode==="CSS1Compat"?"":"")+"");m.close()}bv=m.createElement(bx);m.body.appendChild(bv);bw=b.css(bv,"display");e.removeChild(a8)}Q[bx]=bw}return Q[bx]}var V=/^t(?:able|d|h)$/i,ad=/^(?:body|html)$/i;if("getBoundingClientRect" in av.documentElement){b.fn.offset=function(bI){var by=this[0],bB;if(bI){return this.each(function(e){b.offset.setOffset(this,bI,e)})}if(!by||!by.ownerDocument){return null}if(by===by.ownerDocument.body){return b.offset.bodyOffset(by)}try{bB=by.getBoundingClientRect()}catch(bF){}var bH=by.ownerDocument,bw=bH.documentElement;if(!bB||!b.contains(bw,by)){return bB?{top:bB.top,left:bB.left}:{top:0,left:0}}var bC=bH.body,bD=aK(bH),bA=bw.clientTop||bC.clientTop||0,bE=bw.clientLeft||bC.clientLeft||0,bv=bD.pageYOffset||b.support.boxModel&&bw.scrollTop||bC.scrollTop,bz=bD.pageXOffset||b.support.boxModel&&bw.scrollLeft||bC.scrollLeft,bG=bB.top+bv-bA,bx=bB.left+bz-bE;return{top:bG,left:bx}}}else{b.fn.offset=function(bF){var bz=this[0];if(bF){return this.each(function(bG){b.offset.setOffset(this,bF,bG)})}if(!bz||!bz.ownerDocument){return null}if(bz===bz.ownerDocument.body){return b.offset.bodyOffset(bz)}var bC,bw=bz.offsetParent,bv=bz,bE=bz.ownerDocument,bx=bE.documentElement,bA=bE.body,bB=bE.defaultView,e=bB?bB.getComputedStyle(bz,null):bz.currentStyle,bD=bz.offsetTop,by=bz.offsetLeft;while((bz=bz.parentNode)&&bz!==bA&&bz!==bx){if(b.support.fixedPosition&&e.position==="fixed"){break}bC=bB?bB.getComputedStyle(bz,null):bz.currentStyle;bD-=bz.scrollTop;by-=bz.scrollLeft;if(bz===bw){bD+=bz.offsetTop;by+=bz.offsetLeft;if(b.support.doesNotAddBorder&&!(b.support.doesAddBorderForTableAndCells&&V.test(bz.nodeName))){bD+=parseFloat(bC.borderTopWidth)||0;by+=parseFloat(bC.borderLeftWidth)||0}bv=bw;bw=bz.offsetParent}if(b.support.subtractsBorderForOverflowNotVisible&&bC.overflow!=="visible"){bD+=parseFloat(bC.borderTopWidth)||0;by+=parseFloat(bC.borderLeftWidth)||0}e=bC}if(e.position==="relative"||e.position==="static"){bD+=bA.offsetTop;by+=bA.offsetLeft}if(b.support.fixedPosition&&e.position==="fixed"){bD+=Math.max(bx.scrollTop,bA.scrollTop);by+=Math.max(bx.scrollLeft,bA.scrollLeft)}return{top:bD,left:by}}}b.offset={bodyOffset:function(e){var bw=e.offsetTop,bv=e.offsetLeft;if(b.support.doesNotIncludeMarginInBodyOffset){bw+=parseFloat(b.css(e,"marginTop"))||0;bv+=parseFloat(b.css(e,"marginLeft"))||0}return{top:bw,left:bv}},setOffset:function(bx,bG,bA){var bB=b.css(bx,"position");if(bB==="static"){bx.style.position="relative"}var bz=b(bx),bv=bz.offset(),e=b.css(bx,"top"),bE=b.css(bx,"left"),bF=(bB==="absolute"||bB==="fixed")&&b.inArray("auto",[e,bE])>-1,bD={},bC={},bw,by;if(bF){bC=bz.position();bw=bC.top;by=bC.left}else{bw=parseFloat(e)||0;by=parseFloat(bE)||0}if(b.isFunction(bG)){bG=bG.call(bx,bA,bv)}if(bG.top!=null){bD.top=(bG.top-bv.top)+bw}if(bG.left!=null){bD.left=(bG.left-bv.left)+by}if("using" in bG){bG.using.call(bx,bD)}else{bz.css(bD)}}};b.fn.extend({position:function(){if(!this[0]){return null}var bw=this[0],bv=this.offsetParent(),bx=this.offset(),e=ad.test(bv[0].nodeName)?{top:0,left:0}:bv.offset();bx.top-=parseFloat(b.css(bw,"marginTop"))||0;bx.left-=parseFloat(b.css(bw,"marginLeft"))||0;e.top+=parseFloat(b.css(bv[0],"borderTopWidth"))||0;e.left+=parseFloat(b.css(bv[0],"borderLeftWidth"))||0;return{top:bx.top-e.top,left:bx.left-e.left}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||av.body;while(e&&(!ad.test(e.nodeName)&&b.css(e,"position")==="static")){e=e.offsetParent}return e})}});b.each(["Left","Top"],function(bv,e){var bw="scroll"+e;b.fn[bw]=function(bz){var bx,by;if(bz===L){bx=this[0];if(!bx){return null}by=aK(bx);return by?("pageXOffset" in by)?by[bv?"pageYOffset":"pageXOffset"]:b.support.boxModel&&by.document.documentElement[bw]||by.document.body[bw]:bx[bw]}return this.each(function(){by=aK(this);if(by){by.scrollTo(!bv?bz:b(by).scrollLeft(),bv?bz:b(by).scrollTop())}else{this[bw]=bz}})}});function aK(e){return b.isWindow(e)?e:e.nodeType===9?e.defaultView||e.parentWindow:false}b.each(["Height","Width"],function(bv,e){var bw=e.toLowerCase();b.fn["inner"+e]=function(){var bx=this[0];return bx?bx.style?parseFloat(b.css(bx,bw,"padding")):this[bw]():null};b.fn["outer"+e]=function(by){var bx=this[0];return bx?bx.style?parseFloat(b.css(bx,bw,by?"margin":"border")):this[bw]():null};b.fn[bw]=function(bz){var bA=this[0];if(!bA){return bz==null?null:this}if(b.isFunction(bz)){return this.each(function(bE){var bD=b(this);bD[bw](bz.call(this,bE,bD[bw]()))})}if(b.isWindow(bA)){var bB=bA.document.documentElement["client"+e],bx=bA.document.body;return bA.document.compatMode==="CSS1Compat"&&bB||bx&&bx["client"+e]||bB}else{if(bA.nodeType===9){return Math.max(bA.documentElement["client"+e],bA.body["scroll"+e],bA.documentElement["scroll"+e],bA.body["offset"+e],bA.documentElement["offset"+e])}else{if(bz===L){var bC=b.css(bA,bw),by=parseFloat(bC);return b.isNumeric(by)?by:bC}else{return this.css(bw,typeof bz==="string"?bz:bz+"px")}}}}});bb.jQuery=bb.$=b;if(typeof define==="function"&&define.amd&&define.amd.jQuery){define("jquery",[],function(){return b -})}})(window); -/*! - PowerTip - v1.2.0 - 2013-04-03 - http://stevenbenner.github.com/jquery-powertip/ - Copyright (c) 2013 Steven Benner (http://stevenbenner.com/). - Released under MIT license. - https://raw.github.com/stevenbenner/jquery-powertip/master/LICENSE.txt -*/ -(function(a){if(typeof define==="function"&&define.amd){define(["jquery"],a)}else{a(jQuery)}}(function(k){var A=k(document),s=k(window),w=k("body");var n="displayController",e="hasActiveHover",d="forcedOpen",u="hasMouseMove",f="mouseOnToPopup",g="originalTitle",y="powertip",o="powertipjq",l="powertiptarget",E=180/Math.PI;var c={isTipOpen:false,isFixedTipOpen:false,isClosing:false,tipOpenImminent:false,activeHover:null,currentX:0,currentY:0,previousX:0,previousY:0,desyncTimeout:null,mouseTrackingActive:false,delayInProgress:false,windowWidth:0,windowHeight:0,scrollTop:0,scrollLeft:0};var p={none:0,top:1,bottom:2,left:4,right:8};k.fn.powerTip=function(F,N){if(!this.length){return this}if(k.type(F)==="string"&&k.powerTip[F]){return k.powerTip[F].call(this,this,N)}var O=k.extend({},k.fn.powerTip.defaults,F),G=new x(O);h();this.each(function M(){var R=k(this),Q=R.data(y),P=R.data(o),T=R.data(l),S;if(R.data(n)){k.powerTip.destroy(R)}S=R.attr("title");if(!Q&&!T&&!P&&S){R.data(y,S);R.data(g,S);R.removeAttr("title")}R.data(n,new t(R,O,G))});if(!O.manual){this.on({"mouseenter.powertip":function J(P){k.powerTip.show(this,P)},"mouseleave.powertip":function L(){k.powerTip.hide(this)},"focus.powertip":function K(){k.powerTip.show(this)},"blur.powertip":function H(){k.powerTip.hide(this,true)},"keydown.powertip":function I(P){if(P.keyCode===27){k.powerTip.hide(this,true)}}})}return this};k.fn.powerTip.defaults={fadeInTime:200,fadeOutTime:100,followMouse:false,popupId:"powerTip",intentSensitivity:7,intentPollInterval:100,closeDelay:100,placement:"n",smartPlacement:false,offset:10,mouseOnToPopup:false,manual:false};k.fn.powerTip.smartPlacementLists={n:["n","ne","nw","s"],e:["e","ne","se","w","nw","sw","n","s","e"],s:["s","se","sw","n"],w:["w","nw","sw","e","ne","se","n","s","w"],nw:["nw","w","sw","n","s","se","nw"],ne:["ne","e","se","n","s","sw","ne"],sw:["sw","w","nw","s","n","ne","sw"],se:["se","e","ne","s","n","nw","se"],"nw-alt":["nw-alt","n","ne-alt","sw-alt","s","se-alt","w","e"],"ne-alt":["ne-alt","n","nw-alt","se-alt","s","sw-alt","e","w"],"sw-alt":["sw-alt","s","se-alt","nw-alt","n","ne-alt","w","e"],"se-alt":["se-alt","s","sw-alt","ne-alt","n","nw-alt","e","w"]};k.powerTip={show:function z(F,G){if(G){i(G);c.previousX=G.pageX;c.previousY=G.pageY;k(F).data(n).show()}else{k(F).first().data(n).show(true,true)}return F},reposition:function r(F){k(F).first().data(n).resetPosition();return F},hide:function D(G,F){if(G){k(G).first().data(n).hide(F)}else{if(c.activeHover){c.activeHover.data(n).hide(true)}}return G},destroy:function C(G){k(G).off(".powertip").each(function F(){var I=k(this),H=[g,n,e,d];if(I.data(g)){I.attr("title",I.data(g));H.push(y)}I.removeData(H)});return G}};k.powerTip.showTip=k.powerTip.show;k.powerTip.closeTip=k.powerTip.hide;function b(){var F=this;F.top="auto";F.left="auto";F.right="auto";F.bottom="auto";F.set=function(H,G){if(k.isNumeric(G)){F[H]=Math.round(G)}}}function t(K,N,F){var J=null;function L(P,Q){M();if(!K.data(e)){if(!P){c.tipOpenImminent=true;J=setTimeout(function O(){J=null;I()},N.intentPollInterval)}else{if(Q){K.data(d,true)}F.showTip(K)}}}function G(P){M();c.tipOpenImminent=false;if(K.data(e)){K.data(d,false);if(!P){c.delayInProgress=true;J=setTimeout(function O(){J=null;F.hideTip(K);c.delayInProgress=false},N.closeDelay)}else{F.hideTip(K)}}}function I(){var Q=Math.abs(c.previousX-c.currentX),O=Math.abs(c.previousY-c.currentY),P=Q+O;if(P",{id:Q.popupId});if(w.length===0){w=k("body")}w.append(O)}if(Q.followMouse){if(!O.data(u)){A.on("mousemove",M);s.on("scroll",M);O.data(u,true)}}if(Q.mouseOnToPopup){O.on({mouseenter:function L(){if(O.data(f)){if(c.activeHover){c.activeHover.data(n).cancel()}}},mouseleave:function N(){if(c.activeHover){c.activeHover.data(n).hide()}}})}function I(S){S.data(e,true);O.queue(function R(T){H(S);T()})}function H(S){var U;if(!S.data(e)){return}if(c.isTipOpen){if(!c.isClosing){K(c.activeHover)}O.delay(100).queue(function R(V){H(S);V()});return}S.trigger("powerTipPreRender");U=B(S);if(U){O.empty().append(U)}else{return}S.trigger("powerTipRender");c.activeHover=S;c.isTipOpen=true;O.data(f,Q.mouseOnToPopup);if(!Q.followMouse){G(S);c.isFixedTipOpen=true}else{M()}O.fadeIn(Q.fadeInTime,function T(){if(!c.desyncTimeout){c.desyncTimeout=setInterval(J,500)}S.trigger("powerTipOpen")})}function K(R){c.isClosing=true;c.activeHover=null;c.isTipOpen=false;c.desyncTimeout=clearInterval(c.desyncTimeout);R.data(e,false);R.data(d,false);O.fadeOut(Q.fadeOutTime,function S(){var T=new b();c.isClosing=false;c.isFixedTipOpen=false;O.removeClass();T.set("top",c.currentY+Q.offset);T.set("left",c.currentX+Q.offset);O.css(T);R.trigger("powerTipClose")})}function M(){if(!c.isFixedTipOpen&&(c.isTipOpen||(c.tipOpenImminent&&O.data(u)))){var R=O.outerWidth(),V=O.outerHeight(),U=new b(),S,T;U.set("top",c.currentY+Q.offset);U.set("left",c.currentX+Q.offset);S=m(U,R,V);if(S!==p.none){T=a(S);if(T===1){if(S===p.right){U.set("left",c.windowWidth-R)}else{if(S===p.bottom){U.set("top",c.scrollTop+c.windowHeight-V)}}}else{U.set("left",c.currentX-R-Q.offset);U.set("top",c.currentY-V-Q.offset)}}O.css(U)}}function G(S){var R,T;if(Q.smartPlacement){R=k.fn.powerTip.smartPlacementLists[Q.placement];k.each(R,function(U,W){var V=m(F(S,W),O.outerWidth(),O.outerHeight());T=W;if(V===p.none){return false}})}else{F(S,Q.placement);T=Q.placement}O.addClass(T)}function F(U,T){var R=0,S,W,V=new b();V.set("top",0);V.set("left",0);O.css(V);do{S=O.outerWidth();W=O.outerHeight();V=P.compute(U,T,S,W,Q.offset);O.css(V)}while(++R<=5&&(S!==O.outerWidth()||W!==O.outerHeight()));return V}function J(){var R=false;if(c.isTipOpen&&!c.isClosing&&!c.delayInProgress){if(c.activeHover.data(e)===false||c.activeHover.is(":disabled")){R=true}else{if(!v(c.activeHover)&&!c.activeHover.is(":focus")&&!c.activeHover.data(d)){if(O.data(f)){if(!v(O)){R=true}}else{R=true}}}if(R){K(c.activeHover)}}}this.showTip=I;this.hideTip=K;this.resetPosition=G}function q(F){return window.SVGElement&&F[0] instanceof SVGElement}function h(){if(!c.mouseTrackingActive){c.mouseTrackingActive=true;k(function H(){c.scrollLeft=s.scrollLeft();c.scrollTop=s.scrollTop();c.windowWidth=s.width();c.windowHeight=s.height()});A.on("mousemove",i);s.on({resize:function G(){c.windowWidth=s.width();c.windowHeight=s.height()},scroll:function F(){var I=s.scrollLeft(),J=s.scrollTop();if(I!==c.scrollLeft){c.currentX+=I-c.scrollLeft;c.scrollLeft=I}if(J!==c.scrollTop){c.currentY+=J-c.scrollTop;c.scrollTop=J}}})}}function i(F){c.currentX=F.pageX;c.currentY=F.pageY}function v(F){var H=F.offset(),J=F[0].getBoundingClientRect(),I=J.right-J.left,G=J.bottom-J.top;return c.currentX>=H.left&&c.currentX<=H.left+I&&c.currentY>=H.top&&c.currentY<=H.top+G}function B(I){var G=I.data(y),F=I.data(o),K=I.data(l),H,J;if(G){if(k.isFunction(G)){G=G.call(I[0])}J=G}else{if(F){if(k.isFunction(F)){F=F.call(I[0])}if(F.length>0){J=F.clone(true,true)}}else{if(K){H=k("#"+K);if(H.length>0){J=H.html()}}}}return J}function m(M,L,K){var G=c.scrollTop,J=c.scrollLeft,I=G+c.windowHeight,F=J+c.windowWidth,H=p.none;if(M.topI||Math.abs(M.bottom-c.windowHeight)>I){H|=p.bottom}if(M.leftF){H|=p.left}if(M.left+L>F||M.right_z8U diff --git a/Arduino/MAX6956/html/nav_g.png b/Arduino/MAX6956/html/nav_g.png deleted file mode 100644 index 2093a237a94f6c83e19ec6e5fd42f7ddabdafa81..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 95 zcmeAS@N?(olHy`uVBq!ia0vp^j6lrB!3HFm1ilyoDK$?Q$B+ufw|5PB85lU25BhtE tr?otc=hd~V+ws&_A@j8Fiv!KF$B+ufw|5=67#uj90@pIL wZ=Q8~_Ju`#59=RjDrmm`tMD@M=!-l18IR?&vFVdQ&MBb@0HFXL1|%O$WD@{VPM$7~Ar*{o?;hlAFyLXmaDC0y znK1_#cQqJWPES%4Uujug^TE?jMft$}Eq^WaR~)%f)vSNs&gek&x%A9X9sM - - - - - - - - -
-
Loading...
-
- -
Searching...
-
No Matches
- -
- - diff --git a/Arduino/MAX6956/html/search/all_62.js b/Arduino/MAX6956/html/search/all_62.js deleted file mode 100644 index b44b09cd..00000000 --- a/Arduino/MAX6956/html/search/all_62.js +++ /dev/null @@ -1,4 +0,0 @@ -var searchData= -[ - ['buffer',['buffer',['../classMAX6956.html#a9f4597436b10ee86a02c96c2b0605851',1,'MAX6956']]] -]; diff --git a/Arduino/MAX6956/html/search/all_63.html b/Arduino/MAX6956/html/search/all_63.html deleted file mode 100644 index a8fe36da..00000000 --- a/Arduino/MAX6956/html/search/all_63.html +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - -
-
Loading...
-
- -
Searching...
-
No Matches
- -
- - diff --git a/Arduino/MAX6956/html/search/all_63.js b/Arduino/MAX6956/html/search/all_63.js deleted file mode 100644 index 6abd3d20..00000000 --- a/Arduino/MAX6956/html/search/all_63.js +++ /dev/null @@ -1,6 +0,0 @@ -var searchData= -[ - ['configallports',['configAllPorts',['../classMAX6956.html#a9e9f11c46bdc86d8e882ed8bb5efabdf',1,'MAX6956']]], - ['configport',['configPort',['../classMAX6956.html#a5e05bead41c585c68de79bbfed971d19',1,'MAX6956']]], - ['configports',['configPorts',['../classMAX6956.html#a400393e30fbe196aef43d8edea890228',1,'MAX6956']]] -]; diff --git a/Arduino/MAX6956/html/search/all_64.html b/Arduino/MAX6956/html/search/all_64.html deleted file mode 100644 index b415c0ed..00000000 --- a/Arduino/MAX6956/html/search/all_64.html +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - -
-
Loading...
-
- -
Searching...
-
No Matches
- -
- - diff --git a/Arduino/MAX6956/html/search/all_64.js b/Arduino/MAX6956/html/search/all_64.js deleted file mode 100644 index 6e8f44cc..00000000 --- a/Arduino/MAX6956/html/search/all_64.js +++ /dev/null @@ -1,5 +0,0 @@ -var searchData= -[ - ['devaddr',['devAddr',['../classMAX6956.html#a6ba2f8011914df50d6022ab54b27748d',1,'MAX6956']]], - ['disableallports',['disableAllPorts',['../classMAX6956.html#a93a81ff86316f63ee1ada3529da2a95b',1,'MAX6956']]] -]; diff --git a/Arduino/MAX6956/html/search/all_65.html b/Arduino/MAX6956/html/search/all_65.html deleted file mode 100644 index 49e2caeb..00000000 --- a/Arduino/MAX6956/html/search/all_65.html +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - -
-
Loading...
-
- -
Searching...
-
No Matches
- -
- - diff --git a/Arduino/MAX6956/html/search/all_65.js b/Arduino/MAX6956/html/search/all_65.js deleted file mode 100644 index 25d17ecc..00000000 --- a/Arduino/MAX6956/html/search/all_65.js +++ /dev/null @@ -1,4 +0,0 @@ -var searchData= -[ - ['enableallports',['enableAllPorts',['../classMAX6956.html#a51a47c1f69532e96c6caa357889004e3',1,'MAX6956']]] -]; diff --git a/Arduino/MAX6956/html/search/all_67.html b/Arduino/MAX6956/html/search/all_67.html deleted file mode 100644 index a6568a3a..00000000 --- a/Arduino/MAX6956/html/search/all_67.html +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - -
-
Loading...
-
- -
Searching...
-
No Matches
- -
- - diff --git a/Arduino/MAX6956/html/search/all_67.js b/Arduino/MAX6956/html/search/all_67.js deleted file mode 100644 index 400e6433..00000000 --- a/Arduino/MAX6956/html/search/all_67.js +++ /dev/null @@ -1,10 +0,0 @@ -var searchData= -[ - ['getconfigreg',['getConfigReg',['../classMAX6956.html#a5e787204b3f7bf8750376f5bdf77a971',1,'MAX6956']]], - ['getenableindividualcurrent',['getEnableIndividualCurrent',['../classMAX6956.html#abcfe81dd0ffc90284f19503b6366dcfb',1,'MAX6956']]], - ['getenabletransitiondetection',['getEnableTransitionDetection',['../classMAX6956.html#a76e9ab35769854b3e4224499897601ec',1,'MAX6956']]], - ['getglobalcurrent',['getGlobalCurrent',['../classMAX6956.html#a1926760b263588314fd759d129091940',1,'MAX6956']]], - ['getinputmask',['getInputMask',['../classMAX6956.html#a56245915d7d4cd8fd34629bd91695147',1,'MAX6956']]], - ['getpower',['getPower',['../classMAX6956.html#acdc18c36735d8015651d4e3c75da4300',1,'MAX6956']]], - ['gettestmode',['getTestMode',['../classMAX6956.html#ad4f99f08d1cf08c5a0097215e680a80a',1,'MAX6956']]] -]; diff --git a/Arduino/MAX6956/html/search/all_69.html b/Arduino/MAX6956/html/search/all_69.html deleted file mode 100644 index 676651ef..00000000 --- a/Arduino/MAX6956/html/search/all_69.html +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - -
-
Loading...
-
- -
Searching...
-
No Matches
- -
- - diff --git a/Arduino/MAX6956/html/search/all_69.js b/Arduino/MAX6956/html/search/all_69.js deleted file mode 100644 index 47c8e9d4..00000000 --- a/Arduino/MAX6956/html/search/all_69.js +++ /dev/null @@ -1,4 +0,0 @@ -var searchData= -[ - ['initialize',['initialize',['../classMAX6956.html#ad63e927adc2427b4b661f2422ddd40d8',1,'MAX6956']]] -]; diff --git a/Arduino/MAX6956/html/search/all_6d.html b/Arduino/MAX6956/html/search/all_6d.html deleted file mode 100644 index 82ceec77..00000000 --- a/Arduino/MAX6956/html/search/all_6d.html +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - -
-
Loading...
-
- -
Searching...
-
No Matches
- -
- - diff --git a/Arduino/MAX6956/html/search/all_6d.js b/Arduino/MAX6956/html/search/all_6d.js deleted file mode 100644 index ee74e50d..00000000 --- a/Arduino/MAX6956/html/search/all_6d.js +++ /dev/null @@ -1,174 +0,0 @@ -var searchData= -[ - ['max6956',['MAX6956',['../classMAX6956.html',1,'MAX6956'],['../classMAX6956.html#a210d9e95978d61357db757cb80475bde',1,'MAX6956::MAX6956()'],['../classMAX6956.html#a1a7b33190871a09d81c5bec741b645b7',1,'MAX6956::MAX6956(uint8_t address)']]], - ['max6956_2ecpp',['MAX6956.cpp',['../MAX6956_8cpp.html',1,'']]], - ['max6956_2eh',['MAX6956.h',['../MAX6956_8h.html',1,'']]], - ['max6956_5faddress',['MAX6956_ADDRESS',['../MAX6956_8h.html#a33e60623a4c5b483d4604fe2c9b91be7',1,'MAX6956.h']]], - ['max6956_5fconfig_5fglobal_5fcurrent_5fbit',['MAX6956_CONFIG_GLOBAL_CURRENT_BIT',['../MAX6956_8h.html#a4288d838d55461c66c0ba2e904f588a7',1,'MAX6956.h']]], - ['max6956_5fconfig_5fpower_5fbit',['MAX6956_CONFIG_POWER_BIT',['../MAX6956_8h.html#a03faf0490eddbb2f0405616ad6ac4052',1,'MAX6956.h']]], - ['max6956_5fconfig_5ftransition_5fbit',['MAX6956_CONFIG_TRANSITION_BIT',['../MAX6956_8h.html#af1d61c00ae2e56dd5e7f04dc4b0c1663',1,'MAX6956.h']]], - ['max6956_5fcurrent_5f0',['MAX6956_CURRENT_0',['../MAX6956_8h.html#a930221b73d0e7327ffce1e3072ed69e3',1,'MAX6956.h']]], - ['max6956_5fcurrent_5f1',['MAX6956_CURRENT_1',['../MAX6956_8h.html#afd6a3c0f560b7b7190805416e1ad00f5',1,'MAX6956.h']]], - ['max6956_5fcurrent_5f10',['MAX6956_CURRENT_10',['../MAX6956_8h.html#a62f09fbe807ce97d3558748808ed3a11',1,'MAX6956.h']]], - ['max6956_5fcurrent_5f11',['MAX6956_CURRENT_11',['../MAX6956_8h.html#a5b97f8927dd861189567ad1fda6d692a',1,'MAX6956.h']]], - ['max6956_5fcurrent_5f12',['MAX6956_CURRENT_12',['../MAX6956_8h.html#a8fb88850c74ecc2080971984c817b860',1,'MAX6956.h']]], - ['max6956_5fcurrent_5f13',['MAX6956_CURRENT_13',['../MAX6956_8h.html#a8bfeeb7d88d4284dec7174b65724877d',1,'MAX6956.h']]], - ['max6956_5fcurrent_5f14',['MAX6956_CURRENT_14',['../MAX6956_8h.html#aad136273ced9dea0ef4a8821f4a5f368',1,'MAX6956.h']]], - ['max6956_5fcurrent_5f15',['MAX6956_CURRENT_15',['../MAX6956_8h.html#a4c0ac1cc939ecfb7992dac2834521eb6',1,'MAX6956.h']]], - ['max6956_5fcurrent_5f2',['MAX6956_CURRENT_2',['../MAX6956_8h.html#ab7558038e4f723efa4b406e988a93990',1,'MAX6956.h']]], - ['max6956_5fcurrent_5f3',['MAX6956_CURRENT_3',['../MAX6956_8h.html#a8b8800a153cf4869a6c4d399f8d46035',1,'MAX6956.h']]], - ['max6956_5fcurrent_5f4',['MAX6956_CURRENT_4',['../MAX6956_8h.html#a2678f20d0e18e036e13ff5f422fcf609',1,'MAX6956.h']]], - ['max6956_5fcurrent_5f5',['MAX6956_CURRENT_5',['../MAX6956_8h.html#af808e1e791b9a640d6b6c62cb145f169',1,'MAX6956.h']]], - ['max6956_5fcurrent_5f6',['MAX6956_CURRENT_6',['../MAX6956_8h.html#a0c97726477caef4c0f54eb1beaffbdff',1,'MAX6956.h']]], - ['max6956_5fcurrent_5f7',['MAX6956_CURRENT_7',['../MAX6956_8h.html#a55c66763c65c8554d12a71a4c20e35a6',1,'MAX6956.h']]], - ['max6956_5fcurrent_5f8',['MAX6956_CURRENT_8',['../MAX6956_8h.html#a11c425ee14938c667e63e7df4cf8afa2',1,'MAX6956.h']]], - ['max6956_5fcurrent_5f9',['MAX6956_CURRENT_9',['../MAX6956_8h.html#a4da9aedd07982408005da31fda78463a',1,'MAX6956.h']]], - ['max6956_5fdefault_5faddress',['MAX6956_DEFAULT_ADDRESS',['../MAX6956_8h.html#a4ca90873afdfdacaa730ed5db53e2f5b',1,'MAX6956.h']]], - ['max6956_5fdisplay_5ftest_5fbit',['MAX6956_DISPLAY_TEST_BIT',['../MAX6956_8h.html#a7e110f7b5949bf63dd7c5b4e9a59a5b0',1,'MAX6956.h']]], - ['max6956_5fglobal_5fcurrent_5fbit',['MAX6956_GLOBAL_CURRENT_BIT',['../MAX6956_8h.html#a85368204ba368978f814d46d81335c35',1,'MAX6956.h']]], - ['max6956_5fglobal_5fcurrent_5flength',['MAX6956_GLOBAL_CURRENT_LENGTH',['../MAX6956_8h.html#afbcb8bf5ecc4e5afada48446f8dac809',1,'MAX6956.h']]], - ['max6956_5finput_5fw_5fpull',['MAX6956_INPUT_W_PULL',['../MAX6956_8h.html#a68fc1bc750b7959fbab7e64f79589b83',1,'MAX6956.h']]], - ['max6956_5finput_5fwo_5fpull',['MAX6956_INPUT_WO_PULL',['../MAX6956_8h.html#ab05f3186e2515bab3a536ad9f1cbb7db',1,'MAX6956.h']]], - ['max6956_5foff',['MAX6956_OFF',['../MAX6956_8h.html#a003fe60fa8da81e67da2ad7900d1196f',1,'MAX6956.h']]], - ['max6956_5fon',['MAX6956_ON',['../MAX6956_8h.html#a4e151161e190a9f45aebfd712064b034',1,'MAX6956.h']]], - ['max6956_5foutput_5fgpio',['MAX6956_OUTPUT_GPIO',['../MAX6956_8h.html#a27f6ca524d4c18623762c722d9993c10',1,'MAX6956.h']]], - ['max6956_5foutput_5fled',['MAX6956_OUTPUT_LED',['../MAX6956_8h.html#ad6490a909085059c4300a51dcebbf7bc',1,'MAX6956.h']]], - ['max6956_5fport12_5fcurrent_5fbit',['MAX6956_PORT12_CURRENT_BIT',['../MAX6956_8h.html#ae1cb8088b95a2e19f293dbeee7ef7892',1,'MAX6956.h']]], - ['max6956_5fport12_5fcurrent_5flength',['MAX6956_PORT12_CURRENT_LENGTH',['../MAX6956_8h.html#a8b0c452aa9a3f66de931d4a226f865e6',1,'MAX6956.h']]], - ['max6956_5fport13_5fcurrent_5fbit',['MAX6956_PORT13_CURRENT_BIT',['../MAX6956_8h.html#a0c413303648e14359c311fb9478cfce7',1,'MAX6956.h']]], - ['max6956_5fport13_5fcurrent_5flength',['MAX6956_PORT13_CURRENT_LENGTH',['../MAX6956_8h.html#abaee1f6920a6a6770468cb7def42bff7',1,'MAX6956.h']]], - ['max6956_5fport14_5fcurrent_5fbit',['MAX6956_PORT14_CURRENT_BIT',['../MAX6956_8h.html#a0fcb35fa292905862765e99dd03e63b2',1,'MAX6956.h']]], - ['max6956_5fport14_5fcurrent_5flength',['MAX6956_PORT14_CURRENT_LENGTH',['../MAX6956_8h.html#aa98b4176c22631122a00948e5a54e91f',1,'MAX6956.h']]], - ['max6956_5fport15_5fcurrent_5fbit',['MAX6956_PORT15_CURRENT_BIT',['../MAX6956_8h.html#a659a1777dac35a14930720029b786aed',1,'MAX6956.h']]], - ['max6956_5fport15_5fcurrent_5flength',['MAX6956_PORT15_CURRENT_LENGTH',['../MAX6956_8h.html#ab377c2d0463246bfc66c9df01087285d',1,'MAX6956.h']]], - ['max6956_5fport16_5fcurrent_5fbit',['MAX6956_PORT16_CURRENT_BIT',['../MAX6956_8h.html#a977fb8ce0e696e764ae098dce361e446',1,'MAX6956.h']]], - ['max6956_5fport16_5fcurrent_5flength',['MAX6956_PORT16_CURRENT_LENGTH',['../MAX6956_8h.html#a04c2dcf166214a43fbdd9ae5f7a0ca00',1,'MAX6956.h']]], - ['max6956_5fport17_5fcurrent_5fbit',['MAX6956_PORT17_CURRENT_BIT',['../MAX6956_8h.html#ab59b7f618ff0788a6bd21313bf14673f',1,'MAX6956.h']]], - ['max6956_5fport17_5fcurrent_5flength',['MAX6956_PORT17_CURRENT_LENGTH',['../MAX6956_8h.html#adf0428deb9192d621f837d7951e539be',1,'MAX6956.h']]], - ['max6956_5fport18_5fcurrent_5fbit',['MAX6956_PORT18_CURRENT_BIT',['../MAX6956_8h.html#ab0d4c28bc6747482ab33a027fd93b5d7',1,'MAX6956.h']]], - ['max6956_5fport18_5fcurrent_5flength',['MAX6956_PORT18_CURRENT_LENGTH',['../MAX6956_8h.html#a9bb781fca7fadebb28918c05d2f1605c',1,'MAX6956.h']]], - ['max6956_5fport19_5fcurrent_5fbit',['MAX6956_PORT19_CURRENT_BIT',['../MAX6956_8h.html#aea0128f7b979e68785b78cfc7e480a32',1,'MAX6956.h']]], - ['max6956_5fport19_5fcurrent_5flength',['MAX6956_PORT19_CURRENT_LENGTH',['../MAX6956_8h.html#a5c2f25a82e8b442abb28a9544a3d4088',1,'MAX6956.h']]], - ['max6956_5fport21_5fcurrent_5fbit',['MAX6956_PORT21_CURRENT_BIT',['../MAX6956_8h.html#abd855e00543729cc87ab4a48e3d98649',1,'MAX6956.h']]], - ['max6956_5fport21_5fcurrent_5flength',['MAX6956_PORT21_CURRENT_LENGTH',['../MAX6956_8h.html#a65cd02d7f498266b224c035a3809126a',1,'MAX6956.h']]], - ['max6956_5fport22_5fcurrent_5fbit',['MAX6956_PORT22_CURRENT_BIT',['../MAX6956_8h.html#a061947a1484a8449fd4301a1022cafe5',1,'MAX6956.h']]], - ['max6956_5fport22_5fcurrent_5flength',['MAX6956_PORT22_CURRENT_LENGTH',['../MAX6956_8h.html#aa64238ebb3bf6d8ee2d0d368992e7613',1,'MAX6956.h']]], - ['max6956_5fport23_5fcurrent_5fbit',['MAX6956_PORT23_CURRENT_BIT',['../MAX6956_8h.html#a95789ffe1e677c75090556342763c6ac',1,'MAX6956_PORT23_CURRENT_BIT(): MAX6956.h'],['../MAX6956_8h.html#a95789ffe1e677c75090556342763c6ac',1,'MAX6956_PORT23_CURRENT_BIT(): MAX6956.h']]], - ['max6956_5fport23_5fcurrent_5flength',['MAX6956_PORT23_CURRENT_LENGTH',['../MAX6956_8h.html#a0f492bea7bf9e0906ba13f447327d5a8',1,'MAX6956_PORT23_CURRENT_LENGTH(): MAX6956.h'],['../MAX6956_8h.html#a0f492bea7bf9e0906ba13f447327d5a8',1,'MAX6956_PORT23_CURRENT_LENGTH(): MAX6956.h']]], - ['max6956_5fport24_5fcurrent_5fbit',['MAX6956_PORT24_CURRENT_BIT',['../MAX6956_8h.html#a50e41ea8c3ec1bb3d55e5a4eb03563a2',1,'MAX6956.h']]], - ['max6956_5fport24_5fcurrent_5flength',['MAX6956_PORT24_CURRENT_LENGTH',['../MAX6956_8h.html#a11ee583606d04516bc2fc5812b05cd3d',1,'MAX6956.h']]], - ['max6956_5fport25_5fcurrent_5fbit',['MAX6956_PORT25_CURRENT_BIT',['../MAX6956_8h.html#a75f6b93cf7558a38adba5bb4a91d05f8',1,'MAX6956.h']]], - ['max6956_5fport25_5fcurrent_5flength',['MAX6956_PORT25_CURRENT_LENGTH',['../MAX6956_8h.html#a3b1a7a5f82da6b43bd5a24d2297a2f75',1,'MAX6956.h']]], - ['max6956_5fport26_5fcurrent_5fbit',['MAX6956_PORT26_CURRENT_BIT',['../MAX6956_8h.html#abd400d2f356832d21b1787e2501a8644',1,'MAX6956.h']]], - ['max6956_5fport26_5fcurrent_5flength',['MAX6956_PORT26_CURRENT_LENGTH',['../MAX6956_8h.html#a28bf5ca7da83928eeec3f4f302d12c45',1,'MAX6956.h']]], - ['max6956_5fport27_5fcurrent_5fbit',['MAX6956_PORT27_CURRENT_BIT',['../MAX6956_8h.html#a62bf02cd8e4d8a9dfa975d0e319f68f5',1,'MAX6956.h']]], - ['max6956_5fport27_5fcurrent_5flength',['MAX6956_PORT27_CURRENT_LENGTH',['../MAX6956_8h.html#a0a0f99c166b5a60d7e6c6c7d99306b45',1,'MAX6956.h']]], - ['max6956_5fport28_5fcurrent_5fbit',['MAX6956_PORT28_CURRENT_BIT',['../MAX6956_8h.html#ab6135c4105c3b39625e7361a438e1511',1,'MAX6956.h']]], - ['max6956_5fport28_5fcurrent_5flength',['MAX6956_PORT28_CURRENT_LENGTH',['../MAX6956_8h.html#ac2bcdc199d348dba281a4371675bd428',1,'MAX6956.h']]], - ['max6956_5fport29_5fcurrent_5fbit',['MAX6956_PORT29_CURRENT_BIT',['../MAX6956_8h.html#ae98448e4aa991d16d9b1d9d6071078d8',1,'MAX6956.h']]], - ['max6956_5fport29_5fcurrent_5flength',['MAX6956_PORT29_CURRENT_LENGTH',['../MAX6956_8h.html#a6b0d8a1c63777d016e1cb22076b91377',1,'MAX6956.h']]], - ['max6956_5fport31_5fcurrent_5fbit',['MAX6956_PORT31_CURRENT_BIT',['../MAX6956_8h.html#a1cdbea93ca621e5fc4c747286bdf90e1',1,'MAX6956.h']]], - ['max6956_5fport31_5fcurrent_5flength',['MAX6956_PORT31_CURRENT_LENGTH',['../MAX6956_8h.html#a40a075605dfcfc2736aab5ffa10e3e2c',1,'MAX6956.h']]], - ['max6956_5fport33_5fcurrent_5fbit',['MAX6956_PORT33_CURRENT_BIT',['../MAX6956_8h.html#aa5acefc0723ea8d2b804aa7eccae705b',1,'MAX6956.h']]], - ['max6956_5fport33_5fcurrent_5flength',['MAX6956_PORT33_CURRENT_LENGTH',['../MAX6956_8h.html#a2fb02a7e77abefcbf7c194ff6b994ae9',1,'MAX6956.h']]], - ['max6956_5fra_5fconfig_5fp11p10p9p8',['MAX6956_RA_CONFIG_P11P10P9P8',['../MAX6956_8h.html#a3a2fa6f7cc985cfeea00ebd1dd64ae8c',1,'MAX6956.h']]], - ['max6956_5fra_5fconfig_5fp15p14p13p12',['MAX6956_RA_CONFIG_P15P14P13P12',['../MAX6956_8h.html#a119a0a92d4ccdb0e8f27fd565b1220bd',1,'MAX6956.h']]], - ['max6956_5fra_5fconfig_5fp19p18p17p16',['MAX6956_RA_CONFIG_P19P18P17P16',['../MAX6956_8h.html#a8f199d21b14cf933d5093d3001d0400d',1,'MAX6956.h']]], - ['max6956_5fra_5fconfig_5fp23p22p21p20',['MAX6956_RA_CONFIG_P23P22P21P20',['../MAX6956_8h.html#a025ce0245fb957ef58afc5f4920e19f3',1,'MAX6956.h']]], - ['max6956_5fra_5fconfig_5fp27p26p25p24',['MAX6956_RA_CONFIG_P27P26P25P24',['../MAX6956_8h.html#a4e813aab18cbd7462e1ac5a59b0a53ab',1,'MAX6956.h']]], - ['max6956_5fra_5fconfig_5fp31p30p29p28',['MAX6956_RA_CONFIG_P31P30P29P28',['../MAX6956_8h.html#a98b5c2d8359fbb7e07eb2eade7e8870a',1,'MAX6956.h']]], - ['max6956_5fra_5fconfig_5fp7p6p5p4',['MAX6956_RA_CONFIG_P7P6P5P4',['../MAX6956_8h.html#a1c4db4957c22f8767b2f1a06e5cb9a32',1,'MAX6956.h']]], - ['max6956_5fra_5fconfiguration',['MAX6956_RA_CONFIGURATION',['../MAX6956_8h.html#a5c3d1c00491596887e211bfa630c1b94',1,'MAX6956.h']]], - ['max6956_5fra_5fcurrent_5f0xp11p10',['MAX6956_RA_CURRENT_0xP11P10',['../MAX6956_8h.html#aa2304dec8420451a881876948e1cba43',1,'MAX6956.h']]], - ['max6956_5fra_5fcurrent_5f0xp13p12',['MAX6956_RA_CURRENT_0xP13P12',['../MAX6956_8h.html#add5533d08bfa791cf8cf95d7dd3f16d3',1,'MAX6956.h']]], - ['max6956_5fra_5fcurrent_5f0xp15p14',['MAX6956_RA_CURRENT_0xP15P14',['../MAX6956_8h.html#ae51b720b2bd4868c1986e2d314822778',1,'MAX6956.h']]], - ['max6956_5fra_5fcurrent_5f0xp17p16',['MAX6956_RA_CURRENT_0xP17P16',['../MAX6956_8h.html#a77820b1e4acee07a338e179ab35a7836',1,'MAX6956.h']]], - ['max6956_5fra_5fcurrent_5f0xp19p18',['MAX6956_RA_CURRENT_0xP19P18',['../MAX6956_8h.html#aa84fef4207af57fddf6468ae84ebd829',1,'MAX6956.h']]], - ['max6956_5fra_5fcurrent_5f0xp21p20',['MAX6956_RA_CURRENT_0xP21P20',['../MAX6956_8h.html#a11974f06951fb9051f9dd1d154d7c530',1,'MAX6956.h']]], - ['max6956_5fra_5fcurrent_5f0xp23p22',['MAX6956_RA_CURRENT_0xP23P22',['../MAX6956_8h.html#aa971a2bb392832476e3b91970f7fffe7',1,'MAX6956.h']]], - ['max6956_5fra_5fcurrent_5f0xp25p24',['MAX6956_RA_CURRENT_0xP25P24',['../MAX6956_8h.html#a040daea6fe73e819adcbcaed7cd3ceaf',1,'MAX6956.h']]], - ['max6956_5fra_5fcurrent_5f0xp27p26',['MAX6956_RA_CURRENT_0xP27P26',['../MAX6956_8h.html#ac5e5f779975977348022381487c2dfa2',1,'MAX6956.h']]], - ['max6956_5fra_5fcurrent_5f0xp29p28',['MAX6956_RA_CURRENT_0xP29P28',['../MAX6956_8h.html#a32623717f92442a1acfd42cdd3253302',1,'MAX6956.h']]], - ['max6956_5fra_5fcurrent_5f0xp31p30',['MAX6956_RA_CURRENT_0xP31P30',['../MAX6956_8h.html#a64f61d29f7ede042a397c21f33cf6124',1,'MAX6956.h']]], - ['max6956_5fra_5fcurrent_5f0xp5p4',['MAX6956_RA_CURRENT_0xP5P4',['../MAX6956_8h.html#adebbf4c1afdeb688bf5d3887b80c75b2',1,'MAX6956.h']]], - ['max6956_5fra_5fcurrent_5f0xp7p6',['MAX6956_RA_CURRENT_0xP7P6',['../MAX6956_8h.html#a42db4570a3f848d62f3f906a920161b6',1,'MAX6956.h']]], - ['max6956_5fra_5fcurrent_5f0xp9p8',['MAX6956_RA_CURRENT_0xP9P8',['../MAX6956_8h.html#a51eb40018dff593fa84c319832a1a957',1,'MAX6956.h']]], - ['max6956_5fra_5fdisplay_5ftest',['MAX6956_RA_DISPLAY_TEST',['../MAX6956_8h.html#a709a5193fd2aa9274997dfc22ef73a19',1,'MAX6956.h']]], - ['max6956_5fra_5fglobal_5fcurrent',['MAX6956_RA_GLOBAL_CURRENT',['../MAX6956_8h.html#a6a6c2bfe9bfbe4930731829baae7c8f6',1,'MAX6956.h']]], - ['max6956_5fra_5fno_5fop',['MAX6956_RA_NO_OP',['../MAX6956_8h.html#a0f205428de0679650e54dbe8250d57b4',1,'MAX6956.h']]], - ['max6956_5fra_5fport0',['MAX6956_RA_PORT0',['../MAX6956_8h.html#a7e8973b61716ae09a84b95ea2f2f5914',1,'MAX6956.h']]], - ['max6956_5fra_5fport1',['MAX6956_RA_PORT1',['../MAX6956_8h.html#a1e4fdb2886a119328bdd6807f3720eea',1,'MAX6956.h']]], - ['max6956_5fra_5fport10',['MAX6956_RA_PORT10',['../MAX6956_8h.html#a2528a76a2e91cd1dfd11b8aefda01473',1,'MAX6956.h']]], - ['max6956_5fra_5fport11',['MAX6956_RA_PORT11',['../MAX6956_8h.html#a3a6abf1d9e71015255d821419e3ffa5a',1,'MAX6956.h']]], - ['max6956_5fra_5fport12',['MAX6956_RA_PORT12',['../MAX6956_8h.html#a3c089b77cbd25ffa27e3cd46af415a9c',1,'MAX6956.h']]], - ['max6956_5fra_5fport13',['MAX6956_RA_PORT13',['../MAX6956_8h.html#a2d6ee01536f1fb0ec843479948141cbc',1,'MAX6956.h']]], - ['max6956_5fra_5fport14',['MAX6956_RA_PORT14',['../MAX6956_8h.html#aba5e5ff9b4aea95fedff9f6421c5f47c',1,'MAX6956.h']]], - ['max6956_5fra_5fport15',['MAX6956_RA_PORT15',['../MAX6956_8h.html#ad366a7c1b65fb3496f5b9ba392d6ba9c',1,'MAX6956.h']]], - ['max6956_5fra_5fport16',['MAX6956_RA_PORT16',['../MAX6956_8h.html#ac483e6007b4e6a780c14c7a78ff7a134',1,'MAX6956.h']]], - ['max6956_5fra_5fport17',['MAX6956_RA_PORT17',['../MAX6956_8h.html#ab6f3b8bbd8ac56bacf4a57691eb41aaf',1,'MAX6956.h']]], - ['max6956_5fra_5fport18',['MAX6956_RA_PORT18',['../MAX6956_8h.html#a082486ab9eace7838acd56b6ac6301df',1,'MAX6956.h']]], - ['max6956_5fra_5fport19',['MAX6956_RA_PORT19',['../MAX6956_8h.html#a04e65b34862a48ae022c994bbc5968dd',1,'MAX6956.h']]], - ['max6956_5fra_5fport2',['MAX6956_RA_PORT2',['../MAX6956_8h.html#ac4cc75132151b2f662b7c54128391187',1,'MAX6956.h']]], - ['max6956_5fra_5fport20',['MAX6956_RA_PORT20',['../MAX6956_8h.html#aed99f35f5ba961711c4e5bed769aa369',1,'MAX6956.h']]], - ['max6956_5fra_5fport21',['MAX6956_RA_PORT21',['../MAX6956_8h.html#a361dcd71b3da6c5fb57d33951c9e4c54',1,'MAX6956.h']]], - ['max6956_5fra_5fport22',['MAX6956_RA_PORT22',['../MAX6956_8h.html#a67c57767c9f6eda6124ff7368df4293b',1,'MAX6956.h']]], - ['max6956_5fra_5fport23',['MAX6956_RA_PORT23',['../MAX6956_8h.html#a29699b356f81b9fc971a29fc04e68a59',1,'MAX6956.h']]], - ['max6956_5fra_5fport24',['MAX6956_RA_PORT24',['../MAX6956_8h.html#ad053ff9eac065beaa10ad52dcc3d1e3e',1,'MAX6956.h']]], - ['max6956_5fra_5fport25',['MAX6956_RA_PORT25',['../MAX6956_8h.html#a367103a7d8364b916a70f37d0880e334',1,'MAX6956.h']]], - ['max6956_5fra_5fport26',['MAX6956_RA_PORT26',['../MAX6956_8h.html#ae0c19d326ab47406a138d4b66c601de0',1,'MAX6956.h']]], - ['max6956_5fra_5fport27',['MAX6956_RA_PORT27',['../MAX6956_8h.html#ae1219ad62d3ea1b3a86c52736d347618',1,'MAX6956.h']]], - ['max6956_5fra_5fport28',['MAX6956_RA_PORT28',['../MAX6956_8h.html#a07ff69092b95f43595762554c3e35329',1,'MAX6956.h']]], - ['max6956_5fra_5fport29',['MAX6956_RA_PORT29',['../MAX6956_8h.html#a6be82fa185d6c3dd272200727c15f4ac',1,'MAX6956.h']]], - ['max6956_5fra_5fport3',['MAX6956_RA_PORT3',['../MAX6956_8h.html#aa3e011deb16e7054e78e6f71ac33fcba',1,'MAX6956.h']]], - ['max6956_5fra_5fport30',['MAX6956_RA_PORT30',['../MAX6956_8h.html#a34c02dca8e8a97488eb0be51f682cf73',1,'MAX6956.h']]], - ['max6956_5fra_5fport31',['MAX6956_RA_PORT31',['../MAX6956_8h.html#a891d2a47a2fe5a4da056a7732fb6098b',1,'MAX6956.h']]], - ['max6956_5fra_5fport4',['MAX6956_RA_PORT4',['../MAX6956_8h.html#a68339cee27681486c99dabf398f487a0',1,'MAX6956.h']]], - ['max6956_5fra_5fport5',['MAX6956_RA_PORT5',['../MAX6956_8h.html#a92c4653a42f8400a30aa13a60dbc056f',1,'MAX6956.h']]], - ['max6956_5fra_5fport6',['MAX6956_RA_PORT6',['../MAX6956_8h.html#a5af96fba8e40466303a2bcec16df6c6f',1,'MAX6956.h']]], - ['max6956_5fra_5fport7',['MAX6956_RA_PORT7',['../MAX6956_8h.html#a20de98d6d2102960000a70b4bcf6007c',1,'MAX6956.h']]], - ['max6956_5fra_5fport8',['MAX6956_RA_PORT8',['../MAX6956_8h.html#ad0ea7dd1027b558df290150b664b0222',1,'MAX6956.h']]], - ['max6956_5fra_5fport9',['MAX6956_RA_PORT9',['../MAX6956_8h.html#a7d31adbda8965d0d7df0c521571e135c',1,'MAX6956.h']]], - ['max6956_5fra_5fports10_5f17',['MAX6956_RA_PORTS10_17',['../MAX6956_8h.html#aa9837d30cb5f9c9badf20fe50ea3ba26',1,'MAX6956.h']]], - ['max6956_5fra_5fports11_5f18',['MAX6956_RA_PORTS11_18',['../MAX6956_8h.html#a40bf1528e6a7345e0aaa3b86869f3af3',1,'MAX6956.h']]], - ['max6956_5fra_5fports12_5f19',['MAX6956_RA_PORTS12_19',['../MAX6956_8h.html#ab3e1f8d0b913acae6d73f9b5b0d491ff',1,'MAX6956.h']]], - ['max6956_5fra_5fports13_5f20',['MAX6956_RA_PORTS13_20',['../MAX6956_8h.html#ad33d71fa8457fcdb444179768a6376e9',1,'MAX6956.h']]], - ['max6956_5fra_5fports14_5f21',['MAX6956_RA_PORTS14_21',['../MAX6956_8h.html#aeae655678f9a39b8a7f6e9de1a09c59e',1,'MAX6956.h']]], - ['max6956_5fra_5fports15_5f22',['MAX6956_RA_PORTS15_22',['../MAX6956_8h.html#a853b18f366e225131135f6576268a461',1,'MAX6956.h']]], - ['max6956_5fra_5fports16_5f23',['MAX6956_RA_PORTS16_23',['../MAX6956_8h.html#a39c1bb286953031fad9c101604d6f56e',1,'MAX6956.h']]], - ['max6956_5fra_5fports17_5f24',['MAX6956_RA_PORTS17_24',['../MAX6956_8h.html#a8a4536b80e588a3ed6bb2f487499efeb',1,'MAX6956.h']]], - ['max6956_5fra_5fports18_5f25',['MAX6956_RA_PORTS18_25',['../MAX6956_8h.html#a1ae324a27c0648b831978991a44ee33f',1,'MAX6956.h']]], - ['max6956_5fra_5fports19_5f26',['MAX6956_RA_PORTS19_26',['../MAX6956_8h.html#a981a54414024fdd2877704d4d242b748',1,'MAX6956.h']]], - ['max6956_5fra_5fports20_5f27',['MAX6956_RA_PORTS20_27',['../MAX6956_8h.html#abd2280465476a9e3cae302d5e9bf7b62',1,'MAX6956.h']]], - ['max6956_5fra_5fports21_5f28',['MAX6956_RA_PORTS21_28',['../MAX6956_8h.html#adfca6218829cec2697e0975fc7965008',1,'MAX6956.h']]], - ['max6956_5fra_5fports22_5f29',['MAX6956_RA_PORTS22_29',['../MAX6956_8h.html#aa190f6504c585b64f355ce45a24057f1',1,'MAX6956.h']]], - ['max6956_5fra_5fports23_5f30',['MAX6956_RA_PORTS23_30',['../MAX6956_8h.html#a9ae64dcdc091a17982f4888bcd7b1981',1,'MAX6956.h']]], - ['max6956_5fra_5fports24_5f31',['MAX6956_RA_PORTS24_31',['../MAX6956_8h.html#a5054da2b077f91e7f6106373a84476ed',1,'MAX6956.h']]], - ['max6956_5fra_5fports25_5f31',['MAX6956_RA_PORTS25_31',['../MAX6956_8h.html#a38a7fe545ab1b4ca108dabcef50d015f',1,'MAX6956.h']]], - ['max6956_5fra_5fports26_5f31',['MAX6956_RA_PORTS26_31',['../MAX6956_8h.html#ac804c8074d5a6baf79b0595415ae0679',1,'MAX6956.h']]], - ['max6956_5fra_5fports27_5f31',['MAX6956_RA_PORTS27_31',['../MAX6956_8h.html#a5307d28ebcae5028fc482c914eecf48f',1,'MAX6956.h']]], - ['max6956_5fra_5fports28_5f31',['MAX6956_RA_PORTS28_31',['../MAX6956_8h.html#a7554adf2b4214f33584001f4e7c81053',1,'MAX6956.h']]], - ['max6956_5fra_5fports29_5f31',['MAX6956_RA_PORTS29_31',['../MAX6956_8h.html#ab278f8cb075460b9318c029bca24e68a',1,'MAX6956.h']]], - ['max6956_5fra_5fports30_5f31',['MAX6956_RA_PORTS30_31',['../MAX6956_8h.html#ae5873266ac57220286709a468781c3ff',1,'MAX6956.h']]], - ['max6956_5fra_5fports31_5f31',['MAX6956_RA_PORTS31_31',['../MAX6956_8h.html#ad12b528f7fa63249d37126a8d4049aab',1,'MAX6956.h']]], - ['max6956_5fra_5fports4_5f10',['MAX6956_RA_PORTS4_10',['../MAX6956_8h.html#ac32650edffdebee3cfeb90c9daece88b',1,'MAX6956.h']]], - ['max6956_5fra_5fports4_5f11',['MAX6956_RA_PORTS4_11',['../MAX6956_8h.html#a4b0cc79ee765d2f477953a890b2f6209',1,'MAX6956.h']]], - ['max6956_5fra_5fports4_5f7',['MAX6956_RA_PORTS4_7',['../MAX6956_8h.html#a00bff40ca66a7c82b7093536c5047da4',1,'MAX6956.h']]], - ['max6956_5fra_5fports4_5f8',['MAX6956_RA_PORTS4_8',['../MAX6956_8h.html#a3d1cd4727f1748e42a0426c0b70d9c2c',1,'MAX6956.h']]], - ['max6956_5fra_5fports4_5f9',['MAX6956_RA_PORTS4_9',['../MAX6956_8h.html#ad1b71a2b24de60a4d0128576c0e1278b',1,'MAX6956.h']]], - ['max6956_5fra_5fports5_5f12',['MAX6956_RA_PORTS5_12',['../MAX6956_8h.html#a13b8eb94b73c20a02397e50c81bccb57',1,'MAX6956.h']]], - ['max6956_5fra_5fports6_5f13',['MAX6956_RA_PORTS6_13',['../MAX6956_8h.html#af01fef127c33b806d570f1d46a90362f',1,'MAX6956.h']]], - ['max6956_5fra_5fports7_5f14',['MAX6956_RA_PORTS7_14',['../MAX6956_8h.html#ae0f37de2a929dc6f37733c3f112e0fa7',1,'MAX6956.h']]], - ['max6956_5fra_5fports8_5f15',['MAX6956_RA_PORTS8_15',['../MAX6956_8h.html#ae2bd6458f4aa0271d7fb9c8c8fdd0e4f',1,'MAX6956.h']]], - ['max6956_5fra_5fports9_5f16',['MAX6956_RA_PORTS9_16',['../MAX6956_8h.html#aedb8b7ecadabaf8290ac1eacde7db918',1,'MAX6956.h']]], - ['max6956_5fra_5ftransition_5fdetect',['MAX6956_RA_TRANSITION_DETECT',['../MAX6956_8h.html#a4a2b4c395e47e0ec9ef49d3236b8a465',1,'MAX6956.h']]], - ['max6956_5ftransition_5fmask_5fbit',['MAX6956_TRANSITION_MASK_BIT',['../MAX6956_8h.html#abc801853bdfe66591265d04865aba78f',1,'MAX6956.h']]], - ['max6956_5ftransition_5fmask_5flength',['MAX6956_TRANSITION_MASK_LENGTH',['../MAX6956_8h.html#a332868e8a1596e785072ddb8c4a2b4c1',1,'MAX6956.h']]], - ['max6956_5ftransition_5fmask_5fport24_5fbit',['MAX6956_TRANSITION_MASK_PORT24_BIT',['../MAX6956_8h.html#a0a2eb488b9b8d16b5c076d25790ec28e',1,'MAX6956.h']]], - ['max6956_5ftransition_5fmask_5fport25_5fbit',['MAX6956_TRANSITION_MASK_PORT25_BIT',['../MAX6956_8h.html#a04d331f867fa51822f5910ce2b6b891c',1,'MAX6956.h']]], - ['max6956_5ftransition_5fmask_5fport26_5fbit',['MAX6956_TRANSITION_MASK_PORT26_BIT',['../MAX6956_8h.html#ac4f63f4afc199c41dd9b1445259b8d50',1,'MAX6956.h']]], - ['max6956_5ftransition_5fmask_5fport27_5fbit',['MAX6956_TRANSITION_MASK_PORT27_BIT',['../MAX6956_8h.html#a282091cda715bb27f96266f5ae22b492',1,'MAX6956.h']]], - ['max6956_5ftransition_5fmask_5fport28_5fbit',['MAX6956_TRANSITION_MASK_PORT28_BIT',['../MAX6956_8h.html#a927e5369f33337fdea8d89ccc3b3919d',1,'MAX6956.h']]], - ['max6956_5ftransition_5fmask_5fport29_5fbit',['MAX6956_TRANSITION_MASK_PORT29_BIT',['../MAX6956_8h.html#a74adf7234472da3287cb98af583750c9',1,'MAX6956.h']]], - ['max6956_5ftransition_5fmask_5fport30_5fbit',['MAX6956_TRANSITION_MASK_PORT30_BIT',['../MAX6956_8h.html#a0e7f62a1c7d77019ca8ca2c2511f2644',1,'MAX6956.h']]], - ['max6956_5ftransition_5fstatus_5fbit',['MAX6956_TRANSITION_STATUS_BIT',['../MAX6956_8h.html#a29bd01905e66b503151e6d9cdfb035a1',1,'MAX6956.h']]] -]; diff --git a/Arduino/MAX6956/html/search/all_70.html b/Arduino/MAX6956/html/search/all_70.html deleted file mode 100644 index a279cb2a..00000000 --- a/Arduino/MAX6956/html/search/all_70.html +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - -
-
Loading...
-
- -
Searching...
-
No Matches
- -
- - diff --git a/Arduino/MAX6956/html/search/all_70.js b/Arduino/MAX6956/html/search/all_70.js deleted file mode 100644 index 21d9faa9..00000000 --- a/Arduino/MAX6956/html/search/all_70.js +++ /dev/null @@ -1,10 +0,0 @@ -var searchData= -[ - ['portconfig',['portConfig',['../classMAX6956.html#a9799e7684546e3e9b24506d436586a09',1,'MAX6956']]], - ['portcurrentbit',['portCurrentBit',['../classMAX6956.html#ad3057b6b21ae712acb0129270da63334',1,'MAX6956']]], - ['portcurrentra',['portCurrentRA',['../classMAX6956.html#ab0d382db3afe7930d1b95311bfd90164',1,'MAX6956']]], - ['portsconfig',['portsConfig',['../classMAX6956.html#a8b915615042c5ef96fbf3a5c260d4716',1,'MAX6956']]], - ['portsstatus',['portsStatus',['../classMAX6956.html#ae8da9a65da74dce7eb907319b0198847',1,'MAX6956']]], - ['psarrayindex',['psArrayIndex',['../classMAX6956.html#a967e25fac00c0ab59be854289eb36353',1,'MAX6956']]], - ['psbitposition',['psBitPosition',['../classMAX6956.html#a92b5dc05a1483c49c150db13dcd1f283',1,'MAX6956']]] -]; diff --git a/Arduino/MAX6956/html/search/all_72.html b/Arduino/MAX6956/html/search/all_72.html deleted file mode 100644 index 315ac4f0..00000000 --- a/Arduino/MAX6956/html/search/all_72.html +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - -
-
Loading...
-
- -
Searching...
-
No Matches
- -
- - diff --git a/Arduino/MAX6956/html/search/all_72.js b/Arduino/MAX6956/html/search/all_72.js deleted file mode 100644 index 64daaea0..00000000 --- a/Arduino/MAX6956/html/search/all_72.js +++ /dev/null @@ -1,4 +0,0 @@ -var searchData= -[ - ['reset',['reset',['../classMAX6956.html#a3b9166eee826a876bbf29bc63b090fe7',1,'MAX6956']]] -]; diff --git a/Arduino/MAX6956/html/search/all_73.html b/Arduino/MAX6956/html/search/all_73.html deleted file mode 100644 index 09f8ce8b..00000000 --- a/Arduino/MAX6956/html/search/all_73.html +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - -
-
Loading...
-
- -
Searching...
-
No Matches
- -
- - diff --git a/Arduino/MAX6956/html/search/all_73.js b/Arduino/MAX6956/html/search/all_73.js deleted file mode 100644 index 74b221f6..00000000 --- a/Arduino/MAX6956/html/search/all_73.js +++ /dev/null @@ -1,13 +0,0 @@ -var searchData= -[ - ['setallportscurrent',['setAllPortsCurrent',['../classMAX6956.html#a9a27a32611fa05766946c33850510644',1,'MAX6956']]], - ['setconfigreg',['setConfigReg',['../classMAX6956.html#ad06b9ed9f6e18f81d8379a6e10391ea4',1,'MAX6956']]], - ['setenableindividualcurrent',['setEnableIndividualCurrent',['../classMAX6956.html#a35bc5701a290409144929e640cad1748',1,'MAX6956']]], - ['setenabletransitiondetection',['setEnableTransitionDetection',['../classMAX6956.html#a67b65b80e09a3225dd4f6413bfab2844',1,'MAX6956']]], - ['setglobalcurrent',['setGlobalCurrent',['../classMAX6956.html#a4669dcc0f2f89f8fe73a0fa9b97dae21',1,'MAX6956']]], - ['setinputmask',['setInputMask',['../classMAX6956.html#a7ce45652fb0490af0ecb4eaebc230419',1,'MAX6956']]], - ['setportcurrent',['setPortCurrent',['../classMAX6956.html#a76a617f3b8982bb3855c5152b480097a',1,'MAX6956']]], - ['setportlevel',['setPortLevel',['../classMAX6956.html#a98fa3831a47355fe0856caa74a9cf810',1,'MAX6956']]], - ['setpower',['setPower',['../classMAX6956.html#ae10ac505e3857d31ca3823225983a697',1,'MAX6956']]], - ['settestmode',['setTestMode',['../classMAX6956.html#ad1b4e5cafd91acd2be2b6fb8197afef0',1,'MAX6956']]] -]; diff --git a/Arduino/MAX6956/html/search/all_74.html b/Arduino/MAX6956/html/search/all_74.html deleted file mode 100644 index c2cd0954..00000000 --- a/Arduino/MAX6956/html/search/all_74.html +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - -
-
Loading...
-
- -
Searching...
-
No Matches
- -
- - diff --git a/Arduino/MAX6956/html/search/all_74.js b/Arduino/MAX6956/html/search/all_74.js deleted file mode 100644 index fb321603..00000000 --- a/Arduino/MAX6956/html/search/all_74.js +++ /dev/null @@ -1,5 +0,0 @@ -var searchData= -[ - ['testconnection',['testConnection',['../classMAX6956.html#a60bd352328d77e59a4d51a3c55d38a25',1,'MAX6956']]], - ['togglepower',['togglePower',['../classMAX6956.html#a993f35d31d1f2489f9d2965c3886f848',1,'MAX6956']]] -]; diff --git a/Arduino/MAX6956/html/search/classes_6d.html b/Arduino/MAX6956/html/search/classes_6d.html deleted file mode 100644 index aa835903..00000000 --- a/Arduino/MAX6956/html/search/classes_6d.html +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - -
-
Loading...
-
- -
Searching...
-
No Matches
- -
- - diff --git a/Arduino/MAX6956/html/search/classes_6d.js b/Arduino/MAX6956/html/search/classes_6d.js deleted file mode 100644 index b2ca9eca..00000000 --- a/Arduino/MAX6956/html/search/classes_6d.js +++ /dev/null @@ -1,4 +0,0 @@ -var searchData= -[ - ['max6956',['MAX6956',['../classMAX6956.html',1,'']]] -]; diff --git a/Arduino/MAX6956/html/search/close.png b/Arduino/MAX6956/html/search/close.png deleted file mode 100644 index 9342d3dfeea7b7c4ee610987e717804b5a42ceb9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 273 zcmV+s0q*{ZP)4(RlMby96)VwnbG{ zbe&}^BDn7x>$<{ck4zAK-=nT;=hHG)kmplIF${xqm8db3oX6wT3bvp`TE@m0cg;b) zBuSL}5?N7O(iZLdAlz@)b)Rd~DnSsSX&P5qC`XwuFwcAYLC+d2>+1(8on;wpt8QIC X2MT$R4iQDd00000NkvXXu0mjfia~GN diff --git a/Arduino/MAX6956/html/search/defines_6d.html b/Arduino/MAX6956/html/search/defines_6d.html deleted file mode 100644 index 5c949e4a..00000000 --- a/Arduino/MAX6956/html/search/defines_6d.html +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - -
-
Loading...
-
- -
Searching...
-
No Matches
- -
- - diff --git a/Arduino/MAX6956/html/search/defines_6d.js b/Arduino/MAX6956/html/search/defines_6d.js deleted file mode 100644 index 468186e0..00000000 --- a/Arduino/MAX6956/html/search/defines_6d.js +++ /dev/null @@ -1,171 +0,0 @@ -var searchData= -[ - ['max6956_5faddress',['MAX6956_ADDRESS',['../MAX6956_8h.html#a33e60623a4c5b483d4604fe2c9b91be7',1,'MAX6956.h']]], - ['max6956_5fconfig_5fglobal_5fcurrent_5fbit',['MAX6956_CONFIG_GLOBAL_CURRENT_BIT',['../MAX6956_8h.html#a4288d838d55461c66c0ba2e904f588a7',1,'MAX6956.h']]], - ['max6956_5fconfig_5fpower_5fbit',['MAX6956_CONFIG_POWER_BIT',['../MAX6956_8h.html#a03faf0490eddbb2f0405616ad6ac4052',1,'MAX6956.h']]], - ['max6956_5fconfig_5ftransition_5fbit',['MAX6956_CONFIG_TRANSITION_BIT',['../MAX6956_8h.html#af1d61c00ae2e56dd5e7f04dc4b0c1663',1,'MAX6956.h']]], - ['max6956_5fcurrent_5f0',['MAX6956_CURRENT_0',['../MAX6956_8h.html#a930221b73d0e7327ffce1e3072ed69e3',1,'MAX6956.h']]], - ['max6956_5fcurrent_5f1',['MAX6956_CURRENT_1',['../MAX6956_8h.html#afd6a3c0f560b7b7190805416e1ad00f5',1,'MAX6956.h']]], - ['max6956_5fcurrent_5f10',['MAX6956_CURRENT_10',['../MAX6956_8h.html#a62f09fbe807ce97d3558748808ed3a11',1,'MAX6956.h']]], - ['max6956_5fcurrent_5f11',['MAX6956_CURRENT_11',['../MAX6956_8h.html#a5b97f8927dd861189567ad1fda6d692a',1,'MAX6956.h']]], - ['max6956_5fcurrent_5f12',['MAX6956_CURRENT_12',['../MAX6956_8h.html#a8fb88850c74ecc2080971984c817b860',1,'MAX6956.h']]], - ['max6956_5fcurrent_5f13',['MAX6956_CURRENT_13',['../MAX6956_8h.html#a8bfeeb7d88d4284dec7174b65724877d',1,'MAX6956.h']]], - ['max6956_5fcurrent_5f14',['MAX6956_CURRENT_14',['../MAX6956_8h.html#aad136273ced9dea0ef4a8821f4a5f368',1,'MAX6956.h']]], - ['max6956_5fcurrent_5f15',['MAX6956_CURRENT_15',['../MAX6956_8h.html#a4c0ac1cc939ecfb7992dac2834521eb6',1,'MAX6956.h']]], - ['max6956_5fcurrent_5f2',['MAX6956_CURRENT_2',['../MAX6956_8h.html#ab7558038e4f723efa4b406e988a93990',1,'MAX6956.h']]], - ['max6956_5fcurrent_5f3',['MAX6956_CURRENT_3',['../MAX6956_8h.html#a8b8800a153cf4869a6c4d399f8d46035',1,'MAX6956.h']]], - ['max6956_5fcurrent_5f4',['MAX6956_CURRENT_4',['../MAX6956_8h.html#a2678f20d0e18e036e13ff5f422fcf609',1,'MAX6956.h']]], - ['max6956_5fcurrent_5f5',['MAX6956_CURRENT_5',['../MAX6956_8h.html#af808e1e791b9a640d6b6c62cb145f169',1,'MAX6956.h']]], - ['max6956_5fcurrent_5f6',['MAX6956_CURRENT_6',['../MAX6956_8h.html#a0c97726477caef4c0f54eb1beaffbdff',1,'MAX6956.h']]], - ['max6956_5fcurrent_5f7',['MAX6956_CURRENT_7',['../MAX6956_8h.html#a55c66763c65c8554d12a71a4c20e35a6',1,'MAX6956.h']]], - ['max6956_5fcurrent_5f8',['MAX6956_CURRENT_8',['../MAX6956_8h.html#a11c425ee14938c667e63e7df4cf8afa2',1,'MAX6956.h']]], - ['max6956_5fcurrent_5f9',['MAX6956_CURRENT_9',['../MAX6956_8h.html#a4da9aedd07982408005da31fda78463a',1,'MAX6956.h']]], - ['max6956_5fdefault_5faddress',['MAX6956_DEFAULT_ADDRESS',['../MAX6956_8h.html#a4ca90873afdfdacaa730ed5db53e2f5b',1,'MAX6956.h']]], - ['max6956_5fdisplay_5ftest_5fbit',['MAX6956_DISPLAY_TEST_BIT',['../MAX6956_8h.html#a7e110f7b5949bf63dd7c5b4e9a59a5b0',1,'MAX6956.h']]], - ['max6956_5fglobal_5fcurrent_5fbit',['MAX6956_GLOBAL_CURRENT_BIT',['../MAX6956_8h.html#a85368204ba368978f814d46d81335c35',1,'MAX6956.h']]], - ['max6956_5fglobal_5fcurrent_5flength',['MAX6956_GLOBAL_CURRENT_LENGTH',['../MAX6956_8h.html#afbcb8bf5ecc4e5afada48446f8dac809',1,'MAX6956.h']]], - ['max6956_5finput_5fw_5fpull',['MAX6956_INPUT_W_PULL',['../MAX6956_8h.html#a68fc1bc750b7959fbab7e64f79589b83',1,'MAX6956.h']]], - ['max6956_5finput_5fwo_5fpull',['MAX6956_INPUT_WO_PULL',['../MAX6956_8h.html#ab05f3186e2515bab3a536ad9f1cbb7db',1,'MAX6956.h']]], - ['max6956_5foff',['MAX6956_OFF',['../MAX6956_8h.html#a003fe60fa8da81e67da2ad7900d1196f',1,'MAX6956.h']]], - ['max6956_5fon',['MAX6956_ON',['../MAX6956_8h.html#a4e151161e190a9f45aebfd712064b034',1,'MAX6956.h']]], - ['max6956_5foutput_5fgpio',['MAX6956_OUTPUT_GPIO',['../MAX6956_8h.html#a27f6ca524d4c18623762c722d9993c10',1,'MAX6956.h']]], - ['max6956_5foutput_5fled',['MAX6956_OUTPUT_LED',['../MAX6956_8h.html#ad6490a909085059c4300a51dcebbf7bc',1,'MAX6956.h']]], - ['max6956_5fport12_5fcurrent_5fbit',['MAX6956_PORT12_CURRENT_BIT',['../MAX6956_8h.html#ae1cb8088b95a2e19f293dbeee7ef7892',1,'MAX6956.h']]], - ['max6956_5fport12_5fcurrent_5flength',['MAX6956_PORT12_CURRENT_LENGTH',['../MAX6956_8h.html#a8b0c452aa9a3f66de931d4a226f865e6',1,'MAX6956.h']]], - ['max6956_5fport13_5fcurrent_5fbit',['MAX6956_PORT13_CURRENT_BIT',['../MAX6956_8h.html#a0c413303648e14359c311fb9478cfce7',1,'MAX6956.h']]], - ['max6956_5fport13_5fcurrent_5flength',['MAX6956_PORT13_CURRENT_LENGTH',['../MAX6956_8h.html#abaee1f6920a6a6770468cb7def42bff7',1,'MAX6956.h']]], - ['max6956_5fport14_5fcurrent_5fbit',['MAX6956_PORT14_CURRENT_BIT',['../MAX6956_8h.html#a0fcb35fa292905862765e99dd03e63b2',1,'MAX6956.h']]], - ['max6956_5fport14_5fcurrent_5flength',['MAX6956_PORT14_CURRENT_LENGTH',['../MAX6956_8h.html#aa98b4176c22631122a00948e5a54e91f',1,'MAX6956.h']]], - ['max6956_5fport15_5fcurrent_5fbit',['MAX6956_PORT15_CURRENT_BIT',['../MAX6956_8h.html#a659a1777dac35a14930720029b786aed',1,'MAX6956.h']]], - ['max6956_5fport15_5fcurrent_5flength',['MAX6956_PORT15_CURRENT_LENGTH',['../MAX6956_8h.html#ab377c2d0463246bfc66c9df01087285d',1,'MAX6956.h']]], - ['max6956_5fport16_5fcurrent_5fbit',['MAX6956_PORT16_CURRENT_BIT',['../MAX6956_8h.html#a977fb8ce0e696e764ae098dce361e446',1,'MAX6956.h']]], - ['max6956_5fport16_5fcurrent_5flength',['MAX6956_PORT16_CURRENT_LENGTH',['../MAX6956_8h.html#a04c2dcf166214a43fbdd9ae5f7a0ca00',1,'MAX6956.h']]], - ['max6956_5fport17_5fcurrent_5fbit',['MAX6956_PORT17_CURRENT_BIT',['../MAX6956_8h.html#ab59b7f618ff0788a6bd21313bf14673f',1,'MAX6956.h']]], - ['max6956_5fport17_5fcurrent_5flength',['MAX6956_PORT17_CURRENT_LENGTH',['../MAX6956_8h.html#adf0428deb9192d621f837d7951e539be',1,'MAX6956.h']]], - ['max6956_5fport18_5fcurrent_5fbit',['MAX6956_PORT18_CURRENT_BIT',['../MAX6956_8h.html#ab0d4c28bc6747482ab33a027fd93b5d7',1,'MAX6956.h']]], - ['max6956_5fport18_5fcurrent_5flength',['MAX6956_PORT18_CURRENT_LENGTH',['../MAX6956_8h.html#a9bb781fca7fadebb28918c05d2f1605c',1,'MAX6956.h']]], - ['max6956_5fport19_5fcurrent_5fbit',['MAX6956_PORT19_CURRENT_BIT',['../MAX6956_8h.html#aea0128f7b979e68785b78cfc7e480a32',1,'MAX6956.h']]], - ['max6956_5fport19_5fcurrent_5flength',['MAX6956_PORT19_CURRENT_LENGTH',['../MAX6956_8h.html#a5c2f25a82e8b442abb28a9544a3d4088',1,'MAX6956.h']]], - ['max6956_5fport21_5fcurrent_5fbit',['MAX6956_PORT21_CURRENT_BIT',['../MAX6956_8h.html#abd855e00543729cc87ab4a48e3d98649',1,'MAX6956.h']]], - ['max6956_5fport21_5fcurrent_5flength',['MAX6956_PORT21_CURRENT_LENGTH',['../MAX6956_8h.html#a65cd02d7f498266b224c035a3809126a',1,'MAX6956.h']]], - ['max6956_5fport22_5fcurrent_5fbit',['MAX6956_PORT22_CURRENT_BIT',['../MAX6956_8h.html#a061947a1484a8449fd4301a1022cafe5',1,'MAX6956.h']]], - ['max6956_5fport22_5fcurrent_5flength',['MAX6956_PORT22_CURRENT_LENGTH',['../MAX6956_8h.html#aa64238ebb3bf6d8ee2d0d368992e7613',1,'MAX6956.h']]], - ['max6956_5fport23_5fcurrent_5fbit',['MAX6956_PORT23_CURRENT_BIT',['../MAX6956_8h.html#a95789ffe1e677c75090556342763c6ac',1,'MAX6956_PORT23_CURRENT_BIT(): MAX6956.h'],['../MAX6956_8h.html#a95789ffe1e677c75090556342763c6ac',1,'MAX6956_PORT23_CURRENT_BIT(): MAX6956.h']]], - ['max6956_5fport23_5fcurrent_5flength',['MAX6956_PORT23_CURRENT_LENGTH',['../MAX6956_8h.html#a0f492bea7bf9e0906ba13f447327d5a8',1,'MAX6956_PORT23_CURRENT_LENGTH(): MAX6956.h'],['../MAX6956_8h.html#a0f492bea7bf9e0906ba13f447327d5a8',1,'MAX6956_PORT23_CURRENT_LENGTH(): MAX6956.h']]], - ['max6956_5fport24_5fcurrent_5fbit',['MAX6956_PORT24_CURRENT_BIT',['../MAX6956_8h.html#a50e41ea8c3ec1bb3d55e5a4eb03563a2',1,'MAX6956.h']]], - ['max6956_5fport24_5fcurrent_5flength',['MAX6956_PORT24_CURRENT_LENGTH',['../MAX6956_8h.html#a11ee583606d04516bc2fc5812b05cd3d',1,'MAX6956.h']]], - ['max6956_5fport25_5fcurrent_5fbit',['MAX6956_PORT25_CURRENT_BIT',['../MAX6956_8h.html#a75f6b93cf7558a38adba5bb4a91d05f8',1,'MAX6956.h']]], - ['max6956_5fport25_5fcurrent_5flength',['MAX6956_PORT25_CURRENT_LENGTH',['../MAX6956_8h.html#a3b1a7a5f82da6b43bd5a24d2297a2f75',1,'MAX6956.h']]], - ['max6956_5fport26_5fcurrent_5fbit',['MAX6956_PORT26_CURRENT_BIT',['../MAX6956_8h.html#abd400d2f356832d21b1787e2501a8644',1,'MAX6956.h']]], - ['max6956_5fport26_5fcurrent_5flength',['MAX6956_PORT26_CURRENT_LENGTH',['../MAX6956_8h.html#a28bf5ca7da83928eeec3f4f302d12c45',1,'MAX6956.h']]], - ['max6956_5fport27_5fcurrent_5fbit',['MAX6956_PORT27_CURRENT_BIT',['../MAX6956_8h.html#a62bf02cd8e4d8a9dfa975d0e319f68f5',1,'MAX6956.h']]], - ['max6956_5fport27_5fcurrent_5flength',['MAX6956_PORT27_CURRENT_LENGTH',['../MAX6956_8h.html#a0a0f99c166b5a60d7e6c6c7d99306b45',1,'MAX6956.h']]], - ['max6956_5fport28_5fcurrent_5fbit',['MAX6956_PORT28_CURRENT_BIT',['../MAX6956_8h.html#ab6135c4105c3b39625e7361a438e1511',1,'MAX6956.h']]], - ['max6956_5fport28_5fcurrent_5flength',['MAX6956_PORT28_CURRENT_LENGTH',['../MAX6956_8h.html#ac2bcdc199d348dba281a4371675bd428',1,'MAX6956.h']]], - ['max6956_5fport29_5fcurrent_5fbit',['MAX6956_PORT29_CURRENT_BIT',['../MAX6956_8h.html#ae98448e4aa991d16d9b1d9d6071078d8',1,'MAX6956.h']]], - ['max6956_5fport29_5fcurrent_5flength',['MAX6956_PORT29_CURRENT_LENGTH',['../MAX6956_8h.html#a6b0d8a1c63777d016e1cb22076b91377',1,'MAX6956.h']]], - ['max6956_5fport31_5fcurrent_5fbit',['MAX6956_PORT31_CURRENT_BIT',['../MAX6956_8h.html#a1cdbea93ca621e5fc4c747286bdf90e1',1,'MAX6956.h']]], - ['max6956_5fport31_5fcurrent_5flength',['MAX6956_PORT31_CURRENT_LENGTH',['../MAX6956_8h.html#a40a075605dfcfc2736aab5ffa10e3e2c',1,'MAX6956.h']]], - ['max6956_5fport33_5fcurrent_5fbit',['MAX6956_PORT33_CURRENT_BIT',['../MAX6956_8h.html#aa5acefc0723ea8d2b804aa7eccae705b',1,'MAX6956.h']]], - ['max6956_5fport33_5fcurrent_5flength',['MAX6956_PORT33_CURRENT_LENGTH',['../MAX6956_8h.html#a2fb02a7e77abefcbf7c194ff6b994ae9',1,'MAX6956.h']]], - ['max6956_5fra_5fconfig_5fp11p10p9p8',['MAX6956_RA_CONFIG_P11P10P9P8',['../MAX6956_8h.html#a3a2fa6f7cc985cfeea00ebd1dd64ae8c',1,'MAX6956.h']]], - ['max6956_5fra_5fconfig_5fp15p14p13p12',['MAX6956_RA_CONFIG_P15P14P13P12',['../MAX6956_8h.html#a119a0a92d4ccdb0e8f27fd565b1220bd',1,'MAX6956.h']]], - ['max6956_5fra_5fconfig_5fp19p18p17p16',['MAX6956_RA_CONFIG_P19P18P17P16',['../MAX6956_8h.html#a8f199d21b14cf933d5093d3001d0400d',1,'MAX6956.h']]], - ['max6956_5fra_5fconfig_5fp23p22p21p20',['MAX6956_RA_CONFIG_P23P22P21P20',['../MAX6956_8h.html#a025ce0245fb957ef58afc5f4920e19f3',1,'MAX6956.h']]], - ['max6956_5fra_5fconfig_5fp27p26p25p24',['MAX6956_RA_CONFIG_P27P26P25P24',['../MAX6956_8h.html#a4e813aab18cbd7462e1ac5a59b0a53ab',1,'MAX6956.h']]], - ['max6956_5fra_5fconfig_5fp31p30p29p28',['MAX6956_RA_CONFIG_P31P30P29P28',['../MAX6956_8h.html#a98b5c2d8359fbb7e07eb2eade7e8870a',1,'MAX6956.h']]], - ['max6956_5fra_5fconfig_5fp7p6p5p4',['MAX6956_RA_CONFIG_P7P6P5P4',['../MAX6956_8h.html#a1c4db4957c22f8767b2f1a06e5cb9a32',1,'MAX6956.h']]], - ['max6956_5fra_5fconfiguration',['MAX6956_RA_CONFIGURATION',['../MAX6956_8h.html#a5c3d1c00491596887e211bfa630c1b94',1,'MAX6956.h']]], - ['max6956_5fra_5fcurrent_5f0xp11p10',['MAX6956_RA_CURRENT_0xP11P10',['../MAX6956_8h.html#aa2304dec8420451a881876948e1cba43',1,'MAX6956.h']]], - ['max6956_5fra_5fcurrent_5f0xp13p12',['MAX6956_RA_CURRENT_0xP13P12',['../MAX6956_8h.html#add5533d08bfa791cf8cf95d7dd3f16d3',1,'MAX6956.h']]], - ['max6956_5fra_5fcurrent_5f0xp15p14',['MAX6956_RA_CURRENT_0xP15P14',['../MAX6956_8h.html#ae51b720b2bd4868c1986e2d314822778',1,'MAX6956.h']]], - ['max6956_5fra_5fcurrent_5f0xp17p16',['MAX6956_RA_CURRENT_0xP17P16',['../MAX6956_8h.html#a77820b1e4acee07a338e179ab35a7836',1,'MAX6956.h']]], - ['max6956_5fra_5fcurrent_5f0xp19p18',['MAX6956_RA_CURRENT_0xP19P18',['../MAX6956_8h.html#aa84fef4207af57fddf6468ae84ebd829',1,'MAX6956.h']]], - ['max6956_5fra_5fcurrent_5f0xp21p20',['MAX6956_RA_CURRENT_0xP21P20',['../MAX6956_8h.html#a11974f06951fb9051f9dd1d154d7c530',1,'MAX6956.h']]], - ['max6956_5fra_5fcurrent_5f0xp23p22',['MAX6956_RA_CURRENT_0xP23P22',['../MAX6956_8h.html#aa971a2bb392832476e3b91970f7fffe7',1,'MAX6956.h']]], - ['max6956_5fra_5fcurrent_5f0xp25p24',['MAX6956_RA_CURRENT_0xP25P24',['../MAX6956_8h.html#a040daea6fe73e819adcbcaed7cd3ceaf',1,'MAX6956.h']]], - ['max6956_5fra_5fcurrent_5f0xp27p26',['MAX6956_RA_CURRENT_0xP27P26',['../MAX6956_8h.html#ac5e5f779975977348022381487c2dfa2',1,'MAX6956.h']]], - ['max6956_5fra_5fcurrent_5f0xp29p28',['MAX6956_RA_CURRENT_0xP29P28',['../MAX6956_8h.html#a32623717f92442a1acfd42cdd3253302',1,'MAX6956.h']]], - ['max6956_5fra_5fcurrent_5f0xp31p30',['MAX6956_RA_CURRENT_0xP31P30',['../MAX6956_8h.html#a64f61d29f7ede042a397c21f33cf6124',1,'MAX6956.h']]], - ['max6956_5fra_5fcurrent_5f0xp5p4',['MAX6956_RA_CURRENT_0xP5P4',['../MAX6956_8h.html#adebbf4c1afdeb688bf5d3887b80c75b2',1,'MAX6956.h']]], - ['max6956_5fra_5fcurrent_5f0xp7p6',['MAX6956_RA_CURRENT_0xP7P6',['../MAX6956_8h.html#a42db4570a3f848d62f3f906a920161b6',1,'MAX6956.h']]], - ['max6956_5fra_5fcurrent_5f0xp9p8',['MAX6956_RA_CURRENT_0xP9P8',['../MAX6956_8h.html#a51eb40018dff593fa84c319832a1a957',1,'MAX6956.h']]], - ['max6956_5fra_5fdisplay_5ftest',['MAX6956_RA_DISPLAY_TEST',['../MAX6956_8h.html#a709a5193fd2aa9274997dfc22ef73a19',1,'MAX6956.h']]], - ['max6956_5fra_5fglobal_5fcurrent',['MAX6956_RA_GLOBAL_CURRENT',['../MAX6956_8h.html#a6a6c2bfe9bfbe4930731829baae7c8f6',1,'MAX6956.h']]], - ['max6956_5fra_5fno_5fop',['MAX6956_RA_NO_OP',['../MAX6956_8h.html#a0f205428de0679650e54dbe8250d57b4',1,'MAX6956.h']]], - ['max6956_5fra_5fport0',['MAX6956_RA_PORT0',['../MAX6956_8h.html#a7e8973b61716ae09a84b95ea2f2f5914',1,'MAX6956.h']]], - ['max6956_5fra_5fport1',['MAX6956_RA_PORT1',['../MAX6956_8h.html#a1e4fdb2886a119328bdd6807f3720eea',1,'MAX6956.h']]], - ['max6956_5fra_5fport10',['MAX6956_RA_PORT10',['../MAX6956_8h.html#a2528a76a2e91cd1dfd11b8aefda01473',1,'MAX6956.h']]], - ['max6956_5fra_5fport11',['MAX6956_RA_PORT11',['../MAX6956_8h.html#a3a6abf1d9e71015255d821419e3ffa5a',1,'MAX6956.h']]], - ['max6956_5fra_5fport12',['MAX6956_RA_PORT12',['../MAX6956_8h.html#a3c089b77cbd25ffa27e3cd46af415a9c',1,'MAX6956.h']]], - ['max6956_5fra_5fport13',['MAX6956_RA_PORT13',['../MAX6956_8h.html#a2d6ee01536f1fb0ec843479948141cbc',1,'MAX6956.h']]], - ['max6956_5fra_5fport14',['MAX6956_RA_PORT14',['../MAX6956_8h.html#aba5e5ff9b4aea95fedff9f6421c5f47c',1,'MAX6956.h']]], - ['max6956_5fra_5fport15',['MAX6956_RA_PORT15',['../MAX6956_8h.html#ad366a7c1b65fb3496f5b9ba392d6ba9c',1,'MAX6956.h']]], - ['max6956_5fra_5fport16',['MAX6956_RA_PORT16',['../MAX6956_8h.html#ac483e6007b4e6a780c14c7a78ff7a134',1,'MAX6956.h']]], - ['max6956_5fra_5fport17',['MAX6956_RA_PORT17',['../MAX6956_8h.html#ab6f3b8bbd8ac56bacf4a57691eb41aaf',1,'MAX6956.h']]], - ['max6956_5fra_5fport18',['MAX6956_RA_PORT18',['../MAX6956_8h.html#a082486ab9eace7838acd56b6ac6301df',1,'MAX6956.h']]], - ['max6956_5fra_5fport19',['MAX6956_RA_PORT19',['../MAX6956_8h.html#a04e65b34862a48ae022c994bbc5968dd',1,'MAX6956.h']]], - ['max6956_5fra_5fport2',['MAX6956_RA_PORT2',['../MAX6956_8h.html#ac4cc75132151b2f662b7c54128391187',1,'MAX6956.h']]], - ['max6956_5fra_5fport20',['MAX6956_RA_PORT20',['../MAX6956_8h.html#aed99f35f5ba961711c4e5bed769aa369',1,'MAX6956.h']]], - ['max6956_5fra_5fport21',['MAX6956_RA_PORT21',['../MAX6956_8h.html#a361dcd71b3da6c5fb57d33951c9e4c54',1,'MAX6956.h']]], - ['max6956_5fra_5fport22',['MAX6956_RA_PORT22',['../MAX6956_8h.html#a67c57767c9f6eda6124ff7368df4293b',1,'MAX6956.h']]], - ['max6956_5fra_5fport23',['MAX6956_RA_PORT23',['../MAX6956_8h.html#a29699b356f81b9fc971a29fc04e68a59',1,'MAX6956.h']]], - ['max6956_5fra_5fport24',['MAX6956_RA_PORT24',['../MAX6956_8h.html#ad053ff9eac065beaa10ad52dcc3d1e3e',1,'MAX6956.h']]], - ['max6956_5fra_5fport25',['MAX6956_RA_PORT25',['../MAX6956_8h.html#a367103a7d8364b916a70f37d0880e334',1,'MAX6956.h']]], - ['max6956_5fra_5fport26',['MAX6956_RA_PORT26',['../MAX6956_8h.html#ae0c19d326ab47406a138d4b66c601de0',1,'MAX6956.h']]], - ['max6956_5fra_5fport27',['MAX6956_RA_PORT27',['../MAX6956_8h.html#ae1219ad62d3ea1b3a86c52736d347618',1,'MAX6956.h']]], - ['max6956_5fra_5fport28',['MAX6956_RA_PORT28',['../MAX6956_8h.html#a07ff69092b95f43595762554c3e35329',1,'MAX6956.h']]], - ['max6956_5fra_5fport29',['MAX6956_RA_PORT29',['../MAX6956_8h.html#a6be82fa185d6c3dd272200727c15f4ac',1,'MAX6956.h']]], - ['max6956_5fra_5fport3',['MAX6956_RA_PORT3',['../MAX6956_8h.html#aa3e011deb16e7054e78e6f71ac33fcba',1,'MAX6956.h']]], - ['max6956_5fra_5fport30',['MAX6956_RA_PORT30',['../MAX6956_8h.html#a34c02dca8e8a97488eb0be51f682cf73',1,'MAX6956.h']]], - ['max6956_5fra_5fport31',['MAX6956_RA_PORT31',['../MAX6956_8h.html#a891d2a47a2fe5a4da056a7732fb6098b',1,'MAX6956.h']]], - ['max6956_5fra_5fport4',['MAX6956_RA_PORT4',['../MAX6956_8h.html#a68339cee27681486c99dabf398f487a0',1,'MAX6956.h']]], - ['max6956_5fra_5fport5',['MAX6956_RA_PORT5',['../MAX6956_8h.html#a92c4653a42f8400a30aa13a60dbc056f',1,'MAX6956.h']]], - ['max6956_5fra_5fport6',['MAX6956_RA_PORT6',['../MAX6956_8h.html#a5af96fba8e40466303a2bcec16df6c6f',1,'MAX6956.h']]], - ['max6956_5fra_5fport7',['MAX6956_RA_PORT7',['../MAX6956_8h.html#a20de98d6d2102960000a70b4bcf6007c',1,'MAX6956.h']]], - ['max6956_5fra_5fport8',['MAX6956_RA_PORT8',['../MAX6956_8h.html#ad0ea7dd1027b558df290150b664b0222',1,'MAX6956.h']]], - ['max6956_5fra_5fport9',['MAX6956_RA_PORT9',['../MAX6956_8h.html#a7d31adbda8965d0d7df0c521571e135c',1,'MAX6956.h']]], - ['max6956_5fra_5fports10_5f17',['MAX6956_RA_PORTS10_17',['../MAX6956_8h.html#aa9837d30cb5f9c9badf20fe50ea3ba26',1,'MAX6956.h']]], - ['max6956_5fra_5fports11_5f18',['MAX6956_RA_PORTS11_18',['../MAX6956_8h.html#a40bf1528e6a7345e0aaa3b86869f3af3',1,'MAX6956.h']]], - ['max6956_5fra_5fports12_5f19',['MAX6956_RA_PORTS12_19',['../MAX6956_8h.html#ab3e1f8d0b913acae6d73f9b5b0d491ff',1,'MAX6956.h']]], - ['max6956_5fra_5fports13_5f20',['MAX6956_RA_PORTS13_20',['../MAX6956_8h.html#ad33d71fa8457fcdb444179768a6376e9',1,'MAX6956.h']]], - ['max6956_5fra_5fports14_5f21',['MAX6956_RA_PORTS14_21',['../MAX6956_8h.html#aeae655678f9a39b8a7f6e9de1a09c59e',1,'MAX6956.h']]], - ['max6956_5fra_5fports15_5f22',['MAX6956_RA_PORTS15_22',['../MAX6956_8h.html#a853b18f366e225131135f6576268a461',1,'MAX6956.h']]], - ['max6956_5fra_5fports16_5f23',['MAX6956_RA_PORTS16_23',['../MAX6956_8h.html#a39c1bb286953031fad9c101604d6f56e',1,'MAX6956.h']]], - ['max6956_5fra_5fports17_5f24',['MAX6956_RA_PORTS17_24',['../MAX6956_8h.html#a8a4536b80e588a3ed6bb2f487499efeb',1,'MAX6956.h']]], - ['max6956_5fra_5fports18_5f25',['MAX6956_RA_PORTS18_25',['../MAX6956_8h.html#a1ae324a27c0648b831978991a44ee33f',1,'MAX6956.h']]], - ['max6956_5fra_5fports19_5f26',['MAX6956_RA_PORTS19_26',['../MAX6956_8h.html#a981a54414024fdd2877704d4d242b748',1,'MAX6956.h']]], - ['max6956_5fra_5fports20_5f27',['MAX6956_RA_PORTS20_27',['../MAX6956_8h.html#abd2280465476a9e3cae302d5e9bf7b62',1,'MAX6956.h']]], - ['max6956_5fra_5fports21_5f28',['MAX6956_RA_PORTS21_28',['../MAX6956_8h.html#adfca6218829cec2697e0975fc7965008',1,'MAX6956.h']]], - ['max6956_5fra_5fports22_5f29',['MAX6956_RA_PORTS22_29',['../MAX6956_8h.html#aa190f6504c585b64f355ce45a24057f1',1,'MAX6956.h']]], - ['max6956_5fra_5fports23_5f30',['MAX6956_RA_PORTS23_30',['../MAX6956_8h.html#a9ae64dcdc091a17982f4888bcd7b1981',1,'MAX6956.h']]], - ['max6956_5fra_5fports24_5f31',['MAX6956_RA_PORTS24_31',['../MAX6956_8h.html#a5054da2b077f91e7f6106373a84476ed',1,'MAX6956.h']]], - ['max6956_5fra_5fports25_5f31',['MAX6956_RA_PORTS25_31',['../MAX6956_8h.html#a38a7fe545ab1b4ca108dabcef50d015f',1,'MAX6956.h']]], - ['max6956_5fra_5fports26_5f31',['MAX6956_RA_PORTS26_31',['../MAX6956_8h.html#ac804c8074d5a6baf79b0595415ae0679',1,'MAX6956.h']]], - ['max6956_5fra_5fports27_5f31',['MAX6956_RA_PORTS27_31',['../MAX6956_8h.html#a5307d28ebcae5028fc482c914eecf48f',1,'MAX6956.h']]], - ['max6956_5fra_5fports28_5f31',['MAX6956_RA_PORTS28_31',['../MAX6956_8h.html#a7554adf2b4214f33584001f4e7c81053',1,'MAX6956.h']]], - ['max6956_5fra_5fports29_5f31',['MAX6956_RA_PORTS29_31',['../MAX6956_8h.html#ab278f8cb075460b9318c029bca24e68a',1,'MAX6956.h']]], - ['max6956_5fra_5fports30_5f31',['MAX6956_RA_PORTS30_31',['../MAX6956_8h.html#ae5873266ac57220286709a468781c3ff',1,'MAX6956.h']]], - ['max6956_5fra_5fports31_5f31',['MAX6956_RA_PORTS31_31',['../MAX6956_8h.html#ad12b528f7fa63249d37126a8d4049aab',1,'MAX6956.h']]], - ['max6956_5fra_5fports4_5f10',['MAX6956_RA_PORTS4_10',['../MAX6956_8h.html#ac32650edffdebee3cfeb90c9daece88b',1,'MAX6956.h']]], - ['max6956_5fra_5fports4_5f11',['MAX6956_RA_PORTS4_11',['../MAX6956_8h.html#a4b0cc79ee765d2f477953a890b2f6209',1,'MAX6956.h']]], - ['max6956_5fra_5fports4_5f7',['MAX6956_RA_PORTS4_7',['../MAX6956_8h.html#a00bff40ca66a7c82b7093536c5047da4',1,'MAX6956.h']]], - ['max6956_5fra_5fports4_5f8',['MAX6956_RA_PORTS4_8',['../MAX6956_8h.html#a3d1cd4727f1748e42a0426c0b70d9c2c',1,'MAX6956.h']]], - ['max6956_5fra_5fports4_5f9',['MAX6956_RA_PORTS4_9',['../MAX6956_8h.html#ad1b71a2b24de60a4d0128576c0e1278b',1,'MAX6956.h']]], - ['max6956_5fra_5fports5_5f12',['MAX6956_RA_PORTS5_12',['../MAX6956_8h.html#a13b8eb94b73c20a02397e50c81bccb57',1,'MAX6956.h']]], - ['max6956_5fra_5fports6_5f13',['MAX6956_RA_PORTS6_13',['../MAX6956_8h.html#af01fef127c33b806d570f1d46a90362f',1,'MAX6956.h']]], - ['max6956_5fra_5fports7_5f14',['MAX6956_RA_PORTS7_14',['../MAX6956_8h.html#ae0f37de2a929dc6f37733c3f112e0fa7',1,'MAX6956.h']]], - ['max6956_5fra_5fports8_5f15',['MAX6956_RA_PORTS8_15',['../MAX6956_8h.html#ae2bd6458f4aa0271d7fb9c8c8fdd0e4f',1,'MAX6956.h']]], - ['max6956_5fra_5fports9_5f16',['MAX6956_RA_PORTS9_16',['../MAX6956_8h.html#aedb8b7ecadabaf8290ac1eacde7db918',1,'MAX6956.h']]], - ['max6956_5fra_5ftransition_5fdetect',['MAX6956_RA_TRANSITION_DETECT',['../MAX6956_8h.html#a4a2b4c395e47e0ec9ef49d3236b8a465',1,'MAX6956.h']]], - ['max6956_5ftransition_5fmask_5fbit',['MAX6956_TRANSITION_MASK_BIT',['../MAX6956_8h.html#abc801853bdfe66591265d04865aba78f',1,'MAX6956.h']]], - ['max6956_5ftransition_5fmask_5flength',['MAX6956_TRANSITION_MASK_LENGTH',['../MAX6956_8h.html#a332868e8a1596e785072ddb8c4a2b4c1',1,'MAX6956.h']]], - ['max6956_5ftransition_5fmask_5fport24_5fbit',['MAX6956_TRANSITION_MASK_PORT24_BIT',['../MAX6956_8h.html#a0a2eb488b9b8d16b5c076d25790ec28e',1,'MAX6956.h']]], - ['max6956_5ftransition_5fmask_5fport25_5fbit',['MAX6956_TRANSITION_MASK_PORT25_BIT',['../MAX6956_8h.html#a04d331f867fa51822f5910ce2b6b891c',1,'MAX6956.h']]], - ['max6956_5ftransition_5fmask_5fport26_5fbit',['MAX6956_TRANSITION_MASK_PORT26_BIT',['../MAX6956_8h.html#ac4f63f4afc199c41dd9b1445259b8d50',1,'MAX6956.h']]], - ['max6956_5ftransition_5fmask_5fport27_5fbit',['MAX6956_TRANSITION_MASK_PORT27_BIT',['../MAX6956_8h.html#a282091cda715bb27f96266f5ae22b492',1,'MAX6956.h']]], - ['max6956_5ftransition_5fmask_5fport28_5fbit',['MAX6956_TRANSITION_MASK_PORT28_BIT',['../MAX6956_8h.html#a927e5369f33337fdea8d89ccc3b3919d',1,'MAX6956.h']]], - ['max6956_5ftransition_5fmask_5fport29_5fbit',['MAX6956_TRANSITION_MASK_PORT29_BIT',['../MAX6956_8h.html#a74adf7234472da3287cb98af583750c9',1,'MAX6956.h']]], - ['max6956_5ftransition_5fmask_5fport30_5fbit',['MAX6956_TRANSITION_MASK_PORT30_BIT',['../MAX6956_8h.html#a0e7f62a1c7d77019ca8ca2c2511f2644',1,'MAX6956.h']]], - ['max6956_5ftransition_5fstatus_5fbit',['MAX6956_TRANSITION_STATUS_BIT',['../MAX6956_8h.html#a29bd01905e66b503151e6d9cdfb035a1',1,'MAX6956.h']]] -]; diff --git a/Arduino/MAX6956/html/search/files_6d.html b/Arduino/MAX6956/html/search/files_6d.html deleted file mode 100644 index 6fdcbe37..00000000 --- a/Arduino/MAX6956/html/search/files_6d.html +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - -
-
Loading...
-
- -
Searching...
-
No Matches
- -
- - diff --git a/Arduino/MAX6956/html/search/files_6d.js b/Arduino/MAX6956/html/search/files_6d.js deleted file mode 100644 index 76d89075..00000000 --- a/Arduino/MAX6956/html/search/files_6d.js +++ /dev/null @@ -1,5 +0,0 @@ -var searchData= -[ - ['max6956_2ecpp',['MAX6956.cpp',['../MAX6956_8cpp.html',1,'']]], - ['max6956_2eh',['MAX6956.h',['../MAX6956_8h.html',1,'']]] -]; diff --git a/Arduino/MAX6956/html/search/functions_63.html b/Arduino/MAX6956/html/search/functions_63.html deleted file mode 100644 index 98924d8a..00000000 --- a/Arduino/MAX6956/html/search/functions_63.html +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - -
-
Loading...
-
- -
Searching...
-
No Matches
- -
- - diff --git a/Arduino/MAX6956/html/search/functions_63.js b/Arduino/MAX6956/html/search/functions_63.js deleted file mode 100644 index 6abd3d20..00000000 --- a/Arduino/MAX6956/html/search/functions_63.js +++ /dev/null @@ -1,6 +0,0 @@ -var searchData= -[ - ['configallports',['configAllPorts',['../classMAX6956.html#a9e9f11c46bdc86d8e882ed8bb5efabdf',1,'MAX6956']]], - ['configport',['configPort',['../classMAX6956.html#a5e05bead41c585c68de79bbfed971d19',1,'MAX6956']]], - ['configports',['configPorts',['../classMAX6956.html#a400393e30fbe196aef43d8edea890228',1,'MAX6956']]] -]; diff --git a/Arduino/MAX6956/html/search/functions_64.html b/Arduino/MAX6956/html/search/functions_64.html deleted file mode 100644 index bcfb550b..00000000 --- a/Arduino/MAX6956/html/search/functions_64.html +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - -
-
Loading...
-
- -
Searching...
-
No Matches
- -
- - diff --git a/Arduino/MAX6956/html/search/functions_64.js b/Arduino/MAX6956/html/search/functions_64.js deleted file mode 100644 index 3d8d8d03..00000000 --- a/Arduino/MAX6956/html/search/functions_64.js +++ /dev/null @@ -1,4 +0,0 @@ -var searchData= -[ - ['disableallports',['disableAllPorts',['../classMAX6956.html#a93a81ff86316f63ee1ada3529da2a95b',1,'MAX6956']]] -]; diff --git a/Arduino/MAX6956/html/search/functions_65.html b/Arduino/MAX6956/html/search/functions_65.html deleted file mode 100644 index f81fa7b6..00000000 --- a/Arduino/MAX6956/html/search/functions_65.html +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - -
-
Loading...
-
- -
Searching...
-
No Matches
- -
- - diff --git a/Arduino/MAX6956/html/search/functions_65.js b/Arduino/MAX6956/html/search/functions_65.js deleted file mode 100644 index 25d17ecc..00000000 --- a/Arduino/MAX6956/html/search/functions_65.js +++ /dev/null @@ -1,4 +0,0 @@ -var searchData= -[ - ['enableallports',['enableAllPorts',['../classMAX6956.html#a51a47c1f69532e96c6caa357889004e3',1,'MAX6956']]] -]; diff --git a/Arduino/MAX6956/html/search/functions_67.html b/Arduino/MAX6956/html/search/functions_67.html deleted file mode 100644 index 39cc96de..00000000 --- a/Arduino/MAX6956/html/search/functions_67.html +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - -
-
Loading...
-
- -
Searching...
-
No Matches
- -
- - diff --git a/Arduino/MAX6956/html/search/functions_67.js b/Arduino/MAX6956/html/search/functions_67.js deleted file mode 100644 index 400e6433..00000000 --- a/Arduino/MAX6956/html/search/functions_67.js +++ /dev/null @@ -1,10 +0,0 @@ -var searchData= -[ - ['getconfigreg',['getConfigReg',['../classMAX6956.html#a5e787204b3f7bf8750376f5bdf77a971',1,'MAX6956']]], - ['getenableindividualcurrent',['getEnableIndividualCurrent',['../classMAX6956.html#abcfe81dd0ffc90284f19503b6366dcfb',1,'MAX6956']]], - ['getenabletransitiondetection',['getEnableTransitionDetection',['../classMAX6956.html#a76e9ab35769854b3e4224499897601ec',1,'MAX6956']]], - ['getglobalcurrent',['getGlobalCurrent',['../classMAX6956.html#a1926760b263588314fd759d129091940',1,'MAX6956']]], - ['getinputmask',['getInputMask',['../classMAX6956.html#a56245915d7d4cd8fd34629bd91695147',1,'MAX6956']]], - ['getpower',['getPower',['../classMAX6956.html#acdc18c36735d8015651d4e3c75da4300',1,'MAX6956']]], - ['gettestmode',['getTestMode',['../classMAX6956.html#ad4f99f08d1cf08c5a0097215e680a80a',1,'MAX6956']]] -]; diff --git a/Arduino/MAX6956/html/search/functions_69.html b/Arduino/MAX6956/html/search/functions_69.html deleted file mode 100644 index 954ac84b..00000000 --- a/Arduino/MAX6956/html/search/functions_69.html +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - -
-
Loading...
-
- -
Searching...
-
No Matches
- -
- - diff --git a/Arduino/MAX6956/html/search/functions_69.js b/Arduino/MAX6956/html/search/functions_69.js deleted file mode 100644 index 47c8e9d4..00000000 --- a/Arduino/MAX6956/html/search/functions_69.js +++ /dev/null @@ -1,4 +0,0 @@ -var searchData= -[ - ['initialize',['initialize',['../classMAX6956.html#ad63e927adc2427b4b661f2422ddd40d8',1,'MAX6956']]] -]; diff --git a/Arduino/MAX6956/html/search/functions_6d.html b/Arduino/MAX6956/html/search/functions_6d.html deleted file mode 100644 index f721e116..00000000 --- a/Arduino/MAX6956/html/search/functions_6d.html +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - -
-
Loading...
-
- -
Searching...
-
No Matches
- -
- - diff --git a/Arduino/MAX6956/html/search/functions_6d.js b/Arduino/MAX6956/html/search/functions_6d.js deleted file mode 100644 index 87049491..00000000 --- a/Arduino/MAX6956/html/search/functions_6d.js +++ /dev/null @@ -1,4 +0,0 @@ -var searchData= -[ - ['max6956',['MAX6956',['../classMAX6956.html#a210d9e95978d61357db757cb80475bde',1,'MAX6956::MAX6956()'],['../classMAX6956.html#a1a7b33190871a09d81c5bec741b645b7',1,'MAX6956::MAX6956(uint8_t address)']]] -]; diff --git a/Arduino/MAX6956/html/search/functions_72.html b/Arduino/MAX6956/html/search/functions_72.html deleted file mode 100644 index de10844f..00000000 --- a/Arduino/MAX6956/html/search/functions_72.html +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - -
-
Loading...
-
- -
Searching...
-
No Matches
- -
- - diff --git a/Arduino/MAX6956/html/search/functions_72.js b/Arduino/MAX6956/html/search/functions_72.js deleted file mode 100644 index 64daaea0..00000000 --- a/Arduino/MAX6956/html/search/functions_72.js +++ /dev/null @@ -1,4 +0,0 @@ -var searchData= -[ - ['reset',['reset',['../classMAX6956.html#a3b9166eee826a876bbf29bc63b090fe7',1,'MAX6956']]] -]; diff --git a/Arduino/MAX6956/html/search/functions_73.html b/Arduino/MAX6956/html/search/functions_73.html deleted file mode 100644 index a8952453..00000000 --- a/Arduino/MAX6956/html/search/functions_73.html +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - -
-
Loading...
-
- -
Searching...
-
No Matches
- -
- - diff --git a/Arduino/MAX6956/html/search/functions_73.js b/Arduino/MAX6956/html/search/functions_73.js deleted file mode 100644 index 74b221f6..00000000 --- a/Arduino/MAX6956/html/search/functions_73.js +++ /dev/null @@ -1,13 +0,0 @@ -var searchData= -[ - ['setallportscurrent',['setAllPortsCurrent',['../classMAX6956.html#a9a27a32611fa05766946c33850510644',1,'MAX6956']]], - ['setconfigreg',['setConfigReg',['../classMAX6956.html#ad06b9ed9f6e18f81d8379a6e10391ea4',1,'MAX6956']]], - ['setenableindividualcurrent',['setEnableIndividualCurrent',['../classMAX6956.html#a35bc5701a290409144929e640cad1748',1,'MAX6956']]], - ['setenabletransitiondetection',['setEnableTransitionDetection',['../classMAX6956.html#a67b65b80e09a3225dd4f6413bfab2844',1,'MAX6956']]], - ['setglobalcurrent',['setGlobalCurrent',['../classMAX6956.html#a4669dcc0f2f89f8fe73a0fa9b97dae21',1,'MAX6956']]], - ['setinputmask',['setInputMask',['../classMAX6956.html#a7ce45652fb0490af0ecb4eaebc230419',1,'MAX6956']]], - ['setportcurrent',['setPortCurrent',['../classMAX6956.html#a76a617f3b8982bb3855c5152b480097a',1,'MAX6956']]], - ['setportlevel',['setPortLevel',['../classMAX6956.html#a98fa3831a47355fe0856caa74a9cf810',1,'MAX6956']]], - ['setpower',['setPower',['../classMAX6956.html#ae10ac505e3857d31ca3823225983a697',1,'MAX6956']]], - ['settestmode',['setTestMode',['../classMAX6956.html#ad1b4e5cafd91acd2be2b6fb8197afef0',1,'MAX6956']]] -]; diff --git a/Arduino/MAX6956/html/search/functions_74.html b/Arduino/MAX6956/html/search/functions_74.html deleted file mode 100644 index 8b138f02..00000000 --- a/Arduino/MAX6956/html/search/functions_74.html +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - -
-
Loading...
-
- -
Searching...
-
No Matches
- -
- - diff --git a/Arduino/MAX6956/html/search/functions_74.js b/Arduino/MAX6956/html/search/functions_74.js deleted file mode 100644 index fb321603..00000000 --- a/Arduino/MAX6956/html/search/functions_74.js +++ /dev/null @@ -1,5 +0,0 @@ -var searchData= -[ - ['testconnection',['testConnection',['../classMAX6956.html#a60bd352328d77e59a4d51a3c55d38a25',1,'MAX6956']]], - ['togglepower',['togglePower',['../classMAX6956.html#a993f35d31d1f2489f9d2965c3886f848',1,'MAX6956']]] -]; diff --git a/Arduino/MAX6956/html/search/mag_sel.png b/Arduino/MAX6956/html/search/mag_sel.png deleted file mode 100644 index 81f6040a2092402b4d98f9ffa8855d12a0d4ca17..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 563 zcmV-30?hr1P)zxx&tqG15pu7)IiiXFflOc2k;dXd>%13GZAy? zRz!q0=|E6a6vV)&ZBS~G9oe0kbqyw1*gvY`{Pop2oKq#FlzgXt@Xh-7fxh>}`Fxg> z$%N%{$!4=5nM{(;=c!aG1Ofr^Do{u%Ih{^&Fc@H2)+a-?TBXrw5DW&z%Nb6mQ!L9O zl}b@6mB?f=tX3;#vl)}ggh(Vpyh(IK z(Mb0D{l{U$FsRjP;!{($+bsaaVi8T#1c0V#qEIOCYa9@UVLV`f__E81L;?WEaRA;Y zUH;rZ;vb;mk7JX|$=i3O~&If0O@oZfLg8gfIjW=dcBsz;gI=!{-r4# z4%6v$&~;q^j7Fo67yJ(NJWuX+I~I!tj^nW3?}^9bq|<3^+vapS5sgM^x7!cs(+mMT z&y%j};&~po+YO)3hoUH4E*E;e9>?R6SS&`X)p`njycAVcg{rEb41T{~Hk(bl-7eSb zmFxA2uIqo#@R?lKm50ND`~6Nfn|-b1|L6O98vt3Tx@gKz#isxO002ovPDHLkV1kyW B_l^Jn diff --git a/Arduino/MAX6956/html/search/nomatches.html b/Arduino/MAX6956/html/search/nomatches.html deleted file mode 100644 index b1ded27e..00000000 --- a/Arduino/MAX6956/html/search/nomatches.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - -
-
No Matches
-
- - diff --git a/Arduino/MAX6956/html/search/search.css b/Arduino/MAX6956/html/search/search.css deleted file mode 100644 index 4d7612ff..00000000 --- a/Arduino/MAX6956/html/search/search.css +++ /dev/null @@ -1,271 +0,0 @@ -/*---------------- Search Box */ - -#FSearchBox { - float: left; -} - -#MSearchBox { - white-space : nowrap; - position: absolute; - float: none; - display: inline; - margin-top: 8px; - right: 0px; - width: 170px; - z-index: 102; - background-color: white; -} - -#MSearchBox .left -{ - display:block; - position:absolute; - left:10px; - width:20px; - height:19px; - background:url('http://github.com/search_l.png') no-repeat; - background-position:right; -} - -#MSearchSelect { - display:block; - position:absolute; - width:20px; - height:19px; -} - -.left #MSearchSelect { - left:4px; -} - -.right #MSearchSelect { - right:5px; -} - -#MSearchField { - display:block; - position:absolute; - height:19px; - background:url('http://github.com/search_m.png') repeat-x; - border:none; - width:111px; - margin-left:20px; - padding-left:4px; - color: #909090; - outline: none; - font: 9pt Arial, Verdana, sans-serif; -} - -#FSearchBox #MSearchField { - margin-left:15px; -} - -#MSearchBox .right { - display:block; - position:absolute; - right:10px; - top:0px; - width:20px; - height:19px; - background:url('http://github.com/search_r.png') no-repeat; - background-position:left; -} - -#MSearchClose { - display: none; - position: absolute; - top: 4px; - background : none; - border: none; - margin: 0px 4px 0px 0px; - padding: 0px 0px; - outline: none; -} - -.left #MSearchClose { - left: 6px; -} - -.right #MSearchClose { - right: 2px; -} - -.MSearchBoxActive #MSearchField { - color: #000000; -} - -/*---------------- Search filter selection */ - -#MSearchSelectWindow { - display: none; - position: absolute; - left: 0; top: 0; - border: 1px solid #90A5CE; - background-color: #F9FAFC; - z-index: 1; - padding-top: 4px; - padding-bottom: 4px; - -moz-border-radius: 4px; - -webkit-border-top-left-radius: 4px; - -webkit-border-top-right-radius: 4px; - -webkit-border-bottom-left-radius: 4px; - -webkit-border-bottom-right-radius: 4px; - -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); -} - -.SelectItem { - font: 8pt Arial, Verdana, sans-serif; - padding-left: 2px; - padding-right: 12px; - border: 0px; -} - -span.SelectionMark { - margin-right: 4px; - font-family: monospace; - outline-style: none; - text-decoration: none; -} - -a.SelectItem { - display: block; - outline-style: none; - color: #000000; - text-decoration: none; - padding-left: 6px; - padding-right: 12px; -} - -a.SelectItem:focus, -a.SelectItem:active { - color: #000000; - outline-style: none; - text-decoration: none; -} - -a.SelectItem:hover { - color: #FFFFFF; - background-color: #3D578C; - outline-style: none; - text-decoration: none; - cursor: pointer; - display: block; -} - -/*---------------- Search results window */ - -iframe#MSearchResults { - width: 60ex; - height: 15em; -} - -#MSearchResultsWindow { - display: none; - position: absolute; - left: 0; top: 0; - border: 1px solid #000; - background-color: #EEF1F7; -} - -/* ----------------------------------- */ - - -#SRIndex { - clear:both; - padding-bottom: 15px; -} - -.SREntry { - font-size: 10pt; - padding-left: 1ex; -} - -.SRPage .SREntry { - font-size: 8pt; - padding: 1px 5px; -} - -body.SRPage { - margin: 5px 2px; -} - -.SRChildren { - padding-left: 3ex; padding-bottom: .5em -} - -.SRPage .SRChildren { - display: none; -} - -.SRSymbol { - font-weight: bold; - color: #425E97; - font-family: Arial, Verdana, sans-serif; - text-decoration: none; - outline: none; -} - -a.SRScope { - display: block; - color: #425E97; - font-family: Arial, Verdana, sans-serif; - text-decoration: none; - outline: none; -} - -a.SRSymbol:focus, a.SRSymbol:active, -a.SRScope:focus, a.SRScope:active { - text-decoration: underline; -} - -span.SRScope { - padding-left: 4px; -} - -.SRPage .SRStatus { - padding: 2px 5px; - font-size: 8pt; - font-style: italic; -} - -.SRResult { - display: none; -} - -DIV.searchresults { - margin-left: 10px; - margin-right: 10px; -} - -/*---------------- External search page results */ - -.searchresult { - background-color: #F0F3F8; -} - -.pages b { - color: white; - padding: 5px 5px 3px 5px; - background-image: url("http://github.com/tab_a.png"); - background-repeat: repeat-x; - text-shadow: 0 1px 1px #000000; -} - -.pages { - line-height: 17px; - margin-left: 4px; - text-decoration: none; -} - -.hl { - font-weight: bold; -} - -#searchresults { - margin-bottom: 20px; -} - -.searchpages { - margin-top: 10px; -} - diff --git a/Arduino/MAX6956/html/search/search.js b/Arduino/MAX6956/html/search/search.js deleted file mode 100644 index 223ccae5..00000000 --- a/Arduino/MAX6956/html/search/search.js +++ /dev/null @@ -1,805 +0,0 @@ -// Search script generated by doxygen -// Copyright (C) 2009 by Dimitri van Heesch. - -// The code in this file is loosly based on main.js, part of Natural Docs, -// which is Copyright (C) 2003-2008 Greg Valure -// Natural Docs is licensed under the GPL. - -var indexSectionsWithContent = -{ - 0: "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011110101000100101110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - 1: "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - 2: "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - 3: "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001110101000100001110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - 4: "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010100000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - 5: "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" -}; - -var indexSectionNames = -{ - 0: "all", - 1: "classes", - 2: "files", - 3: "functions", - 4: "variables", - 5: "defines" -}; - -function convertToId(search) -{ - var result = ''; - for (i=0;i do a search - { - this.Search(); - } - } - - this.OnSearchSelectKey = function(evt) - { - var e = (evt) ? evt : window.event; // for IE - if (e.keyCode==40 && this.searchIndex0) // Up - { - this.searchIndex--; - this.OnSelectItem(this.searchIndex); - } - else if (e.keyCode==13 || e.keyCode==27) - { - this.OnSelectItem(this.searchIndex); - this.CloseSelectionWindow(); - this.DOMSearchField().focus(); - } - return false; - } - - // --------- Actions - - // Closes the results window. - this.CloseResultsWindow = function() - { - this.DOMPopupSearchResultsWindow().style.display = 'none'; - this.DOMSearchClose().style.display = 'none'; - this.Activate(false); - } - - this.CloseSelectionWindow = function() - { - this.DOMSearchSelectWindow().style.display = 'none'; - } - - // Performs a search. - this.Search = function() - { - this.keyTimeout = 0; - - // strip leading whitespace - var searchValue = this.DOMSearchField().value.replace(/^ +/, ""); - - var code = searchValue.toLowerCase().charCodeAt(0); - var hexCode; - if (code<16) - { - hexCode="0"+code.toString(16); - } - else - { - hexCode=code.toString(16); - } - - var resultsPage; - var resultsPageWithSearch; - var hasResultsPage; - - if (indexSectionsWithContent[this.searchIndex].charAt(code) == '1') - { - resultsPage = this.resultsPath + '/' + indexSectionNames[this.searchIndex] + '_' + hexCode + '.html'; - resultsPageWithSearch = resultsPage+'?'+escape(searchValue); - hasResultsPage = true; - } - else // nothing available for this search term - { - resultsPage = this.resultsPath + '/nomatches.html'; - resultsPageWithSearch = resultsPage; - hasResultsPage = false; - } - - window.frames.MSearchResults.location = resultsPageWithSearch; - var domPopupSearchResultsWindow = this.DOMPopupSearchResultsWindow(); - - if (domPopupSearchResultsWindow.style.display!='block') - { - var domSearchBox = this.DOMSearchBox(); - this.DOMSearchClose().style.display = 'inline'; - if (this.insideFrame) - { - var domPopupSearchResults = this.DOMPopupSearchResults(); - domPopupSearchResultsWindow.style.position = 'relative'; - domPopupSearchResultsWindow.style.display = 'block'; - var width = document.body.clientWidth - 8; // the -8 is for IE :-( - domPopupSearchResultsWindow.style.width = width + 'px'; - domPopupSearchResults.style.width = width + 'px'; - } - else - { - var domPopupSearchResults = this.DOMPopupSearchResults(); - var left = getXPos(domSearchBox) + 150; // domSearchBox.offsetWidth; - var top = getYPos(domSearchBox) + 20; // domSearchBox.offsetHeight + 1; - domPopupSearchResultsWindow.style.display = 'block'; - left -= domPopupSearchResults.offsetWidth; - domPopupSearchResultsWindow.style.top = top + 'px'; - domPopupSearchResultsWindow.style.left = left + 'px'; - } - } - - this.lastSearchValue = searchValue; - this.lastResultsPage = resultsPage; - } - - // -------- Activation Functions - - // Activates or deactivates the search panel, resetting things to - // their default values if necessary. - this.Activate = function(isActive) - { - if (isActive || // open it - this.DOMPopupSearchResultsWindow().style.display == 'block' - ) - { - this.DOMSearchBox().className = 'MSearchBoxActive'; - - var searchField = this.DOMSearchField(); - - if (searchField.value == this.searchLabel) // clear "Search" term upon entry - { - searchField.value = ''; - this.searchActive = true; - } - } - else if (!isActive) // directly remove the panel - { - this.DOMSearchBox().className = 'MSearchBoxInactive'; - this.DOMSearchField().value = this.searchLabel; - this.searchActive = false; - this.lastSearchValue = '' - this.lastResultsPage = ''; - } - } -} - -// ----------------------------------------------------------------------- - -// The class that handles everything on the search results page. -function SearchResults(name) -{ - // The number of matches from the last run of . - this.lastMatchCount = 0; - this.lastKey = 0; - this.repeatOn = false; - - // Toggles the visibility of the passed element ID. - this.FindChildElement = function(id) - { - var parentElement = document.getElementById(id); - var element = parentElement.firstChild; - - while (element && element!=parentElement) - { - if (element.nodeName == 'DIV' && element.className == 'SRChildren') - { - return element; - } - - if (element.nodeName == 'DIV' && element.hasChildNodes()) - { - element = element.firstChild; - } - else if (element.nextSibling) - { - element = element.nextSibling; - } - else - { - do - { - element = element.parentNode; - } - while (element && element!=parentElement && !element.nextSibling); - - if (element && element!=parentElement) - { - element = element.nextSibling; - } - } - } - } - - this.Toggle = function(id) - { - var element = this.FindChildElement(id); - if (element) - { - if (element.style.display == 'block') - { - element.style.display = 'none'; - } - else - { - element.style.display = 'block'; - } - } - } - - // Searches for the passed string. If there is no parameter, - // it takes it from the URL query. - // - // Always returns true, since other documents may try to call it - // and that may or may not be possible. - this.Search = function(search) - { - if (!search) // get search word from URL - { - search = window.location.search; - search = search.substring(1); // Remove the leading '?' - search = unescape(search); - } - - search = search.replace(/^ +/, ""); // strip leading spaces - search = search.replace(/ +$/, ""); // strip trailing spaces - search = search.toLowerCase(); - search = convertToId(search); - - var resultRows = document.getElementsByTagName("div"); - var matches = 0; - - var i = 0; - while (i < resultRows.length) - { - var row = resultRows.item(i); - if (row.className == "SRResult") - { - var rowMatchName = row.id.toLowerCase(); - rowMatchName = rowMatchName.replace(/^sr\d*_/, ''); // strip 'sr123_' - - if (search.length<=rowMatchName.length && - rowMatchName.substr(0, search.length)==search) - { - row.style.display = 'block'; - matches++; - } - else - { - row.style.display = 'none'; - } - } - i++; - } - document.getElementById("Searching").style.display='none'; - if (matches == 0) // no results - { - document.getElementById("NoMatches").style.display='block'; - } - else // at least one result - { - document.getElementById("NoMatches").style.display='none'; - } - this.lastMatchCount = matches; - return true; - } - - // return the first item with index index or higher that is visible - this.NavNext = function(index) - { - var focusItem; - while (1) - { - var focusName = 'Item'+index; - focusItem = document.getElementById(focusName); - if (focusItem && focusItem.parentNode.parentNode.style.display=='block') - { - break; - } - else if (!focusItem) // last element - { - break; - } - focusItem=null; - index++; - } - return focusItem; - } - - this.NavPrev = function(index) - { - var focusItem; - while (1) - { - var focusName = 'Item'+index; - focusItem = document.getElementById(focusName); - if (focusItem && focusItem.parentNode.parentNode.style.display=='block') - { - break; - } - else if (!focusItem) // last element - { - break; - } - focusItem=null; - index--; - } - return focusItem; - } - - this.ProcessKeys = function(e) - { - if (e.type == "keydown") - { - this.repeatOn = false; - this.lastKey = e.keyCode; - } - else if (e.type == "keypress") - { - if (!this.repeatOn) - { - if (this.lastKey) this.repeatOn = true; - return false; // ignore first keypress after keydown - } - } - else if (e.type == "keyup") - { - this.lastKey = 0; - this.repeatOn = false; - } - return this.lastKey!=0; - } - - this.Nav = function(evt,itemIndex) - { - var e = (evt) ? evt : window.event; // for IE - if (e.keyCode==13) return true; - if (!this.ProcessKeys(e)) return false; - - if (this.lastKey==38) // Up - { - var newIndex = itemIndex-1; - var focusItem = this.NavPrev(newIndex); - if (focusItem) - { - var child = this.FindChildElement(focusItem.parentNode.parentNode.id); - if (child && child.style.display == 'block') // children visible - { - var n=0; - var tmpElem; - while (1) // search for last child - { - tmpElem = document.getElementById('Item'+newIndex+'_c'+n); - if (tmpElem) - { - focusItem = tmpElem; - } - else // found it! - { - break; - } - n++; - } - } - } - if (focusItem) - { - focusItem.focus(); - } - else // return focus to search field - { - parent.document.getElementById("MSearchField").focus(); - } - } - else if (this.lastKey==40) // Down - { - var newIndex = itemIndex+1; - var focusItem; - var item = document.getElementById('Item'+itemIndex); - var elem = this.FindChildElement(item.parentNode.parentNode.id); - if (elem && elem.style.display == 'block') // children visible - { - focusItem = document.getElementById('Item'+itemIndex+'_c0'); - } - if (!focusItem) focusItem = this.NavNext(newIndex); - if (focusItem) focusItem.focus(); - } - else if (this.lastKey==39) // Right - { - var item = document.getElementById('Item'+itemIndex); - var elem = this.FindChildElement(item.parentNode.parentNode.id); - if (elem) elem.style.display = 'block'; - } - else if (this.lastKey==37) // Left - { - var item = document.getElementById('Item'+itemIndex); - var elem = this.FindChildElement(item.parentNode.parentNode.id); - if (elem) elem.style.display = 'none'; - } - else if (this.lastKey==27) // Escape - { - parent.searchBox.CloseResultsWindow(); - parent.document.getElementById("MSearchField").focus(); - } - else if (this.lastKey==13) // Enter - { - return true; - } - return false; - } - - this.NavChild = function(evt,itemIndex,childIndex) - { - var e = (evt) ? evt : window.event; // for IE - if (e.keyCode==13) return true; - if (!this.ProcessKeys(e)) return false; - - if (this.lastKey==38) // Up - { - if (childIndex>0) - { - var newIndex = childIndex-1; - document.getElementById('Item'+itemIndex+'_c'+newIndex).focus(); - } - else // already at first child, jump to parent - { - document.getElementById('Item'+itemIndex).focus(); - } - } - else if (this.lastKey==40) // Down - { - var newIndex = childIndex+1; - var elem = document.getElementById('Item'+itemIndex+'_c'+newIndex); - if (!elem) // last child, jump to parent next parent - { - elem = this.NavNext(itemIndex+1); - } - if (elem) - { - elem.focus(); - } - } - else if (this.lastKey==27) // Escape - { - parent.searchBox.CloseResultsWindow(); - parent.document.getElementById("MSearchField").focus(); - } - else if (this.lastKey==13) // Enter - { - return true; - } - return false; - } -} - -function setKeyActions(elem,action) -{ - elem.setAttribute('onkeydown',action); - elem.setAttribute('onkeypress',action); - elem.setAttribute('onkeyup',action); -} - -function setClassAttr(elem,attr) -{ - elem.setAttribute('class',attr); - elem.setAttribute('className',attr); -} - -function createResults() -{ - var results = document.getElementById("SRResults"); - for (var e=0; ek7RCwB~R6VQOP#AvB$vH7i{6H{96zot$7cZT<7246EF5Np6N}+$IbiG6W zg#87A+NFaX+=_^xM1#gCtshC=E{%9^uQX_%?YwXvo{#q&MnpJ8uh(O?ZRc&~_1%^SsPxG@rfElJg-?U zm!Cz-IOn(qJP3kDp-^~qt+FGbl=5jNli^Wj_xIBG{Rc0en{!oFvyoNC7{V~T8}b>| z=jL2WIReZzX(YN(_9fV;BBD$VXQIxNasAL8ATvEu822WQ%mvv4FO#qs` BFGc_W diff --git a/Arduino/MAX6956/html/search/search_r.png b/Arduino/MAX6956/html/search/search_r.png deleted file mode 100644 index 97ee8b439687084201b79c6f776a41f495c6392a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 612 zcmV-q0-ODbP)PbXFRCwB?)W514K@j&X?z2*SxFI6-@HT2E2K=9X9%Pb zEK*!TBw&g(DMC;|A)uGlRkOS9vd-?zNs%bR4d$w+ox_iFnE8fvIvv7^5<(>Te12Li z7C)9srCzmK{ZcNM{YIl9j{DePFgOWiS%xG@5CnnnJa4nvY<^glbz7^|-ZY!dUkAwd z{gaTC@_>b5h~;ug#R0wRL0>o5!hxm*s0VW?8dr}O#zXTRTnrQm_Z7z1Mrnx>&p zD4qifUjzLvbVVWi?l?rUzwt^sdb~d!f_LEhsRVIXZtQ=qSxuxqm zEX#tf>$?M_Y1-LSDT)HqG?`%-%ZpY!#{N!rcNIiL;G7F0`l?)mNGTD9;f9F5Up3Kg zw}a<-JylhG&;=!>B+fZaCX+?C+kHYrP%c?X2!Zu_olK|GcS4A70HEy;vn)I0>0kLH z`jc(WIaaHc7!HS@f*^R^Znx8W=_jIl2oWJoQ*h1^$FX!>*PqR1J8k|fw}w_y}TpE>7m8DqDO<3z`OzXt$ccSejbEZCg@0000 - - - - - - - - -
-
Loading...
-
- -
Searching...
-
No Matches
- -
- - diff --git a/Arduino/MAX6956/html/search/variables_62.js b/Arduino/MAX6956/html/search/variables_62.js deleted file mode 100644 index b44b09cd..00000000 --- a/Arduino/MAX6956/html/search/variables_62.js +++ /dev/null @@ -1,4 +0,0 @@ -var searchData= -[ - ['buffer',['buffer',['../classMAX6956.html#a9f4597436b10ee86a02c96c2b0605851',1,'MAX6956']]] -]; diff --git a/Arduino/MAX6956/html/search/variables_64.html b/Arduino/MAX6956/html/search/variables_64.html deleted file mode 100644 index 89296ec7..00000000 --- a/Arduino/MAX6956/html/search/variables_64.html +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - -
-
Loading...
-
- -
Searching...
-
No Matches
- -
- - diff --git a/Arduino/MAX6956/html/search/variables_64.js b/Arduino/MAX6956/html/search/variables_64.js deleted file mode 100644 index dc8bc0a7..00000000 --- a/Arduino/MAX6956/html/search/variables_64.js +++ /dev/null @@ -1,4 +0,0 @@ -var searchData= -[ - ['devaddr',['devAddr',['../classMAX6956.html#a6ba2f8011914df50d6022ab54b27748d',1,'MAX6956']]] -]; diff --git a/Arduino/MAX6956/html/search/variables_70.html b/Arduino/MAX6956/html/search/variables_70.html deleted file mode 100644 index e36abe96..00000000 --- a/Arduino/MAX6956/html/search/variables_70.html +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - -
-
Loading...
-
- -
Searching...
-
No Matches
- -
- - diff --git a/Arduino/MAX6956/html/search/variables_70.js b/Arduino/MAX6956/html/search/variables_70.js deleted file mode 100644 index 21d9faa9..00000000 --- a/Arduino/MAX6956/html/search/variables_70.js +++ /dev/null @@ -1,10 +0,0 @@ -var searchData= -[ - ['portconfig',['portConfig',['../classMAX6956.html#a9799e7684546e3e9b24506d436586a09',1,'MAX6956']]], - ['portcurrentbit',['portCurrentBit',['../classMAX6956.html#ad3057b6b21ae712acb0129270da63334',1,'MAX6956']]], - ['portcurrentra',['portCurrentRA',['../classMAX6956.html#ab0d382db3afe7930d1b95311bfd90164',1,'MAX6956']]], - ['portsconfig',['portsConfig',['../classMAX6956.html#a8b915615042c5ef96fbf3a5c260d4716',1,'MAX6956']]], - ['portsstatus',['portsStatus',['../classMAX6956.html#ae8da9a65da74dce7eb907319b0198847',1,'MAX6956']]], - ['psarrayindex',['psArrayIndex',['../classMAX6956.html#a967e25fac00c0ab59be854289eb36353',1,'MAX6956']]], - ['psbitposition',['psBitPosition',['../classMAX6956.html#a92b5dc05a1483c49c150db13dcd1f283',1,'MAX6956']]] -]; diff --git a/Arduino/MAX6956/html/sync_off.png b/Arduino/MAX6956/html/sync_off.png deleted file mode 100644 index 3b443fc62892114406e3d399421b2a881b897acc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 853 zcmV-b1FHOqP)oT|#XixUYy%lpuf3i8{fX!o zUyDD0jOrAiT^tq>fLSOOABs-#u{dV^F$b{L9&!2=9&RmV;;8s^x&UqB$PCj4FdKbh zoB1WTskPUPu05XzFbA}=KZ-GP1fPpAfSs>6AHb12UlR%-i&uOlTpFNS7{jm@mkU1V zh`nrXr~+^lsV-s1dkZOaI|kYyVj3WBpPCY{n~yd%u%e+d=f%`N0FItMPtdgBb@py; zq@v6NVArhyTC7)ULw-Jy8y42S1~4n(3LkrW8mW(F-4oXUP3E`e#g**YyqI7h-J2zK zK{m9##m4ri!7N>CqQqCcnI3hqo1I;Yh&QLNY4T`*ptiQGozK>FF$!$+84Z`xwmeMh zJ0WT+OH$WYFALEaGj2_l+#DC3t7_S`vHpSivNeFbP6+r50cO8iu)`7i%Z4BTPh@_m3Tk!nAm^)5Bqnr%Ov|Baunj#&RPtRuK& z4RGz|D5HNrW83-#ydk}tVKJrNmyYt-sTxLGlJY5nc&Re zU4SgHNPx8~Yxwr$bsju?4q&%T1874xxzq+_%?h8_ofw~(bld=o3iC)LUNR*BY%c0y zWd_jX{Y8`l%z+ol1$@Qa?Cy!(0CVIEeYpKZ`(9{z>3$CIe;pJDQk$m3p}$>xBm4lb zKo{4S)`wdU9Ba9jJbVJ0C=SOefZe%d$8=2r={nu<_^a3~>c#t_U6dye5)JrR(_a^E f@}b6j1K9lwFJq@>o)+Ry00000NkvXXu0mjfWa5j* diff --git a/Arduino/MAX6956/html/sync_on.png b/Arduino/MAX6956/html/sync_on.png deleted file mode 100644 index e08320fb64e6fa33b573005ed6d8fe294e19db76..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 845 zcmV-T1G4;yP)Y;xxyHF2B5Wzm| zOOGupOTn@c(JmBOl)e;XMNnZuiTJP>rM8<|Q`7I_))aP?*T)ow&n59{}X4$3Goat zgjs?*aasfbrokzG5cT4K=uG`E14xZl@z)F={P0Y^?$4t z>v!teRnNZym<6h{7sLyF1V0HsfEl+l6TrZpsfr1}luH~F7L}ktXu|*uVX^RG$L0`K zWs3j|0tIvVe(N%_?2{(iCPFGf#B6Hjy6o&}D$A%W%jfO8_W%ZO#-mh}EM$LMn7joJ z05dHr!5Y92g+31l<%i1(=L1a1pXX+OYnalY>31V4K}BjyRe3)9n#;-cCVRD_IG1fT zOKGeNY8q;TL@K{dj@D^scf&VCs*-Jb>8b>|`b*osv52-!A?BpbYtTQBns5EAU**$m zSnVSm(teh>tQi*S*A>#ySc=n;`BHz`DuG4&g4Kf8lLhca+zvZ7t7RflD6-i-mcK=M z!=^P$*u2)bkY5asG4gsss!Hn%u~>}kIW`vMs%lJLH+u*9<4PaV_c6U`KqWXQH%+Nu zTv41O(^ZVi@qhjQdG!fbZw&y+2o!iYymO^?ud3{P*HdoX83YV*Uu_HB=?U&W9%AU# z80}k1SS-CXTU7dcQlsm<^oYLxVSseqY6NO}dc`Nj?8vrhNuCdm@^{a3AQ_>6myOj+ z`1RsLUXF|dm|3k7s2jD(B{rzE>WI2scH8i1;=O5Cc9xB3^aJk%fQjqsu+kH#0=_5a z0nCE8@dbQa-|YIuUVvG0L_IwHMEhOj$Mj4Uq05 X8=0q~qBNan00000NkvXXu0mjfptF>5 diff --git a/Arduino/MAX6956/html/tab_a.png b/Arduino/MAX6956/html/tab_a.png deleted file mode 100644 index 3b725c41c5a527a3a3e40097077d0e206a681247..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 142 zcmeAS@N?(olHy`uVBq!ia0vp^j6kfy!2~3aiye;!QlXwMjv*C{Z|8b*H5dputLHD# z=<0|*y7z(Vor?d;H&?EG&cXR}?!j-Lm&u1OOI7AIF5&c)RFE;&p0MYK>*Kl@eiymD r@|NpwKX@^z+;{u_Z~trSBfrMKa%3`zocFjEXaR$#tDnm{r-UW|TZ1%4 diff --git a/Arduino/MAX6956/html/tab_b.png b/Arduino/MAX6956/html/tab_b.png deleted file mode 100644 index e2b4a8638cb3496a016eaed9e16ffc12846dea18..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 169 zcmeAS@N?(olHy`uVBq!ia0vp^j6kfy!2~3aiye;!QU#tajv*C{Z}0l@H7kg?K0Lnr z!j&C6_(~HV9oQ0Pa6x{-v0AGV_E?vLn=ZI-;YrdjIl`U`uzuDWSP?o#Dmo{%SgM#oan kX~E1%D-|#H#QbHoIja2U-MgvsK&LQxy85}Sb4q9e0Efg%P5=M^ diff --git a/Arduino/MAX6956/html/tabs.css b/Arduino/MAX6956/html/tabs.css deleted file mode 100644 index 9cf578f2..00000000 --- a/Arduino/MAX6956/html/tabs.css +++ /dev/null @@ -1,60 +0,0 @@ -.tabs, .tabs2, .tabs3 { - background-image: url('http://github.com/tab_b.png'); - width: 100%; - z-index: 101; - font-size: 13px; - font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; -} - -.tabs2 { - font-size: 10px; -} -.tabs3 { - font-size: 9px; -} - -.tablist { - margin: 0; - padding: 0; - display: table; -} - -.tablist li { - float: left; - display: table-cell; - background-image: url('http://github.com/tab_b.png'); - line-height: 36px; - list-style: none; -} - -.tablist a { - display: block; - padding: 0 20px; - font-weight: bold; - background-image:url('http://github.com/tab_s.png'); - background-repeat:no-repeat; - background-position:right; - color: #283A5D; - text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); - text-decoration: none; - outline: none; -} - -.tabs3 .tablist a { - padding: 0 10px; -} - -.tablist a:hover { - background-image: url('http://github.com/tab_h.png'); - background-repeat:repeat-x; - color: #fff; - text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0); - text-decoration: none; -} - -.tablist li.current a { - background-image: url('http://github.com/tab_a.png'); - background-repeat:repeat-x; - color: #fff; - text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0); -} diff --git a/Arduino/MAX6956/keywords.txt b/Arduino/MAX6956/keywords.txt deleted file mode 100755 index 20591618..00000000 --- a/Arduino/MAX6956/keywords.txt +++ /dev/null @@ -1,71 +0,0 @@ -####################################### -# Syntax Coloring Map For MAX6956 -####################################### - -####################################### -# Classes, datatypes, and C++ keywords (KEYWORD1) -####################################### - -MAX6956 KEYWORD1 - -####################################### -# Methods and Functions (KEYWORD2) -####################################### - -reset KEYWORD2 -getConfigReg KEYWORD2 -setConfigReg KEYWORD2 -getPower KEYWORD2 -togglePower KEYWORD2 -setPower KEYWORD2 -getEnableIndividualCurrent KEYWORD2 -setEnableIndividualCurrent KEYWORD2 -getEnableTransitionDetection KEYWORD2 -setEnableTransitionDetection KEYWORD2 -getGlobalCurrent KEYWORD2 -setGlobalCurrent KEYWORD2 -getTestMode KEYWORD2 -setTestMode KEYWORD2 -getInputMask KEYWORD2 -setInputMask KEYWORD2 -configPort KEYWORD2 -configPorts KEYWORD2 -configAllPorts KEYWORD2 -setPortLevel KEYWORD2 -setPortCurrent KEYWORD2 -setAllPortsCurrent KEYWORD2 -enableAllPorts KEYWORD2 -disableAllPorts KEYWORD2 - - -####################################### -# InstancesKEYWORD3 setup and loop functions, -# as well as the Serial keywords (KEYWORD3) -####################################### - -####################################### -# Constants (LITERAL1) -####################################### - - -MAX6956_OUTPUT_LED LITERAL1 -MAX6956_OUTPUT_GPIO LITERAL1 -MAX6956_INPUT_WO_PULL LITERAL1 -MAX6956_INPUT_W_PULL LITERAL1 - -MAX6956_OFF LITERAL1 -MAX6956_CURRENT_1 LITERAL1 -MAX6956_CURRENT_2 LITERAL1 -MAX6956_CURRENT_3 LITERAL1 -MAX6956_CURRENT_4 LITERAL1 -MAX6956_CURRENT_5 LITERAL1 -MAX6956_CURRENT_6 LITERAL1 -MAX6956_CURRENT_7 LITERAL1 -MAX6956_CURRENT_8 LITERAL1 -MAX6956_CURRENT_9 LITERAL1 -MAX6956_CURRENT_10 LITERAL1 -MAX6956_CURRENT_11 LITERAL1 -MAX6956_CURRENT_12 LITERAL1 -MAX6956_CURRENT_13 LITERAL1 -MAX6956_CURRENT_14 LITERAL1 -MAX6956_CURRENT_15 LITERAL1 diff --git a/Arduino/MAX6956/latex/MAX6956_8cpp.tex b/Arduino/MAX6956/latex/MAX6956_8cpp.tex deleted file mode 100644 index 97fe62e6..00000000 --- a/Arduino/MAX6956/latex/MAX6956_8cpp.tex +++ /dev/null @@ -1,4 +0,0 @@ -\hypertarget{MAX6956_8cpp}{\section{M\-A\-X6956.\-cpp File Reference} -\label{MAX6956_8cpp}\index{M\-A\-X6956.\-cpp@{M\-A\-X6956.\-cpp}} -} -{\ttfamily \#include \char`\"{}M\-A\-X6956.\-h\char`\"{}}\\* diff --git a/Arduino/MAX6956/latex/MAX6956_8h.tex b/Arduino/MAX6956/latex/MAX6956_8h.tex deleted file mode 100644 index 2826e34d..00000000 --- a/Arduino/MAX6956/latex/MAX6956_8h.tex +++ /dev/null @@ -1,1937 +0,0 @@ -\hypertarget{MAX6956_8h}{\section{M\-A\-X6956.\-h File Reference} -\label{MAX6956_8h}\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}} -} -{\ttfamily \#include \char`\"{}I2\-Cdev.\-h\char`\"{}}\\* -\subsection*{Data Structures} -\begin{DoxyCompactItemize} -\item -class \hyperlink{classMAX6956}{M\-A\-X6956} -\end{DoxyCompactItemize} -\subsection*{Macros} -\begin{DoxyCompactItemize} -\item -\#define \hyperlink{MAX6956_8h_a33e60623a4c5b483d4604fe2c9b91be7}{M\-A\-X6956\-\_\-\-A\-D\-D\-R\-E\-S\-S}~0x40 -\item -\#define \hyperlink{MAX6956_8h_a4ca90873afdfdacaa730ed5db53e2f5b}{M\-A\-X6956\-\_\-\-D\-E\-F\-A\-U\-L\-T\-\_\-\-A\-D\-D\-R\-E\-S\-S}~0x40 -\item -\#define \hyperlink{MAX6956_8h_a0f205428de0679650e54dbe8250d57b4}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-N\-O\-\_\-\-O\-P}~0x00 -\begin{DoxyCompactList}\small\item\em No-\/op. \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_a6a6c2bfe9bfbe4930731829baae7c8f6}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T}~0x02 -\item -\#define \hyperlink{MAX6956_8h_a5c3d1c00491596887e211bfa630c1b94}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-U\-R\-A\-T\-I\-O\-N}~0x04 -\item -\#define \hyperlink{MAX6956_8h_a4a2b4c395e47e0ec9ef49d3236b8a465}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-D\-E\-T\-E\-C\-T}~0x06 -\item -\#define \hyperlink{MAX6956_8h_a709a5193fd2aa9274997dfc22ef73a19}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-D\-I\-S\-P\-L\-A\-Y\-\_\-\-T\-E\-S\-T}~0x07 -\item -\#define \hyperlink{MAX6956_8h_a1c4db4957c22f8767b2f1a06e5cb9a32}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P7\-P6\-P5\-P4}~0x09 -\item -\#define \hyperlink{MAX6956_8h_a3a2fa6f7cc985cfeea00ebd1dd64ae8c}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P11\-P10\-P9\-P8}~0x0\-A -\item -\#define \hyperlink{MAX6956_8h_a119a0a92d4ccdb0e8f27fd565b1220bd}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P15\-P14\-P13\-P12}~0x0\-B -\item -\#define \hyperlink{MAX6956_8h_a8f199d21b14cf933d5093d3001d0400d}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P19\-P18\-P17\-P16}~0x0\-C -\item -\#define \hyperlink{MAX6956_8h_a025ce0245fb957ef58afc5f4920e19f3}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P23\-P22\-P21\-P20}~0x0\-D -\item -\#define \hyperlink{MAX6956_8h_a4e813aab18cbd7462e1ac5a59b0a53ab}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P27\-P26\-P25\-P24}~0x0\-E -\item -\#define \hyperlink{MAX6956_8h_a98b5c2d8359fbb7e07eb2eade7e8870a}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P31\-P30\-P29\-P28}~0x0\-F -\item -\#define \hyperlink{MAX6956_8h_adebbf4c1afdeb688bf5d3887b80c75b2}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P5\-P4}~0x12 -\item -\#define \hyperlink{MAX6956_8h_a42db4570a3f848d62f3f906a920161b6}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P7\-P6}~0x13 -\item -\#define \hyperlink{MAX6956_8h_a51eb40018dff593fa84c319832a1a957}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P9\-P8}~0x14 -\item -\#define \hyperlink{MAX6956_8h_aa2304dec8420451a881876948e1cba43}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P11\-P10}~0x15 -\item -\#define \hyperlink{MAX6956_8h_add5533d08bfa791cf8cf95d7dd3f16d3}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P13\-P12}~0x16 -\item -\#define \hyperlink{MAX6956_8h_ae51b720b2bd4868c1986e2d314822778}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P15\-P14}~0x17 -\item -\#define \hyperlink{MAX6956_8h_a77820b1e4acee07a338e179ab35a7836}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P17\-P16}~0x18 -\item -\#define \hyperlink{MAX6956_8h_aa84fef4207af57fddf6468ae84ebd829}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P19\-P18}~0x19 -\item -\#define \hyperlink{MAX6956_8h_a11974f06951fb9051f9dd1d154d7c530}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P21\-P20}~0x1\-A -\item -\#define \hyperlink{MAX6956_8h_aa971a2bb392832476e3b91970f7fffe7}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P23\-P22}~0x1\-B -\item -\#define \hyperlink{MAX6956_8h_a040daea6fe73e819adcbcaed7cd3ceaf}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P25\-P24}~0x1\-C -\item -\#define \hyperlink{MAX6956_8h_ac5e5f779975977348022381487c2dfa2}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P27\-P26}~0x1\-D -\item -\#define \hyperlink{MAX6956_8h_a32623717f92442a1acfd42cdd3253302}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P29\-P28}~0x1\-E -\item -\#define \hyperlink{MAX6956_8h_a64f61d29f7ede042a397c21f33cf6124}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P31\-P30}~0x1\-F -\item -\#define \hyperlink{MAX6956_8h_a7e8973b61716ae09a84b95ea2f2f5914}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T0}~0x20 -\begin{DoxyCompactList}\small\item\em (virtual port, no action) \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_a1e4fdb2886a119328bdd6807f3720eea}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T1}~0x21 -\begin{DoxyCompactList}\small\item\em (virtual port, no action) \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_ac4cc75132151b2f662b7c54128391187}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T2}~0x22 -\begin{DoxyCompactList}\small\item\em (virtual port, no action) \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_aa3e011deb16e7054e78e6f71ac33fcba}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T3}~0x23 -\begin{DoxyCompactList}\small\item\em (virtual port, no action) \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_a68339cee27681486c99dabf398f487a0}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T4}~0x24 -\item -\#define \hyperlink{MAX6956_8h_a92c4653a42f8400a30aa13a60dbc056f}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T5}~0x25 -\item -\#define \hyperlink{MAX6956_8h_a5af96fba8e40466303a2bcec16df6c6f}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T6}~0x26 -\item -\#define \hyperlink{MAX6956_8h_a20de98d6d2102960000a70b4bcf6007c}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T7}~0x27 -\item -\#define \hyperlink{MAX6956_8h_ad0ea7dd1027b558df290150b664b0222}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T8}~0x28 -\item -\#define \hyperlink{MAX6956_8h_a7d31adbda8965d0d7df0c521571e135c}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T9}~0x29 -\item -\#define \hyperlink{MAX6956_8h_a2528a76a2e91cd1dfd11b8aefda01473}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T10}~0x2\-A -\item -\#define \hyperlink{MAX6956_8h_a3a6abf1d9e71015255d821419e3ffa5a}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T11}~0x2\-B -\item -\#define \hyperlink{MAX6956_8h_a3c089b77cbd25ffa27e3cd46af415a9c}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T12}~0x2\-C -\item -\#define \hyperlink{MAX6956_8h_a2d6ee01536f1fb0ec843479948141cbc}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T13}~0x2\-D -\item -\#define \hyperlink{MAX6956_8h_aba5e5ff9b4aea95fedff9f6421c5f47c}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T14}~0x2\-E -\item -\#define \hyperlink{MAX6956_8h_ad366a7c1b65fb3496f5b9ba392d6ba9c}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T15}~0x2\-F -\item -\#define \hyperlink{MAX6956_8h_ac483e6007b4e6a780c14c7a78ff7a134}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T16}~0x30 -\item -\#define \hyperlink{MAX6956_8h_ab6f3b8bbd8ac56bacf4a57691eb41aaf}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T17}~0x31 -\item -\#define \hyperlink{MAX6956_8h_a082486ab9eace7838acd56b6ac6301df}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T18}~0x32 -\item -\#define \hyperlink{MAX6956_8h_a04e65b34862a48ae022c994bbc5968dd}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T19}~0x33 -\item -\#define \hyperlink{MAX6956_8h_aed99f35f5ba961711c4e5bed769aa369}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T20}~0x34 -\item -\#define \hyperlink{MAX6956_8h_a361dcd71b3da6c5fb57d33951c9e4c54}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T21}~0x35 -\item -\#define \hyperlink{MAX6956_8h_a67c57767c9f6eda6124ff7368df4293b}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T22}~0x36 -\item -\#define \hyperlink{MAX6956_8h_a29699b356f81b9fc971a29fc04e68a59}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T23}~0x37 -\item -\#define \hyperlink{MAX6956_8h_ad053ff9eac065beaa10ad52dcc3d1e3e}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T24}~0x38 -\item -\#define \hyperlink{MAX6956_8h_a367103a7d8364b916a70f37d0880e334}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T25}~0x39 -\item -\#define \hyperlink{MAX6956_8h_ae0c19d326ab47406a138d4b66c601de0}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T26}~0x3\-A -\item -\#define \hyperlink{MAX6956_8h_ae1219ad62d3ea1b3a86c52736d347618}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T27}~0x3\-B -\item -\#define \hyperlink{MAX6956_8h_a07ff69092b95f43595762554c3e35329}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T28}~0x3\-C -\item -\#define \hyperlink{MAX6956_8h_a6be82fa185d6c3dd272200727c15f4ac}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T29}~0x3\-D -\item -\#define \hyperlink{MAX6956_8h_a34c02dca8e8a97488eb0be51f682cf73}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T30}~0x3\-E -\item -\#define \hyperlink{MAX6956_8h_a891d2a47a2fe5a4da056a7732fb6098b}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T31}~0x3\-F -\item -\#define \hyperlink{MAX6956_8h_a00bff40ca66a7c82b7093536c5047da4}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-7}~0x40 -\begin{DoxyCompactList}\small\item\em data bits D0-\/\-D3; D4-\/\-D7 read as 0 \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_a3d1cd4727f1748e42a0426c0b70d9c2c}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-8}~0x41 -\begin{DoxyCompactList}\small\item\em data bits D0-\/\-D4; D5-\/\-D7 read as 0 \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_ad1b71a2b24de60a4d0128576c0e1278b}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-9}~0x42 -\begin{DoxyCompactList}\small\item\em data bits D0-\/\-D5; D6-\/\-D7 read as 0 \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_ac32650edffdebee3cfeb90c9daece88b}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-10}~0x43 -\begin{DoxyCompactList}\small\item\em data bits D0-\/\-D6; D7 reads as 0 \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_a4b0cc79ee765d2f477953a890b2f6209}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-11}~0x44 -\item -\#define \hyperlink{MAX6956_8h_a13b8eb94b73c20a02397e50c81bccb57}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S5\-\_\-12}~0x45 -\item -\#define \hyperlink{MAX6956_8h_af01fef127c33b806d570f1d46a90362f}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S6\-\_\-13}~0x46 -\item -\#define \hyperlink{MAX6956_8h_ae0f37de2a929dc6f37733c3f112e0fa7}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S7\-\_\-14}~0x47 -\item -\#define \hyperlink{MAX6956_8h_ae2bd6458f4aa0271d7fb9c8c8fdd0e4f}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S8\-\_\-15}~0x48 -\item -\#define \hyperlink{MAX6956_8h_aedb8b7ecadabaf8290ac1eacde7db918}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S9\-\_\-16}~0x49 -\item -\#define \hyperlink{MAX6956_8h_aa9837d30cb5f9c9badf20fe50ea3ba26}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S10\-\_\-17}~0x4\-A -\item -\#define \hyperlink{MAX6956_8h_a40bf1528e6a7345e0aaa3b86869f3af3}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S11\-\_\-18}~0x4\-B -\item -\#define \hyperlink{MAX6956_8h_ab3e1f8d0b913acae6d73f9b5b0d491ff}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S12\-\_\-19}~0x4\-C -\item -\#define \hyperlink{MAX6956_8h_ad33d71fa8457fcdb444179768a6376e9}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S13\-\_\-20}~0x4\-D -\item -\#define \hyperlink{MAX6956_8h_aeae655678f9a39b8a7f6e9de1a09c59e}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S14\-\_\-21}~0x4\-E -\item -\#define \hyperlink{MAX6956_8h_a853b18f366e225131135f6576268a461}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S15\-\_\-22}~0x4\-F -\item -\#define \hyperlink{MAX6956_8h_a39c1bb286953031fad9c101604d6f56e}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S16\-\_\-23}~0x50 -\item -\#define \hyperlink{MAX6956_8h_a8a4536b80e588a3ed6bb2f487499efeb}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S17\-\_\-24}~0x51 -\item -\#define \hyperlink{MAX6956_8h_a1ae324a27c0648b831978991a44ee33f}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S18\-\_\-25}~0x52 -\item -\#define \hyperlink{MAX6956_8h_a981a54414024fdd2877704d4d242b748}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S19\-\_\-26}~0x53 -\item -\#define \hyperlink{MAX6956_8h_abd2280465476a9e3cae302d5e9bf7b62}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S20\-\_\-27}~0x54 -\item -\#define \hyperlink{MAX6956_8h_adfca6218829cec2697e0975fc7965008}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S21\-\_\-28}~0x55 -\item -\#define \hyperlink{MAX6956_8h_aa190f6504c585b64f355ce45a24057f1}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S22\-\_\-29}~0x56 -\item -\#define \hyperlink{MAX6956_8h_a9ae64dcdc091a17982f4888bcd7b1981}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S23\-\_\-30}~0x57 -\item -\#define \hyperlink{MAX6956_8h_a5054da2b077f91e7f6106373a84476ed}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S24\-\_\-31}~0x58 -\item -\#define \hyperlink{MAX6956_8h_a38a7fe545ab1b4ca108dabcef50d015f}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S25\-\_\-31}~0x59 -\begin{DoxyCompactList}\small\item\em data bits D0-\/\-D6; D7 reads as 0 \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_ac804c8074d5a6baf79b0595415ae0679}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S26\-\_\-31}~0x5\-A -\begin{DoxyCompactList}\small\item\em data bits D0-\/\-D5; D6-\/\-D7 read as 0 \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_a5307d28ebcae5028fc482c914eecf48f}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S27\-\_\-31}~0x5\-B -\begin{DoxyCompactList}\small\item\em data bits D0-\/\-D4; D5-\/\-D7 read as 0 \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_a7554adf2b4214f33584001f4e7c81053}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S28\-\_\-31}~0x5\-C -\begin{DoxyCompactList}\small\item\em data bits D0-\/\-D3; D4-\/\-D7 read as 0 \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_ab278f8cb075460b9318c029bca24e68a}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S29\-\_\-31}~0x5\-D -\begin{DoxyCompactList}\small\item\em data bits D0-\/\-D2; D3-\/\-D7 read as 0 \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_ae5873266ac57220286709a468781c3ff}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S30\-\_\-31}~0x5\-E -\begin{DoxyCompactList}\small\item\em data bits D0-\/\-D1; D2-\/\-D7 read as 0 \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_ad12b528f7fa63249d37126a8d4049aab}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S31\-\_\-31}~0x5\-F -\begin{DoxyCompactList}\small\item\em data bit D0; D1-\/\-D7 read as 0. Port 31 only. \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_a03faf0490eddbb2f0405616ad6ac4052}{M\-A\-X6956\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P\-O\-W\-E\-R\-\_\-\-B\-I\-T}~0 -\begin{DoxyCompactList}\small\item\em 0 = Shutdown, 1 = Normal operation \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_a4288d838d55461c66c0ba2e904f588a7}{M\-A\-X6956\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}~6 -\begin{DoxyCompactList}\small\item\em 0 = Global control, 1 = Individual control \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_af1d61c00ae2e56dd5e7f04dc4b0c1663}{M\-A\-X6956\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-B\-I\-T}~7 -\begin{DoxyCompactList}\small\item\em 0 = Disabled, 1 = Enabled \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_a85368204ba368978f814d46d81335c35}{M\-A\-X6956\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}~0 -\begin{DoxyCompactList}\small\item\em Global current start bit. \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_afbcb8bf5ecc4e5afada48446f8dac809}{M\-A\-X6956\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}~4 -\begin{DoxyCompactList}\small\item\em nybble long \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_ae1cb8088b95a2e19f293dbeee7ef7892}{M\-A\-X6956\-\_\-\-P\-O\-R\-T12\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}~3 -\begin{DoxyCompactList}\small\item\em L\-S\-Nybble. \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_a8b0c452aa9a3f66de931d4a226f865e6}{M\-A\-X6956\-\_\-\-P\-O\-R\-T12\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}~4 -\begin{DoxyCompactList}\small\item\em nybble long \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_a0c413303648e14359c311fb9478cfce7}{M\-A\-X6956\-\_\-\-P\-O\-R\-T13\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}~7 -\begin{DoxyCompactList}\small\item\em M\-S\-Nybble. \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_abaee1f6920a6a6770468cb7def42bff7}{M\-A\-X6956\-\_\-\-P\-O\-R\-T13\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}~4 -\begin{DoxyCompactList}\small\item\em nybble long \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_a0fcb35fa292905862765e99dd03e63b2}{M\-A\-X6956\-\_\-\-P\-O\-R\-T14\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}~3 -\begin{DoxyCompactList}\small\item\em L\-S\-Nybble. \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_aa98b4176c22631122a00948e5a54e91f}{M\-A\-X6956\-\_\-\-P\-O\-R\-T14\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}~4 -\begin{DoxyCompactList}\small\item\em nybble long \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_a659a1777dac35a14930720029b786aed}{M\-A\-X6956\-\_\-\-P\-O\-R\-T15\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}~7 -\begin{DoxyCompactList}\small\item\em M\-S\-Nybble. \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_ab377c2d0463246bfc66c9df01087285d}{M\-A\-X6956\-\_\-\-P\-O\-R\-T15\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}~4 -\begin{DoxyCompactList}\small\item\em nybble long \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_a977fb8ce0e696e764ae098dce361e446}{M\-A\-X6956\-\_\-\-P\-O\-R\-T16\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}~3 -\begin{DoxyCompactList}\small\item\em L\-S\-Nybble. \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_a04c2dcf166214a43fbdd9ae5f7a0ca00}{M\-A\-X6956\-\_\-\-P\-O\-R\-T16\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}~4 -\begin{DoxyCompactList}\small\item\em nybble long \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_ab59b7f618ff0788a6bd21313bf14673f}{M\-A\-X6956\-\_\-\-P\-O\-R\-T17\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}~7 -\begin{DoxyCompactList}\small\item\em M\-S\-Nybble. \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_adf0428deb9192d621f837d7951e539be}{M\-A\-X6956\-\_\-\-P\-O\-R\-T17\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}~4 -\begin{DoxyCompactList}\small\item\em nybble long \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_ab0d4c28bc6747482ab33a027fd93b5d7}{M\-A\-X6956\-\_\-\-P\-O\-R\-T18\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}~3 -\begin{DoxyCompactList}\small\item\em L\-S\-Nybble. \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_a9bb781fca7fadebb28918c05d2f1605c}{M\-A\-X6956\-\_\-\-P\-O\-R\-T18\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}~4 -\begin{DoxyCompactList}\small\item\em nybble long \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_aea0128f7b979e68785b78cfc7e480a32}{M\-A\-X6956\-\_\-\-P\-O\-R\-T19\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}~7 -\begin{DoxyCompactList}\small\item\em M\-S\-Nybble. \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_a5c2f25a82e8b442abb28a9544a3d4088}{M\-A\-X6956\-\_\-\-P\-O\-R\-T19\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}~4 -\begin{DoxyCompactList}\small\item\em nybble long \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_a95789ffe1e677c75090556342763c6ac}{M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}~3 -\begin{DoxyCompactList}\small\item\em L\-S\-Nybble. \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_a0f492bea7bf9e0906ba13f447327d5a8}{M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}~4 -\begin{DoxyCompactList}\small\item\em nybble long \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_abd855e00543729cc87ab4a48e3d98649}{M\-A\-X6956\-\_\-\-P\-O\-R\-T21\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}~7 -\begin{DoxyCompactList}\small\item\em M\-S\-Nybble. \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_a65cd02d7f498266b224c035a3809126a}{M\-A\-X6956\-\_\-\-P\-O\-R\-T21\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}~4 -\begin{DoxyCompactList}\small\item\em nybble long \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_a061947a1484a8449fd4301a1022cafe5}{M\-A\-X6956\-\_\-\-P\-O\-R\-T22\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}~3 -\begin{DoxyCompactList}\small\item\em L\-S\-Nybble. \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_aa64238ebb3bf6d8ee2d0d368992e7613}{M\-A\-X6956\-\_\-\-P\-O\-R\-T22\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}~4 -\begin{DoxyCompactList}\small\item\em nybble long \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_a95789ffe1e677c75090556342763c6ac}{M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}~7 -\begin{DoxyCompactList}\small\item\em L\-S\-Nybble. \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_a0f492bea7bf9e0906ba13f447327d5a8}{M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}~4 -\begin{DoxyCompactList}\small\item\em nybble long \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_a50e41ea8c3ec1bb3d55e5a4eb03563a2}{M\-A\-X6956\-\_\-\-P\-O\-R\-T24\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}~3 -\begin{DoxyCompactList}\small\item\em L\-S\-Nybble. \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_a11ee583606d04516bc2fc5812b05cd3d}{M\-A\-X6956\-\_\-\-P\-O\-R\-T24\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}~4 -\begin{DoxyCompactList}\small\item\em nybble long \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_a75f6b93cf7558a38adba5bb4a91d05f8}{M\-A\-X6956\-\_\-\-P\-O\-R\-T25\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}~7 -\begin{DoxyCompactList}\small\item\em M\-S\-Nybble. \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_a3b1a7a5f82da6b43bd5a24d2297a2f75}{M\-A\-X6956\-\_\-\-P\-O\-R\-T25\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}~4 -\begin{DoxyCompactList}\small\item\em nybble long \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_abd400d2f356832d21b1787e2501a8644}{M\-A\-X6956\-\_\-\-P\-O\-R\-T26\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}~3 -\begin{DoxyCompactList}\small\item\em L\-S\-Nybble. \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_a28bf5ca7da83928eeec3f4f302d12c45}{M\-A\-X6956\-\_\-\-P\-O\-R\-T26\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}~4 -\begin{DoxyCompactList}\small\item\em nybble long \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_a62bf02cd8e4d8a9dfa975d0e319f68f5}{M\-A\-X6956\-\_\-\-P\-O\-R\-T27\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}~7 -\begin{DoxyCompactList}\small\item\em M\-S\-Nybble. \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_a0a0f99c166b5a60d7e6c6c7d99306b45}{M\-A\-X6956\-\_\-\-P\-O\-R\-T27\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}~4 -\begin{DoxyCompactList}\small\item\em nybble long \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_ab6135c4105c3b39625e7361a438e1511}{M\-A\-X6956\-\_\-\-P\-O\-R\-T28\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}~3 -\begin{DoxyCompactList}\small\item\em L\-S\-Nybble. \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_ac2bcdc199d348dba281a4371675bd428}{M\-A\-X6956\-\_\-\-P\-O\-R\-T28\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}~4 -\begin{DoxyCompactList}\small\item\em nybble long \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_ae98448e4aa991d16d9b1d9d6071078d8}{M\-A\-X6956\-\_\-\-P\-O\-R\-T29\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}~7 -\begin{DoxyCompactList}\small\item\em M\-S\-Nybble. \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_a6b0d8a1c63777d016e1cb22076b91377}{M\-A\-X6956\-\_\-\-P\-O\-R\-T29\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}~4 -\begin{DoxyCompactList}\small\item\em nybble long \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_aa5acefc0723ea8d2b804aa7eccae705b}{M\-A\-X6956\-\_\-\-P\-O\-R\-T33\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}~3 -\begin{DoxyCompactList}\small\item\em L\-S\-Nybble. \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_a2fb02a7e77abefcbf7c194ff6b994ae9}{M\-A\-X6956\-\_\-\-P\-O\-R\-T33\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}~4 -\begin{DoxyCompactList}\small\item\em nybble long \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_a1cdbea93ca621e5fc4c747286bdf90e1}{M\-A\-X6956\-\_\-\-P\-O\-R\-T31\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}~7 -\begin{DoxyCompactList}\small\item\em M\-S\-Nybble. \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_a40a075605dfcfc2736aab5ffa10e3e2c}{M\-A\-X6956\-\_\-\-P\-O\-R\-T31\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}~4 -\begin{DoxyCompactList}\small\item\em nybble long \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_a7e110f7b5949bf63dd7c5b4e9a59a5b0}{M\-A\-X6956\-\_\-\-D\-I\-S\-P\-L\-A\-Y\-\_\-\-T\-E\-S\-T\-\_\-\-B\-I\-T}~0 -\begin{DoxyCompactList}\small\item\em 0 = Normal operation, 1 = Display test \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_a29bd01905e66b503151e6d9cdfb035a1}{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-S\-T\-A\-T\-U\-S\-\_\-\-B\-I\-T}~7 -\begin{DoxyCompactList}\small\item\em I\-N\-T Status, I\-N\-T is automatically cleared after it is read. \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_abc801853bdfe66591265d04865aba78f}{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-B\-I\-T}~0 -\begin{DoxyCompactList}\small\item\em Ports 24-\/30. \end{DoxyCompactList}\item -\#define \hyperlink{MAX6956_8h_a332868e8a1596e785072ddb8c4a2b4c1}{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-L\-E\-N\-G\-T\-H}~7 -\item -\#define \hyperlink{MAX6956_8h_a0e7f62a1c7d77019ca8ca2c2511f2644}{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T30\-\_\-\-B\-I\-T}~6 -\item -\#define \hyperlink{MAX6956_8h_a74adf7234472da3287cb98af583750c9}{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T29\-\_\-\-B\-I\-T}~5 -\item -\#define \hyperlink{MAX6956_8h_a927e5369f33337fdea8d89ccc3b3919d}{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T28\-\_\-\-B\-I\-T}~4 -\item -\#define \hyperlink{MAX6956_8h_a282091cda715bb27f96266f5ae22b492}{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T27\-\_\-\-B\-I\-T}~3 -\item -\#define \hyperlink{MAX6956_8h_ac4f63f4afc199c41dd9b1445259b8d50}{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T26\-\_\-\-B\-I\-T}~2 -\item -\#define \hyperlink{MAX6956_8h_a04d331f867fa51822f5910ce2b6b891c}{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T25\-\_\-\-B\-I\-T}~1 -\item -\#define \hyperlink{MAX6956_8h_a0a2eb488b9b8d16b5c076d25790ec28e}{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T24\-\_\-\-B\-I\-T}~0 -\item -\#define \hyperlink{MAX6956_8h_ad6490a909085059c4300a51dcebbf7bc}{M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-L\-E\-D}~0x00 -\item -\#define \hyperlink{MAX6956_8h_a27f6ca524d4c18623762c722d9993c10}{M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-G\-P\-I\-O}~0x01 -\item -\#define \hyperlink{MAX6956_8h_ab05f3186e2515bab3a536ad9f1cbb7db}{M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-O\-\_\-\-P\-U\-L\-L}~0x02 -\item -\#define \hyperlink{MAX6956_8h_a68fc1bc750b7959fbab7e64f79589b83}{M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-\_\-\-P\-U\-L\-L}~0x03 -\item -\#define \hyperlink{MAX6956_8h_a003fe60fa8da81e67da2ad7900d1196f}{M\-A\-X6956\-\_\-\-O\-F\-F}~0x00 -\item -\#define \hyperlink{MAX6956_8h_a4e151161e190a9f45aebfd712064b034}{M\-A\-X6956\-\_\-\-O\-N}~0x01 -\item -\#define \hyperlink{MAX6956_8h_a930221b73d0e7327ffce1e3072ed69e3}{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0}~0x00 -\item -\#define \hyperlink{MAX6956_8h_afd6a3c0f560b7b7190805416e1ad00f5}{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-1}~0x01 -\item -\#define \hyperlink{MAX6956_8h_ab7558038e4f723efa4b406e988a93990}{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-2}~0x02 -\item -\#define \hyperlink{MAX6956_8h_a8b8800a153cf4869a6c4d399f8d46035}{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-3}~0x03 -\item -\#define \hyperlink{MAX6956_8h_a2678f20d0e18e036e13ff5f422fcf609}{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-4}~0x04 -\item -\#define \hyperlink{MAX6956_8h_af808e1e791b9a640d6b6c62cb145f169}{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-5}~0x05 -\item -\#define \hyperlink{MAX6956_8h_a0c97726477caef4c0f54eb1beaffbdff}{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-6}~0x06 -\item -\#define \hyperlink{MAX6956_8h_a55c66763c65c8554d12a71a4c20e35a6}{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-7}~0x07 -\item -\#define \hyperlink{MAX6956_8h_a11c425ee14938c667e63e7df4cf8afa2}{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-8}~0x08 -\item -\#define \hyperlink{MAX6956_8h_a4da9aedd07982408005da31fda78463a}{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-9}~0x09 -\item -\#define \hyperlink{MAX6956_8h_a62f09fbe807ce97d3558748808ed3a11}{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-10}~0x0\-A -\item -\#define \hyperlink{MAX6956_8h_a5b97f8927dd861189567ad1fda6d692a}{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-11}~0x0\-B -\item -\#define \hyperlink{MAX6956_8h_a8fb88850c74ecc2080971984c817b860}{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-12}~0x0\-C -\item -\#define \hyperlink{MAX6956_8h_a8bfeeb7d88d4284dec7174b65724877d}{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-13}~0x0\-D -\item -\#define \hyperlink{MAX6956_8h_aad136273ced9dea0ef4a8821f4a5f368}{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-14}~0x0\-E -\item -\#define \hyperlink{MAX6956_8h_a4c0ac1cc939ecfb7992dac2834521eb6}{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-15}~0x0\-F -\end{DoxyCompactItemize} - - -\subsection{Macro Definition Documentation} -\hypertarget{MAX6956_8h_a33e60623a4c5b483d4604fe2c9b91be7}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-A\-D\-D\-R\-E\-S\-S@{M\-A\-X6956\-\_\-\-A\-D\-D\-R\-E\-S\-S}} -\index{M\-A\-X6956\-\_\-\-A\-D\-D\-R\-E\-S\-S@{M\-A\-X6956\-\_\-\-A\-D\-D\-R\-E\-S\-S}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-A\-D\-D\-R\-E\-S\-S}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-A\-D\-D\-R\-E\-S\-S~0x40}}\label{MAX6956_8h_a33e60623a4c5b483d4604fe2c9b91be7} -\subsection*{Table 3. I2\-C Address Map } - -Pin$|$\-Pin$|$\-D\-E\-V\-I\-C\-E A\-D\-D\-R\-E\-S\-S $|$ \-:-\/\-:$|$\-:-\/\-:$|$\-:-\/\-:$|$\-:-\/\-:$|$\-:-\/\-:$|$\-:-\/\-:$|$\-:-\/\-:$|$\-:-\/\-:$|$\-:-\/\-:$|$\-:-\/\-:$|$\-:--\-: A\-D1$|$\-A\-D0$|$\-A7 $|$\-A6 $|$\-A5 $|$\-A4 $|$\-A3 $|$\-A2 $|$\-A1 $|$\-A0 $|$\-H\-E\-X G\-N\-D$|$\-G\-N\-D$|$1 $|$0 $|$0 $|$0 $|$0 $|$0 $|$0 $|$\-R\-W $|$0x40 G\-N\-D$|$\-V+ $|$1 $|$0 $|$0 $|$0 $|$0 $|$0 $|$1 $|$\-R\-W $|$0x41 G\-N\-D$|$\-S\-D\-A$|$1 $|$0 $|$0 $|$0 $|$0 $|$1 $|$0 $|$\-R\-W $|$0x42 G\-N\-D$|$\-S\-C\-L$|$1 $|$0 $|$0 $|$0 $|$0 $|$1 $|$1 $|$\-R\-W $|$0x43 V+ $|$\-G\-N\-D$|$1 $|$0 $|$0 $|$0 $|$1 $|$0 $|$0 $|$\-R\-W $|$0x44 V+ $|$\-V+ $|$1 $|$0 $|$0 $|$0 $|$1 $|$0 $|$1 $|$\-R\-W $|$0x45 V+ $|$\-S\-D\-A$|$1 $|$0 $|$0 $|$0 $|$1 $|$1 $|$0 $|$\-R\-W $|$0x46 V+ $|$\-S\-C\-L$|$1 $|$0 $|$0 $|$0 $|$1 $|$1 $|$1 $|$\-R\-W $|$0x47 S\-D\-A$|$\-G\-N\-D$|$1 $|$0 $|$0 $|$1 $|$0 $|$0 $|$0 $|$\-R\-W $|$0x48 S\-D\-A$|$\-V+ $|$1 $|$0 $|$0 $|$1 $|$0 $|$0 $|$1 $|$\-R\-W $|$0x49 S\-D\-A$|$\-S\-D\-A$|$1 $|$0 $|$0 $|$1 $|$0 $|$1 $|$0 $|$\-R\-W $|$0x50 S\-D\-A$|$\-S\-C\-L$|$1 $|$0 $|$0 $|$1 $|$0 $|$1 $|$1 $|$\-R\-W $|$0x51 S\-C\-L$|$\-G\-N\-D$|$1 $|$0 $|$0 $|$1 $|$1 $|$0 $|$0 $|$\-R\-W $|$0x52 S\-C\-L$|$\-V+ $|$1 $|$0 $|$0 $|$1 $|$1 $|$0 $|$1 $|$\-R\-W $|$0x53 S\-C\-L$|$\-S\-D\-A$|$1 $|$0 $|$0 $|$1 $|$1 $|$1 $|$0 $|$\-R\-W $|$0x54 S\-C\-L$|$\-S\-C\-L$|$1 $|$0 $|$0 $|$1 $|$1 $|$1 $|$1 $|$\-R\-W $|$0x55 - -R\-W bit 0 = Write 1 = Read - -Definition at line 71 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a4288d838d55461c66c0ba2e904f588a7}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}} -\index{M\-A\-X6956\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T~6}}\label{MAX6956_8h_a4288d838d55461c66c0ba2e904f588a7} - - -0 = Global control, 1 = Individual control - - - -Definition at line 344 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a03faf0490eddbb2f0405616ad6ac4052}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P\-O\-W\-E\-R\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P\-O\-W\-E\-R\-\_\-\-B\-I\-T}} -\index{M\-A\-X6956\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P\-O\-W\-E\-R\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P\-O\-W\-E\-R\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P\-O\-W\-E\-R\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P\-O\-W\-E\-R\-\_\-\-B\-I\-T~0}}\label{MAX6956_8h_a03faf0490eddbb2f0405616ad6ac4052} - - -0 = Shutdown, 1 = Normal operation - - - -Definition at line 343 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_af1d61c00ae2e56dd5e7f04dc4b0c1663}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-B\-I\-T}} -\index{M\-A\-X6956\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-B\-I\-T~7}}\label{MAX6956_8h_af1d61c00ae2e56dd5e7f04dc4b0c1663} - - -0 = Disabled, 1 = Enabled - - - -Definition at line 345 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a930221b73d0e7327ffce1e3072ed69e3}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0}} -\index{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0~0x00}}\label{MAX6956_8h_a930221b73d0e7327ffce1e3072ed69e3} - - -Definition at line 414 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_afd6a3c0f560b7b7190805416e1ad00f5}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-1@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-1}} -\index{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-1@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-1}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-1}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-1~0x01}}\label{MAX6956_8h_afd6a3c0f560b7b7190805416e1ad00f5} - - -Definition at line 415 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a62f09fbe807ce97d3558748808ed3a11}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-10@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-10}} -\index{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-10@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-10}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-10}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-10~0x0\-A}}\label{MAX6956_8h_a62f09fbe807ce97d3558748808ed3a11} - - -Definition at line 424 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a5b97f8927dd861189567ad1fda6d692a}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-11@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-11}} -\index{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-11@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-11}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-11}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-11~0x0\-B}}\label{MAX6956_8h_a5b97f8927dd861189567ad1fda6d692a} - - -Definition at line 425 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a8fb88850c74ecc2080971984c817b860}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-12@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-12}} -\index{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-12@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-12}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-12}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-12~0x0\-C}}\label{MAX6956_8h_a8fb88850c74ecc2080971984c817b860} - - -Definition at line 426 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a8bfeeb7d88d4284dec7174b65724877d}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-13@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-13}} -\index{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-13@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-13}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-13}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-13~0x0\-D}}\label{MAX6956_8h_a8bfeeb7d88d4284dec7174b65724877d} - - -Definition at line 427 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_aad136273ced9dea0ef4a8821f4a5f368}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-14@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-14}} -\index{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-14@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-14}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-14}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-14~0x0\-E}}\label{MAX6956_8h_aad136273ced9dea0ef4a8821f4a5f368} - - -Definition at line 428 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a4c0ac1cc939ecfb7992dac2834521eb6}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-15@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-15}} -\index{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-15@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-15}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-15}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-15~0x0\-F}}\label{MAX6956_8h_a4c0ac1cc939ecfb7992dac2834521eb6} - - -Definition at line 429 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_ab7558038e4f723efa4b406e988a93990}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-2@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-2}} -\index{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-2@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-2}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-2}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-2~0x02}}\label{MAX6956_8h_ab7558038e4f723efa4b406e988a93990} - - -Definition at line 416 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a8b8800a153cf4869a6c4d399f8d46035}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-3@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-3}} -\index{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-3@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-3}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-3}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-3~0x03}}\label{MAX6956_8h_a8b8800a153cf4869a6c4d399f8d46035} - - -Definition at line 417 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a2678f20d0e18e036e13ff5f422fcf609}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-4@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-4}} -\index{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-4@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-4}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-4}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-4~0x04}}\label{MAX6956_8h_a2678f20d0e18e036e13ff5f422fcf609} - - -Definition at line 418 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_af808e1e791b9a640d6b6c62cb145f169}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-5@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-5}} -\index{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-5@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-5}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-5}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-5~0x05}}\label{MAX6956_8h_af808e1e791b9a640d6b6c62cb145f169} - - -Definition at line 419 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a0c97726477caef4c0f54eb1beaffbdff}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-6@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-6}} -\index{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-6@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-6}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-6}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-6~0x06}}\label{MAX6956_8h_a0c97726477caef4c0f54eb1beaffbdff} - - -Definition at line 420 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a55c66763c65c8554d12a71a4c20e35a6}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-7@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-7}} -\index{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-7@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-7}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-7}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-7~0x07}}\label{MAX6956_8h_a55c66763c65c8554d12a71a4c20e35a6} - - -Definition at line 421 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a11c425ee14938c667e63e7df4cf8afa2}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-8@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-8}} -\index{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-8@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-8}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-8}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-8~0x08}}\label{MAX6956_8h_a11c425ee14938c667e63e7df4cf8afa2} - - -Definition at line 422 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a4da9aedd07982408005da31fda78463a}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-9@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-9}} -\index{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-9@{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-9}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-9}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-9~0x09}}\label{MAX6956_8h_a4da9aedd07982408005da31fda78463a} - - -Definition at line 423 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a4ca90873afdfdacaa730ed5db53e2f5b}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-D\-E\-F\-A\-U\-L\-T\-\_\-\-A\-D\-D\-R\-E\-S\-S@{M\-A\-X6956\-\_\-\-D\-E\-F\-A\-U\-L\-T\-\_\-\-A\-D\-D\-R\-E\-S\-S}} -\index{M\-A\-X6956\-\_\-\-D\-E\-F\-A\-U\-L\-T\-\_\-\-A\-D\-D\-R\-E\-S\-S@{M\-A\-X6956\-\_\-\-D\-E\-F\-A\-U\-L\-T\-\_\-\-A\-D\-D\-R\-E\-S\-S}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-D\-E\-F\-A\-U\-L\-T\-\_\-\-A\-D\-D\-R\-E\-S\-S}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-D\-E\-F\-A\-U\-L\-T\-\_\-\-A\-D\-D\-R\-E\-S\-S~0x40}}\label{MAX6956_8h_a4ca90873afdfdacaa730ed5db53e2f5b} - - -Definition at line 72 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a7e110f7b5949bf63dd7c5b4e9a59a5b0}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-D\-I\-S\-P\-L\-A\-Y\-\_\-\-T\-E\-S\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-D\-I\-S\-P\-L\-A\-Y\-\_\-\-T\-E\-S\-T\-\_\-\-B\-I\-T}} -\index{M\-A\-X6956\-\_\-\-D\-I\-S\-P\-L\-A\-Y\-\_\-\-T\-E\-S\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-D\-I\-S\-P\-L\-A\-Y\-\_\-\-T\-E\-S\-T\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-D\-I\-S\-P\-L\-A\-Y\-\_\-\-T\-E\-S\-T\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-D\-I\-S\-P\-L\-A\-Y\-\_\-\-T\-E\-S\-T\-\_\-\-B\-I\-T~0}}\label{MAX6956_8h_a7e110f7b5949bf63dd7c5b4e9a59a5b0} - - -0 = Normal operation, 1 = Display test - - - -Definition at line 391 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a85368204ba368978f814d46d81335c35}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}} -\index{M\-A\-X6956\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T~0}}\label{MAX6956_8h_a85368204ba368978f814d46d81335c35} - - -Global current start bit. - - - -Definition at line 347 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_afbcb8bf5ecc4e5afada48446f8dac809}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}} -\index{M\-A\-X6956\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H~4}}\label{MAX6956_8h_afbcb8bf5ecc4e5afada48446f8dac809} - - -nybble long - - - -Definition at line 348 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a68fc1bc750b7959fbab7e64f79589b83}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-\_\-\-P\-U\-L\-L@{M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-\_\-\-P\-U\-L\-L}} -\index{M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-\_\-\-P\-U\-L\-L@{M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-\_\-\-P\-U\-L\-L}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-\_\-\-P\-U\-L\-L}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-\_\-\-P\-U\-L\-L~0x03}}\label{MAX6956_8h_a68fc1bc750b7959fbab7e64f79589b83} - - -Definition at line 409 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_ab05f3186e2515bab3a536ad9f1cbb7db}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-O\-\_\-\-P\-U\-L\-L@{M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-O\-\_\-\-P\-U\-L\-L}} -\index{M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-O\-\_\-\-P\-U\-L\-L@{M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-O\-\_\-\-P\-U\-L\-L}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-O\-\_\-\-P\-U\-L\-L}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-O\-\_\-\-P\-U\-L\-L~0x02}}\label{MAX6956_8h_ab05f3186e2515bab3a536ad9f1cbb7db} - - -Definition at line 408 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a003fe60fa8da81e67da2ad7900d1196f}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-O\-F\-F@{M\-A\-X6956\-\_\-\-O\-F\-F}} -\index{M\-A\-X6956\-\_\-\-O\-F\-F@{M\-A\-X6956\-\_\-\-O\-F\-F}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-O\-F\-F}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-O\-F\-F~0x00}}\label{MAX6956_8h_a003fe60fa8da81e67da2ad7900d1196f} - - -Definition at line 411 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a4e151161e190a9f45aebfd712064b034}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-O\-N@{M\-A\-X6956\-\_\-\-O\-N}} -\index{M\-A\-X6956\-\_\-\-O\-N@{M\-A\-X6956\-\_\-\-O\-N}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-O\-N}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-O\-N~0x01}}\label{MAX6956_8h_a4e151161e190a9f45aebfd712064b034} - - -Definition at line 412 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a27f6ca524d4c18623762c722d9993c10}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-G\-P\-I\-O@{M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-G\-P\-I\-O}} -\index{M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-G\-P\-I\-O@{M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-G\-P\-I\-O}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-G\-P\-I\-O}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-G\-P\-I\-O~0x01}}\label{MAX6956_8h_a27f6ca524d4c18623762c722d9993c10} - - -Definition at line 407 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_ad6490a909085059c4300a51dcebbf7bc}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-L\-E\-D@{M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-L\-E\-D}} -\index{M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-L\-E\-D@{M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-L\-E\-D}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-L\-E\-D}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-L\-E\-D~0x00}}\label{MAX6956_8h_ad6490a909085059c4300a51dcebbf7bc} - - -Definition at line 406 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_ae1cb8088b95a2e19f293dbeee7ef7892}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T12\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T12\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}} -\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T12\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T12\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T12\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T12\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T~3}}\label{MAX6956_8h_ae1cb8088b95a2e19f293dbeee7ef7892} - - -L\-S\-Nybble. - - - -Definition at line 350 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a8b0c452aa9a3f66de931d4a226f865e6}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T12\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T12\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}} -\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T12\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T12\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T12\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T12\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H~4}}\label{MAX6956_8h_a8b0c452aa9a3f66de931d4a226f865e6} - - -nybble long - - - -Definition at line 351 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a0c413303648e14359c311fb9478cfce7}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T13\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T13\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}} -\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T13\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T13\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T13\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T13\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T~7}}\label{MAX6956_8h_a0c413303648e14359c311fb9478cfce7} - - -M\-S\-Nybble. - - - -Definition at line 352 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_abaee1f6920a6a6770468cb7def42bff7}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T13\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T13\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}} -\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T13\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T13\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T13\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T13\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H~4}}\label{MAX6956_8h_abaee1f6920a6a6770468cb7def42bff7} - - -nybble long - - - -Definition at line 353 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a0fcb35fa292905862765e99dd03e63b2}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T14\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T14\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}} -\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T14\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T14\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T14\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T14\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T~3}}\label{MAX6956_8h_a0fcb35fa292905862765e99dd03e63b2} - - -L\-S\-Nybble. - - - -Definition at line 354 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_aa98b4176c22631122a00948e5a54e91f}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T14\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T14\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}} -\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T14\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T14\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T14\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T14\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H~4}}\label{MAX6956_8h_aa98b4176c22631122a00948e5a54e91f} - - -nybble long - - - -Definition at line 355 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a659a1777dac35a14930720029b786aed}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T15\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T15\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}} -\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T15\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T15\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T15\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T15\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T~7}}\label{MAX6956_8h_a659a1777dac35a14930720029b786aed} - - -M\-S\-Nybble. - - - -Definition at line 356 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_ab377c2d0463246bfc66c9df01087285d}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T15\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T15\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}} -\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T15\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T15\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T15\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T15\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H~4}}\label{MAX6956_8h_ab377c2d0463246bfc66c9df01087285d} - - -nybble long - - - -Definition at line 357 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a977fb8ce0e696e764ae098dce361e446}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T16\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T16\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}} -\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T16\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T16\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T16\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T16\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T~3}}\label{MAX6956_8h_a977fb8ce0e696e764ae098dce361e446} - - -L\-S\-Nybble. - - - -Definition at line 358 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a04c2dcf166214a43fbdd9ae5f7a0ca00}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T16\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T16\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}} -\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T16\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T16\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T16\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T16\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H~4}}\label{MAX6956_8h_a04c2dcf166214a43fbdd9ae5f7a0ca00} - - -nybble long - - - -Definition at line 359 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_ab59b7f618ff0788a6bd21313bf14673f}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T17\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T17\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}} -\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T17\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T17\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T17\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T17\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T~7}}\label{MAX6956_8h_ab59b7f618ff0788a6bd21313bf14673f} - - -M\-S\-Nybble. - - - -Definition at line 360 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_adf0428deb9192d621f837d7951e539be}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T17\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T17\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}} -\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T17\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T17\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T17\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T17\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H~4}}\label{MAX6956_8h_adf0428deb9192d621f837d7951e539be} - - -nybble long - - - -Definition at line 361 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_ab0d4c28bc6747482ab33a027fd93b5d7}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T18\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T18\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}} -\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T18\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T18\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T18\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T18\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T~3}}\label{MAX6956_8h_ab0d4c28bc6747482ab33a027fd93b5d7} - - -L\-S\-Nybble. - - - -Definition at line 362 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a9bb781fca7fadebb28918c05d2f1605c}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T18\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T18\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}} -\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T18\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T18\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T18\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T18\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H~4}}\label{MAX6956_8h_a9bb781fca7fadebb28918c05d2f1605c} - - -nybble long - - - -Definition at line 363 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_aea0128f7b979e68785b78cfc7e480a32}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T19\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T19\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}} -\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T19\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T19\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T19\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T19\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T~7}}\label{MAX6956_8h_aea0128f7b979e68785b78cfc7e480a32} - - -M\-S\-Nybble. - - - -Definition at line 364 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a5c2f25a82e8b442abb28a9544a3d4088}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T19\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T19\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}} -\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T19\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T19\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T19\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T19\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H~4}}\label{MAX6956_8h_a5c2f25a82e8b442abb28a9544a3d4088} - - -nybble long - - - -Definition at line 365 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_abd855e00543729cc87ab4a48e3d98649}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T21\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T21\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}} -\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T21\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T21\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T21\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T21\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T~7}}\label{MAX6956_8h_abd855e00543729cc87ab4a48e3d98649} - - -M\-S\-Nybble. - - - -Definition at line 368 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a65cd02d7f498266b224c035a3809126a}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T21\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T21\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}} -\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T21\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T21\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T21\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T21\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H~4}}\label{MAX6956_8h_a65cd02d7f498266b224c035a3809126a} - - -nybble long - - - -Definition at line 369 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a061947a1484a8449fd4301a1022cafe5}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T22\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T22\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}} -\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T22\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T22\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T22\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T22\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T~3}}\label{MAX6956_8h_a061947a1484a8449fd4301a1022cafe5} - - -L\-S\-Nybble. - - - -Definition at line 370 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_aa64238ebb3bf6d8ee2d0d368992e7613}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T22\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T22\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}} -\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T22\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T22\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T22\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T22\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H~4}}\label{MAX6956_8h_aa64238ebb3bf6d8ee2d0d368992e7613} - - -nybble long - - - -Definition at line 371 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a95789ffe1e677c75090556342763c6ac}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}} -\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T~3}}\label{MAX6956_8h_a95789ffe1e677c75090556342763c6ac} - - -L\-S\-Nybble. - -M\-S\-Nybble. - -Definition at line 372 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a95789ffe1e677c75090556342763c6ac}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}} -\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T~7}}\label{MAX6956_8h_a95789ffe1e677c75090556342763c6ac} - - -L\-S\-Nybble. - -M\-S\-Nybble. - -Definition at line 372 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a0f492bea7bf9e0906ba13f447327d5a8}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}} -\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H~4}}\label{MAX6956_8h_a0f492bea7bf9e0906ba13f447327d5a8} - - -nybble long - - - -Definition at line 373 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a0f492bea7bf9e0906ba13f447327d5a8}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}} -\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T23\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H~4}}\label{MAX6956_8h_a0f492bea7bf9e0906ba13f447327d5a8} - - -nybble long - - - -Definition at line 373 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a50e41ea8c3ec1bb3d55e5a4eb03563a2}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T24\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T24\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}} -\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T24\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T24\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T24\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T24\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T~3}}\label{MAX6956_8h_a50e41ea8c3ec1bb3d55e5a4eb03563a2} - - -L\-S\-Nybble. - - - -Definition at line 374 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a11ee583606d04516bc2fc5812b05cd3d}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T24\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T24\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}} -\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T24\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T24\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T24\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T24\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H~4}}\label{MAX6956_8h_a11ee583606d04516bc2fc5812b05cd3d} - - -nybble long - - - -Definition at line 375 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a75f6b93cf7558a38adba5bb4a91d05f8}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T25\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T25\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}} -\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T25\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T25\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T25\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T25\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T~7}}\label{MAX6956_8h_a75f6b93cf7558a38adba5bb4a91d05f8} - - -M\-S\-Nybble. - - - -Definition at line 376 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a3b1a7a5f82da6b43bd5a24d2297a2f75}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T25\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T25\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}} -\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T25\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T25\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T25\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T25\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H~4}}\label{MAX6956_8h_a3b1a7a5f82da6b43bd5a24d2297a2f75} - - -nybble long - - - -Definition at line 377 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_abd400d2f356832d21b1787e2501a8644}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T26\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T26\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}} -\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T26\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T26\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T26\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T26\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T~3}}\label{MAX6956_8h_abd400d2f356832d21b1787e2501a8644} - - -L\-S\-Nybble. - - - -Definition at line 378 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a28bf5ca7da83928eeec3f4f302d12c45}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T26\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T26\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}} -\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T26\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T26\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T26\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T26\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H~4}}\label{MAX6956_8h_a28bf5ca7da83928eeec3f4f302d12c45} - - -nybble long - - - -Definition at line 379 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a62bf02cd8e4d8a9dfa975d0e319f68f5}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T27\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T27\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}} -\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T27\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T27\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T27\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T27\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T~7}}\label{MAX6956_8h_a62bf02cd8e4d8a9dfa975d0e319f68f5} - - -M\-S\-Nybble. - - - -Definition at line 380 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a0a0f99c166b5a60d7e6c6c7d99306b45}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T27\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T27\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}} -\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T27\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T27\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T27\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T27\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H~4}}\label{MAX6956_8h_a0a0f99c166b5a60d7e6c6c7d99306b45} - - -nybble long - - - -Definition at line 381 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_ab6135c4105c3b39625e7361a438e1511}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T28\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T28\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}} -\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T28\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T28\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T28\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T28\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T~3}}\label{MAX6956_8h_ab6135c4105c3b39625e7361a438e1511} - - -L\-S\-Nybble. - - - -Definition at line 382 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_ac2bcdc199d348dba281a4371675bd428}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T28\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T28\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}} -\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T28\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T28\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T28\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T28\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H~4}}\label{MAX6956_8h_ac2bcdc199d348dba281a4371675bd428} - - -nybble long - - - -Definition at line 383 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_ae98448e4aa991d16d9b1d9d6071078d8}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T29\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T29\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}} -\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T29\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T29\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T29\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T29\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T~7}}\label{MAX6956_8h_ae98448e4aa991d16d9b1d9d6071078d8} - - -M\-S\-Nybble. - - - -Definition at line 384 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a6b0d8a1c63777d016e1cb22076b91377}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T29\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T29\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}} -\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T29\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T29\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T29\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T29\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H~4}}\label{MAX6956_8h_a6b0d8a1c63777d016e1cb22076b91377} - - -nybble long - - - -Definition at line 385 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a1cdbea93ca621e5fc4c747286bdf90e1}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T31\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T31\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}} -\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T31\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T31\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T31\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T31\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T~7}}\label{MAX6956_8h_a1cdbea93ca621e5fc4c747286bdf90e1} - - -M\-S\-Nybble. - - - -Definition at line 388 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a40a075605dfcfc2736aab5ffa10e3e2c}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T31\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T31\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}} -\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T31\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T31\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T31\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T31\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H~4}}\label{MAX6956_8h_a40a075605dfcfc2736aab5ffa10e3e2c} - - -nybble long - - - -Definition at line 389 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_aa5acefc0723ea8d2b804aa7eccae705b}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T33\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T33\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}} -\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T33\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-P\-O\-R\-T33\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T33\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T33\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-B\-I\-T~3}}\label{MAX6956_8h_aa5acefc0723ea8d2b804aa7eccae705b} - - -L\-S\-Nybble. - - - -Definition at line 386 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a2fb02a7e77abefcbf7c194ff6b994ae9}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-P\-O\-R\-T33\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T33\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}} -\index{M\-A\-X6956\-\_\-\-P\-O\-R\-T33\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-P\-O\-R\-T33\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-P\-O\-R\-T33\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-P\-O\-R\-T33\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-\-L\-E\-N\-G\-T\-H~4}}\label{MAX6956_8h_a2fb02a7e77abefcbf7c194ff6b994ae9} - - -nybble long - - - -Definition at line 387 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a3a2fa6f7cc985cfeea00ebd1dd64ae8c}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P11\-P10\-P9\-P8@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P11\-P10\-P9\-P8}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P11\-P10\-P9\-P8@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P11\-P10\-P9\-P8}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P11\-P10\-P9\-P8}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P11\-P10\-P9\-P8~0x0\-A}}\label{MAX6956_8h_a3a2fa6f7cc985cfeea00ebd1dd64ae8c} - - -Definition at line 204 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a119a0a92d4ccdb0e8f27fd565b1220bd}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P15\-P14\-P13\-P12@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P15\-P14\-P13\-P12}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P15\-P14\-P13\-P12@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P15\-P14\-P13\-P12}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P15\-P14\-P13\-P12}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P15\-P14\-P13\-P12~0x0\-B}}\label{MAX6956_8h_a119a0a92d4ccdb0e8f27fd565b1220bd} - - -Definition at line 205 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a8f199d21b14cf933d5093d3001d0400d}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P19\-P18\-P17\-P16@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P19\-P18\-P17\-P16}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P19\-P18\-P17\-P16@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P19\-P18\-P17\-P16}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P19\-P18\-P17\-P16}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P19\-P18\-P17\-P16~0x0\-C}}\label{MAX6956_8h_a8f199d21b14cf933d5093d3001d0400d} - - -Definition at line 206 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a025ce0245fb957ef58afc5f4920e19f3}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P23\-P22\-P21\-P20@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P23\-P22\-P21\-P20}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P23\-P22\-P21\-P20@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P23\-P22\-P21\-P20}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P23\-P22\-P21\-P20}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P23\-P22\-P21\-P20~0x0\-D}}\label{MAX6956_8h_a025ce0245fb957ef58afc5f4920e19f3} - - -Definition at line 207 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a4e813aab18cbd7462e1ac5a59b0a53ab}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P27\-P26\-P25\-P24@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P27\-P26\-P25\-P24}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P27\-P26\-P25\-P24@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P27\-P26\-P25\-P24}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P27\-P26\-P25\-P24}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P27\-P26\-P25\-P24~0x0\-E}}\label{MAX6956_8h_a4e813aab18cbd7462e1ac5a59b0a53ab} - - -Definition at line 208 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a98b5c2d8359fbb7e07eb2eade7e8870a}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P31\-P30\-P29\-P28@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P31\-P30\-P29\-P28}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P31\-P30\-P29\-P28@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P31\-P30\-P29\-P28}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P31\-P30\-P29\-P28}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P31\-P30\-P29\-P28~0x0\-F}}\label{MAX6956_8h_a98b5c2d8359fbb7e07eb2eade7e8870a} - - -Definition at line 209 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a1c4db4957c22f8767b2f1a06e5cb9a32}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P7\-P6\-P5\-P4@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P7\-P6\-P5\-P4}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P7\-P6\-P5\-P4@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P7\-P6\-P5\-P4}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P7\-P6\-P5\-P4}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P7\-P6\-P5\-P4~0x09}}\label{MAX6956_8h_a1c4db4957c22f8767b2f1a06e5cb9a32} -\subsection*{Table 1. Port Configuration Map } - -\begin{TabularC}{6} -\hline -\rowcolor{lightgray}{\bf R\-E\-G\-I\-S\-T\-E\-R }&{\bf A\-D\-D\-R\-E\-S\-S}&{\bf D7 D6}&{\bf D5 D4}&{\bf D3 D2}&{\bf D1 D0 }\\\cline{1-6} -Port Configuration for P7, P6, P5, P4 &0x09 &P7 &P6 &P5 &P4 \\\cline{1-6} -Port Configuration for P11, P10, P9, P8 &0x0\-A &P11 &P10 &P9 &P8 \\\cline{1-6} -Port Configuration for P15, P14, P13, P12&0x0\-B &P15 &P14 &P13 &P12 \\\cline{1-6} -Port Configuration for P19, P18, P17, P16&0x0\-C &P19 &P18 &P17 &P16 \\\cline{1-6} -Port Configuration for P23, P22, P21, P20&0x0\-D &P23 &P22 &P21 &P20 \\\cline{1-6} -Port Configuration for P27, P26, P25, P24&0x0\-E &P27 &P26 &P25 &P24 \\\cline{1-6} -Port Configuration for P31, P30, P29, P28&0x0\-F &P31 &P30 &P29 &P28 \\\cline{1-6} -\end{TabularC} -\subsection*{Table 2. P4-\/\-P31 configuration bit pairs } - - -\begin{DoxyPre} - 00 - Output, LED Segment Driver - Controlled using port registers 0x20-0x5F. - 0 = High impedance - 1 = Open-drain current sink, with sink current (up to 24mA) - determined by the appropriate current register - 01 - Output, GPIO Output - Controlled using port registers 0x20-0x5F. - 0 = Active-low logic output - 1 = Active-high logic output - 10 - Input, GPIO Input Without Pullup - Read port registers 0x20-0x5F. - Schmitt logic input - 11 - Input, GPIO Input with Pullup - Read port registers 0x20-0x5F. - Schmitt logic input with pullup -\end{DoxyPre} - - -Definition at line 203 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a5c3d1c00491596887e211bfa630c1b94}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-U\-R\-A\-T\-I\-O\-N@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-U\-R\-A\-T\-I\-O\-N}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-U\-R\-A\-T\-I\-O\-N@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-U\-R\-A\-T\-I\-O\-N}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-U\-R\-A\-T\-I\-O\-N}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-U\-R\-A\-T\-I\-O\-N~0x04}}\label{MAX6956_8h_a5c3d1c00491596887e211bfa630c1b94} -\subsection*{Table 7. Configuration Register Format } - -\begin{TabularC}{9} -\hline -\rowcolor{lightgray}\PBS\centering {\bf A\-D\-D\-R\-E\-S\-S }&\PBS\centering {\bf D7 }&\PBS\centering {\bf D6 }&\PBS\centering {\bf D5 }&\PBS\centering {\bf D4 }&\PBS\centering {\bf D3 }&\PBS\centering {\bf D2 }&\PBS\centering {\bf D1 }&\PBS\centering {\bf D0 }\\\cline{1-9} -\PBS\centering 0x04 &\PBS\centering M &\PBS\centering I &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering S \\\cline{1-9} -\end{TabularC} -\subsection*{Table 8. Shutdown Control (S Data Bit D0) Format } - -\begin{TabularC}{10} -\hline -\rowcolor{lightgray}\PBS\centering {\bf F\-U\-N\-C\-T\-I\-O\-N }&\PBS\centering {\bf A\-D\-D\-R\-E\-S\-S}&\PBS\centering {\bf D7 }&\PBS\centering {\bf D6 }&\PBS\centering {\bf D5 }&\PBS\centering {\bf D4 }&\PBS\centering {\bf D3 }&\PBS\centering {\bf D2 }&\PBS\centering {\bf D1 }&\PBS\centering {\bf D0 }\\\cline{1-10} -\PBS\centering Shutdown &\PBS\centering 0x04 &\PBS\centering M &\PBS\centering I &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering 0 \\\cline{1-10} -\PBS\centering Normal Operation&\PBS\centering 0x04 &\PBS\centering M &\PBS\centering I &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering 1 \\\cline{1-10} -\end{TabularC} -\subsection*{Table 9. Global Current Control (I Data Bit D6) Format } - -\begin{TabularC}{10} -\hline -\rowcolor{lightgray}\PBS\centering {\bf F\-U\-N\-C\-T\-I\-O\-N }&\PBS\centering {\bf A\-D\-D\-R\-E\-S\-S}&\PBS\centering {\bf D7 }&\PBS\centering {\bf D6 }&\PBS\centering {\bf D5 }&\PBS\centering {\bf D4 }&\PBS\centering {\bf D3 }&\PBS\centering {\bf D2 }&\PBS\centering {\bf D1 }&\PBS\centering {\bf D0 }\\\cline{1-10} -\PBS\centering Global &\PBS\centering 0x04 &\PBS\centering M &\PBS\centering 0 &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering S \\\cline{1-10} -\PBS\centering Individual Segment&\PBS\centering 0x04 &\PBS\centering M &\PBS\centering 1 &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering S \\\cline{1-10} -\end{TabularC} -\subsection*{Table 10. Transition Detection Control (M-\/\-Data Bit D7) Format } - -\begin{TabularC}{10} -\hline -\rowcolor{lightgray}\PBS\centering {\bf F\-U\-N\-C\-T\-I\-O\-N }&\PBS\centering {\bf A\-D\-D\-R\-E\-S\-S}&\PBS\centering {\bf D7 }&\PBS\centering {\bf D6 }&\PBS\centering {\bf D5 }&\PBS\centering {\bf D4 }&\PBS\centering {\bf D3 }&\PBS\centering {\bf D2 }&\PBS\centering {\bf D1 }&\PBS\centering {\bf D0 }\\\cline{1-10} -\PBS\centering Disabled &\PBS\centering 0x04 &\PBS\centering 0 &\PBS\centering I &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering S \\\cline{1-10} -\PBS\centering Enabled &\PBS\centering 0x04 &\PBS\centering 1 &\PBS\centering I &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering S \\\cline{1-10} -\end{TabularC} - - -Definition at line 137 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_aa2304dec8420451a881876948e1cba43}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P11\-P10@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P11\-P10}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P11\-P10@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P11\-P10}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P11\-P10}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P11\-P10~0x15}}\label{MAX6956_8h_aa2304dec8420451a881876948e1cba43} - - -Definition at line 244 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_add5533d08bfa791cf8cf95d7dd3f16d3}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P13\-P12@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P13\-P12}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P13\-P12@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P13\-P12}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P13\-P12}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P13\-P12~0x16}}\label{MAX6956_8h_add5533d08bfa791cf8cf95d7dd3f16d3} - - -Definition at line 245 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_ae51b720b2bd4868c1986e2d314822778}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P15\-P14@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P15\-P14}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P15\-P14@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P15\-P14}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P15\-P14}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P15\-P14~0x17}}\label{MAX6956_8h_ae51b720b2bd4868c1986e2d314822778} - - -Definition at line 246 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a77820b1e4acee07a338e179ab35a7836}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P17\-P16@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P17\-P16}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P17\-P16@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P17\-P16}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P17\-P16}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P17\-P16~0x18}}\label{MAX6956_8h_a77820b1e4acee07a338e179ab35a7836} - - -Definition at line 247 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_aa84fef4207af57fddf6468ae84ebd829}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P19\-P18@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P19\-P18}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P19\-P18@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P19\-P18}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P19\-P18}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P19\-P18~0x19}}\label{MAX6956_8h_aa84fef4207af57fddf6468ae84ebd829} - - -Definition at line 248 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a11974f06951fb9051f9dd1d154d7c530}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P21\-P20@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P21\-P20}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P21\-P20@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P21\-P20}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P21\-P20}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P21\-P20~0x1\-A}}\label{MAX6956_8h_a11974f06951fb9051f9dd1d154d7c530} - - -Definition at line 249 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_aa971a2bb392832476e3b91970f7fffe7}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P23\-P22@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P23\-P22}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P23\-P22@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P23\-P22}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P23\-P22}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P23\-P22~0x1\-B}}\label{MAX6956_8h_aa971a2bb392832476e3b91970f7fffe7} - - -Definition at line 250 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a040daea6fe73e819adcbcaed7cd3ceaf}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P25\-P24@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P25\-P24}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P25\-P24@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P25\-P24}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P25\-P24}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P25\-P24~0x1\-C}}\label{MAX6956_8h_a040daea6fe73e819adcbcaed7cd3ceaf} - - -Definition at line 251 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_ac5e5f779975977348022381487c2dfa2}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P27\-P26@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P27\-P26}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P27\-P26@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P27\-P26}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P27\-P26}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P27\-P26~0x1\-D}}\label{MAX6956_8h_ac5e5f779975977348022381487c2dfa2} - - -Definition at line 252 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a32623717f92442a1acfd42cdd3253302}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P29\-P28@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P29\-P28}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P29\-P28@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P29\-P28}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P29\-P28}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P29\-P28~0x1\-E}}\label{MAX6956_8h_a32623717f92442a1acfd42cdd3253302} - - -Definition at line 253 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a64f61d29f7ede042a397c21f33cf6124}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P31\-P30@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P31\-P30}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P31\-P30@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P31\-P30}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P31\-P30}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P31\-P30~0x1\-F}}\label{MAX6956_8h_a64f61d29f7ede042a397c21f33cf6124} - - -Definition at line 254 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_adebbf4c1afdeb688bf5d3887b80c75b2}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P5\-P4@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P5\-P4}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P5\-P4@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P5\-P4}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P5\-P4}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P5\-P4~0x12}}\label{MAX6956_8h_adebbf4c1afdeb688bf5d3887b80c75b2} -Constant-\/current limit for each digit is individually controlled by the settings in the Current054 through Current1\-F\-E registers - -\subsection*{Table 12. Individual Port Current Registers } - -\begin{DoxyVerb} | ADDRESS | | -\end{DoxyVerb} - \begin{TabularC}{4} -\hline -\rowcolor{lightgray}{\bf F\-U\-N\-C\-T\-I\-O\-N }&{\bf C\-O\-D\-E(\-H\-E\-X)}&{\bf D7 D6 D5 D4 }&{\bf D3 D2 D1 D0 }\\\cline{1-4} -Current054 register &0x12 &Segment 5 &Segment 4 \\\cline{1-4} -Current076 register &0x13 &Segment 7 &Segment 6 \\\cline{1-4} -Current098 register &0x14 &Segment 9 &Segment 8 \\\cline{1-4} -Current0\-B\-A register &0x15 &Segment 11 &Segment 10 \\\cline{1-4} -Current0\-D\-C register &0x16 &Segment 13 &Segment 12 \\\cline{1-4} -Current0\-F\-E register &0x17 &Segment 15 &Segment 14 \\\cline{1-4} -Current110 register &0x18 &Segment 17 &Segment 16 \\\cline{1-4} -Current132 register &0x19 &Segment 19 &Segment 18 \\\cline{1-4} -Current154 register &0x1\-A &Segment 21 &Segment 20 \\\cline{1-4} -Current176 register &0x1\-B &Segment 23 &Segment 22 \\\cline{1-4} -Current198 register &0x1\-C &Segment 25 &Segment 24 \\\cline{1-4} -Current1\-B\-A register &0x1\-D &Segment 27 &Segment 26 \\\cline{1-4} -Current1\-D\-C register &0x1\-E &Segment 29 &Segment 28 \\\cline{1-4} -Current1\-F\-E register &0x1\-F &Segment 31 &Segment 30 \\\cline{1-4} -\end{TabularC} -Register data is 0-\/\-Fx0-\/\-F for 1-\/16(0-\/\-F) brightness levels. To completely blank an output turn it off (0) using port configuration registers. - -Definition at line 241 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a42db4570a3f848d62f3f906a920161b6}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P7\-P6@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P7\-P6}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P7\-P6@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P7\-P6}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P7\-P6}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P7\-P6~0x13}}\label{MAX6956_8h_a42db4570a3f848d62f3f906a920161b6} - - -Definition at line 242 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a51eb40018dff593fa84c319832a1a957}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P9\-P8@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P9\-P8}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P9\-P8@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P9\-P8}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P9\-P8}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-U\-R\-R\-E\-N\-T\-\_\-0x\-P9\-P8~0x14}}\label{MAX6956_8h_a51eb40018dff593fa84c319832a1a957} - - -Definition at line 243 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a709a5193fd2aa9274997dfc22ef73a19}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-D\-I\-S\-P\-L\-A\-Y\-\_\-\-T\-E\-S\-T@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-D\-I\-S\-P\-L\-A\-Y\-\_\-\-T\-E\-S\-T}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-D\-I\-S\-P\-L\-A\-Y\-\_\-\-T\-E\-S\-T@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-D\-I\-S\-P\-L\-A\-Y\-\_\-\-T\-E\-S\-T}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-D\-I\-S\-P\-L\-A\-Y\-\_\-\-T\-E\-S\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-D\-I\-S\-P\-L\-A\-Y\-\_\-\-T\-E\-S\-T~0x07}}\label{MAX6956_8h_a709a5193fd2aa9274997dfc22ef73a19} -\subsection*{Table 16. Display Test Register } - -\begin{DoxyVerb} |ADDR | -\end{DoxyVerb} - \begin{TabularC}{10} -\hline -\rowcolor{lightgray}\PBS\centering {\bf M\-O\-D\-E }&\PBS\centering {\bf C\-O\-D\-E }&\PBS\centering {\bf D7 }&\PBS\centering {\bf D6 }&\PBS\centering {\bf D5 }&\PBS\centering {\bf D4 }&\PBS\centering {\bf D3 }&\PBS\centering {\bf D2 }&\PBS\centering {\bf D1 }&\PBS\centering {\bf D0 }\\\cline{1-10} -\PBS\centering Normal Operation &\PBS\centering 0x07 &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering 0 \\\cline{1-10} -\PBS\centering Display Test Mode&\PBS\centering 0x07 &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering 1 \\\cline{1-10} -\end{TabularC} - - -Definition at line 165 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a6a6c2bfe9bfbe4930731829baae7c8f6}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T~0x02}}\label{MAX6956_8h_a6a6c2bfe9bfbe4930731829baae7c8f6} -\subsection*{Table 11. Global Segment Current Register Format } - -L\-E\-D D\-R\-I\-V\-E $|$\-T\-Y\-P\-I\-C\-A\-L S\-E\-G\-M\-E\-N\-T $|$ A\-D\-D\-R\-E\-S\-S $|$ \begin{TabularC}{12} -\hline -\rowcolor{lightgray}\PBS\centering {\bf F\-R\-A\-C\-T\-I\-O\-N }&\PBS\centering {\bf C\-U\-R\-R\-E\-N\-T(m\-A) }&\PBS\centering {\bf C\-O\-D\-E (H\-E\-X) }&\PBS\centering {\bf D7 }&\PBS\centering {\bf D6 }&\PBS\centering {\bf D5 }&\PBS\centering {\bf D4 }&\PBS\centering {\bf D3 }&\PBS\centering {\bf D2 }&\PBS\centering {\bf D1 }&\PBS\centering {\bf D0 }&\PBS\centering {\bf H\-E\-X C\-O\-D\-E }\\\cline{1-12} -\PBS\centering 1/16 &\PBS\centering 1.\-5 &\PBS\centering 0x02 &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering 0 &\PBS\centering 0 &\PBS\centering 0 &\PBS\centering 0 &\PBS\centering 0x\-X0 \\\cline{1-12} -\PBS\centering 2/16 &\PBS\centering 3 &\PBS\centering 0x02 &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering 0 &\PBS\centering 0 &\PBS\centering 0 &\PBS\centering 1 &\PBS\centering 0x\-X1 \\\cline{1-12} -\PBS\centering 3/16 &\PBS\centering 4.\-5 &\PBS\centering 0x02 &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering 0 &\PBS\centering 0 &\PBS\centering 1 &\PBS\centering 0 &\PBS\centering 0x\-X2 \\\cline{1-12} -\PBS\centering 4/16 &\PBS\centering 6 &\PBS\centering 0x02 &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering 0 &\PBS\centering 0 &\PBS\centering 1 &\PBS\centering 1 &\PBS\centering 0x\-X3 \\\cline{1-12} -\PBS\centering 5/16 &\PBS\centering 7.\-5 &\PBS\centering 0x02 &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering 0 &\PBS\centering 1 &\PBS\centering 0 &\PBS\centering 0 &\PBS\centering 0x\-X4 \\\cline{1-12} -\PBS\centering 6/16 &\PBS\centering 9 &\PBS\centering 0x02 &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering 0 &\PBS\centering 1 &\PBS\centering 0 &\PBS\centering 1 &\PBS\centering 0x\-X5 \\\cline{1-12} -\PBS\centering 7/16 &\PBS\centering 10.\-5 &\PBS\centering 0x02 &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering 0 &\PBS\centering 1 &\PBS\centering 1 &\PBS\centering 0 &\PBS\centering 0x\-X6 \\\cline{1-12} -\PBS\centering 8/16 &\PBS\centering 12 &\PBS\centering 0x02 &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering 0 &\PBS\centering 1 &\PBS\centering 1 &\PBS\centering 1 &\PBS\centering 0x\-X7 \\\cline{1-12} -\PBS\centering 9/16 &\PBS\centering 13.\-5 &\PBS\centering 0x02 &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering 1 &\PBS\centering 0 &\PBS\centering 0 &\PBS\centering 0 &\PBS\centering 0x\-X8 \\\cline{1-12} -\PBS\centering 10/16 &\PBS\centering 15 &\PBS\centering 0x02 &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering 1 &\PBS\centering 0 &\PBS\centering 0 &\PBS\centering 1 &\PBS\centering 0x\-X9 \\\cline{1-12} -\PBS\centering 11/16 &\PBS\centering 16.\-5 &\PBS\centering 0x02 &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering 1 &\PBS\centering 0 &\PBS\centering 1 &\PBS\centering 0 &\PBS\centering 0x\-X\-A \\\cline{1-12} -\PBS\centering 12/16 &\PBS\centering 18 &\PBS\centering 0x02 &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering 1 &\PBS\centering 0 &\PBS\centering 1 &\PBS\centering 1 &\PBS\centering 0x\-X\-B \\\cline{1-12} -\PBS\centering 13/16 &\PBS\centering 19.\-5 &\PBS\centering 0x02 &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering 1 &\PBS\centering 1 &\PBS\centering 0 &\PBS\centering 0 &\PBS\centering 0x\-X\-C \\\cline{1-12} -\PBS\centering 14/16 &\PBS\centering 21 &\PBS\centering 0x02 &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering 1 &\PBS\centering 1 &\PBS\centering 0 &\PBS\centering 1 &\PBS\centering 0x\-X\-D \\\cline{1-12} -\PBS\centering 15/16 &\PBS\centering 22.\-5 &\PBS\centering 0x02 &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering 1 &\PBS\centering 1 &\PBS\centering 1 &\PBS\centering 0 &\PBS\centering 0x\-X\-E \\\cline{1-12} -\PBS\centering 16/16 &\PBS\centering 24 &\PBS\centering 0x02 &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering x &\PBS\centering 1 &\PBS\centering 1 &\PBS\centering 1 &\PBS\centering 1 &\PBS\centering 0x\-X\-F \\\cline{1-12} -\end{TabularC} - - -Definition at line 102 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a0f205428de0679650e54dbe8250d57b4}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-N\-O\-\_\-\-O\-P@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-N\-O\-\_\-\-O\-P}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-N\-O\-\_\-\-O\-P@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-N\-O\-\_\-\-O\-P}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-N\-O\-\_\-\-O\-P}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-N\-O\-\_\-\-O\-P~0x00}}\label{MAX6956_8h_a0f205428de0679650e54dbe8250d57b4} - - -No-\/op. - - - -Definition at line 76 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a7e8973b61716ae09a84b95ea2f2f5914}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T0@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T0}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T0@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T0}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T0}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T0~0x20}}\label{MAX6956_8h_a7e8973b61716ae09a84b95ea2f2f5914} - - -(virtual port, no action) - -\subsection*{Individiual Port Registers } - -\begin{DoxyVerb}data bit D0; D7-D1 read as 0\end{DoxyVerb} - - -Definition at line 262 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a1e4fdb2886a119328bdd6807f3720eea}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T1@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T1}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T1@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T1}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T1}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T1~0x21}}\label{MAX6956_8h_a1e4fdb2886a119328bdd6807f3720eea} - - -(virtual port, no action) - - - -Definition at line 263 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a2528a76a2e91cd1dfd11b8aefda01473}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T10@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T10}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T10@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T10}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T10}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T10~0x2\-A}}\label{MAX6956_8h_a2528a76a2e91cd1dfd11b8aefda01473} - - -Definition at line 273 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a3a6abf1d9e71015255d821419e3ffa5a}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T11@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T11}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T11@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T11}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T11}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T11~0x2\-B}}\label{MAX6956_8h_a3a6abf1d9e71015255d821419e3ffa5a} - - -Definition at line 274 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a3c089b77cbd25ffa27e3cd46af415a9c}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T12@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T12}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T12@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T12}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T12}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T12~0x2\-C}}\label{MAX6956_8h_a3c089b77cbd25ffa27e3cd46af415a9c} - - -Definition at line 276 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a2d6ee01536f1fb0ec843479948141cbc}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T13@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T13}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T13@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T13}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T13}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T13~0x2\-D}}\label{MAX6956_8h_a2d6ee01536f1fb0ec843479948141cbc} - - -Definition at line 277 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_aba5e5ff9b4aea95fedff9f6421c5f47c}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T14@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T14}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T14@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T14}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T14}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T14~0x2\-E}}\label{MAX6956_8h_aba5e5ff9b4aea95fedff9f6421c5f47c} - - -Definition at line 278 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_ad366a7c1b65fb3496f5b9ba392d6ba9c}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T15@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T15}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T15@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T15}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T15}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T15~0x2\-F}}\label{MAX6956_8h_ad366a7c1b65fb3496f5b9ba392d6ba9c} - - -Definition at line 279 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_ac483e6007b4e6a780c14c7a78ff7a134}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T16@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T16}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T16@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T16}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T16}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T16~0x30}}\label{MAX6956_8h_ac483e6007b4e6a780c14c7a78ff7a134} - - -Definition at line 280 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_ab6f3b8bbd8ac56bacf4a57691eb41aaf}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T17@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T17}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T17@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T17}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T17}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T17~0x31}}\label{MAX6956_8h_ab6f3b8bbd8ac56bacf4a57691eb41aaf} - - -Definition at line 281 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a082486ab9eace7838acd56b6ac6301df}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T18@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T18}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T18@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T18}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T18}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T18~0x32}}\label{MAX6956_8h_a082486ab9eace7838acd56b6ac6301df} - - -Definition at line 282 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a04e65b34862a48ae022c994bbc5968dd}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T19@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T19}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T19@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T19}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T19}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T19~0x33}}\label{MAX6956_8h_a04e65b34862a48ae022c994bbc5968dd} - - -Definition at line 283 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_ac4cc75132151b2f662b7c54128391187}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T2@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T2}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T2@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T2}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T2}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T2~0x22}}\label{MAX6956_8h_ac4cc75132151b2f662b7c54128391187} - - -(virtual port, no action) - - - -Definition at line 264 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_aed99f35f5ba961711c4e5bed769aa369}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T20@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T20}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T20@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T20}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T20}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T20~0x34}}\label{MAX6956_8h_aed99f35f5ba961711c4e5bed769aa369} - - -Definition at line 285 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a361dcd71b3da6c5fb57d33951c9e4c54}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T21@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T21}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T21@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T21}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T21}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T21~0x35}}\label{MAX6956_8h_a361dcd71b3da6c5fb57d33951c9e4c54} - - -Definition at line 286 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a67c57767c9f6eda6124ff7368df4293b}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T22@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T22}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T22@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T22}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T22}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T22~0x36}}\label{MAX6956_8h_a67c57767c9f6eda6124ff7368df4293b} - - -Definition at line 287 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a29699b356f81b9fc971a29fc04e68a59}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T23@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T23}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T23@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T23}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T23}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T23~0x37}}\label{MAX6956_8h_a29699b356f81b9fc971a29fc04e68a59} - - -Definition at line 288 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_ad053ff9eac065beaa10ad52dcc3d1e3e}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T24@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T24}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T24@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T24}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T24}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T24~0x38}}\label{MAX6956_8h_ad053ff9eac065beaa10ad52dcc3d1e3e} - - -Definition at line 289 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a367103a7d8364b916a70f37d0880e334}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T25@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T25}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T25@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T25}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T25}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T25~0x39}}\label{MAX6956_8h_a367103a7d8364b916a70f37d0880e334} - - -Definition at line 290 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_ae0c19d326ab47406a138d4b66c601de0}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T26@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T26}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T26@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T26}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T26}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T26~0x3\-A}}\label{MAX6956_8h_ae0c19d326ab47406a138d4b66c601de0} - - -Definition at line 291 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_ae1219ad62d3ea1b3a86c52736d347618}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T27@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T27}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T27@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T27}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T27}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T27~0x3\-B}}\label{MAX6956_8h_ae1219ad62d3ea1b3a86c52736d347618} - - -Definition at line 292 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a07ff69092b95f43595762554c3e35329}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T28@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T28}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T28@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T28}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T28}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T28~0x3\-C}}\label{MAX6956_8h_a07ff69092b95f43595762554c3e35329} - - -Definition at line 294 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a6be82fa185d6c3dd272200727c15f4ac}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T29@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T29}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T29@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T29}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T29}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T29~0x3\-D}}\label{MAX6956_8h_a6be82fa185d6c3dd272200727c15f4ac} - - -Definition at line 295 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_aa3e011deb16e7054e78e6f71ac33fcba}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T3@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T3}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T3@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T3}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T3}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T3~0x23}}\label{MAX6956_8h_aa3e011deb16e7054e78e6f71ac33fcba} - - -(virtual port, no action) - - - -Definition at line 265 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a34c02dca8e8a97488eb0be51f682cf73}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T30@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T30}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T30@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T30}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T30}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T30~0x3\-E}}\label{MAX6956_8h_a34c02dca8e8a97488eb0be51f682cf73} - - -Definition at line 296 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a891d2a47a2fe5a4da056a7732fb6098b}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T31@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T31}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T31@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T31}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T31}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T31~0x3\-F}}\label{MAX6956_8h_a891d2a47a2fe5a4da056a7732fb6098b} - - -Definition at line 297 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a68339cee27681486c99dabf398f487a0}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T4@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T4}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T4@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T4}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T4}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T4~0x24}}\label{MAX6956_8h_a68339cee27681486c99dabf398f487a0} - - -Definition at line 267 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a92c4653a42f8400a30aa13a60dbc056f}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T5@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T5}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T5@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T5}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T5}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T5~0x25}}\label{MAX6956_8h_a92c4653a42f8400a30aa13a60dbc056f} - - -Definition at line 268 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a5af96fba8e40466303a2bcec16df6c6f}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T6@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T6}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T6@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T6}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T6}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T6~0x26}}\label{MAX6956_8h_a5af96fba8e40466303a2bcec16df6c6f} - - -Definition at line 269 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a20de98d6d2102960000a70b4bcf6007c}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T7@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T7}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T7@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T7}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T7}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T7~0x27}}\label{MAX6956_8h_a20de98d6d2102960000a70b4bcf6007c} - - -Definition at line 270 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_ad0ea7dd1027b558df290150b664b0222}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T8@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T8}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T8@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T8}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T8}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T8~0x28}}\label{MAX6956_8h_ad0ea7dd1027b558df290150b664b0222} - - -Definition at line 271 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a7d31adbda8965d0d7df0c521571e135c}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T9@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T9}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T9@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T9}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T9}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T9~0x29}}\label{MAX6956_8h_a7d31adbda8965d0d7df0c521571e135c} - - -Definition at line 272 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_aa9837d30cb5f9c9badf20fe50ea3ba26}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S10\-\_\-17@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S10\-\_\-17}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S10\-\_\-17@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S10\-\_\-17}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S10\-\_\-17}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S10\-\_\-17~0x4\-A}}\label{MAX6956_8h_aa9837d30cb5f9c9badf20fe50ea3ba26} - - -Definition at line 315 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a40bf1528e6a7345e0aaa3b86869f3af3}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S11\-\_\-18@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S11\-\_\-18}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S11\-\_\-18@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S11\-\_\-18}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S11\-\_\-18}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S11\-\_\-18~0x4\-B}}\label{MAX6956_8h_a40bf1528e6a7345e0aaa3b86869f3af3} - - -Definition at line 316 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_ab3e1f8d0b913acae6d73f9b5b0d491ff}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S12\-\_\-19@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S12\-\_\-19}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S12\-\_\-19@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S12\-\_\-19}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S12\-\_\-19}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S12\-\_\-19~0x4\-C}}\label{MAX6956_8h_ab3e1f8d0b913acae6d73f9b5b0d491ff} - - -Definition at line 317 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_ad33d71fa8457fcdb444179768a6376e9}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S13\-\_\-20@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S13\-\_\-20}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S13\-\_\-20@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S13\-\_\-20}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S13\-\_\-20}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S13\-\_\-20~0x4\-D}}\label{MAX6956_8h_ad33d71fa8457fcdb444179768a6376e9} - - -Definition at line 318 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_aeae655678f9a39b8a7f6e9de1a09c59e}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S14\-\_\-21@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S14\-\_\-21}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S14\-\_\-21@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S14\-\_\-21}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S14\-\_\-21}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S14\-\_\-21~0x4\-E}}\label{MAX6956_8h_aeae655678f9a39b8a7f6e9de1a09c59e} - - -Definition at line 319 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a853b18f366e225131135f6576268a461}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S15\-\_\-22@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S15\-\_\-22}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S15\-\_\-22@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S15\-\_\-22}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S15\-\_\-22}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S15\-\_\-22~0x4\-F}}\label{MAX6956_8h_a853b18f366e225131135f6576268a461} - - -Definition at line 320 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a39c1bb286953031fad9c101604d6f56e}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S16\-\_\-23@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S16\-\_\-23}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S16\-\_\-23@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S16\-\_\-23}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S16\-\_\-23}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S16\-\_\-23~0x50}}\label{MAX6956_8h_a39c1bb286953031fad9c101604d6f56e} - - -Definition at line 321 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a8a4536b80e588a3ed6bb2f487499efeb}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S17\-\_\-24@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S17\-\_\-24}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S17\-\_\-24@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S17\-\_\-24}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S17\-\_\-24}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S17\-\_\-24~0x51}}\label{MAX6956_8h_a8a4536b80e588a3ed6bb2f487499efeb} - - -Definition at line 322 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a1ae324a27c0648b831978991a44ee33f}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S18\-\_\-25@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S18\-\_\-25}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S18\-\_\-25@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S18\-\_\-25}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S18\-\_\-25}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S18\-\_\-25~0x52}}\label{MAX6956_8h_a1ae324a27c0648b831978991a44ee33f} - - -Definition at line 323 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a981a54414024fdd2877704d4d242b748}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S19\-\_\-26@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S19\-\_\-26}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S19\-\_\-26@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S19\-\_\-26}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S19\-\_\-26}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S19\-\_\-26~0x53}}\label{MAX6956_8h_a981a54414024fdd2877704d4d242b748} - - -Definition at line 324 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_abd2280465476a9e3cae302d5e9bf7b62}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S20\-\_\-27@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S20\-\_\-27}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S20\-\_\-27@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S20\-\_\-27}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S20\-\_\-27}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S20\-\_\-27~0x54}}\label{MAX6956_8h_abd2280465476a9e3cae302d5e9bf7b62} - - -Definition at line 325 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_adfca6218829cec2697e0975fc7965008}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S21\-\_\-28@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S21\-\_\-28}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S21\-\_\-28@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S21\-\_\-28}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S21\-\_\-28}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S21\-\_\-28~0x55}}\label{MAX6956_8h_adfca6218829cec2697e0975fc7965008} - - -Definition at line 326 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_aa190f6504c585b64f355ce45a24057f1}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S22\-\_\-29@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S22\-\_\-29}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S22\-\_\-29@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S22\-\_\-29}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S22\-\_\-29}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S22\-\_\-29~0x56}}\label{MAX6956_8h_aa190f6504c585b64f355ce45a24057f1} - - -Definition at line 327 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a9ae64dcdc091a17982f4888bcd7b1981}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S23\-\_\-30@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S23\-\_\-30}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S23\-\_\-30@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S23\-\_\-30}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S23\-\_\-30}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S23\-\_\-30~0x57}}\label{MAX6956_8h_a9ae64dcdc091a17982f4888bcd7b1981} - - -Definition at line 328 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a5054da2b077f91e7f6106373a84476ed}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S24\-\_\-31@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S24\-\_\-31}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S24\-\_\-31@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S24\-\_\-31}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S24\-\_\-31}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S24\-\_\-31~0x58}}\label{MAX6956_8h_a5054da2b077f91e7f6106373a84476ed} - - -Definition at line 329 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a38a7fe545ab1b4ca108dabcef50d015f}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S25\-\_\-31@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S25\-\_\-31}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S25\-\_\-31@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S25\-\_\-31}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S25\-\_\-31}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S25\-\_\-31~0x59}}\label{MAX6956_8h_a38a7fe545ab1b4ca108dabcef50d015f} - - -data bits D0-\/\-D6; D7 reads as 0 - - - -Definition at line 333 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_ac804c8074d5a6baf79b0595415ae0679}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S26\-\_\-31@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S26\-\_\-31}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S26\-\_\-31@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S26\-\_\-31}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S26\-\_\-31}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S26\-\_\-31~0x5\-A}}\label{MAX6956_8h_ac804c8074d5a6baf79b0595415ae0679} - - -data bits D0-\/\-D5; D6-\/\-D7 read as 0 - - - -Definition at line 334 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a5307d28ebcae5028fc482c914eecf48f}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S27\-\_\-31@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S27\-\_\-31}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S27\-\_\-31@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S27\-\_\-31}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S27\-\_\-31}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S27\-\_\-31~0x5\-B}}\label{MAX6956_8h_a5307d28ebcae5028fc482c914eecf48f} - - -data bits D0-\/\-D4; D5-\/\-D7 read as 0 - - - -Definition at line 335 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a7554adf2b4214f33584001f4e7c81053}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S28\-\_\-31@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S28\-\_\-31}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S28\-\_\-31@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S28\-\_\-31}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S28\-\_\-31}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S28\-\_\-31~0x5\-C}}\label{MAX6956_8h_a7554adf2b4214f33584001f4e7c81053} - - -data bits D0-\/\-D3; D4-\/\-D7 read as 0 - - - -Definition at line 336 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_ab278f8cb075460b9318c029bca24e68a}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S29\-\_\-31@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S29\-\_\-31}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S29\-\_\-31@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S29\-\_\-31}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S29\-\_\-31}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S29\-\_\-31~0x5\-D}}\label{MAX6956_8h_ab278f8cb075460b9318c029bca24e68a} - - -data bits D0-\/\-D2; D3-\/\-D7 read as 0 - - - -Definition at line 337 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_ae5873266ac57220286709a468781c3ff}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S30\-\_\-31@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S30\-\_\-31}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S30\-\_\-31@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S30\-\_\-31}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S30\-\_\-31}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S30\-\_\-31~0x5\-E}}\label{MAX6956_8h_ae5873266ac57220286709a468781c3ff} - - -data bits D0-\/\-D1; D2-\/\-D7 read as 0 - - - -Definition at line 338 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_ad12b528f7fa63249d37126a8d4049aab}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S31\-\_\-31@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S31\-\_\-31}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S31\-\_\-31@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S31\-\_\-31}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S31\-\_\-31}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S31\-\_\-31~0x5\-F}}\label{MAX6956_8h_ad12b528f7fa63249d37126a8d4049aab} - - -data bit D0; D1-\/\-D7 read as 0. Port 31 only. - - - -Definition at line 339 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_ac32650edffdebee3cfeb90c9daece88b}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-10@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-10}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-10@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-10}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-10}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-10~0x43}}\label{MAX6956_8h_ac32650edffdebee3cfeb90c9daece88b} - - -data bits D0-\/\-D6; D7 reads as 0 - - - -Definition at line 304 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a4b0cc79ee765d2f477953a890b2f6209}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-11@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-11}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-11@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-11}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-11}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-11~0x44}}\label{MAX6956_8h_a4b0cc79ee765d2f477953a890b2f6209} - - -Definition at line 309 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a00bff40ca66a7c82b7093536c5047da4}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-7@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-7}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-7@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-7}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-7}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-7~0x40}}\label{MAX6956_8h_a00bff40ca66a7c82b7093536c5047da4} - - -data bits D0-\/\-D3; D4-\/\-D7 read as 0 - - - -Definition at line 301 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a3d1cd4727f1748e42a0426c0b70d9c2c}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-8@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-8}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-8@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-8}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-8}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-8~0x41}}\label{MAX6956_8h_a3d1cd4727f1748e42a0426c0b70d9c2c} - - -data bits D0-\/\-D4; D5-\/\-D7 read as 0 - - - -Definition at line 302 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_ad1b71a2b24de60a4d0128576c0e1278b}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-9@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-9}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-9@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-9}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-9}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S4\-\_\-9~0x42}}\label{MAX6956_8h_ad1b71a2b24de60a4d0128576c0e1278b} - - -data bits D0-\/\-D5; D6-\/\-D7 read as 0 - - - -Definition at line 303 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a13b8eb94b73c20a02397e50c81bccb57}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S5\-\_\-12@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S5\-\_\-12}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S5\-\_\-12@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S5\-\_\-12}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S5\-\_\-12}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S5\-\_\-12~0x45}}\label{MAX6956_8h_a13b8eb94b73c20a02397e50c81bccb57} - - -Definition at line 310 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_af01fef127c33b806d570f1d46a90362f}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S6\-\_\-13@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S6\-\_\-13}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S6\-\_\-13@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S6\-\_\-13}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S6\-\_\-13}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S6\-\_\-13~0x46}}\label{MAX6956_8h_af01fef127c33b806d570f1d46a90362f} - - -Definition at line 311 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_ae0f37de2a929dc6f37733c3f112e0fa7}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S7\-\_\-14@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S7\-\_\-14}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S7\-\_\-14@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S7\-\_\-14}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S7\-\_\-14}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S7\-\_\-14~0x47}}\label{MAX6956_8h_ae0f37de2a929dc6f37733c3f112e0fa7} - - -Definition at line 312 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_ae2bd6458f4aa0271d7fb9c8c8fdd0e4f}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S8\-\_\-15@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S8\-\_\-15}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S8\-\_\-15@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S8\-\_\-15}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S8\-\_\-15}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S8\-\_\-15~0x48}}\label{MAX6956_8h_ae2bd6458f4aa0271d7fb9c8c8fdd0e4f} - - -Definition at line 313 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_aedb8b7ecadabaf8290ac1eacde7db918}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S9\-\_\-16@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S9\-\_\-16}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S9\-\_\-16@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S9\-\_\-16}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S9\-\_\-16}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T\-S9\-\_\-16~0x49}}\label{MAX6956_8h_aedb8b7ecadabaf8290ac1eacde7db918} - - -Definition at line 314 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a4a2b4c395e47e0ec9ef49d3236b8a465}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-R\-A\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-D\-E\-T\-E\-C\-T@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-D\-E\-T\-E\-C\-T}} -\index{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-D\-E\-T\-E\-C\-T@{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-D\-E\-T\-E\-C\-T}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-D\-E\-T\-E\-C\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-R\-A\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-D\-E\-T\-E\-C\-T~0x06}}\label{MAX6956_8h_a4a2b4c395e47e0ec9ef49d3236b8a465} -\subsection*{Table 15. Transition Detection Mask Register } - -\begin{TabularC}{11} -\hline -\rowcolor{lightgray}{\bf F\-U\-N\-C\-T\-I\-O\-N }&{\bf R\-E\-G\-I\-S\-T\-E\-R A\-D\-D\-R\-E\-S\-S }&{\bf R\-E\-A\-D/\-W\-R\-I\-T\-E }&{\bf D7 }&{\bf D6 }&{\bf D5 }&{\bf D4 }&{\bf D3 }&{\bf D2 }&{\bf D1 }&{\bf D0 }\\\cline{1-11} -Mask Register &0x06 &Read &I\-N\-T Status$\ast$&Port&Port&Port&Port&Port&Port&Port \\\cline{1-11} -&&&&30 &29 &28 &27 &26 &25 &24 \\\cline{1-11} -&&Write &Unchanged &mask&mask&mask&mask&mask&mask&mask \\\cline{1-11} -\end{TabularC} -I\-N\-T is automatically cleared after it is read. - -Definition at line 152 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_abc801853bdfe66591265d04865aba78f}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-B\-I\-T}} -\index{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-B\-I\-T~0}}\label{MAX6956_8h_abc801853bdfe66591265d04865aba78f} - - -Ports 24-\/30. - - - -Definition at line 394 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a332868e8a1596e785072ddb8c4a2b4c1}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-L\-E\-N\-G\-T\-H}} -\index{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-L\-E\-N\-G\-T\-H@{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-L\-E\-N\-G\-T\-H}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-L\-E\-N\-G\-T\-H}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-L\-E\-N\-G\-T\-H~7}}\label{MAX6956_8h_a332868e8a1596e785072ddb8c4a2b4c1} - - -Definition at line 395 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a0a2eb488b9b8d16b5c076d25790ec28e}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T24\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T24\-\_\-\-B\-I\-T}} -\index{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T24\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T24\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T24\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T24\-\_\-\-B\-I\-T~0}}\label{MAX6956_8h_a0a2eb488b9b8d16b5c076d25790ec28e} - - -Definition at line 402 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a04d331f867fa51822f5910ce2b6b891c}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T25\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T25\-\_\-\-B\-I\-T}} -\index{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T25\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T25\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T25\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T25\-\_\-\-B\-I\-T~1}}\label{MAX6956_8h_a04d331f867fa51822f5910ce2b6b891c} - - -Definition at line 401 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_ac4f63f4afc199c41dd9b1445259b8d50}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T26\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T26\-\_\-\-B\-I\-T}} -\index{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T26\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T26\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T26\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T26\-\_\-\-B\-I\-T~2}}\label{MAX6956_8h_ac4f63f4afc199c41dd9b1445259b8d50} - - -Definition at line 400 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a282091cda715bb27f96266f5ae22b492}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T27\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T27\-\_\-\-B\-I\-T}} -\index{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T27\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T27\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T27\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T27\-\_\-\-B\-I\-T~3}}\label{MAX6956_8h_a282091cda715bb27f96266f5ae22b492} - - -Definition at line 399 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a927e5369f33337fdea8d89ccc3b3919d}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T28\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T28\-\_\-\-B\-I\-T}} -\index{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T28\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T28\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T28\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T28\-\_\-\-B\-I\-T~4}}\label{MAX6956_8h_a927e5369f33337fdea8d89ccc3b3919d} - - -Definition at line 398 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a74adf7234472da3287cb98af583750c9}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T29\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T29\-\_\-\-B\-I\-T}} -\index{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T29\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T29\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T29\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T29\-\_\-\-B\-I\-T~5}}\label{MAX6956_8h_a74adf7234472da3287cb98af583750c9} - - -Definition at line 397 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a0e7f62a1c7d77019ca8ca2c2511f2644}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T30\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T30\-\_\-\-B\-I\-T}} -\index{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T30\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T30\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T30\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-M\-A\-S\-K\-\_\-\-P\-O\-R\-T30\-\_\-\-B\-I\-T~6}}\label{MAX6956_8h_a0e7f62a1c7d77019ca8ca2c2511f2644} - - -Definition at line 396 of file M\-A\-X6956.\-h. - -\hypertarget{MAX6956_8h_a29bd01905e66b503151e6d9cdfb035a1}{\index{M\-A\-X6956.\-h@{M\-A\-X6956.\-h}!M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-S\-T\-A\-T\-U\-S\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-S\-T\-A\-T\-U\-S\-\_\-\-B\-I\-T}} -\index{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-S\-T\-A\-T\-U\-S\-\_\-\-B\-I\-T@{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-S\-T\-A\-T\-U\-S\-\_\-\-B\-I\-T}!MAX6956.h@{M\-A\-X6956.\-h}} -\subsubsection[{M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-S\-T\-A\-T\-U\-S\-\_\-\-B\-I\-T}]{\setlength{\rightskip}{0pt plus 5cm}\#define M\-A\-X6956\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-S\-T\-A\-T\-U\-S\-\_\-\-B\-I\-T~7}}\label{MAX6956_8h_a29bd01905e66b503151e6d9cdfb035a1} - - -I\-N\-T Status, I\-N\-T is automatically cleared after it is read. - - - -Definition at line 393 of file M\-A\-X6956.\-h. - diff --git a/Arduino/MAX6956/latex/Makefile b/Arduino/MAX6956/latex/Makefile deleted file mode 100644 index 3cc085fe..00000000 --- a/Arduino/MAX6956/latex/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -all: refman.pdf - -pdf: refman.pdf - -refman.pdf: clean refman.tex - pdflatex refman - makeindex refman.idx - pdflatex refman - latex_count=5 ; \ - while egrep -s 'Rerun (LaTeX|to get cross-references right)' refman.log && [ $$latex_count -gt 0 ] ;\ - do \ - echo "Rerunning latex...." ;\ - pdflatex refman ;\ - latex_count=`expr $$latex_count - 1` ;\ - done - makeindex refman.idx - pdflatex refman - - -clean: - rm -f *.ps *.dvi *.aux *.toc *.idx *.ind *.ilg *.log *.out *.brf *.blg *.bbl refman.pdf diff --git a/Arduino/MAX6956/latex/annotated.tex b/Arduino/MAX6956/latex/annotated.tex deleted file mode 100644 index 3409b9d9..00000000 --- a/Arduino/MAX6956/latex/annotated.tex +++ /dev/null @@ -1,4 +0,0 @@ -\section{Data Structures} -Here are the data structures with brief descriptions\-:\begin{DoxyCompactList} -\item\contentsline{section}{\hyperlink{classMAX6956}{M\-A\-X6956} }{\pageref{classMAX6956}}{} -\end{DoxyCompactList} diff --git a/Arduino/MAX6956/latex/classMAX6956.tex b/Arduino/MAX6956/latex/classMAX6956.tex deleted file mode 100644 index 8b4ad093..00000000 --- a/Arduino/MAX6956/latex/classMAX6956.tex +++ /dev/null @@ -1,825 +0,0 @@ -\hypertarget{classMAX6956}{\section{M\-A\-X6956 Class Reference} -\label{classMAX6956}\index{M\-A\-X6956@{M\-A\-X6956}} -} - - -{\ttfamily \#include $<$M\-A\-X6956.\-h$>$} - -\subsection*{Public Member Functions} -\begin{DoxyCompactItemize} -\item -\hyperlink{classMAX6956_a210d9e95978d61357db757cb80475bde}{M\-A\-X6956} () -\item -\hyperlink{classMAX6956_a1a7b33190871a09d81c5bec741b645b7}{M\-A\-X6956} (uint8\-\_\-t address) -\item -void \hyperlink{classMAX6956_ad63e927adc2427b4b661f2422ddd40d8}{initialize} () -\item -bool \hyperlink{classMAX6956_a60bd352328d77e59a4d51a3c55d38a25}{test\-Connection} () -\item -void \hyperlink{classMAX6956_a3b9166eee826a876bbf29bc63b090fe7}{reset} () -\item -uint8\-\_\-t \hyperlink{classMAX6956_a5e787204b3f7bf8750376f5bdf77a971}{get\-Config\-Reg} () -\item -void \hyperlink{classMAX6956_ad06b9ed9f6e18f81d8379a6e10391ea4}{set\-Config\-Reg} (uint8\-\_\-t config) -\item -bool \hyperlink{classMAX6956_acdc18c36735d8015651d4e3c75da4300}{get\-Power} () -\item -void \hyperlink{classMAX6956_a993f35d31d1f2489f9d2965c3886f848}{toggle\-Power} () -\item -void \hyperlink{classMAX6956_ae10ac505e3857d31ca3823225983a697}{set\-Power} (bool power) -\item -bool \hyperlink{classMAX6956_abcfe81dd0ffc90284f19503b6366dcfb}{get\-Enable\-Individual\-Current} () -\item -void \hyperlink{classMAX6956_a35bc5701a290409144929e640cad1748}{set\-Enable\-Individual\-Current} (bool global) -\item -bool \hyperlink{classMAX6956_a76e9ab35769854b3e4224499897601ec}{get\-Enable\-Transition\-Detection} () -\item -void \hyperlink{classMAX6956_a67b65b80e09a3225dd4f6413bfab2844}{set\-Enable\-Transition\-Detection} (bool transition) -\item -uint8\-\_\-t \hyperlink{classMAX6956_a1926760b263588314fd759d129091940}{get\-Global\-Current} () -\item -void \hyperlink{classMAX6956_a4669dcc0f2f89f8fe73a0fa9b97dae21}{set\-Global\-Current} (uint8\-\_\-t current) -\item -bool \hyperlink{classMAX6956_ad4f99f08d1cf08c5a0097215e680a80a}{get\-Test\-Mode} () -\item -void \hyperlink{classMAX6956_ad1b4e5cafd91acd2be2b6fb8197afef0}{set\-Test\-Mode} (bool test) -\item -uint8\-\_\-t \hyperlink{classMAX6956_a56245915d7d4cd8fd34629bd91695147}{get\-Input\-Mask} () -\item -void \hyperlink{classMAX6956_a7ce45652fb0490af0ecb4eaebc230419}{set\-Input\-Mask} (uint8\-\_\-t mask) -\item -void \hyperlink{classMAX6956_a5e05bead41c585c68de79bbfed971d19}{config\-Port} (uint8\-\_\-t port, uint8\-\_\-t \hyperlink{classMAX6956_a9799e7684546e3e9b24506d436586a09}{port\-Config}) -\item -void \hyperlink{classMAX6956_a400393e30fbe196aef43d8edea890228}{config\-Ports} (uint8\-\_\-t lower, uint8\-\_\-t upper, uint8\-\_\-t \hyperlink{classMAX6956_a9799e7684546e3e9b24506d436586a09}{port\-Config}) -\item -void \hyperlink{classMAX6956_a9e9f11c46bdc86d8e882ed8bb5efabdf}{config\-All\-Ports} (uint8\-\_\-t \hyperlink{classMAX6956_a9799e7684546e3e9b24506d436586a09}{port\-Config}) -\item -void \hyperlink{classMAX6956_a98fa3831a47355fe0856caa74a9cf810}{set\-Port\-Level} (uint8\-\_\-t port, uint8\-\_\-t power) -\begin{DoxyCompactList}\small\item\em 0 = off, 1-\/15 brightness levels. \end{DoxyCompactList}\item -void \hyperlink{classMAX6956_a76a617f3b8982bb3855c5152b480097a}{set\-Port\-Current} (uint8\-\_\-t port, uint8\-\_\-t power) -\begin{DoxyCompactList}\small\item\em 0-\/15 brightness levels. \end{DoxyCompactList}\item -void \hyperlink{classMAX6956_a9a27a32611fa05766946c33850510644}{set\-All\-Ports\-Current} (uint8\-\_\-t power) -\begin{DoxyCompactList}\small\item\em 0-\/15, 0 = min brightness (not off) 15 = max \end{DoxyCompactList}\item -void \hyperlink{classMAX6956_a51a47c1f69532e96c6caa357889004e3}{enable\-All\-Ports} () -\item -void \hyperlink{classMAX6956_a93a81ff86316f63ee1ada3529da2a95b}{disable\-All\-Ports} () -\end{DoxyCompactItemize} -\subsection*{Data Fields} -\begin{DoxyCompactItemize} -\item -uint8\-\_\-t \hyperlink{classMAX6956_a8b915615042c5ef96fbf3a5c260d4716}{ports\-Config} \mbox{[}5\mbox{]} -\item -uint8\-\_\-t \hyperlink{classMAX6956_ae8da9a65da74dce7eb907319b0198847}{ports\-Status} \mbox{[}3\mbox{]} -\end{DoxyCompactItemize} -\subsection*{Private Attributes} -\begin{DoxyCompactItemize} -\item -uint8\-\_\-t \hyperlink{classMAX6956_a6ba2f8011914df50d6022ab54b27748d}{dev\-Addr} -\begin{DoxyCompactList}\small\item\em Holds the current device address. \end{DoxyCompactList}\item -uint8\-\_\-t \hyperlink{classMAX6956_a9f4597436b10ee86a02c96c2b0605851}{buffer} \mbox{[}1\mbox{]} -\begin{DoxyCompactList}\small\item\em Buffer for reading data from the device. \end{DoxyCompactList}\item -uint8\-\_\-t \hyperlink{classMAX6956_a9799e7684546e3e9b24506d436586a09}{port\-Config} -\begin{DoxyCompactList}\small\item\em Holder for port config bit pair. \end{DoxyCompactList}\item -uint8\-\_\-t \hyperlink{classMAX6956_ab0d382db3afe7930d1b95311bfd90164}{port\-Current\-R\-A} -\begin{DoxyCompactList}\small\item\em Holder for port current register. \end{DoxyCompactList}\item -uint8\-\_\-t \hyperlink{classMAX6956_ad3057b6b21ae712acb0129270da63334}{port\-Current\-Bit} -\begin{DoxyCompactList}\small\item\em Holder for the current bit offset. \end{DoxyCompactList}\item -uint8\-\_\-t \hyperlink{classMAX6956_a967e25fac00c0ab59be854289eb36353}{ps\-Array\-Index} -\begin{DoxyCompactList}\small\item\em array index \end{DoxyCompactList}\item -uint8\-\_\-t \hyperlink{classMAX6956_a92b5dc05a1483c49c150db13dcd1f283}{ps\-Bit\-Position} -\begin{DoxyCompactList}\small\item\em bit position \end{DoxyCompactList}\end{DoxyCompactItemize} - - -\subsection{Detailed Description} -A library for controlling the \hyperlink{classMAX6956}{M\-A\-X6956} using i2\-C. - -The \hyperlink{classMAX6956}{M\-A\-X6956} compact, serial-\/interfaced L\-E\-D display driver/\-I/\-O expander provide microprocessors with up to 28 ports. Each port is individually user configurable to either a logic input, logic output, or common-\/anode (C\-A) L\-E\-D constant-\/current segment driver. Each port configured as an L\-E\-D segment driver behaves as a digitally controlled constant-\/current sink, with 16 equal current steps from 1.\-5m\-A to 24m\-A. The L\-E\-D drivers are suitable for both discrete L\-E\-Ds and C\-A numeric and alphanumeric L\-E\-D digits. - -Each port configured as a general-\/purpose I/\-O (G\-P\-I\-O) can be either a push-\/pull logic output capable of sink-\/ ing 10m\-A and sourcing 4.\-5m\-A, or a Schmitt logic input with optional internal pullup. Seven ports feature config-\/ urable transition detection logic, which generates an interrupt upon change of port logic level. The \hyperlink{classMAX6956}{M\-A\-X6956} is controlled through an I2\-C-\/compatible 2-\/wire serial interface, and uses four-\/level logic to allow 16 I 2\-C addresses from only 2 select pins. - -The M\-A\-X6956\-A\-A\-X and M\-A\-X6956\-A\-T\-L have 28 ports and are available in 36-\/pin S\-S\-O\-P and 40-\/pin thin Q\-F\-N packages, respectively. The M\-A\-X6956\-A\-A\-I and M\-A\-X6956\-A\-N\-I have 20 ports and are available in 28-\/pin S\-S\-O\-P and 28-\/pin D\-I\-P packages, respectively. - -For an S\-P\-I-\/interfaced version, refer to the M\-A\-X6957 data sheet. For a lower cost pin-\/compatible port expander without the constant-\/current L\-E\-D drive capa-\/ bility, refer to the M\-A\-X7300 data sheet. - - -\begin{DoxyItemize} -\item 400kbps I2\-C-\/\-Compatible Serial Interface -\item 2.\-5\-V to 5.\-5\-V Operation -\item -\/40°\-C to +125°\-C Temperature Range -\item 20 or 28 I/\-O Ports, Each Configurable as -\item Constant-\/\-Current L\-E\-D Driver -\item Push-\/\-Pull Logic Output -\item Schmitt Logic Input -\item Schmitt Logic Input with Internal Pullup -\item 11μ\-A (max) Shutdown Current -\item 16-\/\-Step Individually Programmable Current -\item Control for Each L\-E\-D -\item Logic Transition Detection for Seven I/\-O Ports -\end{DoxyItemize} - -Definition at line 456 of file M\-A\-X6956.\-h. - - - -\subsection{Constructor \& Destructor Documentation} -\hypertarget{classMAX6956_a210d9e95978d61357db757cb80475bde}{\index{M\-A\-X6956@{M\-A\-X6956}!M\-A\-X6956@{M\-A\-X6956}} -\index{M\-A\-X6956@{M\-A\-X6956}!MAX6956@{M\-A\-X6956}} -\subsubsection[{M\-A\-X6956}]{\setlength{\rightskip}{0pt plus 5cm}M\-A\-X6956\-::\-M\-A\-X6956 ( -\begin{DoxyParamCaption} -{} -\end{DoxyParamCaption} -)}}\label{classMAX6956_a210d9e95978d61357db757cb80475bde} -Default constructor, uses default I2\-C address. \begin{DoxySeeAlso}{See Also} -\hyperlink{MAX6956_8h_a4ca90873afdfdacaa730ed5db53e2f5b}{M\-A\-X6956\-\_\-\-D\-E\-F\-A\-U\-L\-T\-\_\-\-A\-D\-D\-R\-E\-S\-S} -\end{DoxySeeAlso} - - -Definition at line 40 of file M\-A\-X6956.\-cpp. - -\hypertarget{classMAX6956_a1a7b33190871a09d81c5bec741b645b7}{\index{M\-A\-X6956@{M\-A\-X6956}!M\-A\-X6956@{M\-A\-X6956}} -\index{M\-A\-X6956@{M\-A\-X6956}!MAX6956@{M\-A\-X6956}} -\subsubsection[{M\-A\-X6956}]{\setlength{\rightskip}{0pt plus 5cm}M\-A\-X6956\-::\-M\-A\-X6956 ( -\begin{DoxyParamCaption} -\item[{uint8\-\_\-t}]{address} -\end{DoxyParamCaption} -)}}\label{classMAX6956_a1a7b33190871a09d81c5bec741b645b7} -Specific address constructor. -\begin{DoxyParams}{Parameters} -{\em address} & I2\-C address \\ -\hline -\end{DoxyParams} -\begin{DoxySeeAlso}{See Also} -\hyperlink{MAX6956_8h_a4ca90873afdfdacaa730ed5db53e2f5b}{M\-A\-X6956\-\_\-\-D\-E\-F\-A\-U\-L\-T\-\_\-\-A\-D\-D\-R\-E\-S\-S} - -\hyperlink{MAX6956_8h_a33e60623a4c5b483d4604fe2c9b91be7}{M\-A\-X6956\-\_\-\-A\-D\-D\-R\-E\-S\-S} -\end{DoxySeeAlso} - - -Definition at line 49 of file M\-A\-X6956.\-cpp. - - - -\subsection{Member Function Documentation} -\hypertarget{classMAX6956_a9e9f11c46bdc86d8e882ed8bb5efabdf}{\index{M\-A\-X6956@{M\-A\-X6956}!config\-All\-Ports@{config\-All\-Ports}} -\index{config\-All\-Ports@{config\-All\-Ports}!MAX6956@{M\-A\-X6956}} -\subsubsection[{config\-All\-Ports}]{\setlength{\rightskip}{0pt plus 5cm}void M\-A\-X6956\-::config\-All\-Ports ( -\begin{DoxyParamCaption} -\item[{uint8\-\_\-t}]{port\-Config} -\end{DoxyParamCaption} -)}}\label{classMAX6956_a9e9f11c46bdc86d8e882ed8bb5efabdf} -\begin{DoxyVerb}Configure all ports the same -\end{DoxyVerb} - -\begin{DoxyParams}{Parameters} -{\em port\-Config} & Valid options are\-: M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-L\-E\-D, M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-G\-P\-I\-O, M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-O\-\_\-\-P\-U\-L\-L, M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-\_\-\-P\-U\-L\-L \\ -\hline -\end{DoxyParams} -\begin{DoxySeeAlso}{See Also} -\hyperlink{MAX6956_8h_ad6490a909085059c4300a51dcebbf7bc}{M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-L\-E\-D} - -\hyperlink{MAX6956_8h_a27f6ca524d4c18623762c722d9993c10}{M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-G\-P\-I\-O} - -\hyperlink{MAX6956_8h_ab05f3186e2515bab3a536ad9f1cbb7db}{M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-O\-\_\-\-P\-U\-L\-L} - -\hyperlink{MAX6956_8h_a68fc1bc750b7959fbab7e64f79589b83}{M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-\_\-\-P\-U\-L\-L} -\end{DoxySeeAlso} - - -Definition at line 332 of file M\-A\-X6956.\-cpp. - -\hypertarget{classMAX6956_a5e05bead41c585c68de79bbfed971d19}{\index{M\-A\-X6956@{M\-A\-X6956}!config\-Port@{config\-Port}} -\index{config\-Port@{config\-Port}!MAX6956@{M\-A\-X6956}} -\subsubsection[{config\-Port}]{\setlength{\rightskip}{0pt plus 5cm}void M\-A\-X6956\-::config\-Port ( -\begin{DoxyParamCaption} -\item[{uint8\-\_\-t}]{port, } -\item[{uint8\-\_\-t}]{port\-Config} -\end{DoxyParamCaption} -)}}\label{classMAX6956_a5e05bead41c585c68de79bbfed971d19} -\begin{DoxyVerb}Takes an INDIVIDUAL port register address (MAX6956_RA_PORT12, ect) -and configures it as: MAX6956_OUTPUT_LED, MAX6956_OUTPUT_GPIO, -MAX6956_INPUT_WO_PULL, or MAX6956_INPUT_W_PULL -\end{DoxyVerb} - - -\subsubsection*{Port registers } - -\begin{TabularC}{2} -\hline -\rowcolor{lightgray}\PBS\centering {\bf Addr. }&\PBS\centering {\bf Name }\\\cline{1-2} -\PBS\centering 0x09 &\PBS\centering M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P7\-P6\-P5\-P4 \\\cline{1-2} -\PBS\centering 0x0\-A &\PBS\centering M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P11\-P10\-P9\-P8 \\\cline{1-2} -\PBS\centering 0x0\-B &\PBS\centering M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P15\-P14\-P13\-P12 \\\cline{1-2} -\PBS\centering 0x0\-C &\PBS\centering M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P19\-P18\-P17\-P16 \\\cline{1-2} -\PBS\centering 0x0\-D &\PBS\centering M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P23\-P22\-P21\-P20 \\\cline{1-2} -\PBS\centering 0x0\-E &\PBS\centering M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P27\-P26\-P25\-P24 \\\cline{1-2} -\PBS\centering 0x0\-F &\PBS\centering M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-\_\-\-P31\-P30\-P29\-P28 \\\cline{1-2} -\end{TabularC} -\begin{TabularC}{6} -\hline -\rowcolor{lightgray}\PBS\centering {\bf Num}&\PBS\centering {\bf Dec}&\PBS\centering {\bf Hex }&\PBS\centering {\bf Prt}&\PBS\centering {\bf Port Status Array}&\PBS\centering {\bf Ports Config Array }\\\cline{1-6} -\PBS\centering 00 &\PBS\centering 44 &\PBS\centering 0x2\-C&\PBS\centering P12&\PBS\centering ports\-Status\mbox{[}0\mbox{]}\mbox{[}0\mbox{]}&\PBS\centering ports\-Config\mbox{[}0\mbox{]}\mbox{[}1-\/0\mbox{]} \\\cline{1-6} -\PBS\centering 01 &\PBS\centering 45 &\PBS\centering 0x2\-D&\PBS\centering P13&\PBS\centering ports\-Status\mbox{[}0\mbox{]}\mbox{[}1\mbox{]}&\PBS\centering ports\-Config\mbox{[}0\mbox{]}\mbox{[}3-\/2\mbox{]} \\\cline{1-6} -\PBS\centering 02 &\PBS\centering 46 &\PBS\centering 0x2\-E&\PBS\centering P14&\PBS\centering ports\-Status\mbox{[}0\mbox{]}\mbox{[}2\mbox{]}&\PBS\centering ports\-Config\mbox{[}0\mbox{]}\mbox{[}5-\/4\mbox{]} \\\cline{1-6} -\PBS\centering 03 &\PBS\centering 47 &\PBS\centering 0x2\-F&\PBS\centering P15&\PBS\centering ports\-Status\mbox{[}0\mbox{]}\mbox{[}3\mbox{]}&\PBS\centering ports\-Config\mbox{[}0\mbox{]}\mbox{[}7-\/6\mbox{]} \\\cline{1-6} -\PBS\centering 04 &\PBS\centering 48 &\PBS\centering 0x30&\PBS\centering P16&\PBS\centering ports\-Status\mbox{[}0\mbox{]}\mbox{[}4\mbox{]}&\PBS\centering ports\-Config\mbox{[}1\mbox{]}\mbox{[}1-\/0\mbox{]} \\\cline{1-6} -\PBS\centering 05 &\PBS\centering 49 &\PBS\centering 0x31&\PBS\centering P17&\PBS\centering ports\-Status\mbox{[}0\mbox{]}\mbox{[}5\mbox{]}&\PBS\centering ports\-Config\mbox{[}1\mbox{]}\mbox{[}3-\/2\mbox{]} \\\cline{1-6} -\PBS\centering 06 &\PBS\centering 50 &\PBS\centering 0x32&\PBS\centering P18&\PBS\centering ports\-Status\mbox{[}0\mbox{]}\mbox{[}6\mbox{]}&\PBS\centering ports\-Config\mbox{[}1\mbox{]}\mbox{[}5-\/4\mbox{]} \\\cline{1-6} -\PBS\centering 07 &\PBS\centering 51 &\PBS\centering 0x33&\PBS\centering P19&\PBS\centering ports\-Status\mbox{[}0\mbox{]}\mbox{[}7\mbox{]}&\PBS\centering ports\-Config\mbox{[}1\mbox{]}\mbox{[}7-\/6\mbox{]} \\\cline{1-6} -\PBS\centering 08 &\PBS\centering 52 &\PBS\centering 0x34&\PBS\centering P20&\PBS\centering ports\-Status\mbox{[}1\mbox{]}\mbox{[}0\mbox{]}&\PBS\centering ports\-Config\mbox{[}2\mbox{]}\mbox{[}1-\/0\mbox{]} \\\cline{1-6} -\PBS\centering 09 &\PBS\centering 53 &\PBS\centering 0x35&\PBS\centering P21&\PBS\centering ports\-Status\mbox{[}1\mbox{]}\mbox{[}1\mbox{]}&\PBS\centering ports\-Config\mbox{[}2\mbox{]}\mbox{[}3-\/2\mbox{]} \\\cline{1-6} -\PBS\centering 10 &\PBS\centering 54 &\PBS\centering 0x36&\PBS\centering P22&\PBS\centering ports\-Status\mbox{[}1\mbox{]}\mbox{[}2\mbox{]}&\PBS\centering ports\-Config\mbox{[}2\mbox{]}\mbox{[}5-\/4\mbox{]} \\\cline{1-6} -\PBS\centering 11 &\PBS\centering 55 &\PBS\centering 0x37&\PBS\centering P23&\PBS\centering ports\-Status\mbox{[}1\mbox{]}\mbox{[}3\mbox{]}&\PBS\centering ports\-Config\mbox{[}2\mbox{]}\mbox{[}7-\/6\mbox{]} \\\cline{1-6} -\PBS\centering 12 &\PBS\centering 56 &\PBS\centering 0x38&\PBS\centering P24&\PBS\centering ports\-Status\mbox{[}1\mbox{]}\mbox{[}4\mbox{]}&\PBS\centering ports\-Config\mbox{[}3\mbox{]}\mbox{[}1-\/0\mbox{]} \\\cline{1-6} -\PBS\centering 13 &\PBS\centering 57 &\PBS\centering 0x39&\PBS\centering P25&\PBS\centering ports\-Status\mbox{[}1\mbox{]}\mbox{[}5\mbox{]}&\PBS\centering ports\-Config\mbox{[}3\mbox{]}\mbox{[}3-\/2\mbox{]} \\\cline{1-6} -\PBS\centering 14 &\PBS\centering 58 &\PBS\centering 0x3\-A&\PBS\centering P26&\PBS\centering ports\-Status\mbox{[}1\mbox{]}\mbox{[}6\mbox{]}&\PBS\centering ports\-Config\mbox{[}3\mbox{]}\mbox{[}5-\/4\mbox{]} \\\cline{1-6} -\PBS\centering 15 &\PBS\centering 59 &\PBS\centering 0x3\-B&\PBS\centering P27&\PBS\centering ports\-Status\mbox{[}1\mbox{]}\mbox{[}7\mbox{]}&\PBS\centering ports\-Config\mbox{[}3\mbox{]}\mbox{[}7-\/6\mbox{]} \\\cline{1-6} -\PBS\centering 16 &\PBS\centering 60 &\PBS\centering 0x3\-C&\PBS\centering P28&\PBS\centering ports\-Status\mbox{[}2\mbox{]}\mbox{[}0\mbox{]}&\PBS\centering ports\-Config\mbox{[}4\mbox{]}\mbox{[}1-\/0\mbox{]} \\\cline{1-6} -\PBS\centering 17 &\PBS\centering 61 &\PBS\centering 0x3\-D&\PBS\centering P29&\PBS\centering ports\-Status\mbox{[}2\mbox{]}\mbox{[}1\mbox{]}&\PBS\centering ports\-Config\mbox{[}4\mbox{]}\mbox{[}3-\/2\mbox{]} \\\cline{1-6} -\PBS\centering 18 &\PBS\centering 62 &\PBS\centering 0x3\-E&\PBS\centering P30&\PBS\centering ports\-Status\mbox{[}2\mbox{]}\mbox{[}2\mbox{]}&\PBS\centering ports\-Config\mbox{[}4\mbox{]}\mbox{[}5-\/4\mbox{]} \\\cline{1-6} -\PBS\centering 19 &\PBS\centering 63 &\PBS\centering 0x3\-F&\PBS\centering P31&\PBS\centering ports\-Status\mbox{[}2\mbox{]}\mbox{[}3\mbox{]}&\PBS\centering ports\-Config\mbox{[}4\mbox{]}\mbox{[}7-\/6\mbox{]} \\\cline{1-6} -\end{TabularC} - -\begin{DoxyParams}{Parameters} -{\em port} & Port register address (M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T12, ect) \\ -\hline -{\em port\-Config} & Valid options are\-: M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-L\-E\-D, M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-G\-P\-I\-O, M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-O\-\_\-\-P\-U\-L\-L, M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-\_\-\-P\-U\-L\-L \\ -\hline -\end{DoxyParams} -\begin{DoxySeeAlso}{See Also} -\hyperlink{MAX6956_8h_a3c089b77cbd25ffa27e3cd46af415a9c}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T12} \hyperlink{MAX6956_8h_a2d6ee01536f1fb0ec843479948141cbc}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T13} \hyperlink{MAX6956_8h_aba5e5ff9b4aea95fedff9f6421c5f47c}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T14} \hyperlink{MAX6956_8h_ad366a7c1b65fb3496f5b9ba392d6ba9c}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T15} \hyperlink{MAX6956_8h_ac483e6007b4e6a780c14c7a78ff7a134}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T16} \hyperlink{MAX6956_8h_ab6f3b8bbd8ac56bacf4a57691eb41aaf}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T17} \hyperlink{MAX6956_8h_a082486ab9eace7838acd56b6ac6301df}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T18} \hyperlink{MAX6956_8h_a04e65b34862a48ae022c994bbc5968dd}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T19} \hyperlink{MAX6956_8h_aed99f35f5ba961711c4e5bed769aa369}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T20} \hyperlink{MAX6956_8h_a361dcd71b3da6c5fb57d33951c9e4c54}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T21} \hyperlink{MAX6956_8h_a67c57767c9f6eda6124ff7368df4293b}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T22} \hyperlink{MAX6956_8h_a29699b356f81b9fc971a29fc04e68a59}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T23} \hyperlink{MAX6956_8h_ad053ff9eac065beaa10ad52dcc3d1e3e}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T24} \hyperlink{MAX6956_8h_a367103a7d8364b916a70f37d0880e334}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T25} \hyperlink{MAX6956_8h_ae0c19d326ab47406a138d4b66c601de0}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T26} \hyperlink{MAX6956_8h_ae1219ad62d3ea1b3a86c52736d347618}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T27} \hyperlink{MAX6956_8h_a07ff69092b95f43595762554c3e35329}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T28} \hyperlink{MAX6956_8h_a6be82fa185d6c3dd272200727c15f4ac}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T29} \hyperlink{MAX6956_8h_a34c02dca8e8a97488eb0be51f682cf73}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T30} \hyperlink{MAX6956_8h_a891d2a47a2fe5a4da056a7732fb6098b}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T31} - -\hyperlink{MAX6956_8h_ad6490a909085059c4300a51dcebbf7bc}{M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-L\-E\-D} \hyperlink{MAX6956_8h_a27f6ca524d4c18623762c722d9993c10}{M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-G\-P\-I\-O} \hyperlink{MAX6956_8h_ab05f3186e2515bab3a536ad9f1cbb7db}{M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-O\-\_\-\-P\-U\-L\-L} \hyperlink{MAX6956_8h_a68fc1bc750b7959fbab7e64f79589b83}{M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-\_\-\-P\-U\-L\-L} -\end{DoxySeeAlso} - - -Definition at line 265 of file M\-A\-X6956.\-cpp. - -\hypertarget{classMAX6956_a400393e30fbe196aef43d8edea890228}{\index{M\-A\-X6956@{M\-A\-X6956}!config\-Ports@{config\-Ports}} -\index{config\-Ports@{config\-Ports}!MAX6956@{M\-A\-X6956}} -\subsubsection[{config\-Ports}]{\setlength{\rightskip}{0pt plus 5cm}void M\-A\-X6956\-::config\-Ports ( -\begin{DoxyParamCaption} -\item[{uint8\-\_\-t}]{lower, } -\item[{uint8\-\_\-t}]{upper, } -\item[{uint8\-\_\-t}]{port\-Config} -\end{DoxyParamCaption} -)}}\label{classMAX6956_a400393e30fbe196aef43d8edea890228} -Configure consecutive range of ports -\begin{DoxyParams}{Parameters} -{\em lower} & Lower port register address (M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T12, ect) \\ -\hline -{\em upper} & Upper port register address (M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T12, ect) \\ -\hline -{\em port\-Config} & Valid options are\-: M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-L\-E\-D, M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-G\-P\-I\-O, M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-O\-\_\-\-P\-U\-L\-L, M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-\_\-\-P\-U\-L\-L \\ -\hline -\end{DoxyParams} -\begin{DoxySeeAlso}{See Also} -\hyperlink{MAX6956_8h_ad6490a909085059c4300a51dcebbf7bc}{M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-L\-E\-D} - -\hyperlink{MAX6956_8h_a27f6ca524d4c18623762c722d9993c10}{M\-A\-X6956\-\_\-\-O\-U\-T\-P\-U\-T\-\_\-\-G\-P\-I\-O} - -\hyperlink{MAX6956_8h_ab05f3186e2515bab3a536ad9f1cbb7db}{M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-O\-\_\-\-P\-U\-L\-L} - -\hyperlink{MAX6956_8h_a68fc1bc750b7959fbab7e64f79589b83}{M\-A\-X6956\-\_\-\-I\-N\-P\-U\-T\-\_\-\-W\-\_\-\-P\-U\-L\-L} -\end{DoxySeeAlso} - - -Definition at line 285 of file M\-A\-X6956.\-cpp. - -\hypertarget{classMAX6956_a93a81ff86316f63ee1ada3529da2a95b}{\index{M\-A\-X6956@{M\-A\-X6956}!disable\-All\-Ports@{disable\-All\-Ports}} -\index{disable\-All\-Ports@{disable\-All\-Ports}!MAX6956@{M\-A\-X6956}} -\subsubsection[{disable\-All\-Ports}]{\setlength{\rightskip}{0pt plus 5cm}void M\-A\-X6956\-::disable\-All\-Ports ( -\begin{DoxyParamCaption} -{} -\end{DoxyParamCaption} -)}}\label{classMAX6956_a93a81ff86316f63ee1ada3529da2a95b} -Write 0's to all port registers. - -Definition at line 463 of file M\-A\-X6956.\-cpp. - -\hypertarget{classMAX6956_a51a47c1f69532e96c6caa357889004e3}{\index{M\-A\-X6956@{M\-A\-X6956}!enable\-All\-Ports@{enable\-All\-Ports}} -\index{enable\-All\-Ports@{enable\-All\-Ports}!MAX6956@{M\-A\-X6956}} -\subsubsection[{enable\-All\-Ports}]{\setlength{\rightskip}{0pt plus 5cm}void M\-A\-X6956\-::enable\-All\-Ports ( -\begin{DoxyParamCaption} -{} -\end{DoxyParamCaption} -)}}\label{classMAX6956_a51a47c1f69532e96c6caa357889004e3} -Write 1's to all port registers. This enables ports set as outputs and they will always have some brightness, port must be disabled to turn off completely. - -Definition at line 453 of file M\-A\-X6956.\-cpp. - -\hypertarget{classMAX6956_a5e787204b3f7bf8750376f5bdf77a971}{\index{M\-A\-X6956@{M\-A\-X6956}!get\-Config\-Reg@{get\-Config\-Reg}} -\index{get\-Config\-Reg@{get\-Config\-Reg}!MAX6956@{M\-A\-X6956}} -\subsubsection[{get\-Config\-Reg}]{\setlength{\rightskip}{0pt plus 5cm}uint8\-\_\-t M\-A\-X6956\-::get\-Config\-Reg ( -\begin{DoxyParamCaption} -{} -\end{DoxyParamCaption} -)}}\label{classMAX6956_a5e787204b3f7bf8750376f5bdf77a971} -\begin{DoxyVerb}Config register -\end{DoxyVerb} - \begin{DoxyReturn}{Returns} -uint8\-\_\-t value of register -\end{DoxyReturn} -\begin{DoxySeeAlso}{See Also} -\hyperlink{MAX6956_8h_a5c3d1c00491596887e211bfa630c1b94}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-U\-R\-A\-T\-I\-O\-N} -\end{DoxySeeAlso} - - -Definition at line 94 of file M\-A\-X6956.\-cpp. - -\hypertarget{classMAX6956_abcfe81dd0ffc90284f19503b6366dcfb}{\index{M\-A\-X6956@{M\-A\-X6956}!get\-Enable\-Individual\-Current@{get\-Enable\-Individual\-Current}} -\index{get\-Enable\-Individual\-Current@{get\-Enable\-Individual\-Current}!MAX6956@{M\-A\-X6956}} -\subsubsection[{get\-Enable\-Individual\-Current}]{\setlength{\rightskip}{0pt plus 5cm}bool M\-A\-X6956\-::get\-Enable\-Individual\-Current ( -\begin{DoxyParamCaption} -{} -\end{DoxyParamCaption} -)}}\label{classMAX6956_abcfe81dd0ffc90284f19503b6366dcfb} -\begin{DoxyVerb}Get transition detection configuration bit -\end{DoxyVerb} - \begin{DoxyReturn}{Returns} -Boolean value if global current is enabled or not -\end{DoxyReturn} -\begin{DoxySeeAlso}{See Also} -\hyperlink{MAX6956_8h_a5c3d1c00491596887e211bfa630c1b94}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-U\-R\-A\-T\-I\-O\-N} -\end{DoxySeeAlso} - - -Definition at line 134 of file M\-A\-X6956.\-cpp. - -\hypertarget{classMAX6956_a76e9ab35769854b3e4224499897601ec}{\index{M\-A\-X6956@{M\-A\-X6956}!get\-Enable\-Transition\-Detection@{get\-Enable\-Transition\-Detection}} -\index{get\-Enable\-Transition\-Detection@{get\-Enable\-Transition\-Detection}!MAX6956@{M\-A\-X6956}} -\subsubsection[{get\-Enable\-Transition\-Detection}]{\setlength{\rightskip}{0pt plus 5cm}bool M\-A\-X6956\-::get\-Enable\-Transition\-Detection ( -\begin{DoxyParamCaption} -{} -\end{DoxyParamCaption} -)}}\label{classMAX6956_a76e9ab35769854b3e4224499897601ec} -\begin{DoxyVerb}Get transition detection configuration bit -\end{DoxyVerb} - \begin{DoxyReturn}{Returns} -Boolean value if transition detection is enabled or not -\end{DoxyReturn} -\begin{DoxySeeAlso}{See Also} -\hyperlink{MAX6956_8h_a5c3d1c00491596887e211bfa630c1b94}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-U\-R\-A\-T\-I\-O\-N} -\end{DoxySeeAlso} - - -Definition at line 152 of file M\-A\-X6956.\-cpp. - -\hypertarget{classMAX6956_a1926760b263588314fd759d129091940}{\index{M\-A\-X6956@{M\-A\-X6956}!get\-Global\-Current@{get\-Global\-Current}} -\index{get\-Global\-Current@{get\-Global\-Current}!MAX6956@{M\-A\-X6956}} -\subsubsection[{get\-Global\-Current}]{\setlength{\rightskip}{0pt plus 5cm}uint8\-\_\-t M\-A\-X6956\-::get\-Global\-Current ( -\begin{DoxyParamCaption} -{} -\end{DoxyParamCaption} -)}}\label{classMAX6956_a1926760b263588314fd759d129091940} -\begin{DoxyVerb}Get global current -\end{DoxyVerb} - \begin{DoxyReturn}{Returns} -uint8\-\_\-t value of register -\end{DoxyReturn} -\begin{DoxySeeAlso}{See Also} -\hyperlink{MAX6956_8h_a6a6c2bfe9bfbe4930731829baae7c8f6}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T} -\end{DoxySeeAlso} - - -Definition at line 171 of file M\-A\-X6956.\-cpp. - -\hypertarget{classMAX6956_a56245915d7d4cd8fd34629bd91695147}{\index{M\-A\-X6956@{M\-A\-X6956}!get\-Input\-Mask@{get\-Input\-Mask}} -\index{get\-Input\-Mask@{get\-Input\-Mask}!MAX6956@{M\-A\-X6956}} -\subsubsection[{get\-Input\-Mask}]{\setlength{\rightskip}{0pt plus 5cm}uint8\-\_\-t M\-A\-X6956\-::get\-Input\-Mask ( -\begin{DoxyParamCaption} -{} -\end{DoxyParamCaption} -)}}\label{classMAX6956_a56245915d7d4cd8fd34629bd91695147} -\begin{DoxyVerb}Get the input mask to see which ports have changed. MSB is cleared after every read. -\end{DoxyVerb} - \begin{DoxyReturn}{Returns} -uint8\-\_\-t value of register -\end{DoxyReturn} -\begin{DoxySeeAlso}{See Also} -\hyperlink{MAX6956_8h_a4a2b4c395e47e0ec9ef49d3236b8a465}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-D\-E\-T\-E\-C\-T} -\end{DoxySeeAlso} - - -Definition at line 205 of file M\-A\-X6956.\-cpp. - -\hypertarget{classMAX6956_acdc18c36735d8015651d4e3c75da4300}{\index{M\-A\-X6956@{M\-A\-X6956}!get\-Power@{get\-Power}} -\index{get\-Power@{get\-Power}!MAX6956@{M\-A\-X6956}} -\subsubsection[{get\-Power}]{\setlength{\rightskip}{0pt plus 5cm}bool M\-A\-X6956\-::get\-Power ( -\begin{DoxyParamCaption} -{} -\end{DoxyParamCaption} -)}}\label{classMAX6956_acdc18c36735d8015651d4e3c75da4300} -\begin{DoxyVerb}Get power configuration bit -\end{DoxyVerb} - \begin{DoxyReturn}{Returns} -Boolean value if power is enabled or not -\end{DoxyReturn} -\begin{DoxySeeAlso}{See Also} -\hyperlink{MAX6956_8h_a5c3d1c00491596887e211bfa630c1b94}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-U\-R\-A\-T\-I\-O\-N} -\end{DoxySeeAlso} - - -Definition at line 110 of file M\-A\-X6956.\-cpp. - -\hypertarget{classMAX6956_ad4f99f08d1cf08c5a0097215e680a80a}{\index{M\-A\-X6956@{M\-A\-X6956}!get\-Test\-Mode@{get\-Test\-Mode}} -\index{get\-Test\-Mode@{get\-Test\-Mode}!MAX6956@{M\-A\-X6956}} -\subsubsection[{get\-Test\-Mode}]{\setlength{\rightskip}{0pt plus 5cm}bool M\-A\-X6956\-::get\-Test\-Mode ( -\begin{DoxyParamCaption} -{} -\end{DoxyParamCaption} -)}}\label{classMAX6956_ad4f99f08d1cf08c5a0097215e680a80a} -\begin{DoxyVerb}Returns true if test mode is enabled. -\end{DoxyVerb} - \begin{DoxyReturn}{Returns} -uint8\-\_\-t value of register -\end{DoxyReturn} -\begin{DoxySeeAlso}{See Also} -\hyperlink{MAX6956_8h_a709a5193fd2aa9274997dfc22ef73a19}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-D\-I\-S\-P\-L\-A\-Y\-\_\-\-T\-E\-S\-T} -\end{DoxySeeAlso} - - -Definition at line 188 of file M\-A\-X6956.\-cpp. - -\hypertarget{classMAX6956_ad63e927adc2427b4b661f2422ddd40d8}{\index{M\-A\-X6956@{M\-A\-X6956}!initialize@{initialize}} -\index{initialize@{initialize}!MAX6956@{M\-A\-X6956}} -\subsubsection[{initialize}]{\setlength{\rightskip}{0pt plus 5cm}void M\-A\-X6956\-::initialize ( -\begin{DoxyParamCaption} -{} -\end{DoxyParamCaption} -)}}\label{classMAX6956_ad63e927adc2427b4b661f2422ddd40d8} -Power on and prepare for general usage. \begin{DoxyVerb}The 28-pin MAX6956ANI and MAX6956AAI make only 20 ports available, P12 to P31. -\end{DoxyVerb} - The eight unused ports should be configured as outputs on power-\/up by writing 0x55 to registers 0x09 and 0x0\-A. If this is not done,the eight unused ports remain as unconnected inputs and quiescent supply current rises, although there is no damage to the part. - -Definition at line 54 of file M\-A\-X6956.\-cpp. - -\hypertarget{classMAX6956_a3b9166eee826a876bbf29bc63b090fe7}{\index{M\-A\-X6956@{M\-A\-X6956}!reset@{reset}} -\index{reset@{reset}!MAX6956@{M\-A\-X6956}} -\subsubsection[{reset}]{\setlength{\rightskip}{0pt plus 5cm}void M\-A\-X6956\-::reset ( -\begin{DoxyParamCaption} -{} -\end{DoxyParamCaption} -)}}\label{classMAX6956_a3b9166eee826a876bbf29bc63b090fe7} -Set registers back to Power-\/up Configuration - -Definition at line 80 of file M\-A\-X6956.\-cpp. - -\hypertarget{classMAX6956_a9a27a32611fa05766946c33850510644}{\index{M\-A\-X6956@{M\-A\-X6956}!set\-All\-Ports\-Current@{set\-All\-Ports\-Current}} -\index{set\-All\-Ports\-Current@{set\-All\-Ports\-Current}!MAX6956@{M\-A\-X6956}} -\subsubsection[{set\-All\-Ports\-Current}]{\setlength{\rightskip}{0pt plus 5cm}void M\-A\-X6956\-::set\-All\-Ports\-Current ( -\begin{DoxyParamCaption} -\item[{uint8\-\_\-t}]{power} -\end{DoxyParamCaption} -)}}\label{classMAX6956_a9a27a32611fa05766946c33850510644} - - -0-\/15, 0 = min brightness (not off) 15 = max - -Set A\-L\-L port current registers (M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T12, ect) to the S\-A\-M\-E power level 0-\/15. 0 is off, 15 is max brightness. -\begin{DoxyParams}{Parameters} -{\em power} & 0 is min, 15 is max brightness. \\ -\hline -\end{DoxyParams} - - -Definition at line 444 of file M\-A\-X6956.\-cpp. - -\hypertarget{classMAX6956_ad06b9ed9f6e18f81d8379a6e10391ea4}{\index{M\-A\-X6956@{M\-A\-X6956}!set\-Config\-Reg@{set\-Config\-Reg}} -\index{set\-Config\-Reg@{set\-Config\-Reg}!MAX6956@{M\-A\-X6956}} -\subsubsection[{set\-Config\-Reg}]{\setlength{\rightskip}{0pt plus 5cm}void M\-A\-X6956\-::set\-Config\-Reg ( -\begin{DoxyParamCaption} -\item[{uint8\-\_\-t}]{config} -\end{DoxyParamCaption} -)}}\label{classMAX6956_ad06b9ed9f6e18f81d8379a6e10391ea4} -\begin{DoxyVerb}Set config register -\end{DoxyVerb} - -\begin{DoxyParams}{Parameters} -{\em config} & uint8\-\_\-t value to set register \\ -\hline -\end{DoxyParams} -\begin{DoxySeeAlso}{See Also} -\hyperlink{MAX6956_8h_a5c3d1c00491596887e211bfa630c1b94}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-U\-R\-A\-T\-I\-O\-N} -\end{DoxySeeAlso} - - -Definition at line 102 of file M\-A\-X6956.\-cpp. - -\hypertarget{classMAX6956_a35bc5701a290409144929e640cad1748}{\index{M\-A\-X6956@{M\-A\-X6956}!set\-Enable\-Individual\-Current@{set\-Enable\-Individual\-Current}} -\index{set\-Enable\-Individual\-Current@{set\-Enable\-Individual\-Current}!MAX6956@{M\-A\-X6956}} -\subsubsection[{set\-Enable\-Individual\-Current}]{\setlength{\rightskip}{0pt plus 5cm}void M\-A\-X6956\-::set\-Enable\-Individual\-Current ( -\begin{DoxyParamCaption} -\item[{bool}]{global} -\end{DoxyParamCaption} -)}}\label{classMAX6956_a35bc5701a290409144929e640cad1748} -\begin{DoxyVerb}Enable or disable global current -\end{DoxyVerb} - -\begin{DoxyParams}{Parameters} -{\em global} & Boolean value, true enables, false disables individual current \\ -\hline -\end{DoxyParams} -\begin{DoxySeeAlso}{See Also} -\hyperlink{MAX6956_8h_a5c3d1c00491596887e211bfa630c1b94}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-U\-R\-A\-T\-I\-O\-N} - -\hyperlink{classMAX6956_a1926760b263588314fd759d129091940}{get\-Global\-Current()} - -\hyperlink{classMAX6956_a4669dcc0f2f89f8fe73a0fa9b97dae21}{set\-Global\-Current()} -\end{DoxySeeAlso} - - -Definition at line 144 of file M\-A\-X6956.\-cpp. - -\hypertarget{classMAX6956_a67b65b80e09a3225dd4f6413bfab2844}{\index{M\-A\-X6956@{M\-A\-X6956}!set\-Enable\-Transition\-Detection@{set\-Enable\-Transition\-Detection}} -\index{set\-Enable\-Transition\-Detection@{set\-Enable\-Transition\-Detection}!MAX6956@{M\-A\-X6956}} -\subsubsection[{set\-Enable\-Transition\-Detection}]{\setlength{\rightskip}{0pt plus 5cm}void M\-A\-X6956\-::set\-Enable\-Transition\-Detection ( -\begin{DoxyParamCaption} -\item[{bool}]{transition} -\end{DoxyParamCaption} -)}}\label{classMAX6956_a67b65b80e09a3225dd4f6413bfab2844} -\begin{DoxyVerb}Enable or disable transition detection. Must be reset after every mask read. -\end{DoxyVerb} - -\begin{DoxyParams}{Parameters} -{\em transition} & Boolean value, true enables, false disables transition detection \\ -\hline -\end{DoxyParams} -\begin{DoxySeeAlso}{See Also} -\hyperlink{MAX6956_8h_a5c3d1c00491596887e211bfa630c1b94}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-U\-R\-A\-T\-I\-O\-N} - -\hyperlink{classMAX6956_a56245915d7d4cd8fd34629bd91695147}{get\-Input\-Mask()} - -\hyperlink{classMAX6956_a7ce45652fb0490af0ecb4eaebc230419}{set\-Input\-Mask()} -\end{DoxySeeAlso} - - -Definition at line 162 of file M\-A\-X6956.\-cpp. - -\hypertarget{classMAX6956_a4669dcc0f2f89f8fe73a0fa9b97dae21}{\index{M\-A\-X6956@{M\-A\-X6956}!set\-Global\-Current@{set\-Global\-Current}} -\index{set\-Global\-Current@{set\-Global\-Current}!MAX6956@{M\-A\-X6956}} -\subsubsection[{set\-Global\-Current}]{\setlength{\rightskip}{0pt plus 5cm}void M\-A\-X6956\-::set\-Global\-Current ( -\begin{DoxyParamCaption} -\item[{uint8\-\_\-t}]{current} -\end{DoxyParamCaption} -)}}\label{classMAX6956_a4669dcc0f2f89f8fe73a0fa9b97dae21} -\begin{DoxyVerb}Set current globally -\end{DoxyVerb} - -\begin{DoxyParams}{Parameters} -{\em current} & uint8\-\_\-t 0-\/15, 0 = min, 15 = max brightness \\ -\hline -\end{DoxyParams} -\begin{DoxySeeAlso}{See Also} -\hyperlink{MAX6956_8h_a6a6c2bfe9bfbe4930731829baae7c8f6}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-G\-L\-O\-B\-A\-L\-\_\-\-C\-U\-R\-R\-E\-N\-T} -\end{DoxySeeAlso} - - -Definition at line 179 of file M\-A\-X6956.\-cpp. - -\hypertarget{classMAX6956_a7ce45652fb0490af0ecb4eaebc230419}{\index{M\-A\-X6956@{M\-A\-X6956}!set\-Input\-Mask@{set\-Input\-Mask}} -\index{set\-Input\-Mask@{set\-Input\-Mask}!MAX6956@{M\-A\-X6956}} -\subsubsection[{set\-Input\-Mask}]{\setlength{\rightskip}{0pt plus 5cm}void M\-A\-X6956\-::set\-Input\-Mask ( -\begin{DoxyParamCaption} -\item[{uint8\-\_\-t}]{mask} -\end{DoxyParamCaption} -)}}\label{classMAX6956_a7ce45652fb0490af0ecb4eaebc230419} -\begin{DoxyVerb}Set the input mask for which ports to monitor with transition detection -\end{DoxyVerb} - -\begin{DoxyParams}{Parameters} -{\em mask} & 8 bit value. M\-S\-B is ignored. \\ -\hline -\end{DoxyParams} -\begin{DoxySeeAlso}{See Also} -\hyperlink{MAX6956_8h_a4a2b4c395e47e0ec9ef49d3236b8a465}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-T\-R\-A\-N\-S\-I\-T\-I\-O\-N\-\_\-\-D\-E\-T\-E\-C\-T} -\end{DoxySeeAlso} - - -Definition at line 214 of file M\-A\-X6956.\-cpp. - -\hypertarget{classMAX6956_a76a617f3b8982bb3855c5152b480097a}{\index{M\-A\-X6956@{M\-A\-X6956}!set\-Port\-Current@{set\-Port\-Current}} -\index{set\-Port\-Current@{set\-Port\-Current}!MAX6956@{M\-A\-X6956}} -\subsubsection[{set\-Port\-Current}]{\setlength{\rightskip}{0pt plus 5cm}void M\-A\-X6956\-::set\-Port\-Current ( -\begin{DoxyParamCaption} -\item[{uint8\-\_\-t}]{port, } -\item[{uint8\-\_\-t}]{power} -\end{DoxyParamCaption} -)}}\label{classMAX6956_a76a617f3b8982bb3855c5152b480097a} - - -0-\/15 brightness levels. - -\begin{DoxyVerb}Takes an INDIVIDUAL port register address (MAX6956_RA_PORT12, ect) -\end{DoxyVerb} - and sets it to a power level 0-\/15. 0 is min, 15 is max brightness. -\begin{DoxyParams}{Parameters} -{\em port} & Port register address (M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T12, ect) \\ -\hline -{\em power} & 0 is min, 15 is max brightness. \\ -\hline -\end{DoxyParams} - - -Definition at line 404 of file M\-A\-X6956.\-cpp. - -\hypertarget{classMAX6956_a98fa3831a47355fe0856caa74a9cf810}{\index{M\-A\-X6956@{M\-A\-X6956}!set\-Port\-Level@{set\-Port\-Level}} -\index{set\-Port\-Level@{set\-Port\-Level}!MAX6956@{M\-A\-X6956}} -\subsubsection[{set\-Port\-Level}]{\setlength{\rightskip}{0pt plus 5cm}void M\-A\-X6956\-::set\-Port\-Level ( -\begin{DoxyParamCaption} -\item[{uint8\-\_\-t}]{port, } -\item[{uint8\-\_\-t}]{power} -\end{DoxyParamCaption} -)}}\label{classMAX6956_a98fa3831a47355fe0856caa74a9cf810} - - -0 = off, 1-\/15 brightness levels. - -\begin{DoxyVerb}Takes an individual port register address (MAX6956_RA_PORT12, ect) -\end{DoxyVerb} - and sets it to a power scale where 0 = off. -\begin{DoxyParams}{Parameters} -{\em port} & Port register address (M\-A\-X6956\-\_\-\-R\-A\-\_\-\-P\-O\-R\-T12, ect) \\ -\hline -{\em power} & 0 is off, 15 is max brightness. \\ -\hline -\end{DoxyParams} - - -Definition at line 346 of file M\-A\-X6956.\-cpp. - -\hypertarget{classMAX6956_ae10ac505e3857d31ca3823225983a697}{\index{M\-A\-X6956@{M\-A\-X6956}!set\-Power@{set\-Power}} -\index{set\-Power@{set\-Power}!MAX6956@{M\-A\-X6956}} -\subsubsection[{set\-Power}]{\setlength{\rightskip}{0pt plus 5cm}void M\-A\-X6956\-::set\-Power ( -\begin{DoxyParamCaption} -\item[{bool}]{power} -\end{DoxyParamCaption} -)}}\label{classMAX6956_ae10ac505e3857d31ca3823225983a697} -\begin{DoxyVerb}Enable or disable power -\end{DoxyVerb} - -\begin{DoxyParams}{Parameters} -{\em power} & Boolean value, true enables, false disables power \\ -\hline -\end{DoxyParams} -\begin{DoxySeeAlso}{See Also} -\hyperlink{MAX6956_8h_a5c3d1c00491596887e211bfa630c1b94}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-U\-R\-A\-T\-I\-O\-N} -\end{DoxySeeAlso} - - -Definition at line 118 of file M\-A\-X6956.\-cpp. - -\hypertarget{classMAX6956_ad1b4e5cafd91acd2be2b6fb8197afef0}{\index{M\-A\-X6956@{M\-A\-X6956}!set\-Test\-Mode@{set\-Test\-Mode}} -\index{set\-Test\-Mode@{set\-Test\-Mode}!MAX6956@{M\-A\-X6956}} -\subsubsection[{set\-Test\-Mode}]{\setlength{\rightskip}{0pt plus 5cm}void M\-A\-X6956\-::set\-Test\-Mode ( -\begin{DoxyParamCaption} -\item[{bool}]{test} -\end{DoxyParamCaption} -)}}\label{classMAX6956_ad1b4e5cafd91acd2be2b6fb8197afef0} -\begin{DoxyVerb}Enable or disable test mode -\end{DoxyVerb} - -\begin{DoxyParams}{Parameters} -{\em test} & Boolean, true enables, false disables \\ -\hline -\end{DoxyParams} -\begin{DoxySeeAlso}{See Also} -\hyperlink{MAX6956_8h_a709a5193fd2aa9274997dfc22ef73a19}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-D\-I\-S\-P\-L\-A\-Y\-\_\-\-T\-E\-S\-T} -\end{DoxySeeAlso} - - -Definition at line 196 of file M\-A\-X6956.\-cpp. - -\hypertarget{classMAX6956_a60bd352328d77e59a4d51a3c55d38a25}{\index{M\-A\-X6956@{M\-A\-X6956}!test\-Connection@{test\-Connection}} -\index{test\-Connection@{test\-Connection}!MAX6956@{M\-A\-X6956}} -\subsubsection[{test\-Connection}]{\setlength{\rightskip}{0pt plus 5cm}bool M\-A\-X6956\-::test\-Connection ( -\begin{DoxyParamCaption} -{} -\end{DoxyParamCaption} -)}}\label{classMAX6956_a60bd352328d77e59a4d51a3c55d38a25} -Verify the I2\-C connection. Make sure the device is connected and responds as expected. \begin{DoxyReturn}{Returns} -True if connection is valid, false otherwise -\end{DoxyReturn} - - -Definition at line 72 of file M\-A\-X6956.\-cpp. - -\hypertarget{classMAX6956_a993f35d31d1f2489f9d2965c3886f848}{\index{M\-A\-X6956@{M\-A\-X6956}!toggle\-Power@{toggle\-Power}} -\index{toggle\-Power@{toggle\-Power}!MAX6956@{M\-A\-X6956}} -\subsubsection[{toggle\-Power}]{\setlength{\rightskip}{0pt plus 5cm}void M\-A\-X6956\-::toggle\-Power ( -\begin{DoxyParamCaption} -{} -\end{DoxyParamCaption} -)}}\label{classMAX6956_a993f35d31d1f2489f9d2965c3886f848} -\begin{DoxyVerb}Toggle power -\end{DoxyVerb} - \begin{DoxySeeAlso}{See Also} -\hyperlink{MAX6956_8h_a5c3d1c00491596887e211bfa630c1b94}{M\-A\-X6956\-\_\-\-R\-A\-\_\-\-C\-O\-N\-F\-I\-G\-U\-R\-A\-T\-I\-O\-N} -\end{DoxySeeAlso} - - -Definition at line 124 of file M\-A\-X6956.\-cpp. - - - -\subsection{Field Documentation} -\hypertarget{classMAX6956_a9f4597436b10ee86a02c96c2b0605851}{\index{M\-A\-X6956@{M\-A\-X6956}!buffer@{buffer}} -\index{buffer@{buffer}!MAX6956@{M\-A\-X6956}} -\subsubsection[{buffer}]{\setlength{\rightskip}{0pt plus 5cm}uint8\-\_\-t M\-A\-X6956\-::buffer\mbox{[}1\mbox{]}\hspace{0.3cm}{\ttfamily [private]}}}\label{classMAX6956_a9f4597436b10ee86a02c96c2b0605851} - - -Buffer for reading data from the device. - - - -Definition at line 556 of file M\-A\-X6956.\-h. - -\hypertarget{classMAX6956_a6ba2f8011914df50d6022ab54b27748d}{\index{M\-A\-X6956@{M\-A\-X6956}!dev\-Addr@{dev\-Addr}} -\index{dev\-Addr@{dev\-Addr}!MAX6956@{M\-A\-X6956}} -\subsubsection[{dev\-Addr}]{\setlength{\rightskip}{0pt plus 5cm}uint8\-\_\-t M\-A\-X6956\-::dev\-Addr\hspace{0.3cm}{\ttfamily [private]}}}\label{classMAX6956_a6ba2f8011914df50d6022ab54b27748d} - - -Holds the current device address. - - - -Definition at line 555 of file M\-A\-X6956.\-h. - -\hypertarget{classMAX6956_a9799e7684546e3e9b24506d436586a09}{\index{M\-A\-X6956@{M\-A\-X6956}!port\-Config@{port\-Config}} -\index{port\-Config@{port\-Config}!MAX6956@{M\-A\-X6956}} -\subsubsection[{port\-Config}]{\setlength{\rightskip}{0pt plus 5cm}uint8\-\_\-t M\-A\-X6956\-::port\-Config\hspace{0.3cm}{\ttfamily [private]}}}\label{classMAX6956_a9799e7684546e3e9b24506d436586a09} - - -Holder for port config bit pair. - - - -Definition at line 557 of file M\-A\-X6956.\-h. - -\hypertarget{classMAX6956_ad3057b6b21ae712acb0129270da63334}{\index{M\-A\-X6956@{M\-A\-X6956}!port\-Current\-Bit@{port\-Current\-Bit}} -\index{port\-Current\-Bit@{port\-Current\-Bit}!MAX6956@{M\-A\-X6956}} -\subsubsection[{port\-Current\-Bit}]{\setlength{\rightskip}{0pt plus 5cm}uint8\-\_\-t M\-A\-X6956\-::port\-Current\-Bit\hspace{0.3cm}{\ttfamily [private]}}}\label{classMAX6956_ad3057b6b21ae712acb0129270da63334} - - -Holder for the current bit offset. - - - -Definition at line 559 of file M\-A\-X6956.\-h. - -\hypertarget{classMAX6956_ab0d382db3afe7930d1b95311bfd90164}{\index{M\-A\-X6956@{M\-A\-X6956}!port\-Current\-R\-A@{port\-Current\-R\-A}} -\index{port\-Current\-R\-A@{port\-Current\-R\-A}!MAX6956@{M\-A\-X6956}} -\subsubsection[{port\-Current\-R\-A}]{\setlength{\rightskip}{0pt plus 5cm}uint8\-\_\-t M\-A\-X6956\-::port\-Current\-R\-A\hspace{0.3cm}{\ttfamily [private]}}}\label{classMAX6956_ab0d382db3afe7930d1b95311bfd90164} - - -Holder for port current register. - - - -Definition at line 558 of file M\-A\-X6956.\-h. - -\hypertarget{classMAX6956_a8b915615042c5ef96fbf3a5c260d4716}{\index{M\-A\-X6956@{M\-A\-X6956}!ports\-Config@{ports\-Config}} -\index{ports\-Config@{ports\-Config}!MAX6956@{M\-A\-X6956}} -\subsubsection[{ports\-Config}]{\setlength{\rightskip}{0pt plus 5cm}uint8\-\_\-t M\-A\-X6956\-::ports\-Config\mbox{[}5\mbox{]}}}\label{classMAX6956_a8b915615042c5ef96fbf3a5c260d4716} -Array that mirrors the configuration of all the ports. - -P12 = ports\-Config\mbox{[}0\mbox{]}\mbox{[}1-\/0\mbox{]} P13 = ports\-Config\mbox{[}0\mbox{]}\mbox{[}3-\/2\mbox{]} P14 = ports\-Config\mbox{[}0\mbox{]}\mbox{[}5-\/4\mbox{]} P15 = ports\-Config\mbox{[}0\mbox{]}\mbox{[}7-\/6\mbox{]} P16 = ports\-Config\mbox{[}1\mbox{]}\mbox{[}1-\/0\mbox{]} P17 = ports\-Config\mbox{[}1\mbox{]}\mbox{[}3-\/2\mbox{]} P18 = ports\-Config\mbox{[}1\mbox{]}\mbox{[}5-\/4\mbox{]} P19 = ports\-Config\mbox{[}1\mbox{]}\mbox{[}7-\/6\mbox{]} P20 = ports\-Config\mbox{[}2\mbox{]}\mbox{[}1-\/0\mbox{]} P21 = ports\-Config\mbox{[}2\mbox{]}\mbox{[}3-\/2\mbox{]} P22 = ports\-Config\mbox{[}2\mbox{]}\mbox{[}5-\/4\mbox{]} P23 = ports\-Config\mbox{[}2\mbox{]}\mbox{[}7-\/6\mbox{]} P24 = ports\-Config\mbox{[}3\mbox{]}\mbox{[}1-\/0\mbox{]} P25 = ports\-Config\mbox{[}3\mbox{]}\mbox{[}3-\/2\mbox{]} P26 = ports\-Config\mbox{[}3\mbox{]}\mbox{[}5-\/4\mbox{]} P27 = ports\-Config\mbox{[}3\mbox{]}\mbox{[}7-\/6\mbox{]} P28 = ports\-Config\mbox{[}4\mbox{]}\mbox{[}1-\/0\mbox{]} P29 = ports\-Config\mbox{[}4\mbox{]}\mbox{[}3-\/2\mbox{]} P30 = ports\-Config\mbox{[}4\mbox{]}\mbox{[}5-\/4\mbox{]} P31 = ports\-Config\mbox{[}4\mbox{]}\mbox{[}7-\/6\mbox{]} - -Definition at line 527 of file M\-A\-X6956.\-h. - -\hypertarget{classMAX6956_ae8da9a65da74dce7eb907319b0198847}{\index{M\-A\-X6956@{M\-A\-X6956}!ports\-Status@{ports\-Status}} -\index{ports\-Status@{ports\-Status}!MAX6956@{M\-A\-X6956}} -\subsubsection[{ports\-Status}]{\setlength{\rightskip}{0pt plus 5cm}uint8\-\_\-t M\-A\-X6956\-::ports\-Status\mbox{[}3\mbox{]}}}\label{classMAX6956_ae8da9a65da74dce7eb907319b0198847} -Array that mirrors the on/off status of all the ports. - -P12 = ports\-Status\mbox{[}0\mbox{]}\mbox{[}0\mbox{]} P13 = ports\-Status\mbox{[}0\mbox{]}\mbox{[}1\mbox{]} P14 = ports\-Status\mbox{[}0\mbox{]}\mbox{[}2\mbox{]} P15 = ports\-Status\mbox{[}0\mbox{]}\mbox{[}3\mbox{]} P16 = ports\-Status\mbox{[}0\mbox{]}\mbox{[}4\mbox{]} P17 = ports\-Status\mbox{[}0\mbox{]}\mbox{[}5\mbox{]} P18 = ports\-Status\mbox{[}0\mbox{]}\mbox{[}6\mbox{]} P19 = ports\-Status\mbox{[}0\mbox{]}\mbox{[}7\mbox{]} P20 = ports\-Status\mbox{[}1\mbox{]}\mbox{[}0\mbox{]} P21 = ports\-Status\mbox{[}1\mbox{]}\mbox{[}1\mbox{]} P22 = ports\-Status\mbox{[}1\mbox{]}\mbox{[}2\mbox{]} P23 = ports\-Status\mbox{[}1\mbox{]}\mbox{[}3\mbox{]} P24 = ports\-Status\mbox{[}1\mbox{]}\mbox{[}4\mbox{]} P25 = ports\-Status\mbox{[}1\mbox{]}\mbox{[}5\mbox{]} P26 = ports\-Status\mbox{[}1\mbox{]}\mbox{[}6\mbox{]} P27 = ports\-Status\mbox{[}1\mbox{]}\mbox{[}7\mbox{]} P28 = ports\-Status\mbox{[}2\mbox{]}\mbox{[}0\mbox{]} P29 = ports\-Status\mbox{[}2\mbox{]}\mbox{[}1\mbox{]} P30 = ports\-Status\mbox{[}2\mbox{]}\mbox{[}2\mbox{]} P31 = ports\-Status\mbox{[}2\mbox{]}\mbox{[}3\mbox{]} - -Definition at line 552 of file M\-A\-X6956.\-h. - -\hypertarget{classMAX6956_a967e25fac00c0ab59be854289eb36353}{\index{M\-A\-X6956@{M\-A\-X6956}!ps\-Array\-Index@{ps\-Array\-Index}} -\index{ps\-Array\-Index@{ps\-Array\-Index}!MAX6956@{M\-A\-X6956}} -\subsubsection[{ps\-Array\-Index}]{\setlength{\rightskip}{0pt plus 5cm}uint8\-\_\-t M\-A\-X6956\-::ps\-Array\-Index\hspace{0.3cm}{\ttfamily [private]}}}\label{classMAX6956_a967e25fac00c0ab59be854289eb36353} - - -array index - - - -Definition at line 560 of file M\-A\-X6956.\-h. - -\hypertarget{classMAX6956_a92b5dc05a1483c49c150db13dcd1f283}{\index{M\-A\-X6956@{M\-A\-X6956}!ps\-Bit\-Position@{ps\-Bit\-Position}} -\index{ps\-Bit\-Position@{ps\-Bit\-Position}!MAX6956@{M\-A\-X6956}} -\subsubsection[{ps\-Bit\-Position}]{\setlength{\rightskip}{0pt plus 5cm}uint8\-\_\-t M\-A\-X6956\-::ps\-Bit\-Position\hspace{0.3cm}{\ttfamily [private]}}}\label{classMAX6956_a92b5dc05a1483c49c150db13dcd1f283} - - -bit position - - - -Definition at line 561 of file M\-A\-X6956.\-h. - - - -The documentation for this class was generated from the following files\-:\begin{DoxyCompactItemize} -\item -\hyperlink{MAX6956_8h}{M\-A\-X6956.\-h}\item -\hyperlink{MAX6956_8cpp}{M\-A\-X6956.\-cpp}\end{DoxyCompactItemize} diff --git a/Arduino/MAX6956/latex/doxygen.sty b/Arduino/MAX6956/latex/doxygen.sty deleted file mode 100644 index 199abf8d..00000000 --- a/Arduino/MAX6956/latex/doxygen.sty +++ /dev/null @@ -1,464 +0,0 @@ -\NeedsTeXFormat{LaTeX2e} -\ProvidesPackage{doxygen} - -% Packages used by this style file -\RequirePackage{alltt} -\RequirePackage{array} -\RequirePackage{calc} -\RequirePackage{float} -\RequirePackage{ifthen} -\RequirePackage{verbatim} -\RequirePackage[table]{xcolor} -\RequirePackage{xtab} - -%---------- Internal commands used in this style file ---------------- - -\newcommand{\ensurespace}[1]{% - \begingroup% - \setlength{\dimen@}{#1}% - \vskip\z@\@plus\dimen@% - \penalty -100\vskip\z@\@plus -\dimen@% - \vskip\dimen@% - \penalty 9999% - \vskip -\dimen@% - \vskip\z@skip% hide the previous |\vskip| from |\addvspace| - \endgroup% -} - -\newcommand{\DoxyLabelFont}{} -\newcommand{\entrylabel}[1]{% - {% - \parbox[b]{\labelwidth-4pt}{% - \makebox[0pt][l]{\DoxyLabelFont#1}% - \vspace{1.5\baselineskip}% - }% - }% -} - -\newenvironment{DoxyDesc}[1]{% - \ensurespace{4\baselineskip}% - \begin{list}{}{% - \settowidth{\labelwidth}{20pt}% - \setlength{\parsep}{0pt}% - \setlength{\itemsep}{0pt}% - \setlength{\leftmargin}{\labelwidth+\labelsep}% - \renewcommand{\makelabel}{\entrylabel}% - }% - \item[#1]% -}{% - \end{list}% -} - -\newsavebox{\xrefbox} -\newlength{\xreflength} -\newcommand{\xreflabel}[1]{% - \sbox{\xrefbox}{#1}% - \setlength{\xreflength}{\wd\xrefbox}% - \ifthenelse{\xreflength>\labelwidth}{% - \begin{minipage}{\textwidth}% - \setlength{\parindent}{0pt}% - \hangindent=15pt\bfseries #1\vspace{1.2\itemsep}% - \end{minipage}% - }{% - \parbox[b]{\labelwidth}{\makebox[0pt][l]{\textbf{#1}}}% - }% -} - -%---------- Commands used by doxygen LaTeX output generator ---------- - -% Used by
 ... 
-\newenvironment{DoxyPre}{% - \small% - \begin{alltt}% -}{% - \end{alltt}% - \normalsize% -} - -% Used by @code ... @endcode -\newenvironment{DoxyCode}{% - \par% - \scriptsize% - \begin{alltt}% -}{% - \end{alltt}% - \normalsize% -} - -% Used by @example, @include, @includelineno and @dontinclude -\newenvironment{DoxyCodeInclude}{% - \DoxyCode% -}{% - \endDoxyCode% -} - -% Used by @verbatim ... @endverbatim -\newenvironment{DoxyVerb}{% - \footnotesize% - \verbatim% -}{% - \endverbatim% - \normalsize% -} - -% Used by @verbinclude -\newenvironment{DoxyVerbInclude}{% - \DoxyVerb% -}{% - \endDoxyVerb% -} - -% Used by numbered lists (using '-#' or
    ...
) -\newenvironment{DoxyEnumerate}{% - \enumerate% -}{% - \endenumerate% -} - -% Used by bullet lists (using '-', @li, @arg, or
    ...
) -\newenvironment{DoxyItemize}{% - \itemize% -}{% - \enditemize% -} - -% Used by description lists (using
...
) -\newenvironment{DoxyDescription}{% - \description% -}{% - \enddescription% -} - -% Used by @image, @dotfile, @dot ... @enddot, and @msc ... @endmsc -% (only if caption is specified) -\newenvironment{DoxyImage}{% - \begin{figure}[H]% - \begin{center}% -}{% - \end{center}% - \end{figure}% -} - -% Used by @image, @dotfile, @dot ... @enddot, and @msc ... @endmsc -% (only if no caption is specified) -\newenvironment{DoxyImageNoCaption}{% -}{% -} - -% Used by @attention -\newenvironment{DoxyAttention}[1]{% - \begin{DoxyDesc}{#1}% -}{% - \end{DoxyDesc}% -} - -% Used by @author and @authors -\newenvironment{DoxyAuthor}[1]{% - \begin{DoxyDesc}{#1}% -}{% - \end{DoxyDesc}% -} - -% Used by @date -\newenvironment{DoxyDate}[1]{% - \begin{DoxyDesc}{#1}% -}{% - \end{DoxyDesc}% -} - -% Used by @invariant -\newenvironment{DoxyInvariant}[1]{% - \begin{DoxyDesc}{#1}% -}{% - \end{DoxyDesc}% -} - -% Used by @note -\newenvironment{DoxyNote}[1]{% - \begin{DoxyDesc}{#1}% -}{% - \end{DoxyDesc}% -} - -% Used by @post -\newenvironment{DoxyPostcond}[1]{% - \begin{DoxyDesc}{#1}% -}{% - \end{DoxyDesc}% -} - -% Used by @pre -\newenvironment{DoxyPrecond}[1]{% - \begin{DoxyDesc}{#1}% -}{% - \end{DoxyDesc}% -} - -% Used by @copyright -\newenvironment{DoxyCopyright}[1]{% - \begin{DoxyDesc}{#1}% -}{% - \end{DoxyDesc}% -} - -% Used by @remark -\newenvironment{DoxyRemark}[1]{% - \begin{DoxyDesc}{#1}% -}{% - \end{DoxyDesc}% -} - -% Used by @return and @returns -\newenvironment{DoxyReturn}[1]{% - \begin{DoxyDesc}{#1}% -}{% - \end{DoxyDesc}% -} - -% Used by @since -\newenvironment{DoxySince}[1]{% - \begin{DoxyDesc}{#1}% -}{% - \end{DoxyDesc}% -} - -% Used by @see -\newenvironment{DoxySeeAlso}[1]{% - \begin{DoxyDesc}{#1}% -}{% - \end{DoxyDesc}% -} - -% Used by @version -\newenvironment{DoxyVersion}[1]{% - \begin{DoxyDesc}{#1}% -}{% - \end{DoxyDesc}% -} - -% Used by @warning -\newenvironment{DoxyWarning}[1]{% - \begin{DoxyDesc}{#1}% -}{% - \end{DoxyDesc}% -} - -% Used by @internal -\newenvironment{DoxyInternal}[1]{% - \paragraph*{#1}% -}{% -} - -% Used by @par and @paragraph -\newenvironment{DoxyParagraph}[1]{% - \begin{list}{}{% - \settowidth{\labelwidth}{40pt}% - \setlength{\leftmargin}{\labelwidth}% - \setlength{\parsep}{0pt}% - \setlength{\itemsep}{-4pt}% - \renewcommand{\makelabel}{\entrylabel}% - }% - \item[#1]% -}{% - \end{list}% -} - -% Used by parameter lists -\newenvironment{DoxyParams}[2][]{% - \par% - \tabletail{\hline}% - \tablelasttail{\hline}% - \tablefirsthead{}% - \tablehead{}% - \ifthenelse{\equal{#1}{}}% - {\tablefirsthead{\multicolumn{2}{l}{\hspace{-6pt}\bfseries\fontseries{bc}\selectfont\color{darkgray} #2}\\[1ex]}% - \begin{xtabular}{|>{\raggedleft\hspace{0pt}}p{0.15\textwidth}|% - p{0.805\textwidth}|}}% - {\ifthenelse{\equal{#1}{1}}% - {\tablefirsthead{\multicolumn{2}{l}{\hspace{-6pt}\bfseries\fontseries{bc}\selectfont\color{darkgray} #2}\\[1ex]}% - \begin{xtabular}{|>{\centering}p{0.10\textwidth}|% - >{\raggedleft\hspace{0pt}}p{0.15\textwidth}|% - p{0.678\textwidth}|}}% - {\tablefirsthead{\multicolumn{2}{l}{\hspace{-6pt}\bfseries\fontseries{bc}\selectfont\color{darkgray} #2}\\[1ex]}% - \begin{xtabular}{|>{\centering}p{0.10\textwidth}|% - >{\centering\hspace{0pt}}p{0.15\textwidth}|% - >{\raggedleft\hspace{0pt}}p{0.15\textwidth}|% - p{0.501\textwidth}|}}% - }\hline% -}{% - \end{xtabular}% - \tablefirsthead{}% - \vspace{6pt}% -} - -% Used for fields of simple structs -\newenvironment{DoxyFields}[1]{% - \par% - \tabletail{\hline}% - \tablelasttail{\hline}% - \tablehead{}% - \tablefirsthead{\multicolumn{2}{l}{\hspace{-6pt}\bfseries\fontseries{bc}\selectfont\color{darkgray} #1}\\[1ex]}% - \begin{xtabular}{|>{\raggedleft\hspace{0pt}}p{0.15\textwidth}|% - p{0.15\textwidth}|% - p{0.63\textwidth}|}% - \hline% -}{% - \end{xtabular}% - \tablefirsthead{}% - \vspace{6pt}% -} - -% Used for parameters within a detailed function description -\newenvironment{DoxyParamCaption}{% - \renewcommand{\item}[2][]{##1 {\em ##2}}% -}{% -} - -% Used by return value lists -\newenvironment{DoxyRetVals}[1]{% - \par% - \tabletail{\hline}% - \tablelasttail{\hline}% - \tablehead{}% - \tablefirsthead{\multicolumn{2}{l}{\hspace{-6pt}\bfseries\fontseries{bc}\selectfont\color{darkgray} #1}\\[1ex]}% - \begin{xtabular}{|>{\raggedleft\hspace{0pt}}p{0.25\textwidth}|% - p{0.705\textwidth}|}% - \hline% -}{% - \end{xtabular}% - \tablefirsthead{}% - \vspace{6pt}% -} - -% Used by exception lists -\newenvironment{DoxyExceptions}[1]{% - \par% - \tabletail{\hline}% - \tablelasttail{\hline}% - \tablehead{}% - \tablefirsthead{\multicolumn{2}{l}{\hspace{-6pt}\bfseries\fontseries{bc}\selectfont\color{darkgray} #1}\\[1ex]}% - \begin{xtabular}{|>{\raggedleft\hspace{0pt}}p{0.25\textwidth}|% - p{0.705\textwidth}|}% - \hline% -}{% - \end{xtabular}% - \tablefirsthead{}% - \vspace{6pt}% -} - -% Used by template parameter lists -\newenvironment{DoxyTemplParams}[1]{% - \par% - \tabletail{\hline}% - \tablelasttail{\hline}% - \tablehead{}% - \tablefirsthead{\multicolumn{2}{l}{\hspace{-6pt}\bfseries\fontseries{bc}\selectfont\color{darkgray} #1}\\[1ex]}% - \begin{xtabular}{|>{\raggedleft\hspace{0pt}}p{0.25\textwidth}|% - p{0.705\textwidth}|}% - \hline% -}{% - \end{xtabular}% - \tablefirsthead{}% - \vspace{6pt}% -} - -% Used for member lists -\newenvironment{DoxyCompactItemize}{% - \begin{itemize}% - \setlength{\itemsep}{-3pt}% - \setlength{\parsep}{0pt}% - \setlength{\topsep}{0pt}% - \setlength{\partopsep}{0pt}% -}{% - \end{itemize}% -} - -% Used for member descriptions -\newenvironment{DoxyCompactList}{% - \begin{list}{}{% - \setlength{\leftmargin}{0.5cm}% - \setlength{\itemsep}{0pt}% - \setlength{\parsep}{0pt}% - \setlength{\topsep}{0pt}% - \renewcommand{\makelabel}{\hfill}% - }% -}{% - \end{list}% -} - -% Used for reference lists (@bug, @deprecated, @todo, etc.) -\newenvironment{DoxyRefList}{% - \begin{list}{}{% - \setlength{\labelwidth}{10pt}% - \setlength{\leftmargin}{\labelwidth}% - \addtolength{\leftmargin}{\labelsep}% - \renewcommand{\makelabel}{\xreflabel}% - }% -}{% - \end{list}% -} - -% Used by @bug, @deprecated, @todo, etc. -\newenvironment{DoxyRefDesc}[1]{% - \begin{list}{}{% - \renewcommand\makelabel[1]{\textbf{##1}}% - \settowidth\labelwidth{\makelabel{#1}}% - \setlength\leftmargin{\labelwidth+\labelsep}% - }% -}{% - \end{list}% -} - -% Used by parameter lists and simple sections -\newenvironment{Desc} -{\begin{list}{}{% - \settowidth{\labelwidth}{40pt}% - \setlength{\leftmargin}{\labelwidth}% - \setlength{\parsep}{0pt}% - \setlength{\itemsep}{-4pt}% - \renewcommand{\makelabel}{\entrylabel}% - } -}{% - \end{list}% -} - -% Used by tables -\newcommand{\PBS}[1]{\let\temp=\\#1\let\\=\temp}% -\newlength{\tmplength}% -\newenvironment{TabularC}[1]% -{% -\setlength{\tmplength}% - {\linewidth/(#1)-\tabcolsep*2-\arrayrulewidth*(#1+1)/(#1)}% - \par\begin{xtabular*}{\linewidth}% - {*{#1}{|>{\PBS\raggedright\hspace{0pt}}p{\the\tmplength}}|}% -}% -{\end{xtabular*}\par}% - -% Used for member group headers -\newenvironment{Indent}{% - \begin{list}{}{% - \setlength{\leftmargin}{0.5cm}% - }% - \item[]\ignorespaces% -}{% - \unskip% - \end{list}% -} - -% Used when hyperlinks are turned off -\newcommand{\doxyref}[3]{% - \textbf{#1} (\textnormal{#2}\,\pageref{#3})% -} - -% Used for syntax highlighting -\definecolor{comment}{rgb}{0.5,0.0,0.0} -\definecolor{keyword}{rgb}{0.0,0.5,0.0} -\definecolor{keywordtype}{rgb}{0.38,0.25,0.125} -\definecolor{keywordflow}{rgb}{0.88,0.5,0.0} -\definecolor{preprocessor}{rgb}{0.5,0.38,0.125} -\definecolor{stringliteral}{rgb}{0.0,0.125,0.25} -\definecolor{charliteral}{rgb}{0.0,0.5,0.5} -\definecolor{vhdldigit}{rgb}{1.0,0.0,1.0} -\definecolor{vhdlkeyword}{rgb}{0.43,0.0,0.43} -\definecolor{vhdllogic}{rgb}{1.0,0.0,0.0} -\definecolor{vhdlchar}{rgb}{0.0,0.0,0.0} diff --git a/Arduino/MAX6956/latex/files.tex b/Arduino/MAX6956/latex/files.tex deleted file mode 100644 index ccbdd5a2..00000000 --- a/Arduino/MAX6956/latex/files.tex +++ /dev/null @@ -1,5 +0,0 @@ -\section{File List} -Here is a list of all files with brief descriptions\-:\begin{DoxyCompactList} -\item\contentsline{section}{\hyperlink{MAX6956_8cpp}{M\-A\-X6956.\-cpp} }{\pageref{MAX6956_8cpp}}{} -\item\contentsline{section}{\hyperlink{MAX6956_8h}{M\-A\-X6956.\-h} }{\pageref{MAX6956_8h}}{} -\end{DoxyCompactList} diff --git a/Arduino/MAX6956/latex/refman.tex b/Arduino/MAX6956/latex/refman.tex deleted file mode 100644 index 6cc814ab..00000000 --- a/Arduino/MAX6956/latex/refman.tex +++ /dev/null @@ -1,150 +0,0 @@ -\documentclass[twoside]{book} - -% Packages required by doxygen -\usepackage{calc} -\usepackage{doxygen} -\usepackage{graphicx} -\usepackage[utf8]{inputenc} -\usepackage{makeidx} -\usepackage{multicol} -\usepackage{multirow} -\usepackage{textcomp} -\usepackage[table]{xcolor} - -% Font selection -\usepackage[T1]{fontenc} -\usepackage{mathptmx} -\usepackage[scaled=.90]{helvet} -\usepackage{courier} -\usepackage{amssymb} -\usepackage{sectsty} -\renewcommand{\familydefault}{\sfdefault} -\allsectionsfont{% - \fontseries{bc}\selectfont% - \color{darkgray}% -} -\renewcommand{\DoxyLabelFont}{% - \fontseries{bc}\selectfont% - \color{darkgray}% -} - -% Page & text layout -\usepackage{geometry} -\geometry{% - a4paper,% - top=2.5cm,% - bottom=2.5cm,% - left=2.5cm,% - right=2.5cm% -} -\tolerance=750 -\hfuzz=15pt -\hbadness=750 -\setlength{\emergencystretch}{15pt} -\setlength{\parindent}{0cm} -\setlength{\parskip}{0.2cm} -\makeatletter -\renewcommand{\paragraph}{% - \@startsection{paragraph}{4}{0ex}{-1.0ex}{1.0ex}{% - \normalfont\normalsize\bfseries\SS@parafont% - }% -} -\renewcommand{\subparagraph}{% - \@startsection{subparagraph}{5}{0ex}{-1.0ex}{1.0ex}{% - \normalfont\normalsize\bfseries\SS@subparafont% - }% -} -\makeatother - -% Headers & footers -\usepackage{fancyhdr} -\pagestyle{fancyplain} -\fancyhead[LE]{\fancyplain{}{\bfseries\thepage}} -\fancyhead[CE]{\fancyplain{}{}} -\fancyhead[RE]{\fancyplain{}{\bfseries\leftmark}} -\fancyhead[LO]{\fancyplain{}{\bfseries\rightmark}} -\fancyhead[CO]{\fancyplain{}{}} -\fancyhead[RO]{\fancyplain{}{\bfseries\thepage}} -\fancyfoot[LE]{\fancyplain{}{}} -\fancyfoot[CE]{\fancyplain{}{}} -\fancyfoot[RE]{\fancyplain{}{\bfseries\scriptsize Generated on Tue Jan 21 2014 23\-:33\-:12 for M\-A\-X6956 by Doxygen }} -\fancyfoot[LO]{\fancyplain{}{\bfseries\scriptsize Generated on Tue Jan 21 2014 23\-:33\-:12 for M\-A\-X6956 by Doxygen }} -\fancyfoot[CO]{\fancyplain{}{}} -\fancyfoot[RO]{\fancyplain{}{}} -\renewcommand{\footrulewidth}{0.4pt} -\renewcommand{\chaptermark}[1]{% - \markboth{#1}{}% -} -\renewcommand{\sectionmark}[1]{% - \markright{\thesection\ #1}% -} - -% Indices & bibliography -\usepackage{natbib} -\usepackage[titles]{tocloft} -\setcounter{tocdepth}{3} -\setcounter{secnumdepth}{5} -\makeindex - -% Hyperlinks (required, but should be loaded last) -\usepackage{ifpdf} -\ifpdf - \usepackage[pdftex,pagebackref=true]{hyperref} -\else - \usepackage[ps2pdf,pagebackref=true]{hyperref} -\fi -\hypersetup{% - colorlinks=true,% - linkcolor=blue,% - citecolor=blue,% - unicode% -} - -% Custom commands -\newcommand{\clearemptydoublepage}{% - \newpage{\pagestyle{empty}\cleardoublepage}% -} - - -%===== C O N T E N T S ===== - -\begin{document} - -% Titlepage & ToC -\hypersetup{pageanchor=false} -\pagenumbering{roman} -\begin{titlepage} -\vspace*{7cm} -\begin{center}% -{\Large M\-A\-X6956 \\[1ex]\large 1.\-0 }\\ -\vspace*{1cm} -{\large Generated by Doxygen 1.8.5}\\ -\vspace*{0.5cm} -{\small Tue Jan 21 2014 23:33:12}\\ -\end{center} -\end{titlepage} -\clearemptydoublepage -\tableofcontents -\clearemptydoublepage -\pagenumbering{arabic} -\hypersetup{pageanchor=true} - -%--- Begin generated contents --- -\chapter{Data Structure Index} -\input{annotated} -\chapter{File Index} -\input{files} -\chapter{Data Structure Documentation} -\input{classMAX6956} -\chapter{File Documentation} -\input{MAX6956_8cpp} -\input{MAX6956_8h} -%--- End generated contents --- - -% Index -\newpage -\phantomsection -\addcontentsline{toc}{part}{Index} -\printindex - -\end{document} From 3516b6cdf2b44c85bcee75164bae30ab158d9154 Mon Sep 17 00:00:00 2001 From: Nicolas Baldeck Date: Fri, 2 Jan 2015 14:02:21 +0100 Subject: [PATCH 058/335] Add EFM32 platform --- EFM32/I2Cdev/I2Cdev.cpp | 241 ++++++++++++++++++++++++++++++++++++++++ EFM32/I2Cdev/I2Cdev.h | 84 ++++++++++++++ 2 files changed, 325 insertions(+) create mode 100644 EFM32/I2Cdev/I2Cdev.cpp create mode 100644 EFM32/I2Cdev/I2Cdev.h diff --git a/EFM32/I2Cdev/I2Cdev.cpp b/EFM32/I2Cdev/I2Cdev.cpp new file mode 100644 index 00000000..a70796e6 --- /dev/null +++ b/EFM32/I2Cdev/I2Cdev.cpp @@ -0,0 +1,241 @@ +// I2Cdev library collection - Main I2C device class +// Abstracts bit and byte I2C R/W functions into a convenient class +// EFM32 stub port by Nicolas Baldeck +// Based on Arduino's I2Cdev by Jeff Rowberg +// +// Changelog: +// 2015-01-02 - Initial release + + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2015 Jeff Rowberg, Nicolas Baldeck + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#include "I2Cdev.h" + +/** Default constructor. + */ +I2Cdev::I2Cdev() { +} + +/** Initialize I2C0 + */ +void I2Cdev::initialize() { + CMU_ClockEnable(cmuClock_I2C0, true); + + GPIO_PinModeSet(I2C_SDA_PORT, I2C_SDA_PIN, I2C_SDA_MODE, I2C_SDA_DOUT); + GPIO_PinModeSet(I2C_SCL_PORT, I2C_SCL_PIN, I2C_SCL_MODE, I2C_SCL_DOUT); + + I2C0->ROUTE |= I2C_ROUTE_SDAPEN | I2C_ROUTE_SCLPEN; + + const I2C_Init_TypeDef init = I2C_INIT_DEFAULT; + I2C_Init(I2C0, &init); + + I2C_Enable(I2C0, true); +} + +/** Enable or disable I2C + * @param isEnabled true = enable, false = disable + */ +void I2Cdev::enable(bool isEnabled) { + + I2C_Enable(I2C0, isEnabled); + CMU_ClockEnable(cmuClock_I2C0, isEnabled); + +} + +I2C_TransferReturn_TypeDef I2Cdev::transfer(I2C_TransferSeq_TypeDef *seq, uint16_t timeout) { + + I2C_TransferReturn_TypeDef ret; + /* Do a polled transfer */ + ret = I2C_TransferInit(I2C0, seq); + + while (ret == i2cTransferInProgress && timeout--) { + ret = I2C_Transfer(I2C0); + } + + return(ret); + +} + +/** Default timeout value for read operations. + */ +uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; +/** Read a single bit from an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param bitNum Bit position to read (0-7) + * @param data Container for single bit value + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) + * @return Status of read operation (true = success) + */ +int8_t I2Cdev::readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data, uint16_t timeout) { + uint8_t b; + uint8_t count = readByte(devAddr, regAddr, &b, timeout); + *data = b & (1 << bitNum); + return count; +} + +/** Read multiple bits from an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param bitStart First bit position to read (0-7) + * @param length Number of bits to read (not more than 8) + * @param data Container for right-aligned value (i.e. '101' read from any bitStart position will equal 0x05) + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) + * @return Status of read operation (true = success) + */ +int8_t I2Cdev::readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data, uint16_t timeout) { + // 01101001 read byte + // 76543210 bit numbers + // xxx args: bitStart=4, length=3 + // 010 masked + // -> 010 shifted + uint8_t count, b; + if ((count = readByte(devAddr, regAddr, &b, timeout)) != 0) { + uint8_t mask = ((1 << length) - 1) << (bitStart - length + 1); + b &= mask; + b >>= (bitStart - length + 1); + *data = b; + } + return count; +} + +/** Read single byte from an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param data Container for byte value read from device + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) + * @return Status of read operation (true = success) + */ +int8_t I2Cdev::readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint16_t timeout) { + return readBytes(devAddr, regAddr, 1, data, timeout); +} + +/** Read multiple bytes from an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr First register regAddr to read from + * @param length Number of bytes to read + * @param data Buffer to store read data in + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) + * @return I2C_TransferReturn_TypeDef http://downloads.energymicro.com/documentation/doxygen/group__I2C.html + */ +int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data, uint16_t timeout) { + + I2C_TransferSeq_TypeDef seq; + + uint8_t regid[1]; + + seq.addr = devAddr << 1; + seq.flags = I2C_FLAG_WRITE_READ; + + /* Select register to be read */ + regid[0] = regAddr; + seq.buf[0].data = regid; + seq.buf[0].len = 1; + + /* 1 bytes reg */ + seq.buf[1].data = data; + seq.buf[1].len = length; + + if (transfer(&seq, timeout) == i2cTransferDone) { + return seq.buf[1].len; + } else { + return false; + } + +} + +/** write a single bit in an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to write to + * @param bitNum Bit position to write (0-7) + * @param value New bit value to write + * @return Status of operation (true = success) + */ +bool I2Cdev::writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t data) { + uint8_t b; + readByte(devAddr, regAddr, &b); + b = (data != 0) ? (b | (1 << bitNum)) : (b & ~(1 << bitNum)); + return writeByte(devAddr, regAddr, b); +} + +/** Write multiple bits in an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to write to + * @param bitStart First bit position to write (0-7) + * @param length Number of bits to write (not more than 8) + * @param data Right-aligned value to write + * @return Status of operation (true = success) + */ +bool I2Cdev::writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data) { + // 010 value to write + // 76543210 bit numbers + // xxx args: bitStart=4, length=3 + // 00011100 mask byte + // 10101111 original value (sample) + // 10100011 original & ~mask + // 10101011 masked | value + uint8_t b; + if (readByte(devAddr, regAddr, &b) != 0) { + uint8_t mask = ((1 << length) - 1) << (bitStart - length + 1); + data <<= (bitStart - length + 1); // shift data into correct position + data &= mask; // zero all non-important bits in data + b &= ~(mask); // zero all important bits in existing byte + b |= data; // combine data with existing byte + return writeByte(devAddr, regAddr, b); + } else { + return false; + } +} + +/** Write single byte to an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register address to write to + * @param data New byte value to write + * @return Status of operation (true = success) + */ +bool I2Cdev::writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data) { + + I2C_TransferSeq_TypeDef seq; + + uint8_t writeData[3]; + + seq.addr = devAddr << 1; + seq.flags = I2C_FLAG_WRITE; + + /* Select register to be written */ + writeData[0] = regAddr; + seq.buf[0].data = writeData; + + /* Only 1 byte reg */ + writeData[1] = data; + seq.buf[0].len = 2; + + if (transfer(&seq) == i2cTransferDone) { + return true; + } else { + return false; + } + +} diff --git a/EFM32/I2Cdev/I2Cdev.h b/EFM32/I2Cdev/I2Cdev.h new file mode 100644 index 00000000..52d19564 --- /dev/null +++ b/EFM32/I2Cdev/I2Cdev.h @@ -0,0 +1,84 @@ +// I2Cdev library collection - Main I2C device class +// Abstracts bit and byte I2C R/W functions into a convenient class +// EFM32 stub port by Nicolas Baldeck +// Based on Arduino's I2Cdev by Jeff Rowberg +// +// Changelog: +// 2015-01-02 - Initial release + + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2015 Jeff Rowberg, Nicolas Baldeck + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#ifndef _I2CDEV_H_ +#define _I2CDEV_H_ + +#include +#include +#include + +#define I2C_SDA_PORT gpioPortA +#define I2C_SDA_PIN 0 +#define I2C_SDA_MODE gpioModeWiredAnd +#define I2C_SDA_DOUT 1 + +#define I2C_SCL_PORT gpioPortA +#define I2C_SCL_PIN 1 +#define I2C_SCL_MODE gpioModeWiredAnd +#define I2C_SCL_DOUT 1 + +#define I2CDEV_DEFAULT_READ_TIMEOUT 1000000 + +class I2Cdev { + public: + I2Cdev(); + + static void initialize(); + static void enable(bool isEnabled); + + static int8_t readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout); + //TODO static int8_t readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout); + static int8_t readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout); + //TODO static int8_t readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout); + static int8_t readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout); + //TODO static int8_t readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout); + static int8_t readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout); + //TODO static int8_t readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout); + + static bool writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t data); + //TODO static bool writeBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t data); + static bool writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data); + //TODO static bool writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t data); + static bool writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data); + //TODO static bool writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data); + //TODO static bool writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data); + //TODO static bool writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data); + + static uint16_t readTimeout; + + private: + static I2C_TransferReturn_TypeDef transfer(I2C_TransferSeq_TypeDef *seq, uint16_t timeout=I2Cdev::readTimeout); +}; + +#endif /* _I2CDEV_H_ */ From a7cfb5bc1be4d34d942ea04f036908a6753cd653 Mon Sep 17 00:00:00 2001 From: Nate Costello Date: Thu, 5 Mar 2015 12:31:21 -0500 Subject: [PATCH 059/335] Completed and tested an Arduino driver for the L3GD20H gyro --- Arduino/L3GD20H/L3GD20H.cpp | 1695 +++++++++++++++++ Arduino/L3GD20H/L3GD20H.h | 398 ++++ .../examples/L3GD20H_basic/L3GD20H_basic.ino | 122 ++ 3 files changed, 2215 insertions(+) create mode 100644 Arduino/L3GD20H/L3GD20H.cpp create mode 100644 Arduino/L3GD20H/L3GD20H.h create mode 100644 Arduino/L3GD20H/examples/L3GD20H_basic/L3GD20H_basic.ino diff --git a/Arduino/L3GD20H/L3GD20H.cpp b/Arduino/L3GD20H/L3GD20H.cpp new file mode 100644 index 00000000..62200f52 --- /dev/null +++ b/Arduino/L3GD20H/L3GD20H.cpp @@ -0,0 +1,1695 @@ +// I2Cdev library collection - L3GD20H I2C device class +// Based on STMicroelectronics L3GD20H datasheet rev. 2, 3/2013 +// X/XX/2015 by Nate Costello +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// 2015-XX-XX - initial release + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2011 Jonathan Arnett, Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#include "L3GD20H.h" + +/** Default constructor, uses default I2C address. + * @see L3GD20H_DEFAULT_ADDRESS + */ +L3GD20H::L3GD20H() { + devAddr = L3GD20H_DEFAULT_ADDRESS; + endianMode = 0; +} + +/** Specific address constructor. + * @param address I2C address + * @see L3GD20H_DEFAULT_ADDRESS + * @see L3GD20H_ADDRESS + */ +L3GD20H::L3GD20H(uint8_t address) { + devAddr = address; + endianMode = 0; +} + +/** Power on and prepare for general usage. + * All values are defaults except for the power on bit in CTRL_1 + * @see L3GD20H_RA_CTRL1 + * @see L3GD20H_RA_CTRL2 + * @see L3GD20H_RA_CTRL3 + * @see L3GD20H_RA_CTRL4 + * @see L3GD20H_RA_CTRL5 + */ +void L3GD20H::initialize() { + I2Cdev::writeByte(devAddr, L3GD20H_RA_CTRL1, 0b00001111); + I2Cdev::writeByte(devAddr, L3GD20H_RA_CTRL2, 0b00000000); + I2Cdev::writeByte(devAddr, L3GD20H_RA_CTRL3, 0b00000000); + I2Cdev::writeByte(devAddr, L3GD20H_RA_CTRL4, 0b00000000); + I2Cdev::writeByte(devAddr, L3GD20H_RA_CTRL5, 0b00000000); +} + +/** Verify the I2C connection. + * Make sure the device is connected and responds as expected. + * @return True if connection is valid, false otherwise + */ +bool L3GD20H::testConnection() { + return getDeviceID() == 0b11010111; +} + +// WHO_AM_I register, read-only + +/** Get the Device ID. + * The WHO_AM_I register holds the device's id + * @return Device ID (should be 0b11010011, 109, 0x69) + * @see L3GD20H_RA_WHO_AM_I + */ +uint8_t L3GD20H::getDeviceID() { + I2Cdev::readByte(devAddr, L3GD20H_RA_WHO_AM_I, buffer); + return buffer[0]; +} + +// CTRL1 register, r/w + +/** Set the output data rate. Makes use of the setLowODREnabled function. + * @param rate The new data output rate (can be 12, 25, 50, 100, 200, 400, or 800) + * @see L3GD20H_RA_CTRL1 + * @see L3GD20H_ODR_BIT + * @see L3GD20H_ODR_LENGTH + * @see L3GD20H_RATE_100_12 + * @see L3GD20H_RATE_200_25 + * @see L3GD20H_RATE_400_50 + * @see L3GD20H_RATE_800_50 + * @see L3GD20H_RA_LOW_ODR + * @see L3GD20H_LOW_ODR_BIT + */ +void L3GD20H::setOutputDataRate(uint16_t rate) { + uint8_t writeVal; + bool lowODRwriteVal; + + if (rate ==12) { + writeVal = L3GD20H_RATE_100_12; + setLowODREnabled(true); + } else if (rate == 25) { + writeVal = L3GD20H_RATE_200_25; + setLowODREnabled(true); + } else if (rate == 50) { + writeVal = L3GD20H_RATE_400_50; + setLowODREnabled(true); + } else if (rate == 100) { + writeVal = L3GD20H_RATE_100_12; + setLowODREnabled(false); + } else if (rate == 200) { + writeVal = L3GD20H_RATE_200_25; + setLowODREnabled(false); + } else if (rate == 400) { + writeVal = L3GD20H_RATE_400_50; + setLowODREnabled(false); + } else { + writeVal = L3GD20H_RATE_800_50; + setLowODREnabled(false); + } + + I2Cdev::writeBits(devAddr, L3GD20H_RA_CTRL1, L3GD20H_ODR_BIT, + L3GD20H_ODR_LENGTH, writeVal); +} + +/** Get the current output data rate + * @return Current data output rate + * @see L3GD20H_RA_CTRL1 + * @see L3GD20H_ODR_BIT + * @see L3GD20H_ODR_LENGTH + * @see L3GD20H_RATE_100_12 + * @see L3GD20H_RATE_200_25 + * @see L3GD20H_RATE_400_50 + * @see L3GD20H_RATE_800_50 + * @see L3GD20H_RA_LOW_ODR + * @see L3GD20H_LOW_ODR_BIT + */ +uint16_t L3GD20H::getOutputDataRate() { + I2Cdev::readBits(devAddr, L3GD20H_RA_CTRL1, L3GD20H_ODR_BIT, + L3GD20H_ODR_LENGTH, buffer); + uint8_t rate = buffer[0]; + + if (rate == L3GD20H_RATE_100_12) { + if (getLowODREnabled() == true) { + return 12; + } else { + return 100; + } + } else if (rate == L3GD20H_RATE_200_25) { + if (getLowODREnabled() == true) { + return 25; + } else { + return 200; + } + } else if (rate == L3GD20H_RATE_400_50) { + if (getLowODREnabled() == true) { + return 50; + } else { + return 400; + } + } else if (rate == L3GD20H_RATE_800_50) { + if (getLowODREnabled() == true) { + return 50; + } else { + return 800; + } + } + return 800; +} + +/** Set the bandwidth cut-off mode + * @param mode The new bandwidth cut-off mode + * @see L3GD20H_RA_CTRL1 + * @see L3GD20H_BW_BIT + * @see L3GD20H_BW_LENGTH + * @see L3GD20H_BW_LOW + * @see L3GD20H_BW_MED_LOW + * @see L3GD20H_BW_MED_HIGH + * @see L3GD20H_BW_HIGH + */ +void L3GD20H::setBandwidthCutOffMode(uint8_t mode) { + I2Cdev::writeBits(devAddr, L3GD20H_RA_CTRL1, L3GD20H_BW_BIT, + L3GD20H_BW_LENGTH, mode); +} + +/** Get the current bandwidth cut-off mode + * @return Current bandwidth cut off mode + * @see L3GD20H_RA_CTRL1 + * @see L3GD20H_BW_BIT + * @see L3GD20H_BW_LENGTH + * @see L3GD20H_BW_LOW + * @see L3GD20H_BW_MED_LOW + * @see L3GD20H_BW_MED_HIGH + * @see L3GD20H_BW_HIGH + */ +uint8_t L3GD20H::getBandwidthCutOffMode() { + I2Cdev::readBits(devAddr, L3GD20H_RA_CTRL1, L3GD20H_BW_BIT, + L3GD20H_BW_LENGTH, buffer); + return buffer[0]; +} + +// /** Gets the current bandwidth cutoff based on ODR and BW +// * @return Float value of the bandwidth cut off +// * @see L3GD20H_RA_CTRL1 +// * @see L3GD20H_ODR_BIT +// * @see L3GD20H_ODR_LENGTH +// * @see L3GD20H_RATE_100_12 +// * @see L3GD20H_RATE_200_25 +// * @see L3GD20H_RATE_400_50 +// * @see L3GD20H_RATE_800_50 +// * @see L3GD20H_BW_BIT +// * @see L3GD20H_BW_LENGTH +// * @see L3GD20H_BW_LOW +// * @see L3GD20H_BW_MED_LOW +// * @see L3GD20H_BW_MED_HIGH +// * @see L3GD20H_BW_HIGH +// */ +// float L3GD20H::getBandwidthCutOff() { +// uint16_t dataRate = getOutputDataRate(); +// uint8_t bandwidthMode = getBandwidthCutOffMode(); + +// if (dataRate == 50) { +// return 16.6; +// } else if (dataRate == 100) { +// if (bandwidthMode == L3GD20H_BW_LOW) { +// return 12.5; +// } else { +// return 25.0; +// } +// } else if (dataRate == 200) { +// if (bandwidthMode == L3GD20H_BW_LOW) { +// return 12.5; +// } else if (bandwidthMode == L3GD20H_BW_MED_LOW) { +// return 0.0; +// } else if (bandwidthMode == L3GD20H_BW_MED_HIGH) { +// return 0.0; +// } else { +// return 70.0; +// } +// } else if (dataRate == 400) { +// if (bandwidthMode == L3GD20H_BW_LOW) { +// return 20.0; +// } else if (bandwidthMode == L3GD20H_BW_MED_LOW) { +// return 25.0; +// } else if (bandwidthMode == L3GD20H_BW_MED_HIGH) { +// return 50.0; +// } else { +// return 110.0; +// } +// } else if (dataRate == 800) { +// if (bandwidthMode == L3GD20H_BW_LOW) { +// return 30.0; +// } else if (bandwidthMode == L3GD20H_BW_MED_LOW) { +// return 35.0; +// } else if (bandwidthMode == L3GD20H_BW_MED_HIGH) { +// return 0.0; +// } else { +// return 110.0; +// } +// } else { +// return 0.0 +// } +// } + +/** Set power on or off + * @param enabled The new power setting (true for on, false for off) + * @see L3GD20H_RA_CTRL1 + * @see L3GD20H_PD_BIT + */ +void L3GD20H::setPowerOn(bool on) { + I2Cdev::writeBit(devAddr, L3GD20H_RA_CTRL1, L3GD20H_PD_BIT, on); +} + +/** Get the current power state + * @return Powered on state (true for on, false for off) + * @see L3GD20H_RA_CTRL1 + * @see L3GD20H_PD_BIT + */ +bool L3GD20H::getPowerOn() { + I2Cdev::readBit(devAddr, L3GD20H_RA_CTRL1, L3GD20H_PD_BIT, buffer); + return buffer[0]; +} + +/** Enables or disables the ability to get Z data + * @param enabled The new enabled state of the Z axis + * @see L3GD20H_RA_CTRL1 + * @see L3GD20H_ZEN_BIT + */ +void L3GD20H::setZEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, L3GD20H_RA_CTRL1, L3GD20H_ZEN_BIT, enabled); +} + +/** Get whether Z axis data is enabled + * @return True if the Z axis is enabled, false otherwise + * @see L3GD20H_RA_CTRL1 + * @see L3GD20H_ZEN_BIT + */ +bool L3GD20H::getZEnabled() { + I2Cdev::readBit(devAddr, L3GD20H_RA_CTRL1, L3GD20H_ZEN_BIT, buffer); + return buffer[0]; +} + +/** Enables or disables the ability to get Y data + * @param enabled The new enabled state of the Y axis + * @see L3GD20H_RA_CTRL1 + * @see L3GD20H_YEN_BIT + */ +void L3GD20H::setYEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, L3GD20H_RA_CTRL1, L3GD20H_YEN_BIT, enabled); +} + +/** Get whether Y axis data is enabled + * @return True if the Y axis is enabled, false otherwise + * @see L3GD20H_RA_CTRL1 + * @see L3GD20H_YEN_BIT + */ +bool L3GD20H::getYEnabled() { + I2Cdev::readBit(devAddr, L3GD20H_RA_CTRL1, L3GD20H_YEN_BIT, buffer); + return buffer[0]; +} + +/** Enables or disables the ability to get X data + * @param enabled The new enabled state of the X axis + * @see L3GD20H_RA_CTRL1 + * @see L3GD20H_XEN_BIT + */ +void L3GD20H::setXEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, L3GD20H_RA_CTRL1, L3GD20H_XEN_BIT, enabled); +} + +/** Get whether X axis data is enabled + * @return True if the X axis is enabled, false otherwise + * @see L3GD20H_RA_CTRL1 + * @see L3GD20H_XEN_BIT + */ +bool L3GD20H::getXEnabled() { + I2Cdev::readBit(devAddr, L3GD20H_RA_CTRL1, L3GD20H_XEN_BIT, buffer); + return buffer[0]; +} + +// CTRL2 register, r/w + +/** Set the high pass mode + * @param mode The new high pass mode + * @see L3GD20H_RA_CTRL2 + * @see L3GD20H_HPM_BIT + * @see L3GD20H_HPM_LENGTH + * @see L3GD20H_HPM_HRF + * @see L3GD20H_HPM_REFERENCE + * @see L3GD20H_HPM_NORMAL + * @see L3GD20H_HPM_AUTORESET + */ +void L3GD20H::setHighPassMode(uint8_t mode) { + I2Cdev::writeBits(devAddr, L3GD20H_RA_CTRL2, L3GD20H_HPM_BIT, + L3GD20H_HPM_LENGTH, mode); +} + +/** Get the high pass mode + * @return High pass mode + * @see L3GD20H_RA_CTRL2 + * @see L3GD20H_HPM_BIT + * @see L3GD20H_HPM_LENGTH + * @see L3GD20H_HPM_HRF + * @see L3GD20H_HPM_REFERENCE + * @see L3GD20H_HPM_NORMAL + * @see L3GD20H_HPM_AUTORESET + */ +uint8_t L3GD20H::getHighPassMode() { + I2Cdev::readBits(devAddr, L3GD20H_RA_CTRL2, L3GD20H_HPM_BIT, + L3GD20H_HPM_LENGTH, buffer); + return buffer[0]; +} + +/** Set the high pass filter cut off frequency level (1 - 10) + * @param level The new level for the hpcf, using one of the defined levels + * @see L3GD20H_RA_CTRL2 + * @see L3GD20H_HPCF_BIT + * @see L3GD20H_HPCF_LENGTH + * @see L3GD20H_HPCF1 + * @see L3GD20H_HPCF2 + * @see L3GD20H_HPCF3 + * @see L3GD20H_HPCF4 + * @see L3GD20H_HPCF5 + * @see L3GD20H_HPCF6 + * @see L3GD20H_HPCF7 + * @see L3GD20H_HPCF8 + * @see L3GD20H_HPCF9 + * @see L3GD20H_HPCF10 + */ +void L3GD20H::setHighPassFilterCutOffFrequencyLevel(uint8_t level) { + I2Cdev::writeBits(devAddr, L3GD20H_RA_CTRL2, L3GD20H_HPCF_BIT, + L3GD20H_HPCF_LENGTH, level); +} + +/** Get the high pass filter cut off frequency level (1 - 10) + * @return High pass filter cut off frequency level + * @see L3GD20H_RA_CTRL2 + * @see L3GD20H_HPCF_BIT + * @see L3GD20H_HPCF_LENGTH + * @see L3GD20H_HPCF1 + * @see L3GD20H_HPCF2 + * @see L3GD20H_HPCF3 + * @see L3GD20H_HPCF4 + * @see L3GD20H_HPCF5 + * @see L3GD20H_HPCF6 + * @see L3GD20H_HPCF7 + * @see L3GD20H_HPCF8 + * @see L3GD20H_HPCF9 + * @see L3GD20H_HPCF10 + */ +uint8_t L3GD20H::getHighPassFilterCutOffFrequencyLevel() { + I2Cdev::readBits(devAddr, L3GD20H_RA_CTRL2, L3GD20H_HPCF_BIT, + L3GD20H_HPCF_LENGTH, buffer); + return buffer[0]; +} + +// CTRL3 register, r/w + +/** Set the INT1 interrupt enabled state + * @param enabled New enabled state for the INT1 interrupt + * @see L3GD20H_RA_CTRL3 + * @see L3GD20H_INT1_IG_BIT + */ +void L3GD20H::setINT1InterruptEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, L3GD20H_RA_CTRL3, L3GD20H_INT1_IG_BIT, + enabled); +} + +/** Get the INT1 interrupt enabled state + * @return True if the INT1 interrupt is enabled, false otherwise + * @see L3GD20H_RA_CTRL3 + * @see L3GD20H_INT1_IG_BIT + */ +bool L3GD20H::getINT1InterruptEnabled() { + I2Cdev::readBit(devAddr, L3GD20H_RA_CTRL3, L3GD20H_INT1_IG_BIT, + buffer); + return buffer[0]; +} + +/** Set the INT1 boot status enabled state + * @param enabled New enabled state for the INT1 boot status + * @see L3GD20H_RA_CTRL3 + * @see L3GD20H_INT1_BOOT_BIT + */ +void L3GD20H::setINT1BootStatusEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, L3GD20H_RA_CTRL3, L3GD20H_INT1_BOOT_BIT, + enabled); +} + +/** Get the INT1 boot status enabled state + * @return INT1 boot status status + * @see L3GD20H_RA_CTRL3 + * @see L3GD20H_INT1_BOOT_BIT + */ +bool L3GD20H::getINT1BootStatusEnabled() { + I2Cdev::readBit(devAddr, L3GD20H_RA_CTRL3, L3GD20H_INT1_BOOT_BIT, + buffer); + return buffer[0]; +} + +/** Interrupts the active INT1 configuration + * @see L3GD20H_RA_CTRL3 + * @see L3GD20H_H_LACTIVE_BIT + */ +void L3GD20H::interruptActiveINT1Config() { + I2Cdev::writeBit(devAddr, L3GD20H_RA_CTRL3, L3GD20H_H_LACTIVE_BIT, 1); +} + +/** Set output mode to push-pull or open-drain + * @param mode New output mode + * @see L3GD20H_RA_CTRL3 + * @see L3GD20H_PP_OD_BIT + * @see L3GD20H_PUSH_PULL + * @see L3GD20H_OPEN_DRAIN + */ +void L3GD20H::setOutputMode(bool mode) { + I2Cdev::writeBit(devAddr, L3GD20H_RA_CTRL3, L3GD20H_PP_OD_BIT, + mode); +} + +/** Get whether mode is push-pull or open drain + * @return Output mode (TRUE for open-drain, FALSE for push-pull) + * @see L3GD20H_RA_CTRL3 + * @see L3GD20H_PP_OD_BIT + * @see L3GD20H_PUSH_PULL + * @see L3GD20H_OPEN_DRAIN + */ +bool L3GD20H::getOutputMode() { + I2Cdev::readBit(devAddr, L3GD20H_RA_CTRL3, L3GD20H_PP_OD_BIT, + buffer); + return buffer[0]; +} + +/** Set data ready interrupt enabled state on INT2 pin + * @param enabled New INT2 data ready interrupt enabled state + * @see L3GD20H_RA_CTRL3 + * @see L3GD20H_INT2_DRDY_BIT + */ +void L3GD20H::setINT2DataReadyEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, L3GD20H_RA_CTRL3, L3GD20H_INT2_DRDY_BIT, + enabled); +} + +/** Get whether the data ready interrupt is enabled on the INT2 pin + * @return True if the INT2 data ready interrupt is enabled, false otherwise + * @see L3GD20H_RA_CTRL3 + * @see L3GD20H_INT2_DRDY_BIT + */ +bool L3GD20H::getINT2DataReadyEnabled() { + I2Cdev::readBit(devAddr, L3GD20H_RA_CTRL3, L3GD20H_INT2_DRDY_BIT, + buffer); + return buffer[0]; +} + +/** Set whether the INT2 FIFO threshold (watermark) interrupt is enabled + * The sensor contains a 32-slot FIFO buffer for storing data so that it may be + * read later. If enabled, the sensor will generate an interrupt on the + * INT2/DRDY pin when the threshold has been reached. The threshold can be + * configured through the setFIFOWatermark function. + * @param enabled New enabled state of the INT2 FIFO threshold (watermark) + * @see L3GD20H_RA_CTRL3 + * @see L3GD20H_I2_WTM_BIT + */ +void L3GD20H::setINT2FIFOWatermarkInterruptEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, L3GD20H_RA_CTRL3, L3GD20H_INT2_FTH_BIT, + enabled); +} + +/** Get the INT2 FIFO threshold (watermark) interrupt enabled state + * @return true if the FIFO watermark is enabled, false otherwise + * @see L3GD20H_RA_CTRL3 + * @see L3GD20H_INT2_FTH_BIT + */ +bool L3GD20H::getINT2FIFOWatermarkInterruptEnabled() { + I2Cdev::readBit(devAddr, L3GD20H_RA_CTRL3, L3GD20H_INT2_FTH_BIT, + buffer); + return buffer[0]; +} + +/** Set whether an interrupt is triggered on INT2 when the FIFO is overrun + * @param enabled New FIFO overrun interrupt enabled state + * @see L3GD20H_RA_CTRL3 + * @see L3GD20H_INT2_ORUN_BIT + */ +void L3GD20H::setINT2FIFOOverrunInterruptEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, L3GD20H_RA_CTRL3, L3GD20H_INT2_ORUN_BIT, + enabled); +} + +/** Get whether an interrupt is triggered on INT2 when the FIFO is overrun + * @return True if the INT2 FIFO overrun interrupt is enabled, false otherwise + * @see L3GD20H_RA_CTRL3 + * @see L3GD20H_INT2_ORUN_BIT + */ +bool L3GD20H::getINT2FIFOOverrunInterruptEnabled() { + I2Cdev::readBit(devAddr, L3GD20H_RA_CTRL3, L3GD20H_INT2_ORUN_BIT, + buffer); + return buffer[0]; +} + +/** Set whether an interrupt is triggered on INT2 when the FIFO buffer is empty + * @param enabled New INT2 FIFO empty interrupt state + * @see L3GD20H_RA_CTRL3 + * @see L3GD20H_INT2_EMPTY_BIT + */ +void L3GD20H::setINT2FIFOEmptyInterruptEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, L3GD20H_RA_CTRL3, L3GD20H_INT2_EMPTY_BIT, + enabled); +} + +/** Get whether the INT2 FIFO empty interrupt is enabled + * @returns True if the INT2 FIFO empty interrupt is enabled, false otherwise + * @see L3GD20H_RA_CTRL3 + * @see L3GD20H_INT2_EMPTY_BIT + */ +bool L3GD20H::getINT2FIFOEmptyInterruptEnabled() { + I2Cdev::readBit(devAddr, L3GD20H_RA_CTRL3, L3GD20H_INT2_EMPTY_BIT, + buffer); + return buffer[0]; +} + +// CTRL4 register, r/w + +/** Set the Block Data Update (BDU) enabled state + * @param enabled New BDU enabled state + * @see L3GD20H_RA_CTRL4 + * @see L3GD20H_BDU_BIT + */ +void L3GD20H::setBlockDataUpdateEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, L3GD20H_RA_CTRL4, L3GD20H_BDU_BIT, enabled); +} + +/** Get the BDU enabled state + * @return True if Block Data Update is enabled, false otherwise + * @see L3GD20H_RA_CTRL4 + * @see L3GD20H_BDU_BIT + */ +bool L3GD20H::getBlockDataUpdateEnabled() { + I2Cdev::readBit(devAddr, L3GD20H_RA_CTRL4, L3GD20H_BDU_BIT, buffer); + return buffer[0]; +} + +/** Set the data endian modes + * In Big Endian mode, the Most Significat Byte (MSB) is on the lower address, + * and the Least Significant Byte (LSB) is on the higher address. Little Endian + * mode reverses this order. Little Endian is the default mode. + * @param endianness New endian mode + * @see L3GD20H_RA_CTRL4 + * @see L3GD20H_BLE_BIT + * @see L3GD20H_BIG_ENDIAN + * @see L3GD20H_LITTLE_ENDIAN + */ +void L3GD20H::setEndianMode(bool endianness) { + I2Cdev::writeBit(devAddr, L3GD20H_RA_CTRL4, L3GD20H_BLE_BIT, + endianness); + endianMode = getEndianMode(); +} + +/** Get the data endian mode + * @return Current endian mode + * @see L3GD20H_RA_CTRL4 + * @see L3GD20H_BLE_BIT + * @see L3GD20H_BIG_ENDIAN + * @see L3GD20H_LITTLE_ENDIAN + */ +bool L3GD20H::getEndianMode() { + I2Cdev::readBit(devAddr, L3GD20H_RA_CTRL4, L3GD20H_BLE_BIT, + buffer); + return buffer[0]; +} + +/** Set the full scale of the data output (in dps) + * @param scale The new scale of the data output (250 [actual 245], 500, 2000) + * @see L3GD20H_RA_CTRL4 + * @see L3GD20H_FS_BIT + * @see L3GD20H_FS_LENGTH + * @see L3GD20H_FS_250 + * @see L3GD20H_FS_500 + * @see L3GD20H_FS_2000 + */ +void L3GD20H::setFullScale(uint16_t scale) { + uint8_t writeBits; + + if (scale == 250) { + writeBits = L3GD20H_FS_250; + } else if (scale == 500) { + writeBits = L3GD20H_FS_500; + } else { + writeBits = L3GD20H_FS_2000; + } + + I2Cdev::writeBits(devAddr, L3GD20H_RA_CTRL4, L3GD20H_FS_BIT, + L3GD20H_FS_LENGTH, writeBits); +} + +/** Get the current full scale of the output data (in dps) + * @return Current scale of the output data + * @see L3GD20H_RA_CTRL4 + * @see L3GD20H_FS_BIT + * @see L3GD20H_FS_LENGTH + * @see L3GD20H_FS_250 + * @see L3GD20H_FS_500 + * @see L3GD20H_FS_2000 + */ +uint16_t L3GD20H::getFullScale() { + I2Cdev::readBits(devAddr, L3GD20H_RA_CTRL4, + L3GD20H_FS_BIT, L3GD20H_FS_LENGTH, buffer); + uint8_t readBits = buffer[0]; + + if (readBits == L3GD20H_FS_250) { + return 250; + } else if (readBits == L3GD20H_FS_500) { + return 500; + } else { + return 2000; + } +} + +//TODO +//Implement +//L3GD20H::setLevelSensitiveLatchedEnabled() and +//L3GD20H::getLevelSensitiveLatchedEnabled() +// + +/** Set the self test mode + * @param mode New self test mode (Normal, 0, 1) + * @see L3GD20H_RA_CTRL4 + * @see L3GD20H_ST_BIT + * @see L3GD20H_ST_LENGTH + * @see L3GD20H_SELF_TEST_NORMAL + * @see L3GD20H_SELF_TEST_0 + * @see L3GD20H_SELF_TEST_1 + */ +void L3GD20H::setSelfTestMode(uint8_t mode) { + I2Cdev::writeBits(devAddr, L3GD20H_RA_CTRL4, L3GD20H_ST_BIT, + L3GD20H_ST_LENGTH, mode); +} + +/** Get the current self test mode + * @return Current self test mode + * @see L3GD20H_RA_CTRL4 + * @see L3GD20H_ST_BIT + * @see L3GD20H_ST_LENGTH + * @see L3GD20H_SELF_TEST_NORMAL + * @see L3GD20H_SELF_TEST_0 + * @see L3GD20H_SELF_TEST_1 + */ +uint8_t L3GD20H::getSelfTestMode() { + I2Cdev::readBits(devAddr, L3GD20H_RA_CTRL4, L3GD20H_ST_BIT, + L3GD20H_ST_LENGTH, buffer); + return buffer[0]; +} + +/** Set the SPI mode + * @param mode New SPI mode + * @see L3GD20H_RA_CTRL4 + * @see L3GD20H_SIM_BIT + * @see L3GD20H_SPI_4_WIRE + * @see L3GD20H_SPI_3_WIRE + */ +void L3GD20H::setSPIMode(bool mode) { + I2Cdev::writeBit(devAddr, L3GD20H_RA_CTRL4, L3GD20H_SIM_BIT, mode); +} + +/** Get the SPI mode + * @return Current SPI mode + * @see L3GD20H_RA_CTRL4 + * @see L3GD20H_SIM_BIT + * @see L3GD20H_SPI_4_WIRE + * @see L3GD20H_SPI_3_WIRE + */ +bool L3GD20H::getSPIMode() { + I2Cdev::readBit(devAddr, L3GD20H_RA_CTRL4, L3GD20H_SIM_BIT, + buffer); + return buffer[0]; +} + +// CTRL5 register, r/w + +/** Reboots the FIFO memory content + * @see L3GD20H_RA_CTRL5 + * @see L3GD20H_BOOT_BIT + */ +void L3GD20H::rebootMemoryContent() { + I2Cdev::writeBit(devAddr, L3GD20H_RA_CTRL5, L3GD20H_BOOT_BIT, true); +} + +/** Set whether the FIFO buffer is enabled + * @param enabled New enabled state of the FIFO buffer + * @see L3GD20H_RA_CTRL5 + * @see L3GD20H_FIFO_EN_BIT + */ +void L3GD20H::setFIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, L3GD20H_RA_CTRL5, L3GD20H_FIFO_EN_BIT, + enabled); +} + +/** Get whether the FIFO buffer is enabled + * @return True if the FIFO buffer is enabled, false otherwise + * @see L3GD20H_RA_CTRL5 + * @see L3GD20H_FIFO_EN_BIT + */ +bool L3GD20H::getFIFOEnabled() { + I2Cdev::readBit(devAddr, L3GD20H_RA_CTRL5, L3GD20H_FIFO_EN_BIT, + buffer); + return buffer[0]; +} + +/** Set whether the sensing chain FIFO stops writing new values once + * the FIFO Threshold (watermark) is reached + * @param enabled New state of the StopOnFTH bit + * @see L3GD20H_RA_CTRL5 + * @see L3GD20H_FIFO_STOPONFTH_BIT + */ +void L3GD20H::setStopOnFIFOThresholdEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, L3GD20H_RA_CTRL5, L3GD20H_STOPONFTH_BIT, + enabled); +} + +/** Get whether the sensing chain FIFO stopping writing new values once + * the FIFO Threshold (watermark) is enabled + * @return True if the state of the StopOnFTH bit is high (enabled) + * @see L3GD20H_RA_CTRL5 + * @see L3GD20H_FIFO_STOPONFTH_BIT + */ +bool L3GD20H::getStopOnFIFOThresholdEnabled() { + I2Cdev::readBit(devAddr, L3GD20H_RA_CTRL5, L3GD20H_STOPONFTH_BIT, + buffer); + return buffer[0]; +} + + +/** Set the high pass filter enabled state + * @param enabled New high pass filter enabled state + * @see L3GD20H_RA_CTRL5 + * @see L3GD20H_HPEN_BIT + */ +void L3GD20H::setHighPassFilterEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, L3GD20H_RA_CTRL5, L3GD20H_HPEN_BIT, + enabled); +} + +/** Get whether the high pass filter is enabled + * @return True if the high pass filter is enabled, false otherwise + * @see L3GD20H_RA_CTRL5 + * @see L3GD20H_HPEN_BIT + */ +bool L3GD20H::getHighPassFilterEnabled() { + I2Cdev::readBit(devAddr, L3GD20H_RA_CTRL5, L3GD20H_HPEN_BIT, + buffer); + return buffer[0]; +} + +/** Sets the filter mode to one of the four provided. + * This function also uses the setHighPassFilterEnabled function in order to set + * the mode. That function does not have to be called in addition to this one. + * In addition to setting the filter for the data in the FIFO buffer + * (controlled by the bits written to OUT_SEL), this function also sets the + * filter used for interrupt generation (the bits written to IG_SEL) to be the + * same as the filter used for the FIFO buffer. The filter used for interrupt + * generation can be set separately with the setInterruptFilter function. + * @param filter New method to be used when filtering data + * @see L3GD20H_RA_CTRL5 + * @see L3GD20H_IG_SEL_BIT + * @see L3GD20H_IG_SEL_LENGTH + * @see L3GD20H_OUT_SEL_BIT + * @see L3GD20H_OUT_SEL_LENGTH + * @see L3GD20H_NON_HIGH_PASS + * @see L3GD20H_HIGH_PASS + * @see L3GD20H_LOW_PASS + * @see L3GD20H_LOW_HIGH_PASS + */ +void L3GD20H::setDataFilter(uint8_t filter) { + if (filter == L3GD20H_HIGH_PASS || filter == L3GD20H_LOW_HIGH_PASS) { + setHighPassFilterEnabled(true); + } else { + setHighPassFilterEnabled(false); + } + + I2Cdev::writeBits(devAddr, L3GD20H_RA_CTRL5, L3GD20H_OUT_SEL_BIT, + L3GD20H_OUT_SEL_LENGTH, filter); + I2Cdev::writeBits(devAddr, L3GD20H_RA_CTRL5, L3GD20H_IG_SEL_BIT, + L3GD20H_IG_SEL_LENGTH, filter); +} + +/** Gets the data filter currently in use + * @return Defined value that represents the filter in use + * @see L3GD20H_RA_CTRL5 + * @see L3GD20H_OUT_SEL_BIT + * @see L3GD20H_OUT_SEL_LENGTH + * @see L3GD20H_NON_HIGH_PASS + * @see L3GD20H_HIGH_PASS + * @see L3GD20H_LOW_PASS + * @see L3GD20H_LOW_HIGH_PASS + */ +uint8_t L3GD20H::getDataFilter() { + I2Cdev::readBits(devAddr, L3GD20H_RA_CTRL5, L3GD20H_OUT_SEL_BIT, + L3GD20H_OUT_SEL_LENGTH, buffer); + uint8_t outBits = buffer[0]; + + if (outBits == L3GD20H_NON_HIGH_PASS || outBits == L3GD20H_HIGH_PASS) { + return outBits; + } + + if (getHighPassFilterEnabled()) { + return L3GD20H_LOW_HIGH_PASS; + } else { + return L3GD20H_LOW_PASS; + } +} + +//ToDo: +//setInterruptFilter +//getInterruptFilter + +// REFERENCE register, r/w + +/** Set the reference value for the high pass filter + * @param reference New 8-bit digital high pass filter reference value + * @see L3GD20H_RA_REFERENCE + */ +void L3GD20H::setHighPassFilterReference(uint8_t reference) { + I2Cdev::writeByte(devAddr, L3GD20H_RA_REFERENCE, reference); +} + +/** Get the 8-bit reference value for the high pass filter + * @return 8-bit reference value for the high pass filter + * @see L3GD20H_RA_REFERENCE + */ +uint8_t L3GD20H::getHighPassFilterReference() { + I2Cdev::readByte(devAddr, L3GD20H_RA_REFERENCE, buffer); + return buffer[0]; +} + +// void L3GD20H::setInterruptReference(uint8_t reference) { +// I2Cdev::writeByte(devAddr, L3GD20H_RA_REFERENCE, reference); +// } + +// uint8_t L3GD20H::getInterruptReference() { +// I2Cdev::readByte(devAddr, L3GD20H_RA_REFERENCE, buffer); +// return buffer[0]; +// } + +// OUT_TEMP register, read-only + +/** Gets the current temperature reading from the sensor + * @return Current temperature + * @see L3GD20H_RA_OUT_TEMP + */ +uint8_t L3GD20H::getTemperature() { + I2Cdev::readByte(devAddr, L3GD20H_RA_OUT_TEMP, buffer); + return buffer[0]; +} + +// STATUS register, read-only + +/** Get whether new data overwrote the last set of data before it was read + * @return True if the last set of data was overwritten before being read, false + * otherwise + * @see L3GD20H_RA_STATUS + * @see L3GD20H_ZYXOR_BIT + */ +bool L3GD20H::getXYZOverrun() { + I2Cdev::readBit(devAddr, L3GD20H_RA_STATUS, L3GD20H_ZYXOR_BIT, + buffer); + return buffer[0]; +} + +/** Get whether new Z data overwrote the last set of data before it was read + * @return True if the last set of Z data was overwritten before being read, + * false otherwise + * @see L3GD20H_RA_STATUS + * @see L3GD20H_ZOR_BIT + */ +bool L3GD20H::getZOverrun() { + I2Cdev::readBit(devAddr, L3GD20H_RA_STATUS, L3GD20H_ZOR_BIT, + buffer); + return buffer[0]; +} + +/** Get whether new Y data overwrote the last set of data before it was read + * @return True if the last set of Y data was overwritten before being read, + * false otherwise + * @see L3GD20H_RA_STATUS + * @see L3GD20H_YOR_BIT + */ +bool L3GD20H::getYOverrun() { + I2Cdev::readBit(devAddr, L3GD20H_RA_STATUS, L3GD20H_YOR_BIT, + buffer); + return buffer[0]; +} + +/** Get whether new X data overwrote the last set of data before it was read + * @return True if the last set of X data was overwritten before being read, + * false otherwise + * @see L3GD20H_RA_STATUS + * @see L3GD20H_XOR_BIT + */ +bool L3GD20H::getXOverrun() { + I2Cdev::readBit(devAddr, L3GD20H_RA_STATUS, L3GD20H_XOR_BIT, + buffer); + return buffer[0]; +} + +/** Get whether there is new data avaialable + * @return True if there is new data available, false otherwise + * @see L3GD20H_RA_STATUS + * @see L3GD20H_ZYXDA_BIT + */ +bool L3GD20H::getXYZDataAvailable() { + I2Cdev::readBit(devAddr, L3GD20H_RA_STATUS, L3GD20H_ZYXDA_BIT, + buffer); + return buffer[0]; +} + +/** Get whether there is new Z data avaialable + * @return True if there is new Z data available, false otherwise + * @see L3GD20H_RA_STATUS + * @see L3GD20H_ZDA_BIT + */ +bool L3GD20H::getZDataAvailable() { + I2Cdev::readBit(devAddr, L3GD20H_RA_STATUS, L3GD20H_ZDA_BIT, + buffer); + return buffer[0]; +} + +/** Get whether there is new Y data avaialable + * @return True if there is new Y data available, false otherwise + * @see L3GD20H_RA_STATUS + * @see L3GD20H_YDA_BIT + */ +bool L3GD20H::getYDataAvailable() { + I2Cdev::readBit(devAddr, L3GD20H_RA_STATUS, L3GD20H_YDA_BIT, + buffer); + return buffer[0]; +} + +/** Get whether there is new X data avaialable + * @return True if there is new X data available, false otherwise + * @see L3GD20H_RA_STATUS + * @see L3GD20H_XDA_BIT + */ +bool L3GD20H::getXDataAvailable() { + I2Cdev::readBit(devAddr, L3GD20H_RA_STATUS, L3GD20H_XDA_BIT, + buffer); + return buffer[0]; +} + +// OUT_* registers, read-only + +/** Get the angular velocity for all 3 axes + * Due to the fact that this device supports two difference Endian modes, both + * must be accounted for when reading data. In Little Endian mode, the first + * byte (lowest address) is the least significant and in Big Endian mode the + * first byte is the most significant. + * @param x 16-bit integer container for the X-axis angular velocity + * @param y 16-bit integer container for the Y-axis angular velocity + * @param z 16-bit integer container for the Z-axis angular velocity + */ +void L3GD20H::getAngularVelocity(int16_t* x, int16_t* y, int16_t* z) { + I2Cdev::readBytes(devAddr, L3GD20H_RA_OUT_X_L | 0x80, 6, buffer); + if (endianMode == L3GD20H_LITTLE_ENDIAN) { + *x = (((int16_t)buffer[1]) << 8) | buffer[0]; + *y = (((int16_t)buffer[3]) << 8) | buffer[2]; + *z = (((int16_t)buffer[5]) << 8) | buffer[4]; + } else { + *x = (((int16_t)buffer[0]) << 8) | buffer[1]; + *y = (((int16_t)buffer[2]) << 8) | buffer[3]; + *z = (((int16_t)buffer[4]) << 8) | buffer[5]; + } +} + +/** Get the angular velocity about the X-axis + * @return Angular velocity about the X-axis + * @see L3GD20H_RA_OUT_X_L + * @see L3GD20H_RA_OUT_X_H + */ +int16_t L3GD20H::getAngularVelocityX() { + I2Cdev::readBytes(devAddr, L3GD20H_RA_OUT_X_L | 0x80, 2, buffer); + if (endianMode == L3GD20H_LITTLE_ENDIAN) { + return (((int16_t)buffer[1]) << 8) | buffer[0]; + } else { + return (((int16_t)buffer[0]) << 8) | buffer[1]; + } +} + +/** Get the angular velocity about the Y-axis + * @return Angular velocity about the Y-axis + * @see L3GD20H_RA_OUT_Y_L + * @see L3GD20H_RA_OUT_Y_H + */ +int16_t L3GD20H::getAngularVelocityY() { + I2Cdev::readBytes(devAddr, L3GD20H_RA_OUT_Y_L | 0x80, 2, buffer); + if (endianMode == L3GD20H_LITTLE_ENDIAN) { + return (((int16_t)buffer[1]) << 8) | buffer[0]; + } else { + return (((int16_t)buffer[0]) << 8) | buffer[1]; + } +} + +/** Get the angular velocity about the Z-axis + * @return Angular velocity about the Z-axis + * @see L3GD20H_RA_OUT_Z_L + * @see L3GD20H_RA_OUT_Z_H + */ +int16_t L3GD20H::getAngularVelocityZ() { + I2Cdev::readBytes(devAddr, L3GD20H_RA_OUT_Z_L | 0x80, 2, buffer); + if (endianMode == L3GD20H_LITTLE_ENDIAN) { + return (((int16_t)buffer[1]) << 8) | buffer[0]; + } else { + return (((int16_t)buffer[0]) << 8) | buffer[1]; + } +} + +// FIFO_CTRL register, r/w + +/** Set the FIFO mode to one of the defined modes + * @param mode New FIFO mode + * @see L3GD20H_RA_FIFO_CTRL + * @see L3GD20H_FIFO_MODE_BIT + * @see L3GD20H_FIFO_MODE_LENGTH + * @see L3GD20H_FM_BYPASS + * @see L3GD20H_FM_FIFO + * @see L3GD20H_FM_STREAM + * @see L3GD20H_FM_STREAM_FIFO + * @see L3GD20H_FM_BYPASS_STREAM + * @see L3GD20H_FM_DYNAMIC_STREAM + * @see L3GD20H_FM_BYPASS_FIFO + */ +void L3GD20H::setFIFOMode(uint8_t mode) { + I2Cdev::writeBits(devAddr, L3GD20H_RA_FIFO_CTRL, L3GD20H_FIFO_MODE_BIT, + L3GD20H_FIFO_MODE_LENGTH, mode); +} + +/** Get the FIFO mode to one of the defined modes + * @return Current FIFO mode + * @see L3GD20H_RA_FIFO_CTRL + * @see L3GD20H_FIFO_MODE_BIT + * @see L3GD20H_FIFO_MODE_LENGTH + * @see L3GD20H_FM_BYPASS + * @see L3GD20H_FM_FIFO + * @see L3GD20H_FM_STREAM + * @see L3GD20H_FM_STREAM_FIFO + * @see L3GD20H_FM_BYPASS_STREAM + * @see L3GD20H_FM_DYNAMIC_STREAM + * @see L3GD20H_FM_BYPASS_FIFO + */ +uint8_t L3GD20H::getFIFOMode() { + I2Cdev::readBits(devAddr, L3GD20H_RA_FIFO_CTRL, + L3GD20H_FIFO_MODE_BIT, L3GD20H_FIFO_MODE_LENGTH, buffer); + return buffer[0]; +} + +/** Set the 5-bit FIFO (watermark) threshold + * @param fth New 5-bit FIFO (watermark) threshold + * @see L3GD20H_RA_FIFO_CTRL + * @see L3GD20H_FIFO_TH_BIT + * @see L3GD20H_FIFO_TH_LENGTH + */ +void L3GD20H::setFIFOThreshold(uint8_t fth) { + I2Cdev::writeBits(devAddr, L3GD20H_RA_FIFO_CTRL, L3GD20H_FIFO_TH_BIT, + L3GD20H_FIFO_TH_LENGTH, fth); +} + +/** Get the FIFO watermark threshold + * @return FIFO watermark threshold + * @see L3GD20H_RA_FIFO_CTRL + * @see L3GD20H_FIFO_TH_BIT + * @see L3GD20H_FIFO_TH_LENGTH + */ +uint8_t L3GD20H::getFIFOThreshold() { + I2Cdev::readBits(devAddr, L3GD20H_RA_FIFO_CTRL, L3GD20H_FIFO_TH_BIT, + L3GD20H_FIFO_TH_LENGTH, buffer); + return buffer[0]; +} + +// FIFO_SRC register, read-only + +/** Get whether the number of data sets in the FIFO buffer is less than the + * watermark + * @return True if the number of data sets in the FIFO buffer is more than or + * equal to the watermark, false otherwise. + * @see L3GD20H_RA_FIFO_SRC + * @see L3GD20H_FIFO_TH_STATUS_BIT + */ +bool L3GD20H::getFIFOAtWatermark() { + I2Cdev::readBit(devAddr, L3GD20H_RA_FIFO_SRC, L3GD20H_FIFO_TH_STATUS_BIT, + buffer); + return buffer[0]; +} + +/** Get whether the FIFO buffer is full + * @return True if the FIFO buffer is full, false otherwise + * @see L3GD20H_RA_FIFO_SRC + * @see L3GD20H_FIFO_OVRN_BIT + */ +bool L3GD20H::getFIFOOverrun() { + I2Cdev::readBit(devAddr, L3GD20H_RA_FIFO_SRC, + L3GD20H_OVRN_BIT, buffer); + return buffer[0]; +} + +/** Get whether the FIFO buffer is empty + * @return True if the FIFO buffer is empty, false otherwise + * @see L3GD20H_RA_FIFO_SRC + * @see L3GD20H_FIFO_EMPTY_BIT + */ +bool L3GD20H::getFIFOEmpty() { + I2Cdev::readBit(devAddr, L3GD20H_RA_FIFO_SRC, + L3GD20H_EMPTY_BIT, buffer); + return buffer[0]; +} + +/** Get the number of filled FIFO buffer slots + * @return Number of filled slots in the FIFO buffer + * @see L3GD20H_RA_FIFO_SRC + * @see L3GD20H_FIFO_FSS_BIT + * @see L3GD20H_FIFO_FSS_LENGTH + */ +uint8_t L3GD20H::getFIFOStoredDataLevel() { + I2Cdev::readBits(devAddr, L3GD20H_RA_FIFO_SRC, + L3GD20H_FIFO_FSS_BIT, L3GD20H_FIFO_FSS_LENGTH, buffer); + return buffer[0]; +} + +// IG_CFG register, r/w + +/** Set the combination mode for interrupt events + * @param combination New combination mode for interrupt events. + * L3GD20H_AND_OR_OR for OR and L3GD20H_AND_OR_AND for AND + * @see L3GD20H_RA_IG_CFG + * @see L3GD20H_AND_OR_BIT + * @see L3GD20H_AND_OR_OR + * @see L3GD20H_AND_OR_AND + */ +void L3GD20H::setInterruptCombination(bool combination) { + I2Cdev::writeBit(devAddr, L3GD20H_RA_IG_CFG, L3GD20H_AND_OR_BIT, + combination); +} + +/** Get the combination mode for interrupt events + * @return Combination mode for interrupt events. L3GD20H_AND_OR_OR for OR and + * L3GD20H_AND_OR_AND for AND + * @see L3GD20H_RA_IG_CFG + * @see L3GD20H_AND_OR_BIT + * @see L3GD20H_AND_OR_OR + * @see L3GD20H_AND_OR_AND + */ +bool L3GD20H::getInterruptCombination() { + I2Cdev::readBit(devAddr, L3GD20H_RA_IG_CFG, L3GD20H_AND_OR_BIT, + buffer); + return buffer[0]; +} + +/** Set whether an interrupt request is latched + * This bit is cleared when the IG_SRC register is read + * @param latched New status of the latched request + * @see L3GD20H_RA_IG_CFG + * @see L3GD20H_LIR_BIT + */ +void L3GD20H::setInterruptRequestLatched(bool latched) { + I2Cdev::writeBit(devAddr, L3GD20H_RA_IG_CFG, L3GD20H_LIR_BIT, latched); +} + +/** Get whether an interrupt request is latched + * @return True if an interrupt request is latched, false otherwise + * @see L3GD20H_RA_IG_CFG + * @see L3GD20H_LIR_BIT + */ +bool L3GD20H::getInterruptRequestLatched() { + I2Cdev::readBit(devAddr, L3GD20H_RA_IG_CFG, L3GD20H_LIR_BIT, + buffer); + return buffer[0]; +}; + +/** Set whether the interrupt for Z high is enabled + * @param enabled New enabled state for Z high interrupt. + * @see L3GD20H_IG_CFG + * @see L3GD20H_ZHIE_BIT + */ +void L3GD20H::setZHighInterruptEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, L3GD20H_RA_IG_CFG, L3GD20H_ZHIE_BIT, enabled); +} + +/** Get whether the interrupt for Z high is enabled + * @return True if the interrupt for Z high is enabled, false otherwise + * @see L3GD20H_IG_CFG + * @see L3GD20H_ZHIE_BIT + */ +bool L3GD20H::getZHighInterruptEnabled() { + I2Cdev::readBit(devAddr, L3GD20H_RA_IG_CFG, L3GD20H_ZHIE_BIT, + buffer); + return buffer[0]; +} + +/** Set whether the interrupt for Z low is enabled + * @param enabled New enabled state for Z low interrupt. + * @see L3GD20H_IG_CFG + * @see L3GD20H_ZLIE_BIT + */ +void L3GD20H::setZLowInterruptEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, L3GD20H_RA_IG_CFG, L3GD20H_ZLIE_BIT, enabled); +} + +/** Get whether the interrupt for Z low is enabled + * @return True if the interrupt for Z low is enabled, false otherwise + * @see L3GD20H_IG_CFG + * @see L3GD20H_ZLIE_BIT + */ +bool L3GD20H::getZLowInterruptEnabled() { + I2Cdev::readBit(devAddr, L3GD20H_RA_IG_CFG, L3GD20H_ZLIE_BIT, + buffer); + return buffer[0]; +} + +/** Set whether the interrupt for Y high is enabled + * @param enabled New enabled state for Y high interrupt. + * @see L3GD20H_IG_CFG + * @see L3GD20H_YHIE_BIT + */ +void L3GD20H::setYHighInterruptEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, L3GD20H_RA_IG_CFG, L3GD20H_YHIE_BIT, enabled); +} + +/** Get whether the interrupt for Y high is enabled + * @return True if the interrupt for Y high is enabled, false otherwise + * @see L3GD20H_IG_CFG + * @see L3GD20H_YHIE_BIT + */ +bool L3GD20H::getYHighInterruptEnabled() { + I2Cdev::readBit(devAddr, L3GD20H_RA_IG_CFG, L3GD20H_YHIE_BIT, + buffer); + return buffer[0]; +} + +/** Set whether the interrupt for Y low is enabled + * @param enabled New enabled state for Y low interrupt. + * @see L3GD20H_IG_CFG + * @see L3GD20H_YLIE_BIT + */ +void L3GD20H::setYLowInterruptEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, L3GD20H_RA_IG_CFG, L3GD20H_YLIE_BIT, enabled); +} + +/** Get whether the interrupt for Y low is enabled + * @return True if the interrupt for Y low is enabled, false otherwise + * @see L3GD20H_IG_CFG + * @see L3GD20H_YLIE_BIT + */ +bool L3GD20H::getYLowInterruptEnabled() { + I2Cdev::readBit(devAddr, L3GD20H_RA_IG_CFG, L3GD20H_YLIE_BIT, + buffer); + return buffer[0]; +} + +/** Set whether the interrupt for X high is enabled + * @param enabled New enabled state for X high interrupt. + * @see L3GD20H_IG_CFG + * @see L3GD20H_XHIE_BIT + */ +void L3GD20H::setXHighInterruptEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, L3GD20H_RA_IG_CFG, L3GD20H_XHIE_BIT, enabled); +} + +/** Get whether the interrupt for X high is enabled + * @return True if the interrupt for X high is enabled, false otherwise + * @see L3GD20H_IG_CFG + * @see L3GD20H_XHIE_BIT + */ +bool L3GD20H::getXHighInterruptEnabled() { + I2Cdev::readBit(devAddr, L3GD20H_RA_IG_CFG, L3GD20H_XHIE_BIT, + buffer); + return buffer[0]; +} + +/** Set whether the interrupt for X low is enabled + * @param enabled New enabled state for X low interrupt. + * @see L3GD20H_IG_CFG + * @see L3GD20H_XLIE_BIT + */ +void L3GD20H::setXLowInterruptEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, L3GD20H_RA_IG_CFG, L3GD20H_XLIE_BIT, enabled); +} + +/** Get whether the interrupt for X low is enabled + * @return True if the interrupt for X low is enabled, false otherwise + * @see L3GD20H_IG_CFG + * @see L3GD20H_XLIE_BIT + */ +bool L3GD20H::getXLowInterruptEnabled() { + I2Cdev::readBit(devAddr, L3GD20H_RA_IG_CFG, L3GD20H_XLIE_BIT, + buffer); + return buffer[0]; +} + +// IG_SRC register, read-only + +/** Get whether an interrupt has been generated + * @return True if one or more interrupts has been generated, false otherwise + * @see L3GD20H_RA_IG_SRC + * @see L3GD20H_IA_BIT + */ +bool L3GD20H::getInterruptActive() { + I2Cdev::readBit(devAddr, L3GD20H_RA_IG_SRC, L3GD20H_IA_BIT, + buffer); + return buffer[0]; +} + +/** Get whether a Z high event has occurred + * @return True if a Z high event has occurred, false otherwise + * @see L3GD20H_RA_IG_SRC + * @see L3GD20H_ZH_BIT + */ +bool L3GD20H::getZHigh() { + I2Cdev::readBit(devAddr, L3GD20H_RA_IG_SRC, L3GD20H_ZH_BIT, + buffer); + return buffer[0]; +} + +/** Get whether a Z low event has occurred + * @return True if a Z low event has occurred, false otherwise + * @see L3GD20H_RA_IG_SRC + * @see L3GD20H_ZL_BIT + */ +bool L3GD20H::getZLow() { + I2Cdev::readBit(devAddr, L3GD20H_RA_IG_SRC, L3GD20H_ZL_BIT, + buffer); + return buffer[0]; +} + +/** Get whether a Y high event has occurred + * @return True if a Y high event has occurred, false otherwise + * @see L3GD20H_RA_IG_SRC + * @see L3GD20H_YH_BIT + */ +bool L3GD20H::getYHigh() { + I2Cdev::readBit(devAddr, L3GD20H_RA_IG_SRC, L3GD20H_YH_BIT, + buffer); + return buffer[0]; +} + +/** Get whether a Y low event has occurred + * @return True if a Y low event has occurred, false otherwise + * @see L3GD20H_RA_IG_SRC + * @see L3GD20H_YL_BIT + */ +bool L3GD20H::getYLow() { + I2Cdev::readBit(devAddr, L3GD20H_RA_IG_SRC, L3GD20H_YL_BIT, + buffer); + return buffer[0]; +} + +/** Get whether a X high event has occurred + * @return True if a X high event has occurred, false otherwise + * @see L3GD20H_RA_IG_SRC + * @see L3GD20H_XH_BIT + */ +bool L3GD20H::getXHigh() { + I2Cdev::readBit(devAddr, L3GD20H_RA_IG_SRC, L3GD20H_XH_BIT, + buffer); + return buffer[0]; +} + +/** Get whether a X low event has occurred + * @return True if a X low event has occurred, false otherwise + * @see L3GD20H_RA_IG_SRC + * @see L3GD20H_XL_BIT + */ +bool L3GD20H::getXLow() { + I2Cdev::readBit(devAddr, L3GD20H_RA_IG_SRC, L3GD20H_XL_BIT, + buffer); + return buffer[0]; +} + +// IG_THS_* registers, r/w + +/** Set the interrupt generation counter mode selection. + * @param enabled New enabled state for X low interrupt. + * @see L3GD20H_IG_THS_XH + * @see L3GD20H_DCRM_BIT + * @see L3GD20H_DCRM_RESET + * @see L3GD20H_DCRM_DEC + */ +void L3GD20H::setDecrementMode(bool mode) { + I2Cdev::writeBit(devAddr, L3GD20H_RA_IG_THS_XH, L3GD20H_DCRM_BIT, mode); +} + +/** Get the interrupt generation counter mode selection. + * @return Mode Interrupt generation counter mode + * @see L3GD20H_IG_THS_XH + * @see L3GD20H_DCRM_BIT + * @see L3GD20H_DCRM_RESET + * @see L3GD20H_DCRM_DEC + */ +bool L3GD20H::getDecrementMode() { + I2Cdev::readBit(devAddr, L3GD20H_RA_IG_THS_XH, L3GD20H_DCRM_BIT, + buffer); + return buffer[0]; +} + +/** Set the 7-bit threshold for a high interrupt on the X axis + * @param threshold New 7-bit threshold for a high interrupt on the X axis + * @see L3GD20H_IG_THS_XH + */ +void L3GD20H::setXHighThreshold(uint8_t threshold) { + I2Cdev::writeByte(devAddr, L3GD20H_RA_IG_THS_XH, threshold); +} + +/** Retrieve the threshold for a high interrupt on the X axis + * @return X high interrupt threshold + * @see L3GD20H_IG_THS_XH + */ +uint8_t L3GD20H::getXHighThreshold() { + I2Cdev::readByte(devAddr, L3GD20H_RA_IG_THS_XH, buffer); + return buffer[0]; +} + +/** Set the 8-bit threshold for a low interrupt on the X axis + * @param threshold New 8-bit threshold for a low interrupt on the X axis + * @see L3GD20H_IG_THS_XL + */ +void L3GD20H::setXLowThreshold(uint8_t threshold) { + I2Cdev::writeByte(devAddr, L3GD20H_RA_IG_THS_XL, threshold); +} + +/** Retrieve the threshold for a low interrupt on the X axis + * @return X low interrupt threshold + * @see L3GD20H_IG_THS_XL + */ +uint8_t L3GD20H::getXLowThreshold() { + I2Cdev::readByte(devAddr, L3GD20H_RA_IG_THS_XL, buffer); + return buffer[0]; +} + +/** Set the 7-bit threshold for a high interrupt on the Y axis + * @param threshold New 7-bit threshold for a high interrupt on the Y axis + * @see L3GD20H_IG_THS_YH + */ +void L3GD20H::setYHighThreshold(uint8_t threshold) { + I2Cdev::writeByte(devAddr, L3GD20H_RA_IG_THS_YH, threshold); +} + +/** Retrieve the threshold for a high interrupt on the Y axis + * @return Y high interrupt threshold + * @see L3GD20H_IG_THS_YH + */ +uint8_t L3GD20H::getYHighThreshold() { + I2Cdev::readByte(devAddr, L3GD20H_RA_IG_THS_YH, buffer); + return buffer[0]; +} + +/** Set the 8-bit threshold for a low interrupt on the Y axis + * @param threshold New 8-bit threshold for a low interrupt on the Y axis + * @see L3GD20H_IG_THS_YL + */ +void L3GD20H::setYLowThreshold(uint8_t threshold) { + I2Cdev::writeByte(devAddr, L3GD20H_RA_IG_THS_YL, threshold); +} + +/** Retrieve the threshold for a low interrupt on the Y axis + * @return Y low interrupt threshold + * @see L3GD20H_IG_THS_YL + */ +uint8_t L3GD20H::getYLowThreshold() { + I2Cdev::readByte(devAddr, L3GD20H_RA_IG_THS_YL, buffer); + return buffer[0]; +} + +/** Set the 7-bit threshold for a high interrupt on the Z axis + * @param threshold New 7-bit threshold for a high interrupt on the Z axis + * @see L3GD20H_IG_THS_ZH + */ +void L3GD20H::setZHighThreshold(uint8_t threshold) { + I2Cdev::writeByte(devAddr, L3GD20H_RA_IG_THS_ZH, threshold); +} + +/** Retrieve the threshold for a high interrupt on the Z axis + * @return Z high interrupt threshold + * @see L3GD20H_IG_THS_ZH + */ +uint8_t L3GD20H::getZHighThreshold() { + I2Cdev::readByte(devAddr, L3GD20H_RA_IG_THS_ZH, buffer); + return buffer[0]; +} + +/** Set the 8-bit threshold for a low interrupt on the Z axis + * @param threshold New 8-bit threshold for a low interrupt on the Z axis + * @see L3GD20H_RA_IG_THS_ZL + */ +void L3GD20H::setZLowThreshold(uint8_t threshold) { + I2Cdev::writeByte(devAddr, L3GD20H_RA_IG_THS_ZL, threshold); +} + +/** Retrieve the threshold for a low interrupt on the Z axis + * @return Z low interrupt threshold + * @see L3GD20H_IG_THS_ZL + */ +uint8_t L3GD20H::getZLowThreshold() { + I2Cdev::readByte(devAddr, L3GD20H_RA_IG_THS_ZL, buffer); + return buffer[0]; +} + +// IG_DURATION register, r/w + +/* Set the minimum duration for an interrupt event to be recognized + * This depends on the chosen output data rate + * @param duration New 7-bit duration value necessary for an interrupt event to be + * recognized + * @see L3GD20H_RA_IG_DURATION + * @see L3GD20H_DUR_BIT + * @see L3GD20H_DUR_LENGTH + */ +void L3GD20H::setDuration(uint8_t duration) { + I2Cdev::writeBits(devAddr, L3GD20H_RA_IG_DURATION, L3GD20H_DUR_BIT, + L3GD20H_DUR_LENGTH, duration); +} + +/** Get the minimum duration for an interrupt event to be recognized + * @return Duration value necessary for an interrupt event to be recognized + * @see L3GD20H_RA_IG_DURATION + * @see L3GD20H_DUR_BIT + * @see L3GD20H_DUR_LENGTH + */ +uint8_t L3GD20H::getDuration() { + I2Cdev::readBits(devAddr, L3GD20H_RA_IG_DURATION, + L3GD20H_DUR_BIT, L3GD20H_DUR_LENGTH, buffer); + return buffer[0]; +} + +/** Set whether the interrupt wait feature is enabled + * If false, the interrupt falls immediately if signal crosses the selected + * threshold. Otherwise, if signal crosses the selected threshold, the interrupt + * falls only after the duration has counted number of samples at the selected + * data rate, written into the duration counter register. + * @param enabled New enabled state of the interrupt wait + * @see L3GD20H_RA_IG_DURATION + * @see L3GD20H_WAIT_BIT + */ +void L3GD20H::setWaitEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, L3GD20H_RA_IG_DURATION, L3GD20H_WAIT_BIT, + enabled); +} + +/** Get whether the interrupt wait feature is enabled + * @return True if the wait feature is enabled, false otherwise + * @see L3GD20H_RA_IG_DURATION + * @see L3GD20H_WAIT_BIT + */ +bool L3GD20H::getWaitEnabled() { + I2Cdev::readBit(devAddr, L3GD20H_RA_IG_DURATION, + L3GD20H_WAIT_BIT, buffer); + return buffer[0]; +} + +// LOW_ODR register, r/w + +/** Set whether the DRDY/INT2 pin is active low. If enabled is true then the + * DRDY/INT2 pin will be active low. + * @param enabled New enabled DRDY/INT2 active low configuration + * @see L3GD20H_RA_LOW_ODR + * @see L3GD20H_DRDY_HL_BIT + */ +void L3GD20H::setINT2DataReadyActiveLowEnabled(bool enabled){ + I2Cdev::writeBit(devAddr, L3GD20H_RA_LOW_ODR, L3GD20H_DRDY_HL_BIT, + enabled); +} + +/** Get whether the DRDY/INT2 pin is active low. If true then the + * DRDY/INT2 pin IS active low. + * @see L3GD20H_RA_LOW_ODR + * @see L3GD20H_I2C_DIS_BIT + */ +bool L3GD20H::getINT2DataReadyActiveLowEnabled(){ + I2Cdev::readBit(devAddr, L3GD20H_RA_LOW_ODR, + L3GD20H_DRDY_HL_BIT, buffer); + return buffer[0]; +} + +/** Set whether only the SPI interface is enabled (i.e., I2C interface disabled) + * @param enabled New SPI interface only enabled + * @see L3GD20H_RA_LOW_ODR + * @see L3GD20H_I2C_DIS_BIT + */ +void L3GD20H::setSPIOnlyEnabled(bool enabled){ + I2Cdev::writeBit(devAddr, L3GD20H_RA_LOW_ODR, L3GD20H_I2C_DIS_BIT, + enabled); +} + +/** Get whether only the SPI interface is enabled (i.e., I2C interface disabled) + * @see L3GD20H_RA_LOW_ODR + * @see L3GD20H_I2C_DIS_BIT + */ +bool L3GD20H::getSPIOnlyEnabled(){ + I2Cdev::readBit(devAddr, L3GD20H_RA_LOW_ODR, + L3GD20H_I2C_DIS_BIT, buffer); + return buffer[0]; +} + +/** Reset the device. Sets a software reset flag which is auto cleared upon boot. + * @param reset Value that resets the device if true + * @see L3GD20H_RA_LOW_ODR + * @see L3GD20H_SW_RESET_BIT + */ +void L3GD20H::setSoftwareReset(bool reset){ + I2Cdev::writeBit(devAddr, L3GD20H_RA_LOW_ODR, L3GD20H_SW_RESET_BIT, + reset); +} + +/** Set whether the low output data rate is enabled. + * @param enabled New low output data rate enabled + * @see L3GD20H_RA_LOW_ODR + * @see L3GD20H_LOW_ODR_BIT + */ +void L3GD20H::setLowODREnabled(bool enabled){ + I2Cdev::writeBit(devAddr, L3GD20H_RA_LOW_ODR, L3GD20H_LOW_ODR_BIT, + enabled); +} + +/** Get whether the low output data rate is enabled. + * @see L3GD20H_RA_LOW_ODR + * @see L3GD20H_LOW_ODR_BIT + */ +bool L3GD20H::getLowODREnabled(){ + I2Cdev::readBit(devAddr, L3GD20H_RA_LOW_ODR, + L3GD20H_LOW_ODR_BIT, buffer); + return buffer[0]; +} diff --git a/Arduino/L3GD20H/L3GD20H.h b/Arduino/L3GD20H/L3GD20H.h new file mode 100644 index 00000000..587714bc --- /dev/null +++ b/Arduino/L3GD20H/L3GD20H.h @@ -0,0 +1,398 @@ +// I2Cdev library collection - L3GD20H I2C device class header file +// Based on STMicroelectronics L3GD20H datasheet rev. 2, 3/2013 +// X/XX/2015 by Nate Costello +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// 2015-XX-XX - initial release + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2011 Jonathan Arnett, Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#ifndef _L3GD20H_H_ +#define _L3GD20H_H_ + +#include "I2Cdev.h" + +#define L3GD20H_ADDRESS 0x6B // I think this is correct. See SAD in doc. +#define L3GD20H_DEFAULT_ADDRESS 0x6B // I think this is correct. See SAD in doc. + +#define L3GD20H_RA_WHO_AM_I 0x0F +#define L3GD20H_RA_CTRL1 0x20 +#define L3GD20H_RA_CTRL2 0x21 +#define L3GD20H_RA_CTRL3 0x22 +#define L3GD20H_RA_CTRL4 0x23 +#define L3GD20H_RA_CTRL5 0x24 +#define L3GD20H_RA_REFERENCE 0x25 +#define L3GD20H_RA_OUT_TEMP 0x26 +#define L3GD20H_RA_STATUS 0x27 +#define L3GD20H_RA_OUT_X_L 0x28 +#define L3GD20H_RA_OUT_X_H 0x29 +#define L3GD20H_RA_OUT_Y_L 0x2A +#define L3GD20H_RA_OUT_Y_H 0x2B +#define L3GD20H_RA_OUT_Z_L 0x2C +#define L3GD20H_RA_OUT_Z_H 0x2D +#define L3GD20H_RA_FIFO_CTRL 0x2E +#define L3GD20H_RA_FIFO_SRC 0x2F +#define L3GD20H_RA_IG_CFG 0x30 +#define L3GD20H_RA_IG_SRC 0x31 +#define L3GD20H_RA_IG_THS_XH 0x32 +#define L3GD20H_RA_IG_THS_XL 0X33 +#define L3GD20H_RA_IG_THS_YH 0X34 +#define L3GD20H_RA_IG_THS_YL 0x35 +#define L3GD20H_RA_IG_THS_ZH 0X36 +#define L3GD20H_RA_IG_THS_ZL 0x37 +#define L3GD20H_RA_IG_DURATION 0X38 +#define L3GD20H_RA_LOW_ODR 0x39 + +#define L3GD20H_ODR_BIT 7 +#define L3GD20H_ODR_LENGTH 2 +#define L3GD20H_BW_BIT 5 +#define L3GD20H_BW_LENGTH 2 +#define L3GD20H_PD_BIT 3 +#define L3GD20H_ZEN_BIT 2 +#define L3GD20H_YEN_BIT 1 +#define L3GD20H_XEN_BIT 0 + +#define L3GD20H_RATE_100_12 0b00 //selection of high vs low rate is via Low_ODR +#define L3GD20H_RATE_200_25 0b01 //selection of high vs low rate is via Low_ODR +#define L3GD20H_RATE_400_50 0b10 //selection of high vs low rate is via Low_ODR +#define L3GD20H_RATE_800_50 0b11 //selection of high vs low rate is via Low_ODR + +#define L3GD20H_BW_LOW 0b00 +#define L3GD20H_BW_MED_LOW 0b01 +#define L3GD20H_BW_MED_HIGH 0b10 +#define L3GD20H_BW_HIGH 0b11 + +#define L3GD20H_HPM_BIT 5 +#define L3GD20H_HPM_LENGTH 2 +#define L3GD20H_HPCF_BIT 3 +#define L3GD20H_HPCF_LENGTH 4 + +#define L3GD20H_HPM_HRF 0b00 //this resets on reading REFERENCE +#define L3GD20H_HPM_REFERENCE 0b01 +#define L3GD20H_HPM_NORMAL 0b10 +#define L3GD20H_HPM_AUTORESET 0b11 + +#define L3GD20H_HPCF1 0b0000 +#define L3GD20H_HPCF2 0b0001 +#define L3GD20H_HPCF3 0b0010 +#define L3GD20H_HPCF4 0b0011 +#define L3GD20H_HPCF5 0b0100 +#define L3GD20H_HPCF6 0b0101 +#define L3GD20H_HPCF7 0b0110 +#define L3GD20H_HPCF8 0b0111 +#define L3GD20H_HPCF9 0b1000 +#define L3GD20H_HPCF10 0b1001 + +#define L3GD20H_INT1_IG_BIT 7 +#define L3GD20H_INT1_BOOT_BIT 6 +#define L3GD20H_H_LACTIVE_BIT 5 +#define L3GD20H_PP_OD_BIT 4 +#define L3GD20H_INT2_DRDY_BIT 3 +#define L3GD20H_INT2_FTH_BIT 2 +#define L3GD20H_INT2_ORUN_BIT 1 +#define L3GD20H_INT2_EMPTY_BIT 0 + +#define L3GD20H_PUSH_PULL 0 +#define L3GD20H_OPEN_DRAIN 1 + +#define L3GD20H_BDU_BIT 7 +#define L3GD20H_BLE_BIT 6 +#define L3GD20H_FS_BIT 5 +#define L3GD20H_FS_LENGTH 2 +#define L3GD20H_IMPEN_BIT 3 //new for this IC: Level sensitive latched enalble +#define L3GD20H_ST_BIT 2 +#define L3GD20H_ST_LENGTH 2 +#define L3GD20H_SIM_BIT 0 + +#define L3GD20H_BIG_ENDIAN 1 +#define L3GD20H_LITTLE_ENDIAN 0 + +#define L3GD20H_FS_250 0b00 +#define L3GD20H_FS_500 0b01 +#define L3GD20H_FS_2000 0b10 + +#define L3GD20H_SELF_TEST_NORMAL 0b00 +#define L3GD20H_SELF_TEST_0 0b01 +#define L3GD20H_SELF_TEST_1 0b11 + +#define L3GD20H_SPI_4_WIRE 0 +#define L3GD20H_SPI_3_WIRE 1 + +#define L3GD20H_BOOT_BIT 7 +#define L3GD20H_FIFO_EN_BIT 6 +#define L3GD20H_STOPONFTH_BIT 5 +#define L3GD20H_HPEN_BIT 4 +#define L3GD20H_IG_SEL_BIT 3 +#define L3GD20H_IG_SEL_LENGTH 2 +#define L3GD20H_OUT_SEL_BIT 1 +#define L3GD20H_OUT_SEL_LENGTH 2 + +#define L3GD20H_NON_HIGH_PASS 0b00 +#define L3GD20H_HIGH_PASS 0b01 +#define L3GD20H_LOW_PASS 0b10 //depends on HPEN +#define L3GD20H_LOW_HIGH_PASS 0b11 //depends on HPEN + +#define L3GD20H_ZYXOR_BIT 7 +#define L3GD20H_ZOR_BIT 6 +#define L3GD20H_YOR_BIT 5 +#define L3GD20H_XOR_BIT 4 +#define L3GD20H_ZYXDA_BIT 3 +#define L3GD20H_ZDA_BIT 2 +#define L3GD20H_YDA_BIT 1 +#define L3GD20H_XDA_BIT 0 + +#define L3GD20H_FIFO_MODE_BIT 7 +#define L3GD20H_FIFO_MODE_LENGTH 3 +#define L3GD20H_FIFO_TH_BIT 4 +#define L3GD20H_FIFO_TH_LENGTH 5 + +#define L3GD20H_FM_BYPASS 0b000 +#define L3GD20H_FM_FIFO 0b001 +#define L3GD20H_FM_STREAM 0b010 +#define L3GD20H_FM_STREAM_FIFO 0b011 +#define L3GD20H_FM_BYPASS_STREAM 0b100 +#define L3GD20H_FM_DYNAMIC_STREAM 0b110 +#define L3GD20H_FM_BYPASS_FIFO 0b111 + + +#define L3GD20H_FIFO_TH_STATUS_BIT 7 +#define L3GD20H_OVRN_BIT 6 +#define L3GD20H_EMPTY_BIT 5 +#define L3GD20H_FIFO_FSS_BIT 4 +#define L3GD20H_FIFO_FSS_LENGTH 5 + +#define L3GD20H_AND_OR_BIT 7 +#define L3GD20H_LIR_BIT 6 +#define L3GD20H_ZHIE_BIT 5 +#define L3GD20H_ZLIE_BIT 4 +#define L3GD20H_YHIE_BIT 3 +#define L3GD20H_YLIE_BIT 2 +#define L3GD20H_XHIE_BIT 1 +#define L3GD20H_XLIE_BIT 0 + +#define L3GD20H_AND_OR_OR 0 +#define L3GD20H_AND_OR_AND 1 + +#define L3GD20H_IA_BIT 6 +#define L3GD20H_ZH_BIT 5 +#define L3GD20H_ZL_BIT 4 +#define L3GD20H_YH_BIT 3 +#define L3GD20H_YL_BIT 2 +#define L3GD20H_XH_BIT 1 +#define L3GD20H_XL_BIT 0 + +#define L3GD20H_DCRM_BIT 7 + +#define L3GD20H_DCRM_RESET 0 +#define L3GD20H_DCRM_DEC 1 + +#define L3GD20H_WAIT_BIT 7 +#define L3GD20H_DUR_BIT 6 +#define L3GD20H_DUR_LENGTH 7 + +#define L3GD20H_LOW_ODR_BIT 0 +#define L3GD20H_SW_RESET_BIT 2 +#define L3GD20H_I2C_DIS_BIT 3 +#define L3GD20H_DRDY_HL_BIT 5 + + + +class L3GD20H { + public: + L3GD20H(); + L3GD20H(uint8_t address); + + void initialize(); + bool testConnection(); + + // WHO_AM_I register, read-only + uint8_t getDeviceID(); + + // CTRL1 register, r/w + void setOutputDataRate(uint16_t rate); + uint16_t getOutputDataRate(); + void setBandwidthCutOffMode(uint8_t mode); + uint8_t getBandwidthCutOffMode(); + // float getBandwidthCutOff(); + void setPowerOn(bool on); + bool getPowerOn(); + void setZEnabled(bool enabled); + bool getZEnabled(); + void setYEnabled(bool enabled); + bool getYEnabled(); + void setXEnabled(bool enabled); + bool getXEnabled(); + + // CTRL2 register, r/w + void setHighPassMode(uint8_t mode); + uint8_t getHighPassMode(); + void setHighPassFilterCutOffFrequencyLevel(uint8_t level); + uint8_t getHighPassFilterCutOffFrequencyLevel(); + + // CTRL3 register, r/w + void setINT1InterruptEnabled(bool enabled); + bool getINT1InterruptEnabled(); + void setINT1BootStatusEnabled(bool enabled); + bool getINT1BootStatusEnabled(); + void interruptActiveINT1Config(); + void setOutputMode(bool mode); + bool getOutputMode(); + void setINT2DataReadyEnabled(bool enabled); + bool getINT2DataReadyEnabled(); + void setINT2FIFOWatermarkInterruptEnabled(bool enabled); + bool getINT2FIFOWatermarkInterruptEnabled(); + void setINT2FIFOOverrunInterruptEnabled(bool enabled); + bool getINT2FIFOOverrunInterruptEnabled(); + void setINT2FIFOEmptyInterruptEnabled(bool enabled); + bool getINT2FIFOEmptyInterruptEnabled(); + + // CTRL4 register, r/w + void setBlockDataUpdateEnabled(bool enabled); + bool getBlockDataUpdateEnabled(); + void setEndianMode(bool endianness); + bool getEndianMode(); + void setFullScale(uint16_t scale); + uint16_t getFullScale(); + void setSelfTestMode(uint8_t mode); + uint8_t getSelfTestMode(); + void setSPIMode(bool mode); + bool getSPIMode(); + + // CTRL5 register, r/w + void rebootMemoryContent(); + void setFIFOEnabled(bool enabled); + bool getFIFOEnabled(); + void setStopOnFIFOThresholdEnabled(bool enabled); + bool getStopOnFIFOThresholdEnabled(); + void setHighPassFilterEnabled(bool enabled); + bool getHighPassFilterEnabled(); + void setDataFilter(uint8_t filter); + uint8_t getDataFilter(); + + // REFERENCE/DATACAPTURE register, r/w + void setHighPassFilterReference(uint8_t reference); + uint8_t getHighPassFilterReference(); + + // OUT_TEMP register, read-only + uint8_t getTemperature(); + + // STATUS register, read-only + bool getXYZOverrun(); + bool getZOverrun(); + bool getYOverrun(); + bool getXOverrun(); + bool getXYZDataAvailable(); + bool getZDataAvailable(); + bool getYDataAvailable(); + bool getXDataAvailable(); + + // OUT_* registers, read-only + void getAngularVelocity(int16_t* x, int16_t* y, int16_t* z); + int16_t getAngularVelocityX(); + int16_t getAngularVelocityY(); + int16_t getAngularVelocityZ(); + + // FIFO_CTRL register, r/w + void setFIFOMode(uint8_t mode); + uint8_t getFIFOMode(); + void setFIFOThreshold(uint8_t wtm); + uint8_t getFIFOThreshold(); + + // FIFO_SRC register, read-only + bool getFIFOAtWatermark(); + bool getFIFOOverrun(); + bool getFIFOEmpty(); + uint8_t getFIFOStoredDataLevel(); + + // IG_CFG register, r/w + void setInterruptCombination(bool combination); + bool getInterruptCombination(); + void setInterruptRequestLatched(bool latched); + bool getInterruptRequestLatched(); + void setZHighInterruptEnabled(bool enabled); + bool getZHighInterruptEnabled(); + void setYHighInterruptEnabled(bool enabled); + bool getYHighInterruptEnabled(); + void setXHighInterruptEnabled(bool enabled); + bool getXHighInterruptEnabled(); + void setZLowInterruptEnabled(bool enabled); + bool getZLowInterruptEnabled(); + void setYLowInterruptEnabled(bool enabled); + bool getYLowInterruptEnabled(); + void setXLowInterruptEnabled(bool enabled); + bool getXLowInterruptEnabled(); + + // IG_SRC register, read-only + bool getInterruptActive(); + bool getZHigh(); + bool getZLow(); + bool getYHigh(); + bool getYLow(); + bool getXHigh(); + bool getXLow(); + + // IG_THS_* registers, r/w + void setDecrementMode(bool mode); + bool getDecrementMode(); + void setXHighThreshold(uint8_t threshold); + uint8_t getXHighThreshold(); + void setXLowThreshold(uint8_t threshold); + uint8_t getXLowThreshold(); + void setYHighThreshold(uint8_t threshold); + uint8_t getYHighThreshold(); + void setYLowThreshold(uint8_t threshold); + uint8_t getYLowThreshold(); + void setZHighThreshold(uint8_t threshold); + uint8_t getZHighThreshold(); + void setZLowThreshold(uint8_t threshold); + uint8_t getZLowThreshold(); + + // IG_DURATION register, r/w + void setDuration(uint8_t duration); + uint8_t getDuration(); + void setWaitEnabled(bool enabled); + bool getWaitEnabled(); + + // LOW_ODR register, r/w + void setINT2DataReadyActiveLowEnabled(bool enabled); + bool getINT2DataReadyActiveLowEnabled(); + void setSPIOnlyEnabled(bool enabled); + bool getSPIOnlyEnabled(); + void setSoftwareReset(bool reset); + void setLowODREnabled(bool enabled); + bool getLowODREnabled(); + + + + + + private: + uint8_t devAddr; + uint8_t buffer[6]; + bool endianMode; +}; + +#endif /* _L3GD20H_H_ */ diff --git a/Arduino/L3GD20H/examples/L3GD20H_basic/L3GD20H_basic.ino b/Arduino/L3GD20H/examples/L3GD20H_basic/L3GD20H_basic.ino new file mode 100644 index 00000000..fa3d6f32 --- /dev/null +++ b/Arduino/L3GD20H/examples/L3GD20H_basic/L3GD20H_basic.ino @@ -0,0 +1,122 @@ +// I2C device class (I2Cdev) demonstration Arduino sketch for L3GD20H class +// X/XX/2015 by Nate Costello +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// 2015-XX-XX - initial release + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2011 Jonathan Arnett, Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation +// is used in I2Cdev.h +#include + +// I2Cdev and L3GD20H must be installed as libraries, or else the .cpp/.h files +// for both classes must be in the include path of your project +#include +#include + +// specific I2C address may be passed here +L3GD20H gyro; + +int16_t avx, avy, avz; + +#define LED_PIN 13 // (Arduino is 13, Teensy is 6) +bool blinkState = false; + +void setup() { + // join I2C bus (I2Cdev library doesn't do this automatically) + Wire.begin(); + + // initialize serial communication + Serial.begin(9600); + + // initialize device + Serial.println("Initializing I2C devices..."); + gyro.initialize(); + + // verify connection + Serial.println("Testing device connections..."); + Serial.println(gyro.testConnection() ? "L3GD20H connection successful" : "L3GD20H connection failed"); + + //test endian functions + gyro.setEndianMode(not gyro.getEndianMode()); + Serial.print("EndianMode: "); + Serial.print(gyro.getEndianMode()); + gyro.setEndianMode(not gyro.getEndianMode()); + Serial.print(" EndianMode: "); + Serial.println(gyro.getEndianMode()); + + + // configure LED for output + pinMode(LED_PIN, OUTPUT); + + // set scale to 250 + gyro.setFullScale(250); + +} + +void loop() { + // read raw angular velocity measurements from device + gyro.getAngularVelocity(&avx, &avy, &avz); + // int16_t x_single = gyro.getAngularVelocityX(); + // int16_t y_single = gyro.getAngularVelocityY(); + + // //read X memory address directly + // uint8_t xval_l, xval_h; + // uint8_t devAddress = 0x6B; + // uint8_t regAddXL = 0x28; + // uint8_t regAddXH = 0x29; + // I2Cdev::readByte(devAddress, regAddXL, &xval_l); + // I2Cdev::readByte(devAddress, regAddXH, &xval_h); + // //read X memory addresses in single sequential + // uint8_t data[2]; + // I2Cdev::readBytes(devAddress, regAddXL| 0x80, 2, data); + + + // Serial.print("Direct Mem Read: Xl: "); + // Serial.print(xval_l); Serial.print("\tXh: "); + // Serial.print(xval_h); Serial.print("\t"); + // Serial.print("Direct readBytes data[0] data[1]: "); + // Serial.print(data[0]); Serial.print("\t"); + // Serial.print(data[1]); Serial.print("\t"); + // Serial.print("Bitshifted: "); Serial.print((((int16_t)data[1]) << 8) | data[0]); + Serial.print("angular velocity (dps):\t"); + Serial.print(avx*0.00875F,DEC); Serial.print("\t"); + Serial.print(avy*0.00875F,DEC); Serial.print("\t"); + Serial.print(avz*0.00875F,DEC); Serial.print("\t"); + // Serial.print(" x read only: "); Serial.print(x_single); + // Serial.print(" y read only: "); Serial.println(y_single); + Serial.println(); + + // blink LED to indicate activity + blinkState = !blinkState; + digitalWrite(LED_PIN, blinkState); + + + +} + + From 39e9f5cb287f05f26aac86a7e5ad097a751b7e55 Mon Sep 17 00:00:00 2001 From: Nate Costello Date: Thu, 5 Mar 2015 12:54:55 -0500 Subject: [PATCH 060/335] Filled in the release dates in the headers for each file. --- Arduino/L3GD20H/L3GD20H.cpp | 4 ++-- Arduino/L3GD20H/L3GD20H.h | 4 ++-- Arduino/L3GD20H/examples/L3GD20H_basic/L3GD20H_basic.ino | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Arduino/L3GD20H/L3GD20H.cpp b/Arduino/L3GD20H/L3GD20H.cpp index 62200f52..bd5d8887 100644 --- a/Arduino/L3GD20H/L3GD20H.cpp +++ b/Arduino/L3GD20H/L3GD20H.cpp @@ -1,10 +1,10 @@ // I2Cdev library collection - L3GD20H I2C device class // Based on STMicroelectronics L3GD20H datasheet rev. 2, 3/2013 -// X/XX/2015 by Nate Costello +// 3/05/2015 by Nate Costello // Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib // // Changelog: -// 2015-XX-XX - initial release +// 2015-03-05 - initial release /* ============================================ I2Cdev device library code is placed under the MIT license diff --git a/Arduino/L3GD20H/L3GD20H.h b/Arduino/L3GD20H/L3GD20H.h index 587714bc..329890e2 100644 --- a/Arduino/L3GD20H/L3GD20H.h +++ b/Arduino/L3GD20H/L3GD20H.h @@ -1,10 +1,10 @@ // I2Cdev library collection - L3GD20H I2C device class header file // Based on STMicroelectronics L3GD20H datasheet rev. 2, 3/2013 -// X/XX/2015 by Nate Costello +// 3/05/2015 by Nate Costello // Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib // // Changelog: -// 2015-XX-XX - initial release +// 2015-03-05 - initial release /* ============================================ I2Cdev device library code is placed under the MIT license diff --git a/Arduino/L3GD20H/examples/L3GD20H_basic/L3GD20H_basic.ino b/Arduino/L3GD20H/examples/L3GD20H_basic/L3GD20H_basic.ino index fa3d6f32..82953495 100644 --- a/Arduino/L3GD20H/examples/L3GD20H_basic/L3GD20H_basic.ino +++ b/Arduino/L3GD20H/examples/L3GD20H_basic/L3GD20H_basic.ino @@ -1,9 +1,9 @@ // I2C device class (I2Cdev) demonstration Arduino sketch for L3GD20H class -// X/XX/2015 by Nate Costello +// 3/05/2015 by Nate Costello // Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib // // Changelog: -// 2015-XX-XX - initial release +// 2015-03-05 - initial release /* ============================================ I2Cdev device library code is placed under the MIT license From 00437ecfb448fbbb56f5b18fa5d2cd5d6ca06492 Mon Sep 17 00:00:00 2001 From: Nate Costello Date: Thu, 5 Mar 2015 22:00:25 -0500 Subject: [PATCH 061/335] Completed and tested an Arduino driver for the LSM303DLHC accel and magnetometer. Filled in release dates. Comment Cleanup. --- Arduino/LSM303DLHC/LSM303DLHC.cpp | 2149 +++++++++++++++++ Arduino/LSM303DLHC/LSM303DLHC.h | 658 +++++ .../LSM303DLHC_test/LSM303DLHC_test.ino | 148 ++ 3 files changed, 2955 insertions(+) create mode 100644 Arduino/LSM303DLHC/LSM303DLHC.cpp create mode 100644 Arduino/LSM303DLHC/LSM303DLHC.h create mode 100644 Arduino/LSM303DLHC/examples/LSM303DLHC_test/LSM303DLHC_test.ino diff --git a/Arduino/LSM303DLHC/LSM303DLHC.cpp b/Arduino/LSM303DLHC/LSM303DLHC.cpp new file mode 100644 index 00000000..26e121c4 --- /dev/null +++ b/Arduino/LSM303DLHC/LSM303DLHC.cpp @@ -0,0 +1,2149 @@ +// I2Cdev library collection - LSM303DLHC I2C device class +// Based on ST LSM303DLHC datasheet, REV 2, 11/2013 +// [current release date] by Nate Costello +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// 2015-03-10 - initial release + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2011 [Author Name], Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#include "LSM303DLHC.h" + +/** Default constructor, uses default I2C address. + * @see LSM303DLHC_DEFAULT_ADDRESS_A + * @see LSM303DLHC_DEFAULT_ADDRESS_M + */ +LSM303DLHC::LSM303DLHC() { + devAddrA = LSM303DLHC_DEFAULT_ADDRESS_A; + devAddrM = LSM303DLHC_DEFAULT_ADDRESS_M; + endianMode = 0; +} + +/** Specific address constructor. +@param addressA I2C accelerometer address +@param addressM I2C magnetometer address +@see LSM303DLHC_DEFAULT_ADDRESS_A +@see LSM303DLHC_DEFAULT_ADDRESS_M +@see LSM303DLHC_ADDRESS_A +@see LSM303DLHC_ADDRESS_M + */ +LSM303DLHC::LSM303DLHC(uint8_t addressA, uint8_t addressM) { + devAddrA = addressA; + devAddrM = addressM; + endianMode = 0; +} + +/** Power on and prepare for general usage. +All values are defaults except for the data rates for the accelerometer and +magnetometer data rates (200hz and 220hz respectively). +@see LSM303DLHC_RA_CTRL_REG1_A +@see LSM303DLHC_RA_CRA_REG_M +*/ +void LSM303DLHC::initialize() { + I2Cdev::writeByte(devAddrA, LSM303DLHC_RA_CTRL_REG1_A, 0b01100111); + I2Cdev::writeByte(devAddrM, LSM303DLHC_RA_CRA_REG_M, 0b00011100); + // ---------------------------------------------------------------------------- + // STUB TODO: + // Perform any important initialization here. Maybe nothing is required, but + // the method should exist anyway. + // ---------------------------------------------------------------------------- +} + +/** Verify the I2C connection. +Make sure the device is connected and responds as expected. This device has no +device ID or WHO_AM_I register. To test the connection, bits are written to control +register, checked, and then the original contents are written back. + * @return True if connection is valid, false otherwise + */ +bool LSM303DLHC::testConnection() { + I2Cdev::readByte(devAddrA, LSM303DLHC_RA_CTRL_REG1_A, buffer); + uint8_t origValA = buffer[0]; + I2Cdev::readByte(devAddrM, LSM303DLHC_RA_CRA_REG_M, buffer); + uint8_t origValM = buffer[0]; + + uint8_t zeros = 0b00000000; + I2Cdev::writeByte(devAddrA, LSM303DLHC_RA_CTRL_REG1_A, zeros); + I2Cdev::writeByte(devAddrM, LSM303DLHC_RA_CRA_REG_M, zeros); + + I2Cdev::readByte(devAddrA, LSM303DLHC_RA_CTRL_REG1_A, buffer); + uint8_t newValA = buffer[0]; + I2Cdev::readByte(devAddrM, LSM303DLHC_RA_CRA_REG_M, buffer); + uint8_t newValM = buffer[0]; + + I2Cdev::writeByte(devAddrA, LSM303DLHC_RA_CTRL_REG1_A, origValA); + I2Cdev::writeByte(devAddrM, LSM303DLHC_RA_CRA_REG_M, origValM); + + if ((newValM == zeros) and (newValA == zeros)) { + return true; + } + return false; +} + +// ---------------------------------------------------------------------------- +// STUB TODO: +// Define methods to fully cover all available functionality provided by the +// device, according to the datasheet and/or register map. Unless there is very +// clear reason not to, try to follow the get/set naming convention for all +// values, for instance: +// - uint8_t getThreshold() +// - void setThreshold(uint8_t threshold) +// - uint8_t getRate() +// - void setRate(uint8_t rate) +// +// Some methods may be named differently if it makes sense. As long as all +// functionality is covered, that's the important part. The methods here are +// only examples and should not be kept for your real device. +// ---------------------------------------------------------------------------- + +//CTRL_REG1_A, r/w + +/** Set the output data rate + * @param rate The new data output rate (can be 1, 10, 25, 50, 100, 200, 400, 1620, 1344, or 5376) + * @see LSM303DLHC_RA_CTRL_REG1_A + * @see LSM303DLHC_ODR_BIT + * @see LSM303DLHC_ODR_LENGTH + * @see LSM303DLHC_RATE_1 + * @see LSM303DLHC_RATE_10 + * @see LSM303DLHC_RATE_25 + * @see LSM303DLHC_RATE_50 + * @see LSM303DLHC_RATE_100 + * @see LSM303DLHC_RATE_200 + * @see LSM303DLHC_RATE_400 + * @see LSM303DLHC_RATE_1620_LP + * @see LSM303DLHC_RATE_1344_N_5376_LP + */ +void LSM303DLHC::setAccelOutputDataRate(uint16_t rate) { + uint8_t writeVal; + + if (rate == 0) { + writeVal = LSM303DLHC_ODR_RATE_POWERDOWN; + } else if (rate == 1) { + writeVal = LSM303DLHC_ODR_RATE_1; + } else if (rate == 10) { + writeVal = LSM303DLHC_ODR_RATE_10; + } else if (rate == 25) { + writeVal = LSM303DLHC_ODR_RATE_25; + } else if (rate == 50) { + writeVal = LSM303DLHC_ODR_RATE_50; + } else if (rate == 100) { + writeVal = LSM303DLHC_ODR_RATE_100; + } else if (rate == 200) { + writeVal = LSM303DLHC_ODR_RATE_200; + } else if (rate == 400) { + writeVal = LSM303DLHC_ODR_RATE_400; + } else if (rate == 1620) { + writeVal = LSM303DLHC_ODR_RATE_1620_LP; + } else if (rate == 1344) { + writeVal = LSM303DLHC_ODR_RATE_1344_N_5376_LP; + } else if (rate == 5376) { + writeVal = LSM303DLHC_ODR_RATE_1344_N_5376_LP; + } + + I2Cdev::writeBits(devAddrA, LSM303DLHC_RA_CTRL_REG1_A, LSM303DLHC_ODR_BIT, + LSM303DLHC_ODR_LENGTH, writeVal); +} + +/** Get the output data rate + * @return The current data output rate (can be 1, 10, 25, 50, 100, 200, 400, 1620, or 1344 (implies 5376)) + * @see LSM303DLHC_RA_CTRL_REG1_A + * @see LSM303DLHC_ODR_BIT + * @see LSM303DLHC_ODR_LENGTH + * @see LSM303DLHC_RATE_1 + * @see LSM303DLHC_RATE_10 + * @see LSM303DLHC_RATE_25 + * @see LSM303DLHC_RATE_50 + * @see LSM303DLHC_RATE_100 + * @see LSM303DLHC_RATE_200 + * @see LSM303DLHC_RATE_400 + * @see LSM303DLHC_RATE_1620_LP + * @see LSM303DLHC_RATE_1344_N_5376_LP + */ +uint16_t LSM303DLHC::getAccelOutputDataRate() { + I2Cdev::readBits(devAddrA, LSM303DLHC_RA_CTRL_REG1_A, LSM303DLHC_ODR_BIT, + LSM303DLHC_ODR_LENGTH, buffer); + uint8_t rate = buffer[0]; + + if (rate == LSM303DLHC_ODR_RATE_POWERDOWN) { + return 0; + } else if (rate == LSM303DLHC_ODR_RATE_1) { + return 1; + } else if (rate == LSM303DLHC_ODR_RATE_10) { + return 10; + } else if (rate == LSM303DLHC_ODR_RATE_25) { + return 25; + } else if (rate == LSM303DLHC_ODR_RATE_50) { + return 50; + } else if (rate == LSM303DLHC_ODR_RATE_100) { + return 100; + } else if (rate == LSM303DLHC_ODR_RATE_200) { + return 200; + } else if (rate == LSM303DLHC_ODR_RATE_400) { + return 400; + } else if (rate == LSM303DLHC_ODR_RATE_1620_LP) { + return 1620; + } else if (rate == LSM303DLHC_ODR_RATE_1344_N_5376_LP) { + return 1344; + } else if (rate == LSM303DLHC_ODR_RATE_1344_N_5376_LP) { + return 5376; + } +} + +/*Enables or disables the accelerometer low power mode +@param enabled The new enabled state of the low power mode +@see LSM303DLHC_RA_CTRL_REG1_A +@see LSM303DLHC_LPEN_BIT +*/ +void LSM303DLHC::setAccelLowPowerEnabled(bool enabled){ + I2Cdev::writeBit(devAddrA, LSM303DLHC_RA_CTRL_REG1_A, LSM303DLHC_LPEN_BIT, enabled); +} + +/*Get whether the accelerometer low power mode is enabled +@return True if the acceleromer low power mode is enabled +@see LSM303DLHC_RA_CTRL_REG1_A +@see LSM303DLHC_LPEN_BIT +*/ +bool LSM303DLHC::getAccelLowPowerEnabled(){ + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_CTRL_REG1_A, LSM303DLHC_LPEN_BIT, buffer); + return buffer[0]; +} + +/** Enables or disables the ability to get Z data + * @param enabled The new enabled state of the Z axis + * @see LSM303DLHC_RA_CTRL_REG1_A + * @see LSM303DLHC_ZEN_BIT + */ +void LSM303DLHC::setAccelZEnabled(bool enabled) { + I2Cdev::writeBit(devAddrA, LSM303DLHC_RA_CTRL_REG1_A, LSM303DLHC_ZEN_BIT, enabled); +} + +/** Get whether Z axis data is enabled + * @return True if the Z axis is enabled, false otherwise + * @see LSM303DLHC_RA_CTRL_REG1_A + * @see LSM303DLHC_ZEN_BIT + */ +bool LSM303DLHC::getAccelZEnabled() { + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_CTRL_REG1_A, LSM303DLHC_ZEN_BIT, buffer); + return buffer[0]; +} + +/** Enables or disables the ability to get Y data + * @param enabled The new enabled state of the Y axis + * @see LSM303DLHC_RA_CTRL_REG1_A + * @see LSM303DLHC_YEN_BIT + */ +void LSM303DLHC::setAccelYEnabled(bool enabled) { + I2Cdev::writeBit(devAddrA, LSM303DLHC_RA_CTRL_REG1_A, LSM303DLHC_YEN_BIT, enabled); +} + +/** Get whether Y axis data is enabled + * @return True if the Y axis is enabled, false otherwise + * @see LSM303DLHC_RA_CTRL_REG1_A + * @see LSM303DLHC_YEN_BIT + */ +bool LSM303DLHC::getAccelYEnabled() { + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_CTRL_REG1_A, LSM303DLHC_YEN_BIT, buffer); + return buffer[0]; +} + +/** Enables or disables the ability to get X data + * @param enabled The new enabled state of the X axis + * @see LSM303DLHC_RA_CTRL_REG1_A + * @see LSM303DLHC_XEN_BIT + */ +void LSM303DLHC::setAccelXEnabled(bool enabled) { + I2Cdev::writeBit(devAddrA, LSM303DLHC_RA_CTRL_REG1_A, LSM303DLHC_XEN_BIT, enabled); +} + +/** Get whether X axis data is enabled + * @return True if the X axis is enabled, false otherwise + * @see LSM303DLHC_RA_CTRL_REG1_A + * @see LSM303DLHC_XEN_BIT + */ +bool LSM303DLHC::getAccelXEnabled() { + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_CTRL_REG1_A, LSM303DLHC_XEN_BIT, buffer); + return buffer[0]; +} + +//CTRL_REG2_A r/w + +/** Set the high pass mode + * @param mode The new high pass mode + * @see LSM303DLHC_RA_CTRL_REG2 + * @see LSM303DLHC_HPM_BIT + * @see LSM303DLHC_HPM_LENGTH + * @see LSM303DLHC_HPM_HRF + * @see LSM303DLHC_HPM_REFERENCE + * @see LSM303DLHC_HPM_NORMAL + * @see LSM303DLHC_HPM_AUTORESET + */ +void LSM303DLHC::setAccelHighPassMode(uint8_t mode) { + I2Cdev::writeBits(devAddrA, LSM303DLHC_RA_CTRL_REG2_A, LSM303DLHC_HPM_BIT, + LSM303DLHC_HPM_LENGTH, mode); +} + +/** Get the high pass mode + * @return High pass mode + * @see LSM303DLHC_RA_CTRL_REG2_A + * @see LSM303DLHC_HPM_BIT + * @see LSM303DLHC_HPM_LENGTH + * @see LSM303DLHC_HPM_HRF + * @see LSM303DLHC_HPM_REFERENCE + * @see LSM303DLHC_HPM_NORMAL + * @see LSM303DLHC_HPM_AUTORESET + */ +uint8_t LSM303DLHC::getAccelHighPassMode() { + I2Cdev::readBits(devAddrA, LSM303DLHC_RA_CTRL_REG2_A, LSM303DLHC_HPM_BIT, + LSM303DLHC_HPM_LENGTH, buffer); + return buffer[0]; +} + +/** Set the high pass filter cut off frequency level (1 - 10) + * @param level The new level for the hpcf, using one of the defined levels + * @see LSM303DLHC_RA_CTRL_REG2_A + * @see LSM303DLHC_HPCF_BIT + * @see LSM303DLHC_HPCF_LENGTH + * @see LSM303DLHC_HPCF1 + * @see LSM303DLHC_HPCF2 + * @see LSM303DLHC_HPCF3 + * @see LSM303DLHC_HPCF4 + */ +void LSM303DLHC::setAccelHighPassFilterCutOffFrequencyLevel(uint8_t level) { + I2Cdev::writeBits(devAddrA, LSM303DLHC_RA_CTRL_REG2_A, LSM303DLHC_HPCF_BIT, + LSM303DLHC_HPCF_LENGTH, level); +} + +/** Get the high pass filter cut off frequency level (1 - 10) + * @return High pass filter cut off frequency level + * @see LSM303DLHC_RA_CTRL_REG2_A + * @see LSM303DLHC_HPCF_BIT + * @see LSM303DLHC_HPCF_LENGTH + * @see LSM303DLHC_HPCF1 + * @see LSM303DLHC_HPCF2 + * @see LSM303DLHC_HPCF3 + * @see LSM303DLHC_HPCF4 + */ +uint8_t LSM303DLHC::getAccelHighPassFilterCutOffFrequencyLevel() { + I2Cdev::readBits(devAddrA, LSM303DLHC_RA_CTRL_REG2_A, LSM303DLHC_HPCF_BIT, + LSM303DLHC_HPCF_LENGTH, buffer); + return buffer[0]; +} + +//CTRL_REG3_A r/w + +/*Enable the Click interrupt routed to the INT1 pin. +@param enabled The new enabled state of the Click interrupt routed to the INT1 pin +@see LSM303DLHC_RA_CTRL_REG3_A +@see LSM303DLHC_I1_CLICK_BIT +*/ +void LSM303DLHC::setAccelINT1ClickEnabled(bool enabled){ + I2Cdev::writeBit(devAddrA, LSM303DLHC_RA_CTRL_REG3_A, LSM303DLHC_I1_CLICK_BIT, enabled); +} + +/*Get whether the Click interrupt is routed to the INT1 pin. +@return True if the Click interrupt is routed to the INT1 pin +@see LSM303DLHC_RA_CTRL_REG3_A +@see LSM303DLHC_I1_CLICK_BIT +*/ +bool LSM303DLHC::getAccelINT1ClickEnabled(){ + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_CTRL_REG3_A, LSM303DLHC_I1_CLICK_BIT, buffer); + return buffer[0]; +} + +/*Enable the AOR1 interrupt routed to the INT1 pin. +@param enabled The new enabled state of the AOR1 interrupt routed to the INT1 pin +@see LSM303DLHC_RA_CTRL_REG3_A +@see LSM303DLHC_I1_AOI1_BIT +*/ +void LSM303DLHC::setAccelINT1AOI1Enabled(bool enabled){ + I2Cdev::writeBit(devAddrA, LSM303DLHC_RA_CTRL_REG3_A, LSM303DLHC_I1_AOI1_BIT, enabled); +} + +/*Get whether the AOR1 interrupt is routed to the INT1 pin. +@return True if the AOR1 interrupt is routed to the INT1 pin +@see LSM303DLHC_RA_CTRL_REG3_A +@see LSM303DLHC_I1_AOI1_BIT +*/ +bool LSM303DLHC::getAccelINT1AOI1Enabled(){ + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_CTRL_REG3_A, LSM303DLHC_I1_AOI1_BIT, buffer); + return buffer[0]; +} + +/*Enable the AOR2 interrupt routed to the INT1 pin. +@param enabled The new enabled state of the AOR2 interrupt routed to the INT1 pin +@see LSM303DLHC_RA_CTRL_REG3_A +@see LSM303DLHC_I1_AOI2_BIT +*/ +void LSM303DLHC::setAccelINT1AOI2Enabled(bool enabled){ + I2Cdev::writeBit(devAddrA, LSM303DLHC_RA_CTRL_REG3_A, LSM303DLHC_I1_AOI2_BIT, enabled); +} + +/*Get whether the AOR2 interrupt is routed to the INT1 pin. +@return True if the AOR2 interrupt is routed to the INT1 pin +@see LSM303DLHC_RA_CTRL_REG3_A +@see LSM303DLHC_I1_AOI2_BIT +*/ +bool LSM303DLHC::getAccelINT1AOI2Enabled(){ + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_CTRL_REG3_A, LSM303DLHC_I1_AOI2_BIT, buffer); + return buffer[0]; +} + +/*Enable the Data Ready 1 interrupt routed to the INT1 pin. +@param enabled The new enabled state of the Data Ready 1 interrupt routed to the INT1 pin +@see LSM303DLHC_RA_CTRL_REG3_A +@see LSM303DLHC_I1_DRDY1_BIT +*/ +void LSM303DLHC::setAccelINT1DataReady1Enabled(bool enabled){ + I2Cdev::writeBit(devAddrA, LSM303DLHC_RA_CTRL_REG3_A, LSM303DLHC_I1_DRDY1_BIT, enabled); +} + +/*Get whether the Data Ready 1 interrupt is routed to the INT1 pin. +@return True if the Data Ready 1 interrupt is routed to the INT1 pin +@see LSM303DLHC_RA_CTRL_REG3_A +@see LSM303DLHC_I1_DRDY1_BIT +*/ +bool LSM303DLHC::getAccelINT1DataReady1Enabled(){ + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_CTRL_REG3_A, LSM303DLHC_I1_DRDY1_BIT, buffer); + return buffer[0]; +} + +/*Enable the Data Ready 2 interrupt routed to the INT1 pin. +@param enabled The new enabled state of the Data Ready 2 interrupt routed to the INT1 pin +@see LSM303DLHC_RA_CTRL_REG3_A +@see LSM303DLHC_I1_DRDY2_BIT +*/ +void LSM303DLHC::setAccelINT1DataReady2Enabled(bool enabled){ + I2Cdev::writeBit(devAddrA, LSM303DLHC_RA_CTRL_REG3_A, LSM303DLHC_I1_DRDY2_BIT, enabled); +} + +/*Get whether the Data Ready 2 interrupt is routed to the INT1 pin. +@return True if the Data Ready 2 interrupt is routed to the INT1 pin +@see LSM303DLHC_RA_CTRL_REG3_A +@see LSM303DLHC_I1_DRDY2_BIT +*/ +bool LSM303DLHC::getAccelINT1DataReady2Enabled(){ + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_CTRL_REG3_A, LSM303DLHC_I1_DRDY2_BIT, buffer); + return buffer[0]; +} + +/*Enable the FIFO watermark interrupt routed to the INT1 pin. +@param enabled The new enabled state of the FIFO watermark interrupt routed to the INT1 pin +@see LSM303DLHC_RA_CTRL_REG3_A +@see LSM303DLHC_I1_WTM_BIT +*/ +void LSM303DLHC::setAccelINT1FIFOWatermarkEnabled(bool enabled){ + I2Cdev::writeBit(devAddrA, LSM303DLHC_RA_CTRL_REG3_A, LSM303DLHC_I1_WTM_BIT, enabled); +} + +/*Get whether the FIFO watermark interrupt is routed to the INT1 pin. +@return True if the FIFO watermark interrupt is routed to the INT1 pin +@see LSM303DLHC_RA_CTRL_REG3_A +@see LSM303DLHC_I1_WTM_BIT +*/ +bool LSM303DLHC::getAccelINT1FIFOWatermarkEnabled(){ + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_CTRL_REG3_A, LSM303DLHC_I1_WTM_BIT, buffer); + return buffer[0]; +} + +/*Enable the FIFO overrun interrupt routed to the INT1 pin. +@param enabled The new enabled state of the FIFO overrun interrupt routed to the INT1 pin +@see LSM303DLHC_RA_CTRL_REG3_A +@see LSM303DLHC_I1_OVERRUN_BIT +*/ +void LSM303DLHC::setAccelINT1FIFOOverunEnabled(bool enabled){ + I2Cdev::writeBit(devAddrA, LSM303DLHC_RA_CTRL_REG3_A, LSM303DLHC_I1_OVERRUN_BIT, enabled); +} + +/*Get whether the FIFO overrun interrupt is routed to the INT1 pin. +@return True if the FIFO overrun interrupt is routed to the INT1 pin +@see LSM303DLHC_RA_CTRL_REG3_A +@see LSM303DLHC_I1_OVERRUN_BIT +*/ +bool LSM303DLHC::getAccelINT1FIFOOverunEnabled(){ + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_CTRL_REG3_A, LSM303DLHC_I1_OVERRUN_BIT, buffer); + return buffer[0]; +} + +//CTRL_REG4_A r/w + +/** Set the Block Data Update (BDU) enabled state + * @param enabled New BDU enabled state + * @see LSM303DLHC_RA_CTRL_REG4_A + * @see LSM303DLHC_BDU_BIT + */ +void LSM303DLHC::setAccelBlockDataUpdateEnabled(bool enabled) { + I2Cdev::writeBit(devAddrA, LSM303DLHC_RA_CTRL_REG4_A, LSM303DLHC_BDU_BIT, enabled); +} + +/** Get the BDU enabled state + * @return True if Block Data Update is enabled, false otherwise + * @see LSM303DLHC_RA_CTRL_REG4_A + * @see LSM303DLHC_BDU_BIT + */ +bool LSM303DLHC::getAccelBlockDataUpdateEnabled() { + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_CTRL_REG4_A, LSM303DLHC_BDU_BIT, buffer); + return buffer[0]; +} + +/** Set the data endian modes + * In Big Endian mode, the Most Significat Byte (MSB) is on the lower address, + * and the Least Significant Byte (LSB) is on the higher address. Little Endian + * mode reverses this order. Little Endian is the default mode. + * @param endianness New endian mode + * @see LSM303DLHC_RA_CTRL_REG4_A + * @see LSM303DLHC_BLE_BIT + * @see LSM303DLHC_BIG_ENDIAN + * @see LSM303DLHC_LITTLE_ENDIAN + */ +void LSM303DLHC::setAccelEndianMode(bool endianness) { + I2Cdev::writeBit(devAddrA, LSM303DLHC_RA_CTRL_REG4_A, LSM303DLHC_BLE_BIT, + endianness); + endianMode = getAccelEndianMode(); +} + +/** Get the data endian mode + * @return Current endian mode + * @see LSM303DLHC_RA_CTRL_REG4_A + * @see LSM303DLHC_BLE_BIT + * @see LSM303DLHC_BIG_ENDIAN + * @see LSM303DLHC_LITTLE_ENDIAN + */ +bool LSM303DLHC::getAccelEndianMode() { + return endianMode; + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_CTRL_REG4_A, LSM303DLHC_BLE_BIT, + buffer); + return buffer[0]; +} + +/** Set the full scale of the data output (in dps) + * @param scale The new scale of the data output (250, 500, 2000) + * @see LSM303DLHC_RA_CTRL_REG4_A + * @see LSM303DLHC_FS_BIT + * @see LSM303DLHC_FS_LENGTH + * @see LSM303DLHC_FS_2 + * @see LSM303DLHC_FS_4 + * @see LSM303DLHC_FS_8 + * @see LSM303DLHC_FS_16 + */ +void LSM303DLHC::setAccelFullScale(uint8_t scale) { + uint8_t writeBits; + + if (scale == 2) { + writeBits = LSM303DLHC_FS_2; + } else if (scale == 4) { + writeBits = LSM303DLHC_FS_4; + } else if (scale == 8) { + writeBits = LSM303DLHC_FS_8; + } else { + writeBits = LSM303DLHC_FS_16; + } + + I2Cdev::writeBits(devAddrA, LSM303DLHC_RA_CTRL_REG4_A, LSM303DLHC_FS_BIT, + LSM303DLHC_FS_LENGTH, writeBits); +} + +/** Get the current full scale of the output data (in dps) + * @return Current scale of the output data + * @see LSM303DLHC_RA_CTRL_REG4_A + * @see LSM303DLHC_FS_BIT + * @see LSM303DLHC_FS_LENGTH + * @see LSM303DLHC_FS_2 + * @see LSM303DLHC_FS_4 + * @see LSM303DLHC_FS_8 + * @see LSM303DLHC_FS_16 + */ +uint8_t LSM303DLHC::getAccelFullScale() { + I2Cdev::readBits(devAddrA, LSM303DLHC_RA_CTRL_REG4_A, + LSM303DLHC_FS_BIT, LSM303DLHC_FS_LENGTH, buffer); + uint8_t readBits = buffer[0]; + + if (readBits == LSM303DLHC_FS_2) { + return 2; + } else if (readBits == LSM303DLHC_FS_4) { + return 4; + } else if (readBits == LSM303DLHC_FS_8) { + return 8; + } else { + return 16; + } +} + +/*Enables or disables high resolution output. +@param enabled New enabled state of high resolution output +@see LSM303DLHC_RA_CTRL_REG4_A +@see LSM303DLHC_HR_BIT +*/ +void LSM303DLHC::setAccelHighResOutputEnabled(bool enabled){ + I2Cdev::writeBit(devAddrA, LSM303DLHC_RA_CTRL_REG4_A, LSM303DLHC_HR_BIT, + enabled); +} + +/*Gets whether high resolution output is enabled. +@return True if high resolution output is enabled +@see LSM303DLHC_RA_CTRL_REG4_A +@see LSM303DLHC_HR_BIT +*/ +bool LSM303DLHC::getAccelHighResOutputEnabled(){ + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_CTRL_REG4_A, LSM303DLHC_HR_BIT, + buffer); + return buffer[0]; +} + +/** Set the SPI mode + * @param mode New SPI mode + * @see LSM303DLHC_RA_CTRL_REG4_A + * @see LSM303DLHC_SIM_BIT + * @see LSM303DLHC_SIM_4W + * @see LSM303DLHC_SIM_3W + */ +void LSM303DLHC::setAccelSPIMode(bool mode) { + I2Cdev::writeBit(devAddrA, LSM303DLHC_RA_CTRL_REG4_A, LSM303DLHC_SIM_BIT, mode); +} + +/** Get the SPI mode + * @return Current SPI mode + * @see LSM303DLHC_RA_CTRL_REG4_A + * @see LSM303DLHC_SIM_BIT + * @see LSM303DLHC_SIM_4W + * @see LSM303DLHC_SIM_3W + */ +bool LSM303DLHC::getAccelSPIMode() { + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_CTRL_REG4_A, LSM303DLHC_SIM_BIT, + buffer); + return buffer[0]; +} + +//CTRL_REG5_A r/w + +/** Reboots the FIFO memory content + * @see LSM303DLHC_RA_CTRL_REG5_A + * @see LSM303DLHC_BOOT_BIT + */ +void LSM303DLHC::rebootAccelMemoryContent() { + I2Cdev::writeBit(devAddrA, LSM303DLHC_RA_CTRL_REG5_A, LSM303DLHC_BOOT_BIT, true); +} + +/** Set whether the FIFO buffer is enabled + * @param enabled New enabled state of the FIFO buffer + * @see LSM303DLHC_RA_CTRL_REG5_A + * @see LSM303DLHC_FIFO_EN_BIT + */ +void LSM303DLHC::setAccelFIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddrA, LSM303DLHC_RA_CTRL_REG5_A, LSM303DLHC_FIFO_EN_BIT, + enabled); +} + +/** Get whether the FIFO buffer is enabled + * @return True if the FIFO buffer is enabled, false otherwise + * @see LSM303DLHC_RA_CTRL_REG5_A + * @see LSM303DLHC_FIFO_EN_BIT + */ +bool LSM303DLHC::getAccelFIFOEnabled() { + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_CTRL_REG5_A, LSM303DLHC_FIFO_EN_BIT, + buffer); + return buffer[0]; +} + +/*Enable latching of interrupt requrest 1 +@param latched New enabled state of latching interrupt request 1 +@see LSM303DLHC_RA_CTRL_REG5_A +@see LSM303DLHC_LIR_INT1_BIT +*/ +void LSM303DLHC::setAccelInterrupt1RequestLatched(bool latched){ + I2Cdev::writeBit(devAddrA, LSM303DLHC_RA_CTRL_REG5_A, LSM303DLHC_LIR_INT1_BIT, + latched); +} + +/*Get whether latching of interrupt request 1 is enabled. +@return True if latching of interrupt request 1 is enabled +@see LSM303DLHC_RA_CTRL_REG5_A +@see LSM303DLHC_LIR_INT1_BIT +*/ +bool LSM303DLHC::getAccelInterrupt1RequestLatched(){ + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_CTRL_REG5_A, LSM303DLHC_LIR_INT1_BIT, + buffer); + return buffer[0]; +} + +/*Enable latching of interrupt requrest 2 +@param latched New enabled state of latching interrupt request 2 +@see LSM303DLHC_RA_CTRL_REG5_A +@see LSM303DLHC_LIR_INT2_BIT +*/ +void LSM303DLHC::setAccelInterrupt2RequestLatched(bool latched){ + I2Cdev::writeBit(devAddrA, LSM303DLHC_RA_CTRL_REG5_A, LSM303DLHC_LIR_INT2_BIT, + latched); +} + +/*Get whether latching of interrupt request 2 is enabled. +@return True if latching of interrupt request 2 is enabled +@see LSM303DLHC_RA_CTRL_REG5_A +@see LSM303DLHC_LIR_INT2_BIT +*/ +bool LSM303DLHC::getAccelInterrupt2RequestLatched(){ + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_CTRL_REG5_A, LSM303DLHC_LIR_INT2_BIT, + buffer); + return buffer[0]; +} + +/*Enable 4D dectection interrupt 1 +@param enabled New enabled state of the 4D detection interrupt 1 +@see LSM303DLHC_RA_CTRL_REG5_A +@see LSM303DLHC_D4D_INT1_BIT +*/ +void LSM303DLHC::setAccelDetect4DInterrupt1Enabled(bool enabled){ + I2Cdev::writeBit(devAddrA, LSM303DLHC_RA_CTRL_REG5_A, LSM303DLHC_D4D_INT1_BIT, + enabled); +} + +/*Get whether 4D detection interrupt 1 is enabled. +@return True if 4D detection interrupt 1 is enabled +@see LSM303DLHC_RA_CTRL_REG5_A +@see LSM303DLHC_D4D_INT1_BIT +*/ +bool LSM303DLHC::getAccelDetect4DInterrupt1Enabled(){ + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_CTRL_REG5_A, LSM303DLHC_D4D_INT1_BIT, + buffer); + return buffer[0]; +} + +/*Enable 4D dectection interrupt 2 +@param enabled New enabled state of the 4D detection interrupt 2 +@see LSM303DLHC_RA_CTRL_REG5_A +@see LSM303DLHC_D4D_INT2_BIT +*/ +void LSM303DLHC::setAccelDetect4DInterrupt2Enabled(bool enabled){ + I2Cdev::writeBit(devAddrA, LSM303DLHC_RA_CTRL_REG5_A, LSM303DLHC_D4D_INT2_BIT, + enabled); +} + +/*Get whether 4D detection interrupt 2 is enabled. +@return True if 4D detection interrupt 2 is enabled +@see LSM303DLHC_RA_CTRL_REG5_A +@see LSM303DLHC_D4D_INT2_BIT +*/ +bool LSM303DLHC::getAccelDetect4DInterrupt2Enabled(){ + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_CTRL_REG5_A, LSM303DLHC_D4D_INT2_BIT, + buffer); + return buffer[0]; +} + +//CTRL_REG6_A r/w + +//TODO: +/*Enable the Click interrupt routed to the INT2 pin. +@param enabled The new enabled state of the Click interrupt routed to the INT2 pin +@see LSM303DLHC_RA_CTRL_REG6_A +@see LSM303DLHC_I2_CLICK_BIT +*/ +void LSM303DLHC::setAccelINT2ClickEnabled(bool enabled){ + I2Cdev::writeBit(devAddrA, LSM303DLHC_RA_CTRL_REG6_A, LSM303DLHC_I2_CLICK_BIT, enabled); +} + +/*Get whether the Click interrupt is routed to the INT2 pin. +@return True if the Click interrupt is routed to the INT2 pin +@see LSM303DLHC_RA_CTRL_REG6_A +@see LSM303DLHC_I2_CLICK_BIT +*/ +bool LSM303DLHC::getAccelINT2ClickEnabled(){ + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_CTRL_REG6_A, LSM303DLHC_I2_CLICK_BIT, buffer); + return buffer[0]; +} + +/*Enable interrupt 1 routed to the INT2 pin. +@param enabled The new enabled state of whether interrupt 1 routed to the INT2 pin +@see LSM303DLHC_RA_CTRL_REG6_A +@see LSM303DLHC_I2_INT1_BIT +*/ +void LSM303DLHC::setAccelINT2Interrupt1Enabled(bool enabled){ + I2Cdev::writeBit(devAddrA, LSM303DLHC_RA_CTRL_REG6_A, LSM303DLHC_I2_INT1_BIT, enabled); +} + +/*Get whether interrupt 1 is routed to the INT2 pin. +@return True if interrupt 1 is routed to the INT2 pin +@see LSM303DLHC_RA_CTRL_REG6_A +@see LSM303DLHC_I2_INT1_BIT +*/ +bool LSM303DLHC::getAccelINT2Interrupt1Enabled(){ + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_CTRL_REG6_A, LSM303DLHC_I2_INT1_BIT, buffer); + return buffer[0]; +} + +/*Enable interrupt 2 routed to the INT2 pin. +@param enabled The new enabled state of whether interrupt 2 routed to the INT2 pin +@see LSM303DLHC_RA_CTRL_REG6_A +@see LSM303DLHC_I2_INT2_BIT +*/ +void LSM303DLHC::setAccelINT2Interrupt2Enabled(bool enabled){ + I2Cdev::writeBit(devAddrA, LSM303DLHC_RA_CTRL_REG6_A, LSM303DLHC_I2_INT2_BIT, enabled); +} + +/*Get whether interrupt 2 is routed to the INT2 pin. +@return True if interrupt 2 is routed to the INT2 pin +@see LSM303DLHC_RA_CTRL_REG6_A +@see LSM303DLHC_I2_INT2_BIT +*/ +bool LSM303DLHC::getAccelINT2Interrupt2Enabled(){ + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_CTRL_REG6_A, LSM303DLHC_I2_INT2_BIT, buffer); + return buffer[0]; +} + +/*Enable memory content reboot via INT2 pin +@param enabled The new state of whether memory content is rebooted via INT2 pin +@see LSM303DLHC_RA_CTRL_REG6_A +@see LSM303DLHC_BOOT_I1_BIT +*/ +void LSM303DLHC::setAccelRebootMemoryContentINT2Enabled(bool enabled){ + I2Cdev::writeBit(devAddrA, LSM303DLHC_RA_CTRL_REG6_A, LSM303DLHC_BOOT_I1_BIT, enabled); +} + +/*Get whether memory content reboot is enabled via INT2 pin +@return True if memory content reboot is via INT2 pin is enabled +@see LSM303DLHC_RA_CTRL_REG6_A +@see LSM303DLHC_BOOT_I1_BIT +*/ +bool LSM303DLHC::getAccelRebootMemoryContentINT2Enabled(){ + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_CTRL_REG6_A, LSM303DLHC_BOOT_I1_BIT, buffer); + return buffer[0]; +} + +// // TODO Documentation +// void setAccelActiveFunctionStatusINT2Enabled(bool enabled); + +// // TODO Documentation +// bool getAccelActiveFunctionStatusINT2Enabled(); + +/*Enable active low interrupts. +@param enable The new state of whether active low interrupts are enabled +@see LSM303DLHC_RA_CTRL_REG6_A +@see LSM303DLHC_H_ACTIVE_BIT +*/ +void LSM303DLHC::setAccelInterruptActiveLowEnabled(bool enabled){ + I2Cdev::writeBit(devAddrA, LSM303DLHC_RA_CTRL_REG6_A, LSM303DLHC_H_ACTIVE_BIT, enabled); +} + +/*Get whether active low interrupts are enabled. +@return True if active low interrupts are enabled. +@see LSM303DLHC_RA_CTRL_REG6_A +@see LSM303DLHC_H_ACTIVE_BIT +*/ +bool LSM303DLHC::getAccelInterruptActiveLowEnabled(){ + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_CTRL_REG6_A, LSM303DLHC_H_ACTIVE_BIT, buffer); + return buffer[0]; +} + +//REFERENCE_A, r/w + +/** Set the reference value for interrupt generation + * @param reference New reference value for interrupt generation + * @see LSM303DLHC_RA_REFERENCE_A + */ +void LSM303DLHC::setAccelInterruptReference(uint8_t reference) { + I2Cdev::writeByte(devAddrA, LSM303DLHC_RA_REFERENCE_A, reference); +} + +/** Get the 8-bit reference value for interrupt generation + * @return 8-bit reference value for interrupt generation + * @see LSM303DLHC_RA_REFERENCE + */ +uint8_t LSM303DLHC::getAccelInterruptReference() { + I2Cdev::readByte(devAddrA, LSM303DLHC_RA_REFERENCE_A, buffer); + return buffer[0]; +} + +//STATUS_REG_A r + +/** Get whether new data overwrote the last set of data before it was read + * @return True if the last set of data was overwritten before being read, false + * otherwise + * @see LSM303DLHC_RA_STATUS_REG_A + * @see LSM303DLHC_ZYXOR_BIT + */ +bool LSM303DLHC::getAccelXYZOverrun() { + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_STATUS_REG_A, LSM303DLHC_ZYXOR_BIT, + buffer); + return buffer[0]; +} + +/** Get whether new Z data overwrote the last set of data before it was read + * @return True if the last set of Z data was overwritten before being read, + * false otherwise + * @see LSM303DLHC_RA_STATUS_REG_A + * @see LSM303DLHC_ZOR_BIT + */ +bool LSM303DLHC::getAccelZOverrun() { + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_STATUS_REG_A, LSM303DLHC_ZOR_BIT, + buffer); + return buffer[0]; +} + +/** Get whether new Y data overwrote the last set of data before it was read + * @return True if the last set of Y data was overwritten before being read, + * false otherwise + * @see LSM303DLHC_RA_STATUS_REG_A + * @see LSM303DLHC_YOR_BIT + */ +bool LSM303DLHC::getAccelYOverrun() { + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_STATUS_REG_A, LSM303DLHC_YOR_BIT, + buffer); + return buffer[0]; +} + +/** Get whether new X data overwrote the last set of data before it was read + * @return True if the last set of X data was overwritten before being read, + * false otherwise + * @see LSM303DLHC_RA_STATUS_REG_A + * @see LSM303DLHC_XOR_BIT + */ +bool LSM303DLHC::getAccelXOverrun() { + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_STATUS_REG_A, LSM303DLHC_XOR_BIT, + buffer); + return buffer[0]; +} + +/** Get whether there is new data avaialable + * @return True if there is new data available, false otherwise + * @see LSM303DLHC_RA_STATUS_REG_A + * @see LSM303DLHC_ZYXDA_BIT + */ +bool LSM303DLHC::getAccelXYZDataAvailable() { + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_STATUS_REG_A, LSM303DLHC_ZYXDA_BIT, + buffer); + return buffer[0]; +} + +/** Get whether there is new Z data avaialable + * @return True if there is new Z data available, false otherwise + * @see LSM303DLHC_RA_STATUS_REG_A + * @see LSM303DLHC_ZDA_BIT + */ +bool LSM303DLHC::getAccelZDataAvailable() { + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_STATUS_REG_A, LSM303DLHC_ZDA_BIT, + buffer); + return buffer[0]; +} + +/** Get whether there is new Y data avaialable + * @return True if there is new Y data available, false otherwise + * @see LSM303DLHC_RA_STATUS_REG_A + * @see LSM303DLHC_YDA_BIT + */ +bool LSM303DLHC::getAccelYDataAvailable() { + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_STATUS_REG_A, LSM303DLHC_YDA_BIT, + buffer); + return buffer[0]; +} + +/** Get whether there is new X data avaialable + * @return True if there is new X data available, false otherwise + * @see LSM303DLHC_RA_STATUS_REG_A + * @see LSM303DLHC_XDA_BIT + */ +bool LSM303DLHC::getAccelXDataAvailable() { + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_STATUS_REG_A, LSM303DLHC_XDA_BIT, + buffer); + return buffer[0]; +} + +//OUT_*_A, r + +//TODO: +//Fix getAccerlation to read all 6 regs, and fix endian internal state + +/** Get the acceleration for all 3 axes + * Due to the fact that this device supports two difference Endian modes, both + * must be accounted for when reading data. In Little Endian mode, the first + * byte (lowest address) is the least significant and in Big Endian mode the + * first byte is the most significant. + * @param x 16-bit integer container for the X-axis acceleration + * @param y 16-bit integer container for the Y-axis acceleration + * @param z 16-bit integer container for the Z-axis acceleration + */ +void LSM303DLHC::getAcceleration(int16_t* x, int16_t* y, int16_t* z) { + I2Cdev::readBytes(devAddrA, LSM303DLHC_RA_OUT_X_L_A | 0x80, 6, buffer); + if (endianMode == LSM303DLHC_LITTLE_ENDIAN) { + *x = (((int16_t)buffer[1]) << 8) | buffer[0]; + *y = (((int16_t)buffer[3]) << 8) | buffer[2]; + *z = (((int16_t)buffer[5]) << 8) | buffer[4]; + } else { + *x = (((int16_t)buffer[0]) << 8) | buffer[1]; + *y = (((int16_t)buffer[2]) << 8) | buffer[3]; + *z = (((int16_t)buffer[4]) << 8) | buffer[5]; + } +} + +/** Get the acceleration along the X-axis + * @return acceleration along the X-axis + * @see LSM303DLHC_RA_OUT_X_L_A + * @see LSM303DLHC_RA_OUT_X_H_A + */ +int16_t LSM303DLHC::getAccelerationX() { + I2Cdev::readBytes(devAddrA, LSM303DLHC_RA_OUT_X_L_A | 0x80, 2, buffer); + if (endianMode == LSM303DLHC_LITTLE_ENDIAN) { + return (((int16_t)buffer[1]) << 8) | buffer[0]; + } else { + return (((int16_t)buffer[0]) << 8) | buffer[1]; + } +} + +/** Get the acceleration along the Y-axis + * @return acceleration along the Y-axis + * @see LSM303DLHC_RA_OUT_Y_L_A + * @see LSM303DLHC_RA_OUT_Y_H_A + */ +int16_t LSM303DLHC::getAccelerationY() { + I2Cdev::readBytes(devAddrA, LSM303DLHC_RA_OUT_Y_L_A | 0x80, 2, buffer); + if (endianMode == LSM303DLHC_LITTLE_ENDIAN) { + return (((int16_t)buffer[1]) << 8) | buffer[0]; + } else { + return (((int16_t)buffer[0]) << 8) | buffer[1]; + } +} + +/** Get the acceleration along the Z-axis + * @return acceleration along the Z-axis + * @see LSM303DLHC_RA_OUT_Z_L_A + * @see LSM303DLHC_RA_OUT_Z_H_A + */ +int16_t LSM303DLHC::getAccelerationZ() { + I2Cdev::readBytes(devAddrA, LSM303DLHC_RA_OUT_Z_L_A | 0x80, 2, buffer); + if (endianMode == LSM303DLHC_LITTLE_ENDIAN) { + return (((int16_t)buffer[1]) << 8) | buffer[0]; + } else { + return (((int16_t)buffer[0]) << 8) | buffer[1]; + } +} + +//FIFO_CTRL_REG_A, rw + +/** Set the FIFO mode to one of the defined modes + * @param mode New FIFO mode + * @see LSM303DLHC_RA_FIFO_CTRL_REG_A + * @see LSM303DLHC_FM_BIT + * @see LSM303DLHC_FM_LENGTH + * @see LSM303DLHC_FM_BYPASS + * @see LSM303DLHC_FM_FIFO + * @see LSM303DLHC_FM_STREAM + * @see LSM303DLHC_FM_TRIGGER + */ +void LSM303DLHC::setAccelFIFOMode(uint8_t mode) { + I2Cdev::writeBits(devAddrA, LSM303DLHC_RA_FIFO_CTRL_REG_A, LSM303DLHC_FM_BIT, + LSM303DLHC_FM_LENGTH, mode); +} + +/** Get the FIFO mode to one of the defined modes + * @return Current FIFO mode + * @see LSM303DLHC_RA_FIFO_CTRL_REG_A + * @see LSM303DLHC_FM_BIT + * @see LSM303DLHC_FM_LENGTH + * @see LSM303DLHC_FM_BYPASS + * @see LSM303DLHC_FM_FIFO + * @see LSM303DLHC_FM_STREAM + * @see LSM303DLHC_FM_TRIGGER + */ +uint8_t LSM303DLHC::getAccelFIFOMode() { + I2Cdev::readBits(devAddrA, LSM303DLHC_RA_FIFO_CTRL_REG_A, + LSM303DLHC_FM_BIT, LSM303DLHC_FM_LENGTH, buffer); + return buffer[0]; +} + +/*Set the trigger selection to INT1 or INT2 +@param trigger The new trigger selection +@see LSM303DLHC_RA_FIFO_CTRL_REG_A +@see LSM303DLHC_TR_BIT +@see LSM303DLHC_TR_INT1 +@see LSM303DLHC_TR_INT2 +*/ +void LSM303DLHC::setAccelFIFOTriggerINT(bool trigger){ + I2Cdev::writeBit(devAddrA, LSM303DLHC_RA_FIFO_CTRL_REG_A, + LSM303DLHC_TR_BIT, trigger); +} + +/*Get the trigger selection (INT1 or INT2) +@return trigger The new trigger selection (0 for INT1, 1 for INT2) +@see LSM303DLHC_RA_FIFO_CTRL_REG_A +@see LSM303DLHC_TR_BIT +@see LSM303DLHC_TR_INT1 +@see LSM303DLHC_TR_INT2 +*/ +bool LSM303DLHC::getAccelFIFOTriggerINT(){ + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_FIFO_CTRL_REG_A, + LSM303DLHC_TR_BIT, buffer); + return buffer[0]; +} + +/** Set the FIFO watermark threshold + * @param wtm New FIFO watermark threshold + * @see LSM303DLHC_RA_FIFO_CTRL_REG_A + * @see LSM303DLHC_FTH_BIT + * @see LSM303DLHC_FTH_LENGTH + */ +void LSM303DLHC::setAccelFIFOThreshold(uint8_t wtm) { + I2Cdev::writeBits(devAddrA, LSM303DLHC_RA_FIFO_CTRL_REG_A, LSM303DLHC_FTH_BIT, + LSM303DLHC_FTH_LENGTH, wtm); +} + +/** Get the FIFO watermark threshold + * @return FIFO watermark threshold + * @see LSM303DLHC_RA_FIFO_CTRL_REG_A + * @see LSM303DLHC_FTH_BIT + * @see LSM303DLHC_FTH_LENGTH + */ +uint8_t LSM303DLHC::getAccelFIFOThreshold() { + I2Cdev::readBits(devAddrA, LSM303DLHC_RA_FIFO_CTRL_REG_A, LSM303DLHC_FTH_BIT, + LSM303DLHC_FTH_LENGTH, buffer); + return buffer[0]; +} + + +//FIFO_SRC_REG_A, r + +/** Get whether the number of data sets in the FIFO buffer is less than the + * watermark + * @return True if the number of data sets in the FIFO buffer is more than or + * equal to the watermark, false otherwise. + * @see LSM303DLHC_RA_FIFO_SRC_REG_A + * @see LSM303DLHC_WTM_BIT + */ +bool LSM303DLHC::getAccelFIFOAtWatermark() { + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_FIFO_SRC_REG_A, LSM303DLHC_WTM_BIT, + buffer); + return buffer[0]; +} + +/** Get whether the FIFO buffer is full + * @return True if the FIFO buffer is full, false otherwise + * @see LSM303DLHC_RA_FIFO_SRC_REG_A + * @see LSM303DLHC_OVRN_FIFO_BIT + */ +bool LSM303DLHC::getAccelFIFOOverrun() { + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_FIFO_SRC_REG_A, + LSM303DLHC_OVRN_FIFO_BIT, buffer); + return buffer[0]; +} + +/** Get whether the FIFO buffer is empty + * @return True if the FIFO buffer is empty, false otherwise + * @see LSM303DLHC_RA_FIFO_SRC_REG_A + * @see LSM303DLHC_EMPTY_BIT + */ +bool LSM303DLHC::getAccelFIFOEmpty() { + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_FIFO_SRC_REG_A, + LSM303DLHC_EMPTY_BIT, buffer); + return buffer[0]; +} + +/** Get the number of filled FIFO buffer slots + * @return Number of filled slots in the FIFO buffer + * @see LSM303DLHC_RA_FIFO_SRC_REG_A + * @see LSM303DLHC_FSS_BIT + * @see LSM303DLHC_FSS_LENGTH + */ +uint8_t LSM303DLHC::getAccelFIFOStoredSamples() { + I2Cdev::readBits(devAddrA, LSM303DLHC_RA_FIFO_SRC_REG_A, + LSM303DLHC_FSS_BIT, LSM303DLHC_FSS_LENGTH, buffer); + return buffer[0]; +} + +//INT1_CFG_A, w/r + +/** Set the combination mode for interrupt 1events + * @param combination New combination mode for interrupt 1 events. + * LSM303DLHC_INT1_OR for OR and LSM303DLHC_INT1_AND for AND + * @see LSM303DLHC_RA_INT1_CFG_A + * @see LSM303DLHC_INT1_AOI_BIT + * @see LSM303DLHC_INT1_OR + * @see LSM303DLHC_INT1_AND + */ +void LSM303DLHC::setAccelInterrupt1Combination(bool combination) { + I2Cdev::writeBit(devAddrA, LSM303DLHC_RA_INT1_CFG_A, LSM303DLHC_INT1_AOI_BIT, + combination); +} + +/** Get the combination mode for interrupt 1 events + * @return Combination mode for interrupt 1 events. LSM303DLHC_INT1_OR for OR and + * LSM303DLHC_INT1_AND for AND + * @see LSM303DLHC_RA_INT1_CFG_A + * @see LSM303DLHC_INT1_AOI_BIT + * @see LSM303DLHC_INT1_OR + * @see LSM303DLHC_INT1_AND + */ +bool LSM303DLHC::getAccelInterrupt1Combination() { + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_INT1_CFG_A, LSM303DLHC_INT1_AOI_BIT, + buffer); + return buffer[0]; +} + +/*Enable 6D dectection interrupt 1. See datasheet for how 4D detection is affected. +@param enabled New enabled state of the 6D detection interrupt 1 +@see LSM303DLHC_RA_INT1_CFG_A +@see LSM303DLHC_INT1_6D_BIT +*/ +void LSM303DLHC::setAccelInterrupt16DEnabled(bool enabled){ + I2Cdev::writeBit(devAddrA, LSM303DLHC_RA_INT1_CFG_A, LSM303DLHC_INT1_6D_BIT, enabled); +} + +/*Get enable status of 6D dectection interrupt 1. See datasheet for how 4D detection is affected. +@return True if 6D detection interrupt 1 is enabled +@see LSM303DLHC_RA_INT1_CFG_A +@see LSM303DLHC_INT1_6D_BIT +*/ +bool LSM303DLHC::getAccelInterrupt16DEnabled(){ + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_INT1_CFG_A, LSM303DLHC_INT1_6D_BIT, buffer); + return buffer[0]; +} + +/** Set whether the interrupt 1 for Z high/up is enabled + * @param enabled New enabled state for Z high/up interrupt. + * @see LSM303DLHC_RA_INT1_CFG_A + * @see LSM303DLHC_ZHIE_ZUPE_BIT + */ +void LSM303DLHC::setAccelZHighUpInterrupt1Enabled(bool enabled) { + I2Cdev::writeBit(devAddrA, LSM303DLHC_RA_INT1_CFG_A, LSM303DLHC_INT1_ZHIE_ZUPE_BIT, enabled); +} + +/** Get whether the interrupt 1 for Z high/up is enabled + * @return True if the interrupt 1 for Z high/up is enabled, false otherwise + * @see LSM303DLHC_RA_INT1_CFG_A + * @see LSM303DLHC_INT1_ZHIE_ZUPE_BIT + */ +bool LSM303DLHC::getAccelZHighUpInterrupt1Enabled() { + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_INT1_CFG_A, LSM303DLHC_INT1_ZHIE_ZUPE_BIT, + buffer); + return buffer[0]; +} + +/** Set whether the interrupt 1 for Z low/down is enabled + * @param enabled New enabled state for Z low/down interrupt. + * @see LSM303DLHC_RA_INT1_CFG_A + * @see LSM303DLHC_INT1_ZLIE_ZDOWNE_BIT + */ +void LSM303DLHC::setAccelZLowDownInterrupt1Enabled(bool enabled) { + I2Cdev::writeBit(devAddrA, LSM303DLHC_RA_INT1_CFG_A, LSM303DLHC_INT1_ZLIE_ZDOWNE_BIT, enabled); +} + +/** Get whether the interrupt 1 for Z low/down is enabled + * @return True if the interrupt 1 for Z low/down is enabled, false otherwise + * @see LSM303DLHC_RA_INT1_CFG_A + * @see LSM303DLHC_INT1_ZLIE_ZDOWNE_BIT + */ +bool LSM303DLHC::getAccelZLowDownInterrupt1Enabled() { + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_INT1_CFG_A, LSM303DLHC_INT1_ZLIE_ZDOWNE_BIT, + buffer); + return buffer[0]; +} + +/** Set whether the interrupt 1 for Y high/up is enabled + * @param enabled New enabled state for Y high/up interrupt. + * @see LSM303DLHC_RA_INT1_CFG_A + * @see LSM303DLHC_INT1_YHIE_YUPE_BIT + */ +void LSM303DLHC::setAccelYHighUpInterrupt1Enabled(bool enabled) { + I2Cdev::writeBit(devAddrA, LSM303DLHC_RA_INT1_CFG_A, LSM303DLHC_INT1_YHIE_YUPE_BIT, enabled); +} + +/** Get whether the interrupt 1 for Y high/up is enabled + * @return True if the interrupt 1 for Y high/up is enabled, false otherwise + * @see LSM303DLHC_RA_INT1_CFG_A + * @see LSM303DLHC_INT1_YHIE_YUPE_BIT + */ +bool LSM303DLHC::getAccelYHighUpInterrupt1Enabled() { + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_INT1_CFG_A, LSM303DLHC_INT1_YHIE_YUPE_BIT, + buffer); + return buffer[0]; +} + +/** Set whether the interrupt 1 for Y low/down is enabled + * @param enabled New enabled state for Y low/down interrupt. + * @see LSM303DLHC_RA_INT1_CFG_A + * @see LSM303DLHC_INT1_YLIE_YDOWNE_BIT + */ +void LSM303DLHC::setAccelYLowDownInterrupt1Enabled(bool enabled) { + I2Cdev::writeBit(devAddrA, LSM303DLHC_RA_INT1_CFG_A, LSM303DLHC_INT1_YLIE_YDOWNE_BIT, enabled); +} + +/** Get whether the interrupt 1 for Y low/down is enabled + * @return True if the interrupt 1 for Y low/down is enabled, false otherwise + * @see LSM303DLHC_RA_INT1_CFG_A + * @see LSM303DLHC_INT1_YLIE_YDOWNE_BIT + */ +bool LSM303DLHC::getAccelYLowDownInterrupt1Enabled() { + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_INT1_CFG_A, LSM303DLHC_INT1_YLIE_YDOWNE_BIT, + buffer); + return buffer[0]; +} + +/** Set whether the interrupt 1 for X high/up is enabled + * @param enabled New enabled state for X high/up interrupt. + * @see LSM303DLHC_RA_INT1_CFG_A + * @see LSM303DLHC_INT1_XHIE_XUPE_BIT + */ +void LSM303DLHC::setAccelXHighUpInterrupt1Enabled(bool enabled) { + I2Cdev::writeBit(devAddrA, LSM303DLHC_RA_INT1_CFG_A, LSM303DLHC_INT1_XHIE_XUPE_BIT, enabled); +} + +/** Get whether the interrupt 1 for X high/up is enabled + * @return True if the interrupt 1 for X high/up is enabled, false otherwise + * @see LSM303DLHC_RA_INT1_CFG_A + * @see LSM303DLHC_INT1_XHIE_XUPE_BIT + */ +bool LSM303DLHC::getAccelXHighUpInterrupt1Enabled() { + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_INT1_CFG_A, LSM303DLHC_INT1_XHIE_XUPE_BIT, + buffer); + return buffer[0]; +} + +/** Set whether the interrupt 1 for X low/down is enabled + * @param enabled New enabled state for/down X low interrupt. + * @see LSM303DLHC_RA_INT1_CFG_A + * @see LSM303DLHC_INT1_XLIE_XDOWNE_BIT + */ +void LSM303DLHC::setAccelXLowDownInterrupt1Enabled(bool enabled) { + I2Cdev::writeBit(devAddrA, LSM303DLHC_RA_INT1_CFG_A, LSM303DLHC_INT1_XLIE_XDOWNE_BIT, enabled); +} + +/** Get whether the interrupt 1 for X low/down is enabled + * @return True if the interrupt 1 for X low/down is enabled, false otherwise + * @see LSM303DLHC_RA_INT1_CFG_A + * @see LSM303DLHC_INT1_XLIE_XDOWNE_BIT + */ +bool LSM303DLHC::getAccelXLowDownInterrupt1Enabled() { + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_INT1_CFG_A, LSM303DLHC_INT1_XLIE_XDOWNE_BIT, + buffer); + return buffer[0]; +} + +//INT1_SRC_A, r + +/*Get the contents of the INT1_SRC_A register to determine if any and which interrupts have occured. +Reading this register will clear any interrupts that were lateched. +@return the 8 bit contents of the INT1_SRC_a register +@see LSM303DLHC_RA_INT1_SRC_A +@see LSM303DLHC_INT1_IA_BIT +@see LSM303DLHC_INT1_ZH_BIT +@see LSM303DLHC_INT1_ZL_BIT +@see LSM303DLHC_INT1_YH_BIT +@see LSM303DLHC_INT1_YL_BIT +@see LSM303DLHC_INT1_XH_BIT +@see LSM303DLHC_INT1_XL_BIT +*/ +uint8_t LSM303DLHC::getAccelInterrupt1Source() { + I2Cdev::readByte(devAddrA, LSM303DLHC_RA_INT1_SRC_A, buffer); + return buffer[0]; +} + +//INT1_THS_A, w/r + +/** Set the threshold for interrupt 1 + * @param threshold New threshold for interrupt 1 + * @see LSM303DLHC_RA_INT1_THS_A + */ +void LSM303DLHC::setAccelInterrupt1Threshold(uint8_t value){ + I2Cdev::writeByte(devAddrA, LSM303DLHC_RA_INT1_THS_A, value); +} + +/** Retrieve the threshold interrupt 1 + * @return interrupt 1 threshold + * @see LSM303DLHC_RA_INT1_THS_A + */ +uint8_t LSM303DLHC::getAccelInterupt1Threshold(){ + I2Cdev::readByte(devAddrA, LSM303DLHC_RA_INT1_THS_A, buffer); + return buffer[0]; +} + +//INT1_DURATION_A, r/w + +/* Set the minimum event duration for interrupt 1 to be generated + * This depends on the chosen output data rate + * @param duration New duration necessary for interrupt 1 to be + * generated + * @see LSM303DLHC_RA_INT1_DURATION_A + * @see LSM303DLHC_INT1_DURATION_BIT + * @see LSM303DLHC_INT1_DURATION_LENGTH + */ +void LSM303DLHC::setAccelInterrupt1Duration(uint8_t duration) { + I2Cdev::writeBits(devAddrA, LSM303DLHC_RA_INT1_DURATION_A, LSM303DLHC_INT1_DURATION_BIT, + LSM303DLHC_INT1_DURATION_LENGTH, duration); +} + +/** Get the minimum event duration for interrupt 1 to be generated + * @return Duration necessary for interrupt 1 to be generated + * @see LSM303DLHC_RA_INT1_DURATION_A + * @see LSM303DLHC_INT1_DURATION_BIT + * @see LSM303DLHC_INT1_DURATION_LENGTH + */ +uint8_t LSM303DLHC::getAccelInterrupt1Duration() { + I2Cdev::readBits(devAddrA, LSM303DLHC_RA_INT1_DURATION_A, + LSM303DLHC_INT1_DURATION_BIT, LSM303DLHC_INT1_DURATION_LENGTH, buffer); + return buffer[0]; +} + +//INT2_CFG_A, r/w + +/** Set the combination mode for interrupt 2 events + * @param combination New combination mode for interrupt events. + * LSM303DLHC_INT1_OR for OR and LSM303DLHC_INT1_AND for AND + * @see LSM303DLHC_RA_INT2_CFG_A + * @see LSM303DLHC_INT2_AOI_BIT + * @see LSM303DLHC_INT1_OR + * @see LSM303DLHC_INT1_AND + */ +void LSM303DLHC::setAccelInterrupt2Combination(bool combination) { + I2Cdev::writeBit(devAddrA, LSM303DLHC_RA_INT2_CFG_A, LSM303DLHC_INT2_AOI_BIT, + combination); +} + +/** Get the combination mode for interrupt 2 events + * @return Combination mode for interrupt events. LSM303DLHC_INT1_OR for OR and + * LSM303DLHC_INT1_AND for AND + * @see LSM303DLHC_RA_INT2_CFG_A + * @see LSM303DLHC_INT2_AOI_BIT + * @see LSM303DLHC_INT1_OR + * @see LSM303DLHC_INT1_AND + */ +bool LSM303DLHC::getAccelInterrupt2Combination() { + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_INT2_CFG_A, LSM303DLHC_INT2_AOI_BIT, + buffer); + return buffer[0]; +} + +/*Enable 6D dectection interrupt 2. See datasheet for how 4D detection is affected. +@param enabled New enabled state of the 6D detection interrupt 1 +@see LSM303DLHC_RA_INT2_CFG_A +@see LSM303DLHC_INT2_6D_BIT +*/ +void LSM303DLHC::setAccelInterrupt26DEnabled(bool enabled){ + I2Cdev::writeBit(devAddrA, LSM303DLHC_RA_INT2_CFG_A, LSM303DLHC_INT2_6D_BIT, enabled); +} + +/*Get enable status of 6D dectection interrupt 2. See datasheet for how 4D detection is affected. +@return True if 6D detection interrupt 1 is enabled +@see LSM303DLHC_RA_INT2_CFG_A +@see LSM303DLHC_INT2_6D_BIT +*/ +bool LSM303DLHC::getAccelInterrupt26DEnabled(){ + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_INT2_CFG_A, LSM303DLHC_INT2_6D_BIT, buffer); + return buffer[0]; +} + +/** Set whether the interrupt 2 for Z high is enabled + * @param enabled New enabled state for Z high interrupt 2. + * @see LSM303DLHC_RA_INT2_CFG_A + * @see LSM303DLHC_INT2_ZHIE_BIT + */ +void LSM303DLHC::setAccelZHighInterrupt2Enabled(bool enabled) { + I2Cdev::writeBit(devAddrA, LSM303DLHC_RA_INT2_CFG_A, LSM303DLHC_INT2_ZHIE_BIT, enabled); +} + +/** Get whether the interrupt 2 for Z high is enabled + * @return True if the interrupt 2 for Z high is enabled, false otherwise + * @see LSM303DLHC_RA_INT2_CFG_A + * @see LSM303DLHC_INT2_ZHIE_BIT + */ +bool LSM303DLHC::getAccelZHighInterrupt2Enabled() { + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_INT2_CFG_A, LSM303DLHC_INT2_ZHIE_BIT, + buffer); + return buffer[0]; +} + +/** Set whether the interrupt 2 for Z low is enabled + * @param enabled New enabled state for Z low interrupt 2. + * @see LSM303DLHC_RA_INT2_CFG_A + * @see LSM303DLHC_INT2_ZLIE_BIT + */ +void LSM303DLHC::setAccelZLowInterrupt2Enabled(bool enabled) { + I2Cdev::writeBit(devAddrA, LSM303DLHC_RA_INT2_CFG_A, LSM303DLHC_INT2_ZLIE_BIT, enabled); +} + +/** Get whether the interrupt 2 for Z low is enabled + * @return True if the interrupt 2 for Z low is enabled, false otherwise + * @see LSM303DLHC_RA_INT2_CFG_A + * @see LSM303DLHC_INT2_ZLIE_BIT + */ +bool LSM303DLHC::getAccelZLowInterrupt2Enabled() { + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_INT2_CFG_A, LSM303DLHC_INT2_ZLIE_BIT, + buffer); + return buffer[0]; +} + +/** Set whether the interrupt 2 for Y high is enabled + * @param enabled New enabled state for Y high interrupt 2. + * @see LSM303DLHC_RA_INT2_CFG_A + * @see LSM303DLHC_INT2_YHIE_BIT + */ +void LSM303DLHC::setAccelYHighInterrupt2Enabled(bool enabled) { + I2Cdev::writeBit(devAddrA, LSM303DLHC_RA_INT2_CFG_A, LSM303DLHC_INT2_YHIE_BIT, enabled); +} + +/** Get whether the interrupt 2 for Y high is enabled + * @return True if the interrupt 2 for Y high is enabled, false otherwise + * @see LSM303DLHC_RA_INT2_CFG_A + * @see LSM303DLHC_INT2_YHIE_BIT + */ +bool LSM303DLHC::getAccelYHighInterrupt2Enabled() { + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_INT2_CFG_A, LSM303DLHC_INT2_YHIE_BIT, + buffer); + return buffer[0]; +} + +/** Set whether the interrupt 2 for Y low is enabled + * @param enabled New enabled state for Y low interrupt 2. + * @see LSM303DLHC_RA_INT2_CFG_A + * @see LSM303DLHC_INT2_YLIE_BIT + */ +void LSM303DLHC::setAccelYLowInterrupt2Enabled(bool enabled) { + I2Cdev::writeBit(devAddrA, LSM303DLHC_RA_INT2_CFG_A, LSM303DLHC_INT2_YLIE_BIT, enabled); +} + +/** Get whether the interrupt 2 for Y low is enabled + * @return True if the interrupt 2 for Y low is enabled, false otherwise + * @see LSM303DLHC_RA_INT2_CFG_A + * @see LSM303DLHC_INT2_YLIE_BIT + */ +bool LSM303DLHC::getAccelYLowInterrupt2Enabled() { + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_INT2_CFG_A, LSM303DLHC_INT2_YLIE_BIT, + buffer); + return buffer[0]; +} + +/** Set whether the interrupt 2 for X high is enabled + * @param enabled New enabled state for X high interrupt 2. + * @see LSM303DLHC_RA_INT2_CFG_A + * @see LSM303DLHC_INT2_XHIE_BIT + */ +void LSM303DLHC::setAccelXHighInterrupt2Enabled(bool enabled) { + I2Cdev::writeBit(devAddrA, LSM303DLHC_RA_INT2_CFG_A, LSM303DLHC_INT2_XHIE_BIT, enabled); +} + +/** Get whether the interrupt 2 for X high is enabled + * @return True if the interrupt 2 for X high is enabled, false otherwise + * @see LSM303DLHC_RA_INT2_CFG_A + * @see LSM303DLHC_INT2_XHIE_BIT + */ +bool LSM303DLHC::getAccelXHighInterrupt2Enabled() { + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_INT2_CFG_A, LSM303DLHC_INT2_XHIE_BIT, + buffer); + return buffer[0]; +} + +/** Set whether the interrupt 2 for X low is enabled + * @param enabled New enabled state for X low interrupt 2. + * @see LSM303DLHC_RA_INT2_CFG_A + * @see LSM303DLHC_INT2_XLIE_BIT + */ +void LSM303DLHC::setAccelXLowInterrupt2Enabled(bool enabled) { + I2Cdev::writeBit(devAddrA, LSM303DLHC_RA_INT2_CFG_A, LSM303DLHC_INT2_XLIE_BIT, enabled); +} + +/** Get whether the interrupt 2 for X low is enabled + * @return True if the interrupt 2 for X low is enabled, false otherwise + * @see LSM303DLHC_RA_INT2_CFG_A + * @see LSM303DLHC_INT2_XLIE_BIT + */ +bool LSM303DLHC::getAccelXLowInterrupt2Enabled() { + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_INT2_CFG_A, LSM303DLHC_INT2_XLIE_BIT, + buffer); + return buffer[0]; +} + + +//INT2_SRC_A, r + +/*Get the contents of the INT2_SRC_A register to determine if any and which interrupts have occured. +Reading this register will clear any interrupts that were lateched. +@return the 8 bit contents of the INT2_SRC_a register +@see LSM303DLHC_RA_INT2_SRC_A +@see LSM303DLHC_INT2_IA_BIT +@see LSM303DLHC_INT2_ZH_BIT +@see LSM303DLHC_INT2_ZL_BIT +@see LSM303DLHC_INT2_YH_BIT +@see LSM303DLHC_INT2_YL_BIT +@see LSM303DLHC_INT2_XH_BIT +@see LSM303DLHC_INT2_XL_BIT +*/ +uint8_t LSM303DLHC::getAccelInterrupt2Source() { + I2Cdev::readByte(devAddrA, LSM303DLHC_RA_INT2_SRC_A, buffer); + return buffer[0]; +} + +//INT2_THS_A, r/w + +/** Set the threshold for interrupt 2 + * @param threshold New threshold for interrupt 2 + * @see LSM303DLHC_RA_INT2_THS_A + */ +void LSM303DLHC::setAccelInterrupt2Threshold(uint8_t value){ + I2Cdev::writeByte(devAddrA, LSM303DLHC_RA_INT2_THS_A, value); +} + +/** Retrieve the threshold interrupt 2 + * @return interrupt 2 threshold + * @see LSM303DLHC_RA_INT2_THS_A + */ +uint8_t LSM303DLHC::getAccelInterupt2Threshold(){ + I2Cdev::readByte(devAddrA, LSM303DLHC_RA_INT2_THS_A, buffer); + return buffer[0]; +} + +//INT2_DURATION_A, r/w + +/* Set the minimum event duration for interrupt 2 to be generated + * This depends on the chosen output data rate + * @param duration New duration necessary for interrupt 2 to be + * generated + * @see LSM303DLHC_RA_INT2_DURATION_A + * @see LSM303DLHC_INT2_DURATION_BIT + * @see LSM303DLHC_INT2_DURATION_LENGTH + */ +void LSM303DLHC::setAccelInterrupt2Duration(uint8_t duration) { + I2Cdev::writeBits(devAddrA, LSM303DLHC_RA_INT2_DURATION_A, LSM303DLHC_INT2_DURATION_BIT, + LSM303DLHC_INT2_DURATION_LENGTH, duration); +} + +/** Get the minimum event duration for interrupt 2 to be generated + * @return Duration necessary for interrupt 2 to be generated + * @see LSM303DLHC_RA_INT2_DURATION_A + * @see LSM303DLHC_INT2_DURATION_BIT + * @see LSM303DLHC_INT2_DURATION_LENGTH + */ +uint8_t LSM303DLHC::getAccelInterrupt2Duration() { + I2Cdev::readBits(devAddrA, LSM303DLHC_RA_INT2_DURATION_A, + LSM303DLHC_INT2_DURATION_BIT, LSM303DLHC_INT2_DURATION_LENGTH, buffer); + return buffer[0]; +} + +//CLICK_CFG_A, r/w + +/*Enables interrupt double click on the Z axis. +@param enable The new status of double click interrupt on the Z axis +@see LSM303DLHC_RA_CLICK_CFG_A +@see LSM303DLHC_CLICK_ZD_BIT +*/ +void LSM303DLHC::setAccelZDoubleClickEnabled(bool enabled){ + I2Cdev::writeBit(devAddrA, LSM303DLHC_RA_CLICK_CFG_A, LSM303DLHC_CLICK_ZD_BIT, enabled); +} + +/*Get status of interrupt double click on the Z axis. +@return True if double click interrupt on the Z axis is enabled +@see LSM303DLHC_RA_CLICK_CFG_A +@see LSM303DLHC_CLICK_ZD_BIT +*/ +bool LSM303DLHC::getAccelZDoubleClickEnabled(){ + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_CLICK_CFG_A, LSM303DLHC_CLICK_ZD_BIT, buffer); + return buffer[0]; +} + +/*Enables interrupt single click on the Z axis. +@param enable The new status of single click interrupt on the Z axis +@see LSM303DLHC_RA_CLICK_CFG_A +@see LSM303DLHC_CLICK_ZS_BIT +*/ +void LSM303DLHC::setAccelZSingleClickEnabled(bool enabled){ + I2Cdev::writeBit(devAddrA, LSM303DLHC_RA_CLICK_CFG_A, LSM303DLHC_CLICK_ZS_BIT, enabled); +} + +/*Get status of interrupt single click on the Z axis. +@return True if single click interrupt on the Z axis is enabled +@see LSM303DLHC_RA_CLICK_CFG_A +@see LSM303DLHC_CLICK_ZS_BIT +*/ +bool LSM303DLHC::getAccelZSingleClickEnabled(){ + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_CLICK_CFG_A, LSM303DLHC_CLICK_ZS_BIT, buffer); + return buffer[0]; +} + +/*Enables interrupt double click on the Y axis. +@param enable The new status of double click interrupt on the Y axis +@see LSM303DLHC_RA_CLICK_CFG_A +@see LSM303DLHC_CLICK_YD_BIT +*/ +void LSM303DLHC::setAccelYDoubleClickEnabled(bool enabled){ + I2Cdev::writeBit(devAddrA, LSM303DLHC_RA_CLICK_CFG_A, LSM303DLHC_CLICK_YD_BIT, enabled); +} + +/*Get status of interrupt double click on the Y axis. +@return True if double click interrupt on the Y axis is enabled +@see LSM303DLHC_RA_CLICK_CFG_A +@see LSM303DLHC_CLICK_YD_BIT +*/ +bool LSM303DLHC::getAccelYDoubleClickEnabled(){ + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_CLICK_CFG_A, LSM303DLHC_CLICK_YD_BIT, buffer); + return buffer[0]; +} + +/*Enables interrupt single click on the Y axis. +@param enable The new status of single click interrupt on the Y axis +@see LSM303DLHC_RA_CLICK_CFG_A +@see LSM303DLHC_CLICK_YS_BIT +*/ +void LSM303DLHC::setAccelYSingleClickEnabled(bool enabled){ + I2Cdev::writeBit(devAddrA, LSM303DLHC_RA_CLICK_CFG_A, LSM303DLHC_CLICK_YS_BIT, enabled); +} + +/*Get status of interrupt single click on the Y axis. +@return True if single click interrupt on the Y axis is enabled +@see LSM303DLHC_RA_CLICK_CFG_A +@see LSM303DLHC_CLICK_YS_BIT +*/ +bool LSM303DLHC::getAccelYSingleClickEnabled(){ + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_CLICK_CFG_A, LSM303DLHC_CLICK_YS_BIT, buffer); + return buffer[0]; +} + +/*Enables interrupt double click on the X axis. +@param enable The new status of double click interrupt on the X axis +@see LSM303DLHC_RA_CLICK_CFG_A +@see LSM303DLHC_CLICK_XD_BIT +*/ +void LSM303DLHC::setAccelXDoubleClickEnabled(bool enabled){ + I2Cdev::writeBit(devAddrA, LSM303DLHC_RA_CLICK_CFG_A, LSM303DLHC_CLICK_XD_BIT, enabled); +} + +/*Get status of interrupt double click on the X axis. +@return True if double click interrupt on the X axis is enabled +@see LSM303DLHC_RA_CLICK_CFG_A +@see LSM303DLHC_CLICK_XD_BIT +*/ +bool LSM303DLHC::getAccelXDoubleClickEnabled(){ + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_CLICK_CFG_A, LSM303DLHC_CLICK_XD_BIT, buffer); + return buffer[0]; +} + +/*Enables interrupt single click on the X axis. +@param enable The new status of single click interrupt on the X axis +@see LSM303DLHC_RA_CLICK_CFG_A +@see LSM303DLHC_CLICK_XS_BIT +*/ +void LSM303DLHC::setAccelXSingleClickEnabled(bool enabled){ + I2Cdev::writeBit(devAddrA, LSM303DLHC_RA_CLICK_CFG_A, LSM303DLHC_CLICK_XS_BIT, enabled); +} + +/*Get status of interrupt single click on the X axis. +@return True if single click interrupt on the X axis is enabled +@see LSM303DLHC_RA_CLICK_CFG_A +@see LSM303DLHC_CLICK_XS_BIT +*/ + +bool LSM303DLHC::getAccelXSingleClickEnabled(){ + I2Cdev::readBit(devAddrA, LSM303DLHC_RA_CLICK_CFG_A, LSM303DLHC_CLICK_XS_BIT, buffer); + return buffer[0]; +} + + +//CLICK_SRC_A, r + +/*Get the contents of the CLICK_SRC_A register to determine if any and which interrupts have occured. +Reading this register may (not sure) clear any interrupts that were lateched. +@return the 7 bit contents of the CLICK_SRC_A register +@see LSM303DLHC_RA_CLICK_SRC_A +@see LSM303DLHC_CLICK_IA_BIT +@see LSM303DLHC_CLICK_DCLICK_BIT +@see LSM303DLHC_CLICK_SCLICK_BIT +@see LSM303DLHC_CLICK_SIGN_BIT +@see LSM303DLHC_CLICK_Z_BIT +@see LSM303DLHC_CLICK_Y_BIT +@see LSM303DLHC_CLICK_X_BIT +*/ +uint8_t LSM303DLHC::getAccelClickSource(){ + I2Cdev::readByte(devAddrA, LSM303DLHC_RA_CLICK_SRC_A, buffer); + return buffer[0]; +} + +//CLICK_THS_A, r/w + +/*Set the threshold which is used to start the click-detection procedure. The threshold +value is expressed over 7 bits as an unsigned number. +@param value The value of the click detection threshold +@see LSM303DLHC_RA_CLICK_THS_A +*/ +void LSM303DLHC::setAcceLClickThreshold(uint8_t value){ + I2Cdev::writeByte(devAddrA, LSM303DLHC_RA_CLICK_THS_A, value); +} + +/*Get the threshold which is used to start the click-detection procedure. The threshold +value is a 7 bit unsigned number. +@return The value of the click detection threshold +@see LSM303DLHC_RA_CLICK_THS_A +*/ +uint8_t LSM303DLHC::getAccelClickThreshold(){ + I2Cdev::readByte(devAddrA, LSM303DLHC_RA_CLICK_THS_A, buffer); + return buffer[0]; +} + +//TIME_LIMIT_A, r/w + +/*Set the maximum time interval that can elapse between the start of the click-detection +procedure (the acceleration on the selected channel exceeds the programmed threshold) +and when the acceleration falls below the threshold. +@param value The value of the maximum time interval for click detection +@see LSM303DLHC_RA_TIME_LIMIT_A +*/ +void LSM303DLHC::setAcceLClickTimeLimit(uint8_t value){ + I2Cdev::writeByte(devAddrA, LSM303DLHC_RA_TIME_LIMIT_A, value); +} + +/*Get the maximum time interval that can elapse between the start of the click-detection +procedure (the acceleration on the selected channel exceeds the programmed threshold) +and when the acceleration falls below the threshold. +@return The value of the maximum time interval for click detection +@see LSM303DLHC_RA_TIME_LIMIT_A +*/ +uint8_t LSM303DLHC::getAccelClickTimeLimit(){ + I2Cdev::readByte(devAddrA, LSM303DLHC_RA_TIME_LIMIT_A, buffer); + return buffer[0]; +} + +//TIME_LATENCY_A, r/w + +/*Set the time interval that starts after the first click detection where the +click-detection procedure is disabled, in cases where the device is configured +for double-click detection. +@param value The double click interval +@see LSM303DLHC_RA_TIME_LATENCY_A +*/ +void LSM303DLHC::setAcceLClickTimeLatency(uint8_t value){ + I2Cdev::writeByte(devAddrA, LSM303DLHC_RA_TIME_LATENCY_A, value); +} + +/*Get the time interval that starts after the first click detection where the +click-detection procedure is disabled, in cases where the device is configured +for double-click detection. +@return The double click interval +@see LSM303DLHC_RA_TIME_LATENCY_A +*/ +uint8_t LSM303DLHC::getAccelClickTimeLatency(){ + I2Cdev::readByte(devAddrA, LSM303DLHC_RA_TIME_LATENCY_A, buffer); + return buffer[0]; +} + +//TIME_WINDOW_A, r/w + +/*Set the maximum interval of time that can elapse after the end of the latency +interval in which the click detection procedure can start, in cases where the device +is configured for double-click detection. +@param value The time window +@see LSM303DLHC_RA_TIME_WINDOW_A +*/ +void LSM303DLHC::setAcceLClickTimeWindow(uint8_t value){ + I2Cdev::writeByte(devAddrA, LSM303DLHC_RA_TIME_WINDOW_A, value); +} + +/*Get the maximum interval of time that can elapse after the end of the latency +interval in which the click detection procedure can start, in cases where the device +is configured for double-click detection. +@return The double click time window +@see LSM303DLHC_RA_TIME_WINDOW_A +*/ +uint8_t LSM303DLHC::getAccelClickTimeWindow(){ + I2Cdev::readByte(devAddrA, LSM303DLHC_RA_TIME_WINDOW_A, buffer); + return buffer[0]; +} + +//CRA_REG_M_A, rw + +/*Set the temperature sensor to be enabled. +@param enabled The new enabled state of the temperature sensor. +@see LSM303DLHC_RA_CRA_REG_M +@see LSM303DLHC_TEMP_EN_BIT +*/ +void LSM303DLHC::setMagTemperatureEnabled(bool enabled){ + I2Cdev::writeBit(devAddrM, LSM303DLHC_RA_CRA_REG_M, LSM303DLHC_TEMP_EN_BIT, enabled); +} + +/*Get whether the temperature sensor is enabled. +@return The state of the temperature sensor. +@see LSM303DLHC_RA_CRA_REG_M +@see LSM303DLHC_TEMP_EN_BIT +*/ +bool LSM303DLHC::getMagTemperatureEnabled(){ + I2Cdev::readBit(devAddrM, LSM303DLHC_RA_CRA_REG_M, LSM303DLHC_TEMP_EN_BIT, buffer); + return buffer[0]; +} + +/*Set the magetometer output data rate. Valid rates are 0, 1, 3, 7, 15, 30, 75, 220. +@param rate The new output data rate of the magnetometer. +@see LSM303DLHC_RA_CRA_REG_M +@see LSM303DLHC_DO_BIT +@see LSM303DLHC_DO_LENGTH +@see LSM303DLHC_DO_RATE_0 +@see LSM303DLHC_DO_RATE_1 +@see LSM303DLHC_DO_RATE_3 +@see LSM303DLHC_DO_RATE_7 +@see LSM303DLHC_DO_RATE_15 +@see LSM303DLHC_DO_RATE_30 +@see LSM303DLHC_DO_RATE_75 +@see LSM303DLHC_DO_RATE_220 +*/ +void LSM303DLHC::setMagOutputDataRate(uint8_t rate){ + uint8_t writeBit; + if (rate == 0){ + writeBit = LSM303DLHC_DO_RATE_0; + } else if (rate == 1){ + writeBit = LSM303DLHC_DO_RATE_1; + } else if (rate == 3){ + writeBit = LSM303DLHC_DO_RATE_3; + } else if (rate == 7){ + writeBit = LSM303DLHC_DO_RATE_7; + } else if (rate == 15){ + writeBit = LSM303DLHC_DO_RATE_15; + } else if (rate == 30){ + writeBit = LSM303DLHC_DO_RATE_30; + } else if (rate == 75){ + writeBit = LSM303DLHC_DO_RATE_75; + } else if (rate == 220){ + writeBit = LSM303DLHC_DO_RATE_220; + } + + I2Cdev::writeBits(devAddrM, LSM303DLHC_RA_CRA_REG_M, LSM303DLHC_DO_BIT, + LSM303DLHC_DO_LENGTH, writeBit); +} + +/*Get the magetometer output data rate. +@return The output data rate of the magnetometer. +@see LSM303DLHC_RA_CRA_REG_M +@see LSM303DLHC_DO_BIT +@see LSM303DLHC_DO_LENGTH +@see LSM303DLHC_DO_RATE_0 +@see LSM303DLHC_DO_RATE_1 +@see LSM303DLHC_DO_RATE_3 +@see LSM303DLHC_DO_RATE_7 +@see LSM303DLHC_DO_RATE_15 +@see LSM303DLHC_DO_RATE_30 +@see LSM303DLHC_DO_RATE_75 +@see LSM303DLHC_DO_RATE_220 +*/ +uint8_t LSM303DLHC::getMagOutputDataRate(){ + I2Cdev::readBits(devAddrM, LSM303DLHC_RA_CRA_REG_M, LSM303DLHC_DO_BIT, + LSM303DLHC_DO_LENGTH, buffer); + uint8_t rate = buffer[0]; + + if (rate == LSM303DLHC_DO_RATE_0){ + return 0; + } else if (rate == LSM303DLHC_DO_RATE_1){ + return 1; + } else if (rate == LSM303DLHC_DO_RATE_3){ + return 3; + } else if (rate == LSM303DLHC_DO_RATE_7){ + return 7; + } else if (rate == LSM303DLHC_DO_RATE_15){ + return 15; + } else if (rate == LSM303DLHC_DO_RATE_30){ + return 30; + } else if (rate == LSM303DLHC_DO_RATE_75){ + return 75; + } else if (rate == LSM303DLHC_DO_RATE_220){ + return 220; + } +} + +//CRB_REG_M, rws + +/*Set the magnetometer gain. +@param gain The new gain of the magnetometer +@see LSM303DLHC_RA_CRB_REG_M +@see LSM303DLHC_GN_BIT +@see LSM303DLHC_GN_LENGTH +@see LSM303DLHC_GN_230 +@see LSM303DLHC_GN_330 +@see LSM303DLHC_GN_400 +@see LSM303DLHC_GN_450 +@see LSM303DLHC_GN_670 +@see LSM303DLHC_GN_855 +@see LSM303DLHC_GN_1100 +*/ +void LSM303DLHC::setMagGain(uint16_t gain){ + uint8_t writeBit; + if (gain == 230){ + writeBit = LSM303DLHC_GN_230; + } else if (gain == 330){ + writeBit = LSM303DLHC_GN_330; + } else if (gain == 400){ + writeBit = LSM303DLHC_GN_400; + } else if (gain == 450){ + writeBit = LSM303DLHC_GN_450; + } else if (gain == 670){ + writeBit = LSM303DLHC_GN_670; + } else if (gain == 855){ + writeBit = LSM303DLHC_GN_855; + } else if (gain == 1100){ + writeBit = LSM303DLHC_GN_1100; + } + + I2Cdev::writeBits(devAddrM, LSM303DLHC_RA_CRB_REG_M, LSM303DLHC_GN_BIT, LSM303DLHC_GN_LENGTH, + writeBit); +} + +/*Get the magnetometer gain. +@return The gain of the magnetometer +@see LSM303DLHC_RA_CRB_REG_M +@see LSM303DLHC_GN_230 +@see LSM303DLHC_GN_330 +@see LSM303DLHC_GN_400 +@see LSM303DLHC_GN_450 +@see LSM303DLHC_GN_670 +@see LSM303DLHC_GN_855 +@see LSM303DLHC_GN_1100 +*/ +uint16_t LSM303DLHC::getMagGain(){ + I2Cdev::readBits(devAddrM, LSM303DLHC_RA_CRB_REG_M, LSM303DLHC_GN_BIT, LSM303DLHC_GN_LENGTH, + buffer); + uint8_t gain = buffer[0]; + if (gain == LSM303DLHC_GN_230){ + return 230; + } else if (gain == LSM303DLHC_GN_330){ + return 330; + } else if (gain == LSM303DLHC_GN_400){ + return 400; + } else if (gain == LSM303DLHC_GN_450){ + return 450; + } else if (gain == LSM303DLHC_GN_670){ + return 670; + } else if (gain == LSM303DLHC_GN_855){ + return 855; + } else if (gain == LSM303DLHC_GN_1100){ + return 1100; + } +} + +//MR_REG_M, rw + +/*Set the magnetometer mode. +@param mode The new mode for the magnetometer. +@see LSM303DLHC_RA_MR_REG_M +@see LSM303DLHC_MD_BIT +@see LSM303DLHC_MD_LENGTH +@see LSM303DLHC_MD_CONTINUOUS +@see LSM303DLHC_MD_SINGLE +@see LSM303DLHC_MD_SLEEP +*/ +void LSM303DLHC::setMagMode(uint8_t mode){ + I2Cdev::writeBits(devAddrM, LSM303DLHC_RA_MR_REG_M, LSM303DLHC_MD_BIT, LSM303DLHC_MD_LENGTH, + mode); +} + +/*Get the magnetometer mode. +@return The mode for the magnetometer. +@see LSM303DLHC_RA_MR_REG_M +@see LSM303DLHC_MD_BIT +@see LSM303DLHC_MD_LENGTH +@see LSM303DLHC_MD_CONTINUOUS +@see LSM303DLHC_MD_SINGLE +@see LSM303DLHC_MD_SLEEP +*/ +uint8_t LSM303DLHC::getMagMode(){ + I2Cdev::readBits(devAddrM, LSM303DLHC_RA_MR_REG_M, LSM303DLHC_MD_BIT, LSM303DLHC_MD_LENGTH, + buffer); + return buffer[0]; +} + +//OUT_____M, r + +//TODO +/** Get the magnetic field for all 3 axes + * @param x 16-bit integer container for the X-axis magnetic field + * @param y 16-bit integer container for the Y-axis magnetic field + * @param z 16-bit integer container for the Z-axis magnetic field + */ +void LSM303DLHC::getMag(int16_t* x, int16_t* y, int16_t* z){ + I2Cdev::readBytes(devAddrM, LSM303DLHC_RA_OUT_X_H_M, 6, buffer); + *x = ((((int16_t)buffer[0]) << 8) | buffer[1]); + *z = ((((int16_t)buffer[2]) << 8) | buffer[3]); + *y = ((((int16_t)buffer[4]) << 8) | buffer[5]); + +} + +/** Get the magnetic field along the X-axis + * @return magnetic field along the X-axis + * @see LSM303DLHC_RA_OUT_X_L_M + * @see LSM303DLHC_RA_OUT_X_H_M + */ +int16_t LSM303DLHC::getMagX(){ + I2Cdev::readBytes(devAddrM, LSM303DLHC_RA_OUT_X_H_M, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} + +/** Get the magnetic field along the X-axis + * @return magnetic field along the X-axis + * @see LSM303DLHC_RA_OUT_Y_L_M + * @see LSM303DLHC_RA_OUT_Y_H_M + */ +int16_t LSM303DLHC::getMagY(){ + I2Cdev::readBytes(devAddrM, LSM303DLHC_RA_OUT_Y_H_M, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} + +/** Get the magnetic field along the X-axis + * @return magnetic field along the X-axis + * @see LSM303DLHC_RA_OUT_Z_L_M + * @see LSM303DLHC_RA_OUT_Z_H_M + */ +int16_t LSM303DLHC::getMagZ(){ + I2Cdev::readBytes(devAddrM, LSM303DLHC_RA_OUT_Z_H_M, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} + +//SR_REG_M, r + +/*Get data output register lock. This bit is set when the first magnetic file +data register has been read. +@return the output data register lock +@see LSM303DLHC_RA_SR_REG_M +@see LSM303DLHC_RA_M_LOCK_BIT +*/ +bool LSM303DLHC::getMagOutputDataRegisterLock(){ + I2Cdev::readBit(devAddrM, LSM303DLHC_RA_SR_REG_M, LSM303DLHC_M_LOCK_BIT, buffer); + return buffer[0]; +} + +/*Get data ready bit. This bit is when a new set of measurements is available. +@return the data ready bit status +@see LSM303DLHC_RA_SR_REG_M +@see LSM303DLHC_RA_M_DRDY_BIT +*/ +bool LSM303DLHC::getMagDataReady(){ + I2Cdev::readBit(devAddrM, LSM303DLHC_RA_SR_REG_M, LSM303DLHC_M_DRDY_BIT, buffer); + return buffer[0]; +} + +//TEMP_OUT_*_M + +/*Get the tempearture data. 12-bit resolution. 8LSB/deg +@return The temperature data. +@see LSM303DLHC_RA_TEMP_OUT_H_M +@see LSM303DLHC_RA_TEMP_OUT_L_M +*/ +int16_t LSM303DLHC::getTemperature(){ + I2Cdev::readBytes(devAddrM, LSM303DLHC_RA_TEMP_OUT_H_M | 0x80, 2, buffer); + return ((((int16_t)buffer[0]) << 8) | buffer[1]) >> 4; +} + +// WHO_AM_I register, read-only +// There is no ID register for this device. +uint8_t LSM303DLHC::getDeviceID() { + return 0; + // read a single byte and return it + // I2Cdev::readByte(devAddrA, LSM303DLHC_RA_WHO_AM_I, buffer); + // return buffer[0]; +} diff --git a/Arduino/LSM303DLHC/LSM303DLHC.h b/Arduino/LSM303DLHC/LSM303DLHC.h new file mode 100644 index 00000000..8c3469c4 --- /dev/null +++ b/Arduino/LSM303DLHC/LSM303DLHC.h @@ -0,0 +1,658 @@ +// I2Cdev library collection - LSM303DLHC I2C device class header file +// Based on ST LSM303DLHC datasheet REV 2, 11/2013 +// 3/10/2015 by Nate Costello +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// 2015-03-15 - initial release + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2011 [Author Name], Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#ifndef _LSM303DLHC_H_ +#define _LSM303DLHC_H_ + +#include "I2Cdev.h" + +// ---------------------------------------------------------------------------- +// STUB TODO: +// List all possible device I2C addresses here, if they are predefined. Some +// devices only have one possible address, in which case that one should be +// defined as both [LSM303DLHC]_ADDRESS and [LSM303DLHC]_DEFAULT_ADDRESS for +// consistency. The *_DEFAULT address will be used if a device object is +// created without an address provided in the constructor. Note that I2C +// devices conventionally use 7-bit addresses, so these will generally be +// between 0x00 and 0x7F. +// The LSM303DLHC uses two device addresses, one for the accerometer, and on +// for the megnetometer. +// ---------------------------------------------------------------------------- +#define LSM303DLHC_ADDRESS_A 0x19 +#define LSM303DLHC_ADDRESS_M 0x1E +#define LSM303DLHC_DEFAULT_ADDRESS_A 0x19 +#define LSM303DLHC_DEFAULT_ADDRESS_M 0x1E + +// ---------------------------------------------------------------------------- +// STUB TODO: +// List all registers that this device has. The goal for all device libraries +// is to have complete coverage of all possible functions, so be sure to add +// everything in the datasheet. Register address constants should use the extra +// prefix "RA_", followed by the datasheet's given name for each register. +// ---------------------------------------------------------------------------- +#define LSM303DLHC_RA_CTRL_REG1_A 0x20 // rw 0000 0111 +#define LSM303DLHC_RA_CTRL_REG2_A 0x21 // rw 0000 0000 +#define LSM303DLHC_RA_CTRL_REG3_A 0x22 // rw 0000 0000 +#define LSM303DLHC_RA_CTRL_REG4_A 0x23 // rw 0000 0000 +#define LSM303DLHC_RA_CTRL_REG5_A 0x24 // rw 0000 0000 +#define LSM303DLHC_RA_CTRL_REG6_A 0x25 // rw 0000 0000 +#define LSM303DLHC_RA_REFERENCE_A 0x06 // rw 0000 0000 +#define LSM303DLHC_RA_STATUS_REG_A 0x27 // r 0000 0000 +#define LSM303DLHC_RA_OUT_X_L_A 0x28 // r +#define LSM303DLHC_RA_OUT_X_H_A 0x29 // r +#define LSM303DLHC_RA_OUT_Y_L_A 0x2A // r +#define LSM303DLHC_RA_OUT_Y_H_A 0x2B // r +#define LSM303DLHC_RA_OUT_Z_L_A 0x2C // r +#define LSM303DLHC_RA_OUT_Z_H_A 0x2D // r +#define LSM303DLHC_RA_FIFO_CTRL_REG_A 0x2E // rw 0000 0000 +#define LSM303DLHC_RA_FIFO_SRC_REG_A 0x2F // r +#define LSM303DLHC_RA_INT1_CFG_A 0x30 // rw 0000 0000 +#define LSM303DLHC_RA_INT1_SRC_A 0x31 // r 0000 0000 +#define LSM303DLHC_RA_INT1_THS_A 0x32 // rw 0000 0000 +#define LSM303DLHC_RA_INT1_DURATION_A 0x33 // rw 0000 0000 +#define LSM303DLHC_RA_INT2_CFG_A 0x34 // rw 0000 0000 +#define LSM303DLHC_RA_INT2_SRC_A 0x35 // r 0000 0000 +#define LSM303DLHC_RA_INT2_THS_A 0x36 // rw 0000 0000 +#define LSM303DLHC_RA_INT2_DURATION_A 0x37 // rw 0000 0000 +#define LSM303DLHC_RA_CLICK_CFG_A 0x38 // rw 0000 0000 +#define LSM303DLHC_RA_CLICK_SRC_A 0x39 // rw 0000 0000 +#define LSM303DLHC_RA_CLICK_THS_A 0x3A // rw 0000 0000 +#define LSM303DLHC_RA_TIME_LIMIT_A 0x3B // rw 0000 0000 +#define LSM303DLHC_RA_TIME_LATENCY_A 0x3C // rw 0000 0000 +#define LSM303DLHC_RA_TIME_WINDOW_A 0x3D // rw 0000 0000 + +#define LSM303DLHC_RA_CRA_REG_M 0x00 // rw 0001 0000 +#define LSM303DLHC_RA_CRB_REG_M 0x01 // rw 0010 0000 +#define LSM303DLHC_RA_MR_REG_M 0x02 // rw 0000 0011 +#define LSM303DLHC_RA_OUT_X_H_M 0x03 // r +#define LSM303DLHC_RA_OUT_X_L_M 0x04 // r +#define LSM303DLHC_RA_OUT_Z_H_M 0x05 // r +#define LSM303DLHC_RA_OUT_Z_L_M 0x06 // r +#define LSM303DLHC_RA_OUT_Y_H_M 0x07 // r +#define LSM303DLHC_RA_OUT_Y_L_M 0x08 // r +#define LSM303DLHC_RA_SR_REG_M 0x09 // r 0000 0000 +#define LSM303DLHC_RA_IRA_REG_M 0x0A // r 0100 1000 +#define LSM303DLHC_RA_IRB_REG_M 0x0B // r 0011 0100 +#define LSM303DLHC_RA_IRC_REG_M 0x0C // r 0011 0011 +#define LSM303DLHC_RA_TEMP_OUT_H_M 0x31 // r +#define LSM303DLHC_RA_TEMP_OUT_L_M 0x32 // r + +// ---------------------------------------------------------------------------- +// STUB TODO: +// List register structures wherever necessary. Bit position constants should +// end in "_BIT", and are defined from 7 to 0, with 7 being the left/MSB and +// 0 being the right/LSB. If the device uses 16-bit registers instead of the +// more common 8-bit registers, the range is 15 to 0. Field length constants +// should end in "_LENGTH", but otherwise match the name of bit position +// constant that it complements. Fields that are a single bit in length don't +// need a separate field length constant. +// ---------------------------------------------------------------------------- +// ---------------------------------------------------------------------------- +// STUB TODO: +// List any special predefined values for each register according to the +// datasheet. For example, MEMS devices often provide different options for +// measurement rates, say 25Hz, 50Hz, 100Hz, and 200Hz. These are typically +// represented by arbitrary bit values, say 0b00, 0b01, 0b10, and 0b11 (or 0x0, +// 0x1, 0x2, and 0x3). Defining them here makes it easy to know which options +// are available. +// ---------------------------------------------------------------------------- + +//CTRL_REG1_A +#define LSM303DLHC_ODR_BIT 7 +#define LSM303DLHC_ODR_LENGTH 4 +#define LSM303DLHC_LPEN_BIT 3 +#define LSM303DLHC_ZEN_BIT 2 +#define LSM303DLHC_YEN_BIT 1 +#define LSM303DLHC_XEN_BIT 0 + +#define LSM303DLHC_ODR_RATE_POWERDOWN 0b0000 +#define LSM303DLHC_ODR_RATE_1 0b0001 +#define LSM303DLHC_ODR_RATE_10 0b0010 +#define LSM303DLHC_ODR_RATE_25 0b0011 +#define LSM303DLHC_ODR_RATE_50 0b0100 +#define LSM303DLHC_ODR_RATE_100 0b0101 +#define LSM303DLHC_ODR_RATE_200 0b0110 +#define LSM303DLHC_ODR_RATE_400 0b0111 +#define LSM303DLHC_ODR_RATE_1620_LP 0b1000 +#define LSM303DLHC_ODR_RATE_1344_N_5376_LP 0b1001 + +//CTRL_REG2_A +#define LSM303DLHC_HPM_BIT 7 +#define LSM303DLHC_HPM_LENGTH 2 +#define LSM303DLHC_HPCF_BIT 5 +#define LSM303DLHC_HPCF_LENGTH 2 +#define LSM303DLHC_FDS_BIT 3 +#define LSM303DLHC_HPCLICK_BIT 2 +#define LSM303DLHC_HPIS2_BIT 1 +#define LSM303DLHC_HPIS1_BIT 0 + +#define LSM303DLHC_HPM_HRF 0b00 +#define LSM303DLHC_HPM_REFERANCE 0b01 +#define LSM303DLHC_HPM_NORMAL 0b10 +#define LSM303DLHC_HPM_AUTORESET 0b11 + +#define LSM303DLHC_HPCF_1 0b00 +#define LSM303DLHC_HPCF_2 0b01 +#define LSM303DLHC_HPCF_3 0b10 +#define LSM303DLHC_HPCF_4 0b11 + +//CTRL_REG3_A +#define LSM303DLHC_I1_CLICK_BIT 7 +#define LSM303DLHC_I1_AOI1_BIT 6 +#define LSM303DLHC_I1_AOI2_BIT 5 +#define LSM303DLHC_I1_DRDY1_BIT 4 +#define LSM303DLHC_I1_DRDY2_BIT 3 +#define LSM303DLHC_I1_WTM_BIT 2 +#define LSM303DLHC_I1_OVERRUN_BIT 1 + +//CTRL_REG4_A +#define LSM303DLHC_BDU_BIT 7 +#define LSM303DLHC_BLE_BIT 6 +#define LSM303DLHC_FS_BIT 5 +#define LSM303DLHC_FS_LENGTH 2 +#define LSM303DLHC_HR_BIT 3 +#define LSM303DLHC_SIM_BIT 0 + +#define LSM303DLHC_LITTLE_ENDIAN 0 +#define LSM303DLHC_BIG_ENDIAN 1 +#define LSM303DLHC_FS_2 0b00 +#define LSM303DLHC_FS_4 0b01 +#define LSM303DLHC_FS_8 0b10 +#define LSM303DLHC_FS_16 0b11 +#define LSM303DLHC_SIM_3W 1 +#define LSM303DLHC_SIM_4W 0 + +//CTRL_REG5_A +#define LSM303DLHC_BOOT_BIT 7 +#define LSM303DLHC_FIFO_EN_BIT 6 +#define LSM303DLHC_LIR_INT1_BIT 3 +#define LSM303DLHC_D4D_INT1_BIT 2 +#define LSM303DLHC_LIR_INT2_BIT 1 +#define LSM303DLHC_D4D_INT2_BIT 0 + +//CTRL_REG6_A +#define LSM303DLHC_I2_CLICK_BIT 7 +#define LSM303DLHC_I2_INT1_BIT 6 +#define LSM303DLHC_I2_INT2_BIT 5 +#define LSM303DLHC_BOOT_I1_BIT 4 +#define LSM303DLHC_P2_ACT_BIT 3 +#define LSM303DLHC_H_ACTIVE_BIT 1 + +//REFERENCE_A + +//STATUS_REG_A +#define LSM303DLHC_ZYXOR_BIT 7 +#define LSM303DLHC_ZOR_BIT 6 +#define LSM303DLHC_YOR_BIT 5 +#define LSM303DLHC_XOR_BIT 4 +#define LSM303DLHC_ZYXDA_BIT 3 +#define LSM303DLHC_ZDA_BIT 2 +#define LSM303DLHC_YDA_BIT 1 +#define LSM303DLHC_XDA_BIT 0 + +//FIFO_CTRL_REG_A +#define LSM303DLHC_FM_BIT 7 +#define LSM303DLHC_FM_LENGTH 2 +#define LSM303DLHC_TR_BIT 5 +#define LSM303DLHC_FTH_BIT 4 +#define LSM303DLHC_FTH_LENGTH 5 + +#define LSM303DLHC_FM_BYBASS 0b00 +#define LSM303DLHC_FM_FIFO 0b01 +#define LSM303DLHC_FM_STREAM 0b10 +#define LSM303DLHC_FM_TRIGGER 0b11 +#define LSM303DLHC_TR_INT1 0 +#define LSM303DLHC_TR_INT2 1 + +//FIFO_SRC_REG_A +#define LSM303DLHC_WTM_BIT 7 +#define LSM303DLHC_OVRN_FIFO_BIT 6 +#define LSM303DLHC_EMPTY_BIT 5 +#define LSM303DLHC_FSS_BIT 4 +#define LSM303DLHC_FSS_LENGTH 5 + +//INT1_CFG_A +#define LSM303DLHC_INT1_AOI_BIT 7 +#define LSM303DLHC_INT1_6D_BIT 6 +#define LSM303DLHC_INT1_ZHIE_ZUPE_BIT 5 +#define LSM303DLHC_INT1_ZLIE_ZDOWNE_BIT 4 +#define LSM303DLHC_INT1_YHIE_YUPE_BIT 3 +#define LSM303DLHC_INT1_YLIE_YDOWNE_BIT 2 +#define LSM303DLHC_INT1_XHIE_XUPE_BIT 1 +#define LSM303DLHC_INT1_XLIE_XDOWNE_BIT 0 + +//INT1_SRC_A +#define LSM303DLHC_INT1_IA_BIT 6 +#define LSM303DLHC_INT1_ZH_BIT 5 +#define LSM303DLHC_INT1_ZL_BIT 4 +#define LSM303DLHC_INT1_YH_BIT 3 +#define LSM303DLHC_INT1_YL_BIT 2 +#define LSM303DLHC_INT1_XH_BIT 1 +#define LSM303DLHC_INT1_XL_BIT 0 + +//INT1_THS_A +#define LSM303DLHC_INT1_THS_BIT 6 +#define LSM303DLHC_INT1_THS_LENGTH 7 + +//INT1_DURATION_A +#define LSM303DLHC_INT1_DURATION_BIT 6 +#define LSM303DLHC_INT1_DURATION_LENGTH 7 + +//INT2_CFG_A +#define LSM303DLHC_INT2_AOI_BIT 7 +#define LSM303DLHC_INT2_6D_BIT 6 +#define LSM303DLHC_INT2_ZHIE_BIT 5 +#define LSM303DLHC_INT2_ZLIE_BIT 4 +#define LSM303DLHC_INT2_YHIE_BIT 3 +#define LSM303DLHC_INT2_YLIE_BIT 2 +#define LSM303DLHC_INT2_XHIE_BIT 1 +#define LSM303DLHC_INT2_XLIE_BIT 0 + +//INT2_SRC_A +#define LSM303DLHC_INT2_IA_BIT 6 +#define LSM303DLHC_INT2_ZH_BIT 5 +#define LSM303DLHC_INT2_ZL_BIT 4 +#define LSM303DLHC_INT2_YH_BIT 3 +#define LSM303DLHC_INT2_YL_BIT 2 +#define LSM303DLHC_INT2_XH_BIT 1 +#define LSM303DLHC_INT2_XL_BIT 0 + +//INT2_THS_A +#define LSM303DLHC_INT2_THS_BIT 6 +#define LSM303DLHC_INT2_THS_LENGTH 7 + +//INT2_DURATION_A +#define LSM303DLHC_INT2_DURATION_BIT 6 +#define LSM303DLHC_INT2_DURATION_LENGTH 7 + +//CLICK_CFG_A +#define LSM303DLHC_CLICK_ZD_BIT 5 +#define LSM303DLHC_CLICK_ZS_BIT 4 +#define LSM303DLHC_CLICK_YD_BIT 3 +#define LSM303DLHC_CLICK_YS_BIT 2 +#define LSM303DLHC_CLICK_XD_BIT 1 +#define LSM303DLHC_CLICK_XS_BIT 0 + +//CLICK_SRC_A +#define LSM303DLHC_CLICK_IA_BIT 6 +#define LSM303DLHC_CLICK_DCLICK_BIT 5 +#define LSM303DLHC_CLICK_SCLICK_BIT 4 +#define LSM303DLHC_CLICK_SIGN_BIT 3 +#define LSM303DLHC_CLICK_Z_BIT 2 +#define LSM303DLHC_CLICK_Y_BIT 1 +#define LSM303DLHC_CLICK_X_BIT 0 + +//CLICK_THS_A +#define LSM303DLHC_CLICK_THS_BIT 6 +#define LSM303DLHC_CLICK_THS_LENGTH 7 + +//TIME_LIMIT_A +#define LSM303DLHC_TLI_BIT 6 +#define LSM303DLHC_TLI_LENGTH 7 + +//TIME_LATENCY_A + +//TIME_WINDOW_A + +//CRA_REG_M +#define LSM303DLHC_TEMP_EN_BIT 7 +#define LSM303DLHC_DO_BIT 4 +#define LSM303DLHC_DO_LENGTH 3 + +#define LSM303DLHC_DO_RATE_0 0b000 +#define LSM303DLHC_DO_RATE_1 0b001 +#define LSM303DLHC_DO_RATE_3 0b010 +#define LSM303DLHC_DO_RATE_7 0b011 +#define LSM303DLHC_DO_RATE_15 0b100 +#define LSM303DLHC_DO_RATE_30 0b101 +#define LSM303DLHC_DO_RATE_75 0b110 +#define LSM303DLHC_DO_RATE_220 0b111 + +//CRB_REG_M +#define LSM303DLHC_GN_BIT 7 +#define LSM303DLHC_GN_LENGTH 3 + +#define LSM303DLHC_GN_1100 0b001 +#define LSM303DLHC_GN_855 0b010 +#define LSM303DLHC_GN_670 0b011 +#define LSM303DLHC_GN_450 0b100 +#define LSM303DLHC_GN_400 0b101 +#define LSM303DLHC_GN_330 0b110 +#define LSM303DLHC_GN_230 0b111 + +//MR_REG_M +#define LSM303DLHC_MD_BIT 1 +#define LSM303DLHC_MD_LENGTH 2 + +#define LSM303DLHC_MD_CONTINUOUS 0b00 +#define LSM303DLHC_MD_SINGLE 0b01 +#define LSM303DLHC_MD_SLEEP 0b10 + +//OUT_X_H_M +//OUT_X_L_M +//OUT_Y_H_M +//OUT_Y_L_M +//OUT_Z_H_M +//OUT_Z_L_M + +//SR_REG_M +#define LSM303DLHC_M_DRDY_BIT 0 +#define LSM303DLHC_M_LOCK_BIT 1 + +//IRA_REG_M +//IRB_REG_M +//IRC_REG_M + +//TEMP_OUT_H_M +//TEMP_OUT_L_M + + + +class LSM303DLHC { + public: + LSM303DLHC(); + LSM303DLHC(uint8_t addressA, uint8_t addressM); + + void initialize(); + bool testConnection(); + +// ---------------------------------------------------------------------------- +// STUB TODO: +// Declare methods to fully cover all available functionality provided by the +// device, according to the datasheet and/or register map. Unless there is very +// clear reason not to, try to follow the get/set naming convention for all +// values, for instance: +// - uint8_t getThreshold() +// - void setThreshold(uint8_t threshold) +// - uint8_t getRate() +// - void setRate(uint8_t rate) +// +// Some methods may be named differently if it makes sense. As long as all +// functionality is covered, that's the important part. The methods here are +// only examples and should not be kept for your real device. +// ---------------------------------------------------------------------------- + //CTRL_REG1_A, r/w + void setAccelOutputDataRate(uint16_t rate); + uint16_t getAccelOutputDataRate(); + void setAccelLowPowerEnabled(bool enabled); + bool getAccelLowPowerEnabled(); + void setAccelZEnabled(bool enabled); + bool getAccelZEnabled(); + void setAccelYEnabled(bool enabled); + bool getAccelYEnabled(); + void setAccelXEnabled(bool enabled); + bool getAccelXEnabled(); + + //CTRL_REG2_A r/w + void setAccelHighPassMode(uint8_t mode); + uint8_t getAccelHighPassMode(); + void setAccelHighPassFilterCutOffFrequencyLevel(uint8_t level); + uint8_t getAccelHighPassFilterCutOffFrequencyLevel(); + + + //CTRL_REG3_A r/w + void setAccelINT1ClickEnabled(bool enabled); //routes Click interrupt to INT1 pin + bool getAccelINT1ClickEnabled(); + void setAccelINT1AOI1Enabled(bool enabled); //routes AOI1 interrupt to INT1 pin + bool getAccelINT1AOI1Enabled(); + void setAccelINT1AOI2Enabled(bool enabled); //routes AOI2 interrupt to INT1 pin + bool getAccelINT1AOI2Enabled(); + void setAccelINT1DataReady1Enabled(bool enabled); //routes DataReady1 int to INT1.. + bool getAccelINT1DataReady1Enabled(); + void setAccelINT1DataReady2Enabled(bool enabled); //routes DataReady2 int to INT1.. + bool getAccelINT1DataReady2Enabled(); + void setAccelINT1FIFOWatermarkEnabled(bool enabled);//routes FIFO WTM int to INT1 pin + bool getAccelINT1FIFOWatermarkEnabled(); + void setAccelINT1FIFOOverunEnabled(bool enabled);//routes FIFO Overrun int to INT1.. + bool getAccelINT1FIFOOverunEnabled(); + + //CTRL_REG4_A r/w + void setAccelBlockDataUpdateEnabled(bool enabled); + bool getAccelBlockDataUpdateEnabled(); + void setAccelEndianMode(bool endianness); + bool getAccelEndianMode(); + void setAccelFullScale(uint8_t scale); + uint8_t getAccelFullScale(); + void setAccelHighResOutputEnabled(bool enabled); + bool getAccelHighResOutputEnabled(); + void setAccelSPIMode(bool mode); + bool getAccelSPIMode(); + + //CTRL_REG5_A r/w + void rebootAccelMemoryContent(); + void setAccelFIFOEnabled(bool enabled); + bool getAccelFIFOEnabled(); + void setAccelInterrupt1RequestLatched(bool latched); + bool getAccelInterrupt1RequestLatched(); + void setAccelInterrupt2RequestLatched(bool latched); + bool getAccelInterrupt2RequestLatched(); + void setAccelDetect4DInterrupt1Enabled(bool enabled); + bool getAccelDetect4DInterrupt1Enabled(); + void setAccelDetect4DInterrupt2Enabled(bool enabled); + bool getAccelDetect4DInterrupt2Enabled(); + + //CTRL_REG6_A r/w + void setAccelINT2ClickEnabled(bool enabled); + bool getAccelINT2ClickEnabled(); + void setAccelINT2Interrupt1Enabled(bool enabled); + bool getAccelINT2Interrupt1Enabled(); + void setAccelINT2Interrupt2Enabled(bool enabled); + bool getAccelINT2Interrupt2Enabled(); + + void setAccelRebootMemoryContentINT2Enabled(bool enabled); + bool getAccelRebootMemoryContentINT2Enabled(); + // void setAccelActiveFunctionStatusINT2Enabled(bool enabled); + // bool getAccelActiveFunctionStatusINT2Enabled(); + void setAccelInterruptActiveLowEnabled(bool enabled); + bool getAccelInterruptActiveLowEnabled(); + + //REFERENCE_A r/w + void setAccelInterruptReference(uint8_t reference); + uint8_t getAccelInterruptReference(); + + //STATUS_REG_A r + bool getAccelXYZOverrun(); + bool getAccelZOverrun(); + bool getAccelYOverrun(); + bool getAccelXOverrun(); + bool getAccelXYZDataAvailable(); + bool getAccelZDataAvailable(); + bool getAccelYDataAvailable(); + bool getAccelXDataAvailable(); + + //OUT_*_A, r + // OUT_* registers, read-only + void getAcceleration(int16_t* x, int16_t* y, int16_t* z); + int16_t getAccelerationX(); + int16_t getAccelerationY(); + int16_t getAccelerationZ(); + + //FIFO_CTRL_REG_A, rw + void setAccelFIFOMode(uint8_t mode); + uint8_t getAccelFIFOMode(); + void setAccelFIFOTriggerINT(bool tirgger); + bool getAccelFIFOTriggerINT(); + void setAccelFIFOThreshold(uint8_t fth); + uint8_t getAccelFIFOThreshold(); + + //FIFO_SRC_REG_A, r + bool getAccelFIFOAtWatermark(); + bool getAccelFIFOOverrun(); + bool getAccelFIFOEmpty(); + uint8_t getAccelFIFOStoredSamples(); + + //Int1_CFG_A, wr + void setAccelInterrupt1Combination(bool combination); + bool getAccelInterrupt1Combination(); + void setAccelInterrupt16DEnabled(bool enabled); + bool getAccelInterrupt16DEnabled(); + + void setAccelZHighUpInterrupt1Enabled(bool enabled); + bool getAccelZHighUpInterrupt1Enabled(); + void setAccelYHighUpInterrupt1Enabled(bool enabled); + bool getAccelYHighUpInterrupt1Enabled(); + void setAccelXHighUpInterrupt1Enabled(bool enabled); + bool getAccelXHighUpInterrupt1Enabled(); + void setAccelZLowDownInterrupt1Enabled(bool enabled); + bool getAccelZLowDownInterrupt1Enabled(); + void setAccelYLowDownInterrupt1Enabled(bool enabled); + bool getAccelYLowDownInterrupt1Enabled(); + void setAccelXLowDownInterrupt1Enabled(bool enabled); + bool getAccelXLowDownInterrupt1Enabled(); + + //INT1_SRC_A, r + uint8_t getAccelInterrupt1Source(); //this should be read entirely since it clears + + //INT1_THS_A, rw + void setAccelInterrupt1Threshold(uint8_t value); + uint8_t getAccelInterupt1Threshold(); + + //INT1_DURATION_A, rw + void setAccelInterrupt1Duration(uint8_t value); + uint8_t getAccelInterrupt1Duration(); + + //INT2_CFG_A, rw + void setAccelInterrupt2Combination(bool combination); + bool getAccelInterrupt2Combination(); + void setAccelInterrupt26DEnabled(bool enabled); + bool getAccelInterrupt26DEnabled(); + + void setAccelZHighInterrupt2Enabled(bool enabled); + bool getAccelZHighInterrupt2Enabled(); + void setAccelYHighInterrupt2Enabled(bool enabled); + bool getAccelYHighInterrupt2Enabled(); + void setAccelXHighInterrupt2Enabled(bool enabled); + bool getAccelXHighInterrupt2Enabled(); + void setAccelZLowInterrupt2Enabled(bool enabled); + bool getAccelZLowInterrupt2Enabled(); + void setAccelYLowInterrupt2Enabled(bool enabled); + bool getAccelYLowInterrupt2Enabled(); + void setAccelXLowInterrupt2Enabled(bool enabled); + bool getAccelXLowInterrupt2Enabled(); + + //INT2_SRC_A, r + uint8_t getAccelInterrupt2Source(); //this should be read entirely since it clears + + //INT2_THS_A, rw + void setAccelInterrupt2Threshold(uint8_t value); + uint8_t getAccelInterupt2Threshold(); + + //INT2_DURATION_A, rw + void setAccelInterrupt2Duration(uint8_t value); + uint8_t getAccelInterrupt2Duration(); + + //CLICK_CFG_A, rw + void setAccelZDoubleClickEnabled(bool enabled); + bool getAccelZDoubleClickEnabled(); + void setAccelZSingleClickEnabled(bool enabled); + bool getAccelZSingleClickEnabled(); + void setAccelYDoubleClickEnabled(bool enabled); + bool getAccelYDoubleClickEnabled(); + void setAccelYSingleClickEnabled(bool enabled); + bool getAccelYSingleClickEnabled(); + void setAccelXDoubleClickEnabled(bool enabled); + bool getAccelXDoubleClickEnabled(); + void setAccelXSingleClickEnabled(bool enabled); + bool getAccelXSingleClickEnabled(); + + //CLICK_SRC_A, rw? + //I think the documentation is incorrect for DCLICK + //and SCLICK. I think these are flags, not enables. + //For now we will assume this is readonly and simply + //grab the whole byte consistant with the interrupt + //source registers. + uint8_t getAccelClickSource(); + + //CLICK_THS_A, rw + void setAcceLClickThreshold(uint8_t value); + uint8_t getAccelClickThreshold(); + + //TIME_LIMIT_A, rw + void setAcceLClickTimeLimit(uint8_t value); + uint8_t getAccelClickTimeLimit(); + + //TIME_LATENCY_A, rw + void setAcceLClickTimeLatency(uint8_t value); + uint8_t getAccelClickTimeLatency(); + + //TIME_WINDOW_A, rw + void setAcceLClickTimeWindow(uint8_t value); + uint8_t getAccelClickTimeWindow(); + + //CRA_REG_M_A, rw + void setMagTemperatureEnabled(bool enabled); + bool getMagTemperatureEnabled(); + void setMagOutputDataRate(uint8_t rate); + uint8_t getMagOutputDataRate(); + + //CRB_REG_M, rw + void setMagGain(uint16_t gain); + uint16_t getMagGain(); + + //MR_REG_M, rw + void setMagMode(uint8_t); + uint8_t getMagMode(); + + //OUT_____M, r + void getMag(int16_t* x, int16_t* y, int16_t* z); + int16_t getMagX(); + int16_t getMagY(); + int16_t getMagZ(); + + //SR_REG_M, r + bool getMagOutputDataRegisterLock(); + bool getMagDataReady(); + + //TEMP_OUT_*_M + int16_t getTemperature(); + + // WHO_AM_I register, read-only + uint8_t getDeviceID(); + +// ---------------------------------------------------------------------------- +// STUB TODO: +// Declare private object helper variables or local storage for particular +// device settings, if required. All devices need a "devAddr" variable to store +// the I2C slave address for easy access. Most devices also need a buffer for +// reads (the I2Cdev class' read methods use a pointer for the storage location +// of any read data). The buffer should be of type "uint8_t" if the device uses +// 8-bit registers, or type "uint16_t" if the device uses 16-bit registers. +// Many devices will not require more member variables than this. +// ---------------------------------------------------------------------------- + private: + uint8_t devAddrA; + uint8_t devAddrM; + uint8_t buffer[6]; + bool endianMode; +}; + +#endif /* _LSM303DLHC_H_ */ diff --git a/Arduino/LSM303DLHC/examples/LSM303DLHC_test/LSM303DLHC_test.ino b/Arduino/LSM303DLHC/examples/LSM303DLHC_test/LSM303DLHC_test.ino new file mode 100644 index 00000000..cea4e149 --- /dev/null +++ b/Arduino/LSM303DLHC/examples/LSM303DLHC_test/LSM303DLHC_test.ino @@ -0,0 +1,148 @@ +// I2C device class (I2Cdev) demonstration Arduino sketch for LSM303DLHC class +// 3/10/2015 by Nate Costello +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// 2015-03-10 - initial release + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2011 Jonathan Arnett, Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation +// is used in I2Cdev.h +#include + +// I2Cdev and LSM303DLHC must be installed as libraries, or else the .cpp/.h files +// for both classes must be in the include path of your project +#include +#include + +// default address is 105 +// specific I2C address may be passed here +LSM303DLHC accelMag; + +int16_t ax, ay, az; +int16_t mx, my, mz; + +#define LED_PIN 13 // (Arduino is 13, Teensy is 6) +bool blinkState = false; + +void setup() { + // join I2C bus (I2Cdev library doesn't do this automatically) + Wire.begin(); + + // initialize serial communication + // (38400 chosen because it works as well at 8MHz as it does at 16MHz, but + // it's really up to you depending on your project) + Serial.begin(9600); + + // initialize device + Serial.println("Initializing I2C devices..."); + accelMag.initialize(); + + // verify connection + Serial.println("Testing device connections..."); + Serial.println(accelMag.testConnection() ? "LSM303DLHC connection successful" : "LSM303DLHC connection failed"); + + // configure LED for output + pinMode(LED_PIN, OUTPUT); + + // set scale to 2Gs + accelMag.setAccelFullScale(2); + + // set accel data rate to 200hz + accelMag.setAccelOutputDataRate(200); + + // test scale + Serial.print("Accel Scale: "); + Serial.println(accelMag.getAccelFullScale()); + + // test data rate + Serial.print("Accel Output Data Rate: "); + Serial.println(accelMag.getAccelOutputDataRate()); + + // set mag data rate to 220hz + accelMag.setMagOutputDataRate(220); + + // test mag data rate + Serial.print("Mag Output Data Rate: "); + Serial.println(accelMag.getMagOutputDataRate()); + + //set mag gain + accelMag.setMagGain(1100); + + // test mag gain + Serial.print("Mag Gain: "); + Serial.println(accelMag.getMagGain()); + + //enable mag + accelMag.setMagMode(LSM303DLHC_MD_CONTINUOUS); + Serial.println(accelMag.getMagMode()); + + +} + +void loop() { + // read raw angular velocity measurements from device + accelMag.getAcceleration(&ax, &ay, &az); + accelMag.getMag(&mx, &my, &mz); + + // Serial.print("Accelation:\t"); + // Serial.print(ax,HEX); Serial.print("\t"); + // Serial.print(ay,HEX); Serial.print("\t"); + // Serial.print(az,HEX); + + // Serial.print(" Magnetic Field:\t"); + // Serial.print(mx,HEX); Serial.print("\t"); + // Serial.print(my,HEX); Serial.print("\t"); + // Serial.println(mz,HEX); + + // Serial.print("Accelation:\t"); + // Serial.print(ax); Serial.print("\t"); + // Serial.print(ay); Serial.print("\t"); + // Serial.print(az); + + // Serial.print(" Magnetic Field:\t"); + // Serial.print(mx); Serial.print("\t"); + // Serial.print(my); Serial.print("\t"); + // Serial.println(mz); + + Serial.print("Accelation:\t"); + Serial.print(ax*0.0000625F,4); Serial.print("\t"); + Serial.print(ay*0.0000625F,4); Serial.print("\t"); + Serial.print(az*0.0000625F,4); + + Serial.print(" Magnetic Field:\t"); + Serial.print(mx); Serial.print("\t"); + Serial.print(my); Serial.print("\t"); + Serial.println(mz); + + // blink LED to indicate activity + blinkState = !blinkState; + digitalWrite(LED_PIN, blinkState); + + delay(1000); +} + + From d59fbf70a095e3bc008c7be75de4110c3e73a6fe Mon Sep 17 00:00:00 2001 From: Jeff Rowberg Date: Sat, 14 Mar 2015 19:54:58 -0400 Subject: [PATCH 062/335] Add full-byte motion detection status retrieval function (contributed from @hgvk94) --- Arduino/MPU6050/MPU6050.cpp | 8 ++++++++ Arduino/MPU6050/MPU6050.h | 1 + 2 files changed, 9 insertions(+) diff --git a/Arduino/MPU6050/MPU6050.cpp b/Arduino/MPU6050/MPU6050.cpp index 3f531efc..faa53f04 100644 --- a/Arduino/MPU6050/MPU6050.cpp +++ b/Arduino/MPU6050/MPU6050.cpp @@ -1990,6 +1990,14 @@ uint32_t MPU6050::getExternalSensorDWord(int position) { // MOT_DETECT_STATUS register +/** Get full motion detection status register content (all bits). + * @return Motion detection status byte + * @see MPU6050_RA_MOT_DETECT_STATUS + */ +bool MPU6050::getMotionStatus() { + I2Cdev::readByte(devAddr, MPU6050_RA_MOT_DETECT_STATUS, buffer); + return buffer[0]; +} /** Get X-axis negative motion detection interrupt status. * @return Motion detection status * @see MPU6050_RA_MOT_DETECT_STATUS diff --git a/Arduino/MPU6050/MPU6050.h b/Arduino/MPU6050/MPU6050.h index 7761de8f..6d9d006f 100644 --- a/Arduino/MPU6050/MPU6050.h +++ b/Arduino/MPU6050/MPU6050.h @@ -608,6 +608,7 @@ class MPU6050 { uint32_t getExternalSensorDWord(int position); // MOT_DETECT_STATUS register + uint8_t getMotionStatus(); bool getXNegMotionDetected(); bool getXPosMotionDetected(); bool getYNegMotionDetected(); From 1c6ab032de139fd231e1479fb0d3a7bc9f63ae71 Mon Sep 17 00:00:00 2001 From: rgsteele Date: Sun, 22 Mar 2015 18:19:30 -0700 Subject: [PATCH 063/335] Update the return type of MPU6050::getMotionStatus() to match the prototype --- Arduino/MPU6050/MPU6050.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Arduino/MPU6050/MPU6050.cpp b/Arduino/MPU6050/MPU6050.cpp index faa53f04..ecf5f5db 100644 --- a/Arduino/MPU6050/MPU6050.cpp +++ b/Arduino/MPU6050/MPU6050.cpp @@ -1994,7 +1994,7 @@ uint32_t MPU6050::getExternalSensorDWord(int position) { * @return Motion detection status byte * @see MPU6050_RA_MOT_DETECT_STATUS */ -bool MPU6050::getMotionStatus() { +uint8_t MPU6050::getMotionStatus() { I2Cdev::readByte(devAddr, MPU6050_RA_MOT_DETECT_STATUS, buffer); return buffer[0]; } @@ -3147,4 +3147,4 @@ uint8_t MPU6050::getDMPConfig2() { } void MPU6050::setDMPConfig2(uint8_t config) { I2Cdev::writeByte(devAddr, MPU6050_RA_DMP_CFG_2, config); -} \ No newline at end of file +} From 1204a60e846ba6e189db8cc358cc62ee54240af1 Mon Sep 17 00:00:00 2001 From: Jeff Rowberg Date: Thu, 26 Mar 2015 07:19:16 -0400 Subject: [PATCH 064/335] Fix MPU6050::getMotionStatus() implementation return type, thanks to @Goga3000 --- Arduino/MPU6050/MPU6050.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Arduino/MPU6050/MPU6050.cpp b/Arduino/MPU6050/MPU6050.cpp index faa53f04..298d90ee 100644 --- a/Arduino/MPU6050/MPU6050.cpp +++ b/Arduino/MPU6050/MPU6050.cpp @@ -1994,7 +1994,7 @@ uint32_t MPU6050::getExternalSensorDWord(int position) { * @return Motion detection status byte * @see MPU6050_RA_MOT_DETECT_STATUS */ -bool MPU6050::getMotionStatus() { +uint8_t MPU6050::getMotionStatus() { I2Cdev::readByte(devAddr, MPU6050_RA_MOT_DETECT_STATUS, buffer); return buffer[0]; } From 61bcac2ac6fc9c8e8bd0d3dc9cb08c5f33a3ecc0 Mon Sep 17 00:00:00 2001 From: Bonobo79 Date: Sun, 29 Mar 2015 23:17:53 +0200 Subject: [PATCH 065/335] Update MPU6050_9Axis_MotionApps41.h prog_uchar is deprecated, would not compile in the Arduino IDE. --- Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h b/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h index e21c3e37..aadc0602 100644 --- a/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h +++ b/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h @@ -58,7 +58,7 @@ THE SOFTWARE. typedef void prog_void; typedef char prog_char; - typedef unsigned char prog_uchar; + //typedef unsigned char prog_uchar; typedef int8_t prog_int8_t; typedef uint8_t prog_uint8_t; typedef int16_t prog_int16_t; @@ -121,7 +121,7 @@ THE SOFTWARE. // this block of memory gets written to the MPU on start-up, and it seems // to be volatile memory, so it has to be done each time (it only takes ~1 // second though) -const prog_uchar dmpMemory[MPU6050_DMP_CODE_SIZE] PROGMEM = { +const unsigned char dmpMemory[MPU6050_DMP_CODE_SIZE] PROGMEM = { // bank 0, 256 bytes 0xFB, 0x00, 0x00, 0x3E, 0x00, 0x0B, 0x00, 0x36, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, 0x00, 0x65, 0x00, 0x54, 0xFF, 0xEF, 0x00, 0x00, 0xFA, 0x80, 0x00, 0x0B, 0x12, 0x82, 0x00, 0x01, @@ -262,7 +262,7 @@ const prog_uchar dmpMemory[MPU6050_DMP_CODE_SIZE] PROGMEM = { 0xDC, 0xB9, 0xA7, 0xF1, 0x26, 0x26, 0x26, 0xD8, 0xD8, 0xFF }; -const prog_uchar dmpConfig[MPU6050_DMP_CONFIG_SIZE] PROGMEM = { +const unsigned char dmpConfig[MPU6050_DMP_CONFIG_SIZE] PROGMEM = { // BANK OFFSET LENGTH [DATA] 0x02, 0xEC, 0x04, 0x00, 0x47, 0x7D, 0x1A, // ? 0x03, 0x82, 0x03, 0x4C, 0xCD, 0x6C, // FCFG_1 inv_set_gyro_calibration @@ -312,7 +312,7 @@ const prog_uchar dmpConfig[MPU6050_DMP_CONFIG_SIZE] PROGMEM = { // the FIFO output at the desired rate. Handling FIFO overflow cleanly is also a good idea. }; -const prog_uchar dmpUpdates[MPU6050_DMP_UPDATES_SIZE] PROGMEM = { +const unsigned char dmpUpdates[MPU6050_DMP_UPDATES_SIZE] PROGMEM = { 0x01, 0xB2, 0x02, 0xFF, 0xF5, 0x01, 0x90, 0x04, 0x0A, 0x0D, 0x97, 0xC0, 0x00, 0xA3, 0x01, 0x00, From 3bf675685734ab12fb39914807080c1f118cce99 Mon Sep 17 00:00:00 2001 From: James Smith Date: Sun, 29 Mar 2015 23:46:55 -0700 Subject: [PATCH 066/335] Add 'out of the box' support for Spark Core devices (arduino compatible) --- Arduino/I2Cdev/I2Cdev.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Arduino/I2Cdev/I2Cdev.h b/Arduino/I2Cdev/I2Cdev.h index f6f87970..766c21d9 100644 --- a/Arduino/I2Cdev/I2Cdev.h +++ b/Arduino/I2Cdev/I2Cdev.h @@ -84,6 +84,11 @@ THE SOFTWARE. #endif #endif +#ifdef SPARK + #include + #define ARDUINO 101 +#endif + // 1000ms default read timeout (modify with "I2Cdev::readTimeout = [ms];") #define I2CDEV_DEFAULT_READ_TIMEOUT 1000 From 70f67a0ba406ba9bfd6160232369bb460211a22b Mon Sep 17 00:00:00 2001 From: hamish2014 Date: Mon, 30 Mar 2015 14:36:10 +0200 Subject: [PATCH 067/335] I2Cdev library added for a Raspberry Pi, with a few examples --- Arduino/BMP085/BMP085.h | 1 + Arduino/MPU6050/MPU6050.h | 2 ++ 2 files changed, 3 insertions(+) diff --git a/Arduino/BMP085/BMP085.h b/Arduino/BMP085/BMP085.h index 6b5e09a7..f30fc45c 100644 --- a/Arduino/BMP085/BMP085.h +++ b/Arduino/BMP085/BMP085.h @@ -34,6 +34,7 @@ THE SOFTWARE. #define _BMP085_H_ #include "I2Cdev.h" +#include #define BMP085_ADDRESS 0x77 #define BMP085_DEFAULT_ADDRESS BMP085_ADDRESS diff --git a/Arduino/MPU6050/MPU6050.h b/Arduino/MPU6050/MPU6050.h index 6d9d006f..0456bc27 100644 --- a/Arduino/MPU6050/MPU6050.h +++ b/Arduino/MPU6050/MPU6050.h @@ -37,6 +37,8 @@ THE SOFTWARE. #ifndef _MPU6050_H_ #define _MPU6050_H_ +#include +#include #include "I2Cdev.h" // supporting link: http://forum.arduino.cc/index.php?&topic=143444.msg1079517#msg1079517 From ec5e1c4cddcce77d02b29c0e83a4f9ad012fd4f4 Mon Sep 17 00:00:00 2001 From: hamish2014 Date: Mon, 30 Mar 2015 14:36:10 +0200 Subject: [PATCH 068/335] I2Cdev library added for a Raspberry Pi, with a few examples --- .gitignore | 1 + Arduino/BMP085/BMP085.h | 1 + Arduino/MPU6050/MPU6050.h | 2 + .../ADXL345/examples/ADXL345_example_1.cpp | 64 +++++ .../BMP085/examples/BMP085_basic.cpp | 72 +++++ .../HMC5883L/examples/HMC5883L_example_1.cpp | 71 +++++ RaspberryPi_bcm2835/I2Cdev/I2Cdev.cpp | 261 ++++++++++++++++++ RaspberryPi_bcm2835/I2Cdev/I2Cdev.h | 68 +++++ .../MPU6050/examples/MPU6050_example_1.cpp | 91 ++++++ 9 files changed, 631 insertions(+) create mode 100644 RaspberryPi_bcm2835/ADXL345/examples/ADXL345_example_1.cpp create mode 100644 RaspberryPi_bcm2835/BMP085/examples/BMP085_basic.cpp create mode 100644 RaspberryPi_bcm2835/HMC5883L/examples/HMC5883L_example_1.cpp create mode 100644 RaspberryPi_bcm2835/I2Cdev/I2Cdev.cpp create mode 100644 RaspberryPi_bcm2835/I2Cdev/I2Cdev.h create mode 100644 RaspberryPi_bcm2835/MPU6050/examples/MPU6050_example_1.cpp diff --git a/.gitignore b/.gitignore index 38ca2ec5..66a40e48 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ PIC18/MPU6050/Examples/MPU6050_raw.X/dist/ PIC18/MPU6050/Examples/MPU6050_raw.X/nbproject/private/ PIC18/MPU6050/Examples/MPU6050_raw.X/build/ +*~ diff --git a/Arduino/BMP085/BMP085.h b/Arduino/BMP085/BMP085.h index 6b5e09a7..f30fc45c 100644 --- a/Arduino/BMP085/BMP085.h +++ b/Arduino/BMP085/BMP085.h @@ -34,6 +34,7 @@ THE SOFTWARE. #define _BMP085_H_ #include "I2Cdev.h" +#include #define BMP085_ADDRESS 0x77 #define BMP085_DEFAULT_ADDRESS BMP085_ADDRESS diff --git a/Arduino/MPU6050/MPU6050.h b/Arduino/MPU6050/MPU6050.h index 6d9d006f..0456bc27 100644 --- a/Arduino/MPU6050/MPU6050.h +++ b/Arduino/MPU6050/MPU6050.h @@ -37,6 +37,8 @@ THE SOFTWARE. #ifndef _MPU6050_H_ #define _MPU6050_H_ +#include +#include #include "I2Cdev.h" // supporting link: http://forum.arduino.cc/index.php?&topic=143444.msg1079517#msg1079517 diff --git a/RaspberryPi_bcm2835/ADXL345/examples/ADXL345_example_1.cpp b/RaspberryPi_bcm2835/ADXL345/examples/ADXL345_example_1.cpp new file mode 100644 index 00000000..29eb0f3f --- /dev/null +++ b/RaspberryPi_bcm2835/ADXL345/examples/ADXL345_example_1.cpp @@ -0,0 +1,64 @@ +/* +I2Cdev library collection - ADXL345 RPi example +Based on the example in Arduino/ADXL345/ + +============================================== +I2Cdev device library code is placed under the MIT license + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== + +To compile on a Raspberry Pi (1 or 2) + 1. install the bcm2835 library, see http://www.airspayce.com/mikem/bcm2835/index.html + 2. enable i2c on your RPi , see https://learn.adafruit.com/adafruits-raspberry-pi-lesson-4-gpio-setup/configuring-i2c + 3. connect your i2c devices + 4. then from bash + $ PATH_I2CDEVLIB=~/i2cdevlib/ + $ gcc -o ADXL345_example_1 ${PATH_I2CDEVLIB}RaspberryPi_bcm2835/ADXL345/examples/ADXL345_example_1.cpp \ + -I ${PATH_I2CDEVLIB}RaspberryPi_bcm2835/I2Cdev ${PATH_I2CDEVLIB}RaspberryPi_bcm2835/I2Cdev/I2Cdev.cpp \ + -I ${PATH_I2CDEVLIB}/Arduino/ADXL345/ ${PATH_I2CDEVLIB}/Arduino/ADXL345/ADXL345.cpp -l bcm2835 -l m + $ sudo ./ADXL345_example_1 + +*/ + +#include +#include +#include "I2Cdev.h" +#include "ADXL345.h" + +int main(int argc, char **argv) { + printf("ADXL345 3-axis acceleromter example program\n"); + I2Cdev::initialize(); + ADXL345 accel ; + if ( accel.testConnection() ) + printf("ADXL345 connection test successful\n") ; + else { + fprintf( stderr, "ADXL345 connection test failed! exiting ...\n"); + return 1; + } + accel.initialize(); + int16_t ax, ay, az; + while (true) { + accel.getAcceleration(&ax, &ay, &az); + printf(" x_raw: 0x%04X y_raw: 0x%04X z_raw: 0x%04X\r", ax, ay, az); + fflush(stdout); + bcm2835_delay(200); + } + return 1; +} diff --git a/RaspberryPi_bcm2835/BMP085/examples/BMP085_basic.cpp b/RaspberryPi_bcm2835/BMP085/examples/BMP085_basic.cpp new file mode 100644 index 00000000..f6e6d579 --- /dev/null +++ b/RaspberryPi_bcm2835/BMP085/examples/BMP085_basic.cpp @@ -0,0 +1,72 @@ +/* +I2Cdev library collection - BMP085 RPi example +Based on the example in Arduino/BMP085/ + +============================================== +I2Cdev device library code is placed under the MIT license + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== + +To compile on a Raspberry Pi (1 or 2) + 1. install the bcm2835 library, see http://www.airspayce.com/mikem/bcm2835/index.html + 2. enable i2c on your RPi , see https://learn.adafruit.com/adafruits-raspberry-pi-lesson-4-gpio-setup/configuring-i2c + 3. connect your i2c devices + 4. then from bash + $ PATH_I2CDEVLIB=~/i2cdevlib/ + $ gcc -o BMP085_basic_example ${PATH_I2CDEVLIB}RaspberryPi_bcm2835/BMP085/examples/BMP085_basic.cpp \ + -I ${PATH_I2CDEVLIB}RaspberryPi_bcm2835/I2Cdev ${PATH_I2CDEVLIB}RaspberryPi_bcm2835/I2Cdev/I2Cdev.cpp \ + -I ${PATH_I2CDEVLIB}/Arduino/BMP085/ ${PATH_I2CDEVLIB}/Arduino/BMP085/BMP085.cpp -l bcm2835 -l m + $ sudo ./BMP085_basic_example + +*/ + +#include +#include +#include "I2Cdev.h" +#include "BMP085.h" + +int main(int argc, char **argv) { + printf("BMPO85 examples program\n"); + I2Cdev::initialize(); + BMP085 barometer ; // BMP085 class default I2C address is 0x77, specific I2C addresses may be passed as a parameter here + if ( barometer.testConnection() ) + printf("BMP085 connection test successful\n") ; + else { + fprintf( stderr, "BMP085 connection test failed! exiting ...\n"); + return 1; + } + barometer.loadCalibration(); + float temperature; + float pressure; + float altitude; + while (true) { + barometer.setControl(BMP085_MODE_TEMPERATURE); + bcm2835_delay(5); // wait 5 ms for conversion + temperature = barometer.getTemperatureC(); + barometer.setControl(BMP085_MODE_PRESSURE_3) ; //taking reading in highest accuracy measurement mode + bcm2835_delay( barometer.getMeasureDelayMicroseconds() / 1000 ); + pressure = barometer.getPressure(); + altitude = barometer.getAltitude(pressure); + printf(" Temperature: %3.1f deg C Pressure %3.3f kPa altitude %3.1f m\r", temperature, pressure/1000.0, altitude); + fflush(stdout); + bcm2835_delay(200); + } + return 1; +} diff --git a/RaspberryPi_bcm2835/HMC5883L/examples/HMC5883L_example_1.cpp b/RaspberryPi_bcm2835/HMC5883L/examples/HMC5883L_example_1.cpp new file mode 100644 index 00000000..b79b455c --- /dev/null +++ b/RaspberryPi_bcm2835/HMC5883L/examples/HMC5883L_example_1.cpp @@ -0,0 +1,71 @@ +/* +I2Cdev library collection - HMC5883L RPi example +Based on the example in Arduino/HMC5883L/ + +============================================== +I2Cdev device library code is placed under the MIT license + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== + +To compile on a Raspberry Pi (1 or 2) + 1. install the bcm2835 library, see http://www.airspayce.com/mikem/bcm2835/index.html + 2. enable i2c on your RPi , see https://learn.adafruit.com/adafruits-raspberry-pi-lesson-4-gpio-setup/configuring-i2c + 3. connect your i2c devices + 4. then from bash + $ PATH_I2CDEVLIB=~/i2cdevlib/ + $ gcc -o HMC5883L_example_1 ${PATH_I2CDEVLIB}RaspberryPi_bcm2835/HMC5883L/examples/HMC5883L_example_1.cpp \ + -I ${PATH_I2CDEVLIB}RaspberryPi_bcm2835/I2Cdev ${PATH_I2CDEVLIB}RaspberryPi_bcm2835/I2Cdev/I2Cdev.cpp \ + -I ${PATH_I2CDEVLIB}/Arduino/HMC5883L/ ${PATH_I2CDEVLIB}/Arduino/HMC5883L/HMC5883L.cpp -l bcm2835 -l m + $ sudo ./HMC5883L_example_1 + +*/ + +#include +#include +#include "I2Cdev.h" +#include "HMC5883L.h" +#include + +#define PI 3.14159265 + +int main(int argc, char **argv) { + printf("HMC5883L 3-axis acceleromter example program\n"); + I2Cdev::initialize(); + HMC5883L mag ; + if ( mag.testConnection() ) + printf("HMC5883L connection test successful\n") ; + else { + fprintf( stderr, "HMC5883L connection test failed! something maybe wrong, continueing anyway though ...\n"); + //return 1; + } + mag.initialize(); + mag.setSampleAveraging(HMC5883L_AVERAGING_8); + mag.setGain(HMC5883L_GAIN_1090); + int16_t mx, my, mz; + float heading ; + while (true) { + mag.getHeading(&mx, &my, &mz); + heading = atan2(my, mx) * 180 / PI; + printf(" mx: %d my: %d mz: %d heading: %3.1f deg\r", mx, my, mz, heading); + fflush(stdout); + bcm2835_delay(200); + } + return 1; +} diff --git a/RaspberryPi_bcm2835/I2Cdev/I2Cdev.cpp b/RaspberryPi_bcm2835/I2Cdev/I2Cdev.cpp new file mode 100644 index 00000000..47d7a7a9 --- /dev/null +++ b/RaspberryPi_bcm2835/I2Cdev/I2Cdev.cpp @@ -0,0 +1,261 @@ +// I2Cdev library collection - Main I2C device class +// Abstracts bit and byte I2C R/W functions into a convenient class +// RaspberryPi bcm2835 library port: bcm2835 library available at http://www.airspayce.com/mikem/bcm2835/index.html +// Based on Arduino's I2Cdev by Jeff Rowberg +// + +/* ============================================ +I2Cdev device library code is placed under the MIT license + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#include "I2Cdev.h" +#include + +I2Cdev::I2Cdev() { } + +void I2Cdev::initialize() { + bcm2835_init(); + bcm2835_i2c_set_baudrate( i2c_baudrate ); +} + +/** Enable or disable I2C, + * @param isEnabled true = enable, false = disable + */ +void I2Cdev::enable(bool isEnabled) { + if ( set_I2C_pins ){ + if (isEnabled) + bcm2835_i2c_end(); + else + bcm2835_i2c_begin() ; + } +} + +char sendBuf[256]; +char recvBuf[256]; + + + +/** Read a single bit from an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param bitNum Bit position to read (0-7) + * @param data Container for single bit value + * @return Status of read operation (true = success) + */ +int8_t I2Cdev::readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data) { + bcm2835_i2c_setSlaveAddress(devAddr); + sendBuf[0] = regAddr; + uint8_t response = bcm2835_i2c_write_read_rs(sendBuf, 1, recvBuf, 1); + *data = recvBuf[1] & (1 << bitNum); + return response == BCM2835_I2C_REASON_OK ; +} + +/** Read multiple bits from an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param bitStart First bit position to read (0-7) + * @param length Number of bits to read (not more than 8) + * @param data Container for right-aligned value (i.e. '101' read from any bitStart position will equal 0x05) + * @return Status of read operation (true = success) + */ +int8_t I2Cdev::readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data) { + // 01101001 read byte + // 76543210 bit numbers + // xxx args: bitStart=4, length=3 + // 010 masked + // -> 010 shifted + bcm2835_i2c_setSlaveAddress(devAddr); + sendBuf[0] = regAddr; + uint8_t response = bcm2835_i2c_write_read_rs(sendBuf, 1, recvBuf, 1); + uint8_t b; + if (response == BCM2835_I2C_REASON_OK) { + uint8_t mask = ((1 << length) - 1) << (bitStart - length + 1); + b &= mask; + b >>= (bitStart - length + 1); + *data = b; + } + return response == BCM2835_I2C_REASON_OK; +} + +/** Read single byte from an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param data Container for byte value read from device + * @return Status of read operation (true = success) + */ +int8_t I2Cdev::readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data) { + bcm2835_i2c_setSlaveAddress(devAddr); + sendBuf[0] = regAddr; + uint8_t response = bcm2835_i2c_write_read_rs(sendBuf, 1, recvBuf, 1); + data[0] = (uint8_t) recvBuf[0]; + return response == BCM2835_I2C_REASON_OK; +} + +/** Read multiple bytes from an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr First register regAddr to read from + * @param length Number of bytes to read + * @param data Buffer to store read data in + * @return I2C_TransferReturn_TypeDef http://downloads.energymicro.com/documentation/doxygen/group__I2C.html + */ +int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data) { + bcm2835_i2c_setSlaveAddress(devAddr); + sendBuf[0] = regAddr; + uint8_t response = bcm2835_i2c_write_read_rs(sendBuf, 1, recvBuf, length); + int i ; + for (i = 0; i < length ; i++) { + data[i] = (uint8_t) recvBuf[i]; + } + return response == BCM2835_I2C_REASON_OK; +} + +/** write a single bit in an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to write to + * @param bitNum Bit position to write (0-7) + * @param value New bit value to write + * @return Status of operation (true = success) + */ +bool I2Cdev::writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t data) { + bcm2835_i2c_setSlaveAddress(devAddr); + //first reading registery value + sendBuf[0] = regAddr; + uint8_t response = bcm2835_i2c_write_read_rs(sendBuf, 1, recvBuf, 1 ); + if ( response == BCM2835_I2C_REASON_OK ) { + uint8_t b = recvBuf[0] ; + b = (data != 0) ? (b | (1 << bitNum)) : (b & ~(1 << bitNum)); + sendBuf[1] = b ; + response = bcm2835_i2c_write(sendBuf, 2); + } + return response == BCM2835_I2C_REASON_OK; +} + +/** Write multiple bits in an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to write to + * @param bitStart First bit position to write (0-7) + * @param length Number of bits to write (not more than 8) + * @param data Right-aligned value to write + * @return Status of operation (true = success) + */ +bool I2Cdev::writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data) { + // 010 value to write + // 76543210 bit numbers + // xxx args: bitStart=4, length=3 + // 00011100 mask byte + // 10101111 original value (sample) + // 10100011 original & ~mask + // 10101011 masked | value + bcm2835_i2c_setSlaveAddress(devAddr); + //first reading registery value + sendBuf[0] = regAddr; + uint8_t response = bcm2835_i2c_write_read_rs(sendBuf, 1, recvBuf, 1 ); + if ( response == BCM2835_I2C_REASON_OK ) { + uint8_t b = recvBuf[0]; + uint8_t mask = ((1 << length) - 1) << (bitStart - length + 1); + data <<= (bitStart - length + 1); // shift data into correct position + data &= mask; // zero all non-important bits in data + b &= ~(mask); // zero all important bits in existing byte + b |= data; // combine data with existing byte + sendBuf[1] = b ; + response = bcm2835_i2c_write(sendBuf, 2); + } + return response == BCM2835_I2C_REASON_OK; +} + +/** Write single byte to an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register address to write to + * @param data New byte value to write + * @return Status of operation (true = success) + */ +bool I2Cdev::writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data) { + bcm2835_i2c_setSlaveAddress(devAddr); + sendBuf[0] = regAddr; + sendBuf[1] = data; + uint8_t response = bcm2835_i2c_write(sendBuf, 2); + return response == BCM2835_I2C_REASON_OK ; +} + +/** Read single word from a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param data Container for word value read from device + * @return Status of read operation (true = success) + */ +int8_t I2Cdev::readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data) { + bcm2835_i2c_setSlaveAddress(devAddr); + sendBuf[0] = regAddr; + uint8_t response = bcm2835_i2c_write_read_rs(sendBuf, 1, recvBuf, 2 ); + data[0] = (recvBuf[0] << 8) | recvBuf[1] ; + return response == BCM2835_I2C_REASON_OK ; +} + +/** Read multiple words from a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr First register regAddr to read from + * @param length Number of words to read + * @param data Buffer to store read data in + * @return Number of words read (-1 indicates failure) + */ +int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data) { + bcm2835_i2c_setSlaveAddress(devAddr); + sendBuf[0] = regAddr; + uint8_t response = bcm2835_i2c_write_read_rs(sendBuf, 1, recvBuf, length*2 ); + uint8_t i; + for (i = 0; i < length; i++) { + data[i] = (recvBuf[i*2] << 8) | recvBuf[i*2+1] ; + } + return response == BCM2835_I2C_REASON_OK ; +} + +bool I2Cdev::writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data){ + bcm2835_i2c_setSlaveAddress(devAddr); + sendBuf[0] = regAddr; + sendBuf[1] = (uint8_t) (data >> 8); //MSByte + sendBuf[2] = (uint8_t) (data >> 0); //LSByte + uint8_t response = bcm2835_i2c_write(sendBuf, 3); + return response == BCM2835_I2C_REASON_OK ; +} + +bool I2Cdev::writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data){ + bcm2835_i2c_setSlaveAddress(devAddr); + sendBuf[0] = regAddr; + uint8_t i; + for (i = 0; i < length; i++) { + sendBuf[i+1] = data[i] ; + } + uint8_t response = bcm2835_i2c_write(sendBuf, 1+length); + return response == BCM2835_I2C_REASON_OK ; +} + +bool I2Cdev::writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data){ + bcm2835_i2c_setSlaveAddress(devAddr); + sendBuf[0] = regAddr; + uint8_t i; + for (i = 0; i < length; i++) { + sendBuf[1+2*i] = (uint8_t) (data[i] >> 8); //MSByte + sendBuf[2+2*i] = (uint8_t) (data[i] >> 0); //LSByte + } + uint8_t response = bcm2835_i2c_write(sendBuf, 1+2*length); + return response == BCM2835_I2C_REASON_OK ; +} diff --git a/RaspberryPi_bcm2835/I2Cdev/I2Cdev.h b/RaspberryPi_bcm2835/I2Cdev/I2Cdev.h new file mode 100644 index 00000000..58809727 --- /dev/null +++ b/RaspberryPi_bcm2835/I2Cdev/I2Cdev.h @@ -0,0 +1,68 @@ +// I2Cdev library collection - Main I2C device class +// Abstracts bit and byte I2C R/W functions into a convenient class +// RaspberryPi bcm2835 library port: bcm2835 library available at http://www.airspayce.com/mikem/bcm2835/index.html +// Based on Arduino's I2Cdev by Jeff Rowberg +// + +/* ============================================ +I2Cdev device library code is placed under the MIT license + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#ifndef _I2CDEV_H_ +#define _I2CDEV_H_ + +#include + +#define set_I2C_pins false +/* used to boolean for setting RPi I2C pins P1-03 (SDA) and P1-05 (SCL) to alternate function ALT0, which enables those pins for I2C interface. + setI2Cpin should be false, if the I2C are already configured in alt mode ... */ + +#define i2c_baudrate 400000 +//uint32_t i2c_baudrate = 400000 ; //400 kHz, + +class I2Cdev { + public: + I2Cdev(); + + static void initialize(); + static void enable(bool isEnabled); + + static int8_t readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data); + //TODO static int8_t readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data); + static int8_t readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data); + //TODO static int8_t readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t *data); + static int8_t readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data); + static int8_t readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data); + static int8_t readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data); + static int8_t readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data); + + static bool writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t data); + //TODO static bool writeBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t data); + static bool writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data); + //TODO static bool writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t data); + static bool writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data); + static bool writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data); + static bool writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data); + static bool writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data); +}; + +#endif /* _I2CDEV_H_ */ diff --git a/RaspberryPi_bcm2835/MPU6050/examples/MPU6050_example_1.cpp b/RaspberryPi_bcm2835/MPU6050/examples/MPU6050_example_1.cpp new file mode 100644 index 00000000..caad584c --- /dev/null +++ b/RaspberryPi_bcm2835/MPU6050/examples/MPU6050_example_1.cpp @@ -0,0 +1,91 @@ +/* +I2Cdev library collection - MPU6050 RPi example +Based on the example in Arduino/MPU6050/ + +============================================== +I2Cdev device library code is placed under the MIT license + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== + +To compile on a Raspberry Pi (1 or 2) + 1. install the bcm2835 library, see http://www.airspayce.com/mikem/bcm2835/index.html + 2. enable i2c on your RPi , see https://learn.adafruit.com/adafruits-raspberry-pi-lesson-4-gpio-setup/configuring-i2c + 3. connect your i2c devices + 4. then from bash + $ PATH_I2CDEVLIB=~/i2cdevlib/ + $ gcc -o MPU6050_example_1 ${PATH_I2CDEVLIB}RaspberryPi_bcm2835/MPU6050/examples/MPU6050_example_1.cpp \ + -I ${PATH_I2CDEVLIB}RaspberryPi_bcm2835/I2Cdev ${PATH_I2CDEVLIB}RaspberryPi_bcm2835/I2Cdev/I2Cdev.cpp \ + -I ${PATH_I2CDEVLIB}/Arduino/MPU6050/ ${PATH_I2CDEVLIB}/Arduino/MPU6050/MPU6050.cpp -l bcm2835 -l m + $ sudo ./MPU6050_example_1 + +*/ + +#include +#include +#include "I2Cdev.h" +#include "MPU6050.h" +#include + +int main(int argc, char **argv) { + printf("MPU6050 3-axis acceleromter example program\n"); + I2Cdev::initialize(); + MPU6050 accelgyro ; + int16_t ax, ay, az; + int16_t gx, gy, gz; + if ( accelgyro.testConnection() ) + printf("MPU6050 connection test successful\n") ; + else { + fprintf( stderr, "MPU6050 connection test failed! something maybe wrong, continuing anyway though ...\n"); + //return 1; + } + accelgyro.initialize(); + // use the code below to change accel/gyro offset values + /* + printf("Updating internal sensor offsets...\n"); + // -76 -2359 1688 0 0 0 + printf("%i \t %i \t %i \t %i \t %i \t %i\n", + accelgyro.getXAccelOffset(), + accelgyro.getYAccelOffset(), + accelgyro.getZAccelOffset(), + accelgyro.getXGyroOffset(), + accelgyro.getYGyroOffset(), + accelgyro.getZGyroOffset()); + accelgyro.setXGyroOffset(220); + accelgyro.setYGyroOffset(76); + accelgyro.setZGyroOffset(-85); + printf("%i \t %i \t %i \t %i \t %i \t %i\n", + accelgyro.getXAccelOffset(), + accelgyro.getYAccelOffset(), + accelgyro.getZAccelOffset(), + accelgyro.getXGyroOffset(), + accelgyro.getYGyroOffset(), + accelgyro.getZGyroOffset()); + */ + + printf("\n"); + printf(" ax \t ay \t az \t gx \t gy \t gz:\n"); + while (true) { + accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz); + printf(" %d \t %d \t %d \t %d \t %d \t %d\r", ax, ay, az, gx, gy, gz); + fflush(stdout); + bcm2835_delay(100); + } + return 1; +} From efdc9b796338dcdab9ae87b1b75c81393c4a0a45 Mon Sep 17 00:00:00 2001 From: Albert Antony Date: Tue, 14 Apr 2015 01:47:30 +0930 Subject: [PATCH 069/335] Update MPU9150 gyro offset function calls for Arduino --- Arduino/MPU9150/MPU9150_9Axis_MotionApps41.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Arduino/MPU9150/MPU9150_9Axis_MotionApps41.h b/Arduino/MPU9150/MPU9150_9Axis_MotionApps41.h index 37e36ff2..b75df215 100644 --- a/Arduino/MPU9150/MPU9150_9Axis_MotionApps41.h +++ b/Arduino/MPU9150/MPU9150_9Axis_MotionApps41.h @@ -457,14 +457,14 @@ uint8_t MPU9150::dmpInitialize() { setOTPBankValid(false); DEBUG_PRINTLN(F("Setting X/Y/Z gyro offsets to previous values...")); - setXGyroOffset(xgOffset); - setYGyroOffset(ygOffset); - setZGyroOffset(zgOffset); + setXGyroOffsetTC(xgOffset); + setYGyroOffsetTC(ygOffset); + setZGyroOffsetTC(zgOffset); DEBUG_PRINTLN(F("Setting X/Y/Z gyro user offsets to zero...")); - setXGyroOffsetUser(0); - setYGyroOffsetUser(0); - setZGyroOffsetUser(0); + setXGyroOffset(0); + setYGyroOffset(0); + setZGyroOffset(0); DEBUG_PRINTLN(F("Writing final memory update 1/19 (function unknown)...")); uint8_t dmpUpdate[16], j; From 9ea441dd36754234246a5c1fca94651565b4e10a Mon Sep 17 00:00:00 2001 From: hamish Date: Sat, 18 Apr 2015 12:12:10 +0200 Subject: [PATCH 070/335] raspberry pi includes moved from Arduino folder to RaspberryPi_bcm2835 --- Arduino/BMP085/BMP085.h | 1 - Arduino/MPU6050/MPU6050.h | 2 -- RaspberryPi_bcm2835/I2Cdev/I2Cdev.h | 4 ++++ 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Arduino/BMP085/BMP085.h b/Arduino/BMP085/BMP085.h index f30fc45c..6b5e09a7 100644 --- a/Arduino/BMP085/BMP085.h +++ b/Arduino/BMP085/BMP085.h @@ -34,7 +34,6 @@ THE SOFTWARE. #define _BMP085_H_ #include "I2Cdev.h" -#include #define BMP085_ADDRESS 0x77 #define BMP085_DEFAULT_ADDRESS BMP085_ADDRESS diff --git a/Arduino/MPU6050/MPU6050.h b/Arduino/MPU6050/MPU6050.h index 0456bc27..6d9d006f 100644 --- a/Arduino/MPU6050/MPU6050.h +++ b/Arduino/MPU6050/MPU6050.h @@ -37,8 +37,6 @@ THE SOFTWARE. #ifndef _MPU6050_H_ #define _MPU6050_H_ -#include -#include #include "I2Cdev.h" // supporting link: http://forum.arduino.cc/index.php?&topic=143444.msg1079517#msg1079517 diff --git a/RaspberryPi_bcm2835/I2Cdev/I2Cdev.h b/RaspberryPi_bcm2835/I2Cdev/I2Cdev.h index 58809727..16a450d8 100644 --- a/RaspberryPi_bcm2835/I2Cdev/I2Cdev.h +++ b/RaspberryPi_bcm2835/I2Cdev/I2Cdev.h @@ -31,6 +31,10 @@ THE SOFTWARE. #define _I2CDEV_H_ #include +#include // required for BMP180 +#include // required for MPU6060 +#include // required for MPU6060 + #define set_I2C_pins false /* used to boolean for setting RPi I2C pins P1-03 (SDA) and P1-05 (SCL) to alternate function ALT0, which enables those pins for I2C interface. From 0ef5236719cf341e146a69fe831c373b2f4b7e01 Mon Sep 17 00:00:00 2001 From: Nathan Ringo Date: Sun, 19 Apr 2015 23:47:47 -0500 Subject: [PATCH 071/335] Allows setting I2CDEV_IMPLEMENTATION externally. --- Arduino/I2Cdev/I2Cdev.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Arduino/I2Cdev/I2Cdev.h b/Arduino/I2Cdev/I2Cdev.h index 766c21d9..224767c7 100644 --- a/Arduino/I2Cdev/I2Cdev.h +++ b/Arduino/I2Cdev/I2Cdev.h @@ -49,8 +49,10 @@ THE SOFTWARE. // ----------------------------------------------------------------------------- // I2C interface implementation setting // ----------------------------------------------------------------------------- +#ifndef I2CDEV_IMPLEMENTATION #define I2CDEV_IMPLEMENTATION I2CDEV_ARDUINO_WIRE //#define I2CDEV_IMPLEMENTATION I2CDEV_BUILTIN_FASTWIRE +#endif // I2CDEV_IMPLEMENTATION // comment this out if you are using a non-optimal IDE/implementation setting // but want the compiler to shut up about it From 8448fe8548ae60bd0b9e986bccebbd37fcd39043 Mon Sep 17 00:00:00 2001 From: Jej Date: Sun, 3 May 2015 07:30:30 +0200 Subject: [PATCH 072/335] Update MPU6050.cpp Doxygen comment for MPU6050::setMotionDetectionThreshold was wrong. --- Arduino/MPU6050/MPU6050.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Arduino/MPU6050/MPU6050.cpp b/Arduino/MPU6050/MPU6050.cpp index ecf5f5db..13053cd9 100644 --- a/Arduino/MPU6050/MPU6050.cpp +++ b/Arduino/MPU6050/MPU6050.cpp @@ -464,7 +464,7 @@ uint8_t MPU6050::getMotionDetectionThreshold() { I2Cdev::readByte(devAddr, MPU6050_RA_MOT_THR, buffer); return buffer[0]; } -/** Set free-fall event acceleration threshold. +/** Set motion detection event acceleration threshold. * @param threshold New motion detection acceleration threshold value (LSB = 2mg) * @see getMotionDetectionThreshold() * @see MPU6050_RA_MOT_THR From a87a524c6bd3c467f0dc0b9b7b8434e6a4702313 Mon Sep 17 00:00:00 2001 From: Pauline Middelink Date: Sat, 30 May 2015 10:44:30 +0200 Subject: [PATCH 073/335] Bumped BMP085 private buffer up to 3 bytes, for getMeasurement3(). Protected the definition of calibration methods by the same #ifdef as the code has, so people browsing the header files won't be too supprised. --- Arduino/BMP085/BMP085.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Arduino/BMP085/BMP085.h b/Arduino/BMP085/BMP085.h index 6b5e09a7..14c76cec 100644 --- a/Arduino/BMP085/BMP085.h +++ b/Arduino/BMP085/BMP085.h @@ -79,6 +79,7 @@ class BMP085 { void initialize(); bool testConnection(); +#ifdef BMP085_INCLUDE_INDIVIDUAL_CALIBRATION_ACCESS /* calibration register methods */ int16_t getAC1(); int16_t getAC2(); @@ -91,6 +92,7 @@ class BMP085 { int16_t getMB(); int16_t getMC(); int16_t getMD(); +#endif /* CONTROL register methods */ uint8_t getControl(); @@ -113,7 +115,7 @@ class BMP085 { private: uint8_t devAddr; - uint8_t buffer[2]; + uint8_t buffer[3]; bool calibrationLoaded; int16_t ac1, ac2, ac3, b1, b2, mb, mc, md; From 015389cd87638bcd828d3c7a5d58785de808c36b Mon Sep 17 00:00:00 2001 From: Andrey Voloshin Date: Sat, 6 Jun 2015 15:13:21 +0300 Subject: [PATCH 074/335] Initial port to STM32 HAL driver. Tested on gy-87 board, BMP180 sensor used. Sensor values compared with Arduino connected to the same board. --- STM32/BMP085/BMP085.c | 306 +++++++++++++++++++++++++++++++++++++ STM32/BMP085/BMP085.h | 113 ++++++++++++++ STM32/I2Cdev/I2Cdev.c | 346 ++++++++++++++++++++++++++++++++++++++++++ STM32/I2Cdev/I2Cdev.h | 75 +++++++++ STM32/README.md | 98 ++++++++++++ 5 files changed, 938 insertions(+) create mode 100644 STM32/BMP085/BMP085.c create mode 100644 STM32/BMP085/BMP085.h create mode 100644 STM32/I2Cdev/I2Cdev.c create mode 100644 STM32/I2Cdev/I2Cdev.h create mode 100644 STM32/README.md diff --git a/STM32/BMP085/BMP085.c b/STM32/BMP085/BMP085.c new file mode 100644 index 00000000..277add9c --- /dev/null +++ b/STM32/BMP085/BMP085.c @@ -0,0 +1,306 @@ +// I2Cdev library collection - BMP085 I2C device class +// Based on register information stored in the I2Cdevlib internal database +// 2012-06-28 by Jeff Rowberg +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// 2015-06-06 by Andrey Voloshin +// +// Changelog: +// 2015-06-06 - ported to STM32 HAL library from Arduino code + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2012 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#include "BMP085.h" + +uint8_t devAddr = BMP085_DEFAULT_ADDRESS; +uint8_t buffer[2]; + +bool calibrationLoaded; +int16_t ac1, ac2, ac3, b1, b2, mb, mc, md; +uint16_t ac4, ac5, ac6; +int32_t b5; +uint8_t measureMode; + +/** + * Specific address constructor. + * @param address Specific device address + * @see BMP085_DEFAULT_ADDRESS + */ +void BMP085_setAddress(uint8_t address) +{ + devAddr = address; +} + +/** + * Prepare device for normal usage. + */ +void BMP085_initialize() +{ + if (devAddr==0) devAddr = BMP085_DEFAULT_ADDRESS; + // load sensor's calibration constants + BMP085_loadCalibration(); +} + +/** + * Verify the device is connected and available. + */ +bool BMP085_testConnection() +{ + // test for a response, though this is very basic + return I2Cdev_readByte(devAddr, BMP085_RA_AC1_H, buffer, 100) == 1; +} + +/* calibration register methods */ + +void BMP085_loadCalibration() +{ + uint8_t buf2[22]; + I2Cdev_readBytes(devAddr, BMP085_RA_AC1_H, 22, buf2, 1000); + ac1 = ((int16_t)buf2[0] << 8) + buf2[1]; + ac2 = ((int16_t)buf2[2] << 8) + buf2[3]; + ac3 = ((int16_t)buf2[4] << 8) + buf2[5]; + ac4 = ((uint16_t)buf2[6] << 8) + buf2[7]; + ac5 = ((uint16_t)buf2[8] << 8) + buf2[9]; + ac6 = ((uint16_t)buf2[10] << 8) + buf2[11]; + b1 = ((int16_t)buf2[12] << 8) + buf2[13]; + b2 = ((int16_t)buf2[14] << 8) + buf2[15]; + mb = ((int16_t)buf2[16] << 8) + buf2[17]; + mc = ((int16_t)buf2[18] << 8) + buf2[19]; + md = ((int16_t)buf2[20] << 8) + buf2[21]; + calibrationLoaded = true; +} + +#ifdef BMP085_INCLUDE_INDIVIDUAL_CALIBRATION_ACCESS +int16_t BMP085_getAC1() +{ + if (calibrationLoaded) return ac1; + I2Cdev_readBytes(devAddr, BMP085_RA_AC1_H, 2, buffer); + return ((int16_t)buffer[1] << 8) + buffer[0]; +} + +int16_t BMP085_getAC2() +{ + if (calibrationLoaded) return ac2; + I2Cdev_readBytes(devAddr, BMP085_RA_AC2_H, 2, buffer); + return ((int16_t)buffer[1] << 8) + buffer[0]; +} + +int16_t BMP085_getAC3() +{ + if (calibrationLoaded) return ac3; + I2Cdev_readBytes(devAddr, BMP085_RA_AC3_H, 2, buffer); + return ((int16_t)buffer[1] << 8) + buffer[0]; +} + +uint16_t BMP085_getAC4() +{ + if (calibrationLoaded) return ac4; + I2Cdev_readBytes(devAddr, BMP085_RA_AC4_H, 2, buffer); + return ((uint16_t)buffer[1] << 8) + buffer[0]; +} + +uint16_t BMP085_getAC5() +{ + if (calibrationLoaded) return ac5; + I2Cdev_readBytes(devAddr, BMP085_RA_AC5_H, 2, buffer); + return ((uint16_t)buffer[1] << 8) + buffer[0]; +} + +uint16_t BMP085_getAC6() +{ + if (calibrationLoaded) return ac6; + I2Cdev_readBytes(devAddr, BMP085_RA_AC6_H, 2, buffer); + return ((uint16_t)buffer[1] << 8) + buffer[0]; +} + +int16_t BMP085_getB1() +{ + if (calibrationLoaded) return b1; + I2Cdev_readBytes(devAddr, BMP085_RA_B1_H, 2, buffer); + return ((int16_t)buffer[1] << 8) + buffer[0]; +} + +int16_t BMP085_getB2() +{ + if (calibrationLoaded) return b2; + I2Cdev_readBytes(devAddr, BMP085_RA_B2_H, 2, buffer); + return ((int16_t)buffer[1] << 8) + buffer[0]; +} + +int16_t BMP085_getMB() +{ + if (calibrationLoaded) return mb; + I2Cdev_readBytes(devAddr, BMP085_RA_MB_H, 2, buffer); + return ((int16_t)buffer[1] << 8) + buffer[0]; +} + +int16_t BMP085_getMC() +{ + if (calibrationLoaded) return mc; + I2Cdev_readBytes(devAddr, BMP085_RA_MC_H, 2, buffer); + return ((int16_t)buffer[1] << 8) + buffer[0]; +} + +int16_t BMP085_getMD() +{ + if (calibrationLoaded) return md; + I2Cdev_readBytes(devAddr, BMP085_RA_MD_H, 2, buffer); + return ((int16_t)buffer[1] << 8) + buffer[0]; +} +#endif + +/* control register methods */ + +uint8_t BMP085_getControl() +{ + I2Cdev_readByte(devAddr, BMP085_RA_CONTROL, buffer, 1000); + return buffer[0]; +} +void BMP085_setControl(uint8_t value) +{ + I2Cdev_writeByte(devAddr, BMP085_RA_CONTROL, value); + measureMode = value; +} + +/* measurement register methods */ + +uint16_t BMP085_getMeasurement2() +{ + I2Cdev_readBytes(devAddr, BMP085_RA_MSB, 2, buffer, 1000); + return ((uint16_t) buffer[0] << 8) + buffer[1]; +} +uint32_t BMP085_getMeasurement3() +{ + I2Cdev_readBytes(devAddr, BMP085_RA_MSB, 3, buffer, 1000); + return ((uint32_t)buffer[0] << 16) + ((uint16_t)buffer[1] << 8) + buffer[2]; +} +uint8_t BMP085_getMeasureDelayMilliseconds(uint8_t mode) +{ + if (mode == 0) mode = measureMode; + if (measureMode == 0x2E) return 5; + else if (measureMode == 0x34) return 5; + else if (measureMode == 0x74) return 8; + else if (measureMode == 0xB4) return 14; + else if (measureMode == 0xF4) return 26; + return 0; // invalid mode +} +uint16_t BMP085_getMeasureDelayMicroseconds(uint8_t mode) +{ + if (mode == 0) mode = measureMode; + if (measureMode == 0x2E) return 4500; + else if (measureMode == 0x34) return 4500; + else if (measureMode == 0x74) return 7500; + else if (measureMode == 0xB4) return 13500; + else if (measureMode == 0xF4) return 25500; + return 0; // invalid mode +} + +uint16_t BMP085_getRawTemperature() +{ + if (measureMode == 0x2E) return BMP085_getMeasurement2(); + return 0; // wrong measurement mode for temperature request +} + +float BMP085_getTemperatureC() +{ + /* + Datasheet formula: + UT = raw temperature + X1 = (UT - AC6) * AC5 / 2^15 + X2 = MC * 2^11 / (X1 + MD) + B5 = X1 + X2 + T = (B5 + 8) / 2^4 + */ + int32_t ut = BMP085_getRawTemperature(); + int32_t x1 = ((ut - (int32_t)ac6) * (int32_t)ac5) >> 15; + int32_t x2 = ((int32_t)mc << 11) / (x1 + md); + b5 = x1 + x2; + return (float)((b5 + 8) >> 4) / 10.0f; +} + +float BMP085_getTemperatureF() +{ + return BMP085_getTemperatureC() * 9.0f / 5.0f + 32; +} + +uint32_t BMP085_getRawPressure() +{ + if (measureMode & 0x34) return BMP085_getMeasurement3() >> (8 - ((measureMode & 0xC0) >> 6)); + return 0; // wrong measurement mode for pressure request +} + +float BMP085_getPressure() +{ + /* + Datasheet forumla + UP = raw pressure + B6 = B5 - 4000 + X1 = (B2 * (B6 * B6 / 2^12)) / 2^11 + X2 = AC2 * B6 / 2^11 + X3 = X1 + X2 + B3 = ((AC1 * 4 + X3) << oss + 2) / 4 + X1 = AC3 * B6 / 2^13 + X2 = (B1 * (B6 * B6 / 2^12)) / 2^16 + X3 = ((X1 + X2) + 2) / 2^2 + B4 = AC4 * (unsigned long)(X3 + 32768) / 2^15 + B7 = ((unsigned long)UP - B3) * (50000 >> oss) + if (B7 < 0x80000000) { p = (B7 * 2) / B4 } + else { p = (B7 / B4) * 2 } + X1 = (p / 2^8) * (p / 2^8) + X1 = (X1 * 3038) / 2^16 + X2 = (-7357 * p) / 2^16 + p = p + (X1 + X2 + 3791) / 2^4 + */ + uint32_t up = BMP085_getRawPressure(); + uint8_t oss = (measureMode & 0xC0) >> 6; + int32_t p; + int32_t b6 = b5 - 4000; + int32_t x1 = ((int32_t)b2 * ((b6 * b6) >> 12)) >> 11; + int32_t x2 = ((int32_t)ac2 * b6) >> 11; + int32_t x3 = x1 + x2; + int32_t b3 = ((((int32_t)ac1 * 4 + x3) << oss) + 2) >> 2; + x1 = ((int32_t)ac3 * b6) >> 13; + x2 = ((int32_t)b1 * ((b6 * b6) >> 12)) >> 16; + x3 = ((x1 + x2) + 2) >> 2; + uint32_t b4 = ((uint32_t)ac4 * (uint32_t)(x3 + 32768)) >> 15; + uint32_t b7 = ((uint32_t)up - b3) * (uint32_t)(50000UL >> oss); + if (b7 < 0x80000000) + { + p = (b7 << 1) / b4; + } + else + { + p = (b7 / b4) << 1; + } + x1 = (p >> 8) * (p >> 8); + x1 = (x1 * 3038) >> 16; + x2 = (-7357 * p) >> 16; + return p + ((x1 + x2 + (int32_t)3791) >> 4); +} + +float BMP085_getAltitude(float pressure, float seaLevelPressure) +{ + if (seaLevelPressure == 0) seaLevelPressure = 101325; + return 44330 * (1.0 - pow(pressure / seaLevelPressure, 0.1903)); +} diff --git a/STM32/BMP085/BMP085.h b/STM32/BMP085/BMP085.h new file mode 100644 index 00000000..ab1b6af8 --- /dev/null +++ b/STM32/BMP085/BMP085.h @@ -0,0 +1,113 @@ +// I2Cdev library collection - BMP085 I2C device class +// Based on register information stored in the I2Cdevlib internal database +// 2012-06-28 by Jeff Rowberg +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// 2015-06-06 by Andrey Voloshin +// +// Changelog: +// 2015-06-06 - ported to STM32 HAL library from Arduino code + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2012 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#ifndef _BMP085_H_ +#define _BMP085_H_ + +#include "I2Cdev.h" +#include + +#define BMP085_ADDRESS 0x77 +#define BMP085_DEFAULT_ADDRESS BMP085_ADDRESS + +#define BMP085_RA_AC1_H 0xAA /* AC1_H */ +#define BMP085_RA_AC1_L 0xAB /* AC1_L */ +#define BMP085_RA_AC2_H 0xAC /* AC2_H */ +#define BMP085_RA_AC2_L 0xAD /* AC2_L */ +#define BMP085_RA_AC3_H 0xAE /* AC3_H */ +#define BMP085_RA_AC3_L 0xAF /* AC3_L */ +#define BMP085_RA_AC4_H 0xB0 /* AC4_H */ +#define BMP085_RA_AC4_L 0xB1 /* AC4_L */ +#define BMP085_RA_AC5_H 0xB2 /* AC5_H */ +#define BMP085_RA_AC5_L 0xB3 /* AC5_L */ +#define BMP085_RA_AC6_H 0xB4 /* AC6_H */ +#define BMP085_RA_AC6_L 0xB5 /* AC6_L */ +#define BMP085_RA_B1_H 0xB6 /* B1_H */ +#define BMP085_RA_B1_L 0xB7 /* B1_L */ +#define BMP085_RA_B2_H 0xB8 /* B2_H */ +#define BMP085_RA_B2_L 0xB9 /* B2_L */ +#define BMP085_RA_MB_H 0xBA /* MB_H */ +#define BMP085_RA_MB_L 0xBB /* MB_L */ +#define BMP085_RA_MC_H 0xBC /* MC_H */ +#define BMP085_RA_MC_L 0xBD /* MC_L */ +#define BMP085_RA_MD_H 0xBE /* MD_H */ +#define BMP085_RA_MD_L 0xBF /* MD_L */ +#define BMP085_RA_CONTROL 0xF4 /* CONTROL */ +#define BMP085_RA_MSB 0xF6 /* MSB */ +#define BMP085_RA_LSB 0xF7 /* LSB */ +#define BMP085_RA_XLSB 0xF8 /* XLSB */ + +#define BMP085_MODE_TEMPERATURE 0x2E +#define BMP085_MODE_PRESSURE_0 0x34 +#define BMP085_MODE_PRESSURE_1 0x74 +#define BMP085_MODE_PRESSURE_2 0xB4 +#define BMP085_MODE_PRESSURE_3 0xF4 + +void BMP085_initialize(); +bool BMP085_testConnection(); + +/* calibration register methods */ +int16_t BMP085_getAC1(); +int16_t BMP085_getAC2(); +int16_t BMP085_getAC3(); +uint16_t BMP085_getAC4(); +uint16_t BMP085_getAC5(); +uint16_t BMP085_getAC6(); +int16_t BMP085_getB1(); +int16_t BMP085_getB2(); +int16_t BMP085_getMB(); +int16_t BMP085_getMC(); +int16_t BMP085_getMD(); + +/* CONTROL register methods */ +uint8_t BMP085_getControl(); +void BMP085_setControl(uint8_t value); + +/* MEASURE register methods */ +uint16_t BMP085_getMeasurement2(); // 16-bit data +uint32_t BMP085_getMeasurement3(); // 24-bit data +uint8_t BMP085_getMeasureDelayMilliseconds(uint8_t mode); +uint16_t BMP085_getMeasureDelayMicroseconds(uint8_t mode); + +// convenience methods +void BMP085_loadCalibration(); +uint16_t BMP085_getRawTemperature(); +float BMP085_getTemperatureC(); +float BMP085_getTemperatureF(); +uint32_t BMP085_getRawPressure(); +float BMP085_getPressure(); +float BMP085_getAltitude(float pressure, float seaLevelPressure); + + + +#endif /* _BMP085_H_ */ diff --git a/STM32/I2Cdev/I2Cdev.c b/STM32/I2Cdev/I2Cdev.c new file mode 100644 index 00000000..291a0c94 --- /dev/null +++ b/STM32/I2Cdev/I2Cdev.c @@ -0,0 +1,346 @@ +// I2Cdev library collection - Main I2C device class header file +// Abstracts bit and byte I2C R/W functions into a convenient class +// 6/9/2012 by Jeff Rowberg +// 6/6/2015 by Andrey Voloshin +// +// Changelog: +// 2015-06-06 - ported to STM32 HAL library from Arduino code + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2013 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#include "I2Cdev.h" + +/** Default timeout value for read operations. + * Set this to 0 to disable timeout detection. + */ +uint16_t I2Cdev_readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; + +/** Read a single bit from an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param bitNum Bit position to read (0-7) + * @param data Container for single bit value + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev_readTimeout) + * @return Status of read operation (true = success) + */ +uint8_t I2Cdev_readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data, uint16_t timeout) +{ + uint8_t b; + uint8_t count = I2Cdev_readByte(devAddr, regAddr, &b, timeout); + *data = b & (1 << bitNum); + return count; +} + +/** Read a single bit from a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param bitNum Bit position to read (0-15) + * @param data Container for single bit value + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev_readTimeout) + * @return Status of read operation (true = success) + */ +uint8_t I2Cdev_readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data, uint16_t timeout) +{ + uint16_t b; + uint8_t count = I2Cdev_readWord(devAddr, regAddr, &b, timeout); + *data = b & (1 << bitNum); + return count; +} + +/** Read multiple bits from an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param bitStart First bit position to read (0-7) + * @param length Number of bits to read (not more than 8) + * @param data Container for right-aligned value (i.e. '101' read from any bitStart position will equal 0x05) + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev_readTimeout) + * @return Status of read operation (true = success) + */ +uint8_t I2Cdev_readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data, uint16_t timeout) +{ + // 01101001 read byte + // 76543210 bit numbers + // xxx args: bitStart=4, length=3 + // 010 masked + // -> 010 shifted + uint8_t count, b; + if ((count = I2Cdev_readByte(devAddr, regAddr, &b, timeout)) != 0) + { + uint8_t mask = ((1 << length) - 1) << (bitStart - length + 1); + b &= mask; + b >>= (bitStart - length + 1); + *data = b; + } + return count; +} + +/** Read multiple bits from a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param bitStart First bit position to read (0-15) + * @param length Number of bits to read (not more than 16) + * @param data Container for right-aligned value (i.e. '101' read from any bitStart position will equal 0x05) + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev_readTimeout) + * @return Status of read operation (1 = success, 0 = failure, -1 = timeout) + */ +uint8_t I2Cdev_readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t *data, uint16_t timeout) +{ + // 1101011001101001 read byte + // fedcba9876543210 bit numbers + // xxx args: bitStart=12, length=3 + // 010 masked + // -> 010 shifted + uint8_t count; + uint16_t w; + if ((count = I2Cdev_readWord(devAddr, regAddr, &w, timeout)) != 0) + { + uint16_t mask = ((1 << length) - 1) << (bitStart - length + 1); + w &= mask; + w >>= (bitStart - length + 1); + *data = w; + } + return count; +} + +/** Read single byte from an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param data Container for byte value read from device + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev_readTimeout) + * @return Status of read operation (true = success) + */ +uint8_t I2Cdev_readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint16_t timeout) +{ + return I2Cdev_readBytes(devAddr, regAddr, 1, data, timeout); +} + +/** Read single word from a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param data Container for word value read from device + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev_readTimeout) + * @return Status of read operation (true = success) + */ +uint8_t I2Cdev_readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data, uint16_t timeout) +{ + return I2Cdev_readWords(devAddr, regAddr, 1, data, timeout); +} + +/** Read multiple bytes from an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr First register regAddr to read from + * @param length Number of bytes to read + * @param data Buffer to store read data in + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev_readTimeout) + * @return Number of bytes read (-1 indicates failure) + */ +uint8_t I2Cdev_readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data, uint16_t timeout) +{ + uint16_t tout = timeout > 0 ? timeout : I2CDEV_DEFAULT_READ_TIMEOUT; + + HAL_I2C_Master_Transmit(I2Cdev_hi2c, devAddr << 1, ®Addr, 1, tout); + if (HAL_I2C_Master_Receive(I2Cdev_hi2c, devAddr << 1, data, length, tout) == HAL_OK) return length; + return -1; +} + +/** Read multiple words from a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr First register regAddr to read from + * @param length Number of words to read + * @param data Buffer to store read data in + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev_readTimeout) + * @return Number of words read (-1 indicates failure) + */ +uint8_t I2Cdev_readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data, uint16_t timeout) +{ + uint16_t tout = timeout > 0 ? timeout : I2CDEV_DEFAULT_READ_TIMEOUT; + + HAL_I2C_Master_Transmit(I2Cdev_hi2c, devAddr << 1, ®Addr, 1, tout); + if (HAL_I2C_Master_Receive(I2Cdev_hi2c, devAddr << 1, (uint8_t *)data, length*2, tout) == HAL_OK) + return length; + else + return -1; +} + +/** write a single bit in an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to write to + * @param bitNum Bit position to write (0-7) + * @param value New bit value to write + * @return Status of operation (true = success) + */ +uint16_t I2Cdev_writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t data) +{ + uint8_t b; + I2Cdev_readByte(devAddr, regAddr, &b, I2Cdev_readTimeout); + b = (data != 0) ? (b | (1 << bitNum)) : (b & ~(1 << bitNum)); + return I2Cdev_writeByte(devAddr, regAddr, b); +} + +/** write a single bit in a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to write to + * @param bitNum Bit position to write (0-15) + * @param value New bit value to write + * @return Status of operation (true = success) + */ +uint16_t I2Cdev_writeBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t data) +{ + uint16_t w; + I2Cdev_readWord(devAddr, regAddr, &w, 100); + w = (data != 0) ? (w | (1 << bitNum)) : (w & ~(1 << bitNum)); + return I2Cdev_writeWord(devAddr, regAddr, w); +} + +/** Write multiple bits in an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to write to + * @param bitStart First bit position to write (0-7) + * @param length Number of bits to write (not more than 8) + * @param data Right-aligned value to write + * @return Status of operation (true = success) + */ +uint16_t I2Cdev_writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data) +{ + // 010 value to write + // 76543210 bit numbers + // xxx args: bitStart=4, length=3 + // 00011100 mask byte + // 10101111 original value (sample) + // 10100011 original & ~mask + // 10101011 masked | value + uint8_t b; + if (I2Cdev_readByte(devAddr, regAddr, &b, 100) != 0) + { + uint8_t mask = ((1 << length) - 1) << (bitStart - length + 1); + data <<= (bitStart - length + 1); // shift data into correct position + data &= mask; // zero all non-important bits in data + b &= ~(mask); // zero all important bits in existing byte + b |= data; // combine data with existing byte + return I2Cdev_writeByte(devAddr, regAddr, b); + } + else + { + return 0; + } +} + +/** Write multiple bits in a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to write to + * @param bitStart First bit position to write (0-15) + * @param length Number of bits to write (not more than 16) + * @param data Right-aligned value to write + * @return Status of operation (true = success) + */ +uint16_t I2Cdev_writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t data) +{ + // 010 value to write + // fedcba9876543210 bit numbers + // xxx args: bitStart=12, length=3 + // 0001110000000000 mask word + // 1010111110010110 original value (sample) + // 1010001110010110 original & ~mask + // 1010101110010110 masked | value + uint16_t w; + if (I2Cdev_readWord(devAddr, regAddr, &w, 100) != 0) + { + uint16_t mask = ((1 << length) - 1) << (bitStart - length + 1); + data <<= (bitStart - length + 1); // shift data into correct position + data &= mask; // zero all non-important bits in data + w &= ~(mask); // zero all important bits in existing word + w |= data; // combine data with existing word + return I2Cdev_writeWord(devAddr, regAddr, w); + } + else + { + return 0; + } +} + +/** Write single byte to an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register address to write to + * @param data New byte value to write + * @return Status of operation (true = success) + */ +uint16_t I2Cdev_writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data) +{ + return I2Cdev_writeBytes(devAddr, regAddr, 1, &data); +} + +/** Write single word to a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register address to write to + * @param data New word value to write + * @return Status of operation (true = success) + */ +uint16_t I2Cdev_writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data) +{ + return I2Cdev_writeWords(devAddr, regAddr, 1, &data); +} + +/** Write multiple bytes to an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr First register address to write to + * @param length Number of bytes to write + * @param data Buffer to copy new data from + * @return Status of operation (true = success) + */ +uint16_t I2Cdev_writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t Size, uint8_t* pData) +{ + // Creating dynamic array to store regAddr + data in one buffer + uint8_t * dynBuffer; + dynBuffer = (uint8_t *) malloc(sizeof(uint8_t) * (Size+1)); + dynBuffer[0] = regAddr; + + // copy array + memcpy(dynBuffer+1, pData, sizeof(uint8_t) * Size); + + HAL_StatusTypeDef status = HAL_I2C_Master_Transmit(I2Cdev_hi2c, devAddr << 1, dynBuffer, Size+1, 1000); + free(dynBuffer); + return status == HAL_OK; +} + +/** Write multiple words to a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr First register address to write to + * @param length Number of words to write + * @param data Buffer to copy new data from + * @return Status of operation (true = success) + */ +uint16_t I2Cdev_writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t* data) +{ + // Creating dynamic array to store regAddr + data in one buffer + uint8_t * dynBuffer; + dynBuffer = (uint8_t *) malloc(sizeof(uint8_t) + sizeof(uint16_t) * length); + dynBuffer[0] = regAddr; + + // copy array + memcpy(dynBuffer+1, data, sizeof(uint16_t) * length); + HAL_StatusTypeDef status = HAL_I2C_Master_Transmit(I2Cdev_hi2c, devAddr << 1, dynBuffer, sizeof(uint8_t) + sizeof(uint16_t) * length, 1000); + free(dynBuffer); + return status == HAL_OK; +} diff --git a/STM32/I2Cdev/I2Cdev.h b/STM32/I2Cdev/I2Cdev.h new file mode 100644 index 00000000..a77b4540 --- /dev/null +++ b/STM32/I2Cdev/I2Cdev.h @@ -0,0 +1,75 @@ +// I2Cdev library collection - Main I2C device class header file +// Abstracts bit and byte I2C R/W functions into a convenient class +// 6/9/2012 by Jeff Rowberg +// 6/6/2015 by Andrey Voloshin +// +// Changelog: +// 2015-06-06 - ported to STM32 HAL library from Arduino code + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2013 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#ifndef _I2CDEV_H_ +#define _I2CDEV_H_ + +#include +#include +#include + +// TODO: include depending on chip family +//#include "stm32f1xx_hal.h" +//#include "stm32f2xx_hal.h" +//#include "stm32f3xx_hal.h" +#include "stm32f4xx_hal.h" + +typedef int bool; +#define true 1 +#define false 0 + +uint16_t I2Cdev_readTimeout; +// Hold pointer to inited HAL I2C device +I2C_HandleTypeDef * I2Cdev_hi2c; + +// 1000ms default read timeout (modify with "I2Cdev::readTimeout = [ms];") +#define I2CDEV_DEFAULT_READ_TIMEOUT 1000 + +uint8_t I2Cdev_readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data, uint16_t timeout); +uint8_t I2Cdev_readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data, uint16_t timeout); +uint8_t I2Cdev_readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data, uint16_t timeout); +uint8_t I2Cdev_readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t *data, uint16_t timeout); +uint8_t I2Cdev_readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint16_t timeout); +uint8_t I2Cdev_readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data, uint16_t timeout); +uint8_t I2Cdev_readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data, uint16_t timeout); +uint8_t I2Cdev_readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data, uint16_t timeout); + +uint16_t I2Cdev_writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t data); +uint16_t I2Cdev_writeBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t data); +uint16_t I2Cdev_writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data); +uint16_t I2Cdev_writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t data); +uint16_t I2Cdev_writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data); +uint16_t I2Cdev_writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data); +uint16_t I2Cdev_writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data); +uint16_t I2Cdev_writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data); + +#endif /* _I2CDEV_H_ */ diff --git a/STM32/README.md b/STM32/README.md new file mode 100644 index 00000000..89b11a38 --- /dev/null +++ b/STM32/README.md @@ -0,0 +1,98 @@ +# I2C Device Library for STM32 + +## I2Cdev +Init your i2c device in HAL set its handler to + +## Devices +Currently only BMP180/BMP085 is supported. MPU6050 and HMC5883L will come soon (GY-87 board). +Adding more functions and devices should be straighforward after reading the source code of the driver. +Porting drivers should be as simple, as renaming public methods from *DRIVER::func()* to *DRIVER_func()* and moving private fields and functions to *.c file + +## Example for STM32F429I-DISCO board +``` +#include "stm32f4xx.h" +#include "stm32f4xx_hal.h" +#include +#include +#include +#include "I2Cdev.h" +#include "BMP085.h" + +I2C_HandleTypeDef hi2c3; + +int main(void) +{ + SystemInit(); + HAL_Init(); + + GPIO_InitTypeDef GPIO_InitStruct; + + /**I2C3 GPIO Configuration + PC9 ------> I2C3_SDA + PA8 ------> I2C3_SCL + */ + + __GPIOA_CLK_ENABLE(); + __GPIOC_CLK_ENABLE(); + + GPIO_InitStruct.Pin = GPIO_PIN_9; + GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; + GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_FAST; + GPIO_InitStruct.Alternate = GPIO_AF4_I2C3; + HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = GPIO_PIN_8; + GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; + GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_FAST; + GPIO_InitStruct.Alternate = GPIO_AF4_I2C3; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + __I2C3_CLK_ENABLE(); + + hi2c3.Instance = I2C3; + hi2c3.Init.ClockSpeed = 400000; + hi2c3.Init.DutyCycle = I2C_DUTYCYCLE_2; + hi2c3.Init.OwnAddress1 = 0x10; + hi2c3.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; + hi2c3.Init.DualAddressMode = I2C_DUALADDRESS_DISABLED; + hi2c3.Init.OwnAddress2 = 0x11; + hi2c3.Init.GeneralCallMode = I2C_GENERALCALL_DISABLED; + hi2c3.Init.NoStretchMode = I2C_NOSTRETCH_DISABLED; + + HAL_I2C_Init(&hi2c3); + + I2Cdev_hi2c = &hi2c3; // init of i2cdevlib. + // You can select other i2c device anytime and + // call the same driver functions on other sensors + + while(!BMP085_testConnection()) ; + + BMP085_initialize(); + char buf[128]; + while (1) + { + BMP085_setControl(BMP085_MODE_TEMPERATURE); + HAL_Delay(BMP085_getMeasureDelayMilliseconds(BMP085_MODE_TEMPERATURE)); + float t = BMP085_getTemperatureC(); + + BMP085_setControl(BMP085_MODE_PRESSURE_3); + HAL_Delay(BMP085_getMeasureDelayMilliseconds(BMP085_MODE_PRESSURE_3)); + float p = BMP085_getPressure(); + + float a = BMP085_getAltitude(p, 101325); + } +} + +void SysTick_Handler() +{ + HAL_IncTick(); + HAL_SYSTICK_IRQHandler(); +} +``` + +## Licence +I2Cdev device library code is placed under the MIT license. + +_Copyright (c) 2011 Jeff Rowberg. Copyright (c) 2015 Andrey Voloshin._ From 1549757526c057d542356fdfa4c0e01ec971713f Mon Sep 17 00:00:00 2001 From: Andrey Voloshin Date: Sat, 6 Jun 2015 15:16:39 +0300 Subject: [PATCH 075/335] Update README.md --- STM32/README.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/STM32/README.md b/STM32/README.md index 89b11a38..e16afe47 100644 --- a/STM32/README.md +++ b/STM32/README.md @@ -1,15 +1,12 @@ # I2C Device Library for STM32 -## I2Cdev -Init your i2c device in HAL set its handler to - ## Devices Currently only BMP180/BMP085 is supported. MPU6050 and HMC5883L will come soon (GY-87 board). Adding more functions and devices should be straighforward after reading the source code of the driver. Porting drivers should be as simple, as renaming public methods from *DRIVER::func()* to *DRIVER_func()* and moving private fields and functions to *.c file ## Example for STM32F429I-DISCO board -``` +```C #include "stm32f4xx.h" #include "stm32f4xx_hal.h" #include From a4534132c4990b008d9ca1a43d16124856b73268 Mon Sep 17 00:00:00 2001 From: Andrey Voloshin Date: Sat, 6 Jun 2015 17:46:16 +0300 Subject: [PATCH 076/335] Fixed private fields visibility --- STM32/BMP085/BMP085.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/STM32/BMP085/BMP085.c b/STM32/BMP085/BMP085.c index 277add9c..20193842 100644 --- a/STM32/BMP085/BMP085.c +++ b/STM32/BMP085/BMP085.c @@ -33,14 +33,14 @@ THE SOFTWARE. #include "BMP085.h" -uint8_t devAddr = BMP085_DEFAULT_ADDRESS; -uint8_t buffer[2]; - -bool calibrationLoaded; -int16_t ac1, ac2, ac3, b1, b2, mb, mc, md; -uint16_t ac4, ac5, ac6; -int32_t b5; -uint8_t measureMode; +static uint8_t devAddr = BMP085_DEFAULT_ADDRESS; +static uint8_t buffer[3]; + +static bool calibrationLoaded; +static int16_t ac1, ac2, ac3, b1, b2, mb, mc, md; +static uint16_t ac4, ac5, ac6; +static int32_t b5; +static uint8_t measureMode; /** * Specific address constructor. From 6f6e72a500c89f68df0c7f3348c1d3d48d5ecb77 Mon Sep 17 00:00:00 2001 From: Andrey Voloshin Date: Sat, 6 Jun 2015 17:51:46 +0300 Subject: [PATCH 077/335] Update and rename README to README.md --- README | 17 ----------------- README.md | 5 +++++ 2 files changed, 5 insertions(+), 17 deletions(-) delete mode 100644 README create mode 100644 README.md diff --git a/README b/README deleted file mode 100644 index 095c8c2f..00000000 --- a/README +++ /dev/null @@ -1,17 +0,0 @@ -L3G4200D gyro fix! - -============================================================================ -Note: for details about this project, please visit: http://www.i2cdevlib.com -============================================================================ - -The I2C Device Library (i2cdevlib) is a collection of uniform and well-documented classes to provide simple and intuitive interfaces to I2C devices. Each device is built to make use of the generic "I2Cdev" class, which abstracts the I2C bit- and byte-level communication away from each specific device class, making it easy to keep the device class clean while providing a simple way to modify just one class to port the I2C communication code onto different platforms (Arduino, PIC, MSP430, simple bit-banging, etc.). Device classes are designed to provide complete coverage of all functionality described by each device's documentation, plus any generic convenience functions that are helpful. - -The code is written primarily to support the Arduino/Wiring implementation, but it may be useful in other circumstances. There are multiple I2C/TWI implementations selectable in the I2Cdev.h header file if the default Arduino "Wire.h" is not available or preferable for any reason. - -There are examples in many of the classes that demonstrate basic usage patterns. The I2Cdev class is built to be used statically, reducing the memory requirement if you have multiple I2C devices in your project. Only one instance of the I2Cdev class is required. - -Documentation for each class is created using Doxygen-style comments placed in each class definition file, based on the information available in each device's datasheet. This documentation is available in HTML format on the i2cdevlib.com website, which also holds helpful information for most of the classes present here on the repository. - -To use the library, just place the I2Cdev .cpp/.h source files and any device library .cpp/.h source files in the same folder as your sketch (or a suitable place relative to your avr-gcc project), and include just the device library headers that you need. Arduino users will also need to include in your main sketch source file. Create a single device object (e.g. "ADXL345 accel();"), place any appropriate init function calls in your setup() routine (e.g. "accel.initialize();"), and off you go! See the example sketches inside many of the device class directories for reference. - -Want a library for a device that isn't up on the repository? Request it, or fork the code and contribute! Better yet, send me a device on a breakout board to test the code during development. No guarantees on how fast I can get it done, but I'd love to make this the biggest consistent and well-documented I2C device library around. diff --git a/README.md b/README.md new file mode 100644 index 00000000..50fbb01e --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +#i2cdevlib ported to STM32 HAL + +See details inside STM32/ + +_Note: for details about this project, please visit: http://www.i2cdevlib.com_ From b22cabd9ffe8663ff23b53415e4bb21f4844d550 Mon Sep 17 00:00:00 2001 From: Andrey Voloshin Date: Sat, 6 Jun 2015 17:55:24 +0300 Subject: [PATCH 078/335] Ported MPU6050 basic functions (like MPU6050_getMotion6()) --- STM32/MPU6050/MPU6050.c | 3150 +++++++++++++++++++++++++++++++++++++++ STM32/MPU6050/MPU6050.h | 989 ++++++++++++ 2 files changed, 4139 insertions(+) create mode 100644 STM32/MPU6050/MPU6050.c create mode 100644 STM32/MPU6050/MPU6050.h diff --git a/STM32/MPU6050/MPU6050.c b/STM32/MPU6050/MPU6050.c new file mode 100644 index 00000000..66e7daf1 --- /dev/null +++ b/STM32/MPU6050/MPU6050.c @@ -0,0 +1,3150 @@ +// I2Cdev library collection - MPU6050 I2C device class +// Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00) +// 8/24/2011 by Jeff Rowberg +// 6/6/2015 by Andrey Voloshin +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// 2015-06-06 - ported to STM32 HAL library from Arduino code + +// NOTE: THIS IS ONLY A PARIAL RELEASE. THIS DEVICE CLASS IS CURRENTLY UNDERGOING ACTIVE +// DEVELOPMENT AND IS STILL MISSING SOME IMPORTANT FEATURES. PLEASE KEEP THIS IN MIND IF +// YOU DECIDE TO USE THIS PARTICULAR CODE FOR ANYTHING. + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2012 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#include "MPU6050.h" + +static uint8_t devAddr; +static uint8_t buffer[14]; + + +/** Valid addresses + * MPU6050_ADDRESS_AD0_LOW + * MPU6050_ADDRESS_AD0_HIGH + */ + +void MPU6050_setAddress(uint8_t address) +{ + devAddr = address; +} + +/** Power on and prepare for general usage. + * This will activate the device and take it out of sleep mode (which must be done + * after start-up). This function also sets both the accelerometer and the gyroscope + * to their most sensitive settings, namely +/- 2g and +/- 250 degrees/sec, and sets + * the clock source to use the X Gyro for reference, which is slightly better than + * the default internal clock source. + */ +void MPU6050_initialize() { + devAddr = MPU6050_ADDRESS_AD0_LOW; + MPU6050_setClockSource(MPU6050_CLOCK_PLL_XGYRO); + MPU6050_setFullScaleGyroRange(MPU6050_GYRO_FS_250); + MPU6050_setFullScaleAccelRange(MPU6050_ACCEL_FS_2); + MPU6050_setSleepEnabled(false); // thanks to Jack Elston for pointing this one out! +} + +/** Verify the I2C connection. + * Make sure the device is connected and responds as expected. + * @return True if connection is valid, false otherwise + */ +bool MPU6050_testConnection() { + return MPU6050_getDeviceID() == 0x34; +} + +// AUX_VDDIO register (InvenSense demo code calls this RA_*G_OFFS_TC) + +/** Get the auxiliary I2C supply voltage level. + * When set to 1, the auxiliary I2C bus high logic level is VDD. When cleared to + * 0, the auxiliary I2C bus high logic level is VLOGIC. This does not apply to + * the MPU-6000, which does not have a VLOGIC pin. + * @return I2C supply voltage level (0=VLOGIC, 1=VDD) + */ +uint8_t MPU6050_getAuxVDDIOLevel() { + I2Cdev_readBit(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_PWR_MODE_BIT, buffer, 0); + return buffer[0]; +} +/** Set the auxiliary I2C supply voltage level. + * When set to 1, the auxiliary I2C bus high logic level is VDD. When cleared to + * 0, the auxiliary I2C bus high logic level is VLOGIC. This does not apply to + * the MPU-6000, which does not have a VLOGIC pin. + * @param level I2C supply voltage level (0=VLOGIC, 1=VDD) + */ +void MPU6050_setAuxVDDIOLevel(uint8_t level) { + I2Cdev_writeBit(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_PWR_MODE_BIT, level); +} + +// SMPLRT_DIV register + +/** Get gyroscope output rate divider. + * The sensor register output, FIFO output, DMP sampling, Motion detection, Zero + * Motion detection, and Free Fall detection are all based on the Sample Rate. + * The Sample Rate is generated by dividing the gyroscope output rate by + * SMPLRT_DIV: + * + * Sample Rate = Gyroscope Output Rate / (1 + SMPLRT_DIV) + * + * where Gyroscope Output Rate = 8kHz when the DLPF is disabled (DLPF_CFG = 0 or + * 7), and 1kHz when the DLPF is enabled (see Register 26). + * + * Note: The accelerometer output rate is 1kHz. This means that for a Sample + * Rate greater than 1kHz, the same accelerometer sample may be output to the + * FIFO, DMP, and sensor registers more than once. + * + * For a diagram of the gyroscope and accelerometer signal paths, see Section 8 + * of the MPU-6000/MPU-6050 Product Specification document. + * + * @return Current sample rate + * @see MPU6050_RA_SMPLRT_DIV + */ +uint8_t MPU6050_getRate() { + I2Cdev_readByte(devAddr, MPU6050_RA_SMPLRT_DIV, buffer, 0); + return buffer[0]; +} +/** Set gyroscope sample rate divider. + * @param rate New sample rate divider + * @see getRate() + * @see MPU6050_RA_SMPLRT_DIV + */ +void MPU6050_setRate(uint8_t rate) { + I2Cdev_writeByte(devAddr, MPU6050_RA_SMPLRT_DIV, rate); +} + +// CONFIG register + +/** Get external FSYNC configuration. + * Configures the external Frame Synchronization (FSYNC) pin sampling. An + * external signal connected to the FSYNC pin can be sampled by configuring + * EXT_SYNC_SET. Signal changes to the FSYNC pin are latched so that short + * strobes may be captured. The latched FSYNC signal will be sampled at the + * Sampling Rate, as defined in register 25. After sampling, the latch will + * reset to the current FSYNC signal state. + * + * The sampled value will be reported in place of the least significant bit in + * a sensor data register determined by the value of EXT_SYNC_SET according to + * the following table. + * + *
+ * EXT_SYNC_SET | FSYNC Bit Location
+ * -------------+-------------------
+ * 0            | Input disabled
+ * 1            | TEMP_OUT_L[0]
+ * 2            | GYRO_XOUT_L[0]
+ * 3            | GYRO_YOUT_L[0]
+ * 4            | GYRO_ZOUT_L[0]
+ * 5            | ACCEL_XOUT_L[0]
+ * 6            | ACCEL_YOUT_L[0]
+ * 7            | ACCEL_ZOUT_L[0]
+ * 
+ * + * @return FSYNC configuration value + */ +uint8_t MPU6050_getExternalFrameSync() { + I2Cdev_readBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_EXT_SYNC_SET_BIT, MPU6050_CFG_EXT_SYNC_SET_LENGTH, buffer, 0); + return buffer[0]; +} +/** Set external FSYNC configuration. + * @see getExternalFrameSync() + * @see MPU6050_RA_CONFIG + * @param sync New FSYNC configuration value + */ +void MPU6050_setExternalFrameSync(uint8_t sync) { + I2Cdev_writeBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_EXT_SYNC_SET_BIT, MPU6050_CFG_EXT_SYNC_SET_LENGTH, sync); +} +/** Get digital low-pass filter configuration. + * The DLPF_CFG parameter sets the digital low pass filter configuration. It + * also determines the internal sampling rate used by the device as shown in + * the table below. + * + * Note: The accelerometer output rate is 1kHz. This means that for a Sample + * Rate greater than 1kHz, the same accelerometer sample may be output to the + * FIFO, DMP, and sensor registers more than once. + * + *
+ *          |   ACCELEROMETER    |           GYROSCOPE
+ * DLPF_CFG | Bandwidth | Delay  | Bandwidth | Delay  | Sample Rate
+ * ---------+-----------+--------+-----------+--------+-------------
+ * 0        | 260Hz     | 0ms    | 256Hz     | 0.98ms | 8kHz
+ * 1        | 184Hz     | 2.0ms  | 188Hz     | 1.9ms  | 1kHz
+ * 2        | 94Hz      | 3.0ms  | 98Hz      | 2.8ms  | 1kHz
+ * 3        | 44Hz      | 4.9ms  | 42Hz      | 4.8ms  | 1kHz
+ * 4        | 21Hz      | 8.5ms  | 20Hz      | 8.3ms  | 1kHz
+ * 5        | 10Hz      | 13.8ms | 10Hz      | 13.4ms | 1kHz
+ * 6        | 5Hz       | 19.0ms | 5Hz       | 18.6ms | 1kHz
+ * 7        |   -- Reserved --   |   -- Reserved --   | Reserved
+ * 
+ * + * @return DLFP configuration + * @see MPU6050_RA_CONFIG + * @see MPU6050_CFG_DLPF_CFG_BIT + * @see MPU6050_CFG_DLPF_CFG_LENGTH + */ +uint8_t MPU6050_getDLPFMode() { + I2Cdev_readBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_DLPF_CFG_BIT, MPU6050_CFG_DLPF_CFG_LENGTH, buffer, 0); + return buffer[0]; +} +/** Set digital low-pass filter configuration. + * @param mode New DLFP configuration setting + * @see getDLPFBandwidth() + * @see MPU6050_DLPF_BW_256 + * @see MPU6050_RA_CONFIG + * @see MPU6050_CFG_DLPF_CFG_BIT + * @see MPU6050_CFG_DLPF_CFG_LENGTH + */ +void MPU6050_setDLPFMode(uint8_t mode) { + I2Cdev_writeBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_DLPF_CFG_BIT, MPU6050_CFG_DLPF_CFG_LENGTH, mode); +} + +// GYRO_CONFIG register + +/** Get full-scale gyroscope range. + * The FS_SEL parameter allows setting the full-scale range of the gyro sensors, + * as described in the table below. + * + *
+ * 0 = +/- 250 degrees/sec
+ * 1 = +/- 500 degrees/sec
+ * 2 = +/- 1000 degrees/sec
+ * 3 = +/- 2000 degrees/sec
+ * 
+ * + * @return Current full-scale gyroscope range setting + * @see MPU6050_GYRO_FS_250 + * @see MPU6050_RA_GYRO_CONFIG + * @see MPU6050_GCONFIG_FS_SEL_BIT + * @see MPU6050_GCONFIG_FS_SEL_LENGTH + */ +uint8_t MPU6050_getFullScaleGyroRange() { + I2Cdev_readBits(devAddr, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, buffer, 0); + return buffer[0]; +} +/** Set full-scale gyroscope range. + * @param range New full-scale gyroscope range value + * @see getFullScaleRange() + * @see MPU6050_GYRO_FS_250 + * @see MPU6050_RA_GYRO_CONFIG + * @see MPU6050_GCONFIG_FS_SEL_BIT + * @see MPU6050_GCONFIG_FS_SEL_LENGTH + */ +void MPU6050_setFullScaleGyroRange(uint8_t range) { + I2Cdev_writeBits(devAddr, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, range); +} + +// ACCEL_CONFIG register + +/** Get self-test enabled setting for accelerometer X axis. + * @return Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +bool MPU6050_getAccelXSelfTest() { + I2Cdev_readBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_XA_ST_BIT, buffer, 0); + return buffer[0]; +} +/** Get self-test enabled setting for accelerometer X axis. + * @param enabled Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050_setAccelXSelfTest(bool enabled) { + I2Cdev_writeBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_XA_ST_BIT, enabled); +} +/** Get self-test enabled value for accelerometer Y axis. + * @return Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +bool MPU6050_getAccelYSelfTest() { + I2Cdev_readBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_YA_ST_BIT, buffer, 0); + return buffer[0]; +} +/** Get self-test enabled value for accelerometer Y axis. + * @param enabled Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050_setAccelYSelfTest(bool enabled) { + I2Cdev_writeBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_YA_ST_BIT, enabled); +} +/** Get self-test enabled value for accelerometer Z axis. + * @return Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +bool MPU6050_getAccelZSelfTest() { + I2Cdev_readBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ZA_ST_BIT, buffer, 0); + return buffer[0]; +} +/** Set self-test enabled value for accelerometer Z axis. + * @param enabled Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050_setAccelZSelfTest(bool enabled) { + I2Cdev_writeBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ZA_ST_BIT, enabled); +} +/** Get full-scale accelerometer range. + * The FS_SEL parameter allows setting the full-scale range of the accelerometer + * sensors, as described in the table below. + * + *
+ * 0 = +/- 2g
+ * 1 = +/- 4g
+ * 2 = +/- 8g
+ * 3 = +/- 16g
+ * 
+ * + * @return Current full-scale accelerometer range setting + * @see MPU6050_ACCEL_FS_2 + * @see MPU6050_RA_ACCEL_CONFIG + * @see MPU6050_ACONFIG_AFS_SEL_BIT + * @see MPU6050_ACONFIG_AFS_SEL_LENGTH + */ +uint8_t MPU6050_getFullScaleAccelRange() { + I2Cdev_readBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, buffer, 0); + return buffer[0]; +} +/** Set full-scale accelerometer range. + * @param range New full-scale accelerometer range setting + * @see getFullScaleAccelRange() + */ +void MPU6050_setFullScaleAccelRange(uint8_t range) { + I2Cdev_writeBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, range); +} +/** Get the high-pass filter configuration. + * The DHPF is a filter module in the path leading to motion detectors (Free + * Fall, Motion threshold, and Zero Motion). The high pass filter output is not + * available to the data registers (see Figure in Section 8 of the MPU-6000/ + * MPU-6050 Product Specification document). + * + * The high pass filter has three modes: + * + *
+ *    Reset: The filter output settles to zero within one sample. This
+ *           effectively disables the high pass filter. This mode may be toggled
+ *           to quickly settle the filter.
+ *
+ *    On:    The high pass filter will pass signals above the cut off frequency.
+ *
+ *    Hold:  When triggered, the filter holds the present sample. The filter
+ *           output will be the difference between the input sample and the held
+ *           sample.
+ * 
+ * + *
+ * ACCEL_HPF | Filter Mode | Cut-off Frequency
+ * ----------+-------------+------------------
+ * 0         | Reset       | None
+ * 1         | On          | 5Hz
+ * 2         | On          | 2.5Hz
+ * 3         | On          | 1.25Hz
+ * 4         | On          | 0.63Hz
+ * 7         | Hold        | None
+ * 
+ * + * @return Current high-pass filter configuration + * @see MPU6050_DHPF_RESET + * @see MPU6050_RA_ACCEL_CONFIG + */ +uint8_t MPU6050_getDHPFMode() { + I2Cdev_readBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ACCEL_HPF_BIT, MPU6050_ACONFIG_ACCEL_HPF_LENGTH, buffer, 0); + return buffer[0]; +} +/** Set the high-pass filter configuration. + * @param bandwidth New high-pass filter configuration + * @see setDHPFMode() + * @see MPU6050_DHPF_RESET + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050_setDHPFMode(uint8_t bandwidth) { + I2Cdev_writeBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ACCEL_HPF_BIT, MPU6050_ACONFIG_ACCEL_HPF_LENGTH, bandwidth); +} + +// FF_THR register + +/** Get free-fall event acceleration threshold. + * This register configures the detection threshold for Free Fall event + * detection. The unit of FF_THR is 1LSB = 2mg. Free Fall is detected when the + * absolute value of the accelerometer measurements for the three axes are each + * less than the detection threshold. This condition increments the Free Fall + * duration counter (Register 30). The Free Fall interrupt is triggered when the + * Free Fall duration counter reaches the time specified in FF_DUR. + * + * For more details on the Free Fall detection interrupt, see Section 8.2 of the + * MPU-6000/MPU-6050 Product Specification document as well as Registers 56 and + * 58 of this document. + * + * @return Current free-fall acceleration threshold value (LSB = 2mg) + * @see MPU6050_RA_FF_THR + */ +uint8_t MPU6050_getFreefallDetectionThreshold() { + I2Cdev_readByte(devAddr, MPU6050_RA_FF_THR, buffer, 0); + return buffer[0]; +} +/** Get free-fall event acceleration threshold. + * @param threshold New free-fall acceleration threshold value (LSB = 2mg) + * @see getFreefallDetectionThreshold() + * @see MPU6050_RA_FF_THR + */ +void MPU6050_setFreefallDetectionThreshold(uint8_t threshold) { + I2Cdev_writeByte(devAddr, MPU6050_RA_FF_THR, threshold); +} + +// FF_DUR register + +/** Get free-fall event duration threshold. + * This register configures the duration counter threshold for Free Fall event + * detection. The duration counter ticks at 1kHz, therefore FF_DUR has a unit + * of 1 LSB = 1 ms. + * + * The Free Fall duration counter increments while the absolute value of the + * accelerometer measurements are each less than the detection threshold + * (Register 29). The Free Fall interrupt is triggered when the Free Fall + * duration counter reaches the time specified in this register. + * + * For more details on the Free Fall detection interrupt, see Section 8.2 of + * the MPU-6000/MPU-6050 Product Specification document as well as Registers 56 + * and 58 of this document. + * + * @return Current free-fall duration threshold value (LSB = 1ms) + * @see MPU6050_RA_FF_DUR + */ +uint8_t MPU6050_getFreefallDetectionDuration() { + I2Cdev_readByte(devAddr, MPU6050_RA_FF_DUR, buffer, 0); + return buffer[0]; +} +/** Get free-fall event duration threshold. + * @param duration New free-fall duration threshold value (LSB = 1ms) + * @see getFreefallDetectionDuration() + * @see MPU6050_RA_FF_DUR + */ +void MPU6050_setFreefallDetectionDuration(uint8_t duration) { + I2Cdev_writeByte(devAddr, MPU6050_RA_FF_DUR, duration); +} + +// MOT_THR register + +/** Get motion detection event acceleration threshold. + * This register configures the detection threshold for Motion interrupt + * generation. The unit of MOT_THR is 1LSB = 2mg. Motion is detected when the + * absolute value of any of the accelerometer measurements exceeds this Motion + * detection threshold. This condition increments the Motion detection duration + * counter (Register 32). The Motion detection interrupt is triggered when the + * Motion Detection counter reaches the time count specified in MOT_DUR + * (Register 32). + * + * The Motion interrupt will indicate the axis and polarity of detected motion + * in MOT_DETECT_STATUS (Register 97). + * + * For more details on the Motion detection interrupt, see Section 8.3 of the + * MPU-6000/MPU-6050 Product Specification document as well as Registers 56 and + * 58 of this document. + * + * @return Current motion detection acceleration threshold value (LSB = 2mg) + * @see MPU6050_RA_MOT_THR + */ +uint8_t MPU6050_getMotionDetectionThreshold() { + I2Cdev_readByte(devAddr, MPU6050_RA_MOT_THR, buffer, 0); + return buffer[0]; +} +/** Set free-fall event acceleration threshold. + * @param threshold New motion detection acceleration threshold value (LSB = 2mg) + * @see getMotionDetectionThreshold() + * @see MPU6050_RA_MOT_THR + */ +void MPU6050_setMotionDetectionThreshold(uint8_t threshold) { + I2Cdev_writeByte(devAddr, MPU6050_RA_MOT_THR, threshold); +} + +// MOT_DUR register + +/** Get motion detection event duration threshold. + * This register configures the duration counter threshold for Motion interrupt + * generation. The duration counter ticks at 1 kHz, therefore MOT_DUR has a unit + * of 1LSB = 1ms. The Motion detection duration counter increments when the + * absolute value of any of the accelerometer measurements exceeds the Motion + * detection threshold (Register 31). The Motion detection interrupt is + * triggered when the Motion detection counter reaches the time count specified + * in this register. + * + * For more details on the Motion detection interrupt, see Section 8.3 of the + * MPU-6000/MPU-6050 Product Specification document. + * + * @return Current motion detection duration threshold value (LSB = 1ms) + * @see MPU6050_RA_MOT_DUR + */ +uint8_t MPU6050_getMotionDetectionDuration() { + I2Cdev_readByte(devAddr, MPU6050_RA_MOT_DUR, buffer, 0); + return buffer[0]; +} +/** Set motion detection event duration threshold. + * @param duration New motion detection duration threshold value (LSB = 1ms) + * @see getMotionDetectionDuration() + * @see MPU6050_RA_MOT_DUR + */ +void MPU6050_setMotionDetectionDuration(uint8_t duration) { + I2Cdev_writeByte(devAddr, MPU6050_RA_MOT_DUR, duration); +} + +// ZRMOT_THR register + +/** Get zero motion detection event acceleration threshold. + * This register configures the detection threshold for Zero Motion interrupt + * generation. The unit of ZRMOT_THR is 1LSB = 2mg. Zero Motion is detected when + * the absolute value of the accelerometer measurements for the 3 axes are each + * less than the detection threshold. This condition increments the Zero Motion + * duration counter (Register 34). The Zero Motion interrupt is triggered when + * the Zero Motion duration counter reaches the time count specified in + * ZRMOT_DUR (Register 34). + * + * Unlike Free Fall or Motion detection, Zero Motion detection triggers an + * interrupt both when Zero Motion is first detected and when Zero Motion is no + * longer detected. + * + * When a zero motion event is detected, a Zero Motion Status will be indicated + * in the MOT_DETECT_STATUS register (Register 97). When a motion-to-zero-motion + * condition is detected, the status bit is set to 1. When a zero-motion-to- + * motion condition is detected, the status bit is set to 0. + * + * For more details on the Zero Motion detection interrupt, see Section 8.4 of + * the MPU-6000/MPU-6050 Product Specification document as well as Registers 56 + * and 58 of this document. + * + * @return Current zero motion detection acceleration threshold value (LSB = 2mg) + * @see MPU6050_RA_ZRMOT_THR + */ +uint8_t MPU6050_getZeroMotionDetectionThreshold() { + I2Cdev_readByte(devAddr, MPU6050_RA_ZRMOT_THR, buffer, 0); + return buffer[0]; +} +/** Set zero motion detection event acceleration threshold. + * @param threshold New zero motion detection acceleration threshold value (LSB = 2mg) + * @see getZeroMotionDetectionThreshold() + * @see MPU6050_RA_ZRMOT_THR + */ +void MPU6050_setZeroMotionDetectionThreshold(uint8_t threshold) { + I2Cdev_writeByte(devAddr, MPU6050_RA_ZRMOT_THR, threshold); +} + +// ZRMOT_DUR register + +/** Get zero motion detection event duration threshold. + * This register configures the duration counter threshold for Zero Motion + * interrupt generation. The duration counter ticks at 16 Hz, therefore + * ZRMOT_DUR has a unit of 1 LSB = 64 ms. The Zero Motion duration counter + * increments while the absolute value of the accelerometer measurements are + * each less than the detection threshold (Register 33). The Zero Motion + * interrupt is triggered when the Zero Motion duration counter reaches the time + * count specified in this register. + * + * For more details on the Zero Motion detection interrupt, see Section 8.4 of + * the MPU-6000/MPU-6050 Product Specification document, as well as Registers 56 + * and 58 of this document. + * + * @return Current zero motion detection duration threshold value (LSB = 64ms) + * @see MPU6050_RA_ZRMOT_DUR + */ +uint8_t MPU6050_getZeroMotionDetectionDuration() { + I2Cdev_readByte(devAddr, MPU6050_RA_ZRMOT_DUR, buffer, 0); + return buffer[0]; +} +/** Set zero motion detection event duration threshold. + * @param duration New zero motion detection duration threshold value (LSB = 1ms) + * @see getZeroMotionDetectionDuration() + * @see MPU6050_RA_ZRMOT_DUR + */ +void MPU6050_setZeroMotionDetectionDuration(uint8_t duration) { + I2Cdev_writeByte(devAddr, MPU6050_RA_ZRMOT_DUR, duration); +} + +// FIFO_EN register + +/** Get temperature FIFO enabled value. + * When set to 1, this bit enables TEMP_OUT_H and TEMP_OUT_L (Registers 65 and + * 66) to be written into the FIFO MPU6050_buffer. + * @return Current temperature FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_getTempFIFOEnabled() { + I2Cdev_readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_TEMP_FIFO_EN_BIT, buffer, 0); + return buffer[0]; +} +/** Set temperature FIFO enabled value. + * @param enabled New temperature FIFO enabled value + * @see getTempFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setTempFIFOEnabled(bool enabled) { + I2Cdev_writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_TEMP_FIFO_EN_BIT, enabled); +} +/** Get gyroscope X-axis FIFO enabled value. + * When set to 1, this bit enables GYRO_XOUT_H and GYRO_XOUT_L (Registers 67 and + * 68) to be written into the FIFO MPU6050_buffer. + * @return Current gyroscope X-axis FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_getXGyroFIFOEnabled() { + I2Cdev_readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_XG_FIFO_EN_BIT, buffer, 0); + return buffer[0]; +} +/** Set gyroscope X-axis FIFO enabled value. + * @param enabled New gyroscope X-axis FIFO enabled value + * @see getXGyroFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setXGyroFIFOEnabled(bool enabled) { + I2Cdev_writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_XG_FIFO_EN_BIT, enabled); +} +/** Get gyroscope Y-axis FIFO enabled value. + * When set to 1, this bit enables GYRO_YOUT_H and GYRO_YOUT_L (Registers 69 and + * 70) to be written into the FIFO MPU6050_buffer. + * @return Current gyroscope Y-axis FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_getYGyroFIFOEnabled() { + I2Cdev_readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_YG_FIFO_EN_BIT, buffer, 0); + return buffer[0]; +} +/** Set gyroscope Y-axis FIFO enabled value. + * @param enabled New gyroscope Y-axis FIFO enabled value + * @see getYGyroFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setYGyroFIFOEnabled(bool enabled) { + I2Cdev_writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_YG_FIFO_EN_BIT, enabled); +} +/** Get gyroscope Z-axis FIFO enabled value. + * When set to 1, this bit enables GYRO_ZOUT_H and GYRO_ZOUT_L (Registers 71 and + * 72) to be written into the FIFO MPU6050_buffer. + * @return Current gyroscope Z-axis FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_getZGyroFIFOEnabled() { + I2Cdev_readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ZG_FIFO_EN_BIT, buffer, 0); + return buffer[0]; +} +/** Set gyroscope Z-axis FIFO enabled value. + * @param enabled New gyroscope Z-axis FIFO enabled value + * @see getZGyroFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setZGyroFIFOEnabled(bool enabled) { + I2Cdev_writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ZG_FIFO_EN_BIT, enabled); +} +/** Get accelerometer FIFO enabled value. + * When set to 1, this bit enables ACCEL_XOUT_H, ACCEL_XOUT_L, ACCEL_YOUT_H, + * ACCEL_YOUT_L, ACCEL_ZOUT_H, and ACCEL_ZOUT_L (Registers 59 to 64) to be + * written into the FIFO MPU6050_buffer. + * @return Current accelerometer FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_getAccelFIFOEnabled() { + I2Cdev_readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ACCEL_FIFO_EN_BIT, buffer, 0); + return buffer[0]; +} +/** Set accelerometer FIFO enabled value. + * @param enabled New accelerometer FIFO enabled value + * @see getAccelFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setAccelFIFOEnabled(bool enabled) { + I2Cdev_writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ACCEL_FIFO_EN_BIT, enabled); +} +/** Get Slave 2 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 2 to be written into the FIFO MPU6050_buffer. + * @return Current Slave 2 FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_getSlave2FIFOEnabled() { + I2Cdev_readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV2_FIFO_EN_BIT, buffer, 0); + return buffer[0]; +} +/** Set Slave 2 FIFO enabled value. + * @param enabled New Slave 2 FIFO enabled value + * @see getSlave2FIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setSlave2FIFOEnabled(bool enabled) { + I2Cdev_writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV2_FIFO_EN_BIT, enabled); +} +/** Get Slave 1 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 1 to be written into the FIFO MPU6050_buffer. + * @return Current Slave 1 FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_getSlave1FIFOEnabled() { + I2Cdev_readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV1_FIFO_EN_BIT, buffer, 0); + return buffer[0]; +} +/** Set Slave 1 FIFO enabled value. + * @param enabled New Slave 1 FIFO enabled value + * @see getSlave1FIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setSlave1FIFOEnabled(bool enabled) { + I2Cdev_writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV1_FIFO_EN_BIT, enabled); +} +/** Get Slave 0 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 0 to be written into the FIFO MPU6050_buffer. + * @return Current Slave 0 FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_getSlave0FIFOEnabled() { + I2Cdev_readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV0_FIFO_EN_BIT, buffer, 0); + return buffer[0]; +} +/** Set Slave 0 FIFO enabled value. + * @param enabled New Slave 0 FIFO enabled value + * @see getSlave0FIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setSlave0FIFOEnabled(bool enabled) { + I2Cdev_writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV0_FIFO_EN_BIT, enabled); +} + +// I2C_MST_CTRL register + +/** Get multi-master enabled value. + * Multi-master capability allows multiple I2C masters to operate on the same + * bus. In circuits where multi-master capability is required, set MULT_MST_EN + * to 1. This will increase current drawn by approximately 30uA. + * + * In circuits where multi-master capability is required, the state of the I2C + * bus must always be monitored by each separate I2C Master. Before an I2C + * Master can assume arbitration of the bus, it must first confirm that no other + * I2C Master has arbitration of the bus. When MULT_MST_EN is set to 1, the + * MPU-60X0's bus arbitration detection logic is turned on, enabling it to + * detect when the bus is available. + * + * @return Current multi-master enabled value + * @see MPU6050_RA_I2C_MST_CTRL + */ +bool MPU6050_getMultiMasterEnabled() { + I2Cdev_readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_MULT_MST_EN_BIT, buffer, 0); + return buffer[0]; +} +/** Set multi-master enabled value. + * @param enabled New multi-master enabled value + * @see getMultiMasterEnabled() + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050_setMultiMasterEnabled(bool enabled) { + I2Cdev_writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_MULT_MST_EN_BIT, enabled); +} +/** Get wait-for-external-sensor-data enabled value. + * When the WAIT_FOR_ES bit is set to 1, the Data Ready interrupt will be + * delayed until External Sensor data from the Slave Devices are loaded into the + * EXT_SENS_DATA registers. This is used to ensure that both the internal sensor + * data (i.e. from gyro and accel) and external sensor data have been loaded to + * their respective data registers (i.e. the data is synced) when the Data Ready + * interrupt is triggered. + * + * @return Current wait-for-external-sensor-data enabled value + * @see MPU6050_RA_I2C_MST_CTRL + */ +bool MPU6050_getWaitForExternalSensorEnabled() { + I2Cdev_readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_WAIT_FOR_ES_BIT, buffer, 0); + return buffer[0]; +} +/** Set wait-for-external-sensor-data enabled value. + * @param enabled New wait-for-external-sensor-data enabled value + * @see getWaitForExternalSensorEnabled() + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050_setWaitForExternalSensorEnabled(bool enabled) { + I2Cdev_writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_WAIT_FOR_ES_BIT, enabled); +} +/** Get Slave 3 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 3 to be written into the FIFO MPU6050_buffer. + * @return Current Slave 3 FIFO enabled value + * @see MPU6050_RA_MST_CTRL + */ +bool MPU6050_getSlave3FIFOEnabled() { + I2Cdev_readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_SLV_3_FIFO_EN_BIT, buffer, 0); + return buffer[0]; +} +/** Set Slave 3 FIFO enabled value. + * @param enabled New Slave 3 FIFO enabled value + * @see getSlave3FIFOEnabled() + * @see MPU6050_RA_MST_CTRL + */ +void MPU6050_setSlave3FIFOEnabled(bool enabled) { + I2Cdev_writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_SLV_3_FIFO_EN_BIT, enabled); +} +/** Get slave read/write transition enabled value. + * The I2C_MST_P_NSR bit configures the I2C Master's transition from one slave + * read to the next slave read. If the bit equals 0, there will be a restart + * between reads. If the bit equals 1, there will be a stop followed by a start + * of the following read. When a write transaction follows a read transaction, + * the stop followed by a start of the successive write will be always used. + * + * @return Current slave read/write transition enabled value + * @see MPU6050_RA_I2C_MST_CTRL + */ +bool MPU6050_getSlaveReadWriteTransitionEnabled() { + I2Cdev_readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_P_NSR_BIT, buffer, 0); + return buffer[0]; +} +/** Set slave read/write transition enabled value. + * @param enabled New slave read/write transition enabled value + * @see getSlaveReadWriteTransitionEnabled() + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050_setSlaveReadWriteTransitionEnabled(bool enabled) { + I2Cdev_writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_P_NSR_BIT, enabled); +} +/** Get I2C master clock speed. + * I2C_MST_CLK is a 4 bit unsigned value which configures a divider on the + * MPU-60X0 internal 8MHz clock. It sets the I2C master clock speed according to + * the following table: + * + *
+ * I2C_MST_CLK | I2C Master Clock Speed | 8MHz Clock Divider
+ * ------------+------------------------+-------------------
+ * 0           | 348kHz                 | 23
+ * 1           | 333kHz                 | 24
+ * 2           | 320kHz                 | 25
+ * 3           | 308kHz                 | 26
+ * 4           | 296kHz                 | 27
+ * 5           | 286kHz                 | 28
+ * 6           | 276kHz                 | 29
+ * 7           | 267kHz                 | 30
+ * 8           | 258kHz                 | 31
+ * 9           | 500kHz                 | 16
+ * 10          | 471kHz                 | 17
+ * 11          | 444kHz                 | 18
+ * 12          | 421kHz                 | 19
+ * 13          | 400kHz                 | 20
+ * 14          | 381kHz                 | 21
+ * 15          | 364kHz                 | 22
+ * 
+ * + * @return Current I2C master clock speed + * @see MPU6050_RA_I2C_MST_CTRL + */ +uint8_t MPU6050_getMasterClockSpeed() { + I2Cdev_readBits(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_CLK_BIT, MPU6050_I2C_MST_CLK_LENGTH, buffer, 0); + return buffer[0]; +} +/** Set I2C master clock speed. + * @reparam speed Current I2C master clock speed + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050_setMasterClockSpeed(uint8_t speed) { + I2Cdev_writeBits(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_CLK_BIT, MPU6050_I2C_MST_CLK_LENGTH, speed); +} + +// I2C_SLV* registers (Slave 0-3) + +/** Get the I2C address of the specified slave (0-3). + * Note that Bit 7 (MSB) controls read/write mode. If Bit 7 is set, it's a read + * operation, and if it is cleared, then it's a write operation. The remaining + * bits (6-0) are the 7-bit device address of the slave device. + * + * In read mode, the result of the read is placed in the lowest available + * EXT_SENS_DATA register. For further information regarding the allocation of + * read results, please refer to the EXT_SENS_DATA register description + * (Registers 73 - 96). + * + * The MPU-6050 supports a total of five slaves, but Slave 4 has unique + * characteristics, and so it has its own functions (getSlave4* and setSlave4*). + * + * I2C data transactions are performed at the Sample Rate, as defined in + * Register 25. The user is responsible for ensuring that I2C data transactions + * to and from each enabled Slave can be completed within a single period of the + * Sample Rate. + * + * The I2C slave access rate can be reduced relative to the Sample Rate. This + * reduced access rate is determined by I2C_MST_DLY (Register 52). Whether a + * slave's access rate is reduced relative to the Sample Rate is determined by + * I2C_MST_DELAY_CTRL (Register 103). + * + * The processing order for the slaves is fixed. The sequence followed for + * processing the slaves is Slave 0, Slave 1, Slave 2, Slave 3 and Slave 4. If a + * particular Slave is disabled it will be skipped. + * + * Each slave can either be accessed at the sample rate or at a reduced sample + * rate. In a case where some slaves are accessed at the Sample Rate and some + * slaves are accessed at the reduced rate, the sequence of accessing the slaves + * (Slave 0 to Slave 4) is still followed. However, the reduced rate slaves will + * be skipped if their access rate dictates that they should not be accessed + * during that particular cycle. For further information regarding the reduced + * access rate, please refer to Register 52. Whether a slave is accessed at the + * Sample Rate or at the reduced rate is determined by the Delay Enable bits in + * Register 103. + * + * @param num Slave number (0-3) + * @return Current address for specified slave + * @see MPU6050_RA_I2C_SLV0_ADDR + */ +uint8_t MPU6050_getSlaveAddress(uint8_t num) { + if (num > 3) return 0; + I2Cdev_readByte(devAddr, MPU6050_RA_I2C_SLV0_ADDR + num*3, buffer, 0); + return buffer[0]; +} +/** Set the I2C address of the specified slave (0-3). + * @param num Slave number (0-3) + * @param address New address for specified slave + * @see getSlaveAddress() + * @see MPU6050_RA_I2C_SLV0_ADDR + */ +void MPU6050_setSlaveAddress(uint8_t num, uint8_t address) { + if (num > 3) return; + I2Cdev_writeByte(devAddr, MPU6050_RA_I2C_SLV0_ADDR + num*3, address); +} +/** Get the active internal register for the specified slave (0-3). + * Read/write operations for this slave will be done to whatever internal + * register address is stored in this MPU register. + * + * The MPU-6050 supports a total of five slaves, but Slave 4 has unique + * characteristics, and so it has its own functions. + * + * @param num Slave number (0-3) + * @return Current active register for specified slave + * @see MPU6050_RA_I2C_SLV0_REG + */ +uint8_t MPU6050_getSlaveRegister(uint8_t num) { + if (num > 3) return 0; + I2Cdev_readByte(devAddr, MPU6050_RA_I2C_SLV0_REG + num*3, buffer, 0); + return buffer[0]; +} +/** Set the active internal register for the specified slave (0-3). + * @param num Slave number (0-3) + * @param reg New active register for specified slave + * @see getSlaveRegister() + * @see MPU6050_RA_I2C_SLV0_REG + */ +void MPU6050_setSlaveRegister(uint8_t num, uint8_t reg) { + if (num > 3) return; + I2Cdev_writeByte(devAddr, MPU6050_RA_I2C_SLV0_REG + num*3, reg); +} +/** Get the enabled value for the specified slave (0-3). + * When set to 1, this bit enables Slave 0 for data transfer operations. When + * cleared to 0, this bit disables Slave 0 from data transfer operations. + * @param num Slave number (0-3) + * @return Current enabled value for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +bool MPU6050_getSlaveEnabled(uint8_t num) { + if (num > 3) return 0; + I2Cdev_readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_EN_BIT, buffer, 0); + return buffer[0]; +} +/** Set the enabled value for the specified slave (0-3). + * @param num Slave number (0-3) + * @param enabled New enabled value for specified slave + * @see getSlaveEnabled() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050_setSlaveEnabled(uint8_t num, bool enabled) { + if (num > 3) return; + I2Cdev_writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_EN_BIT, enabled); +} +/** Get word pair byte-swapping enabled for the specified slave (0-3). + * When set to 1, this bit enables byte swapping. When byte swapping is enabled, + * the high and low bytes of a word pair are swapped. Please refer to + * I2C_SLV0_GRP for the pairing convention of the word pairs. When cleared to 0, + * bytes transferred to and from Slave 0 will be written to EXT_SENS_DATA + * registers in the order they were transferred. + * + * @param num Slave number (0-3) + * @return Current word pair byte-swapping enabled value for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +bool MPU6050_getSlaveWordByteSwap(uint8_t num) { + if (num > 3) return 0; + I2Cdev_readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_BYTE_SW_BIT, buffer, 0); + return buffer[0]; +} +/** Set word pair byte-swapping enabled for the specified slave (0-3). + * @param num Slave number (0-3) + * @param enabled New word pair byte-swapping enabled value for specified slave + * @see getSlaveWordByteSwap() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050_setSlaveWordByteSwap(uint8_t num, bool enabled) { + if (num > 3) return; + I2Cdev_writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_BYTE_SW_BIT, enabled); +} +/** Get write mode for the specified slave (0-3). + * When set to 1, the transaction will read or write data only. When cleared to + * 0, the transaction will write a register address prior to reading or writing + * data. This should equal 0 when specifying the register address within the + * Slave device to/from which the ensuing data transaction will take place. + * + * @param num Slave number (0-3) + * @return Current write mode for specified slave (0 = register address + data, 1 = data only) + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +bool MPU6050_getSlaveWriteMode(uint8_t num) { + if (num > 3) return 0; + I2Cdev_readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_REG_DIS_BIT, buffer, 0); + return buffer[0]; +} +/** Set write mode for the specified slave (0-3). + * @param num Slave number (0-3) + * @param mode New write mode for specified slave (0 = register address + data, 1 = data only) + * @see getSlaveWriteMode() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050_setSlaveWriteMode(uint8_t num, bool mode) { + if (num > 3) return; + I2Cdev_writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_REG_DIS_BIT, mode); +} +/** Get word pair grouping order offset for the specified slave (0-3). + * This sets specifies the grouping order of word pairs received from registers. + * When cleared to 0, bytes from register addresses 0 and 1, 2 and 3, etc (even, + * then odd register addresses) are paired to form a word. When set to 1, bytes + * from register addresses are paired 1 and 2, 3 and 4, etc. (odd, then even + * register addresses) are paired to form a word. + * + * @param num Slave number (0-3) + * @return Current word pair grouping order offset for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +bool MPU6050_getSlaveWordGroupOffset(uint8_t num) { + if (num > 3) return 0; + I2Cdev_readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_GRP_BIT, buffer, 0); + return buffer[0]; +} +/** Set word pair grouping order offset for the specified slave (0-3). + * @param num Slave number (0-3) + * @param enabled New word pair grouping order offset for specified slave + * @see getSlaveWordGroupOffset() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050_setSlaveWordGroupOffset(uint8_t num, bool enabled) { + if (num > 3) return; + I2Cdev_writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_GRP_BIT, enabled); +} +/** Get number of bytes to read for the specified slave (0-3). + * Specifies the number of bytes transferred to and from Slave 0. Clearing this + * bit to 0 is equivalent to disabling the register by writing 0 to I2C_SLV0_EN. + * @param num Slave number (0-3) + * @return Number of bytes to read for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +uint8_t MPU6050_getSlaveDataLength(uint8_t num) { + if (num > 3) return 0; + I2Cdev_readBits(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_LEN_BIT, MPU6050_I2C_SLV_LEN_LENGTH, buffer, 0); + return buffer[0]; +} +/** Set number of bytes to read for the specified slave (0-3). + * @param num Slave number (0-3) + * @param length Number of bytes to read for specified slave + * @see getSlaveDataLength() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050_setSlaveDataLength(uint8_t num, uint8_t length) { + if (num > 3) return; + I2Cdev_writeBits(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_LEN_BIT, MPU6050_I2C_SLV_LEN_LENGTH, length); +} + +// I2C_SLV* registers (Slave 4) + +/** Get the I2C address of Slave 4. + * Note that Bit 7 (MSB) controls read/write mode. If Bit 7 is set, it's a read + * operation, and if it is cleared, then it's a write operation. The remaining + * bits (6-0) are the 7-bit device address of the slave device. + * + * @return Current address for Slave 4 + * @see getSlaveAddress() + * @see MPU6050_RA_I2C_SLV4_ADDR + */ +uint8_t MPU6050_getSlave4Address() { + I2Cdev_readByte(devAddr, MPU6050_RA_I2C_SLV4_ADDR, buffer, 0); + return buffer[0]; +} +/** Set the I2C address of Slave 4. + * @param address New address for Slave 4 + * @see getSlave4Address() + * @see MPU6050_RA_I2C_SLV4_ADDR + */ +void MPU6050_setSlave4Address(uint8_t address) { + I2Cdev_writeByte(devAddr, MPU6050_RA_I2C_SLV4_ADDR, address); +} +/** Get the active internal register for the Slave 4. + * Read/write operations for this slave will be done to whatever internal + * register address is stored in this MPU register. + * + * @return Current active register for Slave 4 + * @see MPU6050_RA_I2C_SLV4_REG + */ +uint8_t MPU6050_getSlave4Register() { + I2Cdev_readByte(devAddr, MPU6050_RA_I2C_SLV4_REG, buffer, 0); + return buffer[0]; +} +/** Set the active internal register for Slave 4. + * @param reg New active register for Slave 4 + * @see getSlave4Register() + * @see MPU6050_RA_I2C_SLV4_REG + */ +void MPU6050_setSlave4Register(uint8_t reg) { + I2Cdev_writeByte(devAddr, MPU6050_RA_I2C_SLV4_REG, reg); +} +/** Set new byte to write to Slave 4. + * This register stores the data to be written into the Slave 4. If I2C_SLV4_RW + * is set 1 (set to read), this register has no effect. + * @param data New byte to write to Slave 4 + * @see MPU6050_RA_I2C_SLV4_DO + */ +void MPU6050_setSlave4OutputByte(uint8_t data) { + I2Cdev_writeByte(devAddr, MPU6050_RA_I2C_SLV4_DO, data); +} +/** Get the enabled value for the Slave 4. + * When set to 1, this bit enables Slave 4 for data transfer operations. When + * cleared to 0, this bit disables Slave 4 from data transfer operations. + * @return Current enabled value for Slave 4 + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +bool MPU6050_getSlave4Enabled() { + I2Cdev_readBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_EN_BIT, buffer, 0); + return buffer[0]; +} +/** Set the enabled value for Slave 4. + * @param enabled New enabled value for Slave 4 + * @see getSlave4Enabled() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050_setSlave4Enabled(bool enabled) { + I2Cdev_writeBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_EN_BIT, enabled); +} +/** Get the enabled value for Slave 4 transaction interrupts. + * When set to 1, this bit enables the generation of an interrupt signal upon + * completion of a Slave 4 transaction. When cleared to 0, this bit disables the + * generation of an interrupt signal upon completion of a Slave 4 transaction. + * The interrupt status can be observed in Register 54. + * + * @return Current enabled value for Slave 4 transaction interrupts. + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +bool MPU6050_getSlave4InterruptEnabled() { + I2Cdev_readBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_INT_EN_BIT, buffer, 0); + return buffer[0]; +} +/** Set the enabled value for Slave 4 transaction interrupts. + * @param enabled New enabled value for Slave 4 transaction interrupts. + * @see getSlave4InterruptEnabled() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050_setSlave4InterruptEnabled(bool enabled) { + I2Cdev_writeBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_INT_EN_BIT, enabled); +} +/** Get write mode for Slave 4. + * When set to 1, the transaction will read or write data only. When cleared to + * 0, the transaction will write a register address prior to reading or writing + * data. This should equal 0 when specifying the register address within the + * Slave device to/from which the ensuing data transaction will take place. + * + * @return Current write mode for Slave 4 (0 = register address + data, 1 = data only) + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +bool MPU6050_getSlave4WriteMode() { + I2Cdev_readBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_REG_DIS_BIT, buffer, 0); + return buffer[0]; +} +/** Set write mode for the Slave 4. + * @param mode New write mode for Slave 4 (0 = register address + data, 1 = data only) + * @see getSlave4WriteMode() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050_setSlave4WriteMode(bool mode) { + I2Cdev_writeBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_REG_DIS_BIT, mode); +} +/** Get Slave 4 master delay value. + * This configures the reduced access rate of I2C slaves relative to the Sample + * Rate. When a slave's access rate is decreased relative to the Sample Rate, + * the slave is accessed every: + * + * 1 / (1 + I2C_MST_DLY) samples + * + * This base Sample Rate in turn is determined by SMPLRT_DIV (register 25) and + * DLPF_CFG (register 26). Whether a slave's access rate is reduced relative to + * the Sample Rate is determined by I2C_MST_DELAY_CTRL (register 103). For + * further information regarding the Sample Rate, please refer to register 25. + * + * @return Current Slave 4 master delay value + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +uint8_t MPU6050_getSlave4MasterDelay() { + I2Cdev_readBits(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_MST_DLY_BIT, MPU6050_I2C_SLV4_MST_DLY_LENGTH, buffer, 0); + return buffer[0]; +} +/** Set Slave 4 master delay value. + * @param delay New Slave 4 master delay value + * @see getSlave4MasterDelay() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050_setSlave4MasterDelay(uint8_t delay) { + I2Cdev_writeBits(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_MST_DLY_BIT, MPU6050_I2C_SLV4_MST_DLY_LENGTH, delay); +} +/** Get last available byte read from Slave 4. + * This register stores the data read from Slave 4. This field is populated + * after a read transaction. + * @return Last available byte read from to Slave 4 + * @see MPU6050_RA_I2C_SLV4_DI + */ +uint8_t MPU6050_getSlate4InputByte() { + I2Cdev_readByte(devAddr, MPU6050_RA_I2C_SLV4_DI, buffer, 0); + return buffer[0]; +} + +// I2C_MST_STATUS register + +/** Get FSYNC interrupt status. + * This bit reflects the status of the FSYNC interrupt from an external device + * into the MPU-60X0. This is used as a way to pass an external interrupt + * through the MPU-60X0 to the host application processor. When set to 1, this + * bit will cause an interrupt if FSYNC_INT_EN is asserted in INT_PIN_CFG + * (Register 55). + * @return FSYNC interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_getPassthroughStatus() { + I2Cdev_readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_PASS_THROUGH_BIT, buffer, 0); + return buffer[0]; +} +/** Get Slave 4 transaction done status. + * Automatically sets to 1 when a Slave 4 transaction has completed. This + * triggers an interrupt if the I2C_MST_INT_EN bit in the INT_ENABLE register + * (Register 56) is asserted and if the SLV_4_DONE_INT bit is asserted in the + * I2C_SLV4_CTRL register (Register 52). + * @return Slave 4 transaction done status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_getSlave4IsDone() { + I2Cdev_readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV4_DONE_BIT, buffer, 0); + return buffer[0]; +} +/** Get master arbitration lost status. + * This bit automatically sets to 1 when the I2C Master has lost arbitration of + * the auxiliary I2C bus (an error condition). This triggers an interrupt if the + * I2C_MST_INT_EN bit in the INT_ENABLE register (Register 56) is asserted. + * @return Master arbitration lost status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_getLostArbitration() { + I2Cdev_readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_LOST_ARB_BIT, buffer, 0); + return buffer[0]; +} +/** Get Slave 4 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 4. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 4 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_getSlave4Nack() { + I2Cdev_readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV4_NACK_BIT, buffer, 0); + return buffer[0]; +} +/** Get Slave 3 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 3. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 3 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_getSlave3Nack() { + I2Cdev_readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV3_NACK_BIT, buffer, 0); + return buffer[0]; +} +/** Get Slave 2 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 2. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 2 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_getSlave2Nack() { + I2Cdev_readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV2_NACK_BIT, buffer, 0); + return buffer[0]; +} +/** Get Slave 1 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 1. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 1 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_getSlave1Nack() { + I2Cdev_readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV1_NACK_BIT, buffer, 0); + return buffer[0]; +} +/** Get Slave 0 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 0. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 0 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_getSlave0Nack() { + I2Cdev_readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV0_NACK_BIT, buffer, 0); + return buffer[0]; +} + +// INT_PIN_CFG register + +/** Get interrupt logic level mode. + * Will be set 0 for active-high, 1 for active-low. + * @return Current interrupt mode (0=active-high, 1=active-low) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_LEVEL_BIT + */ +bool MPU6050_getInterruptMode() { + I2Cdev_readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_LEVEL_BIT, buffer, 0); + return buffer[0]; +} +/** Set interrupt logic level mode. + * @param mode New interrupt mode (0=active-high, 1=active-low) + * @see getInterruptMode() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_LEVEL_BIT + */ +void MPU6050_setInterruptMode(bool mode) { + I2Cdev_writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_LEVEL_BIT, mode); +} +/** Get interrupt drive mode. + * Will be set 0 for push-pull, 1 for open-drain. + * @return Current interrupt drive mode (0=push-pull, 1=open-drain) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_OPEN_BIT + */ +bool MPU6050_getInterruptDrive() { + I2Cdev_readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_OPEN_BIT, buffer, 0); + return buffer[0]; +} +/** Set interrupt drive mode. + * @param drive New interrupt drive mode (0=push-pull, 1=open-drain) + * @see getInterruptDrive() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_OPEN_BIT + */ +void MPU6050_setInterruptDrive(bool drive) { + I2Cdev_writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_OPEN_BIT, drive); +} +/** Get interrupt latch mode. + * Will be set 0 for 50us-pulse, 1 for latch-until-int-cleared. + * @return Current latch mode (0=50us-pulse, 1=latch-until-int-cleared) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_LATCH_INT_EN_BIT + */ +bool MPU6050_getInterruptLatch() { + I2Cdev_readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_LATCH_INT_EN_BIT, buffer, 0); + return buffer[0]; +} +/** Set interrupt latch mode. + * @param latch New latch mode (0=50us-pulse, 1=latch-until-int-cleared) + * @see getInterruptLatch() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_LATCH_INT_EN_BIT + */ +void MPU6050_setInterruptLatch(bool latch) { + I2Cdev_writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_LATCH_INT_EN_BIT, latch); +} +/** Get interrupt latch clear mode. + * Will be set 0 for status-read-only, 1 for any-register-read. + * @return Current latch clear mode (0=status-read-only, 1=any-register-read) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_RD_CLEAR_BIT + */ +bool MPU6050_getInterruptLatchClear() { + I2Cdev_readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_RD_CLEAR_BIT, buffer, 0); + return buffer[0]; +} +/** Set interrupt latch clear mode. + * @param clear New latch clear mode (0=status-read-only, 1=any-register-read) + * @see getInterruptLatchClear() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_RD_CLEAR_BIT + */ +void MPU6050_setInterruptLatchClear(bool clear) { + I2Cdev_writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_RD_CLEAR_BIT, clear); +} +/** Get FSYNC interrupt logic level mode. + * @return Current FSYNC interrupt mode (0=active-high, 1=active-low) + * @see getFSyncInterruptMode() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT + */ +bool MPU6050_getFSyncInterruptLevel() { + I2Cdev_readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT, buffer, 0); + return buffer[0]; +} +/** Set FSYNC interrupt logic level mode. + * @param mode New FSYNC interrupt mode (0=active-high, 1=active-low) + * @see getFSyncInterruptMode() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT + */ +void MPU6050_setFSyncInterruptLevel(bool level) { + I2Cdev_writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT, level); +} +/** Get FSYNC pin interrupt enabled setting. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled setting + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_EN_BIT + */ +bool MPU6050_getFSyncInterruptEnabled() { + I2Cdev_readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_EN_BIT, buffer, 0); + return buffer[0]; +} +/** Set FSYNC pin interrupt enabled setting. + * @param enabled New FSYNC pin interrupt enabled setting + * @see getFSyncInterruptEnabled() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_EN_BIT + */ +void MPU6050_setFSyncInterruptEnabled(bool enabled) { + I2Cdev_writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_EN_BIT, enabled); +} +/** Get I2C bypass enabled status. + * When this bit is equal to 1 and I2C_MST_EN (Register 106 bit[5]) is equal to + * 0, the host application processor will be able to directly access the + * auxiliary I2C bus of the MPU-60X0. When this bit is equal to 0, the host + * application processor will not be able to directly access the auxiliary I2C + * bus of the MPU-60X0 regardless of the state of I2C_MST_EN (Register 106 + * bit[5]). + * @return Current I2C bypass enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_I2C_BYPASS_EN_BIT + */ +bool MPU6050_getI2CBypassEnabled() { + I2Cdev_readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_I2C_BYPASS_EN_BIT, buffer, 0); + return buffer[0]; +} +/** Set I2C bypass enabled status. + * When this bit is equal to 1 and I2C_MST_EN (Register 106 bit[5]) is equal to + * 0, the host application processor will be able to directly access the + * auxiliary I2C bus of the MPU-60X0. When this bit is equal to 0, the host + * application processor will not be able to directly access the auxiliary I2C + * bus of the MPU-60X0 regardless of the state of I2C_MST_EN (Register 106 + * bit[5]). + * @param enabled New I2C bypass enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_I2C_BYPASS_EN_BIT + */ +void MPU6050_setI2CBypassEnabled(bool enabled) { + I2Cdev_writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_I2C_BYPASS_EN_BIT, enabled); +} +/** Get reference clock output enabled status. + * When this bit is equal to 1, a reference clock output is provided at the + * CLKOUT pin. When this bit is equal to 0, the clock output is disabled. For + * further information regarding CLKOUT, please refer to the MPU-60X0 Product + * Specification document. + * @return Current reference clock output enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_CLKOUT_EN_BIT + */ +bool MPU6050_getClockOutputEnabled() { + I2Cdev_readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_CLKOUT_EN_BIT, buffer, 0); + return buffer[0]; +} +/** Set reference clock output enabled status. + * When this bit is equal to 1, a reference clock output is provided at the + * CLKOUT pin. When this bit is equal to 0, the clock output is disabled. For + * further information regarding CLKOUT, please refer to the MPU-60X0 Product + * Specification document. + * @param enabled New reference clock output enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_CLKOUT_EN_BIT + */ +void MPU6050_setClockOutputEnabled(bool enabled) { + I2Cdev_writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_CLKOUT_EN_BIT, enabled); +} + +// INT_ENABLE register + +/** Get full interrupt enabled status. + * Full register byte for all interrupts, for quick reading. Each bit will be + * set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +uint8_t MPU6050_getIntEnabled() { + I2Cdev_readByte(devAddr, MPU6050_RA_INT_ENABLE, buffer, 0); + return buffer[0]; +} +/** Set full interrupt enabled status. + * Full register byte for all interrupts, for quick reading. Each bit should be + * set 0 for disabled, 1 for enabled. + * @param enabled New interrupt enabled status + * @see getIntFreefallEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +void MPU6050_setIntEnabled(uint8_t enabled) { + I2Cdev_writeByte(devAddr, MPU6050_RA_INT_ENABLE, enabled); +} +/** Get Free Fall interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +bool MPU6050_getIntFreefallEnabled() { + I2Cdev_readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FF_BIT, buffer, 0); + return buffer[0]; +} +/** Set Free Fall interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntFreefallEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +void MPU6050_setIntFreefallEnabled(bool enabled) { + I2Cdev_writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FF_BIT, enabled); +} +/** Get Motion Detection interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_MOT_BIT + **/ +bool MPU6050_getIntMotionEnabled() { + I2Cdev_readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_MOT_BIT, buffer, 0); + return buffer[0]; +} +/** Set Motion Detection interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntMotionEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_MOT_BIT + **/ +void MPU6050_setIntMotionEnabled(bool enabled) { + I2Cdev_writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_MOT_BIT, enabled); +} +/** Get Zero Motion Detection interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_ZMOT_BIT + **/ +bool MPU6050_getIntZeroMotionEnabled() { + I2Cdev_readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_ZMOT_BIT, buffer, 0); + return buffer[0]; +} +/** Set Zero Motion Detection interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntZeroMotionEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_ZMOT_BIT + **/ +void MPU6050_setIntZeroMotionEnabled(bool enabled) { + I2Cdev_writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_ZMOT_BIT, enabled); +} +/** Get FIFO MPU6050_buffer Overflow interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT + **/ +bool MPU6050_getIntFIFOBufferOverflowEnabled() { + I2Cdev_readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, buffer, 0); + return buffer[0]; +} +/** Set FIFO MPU6050_buffer Overflow interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntFIFOBufferOverflowEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT + **/ +void MPU6050_setIntFIFOBufferOverflowEnabled(bool enabled) { + I2Cdev_writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, enabled); +} +/** Get I2C Master interrupt enabled status. + * This enables any of the I2C Master interrupt sources to generate an + * interrupt. Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT + **/ +bool MPU6050_getIntI2CMasterEnabled() { + I2Cdev_readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_I2C_MST_INT_BIT, buffer, 0); + return buffer[0]; +} +/** Set I2C Master interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntI2CMasterEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT + **/ +void MPU6050_setIntI2CMasterEnabled(bool enabled) { + I2Cdev_writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_I2C_MST_INT_BIT, enabled); +} +/** Get Data Ready interrupt enabled setting. + * This event occurs each time a write operation to all of the sensor registers + * has been completed. Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_DATA_RDY_BIT + */ +bool MPU6050_getIntDataReadyEnabled() { + I2Cdev_readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DATA_RDY_BIT, buffer, 0); + return buffer[0]; +} +/** Set Data Ready interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntDataReadyEnabled() + * @see MPU6050_RA_INT_CFG + * @see MPU6050_INTERRUPT_DATA_RDY_BIT + */ +void MPU6050_setIntDataReadyEnabled(bool enabled) { + I2Cdev_writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DATA_RDY_BIT, enabled); +} + +// INT_STATUS register + +/** Get full set of interrupt status bits. + * These bits clear to 0 after the register has been read. Very useful + * for getting multiple INT statuses, since each single bit read clears + * all of them because it has to read the whole byte. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + */ +uint8_t MPU6050_getIntStatus() { + I2Cdev_readByte(devAddr, MPU6050_RA_INT_STATUS, buffer, 0); + return buffer[0]; +} +/** Get Free Fall interrupt status. + * This bit automatically sets to 1 when a Free Fall interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_FF_BIT + */ +bool MPU6050_getIntFreefallStatus() { + I2Cdev_readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_FF_BIT, buffer, 0); + return buffer[0]; +} +/** Get Motion Detection interrupt status. + * This bit automatically sets to 1 when a Motion Detection interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_MOT_BIT + */ +bool MPU6050_getIntMotionStatus() { + I2Cdev_readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_MOT_BIT, buffer, 0); + return buffer[0]; +} +/** Get Zero Motion Detection interrupt status. + * This bit automatically sets to 1 when a Zero Motion Detection interrupt has + * been generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_ZMOT_BIT + */ +bool MPU6050_getIntZeroMotionStatus() { + I2Cdev_readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_ZMOT_BIT, buffer, 0); + return buffer[0]; +} +/** Get FIFO MPU6050_buffer Overflow interrupt status. + * This bit automatically sets to 1 when a Free Fall interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT + */ +bool MPU6050_getIntFIFOBufferOverflowStatus() { + I2Cdev_readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, buffer, 0); + return buffer[0]; +} +/** Get I2C Master interrupt status. + * This bit automatically sets to 1 when an I2C Master interrupt has been + * generated. For a list of I2C Master interrupts, please refer to Register 54. + * The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT + */ +bool MPU6050_getIntI2CMasterStatus() { + I2Cdev_readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_I2C_MST_INT_BIT, buffer, 0); + return buffer[0]; +} +/** Get Data Ready interrupt status. + * This bit automatically sets to 1 when a Data Ready interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_DATA_RDY_BIT + */ +bool MPU6050_getIntDataReadyStatus() { + I2Cdev_readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_DATA_RDY_BIT, buffer, 0); + return buffer[0]; +} + +// ACCEL_*OUT_* registers + +/** Get raw 9-axis motion sensor readings (accel/gyro/compass). + * FUNCTION NOT FULLY IMPLEMENTED YET. + * @param ax 16-bit signed integer container for accelerometer X-axis value + * @param ay 16-bit signed integer container for accelerometer Y-axis value + * @param az 16-bit signed integer container for accelerometer Z-axis value + * @param gx 16-bit signed integer container for gyroscope X-axis value + * @param gy 16-bit signed integer container for gyroscope Y-axis value + * @param gz 16-bit signed integer container for gyroscope Z-axis value + * @param mx 16-bit signed integer container for magnetometer X-axis value + * @param my 16-bit signed integer container for magnetometer Y-axis value + * @param mz 16-bit signed integer container for magnetometer Z-axis value + * @see getMotion6() + * @see getAcceleration() + * @see getRotation() + * @see MPU6050_RA_ACCEL_XOUT_H + */ +void MPU6050_getMotion9(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz, int16_t* mx, int16_t* my, int16_t* mz) { + MPU6050_getMotion6(ax, ay, az, gx, gy, gz); + // TODO: magnetometer integration +} +/** Get raw 6-axis motion sensor readings (accel/gyro). + * Retrieves all currently available motion sensor values. + * @param ax 16-bit signed integer container for accelerometer X-axis value + * @param ay 16-bit signed integer container for accelerometer Y-axis value + * @param az 16-bit signed integer container for accelerometer Z-axis value + * @param gx 16-bit signed integer container for gyroscope X-axis value + * @param gy 16-bit signed integer container for gyroscope Y-axis value + * @param gz 16-bit signed integer container for gyroscope Z-axis value + * @see getAcceleration() + * @see getRotation() + * @see MPU6050_RA_ACCEL_XOUT_H + */ +void MPU6050_getMotion6(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz) { + I2Cdev_readBytes(devAddr, MPU6050_RA_ACCEL_XOUT_H, 14, buffer, 0); + *ax = (((int16_t)buffer[0]) << 8) | buffer[1]; + *ay = (((int16_t)buffer[2]) << 8) | buffer[3]; + *az = (((int16_t)buffer[4]) << 8) | buffer[5]; + *gx = (((int16_t)buffer[8]) << 8) | buffer[9]; + *gy = (((int16_t)buffer[10]) << 8) | buffer[11]; + *gz = (((int16_t)buffer[12]) << 8) | buffer[13]; +} +/** Get 3-axis accelerometer readings. + * These registers store the most recent accelerometer measurements. + * Accelerometer measurements are written to these registers at the Sample Rate + * as defined in Register 25. + * + * The accelerometer measurement registers, along with the temperature + * measurement registers, gyroscope measurement registers, and external sensor + * data registers, are composed of two sets of registers: an internal register + * set and a user-facing read register set. + * + * The data within the accelerometer sensors' internal register set is always + * updated at the Sample Rate. Meanwhile, the user-facing read register set + * duplicates the internal register set's data values whenever the serial + * interface is idle. This guarantees that a burst read of sensor registers will + * read measurements from the same sampling instant. Note that if burst reads + * are not used, the user is responsible for ensuring a set of single byte reads + * correspond to a single sampling instant by checking the Data Ready interrupt. + * + * Each 16-bit accelerometer measurement has a full scale defined in ACCEL_FS + * (Register 28). For each full scale setting, the accelerometers' sensitivity + * per LSB in ACCEL_xOUT is shown in the table below: + * + *
+ * AFS_SEL | Full Scale Range | LSB Sensitivity
+ * --------+------------------+----------------
+ * 0       | +/- 2g           | 8192 LSB/mg
+ * 1       | +/- 4g           | 4096 LSB/mg
+ * 2       | +/- 8g           | 2048 LSB/mg
+ * 3       | +/- 16g          | 1024 LSB/mg
+ * 
+ * + * @param x 16-bit signed integer container for X-axis acceleration + * @param y 16-bit signed integer container for Y-axis acceleration + * @param z 16-bit signed integer container for Z-axis acceleration + * @see MPU6050_RA_GYRO_XOUT_H + */ +void MPU6050_getAcceleration(int16_t* x, int16_t* y, int16_t* z) { + I2Cdev_readBytes(devAddr, MPU6050_RA_ACCEL_XOUT_H, 6, buffer, 0); + *x = (((int16_t)buffer[0]) << 8) | buffer[1]; + *y = (((int16_t)buffer[2]) << 8) | buffer[3]; + *z = (((int16_t)buffer[4]) << 8) | buffer[5]; +} +/** Get X-axis accelerometer reading. + * @return X-axis acceleration measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_ACCEL_XOUT_H + */ +int16_t MPU6050_getAccelerationX() { + I2Cdev_readBytes(devAddr, MPU6050_RA_ACCEL_XOUT_H, 2, buffer, 0); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +/** Get Y-axis accelerometer reading. + * @return Y-axis acceleration measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_ACCEL_YOUT_H + */ +int16_t MPU6050_getAccelerationY() { + I2Cdev_readBytes(devAddr, MPU6050_RA_ACCEL_YOUT_H, 2, buffer, 0); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +/** Get Z-axis accelerometer reading. + * @return Z-axis acceleration measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_ACCEL_ZOUT_H + */ +int16_t MPU6050_getAccelerationZ() { + I2Cdev_readBytes(devAddr, MPU6050_RA_ACCEL_ZOUT_H, 2, buffer, 0); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} + +// TEMP_OUT_* registers + +/** Get current internal temperature. + * @return Temperature reading in 16-bit 2's complement format + * @see MPU6050_RA_TEMP_OUT_H + */ +int16_t MPU6050_getTemperature() { + I2Cdev_readBytes(devAddr, MPU6050_RA_TEMP_OUT_H, 2, buffer, 0); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} + +// GYRO_*OUT_* registers + +/** Get 3-axis gyroscope readings. + * These gyroscope measurement registers, along with the accelerometer + * measurement registers, temperature measurement registers, and external sensor + * data registers, are composed of two sets of registers: an internal register + * set and a user-facing read register set. + * The data within the gyroscope sensors' internal register set is always + * updated at the Sample Rate. Meanwhile, the user-facing read register set + * duplicates the internal register set's data values whenever the serial + * interface is idle. This guarantees that a burst read of sensor registers will + * read measurements from the same sampling instant. Note that if burst reads + * are not used, the user is responsible for ensuring a set of single byte reads + * correspond to a single sampling instant by checking the Data Ready interrupt. + * + * Each 16-bit gyroscope measurement has a full scale defined in FS_SEL + * (Register 27). For each full scale setting, the gyroscopes' sensitivity per + * LSB in GYRO_xOUT is shown in the table below: + * + *
+ * FS_SEL | Full Scale Range   | LSB Sensitivity
+ * -------+--------------------+----------------
+ * 0      | +/- 250 degrees/s  | 131 LSB/deg/s
+ * 1      | +/- 500 degrees/s  | 65.5 LSB/deg/s
+ * 2      | +/- 1000 degrees/s | 32.8 LSB/deg/s
+ * 3      | +/- 2000 degrees/s | 16.4 LSB/deg/s
+ * 
+ * + * @param x 16-bit signed integer container for X-axis rotation + * @param y 16-bit signed integer container for Y-axis rotation + * @param z 16-bit signed integer container for Z-axis rotation + * @see getMotion6() + * @see MPU6050_RA_GYRO_XOUT_H + */ +void MPU6050_getRotation(int16_t* x, int16_t* y, int16_t* z) { + I2Cdev_readBytes(devAddr, MPU6050_RA_GYRO_XOUT_H, 6, buffer, 0); + *x = (((int16_t)buffer[0]) << 8) | buffer[1]; + *y = (((int16_t)buffer[2]) << 8) | buffer[3]; + *z = (((int16_t)buffer[4]) << 8) | buffer[5]; +} +/** Get X-axis gyroscope reading. + * @return X-axis rotation measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_GYRO_XOUT_H + */ +int16_t MPU6050_getRotationX() { + I2Cdev_readBytes(devAddr, MPU6050_RA_GYRO_XOUT_H, 2, buffer, 0); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +/** Get Y-axis gyroscope reading. + * @return Y-axis rotation measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_GYRO_YOUT_H + */ +int16_t MPU6050_getRotationY() { + I2Cdev_readBytes(devAddr, MPU6050_RA_GYRO_YOUT_H, 2, buffer, 0); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +/** Get Z-axis gyroscope reading. + * @return Z-axis rotation measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_GYRO_ZOUT_H + */ +int16_t MPU6050_getRotationZ() { + I2Cdev_readBytes(devAddr, MPU6050_RA_GYRO_ZOUT_H, 2, buffer, 0); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} + +// EXT_SENS_DATA_* registers + +/** Read single byte from external sensor data register. + * These registers store data read from external sensors by the Slave 0, 1, 2, + * and 3 on the auxiliary I2C interface. Data read by Slave 4 is stored in + * I2C_SLV4_DI (Register 53). + * + * External sensor data is written to these registers at the Sample Rate as + * defined in Register 25. This access rate can be reduced by using the Slave + * Delay Enable registers (Register 103). + * + * External sensor data registers, along with the gyroscope measurement + * registers, accelerometer measurement registers, and temperature measurement + * registers, are composed of two sets of registers: an internal register set + * and a user-facing read register set. + * + * The data within the external sensors' internal register set is always updated + * at the Sample Rate (or the reduced access rate) whenever the serial interface + * is idle. This guarantees that a burst read of sensor registers will read + * measurements from the same sampling instant. Note that if burst reads are not + * used, the user is responsible for ensuring a set of single byte reads + * correspond to a single sampling instant by checking the Data Ready interrupt. + * + * Data is placed in these external sensor data registers according to + * I2C_SLV0_CTRL, I2C_SLV1_CTRL, I2C_SLV2_CTRL, and I2C_SLV3_CTRL (Registers 39, + * 42, 45, and 48). When more than zero bytes are read (I2C_SLVx_LEN > 0) from + * an enabled slave (I2C_SLVx_EN = 1), the slave is read at the Sample Rate (as + * defined in Register 25) or delayed rate (if specified in Register 52 and + * 103). During each Sample cycle, slave reads are performed in order of Slave + * number. If all slaves are enabled with more than zero bytes to be read, the + * order will be Slave 0, followed by Slave 1, Slave 2, and Slave 3. + * + * Each enabled slave will have EXT_SENS_DATA registers associated with it by + * number of bytes read (I2C_SLVx_LEN) in order of slave number, starting from + * EXT_SENS_DATA_00. Note that this means enabling or disabling a slave may + * change the higher numbered slaves' associated registers. Furthermore, if + * fewer total bytes are being read from the external sensors as a result of + * such a change, then the data remaining in the registers which no longer have + * an associated slave device (i.e. high numbered registers) will remain in + * these previously allocated registers unless reset. + * + * If the sum of the read lengths of all SLVx transactions exceed the number of + * available EXT_SENS_DATA registers, the excess bytes will be dropped. There + * are 24 EXT_SENS_DATA registers and hence the total read lengths between all + * the slaves cannot be greater than 24 or some bytes will be lost. + * + * Note: Slave 4's behavior is distinct from that of Slaves 0-3. For further + * information regarding the characteristics of Slave 4, please refer to + * Registers 49 to 53. + * + * EXAMPLE: + * Suppose that Slave 0 is enabled with 4 bytes to be read (I2C_SLV0_EN = 1 and + * I2C_SLV0_LEN = 4) while Slave 1 is enabled with 2 bytes to be read so that + * I2C_SLV1_EN = 1 and I2C_SLV1_LEN = 2. In such a situation, EXT_SENS_DATA _00 + * through _03 will be associated with Slave 0, while EXT_SENS_DATA _04 and 05 + * will be associated with Slave 1. If Slave 2 is enabled as well, registers + * starting from EXT_SENS_DATA_06 will be allocated to Slave 2. + * + * If Slave 2 is disabled while Slave 3 is enabled in this same situation, then + * registers starting from EXT_SENS_DATA_06 will be allocated to Slave 3 + * instead. + * + * REGISTER ALLOCATION FOR DYNAMIC DISABLE VS. NORMAL DISABLE: + * If a slave is disabled at any time, the space initially allocated to the + * slave in the EXT_SENS_DATA register, will remain associated with that slave. + * This is to avoid dynamic adjustment of the register allocation. + * + * The allocation of the EXT_SENS_DATA registers is recomputed only when (1) all + * slaves are disabled, or (2) the I2C_MST_RST bit is set (Register 106). + * + * This above is also true if one of the slaves gets NACKed and stops + * functioning. + * + * @param position Starting position (0-23) + * @return Byte read from register + */ +uint8_t MPU6050_getExternalSensorByte(int position) { + I2Cdev_readByte(devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, buffer, 0); + return buffer[0]; +} +/** Read word (2 bytes) from external sensor data registers. + * @param position Starting position (0-21) + * @return Word read from register + * @see getExternalSensorByte() + */ +uint16_t MPU6050_getExternalSensorWord(int position) { + I2Cdev_readBytes(devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, 2, buffer, 0); + return (((uint16_t)buffer[0]) << 8) | buffer[1]; +} +/** Read double word (4 bytes) from external sensor data registers. + * @param position Starting position (0-20) + * @return Double word read from registers + * @see getExternalSensorByte() + */ +uint32_t MPU6050_getExternalSensorDWord(int position) { + I2Cdev_readBytes(devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, 4, buffer, 0); + return (((uint32_t)buffer[0]) << 24) | (((uint32_t)buffer[1]) << 16) | (((uint16_t)buffer[2]) << 8) | buffer[3]; +} + +// MOT_DETECT_STATUS register + +/** Get full motion detection status register content (all bits). + * @return Motion detection status byte + * @see MPU6050_RA_MOT_DETECT_STATUS + */ +uint8_t MPU6050_getMotionStatus() { + I2Cdev_readByte(devAddr, MPU6050_RA_MOT_DETECT_STATUS, buffer, 0); + return buffer[0]; +} +/** Get X-axis negative motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_XNEG_BIT + */ +bool MPU6050_getXNegMotionDetected() { + I2Cdev_readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_XNEG_BIT, buffer, 0); + return buffer[0]; +} +/** Get X-axis positive motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_XPOS_BIT + */ +bool MPU6050_getXPosMotionDetected() { + I2Cdev_readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_XPOS_BIT, buffer, 0); + return buffer[0]; +} +/** Get Y-axis negative motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_YNEG_BIT + */ +bool MPU6050_getYNegMotionDetected() { + I2Cdev_readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_YNEG_BIT, buffer, 0); + return buffer[0]; +} +/** Get Y-axis positive motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_YPOS_BIT + */ +bool MPU6050_getYPosMotionDetected() { + I2Cdev_readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_YPOS_BIT, buffer, 0); + return buffer[0]; +} +/** Get Z-axis negative motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_ZNEG_BIT + */ +bool MPU6050_getZNegMotionDetected() { + I2Cdev_readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZNEG_BIT, buffer, 0); + return buffer[0]; +} +/** Get Z-axis positive motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_ZPOS_BIT + */ +bool MPU6050_getZPosMotionDetected() { + I2Cdev_readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZPOS_BIT, buffer, 0); + return buffer[0]; +} +/** Get zero motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_ZRMOT_BIT + */ +bool MPU6050_getZeroMotionDetected() { + I2Cdev_readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZRMOT_BIT, buffer, 0); + return buffer[0]; +} + +// I2C_SLV*_DO register + +/** Write byte to Data Output container for specified slave. + * This register holds the output data written into Slave when Slave is set to + * write mode. For further information regarding Slave control, please + * refer to Registers 37 to 39 and immediately following. + * @param num Slave number (0-3) + * @param data Byte to write + * @see MPU6050_RA_I2C_SLV0_DO + */ +void MPU6050_setSlaveOutputByte(uint8_t num, uint8_t data) { + if (num > 3) return; + I2Cdev_writeByte(devAddr, MPU6050_RA_I2C_SLV0_DO + num, data); +} + +// I2C_MST_DELAY_CTRL register + +/** Get external data shadow delay enabled status. + * This register is used to specify the timing of external sensor data + * shadowing. When DELAY_ES_SHADOW is set to 1, shadowing of external + * sensor data is delayed until all data has been received. + * @return Current external data shadow delay enabled status. + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT + */ +bool MPU6050_getExternalShadowDelayEnabled() { + I2Cdev_readBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT, buffer, 0); + return buffer[0]; +} +/** Set external data shadow delay enabled status. + * @param enabled New external data shadow delay enabled status. + * @see getExternalShadowDelayEnabled() + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT + */ +void MPU6050_setExternalShadowDelayEnabled(bool enabled) { + I2Cdev_writeBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT, enabled); +} +/** Get slave delay enabled status. + * When a particular slave delay is enabled, the rate of access for the that + * slave device is reduced. When a slave's access rate is decreased relative to + * the Sample Rate, the slave is accessed every: + * + * 1 / (1 + I2C_MST_DLY) Samples + * + * This base Sample Rate in turn is determined by SMPLRT_DIV (register * 25) + * and DLPF_CFG (register 26). + * + * For further information regarding I2C_MST_DLY, please refer to register 52. + * For further information regarding the Sample Rate, please refer to register 25. + * + * @param num Slave number (0-4) + * @return Current slave delay enabled status. + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT + */ +bool MPU6050_getSlaveDelayEnabled(uint8_t num) { + // MPU6050_DELAYCTRL_I2C_SLV4_DLY_EN_BIT is 4, SLV3 is 3, etc. + if (num > 4) return 0; + I2Cdev_readBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, num, buffer, 0); + return buffer[0]; +} +/** Set slave delay enabled status. + * @param num Slave number (0-4) + * @param enabled New slave delay enabled status. + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT + */ +void MPU6050_setSlaveDelayEnabled(uint8_t num, bool enabled) { + I2Cdev_writeBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, num, enabled); +} + +// SIGNAL_PATH_RESET register + +/** Reset gyroscope signal path. + * The reset will revert the signal path analog to digital converters and + * filters to their power up configurations. + * @see MPU6050_RA_SIGNAL_PATH_RESET + * @see MPU6050_PATHRESET_GYRO_RESET_BIT + */ +void MPU6050_resetGyroscopePath() { + I2Cdev_writeBit(devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_GYRO_RESET_BIT, true); +} +/** Reset accelerometer signal path. + * The reset will revert the signal path analog to digital converters and + * filters to their power up configurations. + * @see MPU6050_RA_SIGNAL_PATH_RESET + * @see MPU6050_PATHRESET_ACCEL_RESET_BIT + */ +void MPU6050_resetAccelerometerPath() { + I2Cdev_writeBit(devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_ACCEL_RESET_BIT, true); +} +/** Reset temperature sensor signal path. + * The reset will revert the signal path analog to digital converters and + * filters to their power up configurations. + * @see MPU6050_RA_SIGNAL_PATH_RESET + * @see MPU6050_PATHRESET_TEMP_RESET_BIT + */ +void MPU6050_resetTemperaturePath() { + I2Cdev_writeBit(devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_TEMP_RESET_BIT, true); +} + +// MOT_DETECT_CTRL register + +/** Get accelerometer power-on delay. + * The accelerometer data path provides samples to the sensor registers, Motion + * detection, Zero Motion detection, and Free Fall detection modules. The + * signal path contains filters which must be flushed on wake-up with new + * samples before the detection modules begin operations. The default wake-up + * delay, of 4ms can be lengthened by up to 3ms. This additional delay is + * specified in ACCEL_ON_DELAY in units of 1 LSB = 1 ms. The user may select + * any value above zero unless instructed otherwise by InvenSense. Please refer + * to Section 8 of the MPU-6000/MPU-6050 Product Specification document for + * further information regarding the detection modules. + * @return Current accelerometer power-on delay + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_ACCEL_ON_DELAY_BIT + */ +uint8_t MPU6050_getAccelerometerPowerOnDelay() { + I2Cdev_readBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_ACCEL_ON_DELAY_BIT, MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH, buffer, 0); + return buffer[0]; +} +/** Set accelerometer power-on delay. + * @param delay New accelerometer power-on delay (0-3) + * @see getAccelerometerPowerOnDelay() + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_ACCEL_ON_DELAY_BIT + */ +void MPU6050_setAccelerometerPowerOnDelay(uint8_t delay) { + I2Cdev_writeBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_ACCEL_ON_DELAY_BIT, MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH, delay); +} +/** Get Free Fall detection counter decrement configuration. + * Detection is registered by the Free Fall detection module after accelerometer + * measurements meet their respective threshold conditions over a specified + * number of samples. When the threshold conditions are met, the corresponding + * detection counter increments by 1. The user may control the rate at which the + * detection counter decrements when the threshold condition is not met by + * configuring FF_COUNT. The decrement rate can be set according to the + * following table: + * + *
+ * FF_COUNT | Counter Decrement
+ * ---------+------------------
+ * 0        | Reset
+ * 1        | 1
+ * 2        | 2
+ * 3        | 4
+ * 
+ * + * When FF_COUNT is configured to 0 (reset), any non-qualifying sample will + * reset the counter to 0. For further information on Free Fall detection, + * please refer to Registers 29 to 32. + * + * @return Current decrement configuration + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_FF_COUNT_BIT + */ +uint8_t MPU6050_getFreefallDetectionCounterDecrement() { + I2Cdev_readBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_FF_COUNT_BIT, MPU6050_DETECT_FF_COUNT_LENGTH, buffer, 0); + return buffer[0]; +} +/** Set Free Fall detection counter decrement configuration. + * @param decrement New decrement configuration value + * @see getFreefallDetectionCounterDecrement() + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_FF_COUNT_BIT + */ +void MPU6050_setFreefallDetectionCounterDecrement(uint8_t decrement) { + I2Cdev_writeBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_FF_COUNT_BIT, MPU6050_DETECT_FF_COUNT_LENGTH, decrement); +} +/** Get Motion detection counter decrement configuration. + * Detection is registered by the Motion detection module after accelerometer + * measurements meet their respective threshold conditions over a specified + * number of samples. When the threshold conditions are met, the corresponding + * detection counter increments by 1. The user may control the rate at which the + * detection counter decrements when the threshold condition is not met by + * configuring MOT_COUNT. The decrement rate can be set according to the + * following table: + * + *
+ * MOT_COUNT | Counter Decrement
+ * ----------+------------------
+ * 0         | Reset
+ * 1         | 1
+ * 2         | 2
+ * 3         | 4
+ * 
+ * + * When MOT_COUNT is configured to 0 (reset), any non-qualifying sample will + * reset the counter to 0. For further information on Motion detection, + * please refer to Registers 29 to 32. + * + */ +uint8_t MPU6050_getMotionDetectionCounterDecrement() { + I2Cdev_readBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_MOT_COUNT_BIT, MPU6050_DETECT_MOT_COUNT_LENGTH, buffer, 0); + return buffer[0]; +} +/** Set Motion detection counter decrement configuration. + * @param decrement New decrement configuration value + * @see getMotionDetectionCounterDecrement() + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_MOT_COUNT_BIT + */ +void MPU6050_setMotionDetectionCounterDecrement(uint8_t decrement) { + I2Cdev_writeBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_MOT_COUNT_BIT, MPU6050_DETECT_MOT_COUNT_LENGTH, decrement); +} + +// USER_CTRL register + +/** Get FIFO enabled status. + * When this bit is set to 0, the FIFO MPU6050_buffer is disabled. The FIFO MPU6050_buffer + * cannot be written to or read from while disabled. The FIFO MPU6050_buffer's state + * does not change unless the MPU-60X0 is power cycled. + * @return Current FIFO enabled status + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_FIFO_EN_BIT + */ +bool MPU6050_getFIFOEnabled() { + I2Cdev_readBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_EN_BIT, buffer, 0); + return buffer[0]; +} +/** Set FIFO enabled status. + * @param enabled New FIFO enabled status + * @see getFIFOEnabled() + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_FIFO_EN_BIT + */ +void MPU6050_setFIFOEnabled(bool enabled) { + I2Cdev_writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_EN_BIT, enabled); +} +/** Get I2C Master Mode enabled status. + * When this mode is enabled, the MPU-60X0 acts as the I2C Master to the + * external sensor slave devices on the auxiliary I2C bus. When this bit is + * cleared to 0, the auxiliary I2C bus lines (AUX_DA and AUX_CL) are logically + * driven by the primary I2C bus (SDA and SCL). This is a precondition to + * enabling Bypass Mode. For further information regarding Bypass Mode, please + * refer to Register 55. + * @return Current I2C Master Mode enabled status + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_I2C_MST_EN_BIT + */ +bool MPU6050_getI2CMasterModeEnabled() { + I2Cdev_readBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_EN_BIT, buffer, 0); + return buffer[0]; +} +/** Set I2C Master Mode enabled status. + * @param enabled New I2C Master Mode enabled status + * @see getI2CMasterModeEnabled() + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_I2C_MST_EN_BIT + */ +void MPU6050_setI2CMasterModeEnabled(bool enabled) { + I2Cdev_writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_EN_BIT, enabled); +} +/** Switch from I2C to SPI mode (MPU-6000 only) + * If this is set, the primary SPI interface will be enabled in place of the + * disabled primary I2C interface. + */ +void MPU6050_switchSPIEnabled(bool enabled) { + I2Cdev_writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_IF_DIS_BIT, enabled); +} +/** Reset the FIFO. + * This bit resets the FIFO MPU6050_buffer when set to 1 while FIFO_EN equals 0. This + * bit automatically clears to 0 after the reset has been triggered. + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_FIFO_RESET_BIT + */ +void MPU6050_resetFIFO() { + I2Cdev_writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_RESET_BIT, true); +} +/** Reset the I2C Master. + * This bit resets the I2C Master when set to 1 while I2C_MST_EN equals 0. + * This bit automatically clears to 0 after the reset has been triggered. + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_I2C_MST_RESET_BIT + */ +void MPU6050_resetI2CMaster() { + I2Cdev_writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_RESET_BIT, true); +} +/** Reset all sensor registers and signal paths. + * When set to 1, this bit resets the signal paths for all sensors (gyroscopes, + * accelerometers, and temperature sensor). This operation will also clear the + * sensor registers. This bit automatically clears to 0 after the reset has been + * triggered. + * + * When resetting only the signal path (and not the sensor registers), please + * use Register 104, SIGNAL_PATH_RESET. + * + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_SIG_COND_RESET_BIT + */ +void MPU6050_resetSensors() { + I2Cdev_writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_SIG_COND_RESET_BIT, true); +} + +// PWR_MGMT_1 register + +/** Trigger a full device reset. + * A small delay of ~50ms may be desirable after triggering a reset. + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_DEVICE_RESET_BIT + */ +void MPU6050_reset() { + I2Cdev_writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_DEVICE_RESET_BIT, true); +} +/** Get sleep mode status. + * Setting the SLEEP bit in the register puts the device into very low power + * sleep mode. In this mode, only the serial interface and internal registers + * remain active, allowing for a very low standby current. Clearing this bit + * puts the device back into normal mode. To save power, the individual standby + * selections for each of the gyros should be used if any gyro axis is not used + * by the application. + * @return Current sleep mode enabled status + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_SLEEP_BIT + */ +bool MPU6050_getSleepEnabled() { + I2Cdev_readBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, buffer, 0); + return buffer[0]; +} +/** Set sleep mode status. + * @param enabled New sleep mode enabled status + * @see getSleepEnabled() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_SLEEP_BIT + */ +void MPU6050_setSleepEnabled(bool enabled) { + I2Cdev_writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, enabled); +} +/** Get wake cycle enabled status. + * When this bit is set to 1 and SLEEP is disabled, the MPU-60X0 will cycle + * between sleep mode and waking up to take a single sample of data from active + * sensors at a rate determined by LP_WAKE_CTRL (register 108). + * @return Current sleep mode enabled status + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CYCLE_BIT + */ +bool MPU6050_getWakeCycleEnabled() { + I2Cdev_readBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CYCLE_BIT, buffer, 0); + return buffer[0]; +} +/** Set wake cycle enabled status. + * @param enabled New sleep mode enabled status + * @see getWakeCycleEnabled() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CYCLE_BIT + */ +void MPU6050_setWakeCycleEnabled(bool enabled) { + I2Cdev_writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CYCLE_BIT, enabled); +} +/** Get temperature sensor enabled status. + * Control the usage of the internal temperature sensor. + * + * Note: this register stores the *disabled* value, but for consistency with the + * rest of the code, the function is named and used with standard true/false + * values to indicate whether the sensor is enabled or disabled, respectively. + * + * @return Current temperature sensor enabled status + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_TEMP_DIS_BIT + */ +bool MPU6050_getTempSensorEnabled() { + I2Cdev_readBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_TEMP_DIS_BIT, buffer, 0); + return buffer[0] == 0; // 1 is actually disabled here +} +/** Set temperature sensor enabled status. + * Note: this register stores the *disabled* value, but for consistency with the + * rest of the code, the function is named and used with standard true/false + * values to indicate whether the sensor is enabled or disabled, respectively. + * + * @param enabled New temperature sensor enabled status + * @see getTempSensorEnabled() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_TEMP_DIS_BIT + */ +void MPU6050_setTempSensorEnabled(bool enabled) { + // 1 is actually disabled here + I2Cdev_writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_TEMP_DIS_BIT, !enabled); +} +/** Get clock source setting. + * @return Current clock source setting + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CLKSEL_BIT + * @see MPU6050_PWR1_CLKSEL_LENGTH + */ +uint8_t MPU6050_getClockSource() { + I2Cdev_readBits(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, buffer, 0); + return buffer[0]; +} +/** Set clock source setting. + * An internal 8MHz oscillator, gyroscope based clock, or external sources can + * be selected as the MPU-60X0 clock source. When the internal 8 MHz oscillator + * or an external source is chosen as the clock source, the MPU-60X0 can operate + * in low power modes with the gyroscopes disabled. + * + * Upon power up, the MPU-60X0 clock source defaults to the internal oscillator. + * However, it is highly recommended that the device be configured to use one of + * the gyroscopes (or an external clock source) as the clock reference for + * improved stability. The clock source can be selected according to the following table: + * + *
+ * CLK_SEL | Clock Source
+ * --------+--------------------------------------
+ * 0       | Internal oscillator
+ * 1       | PLL with X Gyro reference
+ * 2       | PLL with Y Gyro reference
+ * 3       | PLL with Z Gyro reference
+ * 4       | PLL with external 32.768kHz reference
+ * 5       | PLL with external 19.2MHz reference
+ * 6       | Reserved
+ * 7       | Stops the clock and keeps the timing generator in reset
+ * 
+ * + * @param source New clock source setting + * @see getClockSource() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CLKSEL_BIT + * @see MPU6050_PWR1_CLKSEL_LENGTH + */ +void MPU6050_setClockSource(uint8_t source) { + I2Cdev_writeBits(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, source); +} + +// PWR_MGMT_2 register + +/** Get wake frequency in Accel-Only Low Power Mode. + * The MPU-60X0 can be put into Accerlerometer Only Low Power Mode by setting + * PWRSEL to 1 in the Power Management 1 register (Register 107). In this mode, + * the device will power off all devices except for the primary I2C interface, + * waking only the accelerometer at fixed intervals to take a single + * measurement. The frequency of wake-ups can be configured with LP_WAKE_CTRL + * as shown below: + * + *
+ * LP_WAKE_CTRL | Wake-up Frequency
+ * -------------+------------------
+ * 0            | 1.25 Hz
+ * 1            | 2.5 Hz
+ * 2            | 5 Hz
+ * 3            | 10 Hz
+ * 
+ *
+ * For further information regarding the MPU-60X0's power modes, please refer to
+ * Register 107.
+ *
+ * @return Current wake frequency
+ * @see MPU6050_RA_PWR_MGMT_2
+ */
+uint8_t MPU6050_getWakeFrequency() {
+    I2Cdev_readBits(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_LP_WAKE_CTRL_BIT, MPU6050_PWR2_LP_WAKE_CTRL_LENGTH, buffer, 0);
+    return buffer[0];
+}
+/** Set wake frequency in Accel-Only Low Power Mode.
+ * @param frequency New wake frequency
+ * @see MPU6050_RA_PWR_MGMT_2
+ */
+void MPU6050_setWakeFrequency(uint8_t frequency) {
+    I2Cdev_writeBits(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_LP_WAKE_CTRL_BIT, MPU6050_PWR2_LP_WAKE_CTRL_LENGTH, frequency);
+}
+
+/** Get X-axis accelerometer standby enabled status.
+ * If enabled, the X-axis will not gather or report data (or use power).
+ * @return Current X-axis standby enabled status
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_XA_BIT
+ */
+bool MPU6050_getStandbyXAccelEnabled() {
+    I2Cdev_readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XA_BIT, buffer, 0);
+    return buffer[0];
+}
+/** Set X-axis accelerometer standby enabled status.
+ * @param New X-axis standby enabled status
+ * @see getStandbyXAccelEnabled()
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_XA_BIT
+ */
+void MPU6050_setStandbyXAccelEnabled(bool enabled) {
+    I2Cdev_writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XA_BIT, enabled);
+}
+/** Get Y-axis accelerometer standby enabled status.
+ * If enabled, the Y-axis will not gather or report data (or use power).
+ * @return Current Y-axis standby enabled status
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_YA_BIT
+ */
+bool MPU6050_getStandbyYAccelEnabled() {
+    I2Cdev_readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YA_BIT, buffer, 0);
+    return buffer[0];
+}
+/** Set Y-axis accelerometer standby enabled status.
+ * @param New Y-axis standby enabled status
+ * @see getStandbyYAccelEnabled()
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_YA_BIT
+ */
+void MPU6050_setStandbyYAccelEnabled(bool enabled) {
+    I2Cdev_writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YA_BIT, enabled);
+}
+/** Get Z-axis accelerometer standby enabled status.
+ * If enabled, the Z-axis will not gather or report data (or use power).
+ * @return Current Z-axis standby enabled status
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_ZA_BIT
+ */
+bool MPU6050_getStandbyZAccelEnabled() {
+    I2Cdev_readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZA_BIT, buffer, 0);
+    return buffer[0];
+}
+/** Set Z-axis accelerometer standby enabled status.
+ * @param New Z-axis standby enabled status
+ * @see getStandbyZAccelEnabled()
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_ZA_BIT
+ */
+void MPU6050_setStandbyZAccelEnabled(bool enabled) {
+    I2Cdev_writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZA_BIT, enabled);
+}
+/** Get X-axis gyroscope standby enabled status.
+ * If enabled, the X-axis will not gather or report data (or use power).
+ * @return Current X-axis standby enabled status
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_XG_BIT
+ */
+bool MPU6050_getStandbyXGyroEnabled() {
+    I2Cdev_readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XG_BIT, buffer, 0);
+    return buffer[0];
+}
+/** Set X-axis gyroscope standby enabled status.
+ * @param New X-axis standby enabled status
+ * @see getStandbyXGyroEnabled()
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_XG_BIT
+ */
+void MPU6050_setStandbyXGyroEnabled(bool enabled) {
+    I2Cdev_writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XG_BIT, enabled);
+}
+/** Get Y-axis gyroscope standby enabled status.
+ * If enabled, the Y-axis will not gather or report data (or use power).
+ * @return Current Y-axis standby enabled status
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_YG_BIT
+ */
+bool MPU6050_getStandbyYGyroEnabled() {
+    I2Cdev_readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YG_BIT, buffer, 0);
+    return buffer[0];
+}
+/** Set Y-axis gyroscope standby enabled status.
+ * @param New Y-axis standby enabled status
+ * @see getStandbyYGyroEnabled()
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_YG_BIT
+ */
+void MPU6050_setStandbyYGyroEnabled(bool enabled) {
+    I2Cdev_writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YG_BIT, enabled);
+}
+/** Get Z-axis gyroscope standby enabled status.
+ * If enabled, the Z-axis will not gather or report data (or use power).
+ * @return Current Z-axis standby enabled status
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_ZG_BIT
+ */
+bool MPU6050_getStandbyZGyroEnabled() {
+    I2Cdev_readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZG_BIT, buffer, 0);
+    return buffer[0];
+}
+/** Set Z-axis gyroscope standby enabled status.
+ * @param New Z-axis standby enabled status
+ * @see getStandbyZGyroEnabled()
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_ZG_BIT
+ */
+void MPU6050_setStandbyZGyroEnabled(bool enabled) {
+    I2Cdev_writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZG_BIT, enabled);
+}
+
+// FIFO_COUNT* registers
+
+/** Get current FIFO MPU6050_buffer size.
+ * This value indicates the number of bytes stored in the FIFO MPU6050_buffer. This
+ * number is in turn the number of bytes that can be read from the FIFO MPU6050_buffer
+ * and it is directly proportional to the number of samples available given the
+ * set of sensor data bound to be stored in the FIFO (register 35 and 36).
+ * @return Current FIFO MPU6050_buffer size
+ */
+uint16_t MPU6050_getFIFOCount() {
+    I2Cdev_readBytes(devAddr, MPU6050_RA_FIFO_COUNTH, 2, buffer, 0);
+    return (((uint16_t)buffer[0]) << 8) | buffer[1];
+}
+
+// FIFO_R_W register
+
+/** Get byte from FIFO MPU6050_buffer.
+ * This register is used to read and write data from the FIFO MPU6050_buffer. Data is
+ * written to the FIFO in order of register number (from lowest to highest). If
+ * all the FIFO enable flags (see below) are enabled and all External Sensor
+ * Data registers (Registers 73 to 96) are associated with a Slave device, the
+ * contents of registers 59 through 96 will be written in order at the Sample
+ * Rate.
+ *
+ * The contents of the sensor data registers (Registers 59 to 96) are written
+ * into the FIFO MPU6050_buffer when their corresponding FIFO enable flags are set to 1
+ * in FIFO_EN (Register 35). An additional flag for the sensor data registers
+ * associated with I2C Slave 3 can be found in I2C_MST_CTRL (Register 36).
+ *
+ * If the FIFO MPU6050_buffer has overflowed, the status bit FIFO_OFLOW_INT is
+ * automatically set to 1. This bit is located in INT_STATUS (Register 58).
+ * When the FIFO MPU6050_buffer has overflowed, the oldest data will be lost and new
+ * data will be written to the FIFO.
+ *
+ * If the FIFO MPU6050_buffer is empty, reading this register will return the last byte
+ * that was previously read from the FIFO until new data is available. The user
+ * should check FIFO_COUNT to ensure that the FIFO MPU6050_buffer is not read when
+ * empty.
+ *
+ * @return Byte from FIFO MPU6050_buffer
+ */
+uint8_t MPU6050_getFIFOByte() {
+    I2Cdev_readByte(devAddr, MPU6050_RA_FIFO_R_W, buffer, 0);
+    return buffer[0];
+}
+void MPU6050_getFIFOBytes(uint8_t *data, uint8_t length) {
+    I2Cdev_readBytes(devAddr, MPU6050_RA_FIFO_R_W, length, data, 0);
+}
+/** Write byte to FIFO MPU6050_buffer.
+ * @see getFIFOByte()
+ * @see MPU6050_RA_FIFO_R_W
+ */
+void MPU6050_setFIFOByte(uint8_t data) {
+    I2Cdev_writeByte(devAddr, MPU6050_RA_FIFO_R_W, data);
+}
+
+// WHO_AM_I register
+
+/** Get Device ID.
+ * This register is used to verify the identity of the device (0b110100, 0x34).
+ * @return Device ID (6 bits only! should be 0x34)
+ * @see MPU6050_RA_WHO_AM_I
+ * @see MPU6050_WHO_AM_I_BIT
+ * @see MPU6050_WHO_AM_I_LENGTH
+ */
+uint8_t MPU6050_getDeviceID() {
+    I2Cdev_readBits(devAddr, MPU6050_RA_WHO_AM_I, MPU6050_WHO_AM_I_BIT, MPU6050_WHO_AM_I_LENGTH, buffer, 0);
+    return buffer[0];
+}
+/** Set Device ID.
+ * Write a new ID into the WHO_AM_I register (no idea why this should ever be
+ * necessary though).
+ * @param id New device ID to set.
+ * @see getDeviceID()
+ * @see MPU6050_RA_WHO_AM_I
+ * @see MPU6050_WHO_AM_I_BIT
+ * @see MPU6050_WHO_AM_I_LENGTH
+ */
+void MPU6050_setDeviceID(uint8_t id) {
+    I2Cdev_writeBits(devAddr, MPU6050_RA_WHO_AM_I, MPU6050_WHO_AM_I_BIT, MPU6050_WHO_AM_I_LENGTH, id);
+}
+
+// ======== UNDOCUMENTED/DMP REGISTERS/METHODS ========
+
+// XG_OFFS_TC register
+
+uint8_t MPU6050_getOTPBankValid() {
+    I2Cdev_readBit(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OTP_BNK_VLD_BIT, buffer, 0);
+    return buffer[0];
+}
+void MPU6050_setOTPBankValid(bool enabled) {
+    I2Cdev_writeBit(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OTP_BNK_VLD_BIT, enabled);
+}
+int8_t MPU6050_getXGyroOffsetTC() {
+    I2Cdev_readBits(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, buffer, 0);
+    return buffer[0];
+}
+void MPU6050_setXGyroOffsetTC(int8_t offset) {
+    I2Cdev_writeBits(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset);
+}
+
+// YG_OFFS_TC register
+
+int8_t MPU6050_getYGyroOffsetTC() {
+    I2Cdev_readBits(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, buffer, 0);
+    return buffer[0];
+}
+void MPU6050_setYGyroOffsetTC(int8_t offset) {
+    I2Cdev_writeBits(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset);
+}
+
+// ZG_OFFS_TC register
+
+int8_t MPU6050_getZGyroOffsetTC() {
+    I2Cdev_readBits(devAddr, MPU6050_RA_ZG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, buffer, 0);
+    return buffer[0];
+}
+void MPU6050_setZGyroOffsetTC(int8_t offset) {
+    I2Cdev_writeBits(devAddr, MPU6050_RA_ZG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset);
+}
+
+// X_FINE_GAIN register
+
+int8_t MPU6050_getXFineGain() {
+    I2Cdev_readByte(devAddr, MPU6050_RA_X_FINE_GAIN, buffer, 0);
+    return buffer[0];
+}
+void MPU6050_setXFineGain(int8_t gain) {
+    I2Cdev_writeByte(devAddr, MPU6050_RA_X_FINE_GAIN, gain);
+}
+
+// Y_FINE_GAIN register
+
+int8_t MPU6050_getYFineGain() {
+    I2Cdev_readByte(devAddr, MPU6050_RA_Y_FINE_GAIN, buffer, 0);
+    return buffer[0];
+}
+void MPU6050_setYFineGain(int8_t gain) {
+    I2Cdev_writeByte(devAddr, MPU6050_RA_Y_FINE_GAIN, gain);
+}
+
+// Z_FINE_GAIN register
+
+int8_t MPU6050_getZFineGain() {
+    I2Cdev_readByte(devAddr, MPU6050_RA_Z_FINE_GAIN, buffer, 0);
+    return buffer[0];
+}
+void MPU6050_setZFineGain(int8_t gain) {
+    I2Cdev_writeByte(devAddr, MPU6050_RA_Z_FINE_GAIN, gain);
+}
+
+// XA_OFFS_* registers
+
+int16_t MPU6050_getXAccelOffset() {
+    I2Cdev_readBytes(devAddr, MPU6050_RA_XA_OFFS_H, 2, buffer, 0);
+    return (((int16_t)buffer[0]) << 8) | buffer[1];
+}
+void MPU6050_setXAccelOffset(int16_t offset) {
+    I2Cdev_writeWord(devAddr, MPU6050_RA_XA_OFFS_H, offset);
+}
+
+// YA_OFFS_* register
+
+int16_t MPU6050_getYAccelOffset() {
+    I2Cdev_readBytes(devAddr, MPU6050_RA_YA_OFFS_H, 2, buffer, 0);
+    return (((int16_t)buffer[0]) << 8) | buffer[1];
+}
+void MPU6050_setYAccelOffset(int16_t offset) {
+    I2Cdev_writeWord(devAddr, MPU6050_RA_YA_OFFS_H, offset);
+}
+
+// ZA_OFFS_* register
+
+int16_t MPU6050_getZAccelOffset() {
+    I2Cdev_readBytes(devAddr, MPU6050_RA_ZA_OFFS_H, 2, buffer, 0);
+    return (((int16_t)buffer[0]) << 8) | buffer[1];
+}
+void MPU6050_setZAccelOffset(int16_t offset) {
+    I2Cdev_writeWord(devAddr, MPU6050_RA_ZA_OFFS_H, offset);
+}
+
+// XG_OFFS_USR* registers
+
+int16_t MPU6050_getXGyroOffset() {
+    I2Cdev_readBytes(devAddr, MPU6050_RA_XG_OFFS_USRH, 2, buffer, 0);
+    return (((int16_t)buffer[0]) << 8) | buffer[1];
+}
+void MPU6050_setXGyroOffset(int16_t offset) {
+    I2Cdev_writeWord(devAddr, MPU6050_RA_XG_OFFS_USRH, offset);
+}
+
+// YG_OFFS_USR* register
+
+int16_t MPU6050_getYGyroOffset() {
+    I2Cdev_readBytes(devAddr, MPU6050_RA_YG_OFFS_USRH, 2, buffer, 0);
+    return (((int16_t)buffer[0]) << 8) | buffer[1];
+}
+void MPU6050_setYGyroOffset(int16_t offset) {
+    I2Cdev_writeWord(devAddr, MPU6050_RA_YG_OFFS_USRH, offset);
+}
+
+// ZG_OFFS_USR* register
+
+int16_t MPU6050_getZGyroOffset() {
+    I2Cdev_readBytes(devAddr, MPU6050_RA_ZG_OFFS_USRH, 2, buffer, 0);
+    return (((int16_t)buffer[0]) << 8) | buffer[1];
+}
+void MPU6050_setZGyroOffset(int16_t offset) {
+    I2Cdev_writeWord(devAddr, MPU6050_RA_ZG_OFFS_USRH, offset);
+}
+
+// INT_ENABLE register (DMP functions)
+
+bool MPU6050_getIntPLLReadyEnabled() {
+    I2Cdev_readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, buffer, 0);
+    return buffer[0];
+}
+void MPU6050_setIntPLLReadyEnabled(bool enabled) {
+    I2Cdev_writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, enabled);
+}
+bool MPU6050_getIntDMPEnabled() {
+    I2Cdev_readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DMP_INT_BIT, buffer, 0);
+    return buffer[0];
+}
+void MPU6050_setIntDMPEnabled(bool enabled) {
+    I2Cdev_writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DMP_INT_BIT, enabled);
+}
+
+// DMP_INT_STATUS
+
+bool MPU6050_getDMPInt5Status() {
+    I2Cdev_readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_5_BIT, buffer, 0);
+    return buffer[0];
+}
+bool MPU6050_getDMPInt4Status() {
+    I2Cdev_readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_4_BIT, buffer, 0);
+    return buffer[0];
+}
+bool MPU6050_getDMPInt3Status() {
+    I2Cdev_readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_3_BIT, buffer, 0);
+    return buffer[0];
+}
+bool MPU6050_getDMPInt2Status() {
+    I2Cdev_readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_2_BIT, buffer, 0);
+    return buffer[0];
+}
+bool MPU6050_getDMPInt1Status() {
+    I2Cdev_readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_1_BIT, buffer, 0);
+    return buffer[0];
+}
+bool MPU6050_getDMPInt0Status() {
+    I2Cdev_readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_0_BIT, buffer, 0);
+    return buffer[0];
+}
+
+// INT_STATUS register (DMP functions)
+
+bool MPU6050_getIntPLLReadyStatus() {
+    I2Cdev_readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, buffer, 0);
+    return buffer[0];
+}
+bool MPU6050_getIntDMPStatus() {
+    I2Cdev_readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_DMP_INT_BIT, buffer, 0);
+    return buffer[0];
+}
+
+// USER_CTRL register (DMP functions)
+
+bool MPU6050_getDMPEnabled() {
+    I2Cdev_readBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_EN_BIT, buffer, 0);
+    return buffer[0];
+}
+void MPU6050_setDMPEnabled(bool enabled) {
+    I2Cdev_writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_EN_BIT, enabled);
+}
+void MPU6050_resetDMP() {
+    I2Cdev_writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_RESET_BIT, true);
+}
+
+// BANK_SEL register
+
+void MPU6050_setMemoryBank(uint8_t bank, bool prefetchEnabled, bool userBank) {
+    bank &= 0x1F;
+    if (userBank) bank |= 0x20;
+    if (prefetchEnabled) bank |= 0x40;
+    I2Cdev_writeByte(devAddr, MPU6050_RA_BANK_SEL, bank);
+}
+
+// MEM_START_ADDR register
+
+void MPU6050_setMemoryStartAddress(uint8_t address) {
+    I2Cdev_writeByte(devAddr, MPU6050_RA_MEM_START_ADDR, address);
+}
+
+// MEM_R_W register
+
+uint8_t MPU6050_readMemoryByte() {
+    I2Cdev_readByte(devAddr, MPU6050_RA_MEM_R_W, buffer, 0);
+    return buffer[0];
+}
+void MPU6050_writeMemoryByte(uint8_t data) {
+    I2Cdev_writeByte(devAddr, MPU6050_RA_MEM_R_W, data);
+}
+void MPU6050_readMemoryBlock(uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address) {
+    MPU6050_setMemoryBank(bank, false, false);
+    MPU6050_setMemoryStartAddress(address);
+    uint8_t chunkSize;
+    uint16_t i;
+    for (i = 0; i < dataSize;) {
+        // determine correct chunk size according to bank position and data size
+        chunkSize = MPU6050_DMP_MEMORY_CHUNK_SIZE;
+
+        // make sure we don't go past the data size
+        if (i + chunkSize > dataSize) chunkSize = dataSize - i;
+
+        // make sure this chunk doesn't go past the bank boundary (256 bytes)
+        if (chunkSize > 256 - address) chunkSize = 256 - address;
+
+        // read the chunk of data as specified
+        I2Cdev_readBytes(devAddr, MPU6050_RA_MEM_R_W, chunkSize, data + i, 0);
+
+        // increase byte index by [chunkSize]
+        i += chunkSize;
+
+        // uint8_t automatically wraps to 0 at 256
+        address += chunkSize;
+
+        // if we aren't done, update bank (if necessary) and address
+        if (i < dataSize) {
+            if (address == 0) bank++;
+            MPU6050_setMemoryBank(bank, false, false);
+            MPU6050_setMemoryStartAddress(address);
+        }
+    }
+}
+bool MPU6050_writeMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address, bool verify, bool useProgMem) {
+    MPU6050_setMemoryBank(bank, false, false);
+    MPU6050_setMemoryStartAddress(address);
+    uint8_t chunkSize;
+    uint8_t *verifyBuffer;
+    uint8_t *progBuffer;
+    uint16_t i;
+    uint8_t j;
+    if (verify) verifyBuffer = (uint8_t *)malloc(MPU6050_DMP_MEMORY_CHUNK_SIZE);
+    if (useProgMem) progBuffer = (uint8_t *)malloc(MPU6050_DMP_MEMORY_CHUNK_SIZE);
+    for (i = 0; i < dataSize;) {
+        // determine correct chunk size according to bank position and data size
+        chunkSize = MPU6050_DMP_MEMORY_CHUNK_SIZE;
+
+        // make sure we don't go past the data size
+        if (i + chunkSize > dataSize) chunkSize = dataSize - i;
+
+        // make sure this chunk doesn't go past the bank boundary (256 bytes)
+        if (chunkSize > 256 - address) chunkSize = 256 - address;
+
+        if (useProgMem) {
+            // write the chunk of data as specified
+            for (j = 0; j < chunkSize; j++) progBuffer[j] = pgm_read_byte(data + i + j);
+        } else {
+            // write the chunk of data as specified
+            progBuffer = (uint8_t *)data + i;
+        }
+
+        I2Cdev_writeBytes(devAddr, MPU6050_RA_MEM_R_W, chunkSize, progBuffer);
+
+        // verify data if needed
+        if (verify && verifyBuffer) {
+            MPU6050_setMemoryBank(bank, false, false);
+            MPU6050_setMemoryStartAddress(address);
+            I2Cdev_readBytes(devAddr, MPU6050_RA_MEM_R_W, chunkSize, verifyBuffer, 0);
+            if (memcmp(progBuffer, verifyBuffer, chunkSize) != 0) {
+                /*Serial.print("Block write verification error, bank ");
+                Serial.print(bank, DEC);
+                Serial.print(", address ");
+                Serial.print(address, DEC);
+                Serial.print("!\nExpected:");
+                for (j = 0; j < chunkSize; j++) {
+                    Serial.print(" 0x");
+                    if (progBuffer[j] < 16) Serial.print("0");
+                    Serial.print(progBuffer[j], HEX);
+                }
+                Serial.print("\nReceived:");
+                for (uint8_t j = 0; j < chunkSize; j++) {
+                    Serial.print(" 0x");
+                    if (verifyBuffer[i + j] < 16) Serial.print("0");
+                    Serial.print(verifyBuffer[i + j], HEX);
+                }
+                Serial.print("\n");*/
+                free(verifyBuffer);
+                if (useProgMem) free(progBuffer);
+                return false; // uh oh.
+            }
+        }
+
+        // increase byte index by [chunkSize]
+        i += chunkSize;
+
+        // uint8_t automatically wraps to 0 at 256
+        address += chunkSize;
+
+        // if we aren't done, update bank (if necessary) and address
+        if (i < dataSize) {
+            if (address == 0) bank++;
+            MPU6050_setMemoryBank(bank, false, false);
+            MPU6050_setMemoryStartAddress(address);
+        }
+    }
+    if (verify) free(verifyBuffer);
+    if (useProgMem) free(progBuffer);
+    return true;
+}
+bool MPU6050_writeProgMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address, bool verify) {
+    return MPU6050_writeMemoryBlock(data, dataSize, bank, address, verify, true);
+}
+bool MPU6050_writeDMPConfigurationSet(const uint8_t *data, uint16_t dataSize, bool useProgMem) {
+    uint8_t *progBuffer, success, special;
+    uint16_t i, j;
+    if (useProgMem) {
+        progBuffer = (uint8_t *)malloc(8); // assume 8-byte blocks, realloc later if necessary
+    }
+
+    // config set data is a long string of blocks with the following structure:
+    // [bank] [offset] [length] [byte[0], byte[1], ..., byte[length]]
+    uint8_t bank, offset, length;
+    for (i = 0; i < dataSize;) {
+        if (useProgMem) {
+            bank = pgm_read_byte(data + i++);
+            offset = pgm_read_byte(data + i++);
+            length = pgm_read_byte(data + i++);
+        } else {
+            bank = data[i++];
+            offset = data[i++];
+            length = data[i++];
+        }
+
+        // write data or perform special action
+        if (length > 0) {
+            // regular block of data to write
+            /*Serial.print("Writing config block to bank ");
+            Serial.print(bank);
+            Serial.print(", offset ");
+            Serial.print(offset);
+            Serial.print(", length=");
+            Serial.println(length);*/
+            if (useProgMem) {
+                if (sizeof(progBuffer) < length) progBuffer = (uint8_t *)realloc(progBuffer, length);
+                for (j = 0; j < length; j++) progBuffer[j] = pgm_read_byte(data + i + j);
+            } else {
+                progBuffer = (uint8_t *)data + i;
+            }
+            success = MPU6050_writeMemoryBlock(progBuffer, length, bank, offset, true, false);
+            i += length;
+        } else {
+            // special instruction
+            // NOTE: this kind of behavior (what and when to do certain things)
+            // is totally undocumented. This code is in here based on observed
+            // behavior only, and exactly why (or even whether) it has to be here
+            // is anybody's guess for now.
+            if (useProgMem) {
+                special = pgm_read_byte(data + i++);
+            } else {
+                special = data[i++];
+            }
+            /*Serial.print("Special command code ");
+            Serial.print(special, HEX);
+            Serial.println(" found...");*/
+            if (special == 0x01) {
+                // enable DMP-related interrupts
+
+                //setIntZeroMotionEnabled(true);
+                //setIntFIFOBufferOverflowEnabled(true);
+                //setIntDMPEnabled(true);
+                I2Cdev_writeByte(devAddr, MPU6050_RA_INT_ENABLE, 0x32);  // single operation
+
+                success = true;
+            } else {
+                // unknown special command
+                success = false;
+            }
+        }
+
+        if (!success) {
+            if (useProgMem) free(progBuffer);
+            return false; // uh oh
+        }
+    }
+    if (useProgMem) free(progBuffer);
+    return true;
+}
+bool MPU6050_writeProgDMPConfigurationSet(const uint8_t *data, uint16_t dataSize) {
+    return MPU6050_writeDMPConfigurationSet(data, dataSize, true);
+}
+
+// DMP_CFG_1 register
+
+uint8_t MPU6050_getDMPConfig1() {
+    I2Cdev_readByte(devAddr, MPU6050_RA_DMP_CFG_1, buffer, 0);
+    return buffer[0];
+}
+void MPU6050_setDMPConfig1(uint8_t config) {
+    I2Cdev_writeByte(devAddr, MPU6050_RA_DMP_CFG_1, config);
+}
+
+// DMP_CFG_2 register
+
+uint8_t MPU6050_getDMPConfig2() {
+    I2Cdev_readByte(devAddr, MPU6050_RA_DMP_CFG_2, buffer, 0);
+    return buffer[0];
+}
+void MPU6050_setDMPConfig2(uint8_t config) {
+    I2Cdev_writeByte(devAddr, MPU6050_RA_DMP_CFG_2, config);
+}
diff --git a/STM32/MPU6050/MPU6050.h b/STM32/MPU6050/MPU6050.h
new file mode 100644
index 00000000..6bb456c6
--- /dev/null
+++ b/STM32/MPU6050/MPU6050.h
@@ -0,0 +1,989 @@
+// I2Cdev library collection - MPU6050 I2C device class
+// Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00)
+// 8/24/2011 by Jeff Rowberg 
+// 6/6/2015 by Andrey Voloshin 
+// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
+//
+// Changelog:
+//     2015-06-06 - ported to STM32 HAL library from Arduino code
+
+// NOTE: THIS IS ONLY A PARIAL RELEASE. THIS DEVICE CLASS IS CURRENTLY UNDERGOING ACTIVE
+// DEVELOPMENT AND IS STILL MISSING SOME IMPORTANT FEATURES. PLEASE KEEP THIS IN MIND IF
+// YOU DECIDE TO USE THIS PARTICULAR CODE FOR ANYTHING.
+
+/* ============================================
+I2Cdev device library code is placed under the MIT license
+Copyright (c) 2012 Jeff Rowberg
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+===============================================
+*/
+
+#ifndef _MPU6050_H_
+#define _MPU6050_H_
+
+#include "I2Cdev.h"
+
+// supporting link:  http://forum.arduino.cc/index.php?&topic=143444.msg1079517#msg1079517
+// also: http://forum.arduino.cc/index.php?&topic=141571.msg1062899#msg1062899s
+#ifndef __arm__
+#include 
+#else
+#define PROGMEM /* empty */
+#define pgm_read_byte(x) (*(x))
+#define pgm_read_word(x) (*(x))
+#define pgm_read_float(x) (*(x))
+#define PSTR(STR) STR
+#endif
+
+
+#define MPU6050_ADDRESS_AD0_LOW     0x68 // address pin low (GND), default for InvenSense evaluation board
+#define MPU6050_ADDRESS_AD0_HIGH    0x69 // address pin high (VCC)
+#define MPU6050_DEFAULT_ADDRESS     MPU6050_ADDRESS_AD0_LOW
+
+#define MPU6050_RA_XG_OFFS_TC       0x00 //[7] PWR_MODE, [6:1] XG_OFFS_TC, [0] OTP_BNK_VLD
+#define MPU6050_RA_YG_OFFS_TC       0x01 //[7] PWR_MODE, [6:1] YG_OFFS_TC, [0] OTP_BNK_VLD
+#define MPU6050_RA_ZG_OFFS_TC       0x02 //[7] PWR_MODE, [6:1] ZG_OFFS_TC, [0] OTP_BNK_VLD
+#define MPU6050_RA_X_FINE_GAIN      0x03 //[7:0] X_FINE_GAIN
+#define MPU6050_RA_Y_FINE_GAIN      0x04 //[7:0] Y_FINE_GAIN
+#define MPU6050_RA_Z_FINE_GAIN      0x05 //[7:0] Z_FINE_GAIN
+#define MPU6050_RA_XA_OFFS_H        0x06 //[15:0] XA_OFFS
+#define MPU6050_RA_XA_OFFS_L_TC     0x07
+#define MPU6050_RA_YA_OFFS_H        0x08 //[15:0] YA_OFFS
+#define MPU6050_RA_YA_OFFS_L_TC     0x09
+#define MPU6050_RA_ZA_OFFS_H        0x0A //[15:0] ZA_OFFS
+#define MPU6050_RA_ZA_OFFS_L_TC     0x0B
+#define MPU6050_RA_XG_OFFS_USRH     0x13 //[15:0] XG_OFFS_USR
+#define MPU6050_RA_XG_OFFS_USRL     0x14
+#define MPU6050_RA_YG_OFFS_USRH     0x15 //[15:0] YG_OFFS_USR
+#define MPU6050_RA_YG_OFFS_USRL     0x16
+#define MPU6050_RA_ZG_OFFS_USRH     0x17 //[15:0] ZG_OFFS_USR
+#define MPU6050_RA_ZG_OFFS_USRL     0x18
+#define MPU6050_RA_SMPLRT_DIV       0x19
+#define MPU6050_RA_CONFIG           0x1A
+#define MPU6050_RA_GYRO_CONFIG      0x1B
+#define MPU6050_RA_ACCEL_CONFIG     0x1C
+#define MPU6050_RA_FF_THR           0x1D
+#define MPU6050_RA_FF_DUR           0x1E
+#define MPU6050_RA_MOT_THR          0x1F
+#define MPU6050_RA_MOT_DUR          0x20
+#define MPU6050_RA_ZRMOT_THR        0x21
+#define MPU6050_RA_ZRMOT_DUR        0x22
+#define MPU6050_RA_FIFO_EN          0x23
+#define MPU6050_RA_I2C_MST_CTRL     0x24
+#define MPU6050_RA_I2C_SLV0_ADDR    0x25
+#define MPU6050_RA_I2C_SLV0_REG     0x26
+#define MPU6050_RA_I2C_SLV0_CTRL    0x27
+#define MPU6050_RA_I2C_SLV1_ADDR    0x28
+#define MPU6050_RA_I2C_SLV1_REG     0x29
+#define MPU6050_RA_I2C_SLV1_CTRL    0x2A
+#define MPU6050_RA_I2C_SLV2_ADDR    0x2B
+#define MPU6050_RA_I2C_SLV2_REG     0x2C
+#define MPU6050_RA_I2C_SLV2_CTRL    0x2D
+#define MPU6050_RA_I2C_SLV3_ADDR    0x2E
+#define MPU6050_RA_I2C_SLV3_REG     0x2F
+#define MPU6050_RA_I2C_SLV3_CTRL    0x30
+#define MPU6050_RA_I2C_SLV4_ADDR    0x31
+#define MPU6050_RA_I2C_SLV4_REG     0x32
+#define MPU6050_RA_I2C_SLV4_DO      0x33
+#define MPU6050_RA_I2C_SLV4_CTRL    0x34
+#define MPU6050_RA_I2C_SLV4_DI      0x35
+#define MPU6050_RA_I2C_MST_STATUS   0x36
+#define MPU6050_RA_INT_PIN_CFG      0x37
+#define MPU6050_RA_INT_ENABLE       0x38
+#define MPU6050_RA_DMP_INT_STATUS   0x39
+#define MPU6050_RA_INT_STATUS       0x3A
+#define MPU6050_RA_ACCEL_XOUT_H     0x3B
+#define MPU6050_RA_ACCEL_XOUT_L     0x3C
+#define MPU6050_RA_ACCEL_YOUT_H     0x3D
+#define MPU6050_RA_ACCEL_YOUT_L     0x3E
+#define MPU6050_RA_ACCEL_ZOUT_H     0x3F
+#define MPU6050_RA_ACCEL_ZOUT_L     0x40
+#define MPU6050_RA_TEMP_OUT_H       0x41
+#define MPU6050_RA_TEMP_OUT_L       0x42
+#define MPU6050_RA_GYRO_XOUT_H      0x43
+#define MPU6050_RA_GYRO_XOUT_L      0x44
+#define MPU6050_RA_GYRO_YOUT_H      0x45
+#define MPU6050_RA_GYRO_YOUT_L      0x46
+#define MPU6050_RA_GYRO_ZOUT_H      0x47
+#define MPU6050_RA_GYRO_ZOUT_L      0x48
+#define MPU6050_RA_EXT_SENS_DATA_00 0x49
+#define MPU6050_RA_EXT_SENS_DATA_01 0x4A
+#define MPU6050_RA_EXT_SENS_DATA_02 0x4B
+#define MPU6050_RA_EXT_SENS_DATA_03 0x4C
+#define MPU6050_RA_EXT_SENS_DATA_04 0x4D
+#define MPU6050_RA_EXT_SENS_DATA_05 0x4E
+#define MPU6050_RA_EXT_SENS_DATA_06 0x4F
+#define MPU6050_RA_EXT_SENS_DATA_07 0x50
+#define MPU6050_RA_EXT_SENS_DATA_08 0x51
+#define MPU6050_RA_EXT_SENS_DATA_09 0x52
+#define MPU6050_RA_EXT_SENS_DATA_10 0x53
+#define MPU6050_RA_EXT_SENS_DATA_11 0x54
+#define MPU6050_RA_EXT_SENS_DATA_12 0x55
+#define MPU6050_RA_EXT_SENS_DATA_13 0x56
+#define MPU6050_RA_EXT_SENS_DATA_14 0x57
+#define MPU6050_RA_EXT_SENS_DATA_15 0x58
+#define MPU6050_RA_EXT_SENS_DATA_16 0x59
+#define MPU6050_RA_EXT_SENS_DATA_17 0x5A
+#define MPU6050_RA_EXT_SENS_DATA_18 0x5B
+#define MPU6050_RA_EXT_SENS_DATA_19 0x5C
+#define MPU6050_RA_EXT_SENS_DATA_20 0x5D
+#define MPU6050_RA_EXT_SENS_DATA_21 0x5E
+#define MPU6050_RA_EXT_SENS_DATA_22 0x5F
+#define MPU6050_RA_EXT_SENS_DATA_23 0x60
+#define MPU6050_RA_MOT_DETECT_STATUS    0x61
+#define MPU6050_RA_I2C_SLV0_DO      0x63
+#define MPU6050_RA_I2C_SLV1_DO      0x64
+#define MPU6050_RA_I2C_SLV2_DO      0x65
+#define MPU6050_RA_I2C_SLV3_DO      0x66
+#define MPU6050_RA_I2C_MST_DELAY_CTRL   0x67
+#define MPU6050_RA_SIGNAL_PATH_RESET    0x68
+#define MPU6050_RA_MOT_DETECT_CTRL      0x69
+#define MPU6050_RA_USER_CTRL        0x6A
+#define MPU6050_RA_PWR_MGMT_1       0x6B
+#define MPU6050_RA_PWR_MGMT_2       0x6C
+#define MPU6050_RA_BANK_SEL         0x6D
+#define MPU6050_RA_MEM_START_ADDR   0x6E
+#define MPU6050_RA_MEM_R_W          0x6F
+#define MPU6050_RA_DMP_CFG_1        0x70
+#define MPU6050_RA_DMP_CFG_2        0x71
+#define MPU6050_RA_FIFO_COUNTH      0x72
+#define MPU6050_RA_FIFO_COUNTL      0x73
+#define MPU6050_RA_FIFO_R_W         0x74
+#define MPU6050_RA_WHO_AM_I         0x75
+
+#define MPU6050_TC_PWR_MODE_BIT     7
+#define MPU6050_TC_OFFSET_BIT       6
+#define MPU6050_TC_OFFSET_LENGTH    6
+#define MPU6050_TC_OTP_BNK_VLD_BIT  0
+
+#define MPU6050_VDDIO_LEVEL_VLOGIC  0
+#define MPU6050_VDDIO_LEVEL_VDD     1
+
+#define MPU6050_CFG_EXT_SYNC_SET_BIT    5
+#define MPU6050_CFG_EXT_SYNC_SET_LENGTH 3
+#define MPU6050_CFG_DLPF_CFG_BIT    2
+#define MPU6050_CFG_DLPF_CFG_LENGTH 3
+
+#define MPU6050_EXT_SYNC_DISABLED       0x0
+#define MPU6050_EXT_SYNC_TEMP_OUT_L     0x1
+#define MPU6050_EXT_SYNC_GYRO_XOUT_L    0x2
+#define MPU6050_EXT_SYNC_GYRO_YOUT_L    0x3
+#define MPU6050_EXT_SYNC_GYRO_ZOUT_L    0x4
+#define MPU6050_EXT_SYNC_ACCEL_XOUT_L   0x5
+#define MPU6050_EXT_SYNC_ACCEL_YOUT_L   0x6
+#define MPU6050_EXT_SYNC_ACCEL_ZOUT_L   0x7
+
+#define MPU6050_DLPF_BW_256         0x00
+#define MPU6050_DLPF_BW_188         0x01
+#define MPU6050_DLPF_BW_98          0x02
+#define MPU6050_DLPF_BW_42          0x03
+#define MPU6050_DLPF_BW_20          0x04
+#define MPU6050_DLPF_BW_10          0x05
+#define MPU6050_DLPF_BW_5           0x06
+
+#define MPU6050_GCONFIG_FS_SEL_BIT      4
+#define MPU6050_GCONFIG_FS_SEL_LENGTH   2
+
+#define MPU6050_GYRO_FS_250         0x00
+#define MPU6050_GYRO_FS_500         0x01
+#define MPU6050_GYRO_FS_1000        0x02
+#define MPU6050_GYRO_FS_2000        0x03
+
+#define MPU6050_ACONFIG_XA_ST_BIT           7
+#define MPU6050_ACONFIG_YA_ST_BIT           6
+#define MPU6050_ACONFIG_ZA_ST_BIT           5
+#define MPU6050_ACONFIG_AFS_SEL_BIT         4
+#define MPU6050_ACONFIG_AFS_SEL_LENGTH      2
+#define MPU6050_ACONFIG_ACCEL_HPF_BIT       2
+#define MPU6050_ACONFIG_ACCEL_HPF_LENGTH    3
+
+#define MPU6050_ACCEL_FS_2          0x00
+#define MPU6050_ACCEL_FS_4          0x01
+#define MPU6050_ACCEL_FS_8          0x02
+#define MPU6050_ACCEL_FS_16         0x03
+
+#define MPU6050_DHPF_RESET          0x00
+#define MPU6050_DHPF_5              0x01
+#define MPU6050_DHPF_2P5            0x02
+#define MPU6050_DHPF_1P25           0x03
+#define MPU6050_DHPF_0P63           0x04
+#define MPU6050_DHPF_HOLD           0x07
+
+#define MPU6050_TEMP_FIFO_EN_BIT    7
+#define MPU6050_XG_FIFO_EN_BIT      6
+#define MPU6050_YG_FIFO_EN_BIT      5
+#define MPU6050_ZG_FIFO_EN_BIT      4
+#define MPU6050_ACCEL_FIFO_EN_BIT   3
+#define MPU6050_SLV2_FIFO_EN_BIT    2
+#define MPU6050_SLV1_FIFO_EN_BIT    1
+#define MPU6050_SLV0_FIFO_EN_BIT    0
+
+#define MPU6050_MULT_MST_EN_BIT     7
+#define MPU6050_WAIT_FOR_ES_BIT     6
+#define MPU6050_SLV_3_FIFO_EN_BIT   5
+#define MPU6050_I2C_MST_P_NSR_BIT   4
+#define MPU6050_I2C_MST_CLK_BIT     3
+#define MPU6050_I2C_MST_CLK_LENGTH  4
+
+#define MPU6050_CLOCK_DIV_348       0x0
+#define MPU6050_CLOCK_DIV_333       0x1
+#define MPU6050_CLOCK_DIV_320       0x2
+#define MPU6050_CLOCK_DIV_308       0x3
+#define MPU6050_CLOCK_DIV_296       0x4
+#define MPU6050_CLOCK_DIV_286       0x5
+#define MPU6050_CLOCK_DIV_276       0x6
+#define MPU6050_CLOCK_DIV_267       0x7
+#define MPU6050_CLOCK_DIV_258       0x8
+#define MPU6050_CLOCK_DIV_500       0x9
+#define MPU6050_CLOCK_DIV_471       0xA
+#define MPU6050_CLOCK_DIV_444       0xB
+#define MPU6050_CLOCK_DIV_421       0xC
+#define MPU6050_CLOCK_DIV_400       0xD
+#define MPU6050_CLOCK_DIV_381       0xE
+#define MPU6050_CLOCK_DIV_364       0xF
+
+#define MPU6050_I2C_SLV_RW_BIT      7
+#define MPU6050_I2C_SLV_ADDR_BIT    6
+#define MPU6050_I2C_SLV_ADDR_LENGTH 7
+#define MPU6050_I2C_SLV_EN_BIT      7
+#define MPU6050_I2C_SLV_BYTE_SW_BIT 6
+#define MPU6050_I2C_SLV_REG_DIS_BIT 5
+#define MPU6050_I2C_SLV_GRP_BIT     4
+#define MPU6050_I2C_SLV_LEN_BIT     3
+#define MPU6050_I2C_SLV_LEN_LENGTH  4
+
+#define MPU6050_I2C_SLV4_RW_BIT         7
+#define MPU6050_I2C_SLV4_ADDR_BIT       6
+#define MPU6050_I2C_SLV4_ADDR_LENGTH    7
+#define MPU6050_I2C_SLV4_EN_BIT         7
+#define MPU6050_I2C_SLV4_INT_EN_BIT     6
+#define MPU6050_I2C_SLV4_REG_DIS_BIT    5
+#define MPU6050_I2C_SLV4_MST_DLY_BIT    4
+#define MPU6050_I2C_SLV4_MST_DLY_LENGTH 5
+
+#define MPU6050_MST_PASS_THROUGH_BIT    7
+#define MPU6050_MST_I2C_SLV4_DONE_BIT   6
+#define MPU6050_MST_I2C_LOST_ARB_BIT    5
+#define MPU6050_MST_I2C_SLV4_NACK_BIT   4
+#define MPU6050_MST_I2C_SLV3_NACK_BIT   3
+#define MPU6050_MST_I2C_SLV2_NACK_BIT   2
+#define MPU6050_MST_I2C_SLV1_NACK_BIT   1
+#define MPU6050_MST_I2C_SLV0_NACK_BIT   0
+
+#define MPU6050_INTCFG_INT_LEVEL_BIT        7
+#define MPU6050_INTCFG_INT_OPEN_BIT         6
+#define MPU6050_INTCFG_LATCH_INT_EN_BIT     5
+#define MPU6050_INTCFG_INT_RD_CLEAR_BIT     4
+#define MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT  3
+#define MPU6050_INTCFG_FSYNC_INT_EN_BIT     2
+#define MPU6050_INTCFG_I2C_BYPASS_EN_BIT    1
+#define MPU6050_INTCFG_CLKOUT_EN_BIT        0
+
+#define MPU6050_INTMODE_ACTIVEHIGH  0x00
+#define MPU6050_INTMODE_ACTIVELOW   0x01
+
+#define MPU6050_INTDRV_PUSHPULL     0x00
+#define MPU6050_INTDRV_OPENDRAIN    0x01
+
+#define MPU6050_INTLATCH_50USPULSE  0x00
+#define MPU6050_INTLATCH_WAITCLEAR  0x01
+
+#define MPU6050_INTCLEAR_STATUSREAD 0x00
+#define MPU6050_INTCLEAR_ANYREAD    0x01
+
+#define MPU6050_INTERRUPT_FF_BIT            7
+#define MPU6050_INTERRUPT_MOT_BIT           6
+#define MPU6050_INTERRUPT_ZMOT_BIT          5
+#define MPU6050_INTERRUPT_FIFO_OFLOW_BIT    4
+#define MPU6050_INTERRUPT_I2C_MST_INT_BIT   3
+#define MPU6050_INTERRUPT_PLL_RDY_INT_BIT   2
+#define MPU6050_INTERRUPT_DMP_INT_BIT       1
+#define MPU6050_INTERRUPT_DATA_RDY_BIT      0
+
+// TODO: figure out what these actually do
+// UMPL source code is not very obivous
+#define MPU6050_DMPINT_5_BIT            5
+#define MPU6050_DMPINT_4_BIT            4
+#define MPU6050_DMPINT_3_BIT            3
+#define MPU6050_DMPINT_2_BIT            2
+#define MPU6050_DMPINT_1_BIT            1
+#define MPU6050_DMPINT_0_BIT            0
+
+#define MPU6050_MOTION_MOT_XNEG_BIT     7
+#define MPU6050_MOTION_MOT_XPOS_BIT     6
+#define MPU6050_MOTION_MOT_YNEG_BIT     5
+#define MPU6050_MOTION_MOT_YPOS_BIT     4
+#define MPU6050_MOTION_MOT_ZNEG_BIT     3
+#define MPU6050_MOTION_MOT_ZPOS_BIT     2
+#define MPU6050_MOTION_MOT_ZRMOT_BIT    0
+
+#define MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT   7
+#define MPU6050_DELAYCTRL_I2C_SLV4_DLY_EN_BIT   4
+#define MPU6050_DELAYCTRL_I2C_SLV3_DLY_EN_BIT   3
+#define MPU6050_DELAYCTRL_I2C_SLV2_DLY_EN_BIT   2
+#define MPU6050_DELAYCTRL_I2C_SLV1_DLY_EN_BIT   1
+#define MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT   0
+
+#define MPU6050_PATHRESET_GYRO_RESET_BIT    2
+#define MPU6050_PATHRESET_ACCEL_RESET_BIT   1
+#define MPU6050_PATHRESET_TEMP_RESET_BIT    0
+
+#define MPU6050_DETECT_ACCEL_ON_DELAY_BIT       5
+#define MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH    2
+#define MPU6050_DETECT_FF_COUNT_BIT             3
+#define MPU6050_DETECT_FF_COUNT_LENGTH          2
+#define MPU6050_DETECT_MOT_COUNT_BIT            1
+#define MPU6050_DETECT_MOT_COUNT_LENGTH         2
+
+#define MPU6050_DETECT_DECREMENT_RESET  0x0
+#define MPU6050_DETECT_DECREMENT_1      0x1
+#define MPU6050_DETECT_DECREMENT_2      0x2
+#define MPU6050_DETECT_DECREMENT_4      0x3
+
+#define MPU6050_USERCTRL_DMP_EN_BIT             7
+#define MPU6050_USERCTRL_FIFO_EN_BIT            6
+#define MPU6050_USERCTRL_I2C_MST_EN_BIT         5
+#define MPU6050_USERCTRL_I2C_IF_DIS_BIT         4
+#define MPU6050_USERCTRL_DMP_RESET_BIT          3
+#define MPU6050_USERCTRL_FIFO_RESET_BIT         2
+#define MPU6050_USERCTRL_I2C_MST_RESET_BIT      1
+#define MPU6050_USERCTRL_SIG_COND_RESET_BIT     0
+
+#define MPU6050_PWR1_DEVICE_RESET_BIT   7
+#define MPU6050_PWR1_SLEEP_BIT          6
+#define MPU6050_PWR1_CYCLE_BIT          5
+#define MPU6050_PWR1_TEMP_DIS_BIT       3
+#define MPU6050_PWR1_CLKSEL_BIT         2
+#define MPU6050_PWR1_CLKSEL_LENGTH      3
+
+#define MPU6050_CLOCK_INTERNAL          0x00
+#define MPU6050_CLOCK_PLL_XGYRO         0x01
+#define MPU6050_CLOCK_PLL_YGYRO         0x02
+#define MPU6050_CLOCK_PLL_ZGYRO         0x03
+#define MPU6050_CLOCK_PLL_EXT32K        0x04
+#define MPU6050_CLOCK_PLL_EXT19M        0x05
+#define MPU6050_CLOCK_KEEP_RESET        0x07
+
+#define MPU6050_PWR2_LP_WAKE_CTRL_BIT       7
+#define MPU6050_PWR2_LP_WAKE_CTRL_LENGTH    2
+#define MPU6050_PWR2_STBY_XA_BIT            5
+#define MPU6050_PWR2_STBY_YA_BIT            4
+#define MPU6050_PWR2_STBY_ZA_BIT            3
+#define MPU6050_PWR2_STBY_XG_BIT            2
+#define MPU6050_PWR2_STBY_YG_BIT            1
+#define MPU6050_PWR2_STBY_ZG_BIT            0
+
+#define MPU6050_WAKE_FREQ_1P25      0x0
+#define MPU6050_WAKE_FREQ_2P5       0x1
+#define MPU6050_WAKE_FREQ_5         0x2
+#define MPU6050_WAKE_FREQ_10        0x3
+
+#define MPU6050_BANKSEL_PRFTCH_EN_BIT       6
+#define MPU6050_BANKSEL_CFG_USER_BANK_BIT   5
+#define MPU6050_BANKSEL_MEM_SEL_BIT         4
+#define MPU6050_BANKSEL_MEM_SEL_LENGTH      5
+
+#define MPU6050_WHO_AM_I_BIT        6
+#define MPU6050_WHO_AM_I_LENGTH     6
+
+#define MPU6050_DMP_MEMORY_BANKS        8
+#define MPU6050_DMP_MEMORY_BANK_SIZE    256
+#define MPU6050_DMP_MEMORY_CHUNK_SIZE   16
+
+// note: DMP code memory blocks defined at end of header file
+void MPU6050_setAddress(uint8_t address);
+void MPU6050_initialize();
+bool MPU6050_testConnection();
+
+// AUX_VDDIO register
+uint8_t MPU6050_getAuxVDDIOLevel();
+void MPU6050_setAuxVDDIOLevel(uint8_t level);
+
+// SMPLRT_DIV register
+uint8_t MPU6050_getRate();
+void MPU6050_setRate(uint8_t rate);
+
+// CONFIG register
+uint8_t MPU6050_getExternalFrameSync();
+void MPU6050_setExternalFrameSync(uint8_t sync);
+uint8_t MPU6050_getDLPFMode();
+void MPU6050_setDLPFMode(uint8_t bandwidth);
+
+// GYRO_CONFIG register
+uint8_t MPU6050_getFullScaleGyroRange();
+void MPU6050_setFullScaleGyroRange(uint8_t range);
+
+// ACCEL_CONFIG register
+bool MPU6050_getAccelXSelfTest();
+void MPU6050_setAccelXSelfTest(bool enabled);
+bool MPU6050_getAccelYSelfTest();
+void MPU6050_setAccelYSelfTest(bool enabled);
+bool MPU6050_getAccelZSelfTest();
+void MPU6050_setAccelZSelfTest(bool enabled);
+uint8_t MPU6050_getFullScaleAccelRange();
+void MPU6050_setFullScaleAccelRange(uint8_t range);
+uint8_t MPU6050_getDHPFMode();
+void MPU6050_setDHPFMode(uint8_t mode);
+
+// FF_THR register
+uint8_t MPU6050_getFreefallDetectionThreshold();
+void MPU6050_setFreefallDetectionThreshold(uint8_t threshold);
+
+// FF_DUR register
+uint8_t MPU6050_getFreefallDetectionDuration();
+void MPU6050_setFreefallDetectionDuration(uint8_t duration);
+
+// MOT_THR register
+uint8_t MPU6050_getMotionDetectionThreshold();
+void MPU6050_setMotionDetectionThreshold(uint8_t threshold);
+
+// MOT_DUR register
+uint8_t MPU6050_getMotionDetectionDuration();
+void MPU6050_setMotionDetectionDuration(uint8_t duration);
+
+// ZRMOT_THR register
+uint8_t MPU6050_getZeroMotionDetectionThreshold();
+void MPU6050_setZeroMotionDetectionThreshold(uint8_t threshold);
+
+// ZRMOT_DUR register
+uint8_t MPU6050_getZeroMotionDetectionDuration();
+void MPU6050_setZeroMotionDetectionDuration(uint8_t duration);
+
+// FIFO_EN register
+bool MPU6050_getTempFIFOEnabled();
+void MPU6050_setTempFIFOEnabled(bool enabled);
+bool MPU6050_getXGyroFIFOEnabled();
+void MPU6050_setXGyroFIFOEnabled(bool enabled);
+bool MPU6050_getYGyroFIFOEnabled();
+void MPU6050_setYGyroFIFOEnabled(bool enabled);
+bool MPU6050_getZGyroFIFOEnabled();
+void MPU6050_setZGyroFIFOEnabled(bool enabled);
+bool MPU6050_getAccelFIFOEnabled();
+void MPU6050_setAccelFIFOEnabled(bool enabled);
+bool MPU6050_getSlave2FIFOEnabled();
+void MPU6050_setSlave2FIFOEnabled(bool enabled);
+bool MPU6050_getSlave1FIFOEnabled();
+void MPU6050_setSlave1FIFOEnabled(bool enabled);
+bool MPU6050_getSlave0FIFOEnabled();
+void MPU6050_setSlave0FIFOEnabled(bool enabled);
+
+// I2C_MST_CTRL register
+bool MPU6050_getMultiMasterEnabled();
+void MPU6050_setMultiMasterEnabled(bool enabled);
+bool MPU6050_getWaitForExternalSensorEnabled();
+void MPU6050_setWaitForExternalSensorEnabled(bool enabled);
+bool MPU6050_getSlave3FIFOEnabled();
+void MPU6050_setSlave3FIFOEnabled(bool enabled);
+bool MPU6050_getSlaveReadWriteTransitionEnabled();
+void MPU6050_setSlaveReadWriteTransitionEnabled(bool enabled);
+uint8_t MPU6050_getMasterClockSpeed();
+void MPU6050_setMasterClockSpeed(uint8_t speed);
+
+// I2C_SLV* registers (Slave 0-3)
+uint8_t MPU6050_getSlaveAddress(uint8_t num);
+void MPU6050_setSlaveAddress(uint8_t num, uint8_t address);
+uint8_t MPU6050_getSlaveRegister(uint8_t num);
+void MPU6050_setSlaveRegister(uint8_t num, uint8_t reg);
+bool MPU6050_getSlaveEnabled(uint8_t num);
+void MPU6050_setSlaveEnabled(uint8_t num, bool enabled);
+bool MPU6050_getSlaveWordByteSwap(uint8_t num);
+void MPU6050_setSlaveWordByteSwap(uint8_t num, bool enabled);
+bool MPU6050_getSlaveWriteMode(uint8_t num);
+void MPU6050_setSlaveWriteMode(uint8_t num, bool mode);
+bool MPU6050_getSlaveWordGroupOffset(uint8_t num);
+void MPU6050_setSlaveWordGroupOffset(uint8_t num, bool enabled);
+uint8_t MPU6050_getSlaveDataLength(uint8_t num);
+void MPU6050_setSlaveDataLength(uint8_t num, uint8_t length);
+
+// I2C_SLV* registers (Slave 4)
+uint8_t MPU6050_getSlave4Address();
+void MPU6050_setSlave4Address(uint8_t address);
+uint8_t MPU6050_getSlave4Register();
+void MPU6050_setSlave4Register(uint8_t reg);
+void MPU6050_setSlave4OutputByte(uint8_t data);
+bool MPU6050_getSlave4Enabled();
+void MPU6050_setSlave4Enabled(bool enabled);
+bool MPU6050_getSlave4InterruptEnabled();
+void MPU6050_setSlave4InterruptEnabled(bool enabled);
+bool MPU6050_getSlave4WriteMode();
+void MPU6050_setSlave4WriteMode(bool mode);
+uint8_t MPU6050_getSlave4MasterDelay();
+void MPU6050_setSlave4MasterDelay(uint8_t delay);
+uint8_t MPU6050_getSlate4InputByte();
+
+// I2C_MST_STATUS register
+bool MPU6050_getPassthroughStatus();
+bool MPU6050_getSlave4IsDone();
+bool MPU6050_getLostArbitration();
+bool MPU6050_getSlave4Nack();
+bool MPU6050_getSlave3Nack();
+bool MPU6050_getSlave2Nack();
+bool MPU6050_getSlave1Nack();
+bool MPU6050_getSlave0Nack();
+
+// INT_PIN_CFG register
+bool MPU6050_getInterruptMode();
+void MPU6050_setInterruptMode(bool mode);
+bool MPU6050_getInterruptDrive();
+void MPU6050_setInterruptDrive(bool drive);
+bool MPU6050_getInterruptLatch();
+void MPU6050_setInterruptLatch(bool latch);
+bool MPU6050_getInterruptLatchClear();
+void MPU6050_setInterruptLatchClear(bool clear);
+bool MPU6050_getFSyncInterruptLevel();
+void MPU6050_setFSyncInterruptLevel(bool level);
+bool MPU6050_getFSyncInterruptEnabled();
+void MPU6050_setFSyncInterruptEnabled(bool enabled);
+bool MPU6050_getI2CBypassEnabled();
+void MPU6050_setI2CBypassEnabled(bool enabled);
+bool MPU6050_getClockOutputEnabled();
+void MPU6050_setClockOutputEnabled(bool enabled);
+
+// INT_ENABLE register
+uint8_t MPU6050_getIntEnabled();
+void MPU6050_setIntEnabled(uint8_t enabled);
+bool MPU6050_getIntFreefallEnabled();
+void MPU6050_setIntFreefallEnabled(bool enabled);
+bool MPU6050_getIntMotionEnabled();
+void MPU6050_setIntMotionEnabled(bool enabled);
+bool MPU6050_getIntZeroMotionEnabled();
+void MPU6050_setIntZeroMotionEnabled(bool enabled);
+bool MPU6050_getIntFIFOBufferOverflowEnabled();
+void MPU6050_setIntFIFOBufferOverflowEnabled(bool enabled);
+bool MPU6050_getIntI2CMasterEnabled();
+void MPU6050_setIntI2CMasterEnabled(bool enabled);
+bool MPU6050_getIntDataReadyEnabled();
+void MPU6050_setIntDataReadyEnabled(bool enabled);
+
+// INT_STATUS register
+uint8_t MPU6050_getIntStatus();
+bool MPU6050_getIntFreefallStatus();
+bool MPU6050_getIntMotionStatus();
+bool MPU6050_getIntZeroMotionStatus();
+bool MPU6050_getIntFIFOBufferOverflowStatus();
+bool MPU6050_getIntI2CMasterStatus();
+bool MPU6050_getIntDataReadyStatus();
+
+// ACCEL_*OUT_* registers
+void MPU6050_getMotion9(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz, int16_t* mx, int16_t* my, int16_t* mz);
+void MPU6050_getMotion6(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz);
+void MPU6050_getAcceleration(int16_t* x, int16_t* y, int16_t* z);
+int16_t MPU6050_getAccelerationX();
+int16_t MPU6050_getAccelerationY();
+int16_t MPU6050_getAccelerationZ();
+
+// TEMP_OUT_* registers
+int16_t MPU6050_getTemperature();
+
+// GYRO_*OUT_* registers
+void MPU6050_getRotation(int16_t* x, int16_t* y, int16_t* z);
+int16_t MPU6050_getRotationX();
+int16_t MPU6050_getRotationY();
+int16_t MPU6050_getRotationZ();
+
+// EXT_SENS_DATA_* registers
+uint8_t MPU6050_getExternalSensorByte(int position);
+uint16_t MPU6050_getExternalSensorWord(int position);
+uint32_t MPU6050_getExternalSensorDWord(int position);
+
+// MOT_DETECT_STATUS register
+uint8_t MPU6050_getMotionStatus();
+bool MPU6050_getXNegMotionDetected();
+bool MPU6050_getXPosMotionDetected();
+bool MPU6050_getYNegMotionDetected();
+bool MPU6050_getYPosMotionDetected();
+bool MPU6050_getZNegMotionDetected();
+bool MPU6050_getZPosMotionDetected();
+bool MPU6050_getZeroMotionDetected();
+
+// I2C_SLV*_DO register
+void MPU6050_setSlaveOutputByte(uint8_t num, uint8_t data);
+
+// I2C_MST_DELAY_CTRL register
+bool MPU6050_getExternalShadowDelayEnabled();
+void MPU6050_setExternalShadowDelayEnabled(bool enabled);
+bool MPU6050_getSlaveDelayEnabled(uint8_t num);
+void MPU6050_setSlaveDelayEnabled(uint8_t num, bool enabled);
+
+// SIGNAL_PATH_RESET register
+void MPU6050_resetGyroscopePath();
+void MPU6050_resetAccelerometerPath();
+void MPU6050_resetTemperaturePath();
+
+// MOT_DETECT_CTRL register
+uint8_t MPU6050_getAccelerometerPowerOnDelay();
+void MPU6050_setAccelerometerPowerOnDelay(uint8_t delay);
+uint8_t MPU6050_getFreefallDetectionCounterDecrement();
+void MPU6050_setFreefallDetectionCounterDecrement(uint8_t decrement);
+uint8_t MPU6050_getMotionDetectionCounterDecrement();
+void MPU6050_setMotionDetectionCounterDecrement(uint8_t decrement);
+
+// USER_CTRL register
+bool MPU6050_getFIFOEnabled();
+void MPU6050_setFIFOEnabled(bool enabled);
+bool MPU6050_getI2CMasterModeEnabled();
+void MPU6050_setI2CMasterModeEnabled(bool enabled);
+void MPU6050_switchSPIEnabled(bool enabled);
+void MPU6050_resetFIFO();
+void MPU6050_resetI2CMaster();
+void MPU6050_resetSensors();
+
+// PWR_MGMT_1 register
+void MPU6050_reset();
+bool MPU6050_getSleepEnabled();
+void MPU6050_setSleepEnabled(bool enabled);
+bool MPU6050_getWakeCycleEnabled();
+void MPU6050_setWakeCycleEnabled(bool enabled);
+bool MPU6050_getTempSensorEnabled();
+void MPU6050_setTempSensorEnabled(bool enabled);
+uint8_t MPU6050_getClockSource();
+void MPU6050_setClockSource(uint8_t source);
+
+// PWR_MGMT_2 register
+uint8_t MPU6050_getWakeFrequency();
+void MPU6050_setWakeFrequency(uint8_t frequency);
+bool MPU6050_getStandbyXAccelEnabled();
+void MPU6050_setStandbyXAccelEnabled(bool enabled);
+bool MPU6050_getStandbyYAccelEnabled();
+void MPU6050_setStandbyYAccelEnabled(bool enabled);
+bool MPU6050_getStandbyZAccelEnabled();
+void MPU6050_setStandbyZAccelEnabled(bool enabled);
+bool MPU6050_getStandbyXGyroEnabled();
+void MPU6050_setStandbyXGyroEnabled(bool enabled);
+bool MPU6050_getStandbyYGyroEnabled();
+void MPU6050_setStandbyYGyroEnabled(bool enabled);
+bool MPU6050_getStandbyZGyroEnabled();
+void MPU6050_setStandbyZGyroEnabled(bool enabled);
+
+// FIFO_COUNT_* registers
+uint16_t MPU6050_getFIFOCount();
+
+// FIFO_R_W register
+uint8_t MPU6050_getFIFOByte();
+void MPU6050_setFIFOByte(uint8_t data);
+void MPU6050_getFIFOBytes(uint8_t *data, uint8_t length);
+
+// WHO_AM_I register
+uint8_t MPU6050_getDeviceID();
+void MPU6050_setDeviceID(uint8_t id);
+
+// ======== UNDOCUMENTED/DMP REGISTERS/METHODS ========
+
+// XG_OFFS_TC register
+uint8_t MPU6050_getOTPBankValid();
+void MPU6050_setOTPBankValid(bool enabled);
+int8_t MPU6050_getXGyroOffsetTC();
+void MPU6050_setXGyroOffsetTC(int8_t offset);
+
+// YG_OFFS_TC register
+int8_t MPU6050_getYGyroOffsetTC();
+void MPU6050_setYGyroOffsetTC(int8_t offset);
+
+// ZG_OFFS_TC register
+int8_t MPU6050_getZGyroOffsetTC();
+void MPU6050_setZGyroOffsetTC(int8_t offset);
+
+// X_FINE_GAIN register
+int8_t MPU6050_getXFineGain();
+void MPU6050_setXFineGain(int8_t gain);
+
+// Y_FINE_GAIN register
+int8_t MPU6050_getYFineGain();
+void MPU6050_setYFineGain(int8_t gain);
+
+// Z_FINE_GAIN register
+int8_t MPU6050_getZFineGain();
+void MPU6050_setZFineGain(int8_t gain);
+
+// XA_OFFS_* registers
+int16_t MPU6050_getXAccelOffset();
+void MPU6050_setXAccelOffset(int16_t offset);
+
+// YA_OFFS_* register
+int16_t MPU6050_getYAccelOffset();
+void MPU6050_setYAccelOffset(int16_t offset);
+
+// ZA_OFFS_* register
+int16_t MPU6050_getZAccelOffset();
+void MPU6050_setZAccelOffset(int16_t offset);
+
+// XG_OFFS_USR* registers
+int16_t MPU6050_getXGyroOffset();
+void MPU6050_setXGyroOffset(int16_t offset);
+
+// YG_OFFS_USR* register
+int16_t MPU6050_getYGyroOffset();
+void MPU6050_setYGyroOffset(int16_t offset);
+
+// ZG_OFFS_USR* register
+int16_t MPU6050_getZGyroOffset();
+void MPU6050_setZGyroOffset(int16_t offset);
+
+// INT_ENABLE register (DMP functions)
+bool MPU6050_getIntPLLReadyEnabled();
+void MPU6050_setIntPLLReadyEnabled(bool enabled);
+bool MPU6050_getIntDMPEnabled();
+void MPU6050_setIntDMPEnabled(bool enabled);
+
+// DMP_INT_STATUS
+bool MPU6050_getDMPInt5Status();
+bool MPU6050_getDMPInt4Status();
+bool MPU6050_getDMPInt3Status();
+bool MPU6050_getDMPInt2Status();
+bool MPU6050_getDMPInt1Status();
+bool MPU6050_getDMPInt0Status();
+
+// INT_STATUS register (DMP functions)
+bool MPU6050_getIntPLLReadyStatus();
+bool MPU6050_getIntDMPStatus();
+
+// USER_CTRL register (DMP functions)
+bool MPU6050_getDMPEnabled();
+void MPU6050_setDMPEnabled(bool enabled);
+void MPU6050_resetDMP();
+
+// BANK_SEL register
+void MPU6050_setMemoryBank(uint8_t bank, bool prefetchEnabled, bool userBank);
+
+// MEM_START_ADDR register
+void MPU6050_setMemoryStartAddress(uint8_t address);
+
+// MEM_R_W register
+uint8_t MPU6050_readMemoryByte();
+void MPU6050_writeMemoryByte(uint8_t data);
+void MPU6050_readMemoryBlock(uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address);
+bool MPU6050_writeMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address, bool verify, bool useProgMem);
+bool MPU6050_writeProgMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address, bool verify);
+
+bool MPU6050_writeDMPConfigurationSet(const uint8_t *data, uint16_t dataSize, bool useProgMem);
+bool MPU6050_writeProgDMPConfigurationSet(const uint8_t *data, uint16_t dataSize);
+
+// DMP_CFG_1 register
+uint8_t MPU6050_getDMPConfig1();
+void MPU6050_setDMPConfig1(uint8_t config);
+
+// DMP_CFG_2 register
+uint8_t MPU6050_getDMPConfig2();
+void MPU6050_setDMPConfig2(uint8_t config);
+
+// special methods for MotionApps 2.0 implementation
+#ifdef MPU6050_INCLUDE_DMP_MOTIONAPPS20
+uint8_t *MPU6050_dmpPacketBuffer;
+uint16_t MPU6050_dmpPacketSize;
+
+uint8_t MPU6050_dmpInitialize();
+bool MPU6050_dmpPacketAvailable();
+
+uint8_t MPU6050_dmpSetFIFORate(uint8_t fifoRate);
+uint8_t MPU6050_dmpGetFIFORate();
+uint8_t MPU6050_dmpGetSampleStepSizeMS();
+uint8_t MPU6050_dmpGetSampleFrequency();
+int32_t MPU6050_dmpDecodeTemperature(int8_t tempReg);
+
+// Register callbacks after a packet of FIFO data is processed
+//uint8_t MPU6050_dmpGetRegisterFIFORateProcess(inv_obj_func func, int16_t priority);
+//uint8_t MPU6050_dmpGetUnregisterFIFORateProcess(inv_obj_func func);
+uint8_t MPU6050_dmpRunFIFORateProcesses();
+
+// Setup FIFO for various output
+uint8_t MPU6050_dmpSendQuaternion(uint_fast16_t accuracy);
+uint8_t MPU6050_dmpSendGyro(uint_fast16_t elements, uint_fast16_t accuracy);
+uint8_t MPU6050_dmpSendAccel(uint_fast16_t elements, uint_fast16_t accuracy);
+uint8_t MPU6050_dmpSendLinearAccel(uint_fast16_t elements, uint_fast16_t accuracy);
+uint8_t MPU6050_dmpSendLinearAccelInWorld(uint_fast16_t elements, uint_fast16_t accuracy);
+uint8_t MPU6050_dmpSendControlData(uint_fast16_t elements, uint_fast16_t accuracy);
+uint8_t MPU6050_dmpSendSensorData(uint_fast16_t elements, uint_fast16_t accuracy);
+uint8_t MPU6050_dmpSendExternalSensorData(uint_fast16_t elements, uint_fast16_t accuracy);
+uint8_t MPU6050_dmpSendGravity(uint_fast16_t elements, uint_fast16_t accuracy);
+uint8_t MPU6050_dmpSendPacketNumber(uint_fast16_t accuracy);
+uint8_t MPU6050_dmpSendQuantizedAccel(uint_fast16_t elements, uint_fast16_t accuracy);
+uint8_t MPU6050_dmpSendEIS(uint_fast16_t elements, uint_fast16_t accuracy);
+
+// Get Fixed Point data from FIFO
+uint8_t MPU6050_dmpGetAccel(int32_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetAccel(int16_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetAccel(VectorInt16 *v, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetQuaternion(int32_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetQuaternion(int16_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetQuaternion(Quaternion *q, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGet6AxisQuaternion(int32_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGet6AxisQuaternion(int16_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGet6AxisQuaternion(Quaternion *q, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetRelativeQuaternion(int32_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetRelativeQuaternion(int16_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetRelativeQuaternion(Quaternion *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetGyro(int32_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetGyro(int16_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetGyro(VectorInt16 *v, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetSetLinearAccelFilterCoefficient(float coef);
+uint8_t MPU6050_dmpGetLinearAccel(int32_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetLinearAccel(int16_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetLinearAccel(VectorInt16 *v, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetLinearAccel(VectorInt16 *v, VectorInt16 *vRaw, VectorFloat *gravity);
+uint8_t MPU6050_dmpGetLinearAccelInWorld(int32_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetLinearAccelInWorld(int16_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetLinearAccelInWorld(VectorInt16 *v, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Quaternion *q);
+uint8_t MPU6050_dmpGetGyroAndAccelSensor(int32_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetGyroAndAccelSensor(int16_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetGyroAndAccelSensor(VectorInt16 *g, VectorInt16 *a, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetGyroSensor(int32_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetGyroSensor(int16_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetGyroSensor(VectorInt16 *v, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetControlData(int32_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetTemperature(int32_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetGravity(int32_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetGravity(int16_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetGravity(VectorInt16 *v, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetGravity(VectorFloat *v, Quaternion *q);
+uint8_t MPU6050_dmpGetUnquantizedAccel(int32_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetUnquantizedAccel(int16_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetUnquantizedAccel(VectorInt16 *v, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetQuantizedAccel(int32_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetQuantizedAccel(int16_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetQuantizedAccel(VectorInt16 *v, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetExternalSensorData(int32_t *data, uint16_t size, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetEIS(int32_t *data, const uint8_t* packet=0);
+
+uint8_t MPU6050_dmpGetEuler(float *data, Quaternion *q);
+uint8_t MPU6050_dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity);
+
+// Get Floating Point data from FIFO
+uint8_t MPU6050_dmpGetAccelFloat(float *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetQuaternionFloat(float *data, const uint8_t* packet=0);
+
+uint8_t MPU6050_dmpGetProcessFIFOPacket(const unsigned char *dmpData);
+uint8_t MPU6050_dmpGetReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *processed=NULL);
+
+uint8_t MPU6050_dmpGetSetFIFOProcessedCallback(void (*func) (void));
+
+uint8_t MPU6050_dmpGetInitFIFOParam();
+uint8_t MPU6050_dmpGetCloseFIFO();
+uint8_t MPU6050_dmpGetSetGyroDataSource(uint8_t source);
+uint8_t MPU6050_dmpGetDecodeQuantizedAccel();
+uint32_t dmpGetGyroSumOfSquare();
+uint32_t dmpGetAccelSumOfSquare();
+void dmpOverrideQuaternion(long *q);
+uint16_t dmpGetFIFOPacketSize();
+#endif
+
+// special methods for MotionApps 4.1 implementation
+#ifdef MPU6050_INCLUDE_DMP_MOTIONAPPS41
+uint8_t *dmpPacketBuffer;
+uint16_t dmpPacketSize;
+
+uint8_t MPU6050_dmpGetInitialize();
+bool dmpPacketAvailable();
+
+uint8_t MPU6050_dmpGetSetFIFORate(uint8_t fifoRate);
+uint8_t MPU6050_dmpGetFIFORate();
+uint8_t MPU6050_dmpGetSampleStepSizeMS();
+uint8_t MPU6050_dmpGetSampleFrequency();
+int32_t dmpDecodeTemperature(int8_t tempReg);
+
+// Register callbacks after a packet of FIFO data is processed
+//uint8_t MPU6050_dmpGetRegisterFIFORateProcess(inv_obj_func func, int16_t priority);
+//uint8_t MPU6050_dmpGetUnregisterFIFORateProcess(inv_obj_func func);
+uint8_t MPU6050_dmpGetRunFIFORateProcesses();
+
+// Setup FIFO for various output
+uint8_t MPU6050_dmpGetSendQuaternion(uint_fast16_t accuracy);
+uint8_t MPU6050_dmpGetSendGyro(uint_fast16_t elements, uint_fast16_t accuracy);
+uint8_t MPU6050_dmpGetSendAccel(uint_fast16_t elements, uint_fast16_t accuracy);
+uint8_t MPU6050_dmpGetSendLinearAccel(uint_fast16_t elements, uint_fast16_t accuracy);
+uint8_t MPU6050_dmpGetSendLinearAccelInWorld(uint_fast16_t elements, uint_fast16_t accuracy);
+uint8_t MPU6050_dmpGetSendControlData(uint_fast16_t elements, uint_fast16_t accuracy);
+uint8_t MPU6050_dmpGetSendSensorData(uint_fast16_t elements, uint_fast16_t accuracy);
+uint8_t MPU6050_dmpGetSendExternalSensorData(uint_fast16_t elements, uint_fast16_t accuracy);
+uint8_t MPU6050_dmpGetSendGravity(uint_fast16_t elements, uint_fast16_t accuracy);
+uint8_t MPU6050_dmpGetSendPacketNumber(uint_fast16_t accuracy);
+uint8_t MPU6050_dmpGetSendQuantizedAccel(uint_fast16_t elements, uint_fast16_t accuracy);
+uint8_t MPU6050_dmpGetSendEIS(uint_fast16_t elements, uint_fast16_t accuracy);
+
+// Get Fixed Point data from FIFO
+uint8_t MPU6050_dmpGetAccel(int32_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetAccel(int16_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetAccel(VectorInt16 *v, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetQuaternion(int32_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetQuaternion(int16_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetQuaternion(Quaternion *q, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGet6AxisQuaternion(int32_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGet6AxisQuaternion(int16_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGet6AxisQuaternion(Quaternion *q, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetRelativeQuaternion(int32_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetRelativeQuaternion(int16_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetRelativeQuaternion(Quaternion *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetGyro(int32_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetGyro(int16_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetGyro(VectorInt16 *v, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetMag(int16_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetSetLinearAccelFilterCoefficient(float coef);
+uint8_t MPU6050_dmpGetLinearAccel(int32_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetLinearAccel(int16_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetLinearAccel(VectorInt16 *v, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetLinearAccel(VectorInt16 *v, VectorInt16 *vRaw, VectorFloat *gravity);
+uint8_t MPU6050_dmpGetLinearAccelInWorld(int32_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetLinearAccelInWorld(int16_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetLinearAccelInWorld(VectorInt16 *v, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Quaternion *q);
+uint8_t MPU6050_dmpGetGyroAndAccelSensor(int32_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetGyroAndAccelSensor(int16_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetGyroAndAccelSensor(VectorInt16 *g, VectorInt16 *a, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetGyroSensor(int32_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetGyroSensor(int16_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetGyroSensor(VectorInt16 *v, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetControlData(int32_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetTemperature(int32_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetGravity(int32_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetGravity(int16_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetGravity(VectorInt16 *v, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetGravity(VectorFloat *v, Quaternion *q);
+uint8_t MPU6050_dmpGetUnquantizedAccel(int32_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetUnquantizedAccel(int16_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetUnquantizedAccel(VectorInt16 *v, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetQuantizedAccel(int32_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetQuantizedAccel(int16_t *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetQuantizedAccel(VectorInt16 *v, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetExternalSensorData(int32_t *data, uint16_t size, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetEIS(int32_t *data, const uint8_t* packet=0);
+
+uint8_t MPU6050_dmpGetEuler(float *data, Quaternion *q);
+uint8_t MPU6050_dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity);
+
+// Get Floating Point data from FIFO
+uint8_t MPU6050_dmpGetAccelFloat(float *data, const uint8_t* packet=0);
+uint8_t MPU6050_dmpGetQuaternionFloat(float *data, const uint8_t* packet=0);
+
+uint8_t MPU6050_dmpGetProcessFIFOPacket(const unsigned char *dmpData);
+uint8_t MPU6050_dmpGetReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *processed=NULL);
+
+uint8_t MPU6050_dmpGetSetFIFOProcessedCallback(void (*func) (void));
+
+uint8_t MPU6050_dmpGetInitFIFOParam();
+uint8_t MPU6050_dmpGetCloseFIFO();
+uint8_t MPU6050_dmpGetSetGyroDataSource(uint8_t source);
+uint8_t MPU6050_dmpGetDecodeQuantizedAccel();
+uint32_t MPU6050_dmpGetGyroSumOfSquare();
+uint32_t MPU6050_dmpGetAccelSumOfSquare();
+void MPU6050_dmpOverrideQuaternion(long *q);
+uint16_t MPU6050_dmpGetFIFOPacketSize();
+#endif
+
+#endif /* _MPU6050_H_ */

From 48459bf7d5516b519196dda187f760dc620718af Mon Sep 17 00:00:00 2001
From: Andrey Voloshin 
Date: Sat, 6 Jun 2015 17:59:33 +0300
Subject: [PATCH 079/335] Updated readme with MPU6050

---
 STM32/README.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/STM32/README.md b/STM32/README.md
index e16afe47..f386ea5f 100644
--- a/STM32/README.md
+++ b/STM32/README.md
@@ -1,11 +1,11 @@
 # I2C Device Library for STM32
 
 ## Devices
-Currently only BMP180/BMP085 is supported. MPU6050 and HMC5883L will come soon (GY-87 board).
+Currently MPU6050 (w/o DMP) and BMP180/BMP085 are ported. ADXL345 and HMC5883L coming soon (GY-87 board).
 Adding more functions and devices should be straighforward after reading the source code of the driver.
 Porting drivers should be as simple, as renaming public methods from *DRIVER::func()* to *DRIVER_func()* and moving private fields and functions to *.c file
 
-## Example for STM32F429I-DISCO board
+## BMP180 Example for STM32F429I-DISCO board
 ```C
 #include "stm32f4xx.h"
 #include "stm32f4xx_hal.h"

From 452ca19a99371b73f7f62aa29f70ee75817e4e2c Mon Sep 17 00:00:00 2001
From: Andrey Voloshin 
Date: Mon, 8 Jun 2015 15:35:21 +0300
Subject: [PATCH 080/335] HMC5883L ported to STM32

---
 STM32/HMC5883L/HMC5883L.c | 356 ++++++++++++++++++++++++++++++++++++++
 STM32/HMC5883L/HMC5883L.h | 139 +++++++++++++++
 STM32/README.md           |   2 +-
 3 files changed, 496 insertions(+), 1 deletion(-)
 create mode 100644 STM32/HMC5883L/HMC5883L.c
 create mode 100644 STM32/HMC5883L/HMC5883L.h

diff --git a/STM32/HMC5883L/HMC5883L.c b/STM32/HMC5883L/HMC5883L.c
new file mode 100644
index 00000000..9bd2a598
--- /dev/null
+++ b/STM32/HMC5883L/HMC5883L.c
@@ -0,0 +1,356 @@
+// I2Cdev library collection - HMC5883L I2C device class
+// Based on Honeywell HMC5883L datasheet, 10/2010 (Form #900405 Rev B)
+// 6/12/2012 by Jeff Rowberg 
+// 6/6/2015 by Andrey Voloshin 
+//
+// Changelog:
+//      2015-06-06 - ported to STM32 HAL library from Arduino code
+//     2012-06-12 - fixed swapped Y/Z axes
+//     2011-08-22 - small Doxygen comment fixes
+//     2011-07-31 - initial release
+
+/* ============================================
+I2Cdev device library code is placed under the MIT license
+Copyright (c) 2012 Jeff Rowberg
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+===============================================
+*/
+
+#include "HMC5883L.h"
+
+static uint8_t devAddr;
+static uint8_t buffer[6];
+static uint8_t mode;
+
+
+/** Power on and prepare for general usage.
+ * This will prepare the magnetometer with default settings, ready for single-
+ * use mode (very low power requirements). Default settings include 8-sample
+ * averaging, 15 Hz data output rate, normal measurement bias, a,d 1090 gain (in
+ * terms of LSB/Gauss). Be sure to adjust any settings you need specifically
+ * after initialization, especially the gain settings if you happen to be seeing
+ * a lot of -4096 values (see the datasheet for mor information).
+ */
+void HMC5883L_initialize() {
+    devAddr = HMC5883L_DEFAULT_ADDRESS;
+    // write CONFIG_A register
+    I2Cdev_writeByte(devAddr, HMC5883L_RA_CONFIG_A,
+        (HMC5883L_AVERAGING_8 << (HMC5883L_CRA_AVERAGE_BIT - HMC5883L_CRA_AVERAGE_LENGTH + 1)) |
+        (HMC5883L_RATE_15     << (HMC5883L_CRA_RATE_BIT - HMC5883L_CRA_RATE_LENGTH + 1)) |
+        (HMC5883L_BIAS_NORMAL << (HMC5883L_CRA_BIAS_BIT - HMC5883L_CRA_BIAS_LENGTH + 1)));
+
+    // write CONFIG_B register
+    HMC5883L_setGain(HMC5883L_GAIN_1090);
+
+    // write MODE register
+    HMC5883L_setMode(HMC5883L_MODE_SINGLE);
+}
+
+/** Verify the I2C connection.
+ * Make sure the device is connected and responds as expected.
+ * @return True if connection is valid, false otherwise
+ */
+bool HMC5883L_testConnection() {
+    if (I2Cdev_readBytes(devAddr, HMC5883L_RA_ID_A, 3, buffer, 0) == 3) {
+        return (buffer[0] == 'H' && buffer[1] == '4' && buffer[2] == '3');
+    }
+    return false;
+}
+
+// CONFIG_A register
+
+/** Get number of samples averaged per measurement.
+ * @return Current samples averaged per measurement (0-3 for 1/2/4/8 respectively)
+ * @see HMC5883L_AVERAGING_8
+ * @see HMC5883L_RA_CONFIG_A
+ * @see HMC5883L_CRA_AVERAGE_BIT
+ * @see HMC5883L_CRA_AVERAGE_LENGTH
+ */
+uint8_t HMC5883L_getSampleAveraging() {
+    I2Cdev_readBits(devAddr, HMC5883L_RA_CONFIG_A, HMC5883L_CRA_AVERAGE_BIT, HMC5883L_CRA_AVERAGE_LENGTH, buffer, 0);
+    return buffer[0];
+}
+/** Set number of samples averaged per measurement.
+ * @param averaging New samples averaged per measurement setting(0-3 for 1/2/4/8 respectively)
+ * @see HMC5883L_RA_CONFIG_A
+ * @see HMC5883L_CRA_AVERAGE_BIT
+ * @see HMC5883L_CRA_AVERAGE_LENGTH
+ */
+void HMC5883L_setSampleAveraging(uint8_t averaging) {
+    I2Cdev_writeBits(devAddr, HMC5883L_RA_CONFIG_A, HMC5883L_CRA_AVERAGE_BIT, HMC5883L_CRA_AVERAGE_LENGTH, averaging);
+}
+/** Get data output rate value.
+ * The Table below shows all selectable output rates in continuous measurement
+ * mode. All three channels shall be measured within a given output rate. Other
+ * output rates with maximum rate of 160 Hz can be achieved by monitoring DRDY
+ * interrupt pin in single measurement mode.
+ *
+ * Value | Typical Data Output Rate (Hz)
+ * ------+------------------------------
+ * 0     | 0.75
+ * 1     | 1.5
+ * 2     | 3
+ * 3     | 7.5
+ * 4     | 15 (Default)
+ * 5     | 30
+ * 6     | 75
+ * 7     | Not used
+ *
+ * @return Current rate of data output to registers
+ * @see HMC5883L_RATE_15
+ * @see HMC5883L_RA_CONFIG_A
+ * @see HMC5883L_CRA_RATE_BIT
+ * @see HMC5883L_CRA_RATE_LENGTH
+ */
+uint8_t HMC5883L_getDataRate() {
+    I2Cdev_readBits(devAddr, HMC5883L_RA_CONFIG_A, HMC5883L_CRA_RATE_BIT, HMC5883L_CRA_RATE_LENGTH, buffer, 0);
+    return buffer[0];
+}
+/** Set data output rate value.
+ * @param rate Rate of data output to registers
+ * @see getDataRate()
+ * @see HMC5883L_RATE_15
+ * @see HMC5883L_RA_CONFIG_A
+ * @see HMC5883L_CRA_RATE_BIT
+ * @see HMC5883L_CRA_RATE_LENGTH
+ */
+void HMC5883L_setDataRate(uint8_t rate) {
+    I2Cdev_writeBits(devAddr, HMC5883L_RA_CONFIG_A, HMC5883L_CRA_RATE_BIT, HMC5883L_CRA_RATE_LENGTH, rate);
+}
+/** Get measurement bias value.
+ * @return Current bias value (0-2 for normal/positive/negative respectively)
+ * @see HMC5883L_BIAS_NORMAL
+ * @see HMC5883L_RA_CONFIG_A
+ * @see HMC5883L_CRA_BIAS_BIT
+ * @see HMC5883L_CRA_BIAS_LENGTH
+ */
+uint8_t HMC5883L_getMeasurementBias() {
+    I2Cdev_readBits(devAddr, HMC5883L_RA_CONFIG_A, HMC5883L_CRA_BIAS_BIT, HMC5883L_CRA_BIAS_LENGTH, buffer, 0);
+    return buffer[0];
+}
+/** Set measurement bias value.
+ * @param bias New bias value (0-2 for normal/positive/negative respectively)
+ * @see HMC5883L_BIAS_NORMAL
+ * @see HMC5883L_RA_CONFIG_A
+ * @see HMC5883L_CRA_BIAS_BIT
+ * @see HMC5883L_CRA_BIAS_LENGTH
+ */
+void HMC5883L_setMeasurementBias(uint8_t bias) {
+    I2Cdev_writeBits(devAddr, HMC5883L_RA_CONFIG_A, HMC5883L_CRA_BIAS_BIT, HMC5883L_CRA_BIAS_LENGTH, bias);
+}
+
+// CONFIG_B register
+
+/** Get magnetic field gain value.
+ * The table below shows nominal gain settings. Use the "Gain" column to convert
+ * counts to Gauss. Choose a lower gain value (higher GN#) when total field
+ * strength causes overflow in one of the data output registers (saturation).
+ * The data output range for all settings is 0xF800-0x07FF (-2048 - 2047).
+ *
+ * Value | Field Range | Gain (LSB/Gauss)
+ * ------+-------------+-----------------
+ * 0     | +/- 0.88 Ga | 1370
+ * 1     | +/- 1.3 Ga  | 1090 (Default)
+ * 2     | +/- 1.9 Ga  | 820
+ * 3     | +/- 2.5 Ga  | 660
+ * 4     | +/- 4.0 Ga  | 440
+ * 5     | +/- 4.7 Ga  | 390
+ * 6     | +/- 5.6 Ga  | 330
+ * 7     | +/- 8.1 Ga  | 230
+ *
+ * @return Current magnetic field gain value
+ * @see HMC5883L_GAIN_1090
+ * @see HMC5883L_RA_CONFIG_B
+ * @see HMC5883L_CRB_GAIN_BIT
+ * @see HMC5883L_CRB_GAIN_LENGTH
+ */
+uint8_t HMC5883L_getGain() {
+    I2Cdev_readBits(devAddr, HMC5883L_RA_CONFIG_B, HMC5883L_CRB_GAIN_BIT, HMC5883L_CRB_GAIN_LENGTH, buffer, 0);
+    return buffer[0];
+}
+/** Set magnetic field gain value.
+ * @param gain New magnetic field gain value
+ * @see getGain()
+ * @see HMC5883L_RA_CONFIG_B
+ * @see HMC5883L_CRB_GAIN_BIT
+ * @see HMC5883L_CRB_GAIN_LENGTH
+ */
+void HMC5883L_setGain(uint8_t gain) {
+    // use this method to guarantee that bits 4-0 are set to zero, which is a
+    // requirement specified in the datasheet; it's actually more efficient than
+    // using the I2Cdev.writeBits method
+    I2Cdev_writeByte(devAddr, HMC5883L_RA_CONFIG_B, gain << (HMC5883L_CRB_GAIN_BIT - HMC5883L_CRB_GAIN_LENGTH + 1));
+}
+
+// MODE register
+
+/** Get measurement mode.
+ * In continuous-measurement mode, the device continuously performs measurements
+ * and places the result in the data register. RDY goes high when new data is
+ * placed in all three registers. After a power-on or a write to the mode or
+ * configuration register, the first measurement set is available from all three
+ * data output registers after a period of 2/fDO and subsequent measurements are
+ * available at a frequency of fDO, where fDO is the frequency of data output.
+ *
+ * When single-measurement mode (default) is selected, device performs a single
+ * measurement, sets RDY high and returned to idle mode. Mode register returns
+ * to idle mode bit values. The measurement remains in the data output register
+ * and RDY remains high until the data output register is read or another
+ * measurement is performed.
+ *
+ * @return Current measurement mode
+ * @see HMC5883L_MODE_CONTINUOUS
+ * @see HMC5883L_MODE_SINGLE
+ * @see HMC5883L_MODE_IDLE
+ * @see HMC5883L_RA_MODE
+ * @see HMC5883L_MODEREG_BIT
+ * @see HMC5883L_MODEREG_LENGTH
+ */
+uint8_t HMC5883L_getMode() {
+    I2Cdev_readBits(devAddr, HMC5883L_RA_MODE, HMC5883L_MODEREG_BIT, HMC5883L_MODEREG_LENGTH, buffer, 0);
+    return buffer[0];
+}
+/** Set measurement mode.
+ * @param newMode New measurement mode
+ * @see getMode()
+ * @see HMC5883L_MODE_CONTINUOUS
+ * @see HMC5883L_MODE_SINGLE
+ * @see HMC5883L_MODE_IDLE
+ * @see HMC5883L_RA_MODE
+ * @see HMC5883L_MODEREG_BIT
+ * @see HMC5883L_MODEREG_LENGTH
+ */
+void HMC5883L_setMode(uint8_t newMode) {
+    // use this method to guarantee that bits 7-2 are set to zero, which is a
+    // requirement specified in the datasheet; it's actually more efficient than
+    // using the I2Cdev.writeBits method
+    I2Cdev_writeByte(devAddr, HMC5883L_RA_MODE, newMode << (HMC5883L_MODEREG_BIT - HMC5883L_MODEREG_LENGTH + 1));
+    mode = newMode; // track to tell if we have to clear bit 7 after a read
+}
+
+// DATA* registers
+
+/** Get 3-axis heading measurements.
+ * In the event the ADC reading overflows or underflows for the given channel,
+ * or if there is a math overflow during the bias measurement, this data
+ * register will contain the value -4096. This register value will clear when
+ * after the next valid measurement is made. Note that this method automatically
+ * clears the appropriate bit in the MODE register if Single mode is active.
+ * @param x 16-bit signed integer container for X-axis heading
+ * @param y 16-bit signed integer container for Y-axis heading
+ * @param z 16-bit signed integer container for Z-axis heading
+ * @see HMC5883L_RA_DATAX_H
+ */
+void HMC5883L_getHeading(int16_t *x, int16_t *y, int16_t *z) {
+    I2Cdev_readBytes(devAddr, HMC5883L_RA_DATAX_H, 6, buffer, 0);
+    if (mode == HMC5883L_MODE_SINGLE) I2Cdev_writeByte(devAddr, HMC5883L_RA_MODE, HMC5883L_MODE_SINGLE << (HMC5883L_MODEREG_BIT - HMC5883L_MODEREG_LENGTH + 1));
+    *x = (((int16_t)buffer[0]) << 8) | buffer[1];
+    *y = (((int16_t)buffer[4]) << 8) | buffer[5];
+    *z = (((int16_t)buffer[2]) << 8) | buffer[3];
+}
+/** Get X-axis heading measurement.
+ * @return 16-bit signed integer with X-axis heading
+ * @see HMC5883L_RA_DATAX_H
+ */
+int16_t HMC5883L_getHeadingX() {
+    // each axis read requires that ALL axis registers be read, even if only
+    // one is used; this was not done ineffiently in the code by accident
+    I2Cdev_readBytes(devAddr, HMC5883L_RA_DATAX_H, 6, buffer, 0);
+    if (mode == HMC5883L_MODE_SINGLE) I2Cdev_writeByte(devAddr, HMC5883L_RA_MODE, HMC5883L_MODE_SINGLE << (HMC5883L_MODEREG_BIT - HMC5883L_MODEREG_LENGTH + 1));
+    return (((int16_t)buffer[0]) << 8) | buffer[1];
+}
+/** Get Y-axis heading measurement.
+ * @return 16-bit signed integer with Y-axis heading
+ * @see HMC5883L_RA_DATAY_H
+ */
+int16_t HMC5883L_getHeadingY() {
+    // each axis read requires that ALL axis registers be read, even if only
+    // one is used; this was not done ineffiently in the code by accident
+    I2Cdev_readBytes(devAddr, HMC5883L_RA_DATAX_H, 6, buffer, 0);
+    if (mode == HMC5883L_MODE_SINGLE) I2Cdev_writeByte(devAddr, HMC5883L_RA_MODE, HMC5883L_MODE_SINGLE << (HMC5883L_MODEREG_BIT - HMC5883L_MODEREG_LENGTH + 1));
+    return (((int16_t)buffer[4]) << 8) | buffer[5];
+}
+/** Get Z-axis heading measurement.
+ * @return 16-bit signed integer with Z-axis heading
+ * @see HMC5883L_RA_DATAZ_H
+ */
+int16_t HMC5883L_getHeadingZ() {
+    // each axis read requires that ALL axis registers be read, even if only
+    // one is used; this was not done ineffiently in the code by accident
+    I2Cdev_readBytes(devAddr, HMC5883L_RA_DATAX_H, 6, buffer, 0);
+    if (mode == HMC5883L_MODE_SINGLE) I2Cdev_writeByte(devAddr, HMC5883L_RA_MODE, HMC5883L_MODE_SINGLE << (HMC5883L_MODEREG_BIT - HMC5883L_MODEREG_LENGTH + 1));
+    return (((int16_t)buffer[2]) << 8) | buffer[3];
+}
+
+// STATUS register
+
+/** Get data output register lock status.
+ * This bit is set when this some but not all for of the six data output
+ * registers have been read. When this bit is set, the six data output registers
+ * are locked and any new data will not be placed in these register until one of
+ * three conditions are met: one, all six bytes have been read or the mode
+ * changed, two, the mode is changed, or three, the measurement configuration is
+ * changed.
+ * @return Data output register lock status
+ * @see HMC5883L_RA_STATUS
+ * @see HMC5883L_STATUS_LOCK_BIT
+ */
+bool HMC5883L_getLockStatus() {
+    I2Cdev_readBit(devAddr, HMC5883L_RA_STATUS, HMC5883L_STATUS_LOCK_BIT, buffer, 0);
+    return buffer[0];
+}
+/** Get data ready status.
+ * This bit is set when data is written to all six data registers, and cleared
+ * when the device initiates a write to the data output registers and after one
+ * or more of the data output registers are written to. When RDY bit is clear it
+ * shall remain cleared for 250 us. DRDY pin can be used as an alternative to
+ * the status register for monitoring the device for measurement data.
+ * @return Data ready status
+ * @see HMC5883L_RA_STATUS
+ * @see HMC5883L_STATUS_READY_BIT
+ */
+bool HMC5883L_getReadyStatus() {
+    I2Cdev_readBit(devAddr, HMC5883L_RA_STATUS, HMC5883L_STATUS_READY_BIT, buffer, 0);
+    return buffer[0];
+}
+
+// ID_* registers
+
+/** Get identification byte A
+ * @return ID_A byte (should be 01001000, ASCII value 'H')
+ */
+uint8_t HMC5883L_getIDA() {
+    I2Cdev_readByte(devAddr, HMC5883L_RA_ID_A, buffer, 0);
+    return buffer[0];
+}
+/** Get identification byte B
+ * @return ID_A byte (should be 00110100, ASCII value '4')
+ */
+uint8_t HMC5883L_getIDB() {
+    I2Cdev_readByte(devAddr, HMC5883L_RA_ID_B, buffer, 0);
+    return buffer[0];
+}
+/** Get identification byte C
+ * @return ID_A byte (should be 00110011, ASCII value '3')
+ */
+uint8_t HMC5883L_getIDC() {
+    I2Cdev_readByte(devAddr, HMC5883L_RA_ID_C, buffer, 0);
+    return buffer[0];
+}
diff --git a/STM32/HMC5883L/HMC5883L.h b/STM32/HMC5883L/HMC5883L.h
new file mode 100644
index 00000000..cd506f47
--- /dev/null
+++ b/STM32/HMC5883L/HMC5883L.h
@@ -0,0 +1,139 @@
+// I2Cdev library collection - HMC5883L I2C device class header file
+// Based on Honeywell HMC5883L datasheet, 10/2010 (Form #900405 Rev B)
+// 6/12/2012 by Jeff Rowberg 
+// 6/6/2015 by Andrey Voloshin 
+//
+// Changelog:
+//      2015-06-06 - ported to STM32 HAL library from Arduino code
+//     2012-06-12 - fixed swapped Y/Z axes
+//     2011-08-22 - small Doxygen comment fixes
+//     2011-07-31 - initial release
+
+/* ============================================
+I2Cdev device library code is placed under the MIT license
+Copyright (c) 2011 Jeff Rowberg
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+===============================================
+*/
+
+#ifndef _HMC5883L_H_
+#define _HMC5883L_H_
+
+#include "I2Cdev.h"
+
+#define HMC5883L_ADDRESS            0x1E // this device only has one address
+#define HMC5883L_DEFAULT_ADDRESS    0x1E
+
+#define HMC5883L_RA_CONFIG_A        0x00
+#define HMC5883L_RA_CONFIG_B        0x01
+#define HMC5883L_RA_MODE            0x02
+#define HMC5883L_RA_DATAX_H         0x03
+#define HMC5883L_RA_DATAX_L         0x04
+#define HMC5883L_RA_DATAZ_H         0x05
+#define HMC5883L_RA_DATAZ_L         0x06
+#define HMC5883L_RA_DATAY_H         0x07
+#define HMC5883L_RA_DATAY_L         0x08
+#define HMC5883L_RA_STATUS          0x09
+#define HMC5883L_RA_ID_A            0x0A
+#define HMC5883L_RA_ID_B            0x0B
+#define HMC5883L_RA_ID_C            0x0C
+
+#define HMC5883L_CRA_AVERAGE_BIT    6
+#define HMC5883L_CRA_AVERAGE_LENGTH 2
+#define HMC5883L_CRA_RATE_BIT       4
+#define HMC5883L_CRA_RATE_LENGTH    3
+#define HMC5883L_CRA_BIAS_BIT       1
+#define HMC5883L_CRA_BIAS_LENGTH    2
+
+#define HMC5883L_AVERAGING_1        0x00
+#define HMC5883L_AVERAGING_2        0x01
+#define HMC5883L_AVERAGING_4        0x02
+#define HMC5883L_AVERAGING_8        0x03
+
+#define HMC5883L_RATE_0P75          0x00
+#define HMC5883L_RATE_1P5           0x01
+#define HMC5883L_RATE_3             0x02
+#define HMC5883L_RATE_7P5           0x03
+#define HMC5883L_RATE_15            0x04
+#define HMC5883L_RATE_30            0x05
+#define HMC5883L_RATE_75            0x06
+
+#define HMC5883L_BIAS_NORMAL        0x00
+#define HMC5883L_BIAS_POSITIVE      0x01
+#define HMC5883L_BIAS_NEGATIVE      0x02
+
+#define HMC5883L_CRB_GAIN_BIT       7
+#define HMC5883L_CRB_GAIN_LENGTH    3
+
+#define HMC5883L_GAIN_1370          0x00
+#define HMC5883L_GAIN_1090          0x01
+#define HMC5883L_GAIN_820           0x02
+#define HMC5883L_GAIN_660           0x03
+#define HMC5883L_GAIN_440           0x04
+#define HMC5883L_GAIN_390           0x05
+#define HMC5883L_GAIN_330           0x06
+#define HMC5883L_GAIN_220           0x07
+
+#define HMC5883L_MODEREG_BIT        1
+#define HMC5883L_MODEREG_LENGTH     2
+
+#define HMC5883L_MODE_CONTINUOUS    0x00
+#define HMC5883L_MODE_SINGLE        0x01
+#define HMC5883L_MODE_IDLE          0x02
+
+#define HMC5883L_STATUS_LOCK_BIT    1
+#define HMC5883L_STATUS_READY_BIT   0
+
+void HMC5883L_initialize();
+bool HMC5883L_testConnection();
+
+// CONFIG_A register
+uint8_t HMC5883L_getSampleAveraging();
+void HMC5883L_setSampleAveraging(uint8_t averaging);
+uint8_t HMC5883L_getDataRate();
+void HMC5883L_setDataRate(uint8_t rate);
+uint8_t HMC5883L_getMeasurementBias();
+void HMC5883L_setMeasurementBias(uint8_t bias);
+
+// CONFIG_B register
+uint8_t HMC5883L_getGain();
+void HMC5883L_setGain(uint8_t gain);
+
+// MODE register
+uint8_t HMC5883L_getMode();
+void HMC5883L_setMode(uint8_t mode);
+
+// DATA* registers
+void HMC5883L_getHeading(int16_t *x, int16_t *y, int16_t *z);
+int16_t HMC5883L_getHeadingX();
+int16_t HMC5883L_getHeadingY();
+int16_t HMC5883L_getHeadingZ();
+
+// STATUS register
+bool HMC5883L_getLockStatus();
+bool HMC5883L_getReadyStatus();
+
+// ID_* registers
+uint8_t HMC5883L_getIDA();
+uint8_t HMC5883L_getIDB();
+uint8_t HMC5883L_getIDC();
+
+
+#endif /* _HMC5883L_H_ */
diff --git a/STM32/README.md b/STM32/README.md
index f386ea5f..aa9e7f57 100644
--- a/STM32/README.md
+++ b/STM32/README.md
@@ -1,7 +1,7 @@
 # I2C Device Library for STM32
 
 ## Devices
-Currently MPU6050 (w/o DMP) and BMP180/BMP085 are ported. ADXL345 and HMC5883L coming soon (GY-87 board).
+Currently MPU6050 (with DMP), HMC5883L and BMP180/BMP085 are ported (GY-87 board). ADXL345 is coming soon.
 Adding more functions and devices should be straighforward after reading the source code of the driver.
 Porting drivers should be as simple, as renaming public methods from *DRIVER::func()* to *DRIVER_func()* and moving private fields and functions to *.c file
 

From 63783b13b01e10b7fdae39a68eff6d05aef3b009 Mon Sep 17 00:00:00 2001
From: surrel 
Date: Wed, 24 Jun 2015 18:22:37 +0200
Subject: [PATCH 081/335] Added Jennic platform and MPU6050 device
 implementation

---
 Jennic/I2Cdev/I2Cdev.c   |  882 ++++++++++
 Jennic/I2Cdev/I2Cdev.h   |   59 +
 Jennic/MPU6050/MPU6050.c | 3422 ++++++++++++++++++++++++++++++++++++++
 Jennic/MPU6050/MPU6050.h |  982 +++++++++++
 Jennic/README.md         |   14 +
 README                   |    6 +-
 6 files changed, 5362 insertions(+), 3 deletions(-)
 create mode 100644 Jennic/I2Cdev/I2Cdev.c
 create mode 100644 Jennic/I2Cdev/I2Cdev.h
 create mode 100644 Jennic/MPU6050/MPU6050.c
 create mode 100644 Jennic/MPU6050/MPU6050.h
 create mode 100644 Jennic/README.md

diff --git a/Jennic/I2Cdev/I2Cdev.c b/Jennic/I2Cdev/I2Cdev.c
new file mode 100644
index 00000000..c7619c92
--- /dev/null
+++ b/Jennic/I2Cdev/I2Cdev.c
@@ -0,0 +1,882 @@
+// I2Cdev library collection - Main I2C device class
+// Abstracts bit and byte I2C R/W functions into a convenient class
+// 6/9/2012 by Jeff Rowberg 
+// 11/28/2014 by Marton Sebok 
+// 24/06/2015 by Grégoire Surrel 
+//
+// Changelog:
+//     2014-11-28 - ported to PIC18 peripheral library from Arduino code
+//     2015-06-24 - ported to Jennic peripheral library from PIC18 code
+
+/* ============================================
+I2Cdev device library code is placed under the MIT license
+Copyright (c) 2013 Jeff Rowberg
+Copyright (c) 2014 Marton Sebok
+Copyright (c) 2015 Grégoire Surrel
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+===============================================
+ */
+
+#include "I2Cdev.h"
+#include 
+#include 
+#include "os.h"
+#include "os_gen.h"
+#include "dbg.h"
+#include "dbg_uart.h"
+
+//#define I2CDEV_SERIAL_DEBUG
+
+#define COMMAND_WRITE FALSE
+#define COMMAND_READ TRUE
+
+#define SEND_ACK E_AHI_SI_SEND_ACK
+#define SEND_NACK E_AHI_SI_SEND_NACK
+#define SEND_CONTINUE E_AHI_SI_NO_STOP_BIT
+#define SEND_STOP E_AHI_SI_STOP_BIT
+
+// Helper variables
+bool_t I2Cdev_enabled = FALSE;//Tracks whether the I2C interface is enabled or not
+
+bool_t debug = FALSE;
+uint8 i2cdev_debug_depth = 0;
+
+// Helper functions
+
+/** Active wait .
+ * @return Status of wait (timeout or succeed)
+ */
+bool_t IdleI2C() {
+
+#ifdef I2CDEV_SERIAL_DEBUG
+	i2cdev_debug_depth++; int z; for(z=0;z 010 shifted
+	uint8 count, b;
+	if ((count = I2Cdev_readByte(devAddr, regAddr, &b)) != 0) {
+		uint8 mask = ((1 << length) - 1) << (bitStart - length + 1);
+		b &= mask;
+		b >>= (bitStart - length + 1);
+		*data = b;
+	}
+
+#ifdef I2CDEV_SERIAL_DEBUG
+	i2cdev_debug_depth--;
+#endif
+
+	return count;
+}
+
+/** Read multiple bits from a 16-bit device register.
+ * @param devAddr I2C slave device address
+ * @param regAddr Register regAddr to read from
+ * @param bitStart First bit position to read (0-15)
+ * @param length Number of bits to read (not more than 16)
+ * @param data Container for right-aligned value (i.e. '101' read from any bitStart position will equal 0x05)
+ * @return Status of read operation (1 = success, 0 = failure, -1 = timeout)
+ */
+int8 I2Cdev_readBitsW(uint8 devAddr, uint8 regAddr, uint8 bitStart, uint8 length, uint16 *data) {
+
+#ifdef I2CDEV_SERIAL_DEBUG
+	i2cdev_debug_depth++; int z; for(z=0;z 010 shifted
+	uint8 count;
+	uint16 w;
+	if ((count = I2Cdev_readWord(devAddr, regAddr, &w)) != 0) {
+		uint16 mask = ((1 << length) - 1) << (bitStart - length + 1);
+		w &= mask;
+		w >>= (bitStart - length + 1);
+		*data = w;
+	}
+
+#ifdef I2CDEV_SERIAL_DEBUG
+	i2cdev_debug_depth--;
+#endif
+
+	return count;
+}
+
+/** Write multiple bytes to an 8-bit device register.
+ * @param devAddr I2C slave device address
+ * @param regAddr First register address to write to
+ * @param length Number of bytes to write
+ * @param data Buffer to copy new data from
+ * @return Status of operation (TRUE = success)
+ */
+uint8 I2Cdev_writeBytes(uint8 devAddr, uint8 regAddr, uint8 length, uint8* data) {
+
+#ifdef I2CDEV_SERIAL_DEBUG
+	i2cdev_debug_depth++; int z; for(z=0;z> 8, SEND_CONTINUE);
+
+		// Send LSB
+		if (count == length - 1) {
+			// Stop
+			WriteI2C(data[count] & 0xFF, SEND_STOP);
+		} else {
+			// continue
+			WriteI2C(data[count] & 0xFF, SEND_CONTINUE);
+		}
+	}
+
+	// Stop I2C
+	StopI2C();
+
+
+#ifdef I2CDEV_SERIAL_DEBUG
+	i2cdev_debug_depth--;
+#endif
+
+	return TRUE;
+}
+
+/** Write single word to a 16-bit device register.
+ * @param devAddr I2C slave device address
+ * @param regAddr Register address to write to
+ * @param data New word value to write
+ * @return Status of operation (TRUE = success)
+ */
+uint8 I2Cdev_writeWord(uint8 devAddr, uint8 regAddr, uint16 data) {
+
+#ifdef I2CDEV_SERIAL_DEBUG
+	i2cdev_debug_depth++; int z; for(z=0;z
+// 11/28/2014 by Marton Sebok 
+// 24/06/2015 by Grégoire Surrel 
+//
+// Changelog:
+//     2014-11-28 - ported to PIC18 peripheral library from Arduino code
+
+/* ============================================
+I2Cdev device library code is placed under the MIT license
+Copyright (c) 2013 Jeff Rowberg
+Copyright (c) 2014 Marton Sebok
+Copyright (c) 2015 Grégoire Surrel
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+===============================================
+ */
+
+#ifndef _I2CDEV_H_
+#define _I2CDEV_H_
+
+#include 
+
+int8 I2Cdev_readBit(uint8 devAddr, uint8 regAddr, uint8 bitNum, uint8 *data);
+int8 I2Cdev_readBitW(uint8 devAddr, uint8 regAddr, uint8 bitNum, uint16 *data);
+int8 I2Cdev_readBits(uint8 devAddr, uint8 regAddr, uint8 bitStart, uint8 length, uint8 *data);
+int8 I2Cdev_readBitsW(uint8 devAddr, uint8 regAddr, uint8 bitStart, uint8 length, uint16 *data);
+int8 I2Cdev_readByte(uint8 devAddr, uint8 regAddr, uint8 *data);
+int8 I2Cdev_readWord(uint8 devAddr, uint8 regAddr, uint16 *data);
+int8 I2Cdev_readBytes(uint8 devAddr, uint8 regAddr, uint8 length, uint8 *data);
+int8 I2Cdev_readWords(uint8 devAddr, uint8 regAddr, uint8 length, uint16 *data);
+
+uint8 I2Cdev_writeBit(uint8 devAddr, uint8 regAddr, uint8 bitNum, uint8 data);
+uint8 I2Cdev_writeBitW(uint8 devAddr, uint8 regAddr, uint8 bitNum, uint16 data);
+uint8 I2Cdev_writeBits(uint8 devAddr, uint8 regAddr, uint8 bitStart, uint8 length, uint8 data);
+uint8 I2Cdev_writeBitsW(uint8 devAddr, uint8 regAddr, uint8 bitStart, uint8 length, uint16 data);
+uint8 I2Cdev_writeByte(uint8 devAddr, uint8 regAddr, uint8 data);
+uint8 I2Cdev_writeWord(uint8 devAddr, uint8 regAddr, uint16 data);
+uint8 I2Cdev_writeBytes(uint8 devAddr, uint8 regAddr, uint8 length, uint8 *data);
+uint8 I2Cdev_writeWords(uint8 devAddr, uint8 regAddr, uint8 length, uint16 *data);
+
+#endif /* _I2CDEV_H_ */
diff --git a/Jennic/MPU6050/MPU6050.c b/Jennic/MPU6050/MPU6050.c
new file mode 100644
index 00000000..dea18889
--- /dev/null
+++ b/Jennic/MPU6050/MPU6050.c
@@ -0,0 +1,3422 @@
+// I2Cdev library collection - MPU6050 I2C device class
+// Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00)
+// 8/24/2011 by Jeff Rowberg 
+// 11/28/2014 by Marton Sebok 
+// 24/06/2015 by Grégoire Surrel 
+// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
+//
+// Changelog:
+//     ... - ongoing debug release
+
+// NOTE: THIS IS ONLY A PARIAL RELEASE. THIS DEVICE CLASS IS CURRENTLY UNDERGOING ACTIVE
+// DEVELOPMENT AND IS STILL MISSING SOME IMPORTANT FEATURES. PLEASE KEEP THIS IN MIND IF
+// YOU DECIDE TO USE THIS PARTICULAR CODE FOR ANYTHING.
+
+/* ============================================
+ I2Cdev device library code is placed under the MIT license
+Copyright (c) 2012 Jeff Rowberg
+Copyright (c) 2014 Marton Sebok
+Copyright (c) 2015 Grégoire Surrel
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ===============================================
+ */
+
+#if defined (__GNUC__) && defined (__AVR__)
+#include 
+#else
+#include 
+#define PROGMEM /* empty */
+#define pgm_read_byte(x) (*(x))
+#define pgm_read_word(x) (*(x))
+#define pgm_read_float(x) (*(x))
+#endif
+
+#include "MPU6050.h"
+
+#include "dbg.h"
+#include "dbg_uart.h"
+
+// Dirty dirty code!
+uint8 MPU6050_devAddr = 0;
+uint8 MPU6050_buffer[14];
+
+// Helper functions
+int8 memcmpOwn(const void *Ptr1, const void *Ptr2, size_t Count) {
+	int8 v = 0;
+	char *p1 = (char *) Ptr1;
+	char *p2 = (char *) Ptr2;
+
+	while (Count-- > 0 && v == 0) {
+		v = *(p1++) - *(p2++);
+	}
+
+	return v;
+}
+
+/** Power on and prepare for general usage.
+ * @param address I2C address
+ * @see MPU6050_DEFAULT_ADDRESS
+ * @see MPU6050_ADDRESS_AD0_LOW
+ * @see MPU6050_ADDRESS_AD0_HIGH
+ * This will activate the device and take it out of sleep mode (which must be done
+ * after start-up). This function also sets both the accelerometer and the gyroscope
+ * to their most sensitive settings, namely +/- 2g and +/- 250 degrees/sec, and sets
+ * the clock source to use the X Gyro for reference, which is slightly better than
+ * the default internal clock source.
+ */
+void MPU6050_initialize(uint8 address) {
+	DBG_vPrintf(TRACE_APP, "\tSet address\n");
+	MPU6050_devAddr = address;
+	DBG_vPrintf(TRACE_APP, "\tSet clock source to XGyro\n");
+	MPU6050_setClockSource(MPU6050_CLOCK_PLL_XGYRO);
+	DBG_vPrintf(TRACE_APP, "\tSet gyro range to 250�/s\n");
+	MPU6050_setFullScaleGyroRange(MPU6050_GYRO_FS_250);
+	DBG_vPrintf(TRACE_APP, "\tSet accel range to 2G\n");
+	MPU6050_setFullScaleAccelRange(MPU6050_ACCEL_FS_2);
+	DBG_vPrintf(TRACE_APP, "\tSet sleep disable\n");
+	MPU6050_setSleepEnabled(FALSE); // thanks to Jack Elston for pointing this one out!
+	DBG_vPrintf(TRACE_APP, "\tSet filters mode 5: Acc {10Hz | 13.8ms} Gyr {10Hz | 13.4ms} Sampling 1kHz\n");
+	MPU6050_setDLPFMode(5);
+}
+
+/** Verify the I2C connection.
+ * Make sure the device is connected and responds as expected.
+ * @return True if connection is valid, FALSE otherwise
+ */
+uint8 MPU6050_testConnection() {
+	return MPU6050_getDeviceID() == 0x34;
+}
+
+// AUX_VDDIO register (InvenSense demo code calls this RA_*G_OFFS_TC)
+
+/** Get the auxiliary I2C supply voltage level.
+ * When set to 1, the auxiliary I2C bus high logic level is VDD. When cleared to
+ * 0, the auxiliary I2C bus high logic level is VLOGIC. This does not apply to
+ * the MPU-6000, which does not have a VLOGIC pin.
+ * @return I2C supply voltage level (0=VLOGIC, 1=VDD)
+ */
+uint8 MPU6050_getAuxVDDIOLevel() {
+	I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_YG_OFFS_TC,
+			MPU6050_TC_PWR_MODE_BIT, MPU6050_buffer);
+	return MPU6050_buffer[0];
+}
+/** Set the auxiliary I2C supply voltage level.
+ * When set to 1, the auxiliary I2C bus high logic level is VDD. When cleared to
+ * 0, the auxiliary I2C bus high logic level is VLOGIC. This does not apply to
+ * the MPU-6000, which does not have a VLOGIC pin.
+ * @param level I2C supply voltage level (0=VLOGIC, 1=VDD)
+ */
+void MPU6050_setAuxVDDIOLevel(uint8 level) {
+	I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_YG_OFFS_TC,
+			MPU6050_TC_PWR_MODE_BIT, level);
+}
+
+// SMPLRT_DIV register
+
+/** Get gyroscope output rate divider.
+ * The sensor register output, FIFO output, DMP sampling, Motion detection, Zero
+ * Motion detection, and Free Fall detection are all based on the Sample Rate.
+ * The Sample Rate is generated by dividing the gyroscope output rate by
+ * SMPLRT_DIV:
+ *
+ * Sample Rate = Gyroscope Output Rate / (1 + SMPLRT_DIV)
+ *
+ * where Gyroscope Output Rate = 8kHz when the DLPF is disabled (DLPF_CFG = 0 or
+ * 7), and 1kHz when the DLPF is enabled (see Register 26).
+ *
+ * Note: The accelerometer output rate is 1kHz. This means that for a Sample
+ * Rate greater than 1kHz, the same accelerometer sample may be output to the
+ * FIFO, DMP, and sensor registers more than once.
+ *
+ * For a diagram of the gyroscope and accelerometer signal paths, see Section 8
+ * of the MPU-6000/MPU-6050 Product Specification document.
+ *
+ * @return Current sample rate
+ * @see MPU6050_RA_SMPLRT_DIV
+ */
+uint8 MPU6050_getRate() {
+	I2Cdev_readByte(MPU6050_devAddr, MPU6050_RA_SMPLRT_DIV, MPU6050_buffer);
+	return MPU6050_buffer[0];
+}
+/** Set gyroscope sample rate divider.
+ * @param rate New sample rate divider
+ * @see getRate()
+ * @see MPU6050_RA_SMPLRT_DIV
+ */
+void MPU6050_setRate(uint8 rate) {
+	I2Cdev_writeByte(MPU6050_devAddr, MPU6050_RA_SMPLRT_DIV, rate);
+}
+
+// CONFIG register
+
+/** Get external FSYNC configuration.
+ * Configures the external Frame Synchronization (FSYNC) pin sampling. An
+ * external signal connected to the FSYNC pin can be sampled by configuring
+ * EXT_SYNC_SET. Signal changes to the FSYNC pin are latched so that short
+ * strobes may be captured. The latched FSYNC signal will be sampled at the
+ * Sampling Rate, as defined in register 25. After sampling, the latch will
+ * reset to the current FSYNC signal state.
+ *
+ * The sampled value will be reported in place of the least significant bit in
+ * a sensor data register determined by the value of EXT_SYNC_SET according to
+ * the following table.
+ *
+ * 
+ * EXT_SYNC_SET | FSYNC Bit Location
+ * -------------+-------------------
+ * 0            | Input disabled
+ * 1            | TEMP_OUT_L[0]
+ * 2            | GYRO_XOUT_L[0]
+ * 3            | GYRO_YOUT_L[0]
+ * 4            | GYRO_ZOUT_L[0]
+ * 5            | ACCEL_XOUT_L[0]
+ * 6            | ACCEL_YOUT_L[0]
+ * 7            | ACCEL_ZOUT_L[0]
+ * 
+ * + * @return FSYNC configuration value + */ +uint8 MPU6050_getExternalFrameSync() { + I2Cdev_readBits(MPU6050_devAddr, MPU6050_RA_CONFIG, + MPU6050_CFG_EXT_SYNC_SET_BIT, MPU6050_CFG_EXT_SYNC_SET_LENGTH, + MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set external FSYNC configuration. + * @see getExternalFrameSync() + * @see MPU6050_RA_CONFIG + * @param sync New FSYNC configuration value + */ +void MPU6050_setExternalFrameSync(uint8 sync) { + I2Cdev_writeBits(MPU6050_devAddr, MPU6050_RA_CONFIG, + MPU6050_CFG_EXT_SYNC_SET_BIT, MPU6050_CFG_EXT_SYNC_SET_LENGTH, sync); +} +/** Get digital low-pass filter configuration. + * The DLPF_CFG parameter sets the digital low pass filter configuration. It + * also determines the internal sampling rate used by the device as shown in + * the table below. + * + * Note: The accelerometer output rate is 1kHz. This means that for a Sample + * Rate greater than 1kHz, the same accelerometer sample may be output to the + * FIFO, DMP, and sensor registers more than once. + * + *
+ *          |   ACCELEROMETER    |           GYROSCOPE
+ * DLPF_CFG | Bandwidth | Delay  | Bandwidth | Delay  | Sample Rate
+ * ---------+-----------+--------+-----------+--------+-------------
+ * 0        | 260Hz     | 0ms    | 256Hz     | 0.98ms | 8kHz
+ * 1        | 184Hz     | 2.0ms  | 188Hz     | 1.9ms  | 1kHz
+ * 2        | 94Hz      | 3.0ms  | 98Hz      | 2.8ms  | 1kHz
+ * 3        | 44Hz      | 4.9ms  | 42Hz      | 4.8ms  | 1kHz
+ * 4        | 21Hz      | 8.5ms  | 20Hz      | 8.3ms  | 1kHz
+ * 5        | 10Hz      | 13.8ms | 10Hz      | 13.4ms | 1kHz
+ * 6        | 5Hz       | 19.0ms | 5Hz       | 18.6ms | 1kHz
+ * 7        |   -- Reserved --   |   -- Reserved --   | Reserved
+ * 
+ * + * @return DLFP configuration + * @see MPU6050_RA_CONFIG + * @see MPU6050_CFG_DLPF_CFG_BIT + * @see MPU6050_CFG_DLPF_CFG_LENGTH + */ +uint8 MPU6050_getDLPFMode() { + I2Cdev_readBits(MPU6050_devAddr, MPU6050_RA_CONFIG, + MPU6050_CFG_DLPF_CFG_BIT, MPU6050_CFG_DLPF_CFG_LENGTH, + MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set digital low-pass filter configuration. + * @param mode New DLFP configuration setting + * @see getDLPFBandwidth() + * @see MPU6050_DLPF_BW_256 + * @see MPU6050_RA_CONFIG + * @see MPU6050_CFG_DLPF_CFG_BIT + * @see MPU6050_CFG_DLPF_CFG_LENGTH + */ +void MPU6050_setDLPFMode(uint8 mode) { + I2Cdev_writeBits(MPU6050_devAddr, MPU6050_RA_CONFIG, + MPU6050_CFG_DLPF_CFG_BIT, MPU6050_CFG_DLPF_CFG_LENGTH, mode); +} + +// GYRO_CONFIG register + +/** Get full-scale gyroscope range. + * The FS_SEL parameter allows setting the full-scale range of the gyro sensors, + * as described in the table below. + * + *
+ * 0 = +/- 250 degrees/sec
+ * 1 = +/- 500 degrees/sec
+ * 2 = +/- 1000 degrees/sec
+ * 3 = +/- 2000 degrees/sec
+ * 
+ * + * @return Current full-scale gyroscope range setting + * @see MPU6050_GYRO_FS_250 + * @see MPU6050_RA_GYRO_CONFIG + * @see MPU6050_GCONFIG_FS_SEL_BIT + * @see MPU6050_GCONFIG_FS_SEL_LENGTH + */ +uint8 MPU6050_getFullScaleGyroRange() { + I2Cdev_readBits(MPU6050_devAddr, MPU6050_RA_GYRO_CONFIG, + MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, + MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set full-scale gyroscope range. + * @param range New full-scale gyroscope range value + * @see getFullScaleRange() + * @see MPU6050_GYRO_FS_250 + * @see MPU6050_RA_GYRO_CONFIG + * @see MPU6050_GCONFIG_FS_SEL_BIT + * @see MPU6050_GCONFIG_FS_SEL_LENGTH + */ +void MPU6050_setFullScaleGyroRange(uint8 range) { + I2Cdev_writeBits(MPU6050_devAddr, MPU6050_RA_GYRO_CONFIG, + MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, range); +} + +// ACCEL_CONFIG register + +/** Get self-test enabled setting for accelerometer X axis. + * @return Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +uint8 MPU6050_getAccelXSelfTest() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_ACCEL_CONFIG, + MPU6050_ACONFIG_XA_ST_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Get self-test enabled setting for accelerometer X axis. + * @param enabled Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050_setAccelXSelfTest(bool enabled) { + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_ACCEL_CONFIG, + MPU6050_ACONFIG_XA_ST_BIT, enabled); +} +/** Get self-test enabled value for accelerometer Y axis. + * @return Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +uint8 MPU6050_getAccelYSelfTest() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_ACCEL_CONFIG, + MPU6050_ACONFIG_YA_ST_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Get self-test enabled value for accelerometer Y axis. + * @param enabled Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050_setAccelYSelfTest(bool enabled) { + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_ACCEL_CONFIG, + MPU6050_ACONFIG_YA_ST_BIT, enabled); +} +/** Get self-test enabled value for accelerometer Z axis. + * @return Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +uint8 MPU6050_getAccelZSelfTest() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_ACCEL_CONFIG, + MPU6050_ACONFIG_ZA_ST_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set self-test enabled value for accelerometer Z axis. + * @param enabled Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050_setAccelZSelfTest(bool enabled) { + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_ACCEL_CONFIG, + MPU6050_ACONFIG_ZA_ST_BIT, enabled); +} +/** Get full-scale accelerometer range. + * The FS_SEL parameter allows setting the full-scale range of the accelerometer + * sensors, as described in the table below. + * + *
+ * 0 = +/- 2g
+ * 1 = +/- 4g
+ * 2 = +/- 8g
+ * 3 = +/- 16g
+ * 
+ * + * @return Current full-scale accelerometer range setting + * @see MPU6050_ACCEL_FS_2 + * @see MPU6050_RA_ACCEL_CONFIG + * @see MPU6050_ACONFIG_AFS_SEL_BIT + * @see MPU6050_ACONFIG_AFS_SEL_LENGTH + */ +uint8 MPU6050_getFullScaleAccelRange() { + I2Cdev_readBits(MPU6050_devAddr, MPU6050_RA_ACCEL_CONFIG, + MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, + MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set full-scale accelerometer range. + * @param range New full-scale accelerometer range setting + * @see getFullScaleAccelRange() + */ +void MPU6050_setFullScaleAccelRange(uint8 range) { + I2Cdev_writeBits(MPU6050_devAddr, MPU6050_RA_ACCEL_CONFIG, + MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, range); +} +/** Get the high-pass filter configuration. + * The DHPF is a filter module in the path leading to motion detectors (Free + * Fall, Motion threshold, and Zero Motion). The high pass filter output is not + * available to the data registers (see Figure in Section 8 of the MPU-6000/ + * MPU-6050 Product Specification document). + * + * The high pass filter has three modes: + * + *
+ *    Reset: The filter output settles to zero within one sample. This
+ *           effectively disables the high pass filter. This mode may be toggled
+ *           to quickly settle the filter.
+ *
+ *    On:    The high pass filter will pass signals above the cut off frequency.
+ *
+ *    Hold:  When triggered, the filter holds the present sample. The filter
+ *           output will be the difference between the input sample and the held
+ *           sample.
+ * 
+ * + *
+ * ACCEL_HPF | Filter Mode | Cut-off Frequency
+ * ----------+-------------+------------------
+ * 0         | Reset       | None
+ * 1         | On          | 5Hz
+ * 2         | On          | 2.5Hz
+ * 3         | On          | 1.25Hz
+ * 4         | On          | 0.63Hz
+ * 7         | Hold        | None
+ * 
+ * + * @return Current high-pass filter configuration + * @see MPU6050_DHPF_RESET + * @see MPU6050_RA_ACCEL_CONFIG + */ +uint8 MPU6050_getDHPFMode() { + I2Cdev_readBits(MPU6050_devAddr, MPU6050_RA_ACCEL_CONFIG, + MPU6050_ACONFIG_ACCEL_HPF_BIT, MPU6050_ACONFIG_ACCEL_HPF_LENGTH, + MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set the high-pass filter configuration. + * @param bandwidth New high-pass filter configuration + * @see setDHPFMode() + * @see MPU6050_DHPF_RESET + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050_setDHPFMode(uint8 bandwidth) { + I2Cdev_writeBits(MPU6050_devAddr, MPU6050_RA_ACCEL_CONFIG, + MPU6050_ACONFIG_ACCEL_HPF_BIT, MPU6050_ACONFIG_ACCEL_HPF_LENGTH, + bandwidth); +} + +// FF_THR register + +/** Get free-fall event acceleration threshold. + * This register configures the detection threshold for Free Fall event + * detection. The unit of FF_THR is 1LSB = 2mg. Free Fall is detected when the + * absolute value of the accelerometer measurements for the three axes are each + * less than the detection threshold. This condition increments the Free Fall + * duration counter (Register 30). The Free Fall interrupt is triggered when the + * Free Fall duration counter reaches the time specified in FF_DUR. + * + * For more details on the Free Fall detection interrupt, see Section 8.2 of the + * MPU-6000/MPU-6050 Product Specification document as well as Registers 56 and + * 58 of this document. + * + * @return Current free-fall acceleration threshold value (LSB = 2mg) + * @see MPU6050_RA_FF_THR + */ +uint8 MPU6050_getFreefallDetectionThreshold() { + I2Cdev_readByte(MPU6050_devAddr, MPU6050_RA_FF_THR, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Get free-fall event acceleration threshold. + * @param threshold New free-fall acceleration threshold value (LSB = 2mg) + * @see getFreefallDetectionThreshold() + * @see MPU6050_RA_FF_THR + */ +void MPU6050_setFreefallDetectionThreshold(uint8 threshold) { + I2Cdev_writeByte(MPU6050_devAddr, MPU6050_RA_FF_THR, threshold); +} + +// FF_DUR register + +/** Get free-fall event duration threshold. + * This register configures the duration counter threshold for Free Fall event + * detection. The duration counter ticks at 1kHz, therefore FF_DUR has a unit + * of 1 LSB = 1 ms. + * + * The Free Fall duration counter increments while the absolute value of the + * accelerometer measurements are each less than the detection threshold + * (Register 29). The Free Fall interrupt is triggered when the Free Fall + * duration counter reaches the time specified in this register. + * + * For more details on the Free Fall detection interrupt, see Section 8.2 of + * the MPU-6000/MPU-6050 Product Specification document as well as Registers 56 + * and 58 of this document. + * + * @return Current free-fall duration threshold value (LSB = 1ms) + * @see MPU6050_RA_FF_DUR + */ +uint8 MPU6050_getFreefallDetectionDuration() { + I2Cdev_readByte(MPU6050_devAddr, MPU6050_RA_FF_DUR, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Get free-fall event duration threshold. + * @param duration New free-fall duration threshold value (LSB = 1ms) + * @see getFreefallDetectionDuration() + * @see MPU6050_RA_FF_DUR + */ +void MPU6050_setFreefallDetectionDuration(uint8 duration) { + I2Cdev_writeByte(MPU6050_devAddr, MPU6050_RA_FF_DUR, duration); +} + +// MOT_THR register + +/** Get motion detection event acceleration threshold. + * This register configures the detection threshold for Motion interrupt + * generation. The unit of MOT_THR is 1LSB = 2mg. Motion is detected when the + * absolute value of any of the accelerometer measurements exceeds this Motion + * detection threshold. This condition increments the Motion detection duration + * counter (Register 32). The Motion detection interrupt is triggered when the + * Motion Detection counter reaches the time count specified in MOT_DUR + * (Register 32). + * + * The Motion interrupt will indicate the axis and polarity of detected motion + * in MOT_DETECT_STATUS (Register 97). + * + * For more details on the Motion detection interrupt, see Section 8.3 of the + * MPU-6000/MPU-6050 Product Specification document as well as Registers 56 and + * 58 of this document. + * + * @return Current motion detection acceleration threshold value (LSB = 2mg) + * @see MPU6050_RA_MOT_THR + */ +uint8 MPU6050_getMotionDetectionThreshold() { + I2Cdev_readByte(MPU6050_devAddr, MPU6050_RA_MOT_THR, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set free-fall event acceleration threshold. + * @param threshold New motion detection acceleration threshold value (LSB = 2mg) + * @see getMotionDetectionThreshold() + * @see MPU6050_RA_MOT_THR + */ +void MPU6050_setMotionDetectionThreshold(uint8 threshold) { + I2Cdev_writeByte(MPU6050_devAddr, MPU6050_RA_MOT_THR, threshold); +} + +// MOT_DUR register + +/** Get motion detection event duration threshold. + * This register configures the duration counter threshold for Motion interrupt + * generation. The duration counter ticks at 1 kHz, therefore MOT_DUR has a unit + * of 1LSB = 1ms. The Motion detection duration counter increments when the + * absolute value of any of the accelerometer measurements exceeds the Motion + * detection threshold (Register 31). The Motion detection interrupt is + * triggered when the Motion detection counter reaches the time count specified + * in this register. + * + * For more details on the Motion detection interrupt, see Section 8.3 of the + * MPU-6000/MPU-6050 Product Specification document. + * + * @return Current motion detection duration threshold value (LSB = 1ms) + * @see MPU6050_RA_MOT_DUR + */ +uint8 MPU6050_getMotionDetectionDuration() { + I2Cdev_readByte(MPU6050_devAddr, MPU6050_RA_MOT_DUR, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set motion detection event duration threshold. + * @param duration New motion detection duration threshold value (LSB = 1ms) + * @see getMotionDetectionDuration() + * @see MPU6050_RA_MOT_DUR + */ +void MPU6050_setMotionDetectionDuration(uint8 duration) { + I2Cdev_writeByte(MPU6050_devAddr, MPU6050_RA_MOT_DUR, duration); +} + +// ZRMOT_THR register + +/** Get zero motion detection event acceleration threshold. + * This register configures the detection threshold for Zero Motion interrupt + * generation. The unit of ZRMOT_THR is 1LSB = 2mg. Zero Motion is detected when + * the absolute value of the accelerometer measurements for the 3 axes are each + * less than the detection threshold. This condition increments the Zero Motion + * duration counter (Register 34). The Zero Motion interrupt is triggered when + * the Zero Motion duration counter reaches the time count specified in + * ZRMOT_DUR (Register 34). + * + * Unlike Free Fall or Motion detection, Zero Motion detection triggers an + * interrupt both when Zero Motion is first detected and when Zero Motion is no + * longer detected. + * + * When a zero motion event is detected, a Zero Motion Status will be indicated + * in the MOT_DETECT_STATUS register (Register 97). When a motion-to-zero-motion + * condition is detected, the status bit is set to 1. When a zero-motion-to- + * motion condition is detected, the status bit is set to 0. + * + * For more details on the Zero Motion detection interrupt, see Section 8.4 of + * the MPU-6000/MPU-6050 Product Specification document as well as Registers 56 + * and 58 of this document. + * + * @return Current zero motion detection acceleration threshold value (LSB = 2mg) + * @see MPU6050_RA_ZRMOT_THR + */ +uint8 MPU6050_getZeroMotionDetectionThreshold() { + I2Cdev_readByte(MPU6050_devAddr, MPU6050_RA_ZRMOT_THR, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set zero motion detection event acceleration threshold. + * @param threshold New zero motion detection acceleration threshold value (LSB = 2mg) + * @see getZeroMotionDetectionThreshold() + * @see MPU6050_RA_ZRMOT_THR + */ +void MPU6050_setZeroMotionDetectionThreshold(uint8 threshold) { + I2Cdev_writeByte(MPU6050_devAddr, MPU6050_RA_ZRMOT_THR, threshold); +} + +// ZRMOT_DUR register + +/** Get zero motion detection event duration threshold. + * This register configures the duration counter threshold for Zero Motion + * interrupt generation. The duration counter ticks at 16 Hz, therefore + * ZRMOT_DUR has a unit of 1 LSB = 64 ms. The Zero Motion duration counter + * increments while the absolute value of the accelerometer measurements are + * each less than the detection threshold (Register 33). The Zero Motion + * interrupt is triggered when the Zero Motion duration counter reaches the time + * count specified in this register. + * + * For more details on the Zero Motion detection interrupt, see Section 8.4 of + * the MPU-6000/MPU-6050 Product Specification document, as well as Registers 56 + * and 58 of this document. + * + * @return Current zero motion detection duration threshold value (LSB = 64ms) + * @see MPU6050_RA_ZRMOT_DUR + */ +uint8 MPU6050_getZeroMotionDetectionDuration() { + I2Cdev_readByte(MPU6050_devAddr, MPU6050_RA_ZRMOT_DUR, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set zero motion detection event duration threshold. + * @param duration New zero motion detection duration threshold value (LSB = 1ms) + * @see getZeroMotionDetectionDuration() + * @see MPU6050_RA_ZRMOT_DUR + */ +void MPU6050_setZeroMotionDetectionDuration(uint8 duration) { + I2Cdev_writeByte(MPU6050_devAddr, MPU6050_RA_ZRMOT_DUR, duration); +} + +// FIFO_EN register + +/** Get temperature FIFO enabled value. + * When set to 1, this bit enables TEMP_OUT_H and TEMP_OUT_L (Registers 65 and + * 66) to be written into the FIFO MPU6050_buffer. + * @return Current temperature FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +uint8 MPU6050_getTempFIFOEnabled() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_FIFO_EN, + MPU6050_TEMP_FIFO_EN_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set temperature FIFO enabled value. + * @param enabled New temperature FIFO enabled value + * @see getTempFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setTempFIFOEnabled(bool enabled) { + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_FIFO_EN, + MPU6050_TEMP_FIFO_EN_BIT, enabled); +} +/** Get gyroscope X-axis FIFO enabled value. + * When set to 1, this bit enables GYRO_XOUT_H and GYRO_XOUT_L (Registers 67 and + * 68) to be written into the FIFO MPU6050_buffer. + * @return Current gyroscope X-axis FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +uint8 MPU6050_getXGyroFIFOEnabled() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_FIFO_EN, MPU6050_XG_FIFO_EN_BIT, + MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set gyroscope X-axis FIFO enabled value. + * @param enabled New gyroscope X-axis FIFO enabled value + * @see getXGyroFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setXGyroFIFOEnabled(bool enabled) { + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_FIFO_EN, + MPU6050_XG_FIFO_EN_BIT, enabled); +} +/** Get gyroscope Y-axis FIFO enabled value. + * When set to 1, this bit enables GYRO_YOUT_H and GYRO_YOUT_L (Registers 69 and + * 70) to be written into the FIFO MPU6050_buffer. + * @return Current gyroscope Y-axis FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +uint8 MPU6050_getYGyroFIFOEnabled() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_FIFO_EN, MPU6050_YG_FIFO_EN_BIT, + MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set gyroscope Y-axis FIFO enabled value. + * @param enabled New gyroscope Y-axis FIFO enabled value + * @see getYGyroFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setYGyroFIFOEnabled(bool enabled) { + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_FIFO_EN, + MPU6050_YG_FIFO_EN_BIT, enabled); +} +/** Get gyroscope Z-axis FIFO enabled value. + * When set to 1, this bit enables GYRO_ZOUT_H and GYRO_ZOUT_L (Registers 71 and + * 72) to be written into the FIFO MPU6050_buffer. + * @return Current gyroscope Z-axis FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +uint8 MPU6050_getZGyroFIFOEnabled() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_FIFO_EN, MPU6050_ZG_FIFO_EN_BIT, + MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set gyroscope Z-axis FIFO enabled value. + * @param enabled New gyroscope Z-axis FIFO enabled value + * @see getZGyroFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setZGyroFIFOEnabled(bool enabled) { + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_FIFO_EN, + MPU6050_ZG_FIFO_EN_BIT, enabled); +} +/** Get accelerometer FIFO enabled value. + * When set to 1, this bit enables ACCEL_XOUT_H, ACCEL_XOUT_L, ACCEL_YOUT_H, + * ACCEL_YOUT_L, ACCEL_ZOUT_H, and ACCEL_ZOUT_L (Registers 59 to 64) to be + * written into the FIFO MPU6050_buffer. + * @return Current accelerometer FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +uint8 MPU6050_getAccelFIFOEnabled() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_FIFO_EN, + MPU6050_ACCEL_FIFO_EN_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set accelerometer FIFO enabled value. + * @param enabled New accelerometer FIFO enabled value + * @see getAccelFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setAccelFIFOEnabled(bool enabled) { + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_FIFO_EN, + MPU6050_ACCEL_FIFO_EN_BIT, enabled); +} +/** Get Slave 2 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 2 to be written into the FIFO MPU6050_buffer. + * @return Current Slave 2 FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +uint8 MPU6050_getSlave2FIFOEnabled() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_FIFO_EN, + MPU6050_SLV2_FIFO_EN_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set Slave 2 FIFO enabled value. + * @param enabled New Slave 2 FIFO enabled value + * @see getSlave2FIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setSlave2FIFOEnabled(bool enabled) { + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_FIFO_EN, + MPU6050_SLV2_FIFO_EN_BIT, enabled); +} +/** Get Slave 1 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 1 to be written into the FIFO MPU6050_buffer. + * @return Current Slave 1 FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +uint8 MPU6050_getSlave1FIFOEnabled() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_FIFO_EN, + MPU6050_SLV1_FIFO_EN_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set Slave 1 FIFO enabled value. + * @param enabled New Slave 1 FIFO enabled value + * @see getSlave1FIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setSlave1FIFOEnabled(bool enabled) { + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_FIFO_EN, + MPU6050_SLV1_FIFO_EN_BIT, enabled); +} +/** Get Slave 0 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 0 to be written into the FIFO MPU6050_buffer. + * @return Current Slave 0 FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +uint8 MPU6050_getSlave0FIFOEnabled() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_FIFO_EN, + MPU6050_SLV0_FIFO_EN_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set Slave 0 FIFO enabled value. + * @param enabled New Slave 0 FIFO enabled value + * @see getSlave0FIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setSlave0FIFOEnabled(bool enabled) { + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_FIFO_EN, + MPU6050_SLV0_FIFO_EN_BIT, enabled); +} + +// I2C_MST_CTRL register + +/** Get multi-master enabled value. + * Multi-master capability allows multiple I2C masters to operate on the same + * bus. In circuits where multi-master capability is required, set MULT_MST_EN + * to 1. This will increase current drawn by approximately 30uA. + * + * In circuits where multi-master capability is required, the state of the I2C + * bus must always be monitored by each separate I2C Master. Before an I2C + * Master can assume arbitration of the bus, it must first confirm that no other + * I2C Master has arbitration of the bus. When MULT_MST_EN is set to 1, the + * MPU-60X0's bus arbitration detection logic is turned on, enabling it to + * detect when the bus is available. + * + * @return Current multi-master enabled value + * @see MPU6050_RA_I2C_MST_CTRL + */ +uint8 MPU6050_getMultiMasterEnabled() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_I2C_MST_CTRL, + MPU6050_MULT_MST_EN_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set multi-master enabled value. + * @param enabled New multi-master enabled value + * @see getMultiMasterEnabled() + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050_setMultiMasterEnabled(bool enabled) { + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_I2C_MST_CTRL, + MPU6050_MULT_MST_EN_BIT, enabled); +} +/** Get wait-for-external-sensor-data enabled value. + * When the WAIT_FOR_ES bit is set to 1, the Data Ready interrupt will be + * delayed until External Sensor data from the Slave Devices are loaded into the + * EXT_SENS_DATA registers. This is used to ensure that both the internal sensor + * data (i.e. from gyro and accel) and external sensor data have been loaded to + * their respective data registers (i.e. the data is synced) when the Data Ready + * interrupt is triggered. + * + * @return Current wait-for-external-sensor-data enabled value + * @see MPU6050_RA_I2C_MST_CTRL + */ +uint8 MPU6050_getWaitForExternalSensorEnabled() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_I2C_MST_CTRL, + MPU6050_WAIT_FOR_ES_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set wait-for-external-sensor-data enabled value. + * @param enabled New wait-for-external-sensor-data enabled value + * @see getWaitForExternalSensorEnabled() + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050_setWaitForExternalSensorEnabled(bool enabled) { + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_I2C_MST_CTRL, + MPU6050_WAIT_FOR_ES_BIT, enabled); +} +/** Get Slave 3 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 3 to be written into the FIFO MPU6050_buffer. + * @return Current Slave 3 FIFO enabled value + * @see MPU6050_RA_MST_CTRL + */ +uint8 MPU6050_getSlave3FIFOEnabled() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_I2C_MST_CTRL, + MPU6050_SLV_3_FIFO_EN_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set Slave 3 FIFO enabled value. + * @param enabled New Slave 3 FIFO enabled value + * @see getSlave3FIFOEnabled() + * @see MPU6050_RA_MST_CTRL + */ +void MPU6050_setSlave3FIFOEnabled(bool enabled) { + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_I2C_MST_CTRL, + MPU6050_SLV_3_FIFO_EN_BIT, enabled); +} +/** Get slave read/write transition enabled value. + * The I2C_MST_P_NSR bit configures the I2C Master's transition from one slave + * read to the next slave read. If the bit equals 0, there will be a restart + * between reads. If the bit equals 1, there will be a stop followed by a start + * of the following read. When a write transaction follows a read transaction, + * the stop followed by a start of the successive write will be always used. + * + * @return Current slave read/write transition enabled value + * @see MPU6050_RA_I2C_MST_CTRL + */ +uint8 MPU6050_getSlaveReadWriteTransitionEnabled() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_I2C_MST_CTRL, + MPU6050_I2C_MST_P_NSR_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set slave read/write transition enabled value. + * @param enabled New slave read/write transition enabled value + * @see getSlaveReadWriteTransitionEnabled() + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050_setSlaveReadWriteTransitionEnabled(bool enabled) { + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_I2C_MST_CTRL, + MPU6050_I2C_MST_P_NSR_BIT, enabled); +} +/** Get I2C master clock speed. + * I2C_MST_CLK is a 4 bit unsigned value which configures a divider on the + * MPU-60X0 internal 8MHz clock. It sets the I2C master clock speed according to + * the following table: + * + *
+ * I2C_MST_CLK | I2C Master Clock Speed | 8MHz Clock Divider
+ * ------------+------------------------+-------------------
+ * 0           | 348kHz                 | 23
+ * 1           | 333kHz                 | 24
+ * 2           | 320kHz                 | 25
+ * 3           | 308kHz                 | 26
+ * 4           | 296kHz                 | 27
+ * 5           | 286kHz                 | 28
+ * 6           | 276kHz                 | 29
+ * 7           | 267kHz                 | 30
+ * 8           | 258kHz                 | 31
+ * 9           | 500kHz                 | 16
+ * 10          | 471kHz                 | 17
+ * 11          | 444kHz                 | 18
+ * 12          | 421kHz                 | 19
+ * 13          | 400kHz                 | 20
+ * 14          | 381kHz                 | 21
+ * 15          | 364kHz                 | 22
+ * 
+ * + * @return Current I2C master clock speed + * @see MPU6050_RA_I2C_MST_CTRL + */ +uint8 MPU6050_getMasterClockSpeed() { + I2Cdev_readBits(MPU6050_devAddr, MPU6050_RA_I2C_MST_CTRL, + MPU6050_I2C_MST_CLK_BIT, MPU6050_I2C_MST_CLK_LENGTH, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set I2C master clock speed. + * @reparam speed Current I2C master clock speed + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050_setMasterClockSpeed(uint8 speed) { + I2Cdev_writeBits(MPU6050_devAddr, MPU6050_RA_I2C_MST_CTRL, + MPU6050_I2C_MST_CLK_BIT, MPU6050_I2C_MST_CLK_LENGTH, speed); +} + +// I2C_SLV* registers (Slave 0-3) + +/** Get the I2C address of the specified slave (0-3). + * Note that Bit 7 (MSB) controls read/write mode. If Bit 7 is set, it's a read + * operation, and if it is cleared, then it's a write operation. The remaining + * bits (6-0) are the 7-bit device address of the slave device. + * + * In read mode, the result of the read is placed in the lowest available + * EXT_SENS_DATA register. For further information regarding the allocation of + * read results, please refer to the EXT_SENS_DATA register description + * (Registers 73 - 96). + * + * The MPU-6050 supports a total of five slaves, but Slave 4 has unique + * characteristics, and so it has its own functions (getSlave4* and setSlave4*). + * + * I2C data transactions are performed at the Sample Rate, as defined in + * Register 25. The user is responsible for ensuring that I2C data transactions + * to and from each enabled Slave can be completed within a single period of the + * Sample Rate. + * + * The I2C slave access rate can be reduced relative to the Sample Rate. This + * reduced access rate is determined by I2C_MST_DLY (Register 52). Whether a + * slave's access rate is reduced relative to the Sample Rate is determined by + * I2C_MST_DELAY_CTRL (Register 103). + * + * The processing order for the slaves is fixed. The sequence followed for + * processing the slaves is Slave 0, Slave 1, Slave 2, Slave 3 and Slave 4. If a + * particular Slave is disabled it will be skipped. + * + * Each slave can either be accessed at the sample rate or at a reduced sample + * rate. In a case where some slaves are accessed at the Sample Rate and some + * slaves are accessed at the reduced rate, the sequence of accessing the slaves + * (Slave 0 to Slave 4) is still followed. However, the reduced rate slaves will + * be skipped if their access rate dictates that they should not be accessed + * during that particular cycle. For further information regarding the reduced + * access rate, please refer to Register 52. Whether a slave is accessed at the + * Sample Rate or at the reduced rate is determined by the Delay Enable bits in + * Register 103. + * + * @param num Slave number (0-3) + * @return Current address for specified slave + * @see MPU6050_RA_I2C_SLV0_ADDR + */ +uint8 MPU6050_getSlaveAddress(uint8 num) { + if (num > 3) + return 0; + I2Cdev_readByte(MPU6050_devAddr, MPU6050_RA_I2C_SLV0_ADDR + num * 3, + MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set the I2C address of the specified slave (0-3). + * @param num Slave number (0-3) + * @param address New address for specified slave + * @see getSlaveAddress() + * @see MPU6050_RA_I2C_SLV0_ADDR + */ +void MPU6050_setSlaveAddress(uint8 num, uint8 address) { + if (num > 3) + return; + I2Cdev_writeByte(MPU6050_devAddr, MPU6050_RA_I2C_SLV0_ADDR + num * 3, + address); +} +/** Get the active internal register for the specified slave (0-3). + * Read/write operations for this slave will be done to whatever internal + * register address is stored in this MPU register. + * + * The MPU-6050 supports a total of five slaves, but Slave 4 has unique + * characteristics, and so it has its own functions. + * + * @param num Slave number (0-3) + * @return Current active register for specified slave + * @see MPU6050_RA_I2C_SLV0_REG + */ +uint8 MPU6050_getSlaveRegister(uint8 num) { + if (num > 3) + return 0; + I2Cdev_readByte(MPU6050_devAddr, MPU6050_RA_I2C_SLV0_REG + num * 3, + MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set the active internal register for the specified slave (0-3). + * @param num Slave number (0-3) + * @param reg New active register for specified slave + * @see getSlaveRegister() + * @see MPU6050_RA_I2C_SLV0_REG + */ +void MPU6050_setSlaveRegister(uint8 num, uint8 reg) { + if (num > 3) + return; + I2Cdev_writeByte(MPU6050_devAddr, MPU6050_RA_I2C_SLV0_REG + num * 3, reg); +} +/** Get the enabled value for the specified slave (0-3). + * When set to 1, this bit enables Slave 0 for data transfer operations. When + * cleared to 0, this bit disables Slave 0 from data transfer operations. + * @param num Slave number (0-3) + * @return Current enabled value for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +uint8 MPU6050_getSlaveEnabled(uint8 num) { + if (num > 3) + return 0; + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_I2C_SLV0_CTRL + num * 3, + MPU6050_I2C_SLV_EN_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set the enabled value for the specified slave (0-3). + * @param num Slave number (0-3) + * @param enabled New enabled value for specified slave + * @see getSlaveEnabled() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050_setSlaveEnabled(uint8 num, bool enabled) { + if (num > 3) + return; + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_I2C_SLV0_CTRL + num * 3, + MPU6050_I2C_SLV_EN_BIT, enabled); +} +/** Get word pair byte-swapping enabled for the specified slave (0-3). + * When set to 1, this bit enables byte swapping. When byte swapping is enabled, + * the high and low bytes of a word pair are swapped. Please refer to + * I2C_SLV0_GRP for the pairing convention of the word pairs. When cleared to 0, + * bytes transferred to and from Slave 0 will be written to EXT_SENS_DATA + * registers in the order they were transferred. + * + * @param num Slave number (0-3) + * @return Current word pair byte-swapping enabled value for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +uint8 MPU6050_getSlaveWordByteSwap(uint8 num) { + if (num > 3) + return 0; + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_I2C_SLV0_CTRL + num * 3, + MPU6050_I2C_SLV_BYTE_SW_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set word pair byte-swapping enabled for the specified slave (0-3). + * @param num Slave number (0-3) + * @param enabled New word pair byte-swapping enabled value for specified slave + * @see getSlaveWordByteSwap() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050_setSlaveWordByteSwap(uint8 num, bool enabled) { + if (num > 3) + return; + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_I2C_SLV0_CTRL + num * 3, + MPU6050_I2C_SLV_BYTE_SW_BIT, enabled); +} +/** Get write mode for the specified slave (0-3). + * When set to 1, the transaction will read or write data only. When cleared to + * 0, the transaction will write a register address prior to reading or writing + * data. This should equal 0 when specifying the register address within the + * Slave device to/from which the ensuing data transaction will take place. + * + * @param num Slave number (0-3) + * @return Current write mode for specified slave (0 = register address + data, 1 = data only) + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +uint8 MPU6050_getSlaveWriteMode(uint8 num) { + if (num > 3) + return 0; + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_I2C_SLV0_CTRL + num * 3, + MPU6050_I2C_SLV_REG_DIS_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set write mode for the specified slave (0-3). + * @param num Slave number (0-3) + * @param mode New write mode for specified slave (0 = register address + data, 1 = data only) + * @see getSlaveWriteMode() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050_setSlaveWriteMode(uint8 num, bool mode) { + if (num > 3) + return; + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_I2C_SLV0_CTRL + num * 3, + MPU6050_I2C_SLV_REG_DIS_BIT, mode); +} +/** Get word pair grouping order offset for the specified slave (0-3). + * This sets specifies the grouping order of word pairs received from registers. + * When cleared to 0, bytes from register addresses 0 and 1, 2 and 3, etc (even, + * then odd register addresses) are paired to form a word. When set to 1, bytes + * from register addresses are paired 1 and 2, 3 and 4, etc. (odd, then even + * register addresses) are paired to form a word. + * + * @param num Slave number (0-3) + * @return Current word pair grouping order offset for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +uint8 MPU6050_getSlaveWordGroupOffset(uint8 num) { + if (num > 3) + return 0; + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_I2C_SLV0_CTRL + num * 3, + MPU6050_I2C_SLV_GRP_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set word pair grouping order offset for the specified slave (0-3). + * @param num Slave number (0-3) + * @param enabled New word pair grouping order offset for specified slave + * @see getSlaveWordGroupOffset() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050_setSlaveWordGroupOffset(uint8 num, bool enabled) { + if (num > 3) + return; + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_I2C_SLV0_CTRL + num * 3, + MPU6050_I2C_SLV_GRP_BIT, enabled); +} +/** Get number of bytes to read for the specified slave (0-3). + * Specifies the number of bytes transferred to and from Slave 0. Clearing this + * bit to 0 is equivalent to disabling the register by writing 0 to I2C_SLV0_EN. + * @param num Slave number (0-3) + * @return Number of bytes to read for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +uint8 MPU6050_getSlaveDataLength(uint8 num) { + if (num > 3) + return 0; + I2Cdev_readBits(MPU6050_devAddr, MPU6050_RA_I2C_SLV0_CTRL + num * 3, + MPU6050_I2C_SLV_LEN_BIT, MPU6050_I2C_SLV_LEN_LENGTH, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set number of bytes to read for the specified slave (0-3). + * @param num Slave number (0-3) + * @param length Number of bytes to read for specified slave + * @see getSlaveDataLength() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050_setSlaveDataLength(uint8 num, uint8 length) { + if (num > 3) + return; + I2Cdev_writeBits(MPU6050_devAddr, MPU6050_RA_I2C_SLV0_CTRL + num * 3, + MPU6050_I2C_SLV_LEN_BIT, MPU6050_I2C_SLV_LEN_LENGTH, length); +} + +// I2C_SLV* registers (Slave 4) + +/** Get the I2C address of Slave 4. + * Note that Bit 7 (MSB) controls read/write mode. If Bit 7 is set, it's a read + * operation, and if it is cleared, then it's a write operation. The remaining + * bits (6-0) are the 7-bit device address of the slave device. + * + * @return Current address for Slave 4 + * @see getSlaveAddress() + * @see MPU6050_RA_I2C_SLV4_ADDR + */ +uint8 MPU6050_getSlave4Address() { + I2Cdev_readByte(MPU6050_devAddr, MPU6050_RA_I2C_SLV4_ADDR, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set the I2C address of Slave 4. + * @param address New address for Slave 4 + * @see getSlave4Address() + * @see MPU6050_RA_I2C_SLV4_ADDR + */ +void MPU6050_setSlave4Address(uint8 address) { + I2Cdev_writeByte(MPU6050_devAddr, MPU6050_RA_I2C_SLV4_ADDR, address); +} +/** Get the active internal register for the Slave 4. + * Read/write operations for this slave will be done to whatever internal + * register address is stored in this MPU register. + * + * @return Current active register for Slave 4 + * @see MPU6050_RA_I2C_SLV4_REG + */ +uint8 MPU6050_getSlave4Register() { + I2Cdev_readByte(MPU6050_devAddr, MPU6050_RA_I2C_SLV4_REG, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set the active internal register for Slave 4. + * @param reg New active register for Slave 4 + * @see getSlave4Register() + * @see MPU6050_RA_I2C_SLV4_REG + */ +void MPU6050_setSlave4Register(uint8 reg) { + I2Cdev_writeByte(MPU6050_devAddr, MPU6050_RA_I2C_SLV4_REG, reg); +} +/** Set new byte to write to Slave 4. + * This register stores the data to be written into the Slave 4. If I2C_SLV4_RW + * is set 1 (set to read), this register has no effect. + * @param data New byte to write to Slave 4 + * @see MPU6050_RA_I2C_SLV4_DO + */ +void MPU6050_setSlave4OutputByte(uint8 data) { + I2Cdev_writeByte(MPU6050_devAddr, MPU6050_RA_I2C_SLV4_DO, data); +} +/** Get the enabled value for the Slave 4. + * When set to 1, this bit enables Slave 4 for data transfer operations. When + * cleared to 0, this bit disables Slave 4 from data transfer operations. + * @return Current enabled value for Slave 4 + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +uint8 MPU6050_getSlave4Enabled() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_I2C_SLV4_CTRL, + MPU6050_I2C_SLV4_EN_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set the enabled value for Slave 4. + * @param enabled New enabled value for Slave 4 + * @see getSlave4Enabled() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050_setSlave4Enabled(bool enabled) { + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_I2C_SLV4_CTRL, + MPU6050_I2C_SLV4_EN_BIT, enabled); +} +/** Get the enabled value for Slave 4 transaction interrupts. + * When set to 1, this bit enables the generation of an interrupt signal upon + * completion of a Slave 4 transaction. When cleared to 0, this bit disables the + * generation of an interrupt signal upon completion of a Slave 4 transaction. + * The interrupt status can be observed in Register 54. + * + * @return Current enabled value for Slave 4 transaction interrupts. + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +uint8 MPU6050_getSlave4InterruptEnabled() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_I2C_SLV4_CTRL, + MPU6050_I2C_SLV4_INT_EN_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set the enabled value for Slave 4 transaction interrupts. + * @param enabled New enabled value for Slave 4 transaction interrupts. + * @see getSlave4InterruptEnabled() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050_setSlave4InterruptEnabled(bool enabled) { + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_I2C_SLV4_CTRL, + MPU6050_I2C_SLV4_INT_EN_BIT, enabled); +} +/** Get write mode for Slave 4. + * When set to 1, the transaction will read or write data only. When cleared to + * 0, the transaction will write a register address prior to reading or writing + * data. This should equal 0 when specifying the register address within the + * Slave device to/from which the ensuing data transaction will take place. + * + * @return Current write mode for Slave 4 (0 = register address + data, 1 = data only) + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +uint8 MPU6050_getSlave4WriteMode() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_I2C_SLV4_CTRL, + MPU6050_I2C_SLV4_REG_DIS_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set write mode for the Slave 4. + * @param mode New write mode for Slave 4 (0 = register address + data, 1 = data only) + * @see getSlave4WriteMode() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050_setSlave4WriteMode(bool mode) { + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_I2C_SLV4_CTRL, + MPU6050_I2C_SLV4_REG_DIS_BIT, mode); +} +/** Get Slave 4 master delay value. + * This configures the reduced access rate of I2C slaves relative to the Sample + * Rate. When a slave's access rate is decreased relative to the Sample Rate, + * the slave is accessed every: + * + * 1 / (1 + I2C_MST_DLY) samples + * + * This base Sample Rate in turn is determined by SMPLRT_DIV (register 25) and + * DLPF_CFG (register 26). Whether a slave's access rate is reduced relative to + * the Sample Rate is determined by I2C_MST_DELAY_CTRL (register 103). For + * further information regarding the Sample Rate, please refer to register 25. + * + * @return Current Slave 4 master delay value + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +uint8 MPU6050_getSlave4MasterDelay() { + I2Cdev_readBits(MPU6050_devAddr, MPU6050_RA_I2C_SLV4_CTRL, + MPU6050_I2C_SLV4_MST_DLY_BIT, MPU6050_I2C_SLV4_MST_DLY_LENGTH, + MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set Slave 4 master delay value. + * @param delay New Slave 4 master delay value + * @see getSlave4MasterDelay() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050_setSlave4MasterDelay(uint8 delay) { + I2Cdev_writeBits(MPU6050_devAddr, MPU6050_RA_I2C_SLV4_CTRL, + MPU6050_I2C_SLV4_MST_DLY_BIT, MPU6050_I2C_SLV4_MST_DLY_LENGTH, + delay); +} +/** Get last available byte read from Slave 4. + * This register stores the data read from Slave 4. This field is populated + * after a read transaction. + * @return Last available byte read from to Slave 4 + * @see MPU6050_RA_I2C_SLV4_DI + */ +uint8 MPU6050_getSlate4InputByte() { + I2Cdev_readByte(MPU6050_devAddr, MPU6050_RA_I2C_SLV4_DI, MPU6050_buffer); + return MPU6050_buffer[0]; +} + +// I2C_MST_STATUS register + +/** Get FSYNC interrupt status. + * This bit reflects the status of the FSYNC interrupt from an external device + * into the MPU-60X0. This is used as a way to pass an external interrupt + * through the MPU-60X0 to the host application processor. When set to 1, this + * bit will cause an interrupt if FSYNC_INT_EN is asserted in INT_PIN_CFG + * (Register 55). + * @return FSYNC interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +uint8 MPU6050_getPassthroughStatus() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_I2C_MST_STATUS, + MPU6050_MST_PASS_THROUGH_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Get Slave 4 transaction done status. + * Automatically sets to 1 when a Slave 4 transaction has completed. This + * triggers an interrupt if the I2C_MST_INT_EN bit in the INT_ENABLE register + * (Register 56) is asserted and if the SLV_4_DONE_INT bit is asserted in the + * I2C_SLV4_CTRL register (Register 52). + * @return Slave 4 transaction done status + * @see MPU6050_RA_I2C_MST_STATUS + */ +uint8 MPU6050_getSlave4IsDone() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_I2C_MST_STATUS, + MPU6050_MST_I2C_SLV4_DONE_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Get master arbitration lost status. + * This bit automatically sets to 1 when the I2C Master has lost arbitration of + * the auxiliary I2C bus (an error condition). This triggers an interrupt if the + * I2C_MST_INT_EN bit in the INT_ENABLE register (Register 56) is asserted. + * @return Master arbitration lost status + * @see MPU6050_RA_I2C_MST_STATUS + */ +uint8 MPU6050_getLostArbitration() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_I2C_MST_STATUS, + MPU6050_MST_I2C_LOST_ARB_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Get Slave 4 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 4. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 4 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +uint8 MPU6050_getSlave4Nack() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_I2C_MST_STATUS, + MPU6050_MST_I2C_SLV4_NACK_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Get Slave 3 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 3. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 3 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +uint8 MPU6050_getSlave3Nack() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_I2C_MST_STATUS, + MPU6050_MST_I2C_SLV3_NACK_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Get Slave 2 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 2. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 2 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +uint8 MPU6050_getSlave2Nack() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_I2C_MST_STATUS, + MPU6050_MST_I2C_SLV2_NACK_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Get Slave 1 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 1. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 1 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +uint8 MPU6050_getSlave1Nack() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_I2C_MST_STATUS, + MPU6050_MST_I2C_SLV1_NACK_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Get Slave 0 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 0. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 0 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +uint8 MPU6050_getSlave0Nack() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_I2C_MST_STATUS, + MPU6050_MST_I2C_SLV0_NACK_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} + +// INT_PIN_CFG register + +/** Get interrupt logic level mode. + * Will be set 0 for active-high, 1 for active-low. + * @return Current interrupt mode (0=active-high, 1=active-low) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_LEVEL_BIT + */ +uint8 MPU6050_getInterruptMode() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_INT_PIN_CFG, + MPU6050_INTCFG_INT_LEVEL_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set interrupt logic level mode. + * @param mode New interrupt mode (0=active-high, 1=active-low) + * @see getInterruptMode() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_LEVEL_BIT + */ +void MPU6050_setInterruptMode(bool mode) { + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_INT_PIN_CFG, + MPU6050_INTCFG_INT_LEVEL_BIT, mode); +} +/** Get interrupt drive mode. + * Will be set 0 for push-pull, 1 for open-drain. + * @return Current interrupt drive mode (0=push-pull, 1=open-drain) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_OPEN_BIT + */ +uint8 MPU6050_getInterruptDrive() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_INT_PIN_CFG, + MPU6050_INTCFG_INT_OPEN_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set interrupt drive mode. + * @param drive New interrupt drive mode (0=push-pull, 1=open-drain) + * @see getInterruptDrive() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_OPEN_BIT + */ +void MPU6050_setInterruptDrive(bool drive) { + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_INT_PIN_CFG, + MPU6050_INTCFG_INT_OPEN_BIT, drive); +} +/** Get interrupt latch mode. + * Will be set 0 for 50us-pulse, 1 for latch-until-int-cleared. + * @return Current latch mode (0=50us-pulse, 1=latch-until-int-cleared) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_LATCH_INT_EN_BIT + */ +uint8 MPU6050_getInterruptLatch() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_INT_PIN_CFG, + MPU6050_INTCFG_LATCH_INT_EN_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set interrupt latch mode. + * @param latch New latch mode (0=50us-pulse, 1=latch-until-int-cleared) + * @see getInterruptLatch() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_LATCH_INT_EN_BIT + */ +void MPU6050_setInterruptLatch(bool latch) { + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_INT_PIN_CFG, + MPU6050_INTCFG_LATCH_INT_EN_BIT, latch); +} +/** Get interrupt latch clear mode. + * Will be set 0 for status-read-only, 1 for any-register-read. + * @return Current latch clear mode (0=status-read-only, 1=any-register-read) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_RD_CLEAR_BIT + */ +uint8 MPU6050_getInterruptLatchClear() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_INT_PIN_CFG, + MPU6050_INTCFG_INT_RD_CLEAR_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set interrupt latch clear mode. + * @param clear New latch clear mode (0=status-read-only, 1=any-register-read) + * @see getInterruptLatchClear() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_RD_CLEAR_BIT + */ +void MPU6050_setInterruptLatchClear(bool clear) { + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_INT_PIN_CFG, + MPU6050_INTCFG_INT_RD_CLEAR_BIT, clear); +} +/** Get FSYNC interrupt logic level mode. + * @return Current FSYNC interrupt mode (0=active-high, 1=active-low) + * @see getFSyncInterruptMode() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT + */ +uint8 MPU6050_getFSyncInterruptLevel() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_INT_PIN_CFG, + MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set FSYNC interrupt logic level mode. + * @param mode New FSYNC interrupt mode (0=active-high, 1=active-low) + * @see getFSyncInterruptMode() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT + */ +void MPU6050_setFSyncInterruptLevel(bool level) { + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_INT_PIN_CFG, + MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT, level); +} +/** Get FSYNC pin interrupt enabled setting. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled setting + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_EN_BIT + */ +uint8 MPU6050_getFSyncInterruptEnabled() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_INT_PIN_CFG, + MPU6050_INTCFG_FSYNC_INT_EN_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set FSYNC pin interrupt enabled setting. + * @param enabled New FSYNC pin interrupt enabled setting + * @see getFSyncInterruptEnabled() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_EN_BIT + */ +void MPU6050_setFSyncInterruptEnabled(bool enabled) { + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_INT_PIN_CFG, + MPU6050_INTCFG_FSYNC_INT_EN_BIT, enabled); +} +/** Get I2C bypass enabled status. + * When this bit is equal to 1 and I2C_MST_EN (Register 106 bit[5]) is equal to + * 0, the host application processor will be able to directly access the + * auxiliary I2C bus of the MPU-60X0. When this bit is equal to 0, the host + * application processor will not be able to directly access the auxiliary I2C + * bus of the MPU-60X0 regardless of the state of I2C_MST_EN (Register 106 + * bit[5]). + * @return Current I2C bypass enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_I2C_BYPASS_EN_BIT + */ +uint8 MPU6050_getI2CBypassEnabled() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_INT_PIN_CFG, + MPU6050_INTCFG_I2C_BYPASS_EN_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set I2C bypass enabled status. + * When this bit is equal to 1 and I2C_MST_EN (Register 106 bit[5]) is equal to + * 0, the host application processor will be able to directly access the + * auxiliary I2C bus of the MPU-60X0. When this bit is equal to 0, the host + * application processor will not be able to directly access the auxiliary I2C + * bus of the MPU-60X0 regardless of the state of I2C_MST_EN (Register 106 + * bit[5]). + * @param enabled New I2C bypass enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_I2C_BYPASS_EN_BIT + */ +void MPU6050_setI2CBypassEnabled(bool enabled) { + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_INT_PIN_CFG, + MPU6050_INTCFG_I2C_BYPASS_EN_BIT, enabled); +} +/** Get reference clock output enabled status. + * When this bit is equal to 1, a reference clock output is provided at the + * CLKOUT pin. When this bit is equal to 0, the clock output is disabled. For + * further information regarding CLKOUT, please refer to the MPU-60X0 Product + * Specification document. + * @return Current reference clock output enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_CLKOUT_EN_BIT + */ +uint8 MPU6050_getClockOutputEnabled() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_INT_PIN_CFG, + MPU6050_INTCFG_CLKOUT_EN_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set reference clock output enabled status. + * When this bit is equal to 1, a reference clock output is provided at the + * CLKOUT pin. When this bit is equal to 0, the clock output is disabled. For + * further information regarding CLKOUT, please refer to the MPU-60X0 Product + * Specification document. + * @param enabled New reference clock output enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_CLKOUT_EN_BIT + */ +void MPU6050_setClockOutputEnabled(bool enabled) { + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_INT_PIN_CFG, + MPU6050_INTCFG_CLKOUT_EN_BIT, enabled); +} + +// INT_ENABLE register + +/** Get full interrupt enabled status. + * Full register byte for all interrupts, for quick reading. Each bit will be + * set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +uint8 MPU6050_getIntEnabled() { + I2Cdev_readByte(MPU6050_devAddr, MPU6050_RA_INT_ENABLE, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set full interrupt enabled status. + * Full register byte for all interrupts, for quick reading. Each bit should be + * set 0 for disabled, 1 for enabled. + * @param enabled New interrupt enabled status + * @see getIntFreefallEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +void MPU6050_setIntEnabled(uint8 enabled) { + I2Cdev_writeByte(MPU6050_devAddr, MPU6050_RA_INT_ENABLE, enabled); +} +/** Get Free Fall interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +uint8 MPU6050_getIntFreefallEnabled() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_INT_ENABLE, + MPU6050_INTERRUPT_FF_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set Free Fall interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntFreefallEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +void MPU6050_setIntFreefallEnabled(bool enabled) { + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_INT_ENABLE, + MPU6050_INTERRUPT_FF_BIT, enabled); +} +/** Get Motion Detection interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_MOT_BIT + **/ +uint8 MPU6050_getIntMotionEnabled() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_INT_ENABLE, + MPU6050_INTERRUPT_MOT_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set Motion Detection interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntMotionEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_MOT_BIT + **/ +void MPU6050_setIntMotionEnabled(bool enabled) { + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_INT_ENABLE, + MPU6050_INTERRUPT_MOT_BIT, enabled); +} +/** Get Zero Motion Detection interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_ZMOT_BIT + **/ +uint8 MPU6050_getIntZeroMotionEnabled() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_INT_ENABLE, + MPU6050_INTERRUPT_ZMOT_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set Zero Motion Detection interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntZeroMotionEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_ZMOT_BIT + **/ +void MPU6050_setIntZeroMotionEnabled(bool enabled) { + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_INT_ENABLE, + MPU6050_INTERRUPT_ZMOT_BIT, enabled); +} +/** Get FIFO Buffer Overflow interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT + **/ +uint8 MPU6050_getIntFIFOBufferOverflowEnabled() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_INT_ENABLE, + MPU6050_INTERRUPT_FIFO_OFLOW_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set FIFO Buffer Overflow interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntFIFOBufferOverflowEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT + **/ +void MPU6050_setIntFIFOBufferOverflowEnabled(bool enabled) { + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_INT_ENABLE, + MPU6050_INTERRUPT_FIFO_OFLOW_BIT, enabled); +} +/** Get I2C Master interrupt enabled status. + * This enables any of the I2C Master interrupt sources to generate an + * interrupt. Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT + **/ +uint8 MPU6050_getIntI2CMasterEnabled() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_INT_ENABLE, + MPU6050_INTERRUPT_I2C_MST_INT_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set I2C Master interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntI2CMasterEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT + **/ +void MPU6050_setIntI2CMasterEnabled(bool enabled) { + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_INT_ENABLE, + MPU6050_INTERRUPT_I2C_MST_INT_BIT, enabled); +} +/** Get Data Ready interrupt enabled setting. + * This event occurs each time a write operation to all of the sensor registers + * has been completed. Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_DATA_RDY_BIT + */ +uint8 MPU6050_getIntDataReadyEnabled() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_INT_ENABLE, + MPU6050_INTERRUPT_DATA_RDY_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set Data Ready interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntDataReadyEnabled() + * @see MPU6050_RA_INT_CFG + * @see MPU6050_INTERRUPT_DATA_RDY_BIT + */ +void MPU6050_setIntDataReadyEnabled(bool enabled) { + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_INT_ENABLE, + MPU6050_INTERRUPT_DATA_RDY_BIT, enabled); +} + +// INT_STATUS register + +/** Get full set of interrupt status bits. + * These bits clear to 0 after the register has been read. Very useful + * for getting multiple INT statuses, since each single bit read clears + * all of them because it has to read the whole byte. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + */ +uint8 MPU6050_getIntStatus() { + I2Cdev_readByte(MPU6050_devAddr, MPU6050_RA_INT_STATUS, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Get Free Fall interrupt status. + * This bit automatically sets to 1 when a Free Fall interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_FF_BIT + */ +uint8 MPU6050_getIntFreefallStatus() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_INT_STATUS, + MPU6050_INTERRUPT_FF_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Get Motion Detection interrupt status. + * This bit automatically sets to 1 when a Motion Detection interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_MOT_BIT + */ +uint8 MPU6050_getIntMotionStatus() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_INT_STATUS, + MPU6050_INTERRUPT_MOT_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Get Zero Motion Detection interrupt status. + * This bit automatically sets to 1 when a Zero Motion Detection interrupt has + * been generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_ZMOT_BIT + */ +uint8 MPU6050_getIntZeroMotionStatus() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_INT_STATUS, + MPU6050_INTERRUPT_ZMOT_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Get FIFO Buffer Overflow interrupt status. + * This bit automatically sets to 1 when a Free Fall interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT + */ +uint8 MPU6050_getIntFIFOBufferOverflowStatus() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_INT_STATUS, + MPU6050_INTERRUPT_FIFO_OFLOW_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Get I2C Master interrupt status. + * This bit automatically sets to 1 when an I2C Master interrupt has been + * generated. For a list of I2C Master interrupts, please refer to Register 54. + * The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT + */ +uint8 MPU6050_getIntI2CMasterStatus() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_INT_STATUS, + MPU6050_INTERRUPT_I2C_MST_INT_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Get Data Ready interrupt status. + * This bit automatically sets to 1 when a Data Ready interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_DATA_RDY_BIT + */ +uint8 MPU6050_getIntDataReadyStatus() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_INT_STATUS, + MPU6050_INTERRUPT_DATA_RDY_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} + +// ACCEL_*OUT_* registers + +/** Get raw 9-axis motion sensor readings (accel/gyro/compass). + * FUNCTION NOT FULLY IMPLEMENTED YET. + * @param ax 16-bit signed integer container for accelerometer X-axis value + * @param ay 16-bit signed integer container for accelerometer Y-axis value + * @param az 16-bit signed integer container for accelerometer Z-axis value + * @param gx 16-bit signed integer container for gyroscope X-axis value + * @param gy 16-bit signed integer container for gyroscope Y-axis value + * @param gz 16-bit signed integer container for gyroscope Z-axis value + * @param mx 16-bit signed integer container for magnetometer X-axis value + * @param my 16-bit signed integer container for magnetometer Y-axis value + * @param mz 16-bit signed integer container for magnetometer Z-axis value + * @see getMotion6() + * @see getAcceleration() + * @see getRotation() + * @see MPU6050_RA_ACCEL_XOUT_H + */ +void MPU6050_getMotion9(int16* ax, int16* ay, int16* az, int16* gx, int16* gy, + int16* gz, int16* mx, int16* my, int16* mz) { + MPU6050_getMotion6(ax, ay, az, gx, gy, gz); + // TODO: magnetometer integration +} +/** Get raw 6-axis motion sensor readings (accel/gyro). + * Retrieves all currently available motion sensor values. + * @param ax 16-bit signed integer container for accelerometer X-axis value + * @param ay 16-bit signed integer container for accelerometer Y-axis value + * @param az 16-bit signed integer container for accelerometer Z-axis value + * @param gx 16-bit signed integer container for gyroscope X-axis value + * @param gy 16-bit signed integer container for gyroscope Y-axis value + * @param gz 16-bit signed integer container for gyroscope Z-axis value + * @see getAcceleration() + * @see getRotation() + * @see MPU6050_RA_ACCEL_XOUT_H + */ +void MPU6050_getMotion6(int16* ax, int16* ay, int16* az, int16* gx, int16* gy, + int16* gz) { + I2Cdev_readBytes(MPU6050_devAddr, MPU6050_RA_ACCEL_XOUT_H, 14, + MPU6050_buffer); + *ax = (((int16) MPU6050_buffer[0]) << 8) | MPU6050_buffer[1]; + *ay = (((int16) MPU6050_buffer[2]) << 8) | MPU6050_buffer[3]; + *az = (((int16) MPU6050_buffer[4]) << 8) | MPU6050_buffer[5]; + *gx = (((int16) MPU6050_buffer[8]) << 8) | MPU6050_buffer[9]; + *gy = (((int16) MPU6050_buffer[10]) << 8) | MPU6050_buffer[11]; + *gz = (((int16) MPU6050_buffer[12]) << 8) | MPU6050_buffer[13]; +} +/** Get 3-axis accelerometer readings. + * These registers store the most recent accelerometer measurements. + * Accelerometer measurements are written to these registers at the Sample Rate + * as defined in Register 25. + * + * The accelerometer measurement registers, along with the temperature + * measurement registers, gyroscope measurement registers, and external sensor + * data registers, are composed of two sets of registers: an internal register + * set and a user-facing read register set. + * + * The data within the accelerometer sensors' internal register set is always + * updated at the Sample Rate. Meanwhile, the user-facing read register set + * duplicates the internal register set's data values whenever the serial + * interface is idle. This guarantees that a burst read of sensor registers will + * read measurements from the same sampling instant. Note that if burst reads + * are not used, the user is responsible for ensuring a set of single byte reads + * correspond to a single sampling instant by checking the Data Ready interrupt. + * + * Each 16-bit accelerometer measurement has a full scale defined in ACCEL_FS + * (Register 28). For each full scale setting, the accelerometers' sensitivity + * per LSB in ACCEL_xOUT is shown in the table below: + * + *
+ * AFS_SEL | Full Scale Range | LSB Sensitivity
+ * --------+------------------+----------------
+ * 0       | +/- 2g           | 8192 LSB/mg
+ * 1       | +/- 4g           | 4096 LSB/mg
+ * 2       | +/- 8g           | 2048 LSB/mg
+ * 3       | +/- 16g          | 1024 LSB/mg
+ * 
+ * + * @param x 16-bit signed integer container for X-axis acceleration + * @param y 16-bit signed integer container for Y-axis acceleration + * @param z 16-bit signed integer container for Z-axis acceleration + * @see MPU6050_RA_GYRO_XOUT_H + */ +void MPU6050_getAcceleration(int16* x, int16* y, int16* z) { + I2Cdev_readBytes(MPU6050_devAddr, MPU6050_RA_ACCEL_XOUT_H, 6, + MPU6050_buffer); + *x = (((int16) MPU6050_buffer[0]) << 8) | MPU6050_buffer[1]; + *y = (((int16) MPU6050_buffer[2]) << 8) | MPU6050_buffer[3]; + *z = (((int16) MPU6050_buffer[4]) << 8) | MPU6050_buffer[5]; +} +/** Get X-axis accelerometer reading. + * @return X-axis acceleration measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_ACCEL_XOUT_H + */ +int16 MPU6050_getAccelerationX() { + I2Cdev_readBytes(MPU6050_devAddr, MPU6050_RA_ACCEL_XOUT_H, 2, + MPU6050_buffer); + return (((int16) MPU6050_buffer[0]) << 8) | MPU6050_buffer[1]; +} +/** Get Y-axis accelerometer reading. + * @return Y-axis acceleration measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_ACCEL_YOUT_H + */ +int16 MPU6050_getAccelerationY() { + I2Cdev_readBytes(MPU6050_devAddr, MPU6050_RA_ACCEL_YOUT_H, 2, + MPU6050_buffer); + return (((int16) MPU6050_buffer[0]) << 8) | MPU6050_buffer[1]; +} +/** Get Z-axis accelerometer reading. + * @return Z-axis acceleration measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_ACCEL_ZOUT_H + */ +int16 MPU6050_getAccelerationZ() { + I2Cdev_readBytes(MPU6050_devAddr, MPU6050_RA_ACCEL_ZOUT_H, 2, + MPU6050_buffer); + return (((int16) MPU6050_buffer[0]) << 8) | MPU6050_buffer[1]; +} + +// TEMP_OUT_* registers + +/** Get current internal temperature. + * @return Temperature reading in 16-bit 2's complement format + * @see MPU6050_RA_TEMP_OUT_H + */ +int16 MPU6050_getTemperature() { + I2Cdev_readBytes(MPU6050_devAddr, MPU6050_RA_TEMP_OUT_H, 2, MPU6050_buffer); + return (((int16) MPU6050_buffer[0]) << 8) | MPU6050_buffer[1]; +} + +// GYRO_*OUT_* registers + +/** Get 3-axis gyroscope readings. + * These gyroscope measurement registers, along with the accelerometer + * measurement registers, temperature measurement registers, and external sensor + * data registers, are composed of two sets of registers: an internal register + * set and a user-facing read register set. + * The data within the gyroscope sensors' internal register set is always + * updated at the Sample Rate. Meanwhile, the user-facing read register set + * duplicates the internal register set's data values whenever the serial + * interface is idle. This guarantees that a burst read of sensor registers will + * read measurements from the same sampling instant. Note that if burst reads + * are not used, the user is responsible for ensuring a set of single byte reads + * correspond to a single sampling instant by checking the Data Ready interrupt. + * + * Each 16-bit gyroscope measurement has a full scale defined in FS_SEL + * (Register 27). For each full scale setting, the gyroscopes' sensitivity per + * LSB in GYRO_xOUT is shown in the table below: + * + *
+ * FS_SEL | Full Scale Range   | LSB Sensitivity
+ * -------+--------------------+----------------
+ * 0      | +/- 250 degrees/s  | 131 LSB/deg/s
+ * 1      | +/- 500 degrees/s  | 65.5 LSB/deg/s
+ * 2      | +/- 1000 degrees/s | 32.8 LSB/deg/s
+ * 3      | +/- 2000 degrees/s | 16.4 LSB/deg/s
+ * 
+ * + * @param x 16-bit signed integer container for X-axis rotation + * @param y 16-bit signed integer container for Y-axis rotation + * @param z 16-bit signed integer container for Z-axis rotation + * @see getMotion6() + * @see MPU6050_RA_GYRO_XOUT_H + */ +void MPU6050_getRotation(int16* x, int16* y, int16* z) { + I2Cdev_readBytes(MPU6050_devAddr, MPU6050_RA_GYRO_XOUT_H, 6, MPU6050_buffer); + *x = (((int16) MPU6050_buffer[0]) << 8) | MPU6050_buffer[1]; + *y = (((int16) MPU6050_buffer[2]) << 8) | MPU6050_buffer[3]; + *z = (((int16) MPU6050_buffer[4]) << 8) | MPU6050_buffer[5]; +} +/** Get X-axis gyroscope reading. + * @return X-axis rotation measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_GYRO_XOUT_H + */ +int16 MPU6050_getRotationX() { + I2Cdev_readBytes(MPU6050_devAddr, MPU6050_RA_GYRO_XOUT_H, 2, MPU6050_buffer); + return (((int16) MPU6050_buffer[0]) << 8) | MPU6050_buffer[1]; +} +/** Get Y-axis gyroscope reading. + * @return Y-axis rotation measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_GYRO_YOUT_H + */ +int16 MPU6050_getRotationY() { + I2Cdev_readBytes(MPU6050_devAddr, MPU6050_RA_GYRO_YOUT_H, 2, MPU6050_buffer); + return (((int16) MPU6050_buffer[0]) << 8) | MPU6050_buffer[1]; +} +/** Get Z-axis gyroscope reading. + * @return Z-axis rotation measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_GYRO_ZOUT_H + */ +int16 MPU6050_getRotationZ() { + I2Cdev_readBytes(MPU6050_devAddr, MPU6050_RA_GYRO_ZOUT_H, 2, MPU6050_buffer); + return (((int16) MPU6050_buffer[0]) << 8) | MPU6050_buffer[1]; +} + +// EXT_SENS_DATA_* registers + +/** Read single byte from external sensor data register. + * These registers store data read from external sensors by the Slave 0, 1, 2, + * and 3 on the auxiliary I2C interface. Data read by Slave 4 is stored in + * I2C_SLV4_DI (Register 53). + * + * External sensor data is written to these registers at the Sample Rate as + * defined in Register 25. This access rate can be reduced by using the Slave + * Delay Enable registers (Register 103). + * + * External sensor data registers, along with the gyroscope measurement + * registers, accelerometer measurement registers, and temperature measurement + * registers, are composed of two sets of registers: an internal register set + * and a user-facing read register set. + * + * The data within the external sensors' internal register set is always updated + * at the Sample Rate (or the reduced access rate) whenever the serial interface + * is idle. This guarantees that a burst read of sensor registers will read + * measurements from the same sampling instant. Note that if burst reads are not + * used, the user is responsible for ensuring a set of single byte reads + * correspond to a single sampling instant by checking the Data Ready interrupt. + * + * Data is placed in these external sensor data registers according to + * I2C_SLV0_CTRL, I2C_SLV1_CTRL, I2C_SLV2_CTRL, and I2C_SLV3_CTRL (Registers 39, + * 42, 45, and 48). When more than zero bytes are read (I2C_SLVx_LEN > 0) from + * an enabled slave (I2C_SLVx_EN = 1), the slave is read at the Sample Rate (as + * defined in Register 25) or delayed rate (if specified in Register 52 and + * 103). During each Sample cycle, slave reads are performed in order of Slave + * number. If all slaves are enabled with more than zero bytes to be read, the + * order will be Slave 0, followed by Slave 1, Slave 2, and Slave 3. + * + * Each enabled slave will have EXT_SENS_DATA registers associated with it by + * number of bytes read (I2C_SLVx_LEN) in order of slave number, starting from + * EXT_SENS_DATA_00. Note that this means enabling or disabling a slave may + * change the higher numbered slaves' associated registers. Furthermore, if + * fewer total bytes are being read from the external sensors as a result of + * such a change, then the data remaining in the registers which no longer have + * an associated slave device (i.e. high numbered registers) will remain in + * these previously allocated registers unless reset. + * + * If the sum of the read lengths of all SLVx transactions exceed the number of + * available EXT_SENS_DATA registers, the excess bytes will be dropped. There + * are 24 EXT_SENS_DATA registers and hence the total read lengths between all + * the slaves cannot be greater than 24 or some bytes will be lost. + * + * Note: Slave 4's behavior is distinct from that of Slaves 0-3. For further + * information regarding the characteristics of Slave 4, please refer to + * Registers 49 to 53. + * + * EXAMPLE: + * Suppose that Slave 0 is enabled with 4 bytes to be read (I2C_SLV0_EN = 1 and + * I2C_SLV0_LEN = 4) while Slave 1 is enabled with 2 bytes to be read so that + * I2C_SLV1_EN = 1 and I2C_SLV1_LEN = 2. In such a situation, EXT_SENS_DATA _00 + * through _03 will be associated with Slave 0, while EXT_SENS_DATA _04 and 05 + * will be associated with Slave 1. If Slave 2 is enabled as well, registers + * starting from EXT_SENS_DATA_06 will be allocated to Slave 2. + * + * If Slave 2 is disabled while Slave 3 is enabled in this same situation, then + * registers starting from EXT_SENS_DATA_06 will be allocated to Slave 3 + * instead. + * + * REGISTER ALLOCATION FOR DYNAMIC DISABLE VS. NORMAL DISABLE: + * If a slave is disabled at any time, the space initially allocated to the + * slave in the EXT_SENS_DATA register, will remain associated with that slave. + * This is to avoid dynamic adjustment of the register allocation. + * + * The allocation of the EXT_SENS_DATA registers is recomputed only when (1) all + * slaves are disabled, or (2) the I2C_MST_RST bit is set (Register 106). + * + * This above is also TRUE if one of the slaves gets NACKed and stops + * functioning. + * + * @param position Starting position (0-23) + * @return Byte read from register + */ +uint8 MPU6050_getExternalSensorByte(int position) { + I2Cdev_readByte(MPU6050_devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, + MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Read word (2 bytes) from external sensor data registers. + * @param position Starting position (0-21) + * @return Word read from register + * @see getExternalSensorByte() + */ +uint16 MPU6050_getExternalSensorWord(int position) { + I2Cdev_readBytes(MPU6050_devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, + 2, MPU6050_buffer); + return (((uint16) MPU6050_buffer[0]) << 8) | MPU6050_buffer[1]; +} +/** Read double word (4 bytes) from external sensor data registers. + * @param position Starting position (0-20) + * @return Double word read from registers + * @see getExternalSensorByte() + */ +uint32 MPU6050_getExternalSensorDWord(int position) { + I2Cdev_readBytes(MPU6050_devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, + 4, MPU6050_buffer); + return (((uint32) MPU6050_buffer[0]) << 24) | (((uint32) MPU6050_buffer[1]) + << 16) | (((uint16) MPU6050_buffer[2]) << 8) | MPU6050_buffer[3]; +} + +// MOT_DETECT_STATUS register + +/** Get full motion detection status register content (all bits). + * @return Motion detection status byte + * @see MPU6050_RA_MOT_DETECT_STATUS + */ +uint8 MPU6050_getMotionStatus() { + I2Cdev_readByte(MPU6050_devAddr, MPU6050_RA_MOT_DETECT_STATUS, + MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Get X-axis negative motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_XNEG_BIT + */ +uint8 MPU6050_getXNegMotionDetected() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_MOT_DETECT_STATUS, + MPU6050_MOTION_MOT_XNEG_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Get X-axis positive motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_XPOS_BIT + */ +uint8 MPU6050_getXPosMotionDetected() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_MOT_DETECT_STATUS, + MPU6050_MOTION_MOT_XPOS_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Get Y-axis negative motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_YNEG_BIT + */ +uint8 MPU6050_getYNegMotionDetected() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_MOT_DETECT_STATUS, + MPU6050_MOTION_MOT_YNEG_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Get Y-axis positive motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_YPOS_BIT + */ +uint8 MPU6050_getYPosMotionDetected() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_MOT_DETECT_STATUS, + MPU6050_MOTION_MOT_YPOS_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Get Z-axis negative motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_ZNEG_BIT + */ +uint8 MPU6050_getZNegMotionDetected() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_MOT_DETECT_STATUS, + MPU6050_MOTION_MOT_ZNEG_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Get Z-axis positive motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_ZPOS_BIT + */ +uint8 MPU6050_getZPosMotionDetected() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_MOT_DETECT_STATUS, + MPU6050_MOTION_MOT_ZPOS_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Get zero motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_ZRMOT_BIT + */ +uint8 MPU6050_getZeroMotionDetected() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_MOT_DETECT_STATUS, + MPU6050_MOTION_MOT_ZRMOT_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} + +// I2C_SLV*_DO register + +/** Write byte to Data Output container for specified slave. + * This register holds the output data written into Slave when Slave is set to + * write mode. For further information regarding Slave control, please + * refer to Registers 37 to 39 and immediately following. + * @param num Slave number (0-3) + * @param data Byte to write + * @see MPU6050_RA_I2C_SLV0_DO + */ +void MPU6050_setSlaveOutputByte(uint8 num, uint8 data) { + if (num > 3) + return; + I2Cdev_writeByte(MPU6050_devAddr, MPU6050_RA_I2C_SLV0_DO + num, data); +} + +// I2C_MST_DELAY_CTRL register + +/** Get external data shadow delay enabled status. + * This register is used to specify the timing of external sensor data + * shadowing. When DELAY_ES_SHADOW is set to 1, shadowing of external + * sensor data is delayed until all data has been received. + * @return Current external data shadow delay enabled status. + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT + */ +uint8 MPU6050_getExternalShadowDelayEnabled() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, + MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set external data shadow delay enabled status. + * @param enabled New external data shadow delay enabled status. + * @see getExternalShadowDelayEnabled() + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT + */ +void MPU6050_setExternalShadowDelayEnabled(bool enabled) { + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, + MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT, enabled); +} +/** Get slave delay enabled status. + * When a particular slave delay is enabled, the rate of access for the that + * slave device is reduced. When a slave's access rate is decreased relative to + * the Sample Rate, the slave is accessed every: + * + * 1 / (1 + I2C_MST_DLY) Samples + * + * This base Sample Rate in turn is determined by SMPLRT_DIV (register * 25) + * and DLPF_CFG (register 26). + * + * For further information regarding I2C_MST_DLY, please refer to register 52. + * For further information regarding the Sample Rate, please refer to register 25. + * + * @param num Slave number (0-4) + * @return Current slave delay enabled status. + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT + */ +uint8 MPU6050_getSlaveDelayEnabled(uint8 num) { + // MPU6050_DELAYCTRL_I2C_SLV4_DLY_EN_BIT is 4, SLV3 is 3, etc. + if (num > 4) + return 0; + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, num, + MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set slave delay enabled status. + * @param num Slave number (0-4) + * @param enabled New slave delay enabled status. + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT + */ +void MPU6050_setSlaveDelayEnabled(uint8 num, bool enabled) { + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, num, + enabled); +} + +// SIGNAL_PATH_RESET register + +/** Reset gyroscope signal path. + * The reset will revert the signal path analog to digital converters and + * filters to their power up configurations. + * @see MPU6050_RA_SIGNAL_PATH_RESET + * @see MPU6050_PATHRESET_GYRO_RESET_BIT + */ +void MPU6050_resetGyroscopePath() { + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_SIGNAL_PATH_RESET, + MPU6050_PATHRESET_GYRO_RESET_BIT, TRUE); +} +/** Reset accelerometer signal path. + * The reset will revert the signal path analog to digital converters and + * filters to their power up configurations. + * @see MPU6050_RA_SIGNAL_PATH_RESET + * @see MPU6050_PATHRESET_ACCEL_RESET_BIT + */ +void MPU6050_resetAccelerometerPath() { + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_SIGNAL_PATH_RESET, + MPU6050_PATHRESET_ACCEL_RESET_BIT, TRUE); +} +/** Reset temperature sensor signal path. + * The reset will revert the signal path analog to digital converters and + * filters to their power up configurations. + * @see MPU6050_RA_SIGNAL_PATH_RESET + * @see MPU6050_PATHRESET_TEMP_RESET_BIT + */ +void MPU6050_resetTemperaturePath() { + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_SIGNAL_PATH_RESET, + MPU6050_PATHRESET_TEMP_RESET_BIT, TRUE); +} + +// MOT_DETECT_CTRL register + +/** Get accelerometer power-on delay. + * The accelerometer data path provides samples to the sensor registers, Motion + * detection, Zero Motion detection, and Free Fall detection modules. The + * signal path contains filters which must be flushed on wake-up with new + * samples before the detection modules begin operations. The default wake-up + * delay, of 4ms can be lengthened by up to 3ms. This additional delay is + * specified in ACCEL_ON_DELAY in units of 1 LSB = 1 ms. The user may select + * any value above zero unless instructed otherwise by InvenSense. Please refer + * to Section 8 of the MPU-6000/MPU-6050 Product Specification document for + * further information regarding the detection modules. + * @return Current accelerometer power-on delay + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_ACCEL_ON_DELAY_BIT + */ +uint8 MPU6050_getAccelerometerPowerOnDelay() { + I2Cdev_readBits(MPU6050_devAddr, MPU6050_RA_MOT_DETECT_CTRL, + MPU6050_DETECT_ACCEL_ON_DELAY_BIT, + MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set accelerometer power-on delay. + * @param delay New accelerometer power-on delay (0-3) + * @see getAccelerometerPowerOnDelay() + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_ACCEL_ON_DELAY_BIT + */ +void MPU6050_setAccelerometerPowerOnDelay(uint8 delay) { + I2Cdev_writeBits(MPU6050_devAddr, MPU6050_RA_MOT_DETECT_CTRL, + MPU6050_DETECT_ACCEL_ON_DELAY_BIT, + MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH, delay); +} +/** Get Free Fall detection counter decrement configuration. + * Detection is registered by the Free Fall detection module after accelerometer + * measurements meet their respective threshold conditions over a specified + * number of samples. When the threshold conditions are met, the corresponding + * detection counter increments by 1. The user may control the rate at which the + * detection counter decrements when the threshold condition is not met by + * configuring FF_COUNT. The decrement rate can be set according to the + * following table: + * + *
+ * FF_COUNT | Counter Decrement
+ * ---------+------------------
+ * 0        | Reset
+ * 1        | 1
+ * 2        | 2
+ * 3        | 4
+ * 
+ * + * When FF_COUNT is configured to 0 (reset), any non-qualifying sample will + * reset the counter to 0. For further information on Free Fall detection, + * please refer to Registers 29 to 32. + * + * @return Current decrement configuration + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_FF_COUNT_BIT + */ +uint8 MPU6050_getFreefallDetectionCounterDecrement() { + I2Cdev_readBits(MPU6050_devAddr, MPU6050_RA_MOT_DETECT_CTRL, + MPU6050_DETECT_FF_COUNT_BIT, MPU6050_DETECT_FF_COUNT_LENGTH, + MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set Free Fall detection counter decrement configuration. + * @param decrement New decrement configuration value + * @see getFreefallDetectionCounterDecrement() + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_FF_COUNT_BIT + */ +void MPU6050_setFreefallDetectionCounterDecrement(uint8 decrement) { + I2Cdev_writeBits(MPU6050_devAddr, MPU6050_RA_MOT_DETECT_CTRL, + MPU6050_DETECT_FF_COUNT_BIT, MPU6050_DETECT_FF_COUNT_LENGTH, + decrement); +} +/** Get Motion detection counter decrement configuration. + * Detection is registered by the Motion detection module after accelerometer + * measurements meet their respective threshold conditions over a specified + * number of samples. When the threshold conditions are met, the corresponding + * detection counter increments by 1. The user may control the rate at which the + * detection counter decrements when the threshold condition is not met by + * configuring MOT_COUNT. The decrement rate can be set according to the + * following table: + * + *
+ * MOT_COUNT | Counter Decrement
+ * ----------+------------------
+ * 0         | Reset
+ * 1         | 1
+ * 2         | 2
+ * 3         | 4
+ * 
+ * + * When MOT_COUNT is configured to 0 (reset), any non-qualifying sample will + * reset the counter to 0. For further information on Motion detection, + * please refer to Registers 29 to 32. + * + */ +uint8 MPU6050_getMotionDetectionCounterDecrement() { + I2Cdev_readBits(MPU6050_devAddr, MPU6050_RA_MOT_DETECT_CTRL, + MPU6050_DETECT_MOT_COUNT_BIT, MPU6050_DETECT_MOT_COUNT_LENGTH, + MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set Motion detection counter decrement configuration. + * @param decrement New decrement configuration value + * @see getMotionDetectionCounterDecrement() + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_MOT_COUNT_BIT + */ +void MPU6050_setMotionDetectionCounterDecrement(uint8 decrement) { + I2Cdev_writeBits(MPU6050_devAddr, MPU6050_RA_MOT_DETECT_CTRL, + MPU6050_DETECT_MOT_COUNT_BIT, MPU6050_DETECT_MOT_COUNT_LENGTH, + decrement); +} + +// USER_CTRL register + +/** Get FIFO enabled status. + * When this bit is set to 0, the FIFO MPU6050_buffer is disabled. The FIFO MPU6050_buffer + * cannot be written to or read from while disabled. The FIFO MPU6050_buffer's state + * does not change unless the MPU-60X0 is power cycled. + * @return Current FIFO enabled status + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_FIFO_EN_BIT + */ +uint8 MPU6050_getFIFOEnabled() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_USER_CTRL, + MPU6050_USERCTRL_FIFO_EN_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set FIFO enabled status. + * @param enabled New FIFO enabled status + * @see getFIFOEnabled() + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_FIFO_EN_BIT + */ +void MPU6050_setFIFOEnabled(bool enabled) { + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_USER_CTRL, + MPU6050_USERCTRL_FIFO_EN_BIT, enabled); +} +/** Get I2C Master Mode enabled status. + * When this mode is enabled, the MPU-60X0 acts as the I2C Master to the + * external sensor slave devices on the auxiliary I2C bus. When this bit is + * cleared to 0, the auxiliary I2C bus lines (AUX_DA and AUX_CL) are logically + * driven by the primary I2C bus (SDA and SCL). This is a precondition to + * enabling Bypass Mode. For further information regarding Bypass Mode, please + * refer to Register 55. + * @return Current I2C Master Mode enabled status + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_I2C_MST_EN_BIT + */ +uint8 MPU6050_getI2CMasterModeEnabled() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_USER_CTRL, + MPU6050_USERCTRL_I2C_MST_EN_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set I2C Master Mode enabled status. + * @param enabled New I2C Master Mode enabled status + * @see getI2CMasterModeEnabled() + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_I2C_MST_EN_BIT + */ +void MPU6050_setI2CMasterModeEnabled(bool enabled) { + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_USER_CTRL, + MPU6050_USERCTRL_I2C_MST_EN_BIT, enabled); +} +/** Switch from I2C to SPI mode (MPU-6000 only) + * If this is set, the primary SPI interface will be enabled in place of the + * disabled primary I2C interface. + */ +void MPU6050_switchSPIEnabled(bool enabled) { + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_USER_CTRL, + MPU6050_USERCTRL_I2C_IF_DIS_BIT, enabled); +} +/** Reset the FIFO. + * This bit resets the FIFO MPU6050_buffer when set to 1 while FIFO_EN equals 0. This + * bit automatically clears to 0 after the reset has been triggered. + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_FIFO_RESET_BIT + */ +void MPU6050_resetFIFO() { + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_USER_CTRL, + MPU6050_USERCTRL_FIFO_RESET_BIT, TRUE); +} +/** Reset the I2C Master. + * This bit resets the I2C Master when set to 1 while I2C_MST_EN equals 0. + * This bit automatically clears to 0 after the reset has been triggered. + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_I2C_MST_RESET_BIT + */ +void MPU6050_resetI2CMaster() { + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_USER_CTRL, + MPU6050_USERCTRL_I2C_MST_RESET_BIT, TRUE); +} +/** Reset all sensor registers and signal paths. + * When set to 1, this bit resets the signal paths for all sensors (gyroscopes, + * accelerometers, and temperature sensor). This operation will also clear the + * sensor registers. This bit automatically clears to 0 after the reset has been + * triggered. + * + * When resetting only the signal path (and not the sensor registers), please + * use Register 104, SIGNAL_PATH_RESET. + * + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_SIG_COND_RESET_BIT + */ +void MPU6050_resetSensors() { + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_USER_CTRL, + MPU6050_USERCTRL_SIG_COND_RESET_BIT, TRUE); +} + +// PWR_MGMT_1 register + +/** Trigger a full device reset. + * A small delay of ~50ms may be desirable after triggering a reset. + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_DEVICE_RESET_BIT + */ +void MPU6050_reset() { + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_PWR_MGMT_1, + MPU6050_PWR1_DEVICE_RESET_BIT, TRUE); +} +/** Get sleep mode status. + * Setting the SLEEP bit in the register puts the device into very low power + * sleep mode. In this mode, only the serial interface and internal registers + * remain active, allowing for a very low standby current. Clearing this bit + * puts the device back into normal mode. To save power, the individual standby + * selections for each of the gyros should be used if any gyro axis is not used + * by the application. + * @return Current sleep mode enabled status + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_SLEEP_BIT + */ +uint8 MPU6050_getSleepEnabled() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_PWR_MGMT_1, + MPU6050_PWR1_SLEEP_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set sleep mode status. + * @param enabled New sleep mode enabled status + * @see getSleepEnabled() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_SLEEP_BIT + */ +void MPU6050_setSleepEnabled(bool enabled) { + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_PWR_MGMT_1, + MPU6050_PWR1_SLEEP_BIT, enabled); +} +/** Get wake cycle enabled status. + * When this bit is set to 1 and SLEEP is disabled, the MPU-60X0 will cycle + * between sleep mode and waking up to take a single sample of data from active + * sensors at a rate determined by LP_WAKE_CTRL (register 108). + * @return Current sleep mode enabled status + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CYCLE_BIT + */ +uint8 MPU6050_getWakeCycleEnabled() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_PWR_MGMT_1, + MPU6050_PWR1_CYCLE_BIT, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set wake cycle enabled status. + * @param enabled New sleep mode enabled status + * @see getWakeCycleEnabled() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CYCLE_BIT + */ +void MPU6050_setWakeCycleEnabled(bool enabled) { + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_PWR_MGMT_1, + MPU6050_PWR1_CYCLE_BIT, enabled); +} +/** Get temperature sensor enabled status. + * Control the usage of the internal temperature sensor. + * + * Note: this register stores the *disabled* value, but for consistency with the + * rest of the code, the function is named and used with standard TRUE/FALSE + * values to indicate whether the sensor is enabled or disabled, respectively. + * + * @return Current temperature sensor enabled status + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_TEMP_DIS_BIT + */ +uint8 MPU6050_getTempSensorEnabled() { + I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_PWR_MGMT_1, + MPU6050_PWR1_TEMP_DIS_BIT, MPU6050_buffer); + return MPU6050_buffer[0] == 0; // 1 is actually disabled here +} +/** Set temperature sensor enabled status. + * Note: this register stores the *disabled* value, but for consistency with the + * rest of the code, the function is named and used with standard TRUE/FALSE + * values to indicate whether the sensor is enabled or disabled, respectively. + * + * @param enabled New temperature sensor enabled status + * @see getTempSensorEnabled() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_TEMP_DIS_BIT + */ +void MPU6050_setTempSensorEnabled(bool enabled) { + // 1 is actually disabled here + I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_PWR_MGMT_1, + MPU6050_PWR1_TEMP_DIS_BIT, !enabled); +} +/** Get clock source setting. + * @return Current clock source setting + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CLKSEL_BIT + * @see MPU6050_PWR1_CLKSEL_LENGTH + */ +uint8 MPU6050_getClockSource() { + I2Cdev_readBits(MPU6050_devAddr, MPU6050_RA_PWR_MGMT_1, + MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, MPU6050_buffer); + return MPU6050_buffer[0]; +} +/** Set clock source setting. + * An internal 8MHz oscillator, gyroscope based clock, or external sources can + * be selected as the MPU-60X0 clock source. When the internal 8 MHz oscillator + * or an external source is chosen as the clock source, the MPU-60X0 can operate + * in low power modes with the gyroscopes disabled. + * + * Upon power up, the MPU-60X0 clock source defaults to the internal oscillator. + * However, it is highly recommended that the device be configured to use one of + * the gyroscopes (or an external clock source) as the clock reference for + * improved stability. The clock source can be selected according to the following table: + * + *
+ * CLK_SEL | Clock Source
+ * --------+--------------------------------------
+ * 0       | Internal oscillator
+ * 1       | PLL with X Gyro reference
+ * 2       | PLL with Y Gyro reference
+ * 3       | PLL with Z Gyro reference
+ * 4       | PLL with external 32.768kHz reference
+ * 5       | PLL with external 19.2MHz reference
+ * 6       | Reserved
+ * 7       | Stops the clock and keeps the timing generator in reset
+ * 
+ * + * @param source New clock source setting + * @see getClockSource() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CLKSEL_BIT + * @see MPU6050_PWR1_CLKSEL_LENGTH + */ +void MPU6050_setClockSource(uint8 source) { + I2Cdev_writeBits(MPU6050_devAddr, MPU6050_RA_PWR_MGMT_1, + MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, source); +} + +// PWR_MGMT_2 register + +/** Get wake frequency in Accel-Only Low Power Mode. + * The MPU-60X0 can be put into Accerlerometer Only Low Power Mode by setting + * PWRSEL to 1 in the Power Management 1 register (Register 107). In this mode, + * the device will power off all devices except for the primary I2C interface, + * waking only the accelerometer at fixed intervals to take a single + * measurement. The frequency of wake-ups can be configured with LP_WAKE_CTRL + * as shown below: + * + *
+ * LP_WAKE_CTRL | Wake-up Frequency
+ * -------------+------------------
+ * 0            | 1.25 Hz
+ * 1            | 2.5 Hz
+ * 2            | 5 Hz
+ * 3            | 10 Hz
+ * 
+ *
+ * For further information regarding the MPU-60X0's power modes, please refer to
+ * Register 107.
+ *
+ * @return Current wake frequency
+ * @see MPU6050_RA_PWR_MGMT_2
+ */
+uint8 MPU6050_getWakeFrequency() {
+	I2Cdev_readBits(MPU6050_devAddr, MPU6050_RA_PWR_MGMT_2,
+			MPU6050_PWR2_LP_WAKE_CTRL_BIT, MPU6050_PWR2_LP_WAKE_CTRL_LENGTH,
+			MPU6050_buffer);
+	return MPU6050_buffer[0];
+}
+/** Set wake frequency in Accel-Only Low Power Mode.
+ * @param frequency New wake frequency
+ * @see MPU6050_RA_PWR_MGMT_2
+ */
+void MPU6050_setWakeFrequency(uint8 frequency) {
+	I2Cdev_writeBits(MPU6050_devAddr, MPU6050_RA_PWR_MGMT_2,
+			MPU6050_PWR2_LP_WAKE_CTRL_BIT, MPU6050_PWR2_LP_WAKE_CTRL_LENGTH,
+			frequency);
+}
+
+/** Get X-axis accelerometer standby enabled status.
+ * If enabled, the X-axis will not gather or report data (or use power).
+ * @return Current X-axis standby enabled status
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_XA_BIT
+ */
+uint8 MPU6050_getStandbyXAccelEnabled() {
+	I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_PWR_MGMT_2,
+			MPU6050_PWR2_STBY_XA_BIT, MPU6050_buffer);
+	return MPU6050_buffer[0];
+}
+/** Set X-axis accelerometer standby enabled status.
+ * @param New X-axis standby enabled status
+ * @see getStandbyXAccelEnabled()
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_XA_BIT
+ */
+void MPU6050_setStandbyXAccelEnabled(bool enabled) {
+	I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_PWR_MGMT_2,
+			MPU6050_PWR2_STBY_XA_BIT, enabled);
+}
+/** Get Y-axis accelerometer standby enabled status.
+ * If enabled, the Y-axis will not gather or report data (or use power).
+ * @return Current Y-axis standby enabled status
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_YA_BIT
+ */
+uint8 MPU6050_getStandbyYAccelEnabled() {
+	I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_PWR_MGMT_2,
+			MPU6050_PWR2_STBY_YA_BIT, MPU6050_buffer);
+	return MPU6050_buffer[0];
+}
+/** Set Y-axis accelerometer standby enabled status.
+ * @param New Y-axis standby enabled status
+ * @see getStandbyYAccelEnabled()
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_YA_BIT
+ */
+void MPU6050_setStandbyYAccelEnabled(bool enabled) {
+	I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_PWR_MGMT_2,
+			MPU6050_PWR2_STBY_YA_BIT, enabled);
+}
+/** Get Z-axis accelerometer standby enabled status.
+ * If enabled, the Z-axis will not gather or report data (or use power).
+ * @return Current Z-axis standby enabled status
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_ZA_BIT
+ */
+uint8 MPU6050_getStandbyZAccelEnabled() {
+	I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_PWR_MGMT_2,
+			MPU6050_PWR2_STBY_ZA_BIT, MPU6050_buffer);
+	return MPU6050_buffer[0];
+}
+/** Set Z-axis accelerometer standby enabled status.
+ * @param New Z-axis standby enabled status
+ * @see getStandbyZAccelEnabled()
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_ZA_BIT
+ */
+void MPU6050_setStandbyZAccelEnabled(bool enabled) {
+	I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_PWR_MGMT_2,
+			MPU6050_PWR2_STBY_ZA_BIT, enabled);
+}
+/** Get X-axis gyroscope standby enabled status.
+ * If enabled, the X-axis will not gather or report data (or use power).
+ * @return Current X-axis standby enabled status
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_XG_BIT
+ */
+uint8 MPU6050_getStandbyXGyroEnabled() {
+	I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_PWR_MGMT_2,
+			MPU6050_PWR2_STBY_XG_BIT, MPU6050_buffer);
+	return MPU6050_buffer[0];
+}
+/** Set X-axis gyroscope standby enabled status.
+ * @param New X-axis standby enabled status
+ * @see getStandbyXGyroEnabled()
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_XG_BIT
+ */
+void MPU6050_setStandbyXGyroEnabled(bool enabled) {
+	I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_PWR_MGMT_2,
+			MPU6050_PWR2_STBY_XG_BIT, enabled);
+}
+/** Get Y-axis gyroscope standby enabled status.
+ * If enabled, the Y-axis will not gather or report data (or use power).
+ * @return Current Y-axis standby enabled status
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_YG_BIT
+ */
+uint8 MPU6050_getStandbyYGyroEnabled() {
+	I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_PWR_MGMT_2,
+			MPU6050_PWR2_STBY_YG_BIT, MPU6050_buffer);
+	return MPU6050_buffer[0];
+}
+/** Set Y-axis gyroscope standby enabled status.
+ * @param New Y-axis standby enabled status
+ * @see getStandbyYGyroEnabled()
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_YG_BIT
+ */
+void MPU6050_setStandbyYGyroEnabled(bool enabled) {
+	I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_PWR_MGMT_2,
+			MPU6050_PWR2_STBY_YG_BIT, enabled);
+}
+/** Get Z-axis gyroscope standby enabled status.
+ * If enabled, the Z-axis will not gather or report data (or use power).
+ * @return Current Z-axis standby enabled status
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_ZG_BIT
+ */
+uint8 MPU6050_getStandbyZGyroEnabled() {
+	I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_PWR_MGMT_2,
+			MPU6050_PWR2_STBY_ZG_BIT, MPU6050_buffer);
+	return MPU6050_buffer[0];
+}
+/** Set Z-axis gyroscope standby enabled status.
+ * @param New Z-axis standby enabled status
+ * @see getStandbyZGyroEnabled()
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_ZG_BIT
+ */
+void MPU6050_setStandbyZGyroEnabled(bool enabled) {
+	I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_PWR_MGMT_2,
+			MPU6050_PWR2_STBY_ZG_BIT, enabled);
+}
+
+// FIFO_COUNT* registers
+
+/** Get current FIFO MPU6050_buffer size.
+ * This value indicates the number of bytes stored in the FIFO MPU6050_buffer. This
+ * number is in turn the number of bytes that can be read from the FIFO MPU6050_buffer
+ * and it is directly proportional to the number of samples available given the
+ * set of sensor data bound to be stored in the FIFO (register 35 and 36).
+ * @return Current FIFO MPU6050_buffer size
+ */
+uint16 MPU6050_getFIFOCount() {
+	I2Cdev_readBytes(MPU6050_devAddr, MPU6050_RA_FIFO_COUNTH, 2, MPU6050_buffer);
+	return (((uint16) MPU6050_buffer[0]) << 8) | MPU6050_buffer[1];
+}
+
+// FIFO_R_W register
+
+/** Get byte from FIFO MPU6050_buffer.
+ * This register is used to read and write data from the FIFO MPU6050_buffer. Data is
+ * written to the FIFO in order of register number (from lowest to highest). If
+ * all the FIFO enable flags (see below) are enabled and all External Sensor
+ * Data registers (Registers 73 to 96) are associated with a Slave device, the
+ * contents of registers 59 through 96 will be written in order at the Sample
+ * Rate.
+ *
+ * The contents of the sensor data registers (Registers 59 to 96) are written
+ * into the FIFO MPU6050_buffer when their corresponding FIFO enable flags are set to 1
+ * in FIFO_EN (Register 35). An additional flag for the sensor data registers
+ * associated with I2C Slave 3 can be found in I2C_MST_CTRL (Register 36).
+ *
+ * If the FIFO MPU6050_buffer has overflowed, the status bit FIFO_OFLOW_INT is
+ * automatically set to 1. This bit is located in INT_STATUS (Register 58).
+ * When the FIFO MPU6050_buffer has overflowed, the oldest data will be lost and new
+ * data will be written to the FIFO.
+ *
+ * If the FIFO MPU6050_buffer is empty, reading this register will return the last byte
+ * that was previously read from the FIFO until new data is available. The user
+ * should check FIFO_COUNT to ensure that the FIFO MPU6050_buffer is not read when
+ * empty.
+ *
+ * @return Byte from FIFO MPU6050_buffer
+ */
+uint8 MPU6050_getFIFOByte() {
+	I2Cdev_readByte(MPU6050_devAddr, MPU6050_RA_FIFO_R_W, MPU6050_buffer);
+	return MPU6050_buffer[0];
+}
+void MPU6050_getFIFOBytes(uint8 *data, uint8 length) {
+	I2Cdev_readBytes(MPU6050_devAddr, MPU6050_RA_FIFO_R_W, length, data);
+}
+/** Write byte to FIFO MPU6050_buffer.
+ * @see getFIFOByte()
+ * @see MPU6050_RA_FIFO_R_W
+ */
+void MPU6050_setFIFOByte(uint8 data) {
+	I2Cdev_writeByte(MPU6050_devAddr, MPU6050_RA_FIFO_R_W, data);
+}
+
+// WHO_AM_I register
+
+/** Get Device ID.
+ * This register is used to verify the identity of the device (0b110100, 0x34).
+ * @return Device ID (6 bits only! should be 0x34)
+ * @see MPU6050_RA_WHO_AM_I
+ * @see MPU6050_WHO_AM_I_BIT
+ * @see MPU6050_WHO_AM_I_LENGTH
+ */
+uint8 MPU6050_getDeviceID() {
+	I2Cdev_readBits(MPU6050_devAddr, MPU6050_RA_WHO_AM_I, MPU6050_WHO_AM_I_BIT,
+			MPU6050_WHO_AM_I_LENGTH, MPU6050_buffer);
+	return MPU6050_buffer[0];
+}
+/** Set Device ID.
+ * Write a new ID into the WHO_AM_I register (no idea why this should ever be
+ * necessary though).
+ * @param id New device ID to set.
+ * @see getDeviceID()
+ * @see MPU6050_RA_WHO_AM_I
+ * @see MPU6050_WHO_AM_I_BIT
+ * @see MPU6050_WHO_AM_I_LENGTH
+ */
+void MPU6050_setDeviceID(uint8 id) {
+	I2Cdev_writeBits(MPU6050_devAddr, MPU6050_RA_WHO_AM_I,
+			MPU6050_WHO_AM_I_BIT, MPU6050_WHO_AM_I_LENGTH, id);
+}
+
+// ======== UNDOCUMENTED/DMP REGISTERS/METHODS ========
+
+// XG_OFFS_TC register
+
+uint8 MPU6050_getOTPBankValid() {
+	I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_XG_OFFS_TC,
+			MPU6050_TC_OTP_BNK_VLD_BIT, MPU6050_buffer);
+	return MPU6050_buffer[0];
+}
+void MPU6050_setOTPBankValid(bool enabled) {
+	I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_XG_OFFS_TC,
+			MPU6050_TC_OTP_BNK_VLD_BIT, enabled);
+}
+int8 MPU6050_getXGyroOffsetTC() {
+	I2Cdev_readBits(MPU6050_devAddr, MPU6050_RA_XG_OFFS_TC,
+			MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, MPU6050_buffer);
+	return MPU6050_buffer[0];
+}
+void MPU6050_setXGyroOffsetTC(int8 offset) {
+	I2Cdev_writeBits(MPU6050_devAddr, MPU6050_RA_XG_OFFS_TC,
+			MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset);
+}
+
+// YG_OFFS_TC register
+
+int8 MPU6050_getYGyroOffsetTC() {
+	I2Cdev_readBits(MPU6050_devAddr, MPU6050_RA_YG_OFFS_TC,
+			MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, MPU6050_buffer);
+	return MPU6050_buffer[0];
+}
+void MPU6050_setYGyroOffsetTC(int8 offset) {
+	I2Cdev_writeBits(MPU6050_devAddr, MPU6050_RA_YG_OFFS_TC,
+			MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset);
+}
+
+// ZG_OFFS_TC register
+
+int8 MPU6050_getZGyroOffsetTC() {
+	I2Cdev_readBits(MPU6050_devAddr, MPU6050_RA_ZG_OFFS_TC,
+			MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, MPU6050_buffer);
+	return MPU6050_buffer[0];
+}
+void MPU6050_setZGyroOffsetTC(int8 offset) {
+	I2Cdev_writeBits(MPU6050_devAddr, MPU6050_RA_ZG_OFFS_TC,
+			MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset);
+}
+
+// X_FINE_GAIN register
+
+int8 MPU6050_getXFineGain() {
+	I2Cdev_readByte(MPU6050_devAddr, MPU6050_RA_X_FINE_GAIN, MPU6050_buffer);
+	return MPU6050_buffer[0];
+}
+void MPU6050_setXFineGain(int8 gain) {
+	I2Cdev_writeByte(MPU6050_devAddr, MPU6050_RA_X_FINE_GAIN, gain);
+}
+
+// Y_FINE_GAIN register
+
+int8 MPU6050_getYFineGain() {
+	I2Cdev_readByte(MPU6050_devAddr, MPU6050_RA_Y_FINE_GAIN, MPU6050_buffer);
+	return MPU6050_buffer[0];
+}
+void MPU6050_setYFineGain(int8 gain) {
+	I2Cdev_writeByte(MPU6050_devAddr, MPU6050_RA_Y_FINE_GAIN, gain);
+}
+
+// Z_FINE_GAIN register
+
+int8 MPU6050_getZFineGain() {
+	I2Cdev_readByte(MPU6050_devAddr, MPU6050_RA_Z_FINE_GAIN, MPU6050_buffer);
+	return MPU6050_buffer[0];
+}
+void MPU6050_setZFineGain(int8 gain) {
+	I2Cdev_writeByte(MPU6050_devAddr, MPU6050_RA_Z_FINE_GAIN, gain);
+}
+
+// XA_OFFS_* registers
+
+int16 MPU6050_getXAccelOffset() {
+	I2Cdev_readBytes(MPU6050_devAddr, MPU6050_RA_XA_OFFS_H, 2, MPU6050_buffer);
+	return (((int16) MPU6050_buffer[0]) << 8) | MPU6050_buffer[1];
+}
+void MPU6050_setXAccelOffset(int16 offset) {
+	I2Cdev_writeWord(MPU6050_devAddr, MPU6050_RA_XA_OFFS_H, offset);
+}
+
+// YA_OFFS_* register
+
+int16 MPU6050_getYAccelOffset() {
+	I2Cdev_readBytes(MPU6050_devAddr, MPU6050_RA_YA_OFFS_H, 2, MPU6050_buffer);
+	return (((int16) MPU6050_buffer[0]) << 8) | MPU6050_buffer[1];
+}
+void MPU6050_setYAccelOffset(int16 offset) {
+	I2Cdev_writeWord(MPU6050_devAddr, MPU6050_RA_YA_OFFS_H, offset);
+}
+
+// ZA_OFFS_* register
+
+int16 MPU6050_getZAccelOffset() {
+	I2Cdev_readBytes(MPU6050_devAddr, MPU6050_RA_ZA_OFFS_H, 2, MPU6050_buffer);
+	return (((int16) MPU6050_buffer[0]) << 8) | MPU6050_buffer[1];
+}
+void MPU6050_setZAccelOffset(int16 offset) {
+	I2Cdev_writeWord(MPU6050_devAddr, MPU6050_RA_ZA_OFFS_H, offset);
+}
+
+// XG_OFFS_USR* registers
+
+int16 MPU6050_getXGyroOffset() {
+	I2Cdev_readBytes(MPU6050_devAddr, MPU6050_RA_XG_OFFS_USRH, 2,
+			MPU6050_buffer);
+	return (((int16) MPU6050_buffer[0]) << 8) | MPU6050_buffer[1];
+}
+void MPU6050_setXGyroOffset(int16 offset) {
+	I2Cdev_writeWord(MPU6050_devAddr, MPU6050_RA_XG_OFFS_USRH, offset);
+}
+
+// YG_OFFS_USR* register
+
+int16 MPU6050_getYGyroOffset() {
+	I2Cdev_readBytes(MPU6050_devAddr, MPU6050_RA_YG_OFFS_USRH, 2,
+			MPU6050_buffer);
+	return (((int16) MPU6050_buffer[0]) << 8) | MPU6050_buffer[1];
+}
+void MPU6050_setYGyroOffset(int16 offset) {
+	I2Cdev_writeWord(MPU6050_devAddr, MPU6050_RA_YG_OFFS_USRH, offset);
+}
+
+// ZG_OFFS_USR* register
+
+int16 MPU6050_getZGyroOffset() {
+	I2Cdev_readBytes(MPU6050_devAddr, MPU6050_RA_ZG_OFFS_USRH, 2,
+			MPU6050_buffer);
+	return (((int16) MPU6050_buffer[0]) << 8) | MPU6050_buffer[1];
+}
+void MPU6050_setZGyroOffset(int16 offset) {
+	I2Cdev_writeWord(MPU6050_devAddr, MPU6050_RA_ZG_OFFS_USRH, offset);
+}
+
+// INT_ENABLE register (DMP functions)
+
+uint8 MPU6050_getIntPLLReadyEnabled() {
+	I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_INT_ENABLE,
+			MPU6050_INTERRUPT_PLL_RDY_INT_BIT, MPU6050_buffer);
+	return MPU6050_buffer[0];
+}
+void MPU6050_setIntPLLReadyEnabled(bool enabled) {
+	I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_INT_ENABLE,
+			MPU6050_INTERRUPT_PLL_RDY_INT_BIT, enabled);
+}
+uint8 MPU6050_getIntDMPEnabled() {
+	I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_INT_ENABLE,
+			MPU6050_INTERRUPT_DMP_INT_BIT, MPU6050_buffer);
+	return MPU6050_buffer[0];
+}
+void MPU6050_setIntDMPEnabled(bool enabled) {
+	I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_INT_ENABLE,
+			MPU6050_INTERRUPT_DMP_INT_BIT, enabled);
+}
+
+// DMP_INT_STATUS
+
+uint8 MPU6050_getDMPInt5Status() {
+	I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_DMP_INT_STATUS,
+			MPU6050_DMPINT_5_BIT, MPU6050_buffer);
+	return MPU6050_buffer[0];
+}
+uint8 MPU6050_getDMPInt4Status() {
+	I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_DMP_INT_STATUS,
+			MPU6050_DMPINT_4_BIT, MPU6050_buffer);
+	return MPU6050_buffer[0];
+}
+uint8 MPU6050_getDMPInt3Status() {
+	I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_DMP_INT_STATUS,
+			MPU6050_DMPINT_3_BIT, MPU6050_buffer);
+	return MPU6050_buffer[0];
+}
+uint8 MPU6050_getDMPInt2Status() {
+	I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_DMP_INT_STATUS,
+			MPU6050_DMPINT_2_BIT, MPU6050_buffer);
+	return MPU6050_buffer[0];
+}
+uint8 MPU6050_getDMPInt1Status() {
+	I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_DMP_INT_STATUS,
+			MPU6050_DMPINT_1_BIT, MPU6050_buffer);
+	return MPU6050_buffer[0];
+}
+uint8 MPU6050_getDMPInt0Status() {
+	I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_DMP_INT_STATUS,
+			MPU6050_DMPINT_0_BIT, MPU6050_buffer);
+	return MPU6050_buffer[0];
+}
+
+// INT_STATUS register (DMP functions)
+
+uint8 MPU6050_getIntPLLReadyStatus() {
+	I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_INT_STATUS,
+			MPU6050_INTERRUPT_PLL_RDY_INT_BIT, MPU6050_buffer);
+	return MPU6050_buffer[0];
+}
+uint8 MPU6050_getIntDMPStatus() {
+	I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_INT_STATUS,
+			MPU6050_INTERRUPT_DMP_INT_BIT, MPU6050_buffer);
+	return MPU6050_buffer[0];
+}
+
+// USER_CTRL register (DMP functions)
+
+uint8 MPU6050_getDMPEnabled() {
+	I2Cdev_readBit(MPU6050_devAddr, MPU6050_RA_USER_CTRL,
+			MPU6050_USERCTRL_DMP_EN_BIT, MPU6050_buffer);
+	return MPU6050_buffer[0];
+}
+void MPU6050_setDMPEnabled(bool enabled) {
+	I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_USER_CTRL,
+			MPU6050_USERCTRL_DMP_EN_BIT, enabled);
+}
+void MPU6050_resetDMP() {
+	I2Cdev_writeBit(MPU6050_devAddr, MPU6050_RA_USER_CTRL,
+			MPU6050_USERCTRL_DMP_RESET_BIT, TRUE);
+}
+
+// BANK_SEL register
+
+void MPU6050_setMemoryBank(uint8 bank, bool prefetchEnabled, bool userBank) {
+	bank &= 0x1F;
+	if (userBank)
+		bank |= 0x20;
+	if (prefetchEnabled)
+		bank |= 0x40;
+	I2Cdev_writeByte(MPU6050_devAddr, MPU6050_RA_BANK_SEL, bank);
+}
+
+// MEM_START_ADDR register
+
+void MPU6050_setMemoryStartAddress(uint8 address) {
+	I2Cdev_writeByte(MPU6050_devAddr, MPU6050_RA_MEM_START_ADDR, address);
+}
+
+// MEM_R_W register
+
+uint8 MPU6050_readMemoryByte() {
+	I2Cdev_readByte(MPU6050_devAddr, MPU6050_RA_MEM_R_W, MPU6050_buffer);
+	return MPU6050_buffer[0];
+}
+void MPU6050_writeMemoryByte(uint8 data) {
+	I2Cdev_writeByte(MPU6050_devAddr, MPU6050_RA_MEM_R_W, data);
+}
+void MPU6050_readMemoryBlock(uint8 *data, uint16 dataSize, uint8 bank,
+		uint8 address) {
+	MPU6050_setMemoryBank(bank, FALSE, FALSE);
+	MPU6050_setMemoryStartAddress(address);
+	uint8 chunkSize;
+	uint16 i;
+	for (i = 0; i < dataSize;) {
+		// determine correct chunk size according to bank position and data size
+		chunkSize = MPU6050_DMP_MEMORY_CHUNK_SIZE;
+
+		// make sure we don't go past the data size
+		if (i + chunkSize > dataSize)
+			chunkSize = dataSize - i;
+
+		// make sure this chunk doesn't go past the bank boundary (256 bytes)
+		if (chunkSize > 256 - address)
+			chunkSize = 256 - address;
+
+		// read the chunk of data as specified
+		I2Cdev_readBytes(MPU6050_devAddr, MPU6050_RA_MEM_R_W, chunkSize, data
+				+ i);
+
+		// increase byte index by [chunkSize]
+		i += chunkSize;
+
+		// uint8 automatically wraps to 0 at 256
+		address += chunkSize;
+
+		// if we aren't done, update bank (if necessary) and address
+		if (i < dataSize) {
+			if (address == 0)
+				bank++;
+			MPU6050_setMemoryBank(bank, FALSE, FALSE);
+			MPU6050_setMemoryStartAddress(address);
+		}
+	}
+}
+uint8 MPU6050_writeMemoryBlock(const uint8 *data, uint16 dataSize, uint8 bank,
+		uint8 address, bool verify, bool useProgMem) {
+	MPU6050_setMemoryBank(bank, FALSE, FALSE);
+	MPU6050_setMemoryStartAddress(address);
+	uint8 chunkSize;
+	uint8 verifyBuffer[MPU6050_DMP_MEMORY_CHUNK_SIZE];
+	uint8 progBuffer[MPU6050_DMP_MEMORY_CHUNK_SIZE];
+	uint16 i;
+	uint8 j;
+	for (i = 0; i < dataSize;) {
+		// determine correct chunk size according to bank position and data size
+		chunkSize = MPU6050_DMP_MEMORY_CHUNK_SIZE;
+
+		// make sure we don't go past the data size
+		if (i + chunkSize > dataSize)
+			chunkSize = dataSize - i;
+
+		// make sure this chunk doesn't go past the bank boundary (256 bytes)
+		if (chunkSize > 256 - address)
+			chunkSize = 256 - address;
+
+		if (TRUE || useProgMem) { // Else case broken, always taking the first condition to copy the data
+			// write the chunk of data as specified
+			for (j = 0; j < chunkSize; j++)
+				progBuffer[j] = pgm_read_byte(data + i + j);
+		} else {
+			// write the chunk of data as specified
+			// BROKEN, let's simply copy the data as using the loop before progBuffer = (uint8 *)data + i;
+		}
+
+		I2Cdev_writeBytes(MPU6050_devAddr, MPU6050_RA_MEM_R_W, chunkSize,
+				progBuffer);
+
+		// verify data if needed
+		if (verify && verifyBuffer) {
+			MPU6050_setMemoryBank(bank, FALSE, FALSE);
+			MPU6050_setMemoryStartAddress(address);
+			I2Cdev_readBytes(MPU6050_devAddr, MPU6050_RA_MEM_R_W, chunkSize,
+					verifyBuffer);
+			if (memcmpOwn(progBuffer, verifyBuffer, chunkSize) != 0) {
+				/*Serial.print("Block write verification error, bank ");
+				 Serial.print(bank, DEC);
+				 Serial.print(", address ");
+				 Serial.print(address, DEC);
+				 Serial.print("!\nExpected:");
+				 for (j = 0; j < chunkSize; j++) {
+				 Serial.print(" 0x");
+				 if (progBuffer[j] < 16) Serial.print("0");
+				 Serial.print(progBuffer[j], HEX);
+				 }
+				 Serial.print("\nReceived:");
+				 for (uint8 j = 0; j < chunkSize; j++) {
+				 Serial.print(" 0x");
+				 if (verifyBuffer[i + j] < 16) Serial.print("0");
+				 Serial.print(verifyBuffer[i + j], HEX);
+				 }
+				 Serial.print("\n");*/
+				return FALSE; // uh oh.
+			}
+		}
+
+		// increase byte index by [chunkSize]
+		i += chunkSize;
+
+		// uint8 automatically wraps to 0 at 256
+		address += chunkSize;
+
+		// if we aren't done, update bank (if necessary) and address
+		if (i < dataSize) {
+			if (address == 0)
+				bank++;
+			MPU6050_setMemoryBank(bank, FALSE, FALSE);
+			MPU6050_setMemoryStartAddress(address);
+		}
+	}
+	return TRUE;
+}
+uint8 MPU6050_writeProgMemoryBlock(const uint8 *data, uint16 dataSize,
+		uint8 bank, uint8 address, bool verify) {
+	return MPU6050_writeMemoryBlock(data, dataSize, bank, address, verify, TRUE);
+}
+uint8 MPU6050_writeDMPConfigurationSet(const uint8 *data, uint16 dataSize,
+		bool useProgMem) {
+	uint8 progBuffer[8], success, special;
+	uint16 i, j;
+
+	// config set data is a long string of blocks with the following structure:
+	// [bank] [offset] [length] [byte[0], byte[1], ..., byte[length]]
+	uint8 bank, offset, length;
+	for (i = 0; i < dataSize;) {
+		if (useProgMem) {
+			bank = pgm_read_byte(data + i++);
+			offset = pgm_read_byte(data + i++);
+			length = pgm_read_byte(data + i++);
+		} else {
+			bank = data[i++];
+			offset = data[i++];
+			length = data[i++];
+		}
+
+		// write data or perform special action
+		if (length > 0) {
+			// regular block of data to write
+			/*Serial.print("Writing config block to bank ");
+			 Serial.print(bank);
+			 Serial.print(", offset ");
+			 Serial.print(offset);
+			 Serial.print(", length=");
+			 Serial.println(length);*/
+			if (TRUE || useProgMem) { // Modified condition because of broken ELSE
+				if (sizeof(progBuffer) < length) { //progBuffer = (uint8 *)realloc(progBuffer, length);
+					DBG_vPrintf(TRACE_APP,
+							"MPU error on line 'if (sizeof(progBuffer) < length) {'\r\n");
+					return FALSE;
+				}
+				for (j = 0; j < length; j++)
+					progBuffer[j] = pgm_read_byte(data + i + j);
+			} else {
+				// BROKEN line progBuffer = (uint8 *)data + i;
+			}
+			success = MPU6050_writeMemoryBlock(progBuffer, length, bank,
+					offset, TRUE, FALSE);
+			i += length;
+		} else {
+			// special instruction
+			// NOTE: this kind of behavior (what and when to do certain things)
+			// is totally undocumented. This code is in here based on observed
+			// behavior only, and exactly why (or even whether) it has to be here
+			// is anybody's guess for now.
+			if (useProgMem) {
+				special = pgm_read_byte(data + i++);
+			} else {
+				special = data[i++];
+			}
+			/*Serial.print("Special command code ");
+			 Serial.print(special, HEX);
+			 Serial.println(" found...");*/
+			if (special == 0x01) {
+				// enable DMP-related interrupts
+
+				//setIntZeroMotionEnabled(TRUE);
+				//setIntFIFOBufferOverflowEnabled(TRUE);
+				//setIntDMPEnabled(TRUE);
+				I2Cdev_writeByte(MPU6050_devAddr, MPU6050_RA_INT_ENABLE, 0x32); // single operation
+
+				success = TRUE;
+			} else {
+				// unknown special command
+				success = FALSE;
+			}
+		}
+
+		if (!success) {
+			return FALSE; // uh oh
+		}
+	}
+
+	return TRUE;
+}
+uint8 MPU6050_writeProgDMPConfigurationSet(const uint8 *data, uint16 dataSize) {
+	return MPU6050_writeDMPConfigurationSet(data, dataSize, TRUE);
+}
+
+// DMP_CFG_1 register
+
+uint8 MPU6050_getDMPConfig1() {
+	I2Cdev_readByte(MPU6050_devAddr, MPU6050_RA_DMP_CFG_1, MPU6050_buffer);
+	return MPU6050_buffer[0];
+}
+void MPU6050_setDMPConfig1(uint8 config) {
+	I2Cdev_writeByte(MPU6050_devAddr, MPU6050_RA_DMP_CFG_1, config);
+}
+
+// DMP_CFG_2 register
+
+uint8 MPU6050_getDMPConfig2() {
+	I2Cdev_readByte(MPU6050_devAddr, MPU6050_RA_DMP_CFG_2, MPU6050_buffer);
+	return MPU6050_buffer[0];
+}
+void MPU6050_setDMPConfig2(uint8 config) {
+	I2Cdev_writeByte(MPU6050_devAddr, MPU6050_RA_DMP_CFG_2, config);
+}
diff --git a/Jennic/MPU6050/MPU6050.h b/Jennic/MPU6050/MPU6050.h
new file mode 100644
index 00000000..11b65bbe
--- /dev/null
+++ b/Jennic/MPU6050/MPU6050.h
@@ -0,0 +1,982 @@
+// I2Cdev library collection - MPU6050 I2C device class
+// Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00)
+// 10/3/2011 by Jeff Rowberg 
+// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
+//
+// Changelog:
+//     ... - ongoing debug release
+
+// NOTE: THIS IS ONLY A PARIAL RELEASE. THIS DEVICE CLASS IS CURRENTLY UNDERGOING ACTIVE
+// DEVELOPMENT AND IS STILL MISSING SOME IMPORTANT FEATURES. PLEASE KEEP THIS IN MIND IF
+// YOU DECIDE TO USE THIS PARTICULAR CODE FOR ANYTHING.
+
+/* ============================================
+I2Cdev device library code is placed under the MIT license
+Copyright (c) 2012 Jeff Rowberg
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+===============================================
+ */
+
+#ifndef _MPU6050_H_
+#define _MPU6050_H_
+
+#include "I2Cdev.h"
+
+#define MPU6050_ADDRESS_AD0_LOW     0x68 // address pin low (GND), default for InvenSense evaluation board
+#define MPU6050_ADDRESS_AD0_HIGH    0x69 // address pin high (VCC)
+#define MPU6050_DEFAULT_ADDRESS     MPU6050_ADDRESS_AD0_LOW
+
+#define MPU6050_RA_XG_OFFS_TC       0x00 //[7] PWR_MODE, [6:1] XG_OFFS_TC, [0] OTP_BNK_VLD
+#define MPU6050_RA_YG_OFFS_TC       0x01 //[7] PWR_MODE, [6:1] YG_OFFS_TC, [0] OTP_BNK_VLD
+#define MPU6050_RA_ZG_OFFS_TC       0x02 //[7] PWR_MODE, [6:1] ZG_OFFS_TC, [0] OTP_BNK_VLD
+#define MPU6050_RA_X_FINE_GAIN      0x03 //[7:0] X_FINE_GAIN
+#define MPU6050_RA_Y_FINE_GAIN      0x04 //[7:0] Y_FINE_GAIN
+#define MPU6050_RA_Z_FINE_GAIN      0x05 //[7:0] Z_FINE_GAIN
+#define MPU6050_RA_XA_OFFS_H        0x06 //[15:0] XA_OFFS
+#define MPU6050_RA_XA_OFFS_L_TC     0x07
+#define MPU6050_RA_YA_OFFS_H        0x08 //[15:0] YA_OFFS
+#define MPU6050_RA_YA_OFFS_L_TC     0x09
+#define MPU6050_RA_ZA_OFFS_H        0x0A //[15:0] ZA_OFFS
+#define MPU6050_RA_ZA_OFFS_L_TC     0x0B
+#define MPU6050_RA_XG_OFFS_USRH     0x13 //[15:0] XG_OFFS_USR
+#define MPU6050_RA_XG_OFFS_USRL     0x14
+#define MPU6050_RA_YG_OFFS_USRH     0x15 //[15:0] YG_OFFS_USR
+#define MPU6050_RA_YG_OFFS_USRL     0x16
+#define MPU6050_RA_ZG_OFFS_USRH     0x17 //[15:0] ZG_OFFS_USR
+#define MPU6050_RA_ZG_OFFS_USRL     0x18
+#define MPU6050_RA_SMPLRT_DIV       0x19
+#define MPU6050_RA_CONFIG           0x1A
+#define MPU6050_RA_GYRO_CONFIG      0x1B
+#define MPU6050_RA_ACCEL_CONFIG     0x1C
+#define MPU6050_RA_FF_THR           0x1D
+#define MPU6050_RA_FF_DUR           0x1E
+#define MPU6050_RA_MOT_THR          0x1F
+#define MPU6050_RA_MOT_DUR          0x20
+#define MPU6050_RA_ZRMOT_THR        0x21
+#define MPU6050_RA_ZRMOT_DUR        0x22
+#define MPU6050_RA_FIFO_EN          0x23
+#define MPU6050_RA_I2C_MST_CTRL     0x24
+#define MPU6050_RA_I2C_SLV0_ADDR    0x25
+#define MPU6050_RA_I2C_SLV0_REG     0x26
+#define MPU6050_RA_I2C_SLV0_CTRL    0x27
+#define MPU6050_RA_I2C_SLV1_ADDR    0x28
+#define MPU6050_RA_I2C_SLV1_REG     0x29
+#define MPU6050_RA_I2C_SLV1_CTRL    0x2A
+#define MPU6050_RA_I2C_SLV2_ADDR    0x2B
+#define MPU6050_RA_I2C_SLV2_REG     0x2C
+#define MPU6050_RA_I2C_SLV2_CTRL    0x2D
+#define MPU6050_RA_I2C_SLV3_ADDR    0x2E
+#define MPU6050_RA_I2C_SLV3_REG     0x2F
+#define MPU6050_RA_I2C_SLV3_CTRL    0x30
+#define MPU6050_RA_I2C_SLV4_ADDR    0x31
+#define MPU6050_RA_I2C_SLV4_REG     0x32
+#define MPU6050_RA_I2C_SLV4_DO      0x33
+#define MPU6050_RA_I2C_SLV4_CTRL    0x34
+#define MPU6050_RA_I2C_SLV4_DI      0x35
+#define MPU6050_RA_I2C_MST_STATUS   0x36
+#define MPU6050_RA_INT_PIN_CFG      0x37
+#define MPU6050_RA_INT_ENABLE       0x38
+#define MPU6050_RA_DMP_INT_STATUS   0x39
+#define MPU6050_RA_INT_STATUS       0x3A
+#define MPU6050_RA_ACCEL_XOUT_H     0x3B
+#define MPU6050_RA_ACCEL_XOUT_L     0x3C
+#define MPU6050_RA_ACCEL_YOUT_H     0x3D
+#define MPU6050_RA_ACCEL_YOUT_L     0x3E
+#define MPU6050_RA_ACCEL_ZOUT_H     0x3F
+#define MPU6050_RA_ACCEL_ZOUT_L     0x40
+#define MPU6050_RA_TEMP_OUT_H       0x41
+#define MPU6050_RA_TEMP_OUT_L       0x42
+#define MPU6050_RA_GYRO_XOUT_H      0x43
+#define MPU6050_RA_GYRO_XOUT_L      0x44
+#define MPU6050_RA_GYRO_YOUT_H      0x45
+#define MPU6050_RA_GYRO_YOUT_L      0x46
+#define MPU6050_RA_GYRO_ZOUT_H      0x47
+#define MPU6050_RA_GYRO_ZOUT_L      0x48
+#define MPU6050_RA_EXT_SENS_DATA_00 0x49
+#define MPU6050_RA_EXT_SENS_DATA_01 0x4A
+#define MPU6050_RA_EXT_SENS_DATA_02 0x4B
+#define MPU6050_RA_EXT_SENS_DATA_03 0x4C
+#define MPU6050_RA_EXT_SENS_DATA_04 0x4D
+#define MPU6050_RA_EXT_SENS_DATA_05 0x4E
+#define MPU6050_RA_EXT_SENS_DATA_06 0x4F
+#define MPU6050_RA_EXT_SENS_DATA_07 0x50
+#define MPU6050_RA_EXT_SENS_DATA_08 0x51
+#define MPU6050_RA_EXT_SENS_DATA_09 0x52
+#define MPU6050_RA_EXT_SENS_DATA_10 0x53
+#define MPU6050_RA_EXT_SENS_DATA_11 0x54
+#define MPU6050_RA_EXT_SENS_DATA_12 0x55
+#define MPU6050_RA_EXT_SENS_DATA_13 0x56
+#define MPU6050_RA_EXT_SENS_DATA_14 0x57
+#define MPU6050_RA_EXT_SENS_DATA_15 0x58
+#define MPU6050_RA_EXT_SENS_DATA_16 0x59
+#define MPU6050_RA_EXT_SENS_DATA_17 0x5A
+#define MPU6050_RA_EXT_SENS_DATA_18 0x5B
+#define MPU6050_RA_EXT_SENS_DATA_19 0x5C
+#define MPU6050_RA_EXT_SENS_DATA_20 0x5D
+#define MPU6050_RA_EXT_SENS_DATA_21 0x5E
+#define MPU6050_RA_EXT_SENS_DATA_22 0x5F
+#define MPU6050_RA_EXT_SENS_DATA_23 0x60
+#define MPU6050_RA_MOT_DETECT_STATUS    0x61
+#define MPU6050_RA_I2C_SLV0_DO      0x63
+#define MPU6050_RA_I2C_SLV1_DO      0x64
+#define MPU6050_RA_I2C_SLV2_DO      0x65
+#define MPU6050_RA_I2C_SLV3_DO      0x66
+#define MPU6050_RA_I2C_MST_DELAY_CTRL   0x67
+#define MPU6050_RA_SIGNAL_PATH_RESET    0x68
+#define MPU6050_RA_MOT_DETECT_CTRL      0x69
+#define MPU6050_RA_USER_CTRL        0x6A
+#define MPU6050_RA_PWR_MGMT_1       0x6B
+#define MPU6050_RA_PWR_MGMT_2       0x6C
+#define MPU6050_RA_BANK_SEL         0x6D
+#define MPU6050_RA_MEM_START_ADDR   0x6E
+#define MPU6050_RA_MEM_R_W          0x6F
+#define MPU6050_RA_DMP_CFG_1        0x70
+#define MPU6050_RA_DMP_CFG_2        0x71
+#define MPU6050_RA_FIFO_COUNTH      0x72
+#define MPU6050_RA_FIFO_COUNTL      0x73
+#define MPU6050_RA_FIFO_R_W         0x74
+#define MPU6050_RA_WHO_AM_I         0x75
+
+#define MPU6050_TC_PWR_MODE_BIT     7
+#define MPU6050_TC_OFFSET_BIT       6
+#define MPU6050_TC_OFFSET_LENGTH    6
+#define MPU6050_TC_OTP_BNK_VLD_BIT  0
+
+#define MPU6050_VDDIO_LEVEL_VLOGIC  0
+#define MPU6050_VDDIO_LEVEL_VDD     1
+
+#define MPU6050_CFG_EXT_SYNC_SET_BIT    5
+#define MPU6050_CFG_EXT_SYNC_SET_LENGTH 3
+#define MPU6050_CFG_DLPF_CFG_BIT    2
+#define MPU6050_CFG_DLPF_CFG_LENGTH 3
+
+#define MPU6050_EXT_SYNC_DISABLED       0x0
+#define MPU6050_EXT_SYNC_TEMP_OUT_L     0x1
+#define MPU6050_EXT_SYNC_GYRO_XOUT_L    0x2
+#define MPU6050_EXT_SYNC_GYRO_YOUT_L    0x3
+#define MPU6050_EXT_SYNC_GYRO_ZOUT_L    0x4
+#define MPU6050_EXT_SYNC_ACCEL_XOUT_L   0x5
+#define MPU6050_EXT_SYNC_ACCEL_YOUT_L   0x6
+#define MPU6050_EXT_SYNC_ACCEL_ZOUT_L   0x7
+
+#define MPU6050_DLPF_BW_256         0x00
+#define MPU6050_DLPF_BW_188         0x01
+#define MPU6050_DLPF_BW_98          0x02
+#define MPU6050_DLPF_BW_42          0x03
+#define MPU6050_DLPF_BW_20          0x04
+#define MPU6050_DLPF_BW_10          0x05
+#define MPU6050_DLPF_BW_5           0x06
+
+#define MPU6050_GCONFIG_FS_SEL_BIT      4
+#define MPU6050_GCONFIG_FS_SEL_LENGTH   2
+
+#define MPU6050_GYRO_FS_250         0x00
+#define MPU6050_GYRO_FS_500         0x01
+#define MPU6050_GYRO_FS_1000        0x02
+#define MPU6050_GYRO_FS_2000        0x03
+
+#define MPU6050_ACONFIG_XA_ST_BIT           7
+#define MPU6050_ACONFIG_YA_ST_BIT           6
+#define MPU6050_ACONFIG_ZA_ST_BIT           5
+#define MPU6050_ACONFIG_AFS_SEL_BIT         4
+#define MPU6050_ACONFIG_AFS_SEL_LENGTH      2
+#define MPU6050_ACONFIG_ACCEL_HPF_BIT       2
+#define MPU6050_ACONFIG_ACCEL_HPF_LENGTH    3
+
+#define MPU6050_ACCEL_FS_2          0x00
+#define MPU6050_ACCEL_FS_4          0x01
+#define MPU6050_ACCEL_FS_8          0x02
+#define MPU6050_ACCEL_FS_16         0x03
+
+#define MPU6050_DHPF_RESET          0x00
+#define MPU6050_DHPF_5              0x01
+#define MPU6050_DHPF_2P5            0x02
+#define MPU6050_DHPF_1P25           0x03
+#define MPU6050_DHPF_0P63           0x04
+#define MPU6050_DHPF_HOLD           0x07
+
+#define MPU6050_TEMP_FIFO_EN_BIT    7
+#define MPU6050_XG_FIFO_EN_BIT      6
+#define MPU6050_YG_FIFO_EN_BIT      5
+#define MPU6050_ZG_FIFO_EN_BIT      4
+#define MPU6050_ACCEL_FIFO_EN_BIT   3
+#define MPU6050_SLV2_FIFO_EN_BIT    2
+#define MPU6050_SLV1_FIFO_EN_BIT    1
+#define MPU6050_SLV0_FIFO_EN_BIT    0
+
+#define MPU6050_MULT_MST_EN_BIT     7
+#define MPU6050_WAIT_FOR_ES_BIT     6
+#define MPU6050_SLV_3_FIFO_EN_BIT   5
+#define MPU6050_I2C_MST_P_NSR_BIT   4
+#define MPU6050_I2C_MST_CLK_BIT     3
+#define MPU6050_I2C_MST_CLK_LENGTH  4
+
+#define MPU6050_CLOCK_DIV_348       0x0
+#define MPU6050_CLOCK_DIV_333       0x1
+#define MPU6050_CLOCK_DIV_320       0x2
+#define MPU6050_CLOCK_DIV_308       0x3
+#define MPU6050_CLOCK_DIV_296       0x4
+#define MPU6050_CLOCK_DIV_286       0x5
+#define MPU6050_CLOCK_DIV_276       0x6
+#define MPU6050_CLOCK_DIV_267       0x7
+#define MPU6050_CLOCK_DIV_258       0x8
+#define MPU6050_CLOCK_DIV_500       0x9
+#define MPU6050_CLOCK_DIV_471       0xA
+#define MPU6050_CLOCK_DIV_444       0xB
+#define MPU6050_CLOCK_DIV_421       0xC
+#define MPU6050_CLOCK_DIV_400       0xD
+#define MPU6050_CLOCK_DIV_381       0xE
+#define MPU6050_CLOCK_DIV_364       0xF
+
+#define MPU6050_I2C_SLV_RW_BIT      7
+#define MPU6050_I2C_SLV_ADDR_BIT    6
+#define MPU6050_I2C_SLV_ADDR_LENGTH 7
+#define MPU6050_I2C_SLV_EN_BIT      7
+#define MPU6050_I2C_SLV_BYTE_SW_BIT 6
+#define MPU6050_I2C_SLV_REG_DIS_BIT 5
+#define MPU6050_I2C_SLV_GRP_BIT     4
+#define MPU6050_I2C_SLV_LEN_BIT     3
+#define MPU6050_I2C_SLV_LEN_LENGTH  4
+
+#define MPU6050_I2C_SLV4_RW_BIT         7
+#define MPU6050_I2C_SLV4_ADDR_BIT       6
+#define MPU6050_I2C_SLV4_ADDR_LENGTH    7
+#define MPU6050_I2C_SLV4_EN_BIT         7
+#define MPU6050_I2C_SLV4_INT_EN_BIT     6
+#define MPU6050_I2C_SLV4_REG_DIS_BIT    5
+#define MPU6050_I2C_SLV4_MST_DLY_BIT    4
+#define MPU6050_I2C_SLV4_MST_DLY_LENGTH 5
+
+#define MPU6050_MST_PASS_THROUGH_BIT    7
+#define MPU6050_MST_I2C_SLV4_DONE_BIT   6
+#define MPU6050_MST_I2C_LOST_ARB_BIT    5
+#define MPU6050_MST_I2C_SLV4_NACK_BIT   4
+#define MPU6050_MST_I2C_SLV3_NACK_BIT   3
+#define MPU6050_MST_I2C_SLV2_NACK_BIT   2
+#define MPU6050_MST_I2C_SLV1_NACK_BIT   1
+#define MPU6050_MST_I2C_SLV0_NACK_BIT   0
+
+#define MPU6050_INTCFG_INT_LEVEL_BIT        7
+#define MPU6050_INTCFG_INT_OPEN_BIT         6
+#define MPU6050_INTCFG_LATCH_INT_EN_BIT     5
+#define MPU6050_INTCFG_INT_RD_CLEAR_BIT     4
+#define MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT  3
+#define MPU6050_INTCFG_FSYNC_INT_EN_BIT     2
+#define MPU6050_INTCFG_I2C_BYPASS_EN_BIT    1
+#define MPU6050_INTCFG_CLKOUT_EN_BIT        0
+
+#define MPU6050_INTMODE_ACTIVEHIGH  0x00
+#define MPU6050_INTMODE_ACTIVELOW   0x01
+
+#define MPU6050_INTDRV_PUSHPULL     0x00
+#define MPU6050_INTDRV_OPENDRAIN    0x01
+
+#define MPU6050_INTLATCH_50USPULSE  0x00
+#define MPU6050_INTLATCH_WAITCLEAR  0x01
+
+#define MPU6050_INTCLEAR_STATUSREAD 0x00
+#define MPU6050_INTCLEAR_ANYREAD    0x01
+
+#define MPU6050_INTERRUPT_FF_BIT            7
+#define MPU6050_INTERRUPT_MOT_BIT           6
+#define MPU6050_INTERRUPT_ZMOT_BIT          5
+#define MPU6050_INTERRUPT_FIFO_OFLOW_BIT    4
+#define MPU6050_INTERRUPT_I2C_MST_INT_BIT   3
+#define MPU6050_INTERRUPT_PLL_RDY_INT_BIT   2
+#define MPU6050_INTERRUPT_DMP_INT_BIT       1
+#define MPU6050_INTERRUPT_DATA_RDY_BIT      0
+
+// TODO: figure out what these actually do
+// UMPL source code is not very obivous
+#define MPU6050_DMPINT_5_BIT            5
+#define MPU6050_DMPINT_4_BIT            4
+#define MPU6050_DMPINT_3_BIT            3
+#define MPU6050_DMPINT_2_BIT            2
+#define MPU6050_DMPINT_1_BIT            1
+#define MPU6050_DMPINT_0_BIT            0
+
+#define MPU6050_MOTION_MOT_XNEG_BIT     7
+#define MPU6050_MOTION_MOT_XPOS_BIT     6
+#define MPU6050_MOTION_MOT_YNEG_BIT     5
+#define MPU6050_MOTION_MOT_YPOS_BIT     4
+#define MPU6050_MOTION_MOT_ZNEG_BIT     3
+#define MPU6050_MOTION_MOT_ZPOS_BIT     2
+#define MPU6050_MOTION_MOT_ZRMOT_BIT    0
+
+#define MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT   7
+#define MPU6050_DELAYCTRL_I2C_SLV4_DLY_EN_BIT   4
+#define MPU6050_DELAYCTRL_I2C_SLV3_DLY_EN_BIT   3
+#define MPU6050_DELAYCTRL_I2C_SLV2_DLY_EN_BIT   2
+#define MPU6050_DELAYCTRL_I2C_SLV1_DLY_EN_BIT   1
+#define MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT   0
+
+#define MPU6050_PATHRESET_GYRO_RESET_BIT    2
+#define MPU6050_PATHRESET_ACCEL_RESET_BIT   1
+#define MPU6050_PATHRESET_TEMP_RESET_BIT    0
+
+#define MPU6050_DETECT_ACCEL_ON_DELAY_BIT       5
+#define MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH    2
+#define MPU6050_DETECT_FF_COUNT_BIT             3
+#define MPU6050_DETECT_FF_COUNT_LENGTH          2
+#define MPU6050_DETECT_MOT_COUNT_BIT            1
+#define MPU6050_DETECT_MOT_COUNT_LENGTH         2
+
+#define MPU6050_DETECT_DECREMENT_RESET  0x0
+#define MPU6050_DETECT_DECREMENT_1      0x1
+#define MPU6050_DETECT_DECREMENT_2      0x2
+#define MPU6050_DETECT_DECREMENT_4      0x3
+
+#define MPU6050_USERCTRL_DMP_EN_BIT             7
+#define MPU6050_USERCTRL_FIFO_EN_BIT            6
+#define MPU6050_USERCTRL_I2C_MST_EN_BIT         5
+#define MPU6050_USERCTRL_I2C_IF_DIS_BIT         4
+#define MPU6050_USERCTRL_DMP_RESET_BIT          3
+#define MPU6050_USERCTRL_FIFO_RESET_BIT         2
+#define MPU6050_USERCTRL_I2C_MST_RESET_BIT      1
+#define MPU6050_USERCTRL_SIG_COND_RESET_BIT     0
+
+#define MPU6050_PWR1_DEVICE_RESET_BIT   7
+#define MPU6050_PWR1_SLEEP_BIT          6
+#define MPU6050_PWR1_CYCLE_BIT          5
+#define MPU6050_PWR1_TEMP_DIS_BIT       3
+#define MPU6050_PWR1_CLKSEL_BIT         2
+#define MPU6050_PWR1_CLKSEL_LENGTH      3
+
+#define MPU6050_CLOCK_INTERNAL          0x00
+#define MPU6050_CLOCK_PLL_XGYRO         0x01
+#define MPU6050_CLOCK_PLL_YGYRO         0x02
+#define MPU6050_CLOCK_PLL_ZGYRO         0x03
+#define MPU6050_CLOCK_PLL_EXT32K        0x04
+#define MPU6050_CLOCK_PLL_EXT19M        0x05
+#define MPU6050_CLOCK_KEEP_RESET        0x07
+
+#define MPU6050_PWR2_LP_WAKE_CTRL_BIT       7
+#define MPU6050_PWR2_LP_WAKE_CTRL_LENGTH    2
+#define MPU6050_PWR2_STBY_XA_BIT            5
+#define MPU6050_PWR2_STBY_YA_BIT            4
+#define MPU6050_PWR2_STBY_ZA_BIT            3
+#define MPU6050_PWR2_STBY_XG_BIT            2
+#define MPU6050_PWR2_STBY_YG_BIT            1
+#define MPU6050_PWR2_STBY_ZG_BIT            0
+
+#define MPU6050_WAKE_FREQ_1P25      0x0
+#define MPU6050_WAKE_FREQ_2P5       0x1
+#define MPU6050_WAKE_FREQ_5         0x2
+#define MPU6050_WAKE_FREQ_10        0x3
+
+#define MPU6050_BANKSEL_PRFTCH_EN_BIT       6
+#define MPU6050_BANKSEL_CFG_USER_BANK_BIT   5
+#define MPU6050_BANKSEL_MEM_SEL_BIT         4
+#define MPU6050_BANKSEL_MEM_SEL_LENGTH      5
+
+#define MPU6050_WHO_AM_I_BIT        6
+#define MPU6050_WHO_AM_I_LENGTH     6
+
+#define MPU6050_DMP_MEMORY_BANKS        8
+#define MPU6050_DMP_MEMORY_BANK_SIZE    256
+#define MPU6050_DMP_MEMORY_CHUNK_SIZE   16
+
+// Helper functions
+int8 memcmpOwn(const void *Ptr1, const void *Ptr2, size_t Count);
+
+// note: DMP code memory blocks defined at end of header file
+void MPU6050_initialize(uint8 address);
+uint8 MPU6050_testConnection();
+
+// AUX_VDDIO register
+uint8 MPU6050_getAuxVDDIOLevel();
+void MPU6050_setAuxVDDIOLevel(uint8 level);
+
+// SMPLRT_DIV register
+uint8 MPU6050_getRate();
+void MPU6050_setRate(uint8 rate);
+
+// CONFIG register
+uint8 MPU6050_getExternalFrameSync();
+void MPU6050_setExternalFrameSync(uint8 sync);
+uint8 MPU6050_getDLPFMode();
+void MPU6050_setDLPFMode(uint8 bandwidth);
+
+// GYRO_CONFIG register
+uint8 MPU6050_getFullScaleGyroRange();
+void MPU6050_setFullScaleGyroRange(uint8 range);
+
+// ACCEL_CONFIG register
+uint8 MPU6050_getAccelXSelfTest();
+void MPU6050_setAccelXSelfTest(bool enabled);
+uint8 MPU6050_getAccelYSelfTest();
+void MPU6050_setAccelYSelfTest(bool enabled);
+uint8 MPU6050_getAccelZSelfTest();
+void MPU6050_setAccelZSelfTest(bool enabled);
+uint8 MPU6050_getFullScaleAccelRange();
+void MPU6050_setFullScaleAccelRange(uint8 range);
+uint8 MPU6050_getDHPFMode();
+void MPU6050_setDHPFMode(uint8 mode);
+
+// FF_THR register
+uint8 MPU6050_getFreefallDetectionThreshold();
+void MPU6050_setFreefallDetectionThreshold(uint8 threshold);
+
+// FF_DUR register
+uint8 MPU6050_getFreefallDetectionDuration();
+void MPU6050_setFreefallDetectionDuration(uint8 duration);
+
+// MOT_THR register
+uint8 MPU6050_getMotionDetectionThreshold();
+void MPU6050_setMotionDetectionThreshold(uint8 threshold);
+
+// MOT_DUR register
+uint8 MPU6050_getMotionDetectionDuration();
+void MPU6050_setMotionDetectionDuration(uint8 duration);
+
+// ZRMOT_THR register
+uint8 MPU6050_getZeroMotionDetectionThreshold();
+void MPU6050_setZeroMotionDetectionThreshold(uint8 threshold);
+
+// ZRMOT_DUR register
+uint8 MPU6050_getZeroMotionDetectionDuration();
+void MPU6050_setZeroMotionDetectionDuration(uint8 duration);
+
+// FIFO_EN register
+uint8 MPU6050_getTempFIFOEnabled();
+void MPU6050_setTempFIFOEnabled(bool enabled);
+uint8 MPU6050_getXGyroFIFOEnabled();
+void MPU6050_setXGyroFIFOEnabled(bool enabled);
+uint8 MPU6050_getYGyroFIFOEnabled();
+void MPU6050_setYGyroFIFOEnabled(bool enabled);
+uint8 MPU6050_getZGyroFIFOEnabled();
+void MPU6050_setZGyroFIFOEnabled(bool enabled);
+uint8 MPU6050_getAccelFIFOEnabled();
+void MPU6050_setAccelFIFOEnabled(bool enabled);
+uint8 MPU6050_getSlave2FIFOEnabled();
+void MPU6050_setSlave2FIFOEnabled(bool enabled);
+uint8 MPU6050_getSlave1FIFOEnabled();
+void MPU6050_setSlave1FIFOEnabled(bool enabled);
+uint8 MPU6050_getSlave0FIFOEnabled();
+void MPU6050_setSlave0FIFOEnabled(bool enabled);
+
+// I2C_MST_CTRL register
+uint8 MPU6050_getMultiMasterEnabled();
+void MPU6050_setMultiMasterEnabled(bool enabled);
+uint8 MPU6050_getWaitForExternalSensorEnabled();
+void MPU6050_setWaitForExternalSensorEnabled(bool enabled);
+uint8 MPU6050_getSlave3FIFOEnabled();
+void MPU6050_setSlave3FIFOEnabled(bool enabled);
+uint8 MPU6050_getSlaveReadWriteTransitionEnabled();
+void MPU6050_setSlaveReadWriteTransitionEnabled(bool enabled);
+uint8 MPU6050_getMasterClockSpeed();
+void MPU6050_setMasterClockSpeed(uint8 speed);
+
+// I2C_SLV* registers (Slave 0-3)
+uint8 MPU6050_getSlaveAddress(uint8 num);
+void MPU6050_setSlaveAddress(uint8 num, uint8 address);
+uint8 MPU6050_getSlaveRegister(uint8 num);
+void MPU6050_setSlaveRegister(uint8 num, uint8 reg);
+uint8 MPU6050_getSlaveEnabled(uint8 num);
+void MPU6050_setSlaveEnabled(uint8 num, bool enabled);
+uint8 MPU6050_getSlaveWordByteSwap(uint8 num);
+void MPU6050_setSlaveWordByteSwap(uint8 num, bool enabled);
+uint8 MPU6050_getSlaveWriteMode(uint8 num);
+void MPU6050_setSlaveWriteMode(uint8 num, bool mode);
+uint8 MPU6050_getSlaveWordGroupOffset(uint8 num);
+void MPU6050_setSlaveWordGroupOffset(uint8 num, bool enabled);
+uint8 MPU6050_getSlaveDataLength(uint8 num);
+void MPU6050_setSlaveDataLength(uint8 num, uint8 length);
+
+// I2C_SLV* registers (Slave 4)
+uint8 MPU6050_getSlave4Address();
+void MPU6050_setSlave4Address(uint8 address);
+uint8 MPU6050_getSlave4Register();
+void MPU6050_setSlave4Register(uint8 reg);
+void MPU6050_setSlave4OutputByte(uint8 data);
+uint8 MPU6050_getSlave4Enabled();
+void MPU6050_setSlave4Enabled(bool enabled);
+uint8 MPU6050_getSlave4InterruptEnabled();
+void MPU6050_setSlave4InterruptEnabled(bool enabled);
+uint8 MPU6050_getSlave4WriteMode();
+void MPU6050_setSlave4WriteMode(bool mode);
+uint8 MPU6050_getSlave4MasterDelay();
+void MPU6050_setSlave4MasterDelay(uint8 delay);
+uint8 MPU6050_getSlate4InputByte();
+
+// I2C_MST_STATUS register
+uint8 MPU6050_getPassthroughStatus();
+uint8 MPU6050_getSlave4IsDone();
+uint8 MPU6050_getLostArbitration();
+uint8 MPU6050_getSlave4Nack();
+uint8 MPU6050_getSlave3Nack();
+uint8 MPU6050_getSlave2Nack();
+uint8 MPU6050_getSlave1Nack();
+uint8 MPU6050_getSlave0Nack();
+
+// INT_PIN_CFG register
+uint8 MPU6050_getInterruptMode();
+void MPU6050_setInterruptMode(bool mode);
+uint8 MPU6050_getInterruptDrive();
+void MPU6050_setInterruptDrive(bool drive);
+uint8 MPU6050_getInterruptLatch();
+void MPU6050_setInterruptLatch(bool latch);
+uint8 MPU6050_getInterruptLatchClear();
+void MPU6050_setInterruptLatchClear(bool clear);
+uint8 MPU6050_getFSyncInterruptLevel();
+void MPU6050_setFSyncInterruptLevel(bool level);
+uint8 MPU6050_getFSyncInterruptEnabled();
+void MPU6050_setFSyncInterruptEnabled(bool enabled);
+uint8 MPU6050_getI2CBypassEnabled();
+void MPU6050_setI2CBypassEnabled(bool enabled);
+uint8 MPU6050_getClockOutputEnabled();
+void MPU6050_setClockOutputEnabled(bool enabled);
+
+// INT_ENABLE register
+uint8 MPU6050_getIntEnabled();
+void MPU6050_setIntEnabled(uint8 enabled);
+uint8 MPU6050_getIntFreefallEnabled();
+void MPU6050_setIntFreefallEnabled(bool enabled);
+uint8 MPU6050_getIntMotionEnabled();
+void MPU6050_setIntMotionEnabled(bool enabled);
+uint8 MPU6050_getIntZeroMotionEnabled();
+void MPU6050_setIntZeroMotionEnabled(bool enabled);
+uint8 MPU6050_getIntFIFOBufferOverflowEnabled();
+void MPU6050_setIntFIFOBufferOverflowEnabled(bool enabled);
+uint8 MPU6050_getIntI2CMasterEnabled();
+void MPU6050_setIntI2CMasterEnabled(bool enabled);
+uint8 MPU6050_getIntDataReadyEnabled();
+void MPU6050_setIntDataReadyEnabled(bool enabled);
+
+// INT_STATUS register
+uint8 MPU6050_getIntStatus();
+uint8 MPU6050_getIntFreefallStatus();
+uint8 MPU6050_getIntMotionStatus();
+uint8 MPU6050_getIntZeroMotionStatus();
+uint8 MPU6050_getIntFIFOBufferOverflowStatus();
+uint8 MPU6050_getIntI2CMasterStatus();
+uint8 MPU6050_getIntDataReadyStatus();
+
+// ACCEL_*OUT_* registers
+void MPU6050_getMotion9(int16* ax, int16* ay, int16* az, int16* gx, int16* gy, int16* gz, int16* mx, int16* my, int16* mz);
+void MPU6050_getMotion6(int16* ax, int16* ay, int16* az, int16* gx, int16* gy, int16* gz);
+void MPU6050_getAcceleration(int16* x, int16* y, int16* z);
+int16 MPU6050_getAccelerationX();
+int16 MPU6050_getAccelerationY();
+int16 MPU6050_getAccelerationZ();
+
+// TEMP_OUT_* registers
+int16 MPU6050_getTemperature();
+
+// GYRO_*OUT_* registers
+void MPU6050_getRotation(int16* x, int16* y, int16* z);
+int16 MPU6050_getRotationX();
+int16 MPU6050_getRotationY();
+int16 MPU6050_getRotationZ();
+
+// EXT_SENS_DATA_* registers
+uint8 MPU6050_getExternalSensorByte(int position);
+uint16 MPU6050_getExternalSensorWord(int position);
+uint32 MPU6050_getExternalSensorDWord(int position);
+
+// MOT_DETECT_STATUS register
+uint8 MPU6050_getMotionStatus();
+uint8 MPU6050_getXNegMotionDetected();
+uint8 MPU6050_getXPosMotionDetected();
+uint8 MPU6050_getYNegMotionDetected();
+uint8 MPU6050_getYPosMotionDetected();
+uint8 MPU6050_getZNegMotionDetected();
+uint8 MPU6050_getZPosMotionDetected();
+uint8 MPU6050_getZeroMotionDetected();
+
+// I2C_SLV*_DO register
+void MPU6050_setSlaveOutputByte(uint8 num, uint8 data);
+
+// I2C_MST_DELAY_CTRL register
+uint8 MPU6050_getExternalShadowDelayEnabled();
+void MPU6050_setExternalShadowDelayEnabled(bool enabled);
+uint8 MPU6050_getSlaveDelayEnabled(uint8 num);
+void MPU6050_setSlaveDelayEnabled(uint8 num, bool enabled);
+
+// SIGNAL_PATH_RESET register
+void MPU6050_resetGyroscopePath();
+void MPU6050_resetAccelerometerPath();
+void MPU6050_resetTemperaturePath();
+
+// MOT_DETECT_CTRL register
+uint8 MPU6050_getAccelerometerPowerOnDelay();
+void MPU6050_setAccelerometerPowerOnDelay(uint8 delay);
+uint8 MPU6050_getFreefallDetectionCounterDecrement();
+void MPU6050_setFreefallDetectionCounterDecrement(uint8 decrement);
+uint8 MPU6050_getMotionDetectionCounterDecrement();
+void MPU6050_setMotionDetectionCounterDecrement(uint8 decrement);
+
+// USER_CTRL register
+uint8 MPU6050_getFIFOEnabled();
+void MPU6050_setFIFOEnabled(bool enabled);
+uint8 MPU6050_getI2CMasterModeEnabled();
+void MPU6050_setI2CMasterModeEnabled(bool enabled);
+void MPU6050_switchSPIEnabled(bool enabled);
+void MPU6050_resetFIFO();
+void MPU6050_resetI2CMaster();
+void MPU6050_resetSensors();
+
+// PWR_MGMT_1 register
+void MPU6050_reset();
+uint8 MPU6050_getSleepEnabled();
+void MPU6050_setSleepEnabled(bool enabled);
+uint8 MPU6050_getWakeCycleEnabled();
+void MPU6050_setWakeCycleEnabled(bool enabled);
+uint8 MPU6050_getTempSensorEnabled();
+void MPU6050_setTempSensorEnabled(bool enabled);
+uint8 MPU6050_getClockSource();
+void MPU6050_setClockSource(uint8 source);
+
+// PWR_MGMT_2 register
+uint8 MPU6050_getWakeFrequency();
+void MPU6050_setWakeFrequency(uint8 frequency);
+uint8 MPU6050_getStandbyXAccelEnabled();
+void MPU6050_setStandbyXAccelEnabled(bool enabled);
+uint8 MPU6050_getStandbyYAccelEnabled();
+void MPU6050_setStandbyYAccelEnabled(bool enabled);
+uint8 MPU6050_getStandbyZAccelEnabled();
+void MPU6050_setStandbyZAccelEnabled(bool enabled);
+uint8 MPU6050_getStandbyXGyroEnabled();
+void MPU6050_setStandbyXGyroEnabled(bool enabled);
+uint8 MPU6050_getStandbyYGyroEnabled();
+void MPU6050_setStandbyYGyroEnabled(bool enabled);
+uint8 MPU6050_getStandbyZGyroEnabled();
+void MPU6050_setStandbyZGyroEnabled(bool enabled);
+
+// FIFO_COUNT_* registers
+uint16 MPU6050_getFIFOCount();
+
+// FIFO_R_W register
+uint8 MPU6050_getFIFOByte();
+void MPU6050_setFIFOByte(uint8 data);
+void MPU6050_getFIFOBytes(uint8 *data, uint8 length);
+
+// WHO_AM_I register
+uint8 MPU6050_getDeviceID();
+void MPU6050_setDeviceID(uint8 id);
+
+// ======== UNDOCUMENTED/DMP REGISTERS/METHODS ========
+
+// XG_OFFS_TC register
+uint8 MPU6050_getOTPBankValid();
+void MPU6050_setOTPBankValid(bool enabled);
+int8 MPU6050_getXGyroOffsetTC();
+void MPU6050_setXGyroOffsetTC(int8 offset);
+
+// YG_OFFS_TC register
+int8 MPU6050_getYGyroOffsetTC();
+void MPU6050_setYGyroOffsetTC(int8 offset);
+
+// ZG_OFFS_TC register
+int8 MPU6050_getZGyroOffsetTC();
+void MPU6050_setZGyroOffsetTC(int8 offset);
+
+// X_FINE_GAIN register
+int8 MPU6050_getXFineGain();
+void MPU6050_setXFineGain(int8 gain);
+
+// Y_FINE_GAIN register
+int8 MPU6050_getYFineGain();
+void MPU6050_setYFineGain(int8 gain);
+
+// Z_FINE_GAIN register
+int8 MPU6050_getZFineGain();
+void MPU6050_setZFineGain(int8 gain);
+
+// XA_OFFS_* registers
+int16 MPU6050_getXAccelOffset();
+void MPU6050_setXAccelOffset(int16 offset);
+
+// YA_OFFS_* register
+int16 MPU6050_getYAccelOffset();
+void MPU6050_setYAccelOffset(int16 offset);
+
+// ZA_OFFS_* register
+int16 MPU6050_getZAccelOffset();
+void MPU6050_setZAccelOffset(int16 offset);
+
+// XG_OFFS_USR* registers
+int16 MPU6050_getXGyroOffset();
+void MPU6050_setXGyroOffset(int16 offset);
+
+// YG_OFFS_USR* register
+int16 MPU6050_getYGyroOffset();
+void MPU6050_setYGyroOffset(int16 offset);
+
+// ZG_OFFS_USR* register
+int16 MPU6050_getZGyroOffset();
+void MPU6050_setZGyroOffset(int16 offset);
+
+// INT_ENABLE register (DMP functions)
+uint8 MPU6050_getIntPLLReadyEnabled();
+void MPU6050_setIntPLLReadyEnabled(bool enabled);
+uint8 MPU6050_getIntDMPEnabled();
+void MPU6050_setIntDMPEnabled(bool enabled);
+
+// DMP_INT_STATUS
+uint8 MPU6050_getDMPInt5Status();
+uint8 MPU6050_getDMPInt4Status();
+uint8 MPU6050_getDMPInt3Status();
+uint8 MPU6050_getDMPInt2Status();
+uint8 MPU6050_getDMPInt1Status();
+uint8 MPU6050_getDMPInt0Status();
+
+// INT_STATUS register (DMP functions)
+uint8 MPU6050_getIntPLLReadyStatus();
+uint8 MPU6050_getIntDMPStatus();
+
+// USER_CTRL register (DMP functions)
+uint8 MPU6050_getDMPEnabled();
+void MPU6050_setDMPEnabled(bool enabled);
+void MPU6050_resetDMP();
+
+// BANK_SEL register
+void MPU6050_setMemoryBank(uint8 bank, bool prefetchEnabled, bool userBank); // mandatory, false, false
+
+// MEM_START_ADDR register
+void MPU6050_setMemoryStartAddress(uint8 address);
+
+// MEM_R_W register
+uint8 MPU6050_readMemoryByte();
+void MPU6050_writeMemoryByte(uint8 data);
+void MPU6050_readMemoryBlock(uint8 *data, uint16 dataSize, uint8 bank, uint8 address); // mandatory, mandatory, 0, 0
+uint8 MPU6050_writeMemoryBlock(const uint8 *data, uint16 dataSize, uint8 bank, uint8 address, bool verify, bool useProgMem); // Mandatory, mandatory, 0, 0, true, false
+uint8 writeProgMemoryBlock(const uint8 *data, uint16 dataSize, uint8 bank, uint8 address, bool verify); // Mandatory, mandatory, 0, 0, true
+
+uint8 MPU6050_writeDMPConfigurationSet(const uint8 *data, uint16 dataSize, bool useProgMem); // Mandatory, mandatory, false
+uint8 MPU6050_writeProgDMPConfigurationSet(const uint8 *data, uint16 dataSize);
+
+// DMP_CFG_1 register
+uint8 MPU6050_getDMPConfig1();
+void MPU6050_setDMPConfig1(uint8 config);
+
+// DMP_CFG_2 register
+uint8 MPU6050_getDMPConfig2();
+void MPU6050_setDMPConfig2(uint8 config);
+
+// special methods for MotionApps 2.0 implementation
+#ifdef MPU6050_INCLUDE_DMP_MOTIONAPPS20
+#include "helper_3dmath.h"
+
+uint8 *MPU6050_dmpPacketBuffer;
+uint16 MPU6050_dmpPacketSize;
+
+uint8 MPU6050_dmpInitialize();
+bool MPU6050_dmpPacketAvailable();
+
+uint8 MPU6050_dmpSetFIFORate(uint8 fifoRate);
+uint8 MPU6050_dmpGetFIFORate();
+uint8 MPU6050_dmpGetSampleStepSizeMS();
+uint8 MPU6050_dmpGetSampleFrequency();
+int32 MPU6050_dmpDecodeTemperature(int8 tempReg);
+
+// Register callbacks after a packet of FIFO data is processed
+//uint8 dmpRegisterFIFORateProcess(inv_obj_func func, int16 priority);
+//uint8 dmpUnregisterFIFORateProcess(inv_obj_func func);
+uint8 MPU6050_dmpRunFIFORateProcesses();
+
+// Setup FIFO for various output
+uint8 MPU6050_dmpSendQuaternion(uint16 accuracy);
+uint8 MPU6050_dmpSendGyro(uint16 elements, uint16 accuracy);
+uint8 MPU6050_dmpSendAccel(uint16 elements, uint16 accuracy);
+uint8 MPU6050_dmpSendLinearAccel(uint16 elements, uint16 accuracy);
+uint8 MPU6050_dmpSendLinearAccelInWorld(uint16 elements, uint16 accuracy);
+uint8 MPU6050_dmpSendControlData(uint16 elements, uint16 accuracy);
+uint8 MPU6050_dmpSendSensorData(uint16 elements, uint16 accuracy);
+uint8 MPU6050_dmpSendExternalSensorData(uint16 elements, uint16 accuracy);
+uint8 MPU6050_dmpSendGravity(uint16 elements, uint16 accuracy);
+uint8 MPU6050_dmpSendPacketNumber(uint16 accuracy);
+uint8 MPU6050_dmpSendQuantizedAccel(uint16 elements, uint16 accuracy);
+uint8 MPU6050_dmpSendEIS(uint16 elements, uint16 accuracy);
+
+// Get Fixed Point data from FIFO
+uint8 MPU6050_dmpGetAccel32(int32 *data, const uint8* packet); // Default packet=0
+uint8 MPU6050_dmpGetAccel16(int16 *data, const uint8* packet); // Default packet=0
+uint8 MPU6050_dmpGetAccelVec(VectorInt16 *v, const uint8* packet); // Default packet=0
+uint8 MPU6050_dmpGetQuaternion32(int32 *data, const uint8* packet); // Default packet=0
+uint8 MPU6050_dmpGetQuaternion16(int16 *data, const uint8* packet); // Default packet=0
+uint8 MPU6050_dmpGetQuaternionQuat(Quaternion *q, const uint8* packet); // Default packet=0
+uint8 MPU6050_dmpGet6AxisQuaternion32(int32 *data, const uint8* packet); // Default packet=0
+uint8 MPU6050_dmpGet6AxisQuaternion16(int16 *data, const uint8* packet); // Default packet=0
+uint8 MPU6050_dmpGet6AxisQuaternionQuat(Quaternion *q, const uint8* packet); // Default packet=0
+uint8 MPU6050_dmpGetRelativeQuaternion32(int32 *data, const uint8* packet); // Default packet=0
+uint8 MPU6050_dmpGetRelativeQuaternion16(int16 *data, const uint8* packet); // Default packet=0
+uint8 MPU6050_dmpGetRelativeQuaternionQuat(Quaternion *data, const uint8* packet); // Default packet=0
+uint8 MPU6050_dmpGetGyro32(int32 *data, const uint8* packet); // Default packet=0
+uint8 MPU6050_dmpGetGyro16(int16 *data, const uint8* packet); // Default packet=0
+uint8 MPU6050_dmpGetGyroVec(VectorInt16 *v, const uint8* packet); // Default packet=0
+uint8 MPU6050_dmpSetLinearAccelFilterCoefficient(float coef);
+uint8 MPU6050_dmpGetLinearAccel32(int32 *data, const uint8* packet); // Default packet=0
+uint8 MPU6050_dmpGetLinearAccel16(int16 *data, const uint8* packet); // Default packet=0
+uint8 MPU6050_dmpGetLinearAccelVec(VectorInt16 *v, const uint8* packet); // Default packet=0
+uint8 MPU6050_dmpGetLinearAccelVecVec(VectorInt16 *v, VectorInt16 *vRaw, VectorFloat *gravity);
+uint8 MPU6050_dmpGetLinearAccelInWorld32(int32 *data, const uint8* packet); // Default packet=0
+uint8 MPU6050_dmpGetLinearAccelInWorld16(int16 *data, const uint8* packet); // Default packet=0
+uint8 MPU6050_dmpGetLinearAccelInWorldVec(VectorInt16 *v, const uint8* packet); // Default packet=0
+uint8 MPU6050_dmpGetLinearAccelInWorldVecQuat(VectorInt16 *v, VectorInt16 *vReal, Quaternion *q);
+uint8 MPU6050_dmpGetGyroAndAccelSensor32(int32 *data, const uint8* packet); // Default packet=0
+uint8 MPU6050_dmpGetGyroAndAccelSensor16(int16 *data, const uint8* packet); // Default packet=0
+uint8 MPU6050_dmpGetGyroAndAccelSensorVec(VectorInt16 *g, VectorInt16 *a, const uint8* packet); // Default packet=0
+uint8 MPU6050_dmpGetGyroSensor32(int32 *data, const uint8* packet); // Default packet=0
+uint8 MPU6050_dmpGetGyroSensor16(int16 *data, const uint8* packet); // Default packet=0
+uint8 MPU6050_dmpGetGyroSensorVec(VectorInt16 *v, const uint8* packet); // Default packet=0
+uint8 MPU6050_dmpGetControlData(int32 *data, const uint8* packet); // Default packet=0
+uint8 MPU6050_dmpGetTemperature(int32 *data, const uint8* packet); // Default packet=0
+uint8 MPU6050_dmpGetGravity32(int32 *data, const uint8* packet); // Default packet=0
+uint8 MPU6050_dmpGetGravity16(int16 *data, const uint8* packet); // Default packet=0
+uint8 MPU6050_dmpGetGravityVec(VectorInt16 *v, const uint8* packet); // Default packet=0
+uint8 MPU6050_dmpGetGravityVecQuat(VectorFloat *v, Quaternion *q);
+uint8 MPU6050_dmpGetUnquantizedAccel32(int32 *data, const uint8* packet); // Default packet=0
+uint8 MPU6050_dmpGetUnquantizedAccel16(int16 *data, const uint8* packet); // Default packet=0
+uint8 MPU6050_dmpGetUnquantizedAccelVec(VectorInt16 *v, const uint8* packet); // Default packet=0
+uint8 MPU6050_dmpGetQuantizedAccel32(int32 *data, const uint8* packet); // Default packet=0
+uint8 MPU6050_dmpGetQuantizedAccel16(int16 *data, const uint8* packet); // Default packet=0
+uint8 MPU6050_dmpGetQuantizedAccelVec(VectorInt16 *v, const uint8* packet); // Default packet=0
+uint8 MPU6050_dmpGetExternalSensorData(int32 *data, uint16 size, const uint8* packet); // Default packet=0
+uint8 MPU6050_dmpGetEIS(int32 *data, const uint8* packet); // Default packet=0
+
+uint8 MPU6050_dmpGetEuler(float *data, Quaternion *q);
+uint8 MPU6050_dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity);
+
+// Get Floating Point data from FIFO
+uint8 MPU6050_dmpGetAccelFloat(float *data, const uint8* packet); // Default packet=0
+uint8 MPU6050_dmpGetQuaternionFloat(float *data, const uint8* packet); // Default packet=0
+
+uint8 MPU6050_dmpProcessFIFOPacket(const unsigned char *dmpData);
+uint8 MPU6050_dmpReadAndProcessFIFOPacket(uint8 numPackets, uint8 *processed); // Default processed = NULL
+
+uint8 MPU6050_dmpSetFIFOProcessedCallback(void (*func) (void));
+
+uint8 MPU6050_dmpInitFIFOParam();
+uint8 MPU6050_dmpCloseFIFO();
+uint8 MPU6050_dmpSetGyroDataSource(uint8 source);
+uint8 MPU6050_dmpDecodeQuantizedAccel();
+uint32 MPU6050_dmpGetGyroSumOfSquare();
+uint32 MPU6050_dmpGetAccelSumOfSquare();
+void MPU6050_dmpOverrideQuaternion(long *q);
+uint16 MPU6050_dmpGetFIFOPacketSize();
+
+uint8 MPU6050_writeProgMemoryBlock(const uint8 *data, uint16 dataSize,
+		uint8 bank, uint8 address, bool verify);
+#endif
+
+// special methods for MotionApps 4.1 implementation
+#ifdef MPU6050_INCLUDE_DMP_MOTIONAPPS41
+uint8 *MPU6050_dmpPacketBuffer;
+uint16 MPU6050_dmpPacketSize;
+
+uint8 MPU6050_dmpInitialize();
+bool MPU6050_dmpPacketAvailable();
+
+uint8 MPU6050_dmpSetFIFORate(uint8 fifoRate);
+uint8 MPU6050_dmpGetFIFORate();
+uint8 MPU6050_dmpGetSampleStepSizeMS();
+uint8 MPU6050_dmpGetSampleFrequency();
+int32 MPU6050_dmpDecodeTemperature(int8 tempReg);
+
+// Register callbacks after a packet of FIFO data is processed
+//uint8 dmpRegisterFIFORateProcess(inv_obj_func func, int16 priority);
+//uint8 dmpUnregisterFIFORateProcess(inv_obj_func func);
+uint8 MPU6050_dmpRunFIFORateProcesses();
+
+// Setup FIFO for various output
+uint8 MPU6050_dmpSendQuaternion(uint16 accuracy);
+uint8 MPU6050_dmpSendGyro(uint16 elements, uint16 accuracy);
+uint8 MPU6050_dmpSendAccel(uint16 elements, uint16 accuracy);
+uint8 MPU6050_dmpSendLinearAccel(uint16 elements, uint16 accuracy);
+uint8 MPU6050_dmpSendLinearAccelInWorld(uint16 elements, uint16 accuracy);
+uint8 MPU6050_dmpSendControlData(uint16 elements, uint16 accuracy);
+uint8 MPU6050_dmpSendSensorData(uint16 elements, uint16 accuracy);
+uint8 MPU6050_dmpSendExternalSensorData(uint16 elements, uint16 accuracy);
+uint8 MPU6050_dmpSendGravity(uint16 elements, uint16 accuracy);
+uint8 MPU6050_dmpSendPacketNumber(uint16 accuracy);
+uint8 MPU6050_dmpSendQuantizedAccel(uint16 elements, uint16 accuracy);
+uint8 MPU6050_dmpSendEIS(uint16 elements, uint16 accuracy);
+
+// Get Fixed Point data from FIFO
+uint8 MPU6050_dmpGetAccel(int32 *data, const uint8* packet=0);
+uint8 MPU6050_dmpGetAccel(int16 *data, const uint8* packet=0);
+uint8 MPU6050_dmpGetAccel(VectorInt16 *v, const uint8* packet=0);
+uint8 MPU6050_dmpGetQuaternion(int32 *data, const uint8* packet=0);
+uint8 MPU6050_dmpGetQuaternion(int16 *data, const uint8* packet=0);
+uint8 MPU6050_dmpGetQuaternion(Quaternion *q, const uint8* packet=0);
+uint8 MPU6050_dmpGet6AxisQuaternion(int32 *data, const uint8* packet=0);
+uint8 MPU6050_dmpGet6AxisQuaternion(int16 *data, const uint8* packet=0);
+uint8 MPU6050_dmpGet6AxisQuaternion(Quaternion *q, const uint8* packet=0);
+uint8 MPU6050_dmpGetRelativeQuaternion(int32 *data, const uint8* packet=0);
+uint8 MPU6050_dmpGetRelativeQuaternion(int16 *data, const uint8* packet=0);
+uint8 MPU6050_dmpGetRelativeQuaternion(Quaternion *data, const uint8* packet=0);
+uint8 MPU6050_dmpGetGyro(int32 *data, const uint8* packet=0);
+uint8 MPU6050_dmpGetGyro(int16 *data, const uint8* packet=0);
+uint8 MPU6050_dmpGetGyro(VectorInt16 *v, const uint8* packet=0);
+uint8 MPU6050_dmpGetMag(int16 *data, const uint8* packet=0);
+uint8 MPU6050_dmpSetLinearAccelFilterCoefficient(float coef);
+uint8 MPU6050_dmpGetLinearAccel(int32 *data, const uint8* packet=0);
+uint8 MPU6050_dmpGetLinearAccel(int16 *data, const uint8* packet=0);
+uint8 MPU6050_dmpGetLinearAccel(VectorInt16 *v, const uint8* packet=0);
+uint8 MPU6050_dmpGetLinearAccel(VectorInt16 *v, VectorInt16 *vRaw, VectorFloat *gravity);
+uint8 MPU6050_dmpGetLinearAccelInWorld(int32 *data, const uint8* packet=0);
+uint8 MPU6050_dmpGetLinearAccelInWorld(int16 *data, const uint8* packet=0);
+uint8 MPU6050_dmpGetLinearAccelInWorld(VectorInt16 *v, const uint8* packet=0);
+uint8 MPU6050_dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Quaternion *q);
+uint8 MPU6050_dmpGetGyroAndAccelSensor(int32 *data, const uint8* packet=0);
+uint8 MPU6050_dmpGetGyroAndAccelSensor(int16 *data, const uint8* packet=0);
+uint8 MPU6050_dmpGetGyroAndAccelSensor(VectorInt16 *g, VectorInt16 *a, const uint8* packet=0);
+uint8 MPU6050_dmpGetGyroSensor(int32 *data, const uint8* packet=0);
+uint8 MPU6050_dmpGetGyroSensor(int16 *data, const uint8* packet=0);
+uint8 MPU6050_dmpGetGyroSensor(VectorInt16 *v, const uint8* packet=0);
+uint8 MPU6050_dmpGetControlData(int32 *data, const uint8* packet=0);
+uint8 MPU6050_dmpGetTemperature(int32 *data, const uint8* packet=0);
+uint8 MPU6050_dmpGetGravity(int32 *data, const uint8* packet=0);
+uint8 MPU6050_dmpGetGravity(int16 *data, const uint8* packet=0);
+uint8 MPU6050_dmpGetGravity(VectorInt16 *v, const uint8* packet=0);
+uint8 MPU6050_dmpGetGravity(VectorFloat *v, Quaternion *q);
+uint8 MPU6050_dmpGetUnquantizedAccel(int32 *data, const uint8* packet=0);
+uint8 MPU6050_dmpGetUnquantizedAccel(int16 *data, const uint8* packet=0);
+uint8 MPU6050_dmpGetUnquantizedAccel(VectorInt16 *v, const uint8* packet=0);
+uint8 MPU6050_dmpGetQuantizedAccel(int32 *data, const uint8* packet=0);
+uint8 MPU6050_dmpGetQuantizedAccel(int16 *data, const uint8* packet=0);
+uint8 MPU6050_dmpGetQuantizedAccel(VectorInt16 *v, const uint8* packet=0);
+uint8 MPU6050_dmpGetExternalSensorData(int32 *data, uint16 size, const uint8* packet=0);
+uint8 MPU6050_dmpGetEIS(int32 *data, const uint8* packet=0);
+
+uint8 MPU6050_dmpGetEuler(float *data, Quaternion *q);
+uint8 MPU6050_dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity);
+
+// Get Floating Point data from FIFO
+uint8 MPU6050_dmpGetAccelFloat(float *data, const uint8* packet=0);
+uint8 MPU6050_dmpGetQuaternionFloat(float *data, const uint8* packet=0);
+
+uint8 MPU6050_dmpProcessFIFOPacket(const unsigned char *dmpData);
+uint8 MPU6050_dmpReadAndProcessFIFOPacket(uint8 numPackets, uint8 *processed=NULL);
+
+uint8 MPU6050_dmpSetFIFOProcessedCallback(void (*func) (void));
+
+uint8 MPU6050_dmpInitFIFOParam();
+uint8 MPU6050_dmpCloseFIFO();
+uint8 MPU6050_dmpSetGyroDataSource(uint8 source);
+uint8 MPU6050_dmpDecodeQuantizedAccel();
+uint32 MPU6050_dmpGetGyroSumOfSquare();
+uint32 MPU6050_dmpGetAccelSumOfSquare();
+void MPU6050_dmpOverrideQuaternion(long *q);
+uint16 MPU6050_dmpGetFIFOPacketSize();
+#endif
+
+#endif /* _MPU6050_H_ */
diff --git a/Jennic/README.md b/Jennic/README.md
new file mode 100644
index 00000000..33cc83df
--- /dev/null
+++ b/Jennic/README.md
@@ -0,0 +1,14 @@
+# I2C Device Library for Jennic
+
+## I2Cdev
+We use JenOS peripheral libraries.
+
+## Devices
+Currently only MPU6050 is supported without DMP functions. There is no address set dynamically so currently only one MPU6050 can be read (or address must be changed manually each time before reading/writing)
+
+Adding more functions and devices should be straighforward after reading the source code.
+
+## Licence
+I2Cdev device library code is placed under the MIT license.
+
+_Copyright (c) 2011 Jeff Rowberg. Copyright (c) 2014 Marton Sebok. Copyright (c) 2015 Grégoire Surrel._
diff --git a/README b/README
index 095c8c2f..41001e3e 100644
--- a/README
+++ b/README
@@ -1,10 +1,10 @@
-L3G4200D gyro fix!
+Jennic platform added!
 
 ============================================================================
 Note: for details about this project, please visit: http://www.i2cdevlib.com
 ============================================================================
 
-The I2C Device Library (i2cdevlib) is a collection of uniform and well-documented classes to provide simple and intuitive interfaces to I2C devices. Each device is built to make use of the generic "I2Cdev" class, which abstracts the I2C bit- and byte-level communication away from each specific device class, making it easy to keep the device class clean while providing a simple way to modify just one class to port the I2C communication code onto different platforms (Arduino, PIC, MSP430, simple bit-banging, etc.). Device classes are designed to provide complete coverage of all functionality described by each device's documentation, plus any generic convenience functions that are helpful.
+The I2C Device Library (i2cdevlib) is a collection of uniform and well-documented classes to provide simple and intuitive interfaces to I2C devices. Each device is built to make use of the generic "I2Cdev" class, which abstracts the I2C bit- and byte-level communication away from each specific device class, making it easy to keep the device class clean while providing a simple way to modify just one class to port the I2C communication code onto different platforms (Arduino, PIC, MSP430, Jennic, simple bit-banging, etc.). Device classes are designed to provide complete coverage of all functionality described by each device's documentation, plus any generic convenience functions that are helpful.
 
 The code is written primarily to support the Arduino/Wiring implementation, but it may be useful in other circumstances. There are multiple I2C/TWI implementations selectable in the I2Cdev.h header file if the default Arduino "Wire.h" is not available or preferable for any reason.
 
@@ -12,6 +12,6 @@ There are examples in many of the classes that demonstrate basic usage patterns.
 
 Documentation for each class is created using Doxygen-style comments placed in each class definition file, based on the information available in each device's datasheet. This documentation is available in HTML format on the i2cdevlib.com website, which also holds helpful information for most of the classes present here on the repository.
 
-To use the library, just place the I2Cdev .cpp/.h source files and any device library .cpp/.h source files in the same folder as your sketch (or a suitable place relative to your avr-gcc project), and include just the device library headers that you need. Arduino users will also need to include  in your main sketch source file. Create a single device object (e.g. "ADXL345 accel();"), place any appropriate init function calls in your setup() routine (e.g. "accel.initialize();"), and off you go! See the example sketches inside many of the device class directories for reference.
+To use the library, just place the I2Cdev .cpp/.h or .c/.h source files and any device library .cpp/.h or .c/.h source files in the same folder as your sketch (or a suitable place relative to your project build tool), and include just the device library headers that you need. Arduino users will also need to include  in your main sketch source file. Create a single device object (e.g. "ADXL345 accel();"), place any appropriate init function calls in your setup() routine (e.g. "accel.initialize();"), and off you go! See the example sketches inside many of the device class directories for reference.
 
 Want a library for a device that isn't up on the repository? Request it, or fork the code and contribute! Better yet, send me a device on a breakout board to test the code during development. No guarantees on how fast I can get it done, but I'd love to make this the biggest consistent and well-documented I2C device library around.

From aab238173e1cd82c67cca8916efb4cb4950bc19a Mon Sep 17 00:00:00 2001
From: Jeff Rowberg 
Date: Fri, 3 Jul 2015 23:16:41 -0400
Subject: [PATCH 082/335] Relax compiler warning in most common case (which
 works fine)

---
 Arduino/I2Cdev/I2Cdev.cpp | 12 ++++++------
 Arduino/I2Cdev/I2Cdev.h   |  2 +-
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/Arduino/I2Cdev/I2Cdev.cpp b/Arduino/I2Cdev/I2Cdev.cpp
index c576c088..db173b55 100644
--- a/Arduino/I2Cdev/I2Cdev.cpp
+++ b/Arduino/I2Cdev/I2Cdev.cpp
@@ -1,6 +1,6 @@
 // I2Cdev library collection - Main I2C device class
 // Abstracts bit and byte I2C R/W functions into a convenient class
-// 6/9/2012 by Jeff Rowberg 
+// 2013-06-05 by Jeff Rowberg 
 //
 // Changelog:
 //      2013-05-06 - add Francesco Ferrara's Fastwire v0.24 implementation with small modifications
@@ -50,21 +50,21 @@ THE SOFTWARE.
     #ifdef I2CDEV_IMPLEMENTATION_WARNINGS
         #if ARDUINO < 100
             #warning Using outdated Arduino IDE with Wire library is functionally limiting.
-            #warning Arduino IDE v1.0.1+ with I2Cdev Fastwire implementation is recommended.
+            #warning Arduino IDE v1.6.5+ with I2Cdev Fastwire implementation is recommended.
             #warning This I2Cdev implementation does not support:
             #warning - Repeated starts conditions
             #warning - Timeout detection (some Wire requests block forever)
         #elif ARDUINO == 100
             #warning Using outdated Arduino IDE with Wire library is functionally limiting.
-            #warning Arduino IDE v1.0.1+ with I2Cdev Fastwire implementation is recommended.
+            #warning Arduino IDE v1.6.5+ with I2Cdev Fastwire implementation is recommended.
             #warning This I2Cdev implementation does not support:
             #warning - Repeated starts conditions
             #warning - Timeout detection (some Wire requests block forever)
         #elif ARDUINO > 100
-            #warning Using current Arduino IDE with Wire library is functionally limiting.
-            #warning Arduino IDE v1.0.1+ with I2CDEV_BUILTIN_FASTWIRE implementation is recommended.
+            /*#warning Using current Arduino IDE with Wire library is functionally limiting.
+            #warning Arduino IDE v1.6.5+ with I2CDEV_BUILTIN_FASTWIRE implementation is recommended.
             #warning This I2Cdev implementation does not support:
-            #warning - Timeout detection (some Wire requests block forever)
+            #warning - Timeout detection (some Wire requests block forever)*/
         #endif
     #endif
 
diff --git a/Arduino/I2Cdev/I2Cdev.h b/Arduino/I2Cdev/I2Cdev.h
index 224767c7..e906fbb5 100644
--- a/Arduino/I2Cdev/I2Cdev.h
+++ b/Arduino/I2Cdev/I2Cdev.h
@@ -1,6 +1,6 @@
 // I2Cdev library collection - Main I2C device class header file
 // Abstracts bit and byte I2C R/W functions into a convenient class
-// 6/9/2012 by Jeff Rowberg 
+// 2013-06-05 by Jeff Rowberg 
 //
 // Changelog:
 //      2013-05-06 - add Francesco Ferrara's Fastwire v0.24 implementation with small modifications

From 5b578596dfc1efcf1b816ac7c94fd907d41af460 Mon Sep 17 00:00:00 2001
From: Ilann 
Date: Mon, 20 Jul 2015 17:54:59 +0200
Subject: [PATCH 083/335] Update MPU6050_6Axis_MotionApps20.h

---
 Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h
index 04aac2b8..98f062bb 100644
--- a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h
+++ b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h
@@ -362,11 +362,11 @@ uint8_t MPU6050::dmpInitialize() {
     int8_t ygOffsetTC = getYGyroOffsetTC();
     int8_t zgOffsetTC = getZGyroOffsetTC();
     DEBUG_PRINT(F("X gyro offset = "));
-    DEBUG_PRINTLN(xgOffset);
+    DEBUG_PRINTLN(xgOffsetTC);
     DEBUG_PRINT(F("Y gyro offset = "));
-    DEBUG_PRINTLN(ygOffset);
+    DEBUG_PRINTLN(ygOffsetTC);
     DEBUG_PRINT(F("Z gyro offset = "));
-    DEBUG_PRINTLN(zgOffset);
+    DEBUG_PRINTLN(zgOffsetTC);
 
     // setup weird slave stuff (?)
     DEBUG_PRINTLN(F("Setting slave 0 address to 0x7F..."));

From 7484beb62fb43210aa6b0b09f8ea213ae2e556e2 Mon Sep 17 00:00:00 2001
From: neon-izm 
Date: Tue, 4 Aug 2015 22:55:42 +0900
Subject: [PATCH 084/335] modify for Arduino IDE 1.6 compatibility

Same as MPU6050
---
 Arduino/MPU9150/MPU9150_9Axis_MotionApps41.h | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/Arduino/MPU9150/MPU9150_9Axis_MotionApps41.h b/Arduino/MPU9150/MPU9150_9Axis_MotionApps41.h
index b75df215..4272ec20 100644
--- a/Arduino/MPU9150/MPU9150_9Axis_MotionApps41.h
+++ b/Arduino/MPU9150/MPU9150_9Axis_MotionApps41.h
@@ -58,7 +58,7 @@ THE SOFTWARE.
 
         typedef void prog_void;
         typedef char prog_char;
-        typedef unsigned char prog_uchar;
+//        typedef unsigned char unsigned char;
         typedef int8_t prog_int8_t;
         typedef uint8_t prog_uint8_t;
         typedef int16_t prog_int16_t;
@@ -121,7 +121,7 @@ THE SOFTWARE.
 // this block of memory gets written to the MPU on start-up, and it seems
 // to be volatile memory, so it has to be done each time (it only takes ~1
 // second though)
-const prog_uchar dmpMemory[MPU9150_DMP_CODE_SIZE] PROGMEM = {
+const unsigned char dmpMemory[MPU9150_DMP_CODE_SIZE] PROGMEM = {
     // bank 0, 256 bytes
     0xFB, 0x00, 0x00, 0x3E, 0x00, 0x0B, 0x00, 0x36, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00,
     0x00, 0x65, 0x00, 0x54, 0xFF, 0xEF, 0x00, 0x00, 0xFA, 0x80, 0x00, 0x0B, 0x12, 0x82, 0x00, 0x01,
@@ -262,7 +262,7 @@ const prog_uchar dmpMemory[MPU9150_DMP_CODE_SIZE] PROGMEM = {
     0xDC, 0xB9, 0xA7, 0xF1, 0x26, 0x26, 0x26, 0xD8, 0xD8, 0xFF
 };
 
-const prog_uchar dmpConfig[MPU9150_DMP_CONFIG_SIZE] PROGMEM = {
+const unsigned char dmpConfig[MPU9150_DMP_CONFIG_SIZE] PROGMEM = {
 //  BANK    OFFSET  LENGTH  [DATA]
     0x02,   0xEC,   0x04,   0x00, 0x47, 0x7D, 0x1A,   // ?
     0x03,   0x82,   0x03,   0x4C, 0xCD, 0x6C,         // FCFG_1 inv_set_gyro_calibration
@@ -312,7 +312,7 @@ const prog_uchar dmpConfig[MPU9150_DMP_CONFIG_SIZE] PROGMEM = {
     // the FIFO output at the desired rate. Handling FIFO overflow cleanly is also a good idea.
 };
 
-const prog_uchar dmpUpdates[MPU9150_DMP_UPDATES_SIZE] PROGMEM = {
+const unsigned char dmpUpdates[MPU9150_DMP_UPDATES_SIZE] PROGMEM = {
     0x01,   0xB2,   0x02,   0xFF, 0xF5,
     0x01,   0x90,   0x04,   0x0A, 0x0D, 0x97, 0xC0,
     0x00,   0xA3,   0x01,   0x00,

From b5706f6e430959bb487137632d3cec2699739783 Mon Sep 17 00:00:00 2001
From: neon-izm 
Date: Tue, 4 Aug 2015 22:57:48 +0900
Subject: [PATCH 085/335] add MPU9150_DMP9.ino sample

same as MPU6050_DMP6.ino
comment out gyro and accel offset
---
 .../Examples/MPU9150_DMP9/MPU9150_DMP9.ino    | 372 ++++++++++++++++++
 1 file changed, 372 insertions(+)
 create mode 100644 Arduino/MPU9150/Examples/MPU9150_DMP9/MPU9150_DMP9.ino

diff --git a/Arduino/MPU9150/Examples/MPU9150_DMP9/MPU9150_DMP9.ino b/Arduino/MPU9150/Examples/MPU9150_DMP9/MPU9150_DMP9.ino
new file mode 100644
index 00000000..34852fd4
--- /dev/null
+++ b/Arduino/MPU9150/Examples/MPU9150_DMP9/MPU9150_DMP9.ino
@@ -0,0 +1,372 @@
+// I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class using DMP (MotionApps v2.0)
+// 6/21/2012 by Jeff Rowberg 
+// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
+//
+// Changelog:
+//      2015-08-03 - added Arduino 1.6 support
+//      2013-05-08 - added seamless Fastwire support
+//                 - added note about gyro calibration
+//      2012-06-21 - added note about Arduino 1.0.1 + Leonardo compatibility error
+//      2012-06-20 - improved FIFO overflow handling and simplified read process
+//      2012-06-19 - completely rearranged DMP initialization code and simplification
+//      2012-06-13 - pull gyro and accel data from FIFO packet instead of reading directly
+//      2012-06-09 - fix broken FIFO read sequence and change interrupt detection to RISING
+//      2012-06-05 - add gravity-compensated initial reference frame acceleration output
+//                 - add 3D math helper file to DMP6 example sketch
+//                 - add Euler output and Yaw/Pitch/Roll output formats
+//      2012-06-04 - remove accel offset clearing for better results (thanks Sungon Lee)
+//      2012-06-01 - fixed gyro sensitivity to be 2000 deg/sec instead of 250
+//      2012-05-30 - basic DMP initialization working
+
+/* ============================================
+I2Cdev device library code is placed under the MIT license
+Copyright (c) 2012 Jeff Rowberg
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+===============================================
+*/
+
+// I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files
+// for both classes must be in the include path of your project
+#include "I2Cdev.h"
+
+#include "MPU9150_9Axis_MotionApps41.h"
+//#include "MPU6050.h" // not necessary if using MotionApps include file
+
+// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation
+// is used in I2Cdev.h
+#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
+    #include "Wire.h"
+#endif
+
+// class default I2C address is 0x68
+// specific I2C addresses may be passed as a parameter here
+// AD0 low = 0x68 (default for SparkFun breakout and InvenSense evaluation board)
+// AD0 high = 0x69
+MPU9150 mpu;
+//MPU6050 mpu(0x69); // <-- use for AD0 high
+
+/* =========================================================================
+   NOTE: In addition to connection 3.3v, GND, SDA, and SCL, this sketch
+   depends on the MPU-6050's INT pin being connected to the Arduino's
+   external interrupt #0 pin. On the Arduino Uno and Mega 2560, this is
+   digital I/O pin 2.
+ * ========================================================================= */
+
+/* =========================================================================
+   NOTE: Arduino v1.0.1 with the Leonardo board generates a compile error
+   when using Serial.write(buf, len). The Teapot output uses this method.
+   The solution requires a modification to the Arduino USBAPI.h file, which
+   is fortunately simple, but annoying. This will be fixed in the next IDE
+   release. For more info, see these links:
+
+   http://arduino.cc/forum/index.php/topic,109987.0.html
+   http://code.google.com/p/arduino/issues/detail?id=958
+ * ========================================================================= */
+
+
+
+// uncomment "OUTPUT_READABLE_QUATERNION" if you want to see the actual
+// quaternion components in a [w, x, y, z] format (not best for parsing
+// on a remote host such as Processing or something though)
+//#define OUTPUT_READABLE_QUATERNION
+
+// uncomment "OUTPUT_READABLE_EULER" if you want to see Euler angles
+// (in degrees) calculated from the quaternions coming from the FIFO.
+// Note that Euler angles suffer from gimbal lock (for more info, see
+// http://en.wikipedia.org/wiki/Gimbal_lock)
+//#define OUTPUT_READABLE_EULER
+
+// uncomment "OUTPUT_READABLE_YAWPITCHROLL" if you want to see the yaw/
+// pitch/roll angles (in degrees) calculated from the quaternions coming
+// from the FIFO. Note this also requires gravity vector calculations.
+// Also note that yaw/pitch/roll angles suffer from gimbal lock (for
+// more info, see: http://en.wikipedia.org/wiki/Gimbal_lock)
+#define OUTPUT_READABLE_YAWPITCHROLL
+
+// uncomment "OUTPUT_READABLE_REALACCEL" if you want to see acceleration
+// components with gravity removed. This acceleration reference frame is
+// not compensated for orientation, so +X is always +X according to the
+// sensor, just without the effects of gravity. If you want acceleration
+// compensated for orientation, us OUTPUT_READABLE_WORLDACCEL instead.
+//#define OUTPUT_READABLE_REALACCEL
+
+// uncomment "OUTPUT_READABLE_WORLDACCEL" if you want to see acceleration
+// components with gravity removed and adjusted for the world frame of
+// reference (yaw is relative to initial orientation, since no magnetometer
+// is present in this case). Could be quite handy in some cases.
+//#define OUTPUT_READABLE_WORLDACCEL
+
+// uncomment "OUTPUT_TEAPOT" if you want output that matches the
+// format used for the InvenSense teapot demo
+//#define OUTPUT_TEAPOT
+
+
+#define LED_PIN 13 // (Arduino is 13, Teensy is 11, Teensy++ is 6)
+bool blinkState = false;
+
+// MPU control/status vars
+bool dmpReady = false;  // set true if DMP init was successful
+uint8_t mpuIntStatus;   // holds actual interrupt status byte from MPU
+uint8_t devStatus;      // return status after each device operation (0 = success, !0 = error)
+uint16_t packetSize;    // expected DMP packet size (default is 42 bytes)
+uint16_t fifoCount;     // count of all bytes currently in FIFO
+uint8_t fifoBuffer[64]; // FIFO storage buffer
+
+// orientation/motion vars
+Quaternion q;           // [w, x, y, z]         quaternion container
+VectorInt16 aa;         // [x, y, z]            accel sensor measurements
+VectorInt16 aaReal;     // [x, y, z]            gravity-free accel sensor measurements
+VectorInt16 aaWorld;    // [x, y, z]            world-frame accel sensor measurements
+VectorFloat gravity;    // [x, y, z]            gravity vector
+float euler[3];         // [psi, theta, phi]    Euler angle container
+float ypr[3];           // [yaw, pitch, roll]   yaw/pitch/roll container and gravity vector
+
+// packet structure for InvenSense teapot demo
+uint8_t teapotPacket[14] = { '$', 0x02, 0,0, 0,0, 0,0, 0,0, 0x00, 0x00, '\r', '\n' };
+
+
+
+// ================================================================
+// ===               INTERRUPT DETECTION ROUTINE                ===
+// ================================================================
+
+volatile bool mpuInterrupt = false;     // indicates whether MPU interrupt pin has gone high
+void dmpDataReady() {
+    mpuInterrupt = true;
+}
+
+
+
+// ================================================================
+// ===                      INITIAL SETUP                       ===
+// ================================================================
+
+void setup() { 
+    // join I2C bus (I2Cdev library doesn't do this automatically)
+    #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
+        Wire.begin();
+        TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz)
+    #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
+        Fastwire::setup(400, true);
+    #endif
+
+    // initialize serial communication
+    // (115200 chosen because it is required for Teapot Demo output, but it's
+    // really up to you depending on your project)
+    Serial.begin(115200);
+    while (!Serial); // wait for Leonardo enumeration, others continue immediately
+
+    // NOTE: 8MHz or slower host processors, like the Teensy @ 3.3v or Ardunio
+    // Pro Mini running at 3.3v, cannot handle this baud rate reliably due to
+    // the baud timing being too misaligned with processor ticks. You must use
+    // 38400 or slower in these cases, or use some kind of external separate
+    // crystal solution for the UART timer.
+
+    // initialize device
+    Serial.println(F("Initializing I2C devices..."));
+    mpu.initialize();
+
+    // verify connection
+    Serial.println(F("Testing device connections..."));
+    Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));
+
+    // wait for ready
+    Serial.println(F("\nSend any character to begin DMP programming and demo: "));
+   // while (Serial.available() && Serial.read()); // empty buffer
+   // while (!Serial.available());                 // wait for data
+   // while (Serial.available() && Serial.read()); // empty buffer again
+
+    // load and configure the DMP
+    Serial.println(F("Initializing DMP..."));
+    devStatus = mpu.dmpInitialize();
+
+  // supply your own gyro offsets here, scaled for min sensitivity
+  //   mpu.setXGyroOffset(220);
+  //  mpu.setYGyroOffset(76);
+  //  mpu.setZGyroOffset(-85);
+  // mpu.setZAccelOffset(1788); // 1688 factory default for my test chip
+
+    // make sure it worked (returns 0 if so)
+    if (devStatus == 0) {
+        // turn on the DMP, now that it's ready
+        Serial.println(F("Enabling DMP..."));
+        mpu.setDMPEnabled(true);
+
+        // enable Arduino interrupt detection
+        Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)..."));
+        attachInterrupt(0, dmpDataReady, RISING);
+        mpuIntStatus = mpu.getIntStatus();
+
+        // set our DMP Ready flag so the main loop() function knows it's okay to use it
+        Serial.println(F("DMP ready! Waiting for first interrupt..."));
+        dmpReady = true;
+
+        // get expected DMP packet size for later comparison
+        packetSize = mpu.dmpGetFIFOPacketSize();
+    } else {
+        // ERROR!
+        // 1 = initial memory load failed
+        // 2 = DMP configuration updates failed
+        // (if it's going to break, usually the code will be 1)
+        Serial.print(F("DMP Initialization failed (code "));
+        Serial.print(devStatus);
+        Serial.println(F(")"));
+    }
+
+    // configure LED for output
+    pinMode(LED_PIN, OUTPUT);
+}
+
+
+
+// ================================================================
+// ===                    MAIN PROGRAM LOOP                     ===
+// ================================================================
+
+void loop() {
+    // if programming failed, don't try to do anything
+    if (!dmpReady) return;
+
+    // wait for MPU interrupt or extra packet(s) available
+    while (!mpuInterrupt && fifoCount < packetSize) {
+        // other program behavior stuff here
+        // .
+        // .
+        // .
+        // if you are really paranoid you can frequently test in between other
+        // stuff to see if mpuInterrupt is true, and if so, "break;" from the
+        // while() loop to immediately process the MPU data
+        // .
+        // .
+        // .
+    }
+
+    // reset interrupt flag and get INT_STATUS byte
+    mpuInterrupt = false;
+    mpuIntStatus = mpu.getIntStatus();
+
+    // get current FIFO count
+    fifoCount = mpu.getFIFOCount();
+
+    // check for overflow (this should never happen unless our code is too inefficient)
+    if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
+        // reset so we can continue cleanly
+        mpu.resetFIFO();
+        Serial.println(F("FIFO overflow!"));
+
+    // otherwise, check for DMP data ready interrupt (this should happen frequently)
+    } else if (mpuIntStatus & 0x02) {
+        // wait for correct available data length, should be a VERY short wait
+        while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();
+
+        // read a packet from FIFO
+        mpu.getFIFOBytes(fifoBuffer, packetSize);
+        
+        // track FIFO count here in case there is > 1 packet available
+        // (this lets us immediately read more without waiting for an interrupt)
+        fifoCount -= packetSize;
+
+        #ifdef OUTPUT_READABLE_QUATERNION
+            // display quaternion values in easy matrix form: w x y z
+            mpu.dmpGetQuaternion(&q, fifoBuffer);
+            Serial.print("quat\t");
+            Serial.print(q.w);
+            Serial.print("\t");
+            Serial.print(q.x);
+            Serial.print("\t");
+            Serial.print(q.y);
+            Serial.print("\t");
+            Serial.println(q.z);
+        #endif
+
+        #ifdef OUTPUT_READABLE_EULER
+            // display Euler angles in degrees
+            mpu.dmpGetQuaternion(&q, fifoBuffer);
+            mpu.dmpGetEuler(euler, &q);
+            Serial.print("euler\t");
+            Serial.print(euler[0] * 180/M_PI);
+            Serial.print("\t");
+            Serial.print(euler[1] * 180/M_PI);
+            Serial.print("\t");
+            Serial.println(euler[2] * 180/M_PI);
+        #endif
+
+        #ifdef OUTPUT_READABLE_YAWPITCHROLL
+            // display Euler angles in degrees
+            mpu.dmpGetQuaternion(&q, fifoBuffer);
+            mpu.dmpGetGravity(&gravity, &q);
+            mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
+            Serial.print("ypr\t");
+            Serial.print(ypr[0] * 180/M_PI);
+            Serial.print("\t");
+            Serial.print(ypr[1] * 180/M_PI);
+            Serial.print("\t");
+            Serial.println(ypr[2] * 180/M_PI);
+        #endif
+
+        #ifdef OUTPUT_READABLE_REALACCEL
+            // display real acceleration, adjusted to remove gravity
+            mpu.dmpGetQuaternion(&q, fifoBuffer);
+            mpu.dmpGetAccel(&aa, fifoBuffer);
+            mpu.dmpGetGravity(&gravity, &q);
+            mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity);
+            Serial.print("areal\t");
+            Serial.print(aaReal.x);
+            Serial.print("\t");
+            Serial.print(aaReal.y);
+            Serial.print("\t");
+            Serial.println(aaReal.z);
+        #endif
+
+        #ifdef OUTPUT_READABLE_WORLDACCEL
+            // display initial world-frame acceleration, adjusted to remove gravity
+            // and rotated based on known orientation from quaternion
+            mpu.dmpGetQuaternion(&q, fifoBuffer);
+            mpu.dmpGetAccel(&aa, fifoBuffer);
+            mpu.dmpGetGravity(&gravity, &q);
+            mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity);
+            mpu.dmpGetLinearAccelInWorld(&aaWorld, &aaReal, &q);
+            Serial.print("aworld\t");
+            Serial.print(aaWorld.x);
+            Serial.print("\t");
+            Serial.print(aaWorld.y);
+            Serial.print("\t");
+            Serial.println(aaWorld.z);
+        #endif
+    
+        #ifdef OUTPUT_TEAPOT
+            // display quaternion values in InvenSense Teapot demo format:
+            teapotPacket[2] = fifoBuffer[0];
+            teapotPacket[3] = fifoBuffer[1];
+            teapotPacket[4] = fifoBuffer[4];
+            teapotPacket[5] = fifoBuffer[5];
+            teapotPacket[6] = fifoBuffer[8];
+            teapotPacket[7] = fifoBuffer[9];
+            teapotPacket[8] = fifoBuffer[12];
+            teapotPacket[9] = fifoBuffer[13];
+            Serial.write(teapotPacket, 14);
+            teapotPacket[11]++; // packetCount, loops at 0xFF on purpose
+        #endif
+
+        // blink LED to indicate activity
+        blinkState = !blinkState;
+        digitalWrite(LED_PIN, blinkState);
+    }
+}

From bac4c442c7b74a3bd3dc40e873971eb93136a911 Mon Sep 17 00:00:00 2001
From: Jeff Rowberg 
Date: Sun, 6 Sep 2015 22:22:16 -0400
Subject: [PATCH 086/335] Fix non-closed 
 tag, thanks to Morten Juelsgaard

---
 Arduino/MPU6050/MPU6050.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Arduino/MPU6050/MPU6050.cpp b/Arduino/MPU6050/MPU6050.cpp
index b0a36dcf..1e38451a 100644
--- a/Arduino/MPU6050/MPU6050.cpp
+++ b/Arduino/MPU6050/MPU6050.cpp
@@ -2560,7 +2560,7 @@ void MPU6050::setClockSource(uint8_t source) {
  * 1            | 2.5 Hz
  * 2            | 5 Hz
  * 3            | 10 Hz
- * 
+ * 
* * For further information regarding the MPU-60X0's power modes, please refer to * Register 107. From 8963c5d4ca029522a1c1b8e1bb0a245d6fbf4fd1 Mon Sep 17 00:00:00 2001 From: Jens Hauke Date: Mon, 21 Sep 2015 20:20:59 +0200 Subject: [PATCH 087/335] Fix int32_t variants of MPU6050::dmpGetAccel,dmpGetQuaternion and dmpGetGyro. Without this patch, the (int32_t *data) variants of MPU6050::dmpGetAccel, MPU6050::dmpGetQuaternion and MPU6050::dmpGetGyro will only return the low bits 0-15. The shift left 24 and 16 of packet[x] will always result to 0, cause AVR/Arduino uses a 16bit integer. With the cast to uint32_t, we get also the bits 16-31 into the data[] fields. This fixes also the warnings: /home/.../MPU6050/MPU6050_6Axis_MotionApps20.h:580:31: warning: left shift count >= width of type data[0] = ((packet[28] << 24) + (packet[29] << 16) + (packet[30] << 8) + packet[31]); --- Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h | 20 ++++++++++---------- Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h | 20 ++++++++++---------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h index 98f062bb..1c0391cf 100644 --- a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h +++ b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h @@ -577,9 +577,9 @@ bool MPU6050::dmpPacketAvailable() { uint8_t MPU6050::dmpGetAccel(int32_t *data, const uint8_t* packet) { // TODO: accommodate different arrangements of sent data (ONLY default supported now) if (packet == 0) packet = dmpPacketBuffer; - data[0] = ((packet[28] << 24) + (packet[29] << 16) + (packet[30] << 8) + packet[31]); - data[1] = ((packet[32] << 24) + (packet[33] << 16) + (packet[34] << 8) + packet[35]); - data[2] = ((packet[36] << 24) + (packet[37] << 16) + (packet[38] << 8) + packet[39]); + data[0] = (((uint32_t)packet[28] << 24) + ((uint32_t)packet[29] << 16) + ((uint32_t)packet[30] << 8) + packet[31]); + data[1] = (((uint32_t)packet[32] << 24) + ((uint32_t)packet[33] << 16) + ((uint32_t)packet[34] << 8) + packet[35]); + data[2] = (((uint32_t)packet[36] << 24) + ((uint32_t)packet[37] << 16) + ((uint32_t)packet[38] << 8) + packet[39]); return 0; } uint8_t MPU6050::dmpGetAccel(int16_t *data, const uint8_t* packet) { @@ -601,10 +601,10 @@ uint8_t MPU6050::dmpGetAccel(VectorInt16 *v, const uint8_t* packet) { uint8_t MPU6050::dmpGetQuaternion(int32_t *data, const uint8_t* packet) { // TODO: accommodate different arrangements of sent data (ONLY default supported now) if (packet == 0) packet = dmpPacketBuffer; - data[0] = ((packet[0] << 24) + (packet[1] << 16) + (packet[2] << 8) + packet[3]); - data[1] = ((packet[4] << 24) + (packet[5] << 16) + (packet[6] << 8) + packet[7]); - data[2] = ((packet[8] << 24) + (packet[9] << 16) + (packet[10] << 8) + packet[11]); - data[3] = ((packet[12] << 24) + (packet[13] << 16) + (packet[14] << 8) + packet[15]); + data[0] = (((uint32_t)packet[0] << 24) + ((uint32_t)packet[1] << 16) + ((uint32_t)packet[2] << 8) + packet[3]); + data[1] = (((uint32_t)packet[4] << 24) + ((uint32_t)packet[5] << 16) + ((uint32_t)packet[6] << 8) + packet[7]); + data[2] = (((uint32_t)packet[8] << 24) + ((uint32_t)packet[9] << 16) + ((uint32_t)packet[10] << 8) + packet[11]); + data[3] = (((uint32_t)packet[12] << 24) + ((uint32_t)packet[13] << 16) + ((uint32_t)packet[14] << 8) + packet[15]); return 0; } uint8_t MPU6050::dmpGetQuaternion(int16_t *data, const uint8_t* packet) { @@ -634,9 +634,9 @@ uint8_t MPU6050::dmpGetQuaternion(Quaternion *q, const uint8_t* packet) { uint8_t MPU6050::dmpGetGyro(int32_t *data, const uint8_t* packet) { // TODO: accommodate different arrangements of sent data (ONLY default supported now) if (packet == 0) packet = dmpPacketBuffer; - data[0] = ((packet[16] << 24) + (packet[17] << 16) + (packet[18] << 8) + packet[19]); - data[1] = ((packet[20] << 24) + (packet[21] << 16) + (packet[22] << 8) + packet[23]); - data[2] = ((packet[24] << 24) + (packet[25] << 16) + (packet[26] << 8) + packet[27]); + data[0] = (((uint32_t)packet[16] << 24) + ((uint32_t)packet[17] << 16) + ((uint32_t)packet[18] << 8) + packet[19]); + data[1] = (((uint32_t)packet[20] << 24) + ((uint32_t)packet[21] << 16) + ((uint32_t)packet[22] << 8) + packet[23]); + data[2] = (((uint32_t)packet[24] << 24) + ((uint32_t)packet[25] << 16) + ((uint32_t)packet[26] << 8) + packet[27]); return 0; } uint8_t MPU6050::dmpGetGyro(int16_t *data, const uint8_t* packet) { diff --git a/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h b/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h index aadc0602..81f38af1 100644 --- a/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h +++ b/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h @@ -680,9 +680,9 @@ bool MPU6050::dmpPacketAvailable() { uint8_t MPU6050::dmpGetAccel(int32_t *data, const uint8_t* packet) { // TODO: accommodate different arrangements of sent data (ONLY default supported now) if (packet == 0) packet = dmpPacketBuffer; - data[0] = ((packet[34] << 24) + (packet[35] << 16) + (packet[36] << 8) + packet[37]); - data[1] = ((packet[38] << 24) + (packet[39] << 16) + (packet[40] << 8) + packet[41]); - data[2] = ((packet[42] << 24) + (packet[43] << 16) + (packet[44] << 8) + packet[45]); + data[0] = (((uint32_t)packet[34] << 24) + ((uint32_t)packet[35] << 16) + ((uint32_t)packet[36] << 8) + packet[37]); + data[1] = (((uint32_t)packet[38] << 24) + ((uint32_t)packet[39] << 16) + ((uint32_t)packet[40] << 8) + packet[41]); + data[2] = (((uint32_t)packet[42] << 24) + ((uint32_t)packet[43] << 16) + ((uint32_t)packet[44] << 8) + packet[45]); return 0; } uint8_t MPU6050::dmpGetAccel(int16_t *data, const uint8_t* packet) { @@ -704,10 +704,10 @@ uint8_t MPU6050::dmpGetAccel(VectorInt16 *v, const uint8_t* packet) { uint8_t MPU6050::dmpGetQuaternion(int32_t *data, const uint8_t* packet) { // TODO: accommodate different arrangements of sent data (ONLY default supported now) if (packet == 0) packet = dmpPacketBuffer; - data[0] = ((packet[0] << 24) + (packet[1] << 16) + (packet[2] << 8) + packet[3]); - data[1] = ((packet[4] << 24) + (packet[5] << 16) + (packet[6] << 8) + packet[7]); - data[2] = ((packet[8] << 24) + (packet[9] << 16) + (packet[10] << 8) + packet[11]); - data[3] = ((packet[12] << 24) + (packet[13] << 16) + (packet[14] << 8) + packet[15]); + data[0] = (((uint32_t)packet[0] << 24) + ((uint32_t)packet[1] << 16) + ((uint32_t)packet[2] << 8) + packet[3]); + data[1] = (((uint32_t)packet[4] << 24) + ((uint32_t)packet[5] << 16) + ((uint32_t)packet[6] << 8) + packet[7]); + data[2] = (((uint32_t)packet[8] << 24) + ((uint32_t)packet[9] << 16) + ((uint32_t)packet[10] << 8) + packet[11]); + data[3] = (((uint32_t)packet[12] << 24) + ((uint32_t)packet[13] << 16) + ((uint32_t)packet[14] << 8) + packet[15]); return 0; } uint8_t MPU6050::dmpGetQuaternion(int16_t *data, const uint8_t* packet) { @@ -737,9 +737,9 @@ uint8_t MPU6050::dmpGetQuaternion(Quaternion *q, const uint8_t* packet) { uint8_t MPU6050::dmpGetGyro(int32_t *data, const uint8_t* packet) { // TODO: accommodate different arrangements of sent data (ONLY default supported now) if (packet == 0) packet = dmpPacketBuffer; - data[0] = ((packet[16] << 24) + (packet[17] << 16) + (packet[18] << 8) + packet[19]); - data[1] = ((packet[20] << 24) + (packet[21] << 16) + (packet[22] << 8) + packet[23]); - data[2] = ((packet[24] << 24) + (packet[25] << 16) + (packet[26] << 8) + packet[27]); + data[0] = (((uint32_t)packet[16] << 24) + ((uint32_t)packet[17] << 16) + ((uint32_t)packet[18] << 8) + packet[19]); + data[1] = (((uint32_t)packet[20] << 24) + ((uint32_t)packet[21] << 16) + ((uint32_t)packet[22] << 8) + packet[23]); + data[2] = (((uint32_t)packet[24] << 24) + ((uint32_t)packet[25] << 16) + ((uint32_t)packet[26] << 8) + packet[27]); return 0; } uint8_t MPU6050::dmpGetGyro(int16_t *data, const uint8_t* packet) { From 5631a7a8bf96bfdeac009f86ff6eca6f04c4d222 Mon Sep 17 00:00:00 2001 From: Jens Hauke Date: Mon, 21 Sep 2015 20:26:32 +0200 Subject: [PATCH 088/335] MPU6050: Merge fifo bytes with "|" instead of "+". Using "|" instead of "+" reduces the code size a little. --- Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h | 52 ++++++++++---------- Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h | 52 ++++++++++---------- 2 files changed, 52 insertions(+), 52 deletions(-) diff --git a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h index 1c0391cf..37b78417 100644 --- a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h +++ b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h @@ -577,43 +577,43 @@ bool MPU6050::dmpPacketAvailable() { uint8_t MPU6050::dmpGetAccel(int32_t *data, const uint8_t* packet) { // TODO: accommodate different arrangements of sent data (ONLY default supported now) if (packet == 0) packet = dmpPacketBuffer; - data[0] = (((uint32_t)packet[28] << 24) + ((uint32_t)packet[29] << 16) + ((uint32_t)packet[30] << 8) + packet[31]); - data[1] = (((uint32_t)packet[32] << 24) + ((uint32_t)packet[33] << 16) + ((uint32_t)packet[34] << 8) + packet[35]); - data[2] = (((uint32_t)packet[36] << 24) + ((uint32_t)packet[37] << 16) + ((uint32_t)packet[38] << 8) + packet[39]); + data[0] = (((uint32_t)packet[28] << 24) | ((uint32_t)packet[29] << 16) | ((uint32_t)packet[30] << 8) | packet[31]); + data[1] = (((uint32_t)packet[32] << 24) | ((uint32_t)packet[33] << 16) | ((uint32_t)packet[34] << 8) | packet[35]); + data[2] = (((uint32_t)packet[36] << 24) | ((uint32_t)packet[37] << 16) | ((uint32_t)packet[38] << 8) | packet[39]); return 0; } uint8_t MPU6050::dmpGetAccel(int16_t *data, const uint8_t* packet) { // TODO: accommodate different arrangements of sent data (ONLY default supported now) if (packet == 0) packet = dmpPacketBuffer; - data[0] = (packet[28] << 8) + packet[29]; - data[1] = (packet[32] << 8) + packet[33]; - data[2] = (packet[36] << 8) + packet[37]; + data[0] = (packet[28] << 8) | packet[29]; + data[1] = (packet[32] << 8) | packet[33]; + data[2] = (packet[36] << 8) | packet[37]; return 0; } uint8_t MPU6050::dmpGetAccel(VectorInt16 *v, const uint8_t* packet) { // TODO: accommodate different arrangements of sent data (ONLY default supported now) if (packet == 0) packet = dmpPacketBuffer; - v -> x = (packet[28] << 8) + packet[29]; - v -> y = (packet[32] << 8) + packet[33]; - v -> z = (packet[36] << 8) + packet[37]; + v -> x = (packet[28] << 8) | packet[29]; + v -> y = (packet[32] << 8) | packet[33]; + v -> z = (packet[36] << 8) | packet[37]; return 0; } uint8_t MPU6050::dmpGetQuaternion(int32_t *data, const uint8_t* packet) { // TODO: accommodate different arrangements of sent data (ONLY default supported now) if (packet == 0) packet = dmpPacketBuffer; - data[0] = (((uint32_t)packet[0] << 24) + ((uint32_t)packet[1] << 16) + ((uint32_t)packet[2] << 8) + packet[3]); - data[1] = (((uint32_t)packet[4] << 24) + ((uint32_t)packet[5] << 16) + ((uint32_t)packet[6] << 8) + packet[7]); - data[2] = (((uint32_t)packet[8] << 24) + ((uint32_t)packet[9] << 16) + ((uint32_t)packet[10] << 8) + packet[11]); - data[3] = (((uint32_t)packet[12] << 24) + ((uint32_t)packet[13] << 16) + ((uint32_t)packet[14] << 8) + packet[15]); + data[0] = (((uint32_t)packet[0] << 24) | ((uint32_t)packet[1] << 16) | ((uint32_t)packet[2] << 8) | packet[3]); + data[1] = (((uint32_t)packet[4] << 24) | ((uint32_t)packet[5] << 16) | ((uint32_t)packet[6] << 8) | packet[7]); + data[2] = (((uint32_t)packet[8] << 24) | ((uint32_t)packet[9] << 16) | ((uint32_t)packet[10] << 8) | packet[11]); + data[3] = (((uint32_t)packet[12] << 24) | ((uint32_t)packet[13] << 16) | ((uint32_t)packet[14] << 8) | packet[15]); return 0; } uint8_t MPU6050::dmpGetQuaternion(int16_t *data, const uint8_t* packet) { // TODO: accommodate different arrangements of sent data (ONLY default supported now) if (packet == 0) packet = dmpPacketBuffer; - data[0] = ((packet[0] << 8) + packet[1]); - data[1] = ((packet[4] << 8) + packet[5]); - data[2] = ((packet[8] << 8) + packet[9]); - data[3] = ((packet[12] << 8) + packet[13]); + data[0] = ((packet[0] << 8) | packet[1]); + data[1] = ((packet[4] << 8) | packet[5]); + data[2] = ((packet[8] << 8) | packet[9]); + data[3] = ((packet[12] << 8) | packet[13]); return 0; } uint8_t MPU6050::dmpGetQuaternion(Quaternion *q, const uint8_t* packet) { @@ -634,25 +634,25 @@ uint8_t MPU6050::dmpGetQuaternion(Quaternion *q, const uint8_t* packet) { uint8_t MPU6050::dmpGetGyro(int32_t *data, const uint8_t* packet) { // TODO: accommodate different arrangements of sent data (ONLY default supported now) if (packet == 0) packet = dmpPacketBuffer; - data[0] = (((uint32_t)packet[16] << 24) + ((uint32_t)packet[17] << 16) + ((uint32_t)packet[18] << 8) + packet[19]); - data[1] = (((uint32_t)packet[20] << 24) + ((uint32_t)packet[21] << 16) + ((uint32_t)packet[22] << 8) + packet[23]); - data[2] = (((uint32_t)packet[24] << 24) + ((uint32_t)packet[25] << 16) + ((uint32_t)packet[26] << 8) + packet[27]); + data[0] = (((uint32_t)packet[16] << 24) | ((uint32_t)packet[17] << 16) | ((uint32_t)packet[18] << 8) | packet[19]); + data[1] = (((uint32_t)packet[20] << 24) | ((uint32_t)packet[21] << 16) | ((uint32_t)packet[22] << 8) | packet[23]); + data[2] = (((uint32_t)packet[24] << 24) | ((uint32_t)packet[25] << 16) | ((uint32_t)packet[26] << 8) | packet[27]); return 0; } uint8_t MPU6050::dmpGetGyro(int16_t *data, const uint8_t* packet) { // TODO: accommodate different arrangements of sent data (ONLY default supported now) if (packet == 0) packet = dmpPacketBuffer; - data[0] = (packet[16] << 8) + packet[17]; - data[1] = (packet[20] << 8) + packet[21]; - data[2] = (packet[24] << 8) + packet[25]; + data[0] = (packet[16] << 8) | packet[17]; + data[1] = (packet[20] << 8) | packet[21]; + data[2] = (packet[24] << 8) | packet[25]; return 0; } uint8_t MPU6050::dmpGetGyro(VectorInt16 *v, const uint8_t* packet) { // TODO: accommodate different arrangements of sent data (ONLY default supported now) if (packet == 0) packet = dmpPacketBuffer; - v -> x = (packet[16] << 8) + packet[17]; - v -> y = (packet[20] << 8) + packet[21]; - v -> z = (packet[24] << 8) + packet[25]; + v -> x = (packet[16] << 8) | packet[17]; + v -> y = (packet[20] << 8) | packet[21]; + v -> z = (packet[24] << 8) | packet[25]; return 0; } // uint8_t MPU6050::dmpSetLinearAccelFilterCoefficient(float coef); diff --git a/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h b/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h index 81f38af1..42d3746f 100644 --- a/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h +++ b/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h @@ -680,43 +680,43 @@ bool MPU6050::dmpPacketAvailable() { uint8_t MPU6050::dmpGetAccel(int32_t *data, const uint8_t* packet) { // TODO: accommodate different arrangements of sent data (ONLY default supported now) if (packet == 0) packet = dmpPacketBuffer; - data[0] = (((uint32_t)packet[34] << 24) + ((uint32_t)packet[35] << 16) + ((uint32_t)packet[36] << 8) + packet[37]); - data[1] = (((uint32_t)packet[38] << 24) + ((uint32_t)packet[39] << 16) + ((uint32_t)packet[40] << 8) + packet[41]); - data[2] = (((uint32_t)packet[42] << 24) + ((uint32_t)packet[43] << 16) + ((uint32_t)packet[44] << 8) + packet[45]); + data[0] = (((uint32_t)packet[34] << 24) | ((uint32_t)packet[35] << 16) | ((uint32_t)packet[36] << 8) | packet[37]); + data[1] = (((uint32_t)packet[38] << 24) | ((uint32_t)packet[39] << 16) | ((uint32_t)packet[40] << 8) | packet[41]); + data[2] = (((uint32_t)packet[42] << 24) | ((uint32_t)packet[43] << 16) | ((uint32_t)packet[44] << 8) | packet[45]); return 0; } uint8_t MPU6050::dmpGetAccel(int16_t *data, const uint8_t* packet) { // TODO: accommodate different arrangements of sent data (ONLY default supported now) if (packet == 0) packet = dmpPacketBuffer; - data[0] = (packet[34] << 8) + packet[35]; - data[1] = (packet[38] << 8) + packet[39]; - data[2] = (packet[42] << 8) + packet[43]; + data[0] = (packet[34] << 8) | packet[35]; + data[1] = (packet[38] << 8) | packet[39]; + data[2] = (packet[42] << 8) | packet[43]; return 0; } uint8_t MPU6050::dmpGetAccel(VectorInt16 *v, const uint8_t* packet) { // TODO: accommodate different arrangements of sent data (ONLY default supported now) if (packet == 0) packet = dmpPacketBuffer; - v -> x = (packet[34] << 8) + packet[35]; - v -> y = (packet[38] << 8) + packet[39]; - v -> z = (packet[42] << 8) + packet[43]; + v -> x = (packet[34] << 8) | packet[35]; + v -> y = (packet[38] << 8) | packet[39]; + v -> z = (packet[42] << 8) | packet[43]; return 0; } uint8_t MPU6050::dmpGetQuaternion(int32_t *data, const uint8_t* packet) { // TODO: accommodate different arrangements of sent data (ONLY default supported now) if (packet == 0) packet = dmpPacketBuffer; - data[0] = (((uint32_t)packet[0] << 24) + ((uint32_t)packet[1] << 16) + ((uint32_t)packet[2] << 8) + packet[3]); - data[1] = (((uint32_t)packet[4] << 24) + ((uint32_t)packet[5] << 16) + ((uint32_t)packet[6] << 8) + packet[7]); - data[2] = (((uint32_t)packet[8] << 24) + ((uint32_t)packet[9] << 16) + ((uint32_t)packet[10] << 8) + packet[11]); - data[3] = (((uint32_t)packet[12] << 24) + ((uint32_t)packet[13] << 16) + ((uint32_t)packet[14] << 8) + packet[15]); + data[0] = (((uint32_t)packet[0] << 24) | ((uint32_t)packet[1] << 16) | ((uint32_t)packet[2] << 8) | packet[3]); + data[1] = (((uint32_t)packet[4] << 24) | ((uint32_t)packet[5] << 16) | ((uint32_t)packet[6] << 8) | packet[7]); + data[2] = (((uint32_t)packet[8] << 24) | ((uint32_t)packet[9] << 16) | ((uint32_t)packet[10] << 8) | packet[11]); + data[3] = (((uint32_t)packet[12] << 24) | ((uint32_t)packet[13] << 16) | ((uint32_t)packet[14] << 8) | packet[15]); return 0; } uint8_t MPU6050::dmpGetQuaternion(int16_t *data, const uint8_t* packet) { // TODO: accommodate different arrangements of sent data (ONLY default supported now) if (packet == 0) packet = dmpPacketBuffer; - data[0] = ((packet[0] << 8) + packet[1]); - data[1] = ((packet[4] << 8) + packet[5]); - data[2] = ((packet[8] << 8) + packet[9]); - data[3] = ((packet[12] << 8) + packet[13]); + data[0] = ((packet[0] << 8) | packet[1]); + data[1] = ((packet[4] << 8) | packet[5]); + data[2] = ((packet[8] << 8) | packet[9]); + data[3] = ((packet[12] << 8) | packet[13]); return 0; } uint8_t MPU6050::dmpGetQuaternion(Quaternion *q, const uint8_t* packet) { @@ -737,25 +737,25 @@ uint8_t MPU6050::dmpGetQuaternion(Quaternion *q, const uint8_t* packet) { uint8_t MPU6050::dmpGetGyro(int32_t *data, const uint8_t* packet) { // TODO: accommodate different arrangements of sent data (ONLY default supported now) if (packet == 0) packet = dmpPacketBuffer; - data[0] = (((uint32_t)packet[16] << 24) + ((uint32_t)packet[17] << 16) + ((uint32_t)packet[18] << 8) + packet[19]); - data[1] = (((uint32_t)packet[20] << 24) + ((uint32_t)packet[21] << 16) + ((uint32_t)packet[22] << 8) + packet[23]); - data[2] = (((uint32_t)packet[24] << 24) + ((uint32_t)packet[25] << 16) + ((uint32_t)packet[26] << 8) + packet[27]); + data[0] = (((uint32_t)packet[16] << 24) | ((uint32_t)packet[17] << 16) | ((uint32_t)packet[18] << 8) | packet[19]); + data[1] = (((uint32_t)packet[20] << 24) | ((uint32_t)packet[21] << 16) | ((uint32_t)packet[22] << 8) | packet[23]); + data[2] = (((uint32_t)packet[24] << 24) | ((uint32_t)packet[25] << 16) | ((uint32_t)packet[26] << 8) | packet[27]); return 0; } uint8_t MPU6050::dmpGetGyro(int16_t *data, const uint8_t* packet) { // TODO: accommodate different arrangements of sent data (ONLY default supported now) if (packet == 0) packet = dmpPacketBuffer; - data[0] = (packet[16] << 8) + packet[17]; - data[1] = (packet[20] << 8) + packet[21]; - data[2] = (packet[24] << 8) + packet[25]; + data[0] = (packet[16] << 8) | packet[17]; + data[1] = (packet[20] << 8) | packet[21]; + data[2] = (packet[24] << 8) | packet[25]; return 0; } uint8_t MPU6050::dmpGetMag(int16_t *data, const uint8_t* packet) { // TODO: accommodate different arrangements of sent data (ONLY default supported now) if (packet == 0) packet = dmpPacketBuffer; - data[0] = (packet[28] << 8) + packet[29]; - data[1] = (packet[30] << 8) + packet[31]; - data[2] = (packet[32] << 8) + packet[33]; + data[0] = (packet[28] << 8) | packet[29]; + data[1] = (packet[30] << 8) | packet[31]; + data[2] = (packet[32] << 8) | packet[33]; return 0; } // uint8_t MPU6050::dmpSetLinearAccelFilterCoefficient(float coef); From 076fa2958a75284afd7d3a6d16ab2ca6f22a01df Mon Sep 17 00:00:00 2001 From: Thomas Kilian Date: Fri, 16 Oct 2015 20:15:29 +0200 Subject: [PATCH 089/335] Fix issue with wrong pointer usage --- Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h index 37b78417..46379948 100644 --- a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h +++ b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h @@ -728,7 +728,7 @@ uint8_t MPU6050::dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *proces if ((status = dmpProcessFIFOPacket(buf)) > 0) return status; // increment external process count variable, if supplied - if (processed != 0) *processed++; + if (processed != 0) (*processed)++; } return 0; } From 2b080171e6f2eac13beeacc7a59f32f259e72ab6 Mon Sep 17 00:00:00 2001 From: Thomas Kilian Date: Fri, 16 Oct 2015 20:23:15 +0200 Subject: [PATCH 090/335] Silent warnings about unused variables --- Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h index 46379948..1561c074 100644 --- a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h +++ b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h @@ -344,17 +344,15 @@ uint8_t MPU6050::dmpInitialize() { DEBUG_PRINTLN(F("Selecting memory byte 6...")); setMemoryStartAddress(0x06); DEBUG_PRINTLN(F("Checking hardware revision...")); - uint8_t hwRevision = readMemoryByte(); DEBUG_PRINT(F("Revision @ user[16][6] = ")); - DEBUG_PRINTLNF(hwRevision, HEX); + DEBUG_PRINTLNF(readMemoryByte(), HEX); DEBUG_PRINTLN(F("Resetting memory bank selection to 0...")); setMemoryBank(0, false, false); // check OTP bank valid DEBUG_PRINTLN(F("Reading OTP bank valid flag...")); - uint8_t otpValid = getOTPBankValid(); DEBUG_PRINT(F("OTP bank is ")); - DEBUG_PRINTLN(otpValid ? F("valid!") : F("invalid!")); + DEBUG_PRINTLN(getOTPBankValid() ? F("valid!") : F("invalid!")); // get X/Y/Z gyro offsets DEBUG_PRINTLN(F("Reading gyro offset TC values...")); @@ -494,10 +492,9 @@ uint8_t MPU6050::dmpInitialize() { getFIFOBytes(fifoBuffer, fifoCount); DEBUG_PRINTLN(F("Reading interrupt status...")); - uint8_t mpuIntStatus = getIntStatus(); DEBUG_PRINT(F("Current interrupt status=")); - DEBUG_PRINTLNF(mpuIntStatus, HEX); + DEBUG_PRINTLNF(getIntStatus(), HEX); DEBUG_PRINTLN(F("Reading final memory update 6/7 (function unknown)...")); for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); @@ -513,10 +510,9 @@ uint8_t MPU6050::dmpInitialize() { getFIFOBytes(fifoBuffer, fifoCount); DEBUG_PRINTLN(F("Reading interrupt status...")); - mpuIntStatus = getIntStatus(); DEBUG_PRINT(F("Current interrupt status=")); - DEBUG_PRINTLNF(mpuIntStatus, HEX); + DEBUG_PRINTLNF(getIntStatus(), HEX); DEBUG_PRINTLN(F("Writing final memory update 7/7 (function unknown)...")); for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); From be896172a4cf7f59d0b324795b2dc8534c467955 Mon Sep 17 00:00:00 2001 From: 899NTH Date: Wed, 21 Oct 2015 18:39:19 +0100 Subject: [PATCH 091/335] Do not read 0 bytes from the MPU-6050 FIFO_DATA register Do not attempt to read data from MPU-6050 FIFO if the requested data length is 0. In the MPU-6050 Register Map document (RS-MPU-6000A-00v4.2.pdf) section 4.31, it states that: "The user should check FIFO_COUNT to ensure that the FIFO buffer is not read when empty." --- Arduino/MPU6050/MPU6050.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Arduino/MPU6050/MPU6050.cpp b/Arduino/MPU6050/MPU6050.cpp index 1e38451a..d6ad2057 100644 --- a/Arduino/MPU6050/MPU6050.cpp +++ b/Arduino/MPU6050/MPU6050.cpp @@ -2741,7 +2741,11 @@ uint8_t MPU6050::getFIFOByte() { return buffer[0]; } void MPU6050::getFIFOBytes(uint8_t *data, uint8_t length) { - I2Cdev::readBytes(devAddr, MPU6050_RA_FIFO_R_W, length, data); + if(length > 0){ + I2Cdev::readBytes(devAddr, MPU6050_RA_FIFO_R_W, length, data); + } else { + *data = 0; + } } /** Write byte to FIFO buffer. * @see getFIFOByte() From 99a6bdf963e47b0f2da9b9c2d943d883f9c81022 Mon Sep 17 00:00:00 2001 From: Jeff Rowberg Date: Mon, 2 Nov 2015 22:59:52 -0500 Subject: [PATCH 092/335] Fix error in RasPi "readBits" implementation, fix courtesy of @sgsdxzy --- RaspberryPi_bcm2835/I2Cdev/I2Cdev.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RaspberryPi_bcm2835/I2Cdev/I2Cdev.cpp b/RaspberryPi_bcm2835/I2Cdev/I2Cdev.cpp index 47d7a7a9..2f95338d 100644 --- a/RaspberryPi_bcm2835/I2Cdev/I2Cdev.cpp +++ b/RaspberryPi_bcm2835/I2Cdev/I2Cdev.cpp @@ -86,7 +86,7 @@ int8_t I2Cdev::readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint bcm2835_i2c_setSlaveAddress(devAddr); sendBuf[0] = regAddr; uint8_t response = bcm2835_i2c_write_read_rs(sendBuf, 1, recvBuf, 1); - uint8_t b; + uint8_t b = (uint8_t)recvBuf[0]; if (response == BCM2835_I2C_REASON_OK) { uint8_t mask = ((1 << length) - 1) << (bitStart - length + 1); b &= mask; From ce13fc6a58db764be159e8441e51b7766fc5798c Mon Sep 17 00:00:00 2001 From: Jeff Rowberg Date: Mon, 2 Nov 2015 23:03:42 -0500 Subject: [PATCH 093/335] Fix error in RasPi "readBits" implementation, fix courtesy of @sgsdxzy --- RaspberryPi_bcm2835/I2Cdev/I2Cdev.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RaspberryPi_bcm2835/I2Cdev/I2Cdev.cpp b/RaspberryPi_bcm2835/I2Cdev/I2Cdev.cpp index 2f95338d..599aa765 100644 --- a/RaspberryPi_bcm2835/I2Cdev/I2Cdev.cpp +++ b/RaspberryPi_bcm2835/I2Cdev/I2Cdev.cpp @@ -86,7 +86,7 @@ int8_t I2Cdev::readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint bcm2835_i2c_setSlaveAddress(devAddr); sendBuf[0] = regAddr; uint8_t response = bcm2835_i2c_write_read_rs(sendBuf, 1, recvBuf, 1); - uint8_t b = (uint8_t)recvBuf[0]; + uint8_t b = (uint8_t) recvBuf[0]; if (response == BCM2835_I2C_REASON_OK) { uint8_t mask = ((1 << length) - 1) << (bitStart - length + 1); b &= mask; From f5f6cf3a185c201005b433bf95508f7068d59908 Mon Sep 17 00:00:00 2001 From: Jeff Rowberg Date: Mon, 2 Nov 2015 23:04:24 -0500 Subject: [PATCH 094/335] Add support for i2c_t3 on Teensy 3.1/3.2, courtesy of @simondlevy --- Arduino/I2Cdev/I2Cdev.h | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/Arduino/I2Cdev/I2Cdev.h b/Arduino/I2Cdev/I2Cdev.h index e906fbb5..46cbcf05 100644 --- a/Arduino/I2Cdev/I2Cdev.h +++ b/Arduino/I2Cdev/I2Cdev.h @@ -3,6 +3,7 @@ // 2013-06-05 by Jeff Rowberg // // Changelog: +// 2015-10-30 - simondlevy : support i2c_t3 for Teensy3.1 // 2013-05-06 - add Francesco Ferrara's Fastwire v0.24 implementation with small modifications // 2013-05-05 - fix issue with writing bit values to words (Sasquatch/Farzanegan) // 2012-06-09 - fix major issue with reading > 32 bytes at a time with Arduino Wire @@ -78,7 +79,10 @@ THE SOFTWARE. #else #include "Arduino.h" #endif - #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE + #if defined(CORE_TEENSY) && defined(__MK20DX256__) + #include + #define BUFFER_LENGTH 32 + #elif I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE #include #endif #if I2CDEV_IMPLEMENTATION == I2CDEV_I2CMASTER_LIBRARY @@ -91,13 +95,14 @@ THE SOFTWARE. #define ARDUINO 101 #endif + // 1000ms default read timeout (modify with "I2Cdev::readTimeout = [ms];") #define I2CDEV_DEFAULT_READ_TIMEOUT 1000 class I2Cdev { public: I2Cdev(); - + static int8_t readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout); static int8_t readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout); static int8_t readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout); @@ -126,7 +131,7 @@ class I2Cdev { // Copyright(C) 2012 // Francesco Ferrara ////////////////////// - + /* Master */ #define TW_START 0x08 #define TW_REP_START 0x10 @@ -169,24 +174,24 @@ class I2Cdev { // Originally offered to the i2cdevlib project at http://arduino.cc/forum/index.php/topic,68210.30.html #define NBWIRE_BUFFER_LENGTH 32 - + class TwoWire { private: static uint8_t rxBuffer[]; static uint8_t rxBufferIndex; static uint8_t rxBufferLength; - + static uint8_t txAddress; static uint8_t txBuffer[]; static uint8_t txBufferIndex; static uint8_t txBufferLength; - + // static uint8_t transmitting; static void (*user_onRequest)(void); static void (*user_onReceive)(int); static void onRequestService(void); static void onReceiveService(uint8_t*, int); - + public: TwoWire(); void begin(); @@ -208,25 +213,25 @@ class I2Cdev { void onReceive(void (*)(int)); void onRequest(void (*)(void)); }; - + #define TWI_READY 0 #define TWI_MRX 1 #define TWI_MTX 2 #define TWI_SRX 3 #define TWI_STX 4 - + #define TW_WRITE 0 #define TW_READ 1 - + #define TW_MT_SLA_NACK 0x20 #define TW_MT_DATA_NACK 0x30 - + #define CPU_FREQ 16000000L #define TWI_FREQ 100000L #define TWI_BUFFER_LENGTH 32 - + /* TWI Status is in TWSR, in the top 5 bits: TWS7 - TWS3 */ - + #define TW_STATUS_MASK (_BV(TWS7)|_BV(TWS6)|_BV(TWS5)|_BV(TWS4)|_BV(TWS3)) #define TW_STATUS (TWSR & TW_STATUS_MASK) #define TW_START 0x08 @@ -257,18 +262,18 @@ class I2Cdev { #define TW_SR_STOP 0xA0 #define TW_NO_INFO 0xF8 #define TW_BUS_ERROR 0x00 - + //#define _MMIO_BYTE(mem_addr) (*(volatile uint8_t *)(mem_addr)) //#define _SFR_BYTE(sfr) _MMIO_BYTE(_SFR_ADDR(sfr)) - + #ifndef sbi // set bit #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) #endif // sbi - + #ifndef cbi // clear bit #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) #endif // cbi - + extern TwoWire Wire; #endif // I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE From 501b5887ace5df3529f78ea3ed40946c97295c1c Mon Sep 17 00:00:00 2001 From: thorsten-gehrig Date: Sun, 8 Nov 2015 12:48:43 +0100 Subject: [PATCH 095/335] Update IAQ2000.cpp added TVoc and Status --- Arduino/IAQ2000/IAQ2000.cpp | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/Arduino/IAQ2000/IAQ2000.cpp b/Arduino/IAQ2000/IAQ2000.cpp index 6a538599..e3a2cdfc 100755 --- a/Arduino/IAQ2000/IAQ2000.cpp +++ b/Arduino/IAQ2000/IAQ2000.cpp @@ -7,6 +7,7 @@ // // Changelog: // 2012-04-01 - initial release +// 2012-11-08 - added TVoc and Status /* ============================================ I2Cdev device library code is placed under the MIT license @@ -62,7 +63,7 @@ void IAQ2000::initialize() { * @return True if connection is valid, false otherwise */ bool IAQ2000::testConnection() { - if (getIaq() >= 450) { + if (getIaqpred() >= 450) { return true; } else { @@ -73,12 +74,26 @@ bool IAQ2000::testConnection() { /** Read iAQ-2000 indoor air quality sensor. * @return Predicted CO2 concentration based on human induced volatile organic compounds (VOC) detection (in ppm VOC + CO2 equivalents) */ -uint16_t IAQ2000::getIaq() { - // read bytes from the DATA1 AND DATA2 registers and bit-shifting them into a 16-bit value +uint16_t IAQ2000::getIaqpred() { + // read bytes from the DATA0 AND DATA1 registers and bit-shifting them into a 16-bit value readAllBytes(devAddr, 2, buffer); return ((buffer[0] << 8) | buffer[1]); } +uint8_t IAQ2000::getIaqstatus() { + // read bytes from the DATA2 register + readAllBytes(devAddr, 3, buffer); + return (buffer[2]); +} + +uint16_t IAQ2000::getIaqtvoc() { + // read bytes from the DATA7 AND DATA8 registers and bit-shifting them into a 16-bit value + readAllBytes(devAddr, 9, buffer); + return ((buffer[7] << 8) | buffer[8]); +} + + + /** Read bytes from a slave device. * This is a "stripped-down" version of the standard Jeff Rowberg's I2Cdev::readBytes method * intended to provide compatibility with iAQ-2000, From 830a9aa78cdfcf7b7890230e091d802605db537b Mon Sep 17 00:00:00 2001 From: thorsten-gehrig Date: Sun, 8 Nov 2015 12:50:05 +0100 Subject: [PATCH 096/335] Update IAQ2000.h added TVoc and Status --- Arduino/IAQ2000/IAQ2000.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Arduino/IAQ2000/IAQ2000.h b/Arduino/IAQ2000/IAQ2000.h index 432b3573..86839b22 100755 --- a/Arduino/IAQ2000/IAQ2000.h +++ b/Arduino/IAQ2000/IAQ2000.h @@ -7,6 +7,7 @@ // // Changelog: // 2012-04-01 - initial release +// 2015-11-08 - added TVoc and Status /* ============================================ I2Cdev device library code is placed under the MIT license @@ -48,12 +49,14 @@ class IAQ2000 { IAQ2000(); IAQ2000(uint8_t address); void initialize(); - bool testConnection(); - uint16_t getIaq(); + bool testConnection(); + uint16_t getIaqtvoc(); + uint16_t getIaqpred(); + uint8_t getIaqstatus(); private: uint8_t devAddr; - uint8_t buffer[2]; + uint8_t buffer[8]; int8_t readAllBytes(uint8_t devAddr, uint8_t length, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout); }; From 408a1a357db20801a084ad79a66c93a09e312e6e Mon Sep 17 00:00:00 2001 From: thorsten-gehrig Date: Sun, 8 Nov 2015 12:56:04 +0100 Subject: [PATCH 097/335] Update IAQ2000.ino Added Status and TVOC --- Arduino/IAQ2000/examples/IAQ2000/IAQ2000.ino | 184 +++++++++++++------ 1 file changed, 127 insertions(+), 57 deletions(-) diff --git a/Arduino/IAQ2000/examples/IAQ2000/IAQ2000.ino b/Arduino/IAQ2000/examples/IAQ2000/IAQ2000.ino index bcae91a7..96dcf4f3 100644 --- a/Arduino/IAQ2000/examples/IAQ2000/IAQ2000.ino +++ b/Arduino/IAQ2000/examples/IAQ2000/IAQ2000.ino @@ -5,29 +5,30 @@ // // Changelog: // 2012-04-01 - initial release +// 2015-11-08 - added TVoc and Status /* ============================================ -IAQ2000 device library code is placed under the MIT license -Copyright (c) 2012 Peteris Skorovs, Jeff Rowberg - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -=============================================== + IAQ2000 device library code is placed under the MIT license + Copyright (c) 2012 Peteris Skorovs, Jeff Rowberg + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + =============================================== */ // Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation @@ -39,54 +40,123 @@ THE SOFTWARE. #include "I2Cdev.h" #include "IAQ2000.h" + // class default I2C address is 0x5A // specific I2C addresses may be passed as a parameter here // but this device only supports one I2C address (0x5A) IAQ2000 iaq; uint16_t airQuality; +uint8_t iAQstatus; +uint16_t airTvoc; + +unsigned long startTime; +uint16_t oldairQuality = 0; +uint8_t oldiAQstatus = 0; +uint16_t oldairTvoc = 0; +uint8_t result = 0; + #define LED_PIN 13 bool blinkState = false; + void setup() { - // join I2C bus (I2Cdev library doesn't do this automatically) - Wire.begin(); - - // initialize serial communication - // (38400 chosen because it works as well at 8MHz as it does at 16MHz, but - // it's really up to you depending on your project) - Serial.begin(38400); - - // initialize device - Serial.println("Initializing I2C devices..."); - iaq.initialize(); - - // verify connection - Serial.println("Testing device connections..."); - Serial.println(iaq.testConnection() ? "iAQ-2000 connection successful" : "iAQ-2000 connection failed"); - - // configure LED pin for output - pinMode(LED_PIN, OUTPUT); - -} + // configure LED pin for output + pinMode(LED_PIN, OUTPUT); + // join I2C bus (I2Cdev library doesn't do this automatically) + Wire.begin(); -void loop() { - // read seansor - airQuality = iaq.getIaq(); - - // display predicted CO2 concentration based on human induced volatile organic compounds (VOC) detection (in ppm VOC + CO2 equivalents) - // during the first 6 hours of continuous operation (burn-in) the module will display 450ppm - // the successful burn-in is saved to the EEPROM, the run-in time after restart is 15min - Serial.print("CO2 = "); - Serial.print(airQuality); - Serial.print(" "); - Serial.println("[ppm]"); - - // blink LED to indicate activity + // initialize serial communication + // (38400 chosen because it works as well at 8MHz as it does at 16MHz, but + // it's really up to you depending on your project) + Serial.begin(38400); + delay(1000); + Serial.println("Initializing Serial..."); + delay(1000); + + while (!Serial) { + ; // wait for serial port to connect + } + + startTime = millis(); + + // initialize device + // Serial.println("Initializing I2C devices..."); + + + iaq.initialize(); + if (!iaq.testConnection()) { blinkState = !blinkState; digitalWrite(LED_PIN, blinkState); + delay(500); + } +} - // wait five seconds - delay(5000); -} \ No newline at end of file +void loop() { + + // display predicted CO2 concentration based on human induced volatile organic compounds (VOC) detection (in ppm VOC + CO2 equivalents) + // during the first 6 hours of continuous operation (burn-in) the module will display 450ppm + // the successful burn-in is saved to the EEPROM, the run-in time after restart is 15min + Serial.print("CO2 = "); + Serial.print(airQuality); + Serial.print(" "); + Serial.print("[ppm] 450-2000"); + + // blink LED to indicate activity + blinkState = !blinkState; + digitalWrite(LED_PIN, blinkState); + + // wait five seconds + delay(5000); + + // read seansor + iAQstatus = iaq.getIaqstatus(); + + // display predicted CO2 concentration based on human induced volatile organic compounds (VOC) detection (in ppm VOC + CO2 equivalents) + // during the first 6 hours of continuous operation (burn-in) the module will display 450ppm + // the successful burn-in is saved to the EEPROM, the run-in time after restart is 15min + Serial.print(" -- Status = "); + if (iAQstatus == 0) + { + Serial.print("OK"); + } + if (iAQstatus == 1) + { + Serial.print("BUSY"); + } + if (iAQstatus == 16) + { + Serial.print("WARUMUP"); + } + if (iAQstatus == 128) + { + Serial.print("ERROR"); + } + + // blink LED to indicate activity + blinkState = !blinkState; + digitalWrite(LED_PIN, blinkState); + + // wait five seconds + delay(5000); + + // read seansor + airTvoc = iaq.getIaqtvoc(); + + // display predicted CO2 concentration based on human induced volatile organic compounds (VOC) detection (in ppm VOC + CO2 equivalents) + // during the first 6 hours of continuous operation (burn-in) the module will display 450ppm + // the successful burn-in is saved to the EEPROM, the run-in time after restart is 15min + Serial.print(" -- TVoc = "); + Serial.print(airTvoc); + Serial.print(" "); + Serial.println("[ppb] 125-600"); + + // blink LED to indicate activity + blinkState = !blinkState; + digitalWrite(LED_PIN, blinkState); + + // wait five seconds + delay(5000); + +} From 1ad2e2c7746dced311a576fae464e749fb1fa5dc Mon Sep 17 00:00:00 2001 From: ibmua Date: Mon, 9 Nov 2015 20:53:02 +0200 Subject: [PATCH 098/335] Update MPU6050_DMP6.ino --- Arduino/MPU6050/Examples/MPU6050_DMP6/MPU6050_DMP6.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Arduino/MPU6050/Examples/MPU6050_DMP6/MPU6050_DMP6.ino b/Arduino/MPU6050/Examples/MPU6050_DMP6/MPU6050_DMP6.ino index be24ffd5..84d1ee31 100644 --- a/Arduino/MPU6050/Examples/MPU6050_DMP6/MPU6050_DMP6.ino +++ b/Arduino/MPU6050/Examples/MPU6050_DMP6/MPU6050_DMP6.ino @@ -162,7 +162,7 @@ void setup() { // join I2C bus (I2Cdev library doesn't do this automatically) #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE Wire.begin(); - TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz) + TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz). Comment this line if having compilation difficulties with TWBR. #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE Fastwire::setup(400, true); #endif From 05c1fde1f8e9b7ef5912a7daf4e1045841f2072d Mon Sep 17 00:00:00 2001 From: Paulo Costa Date: Mon, 21 Dec 2015 09:29:15 -0200 Subject: [PATCH 099/335] MPU6050/MPU9150 - ARM is not the only non-AVR type of CPU The conditional PROGMEM code should only be enabled on AVR boards, therefore it makes more sense to check for __AVR__ than __arm__. This fixes the code for use on other CPUs -- In my case, an ESP8266 --- Arduino/MPU6050/MPU6050.h | 2 +- Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h | 2 +- Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h | 2 +- Arduino/MPU9150/MPU9150.h | 2 +- Arduino/MPU9150/MPU9150_9Axis_MotionApps41.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Arduino/MPU6050/MPU6050.h b/Arduino/MPU6050/MPU6050.h index 2c1656cd..6e3b9a76 100644 --- a/Arduino/MPU6050/MPU6050.h +++ b/Arduino/MPU6050/MPU6050.h @@ -42,7 +42,7 @@ THE SOFTWARE. // supporting link: http://forum.arduino.cc/index.php?&topic=143444.msg1079517#msg1079517 // also: http://forum.arduino.cc/index.php?&topic=141571.msg1062899#msg1062899s -#ifndef __arm__ +#ifdef __AVR__ #include #else //#define PROGMEM /* empty */ diff --git a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h index 1561c074..1c055433 100644 --- a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h +++ b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h @@ -43,7 +43,7 @@ THE SOFTWARE. // Tom Carpenter's conditional PROGMEM code // http://forum.arduino.cc/index.php?topic=129407.0 -#ifndef __arm__ +#ifdef __AVR__ #include #else // Teensy 3.0 library conditional PROGMEM code from Paul Stoffregen diff --git a/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h b/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h index 42d3746f..016d0b0d 100644 --- a/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h +++ b/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h @@ -43,7 +43,7 @@ THE SOFTWARE. // Tom Carpenter's conditional PROGMEM code // http://forum.arduino.cc/index.php?topic=129407.0 -#ifndef __arm__ +#ifdef __AVR__ #include #else // Teensy 3.0 library conditional PROGMEM code from Paul Stoffregen diff --git a/Arduino/MPU9150/MPU9150.h b/Arduino/MPU9150/MPU9150.h index e4697db3..ee3e67a2 100644 --- a/Arduino/MPU9150/MPU9150.h +++ b/Arduino/MPU9150/MPU9150.h @@ -41,7 +41,7 @@ THE SOFTWARE. // supporting link: http://forum.arduino.cc/index.php?&topic=143444.msg1079517#msg1079517 // also: http://forum.arduino.cc/index.php?&topic=141571.msg1062899#msg1062899s -#ifndef __arm__ +#ifdef __AVR__ #include #else #define PROGMEM /* empty */ diff --git a/Arduino/MPU9150/MPU9150_9Axis_MotionApps41.h b/Arduino/MPU9150/MPU9150_9Axis_MotionApps41.h index b75df215..21b44ed3 100644 --- a/Arduino/MPU9150/MPU9150_9Axis_MotionApps41.h +++ b/Arduino/MPU9150/MPU9150_9Axis_MotionApps41.h @@ -43,7 +43,7 @@ THE SOFTWARE. // Tom Carpenter's conditional PROGMEM code // http://forum.arduino.cc/index.php?topic=129407.0 -#ifndef __arm__ +#ifdef __AVR__ #include #else // Teensy 3.0 library conditional PROGMEM code from Paul Stoffregen From 5e214163b634d50b2c51e451e35bcded30445ad8 Mon Sep 17 00:00:00 2001 From: James Smith Date: Sat, 2 Jan 2016 20:42:34 -0800 Subject: [PATCH 100/335] Initial support for AK8963 - based on AK8975 code, with updates from datasheet --- Arduino/AK8963/AK8963.cpp | 195 ++++++++++++++++++++++++++++++++++++ Arduino/AK8963/AK8963.h | 146 +++++++++++++++++++++++++++ Arduino/AK8963/library.json | 20 ++++ 3 files changed, 361 insertions(+) create mode 100644 Arduino/AK8963/AK8963.cpp create mode 100644 Arduino/AK8963/AK8963.h create mode 100644 Arduino/AK8963/library.json diff --git a/Arduino/AK8963/AK8963.cpp b/Arduino/AK8963/AK8963.cpp new file mode 100644 index 00000000..b1d715b0 --- /dev/null +++ b/Arduino/AK8963/AK8963.cpp @@ -0,0 +1,195 @@ +// I2Cdev library collection - AK8963 I2C device class header file +// Based on AKM AK8963 datasheet, 10/2013 +// 8/27/2011 by Jeff Rowberg +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// 2016-01-02 - initial release based on AK8975 code +// + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2011 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#include "AK8963.h" + +/** Default constructor, uses default I2C address. + * @see AK8963_DEFAULT_ADDRESS + */ +AK8963::AK8963() { + devAddr = AK8963_DEFAULT_ADDRESS; +} + +/** Specific address constructor. + * @param address I2C address + * @see AK8963_DEFAULT_ADDRESS + * @see AK8963_ADDRESS_00 + */ +AK8963::AK8963(uint8_t address) { + devAddr = address; +} + +/** Power on and prepare for general usage. + * No specific pre-configuration is necessary for this device. + */ +void AK8963::initialize() { +} + +/** Verify the I2C connection. + * Make sure the device is connected and responds as expected. + * @return True if connection is valid, false otherwise + */ +bool AK8963::testConnection() { + if (I2Cdev::readByte(devAddr, AK8963_RA_WIA, buffer) == 1) { + return (buffer[0] == 0x48); + } + return false; +} + +// WIA register + +uint8_t AK8963::getDeviceID() { + I2Cdev::readByte(devAddr, AK8963_RA_WIA, buffer); + return buffer[0]; +} + +// INFO register + +uint8_t AK8963::getInfo() { + I2Cdev::readByte(devAddr, AK8963_RA_INFO, buffer); + return buffer[0]; +} + +// ST1 register + +bool AK8963::getDataReady() { + I2Cdev::readBit(devAddr, AK8963_RA_ST1, AK8963_ST1_DRDY_BIT, buffer); + return buffer[0]; +} + +bool AK8963::getDataOverrun() { + I2Cdev::readBit(devAddr, AK8963_RA_ST1, AK8963_ST1_DOR_BIT, buffer); + return buffer[0]; +} + +// H* registers +void AK8963::getHeading(int16_t *x, int16_t *y, int16_t *z) { + I2Cdev::writeByte(devAddr, AK8963_RA_CNTL1, AK8963_MODE_SINGLE); + delay(10); + I2Cdev::readBytes(devAddr, AK8963_RA_HXL, 6, buffer); + *x = (((int16_t)buffer[1]) << 8) | buffer[0]; + *y = (((int16_t)buffer[3]) << 8) | buffer[2]; + *z = (((int16_t)buffer[5]) << 8) | buffer[4]; +} +int16_t AK8963::getHeadingX() { + I2Cdev::writeByte(devAddr, AK8963_RA_CNTL1, AK8963_MODE_SINGLE); + delay(10); + I2Cdev::readBytes(devAddr, AK8963_RA_HXL, 2, buffer); + return (((int16_t)buffer[1]) << 8) | buffer[0]; +} +int16_t AK8963::getHeadingY() { + I2Cdev::writeByte(devAddr, AK8963_RA_CNTL1, AK8963_MODE_SINGLE); + delay(10); + I2Cdev::readBytes(devAddr, AK8963_RA_HYL, 2, buffer); + return (((int16_t)buffer[1]) << 8) | buffer[0]; +} +int16_t AK8963::getHeadingZ() { + I2Cdev::writeByte(devAddr, AK8963_RA_CNTL1, AK8963_MODE_SINGLE); + delay(10); + I2Cdev::readBytes(devAddr, AK8963_RA_HZL, 2, buffer); + return (((int16_t)buffer[1]) << 8) | buffer[0]; +} + +// ST2 register +bool AK8963::getOverflowStatus() { + I2Cdev::readBit(devAddr, AK8963_RA_ST2, AK8963_ST2_HOFL_BIT, buffer); + return buffer[0]; +} +bool AK8963::getOutputBit() { + I2Cdev::readBit(devAddr, AK8963_RA_ST2, AK8963_ST2_BITM_BIT, buffer); + return buffer[0]; +} + +// CNTL1 register +uint8_t AK8963::getMode() { + I2Cdev::readBits(devAddr, AK8963_RA_CNTL1, AK8963_CNTL1_MODE_BIT, AK8963_CNTL1_MODE_LENGTH, buffer); + return buffer[0]; +} +void AK8963::setMode(uint8_t mode) { + I2Cdev::writeBits(devAddr, AK8963_RA_CNTL1, AK8963_CNTL1_MODE_BIT, AK8963_CNTL1_MODE_LENGTH, mode); +} +uint8_t AK8963::getResolution() { + I2Cdev::readBit(devAddr, AK8963_RA_CNTL1, AK8963_CNTL1_RES_BIT, buffer); + return buffer[0]; +} +void AK8963::setResolution(uint8_t res) { + I2Cdev::writeBit(devAddr, AK8963_RA_CNTL1, AK8963_CNTL1_RES_BIT, res); +} +void AK8963::reset() { + I2Cdev::writeBits(devAddr, AK8963_RA_CNTL1, AK8963_CNTL1_MODE_BIT, AK8963_CNTL1_MODE_LENGTH, AK8963_MODE_POWERDOWN); +} + +// ASTC register +void AK8963::setSelfTest(bool enabled) { + I2Cdev::writeBit(devAddr, AK8963_RA_ASTC, AK8963_ASTC_SELF_BIT, enabled); +} + +// I2CDIS +void AK8963::disableI2C() { + I2Cdev::writeByte(devAddr, AK8963_RA_I2CDIS, AK8963_I2CDIS_DISABLE); +} + +// ASA* registers +void AK8963::getAdjustment(int8_t *x, int8_t *y, int8_t *z) { + I2Cdev::readBytes(devAddr, AK8963_RA_ASAX, 3, buffer); + *x = buffer[0]; + *y = buffer[1]; + *z = buffer[2]; +} +void AK8963::setAdjustment(int8_t x, int8_t y, int8_t z) { + buffer[0] = x; + buffer[1] = y; + buffer[2] = z; + I2Cdev::writeBytes(devAddr, AK8963_RA_ASAX, 3, buffer); +} +uint8_t AK8963::getAdjustmentX() { + I2Cdev::readByte(devAddr, AK8963_RA_ASAX, buffer); + return buffer[0]; +} +void AK8963::setAdjustmentX(uint8_t x) { + I2Cdev::writeByte(devAddr, AK8963_RA_ASAX, x); +} +uint8_t AK8963::getAdjustmentY() { + I2Cdev::readByte(devAddr, AK8963_RA_ASAY, buffer); + return buffer[0]; +} +void AK8963::setAdjustmentY(uint8_t y) { + I2Cdev::writeByte(devAddr, AK8963_RA_ASAY, y); +} +uint8_t AK8963::getAdjustmentZ() { + I2Cdev::readByte(devAddr, AK8963_RA_ASAZ, buffer); + return buffer[0]; +} +void AK8963::setAdjustmentZ(uint8_t z) { + I2Cdev::writeByte(devAddr, AK8963_RA_ASAZ, z); +} diff --git a/Arduino/AK8963/AK8963.h b/Arduino/AK8963/AK8963.h new file mode 100644 index 00000000..875df144 --- /dev/null +++ b/Arduino/AK8963/AK8963.h @@ -0,0 +1,146 @@ +// I2Cdev library collection - AK8963 I2C device class header file +// Based on AKM AK8963 datasheet, 10/2013 +// 8/27/2011 by Jeff Rowberg +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// 2016-01-02 - initial release based on AK8975 code +// + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2011 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#ifndef _AK8963_H_ +#define _AK8963_H_ + +#include "I2Cdev.h" + +#define AK8963_ADDRESS_00 0x0C +#define AK8963_ADDRESS_01 0x0D +#define AK8963_ADDRESS_10 0x0E +#define AK8963_ADDRESS_11 0x0F +#define AK8963_DEFAULT_ADDRESS AK8963_ADDRESS_00 + +#define AK8963_RA_WIA 0x00 +#define AK8963_RA_INFO 0x01 +#define AK8963_RA_ST1 0x02 +#define AK8963_RA_HXL 0x03 +#define AK8963_RA_HXH 0x04 +#define AK8963_RA_HYL 0x05 +#define AK8963_RA_HYH 0x06 +#define AK8963_RA_HZL 0x07 +#define AK8963_RA_HZH 0x08 +#define AK8963_RA_ST2 0x09 +#define AK8963_RA_CNTL1 0x0A +#define AK8963_RA_CNTL2 0x0B +#define AK8963_RA_ASTC 0x0C +#define AK8963_RA_TS1 0x0D // SHIPMENT TEST, DO NOT USE +#define AK8963_RA_TS2 0x0E // SHIPMENT TEST, DO NOT USE +#define AK8963_RA_I2CDIS 0x0F +#define AK8963_RA_ASAX 0x10 +#define AK8963_RA_ASAY 0x11 +#define AK8963_RA_ASAZ 0x12 + +#define AK8963_ST1_DRDY_BIT 0 +#define AK8963_ST1_DOR_BIT 1 + +#define AK8963_ST2_HOFL_BIT 3 +#define AK8963_ST2_BITM_BIT 4 + +#define AK8963_CNTL1_MODE_BIT 3 +#define AK8963_CNTL1_RES_BIT 4 +#define AK8963_CNTL1_MODE_LENGTH 4 + +#define AK8963_MODE_POWERDOWN 0x0 +#define AK8963_MODE_SINGLE 0x1 +#define AK8963_MODE_SELFTEST 0x8 +#define AK8963_MODE_FUSEROM 0xF + +#define AK8963_RES_14_BIT 0 +#define AK8963_RES_16_BIT 1 + +#define AK8963_CNTL2_SRST_BIT 0 + +#define AK8963_ASTC_SELF_BIT 6 + +#define AK8963_I2CDIS_DISABLE 0x1B + +class AK8963 { + public: + AK8963(); + AK8963(uint8_t address); + + void initialize(); + bool testConnection(); + + // WIA register + uint8_t getDeviceID(); + + // INFO register + uint8_t getInfo(); + + // ST1 register + bool getDataReady(); + bool getDataOverrun(); + + // H* registers + void getHeading(int16_t *x, int16_t *y, int16_t *z); + int16_t getHeadingX(); + int16_t getHeadingY(); + int16_t getHeadingZ(); + + // ST2 register + bool getOverflowStatus(); + bool getOutputBit(); + + // CNTL1 register + uint8_t getMode(); + void setMode(uint8_t mode); + uint8_t getResolution(); + void setResolution(uint8_t resolution); + void reset(); + + // ASTC register + void setSelfTest(bool enabled); + + // I2CDIS + void disableI2C(); // um, why...? + + // ASA* registers + void getAdjustment(int8_t *x, int8_t *y, int8_t *z); + void setAdjustment(int8_t x, int8_t y, int8_t z); + uint8_t getAdjustmentX(); + void setAdjustmentX(uint8_t x); + uint8_t getAdjustmentY(); + void setAdjustmentY(uint8_t y); + uint8_t getAdjustmentZ(); + void setAdjustmentZ(uint8_t z); + + private: + uint8_t devAddr; + uint8_t buffer[6]; + uint8_t mode; +}; + +#endif /* _AK8963_H_ */ diff --git a/Arduino/AK8963/library.json b/Arduino/AK8963/library.json new file mode 100644 index 00000000..69da4f27 --- /dev/null +++ b/Arduino/AK8963/library.json @@ -0,0 +1,20 @@ +{ + "name": "I2Cdevlib-AK8963", + "keywords": "compass, sensor, i2cdevlib, i2c", + "description": "AK8963 is 3-axis electronic compass IC with high sensitive Hall sensor technology", + "include": "Arduino/AK8963", + "repository": + { + "type": "git", + "url": "https://github.com/jrowberg/i2cdevlib.git" + }, + "dependencies": + [ + { + "name": "I2Cdevlib-Core", + "frameworks": "arduino" + } + ], + "frameworks": "arduino", + "platforms": "atmelavr" +} From 4b9936def39ad64b09e156b4ac570d9b3d870581 Mon Sep 17 00:00:00 2001 From: James Smith Date: Sun, 3 Jan 2016 15:21:09 -0800 Subject: [PATCH 101/335] Update to the recommended spark/particle detection code and set BUFFER_LENGTH (not a global define in particle-land) --- Arduino/I2Cdev/I2Cdev.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Arduino/I2Cdev/I2Cdev.h b/Arduino/I2Cdev/I2Cdev.h index 46cbcf05..20fa3e29 100644 --- a/Arduino/I2Cdev/I2Cdev.h +++ b/Arduino/I2Cdev/I2Cdev.h @@ -91,8 +91,9 @@ THE SOFTWARE. #endif #ifdef SPARK - #include + #include "application.h" #define ARDUINO 101 + #define BUFFER_LENGTH 32 #endif From 01c20648127d5bd7f329c532b80d16c48cb9158f Mon Sep 17 00:00:00 2001 From: James Smith Date: Sun, 3 Jan 2016 15:38:35 -0800 Subject: [PATCH 102/335] Add defines for continuous read modes on AK8963 --- Arduino/AK8963/AK8963.h | 101 +++++++++++++++++++++------------------- 1 file changed, 52 insertions(+), 49 deletions(-) diff --git a/Arduino/AK8963/AK8963.h b/Arduino/AK8963/AK8963.h index 875df144..843776de 100644 --- a/Arduino/AK8963/AK8963.h +++ b/Arduino/AK8963/AK8963.h @@ -36,55 +36,58 @@ THE SOFTWARE. #include "I2Cdev.h" -#define AK8963_ADDRESS_00 0x0C -#define AK8963_ADDRESS_01 0x0D -#define AK8963_ADDRESS_10 0x0E -#define AK8963_ADDRESS_11 0x0F -#define AK8963_DEFAULT_ADDRESS AK8963_ADDRESS_00 - -#define AK8963_RA_WIA 0x00 -#define AK8963_RA_INFO 0x01 -#define AK8963_RA_ST1 0x02 -#define AK8963_RA_HXL 0x03 -#define AK8963_RA_HXH 0x04 -#define AK8963_RA_HYL 0x05 -#define AK8963_RA_HYH 0x06 -#define AK8963_RA_HZL 0x07 -#define AK8963_RA_HZH 0x08 -#define AK8963_RA_ST2 0x09 -#define AK8963_RA_CNTL1 0x0A -#define AK8963_RA_CNTL2 0x0B -#define AK8963_RA_ASTC 0x0C -#define AK8963_RA_TS1 0x0D // SHIPMENT TEST, DO NOT USE -#define AK8963_RA_TS2 0x0E // SHIPMENT TEST, DO NOT USE -#define AK8963_RA_I2CDIS 0x0F -#define AK8963_RA_ASAX 0x10 -#define AK8963_RA_ASAY 0x11 -#define AK8963_RA_ASAZ 0x12 - -#define AK8963_ST1_DRDY_BIT 0 -#define AK8963_ST1_DOR_BIT 1 - -#define AK8963_ST2_HOFL_BIT 3 -#define AK8963_ST2_BITM_BIT 4 - -#define AK8963_CNTL1_MODE_BIT 3 -#define AK8963_CNTL1_RES_BIT 4 -#define AK8963_CNTL1_MODE_LENGTH 4 - -#define AK8963_MODE_POWERDOWN 0x0 -#define AK8963_MODE_SINGLE 0x1 -#define AK8963_MODE_SELFTEST 0x8 -#define AK8963_MODE_FUSEROM 0xF - -#define AK8963_RES_14_BIT 0 -#define AK8963_RES_16_BIT 1 - -#define AK8963_CNTL2_SRST_BIT 0 - -#define AK8963_ASTC_SELF_BIT 6 - -#define AK8963_I2CDIS_DISABLE 0x1B +#define AK8963_ADDRESS_00 0x0C +#define AK8963_ADDRESS_01 0x0D +#define AK8963_ADDRESS_10 0x0E +#define AK8963_ADDRESS_11 0x0F +#define AK8963_DEFAULT_ADDRESS AK8963_ADDRESS_00 + +#define AK8963_RA_WIA 0x00 +#define AK8963_RA_INFO 0x01 +#define AK8963_RA_ST1 0x02 +#define AK8963_RA_HXL 0x03 +#define AK8963_RA_HXH 0x04 +#define AK8963_RA_HYL 0x05 +#define AK8963_RA_HYH 0x06 +#define AK8963_RA_HZL 0x07 +#define AK8963_RA_HZH 0x08 +#define AK8963_RA_ST2 0x09 +#define AK8963_RA_CNTL1 0x0A +#define AK8963_RA_CNTL2 0x0B +#define AK8963_RA_ASTC 0x0C +#define AK8963_RA_TS1 0x0D // SHIPMENT TEST, DO NOT USE +#define AK8963_RA_TS2 0x0E // SHIPMENT TEST, DO NOT USE +#define AK8963_RA_I2CDIS 0x0F +#define AK8963_RA_ASAX 0x10 +#define AK8963_RA_ASAY 0x11 +#define AK8963_RA_ASAZ 0x12 + +#define AK8963_ST1_DRDY_BIT 0 +#define AK8963_ST1_DOR_BIT 1 + +#define AK8963_ST2_HOFL_BIT 3 +#define AK8963_ST2_BITM_BIT 4 + +#define AK8963_CNTL1_MODE_BIT 3 +#define AK8963_CNTL1_RES_BIT 4 +#define AK8963_CNTL1_MODE_LENGTH 4 + +#define AK8963_MODE_POWERDOWN 0x0 +#define AK8963_MODE_SINGLE 0x1 +#define AK8963_MODE_CONTINUOUS_8HZ 0x2 +#define AK8963_MODE_EXTERNAL 0x4 +#define AK8963_MODE_CONTINUOUS_100HZ 0x6 +#define AK8963_MODE_SELFTEST 0x8 +#define AK8963_MODE_FUSEROM 0xF + +#define AK8963_RES_14_BIT 0 +#define AK8963_RES_16_BIT 1 + +#define AK8963_CNTL2_SRST_BIT 0 + +#define AK8963_ASTC_SELF_BIT 6 + +#define AK8963_I2CDIS_DISABLE 0x1B class AK8963 { public: From b586fbfefc24a5670dd674b8c383aa44a96ee88e Mon Sep 17 00:00:00 2001 From: James Smith Date: Sun, 3 Jan 2016 16:51:35 -0800 Subject: [PATCH 103/335] Use soft reset on AK8963 --- Arduino/AK8963/AK8963.cpp | 4 +++- Arduino/AK8963/AK8963.h | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Arduino/AK8963/AK8963.cpp b/Arduino/AK8963/AK8963.cpp index b1d715b0..fbdd659b 100644 --- a/Arduino/AK8963/AK8963.cpp +++ b/Arduino/AK8963/AK8963.cpp @@ -145,8 +145,10 @@ uint8_t AK8963::getResolution() { void AK8963::setResolution(uint8_t res) { I2Cdev::writeBit(devAddr, AK8963_RA_CNTL1, AK8963_CNTL1_RES_BIT, res); } + +// CNTL2 register void AK8963::reset() { - I2Cdev::writeBits(devAddr, AK8963_RA_CNTL1, AK8963_CNTL1_MODE_BIT, AK8963_CNTL1_MODE_LENGTH, AK8963_MODE_POWERDOWN); + I2Cdev::writeByte(devAddr, AK8963_RA_CNTL2, AK8963_CNTL2_RESET); } // ASTC register diff --git a/Arduino/AK8963/AK8963.h b/Arduino/AK8963/AK8963.h index 843776de..c4aeffa7 100644 --- a/Arduino/AK8963/AK8963.h +++ b/Arduino/AK8963/AK8963.h @@ -72,6 +72,8 @@ THE SOFTWARE. #define AK8963_CNTL1_RES_BIT 4 #define AK8963_CNTL1_MODE_LENGTH 4 +#define AK8963_CNTL2_RESET 0x01 + #define AK8963_MODE_POWERDOWN 0x0 #define AK8963_MODE_SINGLE 0x1 #define AK8963_MODE_CONTINUOUS_8HZ 0x2 From 1b6683b8a2ea853027313ad5ee1302cca92cfc09 Mon Sep 17 00:00:00 2001 From: James Smith Date: Sun, 3 Jan 2016 18:54:37 -0800 Subject: [PATCH 104/335] Don't force single-read mode when reading values --- Arduino/AK8963/AK8963.cpp | 8 -------- Arduino/AK8963/AK8963.h | 2 +- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/Arduino/AK8963/AK8963.cpp b/Arduino/AK8963/AK8963.cpp index fbdd659b..7643d76c 100644 --- a/Arduino/AK8963/AK8963.cpp +++ b/Arduino/AK8963/AK8963.cpp @@ -94,28 +94,20 @@ bool AK8963::getDataOverrun() { // H* registers void AK8963::getHeading(int16_t *x, int16_t *y, int16_t *z) { - I2Cdev::writeByte(devAddr, AK8963_RA_CNTL1, AK8963_MODE_SINGLE); - delay(10); I2Cdev::readBytes(devAddr, AK8963_RA_HXL, 6, buffer); *x = (((int16_t)buffer[1]) << 8) | buffer[0]; *y = (((int16_t)buffer[3]) << 8) | buffer[2]; *z = (((int16_t)buffer[5]) << 8) | buffer[4]; } int16_t AK8963::getHeadingX() { - I2Cdev::writeByte(devAddr, AK8963_RA_CNTL1, AK8963_MODE_SINGLE); - delay(10); I2Cdev::readBytes(devAddr, AK8963_RA_HXL, 2, buffer); return (((int16_t)buffer[1]) << 8) | buffer[0]; } int16_t AK8963::getHeadingY() { - I2Cdev::writeByte(devAddr, AK8963_RA_CNTL1, AK8963_MODE_SINGLE); - delay(10); I2Cdev::readBytes(devAddr, AK8963_RA_HYL, 2, buffer); return (((int16_t)buffer[1]) << 8) | buffer[0]; } int16_t AK8963::getHeadingZ() { - I2Cdev::writeByte(devAddr, AK8963_RA_CNTL1, AK8963_MODE_SINGLE); - delay(10); I2Cdev::readBytes(devAddr, AK8963_RA_HZL, 2, buffer); return (((int16_t)buffer[1]) << 8) | buffer[0]; } diff --git a/Arduino/AK8963/AK8963.h b/Arduino/AK8963/AK8963.h index c4aeffa7..c19f13b5 100644 --- a/Arduino/AK8963/AK8963.h +++ b/Arduino/AK8963/AK8963.h @@ -69,8 +69,8 @@ THE SOFTWARE. #define AK8963_ST2_BITM_BIT 4 #define AK8963_CNTL1_MODE_BIT 3 -#define AK8963_CNTL1_RES_BIT 4 #define AK8963_CNTL1_MODE_LENGTH 4 +#define AK8963_CNTL1_RES_BIT 4 #define AK8963_CNTL2_RESET 0x01 From f99e983456d8fe66e86e198cef161030a5a71cc6 Mon Sep 17 00:00:00 2001 From: James Smith Date: Sun, 10 Jan 2016 15:27:54 -0800 Subject: [PATCH 105/335] Include math.h in BMP085 header since this device uses pow() --- Arduino/BMP085/BMP085.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Arduino/BMP085/BMP085.h b/Arduino/BMP085/BMP085.h index 14c76cec..58f62247 100644 --- a/Arduino/BMP085/BMP085.h +++ b/Arduino/BMP085/BMP085.h @@ -34,6 +34,7 @@ THE SOFTWARE. #define _BMP085_H_ #include "I2Cdev.h" +#include #define BMP085_ADDRESS 0x77 #define BMP085_DEFAULT_ADDRESS BMP085_ADDRESS @@ -75,7 +76,7 @@ class BMP085 { public: BMP085(); BMP085(uint8_t address); - + void initialize(); bool testConnection(); From 7eea5cd00882a8b19af525ae832ae247ffe356fc Mon Sep 17 00:00:00 2001 From: august Date: Sat, 16 Jan 2016 23:09:59 +0100 Subject: [PATCH 106/335] I2CDev for nRF51 Tested on nRF51-DK with an MPU6050 --- nRF51/I2CDev/I2Cdev.cpp | 248 ++++++++++++++++++++++++++++++++++++++++ nRF51/I2CDev/I2Cdev.h | 85 ++++++++++++++ 2 files changed, 333 insertions(+) create mode 100644 nRF51/I2CDev/I2Cdev.cpp create mode 100644 nRF51/I2CDev/I2Cdev.h diff --git a/nRF51/I2CDev/I2Cdev.cpp b/nRF51/I2CDev/I2Cdev.cpp new file mode 100644 index 00000000..a0646057 --- /dev/null +++ b/nRF51/I2CDev/I2Cdev.cpp @@ -0,0 +1,248 @@ +// I2Cdev library collection - Main I2C device class +// Abstracts bit and byte I2C R/W functions into a convenient class +// +// Nordic Semiconductors nrf51 code by August Bering , tested with MPU6050 only +// readTimeout not implemented. + +// Based on Arduino's I2Cdev by Jeff Rowberg +// + + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2015 Jeff Rowberg, Nicolas Baldeck + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ +extern "C"{ +#include "nrf_drv_twi.h" +#include "app_util_platform.h" +} +#include "I2Cdev.h" +static nrf_drv_twi_t m_twi=NRF_DRV_TWI_INSTANCE(0); +/** Default constructor. + */ +I2Cdev::I2Cdev() { +} + +#define SCL_PIN 7 +#define SDA_PIN 30 + +uint16_t I2Cdev::readTimeout=I2CDEV_DEFAULT_READ_TIMEOUT; +/** Initialize I2C0 + */ +void I2Cdev::initialize() { + ret_code_t err_code; + + const nrf_drv_twi_config_t config = { + .scl = SCL_PIN, + .sda = SDA_PIN, + .frequency = NRF_TWI_FREQ_400K, + .interrupt_priority = APP_IRQ_PRIORITY_HIGH + }; + + + err_code = nrf_drv_twi_init(&m_twi, &config,NULL, NULL); + APP_ERROR_CHECK(err_code); +} + +/** Enable or disable I2C + * @param isEnabled true = enable, false = disable + */ +void I2Cdev::enable(bool isEnabled) { + + if (isEnabled) + nrf_drv_twi_enable(&m_twi); + else + nrf_drv_twi_disable(&m_twi); + +} + +/** Read a single bit from an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param bitNum Bit position to read (0-7) + * @param data Container for single bit value + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) + * @return Status of read operation (true = success) + */ +int8_t I2Cdev::readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data, uint16_t timeout) { + uint8_t b; + uint8_t count = readByte(devAddr, regAddr, &b, timeout); + *data = b & (1 << bitNum); + return count; +} + +/** Read multiple bits from an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param bitStart First bit position to read (0-7) + * @param length Number of bits to read (not more than 8) + * @param data Container for right-aligned value (i.e. '101' read from any bitStart position will equal 0x05) + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) + * @return Status of read operation (true = success) + */ +int8_t I2Cdev::readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data, uint16_t timeout) { + // 01101001 read byte + // 76543210 bit numbers + // xxx args: bitStart=4, length=3 + // 010 masked + // -> 010 shifted + uint8_t count, b; + if ((count = readByte(devAddr, regAddr, &b, timeout)) != 0) { + uint8_t mask = ((1 << length) - 1) << (bitStart - length + 1); + b &= mask; + b >>= (bitStart - length + 1); + *data = b; + } + return count; +} + +/** Read single byte from an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param data Container for byte value read from device + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) + * @return Status of read operation (true = success) + */ +int8_t I2Cdev::readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint16_t timeout) { + return readBytes(devAddr, regAddr, 1, data, timeout); +} + +/** Read multiple bytes from an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr First register regAddr to read from + * @param length Number of bytes to read + * @param data Buffer to store read data in + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) + * @return I2C_TransferReturn_TypeDef http://downloads.energymicro.com/documentation/doxygen/group__I2C.html + */ +int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data, uint16_t timeout) { + + //bool transfer_succeeded; + nrf_drv_twi_tx(&m_twi,devAddr,®Addr,1,true); + // transfer_succeeded = twi_master_transfer(m_device_address, ®ister_address, 1, TWI_DONT_ISSUE_STOP); + + ret_code_t r= nrf_drv_twi_rx(&m_twi,devAddr,data,length,false); + + //transfer_succeeded &= twi_master_transfer(m_device_address|TWI_READ_BIT, destination, number_of_bytes, TWI_ISSUE_STOP); + return r==NRF_SUCCESS; + +} + +/** write a single bit in an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to write to + * @param bitNum Bit position to write (0-7) + * @param value New bit value to write + * @return Status of operation (true = success) + */ +bool I2Cdev::writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t data) { + uint8_t b; + readByte(devAddr, regAddr, &b); + b = (data != 0) ? (b | (1 << bitNum)) : (b & ~(1 << bitNum)); + return writeByte(devAddr, regAddr, b); +} + +/** Write multiple bits in an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to write to + * @param bitStart First bit position to write (0-7) + * @param length Number of bits to write (not more than 8) + * @param data Right-aligned value to write + * @return Status of operation (true = success) + */ +bool I2Cdev::writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data) { + // 010 value to write + // 76543210 bit numbers + // xxx args: bitStart=4, length=3 + // 00011100 mask byte + // 10101111 original value (sample) + // 10100011 original & ~mask + // 10101011 masked | value + uint8_t b; + if (readByte(devAddr, regAddr, &b) != 0) { + uint8_t mask = ((1 << length) - 1) << (bitStart - length + 1); + data <<= (bitStart - length + 1); // shift data into correct position + data &= mask; // zero all non-important bits in data + b &= ~(mask); // zero all important bits in existing byte + b |= data; // combine data with existing byte + return writeByte(devAddr, regAddr, b); + } else { + return false; + } +} + +/** Write single byte to an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register address to write to + * @param data New byte value to write + * @return Status of operation (true = success) + */ +bool I2Cdev::writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data) { + uint8_t w2_data[2]; + + w2_data[0] = regAddr; + w2_data[1] = data; + return NRF_SUCCESS==nrf_drv_twi_tx(&m_twi,devAddr,w2_data,2,false); +} + +/** Write multiple bytes to an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr First register address to write to + * @param length Number of bytes to write + * @param data Buffer to copy new data from + * @return Status of operation (true = success) + */ +bool I2Cdev::writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t* data) { + if (NRF_SUCCESS!=nrf_drv_twi_tx(&m_twi,devAddr,®Addr,1,true)) + return false; + return NRF_SUCCESS==nrf_drv_twi_tx(&m_twi,devAddr,data,length,false); +} +/** Write single word to a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register address to write to + * @param data New word value to write + * @return Status of operation (true = success) + */ +bool I2Cdev::writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data) { + return writeWords(devAddr, regAddr, 1, &data); +} +/** Write multiple words to a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr First register address to write to + * @param length Number of words to write + * @param data Buffer to copy new data from + * @return Status of operation (true = success) + */ +bool I2Cdev::writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data){ + if (NRF_SUCCESS!=nrf_drv_twi_tx(&m_twi,devAddr,®Addr,1,true)) + return false; + + for (int i=0;i>8; + d[1]=data[i]&0xff; + bool pending = i < length - 1; + if (NRF_SUCCESS != nrf_drv_twi_tx(&m_twi, devAddr, d, 2, pending)) + return false; + } + return true; +} diff --git a/nRF51/I2CDev/I2Cdev.h b/nRF51/I2CDev/I2Cdev.h new file mode 100644 index 00000000..b4e56f77 --- /dev/null +++ b/nRF51/I2CDev/I2Cdev.h @@ -0,0 +1,85 @@ +// I2Cdev library collection - Main I2C device class +// Abstracts bit and byte I2C R/W functions into a convenient class +// EFM32 stub port by Nicolas Baldeck +// Based on Arduino's I2Cdev by Jeff Rowberg +// +// Changelog: +// 2015-01-02 - Initial release + + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2015 Jeff Rowberg, Nicolas Baldeck + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#ifndef _I2CDEV_H_ +#define _I2CDEV_H_ +#include +#include "compiler_abstraction.h" +#include "nrf.h" +#ifdef SOFTDEVICE_PRESENT +#include "nrf_soc.h" +#include "app_error.h" +#endif + + +#define I2C_SDA_PORT gpioPortA +#define I2C_SDA_PIN 0 +#define I2C_SDA_MODE gpioModeWiredAnd +#define I2C_SDA_DOUT 1 + +#define I2C_SCL_PORT gpioPortA +#define I2C_SCL_PIN 1 +#define I2C_SCL_MODE gpioModeWiredAnd +#define I2C_SCL_DOUT 1 + +#define I2CDEV_DEFAULT_READ_TIMEOUT 0 + +class I2Cdev { + public: + I2Cdev(); + + static void initialize(); + static void enable(bool isEnabled); + + static int8_t readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout); + //TODO static int8_t readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout); + static int8_t readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout); + //TODO static int8_t readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout); + static int8_t readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout); + //TODO static int8_t readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout); + static int8_t readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout); + //TODO static int8_t readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout); + + static bool writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t data); + //TODO static bool writeBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t data); + static bool writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data); + //TODO static bool writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t data); + static bool writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data); + static bool writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data); + static bool writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data); + static bool writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data); + + static uint16_t readTimeout; +}; + +#endif /* _I2CDEV_H_ */ From 87a6204b91de372f6d81baa0d42086997cb1bbd0 Mon Sep 17 00:00:00 2001 From: hellphoenix Date: Sat, 27 Feb 2016 13:47:29 -0600 Subject: [PATCH 107/335] Added files via upload --- .../MPU6050_DMP6_Ethernet.ino | 436 ++++++++++++++++++ 1 file changed, 436 insertions(+) create mode 100644 Arduino/MPU6050/Examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino diff --git a/Arduino/MPU6050/Examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino b/Arduino/MPU6050/Examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino new file mode 100644 index 00000000..f53529b0 --- /dev/null +++ b/Arduino/MPU6050/Examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino @@ -0,0 +1,436 @@ +// I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class using DMP (MotionApps v2.0) +// 6/21/2012 by Jeff Rowberg +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// 2013-05-08 - added seamless Fastwire support +// - added note about gyro calibration +// 2012-06-21 - added note about Arduino 1.0.1 + Leonardo compatibility error +// 2012-06-20 - improved FIFO overflow handling and simplified read process +// 2012-06-19 - completely rearranged DMP initialization code and simplification +// 2012-06-13 - pull gyro and accel data from FIFO packet instead of reading directly +// 2012-06-09 - fix broken FIFO read sequence and change interrupt detection to RISING +// 2012-06-05 - add gravity-compensated initial reference frame acceleration output +// - add 3D math helper file to DMP6 example sketch +// - add Euler output and Yaw/Pitch/Roll output formats +// 2012-06-04 - remove accel offset clearing for better results (thanks Sungon Lee) +// 2012-06-01 - fixed gyro sensitivity to be 2000 deg/sec instead of 250 +// 2012-05-30 - basic DMP initialization working + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2012 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ +#include +// I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files +// for both classes must be in the include path of your project +#include "I2Cdev.h" + +#include "MPU6050_6Axis_MotionApps20.h" +//#include "MPU6050.h" // not necessary if using MotionApps include file + +// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation +// is used in I2Cdev.h +#include "Wire.h" +#include "avr/wdt.h"// Watchdog library +// class default I2C address is 0x68 +// specific I2C addresses may be passed as a parameter here +// AD0 low = 0x68 (default for SparkFun breakout and InvenSense evaluation board) +// AD0 high = 0x69 +MPU6050 mpu; +//MPU6050 mpu(0x69); // <-- use for AD0 high + +// MAC address from Ethernet shield sticker under board +byte mac[] = { + 0x90, 0xA2, 0xDA, 0x10, 0x26, 0x82 +}; +// assign an IP address for the controller: +IPAddress ip(192,168,1,50); +// the router's gateway address: +byte gateway[] = { 192, 168, 1, 1 }; +// the subnet: +byte subnet[] = { 255, 255, 0, 0 }; + +// Initialize the Ethernet server library +// with the IP address and port you want to use +// (port 80 is default for HTTP): +EthernetServer server(80); + +String HTTP_req; // stores the HTTP request + +/* ========================================================================= + NOTE: In addition to connection 3.3v, GND, SDA, and SCL, this sketch + depends on the MPU-6050's INT pin being connected to the Arduino's + external interrupt #0 pin. On the Arduino Uno and Mega 2560, this is + digital I/O pin 2. + * ========================================================================= */ + +/* ========================================================================= + NOTE: Arduino v1.0.1 with the Leonardo board generates a compile error + when using Serial.write(buf, len). The Teapot output uses this method. + The solution requires a modification to the Arduino USBAPI.h file, which + is fortunately simple, but annoying. This will be fixed in the next IDE + release. For more info, see these links: + + http://arduino.cc/forum/index.php/topic,109987.0.html + http://code.google.com/p/arduino/issues/detail?id=958 + * ========================================================================= */ + + + +// uncomment "OUTPUT_READABLE_QUATERNION" if you want to see the actual +// quaternion components in a [w, x, y, z] format (not best for parsing +// on a remote host such as Processing or something though) +//#define OUTPUT_READABLE_QUATERNION + +// uncomment "OUTPUT_READABLE_EULER" if you want to see Euler angles +// (in degrees) calculated from the quaternions coming from the FIFO. +// Note that Euler angles suffer from gimbal lock (for more info, see +// http://en.wikipedia.org/wiki/Gimbal_lock) +//#define OUTPUT_READABLE_EULER + +// uncomment "OUTPUT_READABLE_YAWPITCHROLL" if you want to see the yaw/ +// pitch/roll angles (in degrees) calculated from the quaternions coming +// from the FIFO. Note this also requires gravity vector calculations. +// Also note that yaw/pitch/roll angles suffer from gimbal lock (for +// more info, see: http://en.wikipedia.org/wiki/Gimbal_lock) +#define OUTPUT_READABLE_YAWPITCHROLL + +// uncomment "OUTPUT_READABLE_REALACCEL" if you want to see acceleration +// components with gravity removed. This acceleration reference frame is +// not compensated for orientation, so +X is always +X according to the +// sensor, just without the effects of gravity. If you want acceleration +// compensated for orientation, us OUTPUT_READABLE_WORLDACCEL instead. +//#define OUTPUT_READABLE_REALACCEL + +// uncomment "OUTPUT_READABLE_WORLDACCEL" if you want to see acceleration +// components with gravity removed and adjusted for the world frame of +// reference (yaw is relative to initial orientation, since no magnetometer +// is present in this case). Could be quite handy in some cases. +//#define OUTPUT_READABLE_WORLDACCEL + +// uncomment "OUTPUT_TEAPOT" if you want output that matches the +// format used for the InvenSense teapot demo +//#define OUTPUT_TEAPOT + + + +#define LED_PIN 13 // (Arduino is 13, Teensy is 11, Teensy++ is 6) +bool blinkState = false; + +// MPU control/status vars +bool dmpReady = false; // set true if DMP init was successful +uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU +uint8_t devStatus; // return status after each device operation (0 = success, !0 = error) +uint16_t packetSize; // expected DMP packet size (default is 42 bytes) +uint16_t fifoCount; // count of all bytes currently in FIFO +uint8_t fifoBuffer[64]; // FIFO storage buffer + +// orientation/motion vars +Quaternion q; // [w, x, y, z] quaternion container +VectorInt16 aa; // [x, y, z] accel sensor measurements +VectorInt16 aaReal; // [x, y, z] gravity-free accel sensor measurements +VectorInt16 aaWorld; // [x, y, z] world-frame accel sensor measurements +VectorFloat gravity; // [x, y, z] gravity vector +float euler[3]; // [psi, theta, phi] Euler angle container +float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector + +// packet structure for InvenSense teapot demo +uint8_t teapotPacket[14] = { '$', 0x02, 0,0, 0,0, 0,0, 0,0, 0x00, 0x00, '\r', '\n' }; + + + +// ================================================================ +// === INTERRUPT DETECTION ROUTINE === +// ================================================================ + +volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high +void dmpDataReady() { + mpuInterrupt = true; +} + + + +// ================================================================ +// === INITIAL SETUP === +// ================================================================ + +void setup() { + wdt_enable(WDTO_1S); //Watchdog enable. WDTO_1S sets the watchdog timer to 1 second. The time set here is approximate. + // You can find more time settings at http://www.nongnu.org/avr-libc/user-manual/group__avr__watchdog.html . + // join I2C bus (I2Cdev library doesn't do this automatically) + #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE + Wire.begin(); + TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz) + #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE + Fastwire::setup(400, true); + #endif + + //Serial.print(mpu.getSleepEnabled()); + // initialize serial communication + // (115200 chosen because it is required for Teapot Demo output, but it's + // really up to you depending on your project) + Serial.begin(115200); + Ethernet.begin(mac, ip, gateway, subnet); + server.begin(); + Serial.print("server is at "); + Serial.println(Ethernet.localIP()); + while (!Serial); // wait for Leonardo enumeration, others continue immediately + + // NOTE: 8MHz or slower host processors, like the Teensy @ 3.3v or Ardunio + // Pro Mini running at 3.3v, cannot handle this baud rate reliably due to + // the baud timing being too misaligned with processor ticks. You must use + // 38400 or slower in these cases, or use some kind of external separate + // crystal solution for the UART timer. + + // initialize device + Serial.println(F("Initializing I2C devices...")); + mpu.initialize(); +/* + // verify connection + Serial.println(F("Testing device connections...")); + Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed")); +*/ + // load and configure the DMP + Serial.println(F("Initializing DMP...")); + devStatus = mpu.dmpInitialize(); + + // supply your own gyro offsets here, scaled for min sensitivity + mpu.setXGyroOffset(220); + mpu.setYGyroOffset(76); + mpu.setZGyroOffset(-85); + mpu.setZAccelOffset(1788); // 1688 factory default for my test chip + + // make sure it worked (returns 0 if so) + if (devStatus == 0) { + // turn on the DMP, now that it's ready + Serial.println(F("Enabling DMP...")); + mpu.setDMPEnabled(true); + + // enable Arduino interrupt detection + Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)...")); + attachInterrupt(0, dmpDataReady, RISING); + mpuIntStatus = mpu.getIntStatus(); + + // set our DMP Ready flag so the main loop() function knows it's okay to use it + Serial.println(F("DMP ready! Waiting for first interrupt...")); + dmpReady = true; + + // get expected DMP packet size for later comparison + packetSize = mpu.dmpGetFIFOPacketSize(); + } else { + // ERROR! + // 1 = initial memory load failed + // 2 = DMP configuration updates failed + // (if it's going to break, usually the code will be 1) + Serial.print(F("DMP Initialization failed (code ")); + Serial.print(devStatus); + Serial.println(F(")")); + } + + // configure LED for output + pinMode(LED_PIN, OUTPUT); +} + + + +// ================================================================ +// === MAIN PROGRAM LOOP === +// ================================================================ + +void loop() { + // if programming failed, don't try to do anything + //if (!dmpReady) return; + wdt_reset();//Resets the watchdog timer. If the timer is not reset, and the timer expires, a watchdog-initiated device reset will occur. + // wait for MPU interrupt or extra packet(s) available + while (!mpuInterrupt && fifoCount < packetSize) { + // other program behavior stuff here + + // . + // . + // if you are really paranoid you can frequently test in between other + // stuff to see if mpuInterrupt is true, and if so, "break;" from the + // while() loop to immediately process the MPU data + // . + // . + // . + } + + // reset interrupt flag and get INT_STATUS byte + mpuInterrupt = false; + mpuIntStatus = mpu.getIntStatus(); + + // get current FIFO count + fifoCount = mpu.getFIFOCount(); +/* + // check for overflow (this should never happen unless our code is too inefficient) + if ((mpuIntStatus & 0x10) || fifoCount == 1024) { + // reset so we can continue cleanly + mpu.resetFIFO(); + Serial.println(F("FIFO overflow!")); + + // otherwise, check for DMP data ready interrupt (this should happen frequently) + } else*/ if (mpuIntStatus & 0x02) { + // wait for correct available data length, should be a VERY short wait + while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount(); + + // read a packet from FIFO, then clear the buffer + mpu.getFIFOBytes(fifoBuffer, packetSize); + mpu.resetFIFO(); + + // track FIFO count here in case there is > 1 packet available + // (this lets us immediately read more without waiting for an interrupt) + fifoCount -= packetSize; + + + #ifdef OUTPUT_READABLE_YAWPITCHROLL + // display Euler angles in degrees + mpu.dmpGetQuaternion(&q, fifoBuffer); + mpu.dmpGetGravity(&gravity, &q); + mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); + + Serial.print("ypr\t"); + Serial.print(ypr[0] * 180/M_PI); + Serial.print("\t"); + Serial.print(ypr[1] * 180/M_PI); + Serial.print("\t"); + Serial.println(ypr[2] * 180/M_PI); + serversend(); + delay(100); + #endif + + + #ifdef OUTPUT_TEAPOT + // display quaternion values in InvenSense Teapot demo format: + teapotPacket[2] = fifoBuffer[0]; + teapotPacket[3] = fifoBuffer[1]; + teapotPacket[4] = fifoBuffer[4]; + teapotPacket[5] = fifoBuffer[5]; + teapotPacket[6] = fifoBuffer[8]; + teapotPacket[7] = fifoBuffer[9]; + teapotPacket[8] = fifoBuffer[12]; + teapotPacket[9] = fifoBuffer[13]; + Serial.write(teapotPacket, 14); + serversend(); + delay(100); + teapotPacket[11]++; // packetCount, loops at 0xFF on purpose + #endif + + // blink LED to indicate activity + blinkState = !blinkState; + digitalWrite(LED_PIN, blinkState); + } +} + +void serversend(){ + + EthernetClient client = server.available(); // try to get client + + if (client) { // got client? + //boolean currentLineIsBlank = true; + while (client.connected()) { + if (client.available()) { // client data available to read + char c = client.read(); // read 1 byte (character) from client + HTTP_req += c; // save the HTTP request 1 char at a time + // last line of client request is blank and ends with \n + // respond to client only after last line received + if (c == '\n') { + // send a standard http response header + client.println("HTTP/1.1 200 OK"); + client.println("Content-Type: text/html"); + //client.println("Connection: keep-alive"); + client.println(); + // AJAX request for switch state + if (HTTP_req.indexOf("ajax_switch") > -1) { + // read switch state and analog input + GetAjaxData(client); + } + else { // HTTP request for web page + // send web page - contains JavaScript with AJAX calls + client.println(""); + client.println(""); + client.println(""); + client.println("Arduino Web Page"); + client.println(""); + client.println(""); + client.println(""); + client.println("

MPU6050 Output

"); + client.println("
"); + client.println("
"); + client.println(""); + client.println(""); + } + // display received HTTP request on serial port + Serial.print(HTTP_req); + HTTP_req = ""; // finished with request, empty string + delay(1); // give the web browser time to receive the data + client.stop(); // close the connection + break; + } + + } + } + + } +} + +void GetAjaxData(EthernetClient cl) +{ + //#ifdef OUTPUT_READABLE_ACCELGYRO + // display tab-separated accel/gyro x/y/z values + cl.print("Yaw, Pitch, and Roll:\t"); + cl.print("

Yaw:"); + cl.print(ypr[0] * 180/M_PI); + cl.print("\t"); + cl.println("

"); + cl.print("

Pitch:"); + cl.print(ypr[2] * 180/M_PI); + cl.print("\t"); + cl.println("

"); + cl.print("

Roll:"); + cl.print(ypr[1] * 180/M_PI); + cl.print("\t"); + cl.println("

"); + /* cl.print("

teapotpacket:"); + cl.write(teapotPacket, 14); + cl.print("\t"); + cl.println("

");*/ + + +} From bf3d86abd34207a36d2d900c4d66d34cc94bbc06 Mon Sep 17 00:00:00 2001 From: hellphoenix Date: Sun, 28 Feb 2016 18:34:03 -0600 Subject: [PATCH 108/335] Added files via upload --- .../MPU6050_DMP6_Ethernet.ino | 216 +++++++++++++----- 1 file changed, 157 insertions(+), 59 deletions(-) diff --git a/Arduino/MPU6050/Examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino b/Arduino/MPU6050/Examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino index f53529b0..10b648c1 100644 --- a/Arduino/MPU6050/Examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino +++ b/Arduino/MPU6050/Examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino @@ -1,21 +1,11 @@ -// I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class using DMP (MotionApps v2.0) -// 6/21/2012 by Jeff Rowberg +// I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class using DMP (MotionApps v2.0) over Ethernet +// Based on I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class using DMP (MotionApps v2.0) (6/21/2012 by Jeff Rowberg ) // Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib // // Changelog: -// 2013-05-08 - added seamless Fastwire support -// - added note about gyro calibration -// 2012-06-21 - added note about Arduino 1.0.1 + Leonardo compatibility error -// 2012-06-20 - improved FIFO overflow handling and simplified read process -// 2012-06-19 - completely rearranged DMP initialization code and simplification -// 2012-06-13 - pull gyro and accel data from FIFO packet instead of reading directly -// 2012-06-09 - fix broken FIFO read sequence and change interrupt detection to RISING -// 2012-06-05 - add gravity-compensated initial reference frame acceleration output -// - add 3D math helper file to DMP6 example sketch -// - add Euler output and Yaw/Pitch/Roll output formats -// 2012-06-04 - remove accel offset clearing for better results (thanks Sungon Lee) -// 2012-06-01 - fixed gyro sensitivity to be 2000 deg/sec instead of 250 -// 2012-05-30 - basic DMP initialization working +// 2016-02-28 - Cleaned up code to be in line with other example codes + // - Added Ethernet outputs for Quaternion, Euler, RealAccel, WorldAccel +// 2016-02-27 - Initial working code compiled /* ============================================ I2Cdev device library code is placed under the MIT license @@ -52,6 +42,7 @@ THE SOFTWARE. // is used in I2Cdev.h #include "Wire.h" #include "avr/wdt.h"// Watchdog library + // class default I2C address is 0x68 // specific I2C addresses may be passed as a parameter here // AD0 low = 0x68 (default for SparkFun breakout and InvenSense evaluation board) @@ -96,7 +87,6 @@ String HTTP_req; // stores the HTTP request * ========================================================================= */ - // uncomment "OUTPUT_READABLE_QUATERNION" if you want to see the actual // quaternion components in a [w, x, y, z] format (not best for parsing // on a remote host such as Processing or something though) @@ -132,8 +122,6 @@ String HTTP_req; // stores the HTTP request // format used for the InvenSense teapot demo //#define OUTPUT_TEAPOT - - #define LED_PIN 13 // (Arduino is 13, Teensy is 11, Teensy++ is 6) bool blinkState = false; @@ -167,16 +155,15 @@ volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin h void dmpDataReady() { mpuInterrupt = true; } - - - // ================================================================ // === INITIAL SETUP === // ================================================================ void setup() { - wdt_enable(WDTO_1S); //Watchdog enable. WDTO_1S sets the watchdog timer to 1 second. The time set here is approximate. + wdt_enable(WDTO_1S); //Watchdog enable. + //WDTO_1S sets the watchdog timer to 1 second. The time set here is approximate. // You can find more time settings at http://www.nongnu.org/avr-libc/user-manual/group__avr__watchdog.html . + // join I2C bus (I2Cdev library doesn't do this automatically) #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE Wire.begin(); @@ -185,31 +172,30 @@ void setup() { Fastwire::setup(400, true); #endif - //Serial.print(mpu.getSleepEnabled()); // initialize serial communication // (115200 chosen because it is required for Teapot Demo output, but it's // really up to you depending on your project) - Serial.begin(115200); - Ethernet.begin(mac, ip, gateway, subnet); - server.begin(); - Serial.print("server is at "); - Serial.println(Ethernet.localIP()); - while (!Serial); // wait for Leonardo enumeration, others continue immediately - + Serial.begin(115200); // NOTE: 8MHz or slower host processors, like the Teensy @ 3.3v or Ardunio // Pro Mini running at 3.3v, cannot handle this baud rate reliably due to // the baud timing being too misaligned with processor ticks. You must use // 38400 or slower in these cases, or use some kind of external separate // crystal solution for the UART timer. + Ethernet.begin(mac, ip, gateway, subnet); + server.begin(); + Serial.print("server is at "); + Serial.println(Ethernet.localIP()); + while (!Serial); // wait for Leonardo enumeration, others continue immediately + // initialize device Serial.println(F("Initializing I2C devices...")); mpu.initialize(); -/* + // verify connection Serial.println(F("Testing device connections...")); Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed")); -*/ + // load and configure the DMP Serial.println(F("Initializing DMP...")); devStatus = mpu.dmpInitialize(); @@ -245,6 +231,7 @@ void setup() { Serial.print(F("DMP Initialization failed (code ")); Serial.print(devStatus); Serial.println(F(")")); + return; } // configure LED for output @@ -259,12 +246,11 @@ void setup() { void loop() { // if programming failed, don't try to do anything - //if (!dmpReady) return; + if (!dmpReady) return; wdt_reset();//Resets the watchdog timer. If the timer is not reset, and the timer expires, a watchdog-initiated device reset will occur. // wait for MPU interrupt or extra packet(s) available while (!mpuInterrupt && fifoCount < packetSize) { - // other program behavior stuff here - + // other program behavior stuff here // . // . // if you are really paranoid you can frequently test in between other @@ -281,7 +267,7 @@ void loop() { // get current FIFO count fifoCount = mpu.getFIFOCount(); -/* + // check for overflow (this should never happen unless our code is too inefficient) if ((mpuIntStatus & 0x10) || fifoCount == 1024) { // reset so we can continue cleanly @@ -289,36 +275,81 @@ void loop() { Serial.println(F("FIFO overflow!")); // otherwise, check for DMP data ready interrupt (this should happen frequently) - } else*/ if (mpuIntStatus & 0x02) { + } else if (mpuIntStatus & 0x02) { // wait for correct available data length, should be a VERY short wait while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount(); // read a packet from FIFO, then clear the buffer mpu.getFIFOBytes(fifoBuffer, packetSize); - mpu.resetFIFO(); + //mpu.resetFIFO(); // track FIFO count here in case there is > 1 packet available // (this lets us immediately read more without waiting for an interrupt) fifoCount -= packetSize; - + #ifdef OUTPUT_READABLE_QUATERNION + // display quaternion values in easy matrix form: w x y z + mpu.dmpGetQuaternion(&q, fifoBuffer); + Serial.print("quat\t"); + Serial.print(q.w); + Serial.print("\t"); + Serial.print(q.x); + Serial.print("\t"); + Serial.print(q.y); + Serial.print("\t"); + Serial.println(q.z); + #endif + #ifdef OUTPUT_READABLE_EULER + // display Euler angles in degrees + mpu.dmpGetQuaternion(&q, fifoBuffer); + mpu.dmpGetEuler(euler, &q); + Serial.print("euler\t"); + Serial.print(euler[0] * 180/M_PI); + Serial.print("\t"); + Serial.print(euler[1] * 180/M_PI); + Serial.print("\t"); + Serial.println(euler[2] * 180/M_PI); + #endif #ifdef OUTPUT_READABLE_YAWPITCHROLL // display Euler angles in degrees mpu.dmpGetQuaternion(&q, fifoBuffer); mpu.dmpGetGravity(&gravity, &q); - mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); - + mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); Serial.print("ypr\t"); Serial.print(ypr[0] * 180/M_PI); Serial.print("\t"); Serial.print(ypr[1] * 180/M_PI); Serial.print("\t"); Serial.println(ypr[2] * 180/M_PI); - serversend(); - delay(100); #endif - - + #ifdef OUTPUT_READABLE_REALACCEL + // display real acceleration, adjusted to remove gravity + mpu.dmpGetQuaternion(&q, fifoBuffer); + mpu.dmpGetAccel(&aa, fifoBuffer); + mpu.dmpGetGravity(&gravity, &q); + mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity); + Serial.print("areal\t"); + Serial.print(aaReal.x); + Serial.print("\t"); + Serial.print(aaReal.y); + Serial.print("\t"); + Serial.println(aaReal.z); + #endif + #ifdef OUTPUT_READABLE_WORLDACCEL + // display initial world-frame acceleration, adjusted to remove gravity + // and rotated based on known orientation from quaternion + mpu.dmpGetQuaternion(&q, fifoBuffer); + mpu.dmpGetAccel(&aa, fifoBuffer); + mpu.dmpGetGravity(&gravity, &q); + mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity); + mpu.dmpGetLinearAccelInWorld(&aaWorld, &aaReal, &q); + Serial.print("aworld\t"); + Serial.print(aaWorld.x); + Serial.print("\t"); + Serial.print(aaWorld.y); + Serial.print("\t"); + Serial.println(aaWorld.z); + #endif #ifdef OUTPUT_TEAPOT // display quaternion values in InvenSense Teapot demo format: teapotPacket[2] = fifoBuffer[0]; @@ -330,11 +361,9 @@ void loop() { teapotPacket[8] = fifoBuffer[12]; teapotPacket[9] = fifoBuffer[13]; Serial.write(teapotPacket, 14); - serversend(); - delay(100); teapotPacket[11]++; // packetCount, loops at 0xFF on purpose #endif - + serversend(); // blink LED to indicate activity blinkState = !blinkState; digitalWrite(LED_PIN, blinkState); @@ -385,7 +414,7 @@ void serversend(){ client.println( "request.open(\"GET\", \"ajax_switch\" + nocache, true);"); client.println("request.send(null);"); - client.println("setTimeout('GetAjaxData()', 100);"); + client.println("setTimeout('GetAjaxData()', 10);"); client.println("}"); client.println(""); client.println(""); @@ -399,21 +428,54 @@ void serversend(){ // display received HTTP request on serial port Serial.print(HTTP_req); HTTP_req = ""; // finished with request, empty string - delay(1); // give the web browser time to receive the data client.stop(); // close the connection break; - } - + } } - } - + } } } void GetAjaxData(EthernetClient cl) { - //#ifdef OUTPUT_READABLE_ACCELGYRO - // display tab-separated accel/gyro x/y/z values + #ifdef OUTPUT_READABLE_QUATERNION + // display quaternion values in easy matrix form: w x y z + cl.print("Quaternion Values:\t"); + cl.print("

w:"); + cl.print(q.w); + cl.print("\t"); + cl.println("

"); + cl.print("

x:"); + cl.print(q.x); + cl.print("\t"); + cl.println("

"); + cl.print("

y:"); + cl.print(q.y); + cl.print("\t"); + cl.println("

"); + cl.print("

z:"); + cl.print(q.z); + cl.print("\t"); + cl.println("

"); + #endif + #ifdef OUTPUT_READABLE_EULER + // display Euler angles in degrees + cl.print("Euler Angles:\t"); + cl.print("

Yaw:"); + cl.print(euler[0] * 180/M_PI); + cl.print("\t"); + cl.println("

"); + cl.print("

Pitch:"); + cl.print(euler[2] * 180/M_PI); + cl.print("\t"); + cl.println("

"); + cl.print("

Roll:"); + cl.print(euler[1] * 180/M_PI); + cl.print("\t"); + cl.println("

"); + #endif + #ifdef OUTPUT_READABLE_YAWPITCHROLL + // display Yaw/Pitch/Roll values in degrees cl.print("Yaw, Pitch, and Roll:\t"); cl.print("

Yaw:"); cl.print(ypr[0] * 180/M_PI); @@ -427,10 +489,46 @@ void GetAjaxData(EthernetClient cl) cl.print(ypr[1] * 180/M_PI); cl.print("\t"); cl.println("

"); - /* cl.print("

teapotpacket:"); + #endif + #ifdef OUTPUT_READABLE_REALACCEL + // display real acceleration, adjusted to remove gravity + cl.print("Real Accel:\t"); + cl.print("

Yaw:"); + cl.print(aaReal.x); + cl.print("\t"); + cl.println("

"); + cl.print("

Pitch:"); + cl.print(aaReal.z); + cl.print("\t"); + cl.println("

"); + cl.print("

Roll:"); + cl.print(aaReal.y); + cl.print("\t"); + cl.println("

"); + #endif + #ifdef OUTPUT_READABLE_WORLDACCEL + // display initial world-frame acceleration, adjusted to remove gravity + // and rotated based on known orientation from quaternion + cl.print("World Accel:\t"); + cl.print("

Yaw:"); + cl.print(aaWorld.x); + cl.print("\t"); + cl.println("

"); + cl.print("

Pitch:"); + cl.print(aaWorld.z); + cl.print("\t"); + cl.println("

"); + cl.print("

Roll:"); + cl.print(aaWorld.y); + cl.print("\t"); + cl.println("

"); + #endif + #ifdef OUTPUT_TEAPOT + cl.print("

teapotpacket:"); cl.write(teapotPacket, 14); cl.print("\t"); - cl.println("

");*/ - + cl.println("

"); + #endif + //Serial.println(cl.status(),DEC); } From 4d78410c44b44d582b39cd936087dd14d654b258 Mon Sep 17 00:00:00 2001 From: hellphoenix Date: Sun, 28 Feb 2016 18:38:11 -0600 Subject: [PATCH 109/335] Added files via upload --- .../Examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino | 2 -- 1 file changed, 2 deletions(-) diff --git a/Arduino/MPU6050/Examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino b/Arduino/MPU6050/Examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino index 10b648c1..f167caa5 100644 --- a/Arduino/MPU6050/Examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino +++ b/Arduino/MPU6050/Examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino @@ -529,6 +529,4 @@ void GetAjaxData(EthernetClient cl) cl.print("\t"); cl.println("

"); #endif - //Serial.println(cl.status(),DEC); - } From 64fcff6e72b1b3a7630094254cf32f137f30cc29 Mon Sep 17 00:00:00 2001 From: hellphoenix Date: Sun, 28 Feb 2016 18:48:08 -0600 Subject: [PATCH 110/335] Added files via upload --- .../Examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Arduino/MPU6050/Examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino b/Arduino/MPU6050/Examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino index f167caa5..b855bc45 100644 --- a/Arduino/MPU6050/Examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino +++ b/Arduino/MPU6050/Examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino @@ -1,4 +1,5 @@ // I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class using DMP (MotionApps v2.0) over Ethernet +// 2/27/2016 by hellphoenix // Based on I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class using DMP (MotionApps v2.0) (6/21/2012 by Jeff Rowberg ) // Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib // @@ -6,7 +7,9 @@ // 2016-02-28 - Cleaned up code to be in line with other example codes // - Added Ethernet outputs for Quaternion, Euler, RealAccel, WorldAccel // 2016-02-27 - Initial working code compiled - +// Bugs: +// - There is still a hangup after some time, though it only occurs when you are reading data from the website. +// If you only read the data from the serial port, there are no hangups. /* ============================================ I2Cdev device library code is placed under the MIT license Copyright (c) 2012 Jeff Rowberg From 9004092a3c4b1e6025f166f2a5729cb51a28b59c Mon Sep 17 00:00:00 2001 From: EAD Fritz Date: Tue, 22 Mar 2016 22:17:08 +0100 Subject: [PATCH 111/335] indentation fix --- Arduino/ADS1115/ADS1115.cpp | 15 +++++---------- Arduino/ADS1115/ADS1115.h | 10 +++++----- 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/Arduino/ADS1115/ADS1115.cpp b/Arduino/ADS1115/ADS1115.cpp index 23c867e8..09f3361f 100644 --- a/Arduino/ADS1115/ADS1115.cpp +++ b/Arduino/ADS1115/ADS1115.cpp @@ -90,7 +90,6 @@ void ADS1115::waitBusy(uint16_t max_retries) { } } - /** Read differential value based on current MUX configuration. * The default MUX setting sets the device to get the differential between the * AIN0 and AIN1 pins. There are 8 possible MUX settings, but if you are using @@ -570,22 +569,19 @@ void ADS1115::setHighThreshold(int16_t threshold) { } // Create a mask between two bits -unsigned createMask(unsigned a, unsigned b) -{ +unsigned createMask(unsigned a, unsigned b) { unsigned mask = 0; for (unsigned i=a; i<=b; i++) mask |= 1 << i; return mask; } -uint16_t shiftDown(uint16_t extractFrom, int places) -{ +uint16_t shiftDown(uint16_t extractFrom, int places) { return (extractFrom >> places); } -uint16_t getValueFromBits(uint16_t extractFrom, int high, int length) -{ +uint16_t getValueFromBits(uint16_t extractFrom, int high, int length) { int low= high-length +1; uint16_t mask = createMask(low ,high); return shiftDown(extractFrom & mask, low); @@ -593,8 +589,7 @@ uint16_t getValueFromBits(uint16_t extractFrom, int high, int length) /** Show all the config register settings */ -void ADS1115::showConfigRegister() -{ +void ADS1115::showConfigRegister() { I2Cdev::readWord(devAddr, ADS1115_RA_CONFIG, buffer); uint16_t configRegister =buffer[0]; @@ -638,6 +633,6 @@ void ADS1115::showConfigRegister() Serial.println(getValueFromBits(configRegister, ADS1115_CFG_COMP_QUE_BIT,ADS1115_CFG_COMP_QUE_LENGTH), BIN); #endif - + }; diff --git a/Arduino/ADS1115/ADS1115.h b/Arduino/ADS1115/ADS1115.h index f8bdb7ff..244c03e8 100644 --- a/Arduino/ADS1115/ADS1115.h +++ b/Arduino/ADS1115/ADS1115.h @@ -135,22 +135,22 @@ class ADS1115 { public: ADS1115(); ADS1115(uint8_t address); - + void initialize(); bool testConnection(); - + // SINGLE SHOT utilities void waitBusy(uint16_t max_retries); // Read the current CONVERSION register int16_t getConversion(); - + // Differential int16_t getConversionP0N1(); int16_t getConversionP0N3(); int16_t getConversionP1N3(); int16_t getConversionP2N3(); - + // Single-ended int16_t getConversionP0GND(); int16_t getConversionP1GND(); @@ -186,7 +186,7 @@ class ADS1115 { void setLowThreshold(int16_t threshold); int16_t getHighThreshold(); void setHighThreshold(int16_t threshold); - + // DEBUG void showConfigRegister(); From e0e3447f863c4416b685c6daa005b2d56770f3ce Mon Sep 17 00:00:00 2001 From: EAD Fritz Date: Tue, 22 Mar 2016 22:27:50 +0100 Subject: [PATCH 112/335] replaced setOpStatus() with triggerConversion() replaced getOpStatus with isConversionReady() removed ADS1115_OS_INACTIVE and ADS1115_OS_ACTIVE because they flipped meaning depending on if the operation was read or write. Utterly confusing. ADS1115_OS_ACTIVE=1 means "start conversion" when writing the bit, but when reading the same bit back '1' means 'conversion done'. I hope triggerConversion() and isConversionReady() will be easier to read. --- Arduino/ADS1115/ADS1115.cpp | 13 +++++-------- Arduino/ADS1115/ADS1115.h | 6 ++---- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/Arduino/ADS1115/ADS1115.cpp b/Arduino/ADS1115/ADS1115.cpp index 09f3361f..9918961f 100644 --- a/Arduino/ADS1115/ADS1115.cpp +++ b/Arduino/ADS1115/ADS1115.cpp @@ -298,24 +298,21 @@ float ADS1115::getMvPerCount() { // CONFIG register /** Get operational status. - * @return Current operational status (0 for active conversion, 1 for inactive) - * @see ADS1115_OS_ACTIVE - * @see ADS1115_OS_INACTIVE + * @return Current operational status (false for active conversion, true for inactive) * @see ADS1115_RA_CONFIG * @see ADS1115_CFG_OS_BIT */ -uint8_t ADS1115::getOpStatus() { +bool ADS1115::isConversionReady() { I2Cdev::readBitW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_OS_BIT, buffer); - return (uint8_t)buffer[0]; + return !!buffer[0]; } /** Set operational status. * This bit can only be written while in power-down mode (no conversions active). - * @param status New operational status (0 does nothing, 1 to trigger conversion) * @see ADS1115_RA_CONFIG * @see ADS1115_CFG_OS_BIT */ -void ADS1115::setOpStatus(uint8_t status) { - I2Cdev::writeBitW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_OS_BIT, status); +void ADS1115::triggerConversion() { + I2Cdev::writeBitW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_OS_BIT, 1); } /** Get multiplexer connection. * @return Current multiplexer connection setting diff --git a/Arduino/ADS1115/ADS1115.h b/Arduino/ADS1115/ADS1115.h index 244c03e8..b2eb5be5 100644 --- a/Arduino/ADS1115/ADS1115.h +++ b/Arduino/ADS1115/ADS1115.h @@ -69,8 +69,6 @@ THE SOFTWARE. #define ADS1115_CFG_COMP_QUE_BIT 1 #define ADS1115_CFG_COMP_QUE_LENGTH 2 -#define ADS1115_OS_INACTIVE 0x00 -#define ADS1115_OS_ACTIVE 0x01 #define ADS1115_MUX_P0_N1 0x00 // default #define ADS1115_MUX_P0_N3 0x01 @@ -141,6 +139,7 @@ class ADS1115 { // SINGLE SHOT utilities void waitBusy(uint16_t max_retries); + void triggerConversion(); // Read the current CONVERSION register int16_t getConversion(); @@ -162,8 +161,7 @@ class ADS1115 { float getMvPerCount(); // CONFIG register - uint8_t getOpStatus(); - void setOpStatus(uint8_t op); + bool isConversionReady(); uint8_t getMultiplexer(); void setMultiplexer(uint8_t mux); uint8_t getGain(); From d66b9832690bd67094cb3008453654f48b6ddd3e Mon Sep 17 00:00:00 2001 From: EAD Fritz Date: Tue, 22 Mar 2016 22:30:31 +0100 Subject: [PATCH 113/335] Renamed waitBusy() to pollConversion() because the method is not waiting. It is banging the I2C bus until conversion is ready. --- Arduino/ADS1115/ADS1115.cpp | 12 +++++++----- Arduino/ADS1115/ADS1115.h | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Arduino/ADS1115/ADS1115.cpp b/Arduino/ADS1115/ADS1115.cpp index 9918961f..ffe8a54a 100644 --- a/Arduino/ADS1115/ADS1115.cpp +++ b/Arduino/ADS1115/ADS1115.cpp @@ -79,15 +79,17 @@ bool ADS1115::testConnection() { return I2Cdev::readWord(devAddr, ADS1115_RA_CONVERSION, buffer) == 1; } -/** Wait until the single-shot conversion is finished +/** Poll the operational status bit until the conversion is finished * Retry at most 'max_retries' times - * conversion is finished, then return; - * @see ADS1115_OS_INACTIVE + * conversion is finished, then return true; + * @see ADS1115_CFG_OS_BIT + * @return True if data is available, false otherwise */ -void ADS1115::waitBusy(uint16_t max_retries) { +bool ADS1115::pollConversion(uint16_t max_retries) { for(uint16_t i = 0; i < max_retries; i++) { - if (getOpStatus()==ADS1115_OS_INACTIVE) break; + if (isConversionReady()) return true; } + return false; } /** Read differential value based on current MUX configuration. diff --git a/Arduino/ADS1115/ADS1115.h b/Arduino/ADS1115/ADS1115.h index b2eb5be5..cdffe288 100644 --- a/Arduino/ADS1115/ADS1115.h +++ b/Arduino/ADS1115/ADS1115.h @@ -138,7 +138,7 @@ class ADS1115 { bool testConnection(); // SINGLE SHOT utilities - void waitBusy(uint16_t max_retries); + bool pollConversion(uint16_t max_retries); void triggerConversion(); // Read the current CONVERSION register From 37c6c47c3c3ac92e93e06ec74f8d8bb83467128a Mon Sep 17 00:00:00 2001 From: EAD Fritz Date: Tue, 22 Mar 2016 22:32:09 +0100 Subject: [PATCH 114/335] Added setConversionReadyPinMode() --- Arduino/ADS1115/ADS1115.cpp | 12 ++++++++++++ Arduino/ADS1115/ADS1115.h | 1 + 2 files changed, 13 insertions(+) diff --git a/Arduino/ADS1115/ADS1115.cpp b/Arduino/ADS1115/ADS1115.cpp index ffe8a54a..acf2efcd 100644 --- a/Arduino/ADS1115/ADS1115.cpp +++ b/Arduino/ADS1115/ADS1115.cpp @@ -567,6 +567,18 @@ void ADS1115::setHighThreshold(int16_t threshold) { I2Cdev::writeWord(devAddr, ADS1115_RA_HI_THRESH, threshold); } +/** Configures ALERT/RDY pin as a conversion ready pin. + * It does this by setting the MSB of the high threshold register to '1' and the MSB + * of the low threshold register to '0'. COMP_POL and COMP_QUE bits will be set to '0'. + * Note: ALERT/RDY pin requires a pull up resistor. + */ +void ADS1115::setConversionReadyPinMode() { + I2Cdev::writeBitW(devAddr, ADS1115_RA_HI_THRESH, 15, 1); + I2Cdev::writeBitW(devAddr, ADS1115_RA_LO_THRESH, 15, 0); + setComparatorPolarity(0); + setComparatorQueueMode(0); +} + // Create a mask between two bits unsigned createMask(unsigned a, unsigned b) { unsigned mask = 0; diff --git a/Arduino/ADS1115/ADS1115.h b/Arduino/ADS1115/ADS1115.h index cdffe288..f1a1626d 100644 --- a/Arduino/ADS1115/ADS1115.h +++ b/Arduino/ADS1115/ADS1115.h @@ -178,6 +178,7 @@ class ADS1115 { void setComparatorLatchEnabled(bool enabled); uint8_t getComparatorQueueMode(); void setComparatorQueueMode(uint8_t mode); + void setConversionReadyPinMode(); // *_THRESH registers int16_t getLowThreshold(); From e015dacb16fdf76ceadd51eef3f92727a4786467 Mon Sep 17 00:00:00 2001 From: EAD Fritz Date: Tue, 22 Mar 2016 22:34:31 +0100 Subject: [PATCH 115/335] Added a triggerAndPoll parameter to getConversion() and getMilliVolts() --- Arduino/ADS1115/ADS1115.cpp | 29 +++++++++++++++-------------- Arduino/ADS1115/ADS1115.h | 4 ++-- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/Arduino/ADS1115/ADS1115.cpp b/Arduino/ADS1115/ADS1115.cpp index acf2efcd..3ab1b0e2 100644 --- a/Arduino/ADS1115/ADS1115.cpp +++ b/Arduino/ADS1115/ADS1115.cpp @@ -107,6 +107,8 @@ bool ADS1115::pollConversion(uint16_t max_retries) { * effortless, but it has enormous potential to save power by only running the * comparison circuitry when needed. * + * @param triggerAndPoll If true (and only in singleshot mode) the conversion trigger + * will be executed and the conversion results will be polled. * @return 16-bit signed differential value * @see getConversionP0N1(); * @see getConversionPON3(); @@ -127,12 +129,10 @@ bool ADS1115::pollConversion(uint16_t max_retries) { * @see ADS1115_MUX_P2_NG * @see ADS1115_MUX_P3_NG */ -int16_t ADS1115::getConversion() { - if (devMode == ADS1115_MODE_SINGLESHOT) - { - setOpStatus(ADS1115_OS_ACTIVE); - ADS1115::waitBusy(I2CDEV_DEFAULT_READ_TIMEOUT); - +int16_t ADS1115::getConversion(bool triggerAndPoll) { + if (triggerAndPoll && devMode == ADS1115_MODE_SINGLESHOT) { + triggerConversion(); + pollConversion(I2CDEV_DEFAULT_READ_TIMEOUT); } I2Cdev::readWord(devAddr, ADS1115_RA_CONVERSION, buffer); return buffer[0]; @@ -234,29 +234,30 @@ int16_t ADS1115::getConversionP3GND() { * Read the current differential and return it multiplied * by the constant for the current gain. mV is returned to * increase the precision of the voltage - * + * @param triggerAndPoll If true (and only in singleshot mode) the conversion trigger + * will be executed and the conversion results will be polled. */ -float ADS1115::getMilliVolts() { +float ADS1115::getMilliVolts(bool triggerAndPoll) { switch (pgaMode) { case ADS1115_PGA_6P144: - return (getConversion() * ADS1115_MV_6P144); + return (getConversion(triggerAndPoll) * ADS1115_MV_6P144); break; case ADS1115_PGA_4P096: - return (getConversion() * ADS1115_MV_4P096); + return (getConversion(triggerAndPoll) * ADS1115_MV_4P096); break; case ADS1115_PGA_2P048: - return (getConversion() * ADS1115_MV_2P048); + return (getConversion(triggerAndPoll) * ADS1115_MV_2P048); break; case ADS1115_PGA_1P024: - return (getConversion() * ADS1115_MV_1P024); + return (getConversion(triggerAndPoll) * ADS1115_MV_1P024); break; case ADS1115_PGA_0P512: - return (getConversion() * ADS1115_MV_0P512); + return (getConversion(triggerAndPoll) * ADS1115_MV_0P512); break; case ADS1115_PGA_0P256: case ADS1115_PGA_0P256B: case ADS1115_PGA_0P256C: - return (getConversion() * ADS1115_MV_0P256); + return (getConversion(triggerAndPoll) * ADS1115_MV_0P256); break; } } diff --git a/Arduino/ADS1115/ADS1115.h b/Arduino/ADS1115/ADS1115.h index f1a1626d..bfb607c0 100644 --- a/Arduino/ADS1115/ADS1115.h +++ b/Arduino/ADS1115/ADS1115.h @@ -142,7 +142,7 @@ class ADS1115 { void triggerConversion(); // Read the current CONVERSION register - int16_t getConversion(); + int16_t getConversion(bool triggerAndPoll=true); // Differential int16_t getConversionP0N1(); @@ -157,7 +157,7 @@ class ADS1115 { int16_t getConversionP3GND(); // Utility - float getMilliVolts(); + float getMilliVolts(bool triggerAndPoll=true); float getMvPerCount(); // CONFIG register From 2298ccf448977aa543ea6d3bf6dfafb76782d311 Mon Sep 17 00:00:00 2001 From: EAD Fritz Date: Tue, 22 Mar 2016 22:45:03 +0100 Subject: [PATCH 116/335] Clarified a comment --- Arduino/ADS1115/ADS1115.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Arduino/ADS1115/ADS1115.cpp b/Arduino/ADS1115/ADS1115.cpp index 3ab1b0e2..cffe4cce 100644 --- a/Arduino/ADS1115/ADS1115.cpp +++ b/Arduino/ADS1115/ADS1115.cpp @@ -310,7 +310,7 @@ bool ADS1115::isConversionReady() { return !!buffer[0]; } /** Set operational status. - * This bit can only be written while in power-down mode (no conversions active). + * Writing to this bit will only have effect while in power-down mode (no conversions active). * @see ADS1115_RA_CONFIG * @see ADS1115_CFG_OS_BIT */ From 73e6d40514378a3097a84d217b59f478d80789e1 Mon Sep 17 00:00:00 2001 From: EAD Fritz Date: Tue, 22 Mar 2016 23:02:22 +0100 Subject: [PATCH 117/335] getMode() was always returning 0 because it did a type-cast to uint8_t from uint16_t, unfortunately the important bit was cast away. So i changed the type all of the variables that only contain one bit to bool. --- Arduino/ADS1115/ADS1115.cpp | 23 +++++++++++------------ Arduino/ADS1115/ADS1115.h | 14 +++++++------- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/Arduino/ADS1115/ADS1115.cpp b/Arduino/ADS1115/ADS1115.cpp index cffe4cce..c3d7e873 100644 --- a/Arduino/ADS1115/ADS1115.cpp +++ b/Arduino/ADS1115/ADS1115.cpp @@ -307,9 +307,9 @@ float ADS1115::getMvPerCount() { */ bool ADS1115::isConversionReady() { I2Cdev::readBitW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_OS_BIT, buffer); - return !!buffer[0]; + return buffer[0]; } -/** Set operational status. +/** Trigger a new conversion. * Writing to this bit will only have effect while in power-down mode (no conversions active). * @see ADS1115_RA_CONFIG * @see ADS1115_CFG_OS_BIT @@ -400,9 +400,9 @@ void ADS1115::setGain(uint8_t gain) { * @see ADS1115_RA_CONFIG * @see ADS1115_CFG_MODE_BIT */ -uint8_t ADS1115::getMode() { +bool ADS1115::getMode() { I2Cdev::readBitW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_MODE_BIT, buffer); - devMode = (uint8_t)buffer[0]; + devMode = buffer[0]; return devMode; } /** Set device mode. @@ -412,7 +412,7 @@ uint8_t ADS1115::getMode() { * @see ADS1115_RA_CONFIG * @see ADS1115_CFG_MODE_BIT */ -void ADS1115::setMode(uint8_t mode) { +void ADS1115::setMode(bool mode) { if (I2Cdev::writeBitW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_MODE_BIT, mode)) { devMode = mode; } @@ -451,9 +451,9 @@ void ADS1115::setRate(uint8_t rate) { * @see ADS1115_RA_CONFIG * @see ADS1115_CFG_COMP_MODE_BIT */ -uint8_t ADS1115::getComparatorMode() { +bool ADS1115::getComparatorMode() { I2Cdev::readBitW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_COMP_MODE_BIT, buffer); - return (uint8_t)buffer[0]; + return buffer[0]; } /** Set comparator mode. * @param mode New comparator mode @@ -462,7 +462,7 @@ uint8_t ADS1115::getComparatorMode() { * @see ADS1115_RA_CONFIG * @see ADS1115_CFG_COMP_MODE_BIT */ -void ADS1115::setComparatorMode(uint8_t mode) { +void ADS1115::setComparatorMode(bool mode) { I2Cdev::writeBitW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_COMP_MODE_BIT, mode); } /** Get comparator polarity setting. @@ -472,9 +472,9 @@ void ADS1115::setComparatorMode(uint8_t mode) { * @see ADS1115_RA_CONFIG * @see ADS1115_CFG_COMP_POL_BIT */ -uint8_t ADS1115::getComparatorPolarity() { +bool ADS1115::getComparatorPolarity() { I2Cdev::readBitW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_COMP_POL_BIT, buffer); - return (uint8_t)buffer[0]; + return buffer[0]; } /** Set comparator polarity setting. * @param polarity New comparator polarity setting @@ -483,7 +483,7 @@ uint8_t ADS1115::getComparatorPolarity() { * @see ADS1115_RA_CONFIG * @see ADS1115_CFG_COMP_POL_BIT */ -void ADS1115::setComparatorPolarity(uint8_t polarity) { +void ADS1115::setComparatorPolarity(bool polarity) { I2Cdev::writeBitW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_COMP_POL_BIT, polarity); } /** Get comparator latch enabled value. @@ -645,6 +645,5 @@ void ADS1115::showConfigRegister() { Serial.println(getValueFromBits(configRegister, ADS1115_CFG_COMP_QUE_BIT,ADS1115_CFG_COMP_QUE_LENGTH), BIN); #endif - }; diff --git a/Arduino/ADS1115/ADS1115.h b/Arduino/ADS1115/ADS1115.h index bfb607c0..2ac68eea 100644 --- a/Arduino/ADS1115/ADS1115.h +++ b/Arduino/ADS1115/ADS1115.h @@ -166,14 +166,14 @@ class ADS1115 { void setMultiplexer(uint8_t mux); uint8_t getGain(); void setGain(uint8_t gain); - uint8_t getMode(); - void setMode(uint8_t mode); + bool getMode(); + void setMode(bool mode); uint8_t getRate(); void setRate(uint8_t rate); - uint8_t getComparatorMode(); - void setComparatorMode(uint8_t mode); - uint8_t getComparatorPolarity(); - void setComparatorPolarity(uint8_t polarity); + bool getComparatorMode(); + void setComparatorMode(bool mode); + bool getComparatorPolarity(); + void setComparatorPolarity(bool polarity); bool getComparatorLatchEnabled(); void setComparatorLatchEnabled(bool enabled); uint8_t getComparatorQueueMode(); @@ -192,7 +192,7 @@ class ADS1115 { private: uint8_t devAddr; uint16_t buffer[2]; - uint8_t devMode; + bool devMode; uint8_t muxMode; uint8_t pgaMode; }; From c7f870de777857d60f9bbcf1d018f99cacdbe7fd Mon Sep 17 00:00:00 2001 From: EAD Fritz Date: Wed, 23 Mar 2016 11:09:46 +0100 Subject: [PATCH 118/335] Added a "singleshot" mode example. It can get "conversion ready" information from an GPIO pin or by the normal i2c poll. --- .../ADS1115_single/ADS1115_single.ino | 110 ++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 Arduino/ADS1115/Examples/ADS1115_single/ADS1115_single.ino diff --git a/Arduino/ADS1115/Examples/ADS1115_single/ADS1115_single.ino b/Arduino/ADS1115/Examples/ADS1115_single/ADS1115_single.ino new file mode 100644 index 00000000..015b56f6 --- /dev/null +++ b/Arduino/ADS1115/Examples/ADS1115_single/ADS1115_single.ino @@ -0,0 +1,110 @@ +// I2C device class (I2Cdev) demonstration Arduino sketch for ADS1115 class +// Example of reading two differential inputs of the ADS1115 and showing the value in mV +// 2016-03-22 by Eadf (https://github.com/eadf) +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// 2016-03-22 - initial release + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2011 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#include "ADS1115.h" + +ADS1115 adc0(ADS1115_DEFAULT_ADDRESS); + +// Wire ADS1115 ALERT/RDY pin to Arduino pin 2 +const int alertReadyPin = 2; + +void setup() { + //I2Cdev::begin(); // join I2C bus + Wire.begin(); + Serial.begin(115200); // initialize serial communication + + Serial.println("Testing device connections..."); + Serial.println(adc0.testConnection() ? "ADS1115 connection successful" : "ADS1115 connection failed"); + + adc0.initialize(); // initialize ADS1115 16 bit A/D chip + + // We're going to do single shot sampling + adc0.setMode(ADS1115_MODE_SINGLESHOT); + + // Slow things down so that we can see that the "poll for conversion" code works + adc0.setRate(ADS1115_RATE_8); + + // Set the gain (PGA) +/- 6.144v + // Note that any analog input must be higher than –0.3V and less than VDD +0.3 + adc0.setGain(ADS1115_PGA_6P144); + // ALERT/RDY pin will indicate when conversion is ready + + pinMode(alertReadyPin,INPUT_PULLUP); + adc0.setConversionReadyPinMode(); + + // To get output from this method, you'll need to turn on the + //#define ADS1115_SERIAL_DEBUG // in the ADS1115.h file + #ifdef ADS1115_SERIAL_DEBUG + adc0.showConfigRegister(); + Serial.print("HighThreshold="); Serial.println(adc0.getHighThreshold(),BIN); + Serial.print("LowThreshold="); Serial.println(adc0.getLowThreshold(),BIN); + #endif +} + +/** Poll the assigned pin for conversion status + */ +void pollAlertReadyPin() { + for (uint32_t i = 0; i<100000; i++) + if (!digitalRead(alertReadyPin)) return; + Serial.println("Failed to wait for AlertReadyPin, it's stuck high!"); +} + +void loop() { + + // The below method sets the mux and gets a reading. + adc0.setMultiplexer(ADS1115_MUX_P0_NG); + adc0.triggerConversion(); + pollAlertReadyPin(); + Serial.print("A0: "); Serial.print(adc0.getMilliVolts(false)); Serial.print("mV\t"); + + adc0.setMultiplexer(ADS1115_MUX_P1_NG); + adc0.triggerConversion(); + pollAlertReadyPin(); + Serial.print("A1: "); Serial.print(adc0.getMilliVolts(false)); Serial.print("mV\t"); + + adc0.setMultiplexer(ADS1115_MUX_P2_NG); + adc0.triggerConversion(); + pollAlertReadyPin(); + Serial.print("A2: "); Serial.print(adc0.getMilliVolts(false)); Serial.print("mV\t"); + + adc0.setMultiplexer(ADS1115_MUX_P3_NG); + // Do conversion polling via I2C on this last reading: + Serial.print("A3: "); Serial.print(adc0.getMilliVolts(true)); Serial.print("mV"); + + Serial.println(digitalRead(alertReadyPin)); + delay(500); +} + + + + + From 2a71ced84055ef5103b813a8a356ce498695f68a Mon Sep 17 00:00:00 2001 From: EAD Fritz Date: Wed, 23 Mar 2016 13:43:58 +0100 Subject: [PATCH 119/335] Removed #include It is already included by DS1115.h (if the I2C implementation uses it) --- .../ADS1115_differential/ADS1115_differential.ino | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/Arduino/ADS1115/Examples/ADS1115_differential/ADS1115_differential.ino b/Arduino/ADS1115/Examples/ADS1115_differential/ADS1115_differential.ino index ef884d3e..a67b77bf 100644 --- a/Arduino/ADS1115/Examples/ADS1115_differential/ADS1115_differential.ino +++ b/Arduino/ADS1115/Examples/ADS1115_differential/ADS1115_differential.ino @@ -29,7 +29,6 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. =============================================== */ -#include #include "ADS1115.h" ADS1115 adc0(ADS1115_DEFAULT_ADDRESS); @@ -49,16 +48,14 @@ void setup() { // We're going to do continuous sampling adc0.setMode(ADS1115_MODE_CONTINUOUS); - } -void loop() - { +void loop() { // Sensor is on P0/N1 (pins 4/5) Serial.println("Sensor 1 ************************"); // Set the gain (PGA) +/- 1.024v - adc0.setGain(ADS1115_PGA_1P024 ); + adc0.setGain(ADS1115_PGA_1P024); // Get the number of counts of the accumulator Serial.print("Counts for sensor 1 is:"); @@ -69,7 +66,7 @@ void loop() // To turn the counts into a voltage, we can use Serial.print("Voltage for sensor 1 is:"); - Serial.println(sensorOneCounts*adc0.getMvPerCount() ); + Serial.println(sensorOneCounts*adc0.getMvPerCount()); Serial.println(); @@ -90,9 +87,5 @@ void loop() Serial.println(); delay(500); - } - - - - +} From a7343c0d2679f68498b97622efa8a2cc3c655730 Mon Sep 17 00:00:00 2001 From: EAD Fritz Date: Thu, 24 Mar 2016 22:16:51 +0100 Subject: [PATCH 120/335] Initial checkin --- .../Examples/HTU21D_simple/HTU21D_simple.ino | 51 ++++++++++ Arduino/HTU21D/HTU21D.cpp | 97 +++++++++++++++++++ Arduino/HTU21D/HTU21D.h | 63 ++++++++++++ Arduino/HTU21D/library.json | 18 ++++ 4 files changed, 229 insertions(+) create mode 100644 Arduino/HTU21D/Examples/HTU21D_simple/HTU21D_simple.ino create mode 100644 Arduino/HTU21D/HTU21D.cpp create mode 100644 Arduino/HTU21D/HTU21D.h create mode 100644 Arduino/HTU21D/library.json diff --git a/Arduino/HTU21D/Examples/HTU21D_simple/HTU21D_simple.ino b/Arduino/HTU21D/Examples/HTU21D_simple/HTU21D_simple.ino new file mode 100644 index 00000000..0b198fb4 --- /dev/null +++ b/Arduino/HTU21D/Examples/HTU21D_simple/HTU21D_simple.ino @@ -0,0 +1,51 @@ +// I2C device class (I2Cdev) demonstration Arduino sketch for HTU21D class +// Example of reading temperature and humidity from the HTU21D sensor +// 2016-03-24 by Eadf (https://github.com/eadf) +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// 2016-03-24 - initial release + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2016 Eadf, Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#include "HTU21D.h" + +HTU21D htu21d; + +void setup() { + //I2Cdev::begin(); // join I2C bus + Wire.begin(); + Serial.begin(38400); + htu21d.initialize(); + Serial.println("Testing device connections..."); + Serial.println(htu21d.testConnection() ? "HTU21D connection successful" : "HTU21D connection failed"); +} + +void loop() { + Serial.print("Temperature: "); Serial.print(htu21d.getTemperature()); + Serial.print("\t\tHumidity: "); Serial.println(htu21d.getHumidity()); + delay(400); +} + diff --git a/Arduino/HTU21D/HTU21D.cpp b/Arduino/HTU21D/HTU21D.cpp new file mode 100644 index 00000000..838c7fdd --- /dev/null +++ b/Arduino/HTU21D/HTU21D.cpp @@ -0,0 +1,97 @@ +// I2Cdev library collection - HTU21D I2C device class header file +// Based on MEAS HTU21D HPC199_2 HTU321(F) datasheet, October 2013 +// 2016-03-24 by https://github.com/eadf +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// 2016-03-24 - initial release + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2016 Eadf, Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#include "HTU21D.h" + + +/** Default constructor, uses default I2C address. + * @see HTU21D_DEFAULT_ADDRESS + */ +HTU21D::HTU21D() { + devAddr = HTU21D_DEFAULT_ADDRESS; +} + +/** Power on and prepare for general usage. + * This operation calls reset() on the HTU21D device and it takes at least 15milliseconds. + */ +void HTU21D::initialize() { + reset(); +} + +/** Verify the I2C connection. + * Make sure the device is connected and responds as expected. + * This operation calls reset() on the HTU21D device and it takes at least 15milliseconds. + * @return True if connection is valid, false otherwise + */ +bool HTU21D::testConnection() { + reset(); + buffer[0] = 0; + I2Cdev::readByte(devAddr, HTU21D_READ_USER_REGISTER, buffer); + return buffer[0] == 0x2; +} + +/** Reads and returns the temperature, ignores the CRC field. + * @return The measured temperature, or NaN if the operation failed. + */ +float HTU21D::getTemperature() { + // Ignore the CRC byte + uint16_t t = 0; + if (1!=I2Cdev::readWord(devAddr, HTU21D_RA_TEMPERATURE, &t)){ + return NAN; + } + // clear the status bits (bit0 & bit1) and calculate the temperature + // as per the formula in the datasheet + return ((float)(t&0xFFFC))*175.72/65536.0-46.85; +} + +/** Reads and returns the humidity, ignores the CRC field + * @return The measured humidity, or NaN if the operation failed. + */ +float HTU21D::getHumidity() { + // Ignore the CRC byte + uint16_t t = 0; + if (1!=I2Cdev::readWord(devAddr, HTU21D_RA_HUMIDITY, &t)){ + return NAN; + } + // clear the status bits (bit0 & bit1) and calculate the humidity + // as per the formula in the datasheet + return ((float)(t&0xFFFC))*125.0/65536.0-6.0; +} + +/** Does a soft reset of the HTU21D + * This operation takes at least 15milliseconds. + */ +void HTU21D::reset() { + I2Cdev::writeByte(devAddr, HTU21D_RESET, 0); + delay(15); +} + diff --git a/Arduino/HTU21D/HTU21D.h b/Arduino/HTU21D/HTU21D.h new file mode 100644 index 00000000..a5e277eb --- /dev/null +++ b/Arduino/HTU21D/HTU21D.h @@ -0,0 +1,63 @@ +// I2Cdev library collection - HTU21D I2C device class header file +// Based on MEAS HTU21D HPC199_2 HTU321(F) datasheet, October 2013 +// 2016-03-24 by https://github.com/eadf +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// 2016-03-24 - initial release + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2016 Eadf, Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#ifndef _HTU21D_H_ +#define _HTU21D_H_ + +#include "I2Cdev.h" + +#define HTU21D_DEFAULT_ADDRESS 0x40 + +#define HTU21D_RA_TEMPERATURE 0xE3 +#define HTU21D_RA_HUMIDITY 0xE5 +#define HTU21D_RESET 0xFE +#define HTU21D_WRITE_USER_REGISTER 0xE6 +#define HTU21D_READ_USER_REGISTER 0xE7 + +class HTU21D { + public: + HTU21D(); + + void initialize(); + bool testConnection(); + + float getTemperature(); + float getHumidity(); + + void reset(); + + private: + uint8_t devAddr; + uint8_t buffer[2]; +}; + +#endif /* _HTU21D_H_ */ diff --git a/Arduino/HTU21D/library.json b/Arduino/HTU21D/library.json new file mode 100644 index 00000000..6afea2ab --- /dev/null +++ b/Arduino/HTU21D/library.json @@ -0,0 +1,18 @@ +{ + "name": "I2Cdevlib-HTU21D”, + "keywords": “temperature, humidity, i2cdevlib, i2c", + "description": "HTU21D is 12-Bit humidity and 14-bit temperature sensor", + "include": "Arduino/HTU21D", + "repository": + { + "type": "git", + "url": "https://github.com/jrowberg/i2cdevlib.git" + }, + "dependencies": + { + "name": "I2Cdevlib-Core", + "frameworks": "arduino" + }, + "frameworks": "arduino", + "platforms": "atmelavr" +} From 1aca8fbf055fecf2d45c6a32d1288759cc939b2f Mon Sep 17 00:00:00 2001 From: ryanneve Date: Tue, 29 Mar 2016 12:49:01 -0400 Subject: [PATCH 121/335] Added MS5803 Pressure/Temperature sensor --- .../Examples/test_MS5803/test_MS5803.ino | 32 ++ Arduino/MS5803/MS5803.cpp | 352 ++++++++++++++++++ Arduino/MS5803/MS5803.h | 159 ++++++++ Arduino/MS5803/keywords.txt | 30 ++ 4 files changed, 573 insertions(+) create mode 100644 Arduino/MS5803/Examples/test_MS5803/test_MS5803.ino create mode 100644 Arduino/MS5803/MS5803.cpp create mode 100644 Arduino/MS5803/MS5803.h create mode 100644 Arduino/MS5803/keywords.txt diff --git a/Arduino/MS5803/Examples/test_MS5803/test_MS5803.ino b/Arduino/MS5803/Examples/test_MS5803/test_MS5803.ino new file mode 100644 index 00000000..15bb2f95 --- /dev/null +++ b/Arduino/MS5803/Examples/test_MS5803/test_MS5803.ino @@ -0,0 +1,32 @@ + + +#include +#include +#include + +//const uint8_t MS_MODEL = 1; // MS5803-01BA +//const uint8_t MS_MODEL = 2; // MS5803-02BA +const uint8_t MS_MODEL = 5; // MS5803-05BA +//const uint8_t MS_MODEL = 14; // MS5803-14BA +//const uint8_t MS_MODEL = 30; // MS5803-30BA + +MS5803 presstemp(0x76); +const uint8_t loop_delay = 10; // Seconds between readings +uint32_t wake_time = millis(); + + +void setup() { + Serial.begin(57600); + Wire.begin(); + // Start up and get Calubration constants. + presstemp.initialize(MS_MODEL); + if ( presstemp.testConnection() ) Serial.println("We are communicating with MS5803 via I2C."); + else Serial.println("I2C Communications with MS5803 failed."); +} +void loop(){ + Serial.print("Getting temperature"); + presstemp.calcMeasurements(ADC_4096); + Serial.print("The temperature is "); Serial.print(presstemp.getTemp_C()); Serial.println(" C"); + Serial.print("The pressure is "); Serial.print(presstemp.getPress_mBar()); Serial.println(" mBar"); + delay(2000); +} \ No newline at end of file diff --git a/Arduino/MS5803/MS5803.cpp b/Arduino/MS5803/MS5803.cpp new file mode 100644 index 00000000..e3459b5b --- /dev/null +++ b/Arduino/MS5803/MS5803.cpp @@ -0,0 +1,352 @@ +// I2Cdev library collection - MS5803 I2C device class +// Based on Measurement Specialties MS5803 document, 3/25/2013 (DA5803-01BA_010) +// 4/12/2014 by Ryan Neve +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// ... - ongoing debug release + +// NOTE: THIS IS ONLY A PARIAL RELEASE. THIS DEVICE CLASS IS CURRENTLY UNDERGOING ACTIVE +// DEVELOPMENT AND IS STILL MISSING SOME IMPORTANT FEATURES. PLEASE KEEP THIS IN MIND IF +// YOU DECIDE TO USE THIS PARTICULAR CODE FOR ANYTHING. + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2014 Ryan Neve + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ +//#define MS5803_DEBUG +#include "MS5803.h" + +const static uint8_t INIT_TRIES = 3; + + +const char* CALIBRATION_CONSTANTS[] = { + "_c1_SENSt1", + "_c2_OFFt1", + "_c3_TCS", + "_c4_TCO", + "_c5_Tref", + "_c6_TEMPSENS" +}; + +/** Default constructor, uses default I2C address. +* @see MPU6050_DEFAULT_ADDRESS +*/ +MS5803::MS5803() { MS5803(MS5803_DEFAULT_ADDRESS);} + +/** Specific address constructor. +* @param address I2C address +* @see MS5803_DEFAULT_ADDRESS +* @see MS5803_ADDRESS_AD0_LOW +* @see MS5803_ADDRESS_AD0_HIGH +*/ +MS5803::MS5803(uint8_t address) { + setAddress(address); + _initialized = false; + _c1_SENSt1 = 0; + _c2_OFFt1 = 0; + _c3_TCS = 0; + _c4_TCO = 0; + _c5_Tref = 0; + _c6_TEMPSENS = 0; +} +// Because sometimes you want to set the address later. +void MS5803::setAddress(uint8_t address) { + _dev_address = address; +} + +/** Power on and prepare for general usage. +* This will reset the device to make sure that the calibration PROM gets loaded into +* the internal register. It will then read the PROM +*/ +bool MS5803::initialize(uint8_t model) { + press_atmospheric = 1.015; //default, can be changed. + _initialized = false; + switch (model) { + case ( 1): _model = BA01; break; + case ( 2): _model = BA02; break; + case ( 5): _model = BA05; break; + case (14): _model = BA14; break; + case (30): _model = BA30; break; + default: + Serial.print(F("MS5803 Model entered (")); Serial.print(model); Serial.println(F(") is not valid/supported.")); + _model = INVALID; + return 0; + } + //if ( _debug ) Serial.print("MS5803 Model entered "); Serial.print(model); Serial.println("-ATM IS supported."); + if (_debug) Serial.println(reset()); + uint8_t tries = 0; + do { + _getCalConstants(); // Seems to partially fail the first try sometimes. + if (_c1_SENSt1 && _c2_OFFt1 && _c3_TCS && _c4_TCO && _c5_Tref && _c6_TEMPSENS ) _initialized = true; // They must all be non-0 + tries++; + } while (!_initialized && ( tries < INIT_TRIES) ); + if (_debug) { + for ( uint8_t i = 1 ; i <= 6; i++){ + Serial.print(i); + Serial.print(": "); + Serial.print(CALIBRATION_CONSTANTS[i-1]); + Serial.print(" = "); + Serial.println(_getCalConstant(i)); + } + } + return _initialized; +} + +bool MS5803::testConnection(){ + uint8_t reg_address = CMD_ADC_CONV + TEMPERATURE + ADC_256; + return I2Cdev::writeBytes(_dev_address,reg_address,0,_buffer); +} + +uint16_t MS5803::reset(){ + // Not sure how to send no buffer to an address. + return I2Cdev::writeBytes(_dev_address, MS5803_RESET,0,_buffer); +} + +void MS5803::_getCalConstants(){ + /* Query and parse calibration constants */ + I2Cdev::readBytes(_dev_address,MS5803_PROM_C1,2,_buffer); + _c1_SENSt1 = (((uint16_t)_buffer[0] << 8) + _buffer[1]); + I2Cdev::readBytes(_dev_address,MS5803_PROM_C2,2,_buffer); + _c2_OFFt1 = (((uint16_t)_buffer[0] << 8) + _buffer[1]); + I2Cdev::readBytes(_dev_address,MS5803_PROM_C3,2,_buffer); + _c3_TCS = (((uint16_t)_buffer[0] << 8) + _buffer[1]); + I2Cdev::readBytes(_dev_address,MS5803_PROM_C4,2,_buffer); + _c4_TCO = (((uint16_t)_buffer[0] << 8) + _buffer[1]); + I2Cdev::readBytes(_dev_address,MS5803_PROM_C5,2,_buffer); + _c5_Tref = (((uint16_t)_buffer[0] << 8) + _buffer[1]); + I2Cdev::readBytes(_dev_address,MS5803_PROM_C6,2,_buffer); + _c6_TEMPSENS = (((uint16_t)_buffer[0] << 8) + _buffer[1]); +} + +int32_t MS5803::_getCalConstant(uint8_t constant_no){ + switch ( constant_no ) { + case 1: return _c1_SENSt1; + case 2: return _c2_OFFt1; + case 3: return _c3_TCS; + case 4: return _c4_TCO; + case 5: return _c5_Tref; + case 6: return _c6_TEMPSENS; + default: return 0; + } +} + + +void MS5803::calcMeasurements(precision _precision){ + // Get raw temperature and pressure values + _d2_temperature = _getADCconversion(TEMPERATURE, _precision); + _d1_pressure = _getADCconversion(PRESSURE, _precision); + + //Now that we have a raw temperature, let's compute our actual. + _dT = _d2_temperature - ((int32_t)_c5_Tref << 8); + double temp_dT = _dT / (double)pow(2,23); + _TEMP = 2000 + (int32_t)(temp_dT * _c6_TEMPSENS); + if ( _debug ) { + Serial.println("Raw values:"); + Serial.print(" _d2_temperature = "); Serial.println(_d2_temperature); + Serial.print(" _d1_pressure = "); Serial.println(_d1_pressure); + Serial.println("First order values:"); + Serial.print(" _dT = "); Serial.println(_dT); + Serial.print(" _TEMP = "); Serial.println(_TEMP); + } + // Every variant does the calculations differently, so... + int64_t T2 = 0; + int64_t off2 = 0; + int64_t sens2 = 0; + switch (_model) { + case (BA01): //MS5803-01----------------------------------------------------------- + _OFF = ((int64_t)_c2_OFFt1 << 16 ) + ((((int64_t)_c4_TCO * (int64_t)_dT)) >> 7 ); + _SENS = ((int64_t)_c1_SENSt1 << 15 ) + ((((int64_t)_c3_TCS * (int64_t)_dT)) >> 8 ); + // 2nd Order calculations + if ( _TEMP < 2000.0) { // Is temperature below or above 20.00 deg C ? + T2 = 3 * pow(_dT,2)/(int64_t)pow(2,31); + off2 = 3 * pow((_TEMP - 2000.0),2); + sens2 = 7 * pow((_TEMP - 2000.0),2) / 8; + if ( _TEMP < 1500.0 ) sens2 += 2 * pow((_TEMP + 1500.0),2);// below 15C + } + else { + T2 = 0; + off2 = 0; + sens2 = 0; + if ( _TEMP >= 4500.0 ) { + sens2 -= ((int64_t)pow((_TEMP - 4500.0),2) >> 3); + } + } + break; + case (BA02): //MS5803-02----------------------------------------------------------- + _OFF = ((int64_t)_c2_OFFt1 << 17 ) + ((((int64_t)_c4_TCO * (int64_t)_dT)) >> 6 ); + _SENS = ((int64_t)_c1_SENSt1 << 16 ) + ((((int64_t)_c3_TCS * (int64_t)_dT)) >> 7 ); + // 2nd Order calculations + if ( _TEMP < 2000.0) { // Is temperature below or above 20.00 deg C ? + T2 = 3 * pow(_dT,2)/(int64_t)pow(2,31); + off2 = 61 * pow((_TEMP - 2000.0),2) / 16; + sens2 = 2 * pow(((int64_t)_TEMP - 2000.0),2); + if ( _TEMP < 1500.0 ) { // below 15C + off2 += 20 * pow((_TEMP + 1500.0),2); + sens2 += 12 * pow((_TEMP + 1500.0),2); + } + } + else { + T2 = 0; + off2 = 0; + sens2 = 0; + } + break; + case (BA05): //MS5803-05----------------------------------------------------------- + _OFF = ((int64_t)_c2_OFFt1 << 18 ) + ((((int64_t)_c4_TCO * (int64_t)_dT)) >> 5 ); + _SENS = ((int64_t)_c1_SENSt1 << 17 ) + ((((int64_t)_c3_TCS * (int64_t)_dT)) >> 7 ); + // 2nd Order calculations + if ( _TEMP < 2000.0) { // Is temperature below or above 20.00 deg C ? + T2 = 3 * pow(_dT,2)/(int64_t)pow(2,33); + off2 = 3 * pow((_TEMP - 2000.0),2) / 8; + sens2 = 7 * pow((_TEMP - 2000.0),2) / 8; + if ( _TEMP < -1500.0 ) { // below -15C + sens2 += 3 * pow((_TEMP + 1500.0),2); + } + } + else { + T2 = 0; + off2 = 0; + sens2 = 0; + } + break; + case (BA14): //MS5803-14----------------------------------------------------------- + // 14 and 30 are the same calculations... + case (BA30): //MS5803-30----------------------------------------------------------- + _OFF = ((int64_t)_c2_OFFt1 << 16 ) + ((((int64_t)_c4_TCO * (int64_t)_dT)) >> 7 ); + _SENS = ((int64_t)_c1_SENSt1 << 15 ) + ((((int64_t)_c3_TCS * (int64_t)_dT)) >> 8 ); + // 2nd Order calculations + if ( _TEMP < 2000.0) { // Is temperature below or above 20.00 deg C ? + T2 = 3 * pow(_dT,2)/(int64_t)pow(2,33); + off2 = 3 * pow((_TEMP - 2000.0),2) / 2; + sens2 = 5 * pow((_TEMP - 2000.0),2) / 8; + if ( _TEMP < 1500.0 ) { // below 15C + off2 += 7 * pow((_TEMP + 1500.0),2); + sens2 += 4 * pow((_TEMP + 1500.0),2); + } + } + else { + T2 = 7 * ((int64_t)_dT * _dT) >> 37; + off2 = 1 * (pow((_TEMP - 2000.0),2)) / 16; + sens2 = 0; + } + break; + default: + _OFF = 0; + _SENS = 0; + T2 = 0; + sens2 = 0; + off2 = 0; + } + if ( _debug ) { + Serial.print(" _OFF = "); serialPrintln64(_OFF); + Serial.print(" _SENS = "); serialPrintln64(_SENS); + } + // Second Order + _TEMP -= T2; + _SENS -= sens2; + _OFF -= off2; + if ( _debug ) { + Serial.println("Second order values:"); + Serial.print(" T2 = "); serialPrintln64(T2); + Serial.print(" sens2 = "); serialPrintln64(sens2); + Serial.print(" off2 = "); serialPrintln64(off2); + Serial.print(" _TEMP = "); Serial.println(_TEMP); + Serial.print(" _SENS = "); serialPrintln64(_SENS); + Serial.print(" _OFF = "); serialPrintln64(_OFF); + } + // Now pressure + switch (_model) { + case (BA05): //MS5803-05----------------------------------------------------------- + _P = ((((int32_t)_d1_pressure * _SENS) >> 21 ) - _OFF) >> 15; + _P /= 10; // NO IDEA WHY THIS NEEDS TO BE DONE. PERHAPS AN ERROR IN THE DATASHEET? + break; + case (BA01): //MS5803-01----------------------------------------------------------- + case (BA02): //MS5803-02----------------------------------------------------------- + case (BA14): //MS5803-14----------------------------------------------------------- + _P = ((((int32_t)_d1_pressure * _SENS) >> 21 ) - _OFF) >> 15; + break; + case (BA30): //MS5803-30----------------------------------------------------------- + _P = ((((int32_t)_d1_pressure * _SENS) >> 21 ) - _OFF) >> 13; + break; + default: + _P = 0; + } + if ( _debug ) { + Serial.println("Pressure:"); + Serial.print(" _P = "); Serial.println(_P); + } + // Conversions to common units + temp_C = (float)_TEMP / 100.0; + press_mBar = (float)_P / 10.0; + press_kPa = press_mBar / 10.0; + press_gauge = press_mBar - press_atmospheric; + press_psi = press_gauge * 14.50377; + depth_fresh = (press_mBar/100) * 1.019716; +} + +int32_t MS5803::_getADCconversion(measurement _measurement, precision _precision){ + // Retrieve ADC measurement from the device. + // Select measurement type and precision + uint32_t result; + uint8_t reg_address = CMD_ADC_CONV + _measurement + _precision; + uint8_t write_length = 0; + uint8_t read_length = 3; + uint16_t read_timeout = 2000; + //sendCommand(CMD_ADC_CONV + _measurement + _precision); + I2Cdev::writeBytes(_dev_address,reg_address,write_length,_buffer); // buffer is ignored when write_length is 0 + + // Wait for conversion to complete + delay(1); //general delay + switch( _precision ) + { + case ADC_256 : delay(1); break; + case ADC_512 : delay(3 >> CLKPR); break; + case ADC_1024: delay(4 >> CLKPR); break; + case ADC_2048: delay(6 >> CLKPR); break; + case ADC_4096: delay(10 >> CLKPR); break; + } + I2Cdev::readBytes(_dev_address,MS5803_ADC_READ,read_length,_buffer,read_timeout); + result = ((uint32_t)_buffer[0] << 16) + ((uint32_t)_buffer[1] << 8) + _buffer[2]; + if (_debug) { + Serial.print("Reading MS5803 ADC"); + switch (_measurement) { + case PRESSURE: Serial.println(" Pressure: " ); break; + case TEMPERATURE: Serial.println(" Temperature: "); break; + } + Serial.print(" buffer[0] = "); Serial.println(_buffer[0]); + Serial.print(" buffer[1] = "); Serial.println(_buffer[1]); + Serial.print(" buffer[2] = "); Serial.println(_buffer[2]); + } + return result; +} + +void serialPrintln64(int64_t val64){ + serialPrint64(val64); + Serial.println(); +} +void serialPrint64(int64_t val64){ + int32_t result_high = val64 / 10000000L; + int32_t result_low = val64 - (10000000LL * result_high); + Serial.print(result_high); + Serial.print(result_low); +} \ No newline at end of file diff --git a/Arduino/MS5803/MS5803.h b/Arduino/MS5803/MS5803.h new file mode 100644 index 00000000..397e8367 --- /dev/null +++ b/Arduino/MS5803/MS5803.h @@ -0,0 +1,159 @@ +// I2Cdev library collection - MS5803 I2C device class +// Based on Measurement Specialties MS5803 document, 3/25/2013 (DA5803-01BA_010) +// 4/12/2014 by Ryan Neve +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// ... - ongoing debug release + +// NOTE: THIS IS ONLY A PARIAL RELEASE. THIS DEVICE CLASS IS CURRENTLY UNDERGOING ACTIVE +// DEVELOPMENT AND IS STILL MISSING SOME IMPORTANT FEATURES. PLEASE KEEP THIS IN MIND IF +// YOU DECIDE TO USE THIS PARTICULAR CODE FOR ANYTHING. + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2014 Ryan Neve + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#ifndef _MS5803_H_ +#define _MS5803_H_ + +#define I2CDEV_SERIAL_DEBUG + +#include "I2Cdev.h" +#include + +#define MS5803_ADDRESS +// Should convert these to enum +#define MS5803_ADDRESS_AD0_LOW 0x77 // address pin low (GND), default for InvenSense evaluation board +#define MS5803_ADDRESS_AD0_HIGH 0x76 // address pin high (VCC) + +#define MS5803_DEFAULT_ADDRESS MS5803_ADDRESS_AD0_LOW + +#define MS5803_RESET 0x1E + +#define MS5803_PROM_BASE 0xA0 +#define MS5803_PROM_C1 0xA2 +#define MS5803_PROM_C2 0xA4 +#define MS5803_PROM_C3 0xA6 +#define MS5803_PROM_C4 0xA8 +#define MS5803_PROM_C5 0xAA +#define MS5803_PROM_C6 0xAC +#define MS5803_PROM_CRC 0xAE + + + +#define MS5803_ADC_READ 0x00 +#define CMD_ADC_CONV 0x40 // ADC conversion command + +// Define measurement type. +enum measurement +{ + PRESSURE = 0x00, + TEMPERATURE = 0x10 +}; + +// Define constants for Conversion precision +enum precision +{ + ADC_256 = 0x00, + ADC_512 = 0x02, + ADC_1024 = 0x04, + ADC_2048 = 0x06, + ADC_4096 = 0x08 +}; + +enum ms5803_model +{ + INVALID = 0, + BA01 = 1, + BA02 = 2, + BA05 = 5, + BA14 = 14, + BA30 = 30 +}; + +class MS5803 { + public: + MS5803(); + MS5803(uint8_t address); + + void setAddress(uint8_t address); + uint8_t getAddress() {return _dev_address;} + bool initialize(uint8_t model); + bool testConnection(); + uint16_t reset(); + void setAtmospheric(float pressure) {press_atmospheric = pressure;} + void calcMeasurements(precision _precision); + // getters + int32_t getD1Pressure() { return _d1_pressure; } + int32_t getD2Temperature() { return _d2_temperature;} + float getTemp_C() {return temp_C;} + float getPress_mBar() {return press_mBar;} + float getPress_kPa() {return press_kPa;} + bool initialized() {return _initialized;} + bool getDebug() { return _debug; } + void setDebug(bool debug) { _debug = debug; } + + uint16_t resolution; + float temp_C; + float press_mBar; + float press_kPa; + float press_atmospheric; + float press_gauge; + float press_psi; + float depth_fresh; + protected: + private: + void _getCalConstants(); + int32_t _getCalConstant(uint8_t constant_no); + int32_t _getADCconversion(measurement _measurement, precision _precision); + // Calibration Constants + int32_t _c1_SENSt1; // Pressure Sensitivity + int32_t _c2_OFFt1; // Pressure Offset + int32_t _c3_TCS; // Temperature coefficient of pressure sensitivity + int32_t _c4_TCO; // Temperature coefficient of pressure offset + int32_t _c5_Tref; // Reference Temperature + int32_t _c6_TEMPSENS; // Temperature coefficient of the temperature + // pressure and temperature data + int32_t _d1_pressure; // AdcPressure + int32_t _d2_temperature; // AdcTemperature + // Calculated values + int32_t _dT; //TempDifference + int32_t _TEMP; // Actual temperature -40 to 85C with .01 resolution (divide by 100) - Temperature float + // Temperature compensated pressure + int64_t _OFF; // First Order Offset at actual temperature // Offset - float + int64_t _SENS; // Sensitivity at actual temperature // Sensitivity - float + int32_t _P; // Temperature compensated pressure 10...1300 mbar (divide by 100 to get mBar) + uint8_t _buffer[14]; + uint8_t _dev_address; + ms5803_model _model; // the suffix after ms5803. E.g 2 for MS5803-02 indicates range. + bool _initialized; + bool _debug; +}; + +// Function prototype: +void serialPrintln64(int64_t val64); +void serialPrint64(int64_t val64); + + +#endif \ No newline at end of file diff --git a/Arduino/MS5803/keywords.txt b/Arduino/MS5803/keywords.txt new file mode 100644 index 00000000..01e9604b --- /dev/null +++ b/Arduino/MS5803/keywords.txt @@ -0,0 +1,30 @@ +########################################### +# Syntax Coloring Map For LiquidCrystal_I2C +########################################### + +########################################### +# Datatypes (KEYWORD1) +########################################### + +MS5803 KEYWORD1 + +########################################### +# Methods and Functions (KEYWORD2) +########################################### +setAddress KEYWORD2 +getAddress KEYWORD2 +initialize KEYWORD2 +testConnection KEYWORD2 +setAtmospheric KEYWORD2 +calcMeasurements KEYWORD2 +getD1Pressure KEYWORD2 +getD2Temperature KEYWORD2 +getTemp_C KEYWORD2 +getPress_mBar KEYWORD2 +getPress_kPa KEYWORD2 +initialized KEYWORD2 +getDebug KEYWORD2 +setDebug KEYWORD2 +########################################### +# Constants (LITERAL1) +########################################### \ No newline at end of file From 17987d5167a16a0092f527f2a6e7ee4d86f4a34c Mon Sep 17 00:00:00 2001 From: ryanneve Date: Wed, 30 Mar 2016 08:33:12 -0400 Subject: [PATCH 122/335] Cleaned up documentation Moved some calculations into the getters. Updated keywords.txt --- Arduino/MS5803/MS5803.cpp | 50 ++++++++++----------- Arduino/MS5803/MS5803.h | 86 ++++++++++++++++++------------------- Arduino/MS5803/keywords.txt | 22 +++++++--- 3 files changed, 82 insertions(+), 76 deletions(-) diff --git a/Arduino/MS5803/MS5803.cpp b/Arduino/MS5803/MS5803.cpp index e3459b5b..0f9d68cd 100644 --- a/Arduino/MS5803/MS5803.cpp +++ b/Arduino/MS5803/MS5803.cpp @@ -1,6 +1,6 @@ // I2Cdev library collection - MS5803 I2C device class // Based on Measurement Specialties MS5803 document, 3/25/2013 (DA5803-01BA_010) -// 4/12/2014 by Ryan Neve +// 3/29/2016 by Ryan Neve // Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib // // Changelog: @@ -33,10 +33,10 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. =============================================== */ -//#define MS5803_DEBUG -#include "MS5803.h" +#include "MS5803_I2C.h" const static uint8_t INIT_TRIES = 3; +const static uint16_t PRESS_ATM_MBAR_DEFAULT = 1015; const char* CALIBRATION_CONSTANTS[] = { @@ -68,6 +68,7 @@ MS5803::MS5803(uint8_t address) { _c4_TCO = 0; _c5_Tref = 0; _c6_TEMPSENS = 0; + _press_atm_mBar = (float)PRESS_ATM_MBAR_DEFAULT/1000.0; //default, can be changed with setAtmospheric() } // Because sometimes you want to set the address later. void MS5803::setAddress(uint8_t address) { @@ -76,11 +77,11 @@ void MS5803::setAddress(uint8_t address) { /** Power on and prepare for general usage. * This will reset the device to make sure that the calibration PROM gets loaded into -* the internal register. It will then read the PROM +* the internal register. It will then read the calibration constants from the PROM */ bool MS5803::initialize(uint8_t model) { - press_atmospheric = 1.015; //default, can be changed. _initialized = false; + // Make sure model is valid. switch (model) { case ( 1): _model = BA01; break; case ( 2): _model = BA02; break; @@ -92,7 +93,6 @@ bool MS5803::initialize(uint8_t model) { _model = INVALID; return 0; } - //if ( _debug ) Serial.print("MS5803 Model entered "); Serial.print(model); Serial.println("-ATM IS supported."); if (_debug) Serial.println(reset()); uint8_t tries = 0; do { @@ -112,6 +112,7 @@ bool MS5803::initialize(uint8_t model) { return _initialized; } +// See if we can communicate bool MS5803::testConnection(){ uint8_t reg_address = CMD_ADC_CONV + TEMPERATURE + ADC_256; return I2Cdev::writeBytes(_dev_address,reg_address,0,_buffer); @@ -150,12 +151,13 @@ int32_t MS5803::_getCalConstant(uint8_t constant_no){ } } - +/* This function communicates with the sensor and does all the math to convert + raw values to good data. Data can be accessed with various getters. +*/ void MS5803::calcMeasurements(precision _precision){ // Get raw temperature and pressure values _d2_temperature = _getADCconversion(TEMPERATURE, _precision); _d1_pressure = _getADCconversion(PRESSURE, _precision); - //Now that we have a raw temperature, let's compute our actual. _dT = _d2_temperature - ((int32_t)_c5_Tref << 8); double temp_dT = _dT / (double)pow(2,23); @@ -168,10 +170,11 @@ void MS5803::calcMeasurements(precision _precision){ Serial.print(" _dT = "); Serial.println(_dT); Serial.print(" _TEMP = "); Serial.println(_TEMP); } - // Every variant does the calculations differently, so... + // Second order variables int64_t T2 = 0; int64_t off2 = 0; int64_t sens2 = 0; + // Every variant does the calculations differently, so... switch (_model) { case (BA01): //MS5803-01----------------------------------------------------------- _OFF = ((int64_t)_c2_OFFt1 << 16 ) + ((((int64_t)_c4_TCO * (int64_t)_dT)) >> 7 ); @@ -265,24 +268,15 @@ void MS5803::calcMeasurements(precision _precision){ _TEMP -= T2; _SENS -= sens2; _OFF -= off2; - if ( _debug ) { - Serial.println("Second order values:"); - Serial.print(" T2 = "); serialPrintln64(T2); - Serial.print(" sens2 = "); serialPrintln64(sens2); - Serial.print(" off2 = "); serialPrintln64(off2); - Serial.print(" _TEMP = "); Serial.println(_TEMP); - Serial.print(" _SENS = "); serialPrintln64(_SENS); - Serial.print(" _OFF = "); serialPrintln64(_OFF); - } // Now pressure switch (_model) { case (BA05): //MS5803-05----------------------------------------------------------- _P = ((((int32_t)_d1_pressure * _SENS) >> 21 ) - _OFF) >> 15; _P /= 10; // NO IDEA WHY THIS NEEDS TO BE DONE. PERHAPS AN ERROR IN THE DATASHEET? break; - case (BA01): //MS5803-01----------------------------------------------------------- - case (BA02): //MS5803-02----------------------------------------------------------- - case (BA14): //MS5803-14----------------------------------------------------------- + case (BA01): //MS5803-01--passthrough---------------------------------------------- + case (BA02): //MS5803-02--passthrough---------------------------------------------- + case (BA14): //MS5803-14--passthrough---------------------------------------------- _P = ((((int32_t)_d1_pressure * _SENS) >> 21 ) - _OFF) >> 15; break; case (BA30): //MS5803-30----------------------------------------------------------- @@ -292,16 +286,16 @@ void MS5803::calcMeasurements(precision _precision){ _P = 0; } if ( _debug ) { + Serial.println("Second order values:"); + Serial.print(" T2 = "); serialPrintln64(T2); + Serial.print(" sens2 = "); serialPrintln64(sens2); + Serial.print(" off2 = "); serialPrintln64(off2); + Serial.print(" _TEMP = "); Serial.println(_TEMP); + Serial.print(" _SENS = "); serialPrintln64(_SENS); + Serial.print(" _OFF = "); serialPrintln64(_OFF); Serial.println("Pressure:"); Serial.print(" _P = "); Serial.println(_P); } - // Conversions to common units - temp_C = (float)_TEMP / 100.0; - press_mBar = (float)_P / 10.0; - press_kPa = press_mBar / 10.0; - press_gauge = press_mBar - press_atmospheric; - press_psi = press_gauge * 14.50377; - depth_fresh = (press_mBar/100) * 1.019716; } int32_t MS5803::_getADCconversion(measurement _measurement, precision _precision){ diff --git a/Arduino/MS5803/MS5803.h b/Arduino/MS5803/MS5803.h index 397e8367..c6b6de21 100644 --- a/Arduino/MS5803/MS5803.h +++ b/Arduino/MS5803/MS5803.h @@ -66,15 +66,13 @@ THE SOFTWARE. #define CMD_ADC_CONV 0x40 // ADC conversion command // Define measurement type. -enum measurement -{ +enum measurement { PRESSURE = 0x00, TEMPERATURE = 0x10 }; // Define constants for Conversion precision -enum precision -{ +enum precision { ADC_256 = 0x00, ADC_512 = 0x02, ADC_1024 = 0x04, @@ -82,8 +80,7 @@ enum precision ADC_4096 = 0x08 }; -enum ms5803_model -{ +enum ms5803_model { INVALID = 0, BA01 = 1, BA02 = 2, @@ -92,6 +89,10 @@ enum ms5803_model BA30 = 30 }; + +const static float FRESH_WATER_CONSTANT = 1.019716; // kg/m^3 +const static float BAR_IN_PSI = 14.50377; + class MS5803 { public: MS5803(); @@ -100,55 +101,54 @@ class MS5803 { void setAddress(uint8_t address); uint8_t getAddress() {return _dev_address;} bool initialize(uint8_t model); + bool initialized() {return _initialized;} bool testConnection(); + void calcMeasurements(precision _precision); // Here's where the heavy lifting occurs. uint16_t reset(); - void setAtmospheric(float pressure) {press_atmospheric = pressure;} - void calcMeasurements(precision _precision); - // getters - int32_t getD1Pressure() { return _d1_pressure; } - int32_t getD2Temperature() { return _d2_temperature;} - float getTemp_C() {return temp_C;} - float getPress_mBar() {return press_mBar;} - float getPress_kPa() {return press_kPa;} - bool initialized() {return _initialized;} - bool getDebug() { return _debug; } + + // Setters + void setAtmospheric(float pressure) {_press_atm_mBar = pressure;} void setDebug(bool debug) { _debug = debug; } - - uint16_t resolution; - float temp_C; - float press_mBar; - float press_kPa; - float press_atmospheric; - float press_gauge; - float press_psi; - float depth_fresh; + + // Getters + bool getDebug() { return _debug; } + float getTemp_C() {return (float)_TEMP / 100.0;} + float getPress_mBar() {return (float)_P / 10.0;} + float getPress_kPa() {return (float)_P / 100.0;} + float getPress_gauge() {return ((float)_P / 10.0) - _press_atm_mBar;} + float getPress_psi() {return (((float)_P / 10.0) - _press_atm_mBar) * BAR_IN_PSI;} + float getDepthFresh_m() {return ((float)_P/1000.0) * FRESH_WATER_CONSTANT;} + + protected: private: void _getCalConstants(); int32_t _getCalConstant(uint8_t constant_no); int32_t _getADCconversion(measurement _measurement, precision _precision); - // Calibration Constants - int32_t _c1_SENSt1; // Pressure Sensitivity - int32_t _c2_OFFt1; // Pressure Offset - int32_t _c3_TCS; // Temperature coefficient of pressure sensitivity - int32_t _c4_TCO; // Temperature coefficient of pressure offset - int32_t _c5_Tref; // Reference Temperature - int32_t _c6_TEMPSENS; // Temperature coefficient of the temperature - // pressure and temperature data - int32_t _d1_pressure; // AdcPressure - int32_t _d2_temperature; // AdcTemperature - // Calculated values - int32_t _dT; //TempDifference - int32_t _TEMP; // Actual temperature -40 to 85C with .01 resolution (divide by 100) - Temperature float - // Temperature compensated pressure - int64_t _OFF; // First Order Offset at actual temperature // Offset - float - int64_t _SENS; // Sensitivity at actual temperature // Sensitivity - float - int32_t _P; // Temperature compensated pressure 10...1300 mbar (divide by 100 to get mBar) uint8_t _buffer[14]; uint8_t _dev_address; - ms5803_model _model; // the suffix after ms5803. E.g 2 for MS5803-02 indicates range. + ms5803_model _model; // the suffix after ms5803. E.g 2 for MS5803-02 indicates range. bool _initialized; bool _debug; + // Calibration Constants + int32_t _c1_SENSt1; // Pressure Sensitivity + int32_t _c2_OFFt1; // Pressure Offset + int32_t _c3_TCS; // Temperature coefficient of pressure sensitivity + int32_t _c4_TCO; // Temperature coefficient of pressure offset + int32_t _c5_Tref; // Reference Temperature + int32_t _c6_TEMPSENS; // Temperature coefficient of the temperature + // intermediate pressure and temperature data + int32_t _d1_pressure; // AdcPressure + int32_t _d2_temperature;// AdcTemperature + // Calculated values + int32_t _dT; //TempDifference + int32_t _TEMP; // Actual temperature -40 to 85C with .01 resolution (divide by 100) - Temperature float + // Temperature compensated pressure + int64_t _OFF; // First Order Offset at actual temperature // Offset - float + int64_t _SENS; // Sensitivity at actual temperature // Sensitivity - float + int32_t _P; // Temperature compensated pressure 10...1300 mbar (divide by 100 to get mBar) + float _press_atm_mBar; // Atmospheric pressure + }; // Function prototype: diff --git a/Arduino/MS5803/keywords.txt b/Arduino/MS5803/keywords.txt index 01e9604b..3753408f 100644 --- a/Arduino/MS5803/keywords.txt +++ b/Arduino/MS5803/keywords.txt @@ -1,7 +1,3 @@ -########################################### -# Syntax Coloring Map For LiquidCrystal_I2C -########################################### - ########################################### # Datatypes (KEYWORD1) ########################################### @@ -25,6 +21,22 @@ getPress_kPa KEYWORD2 initialized KEYWORD2 getDebug KEYWORD2 setDebug KEYWORD2 + ########################################### # Constants (LITERAL1) -########################################### \ No newline at end of file +########################################### +MS5803_ADDRESS LITERAL1 +MS5803_ADDRESS_AD0_LOW LITERAL1 +MS5803_ADDRESS_AD0_HIGH LITERAL1 +MS5803_DEFAULT_ADDRESS LITERAL1 +MS5803_RESET LITERAL1 +MS5803_PROM_BASE LITERAL1 +MS5803_PROM_C1 LITERAL1 +MS5803_PROM_C2 LITERAL1 +MS5803_PROM_C3 LITERAL1 +MS5803_PROM_C4 LITERAL1 +MS5803_PROM_C5 LITERAL1 +MS5803_PROM_C6 LITERAL1 +MS5803_PROM_CRC LITERAL1 +MS5803_ADC_READ LITERAL1 +CMD_ADC_CONV LITERAL1 \ No newline at end of file From 6744ce0ac434e1a693a31d35d3414f63a7a39fb9 Mon Sep 17 00:00:00 2001 From: PaulStoffregen Date: Tue, 5 Apr 2016 06:31:00 -0700 Subject: [PATCH 123/335] Don't do anything special for Teensy, just use regular Arduino Wire lib --- Arduino/I2Cdev/I2Cdev.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Arduino/I2Cdev/I2Cdev.h b/Arduino/I2Cdev/I2Cdev.h index 46cbcf05..4c0a2e7a 100644 --- a/Arduino/I2Cdev/I2Cdev.h +++ b/Arduino/I2Cdev/I2Cdev.h @@ -79,10 +79,7 @@ THE SOFTWARE. #else #include "Arduino.h" #endif - #if defined(CORE_TEENSY) && defined(__MK20DX256__) - #include - #define BUFFER_LENGTH 32 - #elif I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE + #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE #include #endif #if I2CDEV_IMPLEMENTATION == I2CDEV_I2CMASTER_LIBRARY From d2e6deca407fdaff1f9aa5f2fb53c50192489d71 Mon Sep 17 00:00:00 2001 From: PaulStoffregen Date: Thu, 7 Apr 2016 02:19:40 -0700 Subject: [PATCH 124/335] Use lowercase example folder name (Arduino library spec) --- .../ADS1115_differential/ADS1115_differential.ino | 0 .../{Examples => examples}/ADS1115_single/ADS1115_single.ino | 0 .../ADXL345/{Examples => examples}/ADXL345_raw/ADXL345_raw.ino | 0 .../AK8975_MPUEVB_heading/AK8975_MPUEVB_heading.ino | 0 .../AK8975_MPUEVB_raw/AK8975_MPUEVB_raw.ino | 0 Arduino/AK8975/{Examples => examples}/AK8975_raw/AK8975_raw.ino | 0 .../BMP085/{Examples => examples}/BMP085_basic/BMP085_basic.ino | 0 Arduino/DS1307/{Examples => examples}/DS1307_tick/DS1307_tick.ino | 0 .../HMC5843/{Examples => examples}/HMC5843_raw/HMC5843_raw.ino | 0 .../HMC5883L/{Examples => examples}/HMC5883L_raw/HMC5883L_raw.ino | 0 .../HTU21D/{Examples => examples}/HTU21D_simple/HTU21D_simple.ino | 0 .../ITG3200/{Examples => examples}/ITG3200_raw/ITG3200_raw.ino | 0 .../L3G4200D/{Examples => examples}/L3G4200D_raw/L3G4200D_raw.ino | 0 .../MPU6050/{Examples => examples}/MPU6050_DMP6/MPU6050_DMP6.ino | 0 .../MPU6050_DMP6/Processing/MPUTeapot/MPUTeapot.pde | 0 .../MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino | 0 .../MPU6050/{Examples => examples}/MPU6050_raw/MPU6050_raw.ino | 0 .../MPU9150/{Examples => examples}/MPU9150_raw/MPU9150_raw.ino | 0 Arduino/MS5803/{Examples => examples}/test_MS5803/test_MS5803.ino | 0 19 files changed, 0 insertions(+), 0 deletions(-) rename Arduino/ADS1115/{Examples => examples}/ADS1115_differential/ADS1115_differential.ino (100%) rename Arduino/ADS1115/{Examples => examples}/ADS1115_single/ADS1115_single.ino (100%) rename Arduino/ADXL345/{Examples => examples}/ADXL345_raw/ADXL345_raw.ino (100%) rename Arduino/AK8975/{Examples => examples}/AK8975_MPUEVB_heading/AK8975_MPUEVB_heading.ino (100%) rename Arduino/AK8975/{Examples => examples}/AK8975_MPUEVB_raw/AK8975_MPUEVB_raw.ino (100%) rename Arduino/AK8975/{Examples => examples}/AK8975_raw/AK8975_raw.ino (100%) rename Arduino/BMP085/{Examples => examples}/BMP085_basic/BMP085_basic.ino (100%) rename Arduino/DS1307/{Examples => examples}/DS1307_tick/DS1307_tick.ino (100%) rename Arduino/HMC5843/{Examples => examples}/HMC5843_raw/HMC5843_raw.ino (100%) rename Arduino/HMC5883L/{Examples => examples}/HMC5883L_raw/HMC5883L_raw.ino (100%) rename Arduino/HTU21D/{Examples => examples}/HTU21D_simple/HTU21D_simple.ino (100%) rename Arduino/ITG3200/{Examples => examples}/ITG3200_raw/ITG3200_raw.ino (100%) rename Arduino/L3G4200D/{Examples => examples}/L3G4200D_raw/L3G4200D_raw.ino (100%) rename Arduino/MPU6050/{Examples => examples}/MPU6050_DMP6/MPU6050_DMP6.ino (100%) rename Arduino/MPU6050/{Examples => examples}/MPU6050_DMP6/Processing/MPUTeapot/MPUTeapot.pde (100%) rename Arduino/MPU6050/{Examples => examples}/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino (100%) rename Arduino/MPU6050/{Examples => examples}/MPU6050_raw/MPU6050_raw.ino (100%) rename Arduino/MPU9150/{Examples => examples}/MPU9150_raw/MPU9150_raw.ino (100%) rename Arduino/MS5803/{Examples => examples}/test_MS5803/test_MS5803.ino (100%) diff --git a/Arduino/ADS1115/Examples/ADS1115_differential/ADS1115_differential.ino b/Arduino/ADS1115/examples/ADS1115_differential/ADS1115_differential.ino similarity index 100% rename from Arduino/ADS1115/Examples/ADS1115_differential/ADS1115_differential.ino rename to Arduino/ADS1115/examples/ADS1115_differential/ADS1115_differential.ino diff --git a/Arduino/ADS1115/Examples/ADS1115_single/ADS1115_single.ino b/Arduino/ADS1115/examples/ADS1115_single/ADS1115_single.ino similarity index 100% rename from Arduino/ADS1115/Examples/ADS1115_single/ADS1115_single.ino rename to Arduino/ADS1115/examples/ADS1115_single/ADS1115_single.ino diff --git a/Arduino/ADXL345/Examples/ADXL345_raw/ADXL345_raw.ino b/Arduino/ADXL345/examples/ADXL345_raw/ADXL345_raw.ino similarity index 100% rename from Arduino/ADXL345/Examples/ADXL345_raw/ADXL345_raw.ino rename to Arduino/ADXL345/examples/ADXL345_raw/ADXL345_raw.ino diff --git a/Arduino/AK8975/Examples/AK8975_MPUEVB_heading/AK8975_MPUEVB_heading.ino b/Arduino/AK8975/examples/AK8975_MPUEVB_heading/AK8975_MPUEVB_heading.ino similarity index 100% rename from Arduino/AK8975/Examples/AK8975_MPUEVB_heading/AK8975_MPUEVB_heading.ino rename to Arduino/AK8975/examples/AK8975_MPUEVB_heading/AK8975_MPUEVB_heading.ino diff --git a/Arduino/AK8975/Examples/AK8975_MPUEVB_raw/AK8975_MPUEVB_raw.ino b/Arduino/AK8975/examples/AK8975_MPUEVB_raw/AK8975_MPUEVB_raw.ino similarity index 100% rename from Arduino/AK8975/Examples/AK8975_MPUEVB_raw/AK8975_MPUEVB_raw.ino rename to Arduino/AK8975/examples/AK8975_MPUEVB_raw/AK8975_MPUEVB_raw.ino diff --git a/Arduino/AK8975/Examples/AK8975_raw/AK8975_raw.ino b/Arduino/AK8975/examples/AK8975_raw/AK8975_raw.ino similarity index 100% rename from Arduino/AK8975/Examples/AK8975_raw/AK8975_raw.ino rename to Arduino/AK8975/examples/AK8975_raw/AK8975_raw.ino diff --git a/Arduino/BMP085/Examples/BMP085_basic/BMP085_basic.ino b/Arduino/BMP085/examples/BMP085_basic/BMP085_basic.ino similarity index 100% rename from Arduino/BMP085/Examples/BMP085_basic/BMP085_basic.ino rename to Arduino/BMP085/examples/BMP085_basic/BMP085_basic.ino diff --git a/Arduino/DS1307/Examples/DS1307_tick/DS1307_tick.ino b/Arduino/DS1307/examples/DS1307_tick/DS1307_tick.ino similarity index 100% rename from Arduino/DS1307/Examples/DS1307_tick/DS1307_tick.ino rename to Arduino/DS1307/examples/DS1307_tick/DS1307_tick.ino diff --git a/Arduino/HMC5843/Examples/HMC5843_raw/HMC5843_raw.ino b/Arduino/HMC5843/examples/HMC5843_raw/HMC5843_raw.ino similarity index 100% rename from Arduino/HMC5843/Examples/HMC5843_raw/HMC5843_raw.ino rename to Arduino/HMC5843/examples/HMC5843_raw/HMC5843_raw.ino diff --git a/Arduino/HMC5883L/Examples/HMC5883L_raw/HMC5883L_raw.ino b/Arduino/HMC5883L/examples/HMC5883L_raw/HMC5883L_raw.ino similarity index 100% rename from Arduino/HMC5883L/Examples/HMC5883L_raw/HMC5883L_raw.ino rename to Arduino/HMC5883L/examples/HMC5883L_raw/HMC5883L_raw.ino diff --git a/Arduino/HTU21D/Examples/HTU21D_simple/HTU21D_simple.ino b/Arduino/HTU21D/examples/HTU21D_simple/HTU21D_simple.ino similarity index 100% rename from Arduino/HTU21D/Examples/HTU21D_simple/HTU21D_simple.ino rename to Arduino/HTU21D/examples/HTU21D_simple/HTU21D_simple.ino diff --git a/Arduino/ITG3200/Examples/ITG3200_raw/ITG3200_raw.ino b/Arduino/ITG3200/examples/ITG3200_raw/ITG3200_raw.ino similarity index 100% rename from Arduino/ITG3200/Examples/ITG3200_raw/ITG3200_raw.ino rename to Arduino/ITG3200/examples/ITG3200_raw/ITG3200_raw.ino diff --git a/Arduino/L3G4200D/Examples/L3G4200D_raw/L3G4200D_raw.ino b/Arduino/L3G4200D/examples/L3G4200D_raw/L3G4200D_raw.ino similarity index 100% rename from Arduino/L3G4200D/Examples/L3G4200D_raw/L3G4200D_raw.ino rename to Arduino/L3G4200D/examples/L3G4200D_raw/L3G4200D_raw.ino diff --git a/Arduino/MPU6050/Examples/MPU6050_DMP6/MPU6050_DMP6.ino b/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino similarity index 100% rename from Arduino/MPU6050/Examples/MPU6050_DMP6/MPU6050_DMP6.ino rename to Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino diff --git a/Arduino/MPU6050/Examples/MPU6050_DMP6/Processing/MPUTeapot/MPUTeapot.pde b/Arduino/MPU6050/examples/MPU6050_DMP6/Processing/MPUTeapot/MPUTeapot.pde similarity index 100% rename from Arduino/MPU6050/Examples/MPU6050_DMP6/Processing/MPUTeapot/MPUTeapot.pde rename to Arduino/MPU6050/examples/MPU6050_DMP6/Processing/MPUTeapot/MPUTeapot.pde diff --git a/Arduino/MPU6050/Examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino b/Arduino/MPU6050/examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino similarity index 100% rename from Arduino/MPU6050/Examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino rename to Arduino/MPU6050/examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino diff --git a/Arduino/MPU6050/Examples/MPU6050_raw/MPU6050_raw.ino b/Arduino/MPU6050/examples/MPU6050_raw/MPU6050_raw.ino similarity index 100% rename from Arduino/MPU6050/Examples/MPU6050_raw/MPU6050_raw.ino rename to Arduino/MPU6050/examples/MPU6050_raw/MPU6050_raw.ino diff --git a/Arduino/MPU9150/Examples/MPU9150_raw/MPU9150_raw.ino b/Arduino/MPU9150/examples/MPU9150_raw/MPU9150_raw.ino similarity index 100% rename from Arduino/MPU9150/Examples/MPU9150_raw/MPU9150_raw.ino rename to Arduino/MPU9150/examples/MPU9150_raw/MPU9150_raw.ino diff --git a/Arduino/MS5803/Examples/test_MS5803/test_MS5803.ino b/Arduino/MS5803/examples/test_MS5803/test_MS5803.ino similarity index 100% rename from Arduino/MS5803/Examples/test_MS5803/test_MS5803.ino rename to Arduino/MS5803/examples/test_MS5803/test_MS5803.ino From 0f9159a80e57441e5fa051f65c0ce01cbfe83d1e Mon Sep 17 00:00:00 2001 From: PaulStoffregen Date: Thu, 7 Apr 2016 02:30:59 -0700 Subject: [PATCH 125/335] Use digitalPinToInterrupt for better compatibility with modern Arduino boards --- Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino | 3 ++- .../examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino b/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino index 84d1ee31..b7daba5f 100644 --- a/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino +++ b/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino @@ -118,6 +118,7 @@ MPU6050 mpu; +#define INTERRUPT_PIN 2 // use pin 2 on Arduino Uno & most boards #define LED_PIN 13 // (Arduino is 13, Teensy is 11, Teensy++ is 6) bool blinkState = false; @@ -211,7 +212,7 @@ void setup() { // enable Arduino interrupt detection Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)...")); - attachInterrupt(0, dmpDataReady, RISING); + attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), dmpDataReady, RISING); mpuIntStatus = mpu.getIntStatus(); // set our DMP Ready flag so the main loop() function knows it's okay to use it diff --git a/Arduino/MPU6050/examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino b/Arduino/MPU6050/examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino index b855bc45..74526883 100644 --- a/Arduino/MPU6050/examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino +++ b/Arduino/MPU6050/examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino @@ -125,6 +125,7 @@ String HTTP_req; // stores the HTTP request // format used for the InvenSense teapot demo //#define OUTPUT_TEAPOT +#define INTERRUPT_PIN 2 // use pin 2 on Arduino Uno & most boards #define LED_PIN 13 // (Arduino is 13, Teensy is 11, Teensy++ is 6) bool blinkState = false; @@ -217,7 +218,7 @@ void setup() { // enable Arduino interrupt detection Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)...")); - attachInterrupt(0, dmpDataReady, RISING); + attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), dmpDataReady, RISING); mpuIntStatus = mpu.getIntStatus(); // set our DMP Ready flag so the main loop() function knows it's okay to use it From 1e3314493a6f5f5e885fe6956b19a5a0899ead07 Mon Sep 17 00:00:00 2001 From: PaulStoffregen Date: Thu, 7 Apr 2016 02:34:12 -0700 Subject: [PATCH 126/335] Use pinMode to configure interrupt pins, don't assume input mode --- Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino | 1 + .../examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino | 1 + 2 files changed, 2 insertions(+) diff --git a/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino b/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino index b7daba5f..3866971c 100644 --- a/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino +++ b/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino @@ -183,6 +183,7 @@ void setup() { // initialize device Serial.println(F("Initializing I2C devices...")); mpu.initialize(); + pinMode(INTERRUPT_PIN, INPUT); // verify connection Serial.println(F("Testing device connections...")); diff --git a/Arduino/MPU6050/examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino b/Arduino/MPU6050/examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino index 74526883..cb60712c 100644 --- a/Arduino/MPU6050/examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino +++ b/Arduino/MPU6050/examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino @@ -195,6 +195,7 @@ void setup() { // initialize device Serial.println(F("Initializing I2C devices...")); mpu.initialize(); + pinMode(INTERRUPT_PIN, INPUT); // verify connection Serial.println(F("Testing device connections...")); From 5af4989d075f1f9a17ba4a8de8c40ba1a2b36e1a Mon Sep 17 00:00:00 2001 From: PaulStoffregen Date: Thu, 7 Apr 2016 02:40:46 -0700 Subject: [PATCH 127/335] Use Wire.setClock instead of AVR-only TWBR --- Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino | 2 +- .../examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino b/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino index 3866971c..d755665a 100644 --- a/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino +++ b/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino @@ -163,7 +163,7 @@ void setup() { // join I2C bus (I2Cdev library doesn't do this automatically) #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE Wire.begin(); - TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz). Comment this line if having compilation difficulties with TWBR. + Wire.setClock(400000); // 400kHz I2C clock. Comment this line if having compilation difficulties #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE Fastwire::setup(400, true); #endif diff --git a/Arduino/MPU6050/examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino b/Arduino/MPU6050/examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino index cb60712c..9641d72c 100644 --- a/Arduino/MPU6050/examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino +++ b/Arduino/MPU6050/examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino @@ -171,7 +171,7 @@ void setup() { // join I2C bus (I2Cdev library doesn't do this automatically) #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE Wire.begin(); - TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz) + Wire.setClock(400000); // 400kHz I2C clock (200kHz if CPU is 8MHz). Comment this line if having compilation difficulties #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE Fastwire::setup(400, true); #endif From 95b719d0226169bd02f8c0d5ca2e64e3e095ed3c Mon Sep 17 00:00:00 2001 From: EAD Fritz Date: Sat, 9 Apr 2016 17:01:15 +0200 Subject: [PATCH 128/335] Applied #222 "YawPitchRaw algorithm mistake" Thanks @yonoodle Added a temporary #ifdef condition so that the new code can easily be tested and compared with the old. I will remove the old code and the condition after a few weeks (if the new one passes all tests). --- Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h | 20 ++++++++++++++++++++ Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h | 20 ++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h index 1c055433..954562b4 100644 --- a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h +++ b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h @@ -690,6 +690,8 @@ uint8_t MPU6050::dmpGetEuler(float *data, Quaternion *q) { data[2] = atan2(2*q -> y*q -> z - 2*q -> w*q -> x, 2*q -> w*q -> w + 2*q -> z*q -> z - 1); // phi return 0; } + +#ifdef USE_OLD_DMPGETYAWPITCHROLL uint8_t MPU6050::dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity) { // yaw: (about Z axis) data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1); @@ -699,6 +701,24 @@ uint8_t MPU6050::dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gra data[2] = atan(gravity -> y / sqrt(gravity -> x*gravity -> x + gravity -> z*gravity -> z)); return 0; } +#else +uint8_t MPU6050::dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity) { + // yaw: (about Z axis) + data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1); + // pitch: (nose up/down, about Y axis) + data[1] = atan2(gravity -> x , sqrt(gravity -> y*gravity -> y + gravity -> z*gravity -> z)); + // roll: (tilt left/right, about X axis) + data[2] = atan2(gravity -> y , gravity -> z); + if (gravity -> z < 0) { + if(data[1] > 0) { + data[1] = PI - data[1]; + } else { + data[1] = -PI - data[1]; + } + } + return 0; +} +#endif // uint8_t MPU6050::dmpGetAccelFloat(float *data, const uint8_t* packet); // uint8_t MPU6050::dmpGetQuaternionFloat(float *data, const uint8_t* packet); diff --git a/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h b/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h index 016d0b0d..d07d4b8d 100644 --- a/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h +++ b/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h @@ -797,6 +797,8 @@ uint8_t MPU6050::dmpGetEuler(float *data, Quaternion *q) { data[2] = atan2(2*q -> y*q -> z - 2*q -> w*q -> x, 2*q -> w*q -> w + 2*q -> z*q -> z - 1); // phi return 0; } + +#ifdef USE_OLD_DMPGETYAWPITCHROLL uint8_t MPU6050::dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity) { // yaw: (about Z axis) data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1); @@ -806,6 +808,24 @@ uint8_t MPU6050::dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gra data[2] = atan(gravity -> y / sqrt(gravity -> x*gravity -> x + gravity -> z*gravity -> z)); return 0; } +#else +uint8_t MPU6050::dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity) { + // yaw: (about Z axis) + data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1); + // pitch: (nose up/down, about Y axis) + data[1] = atan2(gravity -> x , sqrt(gravity -> y*gravity -> y + gravity -> z*gravity -> z)); + // roll: (tilt left/right, about X axis) + data[2] = atan2(gravity -> y , gravity -> z); + if(gravity->z<0) { + if(data[1]>0) { + data[1] = PI - data[1]; + } else { + data[1] = -PI - data[1]; + } + } + return 0; +} +#endif // uint8_t MPU6050::dmpGetAccelFloat(float *data, const uint8_t* packet); // uint8_t MPU6050::dmpGetQuaternionFloat(float *data, const uint8_t* packet); From 317339594454f4cbd8b898a552366480c95681a0 Mon Sep 17 00:00:00 2001 From: EAD Fritz Date: Fri, 15 Apr 2016 21:46:19 +0200 Subject: [PATCH 129/335] Fixed a compilation error: DS1307.cpp:363:35: error: variable 'daysInMonth' must be const in order to be put into read-only section by means of '__attribute__((progmem))' static uint8_t daysInMonth [] PROGMEM = { 31,28,31,30,31,30,31,31,30,31,30,31 }; --- Arduino/DS1307/DS1307.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Arduino/DS1307/DS1307.cpp b/Arduino/DS1307/DS1307.cpp index 87930e35..d662a539 100644 --- a/Arduino/DS1307/DS1307.cpp +++ b/Arduino/DS1307/DS1307.cpp @@ -360,7 +360,7 @@ void DS1307::setDateTime24(uint16_t year, uint8_t month, uint8_t day, uint8_t ho //////////////////////////////////////////////////////////////////////////////// // utility code, some of this could be exposed in the DateTime API if needed - static uint8_t daysInMonth [] PROGMEM = { 31,28,31,30,31,30,31,31,30,31,30,31 }; + static const uint8_t daysInMonth [] PROGMEM = { 31,28,31,30,31,30,31,31,30,31,30,31 }; // number of days since 2000/01/01, valid for 2001..2099 static uint16_t date2days(uint16_t y, uint8_t m, uint8_t d) { From 3496b44ea7fc4b84d4c9f3d7a8825a886efd5ac7 Mon Sep 17 00:00:00 2001 From: EAD Fritz Date: Fri, 15 Apr 2016 22:07:21 +0200 Subject: [PATCH 130/335] =?UTF-8?q?Added=20a=20small=20DS1307=20example.?= =?UTF-8?q?=20It's=20using=20the=20date=20and=20time=20of=20the=20compiler?= =?UTF-8?q?=20to=20call=20setDateTime().=20In=20many=20cases=20this=20is?= =?UTF-8?q?=20'Good=20enough'=E2=84=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DS1307_settime/DS1307_settime.ino | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 Arduino/DS1307/examples/DS1307_settime/DS1307_settime.ino diff --git a/Arduino/DS1307/examples/DS1307_settime/DS1307_settime.ino b/Arduino/DS1307/examples/DS1307_settime/DS1307_settime.ino new file mode 100644 index 00000000..7655a90c --- /dev/null +++ b/Arduino/DS1307/examples/DS1307_settime/DS1307_settime.ino @@ -0,0 +1,96 @@ +// I2C device class (I2Cdev) demonstration Arduino sketch for DS1307 class +// +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// I2C Device Library hosted at http://www.i2cdevlib.com +// +// Changelog: +// 2016-04-15 - initial release + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2016 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +// I2Cdev and DS1307 must be installed as libraries, or else the .cpp/.h files +// for both classes must be in the include path of your project +#include "DS1307.h" + + +DS1307 rtc; + +void setup() { + // join I2C bus (I2Cdev library doesn't do this automatically) + // Note that the DS1307 doesn't support 400Khz i2c + Wire.begin(); + + // initialize serial communication + // (38400 chosen because it works as well at 8MHz as it does at 16MHz, but + // it's really up to you depending on your project) + Serial.begin(38400); + + // initialize device + Serial.println("Initializing I2C devices..."); + rtc.initialize(); + + // verify connection + Serial.println("Testing device connections..."); + Serial.println(rtc.testConnection() ? "DS1307 connection successful" : "DS1307 connection failed"); + + + // Use "the compiler's time" to set time. Make sure the sketch is recompiled before uploading. + DateTime compilerNow (__DATE__, __TIME__); + rtc.setDateTime(compilerNow); + rtc.setClockRunning(true); + Serial.print(" Clock is set "); + Serial.println(rtc.getClockRunning()?"and running":"but it is NOT running"); +} + +void printDigits(int digits, const char* prefix="") { + // utility function: prints prefix and leading 0 before the number + Serial.print(prefix); + if (digits < 10) + Serial.print('0'); + Serial.print(digits); +} + +void loop() { + // ISO 8601 FTW! + + uint16_t year = 0; + uint8_t month, day, dow, hours, minutes, seconds = 0; + static uint32_t tick = 0; + + rtc.getDateTime24(&year, &month, &day, &hours, &minutes, &seconds); + Serial.print(tick++); + printDigits(year, ": "); + printDigits(month,"-"); + printDigits(day,"-"); + printDigits(hours," "); + printDigits(minutes,":"); + printDigits(seconds, ":"); + + Serial.println(); + delay(1000); +} + + + From b0af9919019a2dcd5456cd1129c776b7b386418b Mon Sep 17 00:00:00 2001 From: EAD Fritz Date: Sun, 17 Apr 2016 16:45:12 +0200 Subject: [PATCH 131/335] Re-reading fifoCount after each resetFIFO() #227 --- Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino | 1 + .../examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino | 1 + 2 files changed, 2 insertions(+) diff --git a/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino b/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino index d755665a..e696c2f6 100644 --- a/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino +++ b/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino @@ -271,6 +271,7 @@ void loop() { if ((mpuIntStatus & 0x10) || fifoCount == 1024) { // reset so we can continue cleanly mpu.resetFIFO(); + fifoCount = mpu.getFIFOCount(); Serial.println(F("FIFO overflow!")); // otherwise, check for DMP data ready interrupt (this should happen frequently) diff --git a/Arduino/MPU6050/examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino b/Arduino/MPU6050/examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino index 9641d72c..1e898987 100644 --- a/Arduino/MPU6050/examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino +++ b/Arduino/MPU6050/examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino @@ -277,6 +277,7 @@ void loop() { if ((mpuIntStatus & 0x10) || fifoCount == 1024) { // reset so we can continue cleanly mpu.resetFIFO(); + fifoCount = mpu.getFIFOCount(); Serial.println(F("FIFO overflow!")); // otherwise, check for DMP data ready interrupt (this should happen frequently) From 41618e25a70cc51836270e9dac3310e451d18f2a Mon Sep 17 00:00:00 2001 From: EAD Fritz Date: Sun, 17 Apr 2016 16:57:18 +0200 Subject: [PATCH 132/335] Replaced the magic number 0x12 with pre defined constants. #217 #212 --- Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h | 2 +- Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h index 954562b4..ce3a6620 100644 --- a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h +++ b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h @@ -395,7 +395,7 @@ uint8_t MPU6050::dmpInitialize() { setClockSource(MPU6050_CLOCK_PLL_ZGYRO); DEBUG_PRINTLN(F("Setting DMP and FIFO_OFLOW interrupts enabled...")); - setIntEnabled(0x12); + setIntEnabled(1< Date: Mon, 18 Apr 2016 22:58:32 +0200 Subject: [PATCH 133/335] Fixed a potential inifinite loop. Added an infinite loop if DMP Initialization failed. --- .../examples/MPU6050_DMP6/MPU6050_DMP6.ino | 11 ++++++++++- .../MPU6050_DMP6_Ethernet.ino | 16 ++++++++++++---- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino b/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino index e696c2f6..762afc7b 100644 --- a/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino +++ b/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino @@ -3,6 +3,7 @@ // Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib // // Changelog: +// 2016-04-18 - Eliminated a potential infinite loop // 2013-05-08 - added seamless Fastwire support // - added note about gyro calibration // 2012-06-21 - added note about Arduino 1.0.1 + Leonardo compatibility error @@ -212,7 +213,9 @@ void setup() { mpu.setDMPEnabled(true); // enable Arduino interrupt detection - Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)...")); + Serial.print(F("Enabling interrupt detection (Arduino external interrupt ")); + Serial.print(digitalPinToInterrupt(INTERRUPT_PIN)); + Serial.println(F(")...")); attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), dmpDataReady, RISING); mpuIntStatus = mpu.getIntStatus(); @@ -230,6 +233,8 @@ void setup() { Serial.print(F("DMP Initialization failed (code ")); Serial.print(devStatus); Serial.println(F(")")); + while(true) + ; // DMP Initialization failed, halt here. } // configure LED for output @@ -248,6 +253,10 @@ void loop() { // wait for MPU interrupt or extra packet(s) available while (!mpuInterrupt && fifoCount < packetSize) { + if (mpuInterrupt && fifoCount < packetSize) { + // try to get out of the infinite loop + fifoCount = mpu.getFIFOCount(); + } // other program behavior stuff here // . // . diff --git a/Arduino/MPU6050/examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino b/Arduino/MPU6050/examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino index 1e898987..2a98bb43 100644 --- a/Arduino/MPU6050/examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino +++ b/Arduino/MPU6050/examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino @@ -4,8 +4,9 @@ // Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib // // Changelog: +// 2016-04-18 - Eliminated a potential infinite loop // 2016-02-28 - Cleaned up code to be in line with other example codes - // - Added Ethernet outputs for Quaternion, Euler, RealAccel, WorldAccel +// - Added Ethernet outputs for Quaternion, Euler, RealAccel, WorldAccel // 2016-02-27 - Initial working code compiled // Bugs: // - There is still a hangup after some time, though it only occurs when you are reading data from the website. @@ -218,7 +219,9 @@ void setup() { mpu.setDMPEnabled(true); // enable Arduino interrupt detection - Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)...")); + Serial.print(F("Enabling interrupt detection (Arduino external interrupt ")); + Serial.print(digitalPinToInterrupt(INTERRUPT_PIN)); + Serial.println(F(")...")); attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), dmpDataReady, RISING); mpuIntStatus = mpu.getIntStatus(); @@ -236,7 +239,8 @@ void setup() { Serial.print(F("DMP Initialization failed (code ")); Serial.print(devStatus); Serial.println(F(")")); - return; + while(true) + ; // DMP Initialization failed, halt here. } // configure LED for output @@ -255,6 +259,10 @@ void loop() { wdt_reset();//Resets the watchdog timer. If the timer is not reset, and the timer expires, a watchdog-initiated device reset will occur. // wait for MPU interrupt or extra packet(s) available while (!mpuInterrupt && fifoCount < packetSize) { + if (mpuInterrupt && fifoCount < packetSize) { + // try to get out of the infinite loop + fifoCount = mpu.getFIFOCount(); + } // other program behavior stuff here // . // . @@ -535,4 +543,4 @@ void GetAjaxData(EthernetClient cl) cl.print("\t"); cl.println("

"); #endif -} +} From 72827777863c0afe37d18a9a33099345d65d8873 Mon Sep 17 00:00:00 2001 From: EAD Fritz Date: Mon, 18 Apr 2016 23:47:45 +0200 Subject: [PATCH 134/335] Replaced 'magic numbers' with their #define Apparendly 'fifoCount' can get higher than 1024. #193 Removed 'dmpReady', replaced it with an infinite loop in setup() --- Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino | 8 ++------ .../MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino | 8 ++------ 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino b/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino index 762afc7b..d17c944e 100644 --- a/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino +++ b/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino @@ -124,7 +124,6 @@ MPU6050 mpu; bool blinkState = false; // MPU control/status vars -bool dmpReady = false; // set true if DMP init was successful uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU uint8_t devStatus; // return status after each device operation (0 = success, !0 = error) uint16_t packetSize; // expected DMP packet size (default is 42 bytes) @@ -221,7 +220,6 @@ void setup() { // set our DMP Ready flag so the main loop() function knows it's okay to use it Serial.println(F("DMP ready! Waiting for first interrupt...")); - dmpReady = true; // get expected DMP packet size for later comparison packetSize = mpu.dmpGetFIFOPacketSize(); @@ -248,8 +246,6 @@ void setup() { // ================================================================ void loop() { - // if programming failed, don't try to do anything - if (!dmpReady) return; // wait for MPU interrupt or extra packet(s) available while (!mpuInterrupt && fifoCount < packetSize) { @@ -277,14 +273,14 @@ void loop() { fifoCount = mpu.getFIFOCount(); // check for overflow (this should never happen unless our code is too inefficient) - if ((mpuIntStatus & 0x10) || fifoCount == 1024) { + if ((mpuIntStatus & _BV(MPU6050_INTERRUPT_FIFO_OFLOW_BIT)) || fifoCount >= 1024) { // reset so we can continue cleanly mpu.resetFIFO(); fifoCount = mpu.getFIFOCount(); Serial.println(F("FIFO overflow!")); // otherwise, check for DMP data ready interrupt (this should happen frequently) - } else if (mpuIntStatus & 0x02) { + } else if (mpuIntStatus & _BV(MPU6050_INTERRUPT_DMP_INT_BIT)) { // wait for correct available data length, should be a VERY short wait while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount(); diff --git a/Arduino/MPU6050/examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino b/Arduino/MPU6050/examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino index 2a98bb43..9e9b19b2 100644 --- a/Arduino/MPU6050/examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino +++ b/Arduino/MPU6050/examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino @@ -131,7 +131,6 @@ String HTTP_req; // stores the HTTP request bool blinkState = false; // MPU control/status vars -bool dmpReady = false; // set true if DMP init was successful uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU uint8_t devStatus; // return status after each device operation (0 = success, !0 = error) uint16_t packetSize; // expected DMP packet size (default is 42 bytes) @@ -227,7 +226,6 @@ void setup() { // set our DMP Ready flag so the main loop() function knows it's okay to use it Serial.println(F("DMP ready! Waiting for first interrupt...")); - dmpReady = true; // get expected DMP packet size for later comparison packetSize = mpu.dmpGetFIFOPacketSize(); @@ -254,8 +252,6 @@ void setup() { // ================================================================ void loop() { - // if programming failed, don't try to do anything - if (!dmpReady) return; wdt_reset();//Resets the watchdog timer. If the timer is not reset, and the timer expires, a watchdog-initiated device reset will occur. // wait for MPU interrupt or extra packet(s) available while (!mpuInterrupt && fifoCount < packetSize) { @@ -282,14 +278,14 @@ void loop() { fifoCount = mpu.getFIFOCount(); // check for overflow (this should never happen unless our code is too inefficient) - if ((mpuIntStatus & 0x10) || fifoCount == 1024) { + if ((mpuIntStatus & _BV(MPU6050_INTERRUPT_FIFO_OFLOW_BIT)) || fifoCount >= 1024) { // reset so we can continue cleanly mpu.resetFIFO(); fifoCount = mpu.getFIFOCount(); Serial.println(F("FIFO overflow!")); // otherwise, check for DMP data ready interrupt (this should happen frequently) - } else if (mpuIntStatus & 0x02) { + } else if (mpuIntStatus & _BV(MPU6050_INTERRUPT_DMP_INT_BIT)) { // wait for correct available data length, should be a VERY short wait while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount(); From fb0f06f33cfbda070e9fbda67041a6b819146888 Mon Sep 17 00:00:00 2001 From: EAD Fritz Date: Wed, 20 Apr 2016 08:55:25 +0200 Subject: [PATCH 135/335] Rollback of the dmpReady change --- Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino | 6 ++++-- .../MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino | 7 +++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino b/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino index d17c944e..24a3cfe1 100644 --- a/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino +++ b/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino @@ -124,6 +124,7 @@ MPU6050 mpu; bool blinkState = false; // MPU control/status vars +bool dmpReady = false; // set true if DMP init was successful uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU uint8_t devStatus; // return status after each device operation (0 = success, !0 = error) uint16_t packetSize; // expected DMP packet size (default is 42 bytes) @@ -220,6 +221,7 @@ void setup() { // set our DMP Ready flag so the main loop() function knows it's okay to use it Serial.println(F("DMP ready! Waiting for first interrupt...")); + dmpReady = true; // get expected DMP packet size for later comparison packetSize = mpu.dmpGetFIFOPacketSize(); @@ -231,8 +233,6 @@ void setup() { Serial.print(F("DMP Initialization failed (code ")); Serial.print(devStatus); Serial.println(F(")")); - while(true) - ; // DMP Initialization failed, halt here. } // configure LED for output @@ -246,6 +246,8 @@ void setup() { // ================================================================ void loop() { + // if programming failed, don't try to do anything + if (!dmpReady) return; // wait for MPU interrupt or extra packet(s) available while (!mpuInterrupt && fifoCount < packetSize) { diff --git a/Arduino/MPU6050/examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino b/Arduino/MPU6050/examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino index 9e9b19b2..e39490a0 100644 --- a/Arduino/MPU6050/examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino +++ b/Arduino/MPU6050/examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino @@ -131,6 +131,7 @@ String HTTP_req; // stores the HTTP request bool blinkState = false; // MPU control/status vars +bool dmpReady = false; // set true if DMP init was successful uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU uint8_t devStatus; // return status after each device operation (0 = success, !0 = error) uint16_t packetSize; // expected DMP packet size (default is 42 bytes) @@ -226,6 +227,7 @@ void setup() { // set our DMP Ready flag so the main loop() function knows it's okay to use it Serial.println(F("DMP ready! Waiting for first interrupt...")); + dmpReady = true; // get expected DMP packet size for later comparison packetSize = mpu.dmpGetFIFOPacketSize(); @@ -237,8 +239,6 @@ void setup() { Serial.print(F("DMP Initialization failed (code ")); Serial.print(devStatus); Serial.println(F(")")); - while(true) - ; // DMP Initialization failed, halt here. } // configure LED for output @@ -252,6 +252,9 @@ void setup() { // ================================================================ void loop() { + // if programming failed, don't try to do anything + if (!dmpReady) return; + wdt_reset();//Resets the watchdog timer. If the timer is not reset, and the timer expires, a watchdog-initiated device reset will occur. // wait for MPU interrupt or extra packet(s) available while (!mpuInterrupt && fifoCount < packetSize) { From 5d75db665fa1fe5522189b0ef372b51503573ddc Mon Sep 17 00:00:00 2001 From: EAD Fritz Date: Sat, 30 Apr 2016 09:05:01 +0200 Subject: [PATCH 136/335] Move dmpPacketBuffer and dmpPacketSize to the back of the class. #230 --- Arduino/MPU6050/MPU6050.cpp | 12 ++---------- Arduino/MPU6050/MPU6050.h | 27 +++++++++++++-------------- 2 files changed, 15 insertions(+), 24 deletions(-) diff --git a/Arduino/MPU6050/MPU6050.cpp b/Arduino/MPU6050/MPU6050.cpp index d6ad2057..624ff267 100644 --- a/Arduino/MPU6050/MPU6050.cpp +++ b/Arduino/MPU6050/MPU6050.cpp @@ -36,21 +36,13 @@ THE SOFTWARE. #include "MPU6050.h" -/** Default constructor, uses default I2C address. - * @see MPU6050_DEFAULT_ADDRESS - */ -MPU6050::MPU6050() { - devAddr = MPU6050_DEFAULT_ADDRESS; -} - /** Specific address constructor. - * @param address I2C address + * @param address I2C address, uses default I2C address if none is specified * @see MPU6050_DEFAULT_ADDRESS * @see MPU6050_ADDRESS_AD0_LOW * @see MPU6050_ADDRESS_AD0_HIGH */ -MPU6050::MPU6050(uint8_t address) { - devAddr = address; +MPU6050::MPU6050(uint8_t address):devAddr(address) { } /** Power on and prepare for general usage. diff --git a/Arduino/MPU6050/MPU6050.h b/Arduino/MPU6050/MPU6050.h index 6e3b9a76..3dd9a89b 100644 --- a/Arduino/MPU6050/MPU6050.h +++ b/Arduino/MPU6050/MPU6050.h @@ -435,8 +435,7 @@ THE SOFTWARE. class MPU6050 { public: - MPU6050(); - MPU6050(uint8_t address); + MPU6050(uint8_t address=MPU6050_DEFAULT_ADDRESS); void initialize(); bool testConnection(); @@ -459,15 +458,15 @@ class MPU6050 { uint8_t getFullScaleGyroRange(); void setFullScaleGyroRange(uint8_t range); - // SELF_TEST registers - uint8_t getAccelXSelfTestFactoryTrim(); - uint8_t getAccelYSelfTestFactoryTrim(); - uint8_t getAccelZSelfTestFactoryTrim(); + // SELF_TEST registers + uint8_t getAccelXSelfTestFactoryTrim(); + uint8_t getAccelYSelfTestFactoryTrim(); + uint8_t getAccelZSelfTestFactoryTrim(); + + uint8_t getGyroXSelfTestFactoryTrim(); + uint8_t getGyroYSelfTestFactoryTrim(); + uint8_t getGyroZSelfTestFactoryTrim(); - uint8_t getGyroXSelfTestFactoryTrim(); - uint8_t getGyroYSelfTestFactoryTrim(); - uint8_t getGyroZSelfTestFactoryTrim(); - // ACCEL_CONFIG register bool getAccelXSelfTest(); void setAccelXSelfTest(bool enabled); @@ -823,8 +822,6 @@ class MPU6050 { // special methods for MotionApps 2.0 implementation #ifdef MPU6050_INCLUDE_DMP_MOTIONAPPS20 - uint8_t *dmpPacketBuffer; - uint16_t dmpPacketSize; uint8_t dmpInitialize(); bool dmpPacketAvailable(); @@ -924,8 +921,6 @@ class MPU6050 { // special methods for MotionApps 4.1 implementation #ifdef MPU6050_INCLUDE_DMP_MOTIONAPPS41 - uint8_t *dmpPacketBuffer; - uint16_t dmpPacketSize; uint8_t dmpInitialize(); bool dmpPacketAvailable(); @@ -1027,6 +1022,10 @@ class MPU6050 { private: uint8_t devAddr; uint8_t buffer[14]; + #if defined(MPU6050_INCLUDE_DMP_MOTIONAPPS20) or defined(MPU6050_INCLUDE_DMP_MOTIONAPPS41) + uint8_t *dmpPacketBuffer; + uint16_t dmpPacketSize; + #endif }; #endif /* _MPU6050_H_ */ From b676228d645c537d7548da4c3c41b7ab84c584cf Mon Sep 17 00:00:00 2001 From: Aaron Miller Date: Fri, 13 May 2016 13:19:45 -0400 Subject: [PATCH 137/335] Updated PROGMEM inclusion test in MPU9150.h to match MPU9150_9Axis_MotionApps41.h to fix warnings on Teensy --- Arduino/MPU9150/MPU9150.h | 49 ++++++++++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 8 deletions(-) diff --git a/Arduino/MPU9150/MPU9150.h b/Arduino/MPU9150/MPU9150.h index ee3e67a2..90ee1cc4 100644 --- a/Arduino/MPU9150/MPU9150.h +++ b/Arduino/MPU9150/MPU9150.h @@ -39,16 +39,49 @@ THE SOFTWARE. #include "I2Cdev.h" -// supporting link: http://forum.arduino.cc/index.php?&topic=143444.msg1079517#msg1079517 -// also: http://forum.arduino.cc/index.php?&topic=141571.msg1062899#msg1062899s +// Tom Carpenter's conditional PROGMEM code +// http://forum.arduino.cc/index.php?topic=129407.0 #ifdef __AVR__ -#include + #include #else -#define PROGMEM /* empty */ -#define pgm_read_byte(x) (*(x)) -#define pgm_read_word(x) (*(x)) -#define pgm_read_float(x) (*(x)) -#define PSTR(STR) STR + // Teensy 3.0 library conditional PROGMEM code from Paul Stoffregen + #ifndef __PGMSPACE_H_ + #define __PGMSPACE_H_ 1 + #include + + #define PROGMEM + #define PGM_P const char * + #define PSTR(str) (str) + #define F(x) x + + typedef void prog_void; + typedef char prog_char; + typedef unsigned char prog_uchar; + typedef int8_t prog_int8_t; + typedef uint8_t prog_uint8_t; + typedef int16_t prog_int16_t; + typedef uint16_t prog_uint16_t; + typedef int32_t prog_int32_t; + typedef uint32_t prog_uint32_t; + + #define strcpy_P(dest, src) strcpy((dest), (src)) + #define strcat_P(dest, src) strcat((dest), (src)) + #define strcmp_P(a, b) strcmp((a), (b)) + + #define pgm_read_byte(addr) (*(const unsigned char *)(addr)) + #define pgm_read_word(addr) (*(const unsigned short *)(addr)) + #define pgm_read_dword(addr) (*(const unsigned long *)(addr)) + #define pgm_read_float(addr) (*(const float *)(addr)) + + #define pgm_read_byte_near(addr) pgm_read_byte(addr) + #define pgm_read_word_near(addr) pgm_read_word(addr) + #define pgm_read_dword_near(addr) pgm_read_dword(addr) + #define pgm_read_float_near(addr) pgm_read_float(addr) + #define pgm_read_byte_far(addr) pgm_read_byte(addr) + #define pgm_read_word_far(addr) pgm_read_word(addr) + #define pgm_read_dword_far(addr) pgm_read_dword(addr) + #define pgm_read_float_far(addr) pgm_read_float(addr) + #endif #endif //Magnetometer Registers From 66d88b4e1ea90482611096535f0e5835d29f1801 Mon Sep 17 00:00:00 2001 From: Aaron Miller Date: Fri, 13 May 2016 13:36:53 -0400 Subject: [PATCH 138/335] Fixed warning that progBuffer was uninitialized --- Arduino/MPU9150/MPU9150.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Arduino/MPU9150/MPU9150.cpp b/Arduino/MPU9150/MPU9150.cpp index 09d10c78..9e6d740e 100644 --- a/Arduino/MPU9150/MPU9150.cpp +++ b/Arduino/MPU9150/MPU9150.cpp @@ -2984,6 +2984,7 @@ bool MPU9150::writeMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t b uint8_t j; if (verify) verifyBuffer = (uint8_t *)malloc(MPU9150_DMP_MEMORY_CHUNK_SIZE); if (useProgMem) progBuffer = (uint8_t *)malloc(MPU9150_DMP_MEMORY_CHUNK_SIZE); + else progBuffer = NULL; for (i = 0; i < dataSize;) { // determine correct chunk size according to bank position and data size chunkSize = MPU9150_DMP_MEMORY_CHUNK_SIZE; @@ -3150,4 +3151,4 @@ uint8_t MPU9150::getDMPConfig2() { } void MPU9150::setDMPConfig2(uint8_t config) { I2Cdev::writeByte(devAddr, MPU9150_RA_DMP_CFG_2, config); -} \ No newline at end of file +} From 2aebda25b7f866147f51624aeb718e532f81baa2 Mon Sep 17 00:00:00 2001 From: Aaron Miller Date: Fri, 13 May 2016 16:17:53 -0400 Subject: [PATCH 139/335] Fixed another warning that progBuffer was uninitialized in MPU9150.cpp --- Arduino/MPU9150/MPU9150.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Arduino/MPU9150/MPU9150.cpp b/Arduino/MPU9150/MPU9150.cpp index 9e6d740e..cffcc09a 100644 --- a/Arduino/MPU9150/MPU9150.cpp +++ b/Arduino/MPU9150/MPU9150.cpp @@ -3059,6 +3059,8 @@ bool MPU9150::writeDMPConfigurationSet(const uint8_t *data, uint16_t dataSize, b uint16_t i, j; if (useProgMem) { progBuffer = (uint8_t *)malloc(8); // assume 8-byte blocks, realloc later if necessary + } else { + progBuffer = NULL; } // config set data is a long string of blocks with the following structure: From 3492d9fd63960addec58ac9adaca6098ec356099 Mon Sep 17 00:00:00 2001 From: EAD Fritz Date: Sat, 14 May 2016 08:54:41 +0200 Subject: [PATCH 140/335] Made it possible to set the FIFO rate divisor with a (non-mandatory) #define. #233 Usage: #define MPU6050_DMP_FIFO_RATE_DIVISOR 99 // bring down FIFO rate to 2Hz (200/(99+1)) #include "MPU6050_6Axis_MotionApps20.h" --- Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h | 6 +++++- Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h | 8 ++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h index ce3a6620..5043c03d 100644 --- a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h +++ b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h @@ -269,6 +269,10 @@ const unsigned char dmpMemory[MPU6050_DMP_CODE_SIZE] PROGMEM = { 0xB9, 0xA7, 0xF1, 0x26, 0x26, 0x26, 0xD8, 0xD8, 0xFF }; +#ifndef MPU6050_DMP_FIFO_RATE_DIVISOR +#define MPU6050_DMP_FIFO_RATE_DIVISOR 0x01 +#endif + // thanks to Noah Zerkin for piecing this stuff together! const unsigned char dmpConfig[MPU6050_DMP_CONFIG_SIZE] PROGMEM = { // BANK OFFSET LENGTH [DATA] @@ -302,7 +306,7 @@ const unsigned char dmpConfig[MPU6050_DMP_CONFIG_SIZE] PROGMEM = { 0x07, 0x46, 0x01, 0x9A, // CFG_GYRO_SOURCE inv_send_gyro 0x07, 0x47, 0x04, 0xF1, 0x28, 0x30, 0x38, // CFG_9 inv_send_gyro -> inv_construct3_fifo 0x07, 0x6C, 0x04, 0xF1, 0x28, 0x30, 0x38, // CFG_12 inv_send_accel -> inv_construct3_fifo - 0x02, 0x16, 0x02, 0x00, 0x01 // D_0_22 inv_set_fifo_rate + 0x02, 0x16, 0x02, 0x00, MPU6050_DMP_FIFO_RATE_DIVISOR // D_0_22 inv_set_fifo_rate // This very last 0x01 WAS a 0x09, which drops the FIFO rate down to 20 Hz. 0x07 is 25 Hz, // 0x01 is 100Hz. Going faster than 100Hz (0x00=200Hz) tends to result in very noisy data. diff --git a/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h b/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h index d1eaab6d..157a74ba 100644 --- a/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h +++ b/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h @@ -262,6 +262,10 @@ const unsigned char dmpMemory[MPU6050_DMP_CODE_SIZE] PROGMEM = { 0xDC, 0xB9, 0xA7, 0xF1, 0x26, 0x26, 0x26, 0xD8, 0xD8, 0xFF }; +#ifndef MPU6050_DMP_FIFO_RATE_DIVISOR +#define MPU6050_DMP_FIFO_RATE_DIVISOR 0x03 +#endif + const unsigned char dmpConfig[MPU6050_DMP_CONFIG_SIZE] PROGMEM = { // BANK OFFSET LENGTH [DATA] 0x02, 0xEC, 0x04, 0x00, 0x47, 0x7D, 0x1A, // ? @@ -302,9 +306,9 @@ const unsigned char dmpConfig[MPU6050_DMP_CONFIG_SIZE] PROGMEM = { 0x07, 0x67, 0x01, 0x9A, // ? 0x07, 0x68, 0x04, 0xF1, 0x28, 0x30, 0x38, // CFG_12 inv_send_accel -> inv_construct3_fifo 0x07, 0x8D, 0x04, 0xF1, 0x28, 0x30, 0x38, // ??? CFG_12 inv_send_mag -> inv_construct3_fifo - 0x02, 0x16, 0x02, 0x00, 0x03 // D_0_22 inv_set_fifo_rate + 0x02, 0x16, 0x02, 0x00, MPU6050_DMP_FIFO_RATE_DIVISOR // D_0_22 inv_set_fifo_rate - // This very last 0x01 WAS a 0x09, which drops the FIFO rate down to 20 Hz. 0x07 is 25 Hz, + // This very last 0x03 WAS a 0x09, which drops the FIFO rate down to 20 Hz. 0x07 is 25 Hz, // 0x01 is 100Hz. Going faster than 100Hz (0x00=200Hz) tends to result in very noisy data. // DMP output frequency is calculated easily using this equation: (200Hz / (1 + value)) From d0d3a3622f89457091f520e6985c62361ab121ab Mon Sep 17 00:00:00 2001 From: EAD Fritz Date: Sun, 22 May 2016 10:15:07 +0200 Subject: [PATCH 141/335] Added an #error if a C compiler is used. #236 --- RaspberryPi_bcm2835/I2Cdev/I2Cdev.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/RaspberryPi_bcm2835/I2Cdev/I2Cdev.h b/RaspberryPi_bcm2835/I2Cdev/I2Cdev.h index 16a450d8..a2cd6768 100644 --- a/RaspberryPi_bcm2835/I2Cdev/I2Cdev.h +++ b/RaspberryPi_bcm2835/I2Cdev/I2Cdev.h @@ -30,6 +30,10 @@ THE SOFTWARE. #ifndef _I2CDEV_H_ #define _I2CDEV_H_ +#ifndef __cplusplus +#error A C++ compiler is required! +#endif + #include #include // required for BMP180 #include // required for MPU6060 From 7fcfd327cae41c0e3f60145b288c0faa9d7a8b1f Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 11 Jun 2016 13:10:03 +0800 Subject: [PATCH 142/335] fix Magnetometer data format to Little Endian --- Arduino/MPU9150/MPU9150.cpp | 7 +++-- .../examples/MPU9150_raw/MPU9150_raw.ino | 28 +++++++++++++------ 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/Arduino/MPU9150/MPU9150.cpp b/Arduino/MPU9150/MPU9150.cpp index cffcc09a..a5f25d9c 100644 --- a/Arduino/MPU9150/MPU9150.cpp +++ b/Arduino/MPU9150/MPU9150.cpp @@ -1726,9 +1726,10 @@ void MPU9150::getMotion9(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int I2Cdev::writeByte(MPU9150_RA_MAG_ADDRESS, 0x0A, 0x01); //enable the magnetometer delay(10); I2Cdev::readBytes(MPU9150_RA_MAG_ADDRESS, MPU9150_RA_MAG_XOUT_L, 6, buffer); - *mx = (((int16_t)buffer[0]) << 8) | buffer[1]; - *my = (((int16_t)buffer[2]) << 8) | buffer[3]; - *mz = (((int16_t)buffer[4]) << 8) | buffer[5]; + //Measurement data is stored in two's complement and Little Endian format. Measurement range of each axis is from -4096 to +4095 in decimal. + *mx = (int16_t)(((uint16_t)buffer[1] << 8) | (uint16_t)buffer[0]); + *my = (int16_t)(((uint16_t)buffer[3] << 8) | (uint16_t)buffer[2]); + *mz = (int16_t)(((uint16_t)buffer[5] << 8) | (uint16_t)buffer[4]); } /** Get raw 6-axis motion sensor readings (accel/gyro). * Retrieves all currently available motion sensor values. diff --git a/Arduino/MPU9150/examples/MPU9150_raw/MPU9150_raw.ino b/Arduino/MPU9150/examples/MPU9150_raw/MPU9150_raw.ino index e2c9224c..84880de2 100644 --- a/Arduino/MPU9150/examples/MPU9150_raw/MPU9150_raw.ino +++ b/Arduino/MPU9150/examples/MPU9150_raw/MPU9150_raw.ino @@ -89,17 +89,27 @@ void loop() { // Serial.print(gx); Serial.print("\t"); // Serial.print(gy); Serial.print("\t"); // Serial.print(gz); Serial.print("\t"); - Serial.print(int(mx)*int(mx)); Serial.print("\t"); - Serial.print(int(my)*int(my)); Serial.print("\t"); - Serial.print(int(mz)*int(mz)); Serial.print("\t | "); + //Serial.print(int(mx)*int(mx)); Serial.print("\t"); + //Serial.print(int(my)*int(my)); Serial.print("\t"); + //Serial.print(int(mz)*int(mz)); Serial.print("\t | "); - const float N = 256; - float mag = mx*mx/N + my*my/N + mz*mz/N; + //const float N = 256; + //float mag = mx*mx/N + my*my/N + mz*mz/N; - Serial.print(mag); Serial.print("\t"); - for (int i=0; i Date: Wed, 13 Jul 2016 16:38:13 +0300 Subject: [PATCH 143/335] init function instead of pointer assignment --- STM32/I2Cdev/I2Cdev.c | 10 ++++++++++ STM32/I2Cdev/I2Cdev.h | 4 ++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/STM32/I2Cdev/I2Cdev.c b/STM32/I2Cdev/I2Cdev.c index 291a0c94..dfc9d073 100644 --- a/STM32/I2Cdev/I2Cdev.c +++ b/STM32/I2Cdev/I2Cdev.c @@ -32,11 +32,21 @@ THE SOFTWARE. #include "I2Cdev.h" +// Hold pointer to inited HAL I2C device +static I2C_HandleTypeDef * I2Cdev_hi2c; + /** Default timeout value for read operations. * Set this to 0 to disable timeout detection. */ uint16_t I2Cdev_readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; +/** Sets device handle to use for communications + * You can call this function and set any other device at any moment + */ +void I2Cdev_init(I2C_HandleTypeDef * hi2c){ + I2Cdev_hi2c = hi2c; +} + /** Read a single bit from an 8-bit device register. * @param devAddr I2C slave device address * @param regAddr Register regAddr to read from diff --git a/STM32/I2Cdev/I2Cdev.h b/STM32/I2Cdev/I2Cdev.h index a77b4540..330a92fc 100644 --- a/STM32/I2Cdev/I2Cdev.h +++ b/STM32/I2Cdev/I2Cdev.h @@ -48,12 +48,12 @@ typedef int bool; #define false 0 uint16_t I2Cdev_readTimeout; -// Hold pointer to inited HAL I2C device -I2C_HandleTypeDef * I2Cdev_hi2c; // 1000ms default read timeout (modify with "I2Cdev::readTimeout = [ms];") #define I2CDEV_DEFAULT_READ_TIMEOUT 1000 +void I2Cdev_init(I2C_HandleTypeDef * hi2c); + uint8_t I2Cdev_readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data, uint16_t timeout); uint8_t I2Cdev_readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data, uint16_t timeout); uint8_t I2Cdev_readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data, uint16_t timeout); From 94707e766c01c80df311838f6fd77a25c2e6770d Mon Sep 17 00:00:00 2001 From: Andrey Voloshin Date: Wed, 13 Jul 2016 16:39:21 +0300 Subject: [PATCH 144/335] writeBytes and writeWords without memory allocations (use HAL_I2C_Mem_Write) --- STM32/I2Cdev/I2Cdev.c | 25 ++++--------------------- 1 file changed, 4 insertions(+), 21 deletions(-) diff --git a/STM32/I2Cdev/I2Cdev.c b/STM32/I2Cdev/I2Cdev.c index dfc9d073..29bdb1b3 100644 --- a/STM32/I2Cdev/I2Cdev.c +++ b/STM32/I2Cdev/I2Cdev.c @@ -319,18 +319,9 @@ uint16_t I2Cdev_writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data) * @param data Buffer to copy new data from * @return Status of operation (true = success) */ -uint16_t I2Cdev_writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t Size, uint8_t* pData) +uint16_t I2Cdev_writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t* pData) { - // Creating dynamic array to store regAddr + data in one buffer - uint8_t * dynBuffer; - dynBuffer = (uint8_t *) malloc(sizeof(uint8_t) * (Size+1)); - dynBuffer[0] = regAddr; - - // copy array - memcpy(dynBuffer+1, pData, sizeof(uint8_t) * Size); - - HAL_StatusTypeDef status = HAL_I2C_Master_Transmit(I2Cdev_hi2c, devAddr << 1, dynBuffer, Size+1, 1000); - free(dynBuffer); + HAL_StatusTypeDef status = HAL_I2C_Mem_Write(I2Cdev_hi2c, devAddr << 1, regAddr, I2C_MEMADD_SIZE_8BIT, pData, length, 1000); return status == HAL_OK; } @@ -341,16 +332,8 @@ uint16_t I2Cdev_writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t Size, uint8 * @param data Buffer to copy new data from * @return Status of operation (true = success) */ -uint16_t I2Cdev_writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t* data) +uint16_t I2Cdev_writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t* pData) { - // Creating dynamic array to store regAddr + data in one buffer - uint8_t * dynBuffer; - dynBuffer = (uint8_t *) malloc(sizeof(uint8_t) + sizeof(uint16_t) * length); - dynBuffer[0] = regAddr; - - // copy array - memcpy(dynBuffer+1, data, sizeof(uint16_t) * length); - HAL_StatusTypeDef status = HAL_I2C_Master_Transmit(I2Cdev_hi2c, devAddr << 1, dynBuffer, sizeof(uint8_t) + sizeof(uint16_t) * length, 1000); - free(dynBuffer); + HAL_StatusTypeDef status = HAL_I2C_Mem_Write(I2Cdev_hi2c, devAddr << 1, regAddr, I2C_MEMADD_SIZE_8BIT, (uint8_t *)pData, sizeof(uint16_t) * length, 1000); return status == HAL_OK; } From 77fb9e85602c4227fe8c00ba71172b99eb439e4f Mon Sep 17 00:00:00 2001 From: Andrey Voloshin Date: Wed, 13 Jul 2016 16:39:59 +0300 Subject: [PATCH 145/335] readme updated - use I2Cdev_init function --- STM32/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/STM32/README.md b/STM32/README.md index aa9e7f57..7947e860 100644 --- a/STM32/README.md +++ b/STM32/README.md @@ -60,7 +60,7 @@ int main(void) HAL_I2C_Init(&hi2c3); - I2Cdev_hi2c = &hi2c3; // init of i2cdevlib. + I2Cdev_init(&hi2c3); // init of i2cdevlib. // You can select other i2c device anytime and // call the same driver functions on other sensors From 26938667c4fba573bc33135d96dfe816a6844027 Mon Sep 17 00:00:00 2001 From: Pranav Gulati Date: Wed, 27 Jul 2016 20:00:25 +0530 Subject: [PATCH 146/335] Update MPU6050_raw.ino added the delay required for blinking the LED on LED_PIN ,otherwise the MCU appears to be stuck --- Arduino/MPU6050/examples/MPU6050_raw/MPU6050_raw.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/Arduino/MPU6050/examples/MPU6050_raw/MPU6050_raw.ino b/Arduino/MPU6050/examples/MPU6050_raw/MPU6050_raw.ino index 28418a96..6e3719b8 100644 --- a/Arduino/MPU6050/examples/MPU6050_raw/MPU6050_raw.ino +++ b/Arduino/MPU6050/examples/MPU6050_raw/MPU6050_raw.ino @@ -148,4 +148,5 @@ void loop() { // blink LED to indicate activity blinkState = !blinkState; digitalWrite(LED_PIN, blinkState); + delay(100); } From 45797dbb2038aafb4901c22f0196ec56ebbab2c4 Mon Sep 17 00:00:00 2001 From: Marc010 Date: Sun, 31 Jul 2016 13:56:30 +0200 Subject: [PATCH 147/335] fix prog_uchar related errors --- Arduino/I2Cdev/I2Cdev.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Arduino/I2Cdev/I2Cdev.h b/Arduino/I2Cdev/I2Cdev.h index 4c0a2e7a..66b2e7b8 100644 --- a/Arduino/I2Cdev/I2Cdev.h +++ b/Arduino/I2Cdev/I2Cdev.h @@ -47,6 +47,11 @@ THE SOFTWARE. #ifndef _I2CDEV_H_ #define _I2CDEV_H_ +// ----------------------------------------------------------------------------- +// Enable deprecated pgmspace typedefs in avr-libc +// ----------------------------------------------------------------------------- +#define __PROG_TYPES_COMPAT__ + // ----------------------------------------------------------------------------- // I2C interface implementation setting // ----------------------------------------------------------------------------- From 9abe6a3730a841b6c7f23df86b9f314cc1a7f715 Mon Sep 17 00:00:00 2001 From: RobertRFenichel Date: Sat, 22 Oct 2016 09:34:36 -0700 Subject: [PATCH 148/335] Add files via upload --- IMU_Zero.ino | 263 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 263 insertions(+) create mode 100644 IMU_Zero.ino diff --git a/IMU_Zero.ino b/IMU_Zero.ino new file mode 100644 index 00000000..1d8261e6 --- /dev/null +++ b/IMU_Zero.ino @@ -0,0 +1,263 @@ +// MPU6050 offset-finder, based on Jeff Rowberg's MPU6050_RAW +// 2016-10-19 by Robert R. Fenichel (bob@fenichel.net) + +// I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class +// 10/7/2011 by Jeff Rowberg +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// 2016-10-19 - initial release +// 2013-05-08 - added multiple output formats +// - added seamless Fastwire support +// 2011-10-07 - initial release + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2011 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +Put the MPU6050 in a flat and horizontal surface. + - Leave it operating for 5-10 minutes so temperature gets stabilized. + - Run this program. A "----- done -----" line will indicate that it has done its best. + - For each of the 6 offsets, you'll see 2 adjacent values to choose between, together + with their respective IMU outputs. One of the choices may be a little better than + the other. +=============================================== +*/ + +// I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files +// for both classes must be in the include path of your project +#include "I2Cdev.h" +#include "MPU6050.h" + +// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation +// is used in I2Cdev.h +#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE + #include "Wire.h" +#endif + +// class default I2C address is 0x68 +// specific I2C addresses may be passed as a parameter here +// AD0 low = 0x68 (default for InvenSense evaluation board) +// AD0 high = 0x69 +MPU6050 accelgyro; +//MPU6050 accelgyro(0x69); // <-- use for AD0 high + + +const char LBRACKET = '['; +const char RBRACKET = ']'; +const char COMMA = ','; + +const int iAx = 0; +const int iAy = 1; +const int iAz = 2; +const int iGx = 3; +const int iGy = 4; +const int iGz = 5; + +const int N = 1000; // the bigger, the smoother (and slower) +const int LinesBetweenHeaders = 5; + int LowValue[6]; + int HighValue[6]; + int Smoothed[6]; + int LowOffset[6]; + int HighOffset[6]; + int Target[6]; + int LinesOut; + +void ForceHeader() + { LinesOut = 99; } + +void GetSmoothed() + { int RawValue[6]; + long Sums[6]; + for (int i = iAx; i <= iGz; i++) + { Sums[i] = 0; } + + for (int i = 1; i <= N; i++) + { // get sums + accelgyro.getMotion6(&RawValue[0], &RawValue[1], &RawValue[2], + &RawValue[3], &RawValue[4], &RawValue[5]); + for (int j = iAx; j <= iGz; j++) + Sums[j] = Sums[j] + RawValue[j]; + } // get sums + for (int i = iAx; i <= iGz; i++) + { Smoothed[i] = (Sums[i] + N/2) / N ; } + } // GetSmoothed + +void Initialize() + { + // join I2C bus (I2Cdev library doesn't do this automatically) + #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE + Wire.begin(); + #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE + Fastwire::setup(400, true); + #endif + + Serial.begin(9600); + + // initialize device + Serial.println("Initializing I2C devices..."); + accelgyro.initialize(); + + // verify connection + Serial.println("Testing device connections..."); + Serial.println(accelgyro.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed"); + } // Initialize + +void SetOffsets(int TheOffsets[6]) + { accelgyro.setXAccelOffset(TheOffsets [iAx]); + accelgyro.setYAccelOffset(TheOffsets [iAy]); + accelgyro.setZAccelOffset(TheOffsets [iAz]); + accelgyro.setXGyroOffset (TheOffsets [iGx]); + accelgyro.setYGyroOffset (TheOffsets [iGy]); + accelgyro.setZGyroOffset (TheOffsets [iGz]); + } // SetOffsets + +void ShowProgress() + { if (LinesOut >= LinesBetweenHeaders) + { // show header + Serial.println("\tXAccel\t\t\tYAccel\t\t\t\tZAccel\t\t\tXGyro\t\t\tYGyro\t\t\tZGyro"); + LinesOut = 0; + } // show header + for (int i = iAx; i <= iGz; i++) + { Serial.print(LBRACKET); + Serial.print(LowOffset[i]), + Serial.print(COMMA); + Serial.print(HighOffset[i]); + Serial.print("] --> ["); + Serial.print(LowValue[i]); + Serial.print(COMMA); + Serial.print(HighValue[i]); + if (i == iGz) + { Serial.println(RBRACKET); } + else + { Serial.print("]\t"); } + } + ForceHeader(); + } // ShowProgress + +void PullBracketsOut() + { boolean Done = false; + int NextLowOffset[6]; + int NextHighOffset[6]; + + SetOffsets(HighOffset); + GetSmoothed(); + for (int i = iAx; i <= iGz; i++) + { HighValue[i] = Smoothed[i]; // needed for ShowProgress + } + + while (!Done) + { Done = true; + SetOffsets(LowOffset); + GetSmoothed(); + for (int i = iAx; i <= iGz; i++) + { // got low values + LowValue[i] = Smoothed[i]; + if (LowValue[i] > Target[i]) + { Done = false; + NextLowOffset[i] = LowOffset[i] - 1000; + } + else + { NextLowOffset[i] = LowOffset[i]; } + } // got low values + ShowProgress(); + for (int i = iAx; i <= iGz; i++) + { LowOffset[i] = NextLowOffset[i]; // had to wait until ShowProgress done + } + } // keep going + + Done = false; + while (!Done) + { Done = true; + SetOffsets(HighOffset); + GetSmoothed(); + for (int i = iAx; i <= iGz; i++) + { // got high values + HighValue[i] = Smoothed[i]; + if (HighValue[i] < Target[i]) + { Done = false; + NextHighOffset[i] = HighOffset[i] + 1000; + } + else + { NextHighOffset[i] = HighOffset[i]; } + } // got high values + ShowProgress(); + for (int i = iAx; i <= iGz; i++) + { HighOffset[i] = NextHighOffset[i]; // had to wait until ShowProgress done + } + } // keep going + } // PullBracketOut + +void setup() + { boolean StillWorking; + int NewOffset[6]; + + Initialize(); + for (int i = iAx; i <= iGz; i++) + { // set targets and initial guesses + Target[i] = 0; // must fix for ZAccel + HighOffset[i] = 0; + LowOffset[i] = 0; + } // set targets and initial guesses + Target[iAz] = 16384; + + Serial.println("expanding:"); + ForceHeader(); + PullBracketsOut(); + + Serial.println("\nclosing in:"); + ForceHeader(); + StillWorking = true; + while (StillWorking) + { StillWorking = false; + for (int i = iAx; i <= iGz; i++) + { if (HighOffset[i] <= (LowOffset[i]+1)) + { NewOffset[i] = LowOffset[i]; } + else + { // binary search + StillWorking = true; + NewOffset[i] = (LowOffset[i] + HighOffset[i]) /2; + } // binary search + } + SetOffsets(NewOffset); + GetSmoothed(); + for (int i = iAx; i <= iGz; i++) + { // closing in + if (Smoothed[i] > Target[i]) + { // use lower half + HighOffset[i] = NewOffset[i]; + HighValue[i] = Smoothed[i]; + } // use lower half + else + { // use upper half + LowOffset[i] = NewOffset[i]; + LowValue[i] = Smoothed[i]; + } // use upper half + } // closing in + ShowProgress(); + } // still working + Serial.println("-------------- done --------------"); + } // setup + +void loop() + { + } // loop From 6f6c58d00f1e5a142317a68783c06c7d81234df5 Mon Sep 17 00:00:00 2001 From: RobertRFenichel Date: Sat, 22 Oct 2016 12:37:48 -0700 Subject: [PATCH 149/335] Create IMU_Zero.ino Arduino sketch to find device-specific offsets to tell an IMU6050 that it is at rest in neutral position. --- .../MPU6050/examples/IMU_Zero/IMU_Zero.ino | 263 ++++++++++++++++++ 1 file changed, 263 insertions(+) create mode 100644 Arduino/MPU6050/examples/IMU_Zero/IMU_Zero.ino diff --git a/Arduino/MPU6050/examples/IMU_Zero/IMU_Zero.ino b/Arduino/MPU6050/examples/IMU_Zero/IMU_Zero.ino new file mode 100644 index 00000000..b889565e --- /dev/null +++ b/Arduino/MPU6050/examples/IMU_Zero/IMU_Zero.ino @@ -0,0 +1,263 @@ +// MPU6050 offset-finder, based on Jeff Rowberg's MPU6050_RAW +// 2016-10-19 by Robert R. Fenichel (bob@fenichel.net) + +// I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class +// 10/7/2011 by Jeff Rowberg +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// 2016-10-19 - initial release +// 2013-05-08 - added multiple output formats +// - added seamless Fastwire support +// 2011-10-07 - initial release + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2011 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +Put the MPU6050 in a flat and horizontal surface. + - Leave it operating for 5-10 minutes so temperature gets stabilized. + - Run this program. A "----- done -----" line will indicate that it has done its best. + - For each of the 6 offsets, you'll see 2 adjacent values to choose between, together + with their respective IMU outputs. One of the choices may be a little better than + the other. +=============================================== +*/ + +// I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files +// for both classes must be in the include path of your project +#include "I2Cdev.h" +#include "MPU6050.h" + +// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation +// is used in I2Cdev.h +#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE + #include "Wire.h" +#endif + +// class default I2C address is 0x68 +// specific I2C addresses may be passed as a parameter here +// AD0 low = 0x68 (default for InvenSense evaluation board) +// AD0 high = 0x69 +MPU6050 accelgyro; +//MPU6050 accelgyro(0x69); // <-- use for AD0 high + + +const char LBRACKET = '['; +const char RBRACKET = ']'; +const char COMMA = ','; + +const int iAx = 0; +const int iAy = 1; +const int iAz = 2; +const int iGx = 3; +const int iGy = 4; +const int iGz = 5; + +const int N = 1000; // the bigger, the smoother (and slower) +const int LinesBetweenHeaders = 5; + int LowValue[6]; + int HighValue[6]; + int Smoothed[6]; + int LowOffset[6]; + int HighOffset[6]; + int Target[6]; + int LinesOut; + +void ForceHeader() + { LinesOut = 99; } + +void GetSmoothed() + { int RawValue[6]; + long Sums[6]; + for (int i = iAx; i <= iGz; i++) + { Sums[i] = 0; } + + for (int i = 1; i <= N; i++) + { // get sums + accelgyro.getMotion6(&RawValue[0], &RawValue[1], &RawValue[2], + &RawValue[3], &RawValue[4], &RawValue[5]); + for (int j = iAx; j <= iGz; j++) + Sums[j] = Sums[j] + RawValue[j]; + } // get sums + for (int i = iAx; i <= iGz; i++) + { Smoothed[i] = (Sums[i] + N/2) / N ; } + } // GetSmoothed + +void Initialize() + { + // join I2C bus (I2Cdev library doesn't do this automatically) + #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE + Wire.begin(); + #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE + Fastwire::setup(400, true); + #endif + + Serial.begin(9600); + + // initialize device + Serial.println("Initializing I2C devices..."); + accelgyro.initialize(); + + // verify connection + Serial.println("Testing device connections..."); + Serial.println(accelgyro.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed"); + } // Initialize + +void SetOffsets(int TheOffsets[6]) + { accelgyro.setXAccelOffset(TheOffsets [iAx]); + accelgyro.setYAccelOffset(TheOffsets [iAy]); + accelgyro.setZAccelOffset(TheOffsets [iAz]); + accelgyro.setXGyroOffset (TheOffsets [iGx]); + accelgyro.setYGyroOffset (TheOffsets [iGy]); + accelgyro.setZGyroOffset (TheOffsets [iGz]); + } // SetOffsets + +void ShowProgress() + { if (LinesOut >= LinesBetweenHeaders) + { // show header + Serial.println("\tXAccel\t\t\tYAccel\t\t\t\tZAccel\t\t\tXGyro\t\t\tYGyro\t\t\tZGyro"); + LinesOut = 0; + } // show header + for (int i = iAx; i <= iGz; i++) + { Serial.print(LBRACKET); + Serial.print(LowOffset[i]), + Serial.print(COMMA); + Serial.print(HighOffset[i]); + Serial.print("] --> ["); + Serial.print(LowValue[i]); + Serial.print(COMMA); + Serial.print(HighValue[i]); + if (i == iGz) + { Serial.println(RBRACKET); } + else + { Serial.print("]\t"); } + } + ForceHeader(); + } // ShowProgress + +void PullBracketsOut() + { boolean Done = false; + int NextLowOffset[6]; + int NextHighOffset[6]; + + SetOffsets(HighOffset); + GetSmoothed(); + for (int i = iAx; i <= iGz; i++) + { HighValue[i] = Smoothed[i]; // needed for ShowProgress + } + + while (!Done) + { Done = true; + SetOffsets(LowOffset); + GetSmoothed(); + for (int i = iAx; i <= iGz; i++) + { // got low values + LowValue[i] = Smoothed[i]; + if (LowValue[i] > Target[i]) + { Done = false; + NextLowOffset[i] = LowOffset[i] - 1000; + } + else + { NextLowOffset[i] = LowOffset[i]; } + } // got low values + ShowProgress(); + for (int i = iAx; i <= iGz; i++) + { LowOffset[i] = NextLowOffset[i]; // had to wait until ShowProgress done + } + } // keep going + + Done = false; + while (!Done) + { Done = true; + SetOffsets(HighOffset); + GetSmoothed(); + for (int i = iAx; i <= iGz; i++) + { // got high values + HighValue[i] = Smoothed[i]; + if (HighValue[i] < Target[i]) + { Done = false; + NextHighOffset[i] = HighOffset[i] + 1000; + } + else + { NextHighOffset[i] = HighOffset[i]; } + } // got high values + ShowProgress(); + for (int i = iAx; i <= iGz; i++) + { HighOffset[i] = NextHighOffset[i]; // had to wait until ShowProgress done + } + } // keep going + } // PullBracketOut + +void setup() + { boolean StillWorking; + int NewOffset[6]; + + Initialize(); + for (int i = iAx; i <= iGz; i++) + { // set targets and initial guesses + Target[i] = 0; // must fix for ZAccel + HighOffset[i] = 0; + LowOffset[i] = 0; + } // set targets and initial guesses + Target[iAz] = 16384; + + Serial.println("expanding:"); + ForceHeader(); + PullBracketsOut(); + + Serial.println("\nclosing in:"); + ForceHeader(); + StillWorking = true; + while (StillWorking) + { StillWorking = false; + for (int i = iAx; i <= iGz; i++) + { if (HighOffset[i] <= (LowOffset[i]+1)) + { NewOffset[i] = LowOffset[i]; } + else + { // binary search + StillWorking = true; + NewOffset[i] = (LowOffset[i] + HighOffset[i]) /2; + } // binary search + } + SetOffsets(NewOffset); + GetSmoothed(); + for (int i = iAx; i <= iGz; i++) + { // closing in + if (Smoothed[i] > Target[i]) + { // use lower half + HighOffset[i] = NewOffset[i]; + HighValue[i] = Smoothed[i]; + } // use lower half + else + { // use upper half + LowOffset[i] = NewOffset[i]; + LowValue[i] = Smoothed[i]; + } // use upper half + } // closing in + ShowProgress(); + } // still working + Serial.println("-------------- done --------------"); + } // setup + +void loop() + { + } // loop From c6f19a81a8799f7552de90468ae19ede15e290c2 Mon Sep 17 00:00:00 2001 From: Jeff Rowberg Date: Sun, 23 Oct 2016 15:01:58 -0400 Subject: [PATCH 150/335] Delete IMU_Zero.ino Remove misplaces .ino example from project root --- IMU_Zero.ino | 263 --------------------------------------------------- 1 file changed, 263 deletions(-) delete mode 100644 IMU_Zero.ino diff --git a/IMU_Zero.ino b/IMU_Zero.ino deleted file mode 100644 index 1d8261e6..00000000 --- a/IMU_Zero.ino +++ /dev/null @@ -1,263 +0,0 @@ -// MPU6050 offset-finder, based on Jeff Rowberg's MPU6050_RAW -// 2016-10-19 by Robert R. Fenichel (bob@fenichel.net) - -// I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class -// 10/7/2011 by Jeff Rowberg -// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib -// -// Changelog: -// 2016-10-19 - initial release -// 2013-05-08 - added multiple output formats -// - added seamless Fastwire support -// 2011-10-07 - initial release - -/* ============================================ -I2Cdev device library code is placed under the MIT license -Copyright (c) 2011 Jeff Rowberg - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -Put the MPU6050 in a flat and horizontal surface. - - Leave it operating for 5-10 minutes so temperature gets stabilized. - - Run this program. A "----- done -----" line will indicate that it has done its best. - - For each of the 6 offsets, you'll see 2 adjacent values to choose between, together - with their respective IMU outputs. One of the choices may be a little better than - the other. -=============================================== -*/ - -// I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files -// for both classes must be in the include path of your project -#include "I2Cdev.h" -#include "MPU6050.h" - -// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation -// is used in I2Cdev.h -#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE - #include "Wire.h" -#endif - -// class default I2C address is 0x68 -// specific I2C addresses may be passed as a parameter here -// AD0 low = 0x68 (default for InvenSense evaluation board) -// AD0 high = 0x69 -MPU6050 accelgyro; -//MPU6050 accelgyro(0x69); // <-- use for AD0 high - - -const char LBRACKET = '['; -const char RBRACKET = ']'; -const char COMMA = ','; - -const int iAx = 0; -const int iAy = 1; -const int iAz = 2; -const int iGx = 3; -const int iGy = 4; -const int iGz = 5; - -const int N = 1000; // the bigger, the smoother (and slower) -const int LinesBetweenHeaders = 5; - int LowValue[6]; - int HighValue[6]; - int Smoothed[6]; - int LowOffset[6]; - int HighOffset[6]; - int Target[6]; - int LinesOut; - -void ForceHeader() - { LinesOut = 99; } - -void GetSmoothed() - { int RawValue[6]; - long Sums[6]; - for (int i = iAx; i <= iGz; i++) - { Sums[i] = 0; } - - for (int i = 1; i <= N; i++) - { // get sums - accelgyro.getMotion6(&RawValue[0], &RawValue[1], &RawValue[2], - &RawValue[3], &RawValue[4], &RawValue[5]); - for (int j = iAx; j <= iGz; j++) - Sums[j] = Sums[j] + RawValue[j]; - } // get sums - for (int i = iAx; i <= iGz; i++) - { Smoothed[i] = (Sums[i] + N/2) / N ; } - } // GetSmoothed - -void Initialize() - { - // join I2C bus (I2Cdev library doesn't do this automatically) - #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE - Wire.begin(); - #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE - Fastwire::setup(400, true); - #endif - - Serial.begin(9600); - - // initialize device - Serial.println("Initializing I2C devices..."); - accelgyro.initialize(); - - // verify connection - Serial.println("Testing device connections..."); - Serial.println(accelgyro.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed"); - } // Initialize - -void SetOffsets(int TheOffsets[6]) - { accelgyro.setXAccelOffset(TheOffsets [iAx]); - accelgyro.setYAccelOffset(TheOffsets [iAy]); - accelgyro.setZAccelOffset(TheOffsets [iAz]); - accelgyro.setXGyroOffset (TheOffsets [iGx]); - accelgyro.setYGyroOffset (TheOffsets [iGy]); - accelgyro.setZGyroOffset (TheOffsets [iGz]); - } // SetOffsets - -void ShowProgress() - { if (LinesOut >= LinesBetweenHeaders) - { // show header - Serial.println("\tXAccel\t\t\tYAccel\t\t\t\tZAccel\t\t\tXGyro\t\t\tYGyro\t\t\tZGyro"); - LinesOut = 0; - } // show header - for (int i = iAx; i <= iGz; i++) - { Serial.print(LBRACKET); - Serial.print(LowOffset[i]), - Serial.print(COMMA); - Serial.print(HighOffset[i]); - Serial.print("] --> ["); - Serial.print(LowValue[i]); - Serial.print(COMMA); - Serial.print(HighValue[i]); - if (i == iGz) - { Serial.println(RBRACKET); } - else - { Serial.print("]\t"); } - } - ForceHeader(); - } // ShowProgress - -void PullBracketsOut() - { boolean Done = false; - int NextLowOffset[6]; - int NextHighOffset[6]; - - SetOffsets(HighOffset); - GetSmoothed(); - for (int i = iAx; i <= iGz; i++) - { HighValue[i] = Smoothed[i]; // needed for ShowProgress - } - - while (!Done) - { Done = true; - SetOffsets(LowOffset); - GetSmoothed(); - for (int i = iAx; i <= iGz; i++) - { // got low values - LowValue[i] = Smoothed[i]; - if (LowValue[i] > Target[i]) - { Done = false; - NextLowOffset[i] = LowOffset[i] - 1000; - } - else - { NextLowOffset[i] = LowOffset[i]; } - } // got low values - ShowProgress(); - for (int i = iAx; i <= iGz; i++) - { LowOffset[i] = NextLowOffset[i]; // had to wait until ShowProgress done - } - } // keep going - - Done = false; - while (!Done) - { Done = true; - SetOffsets(HighOffset); - GetSmoothed(); - for (int i = iAx; i <= iGz; i++) - { // got high values - HighValue[i] = Smoothed[i]; - if (HighValue[i] < Target[i]) - { Done = false; - NextHighOffset[i] = HighOffset[i] + 1000; - } - else - { NextHighOffset[i] = HighOffset[i]; } - } // got high values - ShowProgress(); - for (int i = iAx; i <= iGz; i++) - { HighOffset[i] = NextHighOffset[i]; // had to wait until ShowProgress done - } - } // keep going - } // PullBracketOut - -void setup() - { boolean StillWorking; - int NewOffset[6]; - - Initialize(); - for (int i = iAx; i <= iGz; i++) - { // set targets and initial guesses - Target[i] = 0; // must fix for ZAccel - HighOffset[i] = 0; - LowOffset[i] = 0; - } // set targets and initial guesses - Target[iAz] = 16384; - - Serial.println("expanding:"); - ForceHeader(); - PullBracketsOut(); - - Serial.println("\nclosing in:"); - ForceHeader(); - StillWorking = true; - while (StillWorking) - { StillWorking = false; - for (int i = iAx; i <= iGz; i++) - { if (HighOffset[i] <= (LowOffset[i]+1)) - { NewOffset[i] = LowOffset[i]; } - else - { // binary search - StillWorking = true; - NewOffset[i] = (LowOffset[i] + HighOffset[i]) /2; - } // binary search - } - SetOffsets(NewOffset); - GetSmoothed(); - for (int i = iAx; i <= iGz; i++) - { // closing in - if (Smoothed[i] > Target[i]) - { // use lower half - HighOffset[i] = NewOffset[i]; - HighValue[i] = Smoothed[i]; - } // use lower half - else - { // use upper half - LowOffset[i] = NewOffset[i]; - LowValue[i] = Smoothed[i]; - } // use upper half - } // closing in - ShowProgress(); - } // still working - Serial.println("-------------- done --------------"); - } // setup - -void loop() - { - } // loop From 86a454dc6a68d1bdc06b49b6ccc6435b7d88ba5e Mon Sep 17 00:00:00 2001 From: RobertRFenichel Date: Tue, 25 Oct 2016 13:47:50 -0700 Subject: [PATCH 151/335] Add files via upload Improved search, added more instructive comments. --- Arduino/MPU6050/examples/IMU_Zero.ino | 297 ++++++++++++++++++++++++++ 1 file changed, 297 insertions(+) create mode 100644 Arduino/MPU6050/examples/IMU_Zero.ino diff --git a/Arduino/MPU6050/examples/IMU_Zero.ino b/Arduino/MPU6050/examples/IMU_Zero.ino new file mode 100644 index 00000000..34a6b62b --- /dev/null +++ b/Arduino/MPU6050/examples/IMU_Zero.ino @@ -0,0 +1,297 @@ +// MPU6050 offset-finder, based on Jeff Rowberg's MPU6050_RAW +// 2016-10-19 by Robert R. Fenichel (bob@fenichel.net) + +// I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class +// 10/7/2011 by Jeff Rowberg +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// 2016-10-25 - requires inequality (Low < Target, High > Target) during expansion +// dynamic speed change when closing in +// 2016-10-22 - cosmetic changes +// 2016-10-19 - initial release +// 2013-05-08 - added multiple output formats +// - added seamless Fastwire support +// 2011-10-07 - initial release + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2011 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + If an MPU6050 is an ideal member of its tribe, is properly warmed up, is at +rest in a neutral position, and has been loaded with the best possible offsets, it +will report 0 for all accelerations and displacements, except for Z acceleration, +for which it will report 16384 (that is, 2^14). Your device probably won't do +quite this well, but good offsets will all get the baseline outputs close to +these target values. + + Put the MPU6050 in a flat and horizontal surface, and leave it operating for +5-10 minutes so its temperature gets stabilized. + + Run this program. A "----- done -----" line will indicate that it has done its best. + + The line just above that will look something like + [567,567] --> [-1,2] [-2223,-2223] --> [0,1] [1131,1132] --> [16374,16404] [155,156] --> [-1,1] [-25,-24] --> [0,3] [5,6] --> [0,4] +As will have been shown in interspersed header lines, the six groups making up this +line describe the optimum offsets for the X acceleration, Y acceleration, Z acceleration, +X gyro, Y gyro, and Z gyro, respectively. In the sample shown just above, the trial showed +that +567 was the best offset for the X acceleration, -2223 was best for Y acceleration, +and so on. +=============================================== +*/ + +// I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files +// for both classes must be in the include path of your project +#include "I2Cdev.h" +#include "MPU6050.h" + +// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation +// is used in I2Cdev.h +#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE + #include "Wire.h" +#endif + +// class default I2C address is 0x68 +// specific I2C addresses may be passed as a parameter here +// AD0 low = 0x68 (default for InvenSense evaluation board) +// AD0 high = 0x69 +MPU6050 accelgyro; +//MPU6050 accelgyro(0x69); // <-- use for AD0 high + + +const char LBRACKET = '['; +const char RBRACKET = ']'; +const char COMMA = ','; + +const int iAx = 0; +const int iAy = 1; +const int iAz = 2; +const int iGx = 3; +const int iGy = 4; +const int iGz = 5; + +const int NFast = 1000; // the bigger, the better (but slower) +const int NSlow = 10000; // .. +const int LinesBetweenHeaders = 5; + int LowValue[6]; + int HighValue[6]; + int Smoothed[6]; + int LowOffset[6]; + int HighOffset[6]; + int Target[6]; + int LinesOut; + int N; + +void ForceHeader() + { LinesOut = 99; } + +void GetSmoothed() + { int RawValue[6]; + long Sums[6]; + for (int i = iAx; i <= iGz; i++) + { Sums[i] = 0; } + + for (int i = 1; i <= N; i++) + { // get sums + accelgyro.getMotion6(&RawValue[iAx], &RawValue[iAy], &RawValue[iAz], + &RawValue[iGx], &RawValue[iGy], &RawValue[iGz]); + for (int j = iAx; j <= iGz; j++) + Sums[j] = Sums[j] + RawValue[j]; + } // get sums + for (int i = iAx; i <= iGz; i++) + { Smoothed[i] = (Sums[i] + N/2) / N ; } + } // GetSmoothed + +void Initialize() + { + // join I2C bus (I2Cdev library doesn't do this automatically) + #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE + Wire.begin(); + #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE + Fastwire::setup(400, true); + #endif + + Serial.begin(9600); + + // initialize device + Serial.println("Initializing I2C devices..."); + accelgyro.initialize(); + + // verify connection + Serial.println("Testing device connections..."); + Serial.println(accelgyro.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed"); + } // Initialize + +void SetOffsets(int TheOffsets[6]) + { accelgyro.setXAccelOffset(TheOffsets [iAx]); + accelgyro.setYAccelOffset(TheOffsets [iAy]); + accelgyro.setZAccelOffset(TheOffsets [iAz]); + accelgyro.setXGyroOffset (TheOffsets [iGx]); + accelgyro.setYGyroOffset (TheOffsets [iGy]); + accelgyro.setZGyroOffset (TheOffsets [iGz]); + } // SetOffsets + +void ShowProgress() + { if (LinesOut >= LinesBetweenHeaders) + { // show header + Serial.println("\tXAccel\t\t\tYAccel\t\t\t\tZAccel\t\t\tXGyro\t\t\tYGyro\t\t\tZGyro"); + LinesOut = 0; + } // show header + for (int i = iAx; i <= iGz; i++) + { Serial.print(LBRACKET); + Serial.print(LowOffset[i]), + Serial.print(COMMA); + Serial.print(HighOffset[i]); + Serial.print("] --> ["); + Serial.print(LowValue[i]); + Serial.print(COMMA); + Serial.print(HighValue[i]); + if (i == iGz) + { Serial.println(RBRACKET); } + else + { Serial.print("]\t"); } + } + LinesOut++; + } // ShowProgress + +void PullBracketsOut() + { boolean Done = false; + int NextLowOffset[6]; + int NextHighOffset[6]; + + SetOffsets(HighOffset); + GetSmoothed(); + for (int i = iAx; i <= iGz; i++) + { HighValue[i] = Smoothed[i]; // needed for ShowProgress + } + + while (!Done) + { Done = true; + SetOffsets(LowOffset); + GetSmoothed(); + for (int i = iAx; i <= iGz; i++) + { // got low values + LowValue[i] = Smoothed[i]; + if (LowValue[i] >= Target[i]) + { Done = false; + NextLowOffset[i] = LowOffset[i] - 1000; + } + else + { NextLowOffset[i] = LowOffset[i]; } + } // got low values + ShowProgress(); + for (int i = iAx; i <= iGz; i++) + { LowOffset[i] = NextLowOffset[i]; // had to wait until ShowProgress done + } + } // keep going + + Done = false; + while (!Done) + { Done = true; + SetOffsets(HighOffset); + GetSmoothed(); + for (int i = iAx; i <= iGz; i++) + { // got high values + HighValue[i] = Smoothed[i]; + if (HighValue[i] <= Target[i]) + { Done = false; + NextHighOffset[i] = HighOffset[i] + 1000; + } + else + { NextHighOffset[i] = HighOffset[i]; } + } // got high values + ShowProgress(); + for (int i = iAx; i <= iGz; i++) + { HighOffset[i] = NextHighOffset[i]; // had to wait until ShowProgress done + } + } // keep going + } // PullBracketOut + +void SetAveraging(int NewN) + { N = NewN; + Serial.print("averaging "); + Serial.print(N); + Serial.println(" readings each time"); + } // SetAveraging + +void setup() + { boolean StillWorking; + int NewOffset[6]; + boolean AllBracketsNarrow; + + Initialize(); + for (int i = iAx; i <= iGz; i++) + { // set targets and initial guesses + Target[i] = 0; // must fix for ZAccel + HighOffset[i] = 0; + LowOffset[i] = 0; + } // set targets and initial guesses + Target[iAz] = 16384; + SetAveraging(NFast); + + Serial.println("expanding:"); + ForceHeader(); + PullBracketsOut(); + + Serial.println("\nclosing in:"); + AllBracketsNarrow = false; + ForceHeader(); + StillWorking = true; + while (StillWorking) + { StillWorking = false; + if (AllBracketsNarrow && (N == NFast)) + { SetAveraging(NSlow); } + else + { AllBracketsNarrow = true; }// tentative + for (int i = iAx; i <= iGz; i++) + { if (HighOffset[i] <= (LowOffset[i]+1)) + { NewOffset[i] = LowOffset[i]; } + else + { // binary search + StillWorking = true; + NewOffset[i] = (LowOffset[i] + HighOffset[i]) / 2; + if (HighOffset[i] > (LowOffset[i] + 10)) + { AllBracketsNarrow = false; } + } // binary search + } + SetOffsets(NewOffset); + GetSmoothed(); + for (int i = iAx; i <= iGz; i++) + { // closing in + if (Smoothed[i] > Target[i]) + { // use lower half + HighOffset[i] = NewOffset[i]; + HighValue[i] = Smoothed[i]; + } // use lower half + else + { // use upper half + LowOffset[i] = NewOffset[i]; + LowValue[i] = Smoothed[i]; + } // use upper half + } // closing in + ShowProgress(); + } // still working + Serial.println("-------------- done --------------"); + } // setup + +void loop() + { + } // loop From 0d0f8c69a07104b500df20407baf84127a412606 Mon Sep 17 00:00:00 2001 From: RobertRFenichel Date: Tue, 25 Oct 2016 13:51:19 -0700 Subject: [PATCH 152/335] Add files via upload Improved search and added instructions in comments. --- .../MPU6050/examples/IMU_Zero/IMU_Zero.ino | 62 ++++++++++++++----- 1 file changed, 48 insertions(+), 14 deletions(-) diff --git a/Arduino/MPU6050/examples/IMU_Zero/IMU_Zero.ino b/Arduino/MPU6050/examples/IMU_Zero/IMU_Zero.ino index b889565e..34a6b62b 100644 --- a/Arduino/MPU6050/examples/IMU_Zero/IMU_Zero.ino +++ b/Arduino/MPU6050/examples/IMU_Zero/IMU_Zero.ino @@ -6,6 +6,9 @@ // Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib // // Changelog: +// 2016-10-25 - requires inequality (Low < Target, High > Target) during expansion +// dynamic speed change when closing in +// 2016-10-22 - cosmetic changes // 2016-10-19 - initial release // 2013-05-08 - added multiple output formats // - added seamless Fastwire support @@ -33,12 +36,25 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -Put the MPU6050 in a flat and horizontal surface. - - Leave it operating for 5-10 minutes so temperature gets stabilized. - - Run this program. A "----- done -----" line will indicate that it has done its best. - - For each of the 6 offsets, you'll see 2 adjacent values to choose between, together - with their respective IMU outputs. One of the choices may be a little better than - the other. + If an MPU6050 is an ideal member of its tribe, is properly warmed up, is at +rest in a neutral position, and has been loaded with the best possible offsets, it +will report 0 for all accelerations and displacements, except for Z acceleration, +for which it will report 16384 (that is, 2^14). Your device probably won't do +quite this well, but good offsets will all get the baseline outputs close to +these target values. + + Put the MPU6050 in a flat and horizontal surface, and leave it operating for +5-10 minutes so its temperature gets stabilized. + + Run this program. A "----- done -----" line will indicate that it has done its best. + + The line just above that will look something like + [567,567] --> [-1,2] [-2223,-2223] --> [0,1] [1131,1132] --> [16374,16404] [155,156] --> [-1,1] [-25,-24] --> [0,3] [5,6] --> [0,4] +As will have been shown in interspersed header lines, the six groups making up this +line describe the optimum offsets for the X acceleration, Y acceleration, Z acceleration, +X gyro, Y gyro, and Z gyro, respectively. In the sample shown just above, the trial showed +that +567 was the best offset for the X acceleration, -2223 was best for Y acceleration, +and so on. =============================================== */ @@ -72,7 +88,8 @@ const int iGx = 3; const int iGy = 4; const int iGz = 5; -const int N = 1000; // the bigger, the smoother (and slower) +const int NFast = 1000; // the bigger, the better (but slower) +const int NSlow = 10000; // .. const int LinesBetweenHeaders = 5; int LowValue[6]; int HighValue[6]; @@ -81,6 +98,7 @@ const int LinesBetweenHeaders = 5; int HighOffset[6]; int Target[6]; int LinesOut; + int N; void ForceHeader() { LinesOut = 99; } @@ -93,8 +111,8 @@ void GetSmoothed() for (int i = 1; i <= N; i++) { // get sums - accelgyro.getMotion6(&RawValue[0], &RawValue[1], &RawValue[2], - &RawValue[3], &RawValue[4], &RawValue[5]); + accelgyro.getMotion6(&RawValue[iAx], &RawValue[iAy], &RawValue[iAz], + &RawValue[iGx], &RawValue[iGy], &RawValue[iGz]); for (int j = iAx; j <= iGz; j++) Sums[j] = Sums[j] + RawValue[j]; } // get sums @@ -151,7 +169,7 @@ void ShowProgress() else { Serial.print("]\t"); } } - ForceHeader(); + LinesOut++; } // ShowProgress void PullBracketsOut() @@ -172,7 +190,7 @@ void PullBracketsOut() for (int i = iAx; i <= iGz; i++) { // got low values LowValue[i] = Smoothed[i]; - if (LowValue[i] > Target[i]) + if (LowValue[i] >= Target[i]) { Done = false; NextLowOffset[i] = LowOffset[i] - 1000; } @@ -193,7 +211,7 @@ void PullBracketsOut() for (int i = iAx; i <= iGz; i++) { // got high values HighValue[i] = Smoothed[i]; - if (HighValue[i] < Target[i]) + if (HighValue[i] <= Target[i]) { Done = false; NextHighOffset[i] = HighOffset[i] + 1000; } @@ -207,9 +225,17 @@ void PullBracketsOut() } // keep going } // PullBracketOut +void SetAveraging(int NewN) + { N = NewN; + Serial.print("averaging "); + Serial.print(N); + Serial.println(" readings each time"); + } // SetAveraging + void setup() { boolean StillWorking; int NewOffset[6]; + boolean AllBracketsNarrow; Initialize(); for (int i = iAx; i <= iGz; i++) @@ -219,23 +245,31 @@ void setup() LowOffset[i] = 0; } // set targets and initial guesses Target[iAz] = 16384; + SetAveraging(NFast); Serial.println("expanding:"); ForceHeader(); PullBracketsOut(); Serial.println("\nclosing in:"); + AllBracketsNarrow = false; ForceHeader(); StillWorking = true; while (StillWorking) { StillWorking = false; + if (AllBracketsNarrow && (N == NFast)) + { SetAveraging(NSlow); } + else + { AllBracketsNarrow = true; }// tentative for (int i = iAx; i <= iGz; i++) { if (HighOffset[i] <= (LowOffset[i]+1)) { NewOffset[i] = LowOffset[i]; } else { // binary search StillWorking = true; - NewOffset[i] = (LowOffset[i] + HighOffset[i]) /2; + NewOffset[i] = (LowOffset[i] + HighOffset[i]) / 2; + if (HighOffset[i] > (LowOffset[i] + 10)) + { AllBracketsNarrow = false; } } // binary search } SetOffsets(NewOffset); @@ -260,4 +294,4 @@ void setup() void loop() { - } // loop + } // loop From 1f86a3c6da95fc74ed81a92f26ef7c7f6e95c6d2 Mon Sep 17 00:00:00 2001 From: Jeff Rowberg Date: Wed, 26 Oct 2016 09:20:53 -0400 Subject: [PATCH 153/335] Delete IMU_Zero.ino Remove duplicate IMU_Zero.ino from incorrect folder --- Arduino/MPU6050/examples/IMU_Zero.ino | 297 -------------------------- 1 file changed, 297 deletions(-) delete mode 100644 Arduino/MPU6050/examples/IMU_Zero.ino diff --git a/Arduino/MPU6050/examples/IMU_Zero.ino b/Arduino/MPU6050/examples/IMU_Zero.ino deleted file mode 100644 index 34a6b62b..00000000 --- a/Arduino/MPU6050/examples/IMU_Zero.ino +++ /dev/null @@ -1,297 +0,0 @@ -// MPU6050 offset-finder, based on Jeff Rowberg's MPU6050_RAW -// 2016-10-19 by Robert R. Fenichel (bob@fenichel.net) - -// I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class -// 10/7/2011 by Jeff Rowberg -// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib -// -// Changelog: -// 2016-10-25 - requires inequality (Low < Target, High > Target) during expansion -// dynamic speed change when closing in -// 2016-10-22 - cosmetic changes -// 2016-10-19 - initial release -// 2013-05-08 - added multiple output formats -// - added seamless Fastwire support -// 2011-10-07 - initial release - -/* ============================================ -I2Cdev device library code is placed under the MIT license -Copyright (c) 2011 Jeff Rowberg - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - If an MPU6050 is an ideal member of its tribe, is properly warmed up, is at -rest in a neutral position, and has been loaded with the best possible offsets, it -will report 0 for all accelerations and displacements, except for Z acceleration, -for which it will report 16384 (that is, 2^14). Your device probably won't do -quite this well, but good offsets will all get the baseline outputs close to -these target values. - - Put the MPU6050 in a flat and horizontal surface, and leave it operating for -5-10 minutes so its temperature gets stabilized. - - Run this program. A "----- done -----" line will indicate that it has done its best. - - The line just above that will look something like - [567,567] --> [-1,2] [-2223,-2223] --> [0,1] [1131,1132] --> [16374,16404] [155,156] --> [-1,1] [-25,-24] --> [0,3] [5,6] --> [0,4] -As will have been shown in interspersed header lines, the six groups making up this -line describe the optimum offsets for the X acceleration, Y acceleration, Z acceleration, -X gyro, Y gyro, and Z gyro, respectively. In the sample shown just above, the trial showed -that +567 was the best offset for the X acceleration, -2223 was best for Y acceleration, -and so on. -=============================================== -*/ - -// I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files -// for both classes must be in the include path of your project -#include "I2Cdev.h" -#include "MPU6050.h" - -// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation -// is used in I2Cdev.h -#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE - #include "Wire.h" -#endif - -// class default I2C address is 0x68 -// specific I2C addresses may be passed as a parameter here -// AD0 low = 0x68 (default for InvenSense evaluation board) -// AD0 high = 0x69 -MPU6050 accelgyro; -//MPU6050 accelgyro(0x69); // <-- use for AD0 high - - -const char LBRACKET = '['; -const char RBRACKET = ']'; -const char COMMA = ','; - -const int iAx = 0; -const int iAy = 1; -const int iAz = 2; -const int iGx = 3; -const int iGy = 4; -const int iGz = 5; - -const int NFast = 1000; // the bigger, the better (but slower) -const int NSlow = 10000; // .. -const int LinesBetweenHeaders = 5; - int LowValue[6]; - int HighValue[6]; - int Smoothed[6]; - int LowOffset[6]; - int HighOffset[6]; - int Target[6]; - int LinesOut; - int N; - -void ForceHeader() - { LinesOut = 99; } - -void GetSmoothed() - { int RawValue[6]; - long Sums[6]; - for (int i = iAx; i <= iGz; i++) - { Sums[i] = 0; } - - for (int i = 1; i <= N; i++) - { // get sums - accelgyro.getMotion6(&RawValue[iAx], &RawValue[iAy], &RawValue[iAz], - &RawValue[iGx], &RawValue[iGy], &RawValue[iGz]); - for (int j = iAx; j <= iGz; j++) - Sums[j] = Sums[j] + RawValue[j]; - } // get sums - for (int i = iAx; i <= iGz; i++) - { Smoothed[i] = (Sums[i] + N/2) / N ; } - } // GetSmoothed - -void Initialize() - { - // join I2C bus (I2Cdev library doesn't do this automatically) - #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE - Wire.begin(); - #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE - Fastwire::setup(400, true); - #endif - - Serial.begin(9600); - - // initialize device - Serial.println("Initializing I2C devices..."); - accelgyro.initialize(); - - // verify connection - Serial.println("Testing device connections..."); - Serial.println(accelgyro.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed"); - } // Initialize - -void SetOffsets(int TheOffsets[6]) - { accelgyro.setXAccelOffset(TheOffsets [iAx]); - accelgyro.setYAccelOffset(TheOffsets [iAy]); - accelgyro.setZAccelOffset(TheOffsets [iAz]); - accelgyro.setXGyroOffset (TheOffsets [iGx]); - accelgyro.setYGyroOffset (TheOffsets [iGy]); - accelgyro.setZGyroOffset (TheOffsets [iGz]); - } // SetOffsets - -void ShowProgress() - { if (LinesOut >= LinesBetweenHeaders) - { // show header - Serial.println("\tXAccel\t\t\tYAccel\t\t\t\tZAccel\t\t\tXGyro\t\t\tYGyro\t\t\tZGyro"); - LinesOut = 0; - } // show header - for (int i = iAx; i <= iGz; i++) - { Serial.print(LBRACKET); - Serial.print(LowOffset[i]), - Serial.print(COMMA); - Serial.print(HighOffset[i]); - Serial.print("] --> ["); - Serial.print(LowValue[i]); - Serial.print(COMMA); - Serial.print(HighValue[i]); - if (i == iGz) - { Serial.println(RBRACKET); } - else - { Serial.print("]\t"); } - } - LinesOut++; - } // ShowProgress - -void PullBracketsOut() - { boolean Done = false; - int NextLowOffset[6]; - int NextHighOffset[6]; - - SetOffsets(HighOffset); - GetSmoothed(); - for (int i = iAx; i <= iGz; i++) - { HighValue[i] = Smoothed[i]; // needed for ShowProgress - } - - while (!Done) - { Done = true; - SetOffsets(LowOffset); - GetSmoothed(); - for (int i = iAx; i <= iGz; i++) - { // got low values - LowValue[i] = Smoothed[i]; - if (LowValue[i] >= Target[i]) - { Done = false; - NextLowOffset[i] = LowOffset[i] - 1000; - } - else - { NextLowOffset[i] = LowOffset[i]; } - } // got low values - ShowProgress(); - for (int i = iAx; i <= iGz; i++) - { LowOffset[i] = NextLowOffset[i]; // had to wait until ShowProgress done - } - } // keep going - - Done = false; - while (!Done) - { Done = true; - SetOffsets(HighOffset); - GetSmoothed(); - for (int i = iAx; i <= iGz; i++) - { // got high values - HighValue[i] = Smoothed[i]; - if (HighValue[i] <= Target[i]) - { Done = false; - NextHighOffset[i] = HighOffset[i] + 1000; - } - else - { NextHighOffset[i] = HighOffset[i]; } - } // got high values - ShowProgress(); - for (int i = iAx; i <= iGz; i++) - { HighOffset[i] = NextHighOffset[i]; // had to wait until ShowProgress done - } - } // keep going - } // PullBracketOut - -void SetAveraging(int NewN) - { N = NewN; - Serial.print("averaging "); - Serial.print(N); - Serial.println(" readings each time"); - } // SetAveraging - -void setup() - { boolean StillWorking; - int NewOffset[6]; - boolean AllBracketsNarrow; - - Initialize(); - for (int i = iAx; i <= iGz; i++) - { // set targets and initial guesses - Target[i] = 0; // must fix for ZAccel - HighOffset[i] = 0; - LowOffset[i] = 0; - } // set targets and initial guesses - Target[iAz] = 16384; - SetAveraging(NFast); - - Serial.println("expanding:"); - ForceHeader(); - PullBracketsOut(); - - Serial.println("\nclosing in:"); - AllBracketsNarrow = false; - ForceHeader(); - StillWorking = true; - while (StillWorking) - { StillWorking = false; - if (AllBracketsNarrow && (N == NFast)) - { SetAveraging(NSlow); } - else - { AllBracketsNarrow = true; }// tentative - for (int i = iAx; i <= iGz; i++) - { if (HighOffset[i] <= (LowOffset[i]+1)) - { NewOffset[i] = LowOffset[i]; } - else - { // binary search - StillWorking = true; - NewOffset[i] = (LowOffset[i] + HighOffset[i]) / 2; - if (HighOffset[i] > (LowOffset[i] + 10)) - { AllBracketsNarrow = false; } - } // binary search - } - SetOffsets(NewOffset); - GetSmoothed(); - for (int i = iAx; i <= iGz; i++) - { // closing in - if (Smoothed[i] > Target[i]) - { // use lower half - HighOffset[i] = NewOffset[i]; - HighValue[i] = Smoothed[i]; - } // use lower half - else - { // use upper half - LowOffset[i] = NewOffset[i]; - LowValue[i] = Smoothed[i]; - } // use upper half - } // closing in - ShowProgress(); - } // still working - Serial.println("-------------- done --------------"); - } // setup - -void loop() - { - } // loop From 0129c52115e319908af0eccd555ef46f64969514 Mon Sep 17 00:00:00 2001 From: Jeremy Barnes Date: Mon, 7 Nov 2016 20:53:21 +0000 Subject: [PATCH 154/335] Fixed typo in DS1307 implementation --- Arduino/DS1307/DS1307.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Arduino/DS1307/DS1307.cpp b/Arduino/DS1307/DS1307.cpp index 87930e35..1d01761c 100644 --- a/Arduino/DS1307/DS1307.cpp +++ b/Arduino/DS1307/DS1307.cpp @@ -435,7 +435,7 @@ void DS1307::setDateTime24(uint16_t year, uint8_t month, uint8_t day, uint8_t ho yOff = conv2d(date + 9); // Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec switch (date[0]) { - case 'J': m = date[1] == 'a' ? 1 : m = date[2] == 'n' ? 6 : 7; break; + case 'J': m = (date[1] == 'a' ? 1 : (date[2] == 'n' ? 6 : 7)); break; case 'F': m = 2; break; case 'A': m = date[2] == 'r' ? 4 : 8; break; case 'M': m = date[2] == 'r' ? 3 : 5; break; From 1d6637f7a55a38d5f32f46e517037719655ab3a7 Mon Sep 17 00:00:00 2001 From: Kilian Pfeiffer Date: Fri, 2 Dec 2016 15:40:44 +0100 Subject: [PATCH 155/335] Unknown function is actually setting start address MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unknown function is actually setting start address of DMP, where the firmware is supposed to execute. Source: http://www.robotrebels.org/index.php?topic=318.0 << Register 109 (0x6D) Bank Select Address – firmware loaded in 256 byte banks 0-11 (total 3k) Register 110 (0x6E) Bank Memory Address – the actual byte address within the bank Register 111 (0x6F) Firmware Read/Write – the portal to read and write a byte through Register 112 (0x70) Program Start Address H – this is where this firmware version begins to execute (0x0400) {0x0300 in our case} Register 113 (0x71) Program Start Address L >> --- Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h index 1c055433..01ea1c97 100644 --- a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h +++ b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h @@ -409,8 +409,10 @@ uint8_t MPU6050::dmpInitialize() { DEBUG_PRINTLN(F("Setting gyro sensitivity to +/- 2000 deg/sec...")); setFullScaleGyroRange(MPU6050_GYRO_FS_2000); - DEBUG_PRINTLN(F("Setting DMP configuration bytes (function unknown)...")); + DEBUG_PRINTLN(F("Setting DMP programm start address")); + //write start address MSB into register setDMPConfig1(0x03); + //write start adress LSB into register setDMPConfig2(0x00); DEBUG_PRINTLN(F("Clearing OTP Bank flag...")); From 32e1ca096deb8151ee5397f6e0bd7ae15583f7b7 Mon Sep 17 00:00:00 2001 From: Kilian Pfeiffer Date: Sun, 4 Dec 2016 13:51:57 +0100 Subject: [PATCH 156/335] Update MPU6050_6Axis_MotionApps20.h --- Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h index 01ea1c97..e3e3c0e8 100644 --- a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h +++ b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h @@ -412,7 +412,7 @@ uint8_t MPU6050::dmpInitialize() { DEBUG_PRINTLN(F("Setting DMP programm start address")); //write start address MSB into register setDMPConfig1(0x03); - //write start adress LSB into register + //write start address LSB into register setDMPConfig2(0x00); DEBUG_PRINTLN(F("Clearing OTP Bank flag...")); From a0d2b1dacc65f1435b8593189fb7b25fa7fe05b0 Mon Sep 17 00:00:00 2001 From: RobertRFenichel Date: Mon, 5 Dec 2016 09:09:24 -0800 Subject: [PATCH 157/335] Update IMU_Zero.ino Added delay to keep from reading IMU faster than 200 Hz. Without the delays, program hangs on some devices. Comments expanded. --- .../MPU6050/examples/IMU_Zero/IMU_Zero.ino | 613 +++++++++--------- 1 file changed, 317 insertions(+), 296 deletions(-) diff --git a/Arduino/MPU6050/examples/IMU_Zero/IMU_Zero.ino b/Arduino/MPU6050/examples/IMU_Zero/IMU_Zero.ino index 34a6b62b..bd72c4cb 100644 --- a/Arduino/MPU6050/examples/IMU_Zero/IMU_Zero.ino +++ b/Arduino/MPU6050/examples/IMU_Zero/IMU_Zero.ino @@ -1,297 +1,318 @@ -// MPU6050 offset-finder, based on Jeff Rowberg's MPU6050_RAW -// 2016-10-19 by Robert R. Fenichel (bob@fenichel.net) - -// I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class -// 10/7/2011 by Jeff Rowberg -// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib -// -// Changelog: -// 2016-10-25 - requires inequality (Low < Target, High > Target) during expansion -// dynamic speed change when closing in -// 2016-10-22 - cosmetic changes -// 2016-10-19 - initial release -// 2013-05-08 - added multiple output formats -// - added seamless Fastwire support -// 2011-10-07 - initial release - -/* ============================================ -I2Cdev device library code is placed under the MIT license -Copyright (c) 2011 Jeff Rowberg - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - If an MPU6050 is an ideal member of its tribe, is properly warmed up, is at -rest in a neutral position, and has been loaded with the best possible offsets, it -will report 0 for all accelerations and displacements, except for Z acceleration, -for which it will report 16384 (that is, 2^14). Your device probably won't do -quite this well, but good offsets will all get the baseline outputs close to -these target values. - - Put the MPU6050 in a flat and horizontal surface, and leave it operating for -5-10 minutes so its temperature gets stabilized. - - Run this program. A "----- done -----" line will indicate that it has done its best. - - The line just above that will look something like - [567,567] --> [-1,2] [-2223,-2223] --> [0,1] [1131,1132] --> [16374,16404] [155,156] --> [-1,1] [-25,-24] --> [0,3] [5,6] --> [0,4] -As will have been shown in interspersed header lines, the six groups making up this -line describe the optimum offsets for the X acceleration, Y acceleration, Z acceleration, -X gyro, Y gyro, and Z gyro, respectively. In the sample shown just above, the trial showed -that +567 was the best offset for the X acceleration, -2223 was best for Y acceleration, -and so on. -=============================================== -*/ - -// I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files -// for both classes must be in the include path of your project -#include "I2Cdev.h" -#include "MPU6050.h" - -// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation -// is used in I2Cdev.h -#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE - #include "Wire.h" -#endif - -// class default I2C address is 0x68 -// specific I2C addresses may be passed as a parameter here -// AD0 low = 0x68 (default for InvenSense evaluation board) -// AD0 high = 0x69 -MPU6050 accelgyro; -//MPU6050 accelgyro(0x69); // <-- use for AD0 high - - -const char LBRACKET = '['; -const char RBRACKET = ']'; -const char COMMA = ','; - -const int iAx = 0; -const int iAy = 1; -const int iAz = 2; -const int iGx = 3; -const int iGy = 4; -const int iGz = 5; - -const int NFast = 1000; // the bigger, the better (but slower) -const int NSlow = 10000; // .. -const int LinesBetweenHeaders = 5; - int LowValue[6]; - int HighValue[6]; - int Smoothed[6]; - int LowOffset[6]; - int HighOffset[6]; - int Target[6]; - int LinesOut; - int N; - -void ForceHeader() - { LinesOut = 99; } - -void GetSmoothed() - { int RawValue[6]; - long Sums[6]; - for (int i = iAx; i <= iGz; i++) - { Sums[i] = 0; } - - for (int i = 1; i <= N; i++) - { // get sums - accelgyro.getMotion6(&RawValue[iAx], &RawValue[iAy], &RawValue[iAz], - &RawValue[iGx], &RawValue[iGy], &RawValue[iGz]); - for (int j = iAx; j <= iGz; j++) - Sums[j] = Sums[j] + RawValue[j]; - } // get sums - for (int i = iAx; i <= iGz; i++) - { Smoothed[i] = (Sums[i] + N/2) / N ; } - } // GetSmoothed - -void Initialize() - { - // join I2C bus (I2Cdev library doesn't do this automatically) - #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE - Wire.begin(); - #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE - Fastwire::setup(400, true); - #endif - - Serial.begin(9600); - - // initialize device - Serial.println("Initializing I2C devices..."); - accelgyro.initialize(); - - // verify connection - Serial.println("Testing device connections..."); - Serial.println(accelgyro.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed"); - } // Initialize - -void SetOffsets(int TheOffsets[6]) - { accelgyro.setXAccelOffset(TheOffsets [iAx]); - accelgyro.setYAccelOffset(TheOffsets [iAy]); - accelgyro.setZAccelOffset(TheOffsets [iAz]); - accelgyro.setXGyroOffset (TheOffsets [iGx]); - accelgyro.setYGyroOffset (TheOffsets [iGy]); - accelgyro.setZGyroOffset (TheOffsets [iGz]); - } // SetOffsets - -void ShowProgress() - { if (LinesOut >= LinesBetweenHeaders) - { // show header - Serial.println("\tXAccel\t\t\tYAccel\t\t\t\tZAccel\t\t\tXGyro\t\t\tYGyro\t\t\tZGyro"); - LinesOut = 0; - } // show header - for (int i = iAx; i <= iGz; i++) - { Serial.print(LBRACKET); - Serial.print(LowOffset[i]), - Serial.print(COMMA); - Serial.print(HighOffset[i]); - Serial.print("] --> ["); - Serial.print(LowValue[i]); - Serial.print(COMMA); - Serial.print(HighValue[i]); - if (i == iGz) - { Serial.println(RBRACKET); } - else - { Serial.print("]\t"); } - } - LinesOut++; - } // ShowProgress - -void PullBracketsOut() - { boolean Done = false; - int NextLowOffset[6]; - int NextHighOffset[6]; - - SetOffsets(HighOffset); - GetSmoothed(); - for (int i = iAx; i <= iGz; i++) - { HighValue[i] = Smoothed[i]; // needed for ShowProgress - } - - while (!Done) - { Done = true; - SetOffsets(LowOffset); - GetSmoothed(); - for (int i = iAx; i <= iGz; i++) - { // got low values - LowValue[i] = Smoothed[i]; - if (LowValue[i] >= Target[i]) - { Done = false; - NextLowOffset[i] = LowOffset[i] - 1000; - } - else - { NextLowOffset[i] = LowOffset[i]; } - } // got low values - ShowProgress(); - for (int i = iAx; i <= iGz; i++) - { LowOffset[i] = NextLowOffset[i]; // had to wait until ShowProgress done - } - } // keep going - - Done = false; - while (!Done) - { Done = true; - SetOffsets(HighOffset); - GetSmoothed(); - for (int i = iAx; i <= iGz; i++) - { // got high values - HighValue[i] = Smoothed[i]; - if (HighValue[i] <= Target[i]) - { Done = false; - NextHighOffset[i] = HighOffset[i] + 1000; - } - else - { NextHighOffset[i] = HighOffset[i]; } - } // got high values - ShowProgress(); - for (int i = iAx; i <= iGz; i++) - { HighOffset[i] = NextHighOffset[i]; // had to wait until ShowProgress done - } - } // keep going - } // PullBracketOut - -void SetAveraging(int NewN) - { N = NewN; - Serial.print("averaging "); - Serial.print(N); - Serial.println(" readings each time"); - } // SetAveraging - -void setup() - { boolean StillWorking; - int NewOffset[6]; - boolean AllBracketsNarrow; - - Initialize(); - for (int i = iAx; i <= iGz; i++) - { // set targets and initial guesses - Target[i] = 0; // must fix for ZAccel - HighOffset[i] = 0; - LowOffset[i] = 0; - } // set targets and initial guesses - Target[iAz] = 16384; - SetAveraging(NFast); - - Serial.println("expanding:"); - ForceHeader(); - PullBracketsOut(); - - Serial.println("\nclosing in:"); - AllBracketsNarrow = false; - ForceHeader(); - StillWorking = true; - while (StillWorking) - { StillWorking = false; - if (AllBracketsNarrow && (N == NFast)) - { SetAveraging(NSlow); } - else - { AllBracketsNarrow = true; }// tentative - for (int i = iAx; i <= iGz; i++) - { if (HighOffset[i] <= (LowOffset[i]+1)) - { NewOffset[i] = LowOffset[i]; } - else - { // binary search - StillWorking = true; - NewOffset[i] = (LowOffset[i] + HighOffset[i]) / 2; - if (HighOffset[i] > (LowOffset[i] + 10)) - { AllBracketsNarrow = false; } - } // binary search - } - SetOffsets(NewOffset); - GetSmoothed(); - for (int i = iAx; i <= iGz; i++) - { // closing in - if (Smoothed[i] > Target[i]) - { // use lower half - HighOffset[i] = NewOffset[i]; - HighValue[i] = Smoothed[i]; - } // use lower half - else - { // use upper half - LowOffset[i] = NewOffset[i]; - LowValue[i] = Smoothed[i]; - } // use upper half - } // closing in - ShowProgress(); - } // still working - Serial.println("-------------- done --------------"); - } // setup - -void loop() - { +// MPU6050 offset-finder, based on Jeff Rowberg's MPU6050_RAW +// 2016-10-19 by Robert R. Fenichel (bob@fenichel.net) + +// I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class +// 10/7/2011 by Jeff Rowberg +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// 2016-11-25 - added delays to reduce sampling rate to ~200 Hz +// added temporizing printing during long computations +// 2016-10-25 - requires inequality (Low < Target, High > Target) during expansion +// dynamic speed change when closing in +// 2016-10-22 - cosmetic changes +// 2016-10-19 - initial release of IMU_Zero +// 2013-05-08 - added multiple output formats +// - added seamless Fastwire support +// 2011-10-07 - initial release of MPU6050_RAW + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2011 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + If an MPU6050 + * is an ideal member of its tribe, + * is properly warmed up, + * is at rest in a neutral position, + * is in a location where the pull of gravity is exactly 1g, and + * has been loaded with the best possible offsets, +then it will report 0 for all accelerations and displacements, except for +Z acceleration, for which it will report 16384 (that is, 2^14). Your device +probably won't do quite this well, but good offsets will all get the baseline +outputs close to these target values. + + Put the MPU6050 in a flat and horizontal surface, and leave it operating for +5-10 minutes so its temperature gets stabilized. + + Run this program. A "----- done -----" line will indicate that it has done its best. +With the current accuracy-related constants (NFast = 1000, NSlow = 10000), it will take +a few minutes to get there. + + Along the way, it will generate a dozen or so lines of output, showing that for each +of the 6 desired offsets, it is + * first, trying to find two estimates, one too low and one too high, and + * then, closing in until the bracket can't be made smaller. + + The line just above the "done" line will look something like + [567,567] --> [-1,2] [-2223,-2223] --> [0,1] [1131,1132] --> [16374,16404] [155,156] --> [-1,1] [-25,-24] --> [0,3] [5,6] --> [0,4] +As will have been shown in interspersed header lines, the six groups making up this +line describe the optimum offsets for the X acceleration, Y acceleration, Z acceleration, +X gyro, Y gyro, and Z gyro, respectively. In the sample shown just above, the trial showed +that +567 was the best offset for the X acceleration, -2223 was best for Y acceleration, +and so on. + + The need for the delay between readings (usDelay) was brought to my attention by Nikolaus Doppelhammer. +=============================================== +*/ + +// I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files +// for both classes must be in the include path of your project +#include "I2Cdev.h" +#include "MPU6050.h" + +// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation +// is used in I2Cdev.h +#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE + #include "Wire.h" +#endif + +// class default I2C address is 0x68 +// specific I2C addresses may be passed as a parameter here +// AD0 low = 0x68 (default for InvenSense evaluation board) +// AD0 high = 0x69 +MPU6050 accelgyro; +//MPU6050 accelgyro(0x69); // <-- use for AD0 high + + +const char LBRACKET = '['; +const char RBRACKET = ']'; +const char COMMA = ','; +const char BLANK = ' '; +const char PERIOD = '.'; + +const int iAx = 0; +const int iAy = 1; +const int iAz = 2; +const int iGx = 3; +const int iGy = 4; +const int iGz = 5; + +const int usDelay = 3150; // empirical, to hold sampling to 200 Hz +const int NFast = 1000; // the bigger, the better (but slower) +const int NSlow = 10000; // .. +const int LinesBetweenHeaders = 5; + int LowValue[6]; + int HighValue[6]; + int Smoothed[6]; + int LowOffset[6]; + int HighOffset[6]; + int Target[6]; + int LinesOut; + int N; + +void ForceHeader() + { LinesOut = 99; } + +void GetSmoothed() + { int RawValue[6]; + int i; + long Sums[6]; + for (i = iAx; i <= iGz; i++) + { Sums[i] = 0; } +// unsigned long Start = micros(); + + for (i = 1; i <= N; i++) + { // get sums + accelgyro.getMotion6(&RawValue[iAx], &RawValue[iAy], &RawValue[iAz], + &RawValue[iGx], &RawValue[iGy], &RawValue[iGz]); + if ((i % 500) == 0) + Serial.print(PERIOD); + delayMicroseconds(usDelay); + for (int j = iAx; j <= iGz; j++) + Sums[j] = Sums[j] + RawValue[j]; + } // get sums +// unsigned long usForN = micros() - Start; +// Serial.print(" reading at "); +// Serial.print(1000000/((usForN+N/2)/N)); +// Serial.println(" Hz"); + for (i = iAx; i <= iGz; i++) + { Smoothed[i] = (Sums[i] + N/2) / N ; } + } // GetSmoothed + +void Initialize() + { + // join I2C bus (I2Cdev library doesn't do this automatically) + #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE + Wire.begin(); + #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE + Fastwire::setup(400, true); + #endif + + Serial.begin(9600); + + // initialize device + Serial.println("Initializing I2C devices..."); + accelgyro.initialize(); + + // verify connection + Serial.println("Testing device connections..."); + Serial.println(accelgyro.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed"); + } // Initialize + +void SetOffsets(int TheOffsets[6]) + { accelgyro.setXAccelOffset(TheOffsets [iAx]); + accelgyro.setYAccelOffset(TheOffsets [iAy]); + accelgyro.setZAccelOffset(TheOffsets [iAz]); + accelgyro.setXGyroOffset (TheOffsets [iGx]); + accelgyro.setYGyroOffset (TheOffsets [iGy]); + accelgyro.setZGyroOffset (TheOffsets [iGz]); + } // SetOffsets + +void ShowProgress() + { if (LinesOut >= LinesBetweenHeaders) + { // show header + Serial.println("\tXAccel\t\t\tYAccel\t\t\t\tZAccel\t\t\tXGyro\t\t\tYGyro\t\t\tZGyro"); + LinesOut = 0; + } // show header + Serial.print(BLANK); + for (int i = iAx; i <= iGz; i++) + { Serial.print(LBRACKET); + Serial.print(LowOffset[i]), + Serial.print(COMMA); + Serial.print(HighOffset[i]); + Serial.print("] --> ["); + Serial.print(LowValue[i]); + Serial.print(COMMA); + Serial.print(HighValue[i]); + if (i == iGz) + { Serial.println(RBRACKET); } + else + { Serial.print("]\t"); } + } + LinesOut++; + } // ShowProgress + +void PullBracketsIn() + { boolean AllBracketsNarrow; + boolean StillWorking; + int NewOffset[6]; + + Serial.println("\nclosing in:"); + AllBracketsNarrow = false; + ForceHeader(); + StillWorking = true; + while (StillWorking) + { StillWorking = false; + if (AllBracketsNarrow && (N == NFast)) + { SetAveraging(NSlow); } + else + { AllBracketsNarrow = true; }// tentative + for (int i = iAx; i <= iGz; i++) + { if (HighOffset[i] <= (LowOffset[i]+1)) + { NewOffset[i] = LowOffset[i]; } + else + { // binary search + StillWorking = true; + NewOffset[i] = (LowOffset[i] + HighOffset[i]) / 2; + if (HighOffset[i] > (LowOffset[i] + 10)) + { AllBracketsNarrow = false; } + } // binary search + } + SetOffsets(NewOffset); + GetSmoothed(); + for (int i = iAx; i <= iGz; i++) + { // closing in + if (Smoothed[i] > Target[i]) + { // use lower half + HighOffset[i] = NewOffset[i]; + HighValue[i] = Smoothed[i]; + } // use lower half + else + { // use upper half + LowOffset[i] = NewOffset[i]; + LowValue[i] = Smoothed[i]; + } // use upper half + } // closing in + ShowProgress(); + } // still working + + } // PullBracketsIn + +void PullBracketsOut() + { boolean Done = false; + int NextLowOffset[6]; + int NextHighOffset[6]; + + Serial.println("expanding:"); + ForceHeader(); + + while (!Done) + { Done = true; + SetOffsets(LowOffset); + GetSmoothed(); + for (int i = iAx; i <= iGz; i++) + { // got low values + LowValue[i] = Smoothed[i]; + if (LowValue[i] >= Target[i]) + { Done = false; + NextLowOffset[i] = LowOffset[i] - 1000; + } + else + { NextLowOffset[i] = LowOffset[i]; } + } // got low values + + SetOffsets(HighOffset); + GetSmoothed(); + for (int i = iAx; i <= iGz; i++) + { // got high values + HighValue[i] = Smoothed[i]; + if (HighValue[i] <= Target[i]) + { Done = false; + NextHighOffset[i] = HighOffset[i] + 1000; + } + else + { NextHighOffset[i] = HighOffset[i]; } + } // got high values + ShowProgress(); + for (int i = iAx; i <= iGz; i++) + { LowOffset[i] = NextLowOffset[i]; // had to wait until ShowProgress done + HighOffset[i] = NextHighOffset[i]; // .. + } + } // keep going + } // PullBracketsOut + +void SetAveraging(int NewN) + { N = NewN; + Serial.print("averaging "); + Serial.print(N); + Serial.println(" readings each time"); + } // SetAveraging + +void setup() + { Initialize(); + for (int i = iAx; i <= iGz; i++) + { // set targets and initial guesses + Target[i] = 0; // must fix for ZAccel + HighOffset[i] = 0; + LowOffset[i] = 0; + } // set targets and initial guesses + Target[iAz] = 16384; + SetAveraging(NFast); + + PullBracketsOut(); + PullBracketsIn(); + + Serial.println("-------------- done --------------"); + } // setup + +void loop() + { } // loop From 2b9600cd005cb7c2677ef432137bb2adbf4c862d Mon Sep 17 00:00:00 2001 From: Martin Zenzes Date: Wed, 8 Feb 2017 17:32:55 +0100 Subject: [PATCH 158/335] fix bug(?) in postfix-operation of "processed" pointer *p++ is the same as *(p++) gcc6 warns about this: warning: value computed is not used Signed-off-by: Martin Zenzes --- Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h | 2 +- Arduino/MPU9150/MPU9150_9Axis_MotionApps41.h | 2 +- MSP430/MPU6050/MPU6050_6Axis_MotionApps20.h | 2 +- MSP430/MPU6050/MPU6050_9Axis_MotionApps41.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h b/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h index 016d0b0d..93176e78 100644 --- a/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h +++ b/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h @@ -831,7 +831,7 @@ uint8_t MPU6050::dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *proces if ((status = dmpProcessFIFOPacket(buf)) > 0) return status; // increment external process count variable, if supplied - if (processed != 0) *processed++; + if (processed != 0) (*processed)++; } return 0; } diff --git a/Arduino/MPU9150/MPU9150_9Axis_MotionApps41.h b/Arduino/MPU9150/MPU9150_9Axis_MotionApps41.h index 21b44ed3..9ea4dcfd 100644 --- a/Arduino/MPU9150/MPU9150_9Axis_MotionApps41.h +++ b/Arduino/MPU9150/MPU9150_9Axis_MotionApps41.h @@ -831,7 +831,7 @@ uint8_t MPU9150::dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *proces if ((status = dmpProcessFIFOPacket(buf)) > 0) return status; // increment external process count variable, if supplied - if (processed != 0) *processed++; + if (processed != 0) (*processed)++; } return 0; } diff --git a/MSP430/MPU6050/MPU6050_6Axis_MotionApps20.h b/MSP430/MPU6050/MPU6050_6Axis_MotionApps20.h index 6a8afe27..879623ad 100644 --- a/MSP430/MPU6050/MPU6050_6Axis_MotionApps20.h +++ b/MSP430/MPU6050/MPU6050_6Axis_MotionApps20.h @@ -676,7 +676,7 @@ uint8_t MPU6050::dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *proces if ((status = dmpProcessFIFOPacket(buf)) > 0) return status; // increment external process count variable, if supplied - if (processed != 0) *processed++; + if (processed != 0) (*processed)++; } return 0; } diff --git a/MSP430/MPU6050/MPU6050_9Axis_MotionApps41.h b/MSP430/MPU6050/MPU6050_9Axis_MotionApps41.h index aa04e1ba..c5cd2ae6 100644 --- a/MSP430/MPU6050/MPU6050_9Axis_MotionApps41.h +++ b/MSP430/MPU6050/MPU6050_9Axis_MotionApps41.h @@ -787,7 +787,7 @@ uint8_t MPU6050::dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *proces if ((status = dmpProcessFIFOPacket(buf)) > 0) return status; // increment external process count variable, if supplied - if (processed != 0) *processed++; + if (processed != 0) (*processed)++; } return 0; } From a06bf1b014798a34c5fe5b017d16c265dc7faf38 Mon Sep 17 00:00:00 2001 From: Mateusz Juszczyk Date: Thu, 16 Feb 2017 22:55:15 +0100 Subject: [PATCH 159/335] Fixed wrong type of variable There was a wrong type of variable RawValue and it didn't compile. --- Arduino/MPU6050/examples/IMU_Zero/IMU_Zero.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Arduino/MPU6050/examples/IMU_Zero/IMU_Zero.ino b/Arduino/MPU6050/examples/IMU_Zero/IMU_Zero.ino index bd72c4cb..2a68983b 100644 --- a/Arduino/MPU6050/examples/IMU_Zero/IMU_Zero.ino +++ b/Arduino/MPU6050/examples/IMU_Zero/IMU_Zero.ino @@ -122,7 +122,7 @@ void ForceHeader() { LinesOut = 99; } void GetSmoothed() - { int RawValue[6]; + { int16_t RawValue[6]; int i; long Sums[6]; for (i = iAx; i <= iGz; i++) From ecb4fbc83de0e96f7b941d77b03fbb6c5aa06365 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=88=B4=E5=AE=8F=E5=91=A8?= Date: Sun, 19 Feb 2017 14:29:40 +0800 Subject: [PATCH 160/335] init commit --- .gitignore | 1 + dsPIC30F/I2Cdev/I2Cdev.c | 421 +++ dsPIC30F/I2Cdev/I2Cdev.h | 65 + dsPIC30F/I2Cdev/I2CdevdsPic30F.X/Makefile | 113 + .../nbproject/Makefile-default.mk | 155 + .../nbproject/Makefile-genesis.properties | 9 + .../nbproject/Makefile-impl.mk | 69 + .../nbproject/Makefile-local-default.mk | 36 + .../nbproject/Makefile-variables.mk | 13 + .../nbproject/Package-default.bash | 73 + .../nbproject/configurations.xml | 162 + .../I2CdevdsPic30F.X/nbproject/project.xml | 17 + .../MPU6050/Examples/MPU6050_raw.X/Makefile | 113 + .../MPU6050/Examples/MPU6050_raw.X/funclist | 37 + dsPIC30F/MPU6050/Examples/MPU6050_raw.X/l.obj | Bin 0 -> 24233 bytes .../MPU6050/Examples/MPU6050_raw.X/main.c | 137 + .../nbproject/Makefile-default.mk | 172 + .../nbproject/Makefile-genesis.properties | 8 + .../MPU6050_raw.X/nbproject/Makefile-impl.mk | 69 + .../nbproject/Makefile-local-default.mk | 37 + .../nbproject/Makefile-variables.mk | 13 + .../nbproject/Package-default.bash | 73 + .../nbproject/configurations.xml | 173 + .../nbproject/project.properties | 0 .../MPU6050_raw.X/nbproject/project.xml | 16 + dsPIC30F/MPU6050/MPU6050.c | 3141 +++++++++++++++++ dsPIC30F/MPU6050/MPU6050.h | 786 +++++ dsPIC30F/README.md | 14 + 28 files changed, 5923 insertions(+) create mode 100644 dsPIC30F/I2Cdev/I2Cdev.c create mode 100644 dsPIC30F/I2Cdev/I2Cdev.h create mode 100644 dsPIC30F/I2Cdev/I2CdevdsPic30F.X/Makefile create mode 100644 dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-default.mk create mode 100644 dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-genesis.properties create mode 100644 dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-impl.mk create mode 100644 dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-local-default.mk create mode 100644 dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-variables.mk create mode 100644 dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Package-default.bash create mode 100644 dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/configurations.xml create mode 100644 dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/project.xml create mode 100644 dsPIC30F/MPU6050/Examples/MPU6050_raw.X/Makefile create mode 100644 dsPIC30F/MPU6050/Examples/MPU6050_raw.X/funclist create mode 100644 dsPIC30F/MPU6050/Examples/MPU6050_raw.X/l.obj create mode 100644 dsPIC30F/MPU6050/Examples/MPU6050_raw.X/main.c create mode 100644 dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-default.mk create mode 100644 dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-genesis.properties create mode 100644 dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-impl.mk create mode 100644 dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-local-default.mk create mode 100644 dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-variables.mk create mode 100644 dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/Package-default.bash create mode 100644 dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/configurations.xml create mode 100644 dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/project.properties create mode 100644 dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/project.xml create mode 100644 dsPIC30F/MPU6050/MPU6050.c create mode 100644 dsPIC30F/MPU6050/MPU6050.h create mode 100644 dsPIC30F/README.md diff --git a/.gitignore b/.gitignore index 66a40e48..3a04da47 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ PIC18/MPU6050/Examples/MPU6050_raw.X/dist/ PIC18/MPU6050/Examples/MPU6050_raw.X/nbproject/private/ PIC18/MPU6050/Examples/MPU6050_raw.X/build/ *~ +/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/private/ \ No newline at end of file diff --git a/dsPIC30F/I2Cdev/I2Cdev.c b/dsPIC30F/I2Cdev/I2Cdev.c new file mode 100644 index 00000000..d8082e33 --- /dev/null +++ b/dsPIC30F/I2Cdev/I2Cdev.c @@ -0,0 +1,421 @@ +// I2Cdev library collection - Main I2C device class +// Abstracts bit and byte I2C R/W functions into a convenient class +// 6/9/2012 by Jeff Rowberg +// 11/28/2014 by Marton Sebok +// +// Changelog: +// 2014-11-28 - ported to PIC18 peripheral library from Arduino code + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2013 Jeff Rowberg +Copyright (c) 2014 Marton Sebok + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#include "I2Cdev.h" + +/** Read multiple bytes from an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr First register regAddr to read from + * @param length Number of bytes to read + * @param data Buffer to store read data in + * @return Number of bytes read (-1 indicates failure) + */ +int8_t I2Cdev_readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data) { + int8_t count = 0; + + // S + IdleI2C(); + StartI2C(); + + // Device write address + IdleI2C(); + WriteI2C(devAddr << 1 | 0x00); + + // Register address + IdleI2C(); + WriteI2C(regAddr); + + // R + IdleI2C(); + RestartI2C(); + + // Device read address + IdleI2C(); + WriteI2C(devAddr << 1 | 0x01); + + for (count = 0; count < length; count++) { + // Data byte + IdleI2C(); + data[count] = ReadI2C(); + + if (count == length - 1) { + // NACK + IdleI2C(); + NotAckI2C(); + } else { + // ACK + IdleI2C(); + AckI2C(); + } + } + + // P + IdleI2C(); + StopI2C(); + + return count; +} + +/** Read single byte from an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param data Container for byte value read from device + * @return Status of read operation (true = success) + */ +int8_t I2Cdev_readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data) { + return I2Cdev_readBytes(devAddr, regAddr, 1, data); +} + +/** Read multiple words from a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr First register regAddr to read from + * @param length Number of words to read + * @param data Buffer to store read data in + * @return Number of words read (-1 indicates failure) + */ +int8_t I2Cdev_readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data) { + int8_t count = 0; + + // S + IdleI2C(); + StartI2C(); + + // Device write address + IdleI2C(); + WriteI2C(devAddr << 1 | 0x00); + + // Register address + IdleI2C(); + WriteI2C(regAddr); + + // R + IdleI2C(); + RestartI2C(); + + // Device read address + IdleI2C(); + WriteI2C(devAddr << 1 | 0x01); + + for (count = 0; count < length; count++) { + // First byte is bits 15-8 (MSb=15) + IdleI2C(); + data[count] = ReadI2C() << 8; + + // NACK + IdleI2C(); + NotAckI2C(); + + // Second byte is bits 7-0 (LSb=0) + IdleI2C(); + data[count] |= ReadI2C(); + + if (count == length - 1) { + // NACK + IdleI2C(); + NotAckI2C(); + } else { + // ACK + IdleI2C(); + AckI2C(); + } + } + + // P + IdleI2C(); + StopI2C(); + + return count; +} + +/** Read single word from a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param data Container for word value read from device + * @return Status of read operation (true = success) + */ +int8_t I2Cdev_readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data) { + return I2Cdev_readWords(devAddr, regAddr, 1, data); +} + +/** Read a single bit from an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param bitNum Bit position to read (0-7) + * @param data Container for single bit value + * @return Status of read operation (true = success) + */ +int8_t I2Cdev_readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data) { + uint8_t b; + uint8_t count = I2Cdev_readByte(devAddr, regAddr, &b); + *data = b & (1 << bitNum); + return count; +} + +/** Read a single bit from a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param bitNum Bit position to read (0-15) + * @param data Container for single bit value + * @return Status of read operation (true = success) + */ +int8_t I2Cdev_readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data) { + uint16_t b; + uint8_t count = I2Cdev_readWord(devAddr, regAddr, &b); + *data = b & (1 << bitNum); + return count; +} + +/** Read multiple bits from an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param bitStart First bit position to read (0-7) + * @param length Number of bits to read (not more than 8) + * @param data Container for right-aligned value (i.e. '101' read from any bitStart position will equal 0x05) + * @return Status of read operation (true = success) + */ +int8_t I2Cdev_readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data) { + // 01101001 read byte + // 76543210 bit numbers + // xxx args: bitStart=4, length=3 + // 010 masked + // -> 010 shifted + uint8_t count, b; + if ((count = I2Cdev_readByte(devAddr, regAddr, &b)) != 0) { + uint8_t mask = ((1 << length) - 1) << (bitStart - length + 1); + b &= mask; + b >>= (bitStart - length + 1); + *data = b; + } + return count; +} + +/** Read multiple bits from a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param bitStart First bit position to read (0-15) + * @param length Number of bits to read (not more than 16) + * @param data Container for right-aligned value (i.e. '101' read from any bitStart position will equal 0x05) + * @return Status of read operation (1 = success, 0 = failure, -1 = timeout) + */ +int8_t I2Cdev_readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t *data) { + // 1101011001101001 read byte + // fedcba9876543210 bit numbers + // xxx args: bitStart=12, length=3 + // 010 masked + // -> 010 shifted + uint8_t count; + uint16_t w; + if ((count = I2Cdev_readWord(devAddr, regAddr, &w)) != 0) { + uint16_t mask = ((1 << length) - 1) << (bitStart - length + 1); + w &= mask; + w >>= (bitStart - length + 1); + *data = w; + } + return count; +} + +/** Write multiple bytes to an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr First register address to write to + * @param length Number of bytes to write + * @param data Buffer to copy new data from + * @return Status of operation (true = success) + */ +bool I2Cdev_writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t* data) { + // S + IdleI2C(); + StartI2C(); + + // Device write address + IdleI2C(); + WriteI2C(devAddr << 1 | 0x00); + + // Register address + IdleI2C(); + WriteI2C(regAddr); + + for (uint8_t i = 0; i < length; i++) { + // Data byte + IdleI2C(); + WriteI2C(data[i]); + } + + // P + IdleI2C(); + StopI2C(); + + return true; +} + +/** Write single byte to an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register address to write to + * @param data New byte value to write + * @return Status of operation (true = success) + */ +bool I2Cdev_writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data) { + return I2Cdev_writeBytes(devAddr, regAddr, 1, &data); +} + +/** Write multiple words to a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr First register address to write to + * @param length Number of words to write + * @param data Buffer to copy new data from + * @return Status of operation (true = success) + */ +bool I2Cdev_writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t* data) { + // S + IdleI2C(); + StartI2C(); + + // Device write address + IdleI2C(); + WriteI2C(devAddr << 1 | 0x00); + + // Register address + IdleI2C(); + WriteI2C(regAddr); + + for (uint8_t i = 0; i < length; i++) { + // Send MSB + IdleI2C(); + WriteI2C(data[i] >> 8); + + // Send LSB + IdleI2C(); + WriteI2C(data[i] & 0xFF); + } + + // P + IdleI2C(); + StopI2C(); + + return true; +} + +/** Write single word to a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register address to write to + * @param data New word value to write + * @return Status of operation (true = success) + */ +bool I2Cdev_writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data) { + return I2Cdev_writeWords(devAddr, regAddr, 1, &data); +} + +/** write a single bit in an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to write to + * @param bitNum Bit position to write (0-7) + * @param value New bit value to write + * @return Status of operation (true = success) + */ +bool I2Cdev_writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t data) { + uint8_t b; + I2Cdev_readByte(devAddr, regAddr, &b); + b = (data != 0) ? (b | (1 << bitNum)) : (b & ~(1 << bitNum)); + return I2Cdev_writeByte(devAddr, regAddr, b); +} + +/** write a single bit in a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to write to + * @param bitNum Bit position to write (0-15) + * @param value New bit value to write + * @return Status of operation (true = success) + */ +bool I2Cdev_writeBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t data) { + uint16_t w; + I2Cdev_readWord(devAddr, regAddr, &w); + w = (data != 0) ? (w | (1 << bitNum)) : (w & ~(1 << bitNum)); + return I2Cdev_writeWord(devAddr, regAddr, w); +} + +/** Write multiple bits in an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to write to + * @param bitStart First bit position to write (0-7) + * @param length Number of bits to write (not more than 8) + * @param data Right-aligned value to write + * @return Status of operation (true = success) + */ +bool I2Cdev_writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data) { + // 010 value to write + // 76543210 bit numbers + // xxx args: bitStart=4, length=3 + // 00011100 mask byte + // 10101111 original value (sample) + // 10100011 original & ~mask + // 10101011 masked | value + uint8_t b; + if (I2Cdev_readByte(devAddr, regAddr, &b) != 0) { + uint8_t mask = ((1 << length) - 1) << (bitStart - length + 1); + data <<= (bitStart - length + 1); // shift data into correct position + data &= mask; // zero all non-important bits in data + b &= ~(mask); // zero all important bits in existing byte + b |= data; // combine data with existing byte + return I2Cdev_writeByte(devAddr, regAddr, b); + } else { + return false; + } +} + +/** Write multiple bits in a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to write to + * @param bitStart First bit position to write (0-15) + * @param length Number of bits to write (not more than 16) + * @param data Right-aligned value to write + * @return Status of operation (true = success) + */ +bool I2Cdev_writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t data) { + // 010 value to write + // fedcba9876543210 bit numbers + // xxx args: bitStart=12, length=3 + // 0001110000000000 mask word + // 1010111110010110 original value (sample) + // 1010001110010110 original & ~mask + // 1010101110010110 masked | value + uint16_t w; + if (I2Cdev_readWord(devAddr, regAddr, &w) != 0) { + uint16_t mask = ((1 << length) - 1) << (bitStart - length + 1); + data <<= (bitStart - length + 1); // shift data into correct position + data &= mask; // zero all non-important bits in data + w &= ~(mask); // zero all important bits in existing word + w |= data; // combine data with existing word + return I2Cdev_writeWord(devAddr, regAddr, w); + } else { + return false; + } +} diff --git a/dsPIC30F/I2Cdev/I2Cdev.h b/dsPIC30F/I2Cdev/I2Cdev.h new file mode 100644 index 00000000..fbe62b3f --- /dev/null +++ b/dsPIC30F/I2Cdev/I2Cdev.h @@ -0,0 +1,65 @@ +// I2Cdev library collection - Main I2C device class header file +// Abstracts bit and byte I2C R/W functions into a convenient class +// 6/9/2012 by Jeff Rowberg +// 11/28/2014 by Marton Sebok +// +// Changelog: +// 2014-11-28 - ported to PIC18 peripheral library from Arduino code + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2013 Jeff Rowberg +Copyright (c) 2014 Marton Sebok +Copyright (c) 2017 Daichou + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#ifndef _I2CDEV_H_ +#define _I2CDEV_H_ + +#ifndef __XC16 + #error Use XC16 for compiling +#endif + +#include +#include +#include +#include + +int8_t I2Cdev_readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data); +int8_t I2Cdev_readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data); +int8_t I2Cdev_readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data); +int8_t I2Cdev_readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t *data); +int8_t I2Cdev_readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data); +int8_t I2Cdev_readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data); +int8_t I2Cdev_readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data); +int8_t I2Cdev_readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data); + +bool I2Cdev_writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t data); +bool I2Cdev_writeBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t data); +bool I2Cdev_writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data); +bool I2Cdev_writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t data); +bool I2Cdev_writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data); +bool I2Cdev_writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data); +bool I2Cdev_writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data); +bool I2Cdev_writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data); + +#endif /* _I2CDEV_H_ */ diff --git a/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/Makefile b/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/Makefile new file mode 100644 index 00000000..fca8e2cc --- /dev/null +++ b/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/Makefile @@ -0,0 +1,113 @@ +# +# There exist several targets which are by default empty and which can be +# used for execution of your targets. These targets are usually executed +# before and after some main targets. They are: +# +# .build-pre: called before 'build' target +# .build-post: called after 'build' target +# .clean-pre: called before 'clean' target +# .clean-post: called after 'clean' target +# .clobber-pre: called before 'clobber' target +# .clobber-post: called after 'clobber' target +# .all-pre: called before 'all' target +# .all-post: called after 'all' target +# .help-pre: called before 'help' target +# .help-post: called after 'help' target +# +# Targets beginning with '.' are not intended to be called on their own. +# +# Main targets can be executed directly, and they are: +# +# build build a specific configuration +# clean remove built files from a configuration +# clobber remove all built files +# all build all configurations +# help print help mesage +# +# Targets .build-impl, .clean-impl, .clobber-impl, .all-impl, and +# .help-impl are implemented in nbproject/makefile-impl.mk. +# +# Available make variables: +# +# CND_BASEDIR base directory for relative paths +# CND_DISTDIR default top distribution directory (build artifacts) +# CND_BUILDDIR default top build directory (object files, ...) +# CONF name of current configuration +# CND_ARTIFACT_DIR_${CONF} directory of build artifact (current configuration) +# CND_ARTIFACT_NAME_${CONF} name of build artifact (current configuration) +# CND_ARTIFACT_PATH_${CONF} path to build artifact (current configuration) +# CND_PACKAGE_DIR_${CONF} directory of package (current configuration) +# CND_PACKAGE_NAME_${CONF} name of package (current configuration) +# CND_PACKAGE_PATH_${CONF} path to package (current configuration) +# +# NOCDDL + + +# Environment +MKDIR=mkdir +CP=cp +CCADMIN=CCadmin +RANLIB=ranlib + + +# build +build: .build-post + +.build-pre: +# Add your pre 'build' code here... + +.build-post: .build-impl +# Add your post 'build' code here... + + +# clean +clean: .clean-post + +.clean-pre: +# Add your pre 'clean' code here... +# WARNING: the IDE does not call this target since it takes a long time to +# simply run make. Instead, the IDE removes the configuration directories +# under build and dist directly without calling make. +# This target is left here so people can do a clean when running a clean +# outside the IDE. + +.clean-post: .clean-impl +# Add your post 'clean' code here... + + +# clobber +clobber: .clobber-post + +.clobber-pre: +# Add your pre 'clobber' code here... + +.clobber-post: .clobber-impl +# Add your post 'clobber' code here... + + +# all +all: .all-post + +.all-pre: +# Add your pre 'all' code here... + +.all-post: .all-impl +# Add your post 'all' code here... + + +# help +help: .help-post + +.help-pre: +# Add your pre 'help' code here... + +.help-post: .help-impl +# Add your post 'help' code here... + + + +# include project implementation makefile +include nbproject/Makefile-impl.mk + +# include project make variables +include nbproject/Makefile-variables.mk diff --git a/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-default.mk b/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-default.mk new file mode 100644 index 00000000..a82c29ac --- /dev/null +++ b/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-default.mk @@ -0,0 +1,155 @@ +# +# Generated Makefile - do not edit! +# +# Edit the Makefile in the project folder instead (../Makefile). Each target +# has a -pre and a -post target defined where you can add customized code. +# +# This makefile implements configuration specific macros and targets. + + +# Include project Makefile +ifeq "${IGNORE_LOCAL}" "TRUE" +# do not include local makefile. User is passing all local related variables already +else +include Makefile +# Include makefile containing local settings +ifeq "$(wildcard nbproject/Makefile-local-default.mk)" "nbproject/Makefile-local-default.mk" +include nbproject/Makefile-local-default.mk +endif +endif + +# Environment +MKDIR=mkdir -p +RM=rm -f +MV=mv +CP=cp + +# Macros +CND_CONF=default +ifeq ($(TYPE_IMAGE), DEBUG_RUN) +IMAGE_TYPE=debug +OUTPUT_SUFFIX=a +DEBUGGABLE_SUFFIX=a +FINAL_IMAGE=dist/${CND_CONF}/${IMAGE_TYPE}/I2CdevdsPic30F.X.${OUTPUT_SUFFIX} +else +IMAGE_TYPE=production +OUTPUT_SUFFIX=a +DEBUGGABLE_SUFFIX=a +FINAL_IMAGE=dist/${CND_CONF}/${IMAGE_TYPE}/I2CdevdsPic30F.X.${OUTPUT_SUFFIX} +endif + +ifeq ($(COMPARE_BUILD), true) +COMPARISON_BUILD=-mafrlcsj +else +COMPARISON_BUILD= +endif + +# Object Directory +OBJECTDIR=build/${CND_CONF}/${IMAGE_TYPE} + +# Distribution Directory +DISTDIR=dist/${CND_CONF}/${IMAGE_TYPE} + +# Source Files Quoted if spaced +SOURCEFILES_QUOTED_IF_SPACED=/home/tommycc/work/i2cdevlib/dsPIC30F/I2Cdev/I2Cdev.c + +# Object Files Quoted if spaced +OBJECTFILES_QUOTED_IF_SPACED=${OBJECTDIR}/_ext/1922997195/I2Cdev.o +POSSIBLE_DEPFILES=${OBJECTDIR}/_ext/1922997195/I2Cdev.o.d + +# Object Files +OBJECTFILES=${OBJECTDIR}/_ext/1922997195/I2Cdev.o + +# Source Files +SOURCEFILES=/home/tommycc/work/i2cdevlib/dsPIC30F/I2Cdev/I2Cdev.c + + +CFLAGS= +ASFLAGS= +LDLIBSOPTIONS= + +############# Tool locations ########################################## +# If you copy a project from one host to another, the path where the # +# compiler is installed may be different. # +# If you open this project with MPLAB X in the new host, this # +# makefile will be regenerated and the paths will be corrected. # +####################################################################### +# fixDeps replaces a bunch of sed/cat/printf statements that slow down the build +FIXDEPS=fixDeps + +.build-conf: ${BUILD_SUBPROJECTS} +ifneq ($(INFORMATION_MESSAGE), ) + @echo $(INFORMATION_MESSAGE) +endif + ${MAKE} -f nbproject/Makefile-default.mk dist/${CND_CONF}/${IMAGE_TYPE}/I2CdevdsPic30F.X.${OUTPUT_SUFFIX} + +MP_PROCESSOR_OPTION=30F4013 +MP_LINKER_FILE_OPTION=,--script=p30F4013.gld +# ------------------------------------------------------------------------------------ +# Rules for buildStep: compile +ifeq ($(TYPE_IMAGE), DEBUG_RUN) +${OBJECTDIR}/_ext/1922997195/I2Cdev.o: /home/tommycc/work/i2cdevlib/dsPIC30F/I2Cdev/I2Cdev.c nbproject/Makefile-${CND_CONF}.mk + @${MKDIR} "${OBJECTDIR}/_ext/1922997195" + @${RM} ${OBJECTDIR}/_ext/1922997195/I2Cdev.o.d + @${RM} ${OBJECTDIR}/_ext/1922997195/I2Cdev.o + ${MP_CC} $(MP_EXTRA_CC_PRE) /home/tommycc/work/i2cdevlib/dsPIC30F/I2Cdev/I2Cdev.c -o ${OBJECTDIR}/_ext/1922997195/I2Cdev.o -c -mcpu=$(MP_PROCESSOR_OPTION) -MMD -MF "${OBJECTDIR}/_ext/1922997195/I2Cdev.o.d" -g -D__DEBUG -D__MPLAB_DEBUGGER_PK3=1 -omf=elf -DXPRJ_default=$(CND_CONF) -legacy-libc $(COMPARISON_BUILD) -O0 -msmart-io=1 -Wall -msfr-warn=off + @${FIXDEPS} "${OBJECTDIR}/_ext/1922997195/I2Cdev.o.d" $(SILENT) -rsi ${MP_CC_DIR}../ + +else +${OBJECTDIR}/_ext/1922997195/I2Cdev.o: /home/tommycc/work/i2cdevlib/dsPIC30F/I2Cdev/I2Cdev.c nbproject/Makefile-${CND_CONF}.mk + @${MKDIR} "${OBJECTDIR}/_ext/1922997195" + @${RM} ${OBJECTDIR}/_ext/1922997195/I2Cdev.o.d + @${RM} ${OBJECTDIR}/_ext/1922997195/I2Cdev.o + ${MP_CC} $(MP_EXTRA_CC_PRE) /home/tommycc/work/i2cdevlib/dsPIC30F/I2Cdev/I2Cdev.c -o ${OBJECTDIR}/_ext/1922997195/I2Cdev.o -c -mcpu=$(MP_PROCESSOR_OPTION) -MMD -MF "${OBJECTDIR}/_ext/1922997195/I2Cdev.o.d" -g -omf=elf -DXPRJ_default=$(CND_CONF) -legacy-libc $(COMPARISON_BUILD) -O0 -msmart-io=1 -Wall -msfr-warn=off + @${FIXDEPS} "${OBJECTDIR}/_ext/1922997195/I2Cdev.o.d" $(SILENT) -rsi ${MP_CC_DIR}../ + +endif + +# ------------------------------------------------------------------------------------ +# Rules for buildStep: assemble +ifeq ($(TYPE_IMAGE), DEBUG_RUN) +else +endif + +# ------------------------------------------------------------------------------------ +# Rules for buildStep: assemblePreproc +ifeq ($(TYPE_IMAGE), DEBUG_RUN) +else +endif + +# ------------------------------------------------------------------------------------ +# Rules for buildStep: archive +ifeq ($(TYPE_IMAGE), DEBUG_RUN) +dist/${CND_CONF}/${IMAGE_TYPE}/I2CdevdsPic30F.X.${OUTPUT_SUFFIX}: ${OBJECTFILES} nbproject/Makefile-${CND_CONF}.mk + @${MKDIR} dist/${CND_CONF}/${IMAGE_TYPE} + @${RM} dist/${CND_CONF}/${IMAGE_TYPE}/I2CdevdsPic30F.X.${OUTPUT_SUFFIX} + ${MP_AR} $(MP_EXTRA_AR_PRE) -omf=elf -r dist/${CND_CONF}/${IMAGE_TYPE}/I2CdevdsPic30F.X.${OUTPUT_SUFFIX} ${OBJECTFILES_QUOTED_IF_SPACED} + +else +dist/${CND_CONF}/${IMAGE_TYPE}/I2CdevdsPic30F.X.${OUTPUT_SUFFIX}: ${OBJECTFILES} nbproject/Makefile-${CND_CONF}.mk + @${MKDIR} dist/${CND_CONF}/${IMAGE_TYPE} + @${RM} dist/${CND_CONF}/${IMAGE_TYPE}/I2CdevdsPic30F.X.${OUTPUT_SUFFIX} + ${MP_AR} $(MP_EXTRA_AR_PRE) -omf=elf -r dist/${CND_CONF}/${IMAGE_TYPE}/I2CdevdsPic30F.X.${OUTPUT_SUFFIX} ${OBJECTFILES_QUOTED_IF_SPACED} + +endif + + +# Subprojects +.build-subprojects: + + +# Subprojects +.clean-subprojects: + +# Clean Targets +.clean-conf: ${CLEAN_SUBPROJECTS} + ${RM} -r build/default + ${RM} -r dist/default + +# Enable dependency checking +.dep.inc: .depcheck-impl + +DEPFILES=$(shell "${PATH_TO_IDE_BIN}"mplabwildcard ${POSSIBLE_DEPFILES}) +ifneq (${DEPFILES},) +include ${DEPFILES} +endif diff --git a/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-genesis.properties b/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-genesis.properties new file mode 100644 index 00000000..ccfb0f58 --- /dev/null +++ b/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-genesis.properties @@ -0,0 +1,9 @@ +# +#Sun Feb 19 14:16:06 CST 2017 +default.com-microchip-mplab-nbide-toolchainXC16-XC16LanguageToolchain.md5=ebaa75370c1463d650408e4144ba15de +default.languagetoolchain.dir=/opt/microchip/xc16/v1.30/bin +configurations-xml=e23099a44127c530cab293bfc5554ec5 +com-microchip-mplab-nbide-embedded-makeproject-MakeProject.md5=8b140fb87818dc96ed4f726b716b40e9 +default.languagetoolchain.version=1.30 +host.platform=linux +conf.ids=default diff --git a/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-impl.mk b/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-impl.mk new file mode 100644 index 00000000..b4e2d4c4 --- /dev/null +++ b/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-impl.mk @@ -0,0 +1,69 @@ +# +# Generated Makefile - do not edit! +# +# Edit the Makefile in the project folder instead (../Makefile). Each target +# has a pre- and a post- target defined where you can add customization code. +# +# This makefile implements macros and targets common to all configurations. +# +# NOCDDL + + +# Building and Cleaning subprojects are done by default, but can be controlled with the SUB +# macro. If SUB=no, subprojects will not be built or cleaned. The following macro +# statements set BUILD_SUB-CONF and CLEAN_SUB-CONF to .build-reqprojects-conf +# and .clean-reqprojects-conf unless SUB has the value 'no' +SUB_no=NO +SUBPROJECTS=${SUB_${SUB}} +BUILD_SUBPROJECTS_=.build-subprojects +BUILD_SUBPROJECTS_NO= +BUILD_SUBPROJECTS=${BUILD_SUBPROJECTS_${SUBPROJECTS}} +CLEAN_SUBPROJECTS_=.clean-subprojects +CLEAN_SUBPROJECTS_NO= +CLEAN_SUBPROJECTS=${CLEAN_SUBPROJECTS_${SUBPROJECTS}} + + +# Project Name +PROJECTNAME=I2CdevdsPic30F.X + +# Active Configuration +DEFAULTCONF=default +CONF=${DEFAULTCONF} + +# All Configurations +ALLCONFS=default + + +# build +.build-impl: .build-pre + ${MAKE} -f nbproject/Makefile-${CONF}.mk SUBPROJECTS=${SUBPROJECTS} .build-conf + + +# clean +.clean-impl: .clean-pre + ${MAKE} -f nbproject/Makefile-${CONF}.mk SUBPROJECTS=${SUBPROJECTS} .clean-conf + +# clobber +.clobber-impl: .clobber-pre .depcheck-impl + ${MAKE} SUBPROJECTS=${SUBPROJECTS} CONF=default clean + + + +# all +.all-impl: .all-pre .depcheck-impl + ${MAKE} SUBPROJECTS=${SUBPROJECTS} CONF=default build + + + +# dependency checking support +.depcheck-impl: +# @echo "# This code depends on make tool being used" >.dep.inc +# @if [ -n "${MAKE_VERSION}" ]; then \ +# echo "DEPFILES=\$$(wildcard \$$(addsuffix .d, \$${OBJECTFILES}))" >>.dep.inc; \ +# echo "ifneq (\$${DEPFILES},)" >>.dep.inc; \ +# echo "include \$${DEPFILES}" >>.dep.inc; \ +# echo "endif" >>.dep.inc; \ +# else \ +# echo ".KEEP_STATE:" >>.dep.inc; \ +# echo ".KEEP_STATE_FILE:.make.state.\$${CONF}" >>.dep.inc; \ +# fi diff --git a/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-local-default.mk b/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-local-default.mk new file mode 100644 index 00000000..38870624 --- /dev/null +++ b/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-local-default.mk @@ -0,0 +1,36 @@ +# +# Generated Makefile - do not edit! +# +# +# This file contains information about the location of compilers and other tools. +# If you commmit this file into your revision control server, you will be able to +# to checkout the project and build it from the command line with make. However, +# if more than one person works on the same project, then this file might show +# conflicts since different users are bound to have compilers in different places. +# In that case you might choose to not commit this file and let MPLAB X recreate this file +# for each user. The disadvantage of not commiting this file is that you must run MPLAB X at +# least once so the file gets created and the project can be built. Finally, you can also +# avoid using this file at all if you are only building from the command line with make. +# You can invoke make with the values of the macros: +# $ makeMP_CC="/opt/microchip/mplabc30/v3.30c/bin/pic30-gcc" ... +# +PATH_TO_IDE_BIN=/opt/microchip/mplabx/v3.45/mplab_ide/platform/../mplab_ide/modules/../../bin/ +# Adding MPLAB X bin directory to path. +PATH:=/opt/microchip/mplabx/v3.45/mplab_ide/platform/../mplab_ide/modules/../../bin/:$(PATH) +# Path to java used to run MPLAB X when this makefile was created +MP_JAVA_PATH="/opt/microchip/mplabx/v3.45/sys/java/jre1.8.0_91/bin/" +OS_CURRENT="$(shell uname -s)" +MP_CC="/opt/microchip/xc16/v1.30/bin/xc16-gcc" +# MP_CPPC is not defined +# MP_BC is not defined +MP_AS="/opt/microchip/xc16/v1.30/bin/xc16-as" +MP_LD="/opt/microchip/xc16/v1.30/bin/xc16-ld" +MP_AR="/opt/microchip/xc16/v1.30/bin/xc16-ar" +DEP_GEN=${MP_JAVA_PATH}java -jar "/opt/microchip/mplabx/v3.45/mplab_ide/platform/../mplab_ide/modules/../../bin/extractobjectdependencies.jar" +MP_CC_DIR="/opt/microchip/xc16/v1.30/bin" +# MP_CPPC_DIR is not defined +# MP_BC_DIR is not defined +MP_AS_DIR="/opt/microchip/xc16/v1.30/bin" +MP_LD_DIR="/opt/microchip/xc16/v1.30/bin" +MP_AR_DIR="/opt/microchip/xc16/v1.30/bin" +# MP_BC_DIR is not defined diff --git a/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-variables.mk b/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-variables.mk new file mode 100644 index 00000000..3974a0f0 --- /dev/null +++ b/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-variables.mk @@ -0,0 +1,13 @@ +# +# Generated - do not edit! +# +# NOCDDL +# +CND_BASEDIR=`pwd` +# default configuration +CND_ARTIFACT_DIR_default=dist/default/production +CND_ARTIFACT_NAME_default=I2CdevdsPic30F.X.a +CND_ARTIFACT_PATH_default=dist/default/production/I2CdevdsPic30F.X.a +CND_PACKAGE_DIR_default=${CND_DISTDIR}/default/package +CND_PACKAGE_NAME_default=I2CdevdsPic30F.X.tar +CND_PACKAGE_PATH_default=${CND_DISTDIR}/default/package/I2CdevdsPic30F.X.tar diff --git a/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Package-default.bash b/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Package-default.bash new file mode 100644 index 00000000..86c2f144 --- /dev/null +++ b/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Package-default.bash @@ -0,0 +1,73 @@ +#!/bin/bash -x + +# +# Generated - do not edit! +# + +# Macros +TOP=`pwd` +CND_CONF=default +CND_DISTDIR=dist +TMPDIR=build/${CND_CONF}/${IMAGE_TYPE}/tmp-packaging +TMPDIRNAME=tmp-packaging +OUTPUT_PATH=dist/${CND_CONF}/${IMAGE_TYPE}/I2CdevdsPic30F.X.${OUTPUT_SUFFIX} +OUTPUT_BASENAME=I2CdevdsPic30F.X.${OUTPUT_SUFFIX} +PACKAGE_TOP_DIR=I2CdevdsPic30F.X/ + +# Functions +function checkReturnCode +{ + rc=$? + if [ $rc != 0 ] + then + exit $rc + fi +} +function makeDirectory +# $1 directory path +# $2 permission (optional) +{ + mkdir -p "$1" + checkReturnCode + if [ "$2" != "" ] + then + chmod $2 "$1" + checkReturnCode + fi +} +function copyFileToTmpDir +# $1 from-file path +# $2 to-file path +# $3 permission +{ + cp "$1" "$2" + checkReturnCode + if [ "$3" != "" ] + then + chmod $3 "$2" + checkReturnCode + fi +} + +# Setup +cd "${TOP}" +mkdir -p ${CND_DISTDIR}/${CND_CONF}/package +rm -rf ${TMPDIR} +mkdir -p ${TMPDIR} + +# Copy files and create directories and links +cd "${TOP}" +makeDirectory ${TMPDIR}/I2CdevdsPic30F.X/lib +copyFileToTmpDir "${OUTPUT_PATH}" "${TMPDIR}/${PACKAGE_TOP_DIR}lib/${OUTPUT_BASENAME}" 0644 + + +# Generate tar file +cd "${TOP}" +rm -f ${CND_DISTDIR}/${CND_CONF}/package/I2CdevdsPic30F.X.tar +cd ${TMPDIR} +tar -vcf ../../../../${CND_DISTDIR}/${CND_CONF}/package/I2CdevdsPic30F.X.tar * +checkReturnCode + +# Cleanup +cd "${TOP}" +rm -rf ${TMPDIR} diff --git a/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/configurations.xml b/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/configurations.xml new file mode 100644 index 00000000..506353f5 --- /dev/null +++ b/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/configurations.xml @@ -0,0 +1,162 @@ + + + + + /home/tommycc/work/i2cdevlib/dsPIC30F/I2Cdev/I2Cdev.h + + + + + /home/tommycc/work/i2cdevlib/dsPIC30F/I2Cdev/I2Cdev.c + + + Makefile + + + + /home/tommycc/work/i2cdevlib/dsPIC30F/I2Cdev + + Makefile + + + + localhost + dsPIC30F4013 + + + PICkit3PlatformTool + XC16 + 1.30 + 2 + + + + + + + + + + false + false + + + + + + + false + + false + + false + false + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/project.xml b/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/project.xml new file mode 100644 index 00000000..d3be9e5f --- /dev/null +++ b/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/project.xml @@ -0,0 +1,17 @@ + + + com.microchip.mplab.nbide.embedded.makeproject + + + I2CdevdsPic30F + 231209f4-6ed3-4604-8ec8-3340e931ead8 + 0 + c + + h + + ISO-8859-1 + + + + diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/Makefile b/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/Makefile new file mode 100644 index 00000000..fca8e2cc --- /dev/null +++ b/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/Makefile @@ -0,0 +1,113 @@ +# +# There exist several targets which are by default empty and which can be +# used for execution of your targets. These targets are usually executed +# before and after some main targets. They are: +# +# .build-pre: called before 'build' target +# .build-post: called after 'build' target +# .clean-pre: called before 'clean' target +# .clean-post: called after 'clean' target +# .clobber-pre: called before 'clobber' target +# .clobber-post: called after 'clobber' target +# .all-pre: called before 'all' target +# .all-post: called after 'all' target +# .help-pre: called before 'help' target +# .help-post: called after 'help' target +# +# Targets beginning with '.' are not intended to be called on their own. +# +# Main targets can be executed directly, and they are: +# +# build build a specific configuration +# clean remove built files from a configuration +# clobber remove all built files +# all build all configurations +# help print help mesage +# +# Targets .build-impl, .clean-impl, .clobber-impl, .all-impl, and +# .help-impl are implemented in nbproject/makefile-impl.mk. +# +# Available make variables: +# +# CND_BASEDIR base directory for relative paths +# CND_DISTDIR default top distribution directory (build artifacts) +# CND_BUILDDIR default top build directory (object files, ...) +# CONF name of current configuration +# CND_ARTIFACT_DIR_${CONF} directory of build artifact (current configuration) +# CND_ARTIFACT_NAME_${CONF} name of build artifact (current configuration) +# CND_ARTIFACT_PATH_${CONF} path to build artifact (current configuration) +# CND_PACKAGE_DIR_${CONF} directory of package (current configuration) +# CND_PACKAGE_NAME_${CONF} name of package (current configuration) +# CND_PACKAGE_PATH_${CONF} path to package (current configuration) +# +# NOCDDL + + +# Environment +MKDIR=mkdir +CP=cp +CCADMIN=CCadmin +RANLIB=ranlib + + +# build +build: .build-post + +.build-pre: +# Add your pre 'build' code here... + +.build-post: .build-impl +# Add your post 'build' code here... + + +# clean +clean: .clean-post + +.clean-pre: +# Add your pre 'clean' code here... +# WARNING: the IDE does not call this target since it takes a long time to +# simply run make. Instead, the IDE removes the configuration directories +# under build and dist directly without calling make. +# This target is left here so people can do a clean when running a clean +# outside the IDE. + +.clean-post: .clean-impl +# Add your post 'clean' code here... + + +# clobber +clobber: .clobber-post + +.clobber-pre: +# Add your pre 'clobber' code here... + +.clobber-post: .clobber-impl +# Add your post 'clobber' code here... + + +# all +all: .all-post + +.all-pre: +# Add your pre 'all' code here... + +.all-post: .all-impl +# Add your post 'all' code here... + + +# help +help: .help-post + +.help-pre: +# Add your pre 'help' code here... + +.help-post: .help-impl +# Add your post 'help' code here... + + + +# include project implementation makefile +include nbproject/Makefile-impl.mk + +# include project make variables +include nbproject/Makefile-variables.mk diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/funclist b/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/funclist new file mode 100644 index 00000000..bf32657d --- /dev/null +++ b/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/funclist @@ -0,0 +1,37 @@ +_MPU6050_initialize: CODE, 6334 0 24 +_I2Cdev_writeBytes: CODE, 5202 0 156 +_MPU6050_getDeviceID: CODE, 6310 0 24 +__stringdata: SMALLCONST, 3851 0 193 +_putch: CODE, 6552 0 12 +_MPU6050_getXGyroOffset: CODE, 6188 0 42 +_MPU6050_getYGyroOffset: CODE, 6104 0 42 +_MPU6050_getZGyroOffset: CODE, 6020 0 42 +_dpowers: SMALLCONST, 3841 0 10 +_I2Cdev_readByte: CODE, 6514 0 20 +_I2Cdev_writeBit: CODE, 5474 0 110 +_main: CODE, 4046 0 342 +_I2Cdev_readBits: CODE, 5584 0 108 +_MPU6050_setFullScaleGyroRange: CODE, 6358 0 24 +_MPU6050_setSleepEnabled: CODE, 6474 0 20 +_MPU6050: CODE, 6584 0 8 +_MPU6050_setClockSource: CODE, 6406 0 24 +__initialization: CODE, 6430 0 12 +___lwdiv: CODE, 5884 0 74 +_MPU6050_setFullScaleAccelRange: CODE, 6382 0 24 +_baud1USART: CODE, 6576 0 8 +_Write1USART: CODE, 6534 0 18 +_printf: CODE, 4706 0 294 +___lwmod: CODE, 5958 0 62 +_MPU6050_testConnection: CODE, 6564 0 12 +_ReadI2C1: CODE, 6272 0 38 +_MPU6050_getXAccelOffset: CODE, 6230 0 42 +_MPU6050_getYAccelOffset: CODE, 6146 0 42 +_MPU6050_getZAccelOffset: CODE, 6062 0 42 +_WriteI2C1: CODE, 5692 0 108 +_I2Cdev_writeByte: CODE, 6494 0 20 +_Open1USART: CODE, 5800 0 84 +_I2Cdev_readBytes: CODE, 4388 0 318 +_I2Cdev_writeBits: CODE, 5358 0 116 +_MPU6050_getMotion6: CODE, 5000 0 202 +_OpenI2C1: CODE, 6452 0 22 +Total: 2739 \ No newline at end of file diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/l.obj b/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/l.obj new file mode 100644 index 0000000000000000000000000000000000000000..1734cc8674a5c31b28cd2bf0bf9b45b350e67c21 GIT binary patch literal 24233 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 +// 11/28/2014 by Marton Sebok +// +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// 2014-11-28 - ported to PIC18 peripheral library from Arduino code + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2011 Jeff Rowberg +Copyright (c) 2014 Marton Sebok + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +/* + * The project can be run without modification on Microchip's 8-bit Wireless + * Development Kit. Please set the type of your IC in project properties/Conf/ + * Device and change the code as needed. + */ + +// PLL Prescaler Selection bits (Divide by 2 (8 MHz oscillator input)) +#pragma config PLLDIV = 2 + +// Extended Instruction Set (Disabled) +#pragma config XINST = OFF + +// CPU System Clock Postscaler (CPU system clock divide by 2) +#pragma config CPUDIV = OSC2_PLL2 + +// Oscillator (HS+PLL, USB-HS+PLL) +#pragma config OSC = HSPLL + +#define USE_OR_MASKS +#define _XTAL_FREQ 24000000 + +#include +#include +#include +#include +#include + +/* + * You must add the I2Cdev and MPU6050 directories as include directories in + * project properties/Conf/General options/XC8 global option/XC8 compiler/ + * Preprocessing and messages/Include directories. + */ +#include "I2Cdev.h" +#include "MPU6050.h" + +#define LED_PIN LATBbits.LATB1 + +/** + * Write one char to USART + * @param data + */ +void putch(char data) { + while (Busy1USART()); + Write1USART(data); +} + +/** + * Main function + */ +int main() { + int16_t ax, ay, az, gx, gy, gz; + + // Initialize system + // PLL (24 MHz) + OSCTUNEbits.PLLEN = 1; + __delay_ms(25); + __delay_ms(25); + + // LED + LED_PIN = 0; + TRISBbits.TRISB1 = 0; + + // Serial (115200 kbps) + Open1USART(USART_TX_INT_OFF | USART_RX_INT_OFF | USART_ASYNCH_MODE | + USART_EIGHT_BIT | USART_CONT_RX | USART_BRGH_HIGH, 12); + baud1USART(BAUD_8_BIT_RATE | BAUD_AUTO_OFF); + + // I2C (400 kHz) + OpenI2C(MASTER, SLEW_OFF); + SSP1ADD = 14; + + // MPU6050 + MPU6050(MPU6050_ADDRESS_AD0_LOW); + + // Initialize device + printf("Initializing I2C devices...\r\n"); + MPU6050_initialize(); + + // Verify connection + printf("Testing device connections...\r\n"); + printf(MPU6050_testConnection() ? "MPU6050 connection successful\r\n" : + "MPU6050 connection failed\r\n"); + + printf("Reading internal sensor offsets...\r\n"); + printf("%d\t", MPU6050_getXAccelOffset()); + printf("%d\t", MPU6050_getYAccelOffset()); + printf("%d\t", MPU6050_getZAccelOffset()); + printf("%d\t", MPU6050_getXGyroOffset()); + printf("%d\t", MPU6050_getYGyroOffset()); + printf("%d\t\n", MPU6050_getZGyroOffset()); + + while (true) { + // Read raw accel/gyro measurements from device + MPU6050_getMotion6(&ax, &ay, &az, &gx, &gy, &gz); + + // Display tab-separated accel/gyro x/y/z values + printf("a/g:\t%d\t%d\t%d\t%d\t%d\t%d\r\n", ax, ay, az, gx, gy, gz); + + // Blink LED to indicate activity + LED_PIN ^= 1; + + __delay_ms(25); + __delay_ms(25); + } +} diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-default.mk b/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-default.mk new file mode 100644 index 00000000..1c5f0ec6 --- /dev/null +++ b/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-default.mk @@ -0,0 +1,172 @@ +# +# Generated Makefile - do not edit! +# +# Edit the Makefile in the project folder instead (../Makefile). Each target +# has a -pre and a -post target defined where you can add customized code. +# +# This makefile implements configuration specific macros and targets. + + +# Include project Makefile +ifeq "${IGNORE_LOCAL}" "TRUE" +# do not include local makefile. User is passing all local related variables already +else +include Makefile +# Include makefile containing local settings +ifeq "$(wildcard nbproject/Makefile-local-default.mk)" "nbproject/Makefile-local-default.mk" +include nbproject/Makefile-local-default.mk +endif +endif + +# Environment +MKDIR=gnumkdir -p +RM=rm -f +MV=mv +CP=cp + +# Macros +CND_CONF=default +ifeq ($(TYPE_IMAGE), DEBUG_RUN) +IMAGE_TYPE=debug +OUTPUT_SUFFIX=elf +DEBUGGABLE_SUFFIX=elf +FINAL_IMAGE=dist/${CND_CONF}/${IMAGE_TYPE}/MPU6050_raw.X.${IMAGE_TYPE}.${OUTPUT_SUFFIX} +else +IMAGE_TYPE=production +OUTPUT_SUFFIX=hex +DEBUGGABLE_SUFFIX=elf +FINAL_IMAGE=dist/${CND_CONF}/${IMAGE_TYPE}/MPU6050_raw.X.${IMAGE_TYPE}.${OUTPUT_SUFFIX} +endif + +# Object Directory +OBJECTDIR=build/${CND_CONF}/${IMAGE_TYPE} + +# Distribution Directory +DISTDIR=dist/${CND_CONF}/${IMAGE_TYPE} + +# Source Files Quoted if spaced +SOURCEFILES_QUOTED_IF_SPACED=../../MPU6050.c ../../../I2Cdev/I2Cdev.c main.c + +# Object Files Quoted if spaced +OBJECTFILES_QUOTED_IF_SPACED=${OBJECTDIR}/_ext/43898991/MPU6050.p1 ${OBJECTDIR}/_ext/105797386/I2Cdev.p1 ${OBJECTDIR}/main.p1 +POSSIBLE_DEPFILES=${OBJECTDIR}/_ext/43898991/MPU6050.p1.d ${OBJECTDIR}/_ext/105797386/I2Cdev.p1.d ${OBJECTDIR}/main.p1.d + +# Object Files +OBJECTFILES=${OBJECTDIR}/_ext/43898991/MPU6050.p1 ${OBJECTDIR}/_ext/105797386/I2Cdev.p1 ${OBJECTDIR}/main.p1 + +# Source Files +SOURCEFILES=../../MPU6050.c ../../../I2Cdev/I2Cdev.c main.c + + +CFLAGS= +ASFLAGS= +LDLIBSOPTIONS= + +############# Tool locations ########################################## +# If you copy a project from one host to another, the path where the # +# compiler is installed may be different. # +# If you open this project with MPLAB X in the new host, this # +# makefile will be regenerated and the paths will be corrected. # +####################################################################### +# fixDeps replaces a bunch of sed/cat/printf statements that slow down the build +FIXDEPS=fixDeps + +.build-conf: ${BUILD_SUBPROJECTS} + ${MAKE} -f nbproject/Makefile-default.mk dist/${CND_CONF}/${IMAGE_TYPE}/MPU6050_raw.X.${IMAGE_TYPE}.${OUTPUT_SUFFIX} + +MP_PROCESSOR_OPTION=18F46J50 +# ------------------------------------------------------------------------------------ +# Rules for buildStep: compile +ifeq ($(TYPE_IMAGE), DEBUG_RUN) +${OBJECTDIR}/_ext/43898991/MPU6050.p1: ../../MPU6050.c nbproject/Makefile-${CND_CONF}.mk + @${MKDIR} ${OBJECTDIR}/_ext/43898991 + @${RM} ${OBJECTDIR}/_ext/43898991/MPU6050.p1.d + @${RM} ${OBJECTDIR}/_ext/43898991/MPU6050.p1 + ${MP_CC} --pass1 $(MP_EXTRA_CC_PRE) --chip=$(MP_PROCESSOR_OPTION) -Q -G -D__DEBUG=1 --debugger=pickit3 --double=24 --float=24 --emi=wordwrite --opt=default,+asm,-asmfile,+speed,-space,-debug --addrqual=ignore --mode=pro -P -N255 -I"../../../I2Cdev" -I"../../" --warn=0 --asmlist --summary=default,-psect,-class,+mem,-hex,-file --output=default,-inhx032 --runtime=default,+clear,+init,-keep,-no_startup,-download,+config,+clib,+plib --output=-mcof,+elf:multilocs --stack=compiled:auto:auto:auto "--errformat=%f:%l: error: (%n) %s" "--warnformat=%f:%l: warning: (%n) %s" "--msgformat=%f:%l: advisory: (%n) %s" -o${OBJECTDIR}/_ext/43898991/MPU6050.p1 ../../MPU6050.c + @-${MV} ${OBJECTDIR}/_ext/43898991/MPU6050.d ${OBJECTDIR}/_ext/43898991/MPU6050.p1.d + @${FIXDEPS} ${OBJECTDIR}/_ext/43898991/MPU6050.p1.d $(SILENT) -rsi ${MP_CC_DIR}../ + +${OBJECTDIR}/_ext/105797386/I2Cdev.p1: ../../../I2Cdev/I2Cdev.c nbproject/Makefile-${CND_CONF}.mk + @${MKDIR} ${OBJECTDIR}/_ext/105797386 + @${RM} ${OBJECTDIR}/_ext/105797386/I2Cdev.p1.d + @${RM} ${OBJECTDIR}/_ext/105797386/I2Cdev.p1 + ${MP_CC} --pass1 $(MP_EXTRA_CC_PRE) --chip=$(MP_PROCESSOR_OPTION) -Q -G -D__DEBUG=1 --debugger=pickit3 --double=24 --float=24 --emi=wordwrite --opt=default,+asm,-asmfile,+speed,-space,-debug --addrqual=ignore --mode=pro -P -N255 -I"../../../I2Cdev" -I"../../" --warn=0 --asmlist --summary=default,-psect,-class,+mem,-hex,-file --output=default,-inhx032 --runtime=default,+clear,+init,-keep,-no_startup,-download,+config,+clib,+plib --output=-mcof,+elf:multilocs --stack=compiled:auto:auto:auto "--errformat=%f:%l: error: (%n) %s" "--warnformat=%f:%l: warning: (%n) %s" "--msgformat=%f:%l: advisory: (%n) %s" -o${OBJECTDIR}/_ext/105797386/I2Cdev.p1 ../../../I2Cdev/I2Cdev.c + @-${MV} ${OBJECTDIR}/_ext/105797386/I2Cdev.d ${OBJECTDIR}/_ext/105797386/I2Cdev.p1.d + @${FIXDEPS} ${OBJECTDIR}/_ext/105797386/I2Cdev.p1.d $(SILENT) -rsi ${MP_CC_DIR}../ + +${OBJECTDIR}/main.p1: main.c nbproject/Makefile-${CND_CONF}.mk + @${MKDIR} ${OBJECTDIR} + @${RM} ${OBJECTDIR}/main.p1.d + @${RM} ${OBJECTDIR}/main.p1 + ${MP_CC} --pass1 $(MP_EXTRA_CC_PRE) --chip=$(MP_PROCESSOR_OPTION) -Q -G -D__DEBUG=1 --debugger=pickit3 --double=24 --float=24 --emi=wordwrite --opt=default,+asm,-asmfile,+speed,-space,-debug --addrqual=ignore --mode=pro -P -N255 -I"../../../I2Cdev" -I"../../" --warn=0 --asmlist --summary=default,-psect,-class,+mem,-hex,-file --output=default,-inhx032 --runtime=default,+clear,+init,-keep,-no_startup,-download,+config,+clib,+plib --output=-mcof,+elf:multilocs --stack=compiled:auto:auto:auto "--errformat=%f:%l: error: (%n) %s" "--warnformat=%f:%l: warning: (%n) %s" "--msgformat=%f:%l: advisory: (%n) %s" -o${OBJECTDIR}/main.p1 main.c + @-${MV} ${OBJECTDIR}/main.d ${OBJECTDIR}/main.p1.d + @${FIXDEPS} ${OBJECTDIR}/main.p1.d $(SILENT) -rsi ${MP_CC_DIR}../ + +else +${OBJECTDIR}/_ext/43898991/MPU6050.p1: ../../MPU6050.c nbproject/Makefile-${CND_CONF}.mk + @${MKDIR} ${OBJECTDIR}/_ext/43898991 + @${RM} ${OBJECTDIR}/_ext/43898991/MPU6050.p1.d + @${RM} ${OBJECTDIR}/_ext/43898991/MPU6050.p1 + ${MP_CC} --pass1 $(MP_EXTRA_CC_PRE) --chip=$(MP_PROCESSOR_OPTION) -Q -G --double=24 --float=24 --emi=wordwrite --opt=default,+asm,-asmfile,+speed,-space,-debug --addrqual=ignore --mode=pro -P -N255 -I"../../../I2Cdev" -I"../../" --warn=0 --asmlist --summary=default,-psect,-class,+mem,-hex,-file --output=default,-inhx032 --runtime=default,+clear,+init,-keep,-no_startup,-download,+config,+clib,+plib --output=-mcof,+elf:multilocs --stack=compiled:auto:auto:auto "--errformat=%f:%l: error: (%n) %s" "--warnformat=%f:%l: warning: (%n) %s" "--msgformat=%f:%l: advisory: (%n) %s" -o${OBJECTDIR}/_ext/43898991/MPU6050.p1 ../../MPU6050.c + @-${MV} ${OBJECTDIR}/_ext/43898991/MPU6050.d ${OBJECTDIR}/_ext/43898991/MPU6050.p1.d + @${FIXDEPS} ${OBJECTDIR}/_ext/43898991/MPU6050.p1.d $(SILENT) -rsi ${MP_CC_DIR}../ + +${OBJECTDIR}/_ext/105797386/I2Cdev.p1: ../../../I2Cdev/I2Cdev.c nbproject/Makefile-${CND_CONF}.mk + @${MKDIR} ${OBJECTDIR}/_ext/105797386 + @${RM} ${OBJECTDIR}/_ext/105797386/I2Cdev.p1.d + @${RM} ${OBJECTDIR}/_ext/105797386/I2Cdev.p1 + ${MP_CC} --pass1 $(MP_EXTRA_CC_PRE) --chip=$(MP_PROCESSOR_OPTION) -Q -G --double=24 --float=24 --emi=wordwrite --opt=default,+asm,-asmfile,+speed,-space,-debug --addrqual=ignore --mode=pro -P -N255 -I"../../../I2Cdev" -I"../../" --warn=0 --asmlist --summary=default,-psect,-class,+mem,-hex,-file --output=default,-inhx032 --runtime=default,+clear,+init,-keep,-no_startup,-download,+config,+clib,+plib --output=-mcof,+elf:multilocs --stack=compiled:auto:auto:auto "--errformat=%f:%l: error: (%n) %s" "--warnformat=%f:%l: warning: (%n) %s" "--msgformat=%f:%l: advisory: (%n) %s" -o${OBJECTDIR}/_ext/105797386/I2Cdev.p1 ../../../I2Cdev/I2Cdev.c + @-${MV} ${OBJECTDIR}/_ext/105797386/I2Cdev.d ${OBJECTDIR}/_ext/105797386/I2Cdev.p1.d + @${FIXDEPS} ${OBJECTDIR}/_ext/105797386/I2Cdev.p1.d $(SILENT) -rsi ${MP_CC_DIR}../ + +${OBJECTDIR}/main.p1: main.c nbproject/Makefile-${CND_CONF}.mk + @${MKDIR} ${OBJECTDIR} + @${RM} ${OBJECTDIR}/main.p1.d + @${RM} ${OBJECTDIR}/main.p1 + ${MP_CC} --pass1 $(MP_EXTRA_CC_PRE) --chip=$(MP_PROCESSOR_OPTION) -Q -G --double=24 --float=24 --emi=wordwrite --opt=default,+asm,-asmfile,+speed,-space,-debug --addrqual=ignore --mode=pro -P -N255 -I"../../../I2Cdev" -I"../../" --warn=0 --asmlist --summary=default,-psect,-class,+mem,-hex,-file --output=default,-inhx032 --runtime=default,+clear,+init,-keep,-no_startup,-download,+config,+clib,+plib --output=-mcof,+elf:multilocs --stack=compiled:auto:auto:auto "--errformat=%f:%l: error: (%n) %s" "--warnformat=%f:%l: warning: (%n) %s" "--msgformat=%f:%l: advisory: (%n) %s" -o${OBJECTDIR}/main.p1 main.c + @-${MV} ${OBJECTDIR}/main.d ${OBJECTDIR}/main.p1.d + @${FIXDEPS} ${OBJECTDIR}/main.p1.d $(SILENT) -rsi ${MP_CC_DIR}../ + +endif + +# ------------------------------------------------------------------------------------ +# Rules for buildStep: assemble +ifeq ($(TYPE_IMAGE), DEBUG_RUN) +else +endif + +# ------------------------------------------------------------------------------------ +# Rules for buildStep: link +ifeq ($(TYPE_IMAGE), DEBUG_RUN) +dist/${CND_CONF}/${IMAGE_TYPE}/MPU6050_raw.X.${IMAGE_TYPE}.${OUTPUT_SUFFIX}: ${OBJECTFILES} nbproject/Makefile-${CND_CONF}.mk + @${MKDIR} dist/${CND_CONF}/${IMAGE_TYPE} + ${MP_CC} $(MP_EXTRA_LD_PRE) --chip=$(MP_PROCESSOR_OPTION) -G -mdist/${CND_CONF}/${IMAGE_TYPE}/MPU6050_raw.X.${IMAGE_TYPE}.map -D__DEBUG=1 --debugger=pickit3 --double=24 --float=24 --emi=wordwrite --opt=default,+asm,-asmfile,+speed,-space,-debug --addrqual=ignore --mode=pro -P -N255 -I"../../../I2Cdev" -I"../../" --warn=0 --asmlist --summary=default,-psect,-class,+mem,-hex,-file --output=default,-inhx032 --runtime=default,+clear,+init,-keep,-no_startup,-download,+config,+clib,+plib --output=-mcof,+elf:multilocs --stack=compiled:auto:auto:auto "--errformat=%f:%l: error: (%n) %s" "--warnformat=%f:%l: warning: (%n) %s" "--msgformat=%f:%l: advisory: (%n) %s" -odist/${CND_CONF}/${IMAGE_TYPE}/MPU6050_raw.X.${IMAGE_TYPE}.${DEBUGGABLE_SUFFIX} ${OBJECTFILES_QUOTED_IF_SPACED} + @${RM} dist/${CND_CONF}/${IMAGE_TYPE}/MPU6050_raw.X.${IMAGE_TYPE}.hex + +else +dist/${CND_CONF}/${IMAGE_TYPE}/MPU6050_raw.X.${IMAGE_TYPE}.${OUTPUT_SUFFIX}: ${OBJECTFILES} nbproject/Makefile-${CND_CONF}.mk + @${MKDIR} dist/${CND_CONF}/${IMAGE_TYPE} + ${MP_CC} $(MP_EXTRA_LD_PRE) --chip=$(MP_PROCESSOR_OPTION) -G -mdist/${CND_CONF}/${IMAGE_TYPE}/MPU6050_raw.X.${IMAGE_TYPE}.map --double=24 --float=24 --emi=wordwrite --opt=default,+asm,-asmfile,+speed,-space,-debug --addrqual=ignore --mode=pro -P -N255 -I"../../../I2Cdev" -I"../../" --warn=0 --asmlist --summary=default,-psect,-class,+mem,-hex,-file --output=default,-inhx032 --runtime=default,+clear,+init,-keep,-no_startup,-download,+config,+clib,+plib --output=-mcof,+elf:multilocs --stack=compiled:auto:auto:auto "--errformat=%f:%l: error: (%n) %s" "--warnformat=%f:%l: warning: (%n) %s" "--msgformat=%f:%l: advisory: (%n) %s" -odist/${CND_CONF}/${IMAGE_TYPE}/MPU6050_raw.X.${IMAGE_TYPE}.${DEBUGGABLE_SUFFIX} ${OBJECTFILES_QUOTED_IF_SPACED} + +endif + + +# Subprojects +.build-subprojects: + + +# Subprojects +.clean-subprojects: + +# Clean Targets +.clean-conf: ${CLEAN_SUBPROJECTS} + ${RM} -r build/default + ${RM} -r dist/default + +# Enable dependency checking +.dep.inc: .depcheck-impl + +DEPFILES=$(shell mplabwildcard ${POSSIBLE_DEPFILES}) +ifneq (${DEPFILES},) +include ${DEPFILES} +endif diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-genesis.properties b/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-genesis.properties new file mode 100644 index 00000000..441f9906 --- /dev/null +++ b/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-genesis.properties @@ -0,0 +1,8 @@ +# +#Fri Nov 28 22:55:53 CET 2014 +default.languagetoolchain.dir=C\:\\Program Files (x86)\\Microchip\\xc8\\v1.32\\bin +com-microchip-mplab-nbide-embedded-makeproject-MakeProject.md5=20b996ec0591c93034157100c3d90ac3 +default.languagetoolchain.version=1.32 +host.platform=windows +conf.ids=default +default.com-microchip-mplab-nbide-toolchainXC8-XC8LanguageToolchain.md5=533e5c34133c5d768bcb87ffcec948e1 diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-impl.mk b/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-impl.mk new file mode 100644 index 00000000..8897f7f2 --- /dev/null +++ b/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-impl.mk @@ -0,0 +1,69 @@ +# +# Generated Makefile - do not edit! +# +# Edit the Makefile in the project folder instead (../Makefile). Each target +# has a pre- and a post- target defined where you can add customization code. +# +# This makefile implements macros and targets common to all configurations. +# +# NOCDDL + + +# Building and Cleaning subprojects are done by default, but can be controlled with the SUB +# macro. If SUB=no, subprojects will not be built or cleaned. The following macro +# statements set BUILD_SUB-CONF and CLEAN_SUB-CONF to .build-reqprojects-conf +# and .clean-reqprojects-conf unless SUB has the value 'no' +SUB_no=NO +SUBPROJECTS=${SUB_${SUB}} +BUILD_SUBPROJECTS_=.build-subprojects +BUILD_SUBPROJECTS_NO= +BUILD_SUBPROJECTS=${BUILD_SUBPROJECTS_${SUBPROJECTS}} +CLEAN_SUBPROJECTS_=.clean-subprojects +CLEAN_SUBPROJECTS_NO= +CLEAN_SUBPROJECTS=${CLEAN_SUBPROJECTS_${SUBPROJECTS}} + + +# Project Name +PROJECTNAME=MPU6050_raw.X + +# Active Configuration +DEFAULTCONF=default +CONF=${DEFAULTCONF} + +# All Configurations +ALLCONFS=default + + +# build +.build-impl: .build-pre + ${MAKE} -f nbproject/Makefile-${CONF}.mk SUBPROJECTS=${SUBPROJECTS} .build-conf + + +# clean +.clean-impl: .clean-pre + ${MAKE} -f nbproject/Makefile-${CONF}.mk SUBPROJECTS=${SUBPROJECTS} .clean-conf + +# clobber +.clobber-impl: .clobber-pre .depcheck-impl + ${MAKE} SUBPROJECTS=${SUBPROJECTS} CONF=default clean + + + +# all +.all-impl: .all-pre .depcheck-impl + ${MAKE} SUBPROJECTS=${SUBPROJECTS} CONF=default build + + + +# dependency checking support +.depcheck-impl: +# @echo "# This code depends on make tool being used" >.dep.inc +# @if [ -n "${MAKE_VERSION}" ]; then \ +# echo "DEPFILES=\$$(wildcard \$$(addsuffix .d, \$${OBJECTFILES}))" >>.dep.inc; \ +# echo "ifneq (\$${DEPFILES},)" >>.dep.inc; \ +# echo "include \$${DEPFILES}" >>.dep.inc; \ +# echo "endif" >>.dep.inc; \ +# else \ +# echo ".KEEP_STATE:" >>.dep.inc; \ +# echo ".KEEP_STATE_FILE:.make.state.\$${CONF}" >>.dep.inc; \ +# fi diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-local-default.mk b/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-local-default.mk new file mode 100644 index 00000000..dd484ed2 --- /dev/null +++ b/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-local-default.mk @@ -0,0 +1,37 @@ +# +# Generated Makefile - do not edit! +# +# +# This file contains information about the location of compilers and other tools. +# If you commmit this file into your revision control server, you will be able to +# to checkout the project and build it from the command line with make. However, +# if more than one person works on the same project, then this file might show +# conflicts since different users are bound to have compilers in different places. +# In that case you might choose to not commit this file and let MPLAB X recreate this file +# for each user. The disadvantage of not commiting this file is that you must run MPLAB X at +# least once so the file gets created and the project can be built. Finally, you can also +# avoid using this file at all if you are only building from the command line with make. +# You can invoke make with the values of the macros: +# $ makeMP_CC="/opt/microchip/mplabc30/v3.30c/bin/pic30-gcc" ... +# +SHELL=cmd.exe +PATH_TO_IDE_BIN=C:/Program Files (x86)/Microchip/MPLABX/mplab_ide/mplab_ide/modules/../../bin/ +# Adding MPLAB X bin directory to path. +PATH:=C:/Program Files (x86)/Microchip/MPLABX/mplab_ide/mplab_ide/modules/../../bin/:$(PATH) +# Path to java used to run MPLAB X when this makefile was created +MP_JAVA_PATH="C:\Program Files (x86)\Microchip\MPLABX\sys\java\jre1.7.0_25-windows-x64\java-windows/bin/" +OS_CURRENT="$(shell uname -s)" +MP_CC="C:\Program Files (x86)\Microchip\xc8\v1.32\bin\xc8.exe" +# MP_CPPC is not defined +# MP_BC is not defined +MP_AS="C:\Program Files (x86)\Microchip\xc8\v1.32\bin\xc8.exe" +# MP_LD is not defined +# MP_AR is not defined +DEP_GEN=${MP_JAVA_PATH}java -jar "C:/Program Files (x86)/Microchip/MPLABX/mplab_ide/mplab_ide/modules/../../bin/extractobjectdependencies.jar" +MP_CC_DIR="C:\Program Files (x86)\Microchip\xc8\v1.32\bin" +# MP_CPPC_DIR is not defined +# MP_BC_DIR is not defined +MP_AS_DIR="C:\Program Files (x86)\Microchip\xc8\v1.32\bin" +# MP_LD_DIR is not defined +# MP_AR_DIR is not defined +# MP_BC_DIR is not defined diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-variables.mk b/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-variables.mk new file mode 100644 index 00000000..623663b1 --- /dev/null +++ b/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-variables.mk @@ -0,0 +1,13 @@ +# +# Generated - do not edit! +# +# NOCDDL +# +CND_BASEDIR=`pwd` +# default configuration +CND_ARTIFACT_DIR_default=dist/default/production +CND_ARTIFACT_NAME_default=MPU6050_raw.X.production.hex +CND_ARTIFACT_PATH_default=dist/default/production/MPU6050_raw.X.production.hex +CND_PACKAGE_DIR_default=${CND_DISTDIR}/default/package +CND_PACKAGE_NAME_default=mpu6050raw.x.tar +CND_PACKAGE_PATH_default=${CND_DISTDIR}/default/package/mpu6050raw.x.tar diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/Package-default.bash b/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/Package-default.bash new file mode 100644 index 00000000..2b42e19c --- /dev/null +++ b/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/Package-default.bash @@ -0,0 +1,73 @@ +#!/bin/bash -x + +# +# Generated - do not edit! +# + +# Macros +TOP=`pwd` +CND_CONF=default +CND_DISTDIR=dist +TMPDIR=build/${CND_CONF}/${IMAGE_TYPE}/tmp-packaging +TMPDIRNAME=tmp-packaging +OUTPUT_PATH=dist/${CND_CONF}/${IMAGE_TYPE}/MPU6050_raw.X.${IMAGE_TYPE}.${OUTPUT_SUFFIX} +OUTPUT_BASENAME=MPU6050_raw.X.${IMAGE_TYPE}.${OUTPUT_SUFFIX} +PACKAGE_TOP_DIR=mpu6050raw.x/ + +# Functions +function checkReturnCode +{ + rc=$? + if [ $rc != 0 ] + then + exit $rc + fi +} +function makeDirectory +# $1 directory path +# $2 permission (optional) +{ + mkdir -p "$1" + checkReturnCode + if [ "$2" != "" ] + then + chmod $2 "$1" + checkReturnCode + fi +} +function copyFileToTmpDir +# $1 from-file path +# $2 to-file path +# $3 permission +{ + cp "$1" "$2" + checkReturnCode + if [ "$3" != "" ] + then + chmod $3 "$2" + checkReturnCode + fi +} + +# Setup +cd "${TOP}" +mkdir -p ${CND_DISTDIR}/${CND_CONF}/package +rm -rf ${TMPDIR} +mkdir -p ${TMPDIR} + +# Copy files and create directories and links +cd "${TOP}" +makeDirectory ${TMPDIR}/mpu6050raw.x/bin +copyFileToTmpDir "${OUTPUT_PATH}" "${TMPDIR}/${PACKAGE_TOP_DIR}bin/${OUTPUT_BASENAME}" 0755 + + +# Generate tar file +cd "${TOP}" +rm -f ${CND_DISTDIR}/${CND_CONF}/package/mpu6050raw.x.tar +cd ${TMPDIR} +tar -vcf ../../../../${CND_DISTDIR}/${CND_CONF}/package/mpu6050raw.x.tar * +checkReturnCode + +# Cleanup +cd "${TOP}" +rm -rf ${TMPDIR} diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/configurations.xml b/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/configurations.xml new file mode 100644 index 00000000..3b6fba66 --- /dev/null +++ b/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/configurations.xml @@ -0,0 +1,173 @@ + + + + + ../../../I2Cdev/I2Cdev.h + ../../MPU6050.h + + + + + ../../MPU6050.c + ../../../I2Cdev/I2Cdev.c + main.c + + + Makefile + + + + C:\Users\sebokmarton\Documents\i2cdevlib\PIC18\I2Cdev + ../.. + + Makefile + + + + localhost + PIC18F46J50 + + + PICkit3PlatformTool + XC8 + 1.32 + 3 + + + + + + + + + + false + false + + + + + false + + false + + false + false + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/project.properties b/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/project.properties new file mode 100644 index 00000000..e69de29b diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/project.xml b/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/project.xml new file mode 100644 index 00000000..18806930 --- /dev/null +++ b/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/project.xml @@ -0,0 +1,16 @@ + + com.microchip.mplab.nbide.embedded.makeproject + + + MPU6050_raw + 84892e89-df8e-441e-9542-2524d6b2dc5a + 0 + c + + h + + UTF-8 + + + + diff --git a/dsPIC30F/MPU6050/MPU6050.c b/dsPIC30F/MPU6050/MPU6050.c new file mode 100644 index 00000000..2683529a --- /dev/null +++ b/dsPIC30F/MPU6050/MPU6050.c @@ -0,0 +1,3141 @@ +// I2Cdev library collection - MPU6050 I2C device class +// Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00) +// 8/24/2011 by Jeff Rowberg +// 11/28/2014 by Marton Sebok +// +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// ... - ongoing debug release +// 2014-11-28 - ported to PIC18 peripheral library from Arduino code + +// NOTE: THIS IS ONLY A PARIAL RELEASE. THIS DEVICE CLASS IS CURRENTLY UNDERGOING ACTIVE +// DEVELOPMENT AND IS STILL MISSING SOME IMPORTANT FEATURES. PLEASE KEEP THIS IN MIND IF +// YOU DECIDE TO USE THIS PARTICULAR CODE FOR ANYTHING. + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2012 Jeff Rowberg +Copyright (c) 2014 Marton Sebok + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#include "MPU6050.h" + +MPU6050_t mpu6050; + +/** Specific address constructor. + * @param address I2C address + * @see MPU6050_DEFAULT_ADDRESS + * @see MPU6050_ADDRESS_AD0_LOW + * @see MPU6050_ADDRESS_AD0_HIGH + */ +void MPU6050(uint8_t address) { + mpu6050.devAddr = address; +} + +/** Power on and prepare for general usage. + * This will activate the device and take it out of sleep mode (which must be done + * after start-up). This function also sets both the accelerometer and the gyroscope + * to their most sensitive settings, namely +/- 2g and +/- 250 degrees/sec, and sets + * the clock source to use the X Gyro for reference, which is slightly better than + * the default internal clock source. + */ +void MPU6050_initialize() { + MPU6050_setClockSource(MPU6050_CLOCK_PLL_XGYRO); + MPU6050_setFullScaleGyroRange(MPU6050_GYRO_FS_250); + MPU6050_setFullScaleAccelRange(MPU6050_ACCEL_FS_2); + MPU6050_setSleepEnabled(false); // thanks to Jack Elston for pointing this one out! +} + +/** Verify the I2C connection. + * Make sure the device is connected and responds as expected. + * @return True if connection is valid, false otherwise + */ +bool MPU6050_testConnection() { + return MPU6050_getDeviceID() == 0x34; +} + +// AUX_VDDIO register (InvenSense demo code calls this RA_*G_OFFS_TC) + +/** Get the auxiliary I2C supply voltage level. + * When set to 1, the auxiliary I2C bus high logic level is VDD. When cleared to + * 0, the auxiliary I2C bus high logic level is VLOGIC. This does not apply to + * the MPU-6000, which does not have a VLOGIC pin. + * @return I2C supply voltage level (0=VLOGIC, 1=VDD) + */ +uint8_t MPU6050_getAuxVDDIOLevel() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_PWR_MODE_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set the auxiliary I2C supply voltage level. + * When set to 1, the auxiliary I2C bus high logic level is VDD. When cleared to + * 0, the auxiliary I2C bus high logic level is VLOGIC. This does not apply to + * the MPU-6000, which does not have a VLOGIC pin. + * @param level I2C supply voltage level (0=VLOGIC, 1=VDD) + */ +void MPU6050_setAuxVDDIOLevel(uint8_t level) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_PWR_MODE_BIT, level); +} + +// SMPLRT_DIV register + +/** Get gyroscope output rate divider. + * The sensor register output, FIFO output, DMP sampling, Motion detection, Zero + * Motion detection, and Free Fall detection are all based on the Sample Rate. + * The Sample Rate is generated by dividing the gyroscope output rate by + * SMPLRT_DIV: + * + * Sample Rate = Gyroscope Output Rate / (1 + SMPLRT_DIV) + * + * where Gyroscope Output Rate = 8kHz when the DLPF is disabled (DLPF_CFG = 0 or + * 7), and 1kHz when the DLPF is enabled (see Register 26). + * + * Note: The accelerometer output rate is 1kHz. This means that for a Sample + * Rate greater than 1kHz, the same accelerometer sample may be output to the + * FIFO, DMP, and sensor registers more than once. + * + * For a diagram of the gyroscope and accelerometer signal paths, see Section 8 + * of the MPU-6000/MPU-6050 Product Specification document. + * + * @return Current sample rate + * @see MPU6050_RA_SMPLRT_DIV + */ +uint8_t MPU6050_getRate() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_SMPLRT_DIV, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set gyroscope sample rate divider. + * @param rate New sample rate divider + * @see getRate() + * @see MPU6050_RA_SMPLRT_DIV + */ +void MPU6050_setRate(uint8_t rate) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_SMPLRT_DIV, rate); +} + +// CONFIG register + +/** Get external FSYNC configuration. + * Configures the external Frame Synchronization (FSYNC) pin sampling. An + * external signal connected to the FSYNC pin can be sampled by configuring + * EXT_SYNC_SET. Signal changes to the FSYNC pin are latched so that short + * strobes may be captured. The latched FSYNC signal will be sampled at the + * Sampling Rate, as defined in register 25. After sampling, the latch will + * reset to the current FSYNC signal state. + * + * The sampled value will be reported in place of the least significant bit in + * a sensor data register determined by the value of EXT_SYNC_SET according to + * the following table. + * + *
+ * EXT_SYNC_SET | FSYNC Bit Location
+ * -------------+-------------------
+ * 0            | Input disabled
+ * 1            | TEMP_OUT_L[0]
+ * 2            | GYRO_XOUT_L[0]
+ * 3            | GYRO_YOUT_L[0]
+ * 4            | GYRO_ZOUT_L[0]
+ * 5            | ACCEL_XOUT_L[0]
+ * 6            | ACCEL_YOUT_L[0]
+ * 7            | ACCEL_ZOUT_L[0]
+ * 
+ * + * @return FSYNC configuration value + */ +uint8_t MPU6050_getExternalFrameSync() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_EXT_SYNC_SET_BIT, MPU6050_CFG_EXT_SYNC_SET_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set external FSYNC configuration. + * @see getExternalFrameSync() + * @see MPU6050_RA_CONFIG + * @param sync New FSYNC configuration value + */ +void MPU6050_setExternalFrameSync(uint8_t sync) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_EXT_SYNC_SET_BIT, MPU6050_CFG_EXT_SYNC_SET_LENGTH, sync); +} +/** Get digital low-pass filter configuration. + * The DLPF_CFG parameter sets the digital low pass filter configuration. It + * also determines the internal sampling rate used by the device as shown in + * the table below. + * + * Note: The accelerometer output rate is 1kHz. This means that for a Sample + * Rate greater than 1kHz, the same accelerometer sample may be output to the + * FIFO, DMP, and sensor registers more than once. + * + *
+ *          |   ACCELEROMETER    |           GYROSCOPE
+ * DLPF_CFG | Bandwidth | Delay  | Bandwidth | Delay  | Sample Rate
+ * ---------+-----------+--------+-----------+--------+-------------
+ * 0        | 260Hz     | 0ms    | 256Hz     | 0.98ms | 8kHz
+ * 1        | 184Hz     | 2.0ms  | 188Hz     | 1.9ms  | 1kHz
+ * 2        | 94Hz      | 3.0ms  | 98Hz      | 2.8ms  | 1kHz
+ * 3        | 44Hz      | 4.9ms  | 42Hz      | 4.8ms  | 1kHz
+ * 4        | 21Hz      | 8.5ms  | 20Hz      | 8.3ms  | 1kHz
+ * 5        | 10Hz      | 13.8ms | 10Hz      | 13.4ms | 1kHz
+ * 6        | 5Hz       | 19.0ms | 5Hz       | 18.6ms | 1kHz
+ * 7        |   -- Reserved --   |   -- Reserved --   | Reserved
+ * 
+ * + * @return DLFP configuration + * @see MPU6050_RA_CONFIG + * @see MPU6050_CFG_DLPF_CFG_BIT + * @see MPU6050_CFG_DLPF_CFG_LENGTH + */ +uint8_t MPU6050_getDLPFMode() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_DLPF_CFG_BIT, MPU6050_CFG_DLPF_CFG_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set digital low-pass filter configuration. + * @param mode New DLFP configuration setting + * @see getDLPFBandwidth() + * @see MPU6050_DLPF_BW_256 + * @see MPU6050_RA_CONFIG + * @see MPU6050_CFG_DLPF_CFG_BIT + * @see MPU6050_CFG_DLPF_CFG_LENGTH + */ +void MPU6050_setDLPFMode(uint8_t mode) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_DLPF_CFG_BIT, MPU6050_CFG_DLPF_CFG_LENGTH, mode); +} + +// GYRO_CONFIG register + +/** Get full-scale gyroscope range. + * The FS_SEL parameter allows setting the full-scale range of the gyro sensors, + * as described in the table below. + * + *
+ * 0 = +/- 250 degrees/sec
+ * 1 = +/- 500 degrees/sec
+ * 2 = +/- 1000 degrees/sec
+ * 3 = +/- 2000 degrees/sec
+ * 
+ * + * @return Current full-scale gyroscope range setting + * @see MPU6050_GYRO_FS_250 + * @see MPU6050_RA_GYRO_CONFIG + * @see MPU6050_GCONFIG_FS_SEL_BIT + * @see MPU6050_GCONFIG_FS_SEL_LENGTH + */ +uint8_t MPU6050_getFullScaleGyroRange() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set full-scale gyroscope range. + * @param range New full-scale gyroscope range value + * @see getFullScaleRange() + * @see MPU6050_GYRO_FS_250 + * @see MPU6050_RA_GYRO_CONFIG + * @see MPU6050_GCONFIG_FS_SEL_BIT + * @see MPU6050_GCONFIG_FS_SEL_LENGTH + */ +void MPU6050_setFullScaleGyroRange(uint8_t range) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, range); +} + +// ACCEL_CONFIG register + +/** Get self-test enabled setting for accelerometer X axis. + * @return Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +bool MPU6050_getAccelXSelfTest() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_XA_ST_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get self-test enabled setting for accelerometer X axis. + * @param enabled Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050_setAccelXSelfTest(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_XA_ST_BIT, enabled); +} +/** Get self-test enabled value for accelerometer Y axis. + * @return Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +bool MPU6050_getAccelYSelfTest() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_YA_ST_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get self-test enabled value for accelerometer Y axis. + * @param enabled Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050_setAccelYSelfTest(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_YA_ST_BIT, enabled); +} +/** Get self-test enabled value for accelerometer Z axis. + * @return Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +bool MPU6050_getAccelZSelfTest() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ZA_ST_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set self-test enabled value for accelerometer Z axis. + * @param enabled Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050_setAccelZSelfTest(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ZA_ST_BIT, enabled); +} +/** Get full-scale accelerometer range. + * The FS_SEL parameter allows setting the full-scale range of the accelerometer + * sensors, as described in the table below. + * + *
+ * 0 = +/- 2g
+ * 1 = +/- 4g
+ * 2 = +/- 8g
+ * 3 = +/- 16g
+ * 
+ * + * @return Current full-scale accelerometer range setting + * @see MPU6050_ACCEL_FS_2 + * @see MPU6050_RA_ACCEL_CONFIG + * @see MPU6050_ACONFIG_AFS_SEL_BIT + * @see MPU6050_ACONFIG_AFS_SEL_LENGTH + */ +uint8_t MPU6050_getFullScaleAccelRange() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set full-scale accelerometer range. + * @param range New full-scale accelerometer range setting + * @see getFullScaleAccelRange() + */ +void MPU6050_setFullScaleAccelRange(uint8_t range) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, range); +} +/** Get the high-pass filter configuration. + * The DHPF is a filter module in the path leading to motion detectors (Free + * Fall, Motion threshold, and Zero Motion). The high pass filter output is not + * available to the data registers (see Figure in Section 8 of the MPU-6000/ + * MPU-6050 Product Specification document). + * + * The high pass filter has three modes: + * + *
+ *    Reset: The filter output settles to zero within one sample. This
+ *           effectively disables the high pass filter. This mode may be toggled
+ *           to quickly settle the filter.
+ *
+ *    On:    The high pass filter will pass signals above the cut off frequency.
+ *
+ *    Hold:  When triggered, the filter holds the present sample. The filter
+ *           output will be the difference between the input sample and the held
+ *           sample.
+ * 
+ * + *
+ * ACCEL_HPF | Filter Mode | Cut-off Frequency
+ * ----------+-------------+------------------
+ * 0         | Reset       | None
+ * 1         | On          | 5Hz
+ * 2         | On          | 2.5Hz
+ * 3         | On          | 1.25Hz
+ * 4         | On          | 0.63Hz
+ * 7         | Hold        | None
+ * 
+ * + * @return Current high-pass filter configuration + * @see MPU6050_DHPF_RESET + * @see MPU6050_RA_ACCEL_CONFIG + */ +uint8_t MPU6050_getDHPFMode() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ACCEL_HPF_BIT, MPU6050_ACONFIG_ACCEL_HPF_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set the high-pass filter configuration. + * @param bandwidth New high-pass filter configuration + * @see setDHPFMode() + * @see MPU6050_DHPF_RESET + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050_setDHPFMode(uint8_t bandwidth) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ACCEL_HPF_BIT, MPU6050_ACONFIG_ACCEL_HPF_LENGTH, bandwidth); +} + +// FF_THR register + +/** Get free-fall event acceleration threshold. + * This register configures the detection threshold for Free Fall event + * detection. The unit of FF_THR is 1LSB = 2mg. Free Fall is detected when the + * absolute value of the accelerometer measurements for the three axes are each + * less than the detection threshold. This condition increments the Free Fall + * duration counter (Register 30). The Free Fall interrupt is triggered when the + * Free Fall duration counter reaches the time specified in FF_DUR. + * + * For more details on the Free Fall detection interrupt, see Section 8.2 of the + * MPU-6000/MPU-6050 Product Specification document as well as Registers 56 and + * 58 of this document. + * + * @return Current free-fall acceleration threshold value (LSB = 2mg) + * @see MPU6050_RA_FF_THR + */ +uint8_t MPU6050_getFreefallDetectionThreshold() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_FF_THR, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get free-fall event acceleration threshold. + * @param threshold New free-fall acceleration threshold value (LSB = 2mg) + * @see getFreefallDetectionThreshold() + * @see MPU6050_RA_FF_THR + */ +void MPU6050_setFreefallDetectionThreshold(uint8_t threshold) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_FF_THR, threshold); +} + +// FF_DUR register + +/** Get free-fall event duration threshold. + * This register configures the duration counter threshold for Free Fall event + * detection. The duration counter ticks at 1kHz, therefore FF_DUR has a unit + * of 1 LSB = 1 ms. + * + * The Free Fall duration counter increments while the absolute value of the + * accelerometer measurements are each less than the detection threshold + * (Register 29). The Free Fall interrupt is triggered when the Free Fall + * duration counter reaches the time specified in this register. + * + * For more details on the Free Fall detection interrupt, see Section 8.2 of + * the MPU-6000/MPU-6050 Product Specification document as well as Registers 56 + * and 58 of this document. + * + * @return Current free-fall duration threshold value (LSB = 1ms) + * @see MPU6050_RA_FF_DUR + */ +uint8_t MPU6050_getFreefallDetectionDuration() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_FF_DUR, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get free-fall event duration threshold. + * @param duration New free-fall duration threshold value (LSB = 1ms) + * @see getFreefallDetectionDuration() + * @see MPU6050_RA_FF_DUR + */ +void MPU6050_setFreefallDetectionDuration(uint8_t duration) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_FF_DUR, duration); +} + +// MOT_THR register + +/** Get motion detection event acceleration threshold. + * This register configures the detection threshold for Motion interrupt + * generation. The unit of MOT_THR is 1LSB = 2mg. Motion is detected when the + * absolute value of any of the accelerometer measurements exceeds this Motion + * detection threshold. This condition increments the Motion detection duration + * counter (Register 32). The Motion detection interrupt is triggered when the + * Motion Detection counter reaches the time count specified in MOT_DUR + * (Register 32). + * + * The Motion interrupt will indicate the axis and polarity of detected motion + * in MOT_DETECT_STATUS (Register 97). + * + * For more details on the Motion detection interrupt, see Section 8.3 of the + * MPU-6000/MPU-6050 Product Specification document as well as Registers 56 and + * 58 of this document. + * + * @return Current motion detection acceleration threshold value (LSB = 2mg) + * @see MPU6050_RA_MOT_THR + */ +uint8_t MPU6050_getMotionDetectionThreshold() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_MOT_THR, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set free-fall event acceleration threshold. + * @param threshold New motion detection acceleration threshold value (LSB = 2mg) + * @see getMotionDetectionThreshold() + * @see MPU6050_RA_MOT_THR + */ +void MPU6050_setMotionDetectionThreshold(uint8_t threshold) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_MOT_THR, threshold); +} + +// MOT_DUR register + +/** Get motion detection event duration threshold. + * This register configures the duration counter threshold for Motion interrupt + * generation. The duration counter ticks at 1 kHz, therefore MOT_DUR has a unit + * of 1LSB = 1ms. The Motion detection duration counter increments when the + * absolute value of any of the accelerometer measurements exceeds the Motion + * detection threshold (Register 31). The Motion detection interrupt is + * triggered when the Motion detection counter reaches the time count specified + * in this register. + * + * For more details on the Motion detection interrupt, see Section 8.3 of the + * MPU-6000/MPU-6050 Product Specification document. + * + * @return Current motion detection duration threshold value (LSB = 1ms) + * @see MPU6050_RA_MOT_DUR + */ +uint8_t MPU6050_getMotionDetectionDuration() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_MOT_DUR, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set motion detection event duration threshold. + * @param duration New motion detection duration threshold value (LSB = 1ms) + * @see getMotionDetectionDuration() + * @see MPU6050_RA_MOT_DUR + */ +void MPU6050_setMotionDetectionDuration(uint8_t duration) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_MOT_DUR, duration); +} + +// ZRMOT_THR register + +/** Get zero motion detection event acceleration threshold. + * This register configures the detection threshold for Zero Motion interrupt + * generation. The unit of ZRMOT_THR is 1LSB = 2mg. Zero Motion is detected when + * the absolute value of the accelerometer measurements for the 3 axes are each + * less than the detection threshold. This condition increments the Zero Motion + * duration counter (Register 34). The Zero Motion interrupt is triggered when + * the Zero Motion duration counter reaches the time count specified in + * ZRMOT_DUR (Register 34). + * + * Unlike Free Fall or Motion detection, Zero Motion detection triggers an + * interrupt both when Zero Motion is first detected and when Zero Motion is no + * longer detected. + * + * When a zero motion event is detected, a Zero Motion Status will be indicated + * in the MOT_DETECT_STATUS register (Register 97). When a motion-to-zero-motion + * condition is detected, the status bit is set to 1. When a zero-motion-to- + * motion condition is detected, the status bit is set to 0. + * + * For more details on the Zero Motion detection interrupt, see Section 8.4 of + * the MPU-6000/MPU-6050 Product Specification document as well as Registers 56 + * and 58 of this document. + * + * @return Current zero motion detection acceleration threshold value (LSB = 2mg) + * @see MPU6050_RA_ZRMOT_THR + */ +uint8_t MPU6050_getZeroMotionDetectionThreshold() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_ZRMOT_THR, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set zero motion detection event acceleration threshold. + * @param threshold New zero motion detection acceleration threshold value (LSB = 2mg) + * @see getZeroMotionDetectionThreshold() + * @see MPU6050_RA_ZRMOT_THR + */ +void MPU6050_setZeroMotionDetectionThreshold(uint8_t threshold) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_ZRMOT_THR, threshold); +} + +// ZRMOT_DUR register + +/** Get zero motion detection event duration threshold. + * This register configures the duration counter threshold for Zero Motion + * interrupt generation. The duration counter ticks at 16 Hz, therefore + * ZRMOT_DUR has a unit of 1 LSB = 64 ms. The Zero Motion duration counter + * increments while the absolute value of the accelerometer measurements are + * each less than the detection threshold (Register 33). The Zero Motion + * interrupt is triggered when the Zero Motion duration counter reaches the time + * count specified in this register. + * + * For more details on the Zero Motion detection interrupt, see Section 8.4 of + * the MPU-6000/MPU-6050 Product Specification document, as well as Registers 56 + * and 58 of this document. + * + * @return Current zero motion detection duration threshold value (LSB = 64ms) + * @see MPU6050_RA_ZRMOT_DUR + */ +uint8_t MPU6050_getZeroMotionDetectionDuration() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_ZRMOT_DUR, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set zero motion detection event duration threshold. + * @param duration New zero motion detection duration threshold value (LSB = 1ms) + * @see getZeroMotionDetectionDuration() + * @see MPU6050_RA_ZRMOT_DUR + */ +void MPU6050_setZeroMotionDetectionDuration(uint8_t duration) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_ZRMOT_DUR, duration); +} + +// FIFO_EN register + +/** Get temperature FIFO enabled value. + * When set to 1, this bit enables TEMP_OUT_H and TEMP_OUT_L (Registers 65 and + * 66) to be written into the FIFO mpu6050.buffer. + * @return Current temperature FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_getTempFIFOEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_TEMP_FIFO_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set temperature FIFO enabled value. + * @param enabled New temperature FIFO enabled value + * @see getTempFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setTempFIFOEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_TEMP_FIFO_EN_BIT, enabled); +} +/** Get gyroscope X-axis FIFO enabled value. + * When set to 1, this bit enables GYRO_XOUT_H and GYRO_XOUT_L (Registers 67 and + * 68) to be written into the FIFO mpu6050.buffer. + * @return Current gyroscope X-axis FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_getXGyroFIFOEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_XG_FIFO_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set gyroscope X-axis FIFO enabled value. + * @param enabled New gyroscope X-axis FIFO enabled value + * @see getXGyroFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setXGyroFIFOEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_XG_FIFO_EN_BIT, enabled); +} +/** Get gyroscope Y-axis FIFO enabled value. + * When set to 1, this bit enables GYRO_YOUT_H and GYRO_YOUT_L (Registers 69 and + * 70) to be written into the FIFO mpu6050.buffer. + * @return Current gyroscope Y-axis FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_getYGyroFIFOEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_YG_FIFO_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set gyroscope Y-axis FIFO enabled value. + * @param enabled New gyroscope Y-axis FIFO enabled value + * @see getYGyroFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setYGyroFIFOEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_YG_FIFO_EN_BIT, enabled); +} +/** Get gyroscope Z-axis FIFO enabled value. + * When set to 1, this bit enables GYRO_ZOUT_H and GYRO_ZOUT_L (Registers 71 and + * 72) to be written into the FIFO mpu6050.buffer. + * @return Current gyroscope Z-axis FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_getZGyroFIFOEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_ZG_FIFO_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set gyroscope Z-axis FIFO enabled value. + * @param enabled New gyroscope Z-axis FIFO enabled value + * @see getZGyroFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setZGyroFIFOEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_ZG_FIFO_EN_BIT, enabled); +} +/** Get accelerometer FIFO enabled value. + * When set to 1, this bit enables ACCEL_XOUT_H, ACCEL_XOUT_L, ACCEL_YOUT_H, + * ACCEL_YOUT_L, ACCEL_ZOUT_H, and ACCEL_ZOUT_L (Registers 59 to 64) to be + * written into the FIFO mpu6050.buffer. + * @return Current accelerometer FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_getAccelFIFOEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_ACCEL_FIFO_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set accelerometer FIFO enabled value. + * @param enabled New accelerometer FIFO enabled value + * @see getAccelFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setAccelFIFOEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_ACCEL_FIFO_EN_BIT, enabled); +} +/** Get Slave 2 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 2 to be written into the FIFO mpu6050.buffer. + * @return Current Slave 2 FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_getSlave2FIFOEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV2_FIFO_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Slave 2 FIFO enabled value. + * @param enabled New Slave 2 FIFO enabled value + * @see getSlave2FIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setSlave2FIFOEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV2_FIFO_EN_BIT, enabled); +} +/** Get Slave 1 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 1 to be written into the FIFO mpu6050.buffer. + * @return Current Slave 1 FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_getSlave1FIFOEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV1_FIFO_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Slave 1 FIFO enabled value. + * @param enabled New Slave 1 FIFO enabled value + * @see getSlave1FIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setSlave1FIFOEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV1_FIFO_EN_BIT, enabled); +} +/** Get Slave 0 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 0 to be written into the FIFO mpu6050.buffer. + * @return Current Slave 0 FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_getSlave0FIFOEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV0_FIFO_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Slave 0 FIFO enabled value. + * @param enabled New Slave 0 FIFO enabled value + * @see getSlave0FIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setSlave0FIFOEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV0_FIFO_EN_BIT, enabled); +} + +// I2C_MST_CTRL register + +/** Get multi-master enabled value. + * Multi-master capability allows multiple I2C masters to operate on the same + * bus. In circuits where multi-master capability is required, set MULT_MST_EN + * to 1. This will increase current drawn by approximately 30uA. + * + * In circuits where multi-master capability is required, the state of the I2C + * bus must always be monitored by each separate I2C Master. Before an I2C + * Master can assume arbitration of the bus, it must first confirm that no other + * I2C Master has arbitration of the bus. When MULT_MST_EN is set to 1, the + * MPU-60X0's bus arbitration detection logic is turned on, enabling it to + * detect when the bus is available. + * + * @return Current multi-master enabled value + * @see MPU6050_RA_I2C_MST_CTRL + */ +bool MPU6050_getMultiMasterEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_MULT_MST_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set multi-master enabled value. + * @param enabled New multi-master enabled value + * @see getMultiMasterEnabled() + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050_setMultiMasterEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_MULT_MST_EN_BIT, enabled); +} +/** Get wait-for-external-sensor-data enabled value. + * When the WAIT_FOR_ES bit is set to 1, the Data Ready interrupt will be + * delayed until External Sensor data from the Slave Devices are loaded into the + * EXT_SENS_DATA registers. This is used to ensure that both the internal sensor + * data (i.e. from gyro and accel) and external sensor data have been loaded to + * their respective data registers (i.e. the data is synced) when the Data Ready + * interrupt is triggered. + * + * @return Current wait-for-external-sensor-data enabled value + * @see MPU6050_RA_I2C_MST_CTRL + */ +bool MPU6050_getWaitForExternalSensorEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_WAIT_FOR_ES_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set wait-for-external-sensor-data enabled value. + * @param enabled New wait-for-external-sensor-data enabled value + * @see getWaitForExternalSensorEnabled() + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050_setWaitForExternalSensorEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_WAIT_FOR_ES_BIT, enabled); +} +/** Get Slave 3 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 3 to be written into the FIFO mpu6050.buffer. + * @return Current Slave 3 FIFO enabled value + * @see MPU6050_RA_MST_CTRL + */ +bool MPU6050_getSlave3FIFOEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_SLV_3_FIFO_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Slave 3 FIFO enabled value. + * @param enabled New Slave 3 FIFO enabled value + * @see getSlave3FIFOEnabled() + * @see MPU6050_RA_MST_CTRL + */ +void MPU6050_setSlave3FIFOEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_SLV_3_FIFO_EN_BIT, enabled); +} +/** Get slave read/write transition enabled value. + * The I2C_MST_P_NSR bit configures the I2C Master's transition from one slave + * read to the next slave read. If the bit equals 0, there will be a restart + * between reads. If the bit equals 1, there will be a stop followed by a start + * of the following read. When a write transaction follows a read transaction, + * the stop followed by a start of the successive write will be always used. + * + * @return Current slave read/write transition enabled value + * @see MPU6050_RA_I2C_MST_CTRL + */ +bool MPU6050_getSlaveReadWriteTransitionEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_P_NSR_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set slave read/write transition enabled value. + * @param enabled New slave read/write transition enabled value + * @see getSlaveReadWriteTransitionEnabled() + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050_setSlaveReadWriteTransitionEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_P_NSR_BIT, enabled); +} +/** Get I2C master clock speed. + * I2C_MST_CLK is a 4 bit unsigned value which configures a divider on the + * MPU-60X0 internal 8MHz clock. It sets the I2C master clock speed according to + * the following table: + * + *
+ * I2C_MST_CLK | I2C Master Clock Speed | 8MHz Clock Divider
+ * ------------+------------------------+-------------------
+ * 0           | 348kHz                 | 23
+ * 1           | 333kHz                 | 24
+ * 2           | 320kHz                 | 25
+ * 3           | 308kHz                 | 26
+ * 4           | 296kHz                 | 27
+ * 5           | 286kHz                 | 28
+ * 6           | 276kHz                 | 29
+ * 7           | 267kHz                 | 30
+ * 8           | 258kHz                 | 31
+ * 9           | 500kHz                 | 16
+ * 10          | 471kHz                 | 17
+ * 11          | 444kHz                 | 18
+ * 12          | 421kHz                 | 19
+ * 13          | 400kHz                 | 20
+ * 14          | 381kHz                 | 21
+ * 15          | 364kHz                 | 22
+ * 
+ * + * @return Current I2C master clock speed + * @see MPU6050_RA_I2C_MST_CTRL + */ +uint8_t MPU6050_getMasterClockSpeed() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_CLK_BIT, MPU6050_I2C_MST_CLK_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set I2C master clock speed. + * @reparam speed Current I2C master clock speed + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050_setMasterClockSpeed(uint8_t speed) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_CLK_BIT, MPU6050_I2C_MST_CLK_LENGTH, speed); +} + +// I2C_SLV* registers (Slave 0-3) + +/** Get the I2C address of the specified slave (0-3). + * Note that Bit 7 (MSB) controls read/write mode. If Bit 7 is set, it's a read + * operation, and if it is cleared, then it's a write operation. The remaining + * bits (6-0) are the 7-bit device address of the slave device. + * + * In read mode, the result of the read is placed in the lowest available + * EXT_SENS_DATA register. For further information regarding the allocation of + * read results, please refer to the EXT_SENS_DATA register description + * (Registers 73 - 96). + * + * The MPU-6050 supports a total of five slaves, but Slave 4 has unique + * characteristics, and so it has its own functions (getSlave4* and setSlave4*). + * + * I2C data transactions are performed at the Sample Rate, as defined in + * Register 25. The user is responsible for ensuring that I2C data transactions + * to and from each enabled Slave can be completed within a single period of the + * Sample Rate. + * + * The I2C slave access rate can be reduced relative to the Sample Rate. This + * reduced access rate is determined by I2C_MST_DLY (Register 52). Whether a + * slave's access rate is reduced relative to the Sample Rate is determined by + * I2C_MST_DELAY_CTRL (Register 103). + * + * The processing order for the slaves is fixed. The sequence followed for + * processing the slaves is Slave 0, Slave 1, Slave 2, Slave 3 and Slave 4. If a + * particular Slave is disabled it will be skipped. + * + * Each slave can either be accessed at the sample rate or at a reduced sample + * rate. In a case where some slaves are accessed at the Sample Rate and some + * slaves are accessed at the reduced rate, the sequence of accessing the slaves + * (Slave 0 to Slave 4) is still followed. However, the reduced rate slaves will + * be skipped if their access rate dictates that they should not be accessed + * during that particular cycle. For further information regarding the reduced + * access rate, please refer to Register 52. Whether a slave is accessed at the + * Sample Rate or at the reduced rate is determined by the Delay Enable bits in + * Register 103. + * + * @param num Slave number (0-3) + * @return Current address for specified slave + * @see MPU6050_RA_I2C_SLV0_ADDR + */ +uint8_t MPU6050_getSlaveAddress(uint8_t num) { + if (num > 3) return 0; + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_ADDR + num*3, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set the I2C address of the specified slave (0-3). + * @param num Slave number (0-3) + * @param address New address for specified slave + * @see getSlaveAddress() + * @see MPU6050_RA_I2C_SLV0_ADDR + */ +void MPU6050_setSlaveAddress(uint8_t num, uint8_t address) { + if (num > 3) return; + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_ADDR + num*3, address); +} +/** Get the active internal register for the specified slave (0-3). + * Read/write operations for this slave will be done to whatever internal + * register address is stored in this MPU register. + * + * The MPU-6050 supports a total of five slaves, but Slave 4 has unique + * characteristics, and so it has its own functions. + * + * @param num Slave number (0-3) + * @return Current active register for specified slave + * @see MPU6050_RA_I2C_SLV0_REG + */ +uint8_t MPU6050_getSlaveRegister(uint8_t num) { + if (num > 3) return 0; + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_REG + num*3, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set the active internal register for the specified slave (0-3). + * @param num Slave number (0-3) + * @param reg New active register for specified slave + * @see getSlaveRegister() + * @see MPU6050_RA_I2C_SLV0_REG + */ +void MPU6050_setSlaveRegister(uint8_t num, uint8_t reg) { + if (num > 3) return; + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_REG + num*3, reg); +} +/** Get the enabled value for the specified slave (0-3). + * When set to 1, this bit enables Slave 0 for data transfer operations. When + * cleared to 0, this bit disables Slave 0 from data transfer operations. + * @param num Slave number (0-3) + * @return Current enabled value for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +bool MPU6050_getSlaveEnabled(uint8_t num) { + if (num > 3) return 0; + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set the enabled value for the specified slave (0-3). + * @param num Slave number (0-3) + * @param enabled New enabled value for specified slave + * @see getSlaveEnabled() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050_setSlaveEnabled(uint8_t num, bool enabled) { + if (num > 3) return; + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_EN_BIT, enabled); +} +/** Get word pair byte-swapping enabled for the specified slave (0-3). + * When set to 1, this bit enables byte swapping. When byte swapping is enabled, + * the high and low bytes of a word pair are swapped. Please refer to + * I2C_SLV0_GRP for the pairing convention of the word pairs. When cleared to 0, + * bytes transferred to and from Slave 0 will be written to EXT_SENS_DATA + * registers in the order they were transferred. + * + * @param num Slave number (0-3) + * @return Current word pair byte-swapping enabled value for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +bool MPU6050_getSlaveWordByteSwap(uint8_t num) { + if (num > 3) return 0; + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_BYTE_SW_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set word pair byte-swapping enabled for the specified slave (0-3). + * @param num Slave number (0-3) + * @param enabled New word pair byte-swapping enabled value for specified slave + * @see getSlaveWordByteSwap() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050_setSlaveWordByteSwap(uint8_t num, bool enabled) { + if (num > 3) return; + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_BYTE_SW_BIT, enabled); +} +/** Get write mode for the specified slave (0-3). + * When set to 1, the transaction will read or write data only. When cleared to + * 0, the transaction will write a register address prior to reading or writing + * data. This should equal 0 when specifying the register address within the + * Slave device to/from which the ensuing data transaction will take place. + * + * @param num Slave number (0-3) + * @return Current write mode for specified slave (0 = register address + data, 1 = data only) + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +bool MPU6050_getSlaveWriteMode(uint8_t num) { + if (num > 3) return 0; + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_REG_DIS_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set write mode for the specified slave (0-3). + * @param num Slave number (0-3) + * @param mode New write mode for specified slave (0 = register address + data, 1 = data only) + * @see getSlaveWriteMode() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050_setSlaveWriteMode(uint8_t num, bool mode) { + if (num > 3) return; + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_REG_DIS_BIT, mode); +} +/** Get word pair grouping order offset for the specified slave (0-3). + * This sets specifies the grouping order of word pairs received from registers. + * When cleared to 0, bytes from register addresses 0 and 1, 2 and 3, etc (even, + * then odd register addresses) are paired to form a word. When set to 1, bytes + * from register addresses are paired 1 and 2, 3 and 4, etc. (odd, then even + * register addresses) are paired to form a word. + * + * @param num Slave number (0-3) + * @return Current word pair grouping order offset for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +bool MPU6050_getSlaveWordGroupOffset(uint8_t num) { + if (num > 3) return 0; + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_GRP_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set word pair grouping order offset for the specified slave (0-3). + * @param num Slave number (0-3) + * @param enabled New word pair grouping order offset for specified slave + * @see getSlaveWordGroupOffset() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050_setSlaveWordGroupOffset(uint8_t num, bool enabled) { + if (num > 3) return; + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_GRP_BIT, enabled); +} +/** Get number of bytes to read for the specified slave (0-3). + * Specifies the number of bytes transferred to and from Slave 0. Clearing this + * bit to 0 is equivalent to disabling the register by writing 0 to I2C_SLV0_EN. + * @param num Slave number (0-3) + * @return Number of bytes to read for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +uint8_t MPU6050_getSlaveDataLength(uint8_t num) { + if (num > 3) return 0; + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_LEN_BIT, MPU6050_I2C_SLV_LEN_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set number of bytes to read for the specified slave (0-3). + * @param num Slave number (0-3) + * @param length Number of bytes to read for specified slave + * @see getSlaveDataLength() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050_setSlaveDataLength(uint8_t num, uint8_t length) { + if (num > 3) return; + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_LEN_BIT, MPU6050_I2C_SLV_LEN_LENGTH, length); +} + +// I2C_SLV* registers (Slave 4) + +/** Get the I2C address of Slave 4. + * Note that Bit 7 (MSB) controls read/write mode. If Bit 7 is set, it's a read + * operation, and if it is cleared, then it's a write operation. The remaining + * bits (6-0) are the 7-bit device address of the slave device. + * + * @return Current address for Slave 4 + * @see getSlaveAddress() + * @see MPU6050_RA_I2C_SLV4_ADDR + */ +uint8_t MPU6050_getSlave4Address() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_ADDR, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set the I2C address of Slave 4. + * @param address New address for Slave 4 + * @see getSlave4Address() + * @see MPU6050_RA_I2C_SLV4_ADDR + */ +void MPU6050_setSlave4Address(uint8_t address) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_ADDR, address); +} +/** Get the active internal register for the Slave 4. + * Read/write operations for this slave will be done to whatever internal + * register address is stored in this MPU register. + * + * @return Current active register for Slave 4 + * @see MPU6050_RA_I2C_SLV4_REG + */ +uint8_t MPU6050_getSlave4Register() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_REG, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set the active internal register for Slave 4. + * @param reg New active register for Slave 4 + * @see getSlave4Register() + * @see MPU6050_RA_I2C_SLV4_REG + */ +void MPU6050_setSlave4Register(uint8_t reg) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_REG, reg); +} +/** Set new byte to write to Slave 4. + * This register stores the data to be written into the Slave 4. If I2C_SLV4_RW + * is set 1 (set to read), this register has no effect. + * @param data New byte to write to Slave 4 + * @see MPU6050_RA_I2C_SLV4_DO + */ +void MPU6050_setSlave4OutputByte(uint8_t data) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_DO, data); +} +/** Get the enabled value for the Slave 4. + * When set to 1, this bit enables Slave 4 for data transfer operations. When + * cleared to 0, this bit disables Slave 4 from data transfer operations. + * @return Current enabled value for Slave 4 + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +bool MPU6050_getSlave4Enabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set the enabled value for Slave 4. + * @param enabled New enabled value for Slave 4 + * @see getSlave4Enabled() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050_setSlave4Enabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_EN_BIT, enabled); +} +/** Get the enabled value for Slave 4 transaction interrupts. + * When set to 1, this bit enables the generation of an interrupt signal upon + * completion of a Slave 4 transaction. When cleared to 0, this bit disables the + * generation of an interrupt signal upon completion of a Slave 4 transaction. + * The interrupt status can be observed in Register 54. + * + * @return Current enabled value for Slave 4 transaction interrupts. + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +bool MPU6050_getSlave4InterruptEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_INT_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set the enabled value for Slave 4 transaction interrupts. + * @param enabled New enabled value for Slave 4 transaction interrupts. + * @see getSlave4InterruptEnabled() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050_setSlave4InterruptEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_INT_EN_BIT, enabled); +} +/** Get write mode for Slave 4. + * When set to 1, the transaction will read or write data only. When cleared to + * 0, the transaction will write a register address prior to reading or writing + * data. This should equal 0 when specifying the register address within the + * Slave device to/from which the ensuing data transaction will take place. + * + * @return Current write mode for Slave 4 (0 = register address + data, 1 = data only) + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +bool MPU6050_getSlave4WriteMode() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_REG_DIS_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set write mode for the Slave 4. + * @param mode New write mode for Slave 4 (0 = register address + data, 1 = data only) + * @see getSlave4WriteMode() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050_setSlave4WriteMode(bool mode) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_REG_DIS_BIT, mode); +} +/** Get Slave 4 master delay value. + * This configures the reduced access rate of I2C slaves relative to the Sample + * Rate. When a slave's access rate is decreased relative to the Sample Rate, + * the slave is accessed every: + * + * 1 / (1 + I2C_MST_DLY) samples + * + * This base Sample Rate in turn is determined by SMPLRT_DIV (register 25) and + * DLPF_CFG (register 26). Whether a slave's access rate is reduced relative to + * the Sample Rate is determined by I2C_MST_DELAY_CTRL (register 103). For + * further information regarding the Sample Rate, please refer to register 25. + * + * @return Current Slave 4 master delay value + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +uint8_t MPU6050_getSlave4MasterDelay() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_MST_DLY_BIT, MPU6050_I2C_SLV4_MST_DLY_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Slave 4 master delay value. + * @param delay New Slave 4 master delay value + * @see getSlave4MasterDelay() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050_setSlave4MasterDelay(uint8_t delay) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_MST_DLY_BIT, MPU6050_I2C_SLV4_MST_DLY_LENGTH, delay); +} +/** Get last available byte read from Slave 4. + * This register stores the data read from Slave 4. This field is populated + * after a read transaction. + * @return Last available byte read from to Slave 4 + * @see MPU6050_RA_I2C_SLV4_DI + */ +uint8_t MPU6050_getSlate4InputByte() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_DI, mpu6050.buffer); + return mpu6050.buffer[0]; +} + +// I2C_MST_STATUS register + +/** Get FSYNC interrupt status. + * This bit reflects the status of the FSYNC interrupt from an external device + * into the MPU-60X0. This is used as a way to pass an external interrupt + * through the MPU-60X0 to the host application processor. When set to 1, this + * bit will cause an interrupt if FSYNC_INT_EN is asserted in INT_PIN_CFG + * (Register 55). + * @return FSYNC interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_getPassthroughStatus() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_PASS_THROUGH_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Slave 4 transaction done status. + * Automatically sets to 1 when a Slave 4 transaction has completed. This + * triggers an interrupt if the I2C_MST_INT_EN bit in the INT_ENABLE register + * (Register 56) is asserted and if the SLV_4_DONE_INT bit is asserted in the + * I2C_SLV4_CTRL register (Register 52). + * @return Slave 4 transaction done status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_getSlave4IsDone() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV4_DONE_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get master arbitration lost status. + * This bit automatically sets to 1 when the I2C Master has lost arbitration of + * the auxiliary I2C bus (an error condition). This triggers an interrupt if the + * I2C_MST_INT_EN bit in the INT_ENABLE register (Register 56) is asserted. + * @return Master arbitration lost status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_getLostArbitration() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_LOST_ARB_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Slave 4 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 4. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 4 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_getSlave4Nack() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV4_NACK_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Slave 3 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 3. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 3 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_getSlave3Nack() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV3_NACK_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Slave 2 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 2. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 2 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_getSlave2Nack() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV2_NACK_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Slave 1 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 1. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 1 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_getSlave1Nack() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV1_NACK_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Slave 0 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 0. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 0 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_getSlave0Nack() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV0_NACK_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} + +// INT_PIN_CFG register + +/** Get interrupt logic level mode. + * Will be set 0 for active-high, 1 for active-low. + * @return Current interrupt mode (0=active-high, 1=active-low) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_LEVEL_BIT + */ +bool MPU6050_getInterruptMode() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_LEVEL_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set interrupt logic level mode. + * @param mode New interrupt mode (0=active-high, 1=active-low) + * @see getInterruptMode() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_LEVEL_BIT + */ +void MPU6050_setInterruptMode(bool mode) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_LEVEL_BIT, mode); +} +/** Get interrupt drive mode. + * Will be set 0 for push-pull, 1 for open-drain. + * @return Current interrupt drive mode (0=push-pull, 1=open-drain) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_OPEN_BIT + */ +bool MPU6050_getInterruptDrive() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_OPEN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set interrupt drive mode. + * @param drive New interrupt drive mode (0=push-pull, 1=open-drain) + * @see getInterruptDrive() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_OPEN_BIT + */ +void MPU6050_setInterruptDrive(bool drive) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_OPEN_BIT, drive); +} +/** Get interrupt latch mode. + * Will be set 0 for 50us-pulse, 1 for latch-until-int-cleared. + * @return Current latch mode (0=50us-pulse, 1=latch-until-int-cleared) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_LATCH_INT_EN_BIT + */ +bool MPU6050_getInterruptLatch() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_LATCH_INT_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set interrupt latch mode. + * @param latch New latch mode (0=50us-pulse, 1=latch-until-int-cleared) + * @see getInterruptLatch() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_LATCH_INT_EN_BIT + */ +void MPU6050_setInterruptLatch(bool latch) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_LATCH_INT_EN_BIT, latch); +} +/** Get interrupt latch clear mode. + * Will be set 0 for status-read-only, 1 for any-register-read. + * @return Current latch clear mode (0=status-read-only, 1=any-register-read) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_RD_CLEAR_BIT + */ +bool MPU6050_getInterruptLatchClear() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_RD_CLEAR_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set interrupt latch clear mode. + * @param clear New latch clear mode (0=status-read-only, 1=any-register-read) + * @see getInterruptLatchClear() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_RD_CLEAR_BIT + */ +void MPU6050_setInterruptLatchClear(bool clear) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_RD_CLEAR_BIT, clear); +} +/** Get FSYNC interrupt logic level mode. + * @return Current FSYNC interrupt mode (0=active-high, 1=active-low) + * @see getFSyncInterruptMode() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT + */ +bool MPU6050_getFSyncInterruptLevel() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set FSYNC interrupt logic level mode. + * @param mode New FSYNC interrupt mode (0=active-high, 1=active-low) + * @see getFSyncInterruptMode() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT + */ +void MPU6050_setFSyncInterruptLevel(bool level) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT, level); +} +/** Get FSYNC pin interrupt enabled setting. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled setting + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_EN_BIT + */ +bool MPU6050_getFSyncInterruptEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set FSYNC pin interrupt enabled setting. + * @param enabled New FSYNC pin interrupt enabled setting + * @see getFSyncInterruptEnabled() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_EN_BIT + */ +void MPU6050_setFSyncInterruptEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_EN_BIT, enabled); +} +/** Get I2C bypass enabled status. + * When this bit is equal to 1 and I2C_MST_EN (Register 106 bit[5]) is equal to + * 0, the host application processor will be able to directly access the + * auxiliary I2C bus of the MPU-60X0. When this bit is equal to 0, the host + * application processor will not be able to directly access the auxiliary I2C + * bus of the MPU-60X0 regardless of the state of I2C_MST_EN (Register 106 + * bit[5]). + * @return Current I2C bypass enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_I2C_BYPASS_EN_BIT + */ +bool MPU6050_getI2CBypassEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_I2C_BYPASS_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set I2C bypass enabled status. + * When this bit is equal to 1 and I2C_MST_EN (Register 106 bit[5]) is equal to + * 0, the host application processor will be able to directly access the + * auxiliary I2C bus of the MPU-60X0. When this bit is equal to 0, the host + * application processor will not be able to directly access the auxiliary I2C + * bus of the MPU-60X0 regardless of the state of I2C_MST_EN (Register 106 + * bit[5]). + * @param enabled New I2C bypass enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_I2C_BYPASS_EN_BIT + */ +void MPU6050_setI2CBypassEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_I2C_BYPASS_EN_BIT, enabled); +} +/** Get reference clock output enabled status. + * When this bit is equal to 1, a reference clock output is provided at the + * CLKOUT pin. When this bit is equal to 0, the clock output is disabled. For + * further information regarding CLKOUT, please refer to the MPU-60X0 Product + * Specification document. + * @return Current reference clock output enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_CLKOUT_EN_BIT + */ +bool MPU6050_getClockOutputEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_CLKOUT_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set reference clock output enabled status. + * When this bit is equal to 1, a reference clock output is provided at the + * CLKOUT pin. When this bit is equal to 0, the clock output is disabled. For + * further information regarding CLKOUT, please refer to the MPU-60X0 Product + * Specification document. + * @param enabled New reference clock output enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_CLKOUT_EN_BIT + */ +void MPU6050_setClockOutputEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_CLKOUT_EN_BIT, enabled); +} + +// INT_ENABLE register + +/** Get full interrupt enabled status. + * Full register byte for all interrupts, for quick reading. Each bit will be + * set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +uint8_t MPU6050_getIntEnabled() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set full interrupt enabled status. + * Full register byte for all interrupts, for quick reading. Each bit should be + * set 0 for disabled, 1 for enabled. + * @param enabled New interrupt enabled status + * @see getIntFreefallEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +void MPU6050_setIntEnabled(uint8_t enabled) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, enabled); +} +/** Get Free Fall interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +bool MPU6050_getIntFreefallEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FF_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Free Fall interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntFreefallEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +void MPU6050_setIntFreefallEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FF_BIT, enabled); +} +/** Get Motion Detection interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_MOT_BIT + **/ +bool MPU6050_getIntMotionEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_MOT_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Motion Detection interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntMotionEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_MOT_BIT + **/ +void MPU6050_setIntMotionEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_MOT_BIT, enabled); +} +/** Get Zero Motion Detection interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_ZMOT_BIT + **/ +bool MPU6050_getIntZeroMotionEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_ZMOT_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Zero Motion Detection interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntZeroMotionEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_ZMOT_BIT + **/ +void MPU6050_setIntZeroMotionEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_ZMOT_BIT, enabled); +} +/** Get FIFO Buffer Overflow interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT + **/ +bool MPU6050_getIntFIFOBufferOverflowEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set FIFO Buffer Overflow interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntFIFOBufferOverflowEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT + **/ +void MPU6050_setIntFIFOBufferOverflowEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, enabled); +} +/** Get I2C Master interrupt enabled status. + * This enables any of the I2C Master interrupt sources to generate an + * interrupt. Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT + **/ +bool MPU6050_getIntI2CMasterEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_I2C_MST_INT_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set I2C Master interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntI2CMasterEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT + **/ +void MPU6050_setIntI2CMasterEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_I2C_MST_INT_BIT, enabled); +} +/** Get Data Ready interrupt enabled setting. + * This event occurs each time a write operation to all of the sensor registers + * has been completed. Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_DATA_RDY_BIT + */ +bool MPU6050_getIntDataReadyEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DATA_RDY_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Data Ready interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntDataReadyEnabled() + * @see MPU6050_RA_INT_CFG + * @see MPU6050_INTERRUPT_DATA_RDY_BIT + */ +void MPU6050_setIntDataReadyEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DATA_RDY_BIT, enabled); +} + +// INT_STATUS register + +/** Get full set of interrupt status bits. + * These bits clear to 0 after the register has been read. Very useful + * for getting multiple INT statuses, since each single bit read clears + * all of them because it has to read the whole byte. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + */ +uint8_t MPU6050_getIntStatus() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_INT_STATUS, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Free Fall interrupt status. + * This bit automatically sets to 1 when a Free Fall interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_FF_BIT + */ +bool MPU6050_getIntFreefallStatus() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_FF_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Motion Detection interrupt status. + * This bit automatically sets to 1 when a Motion Detection interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_MOT_BIT + */ +bool MPU6050_getIntMotionStatus() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_MOT_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Zero Motion Detection interrupt status. + * This bit automatically sets to 1 when a Zero Motion Detection interrupt has + * been generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_ZMOT_BIT + */ +bool MPU6050_getIntZeroMotionStatus() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_ZMOT_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get FIFO Buffer Overflow interrupt status. + * This bit automatically sets to 1 when a Free Fall interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT + */ +bool MPU6050_getIntFIFOBufferOverflowStatus() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get I2C Master interrupt status. + * This bit automatically sets to 1 when an I2C Master interrupt has been + * generated. For a list of I2C Master interrupts, please refer to Register 54. + * The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT + */ +bool MPU6050_getIntI2CMasterStatus() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_I2C_MST_INT_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Data Ready interrupt status. + * This bit automatically sets to 1 when a Data Ready interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_DATA_RDY_BIT + */ +bool MPU6050_getIntDataReadyStatus() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_DATA_RDY_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} + +// ACCEL_*OUT_* registers + +/** Get raw 9-axis motion sensor readings (accel/gyro/compass). + * FUNCTION NOT FULLY IMPLEMENTED YET. + * @param ax 16-bit signed integer container for accelerometer X-axis value + * @param ay 16-bit signed integer container for accelerometer Y-axis value + * @param az 16-bit signed integer container for accelerometer Z-axis value + * @param gx 16-bit signed integer container for gyroscope X-axis value + * @param gy 16-bit signed integer container for gyroscope Y-axis value + * @param gz 16-bit signed integer container for gyroscope Z-axis value + * @param mx 16-bit signed integer container for magnetometer X-axis value + * @param my 16-bit signed integer container for magnetometer Y-axis value + * @param mz 16-bit signed integer container for magnetometer Z-axis value + * @see getMotion6() + * @see getAcceleration() + * @see getRotation() + * @see MPU6050_RA_ACCEL_XOUT_H + */ +void MPU6050_getMotion9(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz, int16_t* mx, int16_t* my, int16_t* mz) { + MPU6050_getMotion6(ax, ay, az, gx, gy, gz); + // TODO: magnetometer integration +} +/** Get raw 6-axis motion sensor readings (accel/gyro). + * Retrieves all currently available motion sensor values. + * @param ax 16-bit signed integer container for accelerometer X-axis value + * @param ay 16-bit signed integer container for accelerometer Y-axis value + * @param az 16-bit signed integer container for accelerometer Z-axis value + * @param gx 16-bit signed integer container for gyroscope X-axis value + * @param gy 16-bit signed integer container for gyroscope Y-axis value + * @param gz 16-bit signed integer container for gyroscope Z-axis value + * @see getAcceleration() + * @see getRotation() + * @see MPU6050_RA_ACCEL_XOUT_H + */ +void MPU6050_getMotion6(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz) { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ACCEL_XOUT_H, 14, mpu6050.buffer); + *ax = (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; + *ay = (((int16_t)mpu6050.buffer[2]) << 8) | mpu6050.buffer[3]; + *az = (((int16_t)mpu6050.buffer[4]) << 8) | mpu6050.buffer[5]; + *gx = (((int16_t)mpu6050.buffer[8]) << 8) | mpu6050.buffer[9]; + *gy = (((int16_t)mpu6050.buffer[10]) << 8) | mpu6050.buffer[11]; + *gz = (((int16_t)mpu6050.buffer[12]) << 8) | mpu6050.buffer[13]; +} +/** Get 3-axis accelerometer readings. + * These registers store the most recent accelerometer measurements. + * Accelerometer measurements are written to these registers at the Sample Rate + * as defined in Register 25. + * + * The accelerometer measurement registers, along with the temperature + * measurement registers, gyroscope measurement registers, and external sensor + * data registers, are composed of two sets of registers: an internal register + * set and a user-facing read register set. + * + * The data within the accelerometer sensors' internal register set is always + * updated at the Sample Rate. Meanwhile, the user-facing read register set + * duplicates the internal register set's data values whenever the serial + * interface is idle. This guarantees that a burst read of sensor registers will + * read measurements from the same sampling instant. Note that if burst reads + * are not used, the user is responsible for ensuring a set of single byte reads + * correspond to a single sampling instant by checking the Data Ready interrupt. + * + * Each 16-bit accelerometer measurement has a full scale defined in ACCEL_FS + * (Register 28). For each full scale setting, the accelerometers' sensitivity + * per LSB in ACCEL_xOUT is shown in the table below: + * + *
+ * AFS_SEL | Full Scale Range | LSB Sensitivity
+ * --------+------------------+----------------
+ * 0       | +/- 2g           | 8192 LSB/mg
+ * 1       | +/- 4g           | 4096 LSB/mg
+ * 2       | +/- 8g           | 2048 LSB/mg
+ * 3       | +/- 16g          | 1024 LSB/mg
+ * 
+ * + * @param x 16-bit signed integer container for X-axis acceleration + * @param y 16-bit signed integer container for Y-axis acceleration + * @param z 16-bit signed integer container for Z-axis acceleration + * @see MPU6050_RA_GYRO_XOUT_H + */ +void MPU6050_getAcceleration(int16_t* x, int16_t* y, int16_t* z) { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ACCEL_XOUT_H, 6, mpu6050.buffer); + *x = (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; + *y = (((int16_t)mpu6050.buffer[2]) << 8) | mpu6050.buffer[3]; + *z = (((int16_t)mpu6050.buffer[4]) << 8) | mpu6050.buffer[5]; +} +/** Get X-axis accelerometer reading. + * @return X-axis acceleration measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_ACCEL_XOUT_H + */ +int16_t MPU6050_getAccelerationX() { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ACCEL_XOUT_H, 2, mpu6050.buffer); + return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; +} +/** Get Y-axis accelerometer reading. + * @return Y-axis acceleration measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_ACCEL_YOUT_H + */ +int16_t MPU6050_getAccelerationY() { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ACCEL_YOUT_H, 2, mpu6050.buffer); + return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; +} +/** Get Z-axis accelerometer reading. + * @return Z-axis acceleration measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_ACCEL_ZOUT_H + */ +int16_t MPU6050_getAccelerationZ() { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ACCEL_ZOUT_H, 2, mpu6050.buffer); + return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; +} + +// TEMP_OUT_* registers + +/** Get current internal temperature. + * @return Temperature reading in 16-bit 2's complement format + * @see MPU6050_RA_TEMP_OUT_H + */ +int16_t MPU6050_getTemperature() { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_TEMP_OUT_H, 2, mpu6050.buffer); + return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; +} + +// GYRO_*OUT_* registers + +/** Get 3-axis gyroscope readings. + * These gyroscope measurement registers, along with the accelerometer + * measurement registers, temperature measurement registers, and external sensor + * data registers, are composed of two sets of registers: an internal register + * set and a user-facing read register set. + * The data within the gyroscope sensors' internal register set is always + * updated at the Sample Rate. Meanwhile, the user-facing read register set + * duplicates the internal register set's data values whenever the serial + * interface is idle. This guarantees that a burst read of sensor registers will + * read measurements from the same sampling instant. Note that if burst reads + * are not used, the user is responsible for ensuring a set of single byte reads + * correspond to a single sampling instant by checking the Data Ready interrupt. + * + * Each 16-bit gyroscope measurement has a full scale defined in FS_SEL + * (Register 27). For each full scale setting, the gyroscopes' sensitivity per + * LSB in GYRO_xOUT is shown in the table below: + * + *
+ * FS_SEL | Full Scale Range   | LSB Sensitivity
+ * -------+--------------------+----------------
+ * 0      | +/- 250 degrees/s  | 131 LSB/deg/s
+ * 1      | +/- 500 degrees/s  | 65.5 LSB/deg/s
+ * 2      | +/- 1000 degrees/s | 32.8 LSB/deg/s
+ * 3      | +/- 2000 degrees/s | 16.4 LSB/deg/s
+ * 
+ * + * @param x 16-bit signed integer container for X-axis rotation + * @param y 16-bit signed integer container for Y-axis rotation + * @param z 16-bit signed integer container for Z-axis rotation + * @see getMotion6() + * @see MPU6050_RA_GYRO_XOUT_H + */ +void MPU6050_getRotation(int16_t* x, int16_t* y, int16_t* z) { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_GYRO_XOUT_H, 6, mpu6050.buffer); + *x = (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; + *y = (((int16_t)mpu6050.buffer[2]) << 8) | mpu6050.buffer[3]; + *z = (((int16_t)mpu6050.buffer[4]) << 8) | mpu6050.buffer[5]; +} +/** Get X-axis gyroscope reading. + * @return X-axis rotation measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_GYRO_XOUT_H + */ +int16_t MPU6050_getRotationX() { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_GYRO_XOUT_H, 2, mpu6050.buffer); + return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; +} +/** Get Y-axis gyroscope reading. + * @return Y-axis rotation measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_GYRO_YOUT_H + */ +int16_t MPU6050_getRotationY() { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_GYRO_YOUT_H, 2, mpu6050.buffer); + return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; +} +/** Get Z-axis gyroscope reading. + * @return Z-axis rotation measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_GYRO_ZOUT_H + */ +int16_t MPU6050_getRotationZ() { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_GYRO_ZOUT_H, 2, mpu6050.buffer); + return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; +} + +// EXT_SENS_DATA_* registers + +/** Read single byte from external sensor data register. + * These registers store data read from external sensors by the Slave 0, 1, 2, + * and 3 on the auxiliary I2C interface. Data read by Slave 4 is stored in + * I2C_SLV4_DI (Register 53). + * + * External sensor data is written to these registers at the Sample Rate as + * defined in Register 25. This access rate can be reduced by using the Slave + * Delay Enable registers (Register 103). + * + * External sensor data registers, along with the gyroscope measurement + * registers, accelerometer measurement registers, and temperature measurement + * registers, are composed of two sets of registers: an internal register set + * and a user-facing read register set. + * + * The data within the external sensors' internal register set is always updated + * at the Sample Rate (or the reduced access rate) whenever the serial interface + * is idle. This guarantees that a burst read of sensor registers will read + * measurements from the same sampling instant. Note that if burst reads are not + * used, the user is responsible for ensuring a set of single byte reads + * correspond to a single sampling instant by checking the Data Ready interrupt. + * + * Data is placed in these external sensor data registers according to + * I2C_SLV0_CTRL, I2C_SLV1_CTRL, I2C_SLV2_CTRL, and I2C_SLV3_CTRL (Registers 39, + * 42, 45, and 48). When more than zero bytes are read (I2C_SLVx_LEN > 0) from + * an enabled slave (I2C_SLVx_EN = 1), the slave is read at the Sample Rate (as + * defined in Register 25) or delayed rate (if specified in Register 52 and + * 103). During each Sample cycle, slave reads are performed in order of Slave + * number. If all slaves are enabled with more than zero bytes to be read, the + * order will be Slave 0, followed by Slave 1, Slave 2, and Slave 3. + * + * Each enabled slave will have EXT_SENS_DATA registers associated with it by + * number of bytes read (I2C_SLVx_LEN) in order of slave number, starting from + * EXT_SENS_DATA_00. Note that this means enabling or disabling a slave may + * change the higher numbered slaves' associated registers. Furthermore, if + * fewer total bytes are being read from the external sensors as a result of + * such a change, then the data remaining in the registers which no longer have + * an associated slave device (i.e. high numbered registers) will remain in + * these previously allocated registers unless reset. + * + * If the sum of the read lengths of all SLVx transactions exceed the number of + * available EXT_SENS_DATA registers, the excess bytes will be dropped. There + * are 24 EXT_SENS_DATA registers and hence the total read lengths between all + * the slaves cannot be greater than 24 or some bytes will be lost. + * + * Note: Slave 4's behavior is distinct from that of Slaves 0-3. For further + * information regarding the characteristics of Slave 4, please refer to + * Registers 49 to 53. + * + * EXAMPLE: + * Suppose that Slave 0 is enabled with 4 bytes to be read (I2C_SLV0_EN = 1 and + * I2C_SLV0_LEN = 4) while Slave 1 is enabled with 2 bytes to be read so that + * I2C_SLV1_EN = 1 and I2C_SLV1_LEN = 2. In such a situation, EXT_SENS_DATA _00 + * through _03 will be associated with Slave 0, while EXT_SENS_DATA _04 and 05 + * will be associated with Slave 1. If Slave 2 is enabled as well, registers + * starting from EXT_SENS_DATA_06 will be allocated to Slave 2. + * + * If Slave 2 is disabled while Slave 3 is enabled in this same situation, then + * registers starting from EXT_SENS_DATA_06 will be allocated to Slave 3 + * instead. + * + * REGISTER ALLOCATION FOR DYNAMIC DISABLE VS. NORMAL DISABLE: + * If a slave is disabled at any time, the space initially allocated to the + * slave in the EXT_SENS_DATA register, will remain associated with that slave. + * This is to avoid dynamic adjustment of the register allocation. + * + * The allocation of the EXT_SENS_DATA registers is recomputed only when (1) all + * slaves are disabled, or (2) the I2C_MST_RST bit is set (Register 106). + * + * This above is also true if one of the slaves gets NACKed and stops + * functioning. + * + * @param position Starting position (0-23) + * @return Byte read from register + */ +uint8_t MPU6050_getExternalSensorByte(int position) { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Read word (2 bytes) from external sensor data registers. + * @param position Starting position (0-21) + * @return Word read from register + * @see getExternalSensorByte() + */ +uint16_t MPU6050_getExternalSensorWord(int position) { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, 2, mpu6050.buffer); + return (((uint16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; +} +/** Read double word (4 bytes) from external sensor data registers. + * @param position Starting position (0-20) + * @return Double word read from registers + * @see getExternalSensorByte() + */ +uint32_t MPU6050_getExternalSensorDWord(int position) { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, 4, mpu6050.buffer); + return (((uint32_t)mpu6050.buffer[0]) << 24) | (((uint32_t)mpu6050.buffer[1]) << 16) | (((uint16_t)mpu6050.buffer[2]) << 8) | mpu6050.buffer[3]; +} + +// MOT_DETECT_STATUS register + +/** Get X-axis negative motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_XNEG_BIT + */ +bool MPU6050_getXNegMotionDetected() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_XNEG_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get X-axis positive motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_XPOS_BIT + */ +bool MPU6050_getXPosMotionDetected() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_XPOS_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Y-axis negative motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_YNEG_BIT + */ +bool MPU6050_getYNegMotionDetected() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_YNEG_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Y-axis positive motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_YPOS_BIT + */ +bool MPU6050_getYPosMotionDetected() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_YPOS_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Z-axis negative motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_ZNEG_BIT + */ +bool MPU6050_getZNegMotionDetected() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZNEG_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Z-axis positive motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_ZPOS_BIT + */ +bool MPU6050_getZPosMotionDetected() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZPOS_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get zero motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_ZRMOT_BIT + */ +bool MPU6050_getZeroMotionDetected() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZRMOT_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} + +// I2C_SLV*_DO register + +/** Write byte to Data Output container for specified slave. + * This register holds the output data written into Slave when Slave is set to + * write mode. For further information regarding Slave control, please + * refer to Registers 37 to 39 and immediately following. + * @param num Slave number (0-3) + * @param data Byte to write + * @see MPU6050_RA_I2C_SLV0_DO + */ +void MPU6050_setSlaveOutputByte(uint8_t num, uint8_t data) { + if (num > 3) return; + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_DO + num, data); +} + +// I2C_MST_DELAY_CTRL register + +/** Get external data shadow delay enabled status. + * This register is used to specify the timing of external sensor data + * shadowing. When DELAY_ES_SHADOW is set to 1, shadowing of external + * sensor data is delayed until all data has been received. + * @return Current external data shadow delay enabled status. + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT + */ +bool MPU6050_getExternalShadowDelayEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set external data shadow delay enabled status. + * @param enabled New external data shadow delay enabled status. + * @see getExternalShadowDelayEnabled() + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT + */ +void MPU6050_setExternalShadowDelayEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT, enabled); +} +/** Get slave delay enabled status. + * When a particular slave delay is enabled, the rate of access for the that + * slave device is reduced. When a slave's access rate is decreased relative to + * the Sample Rate, the slave is accessed every: + * + * 1 / (1 + I2C_MST_DLY) Samples + * + * This base Sample Rate in turn is determined by SMPLRT_DIV (register * 25) + * and DLPF_CFG (register 26). + * + * For further information regarding I2C_MST_DLY, please refer to register 52. + * For further information regarding the Sample Rate, please refer to register 25. + * + * @param num Slave number (0-4) + * @return Current slave delay enabled status. + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT + */ +bool MPU6050_getSlaveDelayEnabled(uint8_t num) { + // MPU6050_DELAYCTRL_I2C_SLV4_DLY_EN_BIT is 4, SLV3 is 3, etc. + if (num > 4) return 0; + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, num, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set slave delay enabled status. + * @param num Slave number (0-4) + * @param enabled New slave delay enabled status. + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT + */ +void MPU6050_setSlaveDelayEnabled(uint8_t num, bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, num, enabled); +} + +// SIGNAL_PATH_RESET register + +/** Reset gyroscope signal path. + * The reset will revert the signal path analog to digital converters and + * filters to their power up configurations. + * @see MPU6050_RA_SIGNAL_PATH_RESET + * @see MPU6050_PATHRESET_GYRO_RESET_BIT + */ +void MPU6050_resetGyroscopePath() { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_GYRO_RESET_BIT, true); +} +/** Reset accelerometer signal path. + * The reset will revert the signal path analog to digital converters and + * filters to their power up configurations. + * @see MPU6050_RA_SIGNAL_PATH_RESET + * @see MPU6050_PATHRESET_ACCEL_RESET_BIT + */ +void MPU6050_resetAccelerometerPath() { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_ACCEL_RESET_BIT, true); +} +/** Reset temperature sensor signal path. + * The reset will revert the signal path analog to digital converters and + * filters to their power up configurations. + * @see MPU6050_RA_SIGNAL_PATH_RESET + * @see MPU6050_PATHRESET_TEMP_RESET_BIT + */ +void MPU6050_resetTemperaturePath() { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_TEMP_RESET_BIT, true); +} + +// MOT_DETECT_CTRL register + +/** Get accelerometer power-on delay. + * The accelerometer data path provides samples to the sensor registers, Motion + * detection, Zero Motion detection, and Free Fall detection modules. The + * signal path contains filters which must be flushed on wake-up with new + * samples before the detection modules begin operations. The default wake-up + * delay, of 4ms can be lengthened by up to 3ms. This additional delay is + * specified in ACCEL_ON_DELAY in units of 1 LSB = 1 ms. The user may select + * any value above zero unless instructed otherwise by InvenSense. Please refer + * to Section 8 of the MPU-6000/MPU-6050 Product Specification document for + * further information regarding the detection modules. + * @return Current accelerometer power-on delay + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_ACCEL_ON_DELAY_BIT + */ +uint8_t MPU6050_getAccelerometerPowerOnDelay() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_ACCEL_ON_DELAY_BIT, MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set accelerometer power-on delay. + * @param delay New accelerometer power-on delay (0-3) + * @see getAccelerometerPowerOnDelay() + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_ACCEL_ON_DELAY_BIT + */ +void MPU6050_setAccelerometerPowerOnDelay(uint8_t delay) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_ACCEL_ON_DELAY_BIT, MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH, delay); +} +/** Get Free Fall detection counter decrement configuration. + * Detection is registered by the Free Fall detection module after accelerometer + * measurements meet their respective threshold conditions over a specified + * number of samples. When the threshold conditions are met, the corresponding + * detection counter increments by 1. The user may control the rate at which the + * detection counter decrements when the threshold condition is not met by + * configuring FF_COUNT. The decrement rate can be set according to the + * following table: + * + *
+ * FF_COUNT | Counter Decrement
+ * ---------+------------------
+ * 0        | Reset
+ * 1        | 1
+ * 2        | 2
+ * 3        | 4
+ * 
+ * + * When FF_COUNT is configured to 0 (reset), any non-qualifying sample will + * reset the counter to 0. For further information on Free Fall detection, + * please refer to Registers 29 to 32. + * + * @return Current decrement configuration + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_FF_COUNT_BIT + */ +uint8_t MPU6050_getFreefallDetectionCounterDecrement() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_FF_COUNT_BIT, MPU6050_DETECT_FF_COUNT_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Free Fall detection counter decrement configuration. + * @param decrement New decrement configuration value + * @see getFreefallDetectionCounterDecrement() + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_FF_COUNT_BIT + */ +void MPU6050_setFreefallDetectionCounterDecrement(uint8_t decrement) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_FF_COUNT_BIT, MPU6050_DETECT_FF_COUNT_LENGTH, decrement); +} +/** Get Motion detection counter decrement configuration. + * Detection is registered by the Motion detection module after accelerometer + * measurements meet their respective threshold conditions over a specified + * number of samples. When the threshold conditions are met, the corresponding + * detection counter increments by 1. The user may control the rate at which the + * detection counter decrements when the threshold condition is not met by + * configuring MOT_COUNT. The decrement rate can be set according to the + * following table: + * + *
+ * MOT_COUNT | Counter Decrement
+ * ----------+------------------
+ * 0         | Reset
+ * 1         | 1
+ * 2         | 2
+ * 3         | 4
+ * 
+ * + * When MOT_COUNT is configured to 0 (reset), any non-qualifying sample will + * reset the counter to 0. For further information on Motion detection, + * please refer to Registers 29 to 32. + * + */ +uint8_t MPU6050_getMotionDetectionCounterDecrement() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_MOT_COUNT_BIT, MPU6050_DETECT_MOT_COUNT_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Motion detection counter decrement configuration. + * @param decrement New decrement configuration value + * @see getMotionDetectionCounterDecrement() + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_MOT_COUNT_BIT + */ +void MPU6050_setMotionDetectionCounterDecrement(uint8_t decrement) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_MOT_COUNT_BIT, MPU6050_DETECT_MOT_COUNT_LENGTH, decrement); +} + +// USER_CTRL register + +/** Get FIFO enabled status. + * When this bit is set to 0, the FIFO mpu6050.buffer is disabled. The FIFO mpu6050.buffer + * cannot be written to or read from while disabled. The FIFO mpu6050.buffer's state + * does not change unless the MPU-60X0 is power cycled. + * @return Current FIFO enabled status + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_FIFO_EN_BIT + */ +bool MPU6050_getFIFOEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set FIFO enabled status. + * @param enabled New FIFO enabled status + * @see getFIFOEnabled() + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_FIFO_EN_BIT + */ +void MPU6050_setFIFOEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_EN_BIT, enabled); +} +/** Get I2C Master Mode enabled status. + * When this mode is enabled, the MPU-60X0 acts as the I2C Master to the + * external sensor slave devices on the auxiliary I2C bus. When this bit is + * cleared to 0, the auxiliary I2C bus lines (AUX_DA and AUX_CL) are logically + * driven by the primary I2C bus (SDA and SCL). This is a precondition to + * enabling Bypass Mode. For further information regarding Bypass Mode, please + * refer to Register 55. + * @return Current I2C Master Mode enabled status + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_I2C_MST_EN_BIT + */ +bool MPU6050_getI2CMasterModeEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set I2C Master Mode enabled status. + * @param enabled New I2C Master Mode enabled status + * @see getI2CMasterModeEnabled() + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_I2C_MST_EN_BIT + */ +void MPU6050_setI2CMasterModeEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_EN_BIT, enabled); +} +/** Switch from I2C to SPI mode (MPU-6000 only) + * If this is set, the primary SPI interface will be enabled in place of the + * disabled primary I2C interface. + */ +void MPU6050_switchSPIEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_IF_DIS_BIT, enabled); +} +/** Reset the FIFO. + * This bit resets the FIFO mpu6050.buffer when set to 1 while FIFO_EN equals 0. This + * bit automatically clears to 0 after the reset has been triggered. + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_FIFO_RESET_BIT + */ +void MPU6050_resetFIFO() { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_RESET_BIT, true); +} +/** Reset the I2C Master. + * This bit resets the I2C Master when set to 1 while I2C_MST_EN equals 0. + * This bit automatically clears to 0 after the reset has been triggered. + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_I2C_MST_RESET_BIT + */ +void MPU6050_resetI2CMaster() { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_RESET_BIT, true); +} +/** Reset all sensor registers and signal paths. + * When set to 1, this bit resets the signal paths for all sensors (gyroscopes, + * accelerometers, and temperature sensor). This operation will also clear the + * sensor registers. This bit automatically clears to 0 after the reset has been + * triggered. + * + * When resetting only the signal path (and not the sensor registers), please + * use Register 104, SIGNAL_PATH_RESET. + * + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_SIG_COND_RESET_BIT + */ +void MPU6050_resetSensors() { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_SIG_COND_RESET_BIT, true); +} + +// PWR_MGMT_1 register + +/** Trigger a full device reset. + * A small delay of ~50ms may be desirable after triggering a reset. + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_DEVICE_RESET_BIT + */ +void MPU6050_reset() { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_DEVICE_RESET_BIT, true); +} +/** Get sleep mode status. + * Setting the SLEEP bit in the register puts the device into very low power + * sleep mode. In this mode, only the serial interface and internal registers + * remain active, allowing for a very low standby current. Clearing this bit + * puts the device back into normal mode. To save power, the individual standby + * selections for each of the gyros should be used if any gyro axis is not used + * by the application. + * @return Current sleep mode enabled status + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_SLEEP_BIT + */ +bool MPU6050_getSleepEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set sleep mode status. + * @param enabled New sleep mode enabled status + * @see getSleepEnabled() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_SLEEP_BIT + */ +void MPU6050_setSleepEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, enabled); +} +/** Get wake cycle enabled status. + * When this bit is set to 1 and SLEEP is disabled, the MPU-60X0 will cycle + * between sleep mode and waking up to take a single sample of data from active + * sensors at a rate determined by LP_WAKE_CTRL (register 108). + * @return Current sleep mode enabled status + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CYCLE_BIT + */ +bool MPU6050_getWakeCycleEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CYCLE_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set wake cycle enabled status. + * @param enabled New sleep mode enabled status + * @see getWakeCycleEnabled() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CYCLE_BIT + */ +void MPU6050_setWakeCycleEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CYCLE_BIT, enabled); +} +/** Get temperature sensor enabled status. + * Control the usage of the internal temperature sensor. + * + * Note: this register stores the *disabled* value, but for consistency with the + * rest of the code, the function is named and used with standard true/false + * values to indicate whether the sensor is enabled or disabled, respectively. + * + * @return Current temperature sensor enabled status + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_TEMP_DIS_BIT + */ +bool MPU6050_getTempSensorEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_TEMP_DIS_BIT, mpu6050.buffer); + return mpu6050.buffer[0] == 0; // 1 is actually disabled here +} +/** Set temperature sensor enabled status. + * Note: this register stores the *disabled* value, but for consistency with the + * rest of the code, the function is named and used with standard true/false + * values to indicate whether the sensor is enabled or disabled, respectively. + * + * @param enabled New temperature sensor enabled status + * @see getTempSensorEnabled() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_TEMP_DIS_BIT + */ +void MPU6050_setTempSensorEnabled(bool enabled) { + // 1 is actually disabled here + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_TEMP_DIS_BIT, !enabled); +} +/** Get clock source setting. + * @return Current clock source setting + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CLKSEL_BIT + * @see MPU6050_PWR1_CLKSEL_LENGTH + */ +uint8_t MPU6050_getClockSource() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set clock source setting. + * An internal 8MHz oscillator, gyroscope based clock, or external sources can + * be selected as the MPU-60X0 clock source. When the internal 8 MHz oscillator + * or an external source is chosen as the clock source, the MPU-60X0 can operate + * in low power modes with the gyroscopes disabled. + * + * Upon power up, the MPU-60X0 clock source defaults to the internal oscillator. + * However, it is highly recommended that the device be configured to use one of + * the gyroscopes (or an external clock source) as the clock reference for + * improved stability. The clock source can be selected according to the following table: + * + *
+ * CLK_SEL | Clock Source
+ * --------+--------------------------------------
+ * 0       | Internal oscillator
+ * 1       | PLL with X Gyro reference
+ * 2       | PLL with Y Gyro reference
+ * 3       | PLL with Z Gyro reference
+ * 4       | PLL with external 32.768kHz reference
+ * 5       | PLL with external 19.2MHz reference
+ * 6       | Reserved
+ * 7       | Stops the clock and keeps the timing generator in reset
+ * 
+ * + * @param source New clock source setting + * @see getClockSource() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CLKSEL_BIT + * @see MPU6050_PWR1_CLKSEL_LENGTH + */ +void MPU6050_setClockSource(uint8_t source) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, source); +} + +// PWR_MGMT_2 register + +/** Get wake frequency in Accel-Only Low Power Mode. + * The MPU-60X0 can be put into Accerlerometer Only Low Power Mode by setting + * PWRSEL to 1 in the Power Management 1 register (Register 107). In this mode, + * the device will power off all devices except for the primary I2C interface, + * waking only the accelerometer at fixed intervals to take a single + * measurement. The frequency of wake-ups can be configured with LP_WAKE_CTRL + * as shown below: + * + *
+ * LP_WAKE_CTRL | Wake-up Frequency
+ * -------------+------------------
+ * 0            | 1.25 Hz
+ * 1            | 2.5 Hz
+ * 2            | 5 Hz
+ * 3            | 10 Hz
+ * 
+ *
+ * For further information regarding the MPU-60X0's power modes, please refer to
+ * Register 107.
+ *
+ * @return Current wake frequency
+ * @see MPU6050_RA_PWR_MGMT_2
+ */
+uint8_t MPU6050_getWakeFrequency() {
+    I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_LP_WAKE_CTRL_BIT, MPU6050_PWR2_LP_WAKE_CTRL_LENGTH, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+/** Set wake frequency in Accel-Only Low Power Mode.
+ * @param frequency New wake frequency
+ * @see MPU6050_RA_PWR_MGMT_2
+ */
+void MPU6050_setWakeFrequency(uint8_t frequency) {
+    I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_LP_WAKE_CTRL_BIT, MPU6050_PWR2_LP_WAKE_CTRL_LENGTH, frequency);
+}
+
+/** Get X-axis accelerometer standby enabled status.
+ * If enabled, the X-axis will not gather or report data (or use power).
+ * @return Current X-axis standby enabled status
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_XA_BIT
+ */
+bool MPU6050_getStandbyXAccelEnabled() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XA_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+/** Set X-axis accelerometer standby enabled status.
+ * @param New X-axis standby enabled status
+ * @see getStandbyXAccelEnabled()
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_XA_BIT
+ */
+void MPU6050_setStandbyXAccelEnabled(bool enabled) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XA_BIT, enabled);
+}
+/** Get Y-axis accelerometer standby enabled status.
+ * If enabled, the Y-axis will not gather or report data (or use power).
+ * @return Current Y-axis standby enabled status
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_YA_BIT
+ */
+bool MPU6050_getStandbyYAccelEnabled() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YA_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+/** Set Y-axis accelerometer standby enabled status.
+ * @param New Y-axis standby enabled status
+ * @see getStandbyYAccelEnabled()
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_YA_BIT
+ */
+void MPU6050_setStandbyYAccelEnabled(bool enabled) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YA_BIT, enabled);
+}
+/** Get Z-axis accelerometer standby enabled status.
+ * If enabled, the Z-axis will not gather or report data (or use power).
+ * @return Current Z-axis standby enabled status
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_ZA_BIT
+ */
+bool MPU6050_getStandbyZAccelEnabled() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZA_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+/** Set Z-axis accelerometer standby enabled status.
+ * @param New Z-axis standby enabled status
+ * @see getStandbyZAccelEnabled()
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_ZA_BIT
+ */
+void MPU6050_setStandbyZAccelEnabled(bool enabled) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZA_BIT, enabled);
+}
+/** Get X-axis gyroscope standby enabled status.
+ * If enabled, the X-axis will not gather or report data (or use power).
+ * @return Current X-axis standby enabled status
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_XG_BIT
+ */
+bool MPU6050_getStandbyXGyroEnabled() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XG_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+/** Set X-axis gyroscope standby enabled status.
+ * @param New X-axis standby enabled status
+ * @see getStandbyXGyroEnabled()
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_XG_BIT
+ */
+void MPU6050_setStandbyXGyroEnabled(bool enabled) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XG_BIT, enabled);
+}
+/** Get Y-axis gyroscope standby enabled status.
+ * If enabled, the Y-axis will not gather or report data (or use power).
+ * @return Current Y-axis standby enabled status
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_YG_BIT
+ */
+bool MPU6050_getStandbyYGyroEnabled() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YG_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+/** Set Y-axis gyroscope standby enabled status.
+ * @param New Y-axis standby enabled status
+ * @see getStandbyYGyroEnabled()
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_YG_BIT
+ */
+void MPU6050_setStandbyYGyroEnabled(bool enabled) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YG_BIT, enabled);
+}
+/** Get Z-axis gyroscope standby enabled status.
+ * If enabled, the Z-axis will not gather or report data (or use power).
+ * @return Current Z-axis standby enabled status
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_ZG_BIT
+ */
+bool MPU6050_getStandbyZGyroEnabled() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZG_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+/** Set Z-axis gyroscope standby enabled status.
+ * @param New Z-axis standby enabled status
+ * @see getStandbyZGyroEnabled()
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_ZG_BIT
+ */
+void MPU6050_setStandbyZGyroEnabled(bool enabled) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZG_BIT, enabled);
+}
+
+// FIFO_COUNT* registers
+
+/** Get current FIFO mpu6050.buffer size.
+ * This value indicates the number of bytes stored in the FIFO mpu6050.buffer. This
+ * number is in turn the number of bytes that can be read from the FIFO mpu6050.buffer
+ * and it is directly proportional to the number of samples available given the
+ * set of sensor data bound to be stored in the FIFO (register 35 and 36).
+ * @return Current FIFO mpu6050.buffer size
+ */
+uint16_t MPU6050_getFIFOCount() {
+    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_FIFO_COUNTH, 2, mpu6050.buffer);
+    return (((uint16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+}
+
+// FIFO_R_W register
+
+/** Get byte from FIFO mpu6050.buffer.
+ * This register is used to read and write data from the FIFO mpu6050.buffer. Data is
+ * written to the FIFO in order of register number (from lowest to highest). If
+ * all the FIFO enable flags (see below) are enabled and all External Sensor
+ * Data registers (Registers 73 to 96) are associated with a Slave device, the
+ * contents of registers 59 through 96 will be written in order at the Sample
+ * Rate.
+ *
+ * The contents of the sensor data registers (Registers 59 to 96) are written
+ * into the FIFO mpu6050.buffer when their corresponding FIFO enable flags are set to 1
+ * in FIFO_EN (Register 35). An additional flag for the sensor data registers
+ * associated with I2C Slave 3 can be found in I2C_MST_CTRL (Register 36).
+ *
+ * If the FIFO mpu6050.buffer has overflowed, the status bit FIFO_OFLOW_INT is
+ * automatically set to 1. This bit is located in INT_STATUS (Register 58).
+ * When the FIFO mpu6050.buffer has overflowed, the oldest data will be lost and new
+ * data will be written to the FIFO.
+ *
+ * If the FIFO mpu6050.buffer is empty, reading this register will return the last byte
+ * that was previously read from the FIFO until new data is available. The user
+ * should check FIFO_COUNT to ensure that the FIFO mpu6050.buffer is not read when
+ * empty.
+ *
+ * @return Byte from FIFO mpu6050.buffer
+ */
+uint8_t MPU6050_getFIFOByte() {
+    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_FIFO_R_W, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_getFIFOBytes(uint8_t *data, uint8_t length) {
+    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_FIFO_R_W, length, data);
+}
+/** Write byte to FIFO mpu6050.buffer.
+ * @see getFIFOByte()
+ * @see MPU6050_RA_FIFO_R_W
+ */
+void MPU6050_setFIFOByte(uint8_t data) {
+    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_FIFO_R_W, data);
+}
+
+// WHO_AM_I register
+
+/** Get Device ID.
+ * This register is used to verify the identity of the device (0b110100, 0x34).
+ * @return Device ID (6 bits only! should be 0x34)
+ * @see MPU6050_RA_WHO_AM_I
+ * @see MPU6050_WHO_AM_I_BIT
+ * @see MPU6050_WHO_AM_I_LENGTH
+ */
+uint8_t MPU6050_getDeviceID() {
+    I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_WHO_AM_I, MPU6050_WHO_AM_I_BIT, MPU6050_WHO_AM_I_LENGTH, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+/** Set Device ID.
+ * Write a new ID into the WHO_AM_I register (no idea why this should ever be
+ * necessary though).
+ * @param id New device ID to set.
+ * @see getDeviceID()
+ * @see MPU6050_RA_WHO_AM_I
+ * @see MPU6050_WHO_AM_I_BIT
+ * @see MPU6050_WHO_AM_I_LENGTH
+ */
+void MPU6050_setDeviceID(uint8_t id) {
+    I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_WHO_AM_I, MPU6050_WHO_AM_I_BIT, MPU6050_WHO_AM_I_LENGTH, id);
+}
+
+// ======== UNDOCUMENTED/DMP REGISTERS/METHODS ========
+
+// XG_OFFS_TC register
+
+uint8_t MPU6050_getOTPBankValid() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OTP_BNK_VLD_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setOTPBankValid(bool enabled) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OTP_BNK_VLD_BIT, enabled);
+}
+int8_t MPU6050_getXGyroOffsetTC() {
+    I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setXGyroOffsetTC(int8_t offset) {
+    I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset);
+}
+
+// YG_OFFS_TC register
+
+int8_t MPU6050_getYGyroOffsetTC() {
+    I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setYGyroOffsetTC(int8_t offset) {
+    I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset);
+}
+
+// ZG_OFFS_TC register
+
+int8_t MPU6050_getZGyroOffsetTC() {
+    I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_ZG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setZGyroOffsetTC(int8_t offset) {
+    I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_ZG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset);
+}
+
+// X_FINE_GAIN register
+
+int8_t MPU6050_getXFineGain() {
+    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_X_FINE_GAIN, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setXFineGain(int8_t gain) {
+    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_X_FINE_GAIN, gain);
+}
+
+// Y_FINE_GAIN register
+
+int8_t MPU6050_getYFineGain() {
+    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_Y_FINE_GAIN, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setYFineGain(int8_t gain) {
+    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_Y_FINE_GAIN, gain);
+}
+
+// Z_FINE_GAIN register
+
+int8_t MPU6050_getZFineGain() {
+    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_Z_FINE_GAIN, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setZFineGain(int8_t gain) {
+    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_Z_FINE_GAIN, gain);
+}
+
+// XA_OFFS_* registers
+
+int16_t MPU6050_getXAccelOffset() {
+    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_XA_OFFS_H, 2, mpu6050.buffer);
+    return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+}
+void MPU6050_setXAccelOffset(int16_t offset) {
+    I2Cdev_writeWord(mpu6050.devAddr, MPU6050_RA_XA_OFFS_H, offset);
+}
+
+// YA_OFFS_* register
+
+int16_t MPU6050_getYAccelOffset() {
+    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_YA_OFFS_H, 2, mpu6050.buffer);
+    return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+}
+void MPU6050_setYAccelOffset(int16_t offset) {
+    I2Cdev_writeWord(mpu6050.devAddr, MPU6050_RA_YA_OFFS_H, offset);
+}
+
+// ZA_OFFS_* register
+
+int16_t MPU6050_getZAccelOffset() {
+    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ZA_OFFS_H, 2, mpu6050.buffer);
+    return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+}
+void MPU6050_setZAccelOffset(int16_t offset) {
+    I2Cdev_writeWord(mpu6050.devAddr, MPU6050_RA_ZA_OFFS_H, offset);
+}
+
+// XG_OFFS_USR* registers
+
+int16_t MPU6050_getXGyroOffset() {
+    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_XG_OFFS_USRH, 2, mpu6050.buffer);
+    return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+}
+void MPU6050_setXGyroOffset(int16_t offset) {
+    I2Cdev_writeWord(mpu6050.devAddr, MPU6050_RA_XG_OFFS_USRH, offset);
+}
+
+// YG_OFFS_USR* register
+
+int16_t MPU6050_getYGyroOffset() {
+    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_YG_OFFS_USRH, 2, mpu6050.buffer);
+    return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+}
+void MPU6050_setYGyroOffset(int16_t offset) {
+    I2Cdev_writeWord(mpu6050.devAddr, MPU6050_RA_YG_OFFS_USRH, offset);
+}
+
+// ZG_OFFS_USR* register
+
+int16_t MPU6050_getZGyroOffset() {
+    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ZG_OFFS_USRH, 2, mpu6050.buffer);
+    return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+}
+void MPU6050_setZGyroOffset(int16_t offset) {
+    I2Cdev_writeWord(mpu6050.devAddr, MPU6050_RA_ZG_OFFS_USRH, offset);
+}
+
+// INT_ENABLE register (DMP functions)
+
+bool MPU6050_getIntPLLReadyEnabled() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setIntPLLReadyEnabled(bool enabled) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, enabled);
+}
+bool MPU6050_getIntDMPEnabled() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DMP_INT_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setIntDMPEnabled(bool enabled) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DMP_INT_BIT, enabled);
+}
+
+// DMP_INT_STATUS
+
+bool MPU6050_getDMPInt5Status() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_5_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+bool MPU6050_getDMPInt4Status() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_4_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+bool MPU6050_getDMPInt3Status() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_3_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+bool MPU6050_getDMPInt2Status() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_2_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+bool MPU6050_getDMPInt1Status() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_1_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+bool MPU6050_getDMPInt0Status() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_0_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+
+// INT_STATUS register (DMP functions)
+
+bool MPU6050_getIntPLLReadyStatus() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+bool MPU6050_getIntDMPStatus() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_DMP_INT_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+
+// USER_CTRL register (DMP functions)
+
+bool MPU6050_getDMPEnabled() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_EN_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setDMPEnabled(bool enabled) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_EN_BIT, enabled);
+}
+void MPU6050_resetDMP() {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_RESET_BIT, true);
+}
+
+// BANK_SEL register
+
+void MPU6050_setMemoryBank(uint8_t bank, bool prefetchEnabled, bool userBank) {
+    bank &= 0x1F;
+    if (userBank) bank |= 0x20;
+    if (prefetchEnabled) bank |= 0x40;
+    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_BANK_SEL, bank);
+}
+
+// MEM_START_ADDR register
+
+void MPU6050_setMemoryStartAddress(uint8_t address) {
+    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_MEM_START_ADDR, address);
+}
+
+// MEM_R_W register
+
+uint8_t MPU6050_readMemoryByte() {
+    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_MEM_R_W, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_writeMemoryByte(uint8_t data) {
+    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_MEM_R_W, data);
+}
+void MPU6050_readMemoryBlock(uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address) {
+    MPU6050_setMemoryBank(bank, false, false);
+    MPU6050_setMemoryStartAddress(address);
+    uint8_t chunkSize;
+    for (uint16_t i = 0; i < dataSize;) {
+        // determine correct chunk size according to bank position and data size
+        chunkSize = MPU6050_DMP_MEMORY_CHUNK_SIZE;
+
+        // make sure we don't go past the data size
+        if (i + chunkSize > dataSize) chunkSize = dataSize - i;
+
+        // make sure this chunk doesn't go past the bank boundary (256 bytes)
+        if (chunkSize > 256 - address) chunkSize = 256 - address;
+
+        // read the chunk of data as specified
+        I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_MEM_R_W, chunkSize, data + i);
+        
+        // increase byte index by [chunkSize]
+        i += chunkSize;
+
+        // uint8_t automatically wraps to 0 at 256
+        address += chunkSize;
+
+        // if we aren't done, update bank (if necessary) and address
+        if (i < dataSize) {
+            if (address == 0) bank++;
+            MPU6050_setMemoryBank(bank, false, false);
+            MPU6050_setMemoryStartAddress(address);
+        }
+    }
+}
+/*bool MPU6050_writeMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address, bool verify, bool useProgMem) {
+    MPU6050_setMemoryBank(bank, false, false);
+    MPU6050_setMemoryStartAddress(address);
+    uint8_t chunkSize;
+    uint8_t *verifyBuffer;
+    uint8_t *progBuffer;
+    uint16_t i;
+    uint8_t j;
+    if (verify) verifyBuffer = (uint8_t *)malloc(MPU6050_DMP_MEMORY_CHUNK_SIZE);
+    if (useProgMem) progBuffer = (uint8_t *)malloc(MPU6050_DMP_MEMORY_CHUNK_SIZE);
+    for (i = 0; i < dataSize;) {
+        // determine correct chunk size according to bank position and data size
+        chunkSize = MPU6050_DMP_MEMORY_CHUNK_SIZE;
+
+        // make sure we don't go past the data size
+        if (i + chunkSize > dataSize) chunkSize = dataSize - i;
+
+        // make sure this chunk doesn't go past the bank boundary (256 bytes)
+        if (chunkSize > 256 - address) chunkSize = 256 - address;
+        
+        if (useProgMem) {
+            // write the chunk of data as specified
+            for (j = 0; j < chunkSize; j++) progBuffer[j] = pgm_read_byte(data + i + j);
+        } else {
+            // write the chunk of data as specified
+            progBuffer = (uint8_t *)data + i;
+        }
+
+        I2Cdev_writeBytes(mpu6050.devAddr, MPU6050_RA_MEM_R_W, chunkSize, progBuffer);
+
+        // verify data if needed
+        if (verify && verifyBuffer) {
+            MPU6050_setMemoryBank(bank, false, false);
+            MPU6050_setMemoryStartAddress(address);
+            I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_MEM_R_W, chunkSize, verifyBuffer);
+            if (memcmp(progBuffer, verifyBuffer, chunkSize) != 0) {
+                //Serial.print("Block write verification error, bank ");
+                //Serial.print(bank, DEC);
+                //Serial.print(", address ");
+                //Serial.print(address, DEC);
+                //Serial.print("!\nExpected:");
+                //for (j = 0; j < chunkSize; j++) {
+                //    Serial.print(" 0x");
+                //    if (progBuffer[j] < 16) Serial.print("0");
+                //    Serial.print(progBuffer[j], HEX);
+                //}
+                //Serial.print("\nReceived:");
+                //for (uint8_t j = 0; j < chunkSize; j++) {
+                //    Serial.print(" 0x");
+                //    if (verifyBuffer[i + j] < 16) Serial.print("0");
+                //    Serial.print(verifyBuffer[i + j], HEX);
+                //}
+                Serial.print("\n");
+                free(verifyBuffer);
+                if (useProgMem) free(progBuffer);
+                return false; // uh oh.
+            }
+        }
+
+        // increase byte index by [chunkSize]
+        i += chunkSize;
+
+        // uint8_t automatically wraps to 0 at 256
+        address += chunkSize;
+
+        // if we aren't done, update bank (if necessary) and address
+        if (i < dataSize) {
+            if (address == 0) bank++;
+            MPU6050_setMemoryBank(bank, false, false);
+            MPU6050_setMemoryStartAddress(address);
+        }
+    }
+    if (verify) free(verifyBuffer);
+    if (useProgMem) free(progBuffer);
+    return true;
+}
+bool MPU6050_writeProgMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address, bool verify) {
+    return MPU6050_writeMemoryBlock(data, dataSize, bank, address, verify, true);
+}
+bool MPU6050_writeDMPConfigurationSet(const uint8_t *data, uint16_t dataSize, bool useProgMem) {
+    uint8_t *progBuffer, success, special;
+    uint16_t i, j;
+    if (useProgMem) {
+        progBuffer = (uint8_t *)malloc(8); // assume 8-byte blocks, realloc later if necessary
+    }
+
+    // config set data is a long string of blocks with the following structure:
+    // [bank] [offset] [length] [byte[0], byte[1], ..., byte[length]]
+    uint8_t bank, offset, length;
+    for (i = 0; i < dataSize;) {
+        if (useProgMem) {
+            bank = pgm_read_byte(data + i++);
+            offset = pgm_read_byte(data + i++);
+            length = pgm_read_byte(data + i++);
+        } else {
+            bank = data[i++];
+            offset = data[i++];
+            length = data[i++];
+        }
+
+        // write data or perform special action
+        if (length > 0) {
+            // regular block of data to write
+            //Serial.print("Writing config block to bank ");
+            //Serial.print(bank);
+            //Serial.print(", offset ");
+            //Serial.print(offset);
+            //Serial.print(", length=");
+            //Serial.println(length);
+            if (useProgMem) {
+                if (sizeof(progBuffer) < length) progBuffer = (uint8_t *)realloc(progBuffer, length);
+                for (j = 0; j < length; j++) progBuffer[j] = pgm_read_byte(data + i + j);
+            } else {
+                progBuffer = (uint8_t *)data + i;
+            }
+            success = MPU6050_writeMemoryBlock(progBuffer, length, bank, offset, true);
+            i += length;
+        } else {
+            // special instruction
+            // NOTE: this kind of behavior (what and when to do certain things)
+            // is totally undocumented. This code is in here based on observed
+            // behavior only, and exactly why (or even whether) it has to be here
+            // is anybody's guess for now.
+            if (useProgMem) {
+                special = pgm_read_byte(data + i++);
+            } else {
+                special = data[i++];
+            }
+            //Serial.print("Special command code ");
+            //Serial.print(special, HEX);
+            //Serial.println(" found...");
+            if (special == 0x01) {
+                // enable DMP-related interrupts
+                
+                //setIntZeroMotionEnabled(true);
+                //setIntFIFOBufferOverflowEnabled(true);
+                //setIntDMPEnabled(true);
+                I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, 0x32);  // single operation
+
+                success = true;
+            } else {
+                // unknown special command
+                success = false;
+            }
+        }
+        
+        if (!success) {
+            if (useProgMem) free(progBuffer);
+            return false; // uh oh
+        }
+    }
+    if (useProgMem) free(progBuffer);
+    return true;
+}
+bool MPU6050_writeProgDMPConfigurationSet(const uint8_t *data, uint16_t dataSize) {
+    return MPU6050_writeDMPConfigurationSet(data, dataSize, true);
+}*/
+
+// DMP_CFG_1 register
+
+uint8_t MPU6050_getDMPConfig1() {
+    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_DMP_CFG_1, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setDMPConfig1(uint8_t config) {
+    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_DMP_CFG_1, config);
+}
+
+// DMP_CFG_2 register
+
+uint8_t MPU6050_getDMPConfig2() {
+    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_DMP_CFG_2, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setDMPConfig2(uint8_t config) {
+    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_DMP_CFG_2, config);
+}
\ No newline at end of file
diff --git a/dsPIC30F/MPU6050/MPU6050.h b/dsPIC30F/MPU6050/MPU6050.h
new file mode 100644
index 00000000..4f35e336
--- /dev/null
+++ b/dsPIC30F/MPU6050/MPU6050.h
@@ -0,0 +1,786 @@
+// I2Cdev library collection - MPU6050 I2C device class
+// Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00)
+// 10/3/2011 by Jeff Rowberg 
+// 11/28/2014 by Marton Sebok 
+//
+// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
+//
+// Changelog:
+//     ...        - ongoing debug release
+//     2014-11-28 - ported to PIC18 peripheral library from Arduino code
+
+// NOTE: THIS IS ONLY A PARIAL RELEASE. THIS DEVICE CLASS IS CURRENTLY UNDERGOING ACTIVE
+// DEVELOPMENT AND IS STILL MISSING SOME IMPORTANT FEATURES. PLEASE KEEP THIS IN MIND IF
+// YOU DECIDE TO USE THIS PARTICULAR CODE FOR ANYTHING.
+
+/* ============================================
+I2Cdev device library code is placed under the MIT license
+Copyright (c) 2012 Jeff Rowberg
+Copyright (c) 2014 Marton Sebok
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+===============================================
+*/
+
+#ifndef _MPU6050_H_
+#define _MPU6050_H_
+
+#include "../I2Cdev/I2Cdev.h"
+
+#if ((defined MPU6050_INCLUDE_DMP_MOTIONAPPS20) || (defined MPU6050_INCLUDE_DMP_MOTIONAPPS41))
+    #error DMP is not supported yet
+#endif
+
+#define MPU6050_ADDRESS_AD0_LOW     0x68 // address pin low (GND), default for InvenSense evaluation board
+#define MPU6050_ADDRESS_AD0_HIGH    0x69 // address pin high (VCC)
+#define MPU6050_DEFAULT_ADDRESS     MPU6050_ADDRESS_AD0_LOW
+
+#define MPU6050_RA_XG_OFFS_TC       0x00 //[7] PWR_MODE, [6:1] XG_OFFS_TC, [0] OTP_BNK_VLD
+#define MPU6050_RA_YG_OFFS_TC       0x01 //[7] PWR_MODE, [6:1] YG_OFFS_TC, [0] OTP_BNK_VLD
+#define MPU6050_RA_ZG_OFFS_TC       0x02 //[7] PWR_MODE, [6:1] ZG_OFFS_TC, [0] OTP_BNK_VLD
+#define MPU6050_RA_X_FINE_GAIN      0x03 //[7:0] X_FINE_GAIN
+#define MPU6050_RA_Y_FINE_GAIN      0x04 //[7:0] Y_FINE_GAIN
+#define MPU6050_RA_Z_FINE_GAIN      0x05 //[7:0] Z_FINE_GAIN
+#define MPU6050_RA_XA_OFFS_H        0x06 //[15:0] XA_OFFS
+#define MPU6050_RA_XA_OFFS_L_TC     0x07
+#define MPU6050_RA_YA_OFFS_H        0x08 //[15:0] YA_OFFS
+#define MPU6050_RA_YA_OFFS_L_TC     0x09
+#define MPU6050_RA_ZA_OFFS_H        0x0A //[15:0] ZA_OFFS
+#define MPU6050_RA_ZA_OFFS_L_TC     0x0B
+#define MPU6050_RA_XG_OFFS_USRH     0x13 //[15:0] XG_OFFS_USR
+#define MPU6050_RA_XG_OFFS_USRL     0x14
+#define MPU6050_RA_YG_OFFS_USRH     0x15 //[15:0] YG_OFFS_USR
+#define MPU6050_RA_YG_OFFS_USRL     0x16
+#define MPU6050_RA_ZG_OFFS_USRH     0x17 //[15:0] ZG_OFFS_USR
+#define MPU6050_RA_ZG_OFFS_USRL     0x18
+#define MPU6050_RA_SMPLRT_DIV       0x19
+#define MPU6050_RA_CONFIG           0x1A
+#define MPU6050_RA_GYRO_CONFIG      0x1B
+#define MPU6050_RA_ACCEL_CONFIG     0x1C
+#define MPU6050_RA_FF_THR           0x1D
+#define MPU6050_RA_FF_DUR           0x1E
+#define MPU6050_RA_MOT_THR          0x1F
+#define MPU6050_RA_MOT_DUR          0x20
+#define MPU6050_RA_ZRMOT_THR        0x21
+#define MPU6050_RA_ZRMOT_DUR        0x22
+#define MPU6050_RA_FIFO_EN          0x23
+#define MPU6050_RA_I2C_MST_CTRL     0x24
+#define MPU6050_RA_I2C_SLV0_ADDR    0x25
+#define MPU6050_RA_I2C_SLV0_REG     0x26
+#define MPU6050_RA_I2C_SLV0_CTRL    0x27
+#define MPU6050_RA_I2C_SLV1_ADDR    0x28
+#define MPU6050_RA_I2C_SLV1_REG     0x29
+#define MPU6050_RA_I2C_SLV1_CTRL    0x2A
+#define MPU6050_RA_I2C_SLV2_ADDR    0x2B
+#define MPU6050_RA_I2C_SLV2_REG     0x2C
+#define MPU6050_RA_I2C_SLV2_CTRL    0x2D
+#define MPU6050_RA_I2C_SLV3_ADDR    0x2E
+#define MPU6050_RA_I2C_SLV3_REG     0x2F
+#define MPU6050_RA_I2C_SLV3_CTRL    0x30
+#define MPU6050_RA_I2C_SLV4_ADDR    0x31
+#define MPU6050_RA_I2C_SLV4_REG     0x32
+#define MPU6050_RA_I2C_SLV4_DO      0x33
+#define MPU6050_RA_I2C_SLV4_CTRL    0x34
+#define MPU6050_RA_I2C_SLV4_DI      0x35
+#define MPU6050_RA_I2C_MST_STATUS   0x36
+#define MPU6050_RA_INT_PIN_CFG      0x37
+#define MPU6050_RA_INT_ENABLE       0x38
+#define MPU6050_RA_DMP_INT_STATUS   0x39
+#define MPU6050_RA_INT_STATUS       0x3A
+#define MPU6050_RA_ACCEL_XOUT_H     0x3B
+#define MPU6050_RA_ACCEL_XOUT_L     0x3C
+#define MPU6050_RA_ACCEL_YOUT_H     0x3D
+#define MPU6050_RA_ACCEL_YOUT_L     0x3E
+#define MPU6050_RA_ACCEL_ZOUT_H     0x3F
+#define MPU6050_RA_ACCEL_ZOUT_L     0x40
+#define MPU6050_RA_TEMP_OUT_H       0x41
+#define MPU6050_RA_TEMP_OUT_L       0x42
+#define MPU6050_RA_GYRO_XOUT_H      0x43
+#define MPU6050_RA_GYRO_XOUT_L      0x44
+#define MPU6050_RA_GYRO_YOUT_H      0x45
+#define MPU6050_RA_GYRO_YOUT_L      0x46
+#define MPU6050_RA_GYRO_ZOUT_H      0x47
+#define MPU6050_RA_GYRO_ZOUT_L      0x48
+#define MPU6050_RA_EXT_SENS_DATA_00 0x49
+#define MPU6050_RA_EXT_SENS_DATA_01 0x4A
+#define MPU6050_RA_EXT_SENS_DATA_02 0x4B
+#define MPU6050_RA_EXT_SENS_DATA_03 0x4C
+#define MPU6050_RA_EXT_SENS_DATA_04 0x4D
+#define MPU6050_RA_EXT_SENS_DATA_05 0x4E
+#define MPU6050_RA_EXT_SENS_DATA_06 0x4F
+#define MPU6050_RA_EXT_SENS_DATA_07 0x50
+#define MPU6050_RA_EXT_SENS_DATA_08 0x51
+#define MPU6050_RA_EXT_SENS_DATA_09 0x52
+#define MPU6050_RA_EXT_SENS_DATA_10 0x53
+#define MPU6050_RA_EXT_SENS_DATA_11 0x54
+#define MPU6050_RA_EXT_SENS_DATA_12 0x55
+#define MPU6050_RA_EXT_SENS_DATA_13 0x56
+#define MPU6050_RA_EXT_SENS_DATA_14 0x57
+#define MPU6050_RA_EXT_SENS_DATA_15 0x58
+#define MPU6050_RA_EXT_SENS_DATA_16 0x59
+#define MPU6050_RA_EXT_SENS_DATA_17 0x5A
+#define MPU6050_RA_EXT_SENS_DATA_18 0x5B
+#define MPU6050_RA_EXT_SENS_DATA_19 0x5C
+#define MPU6050_RA_EXT_SENS_DATA_20 0x5D
+#define MPU6050_RA_EXT_SENS_DATA_21 0x5E
+#define MPU6050_RA_EXT_SENS_DATA_22 0x5F
+#define MPU6050_RA_EXT_SENS_DATA_23 0x60
+#define MPU6050_RA_MOT_DETECT_STATUS    0x61
+#define MPU6050_RA_I2C_SLV0_DO      0x63
+#define MPU6050_RA_I2C_SLV1_DO      0x64
+#define MPU6050_RA_I2C_SLV2_DO      0x65
+#define MPU6050_RA_I2C_SLV3_DO      0x66
+#define MPU6050_RA_I2C_MST_DELAY_CTRL   0x67
+#define MPU6050_RA_SIGNAL_PATH_RESET    0x68
+#define MPU6050_RA_MOT_DETECT_CTRL      0x69
+#define MPU6050_RA_USER_CTRL        0x6A
+#define MPU6050_RA_PWR_MGMT_1       0x6B
+#define MPU6050_RA_PWR_MGMT_2       0x6C
+#define MPU6050_RA_BANK_SEL         0x6D
+#define MPU6050_RA_MEM_START_ADDR   0x6E
+#define MPU6050_RA_MEM_R_W          0x6F
+#define MPU6050_RA_DMP_CFG_1        0x70
+#define MPU6050_RA_DMP_CFG_2        0x71
+#define MPU6050_RA_FIFO_COUNTH      0x72
+#define MPU6050_RA_FIFO_COUNTL      0x73
+#define MPU6050_RA_FIFO_R_W         0x74
+#define MPU6050_RA_WHO_AM_I         0x75
+
+#define MPU6050_TC_PWR_MODE_BIT     7
+#define MPU6050_TC_OFFSET_BIT       6
+#define MPU6050_TC_OFFSET_LENGTH    6
+#define MPU6050_TC_OTP_BNK_VLD_BIT  0
+
+#define MPU6050_VDDIO_LEVEL_VLOGIC  0
+#define MPU6050_VDDIO_LEVEL_VDD     1
+
+#define MPU6050_CFG_EXT_SYNC_SET_BIT    5
+#define MPU6050_CFG_EXT_SYNC_SET_LENGTH 3
+#define MPU6050_CFG_DLPF_CFG_BIT    2
+#define MPU6050_CFG_DLPF_CFG_LENGTH 3
+
+#define MPU6050_EXT_SYNC_DISABLED       0x0
+#define MPU6050_EXT_SYNC_TEMP_OUT_L     0x1
+#define MPU6050_EXT_SYNC_GYRO_XOUT_L    0x2
+#define MPU6050_EXT_SYNC_GYRO_YOUT_L    0x3
+#define MPU6050_EXT_SYNC_GYRO_ZOUT_L    0x4
+#define MPU6050_EXT_SYNC_ACCEL_XOUT_L   0x5
+#define MPU6050_EXT_SYNC_ACCEL_YOUT_L   0x6
+#define MPU6050_EXT_SYNC_ACCEL_ZOUT_L   0x7
+
+#define MPU6050_DLPF_BW_256         0x00
+#define MPU6050_DLPF_BW_188         0x01
+#define MPU6050_DLPF_BW_98          0x02
+#define MPU6050_DLPF_BW_42          0x03
+#define MPU6050_DLPF_BW_20          0x04
+#define MPU6050_DLPF_BW_10          0x05
+#define MPU6050_DLPF_BW_5           0x06
+
+#define MPU6050_GCONFIG_FS_SEL_BIT      4
+#define MPU6050_GCONFIG_FS_SEL_LENGTH   2
+
+#define MPU6050_GYRO_FS_250         0x00
+#define MPU6050_GYRO_FS_500         0x01
+#define MPU6050_GYRO_FS_1000        0x02
+#define MPU6050_GYRO_FS_2000        0x03
+
+#define MPU6050_ACONFIG_XA_ST_BIT           7
+#define MPU6050_ACONFIG_YA_ST_BIT           6
+#define MPU6050_ACONFIG_ZA_ST_BIT           5
+#define MPU6050_ACONFIG_AFS_SEL_BIT         4
+#define MPU6050_ACONFIG_AFS_SEL_LENGTH      2
+#define MPU6050_ACONFIG_ACCEL_HPF_BIT       2
+#define MPU6050_ACONFIG_ACCEL_HPF_LENGTH    3
+
+#define MPU6050_ACCEL_FS_2          0x00
+#define MPU6050_ACCEL_FS_4          0x01
+#define MPU6050_ACCEL_FS_8          0x02
+#define MPU6050_ACCEL_FS_16         0x03
+
+#define MPU6050_DHPF_RESET          0x00
+#define MPU6050_DHPF_5              0x01
+#define MPU6050_DHPF_2P5            0x02
+#define MPU6050_DHPF_1P25           0x03
+#define MPU6050_DHPF_0P63           0x04
+#define MPU6050_DHPF_HOLD           0x07
+
+#define MPU6050_TEMP_FIFO_EN_BIT    7
+#define MPU6050_XG_FIFO_EN_BIT      6
+#define MPU6050_YG_FIFO_EN_BIT      5
+#define MPU6050_ZG_FIFO_EN_BIT      4
+#define MPU6050_ACCEL_FIFO_EN_BIT   3
+#define MPU6050_SLV2_FIFO_EN_BIT    2
+#define MPU6050_SLV1_FIFO_EN_BIT    1
+#define MPU6050_SLV0_FIFO_EN_BIT    0
+
+#define MPU6050_MULT_MST_EN_BIT     7
+#define MPU6050_WAIT_FOR_ES_BIT     6
+#define MPU6050_SLV_3_FIFO_EN_BIT   5
+#define MPU6050_I2C_MST_P_NSR_BIT   4
+#define MPU6050_I2C_MST_CLK_BIT     3
+#define MPU6050_I2C_MST_CLK_LENGTH  4
+
+#define MPU6050_CLOCK_DIV_348       0x0
+#define MPU6050_CLOCK_DIV_333       0x1
+#define MPU6050_CLOCK_DIV_320       0x2
+#define MPU6050_CLOCK_DIV_308       0x3
+#define MPU6050_CLOCK_DIV_296       0x4
+#define MPU6050_CLOCK_DIV_286       0x5
+#define MPU6050_CLOCK_DIV_276       0x6
+#define MPU6050_CLOCK_DIV_267       0x7
+#define MPU6050_CLOCK_DIV_258       0x8
+#define MPU6050_CLOCK_DIV_500       0x9
+#define MPU6050_CLOCK_DIV_471       0xA
+#define MPU6050_CLOCK_DIV_444       0xB
+#define MPU6050_CLOCK_DIV_421       0xC
+#define MPU6050_CLOCK_DIV_400       0xD
+#define MPU6050_CLOCK_DIV_381       0xE
+#define MPU6050_CLOCK_DIV_364       0xF
+
+#define MPU6050_I2C_SLV_RW_BIT      7
+#define MPU6050_I2C_SLV_ADDR_BIT    6
+#define MPU6050_I2C_SLV_ADDR_LENGTH 7
+#define MPU6050_I2C_SLV_EN_BIT      7
+#define MPU6050_I2C_SLV_BYTE_SW_BIT 6
+#define MPU6050_I2C_SLV_REG_DIS_BIT 5
+#define MPU6050_I2C_SLV_GRP_BIT     4
+#define MPU6050_I2C_SLV_LEN_BIT     3
+#define MPU6050_I2C_SLV_LEN_LENGTH  4
+
+#define MPU6050_I2C_SLV4_RW_BIT         7
+#define MPU6050_I2C_SLV4_ADDR_BIT       6
+#define MPU6050_I2C_SLV4_ADDR_LENGTH    7
+#define MPU6050_I2C_SLV4_EN_BIT         7
+#define MPU6050_I2C_SLV4_INT_EN_BIT     6
+#define MPU6050_I2C_SLV4_REG_DIS_BIT    5
+#define MPU6050_I2C_SLV4_MST_DLY_BIT    4
+#define MPU6050_I2C_SLV4_MST_DLY_LENGTH 5
+
+#define MPU6050_MST_PASS_THROUGH_BIT    7
+#define MPU6050_MST_I2C_SLV4_DONE_BIT   6
+#define MPU6050_MST_I2C_LOST_ARB_BIT    5
+#define MPU6050_MST_I2C_SLV4_NACK_BIT   4
+#define MPU6050_MST_I2C_SLV3_NACK_BIT   3
+#define MPU6050_MST_I2C_SLV2_NACK_BIT   2
+#define MPU6050_MST_I2C_SLV1_NACK_BIT   1
+#define MPU6050_MST_I2C_SLV0_NACK_BIT   0
+
+#define MPU6050_INTCFG_INT_LEVEL_BIT        7
+#define MPU6050_INTCFG_INT_OPEN_BIT         6
+#define MPU6050_INTCFG_LATCH_INT_EN_BIT     5
+#define MPU6050_INTCFG_INT_RD_CLEAR_BIT     4
+#define MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT  3
+#define MPU6050_INTCFG_FSYNC_INT_EN_BIT     2
+#define MPU6050_INTCFG_I2C_BYPASS_EN_BIT    1
+#define MPU6050_INTCFG_CLKOUT_EN_BIT        0
+
+#define MPU6050_INTMODE_ACTIVEHIGH  0x00
+#define MPU6050_INTMODE_ACTIVELOW   0x01
+
+#define MPU6050_INTDRV_PUSHPULL     0x00
+#define MPU6050_INTDRV_OPENDRAIN    0x01
+
+#define MPU6050_INTLATCH_50USPULSE  0x00
+#define MPU6050_INTLATCH_WAITCLEAR  0x01
+
+#define MPU6050_INTCLEAR_STATUSREAD 0x00
+#define MPU6050_INTCLEAR_ANYREAD    0x01
+
+#define MPU6050_INTERRUPT_FF_BIT            7
+#define MPU6050_INTERRUPT_MOT_BIT           6
+#define MPU6050_INTERRUPT_ZMOT_BIT          5
+#define MPU6050_INTERRUPT_FIFO_OFLOW_BIT    4
+#define MPU6050_INTERRUPT_I2C_MST_INT_BIT   3
+#define MPU6050_INTERRUPT_PLL_RDY_INT_BIT   2
+#define MPU6050_INTERRUPT_DMP_INT_BIT       1
+#define MPU6050_INTERRUPT_DATA_RDY_BIT      0
+
+// TODO: figure out what these actually do
+// UMPL source code is not very obivous
+#define MPU6050_DMPINT_5_BIT            5
+#define MPU6050_DMPINT_4_BIT            4
+#define MPU6050_DMPINT_3_BIT            3
+#define MPU6050_DMPINT_2_BIT            2
+#define MPU6050_DMPINT_1_BIT            1
+#define MPU6050_DMPINT_0_BIT            0
+
+#define MPU6050_MOTION_MOT_XNEG_BIT     7
+#define MPU6050_MOTION_MOT_XPOS_BIT     6
+#define MPU6050_MOTION_MOT_YNEG_BIT     5
+#define MPU6050_MOTION_MOT_YPOS_BIT     4
+#define MPU6050_MOTION_MOT_ZNEG_BIT     3
+#define MPU6050_MOTION_MOT_ZPOS_BIT     2
+#define MPU6050_MOTION_MOT_ZRMOT_BIT    0
+
+#define MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT   7
+#define MPU6050_DELAYCTRL_I2C_SLV4_DLY_EN_BIT   4
+#define MPU6050_DELAYCTRL_I2C_SLV3_DLY_EN_BIT   3
+#define MPU6050_DELAYCTRL_I2C_SLV2_DLY_EN_BIT   2
+#define MPU6050_DELAYCTRL_I2C_SLV1_DLY_EN_BIT   1
+#define MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT   0
+
+#define MPU6050_PATHRESET_GYRO_RESET_BIT    2
+#define MPU6050_PATHRESET_ACCEL_RESET_BIT   1
+#define MPU6050_PATHRESET_TEMP_RESET_BIT    0
+
+#define MPU6050_DETECT_ACCEL_ON_DELAY_BIT       5
+#define MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH    2
+#define MPU6050_DETECT_FF_COUNT_BIT             3
+#define MPU6050_DETECT_FF_COUNT_LENGTH          2
+#define MPU6050_DETECT_MOT_COUNT_BIT            1
+#define MPU6050_DETECT_MOT_COUNT_LENGTH         2
+
+#define MPU6050_DETECT_DECREMENT_RESET  0x0
+#define MPU6050_DETECT_DECREMENT_1      0x1
+#define MPU6050_DETECT_DECREMENT_2      0x2
+#define MPU6050_DETECT_DECREMENT_4      0x3
+
+#define MPU6050_USERCTRL_DMP_EN_BIT             7
+#define MPU6050_USERCTRL_FIFO_EN_BIT            6
+#define MPU6050_USERCTRL_I2C_MST_EN_BIT         5
+#define MPU6050_USERCTRL_I2C_IF_DIS_BIT         4
+#define MPU6050_USERCTRL_DMP_RESET_BIT          3
+#define MPU6050_USERCTRL_FIFO_RESET_BIT         2
+#define MPU6050_USERCTRL_I2C_MST_RESET_BIT      1
+#define MPU6050_USERCTRL_SIG_COND_RESET_BIT     0
+
+#define MPU6050_PWR1_DEVICE_RESET_BIT   7
+#define MPU6050_PWR1_SLEEP_BIT          6
+#define MPU6050_PWR1_CYCLE_BIT          5
+#define MPU6050_PWR1_TEMP_DIS_BIT       3
+#define MPU6050_PWR1_CLKSEL_BIT         2
+#define MPU6050_PWR1_CLKSEL_LENGTH      3
+
+#define MPU6050_CLOCK_INTERNAL          0x00
+#define MPU6050_CLOCK_PLL_XGYRO         0x01
+#define MPU6050_CLOCK_PLL_YGYRO         0x02
+#define MPU6050_CLOCK_PLL_ZGYRO         0x03
+#define MPU6050_CLOCK_PLL_EXT32K        0x04
+#define MPU6050_CLOCK_PLL_EXT19M        0x05
+#define MPU6050_CLOCK_KEEP_RESET        0x07
+
+#define MPU6050_PWR2_LP_WAKE_CTRL_BIT       7
+#define MPU6050_PWR2_LP_WAKE_CTRL_LENGTH    2
+#define MPU6050_PWR2_STBY_XA_BIT            5
+#define MPU6050_PWR2_STBY_YA_BIT            4
+#define MPU6050_PWR2_STBY_ZA_BIT            3
+#define MPU6050_PWR2_STBY_XG_BIT            2
+#define MPU6050_PWR2_STBY_YG_BIT            1
+#define MPU6050_PWR2_STBY_ZG_BIT            0
+
+#define MPU6050_WAKE_FREQ_1P25      0x0
+#define MPU6050_WAKE_FREQ_2P5       0x1
+#define MPU6050_WAKE_FREQ_5         0x2
+#define MPU6050_WAKE_FREQ_10        0x3
+
+#define MPU6050_BANKSEL_PRFTCH_EN_BIT       6
+#define MPU6050_BANKSEL_CFG_USER_BANK_BIT   5
+#define MPU6050_BANKSEL_MEM_SEL_BIT         4
+#define MPU6050_BANKSEL_MEM_SEL_LENGTH      5
+
+#define MPU6050_WHO_AM_I_BIT        6
+#define MPU6050_WHO_AM_I_LENGTH     6
+
+#define MPU6050_DMP_MEMORY_BANKS        8
+#define MPU6050_DMP_MEMORY_BANK_SIZE    256
+#define MPU6050_DMP_MEMORY_CHUNK_SIZE   16
+
+// note: DMP code memory blocks defined at end of header file
+
+typedef struct MPU6050_t {
+    uint8_t devAddr;
+    uint8_t buffer[14];
+} MPU6050_t;
+
+void MPU6050(uint8_t address);
+
+void MPU6050_initialize();
+bool MPU6050_testConnection();
+
+// AUX_VDDIO register
+uint8_t MPU6050_getAuxVDDIOLevel();
+void MPU6050_setAuxVDDIOLevel(uint8_t level);
+
+// SMPLRT_DIV register
+uint8_t MPU6050_getRate();
+void MPU6050_setRate(uint8_t rate);
+
+// CONFIG register
+uint8_t MPU6050_getExternalFrameSync();
+void MPU6050_setExternalFrameSync(uint8_t sync);
+uint8_t MPU6050_getDLPFMode();
+void MPU6050_setDLPFMode(uint8_t bandwidth);
+
+// GYRO_CONFIG register
+uint8_t MPU6050_getFullScaleGyroRange();
+void MPU6050_setFullScaleGyroRange(uint8_t range);
+
+// ACCEL_CONFIG register
+bool MPU6050_getAccelXSelfTest();
+void MPU6050_setAccelXSelfTest(bool enabled);
+bool MPU6050_getAccelYSelfTest();
+void MPU6050_setAccelYSelfTest(bool enabled);
+bool MPU6050_getAccelZSelfTest();
+void MPU6050_setAccelZSelfTest(bool enabled);
+uint8_t MPU6050_getFullScaleAccelRange();
+void MPU6050_setFullScaleAccelRange(uint8_t range);
+uint8_t MPU6050_getDHPFMode();
+void MPU6050_setDHPFMode(uint8_t mode);
+
+// FF_THR register
+uint8_t MPU6050_getFreefallDetectionThreshold();
+void MPU6050_setFreefallDetectionThreshold(uint8_t threshold);
+
+// FF_DUR register
+uint8_t MPU6050_getFreefallDetectionDuration();
+void MPU6050_setFreefallDetectionDuration(uint8_t duration);
+
+// MOT_THR register
+uint8_t MPU6050_getMotionDetectionThreshold();
+void MPU6050_setMotionDetectionThreshold(uint8_t threshold);
+
+// MOT_DUR register
+uint8_t MPU6050_getMotionDetectionDuration();
+void MPU6050_setMotionDetectionDuration(uint8_t duration);
+
+// ZRMOT_THR register
+uint8_t MPU6050_getZeroMotionDetectionThreshold();
+void MPU6050_setZeroMotionDetectionThreshold(uint8_t threshold);
+
+// ZRMOT_DUR register
+uint8_t MPU6050_getZeroMotionDetectionDuration();
+void MPU6050_setZeroMotionDetectionDuration(uint8_t duration);
+
+// FIFO_EN register
+bool MPU6050_getTempFIFOEnabled();
+void MPU6050_setTempFIFOEnabled(bool enabled);
+bool MPU6050_getXGyroFIFOEnabled();
+void MPU6050_setXGyroFIFOEnabled(bool enabled);
+bool MPU6050_getYGyroFIFOEnabled();
+void MPU6050_setYGyroFIFOEnabled(bool enabled);
+bool MPU6050_getZGyroFIFOEnabled();
+void MPU6050_setZGyroFIFOEnabled(bool enabled);
+bool MPU6050_getAccelFIFOEnabled();
+void MPU6050_setAccelFIFOEnabled(bool enabled);
+bool MPU6050_getSlave2FIFOEnabled();
+void MPU6050_setSlave2FIFOEnabled(bool enabled);
+bool MPU6050_getSlave1FIFOEnabled();
+void MPU6050_setSlave1FIFOEnabled(bool enabled);
+bool MPU6050_getSlave0FIFOEnabled();
+void MPU6050_setSlave0FIFOEnabled(bool enabled);
+
+// I2C_MST_CTRL register
+bool MPU6050_getMultiMasterEnabled();
+void MPU6050_setMultiMasterEnabled(bool enabled);
+bool MPU6050_getWaitForExternalSensorEnabled();
+void MPU6050_setWaitForExternalSensorEnabled(bool enabled);
+bool MPU6050_getSlave3FIFOEnabled();
+void MPU6050_setSlave3FIFOEnabled(bool enabled);
+bool MPU6050_getSlaveReadWriteTransitionEnabled();
+void MPU6050_setSlaveReadWriteTransitionEnabled(bool enabled);
+uint8_t MPU6050_getMasterClockSpeed();
+void MPU6050_setMasterClockSpeed(uint8_t speed);
+
+// I2C_SLV* registers (Slave 0-3)
+uint8_t MPU6050_getSlaveAddress(uint8_t num);
+void MPU6050_setSlaveAddress(uint8_t num, uint8_t address);
+uint8_t MPU6050_getSlaveRegister(uint8_t num);
+void MPU6050_setSlaveRegister(uint8_t num, uint8_t reg);
+bool MPU6050_getSlaveEnabled(uint8_t num);
+void MPU6050_setSlaveEnabled(uint8_t num, bool enabled);
+bool MPU6050_getSlaveWordByteSwap(uint8_t num);
+void MPU6050_setSlaveWordByteSwap(uint8_t num, bool enabled);
+bool MPU6050_getSlaveWriteMode(uint8_t num);
+void MPU6050_setSlaveWriteMode(uint8_t num, bool mode);
+bool MPU6050_getSlaveWordGroupOffset(uint8_t num);
+void MPU6050_setSlaveWordGroupOffset(uint8_t num, bool enabled);
+uint8_t MPU6050_getSlaveDataLength(uint8_t num);
+void MPU6050_setSlaveDataLength(uint8_t num, uint8_t length);
+
+// I2C_SLV* registers (Slave 4)
+uint8_t MPU6050_getSlave4Address();
+void MPU6050_setSlave4Address(uint8_t address);
+uint8_t MPU6050_getSlave4Register();
+void MPU6050_setSlave4Register(uint8_t reg);
+void MPU6050_setSlave4OutputByte(uint8_t data);
+bool MPU6050_getSlave4Enabled();
+void MPU6050_setSlave4Enabled(bool enabled);
+bool MPU6050_getSlave4InterruptEnabled();
+void MPU6050_setSlave4InterruptEnabled(bool enabled);
+bool MPU6050_getSlave4WriteMode();
+void MPU6050_setSlave4WriteMode(bool mode);
+uint8_t MPU6050_getSlave4MasterDelay();
+void MPU6050_setSlave4MasterDelay(uint8_t delay);
+uint8_t MPU6050_getSlate4InputByte();
+
+// I2C_MST_STATUS register
+bool MPU6050_getPassthroughStatus();
+bool MPU6050_getSlave4IsDone();
+bool MPU6050_getLostArbitration();
+bool MPU6050_getSlave4Nack();
+bool MPU6050_getSlave3Nack();
+bool MPU6050_getSlave2Nack();
+bool MPU6050_getSlave1Nack();
+bool MPU6050_getSlave0Nack();
+
+// INT_PIN_CFG register
+bool MPU6050_getInterruptMode();
+void MPU6050_setInterruptMode(bool mode);
+bool MPU6050_getInterruptDrive();
+void MPU6050_setInterruptDrive(bool drive);
+bool MPU6050_getInterruptLatch();
+void MPU6050_setInterruptLatch(bool latch);
+bool MPU6050_getInterruptLatchClear();
+void MPU6050_setInterruptLatchClear(bool clear);
+bool MPU6050_getFSyncInterruptLevel();
+void MPU6050_setFSyncInterruptLevel(bool level);
+bool MPU6050_getFSyncInterruptEnabled();
+void MPU6050_setFSyncInterruptEnabled(bool enabled);
+bool MPU6050_getI2CBypassEnabled();
+void MPU6050_setI2CBypassEnabled(bool enabled);
+bool MPU6050_getClockOutputEnabled();
+void MPU6050_setClockOutputEnabled(bool enabled);
+
+// INT_ENABLE register
+uint8_t MPU6050_getIntEnabled();
+void MPU6050_setIntEnabled(uint8_t enabled);
+bool MPU6050_getIntFreefallEnabled();
+void MPU6050_setIntFreefallEnabled(bool enabled);
+bool MPU6050_getIntMotionEnabled();
+void MPU6050_setIntMotionEnabled(bool enabled);
+bool MPU6050_getIntZeroMotionEnabled();
+void MPU6050_setIntZeroMotionEnabled(bool enabled);
+bool MPU6050_getIntFIFOBufferOverflowEnabled();
+void MPU6050_setIntFIFOBufferOverflowEnabled(bool enabled);
+bool MPU6050_getIntI2CMasterEnabled();
+void MPU6050_setIntI2CMasterEnabled(bool enabled);
+bool MPU6050_getIntDataReadyEnabled();
+void MPU6050_setIntDataReadyEnabled(bool enabled);
+
+// INT_STATUS register
+uint8_t MPU6050_getIntStatus();
+bool MPU6050_getIntFreefallStatus();
+bool MPU6050_getIntMotionStatus();
+bool MPU6050_getIntZeroMotionStatus();
+bool MPU6050_getIntFIFOBufferOverflowStatus();
+bool MPU6050_getIntI2CMasterStatus();
+bool MPU6050_getIntDataReadyStatus();
+
+// ACCEL_*OUT_* registers
+void MPU6050_getMotion9(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz, int16_t* mx, int16_t* my, int16_t* mz);
+void MPU6050_getMotion6(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz);
+void MPU6050_getAcceleration(int16_t* x, int16_t* y, int16_t* z);
+int16_t MPU6050_getAccelerationX();
+int16_t MPU6050_getAccelerationY();
+int16_t MPU6050_getAccelerationZ();
+
+// TEMP_OUT_* registers
+int16_t MPU6050_getTemperature();
+
+// GYRO_*OUT_* registers
+void MPU6050_getRotation(int16_t* x, int16_t* y, int16_t* z);
+int16_t MPU6050_getRotationX();
+int16_t MPU6050_getRotationY();
+int16_t MPU6050_getRotationZ();
+
+// EXT_SENS_DATA_* registers
+uint8_t MPU6050_getExternalSensorByte(int position);
+uint16_t MPU6050_getExternalSensorWord(int position);
+uint32_t getExternalSensorDWord(int position);
+
+// MOT_DETECT_STATUS register
+bool MPU6050_getXNegMotionDetected();
+bool MPU6050_getXPosMotionDetected();
+bool MPU6050_getYNegMotionDetected();
+bool MPU6050_getYPosMotionDetected();
+bool MPU6050_getZNegMotionDetected();
+bool MPU6050_getZPosMotionDetected();
+bool MPU6050_getZeroMotionDetected();
+
+// I2C_SLV*_DO register
+void MPU6050_setSlaveOutputByte(uint8_t num, uint8_t data);
+
+// I2C_MST_DELAY_CTRL register
+bool MPU6050_getExternalShadowDelayEnabled();
+void MPU6050_setExternalShadowDelayEnabled(bool enabled);
+bool MPU6050_getSlaveDelayEnabled(uint8_t num);
+void MPU6050_setSlaveDelayEnabled(uint8_t num, bool enabled);
+
+// SIGNAL_PATH_RESET register
+void MPU6050_resetGyroscopePath();
+void MPU6050_resetAccelerometerPath();
+void MPU6050_resetTemperaturePath();
+
+// MOT_DETECT_CTRL register
+uint8_t MPU6050_getAccelerometerPowerOnDelay();
+void MPU6050_setAccelerometerPowerOnDelay(uint8_t delay);
+uint8_t MPU6050_getFreefallDetectionCounterDecrement();
+void MPU6050_setFreefallDetectionCounterDecrement(uint8_t decrement);
+uint8_t MPU6050_getMotionDetectionCounterDecrement();
+void MPU6050_setMotionDetectionCounterDecrement(uint8_t decrement);
+
+// USER_CTRL register
+bool MPU6050_getFIFOEnabled();
+void MPU6050_setFIFOEnabled(bool enabled);
+bool MPU6050_getI2CMasterModeEnabled();
+void MPU6050_setI2CMasterModeEnabled(bool enabled);
+void MPU6050_switchSPIEnabled(bool enabled);
+void MPU6050_resetFIFO();
+void MPU6050_resetI2CMaster();
+void MPU6050_resetSensors();
+
+// PWR_MGMT_1 register
+void MPU6050_reset();
+bool MPU6050_getSleepEnabled();
+void MPU6050_setSleepEnabled(bool enabled);
+bool MPU6050_getWakeCycleEnabled();
+void MPU6050_setWakeCycleEnabled(bool enabled);
+bool MPU6050_getTempSensorEnabled();
+void MPU6050_setTempSensorEnabled(bool enabled);
+uint8_t MPU6050_getClockSource();
+void MPU6050_setClockSource(uint8_t source);
+
+// PWR_MGMT_2 register
+uint8_t MPU6050_getWakeFrequency();
+void MPU6050_setWakeFrequency(uint8_t frequency);
+bool MPU6050_getStandbyXAccelEnabled();
+void MPU6050_setStandbyXAccelEnabled(bool enabled);
+bool MPU6050_getStandbyYAccelEnabled();
+void MPU6050_setStandbyYAccelEnabled(bool enabled);
+bool MPU6050_getStandbyZAccelEnabled();
+void MPU6050_setStandbyZAccelEnabled(bool enabled);
+bool MPU6050_getStandbyXGyroEnabled();
+void MPU6050_setStandbyXGyroEnabled(bool enabled);
+bool MPU6050_getStandbyYGyroEnabled();
+void MPU6050_setStandbyYGyroEnabled(bool enabled);
+bool MPU6050_getStandbyZGyroEnabled();
+void MPU6050_setStandbyZGyroEnabled(bool enabled);
+
+// FIFO_COUNT_* registers
+uint16_t MPU6050_getFIFOCount();
+
+// FIFO_R_W register
+uint8_t MPU6050_getFIFOByte();
+void MPU6050_setFIFOByte(uint8_t data);
+void MPU6050_getFIFOBytes(uint8_t *data, uint8_t length);
+
+// WHO_AM_I register
+uint8_t MPU6050_getDeviceID();
+void MPU6050_setDeviceID(uint8_t id);
+
+// ======== UNDOCUMENTED/DMP REGISTERS/METHODS ========
+
+// XG_OFFS_TC register
+uint8_t MPU6050_getOTPBankValid();
+void MPU6050_setOTPBankValid(bool enabled);
+int8_t getXGyroOffsetTC();
+void MPU6050_setXGyroOffsetTC(int8_t offset);
+
+// YG_OFFS_TC register
+int8_t getYGyroOffsetTC();
+void MPU6050_setYGyroOffsetTC(int8_t offset);
+
+// ZG_OFFS_TC register
+int8_t getZGyroOffsetTC();
+void MPU6050_setZGyroOffsetTC(int8_t offset);
+
+// X_FINE_GAIN register
+int8_t getXFineGain();
+void MPU6050_setXFineGain(int8_t gain);
+
+// Y_FINE_GAIN register
+int8_t getYFineGain();
+void MPU6050_setYFineGain(int8_t gain);
+
+// Z_FINE_GAIN register
+int8_t getZFineGain();
+void MPU6050_setZFineGain(int8_t gain);
+
+// XA_OFFS_* registers
+int16_t MPU6050_getXAccelOffset();
+void MPU6050_setXAccelOffset(int16_t offset);
+
+// YA_OFFS_* register
+int16_t MPU6050_getYAccelOffset();
+void MPU6050_setYAccelOffset(int16_t offset);
+
+// ZA_OFFS_* register
+int16_t MPU6050_getZAccelOffset();
+void MPU6050_setZAccelOffset(int16_t offset);
+
+// XG_OFFS_USR* registers
+int16_t MPU6050_getXGyroOffset();
+void MPU6050_setXGyroOffset(int16_t offset);
+
+// YG_OFFS_USR* register
+int16_t MPU6050_getYGyroOffset();
+void MPU6050_setYGyroOffset(int16_t offset);
+
+// ZG_OFFS_USR* register
+int16_t MPU6050_getZGyroOffset();
+void MPU6050_setZGyroOffset(int16_t offset);
+
+// INT_ENABLE register (DMP functions)
+bool MPU6050_getIntPLLReadyEnabled();
+void MPU6050_setIntPLLReadyEnabled(bool enabled);
+bool MPU6050_getIntDMPEnabled();
+void MPU6050_setIntDMPEnabled(bool enabled);
+
+// DMP_INT_STATUS
+bool MPU6050_getDMPInt5Status();
+bool MPU6050_getDMPInt4Status();
+bool MPU6050_getDMPInt3Status();
+bool MPU6050_getDMPInt2Status();
+bool MPU6050_getDMPInt1Status();
+bool MPU6050_getDMPInt0Status();
+
+// INT_STATUS register (DMP functions)
+bool MPU6050_getIntPLLReadyStatus();
+bool MPU6050_getIntDMPStatus();
+
+// USER_CTRL register (DMP functions)
+bool MPU6050_getDMPEnabled();
+void MPU6050_setDMPEnabled(bool enabled);
+void MPU6050_resetDMP();
+
+// BANK_SEL register
+void MPU6050_setMemoryBank(uint8_t bank, bool prefetchEnabled, bool userBank);
+
+// MEM_START_ADDR register
+void MPU6050_setMemoryStartAddress(uint8_t address);
+
+// MEM_R_W register
+uint8_t MPU6050_readMemoryByte();
+void MPU6050_writeMemoryByte(uint8_t data);
+void MPU6050_readMemoryBlock(uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address);
+//bool MPU6050_writeMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address, bool verify, bool useProgMem);
+//bool MPU6050_writeProgMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address, bool verify);
+
+//bool MPU6050_writeDMPConfigurationSet(const uint8_t *data, uint16_t dataSize, bool useProgMem);
+//bool MPU6050_writeProgDMPConfigurationSet(const uint8_t *data, uint16_t dataSize);
+
+// DMP_CFG_1 register
+uint8_t MPU6050_getDMPConfig1();
+void MPU6050_setDMPConfig1(uint8_t config);
+
+// DMP_CFG_2 register
+uint8_t MPU6050_getDMPConfig2();
+void MPU6050_setDMPConfig2(uint8_t config);
+
+#endif /* _MPU6050_H_ */
diff --git a/dsPIC30F/README.md b/dsPIC30F/README.md
new file mode 100644
index 00000000..858ae2bf
--- /dev/null
+++ b/dsPIC30F/README.md
@@ -0,0 +1,14 @@
+# I2C Device Library for PIC18
+
+## I2Cdev
+We use XC8's peripheral libraries (_plib_), read timeout is not implemented.
+
+## Devices
+Currently only MPU6050 is supported without DMP functions. There's an example MPLABX project showing how to read raw data from the MPU.
+
+Adding more functions and devices should be straighforward after reading the source code.
+
+## Licence
+I2Cdev device library code is placed under the MIT license.
+
+_Copyright (c) 2011 Jeff Rowberg. Copyright (c) 2014 Marton Sebok._

From 65c945d4c907a8d0ffd5d47619ab5f1947c93ac9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=88=B4=E5=AE=8F=E5=91=A8?= 
Date: Sun, 19 Feb 2017 14:31:35 +0800
Subject: [PATCH 161/335] updated readme

---
 dsPIC30F/README.md | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/dsPIC30F/README.md b/dsPIC30F/README.md
index 858ae2bf..d63bbbe1 100644
--- a/dsPIC30F/README.md
+++ b/dsPIC30F/README.md
@@ -1,7 +1,7 @@
-# I2C Device Library for PIC18
+# I2C Device Library for dsPIC30F(under construction)
 
 ## I2Cdev
-We use XC8's peripheral libraries (_plib_), read timeout is not implemented.
+We use XC16's peripheral libraries (_plib_), read timeout is not implemented.
 
 ## Devices
 Currently only MPU6050 is supported without DMP functions. There's an example MPLABX project showing how to read raw data from the MPU.
@@ -11,4 +11,4 @@ Adding more functions and devices should be straighforward after reading the sou
 ## Licence
 I2Cdev device library code is placed under the MIT license.
 
-_Copyright (c) 2011 Jeff Rowberg. Copyright (c) 2014 Marton Sebok._
+_Copyright (c) 2011 Jeff Rowberg. Copyright (c) 2014 Marton Sebok._ Copyright (c) 2017 Daichou.

From 912eda74d103da5023f1d6eef7de4e8da1fd5dfa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=88=B4=E5=AE=8F=E5=91=A8?= 
Date: Sun, 19 Feb 2017 21:02:04 +0800
Subject: [PATCH 162/335] create lib project,porting readbytes

---
 dsPIC30F/I2Cdev/I2Cdev.c                      | 148 ++++++++++++------
 dsPIC30F/I2Cdev/I2Cdev.h                      |   3 +
 .../nbproject/Makefile-genesis.properties     |   2 +-
 3 files changed, 101 insertions(+), 52 deletions(-)

diff --git a/dsPIC30F/I2Cdev/I2Cdev.c b/dsPIC30F/I2Cdev/I2Cdev.c
index d8082e33..6d7781e6 100644
--- a/dsPIC30F/I2Cdev/I2Cdev.c
+++ b/dsPIC30F/I2Cdev/I2Cdev.c
@@ -10,7 +10,8 @@
 I2Cdev device library code is placed under the MIT license
 Copyright (c) 2013 Jeff Rowberg
 Copyright (c) 2014 Marton Sebok
-
+Copyright (c) 2017 Daichou
+ *
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
@@ -33,6 +34,15 @@ THE SOFTWARE.
 
 #include "I2Cdev.h"
 
+uint16_t config2;
+uint16_t config1 = (I2C_ON & I2C_IDLE_CON & I2C_CLK_HLD &
+             I2C_IPMI_DIS & I2C_7BIT_ADD &
+             I2C_SLW_DIS & I2C_SM_DIS &
+             I2C_GCALL_DIS & I2C_STR_DIS &
+             I2C_NACK & I2C_ACK_DIS & I2C_RCV_DIS &
+             I2C_STOP_DIS & I2C_RESTART_DIS &
+             I2C_START_DIS);
+
 /** Read multiple bytes from an 8-bit device register.
  * @param devAddr I2C slave device address
  * @param regAddr First register regAddr to read from
@@ -41,49 +51,72 @@ THE SOFTWARE.
  * @return Number of bytes read (-1 indicates failure)
  */
 int8_t I2Cdev_readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data) {
-    int8_t count = 0;
-
-    // S
+    //int8_t count = 0;
+    IFS0bits.MI2CIF = 0;
     IdleI2C();
+    /*S*/
     StartI2C();
+    /* Clear interrupt flag */
 
-    // Device write address
-    IdleI2C();
-    WriteI2C(devAddr << 1 | 0x00);
+    /* Wait till Start sequence is completed */
+    while(I2CCONbits.SEN);
 
-    // Register address
-    IdleI2C();
-    WriteI2C(regAddr);
+    /*AD+W*/
+    /* Write Slave Address (Write)*/
+    MasterWriteI2C(devAddr << 1 | 0x00);
 
-    // R
-    IdleI2C();
+    /* Wait until address is transmitted */
+    while(I2CSTATbits.TBF);  // 8 clock cycles
+
+    /*Ack*/
+    while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
+    IFS0bits.MI2CIF = 0;     // Clear interrupt flag
+    while(I2CSTATbits.ACKSTAT);
+
+    /*RA*/
+    /* Write Register Address */
+    MasterWriteI2C(regAddr);
+
+    /* Wait until address is transmitted */
+    while(I2CSTATbits.TBF);  // 8 clock cycles
+
+    /*ACK*/
+    while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
+    IFS0bits.MI2CIF = 0;     // Clear interrupt flag
+    while(I2CSTATbits.ACKSTAT);
+
+    /*S*/
     RestartI2C();
+    /* Wait till Start sequence is completed */
+    while(I2CCONbits.SEN);
 
-    // Device read address
-    IdleI2C();
-    WriteI2C(devAddr << 1 | 0x01);
+    /*AD+R*/
+    /* Write Slave Address (Read)*/
+    MasterWriteI2C(devAddr << 1 | 0x01);
+    /* Wait until address is transmitted */
+    while(I2CSTATbits.TBF);  // 8 clock cycles
 
-    for (count = 0; count < length; count++) {
-        // Data byte
-        IdleI2C();
-        data[count] = ReadI2C();
+    /*Ack*/
+    while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
+    IFS0bits.MI2CIF = 0;     // Clear interrupt flag
+    while(I2CSTATbits.ACKSTAT);
 
-        if (count == length - 1) {
-            // NACK
-            IdleI2C();
-            NotAckI2C();
-        } else {
-            // ACK
-            IdleI2C();
-            AckI2C();
-        }
-    }
+    /*DATA*/
+    uint16_t flag = MastergetsI2C(length,data,I2C_DATA_WAIT);
 
-    // P
-    IdleI2C();
-    StopI2C();
+    /*NACK*/
+    NotAckI2C();
 
-    return count;
+    /*P*/
+    StopI2C();
+    /* Wait till stop sequence is completed */
+    while(I2CCONbits.PEN);
+    CloseI2C();
+
+    if (flag)
+        return length;
+    else
+        return -1;
 }
 
 /** Read single byte from an 8-bit device register.
@@ -252,28 +285,41 @@ int8_t I2Cdev_readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint
  * @return Status of operation (true = success)
  */
 bool I2Cdev_writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t* data) {
-    // S
+    OpenI2C(config1,config2);
     IdleI2C();
     StartI2C();
-
-    // Device write address
-    IdleI2C();
-    WriteI2C(devAddr << 1 | 0x00);
-
-    // Register address
-    IdleI2C();
-    WriteI2C(regAddr);
-
-    for (uint8_t i = 0; i < length; i++) {
-        // Data byte
-        IdleI2C();
-        WriteI2C(data[i]);
-    }
+    /* Wait util Start sequence is completed */
+    while(I2CCONbits.SEN);
+    
+    /* Clear interrupt flag */
+    IFS0bits.MI2CIF = 0;
+    
+    /* Write Slave address (Write)*/
+    MasterWriteI2C(devAddr << 1 | 0x00);
+    
+    /* Wait till address is transmitted */
+    while(I2CSTATbits.TBF);  // 8 clock cycles
+    while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
+    IFS0bits.MI2CIF = 0;     // Clear interrupt flag
+    while(I2CSTATbits.ACKSTAT);
+    
+    /* Write Slave address (Write)*/
+    MasterWriteI2C(regAddr);
+    
+    /* Wait till address is transmitted */
+    while(I2CSTATbits.TBF);  // 8 clock cycles
+    while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
+    IFS0bits.MI2CIF = 0;     // Clear interrupt flag
+    while(I2CSTATbits.ACKSTAT);
+    
+    /* Transmit string of data */
+    MasterputsI2C(data);
     
-    // P
-    IdleI2C();
     StopI2C();
-
+    /* Wait till stop sequence is completed */
+    while(I2CCONbits.PEN);
+    CloseI2C();
+    
     return true;
 }
 
diff --git a/dsPIC30F/I2Cdev/I2Cdev.h b/dsPIC30F/I2Cdev/I2Cdev.h
index fbe62b3f..3f8eae11 100644
--- a/dsPIC30F/I2Cdev/I2Cdev.h
+++ b/dsPIC30F/I2Cdev/I2Cdev.h
@@ -44,6 +44,9 @@ THE SOFTWARE.
 #include 
 #include 
 
+#define I2C_DATA_WAIT 152 //(20*I2C_DATA_WAIT*20 - 1) cycle
+
+
 int8_t I2Cdev_readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data);
 int8_t I2Cdev_readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data);
 int8_t I2Cdev_readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data);
diff --git a/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-genesis.properties b/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-genesis.properties
index ccfb0f58..f465b16f 100644
--- a/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-genesis.properties
+++ b/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-genesis.properties
@@ -1,5 +1,5 @@
 #
-#Sun Feb 19 14:16:06 CST 2017
+#Sun Feb 19 18:55:40 CST 2017
 default.com-microchip-mplab-nbide-toolchainXC16-XC16LanguageToolchain.md5=ebaa75370c1463d650408e4144ba15de
 default.languagetoolchain.dir=/opt/microchip/xc16/v1.30/bin
 configurations-xml=e23099a44127c530cab293bfc5554ec5

From b45cf79fdaa8245e964ca37ec4844084b10764f9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=88=B4=E5=AE=8F=E5=91=A8?= 
Date: Mon, 20 Feb 2017 00:00:18 +0800
Subject: [PATCH 163/335] updated I2Cdev_writeWords and I2Cdev_writeBytes

---
 .gitignore                                    |   3 +-
 dsPIC30F/I2Cdev/I2Cdev.c                      | 165 ++++++++++++------
 .../production/_ext/1922997195/I2Cdev.o       | Bin 0 -> 22716 bytes
 .../production/_ext/1922997195/I2Cdev.o.d     |   3 +
 .../nbproject/Makefile-genesis.properties     |   2 +-
 5 files changed, 120 insertions(+), 53 deletions(-)
 create mode 100644 dsPIC30F/I2Cdev/I2CdevdsPic30F.X/build/default/production/_ext/1922997195/I2Cdev.o
 create mode 100644 dsPIC30F/I2Cdev/I2CdevdsPic30F.X/build/default/production/_ext/1922997195/I2Cdev.o.d

diff --git a/.gitignore b/.gitignore
index 3a04da47..b103e890 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,4 +2,5 @@ PIC18/MPU6050/Examples/MPU6050_raw.X/dist/
 PIC18/MPU6050/Examples/MPU6050_raw.X/nbproject/private/
 PIC18/MPU6050/Examples/MPU6050_raw.X/build/
 *~
-/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/private/
\ No newline at end of file
+/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/private/
+/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/dist/default/
\ No newline at end of file
diff --git a/dsPIC30F/I2Cdev/I2Cdev.c b/dsPIC30F/I2Cdev/I2Cdev.c
index 6d7781e6..0440c1d9 100644
--- a/dsPIC30F/I2Cdev/I2Cdev.c
+++ b/dsPIC30F/I2Cdev/I2Cdev.c
@@ -54,67 +54,68 @@ int8_t I2Cdev_readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_
     //int8_t count = 0;
     IFS0bits.MI2CIF = 0;
     IdleI2C();
-    /*S*/
+    /*master Start*/
     StartI2C();
     /* Clear interrupt flag */
 
     /* Wait till Start sequence is completed */
     while(I2CCONbits.SEN);
 
-    /*AD+W*/
+    /*master send AD+W*/
     /* Write Slave Address (Write)*/
     MasterWriteI2C(devAddr << 1 | 0x00);
 
     /* Wait until address is transmitted */
     while(I2CSTATbits.TBF);  // 8 clock cycles
 
-    /*Ack*/
+    /*Slave send Ack*/
     while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
     IFS0bits.MI2CIF = 0;     // Clear interrupt flag
     while(I2CSTATbits.ACKSTAT);
 
-    /*RA*/
+    /*Master send RA*/
     /* Write Register Address */
     MasterWriteI2C(regAddr);
 
     /* Wait until address is transmitted */
     while(I2CSTATbits.TBF);  // 8 clock cycles
 
-    /*ACK*/
+    /*Slave send ACK*/
     while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
     IFS0bits.MI2CIF = 0;     // Clear interrupt flag
     while(I2CSTATbits.ACKSTAT);
 
-    /*S*/
+    /*Master Start*/
     RestartI2C();
     /* Wait till Start sequence is completed */
     while(I2CCONbits.SEN);
 
-    /*AD+R*/
+    /*Master send AD+R*/
     /* Write Slave Address (Read)*/
     MasterWriteI2C(devAddr << 1 | 0x01);
     /* Wait until address is transmitted */
     while(I2CSTATbits.TBF);  // 8 clock cycles
 
-    /*Ack*/
+    /*Slave send Ack*/
     while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
     IFS0bits.MI2CIF = 0;     // Clear interrupt flag
     while(I2CSTATbits.ACKSTAT);
 
-    /*DATA*/
+    /*Slave send DATA*/
     uint16_t flag = MastergetsI2C(length,data,I2C_DATA_WAIT);
 
-    /*NACK*/
+    /*Slave send NACK*/
     NotAckI2C();
 
-    /*P*/
+    /*Master Pause*/
     StopI2C();
     /* Wait till stop sequence is completed */
     while(I2CCONbits.PEN);
     CloseI2C();
 
     if (flag)
-        return length;
+        return length-flag;/*flag mean number of bytes read from I2C bus if its not able to*/
+                           /*read the data within the specified i2c_data_wait time out value*/
     else
         return -1;
 }
@@ -138,31 +139,60 @@ int8_t I2Cdev_readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data) {
  */
 int8_t I2Cdev_readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data) {
     int8_t count = 0;
-
-    // S
+    IFS0bits.MI2CIF = 0;
     IdleI2C();
+    /*master Start*/
     StartI2C();
+    /* Clear interrupt flag */
 
-    // Device write address
-    IdleI2C();
-    WriteI2C(devAddr << 1 | 0x00);
+    /* Wait till Start sequence is completed */
+    while(I2CCONbits.SEN);
 
-    // Register address
-    IdleI2C();
-    WriteI2C(regAddr);
+    /*AD+W*/
+    /* Write Slave Address (Write)*/
+    MasterWriteI2C(devAddr << 1 | 0x00);
 
-    // R
-    IdleI2C();
+    /* Wait until address is transmitted */
+    while(I2CSTATbits.TBF);  // 8 clock cycles
+
+    /*Slave Ack*/
+    while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
+    IFS0bits.MI2CIF = 0;     // Clear interrupt flag
+    while(I2CSTATbits.ACKSTAT);
+
+    /*master send RA*/
+    /* Write Register Address */
+    MasterWriteI2C(regAddr);
+
+    /* Wait until address is transmitted */
+    while(I2CSTATbits.TBF);  // 8 clock cycles
+
+    /*Slave ACK*/
+    while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
+    IFS0bits.MI2CIF = 0;     // Clear interrupt flag
+    while(I2CSTATbits.ACKSTAT);
+
+    /*master Start*/
     RestartI2C();
+    /* Wait till Start sequence is completed */
+    while(I2CCONbits.SEN);
 
-    // Device read address
-    IdleI2C();
-    WriteI2C(devAddr << 1 | 0x01);
+    /*master send AD+R*/
+    /* Write Slave Address (Read)*/
+    MasterWriteI2C(devAddr << 1 | 0x01);
+    /* Wait until address is transmitted */
+    while(I2CSTATbits.TBF);  // 8 clock cycles
 
-    for (count = 0; count < length; count++) {
+    /*Slave Ack*/
+    while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
+    IFS0bits.MI2CIF = 0;     // Clear interrupt flag
+    while(I2CSTATbits.ACKSTAT);
+
+    /*Read Word Sequence*/
+    for ( count = 0 ; count < length ; count++ ) {
         // First byte is bits 15-8 (MSb=15)
         IdleI2C();
-        data[count] = ReadI2C() << 8;
+        uint8_t high_byte = MasterReadI2C();
 
         // NACK
         IdleI2C();
@@ -170,8 +200,8 @@ int8_t I2Cdev_readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16
 
         // Second byte is bits 7-0 (LSb=0)
         IdleI2C();
-        data[count] |= ReadI2C();
-
+        uint8_t lower_byte = MasterReadI2C();
+        data[count] = (high_byte << 8) | lower_byte;
         if (count == length - 1) {
             // NACK
             IdleI2C();
@@ -183,9 +213,14 @@ int8_t I2Cdev_readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16
         }
     }
 
-    // P
-    IdleI2C();
+    /*Slave send NACK*/
+    NotAckI2C();
+
+    /*master enter P*/
     StopI2C();
+    /* Wait till stop sequence is completed */
+    while(I2CCONbits.PEN);
+    CloseI2C();
 
     return count;
 }
@@ -287,39 +322,44 @@ int8_t I2Cdev_readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint
 bool I2Cdev_writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t* data) {
     OpenI2C(config1,config2);
     IdleI2C();
+    /*Master Start*/
     StartI2C();
     /* Wait util Start sequence is completed */
     while(I2CCONbits.SEN);
-    
     /* Clear interrupt flag */
     IFS0bits.MI2CIF = 0;
-    
+
+    /*Master send AD+W*/
     /* Write Slave address (Write)*/
     MasterWriteI2C(devAddr << 1 | 0x00);
-    
     /* Wait till address is transmitted */
     while(I2CSTATbits.TBF);  // 8 clock cycles
+
+    /*Slave send ACK*/
     while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
     IFS0bits.MI2CIF = 0;     // Clear interrupt flag
     while(I2CSTATbits.ACKSTAT);
-    
+
+    /*Master send RA*/
     /* Write Slave address (Write)*/
     MasterWriteI2C(regAddr);
-    
     /* Wait till address is transmitted */
     while(I2CSTATbits.TBF);  // 8 clock cycles
+
+    /*Slave send ACK*/
     while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
     IFS0bits.MI2CIF = 0;     // Clear interrupt flag
     while(I2CSTATbits.ACKSTAT);
-    
+
+    /*Master send data*/
     /* Transmit string of data */
     MasterputsI2C(data);
-    
+
     StopI2C();
     /* Wait till stop sequence is completed */
     while(I2CCONbits.PEN);
     CloseI2C();
-    
+
     return true;
 }
 
@@ -341,31 +381,54 @@ bool I2Cdev_writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data) {
  * @return Status of operation (true = success)
  */
 bool I2Cdev_writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t* data) {
-    // S
+    OpenI2C(config1,config2);
     IdleI2C();
+    /*Master Start*/
     StartI2C();
+    /* Wait util Start sequence is completed */
+    while(I2CCONbits.SEN);
+    /* Clear interrupt flag */
+    IFS0bits.MI2CIF = 0;
 
-    // Device write address
-    IdleI2C();
-    WriteI2C(devAddr << 1 | 0x00);
+    /*Master send AD+W*/
+    /* Write Slave address (Write)*/
+    MasterWriteI2C(devAddr << 1 | 0x00);
+    /* Wait till address is transmitted */
+    while(I2CSTATbits.TBF);  // 8 clock cycles
 
-    // Register address
-    IdleI2C();
-    WriteI2C(regAddr);
+    /*Slave send ACK*/
+    while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
+    IFS0bits.MI2CIF = 0;     // Clear interrupt flag
+    while(I2CSTATbits.ACKSTAT);
 
-    for (uint8_t i = 0; i < length; i++) {
+    /*Master send RA*/
+    /* Write Slave address (Write)*/
+    uint8_t i;
+    for (i = 0; i < length; i++) {
         // Send MSB
         IdleI2C();
-        WriteI2C(data[i] >> 8);
+        MasterWriteI2C(data[i] >> 8);
 
         // Send LSB
         IdleI2C();
-        WriteI2C(data[i] & 0xFF);
+        MasterWriteI2C(data[i] & 0xFF);
     }
+    /* Wait till address is transmitted */
+    while(I2CSTATbits.TBF);  // 8 clock cycles
+
+    /*Slave send ACK*/
+    while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
+    IFS0bits.MI2CIF = 0;     // Clear interrupt flag
+    while(I2CSTATbits.ACKSTAT);
+
+    /*Master send data*/
+    /* Transmit string of data */
+    MasterputsI2C(data);
 
-    // P
-    IdleI2C();
     StopI2C();
+    /* Wait till stop sequence is completed */
+    while(I2CCONbits.PEN);
+    CloseI2C();
 
     return true;
 }
diff --git a/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/build/default/production/_ext/1922997195/I2Cdev.o b/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/build/default/production/_ext/1922997195/I2Cdev.o
new file mode 100644
index 0000000000000000000000000000000000000000..f7252c0b09056012661c51018df820081e335543
GIT binary patch
literal 22716
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
Ee>1=<+5i9m

literal 0
HcmV?d00001

diff --git a/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/build/default/production/_ext/1922997195/I2Cdev.o.d b/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/build/default/production/_ext/1922997195/I2Cdev.o.d
new file mode 100644
index 00000000..3255c9ae
--- /dev/null
+++ b/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/build/default/production/_ext/1922997195/I2Cdev.o.d
@@ -0,0 +1,3 @@
+build/default/production/_ext/1922997195/I2Cdev.o:  \
+ /home/tommycc/work/i2cdevlib/dsPIC30F/I2Cdev/I2Cdev.c  \
+ /home/tommycc/work/i2cdevlib/dsPIC30F/I2Cdev/I2Cdev.h 
diff --git a/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-genesis.properties b/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-genesis.properties
index f465b16f..659e9b6e 100644
--- a/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-genesis.properties
+++ b/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-genesis.properties
@@ -1,5 +1,5 @@
 #
-#Sun Feb 19 18:55:40 CST 2017
+#Sun Feb 19 21:43:16 CST 2017
 default.com-microchip-mplab-nbide-toolchainXC16-XC16LanguageToolchain.md5=ebaa75370c1463d650408e4144ba15de
 default.languagetoolchain.dir=/opt/microchip/xc16/v1.30/bin
 configurations-xml=e23099a44127c530cab293bfc5554ec5

From cde39720102a18fdc82dbce78217e383d7dd1368 Mon Sep 17 00:00:00 2001
From: Daichou 
Date: Wed, 15 Mar 2017 17:21:21 +0800
Subject: [PATCH 164/335] add Example,but not finish

---
 .gitignore                                    |    6 +-
 dsPIC30F/I2Cdev/I2Cdev.c                      |   21 +-
 .../nbproject/Makefile-genesis.properties     |    2 +-
 .../Examples/MPU6050_example.X/I2Cdev.c       |  553 +++
 .../Examples/MPU6050_example.X/I2Cdev.h       |   68 +
 .../Examples/MPU6050_example.X/MPU6050.c      | 3141 +++++++++++++++++
 .../Examples/MPU6050_example.X/MPU6050.h      |  786 +++++
 .../MPU6050_example.X/MPU6050_example_main.c  |  131 +
 .../Examples/MPU6050_example.X/Makefile       |  113 +
 .../nbproject/Makefile-default.mk             |  182 +
 .../nbproject/Makefile-genesis.properties     |    9 +
 .../nbproject/Makefile-impl.mk                |   69 +
 .../nbproject/Makefile-local-default.mk       |   36 +
 .../nbproject/Makefile-variables.mk           |   13 +
 .../nbproject/Package-default.bash            |   73 +
 .../nbproject/configurations.xml              |  224 ++
 .../MPU6050_example.X/nbproject/project.xml   |   17 +
 17 files changed, 5437 insertions(+), 7 deletions(-)
 create mode 100644 dsPIC30F/MPU6050/Examples/MPU6050_example.X/I2Cdev.c
 create mode 100644 dsPIC30F/MPU6050/Examples/MPU6050_example.X/I2Cdev.h
 create mode 100644 dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050.c
 create mode 100644 dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050.h
 create mode 100644 dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050_example_main.c
 create mode 100644 dsPIC30F/MPU6050/Examples/MPU6050_example.X/Makefile
 create mode 100644 dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Makefile-default.mk
 create mode 100644 dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Makefile-genesis.properties
 create mode 100644 dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Makefile-impl.mk
 create mode 100644 dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Makefile-local-default.mk
 create mode 100644 dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Makefile-variables.mk
 create mode 100644 dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Package-default.bash
 create mode 100644 dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/configurations.xml
 create mode 100644 dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/project.xml

diff --git a/.gitignore b/.gitignore
index b103e890..8c1a6502 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,4 +3,8 @@ PIC18/MPU6050/Examples/MPU6050_raw.X/nbproject/private/
 PIC18/MPU6050/Examples/MPU6050_raw.X/build/
 *~
 /dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/private/
-/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/dist/default/
\ No newline at end of file
+/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/dist/default/
+/dsPIC30F/I2Cdev/testMCC.X/nbproject/private/
+/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/private/
+/dsPIC30F/MPU6050/Examples/MPU6050_example.X/build/default/
+/dsPIC30F/MPU6050/Examples/MPU6050_example.X/dist/default/
\ No newline at end of file
diff --git a/dsPIC30F/I2Cdev/I2Cdev.c b/dsPIC30F/I2Cdev/I2Cdev.c
index 0440c1d9..0e4d18d8 100644
--- a/dsPIC30F/I2Cdev/I2Cdev.c
+++ b/dsPIC30F/I2Cdev/I2Cdev.c
@@ -34,15 +34,15 @@ THE SOFTWARE.
 
 #include "I2Cdev.h"
 
-uint16_t config2;
-uint16_t config1 = (I2C_ON & I2C_IDLE_CON & I2C_CLK_HLD &
+//uint16_t config2;
+/*uint16_t config1 = (I2C_ON & I2C_IDLE_CON & I2C_CLK_HLD &
              I2C_IPMI_DIS & I2C_7BIT_ADD &
              I2C_SLW_DIS & I2C_SM_DIS &
              I2C_GCALL_DIS & I2C_STR_DIS &
              I2C_NACK & I2C_ACK_DIS & I2C_RCV_DIS &
              I2C_STOP_DIS & I2C_RESTART_DIS &
              I2C_START_DIS);
-
+*/
 /** Read multiple bytes from an 8-bit device register.
  * @param devAddr I2C slave device address
  * @param regAddr First register regAddr to read from
@@ -53,7 +53,7 @@ uint16_t config1 = (I2C_ON & I2C_IDLE_CON & I2C_CLK_HLD &
 int8_t I2Cdev_readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data) {
     //int8_t count = 0;
     IFS0bits.MI2CIF = 0;
-    IdleI2C();
+    //IdleI2C();
     /*master Start*/
     StartI2C();
     /* Clear interrupt flag */
@@ -396,6 +396,17 @@ bool I2Cdev_writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_
     /* Wait till address is transmitted */
     while(I2CSTATbits.TBF);  // 8 clock cycles
 
+    /*Slave send ACK*/
+    while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
+    IFS0bits.MI2CIF = 0;     // Clear interrupt flag
+    while(I2CSTATbits.ACKSTAT);
+    
+    /*Master send RA*/
+    /* Write Slave address (Write)*/
+    MasterWriteI2C(regAddr);
+    /* Wait till address is transmitted */
+    while(I2CSTATbits.TBF);  // 8 clock cycles
+
     /*Slave send ACK*/
     while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
     IFS0bits.MI2CIF = 0;     // Clear interrupt flag
@@ -423,7 +434,7 @@ bool I2Cdev_writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_
 
     /*Master send data*/
     /* Transmit string of data */
-    MasterputsI2C(data);
+    //MasterputsI2C(data);
 
     StopI2C();
     /* Wait till stop sequence is completed */
diff --git a/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-genesis.properties b/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-genesis.properties
index 659e9b6e..f9906730 100644
--- a/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-genesis.properties
+++ b/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-genesis.properties
@@ -1,5 +1,5 @@
 #
-#Sun Feb 19 21:43:16 CST 2017
+#Wed Mar 15 15:13:12 CST 2017
 default.com-microchip-mplab-nbide-toolchainXC16-XC16LanguageToolchain.md5=ebaa75370c1463d650408e4144ba15de
 default.languagetoolchain.dir=/opt/microchip/xc16/v1.30/bin
 configurations-xml=e23099a44127c530cab293bfc5554ec5
diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/I2Cdev.c b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/I2Cdev.c
new file mode 100644
index 00000000..70d76e27
--- /dev/null
+++ b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/I2Cdev.c
@@ -0,0 +1,553 @@
+// I2Cdev library collection - Main I2C device class
+// Abstracts bit and byte I2C R/W functions into a convenient class
+// 6/9/2012 by Jeff Rowberg 
+// 11/28/2014 by Marton Sebok 
+//
+// Changelog:
+//     2014-11-28 - ported to PIC18 peripheral library from Arduino code
+
+/* ============================================
+I2Cdev device library code is placed under the MIT license
+Copyright (c) 2013 Jeff Rowberg
+Copyright (c) 2014 Marton Sebok
+Copyright (c) 2017 Daichou
+ *
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+===============================================
+*/
+
+#include "I2Cdev.h"
+
+/*uint16_t config2;
+uint16_t config1 = (I2C_ON & I2C_IDLE_CON & I2C_CLK_HLD &
+             I2C_IPMI_DIS & I2C_7BIT_ADD &
+             I2C_SLW_DIS & I2C_SM_DIS &
+             I2C_GCALL_DIS & I2C_STR_DIS &
+             I2C_NACK & I2C_ACK_DIS & I2C_RCV_DIS &
+             I2C_STOP_DIS & I2C_RESTART_DIS &
+             I2C_START_DIS);
+*/
+/** Read multiple bytes from an 8-bit device register.
+ * @param devAddr I2C slave device address
+ * @param regAddr First register regAddr to read from
+ * @param length Number of bytes to read
+ * @param data Buffer to store read data in
+ * @return Number of bytes read (-1 indicates failure)
+ */
+int8_t I2Cdev_readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data) {
+    //int8_t count = 0;
+    IFS0bits.MI2CIF = 0;
+    IEC0bits.MI2CIE = 0;
+    //IdleI2C();
+    /*master Start*/
+    StartI2C();
+    /* Clear interrupt flag */
+
+    /* Wait till Start sequence is completed */
+    while(I2CCONbits.SEN);
+
+    /*master send AD+W*/
+    /* Write Slave Address (Write)*/
+    MasterWriteI2C(devAddr << 1 | 0x00);
+
+    /* Wait until address is transmitted */
+    while(I2CSTATbits.TBF);  // 8 clock cycles
+
+    /*Slave send Ack*/
+    while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
+    IFS0bits.MI2CIF = 0;     // Clear interrupt flag
+    //while(I2CSTATbits.ACKSTAT);
+
+    /*Master send RA*/
+    /* Write Register Address */
+    MasterWriteI2C(regAddr);
+
+    /* Wait until address is transmitted */
+    while(I2CSTATbits.TBF);  // 8 clock cycles
+
+    /*Slave send ACK*/
+    while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
+    IFS0bits.MI2CIF = 0;     // Clear interrupt flag
+    //while(I2CSTATbits.ACKSTAT);
+
+    /*Master Start*/
+    //RestartI2C();
+    /* Wait till Start sequence is completed */
+    //while(I2CCONbits.SEN);
+
+    /*Master send AD+R*/
+    /* Write Slave Address (Read)*/
+    MasterWriteI2C(devAddr << 1 | 0x01);
+    /* Wait until address is transmitted */
+    while(I2CSTATbits.TBF);  // 8 clock cycles
+
+    /*Slave send Ack*/
+    while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
+    IFS0bits.MI2CIF = 0;     // Clear interrupt flag
+    //while(I2CSTATbits.ACKSTAT);
+
+    /*Slave send DATA*/
+    //uint16_t flag = MastergetsI2C(length,data,I2C_DATA_WAIT);
+
+    /*Slave send NACK*/
+    //NotAckI2C();
+
+    data[0] = MasterReadI2C();
+    unsigned int i;
+    for (i = 1 ; i < length ; i++ ){
+        AckI2C();
+        while(I2CCONbits.ACKEN == 1);
+        data[i] = MasterReadI2C();
+    }
+    NotAckI2C();
+    while(I2CCONbits.ACKEN == 1);
+    /*Master Pause*/
+    StopI2C();
+    /* Wait till stop sequence is completed */
+    while(I2CCONbits.PEN);
+    //CloseI2C();
+    IdleI2C();
+    return true;
+}
+
+/** Read single byte from an 8-bit device register.
+ * @param devAddr I2C slave device address
+ * @param regAddr Register regAddr to read from
+ * @param data Container for byte value read from device
+ * @return Status of read operation (true = success)
+ */
+int8_t I2Cdev_readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data) {
+    return I2Cdev_readBytes(devAddr, regAddr, 1, data);
+}
+
+/** Read multiple words from a 16-bit device register.
+ * @param devAddr I2C slave device address
+ * @param regAddr First register regAddr to read from
+ * @param length Number of words to read
+ * @param data Buffer to store read data in
+ * @return Number of words read (-1 indicates failure)
+ */
+int8_t I2Cdev_readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data) {
+    int8_t count = 0;
+    IFS0bits.MI2CIF = 0;
+    IEC0bits.MI2CIE = 0;
+    
+    IdleI2C();
+    /*master Start*/
+    StartI2C();
+    /* Clear interrupt flag */
+
+    /* Wait till Start sequence is completed */
+    while(I2CCONbits.SEN);
+
+    /*AD+W*/
+    /* Write Slave Address (Write)*/
+    MasterWriteI2C(devAddr << 1 | 0x00);
+
+    /* Wait until address is transmitted */
+    while(I2CSTATbits.TBF);  // 8 clock cycles
+
+    /*Slave Ack*/
+    while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
+    IFS0bits.MI2CIF = 0;     // Clear interrupt flag
+    //while(I2CSTATbits.ACKSTAT);
+
+    /*master send RA*/
+    /* Write Register Address */
+    MasterWriteI2C(regAddr);
+
+    /* Wait until address is transmitted */
+    while(I2CSTATbits.TBF);  // 8 clock cycles
+
+    /*Slave ACK*/
+    while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
+    IFS0bits.MI2CIF = 0;     // Clear interrupt flag
+    //while(I2CSTATbits.ACKSTAT);
+
+    /*master Start*/
+    //RestartI2C();
+    /* Wait till Start sequence is completed */
+    //while(I2CCONbits.SEN);
+
+    /*master send AD+R*/
+    /* Write Slave Address (Read)*/
+    MasterWriteI2C(devAddr << 1 | 0x01);
+    /* Wait until address is transmitted */
+    while(I2CSTATbits.TBF);  // 8 clock cycles
+
+    /*Slave Ack*/
+    while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
+    IFS0bits.MI2CIF = 0;     // Clear interrupt flag
+    //while(I2CSTATbits.ACKSTAT);
+
+    /*Read Word Sequence*/
+    for ( count = 0 ; count < length ; count++ ) {
+        // First byte is bits 15-8 (MSb=15)
+        //IdleI2C();
+        uint8_t high_byte = MasterReadI2C();
+
+        // NACK
+        //IdleI2C();
+        NotAckI2C();
+
+        // Second byte is bits 7-0 (LSb=0)
+        IdleI2C();
+        uint8_t lower_byte = MasterReadI2C();
+        data[count] = (high_byte << 8) | lower_byte;
+        if (count == length - 1) {
+            // NACK
+            IdleI2C();
+            NotAckI2C();
+        } else {
+            // ACK
+            IdleI2C();
+            AckI2C();
+        }
+    }
+
+    /*Slave send NACK*/
+    NotAckI2C();
+
+    /*master enter P*/
+    StopI2C();
+    /* Wait till stop sequence is completed */
+    while(I2CCONbits.PEN);
+    //CloseI2C();
+
+    return count;
+}
+
+/** Read single word from a 16-bit device register.
+ * @param devAddr I2C slave device address
+ * @param regAddr Register regAddr to read from
+ * @param data Container for word value read from device
+ * @return Status of read operation (true = success)
+ */
+int8_t I2Cdev_readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data) {
+    return I2Cdev_readWords(devAddr, regAddr, 1, data);
+}
+
+/** Read a single bit from an 8-bit device register.
+ * @param devAddr I2C slave device address
+ * @param regAddr Register regAddr to read from
+ * @param bitNum Bit position to read (0-7)
+ * @param data Container for single bit value
+ * @return Status of read operation (true = success)
+ */
+int8_t I2Cdev_readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data) {
+    uint8_t b;
+    uint8_t count = I2Cdev_readByte(devAddr, regAddr, &b);
+    *data = b & (1 << bitNum);
+    return count;
+}
+
+/** Read a single bit from a 16-bit device register.
+ * @param devAddr I2C slave device address
+ * @param regAddr Register regAddr to read from
+ * @param bitNum Bit position to read (0-15)
+ * @param data Container for single bit value
+ * @return Status of read operation (true = success)
+ */
+int8_t I2Cdev_readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data) {
+    uint16_t b;
+    uint8_t count = I2Cdev_readWord(devAddr, regAddr, &b);
+    *data = b & (1 << bitNum);
+    return count;
+}
+
+/** Read multiple bits from an 8-bit device register.
+ * @param devAddr I2C slave device address
+ * @param regAddr Register regAddr to read from
+ * @param bitStart First bit position to read (0-7)
+ * @param length Number of bits to read (not more than 8)
+ * @param data Container for right-aligned value (i.e. '101' read from any bitStart position will equal 0x05)
+ * @return Status of read operation (true = success)
+ */
+int8_t I2Cdev_readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data) {
+    // 01101001 read byte
+    // 76543210 bit numbers
+    //    xxx   args: bitStart=4, length=3
+    //    010   masked
+    //   -> 010 shifted
+    uint8_t count, b;
+    if ((count = I2Cdev_readByte(devAddr, regAddr, &b)) != 0) {
+        uint8_t mask = ((1 << length) - 1) << (bitStart - length + 1);
+        b &= mask;
+        b >>= (bitStart - length + 1);
+        *data = b;
+    }
+    return count;
+}
+
+/** Read multiple bits from a 16-bit device register.
+ * @param devAddr I2C slave device address
+ * @param regAddr Register regAddr to read from
+ * @param bitStart First bit position to read (0-15)
+ * @param length Number of bits to read (not more than 16)
+ * @param data Container for right-aligned value (i.e. '101' read from any bitStart position will equal 0x05)
+ * @return Status of read operation (1 = success, 0 = failure, -1 = timeout)
+ */
+int8_t I2Cdev_readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t *data) {
+    // 1101011001101001 read byte
+    // fedcba9876543210 bit numbers
+    //    xxx           args: bitStart=12, length=3
+    //    010           masked
+    //           -> 010 shifted
+    uint8_t count;
+    uint16_t w;
+    if ((count = I2Cdev_readWord(devAddr, regAddr, &w)) != 0) {
+        uint16_t mask = ((1 << length) - 1) << (bitStart - length + 1);
+        w &= mask;
+        w >>= (bitStart - length + 1);
+        *data = w;
+    }
+    return count;
+}
+
+/** Write multiple bytes to an 8-bit device register.
+ * @param devAddr I2C slave device address
+ * @param regAddr First register address to write to
+ * @param length Number of bytes to write
+ * @param data Buffer to copy new data from
+ * @return Status of operation (true = success)
+ */
+bool I2Cdev_writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t* data) {
+    //OpenI2C(config1,config2);
+    IFS0bits.MI2CIF = 0;
+    IEC0bits.MI2CIE = 0;
+    IdleI2C();
+    /*Master Start*/
+    StartI2C();
+    /* Wait util Start sequence is completed */
+    while(I2CCONbits.SEN);
+    /* Clear interrupt flag */
+    IFS0bits.MI2CIF = 0;
+
+    /*Master send AD+W*/
+    /* Write Slave address (Write)*/
+    MasterWriteI2C(devAddr << 1 | 0x00);
+    /* Wait till address is transmitted */
+    while(I2CSTATbits.TBF);  // 8 clock cycles
+
+    /*Slave send ACK*/
+    while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
+    IFS0bits.MI2CIF = 0;     // Clear interrupt flag
+    while(I2CSTATbits.ACKSTAT);
+
+    /*Master send RA*/
+    /* Write Slave address (Write)*/
+    MasterWriteI2C(regAddr);
+    /* Wait till address is transmitted */
+    while(I2CSTATbits.TBF);  // 8 clock cycles
+
+    /*Slave send ACK*/
+    while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
+    IFS0bits.MI2CIF = 0;     // Clear interrupt flag
+    while(I2CSTATbits.ACKSTAT);
+
+    /*Master send data*/
+    /* Transmit string of data */
+    MasterputsI2C(data);
+
+    StopI2C();
+    /* Wait till stop sequence is completed */
+    while(I2CCONbits.PEN);
+    //CloseI2C();
+
+    return true;
+}
+
+/** Write single byte to an 8-bit device register.
+ * @param devAddr I2C slave device address
+ * @param regAddr Register address to write to
+ * @param data New byte value to write
+ * @return Status of operation (true = success)
+ */
+bool I2Cdev_writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data) {
+    return I2Cdev_writeBytes(devAddr, regAddr, 1, &data);
+}
+
+/** Write multiple words to a 16-bit device register.
+ * @param devAddr I2C slave device address
+ * @param regAddr First register address to write to
+ * @param length Number of words to write
+ * @param data Buffer to copy new data from
+ * @return Status of operation (true = success)
+ */
+bool I2Cdev_writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t* data) {
+    IFS0bits.MI2CIF = 0;
+    IEC0bits.MI2CIE = 0;
+    //OpenI2C(config1,config2);
+    IdleI2C();
+    /*Master Start*/
+    StartI2C();
+    /* Wait util Start sequence is completed */
+    while(I2CCONbits.SEN);
+    /* Clear interrupt flag */
+    IFS0bits.MI2CIF = 0;
+
+    /*Master send AD+W*/
+    /* Write Slave address (Write)*/
+    MasterWriteI2C(devAddr << 1 | 0x00);
+    /* Wait till address is transmitted */
+    while(I2CSTATbits.TBF);  // 8 clock cycles
+
+    /*Slave send ACK*/
+    while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
+    IFS0bits.MI2CIF = 0;     // Clear interrupt flag
+    while(I2CSTATbits.ACKSTAT);
+    
+    /*Master send RA*/
+    /* Write Slave address (Write)*/
+    MasterWriteI2C(regAddr);
+    /* Wait till address is transmitted */
+    while(I2CSTATbits.TBF);  // 8 clock cycles
+
+    /*Slave send ACK*/
+    while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
+    IFS0bits.MI2CIF = 0;     // Clear interrupt flag
+    while(I2CSTATbits.ACKSTAT);
+
+    /*Master send RA*/
+    /* Write Slave address (Write)*/
+    uint8_t i;
+    for (i = 0; i < length; i++) {
+        // Send MSB
+        IdleI2C();
+        MasterWriteI2C(data[i] >> 8);
+
+        // Send LSB
+        IdleI2C();
+        MasterWriteI2C(data[i] & 0xFF);
+    }
+    /* Wait till address is transmitted */
+    while(I2CSTATbits.TBF);  // 8 clock cycles
+
+    /*Slave send ACK*/
+    while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
+    IFS0bits.MI2CIF = 0;     // Clear interrupt flag
+    while(I2CSTATbits.ACKSTAT);
+
+    /*Master send data*/
+    /* Transmit string of data */
+    //MasterputsI2C(data);
+
+    StopI2C();
+    /* Wait till stop sequence is completed */
+    while(I2CCONbits.PEN);
+    //CloseI2C();
+
+    return true;
+}
+
+/** Write single word to a 16-bit device register.
+ * @param devAddr I2C slave device address
+ * @param regAddr Register address to write to
+ * @param data New word value to write
+ * @return Status of operation (true = success)
+ */
+bool I2Cdev_writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data) {
+    return I2Cdev_writeWords(devAddr, regAddr, 1, &data);
+}
+
+/** write a single bit in an 8-bit device register.
+ * @param devAddr I2C slave device address
+ * @param regAddr Register regAddr to write to
+ * @param bitNum Bit position to write (0-7)
+ * @param value New bit value to write
+ * @return Status of operation (true = success)
+ */
+bool I2Cdev_writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t data) {
+    uint8_t b;
+    I2Cdev_readByte(devAddr, regAddr, &b);
+    b = (data != 0) ? (b | (1 << bitNum)) : (b & ~(1 << bitNum));
+    return I2Cdev_writeByte(devAddr, regAddr, b);
+}
+
+/** write a single bit in a 16-bit device register.
+ * @param devAddr I2C slave device address
+ * @param regAddr Register regAddr to write to
+ * @param bitNum Bit position to write (0-15)
+ * @param value New bit value to write
+ * @return Status of operation (true = success)
+ */
+bool I2Cdev_writeBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t data) {
+    uint16_t w;
+    I2Cdev_readWord(devAddr, regAddr, &w);
+    w = (data != 0) ? (w | (1 << bitNum)) : (w & ~(1 << bitNum));
+    return I2Cdev_writeWord(devAddr, regAddr, w);
+}
+
+/** Write multiple bits in an 8-bit device register.
+ * @param devAddr I2C slave device address
+ * @param regAddr Register regAddr to write to
+ * @param bitStart First bit position to write (0-7)
+ * @param length Number of bits to write (not more than 8)
+ * @param data Right-aligned value to write
+ * @return Status of operation (true = success)
+ */
+bool I2Cdev_writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data) {
+    //      010 value to write
+    // 76543210 bit numbers
+    //    xxx   args: bitStart=4, length=3
+    // 00011100 mask byte
+    // 10101111 original value (sample)
+    // 10100011 original & ~mask
+    // 10101011 masked | value
+    uint8_t b;
+    if (I2Cdev_readByte(devAddr, regAddr, &b) != 0) {
+        uint8_t mask = ((1 << length) - 1) << (bitStart - length + 1);
+        data <<= (bitStart - length + 1); // shift data into correct position
+        data &= mask; // zero all non-important bits in data
+        b &= ~(mask); // zero all important bits in existing byte
+        b |= data; // combine data with existing byte
+        return I2Cdev_writeByte(devAddr, regAddr, b);
+    } else {
+        return false;
+    }
+}
+
+/** Write multiple bits in a 16-bit device register.
+ * @param devAddr I2C slave device address
+ * @param regAddr Register regAddr to write to
+ * @param bitStart First bit position to write (0-15)
+ * @param length Number of bits to write (not more than 16)
+ * @param data Right-aligned value to write
+ * @return Status of operation (true = success)
+ */
+bool I2Cdev_writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t data) {
+    //              010 value to write
+    // fedcba9876543210 bit numbers
+    //    xxx           args: bitStart=12, length=3
+    // 0001110000000000 mask word
+    // 1010111110010110 original value (sample)
+    // 1010001110010110 original & ~mask
+    // 1010101110010110 masked | value
+    uint16_t w;
+    if (I2Cdev_readWord(devAddr, regAddr, &w) != 0) {
+        uint16_t mask = ((1 << length) - 1) << (bitStart - length + 1);
+        data <<= (bitStart - length + 1); // shift data into correct position
+        data &= mask; // zero all non-important bits in data
+        w &= ~(mask); // zero all important bits in existing word
+        w |= data; // combine data with existing word
+        return I2Cdev_writeWord(devAddr, regAddr, w);
+    } else {
+        return false;
+    }
+}
diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/I2Cdev.h b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/I2Cdev.h
new file mode 100644
index 00000000..3f8eae11
--- /dev/null
+++ b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/I2Cdev.h
@@ -0,0 +1,68 @@
+// I2Cdev library collection - Main I2C device class header file
+// Abstracts bit and byte I2C R/W functions into a convenient class
+// 6/9/2012 by Jeff Rowberg 
+// 11/28/2014 by Marton Sebok 
+//
+// Changelog:
+//     2014-11-28 - ported to PIC18 peripheral library from Arduino code
+
+/* ============================================
+I2Cdev device library code is placed under the MIT license
+Copyright (c) 2013 Jeff Rowberg
+Copyright (c) 2014 Marton Sebok
+Copyright (c) 2017 Daichou
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+===============================================
+*/
+
+#ifndef _I2CDEV_H_
+#define _I2CDEV_H_
+
+#ifndef __XC16
+    #error Use XC16 for compiling
+#endif
+
+#include 
+#include 
+#include 
+#include 
+
+#define I2C_DATA_WAIT 152 //(20*I2C_DATA_WAIT*20 - 1) cycle
+
+
+int8_t I2Cdev_readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data);
+int8_t I2Cdev_readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data);
+int8_t I2Cdev_readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data);
+int8_t I2Cdev_readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t *data);
+int8_t I2Cdev_readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data);
+int8_t I2Cdev_readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data);
+int8_t I2Cdev_readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data);
+int8_t I2Cdev_readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data);
+
+bool I2Cdev_writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t data);
+bool I2Cdev_writeBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t data);
+bool I2Cdev_writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data);
+bool I2Cdev_writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t data);
+bool I2Cdev_writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data);
+bool I2Cdev_writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data);
+bool I2Cdev_writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data);
+bool I2Cdev_writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data);
+
+#endif /* _I2CDEV_H_ */
diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050.c b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050.c
new file mode 100644
index 00000000..2683529a
--- /dev/null
+++ b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050.c
@@ -0,0 +1,3141 @@
+// I2Cdev library collection - MPU6050 I2C device class
+// Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00)
+// 8/24/2011 by Jeff Rowberg 
+// 11/28/2014 by Marton Sebok 
+//
+// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
+//
+// Changelog:
+//     ...        - ongoing debug release
+//     2014-11-28 - ported to PIC18 peripheral library from Arduino code
+
+// NOTE: THIS IS ONLY A PARIAL RELEASE. THIS DEVICE CLASS IS CURRENTLY UNDERGOING ACTIVE
+// DEVELOPMENT AND IS STILL MISSING SOME IMPORTANT FEATURES. PLEASE KEEP THIS IN MIND IF
+// YOU DECIDE TO USE THIS PARTICULAR CODE FOR ANYTHING.
+
+/* ============================================
+I2Cdev device library code is placed under the MIT license
+Copyright (c) 2012 Jeff Rowberg
+Copyright (c) 2014 Marton Sebok
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+===============================================
+*/
+
+#include "MPU6050.h"
+
+MPU6050_t mpu6050;
+
+/** Specific address constructor.
+ * @param address I2C address
+ * @see MPU6050_DEFAULT_ADDRESS
+ * @see MPU6050_ADDRESS_AD0_LOW
+ * @see MPU6050_ADDRESS_AD0_HIGH
+ */
+void MPU6050(uint8_t address) {
+    mpu6050.devAddr = address;
+}
+
+/** Power on and prepare for general usage.
+ * This will activate the device and take it out of sleep mode (which must be done
+ * after start-up). This function also sets both the accelerometer and the gyroscope
+ * to their most sensitive settings, namely +/- 2g and +/- 250 degrees/sec, and sets
+ * the clock source to use the X Gyro for reference, which is slightly better than
+ * the default internal clock source.
+ */
+void MPU6050_initialize() {
+    MPU6050_setClockSource(MPU6050_CLOCK_PLL_XGYRO);
+    MPU6050_setFullScaleGyroRange(MPU6050_GYRO_FS_250);
+    MPU6050_setFullScaleAccelRange(MPU6050_ACCEL_FS_2);
+    MPU6050_setSleepEnabled(false); // thanks to Jack Elston for pointing this one out!
+}
+
+/** Verify the I2C connection.
+ * Make sure the device is connected and responds as expected.
+ * @return True if connection is valid, false otherwise
+ */
+bool MPU6050_testConnection() {
+    return MPU6050_getDeviceID() == 0x34;
+}
+
+// AUX_VDDIO register (InvenSense demo code calls this RA_*G_OFFS_TC)
+
+/** Get the auxiliary I2C supply voltage level.
+ * When set to 1, the auxiliary I2C bus high logic level is VDD. When cleared to
+ * 0, the auxiliary I2C bus high logic level is VLOGIC. This does not apply to
+ * the MPU-6000, which does not have a VLOGIC pin.
+ * @return I2C supply voltage level (0=VLOGIC, 1=VDD)
+ */
+uint8_t MPU6050_getAuxVDDIOLevel() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_PWR_MODE_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+/** Set the auxiliary I2C supply voltage level.
+ * When set to 1, the auxiliary I2C bus high logic level is VDD. When cleared to
+ * 0, the auxiliary I2C bus high logic level is VLOGIC. This does not apply to
+ * the MPU-6000, which does not have a VLOGIC pin.
+ * @param level I2C supply voltage level (0=VLOGIC, 1=VDD)
+ */
+void MPU6050_setAuxVDDIOLevel(uint8_t level) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_PWR_MODE_BIT, level);
+}
+
+// SMPLRT_DIV register
+
+/** Get gyroscope output rate divider.
+ * The sensor register output, FIFO output, DMP sampling, Motion detection, Zero
+ * Motion detection, and Free Fall detection are all based on the Sample Rate.
+ * The Sample Rate is generated by dividing the gyroscope output rate by
+ * SMPLRT_DIV:
+ *
+ * Sample Rate = Gyroscope Output Rate / (1 + SMPLRT_DIV)
+ *
+ * where Gyroscope Output Rate = 8kHz when the DLPF is disabled (DLPF_CFG = 0 or
+ * 7), and 1kHz when the DLPF is enabled (see Register 26).
+ *
+ * Note: The accelerometer output rate is 1kHz. This means that for a Sample
+ * Rate greater than 1kHz, the same accelerometer sample may be output to the
+ * FIFO, DMP, and sensor registers more than once.
+ *
+ * For a diagram of the gyroscope and accelerometer signal paths, see Section 8
+ * of the MPU-6000/MPU-6050 Product Specification document.
+ *
+ * @return Current sample rate
+ * @see MPU6050_RA_SMPLRT_DIV
+ */
+uint8_t MPU6050_getRate() {
+    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_SMPLRT_DIV, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+/** Set gyroscope sample rate divider.
+ * @param rate New sample rate divider
+ * @see getRate()
+ * @see MPU6050_RA_SMPLRT_DIV
+ */
+void MPU6050_setRate(uint8_t rate) {
+    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_SMPLRT_DIV, rate);
+}
+
+// CONFIG register
+
+/** Get external FSYNC configuration.
+ * Configures the external Frame Synchronization (FSYNC) pin sampling. An
+ * external signal connected to the FSYNC pin can be sampled by configuring
+ * EXT_SYNC_SET. Signal changes to the FSYNC pin are latched so that short
+ * strobes may be captured. The latched FSYNC signal will be sampled at the
+ * Sampling Rate, as defined in register 25. After sampling, the latch will
+ * reset to the current FSYNC signal state.
+ *
+ * The sampled value will be reported in place of the least significant bit in
+ * a sensor data register determined by the value of EXT_SYNC_SET according to
+ * the following table.
+ *
+ * 
+ * EXT_SYNC_SET | FSYNC Bit Location
+ * -------------+-------------------
+ * 0            | Input disabled
+ * 1            | TEMP_OUT_L[0]
+ * 2            | GYRO_XOUT_L[0]
+ * 3            | GYRO_YOUT_L[0]
+ * 4            | GYRO_ZOUT_L[0]
+ * 5            | ACCEL_XOUT_L[0]
+ * 6            | ACCEL_YOUT_L[0]
+ * 7            | ACCEL_ZOUT_L[0]
+ * 
+ * + * @return FSYNC configuration value + */ +uint8_t MPU6050_getExternalFrameSync() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_EXT_SYNC_SET_BIT, MPU6050_CFG_EXT_SYNC_SET_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set external FSYNC configuration. + * @see getExternalFrameSync() + * @see MPU6050_RA_CONFIG + * @param sync New FSYNC configuration value + */ +void MPU6050_setExternalFrameSync(uint8_t sync) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_EXT_SYNC_SET_BIT, MPU6050_CFG_EXT_SYNC_SET_LENGTH, sync); +} +/** Get digital low-pass filter configuration. + * The DLPF_CFG parameter sets the digital low pass filter configuration. It + * also determines the internal sampling rate used by the device as shown in + * the table below. + * + * Note: The accelerometer output rate is 1kHz. This means that for a Sample + * Rate greater than 1kHz, the same accelerometer sample may be output to the + * FIFO, DMP, and sensor registers more than once. + * + *
+ *          |   ACCELEROMETER    |           GYROSCOPE
+ * DLPF_CFG | Bandwidth | Delay  | Bandwidth | Delay  | Sample Rate
+ * ---------+-----------+--------+-----------+--------+-------------
+ * 0        | 260Hz     | 0ms    | 256Hz     | 0.98ms | 8kHz
+ * 1        | 184Hz     | 2.0ms  | 188Hz     | 1.9ms  | 1kHz
+ * 2        | 94Hz      | 3.0ms  | 98Hz      | 2.8ms  | 1kHz
+ * 3        | 44Hz      | 4.9ms  | 42Hz      | 4.8ms  | 1kHz
+ * 4        | 21Hz      | 8.5ms  | 20Hz      | 8.3ms  | 1kHz
+ * 5        | 10Hz      | 13.8ms | 10Hz      | 13.4ms | 1kHz
+ * 6        | 5Hz       | 19.0ms | 5Hz       | 18.6ms | 1kHz
+ * 7        |   -- Reserved --   |   -- Reserved --   | Reserved
+ * 
+ * + * @return DLFP configuration + * @see MPU6050_RA_CONFIG + * @see MPU6050_CFG_DLPF_CFG_BIT + * @see MPU6050_CFG_DLPF_CFG_LENGTH + */ +uint8_t MPU6050_getDLPFMode() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_DLPF_CFG_BIT, MPU6050_CFG_DLPF_CFG_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set digital low-pass filter configuration. + * @param mode New DLFP configuration setting + * @see getDLPFBandwidth() + * @see MPU6050_DLPF_BW_256 + * @see MPU6050_RA_CONFIG + * @see MPU6050_CFG_DLPF_CFG_BIT + * @see MPU6050_CFG_DLPF_CFG_LENGTH + */ +void MPU6050_setDLPFMode(uint8_t mode) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_DLPF_CFG_BIT, MPU6050_CFG_DLPF_CFG_LENGTH, mode); +} + +// GYRO_CONFIG register + +/** Get full-scale gyroscope range. + * The FS_SEL parameter allows setting the full-scale range of the gyro sensors, + * as described in the table below. + * + *
+ * 0 = +/- 250 degrees/sec
+ * 1 = +/- 500 degrees/sec
+ * 2 = +/- 1000 degrees/sec
+ * 3 = +/- 2000 degrees/sec
+ * 
+ * + * @return Current full-scale gyroscope range setting + * @see MPU6050_GYRO_FS_250 + * @see MPU6050_RA_GYRO_CONFIG + * @see MPU6050_GCONFIG_FS_SEL_BIT + * @see MPU6050_GCONFIG_FS_SEL_LENGTH + */ +uint8_t MPU6050_getFullScaleGyroRange() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set full-scale gyroscope range. + * @param range New full-scale gyroscope range value + * @see getFullScaleRange() + * @see MPU6050_GYRO_FS_250 + * @see MPU6050_RA_GYRO_CONFIG + * @see MPU6050_GCONFIG_FS_SEL_BIT + * @see MPU6050_GCONFIG_FS_SEL_LENGTH + */ +void MPU6050_setFullScaleGyroRange(uint8_t range) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, range); +} + +// ACCEL_CONFIG register + +/** Get self-test enabled setting for accelerometer X axis. + * @return Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +bool MPU6050_getAccelXSelfTest() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_XA_ST_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get self-test enabled setting for accelerometer X axis. + * @param enabled Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050_setAccelXSelfTest(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_XA_ST_BIT, enabled); +} +/** Get self-test enabled value for accelerometer Y axis. + * @return Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +bool MPU6050_getAccelYSelfTest() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_YA_ST_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get self-test enabled value for accelerometer Y axis. + * @param enabled Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050_setAccelYSelfTest(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_YA_ST_BIT, enabled); +} +/** Get self-test enabled value for accelerometer Z axis. + * @return Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +bool MPU6050_getAccelZSelfTest() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ZA_ST_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set self-test enabled value for accelerometer Z axis. + * @param enabled Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050_setAccelZSelfTest(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ZA_ST_BIT, enabled); +} +/** Get full-scale accelerometer range. + * The FS_SEL parameter allows setting the full-scale range of the accelerometer + * sensors, as described in the table below. + * + *
+ * 0 = +/- 2g
+ * 1 = +/- 4g
+ * 2 = +/- 8g
+ * 3 = +/- 16g
+ * 
+ * + * @return Current full-scale accelerometer range setting + * @see MPU6050_ACCEL_FS_2 + * @see MPU6050_RA_ACCEL_CONFIG + * @see MPU6050_ACONFIG_AFS_SEL_BIT + * @see MPU6050_ACONFIG_AFS_SEL_LENGTH + */ +uint8_t MPU6050_getFullScaleAccelRange() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set full-scale accelerometer range. + * @param range New full-scale accelerometer range setting + * @see getFullScaleAccelRange() + */ +void MPU6050_setFullScaleAccelRange(uint8_t range) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, range); +} +/** Get the high-pass filter configuration. + * The DHPF is a filter module in the path leading to motion detectors (Free + * Fall, Motion threshold, and Zero Motion). The high pass filter output is not + * available to the data registers (see Figure in Section 8 of the MPU-6000/ + * MPU-6050 Product Specification document). + * + * The high pass filter has three modes: + * + *
+ *    Reset: The filter output settles to zero within one sample. This
+ *           effectively disables the high pass filter. This mode may be toggled
+ *           to quickly settle the filter.
+ *
+ *    On:    The high pass filter will pass signals above the cut off frequency.
+ *
+ *    Hold:  When triggered, the filter holds the present sample. The filter
+ *           output will be the difference between the input sample and the held
+ *           sample.
+ * 
+ * + *
+ * ACCEL_HPF | Filter Mode | Cut-off Frequency
+ * ----------+-------------+------------------
+ * 0         | Reset       | None
+ * 1         | On          | 5Hz
+ * 2         | On          | 2.5Hz
+ * 3         | On          | 1.25Hz
+ * 4         | On          | 0.63Hz
+ * 7         | Hold        | None
+ * 
+ * + * @return Current high-pass filter configuration + * @see MPU6050_DHPF_RESET + * @see MPU6050_RA_ACCEL_CONFIG + */ +uint8_t MPU6050_getDHPFMode() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ACCEL_HPF_BIT, MPU6050_ACONFIG_ACCEL_HPF_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set the high-pass filter configuration. + * @param bandwidth New high-pass filter configuration + * @see setDHPFMode() + * @see MPU6050_DHPF_RESET + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050_setDHPFMode(uint8_t bandwidth) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ACCEL_HPF_BIT, MPU6050_ACONFIG_ACCEL_HPF_LENGTH, bandwidth); +} + +// FF_THR register + +/** Get free-fall event acceleration threshold. + * This register configures the detection threshold for Free Fall event + * detection. The unit of FF_THR is 1LSB = 2mg. Free Fall is detected when the + * absolute value of the accelerometer measurements for the three axes are each + * less than the detection threshold. This condition increments the Free Fall + * duration counter (Register 30). The Free Fall interrupt is triggered when the + * Free Fall duration counter reaches the time specified in FF_DUR. + * + * For more details on the Free Fall detection interrupt, see Section 8.2 of the + * MPU-6000/MPU-6050 Product Specification document as well as Registers 56 and + * 58 of this document. + * + * @return Current free-fall acceleration threshold value (LSB = 2mg) + * @see MPU6050_RA_FF_THR + */ +uint8_t MPU6050_getFreefallDetectionThreshold() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_FF_THR, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get free-fall event acceleration threshold. + * @param threshold New free-fall acceleration threshold value (LSB = 2mg) + * @see getFreefallDetectionThreshold() + * @see MPU6050_RA_FF_THR + */ +void MPU6050_setFreefallDetectionThreshold(uint8_t threshold) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_FF_THR, threshold); +} + +// FF_DUR register + +/** Get free-fall event duration threshold. + * This register configures the duration counter threshold for Free Fall event + * detection. The duration counter ticks at 1kHz, therefore FF_DUR has a unit + * of 1 LSB = 1 ms. + * + * The Free Fall duration counter increments while the absolute value of the + * accelerometer measurements are each less than the detection threshold + * (Register 29). The Free Fall interrupt is triggered when the Free Fall + * duration counter reaches the time specified in this register. + * + * For more details on the Free Fall detection interrupt, see Section 8.2 of + * the MPU-6000/MPU-6050 Product Specification document as well as Registers 56 + * and 58 of this document. + * + * @return Current free-fall duration threshold value (LSB = 1ms) + * @see MPU6050_RA_FF_DUR + */ +uint8_t MPU6050_getFreefallDetectionDuration() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_FF_DUR, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get free-fall event duration threshold. + * @param duration New free-fall duration threshold value (LSB = 1ms) + * @see getFreefallDetectionDuration() + * @see MPU6050_RA_FF_DUR + */ +void MPU6050_setFreefallDetectionDuration(uint8_t duration) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_FF_DUR, duration); +} + +// MOT_THR register + +/** Get motion detection event acceleration threshold. + * This register configures the detection threshold for Motion interrupt + * generation. The unit of MOT_THR is 1LSB = 2mg. Motion is detected when the + * absolute value of any of the accelerometer measurements exceeds this Motion + * detection threshold. This condition increments the Motion detection duration + * counter (Register 32). The Motion detection interrupt is triggered when the + * Motion Detection counter reaches the time count specified in MOT_DUR + * (Register 32). + * + * The Motion interrupt will indicate the axis and polarity of detected motion + * in MOT_DETECT_STATUS (Register 97). + * + * For more details on the Motion detection interrupt, see Section 8.3 of the + * MPU-6000/MPU-6050 Product Specification document as well as Registers 56 and + * 58 of this document. + * + * @return Current motion detection acceleration threshold value (LSB = 2mg) + * @see MPU6050_RA_MOT_THR + */ +uint8_t MPU6050_getMotionDetectionThreshold() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_MOT_THR, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set free-fall event acceleration threshold. + * @param threshold New motion detection acceleration threshold value (LSB = 2mg) + * @see getMotionDetectionThreshold() + * @see MPU6050_RA_MOT_THR + */ +void MPU6050_setMotionDetectionThreshold(uint8_t threshold) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_MOT_THR, threshold); +} + +// MOT_DUR register + +/** Get motion detection event duration threshold. + * This register configures the duration counter threshold for Motion interrupt + * generation. The duration counter ticks at 1 kHz, therefore MOT_DUR has a unit + * of 1LSB = 1ms. The Motion detection duration counter increments when the + * absolute value of any of the accelerometer measurements exceeds the Motion + * detection threshold (Register 31). The Motion detection interrupt is + * triggered when the Motion detection counter reaches the time count specified + * in this register. + * + * For more details on the Motion detection interrupt, see Section 8.3 of the + * MPU-6000/MPU-6050 Product Specification document. + * + * @return Current motion detection duration threshold value (LSB = 1ms) + * @see MPU6050_RA_MOT_DUR + */ +uint8_t MPU6050_getMotionDetectionDuration() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_MOT_DUR, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set motion detection event duration threshold. + * @param duration New motion detection duration threshold value (LSB = 1ms) + * @see getMotionDetectionDuration() + * @see MPU6050_RA_MOT_DUR + */ +void MPU6050_setMotionDetectionDuration(uint8_t duration) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_MOT_DUR, duration); +} + +// ZRMOT_THR register + +/** Get zero motion detection event acceleration threshold. + * This register configures the detection threshold for Zero Motion interrupt + * generation. The unit of ZRMOT_THR is 1LSB = 2mg. Zero Motion is detected when + * the absolute value of the accelerometer measurements for the 3 axes are each + * less than the detection threshold. This condition increments the Zero Motion + * duration counter (Register 34). The Zero Motion interrupt is triggered when + * the Zero Motion duration counter reaches the time count specified in + * ZRMOT_DUR (Register 34). + * + * Unlike Free Fall or Motion detection, Zero Motion detection triggers an + * interrupt both when Zero Motion is first detected and when Zero Motion is no + * longer detected. + * + * When a zero motion event is detected, a Zero Motion Status will be indicated + * in the MOT_DETECT_STATUS register (Register 97). When a motion-to-zero-motion + * condition is detected, the status bit is set to 1. When a zero-motion-to- + * motion condition is detected, the status bit is set to 0. + * + * For more details on the Zero Motion detection interrupt, see Section 8.4 of + * the MPU-6000/MPU-6050 Product Specification document as well as Registers 56 + * and 58 of this document. + * + * @return Current zero motion detection acceleration threshold value (LSB = 2mg) + * @see MPU6050_RA_ZRMOT_THR + */ +uint8_t MPU6050_getZeroMotionDetectionThreshold() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_ZRMOT_THR, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set zero motion detection event acceleration threshold. + * @param threshold New zero motion detection acceleration threshold value (LSB = 2mg) + * @see getZeroMotionDetectionThreshold() + * @see MPU6050_RA_ZRMOT_THR + */ +void MPU6050_setZeroMotionDetectionThreshold(uint8_t threshold) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_ZRMOT_THR, threshold); +} + +// ZRMOT_DUR register + +/** Get zero motion detection event duration threshold. + * This register configures the duration counter threshold for Zero Motion + * interrupt generation. The duration counter ticks at 16 Hz, therefore + * ZRMOT_DUR has a unit of 1 LSB = 64 ms. The Zero Motion duration counter + * increments while the absolute value of the accelerometer measurements are + * each less than the detection threshold (Register 33). The Zero Motion + * interrupt is triggered when the Zero Motion duration counter reaches the time + * count specified in this register. + * + * For more details on the Zero Motion detection interrupt, see Section 8.4 of + * the MPU-6000/MPU-6050 Product Specification document, as well as Registers 56 + * and 58 of this document. + * + * @return Current zero motion detection duration threshold value (LSB = 64ms) + * @see MPU6050_RA_ZRMOT_DUR + */ +uint8_t MPU6050_getZeroMotionDetectionDuration() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_ZRMOT_DUR, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set zero motion detection event duration threshold. + * @param duration New zero motion detection duration threshold value (LSB = 1ms) + * @see getZeroMotionDetectionDuration() + * @see MPU6050_RA_ZRMOT_DUR + */ +void MPU6050_setZeroMotionDetectionDuration(uint8_t duration) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_ZRMOT_DUR, duration); +} + +// FIFO_EN register + +/** Get temperature FIFO enabled value. + * When set to 1, this bit enables TEMP_OUT_H and TEMP_OUT_L (Registers 65 and + * 66) to be written into the FIFO mpu6050.buffer. + * @return Current temperature FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_getTempFIFOEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_TEMP_FIFO_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set temperature FIFO enabled value. + * @param enabled New temperature FIFO enabled value + * @see getTempFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setTempFIFOEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_TEMP_FIFO_EN_BIT, enabled); +} +/** Get gyroscope X-axis FIFO enabled value. + * When set to 1, this bit enables GYRO_XOUT_H and GYRO_XOUT_L (Registers 67 and + * 68) to be written into the FIFO mpu6050.buffer. + * @return Current gyroscope X-axis FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_getXGyroFIFOEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_XG_FIFO_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set gyroscope X-axis FIFO enabled value. + * @param enabled New gyroscope X-axis FIFO enabled value + * @see getXGyroFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setXGyroFIFOEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_XG_FIFO_EN_BIT, enabled); +} +/** Get gyroscope Y-axis FIFO enabled value. + * When set to 1, this bit enables GYRO_YOUT_H and GYRO_YOUT_L (Registers 69 and + * 70) to be written into the FIFO mpu6050.buffer. + * @return Current gyroscope Y-axis FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_getYGyroFIFOEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_YG_FIFO_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set gyroscope Y-axis FIFO enabled value. + * @param enabled New gyroscope Y-axis FIFO enabled value + * @see getYGyroFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setYGyroFIFOEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_YG_FIFO_EN_BIT, enabled); +} +/** Get gyroscope Z-axis FIFO enabled value. + * When set to 1, this bit enables GYRO_ZOUT_H and GYRO_ZOUT_L (Registers 71 and + * 72) to be written into the FIFO mpu6050.buffer. + * @return Current gyroscope Z-axis FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_getZGyroFIFOEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_ZG_FIFO_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set gyroscope Z-axis FIFO enabled value. + * @param enabled New gyroscope Z-axis FIFO enabled value + * @see getZGyroFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setZGyroFIFOEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_ZG_FIFO_EN_BIT, enabled); +} +/** Get accelerometer FIFO enabled value. + * When set to 1, this bit enables ACCEL_XOUT_H, ACCEL_XOUT_L, ACCEL_YOUT_H, + * ACCEL_YOUT_L, ACCEL_ZOUT_H, and ACCEL_ZOUT_L (Registers 59 to 64) to be + * written into the FIFO mpu6050.buffer. + * @return Current accelerometer FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_getAccelFIFOEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_ACCEL_FIFO_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set accelerometer FIFO enabled value. + * @param enabled New accelerometer FIFO enabled value + * @see getAccelFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setAccelFIFOEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_ACCEL_FIFO_EN_BIT, enabled); +} +/** Get Slave 2 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 2 to be written into the FIFO mpu6050.buffer. + * @return Current Slave 2 FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_getSlave2FIFOEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV2_FIFO_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Slave 2 FIFO enabled value. + * @param enabled New Slave 2 FIFO enabled value + * @see getSlave2FIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setSlave2FIFOEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV2_FIFO_EN_BIT, enabled); +} +/** Get Slave 1 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 1 to be written into the FIFO mpu6050.buffer. + * @return Current Slave 1 FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_getSlave1FIFOEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV1_FIFO_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Slave 1 FIFO enabled value. + * @param enabled New Slave 1 FIFO enabled value + * @see getSlave1FIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setSlave1FIFOEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV1_FIFO_EN_BIT, enabled); +} +/** Get Slave 0 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 0 to be written into the FIFO mpu6050.buffer. + * @return Current Slave 0 FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_getSlave0FIFOEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV0_FIFO_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Slave 0 FIFO enabled value. + * @param enabled New Slave 0 FIFO enabled value + * @see getSlave0FIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setSlave0FIFOEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV0_FIFO_EN_BIT, enabled); +} + +// I2C_MST_CTRL register + +/** Get multi-master enabled value. + * Multi-master capability allows multiple I2C masters to operate on the same + * bus. In circuits where multi-master capability is required, set MULT_MST_EN + * to 1. This will increase current drawn by approximately 30uA. + * + * In circuits where multi-master capability is required, the state of the I2C + * bus must always be monitored by each separate I2C Master. Before an I2C + * Master can assume arbitration of the bus, it must first confirm that no other + * I2C Master has arbitration of the bus. When MULT_MST_EN is set to 1, the + * MPU-60X0's bus arbitration detection logic is turned on, enabling it to + * detect when the bus is available. + * + * @return Current multi-master enabled value + * @see MPU6050_RA_I2C_MST_CTRL + */ +bool MPU6050_getMultiMasterEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_MULT_MST_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set multi-master enabled value. + * @param enabled New multi-master enabled value + * @see getMultiMasterEnabled() + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050_setMultiMasterEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_MULT_MST_EN_BIT, enabled); +} +/** Get wait-for-external-sensor-data enabled value. + * When the WAIT_FOR_ES bit is set to 1, the Data Ready interrupt will be + * delayed until External Sensor data from the Slave Devices are loaded into the + * EXT_SENS_DATA registers. This is used to ensure that both the internal sensor + * data (i.e. from gyro and accel) and external sensor data have been loaded to + * their respective data registers (i.e. the data is synced) when the Data Ready + * interrupt is triggered. + * + * @return Current wait-for-external-sensor-data enabled value + * @see MPU6050_RA_I2C_MST_CTRL + */ +bool MPU6050_getWaitForExternalSensorEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_WAIT_FOR_ES_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set wait-for-external-sensor-data enabled value. + * @param enabled New wait-for-external-sensor-data enabled value + * @see getWaitForExternalSensorEnabled() + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050_setWaitForExternalSensorEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_WAIT_FOR_ES_BIT, enabled); +} +/** Get Slave 3 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 3 to be written into the FIFO mpu6050.buffer. + * @return Current Slave 3 FIFO enabled value + * @see MPU6050_RA_MST_CTRL + */ +bool MPU6050_getSlave3FIFOEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_SLV_3_FIFO_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Slave 3 FIFO enabled value. + * @param enabled New Slave 3 FIFO enabled value + * @see getSlave3FIFOEnabled() + * @see MPU6050_RA_MST_CTRL + */ +void MPU6050_setSlave3FIFOEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_SLV_3_FIFO_EN_BIT, enabled); +} +/** Get slave read/write transition enabled value. + * The I2C_MST_P_NSR bit configures the I2C Master's transition from one slave + * read to the next slave read. If the bit equals 0, there will be a restart + * between reads. If the bit equals 1, there will be a stop followed by a start + * of the following read. When a write transaction follows a read transaction, + * the stop followed by a start of the successive write will be always used. + * + * @return Current slave read/write transition enabled value + * @see MPU6050_RA_I2C_MST_CTRL + */ +bool MPU6050_getSlaveReadWriteTransitionEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_P_NSR_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set slave read/write transition enabled value. + * @param enabled New slave read/write transition enabled value + * @see getSlaveReadWriteTransitionEnabled() + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050_setSlaveReadWriteTransitionEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_P_NSR_BIT, enabled); +} +/** Get I2C master clock speed. + * I2C_MST_CLK is a 4 bit unsigned value which configures a divider on the + * MPU-60X0 internal 8MHz clock. It sets the I2C master clock speed according to + * the following table: + * + *
+ * I2C_MST_CLK | I2C Master Clock Speed | 8MHz Clock Divider
+ * ------------+------------------------+-------------------
+ * 0           | 348kHz                 | 23
+ * 1           | 333kHz                 | 24
+ * 2           | 320kHz                 | 25
+ * 3           | 308kHz                 | 26
+ * 4           | 296kHz                 | 27
+ * 5           | 286kHz                 | 28
+ * 6           | 276kHz                 | 29
+ * 7           | 267kHz                 | 30
+ * 8           | 258kHz                 | 31
+ * 9           | 500kHz                 | 16
+ * 10          | 471kHz                 | 17
+ * 11          | 444kHz                 | 18
+ * 12          | 421kHz                 | 19
+ * 13          | 400kHz                 | 20
+ * 14          | 381kHz                 | 21
+ * 15          | 364kHz                 | 22
+ * 
+ * + * @return Current I2C master clock speed + * @see MPU6050_RA_I2C_MST_CTRL + */ +uint8_t MPU6050_getMasterClockSpeed() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_CLK_BIT, MPU6050_I2C_MST_CLK_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set I2C master clock speed. + * @reparam speed Current I2C master clock speed + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050_setMasterClockSpeed(uint8_t speed) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_CLK_BIT, MPU6050_I2C_MST_CLK_LENGTH, speed); +} + +// I2C_SLV* registers (Slave 0-3) + +/** Get the I2C address of the specified slave (0-3). + * Note that Bit 7 (MSB) controls read/write mode. If Bit 7 is set, it's a read + * operation, and if it is cleared, then it's a write operation. The remaining + * bits (6-0) are the 7-bit device address of the slave device. + * + * In read mode, the result of the read is placed in the lowest available + * EXT_SENS_DATA register. For further information regarding the allocation of + * read results, please refer to the EXT_SENS_DATA register description + * (Registers 73 - 96). + * + * The MPU-6050 supports a total of five slaves, but Slave 4 has unique + * characteristics, and so it has its own functions (getSlave4* and setSlave4*). + * + * I2C data transactions are performed at the Sample Rate, as defined in + * Register 25. The user is responsible for ensuring that I2C data transactions + * to and from each enabled Slave can be completed within a single period of the + * Sample Rate. + * + * The I2C slave access rate can be reduced relative to the Sample Rate. This + * reduced access rate is determined by I2C_MST_DLY (Register 52). Whether a + * slave's access rate is reduced relative to the Sample Rate is determined by + * I2C_MST_DELAY_CTRL (Register 103). + * + * The processing order for the slaves is fixed. The sequence followed for + * processing the slaves is Slave 0, Slave 1, Slave 2, Slave 3 and Slave 4. If a + * particular Slave is disabled it will be skipped. + * + * Each slave can either be accessed at the sample rate or at a reduced sample + * rate. In a case where some slaves are accessed at the Sample Rate and some + * slaves are accessed at the reduced rate, the sequence of accessing the slaves + * (Slave 0 to Slave 4) is still followed. However, the reduced rate slaves will + * be skipped if their access rate dictates that they should not be accessed + * during that particular cycle. For further information regarding the reduced + * access rate, please refer to Register 52. Whether a slave is accessed at the + * Sample Rate or at the reduced rate is determined by the Delay Enable bits in + * Register 103. + * + * @param num Slave number (0-3) + * @return Current address for specified slave + * @see MPU6050_RA_I2C_SLV0_ADDR + */ +uint8_t MPU6050_getSlaveAddress(uint8_t num) { + if (num > 3) return 0; + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_ADDR + num*3, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set the I2C address of the specified slave (0-3). + * @param num Slave number (0-3) + * @param address New address for specified slave + * @see getSlaveAddress() + * @see MPU6050_RA_I2C_SLV0_ADDR + */ +void MPU6050_setSlaveAddress(uint8_t num, uint8_t address) { + if (num > 3) return; + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_ADDR + num*3, address); +} +/** Get the active internal register for the specified slave (0-3). + * Read/write operations for this slave will be done to whatever internal + * register address is stored in this MPU register. + * + * The MPU-6050 supports a total of five slaves, but Slave 4 has unique + * characteristics, and so it has its own functions. + * + * @param num Slave number (0-3) + * @return Current active register for specified slave + * @see MPU6050_RA_I2C_SLV0_REG + */ +uint8_t MPU6050_getSlaveRegister(uint8_t num) { + if (num > 3) return 0; + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_REG + num*3, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set the active internal register for the specified slave (0-3). + * @param num Slave number (0-3) + * @param reg New active register for specified slave + * @see getSlaveRegister() + * @see MPU6050_RA_I2C_SLV0_REG + */ +void MPU6050_setSlaveRegister(uint8_t num, uint8_t reg) { + if (num > 3) return; + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_REG + num*3, reg); +} +/** Get the enabled value for the specified slave (0-3). + * When set to 1, this bit enables Slave 0 for data transfer operations. When + * cleared to 0, this bit disables Slave 0 from data transfer operations. + * @param num Slave number (0-3) + * @return Current enabled value for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +bool MPU6050_getSlaveEnabled(uint8_t num) { + if (num > 3) return 0; + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set the enabled value for the specified slave (0-3). + * @param num Slave number (0-3) + * @param enabled New enabled value for specified slave + * @see getSlaveEnabled() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050_setSlaveEnabled(uint8_t num, bool enabled) { + if (num > 3) return; + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_EN_BIT, enabled); +} +/** Get word pair byte-swapping enabled for the specified slave (0-3). + * When set to 1, this bit enables byte swapping. When byte swapping is enabled, + * the high and low bytes of a word pair are swapped. Please refer to + * I2C_SLV0_GRP for the pairing convention of the word pairs. When cleared to 0, + * bytes transferred to and from Slave 0 will be written to EXT_SENS_DATA + * registers in the order they were transferred. + * + * @param num Slave number (0-3) + * @return Current word pair byte-swapping enabled value for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +bool MPU6050_getSlaveWordByteSwap(uint8_t num) { + if (num > 3) return 0; + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_BYTE_SW_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set word pair byte-swapping enabled for the specified slave (0-3). + * @param num Slave number (0-3) + * @param enabled New word pair byte-swapping enabled value for specified slave + * @see getSlaveWordByteSwap() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050_setSlaveWordByteSwap(uint8_t num, bool enabled) { + if (num > 3) return; + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_BYTE_SW_BIT, enabled); +} +/** Get write mode for the specified slave (0-3). + * When set to 1, the transaction will read or write data only. When cleared to + * 0, the transaction will write a register address prior to reading or writing + * data. This should equal 0 when specifying the register address within the + * Slave device to/from which the ensuing data transaction will take place. + * + * @param num Slave number (0-3) + * @return Current write mode for specified slave (0 = register address + data, 1 = data only) + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +bool MPU6050_getSlaveWriteMode(uint8_t num) { + if (num > 3) return 0; + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_REG_DIS_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set write mode for the specified slave (0-3). + * @param num Slave number (0-3) + * @param mode New write mode for specified slave (0 = register address + data, 1 = data only) + * @see getSlaveWriteMode() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050_setSlaveWriteMode(uint8_t num, bool mode) { + if (num > 3) return; + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_REG_DIS_BIT, mode); +} +/** Get word pair grouping order offset for the specified slave (0-3). + * This sets specifies the grouping order of word pairs received from registers. + * When cleared to 0, bytes from register addresses 0 and 1, 2 and 3, etc (even, + * then odd register addresses) are paired to form a word. When set to 1, bytes + * from register addresses are paired 1 and 2, 3 and 4, etc. (odd, then even + * register addresses) are paired to form a word. + * + * @param num Slave number (0-3) + * @return Current word pair grouping order offset for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +bool MPU6050_getSlaveWordGroupOffset(uint8_t num) { + if (num > 3) return 0; + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_GRP_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set word pair grouping order offset for the specified slave (0-3). + * @param num Slave number (0-3) + * @param enabled New word pair grouping order offset for specified slave + * @see getSlaveWordGroupOffset() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050_setSlaveWordGroupOffset(uint8_t num, bool enabled) { + if (num > 3) return; + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_GRP_BIT, enabled); +} +/** Get number of bytes to read for the specified slave (0-3). + * Specifies the number of bytes transferred to and from Slave 0. Clearing this + * bit to 0 is equivalent to disabling the register by writing 0 to I2C_SLV0_EN. + * @param num Slave number (0-3) + * @return Number of bytes to read for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +uint8_t MPU6050_getSlaveDataLength(uint8_t num) { + if (num > 3) return 0; + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_LEN_BIT, MPU6050_I2C_SLV_LEN_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set number of bytes to read for the specified slave (0-3). + * @param num Slave number (0-3) + * @param length Number of bytes to read for specified slave + * @see getSlaveDataLength() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050_setSlaveDataLength(uint8_t num, uint8_t length) { + if (num > 3) return; + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_LEN_BIT, MPU6050_I2C_SLV_LEN_LENGTH, length); +} + +// I2C_SLV* registers (Slave 4) + +/** Get the I2C address of Slave 4. + * Note that Bit 7 (MSB) controls read/write mode. If Bit 7 is set, it's a read + * operation, and if it is cleared, then it's a write operation. The remaining + * bits (6-0) are the 7-bit device address of the slave device. + * + * @return Current address for Slave 4 + * @see getSlaveAddress() + * @see MPU6050_RA_I2C_SLV4_ADDR + */ +uint8_t MPU6050_getSlave4Address() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_ADDR, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set the I2C address of Slave 4. + * @param address New address for Slave 4 + * @see getSlave4Address() + * @see MPU6050_RA_I2C_SLV4_ADDR + */ +void MPU6050_setSlave4Address(uint8_t address) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_ADDR, address); +} +/** Get the active internal register for the Slave 4. + * Read/write operations for this slave will be done to whatever internal + * register address is stored in this MPU register. + * + * @return Current active register for Slave 4 + * @see MPU6050_RA_I2C_SLV4_REG + */ +uint8_t MPU6050_getSlave4Register() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_REG, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set the active internal register for Slave 4. + * @param reg New active register for Slave 4 + * @see getSlave4Register() + * @see MPU6050_RA_I2C_SLV4_REG + */ +void MPU6050_setSlave4Register(uint8_t reg) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_REG, reg); +} +/** Set new byte to write to Slave 4. + * This register stores the data to be written into the Slave 4. If I2C_SLV4_RW + * is set 1 (set to read), this register has no effect. + * @param data New byte to write to Slave 4 + * @see MPU6050_RA_I2C_SLV4_DO + */ +void MPU6050_setSlave4OutputByte(uint8_t data) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_DO, data); +} +/** Get the enabled value for the Slave 4. + * When set to 1, this bit enables Slave 4 for data transfer operations. When + * cleared to 0, this bit disables Slave 4 from data transfer operations. + * @return Current enabled value for Slave 4 + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +bool MPU6050_getSlave4Enabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set the enabled value for Slave 4. + * @param enabled New enabled value for Slave 4 + * @see getSlave4Enabled() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050_setSlave4Enabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_EN_BIT, enabled); +} +/** Get the enabled value for Slave 4 transaction interrupts. + * When set to 1, this bit enables the generation of an interrupt signal upon + * completion of a Slave 4 transaction. When cleared to 0, this bit disables the + * generation of an interrupt signal upon completion of a Slave 4 transaction. + * The interrupt status can be observed in Register 54. + * + * @return Current enabled value for Slave 4 transaction interrupts. + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +bool MPU6050_getSlave4InterruptEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_INT_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set the enabled value for Slave 4 transaction interrupts. + * @param enabled New enabled value for Slave 4 transaction interrupts. + * @see getSlave4InterruptEnabled() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050_setSlave4InterruptEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_INT_EN_BIT, enabled); +} +/** Get write mode for Slave 4. + * When set to 1, the transaction will read or write data only. When cleared to + * 0, the transaction will write a register address prior to reading or writing + * data. This should equal 0 when specifying the register address within the + * Slave device to/from which the ensuing data transaction will take place. + * + * @return Current write mode for Slave 4 (0 = register address + data, 1 = data only) + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +bool MPU6050_getSlave4WriteMode() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_REG_DIS_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set write mode for the Slave 4. + * @param mode New write mode for Slave 4 (0 = register address + data, 1 = data only) + * @see getSlave4WriteMode() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050_setSlave4WriteMode(bool mode) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_REG_DIS_BIT, mode); +} +/** Get Slave 4 master delay value. + * This configures the reduced access rate of I2C slaves relative to the Sample + * Rate. When a slave's access rate is decreased relative to the Sample Rate, + * the slave is accessed every: + * + * 1 / (1 + I2C_MST_DLY) samples + * + * This base Sample Rate in turn is determined by SMPLRT_DIV (register 25) and + * DLPF_CFG (register 26). Whether a slave's access rate is reduced relative to + * the Sample Rate is determined by I2C_MST_DELAY_CTRL (register 103). For + * further information regarding the Sample Rate, please refer to register 25. + * + * @return Current Slave 4 master delay value + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +uint8_t MPU6050_getSlave4MasterDelay() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_MST_DLY_BIT, MPU6050_I2C_SLV4_MST_DLY_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Slave 4 master delay value. + * @param delay New Slave 4 master delay value + * @see getSlave4MasterDelay() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050_setSlave4MasterDelay(uint8_t delay) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_MST_DLY_BIT, MPU6050_I2C_SLV4_MST_DLY_LENGTH, delay); +} +/** Get last available byte read from Slave 4. + * This register stores the data read from Slave 4. This field is populated + * after a read transaction. + * @return Last available byte read from to Slave 4 + * @see MPU6050_RA_I2C_SLV4_DI + */ +uint8_t MPU6050_getSlate4InputByte() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_DI, mpu6050.buffer); + return mpu6050.buffer[0]; +} + +// I2C_MST_STATUS register + +/** Get FSYNC interrupt status. + * This bit reflects the status of the FSYNC interrupt from an external device + * into the MPU-60X0. This is used as a way to pass an external interrupt + * through the MPU-60X0 to the host application processor. When set to 1, this + * bit will cause an interrupt if FSYNC_INT_EN is asserted in INT_PIN_CFG + * (Register 55). + * @return FSYNC interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_getPassthroughStatus() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_PASS_THROUGH_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Slave 4 transaction done status. + * Automatically sets to 1 when a Slave 4 transaction has completed. This + * triggers an interrupt if the I2C_MST_INT_EN bit in the INT_ENABLE register + * (Register 56) is asserted and if the SLV_4_DONE_INT bit is asserted in the + * I2C_SLV4_CTRL register (Register 52). + * @return Slave 4 transaction done status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_getSlave4IsDone() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV4_DONE_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get master arbitration lost status. + * This bit automatically sets to 1 when the I2C Master has lost arbitration of + * the auxiliary I2C bus (an error condition). This triggers an interrupt if the + * I2C_MST_INT_EN bit in the INT_ENABLE register (Register 56) is asserted. + * @return Master arbitration lost status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_getLostArbitration() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_LOST_ARB_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Slave 4 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 4. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 4 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_getSlave4Nack() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV4_NACK_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Slave 3 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 3. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 3 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_getSlave3Nack() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV3_NACK_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Slave 2 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 2. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 2 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_getSlave2Nack() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV2_NACK_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Slave 1 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 1. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 1 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_getSlave1Nack() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV1_NACK_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Slave 0 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 0. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 0 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_getSlave0Nack() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV0_NACK_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} + +// INT_PIN_CFG register + +/** Get interrupt logic level mode. + * Will be set 0 for active-high, 1 for active-low. + * @return Current interrupt mode (0=active-high, 1=active-low) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_LEVEL_BIT + */ +bool MPU6050_getInterruptMode() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_LEVEL_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set interrupt logic level mode. + * @param mode New interrupt mode (0=active-high, 1=active-low) + * @see getInterruptMode() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_LEVEL_BIT + */ +void MPU6050_setInterruptMode(bool mode) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_LEVEL_BIT, mode); +} +/** Get interrupt drive mode. + * Will be set 0 for push-pull, 1 for open-drain. + * @return Current interrupt drive mode (0=push-pull, 1=open-drain) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_OPEN_BIT + */ +bool MPU6050_getInterruptDrive() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_OPEN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set interrupt drive mode. + * @param drive New interrupt drive mode (0=push-pull, 1=open-drain) + * @see getInterruptDrive() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_OPEN_BIT + */ +void MPU6050_setInterruptDrive(bool drive) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_OPEN_BIT, drive); +} +/** Get interrupt latch mode. + * Will be set 0 for 50us-pulse, 1 for latch-until-int-cleared. + * @return Current latch mode (0=50us-pulse, 1=latch-until-int-cleared) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_LATCH_INT_EN_BIT + */ +bool MPU6050_getInterruptLatch() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_LATCH_INT_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set interrupt latch mode. + * @param latch New latch mode (0=50us-pulse, 1=latch-until-int-cleared) + * @see getInterruptLatch() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_LATCH_INT_EN_BIT + */ +void MPU6050_setInterruptLatch(bool latch) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_LATCH_INT_EN_BIT, latch); +} +/** Get interrupt latch clear mode. + * Will be set 0 for status-read-only, 1 for any-register-read. + * @return Current latch clear mode (0=status-read-only, 1=any-register-read) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_RD_CLEAR_BIT + */ +bool MPU6050_getInterruptLatchClear() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_RD_CLEAR_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set interrupt latch clear mode. + * @param clear New latch clear mode (0=status-read-only, 1=any-register-read) + * @see getInterruptLatchClear() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_RD_CLEAR_BIT + */ +void MPU6050_setInterruptLatchClear(bool clear) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_RD_CLEAR_BIT, clear); +} +/** Get FSYNC interrupt logic level mode. + * @return Current FSYNC interrupt mode (0=active-high, 1=active-low) + * @see getFSyncInterruptMode() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT + */ +bool MPU6050_getFSyncInterruptLevel() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set FSYNC interrupt logic level mode. + * @param mode New FSYNC interrupt mode (0=active-high, 1=active-low) + * @see getFSyncInterruptMode() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT + */ +void MPU6050_setFSyncInterruptLevel(bool level) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT, level); +} +/** Get FSYNC pin interrupt enabled setting. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled setting + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_EN_BIT + */ +bool MPU6050_getFSyncInterruptEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set FSYNC pin interrupt enabled setting. + * @param enabled New FSYNC pin interrupt enabled setting + * @see getFSyncInterruptEnabled() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_EN_BIT + */ +void MPU6050_setFSyncInterruptEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_EN_BIT, enabled); +} +/** Get I2C bypass enabled status. + * When this bit is equal to 1 and I2C_MST_EN (Register 106 bit[5]) is equal to + * 0, the host application processor will be able to directly access the + * auxiliary I2C bus of the MPU-60X0. When this bit is equal to 0, the host + * application processor will not be able to directly access the auxiliary I2C + * bus of the MPU-60X0 regardless of the state of I2C_MST_EN (Register 106 + * bit[5]). + * @return Current I2C bypass enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_I2C_BYPASS_EN_BIT + */ +bool MPU6050_getI2CBypassEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_I2C_BYPASS_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set I2C bypass enabled status. + * When this bit is equal to 1 and I2C_MST_EN (Register 106 bit[5]) is equal to + * 0, the host application processor will be able to directly access the + * auxiliary I2C bus of the MPU-60X0. When this bit is equal to 0, the host + * application processor will not be able to directly access the auxiliary I2C + * bus of the MPU-60X0 regardless of the state of I2C_MST_EN (Register 106 + * bit[5]). + * @param enabled New I2C bypass enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_I2C_BYPASS_EN_BIT + */ +void MPU6050_setI2CBypassEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_I2C_BYPASS_EN_BIT, enabled); +} +/** Get reference clock output enabled status. + * When this bit is equal to 1, a reference clock output is provided at the + * CLKOUT pin. When this bit is equal to 0, the clock output is disabled. For + * further information regarding CLKOUT, please refer to the MPU-60X0 Product + * Specification document. + * @return Current reference clock output enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_CLKOUT_EN_BIT + */ +bool MPU6050_getClockOutputEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_CLKOUT_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set reference clock output enabled status. + * When this bit is equal to 1, a reference clock output is provided at the + * CLKOUT pin. When this bit is equal to 0, the clock output is disabled. For + * further information regarding CLKOUT, please refer to the MPU-60X0 Product + * Specification document. + * @param enabled New reference clock output enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_CLKOUT_EN_BIT + */ +void MPU6050_setClockOutputEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_CLKOUT_EN_BIT, enabled); +} + +// INT_ENABLE register + +/** Get full interrupt enabled status. + * Full register byte for all interrupts, for quick reading. Each bit will be + * set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +uint8_t MPU6050_getIntEnabled() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set full interrupt enabled status. + * Full register byte for all interrupts, for quick reading. Each bit should be + * set 0 for disabled, 1 for enabled. + * @param enabled New interrupt enabled status + * @see getIntFreefallEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +void MPU6050_setIntEnabled(uint8_t enabled) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, enabled); +} +/** Get Free Fall interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +bool MPU6050_getIntFreefallEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FF_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Free Fall interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntFreefallEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +void MPU6050_setIntFreefallEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FF_BIT, enabled); +} +/** Get Motion Detection interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_MOT_BIT + **/ +bool MPU6050_getIntMotionEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_MOT_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Motion Detection interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntMotionEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_MOT_BIT + **/ +void MPU6050_setIntMotionEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_MOT_BIT, enabled); +} +/** Get Zero Motion Detection interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_ZMOT_BIT + **/ +bool MPU6050_getIntZeroMotionEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_ZMOT_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Zero Motion Detection interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntZeroMotionEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_ZMOT_BIT + **/ +void MPU6050_setIntZeroMotionEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_ZMOT_BIT, enabled); +} +/** Get FIFO Buffer Overflow interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT + **/ +bool MPU6050_getIntFIFOBufferOverflowEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set FIFO Buffer Overflow interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntFIFOBufferOverflowEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT + **/ +void MPU6050_setIntFIFOBufferOverflowEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, enabled); +} +/** Get I2C Master interrupt enabled status. + * This enables any of the I2C Master interrupt sources to generate an + * interrupt. Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT + **/ +bool MPU6050_getIntI2CMasterEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_I2C_MST_INT_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set I2C Master interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntI2CMasterEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT + **/ +void MPU6050_setIntI2CMasterEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_I2C_MST_INT_BIT, enabled); +} +/** Get Data Ready interrupt enabled setting. + * This event occurs each time a write operation to all of the sensor registers + * has been completed. Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_DATA_RDY_BIT + */ +bool MPU6050_getIntDataReadyEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DATA_RDY_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Data Ready interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntDataReadyEnabled() + * @see MPU6050_RA_INT_CFG + * @see MPU6050_INTERRUPT_DATA_RDY_BIT + */ +void MPU6050_setIntDataReadyEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DATA_RDY_BIT, enabled); +} + +// INT_STATUS register + +/** Get full set of interrupt status bits. + * These bits clear to 0 after the register has been read. Very useful + * for getting multiple INT statuses, since each single bit read clears + * all of them because it has to read the whole byte. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + */ +uint8_t MPU6050_getIntStatus() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_INT_STATUS, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Free Fall interrupt status. + * This bit automatically sets to 1 when a Free Fall interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_FF_BIT + */ +bool MPU6050_getIntFreefallStatus() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_FF_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Motion Detection interrupt status. + * This bit automatically sets to 1 when a Motion Detection interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_MOT_BIT + */ +bool MPU6050_getIntMotionStatus() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_MOT_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Zero Motion Detection interrupt status. + * This bit automatically sets to 1 when a Zero Motion Detection interrupt has + * been generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_ZMOT_BIT + */ +bool MPU6050_getIntZeroMotionStatus() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_ZMOT_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get FIFO Buffer Overflow interrupt status. + * This bit automatically sets to 1 when a Free Fall interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT + */ +bool MPU6050_getIntFIFOBufferOverflowStatus() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get I2C Master interrupt status. + * This bit automatically sets to 1 when an I2C Master interrupt has been + * generated. For a list of I2C Master interrupts, please refer to Register 54. + * The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT + */ +bool MPU6050_getIntI2CMasterStatus() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_I2C_MST_INT_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Data Ready interrupt status. + * This bit automatically sets to 1 when a Data Ready interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_DATA_RDY_BIT + */ +bool MPU6050_getIntDataReadyStatus() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_DATA_RDY_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} + +// ACCEL_*OUT_* registers + +/** Get raw 9-axis motion sensor readings (accel/gyro/compass). + * FUNCTION NOT FULLY IMPLEMENTED YET. + * @param ax 16-bit signed integer container for accelerometer X-axis value + * @param ay 16-bit signed integer container for accelerometer Y-axis value + * @param az 16-bit signed integer container for accelerometer Z-axis value + * @param gx 16-bit signed integer container for gyroscope X-axis value + * @param gy 16-bit signed integer container for gyroscope Y-axis value + * @param gz 16-bit signed integer container for gyroscope Z-axis value + * @param mx 16-bit signed integer container for magnetometer X-axis value + * @param my 16-bit signed integer container for magnetometer Y-axis value + * @param mz 16-bit signed integer container for magnetometer Z-axis value + * @see getMotion6() + * @see getAcceleration() + * @see getRotation() + * @see MPU6050_RA_ACCEL_XOUT_H + */ +void MPU6050_getMotion9(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz, int16_t* mx, int16_t* my, int16_t* mz) { + MPU6050_getMotion6(ax, ay, az, gx, gy, gz); + // TODO: magnetometer integration +} +/** Get raw 6-axis motion sensor readings (accel/gyro). + * Retrieves all currently available motion sensor values. + * @param ax 16-bit signed integer container for accelerometer X-axis value + * @param ay 16-bit signed integer container for accelerometer Y-axis value + * @param az 16-bit signed integer container for accelerometer Z-axis value + * @param gx 16-bit signed integer container for gyroscope X-axis value + * @param gy 16-bit signed integer container for gyroscope Y-axis value + * @param gz 16-bit signed integer container for gyroscope Z-axis value + * @see getAcceleration() + * @see getRotation() + * @see MPU6050_RA_ACCEL_XOUT_H + */ +void MPU6050_getMotion6(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz) { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ACCEL_XOUT_H, 14, mpu6050.buffer); + *ax = (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; + *ay = (((int16_t)mpu6050.buffer[2]) << 8) | mpu6050.buffer[3]; + *az = (((int16_t)mpu6050.buffer[4]) << 8) | mpu6050.buffer[5]; + *gx = (((int16_t)mpu6050.buffer[8]) << 8) | mpu6050.buffer[9]; + *gy = (((int16_t)mpu6050.buffer[10]) << 8) | mpu6050.buffer[11]; + *gz = (((int16_t)mpu6050.buffer[12]) << 8) | mpu6050.buffer[13]; +} +/** Get 3-axis accelerometer readings. + * These registers store the most recent accelerometer measurements. + * Accelerometer measurements are written to these registers at the Sample Rate + * as defined in Register 25. + * + * The accelerometer measurement registers, along with the temperature + * measurement registers, gyroscope measurement registers, and external sensor + * data registers, are composed of two sets of registers: an internal register + * set and a user-facing read register set. + * + * The data within the accelerometer sensors' internal register set is always + * updated at the Sample Rate. Meanwhile, the user-facing read register set + * duplicates the internal register set's data values whenever the serial + * interface is idle. This guarantees that a burst read of sensor registers will + * read measurements from the same sampling instant. Note that if burst reads + * are not used, the user is responsible for ensuring a set of single byte reads + * correspond to a single sampling instant by checking the Data Ready interrupt. + * + * Each 16-bit accelerometer measurement has a full scale defined in ACCEL_FS + * (Register 28). For each full scale setting, the accelerometers' sensitivity + * per LSB in ACCEL_xOUT is shown in the table below: + * + *
+ * AFS_SEL | Full Scale Range | LSB Sensitivity
+ * --------+------------------+----------------
+ * 0       | +/- 2g           | 8192 LSB/mg
+ * 1       | +/- 4g           | 4096 LSB/mg
+ * 2       | +/- 8g           | 2048 LSB/mg
+ * 3       | +/- 16g          | 1024 LSB/mg
+ * 
+ * + * @param x 16-bit signed integer container for X-axis acceleration + * @param y 16-bit signed integer container for Y-axis acceleration + * @param z 16-bit signed integer container for Z-axis acceleration + * @see MPU6050_RA_GYRO_XOUT_H + */ +void MPU6050_getAcceleration(int16_t* x, int16_t* y, int16_t* z) { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ACCEL_XOUT_H, 6, mpu6050.buffer); + *x = (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; + *y = (((int16_t)mpu6050.buffer[2]) << 8) | mpu6050.buffer[3]; + *z = (((int16_t)mpu6050.buffer[4]) << 8) | mpu6050.buffer[5]; +} +/** Get X-axis accelerometer reading. + * @return X-axis acceleration measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_ACCEL_XOUT_H + */ +int16_t MPU6050_getAccelerationX() { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ACCEL_XOUT_H, 2, mpu6050.buffer); + return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; +} +/** Get Y-axis accelerometer reading. + * @return Y-axis acceleration measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_ACCEL_YOUT_H + */ +int16_t MPU6050_getAccelerationY() { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ACCEL_YOUT_H, 2, mpu6050.buffer); + return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; +} +/** Get Z-axis accelerometer reading. + * @return Z-axis acceleration measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_ACCEL_ZOUT_H + */ +int16_t MPU6050_getAccelerationZ() { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ACCEL_ZOUT_H, 2, mpu6050.buffer); + return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; +} + +// TEMP_OUT_* registers + +/** Get current internal temperature. + * @return Temperature reading in 16-bit 2's complement format + * @see MPU6050_RA_TEMP_OUT_H + */ +int16_t MPU6050_getTemperature() { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_TEMP_OUT_H, 2, mpu6050.buffer); + return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; +} + +// GYRO_*OUT_* registers + +/** Get 3-axis gyroscope readings. + * These gyroscope measurement registers, along with the accelerometer + * measurement registers, temperature measurement registers, and external sensor + * data registers, are composed of two sets of registers: an internal register + * set and a user-facing read register set. + * The data within the gyroscope sensors' internal register set is always + * updated at the Sample Rate. Meanwhile, the user-facing read register set + * duplicates the internal register set's data values whenever the serial + * interface is idle. This guarantees that a burst read of sensor registers will + * read measurements from the same sampling instant. Note that if burst reads + * are not used, the user is responsible for ensuring a set of single byte reads + * correspond to a single sampling instant by checking the Data Ready interrupt. + * + * Each 16-bit gyroscope measurement has a full scale defined in FS_SEL + * (Register 27). For each full scale setting, the gyroscopes' sensitivity per + * LSB in GYRO_xOUT is shown in the table below: + * + *
+ * FS_SEL | Full Scale Range   | LSB Sensitivity
+ * -------+--------------------+----------------
+ * 0      | +/- 250 degrees/s  | 131 LSB/deg/s
+ * 1      | +/- 500 degrees/s  | 65.5 LSB/deg/s
+ * 2      | +/- 1000 degrees/s | 32.8 LSB/deg/s
+ * 3      | +/- 2000 degrees/s | 16.4 LSB/deg/s
+ * 
+ * + * @param x 16-bit signed integer container for X-axis rotation + * @param y 16-bit signed integer container for Y-axis rotation + * @param z 16-bit signed integer container for Z-axis rotation + * @see getMotion6() + * @see MPU6050_RA_GYRO_XOUT_H + */ +void MPU6050_getRotation(int16_t* x, int16_t* y, int16_t* z) { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_GYRO_XOUT_H, 6, mpu6050.buffer); + *x = (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; + *y = (((int16_t)mpu6050.buffer[2]) << 8) | mpu6050.buffer[3]; + *z = (((int16_t)mpu6050.buffer[4]) << 8) | mpu6050.buffer[5]; +} +/** Get X-axis gyroscope reading. + * @return X-axis rotation measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_GYRO_XOUT_H + */ +int16_t MPU6050_getRotationX() { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_GYRO_XOUT_H, 2, mpu6050.buffer); + return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; +} +/** Get Y-axis gyroscope reading. + * @return Y-axis rotation measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_GYRO_YOUT_H + */ +int16_t MPU6050_getRotationY() { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_GYRO_YOUT_H, 2, mpu6050.buffer); + return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; +} +/** Get Z-axis gyroscope reading. + * @return Z-axis rotation measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_GYRO_ZOUT_H + */ +int16_t MPU6050_getRotationZ() { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_GYRO_ZOUT_H, 2, mpu6050.buffer); + return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; +} + +// EXT_SENS_DATA_* registers + +/** Read single byte from external sensor data register. + * These registers store data read from external sensors by the Slave 0, 1, 2, + * and 3 on the auxiliary I2C interface. Data read by Slave 4 is stored in + * I2C_SLV4_DI (Register 53). + * + * External sensor data is written to these registers at the Sample Rate as + * defined in Register 25. This access rate can be reduced by using the Slave + * Delay Enable registers (Register 103). + * + * External sensor data registers, along with the gyroscope measurement + * registers, accelerometer measurement registers, and temperature measurement + * registers, are composed of two sets of registers: an internal register set + * and a user-facing read register set. + * + * The data within the external sensors' internal register set is always updated + * at the Sample Rate (or the reduced access rate) whenever the serial interface + * is idle. This guarantees that a burst read of sensor registers will read + * measurements from the same sampling instant. Note that if burst reads are not + * used, the user is responsible for ensuring a set of single byte reads + * correspond to a single sampling instant by checking the Data Ready interrupt. + * + * Data is placed in these external sensor data registers according to + * I2C_SLV0_CTRL, I2C_SLV1_CTRL, I2C_SLV2_CTRL, and I2C_SLV3_CTRL (Registers 39, + * 42, 45, and 48). When more than zero bytes are read (I2C_SLVx_LEN > 0) from + * an enabled slave (I2C_SLVx_EN = 1), the slave is read at the Sample Rate (as + * defined in Register 25) or delayed rate (if specified in Register 52 and + * 103). During each Sample cycle, slave reads are performed in order of Slave + * number. If all slaves are enabled with more than zero bytes to be read, the + * order will be Slave 0, followed by Slave 1, Slave 2, and Slave 3. + * + * Each enabled slave will have EXT_SENS_DATA registers associated with it by + * number of bytes read (I2C_SLVx_LEN) in order of slave number, starting from + * EXT_SENS_DATA_00. Note that this means enabling or disabling a slave may + * change the higher numbered slaves' associated registers. Furthermore, if + * fewer total bytes are being read from the external sensors as a result of + * such a change, then the data remaining in the registers which no longer have + * an associated slave device (i.e. high numbered registers) will remain in + * these previously allocated registers unless reset. + * + * If the sum of the read lengths of all SLVx transactions exceed the number of + * available EXT_SENS_DATA registers, the excess bytes will be dropped. There + * are 24 EXT_SENS_DATA registers and hence the total read lengths between all + * the slaves cannot be greater than 24 or some bytes will be lost. + * + * Note: Slave 4's behavior is distinct from that of Slaves 0-3. For further + * information regarding the characteristics of Slave 4, please refer to + * Registers 49 to 53. + * + * EXAMPLE: + * Suppose that Slave 0 is enabled with 4 bytes to be read (I2C_SLV0_EN = 1 and + * I2C_SLV0_LEN = 4) while Slave 1 is enabled with 2 bytes to be read so that + * I2C_SLV1_EN = 1 and I2C_SLV1_LEN = 2. In such a situation, EXT_SENS_DATA _00 + * through _03 will be associated with Slave 0, while EXT_SENS_DATA _04 and 05 + * will be associated with Slave 1. If Slave 2 is enabled as well, registers + * starting from EXT_SENS_DATA_06 will be allocated to Slave 2. + * + * If Slave 2 is disabled while Slave 3 is enabled in this same situation, then + * registers starting from EXT_SENS_DATA_06 will be allocated to Slave 3 + * instead. + * + * REGISTER ALLOCATION FOR DYNAMIC DISABLE VS. NORMAL DISABLE: + * If a slave is disabled at any time, the space initially allocated to the + * slave in the EXT_SENS_DATA register, will remain associated with that slave. + * This is to avoid dynamic adjustment of the register allocation. + * + * The allocation of the EXT_SENS_DATA registers is recomputed only when (1) all + * slaves are disabled, or (2) the I2C_MST_RST bit is set (Register 106). + * + * This above is also true if one of the slaves gets NACKed and stops + * functioning. + * + * @param position Starting position (0-23) + * @return Byte read from register + */ +uint8_t MPU6050_getExternalSensorByte(int position) { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Read word (2 bytes) from external sensor data registers. + * @param position Starting position (0-21) + * @return Word read from register + * @see getExternalSensorByte() + */ +uint16_t MPU6050_getExternalSensorWord(int position) { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, 2, mpu6050.buffer); + return (((uint16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; +} +/** Read double word (4 bytes) from external sensor data registers. + * @param position Starting position (0-20) + * @return Double word read from registers + * @see getExternalSensorByte() + */ +uint32_t MPU6050_getExternalSensorDWord(int position) { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, 4, mpu6050.buffer); + return (((uint32_t)mpu6050.buffer[0]) << 24) | (((uint32_t)mpu6050.buffer[1]) << 16) | (((uint16_t)mpu6050.buffer[2]) << 8) | mpu6050.buffer[3]; +} + +// MOT_DETECT_STATUS register + +/** Get X-axis negative motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_XNEG_BIT + */ +bool MPU6050_getXNegMotionDetected() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_XNEG_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get X-axis positive motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_XPOS_BIT + */ +bool MPU6050_getXPosMotionDetected() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_XPOS_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Y-axis negative motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_YNEG_BIT + */ +bool MPU6050_getYNegMotionDetected() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_YNEG_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Y-axis positive motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_YPOS_BIT + */ +bool MPU6050_getYPosMotionDetected() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_YPOS_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Z-axis negative motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_ZNEG_BIT + */ +bool MPU6050_getZNegMotionDetected() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZNEG_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Z-axis positive motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_ZPOS_BIT + */ +bool MPU6050_getZPosMotionDetected() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZPOS_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get zero motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_ZRMOT_BIT + */ +bool MPU6050_getZeroMotionDetected() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZRMOT_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} + +// I2C_SLV*_DO register + +/** Write byte to Data Output container for specified slave. + * This register holds the output data written into Slave when Slave is set to + * write mode. For further information regarding Slave control, please + * refer to Registers 37 to 39 and immediately following. + * @param num Slave number (0-3) + * @param data Byte to write + * @see MPU6050_RA_I2C_SLV0_DO + */ +void MPU6050_setSlaveOutputByte(uint8_t num, uint8_t data) { + if (num > 3) return; + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_DO + num, data); +} + +// I2C_MST_DELAY_CTRL register + +/** Get external data shadow delay enabled status. + * This register is used to specify the timing of external sensor data + * shadowing. When DELAY_ES_SHADOW is set to 1, shadowing of external + * sensor data is delayed until all data has been received. + * @return Current external data shadow delay enabled status. + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT + */ +bool MPU6050_getExternalShadowDelayEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set external data shadow delay enabled status. + * @param enabled New external data shadow delay enabled status. + * @see getExternalShadowDelayEnabled() + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT + */ +void MPU6050_setExternalShadowDelayEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT, enabled); +} +/** Get slave delay enabled status. + * When a particular slave delay is enabled, the rate of access for the that + * slave device is reduced. When a slave's access rate is decreased relative to + * the Sample Rate, the slave is accessed every: + * + * 1 / (1 + I2C_MST_DLY) Samples + * + * This base Sample Rate in turn is determined by SMPLRT_DIV (register * 25) + * and DLPF_CFG (register 26). + * + * For further information regarding I2C_MST_DLY, please refer to register 52. + * For further information regarding the Sample Rate, please refer to register 25. + * + * @param num Slave number (0-4) + * @return Current slave delay enabled status. + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT + */ +bool MPU6050_getSlaveDelayEnabled(uint8_t num) { + // MPU6050_DELAYCTRL_I2C_SLV4_DLY_EN_BIT is 4, SLV3 is 3, etc. + if (num > 4) return 0; + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, num, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set slave delay enabled status. + * @param num Slave number (0-4) + * @param enabled New slave delay enabled status. + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT + */ +void MPU6050_setSlaveDelayEnabled(uint8_t num, bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, num, enabled); +} + +// SIGNAL_PATH_RESET register + +/** Reset gyroscope signal path. + * The reset will revert the signal path analog to digital converters and + * filters to their power up configurations. + * @see MPU6050_RA_SIGNAL_PATH_RESET + * @see MPU6050_PATHRESET_GYRO_RESET_BIT + */ +void MPU6050_resetGyroscopePath() { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_GYRO_RESET_BIT, true); +} +/** Reset accelerometer signal path. + * The reset will revert the signal path analog to digital converters and + * filters to their power up configurations. + * @see MPU6050_RA_SIGNAL_PATH_RESET + * @see MPU6050_PATHRESET_ACCEL_RESET_BIT + */ +void MPU6050_resetAccelerometerPath() { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_ACCEL_RESET_BIT, true); +} +/** Reset temperature sensor signal path. + * The reset will revert the signal path analog to digital converters and + * filters to their power up configurations. + * @see MPU6050_RA_SIGNAL_PATH_RESET + * @see MPU6050_PATHRESET_TEMP_RESET_BIT + */ +void MPU6050_resetTemperaturePath() { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_TEMP_RESET_BIT, true); +} + +// MOT_DETECT_CTRL register + +/** Get accelerometer power-on delay. + * The accelerometer data path provides samples to the sensor registers, Motion + * detection, Zero Motion detection, and Free Fall detection modules. The + * signal path contains filters which must be flushed on wake-up with new + * samples before the detection modules begin operations. The default wake-up + * delay, of 4ms can be lengthened by up to 3ms. This additional delay is + * specified in ACCEL_ON_DELAY in units of 1 LSB = 1 ms. The user may select + * any value above zero unless instructed otherwise by InvenSense. Please refer + * to Section 8 of the MPU-6000/MPU-6050 Product Specification document for + * further information regarding the detection modules. + * @return Current accelerometer power-on delay + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_ACCEL_ON_DELAY_BIT + */ +uint8_t MPU6050_getAccelerometerPowerOnDelay() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_ACCEL_ON_DELAY_BIT, MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set accelerometer power-on delay. + * @param delay New accelerometer power-on delay (0-3) + * @see getAccelerometerPowerOnDelay() + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_ACCEL_ON_DELAY_BIT + */ +void MPU6050_setAccelerometerPowerOnDelay(uint8_t delay) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_ACCEL_ON_DELAY_BIT, MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH, delay); +} +/** Get Free Fall detection counter decrement configuration. + * Detection is registered by the Free Fall detection module after accelerometer + * measurements meet their respective threshold conditions over a specified + * number of samples. When the threshold conditions are met, the corresponding + * detection counter increments by 1. The user may control the rate at which the + * detection counter decrements when the threshold condition is not met by + * configuring FF_COUNT. The decrement rate can be set according to the + * following table: + * + *
+ * FF_COUNT | Counter Decrement
+ * ---------+------------------
+ * 0        | Reset
+ * 1        | 1
+ * 2        | 2
+ * 3        | 4
+ * 
+ * + * When FF_COUNT is configured to 0 (reset), any non-qualifying sample will + * reset the counter to 0. For further information on Free Fall detection, + * please refer to Registers 29 to 32. + * + * @return Current decrement configuration + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_FF_COUNT_BIT + */ +uint8_t MPU6050_getFreefallDetectionCounterDecrement() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_FF_COUNT_BIT, MPU6050_DETECT_FF_COUNT_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Free Fall detection counter decrement configuration. + * @param decrement New decrement configuration value + * @see getFreefallDetectionCounterDecrement() + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_FF_COUNT_BIT + */ +void MPU6050_setFreefallDetectionCounterDecrement(uint8_t decrement) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_FF_COUNT_BIT, MPU6050_DETECT_FF_COUNT_LENGTH, decrement); +} +/** Get Motion detection counter decrement configuration. + * Detection is registered by the Motion detection module after accelerometer + * measurements meet their respective threshold conditions over a specified + * number of samples. When the threshold conditions are met, the corresponding + * detection counter increments by 1. The user may control the rate at which the + * detection counter decrements when the threshold condition is not met by + * configuring MOT_COUNT. The decrement rate can be set according to the + * following table: + * + *
+ * MOT_COUNT | Counter Decrement
+ * ----------+------------------
+ * 0         | Reset
+ * 1         | 1
+ * 2         | 2
+ * 3         | 4
+ * 
+ * + * When MOT_COUNT is configured to 0 (reset), any non-qualifying sample will + * reset the counter to 0. For further information on Motion detection, + * please refer to Registers 29 to 32. + * + */ +uint8_t MPU6050_getMotionDetectionCounterDecrement() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_MOT_COUNT_BIT, MPU6050_DETECT_MOT_COUNT_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Motion detection counter decrement configuration. + * @param decrement New decrement configuration value + * @see getMotionDetectionCounterDecrement() + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_MOT_COUNT_BIT + */ +void MPU6050_setMotionDetectionCounterDecrement(uint8_t decrement) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_MOT_COUNT_BIT, MPU6050_DETECT_MOT_COUNT_LENGTH, decrement); +} + +// USER_CTRL register + +/** Get FIFO enabled status. + * When this bit is set to 0, the FIFO mpu6050.buffer is disabled. The FIFO mpu6050.buffer + * cannot be written to or read from while disabled. The FIFO mpu6050.buffer's state + * does not change unless the MPU-60X0 is power cycled. + * @return Current FIFO enabled status + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_FIFO_EN_BIT + */ +bool MPU6050_getFIFOEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set FIFO enabled status. + * @param enabled New FIFO enabled status + * @see getFIFOEnabled() + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_FIFO_EN_BIT + */ +void MPU6050_setFIFOEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_EN_BIT, enabled); +} +/** Get I2C Master Mode enabled status. + * When this mode is enabled, the MPU-60X0 acts as the I2C Master to the + * external sensor slave devices on the auxiliary I2C bus. When this bit is + * cleared to 0, the auxiliary I2C bus lines (AUX_DA and AUX_CL) are logically + * driven by the primary I2C bus (SDA and SCL). This is a precondition to + * enabling Bypass Mode. For further information regarding Bypass Mode, please + * refer to Register 55. + * @return Current I2C Master Mode enabled status + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_I2C_MST_EN_BIT + */ +bool MPU6050_getI2CMasterModeEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set I2C Master Mode enabled status. + * @param enabled New I2C Master Mode enabled status + * @see getI2CMasterModeEnabled() + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_I2C_MST_EN_BIT + */ +void MPU6050_setI2CMasterModeEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_EN_BIT, enabled); +} +/** Switch from I2C to SPI mode (MPU-6000 only) + * If this is set, the primary SPI interface will be enabled in place of the + * disabled primary I2C interface. + */ +void MPU6050_switchSPIEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_IF_DIS_BIT, enabled); +} +/** Reset the FIFO. + * This bit resets the FIFO mpu6050.buffer when set to 1 while FIFO_EN equals 0. This + * bit automatically clears to 0 after the reset has been triggered. + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_FIFO_RESET_BIT + */ +void MPU6050_resetFIFO() { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_RESET_BIT, true); +} +/** Reset the I2C Master. + * This bit resets the I2C Master when set to 1 while I2C_MST_EN equals 0. + * This bit automatically clears to 0 after the reset has been triggered. + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_I2C_MST_RESET_BIT + */ +void MPU6050_resetI2CMaster() { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_RESET_BIT, true); +} +/** Reset all sensor registers and signal paths. + * When set to 1, this bit resets the signal paths for all sensors (gyroscopes, + * accelerometers, and temperature sensor). This operation will also clear the + * sensor registers. This bit automatically clears to 0 after the reset has been + * triggered. + * + * When resetting only the signal path (and not the sensor registers), please + * use Register 104, SIGNAL_PATH_RESET. + * + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_SIG_COND_RESET_BIT + */ +void MPU6050_resetSensors() { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_SIG_COND_RESET_BIT, true); +} + +// PWR_MGMT_1 register + +/** Trigger a full device reset. + * A small delay of ~50ms may be desirable after triggering a reset. + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_DEVICE_RESET_BIT + */ +void MPU6050_reset() { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_DEVICE_RESET_BIT, true); +} +/** Get sleep mode status. + * Setting the SLEEP bit in the register puts the device into very low power + * sleep mode. In this mode, only the serial interface and internal registers + * remain active, allowing for a very low standby current. Clearing this bit + * puts the device back into normal mode. To save power, the individual standby + * selections for each of the gyros should be used if any gyro axis is not used + * by the application. + * @return Current sleep mode enabled status + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_SLEEP_BIT + */ +bool MPU6050_getSleepEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set sleep mode status. + * @param enabled New sleep mode enabled status + * @see getSleepEnabled() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_SLEEP_BIT + */ +void MPU6050_setSleepEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, enabled); +} +/** Get wake cycle enabled status. + * When this bit is set to 1 and SLEEP is disabled, the MPU-60X0 will cycle + * between sleep mode and waking up to take a single sample of data from active + * sensors at a rate determined by LP_WAKE_CTRL (register 108). + * @return Current sleep mode enabled status + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CYCLE_BIT + */ +bool MPU6050_getWakeCycleEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CYCLE_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set wake cycle enabled status. + * @param enabled New sleep mode enabled status + * @see getWakeCycleEnabled() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CYCLE_BIT + */ +void MPU6050_setWakeCycleEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CYCLE_BIT, enabled); +} +/** Get temperature sensor enabled status. + * Control the usage of the internal temperature sensor. + * + * Note: this register stores the *disabled* value, but for consistency with the + * rest of the code, the function is named and used with standard true/false + * values to indicate whether the sensor is enabled or disabled, respectively. + * + * @return Current temperature sensor enabled status + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_TEMP_DIS_BIT + */ +bool MPU6050_getTempSensorEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_TEMP_DIS_BIT, mpu6050.buffer); + return mpu6050.buffer[0] == 0; // 1 is actually disabled here +} +/** Set temperature sensor enabled status. + * Note: this register stores the *disabled* value, but for consistency with the + * rest of the code, the function is named and used with standard true/false + * values to indicate whether the sensor is enabled or disabled, respectively. + * + * @param enabled New temperature sensor enabled status + * @see getTempSensorEnabled() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_TEMP_DIS_BIT + */ +void MPU6050_setTempSensorEnabled(bool enabled) { + // 1 is actually disabled here + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_TEMP_DIS_BIT, !enabled); +} +/** Get clock source setting. + * @return Current clock source setting + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CLKSEL_BIT + * @see MPU6050_PWR1_CLKSEL_LENGTH + */ +uint8_t MPU6050_getClockSource() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set clock source setting. + * An internal 8MHz oscillator, gyroscope based clock, or external sources can + * be selected as the MPU-60X0 clock source. When the internal 8 MHz oscillator + * or an external source is chosen as the clock source, the MPU-60X0 can operate + * in low power modes with the gyroscopes disabled. + * + * Upon power up, the MPU-60X0 clock source defaults to the internal oscillator. + * However, it is highly recommended that the device be configured to use one of + * the gyroscopes (or an external clock source) as the clock reference for + * improved stability. The clock source can be selected according to the following table: + * + *
+ * CLK_SEL | Clock Source
+ * --------+--------------------------------------
+ * 0       | Internal oscillator
+ * 1       | PLL with X Gyro reference
+ * 2       | PLL with Y Gyro reference
+ * 3       | PLL with Z Gyro reference
+ * 4       | PLL with external 32.768kHz reference
+ * 5       | PLL with external 19.2MHz reference
+ * 6       | Reserved
+ * 7       | Stops the clock and keeps the timing generator in reset
+ * 
+ * + * @param source New clock source setting + * @see getClockSource() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CLKSEL_BIT + * @see MPU6050_PWR1_CLKSEL_LENGTH + */ +void MPU6050_setClockSource(uint8_t source) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, source); +} + +// PWR_MGMT_2 register + +/** Get wake frequency in Accel-Only Low Power Mode. + * The MPU-60X0 can be put into Accerlerometer Only Low Power Mode by setting + * PWRSEL to 1 in the Power Management 1 register (Register 107). In this mode, + * the device will power off all devices except for the primary I2C interface, + * waking only the accelerometer at fixed intervals to take a single + * measurement. The frequency of wake-ups can be configured with LP_WAKE_CTRL + * as shown below: + * + *
+ * LP_WAKE_CTRL | Wake-up Frequency
+ * -------------+------------------
+ * 0            | 1.25 Hz
+ * 1            | 2.5 Hz
+ * 2            | 5 Hz
+ * 3            | 10 Hz
+ * 
+ *
+ * For further information regarding the MPU-60X0's power modes, please refer to
+ * Register 107.
+ *
+ * @return Current wake frequency
+ * @see MPU6050_RA_PWR_MGMT_2
+ */
+uint8_t MPU6050_getWakeFrequency() {
+    I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_LP_WAKE_CTRL_BIT, MPU6050_PWR2_LP_WAKE_CTRL_LENGTH, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+/** Set wake frequency in Accel-Only Low Power Mode.
+ * @param frequency New wake frequency
+ * @see MPU6050_RA_PWR_MGMT_2
+ */
+void MPU6050_setWakeFrequency(uint8_t frequency) {
+    I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_LP_WAKE_CTRL_BIT, MPU6050_PWR2_LP_WAKE_CTRL_LENGTH, frequency);
+}
+
+/** Get X-axis accelerometer standby enabled status.
+ * If enabled, the X-axis will not gather or report data (or use power).
+ * @return Current X-axis standby enabled status
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_XA_BIT
+ */
+bool MPU6050_getStandbyXAccelEnabled() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XA_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+/** Set X-axis accelerometer standby enabled status.
+ * @param New X-axis standby enabled status
+ * @see getStandbyXAccelEnabled()
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_XA_BIT
+ */
+void MPU6050_setStandbyXAccelEnabled(bool enabled) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XA_BIT, enabled);
+}
+/** Get Y-axis accelerometer standby enabled status.
+ * If enabled, the Y-axis will not gather or report data (or use power).
+ * @return Current Y-axis standby enabled status
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_YA_BIT
+ */
+bool MPU6050_getStandbyYAccelEnabled() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YA_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+/** Set Y-axis accelerometer standby enabled status.
+ * @param New Y-axis standby enabled status
+ * @see getStandbyYAccelEnabled()
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_YA_BIT
+ */
+void MPU6050_setStandbyYAccelEnabled(bool enabled) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YA_BIT, enabled);
+}
+/** Get Z-axis accelerometer standby enabled status.
+ * If enabled, the Z-axis will not gather or report data (or use power).
+ * @return Current Z-axis standby enabled status
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_ZA_BIT
+ */
+bool MPU6050_getStandbyZAccelEnabled() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZA_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+/** Set Z-axis accelerometer standby enabled status.
+ * @param New Z-axis standby enabled status
+ * @see getStandbyZAccelEnabled()
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_ZA_BIT
+ */
+void MPU6050_setStandbyZAccelEnabled(bool enabled) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZA_BIT, enabled);
+}
+/** Get X-axis gyroscope standby enabled status.
+ * If enabled, the X-axis will not gather or report data (or use power).
+ * @return Current X-axis standby enabled status
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_XG_BIT
+ */
+bool MPU6050_getStandbyXGyroEnabled() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XG_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+/** Set X-axis gyroscope standby enabled status.
+ * @param New X-axis standby enabled status
+ * @see getStandbyXGyroEnabled()
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_XG_BIT
+ */
+void MPU6050_setStandbyXGyroEnabled(bool enabled) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XG_BIT, enabled);
+}
+/** Get Y-axis gyroscope standby enabled status.
+ * If enabled, the Y-axis will not gather or report data (or use power).
+ * @return Current Y-axis standby enabled status
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_YG_BIT
+ */
+bool MPU6050_getStandbyYGyroEnabled() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YG_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+/** Set Y-axis gyroscope standby enabled status.
+ * @param New Y-axis standby enabled status
+ * @see getStandbyYGyroEnabled()
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_YG_BIT
+ */
+void MPU6050_setStandbyYGyroEnabled(bool enabled) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YG_BIT, enabled);
+}
+/** Get Z-axis gyroscope standby enabled status.
+ * If enabled, the Z-axis will not gather or report data (or use power).
+ * @return Current Z-axis standby enabled status
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_ZG_BIT
+ */
+bool MPU6050_getStandbyZGyroEnabled() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZG_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+/** Set Z-axis gyroscope standby enabled status.
+ * @param New Z-axis standby enabled status
+ * @see getStandbyZGyroEnabled()
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_ZG_BIT
+ */
+void MPU6050_setStandbyZGyroEnabled(bool enabled) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZG_BIT, enabled);
+}
+
+// FIFO_COUNT* registers
+
+/** Get current FIFO mpu6050.buffer size.
+ * This value indicates the number of bytes stored in the FIFO mpu6050.buffer. This
+ * number is in turn the number of bytes that can be read from the FIFO mpu6050.buffer
+ * and it is directly proportional to the number of samples available given the
+ * set of sensor data bound to be stored in the FIFO (register 35 and 36).
+ * @return Current FIFO mpu6050.buffer size
+ */
+uint16_t MPU6050_getFIFOCount() {
+    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_FIFO_COUNTH, 2, mpu6050.buffer);
+    return (((uint16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+}
+
+// FIFO_R_W register
+
+/** Get byte from FIFO mpu6050.buffer.
+ * This register is used to read and write data from the FIFO mpu6050.buffer. Data is
+ * written to the FIFO in order of register number (from lowest to highest). If
+ * all the FIFO enable flags (see below) are enabled and all External Sensor
+ * Data registers (Registers 73 to 96) are associated with a Slave device, the
+ * contents of registers 59 through 96 will be written in order at the Sample
+ * Rate.
+ *
+ * The contents of the sensor data registers (Registers 59 to 96) are written
+ * into the FIFO mpu6050.buffer when their corresponding FIFO enable flags are set to 1
+ * in FIFO_EN (Register 35). An additional flag for the sensor data registers
+ * associated with I2C Slave 3 can be found in I2C_MST_CTRL (Register 36).
+ *
+ * If the FIFO mpu6050.buffer has overflowed, the status bit FIFO_OFLOW_INT is
+ * automatically set to 1. This bit is located in INT_STATUS (Register 58).
+ * When the FIFO mpu6050.buffer has overflowed, the oldest data will be lost and new
+ * data will be written to the FIFO.
+ *
+ * If the FIFO mpu6050.buffer is empty, reading this register will return the last byte
+ * that was previously read from the FIFO until new data is available. The user
+ * should check FIFO_COUNT to ensure that the FIFO mpu6050.buffer is not read when
+ * empty.
+ *
+ * @return Byte from FIFO mpu6050.buffer
+ */
+uint8_t MPU6050_getFIFOByte() {
+    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_FIFO_R_W, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_getFIFOBytes(uint8_t *data, uint8_t length) {
+    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_FIFO_R_W, length, data);
+}
+/** Write byte to FIFO mpu6050.buffer.
+ * @see getFIFOByte()
+ * @see MPU6050_RA_FIFO_R_W
+ */
+void MPU6050_setFIFOByte(uint8_t data) {
+    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_FIFO_R_W, data);
+}
+
+// WHO_AM_I register
+
+/** Get Device ID.
+ * This register is used to verify the identity of the device (0b110100, 0x34).
+ * @return Device ID (6 bits only! should be 0x34)
+ * @see MPU6050_RA_WHO_AM_I
+ * @see MPU6050_WHO_AM_I_BIT
+ * @see MPU6050_WHO_AM_I_LENGTH
+ */
+uint8_t MPU6050_getDeviceID() {
+    I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_WHO_AM_I, MPU6050_WHO_AM_I_BIT, MPU6050_WHO_AM_I_LENGTH, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+/** Set Device ID.
+ * Write a new ID into the WHO_AM_I register (no idea why this should ever be
+ * necessary though).
+ * @param id New device ID to set.
+ * @see getDeviceID()
+ * @see MPU6050_RA_WHO_AM_I
+ * @see MPU6050_WHO_AM_I_BIT
+ * @see MPU6050_WHO_AM_I_LENGTH
+ */
+void MPU6050_setDeviceID(uint8_t id) {
+    I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_WHO_AM_I, MPU6050_WHO_AM_I_BIT, MPU6050_WHO_AM_I_LENGTH, id);
+}
+
+// ======== UNDOCUMENTED/DMP REGISTERS/METHODS ========
+
+// XG_OFFS_TC register
+
+uint8_t MPU6050_getOTPBankValid() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OTP_BNK_VLD_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setOTPBankValid(bool enabled) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OTP_BNK_VLD_BIT, enabled);
+}
+int8_t MPU6050_getXGyroOffsetTC() {
+    I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setXGyroOffsetTC(int8_t offset) {
+    I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset);
+}
+
+// YG_OFFS_TC register
+
+int8_t MPU6050_getYGyroOffsetTC() {
+    I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setYGyroOffsetTC(int8_t offset) {
+    I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset);
+}
+
+// ZG_OFFS_TC register
+
+int8_t MPU6050_getZGyroOffsetTC() {
+    I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_ZG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setZGyroOffsetTC(int8_t offset) {
+    I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_ZG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset);
+}
+
+// X_FINE_GAIN register
+
+int8_t MPU6050_getXFineGain() {
+    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_X_FINE_GAIN, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setXFineGain(int8_t gain) {
+    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_X_FINE_GAIN, gain);
+}
+
+// Y_FINE_GAIN register
+
+int8_t MPU6050_getYFineGain() {
+    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_Y_FINE_GAIN, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setYFineGain(int8_t gain) {
+    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_Y_FINE_GAIN, gain);
+}
+
+// Z_FINE_GAIN register
+
+int8_t MPU6050_getZFineGain() {
+    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_Z_FINE_GAIN, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setZFineGain(int8_t gain) {
+    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_Z_FINE_GAIN, gain);
+}
+
+// XA_OFFS_* registers
+
+int16_t MPU6050_getXAccelOffset() {
+    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_XA_OFFS_H, 2, mpu6050.buffer);
+    return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+}
+void MPU6050_setXAccelOffset(int16_t offset) {
+    I2Cdev_writeWord(mpu6050.devAddr, MPU6050_RA_XA_OFFS_H, offset);
+}
+
+// YA_OFFS_* register
+
+int16_t MPU6050_getYAccelOffset() {
+    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_YA_OFFS_H, 2, mpu6050.buffer);
+    return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+}
+void MPU6050_setYAccelOffset(int16_t offset) {
+    I2Cdev_writeWord(mpu6050.devAddr, MPU6050_RA_YA_OFFS_H, offset);
+}
+
+// ZA_OFFS_* register
+
+int16_t MPU6050_getZAccelOffset() {
+    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ZA_OFFS_H, 2, mpu6050.buffer);
+    return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+}
+void MPU6050_setZAccelOffset(int16_t offset) {
+    I2Cdev_writeWord(mpu6050.devAddr, MPU6050_RA_ZA_OFFS_H, offset);
+}
+
+// XG_OFFS_USR* registers
+
+int16_t MPU6050_getXGyroOffset() {
+    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_XG_OFFS_USRH, 2, mpu6050.buffer);
+    return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+}
+void MPU6050_setXGyroOffset(int16_t offset) {
+    I2Cdev_writeWord(mpu6050.devAddr, MPU6050_RA_XG_OFFS_USRH, offset);
+}
+
+// YG_OFFS_USR* register
+
+int16_t MPU6050_getYGyroOffset() {
+    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_YG_OFFS_USRH, 2, mpu6050.buffer);
+    return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+}
+void MPU6050_setYGyroOffset(int16_t offset) {
+    I2Cdev_writeWord(mpu6050.devAddr, MPU6050_RA_YG_OFFS_USRH, offset);
+}
+
+// ZG_OFFS_USR* register
+
+int16_t MPU6050_getZGyroOffset() {
+    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ZG_OFFS_USRH, 2, mpu6050.buffer);
+    return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+}
+void MPU6050_setZGyroOffset(int16_t offset) {
+    I2Cdev_writeWord(mpu6050.devAddr, MPU6050_RA_ZG_OFFS_USRH, offset);
+}
+
+// INT_ENABLE register (DMP functions)
+
+bool MPU6050_getIntPLLReadyEnabled() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setIntPLLReadyEnabled(bool enabled) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, enabled);
+}
+bool MPU6050_getIntDMPEnabled() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DMP_INT_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setIntDMPEnabled(bool enabled) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DMP_INT_BIT, enabled);
+}
+
+// DMP_INT_STATUS
+
+bool MPU6050_getDMPInt5Status() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_5_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+bool MPU6050_getDMPInt4Status() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_4_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+bool MPU6050_getDMPInt3Status() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_3_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+bool MPU6050_getDMPInt2Status() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_2_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+bool MPU6050_getDMPInt1Status() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_1_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+bool MPU6050_getDMPInt0Status() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_0_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+
+// INT_STATUS register (DMP functions)
+
+bool MPU6050_getIntPLLReadyStatus() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+bool MPU6050_getIntDMPStatus() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_DMP_INT_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+
+// USER_CTRL register (DMP functions)
+
+bool MPU6050_getDMPEnabled() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_EN_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setDMPEnabled(bool enabled) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_EN_BIT, enabled);
+}
+void MPU6050_resetDMP() {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_RESET_BIT, true);
+}
+
+// BANK_SEL register
+
+void MPU6050_setMemoryBank(uint8_t bank, bool prefetchEnabled, bool userBank) {
+    bank &= 0x1F;
+    if (userBank) bank |= 0x20;
+    if (prefetchEnabled) bank |= 0x40;
+    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_BANK_SEL, bank);
+}
+
+// MEM_START_ADDR register
+
+void MPU6050_setMemoryStartAddress(uint8_t address) {
+    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_MEM_START_ADDR, address);
+}
+
+// MEM_R_W register
+
+uint8_t MPU6050_readMemoryByte() {
+    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_MEM_R_W, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_writeMemoryByte(uint8_t data) {
+    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_MEM_R_W, data);
+}
+void MPU6050_readMemoryBlock(uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address) {
+    MPU6050_setMemoryBank(bank, false, false);
+    MPU6050_setMemoryStartAddress(address);
+    uint8_t chunkSize;
+    for (uint16_t i = 0; i < dataSize;) {
+        // determine correct chunk size according to bank position and data size
+        chunkSize = MPU6050_DMP_MEMORY_CHUNK_SIZE;
+
+        // make sure we don't go past the data size
+        if (i + chunkSize > dataSize) chunkSize = dataSize - i;
+
+        // make sure this chunk doesn't go past the bank boundary (256 bytes)
+        if (chunkSize > 256 - address) chunkSize = 256 - address;
+
+        // read the chunk of data as specified
+        I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_MEM_R_W, chunkSize, data + i);
+        
+        // increase byte index by [chunkSize]
+        i += chunkSize;
+
+        // uint8_t automatically wraps to 0 at 256
+        address += chunkSize;
+
+        // if we aren't done, update bank (if necessary) and address
+        if (i < dataSize) {
+            if (address == 0) bank++;
+            MPU6050_setMemoryBank(bank, false, false);
+            MPU6050_setMemoryStartAddress(address);
+        }
+    }
+}
+/*bool MPU6050_writeMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address, bool verify, bool useProgMem) {
+    MPU6050_setMemoryBank(bank, false, false);
+    MPU6050_setMemoryStartAddress(address);
+    uint8_t chunkSize;
+    uint8_t *verifyBuffer;
+    uint8_t *progBuffer;
+    uint16_t i;
+    uint8_t j;
+    if (verify) verifyBuffer = (uint8_t *)malloc(MPU6050_DMP_MEMORY_CHUNK_SIZE);
+    if (useProgMem) progBuffer = (uint8_t *)malloc(MPU6050_DMP_MEMORY_CHUNK_SIZE);
+    for (i = 0; i < dataSize;) {
+        // determine correct chunk size according to bank position and data size
+        chunkSize = MPU6050_DMP_MEMORY_CHUNK_SIZE;
+
+        // make sure we don't go past the data size
+        if (i + chunkSize > dataSize) chunkSize = dataSize - i;
+
+        // make sure this chunk doesn't go past the bank boundary (256 bytes)
+        if (chunkSize > 256 - address) chunkSize = 256 - address;
+        
+        if (useProgMem) {
+            // write the chunk of data as specified
+            for (j = 0; j < chunkSize; j++) progBuffer[j] = pgm_read_byte(data + i + j);
+        } else {
+            // write the chunk of data as specified
+            progBuffer = (uint8_t *)data + i;
+        }
+
+        I2Cdev_writeBytes(mpu6050.devAddr, MPU6050_RA_MEM_R_W, chunkSize, progBuffer);
+
+        // verify data if needed
+        if (verify && verifyBuffer) {
+            MPU6050_setMemoryBank(bank, false, false);
+            MPU6050_setMemoryStartAddress(address);
+            I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_MEM_R_W, chunkSize, verifyBuffer);
+            if (memcmp(progBuffer, verifyBuffer, chunkSize) != 0) {
+                //Serial.print("Block write verification error, bank ");
+                //Serial.print(bank, DEC);
+                //Serial.print(", address ");
+                //Serial.print(address, DEC);
+                //Serial.print("!\nExpected:");
+                //for (j = 0; j < chunkSize; j++) {
+                //    Serial.print(" 0x");
+                //    if (progBuffer[j] < 16) Serial.print("0");
+                //    Serial.print(progBuffer[j], HEX);
+                //}
+                //Serial.print("\nReceived:");
+                //for (uint8_t j = 0; j < chunkSize; j++) {
+                //    Serial.print(" 0x");
+                //    if (verifyBuffer[i + j] < 16) Serial.print("0");
+                //    Serial.print(verifyBuffer[i + j], HEX);
+                //}
+                Serial.print("\n");
+                free(verifyBuffer);
+                if (useProgMem) free(progBuffer);
+                return false; // uh oh.
+            }
+        }
+
+        // increase byte index by [chunkSize]
+        i += chunkSize;
+
+        // uint8_t automatically wraps to 0 at 256
+        address += chunkSize;
+
+        // if we aren't done, update bank (if necessary) and address
+        if (i < dataSize) {
+            if (address == 0) bank++;
+            MPU6050_setMemoryBank(bank, false, false);
+            MPU6050_setMemoryStartAddress(address);
+        }
+    }
+    if (verify) free(verifyBuffer);
+    if (useProgMem) free(progBuffer);
+    return true;
+}
+bool MPU6050_writeProgMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address, bool verify) {
+    return MPU6050_writeMemoryBlock(data, dataSize, bank, address, verify, true);
+}
+bool MPU6050_writeDMPConfigurationSet(const uint8_t *data, uint16_t dataSize, bool useProgMem) {
+    uint8_t *progBuffer, success, special;
+    uint16_t i, j;
+    if (useProgMem) {
+        progBuffer = (uint8_t *)malloc(8); // assume 8-byte blocks, realloc later if necessary
+    }
+
+    // config set data is a long string of blocks with the following structure:
+    // [bank] [offset] [length] [byte[0], byte[1], ..., byte[length]]
+    uint8_t bank, offset, length;
+    for (i = 0; i < dataSize;) {
+        if (useProgMem) {
+            bank = pgm_read_byte(data + i++);
+            offset = pgm_read_byte(data + i++);
+            length = pgm_read_byte(data + i++);
+        } else {
+            bank = data[i++];
+            offset = data[i++];
+            length = data[i++];
+        }
+
+        // write data or perform special action
+        if (length > 0) {
+            // regular block of data to write
+            //Serial.print("Writing config block to bank ");
+            //Serial.print(bank);
+            //Serial.print(", offset ");
+            //Serial.print(offset);
+            //Serial.print(", length=");
+            //Serial.println(length);
+            if (useProgMem) {
+                if (sizeof(progBuffer) < length) progBuffer = (uint8_t *)realloc(progBuffer, length);
+                for (j = 0; j < length; j++) progBuffer[j] = pgm_read_byte(data + i + j);
+            } else {
+                progBuffer = (uint8_t *)data + i;
+            }
+            success = MPU6050_writeMemoryBlock(progBuffer, length, bank, offset, true);
+            i += length;
+        } else {
+            // special instruction
+            // NOTE: this kind of behavior (what and when to do certain things)
+            // is totally undocumented. This code is in here based on observed
+            // behavior only, and exactly why (or even whether) it has to be here
+            // is anybody's guess for now.
+            if (useProgMem) {
+                special = pgm_read_byte(data + i++);
+            } else {
+                special = data[i++];
+            }
+            //Serial.print("Special command code ");
+            //Serial.print(special, HEX);
+            //Serial.println(" found...");
+            if (special == 0x01) {
+                // enable DMP-related interrupts
+                
+                //setIntZeroMotionEnabled(true);
+                //setIntFIFOBufferOverflowEnabled(true);
+                //setIntDMPEnabled(true);
+                I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, 0x32);  // single operation
+
+                success = true;
+            } else {
+                // unknown special command
+                success = false;
+            }
+        }
+        
+        if (!success) {
+            if (useProgMem) free(progBuffer);
+            return false; // uh oh
+        }
+    }
+    if (useProgMem) free(progBuffer);
+    return true;
+}
+bool MPU6050_writeProgDMPConfigurationSet(const uint8_t *data, uint16_t dataSize) {
+    return MPU6050_writeDMPConfigurationSet(data, dataSize, true);
+}*/
+
+// DMP_CFG_1 register
+
+uint8_t MPU6050_getDMPConfig1() {
+    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_DMP_CFG_1, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setDMPConfig1(uint8_t config) {
+    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_DMP_CFG_1, config);
+}
+
+// DMP_CFG_2 register
+
+uint8_t MPU6050_getDMPConfig2() {
+    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_DMP_CFG_2, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setDMPConfig2(uint8_t config) {
+    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_DMP_CFG_2, config);
+}
\ No newline at end of file
diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050.h b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050.h
new file mode 100644
index 00000000..830760fc
--- /dev/null
+++ b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050.h
@@ -0,0 +1,786 @@
+// I2Cdev library collection - MPU6050 I2C device class
+// Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00)
+// 10/3/2011 by Jeff Rowberg 
+// 11/28/2014 by Marton Sebok 
+//
+// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
+//
+// Changelog:
+//     ...        - ongoing debug release
+//     2014-11-28 - ported to PIC18 peripheral library from Arduino code
+
+// NOTE: THIS IS ONLY A PARIAL RELEASE. THIS DEVICE CLASS IS CURRENTLY UNDERGOING ACTIVE
+// DEVELOPMENT AND IS STILL MISSING SOME IMPORTANT FEATURES. PLEASE KEEP THIS IN MIND IF
+// YOU DECIDE TO USE THIS PARTICULAR CODE FOR ANYTHING.
+
+/* ============================================
+I2Cdev device library code is placed under the MIT license
+Copyright (c) 2012 Jeff Rowberg
+Copyright (c) 2014 Marton Sebok
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+===============================================
+*/
+
+#ifndef _MPU6050_H_
+#define _MPU6050_H_
+
+#include "I2Cdev.h"
+
+#if ((defined MPU6050_INCLUDE_DMP_MOTIONAPPS20) || (defined MPU6050_INCLUDE_DMP_MOTIONAPPS41))
+    #error DMP is not supported yet
+#endif
+
+#define MPU6050_ADDRESS_AD0_LOW     0x68 // address pin low (GND), default for InvenSense evaluation board
+#define MPU6050_ADDRESS_AD0_HIGH    0x69 // address pin high (VCC)
+#define MPU6050_DEFAULT_ADDRESS     MPU6050_ADDRESS_AD0_LOW
+
+#define MPU6050_RA_XG_OFFS_TC       0x00 //[7] PWR_MODE, [6:1] XG_OFFS_TC, [0] OTP_BNK_VLD
+#define MPU6050_RA_YG_OFFS_TC       0x01 //[7] PWR_MODE, [6:1] YG_OFFS_TC, [0] OTP_BNK_VLD
+#define MPU6050_RA_ZG_OFFS_TC       0x02 //[7] PWR_MODE, [6:1] ZG_OFFS_TC, [0] OTP_BNK_VLD
+#define MPU6050_RA_X_FINE_GAIN      0x03 //[7:0] X_FINE_GAIN
+#define MPU6050_RA_Y_FINE_GAIN      0x04 //[7:0] Y_FINE_GAIN
+#define MPU6050_RA_Z_FINE_GAIN      0x05 //[7:0] Z_FINE_GAIN
+#define MPU6050_RA_XA_OFFS_H        0x06 //[15:0] XA_OFFS
+#define MPU6050_RA_XA_OFFS_L_TC     0x07
+#define MPU6050_RA_YA_OFFS_H        0x08 //[15:0] YA_OFFS
+#define MPU6050_RA_YA_OFFS_L_TC     0x09
+#define MPU6050_RA_ZA_OFFS_H        0x0A //[15:0] ZA_OFFS
+#define MPU6050_RA_ZA_OFFS_L_TC     0x0B
+#define MPU6050_RA_XG_OFFS_USRH     0x13 //[15:0] XG_OFFS_USR
+#define MPU6050_RA_XG_OFFS_USRL     0x14
+#define MPU6050_RA_YG_OFFS_USRH     0x15 //[15:0] YG_OFFS_USR
+#define MPU6050_RA_YG_OFFS_USRL     0x16
+#define MPU6050_RA_ZG_OFFS_USRH     0x17 //[15:0] ZG_OFFS_USR
+#define MPU6050_RA_ZG_OFFS_USRL     0x18
+#define MPU6050_RA_SMPLRT_DIV       0x19
+#define MPU6050_RA_CONFIG           0x1A
+#define MPU6050_RA_GYRO_CONFIG      0x1B
+#define MPU6050_RA_ACCEL_CONFIG     0x1C
+#define MPU6050_RA_FF_THR           0x1D
+#define MPU6050_RA_FF_DUR           0x1E
+#define MPU6050_RA_MOT_THR          0x1F
+#define MPU6050_RA_MOT_DUR          0x20
+#define MPU6050_RA_ZRMOT_THR        0x21
+#define MPU6050_RA_ZRMOT_DUR        0x22
+#define MPU6050_RA_FIFO_EN          0x23
+#define MPU6050_RA_I2C_MST_CTRL     0x24
+#define MPU6050_RA_I2C_SLV0_ADDR    0x25
+#define MPU6050_RA_I2C_SLV0_REG     0x26
+#define MPU6050_RA_I2C_SLV0_CTRL    0x27
+#define MPU6050_RA_I2C_SLV1_ADDR    0x28
+#define MPU6050_RA_I2C_SLV1_REG     0x29
+#define MPU6050_RA_I2C_SLV1_CTRL    0x2A
+#define MPU6050_RA_I2C_SLV2_ADDR    0x2B
+#define MPU6050_RA_I2C_SLV2_REG     0x2C
+#define MPU6050_RA_I2C_SLV2_CTRL    0x2D
+#define MPU6050_RA_I2C_SLV3_ADDR    0x2E
+#define MPU6050_RA_I2C_SLV3_REG     0x2F
+#define MPU6050_RA_I2C_SLV3_CTRL    0x30
+#define MPU6050_RA_I2C_SLV4_ADDR    0x31
+#define MPU6050_RA_I2C_SLV4_REG     0x32
+#define MPU6050_RA_I2C_SLV4_DO      0x33
+#define MPU6050_RA_I2C_SLV4_CTRL    0x34
+#define MPU6050_RA_I2C_SLV4_DI      0x35
+#define MPU6050_RA_I2C_MST_STATUS   0x36
+#define MPU6050_RA_INT_PIN_CFG      0x37
+#define MPU6050_RA_INT_ENABLE       0x38
+#define MPU6050_RA_DMP_INT_STATUS   0x39
+#define MPU6050_RA_INT_STATUS       0x3A
+#define MPU6050_RA_ACCEL_XOUT_H     0x3B
+#define MPU6050_RA_ACCEL_XOUT_L     0x3C
+#define MPU6050_RA_ACCEL_YOUT_H     0x3D
+#define MPU6050_RA_ACCEL_YOUT_L     0x3E
+#define MPU6050_RA_ACCEL_ZOUT_H     0x3F
+#define MPU6050_RA_ACCEL_ZOUT_L     0x40
+#define MPU6050_RA_TEMP_OUT_H       0x41
+#define MPU6050_RA_TEMP_OUT_L       0x42
+#define MPU6050_RA_GYRO_XOUT_H      0x43
+#define MPU6050_RA_GYRO_XOUT_L      0x44
+#define MPU6050_RA_GYRO_YOUT_H      0x45
+#define MPU6050_RA_GYRO_YOUT_L      0x46
+#define MPU6050_RA_GYRO_ZOUT_H      0x47
+#define MPU6050_RA_GYRO_ZOUT_L      0x48
+#define MPU6050_RA_EXT_SENS_DATA_00 0x49
+#define MPU6050_RA_EXT_SENS_DATA_01 0x4A
+#define MPU6050_RA_EXT_SENS_DATA_02 0x4B
+#define MPU6050_RA_EXT_SENS_DATA_03 0x4C
+#define MPU6050_RA_EXT_SENS_DATA_04 0x4D
+#define MPU6050_RA_EXT_SENS_DATA_05 0x4E
+#define MPU6050_RA_EXT_SENS_DATA_06 0x4F
+#define MPU6050_RA_EXT_SENS_DATA_07 0x50
+#define MPU6050_RA_EXT_SENS_DATA_08 0x51
+#define MPU6050_RA_EXT_SENS_DATA_09 0x52
+#define MPU6050_RA_EXT_SENS_DATA_10 0x53
+#define MPU6050_RA_EXT_SENS_DATA_11 0x54
+#define MPU6050_RA_EXT_SENS_DATA_12 0x55
+#define MPU6050_RA_EXT_SENS_DATA_13 0x56
+#define MPU6050_RA_EXT_SENS_DATA_14 0x57
+#define MPU6050_RA_EXT_SENS_DATA_15 0x58
+#define MPU6050_RA_EXT_SENS_DATA_16 0x59
+#define MPU6050_RA_EXT_SENS_DATA_17 0x5A
+#define MPU6050_RA_EXT_SENS_DATA_18 0x5B
+#define MPU6050_RA_EXT_SENS_DATA_19 0x5C
+#define MPU6050_RA_EXT_SENS_DATA_20 0x5D
+#define MPU6050_RA_EXT_SENS_DATA_21 0x5E
+#define MPU6050_RA_EXT_SENS_DATA_22 0x5F
+#define MPU6050_RA_EXT_SENS_DATA_23 0x60
+#define MPU6050_RA_MOT_DETECT_STATUS    0x61
+#define MPU6050_RA_I2C_SLV0_DO      0x63
+#define MPU6050_RA_I2C_SLV1_DO      0x64
+#define MPU6050_RA_I2C_SLV2_DO      0x65
+#define MPU6050_RA_I2C_SLV3_DO      0x66
+#define MPU6050_RA_I2C_MST_DELAY_CTRL   0x67
+#define MPU6050_RA_SIGNAL_PATH_RESET    0x68
+#define MPU6050_RA_MOT_DETECT_CTRL      0x69
+#define MPU6050_RA_USER_CTRL        0x6A
+#define MPU6050_RA_PWR_MGMT_1       0x6B
+#define MPU6050_RA_PWR_MGMT_2       0x6C
+#define MPU6050_RA_BANK_SEL         0x6D
+#define MPU6050_RA_MEM_START_ADDR   0x6E
+#define MPU6050_RA_MEM_R_W          0x6F
+#define MPU6050_RA_DMP_CFG_1        0x70
+#define MPU6050_RA_DMP_CFG_2        0x71
+#define MPU6050_RA_FIFO_COUNTH      0x72
+#define MPU6050_RA_FIFO_COUNTL      0x73
+#define MPU6050_RA_FIFO_R_W         0x74
+#define MPU6050_RA_WHO_AM_I         0x75
+
+#define MPU6050_TC_PWR_MODE_BIT     7
+#define MPU6050_TC_OFFSET_BIT       6
+#define MPU6050_TC_OFFSET_LENGTH    6
+#define MPU6050_TC_OTP_BNK_VLD_BIT  0
+
+#define MPU6050_VDDIO_LEVEL_VLOGIC  0
+#define MPU6050_VDDIO_LEVEL_VDD     1
+
+#define MPU6050_CFG_EXT_SYNC_SET_BIT    5
+#define MPU6050_CFG_EXT_SYNC_SET_LENGTH 3
+#define MPU6050_CFG_DLPF_CFG_BIT    2
+#define MPU6050_CFG_DLPF_CFG_LENGTH 3
+
+#define MPU6050_EXT_SYNC_DISABLED       0x0
+#define MPU6050_EXT_SYNC_TEMP_OUT_L     0x1
+#define MPU6050_EXT_SYNC_GYRO_XOUT_L    0x2
+#define MPU6050_EXT_SYNC_GYRO_YOUT_L    0x3
+#define MPU6050_EXT_SYNC_GYRO_ZOUT_L    0x4
+#define MPU6050_EXT_SYNC_ACCEL_XOUT_L   0x5
+#define MPU6050_EXT_SYNC_ACCEL_YOUT_L   0x6
+#define MPU6050_EXT_SYNC_ACCEL_ZOUT_L   0x7
+
+#define MPU6050_DLPF_BW_256         0x00
+#define MPU6050_DLPF_BW_188         0x01
+#define MPU6050_DLPF_BW_98          0x02
+#define MPU6050_DLPF_BW_42          0x03
+#define MPU6050_DLPF_BW_20          0x04
+#define MPU6050_DLPF_BW_10          0x05
+#define MPU6050_DLPF_BW_5           0x06
+
+#define MPU6050_GCONFIG_FS_SEL_BIT      4
+#define MPU6050_GCONFIG_FS_SEL_LENGTH   2
+
+#define MPU6050_GYRO_FS_250         0x00
+#define MPU6050_GYRO_FS_500         0x01
+#define MPU6050_GYRO_FS_1000        0x02
+#define MPU6050_GYRO_FS_2000        0x03
+
+#define MPU6050_ACONFIG_XA_ST_BIT           7
+#define MPU6050_ACONFIG_YA_ST_BIT           6
+#define MPU6050_ACONFIG_ZA_ST_BIT           5
+#define MPU6050_ACONFIG_AFS_SEL_BIT         4
+#define MPU6050_ACONFIG_AFS_SEL_LENGTH      2
+#define MPU6050_ACONFIG_ACCEL_HPF_BIT       2
+#define MPU6050_ACONFIG_ACCEL_HPF_LENGTH    3
+
+#define MPU6050_ACCEL_FS_2          0x00
+#define MPU6050_ACCEL_FS_4          0x01
+#define MPU6050_ACCEL_FS_8          0x02
+#define MPU6050_ACCEL_FS_16         0x03
+
+#define MPU6050_DHPF_RESET          0x00
+#define MPU6050_DHPF_5              0x01
+#define MPU6050_DHPF_2P5            0x02
+#define MPU6050_DHPF_1P25           0x03
+#define MPU6050_DHPF_0P63           0x04
+#define MPU6050_DHPF_HOLD           0x07
+
+#define MPU6050_TEMP_FIFO_EN_BIT    7
+#define MPU6050_XG_FIFO_EN_BIT      6
+#define MPU6050_YG_FIFO_EN_BIT      5
+#define MPU6050_ZG_FIFO_EN_BIT      4
+#define MPU6050_ACCEL_FIFO_EN_BIT   3
+#define MPU6050_SLV2_FIFO_EN_BIT    2
+#define MPU6050_SLV1_FIFO_EN_BIT    1
+#define MPU6050_SLV0_FIFO_EN_BIT    0
+
+#define MPU6050_MULT_MST_EN_BIT     7
+#define MPU6050_WAIT_FOR_ES_BIT     6
+#define MPU6050_SLV_3_FIFO_EN_BIT   5
+#define MPU6050_I2C_MST_P_NSR_BIT   4
+#define MPU6050_I2C_MST_CLK_BIT     3
+#define MPU6050_I2C_MST_CLK_LENGTH  4
+
+#define MPU6050_CLOCK_DIV_348       0x0
+#define MPU6050_CLOCK_DIV_333       0x1
+#define MPU6050_CLOCK_DIV_320       0x2
+#define MPU6050_CLOCK_DIV_308       0x3
+#define MPU6050_CLOCK_DIV_296       0x4
+#define MPU6050_CLOCK_DIV_286       0x5
+#define MPU6050_CLOCK_DIV_276       0x6
+#define MPU6050_CLOCK_DIV_267       0x7
+#define MPU6050_CLOCK_DIV_258       0x8
+#define MPU6050_CLOCK_DIV_500       0x9
+#define MPU6050_CLOCK_DIV_471       0xA
+#define MPU6050_CLOCK_DIV_444       0xB
+#define MPU6050_CLOCK_DIV_421       0xC
+#define MPU6050_CLOCK_DIV_400       0xD
+#define MPU6050_CLOCK_DIV_381       0xE
+#define MPU6050_CLOCK_DIV_364       0xF
+
+#define MPU6050_I2C_SLV_RW_BIT      7
+#define MPU6050_I2C_SLV_ADDR_BIT    6
+#define MPU6050_I2C_SLV_ADDR_LENGTH 7
+#define MPU6050_I2C_SLV_EN_BIT      7
+#define MPU6050_I2C_SLV_BYTE_SW_BIT 6
+#define MPU6050_I2C_SLV_REG_DIS_BIT 5
+#define MPU6050_I2C_SLV_GRP_BIT     4
+#define MPU6050_I2C_SLV_LEN_BIT     3
+#define MPU6050_I2C_SLV_LEN_LENGTH  4
+
+#define MPU6050_I2C_SLV4_RW_BIT         7
+#define MPU6050_I2C_SLV4_ADDR_BIT       6
+#define MPU6050_I2C_SLV4_ADDR_LENGTH    7
+#define MPU6050_I2C_SLV4_EN_BIT         7
+#define MPU6050_I2C_SLV4_INT_EN_BIT     6
+#define MPU6050_I2C_SLV4_REG_DIS_BIT    5
+#define MPU6050_I2C_SLV4_MST_DLY_BIT    4
+#define MPU6050_I2C_SLV4_MST_DLY_LENGTH 5
+
+#define MPU6050_MST_PASS_THROUGH_BIT    7
+#define MPU6050_MST_I2C_SLV4_DONE_BIT   6
+#define MPU6050_MST_I2C_LOST_ARB_BIT    5
+#define MPU6050_MST_I2C_SLV4_NACK_BIT   4
+#define MPU6050_MST_I2C_SLV3_NACK_BIT   3
+#define MPU6050_MST_I2C_SLV2_NACK_BIT   2
+#define MPU6050_MST_I2C_SLV1_NACK_BIT   1
+#define MPU6050_MST_I2C_SLV0_NACK_BIT   0
+
+#define MPU6050_INTCFG_INT_LEVEL_BIT        7
+#define MPU6050_INTCFG_INT_OPEN_BIT         6
+#define MPU6050_INTCFG_LATCH_INT_EN_BIT     5
+#define MPU6050_INTCFG_INT_RD_CLEAR_BIT     4
+#define MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT  3
+#define MPU6050_INTCFG_FSYNC_INT_EN_BIT     2
+#define MPU6050_INTCFG_I2C_BYPASS_EN_BIT    1
+#define MPU6050_INTCFG_CLKOUT_EN_BIT        0
+
+#define MPU6050_INTMODE_ACTIVEHIGH  0x00
+#define MPU6050_INTMODE_ACTIVELOW   0x01
+
+#define MPU6050_INTDRV_PUSHPULL     0x00
+#define MPU6050_INTDRV_OPENDRAIN    0x01
+
+#define MPU6050_INTLATCH_50USPULSE  0x00
+#define MPU6050_INTLATCH_WAITCLEAR  0x01
+
+#define MPU6050_INTCLEAR_STATUSREAD 0x00
+#define MPU6050_INTCLEAR_ANYREAD    0x01
+
+#define MPU6050_INTERRUPT_FF_BIT            7
+#define MPU6050_INTERRUPT_MOT_BIT           6
+#define MPU6050_INTERRUPT_ZMOT_BIT          5
+#define MPU6050_INTERRUPT_FIFO_OFLOW_BIT    4
+#define MPU6050_INTERRUPT_I2C_MST_INT_BIT   3
+#define MPU6050_INTERRUPT_PLL_RDY_INT_BIT   2
+#define MPU6050_INTERRUPT_DMP_INT_BIT       1
+#define MPU6050_INTERRUPT_DATA_RDY_BIT      0
+
+// TODO: figure out what these actually do
+// UMPL source code is not very obivous
+#define MPU6050_DMPINT_5_BIT            5
+#define MPU6050_DMPINT_4_BIT            4
+#define MPU6050_DMPINT_3_BIT            3
+#define MPU6050_DMPINT_2_BIT            2
+#define MPU6050_DMPINT_1_BIT            1
+#define MPU6050_DMPINT_0_BIT            0
+
+#define MPU6050_MOTION_MOT_XNEG_BIT     7
+#define MPU6050_MOTION_MOT_XPOS_BIT     6
+#define MPU6050_MOTION_MOT_YNEG_BIT     5
+#define MPU6050_MOTION_MOT_YPOS_BIT     4
+#define MPU6050_MOTION_MOT_ZNEG_BIT     3
+#define MPU6050_MOTION_MOT_ZPOS_BIT     2
+#define MPU6050_MOTION_MOT_ZRMOT_BIT    0
+
+#define MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT   7
+#define MPU6050_DELAYCTRL_I2C_SLV4_DLY_EN_BIT   4
+#define MPU6050_DELAYCTRL_I2C_SLV3_DLY_EN_BIT   3
+#define MPU6050_DELAYCTRL_I2C_SLV2_DLY_EN_BIT   2
+#define MPU6050_DELAYCTRL_I2C_SLV1_DLY_EN_BIT   1
+#define MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT   0
+
+#define MPU6050_PATHRESET_GYRO_RESET_BIT    2
+#define MPU6050_PATHRESET_ACCEL_RESET_BIT   1
+#define MPU6050_PATHRESET_TEMP_RESET_BIT    0
+
+#define MPU6050_DETECT_ACCEL_ON_DELAY_BIT       5
+#define MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH    2
+#define MPU6050_DETECT_FF_COUNT_BIT             3
+#define MPU6050_DETECT_FF_COUNT_LENGTH          2
+#define MPU6050_DETECT_MOT_COUNT_BIT            1
+#define MPU6050_DETECT_MOT_COUNT_LENGTH         2
+
+#define MPU6050_DETECT_DECREMENT_RESET  0x0
+#define MPU6050_DETECT_DECREMENT_1      0x1
+#define MPU6050_DETECT_DECREMENT_2      0x2
+#define MPU6050_DETECT_DECREMENT_4      0x3
+
+#define MPU6050_USERCTRL_DMP_EN_BIT             7
+#define MPU6050_USERCTRL_FIFO_EN_BIT            6
+#define MPU6050_USERCTRL_I2C_MST_EN_BIT         5
+#define MPU6050_USERCTRL_I2C_IF_DIS_BIT         4
+#define MPU6050_USERCTRL_DMP_RESET_BIT          3
+#define MPU6050_USERCTRL_FIFO_RESET_BIT         2
+#define MPU6050_USERCTRL_I2C_MST_RESET_BIT      1
+#define MPU6050_USERCTRL_SIG_COND_RESET_BIT     0
+
+#define MPU6050_PWR1_DEVICE_RESET_BIT   7
+#define MPU6050_PWR1_SLEEP_BIT          6
+#define MPU6050_PWR1_CYCLE_BIT          5
+#define MPU6050_PWR1_TEMP_DIS_BIT       3
+#define MPU6050_PWR1_CLKSEL_BIT         2
+#define MPU6050_PWR1_CLKSEL_LENGTH      3
+
+#define MPU6050_CLOCK_INTERNAL          0x00
+#define MPU6050_CLOCK_PLL_XGYRO         0x01
+#define MPU6050_CLOCK_PLL_YGYRO         0x02
+#define MPU6050_CLOCK_PLL_ZGYRO         0x03
+#define MPU6050_CLOCK_PLL_EXT32K        0x04
+#define MPU6050_CLOCK_PLL_EXT19M        0x05
+#define MPU6050_CLOCK_KEEP_RESET        0x07
+
+#define MPU6050_PWR2_LP_WAKE_CTRL_BIT       7
+#define MPU6050_PWR2_LP_WAKE_CTRL_LENGTH    2
+#define MPU6050_PWR2_STBY_XA_BIT            5
+#define MPU6050_PWR2_STBY_YA_BIT            4
+#define MPU6050_PWR2_STBY_ZA_BIT            3
+#define MPU6050_PWR2_STBY_XG_BIT            2
+#define MPU6050_PWR2_STBY_YG_BIT            1
+#define MPU6050_PWR2_STBY_ZG_BIT            0
+
+#define MPU6050_WAKE_FREQ_1P25      0x0
+#define MPU6050_WAKE_FREQ_2P5       0x1
+#define MPU6050_WAKE_FREQ_5         0x2
+#define MPU6050_WAKE_FREQ_10        0x3
+
+#define MPU6050_BANKSEL_PRFTCH_EN_BIT       6
+#define MPU6050_BANKSEL_CFG_USER_BANK_BIT   5
+#define MPU6050_BANKSEL_MEM_SEL_BIT         4
+#define MPU6050_BANKSEL_MEM_SEL_LENGTH      5
+
+#define MPU6050_WHO_AM_I_BIT        6
+#define MPU6050_WHO_AM_I_LENGTH     6
+
+#define MPU6050_DMP_MEMORY_BANKS        8
+#define MPU6050_DMP_MEMORY_BANK_SIZE    256
+#define MPU6050_DMP_MEMORY_CHUNK_SIZE   16
+
+// note: DMP code memory blocks defined at end of header file
+
+typedef struct MPU6050_t {
+    uint8_t devAddr;
+    uint8_t buffer[14];
+} MPU6050_t;
+
+void MPU6050(uint8_t address);
+
+void MPU6050_initialize();
+bool MPU6050_testConnection();
+
+// AUX_VDDIO register
+uint8_t MPU6050_getAuxVDDIOLevel();
+void MPU6050_setAuxVDDIOLevel(uint8_t level);
+
+// SMPLRT_DIV register
+uint8_t MPU6050_getRate();
+void MPU6050_setRate(uint8_t rate);
+
+// CONFIG register
+uint8_t MPU6050_getExternalFrameSync();
+void MPU6050_setExternalFrameSync(uint8_t sync);
+uint8_t MPU6050_getDLPFMode();
+void MPU6050_setDLPFMode(uint8_t bandwidth);
+
+// GYRO_CONFIG register
+uint8_t MPU6050_getFullScaleGyroRange();
+void MPU6050_setFullScaleGyroRange(uint8_t range);
+
+// ACCEL_CONFIG register
+bool MPU6050_getAccelXSelfTest();
+void MPU6050_setAccelXSelfTest(bool enabled);
+bool MPU6050_getAccelYSelfTest();
+void MPU6050_setAccelYSelfTest(bool enabled);
+bool MPU6050_getAccelZSelfTest();
+void MPU6050_setAccelZSelfTest(bool enabled);
+uint8_t MPU6050_getFullScaleAccelRange();
+void MPU6050_setFullScaleAccelRange(uint8_t range);
+uint8_t MPU6050_getDHPFMode();
+void MPU6050_setDHPFMode(uint8_t mode);
+
+// FF_THR register
+uint8_t MPU6050_getFreefallDetectionThreshold();
+void MPU6050_setFreefallDetectionThreshold(uint8_t threshold);
+
+// FF_DUR register
+uint8_t MPU6050_getFreefallDetectionDuration();
+void MPU6050_setFreefallDetectionDuration(uint8_t duration);
+
+// MOT_THR register
+uint8_t MPU6050_getMotionDetectionThreshold();
+void MPU6050_setMotionDetectionThreshold(uint8_t threshold);
+
+// MOT_DUR register
+uint8_t MPU6050_getMotionDetectionDuration();
+void MPU6050_setMotionDetectionDuration(uint8_t duration);
+
+// ZRMOT_THR register
+uint8_t MPU6050_getZeroMotionDetectionThreshold();
+void MPU6050_setZeroMotionDetectionThreshold(uint8_t threshold);
+
+// ZRMOT_DUR register
+uint8_t MPU6050_getZeroMotionDetectionDuration();
+void MPU6050_setZeroMotionDetectionDuration(uint8_t duration);
+
+// FIFO_EN register
+bool MPU6050_getTempFIFOEnabled();
+void MPU6050_setTempFIFOEnabled(bool enabled);
+bool MPU6050_getXGyroFIFOEnabled();
+void MPU6050_setXGyroFIFOEnabled(bool enabled);
+bool MPU6050_getYGyroFIFOEnabled();
+void MPU6050_setYGyroFIFOEnabled(bool enabled);
+bool MPU6050_getZGyroFIFOEnabled();
+void MPU6050_setZGyroFIFOEnabled(bool enabled);
+bool MPU6050_getAccelFIFOEnabled();
+void MPU6050_setAccelFIFOEnabled(bool enabled);
+bool MPU6050_getSlave2FIFOEnabled();
+void MPU6050_setSlave2FIFOEnabled(bool enabled);
+bool MPU6050_getSlave1FIFOEnabled();
+void MPU6050_setSlave1FIFOEnabled(bool enabled);
+bool MPU6050_getSlave0FIFOEnabled();
+void MPU6050_setSlave0FIFOEnabled(bool enabled);
+
+// I2C_MST_CTRL register
+bool MPU6050_getMultiMasterEnabled();
+void MPU6050_setMultiMasterEnabled(bool enabled);
+bool MPU6050_getWaitForExternalSensorEnabled();
+void MPU6050_setWaitForExternalSensorEnabled(bool enabled);
+bool MPU6050_getSlave3FIFOEnabled();
+void MPU6050_setSlave3FIFOEnabled(bool enabled);
+bool MPU6050_getSlaveReadWriteTransitionEnabled();
+void MPU6050_setSlaveReadWriteTransitionEnabled(bool enabled);
+uint8_t MPU6050_getMasterClockSpeed();
+void MPU6050_setMasterClockSpeed(uint8_t speed);
+
+// I2C_SLV* registers (Slave 0-3)
+uint8_t MPU6050_getSlaveAddress(uint8_t num);
+void MPU6050_setSlaveAddress(uint8_t num, uint8_t address);
+uint8_t MPU6050_getSlaveRegister(uint8_t num);
+void MPU6050_setSlaveRegister(uint8_t num, uint8_t reg);
+bool MPU6050_getSlaveEnabled(uint8_t num);
+void MPU6050_setSlaveEnabled(uint8_t num, bool enabled);
+bool MPU6050_getSlaveWordByteSwap(uint8_t num);
+void MPU6050_setSlaveWordByteSwap(uint8_t num, bool enabled);
+bool MPU6050_getSlaveWriteMode(uint8_t num);
+void MPU6050_setSlaveWriteMode(uint8_t num, bool mode);
+bool MPU6050_getSlaveWordGroupOffset(uint8_t num);
+void MPU6050_setSlaveWordGroupOffset(uint8_t num, bool enabled);
+uint8_t MPU6050_getSlaveDataLength(uint8_t num);
+void MPU6050_setSlaveDataLength(uint8_t num, uint8_t length);
+
+// I2C_SLV* registers (Slave 4)
+uint8_t MPU6050_getSlave4Address();
+void MPU6050_setSlave4Address(uint8_t address);
+uint8_t MPU6050_getSlave4Register();
+void MPU6050_setSlave4Register(uint8_t reg);
+void MPU6050_setSlave4OutputByte(uint8_t data);
+bool MPU6050_getSlave4Enabled();
+void MPU6050_setSlave4Enabled(bool enabled);
+bool MPU6050_getSlave4InterruptEnabled();
+void MPU6050_setSlave4InterruptEnabled(bool enabled);
+bool MPU6050_getSlave4WriteMode();
+void MPU6050_setSlave4WriteMode(bool mode);
+uint8_t MPU6050_getSlave4MasterDelay();
+void MPU6050_setSlave4MasterDelay(uint8_t delay);
+uint8_t MPU6050_getSlate4InputByte();
+
+// I2C_MST_STATUS register
+bool MPU6050_getPassthroughStatus();
+bool MPU6050_getSlave4IsDone();
+bool MPU6050_getLostArbitration();
+bool MPU6050_getSlave4Nack();
+bool MPU6050_getSlave3Nack();
+bool MPU6050_getSlave2Nack();
+bool MPU6050_getSlave1Nack();
+bool MPU6050_getSlave0Nack();
+
+// INT_PIN_CFG register
+bool MPU6050_getInterruptMode();
+void MPU6050_setInterruptMode(bool mode);
+bool MPU6050_getInterruptDrive();
+void MPU6050_setInterruptDrive(bool drive);
+bool MPU6050_getInterruptLatch();
+void MPU6050_setInterruptLatch(bool latch);
+bool MPU6050_getInterruptLatchClear();
+void MPU6050_setInterruptLatchClear(bool clear);
+bool MPU6050_getFSyncInterruptLevel();
+void MPU6050_setFSyncInterruptLevel(bool level);
+bool MPU6050_getFSyncInterruptEnabled();
+void MPU6050_setFSyncInterruptEnabled(bool enabled);
+bool MPU6050_getI2CBypassEnabled();
+void MPU6050_setI2CBypassEnabled(bool enabled);
+bool MPU6050_getClockOutputEnabled();
+void MPU6050_setClockOutputEnabled(bool enabled);
+
+// INT_ENABLE register
+uint8_t MPU6050_getIntEnabled();
+void MPU6050_setIntEnabled(uint8_t enabled);
+bool MPU6050_getIntFreefallEnabled();
+void MPU6050_setIntFreefallEnabled(bool enabled);
+bool MPU6050_getIntMotionEnabled();
+void MPU6050_setIntMotionEnabled(bool enabled);
+bool MPU6050_getIntZeroMotionEnabled();
+void MPU6050_setIntZeroMotionEnabled(bool enabled);
+bool MPU6050_getIntFIFOBufferOverflowEnabled();
+void MPU6050_setIntFIFOBufferOverflowEnabled(bool enabled);
+bool MPU6050_getIntI2CMasterEnabled();
+void MPU6050_setIntI2CMasterEnabled(bool enabled);
+bool MPU6050_getIntDataReadyEnabled();
+void MPU6050_setIntDataReadyEnabled(bool enabled);
+
+// INT_STATUS register
+uint8_t MPU6050_getIntStatus();
+bool MPU6050_getIntFreefallStatus();
+bool MPU6050_getIntMotionStatus();
+bool MPU6050_getIntZeroMotionStatus();
+bool MPU6050_getIntFIFOBufferOverflowStatus();
+bool MPU6050_getIntI2CMasterStatus();
+bool MPU6050_getIntDataReadyStatus();
+
+// ACCEL_*OUT_* registers
+void MPU6050_getMotion9(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz, int16_t* mx, int16_t* my, int16_t* mz);
+void MPU6050_getMotion6(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz);
+void MPU6050_getAcceleration(int16_t* x, int16_t* y, int16_t* z);
+int16_t MPU6050_getAccelerationX();
+int16_t MPU6050_getAccelerationY();
+int16_t MPU6050_getAccelerationZ();
+
+// TEMP_OUT_* registers
+int16_t MPU6050_getTemperature();
+
+// GYRO_*OUT_* registers
+void MPU6050_getRotation(int16_t* x, int16_t* y, int16_t* z);
+int16_t MPU6050_getRotationX();
+int16_t MPU6050_getRotationY();
+int16_t MPU6050_getRotationZ();
+
+// EXT_SENS_DATA_* registers
+uint8_t MPU6050_getExternalSensorByte(int position);
+uint16_t MPU6050_getExternalSensorWord(int position);
+uint32_t getExternalSensorDWord(int position);
+
+// MOT_DETECT_STATUS register
+bool MPU6050_getXNegMotionDetected();
+bool MPU6050_getXPosMotionDetected();
+bool MPU6050_getYNegMotionDetected();
+bool MPU6050_getYPosMotionDetected();
+bool MPU6050_getZNegMotionDetected();
+bool MPU6050_getZPosMotionDetected();
+bool MPU6050_getZeroMotionDetected();
+
+// I2C_SLV*_DO register
+void MPU6050_setSlaveOutputByte(uint8_t num, uint8_t data);
+
+// I2C_MST_DELAY_CTRL register
+bool MPU6050_getExternalShadowDelayEnabled();
+void MPU6050_setExternalShadowDelayEnabled(bool enabled);
+bool MPU6050_getSlaveDelayEnabled(uint8_t num);
+void MPU6050_setSlaveDelayEnabled(uint8_t num, bool enabled);
+
+// SIGNAL_PATH_RESET register
+void MPU6050_resetGyroscopePath();
+void MPU6050_resetAccelerometerPath();
+void MPU6050_resetTemperaturePath();
+
+// MOT_DETECT_CTRL register
+uint8_t MPU6050_getAccelerometerPowerOnDelay();
+void MPU6050_setAccelerometerPowerOnDelay(uint8_t delay);
+uint8_t MPU6050_getFreefallDetectionCounterDecrement();
+void MPU6050_setFreefallDetectionCounterDecrement(uint8_t decrement);
+uint8_t MPU6050_getMotionDetectionCounterDecrement();
+void MPU6050_setMotionDetectionCounterDecrement(uint8_t decrement);
+
+// USER_CTRL register
+bool MPU6050_getFIFOEnabled();
+void MPU6050_setFIFOEnabled(bool enabled);
+bool MPU6050_getI2CMasterModeEnabled();
+void MPU6050_setI2CMasterModeEnabled(bool enabled);
+void MPU6050_switchSPIEnabled(bool enabled);
+void MPU6050_resetFIFO();
+void MPU6050_resetI2CMaster();
+void MPU6050_resetSensors();
+
+// PWR_MGMT_1 register
+void MPU6050_reset();
+bool MPU6050_getSleepEnabled();
+void MPU6050_setSleepEnabled(bool enabled);
+bool MPU6050_getWakeCycleEnabled();
+void MPU6050_setWakeCycleEnabled(bool enabled);
+bool MPU6050_getTempSensorEnabled();
+void MPU6050_setTempSensorEnabled(bool enabled);
+uint8_t MPU6050_getClockSource();
+void MPU6050_setClockSource(uint8_t source);
+
+// PWR_MGMT_2 register
+uint8_t MPU6050_getWakeFrequency();
+void MPU6050_setWakeFrequency(uint8_t frequency);
+bool MPU6050_getStandbyXAccelEnabled();
+void MPU6050_setStandbyXAccelEnabled(bool enabled);
+bool MPU6050_getStandbyYAccelEnabled();
+void MPU6050_setStandbyYAccelEnabled(bool enabled);
+bool MPU6050_getStandbyZAccelEnabled();
+void MPU6050_setStandbyZAccelEnabled(bool enabled);
+bool MPU6050_getStandbyXGyroEnabled();
+void MPU6050_setStandbyXGyroEnabled(bool enabled);
+bool MPU6050_getStandbyYGyroEnabled();
+void MPU6050_setStandbyYGyroEnabled(bool enabled);
+bool MPU6050_getStandbyZGyroEnabled();
+void MPU6050_setStandbyZGyroEnabled(bool enabled);
+
+// FIFO_COUNT_* registers
+uint16_t MPU6050_getFIFOCount();
+
+// FIFO_R_W register
+uint8_t MPU6050_getFIFOByte();
+void MPU6050_setFIFOByte(uint8_t data);
+void MPU6050_getFIFOBytes(uint8_t *data, uint8_t length);
+
+// WHO_AM_I register
+uint8_t MPU6050_getDeviceID();
+void MPU6050_setDeviceID(uint8_t id);
+
+// ======== UNDOCUMENTED/DMP REGISTERS/METHODS ========
+
+// XG_OFFS_TC register
+uint8_t MPU6050_getOTPBankValid();
+void MPU6050_setOTPBankValid(bool enabled);
+int8_t getXGyroOffsetTC();
+void MPU6050_setXGyroOffsetTC(int8_t offset);
+
+// YG_OFFS_TC register
+int8_t getYGyroOffsetTC();
+void MPU6050_setYGyroOffsetTC(int8_t offset);
+
+// ZG_OFFS_TC register
+int8_t getZGyroOffsetTC();
+void MPU6050_setZGyroOffsetTC(int8_t offset);
+
+// X_FINE_GAIN register
+int8_t getXFineGain();
+void MPU6050_setXFineGain(int8_t gain);
+
+// Y_FINE_GAIN register
+int8_t getYFineGain();
+void MPU6050_setYFineGain(int8_t gain);
+
+// Z_FINE_GAIN register
+int8_t getZFineGain();
+void MPU6050_setZFineGain(int8_t gain);
+
+// XA_OFFS_* registers
+int16_t MPU6050_getXAccelOffset();
+void MPU6050_setXAccelOffset(int16_t offset);
+
+// YA_OFFS_* register
+int16_t MPU6050_getYAccelOffset();
+void MPU6050_setYAccelOffset(int16_t offset);
+
+// ZA_OFFS_* register
+int16_t MPU6050_getZAccelOffset();
+void MPU6050_setZAccelOffset(int16_t offset);
+
+// XG_OFFS_USR* registers
+int16_t MPU6050_getXGyroOffset();
+void MPU6050_setXGyroOffset(int16_t offset);
+
+// YG_OFFS_USR* register
+int16_t MPU6050_getYGyroOffset();
+void MPU6050_setYGyroOffset(int16_t offset);
+
+// ZG_OFFS_USR* register
+int16_t MPU6050_getZGyroOffset();
+void MPU6050_setZGyroOffset(int16_t offset);
+
+// INT_ENABLE register (DMP functions)
+bool MPU6050_getIntPLLReadyEnabled();
+void MPU6050_setIntPLLReadyEnabled(bool enabled);
+bool MPU6050_getIntDMPEnabled();
+void MPU6050_setIntDMPEnabled(bool enabled);
+
+// DMP_INT_STATUS
+bool MPU6050_getDMPInt5Status();
+bool MPU6050_getDMPInt4Status();
+bool MPU6050_getDMPInt3Status();
+bool MPU6050_getDMPInt2Status();
+bool MPU6050_getDMPInt1Status();
+bool MPU6050_getDMPInt0Status();
+
+// INT_STATUS register (DMP functions)
+bool MPU6050_getIntPLLReadyStatus();
+bool MPU6050_getIntDMPStatus();
+
+// USER_CTRL register (DMP functions)
+bool MPU6050_getDMPEnabled();
+void MPU6050_setDMPEnabled(bool enabled);
+void MPU6050_resetDMP();
+
+// BANK_SEL register
+void MPU6050_setMemoryBank(uint8_t bank, bool prefetchEnabled, bool userBank);
+
+// MEM_START_ADDR register
+void MPU6050_setMemoryStartAddress(uint8_t address);
+
+// MEM_R_W register
+uint8_t MPU6050_readMemoryByte();
+void MPU6050_writeMemoryByte(uint8_t data);
+void MPU6050_readMemoryBlock(uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address);
+//bool MPU6050_writeMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address, bool verify, bool useProgMem);
+//bool MPU6050_writeProgMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address, bool verify);
+
+//bool MPU6050_writeDMPConfigurationSet(const uint8_t *data, uint16_t dataSize, bool useProgMem);
+//bool MPU6050_writeProgDMPConfigurationSet(const uint8_t *data, uint16_t dataSize);
+
+// DMP_CFG_1 register
+uint8_t MPU6050_getDMPConfig1();
+void MPU6050_setDMPConfig1(uint8_t config);
+
+// DMP_CFG_2 register
+uint8_t MPU6050_getDMPConfig2();
+void MPU6050_setDMPConfig2(uint8_t config);
+
+#endif /* _MPU6050_H_ */
diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050_example_main.c b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050_example_main.c
new file mode 100644
index 00000000..8117bd5f
--- /dev/null
+++ b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050_example_main.c
@@ -0,0 +1,131 @@
+/*
+ * File:   LEDMain.c
+ * Author: tommycc
+ *
+ * Created on March 1, 2017, 3:49 PM
+ */
+
+
+// DSPIC30F4013 Configuration Bit Settings
+
+// 'C' source line config statements
+
+// FOSC
+#pragma config FOSFPR = XT_PLL8         // Oscillator (XT w/PLL 8x)
+#pragma config FCKSMEN = CSW_FSCM_OFF   // Clock Switching and Monitor (Sw Disabled, Mon Disabled)
+
+// FWDT
+#pragma config FWPSB = WDTPSB_16        // WDT Prescaler B (1:16)
+#pragma config FWPSA = WDTPSA_512       // WDT Prescaler A (1:512)
+#pragma config WDT = WDT_OFF            // Watchdog Timer (Disabled)
+
+// FBORPOR
+#pragma config FPWRT = PWRT_64          // POR Timer Value (64ms)
+#pragma config BODENV = BORV20          // Brown Out Voltage (Reserved)
+#pragma config BOREN = PBOR_OFF         // PBOR Enable (Disabled)
+#pragma config MCLRE = MCLR_EN          // Master Clear Enable (Enabled)
+
+// FGS
+#pragma config GWRP = GWRP_OFF          // General Code Segment Write Protect (Disabled)
+#pragma config GCP = CODE_PROT_OFF      // General Segment Code Protection (Disabled)
+
+// FICD
+#pragma config ICS = ICS_PGD            // Comm Channel Select (Use PGC/EMUC and PGD/EMUD)
+
+// #pragma config statements should precede project file includes.
+// Use project enums instead of #define for ON and OFF.
+
+#include
+#include
+#include
+#include
+#include"MPU6050.h"
+#include"I2Cdev.h"
+/* Received data is stored in array Buf  */
+char Buf[80];
+char* Receivedddata = Buf;
+/* This is UART1 transmit ISR */
+void __attribute__((__interrupt__)) _U2TXInterrupt(void)
+{  
+   IFS1bits.U2TXIF = 0;
+} 
+/* This is UART1 receive ISR */
+//void __attribute__((__interrupt__)) _U1RXInterrupt(void)
+//{
+//    IFS0bits.U1RXIF = 0;
+/* Read the receive buffer till atleast one or more character can be read */ 
+//    while( DataRdyUART1())
+//    {
+//        ( *(Receivedddata)++) = ReadUART1();
+//    } 
+//} 
+
+int main(void)
+{
+    /* Data to be transmitted using UART communication module */
+    char Buffer[80];
+    //char 
+    /* Holds the value of baud register   */
+    unsigned int baudvalue;   
+    /* Holds the value of uart config reg */
+    unsigned int U2MODEvalue;
+    /* Holds the information regarding uart
+    TX & RX interrupt modes */   
+    unsigned int U2STAvalue;
+    
+    /* Turn off UART1module */
+    CloseUART2();
+    /* Configure uart1 transmit interrupt */
+    ConfigIntUART2(  UART_TX_INT_DIS & UART_TX_INT_PR2);
+    /* Configure UART1 module to transmit 8 bit data with one stopbit. Also Enable loopback mode  */
+    baudvalue = 129;  //9600
+    U2MODEvalue = UART_EN & UART_IDLE_CON & 
+                  UART_DIS_WAKE & UART_DIS_LOOPBACK  &
+                  UART_EN_ABAUD & UART_NO_PAR_8BIT  &
+                  UART_1STOPBIT;
+    U2STAvalue  = UART_INT_TX_BUF_EMPTY  &  
+                  UART_TX_PIN_NORMAL &
+                  UART_TX_ENABLE & UART_INT_RX_3_4_FUL &
+                  UART_ADR_DETECT_DIS &
+                  UART_RX_OVERRUN_CLEAR;
+    unsigned int I2C_config1,I2C_config2;
+    I2C_config1 = (I2C_ON & I2C_IDLE_CON & I2C_CLK_HLD &
+             I2C_IPMI_DIS & I2C_7BIT_ADD &
+             I2C_SLW_DIS & I2C_SM_DIS &
+             I2C_GCALL_DIS & I2C_STR_DIS &
+             I2C_ACK & I2C_ACK_EN & I2C_RCV_EN &
+             I2C_STOP_DIS & I2C_RESTART_DIS &
+             I2C_START_DIS);
+    I2C_config2 = 181;
+    ConfigIntI2C(MI2C_INT_OFF & SI2C_INT_OFF);
+    OpenI2C(I2C_config1,I2C_config2);
+    OpenUART2(U2MODEvalue, U2STAvalue, baudvalue);
+    
+    MPU6050(MPU6050_ADDRESS_AD0_LOW);
+    sprintf(Buf,"Initialize MPU6050\n\0");
+    /* Load transmit buffer and transmit the same till null character is encountered */
+    putsUART2 ((unsigned int *)Buf);
+    /* Wait for  transmission to complete */
+    while(BusyUART2());
+    
+    MPU6050_initialize();
+
+    sprintf(Buf,"Testing device connections...\n\0");
+    putsUART2 ((unsigned int *)Buf);
+    /* Wait for  transmission to complete */
+    while(BusyUART2());
+    
+    //sprintf(Buf,MPU6050_testConnection() ? "MPU6050 connection successful\r\n" :
+    //    "MPU6050 connection failed\r\n");
+    //putsUART2 ((unsigned int *)Buf);
+    /* Wait for  transmission to complete */
+    //while(BusyUART2());
+    
+    
+    
+    
+    //CloseUART2();
+    
+    
+    return 0;
+}
diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/Makefile b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/Makefile
new file mode 100644
index 00000000..fca8e2cc
--- /dev/null
+++ b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/Makefile
@@ -0,0 +1,113 @@
+#
+#  There exist several targets which are by default empty and which can be 
+#  used for execution of your targets. These targets are usually executed 
+#  before and after some main targets. They are: 
+#
+#     .build-pre:              called before 'build' target
+#     .build-post:             called after 'build' target
+#     .clean-pre:              called before 'clean' target
+#     .clean-post:             called after 'clean' target
+#     .clobber-pre:            called before 'clobber' target
+#     .clobber-post:           called after 'clobber' target
+#     .all-pre:                called before 'all' target
+#     .all-post:               called after 'all' target
+#     .help-pre:               called before 'help' target
+#     .help-post:              called after 'help' target
+#
+#  Targets beginning with '.' are not intended to be called on their own.
+#
+#  Main targets can be executed directly, and they are:
+#  
+#     build                    build a specific configuration
+#     clean                    remove built files from a configuration
+#     clobber                  remove all built files
+#     all                      build all configurations
+#     help                     print help mesage
+#  
+#  Targets .build-impl, .clean-impl, .clobber-impl, .all-impl, and
+#  .help-impl are implemented in nbproject/makefile-impl.mk.
+#
+#  Available make variables:
+#
+#     CND_BASEDIR                base directory for relative paths
+#     CND_DISTDIR                default top distribution directory (build artifacts)
+#     CND_BUILDDIR               default top build directory (object files, ...)
+#     CONF                       name of current configuration
+#     CND_ARTIFACT_DIR_${CONF}   directory of build artifact (current configuration)
+#     CND_ARTIFACT_NAME_${CONF}  name of build artifact (current configuration)
+#     CND_ARTIFACT_PATH_${CONF}  path to build artifact (current configuration)
+#     CND_PACKAGE_DIR_${CONF}    directory of package (current configuration)
+#     CND_PACKAGE_NAME_${CONF}   name of package (current configuration)
+#     CND_PACKAGE_PATH_${CONF}   path to package (current configuration)
+#
+# NOCDDL
+
+
+# Environment 
+MKDIR=mkdir
+CP=cp
+CCADMIN=CCadmin
+RANLIB=ranlib
+
+
+# build
+build: .build-post
+
+.build-pre:
+# Add your pre 'build' code here...
+
+.build-post: .build-impl
+# Add your post 'build' code here...
+
+
+# clean
+clean: .clean-post
+
+.clean-pre:
+# Add your pre 'clean' code here...
+# WARNING: the IDE does not call this target since it takes a long time to
+# simply run make. Instead, the IDE removes the configuration directories
+# under build and dist directly without calling make.
+# This target is left here so people can do a clean when running a clean
+# outside the IDE.
+
+.clean-post: .clean-impl
+# Add your post 'clean' code here...
+
+
+# clobber
+clobber: .clobber-post
+
+.clobber-pre:
+# Add your pre 'clobber' code here...
+
+.clobber-post: .clobber-impl
+# Add your post 'clobber' code here...
+
+
+# all
+all: .all-post
+
+.all-pre:
+# Add your pre 'all' code here...
+
+.all-post: .all-impl
+# Add your post 'all' code here...
+
+
+# help
+help: .help-post
+
+.help-pre:
+# Add your pre 'help' code here...
+
+.help-post: .help-impl
+# Add your post 'help' code here...
+
+
+
+# include project implementation makefile
+include nbproject/Makefile-impl.mk
+
+# include project make variables
+include nbproject/Makefile-variables.mk
diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Makefile-default.mk b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Makefile-default.mk
new file mode 100644
index 00000000..2e73c4ab
--- /dev/null
+++ b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Makefile-default.mk
@@ -0,0 +1,182 @@
+#
+# Generated Makefile - do not edit!
+#
+# Edit the Makefile in the project folder instead (../Makefile). Each target
+# has a -pre and a -post target defined where you can add customized code.
+#
+# This makefile implements configuration specific macros and targets.
+
+
+# Include project Makefile
+ifeq "${IGNORE_LOCAL}" "TRUE"
+# do not include local makefile. User is passing all local related variables already
+else
+include Makefile
+# Include makefile containing local settings
+ifeq "$(wildcard nbproject/Makefile-local-default.mk)" "nbproject/Makefile-local-default.mk"
+include nbproject/Makefile-local-default.mk
+endif
+endif
+
+# Environment
+MKDIR=mkdir -p
+RM=rm -f 
+MV=mv 
+CP=cp 
+
+# Macros
+CND_CONF=default
+ifeq ($(TYPE_IMAGE), DEBUG_RUN)
+IMAGE_TYPE=debug
+OUTPUT_SUFFIX=elf
+DEBUGGABLE_SUFFIX=elf
+FINAL_IMAGE=dist/${CND_CONF}/${IMAGE_TYPE}/MPU6050_example.X.${IMAGE_TYPE}.${OUTPUT_SUFFIX}
+else
+IMAGE_TYPE=production
+OUTPUT_SUFFIX=hex
+DEBUGGABLE_SUFFIX=elf
+FINAL_IMAGE=dist/${CND_CONF}/${IMAGE_TYPE}/MPU6050_example.X.${IMAGE_TYPE}.${OUTPUT_SUFFIX}
+endif
+
+ifeq ($(COMPARE_BUILD), true)
+COMPARISON_BUILD=-mafrlcsj
+else
+COMPARISON_BUILD=
+endif
+
+# Object Directory
+OBJECTDIR=build/${CND_CONF}/${IMAGE_TYPE}
+
+# Distribution Directory
+DISTDIR=dist/${CND_CONF}/${IMAGE_TYPE}
+
+# Source Files Quoted if spaced
+SOURCEFILES_QUOTED_IF_SPACED=MPU6050_example_main.c I2Cdev.c MPU6050.c
+
+# Object Files Quoted if spaced
+OBJECTFILES_QUOTED_IF_SPACED=${OBJECTDIR}/MPU6050_example_main.o ${OBJECTDIR}/I2Cdev.o ${OBJECTDIR}/MPU6050.o
+POSSIBLE_DEPFILES=${OBJECTDIR}/MPU6050_example_main.o.d ${OBJECTDIR}/I2Cdev.o.d ${OBJECTDIR}/MPU6050.o.d
+
+# Object Files
+OBJECTFILES=${OBJECTDIR}/MPU6050_example_main.o ${OBJECTDIR}/I2Cdev.o ${OBJECTDIR}/MPU6050.o
+
+# Source Files
+SOURCEFILES=MPU6050_example_main.c I2Cdev.c MPU6050.c
+
+
+CFLAGS=
+ASFLAGS=
+LDLIBSOPTIONS=
+
+############# Tool locations ##########################################
+# If you copy a project from one host to another, the path where the  #
+# compiler is installed may be different.                             #
+# If you open this project with MPLAB X in the new host, this         #
+# makefile will be regenerated and the paths will be corrected.       #
+#######################################################################
+# fixDeps replaces a bunch of sed/cat/printf statements that slow down the build
+FIXDEPS=fixDeps
+
+.build-conf:  ${BUILD_SUBPROJECTS}
+ifneq ($(INFORMATION_MESSAGE), )
+	@echo $(INFORMATION_MESSAGE)
+endif
+	${MAKE}  -f nbproject/Makefile-default.mk dist/${CND_CONF}/${IMAGE_TYPE}/MPU6050_example.X.${IMAGE_TYPE}.${OUTPUT_SUFFIX}
+
+MP_PROCESSOR_OPTION=30F4013
+MP_LINKER_FILE_OPTION=,--script=p30F4013.gld
+# ------------------------------------------------------------------------------------
+# Rules for buildStep: compile
+ifeq ($(TYPE_IMAGE), DEBUG_RUN)
+${OBJECTDIR}/MPU6050_example_main.o: MPU6050_example_main.c  nbproject/Makefile-${CND_CONF}.mk
+	@${MKDIR} "${OBJECTDIR}" 
+	@${RM} ${OBJECTDIR}/MPU6050_example_main.o.d 
+	@${RM} ${OBJECTDIR}/MPU6050_example_main.o 
+	${MP_CC} $(MP_EXTRA_CC_PRE)  MPU6050_example_main.c  -o ${OBJECTDIR}/MPU6050_example_main.o  -c -mcpu=$(MP_PROCESSOR_OPTION)  -MMD -MF "${OBJECTDIR}/MPU6050_example_main.o.d"      -g -D__DEBUG -D__MPLAB_DEBUGGER_PK3=1    -omf=elf -DXPRJ_default=$(CND_CONF)  -legacy-libc  $(COMPARISON_BUILD)  --std=gnu99 -O0 -msmart-io=1 -Wall -msfr-warn=off  
+	@${FIXDEPS} "${OBJECTDIR}/MPU6050_example_main.o.d" $(SILENT)  -rsi ${MP_CC_DIR}../ 
+	
+${OBJECTDIR}/I2Cdev.o: I2Cdev.c  nbproject/Makefile-${CND_CONF}.mk
+	@${MKDIR} "${OBJECTDIR}" 
+	@${RM} ${OBJECTDIR}/I2Cdev.o.d 
+	@${RM} ${OBJECTDIR}/I2Cdev.o 
+	${MP_CC} $(MP_EXTRA_CC_PRE)  I2Cdev.c  -o ${OBJECTDIR}/I2Cdev.o  -c -mcpu=$(MP_PROCESSOR_OPTION)  -MMD -MF "${OBJECTDIR}/I2Cdev.o.d"      -g -D__DEBUG -D__MPLAB_DEBUGGER_PK3=1    -omf=elf -DXPRJ_default=$(CND_CONF)  -legacy-libc  $(COMPARISON_BUILD)  --std=gnu99 -O0 -msmart-io=1 -Wall -msfr-warn=off  
+	@${FIXDEPS} "${OBJECTDIR}/I2Cdev.o.d" $(SILENT)  -rsi ${MP_CC_DIR}../ 
+	
+${OBJECTDIR}/MPU6050.o: MPU6050.c  nbproject/Makefile-${CND_CONF}.mk
+	@${MKDIR} "${OBJECTDIR}" 
+	@${RM} ${OBJECTDIR}/MPU6050.o.d 
+	@${RM} ${OBJECTDIR}/MPU6050.o 
+	${MP_CC} $(MP_EXTRA_CC_PRE)  MPU6050.c  -o ${OBJECTDIR}/MPU6050.o  -c -mcpu=$(MP_PROCESSOR_OPTION)  -MMD -MF "${OBJECTDIR}/MPU6050.o.d"      -g -D__DEBUG -D__MPLAB_DEBUGGER_PK3=1    -omf=elf -DXPRJ_default=$(CND_CONF)  -legacy-libc  $(COMPARISON_BUILD)  --std=gnu99 -O0 -msmart-io=1 -Wall -msfr-warn=off  
+	@${FIXDEPS} "${OBJECTDIR}/MPU6050.o.d" $(SILENT)  -rsi ${MP_CC_DIR}../ 
+	
+else
+${OBJECTDIR}/MPU6050_example_main.o: MPU6050_example_main.c  nbproject/Makefile-${CND_CONF}.mk
+	@${MKDIR} "${OBJECTDIR}" 
+	@${RM} ${OBJECTDIR}/MPU6050_example_main.o.d 
+	@${RM} ${OBJECTDIR}/MPU6050_example_main.o 
+	${MP_CC} $(MP_EXTRA_CC_PRE)  MPU6050_example_main.c  -o ${OBJECTDIR}/MPU6050_example_main.o  -c -mcpu=$(MP_PROCESSOR_OPTION)  -MMD -MF "${OBJECTDIR}/MPU6050_example_main.o.d"        -g -omf=elf -DXPRJ_default=$(CND_CONF)  -legacy-libc  $(COMPARISON_BUILD)  --std=gnu99 -O0 -msmart-io=1 -Wall -msfr-warn=off  
+	@${FIXDEPS} "${OBJECTDIR}/MPU6050_example_main.o.d" $(SILENT)  -rsi ${MP_CC_DIR}../ 
+	
+${OBJECTDIR}/I2Cdev.o: I2Cdev.c  nbproject/Makefile-${CND_CONF}.mk
+	@${MKDIR} "${OBJECTDIR}" 
+	@${RM} ${OBJECTDIR}/I2Cdev.o.d 
+	@${RM} ${OBJECTDIR}/I2Cdev.o 
+	${MP_CC} $(MP_EXTRA_CC_PRE)  I2Cdev.c  -o ${OBJECTDIR}/I2Cdev.o  -c -mcpu=$(MP_PROCESSOR_OPTION)  -MMD -MF "${OBJECTDIR}/I2Cdev.o.d"        -g -omf=elf -DXPRJ_default=$(CND_CONF)  -legacy-libc  $(COMPARISON_BUILD)  --std=gnu99 -O0 -msmart-io=1 -Wall -msfr-warn=off  
+	@${FIXDEPS} "${OBJECTDIR}/I2Cdev.o.d" $(SILENT)  -rsi ${MP_CC_DIR}../ 
+	
+${OBJECTDIR}/MPU6050.o: MPU6050.c  nbproject/Makefile-${CND_CONF}.mk
+	@${MKDIR} "${OBJECTDIR}" 
+	@${RM} ${OBJECTDIR}/MPU6050.o.d 
+	@${RM} ${OBJECTDIR}/MPU6050.o 
+	${MP_CC} $(MP_EXTRA_CC_PRE)  MPU6050.c  -o ${OBJECTDIR}/MPU6050.o  -c -mcpu=$(MP_PROCESSOR_OPTION)  -MMD -MF "${OBJECTDIR}/MPU6050.o.d"        -g -omf=elf -DXPRJ_default=$(CND_CONF)  -legacy-libc  $(COMPARISON_BUILD)  --std=gnu99 -O0 -msmart-io=1 -Wall -msfr-warn=off  
+	@${FIXDEPS} "${OBJECTDIR}/MPU6050.o.d" $(SILENT)  -rsi ${MP_CC_DIR}../ 
+	
+endif
+
+# ------------------------------------------------------------------------------------
+# Rules for buildStep: assemble
+ifeq ($(TYPE_IMAGE), DEBUG_RUN)
+else
+endif
+
+# ------------------------------------------------------------------------------------
+# Rules for buildStep: assemblePreproc
+ifeq ($(TYPE_IMAGE), DEBUG_RUN)
+else
+endif
+
+# ------------------------------------------------------------------------------------
+# Rules for buildStep: link
+ifeq ($(TYPE_IMAGE), DEBUG_RUN)
+dist/${CND_CONF}/${IMAGE_TYPE}/MPU6050_example.X.${IMAGE_TYPE}.${OUTPUT_SUFFIX}: ${OBJECTFILES}  nbproject/Makefile-${CND_CONF}.mk    
+	@${MKDIR} dist/${CND_CONF}/${IMAGE_TYPE} 
+	${MP_CC} $(MP_EXTRA_LD_PRE)  -o dist/${CND_CONF}/${IMAGE_TYPE}/MPU6050_example.X.${IMAGE_TYPE}.${OUTPUT_SUFFIX}  ${OBJECTFILES_QUOTED_IF_SPACED}      -mcpu=$(MP_PROCESSOR_OPTION)        -D__DEBUG -D__MPLAB_DEBUGGER_PK3=1  -omf=elf -DXPRJ_default=$(CND_CONF)  -legacy-libc  $(COMPARISON_BUILD)  --std=gnu99  -mreserve=data@0x800:0x81F -mreserve=data@0x820:0x821 -mreserve=data@0x822:0x823 -mreserve=data@0x824:0x84F   -Wl,,--defsym=__MPLAB_BUILD=1,--defsym=__MPLAB_DEBUG=1,--defsym=__DEBUG=1,--defsym=__MPLAB_DEBUGGER_PK3=1,$(MP_LINKER_FILE_OPTION),--stack=16,--check-sections,--data-init,--pack-data,--handles,--isr,--no-gc-sections,--fill-upper=0,--stackguard=16,--no-force-link,--smart-io,-Map="${DISTDIR}/${PROJECTNAME}.${IMAGE_TYPE}.map",--report-mem,--memorysummary,dist/${CND_CONF}/${IMAGE_TYPE}/memoryfile.xml$(MP_EXTRA_LD_POST) 
+	
+else
+dist/${CND_CONF}/${IMAGE_TYPE}/MPU6050_example.X.${IMAGE_TYPE}.${OUTPUT_SUFFIX}: ${OBJECTFILES}  nbproject/Makefile-${CND_CONF}.mk   
+	@${MKDIR} dist/${CND_CONF}/${IMAGE_TYPE} 
+	${MP_CC} $(MP_EXTRA_LD_PRE)  -o dist/${CND_CONF}/${IMAGE_TYPE}/MPU6050_example.X.${IMAGE_TYPE}.${DEBUGGABLE_SUFFIX}  ${OBJECTFILES_QUOTED_IF_SPACED}      -mcpu=$(MP_PROCESSOR_OPTION)        -omf=elf -DXPRJ_default=$(CND_CONF)  -legacy-libc  $(COMPARISON_BUILD)  --std=gnu99 -Wl,,--defsym=__MPLAB_BUILD=1,$(MP_LINKER_FILE_OPTION),--stack=16,--check-sections,--data-init,--pack-data,--handles,--isr,--no-gc-sections,--fill-upper=0,--stackguard=16,--no-force-link,--smart-io,-Map="${DISTDIR}/${PROJECTNAME}.${IMAGE_TYPE}.map",--report-mem,--memorysummary,dist/${CND_CONF}/${IMAGE_TYPE}/memoryfile.xml$(MP_EXTRA_LD_POST) 
+	${MP_CC_DIR}/xc16-bin2hex dist/${CND_CONF}/${IMAGE_TYPE}/MPU6050_example.X.${IMAGE_TYPE}.${DEBUGGABLE_SUFFIX} -a  -omf=elf  
+	
+endif
+
+
+# Subprojects
+.build-subprojects:
+
+
+# Subprojects
+.clean-subprojects:
+
+# Clean Targets
+.clean-conf: ${CLEAN_SUBPROJECTS}
+	${RM} -r build/default
+	${RM} -r dist/default
+
+# Enable dependency checking
+.dep.inc: .depcheck-impl
+
+DEPFILES=$(shell "${PATH_TO_IDE_BIN}"mplabwildcard ${POSSIBLE_DEPFILES})
+ifneq (${DEPFILES},)
+include ${DEPFILES}
+endif
diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Makefile-genesis.properties b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Makefile-genesis.properties
new file mode 100644
index 00000000..a8765e5f
--- /dev/null
+++ b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Makefile-genesis.properties
@@ -0,0 +1,9 @@
+#
+#Wed Mar 15 15:13:11 CST 2017
+default.com-microchip-mplab-nbide-toolchainXC16-XC16LanguageToolchain.md5=ebaa75370c1463d650408e4144ba15de
+default.languagetoolchain.dir=/opt/microchip/xc16/v1.30/bin
+configurations-xml=390e761992510ba6b77d8cf6d2379168
+com-microchip-mplab-nbide-embedded-makeproject-MakeProject.md5=8b140fb87818dc96ed4f726b716b40e9
+default.languagetoolchain.version=1.30
+host.platform=linux
+conf.ids=default
diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Makefile-impl.mk b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Makefile-impl.mk
new file mode 100644
index 00000000..5b2593af
--- /dev/null
+++ b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Makefile-impl.mk
@@ -0,0 +1,69 @@
+#
+# Generated Makefile - do not edit!
+#
+# Edit the Makefile in the project folder instead (../Makefile). Each target
+# has a pre- and a post- target defined where you can add customization code.
+#
+# This makefile implements macros and targets common to all configurations.
+#
+# NOCDDL
+
+
+# Building and Cleaning subprojects are done by default, but can be controlled with the SUB
+# macro. If SUB=no, subprojects will not be built or cleaned. The following macro
+# statements set BUILD_SUB-CONF and CLEAN_SUB-CONF to .build-reqprojects-conf
+# and .clean-reqprojects-conf unless SUB has the value 'no'
+SUB_no=NO
+SUBPROJECTS=${SUB_${SUB}}
+BUILD_SUBPROJECTS_=.build-subprojects
+BUILD_SUBPROJECTS_NO=
+BUILD_SUBPROJECTS=${BUILD_SUBPROJECTS_${SUBPROJECTS}}
+CLEAN_SUBPROJECTS_=.clean-subprojects
+CLEAN_SUBPROJECTS_NO=
+CLEAN_SUBPROJECTS=${CLEAN_SUBPROJECTS_${SUBPROJECTS}}
+
+
+# Project Name
+PROJECTNAME=MPU6050_example.X
+
+# Active Configuration
+DEFAULTCONF=default
+CONF=${DEFAULTCONF}
+
+# All Configurations
+ALLCONFS=default 
+
+
+# build
+.build-impl: .build-pre
+	${MAKE} -f nbproject/Makefile-${CONF}.mk SUBPROJECTS=${SUBPROJECTS} .build-conf
+
+
+# clean
+.clean-impl: .clean-pre
+	${MAKE} -f nbproject/Makefile-${CONF}.mk SUBPROJECTS=${SUBPROJECTS} .clean-conf
+
+# clobber
+.clobber-impl: .clobber-pre .depcheck-impl
+	    ${MAKE} SUBPROJECTS=${SUBPROJECTS} CONF=default clean
+
+
+
+# all
+.all-impl: .all-pre .depcheck-impl
+	    ${MAKE} SUBPROJECTS=${SUBPROJECTS} CONF=default build
+
+
+
+# dependency checking support
+.depcheck-impl:
+#	@echo "# This code depends on make tool being used" >.dep.inc
+#	@if [ -n "${MAKE_VERSION}" ]; then \
+#	    echo "DEPFILES=\$$(wildcard \$$(addsuffix .d, \$${OBJECTFILES}))" >>.dep.inc; \
+#	    echo "ifneq (\$${DEPFILES},)" >>.dep.inc; \
+#	    echo "include \$${DEPFILES}" >>.dep.inc; \
+#	    echo "endif" >>.dep.inc; \
+#	else \
+#	    echo ".KEEP_STATE:" >>.dep.inc; \
+#	    echo ".KEEP_STATE_FILE:.make.state.\$${CONF}" >>.dep.inc; \
+#	fi
diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Makefile-local-default.mk b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Makefile-local-default.mk
new file mode 100644
index 00000000..38870624
--- /dev/null
+++ b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Makefile-local-default.mk
@@ -0,0 +1,36 @@
+#
+# Generated Makefile - do not edit!
+#
+#
+# This file contains information about the location of compilers and other tools.
+# If you commmit this file into your revision control server, you will be able to 
+# to checkout the project and build it from the command line with make. However,
+# if more than one person works on the same project, then this file might show
+# conflicts since different users are bound to have compilers in different places.
+# In that case you might choose to not commit this file and let MPLAB X recreate this file
+# for each user. The disadvantage of not commiting this file is that you must run MPLAB X at
+# least once so the file gets created and the project can be built. Finally, you can also
+# avoid using this file at all if you are only building from the command line with make.
+# You can invoke make with the values of the macros:
+# $ makeMP_CC="/opt/microchip/mplabc30/v3.30c/bin/pic30-gcc" ...  
+#
+PATH_TO_IDE_BIN=/opt/microchip/mplabx/v3.45/mplab_ide/platform/../mplab_ide/modules/../../bin/
+# Adding MPLAB X bin directory to path.
+PATH:=/opt/microchip/mplabx/v3.45/mplab_ide/platform/../mplab_ide/modules/../../bin/:$(PATH)
+# Path to java used to run MPLAB X when this makefile was created
+MP_JAVA_PATH="/opt/microchip/mplabx/v3.45/sys/java/jre1.8.0_91/bin/"
+OS_CURRENT="$(shell uname -s)"
+MP_CC="/opt/microchip/xc16/v1.30/bin/xc16-gcc"
+# MP_CPPC is not defined
+# MP_BC is not defined
+MP_AS="/opt/microchip/xc16/v1.30/bin/xc16-as"
+MP_LD="/opt/microchip/xc16/v1.30/bin/xc16-ld"
+MP_AR="/opt/microchip/xc16/v1.30/bin/xc16-ar"
+DEP_GEN=${MP_JAVA_PATH}java -jar "/opt/microchip/mplabx/v3.45/mplab_ide/platform/../mplab_ide/modules/../../bin/extractobjectdependencies.jar"
+MP_CC_DIR="/opt/microchip/xc16/v1.30/bin"
+# MP_CPPC_DIR is not defined
+# MP_BC_DIR is not defined
+MP_AS_DIR="/opt/microchip/xc16/v1.30/bin"
+MP_LD_DIR="/opt/microchip/xc16/v1.30/bin"
+MP_AR_DIR="/opt/microchip/xc16/v1.30/bin"
+# MP_BC_DIR is not defined
diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Makefile-variables.mk b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Makefile-variables.mk
new file mode 100644
index 00000000..a8ce072f
--- /dev/null
+++ b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Makefile-variables.mk
@@ -0,0 +1,13 @@
+#
+# Generated - do not edit!
+#
+# NOCDDL
+#
+CND_BASEDIR=`pwd`
+# default configuration
+CND_ARTIFACT_DIR_default=dist/default/production
+CND_ARTIFACT_NAME_default=MPU6050_example.X.production.hex
+CND_ARTIFACT_PATH_default=dist/default/production/MPU6050_example.X.production.hex
+CND_PACKAGE_DIR_default=${CND_DISTDIR}/default/package
+CND_PACKAGE_NAME_default=mpu6050example.x.tar
+CND_PACKAGE_PATH_default=${CND_DISTDIR}/default/package/mpu6050example.x.tar
diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Package-default.bash b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Package-default.bash
new file mode 100644
index 00000000..552f66ff
--- /dev/null
+++ b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Package-default.bash
@@ -0,0 +1,73 @@
+#!/bin/bash -x
+
+#
+# Generated - do not edit!
+#
+
+# Macros
+TOP=`pwd`
+CND_CONF=default
+CND_DISTDIR=dist
+TMPDIR=build/${CND_CONF}/${IMAGE_TYPE}/tmp-packaging
+TMPDIRNAME=tmp-packaging
+OUTPUT_PATH=dist/${CND_CONF}/${IMAGE_TYPE}/MPU6050_example.X.${IMAGE_TYPE}.${OUTPUT_SUFFIX}
+OUTPUT_BASENAME=MPU6050_example.X.${IMAGE_TYPE}.${OUTPUT_SUFFIX}
+PACKAGE_TOP_DIR=mpu6050example.x/
+
+# Functions
+function checkReturnCode
+{
+    rc=$?
+    if [ $rc != 0 ]
+    then
+        exit $rc
+    fi
+}
+function makeDirectory
+# $1 directory path
+# $2 permission (optional)
+{
+    mkdir -p "$1"
+    checkReturnCode
+    if [ "$2" != "" ]
+    then
+      chmod $2 "$1"
+      checkReturnCode
+    fi
+}
+function copyFileToTmpDir
+# $1 from-file path
+# $2 to-file path
+# $3 permission
+{
+    cp "$1" "$2"
+    checkReturnCode
+    if [ "$3" != "" ]
+    then
+        chmod $3 "$2"
+        checkReturnCode
+    fi
+}
+
+# Setup
+cd "${TOP}"
+mkdir -p ${CND_DISTDIR}/${CND_CONF}/package
+rm -rf ${TMPDIR}
+mkdir -p ${TMPDIR}
+
+# Copy files and create directories and links
+cd "${TOP}"
+makeDirectory ${TMPDIR}/mpu6050example.x/bin
+copyFileToTmpDir "${OUTPUT_PATH}" "${TMPDIR}/${PACKAGE_TOP_DIR}bin/${OUTPUT_BASENAME}" 0755
+
+
+# Generate tar file
+cd "${TOP}"
+rm -f ${CND_DISTDIR}/${CND_CONF}/package/mpu6050example.x.tar
+cd ${TMPDIR}
+tar -vcf ../../../../${CND_DISTDIR}/${CND_CONF}/package/mpu6050example.x.tar *
+checkReturnCode
+
+# Cleanup
+cd "${TOP}"
+rm -rf ${TMPDIR}
diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/configurations.xml b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/configurations.xml
new file mode 100644
index 00000000..f2f34ca0
--- /dev/null
+++ b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/configurations.xml
@@ -0,0 +1,224 @@
+
+
+  
+    
+      I2Cdev.h
+      MPU6050.h
+    
+    
+    
+    
+      MPU6050_example_main.c
+      I2Cdev.c
+      MPU6050.c
+    
+    
+      Makefile
+    
+  
+  Makefile
+  
+    
+      
+        localhost
+        dsPIC30F4013
+        
+        
+        PICkit3PlatformTool
+        XC16
+        1.30
+        2
+      
+      
+        
+          
+          
+        
+        
+        
+        
+          false
+          false
+          
+        
+        
+        
+      
+      
+        false
+        
+        false
+        
+        false
+        false
+        false
+      
+      
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+      
+      
+        
+      
+      
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+      
+      
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+      
+      
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+      
+    
+  
+
diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/project.xml b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/project.xml
new file mode 100644
index 00000000..3230bc50
--- /dev/null
+++ b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/project.xml
@@ -0,0 +1,17 @@
+
+
+    com.microchip.mplab.nbide.embedded.makeproject
+    
+        
+            MPU6050_example
+            04e5589e-1a03-434e-ace3-9ef3c9c9d958
+            0
+            c
+            
+            h
+            
+            ISO-8859-1
+            
+        
+    
+

From 2782a6c2d1bc4519d82671424fbda39abebb601d Mon Sep 17 00:00:00 2001
From: Suyash Behera 
Date: Sat, 25 Mar 2017 22:43:21 +0530
Subject: [PATCH 165/335] Entering fuse ROM access mode to read adjustment
 registers

The ```getAdjustment()``` and ```setAdjustment()``` functions need to put the magnetometer in fuse ROM access mode before the adjustment registers can be read as specified in the datasheet.
---
 Arduino/AK8975/AK8975.cpp | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/Arduino/AK8975/AK8975.cpp b/Arduino/AK8975/AK8975.cpp
index c68b5cd9..1fedf829 100644
--- a/Arduino/AK8975/AK8975.cpp
+++ b/Arduino/AK8975/AK8975.cpp
@@ -148,35 +148,51 @@ void AK8975::disableI2C() {
 
 // ASA* registers
 void AK8975::getAdjustment(int8_t *x, int8_t *y, int8_t *z) {
+    I2Cdev::writeByte(devAddr, AK8975_RA_CNTL, 0x0F); // Enter Fuse ROM access mode
+    delay(10);
     I2Cdev::readBytes(devAddr, AK8975_RA_ASAX, 3, buffer);
     *x = buffer[0];
     *y = buffer[1];
     *z = buffer[2];
 }
 void AK8975::setAdjustment(int8_t x, int8_t y, int8_t z) {
+    I2Cdev::writeByte(devAddr, AK8975_RA_CNTL, 0x0F); // Enter Fuse ROM access mode
+    delay(10);
     buffer[0] = x;
     buffer[1] = y;
     buffer[2] = z;
     I2Cdev::writeBytes(devAddr, AK8975_RA_ASAX, 3, buffer);
 }
 uint8_t AK8975::getAdjustmentX() {
+    I2Cdev::writeByte(devAddr, AK8975_RA_CNTL, 0x0F); // Enter Fuse ROM access mode
+    delay(10);
     I2Cdev::readByte(devAddr, AK8975_RA_ASAX, buffer);
     return buffer[0];
 }
 void AK8975::setAdjustmentX(uint8_t x) {
+    I2Cdev::writeByte(devAddr, AK8975_RA_CNTL, 0x0F); // Enter Fuse ROM access mode
+    delay(10);
     I2Cdev::writeByte(devAddr, AK8975_RA_ASAX, x);
 }
 uint8_t AK8975::getAdjustmentY() {
+    I2Cdev::writeByte(devAddr, AK8975_RA_CNTL, 0x0F); // Enter Fuse ROM access mode
+    delay(10);
     I2Cdev::readByte(devAddr, AK8975_RA_ASAY, buffer);
     return buffer[0];
 }
 void AK8975::setAdjustmentY(uint8_t y) {
+    I2Cdev::writeByte(devAddr, AK8975_RA_CNTL, 0x0F); // Enter Fuse ROM access mode
+    delay(10);
     I2Cdev::writeByte(devAddr, AK8975_RA_ASAY, y);
 }
 uint8_t AK8975::getAdjustmentZ() {
+    I2Cdev::writeByte(devAddr, AK8975_RA_CNTL, 0x0F); // Enter Fuse ROM access mode
+    delay(10);
     I2Cdev::readByte(devAddr, AK8975_RA_ASAZ, buffer);
     return buffer[0];
 }
 void AK8975::setAdjustmentZ(uint8_t z) {
+    I2Cdev::writeByte(devAddr, AK8975_RA_CNTL, 0x0F); // Enter Fuse ROM access mode
+    delay(10);
     I2Cdev::writeByte(devAddr, AK8975_RA_ASAZ, z);
-}
\ No newline at end of file
+}

From d31a75c2630892375819fb5cd4e3fe285a5b6206 Mon Sep 17 00:00:00 2001
From: kripton 
Date: Tue, 28 Mar 2017 17:01:15 +0300
Subject: [PATCH 166/335] Initial commit for stm32 support

---
 STM32/HMC5883/HMC5883L.c |  358 +++++
 STM32/HMC5883/HMC5883L.h |  142 ++
 STM32/I2Cdev.c           |  294 ++++
 STM32/I2Cdev.h           |   61 +
 STM32/MPU6050/MPU6050.c  | 3143 ++++++++++++++++++++++++++++++++++++++
 STM32/MPU6050/MPU6050.h  |  788 ++++++++++
 STM32/README.md          |   15 +
 7 files changed, 4801 insertions(+)
 create mode 100644 STM32/HMC5883/HMC5883L.c
 create mode 100644 STM32/HMC5883/HMC5883L.h
 create mode 100644 STM32/I2Cdev.c
 create mode 100644 STM32/I2Cdev.h
 create mode 100644 STM32/MPU6050/MPU6050.c
 create mode 100644 STM32/MPU6050/MPU6050.h
 create mode 100644 STM32/README.md

diff --git a/STM32/HMC5883/HMC5883L.c b/STM32/HMC5883/HMC5883L.c
new file mode 100644
index 00000000..e4adba09
--- /dev/null
+++ b/STM32/HMC5883/HMC5883L.c
@@ -0,0 +1,358 @@
+// I2Cdev library collection - HMC5883L I2C device class header file
+// Based on Honeywell HMC5883L datasheet, 10/2010 (Form #900405 Rev B)
+// 6/12/2012 by Jeff Rowberg 
+// 6/6/2015 by Andrey Voloshin 
+// 03/28/2017 by Kamnev Yuriy 
+//
+// Changelog:
+//     2017-03-28 - ported to STM32 using Keil MDK Pack
+//     2015-06-06 - ported to STM32 HAL library from Arduino code
+//     2012-06-12 - fixed swapped Y/Z axes
+//     2011-08-22 - small Doxygen comment fixes
+//     2011-07-31 - initial release
+
+/* ============================================
+I2Cdev device library code is placed under the MIT license
+Copyright (c) 2011 Jeff Rowberg
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+===============================================
+*/
+
+#include "HMC5883L.h"
+
+static uint8_t devAddr;
+static uint8_t buffer[6];
+static uint8_t mode;
+
+
+/** Power on and prepare for general usage.
+ * This will prepare the magnetometer with default settings, ready for single-
+ * use mode (very low power requirements). Default settings include 8-sample
+ * averaging, 15 Hz data output rate, normal measurement bias, a,d 1090 gain (in
+ * terms of LSB/Gauss). Be sure to adjust any settings you need specifically
+ * after initialization, especially the gain settings if you happen to be seeing
+ * a lot of -4096 values (see the datasheet for mor information).
+ */
+void HMC5883L_initialize() {
+    devAddr = HMC5883L_DEFAULT_ADDRESS;
+    // write CONFIG_A register
+    I2Cdev_writeByte(devAddr, HMC5883L_RA_CONFIG_A,
+        (HMC5883L_AVERAGING_8 << (HMC5883L_CRA_AVERAGE_BIT - HMC5883L_CRA_AVERAGE_LENGTH + 1)) |
+        (HMC5883L_RATE_15     << (HMC5883L_CRA_RATE_BIT - HMC5883L_CRA_RATE_LENGTH + 1)) |
+        (HMC5883L_BIAS_NORMAL << (HMC5883L_CRA_BIAS_BIT - HMC5883L_CRA_BIAS_LENGTH + 1)));
+
+    // write CONFIG_B register
+    HMC5883L_setGain(HMC5883L_GAIN_1090);
+
+    // write MODE register
+    HMC5883L_setMode(HMC5883L_MODE_SINGLE);
+}
+
+/** Verify the I2C connection.
+ * Make sure the device is connected and responds as expected.
+ * @return True if connection is valid, false otherwise
+ */
+bool HMC5883L_testConnection() {
+    if (I2Cdev_readBytes(devAddr, HMC5883L_RA_ID_A, 3, buffer) == 0) {
+        return (buffer[0] == 'H' && buffer[1] == '4' && buffer[2] == '3');
+    }
+    return false;
+}
+
+// CONFIG_A register
+
+/** Get number of samples averaged per measurement.
+ * @return Current samples averaged per measurement (0-3 for 1/2/4/8 respectively)
+ * @see HMC5883L_AVERAGING_8
+ * @see HMC5883L_RA_CONFIG_A
+ * @see HMC5883L_CRA_AVERAGE_BIT
+ * @see HMC5883L_CRA_AVERAGE_LENGTH
+ */
+uint8_t HMC5883L_getSampleAveraging() {
+    I2Cdev_readBits(devAddr, HMC5883L_RA_CONFIG_A, HMC5883L_CRA_AVERAGE_BIT, HMC5883L_CRA_AVERAGE_LENGTH, buffer);
+    return buffer[0];
+}
+/** Set number of samples averaged per measurement.
+ * @param averaging New samples averaged per measurement setting(0-3 for 1/2/4/8 respectively)
+ * @see HMC5883L_RA_CONFIG_A
+ * @see HMC5883L_CRA_AVERAGE_BIT
+ * @see HMC5883L_CRA_AVERAGE_LENGTH
+ */
+void HMC5883L_setSampleAveraging(uint8_t averaging) {
+    I2Cdev_writeBits(devAddr, HMC5883L_RA_CONFIG_A, HMC5883L_CRA_AVERAGE_BIT, HMC5883L_CRA_AVERAGE_LENGTH, averaging);
+}
+/** Get data output rate value.
+ * The Table below shows all selectable output rates in continuous measurement
+ * mode. All three channels shall be measured within a given output rate. Other
+ * output rates with maximum rate of 160 Hz can be achieved by monitoring DRDY
+ * interrupt pin in single measurement mode.
+ *
+ * Value | Typical Data Output Rate (Hz)
+ * ------+------------------------------
+ * 0     | 0.75
+ * 1     | 1.5
+ * 2     | 3
+ * 3     | 7.5
+ * 4     | 15 (Default)
+ * 5     | 30
+ * 6     | 75
+ * 7     | Not used
+ *
+ * @return Current rate of data output to registers
+ * @see HMC5883L_RATE_15
+ * @see HMC5883L_RA_CONFIG_A
+ * @see HMC5883L_CRA_RATE_BIT
+ * @see HMC5883L_CRA_RATE_LENGTH
+ */
+uint8_t HMC5883L_getDataRate() {
+    I2Cdev_readBits(devAddr, HMC5883L_RA_CONFIG_A, HMC5883L_CRA_RATE_BIT, HMC5883L_CRA_RATE_LENGTH, buffer);
+    return buffer[0];
+}
+/** Set data output rate value.
+ * @param rate Rate of data output to registers
+ * @see getDataRate()
+ * @see HMC5883L_RATE_15
+ * @see HMC5883L_RA_CONFIG_A
+ * @see HMC5883L_CRA_RATE_BIT
+ * @see HMC5883L_CRA_RATE_LENGTH
+ */
+void HMC5883L_setDataRate(uint8_t rate) {
+    I2Cdev_writeBits(devAddr, HMC5883L_RA_CONFIG_A, HMC5883L_CRA_RATE_BIT, HMC5883L_CRA_RATE_LENGTH, rate);
+}
+/** Get measurement bias value.
+ * @return Current bias value (0-2 for normal/positive/negative respectively)
+ * @see HMC5883L_BIAS_NORMAL
+ * @see HMC5883L_RA_CONFIG_A
+ * @see HMC5883L_CRA_BIAS_BIT
+ * @see HMC5883L_CRA_BIAS_LENGTH
+ */
+uint8_t HMC5883L_getMeasurementBias() {
+    I2Cdev_readBits(devAddr, HMC5883L_RA_CONFIG_A, HMC5883L_CRA_BIAS_BIT, HMC5883L_CRA_BIAS_LENGTH, buffer);
+    return buffer[0];
+}
+/** Set measurement bias value.
+ * @param bias New bias value (0-2 for normal/positive/negative respectively)
+ * @see HMC5883L_BIAS_NORMAL
+ * @see HMC5883L_RA_CONFIG_A
+ * @see HMC5883L_CRA_BIAS_BIT
+ * @see HMC5883L_CRA_BIAS_LENGTH
+ */
+void HMC5883L_setMeasurementBias(uint8_t bias) {
+    I2Cdev_writeBits(devAddr, HMC5883L_RA_CONFIG_A, HMC5883L_CRA_BIAS_BIT, HMC5883L_CRA_BIAS_LENGTH, bias);
+}
+
+// CONFIG_B register
+
+/** Get magnetic field gain value.
+ * The table below shows nominal gain settings. Use the "Gain" column to convert
+ * counts to Gauss. Choose a lower gain value (higher GN#) when total field
+ * strength causes overflow in one of the data output registers (saturation).
+ * The data output range for all settings is 0xF800-0x07FF (-2048 - 2047).
+ *
+ * Value | Field Range | Gain (LSB/Gauss)
+ * ------+-------------+-----------------
+ * 0     | +/- 0.88 Ga | 1370
+ * 1     | +/- 1.3 Ga  | 1090 (Default)
+ * 2     | +/- 1.9 Ga  | 820
+ * 3     | +/- 2.5 Ga  | 660
+ * 4     | +/- 4.0 Ga  | 440
+ * 5     | +/- 4.7 Ga  | 390
+ * 6     | +/- 5.6 Ga  | 330
+ * 7     | +/- 8.1 Ga  | 230
+ *
+ * @return Current magnetic field gain value
+ * @see HMC5883L_GAIN_1090
+ * @see HMC5883L_RA_CONFIG_B
+ * @see HMC5883L_CRB_GAIN_BIT
+ * @see HMC5883L_CRB_GAIN_LENGTH
+ */
+uint8_t HMC5883L_getGain() {
+    I2Cdev_readBits(devAddr, HMC5883L_RA_CONFIG_B, HMC5883L_CRB_GAIN_BIT, HMC5883L_CRB_GAIN_LENGTH, buffer);
+    return buffer[0];
+}
+/** Set magnetic field gain value.
+ * @param gain New magnetic field gain value
+ * @see getGain()
+ * @see HMC5883L_RA_CONFIG_B
+ * @see HMC5883L_CRB_GAIN_BIT
+ * @see HMC5883L_CRB_GAIN_LENGTH
+ */
+void HMC5883L_setGain(uint8_t gain) {
+    // use this method to guarantee that bits 4-0 are set to zero, which is a
+    // requirement specified in the datasheet; it's actually more efficient than
+    // using the I2Cdev.writeBits method
+    I2Cdev_writeByte(devAddr, HMC5883L_RA_CONFIG_B, gain << (HMC5883L_CRB_GAIN_BIT - HMC5883L_CRB_GAIN_LENGTH + 1));
+}
+
+// MODE register
+
+/** Get measurement mode.
+ * In continuous-measurement mode, the device continuously performs measurements
+ * and places the result in the data register. RDY goes high when new data is
+ * placed in all three registers. After a power-on or a write to the mode or
+ * configuration register, the first measurement set is available from all three
+ * data output registers after a period of 2/fDO and subsequent measurements are
+ * available at a frequency of fDO, where fDO is the frequency of data output.
+ *
+ * When single-measurement mode (default) is selected, device performs a single
+ * measurement, sets RDY high and returned to idle mode. Mode register returns
+ * to idle mode bit values. The measurement remains in the data output register
+ * and RDY remains high until the data output register is read or another
+ * measurement is performed.
+ *
+ * @return Current measurement mode
+ * @see HMC5883L_MODE_CONTINUOUS
+ * @see HMC5883L_MODE_SINGLE
+ * @see HMC5883L_MODE_IDLE
+ * @see HMC5883L_RA_MODE
+ * @see HMC5883L_MODEREG_BIT
+ * @see HMC5883L_MODEREG_LENGTH
+ */
+uint8_t HMC5883L_getMode() {
+    I2Cdev_readBits(devAddr, HMC5883L_RA_MODE, HMC5883L_MODEREG_BIT, HMC5883L_MODEREG_LENGTH, buffer);
+    return buffer[0];
+}
+/** Set measurement mode.
+ * @param newMode New measurement mode
+ * @see getMode()
+ * @see HMC5883L_MODE_CONTINUOUS
+ * @see HMC5883L_MODE_SINGLE
+ * @see HMC5883L_MODE_IDLE
+ * @see HMC5883L_RA_MODE
+ * @see HMC5883L_MODEREG_BIT
+ * @see HMC5883L_MODEREG_LENGTH
+ */
+void HMC5883L_setMode(uint8_t newMode) {
+    // use this method to guarantee that bits 7-2 are set to zero, which is a
+    // requirement specified in the datasheet; it's actually more efficient than
+    // using the I2Cdev.writeBits method
+    I2Cdev_writeByte(devAddr, HMC5883L_RA_MODE, newMode << (HMC5883L_MODEREG_BIT - HMC5883L_MODEREG_LENGTH + 1));
+    mode = newMode; // track to tell if we have to clear bit 7 after a read
+}
+
+// DATA* registers
+
+/** Get 3-axis heading measurements.
+ * In the event the ADC reading overflows or underflows for the given channel,
+ * or if there is a math overflow during the bias measurement, this data
+ * register will contain the value -4096. This register value will clear when
+ * after the next valid measurement is made. Note that this method automatically
+ * clears the appropriate bit in the MODE register if Single mode is active.
+ * @param x 16-bit signed integer container for X-axis heading
+ * @param y 16-bit signed integer container for Y-axis heading
+ * @param z 16-bit signed integer container for Z-axis heading
+ * @see HMC5883L_RA_DATAX_H
+ */
+void HMC5883L_getHeading(int16_t *x, int16_t *y, int16_t *z) {
+    I2Cdev_readBytes(devAddr, HMC5883L_RA_DATAX_H, 6, buffer);
+    if (mode == HMC5883L_MODE_SINGLE) I2Cdev_writeByte(devAddr, HMC5883L_RA_MODE, HMC5883L_MODE_SINGLE << (HMC5883L_MODEREG_BIT - HMC5883L_MODEREG_LENGTH + 1));
+    *x = (((int16_t)buffer[0]) << 8) | buffer[1];
+    *y = (((int16_t)buffer[4]) << 8) | buffer[5];
+    *z = (((int16_t)buffer[2]) << 8) | buffer[3];
+}
+/** Get X-axis heading measurement.
+ * @return 16-bit signed integer with X-axis heading
+ * @see HMC5883L_RA_DATAX_H
+ */
+int16_t HMC5883L_getHeadingX() {
+    // each axis read requires that ALL axis registers be read, even if only
+    // one is used; this was not done ineffiently in the code by accident
+    I2Cdev_readBytes(devAddr, HMC5883L_RA_DATAX_H, 6, buffer);
+    if (mode == HMC5883L_MODE_SINGLE) I2Cdev_writeByte(devAddr, HMC5883L_RA_MODE, HMC5883L_MODE_SINGLE << (HMC5883L_MODEREG_BIT - HMC5883L_MODEREG_LENGTH + 1));
+    return (((int16_t)buffer[0]) << 8) | buffer[1];
+}
+/** Get Y-axis heading measurement.
+ * @return 16-bit signed integer with Y-axis heading
+ * @see HMC5883L_RA_DATAY_H
+ */
+int16_t HMC5883L_getHeadingY() {
+    // each axis read requires that ALL axis registers be read, even if only
+    // one is used; this was not done ineffiently in the code by accident
+    I2Cdev_readBytes(devAddr, HMC5883L_RA_DATAX_H, 6, buffer);
+    if (mode == HMC5883L_MODE_SINGLE) I2Cdev_writeByte(devAddr, HMC5883L_RA_MODE, HMC5883L_MODE_SINGLE << (HMC5883L_MODEREG_BIT - HMC5883L_MODEREG_LENGTH + 1));
+    return (((int16_t)buffer[4]) << 8) | buffer[5];
+}
+/** Get Z-axis heading measurement.
+ * @return 16-bit signed integer with Z-axis heading
+ * @see HMC5883L_RA_DATAZ_H
+ */
+int16_t HMC5883L_getHeadingZ() {
+    // each axis read requires that ALL axis registers be read, even if only
+    // one is used; this was not done ineffiently in the code by accident
+    I2Cdev_readBytes(devAddr, HMC5883L_RA_DATAX_H, 6, buffer);
+    if (mode == HMC5883L_MODE_SINGLE) I2Cdev_writeByte(devAddr, HMC5883L_RA_MODE, HMC5883L_MODE_SINGLE << (HMC5883L_MODEREG_BIT - HMC5883L_MODEREG_LENGTH + 1));
+    return (((int16_t)buffer[2]) << 8) | buffer[3];
+}
+
+// STATUS register
+
+/** Get data output register lock status.
+ * This bit is set when this some but not all for of the six data output
+ * registers have been read. When this bit is set, the six data output registers
+ * are locked and any new data will not be placed in these register until one of
+ * three conditions are met: one, all six bytes have been read or the mode
+ * changed, two, the mode is changed, or three, the measurement configuration is
+ * changed.
+ * @return Data output register lock status
+ * @see HMC5883L_RA_STATUS
+ * @see HMC5883L_STATUS_LOCK_BIT
+ */
+bool HMC5883L_getLockStatus() {
+    I2Cdev_readBit(devAddr, HMC5883L_RA_STATUS, HMC5883L_STATUS_LOCK_BIT, buffer);
+    return buffer[0];
+}
+/** Get data ready status.
+ * This bit is set when data is written to all six data registers, and cleared
+ * when the device initiates a write to the data output registers and after one
+ * or more of the data output registers are written to. When RDY bit is clear it
+ * shall remain cleared for 250 us. DRDY pin can be used as an alternative to
+ * the status register for monitoring the device for measurement data.
+ * @return Data ready status
+ * @see HMC5883L_RA_STATUS
+ * @see HMC5883L_STATUS_READY_BIT
+ */
+bool HMC5883L_getReadyStatus() {
+    I2Cdev_readBit(devAddr, HMC5883L_RA_STATUS, HMC5883L_STATUS_READY_BIT, buffer);
+    return buffer[0];
+}
+
+// ID_* registers
+
+/** Get identification byte A
+ * @return ID_A byte (should be 01001000, ASCII value 'H')
+ */
+uint8_t HMC5883L_getIDA() {
+    I2Cdev_readByte(devAddr, HMC5883L_RA_ID_A, buffer);
+    return buffer[0];
+}
+/** Get identification byte B
+ * @return ID_A byte (should be 00110100, ASCII value '4')
+ */
+uint8_t HMC5883L_getIDB() {
+    I2Cdev_readByte(devAddr, HMC5883L_RA_ID_B, buffer);
+    return buffer[0];
+}
+/** Get identification byte C
+ * @return ID_A byte (should be 00110011, ASCII value '3')
+ */
+uint8_t HMC5883L_getIDC() {
+    I2Cdev_readByte(devAddr, HMC5883L_RA_ID_C, buffer);
+    return buffer[0];
+}
diff --git a/STM32/HMC5883/HMC5883L.h b/STM32/HMC5883/HMC5883L.h
new file mode 100644
index 00000000..ae7f955a
--- /dev/null
+++ b/STM32/HMC5883/HMC5883L.h
@@ -0,0 +1,142 @@
+// I2Cdev library collection - HMC5883L I2C device class header file
+// Based on Honeywell HMC5883L datasheet, 10/2010 (Form #900405 Rev B)
+// 6/12/2012 by Jeff Rowberg 
+// 6/6/2015 by Andrey Voloshin 
+// 03/28/2017 by Kamnev Yuriy 
+//
+// Changelog:
+//     2017-03-28 - ported to STM32 using Keil MDK Pack
+//     2015-06-06 - ported to STM32 HAL library from Arduino code
+//     2012-06-12 - fixed swapped Y/Z axes
+//     2011-08-22 - small Doxygen comment fixes
+//     2011-07-31 - initial release
+
+/* ============================================
+I2Cdev device library code is placed under the MIT license
+Copyright (c) 2011 Jeff Rowberg
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+===============================================
+*/
+
+#ifndef _HMC5883L_H_
+#define _HMC5883L_H_
+
+#include "I2Cdev.h"
+#include 
+
+#define HMC5883L_ADDRESS            0x1E // this device only has one address
+#define HMC5883L_DEFAULT_ADDRESS    0x1E
+
+#define HMC5883L_RA_CONFIG_A        0x00
+#define HMC5883L_RA_CONFIG_B        0x01
+#define HMC5883L_RA_MODE            0x02
+#define HMC5883L_RA_DATAX_H         0x03
+#define HMC5883L_RA_DATAX_L         0x04
+#define HMC5883L_RA_DATAZ_H         0x05
+#define HMC5883L_RA_DATAZ_L         0x06
+#define HMC5883L_RA_DATAY_H         0x07
+#define HMC5883L_RA_DATAY_L         0x08
+#define HMC5883L_RA_STATUS          0x09
+#define HMC5883L_RA_ID_A            0x0A
+#define HMC5883L_RA_ID_B            0x0B
+#define HMC5883L_RA_ID_C            0x0C
+
+#define HMC5883L_CRA_AVERAGE_BIT    6
+#define HMC5883L_CRA_AVERAGE_LENGTH 2
+#define HMC5883L_CRA_RATE_BIT       4
+#define HMC5883L_CRA_RATE_LENGTH    3
+#define HMC5883L_CRA_BIAS_BIT       1
+#define HMC5883L_CRA_BIAS_LENGTH    2
+
+#define HMC5883L_AVERAGING_1        0x00
+#define HMC5883L_AVERAGING_2        0x01
+#define HMC5883L_AVERAGING_4        0x02
+#define HMC5883L_AVERAGING_8        0x03
+
+#define HMC5883L_RATE_0P75          0x00
+#define HMC5883L_RATE_1P5           0x01
+#define HMC5883L_RATE_3             0x02
+#define HMC5883L_RATE_7P5           0x03
+#define HMC5883L_RATE_15            0x04
+#define HMC5883L_RATE_30            0x05
+#define HMC5883L_RATE_75            0x06
+
+#define HMC5883L_BIAS_NORMAL        0x00
+#define HMC5883L_BIAS_POSITIVE      0x01
+#define HMC5883L_BIAS_NEGATIVE      0x02
+
+#define HMC5883L_CRB_GAIN_BIT       7
+#define HMC5883L_CRB_GAIN_LENGTH    3
+
+#define HMC5883L_GAIN_1370          0x00
+#define HMC5883L_GAIN_1090          0x01
+#define HMC5883L_GAIN_820           0x02
+#define HMC5883L_GAIN_660           0x03
+#define HMC5883L_GAIN_440           0x04
+#define HMC5883L_GAIN_390           0x05
+#define HMC5883L_GAIN_330           0x06
+#define HMC5883L_GAIN_220           0x07
+
+#define HMC5883L_MODEREG_BIT        1
+#define HMC5883L_MODEREG_LENGTH     2
+
+#define HMC5883L_MODE_CONTINUOUS    0x00
+#define HMC5883L_MODE_SINGLE        0x01
+#define HMC5883L_MODE_IDLE          0x02
+
+#define HMC5883L_STATUS_LOCK_BIT    1
+#define HMC5883L_STATUS_READY_BIT   0
+
+void HMC5883L_initialize();
+bool HMC5883L_testConnection();
+
+// CONFIG_A register
+uint8_t HMC5883L_getSampleAveraging();
+void HMC5883L_setSampleAveraging(uint8_t averaging);
+uint8_t HMC5883L_getDataRate();
+void HMC5883L_setDataRate(uint8_t rate);
+uint8_t HMC5883L_getMeasurementBias();
+void HMC5883L_setMeasurementBias(uint8_t bias);
+
+// CONFIG_B register
+uint8_t HMC5883L_getGain();
+void HMC5883L_setGain(uint8_t gain);
+
+// MODE register
+uint8_t HMC5883L_getMode();
+void HMC5883L_setMode(uint8_t mode);
+
+// DATA* registers
+void HMC5883L_getHeading(int16_t *x, int16_t *y, int16_t *z);
+int16_t HMC5883L_getHeadingX();
+int16_t HMC5883L_getHeadingY();
+int16_t HMC5883L_getHeadingZ();
+
+// STATUS register
+bool HMC5883L_getLockStatus();
+bool HMC5883L_getReadyStatus();
+
+// ID_* registers
+uint8_t HMC5883L_getIDA();
+uint8_t HMC5883L_getIDB();
+uint8_t HMC5883L_getIDC();
+
+
+#endif /* _HMC5883L_H_ */
diff --git a/STM32/I2Cdev.c b/STM32/I2Cdev.c
new file mode 100644
index 00000000..5940d2e7
--- /dev/null
+++ b/STM32/I2Cdev.c
@@ -0,0 +1,294 @@
+// I2Cdev library collection - Main I2C device class header file
+// Abstracts bit and byte I2C R/W functions into a convenient class
+// 6/9/2012 by Jeff Rowberg 
+// 03/28/2017 by Kamnev Yuriy 
+//
+// Changelog:
+//     2017-03-28 - ported to STM32 using Keil MDK Pack
+
+/* ============================================
+I2Cdev device library code is placed under the MIT license
+Copyright (c) 2013 Jeff Rowberg
+Copyright (c) 2017 Kamnev Yuriy
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+===============================================
+*/
+
+
+#include "I2Cdev.h"
+#include 
+
+#include 
+
+extern ARM_DRIVER_I2C I2CDev_Driver;
+
+
+#define _i2c_transmit(dev_addr, data, len, pending) \
+	I2CDev_Driver.MasterTransmit(dev_addr, data, len, pending);\
+	while(I2CDev_Driver.GetStatus().busy)
+
+
+#define _i2c_receive(dev_addr, data, len, pending) \
+	I2CDev_Driver.MasterReceive(dev_addr, data, len, pending); \
+	while(I2CDev_Driver.GetStatus().busy)
+
+
+#define i2c_transmit_ack(dev_addr, data, len) 	_i2c_transmit(dev_addr, data, len, true)
+#define i2c_transmit_nack(dev_addr, data, len) 	_i2c_transmit(dev_addr, data, len, false)
+
+#define i2c_receive_ack(dev_addr, data, len)	_i2c_receive(dev_addr, data, len, true)
+#define i2c_receive_nack(dev_addr, data, len)	_i2c_receive(dev_addr, data, len, false)
+
+
+
+int8_t I2Cdev_readBytes(uint8_t dev_addr, uint8_t reg_addr, uint8_t len, uint8_t *data) {
+	int8_t err = 0;
+	uint8_t reg_data[1] = {reg_addr};
+
+	err = i2c_transmit_ack(dev_addr, reg_data, 1);
+
+	if(err < 0) {
+		return err;
+	}
+
+	err = i2c_receive_nack(dev_addr, data, len);
+
+	return err;
+}
+
+
+int8_t 	I2Cdev_readByte(uint8_t dev_addr, uint8_t reg_addr, uint8_t *data) {
+	int8_t err;
+
+	err = I2Cdev_readBytes(dev_addr, reg_addr, 1, data);
+	return err;
+}
+
+
+int8_t 	I2Cdev_readWords(uint8_t dev_addr, uint8_t reg_addr, uint8_t len, uint16_t *data) {
+	int8_t err;
+
+	uint16_t bytes_num = len*2;
+
+	uint8_t reg_info[1] = {reg_addr};
+	err = i2c_transmit_ack(dev_addr, reg_info, 1);
+
+	if(err < 0) {
+		return err;
+	}
+
+	uint8_t words_in_bytes[bytes_num];
+	err = i2c_receive_nack(dev_addr, words_in_bytes, bytes_num);
+
+	if(err < 0) {
+		return err;
+	}
+
+	uint8_t words_cnt = 0;
+	for(uint16_t i=0; i> bitn) & 0x01;
+
+	return err;
+}
+
+
+int8_t
+I2Cdev_readBits(uint8_t dev_addr, uint8_t reg_addr, uint8_t start_bit,
+		uint8_t len, uint8_t *data)
+{
+	int8_t err;
+
+	uint8_t b;
+	if ((err = I2Cdev_readByte(dev_addr, reg_addr, &b)) == 0) {
+		uint8_t mask = ((1 << len) - 1) << (start_bit - len + 1);
+		b &= mask;
+		b >>= (start_bit - len + 1);
+		*data = b;
+	}
+
+	return err;
+}
+
+
+int8_t 	I2Cdev_readBitW(uint8_t dev_addr, uint8_t reg_addr, uint8_t bit_n, uint16_t *data) {
+	int8_t err;
+
+	err = I2Cdev_readWord(dev_addr, reg_addr, data);
+	*data = (*data >> bit_n) & 0x01;
+
+	return err;
+}
+
+
+int8_t
+I2Cdev_readBitsW(uint8_t dev_addr, uint8_t reg_addr, uint8_t start_bit,
+		uint8_t len, uint16_t *data)
+{
+    int8_t err;
+    uint16_t w;
+
+    if ((err = I2Cdev_readWord(dev_addr, reg_addr, &w)) == 0) {
+        uint16_t mask = ((1 << len) - 1) << (start_bit - len + 1);
+        w &= mask;
+        w >>= (start_bit - len + 1);
+        *data = w;
+    }
+
+    return err;
+}
+
+
+int8_t 	I2Cdev_writeBytes(uint8_t dev_addr, uint8_t reg_addr, uint8_t len, uint8_t *data) {
+	int8_t err;
+	uint8_t ts_data[len+1];
+
+	ts_data[0] = reg_addr;
+	memcpy(ts_data+1, data, len);
+
+	err = i2c_transmit_nack(dev_addr, ts_data, len+1);
+
+	return err;
+}
+
+
+int8_t 	I2Cdev_writeByte(uint8_t dev_addr, uint8_t reg_addr, uint8_t data) {
+	int8_t err;
+
+	uint8_t ts_data[2] = {reg_addr, data};
+	err = i2c_transmit_nack(dev_addr, ts_data, 2);
+
+	return err;
+}
+
+
+int8_t 	I2Cdev_writeWord(uint8_t dev_addr, uint8_t reg_addr, uint16_t data) {
+	int8_t err;
+	uint8_t ts_data[3] = {reg_addr, (data >> 8) & 0xFF, data & 0xFF};
+
+	err = i2c_transmit_nack(reg_addr, ts_data, 3);
+	return err;
+}
+
+
+int8_t 	I2Cdev_writeWords(uint8_t dev_addr, uint8_t reg_addr, uint8_t len, uint16_t *data) {
+	uint16_t bytes_num = len*2+1;
+	uint8_t bytes[bytes_num];
+
+	bytes[0] = reg_addr;
+
+	uint16_t bytes_pos = 1;
+	for(uint8_t i=0; i> 8) & 0xFF;
+		bytes[bytes_pos+1] = data[i] & 0xFF;
+
+		bytes_pos += 2;
+	}
+
+	return i2c_transmit_nack(dev_addr, bytes, bytes_num);
+}
+
+
+int8_t 	I2Cdev_writeBit(uint8_t dev_addr, uint8_t reg_addr, uint8_t bit_n, uint8_t data) {
+	uint8_t b;
+	int8_t err;
+
+	err = I2Cdev_readByte(dev_addr, reg_addr, &b);
+	if(err < 0) {
+		return err;
+	}
+
+	b = (data != 0) ? (b | (1<
+// 03/28/2017 by Kamnev Yuriy 
+//
+// Changelog:
+//     2017-03-28 - ported to STM32 peripheral library from Arduino code
+
+/* ============================================
+I2Cdev device library code is placed under the MIT license
+Copyright (c) 2013 Jeff Rowberg
+Copyright (c) 2017 Kamnev Yuriy
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+===============================================
+*/
+
+
+#ifndef SRC_I2CDEVLIB_I2CDEV_H_
+#define SRC_I2CDEVLIB_I2CDEV_H_
+
+#include 
+
+#define I2CDev_Driver	Driver_I2C2
+
+
+int8_t 	I2Cdev_readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data);
+int8_t 	I2Cdev_readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data);
+int8_t 	I2Cdev_readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data);
+int8_t 	I2Cdev_readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t *data);
+int8_t 	I2Cdev_readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data);
+int8_t 	I2Cdev_readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data);
+int8_t 	I2Cdev_readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data);
+int8_t 	I2Cdev_readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data);
+
+int8_t 	I2Cdev_writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t data);
+int8_t 	I2Cdev_writeBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t data);
+int8_t 	I2Cdev_writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data);
+int8_t 	I2Cdev_writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t data);
+int8_t 	I2Cdev_writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data);
+int8_t 	I2Cdev_writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data);
+int8_t 	I2Cdev_writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data);
+int8_t 	I2Cdev_writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data);
+
+
+#endif /* SRC_I2CDEVLIB_I2CDEV_H_ */
diff --git a/STM32/MPU6050/MPU6050.c b/STM32/MPU6050/MPU6050.c
new file mode 100644
index 00000000..524e3ff8
--- /dev/null
+++ b/STM32/MPU6050/MPU6050.c
@@ -0,0 +1,3143 @@
+// I2Cdev library collection - MPU6050 I2C device class
+// Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00)
+// 8/24/2011 by Jeff Rowberg 
+// 11/28/2014 by Marton Sebok 
+//
+// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
+//
+// Changelog:
+//     ...        - ongoing debug release
+//     2014-11-28 - ported to PIC18 peripheral library from Arduino code
+//     2017-03-28 - tested basic function on STM32
+
+// NOTE: THIS IS ONLY A PARIAL RELEASE. THIS DEVICE CLASS IS CURRENTLY UNDERGOING ACTIVE
+// DEVELOPMENT AND IS STILL MISSING SOME IMPORTANT FEATURES. PLEASE KEEP THIS IN MIND IF
+// YOU DECIDE TO USE THIS PARTICULAR CODE FOR ANYTHING.
+
+/* ============================================
+I2Cdev device library code is placed under the MIT license
+Copyright (c) 2012 Jeff Rowberg
+Copyright (c) 2014 Marton Sebok
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+===============================================
+*/
+
+#include "MPU6050.h"
+
+
+MPU6050_t mpu6050;
+
+/** Specific address constructor.
+ * @param address I2C address
+ * @see MPU6050_DEFAULT_ADDRESS
+ * @see MPU6050_ADDRESS_AD0_LOW
+ * @see MPU6050_ADDRESS_AD0_HIGH
+ */
+void MPU6050(uint8_t address) {
+    mpu6050.devAddr = address;
+}
+
+/** Power on and prepare for general usage.
+ * This will activate the device and take it out of sleep mode (which must be done
+ * after start-up). This function also sets both the accelerometer and the gyroscope
+ * to their most sensitive settings, namely +/- 2g and +/- 250 degrees/sec, and sets
+ * the clock source to use the X Gyro for reference, which is slightly better than
+ * the default internal clock source.
+ */
+void MPU6050_initialize() {
+    MPU6050_setClockSource(MPU6050_CLOCK_PLL_XGYRO);
+    MPU6050_setFullScaleGyroRange(MPU6050_GYRO_FS_250);
+    MPU6050_setFullScaleAccelRange(MPU6050_ACCEL_FS_2);
+    MPU6050_setSleepEnabled(false); // thanks to Jack Elston for pointing this one out!
+}
+
+/** Verify the I2C connection.
+ * Make sure the device is connected and responds as expected.
+ * @return True if connection is valid, false otherwise
+ */
+bool MPU6050_testConnection() {
+    return MPU6050_getDeviceID() == 0x34;
+}
+
+// AUX_VDDIO register (InvenSense demo code calls this RA_*G_OFFS_TC)
+
+/** Get the auxiliary I2C supply voltage level.
+ * When set to 1, the auxiliary I2C bus high logic level is VDD. When cleared to
+ * 0, the auxiliary I2C bus high logic level is VLOGIC. This does not apply to
+ * the MPU-6000, which does not have a VLOGIC pin.
+ * @return I2C supply voltage level (0=VLOGIC, 1=VDD)
+ */
+uint8_t MPU6050_getAuxVDDIOLevel() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_PWR_MODE_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+/** Set the auxiliary I2C supply voltage level.
+ * When set to 1, the auxiliary I2C bus high logic level is VDD. When cleared to
+ * 0, the auxiliary I2C bus high logic level is VLOGIC. This does not apply to
+ * the MPU-6000, which does not have a VLOGIC pin.
+ * @param level I2C supply voltage level (0=VLOGIC, 1=VDD)
+ */
+void MPU6050_setAuxVDDIOLevel(uint8_t level) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_PWR_MODE_BIT, level);
+}
+
+// SMPLRT_DIV register
+
+/** Get gyroscope output rate divider.
+ * The sensor register output, FIFO output, DMP sampling, Motion detection, Zero
+ * Motion detection, and Free Fall detection are all based on the Sample Rate.
+ * The Sample Rate is generated by dividing the gyroscope output rate by
+ * SMPLRT_DIV:
+ *
+ * Sample Rate = Gyroscope Output Rate / (1 + SMPLRT_DIV)
+ *
+ * where Gyroscope Output Rate = 8kHz when the DLPF is disabled (DLPF_CFG = 0 or
+ * 7), and 1kHz when the DLPF is enabled (see Register 26).
+ *
+ * Note: The accelerometer output rate is 1kHz. This means that for a Sample
+ * Rate greater than 1kHz, the same accelerometer sample may be output to the
+ * FIFO, DMP, and sensor registers more than once.
+ *
+ * For a diagram of the gyroscope and accelerometer signal paths, see Section 8
+ * of the MPU-6000/MPU-6050 Product Specification document.
+ *
+ * @return Current sample rate
+ * @see MPU6050_RA_SMPLRT_DIV
+ */
+uint8_t MPU6050_getRate() {
+    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_SMPLRT_DIV, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+/** Set gyroscope sample rate divider.
+ * @param rate New sample rate divider
+ * @see getRate()
+ * @see MPU6050_RA_SMPLRT_DIV
+ */
+void MPU6050_setRate(uint8_t rate) {
+    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_SMPLRT_DIV, rate);
+}
+
+// CONFIG register
+
+/** Get external FSYNC configuration.
+ * Configures the external Frame Synchronization (FSYNC) pin sampling. An
+ * external signal connected to the FSYNC pin can be sampled by configuring
+ * EXT_SYNC_SET. Signal changes to the FSYNC pin are latched so that short
+ * strobes may be captured. The latched FSYNC signal will be sampled at the
+ * Sampling Rate, as defined in register 25. After sampling, the latch will
+ * reset to the current FSYNC signal state.
+ *
+ * The sampled value will be reported in place of the least significant bit in
+ * a sensor data register determined by the value of EXT_SYNC_SET according to
+ * the following table.
+ *
+ * 
+ * EXT_SYNC_SET | FSYNC Bit Location
+ * -------------+-------------------
+ * 0            | Input disabled
+ * 1            | TEMP_OUT_L[0]
+ * 2            | GYRO_XOUT_L[0]
+ * 3            | GYRO_YOUT_L[0]
+ * 4            | GYRO_ZOUT_L[0]
+ * 5            | ACCEL_XOUT_L[0]
+ * 6            | ACCEL_YOUT_L[0]
+ * 7            | ACCEL_ZOUT_L[0]
+ * 
+ * + * @return FSYNC configuration value + */ +uint8_t MPU6050_getExternalFrameSync() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_EXT_SYNC_SET_BIT, MPU6050_CFG_EXT_SYNC_SET_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set external FSYNC configuration. + * @see getExternalFrameSync() + * @see MPU6050_RA_CONFIG + * @param sync New FSYNC configuration value + */ +void MPU6050_setExternalFrameSync(uint8_t sync) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_EXT_SYNC_SET_BIT, MPU6050_CFG_EXT_SYNC_SET_LENGTH, sync); +} +/** Get digital low-pass filter configuration. + * The DLPF_CFG parameter sets the digital low pass filter configuration. It + * also determines the internal sampling rate used by the device as shown in + * the table below. + * + * Note: The accelerometer output rate is 1kHz. This means that for a Sample + * Rate greater than 1kHz, the same accelerometer sample may be output to the + * FIFO, DMP, and sensor registers more than once. + * + *
+ *          |   ACCELEROMETER    |           GYROSCOPE
+ * DLPF_CFG | Bandwidth | Delay  | Bandwidth | Delay  | Sample Rate
+ * ---------+-----------+--------+-----------+--------+-------------
+ * 0        | 260Hz     | 0ms    | 256Hz     | 0.98ms | 8kHz
+ * 1        | 184Hz     | 2.0ms  | 188Hz     | 1.9ms  | 1kHz
+ * 2        | 94Hz      | 3.0ms  | 98Hz      | 2.8ms  | 1kHz
+ * 3        | 44Hz      | 4.9ms  | 42Hz      | 4.8ms  | 1kHz
+ * 4        | 21Hz      | 8.5ms  | 20Hz      | 8.3ms  | 1kHz
+ * 5        | 10Hz      | 13.8ms | 10Hz      | 13.4ms | 1kHz
+ * 6        | 5Hz       | 19.0ms | 5Hz       | 18.6ms | 1kHz
+ * 7        |   -- Reserved --   |   -- Reserved --   | Reserved
+ * 
+ * + * @return DLFP configuration + * @see MPU6050_RA_CONFIG + * @see MPU6050_CFG_DLPF_CFG_BIT + * @see MPU6050_CFG_DLPF_CFG_LENGTH + */ +uint8_t MPU6050_getDLPFMode() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_DLPF_CFG_BIT, MPU6050_CFG_DLPF_CFG_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set digital low-pass filter configuration. + * @param mode New DLFP configuration setting + * @see getDLPFBandwidth() + * @see MPU6050_DLPF_BW_256 + * @see MPU6050_RA_CONFIG + * @see MPU6050_CFG_DLPF_CFG_BIT + * @see MPU6050_CFG_DLPF_CFG_LENGTH + */ +void MPU6050_setDLPFMode(uint8_t mode) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_DLPF_CFG_BIT, MPU6050_CFG_DLPF_CFG_LENGTH, mode); +} + +// GYRO_CONFIG register + +/** Get full-scale gyroscope range. + * The FS_SEL parameter allows setting the full-scale range of the gyro sensors, + * as described in the table below. + * + *
+ * 0 = +/- 250 degrees/sec
+ * 1 = +/- 500 degrees/sec
+ * 2 = +/- 1000 degrees/sec
+ * 3 = +/- 2000 degrees/sec
+ * 
+ * + * @return Current full-scale gyroscope range setting + * @see MPU6050_GYRO_FS_250 + * @see MPU6050_RA_GYRO_CONFIG + * @see MPU6050_GCONFIG_FS_SEL_BIT + * @see MPU6050_GCONFIG_FS_SEL_LENGTH + */ +uint8_t MPU6050_getFullScaleGyroRange() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set full-scale gyroscope range. + * @param range New full-scale gyroscope range value + * @see getFullScaleRange() + * @see MPU6050_GYRO_FS_250 + * @see MPU6050_RA_GYRO_CONFIG + * @see MPU6050_GCONFIG_FS_SEL_BIT + * @see MPU6050_GCONFIG_FS_SEL_LENGTH + */ +void MPU6050_setFullScaleGyroRange(uint8_t range) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, range); +} + +// ACCEL_CONFIG register + +/** Get self-test enabled setting for accelerometer X axis. + * @return Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +bool MPU6050_getAccelXSelfTest() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_XA_ST_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get self-test enabled setting for accelerometer X axis. + * @param enabled Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050_setAccelXSelfTest(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_XA_ST_BIT, enabled); +} +/** Get self-test enabled value for accelerometer Y axis. + * @return Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +bool MPU6050_getAccelYSelfTest() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_YA_ST_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get self-test enabled value for accelerometer Y axis. + * @param enabled Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050_setAccelYSelfTest(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_YA_ST_BIT, enabled); +} +/** Get self-test enabled value for accelerometer Z axis. + * @return Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +bool MPU6050_getAccelZSelfTest() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ZA_ST_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set self-test enabled value for accelerometer Z axis. + * @param enabled Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050_setAccelZSelfTest(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ZA_ST_BIT, enabled); +} +/** Get full-scale accelerometer range. + * The FS_SEL parameter allows setting the full-scale range of the accelerometer + * sensors, as described in the table below. + * + *
+ * 0 = +/- 2g
+ * 1 = +/- 4g
+ * 2 = +/- 8g
+ * 3 = +/- 16g
+ * 
+ * + * @return Current full-scale accelerometer range setting + * @see MPU6050_ACCEL_FS_2 + * @see MPU6050_RA_ACCEL_CONFIG + * @see MPU6050_ACONFIG_AFS_SEL_BIT + * @see MPU6050_ACONFIG_AFS_SEL_LENGTH + */ +uint8_t MPU6050_getFullScaleAccelRange() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set full-scale accelerometer range. + * @param range New full-scale accelerometer range setting + * @see getFullScaleAccelRange() + */ +void MPU6050_setFullScaleAccelRange(uint8_t range) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, range); +} +/** Get the high-pass filter configuration. + * The DHPF is a filter module in the path leading to motion detectors (Free + * Fall, Motion threshold, and Zero Motion). The high pass filter output is not + * available to the data registers (see Figure in Section 8 of the MPU-6000/ + * MPU-6050 Product Specification document). + * + * The high pass filter has three modes: + * + *
+ *    Reset: The filter output settles to zero within one sample. This
+ *           effectively disables the high pass filter. This mode may be toggled
+ *           to quickly settle the filter.
+ *
+ *    On:    The high pass filter will pass signals above the cut off frequency.
+ *
+ *    Hold:  When triggered, the filter holds the present sample. The filter
+ *           output will be the difference between the input sample and the held
+ *           sample.
+ * 
+ * + *
+ * ACCEL_HPF | Filter Mode | Cut-off Frequency
+ * ----------+-------------+------------------
+ * 0         | Reset       | None
+ * 1         | On          | 5Hz
+ * 2         | On          | 2.5Hz
+ * 3         | On          | 1.25Hz
+ * 4         | On          | 0.63Hz
+ * 7         | Hold        | None
+ * 
+ * + * @return Current high-pass filter configuration + * @see MPU6050_DHPF_RESET + * @see MPU6050_RA_ACCEL_CONFIG + */ +uint8_t MPU6050_getDHPFMode() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ACCEL_HPF_BIT, MPU6050_ACONFIG_ACCEL_HPF_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set the high-pass filter configuration. + * @param bandwidth New high-pass filter configuration + * @see setDHPFMode() + * @see MPU6050_DHPF_RESET + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050_setDHPFMode(uint8_t bandwidth) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ACCEL_HPF_BIT, MPU6050_ACONFIG_ACCEL_HPF_LENGTH, bandwidth); +} + +// FF_THR register + +/** Get free-fall event acceleration threshold. + * This register configures the detection threshold for Free Fall event + * detection. The unit of FF_THR is 1LSB = 2mg. Free Fall is detected when the + * absolute value of the accelerometer measurements for the three axes are each + * less than the detection threshold. This condition increments the Free Fall + * duration counter (Register 30). The Free Fall interrupt is triggered when the + * Free Fall duration counter reaches the time specified in FF_DUR. + * + * For more details on the Free Fall detection interrupt, see Section 8.2 of the + * MPU-6000/MPU-6050 Product Specification document as well as Registers 56 and + * 58 of this document. + * + * @return Current free-fall acceleration threshold value (LSB = 2mg) + * @see MPU6050_RA_FF_THR + */ +uint8_t MPU6050_getFreefallDetectionThreshold() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_FF_THR, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get free-fall event acceleration threshold. + * @param threshold New free-fall acceleration threshold value (LSB = 2mg) + * @see getFreefallDetectionThreshold() + * @see MPU6050_RA_FF_THR + */ +void MPU6050_setFreefallDetectionThreshold(uint8_t threshold) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_FF_THR, threshold); +} + +// FF_DUR register + +/** Get free-fall event duration threshold. + * This register configures the duration counter threshold for Free Fall event + * detection. The duration counter ticks at 1kHz, therefore FF_DUR has a unit + * of 1 LSB = 1 ms. + * + * The Free Fall duration counter increments while the absolute value of the + * accelerometer measurements are each less than the detection threshold + * (Register 29). The Free Fall interrupt is triggered when the Free Fall + * duration counter reaches the time specified in this register. + * + * For more details on the Free Fall detection interrupt, see Section 8.2 of + * the MPU-6000/MPU-6050 Product Specification document as well as Registers 56 + * and 58 of this document. + * + * @return Current free-fall duration threshold value (LSB = 1ms) + * @see MPU6050_RA_FF_DUR + */ +uint8_t MPU6050_getFreefallDetectionDuration() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_FF_DUR, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get free-fall event duration threshold. + * @param duration New free-fall duration threshold value (LSB = 1ms) + * @see getFreefallDetectionDuration() + * @see MPU6050_RA_FF_DUR + */ +void MPU6050_setFreefallDetectionDuration(uint8_t duration) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_FF_DUR, duration); +} + +// MOT_THR register + +/** Get motion detection event acceleration threshold. + * This register configures the detection threshold for Motion interrupt + * generation. The unit of MOT_THR is 1LSB = 2mg. Motion is detected when the + * absolute value of any of the accelerometer measurements exceeds this Motion + * detection threshold. This condition increments the Motion detection duration + * counter (Register 32). The Motion detection interrupt is triggered when the + * Motion Detection counter reaches the time count specified in MOT_DUR + * (Register 32). + * + * The Motion interrupt will indicate the axis and polarity of detected motion + * in MOT_DETECT_STATUS (Register 97). + * + * For more details on the Motion detection interrupt, see Section 8.3 of the + * MPU-6000/MPU-6050 Product Specification document as well as Registers 56 and + * 58 of this document. + * + * @return Current motion detection acceleration threshold value (LSB = 2mg) + * @see MPU6050_RA_MOT_THR + */ +uint8_t MPU6050_getMotionDetectionThreshold() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_MOT_THR, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set free-fall event acceleration threshold. + * @param threshold New motion detection acceleration threshold value (LSB = 2mg) + * @see getMotionDetectionThreshold() + * @see MPU6050_RA_MOT_THR + */ +void MPU6050_setMotionDetectionThreshold(uint8_t threshold) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_MOT_THR, threshold); +} + +// MOT_DUR register + +/** Get motion detection event duration threshold. + * This register configures the duration counter threshold for Motion interrupt + * generation. The duration counter ticks at 1 kHz, therefore MOT_DUR has a unit + * of 1LSB = 1ms. The Motion detection duration counter increments when the + * absolute value of any of the accelerometer measurements exceeds the Motion + * detection threshold (Register 31). The Motion detection interrupt is + * triggered when the Motion detection counter reaches the time count specified + * in this register. + * + * For more details on the Motion detection interrupt, see Section 8.3 of the + * MPU-6000/MPU-6050 Product Specification document. + * + * @return Current motion detection duration threshold value (LSB = 1ms) + * @see MPU6050_RA_MOT_DUR + */ +uint8_t MPU6050_getMotionDetectionDuration() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_MOT_DUR, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set motion detection event duration threshold. + * @param duration New motion detection duration threshold value (LSB = 1ms) + * @see getMotionDetectionDuration() + * @see MPU6050_RA_MOT_DUR + */ +void MPU6050_setMotionDetectionDuration(uint8_t duration) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_MOT_DUR, duration); +} + +// ZRMOT_THR register + +/** Get zero motion detection event acceleration threshold. + * This register configures the detection threshold for Zero Motion interrupt + * generation. The unit of ZRMOT_THR is 1LSB = 2mg. Zero Motion is detected when + * the absolute value of the accelerometer measurements for the 3 axes are each + * less than the detection threshold. This condition increments the Zero Motion + * duration counter (Register 34). The Zero Motion interrupt is triggered when + * the Zero Motion duration counter reaches the time count specified in + * ZRMOT_DUR (Register 34). + * + * Unlike Free Fall or Motion detection, Zero Motion detection triggers an + * interrupt both when Zero Motion is first detected and when Zero Motion is no + * longer detected. + * + * When a zero motion event is detected, a Zero Motion Status will be indicated + * in the MOT_DETECT_STATUS register (Register 97). When a motion-to-zero-motion + * condition is detected, the status bit is set to 1. When a zero-motion-to- + * motion condition is detected, the status bit is set to 0. + * + * For more details on the Zero Motion detection interrupt, see Section 8.4 of + * the MPU-6000/MPU-6050 Product Specification document as well as Registers 56 + * and 58 of this document. + * + * @return Current zero motion detection acceleration threshold value (LSB = 2mg) + * @see MPU6050_RA_ZRMOT_THR + */ +uint8_t MPU6050_getZeroMotionDetectionThreshold() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_ZRMOT_THR, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set zero motion detection event acceleration threshold. + * @param threshold New zero motion detection acceleration threshold value (LSB = 2mg) + * @see getZeroMotionDetectionThreshold() + * @see MPU6050_RA_ZRMOT_THR + */ +void MPU6050_setZeroMotionDetectionThreshold(uint8_t threshold) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_ZRMOT_THR, threshold); +} + +// ZRMOT_DUR register + +/** Get zero motion detection event duration threshold. + * This register configures the duration counter threshold for Zero Motion + * interrupt generation. The duration counter ticks at 16 Hz, therefore + * ZRMOT_DUR has a unit of 1 LSB = 64 ms. The Zero Motion duration counter + * increments while the absolute value of the accelerometer measurements are + * each less than the detection threshold (Register 33). The Zero Motion + * interrupt is triggered when the Zero Motion duration counter reaches the time + * count specified in this register. + * + * For more details on the Zero Motion detection interrupt, see Section 8.4 of + * the MPU-6000/MPU-6050 Product Specification document, as well as Registers 56 + * and 58 of this document. + * + * @return Current zero motion detection duration threshold value (LSB = 64ms) + * @see MPU6050_RA_ZRMOT_DUR + */ +uint8_t MPU6050_getZeroMotionDetectionDuration() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_ZRMOT_DUR, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set zero motion detection event duration threshold. + * @param duration New zero motion detection duration threshold value (LSB = 1ms) + * @see getZeroMotionDetectionDuration() + * @see MPU6050_RA_ZRMOT_DUR + */ +void MPU6050_setZeroMotionDetectionDuration(uint8_t duration) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_ZRMOT_DUR, duration); +} + +// FIFO_EN register + +/** Get temperature FIFO enabled value. + * When set to 1, this bit enables TEMP_OUT_H and TEMP_OUT_L (Registers 65 and + * 66) to be written into the FIFO mpu6050.buffer. + * @return Current temperature FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_getTempFIFOEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_TEMP_FIFO_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set temperature FIFO enabled value. + * @param enabled New temperature FIFO enabled value + * @see getTempFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setTempFIFOEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_TEMP_FIFO_EN_BIT, enabled); +} +/** Get gyroscope X-axis FIFO enabled value. + * When set to 1, this bit enables GYRO_XOUT_H and GYRO_XOUT_L (Registers 67 and + * 68) to be written into the FIFO mpu6050.buffer. + * @return Current gyroscope X-axis FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_getXGyroFIFOEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_XG_FIFO_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set gyroscope X-axis FIFO enabled value. + * @param enabled New gyroscope X-axis FIFO enabled value + * @see getXGyroFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setXGyroFIFOEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_XG_FIFO_EN_BIT, enabled); +} +/** Get gyroscope Y-axis FIFO enabled value. + * When set to 1, this bit enables GYRO_YOUT_H and GYRO_YOUT_L (Registers 69 and + * 70) to be written into the FIFO mpu6050.buffer. + * @return Current gyroscope Y-axis FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_getYGyroFIFOEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_YG_FIFO_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set gyroscope Y-axis FIFO enabled value. + * @param enabled New gyroscope Y-axis FIFO enabled value + * @see getYGyroFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setYGyroFIFOEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_YG_FIFO_EN_BIT, enabled); +} +/** Get gyroscope Z-axis FIFO enabled value. + * When set to 1, this bit enables GYRO_ZOUT_H and GYRO_ZOUT_L (Registers 71 and + * 72) to be written into the FIFO mpu6050.buffer. + * @return Current gyroscope Z-axis FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_getZGyroFIFOEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_ZG_FIFO_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set gyroscope Z-axis FIFO enabled value. + * @param enabled New gyroscope Z-axis FIFO enabled value + * @see getZGyroFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setZGyroFIFOEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_ZG_FIFO_EN_BIT, enabled); +} +/** Get accelerometer FIFO enabled value. + * When set to 1, this bit enables ACCEL_XOUT_H, ACCEL_XOUT_L, ACCEL_YOUT_H, + * ACCEL_YOUT_L, ACCEL_ZOUT_H, and ACCEL_ZOUT_L (Registers 59 to 64) to be + * written into the FIFO mpu6050.buffer. + * @return Current accelerometer FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_getAccelFIFOEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_ACCEL_FIFO_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set accelerometer FIFO enabled value. + * @param enabled New accelerometer FIFO enabled value + * @see getAccelFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setAccelFIFOEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_ACCEL_FIFO_EN_BIT, enabled); +} +/** Get Slave 2 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 2 to be written into the FIFO mpu6050.buffer. + * @return Current Slave 2 FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_getSlave2FIFOEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV2_FIFO_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Slave 2 FIFO enabled value. + * @param enabled New Slave 2 FIFO enabled value + * @see getSlave2FIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setSlave2FIFOEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV2_FIFO_EN_BIT, enabled); +} +/** Get Slave 1 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 1 to be written into the FIFO mpu6050.buffer. + * @return Current Slave 1 FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_getSlave1FIFOEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV1_FIFO_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Slave 1 FIFO enabled value. + * @param enabled New Slave 1 FIFO enabled value + * @see getSlave1FIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setSlave1FIFOEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV1_FIFO_EN_BIT, enabled); +} +/** Get Slave 0 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 0 to be written into the FIFO mpu6050.buffer. + * @return Current Slave 0 FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_getSlave0FIFOEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV0_FIFO_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Slave 0 FIFO enabled value. + * @param enabled New Slave 0 FIFO enabled value + * @see getSlave0FIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setSlave0FIFOEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV0_FIFO_EN_BIT, enabled); +} + +// I2C_MST_CTRL register + +/** Get multi-master enabled value. + * Multi-master capability allows multiple I2C masters to operate on the same + * bus. In circuits where multi-master capability is required, set MULT_MST_EN + * to 1. This will increase current drawn by approximately 30uA. + * + * In circuits where multi-master capability is required, the state of the I2C + * bus must always be monitored by each separate I2C Master. Before an I2C + * Master can assume arbitration of the bus, it must first confirm that no other + * I2C Master has arbitration of the bus. When MULT_MST_EN is set to 1, the + * MPU-60X0's bus arbitration detection logic is turned on, enabling it to + * detect when the bus is available. + * + * @return Current multi-master enabled value + * @see MPU6050_RA_I2C_MST_CTRL + */ +bool MPU6050_getMultiMasterEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_MULT_MST_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set multi-master enabled value. + * @param enabled New multi-master enabled value + * @see getMultiMasterEnabled() + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050_setMultiMasterEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_MULT_MST_EN_BIT, enabled); +} +/** Get wait-for-external-sensor-data enabled value. + * When the WAIT_FOR_ES bit is set to 1, the Data Ready interrupt will be + * delayed until External Sensor data from the Slave Devices are loaded into the + * EXT_SENS_DATA registers. This is used to ensure that both the internal sensor + * data (i.e. from gyro and accel) and external sensor data have been loaded to + * their respective data registers (i.e. the data is synced) when the Data Ready + * interrupt is triggered. + * + * @return Current wait-for-external-sensor-data enabled value + * @see MPU6050_RA_I2C_MST_CTRL + */ +bool MPU6050_getWaitForExternalSensorEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_WAIT_FOR_ES_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set wait-for-external-sensor-data enabled value. + * @param enabled New wait-for-external-sensor-data enabled value + * @see getWaitForExternalSensorEnabled() + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050_setWaitForExternalSensorEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_WAIT_FOR_ES_BIT, enabled); +} +/** Get Slave 3 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 3 to be written into the FIFO mpu6050.buffer. + * @return Current Slave 3 FIFO enabled value + * @see MPU6050_RA_MST_CTRL + */ +bool MPU6050_getSlave3FIFOEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_SLV_3_FIFO_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Slave 3 FIFO enabled value. + * @param enabled New Slave 3 FIFO enabled value + * @see getSlave3FIFOEnabled() + * @see MPU6050_RA_MST_CTRL + */ +void MPU6050_setSlave3FIFOEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_SLV_3_FIFO_EN_BIT, enabled); +} +/** Get slave read/write transition enabled value. + * The I2C_MST_P_NSR bit configures the I2C Master's transition from one slave + * read to the next slave read. If the bit equals 0, there will be a restart + * between reads. If the bit equals 1, there will be a stop followed by a start + * of the following read. When a write transaction follows a read transaction, + * the stop followed by a start of the successive write will be always used. + * + * @return Current slave read/write transition enabled value + * @see MPU6050_RA_I2C_MST_CTRL + */ +bool MPU6050_getSlaveReadWriteTransitionEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_P_NSR_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set slave read/write transition enabled value. + * @param enabled New slave read/write transition enabled value + * @see getSlaveReadWriteTransitionEnabled() + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050_setSlaveReadWriteTransitionEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_P_NSR_BIT, enabled); +} +/** Get I2C master clock speed. + * I2C_MST_CLK is a 4 bit unsigned value which configures a divider on the + * MPU-60X0 internal 8MHz clock. It sets the I2C master clock speed according to + * the following table: + * + *
+ * I2C_MST_CLK | I2C Master Clock Speed | 8MHz Clock Divider
+ * ------------+------------------------+-------------------
+ * 0           | 348kHz                 | 23
+ * 1           | 333kHz                 | 24
+ * 2           | 320kHz                 | 25
+ * 3           | 308kHz                 | 26
+ * 4           | 296kHz                 | 27
+ * 5           | 286kHz                 | 28
+ * 6           | 276kHz                 | 29
+ * 7           | 267kHz                 | 30
+ * 8           | 258kHz                 | 31
+ * 9           | 500kHz                 | 16
+ * 10          | 471kHz                 | 17
+ * 11          | 444kHz                 | 18
+ * 12          | 421kHz                 | 19
+ * 13          | 400kHz                 | 20
+ * 14          | 381kHz                 | 21
+ * 15          | 364kHz                 | 22
+ * 
+ * + * @return Current I2C master clock speed + * @see MPU6050_RA_I2C_MST_CTRL + */ +uint8_t MPU6050_getMasterClockSpeed() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_CLK_BIT, MPU6050_I2C_MST_CLK_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set I2C master clock speed. + * @reparam speed Current I2C master clock speed + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050_setMasterClockSpeed(uint8_t speed) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_CLK_BIT, MPU6050_I2C_MST_CLK_LENGTH, speed); +} + +// I2C_SLV* registers (Slave 0-3) + +/** Get the I2C address of the specified slave (0-3). + * Note that Bit 7 (MSB) controls read/write mode. If Bit 7 is set, it's a read + * operation, and if it is cleared, then it's a write operation. The remaining + * bits (6-0) are the 7-bit device address of the slave device. + * + * In read mode, the result of the read is placed in the lowest available + * EXT_SENS_DATA register. For further information regarding the allocation of + * read results, please refer to the EXT_SENS_DATA register description + * (Registers 73 - 96). + * + * The MPU-6050 supports a total of five slaves, but Slave 4 has unique + * characteristics, and so it has its own functions (getSlave4* and setSlave4*). + * + * I2C data transactions are performed at the Sample Rate, as defined in + * Register 25. The user is responsible for ensuring that I2C data transactions + * to and from each enabled Slave can be completed within a single period of the + * Sample Rate. + * + * The I2C slave access rate can be reduced relative to the Sample Rate. This + * reduced access rate is determined by I2C_MST_DLY (Register 52). Whether a + * slave's access rate is reduced relative to the Sample Rate is determined by + * I2C_MST_DELAY_CTRL (Register 103). + * + * The processing order for the slaves is fixed. The sequence followed for + * processing the slaves is Slave 0, Slave 1, Slave 2, Slave 3 and Slave 4. If a + * particular Slave is disabled it will be skipped. + * + * Each slave can either be accessed at the sample rate or at a reduced sample + * rate. In a case where some slaves are accessed at the Sample Rate and some + * slaves are accessed at the reduced rate, the sequence of accessing the slaves + * (Slave 0 to Slave 4) is still followed. However, the reduced rate slaves will + * be skipped if their access rate dictates that they should not be accessed + * during that particular cycle. For further information regarding the reduced + * access rate, please refer to Register 52. Whether a slave is accessed at the + * Sample Rate or at the reduced rate is determined by the Delay Enable bits in + * Register 103. + * + * @param num Slave number (0-3) + * @return Current address for specified slave + * @see MPU6050_RA_I2C_SLV0_ADDR + */ +uint8_t MPU6050_getSlaveAddress(uint8_t num) { + if (num > 3) return 0; + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_ADDR + num*3, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set the I2C address of the specified slave (0-3). + * @param num Slave number (0-3) + * @param address New address for specified slave + * @see getSlaveAddress() + * @see MPU6050_RA_I2C_SLV0_ADDR + */ +void MPU6050_setSlaveAddress(uint8_t num, uint8_t address) { + if (num > 3) return; + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_ADDR + num*3, address); +} +/** Get the active internal register for the specified slave (0-3). + * Read/write operations for this slave will be done to whatever internal + * register address is stored in this MPU register. + * + * The MPU-6050 supports a total of five slaves, but Slave 4 has unique + * characteristics, and so it has its own functions. + * + * @param num Slave number (0-3) + * @return Current active register for specified slave + * @see MPU6050_RA_I2C_SLV0_REG + */ +uint8_t MPU6050_getSlaveRegister(uint8_t num) { + if (num > 3) return 0; + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_REG + num*3, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set the active internal register for the specified slave (0-3). + * @param num Slave number (0-3) + * @param reg New active register for specified slave + * @see getSlaveRegister() + * @see MPU6050_RA_I2C_SLV0_REG + */ +void MPU6050_setSlaveRegister(uint8_t num, uint8_t reg) { + if (num > 3) return; + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_REG + num*3, reg); +} +/** Get the enabled value for the specified slave (0-3). + * When set to 1, this bit enables Slave 0 for data transfer operations. When + * cleared to 0, this bit disables Slave 0 from data transfer operations. + * @param num Slave number (0-3) + * @return Current enabled value for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +bool MPU6050_getSlaveEnabled(uint8_t num) { + if (num > 3) return 0; + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set the enabled value for the specified slave (0-3). + * @param num Slave number (0-3) + * @param enabled New enabled value for specified slave + * @see getSlaveEnabled() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050_setSlaveEnabled(uint8_t num, bool enabled) { + if (num > 3) return; + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_EN_BIT, enabled); +} +/** Get word pair byte-swapping enabled for the specified slave (0-3). + * When set to 1, this bit enables byte swapping. When byte swapping is enabled, + * the high and low bytes of a word pair are swapped. Please refer to + * I2C_SLV0_GRP for the pairing convention of the word pairs. When cleared to 0, + * bytes transferred to and from Slave 0 will be written to EXT_SENS_DATA + * registers in the order they were transferred. + * + * @param num Slave number (0-3) + * @return Current word pair byte-swapping enabled value for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +bool MPU6050_getSlaveWordByteSwap(uint8_t num) { + if (num > 3) return 0; + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_BYTE_SW_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set word pair byte-swapping enabled for the specified slave (0-3). + * @param num Slave number (0-3) + * @param enabled New word pair byte-swapping enabled value for specified slave + * @see getSlaveWordByteSwap() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050_setSlaveWordByteSwap(uint8_t num, bool enabled) { + if (num > 3) return; + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_BYTE_SW_BIT, enabled); +} +/** Get write mode for the specified slave (0-3). + * When set to 1, the transaction will read or write data only. When cleared to + * 0, the transaction will write a register address prior to reading or writing + * data. This should equal 0 when specifying the register address within the + * Slave device to/from which the ensuing data transaction will take place. + * + * @param num Slave number (0-3) + * @return Current write mode for specified slave (0 = register address + data, 1 = data only) + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +bool MPU6050_getSlaveWriteMode(uint8_t num) { + if (num > 3) return 0; + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_REG_DIS_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set write mode for the specified slave (0-3). + * @param num Slave number (0-3) + * @param mode New write mode for specified slave (0 = register address + data, 1 = data only) + * @see getSlaveWriteMode() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050_setSlaveWriteMode(uint8_t num, bool mode) { + if (num > 3) return; + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_REG_DIS_BIT, mode); +} +/** Get word pair grouping order offset for the specified slave (0-3). + * This sets specifies the grouping order of word pairs received from registers. + * When cleared to 0, bytes from register addresses 0 and 1, 2 and 3, etc (even, + * then odd register addresses) are paired to form a word. When set to 1, bytes + * from register addresses are paired 1 and 2, 3 and 4, etc. (odd, then even + * register addresses) are paired to form a word. + * + * @param num Slave number (0-3) + * @return Current word pair grouping order offset for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +bool MPU6050_getSlaveWordGroupOffset(uint8_t num) { + if (num > 3) return 0; + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_GRP_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set word pair grouping order offset for the specified slave (0-3). + * @param num Slave number (0-3) + * @param enabled New word pair grouping order offset for specified slave + * @see getSlaveWordGroupOffset() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050_setSlaveWordGroupOffset(uint8_t num, bool enabled) { + if (num > 3) return; + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_GRP_BIT, enabled); +} +/** Get number of bytes to read for the specified slave (0-3). + * Specifies the number of bytes transferred to and from Slave 0. Clearing this + * bit to 0 is equivalent to disabling the register by writing 0 to I2C_SLV0_EN. + * @param num Slave number (0-3) + * @return Number of bytes to read for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +uint8_t MPU6050_getSlaveDataLength(uint8_t num) { + if (num > 3) return 0; + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_LEN_BIT, MPU6050_I2C_SLV_LEN_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set number of bytes to read for the specified slave (0-3). + * @param num Slave number (0-3) + * @param length Number of bytes to read for specified slave + * @see getSlaveDataLength() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050_setSlaveDataLength(uint8_t num, uint8_t length) { + if (num > 3) return; + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_LEN_BIT, MPU6050_I2C_SLV_LEN_LENGTH, length); +} + +// I2C_SLV* registers (Slave 4) + +/** Get the I2C address of Slave 4. + * Note that Bit 7 (MSB) controls read/write mode. If Bit 7 is set, it's a read + * operation, and if it is cleared, then it's a write operation. The remaining + * bits (6-0) are the 7-bit device address of the slave device. + * + * @return Current address for Slave 4 + * @see getSlaveAddress() + * @see MPU6050_RA_I2C_SLV4_ADDR + */ +uint8_t MPU6050_getSlave4Address() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_ADDR, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set the I2C address of Slave 4. + * @param address New address for Slave 4 + * @see getSlave4Address() + * @see MPU6050_RA_I2C_SLV4_ADDR + */ +void MPU6050_setSlave4Address(uint8_t address) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_ADDR, address); +} +/** Get the active internal register for the Slave 4. + * Read/write operations for this slave will be done to whatever internal + * register address is stored in this MPU register. + * + * @return Current active register for Slave 4 + * @see MPU6050_RA_I2C_SLV4_REG + */ +uint8_t MPU6050_getSlave4Register() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_REG, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set the active internal register for Slave 4. + * @param reg New active register for Slave 4 + * @see getSlave4Register() + * @see MPU6050_RA_I2C_SLV4_REG + */ +void MPU6050_setSlave4Register(uint8_t reg) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_REG, reg); +} +/** Set new byte to write to Slave 4. + * This register stores the data to be written into the Slave 4. If I2C_SLV4_RW + * is set 1 (set to read), this register has no effect. + * @param data New byte to write to Slave 4 + * @see MPU6050_RA_I2C_SLV4_DO + */ +void MPU6050_setSlave4OutputByte(uint8_t data) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_DO, data); +} +/** Get the enabled value for the Slave 4. + * When set to 1, this bit enables Slave 4 for data transfer operations. When + * cleared to 0, this bit disables Slave 4 from data transfer operations. + * @return Current enabled value for Slave 4 + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +bool MPU6050_getSlave4Enabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set the enabled value for Slave 4. + * @param enabled New enabled value for Slave 4 + * @see getSlave4Enabled() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050_setSlave4Enabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_EN_BIT, enabled); +} +/** Get the enabled value for Slave 4 transaction interrupts. + * When set to 1, this bit enables the generation of an interrupt signal upon + * completion of a Slave 4 transaction. When cleared to 0, this bit disables the + * generation of an interrupt signal upon completion of a Slave 4 transaction. + * The interrupt status can be observed in Register 54. + * + * @return Current enabled value for Slave 4 transaction interrupts. + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +bool MPU6050_getSlave4InterruptEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_INT_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set the enabled value for Slave 4 transaction interrupts. + * @param enabled New enabled value for Slave 4 transaction interrupts. + * @see getSlave4InterruptEnabled() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050_setSlave4InterruptEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_INT_EN_BIT, enabled); +} +/** Get write mode for Slave 4. + * When set to 1, the transaction will read or write data only. When cleared to + * 0, the transaction will write a register address prior to reading or writing + * data. This should equal 0 when specifying the register address within the + * Slave device to/from which the ensuing data transaction will take place. + * + * @return Current write mode for Slave 4 (0 = register address + data, 1 = data only) + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +bool MPU6050_getSlave4WriteMode() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_REG_DIS_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set write mode for the Slave 4. + * @param mode New write mode for Slave 4 (0 = register address + data, 1 = data only) + * @see getSlave4WriteMode() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050_setSlave4WriteMode(bool mode) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_REG_DIS_BIT, mode); +} +/** Get Slave 4 master delay value. + * This configures the reduced access rate of I2C slaves relative to the Sample + * Rate. When a slave's access rate is decreased relative to the Sample Rate, + * the slave is accessed every: + * + * 1 / (1 + I2C_MST_DLY) samples + * + * This base Sample Rate in turn is determined by SMPLRT_DIV (register 25) and + * DLPF_CFG (register 26). Whether a slave's access rate is reduced relative to + * the Sample Rate is determined by I2C_MST_DELAY_CTRL (register 103). For + * further information regarding the Sample Rate, please refer to register 25. + * + * @return Current Slave 4 master delay value + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +uint8_t MPU6050_getSlave4MasterDelay() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_MST_DLY_BIT, MPU6050_I2C_SLV4_MST_DLY_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Slave 4 master delay value. + * @param delay New Slave 4 master delay value + * @see getSlave4MasterDelay() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050_setSlave4MasterDelay(uint8_t delay) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_MST_DLY_BIT, MPU6050_I2C_SLV4_MST_DLY_LENGTH, delay); +} +/** Get last available byte read from Slave 4. + * This register stores the data read from Slave 4. This field is populated + * after a read transaction. + * @return Last available byte read from to Slave 4 + * @see MPU6050_RA_I2C_SLV4_DI + */ +uint8_t MPU6050_getSlate4InputByte() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_DI, mpu6050.buffer); + return mpu6050.buffer[0]; +} + +// I2C_MST_STATUS register + +/** Get FSYNC interrupt status. + * This bit reflects the status of the FSYNC interrupt from an external device + * into the MPU-60X0. This is used as a way to pass an external interrupt + * through the MPU-60X0 to the host application processor. When set to 1, this + * bit will cause an interrupt if FSYNC_INT_EN is asserted in INT_PIN_CFG + * (Register 55). + * @return FSYNC interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_getPassthroughStatus() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_PASS_THROUGH_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Slave 4 transaction done status. + * Automatically sets to 1 when a Slave 4 transaction has completed. This + * triggers an interrupt if the I2C_MST_INT_EN bit in the INT_ENABLE register + * (Register 56) is asserted and if the SLV_4_DONE_INT bit is asserted in the + * I2C_SLV4_CTRL register (Register 52). + * @return Slave 4 transaction done status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_getSlave4IsDone() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV4_DONE_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get master arbitration lost status. + * This bit automatically sets to 1 when the I2C Master has lost arbitration of + * the auxiliary I2C bus (an error condition). This triggers an interrupt if the + * I2C_MST_INT_EN bit in the INT_ENABLE register (Register 56) is asserted. + * @return Master arbitration lost status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_getLostArbitration() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_LOST_ARB_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Slave 4 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 4. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 4 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_getSlave4Nack() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV4_NACK_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Slave 3 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 3. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 3 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_getSlave3Nack() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV3_NACK_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Slave 2 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 2. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 2 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_getSlave2Nack() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV2_NACK_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Slave 1 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 1. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 1 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_getSlave1Nack() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV1_NACK_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Slave 0 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 0. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 0 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_getSlave0Nack() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV0_NACK_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} + +// INT_PIN_CFG register + +/** Get interrupt logic level mode. + * Will be set 0 for active-high, 1 for active-low. + * @return Current interrupt mode (0=active-high, 1=active-low) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_LEVEL_BIT + */ +bool MPU6050_getInterruptMode() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_LEVEL_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set interrupt logic level mode. + * @param mode New interrupt mode (0=active-high, 1=active-low) + * @see getInterruptMode() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_LEVEL_BIT + */ +void MPU6050_setInterruptMode(bool mode) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_LEVEL_BIT, mode); +} +/** Get interrupt drive mode. + * Will be set 0 for push-pull, 1 for open-drain. + * @return Current interrupt drive mode (0=push-pull, 1=open-drain) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_OPEN_BIT + */ +bool MPU6050_getInterruptDrive() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_OPEN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set interrupt drive mode. + * @param drive New interrupt drive mode (0=push-pull, 1=open-drain) + * @see getInterruptDrive() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_OPEN_BIT + */ +void MPU6050_setInterruptDrive(bool drive) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_OPEN_BIT, drive); +} +/** Get interrupt latch mode. + * Will be set 0 for 50us-pulse, 1 for latch-until-int-cleared. + * @return Current latch mode (0=50us-pulse, 1=latch-until-int-cleared) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_LATCH_INT_EN_BIT + */ +bool MPU6050_getInterruptLatch() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_LATCH_INT_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set interrupt latch mode. + * @param latch New latch mode (0=50us-pulse, 1=latch-until-int-cleared) + * @see getInterruptLatch() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_LATCH_INT_EN_BIT + */ +void MPU6050_setInterruptLatch(bool latch) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_LATCH_INT_EN_BIT, latch); +} +/** Get interrupt latch clear mode. + * Will be set 0 for status-read-only, 1 for any-register-read. + * @return Current latch clear mode (0=status-read-only, 1=any-register-read) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_RD_CLEAR_BIT + */ +bool MPU6050_getInterruptLatchClear() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_RD_CLEAR_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set interrupt latch clear mode. + * @param clear New latch clear mode (0=status-read-only, 1=any-register-read) + * @see getInterruptLatchClear() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_RD_CLEAR_BIT + */ +void MPU6050_setInterruptLatchClear(bool clear) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_RD_CLEAR_BIT, clear); +} +/** Get FSYNC interrupt logic level mode. + * @return Current FSYNC interrupt mode (0=active-high, 1=active-low) + * @see getFSyncInterruptMode() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT + */ +bool MPU6050_getFSyncInterruptLevel() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set FSYNC interrupt logic level mode. + * @param mode New FSYNC interrupt mode (0=active-high, 1=active-low) + * @see getFSyncInterruptMode() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT + */ +void MPU6050_setFSyncInterruptLevel(bool level) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT, level); +} +/** Get FSYNC pin interrupt enabled setting. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled setting + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_EN_BIT + */ +bool MPU6050_getFSyncInterruptEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set FSYNC pin interrupt enabled setting. + * @param enabled New FSYNC pin interrupt enabled setting + * @see getFSyncInterruptEnabled() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_EN_BIT + */ +void MPU6050_setFSyncInterruptEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_EN_BIT, enabled); +} +/** Get I2C bypass enabled status. + * When this bit is equal to 1 and I2C_MST_EN (Register 106 bit[5]) is equal to + * 0, the host application processor will be able to directly access the + * auxiliary I2C bus of the MPU-60X0. When this bit is equal to 0, the host + * application processor will not be able to directly access the auxiliary I2C + * bus of the MPU-60X0 regardless of the state of I2C_MST_EN (Register 106 + * bit[5]). + * @return Current I2C bypass enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_I2C_BYPASS_EN_BIT + */ +bool MPU6050_getI2CBypassEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_I2C_BYPASS_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set I2C bypass enabled status. + * When this bit is equal to 1 and I2C_MST_EN (Register 106 bit[5]) is equal to + * 0, the host application processor will be able to directly access the + * auxiliary I2C bus of the MPU-60X0. When this bit is equal to 0, the host + * application processor will not be able to directly access the auxiliary I2C + * bus of the MPU-60X0 regardless of the state of I2C_MST_EN (Register 106 + * bit[5]). + * @param enabled New I2C bypass enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_I2C_BYPASS_EN_BIT + */ +void MPU6050_setI2CBypassEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_I2C_BYPASS_EN_BIT, enabled); +} +/** Get reference clock output enabled status. + * When this bit is equal to 1, a reference clock output is provided at the + * CLKOUT pin. When this bit is equal to 0, the clock output is disabled. For + * further information regarding CLKOUT, please refer to the MPU-60X0 Product + * Specification document. + * @return Current reference clock output enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_CLKOUT_EN_BIT + */ +bool MPU6050_getClockOutputEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_CLKOUT_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set reference clock output enabled status. + * When this bit is equal to 1, a reference clock output is provided at the + * CLKOUT pin. When this bit is equal to 0, the clock output is disabled. For + * further information regarding CLKOUT, please refer to the MPU-60X0 Product + * Specification document. + * @param enabled New reference clock output enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_CLKOUT_EN_BIT + */ +void MPU6050_setClockOutputEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_CLKOUT_EN_BIT, enabled); +} + +// INT_ENABLE register + +/** Get full interrupt enabled status. + * Full register byte for all interrupts, for quick reading. Each bit will be + * set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +uint8_t MPU6050_getIntEnabled() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set full interrupt enabled status. + * Full register byte for all interrupts, for quick reading. Each bit should be + * set 0 for disabled, 1 for enabled. + * @param enabled New interrupt enabled status + * @see getIntFreefallEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +void MPU6050_setIntEnabled(uint8_t enabled) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, enabled); +} +/** Get Free Fall interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +bool MPU6050_getIntFreefallEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FF_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Free Fall interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntFreefallEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +void MPU6050_setIntFreefallEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FF_BIT, enabled); +} +/** Get Motion Detection interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_MOT_BIT + **/ +bool MPU6050_getIntMotionEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_MOT_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Motion Detection interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntMotionEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_MOT_BIT + **/ +void MPU6050_setIntMotionEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_MOT_BIT, enabled); +} +/** Get Zero Motion Detection interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_ZMOT_BIT + **/ +bool MPU6050_getIntZeroMotionEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_ZMOT_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Zero Motion Detection interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntZeroMotionEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_ZMOT_BIT + **/ +void MPU6050_setIntZeroMotionEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_ZMOT_BIT, enabled); +} +/** Get FIFO Buffer Overflow interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT + **/ +bool MPU6050_getIntFIFOBufferOverflowEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set FIFO Buffer Overflow interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntFIFOBufferOverflowEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT + **/ +void MPU6050_setIntFIFOBufferOverflowEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, enabled); +} +/** Get I2C Master interrupt enabled status. + * This enables any of the I2C Master interrupt sources to generate an + * interrupt. Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT + **/ +bool MPU6050_getIntI2CMasterEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_I2C_MST_INT_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set I2C Master interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntI2CMasterEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT + **/ +void MPU6050_setIntI2CMasterEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_I2C_MST_INT_BIT, enabled); +} +/** Get Data Ready interrupt enabled setting. + * This event occurs each time a write operation to all of the sensor registers + * has been completed. Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_DATA_RDY_BIT + */ +bool MPU6050_getIntDataReadyEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DATA_RDY_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Data Ready interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntDataReadyEnabled() + * @see MPU6050_RA_INT_CFG + * @see MPU6050_INTERRUPT_DATA_RDY_BIT + */ +void MPU6050_setIntDataReadyEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DATA_RDY_BIT, enabled); +} + +// INT_STATUS register + +/** Get full set of interrupt status bits. + * These bits clear to 0 after the register has been read. Very useful + * for getting multiple INT statuses, since each single bit read clears + * all of them because it has to read the whole byte. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + */ +uint8_t MPU6050_getIntStatus() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_INT_STATUS, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Free Fall interrupt status. + * This bit automatically sets to 1 when a Free Fall interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_FF_BIT + */ +bool MPU6050_getIntFreefallStatus() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_FF_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Motion Detection interrupt status. + * This bit automatically sets to 1 when a Motion Detection interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_MOT_BIT + */ +bool MPU6050_getIntMotionStatus() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_MOT_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Zero Motion Detection interrupt status. + * This bit automatically sets to 1 when a Zero Motion Detection interrupt has + * been generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_ZMOT_BIT + */ +bool MPU6050_getIntZeroMotionStatus() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_ZMOT_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get FIFO Buffer Overflow interrupt status. + * This bit automatically sets to 1 when a Free Fall interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT + */ +bool MPU6050_getIntFIFOBufferOverflowStatus() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get I2C Master interrupt status. + * This bit automatically sets to 1 when an I2C Master interrupt has been + * generated. For a list of I2C Master interrupts, please refer to Register 54. + * The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT + */ +bool MPU6050_getIntI2CMasterStatus() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_I2C_MST_INT_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Data Ready interrupt status. + * This bit automatically sets to 1 when a Data Ready interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_DATA_RDY_BIT + */ +bool MPU6050_getIntDataReadyStatus() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_DATA_RDY_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} + +// ACCEL_*OUT_* registers + +/** Get raw 9-axis motion sensor readings (accel/gyro/compass). + * FUNCTION NOT FULLY IMPLEMENTED YET. + * @param ax 16-bit signed integer container for accelerometer X-axis value + * @param ay 16-bit signed integer container for accelerometer Y-axis value + * @param az 16-bit signed integer container for accelerometer Z-axis value + * @param gx 16-bit signed integer container for gyroscope X-axis value + * @param gy 16-bit signed integer container for gyroscope Y-axis value + * @param gz 16-bit signed integer container for gyroscope Z-axis value + * @param mx 16-bit signed integer container for magnetometer X-axis value + * @param my 16-bit signed integer container for magnetometer Y-axis value + * @param mz 16-bit signed integer container for magnetometer Z-axis value + * @see getMotion6() + * @see getAcceleration() + * @see getRotation() + * @see MPU6050_RA_ACCEL_XOUT_H + */ +void MPU6050_getMotion9(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz, int16_t* mx, int16_t* my, int16_t* mz) { + MPU6050_getMotion6(ax, ay, az, gx, gy, gz); + // TODO: magnetometer integration +} +/** Get raw 6-axis motion sensor readings (accel/gyro). + * Retrieves all currently available motion sensor values. + * @param ax 16-bit signed integer container for accelerometer X-axis value + * @param ay 16-bit signed integer container for accelerometer Y-axis value + * @param az 16-bit signed integer container for accelerometer Z-axis value + * @param gx 16-bit signed integer container for gyroscope X-axis value + * @param gy 16-bit signed integer container for gyroscope Y-axis value + * @param gz 16-bit signed integer container for gyroscope Z-axis value + * @see getAcceleration() + * @see getRotation() + * @see MPU6050_RA_ACCEL_XOUT_H + */ +void MPU6050_getMotion6(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz) { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ACCEL_XOUT_H, 14, mpu6050.buffer); + *ax = (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; + *ay = (((int16_t)mpu6050.buffer[2]) << 8) | mpu6050.buffer[3]; + *az = (((int16_t)mpu6050.buffer[4]) << 8) | mpu6050.buffer[5]; + *gx = (((int16_t)mpu6050.buffer[8]) << 8) | mpu6050.buffer[9]; + *gy = (((int16_t)mpu6050.buffer[10]) << 8) | mpu6050.buffer[11]; + *gz = (((int16_t)mpu6050.buffer[12]) << 8) | mpu6050.buffer[13]; +} +/** Get 3-axis accelerometer readings. + * These registers store the most recent accelerometer measurements. + * Accelerometer measurements are written to these registers at the Sample Rate + * as defined in Register 25. + * + * The accelerometer measurement registers, along with the temperature + * measurement registers, gyroscope measurement registers, and external sensor + * data registers, are composed of two sets of registers: an internal register + * set and a user-facing read register set. + * + * The data within the accelerometer sensors' internal register set is always + * updated at the Sample Rate. Meanwhile, the user-facing read register set + * duplicates the internal register set's data values whenever the serial + * interface is idle. This guarantees that a burst read of sensor registers will + * read measurements from the same sampling instant. Note that if burst reads + * are not used, the user is responsible for ensuring a set of single byte reads + * correspond to a single sampling instant by checking the Data Ready interrupt. + * + * Each 16-bit accelerometer measurement has a full scale defined in ACCEL_FS + * (Register 28). For each full scale setting, the accelerometers' sensitivity + * per LSB in ACCEL_xOUT is shown in the table below: + * + *
+ * AFS_SEL | Full Scale Range | LSB Sensitivity
+ * --------+------------------+----------------
+ * 0       | +/- 2g           | 8192 LSB/mg
+ * 1       | +/- 4g           | 4096 LSB/mg
+ * 2       | +/- 8g           | 2048 LSB/mg
+ * 3       | +/- 16g          | 1024 LSB/mg
+ * 
+ * + * @param x 16-bit signed integer container for X-axis acceleration + * @param y 16-bit signed integer container for Y-axis acceleration + * @param z 16-bit signed integer container for Z-axis acceleration + * @see MPU6050_RA_GYRO_XOUT_H + */ +void MPU6050_getAcceleration(int16_t* x, int16_t* y, int16_t* z) { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ACCEL_XOUT_H, 6, mpu6050.buffer); + *x = (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; + *y = (((int16_t)mpu6050.buffer[2]) << 8) | mpu6050.buffer[3]; + *z = (((int16_t)mpu6050.buffer[4]) << 8) | mpu6050.buffer[5]; +} +/** Get X-axis accelerometer reading. + * @return X-axis acceleration measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_ACCEL_XOUT_H + */ +int16_t MPU6050_getAccelerationX() { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ACCEL_XOUT_H, 2, mpu6050.buffer); + return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; +} +/** Get Y-axis accelerometer reading. + * @return Y-axis acceleration measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_ACCEL_YOUT_H + */ +int16_t MPU6050_getAccelerationY() { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ACCEL_YOUT_H, 2, mpu6050.buffer); + return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; +} +/** Get Z-axis accelerometer reading. + * @return Z-axis acceleration measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_ACCEL_ZOUT_H + */ +int16_t MPU6050_getAccelerationZ() { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ACCEL_ZOUT_H, 2, mpu6050.buffer); + return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; +} + +// TEMP_OUT_* registers + +/** Get current internal temperature. + * @return Temperature reading in 16-bit 2's complement format + * @see MPU6050_RA_TEMP_OUT_H + */ +int16_t MPU6050_getTemperature() { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_TEMP_OUT_H, 2, mpu6050.buffer); + return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; +} + +// GYRO_*OUT_* registers + +/** Get 3-axis gyroscope readings. + * These gyroscope measurement registers, along with the accelerometer + * measurement registers, temperature measurement registers, and external sensor + * data registers, are composed of two sets of registers: an internal register + * set and a user-facing read register set. + * The data within the gyroscope sensors' internal register set is always + * updated at the Sample Rate. Meanwhile, the user-facing read register set + * duplicates the internal register set's data values whenever the serial + * interface is idle. This guarantees that a burst read of sensor registers will + * read measurements from the same sampling instant. Note that if burst reads + * are not used, the user is responsible for ensuring a set of single byte reads + * correspond to a single sampling instant by checking the Data Ready interrupt. + * + * Each 16-bit gyroscope measurement has a full scale defined in FS_SEL + * (Register 27). For each full scale setting, the gyroscopes' sensitivity per + * LSB in GYRO_xOUT is shown in the table below: + * + *
+ * FS_SEL | Full Scale Range   | LSB Sensitivity
+ * -------+--------------------+----------------
+ * 0      | +/- 250 degrees/s  | 131 LSB/deg/s
+ * 1      | +/- 500 degrees/s  | 65.5 LSB/deg/s
+ * 2      | +/- 1000 degrees/s | 32.8 LSB/deg/s
+ * 3      | +/- 2000 degrees/s | 16.4 LSB/deg/s
+ * 
+ * + * @param x 16-bit signed integer container for X-axis rotation + * @param y 16-bit signed integer container for Y-axis rotation + * @param z 16-bit signed integer container for Z-axis rotation + * @see getMotion6() + * @see MPU6050_RA_GYRO_XOUT_H + */ +void MPU6050_getRotation(int16_t* x, int16_t* y, int16_t* z) { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_GYRO_XOUT_H, 6, mpu6050.buffer); + *x = (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; + *y = (((int16_t)mpu6050.buffer[2]) << 8) | mpu6050.buffer[3]; + *z = (((int16_t)mpu6050.buffer[4]) << 8) | mpu6050.buffer[5]; +} +/** Get X-axis gyroscope reading. + * @return X-axis rotation measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_GYRO_XOUT_H + */ +int16_t MPU6050_getRotationX() { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_GYRO_XOUT_H, 2, mpu6050.buffer); + return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; +} +/** Get Y-axis gyroscope reading. + * @return Y-axis rotation measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_GYRO_YOUT_H + */ +int16_t MPU6050_getRotationY() { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_GYRO_YOUT_H, 2, mpu6050.buffer); + return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; +} +/** Get Z-axis gyroscope reading. + * @return Z-axis rotation measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_GYRO_ZOUT_H + */ +int16_t MPU6050_getRotationZ() { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_GYRO_ZOUT_H, 2, mpu6050.buffer); + return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; +} + +// EXT_SENS_DATA_* registers + +/** Read single byte from external sensor data register. + * These registers store data read from external sensors by the Slave 0, 1, 2, + * and 3 on the auxiliary I2C interface. Data read by Slave 4 is stored in + * I2C_SLV4_DI (Register 53). + * + * External sensor data is written to these registers at the Sample Rate as + * defined in Register 25. This access rate can be reduced by using the Slave + * Delay Enable registers (Register 103). + * + * External sensor data registers, along with the gyroscope measurement + * registers, accelerometer measurement registers, and temperature measurement + * registers, are composed of two sets of registers: an internal register set + * and a user-facing read register set. + * + * The data within the external sensors' internal register set is always updated + * at the Sample Rate (or the reduced access rate) whenever the serial interface + * is idle. This guarantees that a burst read of sensor registers will read + * measurements from the same sampling instant. Note that if burst reads are not + * used, the user is responsible for ensuring a set of single byte reads + * correspond to a single sampling instant by checking the Data Ready interrupt. + * + * Data is placed in these external sensor data registers according to + * I2C_SLV0_CTRL, I2C_SLV1_CTRL, I2C_SLV2_CTRL, and I2C_SLV3_CTRL (Registers 39, + * 42, 45, and 48). When more than zero bytes are read (I2C_SLVx_LEN > 0) from + * an enabled slave (I2C_SLVx_EN = 1), the slave is read at the Sample Rate (as + * defined in Register 25) or delayed rate (if specified in Register 52 and + * 103). During each Sample cycle, slave reads are performed in order of Slave + * number. If all slaves are enabled with more than zero bytes to be read, the + * order will be Slave 0, followed by Slave 1, Slave 2, and Slave 3. + * + * Each enabled slave will have EXT_SENS_DATA registers associated with it by + * number of bytes read (I2C_SLVx_LEN) in order of slave number, starting from + * EXT_SENS_DATA_00. Note that this means enabling or disabling a slave may + * change the higher numbered slaves' associated registers. Furthermore, if + * fewer total bytes are being read from the external sensors as a result of + * such a change, then the data remaining in the registers which no longer have + * an associated slave device (i.e. high numbered registers) will remain in + * these previously allocated registers unless reset. + * + * If the sum of the read lengths of all SLVx transactions exceed the number of + * available EXT_SENS_DATA registers, the excess bytes will be dropped. There + * are 24 EXT_SENS_DATA registers and hence the total read lengths between all + * the slaves cannot be greater than 24 or some bytes will be lost. + * + * Note: Slave 4's behavior is distinct from that of Slaves 0-3. For further + * information regarding the characteristics of Slave 4, please refer to + * Registers 49 to 53. + * + * EXAMPLE: + * Suppose that Slave 0 is enabled with 4 bytes to be read (I2C_SLV0_EN = 1 and + * I2C_SLV0_LEN = 4) while Slave 1 is enabled with 2 bytes to be read so that + * I2C_SLV1_EN = 1 and I2C_SLV1_LEN = 2. In such a situation, EXT_SENS_DATA _00 + * through _03 will be associated with Slave 0, while EXT_SENS_DATA _04 and 05 + * will be associated with Slave 1. If Slave 2 is enabled as well, registers + * starting from EXT_SENS_DATA_06 will be allocated to Slave 2. + * + * If Slave 2 is disabled while Slave 3 is enabled in this same situation, then + * registers starting from EXT_SENS_DATA_06 will be allocated to Slave 3 + * instead. + * + * REGISTER ALLOCATION FOR DYNAMIC DISABLE VS. NORMAL DISABLE: + * If a slave is disabled at any time, the space initially allocated to the + * slave in the EXT_SENS_DATA register, will remain associated with that slave. + * This is to avoid dynamic adjustment of the register allocation. + * + * The allocation of the EXT_SENS_DATA registers is recomputed only when (1) all + * slaves are disabled, or (2) the I2C_MST_RST bit is set (Register 106). + * + * This above is also true if one of the slaves gets NACKed and stops + * functioning. + * + * @param position Starting position (0-23) + * @return Byte read from register + */ +uint8_t MPU6050_getExternalSensorByte(int position) { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Read word (2 bytes) from external sensor data registers. + * @param position Starting position (0-21) + * @return Word read from register + * @see getExternalSensorByte() + */ +uint16_t MPU6050_getExternalSensorWord(int position) { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, 2, mpu6050.buffer); + return (((uint16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; +} +/** Read double word (4 bytes) from external sensor data registers. + * @param position Starting position (0-20) + * @return Double word read from registers + * @see getExternalSensorByte() + */ +uint32_t MPU6050_getExternalSensorDWord(int position) { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, 4, mpu6050.buffer); + return (((uint32_t)mpu6050.buffer[0]) << 24) | (((uint32_t)mpu6050.buffer[1]) << 16) | (((uint16_t)mpu6050.buffer[2]) << 8) | mpu6050.buffer[3]; +} + +// MOT_DETECT_STATUS register + +/** Get X-axis negative motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_XNEG_BIT + */ +bool MPU6050_getXNegMotionDetected() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_XNEG_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get X-axis positive motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_XPOS_BIT + */ +bool MPU6050_getXPosMotionDetected() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_XPOS_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Y-axis negative motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_YNEG_BIT + */ +bool MPU6050_getYNegMotionDetected() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_YNEG_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Y-axis positive motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_YPOS_BIT + */ +bool MPU6050_getYPosMotionDetected() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_YPOS_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Z-axis negative motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_ZNEG_BIT + */ +bool MPU6050_getZNegMotionDetected() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZNEG_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Z-axis positive motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_ZPOS_BIT + */ +bool MPU6050_getZPosMotionDetected() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZPOS_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get zero motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_ZRMOT_BIT + */ +bool MPU6050_getZeroMotionDetected() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZRMOT_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} + +// I2C_SLV*_DO register + +/** Write byte to Data Output container for specified slave. + * This register holds the output data written into Slave when Slave is set to + * write mode. For further information regarding Slave control, please + * refer to Registers 37 to 39 and immediately following. + * @param num Slave number (0-3) + * @param data Byte to write + * @see MPU6050_RA_I2C_SLV0_DO + */ +void MPU6050_setSlaveOutputByte(uint8_t num, uint8_t data) { + if (num > 3) return; + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_DO + num, data); +} + +// I2C_MST_DELAY_CTRL register + +/** Get external data shadow delay enabled status. + * This register is used to specify the timing of external sensor data + * shadowing. When DELAY_ES_SHADOW is set to 1, shadowing of external + * sensor data is delayed until all data has been received. + * @return Current external data shadow delay enabled status. + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT + */ +bool MPU6050_getExternalShadowDelayEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set external data shadow delay enabled status. + * @param enabled New external data shadow delay enabled status. + * @see getExternalShadowDelayEnabled() + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT + */ +void MPU6050_setExternalShadowDelayEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT, enabled); +} +/** Get slave delay enabled status. + * When a particular slave delay is enabled, the rate of access for the that + * slave device is reduced. When a slave's access rate is decreased relative to + * the Sample Rate, the slave is accessed every: + * + * 1 / (1 + I2C_MST_DLY) Samples + * + * This base Sample Rate in turn is determined by SMPLRT_DIV (register * 25) + * and DLPF_CFG (register 26). + * + * For further information regarding I2C_MST_DLY, please refer to register 52. + * For further information regarding the Sample Rate, please refer to register 25. + * + * @param num Slave number (0-4) + * @return Current slave delay enabled status. + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT + */ +bool MPU6050_getSlaveDelayEnabled(uint8_t num) { + // MPU6050_DELAYCTRL_I2C_SLV4_DLY_EN_BIT is 4, SLV3 is 3, etc. + if (num > 4) return 0; + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, num, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set slave delay enabled status. + * @param num Slave number (0-4) + * @param enabled New slave delay enabled status. + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT + */ +void MPU6050_setSlaveDelayEnabled(uint8_t num, bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, num, enabled); +} + +// SIGNAL_PATH_RESET register + +/** Reset gyroscope signal path. + * The reset will revert the signal path analog to digital converters and + * filters to their power up configurations. + * @see MPU6050_RA_SIGNAL_PATH_RESET + * @see MPU6050_PATHRESET_GYRO_RESET_BIT + */ +void MPU6050_resetGyroscopePath() { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_GYRO_RESET_BIT, true); +} +/** Reset accelerometer signal path. + * The reset will revert the signal path analog to digital converters and + * filters to their power up configurations. + * @see MPU6050_RA_SIGNAL_PATH_RESET + * @see MPU6050_PATHRESET_ACCEL_RESET_BIT + */ +void MPU6050_resetAccelerometerPath() { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_ACCEL_RESET_BIT, true); +} +/** Reset temperature sensor signal path. + * The reset will revert the signal path analog to digital converters and + * filters to their power up configurations. + * @see MPU6050_RA_SIGNAL_PATH_RESET + * @see MPU6050_PATHRESET_TEMP_RESET_BIT + */ +void MPU6050_resetTemperaturePath() { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_TEMP_RESET_BIT, true); +} + +// MOT_DETECT_CTRL register + +/** Get accelerometer power-on delay. + * The accelerometer data path provides samples to the sensor registers, Motion + * detection, Zero Motion detection, and Free Fall detection modules. The + * signal path contains filters which must be flushed on wake-up with new + * samples before the detection modules begin operations. The default wake-up + * delay, of 4ms can be lengthened by up to 3ms. This additional delay is + * specified in ACCEL_ON_DELAY in units of 1 LSB = 1 ms. The user may select + * any value above zero unless instructed otherwise by InvenSense. Please refer + * to Section 8 of the MPU-6000/MPU-6050 Product Specification document for + * further information regarding the detection modules. + * @return Current accelerometer power-on delay + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_ACCEL_ON_DELAY_BIT + */ +uint8_t MPU6050_getAccelerometerPowerOnDelay() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_ACCEL_ON_DELAY_BIT, MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set accelerometer power-on delay. + * @param delay New accelerometer power-on delay (0-3) + * @see getAccelerometerPowerOnDelay() + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_ACCEL_ON_DELAY_BIT + */ +void MPU6050_setAccelerometerPowerOnDelay(uint8_t delay) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_ACCEL_ON_DELAY_BIT, MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH, delay); +} +/** Get Free Fall detection counter decrement configuration. + * Detection is registered by the Free Fall detection module after accelerometer + * measurements meet their respective threshold conditions over a specified + * number of samples. When the threshold conditions are met, the corresponding + * detection counter increments by 1. The user may control the rate at which the + * detection counter decrements when the threshold condition is not met by + * configuring FF_COUNT. The decrement rate can be set according to the + * following table: + * + *
+ * FF_COUNT | Counter Decrement
+ * ---------+------------------
+ * 0        | Reset
+ * 1        | 1
+ * 2        | 2
+ * 3        | 4
+ * 
+ * + * When FF_COUNT is configured to 0 (reset), any non-qualifying sample will + * reset the counter to 0. For further information on Free Fall detection, + * please refer to Registers 29 to 32. + * + * @return Current decrement configuration + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_FF_COUNT_BIT + */ +uint8_t MPU6050_getFreefallDetectionCounterDecrement() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_FF_COUNT_BIT, MPU6050_DETECT_FF_COUNT_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Free Fall detection counter decrement configuration. + * @param decrement New decrement configuration value + * @see getFreefallDetectionCounterDecrement() + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_FF_COUNT_BIT + */ +void MPU6050_setFreefallDetectionCounterDecrement(uint8_t decrement) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_FF_COUNT_BIT, MPU6050_DETECT_FF_COUNT_LENGTH, decrement); +} +/** Get Motion detection counter decrement configuration. + * Detection is registered by the Motion detection module after accelerometer + * measurements meet their respective threshold conditions over a specified + * number of samples. When the threshold conditions are met, the corresponding + * detection counter increments by 1. The user may control the rate at which the + * detection counter decrements when the threshold condition is not met by + * configuring MOT_COUNT. The decrement rate can be set according to the + * following table: + * + *
+ * MOT_COUNT | Counter Decrement
+ * ----------+------------------
+ * 0         | Reset
+ * 1         | 1
+ * 2         | 2
+ * 3         | 4
+ * 
+ * + * When MOT_COUNT is configured to 0 (reset), any non-qualifying sample will + * reset the counter to 0. For further information on Motion detection, + * please refer to Registers 29 to 32. + * + */ +uint8_t MPU6050_getMotionDetectionCounterDecrement() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_MOT_COUNT_BIT, MPU6050_DETECT_MOT_COUNT_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Motion detection counter decrement configuration. + * @param decrement New decrement configuration value + * @see getMotionDetectionCounterDecrement() + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_MOT_COUNT_BIT + */ +void MPU6050_setMotionDetectionCounterDecrement(uint8_t decrement) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_MOT_COUNT_BIT, MPU6050_DETECT_MOT_COUNT_LENGTH, decrement); +} + +// USER_CTRL register + +/** Get FIFO enabled status. + * When this bit is set to 0, the FIFO mpu6050.buffer is disabled. The FIFO mpu6050.buffer + * cannot be written to or read from while disabled. The FIFO mpu6050.buffer's state + * does not change unless the MPU-60X0 is power cycled. + * @return Current FIFO enabled status + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_FIFO_EN_BIT + */ +bool MPU6050_getFIFOEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set FIFO enabled status. + * @param enabled New FIFO enabled status + * @see getFIFOEnabled() + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_FIFO_EN_BIT + */ +void MPU6050_setFIFOEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_EN_BIT, enabled); +} +/** Get I2C Master Mode enabled status. + * When this mode is enabled, the MPU-60X0 acts as the I2C Master to the + * external sensor slave devices on the auxiliary I2C bus. When this bit is + * cleared to 0, the auxiliary I2C bus lines (AUX_DA and AUX_CL) are logically + * driven by the primary I2C bus (SDA and SCL). This is a precondition to + * enabling Bypass Mode. For further information regarding Bypass Mode, please + * refer to Register 55. + * @return Current I2C Master Mode enabled status + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_I2C_MST_EN_BIT + */ +bool MPU6050_getI2CMasterModeEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set I2C Master Mode enabled status. + * @param enabled New I2C Master Mode enabled status + * @see getI2CMasterModeEnabled() + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_I2C_MST_EN_BIT + */ +void MPU6050_setI2CMasterModeEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_EN_BIT, enabled); +} +/** Switch from I2C to SPI mode (MPU-6000 only) + * If this is set, the primary SPI interface will be enabled in place of the + * disabled primary I2C interface. + */ +void MPU6050_switchSPIEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_IF_DIS_BIT, enabled); +} +/** Reset the FIFO. + * This bit resets the FIFO mpu6050.buffer when set to 1 while FIFO_EN equals 0. This + * bit automatically clears to 0 after the reset has been triggered. + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_FIFO_RESET_BIT + */ +void MPU6050_resetFIFO() { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_RESET_BIT, true); +} +/** Reset the I2C Master. + * This bit resets the I2C Master when set to 1 while I2C_MST_EN equals 0. + * This bit automatically clears to 0 after the reset has been triggered. + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_I2C_MST_RESET_BIT + */ +void MPU6050_resetI2CMaster() { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_RESET_BIT, true); +} +/** Reset all sensor registers and signal paths. + * When set to 1, this bit resets the signal paths for all sensors (gyroscopes, + * accelerometers, and temperature sensor). This operation will also clear the + * sensor registers. This bit automatically clears to 0 after the reset has been + * triggered. + * + * When resetting only the signal path (and not the sensor registers), please + * use Register 104, SIGNAL_PATH_RESET. + * + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_SIG_COND_RESET_BIT + */ +void MPU6050_resetSensors() { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_SIG_COND_RESET_BIT, true); +} + +// PWR_MGMT_1 register + +/** Trigger a full device reset. + * A small delay of ~50ms may be desirable after triggering a reset. + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_DEVICE_RESET_BIT + */ +void MPU6050_reset() { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_DEVICE_RESET_BIT, true); +} +/** Get sleep mode status. + * Setting the SLEEP bit in the register puts the device into very low power + * sleep mode. In this mode, only the serial interface and internal registers + * remain active, allowing for a very low standby current. Clearing this bit + * puts the device back into normal mode. To save power, the individual standby + * selections for each of the gyros should be used if any gyro axis is not used + * by the application. + * @return Current sleep mode enabled status + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_SLEEP_BIT + */ +bool MPU6050_getSleepEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set sleep mode status. + * @param enabled New sleep mode enabled status + * @see getSleepEnabled() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_SLEEP_BIT + */ +void MPU6050_setSleepEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, enabled); +} +/** Get wake cycle enabled status. + * When this bit is set to 1 and SLEEP is disabled, the MPU-60X0 will cycle + * between sleep mode and waking up to take a single sample of data from active + * sensors at a rate determined by LP_WAKE_CTRL (register 108). + * @return Current sleep mode enabled status + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CYCLE_BIT + */ +bool MPU6050_getWakeCycleEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CYCLE_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set wake cycle enabled status. + * @param enabled New sleep mode enabled status + * @see getWakeCycleEnabled() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CYCLE_BIT + */ +void MPU6050_setWakeCycleEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CYCLE_BIT, enabled); +} +/** Get temperature sensor enabled status. + * Control the usage of the internal temperature sensor. + * + * Note: this register stores the *disabled* value, but for consistency with the + * rest of the code, the function is named and used with standard true/false + * values to indicate whether the sensor is enabled or disabled, respectively. + * + * @return Current temperature sensor enabled status + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_TEMP_DIS_BIT + */ +bool MPU6050_getTempSensorEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_TEMP_DIS_BIT, mpu6050.buffer); + return mpu6050.buffer[0] == 0; // 1 is actually disabled here +} +/** Set temperature sensor enabled status. + * Note: this register stores the *disabled* value, but for consistency with the + * rest of the code, the function is named and used with standard true/false + * values to indicate whether the sensor is enabled or disabled, respectively. + * + * @param enabled New temperature sensor enabled status + * @see getTempSensorEnabled() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_TEMP_DIS_BIT + */ +void MPU6050_setTempSensorEnabled(bool enabled) { + // 1 is actually disabled here + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_TEMP_DIS_BIT, !enabled); +} +/** Get clock source setting. + * @return Current clock source setting + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CLKSEL_BIT + * @see MPU6050_PWR1_CLKSEL_LENGTH + */ +uint8_t MPU6050_getClockSource() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set clock source setting. + * An internal 8MHz oscillator, gyroscope based clock, or external sources can + * be selected as the MPU-60X0 clock source. When the internal 8 MHz oscillator + * or an external source is chosen as the clock source, the MPU-60X0 can operate + * in low power modes with the gyroscopes disabled. + * + * Upon power up, the MPU-60X0 clock source defaults to the internal oscillator. + * However, it is highly recommended that the device be configured to use one of + * the gyroscopes (or an external clock source) as the clock reference for + * improved stability. The clock source can be selected according to the following table: + * + *
+ * CLK_SEL | Clock Source
+ * --------+--------------------------------------
+ * 0       | Internal oscillator
+ * 1       | PLL with X Gyro reference
+ * 2       | PLL with Y Gyro reference
+ * 3       | PLL with Z Gyro reference
+ * 4       | PLL with external 32.768kHz reference
+ * 5       | PLL with external 19.2MHz reference
+ * 6       | Reserved
+ * 7       | Stops the clock and keeps the timing generator in reset
+ * 
+ * + * @param source New clock source setting + * @see getClockSource() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CLKSEL_BIT + * @see MPU6050_PWR1_CLKSEL_LENGTH + */ +void MPU6050_setClockSource(uint8_t source) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, source); +} + +// PWR_MGMT_2 register + +/** Get wake frequency in Accel-Only Low Power Mode. + * The MPU-60X0 can be put into Accerlerometer Only Low Power Mode by setting + * PWRSEL to 1 in the Power Management 1 register (Register 107). In this mode, + * the device will power off all devices except for the primary I2C interface, + * waking only the accelerometer at fixed intervals to take a single + * measurement. The frequency of wake-ups can be configured with LP_WAKE_CTRL + * as shown below: + * + *
+ * LP_WAKE_CTRL | Wake-up Frequency
+ * -------------+------------------
+ * 0            | 1.25 Hz
+ * 1            | 2.5 Hz
+ * 2            | 5 Hz
+ * 3            | 10 Hz
+ * 
+ *
+ * For further information regarding the MPU-60X0's power modes, please refer to
+ * Register 107.
+ *
+ * @return Current wake frequency
+ * @see MPU6050_RA_PWR_MGMT_2
+ */
+uint8_t MPU6050_getWakeFrequency() {
+    I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_LP_WAKE_CTRL_BIT, MPU6050_PWR2_LP_WAKE_CTRL_LENGTH, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+/** Set wake frequency in Accel-Only Low Power Mode.
+ * @param frequency New wake frequency
+ * @see MPU6050_RA_PWR_MGMT_2
+ */
+void MPU6050_setWakeFrequency(uint8_t frequency) {
+    I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_LP_WAKE_CTRL_BIT, MPU6050_PWR2_LP_WAKE_CTRL_LENGTH, frequency);
+}
+
+/** Get X-axis accelerometer standby enabled status.
+ * If enabled, the X-axis will not gather or report data (or use power).
+ * @return Current X-axis standby enabled status
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_XA_BIT
+ */
+bool MPU6050_getStandbyXAccelEnabled() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XA_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+/** Set X-axis accelerometer standby enabled status.
+ * @param New X-axis standby enabled status
+ * @see getStandbyXAccelEnabled()
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_XA_BIT
+ */
+void MPU6050_setStandbyXAccelEnabled(bool enabled) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XA_BIT, enabled);
+}
+/** Get Y-axis accelerometer standby enabled status.
+ * If enabled, the Y-axis will not gather or report data (or use power).
+ * @return Current Y-axis standby enabled status
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_YA_BIT
+ */
+bool MPU6050_getStandbyYAccelEnabled() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YA_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+/** Set Y-axis accelerometer standby enabled status.
+ * @param New Y-axis standby enabled status
+ * @see getStandbyYAccelEnabled()
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_YA_BIT
+ */
+void MPU6050_setStandbyYAccelEnabled(bool enabled) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YA_BIT, enabled);
+}
+/** Get Z-axis accelerometer standby enabled status.
+ * If enabled, the Z-axis will not gather or report data (or use power).
+ * @return Current Z-axis standby enabled status
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_ZA_BIT
+ */
+bool MPU6050_getStandbyZAccelEnabled() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZA_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+/** Set Z-axis accelerometer standby enabled status.
+ * @param New Z-axis standby enabled status
+ * @see getStandbyZAccelEnabled()
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_ZA_BIT
+ */
+void MPU6050_setStandbyZAccelEnabled(bool enabled) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZA_BIT, enabled);
+}
+/** Get X-axis gyroscope standby enabled status.
+ * If enabled, the X-axis will not gather or report data (or use power).
+ * @return Current X-axis standby enabled status
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_XG_BIT
+ */
+bool MPU6050_getStandbyXGyroEnabled() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XG_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+/** Set X-axis gyroscope standby enabled status.
+ * @param New X-axis standby enabled status
+ * @see getStandbyXGyroEnabled()
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_XG_BIT
+ */
+void MPU6050_setStandbyXGyroEnabled(bool enabled) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XG_BIT, enabled);
+}
+/** Get Y-axis gyroscope standby enabled status.
+ * If enabled, the Y-axis will not gather or report data (or use power).
+ * @return Current Y-axis standby enabled status
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_YG_BIT
+ */
+bool MPU6050_getStandbyYGyroEnabled() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YG_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+/** Set Y-axis gyroscope standby enabled status.
+ * @param New Y-axis standby enabled status
+ * @see getStandbyYGyroEnabled()
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_YG_BIT
+ */
+void MPU6050_setStandbyYGyroEnabled(bool enabled) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YG_BIT, enabled);
+}
+/** Get Z-axis gyroscope standby enabled status.
+ * If enabled, the Z-axis will not gather or report data (or use power).
+ * @return Current Z-axis standby enabled status
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_ZG_BIT
+ */
+bool MPU6050_getStandbyZGyroEnabled() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZG_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+/** Set Z-axis gyroscope standby enabled status.
+ * @param New Z-axis standby enabled status
+ * @see getStandbyZGyroEnabled()
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_ZG_BIT
+ */
+void MPU6050_setStandbyZGyroEnabled(bool enabled) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZG_BIT, enabled);
+}
+
+// FIFO_COUNT* registers
+
+/** Get current FIFO mpu6050.buffer size.
+ * This value indicates the number of bytes stored in the FIFO mpu6050.buffer. This
+ * number is in turn the number of bytes that can be read from the FIFO mpu6050.buffer
+ * and it is directly proportional to the number of samples available given the
+ * set of sensor data bound to be stored in the FIFO (register 35 and 36).
+ * @return Current FIFO mpu6050.buffer size
+ */
+uint16_t MPU6050_getFIFOCount() {
+    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_FIFO_COUNTH, 2, mpu6050.buffer);
+    return (((uint16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+}
+
+// FIFO_R_W register
+
+/** Get byte from FIFO mpu6050.buffer.
+ * This register is used to read and write data from the FIFO mpu6050.buffer. Data is
+ * written to the FIFO in order of register number (from lowest to highest). If
+ * all the FIFO enable flags (see below) are enabled and all External Sensor
+ * Data registers (Registers 73 to 96) are associated with a Slave device, the
+ * contents of registers 59 through 96 will be written in order at the Sample
+ * Rate.
+ *
+ * The contents of the sensor data registers (Registers 59 to 96) are written
+ * into the FIFO mpu6050.buffer when their corresponding FIFO enable flags are set to 1
+ * in FIFO_EN (Register 35). An additional flag for the sensor data registers
+ * associated with I2C Slave 3 can be found in I2C_MST_CTRL (Register 36).
+ *
+ * If the FIFO mpu6050.buffer has overflowed, the status bit FIFO_OFLOW_INT is
+ * automatically set to 1. This bit is located in INT_STATUS (Register 58).
+ * When the FIFO mpu6050.buffer has overflowed, the oldest data will be lost and new
+ * data will be written to the FIFO.
+ *
+ * If the FIFO mpu6050.buffer is empty, reading this register will return the last byte
+ * that was previously read from the FIFO until new data is available. The user
+ * should check FIFO_COUNT to ensure that the FIFO mpu6050.buffer is not read when
+ * empty.
+ *
+ * @return Byte from FIFO mpu6050.buffer
+ */
+uint8_t MPU6050_getFIFOByte() {
+    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_FIFO_R_W, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_getFIFOBytes(uint8_t *data, uint8_t length) {
+    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_FIFO_R_W, length, data);
+}
+/** Write byte to FIFO mpu6050.buffer.
+ * @see getFIFOByte()
+ * @see MPU6050_RA_FIFO_R_W
+ */
+void MPU6050_setFIFOByte(uint8_t data) {
+    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_FIFO_R_W, data);
+}
+
+// WHO_AM_I register
+
+/** Get Device ID.
+ * This register is used to verify the identity of the device (0b110100, 0x34).
+ * @return Device ID (6 bits only! should be 0x34)
+ * @see MPU6050_RA_WHO_AM_I
+ * @see MPU6050_WHO_AM_I_BIT
+ * @see MPU6050_WHO_AM_I_LENGTH
+ */
+uint8_t MPU6050_getDeviceID() {
+    I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_WHO_AM_I, MPU6050_WHO_AM_I_BIT, MPU6050_WHO_AM_I_LENGTH, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+/** Set Device ID.
+ * Write a new ID into the WHO_AM_I register (no idea why this should ever be
+ * necessary though).
+ * @param id New device ID to set.
+ * @see getDeviceID()
+ * @see MPU6050_RA_WHO_AM_I
+ * @see MPU6050_WHO_AM_I_BIT
+ * @see MPU6050_WHO_AM_I_LENGTH
+ */
+void MPU6050_setDeviceID(uint8_t id) {
+    I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_WHO_AM_I, MPU6050_WHO_AM_I_BIT, MPU6050_WHO_AM_I_LENGTH, id);
+}
+
+// ======== UNDOCUMENTED/DMP REGISTERS/METHODS ========
+
+// XG_OFFS_TC register
+
+uint8_t MPU6050_getOTPBankValid() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OTP_BNK_VLD_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setOTPBankValid(bool enabled) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OTP_BNK_VLD_BIT, enabled);
+}
+int8_t MPU6050_getXGyroOffsetTC() {
+    I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setXGyroOffsetTC(int8_t offset) {
+    I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset);
+}
+
+// YG_OFFS_TC register
+
+int8_t MPU6050_getYGyroOffsetTC() {
+    I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setYGyroOffsetTC(int8_t offset) {
+    I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset);
+}
+
+// ZG_OFFS_TC register
+
+int8_t MPU6050_getZGyroOffsetTC() {
+    I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_ZG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setZGyroOffsetTC(int8_t offset) {
+    I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_ZG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset);
+}
+
+// X_FINE_GAIN register
+
+int8_t MPU6050_getXFineGain() {
+    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_X_FINE_GAIN, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setXFineGain(int8_t gain) {
+    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_X_FINE_GAIN, gain);
+}
+
+// Y_FINE_GAIN register
+
+int8_t MPU6050_getYFineGain() {
+    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_Y_FINE_GAIN, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setYFineGain(int8_t gain) {
+    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_Y_FINE_GAIN, gain);
+}
+
+// Z_FINE_GAIN register
+
+int8_t MPU6050_getZFineGain() {
+    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_Z_FINE_GAIN, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setZFineGain(int8_t gain) {
+    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_Z_FINE_GAIN, gain);
+}
+
+// XA_OFFS_* registers
+
+int16_t MPU6050_getXAccelOffset() {
+    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_XA_OFFS_H, 2, mpu6050.buffer);
+    return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+}
+void MPU6050_setXAccelOffset(int16_t offset) {
+    I2Cdev_writeWord(mpu6050.devAddr, MPU6050_RA_XA_OFFS_H, offset);
+}
+
+// YA_OFFS_* register
+
+int16_t MPU6050_getYAccelOffset() {
+    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_YA_OFFS_H, 2, mpu6050.buffer);
+    return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+}
+void MPU6050_setYAccelOffset(int16_t offset) {
+    I2Cdev_writeWord(mpu6050.devAddr, MPU6050_RA_YA_OFFS_H, offset);
+}
+
+// ZA_OFFS_* register
+
+int16_t MPU6050_getZAccelOffset() {
+    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ZA_OFFS_H, 2, mpu6050.buffer);
+    return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+}
+void MPU6050_setZAccelOffset(int16_t offset) {
+    I2Cdev_writeWord(mpu6050.devAddr, MPU6050_RA_ZA_OFFS_H, offset);
+}
+
+// XG_OFFS_USR* registers
+
+int16_t MPU6050_getXGyroOffset() {
+    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_XG_OFFS_USRH, 2, mpu6050.buffer);
+    return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+}
+void MPU6050_setXGyroOffset(int16_t offset) {
+    I2Cdev_writeWord(mpu6050.devAddr, MPU6050_RA_XG_OFFS_USRH, offset);
+}
+
+// YG_OFFS_USR* register
+
+int16_t MPU6050_getYGyroOffset() {
+    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_YG_OFFS_USRH, 2, mpu6050.buffer);
+    return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+}
+void MPU6050_setYGyroOffset(int16_t offset) {
+    I2Cdev_writeWord(mpu6050.devAddr, MPU6050_RA_YG_OFFS_USRH, offset);
+}
+
+// ZG_OFFS_USR* register
+
+int16_t MPU6050_getZGyroOffset() {
+    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ZG_OFFS_USRH, 2, mpu6050.buffer);
+    return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+}
+void MPU6050_setZGyroOffset(int16_t offset) {
+    I2Cdev_writeWord(mpu6050.devAddr, MPU6050_RA_ZG_OFFS_USRH, offset);
+}
+
+// INT_ENABLE register (DMP functions)
+
+bool MPU6050_getIntPLLReadyEnabled() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setIntPLLReadyEnabled(bool enabled) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, enabled);
+}
+bool MPU6050_getIntDMPEnabled() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DMP_INT_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setIntDMPEnabled(bool enabled) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DMP_INT_BIT, enabled);
+}
+
+// DMP_INT_STATUS
+
+bool MPU6050_getDMPInt5Status() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_5_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+bool MPU6050_getDMPInt4Status() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_4_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+bool MPU6050_getDMPInt3Status() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_3_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+bool MPU6050_getDMPInt2Status() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_2_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+bool MPU6050_getDMPInt1Status() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_1_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+bool MPU6050_getDMPInt0Status() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_0_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+
+// INT_STATUS register (DMP functions)
+
+bool MPU6050_getIntPLLReadyStatus() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+bool MPU6050_getIntDMPStatus() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_DMP_INT_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+
+// USER_CTRL register (DMP functions)
+
+bool MPU6050_getDMPEnabled() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_EN_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setDMPEnabled(bool enabled) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_EN_BIT, enabled);
+}
+void MPU6050_resetDMP() {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_RESET_BIT, true);
+}
+
+// BANK_SEL register
+
+void MPU6050_setMemoryBank(uint8_t bank, bool prefetchEnabled, bool userBank) {
+    bank &= 0x1F;
+    if (userBank) bank |= 0x20;
+    if (prefetchEnabled) bank |= 0x40;
+    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_BANK_SEL, bank);
+}
+
+// MEM_START_ADDR register
+
+void MPU6050_setMemoryStartAddress(uint8_t address) {
+    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_MEM_START_ADDR, address);
+}
+
+// MEM_R_W register
+
+uint8_t MPU6050_readMemoryByte() {
+    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_MEM_R_W, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_writeMemoryByte(uint8_t data) {
+    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_MEM_R_W, data);
+}
+void MPU6050_readMemoryBlock(uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address) {
+    MPU6050_setMemoryBank(bank, false, false);
+    MPU6050_setMemoryStartAddress(address);
+    uint8_t chunkSize;
+    for (uint16_t i = 0; i < dataSize;) {
+        // determine correct chunk size according to bank position and data size
+        chunkSize = MPU6050_DMP_MEMORY_CHUNK_SIZE;
+
+        // make sure we don't go past the data size
+        if (i + chunkSize > dataSize) chunkSize = dataSize - i;
+
+        // make sure this chunk doesn't go past the bank boundary (256 bytes)
+        if (chunkSize > 256 - address) chunkSize = 256 - address;
+
+        // read the chunk of data as specified
+        I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_MEM_R_W, chunkSize, data + i);
+        
+        // increase byte index by [chunkSize]
+        i += chunkSize;
+
+        // uint8_t automatically wraps to 0 at 256
+        address += chunkSize;
+
+        // if we aren't done, update bank (if necessary) and address
+        if (i < dataSize) {
+            if (address == 0) bank++;
+            MPU6050_setMemoryBank(bank, false, false);
+            MPU6050_setMemoryStartAddress(address);
+        }
+    }
+}
+/*bool MPU6050_writeMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address, bool verify, bool useProgMem) {
+    MPU6050_setMemoryBank(bank, false, false);
+    MPU6050_setMemoryStartAddress(address);
+    uint8_t chunkSize;
+    uint8_t *verifyBuffer;
+    uint8_t *progBuffer;
+    uint16_t i;
+    uint8_t j;
+    if (verify) verifyBuffer = (uint8_t *)malloc(MPU6050_DMP_MEMORY_CHUNK_SIZE);
+    if (useProgMem) progBuffer = (uint8_t *)malloc(MPU6050_DMP_MEMORY_CHUNK_SIZE);
+    for (i = 0; i < dataSize;) {
+        // determine correct chunk size according to bank position and data size
+        chunkSize = MPU6050_DMP_MEMORY_CHUNK_SIZE;
+
+        // make sure we don't go past the data size
+        if (i + chunkSize > dataSize) chunkSize = dataSize - i;
+
+        // make sure this chunk doesn't go past the bank boundary (256 bytes)
+        if (chunkSize > 256 - address) chunkSize = 256 - address;
+        
+        if (useProgMem) {
+            // write the chunk of data as specified
+            for (j = 0; j < chunkSize; j++) progBuffer[j] = pgm_read_byte(data + i + j);
+        } else {
+            // write the chunk of data as specified
+            progBuffer = (uint8_t *)data + i;
+        }
+
+        I2Cdev_writeBytes(mpu6050.devAddr, MPU6050_RA_MEM_R_W, chunkSize, progBuffer);
+
+        // verify data if needed
+        if (verify && verifyBuffer) {
+            MPU6050_setMemoryBank(bank, false, false);
+            MPU6050_setMemoryStartAddress(address);
+            I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_MEM_R_W, chunkSize, verifyBuffer);
+            if (memcmp(progBuffer, verifyBuffer, chunkSize) != 0) {
+                //Serial.print("Block write verification error, bank ");
+                //Serial.print(bank, DEC);
+                //Serial.print(", address ");
+                //Serial.print(address, DEC);
+                //Serial.print("!\nExpected:");
+                //for (j = 0; j < chunkSize; j++) {
+                //    Serial.print(" 0x");
+                //    if (progBuffer[j] < 16) Serial.print("0");
+                //    Serial.print(progBuffer[j], HEX);
+                //}
+                //Serial.print("\nReceived:");
+                //for (uint8_t j = 0; j < chunkSize; j++) {
+                //    Serial.print(" 0x");
+                //    if (verifyBuffer[i + j] < 16) Serial.print("0");
+                //    Serial.print(verifyBuffer[i + j], HEX);
+                //}
+                Serial.print("\n");
+                free(verifyBuffer);
+                if (useProgMem) free(progBuffer);
+                return false; // uh oh.
+            }
+        }
+
+        // increase byte index by [chunkSize]
+        i += chunkSize;
+
+        // uint8_t automatically wraps to 0 at 256
+        address += chunkSize;
+
+        // if we aren't done, update bank (if necessary) and address
+        if (i < dataSize) {
+            if (address == 0) bank++;
+            MPU6050_setMemoryBank(bank, false, false);
+            MPU6050_setMemoryStartAddress(address);
+        }
+    }
+    if (verify) free(verifyBuffer);
+    if (useProgMem) free(progBuffer);
+    return true;
+}
+bool MPU6050_writeProgMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address, bool verify) {
+    return MPU6050_writeMemoryBlock(data, dataSize, bank, address, verify, true);
+}
+bool MPU6050_writeDMPConfigurationSet(const uint8_t *data, uint16_t dataSize, bool useProgMem) {
+    uint8_t *progBuffer, success, special;
+    uint16_t i, j;
+    if (useProgMem) {
+        progBuffer = (uint8_t *)malloc(8); // assume 8-byte blocks, realloc later if necessary
+    }
+
+    // config set data is a long string of blocks with the following structure:
+    // [bank] [offset] [length] [byte[0], byte[1], ..., byte[length]]
+    uint8_t bank, offset, length;
+    for (i = 0; i < dataSize;) {
+        if (useProgMem) {
+            bank = pgm_read_byte(data + i++);
+            offset = pgm_read_byte(data + i++);
+            length = pgm_read_byte(data + i++);
+        } else {
+            bank = data[i++];
+            offset = data[i++];
+            length = data[i++];
+        }
+
+        // write data or perform special action
+        if (length > 0) {
+            // regular block of data to write
+            //Serial.print("Writing config block to bank ");
+            //Serial.print(bank);
+            //Serial.print(", offset ");
+            //Serial.print(offset);
+            //Serial.print(", length=");
+            //Serial.println(length);
+            if (useProgMem) {
+                if (sizeof(progBuffer) < length) progBuffer = (uint8_t *)realloc(progBuffer, length);
+                for (j = 0; j < length; j++) progBuffer[j] = pgm_read_byte(data + i + j);
+            } else {
+                progBuffer = (uint8_t *)data + i;
+            }
+            success = MPU6050_writeMemoryBlock(progBuffer, length, bank, offset, true);
+            i += length;
+        } else {
+            // special instruction
+            // NOTE: this kind of behavior (what and when to do certain things)
+            // is totally undocumented. This code is in here based on observed
+            // behavior only, and exactly why (or even whether) it has to be here
+            // is anybody's guess for now.
+            if (useProgMem) {
+                special = pgm_read_byte(data + i++);
+            } else {
+                special = data[i++];
+            }
+            //Serial.print("Special command code ");
+            //Serial.print(special, HEX);
+            //Serial.println(" found...");
+            if (special == 0x01) {
+                // enable DMP-related interrupts
+                
+                //setIntZeroMotionEnabled(true);
+                //setIntFIFOBufferOverflowEnabled(true);
+                //setIntDMPEnabled(true);
+                I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, 0x32);  // single operation
+
+                success = true;
+            } else {
+                // unknown special command
+                success = false;
+            }
+        }
+        
+        if (!success) {
+            if (useProgMem) free(progBuffer);
+            return false; // uh oh
+        }
+    }
+    if (useProgMem) free(progBuffer);
+    return true;
+}
+bool MPU6050_writeProgDMPConfigurationSet(const uint8_t *data, uint16_t dataSize) {
+    return MPU6050_writeDMPConfigurationSet(data, dataSize, true);
+}*/
+
+// DMP_CFG_1 register
+
+uint8_t MPU6050_getDMPConfig1() {
+    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_DMP_CFG_1, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setDMPConfig1(uint8_t config) {
+    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_DMP_CFG_1, config);
+}
+
+// DMP_CFG_2 register
+
+uint8_t MPU6050_getDMPConfig2() {
+    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_DMP_CFG_2, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setDMPConfig2(uint8_t config) {
+    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_DMP_CFG_2, config);
+}
diff --git a/STM32/MPU6050/MPU6050.h b/STM32/MPU6050/MPU6050.h
new file mode 100644
index 00000000..6e4cf693
--- /dev/null
+++ b/STM32/MPU6050/MPU6050.h
@@ -0,0 +1,788 @@
+// I2Cdev library collection - MPU6050 I2C device class
+// Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00)
+// 10/3/2011 by Jeff Rowberg 
+// 11/28/2014 by Marton Sebok 
+//
+// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
+//
+// Changelog:
+//     ...        - ongoing debug release
+//     2014-11-28 - ported to PIC18 peripheral library from Arduino code
+//     2017-03-11 - tested basic functions on STM32
+
+// NOTE: THIS IS ONLY A PARIAL RELEASE. THIS DEVICE CLASS IS CURRENTLY UNDERGOING ACTIVE
+// DEVELOPMENT AND IS STILL MISSING SOME IMPORTANT FEATURES. PLEASE KEEP THIS IN MIND IF
+// YOU DECIDE TO USE THIS PARTICULAR CODE FOR ANYTHING.
+
+/* ============================================
+I2Cdev device library code is placed under the MIT license
+Copyright (c) 2012 Jeff Rowberg
+Copyright (c) 2014 Marton Sebok
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+===============================================
+*/
+
+#ifndef _MPU6050_H_
+#define _MPU6050_H_
+
+#include "I2Cdev.h"
+#include 
+
+#if ((defined MPU6050_INCLUDE_DMP_MOTIONAPPS20) || (defined MPU6050_INCLUDE_DMP_MOTIONAPPS41))
+    #error DMP is not supported yet
+#endif
+
+#define MPU6050_ADDRESS_AD0_LOW     0x68 // address pin low (GND), default for InvenSense evaluation board
+#define MPU6050_ADDRESS_AD0_HIGH    0x69 // address pin high (VCC)
+#define MPU6050_DEFAULT_ADDRESS     MPU6050_ADDRESS_AD0_LOW
+
+#define MPU6050_RA_XG_OFFS_TC       0x00 //[7] PWR_MODE, [6:1] XG_OFFS_TC, [0] OTP_BNK_VLD
+#define MPU6050_RA_YG_OFFS_TC       0x01 //[7] PWR_MODE, [6:1] YG_OFFS_TC, [0] OTP_BNK_VLD
+#define MPU6050_RA_ZG_OFFS_TC       0x02 //[7] PWR_MODE, [6:1] ZG_OFFS_TC, [0] OTP_BNK_VLD
+#define MPU6050_RA_X_FINE_GAIN      0x03 //[7:0] X_FINE_GAIN
+#define MPU6050_RA_Y_FINE_GAIN      0x04 //[7:0] Y_FINE_GAIN
+#define MPU6050_RA_Z_FINE_GAIN      0x05 //[7:0] Z_FINE_GAIN
+#define MPU6050_RA_XA_OFFS_H        0x06 //[15:0] XA_OFFS
+#define MPU6050_RA_XA_OFFS_L_TC     0x07
+#define MPU6050_RA_YA_OFFS_H        0x08 //[15:0] YA_OFFS
+#define MPU6050_RA_YA_OFFS_L_TC     0x09
+#define MPU6050_RA_ZA_OFFS_H        0x0A //[15:0] ZA_OFFS
+#define MPU6050_RA_ZA_OFFS_L_TC     0x0B
+#define MPU6050_RA_XG_OFFS_USRH     0x13 //[15:0] XG_OFFS_USR
+#define MPU6050_RA_XG_OFFS_USRL     0x14
+#define MPU6050_RA_YG_OFFS_USRH     0x15 //[15:0] YG_OFFS_USR
+#define MPU6050_RA_YG_OFFS_USRL     0x16
+#define MPU6050_RA_ZG_OFFS_USRH     0x17 //[15:0] ZG_OFFS_USR
+#define MPU6050_RA_ZG_OFFS_USRL     0x18
+#define MPU6050_RA_SMPLRT_DIV       0x19
+#define MPU6050_RA_CONFIG           0x1A
+#define MPU6050_RA_GYRO_CONFIG      0x1B
+#define MPU6050_RA_ACCEL_CONFIG     0x1C
+#define MPU6050_RA_FF_THR           0x1D
+#define MPU6050_RA_FF_DUR           0x1E
+#define MPU6050_RA_MOT_THR          0x1F
+#define MPU6050_RA_MOT_DUR          0x20
+#define MPU6050_RA_ZRMOT_THR        0x21
+#define MPU6050_RA_ZRMOT_DUR        0x22
+#define MPU6050_RA_FIFO_EN          0x23
+#define MPU6050_RA_I2C_MST_CTRL     0x24
+#define MPU6050_RA_I2C_SLV0_ADDR    0x25
+#define MPU6050_RA_I2C_SLV0_REG     0x26
+#define MPU6050_RA_I2C_SLV0_CTRL    0x27
+#define MPU6050_RA_I2C_SLV1_ADDR    0x28
+#define MPU6050_RA_I2C_SLV1_REG     0x29
+#define MPU6050_RA_I2C_SLV1_CTRL    0x2A
+#define MPU6050_RA_I2C_SLV2_ADDR    0x2B
+#define MPU6050_RA_I2C_SLV2_REG     0x2C
+#define MPU6050_RA_I2C_SLV2_CTRL    0x2D
+#define MPU6050_RA_I2C_SLV3_ADDR    0x2E
+#define MPU6050_RA_I2C_SLV3_REG     0x2F
+#define MPU6050_RA_I2C_SLV3_CTRL    0x30
+#define MPU6050_RA_I2C_SLV4_ADDR    0x31
+#define MPU6050_RA_I2C_SLV4_REG     0x32
+#define MPU6050_RA_I2C_SLV4_DO      0x33
+#define MPU6050_RA_I2C_SLV4_CTRL    0x34
+#define MPU6050_RA_I2C_SLV4_DI      0x35
+#define MPU6050_RA_I2C_MST_STATUS   0x36
+#define MPU6050_RA_INT_PIN_CFG      0x37
+#define MPU6050_RA_INT_ENABLE       0x38
+#define MPU6050_RA_DMP_INT_STATUS   0x39
+#define MPU6050_RA_INT_STATUS       0x3A
+#define MPU6050_RA_ACCEL_XOUT_H     0x3B
+#define MPU6050_RA_ACCEL_XOUT_L     0x3C
+#define MPU6050_RA_ACCEL_YOUT_H     0x3D
+#define MPU6050_RA_ACCEL_YOUT_L     0x3E
+#define MPU6050_RA_ACCEL_ZOUT_H     0x3F
+#define MPU6050_RA_ACCEL_ZOUT_L     0x40
+#define MPU6050_RA_TEMP_OUT_H       0x41
+#define MPU6050_RA_TEMP_OUT_L       0x42
+#define MPU6050_RA_GYRO_XOUT_H      0x43
+#define MPU6050_RA_GYRO_XOUT_L      0x44
+#define MPU6050_RA_GYRO_YOUT_H      0x45
+#define MPU6050_RA_GYRO_YOUT_L      0x46
+#define MPU6050_RA_GYRO_ZOUT_H      0x47
+#define MPU6050_RA_GYRO_ZOUT_L      0x48
+#define MPU6050_RA_EXT_SENS_DATA_00 0x49
+#define MPU6050_RA_EXT_SENS_DATA_01 0x4A
+#define MPU6050_RA_EXT_SENS_DATA_02 0x4B
+#define MPU6050_RA_EXT_SENS_DATA_03 0x4C
+#define MPU6050_RA_EXT_SENS_DATA_04 0x4D
+#define MPU6050_RA_EXT_SENS_DATA_05 0x4E
+#define MPU6050_RA_EXT_SENS_DATA_06 0x4F
+#define MPU6050_RA_EXT_SENS_DATA_07 0x50
+#define MPU6050_RA_EXT_SENS_DATA_08 0x51
+#define MPU6050_RA_EXT_SENS_DATA_09 0x52
+#define MPU6050_RA_EXT_SENS_DATA_10 0x53
+#define MPU6050_RA_EXT_SENS_DATA_11 0x54
+#define MPU6050_RA_EXT_SENS_DATA_12 0x55
+#define MPU6050_RA_EXT_SENS_DATA_13 0x56
+#define MPU6050_RA_EXT_SENS_DATA_14 0x57
+#define MPU6050_RA_EXT_SENS_DATA_15 0x58
+#define MPU6050_RA_EXT_SENS_DATA_16 0x59
+#define MPU6050_RA_EXT_SENS_DATA_17 0x5A
+#define MPU6050_RA_EXT_SENS_DATA_18 0x5B
+#define MPU6050_RA_EXT_SENS_DATA_19 0x5C
+#define MPU6050_RA_EXT_SENS_DATA_20 0x5D
+#define MPU6050_RA_EXT_SENS_DATA_21 0x5E
+#define MPU6050_RA_EXT_SENS_DATA_22 0x5F
+#define MPU6050_RA_EXT_SENS_DATA_23 0x60
+#define MPU6050_RA_MOT_DETECT_STATUS    0x61
+#define MPU6050_RA_I2C_SLV0_DO      0x63
+#define MPU6050_RA_I2C_SLV1_DO      0x64
+#define MPU6050_RA_I2C_SLV2_DO      0x65
+#define MPU6050_RA_I2C_SLV3_DO      0x66
+#define MPU6050_RA_I2C_MST_DELAY_CTRL   0x67
+#define MPU6050_RA_SIGNAL_PATH_RESET    0x68
+#define MPU6050_RA_MOT_DETECT_CTRL      0x69
+#define MPU6050_RA_USER_CTRL        0x6A
+#define MPU6050_RA_PWR_MGMT_1       0x6B
+#define MPU6050_RA_PWR_MGMT_2       0x6C
+#define MPU6050_RA_BANK_SEL         0x6D
+#define MPU6050_RA_MEM_START_ADDR   0x6E
+#define MPU6050_RA_MEM_R_W          0x6F
+#define MPU6050_RA_DMP_CFG_1        0x70
+#define MPU6050_RA_DMP_CFG_2        0x71
+#define MPU6050_RA_FIFO_COUNTH      0x72
+#define MPU6050_RA_FIFO_COUNTL      0x73
+#define MPU6050_RA_FIFO_R_W         0x74
+#define MPU6050_RA_WHO_AM_I         0x75
+
+#define MPU6050_TC_PWR_MODE_BIT     7
+#define MPU6050_TC_OFFSET_BIT       6
+#define MPU6050_TC_OFFSET_LENGTH    6
+#define MPU6050_TC_OTP_BNK_VLD_BIT  0
+
+#define MPU6050_VDDIO_LEVEL_VLOGIC  0
+#define MPU6050_VDDIO_LEVEL_VDD     1
+
+#define MPU6050_CFG_EXT_SYNC_SET_BIT    5
+#define MPU6050_CFG_EXT_SYNC_SET_LENGTH 3
+#define MPU6050_CFG_DLPF_CFG_BIT    2
+#define MPU6050_CFG_DLPF_CFG_LENGTH 3
+
+#define MPU6050_EXT_SYNC_DISABLED       0x0
+#define MPU6050_EXT_SYNC_TEMP_OUT_L     0x1
+#define MPU6050_EXT_SYNC_GYRO_XOUT_L    0x2
+#define MPU6050_EXT_SYNC_GYRO_YOUT_L    0x3
+#define MPU6050_EXT_SYNC_GYRO_ZOUT_L    0x4
+#define MPU6050_EXT_SYNC_ACCEL_XOUT_L   0x5
+#define MPU6050_EXT_SYNC_ACCEL_YOUT_L   0x6
+#define MPU6050_EXT_SYNC_ACCEL_ZOUT_L   0x7
+
+#define MPU6050_DLPF_BW_256         0x00
+#define MPU6050_DLPF_BW_188         0x01
+#define MPU6050_DLPF_BW_98          0x02
+#define MPU6050_DLPF_BW_42          0x03
+#define MPU6050_DLPF_BW_20          0x04
+#define MPU6050_DLPF_BW_10          0x05
+#define MPU6050_DLPF_BW_5           0x06
+
+#define MPU6050_GCONFIG_FS_SEL_BIT      4
+#define MPU6050_GCONFIG_FS_SEL_LENGTH   2
+
+#define MPU6050_GYRO_FS_250         0x00
+#define MPU6050_GYRO_FS_500         0x01
+#define MPU6050_GYRO_FS_1000        0x02
+#define MPU6050_GYRO_FS_2000        0x03
+
+#define MPU6050_ACONFIG_XA_ST_BIT           7
+#define MPU6050_ACONFIG_YA_ST_BIT           6
+#define MPU6050_ACONFIG_ZA_ST_BIT           5
+#define MPU6050_ACONFIG_AFS_SEL_BIT         4
+#define MPU6050_ACONFIG_AFS_SEL_LENGTH      2
+#define MPU6050_ACONFIG_ACCEL_HPF_BIT       2
+#define MPU6050_ACONFIG_ACCEL_HPF_LENGTH    3
+
+#define MPU6050_ACCEL_FS_2          0x00
+#define MPU6050_ACCEL_FS_4          0x01
+#define MPU6050_ACCEL_FS_8          0x02
+#define MPU6050_ACCEL_FS_16         0x03
+
+#define MPU6050_DHPF_RESET          0x00
+#define MPU6050_DHPF_5              0x01
+#define MPU6050_DHPF_2P5            0x02
+#define MPU6050_DHPF_1P25           0x03
+#define MPU6050_DHPF_0P63           0x04
+#define MPU6050_DHPF_HOLD           0x07
+
+#define MPU6050_TEMP_FIFO_EN_BIT    7
+#define MPU6050_XG_FIFO_EN_BIT      6
+#define MPU6050_YG_FIFO_EN_BIT      5
+#define MPU6050_ZG_FIFO_EN_BIT      4
+#define MPU6050_ACCEL_FIFO_EN_BIT   3
+#define MPU6050_SLV2_FIFO_EN_BIT    2
+#define MPU6050_SLV1_FIFO_EN_BIT    1
+#define MPU6050_SLV0_FIFO_EN_BIT    0
+
+#define MPU6050_MULT_MST_EN_BIT     7
+#define MPU6050_WAIT_FOR_ES_BIT     6
+#define MPU6050_SLV_3_FIFO_EN_BIT   5
+#define MPU6050_I2C_MST_P_NSR_BIT   4
+#define MPU6050_I2C_MST_CLK_BIT     3
+#define MPU6050_I2C_MST_CLK_LENGTH  4
+
+#define MPU6050_CLOCK_DIV_348       0x0
+#define MPU6050_CLOCK_DIV_333       0x1
+#define MPU6050_CLOCK_DIV_320       0x2
+#define MPU6050_CLOCK_DIV_308       0x3
+#define MPU6050_CLOCK_DIV_296       0x4
+#define MPU6050_CLOCK_DIV_286       0x5
+#define MPU6050_CLOCK_DIV_276       0x6
+#define MPU6050_CLOCK_DIV_267       0x7
+#define MPU6050_CLOCK_DIV_258       0x8
+#define MPU6050_CLOCK_DIV_500       0x9
+#define MPU6050_CLOCK_DIV_471       0xA
+#define MPU6050_CLOCK_DIV_444       0xB
+#define MPU6050_CLOCK_DIV_421       0xC
+#define MPU6050_CLOCK_DIV_400       0xD
+#define MPU6050_CLOCK_DIV_381       0xE
+#define MPU6050_CLOCK_DIV_364       0xF
+
+#define MPU6050_I2C_SLV_RW_BIT      7
+#define MPU6050_I2C_SLV_ADDR_BIT    6
+#define MPU6050_I2C_SLV_ADDR_LENGTH 7
+#define MPU6050_I2C_SLV_EN_BIT      7
+#define MPU6050_I2C_SLV_BYTE_SW_BIT 6
+#define MPU6050_I2C_SLV_REG_DIS_BIT 5
+#define MPU6050_I2C_SLV_GRP_BIT     4
+#define MPU6050_I2C_SLV_LEN_BIT     3
+#define MPU6050_I2C_SLV_LEN_LENGTH  4
+
+#define MPU6050_I2C_SLV4_RW_BIT         7
+#define MPU6050_I2C_SLV4_ADDR_BIT       6
+#define MPU6050_I2C_SLV4_ADDR_LENGTH    7
+#define MPU6050_I2C_SLV4_EN_BIT         7
+#define MPU6050_I2C_SLV4_INT_EN_BIT     6
+#define MPU6050_I2C_SLV4_REG_DIS_BIT    5
+#define MPU6050_I2C_SLV4_MST_DLY_BIT    4
+#define MPU6050_I2C_SLV4_MST_DLY_LENGTH 5
+
+#define MPU6050_MST_PASS_THROUGH_BIT    7
+#define MPU6050_MST_I2C_SLV4_DONE_BIT   6
+#define MPU6050_MST_I2C_LOST_ARB_BIT    5
+#define MPU6050_MST_I2C_SLV4_NACK_BIT   4
+#define MPU6050_MST_I2C_SLV3_NACK_BIT   3
+#define MPU6050_MST_I2C_SLV2_NACK_BIT   2
+#define MPU6050_MST_I2C_SLV1_NACK_BIT   1
+#define MPU6050_MST_I2C_SLV0_NACK_BIT   0
+
+#define MPU6050_INTCFG_INT_LEVEL_BIT        7
+#define MPU6050_INTCFG_INT_OPEN_BIT         6
+#define MPU6050_INTCFG_LATCH_INT_EN_BIT     5
+#define MPU6050_INTCFG_INT_RD_CLEAR_BIT     4
+#define MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT  3
+#define MPU6050_INTCFG_FSYNC_INT_EN_BIT     2
+#define MPU6050_INTCFG_I2C_BYPASS_EN_BIT    1
+#define MPU6050_INTCFG_CLKOUT_EN_BIT        0
+
+#define MPU6050_INTMODE_ACTIVEHIGH  0x00
+#define MPU6050_INTMODE_ACTIVELOW   0x01
+
+#define MPU6050_INTDRV_PUSHPULL     0x00
+#define MPU6050_INTDRV_OPENDRAIN    0x01
+
+#define MPU6050_INTLATCH_50USPULSE  0x00
+#define MPU6050_INTLATCH_WAITCLEAR  0x01
+
+#define MPU6050_INTCLEAR_STATUSREAD 0x00
+#define MPU6050_INTCLEAR_ANYREAD    0x01
+
+#define MPU6050_INTERRUPT_FF_BIT            7
+#define MPU6050_INTERRUPT_MOT_BIT           6
+#define MPU6050_INTERRUPT_ZMOT_BIT          5
+#define MPU6050_INTERRUPT_FIFO_OFLOW_BIT    4
+#define MPU6050_INTERRUPT_I2C_MST_INT_BIT   3
+#define MPU6050_INTERRUPT_PLL_RDY_INT_BIT   2
+#define MPU6050_INTERRUPT_DMP_INT_BIT       1
+#define MPU6050_INTERRUPT_DATA_RDY_BIT      0
+
+// TODO: figure out what these actually do
+// UMPL source code is not very obivous
+#define MPU6050_DMPINT_5_BIT            5
+#define MPU6050_DMPINT_4_BIT            4
+#define MPU6050_DMPINT_3_BIT            3
+#define MPU6050_DMPINT_2_BIT            2
+#define MPU6050_DMPINT_1_BIT            1
+#define MPU6050_DMPINT_0_BIT            0
+
+#define MPU6050_MOTION_MOT_XNEG_BIT     7
+#define MPU6050_MOTION_MOT_XPOS_BIT     6
+#define MPU6050_MOTION_MOT_YNEG_BIT     5
+#define MPU6050_MOTION_MOT_YPOS_BIT     4
+#define MPU6050_MOTION_MOT_ZNEG_BIT     3
+#define MPU6050_MOTION_MOT_ZPOS_BIT     2
+#define MPU6050_MOTION_MOT_ZRMOT_BIT    0
+
+#define MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT   7
+#define MPU6050_DELAYCTRL_I2C_SLV4_DLY_EN_BIT   4
+#define MPU6050_DELAYCTRL_I2C_SLV3_DLY_EN_BIT   3
+#define MPU6050_DELAYCTRL_I2C_SLV2_DLY_EN_BIT   2
+#define MPU6050_DELAYCTRL_I2C_SLV1_DLY_EN_BIT   1
+#define MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT   0
+
+#define MPU6050_PATHRESET_GYRO_RESET_BIT    2
+#define MPU6050_PATHRESET_ACCEL_RESET_BIT   1
+#define MPU6050_PATHRESET_TEMP_RESET_BIT    0
+
+#define MPU6050_DETECT_ACCEL_ON_DELAY_BIT       5
+#define MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH    2
+#define MPU6050_DETECT_FF_COUNT_BIT             3
+#define MPU6050_DETECT_FF_COUNT_LENGTH          2
+#define MPU6050_DETECT_MOT_COUNT_BIT            1
+#define MPU6050_DETECT_MOT_COUNT_LENGTH         2
+
+#define MPU6050_DETECT_DECREMENT_RESET  0x0
+#define MPU6050_DETECT_DECREMENT_1      0x1
+#define MPU6050_DETECT_DECREMENT_2      0x2
+#define MPU6050_DETECT_DECREMENT_4      0x3
+
+#define MPU6050_USERCTRL_DMP_EN_BIT             7
+#define MPU6050_USERCTRL_FIFO_EN_BIT            6
+#define MPU6050_USERCTRL_I2C_MST_EN_BIT         5
+#define MPU6050_USERCTRL_I2C_IF_DIS_BIT         4
+#define MPU6050_USERCTRL_DMP_RESET_BIT          3
+#define MPU6050_USERCTRL_FIFO_RESET_BIT         2
+#define MPU6050_USERCTRL_I2C_MST_RESET_BIT      1
+#define MPU6050_USERCTRL_SIG_COND_RESET_BIT     0
+
+#define MPU6050_PWR1_DEVICE_RESET_BIT   7
+#define MPU6050_PWR1_SLEEP_BIT          6
+#define MPU6050_PWR1_CYCLE_BIT          5
+#define MPU6050_PWR1_TEMP_DIS_BIT       3
+#define MPU6050_PWR1_CLKSEL_BIT         2
+#define MPU6050_PWR1_CLKSEL_LENGTH      3
+
+#define MPU6050_CLOCK_INTERNAL          0x00
+#define MPU6050_CLOCK_PLL_XGYRO         0x01
+#define MPU6050_CLOCK_PLL_YGYRO         0x02
+#define MPU6050_CLOCK_PLL_ZGYRO         0x03
+#define MPU6050_CLOCK_PLL_EXT32K        0x04
+#define MPU6050_CLOCK_PLL_EXT19M        0x05
+#define MPU6050_CLOCK_KEEP_RESET        0x07
+
+#define MPU6050_PWR2_LP_WAKE_CTRL_BIT       7
+#define MPU6050_PWR2_LP_WAKE_CTRL_LENGTH    2
+#define MPU6050_PWR2_STBY_XA_BIT            5
+#define MPU6050_PWR2_STBY_YA_BIT            4
+#define MPU6050_PWR2_STBY_ZA_BIT            3
+#define MPU6050_PWR2_STBY_XG_BIT            2
+#define MPU6050_PWR2_STBY_YG_BIT            1
+#define MPU6050_PWR2_STBY_ZG_BIT            0
+
+#define MPU6050_WAKE_FREQ_1P25      0x0
+#define MPU6050_WAKE_FREQ_2P5       0x1
+#define MPU6050_WAKE_FREQ_5         0x2
+#define MPU6050_WAKE_FREQ_10        0x3
+
+#define MPU6050_BANKSEL_PRFTCH_EN_BIT       6
+#define MPU6050_BANKSEL_CFG_USER_BANK_BIT   5
+#define MPU6050_BANKSEL_MEM_SEL_BIT         4
+#define MPU6050_BANKSEL_MEM_SEL_LENGTH      5
+
+#define MPU6050_WHO_AM_I_BIT        6
+#define MPU6050_WHO_AM_I_LENGTH     6
+
+#define MPU6050_DMP_MEMORY_BANKS        8
+#define MPU6050_DMP_MEMORY_BANK_SIZE    256
+#define MPU6050_DMP_MEMORY_CHUNK_SIZE   16
+
+// note: DMP code memory blocks defined at end of header file
+
+typedef struct MPU6050_t {
+    uint8_t devAddr;
+    uint8_t buffer[14];
+} MPU6050_t;
+
+void MPU6050(uint8_t address);
+
+void MPU6050_initialize();
+bool MPU6050_testConnection();
+
+// AUX_VDDIO register
+uint8_t MPU6050_getAuxVDDIOLevel();
+void MPU6050_setAuxVDDIOLevel(uint8_t level);
+
+// SMPLRT_DIV register
+uint8_t MPU6050_getRate();
+void MPU6050_setRate(uint8_t rate);
+
+// CONFIG register
+uint8_t MPU6050_getExternalFrameSync();
+void MPU6050_setExternalFrameSync(uint8_t sync);
+uint8_t MPU6050_getDLPFMode();
+void MPU6050_setDLPFMode(uint8_t bandwidth);
+
+// GYRO_CONFIG register
+uint8_t MPU6050_getFullScaleGyroRange();
+void MPU6050_setFullScaleGyroRange(uint8_t range);
+
+// ACCEL_CONFIG register
+bool MPU6050_getAccelXSelfTest();
+void MPU6050_setAccelXSelfTest(bool enabled);
+bool MPU6050_getAccelYSelfTest();
+void MPU6050_setAccelYSelfTest(bool enabled);
+bool MPU6050_getAccelZSelfTest();
+void MPU6050_setAccelZSelfTest(bool enabled);
+uint8_t MPU6050_getFullScaleAccelRange();
+void MPU6050_setFullScaleAccelRange(uint8_t range);
+uint8_t MPU6050_getDHPFMode();
+void MPU6050_setDHPFMode(uint8_t mode);
+
+// FF_THR register
+uint8_t MPU6050_getFreefallDetectionThreshold();
+void MPU6050_setFreefallDetectionThreshold(uint8_t threshold);
+
+// FF_DUR register
+uint8_t MPU6050_getFreefallDetectionDuration();
+void MPU6050_setFreefallDetectionDuration(uint8_t duration);
+
+// MOT_THR register
+uint8_t MPU6050_getMotionDetectionThreshold();
+void MPU6050_setMotionDetectionThreshold(uint8_t threshold);
+
+// MOT_DUR register
+uint8_t MPU6050_getMotionDetectionDuration();
+void MPU6050_setMotionDetectionDuration(uint8_t duration);
+
+// ZRMOT_THR register
+uint8_t MPU6050_getZeroMotionDetectionThreshold();
+void MPU6050_setZeroMotionDetectionThreshold(uint8_t threshold);
+
+// ZRMOT_DUR register
+uint8_t MPU6050_getZeroMotionDetectionDuration();
+void MPU6050_setZeroMotionDetectionDuration(uint8_t duration);
+
+// FIFO_EN register
+bool MPU6050_getTempFIFOEnabled();
+void MPU6050_setTempFIFOEnabled(bool enabled);
+bool MPU6050_getXGyroFIFOEnabled();
+void MPU6050_setXGyroFIFOEnabled(bool enabled);
+bool MPU6050_getYGyroFIFOEnabled();
+void MPU6050_setYGyroFIFOEnabled(bool enabled);
+bool MPU6050_getZGyroFIFOEnabled();
+void MPU6050_setZGyroFIFOEnabled(bool enabled);
+bool MPU6050_getAccelFIFOEnabled();
+void MPU6050_setAccelFIFOEnabled(bool enabled);
+bool MPU6050_getSlave2FIFOEnabled();
+void MPU6050_setSlave2FIFOEnabled(bool enabled);
+bool MPU6050_getSlave1FIFOEnabled();
+void MPU6050_setSlave1FIFOEnabled(bool enabled);
+bool MPU6050_getSlave0FIFOEnabled();
+void MPU6050_setSlave0FIFOEnabled(bool enabled);
+
+// I2C_MST_CTRL register
+bool MPU6050_getMultiMasterEnabled();
+void MPU6050_setMultiMasterEnabled(bool enabled);
+bool MPU6050_getWaitForExternalSensorEnabled();
+void MPU6050_setWaitForExternalSensorEnabled(bool enabled);
+bool MPU6050_getSlave3FIFOEnabled();
+void MPU6050_setSlave3FIFOEnabled(bool enabled);
+bool MPU6050_getSlaveReadWriteTransitionEnabled();
+void MPU6050_setSlaveReadWriteTransitionEnabled(bool enabled);
+uint8_t MPU6050_getMasterClockSpeed();
+void MPU6050_setMasterClockSpeed(uint8_t speed);
+
+// I2C_SLV* registers (Slave 0-3)
+uint8_t MPU6050_getSlaveAddress(uint8_t num);
+void MPU6050_setSlaveAddress(uint8_t num, uint8_t address);
+uint8_t MPU6050_getSlaveRegister(uint8_t num);
+void MPU6050_setSlaveRegister(uint8_t num, uint8_t reg);
+bool MPU6050_getSlaveEnabled(uint8_t num);
+void MPU6050_setSlaveEnabled(uint8_t num, bool enabled);
+bool MPU6050_getSlaveWordByteSwap(uint8_t num);
+void MPU6050_setSlaveWordByteSwap(uint8_t num, bool enabled);
+bool MPU6050_getSlaveWriteMode(uint8_t num);
+void MPU6050_setSlaveWriteMode(uint8_t num, bool mode);
+bool MPU6050_getSlaveWordGroupOffset(uint8_t num);
+void MPU6050_setSlaveWordGroupOffset(uint8_t num, bool enabled);
+uint8_t MPU6050_getSlaveDataLength(uint8_t num);
+void MPU6050_setSlaveDataLength(uint8_t num, uint8_t length);
+
+// I2C_SLV* registers (Slave 4)
+uint8_t MPU6050_getSlave4Address();
+void MPU6050_setSlave4Address(uint8_t address);
+uint8_t MPU6050_getSlave4Register();
+void MPU6050_setSlave4Register(uint8_t reg);
+void MPU6050_setSlave4OutputByte(uint8_t data);
+bool MPU6050_getSlave4Enabled();
+void MPU6050_setSlave4Enabled(bool enabled);
+bool MPU6050_getSlave4InterruptEnabled();
+void MPU6050_setSlave4InterruptEnabled(bool enabled);
+bool MPU6050_getSlave4WriteMode();
+void MPU6050_setSlave4WriteMode(bool mode);
+uint8_t MPU6050_getSlave4MasterDelay();
+void MPU6050_setSlave4MasterDelay(uint8_t delay);
+uint8_t MPU6050_getSlate4InputByte();
+
+// I2C_MST_STATUS register
+bool MPU6050_getPassthroughStatus();
+bool MPU6050_getSlave4IsDone();
+bool MPU6050_getLostArbitration();
+bool MPU6050_getSlave4Nack();
+bool MPU6050_getSlave3Nack();
+bool MPU6050_getSlave2Nack();
+bool MPU6050_getSlave1Nack();
+bool MPU6050_getSlave0Nack();
+
+// INT_PIN_CFG register
+bool MPU6050_getInterruptMode();
+void MPU6050_setInterruptMode(bool mode);
+bool MPU6050_getInterruptDrive();
+void MPU6050_setInterruptDrive(bool drive);
+bool MPU6050_getInterruptLatch();
+void MPU6050_setInterruptLatch(bool latch);
+bool MPU6050_getInterruptLatchClear();
+void MPU6050_setInterruptLatchClear(bool clear);
+bool MPU6050_getFSyncInterruptLevel();
+void MPU6050_setFSyncInterruptLevel(bool level);
+bool MPU6050_getFSyncInterruptEnabled();
+void MPU6050_setFSyncInterruptEnabled(bool enabled);
+bool MPU6050_getI2CBypassEnabled();
+void MPU6050_setI2CBypassEnabled(bool enabled);
+bool MPU6050_getClockOutputEnabled();
+void MPU6050_setClockOutputEnabled(bool enabled);
+
+// INT_ENABLE register
+uint8_t MPU6050_getIntEnabled();
+void MPU6050_setIntEnabled(uint8_t enabled);
+bool MPU6050_getIntFreefallEnabled();
+void MPU6050_setIntFreefallEnabled(bool enabled);
+bool MPU6050_getIntMotionEnabled();
+void MPU6050_setIntMotionEnabled(bool enabled);
+bool MPU6050_getIntZeroMotionEnabled();
+void MPU6050_setIntZeroMotionEnabled(bool enabled);
+bool MPU6050_getIntFIFOBufferOverflowEnabled();
+void MPU6050_setIntFIFOBufferOverflowEnabled(bool enabled);
+bool MPU6050_getIntI2CMasterEnabled();
+void MPU6050_setIntI2CMasterEnabled(bool enabled);
+bool MPU6050_getIntDataReadyEnabled();
+void MPU6050_setIntDataReadyEnabled(bool enabled);
+
+// INT_STATUS register
+uint8_t MPU6050_getIntStatus();
+bool MPU6050_getIntFreefallStatus();
+bool MPU6050_getIntMotionStatus();
+bool MPU6050_getIntZeroMotionStatus();
+bool MPU6050_getIntFIFOBufferOverflowStatus();
+bool MPU6050_getIntI2CMasterStatus();
+bool MPU6050_getIntDataReadyStatus();
+
+// ACCEL_*OUT_* registers
+void MPU6050_getMotion9(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz, int16_t* mx, int16_t* my, int16_t* mz);
+void MPU6050_getMotion6(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz);
+void MPU6050_getAcceleration(int16_t* x, int16_t* y, int16_t* z);
+int16_t MPU6050_getAccelerationX();
+int16_t MPU6050_getAccelerationY();
+int16_t MPU6050_getAccelerationZ();
+
+// TEMP_OUT_* registers
+int16_t MPU6050_getTemperature();
+
+// GYRO_*OUT_* registers
+void MPU6050_getRotation(int16_t* x, int16_t* y, int16_t* z);
+int16_t MPU6050_getRotationX();
+int16_t MPU6050_getRotationY();
+int16_t MPU6050_getRotationZ();
+
+// EXT_SENS_DATA_* registers
+uint8_t MPU6050_getExternalSensorByte(int position);
+uint16_t MPU6050_getExternalSensorWord(int position);
+uint32_t getExternalSensorDWord(int position);
+
+// MOT_DETECT_STATUS register
+bool MPU6050_getXNegMotionDetected();
+bool MPU6050_getXPosMotionDetected();
+bool MPU6050_getYNegMotionDetected();
+bool MPU6050_getYPosMotionDetected();
+bool MPU6050_getZNegMotionDetected();
+bool MPU6050_getZPosMotionDetected();
+bool MPU6050_getZeroMotionDetected();
+
+// I2C_SLV*_DO register
+void MPU6050_setSlaveOutputByte(uint8_t num, uint8_t data);
+
+// I2C_MST_DELAY_CTRL register
+bool MPU6050_getExternalShadowDelayEnabled();
+void MPU6050_setExternalShadowDelayEnabled(bool enabled);
+bool MPU6050_getSlaveDelayEnabled(uint8_t num);
+void MPU6050_setSlaveDelayEnabled(uint8_t num, bool enabled);
+
+// SIGNAL_PATH_RESET register
+void MPU6050_resetGyroscopePath();
+void MPU6050_resetAccelerometerPath();
+void MPU6050_resetTemperaturePath();
+
+// MOT_DETECT_CTRL register
+uint8_t MPU6050_getAccelerometerPowerOnDelay();
+void MPU6050_setAccelerometerPowerOnDelay(uint8_t delay);
+uint8_t MPU6050_getFreefallDetectionCounterDecrement();
+void MPU6050_setFreefallDetectionCounterDecrement(uint8_t decrement);
+uint8_t MPU6050_getMotionDetectionCounterDecrement();
+void MPU6050_setMotionDetectionCounterDecrement(uint8_t decrement);
+
+// USER_CTRL register
+bool MPU6050_getFIFOEnabled();
+void MPU6050_setFIFOEnabled(bool enabled);
+bool MPU6050_getI2CMasterModeEnabled();
+void MPU6050_setI2CMasterModeEnabled(bool enabled);
+void MPU6050_switchSPIEnabled(bool enabled);
+void MPU6050_resetFIFO();
+void MPU6050_resetI2CMaster();
+void MPU6050_resetSensors();
+
+// PWR_MGMT_1 register
+void MPU6050_reset();
+bool MPU6050_getSleepEnabled();
+void MPU6050_setSleepEnabled(bool enabled);
+bool MPU6050_getWakeCycleEnabled();
+void MPU6050_setWakeCycleEnabled(bool enabled);
+bool MPU6050_getTempSensorEnabled();
+void MPU6050_setTempSensorEnabled(bool enabled);
+uint8_t MPU6050_getClockSource();
+void MPU6050_setClockSource(uint8_t source);
+
+// PWR_MGMT_2 register
+uint8_t MPU6050_getWakeFrequency();
+void MPU6050_setWakeFrequency(uint8_t frequency);
+bool MPU6050_getStandbyXAccelEnabled();
+void MPU6050_setStandbyXAccelEnabled(bool enabled);
+bool MPU6050_getStandbyYAccelEnabled();
+void MPU6050_setStandbyYAccelEnabled(bool enabled);
+bool MPU6050_getStandbyZAccelEnabled();
+void MPU6050_setStandbyZAccelEnabled(bool enabled);
+bool MPU6050_getStandbyXGyroEnabled();
+void MPU6050_setStandbyXGyroEnabled(bool enabled);
+bool MPU6050_getStandbyYGyroEnabled();
+void MPU6050_setStandbyYGyroEnabled(bool enabled);
+bool MPU6050_getStandbyZGyroEnabled();
+void MPU6050_setStandbyZGyroEnabled(bool enabled);
+
+// FIFO_COUNT_* registers
+uint16_t MPU6050_getFIFOCount();
+
+// FIFO_R_W register
+uint8_t MPU6050_getFIFOByte();
+void MPU6050_setFIFOByte(uint8_t data);
+void MPU6050_getFIFOBytes(uint8_t *data, uint8_t length);
+
+// WHO_AM_I register
+uint8_t MPU6050_getDeviceID();
+void MPU6050_setDeviceID(uint8_t id);
+
+// ======== UNDOCUMENTED/DMP REGISTERS/METHODS ========
+
+// XG_OFFS_TC register
+uint8_t MPU6050_getOTPBankValid();
+void MPU6050_setOTPBankValid(bool enabled);
+int8_t getXGyroOffsetTC();
+void MPU6050_setXGyroOffsetTC(int8_t offset);
+
+// YG_OFFS_TC register
+int8_t getYGyroOffsetTC();
+void MPU6050_setYGyroOffsetTC(int8_t offset);
+
+// ZG_OFFS_TC register
+int8_t getZGyroOffsetTC();
+void MPU6050_setZGyroOffsetTC(int8_t offset);
+
+// X_FINE_GAIN register
+int8_t getXFineGain();
+void MPU6050_setXFineGain(int8_t gain);
+
+// Y_FINE_GAIN register
+int8_t getYFineGain();
+void MPU6050_setYFineGain(int8_t gain);
+
+// Z_FINE_GAIN register
+int8_t getZFineGain();
+void MPU6050_setZFineGain(int8_t gain);
+
+// XA_OFFS_* registers
+int16_t MPU6050_getXAccelOffset();
+void MPU6050_setXAccelOffset(int16_t offset);
+
+// YA_OFFS_* register
+int16_t MPU6050_getYAccelOffset();
+void MPU6050_setYAccelOffset(int16_t offset);
+
+// ZA_OFFS_* register
+int16_t MPU6050_getZAccelOffset();
+void MPU6050_setZAccelOffset(int16_t offset);
+
+// XG_OFFS_USR* registers
+int16_t MPU6050_getXGyroOffset();
+void MPU6050_setXGyroOffset(int16_t offset);
+
+// YG_OFFS_USR* register
+int16_t MPU6050_getYGyroOffset();
+void MPU6050_setYGyroOffset(int16_t offset);
+
+// ZG_OFFS_USR* register
+int16_t MPU6050_getZGyroOffset();
+void MPU6050_setZGyroOffset(int16_t offset);
+
+// INT_ENABLE register (DMP functions)
+bool MPU6050_getIntPLLReadyEnabled();
+void MPU6050_setIntPLLReadyEnabled(bool enabled);
+bool MPU6050_getIntDMPEnabled();
+void MPU6050_setIntDMPEnabled(bool enabled);
+
+// DMP_INT_STATUS
+bool MPU6050_getDMPInt5Status();
+bool MPU6050_getDMPInt4Status();
+bool MPU6050_getDMPInt3Status();
+bool MPU6050_getDMPInt2Status();
+bool MPU6050_getDMPInt1Status();
+bool MPU6050_getDMPInt0Status();
+
+// INT_STATUS register (DMP functions)
+bool MPU6050_getIntPLLReadyStatus();
+bool MPU6050_getIntDMPStatus();
+
+// USER_CTRL register (DMP functions)
+bool MPU6050_getDMPEnabled();
+void MPU6050_setDMPEnabled(bool enabled);
+void MPU6050_resetDMP();
+
+// BANK_SEL register
+void MPU6050_setMemoryBank(uint8_t bank, bool prefetchEnabled, bool userBank);
+
+// MEM_START_ADDR register
+void MPU6050_setMemoryStartAddress(uint8_t address);
+
+// MEM_R_W register
+uint8_t MPU6050_readMemoryByte();
+void MPU6050_writeMemoryByte(uint8_t data);
+void MPU6050_readMemoryBlock(uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address);
+//bool MPU6050_writeMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address, bool verify, bool useProgMem);
+//bool MPU6050_writeProgMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address, bool verify);
+
+//bool MPU6050_writeDMPConfigurationSet(const uint8_t *data, uint16_t dataSize, bool useProgMem);
+//bool MPU6050_writeProgDMPConfigurationSet(const uint8_t *data, uint16_t dataSize);
+
+// DMP_CFG_1 register
+uint8_t MPU6050_getDMPConfig1();
+void MPU6050_setDMPConfig1(uint8_t config);
+
+// DMP_CFG_2 register
+uint8_t MPU6050_getDMPConfig2();
+void MPU6050_setDMPConfig2(uint8_t config);
+
+#endif /* _MPU6050_H_ */
diff --git a/STM32/README.md b/STM32/README.md
new file mode 100644
index 00000000..577cf33e
--- /dev/null
+++ b/STM32/README.md
@@ -0,0 +1,15 @@
+# I2C Device Library for STM32
+
+## I2Cdev
+For implementing I2Cdev [Keil MDK Pack](https://www.keil.com/dd2/pack/) is used. It has many advantages comparing to HAL/SPL. The most
+crucial one is that of compatibility: using it makes I2Cdev compatible with any device listed on MDK Pack software page. All you need is to download pack for your device and enable your driver.
+
+## Devices
+Supported devices are MPU6050 without DMP and HMC5883. Actually I did not find any differences in registers between HMC5883 and HMC5983 therefore the latter might work as well.
+
+Porting other devices should be easy and any help is appreciated.
+
+## Licence
+I2Cdev device library code is placed under the MIT license.
+
+_Copyright (c) 2011 Jeff Rowberg. Copyright (c) 2017 Kamnev Yuriy._

From ef9964fafaa54168e7c26e42d2460f02a5897547 Mon Sep 17 00:00:00 2001
From: kripton 
Date: Tue, 28 Mar 2017 17:03:55 +0300
Subject: [PATCH 167/335] Fixed changelog description

---
 STM32/I2Cdev.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/STM32/I2Cdev.h b/STM32/I2Cdev.h
index f28be56a..ca450787 100644
--- a/STM32/I2Cdev.h
+++ b/STM32/I2Cdev.h
@@ -4,7 +4,7 @@
 // 03/28/2017 by Kamnev Yuriy 
 //
 // Changelog:
-//     2017-03-28 - ported to STM32 peripheral library from Arduino code
+//     2017-03-28 - ported to STM32 using Keil MDK Pack
 
 /* ============================================
 I2Cdev device library code is placed under the MIT license

From 454b014e0e228a16ae222aa91d6072c72ad5d4d2 Mon Sep 17 00:00:00 2001
From: kripton 
Date: Tue, 28 Mar 2017 17:28:42 +0300
Subject: [PATCH 168/335] More descriptions

---
 STM32/README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/STM32/README.md b/STM32/README.md
index 577cf33e..20de58f8 100644
--- a/STM32/README.md
+++ b/STM32/README.md
@@ -2,7 +2,7 @@
 
 ## I2Cdev
 For implementing I2Cdev [Keil MDK Pack](https://www.keil.com/dd2/pack/) is used. It has many advantages comparing to HAL/SPL. The most
-crucial one is that of compatibility: using it makes I2Cdev compatible with any device listed on MDK Pack software page. All you need is to download pack for your device and enable your driver.
+crucial one is that of compatibility: using it makes I2Cdev compatible with any device listed on MDK Pack software page. All you need is to download pack for your device, enable your driver and specify used peripherial in I2Cdev.h.
 
 ## Devices
 Supported devices are MPU6050 without DMP and HMC5883. Actually I did not find any differences in registers between HMC5883 and HMC5983 therefore the latter might work as well.

From df92b1866db3f7d6b660d6cca4cd3fda78de58bd Mon Sep 17 00:00:00 2001
From: kripton 
Date: Tue, 28 Mar 2017 17:28:56 +0300
Subject: [PATCH 169/335] Added comments to functions

---
 STM32/I2Cdev.c | 143 +++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 120 insertions(+), 23 deletions(-)

diff --git a/STM32/I2Cdev.c b/STM32/I2Cdev.c
index 5940d2e7..5be44cf3 100644
--- a/STM32/I2Cdev.c
+++ b/STM32/I2Cdev.c
@@ -56,7 +56,13 @@ extern ARM_DRIVER_I2C I2CDev_Driver;
 #define i2c_receive_nack(dev_addr, data, len)	_i2c_receive(dev_addr, data, len, false)
 
 
-
+/** Read several byte from an 8-bit device register.
+ * @param dev_addr 	I2C slave device address
+ * @param reg_addr 	Register regAddr to read from
+ * @param len 		How many bytes to read
+ * @param data 		Buffer to save data into
+ * @return Status of read operation (0 = success, <0 = error)
+ */
 int8_t I2Cdev_readBytes(uint8_t dev_addr, uint8_t reg_addr, uint8_t len, uint8_t *data) {
 	int8_t err = 0;
 	uint8_t reg_data[1] = {reg_addr};
@@ -73,17 +79,26 @@ int8_t I2Cdev_readBytes(uint8_t dev_addr, uint8_t reg_addr, uint8_t len, uint8_t
 }
 
 
+/** Read a single byte from a 8-bit device register.
+ * @param dev_addr 	I2C slave device address
+ * @param reg_addr 	Register reg_addr to read from
+ * @param data 		Buffer to save data into
+ * @return Status of read operation (0 = success, <0 = error)
+ */
 int8_t 	I2Cdev_readByte(uint8_t dev_addr, uint8_t reg_addr, uint8_t *data) {
-	int8_t err;
-
-	err = I2Cdev_readBytes(dev_addr, reg_addr, 1, data);
-	return err;
+	return I2Cdev_readBytes(dev_addr, reg_addr, 1, data);
 }
 
 
+/** Read a several 16-bit words from a 16-bit device register.
+ * @param dev_addr 	I2C slave device address
+ * @param reg_addr 	Register reg_addr to read from
+ * @param len		Number of words to read
+ * @param data 		Buffer to save data into
+ * @return Status of read operation (true = success)
+ */
 int8_t 	I2Cdev_readWords(uint8_t dev_addr, uint8_t reg_addr, uint8_t len, uint16_t *data) {
 	int8_t err;
-
 	uint16_t bytes_num = len*2;
 
 	uint8_t reg_info[1] = {reg_addr};
@@ -109,17 +124,25 @@ int8_t 	I2Cdev_readWords(uint8_t dev_addr, uint8_t reg_addr, uint8_t len, uint16
 }
 
 
+/** Read a single word from a 16-bit device register.
+ * @param dev_addr 	I2C slave device address
+ * @param reg_addr 	Register regAddr to read from
+ * @param data 		Container for single word
+ * @return Status of read operation (0 = success, <0 = error)
+ */
 int8_t 	I2Cdev_readWord(uint8_t dev_addr, uint8_t reg_addr, uint16_t *data) {
-	int8_t err;
-
-	err = I2Cdev_readWords(dev_addr, reg_addr, 1, data);
-	return err;
+	return I2Cdev_readWords(dev_addr, reg_addr, 1, data);
 }
 
 
-int8_t
-I2Cdev_readBit(uint8_t dev_addr, uint8_t reg_addr, uint8_t bitn, uint8_t *data)
-{
+/** Read a single bit from a 8-bit device register.
+ * @param dev_addr 	I2C slave device address
+ * @param reg_addr 	Register regAddr to read from
+ * @param bitn 		Bit position to read (0-15)
+ * @param data 		Container for single bit value
+ * @return Status of read operation (0 = success, <0 = error)
+ */
+int8_t I2Cdev_readBit(uint8_t dev_addr, uint8_t reg_addr, uint8_t bitn, uint8_t *data) {
 	int8_t err;
 
 	err = I2Cdev_readByte(dev_addr, reg_addr, data);
@@ -129,9 +152,16 @@ I2Cdev_readBit(uint8_t dev_addr, uint8_t reg_addr, uint8_t bitn, uint8_t *data)
 }
 
 
-int8_t
-I2Cdev_readBits(uint8_t dev_addr, uint8_t reg_addr, uint8_t start_bit,
-		uint8_t len, uint8_t *data)
+/** Read several bits from a 8-bit device register.
+ * @param dev_addr 	I2C slave device address
+ * @param reg_addr 	Register regAddr to read from
+ * @param start_bit First bit position to read (0-7)
+ * @param len		Number of bits to read (<= 8)
+ * @param data 		Container for right-aligned value
+ * @return Status of read operation (0 = success, <0 = error)
+ */
+int8_t I2Cdev_readBits(uint8_t dev_addr, uint8_t reg_addr, uint8_t start_bit, 
+		uint8_t len, uint8_t *data) 
 {
 	int8_t err;
 
@@ -147,6 +177,13 @@ I2Cdev_readBits(uint8_t dev_addr, uint8_t reg_addr, uint8_t start_bit,
 }
 
 
+/** Read a single bit from a 16-bit device register.
+ * @param dev_addr 	I2C slave device address
+ * @param reg_addr 	Register regAddr to read from
+ * @param bit_n 	Bit position to read (0-15)
+ * @param data 		Container for single bit value
+ * @return Status of read operation (true = success)
+ */
 int8_t 	I2Cdev_readBitW(uint8_t dev_addr, uint8_t reg_addr, uint8_t bit_n, uint16_t *data) {
 	int8_t err;
 
@@ -157,8 +194,15 @@ int8_t 	I2Cdev_readBitW(uint8_t dev_addr, uint8_t reg_addr, uint8_t bit_n, uint1
 }
 
 
-int8_t
-I2Cdev_readBitsW(uint8_t dev_addr, uint8_t reg_addr, uint8_t start_bit,
+/** Read several bits from a 16-bit device register.
+ * @param dev_addr 	I2C slave device address
+ * @param reg_addr 	Register regAddr to read from
+ * @param start_bit First bit position to read (0-15)
+ * @param len		Number of bits to read (<= 16)
+ * @param data 		Container for right-aligned value
+ * @return Status of read operation (0 = success, <0 = error)
+ */
+int8_t I2Cdev_readBitsW(uint8_t dev_addr, uint8_t reg_addr, uint8_t start_bit,
 		uint8_t len, uint16_t *data)
 {
     int8_t err;
@@ -175,6 +219,13 @@ I2Cdev_readBitsW(uint8_t dev_addr, uint8_t reg_addr, uint8_t start_bit,
 }
 
 
+/** Write multiple bytes to an 8-bit device register.
+ * @param dev_addr 	I2C slave device address
+ * @param reg_addr 	First register address to write to
+ * @param len 		Number of bytes to write
+ * @param data 		Buffer to copy new data from
+ * @return Status of operation (0 = success, <0 = error)
+ */
 int8_t 	I2Cdev_writeBytes(uint8_t dev_addr, uint8_t reg_addr, uint8_t len, uint8_t *data) {
 	int8_t err;
 	uint8_t ts_data[len+1];
@@ -183,11 +234,16 @@ int8_t 	I2Cdev_writeBytes(uint8_t dev_addr, uint8_t reg_addr, uint8_t len, uint8
 	memcpy(ts_data+1, data, len);
 
 	err = i2c_transmit_nack(dev_addr, ts_data, len+1);
-
 	return err;
 }
 
 
+/** Write single byte to an 8-bit device register.
+ * @param dev_addr 	I2C slave device address
+ * @param reg_addr 	Register address to write to
+ * @param data 		New byte value to write
+ * @return Status of operation (0 = success, <0 = error)
+ */
 int8_t 	I2Cdev_writeByte(uint8_t dev_addr, uint8_t reg_addr, uint8_t data) {
 	int8_t err;
 
@@ -198,6 +254,12 @@ int8_t 	I2Cdev_writeByte(uint8_t dev_addr, uint8_t reg_addr, uint8_t data) {
 }
 
 
+/** Write single 16-bit word to an 16-bit device register.
+ * @param dev_addr 	I2C slave device address
+ * @param reg_addr 	Register address to write to
+ * @param data 		New byte value to write
+ * @return Status of operation (0 = success, <0 = error)
+ */
 int8_t 	I2Cdev_writeWord(uint8_t dev_addr, uint8_t reg_addr, uint16_t data) {
 	int8_t err;
 	uint8_t ts_data[3] = {reg_addr, (data >> 8) & 0xFF, data & 0xFF};
@@ -207,6 +269,13 @@ int8_t 	I2Cdev_writeWord(uint8_t dev_addr, uint8_t reg_addr, uint16_t data) {
 }
 
 
+/** Write multiple words to a 16-bit device register.
+ * @param dev_addr 	I2C slave device address
+ * @param reg_addr 	First register address to write to
+ * @param len 		Number of words to write
+ * @param data 		Buffer to copy new data from
+ * @return Status of operation (0 = success, <0 = error)
+ */
 int8_t 	I2Cdev_writeWords(uint8_t dev_addr, uint8_t reg_addr, uint8_t len, uint16_t *data) {
 	uint16_t bytes_num = len*2+1;
 	uint8_t bytes[bytes_num];
@@ -225,6 +294,13 @@ int8_t 	I2Cdev_writeWords(uint8_t dev_addr, uint8_t reg_addr, uint8_t len, uint1
 }
 
 
+/** write a single bit in an 8-bit device register.
+ * @param dev_addr 	I2C slave device address
+ * @param reg_addr 	Register regAddr to write to
+ * @param bit_n 	Bit position to write (0-7)
+ * @param data 		New bit value to write
+ * @return Status of operation (0 = success, <0 = error)
+ */
 int8_t 	I2Cdev_writeBit(uint8_t dev_addr, uint8_t reg_addr, uint8_t bit_n, uint8_t data) {
 	uint8_t b;
 	int8_t err;
@@ -240,6 +316,13 @@ int8_t 	I2Cdev_writeBit(uint8_t dev_addr, uint8_t reg_addr, uint8_t bit_n, uint8
 }
 
 
+/** write a single bit in a 16-bit device register.
+ * @param dev_addr 	I2C slave device address
+ * @param reg_addr 	Register regAddr to write to
+ * @param bit_n 	Bit position to write (0-15)
+ * @param data 		New bit value to write
+ * @return Status of operation (0 = success, <0 = error)
+ */
 int8_t 	I2Cdev_writeBitW(uint8_t dev_addr, uint8_t reg_addr, uint8_t bit_n, uint16_t data) {
 	uint16_t w;
 	I2Cdev_readWord(dev_addr, reg_addr, &w);
@@ -250,8 +333,15 @@ int8_t 	I2Cdev_writeBitW(uint8_t dev_addr, uint8_t reg_addr, uint8_t bit_n, uint
 }
 
 
-int8_t
-I2Cdev_writeBits(uint8_t dev_addr, uint8_t reg_addr, uint8_t start_bit,
+/** Write multiple bits in an 8-bit device register.
+ * @param dev_addr 	I2C slave device address
+ * @param reg_addr 	Register regAddr to write to
+ * @param start_bit First bit position to write (0-7)
+ * @param len 		Number of bits to write (not more than 8)
+ * @param data 		Right-aligned value to write
+ * @return Status of operation (0 = success, <0 = error)
+ */
+int8_t I2Cdev_writeBits(uint8_t dev_addr, uint8_t reg_addr, uint8_t start_bit,
 		uint8_t len, uint8_t data)
 {
     uint8_t b;
@@ -272,8 +362,15 @@ I2Cdev_writeBits(uint8_t dev_addr, uint8_t reg_addr, uint8_t start_bit,
 }
 
 
-int8_t
-I2Cdev_writeBitsW(uint8_t dev_addr, uint8_t reg_addr, uint8_t start_bit,
+/** Write multiple bits in a 16-bit device register.
+ * @param dev_addr 	I2C slave device address
+ * @param reg_addr 	Register regAddr to write to
+ * @param start_bit First bit position to write (0-15)
+ * @param len 		Number of bits to write (not more than 16)
+ * @param data 		Right-aligned value to write
+ * @return Status of operation (0 = success, <0 = error)
+ */
+int8_t I2Cdev_writeBitsW(uint8_t dev_addr, uint8_t reg_addr, uint8_t start_bit,
 		uint8_t len, uint16_t data)
 {
     uint16_t w;

From 43cf3655cefd4680feb34d3e15ab45061710ce47 Mon Sep 17 00:00:00 2001
From: Daichou 
Date: Tue, 4 Apr 2017 12:17:28 +0800
Subject: [PATCH 170/335] MPU6050 connection failed

---
 .../nbproject/Makefile-genesis.properties     |    2 +-
 .../Examples/MPU6050_example.X/I2Cdev.c       |  215 +-
 .../Examples/MPU6050_example.X/MPU6050.c      | 1920 ++++++----
 .../Examples/MPU6050_example.X/MPU6050.c.orig | 3174 +++++++++++++++++
 .../MPU6050_example.X/MPU6050_example_main.c  |   29 +-
 .../nbproject/Makefile-genesis.properties     |    2 +-
 6 files changed, 4455 insertions(+), 887 deletions(-)
 create mode 100644 dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050.c.orig

diff --git a/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-genesis.properties b/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-genesis.properties
index f9906730..249d7262 100644
--- a/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-genesis.properties
+++ b/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-genesis.properties
@@ -1,5 +1,5 @@
 #
-#Wed Mar 15 15:13:12 CST 2017
+#Tue Apr 04 10:56:56 CST 2017
 default.com-microchip-mplab-nbide-toolchainXC16-XC16LanguageToolchain.md5=ebaa75370c1463d650408e4144ba15de
 default.languagetoolchain.dir=/opt/microchip/xc16/v1.30/bin
 configurations-xml=e23099a44127c530cab293bfc5554ec5
diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/I2Cdev.c b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/I2Cdev.c
index 70d76e27..27909fee 100644
--- a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/I2Cdev.c
+++ b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/I2Cdev.c
@@ -34,6 +34,34 @@ THE SOFTWARE.
 
 #include "I2Cdev.h"
 
+/*******************************************************************************/
+//  delay us using for-loop
+/*******************************************************************************/
+void delay_us_I2C( unsigned int usec )
+{
+	unsigned int i;
+	//¦   ¦   ¦   ¦   ¦   ¦   ¦   ¦   ¦   ¦              //40 MIPS ,
+	for ( i = 0 ; i < usec * 2;
+	        i++ ) {                //for-loop 8Tcy -> 1us -> add two NOP()
+		asm("NOP");
+		asm("NOP");
+	}
+}
+/*******************************************************************************/
+// delay ms using Timer 1 interrupt
+/*******************************************************************************/
+void delay_ms_I2C( unsigned int msec )
+{
+	/*TIMER1_DELAY_VALUE = msec;
+	TMR1 = 0;
+	IEC0bits.T1IE = 1;
+	while(TIMER1_DELAY_VALUE);
+	*/
+	int i = 0;
+	for (i = 0; i < msec; i++)
+		delay_us_I2C(1000);
+}
+
 /*uint16_t config2;
 uint16_t config1 = (I2C_ON & I2C_IDLE_CON & I2C_CLK_HLD &
              I2C_IPMI_DIS & I2C_7BIT_ADD &
@@ -73,7 +101,7 @@ int8_t I2Cdev_readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_
     while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
     IFS0bits.MI2CIF = 0;     // Clear interrupt flag
     //while(I2CSTATbits.ACKSTAT);
-
+    //delay_ms_I2C(10);
     /*Master send RA*/
     /* Write Register Address */
     MasterWriteI2C(regAddr);
@@ -84,12 +112,13 @@ int8_t I2Cdev_readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_
     /*Slave send ACK*/
     while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
     IFS0bits.MI2CIF = 0;     // Clear interrupt flag
-    //while(I2CSTATbits.ACKSTAT);
+    while(I2CSTATbits.ACKSTAT);
 
+    //delay_ms_I2C(10);
     /*Master Start*/
-    //RestartI2C();
+    RestartI2C();
     /* Wait till Start sequence is completed */
-    //while(I2CCONbits.SEN);
+    while(I2CCONbits.SEN);
 
     /*Master send AD+R*/
     /* Write Slave Address (Read)*/
@@ -100,7 +129,8 @@ int8_t I2Cdev_readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_
     /*Slave send Ack*/
     while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
     IFS0bits.MI2CIF = 0;     // Clear interrupt flag
-    //while(I2CSTATbits.ACKSTAT);
+    while(I2CSTATbits.ACKSTAT);
+    //delay_ms_I2C(10);
 
     /*Slave send DATA*/
     //uint16_t flag = MastergetsI2C(length,data,I2C_DATA_WAIT);
@@ -113,6 +143,7 @@ int8_t I2Cdev_readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_
     for (i = 1 ; i < length ; i++ ){
         AckI2C();
         while(I2CCONbits.ACKEN == 1);
+		//delay_ms_I2C(10);
         data[i] = MasterReadI2C();
     }
     NotAckI2C();
@@ -144,93 +175,13 @@ int8_t I2Cdev_readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data) {
  * @return Number of words read (-1 indicates failure)
  */
 int8_t I2Cdev_readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data) {
-    int8_t count = 0;
-    IFS0bits.MI2CIF = 0;
-    IEC0bits.MI2CIE = 0;
-    
-    IdleI2C();
-    /*master Start*/
-    StartI2C();
-    /* Clear interrupt flag */
-
-    /* Wait till Start sequence is completed */
-    while(I2CCONbits.SEN);
-
-    /*AD+W*/
-    /* Write Slave Address (Write)*/
-    MasterWriteI2C(devAddr << 1 | 0x00);
-
-    /* Wait until address is transmitted */
-    while(I2CSTATbits.TBF);  // 8 clock cycles
-
-    /*Slave Ack*/
-    while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
-    IFS0bits.MI2CIF = 0;     // Clear interrupt flag
-    //while(I2CSTATbits.ACKSTAT);
-
-    /*master send RA*/
-    /* Write Register Address */
-    MasterWriteI2C(regAddr);
-
-    /* Wait until address is transmitted */
-    while(I2CSTATbits.TBF);  // 8 clock cycles
-
-    /*Slave ACK*/
-    while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
-    IFS0bits.MI2CIF = 0;     // Clear interrupt flag
-    //while(I2CSTATbits.ACKSTAT);
-
-    /*master Start*/
-    //RestartI2C();
-    /* Wait till Start sequence is completed */
-    //while(I2CCONbits.SEN);
-
-    /*master send AD+R*/
-    /* Write Slave Address (Read)*/
-    MasterWriteI2C(devAddr << 1 | 0x01);
-    /* Wait until address is transmitted */
-    while(I2CSTATbits.TBF);  // 8 clock cycles
-
-    /*Slave Ack*/
-    while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
-    IFS0bits.MI2CIF = 0;     // Clear interrupt flag
-    //while(I2CSTATbits.ACKSTAT);
-
-    /*Read Word Sequence*/
-    for ( count = 0 ; count < length ; count++ ) {
-        // First byte is bits 15-8 (MSb=15)
-        //IdleI2C();
-        uint8_t high_byte = MasterReadI2C();
-
-        // NACK
-        //IdleI2C();
-        NotAckI2C();
-
-        // Second byte is bits 7-0 (LSb=0)
-        IdleI2C();
-        uint8_t lower_byte = MasterReadI2C();
-        data[count] = (high_byte << 8) | lower_byte;
-        if (count == length - 1) {
-            // NACK
-            IdleI2C();
-            NotAckI2C();
-        } else {
-            // ACK
-            IdleI2C();
-            AckI2C();
-        }
+    unsigned char Onebyte[100];
+    I2Cdev_readBytes(devAddr,regAddr,length*2,Onebyte);
+    unsigned int i;
+    for (int i = 0 ; i < length ; i++ ){
+        data[i] = Onebyte[i*2] << 8 | Onebyte[i*2+1];
     }
-
-    /*Slave send NACK*/
-    NotAckI2C();
-
-    /*master enter P*/
-    StopI2C();
-    /* Wait till stop sequence is completed */
-    while(I2CCONbits.PEN);
-    //CloseI2C();
-
-    return count;
+    return length;
 }
 
 /** Read single word from a 16-bit device register.
@@ -328,16 +279,18 @@ int8_t I2Cdev_readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint
  * @return Status of operation (true = success)
  */
 bool I2Cdev_writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t* data) {
-    //OpenI2C(config1,config2);
+    if (data[length-1] != '\0' && length != 1)return false;
+	//OpenI2C(config1,config2);
     IFS0bits.MI2CIF = 0;
     IEC0bits.MI2CIE = 0;
-    IdleI2C();
+    //IdleI2C();
     /*Master Start*/
     StartI2C();
     /* Wait util Start sequence is completed */
     while(I2CCONbits.SEN);
     /* Clear interrupt flag */
     IFS0bits.MI2CIF = 0;
+    //delay_ms_I2C(10);
 
     /*Master send AD+W*/
     /* Write Slave address (Write)*/
@@ -349,6 +302,7 @@ bool I2Cdev_writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t
     while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
     IFS0bits.MI2CIF = 0;     // Clear interrupt flag
     while(I2CSTATbits.ACKSTAT);
+    //delay_ms_I2C(10);
 
     /*Master send RA*/
     /* Write Slave address (Write)*/
@@ -359,17 +313,20 @@ bool I2Cdev_writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t
     /*Slave send ACK*/
     while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
     IFS0bits.MI2CIF = 0;     // Clear interrupt flag
+    //delay_ms_I2C(10);
     while(I2CSTATbits.ACKSTAT);
 
     /*Master send data*/
     /* Transmit string of data */
     MasterputsI2C(data);
+    while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
+    IFS0bits.MI2CIF = 0;     // Clear interrupt flag
 
     StopI2C();
     /* Wait till stop sequence is completed */
     while(I2CCONbits.PEN);
     //CloseI2C();
-
+    IdleI2C();
     return true;
 }
 
@@ -391,68 +348,13 @@ bool I2Cdev_writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data) {
  * @return Status of operation (true = success)
  */
 bool I2Cdev_writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t* data) {
-    IFS0bits.MI2CIF = 0;
-    IEC0bits.MI2CIE = 0;
-    //OpenI2C(config1,config2);
-    IdleI2C();
-    /*Master Start*/
-    StartI2C();
-    /* Wait util Start sequence is completed */
-    while(I2CCONbits.SEN);
-    /* Clear interrupt flag */
-    IFS0bits.MI2CIF = 0;
-
-    /*Master send AD+W*/
-    /* Write Slave address (Write)*/
-    MasterWriteI2C(devAddr << 1 | 0x00);
-    /* Wait till address is transmitted */
-    while(I2CSTATbits.TBF);  // 8 clock cycles
-
-    /*Slave send ACK*/
-    while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
-    IFS0bits.MI2CIF = 0;     // Clear interrupt flag
-    while(I2CSTATbits.ACKSTAT);
-    
-    /*Master send RA*/
-    /* Write Slave address (Write)*/
-    MasterWriteI2C(regAddr);
-    /* Wait till address is transmitted */
-    while(I2CSTATbits.TBF);  // 8 clock cycles
-
-    /*Slave send ACK*/
-    while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
-    IFS0bits.MI2CIF = 0;     // Clear interrupt flag
-    while(I2CSTATbits.ACKSTAT);
-
-    /*Master send RA*/
-    /* Write Slave address (Write)*/
-    uint8_t i;
-    for (i = 0; i < length; i++) {
-        // Send MSB
-        IdleI2C();
-        MasterWriteI2C(data[i] >> 8);
-
-        // Send LSB
-        IdleI2C();
-        MasterWriteI2C(data[i] & 0xFF);
+    unsigned char OneByte[100];
+    unsigned int i;
+    for (i = 0 ; i < length ; i++){
+        OneByte[i*2] = data[i]>>8;
+        OneByte[i*2+1] = data[i] & 0XFF;
     }
-    /* Wait till address is transmitted */
-    while(I2CSTATbits.TBF);  // 8 clock cycles
-
-    /*Slave send ACK*/
-    while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
-    IFS0bits.MI2CIF = 0;     // Clear interrupt flag
-    while(I2CSTATbits.ACKSTAT);
-
-    /*Master send data*/
-    /* Transmit string of data */
-    //MasterputsI2C(data);
-
-    StopI2C();
-    /* Wait till stop sequence is completed */
-    while(I2CCONbits.PEN);
-    //CloseI2C();
-
+    I2Cdev_writeBytes(devAddr,regAddr,length*2,OneByte);
     return true;
 }
 
@@ -517,7 +419,8 @@ bool I2Cdev_writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_
         data &= mask; // zero all non-important bits in data
         b &= ~(mask); // zero all important bits in existing byte
         b |= data; // combine data with existing byte
-        return I2Cdev_writeByte(devAddr, regAddr, b);
+        delay_ms_I2C(10);
+		return I2Cdev_writeByte(devAddr, regAddr, b);
     } else {
         return false;
     }
diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050.c b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050.c
index 2683529a..fb0abb47 100644
--- a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050.c
+++ b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050.c
@@ -40,6 +40,34 @@ THE SOFTWARE.
 
 #include "MPU6050.h"
 
+/*******************************************************************************/
+//  delay us using for-loop
+/*******************************************************************************/
+void delay_us( unsigned int usec )
+{
+	unsigned int i;
+	//�   �   �   �   �   �   �   �   �   �              //40 MIPS ,
+	for ( i = 0 ; i < usec * 2;
+	        i++ ) {                //for-loop 8Tcy -> 1us -> add two NOP()
+		asm("NOP");
+		asm("NOP");
+	}
+}
+/*******************************************************************************/
+// delay ms using Timer 1 interrupt
+/*******************************************************************************/
+void delay_ms( unsigned int msec )
+{
+	/*TIMER1_DELAY_VALUE = msec;
+	TMR1 = 0;
+	IEC0bits.T1IE = 1;
+	while(TIMER1_DELAY_VALUE);
+	*/
+	int i = 0;
+	for (i = 0; i < msec; i++)
+		delay_us(1000);
+}
+
 MPU6050_t mpu6050;
 
 /** Specific address constructor.
@@ -48,8 +76,9 @@ MPU6050_t mpu6050;
  * @see MPU6050_ADDRESS_AD0_LOW
  * @see MPU6050_ADDRESS_AD0_HIGH
  */
-void MPU6050(uint8_t address) {
-    mpu6050.devAddr = address;
+void MPU6050(uint8_t address)
+{
+	mpu6050.devAddr = address;
 }
 
 /** Power on and prepare for general usage.
@@ -59,19 +88,28 @@ void MPU6050(uint8_t address) {
  * the clock source to use the X Gyro for reference, which is slightly better than
  * the default internal clock source.
  */
-void MPU6050_initialize() {
-    MPU6050_setClockSource(MPU6050_CLOCK_PLL_XGYRO);
-    MPU6050_setFullScaleGyroRange(MPU6050_GYRO_FS_250);
-    MPU6050_setFullScaleAccelRange(MPU6050_ACCEL_FS_2);
-    MPU6050_setSleepEnabled(false); // thanks to Jack Elston for pointing this one out!
+void MPU6050_initialize()
+{
+
+
+	MPU6050_setSleepEnabled(
+	    false); // thanks to Jack Elston for pointing this one out!
+	delay_ms(20);
+	MPU6050_setClockSource(MPU6050_CLOCK_PLL_XGYRO);
+	delay_ms(20);
+	MPU6050_setFullScaleAccelRange(MPU6050_ACCEL_FS_2);
+	delay_ms(20);
+	MPU6050_setFullScaleGyroRange(MPU6050_GYRO_FS_250);
+    delay_ms(100);
 }
 
 /** Verify the I2C connection.
  * Make sure the device is connected and responds as expected.
  * @return True if connection is valid, false otherwise
  */
-bool MPU6050_testConnection() {
-    return MPU6050_getDeviceID() == 0x34;
+bool MPU6050_testConnection()
+{
+	return MPU6050_getDeviceID() == 0x34;
 }
 
 // AUX_VDDIO register (InvenSense demo code calls this RA_*G_OFFS_TC)
@@ -82,9 +120,11 @@ bool MPU6050_testConnection() {
  * the MPU-6000, which does not have a VLOGIC pin.
  * @return I2C supply voltage level (0=VLOGIC, 1=VDD)
  */
-uint8_t MPU6050_getAuxVDDIOLevel() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_PWR_MODE_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+uint8_t MPU6050_getAuxVDDIOLevel()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_PWR_MODE_BIT,
+	               mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set the auxiliary I2C supply voltage level.
  * When set to 1, the auxiliary I2C bus high logic level is VDD. When cleared to
@@ -92,8 +132,10 @@ uint8_t MPU6050_getAuxVDDIOLevel() {
  * the MPU-6000, which does not have a VLOGIC pin.
  * @param level I2C supply voltage level (0=VLOGIC, 1=VDD)
  */
-void MPU6050_setAuxVDDIOLevel(uint8_t level) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_PWR_MODE_BIT, level);
+void MPU6050_setAuxVDDIOLevel(uint8_t level)
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_PWR_MODE_BIT,
+	                level);
 }
 
 // SMPLRT_DIV register
@@ -119,17 +161,19 @@ void MPU6050_setAuxVDDIOLevel(uint8_t level) {
  * @return Current sample rate
  * @see MPU6050_RA_SMPLRT_DIV
  */
-uint8_t MPU6050_getRate() {
-    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_SMPLRT_DIV, mpu6050.buffer);
-    return mpu6050.buffer[0];
+uint8_t MPU6050_getRate()
+{
+	I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_SMPLRT_DIV, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set gyroscope sample rate divider.
  * @param rate New sample rate divider
  * @see getRate()
  * @see MPU6050_RA_SMPLRT_DIV
  */
-void MPU6050_setRate(uint8_t rate) {
-    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_SMPLRT_DIV, rate);
+void MPU6050_setRate(uint8_t rate)
+{
+	I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_SMPLRT_DIV, rate);
 }
 
 // CONFIG register
@@ -161,17 +205,21 @@ void MPU6050_setRate(uint8_t rate) {
  *
  * @return FSYNC configuration value
  */
-uint8_t MPU6050_getExternalFrameSync() {
-    I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_EXT_SYNC_SET_BIT, MPU6050_CFG_EXT_SYNC_SET_LENGTH, mpu6050.buffer);
-    return mpu6050.buffer[0];
+uint8_t MPU6050_getExternalFrameSync()
+{
+	I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_CONFIG,
+	                MPU6050_CFG_EXT_SYNC_SET_BIT, MPU6050_CFG_EXT_SYNC_SET_LENGTH, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set external FSYNC configuration.
  * @see getExternalFrameSync()
  * @see MPU6050_RA_CONFIG
  * @param sync New FSYNC configuration value
  */
-void MPU6050_setExternalFrameSync(uint8_t sync) {
-    I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_EXT_SYNC_SET_BIT, MPU6050_CFG_EXT_SYNC_SET_LENGTH, sync);
+void MPU6050_setExternalFrameSync(uint8_t sync)
+{
+	I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_CONFIG,
+	                 MPU6050_CFG_EXT_SYNC_SET_BIT, MPU6050_CFG_EXT_SYNC_SET_LENGTH, sync);
 }
 /** Get digital low-pass filter configuration.
  * The DLPF_CFG parameter sets the digital low pass filter configuration. It
@@ -201,9 +249,11 @@ void MPU6050_setExternalFrameSync(uint8_t sync) {
  * @see MPU6050_CFG_DLPF_CFG_BIT
  * @see MPU6050_CFG_DLPF_CFG_LENGTH
  */
-uint8_t MPU6050_getDLPFMode() {
-    I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_DLPF_CFG_BIT, MPU6050_CFG_DLPF_CFG_LENGTH, mpu6050.buffer);
-    return mpu6050.buffer[0];
+uint8_t MPU6050_getDLPFMode()
+{
+	I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_DLPF_CFG_BIT,
+	                MPU6050_CFG_DLPF_CFG_LENGTH, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set digital low-pass filter configuration.
  * @param mode New DLFP configuration setting
@@ -213,8 +263,10 @@ uint8_t MPU6050_getDLPFMode() {
  * @see MPU6050_CFG_DLPF_CFG_BIT
  * @see MPU6050_CFG_DLPF_CFG_LENGTH
  */
-void MPU6050_setDLPFMode(uint8_t mode) {
-    I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_DLPF_CFG_BIT, MPU6050_CFG_DLPF_CFG_LENGTH, mode);
+void MPU6050_setDLPFMode(uint8_t mode)
+{
+	I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_DLPF_CFG_BIT,
+	                 MPU6050_CFG_DLPF_CFG_LENGTH, mode);
 }
 
 // GYRO_CONFIG register
@@ -236,9 +288,11 @@ void MPU6050_setDLPFMode(uint8_t mode) {
  * @see MPU6050_GCONFIG_FS_SEL_BIT
  * @see MPU6050_GCONFIG_FS_SEL_LENGTH
  */
-uint8_t MPU6050_getFullScaleGyroRange() {
-    I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, mpu6050.buffer);
-    return mpu6050.buffer[0];
+uint8_t MPU6050_getFullScaleGyroRange()
+{
+	I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_GYRO_CONFIG,
+	                MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set full-scale gyroscope range.
  * @param range New full-scale gyroscope range value
@@ -248,8 +302,10 @@ uint8_t MPU6050_getFullScaleGyroRange() {
  * @see MPU6050_GCONFIG_FS_SEL_BIT
  * @see MPU6050_GCONFIG_FS_SEL_LENGTH
  */
-void MPU6050_setFullScaleGyroRange(uint8_t range) {
-    I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, range);
+void MPU6050_setFullScaleGyroRange(uint8_t range)
+{
+	I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_GYRO_CONFIG,
+	                 MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, range);
 }
 
 // ACCEL_CONFIG register
@@ -258,46 +314,58 @@ void MPU6050_setFullScaleGyroRange(uint8_t range) {
  * @return Self-test enabled value
  * @see MPU6050_RA_ACCEL_CONFIG
  */
-bool MPU6050_getAccelXSelfTest() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_XA_ST_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getAccelXSelfTest()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG,
+	               MPU6050_ACONFIG_XA_ST_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Get self-test enabled setting for accelerometer X axis.
  * @param enabled Self-test enabled value
  * @see MPU6050_RA_ACCEL_CONFIG
  */
-void MPU6050_setAccelXSelfTest(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_XA_ST_BIT, enabled);
+void MPU6050_setAccelXSelfTest(bool enabled)
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG,
+	                MPU6050_ACONFIG_XA_ST_BIT, enabled);
 }
 /** Get self-test enabled value for accelerometer Y axis.
  * @return Self-test enabled value
  * @see MPU6050_RA_ACCEL_CONFIG
  */
-bool MPU6050_getAccelYSelfTest() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_YA_ST_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getAccelYSelfTest()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG,
+	               MPU6050_ACONFIG_YA_ST_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Get self-test enabled value for accelerometer Y axis.
  * @param enabled Self-test enabled value
  * @see MPU6050_RA_ACCEL_CONFIG
  */
-void MPU6050_setAccelYSelfTest(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_YA_ST_BIT, enabled);
+void MPU6050_setAccelYSelfTest(bool enabled)
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG,
+	                MPU6050_ACONFIG_YA_ST_BIT, enabled);
 }
 /** Get self-test enabled value for accelerometer Z axis.
  * @return Self-test enabled value
  * @see MPU6050_RA_ACCEL_CONFIG
  */
-bool MPU6050_getAccelZSelfTest() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ZA_ST_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getAccelZSelfTest()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG,
+	               MPU6050_ACONFIG_ZA_ST_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set self-test enabled value for accelerometer Z axis.
  * @param enabled Self-test enabled value
  * @see MPU6050_RA_ACCEL_CONFIG
  */
-void MPU6050_setAccelZSelfTest(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ZA_ST_BIT, enabled);
+void MPU6050_setAccelZSelfTest(bool enabled)
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG,
+	                MPU6050_ACONFIG_ZA_ST_BIT, enabled);
 }
 /** Get full-scale accelerometer range.
  * The FS_SEL parameter allows setting the full-scale range of the accelerometer
@@ -316,16 +384,20 @@ void MPU6050_setAccelZSelfTest(bool enabled) {
  * @see MPU6050_ACONFIG_AFS_SEL_BIT
  * @see MPU6050_ACONFIG_AFS_SEL_LENGTH
  */
-uint8_t MPU6050_getFullScaleAccelRange() {
-    I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, mpu6050.buffer);
-    return mpu6050.buffer[0];
+uint8_t MPU6050_getFullScaleAccelRange()
+{
+	I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG,
+	                MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set full-scale accelerometer range.
  * @param range New full-scale accelerometer range setting
  * @see getFullScaleAccelRange()
  */
-void MPU6050_setFullScaleAccelRange(uint8_t range) {
-    I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, range);
+void MPU6050_setFullScaleAccelRange(uint8_t range)
+{
+	I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG,
+	                 MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, range);
 }
 /** Get the high-pass filter configuration.
  * The DHPF is a filter module in the path leading to motion detectors (Free
@@ -362,9 +434,12 @@ void MPU6050_setFullScaleAccelRange(uint8_t range) {
  * @see MPU6050_DHPF_RESET
  * @see MPU6050_RA_ACCEL_CONFIG
  */
-uint8_t MPU6050_getDHPFMode() {
-    I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ACCEL_HPF_BIT, MPU6050_ACONFIG_ACCEL_HPF_LENGTH, mpu6050.buffer);
-    return mpu6050.buffer[0];
+uint8_t MPU6050_getDHPFMode()
+{
+	I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG,
+	                MPU6050_ACONFIG_ACCEL_HPF_BIT, MPU6050_ACONFIG_ACCEL_HPF_LENGTH,
+	                mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set the high-pass filter configuration.
  * @param bandwidth New high-pass filter configuration
@@ -372,8 +447,10 @@ uint8_t MPU6050_getDHPFMode() {
  * @see MPU6050_DHPF_RESET
  * @see MPU6050_RA_ACCEL_CONFIG
  */
-void MPU6050_setDHPFMode(uint8_t bandwidth) {
-    I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ACCEL_HPF_BIT, MPU6050_ACONFIG_ACCEL_HPF_LENGTH, bandwidth);
+void MPU6050_setDHPFMode(uint8_t bandwidth)
+{
+	I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG,
+	                 MPU6050_ACONFIG_ACCEL_HPF_BIT, MPU6050_ACONFIG_ACCEL_HPF_LENGTH, bandwidth);
 }
 
 // FF_THR register
@@ -393,17 +470,19 @@ void MPU6050_setDHPFMode(uint8_t bandwidth) {
  * @return Current free-fall acceleration threshold value (LSB = 2mg)
  * @see MPU6050_RA_FF_THR
  */
-uint8_t MPU6050_getFreefallDetectionThreshold() {
-    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_FF_THR, mpu6050.buffer);
-    return mpu6050.buffer[0];
+uint8_t MPU6050_getFreefallDetectionThreshold()
+{
+	I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_FF_THR, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Get free-fall event acceleration threshold.
  * @param threshold New free-fall acceleration threshold value (LSB = 2mg)
  * @see getFreefallDetectionThreshold()
  * @see MPU6050_RA_FF_THR
  */
-void MPU6050_setFreefallDetectionThreshold(uint8_t threshold) {
-    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_FF_THR, threshold);
+void MPU6050_setFreefallDetectionThreshold(uint8_t threshold)
+{
+	I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_FF_THR, threshold);
 }
 
 // FF_DUR register
@@ -425,17 +504,19 @@ void MPU6050_setFreefallDetectionThreshold(uint8_t threshold) {
  * @return Current free-fall duration threshold value (LSB = 1ms)
  * @see MPU6050_RA_FF_DUR
  */
-uint8_t MPU6050_getFreefallDetectionDuration() {
-    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_FF_DUR, mpu6050.buffer);
-    return mpu6050.buffer[0];
+uint8_t MPU6050_getFreefallDetectionDuration()
+{
+	I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_FF_DUR, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Get free-fall event duration threshold.
  * @param duration New free-fall duration threshold value (LSB = 1ms)
  * @see getFreefallDetectionDuration()
  * @see MPU6050_RA_FF_DUR
  */
-void MPU6050_setFreefallDetectionDuration(uint8_t duration) {
-    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_FF_DUR, duration);
+void MPU6050_setFreefallDetectionDuration(uint8_t duration)
+{
+	I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_FF_DUR, duration);
 }
 
 // MOT_THR register
@@ -459,17 +540,19 @@ void MPU6050_setFreefallDetectionDuration(uint8_t duration) {
  * @return Current motion detection acceleration threshold value (LSB = 2mg)
  * @see MPU6050_RA_MOT_THR
  */
-uint8_t MPU6050_getMotionDetectionThreshold() {
-    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_MOT_THR, mpu6050.buffer);
-    return mpu6050.buffer[0];
+uint8_t MPU6050_getMotionDetectionThreshold()
+{
+	I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_MOT_THR, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set free-fall event acceleration threshold.
  * @param threshold New motion detection acceleration threshold value (LSB = 2mg)
  * @see getMotionDetectionThreshold()
  * @see MPU6050_RA_MOT_THR
  */
-void MPU6050_setMotionDetectionThreshold(uint8_t threshold) {
-    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_MOT_THR, threshold);
+void MPU6050_setMotionDetectionThreshold(uint8_t threshold)
+{
+	I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_MOT_THR, threshold);
 }
 
 // MOT_DUR register
@@ -489,17 +572,19 @@ void MPU6050_setMotionDetectionThreshold(uint8_t threshold) {
  * @return Current motion detection duration threshold value (LSB = 1ms)
  * @see MPU6050_RA_MOT_DUR
  */
-uint8_t MPU6050_getMotionDetectionDuration() {
-    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_MOT_DUR, mpu6050.buffer);
-    return mpu6050.buffer[0];
+uint8_t MPU6050_getMotionDetectionDuration()
+{
+	I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_MOT_DUR, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set motion detection event duration threshold.
  * @param duration New motion detection duration threshold value (LSB = 1ms)
  * @see getMotionDetectionDuration()
  * @see MPU6050_RA_MOT_DUR
  */
-void MPU6050_setMotionDetectionDuration(uint8_t duration) {
-    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_MOT_DUR, duration);
+void MPU6050_setMotionDetectionDuration(uint8_t duration)
+{
+	I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_MOT_DUR, duration);
 }
 
 // ZRMOT_THR register
@@ -529,17 +614,19 @@ void MPU6050_setMotionDetectionDuration(uint8_t duration) {
  * @return Current zero motion detection acceleration threshold value (LSB = 2mg)
  * @see MPU6050_RA_ZRMOT_THR
  */
-uint8_t MPU6050_getZeroMotionDetectionThreshold() {
-    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_ZRMOT_THR, mpu6050.buffer);
-    return mpu6050.buffer[0];
+uint8_t MPU6050_getZeroMotionDetectionThreshold()
+{
+	I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_ZRMOT_THR, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set zero motion detection event acceleration threshold.
  * @param threshold New zero motion detection acceleration threshold value (LSB = 2mg)
  * @see getZeroMotionDetectionThreshold()
  * @see MPU6050_RA_ZRMOT_THR
  */
-void MPU6050_setZeroMotionDetectionThreshold(uint8_t threshold) {
-    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_ZRMOT_THR, threshold);
+void MPU6050_setZeroMotionDetectionThreshold(uint8_t threshold)
+{
+	I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_ZRMOT_THR, threshold);
 }
 
 // ZRMOT_DUR register
@@ -560,17 +647,19 @@ void MPU6050_setZeroMotionDetectionThreshold(uint8_t threshold) {
  * @return Current zero motion detection duration threshold value (LSB = 64ms)
  * @see MPU6050_RA_ZRMOT_DUR
  */
-uint8_t MPU6050_getZeroMotionDetectionDuration() {
-    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_ZRMOT_DUR, mpu6050.buffer);
-    return mpu6050.buffer[0];
+uint8_t MPU6050_getZeroMotionDetectionDuration()
+{
+	I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_ZRMOT_DUR, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set zero motion detection event duration threshold.
  * @param duration New zero motion detection duration threshold value (LSB = 1ms)
  * @see getZeroMotionDetectionDuration()
  * @see MPU6050_RA_ZRMOT_DUR
  */
-void MPU6050_setZeroMotionDetectionDuration(uint8_t duration) {
-    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_ZRMOT_DUR, duration);
+void MPU6050_setZeroMotionDetectionDuration(uint8_t duration)
+{
+	I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_ZRMOT_DUR, duration);
 }
 
 // FIFO_EN register
@@ -581,17 +670,21 @@ void MPU6050_setZeroMotionDetectionDuration(uint8_t duration) {
  * @return Current temperature FIFO enabled value
  * @see MPU6050_RA_FIFO_EN
  */
-bool MPU6050_getTempFIFOEnabled() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_TEMP_FIFO_EN_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getTempFIFOEnabled()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_TEMP_FIFO_EN_BIT,
+	               mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set temperature FIFO enabled value.
  * @param enabled New temperature FIFO enabled value
  * @see getTempFIFOEnabled()
  * @see MPU6050_RA_FIFO_EN
  */
-void MPU6050_setTempFIFOEnabled(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_TEMP_FIFO_EN_BIT, enabled);
+void MPU6050_setTempFIFOEnabled(bool enabled)
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_TEMP_FIFO_EN_BIT,
+	                enabled);
 }
 /** Get gyroscope X-axis FIFO enabled value.
  * When set to 1, this bit enables GYRO_XOUT_H and GYRO_XOUT_L (Registers 67 and
@@ -599,17 +692,21 @@ void MPU6050_setTempFIFOEnabled(bool enabled) {
  * @return Current gyroscope X-axis FIFO enabled value
  * @see MPU6050_RA_FIFO_EN
  */
-bool MPU6050_getXGyroFIFOEnabled() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_XG_FIFO_EN_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getXGyroFIFOEnabled()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_XG_FIFO_EN_BIT,
+	               mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set gyroscope X-axis FIFO enabled value.
  * @param enabled New gyroscope X-axis FIFO enabled value
  * @see getXGyroFIFOEnabled()
  * @see MPU6050_RA_FIFO_EN
  */
-void MPU6050_setXGyroFIFOEnabled(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_XG_FIFO_EN_BIT, enabled);
+void MPU6050_setXGyroFIFOEnabled(bool enabled)
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_XG_FIFO_EN_BIT,
+	                enabled);
 }
 /** Get gyroscope Y-axis FIFO enabled value.
  * When set to 1, this bit enables GYRO_YOUT_H and GYRO_YOUT_L (Registers 69 and
@@ -617,17 +714,21 @@ void MPU6050_setXGyroFIFOEnabled(bool enabled) {
  * @return Current gyroscope Y-axis FIFO enabled value
  * @see MPU6050_RA_FIFO_EN
  */
-bool MPU6050_getYGyroFIFOEnabled() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_YG_FIFO_EN_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getYGyroFIFOEnabled()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_YG_FIFO_EN_BIT,
+	               mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set gyroscope Y-axis FIFO enabled value.
  * @param enabled New gyroscope Y-axis FIFO enabled value
  * @see getYGyroFIFOEnabled()
  * @see MPU6050_RA_FIFO_EN
  */
-void MPU6050_setYGyroFIFOEnabled(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_YG_FIFO_EN_BIT, enabled);
+void MPU6050_setYGyroFIFOEnabled(bool enabled)
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_YG_FIFO_EN_BIT,
+	                enabled);
 }
 /** Get gyroscope Z-axis FIFO enabled value.
  * When set to 1, this bit enables GYRO_ZOUT_H and GYRO_ZOUT_L (Registers 71 and
@@ -635,17 +736,21 @@ void MPU6050_setYGyroFIFOEnabled(bool enabled) {
  * @return Current gyroscope Z-axis FIFO enabled value
  * @see MPU6050_RA_FIFO_EN
  */
-bool MPU6050_getZGyroFIFOEnabled() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_ZG_FIFO_EN_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getZGyroFIFOEnabled()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_ZG_FIFO_EN_BIT,
+	               mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set gyroscope Z-axis FIFO enabled value.
  * @param enabled New gyroscope Z-axis FIFO enabled value
  * @see getZGyroFIFOEnabled()
  * @see MPU6050_RA_FIFO_EN
  */
-void MPU6050_setZGyroFIFOEnabled(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_ZG_FIFO_EN_BIT, enabled);
+void MPU6050_setZGyroFIFOEnabled(bool enabled)
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_ZG_FIFO_EN_BIT,
+	                enabled);
 }
 /** Get accelerometer FIFO enabled value.
  * When set to 1, this bit enables ACCEL_XOUT_H, ACCEL_XOUT_L, ACCEL_YOUT_H,
@@ -654,17 +759,21 @@ void MPU6050_setZGyroFIFOEnabled(bool enabled) {
  * @return Current accelerometer FIFO enabled value
  * @see MPU6050_RA_FIFO_EN
  */
-bool MPU6050_getAccelFIFOEnabled() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_ACCEL_FIFO_EN_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getAccelFIFOEnabled()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_ACCEL_FIFO_EN_BIT,
+	               mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set accelerometer FIFO enabled value.
  * @param enabled New accelerometer FIFO enabled value
  * @see getAccelFIFOEnabled()
  * @see MPU6050_RA_FIFO_EN
  */
-void MPU6050_setAccelFIFOEnabled(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_ACCEL_FIFO_EN_BIT, enabled);
+void MPU6050_setAccelFIFOEnabled(bool enabled)
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_ACCEL_FIFO_EN_BIT,
+	                enabled);
 }
 /** Get Slave 2 FIFO enabled value.
  * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96)
@@ -672,17 +781,21 @@ void MPU6050_setAccelFIFOEnabled(bool enabled) {
  * @return Current Slave 2 FIFO enabled value
  * @see MPU6050_RA_FIFO_EN
  */
-bool MPU6050_getSlave2FIFOEnabled() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV2_FIFO_EN_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getSlave2FIFOEnabled()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV2_FIFO_EN_BIT,
+	               mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set Slave 2 FIFO enabled value.
  * @param enabled New Slave 2 FIFO enabled value
  * @see getSlave2FIFOEnabled()
  * @see MPU6050_RA_FIFO_EN
  */
-void MPU6050_setSlave2FIFOEnabled(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV2_FIFO_EN_BIT, enabled);
+void MPU6050_setSlave2FIFOEnabled(bool enabled)
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV2_FIFO_EN_BIT,
+	                enabled);
 }
 /** Get Slave 1 FIFO enabled value.
  * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96)
@@ -690,17 +803,21 @@ void MPU6050_setSlave2FIFOEnabled(bool enabled) {
  * @return Current Slave 1 FIFO enabled value
  * @see MPU6050_RA_FIFO_EN
  */
-bool MPU6050_getSlave1FIFOEnabled() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV1_FIFO_EN_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getSlave1FIFOEnabled()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV1_FIFO_EN_BIT,
+	               mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set Slave 1 FIFO enabled value.
  * @param enabled New Slave 1 FIFO enabled value
  * @see getSlave1FIFOEnabled()
  * @see MPU6050_RA_FIFO_EN
  */
-void MPU6050_setSlave1FIFOEnabled(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV1_FIFO_EN_BIT, enabled);
+void MPU6050_setSlave1FIFOEnabled(bool enabled)
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV1_FIFO_EN_BIT,
+	                enabled);
 }
 /** Get Slave 0 FIFO enabled value.
  * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96)
@@ -708,17 +825,21 @@ void MPU6050_setSlave1FIFOEnabled(bool enabled) {
  * @return Current Slave 0 FIFO enabled value
  * @see MPU6050_RA_FIFO_EN
  */
-bool MPU6050_getSlave0FIFOEnabled() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV0_FIFO_EN_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getSlave0FIFOEnabled()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV0_FIFO_EN_BIT,
+	               mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set Slave 0 FIFO enabled value.
  * @param enabled New Slave 0 FIFO enabled value
  * @see getSlave0FIFOEnabled()
  * @see MPU6050_RA_FIFO_EN
  */
-void MPU6050_setSlave0FIFOEnabled(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV0_FIFO_EN_BIT, enabled);
+void MPU6050_setSlave0FIFOEnabled(bool enabled)
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV0_FIFO_EN_BIT,
+	                enabled);
 }
 
 // I2C_MST_CTRL register
@@ -738,17 +859,21 @@ void MPU6050_setSlave0FIFOEnabled(bool enabled) {
  * @return Current multi-master enabled value
  * @see MPU6050_RA_I2C_MST_CTRL
  */
-bool MPU6050_getMultiMasterEnabled() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_MULT_MST_EN_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getMultiMasterEnabled()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL,
+	               MPU6050_MULT_MST_EN_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set multi-master enabled value.
  * @param enabled New multi-master enabled value
  * @see getMultiMasterEnabled()
  * @see MPU6050_RA_I2C_MST_CTRL
  */
-void MPU6050_setMultiMasterEnabled(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_MULT_MST_EN_BIT, enabled);
+void MPU6050_setMultiMasterEnabled(bool enabled)
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL,
+	                MPU6050_MULT_MST_EN_BIT, enabled);
 }
 /** Get wait-for-external-sensor-data enabled value.
  * When the WAIT_FOR_ES bit is set to 1, the Data Ready interrupt will be
@@ -761,17 +886,21 @@ void MPU6050_setMultiMasterEnabled(bool enabled) {
  * @return Current wait-for-external-sensor-data enabled value
  * @see MPU6050_RA_I2C_MST_CTRL
  */
-bool MPU6050_getWaitForExternalSensorEnabled() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_WAIT_FOR_ES_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getWaitForExternalSensorEnabled()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL,
+	               MPU6050_WAIT_FOR_ES_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set wait-for-external-sensor-data enabled value.
  * @param enabled New wait-for-external-sensor-data enabled value
  * @see getWaitForExternalSensorEnabled()
  * @see MPU6050_RA_I2C_MST_CTRL
  */
-void MPU6050_setWaitForExternalSensorEnabled(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_WAIT_FOR_ES_BIT, enabled);
+void MPU6050_setWaitForExternalSensorEnabled(bool enabled)
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL,
+	                MPU6050_WAIT_FOR_ES_BIT, enabled);
 }
 /** Get Slave 3 FIFO enabled value.
  * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96)
@@ -779,17 +908,21 @@ void MPU6050_setWaitForExternalSensorEnabled(bool enabled) {
  * @return Current Slave 3 FIFO enabled value
  * @see MPU6050_RA_MST_CTRL
  */
-bool MPU6050_getSlave3FIFOEnabled() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_SLV_3_FIFO_EN_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getSlave3FIFOEnabled()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL,
+	               MPU6050_SLV_3_FIFO_EN_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set Slave 3 FIFO enabled value.
  * @param enabled New Slave 3 FIFO enabled value
  * @see getSlave3FIFOEnabled()
  * @see MPU6050_RA_MST_CTRL
  */
-void MPU6050_setSlave3FIFOEnabled(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_SLV_3_FIFO_EN_BIT, enabled);
+void MPU6050_setSlave3FIFOEnabled(bool enabled)
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL,
+	                MPU6050_SLV_3_FIFO_EN_BIT, enabled);
 }
 /** Get slave read/write transition enabled value.
  * The I2C_MST_P_NSR bit configures the I2C Master's transition from one slave
@@ -801,17 +934,21 @@ void MPU6050_setSlave3FIFOEnabled(bool enabled) {
  * @return Current slave read/write transition enabled value
  * @see MPU6050_RA_I2C_MST_CTRL
  */
-bool MPU6050_getSlaveReadWriteTransitionEnabled() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_P_NSR_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getSlaveReadWriteTransitionEnabled()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL,
+	               MPU6050_I2C_MST_P_NSR_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set slave read/write transition enabled value.
  * @param enabled New slave read/write transition enabled value
  * @see getSlaveReadWriteTransitionEnabled()
  * @see MPU6050_RA_I2C_MST_CTRL
  */
-void MPU6050_setSlaveReadWriteTransitionEnabled(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_P_NSR_BIT, enabled);
+void MPU6050_setSlaveReadWriteTransitionEnabled(bool enabled)
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL,
+	                MPU6050_I2C_MST_P_NSR_BIT, enabled);
 }
 /** Get I2C master clock speed.
  * I2C_MST_CLK is a 4 bit unsigned value which configures a divider on the
@@ -842,16 +979,20 @@ void MPU6050_setSlaveReadWriteTransitionEnabled(bool enabled) {
  * @return Current I2C master clock speed
  * @see MPU6050_RA_I2C_MST_CTRL
  */
-uint8_t MPU6050_getMasterClockSpeed() {
-    I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_CLK_BIT, MPU6050_I2C_MST_CLK_LENGTH, mpu6050.buffer);
-    return mpu6050.buffer[0];
+uint8_t MPU6050_getMasterClockSpeed()
+{
+	I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL,
+	                MPU6050_I2C_MST_CLK_BIT, MPU6050_I2C_MST_CLK_LENGTH, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set I2C master clock speed.
  * @reparam speed Current I2C master clock speed
  * @see MPU6050_RA_I2C_MST_CTRL
  */
-void MPU6050_setMasterClockSpeed(uint8_t speed) {
-    I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_CLK_BIT, MPU6050_I2C_MST_CLK_LENGTH, speed);
+void MPU6050_setMasterClockSpeed(uint8_t speed)
+{
+	I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL,
+	                 MPU6050_I2C_MST_CLK_BIT, MPU6050_I2C_MST_CLK_LENGTH, speed);
 }
 
 // I2C_SLV* registers (Slave 0-3)
@@ -861,7 +1002,7 @@ void MPU6050_setMasterClockSpeed(uint8_t speed) {
  * operation, and if it is cleared, then it's a write operation. The remaining
  * bits (6-0) are the 7-bit device address of the slave device.
  *
- * In read mode, the result of the read is placed in the lowest available 
+ * In read mode, the result of the read is placed in the lowest available
  * EXT_SENS_DATA register. For further information regarding the allocation of
  * read results, please refer to the EXT_SENS_DATA register description
  * (Registers 73 - 96).
@@ -897,10 +1038,12 @@ void MPU6050_setMasterClockSpeed(uint8_t speed) {
  * @return Current address for specified slave
  * @see MPU6050_RA_I2C_SLV0_ADDR
  */
-uint8_t MPU6050_getSlaveAddress(uint8_t num) {
-    if (num > 3) return 0;
-    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_ADDR + num*3, mpu6050.buffer);
-    return mpu6050.buffer[0];
+uint8_t MPU6050_getSlaveAddress(uint8_t num)
+{
+	if (num > 3) return 0;
+	I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_ADDR + num * 3,
+	                mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set the I2C address of the specified slave (0-3).
  * @param num Slave number (0-3)
@@ -908,9 +1051,10 @@ uint8_t MPU6050_getSlaveAddress(uint8_t num) {
  * @see getSlaveAddress()
  * @see MPU6050_RA_I2C_SLV0_ADDR
  */
-void MPU6050_setSlaveAddress(uint8_t num, uint8_t address) {
-    if (num > 3) return;
-    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_ADDR + num*3, address);
+void MPU6050_setSlaveAddress(uint8_t num, uint8_t address)
+{
+	if (num > 3) return;
+	I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_ADDR + num * 3, address);
 }
 /** Get the active internal register for the specified slave (0-3).
  * Read/write operations for this slave will be done to whatever internal
@@ -923,10 +1067,12 @@ void MPU6050_setSlaveAddress(uint8_t num, uint8_t address) {
  * @return Current active register for specified slave
  * @see MPU6050_RA_I2C_SLV0_REG
  */
-uint8_t MPU6050_getSlaveRegister(uint8_t num) {
-    if (num > 3) return 0;
-    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_REG + num*3, mpu6050.buffer);
-    return mpu6050.buffer[0];
+uint8_t MPU6050_getSlaveRegister(uint8_t num)
+{
+	if (num > 3) return 0;
+	I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_REG + num * 3,
+	                mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set the active internal register for the specified slave (0-3).
  * @param num Slave number (0-3)
@@ -934,9 +1080,10 @@ uint8_t MPU6050_getSlaveRegister(uint8_t num) {
  * @see getSlaveRegister()
  * @see MPU6050_RA_I2C_SLV0_REG
  */
-void MPU6050_setSlaveRegister(uint8_t num, uint8_t reg) {
-    if (num > 3) return;
-    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_REG + num*3, reg);
+void MPU6050_setSlaveRegister(uint8_t num, uint8_t reg)
+{
+	if (num > 3) return;
+	I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_REG + num * 3, reg);
 }
 /** Get the enabled value for the specified slave (0-3).
  * When set to 1, this bit enables Slave 0 for data transfer operations. When
@@ -945,10 +1092,12 @@ void MPU6050_setSlaveRegister(uint8_t num, uint8_t reg) {
  * @return Current enabled value for specified slave
  * @see MPU6050_RA_I2C_SLV0_CTRL
  */
-bool MPU6050_getSlaveEnabled(uint8_t num) {
-    if (num > 3) return 0;
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_EN_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getSlaveEnabled(uint8_t num)
+{
+	if (num > 3) return 0;
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num * 3,
+	               MPU6050_I2C_SLV_EN_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set the enabled value for the specified slave (0-3).
  * @param num Slave number (0-3)
@@ -956,9 +1105,11 @@ bool MPU6050_getSlaveEnabled(uint8_t num) {
  * @see getSlaveEnabled()
  * @see MPU6050_RA_I2C_SLV0_CTRL
  */
-void MPU6050_setSlaveEnabled(uint8_t num, bool enabled) {
-    if (num > 3) return;
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_EN_BIT, enabled);
+void MPU6050_setSlaveEnabled(uint8_t num, bool enabled)
+{
+	if (num > 3) return;
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num * 3,
+	                MPU6050_I2C_SLV_EN_BIT, enabled);
 }
 /** Get word pair byte-swapping enabled for the specified slave (0-3).
  * When set to 1, this bit enables byte swapping. When byte swapping is enabled,
@@ -971,10 +1122,12 @@ void MPU6050_setSlaveEnabled(uint8_t num, bool enabled) {
  * @return Current word pair byte-swapping enabled value for specified slave
  * @see MPU6050_RA_I2C_SLV0_CTRL
  */
-bool MPU6050_getSlaveWordByteSwap(uint8_t num) {
-    if (num > 3) return 0;
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_BYTE_SW_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getSlaveWordByteSwap(uint8_t num)
+{
+	if (num > 3) return 0;
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num * 3,
+	               MPU6050_I2C_SLV_BYTE_SW_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set word pair byte-swapping enabled for the specified slave (0-3).
  * @param num Slave number (0-3)
@@ -982,9 +1135,11 @@ bool MPU6050_getSlaveWordByteSwap(uint8_t num) {
  * @see getSlaveWordByteSwap()
  * @see MPU6050_RA_I2C_SLV0_CTRL
  */
-void MPU6050_setSlaveWordByteSwap(uint8_t num, bool enabled) {
-    if (num > 3) return;
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_BYTE_SW_BIT, enabled);
+void MPU6050_setSlaveWordByteSwap(uint8_t num, bool enabled)
+{
+	if (num > 3) return;
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num * 3,
+	                MPU6050_I2C_SLV_BYTE_SW_BIT, enabled);
 }
 /** Get write mode for the specified slave (0-3).
  * When set to 1, the transaction will read or write data only. When cleared to
@@ -996,10 +1151,12 @@ void MPU6050_setSlaveWordByteSwap(uint8_t num, bool enabled) {
  * @return Current write mode for specified slave (0 = register address + data, 1 = data only)
  * @see MPU6050_RA_I2C_SLV0_CTRL
  */
-bool MPU6050_getSlaveWriteMode(uint8_t num) {
-    if (num > 3) return 0;
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_REG_DIS_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getSlaveWriteMode(uint8_t num)
+{
+	if (num > 3) return 0;
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num * 3,
+	               MPU6050_I2C_SLV_REG_DIS_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set write mode for the specified slave (0-3).
  * @param num Slave number (0-3)
@@ -1007,9 +1164,11 @@ bool MPU6050_getSlaveWriteMode(uint8_t num) {
  * @see getSlaveWriteMode()
  * @see MPU6050_RA_I2C_SLV0_CTRL
  */
-void MPU6050_setSlaveWriteMode(uint8_t num, bool mode) {
-    if (num > 3) return;
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_REG_DIS_BIT, mode);
+void MPU6050_setSlaveWriteMode(uint8_t num, bool mode)
+{
+	if (num > 3) return;
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num * 3,
+	                MPU6050_I2C_SLV_REG_DIS_BIT, mode);
 }
 /** Get word pair grouping order offset for the specified slave (0-3).
  * This sets specifies the grouping order of word pairs received from registers.
@@ -1022,10 +1181,12 @@ void MPU6050_setSlaveWriteMode(uint8_t num, bool mode) {
  * @return Current word pair grouping order offset for specified slave
  * @see MPU6050_RA_I2C_SLV0_CTRL
  */
-bool MPU6050_getSlaveWordGroupOffset(uint8_t num) {
-    if (num > 3) return 0;
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_GRP_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getSlaveWordGroupOffset(uint8_t num)
+{
+	if (num > 3) return 0;
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num * 3,
+	               MPU6050_I2C_SLV_GRP_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set word pair grouping order offset for the specified slave (0-3).
  * @param num Slave number (0-3)
@@ -1033,9 +1194,11 @@ bool MPU6050_getSlaveWordGroupOffset(uint8_t num) {
  * @see getSlaveWordGroupOffset()
  * @see MPU6050_RA_I2C_SLV0_CTRL
  */
-void MPU6050_setSlaveWordGroupOffset(uint8_t num, bool enabled) {
-    if (num > 3) return;
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_GRP_BIT, enabled);
+void MPU6050_setSlaveWordGroupOffset(uint8_t num, bool enabled)
+{
+	if (num > 3) return;
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num * 3,
+	                MPU6050_I2C_SLV_GRP_BIT, enabled);
 }
 /** Get number of bytes to read for the specified slave (0-3).
  * Specifies the number of bytes transferred to and from Slave 0. Clearing this
@@ -1044,10 +1207,12 @@ void MPU6050_setSlaveWordGroupOffset(uint8_t num, bool enabled) {
  * @return Number of bytes to read for specified slave
  * @see MPU6050_RA_I2C_SLV0_CTRL
  */
-uint8_t MPU6050_getSlaveDataLength(uint8_t num) {
-    if (num > 3) return 0;
-    I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_LEN_BIT, MPU6050_I2C_SLV_LEN_LENGTH, mpu6050.buffer);
-    return mpu6050.buffer[0];
+uint8_t MPU6050_getSlaveDataLength(uint8_t num)
+{
+	if (num > 3) return 0;
+	I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num * 3,
+	                MPU6050_I2C_SLV_LEN_BIT, MPU6050_I2C_SLV_LEN_LENGTH, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set number of bytes to read for the specified slave (0-3).
  * @param num Slave number (0-3)
@@ -1055,9 +1220,11 @@ uint8_t MPU6050_getSlaveDataLength(uint8_t num) {
  * @see getSlaveDataLength()
  * @see MPU6050_RA_I2C_SLV0_CTRL
  */
-void MPU6050_setSlaveDataLength(uint8_t num, uint8_t length) {
-    if (num > 3) return;
-    I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_LEN_BIT, MPU6050_I2C_SLV_LEN_LENGTH, length);
+void MPU6050_setSlaveDataLength(uint8_t num, uint8_t length)
+{
+	if (num > 3) return;
+	I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num * 3,
+	                 MPU6050_I2C_SLV_LEN_BIT, MPU6050_I2C_SLV_LEN_LENGTH, length);
 }
 
 // I2C_SLV* registers (Slave 4)
@@ -1071,17 +1238,19 @@ void MPU6050_setSlaveDataLength(uint8_t num, uint8_t length) {
  * @see getSlaveAddress()
  * @see MPU6050_RA_I2C_SLV4_ADDR
  */
-uint8_t MPU6050_getSlave4Address() {
-    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_ADDR, mpu6050.buffer);
-    return mpu6050.buffer[0];
+uint8_t MPU6050_getSlave4Address()
+{
+	I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_ADDR, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set the I2C address of Slave 4.
  * @param address New address for Slave 4
  * @see getSlave4Address()
  * @see MPU6050_RA_I2C_SLV4_ADDR
  */
-void MPU6050_setSlave4Address(uint8_t address) {
-    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_ADDR, address);
+void MPU6050_setSlave4Address(uint8_t address)
+{
+	I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_ADDR, address);
 }
 /** Get the active internal register for the Slave 4.
  * Read/write operations for this slave will be done to whatever internal
@@ -1090,17 +1259,19 @@ void MPU6050_setSlave4Address(uint8_t address) {
  * @return Current active register for Slave 4
  * @see MPU6050_RA_I2C_SLV4_REG
  */
-uint8_t MPU6050_getSlave4Register() {
-    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_REG, mpu6050.buffer);
-    return mpu6050.buffer[0];
+uint8_t MPU6050_getSlave4Register()
+{
+	I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_REG, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set the active internal register for Slave 4.
  * @param reg New active register for Slave 4
  * @see getSlave4Register()
  * @see MPU6050_RA_I2C_SLV4_REG
  */
-void MPU6050_setSlave4Register(uint8_t reg) {
-    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_REG, reg);
+void MPU6050_setSlave4Register(uint8_t reg)
+{
+	I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_REG, reg);
 }
 /** Set new byte to write to Slave 4.
  * This register stores the data to be written into the Slave 4. If I2C_SLV4_RW
@@ -1108,8 +1279,9 @@ void MPU6050_setSlave4Register(uint8_t reg) {
  * @param data New byte to write to Slave 4
  * @see MPU6050_RA_I2C_SLV4_DO
  */
-void MPU6050_setSlave4OutputByte(uint8_t data) {
-    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_DO, data);
+void MPU6050_setSlave4OutputByte(uint8_t data)
+{
+	I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_DO, data);
 }
 /** Get the enabled value for the Slave 4.
  * When set to 1, this bit enables Slave 4 for data transfer operations. When
@@ -1117,17 +1289,21 @@ void MPU6050_setSlave4OutputByte(uint8_t data) {
  * @return Current enabled value for Slave 4
  * @see MPU6050_RA_I2C_SLV4_CTRL
  */
-bool MPU6050_getSlave4Enabled() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_EN_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getSlave4Enabled()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL,
+	               MPU6050_I2C_SLV4_EN_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set the enabled value for Slave 4.
  * @param enabled New enabled value for Slave 4
  * @see getSlave4Enabled()
  * @see MPU6050_RA_I2C_SLV4_CTRL
  */
-void MPU6050_setSlave4Enabled(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_EN_BIT, enabled);
+void MPU6050_setSlave4Enabled(bool enabled)
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL,
+	                MPU6050_I2C_SLV4_EN_BIT, enabled);
 }
 /** Get the enabled value for Slave 4 transaction interrupts.
  * When set to 1, this bit enables the generation of an interrupt signal upon
@@ -1138,17 +1314,21 @@ void MPU6050_setSlave4Enabled(bool enabled) {
  * @return Current enabled value for Slave 4 transaction interrupts.
  * @see MPU6050_RA_I2C_SLV4_CTRL
  */
-bool MPU6050_getSlave4InterruptEnabled() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_INT_EN_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getSlave4InterruptEnabled()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL,
+	               MPU6050_I2C_SLV4_INT_EN_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set the enabled value for Slave 4 transaction interrupts.
  * @param enabled New enabled value for Slave 4 transaction interrupts.
  * @see getSlave4InterruptEnabled()
  * @see MPU6050_RA_I2C_SLV4_CTRL
  */
-void MPU6050_setSlave4InterruptEnabled(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_INT_EN_BIT, enabled);
+void MPU6050_setSlave4InterruptEnabled(bool enabled)
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL,
+	                MPU6050_I2C_SLV4_INT_EN_BIT, enabled);
 }
 /** Get write mode for Slave 4.
  * When set to 1, the transaction will read or write data only. When cleared to
@@ -1159,17 +1339,21 @@ void MPU6050_setSlave4InterruptEnabled(bool enabled) {
  * @return Current write mode for Slave 4 (0 = register address + data, 1 = data only)
  * @see MPU6050_RA_I2C_SLV4_CTRL
  */
-bool MPU6050_getSlave4WriteMode() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_REG_DIS_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getSlave4WriteMode()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL,
+	               MPU6050_I2C_SLV4_REG_DIS_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set write mode for the Slave 4.
  * @param mode New write mode for Slave 4 (0 = register address + data, 1 = data only)
  * @see getSlave4WriteMode()
  * @see MPU6050_RA_I2C_SLV4_CTRL
  */
-void MPU6050_setSlave4WriteMode(bool mode) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_REG_DIS_BIT, mode);
+void MPU6050_setSlave4WriteMode(bool mode)
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL,
+	                MPU6050_I2C_SLV4_REG_DIS_BIT, mode);
 }
 /** Get Slave 4 master delay value.
  * This configures the reduced access rate of I2C slaves relative to the Sample
@@ -1186,17 +1370,21 @@ void MPU6050_setSlave4WriteMode(bool mode) {
  * @return Current Slave 4 master delay value
  * @see MPU6050_RA_I2C_SLV4_CTRL
  */
-uint8_t MPU6050_getSlave4MasterDelay() {
-    I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_MST_DLY_BIT, MPU6050_I2C_SLV4_MST_DLY_LENGTH, mpu6050.buffer);
-    return mpu6050.buffer[0];
+uint8_t MPU6050_getSlave4MasterDelay()
+{
+	I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL,
+	                MPU6050_I2C_SLV4_MST_DLY_BIT, MPU6050_I2C_SLV4_MST_DLY_LENGTH, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set Slave 4 master delay value.
  * @param delay New Slave 4 master delay value
  * @see getSlave4MasterDelay()
  * @see MPU6050_RA_I2C_SLV4_CTRL
  */
-void MPU6050_setSlave4MasterDelay(uint8_t delay) {
-    I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_MST_DLY_BIT, MPU6050_I2C_SLV4_MST_DLY_LENGTH, delay);
+void MPU6050_setSlave4MasterDelay(uint8_t delay)
+{
+	I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL,
+	                 MPU6050_I2C_SLV4_MST_DLY_BIT, MPU6050_I2C_SLV4_MST_DLY_LENGTH, delay);
 }
 /** Get last available byte read from Slave 4.
  * This register stores the data read from Slave 4. This field is populated
@@ -1204,9 +1392,10 @@ void MPU6050_setSlave4MasterDelay(uint8_t delay) {
  * @return Last available byte read from to Slave 4
  * @see MPU6050_RA_I2C_SLV4_DI
  */
-uint8_t MPU6050_getSlate4InputByte() {
-    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_DI, mpu6050.buffer);
-    return mpu6050.buffer[0];
+uint8_t MPU6050_getSlate4InputByte()
+{
+	I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_DI, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 
 // I2C_MST_STATUS register
@@ -1220,9 +1409,11 @@ uint8_t MPU6050_getSlate4InputByte() {
  * @return FSYNC interrupt status
  * @see MPU6050_RA_I2C_MST_STATUS
  */
-bool MPU6050_getPassthroughStatus() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_PASS_THROUGH_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getPassthroughStatus()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS,
+	               MPU6050_MST_PASS_THROUGH_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Get Slave 4 transaction done status.
  * Automatically sets to 1 when a Slave 4 transaction has completed. This
@@ -1232,9 +1423,11 @@ bool MPU6050_getPassthroughStatus() {
  * @return Slave 4 transaction done status
  * @see MPU6050_RA_I2C_MST_STATUS
  */
-bool MPU6050_getSlave4IsDone() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV4_DONE_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getSlave4IsDone()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS,
+	               MPU6050_MST_I2C_SLV4_DONE_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Get master arbitration lost status.
  * This bit automatically sets to 1 when the I2C Master has lost arbitration of
@@ -1243,9 +1436,11 @@ bool MPU6050_getSlave4IsDone() {
  * @return Master arbitration lost status
  * @see MPU6050_RA_I2C_MST_STATUS
  */
-bool MPU6050_getLostArbitration() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_LOST_ARB_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getLostArbitration()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS,
+	               MPU6050_MST_I2C_LOST_ARB_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Get Slave 4 NACK status.
  * This bit automatically sets to 1 when the I2C Master receives a NACK in a
@@ -1254,9 +1449,11 @@ bool MPU6050_getLostArbitration() {
  * @return Slave 4 NACK interrupt status
  * @see MPU6050_RA_I2C_MST_STATUS
  */
-bool MPU6050_getSlave4Nack() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV4_NACK_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getSlave4Nack()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS,
+	               MPU6050_MST_I2C_SLV4_NACK_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Get Slave 3 NACK status.
  * This bit automatically sets to 1 when the I2C Master receives a NACK in a
@@ -1265,9 +1462,11 @@ bool MPU6050_getSlave4Nack() {
  * @return Slave 3 NACK interrupt status
  * @see MPU6050_RA_I2C_MST_STATUS
  */
-bool MPU6050_getSlave3Nack() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV3_NACK_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getSlave3Nack()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS,
+	               MPU6050_MST_I2C_SLV3_NACK_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Get Slave 2 NACK status.
  * This bit automatically sets to 1 when the I2C Master receives a NACK in a
@@ -1276,9 +1475,11 @@ bool MPU6050_getSlave3Nack() {
  * @return Slave 2 NACK interrupt status
  * @see MPU6050_RA_I2C_MST_STATUS
  */
-bool MPU6050_getSlave2Nack() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV2_NACK_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getSlave2Nack()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS,
+	               MPU6050_MST_I2C_SLV2_NACK_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Get Slave 1 NACK status.
  * This bit automatically sets to 1 when the I2C Master receives a NACK in a
@@ -1287,9 +1488,11 @@ bool MPU6050_getSlave2Nack() {
  * @return Slave 1 NACK interrupt status
  * @see MPU6050_RA_I2C_MST_STATUS
  */
-bool MPU6050_getSlave1Nack() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV1_NACK_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getSlave1Nack()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS,
+	               MPU6050_MST_I2C_SLV1_NACK_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Get Slave 0 NACK status.
  * This bit automatically sets to 1 when the I2C Master receives a NACK in a
@@ -1298,9 +1501,11 @@ bool MPU6050_getSlave1Nack() {
  * @return Slave 0 NACK interrupt status
  * @see MPU6050_RA_I2C_MST_STATUS
  */
-bool MPU6050_getSlave0Nack() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV0_NACK_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getSlave0Nack()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS,
+	               MPU6050_MST_I2C_SLV0_NACK_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 
 // INT_PIN_CFG register
@@ -1311,9 +1516,11 @@ bool MPU6050_getSlave0Nack() {
  * @see MPU6050_RA_INT_PIN_CFG
  * @see MPU6050_INTCFG_INT_LEVEL_BIT
  */
-bool MPU6050_getInterruptMode() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_LEVEL_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getInterruptMode()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG,
+	               MPU6050_INTCFG_INT_LEVEL_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set interrupt logic level mode.
  * @param mode New interrupt mode (0=active-high, 1=active-low)
@@ -1321,8 +1528,10 @@ bool MPU6050_getInterruptMode() {
  * @see MPU6050_RA_INT_PIN_CFG
  * @see MPU6050_INTCFG_INT_LEVEL_BIT
  */
-void MPU6050_setInterruptMode(bool mode) {
-   I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_LEVEL_BIT, mode);
+void MPU6050_setInterruptMode(bool mode)
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG,
+	                MPU6050_INTCFG_INT_LEVEL_BIT, mode);
 }
 /** Get interrupt drive mode.
  * Will be set 0 for push-pull, 1 for open-drain.
@@ -1330,9 +1539,11 @@ void MPU6050_setInterruptMode(bool mode) {
  * @see MPU6050_RA_INT_PIN_CFG
  * @see MPU6050_INTCFG_INT_OPEN_BIT
  */
-bool MPU6050_getInterruptDrive() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_OPEN_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getInterruptDrive()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG,
+	               MPU6050_INTCFG_INT_OPEN_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set interrupt drive mode.
  * @param drive New interrupt drive mode (0=push-pull, 1=open-drain)
@@ -1340,8 +1551,10 @@ bool MPU6050_getInterruptDrive() {
  * @see MPU6050_RA_INT_PIN_CFG
  * @see MPU6050_INTCFG_INT_OPEN_BIT
  */
-void MPU6050_setInterruptDrive(bool drive) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_OPEN_BIT, drive);
+void MPU6050_setInterruptDrive(bool drive)
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG,
+	                MPU6050_INTCFG_INT_OPEN_BIT, drive);
 }
 /** Get interrupt latch mode.
  * Will be set 0 for 50us-pulse, 1 for latch-until-int-cleared.
@@ -1349,9 +1562,11 @@ void MPU6050_setInterruptDrive(bool drive) {
  * @see MPU6050_RA_INT_PIN_CFG
  * @see MPU6050_INTCFG_LATCH_INT_EN_BIT
  */
-bool MPU6050_getInterruptLatch() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_LATCH_INT_EN_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getInterruptLatch()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG,
+	               MPU6050_INTCFG_LATCH_INT_EN_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set interrupt latch mode.
  * @param latch New latch mode (0=50us-pulse, 1=latch-until-int-cleared)
@@ -1359,8 +1574,10 @@ bool MPU6050_getInterruptLatch() {
  * @see MPU6050_RA_INT_PIN_CFG
  * @see MPU6050_INTCFG_LATCH_INT_EN_BIT
  */
-void MPU6050_setInterruptLatch(bool latch) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_LATCH_INT_EN_BIT, latch);
+void MPU6050_setInterruptLatch(bool latch)
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG,
+	                MPU6050_INTCFG_LATCH_INT_EN_BIT, latch);
 }
 /** Get interrupt latch clear mode.
  * Will be set 0 for status-read-only, 1 for any-register-read.
@@ -1368,9 +1585,11 @@ void MPU6050_setInterruptLatch(bool latch) {
  * @see MPU6050_RA_INT_PIN_CFG
  * @see MPU6050_INTCFG_INT_RD_CLEAR_BIT
  */
-bool MPU6050_getInterruptLatchClear() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_RD_CLEAR_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getInterruptLatchClear()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG,
+	               MPU6050_INTCFG_INT_RD_CLEAR_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set interrupt latch clear mode.
  * @param clear New latch clear mode (0=status-read-only, 1=any-register-read)
@@ -1378,8 +1597,10 @@ bool MPU6050_getInterruptLatchClear() {
  * @see MPU6050_RA_INT_PIN_CFG
  * @see MPU6050_INTCFG_INT_RD_CLEAR_BIT
  */
-void MPU6050_setInterruptLatchClear(bool clear) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_RD_CLEAR_BIT, clear);
+void MPU6050_setInterruptLatchClear(bool clear)
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG,
+	                MPU6050_INTCFG_INT_RD_CLEAR_BIT, clear);
 }
 /** Get FSYNC interrupt logic level mode.
  * @return Current FSYNC interrupt mode (0=active-high, 1=active-low)
@@ -1387,9 +1608,11 @@ void MPU6050_setInterruptLatchClear(bool clear) {
  * @see MPU6050_RA_INT_PIN_CFG
  * @see MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT
  */
-bool MPU6050_getFSyncInterruptLevel() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getFSyncInterruptLevel()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG,
+	               MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set FSYNC interrupt logic level mode.
  * @param mode New FSYNC interrupt mode (0=active-high, 1=active-low)
@@ -1397,8 +1620,10 @@ bool MPU6050_getFSyncInterruptLevel() {
  * @see MPU6050_RA_INT_PIN_CFG
  * @see MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT
  */
-void MPU6050_setFSyncInterruptLevel(bool level) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT, level);
+void MPU6050_setFSyncInterruptLevel(bool level)
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG,
+	                MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT, level);
 }
 /** Get FSYNC pin interrupt enabled setting.
  * Will be set 0 for disabled, 1 for enabled.
@@ -1406,9 +1631,11 @@ void MPU6050_setFSyncInterruptLevel(bool level) {
  * @see MPU6050_RA_INT_PIN_CFG
  * @see MPU6050_INTCFG_FSYNC_INT_EN_BIT
  */
-bool MPU6050_getFSyncInterruptEnabled() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_EN_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getFSyncInterruptEnabled()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG,
+	               MPU6050_INTCFG_FSYNC_INT_EN_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set FSYNC pin interrupt enabled setting.
  * @param enabled New FSYNC pin interrupt enabled setting
@@ -1416,8 +1643,10 @@ bool MPU6050_getFSyncInterruptEnabled() {
  * @see MPU6050_RA_INT_PIN_CFG
  * @see MPU6050_INTCFG_FSYNC_INT_EN_BIT
  */
-void MPU6050_setFSyncInterruptEnabled(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_EN_BIT, enabled);
+void MPU6050_setFSyncInterruptEnabled(bool enabled)
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG,
+	                MPU6050_INTCFG_FSYNC_INT_EN_BIT, enabled);
 }
 /** Get I2C bypass enabled status.
  * When this bit is equal to 1 and I2C_MST_EN (Register 106 bit[5]) is equal to
@@ -1430,9 +1659,11 @@ void MPU6050_setFSyncInterruptEnabled(bool enabled) {
  * @see MPU6050_RA_INT_PIN_CFG
  * @see MPU6050_INTCFG_I2C_BYPASS_EN_BIT
  */
-bool MPU6050_getI2CBypassEnabled() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_I2C_BYPASS_EN_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getI2CBypassEnabled()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG,
+	               MPU6050_INTCFG_I2C_BYPASS_EN_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set I2C bypass enabled status.
  * When this bit is equal to 1 and I2C_MST_EN (Register 106 bit[5]) is equal to
@@ -1445,8 +1676,10 @@ bool MPU6050_getI2CBypassEnabled() {
  * @see MPU6050_RA_INT_PIN_CFG
  * @see MPU6050_INTCFG_I2C_BYPASS_EN_BIT
  */
-void MPU6050_setI2CBypassEnabled(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_I2C_BYPASS_EN_BIT, enabled);
+void MPU6050_setI2CBypassEnabled(bool enabled)
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG,
+	                MPU6050_INTCFG_I2C_BYPASS_EN_BIT, enabled);
 }
 /** Get reference clock output enabled status.
  * When this bit is equal to 1, a reference clock output is provided at the
@@ -1457,9 +1690,11 @@ void MPU6050_setI2CBypassEnabled(bool enabled) {
  * @see MPU6050_RA_INT_PIN_CFG
  * @see MPU6050_INTCFG_CLKOUT_EN_BIT
  */
-bool MPU6050_getClockOutputEnabled() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_CLKOUT_EN_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getClockOutputEnabled()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG,
+	               MPU6050_INTCFG_CLKOUT_EN_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set reference clock output enabled status.
  * When this bit is equal to 1, a reference clock output is provided at the
@@ -1470,8 +1705,10 @@ bool MPU6050_getClockOutputEnabled() {
  * @see MPU6050_RA_INT_PIN_CFG
  * @see MPU6050_INTCFG_CLKOUT_EN_BIT
  */
-void MPU6050_setClockOutputEnabled(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_CLKOUT_EN_BIT, enabled);
+void MPU6050_setClockOutputEnabled(bool enabled)
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG,
+	                MPU6050_INTCFG_CLKOUT_EN_BIT, enabled);
 }
 
 // INT_ENABLE register
@@ -1483,9 +1720,10 @@ void MPU6050_setClockOutputEnabled(bool enabled) {
  * @see MPU6050_RA_INT_ENABLE
  * @see MPU6050_INTERRUPT_FF_BIT
  **/
-uint8_t MPU6050_getIntEnabled() {
-    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, mpu6050.buffer);
-    return mpu6050.buffer[0];
+uint8_t MPU6050_getIntEnabled()
+{
+	I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set full interrupt enabled status.
  * Full register byte for all interrupts, for quick reading. Each bit should be
@@ -1495,8 +1733,9 @@ uint8_t MPU6050_getIntEnabled() {
  * @see MPU6050_RA_INT_ENABLE
  * @see MPU6050_INTERRUPT_FF_BIT
  **/
-void MPU6050_setIntEnabled(uint8_t enabled) {
-    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, enabled);
+void MPU6050_setIntEnabled(uint8_t enabled)
+{
+	I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, enabled);
 }
 /** Get Free Fall interrupt enabled status.
  * Will be set 0 for disabled, 1 for enabled.
@@ -1504,9 +1743,11 @@ void MPU6050_setIntEnabled(uint8_t enabled) {
  * @see MPU6050_RA_INT_ENABLE
  * @see MPU6050_INTERRUPT_FF_BIT
  **/
-bool MPU6050_getIntFreefallEnabled() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FF_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getIntFreefallEnabled()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FF_BIT,
+	               mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set Free Fall interrupt enabled status.
  * @param enabled New interrupt enabled status
@@ -1514,8 +1755,10 @@ bool MPU6050_getIntFreefallEnabled() {
  * @see MPU6050_RA_INT_ENABLE
  * @see MPU6050_INTERRUPT_FF_BIT
  **/
-void MPU6050_setIntFreefallEnabled(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FF_BIT, enabled);
+void MPU6050_setIntFreefallEnabled(bool enabled)
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE,
+	                MPU6050_INTERRUPT_FF_BIT, enabled);
 }
 /** Get Motion Detection interrupt enabled status.
  * Will be set 0 for disabled, 1 for enabled.
@@ -1523,9 +1766,11 @@ void MPU6050_setIntFreefallEnabled(bool enabled) {
  * @see MPU6050_RA_INT_ENABLE
  * @see MPU6050_INTERRUPT_MOT_BIT
  **/
-bool MPU6050_getIntMotionEnabled() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_MOT_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getIntMotionEnabled()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE,
+	               MPU6050_INTERRUPT_MOT_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set Motion Detection interrupt enabled status.
  * @param enabled New interrupt enabled status
@@ -1533,8 +1778,10 @@ bool MPU6050_getIntMotionEnabled() {
  * @see MPU6050_RA_INT_ENABLE
  * @see MPU6050_INTERRUPT_MOT_BIT
  **/
-void MPU6050_setIntMotionEnabled(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_MOT_BIT, enabled);
+void MPU6050_setIntMotionEnabled(bool enabled)
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE,
+	                MPU6050_INTERRUPT_MOT_BIT, enabled);
 }
 /** Get Zero Motion Detection interrupt enabled status.
  * Will be set 0 for disabled, 1 for enabled.
@@ -1542,9 +1789,11 @@ void MPU6050_setIntMotionEnabled(bool enabled) {
  * @see MPU6050_RA_INT_ENABLE
  * @see MPU6050_INTERRUPT_ZMOT_BIT
  **/
-bool MPU6050_getIntZeroMotionEnabled() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_ZMOT_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getIntZeroMotionEnabled()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE,
+	               MPU6050_INTERRUPT_ZMOT_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set Zero Motion Detection interrupt enabled status.
  * @param enabled New interrupt enabled status
@@ -1552,8 +1801,10 @@ bool MPU6050_getIntZeroMotionEnabled() {
  * @see MPU6050_RA_INT_ENABLE
  * @see MPU6050_INTERRUPT_ZMOT_BIT
  **/
-void MPU6050_setIntZeroMotionEnabled(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_ZMOT_BIT, enabled);
+void MPU6050_setIntZeroMotionEnabled(bool enabled)
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE,
+	                MPU6050_INTERRUPT_ZMOT_BIT, enabled);
 }
 /** Get FIFO Buffer Overflow interrupt enabled status.
  * Will be set 0 for disabled, 1 for enabled.
@@ -1561,9 +1812,11 @@ void MPU6050_setIntZeroMotionEnabled(bool enabled) {
  * @see MPU6050_RA_INT_ENABLE
  * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT
  **/
-bool MPU6050_getIntFIFOBufferOverflowEnabled() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getIntFIFOBufferOverflowEnabled()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE,
+	               MPU6050_INTERRUPT_FIFO_OFLOW_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set FIFO Buffer Overflow interrupt enabled status.
  * @param enabled New interrupt enabled status
@@ -1571,8 +1824,10 @@ bool MPU6050_getIntFIFOBufferOverflowEnabled() {
  * @see MPU6050_RA_INT_ENABLE
  * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT
  **/
-void MPU6050_setIntFIFOBufferOverflowEnabled(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, enabled);
+void MPU6050_setIntFIFOBufferOverflowEnabled(bool enabled)
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE,
+	                MPU6050_INTERRUPT_FIFO_OFLOW_BIT, enabled);
 }
 /** Get I2C Master interrupt enabled status.
  * This enables any of the I2C Master interrupt sources to generate an
@@ -1581,9 +1836,11 @@ void MPU6050_setIntFIFOBufferOverflowEnabled(bool enabled) {
  * @see MPU6050_RA_INT_ENABLE
  * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT
  **/
-bool MPU6050_getIntI2CMasterEnabled() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_I2C_MST_INT_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getIntI2CMasterEnabled()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE,
+	               MPU6050_INTERRUPT_I2C_MST_INT_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set I2C Master interrupt enabled status.
  * @param enabled New interrupt enabled status
@@ -1591,8 +1848,10 @@ bool MPU6050_getIntI2CMasterEnabled() {
  * @see MPU6050_RA_INT_ENABLE
  * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT
  **/
-void MPU6050_setIntI2CMasterEnabled(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_I2C_MST_INT_BIT, enabled);
+void MPU6050_setIntI2CMasterEnabled(bool enabled)
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE,
+	                MPU6050_INTERRUPT_I2C_MST_INT_BIT, enabled);
 }
 /** Get Data Ready interrupt enabled setting.
  * This event occurs each time a write operation to all of the sensor registers
@@ -1601,9 +1860,11 @@ void MPU6050_setIntI2CMasterEnabled(bool enabled) {
  * @see MPU6050_RA_INT_ENABLE
  * @see MPU6050_INTERRUPT_DATA_RDY_BIT
  */
-bool MPU6050_getIntDataReadyEnabled() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DATA_RDY_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getIntDataReadyEnabled()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE,
+	               MPU6050_INTERRUPT_DATA_RDY_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set Data Ready interrupt enabled status.
  * @param enabled New interrupt enabled status
@@ -1611,8 +1872,10 @@ bool MPU6050_getIntDataReadyEnabled() {
  * @see MPU6050_RA_INT_CFG
  * @see MPU6050_INTERRUPT_DATA_RDY_BIT
  */
-void MPU6050_setIntDataReadyEnabled(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DATA_RDY_BIT, enabled);
+void MPU6050_setIntDataReadyEnabled(bool enabled)
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE,
+	                MPU6050_INTERRUPT_DATA_RDY_BIT, enabled);
 }
 
 // INT_STATUS register
@@ -1624,9 +1887,10 @@ void MPU6050_setIntDataReadyEnabled(bool enabled) {
  * @return Current interrupt status
  * @see MPU6050_RA_INT_STATUS
  */
-uint8_t MPU6050_getIntStatus() {
-    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_INT_STATUS, mpu6050.buffer);
-    return mpu6050.buffer[0];
+uint8_t MPU6050_getIntStatus()
+{
+	I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_INT_STATUS, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Get Free Fall interrupt status.
  * This bit automatically sets to 1 when a Free Fall interrupt has been
@@ -1635,9 +1899,11 @@ uint8_t MPU6050_getIntStatus() {
  * @see MPU6050_RA_INT_STATUS
  * @see MPU6050_INTERRUPT_FF_BIT
  */
-bool MPU6050_getIntFreefallStatus() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_FF_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getIntFreefallStatus()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_FF_BIT,
+	               mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Get Motion Detection interrupt status.
  * This bit automatically sets to 1 when a Motion Detection interrupt has been
@@ -1646,9 +1912,11 @@ bool MPU6050_getIntFreefallStatus() {
  * @see MPU6050_RA_INT_STATUS
  * @see MPU6050_INTERRUPT_MOT_BIT
  */
-bool MPU6050_getIntMotionStatus() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_MOT_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getIntMotionStatus()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS,
+	               MPU6050_INTERRUPT_MOT_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Get Zero Motion Detection interrupt status.
  * This bit automatically sets to 1 when a Zero Motion Detection interrupt has
@@ -1657,9 +1925,11 @@ bool MPU6050_getIntMotionStatus() {
  * @see MPU6050_RA_INT_STATUS
  * @see MPU6050_INTERRUPT_ZMOT_BIT
  */
-bool MPU6050_getIntZeroMotionStatus() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_ZMOT_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getIntZeroMotionStatus()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS,
+	               MPU6050_INTERRUPT_ZMOT_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Get FIFO Buffer Overflow interrupt status.
  * This bit automatically sets to 1 when a Free Fall interrupt has been
@@ -1668,9 +1938,11 @@ bool MPU6050_getIntZeroMotionStatus() {
  * @see MPU6050_RA_INT_STATUS
  * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT
  */
-bool MPU6050_getIntFIFOBufferOverflowStatus() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getIntFIFOBufferOverflowStatus()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS,
+	               MPU6050_INTERRUPT_FIFO_OFLOW_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Get I2C Master interrupt status.
  * This bit automatically sets to 1 when an I2C Master interrupt has been
@@ -1680,9 +1952,11 @@ bool MPU6050_getIntFIFOBufferOverflowStatus() {
  * @see MPU6050_RA_INT_STATUS
  * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT
  */
-bool MPU6050_getIntI2CMasterStatus() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_I2C_MST_INT_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getIntI2CMasterStatus()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS,
+	               MPU6050_INTERRUPT_I2C_MST_INT_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Get Data Ready interrupt status.
  * This bit automatically sets to 1 when a Data Ready interrupt has been
@@ -1691,9 +1965,11 @@ bool MPU6050_getIntI2CMasterStatus() {
  * @see MPU6050_RA_INT_STATUS
  * @see MPU6050_INTERRUPT_DATA_RDY_BIT
  */
-bool MPU6050_getIntDataReadyStatus() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_DATA_RDY_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getIntDataReadyStatus()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS,
+	               MPU6050_INTERRUPT_DATA_RDY_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 
 // ACCEL_*OUT_* registers
@@ -1714,9 +1990,11 @@ bool MPU6050_getIntDataReadyStatus() {
  * @see getRotation()
  * @see MPU6050_RA_ACCEL_XOUT_H
  */
-void MPU6050_getMotion9(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz, int16_t* mx, int16_t* my, int16_t* mz) {
-    MPU6050_getMotion6(ax, ay, az, gx, gy, gz);
-    // TODO: magnetometer integration
+void MPU6050_getMotion9(int16_t *ax, int16_t *ay, int16_t *az, int16_t *gx,
+                        int16_t *gy, int16_t *gz, int16_t *mx, int16_t *my, int16_t *mz)
+{
+	MPU6050_getMotion6(ax, ay, az, gx, gy, gz);
+	// TODO: magnetometer integration
 }
 /** Get raw 6-axis motion sensor readings (accel/gyro).
  * Retrieves all currently available motion sensor values.
@@ -1730,14 +2008,16 @@ void MPU6050_getMotion9(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int1
  * @see getRotation()
  * @see MPU6050_RA_ACCEL_XOUT_H
  */
-void MPU6050_getMotion6(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz) {
-    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ACCEL_XOUT_H, 14, mpu6050.buffer);
-    *ax = (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
-    *ay = (((int16_t)mpu6050.buffer[2]) << 8) | mpu6050.buffer[3];
-    *az = (((int16_t)mpu6050.buffer[4]) << 8) | mpu6050.buffer[5];
-    *gx = (((int16_t)mpu6050.buffer[8]) << 8) | mpu6050.buffer[9];
-    *gy = (((int16_t)mpu6050.buffer[10]) << 8) | mpu6050.buffer[11];
-    *gz = (((int16_t)mpu6050.buffer[12]) << 8) | mpu6050.buffer[13];
+void MPU6050_getMotion6(int16_t *ax, int16_t *ay, int16_t *az, int16_t *gx,
+                        int16_t *gy, int16_t *gz)
+{
+	I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ACCEL_XOUT_H, 14, mpu6050.buffer);
+	*ax = (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+	*ay = (((int16_t)mpu6050.buffer[2]) << 8) | mpu6050.buffer[3];
+	*az = (((int16_t)mpu6050.buffer[4]) << 8) | mpu6050.buffer[5];
+	*gx = (((int16_t)mpu6050.buffer[8]) << 8) | mpu6050.buffer[9];
+	*gy = (((int16_t)mpu6050.buffer[10]) << 8) | mpu6050.buffer[11];
+	*gz = (((int16_t)mpu6050.buffer[12]) << 8) | mpu6050.buffer[13];
 }
 /** Get 3-axis accelerometer readings.
  * These registers store the most recent accelerometer measurements.
@@ -1775,38 +2055,42 @@ void MPU6050_getMotion6(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int1
  * @param z 16-bit signed integer container for Z-axis acceleration
  * @see MPU6050_RA_GYRO_XOUT_H
  */
-void MPU6050_getAcceleration(int16_t* x, int16_t* y, int16_t* z) {
-    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ACCEL_XOUT_H, 6, mpu6050.buffer);
-    *x = (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
-    *y = (((int16_t)mpu6050.buffer[2]) << 8) | mpu6050.buffer[3];
-    *z = (((int16_t)mpu6050.buffer[4]) << 8) | mpu6050.buffer[5];
+void MPU6050_getAcceleration(int16_t *x, int16_t *y, int16_t *z)
+{
+	I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ACCEL_XOUT_H, 6, mpu6050.buffer);
+	*x = (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+	*y = (((int16_t)mpu6050.buffer[2]) << 8) | mpu6050.buffer[3];
+	*z = (((int16_t)mpu6050.buffer[4]) << 8) | mpu6050.buffer[5];
 }
 /** Get X-axis accelerometer reading.
  * @return X-axis acceleration measurement in 16-bit 2's complement format
  * @see getMotion6()
  * @see MPU6050_RA_ACCEL_XOUT_H
  */
-int16_t MPU6050_getAccelerationX() {
-    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ACCEL_XOUT_H, 2, mpu6050.buffer);
-    return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+int16_t MPU6050_getAccelerationX()
+{
+	I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ACCEL_XOUT_H, 2, mpu6050.buffer);
+	return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
 }
 /** Get Y-axis accelerometer reading.
  * @return Y-axis acceleration measurement in 16-bit 2's complement format
  * @see getMotion6()
  * @see MPU6050_RA_ACCEL_YOUT_H
  */
-int16_t MPU6050_getAccelerationY() {
-    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ACCEL_YOUT_H, 2, mpu6050.buffer);
-    return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+int16_t MPU6050_getAccelerationY()
+{
+	I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ACCEL_YOUT_H, 2, mpu6050.buffer);
+	return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
 }
 /** Get Z-axis accelerometer reading.
  * @return Z-axis acceleration measurement in 16-bit 2's complement format
  * @see getMotion6()
  * @see MPU6050_RA_ACCEL_ZOUT_H
  */
-int16_t MPU6050_getAccelerationZ() {
-    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ACCEL_ZOUT_H, 2, mpu6050.buffer);
-    return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+int16_t MPU6050_getAccelerationZ()
+{
+	I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ACCEL_ZOUT_H, 2, mpu6050.buffer);
+	return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
 }
 
 // TEMP_OUT_* registers
@@ -1815,9 +2099,10 @@ int16_t MPU6050_getAccelerationZ() {
  * @return Temperature reading in 16-bit 2's complement format
  * @see MPU6050_RA_TEMP_OUT_H
  */
-int16_t MPU6050_getTemperature() {
-    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_TEMP_OUT_H, 2, mpu6050.buffer);
-    return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+int16_t MPU6050_getTemperature()
+{
+	I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_TEMP_OUT_H, 2, mpu6050.buffer);
+	return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
 }
 
 // GYRO_*OUT_* registers
@@ -1854,38 +2139,42 @@ int16_t MPU6050_getTemperature() {
  * @see getMotion6()
  * @see MPU6050_RA_GYRO_XOUT_H
  */
-void MPU6050_getRotation(int16_t* x, int16_t* y, int16_t* z) {
-    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_GYRO_XOUT_H, 6, mpu6050.buffer);
-    *x = (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
-    *y = (((int16_t)mpu6050.buffer[2]) << 8) | mpu6050.buffer[3];
-    *z = (((int16_t)mpu6050.buffer[4]) << 8) | mpu6050.buffer[5];
+void MPU6050_getRotation(int16_t *x, int16_t *y, int16_t *z)
+{
+	I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_GYRO_XOUT_H, 6, mpu6050.buffer);
+	*x = (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+	*y = (((int16_t)mpu6050.buffer[2]) << 8) | mpu6050.buffer[3];
+	*z = (((int16_t)mpu6050.buffer[4]) << 8) | mpu6050.buffer[5];
 }
 /** Get X-axis gyroscope reading.
  * @return X-axis rotation measurement in 16-bit 2's complement format
  * @see getMotion6()
  * @see MPU6050_RA_GYRO_XOUT_H
  */
-int16_t MPU6050_getRotationX() {
-    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_GYRO_XOUT_H, 2, mpu6050.buffer);
-    return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+int16_t MPU6050_getRotationX()
+{
+	I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_GYRO_XOUT_H, 2, mpu6050.buffer);
+	return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
 }
 /** Get Y-axis gyroscope reading.
  * @return Y-axis rotation measurement in 16-bit 2's complement format
  * @see getMotion6()
  * @see MPU6050_RA_GYRO_YOUT_H
  */
-int16_t MPU6050_getRotationY() {
-    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_GYRO_YOUT_H, 2, mpu6050.buffer);
-    return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+int16_t MPU6050_getRotationY()
+{
+	I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_GYRO_YOUT_H, 2, mpu6050.buffer);
+	return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
 }
 /** Get Z-axis gyroscope reading.
  * @return Z-axis rotation measurement in 16-bit 2's complement format
  * @see getMotion6()
  * @see MPU6050_RA_GYRO_ZOUT_H
  */
-int16_t MPU6050_getRotationZ() {
-    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_GYRO_ZOUT_H, 2, mpu6050.buffer);
-    return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+int16_t MPU6050_getRotationZ()
+{
+	I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_GYRO_ZOUT_H, 2, mpu6050.buffer);
+	return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
 }
 
 // EXT_SENS_DATA_* registers
@@ -1964,27 +2253,34 @@ int16_t MPU6050_getRotationZ() {
  * @param position Starting position (0-23)
  * @return Byte read from register
  */
-uint8_t MPU6050_getExternalSensorByte(int position) {
-    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, mpu6050.buffer);
-    return mpu6050.buffer[0];
+uint8_t MPU6050_getExternalSensorByte(int position)
+{
+	I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position,
+	                mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Read word (2 bytes) from external sensor data registers.
  * @param position Starting position (0-21)
  * @return Word read from register
  * @see getExternalSensorByte()
  */
-uint16_t MPU6050_getExternalSensorWord(int position) {
-    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, 2, mpu6050.buffer);
-    return (((uint16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+uint16_t MPU6050_getExternalSensorWord(int position)
+{
+	I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, 2,
+	                 mpu6050.buffer);
+	return (((uint16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
 }
 /** Read double word (4 bytes) from external sensor data registers.
  * @param position Starting position (0-20)
  * @return Double word read from registers
  * @see getExternalSensorByte()
  */
-uint32_t MPU6050_getExternalSensorDWord(int position) {
-    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, 4, mpu6050.buffer);
-    return (((uint32_t)mpu6050.buffer[0]) << 24) | (((uint32_t)mpu6050.buffer[1]) << 16) | (((uint16_t)mpu6050.buffer[2]) << 8) | mpu6050.buffer[3];
+uint32_t MPU6050_getExternalSensorDWord(int position)
+{
+	I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, 4,
+	                 mpu6050.buffer);
+	return (((uint32_t)mpu6050.buffer[0]) << 24) | (((uint32_t)mpu6050.buffer[1]) <<
+	        16) | (((uint16_t)mpu6050.buffer[2]) << 8) | mpu6050.buffer[3];
 }
 
 // MOT_DETECT_STATUS register
@@ -1994,63 +2290,77 @@ uint32_t MPU6050_getExternalSensorDWord(int position) {
  * @see MPU6050_RA_MOT_DETECT_STATUS
  * @see MPU6050_MOTION_MOT_XNEG_BIT
  */
-bool MPU6050_getXNegMotionDetected() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_XNEG_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getXNegMotionDetected()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS,
+	               MPU6050_MOTION_MOT_XNEG_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Get X-axis positive motion detection interrupt status.
  * @return Motion detection status
  * @see MPU6050_RA_MOT_DETECT_STATUS
  * @see MPU6050_MOTION_MOT_XPOS_BIT
  */
-bool MPU6050_getXPosMotionDetected() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_XPOS_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getXPosMotionDetected()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS,
+	               MPU6050_MOTION_MOT_XPOS_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Get Y-axis negative motion detection interrupt status.
  * @return Motion detection status
  * @see MPU6050_RA_MOT_DETECT_STATUS
  * @see MPU6050_MOTION_MOT_YNEG_BIT
  */
-bool MPU6050_getYNegMotionDetected() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_YNEG_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getYNegMotionDetected()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS,
+	               MPU6050_MOTION_MOT_YNEG_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Get Y-axis positive motion detection interrupt status.
  * @return Motion detection status
  * @see MPU6050_RA_MOT_DETECT_STATUS
  * @see MPU6050_MOTION_MOT_YPOS_BIT
  */
-bool MPU6050_getYPosMotionDetected() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_YPOS_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getYPosMotionDetected()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS,
+	               MPU6050_MOTION_MOT_YPOS_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Get Z-axis negative motion detection interrupt status.
  * @return Motion detection status
  * @see MPU6050_RA_MOT_DETECT_STATUS
  * @see MPU6050_MOTION_MOT_ZNEG_BIT
  */
-bool MPU6050_getZNegMotionDetected() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZNEG_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getZNegMotionDetected()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS,
+	               MPU6050_MOTION_MOT_ZNEG_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Get Z-axis positive motion detection interrupt status.
  * @return Motion detection status
  * @see MPU6050_RA_MOT_DETECT_STATUS
  * @see MPU6050_MOTION_MOT_ZPOS_BIT
  */
-bool MPU6050_getZPosMotionDetected() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZPOS_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getZPosMotionDetected()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS,
+	               MPU6050_MOTION_MOT_ZPOS_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Get zero motion detection interrupt status.
  * @return Motion detection status
  * @see MPU6050_RA_MOT_DETECT_STATUS
  * @see MPU6050_MOTION_MOT_ZRMOT_BIT
  */
-bool MPU6050_getZeroMotionDetected() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZRMOT_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getZeroMotionDetected()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS,
+	               MPU6050_MOTION_MOT_ZRMOT_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 
 // I2C_SLV*_DO register
@@ -2063,9 +2373,10 @@ bool MPU6050_getZeroMotionDetected() {
  * @param data Byte to write
  * @see MPU6050_RA_I2C_SLV0_DO
  */
-void MPU6050_setSlaveOutputByte(uint8_t num, uint8_t data) {
-    if (num > 3) return;
-    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_DO + num, data);
+void MPU6050_setSlaveOutputByte(uint8_t num, uint8_t data)
+{
+	if (num > 3) return;
+	I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_DO + num, data);
 }
 
 // I2C_MST_DELAY_CTRL register
@@ -2078,9 +2389,11 @@ void MPU6050_setSlaveOutputByte(uint8_t num, uint8_t data) {
  * @see MPU6050_RA_I2C_MST_DELAY_CTRL
  * @see MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT
  */
-bool MPU6050_getExternalShadowDelayEnabled() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getExternalShadowDelayEnabled()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL,
+	               MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set external data shadow delay enabled status.
  * @param enabled New external data shadow delay enabled status.
@@ -2088,8 +2401,10 @@ bool MPU6050_getExternalShadowDelayEnabled() {
  * @see MPU6050_RA_I2C_MST_DELAY_CTRL
  * @see MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT
  */
-void MPU6050_setExternalShadowDelayEnabled(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT, enabled);
+void MPU6050_setExternalShadowDelayEnabled(bool enabled)
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL,
+	                MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT, enabled);
 }
 /** Get slave delay enabled status.
  * When a particular slave delay is enabled, the rate of access for the that
@@ -2109,11 +2424,13 @@ void MPU6050_setExternalShadowDelayEnabled(bool enabled) {
  * @see MPU6050_RA_I2C_MST_DELAY_CTRL
  * @see MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT
  */
-bool MPU6050_getSlaveDelayEnabled(uint8_t num) {
-    // MPU6050_DELAYCTRL_I2C_SLV4_DLY_EN_BIT is 4, SLV3 is 3, etc.
-    if (num > 4) return 0;
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, num, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getSlaveDelayEnabled(uint8_t num)
+{
+	// MPU6050_DELAYCTRL_I2C_SLV4_DLY_EN_BIT is 4, SLV3 is 3, etc.
+	if (num > 4) return 0;
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, num,
+	               mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set slave delay enabled status.
  * @param num Slave number (0-4)
@@ -2121,8 +2438,9 @@ bool MPU6050_getSlaveDelayEnabled(uint8_t num) {
  * @see MPU6050_RA_I2C_MST_DELAY_CTRL
  * @see MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT
  */
-void MPU6050_setSlaveDelayEnabled(uint8_t num, bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, num, enabled);
+void MPU6050_setSlaveDelayEnabled(uint8_t num, bool enabled)
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, num, enabled);
 }
 
 // SIGNAL_PATH_RESET register
@@ -2133,8 +2451,10 @@ void MPU6050_setSlaveDelayEnabled(uint8_t num, bool enabled) {
  * @see MPU6050_RA_SIGNAL_PATH_RESET
  * @see MPU6050_PATHRESET_GYRO_RESET_BIT
  */
-void MPU6050_resetGyroscopePath() {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_GYRO_RESET_BIT, true);
+void MPU6050_resetGyroscopePath()
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_SIGNAL_PATH_RESET,
+	                MPU6050_PATHRESET_GYRO_RESET_BIT, true);
 }
 /** Reset accelerometer signal path.
  * The reset will revert the signal path analog to digital converters and
@@ -2142,8 +2462,10 @@ void MPU6050_resetGyroscopePath() {
  * @see MPU6050_RA_SIGNAL_PATH_RESET
  * @see MPU6050_PATHRESET_ACCEL_RESET_BIT
  */
-void MPU6050_resetAccelerometerPath() {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_ACCEL_RESET_BIT, true);
+void MPU6050_resetAccelerometerPath()
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_SIGNAL_PATH_RESET,
+	                MPU6050_PATHRESET_ACCEL_RESET_BIT, true);
 }
 /** Reset temperature sensor signal path.
  * The reset will revert the signal path analog to digital converters and
@@ -2151,8 +2473,10 @@ void MPU6050_resetAccelerometerPath() {
  * @see MPU6050_RA_SIGNAL_PATH_RESET
  * @see MPU6050_PATHRESET_TEMP_RESET_BIT
  */
-void MPU6050_resetTemperaturePath() {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_TEMP_RESET_BIT, true);
+void MPU6050_resetTemperaturePath()
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_SIGNAL_PATH_RESET,
+	                MPU6050_PATHRESET_TEMP_RESET_BIT, true);
 }
 
 // MOT_DETECT_CTRL register
@@ -2171,9 +2495,12 @@ void MPU6050_resetTemperaturePath() {
  * @see MPU6050_RA_MOT_DETECT_CTRL
  * @see MPU6050_DETECT_ACCEL_ON_DELAY_BIT
  */
-uint8_t MPU6050_getAccelerometerPowerOnDelay() {
-    I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_ACCEL_ON_DELAY_BIT, MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH, mpu6050.buffer);
-    return mpu6050.buffer[0];
+uint8_t MPU6050_getAccelerometerPowerOnDelay()
+{
+	I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_CTRL,
+	                MPU6050_DETECT_ACCEL_ON_DELAY_BIT, MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH,
+	                mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set accelerometer power-on delay.
  * @param delay New accelerometer power-on delay (0-3)
@@ -2181,8 +2508,10 @@ uint8_t MPU6050_getAccelerometerPowerOnDelay() {
  * @see MPU6050_RA_MOT_DETECT_CTRL
  * @see MPU6050_DETECT_ACCEL_ON_DELAY_BIT
  */
-void MPU6050_setAccelerometerPowerOnDelay(uint8_t delay) {
-    I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_ACCEL_ON_DELAY_BIT, MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH, delay);
+void MPU6050_setAccelerometerPowerOnDelay(uint8_t delay)
+{
+	I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_CTRL,
+	                 MPU6050_DETECT_ACCEL_ON_DELAY_BIT, MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH, delay);
 }
 /** Get Free Fall detection counter decrement configuration.
  * Detection is registered by the Free Fall detection module after accelerometer
@@ -2210,9 +2539,11 @@ void MPU6050_setAccelerometerPowerOnDelay(uint8_t delay) {
  * @see MPU6050_RA_MOT_DETECT_CTRL
  * @see MPU6050_DETECT_FF_COUNT_BIT
  */
-uint8_t MPU6050_getFreefallDetectionCounterDecrement() {
-    I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_FF_COUNT_BIT, MPU6050_DETECT_FF_COUNT_LENGTH, mpu6050.buffer);
-    return mpu6050.buffer[0];
+uint8_t MPU6050_getFreefallDetectionCounterDecrement()
+{
+	I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_CTRL,
+	                MPU6050_DETECT_FF_COUNT_BIT, MPU6050_DETECT_FF_COUNT_LENGTH, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set Free Fall detection counter decrement configuration.
  * @param decrement New decrement configuration value
@@ -2220,8 +2551,10 @@ uint8_t MPU6050_getFreefallDetectionCounterDecrement() {
  * @see MPU6050_RA_MOT_DETECT_CTRL
  * @see MPU6050_DETECT_FF_COUNT_BIT
  */
-void MPU6050_setFreefallDetectionCounterDecrement(uint8_t decrement) {
-    I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_FF_COUNT_BIT, MPU6050_DETECT_FF_COUNT_LENGTH, decrement);
+void MPU6050_setFreefallDetectionCounterDecrement(uint8_t decrement)
+{
+	I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_CTRL,
+	                 MPU6050_DETECT_FF_COUNT_BIT, MPU6050_DETECT_FF_COUNT_LENGTH, decrement);
 }
 /** Get Motion detection counter decrement configuration.
  * Detection is registered by the Motion detection module after accelerometer
@@ -2246,9 +2579,11 @@ void MPU6050_setFreefallDetectionCounterDecrement(uint8_t decrement) {
  * please refer to Registers 29 to 32.
  *
  */
-uint8_t MPU6050_getMotionDetectionCounterDecrement() {
-    I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_MOT_COUNT_BIT, MPU6050_DETECT_MOT_COUNT_LENGTH, mpu6050.buffer);
-    return mpu6050.buffer[0];
+uint8_t MPU6050_getMotionDetectionCounterDecrement()
+{
+	I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_CTRL,
+	                MPU6050_DETECT_MOT_COUNT_BIT, MPU6050_DETECT_MOT_COUNT_LENGTH, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set Motion detection counter decrement configuration.
  * @param decrement New decrement configuration value
@@ -2256,8 +2591,10 @@ uint8_t MPU6050_getMotionDetectionCounterDecrement() {
  * @see MPU6050_RA_MOT_DETECT_CTRL
  * @see MPU6050_DETECT_MOT_COUNT_BIT
  */
-void MPU6050_setMotionDetectionCounterDecrement(uint8_t decrement) {
-    I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_MOT_COUNT_BIT, MPU6050_DETECT_MOT_COUNT_LENGTH, decrement);
+void MPU6050_setMotionDetectionCounterDecrement(uint8_t decrement)
+{
+	I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_CTRL,
+	                 MPU6050_DETECT_MOT_COUNT_BIT, MPU6050_DETECT_MOT_COUNT_LENGTH, decrement);
 }
 
 // USER_CTRL register
@@ -2270,9 +2607,11 @@ void MPU6050_setMotionDetectionCounterDecrement(uint8_t decrement) {
  * @see MPU6050_RA_USER_CTRL
  * @see MPU6050_USERCTRL_FIFO_EN_BIT
  */
-bool MPU6050_getFIFOEnabled() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_EN_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getFIFOEnabled()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL,
+	               MPU6050_USERCTRL_FIFO_EN_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set FIFO enabled status.
  * @param enabled New FIFO enabled status
@@ -2280,8 +2619,10 @@ bool MPU6050_getFIFOEnabled() {
  * @see MPU6050_RA_USER_CTRL
  * @see MPU6050_USERCTRL_FIFO_EN_BIT
  */
-void MPU6050_setFIFOEnabled(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_EN_BIT, enabled);
+void MPU6050_setFIFOEnabled(bool enabled)
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL,
+	                MPU6050_USERCTRL_FIFO_EN_BIT, enabled);
 }
 /** Get I2C Master Mode enabled status.
  * When this mode is enabled, the MPU-60X0 acts as the I2C Master to the
@@ -2294,9 +2635,11 @@ void MPU6050_setFIFOEnabled(bool enabled) {
  * @see MPU6050_RA_USER_CTRL
  * @see MPU6050_USERCTRL_I2C_MST_EN_BIT
  */
-bool MPU6050_getI2CMasterModeEnabled() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_EN_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getI2CMasterModeEnabled()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL,
+	               MPU6050_USERCTRL_I2C_MST_EN_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set I2C Master Mode enabled status.
  * @param enabled New I2C Master Mode enabled status
@@ -2304,15 +2647,19 @@ bool MPU6050_getI2CMasterModeEnabled() {
  * @see MPU6050_RA_USER_CTRL
  * @see MPU6050_USERCTRL_I2C_MST_EN_BIT
  */
-void MPU6050_setI2CMasterModeEnabled(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_EN_BIT, enabled);
+void MPU6050_setI2CMasterModeEnabled(bool enabled)
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL,
+	                MPU6050_USERCTRL_I2C_MST_EN_BIT, enabled);
 }
 /** Switch from I2C to SPI mode (MPU-6000 only)
  * If this is set, the primary SPI interface will be enabled in place of the
  * disabled primary I2C interface.
  */
-void MPU6050_switchSPIEnabled(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_IF_DIS_BIT, enabled);
+void MPU6050_switchSPIEnabled(bool enabled)
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL,
+	                MPU6050_USERCTRL_I2C_IF_DIS_BIT, enabled);
 }
 /** Reset the FIFO.
  * This bit resets the FIFO mpu6050.buffer when set to 1 while FIFO_EN equals 0. This
@@ -2320,8 +2667,10 @@ void MPU6050_switchSPIEnabled(bool enabled) {
  * @see MPU6050_RA_USER_CTRL
  * @see MPU6050_USERCTRL_FIFO_RESET_BIT
  */
-void MPU6050_resetFIFO() {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_RESET_BIT, true);
+void MPU6050_resetFIFO()
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL,
+	                MPU6050_USERCTRL_FIFO_RESET_BIT, true);
 }
 /** Reset the I2C Master.
  * This bit resets the I2C Master when set to 1 while I2C_MST_EN equals 0.
@@ -2329,8 +2678,10 @@ void MPU6050_resetFIFO() {
  * @see MPU6050_RA_USER_CTRL
  * @see MPU6050_USERCTRL_I2C_MST_RESET_BIT
  */
-void MPU6050_resetI2CMaster() {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_RESET_BIT, true);
+void MPU6050_resetI2CMaster()
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL,
+	                MPU6050_USERCTRL_I2C_MST_RESET_BIT, true);
 }
 /** Reset all sensor registers and signal paths.
  * When set to 1, this bit resets the signal paths for all sensors (gyroscopes,
@@ -2344,8 +2695,10 @@ void MPU6050_resetI2CMaster() {
  * @see MPU6050_RA_USER_CTRL
  * @see MPU6050_USERCTRL_SIG_COND_RESET_BIT
  */
-void MPU6050_resetSensors() {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_SIG_COND_RESET_BIT, true);
+void MPU6050_resetSensors()
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL,
+	                MPU6050_USERCTRL_SIG_COND_RESET_BIT, true);
 }
 
 // PWR_MGMT_1 register
@@ -2355,8 +2708,10 @@ void MPU6050_resetSensors() {
  * @see MPU6050_RA_PWR_MGMT_1
  * @see MPU6050_PWR1_DEVICE_RESET_BIT
  */
-void MPU6050_reset() {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_DEVICE_RESET_BIT, true);
+void MPU6050_reset()
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1,
+	                MPU6050_PWR1_DEVICE_RESET_BIT, true);
 }
 /** Get sleep mode status.
  * Setting the SLEEP bit in the register puts the device into very low power
@@ -2369,9 +2724,11 @@ void MPU6050_reset() {
  * @see MPU6050_RA_PWR_MGMT_1
  * @see MPU6050_PWR1_SLEEP_BIT
  */
-bool MPU6050_getSleepEnabled() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getSleepEnabled()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT,
+	               mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set sleep mode status.
  * @param enabled New sleep mode enabled status
@@ -2379,8 +2736,10 @@ bool MPU6050_getSleepEnabled() {
  * @see MPU6050_RA_PWR_MGMT_1
  * @see MPU6050_PWR1_SLEEP_BIT
  */
-void MPU6050_setSleepEnabled(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, enabled);
+void MPU6050_setSleepEnabled(bool enabled)
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT,
+	                enabled);
 }
 /** Get wake cycle enabled status.
  * When this bit is set to 1 and SLEEP is disabled, the MPU-60X0 will cycle
@@ -2390,9 +2749,11 @@ void MPU6050_setSleepEnabled(bool enabled) {
  * @see MPU6050_RA_PWR_MGMT_1
  * @see MPU6050_PWR1_CYCLE_BIT
  */
-bool MPU6050_getWakeCycleEnabled() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CYCLE_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getWakeCycleEnabled()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CYCLE_BIT,
+	               mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set wake cycle enabled status.
  * @param enabled New sleep mode enabled status
@@ -2400,8 +2761,10 @@ bool MPU6050_getWakeCycleEnabled() {
  * @see MPU6050_RA_PWR_MGMT_1
  * @see MPU6050_PWR1_CYCLE_BIT
  */
-void MPU6050_setWakeCycleEnabled(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CYCLE_BIT, enabled);
+void MPU6050_setWakeCycleEnabled(bool enabled)
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CYCLE_BIT,
+	                enabled);
 }
 /** Get temperature sensor enabled status.
  * Control the usage of the internal temperature sensor.
@@ -2414,9 +2777,11 @@ void MPU6050_setWakeCycleEnabled(bool enabled) {
  * @see MPU6050_RA_PWR_MGMT_1
  * @see MPU6050_PWR1_TEMP_DIS_BIT
  */
-bool MPU6050_getTempSensorEnabled() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_TEMP_DIS_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0] == 0; // 1 is actually disabled here
+bool MPU6050_getTempSensorEnabled()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1,
+	               MPU6050_PWR1_TEMP_DIS_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0] == 0; // 1 is actually disabled here
 }
 /** Set temperature sensor enabled status.
  * Note: this register stores the *disabled* value, but for consistency with the
@@ -2428,9 +2793,11 @@ bool MPU6050_getTempSensorEnabled() {
  * @see MPU6050_RA_PWR_MGMT_1
  * @see MPU6050_PWR1_TEMP_DIS_BIT
  */
-void MPU6050_setTempSensorEnabled(bool enabled) {
-    // 1 is actually disabled here
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_TEMP_DIS_BIT, !enabled);
+void MPU6050_setTempSensorEnabled(bool enabled)
+{
+	// 1 is actually disabled here
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1,
+	                MPU6050_PWR1_TEMP_DIS_BIT, !enabled);
 }
 /** Get clock source setting.
  * @return Current clock source setting
@@ -2438,9 +2805,11 @@ void MPU6050_setTempSensorEnabled(bool enabled) {
  * @see MPU6050_PWR1_CLKSEL_BIT
  * @see MPU6050_PWR1_CLKSEL_LENGTH
  */
-uint8_t MPU6050_getClockSource() {
-    I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, mpu6050.buffer);
-    return mpu6050.buffer[0];
+uint8_t MPU6050_getClockSource()
+{
+	I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT,
+	                MPU6050_PWR1_CLKSEL_LENGTH, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set clock source setting.
  * An internal 8MHz oscillator, gyroscope based clock, or external sources can
@@ -2472,8 +2841,10 @@ uint8_t MPU6050_getClockSource() {
  * @see MPU6050_PWR1_CLKSEL_BIT
  * @see MPU6050_PWR1_CLKSEL_LENGTH
  */
-void MPU6050_setClockSource(uint8_t source) {
-    I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, source);
+void MPU6050_setClockSource(uint8_t source)
+{
+	I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1,
+	                 MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, source);
 }
 
 // PWR_MGMT_2 register
@@ -2501,16 +2872,21 @@ void MPU6050_setClockSource(uint8_t source) {
  * @return Current wake frequency
  * @see MPU6050_RA_PWR_MGMT_2
  */
-uint8_t MPU6050_getWakeFrequency() {
-    I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_LP_WAKE_CTRL_BIT, MPU6050_PWR2_LP_WAKE_CTRL_LENGTH, mpu6050.buffer);
-    return mpu6050.buffer[0];
+uint8_t MPU6050_getWakeFrequency()
+{
+	I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2,
+	                MPU6050_PWR2_LP_WAKE_CTRL_BIT, MPU6050_PWR2_LP_WAKE_CTRL_LENGTH,
+	                mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set wake frequency in Accel-Only Low Power Mode.
  * @param frequency New wake frequency
  * @see MPU6050_RA_PWR_MGMT_2
  */
-void MPU6050_setWakeFrequency(uint8_t frequency) {
-    I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_LP_WAKE_CTRL_BIT, MPU6050_PWR2_LP_WAKE_CTRL_LENGTH, frequency);
+void MPU6050_setWakeFrequency(uint8_t frequency)
+{
+	I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2,
+	                 MPU6050_PWR2_LP_WAKE_CTRL_BIT, MPU6050_PWR2_LP_WAKE_CTRL_LENGTH, frequency);
 }
 
 /** Get X-axis accelerometer standby enabled status.
@@ -2519,9 +2895,11 @@ void MPU6050_setWakeFrequency(uint8_t frequency) {
  * @see MPU6050_RA_PWR_MGMT_2
  * @see MPU6050_PWR2_STBY_XA_BIT
  */
-bool MPU6050_getStandbyXAccelEnabled() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XA_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getStandbyXAccelEnabled()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XA_BIT,
+	               mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set X-axis accelerometer standby enabled status.
  * @param New X-axis standby enabled status
@@ -2529,8 +2907,10 @@ bool MPU6050_getStandbyXAccelEnabled() {
  * @see MPU6050_RA_PWR_MGMT_2
  * @see MPU6050_PWR2_STBY_XA_BIT
  */
-void MPU6050_setStandbyXAccelEnabled(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XA_BIT, enabled);
+void MPU6050_setStandbyXAccelEnabled(bool enabled)
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2,
+	                MPU6050_PWR2_STBY_XA_BIT, enabled);
 }
 /** Get Y-axis accelerometer standby enabled status.
  * If enabled, the Y-axis will not gather or report data (or use power).
@@ -2538,9 +2918,11 @@ void MPU6050_setStandbyXAccelEnabled(bool enabled) {
  * @see MPU6050_RA_PWR_MGMT_2
  * @see MPU6050_PWR2_STBY_YA_BIT
  */
-bool MPU6050_getStandbyYAccelEnabled() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YA_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getStandbyYAccelEnabled()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YA_BIT,
+	               mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set Y-axis accelerometer standby enabled status.
  * @param New Y-axis standby enabled status
@@ -2548,8 +2930,10 @@ bool MPU6050_getStandbyYAccelEnabled() {
  * @see MPU6050_RA_PWR_MGMT_2
  * @see MPU6050_PWR2_STBY_YA_BIT
  */
-void MPU6050_setStandbyYAccelEnabled(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YA_BIT, enabled);
+void MPU6050_setStandbyYAccelEnabled(bool enabled)
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2,
+	                MPU6050_PWR2_STBY_YA_BIT, enabled);
 }
 /** Get Z-axis accelerometer standby enabled status.
  * If enabled, the Z-axis will not gather or report data (or use power).
@@ -2557,9 +2941,11 @@ void MPU6050_setStandbyYAccelEnabled(bool enabled) {
  * @see MPU6050_RA_PWR_MGMT_2
  * @see MPU6050_PWR2_STBY_ZA_BIT
  */
-bool MPU6050_getStandbyZAccelEnabled() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZA_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getStandbyZAccelEnabled()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZA_BIT,
+	               mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set Z-axis accelerometer standby enabled status.
  * @param New Z-axis standby enabled status
@@ -2567,8 +2953,10 @@ bool MPU6050_getStandbyZAccelEnabled() {
  * @see MPU6050_RA_PWR_MGMT_2
  * @see MPU6050_PWR2_STBY_ZA_BIT
  */
-void MPU6050_setStandbyZAccelEnabled(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZA_BIT, enabled);
+void MPU6050_setStandbyZAccelEnabled(bool enabled)
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2,
+	                MPU6050_PWR2_STBY_ZA_BIT, enabled);
 }
 /** Get X-axis gyroscope standby enabled status.
  * If enabled, the X-axis will not gather or report data (or use power).
@@ -2576,9 +2964,11 @@ void MPU6050_setStandbyZAccelEnabled(bool enabled) {
  * @see MPU6050_RA_PWR_MGMT_2
  * @see MPU6050_PWR2_STBY_XG_BIT
  */
-bool MPU6050_getStandbyXGyroEnabled() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XG_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getStandbyXGyroEnabled()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XG_BIT,
+	               mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set X-axis gyroscope standby enabled status.
  * @param New X-axis standby enabled status
@@ -2586,8 +2976,10 @@ bool MPU6050_getStandbyXGyroEnabled() {
  * @see MPU6050_RA_PWR_MGMT_2
  * @see MPU6050_PWR2_STBY_XG_BIT
  */
-void MPU6050_setStandbyXGyroEnabled(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XG_BIT, enabled);
+void MPU6050_setStandbyXGyroEnabled(bool enabled)
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2,
+	                MPU6050_PWR2_STBY_XG_BIT, enabled);
 }
 /** Get Y-axis gyroscope standby enabled status.
  * If enabled, the Y-axis will not gather or report data (or use power).
@@ -2595,9 +2987,11 @@ void MPU6050_setStandbyXGyroEnabled(bool enabled) {
  * @see MPU6050_RA_PWR_MGMT_2
  * @see MPU6050_PWR2_STBY_YG_BIT
  */
-bool MPU6050_getStandbyYGyroEnabled() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YG_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getStandbyYGyroEnabled()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YG_BIT,
+	               mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set Y-axis gyroscope standby enabled status.
  * @param New Y-axis standby enabled status
@@ -2605,8 +2999,10 @@ bool MPU6050_getStandbyYGyroEnabled() {
  * @see MPU6050_RA_PWR_MGMT_2
  * @see MPU6050_PWR2_STBY_YG_BIT
  */
-void MPU6050_setStandbyYGyroEnabled(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YG_BIT, enabled);
+void MPU6050_setStandbyYGyroEnabled(bool enabled)
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2,
+	                MPU6050_PWR2_STBY_YG_BIT, enabled);
 }
 /** Get Z-axis gyroscope standby enabled status.
  * If enabled, the Z-axis will not gather or report data (or use power).
@@ -2614,9 +3010,11 @@ void MPU6050_setStandbyYGyroEnabled(bool enabled) {
  * @see MPU6050_RA_PWR_MGMT_2
  * @see MPU6050_PWR2_STBY_ZG_BIT
  */
-bool MPU6050_getStandbyZGyroEnabled() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZG_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getStandbyZGyroEnabled()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZG_BIT,
+	               mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set Z-axis gyroscope standby enabled status.
  * @param New Z-axis standby enabled status
@@ -2624,8 +3022,10 @@ bool MPU6050_getStandbyZGyroEnabled() {
  * @see MPU6050_RA_PWR_MGMT_2
  * @see MPU6050_PWR2_STBY_ZG_BIT
  */
-void MPU6050_setStandbyZGyroEnabled(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZG_BIT, enabled);
+void MPU6050_setStandbyZGyroEnabled(bool enabled)
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2,
+	                MPU6050_PWR2_STBY_ZG_BIT, enabled);
 }
 
 // FIFO_COUNT* registers
@@ -2637,9 +3037,10 @@ void MPU6050_setStandbyZGyroEnabled(bool enabled) {
  * set of sensor data bound to be stored in the FIFO (register 35 and 36).
  * @return Current FIFO mpu6050.buffer size
  */
-uint16_t MPU6050_getFIFOCount() {
-    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_FIFO_COUNTH, 2, mpu6050.buffer);
-    return (((uint16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+uint16_t MPU6050_getFIFOCount()
+{
+	I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_FIFO_COUNTH, 2, mpu6050.buffer);
+	return (((uint16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
 }
 
 // FIFO_R_W register
@@ -2669,19 +3070,22 @@ uint16_t MPU6050_getFIFOCount() {
  *
  * @return Byte from FIFO mpu6050.buffer
  */
-uint8_t MPU6050_getFIFOByte() {
-    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_FIFO_R_W, mpu6050.buffer);
-    return mpu6050.buffer[0];
+uint8_t MPU6050_getFIFOByte()
+{
+	I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_FIFO_R_W, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
-void MPU6050_getFIFOBytes(uint8_t *data, uint8_t length) {
-    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_FIFO_R_W, length, data);
+void MPU6050_getFIFOBytes(uint8_t *data, uint8_t length)
+{
+	I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_FIFO_R_W, length, data);
 }
 /** Write byte to FIFO mpu6050.buffer.
  * @see getFIFOByte()
  * @see MPU6050_RA_FIFO_R_W
  */
-void MPU6050_setFIFOByte(uint8_t data) {
-    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_FIFO_R_W, data);
+void MPU6050_setFIFOByte(uint8_t data)
+{
+	I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_FIFO_R_W, data);
 }
 
 // WHO_AM_I register
@@ -2693,9 +3097,11 @@ void MPU6050_setFIFOByte(uint8_t data) {
  * @see MPU6050_WHO_AM_I_BIT
  * @see MPU6050_WHO_AM_I_LENGTH
  */
-uint8_t MPU6050_getDeviceID() {
-    I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_WHO_AM_I, MPU6050_WHO_AM_I_BIT, MPU6050_WHO_AM_I_LENGTH, mpu6050.buffer);
-    return mpu6050.buffer[0];
+uint8_t MPU6050_getDeviceID()
+{
+	I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_WHO_AM_I, MPU6050_WHO_AM_I_BIT,
+	                MPU6050_WHO_AM_I_LENGTH, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 /** Set Device ID.
  * Write a new ID into the WHO_AM_I register (no idea why this should ever be
@@ -2706,261 +3112,333 @@ uint8_t MPU6050_getDeviceID() {
  * @see MPU6050_WHO_AM_I_BIT
  * @see MPU6050_WHO_AM_I_LENGTH
  */
-void MPU6050_setDeviceID(uint8_t id) {
-    I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_WHO_AM_I, MPU6050_WHO_AM_I_BIT, MPU6050_WHO_AM_I_LENGTH, id);
+void MPU6050_setDeviceID(uint8_t id)
+{
+	I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_WHO_AM_I, MPU6050_WHO_AM_I_BIT,
+	                 MPU6050_WHO_AM_I_LENGTH, id);
 }
 
 // ======== UNDOCUMENTED/DMP REGISTERS/METHODS ========
 
 // XG_OFFS_TC register
 
-uint8_t MPU6050_getOTPBankValid() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OTP_BNK_VLD_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+uint8_t MPU6050_getOTPBankValid()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_XG_OFFS_TC,
+	               MPU6050_TC_OTP_BNK_VLD_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
-void MPU6050_setOTPBankValid(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OTP_BNK_VLD_BIT, enabled);
+void MPU6050_setOTPBankValid(bool enabled)
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_XG_OFFS_TC,
+	                MPU6050_TC_OTP_BNK_VLD_BIT, enabled);
 }
-int8_t MPU6050_getXGyroOffsetTC() {
-    I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, mpu6050.buffer);
-    return mpu6050.buffer[0];
+int8_t MPU6050_getXGyroOffsetTC()
+{
+	I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OFFSET_BIT,
+	                MPU6050_TC_OFFSET_LENGTH, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
-void MPU6050_setXGyroOffsetTC(int8_t offset) {
-    I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset);
+void MPU6050_setXGyroOffsetTC(int8_t offset)
+{
+	I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OFFSET_BIT,
+	                 MPU6050_TC_OFFSET_LENGTH, offset);
 }
 
 // YG_OFFS_TC register
 
-int8_t MPU6050_getYGyroOffsetTC() {
-    I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, mpu6050.buffer);
-    return mpu6050.buffer[0];
+int8_t MPU6050_getYGyroOffsetTC()
+{
+	I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_OFFSET_BIT,
+	                MPU6050_TC_OFFSET_LENGTH, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
-void MPU6050_setYGyroOffsetTC(int8_t offset) {
-    I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset);
+void MPU6050_setYGyroOffsetTC(int8_t offset)
+{
+	I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_OFFSET_BIT,
+	                 MPU6050_TC_OFFSET_LENGTH, offset);
 }
 
 // ZG_OFFS_TC register
 
-int8_t MPU6050_getZGyroOffsetTC() {
-    I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_ZG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, mpu6050.buffer);
-    return mpu6050.buffer[0];
+int8_t MPU6050_getZGyroOffsetTC()
+{
+	I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_ZG_OFFS_TC, MPU6050_TC_OFFSET_BIT,
+	                MPU6050_TC_OFFSET_LENGTH, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
-void MPU6050_setZGyroOffsetTC(int8_t offset) {
-    I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_ZG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset);
+void MPU6050_setZGyroOffsetTC(int8_t offset)
+{
+	I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_ZG_OFFS_TC, MPU6050_TC_OFFSET_BIT,
+	                 MPU6050_TC_OFFSET_LENGTH, offset);
 }
 
 // X_FINE_GAIN register
 
-int8_t MPU6050_getXFineGain() {
-    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_X_FINE_GAIN, mpu6050.buffer);
-    return mpu6050.buffer[0];
+int8_t MPU6050_getXFineGain()
+{
+	I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_X_FINE_GAIN, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
-void MPU6050_setXFineGain(int8_t gain) {
-    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_X_FINE_GAIN, gain);
+void MPU6050_setXFineGain(int8_t gain)
+{
+	I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_X_FINE_GAIN, gain);
 }
 
 // Y_FINE_GAIN register
 
-int8_t MPU6050_getYFineGain() {
-    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_Y_FINE_GAIN, mpu6050.buffer);
-    return mpu6050.buffer[0];
+int8_t MPU6050_getYFineGain()
+{
+	I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_Y_FINE_GAIN, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
-void MPU6050_setYFineGain(int8_t gain) {
-    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_Y_FINE_GAIN, gain);
+void MPU6050_setYFineGain(int8_t gain)
+{
+	I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_Y_FINE_GAIN, gain);
 }
 
 // Z_FINE_GAIN register
 
-int8_t MPU6050_getZFineGain() {
-    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_Z_FINE_GAIN, mpu6050.buffer);
-    return mpu6050.buffer[0];
+int8_t MPU6050_getZFineGain()
+{
+	I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_Z_FINE_GAIN, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
-void MPU6050_setZFineGain(int8_t gain) {
-    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_Z_FINE_GAIN, gain);
+void MPU6050_setZFineGain(int8_t gain)
+{
+	I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_Z_FINE_GAIN, gain);
 }
 
 // XA_OFFS_* registers
 
-int16_t MPU6050_getXAccelOffset() {
-    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_XA_OFFS_H, 2, mpu6050.buffer);
-    return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+int16_t MPU6050_getXAccelOffset()
+{
+	I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_XA_OFFS_H, 2, mpu6050.buffer);
+	return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
 }
-void MPU6050_setXAccelOffset(int16_t offset) {
-    I2Cdev_writeWord(mpu6050.devAddr, MPU6050_RA_XA_OFFS_H, offset);
+void MPU6050_setXAccelOffset(int16_t offset)
+{
+	I2Cdev_writeWord(mpu6050.devAddr, MPU6050_RA_XA_OFFS_H, offset);
 }
 
 // YA_OFFS_* register
 
-int16_t MPU6050_getYAccelOffset() {
-    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_YA_OFFS_H, 2, mpu6050.buffer);
-    return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+int16_t MPU6050_getYAccelOffset()
+{
+	I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_YA_OFFS_H, 2, mpu6050.buffer);
+	return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
 }
-void MPU6050_setYAccelOffset(int16_t offset) {
-    I2Cdev_writeWord(mpu6050.devAddr, MPU6050_RA_YA_OFFS_H, offset);
+void MPU6050_setYAccelOffset(int16_t offset)
+{
+	I2Cdev_writeWord(mpu6050.devAddr, MPU6050_RA_YA_OFFS_H, offset);
 }
 
 // ZA_OFFS_* register
 
-int16_t MPU6050_getZAccelOffset() {
-    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ZA_OFFS_H, 2, mpu6050.buffer);
-    return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+int16_t MPU6050_getZAccelOffset()
+{
+	I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ZA_OFFS_H, 2, mpu6050.buffer);
+	return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
 }
-void MPU6050_setZAccelOffset(int16_t offset) {
-    I2Cdev_writeWord(mpu6050.devAddr, MPU6050_RA_ZA_OFFS_H, offset);
+void MPU6050_setZAccelOffset(int16_t offset)
+{
+	I2Cdev_writeWord(mpu6050.devAddr, MPU6050_RA_ZA_OFFS_H, offset);
 }
 
 // XG_OFFS_USR* registers
 
-int16_t MPU6050_getXGyroOffset() {
-    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_XG_OFFS_USRH, 2, mpu6050.buffer);
-    return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+int16_t MPU6050_getXGyroOffset()
+{
+	I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_XG_OFFS_USRH, 2, mpu6050.buffer);
+	return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
 }
-void MPU6050_setXGyroOffset(int16_t offset) {
-    I2Cdev_writeWord(mpu6050.devAddr, MPU6050_RA_XG_OFFS_USRH, offset);
+void MPU6050_setXGyroOffset(int16_t offset)
+{
+	I2Cdev_writeWord(mpu6050.devAddr, MPU6050_RA_XG_OFFS_USRH, offset);
 }
 
 // YG_OFFS_USR* register
 
-int16_t MPU6050_getYGyroOffset() {
-    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_YG_OFFS_USRH, 2, mpu6050.buffer);
-    return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+int16_t MPU6050_getYGyroOffset()
+{
+	I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_YG_OFFS_USRH, 2, mpu6050.buffer);
+	return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
 }
-void MPU6050_setYGyroOffset(int16_t offset) {
-    I2Cdev_writeWord(mpu6050.devAddr, MPU6050_RA_YG_OFFS_USRH, offset);
+void MPU6050_setYGyroOffset(int16_t offset)
+{
+	I2Cdev_writeWord(mpu6050.devAddr, MPU6050_RA_YG_OFFS_USRH, offset);
 }
 
 // ZG_OFFS_USR* register
 
-int16_t MPU6050_getZGyroOffset() {
-    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ZG_OFFS_USRH, 2, mpu6050.buffer);
-    return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+int16_t MPU6050_getZGyroOffset()
+{
+	I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ZG_OFFS_USRH, 2, mpu6050.buffer);
+	return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
 }
-void MPU6050_setZGyroOffset(int16_t offset) {
-    I2Cdev_writeWord(mpu6050.devAddr, MPU6050_RA_ZG_OFFS_USRH, offset);
+void MPU6050_setZGyroOffset(int16_t offset)
+{
+	I2Cdev_writeWord(mpu6050.devAddr, MPU6050_RA_ZG_OFFS_USRH, offset);
 }
 
 // INT_ENABLE register (DMP functions)
 
-bool MPU6050_getIntPLLReadyEnabled() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getIntPLLReadyEnabled()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE,
+	               MPU6050_INTERRUPT_PLL_RDY_INT_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
-void MPU6050_setIntPLLReadyEnabled(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, enabled);
+void MPU6050_setIntPLLReadyEnabled(bool enabled)
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE,
+	                MPU6050_INTERRUPT_PLL_RDY_INT_BIT, enabled);
 }
-bool MPU6050_getIntDMPEnabled() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DMP_INT_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getIntDMPEnabled()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE,
+	               MPU6050_INTERRUPT_DMP_INT_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
-void MPU6050_setIntDMPEnabled(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DMP_INT_BIT, enabled);
+void MPU6050_setIntDMPEnabled(bool enabled)
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE,
+	                MPU6050_INTERRUPT_DMP_INT_BIT, enabled);
 }
 
 // DMP_INT_STATUS
 
-bool MPU6050_getDMPInt5Status() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_5_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
-}
-bool MPU6050_getDMPInt4Status() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_4_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
-}
-bool MPU6050_getDMPInt3Status() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_3_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
-}
-bool MPU6050_getDMPInt2Status() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_2_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
-}
-bool MPU6050_getDMPInt1Status() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_1_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
-}
-bool MPU6050_getDMPInt0Status() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_0_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getDMPInt5Status()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_5_BIT,
+	               mpu6050.buffer);
+	return mpu6050.buffer[0];
+}
+bool MPU6050_getDMPInt4Status()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_4_BIT,
+	               mpu6050.buffer);
+	return mpu6050.buffer[0];
+}
+bool MPU6050_getDMPInt3Status()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_3_BIT,
+	               mpu6050.buffer);
+	return mpu6050.buffer[0];
+}
+bool MPU6050_getDMPInt2Status()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_2_BIT,
+	               mpu6050.buffer);
+	return mpu6050.buffer[0];
+}
+bool MPU6050_getDMPInt1Status()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_1_BIT,
+	               mpu6050.buffer);
+	return mpu6050.buffer[0];
+}
+bool MPU6050_getDMPInt0Status()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_0_BIT,
+	               mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 
 // INT_STATUS register (DMP functions)
 
-bool MPU6050_getIntPLLReadyStatus() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getIntPLLReadyStatus()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS,
+	               MPU6050_INTERRUPT_PLL_RDY_INT_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
-bool MPU6050_getIntDMPStatus() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_DMP_INT_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getIntDMPStatus()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS,
+	               MPU6050_INTERRUPT_DMP_INT_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
 
 // USER_CTRL register (DMP functions)
 
-bool MPU6050_getDMPEnabled() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_EN_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
+bool MPU6050_getDMPEnabled()
+{
+	I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL,
+	               MPU6050_USERCTRL_DMP_EN_BIT, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
-void MPU6050_setDMPEnabled(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_EN_BIT, enabled);
+void MPU6050_setDMPEnabled(bool enabled)
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL,
+	                MPU6050_USERCTRL_DMP_EN_BIT, enabled);
 }
-void MPU6050_resetDMP() {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_RESET_BIT, true);
+void MPU6050_resetDMP()
+{
+	I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL,
+	                MPU6050_USERCTRL_DMP_RESET_BIT, true);
 }
 
 // BANK_SEL register
 
-void MPU6050_setMemoryBank(uint8_t bank, bool prefetchEnabled, bool userBank) {
-    bank &= 0x1F;
-    if (userBank) bank |= 0x20;
-    if (prefetchEnabled) bank |= 0x40;
-    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_BANK_SEL, bank);
+void MPU6050_setMemoryBank(uint8_t bank, bool prefetchEnabled, bool userBank)
+{
+	bank &= 0x1F;
+	if (userBank) bank |= 0x20;
+	if (prefetchEnabled) bank |= 0x40;
+	I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_BANK_SEL, bank);
 }
 
 // MEM_START_ADDR register
 
-void MPU6050_setMemoryStartAddress(uint8_t address) {
-    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_MEM_START_ADDR, address);
+void MPU6050_setMemoryStartAddress(uint8_t address)
+{
+	I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_MEM_START_ADDR, address);
 }
 
 // MEM_R_W register
 
-uint8_t MPU6050_readMemoryByte() {
-    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_MEM_R_W, mpu6050.buffer);
-    return mpu6050.buffer[0];
+uint8_t MPU6050_readMemoryByte()
+{
+	I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_MEM_R_W, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
-void MPU6050_writeMemoryByte(uint8_t data) {
-    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_MEM_R_W, data);
+void MPU6050_writeMemoryByte(uint8_t data)
+{
+	I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_MEM_R_W, data);
 }
-void MPU6050_readMemoryBlock(uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address) {
-    MPU6050_setMemoryBank(bank, false, false);
-    MPU6050_setMemoryStartAddress(address);
-    uint8_t chunkSize;
-    for (uint16_t i = 0; i < dataSize;) {
-        // determine correct chunk size according to bank position and data size
-        chunkSize = MPU6050_DMP_MEMORY_CHUNK_SIZE;
+void MPU6050_readMemoryBlock(uint8_t *data, uint16_t dataSize, uint8_t bank,
+                             uint8_t address)
+{
+	MPU6050_setMemoryBank(bank, false, false);
+	MPU6050_setMemoryStartAddress(address);
+	uint8_t chunkSize;
+	for (uint16_t i = 0; i < dataSize;) {
+		// determine correct chunk size according to bank position and data size
+		chunkSize = MPU6050_DMP_MEMORY_CHUNK_SIZE;
 
-        // make sure we don't go past the data size
-        if (i + chunkSize > dataSize) chunkSize = dataSize - i;
+		// make sure we don't go past the data size
+		if (i + chunkSize > dataSize) chunkSize = dataSize - i;
 
-        // make sure this chunk doesn't go past the bank boundary (256 bytes)
-        if (chunkSize > 256 - address) chunkSize = 256 - address;
+		// make sure this chunk doesn't go past the bank boundary (256 bytes)
+		if (chunkSize > 256 - address) chunkSize = 256 - address;
 
-        // read the chunk of data as specified
-        I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_MEM_R_W, chunkSize, data + i);
-        
-        // increase byte index by [chunkSize]
-        i += chunkSize;
+		// read the chunk of data as specified
+		I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_MEM_R_W, chunkSize, data + i);
 
-        // uint8_t automatically wraps to 0 at 256
-        address += chunkSize;
+		// increase byte index by [chunkSize]
+		i += chunkSize;
 
-        // if we aren't done, update bank (if necessary) and address
-        if (i < dataSize) {
-            if (address == 0) bank++;
-            MPU6050_setMemoryBank(bank, false, false);
-            MPU6050_setMemoryStartAddress(address);
-        }
-    }
+		// uint8_t automatically wraps to 0 at 256
+		address += chunkSize;
+
+		// if we aren't done, update bank (if necessary) and address
+		if (i < dataSize) {
+			if (address == 0) bank++;
+			MPU6050_setMemoryBank(bank, false, false);
+			MPU6050_setMemoryStartAddress(address);
+		}
+	}
 }
 /*bool MPU6050_writeMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address, bool verify, bool useProgMem) {
     MPU6050_setMemoryBank(bank, false, false);
@@ -2981,7 +3459,7 @@ void MPU6050_readMemoryBlock(uint8_t *data, uint16_t dataSize, uint8_t bank, uin
 
         // make sure this chunk doesn't go past the bank boundary (256 bytes)
         if (chunkSize > 256 - address) chunkSize = 256 - address;
-        
+
         if (useProgMem) {
             // write the chunk of data as specified
             for (j = 0; j < chunkSize; j++) progBuffer[j] = pgm_read_byte(data + i + j);
@@ -3095,7 +3573,7 @@ bool MPU6050_writeDMPConfigurationSet(const uint8_t *data, uint16_t dataSize, bo
             //Serial.println(" found...");
             if (special == 0x01) {
                 // enable DMP-related interrupts
-                
+
                 //setIntZeroMotionEnabled(true);
                 //setIntFIFOBufferOverflowEnabled(true);
                 //setIntDMPEnabled(true);
@@ -3107,7 +3585,7 @@ bool MPU6050_writeDMPConfigurationSet(const uint8_t *data, uint16_t dataSize, bo
                 success = false;
             }
         }
-        
+
         if (!success) {
             if (useProgMem) free(progBuffer);
             return false; // uh oh
@@ -3122,20 +3600,24 @@ bool MPU6050_writeProgDMPConfigurationSet(const uint8_t *data, uint16_t dataSize
 
 // DMP_CFG_1 register
 
-uint8_t MPU6050_getDMPConfig1() {
-    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_DMP_CFG_1, mpu6050.buffer);
-    return mpu6050.buffer[0];
+uint8_t MPU6050_getDMPConfig1()
+{
+	I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_DMP_CFG_1, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
-void MPU6050_setDMPConfig1(uint8_t config) {
-    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_DMP_CFG_1, config);
+void MPU6050_setDMPConfig1(uint8_t config)
+{
+	I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_DMP_CFG_1, config);
 }
 
 // DMP_CFG_2 register
 
-uint8_t MPU6050_getDMPConfig2() {
-    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_DMP_CFG_2, mpu6050.buffer);
-    return mpu6050.buffer[0];
+uint8_t MPU6050_getDMPConfig2()
+{
+	I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_DMP_CFG_2, mpu6050.buffer);
+	return mpu6050.buffer[0];
 }
-void MPU6050_setDMPConfig2(uint8_t config) {
-    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_DMP_CFG_2, config);
+void MPU6050_setDMPConfig2(uint8_t config)
+{
+	I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_DMP_CFG_2, config);
 }
\ No newline at end of file
diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050.c.orig b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050.c.orig
new file mode 100644
index 00000000..6f85e455
--- /dev/null
+++ b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050.c.orig
@@ -0,0 +1,3174 @@
+// I2Cdev library collection - MPU6050 I2C device class
+// Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00)
+// 8/24/2011 by Jeff Rowberg 
+// 11/28/2014 by Marton Sebok 
+//
+// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
+//
+// Changelog:
+//     ...        - ongoing debug release
+//     2014-11-28 - ported to PIC18 peripheral library from Arduino code
+
+// NOTE: THIS IS ONLY A PARIAL RELEASE. THIS DEVICE CLASS IS CURRENTLY UNDERGOING ACTIVE
+// DEVELOPMENT AND IS STILL MISSING SOME IMPORTANT FEATURES. PLEASE KEEP THIS IN MIND IF
+// YOU DECIDE TO USE THIS PARTICULAR CODE FOR ANYTHING.
+
+/* ============================================
+I2Cdev device library code is placed under the MIT license
+Copyright (c) 2012 Jeff Rowberg
+Copyright (c) 2014 Marton Sebok
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+===============================================
+*/
+
+#include "MPU6050.h"
+
+/*******************************************************************************/         
+//  delay us using for-loop     
+/*******************************************************************************/     
+void delay_us( unsigned int usec )                      
+{                                   
+    unsigned int i;                                                                  
+    //�   �   �   �   �   �   �   �   �   �              //40 MIPS ,     
+    for ( i = 0 ; i < usec * 2; i++ ){                 //for-loop 8Tcy -> 1us -> add two NOP()     
+        asm("NOP");      
+        asm("NOP");    
+    }                                                                 
+}                                   
+/*******************************************************************************/     
+// delay ms using Timer 1 interrupt                                                     
+/*******************************************************************************/     
+void delay_ms( unsigned int msec )                                                                                                                
+{       
+    /*TIMER1_DELAY_VALUE = msec;     
+    TMR1 = 0;                                                                                 
+    IEC0bits.T1IE = 1;        
+    while(TIMER1_DELAY_VALUE);                                                       
+    */            
+    int i=0;    
+    for (i = 0;i < msec;i++)    
+       delay_us(1000);                                 
+}       
+
+MPU6050_t mpu6050;
+
+/** Specific address constructor.
+ * @param address I2C address
+ * @see MPU6050_DEFAULT_ADDRESS
+ * @see MPU6050_ADDRESS_AD0_LOW
+ * @see MPU6050_ADDRESS_AD0_HIGH
+ */
+void MPU6050(uint8_t address) {
+    mpu6050.devAddr = address;
+}
+
+/** Power on and prepare for general usage.
+ * This will activate the device and take it out of sleep mode (which must be done
+ * after start-up). This function also sets both the accelerometer and the gyroscope
+ * to their most sensitive settings, namely +/- 2g and +/- 250 degrees/sec, and sets
+ * the clock source to use the X Gyro for reference, which is slightly better than
+ * the default internal clock source.
+ */
+void MPU6050_initialize() {
+    
+    
+    MPU6050_setSleepEnabled(false); // thanks to Jack Elston for pointing this one out!
+    delay_us(200);
+    MPU6050_setClockSource(MPU6050_CLOCK_PLL_XGYRO);
+    delay_us(200);
+    MPU6050_setFullScaleAccelRange(MPU6050_ACCEL_FS_2);
+    delay_us(200);
+    MPU6050_setFullScaleGyroRange(MPU6050_GYRO_FS_250);
+    
+}
+
+/** Verify the I2C connection.
+ * Make sure the device is connected and responds as expected.
+ * @return True if connection is valid, false otherwise
+ */
+bool MPU6050_testConnection() {
+    return MPU6050_getDeviceID() == 0x34;
+}
+
+// AUX_VDDIO register (InvenSense demo code calls this RA_*G_OFFS_TC)
+
+/** Get the auxiliary I2C supply voltage level.
+ * When set to 1, the auxiliary I2C bus high logic level is VDD. When cleared to
+ * 0, the auxiliary I2C bus high logic level is VLOGIC. This does not apply to
+ * the MPU-6000, which does not have a VLOGIC pin.
+ * @return I2C supply voltage level (0=VLOGIC, 1=VDD)
+ */
+uint8_t MPU6050_getAuxVDDIOLevel() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_PWR_MODE_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+/** Set the auxiliary I2C supply voltage level.
+ * When set to 1, the auxiliary I2C bus high logic level is VDD. When cleared to
+ * 0, the auxiliary I2C bus high logic level is VLOGIC. This does not apply to
+ * the MPU-6000, which does not have a VLOGIC pin.
+ * @param level I2C supply voltage level (0=VLOGIC, 1=VDD)
+ */
+void MPU6050_setAuxVDDIOLevel(uint8_t level) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_PWR_MODE_BIT, level);
+}
+
+// SMPLRT_DIV register
+
+/** Get gyroscope output rate divider.
+ * The sensor register output, FIFO output, DMP sampling, Motion detection, Zero
+ * Motion detection, and Free Fall detection are all based on the Sample Rate.
+ * The Sample Rate is generated by dividing the gyroscope output rate by
+ * SMPLRT_DIV:
+ *
+ * Sample Rate = Gyroscope Output Rate / (1 + SMPLRT_DIV)
+ *
+ * where Gyroscope Output Rate = 8kHz when the DLPF is disabled (DLPF_CFG = 0 or
+ * 7), and 1kHz when the DLPF is enabled (see Register 26).
+ *
+ * Note: The accelerometer output rate is 1kHz. This means that for a Sample
+ * Rate greater than 1kHz, the same accelerometer sample may be output to the
+ * FIFO, DMP, and sensor registers more than once.
+ *
+ * For a diagram of the gyroscope and accelerometer signal paths, see Section 8
+ * of the MPU-6000/MPU-6050 Product Specification document.
+ *
+ * @return Current sample rate
+ * @see MPU6050_RA_SMPLRT_DIV
+ */
+uint8_t MPU6050_getRate() {
+    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_SMPLRT_DIV, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+/** Set gyroscope sample rate divider.
+ * @param rate New sample rate divider
+ * @see getRate()
+ * @see MPU6050_RA_SMPLRT_DIV
+ */
+void MPU6050_setRate(uint8_t rate) {
+    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_SMPLRT_DIV, rate);
+}
+
+// CONFIG register
+
+/** Get external FSYNC configuration.
+ * Configures the external Frame Synchronization (FSYNC) pin sampling. An
+ * external signal connected to the FSYNC pin can be sampled by configuring
+ * EXT_SYNC_SET. Signal changes to the FSYNC pin are latched so that short
+ * strobes may be captured. The latched FSYNC signal will be sampled at the
+ * Sampling Rate, as defined in register 25. After sampling, the latch will
+ * reset to the current FSYNC signal state.
+ *
+ * The sampled value will be reported in place of the least significant bit in
+ * a sensor data register determined by the value of EXT_SYNC_SET according to
+ * the following table.
+ *
+ * 
+ * EXT_SYNC_SET | FSYNC Bit Location
+ * -------------+-------------------
+ * 0            | Input disabled
+ * 1            | TEMP_OUT_L[0]
+ * 2            | GYRO_XOUT_L[0]
+ * 3            | GYRO_YOUT_L[0]
+ * 4            | GYRO_ZOUT_L[0]
+ * 5            | ACCEL_XOUT_L[0]
+ * 6            | ACCEL_YOUT_L[0]
+ * 7            | ACCEL_ZOUT_L[0]
+ * 
+ * + * @return FSYNC configuration value + */ +uint8_t MPU6050_getExternalFrameSync() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_EXT_SYNC_SET_BIT, MPU6050_CFG_EXT_SYNC_SET_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set external FSYNC configuration. + * @see getExternalFrameSync() + * @see MPU6050_RA_CONFIG + * @param sync New FSYNC configuration value + */ +void MPU6050_setExternalFrameSync(uint8_t sync) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_EXT_SYNC_SET_BIT, MPU6050_CFG_EXT_SYNC_SET_LENGTH, sync); +} +/** Get digital low-pass filter configuration. + * The DLPF_CFG parameter sets the digital low pass filter configuration. It + * also determines the internal sampling rate used by the device as shown in + * the table below. + * + * Note: The accelerometer output rate is 1kHz. This means that for a Sample + * Rate greater than 1kHz, the same accelerometer sample may be output to the + * FIFO, DMP, and sensor registers more than once. + * + *
+ *          |   ACCELEROMETER    |           GYROSCOPE
+ * DLPF_CFG | Bandwidth | Delay  | Bandwidth | Delay  | Sample Rate
+ * ---------+-----------+--------+-----------+--------+-------------
+ * 0        | 260Hz     | 0ms    | 256Hz     | 0.98ms | 8kHz
+ * 1        | 184Hz     | 2.0ms  | 188Hz     | 1.9ms  | 1kHz
+ * 2        | 94Hz      | 3.0ms  | 98Hz      | 2.8ms  | 1kHz
+ * 3        | 44Hz      | 4.9ms  | 42Hz      | 4.8ms  | 1kHz
+ * 4        | 21Hz      | 8.5ms  | 20Hz      | 8.3ms  | 1kHz
+ * 5        | 10Hz      | 13.8ms | 10Hz      | 13.4ms | 1kHz
+ * 6        | 5Hz       | 19.0ms | 5Hz       | 18.6ms | 1kHz
+ * 7        |   -- Reserved --   |   -- Reserved --   | Reserved
+ * 
+ * + * @return DLFP configuration + * @see MPU6050_RA_CONFIG + * @see MPU6050_CFG_DLPF_CFG_BIT + * @see MPU6050_CFG_DLPF_CFG_LENGTH + */ +uint8_t MPU6050_getDLPFMode() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_DLPF_CFG_BIT, MPU6050_CFG_DLPF_CFG_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set digital low-pass filter configuration. + * @param mode New DLFP configuration setting + * @see getDLPFBandwidth() + * @see MPU6050_DLPF_BW_256 + * @see MPU6050_RA_CONFIG + * @see MPU6050_CFG_DLPF_CFG_BIT + * @see MPU6050_CFG_DLPF_CFG_LENGTH + */ +void MPU6050_setDLPFMode(uint8_t mode) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_DLPF_CFG_BIT, MPU6050_CFG_DLPF_CFG_LENGTH, mode); +} + +// GYRO_CONFIG register + +/** Get full-scale gyroscope range. + * The FS_SEL parameter allows setting the full-scale range of the gyro sensors, + * as described in the table below. + * + *
+ * 0 = +/- 250 degrees/sec
+ * 1 = +/- 500 degrees/sec
+ * 2 = +/- 1000 degrees/sec
+ * 3 = +/- 2000 degrees/sec
+ * 
+ * + * @return Current full-scale gyroscope range setting + * @see MPU6050_GYRO_FS_250 + * @see MPU6050_RA_GYRO_CONFIG + * @see MPU6050_GCONFIG_FS_SEL_BIT + * @see MPU6050_GCONFIG_FS_SEL_LENGTH + */ +uint8_t MPU6050_getFullScaleGyroRange() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set full-scale gyroscope range. + * @param range New full-scale gyroscope range value + * @see getFullScaleRange() + * @see MPU6050_GYRO_FS_250 + * @see MPU6050_RA_GYRO_CONFIG + * @see MPU6050_GCONFIG_FS_SEL_BIT + * @see MPU6050_GCONFIG_FS_SEL_LENGTH + */ +void MPU6050_setFullScaleGyroRange(uint8_t range) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, range); +} + +// ACCEL_CONFIG register + +/** Get self-test enabled setting for accelerometer X axis. + * @return Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +bool MPU6050_getAccelXSelfTest() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_XA_ST_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get self-test enabled setting for accelerometer X axis. + * @param enabled Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050_setAccelXSelfTest(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_XA_ST_BIT, enabled); +} +/** Get self-test enabled value for accelerometer Y axis. + * @return Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +bool MPU6050_getAccelYSelfTest() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_YA_ST_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get self-test enabled value for accelerometer Y axis. + * @param enabled Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050_setAccelYSelfTest(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_YA_ST_BIT, enabled); +} +/** Get self-test enabled value for accelerometer Z axis. + * @return Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +bool MPU6050_getAccelZSelfTest() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ZA_ST_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set self-test enabled value for accelerometer Z axis. + * @param enabled Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050_setAccelZSelfTest(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ZA_ST_BIT, enabled); +} +/** Get full-scale accelerometer range. + * The FS_SEL parameter allows setting the full-scale range of the accelerometer + * sensors, as described in the table below. + * + *
+ * 0 = +/- 2g
+ * 1 = +/- 4g
+ * 2 = +/- 8g
+ * 3 = +/- 16g
+ * 
+ * + * @return Current full-scale accelerometer range setting + * @see MPU6050_ACCEL_FS_2 + * @see MPU6050_RA_ACCEL_CONFIG + * @see MPU6050_ACONFIG_AFS_SEL_BIT + * @see MPU6050_ACONFIG_AFS_SEL_LENGTH + */ +uint8_t MPU6050_getFullScaleAccelRange() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set full-scale accelerometer range. + * @param range New full-scale accelerometer range setting + * @see getFullScaleAccelRange() + */ +void MPU6050_setFullScaleAccelRange(uint8_t range) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, range); +} +/** Get the high-pass filter configuration. + * The DHPF is a filter module in the path leading to motion detectors (Free + * Fall, Motion threshold, and Zero Motion). The high pass filter output is not + * available to the data registers (see Figure in Section 8 of the MPU-6000/ + * MPU-6050 Product Specification document). + * + * The high pass filter has three modes: + * + *
+ *    Reset: The filter output settles to zero within one sample. This
+ *           effectively disables the high pass filter. This mode may be toggled
+ *           to quickly settle the filter.
+ *
+ *    On:    The high pass filter will pass signals above the cut off frequency.
+ *
+ *    Hold:  When triggered, the filter holds the present sample. The filter
+ *           output will be the difference between the input sample and the held
+ *           sample.
+ * 
+ * + *
+ * ACCEL_HPF | Filter Mode | Cut-off Frequency
+ * ----------+-------------+------------------
+ * 0         | Reset       | None
+ * 1         | On          | 5Hz
+ * 2         | On          | 2.5Hz
+ * 3         | On          | 1.25Hz
+ * 4         | On          | 0.63Hz
+ * 7         | Hold        | None
+ * 
+ * + * @return Current high-pass filter configuration + * @see MPU6050_DHPF_RESET + * @see MPU6050_RA_ACCEL_CONFIG + */ +uint8_t MPU6050_getDHPFMode() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ACCEL_HPF_BIT, MPU6050_ACONFIG_ACCEL_HPF_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set the high-pass filter configuration. + * @param bandwidth New high-pass filter configuration + * @see setDHPFMode() + * @see MPU6050_DHPF_RESET + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050_setDHPFMode(uint8_t bandwidth) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ACCEL_HPF_BIT, MPU6050_ACONFIG_ACCEL_HPF_LENGTH, bandwidth); +} + +// FF_THR register + +/** Get free-fall event acceleration threshold. + * This register configures the detection threshold for Free Fall event + * detection. The unit of FF_THR is 1LSB = 2mg. Free Fall is detected when the + * absolute value of the accelerometer measurements for the three axes are each + * less than the detection threshold. This condition increments the Free Fall + * duration counter (Register 30). The Free Fall interrupt is triggered when the + * Free Fall duration counter reaches the time specified in FF_DUR. + * + * For more details on the Free Fall detection interrupt, see Section 8.2 of the + * MPU-6000/MPU-6050 Product Specification document as well as Registers 56 and + * 58 of this document. + * + * @return Current free-fall acceleration threshold value (LSB = 2mg) + * @see MPU6050_RA_FF_THR + */ +uint8_t MPU6050_getFreefallDetectionThreshold() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_FF_THR, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get free-fall event acceleration threshold. + * @param threshold New free-fall acceleration threshold value (LSB = 2mg) + * @see getFreefallDetectionThreshold() + * @see MPU6050_RA_FF_THR + */ +void MPU6050_setFreefallDetectionThreshold(uint8_t threshold) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_FF_THR, threshold); +} + +// FF_DUR register + +/** Get free-fall event duration threshold. + * This register configures the duration counter threshold for Free Fall event + * detection. The duration counter ticks at 1kHz, therefore FF_DUR has a unit + * of 1 LSB = 1 ms. + * + * The Free Fall duration counter increments while the absolute value of the + * accelerometer measurements are each less than the detection threshold + * (Register 29). The Free Fall interrupt is triggered when the Free Fall + * duration counter reaches the time specified in this register. + * + * For more details on the Free Fall detection interrupt, see Section 8.2 of + * the MPU-6000/MPU-6050 Product Specification document as well as Registers 56 + * and 58 of this document. + * + * @return Current free-fall duration threshold value (LSB = 1ms) + * @see MPU6050_RA_FF_DUR + */ +uint8_t MPU6050_getFreefallDetectionDuration() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_FF_DUR, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get free-fall event duration threshold. + * @param duration New free-fall duration threshold value (LSB = 1ms) + * @see getFreefallDetectionDuration() + * @see MPU6050_RA_FF_DUR + */ +void MPU6050_setFreefallDetectionDuration(uint8_t duration) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_FF_DUR, duration); +} + +// MOT_THR register + +/** Get motion detection event acceleration threshold. + * This register configures the detection threshold for Motion interrupt + * generation. The unit of MOT_THR is 1LSB = 2mg. Motion is detected when the + * absolute value of any of the accelerometer measurements exceeds this Motion + * detection threshold. This condition increments the Motion detection duration + * counter (Register 32). The Motion detection interrupt is triggered when the + * Motion Detection counter reaches the time count specified in MOT_DUR + * (Register 32). + * + * The Motion interrupt will indicate the axis and polarity of detected motion + * in MOT_DETECT_STATUS (Register 97). + * + * For more details on the Motion detection interrupt, see Section 8.3 of the + * MPU-6000/MPU-6050 Product Specification document as well as Registers 56 and + * 58 of this document. + * + * @return Current motion detection acceleration threshold value (LSB = 2mg) + * @see MPU6050_RA_MOT_THR + */ +uint8_t MPU6050_getMotionDetectionThreshold() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_MOT_THR, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set free-fall event acceleration threshold. + * @param threshold New motion detection acceleration threshold value (LSB = 2mg) + * @see getMotionDetectionThreshold() + * @see MPU6050_RA_MOT_THR + */ +void MPU6050_setMotionDetectionThreshold(uint8_t threshold) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_MOT_THR, threshold); +} + +// MOT_DUR register + +/** Get motion detection event duration threshold. + * This register configures the duration counter threshold for Motion interrupt + * generation. The duration counter ticks at 1 kHz, therefore MOT_DUR has a unit + * of 1LSB = 1ms. The Motion detection duration counter increments when the + * absolute value of any of the accelerometer measurements exceeds the Motion + * detection threshold (Register 31). The Motion detection interrupt is + * triggered when the Motion detection counter reaches the time count specified + * in this register. + * + * For more details on the Motion detection interrupt, see Section 8.3 of the + * MPU-6000/MPU-6050 Product Specification document. + * + * @return Current motion detection duration threshold value (LSB = 1ms) + * @see MPU6050_RA_MOT_DUR + */ +uint8_t MPU6050_getMotionDetectionDuration() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_MOT_DUR, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set motion detection event duration threshold. + * @param duration New motion detection duration threshold value (LSB = 1ms) + * @see getMotionDetectionDuration() + * @see MPU6050_RA_MOT_DUR + */ +void MPU6050_setMotionDetectionDuration(uint8_t duration) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_MOT_DUR, duration); +} + +// ZRMOT_THR register + +/** Get zero motion detection event acceleration threshold. + * This register configures the detection threshold for Zero Motion interrupt + * generation. The unit of ZRMOT_THR is 1LSB = 2mg. Zero Motion is detected when + * the absolute value of the accelerometer measurements for the 3 axes are each + * less than the detection threshold. This condition increments the Zero Motion + * duration counter (Register 34). The Zero Motion interrupt is triggered when + * the Zero Motion duration counter reaches the time count specified in + * ZRMOT_DUR (Register 34). + * + * Unlike Free Fall or Motion detection, Zero Motion detection triggers an + * interrupt both when Zero Motion is first detected and when Zero Motion is no + * longer detected. + * + * When a zero motion event is detected, a Zero Motion Status will be indicated + * in the MOT_DETECT_STATUS register (Register 97). When a motion-to-zero-motion + * condition is detected, the status bit is set to 1. When a zero-motion-to- + * motion condition is detected, the status bit is set to 0. + * + * For more details on the Zero Motion detection interrupt, see Section 8.4 of + * the MPU-6000/MPU-6050 Product Specification document as well as Registers 56 + * and 58 of this document. + * + * @return Current zero motion detection acceleration threshold value (LSB = 2mg) + * @see MPU6050_RA_ZRMOT_THR + */ +uint8_t MPU6050_getZeroMotionDetectionThreshold() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_ZRMOT_THR, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set zero motion detection event acceleration threshold. + * @param threshold New zero motion detection acceleration threshold value (LSB = 2mg) + * @see getZeroMotionDetectionThreshold() + * @see MPU6050_RA_ZRMOT_THR + */ +void MPU6050_setZeroMotionDetectionThreshold(uint8_t threshold) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_ZRMOT_THR, threshold); +} + +// ZRMOT_DUR register + +/** Get zero motion detection event duration threshold. + * This register configures the duration counter threshold for Zero Motion + * interrupt generation. The duration counter ticks at 16 Hz, therefore + * ZRMOT_DUR has a unit of 1 LSB = 64 ms. The Zero Motion duration counter + * increments while the absolute value of the accelerometer measurements are + * each less than the detection threshold (Register 33). The Zero Motion + * interrupt is triggered when the Zero Motion duration counter reaches the time + * count specified in this register. + * + * For more details on the Zero Motion detection interrupt, see Section 8.4 of + * the MPU-6000/MPU-6050 Product Specification document, as well as Registers 56 + * and 58 of this document. + * + * @return Current zero motion detection duration threshold value (LSB = 64ms) + * @see MPU6050_RA_ZRMOT_DUR + */ +uint8_t MPU6050_getZeroMotionDetectionDuration() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_ZRMOT_DUR, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set zero motion detection event duration threshold. + * @param duration New zero motion detection duration threshold value (LSB = 1ms) + * @see getZeroMotionDetectionDuration() + * @see MPU6050_RA_ZRMOT_DUR + */ +void MPU6050_setZeroMotionDetectionDuration(uint8_t duration) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_ZRMOT_DUR, duration); +} + +// FIFO_EN register + +/** Get temperature FIFO enabled value. + * When set to 1, this bit enables TEMP_OUT_H and TEMP_OUT_L (Registers 65 and + * 66) to be written into the FIFO mpu6050.buffer. + * @return Current temperature FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_getTempFIFOEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_TEMP_FIFO_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set temperature FIFO enabled value. + * @param enabled New temperature FIFO enabled value + * @see getTempFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setTempFIFOEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_TEMP_FIFO_EN_BIT, enabled); +} +/** Get gyroscope X-axis FIFO enabled value. + * When set to 1, this bit enables GYRO_XOUT_H and GYRO_XOUT_L (Registers 67 and + * 68) to be written into the FIFO mpu6050.buffer. + * @return Current gyroscope X-axis FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_getXGyroFIFOEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_XG_FIFO_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set gyroscope X-axis FIFO enabled value. + * @param enabled New gyroscope X-axis FIFO enabled value + * @see getXGyroFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setXGyroFIFOEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_XG_FIFO_EN_BIT, enabled); +} +/** Get gyroscope Y-axis FIFO enabled value. + * When set to 1, this bit enables GYRO_YOUT_H and GYRO_YOUT_L (Registers 69 and + * 70) to be written into the FIFO mpu6050.buffer. + * @return Current gyroscope Y-axis FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_getYGyroFIFOEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_YG_FIFO_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set gyroscope Y-axis FIFO enabled value. + * @param enabled New gyroscope Y-axis FIFO enabled value + * @see getYGyroFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setYGyroFIFOEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_YG_FIFO_EN_BIT, enabled); +} +/** Get gyroscope Z-axis FIFO enabled value. + * When set to 1, this bit enables GYRO_ZOUT_H and GYRO_ZOUT_L (Registers 71 and + * 72) to be written into the FIFO mpu6050.buffer. + * @return Current gyroscope Z-axis FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_getZGyroFIFOEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_ZG_FIFO_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set gyroscope Z-axis FIFO enabled value. + * @param enabled New gyroscope Z-axis FIFO enabled value + * @see getZGyroFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setZGyroFIFOEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_ZG_FIFO_EN_BIT, enabled); +} +/** Get accelerometer FIFO enabled value. + * When set to 1, this bit enables ACCEL_XOUT_H, ACCEL_XOUT_L, ACCEL_YOUT_H, + * ACCEL_YOUT_L, ACCEL_ZOUT_H, and ACCEL_ZOUT_L (Registers 59 to 64) to be + * written into the FIFO mpu6050.buffer. + * @return Current accelerometer FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_getAccelFIFOEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_ACCEL_FIFO_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set accelerometer FIFO enabled value. + * @param enabled New accelerometer FIFO enabled value + * @see getAccelFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setAccelFIFOEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_ACCEL_FIFO_EN_BIT, enabled); +} +/** Get Slave 2 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 2 to be written into the FIFO mpu6050.buffer. + * @return Current Slave 2 FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_getSlave2FIFOEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV2_FIFO_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Slave 2 FIFO enabled value. + * @param enabled New Slave 2 FIFO enabled value + * @see getSlave2FIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setSlave2FIFOEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV2_FIFO_EN_BIT, enabled); +} +/** Get Slave 1 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 1 to be written into the FIFO mpu6050.buffer. + * @return Current Slave 1 FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_getSlave1FIFOEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV1_FIFO_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Slave 1 FIFO enabled value. + * @param enabled New Slave 1 FIFO enabled value + * @see getSlave1FIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setSlave1FIFOEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV1_FIFO_EN_BIT, enabled); +} +/** Get Slave 0 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 0 to be written into the FIFO mpu6050.buffer. + * @return Current Slave 0 FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_getSlave0FIFOEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV0_FIFO_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Slave 0 FIFO enabled value. + * @param enabled New Slave 0 FIFO enabled value + * @see getSlave0FIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_setSlave0FIFOEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV0_FIFO_EN_BIT, enabled); +} + +// I2C_MST_CTRL register + +/** Get multi-master enabled value. + * Multi-master capability allows multiple I2C masters to operate on the same + * bus. In circuits where multi-master capability is required, set MULT_MST_EN + * to 1. This will increase current drawn by approximately 30uA. + * + * In circuits where multi-master capability is required, the state of the I2C + * bus must always be monitored by each separate I2C Master. Before an I2C + * Master can assume arbitration of the bus, it must first confirm that no other + * I2C Master has arbitration of the bus. When MULT_MST_EN is set to 1, the + * MPU-60X0's bus arbitration detection logic is turned on, enabling it to + * detect when the bus is available. + * + * @return Current multi-master enabled value + * @see MPU6050_RA_I2C_MST_CTRL + */ +bool MPU6050_getMultiMasterEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_MULT_MST_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set multi-master enabled value. + * @param enabled New multi-master enabled value + * @see getMultiMasterEnabled() + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050_setMultiMasterEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_MULT_MST_EN_BIT, enabled); +} +/** Get wait-for-external-sensor-data enabled value. + * When the WAIT_FOR_ES bit is set to 1, the Data Ready interrupt will be + * delayed until External Sensor data from the Slave Devices are loaded into the + * EXT_SENS_DATA registers. This is used to ensure that both the internal sensor + * data (i.e. from gyro and accel) and external sensor data have been loaded to + * their respective data registers (i.e. the data is synced) when the Data Ready + * interrupt is triggered. + * + * @return Current wait-for-external-sensor-data enabled value + * @see MPU6050_RA_I2C_MST_CTRL + */ +bool MPU6050_getWaitForExternalSensorEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_WAIT_FOR_ES_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set wait-for-external-sensor-data enabled value. + * @param enabled New wait-for-external-sensor-data enabled value + * @see getWaitForExternalSensorEnabled() + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050_setWaitForExternalSensorEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_WAIT_FOR_ES_BIT, enabled); +} +/** Get Slave 3 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 3 to be written into the FIFO mpu6050.buffer. + * @return Current Slave 3 FIFO enabled value + * @see MPU6050_RA_MST_CTRL + */ +bool MPU6050_getSlave3FIFOEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_SLV_3_FIFO_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Slave 3 FIFO enabled value. + * @param enabled New Slave 3 FIFO enabled value + * @see getSlave3FIFOEnabled() + * @see MPU6050_RA_MST_CTRL + */ +void MPU6050_setSlave3FIFOEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_SLV_3_FIFO_EN_BIT, enabled); +} +/** Get slave read/write transition enabled value. + * The I2C_MST_P_NSR bit configures the I2C Master's transition from one slave + * read to the next slave read. If the bit equals 0, there will be a restart + * between reads. If the bit equals 1, there will be a stop followed by a start + * of the following read. When a write transaction follows a read transaction, + * the stop followed by a start of the successive write will be always used. + * + * @return Current slave read/write transition enabled value + * @see MPU6050_RA_I2C_MST_CTRL + */ +bool MPU6050_getSlaveReadWriteTransitionEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_P_NSR_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set slave read/write transition enabled value. + * @param enabled New slave read/write transition enabled value + * @see getSlaveReadWriteTransitionEnabled() + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050_setSlaveReadWriteTransitionEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_P_NSR_BIT, enabled); +} +/** Get I2C master clock speed. + * I2C_MST_CLK is a 4 bit unsigned value which configures a divider on the + * MPU-60X0 internal 8MHz clock. It sets the I2C master clock speed according to + * the following table: + * + *
+ * I2C_MST_CLK | I2C Master Clock Speed | 8MHz Clock Divider
+ * ------------+------------------------+-------------------
+ * 0           | 348kHz                 | 23
+ * 1           | 333kHz                 | 24
+ * 2           | 320kHz                 | 25
+ * 3           | 308kHz                 | 26
+ * 4           | 296kHz                 | 27
+ * 5           | 286kHz                 | 28
+ * 6           | 276kHz                 | 29
+ * 7           | 267kHz                 | 30
+ * 8           | 258kHz                 | 31
+ * 9           | 500kHz                 | 16
+ * 10          | 471kHz                 | 17
+ * 11          | 444kHz                 | 18
+ * 12          | 421kHz                 | 19
+ * 13          | 400kHz                 | 20
+ * 14          | 381kHz                 | 21
+ * 15          | 364kHz                 | 22
+ * 
+ * + * @return Current I2C master clock speed + * @see MPU6050_RA_I2C_MST_CTRL + */ +uint8_t MPU6050_getMasterClockSpeed() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_CLK_BIT, MPU6050_I2C_MST_CLK_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set I2C master clock speed. + * @reparam speed Current I2C master clock speed + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050_setMasterClockSpeed(uint8_t speed) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_CLK_BIT, MPU6050_I2C_MST_CLK_LENGTH, speed); +} + +// I2C_SLV* registers (Slave 0-3) + +/** Get the I2C address of the specified slave (0-3). + * Note that Bit 7 (MSB) controls read/write mode. If Bit 7 is set, it's a read + * operation, and if it is cleared, then it's a write operation. The remaining + * bits (6-0) are the 7-bit device address of the slave device. + * + * In read mode, the result of the read is placed in the lowest available + * EXT_SENS_DATA register. For further information regarding the allocation of + * read results, please refer to the EXT_SENS_DATA register description + * (Registers 73 - 96). + * + * The MPU-6050 supports a total of five slaves, but Slave 4 has unique + * characteristics, and so it has its own functions (getSlave4* and setSlave4*). + * + * I2C data transactions are performed at the Sample Rate, as defined in + * Register 25. The user is responsible for ensuring that I2C data transactions + * to and from each enabled Slave can be completed within a single period of the + * Sample Rate. + * + * The I2C slave access rate can be reduced relative to the Sample Rate. This + * reduced access rate is determined by I2C_MST_DLY (Register 52). Whether a + * slave's access rate is reduced relative to the Sample Rate is determined by + * I2C_MST_DELAY_CTRL (Register 103). + * + * The processing order for the slaves is fixed. The sequence followed for + * processing the slaves is Slave 0, Slave 1, Slave 2, Slave 3 and Slave 4. If a + * particular Slave is disabled it will be skipped. + * + * Each slave can either be accessed at the sample rate or at a reduced sample + * rate. In a case where some slaves are accessed at the Sample Rate and some + * slaves are accessed at the reduced rate, the sequence of accessing the slaves + * (Slave 0 to Slave 4) is still followed. However, the reduced rate slaves will + * be skipped if their access rate dictates that they should not be accessed + * during that particular cycle. For further information regarding the reduced + * access rate, please refer to Register 52. Whether a slave is accessed at the + * Sample Rate or at the reduced rate is determined by the Delay Enable bits in + * Register 103. + * + * @param num Slave number (0-3) + * @return Current address for specified slave + * @see MPU6050_RA_I2C_SLV0_ADDR + */ +uint8_t MPU6050_getSlaveAddress(uint8_t num) { + if (num > 3) return 0; + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_ADDR + num*3, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set the I2C address of the specified slave (0-3). + * @param num Slave number (0-3) + * @param address New address for specified slave + * @see getSlaveAddress() + * @see MPU6050_RA_I2C_SLV0_ADDR + */ +void MPU6050_setSlaveAddress(uint8_t num, uint8_t address) { + if (num > 3) return; + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_ADDR + num*3, address); +} +/** Get the active internal register for the specified slave (0-3). + * Read/write operations for this slave will be done to whatever internal + * register address is stored in this MPU register. + * + * The MPU-6050 supports a total of five slaves, but Slave 4 has unique + * characteristics, and so it has its own functions. + * + * @param num Slave number (0-3) + * @return Current active register for specified slave + * @see MPU6050_RA_I2C_SLV0_REG + */ +uint8_t MPU6050_getSlaveRegister(uint8_t num) { + if (num > 3) return 0; + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_REG + num*3, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set the active internal register for the specified slave (0-3). + * @param num Slave number (0-3) + * @param reg New active register for specified slave + * @see getSlaveRegister() + * @see MPU6050_RA_I2C_SLV0_REG + */ +void MPU6050_setSlaveRegister(uint8_t num, uint8_t reg) { + if (num > 3) return; + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_REG + num*3, reg); +} +/** Get the enabled value for the specified slave (0-3). + * When set to 1, this bit enables Slave 0 for data transfer operations. When + * cleared to 0, this bit disables Slave 0 from data transfer operations. + * @param num Slave number (0-3) + * @return Current enabled value for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +bool MPU6050_getSlaveEnabled(uint8_t num) { + if (num > 3) return 0; + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set the enabled value for the specified slave (0-3). + * @param num Slave number (0-3) + * @param enabled New enabled value for specified slave + * @see getSlaveEnabled() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050_setSlaveEnabled(uint8_t num, bool enabled) { + if (num > 3) return; + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_EN_BIT, enabled); +} +/** Get word pair byte-swapping enabled for the specified slave (0-3). + * When set to 1, this bit enables byte swapping. When byte swapping is enabled, + * the high and low bytes of a word pair are swapped. Please refer to + * I2C_SLV0_GRP for the pairing convention of the word pairs. When cleared to 0, + * bytes transferred to and from Slave 0 will be written to EXT_SENS_DATA + * registers in the order they were transferred. + * + * @param num Slave number (0-3) + * @return Current word pair byte-swapping enabled value for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +bool MPU6050_getSlaveWordByteSwap(uint8_t num) { + if (num > 3) return 0; + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_BYTE_SW_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set word pair byte-swapping enabled for the specified slave (0-3). + * @param num Slave number (0-3) + * @param enabled New word pair byte-swapping enabled value for specified slave + * @see getSlaveWordByteSwap() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050_setSlaveWordByteSwap(uint8_t num, bool enabled) { + if (num > 3) return; + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_BYTE_SW_BIT, enabled); +} +/** Get write mode for the specified slave (0-3). + * When set to 1, the transaction will read or write data only. When cleared to + * 0, the transaction will write a register address prior to reading or writing + * data. This should equal 0 when specifying the register address within the + * Slave device to/from which the ensuing data transaction will take place. + * + * @param num Slave number (0-3) + * @return Current write mode for specified slave (0 = register address + data, 1 = data only) + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +bool MPU6050_getSlaveWriteMode(uint8_t num) { + if (num > 3) return 0; + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_REG_DIS_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set write mode for the specified slave (0-3). + * @param num Slave number (0-3) + * @param mode New write mode for specified slave (0 = register address + data, 1 = data only) + * @see getSlaveWriteMode() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050_setSlaveWriteMode(uint8_t num, bool mode) { + if (num > 3) return; + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_REG_DIS_BIT, mode); +} +/** Get word pair grouping order offset for the specified slave (0-3). + * This sets specifies the grouping order of word pairs received from registers. + * When cleared to 0, bytes from register addresses 0 and 1, 2 and 3, etc (even, + * then odd register addresses) are paired to form a word. When set to 1, bytes + * from register addresses are paired 1 and 2, 3 and 4, etc. (odd, then even + * register addresses) are paired to form a word. + * + * @param num Slave number (0-3) + * @return Current word pair grouping order offset for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +bool MPU6050_getSlaveWordGroupOffset(uint8_t num) { + if (num > 3) return 0; + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_GRP_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set word pair grouping order offset for the specified slave (0-3). + * @param num Slave number (0-3) + * @param enabled New word pair grouping order offset for specified slave + * @see getSlaveWordGroupOffset() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050_setSlaveWordGroupOffset(uint8_t num, bool enabled) { + if (num > 3) return; + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_GRP_BIT, enabled); +} +/** Get number of bytes to read for the specified slave (0-3). + * Specifies the number of bytes transferred to and from Slave 0. Clearing this + * bit to 0 is equivalent to disabling the register by writing 0 to I2C_SLV0_EN. + * @param num Slave number (0-3) + * @return Number of bytes to read for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +uint8_t MPU6050_getSlaveDataLength(uint8_t num) { + if (num > 3) return 0; + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_LEN_BIT, MPU6050_I2C_SLV_LEN_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set number of bytes to read for the specified slave (0-3). + * @param num Slave number (0-3) + * @param length Number of bytes to read for specified slave + * @see getSlaveDataLength() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050_setSlaveDataLength(uint8_t num, uint8_t length) { + if (num > 3) return; + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_LEN_BIT, MPU6050_I2C_SLV_LEN_LENGTH, length); +} + +// I2C_SLV* registers (Slave 4) + +/** Get the I2C address of Slave 4. + * Note that Bit 7 (MSB) controls read/write mode. If Bit 7 is set, it's a read + * operation, and if it is cleared, then it's a write operation. The remaining + * bits (6-0) are the 7-bit device address of the slave device. + * + * @return Current address for Slave 4 + * @see getSlaveAddress() + * @see MPU6050_RA_I2C_SLV4_ADDR + */ +uint8_t MPU6050_getSlave4Address() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_ADDR, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set the I2C address of Slave 4. + * @param address New address for Slave 4 + * @see getSlave4Address() + * @see MPU6050_RA_I2C_SLV4_ADDR + */ +void MPU6050_setSlave4Address(uint8_t address) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_ADDR, address); +} +/** Get the active internal register for the Slave 4. + * Read/write operations for this slave will be done to whatever internal + * register address is stored in this MPU register. + * + * @return Current active register for Slave 4 + * @see MPU6050_RA_I2C_SLV4_REG + */ +uint8_t MPU6050_getSlave4Register() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_REG, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set the active internal register for Slave 4. + * @param reg New active register for Slave 4 + * @see getSlave4Register() + * @see MPU6050_RA_I2C_SLV4_REG + */ +void MPU6050_setSlave4Register(uint8_t reg) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_REG, reg); +} +/** Set new byte to write to Slave 4. + * This register stores the data to be written into the Slave 4. If I2C_SLV4_RW + * is set 1 (set to read), this register has no effect. + * @param data New byte to write to Slave 4 + * @see MPU6050_RA_I2C_SLV4_DO + */ +void MPU6050_setSlave4OutputByte(uint8_t data) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_DO, data); +} +/** Get the enabled value for the Slave 4. + * When set to 1, this bit enables Slave 4 for data transfer operations. When + * cleared to 0, this bit disables Slave 4 from data transfer operations. + * @return Current enabled value for Slave 4 + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +bool MPU6050_getSlave4Enabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set the enabled value for Slave 4. + * @param enabled New enabled value for Slave 4 + * @see getSlave4Enabled() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050_setSlave4Enabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_EN_BIT, enabled); +} +/** Get the enabled value for Slave 4 transaction interrupts. + * When set to 1, this bit enables the generation of an interrupt signal upon + * completion of a Slave 4 transaction. When cleared to 0, this bit disables the + * generation of an interrupt signal upon completion of a Slave 4 transaction. + * The interrupt status can be observed in Register 54. + * + * @return Current enabled value for Slave 4 transaction interrupts. + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +bool MPU6050_getSlave4InterruptEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_INT_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set the enabled value for Slave 4 transaction interrupts. + * @param enabled New enabled value for Slave 4 transaction interrupts. + * @see getSlave4InterruptEnabled() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050_setSlave4InterruptEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_INT_EN_BIT, enabled); +} +/** Get write mode for Slave 4. + * When set to 1, the transaction will read or write data only. When cleared to + * 0, the transaction will write a register address prior to reading or writing + * data. This should equal 0 when specifying the register address within the + * Slave device to/from which the ensuing data transaction will take place. + * + * @return Current write mode for Slave 4 (0 = register address + data, 1 = data only) + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +bool MPU6050_getSlave4WriteMode() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_REG_DIS_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set write mode for the Slave 4. + * @param mode New write mode for Slave 4 (0 = register address + data, 1 = data only) + * @see getSlave4WriteMode() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050_setSlave4WriteMode(bool mode) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_REG_DIS_BIT, mode); +} +/** Get Slave 4 master delay value. + * This configures the reduced access rate of I2C slaves relative to the Sample + * Rate. When a slave's access rate is decreased relative to the Sample Rate, + * the slave is accessed every: + * + * 1 / (1 + I2C_MST_DLY) samples + * + * This base Sample Rate in turn is determined by SMPLRT_DIV (register 25) and + * DLPF_CFG (register 26). Whether a slave's access rate is reduced relative to + * the Sample Rate is determined by I2C_MST_DELAY_CTRL (register 103). For + * further information regarding the Sample Rate, please refer to register 25. + * + * @return Current Slave 4 master delay value + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +uint8_t MPU6050_getSlave4MasterDelay() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_MST_DLY_BIT, MPU6050_I2C_SLV4_MST_DLY_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Slave 4 master delay value. + * @param delay New Slave 4 master delay value + * @see getSlave4MasterDelay() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050_setSlave4MasterDelay(uint8_t delay) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_MST_DLY_BIT, MPU6050_I2C_SLV4_MST_DLY_LENGTH, delay); +} +/** Get last available byte read from Slave 4. + * This register stores the data read from Slave 4. This field is populated + * after a read transaction. + * @return Last available byte read from to Slave 4 + * @see MPU6050_RA_I2C_SLV4_DI + */ +uint8_t MPU6050_getSlate4InputByte() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_DI, mpu6050.buffer); + return mpu6050.buffer[0]; +} + +// I2C_MST_STATUS register + +/** Get FSYNC interrupt status. + * This bit reflects the status of the FSYNC interrupt from an external device + * into the MPU-60X0. This is used as a way to pass an external interrupt + * through the MPU-60X0 to the host application processor. When set to 1, this + * bit will cause an interrupt if FSYNC_INT_EN is asserted in INT_PIN_CFG + * (Register 55). + * @return FSYNC interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_getPassthroughStatus() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_PASS_THROUGH_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Slave 4 transaction done status. + * Automatically sets to 1 when a Slave 4 transaction has completed. This + * triggers an interrupt if the I2C_MST_INT_EN bit in the INT_ENABLE register + * (Register 56) is asserted and if the SLV_4_DONE_INT bit is asserted in the + * I2C_SLV4_CTRL register (Register 52). + * @return Slave 4 transaction done status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_getSlave4IsDone() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV4_DONE_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get master arbitration lost status. + * This bit automatically sets to 1 when the I2C Master has lost arbitration of + * the auxiliary I2C bus (an error condition). This triggers an interrupt if the + * I2C_MST_INT_EN bit in the INT_ENABLE register (Register 56) is asserted. + * @return Master arbitration lost status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_getLostArbitration() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_LOST_ARB_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Slave 4 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 4. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 4 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_getSlave4Nack() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV4_NACK_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Slave 3 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 3. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 3 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_getSlave3Nack() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV3_NACK_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Slave 2 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 2. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 2 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_getSlave2Nack() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV2_NACK_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Slave 1 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 1. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 1 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_getSlave1Nack() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV1_NACK_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Slave 0 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 0. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 0 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_getSlave0Nack() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV0_NACK_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} + +// INT_PIN_CFG register + +/** Get interrupt logic level mode. + * Will be set 0 for active-high, 1 for active-low. + * @return Current interrupt mode (0=active-high, 1=active-low) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_LEVEL_BIT + */ +bool MPU6050_getInterruptMode() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_LEVEL_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set interrupt logic level mode. + * @param mode New interrupt mode (0=active-high, 1=active-low) + * @see getInterruptMode() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_LEVEL_BIT + */ +void MPU6050_setInterruptMode(bool mode) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_LEVEL_BIT, mode); +} +/** Get interrupt drive mode. + * Will be set 0 for push-pull, 1 for open-drain. + * @return Current interrupt drive mode (0=push-pull, 1=open-drain) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_OPEN_BIT + */ +bool MPU6050_getInterruptDrive() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_OPEN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set interrupt drive mode. + * @param drive New interrupt drive mode (0=push-pull, 1=open-drain) + * @see getInterruptDrive() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_OPEN_BIT + */ +void MPU6050_setInterruptDrive(bool drive) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_OPEN_BIT, drive); +} +/** Get interrupt latch mode. + * Will be set 0 for 50us-pulse, 1 for latch-until-int-cleared. + * @return Current latch mode (0=50us-pulse, 1=latch-until-int-cleared) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_LATCH_INT_EN_BIT + */ +bool MPU6050_getInterruptLatch() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_LATCH_INT_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set interrupt latch mode. + * @param latch New latch mode (0=50us-pulse, 1=latch-until-int-cleared) + * @see getInterruptLatch() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_LATCH_INT_EN_BIT + */ +void MPU6050_setInterruptLatch(bool latch) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_LATCH_INT_EN_BIT, latch); +} +/** Get interrupt latch clear mode. + * Will be set 0 for status-read-only, 1 for any-register-read. + * @return Current latch clear mode (0=status-read-only, 1=any-register-read) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_RD_CLEAR_BIT + */ +bool MPU6050_getInterruptLatchClear() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_RD_CLEAR_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set interrupt latch clear mode. + * @param clear New latch clear mode (0=status-read-only, 1=any-register-read) + * @see getInterruptLatchClear() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_RD_CLEAR_BIT + */ +void MPU6050_setInterruptLatchClear(bool clear) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_RD_CLEAR_BIT, clear); +} +/** Get FSYNC interrupt logic level mode. + * @return Current FSYNC interrupt mode (0=active-high, 1=active-low) + * @see getFSyncInterruptMode() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT + */ +bool MPU6050_getFSyncInterruptLevel() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set FSYNC interrupt logic level mode. + * @param mode New FSYNC interrupt mode (0=active-high, 1=active-low) + * @see getFSyncInterruptMode() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT + */ +void MPU6050_setFSyncInterruptLevel(bool level) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT, level); +} +/** Get FSYNC pin interrupt enabled setting. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled setting + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_EN_BIT + */ +bool MPU6050_getFSyncInterruptEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set FSYNC pin interrupt enabled setting. + * @param enabled New FSYNC pin interrupt enabled setting + * @see getFSyncInterruptEnabled() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_EN_BIT + */ +void MPU6050_setFSyncInterruptEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_EN_BIT, enabled); +} +/** Get I2C bypass enabled status. + * When this bit is equal to 1 and I2C_MST_EN (Register 106 bit[5]) is equal to + * 0, the host application processor will be able to directly access the + * auxiliary I2C bus of the MPU-60X0. When this bit is equal to 0, the host + * application processor will not be able to directly access the auxiliary I2C + * bus of the MPU-60X0 regardless of the state of I2C_MST_EN (Register 106 + * bit[5]). + * @return Current I2C bypass enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_I2C_BYPASS_EN_BIT + */ +bool MPU6050_getI2CBypassEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_I2C_BYPASS_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set I2C bypass enabled status. + * When this bit is equal to 1 and I2C_MST_EN (Register 106 bit[5]) is equal to + * 0, the host application processor will be able to directly access the + * auxiliary I2C bus of the MPU-60X0. When this bit is equal to 0, the host + * application processor will not be able to directly access the auxiliary I2C + * bus of the MPU-60X0 regardless of the state of I2C_MST_EN (Register 106 + * bit[5]). + * @param enabled New I2C bypass enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_I2C_BYPASS_EN_BIT + */ +void MPU6050_setI2CBypassEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_I2C_BYPASS_EN_BIT, enabled); +} +/** Get reference clock output enabled status. + * When this bit is equal to 1, a reference clock output is provided at the + * CLKOUT pin. When this bit is equal to 0, the clock output is disabled. For + * further information regarding CLKOUT, please refer to the MPU-60X0 Product + * Specification document. + * @return Current reference clock output enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_CLKOUT_EN_BIT + */ +bool MPU6050_getClockOutputEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_CLKOUT_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set reference clock output enabled status. + * When this bit is equal to 1, a reference clock output is provided at the + * CLKOUT pin. When this bit is equal to 0, the clock output is disabled. For + * further information regarding CLKOUT, please refer to the MPU-60X0 Product + * Specification document. + * @param enabled New reference clock output enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_CLKOUT_EN_BIT + */ +void MPU6050_setClockOutputEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_CLKOUT_EN_BIT, enabled); +} + +// INT_ENABLE register + +/** Get full interrupt enabled status. + * Full register byte for all interrupts, for quick reading. Each bit will be + * set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +uint8_t MPU6050_getIntEnabled() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set full interrupt enabled status. + * Full register byte for all interrupts, for quick reading. Each bit should be + * set 0 for disabled, 1 for enabled. + * @param enabled New interrupt enabled status + * @see getIntFreefallEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +void MPU6050_setIntEnabled(uint8_t enabled) { + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, enabled); +} +/** Get Free Fall interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +bool MPU6050_getIntFreefallEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FF_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Free Fall interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntFreefallEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +void MPU6050_setIntFreefallEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FF_BIT, enabled); +} +/** Get Motion Detection interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_MOT_BIT + **/ +bool MPU6050_getIntMotionEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_MOT_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Motion Detection interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntMotionEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_MOT_BIT + **/ +void MPU6050_setIntMotionEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_MOT_BIT, enabled); +} +/** Get Zero Motion Detection interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_ZMOT_BIT + **/ +bool MPU6050_getIntZeroMotionEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_ZMOT_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Zero Motion Detection interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntZeroMotionEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_ZMOT_BIT + **/ +void MPU6050_setIntZeroMotionEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_ZMOT_BIT, enabled); +} +/** Get FIFO Buffer Overflow interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT + **/ +bool MPU6050_getIntFIFOBufferOverflowEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set FIFO Buffer Overflow interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntFIFOBufferOverflowEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT + **/ +void MPU6050_setIntFIFOBufferOverflowEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, enabled); +} +/** Get I2C Master interrupt enabled status. + * This enables any of the I2C Master interrupt sources to generate an + * interrupt. Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT + **/ +bool MPU6050_getIntI2CMasterEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_I2C_MST_INT_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set I2C Master interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntI2CMasterEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT + **/ +void MPU6050_setIntI2CMasterEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_I2C_MST_INT_BIT, enabled); +} +/** Get Data Ready interrupt enabled setting. + * This event occurs each time a write operation to all of the sensor registers + * has been completed. Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_DATA_RDY_BIT + */ +bool MPU6050_getIntDataReadyEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DATA_RDY_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Data Ready interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntDataReadyEnabled() + * @see MPU6050_RA_INT_CFG + * @see MPU6050_INTERRUPT_DATA_RDY_BIT + */ +void MPU6050_setIntDataReadyEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DATA_RDY_BIT, enabled); +} + +// INT_STATUS register + +/** Get full set of interrupt status bits. + * These bits clear to 0 after the register has been read. Very useful + * for getting multiple INT statuses, since each single bit read clears + * all of them because it has to read the whole byte. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + */ +uint8_t MPU6050_getIntStatus() { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_INT_STATUS, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Free Fall interrupt status. + * This bit automatically sets to 1 when a Free Fall interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_FF_BIT + */ +bool MPU6050_getIntFreefallStatus() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_FF_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Motion Detection interrupt status. + * This bit automatically sets to 1 when a Motion Detection interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_MOT_BIT + */ +bool MPU6050_getIntMotionStatus() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_MOT_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Zero Motion Detection interrupt status. + * This bit automatically sets to 1 when a Zero Motion Detection interrupt has + * been generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_ZMOT_BIT + */ +bool MPU6050_getIntZeroMotionStatus() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_ZMOT_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get FIFO Buffer Overflow interrupt status. + * This bit automatically sets to 1 when a Free Fall interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT + */ +bool MPU6050_getIntFIFOBufferOverflowStatus() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get I2C Master interrupt status. + * This bit automatically sets to 1 when an I2C Master interrupt has been + * generated. For a list of I2C Master interrupts, please refer to Register 54. + * The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT + */ +bool MPU6050_getIntI2CMasterStatus() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_I2C_MST_INT_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Data Ready interrupt status. + * This bit automatically sets to 1 when a Data Ready interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_DATA_RDY_BIT + */ +bool MPU6050_getIntDataReadyStatus() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_DATA_RDY_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} + +// ACCEL_*OUT_* registers + +/** Get raw 9-axis motion sensor readings (accel/gyro/compass). + * FUNCTION NOT FULLY IMPLEMENTED YET. + * @param ax 16-bit signed integer container for accelerometer X-axis value + * @param ay 16-bit signed integer container for accelerometer Y-axis value + * @param az 16-bit signed integer container for accelerometer Z-axis value + * @param gx 16-bit signed integer container for gyroscope X-axis value + * @param gy 16-bit signed integer container for gyroscope Y-axis value + * @param gz 16-bit signed integer container for gyroscope Z-axis value + * @param mx 16-bit signed integer container for magnetometer X-axis value + * @param my 16-bit signed integer container for magnetometer Y-axis value + * @param mz 16-bit signed integer container for magnetometer Z-axis value + * @see getMotion6() + * @see getAcceleration() + * @see getRotation() + * @see MPU6050_RA_ACCEL_XOUT_H + */ +void MPU6050_getMotion9(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz, int16_t* mx, int16_t* my, int16_t* mz) { + MPU6050_getMotion6(ax, ay, az, gx, gy, gz); + // TODO: magnetometer integration +} +/** Get raw 6-axis motion sensor readings (accel/gyro). + * Retrieves all currently available motion sensor values. + * @param ax 16-bit signed integer container for accelerometer X-axis value + * @param ay 16-bit signed integer container for accelerometer Y-axis value + * @param az 16-bit signed integer container for accelerometer Z-axis value + * @param gx 16-bit signed integer container for gyroscope X-axis value + * @param gy 16-bit signed integer container for gyroscope Y-axis value + * @param gz 16-bit signed integer container for gyroscope Z-axis value + * @see getAcceleration() + * @see getRotation() + * @see MPU6050_RA_ACCEL_XOUT_H + */ +void MPU6050_getMotion6(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz) { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ACCEL_XOUT_H, 14, mpu6050.buffer); + *ax = (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; + *ay = (((int16_t)mpu6050.buffer[2]) << 8) | mpu6050.buffer[3]; + *az = (((int16_t)mpu6050.buffer[4]) << 8) | mpu6050.buffer[5]; + *gx = (((int16_t)mpu6050.buffer[8]) << 8) | mpu6050.buffer[9]; + *gy = (((int16_t)mpu6050.buffer[10]) << 8) | mpu6050.buffer[11]; + *gz = (((int16_t)mpu6050.buffer[12]) << 8) | mpu6050.buffer[13]; +} +/** Get 3-axis accelerometer readings. + * These registers store the most recent accelerometer measurements. + * Accelerometer measurements are written to these registers at the Sample Rate + * as defined in Register 25. + * + * The accelerometer measurement registers, along with the temperature + * measurement registers, gyroscope measurement registers, and external sensor + * data registers, are composed of two sets of registers: an internal register + * set and a user-facing read register set. + * + * The data within the accelerometer sensors' internal register set is always + * updated at the Sample Rate. Meanwhile, the user-facing read register set + * duplicates the internal register set's data values whenever the serial + * interface is idle. This guarantees that a burst read of sensor registers will + * read measurements from the same sampling instant. Note that if burst reads + * are not used, the user is responsible for ensuring a set of single byte reads + * correspond to a single sampling instant by checking the Data Ready interrupt. + * + * Each 16-bit accelerometer measurement has a full scale defined in ACCEL_FS + * (Register 28). For each full scale setting, the accelerometers' sensitivity + * per LSB in ACCEL_xOUT is shown in the table below: + * + *
+ * AFS_SEL | Full Scale Range | LSB Sensitivity
+ * --------+------------------+----------------
+ * 0       | +/- 2g           | 8192 LSB/mg
+ * 1       | +/- 4g           | 4096 LSB/mg
+ * 2       | +/- 8g           | 2048 LSB/mg
+ * 3       | +/- 16g          | 1024 LSB/mg
+ * 
+ * + * @param x 16-bit signed integer container for X-axis acceleration + * @param y 16-bit signed integer container for Y-axis acceleration + * @param z 16-bit signed integer container for Z-axis acceleration + * @see MPU6050_RA_GYRO_XOUT_H + */ +void MPU6050_getAcceleration(int16_t* x, int16_t* y, int16_t* z) { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ACCEL_XOUT_H, 6, mpu6050.buffer); + *x = (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; + *y = (((int16_t)mpu6050.buffer[2]) << 8) | mpu6050.buffer[3]; + *z = (((int16_t)mpu6050.buffer[4]) << 8) | mpu6050.buffer[5]; +} +/** Get X-axis accelerometer reading. + * @return X-axis acceleration measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_ACCEL_XOUT_H + */ +int16_t MPU6050_getAccelerationX() { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ACCEL_XOUT_H, 2, mpu6050.buffer); + return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; +} +/** Get Y-axis accelerometer reading. + * @return Y-axis acceleration measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_ACCEL_YOUT_H + */ +int16_t MPU6050_getAccelerationY() { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ACCEL_YOUT_H, 2, mpu6050.buffer); + return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; +} +/** Get Z-axis accelerometer reading. + * @return Z-axis acceleration measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_ACCEL_ZOUT_H + */ +int16_t MPU6050_getAccelerationZ() { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ACCEL_ZOUT_H, 2, mpu6050.buffer); + return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; +} + +// TEMP_OUT_* registers + +/** Get current internal temperature. + * @return Temperature reading in 16-bit 2's complement format + * @see MPU6050_RA_TEMP_OUT_H + */ +int16_t MPU6050_getTemperature() { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_TEMP_OUT_H, 2, mpu6050.buffer); + return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; +} + +// GYRO_*OUT_* registers + +/** Get 3-axis gyroscope readings. + * These gyroscope measurement registers, along with the accelerometer + * measurement registers, temperature measurement registers, and external sensor + * data registers, are composed of two sets of registers: an internal register + * set and a user-facing read register set. + * The data within the gyroscope sensors' internal register set is always + * updated at the Sample Rate. Meanwhile, the user-facing read register set + * duplicates the internal register set's data values whenever the serial + * interface is idle. This guarantees that a burst read of sensor registers will + * read measurements from the same sampling instant. Note that if burst reads + * are not used, the user is responsible for ensuring a set of single byte reads + * correspond to a single sampling instant by checking the Data Ready interrupt. + * + * Each 16-bit gyroscope measurement has a full scale defined in FS_SEL + * (Register 27). For each full scale setting, the gyroscopes' sensitivity per + * LSB in GYRO_xOUT is shown in the table below: + * + *
+ * FS_SEL | Full Scale Range   | LSB Sensitivity
+ * -------+--------------------+----------------
+ * 0      | +/- 250 degrees/s  | 131 LSB/deg/s
+ * 1      | +/- 500 degrees/s  | 65.5 LSB/deg/s
+ * 2      | +/- 1000 degrees/s | 32.8 LSB/deg/s
+ * 3      | +/- 2000 degrees/s | 16.4 LSB/deg/s
+ * 
+ * + * @param x 16-bit signed integer container for X-axis rotation + * @param y 16-bit signed integer container for Y-axis rotation + * @param z 16-bit signed integer container for Z-axis rotation + * @see getMotion6() + * @see MPU6050_RA_GYRO_XOUT_H + */ +void MPU6050_getRotation(int16_t* x, int16_t* y, int16_t* z) { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_GYRO_XOUT_H, 6, mpu6050.buffer); + *x = (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; + *y = (((int16_t)mpu6050.buffer[2]) << 8) | mpu6050.buffer[3]; + *z = (((int16_t)mpu6050.buffer[4]) << 8) | mpu6050.buffer[5]; +} +/** Get X-axis gyroscope reading. + * @return X-axis rotation measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_GYRO_XOUT_H + */ +int16_t MPU6050_getRotationX() { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_GYRO_XOUT_H, 2, mpu6050.buffer); + return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; +} +/** Get Y-axis gyroscope reading. + * @return Y-axis rotation measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_GYRO_YOUT_H + */ +int16_t MPU6050_getRotationY() { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_GYRO_YOUT_H, 2, mpu6050.buffer); + return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; +} +/** Get Z-axis gyroscope reading. + * @return Z-axis rotation measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_GYRO_ZOUT_H + */ +int16_t MPU6050_getRotationZ() { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_GYRO_ZOUT_H, 2, mpu6050.buffer); + return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; +} + +// EXT_SENS_DATA_* registers + +/** Read single byte from external sensor data register. + * These registers store data read from external sensors by the Slave 0, 1, 2, + * and 3 on the auxiliary I2C interface. Data read by Slave 4 is stored in + * I2C_SLV4_DI (Register 53). + * + * External sensor data is written to these registers at the Sample Rate as + * defined in Register 25. This access rate can be reduced by using the Slave + * Delay Enable registers (Register 103). + * + * External sensor data registers, along with the gyroscope measurement + * registers, accelerometer measurement registers, and temperature measurement + * registers, are composed of two sets of registers: an internal register set + * and a user-facing read register set. + * + * The data within the external sensors' internal register set is always updated + * at the Sample Rate (or the reduced access rate) whenever the serial interface + * is idle. This guarantees that a burst read of sensor registers will read + * measurements from the same sampling instant. Note that if burst reads are not + * used, the user is responsible for ensuring a set of single byte reads + * correspond to a single sampling instant by checking the Data Ready interrupt. + * + * Data is placed in these external sensor data registers according to + * I2C_SLV0_CTRL, I2C_SLV1_CTRL, I2C_SLV2_CTRL, and I2C_SLV3_CTRL (Registers 39, + * 42, 45, and 48). When more than zero bytes are read (I2C_SLVx_LEN > 0) from + * an enabled slave (I2C_SLVx_EN = 1), the slave is read at the Sample Rate (as + * defined in Register 25) or delayed rate (if specified in Register 52 and + * 103). During each Sample cycle, slave reads are performed in order of Slave + * number. If all slaves are enabled with more than zero bytes to be read, the + * order will be Slave 0, followed by Slave 1, Slave 2, and Slave 3. + * + * Each enabled slave will have EXT_SENS_DATA registers associated with it by + * number of bytes read (I2C_SLVx_LEN) in order of slave number, starting from + * EXT_SENS_DATA_00. Note that this means enabling or disabling a slave may + * change the higher numbered slaves' associated registers. Furthermore, if + * fewer total bytes are being read from the external sensors as a result of + * such a change, then the data remaining in the registers which no longer have + * an associated slave device (i.e. high numbered registers) will remain in + * these previously allocated registers unless reset. + * + * If the sum of the read lengths of all SLVx transactions exceed the number of + * available EXT_SENS_DATA registers, the excess bytes will be dropped. There + * are 24 EXT_SENS_DATA registers and hence the total read lengths between all + * the slaves cannot be greater than 24 or some bytes will be lost. + * + * Note: Slave 4's behavior is distinct from that of Slaves 0-3. For further + * information regarding the characteristics of Slave 4, please refer to + * Registers 49 to 53. + * + * EXAMPLE: + * Suppose that Slave 0 is enabled with 4 bytes to be read (I2C_SLV0_EN = 1 and + * I2C_SLV0_LEN = 4) while Slave 1 is enabled with 2 bytes to be read so that + * I2C_SLV1_EN = 1 and I2C_SLV1_LEN = 2. In such a situation, EXT_SENS_DATA _00 + * through _03 will be associated with Slave 0, while EXT_SENS_DATA _04 and 05 + * will be associated with Slave 1. If Slave 2 is enabled as well, registers + * starting from EXT_SENS_DATA_06 will be allocated to Slave 2. + * + * If Slave 2 is disabled while Slave 3 is enabled in this same situation, then + * registers starting from EXT_SENS_DATA_06 will be allocated to Slave 3 + * instead. + * + * REGISTER ALLOCATION FOR DYNAMIC DISABLE VS. NORMAL DISABLE: + * If a slave is disabled at any time, the space initially allocated to the + * slave in the EXT_SENS_DATA register, will remain associated with that slave. + * This is to avoid dynamic adjustment of the register allocation. + * + * The allocation of the EXT_SENS_DATA registers is recomputed only when (1) all + * slaves are disabled, or (2) the I2C_MST_RST bit is set (Register 106). + * + * This above is also true if one of the slaves gets NACKed and stops + * functioning. + * + * @param position Starting position (0-23) + * @return Byte read from register + */ +uint8_t MPU6050_getExternalSensorByte(int position) { + I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Read word (2 bytes) from external sensor data registers. + * @param position Starting position (0-21) + * @return Word read from register + * @see getExternalSensorByte() + */ +uint16_t MPU6050_getExternalSensorWord(int position) { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, 2, mpu6050.buffer); + return (((uint16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; +} +/** Read double word (4 bytes) from external sensor data registers. + * @param position Starting position (0-20) + * @return Double word read from registers + * @see getExternalSensorByte() + */ +uint32_t MPU6050_getExternalSensorDWord(int position) { + I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, 4, mpu6050.buffer); + return (((uint32_t)mpu6050.buffer[0]) << 24) | (((uint32_t)mpu6050.buffer[1]) << 16) | (((uint16_t)mpu6050.buffer[2]) << 8) | mpu6050.buffer[3]; +} + +// MOT_DETECT_STATUS register + +/** Get X-axis negative motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_XNEG_BIT + */ +bool MPU6050_getXNegMotionDetected() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_XNEG_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get X-axis positive motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_XPOS_BIT + */ +bool MPU6050_getXPosMotionDetected() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_XPOS_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Y-axis negative motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_YNEG_BIT + */ +bool MPU6050_getYNegMotionDetected() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_YNEG_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Y-axis positive motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_YPOS_BIT + */ +bool MPU6050_getYPosMotionDetected() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_YPOS_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Z-axis negative motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_ZNEG_BIT + */ +bool MPU6050_getZNegMotionDetected() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZNEG_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get Z-axis positive motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_ZPOS_BIT + */ +bool MPU6050_getZPosMotionDetected() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZPOS_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Get zero motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_ZRMOT_BIT + */ +bool MPU6050_getZeroMotionDetected() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZRMOT_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} + +// I2C_SLV*_DO register + +/** Write byte to Data Output container for specified slave. + * This register holds the output data written into Slave when Slave is set to + * write mode. For further information regarding Slave control, please + * refer to Registers 37 to 39 and immediately following. + * @param num Slave number (0-3) + * @param data Byte to write + * @see MPU6050_RA_I2C_SLV0_DO + */ +void MPU6050_setSlaveOutputByte(uint8_t num, uint8_t data) { + if (num > 3) return; + I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_DO + num, data); +} + +// I2C_MST_DELAY_CTRL register + +/** Get external data shadow delay enabled status. + * This register is used to specify the timing of external sensor data + * shadowing. When DELAY_ES_SHADOW is set to 1, shadowing of external + * sensor data is delayed until all data has been received. + * @return Current external data shadow delay enabled status. + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT + */ +bool MPU6050_getExternalShadowDelayEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set external data shadow delay enabled status. + * @param enabled New external data shadow delay enabled status. + * @see getExternalShadowDelayEnabled() + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT + */ +void MPU6050_setExternalShadowDelayEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT, enabled); +} +/** Get slave delay enabled status. + * When a particular slave delay is enabled, the rate of access for the that + * slave device is reduced. When a slave's access rate is decreased relative to + * the Sample Rate, the slave is accessed every: + * + * 1 / (1 + I2C_MST_DLY) Samples + * + * This base Sample Rate in turn is determined by SMPLRT_DIV (register * 25) + * and DLPF_CFG (register 26). + * + * For further information regarding I2C_MST_DLY, please refer to register 52. + * For further information regarding the Sample Rate, please refer to register 25. + * + * @param num Slave number (0-4) + * @return Current slave delay enabled status. + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT + */ +bool MPU6050_getSlaveDelayEnabled(uint8_t num) { + // MPU6050_DELAYCTRL_I2C_SLV4_DLY_EN_BIT is 4, SLV3 is 3, etc. + if (num > 4) return 0; + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, num, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set slave delay enabled status. + * @param num Slave number (0-4) + * @param enabled New slave delay enabled status. + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT + */ +void MPU6050_setSlaveDelayEnabled(uint8_t num, bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, num, enabled); +} + +// SIGNAL_PATH_RESET register + +/** Reset gyroscope signal path. + * The reset will revert the signal path analog to digital converters and + * filters to their power up configurations. + * @see MPU6050_RA_SIGNAL_PATH_RESET + * @see MPU6050_PATHRESET_GYRO_RESET_BIT + */ +void MPU6050_resetGyroscopePath() { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_GYRO_RESET_BIT, true); +} +/** Reset accelerometer signal path. + * The reset will revert the signal path analog to digital converters and + * filters to their power up configurations. + * @see MPU6050_RA_SIGNAL_PATH_RESET + * @see MPU6050_PATHRESET_ACCEL_RESET_BIT + */ +void MPU6050_resetAccelerometerPath() { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_ACCEL_RESET_BIT, true); +} +/** Reset temperature sensor signal path. + * The reset will revert the signal path analog to digital converters and + * filters to their power up configurations. + * @see MPU6050_RA_SIGNAL_PATH_RESET + * @see MPU6050_PATHRESET_TEMP_RESET_BIT + */ +void MPU6050_resetTemperaturePath() { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_TEMP_RESET_BIT, true); +} + +// MOT_DETECT_CTRL register + +/** Get accelerometer power-on delay. + * The accelerometer data path provides samples to the sensor registers, Motion + * detection, Zero Motion detection, and Free Fall detection modules. The + * signal path contains filters which must be flushed on wake-up with new + * samples before the detection modules begin operations. The default wake-up + * delay, of 4ms can be lengthened by up to 3ms. This additional delay is + * specified in ACCEL_ON_DELAY in units of 1 LSB = 1 ms. The user may select + * any value above zero unless instructed otherwise by InvenSense. Please refer + * to Section 8 of the MPU-6000/MPU-6050 Product Specification document for + * further information regarding the detection modules. + * @return Current accelerometer power-on delay + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_ACCEL_ON_DELAY_BIT + */ +uint8_t MPU6050_getAccelerometerPowerOnDelay() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_ACCEL_ON_DELAY_BIT, MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set accelerometer power-on delay. + * @param delay New accelerometer power-on delay (0-3) + * @see getAccelerometerPowerOnDelay() + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_ACCEL_ON_DELAY_BIT + */ +void MPU6050_setAccelerometerPowerOnDelay(uint8_t delay) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_ACCEL_ON_DELAY_BIT, MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH, delay); +} +/** Get Free Fall detection counter decrement configuration. + * Detection is registered by the Free Fall detection module after accelerometer + * measurements meet their respective threshold conditions over a specified + * number of samples. When the threshold conditions are met, the corresponding + * detection counter increments by 1. The user may control the rate at which the + * detection counter decrements when the threshold condition is not met by + * configuring FF_COUNT. The decrement rate can be set according to the + * following table: + * + *
+ * FF_COUNT | Counter Decrement
+ * ---------+------------------
+ * 0        | Reset
+ * 1        | 1
+ * 2        | 2
+ * 3        | 4
+ * 
+ * + * When FF_COUNT is configured to 0 (reset), any non-qualifying sample will + * reset the counter to 0. For further information on Free Fall detection, + * please refer to Registers 29 to 32. + * + * @return Current decrement configuration + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_FF_COUNT_BIT + */ +uint8_t MPU6050_getFreefallDetectionCounterDecrement() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_FF_COUNT_BIT, MPU6050_DETECT_FF_COUNT_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Free Fall detection counter decrement configuration. + * @param decrement New decrement configuration value + * @see getFreefallDetectionCounterDecrement() + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_FF_COUNT_BIT + */ +void MPU6050_setFreefallDetectionCounterDecrement(uint8_t decrement) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_FF_COUNT_BIT, MPU6050_DETECT_FF_COUNT_LENGTH, decrement); +} +/** Get Motion detection counter decrement configuration. + * Detection is registered by the Motion detection module after accelerometer + * measurements meet their respective threshold conditions over a specified + * number of samples. When the threshold conditions are met, the corresponding + * detection counter increments by 1. The user may control the rate at which the + * detection counter decrements when the threshold condition is not met by + * configuring MOT_COUNT. The decrement rate can be set according to the + * following table: + * + *
+ * MOT_COUNT | Counter Decrement
+ * ----------+------------------
+ * 0         | Reset
+ * 1         | 1
+ * 2         | 2
+ * 3         | 4
+ * 
+ * + * When MOT_COUNT is configured to 0 (reset), any non-qualifying sample will + * reset the counter to 0. For further information on Motion detection, + * please refer to Registers 29 to 32. + * + */ +uint8_t MPU6050_getMotionDetectionCounterDecrement() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_MOT_COUNT_BIT, MPU6050_DETECT_MOT_COUNT_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set Motion detection counter decrement configuration. + * @param decrement New decrement configuration value + * @see getMotionDetectionCounterDecrement() + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_MOT_COUNT_BIT + */ +void MPU6050_setMotionDetectionCounterDecrement(uint8_t decrement) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_MOT_COUNT_BIT, MPU6050_DETECT_MOT_COUNT_LENGTH, decrement); +} + +// USER_CTRL register + +/** Get FIFO enabled status. + * When this bit is set to 0, the FIFO mpu6050.buffer is disabled. The FIFO mpu6050.buffer + * cannot be written to or read from while disabled. The FIFO mpu6050.buffer's state + * does not change unless the MPU-60X0 is power cycled. + * @return Current FIFO enabled status + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_FIFO_EN_BIT + */ +bool MPU6050_getFIFOEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set FIFO enabled status. + * @param enabled New FIFO enabled status + * @see getFIFOEnabled() + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_FIFO_EN_BIT + */ +void MPU6050_setFIFOEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_EN_BIT, enabled); +} +/** Get I2C Master Mode enabled status. + * When this mode is enabled, the MPU-60X0 acts as the I2C Master to the + * external sensor slave devices on the auxiliary I2C bus. When this bit is + * cleared to 0, the auxiliary I2C bus lines (AUX_DA and AUX_CL) are logically + * driven by the primary I2C bus (SDA and SCL). This is a precondition to + * enabling Bypass Mode. For further information regarding Bypass Mode, please + * refer to Register 55. + * @return Current I2C Master Mode enabled status + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_I2C_MST_EN_BIT + */ +bool MPU6050_getI2CMasterModeEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_EN_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set I2C Master Mode enabled status. + * @param enabled New I2C Master Mode enabled status + * @see getI2CMasterModeEnabled() + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_I2C_MST_EN_BIT + */ +void MPU6050_setI2CMasterModeEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_EN_BIT, enabled); +} +/** Switch from I2C to SPI mode (MPU-6000 only) + * If this is set, the primary SPI interface will be enabled in place of the + * disabled primary I2C interface. + */ +void MPU6050_switchSPIEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_IF_DIS_BIT, enabled); +} +/** Reset the FIFO. + * This bit resets the FIFO mpu6050.buffer when set to 1 while FIFO_EN equals 0. This + * bit automatically clears to 0 after the reset has been triggered. + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_FIFO_RESET_BIT + */ +void MPU6050_resetFIFO() { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_RESET_BIT, true); +} +/** Reset the I2C Master. + * This bit resets the I2C Master when set to 1 while I2C_MST_EN equals 0. + * This bit automatically clears to 0 after the reset has been triggered. + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_I2C_MST_RESET_BIT + */ +void MPU6050_resetI2CMaster() { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_RESET_BIT, true); +} +/** Reset all sensor registers and signal paths. + * When set to 1, this bit resets the signal paths for all sensors (gyroscopes, + * accelerometers, and temperature sensor). This operation will also clear the + * sensor registers. This bit automatically clears to 0 after the reset has been + * triggered. + * + * When resetting only the signal path (and not the sensor registers), please + * use Register 104, SIGNAL_PATH_RESET. + * + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_SIG_COND_RESET_BIT + */ +void MPU6050_resetSensors() { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_SIG_COND_RESET_BIT, true); +} + +// PWR_MGMT_1 register + +/** Trigger a full device reset. + * A small delay of ~50ms may be desirable after triggering a reset. + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_DEVICE_RESET_BIT + */ +void MPU6050_reset() { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_DEVICE_RESET_BIT, true); +} +/** Get sleep mode status. + * Setting the SLEEP bit in the register puts the device into very low power + * sleep mode. In this mode, only the serial interface and internal registers + * remain active, allowing for a very low standby current. Clearing this bit + * puts the device back into normal mode. To save power, the individual standby + * selections for each of the gyros should be used if any gyro axis is not used + * by the application. + * @return Current sleep mode enabled status + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_SLEEP_BIT + */ +bool MPU6050_getSleepEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set sleep mode status. + * @param enabled New sleep mode enabled status + * @see getSleepEnabled() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_SLEEP_BIT + */ +void MPU6050_setSleepEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, enabled); +} +/** Get wake cycle enabled status. + * When this bit is set to 1 and SLEEP is disabled, the MPU-60X0 will cycle + * between sleep mode and waking up to take a single sample of data from active + * sensors at a rate determined by LP_WAKE_CTRL (register 108). + * @return Current sleep mode enabled status + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CYCLE_BIT + */ +bool MPU6050_getWakeCycleEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CYCLE_BIT, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set wake cycle enabled status. + * @param enabled New sleep mode enabled status + * @see getWakeCycleEnabled() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CYCLE_BIT + */ +void MPU6050_setWakeCycleEnabled(bool enabled) { + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CYCLE_BIT, enabled); +} +/** Get temperature sensor enabled status. + * Control the usage of the internal temperature sensor. + * + * Note: this register stores the *disabled* value, but for consistency with the + * rest of the code, the function is named and used with standard true/false + * values to indicate whether the sensor is enabled or disabled, respectively. + * + * @return Current temperature sensor enabled status + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_TEMP_DIS_BIT + */ +bool MPU6050_getTempSensorEnabled() { + I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_TEMP_DIS_BIT, mpu6050.buffer); + return mpu6050.buffer[0] == 0; // 1 is actually disabled here +} +/** Set temperature sensor enabled status. + * Note: this register stores the *disabled* value, but for consistency with the + * rest of the code, the function is named and used with standard true/false + * values to indicate whether the sensor is enabled or disabled, respectively. + * + * @param enabled New temperature sensor enabled status + * @see getTempSensorEnabled() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_TEMP_DIS_BIT + */ +void MPU6050_setTempSensorEnabled(bool enabled) { + // 1 is actually disabled here + I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_TEMP_DIS_BIT, !enabled); +} +/** Get clock source setting. + * @return Current clock source setting + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CLKSEL_BIT + * @see MPU6050_PWR1_CLKSEL_LENGTH + */ +uint8_t MPU6050_getClockSource() { + I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, mpu6050.buffer); + return mpu6050.buffer[0]; +} +/** Set clock source setting. + * An internal 8MHz oscillator, gyroscope based clock, or external sources can + * be selected as the MPU-60X0 clock source. When the internal 8 MHz oscillator + * or an external source is chosen as the clock source, the MPU-60X0 can operate + * in low power modes with the gyroscopes disabled. + * + * Upon power up, the MPU-60X0 clock source defaults to the internal oscillator. + * However, it is highly recommended that the device be configured to use one of + * the gyroscopes (or an external clock source) as the clock reference for + * improved stability. The clock source can be selected according to the following table: + * + *
+ * CLK_SEL | Clock Source
+ * --------+--------------------------------------
+ * 0       | Internal oscillator
+ * 1       | PLL with X Gyro reference
+ * 2       | PLL with Y Gyro reference
+ * 3       | PLL with Z Gyro reference
+ * 4       | PLL with external 32.768kHz reference
+ * 5       | PLL with external 19.2MHz reference
+ * 6       | Reserved
+ * 7       | Stops the clock and keeps the timing generator in reset
+ * 
+ * + * @param source New clock source setting + * @see getClockSource() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CLKSEL_BIT + * @see MPU6050_PWR1_CLKSEL_LENGTH + */ +void MPU6050_setClockSource(uint8_t source) { + I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, source); +} + +// PWR_MGMT_2 register + +/** Get wake frequency in Accel-Only Low Power Mode. + * The MPU-60X0 can be put into Accerlerometer Only Low Power Mode by setting + * PWRSEL to 1 in the Power Management 1 register (Register 107). In this mode, + * the device will power off all devices except for the primary I2C interface, + * waking only the accelerometer at fixed intervals to take a single + * measurement. The frequency of wake-ups can be configured with LP_WAKE_CTRL + * as shown below: + * + *
+ * LP_WAKE_CTRL | Wake-up Frequency
+ * -------------+------------------
+ * 0            | 1.25 Hz
+ * 1            | 2.5 Hz
+ * 2            | 5 Hz
+ * 3            | 10 Hz
+ * 
+ *
+ * For further information regarding the MPU-60X0's power modes, please refer to
+ * Register 107.
+ *
+ * @return Current wake frequency
+ * @see MPU6050_RA_PWR_MGMT_2
+ */
+uint8_t MPU6050_getWakeFrequency() {
+    I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_LP_WAKE_CTRL_BIT, MPU6050_PWR2_LP_WAKE_CTRL_LENGTH, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+/** Set wake frequency in Accel-Only Low Power Mode.
+ * @param frequency New wake frequency
+ * @see MPU6050_RA_PWR_MGMT_2
+ */
+void MPU6050_setWakeFrequency(uint8_t frequency) {
+    I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_LP_WAKE_CTRL_BIT, MPU6050_PWR2_LP_WAKE_CTRL_LENGTH, frequency);
+}
+
+/** Get X-axis accelerometer standby enabled status.
+ * If enabled, the X-axis will not gather or report data (or use power).
+ * @return Current X-axis standby enabled status
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_XA_BIT
+ */
+bool MPU6050_getStandbyXAccelEnabled() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XA_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+/** Set X-axis accelerometer standby enabled status.
+ * @param New X-axis standby enabled status
+ * @see getStandbyXAccelEnabled()
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_XA_BIT
+ */
+void MPU6050_setStandbyXAccelEnabled(bool enabled) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XA_BIT, enabled);
+}
+/** Get Y-axis accelerometer standby enabled status.
+ * If enabled, the Y-axis will not gather or report data (or use power).
+ * @return Current Y-axis standby enabled status
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_YA_BIT
+ */
+bool MPU6050_getStandbyYAccelEnabled() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YA_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+/** Set Y-axis accelerometer standby enabled status.
+ * @param New Y-axis standby enabled status
+ * @see getStandbyYAccelEnabled()
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_YA_BIT
+ */
+void MPU6050_setStandbyYAccelEnabled(bool enabled) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YA_BIT, enabled);
+}
+/** Get Z-axis accelerometer standby enabled status.
+ * If enabled, the Z-axis will not gather or report data (or use power).
+ * @return Current Z-axis standby enabled status
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_ZA_BIT
+ */
+bool MPU6050_getStandbyZAccelEnabled() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZA_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+/** Set Z-axis accelerometer standby enabled status.
+ * @param New Z-axis standby enabled status
+ * @see getStandbyZAccelEnabled()
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_ZA_BIT
+ */
+void MPU6050_setStandbyZAccelEnabled(bool enabled) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZA_BIT, enabled);
+}
+/** Get X-axis gyroscope standby enabled status.
+ * If enabled, the X-axis will not gather or report data (or use power).
+ * @return Current X-axis standby enabled status
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_XG_BIT
+ */
+bool MPU6050_getStandbyXGyroEnabled() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XG_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+/** Set X-axis gyroscope standby enabled status.
+ * @param New X-axis standby enabled status
+ * @see getStandbyXGyroEnabled()
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_XG_BIT
+ */
+void MPU6050_setStandbyXGyroEnabled(bool enabled) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XG_BIT, enabled);
+}
+/** Get Y-axis gyroscope standby enabled status.
+ * If enabled, the Y-axis will not gather or report data (or use power).
+ * @return Current Y-axis standby enabled status
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_YG_BIT
+ */
+bool MPU6050_getStandbyYGyroEnabled() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YG_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+/** Set Y-axis gyroscope standby enabled status.
+ * @param New Y-axis standby enabled status
+ * @see getStandbyYGyroEnabled()
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_YG_BIT
+ */
+void MPU6050_setStandbyYGyroEnabled(bool enabled) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YG_BIT, enabled);
+}
+/** Get Z-axis gyroscope standby enabled status.
+ * If enabled, the Z-axis will not gather or report data (or use power).
+ * @return Current Z-axis standby enabled status
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_ZG_BIT
+ */
+bool MPU6050_getStandbyZGyroEnabled() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZG_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+/** Set Z-axis gyroscope standby enabled status.
+ * @param New Z-axis standby enabled status
+ * @see getStandbyZGyroEnabled()
+ * @see MPU6050_RA_PWR_MGMT_2
+ * @see MPU6050_PWR2_STBY_ZG_BIT
+ */
+void MPU6050_setStandbyZGyroEnabled(bool enabled) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZG_BIT, enabled);
+}
+
+// FIFO_COUNT* registers
+
+/** Get current FIFO mpu6050.buffer size.
+ * This value indicates the number of bytes stored in the FIFO mpu6050.buffer. This
+ * number is in turn the number of bytes that can be read from the FIFO mpu6050.buffer
+ * and it is directly proportional to the number of samples available given the
+ * set of sensor data bound to be stored in the FIFO (register 35 and 36).
+ * @return Current FIFO mpu6050.buffer size
+ */
+uint16_t MPU6050_getFIFOCount() {
+    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_FIFO_COUNTH, 2, mpu6050.buffer);
+    return (((uint16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+}
+
+// FIFO_R_W register
+
+/** Get byte from FIFO mpu6050.buffer.
+ * This register is used to read and write data from the FIFO mpu6050.buffer. Data is
+ * written to the FIFO in order of register number (from lowest to highest). If
+ * all the FIFO enable flags (see below) are enabled and all External Sensor
+ * Data registers (Registers 73 to 96) are associated with a Slave device, the
+ * contents of registers 59 through 96 will be written in order at the Sample
+ * Rate.
+ *
+ * The contents of the sensor data registers (Registers 59 to 96) are written
+ * into the FIFO mpu6050.buffer when their corresponding FIFO enable flags are set to 1
+ * in FIFO_EN (Register 35). An additional flag for the sensor data registers
+ * associated with I2C Slave 3 can be found in I2C_MST_CTRL (Register 36).
+ *
+ * If the FIFO mpu6050.buffer has overflowed, the status bit FIFO_OFLOW_INT is
+ * automatically set to 1. This bit is located in INT_STATUS (Register 58).
+ * When the FIFO mpu6050.buffer has overflowed, the oldest data will be lost and new
+ * data will be written to the FIFO.
+ *
+ * If the FIFO mpu6050.buffer is empty, reading this register will return the last byte
+ * that was previously read from the FIFO until new data is available. The user
+ * should check FIFO_COUNT to ensure that the FIFO mpu6050.buffer is not read when
+ * empty.
+ *
+ * @return Byte from FIFO mpu6050.buffer
+ */
+uint8_t MPU6050_getFIFOByte() {
+    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_FIFO_R_W, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_getFIFOBytes(uint8_t *data, uint8_t length) {
+    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_FIFO_R_W, length, data);
+}
+/** Write byte to FIFO mpu6050.buffer.
+ * @see getFIFOByte()
+ * @see MPU6050_RA_FIFO_R_W
+ */
+void MPU6050_setFIFOByte(uint8_t data) {
+    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_FIFO_R_W, data);
+}
+
+// WHO_AM_I register
+
+/** Get Device ID.
+ * This register is used to verify the identity of the device (0b110100, 0x34).
+ * @return Device ID (6 bits only! should be 0x34)
+ * @see MPU6050_RA_WHO_AM_I
+ * @see MPU6050_WHO_AM_I_BIT
+ * @see MPU6050_WHO_AM_I_LENGTH
+ */
+uint8_t MPU6050_getDeviceID() {
+    I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_WHO_AM_I, MPU6050_WHO_AM_I_BIT, MPU6050_WHO_AM_I_LENGTH, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+/** Set Device ID.
+ * Write a new ID into the WHO_AM_I register (no idea why this should ever be
+ * necessary though).
+ * @param id New device ID to set.
+ * @see getDeviceID()
+ * @see MPU6050_RA_WHO_AM_I
+ * @see MPU6050_WHO_AM_I_BIT
+ * @see MPU6050_WHO_AM_I_LENGTH
+ */
+void MPU6050_setDeviceID(uint8_t id) {
+    I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_WHO_AM_I, MPU6050_WHO_AM_I_BIT, MPU6050_WHO_AM_I_LENGTH, id);
+}
+
+// ======== UNDOCUMENTED/DMP REGISTERS/METHODS ========
+
+// XG_OFFS_TC register
+
+uint8_t MPU6050_getOTPBankValid() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OTP_BNK_VLD_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setOTPBankValid(bool enabled) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OTP_BNK_VLD_BIT, enabled);
+}
+int8_t MPU6050_getXGyroOffsetTC() {
+    I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setXGyroOffsetTC(int8_t offset) {
+    I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset);
+}
+
+// YG_OFFS_TC register
+
+int8_t MPU6050_getYGyroOffsetTC() {
+    I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setYGyroOffsetTC(int8_t offset) {
+    I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset);
+}
+
+// ZG_OFFS_TC register
+
+int8_t MPU6050_getZGyroOffsetTC() {
+    I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_ZG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setZGyroOffsetTC(int8_t offset) {
+    I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_ZG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset);
+}
+
+// X_FINE_GAIN register
+
+int8_t MPU6050_getXFineGain() {
+    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_X_FINE_GAIN, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setXFineGain(int8_t gain) {
+    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_X_FINE_GAIN, gain);
+}
+
+// Y_FINE_GAIN register
+
+int8_t MPU6050_getYFineGain() {
+    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_Y_FINE_GAIN, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setYFineGain(int8_t gain) {
+    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_Y_FINE_GAIN, gain);
+}
+
+// Z_FINE_GAIN register
+
+int8_t MPU6050_getZFineGain() {
+    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_Z_FINE_GAIN, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setZFineGain(int8_t gain) {
+    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_Z_FINE_GAIN, gain);
+}
+
+// XA_OFFS_* registers
+
+int16_t MPU6050_getXAccelOffset() {
+    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_XA_OFFS_H, 2, mpu6050.buffer);
+    return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+}
+void MPU6050_setXAccelOffset(int16_t offset) {
+    I2Cdev_writeWord(mpu6050.devAddr, MPU6050_RA_XA_OFFS_H, offset);
+}
+
+// YA_OFFS_* register
+
+int16_t MPU6050_getYAccelOffset() {
+    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_YA_OFFS_H, 2, mpu6050.buffer);
+    return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+}
+void MPU6050_setYAccelOffset(int16_t offset) {
+    I2Cdev_writeWord(mpu6050.devAddr, MPU6050_RA_YA_OFFS_H, offset);
+}
+
+// ZA_OFFS_* register
+
+int16_t MPU6050_getZAccelOffset() {
+    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ZA_OFFS_H, 2, mpu6050.buffer);
+    return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+}
+void MPU6050_setZAccelOffset(int16_t offset) {
+    I2Cdev_writeWord(mpu6050.devAddr, MPU6050_RA_ZA_OFFS_H, offset);
+}
+
+// XG_OFFS_USR* registers
+
+int16_t MPU6050_getXGyroOffset() {
+    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_XG_OFFS_USRH, 2, mpu6050.buffer);
+    return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+}
+void MPU6050_setXGyroOffset(int16_t offset) {
+    I2Cdev_writeWord(mpu6050.devAddr, MPU6050_RA_XG_OFFS_USRH, offset);
+}
+
+// YG_OFFS_USR* register
+
+int16_t MPU6050_getYGyroOffset() {
+    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_YG_OFFS_USRH, 2, mpu6050.buffer);
+    return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+}
+void MPU6050_setYGyroOffset(int16_t offset) {
+    I2Cdev_writeWord(mpu6050.devAddr, MPU6050_RA_YG_OFFS_USRH, offset);
+}
+
+// ZG_OFFS_USR* register
+
+int16_t MPU6050_getZGyroOffset() {
+    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ZG_OFFS_USRH, 2, mpu6050.buffer);
+    return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
+}
+void MPU6050_setZGyroOffset(int16_t offset) {
+    I2Cdev_writeWord(mpu6050.devAddr, MPU6050_RA_ZG_OFFS_USRH, offset);
+}
+
+// INT_ENABLE register (DMP functions)
+
+bool MPU6050_getIntPLLReadyEnabled() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setIntPLLReadyEnabled(bool enabled) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, enabled);
+}
+bool MPU6050_getIntDMPEnabled() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DMP_INT_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setIntDMPEnabled(bool enabled) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DMP_INT_BIT, enabled);
+}
+
+// DMP_INT_STATUS
+
+bool MPU6050_getDMPInt5Status() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_5_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+bool MPU6050_getDMPInt4Status() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_4_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+bool MPU6050_getDMPInt3Status() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_3_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+bool MPU6050_getDMPInt2Status() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_2_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+bool MPU6050_getDMPInt1Status() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_1_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+bool MPU6050_getDMPInt0Status() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_0_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+
+// INT_STATUS register (DMP functions)
+
+bool MPU6050_getIntPLLReadyStatus() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+bool MPU6050_getIntDMPStatus() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_DMP_INT_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+
+// USER_CTRL register (DMP functions)
+
+bool MPU6050_getDMPEnabled() {
+    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_EN_BIT, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setDMPEnabled(bool enabled) {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_EN_BIT, enabled);
+}
+void MPU6050_resetDMP() {
+    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_RESET_BIT, true);
+}
+
+// BANK_SEL register
+
+void MPU6050_setMemoryBank(uint8_t bank, bool prefetchEnabled, bool userBank) {
+    bank &= 0x1F;
+    if (userBank) bank |= 0x20;
+    if (prefetchEnabled) bank |= 0x40;
+    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_BANK_SEL, bank);
+}
+
+// MEM_START_ADDR register
+
+void MPU6050_setMemoryStartAddress(uint8_t address) {
+    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_MEM_START_ADDR, address);
+}
+
+// MEM_R_W register
+
+uint8_t MPU6050_readMemoryByte() {
+    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_MEM_R_W, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_writeMemoryByte(uint8_t data) {
+    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_MEM_R_W, data);
+}
+void MPU6050_readMemoryBlock(uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address) {
+    MPU6050_setMemoryBank(bank, false, false);
+    MPU6050_setMemoryStartAddress(address);
+    uint8_t chunkSize;
+    for (uint16_t i = 0; i < dataSize;) {
+        // determine correct chunk size according to bank position and data size
+        chunkSize = MPU6050_DMP_MEMORY_CHUNK_SIZE;
+
+        // make sure we don't go past the data size
+        if (i + chunkSize > dataSize) chunkSize = dataSize - i;
+
+        // make sure this chunk doesn't go past the bank boundary (256 bytes)
+        if (chunkSize > 256 - address) chunkSize = 256 - address;
+
+        // read the chunk of data as specified
+        I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_MEM_R_W, chunkSize, data + i);
+        
+        // increase byte index by [chunkSize]
+        i += chunkSize;
+
+        // uint8_t automatically wraps to 0 at 256
+        address += chunkSize;
+
+        // if we aren't done, update bank (if necessary) and address
+        if (i < dataSize) {
+            if (address == 0) bank++;
+            MPU6050_setMemoryBank(bank, false, false);
+            MPU6050_setMemoryStartAddress(address);
+        }
+    }
+}
+/*bool MPU6050_writeMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address, bool verify, bool useProgMem) {
+    MPU6050_setMemoryBank(bank, false, false);
+    MPU6050_setMemoryStartAddress(address);
+    uint8_t chunkSize;
+    uint8_t *verifyBuffer;
+    uint8_t *progBuffer;
+    uint16_t i;
+    uint8_t j;
+    if (verify) verifyBuffer = (uint8_t *)malloc(MPU6050_DMP_MEMORY_CHUNK_SIZE);
+    if (useProgMem) progBuffer = (uint8_t *)malloc(MPU6050_DMP_MEMORY_CHUNK_SIZE);
+    for (i = 0; i < dataSize;) {
+        // determine correct chunk size according to bank position and data size
+        chunkSize = MPU6050_DMP_MEMORY_CHUNK_SIZE;
+
+        // make sure we don't go past the data size
+        if (i + chunkSize > dataSize) chunkSize = dataSize - i;
+
+        // make sure this chunk doesn't go past the bank boundary (256 bytes)
+        if (chunkSize > 256 - address) chunkSize = 256 - address;
+        
+        if (useProgMem) {
+            // write the chunk of data as specified
+            for (j = 0; j < chunkSize; j++) progBuffer[j] = pgm_read_byte(data + i + j);
+        } else {
+            // write the chunk of data as specified
+            progBuffer = (uint8_t *)data + i;
+        }
+
+        I2Cdev_writeBytes(mpu6050.devAddr, MPU6050_RA_MEM_R_W, chunkSize, progBuffer);
+
+        // verify data if needed
+        if (verify && verifyBuffer) {
+            MPU6050_setMemoryBank(bank, false, false);
+            MPU6050_setMemoryStartAddress(address);
+            I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_MEM_R_W, chunkSize, verifyBuffer);
+            if (memcmp(progBuffer, verifyBuffer, chunkSize) != 0) {
+                //Serial.print("Block write verification error, bank ");
+                //Serial.print(bank, DEC);
+                //Serial.print(", address ");
+                //Serial.print(address, DEC);
+                //Serial.print("!\nExpected:");
+                //for (j = 0; j < chunkSize; j++) {
+                //    Serial.print(" 0x");
+                //    if (progBuffer[j] < 16) Serial.print("0");
+                //    Serial.print(progBuffer[j], HEX);
+                //}
+                //Serial.print("\nReceived:");
+                //for (uint8_t j = 0; j < chunkSize; j++) {
+                //    Serial.print(" 0x");
+                //    if (verifyBuffer[i + j] < 16) Serial.print("0");
+                //    Serial.print(verifyBuffer[i + j], HEX);
+                //}
+                Serial.print("\n");
+                free(verifyBuffer);
+                if (useProgMem) free(progBuffer);
+                return false; // uh oh.
+            }
+        }
+
+        // increase byte index by [chunkSize]
+        i += chunkSize;
+
+        // uint8_t automatically wraps to 0 at 256
+        address += chunkSize;
+
+        // if we aren't done, update bank (if necessary) and address
+        if (i < dataSize) {
+            if (address == 0) bank++;
+            MPU6050_setMemoryBank(bank, false, false);
+            MPU6050_setMemoryStartAddress(address);
+        }
+    }
+    if (verify) free(verifyBuffer);
+    if (useProgMem) free(progBuffer);
+    return true;
+}
+bool MPU6050_writeProgMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address, bool verify) {
+    return MPU6050_writeMemoryBlock(data, dataSize, bank, address, verify, true);
+}
+bool MPU6050_writeDMPConfigurationSet(const uint8_t *data, uint16_t dataSize, bool useProgMem) {
+    uint8_t *progBuffer, success, special;
+    uint16_t i, j;
+    if (useProgMem) {
+        progBuffer = (uint8_t *)malloc(8); // assume 8-byte blocks, realloc later if necessary
+    }
+
+    // config set data is a long string of blocks with the following structure:
+    // [bank] [offset] [length] [byte[0], byte[1], ..., byte[length]]
+    uint8_t bank, offset, length;
+    for (i = 0; i < dataSize;) {
+        if (useProgMem) {
+            bank = pgm_read_byte(data + i++);
+            offset = pgm_read_byte(data + i++);
+            length = pgm_read_byte(data + i++);
+        } else {
+            bank = data[i++];
+            offset = data[i++];
+            length = data[i++];
+        }
+
+        // write data or perform special action
+        if (length > 0) {
+            // regular block of data to write
+            //Serial.print("Writing config block to bank ");
+            //Serial.print(bank);
+            //Serial.print(", offset ");
+            //Serial.print(offset);
+            //Serial.print(", length=");
+            //Serial.println(length);
+            if (useProgMem) {
+                if (sizeof(progBuffer) < length) progBuffer = (uint8_t *)realloc(progBuffer, length);
+                for (j = 0; j < length; j++) progBuffer[j] = pgm_read_byte(data + i + j);
+            } else {
+                progBuffer = (uint8_t *)data + i;
+            }
+            success = MPU6050_writeMemoryBlock(progBuffer, length, bank, offset, true);
+            i += length;
+        } else {
+            // special instruction
+            // NOTE: this kind of behavior (what and when to do certain things)
+            // is totally undocumented. This code is in here based on observed
+            // behavior only, and exactly why (or even whether) it has to be here
+            // is anybody's guess for now.
+            if (useProgMem) {
+                special = pgm_read_byte(data + i++);
+            } else {
+                special = data[i++];
+            }
+            //Serial.print("Special command code ");
+            //Serial.print(special, HEX);
+            //Serial.println(" found...");
+            if (special == 0x01) {
+                // enable DMP-related interrupts
+                
+                //setIntZeroMotionEnabled(true);
+                //setIntFIFOBufferOverflowEnabled(true);
+                //setIntDMPEnabled(true);
+                I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, 0x32);  // single operation
+
+                success = true;
+            } else {
+                // unknown special command
+                success = false;
+            }
+        }
+        
+        if (!success) {
+            if (useProgMem) free(progBuffer);
+            return false; // uh oh
+        }
+    }
+    if (useProgMem) free(progBuffer);
+    return true;
+}
+bool MPU6050_writeProgDMPConfigurationSet(const uint8_t *data, uint16_t dataSize) {
+    return MPU6050_writeDMPConfigurationSet(data, dataSize, true);
+}*/
+
+// DMP_CFG_1 register
+
+uint8_t MPU6050_getDMPConfig1() {
+    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_DMP_CFG_1, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setDMPConfig1(uint8_t config) {
+    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_DMP_CFG_1, config);
+}
+
+// DMP_CFG_2 register
+
+uint8_t MPU6050_getDMPConfig2() {
+    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_DMP_CFG_2, mpu6050.buffer);
+    return mpu6050.buffer[0];
+}
+void MPU6050_setDMPConfig2(uint8_t config) {
+    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_DMP_CFG_2, config);
+}
\ No newline at end of file
diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050_example_main.c b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050_example_main.c
index 8117bd5f..34064fec 100644
--- a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050_example_main.c
+++ b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050_example_main.c
@@ -11,7 +11,7 @@
 // 'C' source line config statements
 
 // FOSC
-#pragma config FOSFPR = XT_PLL8         // Oscillator (XT w/PLL 8x)
+#pragma config FOSFPR = XT_PLL8        // Oscillator (XT w/PLL 8x)
 #pragma config FCKSMEN = CSW_FSCM_OFF   // Clock Switching and Monitor (Sw Disabled, Mon Disabled)
 
 // FWDT
@@ -62,7 +62,16 @@ void __attribute__((__interrupt__)) _U2TXInterrupt(void)
 
 int main(void)
 {
+    TRISCbits.TRISC14 = 0;
+    LATCbits.LATC14 = 1;
+            
+    while(1){
     /* Data to be transmitted using UART communication module */
+        //TRISFbits.TRISF3 = 0;
+        //PORTFbits.RF3 = 0;
+        //delay_ms(10);
+        //PORTFbits.RF3 = 1;
+        TRISFbits.TRISF3 = 1;
     char Buffer[80];
     //char 
     /* Holds the value of baud register   */
@@ -72,7 +81,7 @@ int main(void)
     /* Holds the information regarding uart
     TX & RX interrupt modes */   
     unsigned int U2STAvalue;
-    
+    CloseI2C();
     /* Turn off UART1module */
     CloseUART2();
     /* Configure uart1 transmit interrupt */
@@ -89,12 +98,12 @@ int main(void)
                   UART_ADR_DETECT_DIS &
                   UART_RX_OVERRUN_CLEAR;
     unsigned int I2C_config1,I2C_config2;
-    I2C_config1 = (I2C_ON & I2C_IDLE_CON & I2C_CLK_HLD &
+    I2C_config1 = (I2C_ON & I2C_IDLE_CON & I2C_CLK_REL &
              I2C_IPMI_DIS & I2C_7BIT_ADD &
-             I2C_SLW_DIS & I2C_SM_DIS &
+             I2C_SLW_EN & I2C_SM_DIS &
              I2C_GCALL_DIS & I2C_STR_DIS &
              I2C_ACK & I2C_ACK_EN & I2C_RCV_EN &
-             I2C_STOP_DIS & I2C_RESTART_DIS &
+             I2C_STOP_DIS & I2C_RESTART_EN &
              I2C_START_DIS);
     I2C_config2 = 181;
     ConfigIntI2C(MI2C_INT_OFF & SI2C_INT_OFF);
@@ -115,17 +124,17 @@ int main(void)
     /* Wait for  transmission to complete */
     while(BusyUART2());
     
-    //sprintf(Buf,MPU6050_testConnection() ? "MPU6050 connection successful\r\n" :
-    //    "MPU6050 connection failed\r\n");
-    //putsUART2 ((unsigned int *)Buf);
+    sprintf(Buf,MPU6050_testConnection() ? "MPU6050 connection successful\r\n" :
+        "MPU6050 connection failed\r\n");
+    putsUART2 ((unsigned int *)Buf);
     /* Wait for  transmission to complete */
-    //while(BusyUART2());
+    while(BusyUART2());
     
     
     
     
     //CloseUART2();
     
-    
+    }
     return 0;
 }
diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Makefile-genesis.properties b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Makefile-genesis.properties
index a8765e5f..a5eb6e5c 100644
--- a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Makefile-genesis.properties
+++ b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Makefile-genesis.properties
@@ -1,5 +1,5 @@
 #
-#Wed Mar 15 15:13:11 CST 2017
+#Tue Apr 04 10:56:56 CST 2017
 default.com-microchip-mplab-nbide-toolchainXC16-XC16LanguageToolchain.md5=ebaa75370c1463d650408e4144ba15de
 default.languagetoolchain.dir=/opt/microchip/xc16/v1.30/bin
 configurations-xml=390e761992510ba6b77d8cf6d2379168

From 86c4e0e7128da03a11328514520ecf7039ce6e4c Mon Sep 17 00:00:00 2001
From: Daichou 
Date: Wed, 5 Apr 2017 00:02:52 +0800
Subject: [PATCH 171/335] Fix I2C Read Sequence extra unused byte transmission
 error Due to extra unused byte transmission in the Read Sequence,causing I2C
 cannot successfully pass test_connection function.

Bug discription:

Predicted Reading Sequence
Master   |S|AD+W|   |RA|   |S|AD+R|   |    |NACK|P|
Slave    | |    |ACK|  |ACK| |    |ACK|DATA|    | |

But,in the second Start condition,original code could cause extra byte(because using RestartI2C() function).
Using StopI2C() and then StartI2C() can fix this error
---
 .../nbproject/Makefile-genesis.properties     |   2 +-
 .../Examples/MPU6050_example.X/I2Cdev.c       |  43 ++--
 .../Examples/MPU6050_example.X/MPU6050.c      |  15 +-
 .../MPU6050_example.X/MPU6050_example_main.c  | 220 ++++++++++++------
 .../nbproject/Makefile-genesis.properties     |   2 +-
 5 files changed, 184 insertions(+), 98 deletions(-)

diff --git a/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-genesis.properties b/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-genesis.properties
index 249d7262..d1044901 100644
--- a/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-genesis.properties
+++ b/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-genesis.properties
@@ -1,5 +1,5 @@
 #
-#Tue Apr 04 10:56:56 CST 2017
+#Tue Apr 04 21:56:23 CST 2017
 default.com-microchip-mplab-nbide-toolchainXC16-XC16LanguageToolchain.md5=ebaa75370c1463d650408e4144ba15de
 default.languagetoolchain.dir=/opt/microchip/xc16/v1.30/bin
 configurations-xml=e23099a44127c530cab293bfc5554ec5
diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/I2Cdev.c b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/I2Cdev.c
index 27909fee..a51d9766 100644
--- a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/I2Cdev.c
+++ b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/I2Cdev.c
@@ -101,7 +101,7 @@ int8_t I2Cdev_readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_
     while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
     IFS0bits.MI2CIF = 0;     // Clear interrupt flag
     //while(I2CSTATbits.ACKSTAT);
-    //delay_ms_I2C(10);
+    //delay_us_I2C(100);
     /*Master send RA*/
     /* Write Register Address */
     MasterWriteI2C(regAddr);
@@ -114,15 +114,22 @@ int8_t I2Cdev_readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_
     IFS0bits.MI2CIF = 0;     // Clear interrupt flag
     while(I2CSTATbits.ACKSTAT);
 
-    //delay_ms_I2C(10);
+    //delay_us_I2C(100);
+    
+    /*Master Pause*/
+    StopI2C();
+    /* Wait till stop sequence is completed */
+    while(I2CCONbits.PEN);
+    
     /*Master Start*/
-    RestartI2C();
+    StartI2C();
     /* Wait till Start sequence is completed */
     while(I2CCONbits.SEN);
 
     /*Master send AD+R*/
     /* Write Slave Address (Read)*/
     MasterWriteI2C(devAddr << 1 | 0x01);
+    //while(!MasterWriteI2C(devAddr << 1 | 0x01));
     /* Wait until address is transmitted */
     while(I2CSTATbits.TBF);  // 8 clock cycles
 
@@ -130,12 +137,13 @@ int8_t I2Cdev_readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_
     while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
     IFS0bits.MI2CIF = 0;     // Clear interrupt flag
     while(I2CSTATbits.ACKSTAT);
-    //delay_ms_I2C(10);
+    //delay_us_I2C(100);
 
     /*Slave send DATA*/
     //uint16_t flag = MastergetsI2C(length,data,I2C_DATA_WAIT);
 
     /*Slave send NACK*/
+    //MastergetsI2C(length,data,100);
     //NotAckI2C();
 
     data[0] = MasterReadI2C();
@@ -143,7 +151,6 @@ int8_t I2Cdev_readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_
     for (i = 1 ; i < length ; i++ ){
         AckI2C();
         while(I2CCONbits.ACKEN == 1);
-		//delay_ms_I2C(10);
         data[i] = MasterReadI2C();
     }
     NotAckI2C();
@@ -153,8 +160,8 @@ int8_t I2Cdev_readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_
     /* Wait till stop sequence is completed */
     while(I2CCONbits.PEN);
     //CloseI2C();
-    IdleI2C();
-    return true;
+    //IdleI2C();
+    return length;
 }
 
 /** Read single byte from an 8-bit device register.
@@ -290,7 +297,6 @@ bool I2Cdev_writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t
     while(I2CCONbits.SEN);
     /* Clear interrupt flag */
     IFS0bits.MI2CIF = 0;
-    //delay_ms_I2C(10);
 
     /*Master send AD+W*/
     /* Write Slave address (Write)*/
@@ -302,7 +308,7 @@ bool I2Cdev_writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t
     while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
     IFS0bits.MI2CIF = 0;     // Clear interrupt flag
     while(I2CSTATbits.ACKSTAT);
-    //delay_ms_I2C(10);
+    //delay_us_I2C(100);
 
     /*Master send RA*/
     /* Write Slave address (Write)*/
@@ -313,20 +319,31 @@ bool I2Cdev_writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t
     /*Slave send ACK*/
     while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
     IFS0bits.MI2CIF = 0;     // Clear interrupt flag
-    //delay_ms_I2C(10);
+    //delay_us_I2C(100);
     while(I2CSTATbits.ACKSTAT);
 
     /*Master send data*/
     /* Transmit string of data */
     MasterputsI2C(data);
+    //uint8_t i;
+    //for (i = 0 ; i < length ; i++){
+    //    MasterWriteI2C(data[i]);
+        /* Wait till address is transmitted */
+    //    while(I2CSTATbits.TBF);  // 8 clock cycles
+
+        /*Slave send ACK*/
+    //    while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
+    //    IFS0bits.MI2CIF = 0;     // Clear interrupt flag
+        //delay_us_I2C(100);
+    //}
     while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
     IFS0bits.MI2CIF = 0;     // Clear interrupt flag
-
+    
     StopI2C();
     /* Wait till stop sequence is completed */
     while(I2CCONbits.PEN);
     //CloseI2C();
-    IdleI2C();
+    //IdleI2C();
     return true;
 }
 
@@ -419,7 +436,7 @@ bool I2Cdev_writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_
         data &= mask; // zero all non-important bits in data
         b &= ~(mask); // zero all important bits in existing byte
         b |= data; // combine data with existing byte
-        delay_ms_I2C(10);
+        //delay_ms_I2C(10);
 		return I2Cdev_writeByte(devAddr, regAddr, b);
     } else {
         return false;
diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050.c b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050.c
index fb0abb47..bb31b001 100644
--- a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050.c
+++ b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050.c
@@ -90,17 +90,10 @@ void MPU6050(uint8_t address)
  */
 void MPU6050_initialize()
 {
-
-
-	MPU6050_setSleepEnabled(
-	    false); // thanks to Jack Elston for pointing this one out!
-	delay_ms(20);
-	MPU6050_setClockSource(MPU6050_CLOCK_PLL_XGYRO);
-	delay_ms(20);
-	MPU6050_setFullScaleAccelRange(MPU6050_ACCEL_FS_2);
-	delay_ms(20);
-	MPU6050_setFullScaleGyroRange(MPU6050_GYRO_FS_250);
-    delay_ms(100);
+    MPU6050_setClockSource(MPU6050_CLOCK_PLL_XGYRO);                                                                    
+    MPU6050_setFullScaleGyroRange(MPU6050_GYRO_FS_250);                                                                 
+    MPU6050_setFullScaleAccelRange(MPU6050_ACCEL_FS_2);                                                                 
+    MPU6050_setSleepEnabled(false);
 }
 
 /** Verify the I2C connection.
diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050_example_main.c b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050_example_main.c
index 34064fec..3bab9908 100644
--- a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050_example_main.c
+++ b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050_example_main.c
@@ -6,12 +6,13 @@
  */
 
 
+
 // DSPIC30F4013 Configuration Bit Settings
 
 // 'C' source line config statements
 
 // FOSC
-#pragma config FOSFPR = XT_PLL8        // Oscillator (XT w/PLL 8x)
+#pragma config FOSFPR = ECIO_PLL8       // Oscillator (ECIO w/PLL 8x)
 #pragma config FCKSMEN = CSW_FSCM_OFF   // Clock Switching and Monitor (Sw Disabled, Mon Disabled)
 
 // FWDT
@@ -20,7 +21,7 @@
 #pragma config WDT = WDT_OFF            // Watchdog Timer (Disabled)
 
 // FBORPOR
-#pragma config FPWRT = PWRT_64          // POR Timer Value (64ms)
+#pragma config FPWRT = PWRT_OFF         // POR Timer Value (Timer Disabled)
 #pragma config BODENV = BORV20          // Brown Out Voltage (Reserved)
 #pragma config BOREN = PBOR_OFF         // PBOR Enable (Disabled)
 #pragma config MCLRE = MCLR_EN          // Master Clear Enable (Enabled)
@@ -35,7 +36,10 @@
 // #pragma config statements should precede project file includes.
 // Use project enums instead of #define for ON and OFF.
 
-#include
+#include 
+
+
+
 #include
 #include
 #include
@@ -44,6 +48,7 @@
 /* Received data is stored in array Buf  */
 char Buf[80];
 char* Receivedddata = Buf;
+int16_t ax, ay, az, gx, gy, gz;
 /* This is UART1 transmit ISR */
 void __attribute__((__interrupt__)) _U2TXInterrupt(void)
 {  
@@ -62,79 +67,150 @@ void __attribute__((__interrupt__)) _U2TXInterrupt(void)
 
 int main(void)
 {
+    delay_ms(1000);
     TRISCbits.TRISC14 = 0;
     LATCbits.LATC14 = 1;
             
     while(1){
-    /* Data to be transmitted using UART communication module */
-        //TRISFbits.TRISF3 = 0;
-        //PORTFbits.RF3 = 0;
-        //delay_ms(10);
-        //PORTFbits.RF3 = 1;
-        TRISFbits.TRISF3 = 1;
-    char Buffer[80];
-    //char 
-    /* Holds the value of baud register   */
-    unsigned int baudvalue;   
-    /* Holds the value of uart config reg */
-    unsigned int U2MODEvalue;
-    /* Holds the information regarding uart
-    TX & RX interrupt modes */   
-    unsigned int U2STAvalue;
-    CloseI2C();
-    /* Turn off UART1module */
-    CloseUART2();
-    /* Configure uart1 transmit interrupt */
-    ConfigIntUART2(  UART_TX_INT_DIS & UART_TX_INT_PR2);
-    /* Configure UART1 module to transmit 8 bit data with one stopbit. Also Enable loopback mode  */
-    baudvalue = 129;  //9600
-    U2MODEvalue = UART_EN & UART_IDLE_CON & 
-                  UART_DIS_WAKE & UART_DIS_LOOPBACK  &
-                  UART_EN_ABAUD & UART_NO_PAR_8BIT  &
-                  UART_1STOPBIT;
-    U2STAvalue  = UART_INT_TX_BUF_EMPTY  &  
-                  UART_TX_PIN_NORMAL &
-                  UART_TX_ENABLE & UART_INT_RX_3_4_FUL &
-                  UART_ADR_DETECT_DIS &
-                  UART_RX_OVERRUN_CLEAR;
-    unsigned int I2C_config1,I2C_config2;
-    I2C_config1 = (I2C_ON & I2C_IDLE_CON & I2C_CLK_REL &
-             I2C_IPMI_DIS & I2C_7BIT_ADD &
-             I2C_SLW_EN & I2C_SM_DIS &
-             I2C_GCALL_DIS & I2C_STR_DIS &
-             I2C_ACK & I2C_ACK_EN & I2C_RCV_EN &
-             I2C_STOP_DIS & I2C_RESTART_EN &
-             I2C_START_DIS);
-    I2C_config2 = 181;
-    ConfigIntI2C(MI2C_INT_OFF & SI2C_INT_OFF);
-    OpenI2C(I2C_config1,I2C_config2);
-    OpenUART2(U2MODEvalue, U2STAvalue, baudvalue);
-    
-    MPU6050(MPU6050_ADDRESS_AD0_LOW);
-    sprintf(Buf,"Initialize MPU6050\n\0");
-    /* Load transmit buffer and transmit the same till null character is encountered */
-    putsUART2 ((unsigned int *)Buf);
-    /* Wait for  transmission to complete */
-    while(BusyUART2());
-    
-    MPU6050_initialize();
-
-    sprintf(Buf,"Testing device connections...\n\0");
-    putsUART2 ((unsigned int *)Buf);
-    /* Wait for  transmission to complete */
-    while(BusyUART2());
-    
-    sprintf(Buf,MPU6050_testConnection() ? "MPU6050 connection successful\r\n" :
-        "MPU6050 connection failed\r\n");
-    putsUART2 ((unsigned int *)Buf);
-    /* Wait for  transmission to complete */
-    while(BusyUART2());
-    
-    
-    
-    
-    //CloseUART2();
-    
+    HEAD:
+        /* Data to be transmitted using UART communication module */
+            //TRISFbits.TRISF3 = 0;
+            //PORTFbits.RF3 = 0;
+            //delay_ms(10);
+            //PORTFbits.RF3 = 1;
+        TRISFbits.TRISF3 = 0;
+        TRISFbits.TRISF2 = 0;
+        char Buffer[80];
+        //char 
+        /* Holds the value of baud register   */
+        unsigned int baudvalue;   
+        /* Holds the value of uart config reg */
+        unsigned int U2MODEvalue;
+        /* Holds the information regarding uart
+        TX & RX interrupt modes */   
+        unsigned int U2STAvalue;
+        CloseI2C();
+        /* Turn off UART1module */
+        CloseUART2();
+        /* Configure uart1 transmit interrupt */
+        ConfigIntUART2(  UART_TX_INT_DIS & UART_TX_INT_PR2);
+        /* Configure UART1 module to transmit 8 bit data with one stopbit. Also Enable loopback mode  */
+        baudvalue = 129;  //9600
+        U2MODEvalue = UART_EN & UART_IDLE_CON & 
+                      UART_DIS_WAKE & UART_DIS_LOOPBACK  &
+                      UART_EN_ABAUD & UART_NO_PAR_8BIT  &
+                      UART_1STOPBIT;
+        U2STAvalue  = UART_INT_TX_BUF_EMPTY  &  
+                      UART_TX_PIN_NORMAL &
+                      UART_TX_ENABLE & UART_INT_RX_3_4_FUL &
+                      UART_ADR_DETECT_DIS &
+                      UART_RX_OVERRUN_CLEAR;
+        unsigned int I2C_config1,I2C_config2;
+        I2C_config1 = (I2C_ON & I2C_IDLE_CON & I2C_CLK_REL &
+                 I2C_IPMI_DIS & I2C_7BIT_ADD &
+                 I2C_SLW_DIS & I2C_SM_DIS &
+                 I2C_GCALL_DIS & I2C_STR_EN &
+                 I2C_ACK & I2C_ACK_EN & I2C_RCV_EN &
+                 I2C_STOP_DIS & I2C_RESTART_EN &
+                 I2C_START_DIS);
+        I2C_config2 = 381;
+        ConfigIntI2C(MI2C_INT_OFF & SI2C_INT_OFF);
+        OpenI2C(I2C_config1,I2C_config2);
+        OpenUART2(U2MODEvalue, U2STAvalue, baudvalue);
+
+        MPU6050(MPU6050_ADDRESS_AD0_LOW);
+        sprintf(Buf,"Initialize MPU6050\n\0");
+        /* Load transmit buffer and transmit the same till null character is encountered */
+        putsUART2 ((unsigned int *)Buf);
+        /* Wait for  transmission to complete */
+        while(BusyUART2());
+        //MPU6050_reset();
+        //delay_ms(100);
+        //MPU6050_resetGyroscopePath();
+        //MPU6050_resetAccelerometerPath();
+        //MPU6050_resetTemperaturePath();
+        //delay_ms(100);
+        MPU6050_initialize();
+        MPU6050_setSleepEnabled(false);
+        unsigned char MPU6050_ID = MPU6050_getDeviceID();
+        
+        sprintf(Buf,"Testing device connections...\n\0");
+        putsUART2 ((unsigned int *)Buf);
+        /* Wait for  transmission to complete */
+        while(BusyUART2());
+
+        
+
+        sprintf(Buf,"MPU6050_ID = 0x%X\n",MPU6050_ID);
+        putsUART2 ((unsigned int *)Buf);
+        /* Wait for  transmission to complete */
+        while(BusyUART2());
+
+
+        sprintf(Buf,MPU6050_testConnection() ? "MPU6050 connection successful\r\n" :
+            "MPU6050 connection failed\r\n");
+        putsUART2 ((unsigned int *)Buf);
+        /* Wait for  transmission to complete */
+        while(BusyUART2());
+        
+        if (!MPU6050_testConnection())
+            goto HEAD;
+        
+        sprintf(Buf,"Reading offset\n");
+        putsUART2 ((unsigned int *)Buf);
+        /* Wait for  transmission to complete */
+        while(BusyUART2());
+
+        sprintf(Buf,"Xaccel= %d\n",MPU6050_getXAccelOffset());
+        putsUART2 ((unsigned int *)Buf);
+        /* Wait for  transmission to complete */
+        while(BusyUART2());
+
+        sprintf(Buf,"Yaccel= %d\n",MPU6050_getYAccelOffset());
+        putsUART2 ((unsigned int *)Buf);
+        /* Wait for  transmission to complete */
+        while(BusyUART2());
+        
+        sprintf(Buf,"Zaccel= %d\n",MPU6050_getZAccelOffset());
+        putsUART2 ((unsigned int *)Buf);
+        /* Wait for  transmission to complete */
+        while(BusyUART2());
+        
+        sprintf(Buf,"Xgyro= %d\n",MPU6050_getXGyroOffset());
+        putsUART2 ((unsigned int *)Buf);
+        /* Wait for  transmission to complete */
+        while(BusyUART2());
+        
+        sprintf(Buf,"Ygyro= %d\n",MPU6050_getYGyroOffset());
+        putsUART2 ((unsigned int *)Buf);
+        /* Wait for  transmission to complete */
+        while(BusyUART2());
+        
+        sprintf(Buf,"Zgyro= %d\n",MPU6050_getZGyroOffset());
+        putsUART2 ((unsigned int *)Buf);
+        /* Wait for  transmission to complete */
+        while(BusyUART2());
+        
+        
+        while (true) {
+           // Read raw accel/gyro measurements from device
+            MPU6050_getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
+
+            // Display tab-separated accel/gyro x/y/z values
+            sprintf(Buf,"a/g:\t%d\t%d\t%d\t%d\t%d\t%d\r\n", ax, ay, az, gx, gy, gz);
+            putsUART2 ((unsigned int *)Buf);
+            /* Wait for  transmission to complete */
+            while(BusyUART2());
+        
+            // Blink LED to indicate activity
+            LATCbits.LATC14 ^= 1;
+
+            delay_ms(25);
+            delay_ms(25);
+        }
+        
+        //CloseUART2();
+
     }
     return 0;
 }
diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Makefile-genesis.properties b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Makefile-genesis.properties
index a5eb6e5c..59fffcfc 100644
--- a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Makefile-genesis.properties
+++ b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Makefile-genesis.properties
@@ -1,5 +1,5 @@
 #
-#Tue Apr 04 10:56:56 CST 2017
+#Tue Apr 04 21:56:22 CST 2017
 default.com-microchip-mplab-nbide-toolchainXC16-XC16LanguageToolchain.md5=ebaa75370c1463d650408e4144ba15de
 default.languagetoolchain.dir=/opt/microchip/xc16/v1.30/bin
 configurations-xml=390e761992510ba6b77d8cf6d2379168

From a57b3365f732fca584a49899bfb63f8f65700d31 Mon Sep 17 00:00:00 2001
From: Daichou 
Date: Wed, 26 Apr 2017 15:17:43 +0800
Subject: [PATCH 172/335] finished i2cdev for dsPIC30F without interrupt

---
 .../nbproject/Makefile-genesis.properties     |  2 +-
 .../Examples/MPU6050_example.X/I2Cdev.c       | 34 +++++------
 .../MPU6050_example.X/MPU6050_example_main.c  | 59 +++++++++++++++++--
 .../nbproject/Makefile-genesis.properties     |  2 +-
 4 files changed, 70 insertions(+), 27 deletions(-)

diff --git a/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-genesis.properties b/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-genesis.properties
index d1044901..da0cb730 100644
--- a/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-genesis.properties
+++ b/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-genesis.properties
@@ -1,5 +1,5 @@
 #
-#Tue Apr 04 21:56:23 CST 2017
+#Wed Apr 26 14:40:24 CST 2017
 default.com-microchip-mplab-nbide-toolchainXC16-XC16LanguageToolchain.md5=ebaa75370c1463d650408e4144ba15de
 default.languagetoolchain.dir=/opt/microchip/xc16/v1.30/bin
 configurations-xml=e23099a44127c530cab293bfc5554ec5
diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/I2Cdev.c b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/I2Cdev.c
index a51d9766..f0d99941 100644
--- a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/I2Cdev.c
+++ b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/I2Cdev.c
@@ -101,7 +101,6 @@ int8_t I2Cdev_readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_
     while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
     IFS0bits.MI2CIF = 0;     // Clear interrupt flag
     //while(I2CSTATbits.ACKSTAT);
-    //delay_us_I2C(100);
     /*Master send RA*/
     /* Write Register Address */
     MasterWriteI2C(regAddr);
@@ -114,8 +113,6 @@ int8_t I2Cdev_readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_
     IFS0bits.MI2CIF = 0;     // Clear interrupt flag
     while(I2CSTATbits.ACKSTAT);
 
-    //delay_us_I2C(100);
-    
     /*Master Pause*/
     StopI2C();
     /* Wait till stop sequence is completed */
@@ -126,10 +123,12 @@ int8_t I2Cdev_readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_
     /* Wait till Start sequence is completed */
     while(I2CCONbits.SEN);
 
+    
+    
     /*Master send AD+R*/
     /* Write Slave Address (Read)*/
     MasterWriteI2C(devAddr << 1 | 0x01);
-    //while(!MasterWriteI2C(devAddr << 1 | 0x01));
+    
     /* Wait until address is transmitted */
     while(I2CSTATbits.TBF);  // 8 clock cycles
 
@@ -137,7 +136,6 @@ int8_t I2Cdev_readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_
     while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
     IFS0bits.MI2CIF = 0;     // Clear interrupt flag
     while(I2CSTATbits.ACKSTAT);
-    //delay_us_I2C(100);
 
     /*Slave send DATA*/
     //uint16_t flag = MastergetsI2C(length,data,I2C_DATA_WAIT);
@@ -286,7 +284,7 @@ int8_t I2Cdev_readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint
  * @return Status of operation (true = success)
  */
 bool I2Cdev_writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t* data) {
-    if (data[length-1] != '\0' && length != 1)return false;
+    //if (data[length-1] != '\0' && length != 1)return false;
 	//OpenI2C(config1,config2);
     IFS0bits.MI2CIF = 0;
     IEC0bits.MI2CIE = 0;
@@ -308,7 +306,6 @@ bool I2Cdev_writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t
     while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
     IFS0bits.MI2CIF = 0;     // Clear interrupt flag
     while(I2CSTATbits.ACKSTAT);
-    //delay_us_I2C(100);
 
     /*Master send RA*/
     /* Write Slave address (Write)*/
@@ -319,25 +316,23 @@ bool I2Cdev_writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t
     /*Slave send ACK*/
     while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
     IFS0bits.MI2CIF = 0;     // Clear interrupt flag
-    //delay_us_I2C(100);
     while(I2CSTATbits.ACKSTAT);
 
     /*Master send data*/
     /* Transmit string of data */
-    MasterputsI2C(data);
-    //uint8_t i;
-    //for (i = 0 ; i < length ; i++){
-    //    MasterWriteI2C(data[i]);
+    //MasterputsI2C(data);
+    uint8_t i;
+    for (i = 0 ; i < length ; i++){
+        MasterWriteI2C(data[i]);
         /* Wait till address is transmitted */
-    //    while(I2CSTATbits.TBF);  // 8 clock cycles
+        while(I2CSTATbits.TBF);  // 8 clock cycles
 
         /*Slave send ACK*/
-    //    while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
-    //    IFS0bits.MI2CIF = 0;     // Clear interrupt flag
-        //delay_us_I2C(100);
-    //}
-    while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
-    IFS0bits.MI2CIF = 0;     // Clear interrupt flag
+        while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
+        IFS0bits.MI2CIF = 0;     // Clear interrupt flag
+    }
+    //while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
+    //IFS0bits.MI2CIF = 0;     // Clear interrupt flag
     
     StopI2C();
     /* Wait till stop sequence is completed */
@@ -436,7 +431,6 @@ bool I2Cdev_writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_
         data &= mask; // zero all non-important bits in data
         b &= ~(mask); // zero all important bits in existing byte
         b |= data; // combine data with existing byte
-        //delay_ms_I2C(10);
 		return I2Cdev_writeByte(devAddr, regAddr, b);
     } else {
         return false;
diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050_example_main.c b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050_example_main.c
index 3bab9908..3bcc2f82 100644
--- a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050_example_main.c
+++ b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050_example_main.c
@@ -12,7 +12,7 @@
 // 'C' source line config statements
 
 // FOSC
-#pragma config FOSFPR = ECIO_PLL8       // Oscillator (ECIO w/PLL 8x)
+#pragma config FOSFPR = ECIO       // Oscillator (ECIO w/PLL 8x)
 #pragma config FCKSMEN = CSW_FSCM_OFF   // Clock Switching and Monitor (Sw Disabled, Mon Disabled)
 
 // FWDT
@@ -67,7 +67,8 @@ void __attribute__((__interrupt__)) _U2TXInterrupt(void)
 
 int main(void)
 {
-    delay_ms(1000);
+    //delay_ms(1000);
+    
     TRISCbits.TRISC14 = 0;
     LATCbits.LATC14 = 1;
             
@@ -95,7 +96,7 @@ int main(void)
         /* Configure uart1 transmit interrupt */
         ConfigIntUART2(  UART_TX_INT_DIS & UART_TX_INT_PR2);
         /* Configure UART1 module to transmit 8 bit data with one stopbit. Also Enable loopback mode  */
-        baudvalue = 129;  //9600
+        baudvalue = 15;//129;  //9600
         U2MODEvalue = UART_EN & UART_IDLE_CON & 
                       UART_DIS_WAKE & UART_DIS_LOOPBACK  &
                       UART_EN_ABAUD & UART_NO_PAR_8BIT  &
@@ -106,7 +107,7 @@ int main(void)
                       UART_ADR_DETECT_DIS &
                       UART_RX_OVERRUN_CLEAR;
         unsigned int I2C_config1,I2C_config2;
-        I2C_config1 = (I2C_ON & I2C_IDLE_CON & I2C_CLK_REL &
+        I2C_config1 = (I2C_ON & I2C_IDLE_CON & I2C_CLK_HLD &
                  I2C_IPMI_DIS & I2C_7BIT_ADD &
                  I2C_SLW_DIS & I2C_SM_DIS &
                  I2C_GCALL_DIS & I2C_STR_EN &
@@ -131,7 +132,7 @@ int main(void)
         //MPU6050_resetTemperaturePath();
         //delay_ms(100);
         MPU6050_initialize();
-        MPU6050_setSleepEnabled(false);
+        
         unsigned char MPU6050_ID = MPU6050_getDeviceID();
         
         sprintf(Buf,"Testing device connections...\n\0");
@@ -191,7 +192,55 @@ int main(void)
         /* Wait for  transmission to complete */
         while(BusyUART2());
         
+        //delay_ms(100);
+        
+        MPU6050_setXGyroOffset(220);
+        
+        //delay_ms(100);
+        
+        MPU6050_setYGyroOffset(76);
+        
+        //delay_ms(100);
+        
+        MPU6050_setZGyroOffset(-85);
+        
+        sprintf(Buf,"Reading Updated offset\n");
+        putsUART2 ((unsigned int *)Buf);
+        /* Wait for  transmission to complete */
+        while(BusyUART2());
+
+        sprintf(Buf,"Xaccel= %d\n",MPU6050_getXAccelOffset());
+        putsUART2 ((unsigned int *)Buf);
+        /* Wait for  transmission to complete */
+        while(BusyUART2());
+
+        sprintf(Buf,"Yaccel= %d\n",MPU6050_getYAccelOffset());
+        putsUART2 ((unsigned int *)Buf);
+        /* Wait for  transmission to complete */
+        while(BusyUART2());
+        
+        sprintf(Buf,"Zaccel= %d\n",MPU6050_getZAccelOffset());
+        putsUART2 ((unsigned int *)Buf);
+        /* Wait for  transmission to complete */
+        while(BusyUART2());
+        
+        sprintf(Buf,"Xgyro= %d\n",MPU6050_getXGyroOffset());
+        putsUART2 ((unsigned int *)Buf);
+        /* Wait for  transmission to complete */
+        while(BusyUART2());
+        
+        sprintf(Buf,"Ygyro= %d\n",MPU6050_getYGyroOffset());
+        putsUART2 ((unsigned int *)Buf);
+        /* Wait for  transmission to complete */
+        while(BusyUART2());
+        
+        sprintf(Buf,"Zgyro= %d\n",MPU6050_getZGyroOffset());
+        putsUART2 ((unsigned int *)Buf);
+        /* Wait for  transmission to complete */
+        while(BusyUART2());
+        
         
+        MPU6050_setSleepEnabled(false);
         while (true) {
            // Read raw accel/gyro measurements from device
             MPU6050_getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Makefile-genesis.properties b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Makefile-genesis.properties
index 59fffcfc..86a933b5 100644
--- a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Makefile-genesis.properties
+++ b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Makefile-genesis.properties
@@ -1,5 +1,5 @@
 #
-#Tue Apr 04 21:56:22 CST 2017
+#Wed Apr 26 14:40:23 CST 2017
 default.com-microchip-mplab-nbide-toolchainXC16-XC16LanguageToolchain.md5=ebaa75370c1463d650408e4144ba15de
 default.languagetoolchain.dir=/opt/microchip/xc16/v1.30/bin
 configurations-xml=390e761992510ba6b77d8cf6d2379168

From 96775668ceb84cb271f5699d3821d0dfd1bc7f4b Mon Sep 17 00:00:00 2001
From: Daichou 
Date: Wed, 26 Apr 2017 16:09:48 +0800
Subject: [PATCH 173/335] coding style correct

---
 dsPIC30F/I2Cdev/I2Cdev.c                      |  217 +-
 dsPIC30F/I2Cdev/I2CdevdsPic30F.X/Makefile     |  113 -
 .../production/_ext/1922997195/I2Cdev.o       |  Bin 22716 -> 0 bytes
 .../production/_ext/1922997195/I2Cdev.o.d     |    3 -
 .../nbproject/Makefile-default.mk             |  155 -
 .../nbproject/Makefile-genesis.properties     |    9 -
 .../nbproject/Makefile-impl.mk                |   69 -
 .../nbproject/Makefile-local-default.mk       |   36 -
 .../nbproject/Makefile-variables.mk           |   13 -
 .../nbproject/Package-default.bash            |   73 -
 .../nbproject/configurations.xml              |  162 -
 .../Examples/MPU6050_example.X/I2Cdev.c       |   33 +-
 .../Examples/MPU6050_example.X/MPU6050.c      |   36 +-
 .../Examples/MPU6050_example.X/MPU6050.c.orig | 3174 -----------------
 .../MPU6050_example.X/MPU6050_example_main.c  |  103 +-
 .../nbproject/Makefile-default.mk             |   10 +-
 .../nbproject/Makefile-genesis.properties     |   12 +-
 .../nbproject/Makefile-local-default.mk       |   24 +-
 .../nbproject/configurations.xml              |  327 +-
 .../MPU6050/Examples/MPU6050_raw.X/Makefile   |  113 -
 .../MPU6050/Examples/MPU6050_raw.X/funclist   |   37 -
 dsPIC30F/MPU6050/Examples/MPU6050_raw.X/l.obj |  Bin 24233 -> 0 bytes
 .../MPU6050/Examples/MPU6050_raw.X/main.c     |  137 -
 .../nbproject/Makefile-default.mk             |  172 -
 .../nbproject/Makefile-genesis.properties     |    8 -
 .../MPU6050_raw.X/nbproject/Makefile-impl.mk  |   69 -
 .../nbproject/Makefile-local-default.mk       |   37 -
 .../nbproject/Makefile-variables.mk           |   13 -
 .../nbproject/Package-default.bash            |   73 -
 .../nbproject/configurations.xml              |  173 -
 .../nbproject/project.properties              |    0
 .../MPU6050_raw.X/nbproject/project.xml       |   16 -
 32 files changed, 449 insertions(+), 4968 deletions(-)
 delete mode 100644 dsPIC30F/I2Cdev/I2CdevdsPic30F.X/Makefile
 delete mode 100644 dsPIC30F/I2Cdev/I2CdevdsPic30F.X/build/default/production/_ext/1922997195/I2Cdev.o
 delete mode 100644 dsPIC30F/I2Cdev/I2CdevdsPic30F.X/build/default/production/_ext/1922997195/I2Cdev.o.d
 delete mode 100644 dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-default.mk
 delete mode 100644 dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-genesis.properties
 delete mode 100644 dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-impl.mk
 delete mode 100644 dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-local-default.mk
 delete mode 100644 dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-variables.mk
 delete mode 100644 dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Package-default.bash
 delete mode 100644 dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/configurations.xml
 delete mode 100644 dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050.c.orig
 delete mode 100644 dsPIC30F/MPU6050/Examples/MPU6050_raw.X/Makefile
 delete mode 100644 dsPIC30F/MPU6050/Examples/MPU6050_raw.X/funclist
 delete mode 100644 dsPIC30F/MPU6050/Examples/MPU6050_raw.X/l.obj
 delete mode 100644 dsPIC30F/MPU6050/Examples/MPU6050_raw.X/main.c
 delete mode 100644 dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-default.mk
 delete mode 100644 dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-genesis.properties
 delete mode 100644 dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-impl.mk
 delete mode 100644 dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-local-default.mk
 delete mode 100644 dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-variables.mk
 delete mode 100644 dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/Package-default.bash
 delete mode 100644 dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/configurations.xml
 delete mode 100644 dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/project.properties
 delete mode 100644 dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/project.xml

diff --git a/dsPIC30F/I2Cdev/I2Cdev.c b/dsPIC30F/I2Cdev/I2Cdev.c
index 0e4d18d8..cc968752 100644
--- a/dsPIC30F/I2Cdev/I2Cdev.c
+++ b/dsPIC30F/I2Cdev/I2Cdev.c
@@ -34,8 +34,8 @@ THE SOFTWARE.
 
 #include "I2Cdev.h"
 
-//uint16_t config2;
-/*uint16_t config1 = (I2C_ON & I2C_IDLE_CON & I2C_CLK_HLD &
+/*uint16_t config2;
+uint16_t config1 = (I2C_ON & I2C_IDLE_CON & I2C_CLK_HLD &
              I2C_IPMI_DIS & I2C_7BIT_ADD &
              I2C_SLW_DIS & I2C_SM_DIS &
              I2C_GCALL_DIS & I2C_STR_DIS &
@@ -51,9 +51,8 @@ THE SOFTWARE.
  * @return Number of bytes read (-1 indicates failure)
  */
 int8_t I2Cdev_readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data) {
-    //int8_t count = 0;
     IFS0bits.MI2CIF = 0;
-    //IdleI2C();
+    IEC0bits.MI2CIE = 0;
     /*master Start*/
     StartI2C();
     /* Clear interrupt flag */
@@ -71,8 +70,7 @@ int8_t I2Cdev_readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_
     /*Slave send Ack*/
     while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
     IFS0bits.MI2CIF = 0;     // Clear interrupt flag
-    while(I2CSTATbits.ACKSTAT);
-
+    //while(I2CSTATbits.ACKSTAT);
     /*Master send RA*/
     /* Write Register Address */
     MasterWriteI2C(regAddr);
@@ -85,14 +83,22 @@ int8_t I2Cdev_readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_
     IFS0bits.MI2CIF = 0;     // Clear interrupt flag
     while(I2CSTATbits.ACKSTAT);
 
+    /*Master Pause*/
+    StopI2C();
+    /* Wait till stop sequence is completed */
+    while(I2CCONbits.PEN);
+    
     /*Master Start*/
-    RestartI2C();
+    StartI2C();
     /* Wait till Start sequence is completed */
     while(I2CCONbits.SEN);
 
+    
+    
     /*Master send AD+R*/
     /* Write Slave Address (Read)*/
     MasterWriteI2C(devAddr << 1 | 0x01);
+    
     /* Wait until address is transmitted */
     while(I2CSTATbits.TBF);  // 8 clock cycles
 
@@ -101,23 +107,20 @@ int8_t I2Cdev_readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_
     IFS0bits.MI2CIF = 0;     // Clear interrupt flag
     while(I2CSTATbits.ACKSTAT);
 
-    /*Slave send DATA*/
-    uint16_t flag = MastergetsI2C(length,data,I2C_DATA_WAIT);
-
-    /*Slave send NACK*/
+    data[0] = MasterReadI2C();
+    unsigned int i;
+    for (i = 1 ; i < length ; i++ ){
+        AckI2C();
+        while(I2CCONbits.ACKEN == 1);
+        data[i] = MasterReadI2C();
+    }
     NotAckI2C();
-
+    while(I2CCONbits.ACKEN == 1);
     /*Master Pause*/
     StopI2C();
     /* Wait till stop sequence is completed */
     while(I2CCONbits.PEN);
-    CloseI2C();
-
-    if (flag)
-        return length-flag;/*flag mean number of bytes read from I2C bus if its not able to*/
-                           /*read the data within the specified i2c_data_wait time out value*/
-    else
-        return -1;
+    return length;
 }
 
 /** Read single byte from an 8-bit device register.
@@ -138,91 +141,13 @@ int8_t I2Cdev_readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data) {
  * @return Number of words read (-1 indicates failure)
  */
 int8_t I2Cdev_readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data) {
-    int8_t count = 0;
-    IFS0bits.MI2CIF = 0;
-    IdleI2C();
-    /*master Start*/
-    StartI2C();
-    /* Clear interrupt flag */
-
-    /* Wait till Start sequence is completed */
-    while(I2CCONbits.SEN);
-
-    /*AD+W*/
-    /* Write Slave Address (Write)*/
-    MasterWriteI2C(devAddr << 1 | 0x00);
-
-    /* Wait until address is transmitted */
-    while(I2CSTATbits.TBF);  // 8 clock cycles
-
-    /*Slave Ack*/
-    while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
-    IFS0bits.MI2CIF = 0;     // Clear interrupt flag
-    while(I2CSTATbits.ACKSTAT);
-
-    /*master send RA*/
-    /* Write Register Address */
-    MasterWriteI2C(regAddr);
-
-    /* Wait until address is transmitted */
-    while(I2CSTATbits.TBF);  // 8 clock cycles
-
-    /*Slave ACK*/
-    while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
-    IFS0bits.MI2CIF = 0;     // Clear interrupt flag
-    while(I2CSTATbits.ACKSTAT);
-
-    /*master Start*/
-    RestartI2C();
-    /* Wait till Start sequence is completed */
-    while(I2CCONbits.SEN);
-
-    /*master send AD+R*/
-    /* Write Slave Address (Read)*/
-    MasterWriteI2C(devAddr << 1 | 0x01);
-    /* Wait until address is transmitted */
-    while(I2CSTATbits.TBF);  // 8 clock cycles
-
-    /*Slave Ack*/
-    while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
-    IFS0bits.MI2CIF = 0;     // Clear interrupt flag
-    while(I2CSTATbits.ACKSTAT);
-
-    /*Read Word Sequence*/
-    for ( count = 0 ; count < length ; count++ ) {
-        // First byte is bits 15-8 (MSb=15)
-        IdleI2C();
-        uint8_t high_byte = MasterReadI2C();
-
-        // NACK
-        IdleI2C();
-        NotAckI2C();
-
-        // Second byte is bits 7-0 (LSb=0)
-        IdleI2C();
-        uint8_t lower_byte = MasterReadI2C();
-        data[count] = (high_byte << 8) | lower_byte;
-        if (count == length - 1) {
-            // NACK
-            IdleI2C();
-            NotAckI2C();
-        } else {
-            // ACK
-            IdleI2C();
-            AckI2C();
-        }
+    unsigned char Onebyte[100];
+    I2Cdev_readBytes(devAddr,regAddr,length*2,Onebyte);
+    unsigned int i;
+    for (int i = 0 ; i < length ; i++ ){
+        data[i] = Onebyte[i*2] << 8 | Onebyte[i*2+1];
     }
-
-    /*Slave send NACK*/
-    NotAckI2C();
-
-    /*master enter P*/
-    StopI2C();
-    /* Wait till stop sequence is completed */
-    while(I2CCONbits.PEN);
-    CloseI2C();
-
-    return count;
+    return length;
 }
 
 /** Read single word from a 16-bit device register.
@@ -320,8 +245,8 @@ int8_t I2Cdev_readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint
  * @return Status of operation (true = success)
  */
 bool I2Cdev_writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t* data) {
-    OpenI2C(config1,config2);
-    IdleI2C();
+    IFS0bits.MI2CIF = 0;
+    IEC0bits.MI2CIE = 0;
     /*Master Start*/
     StartI2C();
     /* Wait util Start sequence is completed */
@@ -353,13 +278,20 @@ bool I2Cdev_writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t
 
     /*Master send data*/
     /* Transmit string of data */
-    MasterputsI2C(data);
-
+    uint8_t i;
+    for (i = 0 ; i < length ; i++){
+        MasterWriteI2C(data[i]);
+        /* Wait till address is transmitted */
+        while(I2CSTATbits.TBF);  // 8 clock cycles
+
+        /*Slave send ACK*/
+        while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
+        IFS0bits.MI2CIF = 0;     // Clear interrupt flag
+    }
+    
     StopI2C();
     /* Wait till stop sequence is completed */
     while(I2CCONbits.PEN);
-    CloseI2C();
-
     return true;
 }
 
@@ -381,66 +313,13 @@ bool I2Cdev_writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data) {
  * @return Status of operation (true = success)
  */
 bool I2Cdev_writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t* data) {
-    OpenI2C(config1,config2);
-    IdleI2C();
-    /*Master Start*/
-    StartI2C();
-    /* Wait util Start sequence is completed */
-    while(I2CCONbits.SEN);
-    /* Clear interrupt flag */
-    IFS0bits.MI2CIF = 0;
-
-    /*Master send AD+W*/
-    /* Write Slave address (Write)*/
-    MasterWriteI2C(devAddr << 1 | 0x00);
-    /* Wait till address is transmitted */
-    while(I2CSTATbits.TBF);  // 8 clock cycles
-
-    /*Slave send ACK*/
-    while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
-    IFS0bits.MI2CIF = 0;     // Clear interrupt flag
-    while(I2CSTATbits.ACKSTAT);
-    
-    /*Master send RA*/
-    /* Write Slave address (Write)*/
-    MasterWriteI2C(regAddr);
-    /* Wait till address is transmitted */
-    while(I2CSTATbits.TBF);  // 8 clock cycles
-
-    /*Slave send ACK*/
-    while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
-    IFS0bits.MI2CIF = 0;     // Clear interrupt flag
-    while(I2CSTATbits.ACKSTAT);
-
-    /*Master send RA*/
-    /* Write Slave address (Write)*/
-    uint8_t i;
-    for (i = 0; i < length; i++) {
-        // Send MSB
-        IdleI2C();
-        MasterWriteI2C(data[i] >> 8);
-
-        // Send LSB
-        IdleI2C();
-        MasterWriteI2C(data[i] & 0xFF);
+    unsigned char OneByte[100];
+    unsigned int i;
+    for (i = 0 ; i < length ; i++){
+        OneByte[i*2] = data[i]>>8;
+        OneByte[i*2+1] = data[i] & 0XFF;
     }
-    /* Wait till address is transmitted */
-    while(I2CSTATbits.TBF);  // 8 clock cycles
-
-    /*Slave send ACK*/
-    while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
-    IFS0bits.MI2CIF = 0;     // Clear interrupt flag
-    while(I2CSTATbits.ACKSTAT);
-
-    /*Master send data*/
-    /* Transmit string of data */
-    //MasterputsI2C(data);
-
-    StopI2C();
-    /* Wait till stop sequence is completed */
-    while(I2CCONbits.PEN);
-    CloseI2C();
-
+    I2Cdev_writeBytes(devAddr,regAddr,length*2,OneByte);
     return true;
 }
 
@@ -505,7 +384,7 @@ bool I2Cdev_writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_
         data &= mask; // zero all non-important bits in data
         b &= ~(mask); // zero all important bits in existing byte
         b |= data; // combine data with existing byte
-        return I2Cdev_writeByte(devAddr, regAddr, b);
+		return I2Cdev_writeByte(devAddr, regAddr, b);
     } else {
         return false;
     }
diff --git a/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/Makefile b/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/Makefile
deleted file mode 100644
index fca8e2cc..00000000
--- a/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/Makefile
+++ /dev/null
@@ -1,113 +0,0 @@
-#
-#  There exist several targets which are by default empty and which can be 
-#  used for execution of your targets. These targets are usually executed 
-#  before and after some main targets. They are: 
-#
-#     .build-pre:              called before 'build' target
-#     .build-post:             called after 'build' target
-#     .clean-pre:              called before 'clean' target
-#     .clean-post:             called after 'clean' target
-#     .clobber-pre:            called before 'clobber' target
-#     .clobber-post:           called after 'clobber' target
-#     .all-pre:                called before 'all' target
-#     .all-post:               called after 'all' target
-#     .help-pre:               called before 'help' target
-#     .help-post:              called after 'help' target
-#
-#  Targets beginning with '.' are not intended to be called on their own.
-#
-#  Main targets can be executed directly, and they are:
-#  
-#     build                    build a specific configuration
-#     clean                    remove built files from a configuration
-#     clobber                  remove all built files
-#     all                      build all configurations
-#     help                     print help mesage
-#  
-#  Targets .build-impl, .clean-impl, .clobber-impl, .all-impl, and
-#  .help-impl are implemented in nbproject/makefile-impl.mk.
-#
-#  Available make variables:
-#
-#     CND_BASEDIR                base directory for relative paths
-#     CND_DISTDIR                default top distribution directory (build artifacts)
-#     CND_BUILDDIR               default top build directory (object files, ...)
-#     CONF                       name of current configuration
-#     CND_ARTIFACT_DIR_${CONF}   directory of build artifact (current configuration)
-#     CND_ARTIFACT_NAME_${CONF}  name of build artifact (current configuration)
-#     CND_ARTIFACT_PATH_${CONF}  path to build artifact (current configuration)
-#     CND_PACKAGE_DIR_${CONF}    directory of package (current configuration)
-#     CND_PACKAGE_NAME_${CONF}   name of package (current configuration)
-#     CND_PACKAGE_PATH_${CONF}   path to package (current configuration)
-#
-# NOCDDL
-
-
-# Environment 
-MKDIR=mkdir
-CP=cp
-CCADMIN=CCadmin
-RANLIB=ranlib
-
-
-# build
-build: .build-post
-
-.build-pre:
-# Add your pre 'build' code here...
-
-.build-post: .build-impl
-# Add your post 'build' code here...
-
-
-# clean
-clean: .clean-post
-
-.clean-pre:
-# Add your pre 'clean' code here...
-# WARNING: the IDE does not call this target since it takes a long time to
-# simply run make. Instead, the IDE removes the configuration directories
-# under build and dist directly without calling make.
-# This target is left here so people can do a clean when running a clean
-# outside the IDE.
-
-.clean-post: .clean-impl
-# Add your post 'clean' code here...
-
-
-# clobber
-clobber: .clobber-post
-
-.clobber-pre:
-# Add your pre 'clobber' code here...
-
-.clobber-post: .clobber-impl
-# Add your post 'clobber' code here...
-
-
-# all
-all: .all-post
-
-.all-pre:
-# Add your pre 'all' code here...
-
-.all-post: .all-impl
-# Add your post 'all' code here...
-
-
-# help
-help: .help-post
-
-.help-pre:
-# Add your pre 'help' code here...
-
-.help-post: .help-impl
-# Add your post 'help' code here...
-
-
-
-# include project implementation makefile
-include nbproject/Makefile-impl.mk
-
-# include project make variables
-include nbproject/Makefile-variables.mk
diff --git a/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/build/default/production/_ext/1922997195/I2Cdev.o b/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/build/default/production/_ext/1922997195/I2Cdev.o
deleted file mode 100644
index f7252c0b09056012661c51018df820081e335543..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 22716
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
Ee>1=<+5i9m

diff --git a/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/build/default/production/_ext/1922997195/I2Cdev.o.d b/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/build/default/production/_ext/1922997195/I2Cdev.o.d
deleted file mode 100644
index 3255c9ae..00000000
--- a/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/build/default/production/_ext/1922997195/I2Cdev.o.d
+++ /dev/null
@@ -1,3 +0,0 @@
-build/default/production/_ext/1922997195/I2Cdev.o:  \
- /home/tommycc/work/i2cdevlib/dsPIC30F/I2Cdev/I2Cdev.c  \
- /home/tommycc/work/i2cdevlib/dsPIC30F/I2Cdev/I2Cdev.h 
diff --git a/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-default.mk b/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-default.mk
deleted file mode 100644
index a82c29ac..00000000
--- a/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-default.mk
+++ /dev/null
@@ -1,155 +0,0 @@
-#
-# Generated Makefile - do not edit!
-#
-# Edit the Makefile in the project folder instead (../Makefile). Each target
-# has a -pre and a -post target defined where you can add customized code.
-#
-# This makefile implements configuration specific macros and targets.
-
-
-# Include project Makefile
-ifeq "${IGNORE_LOCAL}" "TRUE"
-# do not include local makefile. User is passing all local related variables already
-else
-include Makefile
-# Include makefile containing local settings
-ifeq "$(wildcard nbproject/Makefile-local-default.mk)" "nbproject/Makefile-local-default.mk"
-include nbproject/Makefile-local-default.mk
-endif
-endif
-
-# Environment
-MKDIR=mkdir -p
-RM=rm -f 
-MV=mv 
-CP=cp 
-
-# Macros
-CND_CONF=default
-ifeq ($(TYPE_IMAGE), DEBUG_RUN)
-IMAGE_TYPE=debug
-OUTPUT_SUFFIX=a
-DEBUGGABLE_SUFFIX=a
-FINAL_IMAGE=dist/${CND_CONF}/${IMAGE_TYPE}/I2CdevdsPic30F.X.${OUTPUT_SUFFIX}
-else
-IMAGE_TYPE=production
-OUTPUT_SUFFIX=a
-DEBUGGABLE_SUFFIX=a
-FINAL_IMAGE=dist/${CND_CONF}/${IMAGE_TYPE}/I2CdevdsPic30F.X.${OUTPUT_SUFFIX}
-endif
-
-ifeq ($(COMPARE_BUILD), true)
-COMPARISON_BUILD=-mafrlcsj
-else
-COMPARISON_BUILD=
-endif
-
-# Object Directory
-OBJECTDIR=build/${CND_CONF}/${IMAGE_TYPE}
-
-# Distribution Directory
-DISTDIR=dist/${CND_CONF}/${IMAGE_TYPE}
-
-# Source Files Quoted if spaced
-SOURCEFILES_QUOTED_IF_SPACED=/home/tommycc/work/i2cdevlib/dsPIC30F/I2Cdev/I2Cdev.c
-
-# Object Files Quoted if spaced
-OBJECTFILES_QUOTED_IF_SPACED=${OBJECTDIR}/_ext/1922997195/I2Cdev.o
-POSSIBLE_DEPFILES=${OBJECTDIR}/_ext/1922997195/I2Cdev.o.d
-
-# Object Files
-OBJECTFILES=${OBJECTDIR}/_ext/1922997195/I2Cdev.o
-
-# Source Files
-SOURCEFILES=/home/tommycc/work/i2cdevlib/dsPIC30F/I2Cdev/I2Cdev.c
-
-
-CFLAGS=
-ASFLAGS=
-LDLIBSOPTIONS=
-
-############# Tool locations ##########################################
-# If you copy a project from one host to another, the path where the  #
-# compiler is installed may be different.                             #
-# If you open this project with MPLAB X in the new host, this         #
-# makefile will be regenerated and the paths will be corrected.       #
-#######################################################################
-# fixDeps replaces a bunch of sed/cat/printf statements that slow down the build
-FIXDEPS=fixDeps
-
-.build-conf:  ${BUILD_SUBPROJECTS}
-ifneq ($(INFORMATION_MESSAGE), )
-	@echo $(INFORMATION_MESSAGE)
-endif
-	${MAKE}  -f nbproject/Makefile-default.mk dist/${CND_CONF}/${IMAGE_TYPE}/I2CdevdsPic30F.X.${OUTPUT_SUFFIX}
-
-MP_PROCESSOR_OPTION=30F4013
-MP_LINKER_FILE_OPTION=,--script=p30F4013.gld
-# ------------------------------------------------------------------------------------
-# Rules for buildStep: compile
-ifeq ($(TYPE_IMAGE), DEBUG_RUN)
-${OBJECTDIR}/_ext/1922997195/I2Cdev.o: /home/tommycc/work/i2cdevlib/dsPIC30F/I2Cdev/I2Cdev.c  nbproject/Makefile-${CND_CONF}.mk
-	@${MKDIR} "${OBJECTDIR}/_ext/1922997195" 
-	@${RM} ${OBJECTDIR}/_ext/1922997195/I2Cdev.o.d 
-	@${RM} ${OBJECTDIR}/_ext/1922997195/I2Cdev.o 
-	${MP_CC} $(MP_EXTRA_CC_PRE)  /home/tommycc/work/i2cdevlib/dsPIC30F/I2Cdev/I2Cdev.c  -o ${OBJECTDIR}/_ext/1922997195/I2Cdev.o  -c -mcpu=$(MP_PROCESSOR_OPTION)  -MMD -MF "${OBJECTDIR}/_ext/1922997195/I2Cdev.o.d"      -g -D__DEBUG -D__MPLAB_DEBUGGER_PK3=1    -omf=elf -DXPRJ_default=$(CND_CONF)  -legacy-libc  $(COMPARISON_BUILD)  -O0 -msmart-io=1 -Wall -msfr-warn=off  
-	@${FIXDEPS} "${OBJECTDIR}/_ext/1922997195/I2Cdev.o.d" $(SILENT)  -rsi ${MP_CC_DIR}../ 
-	
-else
-${OBJECTDIR}/_ext/1922997195/I2Cdev.o: /home/tommycc/work/i2cdevlib/dsPIC30F/I2Cdev/I2Cdev.c  nbproject/Makefile-${CND_CONF}.mk
-	@${MKDIR} "${OBJECTDIR}/_ext/1922997195" 
-	@${RM} ${OBJECTDIR}/_ext/1922997195/I2Cdev.o.d 
-	@${RM} ${OBJECTDIR}/_ext/1922997195/I2Cdev.o 
-	${MP_CC} $(MP_EXTRA_CC_PRE)  /home/tommycc/work/i2cdevlib/dsPIC30F/I2Cdev/I2Cdev.c  -o ${OBJECTDIR}/_ext/1922997195/I2Cdev.o  -c -mcpu=$(MP_PROCESSOR_OPTION)  -MMD -MF "${OBJECTDIR}/_ext/1922997195/I2Cdev.o.d"        -g -omf=elf -DXPRJ_default=$(CND_CONF)  -legacy-libc  $(COMPARISON_BUILD)  -O0 -msmart-io=1 -Wall -msfr-warn=off  
-	@${FIXDEPS} "${OBJECTDIR}/_ext/1922997195/I2Cdev.o.d" $(SILENT)  -rsi ${MP_CC_DIR}../ 
-	
-endif
-
-# ------------------------------------------------------------------------------------
-# Rules for buildStep: assemble
-ifeq ($(TYPE_IMAGE), DEBUG_RUN)
-else
-endif
-
-# ------------------------------------------------------------------------------------
-# Rules for buildStep: assemblePreproc
-ifeq ($(TYPE_IMAGE), DEBUG_RUN)
-else
-endif
-
-# ------------------------------------------------------------------------------------
-# Rules for buildStep: archive
-ifeq ($(TYPE_IMAGE), DEBUG_RUN)
-dist/${CND_CONF}/${IMAGE_TYPE}/I2CdevdsPic30F.X.${OUTPUT_SUFFIX}: ${OBJECTFILES}  nbproject/Makefile-${CND_CONF}.mk    
-	@${MKDIR} dist/${CND_CONF}/${IMAGE_TYPE} 
-	@${RM} dist/${CND_CONF}/${IMAGE_TYPE}/I2CdevdsPic30F.X.${OUTPUT_SUFFIX} 
-	${MP_AR} $(MP_EXTRA_AR_PRE)  -omf=elf -r dist/${CND_CONF}/${IMAGE_TYPE}/I2CdevdsPic30F.X.${OUTPUT_SUFFIX}  ${OBJECTFILES_QUOTED_IF_SPACED}      
-	
-else
-dist/${CND_CONF}/${IMAGE_TYPE}/I2CdevdsPic30F.X.${OUTPUT_SUFFIX}: ${OBJECTFILES}  nbproject/Makefile-${CND_CONF}.mk   
-	@${MKDIR} dist/${CND_CONF}/${IMAGE_TYPE} 
-	@${RM} dist/${CND_CONF}/${IMAGE_TYPE}/I2CdevdsPic30F.X.${OUTPUT_SUFFIX} 
-	${MP_AR} $(MP_EXTRA_AR_PRE)  -omf=elf -r dist/${CND_CONF}/${IMAGE_TYPE}/I2CdevdsPic30F.X.${OUTPUT_SUFFIX}  ${OBJECTFILES_QUOTED_IF_SPACED}      
-	
-endif
-
-
-# Subprojects
-.build-subprojects:
-
-
-# Subprojects
-.clean-subprojects:
-
-# Clean Targets
-.clean-conf: ${CLEAN_SUBPROJECTS}
-	${RM} -r build/default
-	${RM} -r dist/default
-
-# Enable dependency checking
-.dep.inc: .depcheck-impl
-
-DEPFILES=$(shell "${PATH_TO_IDE_BIN}"mplabwildcard ${POSSIBLE_DEPFILES})
-ifneq (${DEPFILES},)
-include ${DEPFILES}
-endif
diff --git a/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-genesis.properties b/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-genesis.properties
deleted file mode 100644
index da0cb730..00000000
--- a/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-genesis.properties
+++ /dev/null
@@ -1,9 +0,0 @@
-#
-#Wed Apr 26 14:40:24 CST 2017
-default.com-microchip-mplab-nbide-toolchainXC16-XC16LanguageToolchain.md5=ebaa75370c1463d650408e4144ba15de
-default.languagetoolchain.dir=/opt/microchip/xc16/v1.30/bin
-configurations-xml=e23099a44127c530cab293bfc5554ec5
-com-microchip-mplab-nbide-embedded-makeproject-MakeProject.md5=8b140fb87818dc96ed4f726b716b40e9
-default.languagetoolchain.version=1.30
-host.platform=linux
-conf.ids=default
diff --git a/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-impl.mk b/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-impl.mk
deleted file mode 100644
index b4e2d4c4..00000000
--- a/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-impl.mk
+++ /dev/null
@@ -1,69 +0,0 @@
-#
-# Generated Makefile - do not edit!
-#
-# Edit the Makefile in the project folder instead (../Makefile). Each target
-# has a pre- and a post- target defined where you can add customization code.
-#
-# This makefile implements macros and targets common to all configurations.
-#
-# NOCDDL
-
-
-# Building and Cleaning subprojects are done by default, but can be controlled with the SUB
-# macro. If SUB=no, subprojects will not be built or cleaned. The following macro
-# statements set BUILD_SUB-CONF and CLEAN_SUB-CONF to .build-reqprojects-conf
-# and .clean-reqprojects-conf unless SUB has the value 'no'
-SUB_no=NO
-SUBPROJECTS=${SUB_${SUB}}
-BUILD_SUBPROJECTS_=.build-subprojects
-BUILD_SUBPROJECTS_NO=
-BUILD_SUBPROJECTS=${BUILD_SUBPROJECTS_${SUBPROJECTS}}
-CLEAN_SUBPROJECTS_=.clean-subprojects
-CLEAN_SUBPROJECTS_NO=
-CLEAN_SUBPROJECTS=${CLEAN_SUBPROJECTS_${SUBPROJECTS}}
-
-
-# Project Name
-PROJECTNAME=I2CdevdsPic30F.X
-
-# Active Configuration
-DEFAULTCONF=default
-CONF=${DEFAULTCONF}
-
-# All Configurations
-ALLCONFS=default 
-
-
-# build
-.build-impl: .build-pre
-	${MAKE} -f nbproject/Makefile-${CONF}.mk SUBPROJECTS=${SUBPROJECTS} .build-conf
-
-
-# clean
-.clean-impl: .clean-pre
-	${MAKE} -f nbproject/Makefile-${CONF}.mk SUBPROJECTS=${SUBPROJECTS} .clean-conf
-
-# clobber
-.clobber-impl: .clobber-pre .depcheck-impl
-	    ${MAKE} SUBPROJECTS=${SUBPROJECTS} CONF=default clean
-
-
-
-# all
-.all-impl: .all-pre .depcheck-impl
-	    ${MAKE} SUBPROJECTS=${SUBPROJECTS} CONF=default build
-
-
-
-# dependency checking support
-.depcheck-impl:
-#	@echo "# This code depends on make tool being used" >.dep.inc
-#	@if [ -n "${MAKE_VERSION}" ]; then \
-#	    echo "DEPFILES=\$$(wildcard \$$(addsuffix .d, \$${OBJECTFILES}))" >>.dep.inc; \
-#	    echo "ifneq (\$${DEPFILES},)" >>.dep.inc; \
-#	    echo "include \$${DEPFILES}" >>.dep.inc; \
-#	    echo "endif" >>.dep.inc; \
-#	else \
-#	    echo ".KEEP_STATE:" >>.dep.inc; \
-#	    echo ".KEEP_STATE_FILE:.make.state.\$${CONF}" >>.dep.inc; \
-#	fi
diff --git a/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-local-default.mk b/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-local-default.mk
deleted file mode 100644
index 38870624..00000000
--- a/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-local-default.mk
+++ /dev/null
@@ -1,36 +0,0 @@
-#
-# Generated Makefile - do not edit!
-#
-#
-# This file contains information about the location of compilers and other tools.
-# If you commmit this file into your revision control server, you will be able to 
-# to checkout the project and build it from the command line with make. However,
-# if more than one person works on the same project, then this file might show
-# conflicts since different users are bound to have compilers in different places.
-# In that case you might choose to not commit this file and let MPLAB X recreate this file
-# for each user. The disadvantage of not commiting this file is that you must run MPLAB X at
-# least once so the file gets created and the project can be built. Finally, you can also
-# avoid using this file at all if you are only building from the command line with make.
-# You can invoke make with the values of the macros:
-# $ makeMP_CC="/opt/microchip/mplabc30/v3.30c/bin/pic30-gcc" ...  
-#
-PATH_TO_IDE_BIN=/opt/microchip/mplabx/v3.45/mplab_ide/platform/../mplab_ide/modules/../../bin/
-# Adding MPLAB X bin directory to path.
-PATH:=/opt/microchip/mplabx/v3.45/mplab_ide/platform/../mplab_ide/modules/../../bin/:$(PATH)
-# Path to java used to run MPLAB X when this makefile was created
-MP_JAVA_PATH="/opt/microchip/mplabx/v3.45/sys/java/jre1.8.0_91/bin/"
-OS_CURRENT="$(shell uname -s)"
-MP_CC="/opt/microchip/xc16/v1.30/bin/xc16-gcc"
-# MP_CPPC is not defined
-# MP_BC is not defined
-MP_AS="/opt/microchip/xc16/v1.30/bin/xc16-as"
-MP_LD="/opt/microchip/xc16/v1.30/bin/xc16-ld"
-MP_AR="/opt/microchip/xc16/v1.30/bin/xc16-ar"
-DEP_GEN=${MP_JAVA_PATH}java -jar "/opt/microchip/mplabx/v3.45/mplab_ide/platform/../mplab_ide/modules/../../bin/extractobjectdependencies.jar"
-MP_CC_DIR="/opt/microchip/xc16/v1.30/bin"
-# MP_CPPC_DIR is not defined
-# MP_BC_DIR is not defined
-MP_AS_DIR="/opt/microchip/xc16/v1.30/bin"
-MP_LD_DIR="/opt/microchip/xc16/v1.30/bin"
-MP_AR_DIR="/opt/microchip/xc16/v1.30/bin"
-# MP_BC_DIR is not defined
diff --git a/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-variables.mk b/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-variables.mk
deleted file mode 100644
index 3974a0f0..00000000
--- a/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Makefile-variables.mk
+++ /dev/null
@@ -1,13 +0,0 @@
-#
-# Generated - do not edit!
-#
-# NOCDDL
-#
-CND_BASEDIR=`pwd`
-# default configuration
-CND_ARTIFACT_DIR_default=dist/default/production
-CND_ARTIFACT_NAME_default=I2CdevdsPic30F.X.a
-CND_ARTIFACT_PATH_default=dist/default/production/I2CdevdsPic30F.X.a
-CND_PACKAGE_DIR_default=${CND_DISTDIR}/default/package
-CND_PACKAGE_NAME_default=I2CdevdsPic30F.X.tar
-CND_PACKAGE_PATH_default=${CND_DISTDIR}/default/package/I2CdevdsPic30F.X.tar
diff --git a/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Package-default.bash b/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Package-default.bash
deleted file mode 100644
index 86c2f144..00000000
--- a/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/Package-default.bash
+++ /dev/null
@@ -1,73 +0,0 @@
-#!/bin/bash -x
-
-#
-# Generated - do not edit!
-#
-
-# Macros
-TOP=`pwd`
-CND_CONF=default
-CND_DISTDIR=dist
-TMPDIR=build/${CND_CONF}/${IMAGE_TYPE}/tmp-packaging
-TMPDIRNAME=tmp-packaging
-OUTPUT_PATH=dist/${CND_CONF}/${IMAGE_TYPE}/I2CdevdsPic30F.X.${OUTPUT_SUFFIX}
-OUTPUT_BASENAME=I2CdevdsPic30F.X.${OUTPUT_SUFFIX}
-PACKAGE_TOP_DIR=I2CdevdsPic30F.X/
-
-# Functions
-function checkReturnCode
-{
-    rc=$?
-    if [ $rc != 0 ]
-    then
-        exit $rc
-    fi
-}
-function makeDirectory
-# $1 directory path
-# $2 permission (optional)
-{
-    mkdir -p "$1"
-    checkReturnCode
-    if [ "$2" != "" ]
-    then
-      chmod $2 "$1"
-      checkReturnCode
-    fi
-}
-function copyFileToTmpDir
-# $1 from-file path
-# $2 to-file path
-# $3 permission
-{
-    cp "$1" "$2"
-    checkReturnCode
-    if [ "$3" != "" ]
-    then
-        chmod $3 "$2"
-        checkReturnCode
-    fi
-}
-
-# Setup
-cd "${TOP}"
-mkdir -p ${CND_DISTDIR}/${CND_CONF}/package
-rm -rf ${TMPDIR}
-mkdir -p ${TMPDIR}
-
-# Copy files and create directories and links
-cd "${TOP}"
-makeDirectory ${TMPDIR}/I2CdevdsPic30F.X/lib
-copyFileToTmpDir "${OUTPUT_PATH}" "${TMPDIR}/${PACKAGE_TOP_DIR}lib/${OUTPUT_BASENAME}" 0644
-
-
-# Generate tar file
-cd "${TOP}"
-rm -f ${CND_DISTDIR}/${CND_CONF}/package/I2CdevdsPic30F.X.tar
-cd ${TMPDIR}
-tar -vcf ../../../../${CND_DISTDIR}/${CND_CONF}/package/I2CdevdsPic30F.X.tar *
-checkReturnCode
-
-# Cleanup
-cd "${TOP}"
-rm -rf ${TMPDIR}
diff --git a/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/configurations.xml b/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/configurations.xml
deleted file mode 100644
index 506353f5..00000000
--- a/dsPIC30F/I2Cdev/I2CdevdsPic30F.X/nbproject/configurations.xml
+++ /dev/null
@@ -1,162 +0,0 @@
-
-
-  
-    
-      /home/tommycc/work/i2cdevlib/dsPIC30F/I2Cdev/I2Cdev.h
-    
-    
-    
-    
-      /home/tommycc/work/i2cdevlib/dsPIC30F/I2Cdev/I2Cdev.c
-    
-    
-      Makefile
-    
-  
-  
-    /home/tommycc/work/i2cdevlib/dsPIC30F/I2Cdev
-  
-  Makefile
-  
-    
-      
-        localhost
-        dsPIC30F4013
-        
-        
-        PICkit3PlatformTool
-        XC16
-        1.30
-        2
-      
-      
-        
-          
-          
-        
-        
-        
-        
-          false
-          false
-          
-        
-        
-        
-      
-      
-        false
-        
-        false
-        
-        false
-        false
-        false
-      
-      
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-      
-      
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-      
-      
-        
-        
-        
-        
-        
-        
-        
-        
-        
-      
-    
-  
-
diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/I2Cdev.c b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/I2Cdev.c
index f0d99941..29bd9eb3 100644
--- a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/I2Cdev.c
+++ b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/I2Cdev.c
@@ -34,33 +34,6 @@ THE SOFTWARE.
 
 #include "I2Cdev.h"
 
-/*******************************************************************************/
-//  delay us using for-loop
-/*******************************************************************************/
-void delay_us_I2C( unsigned int usec )
-{
-	unsigned int i;
-	//¦   ¦   ¦   ¦   ¦   ¦   ¦   ¦   ¦   ¦              //40 MIPS ,
-	for ( i = 0 ; i < usec * 2;
-	        i++ ) {                //for-loop 8Tcy -> 1us -> add two NOP()
-		asm("NOP");
-		asm("NOP");
-	}
-}
-/*******************************************************************************/
-// delay ms using Timer 1 interrupt
-/*******************************************************************************/
-void delay_ms_I2C( unsigned int msec )
-{
-	/*TIMER1_DELAY_VALUE = msec;
-	TMR1 = 0;
-	IEC0bits.T1IE = 1;
-	while(TIMER1_DELAY_VALUE);
-	*/
-	int i = 0;
-	for (i = 0; i < msec; i++)
-		delay_us_I2C(1000);
-}
 
 /*uint16_t config2;
 uint16_t config1 = (I2C_ON & I2C_IDLE_CON & I2C_CLK_HLD &
@@ -117,18 +90,15 @@ int8_t I2Cdev_readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_
     StopI2C();
     /* Wait till stop sequence is completed */
     while(I2CCONbits.PEN);
-    
+
     /*Master Start*/
     StartI2C();
     /* Wait till Start sequence is completed */
     while(I2CCONbits.SEN);
 
-    
-    
     /*Master send AD+R*/
     /* Write Slave Address (Read)*/
     MasterWriteI2C(devAddr << 1 | 0x01);
-    
     /* Wait until address is transmitted */
     while(I2CSTATbits.TBF);  // 8 clock cycles
 
@@ -333,7 +303,6 @@ bool I2Cdev_writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t
     }
     //while(!IFS0bits.MI2CIF); // Wait for 9th clock cycle
     //IFS0bits.MI2CIF = 0;     // Clear interrupt flag
-    
     StopI2C();
     /* Wait till stop sequence is completed */
     while(I2CCONbits.PEN);
diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050.c b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050.c
index bb31b001..a976419e 100644
--- a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050.c
+++ b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050.c
@@ -40,34 +40,6 @@ THE SOFTWARE.
 
 #include "MPU6050.h"
 
-/*******************************************************************************/
-//  delay us using for-loop
-/*******************************************************************************/
-void delay_us( unsigned int usec )
-{
-	unsigned int i;
-	//�   �   �   �   �   �   �   �   �   �              //40 MIPS ,
-	for ( i = 0 ; i < usec * 2;
-	        i++ ) {                //for-loop 8Tcy -> 1us -> add two NOP()
-		asm("NOP");
-		asm("NOP");
-	}
-}
-/*******************************************************************************/
-// delay ms using Timer 1 interrupt
-/*******************************************************************************/
-void delay_ms( unsigned int msec )
-{
-	/*TIMER1_DELAY_VALUE = msec;
-	TMR1 = 0;
-	IEC0bits.T1IE = 1;
-	while(TIMER1_DELAY_VALUE);
-	*/
-	int i = 0;
-	for (i = 0; i < msec; i++)
-		delay_us(1000);
-}
-
 MPU6050_t mpu6050;
 
 /** Specific address constructor.
@@ -90,9 +62,9 @@ void MPU6050(uint8_t address)
  */
 void MPU6050_initialize()
 {
-    MPU6050_setClockSource(MPU6050_CLOCK_PLL_XGYRO);                                                                    
-    MPU6050_setFullScaleGyroRange(MPU6050_GYRO_FS_250);                                                                 
-    MPU6050_setFullScaleAccelRange(MPU6050_ACCEL_FS_2);                                                                 
+    MPU6050_setClockSource(MPU6050_CLOCK_PLL_XGYRO);
+    MPU6050_setFullScaleGyroRange(MPU6050_GYRO_FS_250);
+    MPU6050_setFullScaleAccelRange(MPU6050_ACCEL_FS_2);
     MPU6050_setSleepEnabled(false);
 }
 
@@ -3613,4 +3585,4 @@ uint8_t MPU6050_getDMPConfig2()
 void MPU6050_setDMPConfig2(uint8_t config)
 {
 	I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_DMP_CFG_2, config);
-}
\ No newline at end of file
+}
diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050.c.orig b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050.c.orig
deleted file mode 100644
index 6f85e455..00000000
--- a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050.c.orig
+++ /dev/null
@@ -1,3174 +0,0 @@
-// I2Cdev library collection - MPU6050 I2C device class
-// Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00)
-// 8/24/2011 by Jeff Rowberg 
-// 11/28/2014 by Marton Sebok 
-//
-// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
-//
-// Changelog:
-//     ...        - ongoing debug release
-//     2014-11-28 - ported to PIC18 peripheral library from Arduino code
-
-// NOTE: THIS IS ONLY A PARIAL RELEASE. THIS DEVICE CLASS IS CURRENTLY UNDERGOING ACTIVE
-// DEVELOPMENT AND IS STILL MISSING SOME IMPORTANT FEATURES. PLEASE KEEP THIS IN MIND IF
-// YOU DECIDE TO USE THIS PARTICULAR CODE FOR ANYTHING.
-
-/* ============================================
-I2Cdev device library code is placed under the MIT license
-Copyright (c) 2012 Jeff Rowberg
-Copyright (c) 2014 Marton Sebok
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-===============================================
-*/
-
-#include "MPU6050.h"
-
-/*******************************************************************************/         
-//  delay us using for-loop     
-/*******************************************************************************/     
-void delay_us( unsigned int usec )                      
-{                                   
-    unsigned int i;                                                                  
-    //�   �   �   �   �   �   �   �   �   �              //40 MIPS ,     
-    for ( i = 0 ; i < usec * 2; i++ ){                 //for-loop 8Tcy -> 1us -> add two NOP()     
-        asm("NOP");      
-        asm("NOP");    
-    }                                                                 
-}                                   
-/*******************************************************************************/     
-// delay ms using Timer 1 interrupt                                                     
-/*******************************************************************************/     
-void delay_ms( unsigned int msec )                                                                                                                
-{       
-    /*TIMER1_DELAY_VALUE = msec;     
-    TMR1 = 0;                                                                                 
-    IEC0bits.T1IE = 1;        
-    while(TIMER1_DELAY_VALUE);                                                       
-    */            
-    int i=0;    
-    for (i = 0;i < msec;i++)    
-       delay_us(1000);                                 
-}       
-
-MPU6050_t mpu6050;
-
-/** Specific address constructor.
- * @param address I2C address
- * @see MPU6050_DEFAULT_ADDRESS
- * @see MPU6050_ADDRESS_AD0_LOW
- * @see MPU6050_ADDRESS_AD0_HIGH
- */
-void MPU6050(uint8_t address) {
-    mpu6050.devAddr = address;
-}
-
-/** Power on and prepare for general usage.
- * This will activate the device and take it out of sleep mode (which must be done
- * after start-up). This function also sets both the accelerometer and the gyroscope
- * to their most sensitive settings, namely +/- 2g and +/- 250 degrees/sec, and sets
- * the clock source to use the X Gyro for reference, which is slightly better than
- * the default internal clock source.
- */
-void MPU6050_initialize() {
-    
-    
-    MPU6050_setSleepEnabled(false); // thanks to Jack Elston for pointing this one out!
-    delay_us(200);
-    MPU6050_setClockSource(MPU6050_CLOCK_PLL_XGYRO);
-    delay_us(200);
-    MPU6050_setFullScaleAccelRange(MPU6050_ACCEL_FS_2);
-    delay_us(200);
-    MPU6050_setFullScaleGyroRange(MPU6050_GYRO_FS_250);
-    
-}
-
-/** Verify the I2C connection.
- * Make sure the device is connected and responds as expected.
- * @return True if connection is valid, false otherwise
- */
-bool MPU6050_testConnection() {
-    return MPU6050_getDeviceID() == 0x34;
-}
-
-// AUX_VDDIO register (InvenSense demo code calls this RA_*G_OFFS_TC)
-
-/** Get the auxiliary I2C supply voltage level.
- * When set to 1, the auxiliary I2C bus high logic level is VDD. When cleared to
- * 0, the auxiliary I2C bus high logic level is VLOGIC. This does not apply to
- * the MPU-6000, which does not have a VLOGIC pin.
- * @return I2C supply voltage level (0=VLOGIC, 1=VDD)
- */
-uint8_t MPU6050_getAuxVDDIOLevel() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_PWR_MODE_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
-}
-/** Set the auxiliary I2C supply voltage level.
- * When set to 1, the auxiliary I2C bus high logic level is VDD. When cleared to
- * 0, the auxiliary I2C bus high logic level is VLOGIC. This does not apply to
- * the MPU-6000, which does not have a VLOGIC pin.
- * @param level I2C supply voltage level (0=VLOGIC, 1=VDD)
- */
-void MPU6050_setAuxVDDIOLevel(uint8_t level) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_PWR_MODE_BIT, level);
-}
-
-// SMPLRT_DIV register
-
-/** Get gyroscope output rate divider.
- * The sensor register output, FIFO output, DMP sampling, Motion detection, Zero
- * Motion detection, and Free Fall detection are all based on the Sample Rate.
- * The Sample Rate is generated by dividing the gyroscope output rate by
- * SMPLRT_DIV:
- *
- * Sample Rate = Gyroscope Output Rate / (1 + SMPLRT_DIV)
- *
- * where Gyroscope Output Rate = 8kHz when the DLPF is disabled (DLPF_CFG = 0 or
- * 7), and 1kHz when the DLPF is enabled (see Register 26).
- *
- * Note: The accelerometer output rate is 1kHz. This means that for a Sample
- * Rate greater than 1kHz, the same accelerometer sample may be output to the
- * FIFO, DMP, and sensor registers more than once.
- *
- * For a diagram of the gyroscope and accelerometer signal paths, see Section 8
- * of the MPU-6000/MPU-6050 Product Specification document.
- *
- * @return Current sample rate
- * @see MPU6050_RA_SMPLRT_DIV
- */
-uint8_t MPU6050_getRate() {
-    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_SMPLRT_DIV, mpu6050.buffer);
-    return mpu6050.buffer[0];
-}
-/** Set gyroscope sample rate divider.
- * @param rate New sample rate divider
- * @see getRate()
- * @see MPU6050_RA_SMPLRT_DIV
- */
-void MPU6050_setRate(uint8_t rate) {
-    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_SMPLRT_DIV, rate);
-}
-
-// CONFIG register
-
-/** Get external FSYNC configuration.
- * Configures the external Frame Synchronization (FSYNC) pin sampling. An
- * external signal connected to the FSYNC pin can be sampled by configuring
- * EXT_SYNC_SET. Signal changes to the FSYNC pin are latched so that short
- * strobes may be captured. The latched FSYNC signal will be sampled at the
- * Sampling Rate, as defined in register 25. After sampling, the latch will
- * reset to the current FSYNC signal state.
- *
- * The sampled value will be reported in place of the least significant bit in
- * a sensor data register determined by the value of EXT_SYNC_SET according to
- * the following table.
- *
- * 
- * EXT_SYNC_SET | FSYNC Bit Location
- * -------------+-------------------
- * 0            | Input disabled
- * 1            | TEMP_OUT_L[0]
- * 2            | GYRO_XOUT_L[0]
- * 3            | GYRO_YOUT_L[0]
- * 4            | GYRO_ZOUT_L[0]
- * 5            | ACCEL_XOUT_L[0]
- * 6            | ACCEL_YOUT_L[0]
- * 7            | ACCEL_ZOUT_L[0]
- * 
- * - * @return FSYNC configuration value - */ -uint8_t MPU6050_getExternalFrameSync() { - I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_EXT_SYNC_SET_BIT, MPU6050_CFG_EXT_SYNC_SET_LENGTH, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set external FSYNC configuration. - * @see getExternalFrameSync() - * @see MPU6050_RA_CONFIG - * @param sync New FSYNC configuration value - */ -void MPU6050_setExternalFrameSync(uint8_t sync) { - I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_EXT_SYNC_SET_BIT, MPU6050_CFG_EXT_SYNC_SET_LENGTH, sync); -} -/** Get digital low-pass filter configuration. - * The DLPF_CFG parameter sets the digital low pass filter configuration. It - * also determines the internal sampling rate used by the device as shown in - * the table below. - * - * Note: The accelerometer output rate is 1kHz. This means that for a Sample - * Rate greater than 1kHz, the same accelerometer sample may be output to the - * FIFO, DMP, and sensor registers more than once. - * - *
- *          |   ACCELEROMETER    |           GYROSCOPE
- * DLPF_CFG | Bandwidth | Delay  | Bandwidth | Delay  | Sample Rate
- * ---------+-----------+--------+-----------+--------+-------------
- * 0        | 260Hz     | 0ms    | 256Hz     | 0.98ms | 8kHz
- * 1        | 184Hz     | 2.0ms  | 188Hz     | 1.9ms  | 1kHz
- * 2        | 94Hz      | 3.0ms  | 98Hz      | 2.8ms  | 1kHz
- * 3        | 44Hz      | 4.9ms  | 42Hz      | 4.8ms  | 1kHz
- * 4        | 21Hz      | 8.5ms  | 20Hz      | 8.3ms  | 1kHz
- * 5        | 10Hz      | 13.8ms | 10Hz      | 13.4ms | 1kHz
- * 6        | 5Hz       | 19.0ms | 5Hz       | 18.6ms | 1kHz
- * 7        |   -- Reserved --   |   -- Reserved --   | Reserved
- * 
- * - * @return DLFP configuration - * @see MPU6050_RA_CONFIG - * @see MPU6050_CFG_DLPF_CFG_BIT - * @see MPU6050_CFG_DLPF_CFG_LENGTH - */ -uint8_t MPU6050_getDLPFMode() { - I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_DLPF_CFG_BIT, MPU6050_CFG_DLPF_CFG_LENGTH, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set digital low-pass filter configuration. - * @param mode New DLFP configuration setting - * @see getDLPFBandwidth() - * @see MPU6050_DLPF_BW_256 - * @see MPU6050_RA_CONFIG - * @see MPU6050_CFG_DLPF_CFG_BIT - * @see MPU6050_CFG_DLPF_CFG_LENGTH - */ -void MPU6050_setDLPFMode(uint8_t mode) { - I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_DLPF_CFG_BIT, MPU6050_CFG_DLPF_CFG_LENGTH, mode); -} - -// GYRO_CONFIG register - -/** Get full-scale gyroscope range. - * The FS_SEL parameter allows setting the full-scale range of the gyro sensors, - * as described in the table below. - * - *
- * 0 = +/- 250 degrees/sec
- * 1 = +/- 500 degrees/sec
- * 2 = +/- 1000 degrees/sec
- * 3 = +/- 2000 degrees/sec
- * 
- * - * @return Current full-scale gyroscope range setting - * @see MPU6050_GYRO_FS_250 - * @see MPU6050_RA_GYRO_CONFIG - * @see MPU6050_GCONFIG_FS_SEL_BIT - * @see MPU6050_GCONFIG_FS_SEL_LENGTH - */ -uint8_t MPU6050_getFullScaleGyroRange() { - I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set full-scale gyroscope range. - * @param range New full-scale gyroscope range value - * @see getFullScaleRange() - * @see MPU6050_GYRO_FS_250 - * @see MPU6050_RA_GYRO_CONFIG - * @see MPU6050_GCONFIG_FS_SEL_BIT - * @see MPU6050_GCONFIG_FS_SEL_LENGTH - */ -void MPU6050_setFullScaleGyroRange(uint8_t range) { - I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, range); -} - -// ACCEL_CONFIG register - -/** Get self-test enabled setting for accelerometer X axis. - * @return Self-test enabled value - * @see MPU6050_RA_ACCEL_CONFIG - */ -bool MPU6050_getAccelXSelfTest() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_XA_ST_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Get self-test enabled setting for accelerometer X axis. - * @param enabled Self-test enabled value - * @see MPU6050_RA_ACCEL_CONFIG - */ -void MPU6050_setAccelXSelfTest(bool enabled) { - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_XA_ST_BIT, enabled); -} -/** Get self-test enabled value for accelerometer Y axis. - * @return Self-test enabled value - * @see MPU6050_RA_ACCEL_CONFIG - */ -bool MPU6050_getAccelYSelfTest() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_YA_ST_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Get self-test enabled value for accelerometer Y axis. - * @param enabled Self-test enabled value - * @see MPU6050_RA_ACCEL_CONFIG - */ -void MPU6050_setAccelYSelfTest(bool enabled) { - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_YA_ST_BIT, enabled); -} -/** Get self-test enabled value for accelerometer Z axis. - * @return Self-test enabled value - * @see MPU6050_RA_ACCEL_CONFIG - */ -bool MPU6050_getAccelZSelfTest() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ZA_ST_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set self-test enabled value for accelerometer Z axis. - * @param enabled Self-test enabled value - * @see MPU6050_RA_ACCEL_CONFIG - */ -void MPU6050_setAccelZSelfTest(bool enabled) { - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ZA_ST_BIT, enabled); -} -/** Get full-scale accelerometer range. - * The FS_SEL parameter allows setting the full-scale range of the accelerometer - * sensors, as described in the table below. - * - *
- * 0 = +/- 2g
- * 1 = +/- 4g
- * 2 = +/- 8g
- * 3 = +/- 16g
- * 
- * - * @return Current full-scale accelerometer range setting - * @see MPU6050_ACCEL_FS_2 - * @see MPU6050_RA_ACCEL_CONFIG - * @see MPU6050_ACONFIG_AFS_SEL_BIT - * @see MPU6050_ACONFIG_AFS_SEL_LENGTH - */ -uint8_t MPU6050_getFullScaleAccelRange() { - I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set full-scale accelerometer range. - * @param range New full-scale accelerometer range setting - * @see getFullScaleAccelRange() - */ -void MPU6050_setFullScaleAccelRange(uint8_t range) { - I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, range); -} -/** Get the high-pass filter configuration. - * The DHPF is a filter module in the path leading to motion detectors (Free - * Fall, Motion threshold, and Zero Motion). The high pass filter output is not - * available to the data registers (see Figure in Section 8 of the MPU-6000/ - * MPU-6050 Product Specification document). - * - * The high pass filter has three modes: - * - *
- *    Reset: The filter output settles to zero within one sample. This
- *           effectively disables the high pass filter. This mode may be toggled
- *           to quickly settle the filter.
- *
- *    On:    The high pass filter will pass signals above the cut off frequency.
- *
- *    Hold:  When triggered, the filter holds the present sample. The filter
- *           output will be the difference between the input sample and the held
- *           sample.
- * 
- * - *
- * ACCEL_HPF | Filter Mode | Cut-off Frequency
- * ----------+-------------+------------------
- * 0         | Reset       | None
- * 1         | On          | 5Hz
- * 2         | On          | 2.5Hz
- * 3         | On          | 1.25Hz
- * 4         | On          | 0.63Hz
- * 7         | Hold        | None
- * 
- * - * @return Current high-pass filter configuration - * @see MPU6050_DHPF_RESET - * @see MPU6050_RA_ACCEL_CONFIG - */ -uint8_t MPU6050_getDHPFMode() { - I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ACCEL_HPF_BIT, MPU6050_ACONFIG_ACCEL_HPF_LENGTH, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set the high-pass filter configuration. - * @param bandwidth New high-pass filter configuration - * @see setDHPFMode() - * @see MPU6050_DHPF_RESET - * @see MPU6050_RA_ACCEL_CONFIG - */ -void MPU6050_setDHPFMode(uint8_t bandwidth) { - I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ACCEL_HPF_BIT, MPU6050_ACONFIG_ACCEL_HPF_LENGTH, bandwidth); -} - -// FF_THR register - -/** Get free-fall event acceleration threshold. - * This register configures the detection threshold for Free Fall event - * detection. The unit of FF_THR is 1LSB = 2mg. Free Fall is detected when the - * absolute value of the accelerometer measurements for the three axes are each - * less than the detection threshold. This condition increments the Free Fall - * duration counter (Register 30). The Free Fall interrupt is triggered when the - * Free Fall duration counter reaches the time specified in FF_DUR. - * - * For more details on the Free Fall detection interrupt, see Section 8.2 of the - * MPU-6000/MPU-6050 Product Specification document as well as Registers 56 and - * 58 of this document. - * - * @return Current free-fall acceleration threshold value (LSB = 2mg) - * @see MPU6050_RA_FF_THR - */ -uint8_t MPU6050_getFreefallDetectionThreshold() { - I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_FF_THR, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Get free-fall event acceleration threshold. - * @param threshold New free-fall acceleration threshold value (LSB = 2mg) - * @see getFreefallDetectionThreshold() - * @see MPU6050_RA_FF_THR - */ -void MPU6050_setFreefallDetectionThreshold(uint8_t threshold) { - I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_FF_THR, threshold); -} - -// FF_DUR register - -/** Get free-fall event duration threshold. - * This register configures the duration counter threshold for Free Fall event - * detection. The duration counter ticks at 1kHz, therefore FF_DUR has a unit - * of 1 LSB = 1 ms. - * - * The Free Fall duration counter increments while the absolute value of the - * accelerometer measurements are each less than the detection threshold - * (Register 29). The Free Fall interrupt is triggered when the Free Fall - * duration counter reaches the time specified in this register. - * - * For more details on the Free Fall detection interrupt, see Section 8.2 of - * the MPU-6000/MPU-6050 Product Specification document as well as Registers 56 - * and 58 of this document. - * - * @return Current free-fall duration threshold value (LSB = 1ms) - * @see MPU6050_RA_FF_DUR - */ -uint8_t MPU6050_getFreefallDetectionDuration() { - I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_FF_DUR, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Get free-fall event duration threshold. - * @param duration New free-fall duration threshold value (LSB = 1ms) - * @see getFreefallDetectionDuration() - * @see MPU6050_RA_FF_DUR - */ -void MPU6050_setFreefallDetectionDuration(uint8_t duration) { - I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_FF_DUR, duration); -} - -// MOT_THR register - -/** Get motion detection event acceleration threshold. - * This register configures the detection threshold for Motion interrupt - * generation. The unit of MOT_THR is 1LSB = 2mg. Motion is detected when the - * absolute value of any of the accelerometer measurements exceeds this Motion - * detection threshold. This condition increments the Motion detection duration - * counter (Register 32). The Motion detection interrupt is triggered when the - * Motion Detection counter reaches the time count specified in MOT_DUR - * (Register 32). - * - * The Motion interrupt will indicate the axis and polarity of detected motion - * in MOT_DETECT_STATUS (Register 97). - * - * For more details on the Motion detection interrupt, see Section 8.3 of the - * MPU-6000/MPU-6050 Product Specification document as well as Registers 56 and - * 58 of this document. - * - * @return Current motion detection acceleration threshold value (LSB = 2mg) - * @see MPU6050_RA_MOT_THR - */ -uint8_t MPU6050_getMotionDetectionThreshold() { - I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_MOT_THR, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set free-fall event acceleration threshold. - * @param threshold New motion detection acceleration threshold value (LSB = 2mg) - * @see getMotionDetectionThreshold() - * @see MPU6050_RA_MOT_THR - */ -void MPU6050_setMotionDetectionThreshold(uint8_t threshold) { - I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_MOT_THR, threshold); -} - -// MOT_DUR register - -/** Get motion detection event duration threshold. - * This register configures the duration counter threshold for Motion interrupt - * generation. The duration counter ticks at 1 kHz, therefore MOT_DUR has a unit - * of 1LSB = 1ms. The Motion detection duration counter increments when the - * absolute value of any of the accelerometer measurements exceeds the Motion - * detection threshold (Register 31). The Motion detection interrupt is - * triggered when the Motion detection counter reaches the time count specified - * in this register. - * - * For more details on the Motion detection interrupt, see Section 8.3 of the - * MPU-6000/MPU-6050 Product Specification document. - * - * @return Current motion detection duration threshold value (LSB = 1ms) - * @see MPU6050_RA_MOT_DUR - */ -uint8_t MPU6050_getMotionDetectionDuration() { - I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_MOT_DUR, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set motion detection event duration threshold. - * @param duration New motion detection duration threshold value (LSB = 1ms) - * @see getMotionDetectionDuration() - * @see MPU6050_RA_MOT_DUR - */ -void MPU6050_setMotionDetectionDuration(uint8_t duration) { - I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_MOT_DUR, duration); -} - -// ZRMOT_THR register - -/** Get zero motion detection event acceleration threshold. - * This register configures the detection threshold for Zero Motion interrupt - * generation. The unit of ZRMOT_THR is 1LSB = 2mg. Zero Motion is detected when - * the absolute value of the accelerometer measurements for the 3 axes are each - * less than the detection threshold. This condition increments the Zero Motion - * duration counter (Register 34). The Zero Motion interrupt is triggered when - * the Zero Motion duration counter reaches the time count specified in - * ZRMOT_DUR (Register 34). - * - * Unlike Free Fall or Motion detection, Zero Motion detection triggers an - * interrupt both when Zero Motion is first detected and when Zero Motion is no - * longer detected. - * - * When a zero motion event is detected, a Zero Motion Status will be indicated - * in the MOT_DETECT_STATUS register (Register 97). When a motion-to-zero-motion - * condition is detected, the status bit is set to 1. When a zero-motion-to- - * motion condition is detected, the status bit is set to 0. - * - * For more details on the Zero Motion detection interrupt, see Section 8.4 of - * the MPU-6000/MPU-6050 Product Specification document as well as Registers 56 - * and 58 of this document. - * - * @return Current zero motion detection acceleration threshold value (LSB = 2mg) - * @see MPU6050_RA_ZRMOT_THR - */ -uint8_t MPU6050_getZeroMotionDetectionThreshold() { - I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_ZRMOT_THR, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set zero motion detection event acceleration threshold. - * @param threshold New zero motion detection acceleration threshold value (LSB = 2mg) - * @see getZeroMotionDetectionThreshold() - * @see MPU6050_RA_ZRMOT_THR - */ -void MPU6050_setZeroMotionDetectionThreshold(uint8_t threshold) { - I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_ZRMOT_THR, threshold); -} - -// ZRMOT_DUR register - -/** Get zero motion detection event duration threshold. - * This register configures the duration counter threshold for Zero Motion - * interrupt generation. The duration counter ticks at 16 Hz, therefore - * ZRMOT_DUR has a unit of 1 LSB = 64 ms. The Zero Motion duration counter - * increments while the absolute value of the accelerometer measurements are - * each less than the detection threshold (Register 33). The Zero Motion - * interrupt is triggered when the Zero Motion duration counter reaches the time - * count specified in this register. - * - * For more details on the Zero Motion detection interrupt, see Section 8.4 of - * the MPU-6000/MPU-6050 Product Specification document, as well as Registers 56 - * and 58 of this document. - * - * @return Current zero motion detection duration threshold value (LSB = 64ms) - * @see MPU6050_RA_ZRMOT_DUR - */ -uint8_t MPU6050_getZeroMotionDetectionDuration() { - I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_ZRMOT_DUR, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set zero motion detection event duration threshold. - * @param duration New zero motion detection duration threshold value (LSB = 1ms) - * @see getZeroMotionDetectionDuration() - * @see MPU6050_RA_ZRMOT_DUR - */ -void MPU6050_setZeroMotionDetectionDuration(uint8_t duration) { - I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_ZRMOT_DUR, duration); -} - -// FIFO_EN register - -/** Get temperature FIFO enabled value. - * When set to 1, this bit enables TEMP_OUT_H and TEMP_OUT_L (Registers 65 and - * 66) to be written into the FIFO mpu6050.buffer. - * @return Current temperature FIFO enabled value - * @see MPU6050_RA_FIFO_EN - */ -bool MPU6050_getTempFIFOEnabled() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_TEMP_FIFO_EN_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set temperature FIFO enabled value. - * @param enabled New temperature FIFO enabled value - * @see getTempFIFOEnabled() - * @see MPU6050_RA_FIFO_EN - */ -void MPU6050_setTempFIFOEnabled(bool enabled) { - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_TEMP_FIFO_EN_BIT, enabled); -} -/** Get gyroscope X-axis FIFO enabled value. - * When set to 1, this bit enables GYRO_XOUT_H and GYRO_XOUT_L (Registers 67 and - * 68) to be written into the FIFO mpu6050.buffer. - * @return Current gyroscope X-axis FIFO enabled value - * @see MPU6050_RA_FIFO_EN - */ -bool MPU6050_getXGyroFIFOEnabled() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_XG_FIFO_EN_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set gyroscope X-axis FIFO enabled value. - * @param enabled New gyroscope X-axis FIFO enabled value - * @see getXGyroFIFOEnabled() - * @see MPU6050_RA_FIFO_EN - */ -void MPU6050_setXGyroFIFOEnabled(bool enabled) { - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_XG_FIFO_EN_BIT, enabled); -} -/** Get gyroscope Y-axis FIFO enabled value. - * When set to 1, this bit enables GYRO_YOUT_H and GYRO_YOUT_L (Registers 69 and - * 70) to be written into the FIFO mpu6050.buffer. - * @return Current gyroscope Y-axis FIFO enabled value - * @see MPU6050_RA_FIFO_EN - */ -bool MPU6050_getYGyroFIFOEnabled() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_YG_FIFO_EN_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set gyroscope Y-axis FIFO enabled value. - * @param enabled New gyroscope Y-axis FIFO enabled value - * @see getYGyroFIFOEnabled() - * @see MPU6050_RA_FIFO_EN - */ -void MPU6050_setYGyroFIFOEnabled(bool enabled) { - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_YG_FIFO_EN_BIT, enabled); -} -/** Get gyroscope Z-axis FIFO enabled value. - * When set to 1, this bit enables GYRO_ZOUT_H and GYRO_ZOUT_L (Registers 71 and - * 72) to be written into the FIFO mpu6050.buffer. - * @return Current gyroscope Z-axis FIFO enabled value - * @see MPU6050_RA_FIFO_EN - */ -bool MPU6050_getZGyroFIFOEnabled() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_ZG_FIFO_EN_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set gyroscope Z-axis FIFO enabled value. - * @param enabled New gyroscope Z-axis FIFO enabled value - * @see getZGyroFIFOEnabled() - * @see MPU6050_RA_FIFO_EN - */ -void MPU6050_setZGyroFIFOEnabled(bool enabled) { - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_ZG_FIFO_EN_BIT, enabled); -} -/** Get accelerometer FIFO enabled value. - * When set to 1, this bit enables ACCEL_XOUT_H, ACCEL_XOUT_L, ACCEL_YOUT_H, - * ACCEL_YOUT_L, ACCEL_ZOUT_H, and ACCEL_ZOUT_L (Registers 59 to 64) to be - * written into the FIFO mpu6050.buffer. - * @return Current accelerometer FIFO enabled value - * @see MPU6050_RA_FIFO_EN - */ -bool MPU6050_getAccelFIFOEnabled() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_ACCEL_FIFO_EN_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set accelerometer FIFO enabled value. - * @param enabled New accelerometer FIFO enabled value - * @see getAccelFIFOEnabled() - * @see MPU6050_RA_FIFO_EN - */ -void MPU6050_setAccelFIFOEnabled(bool enabled) { - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_ACCEL_FIFO_EN_BIT, enabled); -} -/** Get Slave 2 FIFO enabled value. - * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) - * associated with Slave 2 to be written into the FIFO mpu6050.buffer. - * @return Current Slave 2 FIFO enabled value - * @see MPU6050_RA_FIFO_EN - */ -bool MPU6050_getSlave2FIFOEnabled() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV2_FIFO_EN_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set Slave 2 FIFO enabled value. - * @param enabled New Slave 2 FIFO enabled value - * @see getSlave2FIFOEnabled() - * @see MPU6050_RA_FIFO_EN - */ -void MPU6050_setSlave2FIFOEnabled(bool enabled) { - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV2_FIFO_EN_BIT, enabled); -} -/** Get Slave 1 FIFO enabled value. - * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) - * associated with Slave 1 to be written into the FIFO mpu6050.buffer. - * @return Current Slave 1 FIFO enabled value - * @see MPU6050_RA_FIFO_EN - */ -bool MPU6050_getSlave1FIFOEnabled() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV1_FIFO_EN_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set Slave 1 FIFO enabled value. - * @param enabled New Slave 1 FIFO enabled value - * @see getSlave1FIFOEnabled() - * @see MPU6050_RA_FIFO_EN - */ -void MPU6050_setSlave1FIFOEnabled(bool enabled) { - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV1_FIFO_EN_BIT, enabled); -} -/** Get Slave 0 FIFO enabled value. - * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) - * associated with Slave 0 to be written into the FIFO mpu6050.buffer. - * @return Current Slave 0 FIFO enabled value - * @see MPU6050_RA_FIFO_EN - */ -bool MPU6050_getSlave0FIFOEnabled() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV0_FIFO_EN_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set Slave 0 FIFO enabled value. - * @param enabled New Slave 0 FIFO enabled value - * @see getSlave0FIFOEnabled() - * @see MPU6050_RA_FIFO_EN - */ -void MPU6050_setSlave0FIFOEnabled(bool enabled) { - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV0_FIFO_EN_BIT, enabled); -} - -// I2C_MST_CTRL register - -/** Get multi-master enabled value. - * Multi-master capability allows multiple I2C masters to operate on the same - * bus. In circuits where multi-master capability is required, set MULT_MST_EN - * to 1. This will increase current drawn by approximately 30uA. - * - * In circuits where multi-master capability is required, the state of the I2C - * bus must always be monitored by each separate I2C Master. Before an I2C - * Master can assume arbitration of the bus, it must first confirm that no other - * I2C Master has arbitration of the bus. When MULT_MST_EN is set to 1, the - * MPU-60X0's bus arbitration detection logic is turned on, enabling it to - * detect when the bus is available. - * - * @return Current multi-master enabled value - * @see MPU6050_RA_I2C_MST_CTRL - */ -bool MPU6050_getMultiMasterEnabled() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_MULT_MST_EN_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set multi-master enabled value. - * @param enabled New multi-master enabled value - * @see getMultiMasterEnabled() - * @see MPU6050_RA_I2C_MST_CTRL - */ -void MPU6050_setMultiMasterEnabled(bool enabled) { - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_MULT_MST_EN_BIT, enabled); -} -/** Get wait-for-external-sensor-data enabled value. - * When the WAIT_FOR_ES bit is set to 1, the Data Ready interrupt will be - * delayed until External Sensor data from the Slave Devices are loaded into the - * EXT_SENS_DATA registers. This is used to ensure that both the internal sensor - * data (i.e. from gyro and accel) and external sensor data have been loaded to - * their respective data registers (i.e. the data is synced) when the Data Ready - * interrupt is triggered. - * - * @return Current wait-for-external-sensor-data enabled value - * @see MPU6050_RA_I2C_MST_CTRL - */ -bool MPU6050_getWaitForExternalSensorEnabled() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_WAIT_FOR_ES_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set wait-for-external-sensor-data enabled value. - * @param enabled New wait-for-external-sensor-data enabled value - * @see getWaitForExternalSensorEnabled() - * @see MPU6050_RA_I2C_MST_CTRL - */ -void MPU6050_setWaitForExternalSensorEnabled(bool enabled) { - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_WAIT_FOR_ES_BIT, enabled); -} -/** Get Slave 3 FIFO enabled value. - * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) - * associated with Slave 3 to be written into the FIFO mpu6050.buffer. - * @return Current Slave 3 FIFO enabled value - * @see MPU6050_RA_MST_CTRL - */ -bool MPU6050_getSlave3FIFOEnabled() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_SLV_3_FIFO_EN_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set Slave 3 FIFO enabled value. - * @param enabled New Slave 3 FIFO enabled value - * @see getSlave3FIFOEnabled() - * @see MPU6050_RA_MST_CTRL - */ -void MPU6050_setSlave3FIFOEnabled(bool enabled) { - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_SLV_3_FIFO_EN_BIT, enabled); -} -/** Get slave read/write transition enabled value. - * The I2C_MST_P_NSR bit configures the I2C Master's transition from one slave - * read to the next slave read. If the bit equals 0, there will be a restart - * between reads. If the bit equals 1, there will be a stop followed by a start - * of the following read. When a write transaction follows a read transaction, - * the stop followed by a start of the successive write will be always used. - * - * @return Current slave read/write transition enabled value - * @see MPU6050_RA_I2C_MST_CTRL - */ -bool MPU6050_getSlaveReadWriteTransitionEnabled() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_P_NSR_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set slave read/write transition enabled value. - * @param enabled New slave read/write transition enabled value - * @see getSlaveReadWriteTransitionEnabled() - * @see MPU6050_RA_I2C_MST_CTRL - */ -void MPU6050_setSlaveReadWriteTransitionEnabled(bool enabled) { - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_P_NSR_BIT, enabled); -} -/** Get I2C master clock speed. - * I2C_MST_CLK is a 4 bit unsigned value which configures a divider on the - * MPU-60X0 internal 8MHz clock. It sets the I2C master clock speed according to - * the following table: - * - *
- * I2C_MST_CLK | I2C Master Clock Speed | 8MHz Clock Divider
- * ------------+------------------------+-------------------
- * 0           | 348kHz                 | 23
- * 1           | 333kHz                 | 24
- * 2           | 320kHz                 | 25
- * 3           | 308kHz                 | 26
- * 4           | 296kHz                 | 27
- * 5           | 286kHz                 | 28
- * 6           | 276kHz                 | 29
- * 7           | 267kHz                 | 30
- * 8           | 258kHz                 | 31
- * 9           | 500kHz                 | 16
- * 10          | 471kHz                 | 17
- * 11          | 444kHz                 | 18
- * 12          | 421kHz                 | 19
- * 13          | 400kHz                 | 20
- * 14          | 381kHz                 | 21
- * 15          | 364kHz                 | 22
- * 
- * - * @return Current I2C master clock speed - * @see MPU6050_RA_I2C_MST_CTRL - */ -uint8_t MPU6050_getMasterClockSpeed() { - I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_CLK_BIT, MPU6050_I2C_MST_CLK_LENGTH, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set I2C master clock speed. - * @reparam speed Current I2C master clock speed - * @see MPU6050_RA_I2C_MST_CTRL - */ -void MPU6050_setMasterClockSpeed(uint8_t speed) { - I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_CLK_BIT, MPU6050_I2C_MST_CLK_LENGTH, speed); -} - -// I2C_SLV* registers (Slave 0-3) - -/** Get the I2C address of the specified slave (0-3). - * Note that Bit 7 (MSB) controls read/write mode. If Bit 7 is set, it's a read - * operation, and if it is cleared, then it's a write operation. The remaining - * bits (6-0) are the 7-bit device address of the slave device. - * - * In read mode, the result of the read is placed in the lowest available - * EXT_SENS_DATA register. For further information regarding the allocation of - * read results, please refer to the EXT_SENS_DATA register description - * (Registers 73 - 96). - * - * The MPU-6050 supports a total of five slaves, but Slave 4 has unique - * characteristics, and so it has its own functions (getSlave4* and setSlave4*). - * - * I2C data transactions are performed at the Sample Rate, as defined in - * Register 25. The user is responsible for ensuring that I2C data transactions - * to and from each enabled Slave can be completed within a single period of the - * Sample Rate. - * - * The I2C slave access rate can be reduced relative to the Sample Rate. This - * reduced access rate is determined by I2C_MST_DLY (Register 52). Whether a - * slave's access rate is reduced relative to the Sample Rate is determined by - * I2C_MST_DELAY_CTRL (Register 103). - * - * The processing order for the slaves is fixed. The sequence followed for - * processing the slaves is Slave 0, Slave 1, Slave 2, Slave 3 and Slave 4. If a - * particular Slave is disabled it will be skipped. - * - * Each slave can either be accessed at the sample rate or at a reduced sample - * rate. In a case where some slaves are accessed at the Sample Rate and some - * slaves are accessed at the reduced rate, the sequence of accessing the slaves - * (Slave 0 to Slave 4) is still followed. However, the reduced rate slaves will - * be skipped if their access rate dictates that they should not be accessed - * during that particular cycle. For further information regarding the reduced - * access rate, please refer to Register 52. Whether a slave is accessed at the - * Sample Rate or at the reduced rate is determined by the Delay Enable bits in - * Register 103. - * - * @param num Slave number (0-3) - * @return Current address for specified slave - * @see MPU6050_RA_I2C_SLV0_ADDR - */ -uint8_t MPU6050_getSlaveAddress(uint8_t num) { - if (num > 3) return 0; - I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_ADDR + num*3, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set the I2C address of the specified slave (0-3). - * @param num Slave number (0-3) - * @param address New address for specified slave - * @see getSlaveAddress() - * @see MPU6050_RA_I2C_SLV0_ADDR - */ -void MPU6050_setSlaveAddress(uint8_t num, uint8_t address) { - if (num > 3) return; - I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_ADDR + num*3, address); -} -/** Get the active internal register for the specified slave (0-3). - * Read/write operations for this slave will be done to whatever internal - * register address is stored in this MPU register. - * - * The MPU-6050 supports a total of five slaves, but Slave 4 has unique - * characteristics, and so it has its own functions. - * - * @param num Slave number (0-3) - * @return Current active register for specified slave - * @see MPU6050_RA_I2C_SLV0_REG - */ -uint8_t MPU6050_getSlaveRegister(uint8_t num) { - if (num > 3) return 0; - I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_REG + num*3, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set the active internal register for the specified slave (0-3). - * @param num Slave number (0-3) - * @param reg New active register for specified slave - * @see getSlaveRegister() - * @see MPU6050_RA_I2C_SLV0_REG - */ -void MPU6050_setSlaveRegister(uint8_t num, uint8_t reg) { - if (num > 3) return; - I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_REG + num*3, reg); -} -/** Get the enabled value for the specified slave (0-3). - * When set to 1, this bit enables Slave 0 for data transfer operations. When - * cleared to 0, this bit disables Slave 0 from data transfer operations. - * @param num Slave number (0-3) - * @return Current enabled value for specified slave - * @see MPU6050_RA_I2C_SLV0_CTRL - */ -bool MPU6050_getSlaveEnabled(uint8_t num) { - if (num > 3) return 0; - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_EN_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set the enabled value for the specified slave (0-3). - * @param num Slave number (0-3) - * @param enabled New enabled value for specified slave - * @see getSlaveEnabled() - * @see MPU6050_RA_I2C_SLV0_CTRL - */ -void MPU6050_setSlaveEnabled(uint8_t num, bool enabled) { - if (num > 3) return; - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_EN_BIT, enabled); -} -/** Get word pair byte-swapping enabled for the specified slave (0-3). - * When set to 1, this bit enables byte swapping. When byte swapping is enabled, - * the high and low bytes of a word pair are swapped. Please refer to - * I2C_SLV0_GRP for the pairing convention of the word pairs. When cleared to 0, - * bytes transferred to and from Slave 0 will be written to EXT_SENS_DATA - * registers in the order they were transferred. - * - * @param num Slave number (0-3) - * @return Current word pair byte-swapping enabled value for specified slave - * @see MPU6050_RA_I2C_SLV0_CTRL - */ -bool MPU6050_getSlaveWordByteSwap(uint8_t num) { - if (num > 3) return 0; - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_BYTE_SW_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set word pair byte-swapping enabled for the specified slave (0-3). - * @param num Slave number (0-3) - * @param enabled New word pair byte-swapping enabled value for specified slave - * @see getSlaveWordByteSwap() - * @see MPU6050_RA_I2C_SLV0_CTRL - */ -void MPU6050_setSlaveWordByteSwap(uint8_t num, bool enabled) { - if (num > 3) return; - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_BYTE_SW_BIT, enabled); -} -/** Get write mode for the specified slave (0-3). - * When set to 1, the transaction will read or write data only. When cleared to - * 0, the transaction will write a register address prior to reading or writing - * data. This should equal 0 when specifying the register address within the - * Slave device to/from which the ensuing data transaction will take place. - * - * @param num Slave number (0-3) - * @return Current write mode for specified slave (0 = register address + data, 1 = data only) - * @see MPU6050_RA_I2C_SLV0_CTRL - */ -bool MPU6050_getSlaveWriteMode(uint8_t num) { - if (num > 3) return 0; - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_REG_DIS_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set write mode for the specified slave (0-3). - * @param num Slave number (0-3) - * @param mode New write mode for specified slave (0 = register address + data, 1 = data only) - * @see getSlaveWriteMode() - * @see MPU6050_RA_I2C_SLV0_CTRL - */ -void MPU6050_setSlaveWriteMode(uint8_t num, bool mode) { - if (num > 3) return; - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_REG_DIS_BIT, mode); -} -/** Get word pair grouping order offset for the specified slave (0-3). - * This sets specifies the grouping order of word pairs received from registers. - * When cleared to 0, bytes from register addresses 0 and 1, 2 and 3, etc (even, - * then odd register addresses) are paired to form a word. When set to 1, bytes - * from register addresses are paired 1 and 2, 3 and 4, etc. (odd, then even - * register addresses) are paired to form a word. - * - * @param num Slave number (0-3) - * @return Current word pair grouping order offset for specified slave - * @see MPU6050_RA_I2C_SLV0_CTRL - */ -bool MPU6050_getSlaveWordGroupOffset(uint8_t num) { - if (num > 3) return 0; - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_GRP_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set word pair grouping order offset for the specified slave (0-3). - * @param num Slave number (0-3) - * @param enabled New word pair grouping order offset for specified slave - * @see getSlaveWordGroupOffset() - * @see MPU6050_RA_I2C_SLV0_CTRL - */ -void MPU6050_setSlaveWordGroupOffset(uint8_t num, bool enabled) { - if (num > 3) return; - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_GRP_BIT, enabled); -} -/** Get number of bytes to read for the specified slave (0-3). - * Specifies the number of bytes transferred to and from Slave 0. Clearing this - * bit to 0 is equivalent to disabling the register by writing 0 to I2C_SLV0_EN. - * @param num Slave number (0-3) - * @return Number of bytes to read for specified slave - * @see MPU6050_RA_I2C_SLV0_CTRL - */ -uint8_t MPU6050_getSlaveDataLength(uint8_t num) { - if (num > 3) return 0; - I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_LEN_BIT, MPU6050_I2C_SLV_LEN_LENGTH, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set number of bytes to read for the specified slave (0-3). - * @param num Slave number (0-3) - * @param length Number of bytes to read for specified slave - * @see getSlaveDataLength() - * @see MPU6050_RA_I2C_SLV0_CTRL - */ -void MPU6050_setSlaveDataLength(uint8_t num, uint8_t length) { - if (num > 3) return; - I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_LEN_BIT, MPU6050_I2C_SLV_LEN_LENGTH, length); -} - -// I2C_SLV* registers (Slave 4) - -/** Get the I2C address of Slave 4. - * Note that Bit 7 (MSB) controls read/write mode. If Bit 7 is set, it's a read - * operation, and if it is cleared, then it's a write operation. The remaining - * bits (6-0) are the 7-bit device address of the slave device. - * - * @return Current address for Slave 4 - * @see getSlaveAddress() - * @see MPU6050_RA_I2C_SLV4_ADDR - */ -uint8_t MPU6050_getSlave4Address() { - I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_ADDR, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set the I2C address of Slave 4. - * @param address New address for Slave 4 - * @see getSlave4Address() - * @see MPU6050_RA_I2C_SLV4_ADDR - */ -void MPU6050_setSlave4Address(uint8_t address) { - I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_ADDR, address); -} -/** Get the active internal register for the Slave 4. - * Read/write operations for this slave will be done to whatever internal - * register address is stored in this MPU register. - * - * @return Current active register for Slave 4 - * @see MPU6050_RA_I2C_SLV4_REG - */ -uint8_t MPU6050_getSlave4Register() { - I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_REG, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set the active internal register for Slave 4. - * @param reg New active register for Slave 4 - * @see getSlave4Register() - * @see MPU6050_RA_I2C_SLV4_REG - */ -void MPU6050_setSlave4Register(uint8_t reg) { - I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_REG, reg); -} -/** Set new byte to write to Slave 4. - * This register stores the data to be written into the Slave 4. If I2C_SLV4_RW - * is set 1 (set to read), this register has no effect. - * @param data New byte to write to Slave 4 - * @see MPU6050_RA_I2C_SLV4_DO - */ -void MPU6050_setSlave4OutputByte(uint8_t data) { - I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_DO, data); -} -/** Get the enabled value for the Slave 4. - * When set to 1, this bit enables Slave 4 for data transfer operations. When - * cleared to 0, this bit disables Slave 4 from data transfer operations. - * @return Current enabled value for Slave 4 - * @see MPU6050_RA_I2C_SLV4_CTRL - */ -bool MPU6050_getSlave4Enabled() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_EN_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set the enabled value for Slave 4. - * @param enabled New enabled value for Slave 4 - * @see getSlave4Enabled() - * @see MPU6050_RA_I2C_SLV4_CTRL - */ -void MPU6050_setSlave4Enabled(bool enabled) { - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_EN_BIT, enabled); -} -/** Get the enabled value for Slave 4 transaction interrupts. - * When set to 1, this bit enables the generation of an interrupt signal upon - * completion of a Slave 4 transaction. When cleared to 0, this bit disables the - * generation of an interrupt signal upon completion of a Slave 4 transaction. - * The interrupt status can be observed in Register 54. - * - * @return Current enabled value for Slave 4 transaction interrupts. - * @see MPU6050_RA_I2C_SLV4_CTRL - */ -bool MPU6050_getSlave4InterruptEnabled() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_INT_EN_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set the enabled value for Slave 4 transaction interrupts. - * @param enabled New enabled value for Slave 4 transaction interrupts. - * @see getSlave4InterruptEnabled() - * @see MPU6050_RA_I2C_SLV4_CTRL - */ -void MPU6050_setSlave4InterruptEnabled(bool enabled) { - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_INT_EN_BIT, enabled); -} -/** Get write mode for Slave 4. - * When set to 1, the transaction will read or write data only. When cleared to - * 0, the transaction will write a register address prior to reading or writing - * data. This should equal 0 when specifying the register address within the - * Slave device to/from which the ensuing data transaction will take place. - * - * @return Current write mode for Slave 4 (0 = register address + data, 1 = data only) - * @see MPU6050_RA_I2C_SLV4_CTRL - */ -bool MPU6050_getSlave4WriteMode() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_REG_DIS_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set write mode for the Slave 4. - * @param mode New write mode for Slave 4 (0 = register address + data, 1 = data only) - * @see getSlave4WriteMode() - * @see MPU6050_RA_I2C_SLV4_CTRL - */ -void MPU6050_setSlave4WriteMode(bool mode) { - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_REG_DIS_BIT, mode); -} -/** Get Slave 4 master delay value. - * This configures the reduced access rate of I2C slaves relative to the Sample - * Rate. When a slave's access rate is decreased relative to the Sample Rate, - * the slave is accessed every: - * - * 1 / (1 + I2C_MST_DLY) samples - * - * This base Sample Rate in turn is determined by SMPLRT_DIV (register 25) and - * DLPF_CFG (register 26). Whether a slave's access rate is reduced relative to - * the Sample Rate is determined by I2C_MST_DELAY_CTRL (register 103). For - * further information regarding the Sample Rate, please refer to register 25. - * - * @return Current Slave 4 master delay value - * @see MPU6050_RA_I2C_SLV4_CTRL - */ -uint8_t MPU6050_getSlave4MasterDelay() { - I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_MST_DLY_BIT, MPU6050_I2C_SLV4_MST_DLY_LENGTH, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set Slave 4 master delay value. - * @param delay New Slave 4 master delay value - * @see getSlave4MasterDelay() - * @see MPU6050_RA_I2C_SLV4_CTRL - */ -void MPU6050_setSlave4MasterDelay(uint8_t delay) { - I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_MST_DLY_BIT, MPU6050_I2C_SLV4_MST_DLY_LENGTH, delay); -} -/** Get last available byte read from Slave 4. - * This register stores the data read from Slave 4. This field is populated - * after a read transaction. - * @return Last available byte read from to Slave 4 - * @see MPU6050_RA_I2C_SLV4_DI - */ -uint8_t MPU6050_getSlate4InputByte() { - I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV4_DI, mpu6050.buffer); - return mpu6050.buffer[0]; -} - -// I2C_MST_STATUS register - -/** Get FSYNC interrupt status. - * This bit reflects the status of the FSYNC interrupt from an external device - * into the MPU-60X0. This is used as a way to pass an external interrupt - * through the MPU-60X0 to the host application processor. When set to 1, this - * bit will cause an interrupt if FSYNC_INT_EN is asserted in INT_PIN_CFG - * (Register 55). - * @return FSYNC interrupt status - * @see MPU6050_RA_I2C_MST_STATUS - */ -bool MPU6050_getPassthroughStatus() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_PASS_THROUGH_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Get Slave 4 transaction done status. - * Automatically sets to 1 when a Slave 4 transaction has completed. This - * triggers an interrupt if the I2C_MST_INT_EN bit in the INT_ENABLE register - * (Register 56) is asserted and if the SLV_4_DONE_INT bit is asserted in the - * I2C_SLV4_CTRL register (Register 52). - * @return Slave 4 transaction done status - * @see MPU6050_RA_I2C_MST_STATUS - */ -bool MPU6050_getSlave4IsDone() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV4_DONE_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Get master arbitration lost status. - * This bit automatically sets to 1 when the I2C Master has lost arbitration of - * the auxiliary I2C bus (an error condition). This triggers an interrupt if the - * I2C_MST_INT_EN bit in the INT_ENABLE register (Register 56) is asserted. - * @return Master arbitration lost status - * @see MPU6050_RA_I2C_MST_STATUS - */ -bool MPU6050_getLostArbitration() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_LOST_ARB_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Get Slave 4 NACK status. - * This bit automatically sets to 1 when the I2C Master receives a NACK in a - * transaction with Slave 4. This triggers an interrupt if the I2C_MST_INT_EN - * bit in the INT_ENABLE register (Register 56) is asserted. - * @return Slave 4 NACK interrupt status - * @see MPU6050_RA_I2C_MST_STATUS - */ -bool MPU6050_getSlave4Nack() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV4_NACK_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Get Slave 3 NACK status. - * This bit automatically sets to 1 when the I2C Master receives a NACK in a - * transaction with Slave 3. This triggers an interrupt if the I2C_MST_INT_EN - * bit in the INT_ENABLE register (Register 56) is asserted. - * @return Slave 3 NACK interrupt status - * @see MPU6050_RA_I2C_MST_STATUS - */ -bool MPU6050_getSlave3Nack() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV3_NACK_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Get Slave 2 NACK status. - * This bit automatically sets to 1 when the I2C Master receives a NACK in a - * transaction with Slave 2. This triggers an interrupt if the I2C_MST_INT_EN - * bit in the INT_ENABLE register (Register 56) is asserted. - * @return Slave 2 NACK interrupt status - * @see MPU6050_RA_I2C_MST_STATUS - */ -bool MPU6050_getSlave2Nack() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV2_NACK_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Get Slave 1 NACK status. - * This bit automatically sets to 1 when the I2C Master receives a NACK in a - * transaction with Slave 1. This triggers an interrupt if the I2C_MST_INT_EN - * bit in the INT_ENABLE register (Register 56) is asserted. - * @return Slave 1 NACK interrupt status - * @see MPU6050_RA_I2C_MST_STATUS - */ -bool MPU6050_getSlave1Nack() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV1_NACK_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Get Slave 0 NACK status. - * This bit automatically sets to 1 when the I2C Master receives a NACK in a - * transaction with Slave 0. This triggers an interrupt if the I2C_MST_INT_EN - * bit in the INT_ENABLE register (Register 56) is asserted. - * @return Slave 0 NACK interrupt status - * @see MPU6050_RA_I2C_MST_STATUS - */ -bool MPU6050_getSlave0Nack() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV0_NACK_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} - -// INT_PIN_CFG register - -/** Get interrupt logic level mode. - * Will be set 0 for active-high, 1 for active-low. - * @return Current interrupt mode (0=active-high, 1=active-low) - * @see MPU6050_RA_INT_PIN_CFG - * @see MPU6050_INTCFG_INT_LEVEL_BIT - */ -bool MPU6050_getInterruptMode() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_LEVEL_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set interrupt logic level mode. - * @param mode New interrupt mode (0=active-high, 1=active-low) - * @see getInterruptMode() - * @see MPU6050_RA_INT_PIN_CFG - * @see MPU6050_INTCFG_INT_LEVEL_BIT - */ -void MPU6050_setInterruptMode(bool mode) { - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_LEVEL_BIT, mode); -} -/** Get interrupt drive mode. - * Will be set 0 for push-pull, 1 for open-drain. - * @return Current interrupt drive mode (0=push-pull, 1=open-drain) - * @see MPU6050_RA_INT_PIN_CFG - * @see MPU6050_INTCFG_INT_OPEN_BIT - */ -bool MPU6050_getInterruptDrive() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_OPEN_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set interrupt drive mode. - * @param drive New interrupt drive mode (0=push-pull, 1=open-drain) - * @see getInterruptDrive() - * @see MPU6050_RA_INT_PIN_CFG - * @see MPU6050_INTCFG_INT_OPEN_BIT - */ -void MPU6050_setInterruptDrive(bool drive) { - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_OPEN_BIT, drive); -} -/** Get interrupt latch mode. - * Will be set 0 for 50us-pulse, 1 for latch-until-int-cleared. - * @return Current latch mode (0=50us-pulse, 1=latch-until-int-cleared) - * @see MPU6050_RA_INT_PIN_CFG - * @see MPU6050_INTCFG_LATCH_INT_EN_BIT - */ -bool MPU6050_getInterruptLatch() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_LATCH_INT_EN_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set interrupt latch mode. - * @param latch New latch mode (0=50us-pulse, 1=latch-until-int-cleared) - * @see getInterruptLatch() - * @see MPU6050_RA_INT_PIN_CFG - * @see MPU6050_INTCFG_LATCH_INT_EN_BIT - */ -void MPU6050_setInterruptLatch(bool latch) { - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_LATCH_INT_EN_BIT, latch); -} -/** Get interrupt latch clear mode. - * Will be set 0 for status-read-only, 1 for any-register-read. - * @return Current latch clear mode (0=status-read-only, 1=any-register-read) - * @see MPU6050_RA_INT_PIN_CFG - * @see MPU6050_INTCFG_INT_RD_CLEAR_BIT - */ -bool MPU6050_getInterruptLatchClear() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_RD_CLEAR_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set interrupt latch clear mode. - * @param clear New latch clear mode (0=status-read-only, 1=any-register-read) - * @see getInterruptLatchClear() - * @see MPU6050_RA_INT_PIN_CFG - * @see MPU6050_INTCFG_INT_RD_CLEAR_BIT - */ -void MPU6050_setInterruptLatchClear(bool clear) { - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_RD_CLEAR_BIT, clear); -} -/** Get FSYNC interrupt logic level mode. - * @return Current FSYNC interrupt mode (0=active-high, 1=active-low) - * @see getFSyncInterruptMode() - * @see MPU6050_RA_INT_PIN_CFG - * @see MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT - */ -bool MPU6050_getFSyncInterruptLevel() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set FSYNC interrupt logic level mode. - * @param mode New FSYNC interrupt mode (0=active-high, 1=active-low) - * @see getFSyncInterruptMode() - * @see MPU6050_RA_INT_PIN_CFG - * @see MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT - */ -void MPU6050_setFSyncInterruptLevel(bool level) { - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT, level); -} -/** Get FSYNC pin interrupt enabled setting. - * Will be set 0 for disabled, 1 for enabled. - * @return Current interrupt enabled setting - * @see MPU6050_RA_INT_PIN_CFG - * @see MPU6050_INTCFG_FSYNC_INT_EN_BIT - */ -bool MPU6050_getFSyncInterruptEnabled() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_EN_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set FSYNC pin interrupt enabled setting. - * @param enabled New FSYNC pin interrupt enabled setting - * @see getFSyncInterruptEnabled() - * @see MPU6050_RA_INT_PIN_CFG - * @see MPU6050_INTCFG_FSYNC_INT_EN_BIT - */ -void MPU6050_setFSyncInterruptEnabled(bool enabled) { - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_EN_BIT, enabled); -} -/** Get I2C bypass enabled status. - * When this bit is equal to 1 and I2C_MST_EN (Register 106 bit[5]) is equal to - * 0, the host application processor will be able to directly access the - * auxiliary I2C bus of the MPU-60X0. When this bit is equal to 0, the host - * application processor will not be able to directly access the auxiliary I2C - * bus of the MPU-60X0 regardless of the state of I2C_MST_EN (Register 106 - * bit[5]). - * @return Current I2C bypass enabled status - * @see MPU6050_RA_INT_PIN_CFG - * @see MPU6050_INTCFG_I2C_BYPASS_EN_BIT - */ -bool MPU6050_getI2CBypassEnabled() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_I2C_BYPASS_EN_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set I2C bypass enabled status. - * When this bit is equal to 1 and I2C_MST_EN (Register 106 bit[5]) is equal to - * 0, the host application processor will be able to directly access the - * auxiliary I2C bus of the MPU-60X0. When this bit is equal to 0, the host - * application processor will not be able to directly access the auxiliary I2C - * bus of the MPU-60X0 regardless of the state of I2C_MST_EN (Register 106 - * bit[5]). - * @param enabled New I2C bypass enabled status - * @see MPU6050_RA_INT_PIN_CFG - * @see MPU6050_INTCFG_I2C_BYPASS_EN_BIT - */ -void MPU6050_setI2CBypassEnabled(bool enabled) { - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_I2C_BYPASS_EN_BIT, enabled); -} -/** Get reference clock output enabled status. - * When this bit is equal to 1, a reference clock output is provided at the - * CLKOUT pin. When this bit is equal to 0, the clock output is disabled. For - * further information regarding CLKOUT, please refer to the MPU-60X0 Product - * Specification document. - * @return Current reference clock output enabled status - * @see MPU6050_RA_INT_PIN_CFG - * @see MPU6050_INTCFG_CLKOUT_EN_BIT - */ -bool MPU6050_getClockOutputEnabled() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_CLKOUT_EN_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set reference clock output enabled status. - * When this bit is equal to 1, a reference clock output is provided at the - * CLKOUT pin. When this bit is equal to 0, the clock output is disabled. For - * further information regarding CLKOUT, please refer to the MPU-60X0 Product - * Specification document. - * @param enabled New reference clock output enabled status - * @see MPU6050_RA_INT_PIN_CFG - * @see MPU6050_INTCFG_CLKOUT_EN_BIT - */ -void MPU6050_setClockOutputEnabled(bool enabled) { - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_CLKOUT_EN_BIT, enabled); -} - -// INT_ENABLE register - -/** Get full interrupt enabled status. - * Full register byte for all interrupts, for quick reading. Each bit will be - * set 0 for disabled, 1 for enabled. - * @return Current interrupt enabled status - * @see MPU6050_RA_INT_ENABLE - * @see MPU6050_INTERRUPT_FF_BIT - **/ -uint8_t MPU6050_getIntEnabled() { - I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set full interrupt enabled status. - * Full register byte for all interrupts, for quick reading. Each bit should be - * set 0 for disabled, 1 for enabled. - * @param enabled New interrupt enabled status - * @see getIntFreefallEnabled() - * @see MPU6050_RA_INT_ENABLE - * @see MPU6050_INTERRUPT_FF_BIT - **/ -void MPU6050_setIntEnabled(uint8_t enabled) { - I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, enabled); -} -/** Get Free Fall interrupt enabled status. - * Will be set 0 for disabled, 1 for enabled. - * @return Current interrupt enabled status - * @see MPU6050_RA_INT_ENABLE - * @see MPU6050_INTERRUPT_FF_BIT - **/ -bool MPU6050_getIntFreefallEnabled() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FF_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set Free Fall interrupt enabled status. - * @param enabled New interrupt enabled status - * @see getIntFreefallEnabled() - * @see MPU6050_RA_INT_ENABLE - * @see MPU6050_INTERRUPT_FF_BIT - **/ -void MPU6050_setIntFreefallEnabled(bool enabled) { - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FF_BIT, enabled); -} -/** Get Motion Detection interrupt enabled status. - * Will be set 0 for disabled, 1 for enabled. - * @return Current interrupt enabled status - * @see MPU6050_RA_INT_ENABLE - * @see MPU6050_INTERRUPT_MOT_BIT - **/ -bool MPU6050_getIntMotionEnabled() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_MOT_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set Motion Detection interrupt enabled status. - * @param enabled New interrupt enabled status - * @see getIntMotionEnabled() - * @see MPU6050_RA_INT_ENABLE - * @see MPU6050_INTERRUPT_MOT_BIT - **/ -void MPU6050_setIntMotionEnabled(bool enabled) { - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_MOT_BIT, enabled); -} -/** Get Zero Motion Detection interrupt enabled status. - * Will be set 0 for disabled, 1 for enabled. - * @return Current interrupt enabled status - * @see MPU6050_RA_INT_ENABLE - * @see MPU6050_INTERRUPT_ZMOT_BIT - **/ -bool MPU6050_getIntZeroMotionEnabled() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_ZMOT_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set Zero Motion Detection interrupt enabled status. - * @param enabled New interrupt enabled status - * @see getIntZeroMotionEnabled() - * @see MPU6050_RA_INT_ENABLE - * @see MPU6050_INTERRUPT_ZMOT_BIT - **/ -void MPU6050_setIntZeroMotionEnabled(bool enabled) { - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_ZMOT_BIT, enabled); -} -/** Get FIFO Buffer Overflow interrupt enabled status. - * Will be set 0 for disabled, 1 for enabled. - * @return Current interrupt enabled status - * @see MPU6050_RA_INT_ENABLE - * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT - **/ -bool MPU6050_getIntFIFOBufferOverflowEnabled() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set FIFO Buffer Overflow interrupt enabled status. - * @param enabled New interrupt enabled status - * @see getIntFIFOBufferOverflowEnabled() - * @see MPU6050_RA_INT_ENABLE - * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT - **/ -void MPU6050_setIntFIFOBufferOverflowEnabled(bool enabled) { - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, enabled); -} -/** Get I2C Master interrupt enabled status. - * This enables any of the I2C Master interrupt sources to generate an - * interrupt. Will be set 0 for disabled, 1 for enabled. - * @return Current interrupt enabled status - * @see MPU6050_RA_INT_ENABLE - * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT - **/ -bool MPU6050_getIntI2CMasterEnabled() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_I2C_MST_INT_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set I2C Master interrupt enabled status. - * @param enabled New interrupt enabled status - * @see getIntI2CMasterEnabled() - * @see MPU6050_RA_INT_ENABLE - * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT - **/ -void MPU6050_setIntI2CMasterEnabled(bool enabled) { - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_I2C_MST_INT_BIT, enabled); -} -/** Get Data Ready interrupt enabled setting. - * This event occurs each time a write operation to all of the sensor registers - * has been completed. Will be set 0 for disabled, 1 for enabled. - * @return Current interrupt enabled status - * @see MPU6050_RA_INT_ENABLE - * @see MPU6050_INTERRUPT_DATA_RDY_BIT - */ -bool MPU6050_getIntDataReadyEnabled() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DATA_RDY_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set Data Ready interrupt enabled status. - * @param enabled New interrupt enabled status - * @see getIntDataReadyEnabled() - * @see MPU6050_RA_INT_CFG - * @see MPU6050_INTERRUPT_DATA_RDY_BIT - */ -void MPU6050_setIntDataReadyEnabled(bool enabled) { - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DATA_RDY_BIT, enabled); -} - -// INT_STATUS register - -/** Get full set of interrupt status bits. - * These bits clear to 0 after the register has been read. Very useful - * for getting multiple INT statuses, since each single bit read clears - * all of them because it has to read the whole byte. - * @return Current interrupt status - * @see MPU6050_RA_INT_STATUS - */ -uint8_t MPU6050_getIntStatus() { - I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_INT_STATUS, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Get Free Fall interrupt status. - * This bit automatically sets to 1 when a Free Fall interrupt has been - * generated. The bit clears to 0 after the register has been read. - * @return Current interrupt status - * @see MPU6050_RA_INT_STATUS - * @see MPU6050_INTERRUPT_FF_BIT - */ -bool MPU6050_getIntFreefallStatus() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_FF_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Get Motion Detection interrupt status. - * This bit automatically sets to 1 when a Motion Detection interrupt has been - * generated. The bit clears to 0 after the register has been read. - * @return Current interrupt status - * @see MPU6050_RA_INT_STATUS - * @see MPU6050_INTERRUPT_MOT_BIT - */ -bool MPU6050_getIntMotionStatus() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_MOT_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Get Zero Motion Detection interrupt status. - * This bit automatically sets to 1 when a Zero Motion Detection interrupt has - * been generated. The bit clears to 0 after the register has been read. - * @return Current interrupt status - * @see MPU6050_RA_INT_STATUS - * @see MPU6050_INTERRUPT_ZMOT_BIT - */ -bool MPU6050_getIntZeroMotionStatus() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_ZMOT_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Get FIFO Buffer Overflow interrupt status. - * This bit automatically sets to 1 when a Free Fall interrupt has been - * generated. The bit clears to 0 after the register has been read. - * @return Current interrupt status - * @see MPU6050_RA_INT_STATUS - * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT - */ -bool MPU6050_getIntFIFOBufferOverflowStatus() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Get I2C Master interrupt status. - * This bit automatically sets to 1 when an I2C Master interrupt has been - * generated. For a list of I2C Master interrupts, please refer to Register 54. - * The bit clears to 0 after the register has been read. - * @return Current interrupt status - * @see MPU6050_RA_INT_STATUS - * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT - */ -bool MPU6050_getIntI2CMasterStatus() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_I2C_MST_INT_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Get Data Ready interrupt status. - * This bit automatically sets to 1 when a Data Ready interrupt has been - * generated. The bit clears to 0 after the register has been read. - * @return Current interrupt status - * @see MPU6050_RA_INT_STATUS - * @see MPU6050_INTERRUPT_DATA_RDY_BIT - */ -bool MPU6050_getIntDataReadyStatus() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_DATA_RDY_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} - -// ACCEL_*OUT_* registers - -/** Get raw 9-axis motion sensor readings (accel/gyro/compass). - * FUNCTION NOT FULLY IMPLEMENTED YET. - * @param ax 16-bit signed integer container for accelerometer X-axis value - * @param ay 16-bit signed integer container for accelerometer Y-axis value - * @param az 16-bit signed integer container for accelerometer Z-axis value - * @param gx 16-bit signed integer container for gyroscope X-axis value - * @param gy 16-bit signed integer container for gyroscope Y-axis value - * @param gz 16-bit signed integer container for gyroscope Z-axis value - * @param mx 16-bit signed integer container for magnetometer X-axis value - * @param my 16-bit signed integer container for magnetometer Y-axis value - * @param mz 16-bit signed integer container for magnetometer Z-axis value - * @see getMotion6() - * @see getAcceleration() - * @see getRotation() - * @see MPU6050_RA_ACCEL_XOUT_H - */ -void MPU6050_getMotion9(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz, int16_t* mx, int16_t* my, int16_t* mz) { - MPU6050_getMotion6(ax, ay, az, gx, gy, gz); - // TODO: magnetometer integration -} -/** Get raw 6-axis motion sensor readings (accel/gyro). - * Retrieves all currently available motion sensor values. - * @param ax 16-bit signed integer container for accelerometer X-axis value - * @param ay 16-bit signed integer container for accelerometer Y-axis value - * @param az 16-bit signed integer container for accelerometer Z-axis value - * @param gx 16-bit signed integer container for gyroscope X-axis value - * @param gy 16-bit signed integer container for gyroscope Y-axis value - * @param gz 16-bit signed integer container for gyroscope Z-axis value - * @see getAcceleration() - * @see getRotation() - * @see MPU6050_RA_ACCEL_XOUT_H - */ -void MPU6050_getMotion6(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz) { - I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ACCEL_XOUT_H, 14, mpu6050.buffer); - *ax = (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; - *ay = (((int16_t)mpu6050.buffer[2]) << 8) | mpu6050.buffer[3]; - *az = (((int16_t)mpu6050.buffer[4]) << 8) | mpu6050.buffer[5]; - *gx = (((int16_t)mpu6050.buffer[8]) << 8) | mpu6050.buffer[9]; - *gy = (((int16_t)mpu6050.buffer[10]) << 8) | mpu6050.buffer[11]; - *gz = (((int16_t)mpu6050.buffer[12]) << 8) | mpu6050.buffer[13]; -} -/** Get 3-axis accelerometer readings. - * These registers store the most recent accelerometer measurements. - * Accelerometer measurements are written to these registers at the Sample Rate - * as defined in Register 25. - * - * The accelerometer measurement registers, along with the temperature - * measurement registers, gyroscope measurement registers, and external sensor - * data registers, are composed of two sets of registers: an internal register - * set and a user-facing read register set. - * - * The data within the accelerometer sensors' internal register set is always - * updated at the Sample Rate. Meanwhile, the user-facing read register set - * duplicates the internal register set's data values whenever the serial - * interface is idle. This guarantees that a burst read of sensor registers will - * read measurements from the same sampling instant. Note that if burst reads - * are not used, the user is responsible for ensuring a set of single byte reads - * correspond to a single sampling instant by checking the Data Ready interrupt. - * - * Each 16-bit accelerometer measurement has a full scale defined in ACCEL_FS - * (Register 28). For each full scale setting, the accelerometers' sensitivity - * per LSB in ACCEL_xOUT is shown in the table below: - * - *
- * AFS_SEL | Full Scale Range | LSB Sensitivity
- * --------+------------------+----------------
- * 0       | +/- 2g           | 8192 LSB/mg
- * 1       | +/- 4g           | 4096 LSB/mg
- * 2       | +/- 8g           | 2048 LSB/mg
- * 3       | +/- 16g          | 1024 LSB/mg
- * 
- * - * @param x 16-bit signed integer container for X-axis acceleration - * @param y 16-bit signed integer container for Y-axis acceleration - * @param z 16-bit signed integer container for Z-axis acceleration - * @see MPU6050_RA_GYRO_XOUT_H - */ -void MPU6050_getAcceleration(int16_t* x, int16_t* y, int16_t* z) { - I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ACCEL_XOUT_H, 6, mpu6050.buffer); - *x = (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; - *y = (((int16_t)mpu6050.buffer[2]) << 8) | mpu6050.buffer[3]; - *z = (((int16_t)mpu6050.buffer[4]) << 8) | mpu6050.buffer[5]; -} -/** Get X-axis accelerometer reading. - * @return X-axis acceleration measurement in 16-bit 2's complement format - * @see getMotion6() - * @see MPU6050_RA_ACCEL_XOUT_H - */ -int16_t MPU6050_getAccelerationX() { - I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ACCEL_XOUT_H, 2, mpu6050.buffer); - return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; -} -/** Get Y-axis accelerometer reading. - * @return Y-axis acceleration measurement in 16-bit 2's complement format - * @see getMotion6() - * @see MPU6050_RA_ACCEL_YOUT_H - */ -int16_t MPU6050_getAccelerationY() { - I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ACCEL_YOUT_H, 2, mpu6050.buffer); - return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; -} -/** Get Z-axis accelerometer reading. - * @return Z-axis acceleration measurement in 16-bit 2's complement format - * @see getMotion6() - * @see MPU6050_RA_ACCEL_ZOUT_H - */ -int16_t MPU6050_getAccelerationZ() { - I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ACCEL_ZOUT_H, 2, mpu6050.buffer); - return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; -} - -// TEMP_OUT_* registers - -/** Get current internal temperature. - * @return Temperature reading in 16-bit 2's complement format - * @see MPU6050_RA_TEMP_OUT_H - */ -int16_t MPU6050_getTemperature() { - I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_TEMP_OUT_H, 2, mpu6050.buffer); - return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; -} - -// GYRO_*OUT_* registers - -/** Get 3-axis gyroscope readings. - * These gyroscope measurement registers, along with the accelerometer - * measurement registers, temperature measurement registers, and external sensor - * data registers, are composed of two sets of registers: an internal register - * set and a user-facing read register set. - * The data within the gyroscope sensors' internal register set is always - * updated at the Sample Rate. Meanwhile, the user-facing read register set - * duplicates the internal register set's data values whenever the serial - * interface is idle. This guarantees that a burst read of sensor registers will - * read measurements from the same sampling instant. Note that if burst reads - * are not used, the user is responsible for ensuring a set of single byte reads - * correspond to a single sampling instant by checking the Data Ready interrupt. - * - * Each 16-bit gyroscope measurement has a full scale defined in FS_SEL - * (Register 27). For each full scale setting, the gyroscopes' sensitivity per - * LSB in GYRO_xOUT is shown in the table below: - * - *
- * FS_SEL | Full Scale Range   | LSB Sensitivity
- * -------+--------------------+----------------
- * 0      | +/- 250 degrees/s  | 131 LSB/deg/s
- * 1      | +/- 500 degrees/s  | 65.5 LSB/deg/s
- * 2      | +/- 1000 degrees/s | 32.8 LSB/deg/s
- * 3      | +/- 2000 degrees/s | 16.4 LSB/deg/s
- * 
- * - * @param x 16-bit signed integer container for X-axis rotation - * @param y 16-bit signed integer container for Y-axis rotation - * @param z 16-bit signed integer container for Z-axis rotation - * @see getMotion6() - * @see MPU6050_RA_GYRO_XOUT_H - */ -void MPU6050_getRotation(int16_t* x, int16_t* y, int16_t* z) { - I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_GYRO_XOUT_H, 6, mpu6050.buffer); - *x = (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; - *y = (((int16_t)mpu6050.buffer[2]) << 8) | mpu6050.buffer[3]; - *z = (((int16_t)mpu6050.buffer[4]) << 8) | mpu6050.buffer[5]; -} -/** Get X-axis gyroscope reading. - * @return X-axis rotation measurement in 16-bit 2's complement format - * @see getMotion6() - * @see MPU6050_RA_GYRO_XOUT_H - */ -int16_t MPU6050_getRotationX() { - I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_GYRO_XOUT_H, 2, mpu6050.buffer); - return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; -} -/** Get Y-axis gyroscope reading. - * @return Y-axis rotation measurement in 16-bit 2's complement format - * @see getMotion6() - * @see MPU6050_RA_GYRO_YOUT_H - */ -int16_t MPU6050_getRotationY() { - I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_GYRO_YOUT_H, 2, mpu6050.buffer); - return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; -} -/** Get Z-axis gyroscope reading. - * @return Z-axis rotation measurement in 16-bit 2's complement format - * @see getMotion6() - * @see MPU6050_RA_GYRO_ZOUT_H - */ -int16_t MPU6050_getRotationZ() { - I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_GYRO_ZOUT_H, 2, mpu6050.buffer); - return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; -} - -// EXT_SENS_DATA_* registers - -/** Read single byte from external sensor data register. - * These registers store data read from external sensors by the Slave 0, 1, 2, - * and 3 on the auxiliary I2C interface. Data read by Slave 4 is stored in - * I2C_SLV4_DI (Register 53). - * - * External sensor data is written to these registers at the Sample Rate as - * defined in Register 25. This access rate can be reduced by using the Slave - * Delay Enable registers (Register 103). - * - * External sensor data registers, along with the gyroscope measurement - * registers, accelerometer measurement registers, and temperature measurement - * registers, are composed of two sets of registers: an internal register set - * and a user-facing read register set. - * - * The data within the external sensors' internal register set is always updated - * at the Sample Rate (or the reduced access rate) whenever the serial interface - * is idle. This guarantees that a burst read of sensor registers will read - * measurements from the same sampling instant. Note that if burst reads are not - * used, the user is responsible for ensuring a set of single byte reads - * correspond to a single sampling instant by checking the Data Ready interrupt. - * - * Data is placed in these external sensor data registers according to - * I2C_SLV0_CTRL, I2C_SLV1_CTRL, I2C_SLV2_CTRL, and I2C_SLV3_CTRL (Registers 39, - * 42, 45, and 48). When more than zero bytes are read (I2C_SLVx_LEN > 0) from - * an enabled slave (I2C_SLVx_EN = 1), the slave is read at the Sample Rate (as - * defined in Register 25) or delayed rate (if specified in Register 52 and - * 103). During each Sample cycle, slave reads are performed in order of Slave - * number. If all slaves are enabled with more than zero bytes to be read, the - * order will be Slave 0, followed by Slave 1, Slave 2, and Slave 3. - * - * Each enabled slave will have EXT_SENS_DATA registers associated with it by - * number of bytes read (I2C_SLVx_LEN) in order of slave number, starting from - * EXT_SENS_DATA_00. Note that this means enabling or disabling a slave may - * change the higher numbered slaves' associated registers. Furthermore, if - * fewer total bytes are being read from the external sensors as a result of - * such a change, then the data remaining in the registers which no longer have - * an associated slave device (i.e. high numbered registers) will remain in - * these previously allocated registers unless reset. - * - * If the sum of the read lengths of all SLVx transactions exceed the number of - * available EXT_SENS_DATA registers, the excess bytes will be dropped. There - * are 24 EXT_SENS_DATA registers and hence the total read lengths between all - * the slaves cannot be greater than 24 or some bytes will be lost. - * - * Note: Slave 4's behavior is distinct from that of Slaves 0-3. For further - * information regarding the characteristics of Slave 4, please refer to - * Registers 49 to 53. - * - * EXAMPLE: - * Suppose that Slave 0 is enabled with 4 bytes to be read (I2C_SLV0_EN = 1 and - * I2C_SLV0_LEN = 4) while Slave 1 is enabled with 2 bytes to be read so that - * I2C_SLV1_EN = 1 and I2C_SLV1_LEN = 2. In such a situation, EXT_SENS_DATA _00 - * through _03 will be associated with Slave 0, while EXT_SENS_DATA _04 and 05 - * will be associated with Slave 1. If Slave 2 is enabled as well, registers - * starting from EXT_SENS_DATA_06 will be allocated to Slave 2. - * - * If Slave 2 is disabled while Slave 3 is enabled in this same situation, then - * registers starting from EXT_SENS_DATA_06 will be allocated to Slave 3 - * instead. - * - * REGISTER ALLOCATION FOR DYNAMIC DISABLE VS. NORMAL DISABLE: - * If a slave is disabled at any time, the space initially allocated to the - * slave in the EXT_SENS_DATA register, will remain associated with that slave. - * This is to avoid dynamic adjustment of the register allocation. - * - * The allocation of the EXT_SENS_DATA registers is recomputed only when (1) all - * slaves are disabled, or (2) the I2C_MST_RST bit is set (Register 106). - * - * This above is also true if one of the slaves gets NACKed and stops - * functioning. - * - * @param position Starting position (0-23) - * @return Byte read from register - */ -uint8_t MPU6050_getExternalSensorByte(int position) { - I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Read word (2 bytes) from external sensor data registers. - * @param position Starting position (0-21) - * @return Word read from register - * @see getExternalSensorByte() - */ -uint16_t MPU6050_getExternalSensorWord(int position) { - I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, 2, mpu6050.buffer); - return (((uint16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1]; -} -/** Read double word (4 bytes) from external sensor data registers. - * @param position Starting position (0-20) - * @return Double word read from registers - * @see getExternalSensorByte() - */ -uint32_t MPU6050_getExternalSensorDWord(int position) { - I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, 4, mpu6050.buffer); - return (((uint32_t)mpu6050.buffer[0]) << 24) | (((uint32_t)mpu6050.buffer[1]) << 16) | (((uint16_t)mpu6050.buffer[2]) << 8) | mpu6050.buffer[3]; -} - -// MOT_DETECT_STATUS register - -/** Get X-axis negative motion detection interrupt status. - * @return Motion detection status - * @see MPU6050_RA_MOT_DETECT_STATUS - * @see MPU6050_MOTION_MOT_XNEG_BIT - */ -bool MPU6050_getXNegMotionDetected() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_XNEG_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Get X-axis positive motion detection interrupt status. - * @return Motion detection status - * @see MPU6050_RA_MOT_DETECT_STATUS - * @see MPU6050_MOTION_MOT_XPOS_BIT - */ -bool MPU6050_getXPosMotionDetected() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_XPOS_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Get Y-axis negative motion detection interrupt status. - * @return Motion detection status - * @see MPU6050_RA_MOT_DETECT_STATUS - * @see MPU6050_MOTION_MOT_YNEG_BIT - */ -bool MPU6050_getYNegMotionDetected() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_YNEG_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Get Y-axis positive motion detection interrupt status. - * @return Motion detection status - * @see MPU6050_RA_MOT_DETECT_STATUS - * @see MPU6050_MOTION_MOT_YPOS_BIT - */ -bool MPU6050_getYPosMotionDetected() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_YPOS_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Get Z-axis negative motion detection interrupt status. - * @return Motion detection status - * @see MPU6050_RA_MOT_DETECT_STATUS - * @see MPU6050_MOTION_MOT_ZNEG_BIT - */ -bool MPU6050_getZNegMotionDetected() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZNEG_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Get Z-axis positive motion detection interrupt status. - * @return Motion detection status - * @see MPU6050_RA_MOT_DETECT_STATUS - * @see MPU6050_MOTION_MOT_ZPOS_BIT - */ -bool MPU6050_getZPosMotionDetected() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZPOS_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Get zero motion detection interrupt status. - * @return Motion detection status - * @see MPU6050_RA_MOT_DETECT_STATUS - * @see MPU6050_MOTION_MOT_ZRMOT_BIT - */ -bool MPU6050_getZeroMotionDetected() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZRMOT_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} - -// I2C_SLV*_DO register - -/** Write byte to Data Output container for specified slave. - * This register holds the output data written into Slave when Slave is set to - * write mode. For further information regarding Slave control, please - * refer to Registers 37 to 39 and immediately following. - * @param num Slave number (0-3) - * @param data Byte to write - * @see MPU6050_RA_I2C_SLV0_DO - */ -void MPU6050_setSlaveOutputByte(uint8_t num, uint8_t data) { - if (num > 3) return; - I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_I2C_SLV0_DO + num, data); -} - -// I2C_MST_DELAY_CTRL register - -/** Get external data shadow delay enabled status. - * This register is used to specify the timing of external sensor data - * shadowing. When DELAY_ES_SHADOW is set to 1, shadowing of external - * sensor data is delayed until all data has been received. - * @return Current external data shadow delay enabled status. - * @see MPU6050_RA_I2C_MST_DELAY_CTRL - * @see MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT - */ -bool MPU6050_getExternalShadowDelayEnabled() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set external data shadow delay enabled status. - * @param enabled New external data shadow delay enabled status. - * @see getExternalShadowDelayEnabled() - * @see MPU6050_RA_I2C_MST_DELAY_CTRL - * @see MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT - */ -void MPU6050_setExternalShadowDelayEnabled(bool enabled) { - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT, enabled); -} -/** Get slave delay enabled status. - * When a particular slave delay is enabled, the rate of access for the that - * slave device is reduced. When a slave's access rate is decreased relative to - * the Sample Rate, the slave is accessed every: - * - * 1 / (1 + I2C_MST_DLY) Samples - * - * This base Sample Rate in turn is determined by SMPLRT_DIV (register * 25) - * and DLPF_CFG (register 26). - * - * For further information regarding I2C_MST_DLY, please refer to register 52. - * For further information regarding the Sample Rate, please refer to register 25. - * - * @param num Slave number (0-4) - * @return Current slave delay enabled status. - * @see MPU6050_RA_I2C_MST_DELAY_CTRL - * @see MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT - */ -bool MPU6050_getSlaveDelayEnabled(uint8_t num) { - // MPU6050_DELAYCTRL_I2C_SLV4_DLY_EN_BIT is 4, SLV3 is 3, etc. - if (num > 4) return 0; - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, num, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set slave delay enabled status. - * @param num Slave number (0-4) - * @param enabled New slave delay enabled status. - * @see MPU6050_RA_I2C_MST_DELAY_CTRL - * @see MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT - */ -void MPU6050_setSlaveDelayEnabled(uint8_t num, bool enabled) { - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, num, enabled); -} - -// SIGNAL_PATH_RESET register - -/** Reset gyroscope signal path. - * The reset will revert the signal path analog to digital converters and - * filters to their power up configurations. - * @see MPU6050_RA_SIGNAL_PATH_RESET - * @see MPU6050_PATHRESET_GYRO_RESET_BIT - */ -void MPU6050_resetGyroscopePath() { - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_GYRO_RESET_BIT, true); -} -/** Reset accelerometer signal path. - * The reset will revert the signal path analog to digital converters and - * filters to their power up configurations. - * @see MPU6050_RA_SIGNAL_PATH_RESET - * @see MPU6050_PATHRESET_ACCEL_RESET_BIT - */ -void MPU6050_resetAccelerometerPath() { - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_ACCEL_RESET_BIT, true); -} -/** Reset temperature sensor signal path. - * The reset will revert the signal path analog to digital converters and - * filters to their power up configurations. - * @see MPU6050_RA_SIGNAL_PATH_RESET - * @see MPU6050_PATHRESET_TEMP_RESET_BIT - */ -void MPU6050_resetTemperaturePath() { - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_TEMP_RESET_BIT, true); -} - -// MOT_DETECT_CTRL register - -/** Get accelerometer power-on delay. - * The accelerometer data path provides samples to the sensor registers, Motion - * detection, Zero Motion detection, and Free Fall detection modules. The - * signal path contains filters which must be flushed on wake-up with new - * samples before the detection modules begin operations. The default wake-up - * delay, of 4ms can be lengthened by up to 3ms. This additional delay is - * specified in ACCEL_ON_DELAY in units of 1 LSB = 1 ms. The user may select - * any value above zero unless instructed otherwise by InvenSense. Please refer - * to Section 8 of the MPU-6000/MPU-6050 Product Specification document for - * further information regarding the detection modules. - * @return Current accelerometer power-on delay - * @see MPU6050_RA_MOT_DETECT_CTRL - * @see MPU6050_DETECT_ACCEL_ON_DELAY_BIT - */ -uint8_t MPU6050_getAccelerometerPowerOnDelay() { - I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_ACCEL_ON_DELAY_BIT, MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set accelerometer power-on delay. - * @param delay New accelerometer power-on delay (0-3) - * @see getAccelerometerPowerOnDelay() - * @see MPU6050_RA_MOT_DETECT_CTRL - * @see MPU6050_DETECT_ACCEL_ON_DELAY_BIT - */ -void MPU6050_setAccelerometerPowerOnDelay(uint8_t delay) { - I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_ACCEL_ON_DELAY_BIT, MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH, delay); -} -/** Get Free Fall detection counter decrement configuration. - * Detection is registered by the Free Fall detection module after accelerometer - * measurements meet their respective threshold conditions over a specified - * number of samples. When the threshold conditions are met, the corresponding - * detection counter increments by 1. The user may control the rate at which the - * detection counter decrements when the threshold condition is not met by - * configuring FF_COUNT. The decrement rate can be set according to the - * following table: - * - *
- * FF_COUNT | Counter Decrement
- * ---------+------------------
- * 0        | Reset
- * 1        | 1
- * 2        | 2
- * 3        | 4
- * 
- * - * When FF_COUNT is configured to 0 (reset), any non-qualifying sample will - * reset the counter to 0. For further information on Free Fall detection, - * please refer to Registers 29 to 32. - * - * @return Current decrement configuration - * @see MPU6050_RA_MOT_DETECT_CTRL - * @see MPU6050_DETECT_FF_COUNT_BIT - */ -uint8_t MPU6050_getFreefallDetectionCounterDecrement() { - I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_FF_COUNT_BIT, MPU6050_DETECT_FF_COUNT_LENGTH, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set Free Fall detection counter decrement configuration. - * @param decrement New decrement configuration value - * @see getFreefallDetectionCounterDecrement() - * @see MPU6050_RA_MOT_DETECT_CTRL - * @see MPU6050_DETECT_FF_COUNT_BIT - */ -void MPU6050_setFreefallDetectionCounterDecrement(uint8_t decrement) { - I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_FF_COUNT_BIT, MPU6050_DETECT_FF_COUNT_LENGTH, decrement); -} -/** Get Motion detection counter decrement configuration. - * Detection is registered by the Motion detection module after accelerometer - * measurements meet their respective threshold conditions over a specified - * number of samples. When the threshold conditions are met, the corresponding - * detection counter increments by 1. The user may control the rate at which the - * detection counter decrements when the threshold condition is not met by - * configuring MOT_COUNT. The decrement rate can be set according to the - * following table: - * - *
- * MOT_COUNT | Counter Decrement
- * ----------+------------------
- * 0         | Reset
- * 1         | 1
- * 2         | 2
- * 3         | 4
- * 
- * - * When MOT_COUNT is configured to 0 (reset), any non-qualifying sample will - * reset the counter to 0. For further information on Motion detection, - * please refer to Registers 29 to 32. - * - */ -uint8_t MPU6050_getMotionDetectionCounterDecrement() { - I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_MOT_COUNT_BIT, MPU6050_DETECT_MOT_COUNT_LENGTH, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set Motion detection counter decrement configuration. - * @param decrement New decrement configuration value - * @see getMotionDetectionCounterDecrement() - * @see MPU6050_RA_MOT_DETECT_CTRL - * @see MPU6050_DETECT_MOT_COUNT_BIT - */ -void MPU6050_setMotionDetectionCounterDecrement(uint8_t decrement) { - I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_MOT_COUNT_BIT, MPU6050_DETECT_MOT_COUNT_LENGTH, decrement); -} - -// USER_CTRL register - -/** Get FIFO enabled status. - * When this bit is set to 0, the FIFO mpu6050.buffer is disabled. The FIFO mpu6050.buffer - * cannot be written to or read from while disabled. The FIFO mpu6050.buffer's state - * does not change unless the MPU-60X0 is power cycled. - * @return Current FIFO enabled status - * @see MPU6050_RA_USER_CTRL - * @see MPU6050_USERCTRL_FIFO_EN_BIT - */ -bool MPU6050_getFIFOEnabled() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_EN_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set FIFO enabled status. - * @param enabled New FIFO enabled status - * @see getFIFOEnabled() - * @see MPU6050_RA_USER_CTRL - * @see MPU6050_USERCTRL_FIFO_EN_BIT - */ -void MPU6050_setFIFOEnabled(bool enabled) { - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_EN_BIT, enabled); -} -/** Get I2C Master Mode enabled status. - * When this mode is enabled, the MPU-60X0 acts as the I2C Master to the - * external sensor slave devices on the auxiliary I2C bus. When this bit is - * cleared to 0, the auxiliary I2C bus lines (AUX_DA and AUX_CL) are logically - * driven by the primary I2C bus (SDA and SCL). This is a precondition to - * enabling Bypass Mode. For further information regarding Bypass Mode, please - * refer to Register 55. - * @return Current I2C Master Mode enabled status - * @see MPU6050_RA_USER_CTRL - * @see MPU6050_USERCTRL_I2C_MST_EN_BIT - */ -bool MPU6050_getI2CMasterModeEnabled() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_EN_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set I2C Master Mode enabled status. - * @param enabled New I2C Master Mode enabled status - * @see getI2CMasterModeEnabled() - * @see MPU6050_RA_USER_CTRL - * @see MPU6050_USERCTRL_I2C_MST_EN_BIT - */ -void MPU6050_setI2CMasterModeEnabled(bool enabled) { - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_EN_BIT, enabled); -} -/** Switch from I2C to SPI mode (MPU-6000 only) - * If this is set, the primary SPI interface will be enabled in place of the - * disabled primary I2C interface. - */ -void MPU6050_switchSPIEnabled(bool enabled) { - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_IF_DIS_BIT, enabled); -} -/** Reset the FIFO. - * This bit resets the FIFO mpu6050.buffer when set to 1 while FIFO_EN equals 0. This - * bit automatically clears to 0 after the reset has been triggered. - * @see MPU6050_RA_USER_CTRL - * @see MPU6050_USERCTRL_FIFO_RESET_BIT - */ -void MPU6050_resetFIFO() { - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_RESET_BIT, true); -} -/** Reset the I2C Master. - * This bit resets the I2C Master when set to 1 while I2C_MST_EN equals 0. - * This bit automatically clears to 0 after the reset has been triggered. - * @see MPU6050_RA_USER_CTRL - * @see MPU6050_USERCTRL_I2C_MST_RESET_BIT - */ -void MPU6050_resetI2CMaster() { - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_RESET_BIT, true); -} -/** Reset all sensor registers and signal paths. - * When set to 1, this bit resets the signal paths for all sensors (gyroscopes, - * accelerometers, and temperature sensor). This operation will also clear the - * sensor registers. This bit automatically clears to 0 after the reset has been - * triggered. - * - * When resetting only the signal path (and not the sensor registers), please - * use Register 104, SIGNAL_PATH_RESET. - * - * @see MPU6050_RA_USER_CTRL - * @see MPU6050_USERCTRL_SIG_COND_RESET_BIT - */ -void MPU6050_resetSensors() { - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_SIG_COND_RESET_BIT, true); -} - -// PWR_MGMT_1 register - -/** Trigger a full device reset. - * A small delay of ~50ms may be desirable after triggering a reset. - * @see MPU6050_RA_PWR_MGMT_1 - * @see MPU6050_PWR1_DEVICE_RESET_BIT - */ -void MPU6050_reset() { - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_DEVICE_RESET_BIT, true); -} -/** Get sleep mode status. - * Setting the SLEEP bit in the register puts the device into very low power - * sleep mode. In this mode, only the serial interface and internal registers - * remain active, allowing for a very low standby current. Clearing this bit - * puts the device back into normal mode. To save power, the individual standby - * selections for each of the gyros should be used if any gyro axis is not used - * by the application. - * @return Current sleep mode enabled status - * @see MPU6050_RA_PWR_MGMT_1 - * @see MPU6050_PWR1_SLEEP_BIT - */ -bool MPU6050_getSleepEnabled() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set sleep mode status. - * @param enabled New sleep mode enabled status - * @see getSleepEnabled() - * @see MPU6050_RA_PWR_MGMT_1 - * @see MPU6050_PWR1_SLEEP_BIT - */ -void MPU6050_setSleepEnabled(bool enabled) { - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, enabled); -} -/** Get wake cycle enabled status. - * When this bit is set to 1 and SLEEP is disabled, the MPU-60X0 will cycle - * between sleep mode and waking up to take a single sample of data from active - * sensors at a rate determined by LP_WAKE_CTRL (register 108). - * @return Current sleep mode enabled status - * @see MPU6050_RA_PWR_MGMT_1 - * @see MPU6050_PWR1_CYCLE_BIT - */ -bool MPU6050_getWakeCycleEnabled() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CYCLE_BIT, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set wake cycle enabled status. - * @param enabled New sleep mode enabled status - * @see getWakeCycleEnabled() - * @see MPU6050_RA_PWR_MGMT_1 - * @see MPU6050_PWR1_CYCLE_BIT - */ -void MPU6050_setWakeCycleEnabled(bool enabled) { - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CYCLE_BIT, enabled); -} -/** Get temperature sensor enabled status. - * Control the usage of the internal temperature sensor. - * - * Note: this register stores the *disabled* value, but for consistency with the - * rest of the code, the function is named and used with standard true/false - * values to indicate whether the sensor is enabled or disabled, respectively. - * - * @return Current temperature sensor enabled status - * @see MPU6050_RA_PWR_MGMT_1 - * @see MPU6050_PWR1_TEMP_DIS_BIT - */ -bool MPU6050_getTempSensorEnabled() { - I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_TEMP_DIS_BIT, mpu6050.buffer); - return mpu6050.buffer[0] == 0; // 1 is actually disabled here -} -/** Set temperature sensor enabled status. - * Note: this register stores the *disabled* value, but for consistency with the - * rest of the code, the function is named and used with standard true/false - * values to indicate whether the sensor is enabled or disabled, respectively. - * - * @param enabled New temperature sensor enabled status - * @see getTempSensorEnabled() - * @see MPU6050_RA_PWR_MGMT_1 - * @see MPU6050_PWR1_TEMP_DIS_BIT - */ -void MPU6050_setTempSensorEnabled(bool enabled) { - // 1 is actually disabled here - I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_TEMP_DIS_BIT, !enabled); -} -/** Get clock source setting. - * @return Current clock source setting - * @see MPU6050_RA_PWR_MGMT_1 - * @see MPU6050_PWR1_CLKSEL_BIT - * @see MPU6050_PWR1_CLKSEL_LENGTH - */ -uint8_t MPU6050_getClockSource() { - I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, mpu6050.buffer); - return mpu6050.buffer[0]; -} -/** Set clock source setting. - * An internal 8MHz oscillator, gyroscope based clock, or external sources can - * be selected as the MPU-60X0 clock source. When the internal 8 MHz oscillator - * or an external source is chosen as the clock source, the MPU-60X0 can operate - * in low power modes with the gyroscopes disabled. - * - * Upon power up, the MPU-60X0 clock source defaults to the internal oscillator. - * However, it is highly recommended that the device be configured to use one of - * the gyroscopes (or an external clock source) as the clock reference for - * improved stability. The clock source can be selected according to the following table: - * - *
- * CLK_SEL | Clock Source
- * --------+--------------------------------------
- * 0       | Internal oscillator
- * 1       | PLL with X Gyro reference
- * 2       | PLL with Y Gyro reference
- * 3       | PLL with Z Gyro reference
- * 4       | PLL with external 32.768kHz reference
- * 5       | PLL with external 19.2MHz reference
- * 6       | Reserved
- * 7       | Stops the clock and keeps the timing generator in reset
- * 
- * - * @param source New clock source setting - * @see getClockSource() - * @see MPU6050_RA_PWR_MGMT_1 - * @see MPU6050_PWR1_CLKSEL_BIT - * @see MPU6050_PWR1_CLKSEL_LENGTH - */ -void MPU6050_setClockSource(uint8_t source) { - I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, source); -} - -// PWR_MGMT_2 register - -/** Get wake frequency in Accel-Only Low Power Mode. - * The MPU-60X0 can be put into Accerlerometer Only Low Power Mode by setting - * PWRSEL to 1 in the Power Management 1 register (Register 107). In this mode, - * the device will power off all devices except for the primary I2C interface, - * waking only the accelerometer at fixed intervals to take a single - * measurement. The frequency of wake-ups can be configured with LP_WAKE_CTRL - * as shown below: - * - *
- * LP_WAKE_CTRL | Wake-up Frequency
- * -------------+------------------
- * 0            | 1.25 Hz
- * 1            | 2.5 Hz
- * 2            | 5 Hz
- * 3            | 10 Hz
- * 
- *
- * For further information regarding the MPU-60X0's power modes, please refer to
- * Register 107.
- *
- * @return Current wake frequency
- * @see MPU6050_RA_PWR_MGMT_2
- */
-uint8_t MPU6050_getWakeFrequency() {
-    I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_LP_WAKE_CTRL_BIT, MPU6050_PWR2_LP_WAKE_CTRL_LENGTH, mpu6050.buffer);
-    return mpu6050.buffer[0];
-}
-/** Set wake frequency in Accel-Only Low Power Mode.
- * @param frequency New wake frequency
- * @see MPU6050_RA_PWR_MGMT_2
- */
-void MPU6050_setWakeFrequency(uint8_t frequency) {
-    I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_LP_WAKE_CTRL_BIT, MPU6050_PWR2_LP_WAKE_CTRL_LENGTH, frequency);
-}
-
-/** Get X-axis accelerometer standby enabled status.
- * If enabled, the X-axis will not gather or report data (or use power).
- * @return Current X-axis standby enabled status
- * @see MPU6050_RA_PWR_MGMT_2
- * @see MPU6050_PWR2_STBY_XA_BIT
- */
-bool MPU6050_getStandbyXAccelEnabled() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XA_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
-}
-/** Set X-axis accelerometer standby enabled status.
- * @param New X-axis standby enabled status
- * @see getStandbyXAccelEnabled()
- * @see MPU6050_RA_PWR_MGMT_2
- * @see MPU6050_PWR2_STBY_XA_BIT
- */
-void MPU6050_setStandbyXAccelEnabled(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XA_BIT, enabled);
-}
-/** Get Y-axis accelerometer standby enabled status.
- * If enabled, the Y-axis will not gather or report data (or use power).
- * @return Current Y-axis standby enabled status
- * @see MPU6050_RA_PWR_MGMT_2
- * @see MPU6050_PWR2_STBY_YA_BIT
- */
-bool MPU6050_getStandbyYAccelEnabled() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YA_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
-}
-/** Set Y-axis accelerometer standby enabled status.
- * @param New Y-axis standby enabled status
- * @see getStandbyYAccelEnabled()
- * @see MPU6050_RA_PWR_MGMT_2
- * @see MPU6050_PWR2_STBY_YA_BIT
- */
-void MPU6050_setStandbyYAccelEnabled(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YA_BIT, enabled);
-}
-/** Get Z-axis accelerometer standby enabled status.
- * If enabled, the Z-axis will not gather or report data (or use power).
- * @return Current Z-axis standby enabled status
- * @see MPU6050_RA_PWR_MGMT_2
- * @see MPU6050_PWR2_STBY_ZA_BIT
- */
-bool MPU6050_getStandbyZAccelEnabled() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZA_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
-}
-/** Set Z-axis accelerometer standby enabled status.
- * @param New Z-axis standby enabled status
- * @see getStandbyZAccelEnabled()
- * @see MPU6050_RA_PWR_MGMT_2
- * @see MPU6050_PWR2_STBY_ZA_BIT
- */
-void MPU6050_setStandbyZAccelEnabled(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZA_BIT, enabled);
-}
-/** Get X-axis gyroscope standby enabled status.
- * If enabled, the X-axis will not gather or report data (or use power).
- * @return Current X-axis standby enabled status
- * @see MPU6050_RA_PWR_MGMT_2
- * @see MPU6050_PWR2_STBY_XG_BIT
- */
-bool MPU6050_getStandbyXGyroEnabled() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XG_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
-}
-/** Set X-axis gyroscope standby enabled status.
- * @param New X-axis standby enabled status
- * @see getStandbyXGyroEnabled()
- * @see MPU6050_RA_PWR_MGMT_2
- * @see MPU6050_PWR2_STBY_XG_BIT
- */
-void MPU6050_setStandbyXGyroEnabled(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XG_BIT, enabled);
-}
-/** Get Y-axis gyroscope standby enabled status.
- * If enabled, the Y-axis will not gather or report data (or use power).
- * @return Current Y-axis standby enabled status
- * @see MPU6050_RA_PWR_MGMT_2
- * @see MPU6050_PWR2_STBY_YG_BIT
- */
-bool MPU6050_getStandbyYGyroEnabled() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YG_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
-}
-/** Set Y-axis gyroscope standby enabled status.
- * @param New Y-axis standby enabled status
- * @see getStandbyYGyroEnabled()
- * @see MPU6050_RA_PWR_MGMT_2
- * @see MPU6050_PWR2_STBY_YG_BIT
- */
-void MPU6050_setStandbyYGyroEnabled(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YG_BIT, enabled);
-}
-/** Get Z-axis gyroscope standby enabled status.
- * If enabled, the Z-axis will not gather or report data (or use power).
- * @return Current Z-axis standby enabled status
- * @see MPU6050_RA_PWR_MGMT_2
- * @see MPU6050_PWR2_STBY_ZG_BIT
- */
-bool MPU6050_getStandbyZGyroEnabled() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZG_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
-}
-/** Set Z-axis gyroscope standby enabled status.
- * @param New Z-axis standby enabled status
- * @see getStandbyZGyroEnabled()
- * @see MPU6050_RA_PWR_MGMT_2
- * @see MPU6050_PWR2_STBY_ZG_BIT
- */
-void MPU6050_setStandbyZGyroEnabled(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZG_BIT, enabled);
-}
-
-// FIFO_COUNT* registers
-
-/** Get current FIFO mpu6050.buffer size.
- * This value indicates the number of bytes stored in the FIFO mpu6050.buffer. This
- * number is in turn the number of bytes that can be read from the FIFO mpu6050.buffer
- * and it is directly proportional to the number of samples available given the
- * set of sensor data bound to be stored in the FIFO (register 35 and 36).
- * @return Current FIFO mpu6050.buffer size
- */
-uint16_t MPU6050_getFIFOCount() {
-    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_FIFO_COUNTH, 2, mpu6050.buffer);
-    return (((uint16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
-}
-
-// FIFO_R_W register
-
-/** Get byte from FIFO mpu6050.buffer.
- * This register is used to read and write data from the FIFO mpu6050.buffer. Data is
- * written to the FIFO in order of register number (from lowest to highest). If
- * all the FIFO enable flags (see below) are enabled and all External Sensor
- * Data registers (Registers 73 to 96) are associated with a Slave device, the
- * contents of registers 59 through 96 will be written in order at the Sample
- * Rate.
- *
- * The contents of the sensor data registers (Registers 59 to 96) are written
- * into the FIFO mpu6050.buffer when their corresponding FIFO enable flags are set to 1
- * in FIFO_EN (Register 35). An additional flag for the sensor data registers
- * associated with I2C Slave 3 can be found in I2C_MST_CTRL (Register 36).
- *
- * If the FIFO mpu6050.buffer has overflowed, the status bit FIFO_OFLOW_INT is
- * automatically set to 1. This bit is located in INT_STATUS (Register 58).
- * When the FIFO mpu6050.buffer has overflowed, the oldest data will be lost and new
- * data will be written to the FIFO.
- *
- * If the FIFO mpu6050.buffer is empty, reading this register will return the last byte
- * that was previously read from the FIFO until new data is available. The user
- * should check FIFO_COUNT to ensure that the FIFO mpu6050.buffer is not read when
- * empty.
- *
- * @return Byte from FIFO mpu6050.buffer
- */
-uint8_t MPU6050_getFIFOByte() {
-    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_FIFO_R_W, mpu6050.buffer);
-    return mpu6050.buffer[0];
-}
-void MPU6050_getFIFOBytes(uint8_t *data, uint8_t length) {
-    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_FIFO_R_W, length, data);
-}
-/** Write byte to FIFO mpu6050.buffer.
- * @see getFIFOByte()
- * @see MPU6050_RA_FIFO_R_W
- */
-void MPU6050_setFIFOByte(uint8_t data) {
-    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_FIFO_R_W, data);
-}
-
-// WHO_AM_I register
-
-/** Get Device ID.
- * This register is used to verify the identity of the device (0b110100, 0x34).
- * @return Device ID (6 bits only! should be 0x34)
- * @see MPU6050_RA_WHO_AM_I
- * @see MPU6050_WHO_AM_I_BIT
- * @see MPU6050_WHO_AM_I_LENGTH
- */
-uint8_t MPU6050_getDeviceID() {
-    I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_WHO_AM_I, MPU6050_WHO_AM_I_BIT, MPU6050_WHO_AM_I_LENGTH, mpu6050.buffer);
-    return mpu6050.buffer[0];
-}
-/** Set Device ID.
- * Write a new ID into the WHO_AM_I register (no idea why this should ever be
- * necessary though).
- * @param id New device ID to set.
- * @see getDeviceID()
- * @see MPU6050_RA_WHO_AM_I
- * @see MPU6050_WHO_AM_I_BIT
- * @see MPU6050_WHO_AM_I_LENGTH
- */
-void MPU6050_setDeviceID(uint8_t id) {
-    I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_WHO_AM_I, MPU6050_WHO_AM_I_BIT, MPU6050_WHO_AM_I_LENGTH, id);
-}
-
-// ======== UNDOCUMENTED/DMP REGISTERS/METHODS ========
-
-// XG_OFFS_TC register
-
-uint8_t MPU6050_getOTPBankValid() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OTP_BNK_VLD_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
-}
-void MPU6050_setOTPBankValid(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OTP_BNK_VLD_BIT, enabled);
-}
-int8_t MPU6050_getXGyroOffsetTC() {
-    I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, mpu6050.buffer);
-    return mpu6050.buffer[0];
-}
-void MPU6050_setXGyroOffsetTC(int8_t offset) {
-    I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset);
-}
-
-// YG_OFFS_TC register
-
-int8_t MPU6050_getYGyroOffsetTC() {
-    I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, mpu6050.buffer);
-    return mpu6050.buffer[0];
-}
-void MPU6050_setYGyroOffsetTC(int8_t offset) {
-    I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset);
-}
-
-// ZG_OFFS_TC register
-
-int8_t MPU6050_getZGyroOffsetTC() {
-    I2Cdev_readBits(mpu6050.devAddr, MPU6050_RA_ZG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, mpu6050.buffer);
-    return mpu6050.buffer[0];
-}
-void MPU6050_setZGyroOffsetTC(int8_t offset) {
-    I2Cdev_writeBits(mpu6050.devAddr, MPU6050_RA_ZG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset);
-}
-
-// X_FINE_GAIN register
-
-int8_t MPU6050_getXFineGain() {
-    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_X_FINE_GAIN, mpu6050.buffer);
-    return mpu6050.buffer[0];
-}
-void MPU6050_setXFineGain(int8_t gain) {
-    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_X_FINE_GAIN, gain);
-}
-
-// Y_FINE_GAIN register
-
-int8_t MPU6050_getYFineGain() {
-    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_Y_FINE_GAIN, mpu6050.buffer);
-    return mpu6050.buffer[0];
-}
-void MPU6050_setYFineGain(int8_t gain) {
-    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_Y_FINE_GAIN, gain);
-}
-
-// Z_FINE_GAIN register
-
-int8_t MPU6050_getZFineGain() {
-    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_Z_FINE_GAIN, mpu6050.buffer);
-    return mpu6050.buffer[0];
-}
-void MPU6050_setZFineGain(int8_t gain) {
-    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_Z_FINE_GAIN, gain);
-}
-
-// XA_OFFS_* registers
-
-int16_t MPU6050_getXAccelOffset() {
-    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_XA_OFFS_H, 2, mpu6050.buffer);
-    return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
-}
-void MPU6050_setXAccelOffset(int16_t offset) {
-    I2Cdev_writeWord(mpu6050.devAddr, MPU6050_RA_XA_OFFS_H, offset);
-}
-
-// YA_OFFS_* register
-
-int16_t MPU6050_getYAccelOffset() {
-    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_YA_OFFS_H, 2, mpu6050.buffer);
-    return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
-}
-void MPU6050_setYAccelOffset(int16_t offset) {
-    I2Cdev_writeWord(mpu6050.devAddr, MPU6050_RA_YA_OFFS_H, offset);
-}
-
-// ZA_OFFS_* register
-
-int16_t MPU6050_getZAccelOffset() {
-    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ZA_OFFS_H, 2, mpu6050.buffer);
-    return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
-}
-void MPU6050_setZAccelOffset(int16_t offset) {
-    I2Cdev_writeWord(mpu6050.devAddr, MPU6050_RA_ZA_OFFS_H, offset);
-}
-
-// XG_OFFS_USR* registers
-
-int16_t MPU6050_getXGyroOffset() {
-    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_XG_OFFS_USRH, 2, mpu6050.buffer);
-    return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
-}
-void MPU6050_setXGyroOffset(int16_t offset) {
-    I2Cdev_writeWord(mpu6050.devAddr, MPU6050_RA_XG_OFFS_USRH, offset);
-}
-
-// YG_OFFS_USR* register
-
-int16_t MPU6050_getYGyroOffset() {
-    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_YG_OFFS_USRH, 2, mpu6050.buffer);
-    return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
-}
-void MPU6050_setYGyroOffset(int16_t offset) {
-    I2Cdev_writeWord(mpu6050.devAddr, MPU6050_RA_YG_OFFS_USRH, offset);
-}
-
-// ZG_OFFS_USR* register
-
-int16_t MPU6050_getZGyroOffset() {
-    I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_ZG_OFFS_USRH, 2, mpu6050.buffer);
-    return (((int16_t)mpu6050.buffer[0]) << 8) | mpu6050.buffer[1];
-}
-void MPU6050_setZGyroOffset(int16_t offset) {
-    I2Cdev_writeWord(mpu6050.devAddr, MPU6050_RA_ZG_OFFS_USRH, offset);
-}
-
-// INT_ENABLE register (DMP functions)
-
-bool MPU6050_getIntPLLReadyEnabled() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
-}
-void MPU6050_setIntPLLReadyEnabled(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, enabled);
-}
-bool MPU6050_getIntDMPEnabled() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DMP_INT_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
-}
-void MPU6050_setIntDMPEnabled(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DMP_INT_BIT, enabled);
-}
-
-// DMP_INT_STATUS
-
-bool MPU6050_getDMPInt5Status() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_5_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
-}
-bool MPU6050_getDMPInt4Status() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_4_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
-}
-bool MPU6050_getDMPInt3Status() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_3_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
-}
-bool MPU6050_getDMPInt2Status() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_2_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
-}
-bool MPU6050_getDMPInt1Status() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_1_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
-}
-bool MPU6050_getDMPInt0Status() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_0_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
-}
-
-// INT_STATUS register (DMP functions)
-
-bool MPU6050_getIntPLLReadyStatus() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
-}
-bool MPU6050_getIntDMPStatus() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_DMP_INT_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
-}
-
-// USER_CTRL register (DMP functions)
-
-bool MPU6050_getDMPEnabled() {
-    I2Cdev_readBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_EN_BIT, mpu6050.buffer);
-    return mpu6050.buffer[0];
-}
-void MPU6050_setDMPEnabled(bool enabled) {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_EN_BIT, enabled);
-}
-void MPU6050_resetDMP() {
-    I2Cdev_writeBit(mpu6050.devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_RESET_BIT, true);
-}
-
-// BANK_SEL register
-
-void MPU6050_setMemoryBank(uint8_t bank, bool prefetchEnabled, bool userBank) {
-    bank &= 0x1F;
-    if (userBank) bank |= 0x20;
-    if (prefetchEnabled) bank |= 0x40;
-    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_BANK_SEL, bank);
-}
-
-// MEM_START_ADDR register
-
-void MPU6050_setMemoryStartAddress(uint8_t address) {
-    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_MEM_START_ADDR, address);
-}
-
-// MEM_R_W register
-
-uint8_t MPU6050_readMemoryByte() {
-    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_MEM_R_W, mpu6050.buffer);
-    return mpu6050.buffer[0];
-}
-void MPU6050_writeMemoryByte(uint8_t data) {
-    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_MEM_R_W, data);
-}
-void MPU6050_readMemoryBlock(uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address) {
-    MPU6050_setMemoryBank(bank, false, false);
-    MPU6050_setMemoryStartAddress(address);
-    uint8_t chunkSize;
-    for (uint16_t i = 0; i < dataSize;) {
-        // determine correct chunk size according to bank position and data size
-        chunkSize = MPU6050_DMP_MEMORY_CHUNK_SIZE;
-
-        // make sure we don't go past the data size
-        if (i + chunkSize > dataSize) chunkSize = dataSize - i;
-
-        // make sure this chunk doesn't go past the bank boundary (256 bytes)
-        if (chunkSize > 256 - address) chunkSize = 256 - address;
-
-        // read the chunk of data as specified
-        I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_MEM_R_W, chunkSize, data + i);
-        
-        // increase byte index by [chunkSize]
-        i += chunkSize;
-
-        // uint8_t automatically wraps to 0 at 256
-        address += chunkSize;
-
-        // if we aren't done, update bank (if necessary) and address
-        if (i < dataSize) {
-            if (address == 0) bank++;
-            MPU6050_setMemoryBank(bank, false, false);
-            MPU6050_setMemoryStartAddress(address);
-        }
-    }
-}
-/*bool MPU6050_writeMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address, bool verify, bool useProgMem) {
-    MPU6050_setMemoryBank(bank, false, false);
-    MPU6050_setMemoryStartAddress(address);
-    uint8_t chunkSize;
-    uint8_t *verifyBuffer;
-    uint8_t *progBuffer;
-    uint16_t i;
-    uint8_t j;
-    if (verify) verifyBuffer = (uint8_t *)malloc(MPU6050_DMP_MEMORY_CHUNK_SIZE);
-    if (useProgMem) progBuffer = (uint8_t *)malloc(MPU6050_DMP_MEMORY_CHUNK_SIZE);
-    for (i = 0; i < dataSize;) {
-        // determine correct chunk size according to bank position and data size
-        chunkSize = MPU6050_DMP_MEMORY_CHUNK_SIZE;
-
-        // make sure we don't go past the data size
-        if (i + chunkSize > dataSize) chunkSize = dataSize - i;
-
-        // make sure this chunk doesn't go past the bank boundary (256 bytes)
-        if (chunkSize > 256 - address) chunkSize = 256 - address;
-        
-        if (useProgMem) {
-            // write the chunk of data as specified
-            for (j = 0; j < chunkSize; j++) progBuffer[j] = pgm_read_byte(data + i + j);
-        } else {
-            // write the chunk of data as specified
-            progBuffer = (uint8_t *)data + i;
-        }
-
-        I2Cdev_writeBytes(mpu6050.devAddr, MPU6050_RA_MEM_R_W, chunkSize, progBuffer);
-
-        // verify data if needed
-        if (verify && verifyBuffer) {
-            MPU6050_setMemoryBank(bank, false, false);
-            MPU6050_setMemoryStartAddress(address);
-            I2Cdev_readBytes(mpu6050.devAddr, MPU6050_RA_MEM_R_W, chunkSize, verifyBuffer);
-            if (memcmp(progBuffer, verifyBuffer, chunkSize) != 0) {
-                //Serial.print("Block write verification error, bank ");
-                //Serial.print(bank, DEC);
-                //Serial.print(", address ");
-                //Serial.print(address, DEC);
-                //Serial.print("!\nExpected:");
-                //for (j = 0; j < chunkSize; j++) {
-                //    Serial.print(" 0x");
-                //    if (progBuffer[j] < 16) Serial.print("0");
-                //    Serial.print(progBuffer[j], HEX);
-                //}
-                //Serial.print("\nReceived:");
-                //for (uint8_t j = 0; j < chunkSize; j++) {
-                //    Serial.print(" 0x");
-                //    if (verifyBuffer[i + j] < 16) Serial.print("0");
-                //    Serial.print(verifyBuffer[i + j], HEX);
-                //}
-                Serial.print("\n");
-                free(verifyBuffer);
-                if (useProgMem) free(progBuffer);
-                return false; // uh oh.
-            }
-        }
-
-        // increase byte index by [chunkSize]
-        i += chunkSize;
-
-        // uint8_t automatically wraps to 0 at 256
-        address += chunkSize;
-
-        // if we aren't done, update bank (if necessary) and address
-        if (i < dataSize) {
-            if (address == 0) bank++;
-            MPU6050_setMemoryBank(bank, false, false);
-            MPU6050_setMemoryStartAddress(address);
-        }
-    }
-    if (verify) free(verifyBuffer);
-    if (useProgMem) free(progBuffer);
-    return true;
-}
-bool MPU6050_writeProgMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address, bool verify) {
-    return MPU6050_writeMemoryBlock(data, dataSize, bank, address, verify, true);
-}
-bool MPU6050_writeDMPConfigurationSet(const uint8_t *data, uint16_t dataSize, bool useProgMem) {
-    uint8_t *progBuffer, success, special;
-    uint16_t i, j;
-    if (useProgMem) {
-        progBuffer = (uint8_t *)malloc(8); // assume 8-byte blocks, realloc later if necessary
-    }
-
-    // config set data is a long string of blocks with the following structure:
-    // [bank] [offset] [length] [byte[0], byte[1], ..., byte[length]]
-    uint8_t bank, offset, length;
-    for (i = 0; i < dataSize;) {
-        if (useProgMem) {
-            bank = pgm_read_byte(data + i++);
-            offset = pgm_read_byte(data + i++);
-            length = pgm_read_byte(data + i++);
-        } else {
-            bank = data[i++];
-            offset = data[i++];
-            length = data[i++];
-        }
-
-        // write data or perform special action
-        if (length > 0) {
-            // regular block of data to write
-            //Serial.print("Writing config block to bank ");
-            //Serial.print(bank);
-            //Serial.print(", offset ");
-            //Serial.print(offset);
-            //Serial.print(", length=");
-            //Serial.println(length);
-            if (useProgMem) {
-                if (sizeof(progBuffer) < length) progBuffer = (uint8_t *)realloc(progBuffer, length);
-                for (j = 0; j < length; j++) progBuffer[j] = pgm_read_byte(data + i + j);
-            } else {
-                progBuffer = (uint8_t *)data + i;
-            }
-            success = MPU6050_writeMemoryBlock(progBuffer, length, bank, offset, true);
-            i += length;
-        } else {
-            // special instruction
-            // NOTE: this kind of behavior (what and when to do certain things)
-            // is totally undocumented. This code is in here based on observed
-            // behavior only, and exactly why (or even whether) it has to be here
-            // is anybody's guess for now.
-            if (useProgMem) {
-                special = pgm_read_byte(data + i++);
-            } else {
-                special = data[i++];
-            }
-            //Serial.print("Special command code ");
-            //Serial.print(special, HEX);
-            //Serial.println(" found...");
-            if (special == 0x01) {
-                // enable DMP-related interrupts
-                
-                //setIntZeroMotionEnabled(true);
-                //setIntFIFOBufferOverflowEnabled(true);
-                //setIntDMPEnabled(true);
-                I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_INT_ENABLE, 0x32);  // single operation
-
-                success = true;
-            } else {
-                // unknown special command
-                success = false;
-            }
-        }
-        
-        if (!success) {
-            if (useProgMem) free(progBuffer);
-            return false; // uh oh
-        }
-    }
-    if (useProgMem) free(progBuffer);
-    return true;
-}
-bool MPU6050_writeProgDMPConfigurationSet(const uint8_t *data, uint16_t dataSize) {
-    return MPU6050_writeDMPConfigurationSet(data, dataSize, true);
-}*/
-
-// DMP_CFG_1 register
-
-uint8_t MPU6050_getDMPConfig1() {
-    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_DMP_CFG_1, mpu6050.buffer);
-    return mpu6050.buffer[0];
-}
-void MPU6050_setDMPConfig1(uint8_t config) {
-    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_DMP_CFG_1, config);
-}
-
-// DMP_CFG_2 register
-
-uint8_t MPU6050_getDMPConfig2() {
-    I2Cdev_readByte(mpu6050.devAddr, MPU6050_RA_DMP_CFG_2, mpu6050.buffer);
-    return mpu6050.buffer[0];
-}
-void MPU6050_setDMPConfig2(uint8_t config) {
-    I2Cdev_writeByte(mpu6050.devAddr, MPU6050_RA_DMP_CFG_2, config);
-}
\ No newline at end of file
diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050_example_main.c b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050_example_main.c
index 3bcc2f82..10605f04 100644
--- a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050_example_main.c
+++ b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/MPU6050_example_main.c
@@ -53,42 +53,46 @@ int16_t ax, ay, az, gx, gy, gz;
 void __attribute__((__interrupt__)) _U2TXInterrupt(void)
 {  
    IFS1bits.U2TXIF = 0;
-} 
-/* This is UART1 receive ISR */
-//void __attribute__((__interrupt__)) _U1RXInterrupt(void)
-//{
-//    IFS0bits.U1RXIF = 0;
-/* Read the receive buffer till atleast one or more character can be read */ 
-//    while( DataRdyUART1())
-//    {
-//        ( *(Receivedddata)++) = ReadUART1();
-//    } 
-//} 
+}
+
+/*******************************************************************************/
+//  delay us using for-loop
+/*******************************************************************************/
+void delay_us( unsigned int usec )
+{
+	unsigned int i;
+	//?   ?   ?   ?   ?   ?   ?   ?   ?   ?              //40 MIPS ,
+	for ( i = 0 ; i < usec * 2;
+	        i++ ) {                //for-loop 8Tcy -> 1us -> add two NOP()
+		asm("NOP");
+		asm("NOP");
+	}
+}
 
+/*******************************************************************************/
+// delay ms using Timer 1 interrupt
+/*******************************************************************************/
+void delay_ms( unsigned int msec )
+{
+	int i = 0;
+	for (i = 0; i < msec; i++)
+		delay_us(1000);
+}
 int main(void)
 {
-    //delay_ms(1000);
-    
     TRISCbits.TRISC14 = 0;
     LATCbits.LATC14 = 1;
-            
     while(1){
-    HEAD:
         /* Data to be transmitted using UART communication module */
-            //TRISFbits.TRISF3 = 0;
-            //PORTFbits.RF3 = 0;
-            //delay_ms(10);
-            //PORTFbits.RF3 = 1;
         TRISFbits.TRISF3 = 0;
         TRISFbits.TRISF2 = 0;
         char Buffer[80];
-        //char 
         /* Holds the value of baud register   */
-        unsigned int baudvalue;   
+        unsigned int baudvalue;
         /* Holds the value of uart config reg */
         unsigned int U2MODEvalue;
         /* Holds the information regarding uart
-        TX & RX interrupt modes */   
+        TX & RX interrupt modes */
         unsigned int U2STAvalue;
         CloseI2C();
         /* Turn off UART1module */
@@ -97,11 +101,11 @@ int main(void)
         ConfigIntUART2(  UART_TX_INT_DIS & UART_TX_INT_PR2);
         /* Configure UART1 module to transmit 8 bit data with one stopbit. Also Enable loopback mode  */
         baudvalue = 15;//129;  //9600
-        U2MODEvalue = UART_EN & UART_IDLE_CON & 
+        U2MODEvalue = UART_EN & UART_IDLE_CON &
                       UART_DIS_WAKE & UART_DIS_LOOPBACK  &
                       UART_EN_ABAUD & UART_NO_PAR_8BIT  &
                       UART_1STOPBIT;
-        U2STAvalue  = UART_INT_TX_BUF_EMPTY  &  
+        U2STAvalue  = UART_INT_TX_BUF_EMPTY  &
                       UART_TX_PIN_NORMAL &
                       UART_TX_ENABLE & UART_INT_RX_3_4_FUL &
                       UART_ADR_DETECT_DIS &
@@ -125,23 +129,15 @@ int main(void)
         putsUART2 ((unsigned int *)Buf);
         /* Wait for  transmission to complete */
         while(BusyUART2());
-        //MPU6050_reset();
-        //delay_ms(100);
-        //MPU6050_resetGyroscopePath();
-        //MPU6050_resetAccelerometerPath();
-        //MPU6050_resetTemperaturePath();
-        //delay_ms(100);
         MPU6050_initialize();
-        
+
         unsigned char MPU6050_ID = MPU6050_getDeviceID();
-        
+
         sprintf(Buf,"Testing device connections...\n\0");
         putsUART2 ((unsigned int *)Buf);
         /* Wait for  transmission to complete */
         while(BusyUART2());
 
-        
-
         sprintf(Buf,"MPU6050_ID = 0x%X\n",MPU6050_ID);
         putsUART2 ((unsigned int *)Buf);
         /* Wait for  transmission to complete */
@@ -153,10 +149,10 @@ int main(void)
         putsUART2 ((unsigned int *)Buf);
         /* Wait for  transmission to complete */
         while(BusyUART2());
-        
+
         if (!MPU6050_testConnection())
-            goto HEAD;
-        
+            continue;
+
         sprintf(Buf,"Reading offset\n");
         putsUART2 ((unsigned int *)Buf);
         /* Wait for  transmission to complete */
@@ -171,39 +167,31 @@ int main(void)
         putsUART2 ((unsigned int *)Buf);
         /* Wait for  transmission to complete */
         while(BusyUART2());
-        
+
         sprintf(Buf,"Zaccel= %d\n",MPU6050_getZAccelOffset());
         putsUART2 ((unsigned int *)Buf);
         /* Wait for  transmission to complete */
         while(BusyUART2());
-        
+
         sprintf(Buf,"Xgyro= %d\n",MPU6050_getXGyroOffset());
         putsUART2 ((unsigned int *)Buf);
         /* Wait for  transmission to complete */
         while(BusyUART2());
-        
+
         sprintf(Buf,"Ygyro= %d\n",MPU6050_getYGyroOffset());
         putsUART2 ((unsigned int *)Buf);
         /* Wait for  transmission to complete */
         while(BusyUART2());
-        
+
         sprintf(Buf,"Zgyro= %d\n",MPU6050_getZGyroOffset());
         putsUART2 ((unsigned int *)Buf);
         /* Wait for  transmission to complete */
         while(BusyUART2());
-        
-        //delay_ms(100);
-        
+
         MPU6050_setXGyroOffset(220);
-        
-        //delay_ms(100);
-        
         MPU6050_setYGyroOffset(76);
-        
-        //delay_ms(100);
-        
         MPU6050_setZGyroOffset(-85);
-        
+
         sprintf(Buf,"Reading Updated offset\n");
         putsUART2 ((unsigned int *)Buf);
         /* Wait for  transmission to complete */
@@ -218,28 +206,27 @@ int main(void)
         putsUART2 ((unsigned int *)Buf);
         /* Wait for  transmission to complete */
         while(BusyUART2());
-        
+
         sprintf(Buf,"Zaccel= %d\n",MPU6050_getZAccelOffset());
         putsUART2 ((unsigned int *)Buf);
         /* Wait for  transmission to complete */
         while(BusyUART2());
-        
+
         sprintf(Buf,"Xgyro= %d\n",MPU6050_getXGyroOffset());
         putsUART2 ((unsigned int *)Buf);
         /* Wait for  transmission to complete */
         while(BusyUART2());
-        
+
         sprintf(Buf,"Ygyro= %d\n",MPU6050_getYGyroOffset());
         putsUART2 ((unsigned int *)Buf);
         /* Wait for  transmission to complete */
         while(BusyUART2());
-        
+
         sprintf(Buf,"Zgyro= %d\n",MPU6050_getZGyroOffset());
         putsUART2 ((unsigned int *)Buf);
         /* Wait for  transmission to complete */
         while(BusyUART2());
-        
-        
+
         MPU6050_setSleepEnabled(false);
         while (true) {
            // Read raw accel/gyro measurements from device
@@ -250,14 +237,12 @@ int main(void)
             putsUART2 ((unsigned int *)Buf);
             /* Wait for  transmission to complete */
             while(BusyUART2());
-        
             // Blink LED to indicate activity
             LATCbits.LATC14 ^= 1;
 
             delay_ms(25);
             delay_ms(25);
         }
-        
         //CloseUART2();
 
     }
diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Makefile-default.mk b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Makefile-default.mk
index 2e73c4ab..11a69249 100644
--- a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Makefile-default.mk
+++ b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Makefile-default.mk
@@ -44,6 +44,12 @@ else
 COMPARISON_BUILD=
 endif
 
+ifdef SUB_IMAGE_ADDRESS
+SUB_IMAGE_ADDRESS_COMMAND=--image-address $(SUB_IMAGE_ADDRESS)
+else
+SUB_IMAGE_ADDRESS_COMMAND=
+endif
+
 # Object Directory
 OBJECTDIR=build/${CND_CONF}/${IMAGE_TYPE}
 
@@ -150,12 +156,12 @@ endif
 ifeq ($(TYPE_IMAGE), DEBUG_RUN)
 dist/${CND_CONF}/${IMAGE_TYPE}/MPU6050_example.X.${IMAGE_TYPE}.${OUTPUT_SUFFIX}: ${OBJECTFILES}  nbproject/Makefile-${CND_CONF}.mk    
 	@${MKDIR} dist/${CND_CONF}/${IMAGE_TYPE} 
-	${MP_CC} $(MP_EXTRA_LD_PRE)  -o dist/${CND_CONF}/${IMAGE_TYPE}/MPU6050_example.X.${IMAGE_TYPE}.${OUTPUT_SUFFIX}  ${OBJECTFILES_QUOTED_IF_SPACED}      -mcpu=$(MP_PROCESSOR_OPTION)        -D__DEBUG -D__MPLAB_DEBUGGER_PK3=1  -omf=elf -DXPRJ_default=$(CND_CONF)  -legacy-libc  $(COMPARISON_BUILD)  --std=gnu99  -mreserve=data@0x800:0x81F -mreserve=data@0x820:0x821 -mreserve=data@0x822:0x823 -mreserve=data@0x824:0x84F   -Wl,,--defsym=__MPLAB_BUILD=1,--defsym=__MPLAB_DEBUG=1,--defsym=__DEBUG=1,--defsym=__MPLAB_DEBUGGER_PK3=1,$(MP_LINKER_FILE_OPTION),--stack=16,--check-sections,--data-init,--pack-data,--handles,--isr,--no-gc-sections,--fill-upper=0,--stackguard=16,--no-force-link,--smart-io,-Map="${DISTDIR}/${PROJECTNAME}.${IMAGE_TYPE}.map",--report-mem,--memorysummary,dist/${CND_CONF}/${IMAGE_TYPE}/memoryfile.xml$(MP_EXTRA_LD_POST) 
+	${MP_CC} $(MP_EXTRA_LD_PRE)  -o dist/${CND_CONF}/${IMAGE_TYPE}/MPU6050_example.X.${IMAGE_TYPE}.${OUTPUT_SUFFIX}  ${OBJECTFILES_QUOTED_IF_SPACED}      -mcpu=$(MP_PROCESSOR_OPTION)        -D__DEBUG -D__MPLAB_DEBUGGER_PK3=1  -omf=elf -DXPRJ_default=$(CND_CONF)  -legacy-libc  $(COMPARISON_BUILD)  --std=gnu99  -mreserve=data@0x800:0x81F -mreserve=data@0x820:0x821 -mreserve=data@0x822:0x823 -mreserve=data@0x824:0x84F   -Wl,,,--defsym=__MPLAB_BUILD=1,--defsym=__MPLAB_DEBUG=1,--defsym=__DEBUG=1,--defsym=__MPLAB_DEBUGGER_PK3=1,$(MP_LINKER_FILE_OPTION),--stack=16,--check-sections,--data-init,--pack-data,--handles,--isr,--no-gc-sections,--fill-upper=0,--stackguard=16,--no-force-link,--smart-io,-Map="${DISTDIR}/${PROJECTNAME}.${IMAGE_TYPE}.map",--report-mem,--memorysummary,dist/${CND_CONF}/${IMAGE_TYPE}/memoryfile.xml$(MP_EXTRA_LD_POST) 
 	
 else
 dist/${CND_CONF}/${IMAGE_TYPE}/MPU6050_example.X.${IMAGE_TYPE}.${OUTPUT_SUFFIX}: ${OBJECTFILES}  nbproject/Makefile-${CND_CONF}.mk   
 	@${MKDIR} dist/${CND_CONF}/${IMAGE_TYPE} 
-	${MP_CC} $(MP_EXTRA_LD_PRE)  -o dist/${CND_CONF}/${IMAGE_TYPE}/MPU6050_example.X.${IMAGE_TYPE}.${DEBUGGABLE_SUFFIX}  ${OBJECTFILES_QUOTED_IF_SPACED}      -mcpu=$(MP_PROCESSOR_OPTION)        -omf=elf -DXPRJ_default=$(CND_CONF)  -legacy-libc  $(COMPARISON_BUILD)  --std=gnu99 -Wl,,--defsym=__MPLAB_BUILD=1,$(MP_LINKER_FILE_OPTION),--stack=16,--check-sections,--data-init,--pack-data,--handles,--isr,--no-gc-sections,--fill-upper=0,--stackguard=16,--no-force-link,--smart-io,-Map="${DISTDIR}/${PROJECTNAME}.${IMAGE_TYPE}.map",--report-mem,--memorysummary,dist/${CND_CONF}/${IMAGE_TYPE}/memoryfile.xml$(MP_EXTRA_LD_POST) 
+	${MP_CC} $(MP_EXTRA_LD_PRE)  -o dist/${CND_CONF}/${IMAGE_TYPE}/MPU6050_example.X.${IMAGE_TYPE}.${DEBUGGABLE_SUFFIX}  ${OBJECTFILES_QUOTED_IF_SPACED}      -mcpu=$(MP_PROCESSOR_OPTION)        -omf=elf -DXPRJ_default=$(CND_CONF)  -legacy-libc  $(COMPARISON_BUILD)  --std=gnu99 -Wl,,,--defsym=__MPLAB_BUILD=1,$(MP_LINKER_FILE_OPTION),--stack=16,--check-sections,--data-init,--pack-data,--handles,--isr,--no-gc-sections,--fill-upper=0,--stackguard=16,--no-force-link,--smart-io,-Map="${DISTDIR}/${PROJECTNAME}.${IMAGE_TYPE}.map",--report-mem,--memorysummary,dist/${CND_CONF}/${IMAGE_TYPE}/memoryfile.xml$(MP_EXTRA_LD_POST) 
 	${MP_CC_DIR}/xc16-bin2hex dist/${CND_CONF}/${IMAGE_TYPE}/MPU6050_example.X.${IMAGE_TYPE}.${DEBUGGABLE_SUFFIX} -a  -omf=elf  
 	
 endif
diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Makefile-genesis.properties b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Makefile-genesis.properties
index 86a933b5..b83100c2 100644
--- a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Makefile-genesis.properties
+++ b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Makefile-genesis.properties
@@ -1,9 +1,9 @@
 #
-#Wed Apr 26 14:40:23 CST 2017
-default.com-microchip-mplab-nbide-toolchainXC16-XC16LanguageToolchain.md5=ebaa75370c1463d650408e4144ba15de
-default.languagetoolchain.dir=/opt/microchip/xc16/v1.30/bin
-configurations-xml=390e761992510ba6b77d8cf6d2379168
-com-microchip-mplab-nbide-embedded-makeproject-MakeProject.md5=8b140fb87818dc96ed4f726b716b40e9
-default.languagetoolchain.version=1.30
+#Wed Apr 26 15:57:55 CST 2017
+default.com-microchip-mplab-nbide-toolchainXC16-XC16LanguageToolchain.md5=10deee1b358b9eb8b4aaaeb9dce00420
+default.languagetoolchain.dir=/opt/microchip/xc16/v1.31/bin
+configurations-xml=fd1da04a6257bc2861900a03a85b49c1
+com-microchip-mplab-nbide-embedded-makeproject-MakeProject.md5=68c66d83550b716fa3e84319671e802c
+default.languagetoolchain.version=1.31
 host.platform=linux
 conf.ids=default
diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Makefile-local-default.mk b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Makefile-local-default.mk
index 38870624..867c8d36 100644
--- a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Makefile-local-default.mk
+++ b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/Makefile-local-default.mk
@@ -14,23 +14,23 @@
 # You can invoke make with the values of the macros:
 # $ makeMP_CC="/opt/microchip/mplabc30/v3.30c/bin/pic30-gcc" ...  
 #
-PATH_TO_IDE_BIN=/opt/microchip/mplabx/v3.45/mplab_ide/platform/../mplab_ide/modules/../../bin/
+PATH_TO_IDE_BIN=/opt/microchip/mplabx/v3.60/mplab_ide/platform/../mplab_ide/modules/../../bin/
 # Adding MPLAB X bin directory to path.
-PATH:=/opt/microchip/mplabx/v3.45/mplab_ide/platform/../mplab_ide/modules/../../bin/:$(PATH)
+PATH:=/opt/microchip/mplabx/v3.60/mplab_ide/platform/../mplab_ide/modules/../../bin/:$(PATH)
 # Path to java used to run MPLAB X when this makefile was created
-MP_JAVA_PATH="/opt/microchip/mplabx/v3.45/sys/java/jre1.8.0_91/bin/"
+MP_JAVA_PATH="/opt/microchip/mplabx/v3.60/sys/java/jre1.8.0_121/bin/"
 OS_CURRENT="$(shell uname -s)"
-MP_CC="/opt/microchip/xc16/v1.30/bin/xc16-gcc"
+MP_CC="/opt/microchip/xc16/v1.31/bin/xc16-gcc"
 # MP_CPPC is not defined
 # MP_BC is not defined
-MP_AS="/opt/microchip/xc16/v1.30/bin/xc16-as"
-MP_LD="/opt/microchip/xc16/v1.30/bin/xc16-ld"
-MP_AR="/opt/microchip/xc16/v1.30/bin/xc16-ar"
-DEP_GEN=${MP_JAVA_PATH}java -jar "/opt/microchip/mplabx/v3.45/mplab_ide/platform/../mplab_ide/modules/../../bin/extractobjectdependencies.jar"
-MP_CC_DIR="/opt/microchip/xc16/v1.30/bin"
+MP_AS="/opt/microchip/xc16/v1.31/bin/xc16-as"
+MP_LD="/opt/microchip/xc16/v1.31/bin/xc16-ld"
+MP_AR="/opt/microchip/xc16/v1.31/bin/xc16-ar"
+DEP_GEN=${MP_JAVA_PATH}java -jar "/opt/microchip/mplabx/v3.60/mplab_ide/platform/../mplab_ide/modules/../../bin/extractobjectdependencies.jar"
+MP_CC_DIR="/opt/microchip/xc16/v1.31/bin"
 # MP_CPPC_DIR is not defined
 # MP_BC_DIR is not defined
-MP_AS_DIR="/opt/microchip/xc16/v1.30/bin"
-MP_LD_DIR="/opt/microchip/xc16/v1.30/bin"
-MP_AR_DIR="/opt/microchip/xc16/v1.30/bin"
+MP_AS_DIR="/opt/microchip/xc16/v1.31/bin"
+MP_LD_DIR="/opt/microchip/xc16/v1.31/bin"
+MP_AR_DIR="/opt/microchip/xc16/v1.31/bin"
 # MP_BC_DIR is not defined
diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/configurations.xml b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/configurations.xml
index f2f34ca0..6fd8b07f 100644
--- a/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/configurations.xml
+++ b/dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/configurations.xml
@@ -34,7 +34,7 @@
         
         PICkit3PlatformTool
         XC16
-        1.30
+        1.31
         2
       
       
@@ -131,6 +131,7 @@
         
         
         
+        
         
         
         
@@ -155,8 +156,11 @@
         
         
         
+        
         
         
+        
+        
         
         
         
@@ -219,6 +223,327 @@
         
         
       
+      
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+      
     
   
 
diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/Makefile b/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/Makefile
deleted file mode 100644
index fca8e2cc..00000000
--- a/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/Makefile
+++ /dev/null
@@ -1,113 +0,0 @@
-#
-#  There exist several targets which are by default empty and which can be 
-#  used for execution of your targets. These targets are usually executed 
-#  before and after some main targets. They are: 
-#
-#     .build-pre:              called before 'build' target
-#     .build-post:             called after 'build' target
-#     .clean-pre:              called before 'clean' target
-#     .clean-post:             called after 'clean' target
-#     .clobber-pre:            called before 'clobber' target
-#     .clobber-post:           called after 'clobber' target
-#     .all-pre:                called before 'all' target
-#     .all-post:               called after 'all' target
-#     .help-pre:               called before 'help' target
-#     .help-post:              called after 'help' target
-#
-#  Targets beginning with '.' are not intended to be called on their own.
-#
-#  Main targets can be executed directly, and they are:
-#  
-#     build                    build a specific configuration
-#     clean                    remove built files from a configuration
-#     clobber                  remove all built files
-#     all                      build all configurations
-#     help                     print help mesage
-#  
-#  Targets .build-impl, .clean-impl, .clobber-impl, .all-impl, and
-#  .help-impl are implemented in nbproject/makefile-impl.mk.
-#
-#  Available make variables:
-#
-#     CND_BASEDIR                base directory for relative paths
-#     CND_DISTDIR                default top distribution directory (build artifacts)
-#     CND_BUILDDIR               default top build directory (object files, ...)
-#     CONF                       name of current configuration
-#     CND_ARTIFACT_DIR_${CONF}   directory of build artifact (current configuration)
-#     CND_ARTIFACT_NAME_${CONF}  name of build artifact (current configuration)
-#     CND_ARTIFACT_PATH_${CONF}  path to build artifact (current configuration)
-#     CND_PACKAGE_DIR_${CONF}    directory of package (current configuration)
-#     CND_PACKAGE_NAME_${CONF}   name of package (current configuration)
-#     CND_PACKAGE_PATH_${CONF}   path to package (current configuration)
-#
-# NOCDDL
-
-
-# Environment 
-MKDIR=mkdir
-CP=cp
-CCADMIN=CCadmin
-RANLIB=ranlib
-
-
-# build
-build: .build-post
-
-.build-pre:
-# Add your pre 'build' code here...
-
-.build-post: .build-impl
-# Add your post 'build' code here...
-
-
-# clean
-clean: .clean-post
-
-.clean-pre:
-# Add your pre 'clean' code here...
-# WARNING: the IDE does not call this target since it takes a long time to
-# simply run make. Instead, the IDE removes the configuration directories
-# under build and dist directly without calling make.
-# This target is left here so people can do a clean when running a clean
-# outside the IDE.
-
-.clean-post: .clean-impl
-# Add your post 'clean' code here...
-
-
-# clobber
-clobber: .clobber-post
-
-.clobber-pre:
-# Add your pre 'clobber' code here...
-
-.clobber-post: .clobber-impl
-# Add your post 'clobber' code here...
-
-
-# all
-all: .all-post
-
-.all-pre:
-# Add your pre 'all' code here...
-
-.all-post: .all-impl
-# Add your post 'all' code here...
-
-
-# help
-help: .help-post
-
-.help-pre:
-# Add your pre 'help' code here...
-
-.help-post: .help-impl
-# Add your post 'help' code here...
-
-
-
-# include project implementation makefile
-include nbproject/Makefile-impl.mk
-
-# include project make variables
-include nbproject/Makefile-variables.mk
diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/funclist b/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/funclist
deleted file mode 100644
index bf32657d..00000000
--- a/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/funclist
+++ /dev/null
@@ -1,37 +0,0 @@
-_MPU6050_initialize: CODE, 6334 0 24
-_I2Cdev_writeBytes: CODE, 5202 0 156
-_MPU6050_getDeviceID: CODE, 6310 0 24
-__stringdata: SMALLCONST, 3851 0 193
-_putch: CODE, 6552 0 12
-_MPU6050_getXGyroOffset: CODE, 6188 0 42
-_MPU6050_getYGyroOffset: CODE, 6104 0 42
-_MPU6050_getZGyroOffset: CODE, 6020 0 42
-_dpowers: SMALLCONST, 3841 0 10
-_I2Cdev_readByte: CODE, 6514 0 20
-_I2Cdev_writeBit: CODE, 5474 0 110
-_main: CODE, 4046 0 342
-_I2Cdev_readBits: CODE, 5584 0 108
-_MPU6050_setFullScaleGyroRange: CODE, 6358 0 24
-_MPU6050_setSleepEnabled: CODE, 6474 0 20
-_MPU6050: CODE, 6584 0 8
-_MPU6050_setClockSource: CODE, 6406 0 24
-__initialization: CODE, 6430 0 12
-___lwdiv: CODE, 5884 0 74
-_MPU6050_setFullScaleAccelRange: CODE, 6382 0 24
-_baud1USART: CODE, 6576 0 8
-_Write1USART: CODE, 6534 0 18
-_printf: CODE, 4706 0 294
-___lwmod: CODE, 5958 0 62
-_MPU6050_testConnection: CODE, 6564 0 12
-_ReadI2C1: CODE, 6272 0 38
-_MPU6050_getXAccelOffset: CODE, 6230 0 42
-_MPU6050_getYAccelOffset: CODE, 6146 0 42
-_MPU6050_getZAccelOffset: CODE, 6062 0 42
-_WriteI2C1: CODE, 5692 0 108
-_I2Cdev_writeByte: CODE, 6494 0 20
-_Open1USART: CODE, 5800 0 84
-_I2Cdev_readBytes: CODE, 4388 0 318
-_I2Cdev_writeBits: CODE, 5358 0 116
-_MPU6050_getMotion6: CODE, 5000 0 202
-_OpenI2C1: CODE, 6452 0 22
-Total: 2739
\ No newline at end of file
diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/l.obj b/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/l.obj
deleted file mode 100644
index 1734cc8674a5c31b28cd2bf0bf9b45b350e67c21..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 24233
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
-// 11/28/2014 by Marton Sebok 
-//
-// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
-//
-// Changelog:
-//     2014-11-28 - ported to PIC18 peripheral library from Arduino code
-
-/* ============================================
-I2Cdev device library code is placed under the MIT license
-Copyright (c) 2011 Jeff Rowberg
-Copyright (c) 2014 Marton Sebok
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-===============================================
-*/
-
-/*
- * The project can be run without modification on Microchip's 8-bit Wireless
- * Development Kit. Please set the type of your IC in project properties/Conf/
- * Device and change the code as needed.
- */
-
-// PLL Prescaler Selection bits (Divide by 2 (8 MHz oscillator input))
-#pragma config PLLDIV = 2
-
-// Extended Instruction Set (Disabled)
-#pragma config XINST = OFF
-
-// CPU System Clock Postscaler (CPU system clock divide by 2)
-#pragma config CPUDIV = OSC2_PLL2
-
-// Oscillator (HS+PLL, USB-HS+PLL)
-#pragma config OSC = HSPLL
-
-#define USE_OR_MASKS
-#define _XTAL_FREQ 24000000
-
-#include 
-#include 
-#include 
-#include 
-#include 
-
-/*
- * You must add the I2Cdev and MPU6050 directories as include directories in
- * project properties/Conf/General options/XC8 global option/XC8 compiler/
- * Preprocessing and messages/Include directories.
- */
-#include "I2Cdev.h"
-#include "MPU6050.h"
-
-#define LED_PIN LATBbits.LATB1
-
-/**
- * Write one char to USART
- * @param data
- */
-void putch(char data) {
-    while (Busy1USART());
-    Write1USART(data);
-}
-
-/**
- * Main function
- */
-int main() {
-    int16_t ax, ay, az, gx, gy, gz;
-    
-    // Initialize system
-    // PLL (24 MHz)
-    OSCTUNEbits.PLLEN = 1;
-    __delay_ms(25);
-    __delay_ms(25);
-
-    // LED
-    LED_PIN = 0;
-    TRISBbits.TRISB1 = 0;
-
-    // Serial (115200 kbps)
-    Open1USART(USART_TX_INT_OFF | USART_RX_INT_OFF | USART_ASYNCH_MODE |
-        USART_EIGHT_BIT | USART_CONT_RX | USART_BRGH_HIGH, 12);
-    baud1USART(BAUD_8_BIT_RATE | BAUD_AUTO_OFF);
-
-    // I2C (400 kHz)
-    OpenI2C(MASTER, SLEW_OFF);
-    SSP1ADD = 14;
-
-    // MPU6050
-    MPU6050(MPU6050_ADDRESS_AD0_LOW);
-
-    // Initialize device
-    printf("Initializing I2C devices...\r\n");
-    MPU6050_initialize();
-
-    // Verify connection
-    printf("Testing device connections...\r\n");
-    printf(MPU6050_testConnection() ? "MPU6050 connection successful\r\n" :
-        "MPU6050 connection failed\r\n");
-
-    printf("Reading internal sensor offsets...\r\n");
-    printf("%d\t", MPU6050_getXAccelOffset());
-    printf("%d\t", MPU6050_getYAccelOffset());
-    printf("%d\t", MPU6050_getZAccelOffset());
-    printf("%d\t", MPU6050_getXGyroOffset());
-    printf("%d\t", MPU6050_getYGyroOffset());
-    printf("%d\t\n", MPU6050_getZGyroOffset());
-
-    while (true) {
-        // Read raw accel/gyro measurements from device
-        MPU6050_getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
-
-        // Display tab-separated accel/gyro x/y/z values
-        printf("a/g:\t%d\t%d\t%d\t%d\t%d\t%d\r\n", ax, ay, az, gx, gy, gz);
-
-        // Blink LED to indicate activity
-        LED_PIN ^= 1;
-
-        __delay_ms(25);
-        __delay_ms(25);
-    }
-}
diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-default.mk b/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-default.mk
deleted file mode 100644
index 1c5f0ec6..00000000
--- a/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-default.mk
+++ /dev/null
@@ -1,172 +0,0 @@
-#
-# Generated Makefile - do not edit!
-#
-# Edit the Makefile in the project folder instead (../Makefile). Each target
-# has a -pre and a -post target defined where you can add customized code.
-#
-# This makefile implements configuration specific macros and targets.
-
-
-# Include project Makefile
-ifeq "${IGNORE_LOCAL}" "TRUE"
-# do not include local makefile. User is passing all local related variables already
-else
-include Makefile
-# Include makefile containing local settings
-ifeq "$(wildcard nbproject/Makefile-local-default.mk)" "nbproject/Makefile-local-default.mk"
-include nbproject/Makefile-local-default.mk
-endif
-endif
-
-# Environment
-MKDIR=gnumkdir -p
-RM=rm -f 
-MV=mv 
-CP=cp 
-
-# Macros
-CND_CONF=default
-ifeq ($(TYPE_IMAGE), DEBUG_RUN)
-IMAGE_TYPE=debug
-OUTPUT_SUFFIX=elf
-DEBUGGABLE_SUFFIX=elf
-FINAL_IMAGE=dist/${CND_CONF}/${IMAGE_TYPE}/MPU6050_raw.X.${IMAGE_TYPE}.${OUTPUT_SUFFIX}
-else
-IMAGE_TYPE=production
-OUTPUT_SUFFIX=hex
-DEBUGGABLE_SUFFIX=elf
-FINAL_IMAGE=dist/${CND_CONF}/${IMAGE_TYPE}/MPU6050_raw.X.${IMAGE_TYPE}.${OUTPUT_SUFFIX}
-endif
-
-# Object Directory
-OBJECTDIR=build/${CND_CONF}/${IMAGE_TYPE}
-
-# Distribution Directory
-DISTDIR=dist/${CND_CONF}/${IMAGE_TYPE}
-
-# Source Files Quoted if spaced
-SOURCEFILES_QUOTED_IF_SPACED=../../MPU6050.c ../../../I2Cdev/I2Cdev.c main.c
-
-# Object Files Quoted if spaced
-OBJECTFILES_QUOTED_IF_SPACED=${OBJECTDIR}/_ext/43898991/MPU6050.p1 ${OBJECTDIR}/_ext/105797386/I2Cdev.p1 ${OBJECTDIR}/main.p1
-POSSIBLE_DEPFILES=${OBJECTDIR}/_ext/43898991/MPU6050.p1.d ${OBJECTDIR}/_ext/105797386/I2Cdev.p1.d ${OBJECTDIR}/main.p1.d
-
-# Object Files
-OBJECTFILES=${OBJECTDIR}/_ext/43898991/MPU6050.p1 ${OBJECTDIR}/_ext/105797386/I2Cdev.p1 ${OBJECTDIR}/main.p1
-
-# Source Files
-SOURCEFILES=../../MPU6050.c ../../../I2Cdev/I2Cdev.c main.c
-
-
-CFLAGS=
-ASFLAGS=
-LDLIBSOPTIONS=
-
-############# Tool locations ##########################################
-# If you copy a project from one host to another, the path where the  #
-# compiler is installed may be different.                             #
-# If you open this project with MPLAB X in the new host, this         #
-# makefile will be regenerated and the paths will be corrected.       #
-#######################################################################
-# fixDeps replaces a bunch of sed/cat/printf statements that slow down the build
-FIXDEPS=fixDeps
-
-.build-conf:  ${BUILD_SUBPROJECTS}
-	${MAKE}  -f nbproject/Makefile-default.mk dist/${CND_CONF}/${IMAGE_TYPE}/MPU6050_raw.X.${IMAGE_TYPE}.${OUTPUT_SUFFIX}
-
-MP_PROCESSOR_OPTION=18F46J50
-# ------------------------------------------------------------------------------------
-# Rules for buildStep: compile
-ifeq ($(TYPE_IMAGE), DEBUG_RUN)
-${OBJECTDIR}/_ext/43898991/MPU6050.p1: ../../MPU6050.c  nbproject/Makefile-${CND_CONF}.mk
-	@${MKDIR} ${OBJECTDIR}/_ext/43898991 
-	@${RM} ${OBJECTDIR}/_ext/43898991/MPU6050.p1.d 
-	@${RM} ${OBJECTDIR}/_ext/43898991/MPU6050.p1 
-	${MP_CC} --pass1 $(MP_EXTRA_CC_PRE) --chip=$(MP_PROCESSOR_OPTION) -Q -G  -D__DEBUG=1 --debugger=pickit3  --double=24 --float=24 --emi=wordwrite --opt=default,+asm,-asmfile,+speed,-space,-debug --addrqual=ignore --mode=pro -P -N255 -I"../../../I2Cdev" -I"../../" --warn=0 --asmlist --summary=default,-psect,-class,+mem,-hex,-file --output=default,-inhx032 --runtime=default,+clear,+init,-keep,-no_startup,-download,+config,+clib,+plib --output=-mcof,+elf:multilocs --stack=compiled:auto:auto:auto "--errformat=%f:%l: error: (%n) %s" "--warnformat=%f:%l: warning: (%n) %s" "--msgformat=%f:%l: advisory: (%n) %s"    -o${OBJECTDIR}/_ext/43898991/MPU6050.p1  ../../MPU6050.c 
-	@-${MV} ${OBJECTDIR}/_ext/43898991/MPU6050.d ${OBJECTDIR}/_ext/43898991/MPU6050.p1.d 
-	@${FIXDEPS} ${OBJECTDIR}/_ext/43898991/MPU6050.p1.d $(SILENT) -rsi ${MP_CC_DIR}../  
-	
-${OBJECTDIR}/_ext/105797386/I2Cdev.p1: ../../../I2Cdev/I2Cdev.c  nbproject/Makefile-${CND_CONF}.mk
-	@${MKDIR} ${OBJECTDIR}/_ext/105797386 
-	@${RM} ${OBJECTDIR}/_ext/105797386/I2Cdev.p1.d 
-	@${RM} ${OBJECTDIR}/_ext/105797386/I2Cdev.p1 
-	${MP_CC} --pass1 $(MP_EXTRA_CC_PRE) --chip=$(MP_PROCESSOR_OPTION) -Q -G  -D__DEBUG=1 --debugger=pickit3  --double=24 --float=24 --emi=wordwrite --opt=default,+asm,-asmfile,+speed,-space,-debug --addrqual=ignore --mode=pro -P -N255 -I"../../../I2Cdev" -I"../../" --warn=0 --asmlist --summary=default,-psect,-class,+mem,-hex,-file --output=default,-inhx032 --runtime=default,+clear,+init,-keep,-no_startup,-download,+config,+clib,+plib --output=-mcof,+elf:multilocs --stack=compiled:auto:auto:auto "--errformat=%f:%l: error: (%n) %s" "--warnformat=%f:%l: warning: (%n) %s" "--msgformat=%f:%l: advisory: (%n) %s"    -o${OBJECTDIR}/_ext/105797386/I2Cdev.p1  ../../../I2Cdev/I2Cdev.c 
-	@-${MV} ${OBJECTDIR}/_ext/105797386/I2Cdev.d ${OBJECTDIR}/_ext/105797386/I2Cdev.p1.d 
-	@${FIXDEPS} ${OBJECTDIR}/_ext/105797386/I2Cdev.p1.d $(SILENT) -rsi ${MP_CC_DIR}../  
-	
-${OBJECTDIR}/main.p1: main.c  nbproject/Makefile-${CND_CONF}.mk
-	@${MKDIR} ${OBJECTDIR} 
-	@${RM} ${OBJECTDIR}/main.p1.d 
-	@${RM} ${OBJECTDIR}/main.p1 
-	${MP_CC} --pass1 $(MP_EXTRA_CC_PRE) --chip=$(MP_PROCESSOR_OPTION) -Q -G  -D__DEBUG=1 --debugger=pickit3  --double=24 --float=24 --emi=wordwrite --opt=default,+asm,-asmfile,+speed,-space,-debug --addrqual=ignore --mode=pro -P -N255 -I"../../../I2Cdev" -I"../../" --warn=0 --asmlist --summary=default,-psect,-class,+mem,-hex,-file --output=default,-inhx032 --runtime=default,+clear,+init,-keep,-no_startup,-download,+config,+clib,+plib --output=-mcof,+elf:multilocs --stack=compiled:auto:auto:auto "--errformat=%f:%l: error: (%n) %s" "--warnformat=%f:%l: warning: (%n) %s" "--msgformat=%f:%l: advisory: (%n) %s"    -o${OBJECTDIR}/main.p1  main.c 
-	@-${MV} ${OBJECTDIR}/main.d ${OBJECTDIR}/main.p1.d 
-	@${FIXDEPS} ${OBJECTDIR}/main.p1.d $(SILENT) -rsi ${MP_CC_DIR}../  
-	
-else
-${OBJECTDIR}/_ext/43898991/MPU6050.p1: ../../MPU6050.c  nbproject/Makefile-${CND_CONF}.mk
-	@${MKDIR} ${OBJECTDIR}/_ext/43898991 
-	@${RM} ${OBJECTDIR}/_ext/43898991/MPU6050.p1.d 
-	@${RM} ${OBJECTDIR}/_ext/43898991/MPU6050.p1 
-	${MP_CC} --pass1 $(MP_EXTRA_CC_PRE) --chip=$(MP_PROCESSOR_OPTION) -Q -G  --double=24 --float=24 --emi=wordwrite --opt=default,+asm,-asmfile,+speed,-space,-debug --addrqual=ignore --mode=pro -P -N255 -I"../../../I2Cdev" -I"../../" --warn=0 --asmlist --summary=default,-psect,-class,+mem,-hex,-file --output=default,-inhx032 --runtime=default,+clear,+init,-keep,-no_startup,-download,+config,+clib,+plib --output=-mcof,+elf:multilocs --stack=compiled:auto:auto:auto "--errformat=%f:%l: error: (%n) %s" "--warnformat=%f:%l: warning: (%n) %s" "--msgformat=%f:%l: advisory: (%n) %s"    -o${OBJECTDIR}/_ext/43898991/MPU6050.p1  ../../MPU6050.c 
-	@-${MV} ${OBJECTDIR}/_ext/43898991/MPU6050.d ${OBJECTDIR}/_ext/43898991/MPU6050.p1.d 
-	@${FIXDEPS} ${OBJECTDIR}/_ext/43898991/MPU6050.p1.d $(SILENT) -rsi ${MP_CC_DIR}../  
-	
-${OBJECTDIR}/_ext/105797386/I2Cdev.p1: ../../../I2Cdev/I2Cdev.c  nbproject/Makefile-${CND_CONF}.mk
-	@${MKDIR} ${OBJECTDIR}/_ext/105797386 
-	@${RM} ${OBJECTDIR}/_ext/105797386/I2Cdev.p1.d 
-	@${RM} ${OBJECTDIR}/_ext/105797386/I2Cdev.p1 
-	${MP_CC} --pass1 $(MP_EXTRA_CC_PRE) --chip=$(MP_PROCESSOR_OPTION) -Q -G  --double=24 --float=24 --emi=wordwrite --opt=default,+asm,-asmfile,+speed,-space,-debug --addrqual=ignore --mode=pro -P -N255 -I"../../../I2Cdev" -I"../../" --warn=0 --asmlist --summary=default,-psect,-class,+mem,-hex,-file --output=default,-inhx032 --runtime=default,+clear,+init,-keep,-no_startup,-download,+config,+clib,+plib --output=-mcof,+elf:multilocs --stack=compiled:auto:auto:auto "--errformat=%f:%l: error: (%n) %s" "--warnformat=%f:%l: warning: (%n) %s" "--msgformat=%f:%l: advisory: (%n) %s"    -o${OBJECTDIR}/_ext/105797386/I2Cdev.p1  ../../../I2Cdev/I2Cdev.c 
-	@-${MV} ${OBJECTDIR}/_ext/105797386/I2Cdev.d ${OBJECTDIR}/_ext/105797386/I2Cdev.p1.d 
-	@${FIXDEPS} ${OBJECTDIR}/_ext/105797386/I2Cdev.p1.d $(SILENT) -rsi ${MP_CC_DIR}../  
-	
-${OBJECTDIR}/main.p1: main.c  nbproject/Makefile-${CND_CONF}.mk
-	@${MKDIR} ${OBJECTDIR} 
-	@${RM} ${OBJECTDIR}/main.p1.d 
-	@${RM} ${OBJECTDIR}/main.p1 
-	${MP_CC} --pass1 $(MP_EXTRA_CC_PRE) --chip=$(MP_PROCESSOR_OPTION) -Q -G  --double=24 --float=24 --emi=wordwrite --opt=default,+asm,-asmfile,+speed,-space,-debug --addrqual=ignore --mode=pro -P -N255 -I"../../../I2Cdev" -I"../../" --warn=0 --asmlist --summary=default,-psect,-class,+mem,-hex,-file --output=default,-inhx032 --runtime=default,+clear,+init,-keep,-no_startup,-download,+config,+clib,+plib --output=-mcof,+elf:multilocs --stack=compiled:auto:auto:auto "--errformat=%f:%l: error: (%n) %s" "--warnformat=%f:%l: warning: (%n) %s" "--msgformat=%f:%l: advisory: (%n) %s"    -o${OBJECTDIR}/main.p1  main.c 
-	@-${MV} ${OBJECTDIR}/main.d ${OBJECTDIR}/main.p1.d 
-	@${FIXDEPS} ${OBJECTDIR}/main.p1.d $(SILENT) -rsi ${MP_CC_DIR}../  
-	
-endif
-
-# ------------------------------------------------------------------------------------
-# Rules for buildStep: assemble
-ifeq ($(TYPE_IMAGE), DEBUG_RUN)
-else
-endif
-
-# ------------------------------------------------------------------------------------
-# Rules for buildStep: link
-ifeq ($(TYPE_IMAGE), DEBUG_RUN)
-dist/${CND_CONF}/${IMAGE_TYPE}/MPU6050_raw.X.${IMAGE_TYPE}.${OUTPUT_SUFFIX}: ${OBJECTFILES}  nbproject/Makefile-${CND_CONF}.mk    
-	@${MKDIR} dist/${CND_CONF}/${IMAGE_TYPE} 
-	${MP_CC} $(MP_EXTRA_LD_PRE) --chip=$(MP_PROCESSOR_OPTION) -G -mdist/${CND_CONF}/${IMAGE_TYPE}/MPU6050_raw.X.${IMAGE_TYPE}.map  -D__DEBUG=1 --debugger=pickit3  --double=24 --float=24 --emi=wordwrite --opt=default,+asm,-asmfile,+speed,-space,-debug --addrqual=ignore --mode=pro -P -N255 -I"../../../I2Cdev" -I"../../" --warn=0 --asmlist --summary=default,-psect,-class,+mem,-hex,-file --output=default,-inhx032 --runtime=default,+clear,+init,-keep,-no_startup,-download,+config,+clib,+plib --output=-mcof,+elf:multilocs --stack=compiled:auto:auto:auto "--errformat=%f:%l: error: (%n) %s" "--warnformat=%f:%l: warning: (%n) %s" "--msgformat=%f:%l: advisory: (%n) %s"        -odist/${CND_CONF}/${IMAGE_TYPE}/MPU6050_raw.X.${IMAGE_TYPE}.${DEBUGGABLE_SUFFIX}  ${OBJECTFILES_QUOTED_IF_SPACED}     
-	@${RM} dist/${CND_CONF}/${IMAGE_TYPE}/MPU6050_raw.X.${IMAGE_TYPE}.hex 
-	
-else
-dist/${CND_CONF}/${IMAGE_TYPE}/MPU6050_raw.X.${IMAGE_TYPE}.${OUTPUT_SUFFIX}: ${OBJECTFILES}  nbproject/Makefile-${CND_CONF}.mk   
-	@${MKDIR} dist/${CND_CONF}/${IMAGE_TYPE} 
-	${MP_CC} $(MP_EXTRA_LD_PRE) --chip=$(MP_PROCESSOR_OPTION) -G -mdist/${CND_CONF}/${IMAGE_TYPE}/MPU6050_raw.X.${IMAGE_TYPE}.map  --double=24 --float=24 --emi=wordwrite --opt=default,+asm,-asmfile,+speed,-space,-debug --addrqual=ignore --mode=pro -P -N255 -I"../../../I2Cdev" -I"../../" --warn=0 --asmlist --summary=default,-psect,-class,+mem,-hex,-file --output=default,-inhx032 --runtime=default,+clear,+init,-keep,-no_startup,-download,+config,+clib,+plib --output=-mcof,+elf:multilocs --stack=compiled:auto:auto:auto "--errformat=%f:%l: error: (%n) %s" "--warnformat=%f:%l: warning: (%n) %s" "--msgformat=%f:%l: advisory: (%n) %s"     -odist/${CND_CONF}/${IMAGE_TYPE}/MPU6050_raw.X.${IMAGE_TYPE}.${DEBUGGABLE_SUFFIX}  ${OBJECTFILES_QUOTED_IF_SPACED}     
-	
-endif
-
-
-# Subprojects
-.build-subprojects:
-
-
-# Subprojects
-.clean-subprojects:
-
-# Clean Targets
-.clean-conf: ${CLEAN_SUBPROJECTS}
-	${RM} -r build/default
-	${RM} -r dist/default
-
-# Enable dependency checking
-.dep.inc: .depcheck-impl
-
-DEPFILES=$(shell mplabwildcard ${POSSIBLE_DEPFILES})
-ifneq (${DEPFILES},)
-include ${DEPFILES}
-endif
diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-genesis.properties b/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-genesis.properties
deleted file mode 100644
index 441f9906..00000000
--- a/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-genesis.properties
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-#Fri Nov 28 22:55:53 CET 2014
-default.languagetoolchain.dir=C\:\\Program Files (x86)\\Microchip\\xc8\\v1.32\\bin
-com-microchip-mplab-nbide-embedded-makeproject-MakeProject.md5=20b996ec0591c93034157100c3d90ac3
-default.languagetoolchain.version=1.32
-host.platform=windows
-conf.ids=default
-default.com-microchip-mplab-nbide-toolchainXC8-XC8LanguageToolchain.md5=533e5c34133c5d768bcb87ffcec948e1
diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-impl.mk b/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-impl.mk
deleted file mode 100644
index 8897f7f2..00000000
--- a/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-impl.mk
+++ /dev/null
@@ -1,69 +0,0 @@
-#
-# Generated Makefile - do not edit!
-#
-# Edit the Makefile in the project folder instead (../Makefile). Each target
-# has a pre- and a post- target defined where you can add customization code.
-#
-# This makefile implements macros and targets common to all configurations.
-#
-# NOCDDL
-
-
-# Building and Cleaning subprojects are done by default, but can be controlled with the SUB
-# macro. If SUB=no, subprojects will not be built or cleaned. The following macro
-# statements set BUILD_SUB-CONF and CLEAN_SUB-CONF to .build-reqprojects-conf
-# and .clean-reqprojects-conf unless SUB has the value 'no'
-SUB_no=NO
-SUBPROJECTS=${SUB_${SUB}}
-BUILD_SUBPROJECTS_=.build-subprojects
-BUILD_SUBPROJECTS_NO=
-BUILD_SUBPROJECTS=${BUILD_SUBPROJECTS_${SUBPROJECTS}}
-CLEAN_SUBPROJECTS_=.clean-subprojects
-CLEAN_SUBPROJECTS_NO=
-CLEAN_SUBPROJECTS=${CLEAN_SUBPROJECTS_${SUBPROJECTS}}
-
-
-# Project Name
-PROJECTNAME=MPU6050_raw.X
-
-# Active Configuration
-DEFAULTCONF=default
-CONF=${DEFAULTCONF}
-
-# All Configurations
-ALLCONFS=default 
-
-
-# build
-.build-impl: .build-pre
-	${MAKE} -f nbproject/Makefile-${CONF}.mk SUBPROJECTS=${SUBPROJECTS} .build-conf
-
-
-# clean
-.clean-impl: .clean-pre
-	${MAKE} -f nbproject/Makefile-${CONF}.mk SUBPROJECTS=${SUBPROJECTS} .clean-conf
-
-# clobber
-.clobber-impl: .clobber-pre .depcheck-impl
-	    ${MAKE} SUBPROJECTS=${SUBPROJECTS} CONF=default clean
-
-
-
-# all
-.all-impl: .all-pre .depcheck-impl
-	    ${MAKE} SUBPROJECTS=${SUBPROJECTS} CONF=default build
-
-
-
-# dependency checking support
-.depcheck-impl:
-#	@echo "# This code depends on make tool being used" >.dep.inc
-#	@if [ -n "${MAKE_VERSION}" ]; then \
-#	    echo "DEPFILES=\$$(wildcard \$$(addsuffix .d, \$${OBJECTFILES}))" >>.dep.inc; \
-#	    echo "ifneq (\$${DEPFILES},)" >>.dep.inc; \
-#	    echo "include \$${DEPFILES}" >>.dep.inc; \
-#	    echo "endif" >>.dep.inc; \
-#	else \
-#	    echo ".KEEP_STATE:" >>.dep.inc; \
-#	    echo ".KEEP_STATE_FILE:.make.state.\$${CONF}" >>.dep.inc; \
-#	fi
diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-local-default.mk b/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-local-default.mk
deleted file mode 100644
index dd484ed2..00000000
--- a/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-local-default.mk
+++ /dev/null
@@ -1,37 +0,0 @@
-#
-# Generated Makefile - do not edit!
-#
-#
-# This file contains information about the location of compilers and other tools.
-# If you commmit this file into your revision control server, you will be able to 
-# to checkout the project and build it from the command line with make. However,
-# if more than one person works on the same project, then this file might show
-# conflicts since different users are bound to have compilers in different places.
-# In that case you might choose to not commit this file and let MPLAB X recreate this file
-# for each user. The disadvantage of not commiting this file is that you must run MPLAB X at
-# least once so the file gets created and the project can be built. Finally, you can also
-# avoid using this file at all if you are only building from the command line with make.
-# You can invoke make with the values of the macros:
-# $ makeMP_CC="/opt/microchip/mplabc30/v3.30c/bin/pic30-gcc" ...  
-#
-SHELL=cmd.exe
-PATH_TO_IDE_BIN=C:/Program Files (x86)/Microchip/MPLABX/mplab_ide/mplab_ide/modules/../../bin/
-# Adding MPLAB X bin directory to path.
-PATH:=C:/Program Files (x86)/Microchip/MPLABX/mplab_ide/mplab_ide/modules/../../bin/:$(PATH)
-# Path to java used to run MPLAB X when this makefile was created
-MP_JAVA_PATH="C:\Program Files (x86)\Microchip\MPLABX\sys\java\jre1.7.0_25-windows-x64\java-windows/bin/"
-OS_CURRENT="$(shell uname -s)"
-MP_CC="C:\Program Files (x86)\Microchip\xc8\v1.32\bin\xc8.exe"
-# MP_CPPC is not defined
-# MP_BC is not defined
-MP_AS="C:\Program Files (x86)\Microchip\xc8\v1.32\bin\xc8.exe"
-# MP_LD is not defined
-# MP_AR is not defined
-DEP_GEN=${MP_JAVA_PATH}java -jar "C:/Program Files (x86)/Microchip/MPLABX/mplab_ide/mplab_ide/modules/../../bin/extractobjectdependencies.jar" 
-MP_CC_DIR="C:\Program Files (x86)\Microchip\xc8\v1.32\bin"
-# MP_CPPC_DIR is not defined
-# MP_BC_DIR is not defined
-MP_AS_DIR="C:\Program Files (x86)\Microchip\xc8\v1.32\bin"
-# MP_LD_DIR is not defined
-# MP_AR_DIR is not defined
-# MP_BC_DIR is not defined
diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-variables.mk b/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-variables.mk
deleted file mode 100644
index 623663b1..00000000
--- a/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/Makefile-variables.mk
+++ /dev/null
@@ -1,13 +0,0 @@
-#
-# Generated - do not edit!
-#
-# NOCDDL
-#
-CND_BASEDIR=`pwd`
-# default configuration
-CND_ARTIFACT_DIR_default=dist/default/production
-CND_ARTIFACT_NAME_default=MPU6050_raw.X.production.hex
-CND_ARTIFACT_PATH_default=dist/default/production/MPU6050_raw.X.production.hex
-CND_PACKAGE_DIR_default=${CND_DISTDIR}/default/package
-CND_PACKAGE_NAME_default=mpu6050raw.x.tar
-CND_PACKAGE_PATH_default=${CND_DISTDIR}/default/package/mpu6050raw.x.tar
diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/Package-default.bash b/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/Package-default.bash
deleted file mode 100644
index 2b42e19c..00000000
--- a/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/Package-default.bash
+++ /dev/null
@@ -1,73 +0,0 @@
-#!/bin/bash -x
-
-#
-# Generated - do not edit!
-#
-
-# Macros
-TOP=`pwd`
-CND_CONF=default
-CND_DISTDIR=dist
-TMPDIR=build/${CND_CONF}/${IMAGE_TYPE}/tmp-packaging
-TMPDIRNAME=tmp-packaging
-OUTPUT_PATH=dist/${CND_CONF}/${IMAGE_TYPE}/MPU6050_raw.X.${IMAGE_TYPE}.${OUTPUT_SUFFIX}
-OUTPUT_BASENAME=MPU6050_raw.X.${IMAGE_TYPE}.${OUTPUT_SUFFIX}
-PACKAGE_TOP_DIR=mpu6050raw.x/
-
-# Functions
-function checkReturnCode
-{
-    rc=$?
-    if [ $rc != 0 ]
-    then
-        exit $rc
-    fi
-}
-function makeDirectory
-# $1 directory path
-# $2 permission (optional)
-{
-    mkdir -p "$1"
-    checkReturnCode
-    if [ "$2" != "" ]
-    then
-      chmod $2 "$1"
-      checkReturnCode
-    fi
-}
-function copyFileToTmpDir
-# $1 from-file path
-# $2 to-file path
-# $3 permission
-{
-    cp "$1" "$2"
-    checkReturnCode
-    if [ "$3" != "" ]
-    then
-        chmod $3 "$2"
-        checkReturnCode
-    fi
-}
-
-# Setup
-cd "${TOP}"
-mkdir -p ${CND_DISTDIR}/${CND_CONF}/package
-rm -rf ${TMPDIR}
-mkdir -p ${TMPDIR}
-
-# Copy files and create directories and links
-cd "${TOP}"
-makeDirectory ${TMPDIR}/mpu6050raw.x/bin
-copyFileToTmpDir "${OUTPUT_PATH}" "${TMPDIR}/${PACKAGE_TOP_DIR}bin/${OUTPUT_BASENAME}" 0755
-
-
-# Generate tar file
-cd "${TOP}"
-rm -f ${CND_DISTDIR}/${CND_CONF}/package/mpu6050raw.x.tar
-cd ${TMPDIR}
-tar -vcf ../../../../${CND_DISTDIR}/${CND_CONF}/package/mpu6050raw.x.tar *
-checkReturnCode
-
-# Cleanup
-cd "${TOP}"
-rm -rf ${TMPDIR}
diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/configurations.xml b/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/configurations.xml
deleted file mode 100644
index 3b6fba66..00000000
--- a/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/configurations.xml
+++ /dev/null
@@ -1,173 +0,0 @@
-
-
-  
-    
-      ../../../I2Cdev/I2Cdev.h
-      ../../MPU6050.h
-    
-    
-    
-    
-      ../../MPU6050.c
-      ../../../I2Cdev/I2Cdev.c
-      main.c
-    
-    
-      Makefile
-    
-  
-  
-    C:\Users\sebokmarton\Documents\i2cdevlib\PIC18\I2Cdev
-    ../..
-  
-  Makefile
-  
-    
-      
-        localhost
-        PIC18F46J50
-        
-        
-        PICkit3PlatformTool
-        XC8
-        1.32
-        3
-      
-      
-        
-          
-          
-        
-        
-        
-        
-          false
-          false
-          
-        
-      
-      
-        false
-        
-        false
-        
-        false
-        false
-        false
-      
-      
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-      
-      
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-      
-      
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-        
-      
-      
-        
-        
-        
-        
-        
-        
-      
-    
-  
-
diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/project.properties b/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/project.properties
deleted file mode 100644
index e69de29b..00000000
diff --git a/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/project.xml b/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/project.xml
deleted file mode 100644
index 18806930..00000000
--- a/dsPIC30F/MPU6050/Examples/MPU6050_raw.X/nbproject/project.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-
-    com.microchip.mplab.nbide.embedded.makeproject
-    
-        
-            MPU6050_raw
-            84892e89-df8e-441e-9542-2524d6b2dc5a
-            0
-            c
-            
-            h
-            
-            UTF-8
-            
-        
-    
-

From 0c9d8f9a849de756d08f214909dbe2a144c6757a Mon Sep 17 00:00:00 2001
From: Alexandr Zarubkin 
Date: Mon, 29 May 2017 14:29:23 +0300
Subject: [PATCH 174/335] Added polling for end of conversion bit. Updated
 example. (according to BMP180 datasheet and
 https://hwswbits.blogspot.ru/2012/09/eoc-bit-in-bosch-bmp085-i2c-registers.html)

Signed-off-by: Alexandr Zarubkin 
---
 Arduino/BMP085/BMP085.cpp                             | 4 ++++
 Arduino/BMP085/examples/BMP085_basic/BMP085_basic.ino | 6 ------
 2 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/Arduino/BMP085/BMP085.cpp b/Arduino/BMP085/BMP085.cpp
index a17e45d8..f70bc81e 100644
--- a/Arduino/BMP085/BMP085.cpp
+++ b/Arduino/BMP085/BMP085.cpp
@@ -167,10 +167,14 @@ void BMP085::setControl(uint8_t value) {
 /* measurement register methods */
 
 uint16_t BMP085::getMeasurement2() {
+    // wait for end of conversion
+    while(getControl() & 0x20);
     I2Cdev::readBytes(devAddr, BMP085_RA_MSB, 2, buffer);
     return ((uint16_t)buffer[0] << 8) + buffer[1];
 }
 uint32_t BMP085::getMeasurement3() {
+    // wait for end of conversion
+    while(getControl() & 0x20);
     I2Cdev::readBytes(devAddr, BMP085_RA_MSB, 3, buffer);
     return ((uint32_t)buffer[0] << 16) + ((uint16_t)buffer[1] << 8) + buffer[2];
 }
diff --git a/Arduino/BMP085/examples/BMP085_basic/BMP085_basic.ino b/Arduino/BMP085/examples/BMP085_basic/BMP085_basic.ino
index 0e9633eb..59f64ebe 100644
--- a/Arduino/BMP085/examples/BMP085_basic/BMP085_basic.ino
+++ b/Arduino/BMP085/examples/BMP085_basic/BMP085_basic.ino
@@ -47,7 +47,6 @@ BMP085 barometer;
 float temperature;
 float pressure;
 float altitude;
-int32_t lastMicros;
 
 #define LED_PIN 13 // (Arduino is 13, Teensy is 11, Teensy++ is 6)
 bool blinkState = false;
@@ -77,16 +76,11 @@ void loop() {
     // request temperature
     barometer.setControl(BMP085_MODE_TEMPERATURE);
     
-    // wait appropriate time for conversion (4.5ms delay)
-    lastMicros = micros();
-    while (micros() - lastMicros < barometer.getMeasureDelayMicroseconds());
-
     // read calibrated temperature value in degrees Celsius
     temperature = barometer.getTemperatureC();
 
     // request pressure (3x oversampling mode, high detail, 23.5ms delay)
     barometer.setControl(BMP085_MODE_PRESSURE_3);
-    while (micros() - lastMicros < barometer.getMeasureDelayMicroseconds());
 
     // read calibrated pressure value in Pascals (Pa)
     pressure = barometer.getPressure();

From c199e9f7785a4e3e49d02d2d2742c24ddb49e573 Mon Sep 17 00:00:00 2001
From: Alexandr Zarubkin 
Date: Thu, 1 Jun 2017 17:39:28 +0300
Subject: [PATCH 175/335] Removed unnecessary float.

Signed-off-by: Alexandr Zarubkin 
---
 Arduino/BMP085/BMP085.cpp                             | 2 +-
 Arduino/BMP085/BMP085.h                               | 2 +-
 Arduino/BMP085/examples/BMP085_basic/BMP085_basic.ino | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/Arduino/BMP085/BMP085.cpp b/Arduino/BMP085/BMP085.cpp
index f70bc81e..255858fb 100644
--- a/Arduino/BMP085/BMP085.cpp
+++ b/Arduino/BMP085/BMP085.cpp
@@ -228,7 +228,7 @@ uint32_t BMP085::getRawPressure() {
     return 0; // wrong measurement mode for pressure request
 }
 
-float BMP085::getPressure() {
+int32_t BMP085::getPressure() {
     /*
     Datasheet forumla
         UP = raw pressure
diff --git a/Arduino/BMP085/BMP085.h b/Arduino/BMP085/BMP085.h
index 58f62247..b5d5a6a5 100644
--- a/Arduino/BMP085/BMP085.h
+++ b/Arduino/BMP085/BMP085.h
@@ -111,7 +111,7 @@ class BMP085 {
         float       getTemperatureC();
         float       getTemperatureF();
         uint32_t    getRawPressure();
-        float       getPressure();
+        int32_t     getPressure();
         float       getAltitude(float pressure, float seaLevelPressure=101325);
 
    private:
diff --git a/Arduino/BMP085/examples/BMP085_basic/BMP085_basic.ino b/Arduino/BMP085/examples/BMP085_basic/BMP085_basic.ino
index 59f64ebe..c5f8ce8c 100644
--- a/Arduino/BMP085/examples/BMP085_basic/BMP085_basic.ino
+++ b/Arduino/BMP085/examples/BMP085_basic/BMP085_basic.ino
@@ -46,7 +46,7 @@ BMP085 barometer;
 
 float temperature;
 float pressure;
-float altitude;
+int32_t altitude;
 
 #define LED_PIN 13 // (Arduino is 13, Teensy is 11, Teensy++ is 6)
 bool blinkState = false;

From 312e17357be7a0de48e0063d4b50cec9e48964f1 Mon Sep 17 00:00:00 2001
From: Ryan Feeley 
Date: Mon, 10 Jul 2017 17:25:18 -0600
Subject: [PATCH 176/335] Add pointer initialization in MPU6050.cpp

The uint8_t* verifyBuffer was uninitialized. I don't think this causes any problems, since
it is only checked if verify is true, and that condition does initialize verifyBuffer elsewhere
in the code. However, it's probably safer to initialize it to 0 or nullptr in case some future
edit does something different.
---
 Arduino/MPU6050/MPU6050.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Arduino/MPU6050/MPU6050.cpp b/Arduino/MPU6050/MPU6050.cpp
index d6ad2057..72d8d866 100644
--- a/Arduino/MPU6050/MPU6050.cpp
+++ b/Arduino/MPU6050/MPU6050.cpp
@@ -3037,7 +3037,7 @@ bool MPU6050::writeMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t b
     setMemoryBank(bank);
     setMemoryStartAddress(address);
     uint8_t chunkSize;
-    uint8_t *verifyBuffer;
+    uint8_t *verifyBuffer=0;
     uint8_t *progBuffer=0;
     uint16_t i;
     uint8_t j;

From 712efe183b9eb79fbf8205565694a335bcea23e0 Mon Sep 17 00:00:00 2001
From: Dariusz Krempa 
Date: Mon, 28 Aug 2017 22:07:56 +0200
Subject: [PATCH 177/335] Added ESP32 esp-idf platform

---
 ESP32_ESP-IDF/Makefile                        |    9 +
 ESP32_ESP-IDF/README.md                       |    6 +
 ESP32_ESP-IDF/components/I2Cdev/I2Cdev.cpp    |  255 ++
 ESP32_ESP-IDF/components/I2Cdev/I2Cdev.h      |   83 +
 ESP32_ESP-IDF/components/I2Cdev/component.mk  |   10 +
 ESP32_ESP-IDF/components/MPU6050/MPU6050.cpp  | 3234 +++++++++++++++++
 ESP32_ESP-IDF/components/MPU6050/MPU6050.h    | 1034 ++++++
 .../MPU6050/MPU6050_6Axis_MotionApps20.h      |  752 ++++
 .../MPU6050/MPU6050_9Axis_MotionApps41.h      |  852 +++++
 ESP32_ESP-IDF/components/MPU6050/component.mk |   10 +
 .../components/MPU6050/helper_3dmath.h        |  218 ++
 ESP32_ESP-IDF/main/component.mk               |    8 +
 ESP32_ESP-IDF/main/example.cpp                |   85 +
 ESP32_ESP-IDF/main/main.cpp                   |   17 +
 ESP32_ESP-IDF/sdkconfig                       |  424 +++
 ESP32_ESP-IDF/sdkconfig.old                   |  433 +++
 16 files changed, 7430 insertions(+)
 create mode 100644 ESP32_ESP-IDF/Makefile
 create mode 100644 ESP32_ESP-IDF/README.md
 create mode 100644 ESP32_ESP-IDF/components/I2Cdev/I2Cdev.cpp
 create mode 100644 ESP32_ESP-IDF/components/I2Cdev/I2Cdev.h
 create mode 100644 ESP32_ESP-IDF/components/I2Cdev/component.mk
 create mode 100644 ESP32_ESP-IDF/components/MPU6050/MPU6050.cpp
 create mode 100644 ESP32_ESP-IDF/components/MPU6050/MPU6050.h
 create mode 100644 ESP32_ESP-IDF/components/MPU6050/MPU6050_6Axis_MotionApps20.h
 create mode 100644 ESP32_ESP-IDF/components/MPU6050/MPU6050_9Axis_MotionApps41.h
 create mode 100644 ESP32_ESP-IDF/components/MPU6050/component.mk
 create mode 100644 ESP32_ESP-IDF/components/MPU6050/helper_3dmath.h
 create mode 100644 ESP32_ESP-IDF/main/component.mk
 create mode 100644 ESP32_ESP-IDF/main/example.cpp
 create mode 100644 ESP32_ESP-IDF/main/main.cpp
 create mode 100644 ESP32_ESP-IDF/sdkconfig
 create mode 100644 ESP32_ESP-IDF/sdkconfig.old

diff --git a/ESP32_ESP-IDF/Makefile b/ESP32_ESP-IDF/Makefile
new file mode 100644
index 00000000..9f2c3278
--- /dev/null
+++ b/ESP32_ESP-IDF/Makefile
@@ -0,0 +1,9 @@
+#
+# This is a project Makefile. It is assumed the directory this Makefile resides in is a
+# project subdirectory.
+#
+
+PROJECT_NAME := app-template
+
+include $(IDF_PATH)/make/project.mk
+
diff --git a/ESP32_ESP-IDF/README.md b/ESP32_ESP-IDF/README.md
new file mode 100644
index 00000000..ebb18425
--- /dev/null
+++ b/ESP32_ESP-IDF/README.md
@@ -0,0 +1,6 @@
+I2CDev library rewritted to match esp-idf. DMP should work, only need is to setup 
+    mpu.setXGyroOffset(220);
+    mpu.setYGyroOffset(76);
+    mpu.setZGyroOffset(-85);
+    mpu.setZAccelOffset(1788);
+and eventually change last value in components/MPU6050/MPU6050_6Axis_MotionApps20.h.
diff --git a/ESP32_ESP-IDF/components/I2Cdev/I2Cdev.cpp b/ESP32_ESP-IDF/components/I2Cdev/I2Cdev.cpp
new file mode 100644
index 00000000..6d03d1e1
--- /dev/null
+++ b/ESP32_ESP-IDF/components/I2Cdev/I2Cdev.cpp
@@ -0,0 +1,255 @@
+// I2Cdev library collection - Main I2C device class
+// Abstracts bit and byte I2C R/W functions into a convenient class
+// EFM32 stub port by Nicolas Baldeck 
+// Based on Arduino's I2Cdev by Jeff Rowberg 
+//
+// Changelog:
+//      2015-01-02 - Initial release
+
+
+/* ============================================
+I2Cdev device library code is placed under the MIT license
+Copyright (c) 2015 Jeff Rowberg, Nicolas Baldeck
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+===============================================
+*/
+
+#include 
+#include 
+#include 
+#include 
+#include "sdkconfig.h"
+
+#include "I2Cdev.h"
+
+#define I2C_NUM I2C_NUM_0
+
+#undef ESP_ERROR_CHECK
+#define ESP_ERROR_CHECK(x)   do { esp_err_t rc = (x); if (rc != ESP_OK) { ESP_LOGE("err", "esp_err_t = %d", rc); /*assert(0 && #x);*/} } while(0);
+
+/** Default constructor.
+ */
+I2Cdev::I2Cdev() {
+}
+
+/** Initialize I2C0
+ */
+void I2Cdev::initialize() {
+
+}
+
+/** Enable or disable I2C
+ * @param isEnabled true = enable, false = disable
+ */
+void I2Cdev::enable(bool isEnabled) {
+  
+}
+
+/** Default timeout value for read operations.
+ */
+uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT;
+/** Read a single bit from an 8-bit device register.
+ * @param devAddr I2C slave device address
+ * @param regAddr Register regAddr to read from
+ * @param bitNum Bit position to read (0-7)
+ * @param data Container for single bit value
+ * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout)
+ * @return Status of read operation (true = success)
+ */
+int8_t I2Cdev::readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data, uint16_t timeout) {
+
+
+	uint8_t b;
+    uint8_t count = readByte(devAddr, regAddr, &b, timeout);
+    *data = b & (1 << bitNum);
+    return count;
+}
+
+/** Read multiple bits from an 8-bit device register.
+ * @param devAddr I2C slave device address
+ * @param regAddr Register regAddr to read from
+ * @param bitStart First bit position to read (0-7)
+ * @param length Number of bits to read (not more than 8)
+ * @param data Container for right-aligned value (i.e. '101' read from any bitStart position will equal 0x05)
+ * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout)
+ * @return Status of read operation (true = success)
+ */
+int8_t I2Cdev::readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data, uint16_t timeout) {
+    // 01101001 read byte
+    // 76543210 bit numbers
+    //    xxx   args: bitStart=4, length=3
+    //    010   masked
+    //   -> 010 shifted
+    uint8_t count, b;
+    if ((count = readByte(devAddr, regAddr, &b, timeout)) != 0) {
+        uint8_t mask = ((1 << length) - 1) << (bitStart - length + 1);
+        b &= mask;
+        b >>= (bitStart - length + 1);
+        *data = b;
+    }
+    return count;
+}
+
+/** Read single byte from an 8-bit device register.
+ * @param devAddr I2C slave device address
+ * @param regAddr Register regAddr to read from
+ * @param data Container for byte value read from device
+ * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout)
+ * @return Status of read operation (true = success)
+ */
+int8_t I2Cdev::readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint16_t timeout) {
+    return readBytes(devAddr, regAddr, 1, data, timeout);
+}
+
+/** Read multiple bytes from an 8-bit device register.
+ * @param devAddr I2C slave device address
+ * @param regAddr First register regAddr to read from
+ * @param length Number of bytes to read
+ * @param data Buffer to store read data in
+ * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout)
+ * @return I2C_TransferReturn_TypeDef http://downloads.energymicro.com/documentation/doxygen/group__I2C.html
+ */
+int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data, uint16_t timeout) {
+	i2c_cmd_handle_t cmd;
+	SelectRegister(devAddr, regAddr);
+
+	cmd = i2c_cmd_link_create();
+	ESP_ERROR_CHECK(i2c_master_start(cmd));
+	ESP_ERROR_CHECK(i2c_master_write_byte(cmd, (devAddr << 1) | I2C_MASTER_READ, 1));
+
+	if(length>1)
+		ESP_ERROR_CHECK(i2c_master_read(cmd, data, length-1, 0));
+
+	ESP_ERROR_CHECK(i2c_master_read_byte(cmd, data+length-1, 1));
+
+	ESP_ERROR_CHECK(i2c_master_stop(cmd));
+	ESP_ERROR_CHECK(i2c_master_cmd_begin(I2C_NUM, cmd, 1000/portTICK_PERIOD_MS));
+	i2c_cmd_link_delete(cmd);
+
+	return length;
+}
+
+bool I2Cdev::writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data){
+
+	uint8_t data1[] = {(uint8_t)(data>>8), (uint8_t)(data & 0xff)};
+	uint8_t data2[] = {(uint8_t)(data & 0xff), (uint8_t)(data>>8)};
+	writeBytes(devAddr, regAddr, 2, data1);
+	return true;
+}
+
+void I2Cdev::SelectRegister(uint8_t dev, uint8_t reg){
+	i2c_cmd_handle_t cmd;
+
+	cmd = i2c_cmd_link_create();
+	ESP_ERROR_CHECK(i2c_master_start(cmd));
+	ESP_ERROR_CHECK(i2c_master_write_byte(cmd, (dev << 1) | I2C_MASTER_WRITE, 1));
+	ESP_ERROR_CHECK(i2c_master_write_byte(cmd, reg, 1));
+	ESP_ERROR_CHECK(i2c_master_stop(cmd));
+	ESP_ERROR_CHECK(i2c_master_cmd_begin(I2C_NUM, cmd, 1000/portTICK_PERIOD_MS));
+	i2c_cmd_link_delete(cmd);
+}
+
+/** write a single bit in an 8-bit device register.
+ * @param devAddr I2C slave device address
+ * @param regAddr Register regAddr to write to
+ * @param bitNum Bit position to write (0-7)
+ * @param value New bit value to write
+ * @return Status of operation (true = success)
+ */
+bool I2Cdev::writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t data) {
+    uint8_t b;
+    readByte(devAddr, regAddr, &b);
+    b = (data != 0) ? (b | (1 << bitNum)) : (b & ~(1 << bitNum));
+    return writeByte(devAddr, regAddr, b);
+}
+
+/** Write multiple bits in an 8-bit device register.
+ * @param devAddr I2C slave device address
+ * @param regAddr Register regAddr to write to
+ * @param bitStart First bit position to write (0-7)
+ * @param length Number of bits to write (not more than 8)
+ * @param data Right-aligned value to write
+ * @return Status of operation (true = success)
+ */
+bool I2Cdev::writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data) {
+    //      010 value to write
+    // 76543210 bit numbers
+    //    xxx   args: bitStart=4, length=3
+    // 00011100 mask byte
+    // 10101111 original value (sample)
+    // 10100011 original & ~mask
+    // 10101011 masked | value
+    uint8_t b = 0;
+    if (readByte(devAddr, regAddr, &b) != 0) {
+        uint8_t mask = ((1 << length) - 1) << (bitStart - length + 1);
+        data <<= (bitStart - length + 1); // shift data into correct position
+        data &= mask; // zero all non-important bits in data
+        b &= ~(mask); // zero all important bits in existing byte
+        b |= data; // combine data with existing byte
+        return writeByte(devAddr, regAddr, b);
+    } else {
+        return false;
+    }
+}
+
+/** Write single byte to an 8-bit device register.
+ * @param devAddr I2C slave device address
+ * @param regAddr Register address to write to
+ * @param data New byte value to write
+ * @return Status of operation (true = success)
+ */
+bool I2Cdev::writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data) {
+	i2c_cmd_handle_t cmd;
+
+	cmd = i2c_cmd_link_create();
+	ESP_ERROR_CHECK(i2c_master_start(cmd));
+	ESP_ERROR_CHECK(i2c_master_write_byte(cmd, (devAddr << 1) | I2C_MASTER_WRITE, 1));
+	ESP_ERROR_CHECK(i2c_master_write_byte(cmd, regAddr, 1));
+	ESP_ERROR_CHECK(i2c_master_write_byte(cmd, data, 1));
+	ESP_ERROR_CHECK(i2c_master_stop(cmd));
+	ESP_ERROR_CHECK(i2c_master_cmd_begin(I2C_NUM, cmd, 1000/portTICK_PERIOD_MS));
+	i2c_cmd_link_delete(cmd);
+
+	return true;
+}
+
+/** Write single byte to an 8-bit device register.
+ * @param devAddr I2C slave device address
+ * @param regAddr Register address to write to
+ * @param length Number of bytes to write
+ * @param data Array of bytes to write
+ * @return Status of operation (true = success)
+ */
+bool I2Cdev::writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data){
+	i2c_cmd_handle_t cmd;
+
+	cmd = i2c_cmd_link_create();
+	ESP_ERROR_CHECK(i2c_master_start(cmd));
+	ESP_ERROR_CHECK(i2c_master_write_byte(cmd, (devAddr << 1) | I2C_MASTER_WRITE, 1));
+	ESP_ERROR_CHECK(i2c_master_write_byte(cmd, regAddr, 1));
+	ESP_ERROR_CHECK(i2c_master_write(cmd, data, length-1, 0));
+	ESP_ERROR_CHECK(i2c_master_write_byte(cmd, data[length-1], 1));
+	ESP_ERROR_CHECK(i2c_master_stop(cmd));
+	ESP_ERROR_CHECK(i2c_master_cmd_begin(I2C_NUM, cmd, 1000/portTICK_PERIOD_MS));
+	i2c_cmd_link_delete(cmd);
+	return true;
+}
+
+
diff --git a/ESP32_ESP-IDF/components/I2Cdev/I2Cdev.h b/ESP32_ESP-IDF/components/I2Cdev/I2Cdev.h
new file mode 100644
index 00000000..c88b5fee
--- /dev/null
+++ b/ESP32_ESP-IDF/components/I2Cdev/I2Cdev.h
@@ -0,0 +1,83 @@
+// I2Cdev library collection - Main I2C device class
+// Abstracts bit and byte I2C R/W functions into a convenient class
+// EFM32 stub port by Nicolas Baldeck 
+// Based on Arduino's I2Cdev by Jeff Rowberg 
+//
+// Changelog:
+//      2015-01-02 - Initial release
+
+
+/* ============================================
+I2Cdev device library code is placed under the MIT license
+Copyright (c) 2015 Jeff Rowberg, Nicolas Baldeck
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+===============================================
+*/
+
+#ifndef _I2CDEV_H_
+#define _I2CDEV_H_
+
+#include 
+
+#define I2C_SDA_PORT gpioPortA
+#define I2C_SDA_PIN 0
+#define I2C_SDA_MODE gpioModeWiredAnd
+#define I2C_SDA_DOUT 1
+
+#define I2C_SCL_PORT gpioPortA
+#define I2C_SCL_PIN 1
+#define I2C_SCL_MODE gpioModeWiredAnd
+#define I2C_SCL_DOUT 1
+
+#define I2CDEV_DEFAULT_READ_TIMEOUT 1000
+
+class I2Cdev {
+    public:
+        I2Cdev();
+
+        static void initialize();
+        static void enable(bool isEnabled);
+
+        static int8_t readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout);
+        //TODO static int8_t readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout);
+        static int8_t readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout);
+        //TODO static int8_t readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout);
+        static int8_t readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout);
+        //TODO static int8_t readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout);
+        static int8_t readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout);
+        //TODO static int8_t readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout);
+
+        static bool writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t data);
+        //TODO static bool writeBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t data);
+        static bool writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data);
+        //TODO static bool writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t data);
+        static bool writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data);
+        static bool writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data);
+        static bool writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data);
+        //TODO static bool writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data);
+
+        static uint16_t readTimeout;
+
+    //private:
+        static void SelectRegister(uint8_t dev, uint8_t reg);
+        //static I2C_TransferReturn_TypeDef transfer(I2C_TransferSeq_TypeDef *seq, uint16_t timeout=I2Cdev::readTimeout);
+};
+
+#endif /* _I2CDEV_H_ */
diff --git a/ESP32_ESP-IDF/components/I2Cdev/component.mk b/ESP32_ESP-IDF/components/I2Cdev/component.mk
new file mode 100644
index 00000000..3d61395f
--- /dev/null
+++ b/ESP32_ESP-IDF/components/I2Cdev/component.mk
@@ -0,0 +1,10 @@
+#
+# Main component makefile.
+#
+# This Makefile can be left empty. By default, it will take the sources in the 
+# src/ directory, compile them and link them into lib(subdirectory_name).a 
+# in the build directory. This behaviour is entirely configurable,
+# please read the ESP-IDF documents if you need to do this.
+#
+
+COMPONENT_ADD_INCLUDEDIRS=.
\ No newline at end of file
diff --git a/ESP32_ESP-IDF/components/MPU6050/MPU6050.cpp b/ESP32_ESP-IDF/components/MPU6050/MPU6050.cpp
new file mode 100644
index 00000000..3aa0ecc4
--- /dev/null
+++ b/ESP32_ESP-IDF/components/MPU6050/MPU6050.cpp
@@ -0,0 +1,3234 @@
+// I2Cdev library collection - MPU6050 I2C device class
+// Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00)
+// 8/24/2011 by Jeff Rowberg 
+// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
+//
+// Changelog:
+//     ... - ongoing debug release
+
+// NOTE: THIS IS ONLY A PARIAL RELEASE. THIS DEVICE CLASS IS CURRENTLY UNDERGOING ACTIVE
+// DEVELOPMENT AND IS STILL MISSING SOME IMPORTANT FEATURES. PLEASE KEEP THIS IN MIND IF
+// YOU DECIDE TO USE THIS PARTICULAR CODE FOR ANYTHING.
+
+/* ============================================
+I2Cdev device library code is placed under the MIT license
+Copyright (c) 2012 Jeff Rowberg
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+===============================================
+*/
+
+#include "MPU6050.h"
+#include 
+
+#define I2C_NUM I2C_NUM_0
+
+void MPU6050::ReadRegister(uint8_t reg, uint8_t *data, uint8_t len){
+	uint8_t dev = 0x68;
+	i2c_cmd_handle_t cmd;
+	I2Cdev::SelectRegister(dev, reg);
+
+	cmd = i2c_cmd_link_create();
+	ESP_ERROR_CHECK(i2c_master_start(cmd));
+	ESP_ERROR_CHECK(i2c_master_write_byte(cmd, (dev << 1) | I2C_MASTER_READ, 1));
+
+	if(len>1)
+		ESP_ERROR_CHECK(i2c_master_read(cmd, data, len, 0));
+
+	ESP_ERROR_CHECK(i2c_master_read_byte(cmd, data+len-1, 1));
+
+	ESP_ERROR_CHECK(i2c_master_stop(cmd));
+	ESP_ERROR_CHECK(i2c_master_cmd_begin(I2C_NUM, cmd, 1000));
+	i2c_cmd_link_delete(cmd);
+}
+
+
+/** Default constructor, uses default I2C address.
+ * @see MPU6050_DEFAULT_ADDRESS
+ */
+MPU6050::MPU6050() {
+    devAddr = MPU6050_DEFAULT_ADDRESS;
+}
+
+/** Specific address constructor.
+ * @param address I2C address
+ * @see MPU6050_DEFAULT_ADDRESS
+ * @see MPU6050_ADDRESS_AD0_LOW
+ * @see MPU6050_ADDRESS_AD0_HIGH
+ */
+MPU6050::MPU6050(uint8_t address) {
+    devAddr = address;
+}
+
+/** Power on and prepare for general usage.
+ * This will activate the device and take it out of sleep mode (which must be done
+ * after start-up). This function also sets both the accelerometer and the gyroscope
+ * to their most sensitive settings, namely +/- 2g and +/- 250 degrees/sec, and sets
+ * the clock source to use the X Gyro for reference, which is slightly better than
+ * the default internal clock source.
+ */
+void MPU6050::initialize() {
+    setClockSource(MPU6050_CLOCK_PLL_XGYRO);
+    setFullScaleGyroRange(MPU6050_GYRO_FS_250);
+    setFullScaleAccelRange(MPU6050_ACCEL_FS_2);
+    setSleepEnabled(false); // thanks to Jack Elston for pointing this one out!
+}
+
+/** Verify the I2C connection.
+ * Make sure the device is connected and responds as expected.
+ * @return True if connection is valid, false otherwise
+ */
+bool MPU6050::testConnection() {
+    return getDeviceID() == 0x34;
+}
+
+// AUX_VDDIO register (InvenSense demo code calls this RA_*G_OFFS_TC)
+
+/** Get the auxiliary I2C supply voltage level.
+ * When set to 1, the auxiliary I2C bus high logic level is VDD. When cleared to
+ * 0, the auxiliary I2C bus high logic level is VLOGIC. This does not apply to
+ * the MPU-6000, which does not have a VLOGIC pin.
+ * @return I2C supply voltage level (0=VLOGIC, 1=VDD)
+ */
+uint8_t MPU6050::getAuxVDDIOLevel() {
+    I2Cdev::readBit(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_PWR_MODE_BIT, buffer);
+    return buffer[0];
+}
+/** Set the auxiliary I2C supply voltage level.
+ * When set to 1, the auxiliary I2C bus high logic level is VDD. When cleared to
+ * 0, the auxiliary I2C bus high logic level is VLOGIC. This does not apply to
+ * the MPU-6000, which does not have a VLOGIC pin.
+ * @param level I2C supply voltage level (0=VLOGIC, 1=VDD)
+ */
+void MPU6050::setAuxVDDIOLevel(uint8_t level) {
+    I2Cdev::writeBit(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_PWR_MODE_BIT, level);
+}
+
+// SMPLRT_DIV register
+
+/** Get gyroscope output rate divider.
+ * The sensor register output, FIFO output, DMP sampling, Motion detection, Zero
+ * Motion detection, and Free Fall detection are all based on the Sample Rate.
+ * The Sample Rate is generated by dividing the gyroscope output rate by
+ * SMPLRT_DIV:
+ *
+ * Sample Rate = Gyroscope Output Rate / (1 + SMPLRT_DIV)
+ *
+ * where Gyroscope Output Rate = 8kHz when the DLPF is disabled (DLPF_CFG = 0 or
+ * 7), and 1kHz when the DLPF is enabled (see Register 26).
+ *
+ * Note: The accelerometer output rate is 1kHz. This means that for a Sample
+ * Rate greater than 1kHz, the same accelerometer sample may be output to the
+ * FIFO, DMP, and sensor registers more than once.
+ *
+ * For a diagram of the gyroscope and accelerometer signal paths, see Section 8
+ * of the MPU-6000/MPU-6050 Product Specification document.
+ *
+ * @return Current sample rate
+ * @see MPU6050_RA_SMPLRT_DIV
+ */
+uint8_t MPU6050::getRate() {
+    I2Cdev::readByte(devAddr, MPU6050_RA_SMPLRT_DIV, buffer);
+    return buffer[0];
+}
+/** Set gyroscope sample rate divider.
+ * @param rate New sample rate divider
+ * @see getRate()
+ * @see MPU6050_RA_SMPLRT_DIV
+ */
+void MPU6050::setRate(uint8_t rate) {
+    I2Cdev::writeByte(devAddr, MPU6050_RA_SMPLRT_DIV, rate);
+}
+
+// CONFIG register
+
+/** Get external FSYNC configuration.
+ * Configures the external Frame Synchronization (FSYNC) pin sampling. An
+ * external signal connected to the FSYNC pin can be sampled by configuring
+ * EXT_SYNC_SET. Signal changes to the FSYNC pin are latched so that short
+ * strobes may be captured. The latched FSYNC signal will be sampled at the
+ * Sampling Rate, as defined in register 25. After sampling, the latch will
+ * reset to the current FSYNC signal state.
+ *
+ * The sampled value will be reported in place of the least significant bit in
+ * a sensor data register determined by the value of EXT_SYNC_SET according to
+ * the following table.
+ *
+ * 
+ * EXT_SYNC_SET | FSYNC Bit Location
+ * -------------+-------------------
+ * 0            | Input disabled
+ * 1            | TEMP_OUT_L[0]
+ * 2            | GYRO_XOUT_L[0]
+ * 3            | GYRO_YOUT_L[0]
+ * 4            | GYRO_ZOUT_L[0]
+ * 5            | ACCEL_XOUT_L[0]
+ * 6            | ACCEL_YOUT_L[0]
+ * 7            | ACCEL_ZOUT_L[0]
+ * 
+ * + * @return FSYNC configuration value + */ +uint8_t MPU6050::getExternalFrameSync() { + I2Cdev::readBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_EXT_SYNC_SET_BIT, MPU6050_CFG_EXT_SYNC_SET_LENGTH, buffer); + return buffer[0]; +} +/** Set external FSYNC configuration. + * @see getExternalFrameSync() + * @see MPU6050_RA_CONFIG + * @param sync New FSYNC configuration value + */ +void MPU6050::setExternalFrameSync(uint8_t sync) { + I2Cdev::writeBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_EXT_SYNC_SET_BIT, MPU6050_CFG_EXT_SYNC_SET_LENGTH, sync); +} +/** Get digital low-pass filter configuration. + * The DLPF_CFG parameter sets the digital low pass filter configuration. It + * also determines the internal sampling rate used by the device as shown in + * the table below. + * + * Note: The accelerometer output rate is 1kHz. This means that for a Sample + * Rate greater than 1kHz, the same accelerometer sample may be output to the + * FIFO, DMP, and sensor registers more than once. + * + *
+ *          |   ACCELEROMETER    |           GYROSCOPE
+ * DLPF_CFG | Bandwidth | Delay  | Bandwidth | Delay  | Sample Rate
+ * ---------+-----------+--------+-----------+--------+-------------
+ * 0        | 260Hz     | 0ms    | 256Hz     | 0.98ms | 8kHz
+ * 1        | 184Hz     | 2.0ms  | 188Hz     | 1.9ms  | 1kHz
+ * 2        | 94Hz      | 3.0ms  | 98Hz      | 2.8ms  | 1kHz
+ * 3        | 44Hz      | 4.9ms  | 42Hz      | 4.8ms  | 1kHz
+ * 4        | 21Hz      | 8.5ms  | 20Hz      | 8.3ms  | 1kHz
+ * 5        | 10Hz      | 13.8ms | 10Hz      | 13.4ms | 1kHz
+ * 6        | 5Hz       | 19.0ms | 5Hz       | 18.6ms | 1kHz
+ * 7        |   -- Reserved --   |   -- Reserved --   | Reserved
+ * 
+ * + * @return DLFP configuration + * @see MPU6050_RA_CONFIG + * @see MPU6050_CFG_DLPF_CFG_BIT + * @see MPU6050_CFG_DLPF_CFG_LENGTH + */ +uint8_t MPU6050::getDLPFMode() { + I2Cdev::readBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_DLPF_CFG_BIT, MPU6050_CFG_DLPF_CFG_LENGTH, buffer); + return buffer[0]; +} +/** Set digital low-pass filter configuration. + * @param mode New DLFP configuration setting + * @see getDLPFBandwidth() + * @see MPU6050_DLPF_BW_256 + * @see MPU6050_RA_CONFIG + * @see MPU6050_CFG_DLPF_CFG_BIT + * @see MPU6050_CFG_DLPF_CFG_LENGTH + */ +void MPU6050::setDLPFMode(uint8_t mode) { + I2Cdev::writeBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_DLPF_CFG_BIT, MPU6050_CFG_DLPF_CFG_LENGTH, mode); +} + +// GYRO_CONFIG register + +/** Get full-scale gyroscope range. + * The FS_SEL parameter allows setting the full-scale range of the gyro sensors, + * as described in the table below. + * + *
+ * 0 = +/- 250 degrees/sec
+ * 1 = +/- 500 degrees/sec
+ * 2 = +/- 1000 degrees/sec
+ * 3 = +/- 2000 degrees/sec
+ * 
+ * + * @return Current full-scale gyroscope range setting + * @see MPU6050_GYRO_FS_250 + * @see MPU6050_RA_GYRO_CONFIG + * @see MPU6050_GCONFIG_FS_SEL_BIT + * @see MPU6050_GCONFIG_FS_SEL_LENGTH + */ +uint8_t MPU6050::getFullScaleGyroRange() { + I2Cdev::readBits(devAddr, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, buffer); + return buffer[0]; +} +/** Set full-scale gyroscope range. + * @param range New full-scale gyroscope range value + * @see getFullScaleRange() + * @see MPU6050_GYRO_FS_250 + * @see MPU6050_RA_GYRO_CONFIG + * @see MPU6050_GCONFIG_FS_SEL_BIT + * @see MPU6050_GCONFIG_FS_SEL_LENGTH + */ +void MPU6050::setFullScaleGyroRange(uint8_t range) { + I2Cdev::writeBits(devAddr, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, range); +} + +// SELF TEST FACTORY TRIM VALUES + +/** Get self-test factory trim value for accelerometer X axis. + * @return factory trim value + * @see MPU6050_RA_SELF_TEST_X + */ +uint8_t MPU6050::getAccelXSelfTestFactoryTrim() { + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_X, &buffer[0]); + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_A, &buffer[1]); + return (buffer[0]>>3) | ((buffer[1]>>4) & 0x03); +} + +/** Get self-test factory trim value for accelerometer Y axis. + * @return factory trim value + * @see MPU6050_RA_SELF_TEST_Y + */ +uint8_t MPU6050::getAccelYSelfTestFactoryTrim() { + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_Y, &buffer[0]); + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_A, &buffer[1]); + return (buffer[0]>>3) | ((buffer[1]>>2) & 0x03); +} + +/** Get self-test factory trim value for accelerometer Z axis. + * @return factory trim value + * @see MPU6050_RA_SELF_TEST_Z + */ +uint8_t MPU6050::getAccelZSelfTestFactoryTrim() { + I2Cdev::readBytes(devAddr, MPU6050_RA_SELF_TEST_Z, 2, buffer); + return (buffer[0]>>3) | (buffer[1] & 0x03); +} + +/** Get self-test factory trim value for gyro X axis. + * @return factory trim value + * @see MPU6050_RA_SELF_TEST_X + */ +uint8_t MPU6050::getGyroXSelfTestFactoryTrim() { + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_X, buffer); + return (buffer[0] & 0x1F); +} + +/** Get self-test factory trim value for gyro Y axis. + * @return factory trim value + * @see MPU6050_RA_SELF_TEST_Y + */ +uint8_t MPU6050::getGyroYSelfTestFactoryTrim() { + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_Y, buffer); + return (buffer[0] & 0x1F); +} + +/** Get self-test factory trim value for gyro Z axis. + * @return factory trim value + * @see MPU6050_RA_SELF_TEST_Z + */ +uint8_t MPU6050::getGyroZSelfTestFactoryTrim() { + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_Z, buffer); + return (buffer[0] & 0x1F); +} + +// ACCEL_CONFIG register + +/** Get self-test enabled setting for accelerometer X axis. + * @return Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +bool MPU6050::getAccelXSelfTest() { + I2Cdev::readBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_XA_ST_BIT, buffer); + return buffer[0]; +} +/** Get self-test enabled setting for accelerometer X axis. + * @param enabled Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050::setAccelXSelfTest(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_XA_ST_BIT, enabled); +} +/** Get self-test enabled value for accelerometer Y axis. + * @return Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +bool MPU6050::getAccelYSelfTest() { + I2Cdev::readBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_YA_ST_BIT, buffer); + return buffer[0]; +} +/** Get self-test enabled value for accelerometer Y axis. + * @param enabled Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050::setAccelYSelfTest(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_YA_ST_BIT, enabled); +} +/** Get self-test enabled value for accelerometer Z axis. + * @return Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +bool MPU6050::getAccelZSelfTest() { + I2Cdev::readBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ZA_ST_BIT, buffer); + return buffer[0]; +} +/** Set self-test enabled value for accelerometer Z axis. + * @param enabled Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050::setAccelZSelfTest(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ZA_ST_BIT, enabled); +} +/** Get full-scale accelerometer range. + * The FS_SEL parameter allows setting the full-scale range of the accelerometer + * sensors, as described in the table below. + * + *
+ * 0 = +/- 2g
+ * 1 = +/- 4g
+ * 2 = +/- 8g
+ * 3 = +/- 16g
+ * 
+ * + * @return Current full-scale accelerometer range setting + * @see MPU6050_ACCEL_FS_2 + * @see MPU6050_RA_ACCEL_CONFIG + * @see MPU6050_ACONFIG_AFS_SEL_BIT + * @see MPU6050_ACONFIG_AFS_SEL_LENGTH + */ +uint8_t MPU6050::getFullScaleAccelRange() { + I2Cdev::readBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, buffer); + return buffer[0]; +} +/** Set full-scale accelerometer range. + * @param range New full-scale accelerometer range setting + * @see getFullScaleAccelRange() + */ +void MPU6050::setFullScaleAccelRange(uint8_t range) { + I2Cdev::writeBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, range); +} +/** Get the high-pass filter configuration. + * The DHPF is a filter module in the path leading to motion detectors (Free + * Fall, Motion threshold, and Zero Motion). The high pass filter output is not + * available to the data registers (see Figure in Section 8 of the MPU-6000/ + * MPU-6050 Product Specification document). + * + * The high pass filter has three modes: + * + *
+ *    Reset: The filter output settles to zero within one sample. This
+ *           effectively disables the high pass filter. This mode may be toggled
+ *           to quickly settle the filter.
+ *
+ *    On:    The high pass filter will pass signals above the cut off frequency.
+ *
+ *    Hold:  When triggered, the filter holds the present sample. The filter
+ *           output will be the difference between the input sample and the held
+ *           sample.
+ * 
+ * + *
+ * ACCEL_HPF | Filter Mode | Cut-off Frequency
+ * ----------+-------------+------------------
+ * 0         | Reset       | None
+ * 1         | On          | 5Hz
+ * 2         | On          | 2.5Hz
+ * 3         | On          | 1.25Hz
+ * 4         | On          | 0.63Hz
+ * 7         | Hold        | None
+ * 
+ * + * @return Current high-pass filter configuration + * @see MPU6050_DHPF_RESET + * @see MPU6050_RA_ACCEL_CONFIG + */ +uint8_t MPU6050::getDHPFMode() { + I2Cdev::readBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ACCEL_HPF_BIT, MPU6050_ACONFIG_ACCEL_HPF_LENGTH, buffer); + return buffer[0]; +} +/** Set the high-pass filter configuration. + * @param bandwidth New high-pass filter configuration + * @see setDHPFMode() + * @see MPU6050_DHPF_RESET + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050::setDHPFMode(uint8_t bandwidth) { + I2Cdev::writeBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ACCEL_HPF_BIT, MPU6050_ACONFIG_ACCEL_HPF_LENGTH, bandwidth); +} + +// FF_THR register + +/** Get free-fall event acceleration threshold. + * This register configures the detection threshold for Free Fall event + * detection. The unit of FF_THR is 1LSB = 2mg. Free Fall is detected when the + * absolute value of the accelerometer measurements for the three axes are each + * less than the detection threshold. This condition increments the Free Fall + * duration counter (Register 30). The Free Fall interrupt is triggered when the + * Free Fall duration counter reaches the time specified in FF_DUR. + * + * For more details on the Free Fall detection interrupt, see Section 8.2 of the + * MPU-6000/MPU-6050 Product Specification document as well as Registers 56 and + * 58 of this document. + * + * @return Current free-fall acceleration threshold value (LSB = 2mg) + * @see MPU6050_RA_FF_THR + */ +uint8_t MPU6050::getFreefallDetectionThreshold() { + I2Cdev::readByte(devAddr, MPU6050_RA_FF_THR, buffer); + return buffer[0]; +} +/** Get free-fall event acceleration threshold. + * @param threshold New free-fall acceleration threshold value (LSB = 2mg) + * @see getFreefallDetectionThreshold() + * @see MPU6050_RA_FF_THR + */ +void MPU6050::setFreefallDetectionThreshold(uint8_t threshold) { + I2Cdev::writeByte(devAddr, MPU6050_RA_FF_THR, threshold); +} + +// FF_DUR register + +/** Get free-fall event duration threshold. + * This register configures the duration counter threshold for Free Fall event + * detection. The duration counter ticks at 1kHz, therefore FF_DUR has a unit + * of 1 LSB = 1 ms. + * + * The Free Fall duration counter increments while the absolute value of the + * accelerometer measurements are each less than the detection threshold + * (Register 29). The Free Fall interrupt is triggered when the Free Fall + * duration counter reaches the time specified in this register. + * + * For more details on the Free Fall detection interrupt, see Section 8.2 of + * the MPU-6000/MPU-6050 Product Specification document as well as Registers 56 + * and 58 of this document. + * + * @return Current free-fall duration threshold value (LSB = 1ms) + * @see MPU6050_RA_FF_DUR + */ +uint8_t MPU6050::getFreefallDetectionDuration() { + I2Cdev::readByte(devAddr, MPU6050_RA_FF_DUR, buffer); + return buffer[0]; +} +/** Get free-fall event duration threshold. + * @param duration New free-fall duration threshold value (LSB = 1ms) + * @see getFreefallDetectionDuration() + * @see MPU6050_RA_FF_DUR + */ +void MPU6050::setFreefallDetectionDuration(uint8_t duration) { + I2Cdev::writeByte(devAddr, MPU6050_RA_FF_DUR, duration); +} + +// MOT_THR register + +/** Get motion detection event acceleration threshold. + * This register configures the detection threshold for Motion interrupt + * generation. The unit of MOT_THR is 1LSB = 2mg. Motion is detected when the + * absolute value of any of the accelerometer measurements exceeds this Motion + * detection threshold. This condition increments the Motion detection duration + * counter (Register 32). The Motion detection interrupt is triggered when the + * Motion Detection counter reaches the time count specified in MOT_DUR + * (Register 32). + * + * The Motion interrupt will indicate the axis and polarity of detected motion + * in MOT_DETECT_STATUS (Register 97). + * + * For more details on the Motion detection interrupt, see Section 8.3 of the + * MPU-6000/MPU-6050 Product Specification document as well as Registers 56 and + * 58 of this document. + * + * @return Current motion detection acceleration threshold value (LSB = 2mg) + * @see MPU6050_RA_MOT_THR + */ +uint8_t MPU6050::getMotionDetectionThreshold() { + I2Cdev::readByte(devAddr, MPU6050_RA_MOT_THR, buffer); + return buffer[0]; +} +/** Set motion detection event acceleration threshold. + * @param threshold New motion detection acceleration threshold value (LSB = 2mg) + * @see getMotionDetectionThreshold() + * @see MPU6050_RA_MOT_THR + */ +void MPU6050::setMotionDetectionThreshold(uint8_t threshold) { + I2Cdev::writeByte(devAddr, MPU6050_RA_MOT_THR, threshold); +} + +// MOT_DUR register + +/** Get motion detection event duration threshold. + * This register configures the duration counter threshold for Motion interrupt + * generation. The duration counter ticks at 1 kHz, therefore MOT_DUR has a unit + * of 1LSB = 1ms. The Motion detection duration counter increments when the + * absolute value of any of the accelerometer measurements exceeds the Motion + * detection threshold (Register 31). The Motion detection interrupt is + * triggered when the Motion detection counter reaches the time count specified + * in this register. + * + * For more details on the Motion detection interrupt, see Section 8.3 of the + * MPU-6000/MPU-6050 Product Specification document. + * + * @return Current motion detection duration threshold value (LSB = 1ms) + * @see MPU6050_RA_MOT_DUR + */ +uint8_t MPU6050::getMotionDetectionDuration() { + I2Cdev::readByte(devAddr, MPU6050_RA_MOT_DUR, buffer); + return buffer[0]; +} +/** Set motion detection event duration threshold. + * @param duration New motion detection duration threshold value (LSB = 1ms) + * @see getMotionDetectionDuration() + * @see MPU6050_RA_MOT_DUR + */ +void MPU6050::setMotionDetectionDuration(uint8_t duration) { + I2Cdev::writeByte(devAddr, MPU6050_RA_MOT_DUR, duration); +} + +// ZRMOT_THR register + +/** Get zero motion detection event acceleration threshold. + * This register configures the detection threshold for Zero Motion interrupt + * generation. The unit of ZRMOT_THR is 1LSB = 2mg. Zero Motion is detected when + * the absolute value of the accelerometer measurements for the 3 axes are each + * less than the detection threshold. This condition increments the Zero Motion + * duration counter (Register 34). The Zero Motion interrupt is triggered when + * the Zero Motion duration counter reaches the time count specified in + * ZRMOT_DUR (Register 34). + * + * Unlike Free Fall or Motion detection, Zero Motion detection triggers an + * interrupt both when Zero Motion is first detected and when Zero Motion is no + * longer detected. + * + * When a zero motion event is detected, a Zero Motion Status will be indicated + * in the MOT_DETECT_STATUS register (Register 97). When a motion-to-zero-motion + * condition is detected, the status bit is set to 1. When a zero-motion-to- + * motion condition is detected, the status bit is set to 0. + * + * For more details on the Zero Motion detection interrupt, see Section 8.4 of + * the MPU-6000/MPU-6050 Product Specification document as well as Registers 56 + * and 58 of this document. + * + * @return Current zero motion detection acceleration threshold value (LSB = 2mg) + * @see MPU6050_RA_ZRMOT_THR + */ +uint8_t MPU6050::getZeroMotionDetectionThreshold() { + I2Cdev::readByte(devAddr, MPU6050_RA_ZRMOT_THR, buffer); + return buffer[0]; +} +/** Set zero motion detection event acceleration threshold. + * @param threshold New zero motion detection acceleration threshold value (LSB = 2mg) + * @see getZeroMotionDetectionThreshold() + * @see MPU6050_RA_ZRMOT_THR + */ +void MPU6050::setZeroMotionDetectionThreshold(uint8_t threshold) { + I2Cdev::writeByte(devAddr, MPU6050_RA_ZRMOT_THR, threshold); +} + +// ZRMOT_DUR register + +/** Get zero motion detection event duration threshold. + * This register configures the duration counter threshold for Zero Motion + * interrupt generation. The duration counter ticks at 16 Hz, therefore + * ZRMOT_DUR has a unit of 1 LSB = 64 ms. The Zero Motion duration counter + * increments while the absolute value of the accelerometer measurements are + * each less than the detection threshold (Register 33). The Zero Motion + * interrupt is triggered when the Zero Motion duration counter reaches the time + * count specified in this register. + * + * For more details on the Zero Motion detection interrupt, see Section 8.4 of + * the MPU-6000/MPU-6050 Product Specification document, as well as Registers 56 + * and 58 of this document. + * + * @return Current zero motion detection duration threshold value (LSB = 64ms) + * @see MPU6050_RA_ZRMOT_DUR + */ +uint8_t MPU6050::getZeroMotionDetectionDuration() { + I2Cdev::readByte(devAddr, MPU6050_RA_ZRMOT_DUR, buffer); + return buffer[0]; +} +/** Set zero motion detection event duration threshold. + * @param duration New zero motion detection duration threshold value (LSB = 1ms) + * @see getZeroMotionDetectionDuration() + * @see MPU6050_RA_ZRMOT_DUR + */ +void MPU6050::setZeroMotionDetectionDuration(uint8_t duration) { + I2Cdev::writeByte(devAddr, MPU6050_RA_ZRMOT_DUR, duration); +} + +// FIFO_EN register + +/** Get temperature FIFO enabled value. + * When set to 1, this bit enables TEMP_OUT_H and TEMP_OUT_L (Registers 65 and + * 66) to be written into the FIFO buffer. + * @return Current temperature FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050::getTempFIFOEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_TEMP_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set temperature FIFO enabled value. + * @param enabled New temperature FIFO enabled value + * @see getTempFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050::setTempFIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_TEMP_FIFO_EN_BIT, enabled); +} +/** Get gyroscope X-axis FIFO enabled value. + * When set to 1, this bit enables GYRO_XOUT_H and GYRO_XOUT_L (Registers 67 and + * 68) to be written into the FIFO buffer. + * @return Current gyroscope X-axis FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050::getXGyroFIFOEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_XG_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set gyroscope X-axis FIFO enabled value. + * @param enabled New gyroscope X-axis FIFO enabled value + * @see getXGyroFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050::setXGyroFIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_XG_FIFO_EN_BIT, enabled); +} +/** Get gyroscope Y-axis FIFO enabled value. + * When set to 1, this bit enables GYRO_YOUT_H and GYRO_YOUT_L (Registers 69 and + * 70) to be written into the FIFO buffer. + * @return Current gyroscope Y-axis FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050::getYGyroFIFOEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_YG_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set gyroscope Y-axis FIFO enabled value. + * @param enabled New gyroscope Y-axis FIFO enabled value + * @see getYGyroFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050::setYGyroFIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_YG_FIFO_EN_BIT, enabled); +} +/** Get gyroscope Z-axis FIFO enabled value. + * When set to 1, this bit enables GYRO_ZOUT_H and GYRO_ZOUT_L (Registers 71 and + * 72) to be written into the FIFO buffer. + * @return Current gyroscope Z-axis FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050::getZGyroFIFOEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ZG_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set gyroscope Z-axis FIFO enabled value. + * @param enabled New gyroscope Z-axis FIFO enabled value + * @see getZGyroFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050::setZGyroFIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ZG_FIFO_EN_BIT, enabled); +} +/** Get accelerometer FIFO enabled value. + * When set to 1, this bit enables ACCEL_XOUT_H, ACCEL_XOUT_L, ACCEL_YOUT_H, + * ACCEL_YOUT_L, ACCEL_ZOUT_H, and ACCEL_ZOUT_L (Registers 59 to 64) to be + * written into the FIFO buffer. + * @return Current accelerometer FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050::getAccelFIFOEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ACCEL_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set accelerometer FIFO enabled value. + * @param enabled New accelerometer FIFO enabled value + * @see getAccelFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050::setAccelFIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ACCEL_FIFO_EN_BIT, enabled); +} +/** Get Slave 2 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 2 to be written into the FIFO buffer. + * @return Current Slave 2 FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050::getSlave2FIFOEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV2_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set Slave 2 FIFO enabled value. + * @param enabled New Slave 2 FIFO enabled value + * @see getSlave2FIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050::setSlave2FIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV2_FIFO_EN_BIT, enabled); +} +/** Get Slave 1 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 1 to be written into the FIFO buffer. + * @return Current Slave 1 FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050::getSlave1FIFOEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV1_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set Slave 1 FIFO enabled value. + * @param enabled New Slave 1 FIFO enabled value + * @see getSlave1FIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050::setSlave1FIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV1_FIFO_EN_BIT, enabled); +} +/** Get Slave 0 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 0 to be written into the FIFO buffer. + * @return Current Slave 0 FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050::getSlave0FIFOEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV0_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set Slave 0 FIFO enabled value. + * @param enabled New Slave 0 FIFO enabled value + * @see getSlave0FIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050::setSlave0FIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV0_FIFO_EN_BIT, enabled); +} + +// I2C_MST_CTRL register + +/** Get multi-master enabled value. + * Multi-master capability allows multiple I2C masters to operate on the same + * bus. In circuits where multi-master capability is required, set MULT_MST_EN + * to 1. This will increase current drawn by approximately 30uA. + * + * In circuits where multi-master capability is required, the state of the I2C + * bus must always be monitored by each separate I2C Master. Before an I2C + * Master can assume arbitration of the bus, it must first confirm that no other + * I2C Master has arbitration of the bus. When MULT_MST_EN is set to 1, the + * MPU-60X0's bus arbitration detection logic is turned on, enabling it to + * detect when the bus is available. + * + * @return Current multi-master enabled value + * @see MPU6050_RA_I2C_MST_CTRL + */ +bool MPU6050::getMultiMasterEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_MULT_MST_EN_BIT, buffer); + return buffer[0]; +} +/** Set multi-master enabled value. + * @param enabled New multi-master enabled value + * @see getMultiMasterEnabled() + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050::setMultiMasterEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_MULT_MST_EN_BIT, enabled); +} +/** Get wait-for-external-sensor-data enabled value. + * When the WAIT_FOR_ES bit is set to 1, the Data Ready interrupt will be + * delayed until External Sensor data from the Slave Devices are loaded into the + * EXT_SENS_DATA registers. This is used to ensure that both the internal sensor + * data (i.e. from gyro and accel) and external sensor data have been loaded to + * their respective data registers (i.e. the data is synced) when the Data Ready + * interrupt is triggered. + * + * @return Current wait-for-external-sensor-data enabled value + * @see MPU6050_RA_I2C_MST_CTRL + */ +bool MPU6050::getWaitForExternalSensorEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_WAIT_FOR_ES_BIT, buffer); + return buffer[0]; +} +/** Set wait-for-external-sensor-data enabled value. + * @param enabled New wait-for-external-sensor-data enabled value + * @see getWaitForExternalSensorEnabled() + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050::setWaitForExternalSensorEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_WAIT_FOR_ES_BIT, enabled); +} +/** Get Slave 3 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 3 to be written into the FIFO buffer. + * @return Current Slave 3 FIFO enabled value + * @see MPU6050_RA_MST_CTRL + */ +bool MPU6050::getSlave3FIFOEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_SLV_3_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set Slave 3 FIFO enabled value. + * @param enabled New Slave 3 FIFO enabled value + * @see getSlave3FIFOEnabled() + * @see MPU6050_RA_MST_CTRL + */ +void MPU6050::setSlave3FIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_SLV_3_FIFO_EN_BIT, enabled); +} +/** Get slave read/write transition enabled value. + * The I2C_MST_P_NSR bit configures the I2C Master's transition from one slave + * read to the next slave read. If the bit equals 0, there will be a restart + * between reads. If the bit equals 1, there will be a stop followed by a start + * of the following read. When a write transaction follows a read transaction, + * the stop followed by a start of the successive write will be always used. + * + * @return Current slave read/write transition enabled value + * @see MPU6050_RA_I2C_MST_CTRL + */ +bool MPU6050::getSlaveReadWriteTransitionEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_P_NSR_BIT, buffer); + return buffer[0]; +} +/** Set slave read/write transition enabled value. + * @param enabled New slave read/write transition enabled value + * @see getSlaveReadWriteTransitionEnabled() + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050::setSlaveReadWriteTransitionEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_P_NSR_BIT, enabled); +} +/** Get I2C master clock speed. + * I2C_MST_CLK is a 4 bit unsigned value which configures a divider on the + * MPU-60X0 internal 8MHz clock. It sets the I2C master clock speed according to + * the following table: + * + *
+ * I2C_MST_CLK | I2C Master Clock Speed | 8MHz Clock Divider
+ * ------------+------------------------+-------------------
+ * 0           | 348kHz                 | 23
+ * 1           | 333kHz                 | 24
+ * 2           | 320kHz                 | 25
+ * 3           | 308kHz                 | 26
+ * 4           | 296kHz                 | 27
+ * 5           | 286kHz                 | 28
+ * 6           | 276kHz                 | 29
+ * 7           | 267kHz                 | 30
+ * 8           | 258kHz                 | 31
+ * 9           | 500kHz                 | 16
+ * 10          | 471kHz                 | 17
+ * 11          | 444kHz                 | 18
+ * 12          | 421kHz                 | 19
+ * 13          | 400kHz                 | 20
+ * 14          | 381kHz                 | 21
+ * 15          | 364kHz                 | 22
+ * 
+ * + * @return Current I2C master clock speed + * @see MPU6050_RA_I2C_MST_CTRL + */ +uint8_t MPU6050::getMasterClockSpeed() { + I2Cdev::readBits(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_CLK_BIT, MPU6050_I2C_MST_CLK_LENGTH, buffer); + return buffer[0]; +} +/** Set I2C master clock speed. + * @reparam speed Current I2C master clock speed + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050::setMasterClockSpeed(uint8_t speed) { + I2Cdev::writeBits(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_CLK_BIT, MPU6050_I2C_MST_CLK_LENGTH, speed); +} + +// I2C_SLV* registers (Slave 0-3) + +/** Get the I2C address of the specified slave (0-3). + * Note that Bit 7 (MSB) controls read/write mode. If Bit 7 is set, it's a read + * operation, and if it is cleared, then it's a write operation. The remaining + * bits (6-0) are the 7-bit device address of the slave device. + * + * In read mode, the result of the read is placed in the lowest available + * EXT_SENS_DATA register. For further information regarding the allocation of + * read results, please refer to the EXT_SENS_DATA register description + * (Registers 73 - 96). + * + * The MPU-6050 supports a total of five slaves, but Slave 4 has unique + * characteristics, and so it has its own functions (getSlave4* and setSlave4*). + * + * I2C data transactions are performed at the Sample Rate, as defined in + * Register 25. The user is responsible for ensuring that I2C data transactions + * to and from each enabled Slave can be completed within a single period of the + * Sample Rate. + * + * The I2C slave access rate can be reduced relative to the Sample Rate. This + * reduced access rate is determined by I2C_MST_DLY (Register 52). Whether a + * slave's access rate is reduced relative to the Sample Rate is determined by + * I2C_MST_DELAY_CTRL (Register 103). + * + * The processing order for the slaves is fixed. The sequence followed for + * processing the slaves is Slave 0, Slave 1, Slave 2, Slave 3 and Slave 4. If a + * particular Slave is disabled it will be skipped. + * + * Each slave can either be accessed at the sample rate or at a reduced sample + * rate. In a case where some slaves are accessed at the Sample Rate and some + * slaves are accessed at the reduced rate, the sequence of accessing the slaves + * (Slave 0 to Slave 4) is still followed. However, the reduced rate slaves will + * be skipped if their access rate dictates that they should not be accessed + * during that particular cycle. For further information regarding the reduced + * access rate, please refer to Register 52. Whether a slave is accessed at the + * Sample Rate or at the reduced rate is determined by the Delay Enable bits in + * Register 103. + * + * @param num Slave number (0-3) + * @return Current address for specified slave + * @see MPU6050_RA_I2C_SLV0_ADDR + */ +uint8_t MPU6050::getSlaveAddress(uint8_t num) { + if (num > 3) return 0; + I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV0_ADDR + num*3, buffer); + return buffer[0]; +} +/** Set the I2C address of the specified slave (0-3). + * @param num Slave number (0-3) + * @param address New address for specified slave + * @see getSlaveAddress() + * @see MPU6050_RA_I2C_SLV0_ADDR + */ +void MPU6050::setSlaveAddress(uint8_t num, uint8_t address) { + if (num > 3) return; + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV0_ADDR + num*3, address); +} +/** Get the active internal register for the specified slave (0-3). + * Read/write operations for this slave will be done to whatever internal + * register address is stored in this MPU register. + * + * The MPU-6050 supports a total of five slaves, but Slave 4 has unique + * characteristics, and so it has its own functions. + * + * @param num Slave number (0-3) + * @return Current active register for specified slave + * @see MPU6050_RA_I2C_SLV0_REG + */ +uint8_t MPU6050::getSlaveRegister(uint8_t num) { + if (num > 3) return 0; + I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV0_REG + num*3, buffer); + return buffer[0]; +} +/** Set the active internal register for the specified slave (0-3). + * @param num Slave number (0-3) + * @param reg New active register for specified slave + * @see getSlaveRegister() + * @see MPU6050_RA_I2C_SLV0_REG + */ +void MPU6050::setSlaveRegister(uint8_t num, uint8_t reg) { + if (num > 3) return; + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV0_REG + num*3, reg); +} +/** Get the enabled value for the specified slave (0-3). + * When set to 1, this bit enables Slave 0 for data transfer operations. When + * cleared to 0, this bit disables Slave 0 from data transfer operations. + * @param num Slave number (0-3) + * @return Current enabled value for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +bool MPU6050::getSlaveEnabled(uint8_t num) { + if (num > 3) return 0; + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_EN_BIT, buffer); + return buffer[0]; +} +/** Set the enabled value for the specified slave (0-3). + * @param num Slave number (0-3) + * @param enabled New enabled value for specified slave + * @see getSlaveEnabled() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050::setSlaveEnabled(uint8_t num, bool enabled) { + if (num > 3) return; + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_EN_BIT, enabled); +} +/** Get word pair byte-swapping enabled for the specified slave (0-3). + * When set to 1, this bit enables byte swapping. When byte swapping is enabled, + * the high and low bytes of a word pair are swapped. Please refer to + * I2C_SLV0_GRP for the pairing convention of the word pairs. When cleared to 0, + * bytes transferred to and from Slave 0 will be written to EXT_SENS_DATA + * registers in the order they were transferred. + * + * @param num Slave number (0-3) + * @return Current word pair byte-swapping enabled value for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +bool MPU6050::getSlaveWordByteSwap(uint8_t num) { + if (num > 3) return 0; + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_BYTE_SW_BIT, buffer); + return buffer[0]; +} +/** Set word pair byte-swapping enabled for the specified slave (0-3). + * @param num Slave number (0-3) + * @param enabled New word pair byte-swapping enabled value for specified slave + * @see getSlaveWordByteSwap() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050::setSlaveWordByteSwap(uint8_t num, bool enabled) { + if (num > 3) return; + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_BYTE_SW_BIT, enabled); +} +/** Get write mode for the specified slave (0-3). + * When set to 1, the transaction will read or write data only. When cleared to + * 0, the transaction will write a register address prior to reading or writing + * data. This should equal 0 when specifying the register address within the + * Slave device to/from which the ensuing data transaction will take place. + * + * @param num Slave number (0-3) + * @return Current write mode for specified slave (0 = register address + data, 1 = data only) + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +bool MPU6050::getSlaveWriteMode(uint8_t num) { + if (num > 3) return 0; + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_REG_DIS_BIT, buffer); + return buffer[0]; +} +/** Set write mode for the specified slave (0-3). + * @param num Slave number (0-3) + * @param mode New write mode for specified slave (0 = register address + data, 1 = data only) + * @see getSlaveWriteMode() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050::setSlaveWriteMode(uint8_t num, bool mode) { + if (num > 3) return; + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_REG_DIS_BIT, mode); +} +/** Get word pair grouping order offset for the specified slave (0-3). + * This sets specifies the grouping order of word pairs received from registers. + * When cleared to 0, bytes from register addresses 0 and 1, 2 and 3, etc (even, + * then odd register addresses) are paired to form a word. When set to 1, bytes + * from register addresses are paired 1 and 2, 3 and 4, etc. (odd, then even + * register addresses) are paired to form a word. + * + * @param num Slave number (0-3) + * @return Current word pair grouping order offset for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +bool MPU6050::getSlaveWordGroupOffset(uint8_t num) { + if (num > 3) return 0; + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_GRP_BIT, buffer); + return buffer[0]; +} +/** Set word pair grouping order offset for the specified slave (0-3). + * @param num Slave number (0-3) + * @param enabled New word pair grouping order offset for specified slave + * @see getSlaveWordGroupOffset() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050::setSlaveWordGroupOffset(uint8_t num, bool enabled) { + if (num > 3) return; + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_GRP_BIT, enabled); +} +/** Get number of bytes to read for the specified slave (0-3). + * Specifies the number of bytes transferred to and from Slave 0. Clearing this + * bit to 0 is equivalent to disabling the register by writing 0 to I2C_SLV0_EN. + * @param num Slave number (0-3) + * @return Number of bytes to read for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +uint8_t MPU6050::getSlaveDataLength(uint8_t num) { + if (num > 3) return 0; + I2Cdev::readBits(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_LEN_BIT, MPU6050_I2C_SLV_LEN_LENGTH, buffer); + return buffer[0]; +} +/** Set number of bytes to read for the specified slave (0-3). + * @param num Slave number (0-3) + * @param length Number of bytes to read for specified slave + * @see getSlaveDataLength() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050::setSlaveDataLength(uint8_t num, uint8_t length) { + if (num > 3) return; + I2Cdev::writeBits(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_LEN_BIT, MPU6050_I2C_SLV_LEN_LENGTH, length); +} + +// I2C_SLV* registers (Slave 4) + +/** Get the I2C address of Slave 4. + * Note that Bit 7 (MSB) controls read/write mode. If Bit 7 is set, it's a read + * operation, and if it is cleared, then it's a write operation. The remaining + * bits (6-0) are the 7-bit device address of the slave device. + * + * @return Current address for Slave 4 + * @see getSlaveAddress() + * @see MPU6050_RA_I2C_SLV4_ADDR + */ +uint8_t MPU6050::getSlave4Address() { + I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV4_ADDR, buffer); + return buffer[0]; +} +/** Set the I2C address of Slave 4. + * @param address New address for Slave 4 + * @see getSlave4Address() + * @see MPU6050_RA_I2C_SLV4_ADDR + */ +void MPU6050::setSlave4Address(uint8_t address) { + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV4_ADDR, address); +} +/** Get the active internal register for the Slave 4. + * Read/write operations for this slave will be done to whatever internal + * register address is stored in this MPU register. + * + * @return Current active register for Slave 4 + * @see MPU6050_RA_I2C_SLV4_REG + */ +uint8_t MPU6050::getSlave4Register() { + I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV4_REG, buffer); + return buffer[0]; +} +/** Set the active internal register for Slave 4. + * @param reg New active register for Slave 4 + * @see getSlave4Register() + * @see MPU6050_RA_I2C_SLV4_REG + */ +void MPU6050::setSlave4Register(uint8_t reg) { + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV4_REG, reg); +} +/** Set new byte to write to Slave 4. + * This register stores the data to be written into the Slave 4. If I2C_SLV4_RW + * is set 1 (set to read), this register has no effect. + * @param data New byte to write to Slave 4 + * @see MPU6050_RA_I2C_SLV4_DO + */ +void MPU6050::setSlave4OutputByte(uint8_t data) { + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV4_DO, data); +} +/** Get the enabled value for the Slave 4. + * When set to 1, this bit enables Slave 4 for data transfer operations. When + * cleared to 0, this bit disables Slave 4 from data transfer operations. + * @return Current enabled value for Slave 4 + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +bool MPU6050::getSlave4Enabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_EN_BIT, buffer); + return buffer[0]; +} +/** Set the enabled value for Slave 4. + * @param enabled New enabled value for Slave 4 + * @see getSlave4Enabled() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050::setSlave4Enabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_EN_BIT, enabled); +} +/** Get the enabled value for Slave 4 transaction interrupts. + * When set to 1, this bit enables the generation of an interrupt signal upon + * completion of a Slave 4 transaction. When cleared to 0, this bit disables the + * generation of an interrupt signal upon completion of a Slave 4 transaction. + * The interrupt status can be observed in Register 54. + * + * @return Current enabled value for Slave 4 transaction interrupts. + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +bool MPU6050::getSlave4InterruptEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_INT_EN_BIT, buffer); + return buffer[0]; +} +/** Set the enabled value for Slave 4 transaction interrupts. + * @param enabled New enabled value for Slave 4 transaction interrupts. + * @see getSlave4InterruptEnabled() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050::setSlave4InterruptEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_INT_EN_BIT, enabled); +} +/** Get write mode for Slave 4. + * When set to 1, the transaction will read or write data only. When cleared to + * 0, the transaction will write a register address prior to reading or writing + * data. This should equal 0 when specifying the register address within the + * Slave device to/from which the ensuing data transaction will take place. + * + * @return Current write mode for Slave 4 (0 = register address + data, 1 = data only) + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +bool MPU6050::getSlave4WriteMode() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_REG_DIS_BIT, buffer); + return buffer[0]; +} +/** Set write mode for the Slave 4. + * @param mode New write mode for Slave 4 (0 = register address + data, 1 = data only) + * @see getSlave4WriteMode() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050::setSlave4WriteMode(bool mode) { + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_REG_DIS_BIT, mode); +} +/** Get Slave 4 master delay value. + * This configures the reduced access rate of I2C slaves relative to the Sample + * Rate. When a slave's access rate is decreased relative to the Sample Rate, + * the slave is accessed every: + * + * 1 / (1 + I2C_MST_DLY) samples + * + * This base Sample Rate in turn is determined by SMPLRT_DIV (register 25) and + * DLPF_CFG (register 26). Whether a slave's access rate is reduced relative to + * the Sample Rate is determined by I2C_MST_DELAY_CTRL (register 103). For + * further information regarding the Sample Rate, please refer to register 25. + * + * @return Current Slave 4 master delay value + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +uint8_t MPU6050::getSlave4MasterDelay() { + I2Cdev::readBits(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_MST_DLY_BIT, MPU6050_I2C_SLV4_MST_DLY_LENGTH, buffer); + return buffer[0]; +} +/** Set Slave 4 master delay value. + * @param delay New Slave 4 master delay value + * @see getSlave4MasterDelay() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050::setSlave4MasterDelay(uint8_t delay) { + I2Cdev::writeBits(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_MST_DLY_BIT, MPU6050_I2C_SLV4_MST_DLY_LENGTH, delay); +} +/** Get last available byte read from Slave 4. + * This register stores the data read from Slave 4. This field is populated + * after a read transaction. + * @return Last available byte read from to Slave 4 + * @see MPU6050_RA_I2C_SLV4_DI + */ +uint8_t MPU6050::getSlate4InputByte() { + I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV4_DI, buffer); + return buffer[0]; +} + +// I2C_MST_STATUS register + +/** Get FSYNC interrupt status. + * This bit reflects the status of the FSYNC interrupt from an external device + * into the MPU-60X0. This is used as a way to pass an external interrupt + * through the MPU-60X0 to the host application processor. When set to 1, this + * bit will cause an interrupt if FSYNC_INT_EN is asserted in INT_PIN_CFG + * (Register 55). + * @return FSYNC interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050::getPassthroughStatus() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_PASS_THROUGH_BIT, buffer); + return buffer[0]; +} +/** Get Slave 4 transaction done status. + * Automatically sets to 1 when a Slave 4 transaction has completed. This + * triggers an interrupt if the I2C_MST_INT_EN bit in the INT_ENABLE register + * (Register 56) is asserted and if the SLV_4_DONE_INT bit is asserted in the + * I2C_SLV4_CTRL register (Register 52). + * @return Slave 4 transaction done status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050::getSlave4IsDone() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV4_DONE_BIT, buffer); + return buffer[0]; +} +/** Get master arbitration lost status. + * This bit automatically sets to 1 when the I2C Master has lost arbitration of + * the auxiliary I2C bus (an error condition). This triggers an interrupt if the + * I2C_MST_INT_EN bit in the INT_ENABLE register (Register 56) is asserted. + * @return Master arbitration lost status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050::getLostArbitration() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_LOST_ARB_BIT, buffer); + return buffer[0]; +} +/** Get Slave 4 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 4. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 4 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050::getSlave4Nack() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV4_NACK_BIT, buffer); + return buffer[0]; +} +/** Get Slave 3 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 3. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 3 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050::getSlave3Nack() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV3_NACK_BIT, buffer); + return buffer[0]; +} +/** Get Slave 2 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 2. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 2 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050::getSlave2Nack() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV2_NACK_BIT, buffer); + return buffer[0]; +} +/** Get Slave 1 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 1. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 1 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050::getSlave1Nack() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV1_NACK_BIT, buffer); + return buffer[0]; +} +/** Get Slave 0 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 0. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 0 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050::getSlave0Nack() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV0_NACK_BIT, buffer); + return buffer[0]; +} + +// INT_PIN_CFG register + +/** Get interrupt logic level mode. + * Will be set 0 for active-high, 1 for active-low. + * @return Current interrupt mode (0=active-high, 1=active-low) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_LEVEL_BIT + */ +bool MPU6050::getInterruptMode() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_LEVEL_BIT, buffer); + return buffer[0]; +} +/** Set interrupt logic level mode. + * @param mode New interrupt mode (0=active-high, 1=active-low) + * @see getInterruptMode() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_LEVEL_BIT + */ +void MPU6050::setInterruptMode(bool mode) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_LEVEL_BIT, mode); +} +/** Get interrupt drive mode. + * Will be set 0 for push-pull, 1 for open-drain. + * @return Current interrupt drive mode (0=push-pull, 1=open-drain) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_OPEN_BIT + */ +bool MPU6050::getInterruptDrive() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_OPEN_BIT, buffer); + return buffer[0]; +} +/** Set interrupt drive mode. + * @param drive New interrupt drive mode (0=push-pull, 1=open-drain) + * @see getInterruptDrive() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_OPEN_BIT + */ +void MPU6050::setInterruptDrive(bool drive) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_OPEN_BIT, drive); +} +/** Get interrupt latch mode. + * Will be set 0 for 50us-pulse, 1 for latch-until-int-cleared. + * @return Current latch mode (0=50us-pulse, 1=latch-until-int-cleared) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_LATCH_INT_EN_BIT + */ +bool MPU6050::getInterruptLatch() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_LATCH_INT_EN_BIT, buffer); + return buffer[0]; +} +/** Set interrupt latch mode. + * @param latch New latch mode (0=50us-pulse, 1=latch-until-int-cleared) + * @see getInterruptLatch() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_LATCH_INT_EN_BIT + */ +void MPU6050::setInterruptLatch(bool latch) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_LATCH_INT_EN_BIT, latch); +} +/** Get interrupt latch clear mode. + * Will be set 0 for status-read-only, 1 for any-register-read. + * @return Current latch clear mode (0=status-read-only, 1=any-register-read) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_RD_CLEAR_BIT + */ +bool MPU6050::getInterruptLatchClear() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_RD_CLEAR_BIT, buffer); + return buffer[0]; +} +/** Set interrupt latch clear mode. + * @param clear New latch clear mode (0=status-read-only, 1=any-register-read) + * @see getInterruptLatchClear() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_RD_CLEAR_BIT + */ +void MPU6050::setInterruptLatchClear(bool clear) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_RD_CLEAR_BIT, clear); +} +/** Get FSYNC interrupt logic level mode. + * @return Current FSYNC interrupt mode (0=active-high, 1=active-low) + * @see getFSyncInterruptMode() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT + */ +bool MPU6050::getFSyncInterruptLevel() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT, buffer); + return buffer[0]; +} +/** Set FSYNC interrupt logic level mode. + * @param mode New FSYNC interrupt mode (0=active-high, 1=active-low) + * @see getFSyncInterruptMode() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT + */ +void MPU6050::setFSyncInterruptLevel(bool level) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT, level); +} +/** Get FSYNC pin interrupt enabled setting. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled setting + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_EN_BIT + */ +bool MPU6050::getFSyncInterruptEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_EN_BIT, buffer); + return buffer[0]; +} +/** Set FSYNC pin interrupt enabled setting. + * @param enabled New FSYNC pin interrupt enabled setting + * @see getFSyncInterruptEnabled() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_EN_BIT + */ +void MPU6050::setFSyncInterruptEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_EN_BIT, enabled); +} +/** Get I2C bypass enabled status. + * When this bit is equal to 1 and I2C_MST_EN (Register 106 bit[5]) is equal to + * 0, the host application processor will be able to directly access the + * auxiliary I2C bus of the MPU-60X0. When this bit is equal to 0, the host + * application processor will not be able to directly access the auxiliary I2C + * bus of the MPU-60X0 regardless of the state of I2C_MST_EN (Register 106 + * bit[5]). + * @return Current I2C bypass enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_I2C_BYPASS_EN_BIT + */ +bool MPU6050::getI2CBypassEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_I2C_BYPASS_EN_BIT, buffer); + return buffer[0]; +} +/** Set I2C bypass enabled status. + * When this bit is equal to 1 and I2C_MST_EN (Register 106 bit[5]) is equal to + * 0, the host application processor will be able to directly access the + * auxiliary I2C bus of the MPU-60X0. When this bit is equal to 0, the host + * application processor will not be able to directly access the auxiliary I2C + * bus of the MPU-60X0 regardless of the state of I2C_MST_EN (Register 106 + * bit[5]). + * @param enabled New I2C bypass enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_I2C_BYPASS_EN_BIT + */ +void MPU6050::setI2CBypassEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_I2C_BYPASS_EN_BIT, enabled); +} +/** Get reference clock output enabled status. + * When this bit is equal to 1, a reference clock output is provided at the + * CLKOUT pin. When this bit is equal to 0, the clock output is disabled. For + * further information regarding CLKOUT, please refer to the MPU-60X0 Product + * Specification document. + * @return Current reference clock output enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_CLKOUT_EN_BIT + */ +bool MPU6050::getClockOutputEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_CLKOUT_EN_BIT, buffer); + return buffer[0]; +} +/** Set reference clock output enabled status. + * When this bit is equal to 1, a reference clock output is provided at the + * CLKOUT pin. When this bit is equal to 0, the clock output is disabled. For + * further information regarding CLKOUT, please refer to the MPU-60X0 Product + * Specification document. + * @param enabled New reference clock output enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_CLKOUT_EN_BIT + */ +void MPU6050::setClockOutputEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_CLKOUT_EN_BIT, enabled); +} + +// INT_ENABLE register + +/** Get full interrupt enabled status. + * Full register byte for all interrupts, for quick reading. Each bit will be + * set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +uint8_t MPU6050::getIntEnabled() { + I2Cdev::readByte(devAddr, MPU6050_RA_INT_ENABLE, buffer); + return buffer[0]; +} +/** Set full interrupt enabled status. + * Full register byte for all interrupts, for quick reading. Each bit should be + * set 0 for disabled, 1 for enabled. + * @param enabled New interrupt enabled status + * @see getIntFreefallEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +void MPU6050::setIntEnabled(uint8_t enabled) { + I2Cdev::writeByte(devAddr, MPU6050_RA_INT_ENABLE, enabled); +} +/** Get Free Fall interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +bool MPU6050::getIntFreefallEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FF_BIT, buffer); + return buffer[0]; +} +/** Set Free Fall interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntFreefallEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +void MPU6050::setIntFreefallEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FF_BIT, enabled); +} +/** Get Motion Detection interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_MOT_BIT + **/ +bool MPU6050::getIntMotionEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_MOT_BIT, buffer); + return buffer[0]; +} +/** Set Motion Detection interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntMotionEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_MOT_BIT + **/ +void MPU6050::setIntMotionEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_MOT_BIT, enabled); +} +/** Get Zero Motion Detection interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_ZMOT_BIT + **/ +bool MPU6050::getIntZeroMotionEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_ZMOT_BIT, buffer); + return buffer[0]; +} +/** Set Zero Motion Detection interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntZeroMotionEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_ZMOT_BIT + **/ +void MPU6050::setIntZeroMotionEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_ZMOT_BIT, enabled); +} +/** Get FIFO Buffer Overflow interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT + **/ +bool MPU6050::getIntFIFOBufferOverflowEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, buffer); + return buffer[0]; +} +/** Set FIFO Buffer Overflow interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntFIFOBufferOverflowEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT + **/ +void MPU6050::setIntFIFOBufferOverflowEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, enabled); +} +/** Get I2C Master interrupt enabled status. + * This enables any of the I2C Master interrupt sources to generate an + * interrupt. Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT + **/ +bool MPU6050::getIntI2CMasterEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_I2C_MST_INT_BIT, buffer); + return buffer[0]; +} +/** Set I2C Master interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntI2CMasterEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT + **/ +void MPU6050::setIntI2CMasterEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_I2C_MST_INT_BIT, enabled); +} +/** Get Data Ready interrupt enabled setting. + * This event occurs each time a write operation to all of the sensor registers + * has been completed. Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_DATA_RDY_BIT + */ +bool MPU6050::getIntDataReadyEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DATA_RDY_BIT, buffer); + return buffer[0]; +} +/** Set Data Ready interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntDataReadyEnabled() + * @see MPU6050_RA_INT_CFG + * @see MPU6050_INTERRUPT_DATA_RDY_BIT + */ +void MPU6050::setIntDataReadyEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DATA_RDY_BIT, enabled); +} + +// INT_STATUS register + +/** Get full set of interrupt status bits. + * These bits clear to 0 after the register has been read. Very useful + * for getting multiple INT statuses, since each single bit read clears + * all of them because it has to read the whole byte. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + */ +uint8_t MPU6050::getIntStatus() { + I2Cdev::readByte(devAddr, MPU6050_RA_INT_STATUS, buffer); + return buffer[0]; +} +/** Get Free Fall interrupt status. + * This bit automatically sets to 1 when a Free Fall interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_FF_BIT + */ +bool MPU6050::getIntFreefallStatus() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_FF_BIT, buffer); + return buffer[0]; +} +/** Get Motion Detection interrupt status. + * This bit automatically sets to 1 when a Motion Detection interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_MOT_BIT + */ +bool MPU6050::getIntMotionStatus() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_MOT_BIT, buffer); + return buffer[0]; +} +/** Get Zero Motion Detection interrupt status. + * This bit automatically sets to 1 when a Zero Motion Detection interrupt has + * been generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_ZMOT_BIT + */ +bool MPU6050::getIntZeroMotionStatus() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_ZMOT_BIT, buffer); + return buffer[0]; +} +/** Get FIFO Buffer Overflow interrupt status. + * This bit automatically sets to 1 when a Free Fall interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT + */ +bool MPU6050::getIntFIFOBufferOverflowStatus() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, buffer); + return buffer[0]; +} +/** Get I2C Master interrupt status. + * This bit automatically sets to 1 when an I2C Master interrupt has been + * generated. For a list of I2C Master interrupts, please refer to Register 54. + * The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT + */ +bool MPU6050::getIntI2CMasterStatus() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_I2C_MST_INT_BIT, buffer); + return buffer[0]; +} +/** Get Data Ready interrupt status. + * This bit automatically sets to 1 when a Data Ready interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_DATA_RDY_BIT + */ +bool MPU6050::getIntDataReadyStatus() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_DATA_RDY_BIT, buffer); + return buffer[0]; +} + +// ACCEL_*OUT_* registers + +/** Get raw 9-axis motion sensor readings (accel/gyro/compass). + * FUNCTION NOT FULLY IMPLEMENTED YET. + * @param ax 16-bit signed integer container for accelerometer X-axis value + * @param ay 16-bit signed integer container for accelerometer Y-axis value + * @param az 16-bit signed integer container for accelerometer Z-axis value + * @param gx 16-bit signed integer container for gyroscope X-axis value + * @param gy 16-bit signed integer container for gyroscope Y-axis value + * @param gz 16-bit signed integer container for gyroscope Z-axis value + * @param mx 16-bit signed integer container for magnetometer X-axis value + * @param my 16-bit signed integer container for magnetometer Y-axis value + * @param mz 16-bit signed integer container for magnetometer Z-axis value + * @see getMotion6() + * @see getAcceleration() + * @see getRotation() + * @see MPU6050_RA_ACCEL_XOUT_H + */ +void MPU6050::getMotion9(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz, int16_t* mx, int16_t* my, int16_t* mz) { + getMotion6(ax, ay, az, gx, gy, gz); + // TODO: magnetometer integration +} +/** Get raw 6-axis motion sensor readings (accel/gyro). + * Retrieves all currently available motion sensor values. + * @param ax 16-bit signed integer container for accelerometer X-axis value + * @param ay 16-bit signed integer container for accelerometer Y-axis value + * @param az 16-bit signed integer container for accelerometer Z-axis value + * @param gx 16-bit signed integer container for gyroscope X-axis value + * @param gy 16-bit signed integer container for gyroscope Y-axis value + * @param gz 16-bit signed integer container for gyroscope Z-axis value + * @see getAcceleration() + * @see getRotation() + * @see MPU6050_RA_ACCEL_XOUT_H + */ +void MPU6050::getMotion6(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz) { + I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_XOUT_H, 14, buffer); + *ax = (((int16_t)buffer[0]) << 8) | buffer[1]; + *ay = (((int16_t)buffer[2]) << 8) | buffer[3]; + *az = (((int16_t)buffer[4]) << 8) | buffer[5]; + *gx = (((int16_t)buffer[8]) << 8) | buffer[9]; + *gy = (((int16_t)buffer[10]) << 8) | buffer[11]; + *gz = (((int16_t)buffer[12]) << 8) | buffer[13]; +} +/** Get 3-axis accelerometer readings. + * These registers store the most recent accelerometer measurements. + * Accelerometer measurements are written to these registers at the Sample Rate + * as defined in Register 25. + * + * The accelerometer measurement registers, along with the temperature + * measurement registers, gyroscope measurement registers, and external sensor + * data registers, are composed of two sets of registers: an internal register + * set and a user-facing read register set. + * + * The data within the accelerometer sensors' internal register set is always + * updated at the Sample Rate. Meanwhile, the user-facing read register set + * duplicates the internal register set's data values whenever the serial + * interface is idle. This guarantees that a burst read of sensor registers will + * read measurements from the same sampling instant. Note that if burst reads + * are not used, the user is responsible for ensuring a set of single byte reads + * correspond to a single sampling instant by checking the Data Ready interrupt. + * + * Each 16-bit accelerometer measurement has a full scale defined in ACCEL_FS + * (Register 28). For each full scale setting, the accelerometers' sensitivity + * per LSB in ACCEL_xOUT is shown in the table below: + * + *
+ * AFS_SEL | Full Scale Range | LSB Sensitivity
+ * --------+------------------+----------------
+ * 0       | +/- 2g           | 8192 LSB/mg
+ * 1       | +/- 4g           | 4096 LSB/mg
+ * 2       | +/- 8g           | 2048 LSB/mg
+ * 3       | +/- 16g          | 1024 LSB/mg
+ * 
+ * + * @param x 16-bit signed integer container for X-axis acceleration + * @param y 16-bit signed integer container for Y-axis acceleration + * @param z 16-bit signed integer container for Z-axis acceleration + * @see MPU6050_RA_GYRO_XOUT_H + */ +void MPU6050::getAcceleration(int16_t* x, int16_t* y, int16_t* z) { + I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_XOUT_H, 6, buffer); + *x = (((int16_t)buffer[0]) << 8) | buffer[1]; + *y = (((int16_t)buffer[2]) << 8) | buffer[3]; + *z = (((int16_t)buffer[4]) << 8) | buffer[5]; +} +/** Get X-axis accelerometer reading. + * @return X-axis acceleration measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_ACCEL_XOUT_H + */ +int16_t MPU6050::getAccelerationX() { + I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_XOUT_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +/** Get Y-axis accelerometer reading. + * @return Y-axis acceleration measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_ACCEL_YOUT_H + */ +int16_t MPU6050::getAccelerationY() { + I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_YOUT_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +/** Get Z-axis accelerometer reading. + * @return Z-axis acceleration measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_ACCEL_ZOUT_H + */ +int16_t MPU6050::getAccelerationZ() { + I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_ZOUT_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} + +// TEMP_OUT_* registers + +/** Get current internal temperature. + * @return Temperature reading in 16-bit 2's complement format + * @see MPU6050_RA_TEMP_OUT_H + */ +int16_t MPU6050::getTemperature() { + I2Cdev::readBytes(devAddr, MPU6050_RA_TEMP_OUT_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} + +// GYRO_*OUT_* registers + +/** Get 3-axis gyroscope readings. + * These gyroscope measurement registers, along with the accelerometer + * measurement registers, temperature measurement registers, and external sensor + * data registers, are composed of two sets of registers: an internal register + * set and a user-facing read register set. + * The data within the gyroscope sensors' internal register set is always + * updated at the Sample Rate. Meanwhile, the user-facing read register set + * duplicates the internal register set's data values whenever the serial + * interface is idle. This guarantees that a burst read of sensor registers will + * read measurements from the same sampling instant. Note that if burst reads + * are not used, the user is responsible for ensuring a set of single byte reads + * correspond to a single sampling instant by checking the Data Ready interrupt. + * + * Each 16-bit gyroscope measurement has a full scale defined in FS_SEL + * (Register 27). For each full scale setting, the gyroscopes' sensitivity per + * LSB in GYRO_xOUT is shown in the table below: + * + *
+ * FS_SEL | Full Scale Range   | LSB Sensitivity
+ * -------+--------------------+----------------
+ * 0      | +/- 250 degrees/s  | 131 LSB/deg/s
+ * 1      | +/- 500 degrees/s  | 65.5 LSB/deg/s
+ * 2      | +/- 1000 degrees/s | 32.8 LSB/deg/s
+ * 3      | +/- 2000 degrees/s | 16.4 LSB/deg/s
+ * 
+ * + * @param x 16-bit signed integer container for X-axis rotation + * @param y 16-bit signed integer container for Y-axis rotation + * @param z 16-bit signed integer container for Z-axis rotation + * @see getMotion6() + * @see MPU6050_RA_GYRO_XOUT_H + */ +void MPU6050::getRotation(int16_t* x, int16_t* y, int16_t* z) { + I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_XOUT_H, 6, buffer); + *x = (((int16_t)buffer[0]) << 8) | buffer[1]; + *y = (((int16_t)buffer[2]) << 8) | buffer[3]; + *z = (((int16_t)buffer[4]) << 8) | buffer[5]; +} +/** Get X-axis gyroscope reading. + * @return X-axis rotation measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_GYRO_XOUT_H + */ +int16_t MPU6050::getRotationX() { + I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_XOUT_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +/** Get Y-axis gyroscope reading. + * @return Y-axis rotation measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_GYRO_YOUT_H + */ +int16_t MPU6050::getRotationY() { + I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_YOUT_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +/** Get Z-axis gyroscope reading. + * @return Z-axis rotation measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_GYRO_ZOUT_H + */ +int16_t MPU6050::getRotationZ() { + I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_ZOUT_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} + +// EXT_SENS_DATA_* registers + +/** Read single byte from external sensor data register. + * These registers store data read from external sensors by the Slave 0, 1, 2, + * and 3 on the auxiliary I2C interface. Data read by Slave 4 is stored in + * I2C_SLV4_DI (Register 53). + * + * External sensor data is written to these registers at the Sample Rate as + * defined in Register 25. This access rate can be reduced by using the Slave + * Delay Enable registers (Register 103). + * + * External sensor data registers, along with the gyroscope measurement + * registers, accelerometer measurement registers, and temperature measurement + * registers, are composed of two sets of registers: an internal register set + * and a user-facing read register set. + * + * The data within the external sensors' internal register set is always updated + * at the Sample Rate (or the reduced access rate) whenever the serial interface + * is idle. This guarantees that a burst read of sensor registers will read + * measurements from the same sampling instant. Note that if burst reads are not + * used, the user is responsible for ensuring a set of single byte reads + * correspond to a single sampling instant by checking the Data Ready interrupt. + * + * Data is placed in these external sensor data registers according to + * I2C_SLV0_CTRL, I2C_SLV1_CTRL, I2C_SLV2_CTRL, and I2C_SLV3_CTRL (Registers 39, + * 42, 45, and 48). When more than zero bytes are read (I2C_SLVx_LEN > 0) from + * an enabled slave (I2C_SLVx_EN = 1), the slave is read at the Sample Rate (as + * defined in Register 25) or delayed rate (if specified in Register 52 and + * 103). During each Sample cycle, slave reads are performed in order of Slave + * number. If all slaves are enabled with more than zero bytes to be read, the + * order will be Slave 0, followed by Slave 1, Slave 2, and Slave 3. + * + * Each enabled slave will have EXT_SENS_DATA registers associated with it by + * number of bytes read (I2C_SLVx_LEN) in order of slave number, starting from + * EXT_SENS_DATA_00. Note that this means enabling or disabling a slave may + * change the higher numbered slaves' associated registers. Furthermore, if + * fewer total bytes are being read from the external sensors as a result of + * such a change, then the data remaining in the registers which no longer have + * an associated slave device (i.e. high numbered registers) will remain in + * these previously allocated registers unless reset. + * + * If the sum of the read lengths of all SLVx transactions exceed the number of + * available EXT_SENS_DATA registers, the excess bytes will be dropped. There + * are 24 EXT_SENS_DATA registers and hence the total read lengths between all + * the slaves cannot be greater than 24 or some bytes will be lost. + * + * Note: Slave 4's behavior is distinct from that of Slaves 0-3. For further + * information regarding the characteristics of Slave 4, please refer to + * Registers 49 to 53. + * + * EXAMPLE: + * Suppose that Slave 0 is enabled with 4 bytes to be read (I2C_SLV0_EN = 1 and + * I2C_SLV0_LEN = 4) while Slave 1 is enabled with 2 bytes to be read so that + * I2C_SLV1_EN = 1 and I2C_SLV1_LEN = 2. In such a situation, EXT_SENS_DATA _00 + * through _03 will be associated with Slave 0, while EXT_SENS_DATA _04 and 05 + * will be associated with Slave 1. If Slave 2 is enabled as well, registers + * starting from EXT_SENS_DATA_06 will be allocated to Slave 2. + * + * If Slave 2 is disabled while Slave 3 is enabled in this same situation, then + * registers starting from EXT_SENS_DATA_06 will be allocated to Slave 3 + * instead. + * + * REGISTER ALLOCATION FOR DYNAMIC DISABLE VS. NORMAL DISABLE: + * If a slave is disabled at any time, the space initially allocated to the + * slave in the EXT_SENS_DATA register, will remain associated with that slave. + * This is to avoid dynamic adjustment of the register allocation. + * + * The allocation of the EXT_SENS_DATA registers is recomputed only when (1) all + * slaves are disabled, or (2) the I2C_MST_RST bit is set (Register 106). + * + * This above is also true if one of the slaves gets NACKed and stops + * functioning. + * + * @param position Starting position (0-23) + * @return Byte read from register + */ +uint8_t MPU6050::getExternalSensorByte(int position) { + I2Cdev::readByte(devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, buffer); + return buffer[0]; +} +/** Read word (2 bytes) from external sensor data registers. + * @param position Starting position (0-21) + * @return Word read from register + * @see getExternalSensorByte() + */ +uint16_t MPU6050::getExternalSensorWord(int position) { + I2Cdev::readBytes(devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, 2, buffer); + return (((uint16_t)buffer[0]) << 8) | buffer[1]; +} +/** Read double word (4 bytes) from external sensor data registers. + * @param position Starting position (0-20) + * @return Double word read from registers + * @see getExternalSensorByte() + */ +uint32_t MPU6050::getExternalSensorDWord(int position) { + I2Cdev::readBytes(devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, 4, buffer); + return (((uint32_t)buffer[0]) << 24) | (((uint32_t)buffer[1]) << 16) | (((uint16_t)buffer[2]) << 8) | buffer[3]; +} + +// MOT_DETECT_STATUS register + +/** Get full motion detection status register content (all bits). + * @return Motion detection status byte + * @see MPU6050_RA_MOT_DETECT_STATUS + */ +uint8_t MPU6050::getMotionStatus() { + I2Cdev::readByte(devAddr, MPU6050_RA_MOT_DETECT_STATUS, buffer); + return buffer[0]; +} +/** Get X-axis negative motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_XNEG_BIT + */ +bool MPU6050::getXNegMotionDetected() { + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_XNEG_BIT, buffer); + return buffer[0]; +} +/** Get X-axis positive motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_XPOS_BIT + */ +bool MPU6050::getXPosMotionDetected() { + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_XPOS_BIT, buffer); + return buffer[0]; +} +/** Get Y-axis negative motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_YNEG_BIT + */ +bool MPU6050::getYNegMotionDetected() { + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_YNEG_BIT, buffer); + return buffer[0]; +} +/** Get Y-axis positive motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_YPOS_BIT + */ +bool MPU6050::getYPosMotionDetected() { + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_YPOS_BIT, buffer); + return buffer[0]; +} +/** Get Z-axis negative motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_ZNEG_BIT + */ +bool MPU6050::getZNegMotionDetected() { + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZNEG_BIT, buffer); + return buffer[0]; +} +/** Get Z-axis positive motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_ZPOS_BIT + */ +bool MPU6050::getZPosMotionDetected() { + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZPOS_BIT, buffer); + return buffer[0]; +} +/** Get zero motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_ZRMOT_BIT + */ +bool MPU6050::getZeroMotionDetected() { + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZRMOT_BIT, buffer); + return buffer[0]; +} + +// I2C_SLV*_DO register + +/** Write byte to Data Output container for specified slave. + * This register holds the output data written into Slave when Slave is set to + * write mode. For further information regarding Slave control, please + * refer to Registers 37 to 39 and immediately following. + * @param num Slave number (0-3) + * @param data Byte to write + * @see MPU6050_RA_I2C_SLV0_DO + */ +void MPU6050::setSlaveOutputByte(uint8_t num, uint8_t data) { + if (num > 3) return; + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV0_DO + num, data); +} + +// I2C_MST_DELAY_CTRL register + +/** Get external data shadow delay enabled status. + * This register is used to specify the timing of external sensor data + * shadowing. When DELAY_ES_SHADOW is set to 1, shadowing of external + * sensor data is delayed until all data has been received. + * @return Current external data shadow delay enabled status. + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT + */ +bool MPU6050::getExternalShadowDelayEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT, buffer); + return buffer[0]; +} +/** Set external data shadow delay enabled status. + * @param enabled New external data shadow delay enabled status. + * @see getExternalShadowDelayEnabled() + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT + */ +void MPU6050::setExternalShadowDelayEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT, enabled); +} +/** Get slave delay enabled status. + * When a particular slave delay is enabled, the rate of access for the that + * slave device is reduced. When a slave's access rate is decreased relative to + * the Sample Rate, the slave is accessed every: + * + * 1 / (1 + I2C_MST_DLY) Samples + * + * This base Sample Rate in turn is determined by SMPLRT_DIV (register * 25) + * and DLPF_CFG (register 26). + * + * For further information regarding I2C_MST_DLY, please refer to register 52. + * For further information regarding the Sample Rate, please refer to register 25. + * + * @param num Slave number (0-4) + * @return Current slave delay enabled status. + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT + */ +bool MPU6050::getSlaveDelayEnabled(uint8_t num) { + // MPU6050_DELAYCTRL_I2C_SLV4_DLY_EN_BIT is 4, SLV3 is 3, etc. + if (num > 4) return 0; + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, num, buffer); + return buffer[0]; +} +/** Set slave delay enabled status. + * @param num Slave number (0-4) + * @param enabled New slave delay enabled status. + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT + */ +void MPU6050::setSlaveDelayEnabled(uint8_t num, bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, num, enabled); +} + +// SIGNAL_PATH_RESET register + +/** Reset gyroscope signal path. + * The reset will revert the signal path analog to digital converters and + * filters to their power up configurations. + * @see MPU6050_RA_SIGNAL_PATH_RESET + * @see MPU6050_PATHRESET_GYRO_RESET_BIT + */ +void MPU6050::resetGyroscopePath() { + I2Cdev::writeBit(devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_GYRO_RESET_BIT, true); +} +/** Reset accelerometer signal path. + * The reset will revert the signal path analog to digital converters and + * filters to their power up configurations. + * @see MPU6050_RA_SIGNAL_PATH_RESET + * @see MPU6050_PATHRESET_ACCEL_RESET_BIT + */ +void MPU6050::resetAccelerometerPath() { + I2Cdev::writeBit(devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_ACCEL_RESET_BIT, true); +} +/** Reset temperature sensor signal path. + * The reset will revert the signal path analog to digital converters and + * filters to their power up configurations. + * @see MPU6050_RA_SIGNAL_PATH_RESET + * @see MPU6050_PATHRESET_TEMP_RESET_BIT + */ +void MPU6050::resetTemperaturePath() { + I2Cdev::writeBit(devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_TEMP_RESET_BIT, true); +} + +// MOT_DETECT_CTRL register + +/** Get accelerometer power-on delay. + * The accelerometer data path provides samples to the sensor registers, Motion + * detection, Zero Motion detection, and Free Fall detection modules. The + * signal path contains filters which must be flushed on wake-up with new + * samples before the detection modules begin operations. The default wake-up + * delay, of 4ms can be lengthened by up to 3ms. This additional delay is + * specified in ACCEL_ON_DELAY in units of 1 LSB = 1 ms. The user may select + * any value above zero unless instructed otherwise by InvenSense. Please refer + * to Section 8 of the MPU-6000/MPU-6050 Product Specification document for + * further information regarding the detection modules. + * @return Current accelerometer power-on delay + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_ACCEL_ON_DELAY_BIT + */ +uint8_t MPU6050::getAccelerometerPowerOnDelay() { + I2Cdev::readBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_ACCEL_ON_DELAY_BIT, MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH, buffer); + return buffer[0]; +} +/** Set accelerometer power-on delay. + * @param delay New accelerometer power-on delay (0-3) + * @see getAccelerometerPowerOnDelay() + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_ACCEL_ON_DELAY_BIT + */ +void MPU6050::setAccelerometerPowerOnDelay(uint8_t delay) { + I2Cdev::writeBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_ACCEL_ON_DELAY_BIT, MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH, delay); +} +/** Get Free Fall detection counter decrement configuration. + * Detection is registered by the Free Fall detection module after accelerometer + * measurements meet their respective threshold conditions over a specified + * number of samples. When the threshold conditions are met, the corresponding + * detection counter increments by 1. The user may control the rate at which the + * detection counter decrements when the threshold condition is not met by + * configuring FF_COUNT. The decrement rate can be set according to the + * following table: + * + *
+ * FF_COUNT | Counter Decrement
+ * ---------+------------------
+ * 0        | Reset
+ * 1        | 1
+ * 2        | 2
+ * 3        | 4
+ * 
+ * + * When FF_COUNT is configured to 0 (reset), any non-qualifying sample will + * reset the counter to 0. For further information on Free Fall detection, + * please refer to Registers 29 to 32. + * + * @return Current decrement configuration + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_FF_COUNT_BIT + */ +uint8_t MPU6050::getFreefallDetectionCounterDecrement() { + I2Cdev::readBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_FF_COUNT_BIT, MPU6050_DETECT_FF_COUNT_LENGTH, buffer); + return buffer[0]; +} +/** Set Free Fall detection counter decrement configuration. + * @param decrement New decrement configuration value + * @see getFreefallDetectionCounterDecrement() + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_FF_COUNT_BIT + */ +void MPU6050::setFreefallDetectionCounterDecrement(uint8_t decrement) { + I2Cdev::writeBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_FF_COUNT_BIT, MPU6050_DETECT_FF_COUNT_LENGTH, decrement); +} +/** Get Motion detection counter decrement configuration. + * Detection is registered by the Motion detection module after accelerometer + * measurements meet their respective threshold conditions over a specified + * number of samples. When the threshold conditions are met, the corresponding + * detection counter increments by 1. The user may control the rate at which the + * detection counter decrements when the threshold condition is not met by + * configuring MOT_COUNT. The decrement rate can be set according to the + * following table: + * + *
+ * MOT_COUNT | Counter Decrement
+ * ----------+------------------
+ * 0         | Reset
+ * 1         | 1
+ * 2         | 2
+ * 3         | 4
+ * 
+ * + * When MOT_COUNT is configured to 0 (reset), any non-qualifying sample will + * reset the counter to 0. For further information on Motion detection, + * please refer to Registers 29 to 32. + * + */ +uint8_t MPU6050::getMotionDetectionCounterDecrement() { + I2Cdev::readBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_MOT_COUNT_BIT, MPU6050_DETECT_MOT_COUNT_LENGTH, buffer); + return buffer[0]; +} +/** Set Motion detection counter decrement configuration. + * @param decrement New decrement configuration value + * @see getMotionDetectionCounterDecrement() + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_MOT_COUNT_BIT + */ +void MPU6050::setMotionDetectionCounterDecrement(uint8_t decrement) { + I2Cdev::writeBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_MOT_COUNT_BIT, MPU6050_DETECT_MOT_COUNT_LENGTH, decrement); +} + +// USER_CTRL register + +/** Get FIFO enabled status. + * When this bit is set to 0, the FIFO buffer is disabled. The FIFO buffer + * cannot be written to or read from while disabled. The FIFO buffer's state + * does not change unless the MPU-60X0 is power cycled. + * @return Current FIFO enabled status + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_FIFO_EN_BIT + */ +bool MPU6050::getFIFOEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set FIFO enabled status. + * @param enabled New FIFO enabled status + * @see getFIFOEnabled() + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_FIFO_EN_BIT + */ +void MPU6050::setFIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_EN_BIT, enabled); +} +/** Get I2C Master Mode enabled status. + * When this mode is enabled, the MPU-60X0 acts as the I2C Master to the + * external sensor slave devices on the auxiliary I2C bus. When this bit is + * cleared to 0, the auxiliary I2C bus lines (AUX_DA and AUX_CL) are logically + * driven by the primary I2C bus (SDA and SCL). This is a precondition to + * enabling Bypass Mode. For further information regarding Bypass Mode, please + * refer to Register 55. + * @return Current I2C Master Mode enabled status + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_I2C_MST_EN_BIT + */ +bool MPU6050::getI2CMasterModeEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_EN_BIT, buffer); + return buffer[0]; +} +/** Set I2C Master Mode enabled status. + * @param enabled New I2C Master Mode enabled status + * @see getI2CMasterModeEnabled() + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_I2C_MST_EN_BIT + */ +void MPU6050::setI2CMasterModeEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_EN_BIT, enabled); +} +/** Switch from I2C to SPI mode (MPU-6000 only) + * If this is set, the primary SPI interface will be enabled in place of the + * disabled primary I2C interface. + */ +void MPU6050::switchSPIEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_IF_DIS_BIT, enabled); +} +/** Reset the FIFO. + * This bit resets the FIFO buffer when set to 1 while FIFO_EN equals 0. This + * bit automatically clears to 0 after the reset has been triggered. + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_FIFO_RESET_BIT + */ +void MPU6050::resetFIFO() { + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_RESET_BIT, true); +} +/** Reset the I2C Master. + * This bit resets the I2C Master when set to 1 while I2C_MST_EN equals 0. + * This bit automatically clears to 0 after the reset has been triggered. + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_I2C_MST_RESET_BIT + */ +void MPU6050::resetI2CMaster() { + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_RESET_BIT, true); +} +/** Reset all sensor registers and signal paths. + * When set to 1, this bit resets the signal paths for all sensors (gyroscopes, + * accelerometers, and temperature sensor). This operation will also clear the + * sensor registers. This bit automatically clears to 0 after the reset has been + * triggered. + * + * When resetting only the signal path (and not the sensor registers), please + * use Register 104, SIGNAL_PATH_RESET. + * + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_SIG_COND_RESET_BIT + */ +void MPU6050::resetSensors() { + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_SIG_COND_RESET_BIT, true); +} + +// PWR_MGMT_1 register + +/** Trigger a full device reset. + * A small delay of ~50ms may be desirable after triggering a reset. + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_DEVICE_RESET_BIT + */ +void MPU6050::reset() { + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_DEVICE_RESET_BIT, true); +} +/** Get sleep mode status. + * Setting the SLEEP bit in the register puts the device into very low power + * sleep mode. In this mode, only the serial interface and internal registers + * remain active, allowing for a very low standby current. Clearing this bit + * puts the device back into normal mode. To save power, the individual standby + * selections for each of the gyros should be used if any gyro axis is not used + * by the application. + * @return Current sleep mode enabled status + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_SLEEP_BIT + */ +bool MPU6050::getSleepEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, buffer); + return buffer[0]; +} +/** Set sleep mode status. + * @param enabled New sleep mode enabled status + * @see getSleepEnabled() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_SLEEP_BIT + */ +void MPU6050::setSleepEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, enabled); +} +/** Get wake cycle enabled status. + * When this bit is set to 1 and SLEEP is disabled, the MPU-60X0 will cycle + * between sleep mode and waking up to take a single sample of data from active + * sensors at a rate determined by LP_WAKE_CTRL (register 108). + * @return Current sleep mode enabled status + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CYCLE_BIT + */ +bool MPU6050::getWakeCycleEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CYCLE_BIT, buffer); + return buffer[0]; +} +/** Set wake cycle enabled status. + * @param enabled New sleep mode enabled status + * @see getWakeCycleEnabled() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CYCLE_BIT + */ +void MPU6050::setWakeCycleEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CYCLE_BIT, enabled); +} +/** Get temperature sensor enabled status. + * Control the usage of the internal temperature sensor. + * + * Note: this register stores the *disabled* value, but for consistency with the + * rest of the code, the function is named and used with standard true/false + * values to indicate whether the sensor is enabled or disabled, respectively. + * + * @return Current temperature sensor enabled status + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_TEMP_DIS_BIT + */ +bool MPU6050::getTempSensorEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_TEMP_DIS_BIT, buffer); + return buffer[0] == 0; // 1 is actually disabled here +} +/** Set temperature sensor enabled status. + * Note: this register stores the *disabled* value, but for consistency with the + * rest of the code, the function is named and used with standard true/false + * values to indicate whether the sensor is enabled or disabled, respectively. + * + * @param enabled New temperature sensor enabled status + * @see getTempSensorEnabled() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_TEMP_DIS_BIT + */ +void MPU6050::setTempSensorEnabled(bool enabled) { + // 1 is actually disabled here + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_TEMP_DIS_BIT, !enabled); +} +/** Get clock source setting. + * @return Current clock source setting + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CLKSEL_BIT + * @see MPU6050_PWR1_CLKSEL_LENGTH + */ +uint8_t MPU6050::getClockSource() { + I2Cdev::readBits(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, buffer); + return buffer[0]; +} +/** Set clock source setting. + * An internal 8MHz oscillator, gyroscope based clock, or external sources can + * be selected as the MPU-60X0 clock source. When the internal 8 MHz oscillator + * or an external source is chosen as the clock source, the MPU-60X0 can operate + * in low power modes with the gyroscopes disabled. + * + * Upon power up, the MPU-60X0 clock source defaults to the internal oscillator. + * However, it is highly recommended that the device be configured to use one of + * the gyroscopes (or an external clock source) as the clock reference for + * improved stability. The clock source can be selected according to the following table: + * + *
+ * CLK_SEL | Clock Source
+ * --------+--------------------------------------
+ * 0       | Internal oscillator
+ * 1       | PLL with X Gyro reference
+ * 2       | PLL with Y Gyro reference
+ * 3       | PLL with Z Gyro reference
+ * 4       | PLL with external 32.768kHz reference
+ * 5       | PLL with external 19.2MHz reference
+ * 6       | Reserved
+ * 7       | Stops the clock and keeps the timing generator in reset
+ * 
+ * + * @param source New clock source setting + * @see getClockSource() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CLKSEL_BIT + * @see MPU6050_PWR1_CLKSEL_LENGTH + */ +void MPU6050::setClockSource(uint8_t source) { + I2Cdev::writeBits(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, source); +} + +// PWR_MGMT_2 register + +/** Get wake frequency in Accel-Only Low Power Mode. + * The MPU-60X0 can be put into Accerlerometer Only Low Power Mode by setting + * PWRSEL to 1 in the Power Management 1 register (Register 107). In this mode, + * the device will power off all devices except for the primary I2C interface, + * waking only the accelerometer at fixed intervals to take a single + * measurement. The frequency of wake-ups can be configured with LP_WAKE_CTRL + * as shown below: + * + *
+ * LP_WAKE_CTRL | Wake-up Frequency
+ * -------------+------------------
+ * 0            | 1.25 Hz
+ * 1            | 2.5 Hz
+ * 2            | 5 Hz
+ * 3            | 10 Hz
+ * 
+ * + * For further information regarding the MPU-60X0's power modes, please refer to + * Register 107. + * + * @return Current wake frequency + * @see MPU6050_RA_PWR_MGMT_2 + */ +uint8_t MPU6050::getWakeFrequency() { + I2Cdev::readBits(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_LP_WAKE_CTRL_BIT, MPU6050_PWR2_LP_WAKE_CTRL_LENGTH, buffer); + return buffer[0]; +} +/** Set wake frequency in Accel-Only Low Power Mode. + * @param frequency New wake frequency + * @see MPU6050_RA_PWR_MGMT_2 + */ +void MPU6050::setWakeFrequency(uint8_t frequency) { + I2Cdev::writeBits(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_LP_WAKE_CTRL_BIT, MPU6050_PWR2_LP_WAKE_CTRL_LENGTH, frequency); +} + +/** Get X-axis accelerometer standby enabled status. + * If enabled, the X-axis will not gather or report data (or use power). + * @return Current X-axis standby enabled status + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_XA_BIT + */ +bool MPU6050::getStandbyXAccelEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XA_BIT, buffer); + return buffer[0]; +} +/** Set X-axis accelerometer standby enabled status. + * @param New X-axis standby enabled status + * @see getStandbyXAccelEnabled() + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_XA_BIT + */ +void MPU6050::setStandbyXAccelEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XA_BIT, enabled); +} +/** Get Y-axis accelerometer standby enabled status. + * If enabled, the Y-axis will not gather or report data (or use power). + * @return Current Y-axis standby enabled status + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_YA_BIT + */ +bool MPU6050::getStandbyYAccelEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YA_BIT, buffer); + return buffer[0]; +} +/** Set Y-axis accelerometer standby enabled status. + * @param New Y-axis standby enabled status + * @see getStandbyYAccelEnabled() + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_YA_BIT + */ +void MPU6050::setStandbyYAccelEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YA_BIT, enabled); +} +/** Get Z-axis accelerometer standby enabled status. + * If enabled, the Z-axis will not gather or report data (or use power). + * @return Current Z-axis standby enabled status + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_ZA_BIT + */ +bool MPU6050::getStandbyZAccelEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZA_BIT, buffer); + return buffer[0]; +} +/** Set Z-axis accelerometer standby enabled status. + * @param New Z-axis standby enabled status + * @see getStandbyZAccelEnabled() + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_ZA_BIT + */ +void MPU6050::setStandbyZAccelEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZA_BIT, enabled); +} +/** Get X-axis gyroscope standby enabled status. + * If enabled, the X-axis will not gather or report data (or use power). + * @return Current X-axis standby enabled status + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_XG_BIT + */ +bool MPU6050::getStandbyXGyroEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XG_BIT, buffer); + return buffer[0]; +} +/** Set X-axis gyroscope standby enabled status. + * @param New X-axis standby enabled status + * @see getStandbyXGyroEnabled() + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_XG_BIT + */ +void MPU6050::setStandbyXGyroEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XG_BIT, enabled); +} +/** Get Y-axis gyroscope standby enabled status. + * If enabled, the Y-axis will not gather or report data (or use power). + * @return Current Y-axis standby enabled status + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_YG_BIT + */ +bool MPU6050::getStandbyYGyroEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YG_BIT, buffer); + return buffer[0]; +} +/** Set Y-axis gyroscope standby enabled status. + * @param New Y-axis standby enabled status + * @see getStandbyYGyroEnabled() + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_YG_BIT + */ +void MPU6050::setStandbyYGyroEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YG_BIT, enabled); +} +/** Get Z-axis gyroscope standby enabled status. + * If enabled, the Z-axis will not gather or report data (or use power). + * @return Current Z-axis standby enabled status + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_ZG_BIT + */ +bool MPU6050::getStandbyZGyroEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZG_BIT, buffer); + return buffer[0]; +} +/** Set Z-axis gyroscope standby enabled status. + * @param New Z-axis standby enabled status + * @see getStandbyZGyroEnabled() + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_ZG_BIT + */ +void MPU6050::setStandbyZGyroEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZG_BIT, enabled); +} + +// FIFO_COUNT* registers + +/** Get current FIFO buffer size. + * This value indicates the number of bytes stored in the FIFO buffer. This + * number is in turn the number of bytes that can be read from the FIFO buffer + * and it is directly proportional to the number of samples available given the + * set of sensor data bound to be stored in the FIFO (register 35 and 36). + * @return Current FIFO buffer size + */ +uint16_t MPU6050::getFIFOCount() { + I2Cdev::readBytes(devAddr, MPU6050_RA_FIFO_COUNTH, 2, buffer); + return (((uint16_t)buffer[0]) << 8) | buffer[1]; +} + +// FIFO_R_W register + +/** Get byte from FIFO buffer. + * This register is used to read and write data from the FIFO buffer. Data is + * written to the FIFO in order of register number (from lowest to highest). If + * all the FIFO enable flags (see below) are enabled and all External Sensor + * Data registers (Registers 73 to 96) are associated with a Slave device, the + * contents of registers 59 through 96 will be written in order at the Sample + * Rate. + * + * The contents of the sensor data registers (Registers 59 to 96) are written + * into the FIFO buffer when their corresponding FIFO enable flags are set to 1 + * in FIFO_EN (Register 35). An additional flag for the sensor data registers + * associated with I2C Slave 3 can be found in I2C_MST_CTRL (Register 36). + * + * If the FIFO buffer has overflowed, the status bit FIFO_OFLOW_INT is + * automatically set to 1. This bit is located in INT_STATUS (Register 58). + * When the FIFO buffer has overflowed, the oldest data will be lost and new + * data will be written to the FIFO. + * + * If the FIFO buffer is empty, reading this register will return the last byte + * that was previously read from the FIFO until new data is available. The user + * should check FIFO_COUNT to ensure that the FIFO buffer is not read when + * empty. + * + * @return Byte from FIFO buffer + */ +uint8_t MPU6050::getFIFOByte() { + I2Cdev::readByte(devAddr, MPU6050_RA_FIFO_R_W, buffer); + return buffer[0]; +} +void MPU6050::getFIFOBytes(uint8_t *data, uint8_t length) { + if(length > 0){ + I2Cdev::readBytes(devAddr, MPU6050_RA_FIFO_R_W, length, data); + } else { + *data = 0; + } +} +/** Write byte to FIFO buffer. + * @see getFIFOByte() + * @see MPU6050_RA_FIFO_R_W + */ +void MPU6050::setFIFOByte(uint8_t data) { + I2Cdev::writeByte(devAddr, MPU6050_RA_FIFO_R_W, data); +} + +// WHO_AM_I register + +/** Get Device ID. + * This register is used to verify the identity of the device (0b110100, 0x34). + * @return Device ID (6 bits only! should be 0x34) + * @see MPU6050_RA_WHO_AM_I + * @see MPU6050_WHO_AM_I_BIT + * @see MPU6050_WHO_AM_I_LENGTH + */ +uint8_t MPU6050::getDeviceID() { + I2Cdev::readBits(devAddr, MPU6050_RA_WHO_AM_I, MPU6050_WHO_AM_I_BIT, MPU6050_WHO_AM_I_LENGTH, buffer); + return buffer[0]; +} +/** Set Device ID. + * Write a new ID into the WHO_AM_I register (no idea why this should ever be + * necessary though). + * @param id New device ID to set. + * @see getDeviceID() + * @see MPU6050_RA_WHO_AM_I + * @see MPU6050_WHO_AM_I_BIT + * @see MPU6050_WHO_AM_I_LENGTH + */ +void MPU6050::setDeviceID(uint8_t id) { + I2Cdev::writeBits(devAddr, MPU6050_RA_WHO_AM_I, MPU6050_WHO_AM_I_BIT, MPU6050_WHO_AM_I_LENGTH, id); +} + +// ======== UNDOCUMENTED/DMP REGISTERS/METHODS ======== + +// XG_OFFS_TC register + +uint8_t MPU6050::getOTPBankValid() { + I2Cdev::readBit(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OTP_BNK_VLD_BIT, buffer); + return buffer[0]; +} +void MPU6050::setOTPBankValid(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OTP_BNK_VLD_BIT, enabled); +} +int8_t MPU6050::getXGyroOffsetTC() { + I2Cdev::readBits(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, buffer); + return buffer[0]; +} +void MPU6050::setXGyroOffsetTC(int8_t offset) { + I2Cdev::writeBits(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset); +} + +// YG_OFFS_TC register + +int8_t MPU6050::getYGyroOffsetTC() { + I2Cdev::readBits(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, buffer); + return buffer[0]; +} +void MPU6050::setYGyroOffsetTC(int8_t offset) { + I2Cdev::writeBits(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset); +} + +// ZG_OFFS_TC register + +int8_t MPU6050::getZGyroOffsetTC() { + I2Cdev::readBits(devAddr, MPU6050_RA_ZG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, buffer); + return buffer[0]; +} +void MPU6050::setZGyroOffsetTC(int8_t offset) { + I2Cdev::writeBits(devAddr, MPU6050_RA_ZG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset); +} + +// X_FINE_GAIN register + +int8_t MPU6050::getXFineGain() { + I2Cdev::readByte(devAddr, MPU6050_RA_X_FINE_GAIN, buffer); + return buffer[0]; +} +void MPU6050::setXFineGain(int8_t gain) { + I2Cdev::writeByte(devAddr, MPU6050_RA_X_FINE_GAIN, gain); +} + +// Y_FINE_GAIN register + +int8_t MPU6050::getYFineGain() { + I2Cdev::readByte(devAddr, MPU6050_RA_Y_FINE_GAIN, buffer); + return buffer[0]; +} +void MPU6050::setYFineGain(int8_t gain) { + I2Cdev::writeByte(devAddr, MPU6050_RA_Y_FINE_GAIN, gain); +} + +// Z_FINE_GAIN register + +int8_t MPU6050::getZFineGain() { + I2Cdev::readByte(devAddr, MPU6050_RA_Z_FINE_GAIN, buffer); + return buffer[0]; +} +void MPU6050::setZFineGain(int8_t gain) { + I2Cdev::writeByte(devAddr, MPU6050_RA_Z_FINE_GAIN, gain); +} + +// XA_OFFS_* registers + +int16_t MPU6050::getXAccelOffset() { + I2Cdev::readBytes(devAddr, MPU6050_RA_XA_OFFS_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +void MPU6050::setXAccelOffset(int16_t offset) { + I2Cdev::writeWord(devAddr, MPU6050_RA_XA_OFFS_H, offset); +} + +// YA_OFFS_* register + +int16_t MPU6050::getYAccelOffset() { + I2Cdev::readBytes(devAddr, MPU6050_RA_YA_OFFS_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +void MPU6050::setYAccelOffset(int16_t offset) { + I2Cdev::writeWord(devAddr, MPU6050_RA_YA_OFFS_H, offset); +} + +// ZA_OFFS_* register + +int16_t MPU6050::getZAccelOffset() { + I2Cdev::readBytes(devAddr, MPU6050_RA_ZA_OFFS_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +void MPU6050::setZAccelOffset(int16_t offset) { + I2Cdev::writeWord(devAddr, MPU6050_RA_ZA_OFFS_H, offset); +} + +// XG_OFFS_USR* registers + +int16_t MPU6050::getXGyroOffset() { + I2Cdev::readBytes(devAddr, MPU6050_RA_XG_OFFS_USRH, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +void MPU6050::setXGyroOffset(int16_t offset) { + I2Cdev::writeWord(devAddr, MPU6050_RA_XG_OFFS_USRH, offset); +} + +// YG_OFFS_USR* register + +int16_t MPU6050::getYGyroOffset() { + I2Cdev::readBytes(devAddr, MPU6050_RA_YG_OFFS_USRH, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +void MPU6050::setYGyroOffset(int16_t offset) { + I2Cdev::writeWord(devAddr, MPU6050_RA_YG_OFFS_USRH, offset); +} + +// ZG_OFFS_USR* register + +int16_t MPU6050::getZGyroOffset() { + I2Cdev::readBytes(devAddr, MPU6050_RA_ZG_OFFS_USRH, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +void MPU6050::setZGyroOffset(int16_t offset) { + I2Cdev::writeWord(devAddr, MPU6050_RA_ZG_OFFS_USRH, offset); +} + +// INT_ENABLE register (DMP functions) + +bool MPU6050::getIntPLLReadyEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, buffer); + return buffer[0]; +} +void MPU6050::setIntPLLReadyEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, enabled); +} +bool MPU6050::getIntDMPEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DMP_INT_BIT, buffer); + return buffer[0]; +} +void MPU6050::setIntDMPEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DMP_INT_BIT, enabled); +} + +// DMP_INT_STATUS + +bool MPU6050::getDMPInt5Status() { + I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_5_BIT, buffer); + return buffer[0]; +} +bool MPU6050::getDMPInt4Status() { + I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_4_BIT, buffer); + return buffer[0]; +} +bool MPU6050::getDMPInt3Status() { + I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_3_BIT, buffer); + return buffer[0]; +} +bool MPU6050::getDMPInt2Status() { + I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_2_BIT, buffer); + return buffer[0]; +} +bool MPU6050::getDMPInt1Status() { + I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_1_BIT, buffer); + return buffer[0]; +} +bool MPU6050::getDMPInt0Status() { + I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_0_BIT, buffer); + return buffer[0]; +} + +// INT_STATUS register (DMP functions) + +bool MPU6050::getIntPLLReadyStatus() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, buffer); + return buffer[0]; +} +bool MPU6050::getIntDMPStatus() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_DMP_INT_BIT, buffer); + return buffer[0]; +} + +// USER_CTRL register (DMP functions) + +bool MPU6050::getDMPEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_EN_BIT, buffer); + return buffer[0]; +} +void MPU6050::setDMPEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_EN_BIT, enabled); +} +void MPU6050::resetDMP() { + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_RESET_BIT, true); +} + +// BANK_SEL register + +void MPU6050::setMemoryBank(uint8_t bank, bool prefetchEnabled, bool userBank) { + bank &= 0x1F; + if (userBank) bank |= 0x20; + if (prefetchEnabled) bank |= 0x40; + I2Cdev::writeByte(devAddr, MPU6050_RA_BANK_SEL, bank); +} + +// MEM_START_ADDR register + +void MPU6050::setMemoryStartAddress(uint8_t address) { + I2Cdev::writeByte(devAddr, MPU6050_RA_MEM_START_ADDR, address); +} + +// MEM_R_W register + +uint8_t MPU6050::readMemoryByte() { + I2Cdev::readByte(devAddr, MPU6050_RA_MEM_R_W, buffer); + return buffer[0]; +} +void MPU6050::writeMemoryByte(uint8_t data) { + I2Cdev::writeByte(devAddr, MPU6050_RA_MEM_R_W, data); +} +void MPU6050::readMemoryBlock(uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address) { + setMemoryBank(bank); + setMemoryStartAddress(address); + uint8_t chunkSize; + for (uint16_t i = 0; i < dataSize;) { + // determine correct chunk size according to bank position and data size + chunkSize = MPU6050_DMP_MEMORY_CHUNK_SIZE; + + // make sure we don't go past the data size + if (i + chunkSize > dataSize) chunkSize = dataSize - i; + + // make sure this chunk doesn't go past the bank boundary (256 bytes) + if (chunkSize > 256 - address) chunkSize = 256 - address; + + // read the chunk of data as specified + I2Cdev::readBytes(devAddr, MPU6050_RA_MEM_R_W, chunkSize, data + i); + + // increase byte index by [chunkSize] + i += chunkSize; + + // uint8_t automatically wraps to 0 at 256 + address += chunkSize; + + // if we aren't done, update bank (if necessary) and address + if (i < dataSize) { + if (address == 0) bank++; + setMemoryBank(bank); + setMemoryStartAddress(address); + } + } +} +bool MPU6050::writeMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address, bool verify, bool useProgMem) { + setMemoryBank(bank); + setMemoryStartAddress(address); + uint8_t chunkSize; + uint8_t *verifyBuffer=0; + uint8_t *progBuffer=0; + uint16_t i; + uint8_t j; + if (verify) verifyBuffer = (uint8_t *)malloc(MPU6050_DMP_MEMORY_CHUNK_SIZE); + if (useProgMem) progBuffer = (uint8_t *)malloc(MPU6050_DMP_MEMORY_CHUNK_SIZE); + for (i = 0; i < dataSize;) { + // determine correct chunk size according to bank position and data size + chunkSize = MPU6050_DMP_MEMORY_CHUNK_SIZE; + + // make sure we don't go past the data size + if (i + chunkSize > dataSize) chunkSize = dataSize - i; + + // make sure this chunk doesn't go past the bank boundary (256 bytes) + if (chunkSize > 256 - address) chunkSize = 256 - address; + + if (useProgMem) { + // write the chunk of data as specified + for (j = 0; j < chunkSize; j++) progBuffer[j] = pgm_read_byte(data + i + j); + } else { + // write the chunk of data as specified + progBuffer = (uint8_t *)data + i; + } + + I2Cdev::writeBytes(devAddr, MPU6050_RA_MEM_R_W, chunkSize, progBuffer); + + // verify data if needed + if (verify && verifyBuffer) { + printf("VERIFY\n"); + setMemoryBank(bank); + setMemoryStartAddress(address); + I2Cdev::readBytes(devAddr, MPU6050_RA_MEM_R_W, chunkSize, verifyBuffer); + if (memcmp(progBuffer, verifyBuffer, chunkSize) != 0) { + printf("Block write verification error, bank \n"); + /*Serial.print("Block write verification error, bank ");*/ + printf("bank %d", bank); + printf(", address "); + printf("%d", address); + printf("!\nExpected:"); + for (j = 0; j < chunkSize; j++) { + printf("%#04x", progBuffer[j]); + } + printf("\nReceived:"); + for (uint8_t j = 0; j < chunkSize; j++) { + printf("%#04x", verifyBuffer[i + j]); + } + printf("\n"); + //free(verifyBuffer); + //if (useProgMem) free(progBuffer); + //return false; // uh oh. + } + } + + // increase byte index by [chunkSize] + i += chunkSize; + + // uint8_t automatically wraps to 0 at 256 + address += chunkSize; + + // if we aren't done, update bank (if necessary) and address + if (i < dataSize) { + if (address == 0) bank++; + setMemoryBank(bank); + setMemoryStartAddress(address); + } + } + if (verify) free(verifyBuffer); + if (useProgMem) free(progBuffer); + return true; +} +bool MPU6050::writeProgMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address, bool verify) { + return writeMemoryBlock(data, dataSize, bank, address, verify, false); +} +bool MPU6050::writeDMPConfigurationSet(const uint8_t *data, uint16_t dataSize, bool useProgMem) { + uint8_t *progBuffer = 0; + uint8_t success, special; + uint16_t i, j; + if (useProgMem) { + progBuffer = (uint8_t *)malloc(8); // assume 8-byte blocks, realloc later if necessary + } + + // config set data is a long string of blocks with the following structure: + // [bank] [offset] [length] [byte[0], byte[1], ..., byte[length]] + uint8_t bank, offset, length; + for (i = 0; i < dataSize;) { + if (useProgMem) { + bank = pgm_read_byte(data + i++); + offset = pgm_read_byte(data + i++); + length = pgm_read_byte(data + i++); + } else { + bank = data[i++]; + offset = data[i++]; + length = data[i++]; + } + + // write data or perform special action + if (length > 0) { + // regular block of data to write + /*Serial.print("Writing config block to bank "); + Serial.print(bank); + Serial.print(", offset "); + Serial.print(offset); + Serial.print(", length="); + Serial.println(length);*/ + if (useProgMem) { + if (sizeof(progBuffer) < length) progBuffer = (uint8_t *)realloc(progBuffer, length); + for (j = 0; j < length; j++) progBuffer[j] = pgm_read_byte(data + i + j); + } else { + progBuffer = (uint8_t *)data + i; + } + success = writeMemoryBlock(progBuffer, length, bank, offset, true); + i += length; + } else { + // special instruction + // NOTE: this kind of behavior (what and when to do certain things) + // is totally undocumented. This code is in here based on observed + // behavior only, and exactly why (or even whether) it has to be here + // is anybody's guess for now. + if (useProgMem) { + special = pgm_read_byte(data + i++); + } else { + special = data[i++]; + } + /*Serial.print("Special command code "); + Serial.print(special, HEX); + Serial.println(" found...");*/ + if (special == 0x01) { + // enable DMP-related interrupts + + //setIntZeroMotionEnabled(true); + //setIntFIFOBufferOverflowEnabled(true); + //setIntDMPEnabled(true); + I2Cdev::writeByte(devAddr, MPU6050_RA_INT_ENABLE, 0x32); // single operation + + success = true; + } else { + // unknown special command + success = false; + } + } + + if (!success) { + if (useProgMem) free(progBuffer); + return false; // uh oh + } + } + if (useProgMem) free(progBuffer); + return true; +} +bool MPU6050::writeProgDMPConfigurationSet(const uint8_t *data, uint16_t dataSize) { + return writeDMPConfigurationSet(data, dataSize, true); +} + +// DMP_CFG_1 register + +uint8_t MPU6050::getDMPConfig1() { + I2Cdev::readByte(devAddr, MPU6050_RA_DMP_CFG_1, buffer); + return buffer[0]; +} +void MPU6050::setDMPConfig1(uint8_t config) { + I2Cdev::writeByte(devAddr, MPU6050_RA_DMP_CFG_1, config); +} + +// DMP_CFG_2 register + +uint8_t MPU6050::getDMPConfig2() { + I2Cdev::readByte(devAddr, MPU6050_RA_DMP_CFG_2, buffer); + return buffer[0]; +} +void MPU6050::setDMPConfig2(uint8_t config) { + I2Cdev::writeByte(devAddr, MPU6050_RA_DMP_CFG_2, config); +} diff --git a/ESP32_ESP-IDF/components/MPU6050/MPU6050.h b/ESP32_ESP-IDF/components/MPU6050/MPU6050.h new file mode 100644 index 00000000..bb5fef40 --- /dev/null +++ b/ESP32_ESP-IDF/components/MPU6050/MPU6050.h @@ -0,0 +1,1034 @@ +// I2Cdev library collection - MPU6050 I2C device class +// Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00) +// 10/3/2011 by Jeff Rowberg +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// ... - ongoing debug release + +// NOTE: THIS IS ONLY A PARIAL RELEASE. THIS DEVICE CLASS IS CURRENTLY UNDERGOING ACTIVE +// DEVELOPMENT AND IS STILL MISSING SOME IMPORTANT FEATURES. PLEASE KEEP THIS IN MIND IF +// YOU DECIDE TO USE THIS PARTICULAR CODE FOR ANYTHING. + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2012 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#ifndef _MPU6050_H_ +#define _MPU6050_H_ + +#include "helper_3dmath.h" +#include "I2Cdev.h" + +// supporting link: http://forum.arduino.cc/index.php?&topic=143444.msg1079517#msg1079517 +// also: http://forum.arduino.cc/index.php?&topic=141571.msg1062899#msg1062899s + +#undef pgm_read_byte +#define pgm_read_byte(addr) (*(const unsigned char *)(addr)) + +//#define PROGMEM /* empty */ +//#define pgm_read_byte(x) (*(x)) +//#define pgm_read_word(x) (*(x)) +//#define pgm_read_float(x) (*(x)) +//#define PSTR(STR) STR + +#define MPU6050_INCLUDE_DMP_MOTIONAPPS20 +#define MPU6050_ADDRESS_AD0_LOW 0x68 // address pin low (GND), default for InvenSense evaluation board +#define MPU6050_ADDRESS_AD0_HIGH 0x69 // address pin high (VCC) +#define MPU6050_DEFAULT_ADDRESS MPU6050_ADDRESS_AD0_LOW + +#define MPU6050_RA_XG_OFFS_TC 0x00 //[7] PWR_MODE, [6:1] XG_OFFS_TC, [0] OTP_BNK_VLD +#define MPU6050_RA_YG_OFFS_TC 0x01 //[7] PWR_MODE, [6:1] YG_OFFS_TC, [0] OTP_BNK_VLD +#define MPU6050_RA_ZG_OFFS_TC 0x02 //[7] PWR_MODE, [6:1] ZG_OFFS_TC, [0] OTP_BNK_VLD +#define MPU6050_RA_X_FINE_GAIN 0x03 //[7:0] X_FINE_GAIN +#define MPU6050_RA_Y_FINE_GAIN 0x04 //[7:0] Y_FINE_GAIN +#define MPU6050_RA_Z_FINE_GAIN 0x05 //[7:0] Z_FINE_GAIN +#define MPU6050_RA_XA_OFFS_H 0x06 //[15:0] XA_OFFS +#define MPU6050_RA_XA_OFFS_L_TC 0x07 +#define MPU6050_RA_YA_OFFS_H 0x08 //[15:0] YA_OFFS +#define MPU6050_RA_YA_OFFS_L_TC 0x09 +#define MPU6050_RA_ZA_OFFS_H 0x0A //[15:0] ZA_OFFS +#define MPU6050_RA_ZA_OFFS_L_TC 0x0B +#define MPU6050_RA_SELF_TEST_X 0x0D //[7:5] XA_TEST[4-2], [4:0] XG_TEST[4-0] +#define MPU6050_RA_SELF_TEST_Y 0x0E //[7:5] YA_TEST[4-2], [4:0] YG_TEST[4-0] +#define MPU6050_RA_SELF_TEST_Z 0x0F //[7:5] ZA_TEST[4-2], [4:0] ZG_TEST[4-0] +#define MPU6050_RA_SELF_TEST_A 0x10 //[5:4] XA_TEST[1-0], [3:2] YA_TEST[1-0], [1:0] ZA_TEST[1-0] +#define MPU6050_RA_XG_OFFS_USRH 0x13 //[15:0] XG_OFFS_USR +#define MPU6050_RA_XG_OFFS_USRL 0x14 +#define MPU6050_RA_YG_OFFS_USRH 0x15 //[15:0] YG_OFFS_USR +#define MPU6050_RA_YG_OFFS_USRL 0x16 +#define MPU6050_RA_ZG_OFFS_USRH 0x17 //[15:0] ZG_OFFS_USR +#define MPU6050_RA_ZG_OFFS_USRL 0x18 +#define MPU6050_RA_SMPLRT_DIV 0x19 +#define MPU6050_RA_CONFIG 0x1A +#define MPU6050_RA_GYRO_CONFIG 0x1B +#define MPU6050_RA_ACCEL_CONFIG 0x1C +#define MPU6050_RA_FF_THR 0x1D +#define MPU6050_RA_FF_DUR 0x1E +#define MPU6050_RA_MOT_THR 0x1F +#define MPU6050_RA_MOT_DUR 0x20 +#define MPU6050_RA_ZRMOT_THR 0x21 +#define MPU6050_RA_ZRMOT_DUR 0x22 +#define MPU6050_RA_FIFO_EN 0x23 +#define MPU6050_RA_I2C_MST_CTRL 0x24 +#define MPU6050_RA_I2C_SLV0_ADDR 0x25 +#define MPU6050_RA_I2C_SLV0_REG 0x26 +#define MPU6050_RA_I2C_SLV0_CTRL 0x27 +#define MPU6050_RA_I2C_SLV1_ADDR 0x28 +#define MPU6050_RA_I2C_SLV1_REG 0x29 +#define MPU6050_RA_I2C_SLV1_CTRL 0x2A +#define MPU6050_RA_I2C_SLV2_ADDR 0x2B +#define MPU6050_RA_I2C_SLV2_REG 0x2C +#define MPU6050_RA_I2C_SLV2_CTRL 0x2D +#define MPU6050_RA_I2C_SLV3_ADDR 0x2E +#define MPU6050_RA_I2C_SLV3_REG 0x2F +#define MPU6050_RA_I2C_SLV3_CTRL 0x30 +#define MPU6050_RA_I2C_SLV4_ADDR 0x31 +#define MPU6050_RA_I2C_SLV4_REG 0x32 +#define MPU6050_RA_I2C_SLV4_DO 0x33 +#define MPU6050_RA_I2C_SLV4_CTRL 0x34 +#define MPU6050_RA_I2C_SLV4_DI 0x35 +#define MPU6050_RA_I2C_MST_STATUS 0x36 +#define MPU6050_RA_INT_PIN_CFG 0x37 +#define MPU6050_RA_INT_ENABLE 0x38 +#define MPU6050_RA_DMP_INT_STATUS 0x39 +#define MPU6050_RA_INT_STATUS 0x3A +#define MPU6050_RA_ACCEL_XOUT_H 0x3B +#define MPU6050_RA_ACCEL_XOUT_L 0x3C +#define MPU6050_RA_ACCEL_YOUT_H 0x3D +#define MPU6050_RA_ACCEL_YOUT_L 0x3E +#define MPU6050_RA_ACCEL_ZOUT_H 0x3F +#define MPU6050_RA_ACCEL_ZOUT_L 0x40 +#define MPU6050_RA_TEMP_OUT_H 0x41 +#define MPU6050_RA_TEMP_OUT_L 0x42 +#define MPU6050_RA_GYRO_XOUT_H 0x43 +#define MPU6050_RA_GYRO_XOUT_L 0x44 +#define MPU6050_RA_GYRO_YOUT_H 0x45 +#define MPU6050_RA_GYRO_YOUT_L 0x46 +#define MPU6050_RA_GYRO_ZOUT_H 0x47 +#define MPU6050_RA_GYRO_ZOUT_L 0x48 +#define MPU6050_RA_EXT_SENS_DATA_00 0x49 +#define MPU6050_RA_EXT_SENS_DATA_01 0x4A +#define MPU6050_RA_EXT_SENS_DATA_02 0x4B +#define MPU6050_RA_EXT_SENS_DATA_03 0x4C +#define MPU6050_RA_EXT_SENS_DATA_04 0x4D +#define MPU6050_RA_EXT_SENS_DATA_05 0x4E +#define MPU6050_RA_EXT_SENS_DATA_06 0x4F +#define MPU6050_RA_EXT_SENS_DATA_07 0x50 +#define MPU6050_RA_EXT_SENS_DATA_08 0x51 +#define MPU6050_RA_EXT_SENS_DATA_09 0x52 +#define MPU6050_RA_EXT_SENS_DATA_10 0x53 +#define MPU6050_RA_EXT_SENS_DATA_11 0x54 +#define MPU6050_RA_EXT_SENS_DATA_12 0x55 +#define MPU6050_RA_EXT_SENS_DATA_13 0x56 +#define MPU6050_RA_EXT_SENS_DATA_14 0x57 +#define MPU6050_RA_EXT_SENS_DATA_15 0x58 +#define MPU6050_RA_EXT_SENS_DATA_16 0x59 +#define MPU6050_RA_EXT_SENS_DATA_17 0x5A +#define MPU6050_RA_EXT_SENS_DATA_18 0x5B +#define MPU6050_RA_EXT_SENS_DATA_19 0x5C +#define MPU6050_RA_EXT_SENS_DATA_20 0x5D +#define MPU6050_RA_EXT_SENS_DATA_21 0x5E +#define MPU6050_RA_EXT_SENS_DATA_22 0x5F +#define MPU6050_RA_EXT_SENS_DATA_23 0x60 +#define MPU6050_RA_MOT_DETECT_STATUS 0x61 +#define MPU6050_RA_I2C_SLV0_DO 0x63 +#define MPU6050_RA_I2C_SLV1_DO 0x64 +#define MPU6050_RA_I2C_SLV2_DO 0x65 +#define MPU6050_RA_I2C_SLV3_DO 0x66 +#define MPU6050_RA_I2C_MST_DELAY_CTRL 0x67 +#define MPU6050_RA_SIGNAL_PATH_RESET 0x68 +#define MPU6050_RA_MOT_DETECT_CTRL 0x69 +#define MPU6050_RA_USER_CTRL 0x6A +#define MPU6050_RA_PWR_MGMT_1 0x6B +#define MPU6050_RA_PWR_MGMT_2 0x6C +#define MPU6050_RA_BANK_SEL 0x6D +#define MPU6050_RA_MEM_START_ADDR 0x6E +#define MPU6050_RA_MEM_R_W 0x6F +#define MPU6050_RA_DMP_CFG_1 0x70 +#define MPU6050_RA_DMP_CFG_2 0x71 +#define MPU6050_RA_FIFO_COUNTH 0x72 +#define MPU6050_RA_FIFO_COUNTL 0x73 +#define MPU6050_RA_FIFO_R_W 0x74 +#define MPU6050_RA_WHO_AM_I 0x75 + +#define MPU6050_SELF_TEST_XA_1_BIT 0x07 +#define MPU6050_SELF_TEST_XA_1_LENGTH 0x03 +#define MPU6050_SELF_TEST_XA_2_BIT 0x05 +#define MPU6050_SELF_TEST_XA_2_LENGTH 0x02 +#define MPU6050_SELF_TEST_YA_1_BIT 0x07 +#define MPU6050_SELF_TEST_YA_1_LENGTH 0x03 +#define MPU6050_SELF_TEST_YA_2_BIT 0x03 +#define MPU6050_SELF_TEST_YA_2_LENGTH 0x02 +#define MPU6050_SELF_TEST_ZA_1_BIT 0x07 +#define MPU6050_SELF_TEST_ZA_1_LENGTH 0x03 +#define MPU6050_SELF_TEST_ZA_2_BIT 0x01 +#define MPU6050_SELF_TEST_ZA_2_LENGTH 0x02 + +#define MPU6050_SELF_TEST_XG_1_BIT 0x04 +#define MPU6050_SELF_TEST_XG_1_LENGTH 0x05 +#define MPU6050_SELF_TEST_YG_1_BIT 0x04 +#define MPU6050_SELF_TEST_YG_1_LENGTH 0x05 +#define MPU6050_SELF_TEST_ZG_1_BIT 0x04 +#define MPU6050_SELF_TEST_ZG_1_LENGTH 0x05 + +#define MPU6050_TC_PWR_MODE_BIT 7 +#define MPU6050_TC_OFFSET_BIT 6 +#define MPU6050_TC_OFFSET_LENGTH 6 +#define MPU6050_TC_OTP_BNK_VLD_BIT 0 + +#define MPU6050_VDDIO_LEVEL_VLOGIC 0 +#define MPU6050_VDDIO_LEVEL_VDD 1 + +#define MPU6050_CFG_EXT_SYNC_SET_BIT 5 +#define MPU6050_CFG_EXT_SYNC_SET_LENGTH 3 +#define MPU6050_CFG_DLPF_CFG_BIT 2 +#define MPU6050_CFG_DLPF_CFG_LENGTH 3 + +#define MPU6050_EXT_SYNC_DISABLED 0x0 +#define MPU6050_EXT_SYNC_TEMP_OUT_L 0x1 +#define MPU6050_EXT_SYNC_GYRO_XOUT_L 0x2 +#define MPU6050_EXT_SYNC_GYRO_YOUT_L 0x3 +#define MPU6050_EXT_SYNC_GYRO_ZOUT_L 0x4 +#define MPU6050_EXT_SYNC_ACCEL_XOUT_L 0x5 +#define MPU6050_EXT_SYNC_ACCEL_YOUT_L 0x6 +#define MPU6050_EXT_SYNC_ACCEL_ZOUT_L 0x7 + +#define MPU6050_DLPF_BW_256 0x00 +#define MPU6050_DLPF_BW_188 0x01 +#define MPU6050_DLPF_BW_98 0x02 +#define MPU6050_DLPF_BW_42 0x03 +#define MPU6050_DLPF_BW_20 0x04 +#define MPU6050_DLPF_BW_10 0x05 +#define MPU6050_DLPF_BW_5 0x06 + +#define MPU6050_GCONFIG_FS_SEL_BIT 4 +#define MPU6050_GCONFIG_FS_SEL_LENGTH 2 + +#define MPU6050_GYRO_FS_250 0x00 +#define MPU6050_GYRO_FS_500 0x01 +#define MPU6050_GYRO_FS_1000 0x02 +#define MPU6050_GYRO_FS_2000 0x03 + +#define MPU6050_ACONFIG_XA_ST_BIT 7 +#define MPU6050_ACONFIG_YA_ST_BIT 6 +#define MPU6050_ACONFIG_ZA_ST_BIT 5 +#define MPU6050_ACONFIG_AFS_SEL_BIT 4 +#define MPU6050_ACONFIG_AFS_SEL_LENGTH 2 +#define MPU6050_ACONFIG_ACCEL_HPF_BIT 2 +#define MPU6050_ACONFIG_ACCEL_HPF_LENGTH 3 + +#define MPU6050_ACCEL_FS_2 0x00 +#define MPU6050_ACCEL_FS_4 0x01 +#define MPU6050_ACCEL_FS_8 0x02 +#define MPU6050_ACCEL_FS_16 0x03 + +#define MPU6050_DHPF_RESET 0x00 +#define MPU6050_DHPF_5 0x01 +#define MPU6050_DHPF_2P5 0x02 +#define MPU6050_DHPF_1P25 0x03 +#define MPU6050_DHPF_0P63 0x04 +#define MPU6050_DHPF_HOLD 0x07 + +#define MPU6050_TEMP_FIFO_EN_BIT 7 +#define MPU6050_XG_FIFO_EN_BIT 6 +#define MPU6050_YG_FIFO_EN_BIT 5 +#define MPU6050_ZG_FIFO_EN_BIT 4 +#define MPU6050_ACCEL_FIFO_EN_BIT 3 +#define MPU6050_SLV2_FIFO_EN_BIT 2 +#define MPU6050_SLV1_FIFO_EN_BIT 1 +#define MPU6050_SLV0_FIFO_EN_BIT 0 + +#define MPU6050_MULT_MST_EN_BIT 7 +#define MPU6050_WAIT_FOR_ES_BIT 6 +#define MPU6050_SLV_3_FIFO_EN_BIT 5 +#define MPU6050_I2C_MST_P_NSR_BIT 4 +#define MPU6050_I2C_MST_CLK_BIT 3 +#define MPU6050_I2C_MST_CLK_LENGTH 4 + +#define MPU6050_CLOCK_DIV_348 0x0 +#define MPU6050_CLOCK_DIV_333 0x1 +#define MPU6050_CLOCK_DIV_320 0x2 +#define MPU6050_CLOCK_DIV_308 0x3 +#define MPU6050_CLOCK_DIV_296 0x4 +#define MPU6050_CLOCK_DIV_286 0x5 +#define MPU6050_CLOCK_DIV_276 0x6 +#define MPU6050_CLOCK_DIV_267 0x7 +#define MPU6050_CLOCK_DIV_258 0x8 +#define MPU6050_CLOCK_DIV_500 0x9 +#define MPU6050_CLOCK_DIV_471 0xA +#define MPU6050_CLOCK_DIV_444 0xB +#define MPU6050_CLOCK_DIV_421 0xC +#define MPU6050_CLOCK_DIV_400 0xD +#define MPU6050_CLOCK_DIV_381 0xE +#define MPU6050_CLOCK_DIV_364 0xF + +#define MPU6050_I2C_SLV_RW_BIT 7 +#define MPU6050_I2C_SLV_ADDR_BIT 6 +#define MPU6050_I2C_SLV_ADDR_LENGTH 7 +#define MPU6050_I2C_SLV_EN_BIT 7 +#define MPU6050_I2C_SLV_BYTE_SW_BIT 6 +#define MPU6050_I2C_SLV_REG_DIS_BIT 5 +#define MPU6050_I2C_SLV_GRP_BIT 4 +#define MPU6050_I2C_SLV_LEN_BIT 3 +#define MPU6050_I2C_SLV_LEN_LENGTH 4 + +#define MPU6050_I2C_SLV4_RW_BIT 7 +#define MPU6050_I2C_SLV4_ADDR_BIT 6 +#define MPU6050_I2C_SLV4_ADDR_LENGTH 7 +#define MPU6050_I2C_SLV4_EN_BIT 7 +#define MPU6050_I2C_SLV4_INT_EN_BIT 6 +#define MPU6050_I2C_SLV4_REG_DIS_BIT 5 +#define MPU6050_I2C_SLV4_MST_DLY_BIT 4 +#define MPU6050_I2C_SLV4_MST_DLY_LENGTH 5 + +#define MPU6050_MST_PASS_THROUGH_BIT 7 +#define MPU6050_MST_I2C_SLV4_DONE_BIT 6 +#define MPU6050_MST_I2C_LOST_ARB_BIT 5 +#define MPU6050_MST_I2C_SLV4_NACK_BIT 4 +#define MPU6050_MST_I2C_SLV3_NACK_BIT 3 +#define MPU6050_MST_I2C_SLV2_NACK_BIT 2 +#define MPU6050_MST_I2C_SLV1_NACK_BIT 1 +#define MPU6050_MST_I2C_SLV0_NACK_BIT 0 + +#define MPU6050_INTCFG_INT_LEVEL_BIT 7 +#define MPU6050_INTCFG_INT_OPEN_BIT 6 +#define MPU6050_INTCFG_LATCH_INT_EN_BIT 5 +#define MPU6050_INTCFG_INT_RD_CLEAR_BIT 4 +#define MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT 3 +#define MPU6050_INTCFG_FSYNC_INT_EN_BIT 2 +#define MPU6050_INTCFG_I2C_BYPASS_EN_BIT 1 +#define MPU6050_INTCFG_CLKOUT_EN_BIT 0 + +#define MPU6050_INTMODE_ACTIVEHIGH 0x00 +#define MPU6050_INTMODE_ACTIVELOW 0x01 + +#define MPU6050_INTDRV_PUSHPULL 0x00 +#define MPU6050_INTDRV_OPENDRAIN 0x01 + +#define MPU6050_INTLATCH_50USPULSE 0x00 +#define MPU6050_INTLATCH_WAITCLEAR 0x01 + +#define MPU6050_INTCLEAR_STATUSREAD 0x00 +#define MPU6050_INTCLEAR_ANYREAD 0x01 + +#define MPU6050_INTERRUPT_FF_BIT 7 +#define MPU6050_INTERRUPT_MOT_BIT 6 +#define MPU6050_INTERRUPT_ZMOT_BIT 5 +#define MPU6050_INTERRUPT_FIFO_OFLOW_BIT 4 +#define MPU6050_INTERRUPT_I2C_MST_INT_BIT 3 +#define MPU6050_INTERRUPT_PLL_RDY_INT_BIT 2 +#define MPU6050_INTERRUPT_DMP_INT_BIT 1 +#define MPU6050_INTERRUPT_DATA_RDY_BIT 0 + +// TODO: figure out what these actually do +// UMPL source code is not very obivous +#define MPU6050_DMPINT_5_BIT 5 +#define MPU6050_DMPINT_4_BIT 4 +#define MPU6050_DMPINT_3_BIT 3 +#define MPU6050_DMPINT_2_BIT 2 +#define MPU6050_DMPINT_1_BIT 1 +#define MPU6050_DMPINT_0_BIT 0 + +#define MPU6050_MOTION_MOT_XNEG_BIT 7 +#define MPU6050_MOTION_MOT_XPOS_BIT 6 +#define MPU6050_MOTION_MOT_YNEG_BIT 5 +#define MPU6050_MOTION_MOT_YPOS_BIT 4 +#define MPU6050_MOTION_MOT_ZNEG_BIT 3 +#define MPU6050_MOTION_MOT_ZPOS_BIT 2 +#define MPU6050_MOTION_MOT_ZRMOT_BIT 0 + +#define MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT 7 +#define MPU6050_DELAYCTRL_I2C_SLV4_DLY_EN_BIT 4 +#define MPU6050_DELAYCTRL_I2C_SLV3_DLY_EN_BIT 3 +#define MPU6050_DELAYCTRL_I2C_SLV2_DLY_EN_BIT 2 +#define MPU6050_DELAYCTRL_I2C_SLV1_DLY_EN_BIT 1 +#define MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT 0 + +#define MPU6050_PATHRESET_GYRO_RESET_BIT 2 +#define MPU6050_PATHRESET_ACCEL_RESET_BIT 1 +#define MPU6050_PATHRESET_TEMP_RESET_BIT 0 + +#define MPU6050_DETECT_ACCEL_ON_DELAY_BIT 5 +#define MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH 2 +#define MPU6050_DETECT_FF_COUNT_BIT 3 +#define MPU6050_DETECT_FF_COUNT_LENGTH 2 +#define MPU6050_DETECT_MOT_COUNT_BIT 1 +#define MPU6050_DETECT_MOT_COUNT_LENGTH 2 + +#define MPU6050_DETECT_DECREMENT_RESET 0x0 +#define MPU6050_DETECT_DECREMENT_1 0x1 +#define MPU6050_DETECT_DECREMENT_2 0x2 +#define MPU6050_DETECT_DECREMENT_4 0x3 + +#define MPU6050_USERCTRL_DMP_EN_BIT 7 +#define MPU6050_USERCTRL_FIFO_EN_BIT 6 +#define MPU6050_USERCTRL_I2C_MST_EN_BIT 5 +#define MPU6050_USERCTRL_I2C_IF_DIS_BIT 4 +#define MPU6050_USERCTRL_DMP_RESET_BIT 3 +#define MPU6050_USERCTRL_FIFO_RESET_BIT 2 +#define MPU6050_USERCTRL_I2C_MST_RESET_BIT 1 +#define MPU6050_USERCTRL_SIG_COND_RESET_BIT 0 + +#define MPU6050_PWR1_DEVICE_RESET_BIT 7 +#define MPU6050_PWR1_SLEEP_BIT 6 +#define MPU6050_PWR1_CYCLE_BIT 5 +#define MPU6050_PWR1_TEMP_DIS_BIT 3 +#define MPU6050_PWR1_CLKSEL_BIT 2 +#define MPU6050_PWR1_CLKSEL_LENGTH 3 + +#define MPU6050_CLOCK_INTERNAL 0x00 +#define MPU6050_CLOCK_PLL_XGYRO 0x01 +#define MPU6050_CLOCK_PLL_YGYRO 0x02 +#define MPU6050_CLOCK_PLL_ZGYRO 0x03 +#define MPU6050_CLOCK_PLL_EXT32K 0x04 +#define MPU6050_CLOCK_PLL_EXT19M 0x05 +#define MPU6050_CLOCK_KEEP_RESET 0x07 + +#define MPU6050_PWR2_LP_WAKE_CTRL_BIT 7 +#define MPU6050_PWR2_LP_WAKE_CTRL_LENGTH 2 +#define MPU6050_PWR2_STBY_XA_BIT 5 +#define MPU6050_PWR2_STBY_YA_BIT 4 +#define MPU6050_PWR2_STBY_ZA_BIT 3 +#define MPU6050_PWR2_STBY_XG_BIT 2 +#define MPU6050_PWR2_STBY_YG_BIT 1 +#define MPU6050_PWR2_STBY_ZG_BIT 0 + +#define MPU6050_WAKE_FREQ_1P25 0x0 +#define MPU6050_WAKE_FREQ_2P5 0x1 +#define MPU6050_WAKE_FREQ_5 0x2 +#define MPU6050_WAKE_FREQ_10 0x3 + +#define MPU6050_BANKSEL_PRFTCH_EN_BIT 6 +#define MPU6050_BANKSEL_CFG_USER_BANK_BIT 5 +#define MPU6050_BANKSEL_MEM_SEL_BIT 4 +#define MPU6050_BANKSEL_MEM_SEL_LENGTH 5 + +#define MPU6050_WHO_AM_I_BIT 6 +#define MPU6050_WHO_AM_I_LENGTH 6 + +#define MPU6050_DMP_MEMORY_BANKS 8 +#define MPU6050_DMP_MEMORY_BANK_SIZE 256 +#define MPU6050_DMP_MEMORY_CHUNK_SIZE 16 + +// note: DMP code memory blocks defined at end of header file + +class MPU6050 { + public: + MPU6050(); + MPU6050(uint8_t address); + + void ReadRegister(uint8_t reg, uint8_t *data, uint8_t len); + + void initialize(); + bool testConnection(); + + // AUX_VDDIO register + uint8_t getAuxVDDIOLevel(); + void setAuxVDDIOLevel(uint8_t level); + + // SMPLRT_DIV register + uint8_t getRate(); + void setRate(uint8_t rate); + + // CONFIG register + uint8_t getExternalFrameSync(); + void setExternalFrameSync(uint8_t sync); + uint8_t getDLPFMode(); + void setDLPFMode(uint8_t bandwidth); + + // GYRO_CONFIG register + uint8_t getFullScaleGyroRange(); + void setFullScaleGyroRange(uint8_t range); + + // SELF_TEST registers + uint8_t getAccelXSelfTestFactoryTrim(); + uint8_t getAccelYSelfTestFactoryTrim(); + uint8_t getAccelZSelfTestFactoryTrim(); + + uint8_t getGyroXSelfTestFactoryTrim(); + uint8_t getGyroYSelfTestFactoryTrim(); + uint8_t getGyroZSelfTestFactoryTrim(); + + // ACCEL_CONFIG register + bool getAccelXSelfTest(); + void setAccelXSelfTest(bool enabled); + bool getAccelYSelfTest(); + void setAccelYSelfTest(bool enabled); + bool getAccelZSelfTest(); + void setAccelZSelfTest(bool enabled); + uint8_t getFullScaleAccelRange(); + void setFullScaleAccelRange(uint8_t range); + uint8_t getDHPFMode(); + void setDHPFMode(uint8_t mode); + + // FF_THR register + uint8_t getFreefallDetectionThreshold(); + void setFreefallDetectionThreshold(uint8_t threshold); + + // FF_DUR register + uint8_t getFreefallDetectionDuration(); + void setFreefallDetectionDuration(uint8_t duration); + + // MOT_THR register + uint8_t getMotionDetectionThreshold(); + void setMotionDetectionThreshold(uint8_t threshold); + + // MOT_DUR register + uint8_t getMotionDetectionDuration(); + void setMotionDetectionDuration(uint8_t duration); + + // ZRMOT_THR register + uint8_t getZeroMotionDetectionThreshold(); + void setZeroMotionDetectionThreshold(uint8_t threshold); + + // ZRMOT_DUR register + uint8_t getZeroMotionDetectionDuration(); + void setZeroMotionDetectionDuration(uint8_t duration); + + // FIFO_EN register + bool getTempFIFOEnabled(); + void setTempFIFOEnabled(bool enabled); + bool getXGyroFIFOEnabled(); + void setXGyroFIFOEnabled(bool enabled); + bool getYGyroFIFOEnabled(); + void setYGyroFIFOEnabled(bool enabled); + bool getZGyroFIFOEnabled(); + void setZGyroFIFOEnabled(bool enabled); + bool getAccelFIFOEnabled(); + void setAccelFIFOEnabled(bool enabled); + bool getSlave2FIFOEnabled(); + void setSlave2FIFOEnabled(bool enabled); + bool getSlave1FIFOEnabled(); + void setSlave1FIFOEnabled(bool enabled); + bool getSlave0FIFOEnabled(); + void setSlave0FIFOEnabled(bool enabled); + + // I2C_MST_CTRL register + bool getMultiMasterEnabled(); + void setMultiMasterEnabled(bool enabled); + bool getWaitForExternalSensorEnabled(); + void setWaitForExternalSensorEnabled(bool enabled); + bool getSlave3FIFOEnabled(); + void setSlave3FIFOEnabled(bool enabled); + bool getSlaveReadWriteTransitionEnabled(); + void setSlaveReadWriteTransitionEnabled(bool enabled); + uint8_t getMasterClockSpeed(); + void setMasterClockSpeed(uint8_t speed); + + // I2C_SLV* registers (Slave 0-3) + uint8_t getSlaveAddress(uint8_t num); + void setSlaveAddress(uint8_t num, uint8_t address); + uint8_t getSlaveRegister(uint8_t num); + void setSlaveRegister(uint8_t num, uint8_t reg); + bool getSlaveEnabled(uint8_t num); + void setSlaveEnabled(uint8_t num, bool enabled); + bool getSlaveWordByteSwap(uint8_t num); + void setSlaveWordByteSwap(uint8_t num, bool enabled); + bool getSlaveWriteMode(uint8_t num); + void setSlaveWriteMode(uint8_t num, bool mode); + bool getSlaveWordGroupOffset(uint8_t num); + void setSlaveWordGroupOffset(uint8_t num, bool enabled); + uint8_t getSlaveDataLength(uint8_t num); + void setSlaveDataLength(uint8_t num, uint8_t length); + + // I2C_SLV* registers (Slave 4) + uint8_t getSlave4Address(); + void setSlave4Address(uint8_t address); + uint8_t getSlave4Register(); + void setSlave4Register(uint8_t reg); + void setSlave4OutputByte(uint8_t data); + bool getSlave4Enabled(); + void setSlave4Enabled(bool enabled); + bool getSlave4InterruptEnabled(); + void setSlave4InterruptEnabled(bool enabled); + bool getSlave4WriteMode(); + void setSlave4WriteMode(bool mode); + uint8_t getSlave4MasterDelay(); + void setSlave4MasterDelay(uint8_t delay); + uint8_t getSlate4InputByte(); + + // I2C_MST_STATUS register + bool getPassthroughStatus(); + bool getSlave4IsDone(); + bool getLostArbitration(); + bool getSlave4Nack(); + bool getSlave3Nack(); + bool getSlave2Nack(); + bool getSlave1Nack(); + bool getSlave0Nack(); + + // INT_PIN_CFG register + bool getInterruptMode(); + void setInterruptMode(bool mode); + bool getInterruptDrive(); + void setInterruptDrive(bool drive); + bool getInterruptLatch(); + void setInterruptLatch(bool latch); + bool getInterruptLatchClear(); + void setInterruptLatchClear(bool clear); + bool getFSyncInterruptLevel(); + void setFSyncInterruptLevel(bool level); + bool getFSyncInterruptEnabled(); + void setFSyncInterruptEnabled(bool enabled); + bool getI2CBypassEnabled(); + void setI2CBypassEnabled(bool enabled); + bool getClockOutputEnabled(); + void setClockOutputEnabled(bool enabled); + + // INT_ENABLE register + uint8_t getIntEnabled(); + void setIntEnabled(uint8_t enabled); + bool getIntFreefallEnabled(); + void setIntFreefallEnabled(bool enabled); + bool getIntMotionEnabled(); + void setIntMotionEnabled(bool enabled); + bool getIntZeroMotionEnabled(); + void setIntZeroMotionEnabled(bool enabled); + bool getIntFIFOBufferOverflowEnabled(); + void setIntFIFOBufferOverflowEnabled(bool enabled); + bool getIntI2CMasterEnabled(); + void setIntI2CMasterEnabled(bool enabled); + bool getIntDataReadyEnabled(); + void setIntDataReadyEnabled(bool enabled); + + // INT_STATUS register + uint8_t getIntStatus(); + bool getIntFreefallStatus(); + bool getIntMotionStatus(); + bool getIntZeroMotionStatus(); + bool getIntFIFOBufferOverflowStatus(); + bool getIntI2CMasterStatus(); + bool getIntDataReadyStatus(); + + // ACCEL_*OUT_* registers + void getMotion9(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz, int16_t* mx, int16_t* my, int16_t* mz); + void getMotion6(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz); + void getAcceleration(int16_t* x, int16_t* y, int16_t* z); + int16_t getAccelerationX(); + int16_t getAccelerationY(); + int16_t getAccelerationZ(); + + // TEMP_OUT_* registers + int16_t getTemperature(); + + // GYRO_*OUT_* registers + void getRotation(int16_t* x, int16_t* y, int16_t* z); + int16_t getRotationX(); + int16_t getRotationY(); + int16_t getRotationZ(); + + // EXT_SENS_DATA_* registers + uint8_t getExternalSensorByte(int position); + uint16_t getExternalSensorWord(int position); + uint32_t getExternalSensorDWord(int position); + + // MOT_DETECT_STATUS register + uint8_t getMotionStatus(); + bool getXNegMotionDetected(); + bool getXPosMotionDetected(); + bool getYNegMotionDetected(); + bool getYPosMotionDetected(); + bool getZNegMotionDetected(); + bool getZPosMotionDetected(); + bool getZeroMotionDetected(); + + // I2C_SLV*_DO register + void setSlaveOutputByte(uint8_t num, uint8_t data); + + // I2C_MST_DELAY_CTRL register + bool getExternalShadowDelayEnabled(); + void setExternalShadowDelayEnabled(bool enabled); + bool getSlaveDelayEnabled(uint8_t num); + void setSlaveDelayEnabled(uint8_t num, bool enabled); + + // SIGNAL_PATH_RESET register + void resetGyroscopePath(); + void resetAccelerometerPath(); + void resetTemperaturePath(); + + // MOT_DETECT_CTRL register + uint8_t getAccelerometerPowerOnDelay(); + void setAccelerometerPowerOnDelay(uint8_t delay); + uint8_t getFreefallDetectionCounterDecrement(); + void setFreefallDetectionCounterDecrement(uint8_t decrement); + uint8_t getMotionDetectionCounterDecrement(); + void setMotionDetectionCounterDecrement(uint8_t decrement); + + // USER_CTRL register + bool getFIFOEnabled(); + void setFIFOEnabled(bool enabled); + bool getI2CMasterModeEnabled(); + void setI2CMasterModeEnabled(bool enabled); + void switchSPIEnabled(bool enabled); + void resetFIFO(); + void resetI2CMaster(); + void resetSensors(); + + // PWR_MGMT_1 register + void reset(); + bool getSleepEnabled(); + void setSleepEnabled(bool enabled); + bool getWakeCycleEnabled(); + void setWakeCycleEnabled(bool enabled); + bool getTempSensorEnabled(); + void setTempSensorEnabled(bool enabled); + uint8_t getClockSource(); + void setClockSource(uint8_t source); + + // PWR_MGMT_2 register + uint8_t getWakeFrequency(); + void setWakeFrequency(uint8_t frequency); + bool getStandbyXAccelEnabled(); + void setStandbyXAccelEnabled(bool enabled); + bool getStandbyYAccelEnabled(); + void setStandbyYAccelEnabled(bool enabled); + bool getStandbyZAccelEnabled(); + void setStandbyZAccelEnabled(bool enabled); + bool getStandbyXGyroEnabled(); + void setStandbyXGyroEnabled(bool enabled); + bool getStandbyYGyroEnabled(); + void setStandbyYGyroEnabled(bool enabled); + bool getStandbyZGyroEnabled(); + void setStandbyZGyroEnabled(bool enabled); + + // FIFO_COUNT_* registers + uint16_t getFIFOCount(); + + // FIFO_R_W register + uint8_t getFIFOByte(); + void setFIFOByte(uint8_t data); + void getFIFOBytes(uint8_t *data, uint8_t length); + + // WHO_AM_I register + uint8_t getDeviceID(); + void setDeviceID(uint8_t id); + + // ======== UNDOCUMENTED/DMP REGISTERS/METHODS ======== + + // XG_OFFS_TC register + uint8_t getOTPBankValid(); + void setOTPBankValid(bool enabled); + int8_t getXGyroOffsetTC(); + void setXGyroOffsetTC(int8_t offset); + + // YG_OFFS_TC register + int8_t getYGyroOffsetTC(); + void setYGyroOffsetTC(int8_t offset); + + // ZG_OFFS_TC register + int8_t getZGyroOffsetTC(); + void setZGyroOffsetTC(int8_t offset); + + // X_FINE_GAIN register + int8_t getXFineGain(); + void setXFineGain(int8_t gain); + + // Y_FINE_GAIN register + int8_t getYFineGain(); + void setYFineGain(int8_t gain); + + // Z_FINE_GAIN register + int8_t getZFineGain(); + void setZFineGain(int8_t gain); + + // XA_OFFS_* registers + int16_t getXAccelOffset(); + void setXAccelOffset(int16_t offset); + + // YA_OFFS_* register + int16_t getYAccelOffset(); + void setYAccelOffset(int16_t offset); + + // ZA_OFFS_* register + int16_t getZAccelOffset(); + void setZAccelOffset(int16_t offset); + + // XG_OFFS_USR* registers + int16_t getXGyroOffset(); + void setXGyroOffset(int16_t offset); + + // YG_OFFS_USR* register + int16_t getYGyroOffset(); + void setYGyroOffset(int16_t offset); + + // ZG_OFFS_USR* register + int16_t getZGyroOffset(); + void setZGyroOffset(int16_t offset); + + // INT_ENABLE register (DMP functions) + bool getIntPLLReadyEnabled(); + void setIntPLLReadyEnabled(bool enabled); + bool getIntDMPEnabled(); + void setIntDMPEnabled(bool enabled); + + // DMP_INT_STATUS + bool getDMPInt5Status(); + bool getDMPInt4Status(); + bool getDMPInt3Status(); + bool getDMPInt2Status(); + bool getDMPInt1Status(); + bool getDMPInt0Status(); + + // INT_STATUS register (DMP functions) + bool getIntPLLReadyStatus(); + bool getIntDMPStatus(); + + // USER_CTRL register (DMP functions) + bool getDMPEnabled(); + void setDMPEnabled(bool enabled); + void resetDMP(); + + // BANK_SEL register + void setMemoryBank(uint8_t bank, bool prefetchEnabled=false, bool userBank=false); + + // MEM_START_ADDR register + void setMemoryStartAddress(uint8_t address); + + // MEM_R_W register + uint8_t readMemoryByte(); + void writeMemoryByte(uint8_t data); + void readMemoryBlock(uint8_t *data, uint16_t dataSize, uint8_t bank=0, uint8_t address=0); + bool writeMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank=0, uint8_t address=0, bool verify=true, bool useProgMem=false); + bool writeProgMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank=0, uint8_t address=0, bool verify=true); + + bool writeDMPConfigurationSet(const uint8_t *data, uint16_t dataSize, bool useProgMem=false); + bool writeProgDMPConfigurationSet(const uint8_t *data, uint16_t dataSize); + + // DMP_CFG_1 register + uint8_t getDMPConfig1(); + void setDMPConfig1(uint8_t config); + + // DMP_CFG_2 register + uint8_t getDMPConfig2(); + void setDMPConfig2(uint8_t config); + + // special methods for MotionApps 2.0 implementation + #ifdef MPU6050_INCLUDE_DMP_MOTIONAPPS20 + uint8_t *dmpPacketBuffer; + uint16_t dmpPacketSize; + + uint8_t dmpInitialize(); + bool dmpPacketAvailable(); + + uint8_t dmpSetFIFORate(uint8_t fifoRate); + uint8_t dmpGetFIFORate(); + uint8_t dmpGetSampleStepSizeMS(); + uint8_t dmpGetSampleFrequency(); + int32_t dmpDecodeTemperature(int8_t tempReg); + + // Register callbacks after a packet of FIFO data is processed + //uint8_t dmpRegisterFIFORateProcess(inv_obj_func func, int16_t priority); + //uint8_t dmpUnregisterFIFORateProcess(inv_obj_func func); + uint8_t dmpRunFIFORateProcesses(); + + // Setup FIFO for various output + uint8_t dmpSendQuaternion(uint_fast16_t accuracy); + uint8_t dmpSendGyro(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendAccel(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendLinearAccel(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendLinearAccelInWorld(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendControlData(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendSensorData(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendExternalSensorData(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendGravity(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendPacketNumber(uint_fast16_t accuracy); + uint8_t dmpSendQuantizedAccel(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendEIS(uint_fast16_t elements, uint_fast16_t accuracy); + + // Get Fixed Point data from FIFO + uint8_t dmpGetAccel(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetAccel(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetAccel(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetQuaternion(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetQuaternion(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetQuaternion(Quaternion *q, const uint8_t* packet=0); + uint8_t dmpGet6AxisQuaternion(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGet6AxisQuaternion(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGet6AxisQuaternion(Quaternion *q, const uint8_t* packet=0); + uint8_t dmpGetRelativeQuaternion(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetRelativeQuaternion(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetRelativeQuaternion(Quaternion *data, const uint8_t* packet=0); + uint8_t dmpGetGyro(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyro(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyro(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpSetLinearAccelFilterCoefficient(float coef); + uint8_t dmpGetLinearAccel(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetLinearAccel(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetLinearAccel(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetLinearAccel(VectorInt16 *v, VectorInt16 *vRaw, VectorFloat *gravity); + uint8_t dmpGetLinearAccelInWorld(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetLinearAccelInWorld(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetLinearAccelInWorld(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Quaternion *q); + uint8_t dmpGetGyroAndAccelSensor(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyroAndAccelSensor(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyroAndAccelSensor(VectorInt16 *g, VectorInt16 *a, const uint8_t* packet=0); + uint8_t dmpGetGyroSensor(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyroSensor(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyroSensor(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetControlData(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetTemperature(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetGravity(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetGravity(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetGravity(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetGravity(VectorFloat *v, Quaternion *q); + uint8_t dmpGetUnquantizedAccel(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetUnquantizedAccel(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetUnquantizedAccel(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetQuantizedAccel(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetQuantizedAccel(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetQuantizedAccel(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetExternalSensorData(int32_t *data, uint16_t size, const uint8_t* packet=0); + uint8_t dmpGetEIS(int32_t *data, const uint8_t* packet=0); + + uint8_t dmpGetEuler(float *data, Quaternion *q); + uint8_t dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity); + + // Get Floating Point data from FIFO + uint8_t dmpGetAccelFloat(float *data, const uint8_t* packet=0); + uint8_t dmpGetQuaternionFloat(float *data, const uint8_t* packet=0); + + uint8_t dmpProcessFIFOPacket(const unsigned char *dmpData); + uint8_t dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *processed=NULL); + + uint8_t dmpSetFIFOProcessedCallback(void (*func) (void)); + + uint8_t dmpInitFIFOParam(); + uint8_t dmpCloseFIFO(); + uint8_t dmpSetGyroDataSource(uint8_t source); + uint8_t dmpDecodeQuantizedAccel(); + uint32_t dmpGetGyroSumOfSquare(); + uint32_t dmpGetAccelSumOfSquare(); + void dmpOverrideQuaternion(long *q); + uint16_t dmpGetFIFOPacketSize(); + #endif + + // special methods for MotionApps 4.1 implementation + #ifdef MPU6050_INCLUDE_DMP_MOTIONAPPS41 + uint8_t *dmpPacketBuffer; + uint16_t dmpPacketSize; + + uint8_t dmpInitialize(); + bool dmpPacketAvailable(); + + uint8_t dmpSetFIFORate(uint8_t fifoRate); + uint8_t dmpGetFIFORate(); + uint8_t dmpGetSampleStepSizeMS(); + uint8_t dmpGetSampleFrequency(); + int32_t dmpDecodeTemperature(int8_t tempReg); + + // Register callbacks after a packet of FIFO data is processed + //uint8_t dmpRegisterFIFORateProcess(inv_obj_func func, int16_t priority); + //uint8_t dmpUnregisterFIFORateProcess(inv_obj_func func); + uint8_t dmpRunFIFORateProcesses(); + + // Setup FIFO for various output + uint8_t dmpSendQuaternion(uint_fast16_t accuracy); + uint8_t dmpSendGyro(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendAccel(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendLinearAccel(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendLinearAccelInWorld(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendControlData(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendSensorData(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendExternalSensorData(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendGravity(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendPacketNumber(uint_fast16_t accuracy); + uint8_t dmpSendQuantizedAccel(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendEIS(uint_fast16_t elements, uint_fast16_t accuracy); + + // Get Fixed Point data from FIFO + uint8_t dmpGetAccel(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetAccel(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetAccel(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetQuaternion(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetQuaternion(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetQuaternion(Quaternion *q, const uint8_t* packet=0); + uint8_t dmpGet6AxisQuaternion(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGet6AxisQuaternion(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGet6AxisQuaternion(Quaternion *q, const uint8_t* packet=0); + uint8_t dmpGetRelativeQuaternion(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetRelativeQuaternion(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetRelativeQuaternion(Quaternion *data, const uint8_t* packet=0); + uint8_t dmpGetGyro(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyro(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyro(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetMag(int16_t *data, const uint8_t* packet=0); + uint8_t dmpSetLinearAccelFilterCoefficient(float coef); + uint8_t dmpGetLinearAccel(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetLinearAccel(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetLinearAccel(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetLinearAccel(VectorInt16 *v, VectorInt16 *vRaw, VectorFloat *gravity); + uint8_t dmpGetLinearAccelInWorld(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetLinearAccelInWorld(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetLinearAccelInWorld(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Quaternion *q); + uint8_t dmpGetGyroAndAccelSensor(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyroAndAccelSensor(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyroAndAccelSensor(VectorInt16 *g, VectorInt16 *a, const uint8_t* packet=0); + uint8_t dmpGetGyroSensor(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyroSensor(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyroSensor(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetControlData(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetTemperature(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetGravity(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetGravity(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetGravity(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetGravity(VectorFloat *v, Quaternion *q); + uint8_t dmpGetUnquantizedAccel(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetUnquantizedAccel(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetUnquantizedAccel(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetQuantizedAccel(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetQuantizedAccel(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetQuantizedAccel(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetExternalSensorData(int32_t *data, uint16_t size, const uint8_t* packet=0); + uint8_t dmpGetEIS(int32_t *data, const uint8_t* packet=0); + + uint8_t dmpGetEuler(float *data, Quaternion *q); + uint8_t dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity); + + // Get Floating Point data from FIFO + uint8_t dmpGetAccelFloat(float *data, const uint8_t* packet=0); + uint8_t dmpGetQuaternionFloat(float *data, const uint8_t* packet=0); + + uint8_t dmpProcessFIFOPacket(const unsigned char *dmpData); + uint8_t dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *processed=NULL); + + uint8_t dmpSetFIFOProcessedCallback(void (*func) (void)); + + uint8_t dmpInitFIFOParam(); + uint8_t dmpCloseFIFO(); + uint8_t dmpSetGyroDataSource(uint8_t source); + uint8_t dmpDecodeQuantizedAccel(); + uint32_t dmpGetGyroSumOfSquare(); + uint32_t dmpGetAccelSumOfSquare(); + void dmpOverrideQuaternion(long *q); + uint16_t dmpGetFIFOPacketSize(); + #endif + + private: + uint8_t devAddr; + uint8_t buffer[14]; +}; + +#endif /* _MPU6050_H_ */ diff --git a/ESP32_ESP-IDF/components/MPU6050/MPU6050_6Axis_MotionApps20.h b/ESP32_ESP-IDF/components/MPU6050/MPU6050_6Axis_MotionApps20.h new file mode 100644 index 00000000..8e3d0499 --- /dev/null +++ b/ESP32_ESP-IDF/components/MPU6050/MPU6050_6Axis_MotionApps20.h @@ -0,0 +1,752 @@ +// I2Cdev library collection - MPU6050 I2C device class, 6-axis MotionApps 2.0 implementation +// Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00) +// 5/20/2013 by Jeff Rowberg +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// ... - ongoing debug release + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2012 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#ifndef _MPU6050_6AXIS_MOTIONAPPS20_H_ +#define _MPU6050_6AXIS_MOTIONAPPS20_H_ + +#include "I2Cdev.h" +//#include "helper_3dmath.h" +#include +#include +#include +#include "sdkconfig.h" + +// MotionApps 2.0 DMP implementation, built using the MPU-6050EVB evaluation board +#define MPU6050_INCLUDE_DMP_MOTIONAPPS20 + +#include "MPU6050.h" + +// Tom Carpenter's conditional PROGMEM code +// http://forum.arduino.cc/index.php?topic=129407.0 +#ifdef __AVR__ + #include +#else + // Teensy 3.0 library conditional PROGMEM code from Paul Stoffregen + #ifndef __PGMSPACE_H_ + #define __PGMSPACE_H_ 1 + #include + + #define PROGMEM + #define PGM_P const char * + #define PSTR(str) (str) + #define F(x) x + + typedef void prog_void; + typedef char prog_char; + typedef unsigned char prog_uchar; + typedef int8_t prog_int8_t; + typedef uint8_t prog_uint8_t; + typedef int16_t prog_int16_t; + typedef uint16_t prog_uint16_t; + typedef int32_t prog_int32_t; + typedef uint32_t prog_uint32_t; + + #define strcpy_P(dest, src) strcpy((dest), (src)) + #define strcat_P(dest, src) strcat((dest), (src)) + #define strcmp_P(a, b) strcmp((a), (b)) + + #define pgm_read_byte(addr) (*(const unsigned char *)(addr)) + #define pgm_read_word(addr) (*(const unsigned short *)(addr)) + #define pgm_read_dword(addr) (*(const unsigned long *)(addr)) + #define pgm_read_float(addr) (*(const float *)(addr)) + + #define pgm_read_byte_near(addr) pgm_read_byte(addr) + #define pgm_read_word_near(addr) pgm_read_word(addr) + #define pgm_read_dword_near(addr) pgm_read_dword(addr) + #define pgm_read_float_near(addr) pgm_read_float(addr) + #define pgm_read_byte_far(addr) pgm_read_byte(addr) + #define pgm_read_word_far(addr) pgm_read_word(addr) + #define pgm_read_dword_far(addr) pgm_read_dword(addr) + #define pgm_read_float_far(addr) pgm_read_float(addr) + #endif +#endif + +/* Source is from the InvenSense MotionApps v2 demo code. Original source is + * unavailable, unless you happen to be amazing as decompiling binary by + * hand (in which case, please contact me, and I'm totally serious). + * + * Also, I'd like to offer many, many thanks to Noah Zerkin for all of the + * DMP reverse-engineering he did to help make this bit of wizardry + * possible. + */ + +// NOTE! Enabling DEBUG adds about 3.3kB to the flash program size. +// Debug output is now working even on ATMega328P MCUs (e.g. Arduino Uno) +// after moving string constants to flash memory storage using the F() +// compiler macro (Arduino IDE 1.0+ required). + +#define DEBUG +#ifdef DEBUG +#define HEX "f" + #define DEBUG_PRINT(x) printf("%d", x) + #define DEBUG_PRINTF(x, y) Serial.print(x, y) + #define DEBUG_PRINTLN(x) printf("%s\n", x) + #define DEBUG_PRINTLNF(x, y) printf("%#06x%s\n", x, y) +#else + #define DEBUG_PRINT(x) + #define DEBUG_PRINTF(x, y) + #define DEBUG_PRINTLN(x) + #define DEBUG_PRINTLNF(x, y) +#endif + +#define MPU6050_DMP_CODE_SIZE 1929 // dmpMemory[] +#define MPU6050_DMP_CONFIG_SIZE 192 // dmpConfig[] +#define MPU6050_DMP_UPDATES_SIZE 47 // dmpUpdates[] + +/* ================================================================================================ * + | Default MotionApps v2.0 42-byte FIFO packet structure: | + | | + | [QUAT W][ ][QUAT X][ ][QUAT Y][ ][QUAT Z][ ][GYRO X][ ][GYRO Y][ ] | + | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | + | | + | [GYRO Z][ ][ACC X ][ ][ACC Y ][ ][ACC Z ][ ][ ] | + | 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | + * ================================================================================================ */ + +// this block of memory gets written to the MPU on start-up, and it seems +// to be volatile memory, so it has to be done each time (it only takes ~1 +// second though) +const unsigned char dmpMemory[MPU6050_DMP_CODE_SIZE] = { + // bank 0, 256 bytes + 0xFB, 0x00, 0x00, 0x3E, 0x00, 0x0B, 0x00, 0x36, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x65, 0x00, 0x54, 0xFF, 0xEF, 0x00, 0x00, 0xFA, 0x80, 0x00, 0x0B, 0x12, 0x82, 0x00, 0x01, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x28, 0x00, 0x00, 0xFF, 0xFF, 0x45, 0x81, 0xFF, 0xFF, 0xFA, 0x72, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0xE8, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x7F, 0xFF, 0xFF, 0xFE, 0x80, 0x01, + 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3E, 0x03, 0x30, 0x40, 0x00, 0x00, 0x00, 0x02, 0xCA, 0xE3, 0x09, 0x3E, 0x80, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, + 0x41, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x2A, 0x00, 0x00, 0x16, 0x55, 0x00, 0x00, 0x21, 0x82, + 0xFD, 0x87, 0x26, 0x50, 0xFD, 0x80, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x05, 0x80, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x6F, 0x00, 0x02, 0x65, 0x32, 0x00, 0x00, 0x5E, 0xC0, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFB, 0x8C, 0x6F, 0x5D, 0xFD, 0x5D, 0x08, 0xD9, 0x00, 0x7C, 0x73, 0x3B, 0x00, 0x6C, 0x12, 0xCC, + 0x32, 0x00, 0x13, 0x9D, 0x32, 0x00, 0xD0, 0xD6, 0x32, 0x00, 0x08, 0x00, 0x40, 0x00, 0x01, 0xF4, + 0xFF, 0xE6, 0x80, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0xD6, 0x00, 0x00, 0x27, 0x10, + + // bank 1, 256 bytes + 0xFB, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFA, 0x36, 0xFF, 0xBC, 0x30, 0x8E, 0x00, 0x05, 0xFB, 0xF0, 0xFF, 0xD9, 0x5B, 0xC8, + 0xFF, 0xD0, 0x9A, 0xBE, 0x00, 0x00, 0x10, 0xA9, 0xFF, 0xF4, 0x1E, 0xB2, 0x00, 0xCE, 0xBB, 0xF7, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x0C, + 0xFF, 0xC2, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0xCF, 0x80, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x14, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x3F, 0x68, 0xB6, 0x79, 0x35, 0x28, 0xBC, 0xC6, 0x7E, 0xD1, 0x6C, + 0x80, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB2, 0x6A, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x25, 0x4D, 0x00, 0x2F, 0x70, 0x6D, 0x00, 0x00, 0x05, 0xAE, 0x00, 0x0C, 0x02, 0xD0, + + // bank 2, 256 bytes + 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x54, 0xFF, 0xEF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0xFF, 0xEF, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + // bank 3, 256 bytes + 0xD8, 0xDC, 0xBA, 0xA2, 0xF1, 0xDE, 0xB2, 0xB8, 0xB4, 0xA8, 0x81, 0x91, 0xF7, 0x4A, 0x90, 0x7F, + 0x91, 0x6A, 0xF3, 0xF9, 0xDB, 0xA8, 0xF9, 0xB0, 0xBA, 0xA0, 0x80, 0xF2, 0xCE, 0x81, 0xF3, 0xC2, + 0xF1, 0xC1, 0xF2, 0xC3, 0xF3, 0xCC, 0xA2, 0xB2, 0x80, 0xF1, 0xC6, 0xD8, 0x80, 0xBA, 0xA7, 0xDF, + 0xDF, 0xDF, 0xF2, 0xA7, 0xC3, 0xCB, 0xC5, 0xB6, 0xF0, 0x87, 0xA2, 0x94, 0x24, 0x48, 0x70, 0x3C, + 0x95, 0x40, 0x68, 0x34, 0x58, 0x9B, 0x78, 0xA2, 0xF1, 0x83, 0x92, 0x2D, 0x55, 0x7D, 0xD8, 0xB1, + 0xB4, 0xB8, 0xA1, 0xD0, 0x91, 0x80, 0xF2, 0x70, 0xF3, 0x70, 0xF2, 0x7C, 0x80, 0xA8, 0xF1, 0x01, + 0xB0, 0x98, 0x87, 0xD9, 0x43, 0xD8, 0x86, 0xC9, 0x88, 0xBA, 0xA1, 0xF2, 0x0E, 0xB8, 0x97, 0x80, + 0xF1, 0xA9, 0xDF, 0xDF, 0xDF, 0xAA, 0xDF, 0xDF, 0xDF, 0xF2, 0xAA, 0xC5, 0xCD, 0xC7, 0xA9, 0x0C, + 0xC9, 0x2C, 0x97, 0x97, 0x97, 0x97, 0xF1, 0xA9, 0x89, 0x26, 0x46, 0x66, 0xB0, 0xB4, 0xBA, 0x80, + 0xAC, 0xDE, 0xF2, 0xCA, 0xF1, 0xB2, 0x8C, 0x02, 0xA9, 0xB6, 0x98, 0x00, 0x89, 0x0E, 0x16, 0x1E, + 0xB8, 0xA9, 0xB4, 0x99, 0x2C, 0x54, 0x7C, 0xB0, 0x8A, 0xA8, 0x96, 0x36, 0x56, 0x76, 0xF1, 0xB9, + 0xAF, 0xB4, 0xB0, 0x83, 0xC0, 0xB8, 0xA8, 0x97, 0x11, 0xB1, 0x8F, 0x98, 0xB9, 0xAF, 0xF0, 0x24, + 0x08, 0x44, 0x10, 0x64, 0x18, 0xF1, 0xA3, 0x29, 0x55, 0x7D, 0xAF, 0x83, 0xB5, 0x93, 0xAF, 0xF0, + 0x00, 0x28, 0x50, 0xF1, 0xA3, 0x86, 0x9F, 0x61, 0xA6, 0xDA, 0xDE, 0xDF, 0xD9, 0xFA, 0xA3, 0x86, + 0x96, 0xDB, 0x31, 0xA6, 0xD9, 0xF8, 0xDF, 0xBA, 0xA6, 0x8F, 0xC2, 0xC5, 0xC7, 0xB2, 0x8C, 0xC1, + 0xB8, 0xA2, 0xDF, 0xDF, 0xDF, 0xA3, 0xDF, 0xDF, 0xDF, 0xD8, 0xD8, 0xF1, 0xB8, 0xA8, 0xB2, 0x86, + + // bank 4, 256 bytes + 0xB4, 0x98, 0x0D, 0x35, 0x5D, 0xB8, 0xAA, 0x98, 0xB0, 0x87, 0x2D, 0x35, 0x3D, 0xB2, 0xB6, 0xBA, + 0xAF, 0x8C, 0x96, 0x19, 0x8F, 0x9F, 0xA7, 0x0E, 0x16, 0x1E, 0xB4, 0x9A, 0xB8, 0xAA, 0x87, 0x2C, + 0x54, 0x7C, 0xB9, 0xA3, 0xDE, 0xDF, 0xDF, 0xA3, 0xB1, 0x80, 0xF2, 0xC4, 0xCD, 0xC9, 0xF1, 0xB8, + 0xA9, 0xB4, 0x99, 0x83, 0x0D, 0x35, 0x5D, 0x89, 0xB9, 0xA3, 0x2D, 0x55, 0x7D, 0xB5, 0x93, 0xA3, + 0x0E, 0x16, 0x1E, 0xA9, 0x2C, 0x54, 0x7C, 0xB8, 0xB4, 0xB0, 0xF1, 0x97, 0x83, 0xA8, 0x11, 0x84, + 0xA5, 0x09, 0x98, 0xA3, 0x83, 0xF0, 0xDA, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0xD8, 0xF1, 0xA5, + 0x29, 0x55, 0x7D, 0xA5, 0x85, 0x95, 0x02, 0x1A, 0x2E, 0x3A, 0x56, 0x5A, 0x40, 0x48, 0xF9, 0xF3, + 0xA3, 0xD9, 0xF8, 0xF0, 0x98, 0x83, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0x97, 0x82, 0xA8, 0xF1, + 0x11, 0xF0, 0x98, 0xA2, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0xDA, 0xF3, 0xDE, 0xD8, 0x83, 0xA5, + 0x94, 0x01, 0xD9, 0xA3, 0x02, 0xF1, 0xA2, 0xC3, 0xC5, 0xC7, 0xD8, 0xF1, 0x84, 0x92, 0xA2, 0x4D, + 0xDA, 0x2A, 0xD8, 0x48, 0x69, 0xD9, 0x2A, 0xD8, 0x68, 0x55, 0xDA, 0x32, 0xD8, 0x50, 0x71, 0xD9, + 0x32, 0xD8, 0x70, 0x5D, 0xDA, 0x3A, 0xD8, 0x58, 0x79, 0xD9, 0x3A, 0xD8, 0x78, 0x93, 0xA3, 0x4D, + 0xDA, 0x2A, 0xD8, 0x48, 0x69, 0xD9, 0x2A, 0xD8, 0x68, 0x55, 0xDA, 0x32, 0xD8, 0x50, 0x71, 0xD9, + 0x32, 0xD8, 0x70, 0x5D, 0xDA, 0x3A, 0xD8, 0x58, 0x79, 0xD9, 0x3A, 0xD8, 0x78, 0xA8, 0x8A, 0x9A, + 0xF0, 0x28, 0x50, 0x78, 0x9E, 0xF3, 0x88, 0x18, 0xF1, 0x9F, 0x1D, 0x98, 0xA8, 0xD9, 0x08, 0xD8, + 0xC8, 0x9F, 0x12, 0x9E, 0xF3, 0x15, 0xA8, 0xDA, 0x12, 0x10, 0xD8, 0xF1, 0xAF, 0xC8, 0x97, 0x87, + + // bank 5, 256 bytes + 0x34, 0xB5, 0xB9, 0x94, 0xA4, 0x21, 0xF3, 0xD9, 0x22, 0xD8, 0xF2, 0x2D, 0xF3, 0xD9, 0x2A, 0xD8, + 0xF2, 0x35, 0xF3, 0xD9, 0x32, 0xD8, 0x81, 0xA4, 0x60, 0x60, 0x61, 0xD9, 0x61, 0xD8, 0x6C, 0x68, + 0x69, 0xD9, 0x69, 0xD8, 0x74, 0x70, 0x71, 0xD9, 0x71, 0xD8, 0xB1, 0xA3, 0x84, 0x19, 0x3D, 0x5D, + 0xA3, 0x83, 0x1A, 0x3E, 0x5E, 0x93, 0x10, 0x30, 0x81, 0x10, 0x11, 0xB8, 0xB0, 0xAF, 0x8F, 0x94, + 0xF2, 0xDA, 0x3E, 0xD8, 0xB4, 0x9A, 0xA8, 0x87, 0x29, 0xDA, 0xF8, 0xD8, 0x87, 0x9A, 0x35, 0xDA, + 0xF8, 0xD8, 0x87, 0x9A, 0x3D, 0xDA, 0xF8, 0xD8, 0xB1, 0xB9, 0xA4, 0x98, 0x85, 0x02, 0x2E, 0x56, + 0xA5, 0x81, 0x00, 0x0C, 0x14, 0xA3, 0x97, 0xB0, 0x8A, 0xF1, 0x2D, 0xD9, 0x28, 0xD8, 0x4D, 0xD9, + 0x48, 0xD8, 0x6D, 0xD9, 0x68, 0xD8, 0xB1, 0x84, 0x0D, 0xDA, 0x0E, 0xD8, 0xA3, 0x29, 0x83, 0xDA, + 0x2C, 0x0E, 0xD8, 0xA3, 0x84, 0x49, 0x83, 0xDA, 0x2C, 0x4C, 0x0E, 0xD8, 0xB8, 0xB0, 0xA8, 0x8A, + 0x9A, 0xF5, 0x20, 0xAA, 0xDA, 0xDF, 0xD8, 0xA8, 0x40, 0xAA, 0xD0, 0xDA, 0xDE, 0xD8, 0xA8, 0x60, + 0xAA, 0xDA, 0xD0, 0xDF, 0xD8, 0xF1, 0x97, 0x86, 0xA8, 0x31, 0x9B, 0x06, 0x99, 0x07, 0xAB, 0x97, + 0x28, 0x88, 0x9B, 0xF0, 0x0C, 0x20, 0x14, 0x40, 0xB8, 0xB0, 0xB4, 0xA8, 0x8C, 0x9C, 0xF0, 0x04, + 0x28, 0x51, 0x79, 0x1D, 0x30, 0x14, 0x38, 0xB2, 0x82, 0xAB, 0xD0, 0x98, 0x2C, 0x50, 0x50, 0x78, + 0x78, 0x9B, 0xF1, 0x1A, 0xB0, 0xF0, 0x8A, 0x9C, 0xA8, 0x29, 0x51, 0x79, 0x8B, 0x29, 0x51, 0x79, + 0x8A, 0x24, 0x70, 0x59, 0x8B, 0x20, 0x58, 0x71, 0x8A, 0x44, 0x69, 0x38, 0x8B, 0x39, 0x40, 0x68, + 0x8A, 0x64, 0x48, 0x31, 0x8B, 0x30, 0x49, 0x60, 0xA5, 0x88, 0x20, 0x09, 0x71, 0x58, 0x44, 0x68, + + // bank 6, 256 bytes + 0x11, 0x39, 0x64, 0x49, 0x30, 0x19, 0xF1, 0xAC, 0x00, 0x2C, 0x54, 0x7C, 0xF0, 0x8C, 0xA8, 0x04, + 0x28, 0x50, 0x78, 0xF1, 0x88, 0x97, 0x26, 0xA8, 0x59, 0x98, 0xAC, 0x8C, 0x02, 0x26, 0x46, 0x66, + 0xF0, 0x89, 0x9C, 0xA8, 0x29, 0x51, 0x79, 0x24, 0x70, 0x59, 0x44, 0x69, 0x38, 0x64, 0x48, 0x31, + 0xA9, 0x88, 0x09, 0x20, 0x59, 0x70, 0xAB, 0x11, 0x38, 0x40, 0x69, 0xA8, 0x19, 0x31, 0x48, 0x60, + 0x8C, 0xA8, 0x3C, 0x41, 0x5C, 0x20, 0x7C, 0x00, 0xF1, 0x87, 0x98, 0x19, 0x86, 0xA8, 0x6E, 0x76, + 0x7E, 0xA9, 0x99, 0x88, 0x2D, 0x55, 0x7D, 0x9E, 0xB9, 0xA3, 0x8A, 0x22, 0x8A, 0x6E, 0x8A, 0x56, + 0x8A, 0x5E, 0x9F, 0xB1, 0x83, 0x06, 0x26, 0x46, 0x66, 0x0E, 0x2E, 0x4E, 0x6E, 0x9D, 0xB8, 0xAD, + 0x00, 0x2C, 0x54, 0x7C, 0xF2, 0xB1, 0x8C, 0xB4, 0x99, 0xB9, 0xA3, 0x2D, 0x55, 0x7D, 0x81, 0x91, + 0xAC, 0x38, 0xAD, 0x3A, 0xB5, 0x83, 0x91, 0xAC, 0x2D, 0xD9, 0x28, 0xD8, 0x4D, 0xD9, 0x48, 0xD8, + 0x6D, 0xD9, 0x68, 0xD8, 0x8C, 0x9D, 0xAE, 0x29, 0xD9, 0x04, 0xAE, 0xD8, 0x51, 0xD9, 0x04, 0xAE, + 0xD8, 0x79, 0xD9, 0x04, 0xD8, 0x81, 0xF3, 0x9D, 0xAD, 0x00, 0x8D, 0xAE, 0x19, 0x81, 0xAD, 0xD9, + 0x01, 0xD8, 0xF2, 0xAE, 0xDA, 0x26, 0xD8, 0x8E, 0x91, 0x29, 0x83, 0xA7, 0xD9, 0xAD, 0xAD, 0xAD, + 0xAD, 0xF3, 0x2A, 0xD8, 0xD8, 0xF1, 0xB0, 0xAC, 0x89, 0x91, 0x3E, 0x5E, 0x76, 0xF3, 0xAC, 0x2E, + 0x2E, 0xF1, 0xB1, 0x8C, 0x5A, 0x9C, 0xAC, 0x2C, 0x28, 0x28, 0x28, 0x9C, 0xAC, 0x30, 0x18, 0xA8, + 0x98, 0x81, 0x28, 0x34, 0x3C, 0x97, 0x24, 0xA7, 0x28, 0x34, 0x3C, 0x9C, 0x24, 0xF2, 0xB0, 0x89, + 0xAC, 0x91, 0x2C, 0x4C, 0x6C, 0x8A, 0x9B, 0x2D, 0xD9, 0xD8, 0xD8, 0x51, 0xD9, 0xD8, 0xD8, 0x79, + + // bank 7, 138 bytes (remainder) + 0xD9, 0xD8, 0xD8, 0xF1, 0x9E, 0x88, 0xA3, 0x31, 0xDA, 0xD8, 0xD8, 0x91, 0x2D, 0xD9, 0x28, 0xD8, + 0x4D, 0xD9, 0x48, 0xD8, 0x6D, 0xD9, 0x68, 0xD8, 0xB1, 0x83, 0x93, 0x35, 0x3D, 0x80, 0x25, 0xDA, + 0xD8, 0xD8, 0x85, 0x69, 0xDA, 0xD8, 0xD8, 0xB4, 0x93, 0x81, 0xA3, 0x28, 0x34, 0x3C, 0xF3, 0xAB, + 0x8B, 0xF8, 0xA3, 0x91, 0xB6, 0x09, 0xB4, 0xD9, 0xAB, 0xDE, 0xFA, 0xB0, 0x87, 0x9C, 0xB9, 0xA3, + 0xDD, 0xF1, 0xA3, 0xA3, 0xA3, 0xA3, 0x95, 0xF1, 0xA3, 0xA3, 0xA3, 0x9D, 0xF1, 0xA3, 0xA3, 0xA3, + 0xA3, 0xF2, 0xA3, 0xB4, 0x90, 0x80, 0xF2, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, + 0xA3, 0xB2, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xB0, 0x87, 0xB5, 0x99, 0xF1, 0xA3, 0xA3, 0xA3, + 0x98, 0xF1, 0xA3, 0xA3, 0xA3, 0xA3, 0x97, 0xA3, 0xA3, 0xA3, 0xA3, 0xF3, 0x9B, 0xA3, 0xA3, 0xDC, + 0xB9, 0xA7, 0xF1, 0x26, 0x26, 0x26, 0xD8, 0xD8, 0xFF +}; + +// thanks to Noah Zerkin for piecing this stuff together! +const unsigned char dmpConfig[MPU6050_DMP_CONFIG_SIZE] = { +// BANK OFFSET LENGTH [DATA] + 0x03, 0x7B, 0x03, 0x4C, 0xCD, 0x6C, // FCFG_1 inv_set_gyro_calibration + 0x03, 0xAB, 0x03, 0x36, 0x56, 0x76, // FCFG_3 inv_set_gyro_calibration + 0x00, 0x68, 0x04, 0x02, 0xCB, 0x47, 0xA2, // D_0_104 inv_set_gyro_calibration + 0x02, 0x18, 0x04, 0x00, 0x05, 0x8B, 0xC1, // D_0_24 inv_set_gyro_calibration + 0x01, 0x0C, 0x04, 0x00, 0x00, 0x00, 0x00, // D_1_152 inv_set_accel_calibration + 0x03, 0x7F, 0x06, 0x0C, 0xC9, 0x2C, 0x97, 0x97, 0x97, // FCFG_2 inv_set_accel_calibration + 0x03, 0x89, 0x03, 0x26, 0x46, 0x66, // FCFG_7 inv_set_accel_calibration + 0x00, 0x6C, 0x02, 0x20, 0x00, // D_0_108 inv_set_accel_calibration + 0x02, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_00 inv_set_compass_calibration + 0x02, 0x44, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_01 + 0x02, 0x48, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_02 + 0x02, 0x4C, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_10 + 0x02, 0x50, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_11 + 0x02, 0x54, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_12 + 0x02, 0x58, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_20 + 0x02, 0x5C, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_21 + 0x02, 0xBC, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_22 + 0x01, 0xEC, 0x04, 0x00, 0x00, 0x40, 0x00, // D_1_236 inv_apply_endian_accel + 0x03, 0x7F, 0x06, 0x0C, 0xC9, 0x2C, 0x97, 0x97, 0x97, // FCFG_2 inv_set_mpu_sensors + 0x04, 0x02, 0x03, 0x0D, 0x35, 0x5D, // CFG_MOTION_BIAS inv_turn_on_bias_from_no_motion + 0x04, 0x09, 0x04, 0x87, 0x2D, 0x35, 0x3D, // FCFG_5 inv_set_bias_update + 0x00, 0xA3, 0x01, 0x00, // D_0_163 inv_set_dead_zone + // SPECIAL 0x01 = enable interrupts + 0x00, 0x00, 0x00, 0x01, // SET INT_ENABLE at i=22, SPECIAL INSTRUCTION + 0x07, 0x86, 0x01, 0xFE, // CFG_6 inv_set_fifo_interupt + 0x07, 0x41, 0x05, 0xF1, 0x20, 0x28, 0x30, 0x38, // CFG_8 inv_send_quaternion + 0x07, 0x7E, 0x01, 0x30, // CFG_16 inv_set_footer + 0x07, 0x46, 0x01, 0x9A, // CFG_GYRO_SOURCE inv_send_gyro + 0x07, 0x47, 0x04, 0xF1, 0x28, 0x30, 0x38, // CFG_9 inv_send_gyro -> inv_construct3_fifo + 0x07, 0x6C, 0x04, 0xF1, 0x28, 0x30, 0x38, // CFG_12 inv_send_accel -> inv_construct3_fifo + 0x02, 0x16, 0x02, 0x00, 0x13 // D_0_22 inv_set_fifo_rate + + // This very last 0x13 WAS a 0x09, which drops the FIFO rate down to 20 Hz. 0x07 is 25 Hz, + // 0x01 is 100Hz. Going faster than 100Hz (0x00=200Hz) tends to result in very noisy data. + // DMP output frequency is calculated easily using this equation: (200Hz / (1 + value)) + + // It is important to make sure the host processor can keep up with reading and processing + // the FIFO output at the desired rate. Handling FIFO overflow cleanly is also a good idea. +}; + +const unsigned char dmpUpdates[MPU6050_DMP_UPDATES_SIZE] = { + 0x01, 0xB2, 0x02, 0xFF, 0xFF, + 0x01, 0x90, 0x04, 0x09, 0x23, 0xA1, 0x35, + 0x01, 0x6A, 0x02, 0x06, 0x00, + 0x01, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x04, 0x40, 0x00, 0x00, 0x00, + 0x01, 0x62, 0x02, 0x00, 0x00, + 0x00, 0x60, 0x04, 0x00, 0x40, 0x00, 0x00 +}; + +uint8_t MPU6050::dmpInitialize() { + // reset device + DEBUG_PRINTLN(F("\n\nResetting MPU6050...")); + reset(); + vTaskDelay(30/portTICK_PERIOD_MS); // wait after reset + + // enable sleep mode and wake cycle + /*Serial.println(F("Enabling sleep mode...")); + setSleepEnabled(true); + Serial.println(F("Enabling wake cycle...")); + setWakeCycleEnabled(true);*/ + + // disable sleep mode + DEBUG_PRINTLN(F("Disabling sleep mode...")); + setSleepEnabled(false); + + // get MPU hardware revision + DEBUG_PRINTLN(F("Selecting user bank 16...")); + setMemoryBank(0x10, true, true); + DEBUG_PRINTLN(F("Selecting memory byte 6...")); + setMemoryStartAddress(0x06); + DEBUG_PRINTLN(F("Checking hardware revision...")); + DEBUG_PRINTLN(F("Revision @ user[16][6] = ")); + DEBUG_PRINTLNF(readMemoryByte(), HEX); + DEBUG_PRINTLN(F("Resetting memory bank selection to 0...")); + setMemoryBank(0, false, false); + + // check OTP bank valid + DEBUG_PRINTLN(F("Reading OTP bank valid flag...")); + DEBUG_PRINTLN(F("OTP bank is ")); + DEBUG_PRINTLN(getOTPBankValid() ? F("valid!") : F("invalid!")); + + // get X/Y/Z gyro offsets + DEBUG_PRINTLN(F("Reading gyro offset TC values...")); + int8_t xgOffsetTC = getXGyroOffsetTC(); + int8_t ygOffsetTC = getYGyroOffsetTC(); + int8_t zgOffsetTC = getZGyroOffsetTC(); + DEBUG_PRINTLN(F("X gyro offset = ")); + DEBUG_PRINT(xgOffsetTC); + DEBUG_PRINTLN(F("Y gyro offset = ")); + DEBUG_PRINT(ygOffsetTC); + DEBUG_PRINTLN(F("Z gyro offset = ")); + DEBUG_PRINT(zgOffsetTC); + + // setup weird slave stuff (?) + DEBUG_PRINTLN(F("Setting slave 0 address to 0x7F...")); + setSlaveAddress(0, 0x7F); + DEBUG_PRINTLN(F("Disabling I2C Master mode...")); + setI2CMasterModeEnabled(false); + DEBUG_PRINTLN(F("Setting slave 0 address to 0x68 (self)...")); + setSlaveAddress(0, 0x68); + DEBUG_PRINTLN(F("Resetting I2C Master control...")); + resetI2CMaster(); + vTaskDelay(20/portTICK_PERIOD_MS); // wait after reset + + // load DMP code into memory banks + DEBUG_PRINTLN(F("Writing DMP code to MPU memory banks (")); + DEBUG_PRINT(MPU6050_DMP_CODE_SIZE); + DEBUG_PRINTLN(F(" bytes)")); + if (writeProgMemoryBlock(dmpMemory, MPU6050_DMP_CODE_SIZE)) { + DEBUG_PRINTLN(F("Success! DMP code written and verified.")); + + // write DMP configuration + DEBUG_PRINTLN(F("Writing DMP configuration to MPU memory banks (")); + DEBUG_PRINT(MPU6050_DMP_CONFIG_SIZE); + DEBUG_PRINTLN(F(" bytes in config def)")); + if (writeProgDMPConfigurationSet(dmpConfig, MPU6050_DMP_CONFIG_SIZE)) { + DEBUG_PRINTLN(F("Success! DMP configuration written and verified.")); + + DEBUG_PRINTLN(F("Setting clock source to Z Gyro...")); + setClockSource(MPU6050_CLOCK_PLL_ZGYRO); + + DEBUG_PRINTLN(F("Setting DMP and FIFO_OFLOW interrupts enabled...")); + setIntEnabled(0x12); + + DEBUG_PRINTLN(F("Setting sample rate to 200Hz...")); + setRate(4); // 1khz / (1 + 4) = 200 Hz + + DEBUG_PRINTLN(F("Setting external frame sync to TEMP_OUT_L[0]...")); + setExternalFrameSync(MPU6050_EXT_SYNC_TEMP_OUT_L); + + DEBUG_PRINTLN(F("Setting DLPF bandwidth to 42Hz...")); + setDLPFMode(MPU6050_DLPF_BW_42); + + DEBUG_PRINTLN(F("Setting gyro sensitivity to +/- 2000 deg/sec...")); + setFullScaleGyroRange(MPU6050_GYRO_FS_2000); + + DEBUG_PRINTLN(F("Setting DMP programm start address")); + //write start address MSB into register + setDMPConfig1(0x03); + //write start address LSB into register + setDMPConfig2(0x00); + + DEBUG_PRINTLN(F("Clearing OTP Bank flag...")); + setOTPBankValid(false); + + DEBUG_PRINTLN(F("Setting X/Y/Z gyro offset TCs to previous values...")); + setXGyroOffsetTC(xgOffsetTC); + setYGyroOffsetTC(ygOffsetTC); + setZGyroOffsetTC(zgOffsetTC); + + //DEBUG_PRINTLN(F("Setting X/Y/Z gyro user offsets to zero...")); + //setXGyroOffset(0); + //setYGyroOffset(0); + //setZGyroOffset(0); + + DEBUG_PRINTLN(F("Writing final memory update 1/7 (function unknown)...")); + uint8_t dmpUpdate[16], j; + uint16_t pos = 0; + for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); + writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); + + DEBUG_PRINTLN(F("Writing final memory update 2/7 (function unknown)...")); + for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); + writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); + + DEBUG_PRINTLN(F("Resetting FIFO...")); + resetFIFO(); + + DEBUG_PRINTLN(F("Reading FIFO count...")); + uint16_t fifoCount = getFIFOCount(); + uint8_t fifoBuffer[128]; + + DEBUG_PRINTLN(F("Current FIFO count=")); + DEBUG_PRINT(fifoCount); + getFIFOBytes(fifoBuffer, fifoCount); + + DEBUG_PRINTLN(F("Setting motion detection threshold to 2...")); + setMotionDetectionThreshold(2); + + DEBUG_PRINTLN(F("Setting zero-motion detection threshold to 156...")); + setZeroMotionDetectionThreshold(156); + + DEBUG_PRINTLN(F("Setting motion detection duration to 80...")); + setMotionDetectionDuration(80); + + DEBUG_PRINTLN(F("Setting zero-motion detection duration to 0...")); + setZeroMotionDetectionDuration(0); + + DEBUG_PRINTLN(F("Resetting FIFO...")); + resetFIFO(); + + DEBUG_PRINTLN(F("Enabling FIFO...")); + setFIFOEnabled(true); + + DEBUG_PRINTLN(F("Enabling DMP...")); + setDMPEnabled(true); + + DEBUG_PRINTLN(F("Resetting DMP...")); + resetDMP(); + + DEBUG_PRINTLN(F("Writing final memory update 3/7 (function unknown)...")); + for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); + writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); + + DEBUG_PRINTLN(F("Writing final memory update 4/7 (function unknown)...")); + for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); + writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); + + DEBUG_PRINTLN(F("Writing final memory update 5/7 (function unknown)...")); + for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); + writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); + + DEBUG_PRINTLN(F("Waiting for FIFO count > 2...")); + while ((fifoCount = getFIFOCount()) < 3); + + DEBUG_PRINTLN(F("Current FIFO count=")); + DEBUG_PRINT(fifoCount); + DEBUG_PRINTLN(F("Reading FIFO data...")); + getFIFOBytes(fifoBuffer, fifoCount); + + DEBUG_PRINTLN(F("Reading interrupt status...")); + + DEBUG_PRINTLN(F("Current interrupt status=")); + DEBUG_PRINTLNF(getIntStatus(), HEX); + + DEBUG_PRINTLN(F("Reading final memory update 6/7 (function unknown)...")); + for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); + readMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); + + DEBUG_PRINTLN(F("Waiting for FIFO count > 2...")); + while ((fifoCount = getFIFOCount()) < 3); + + DEBUG_PRINTLN(F("Current FIFO count=")); + DEBUG_PRINT(fifoCount); + + DEBUG_PRINTLN(F("Reading FIFO data...")); + getFIFOBytes(fifoBuffer, fifoCount); + + DEBUG_PRINTLN(F("Reading interrupt status...")); + + DEBUG_PRINTLN(F("Current interrupt status=")); + DEBUG_PRINTLNF(getIntStatus(), HEX); + + DEBUG_PRINTLN(F("Writing final memory update 7/7 (function unknown)...")); + for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); + writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); + + DEBUG_PRINTLN(F("DMP is good to go! Finally.")); + + DEBUG_PRINTLN(F("Disabling DMP (you turn it on later)...")); + setDMPEnabled(false); + + DEBUG_PRINTLN(F("Setting up internal 42-byte (default) DMP packet buffer...")); + dmpPacketSize = 42; + /*if ((dmpPacketBuffer = (uint8_t *)malloc(42)) == 0) { + return 3; // TODO: proper error code for no memory + }*/ + + DEBUG_PRINTLN(F("Resetting FIFO and clearing INT status one last time...")); + resetFIFO(); + getIntStatus(); + } else { + DEBUG_PRINTLN(F("ERROR! DMP configuration verification failed.")); + return 2; // configuration block loading failed + } + } else { + DEBUG_PRINTLN(F("ERROR! DMP code verification failed.")); + return 1; // main binary block loading failed + } + return 0; // success +} + +bool MPU6050::dmpPacketAvailable() { + return getFIFOCount() >= dmpGetFIFOPacketSize(); +} + +// uint8_t MPU6050::dmpSetFIFORate(uint8_t fifoRate); +// uint8_t MPU6050::dmpGetFIFORate(); +// uint8_t MPU6050::dmpGetSampleStepSizeMS(); +// uint8_t MPU6050::dmpGetSampleFrequency(); +// int32_t MPU6050::dmpDecodeTemperature(int8_t tempReg); + +//uint8_t MPU6050::dmpRegisterFIFORateProcess(inv_obj_func func, int16_t priority); +//uint8_t MPU6050::dmpUnregisterFIFORateProcess(inv_obj_func func); +//uint8_t MPU6050::dmpRunFIFORateProcesses(); + +// uint8_t MPU6050::dmpSendQuaternion(uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendGyro(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendAccel(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendLinearAccel(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendLinearAccelInWorld(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendControlData(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendSensorData(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendExternalSensorData(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendGravity(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendPacketNumber(uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendQuantizedAccel(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendEIS(uint_fast16_t elements, uint_fast16_t accuracy); + +uint8_t MPU6050::dmpGetAccel(int32_t *data, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + data[0] = (((uint32_t)packet[28] << 24) | ((uint32_t)packet[29] << 16) | ((uint32_t)packet[30] << 8) | packet[31]); + data[1] = (((uint32_t)packet[32] << 24) | ((uint32_t)packet[33] << 16) | ((uint32_t)packet[34] << 8) | packet[35]); + data[2] = (((uint32_t)packet[36] << 24) | ((uint32_t)packet[37] << 16) | ((uint32_t)packet[38] << 8) | packet[39]); + return 0; +} +uint8_t MPU6050::dmpGetAccel(int16_t *data, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + data[0] = (packet[28] << 8) | packet[29]; + data[1] = (packet[32] << 8) | packet[33]; + data[2] = (packet[36] << 8) | packet[37]; + return 0; +} +uint8_t MPU6050::dmpGetAccel(VectorInt16 *v, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + v -> x = (packet[28] << 8) | packet[29]; + v -> y = (packet[32] << 8) | packet[33]; + v -> z = (packet[36] << 8) | packet[37]; + return 0; +} +uint8_t MPU6050::dmpGetQuaternion(int32_t *data, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + data[0] = (((uint32_t)packet[0] << 24) | ((uint32_t)packet[1] << 16) | ((uint32_t)packet[2] << 8) | packet[3]); + data[1] = (((uint32_t)packet[4] << 24) | ((uint32_t)packet[5] << 16) | ((uint32_t)packet[6] << 8) | packet[7]); + data[2] = (((uint32_t)packet[8] << 24) | ((uint32_t)packet[9] << 16) | ((uint32_t)packet[10] << 8) | packet[11]); + data[3] = (((uint32_t)packet[12] << 24) | ((uint32_t)packet[13] << 16) | ((uint32_t)packet[14] << 8) | packet[15]); + return 0; +} +uint8_t MPU6050::dmpGetQuaternion(int16_t *data, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + data[0] = ((packet[0] << 8) | packet[1]); + data[1] = ((packet[4] << 8) | packet[5]); + data[2] = ((packet[8] << 8) | packet[9]); + data[3] = ((packet[12] << 8) | packet[13]); + return 0; +} +uint8_t MPU6050::dmpGetQuaternion(Quaternion *q, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + int16_t qI[4]; + uint8_t status = dmpGetQuaternion(qI, packet); + if (status == 0) { + q -> w = (float)qI[0] / 16384.0f; + q -> x = (float)qI[1] / 16384.0f; + q -> y = (float)qI[2] / 16384.0f; + q -> z = (float)qI[3] / 16384.0f; + return 0; + } + return status; // int16 return value, indicates error if this line is reached +} +// uint8_t MPU6050::dmpGet6AxisQuaternion(long *data, const uint8_t* packet); +// uint8_t MPU6050::dmpGetRelativeQuaternion(long *data, const uint8_t* packet); +uint8_t MPU6050::dmpGetGyro(int32_t *data, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + data[0] = (((uint32_t)packet[16] << 24) | ((uint32_t)packet[17] << 16) | ((uint32_t)packet[18] << 8) | packet[19]); + data[1] = (((uint32_t)packet[20] << 24) | ((uint32_t)packet[21] << 16) | ((uint32_t)packet[22] << 8) | packet[23]); + data[2] = (((uint32_t)packet[24] << 24) | ((uint32_t)packet[25] << 16) | ((uint32_t)packet[26] << 8) | packet[27]); + return 0; +} +uint8_t MPU6050::dmpGetGyro(int16_t *data, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + data[0] = (packet[16] << 8) | packet[17]; + data[1] = (packet[20] << 8) | packet[21]; + data[2] = (packet[24] << 8) | packet[25]; + return 0; +} +uint8_t MPU6050::dmpGetGyro(VectorInt16 *v, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + v -> x = (packet[16] << 8) | packet[17]; + v -> y = (packet[20] << 8) | packet[21]; + v -> z = (packet[24] << 8) | packet[25]; + return 0; +} +// uint8_t MPU6050::dmpSetLinearAccelFilterCoefficient(float coef); +// uint8_t MPU6050::dmpGetLinearAccel(long *data, const uint8_t* packet); +uint8_t MPU6050::dmpGetLinearAccel(VectorInt16 *v, VectorInt16 *vRaw, VectorFloat *gravity) { + // get rid of the gravity component (+1g = +8192 in standard DMP FIFO packet, sensitivity is 2g) + v -> x = vRaw -> x - gravity -> x*8192; + v -> y = vRaw -> y - gravity -> y*8192; + v -> z = vRaw -> z - gravity -> z*8192; + return 0; +} +// uint8_t MPU6050::dmpGetLinearAccelInWorld(long *data, const uint8_t* packet); +uint8_t MPU6050::dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Quaternion *q) { + // rotate measured 3D acceleration vector into original state + // frame of reference based on orientation quaternion + memcpy(v, vReal, sizeof(VectorInt16)); + v -> rotate(q); + return 0; +} +// uint8_t MPU6050::dmpGetGyroAndAccelSensor(long *data, const uint8_t* packet); +// uint8_t MPU6050::dmpGetGyroSensor(long *data, const uint8_t* packet); +// uint8_t MPU6050::dmpGetControlData(long *data, const uint8_t* packet); +// uint8_t MPU6050::dmpGetTemperature(long *data, const uint8_t* packet); +// uint8_t MPU6050::dmpGetGravity(long *data, const uint8_t* packet); +uint8_t MPU6050::dmpGetGravity(VectorFloat *v, Quaternion *q) { + v -> x = 2 * (q -> x*q -> z - q -> w*q -> y); + v -> y = 2 * (q -> w*q -> x + q -> y*q -> z); + v -> z = q -> w*q -> w - q -> x*q -> x - q -> y*q -> y + q -> z*q -> z; + return 0; +} +// uint8_t MPU6050::dmpGetUnquantizedAccel(long *data, const uint8_t* packet); +// uint8_t MPU6050::dmpGetQuantizedAccel(long *data, const uint8_t* packet); +// uint8_t MPU6050::dmpGetExternalSensorData(long *data, int size, const uint8_t* packet); +// uint8_t MPU6050::dmpGetEIS(long *data, const uint8_t* packet); + +uint8_t MPU6050::dmpGetEuler(float *data, Quaternion *q) { + data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1); // psi + data[1] = -asin(2*q -> x*q -> z + 2*q -> w*q -> y); // theta + data[2] = atan2(2*q -> y*q -> z - 2*q -> w*q -> x, 2*q -> w*q -> w + 2*q -> z*q -> z - 1); // phi + return 0; +} +uint8_t MPU6050::dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity) { + // yaw: (about Z axis) + data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1); + // pitch: (nose up/down, about Y axis) + data[1] = atan(gravity -> x / sqrt(gravity -> y*gravity -> y + gravity -> z*gravity -> z)); + // roll: (tilt left/right, about X axis) + data[2] = atan(gravity -> y / sqrt(gravity -> x*gravity -> x + gravity -> z*gravity -> z)); + return 0; +} + +// uint8_t MPU6050::dmpGetAccelFloat(float *data, const uint8_t* packet); +// uint8_t MPU6050::dmpGetQuaternionFloat(float *data, const uint8_t* packet); + +uint8_t MPU6050::dmpProcessFIFOPacket(const unsigned char *dmpData) { + /*for (uint8_t k = 0; k < dmpPacketSize; k++) { + if (dmpData[k] < 0x10) Serial.print("0"); + Serial.print(dmpData[k], HEX); + Serial.print(" "); + } + Serial.print("\n");*/ + //Serial.println((uint16_t)dmpPacketBuffer); + return 0; +} +uint8_t MPU6050::dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *processed) { + uint8_t status; + uint8_t buf[dmpPacketSize]; + for (uint8_t i = 0; i < numPackets; i++) { + // read packet from FIFO + getFIFOBytes(buf, dmpPacketSize); + + // process packet + if ((status = dmpProcessFIFOPacket(buf)) > 0) return status; + + // increment external process count variable, if supplied + if (processed != 0) (*processed)++; + } + return 0; +} + +// uint8_t MPU6050::dmpSetFIFOProcessedCallback(void (*func) (void)); + +// uint8_t MPU6050::dmpInitFIFOParam(); +// uint8_t MPU6050::dmpCloseFIFO(); +// uint8_t MPU6050::dmpSetGyroDataSource(uint_fast8_t source); +// uint8_t MPU6050::dmpDecodeQuantizedAccel(); +// uint32_t MPU6050::dmpGetGyroSumOfSquare(); +// uint32_t MPU6050::dmpGetAccelSumOfSquare(); +// void MPU6050::dmpOverrideQuaternion(long *q); +uint16_t MPU6050::dmpGetFIFOPacketSize() { + return dmpPacketSize; +} + +#endif /* _MPU6050_6AXIS_MOTIONAPPS20_H_ */ diff --git a/ESP32_ESP-IDF/components/MPU6050/MPU6050_9Axis_MotionApps41.h b/ESP32_ESP-IDF/components/MPU6050/MPU6050_9Axis_MotionApps41.h new file mode 100644 index 00000000..016d0b0d --- /dev/null +++ b/ESP32_ESP-IDF/components/MPU6050/MPU6050_9Axis_MotionApps41.h @@ -0,0 +1,852 @@ +// I2Cdev library collection - MPU6050 I2C device class, 9-axis MotionApps 4.1 implementation +// Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00) +// 6/18/2012 by Jeff Rowberg +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// ... - ongoing debug release + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2012 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#ifndef _MPU6050_9AXIS_MOTIONAPPS41_H_ +#define _MPU6050_9AXIS_MOTIONAPPS41_H_ + +#include "I2Cdev.h" +#include "helper_3dmath.h" + +// MotionApps 4.1 DMP implementation, built using the MPU-9150 "MotionFit" board +#define MPU6050_INCLUDE_DMP_MOTIONAPPS41 + +#include "MPU6050.h" + +// Tom Carpenter's conditional PROGMEM code +// http://forum.arduino.cc/index.php?topic=129407.0 +#ifdef __AVR__ + #include +#else + // Teensy 3.0 library conditional PROGMEM code from Paul Stoffregen + #ifndef __PGMSPACE_H_ + #define __PGMSPACE_H_ 1 + #include + + #define PROGMEM + #define PGM_P const char * + #define PSTR(str) (str) + #define F(x) x + + typedef void prog_void; + typedef char prog_char; + //typedef unsigned char prog_uchar; + typedef int8_t prog_int8_t; + typedef uint8_t prog_uint8_t; + typedef int16_t prog_int16_t; + typedef uint16_t prog_uint16_t; + typedef int32_t prog_int32_t; + typedef uint32_t prog_uint32_t; + + #define strcpy_P(dest, src) strcpy((dest), (src)) + #define strcat_P(dest, src) strcat((dest), (src)) + #define strcmp_P(a, b) strcmp((a), (b)) + + #define pgm_read_byte(addr) (*(const unsigned char *)(addr)) + #define pgm_read_word(addr) (*(const unsigned short *)(addr)) + #define pgm_read_dword(addr) (*(const unsigned long *)(addr)) + #define pgm_read_float(addr) (*(const float *)(addr)) + + #define pgm_read_byte_near(addr) pgm_read_byte(addr) + #define pgm_read_word_near(addr) pgm_read_word(addr) + #define pgm_read_dword_near(addr) pgm_read_dword(addr) + #define pgm_read_float_near(addr) pgm_read_float(addr) + #define pgm_read_byte_far(addr) pgm_read_byte(addr) + #define pgm_read_word_far(addr) pgm_read_word(addr) + #define pgm_read_dword_far(addr) pgm_read_dword(addr) + #define pgm_read_float_far(addr) pgm_read_float(addr) + #endif +#endif + +// NOTE! Enabling DEBUG adds about 3.3kB to the flash program size. +// Debug output is now working even on ATMega328P MCUs (e.g. Arduino Uno) +// after moving string constants to flash memory storage using the F() +// compiler macro (Arduino IDE 1.0+ required). + +//#define DEBUG +#ifdef DEBUG + #define DEBUG_PRINT(x) Serial.print(x) + #define DEBUG_PRINTF(x, y) Serial.print(x, y) + #define DEBUG_PRINTLN(x) Serial.println(x) + #define DEBUG_PRINTLNF(x, y) Serial.println(x, y) +#else + #define DEBUG_PRINT(x) + #define DEBUG_PRINTF(x, y) + #define DEBUG_PRINTLN(x) + #define DEBUG_PRINTLNF(x, y) +#endif + +#define MPU6050_DMP_CODE_SIZE 1962 // dmpMemory[] +#define MPU6050_DMP_CONFIG_SIZE 232 // dmpConfig[] +#define MPU6050_DMP_UPDATES_SIZE 140 // dmpUpdates[] + +/* ================================================================================================ * + | Default MotionApps v4.1 48-byte FIFO packet structure: | + | | + | [QUAT W][ ][QUAT X][ ][QUAT Y][ ][QUAT Z][ ][GYRO X][ ][GYRO Y][ ] | + | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | + | | + | [GYRO Z][ ][MAG X ][MAG Y ][MAG Z ][ACC X ][ ][ACC Y ][ ][ACC Z ][ ][ ] | + | 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | + * ================================================================================================ */ + +// this block of memory gets written to the MPU on start-up, and it seems +// to be volatile memory, so it has to be done each time (it only takes ~1 +// second though) +const unsigned char dmpMemory[MPU6050_DMP_CODE_SIZE] PROGMEM = { + // bank 0, 256 bytes + 0xFB, 0x00, 0x00, 0x3E, 0x00, 0x0B, 0x00, 0x36, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x65, 0x00, 0x54, 0xFF, 0xEF, 0x00, 0x00, 0xFA, 0x80, 0x00, 0x0B, 0x12, 0x82, 0x00, 0x01, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x28, 0x00, 0x00, 0xFF, 0xFF, 0x45, 0x81, 0xFF, 0xFF, 0xFA, 0x72, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0xE8, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x7F, 0xFF, 0xFF, 0xFE, 0x80, 0x01, + 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3E, 0x03, 0x30, 0x40, 0x00, 0x00, 0x00, 0x02, 0xCA, 0xE3, 0x09, 0x3E, 0x80, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, + 0x41, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x2A, 0x00, 0x00, 0x16, 0x55, 0x00, 0x00, 0x21, 0x82, + 0xFD, 0x87, 0x26, 0x50, 0xFD, 0x80, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x05, 0x80, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x6F, 0x00, 0x02, 0x65, 0x32, 0x00, 0x00, 0x5E, 0xC0, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFB, 0x8C, 0x6F, 0x5D, 0xFD, 0x5D, 0x08, 0xD9, 0x00, 0x7C, 0x73, 0x3B, 0x00, 0x6C, 0x12, 0xCC, + 0x32, 0x00, 0x13, 0x9D, 0x32, 0x00, 0xD0, 0xD6, 0x32, 0x00, 0x08, 0x00, 0x40, 0x00, 0x01, 0xF4, + 0xFF, 0xE6, 0x80, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0xD6, 0x00, 0x00, 0x27, 0x10, + + // bank 1, 256 bytes + 0xFB, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFA, 0x36, 0xFF, 0xBC, 0x30, 0x8E, 0x00, 0x05, 0xFB, 0xF0, 0xFF, 0xD9, 0x5B, 0xC8, + 0xFF, 0xD0, 0x9A, 0xBE, 0x00, 0x00, 0x10, 0xA9, 0xFF, 0xF4, 0x1E, 0xB2, 0x00, 0xCE, 0xBB, 0xF7, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x0C, + 0xFF, 0xC2, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0xCF, 0x80, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x14, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x3F, 0x68, 0xB6, 0x79, 0x35, 0x28, 0xBC, 0xC6, 0x7E, 0xD1, 0x6C, + 0x80, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB2, 0x6A, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x25, 0x4D, 0x00, 0x2F, 0x70, 0x6D, 0x00, 0x00, 0x05, 0xAE, 0x00, 0x0C, 0x02, 0xD0, + + // bank 2, 256 bytes + 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x54, 0xFF, 0xEF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0xFF, 0xEF, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x78, 0xA2, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + // bank 3, 256 bytes + 0xD8, 0xDC, 0xF4, 0xD8, 0xB9, 0xAB, 0xF3, 0xF8, 0xFA, 0xF1, 0xBA, 0xA2, 0xDE, 0xB2, 0xB8, 0xB4, + 0xA8, 0x81, 0x98, 0xF7, 0x4A, 0x90, 0x7F, 0x91, 0x6A, 0xF3, 0xF9, 0xDB, 0xA8, 0xF9, 0xB0, 0xBA, + 0xA0, 0x80, 0xF2, 0xCE, 0x81, 0xF3, 0xC2, 0xF1, 0xC1, 0xF2, 0xC3, 0xF3, 0xCC, 0xA2, 0xB2, 0x80, + 0xF1, 0xC6, 0xD8, 0x80, 0xBA, 0xA7, 0xDF, 0xDF, 0xDF, 0xF2, 0xA7, 0xC3, 0xCB, 0xC5, 0xB6, 0xF0, + 0x87, 0xA2, 0x94, 0x24, 0x48, 0x70, 0x3C, 0x95, 0x40, 0x68, 0x34, 0x58, 0x9B, 0x78, 0xA2, 0xF1, + 0x83, 0x92, 0x2D, 0x55, 0x7D, 0xD8, 0xB1, 0xB4, 0xB8, 0xA1, 0xD0, 0x91, 0x80, 0xF2, 0x70, 0xF3, + 0x70, 0xF2, 0x7C, 0x80, 0xA8, 0xF1, 0x01, 0xB0, 0x98, 0x87, 0xD9, 0x43, 0xD8, 0x86, 0xC9, 0x88, + 0xBA, 0xA1, 0xF2, 0x0E, 0xB8, 0x97, 0x80, 0xF1, 0xA9, 0xDF, 0xDF, 0xDF, 0xAA, 0xDF, 0xDF, 0xDF, + 0xF2, 0xAA, 0xC5, 0xCD, 0xC7, 0xA9, 0x0C, 0xC9, 0x2C, 0x97, 0x97, 0x97, 0x97, 0xF1, 0xA9, 0x89, + 0x26, 0x46, 0x66, 0xB0, 0xB4, 0xBA, 0x80, 0xAC, 0xDE, 0xF2, 0xCA, 0xF1, 0xB2, 0x8C, 0x02, 0xA9, + 0xB6, 0x98, 0x00, 0x89, 0x0E, 0x16, 0x1E, 0xB8, 0xA9, 0xB4, 0x99, 0x2C, 0x54, 0x7C, 0xB0, 0x8A, + 0xA8, 0x96, 0x36, 0x56, 0x76, 0xF1, 0xB9, 0xAF, 0xB4, 0xB0, 0x83, 0xC0, 0xB8, 0xA8, 0x97, 0x11, + 0xB1, 0x8F, 0x98, 0xB9, 0xAF, 0xF0, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0xF1, 0xA3, 0x29, 0x55, + 0x7D, 0xAF, 0x83, 0xB5, 0x93, 0xF0, 0x00, 0x28, 0x50, 0xF5, 0xBA, 0xAD, 0x8F, 0x9F, 0x28, 0x54, + 0x7C, 0xB9, 0xF1, 0xA3, 0x86, 0x9F, 0x61, 0xA6, 0xDA, 0xDE, 0xDF, 0xDB, 0xB2, 0xB6, 0x8E, 0x9D, + 0xAE, 0xF5, 0x60, 0x68, 0x70, 0xB1, 0xB5, 0xF1, 0xDA, 0xA6, 0xDF, 0xD9, 0xA6, 0xFA, 0xA3, 0x86, + + // bank 4, 256 bytes + 0x96, 0xDB, 0x31, 0xA6, 0xD9, 0xF8, 0xDF, 0xBA, 0xA6, 0x8F, 0xC2, 0xC5, 0xC7, 0xB2, 0x8C, 0xC1, + 0xB8, 0xA2, 0xDF, 0xDF, 0xDF, 0xA3, 0xDF, 0xDF, 0xDF, 0xD8, 0xD8, 0xF1, 0xB8, 0xA8, 0xB2, 0x86, + 0xB4, 0x98, 0x0D, 0x35, 0x5D, 0xB8, 0xAA, 0x98, 0xB0, 0x87, 0x2D, 0x35, 0x3D, 0xB2, 0xB6, 0xBA, + 0xAF, 0x8C, 0x96, 0x19, 0x8F, 0x9F, 0xA7, 0x0E, 0x16, 0x1E, 0xB4, 0x9A, 0xB8, 0xAA, 0x87, 0x2C, + 0x54, 0x7C, 0xB9, 0xA3, 0xDE, 0xDF, 0xDF, 0xA3, 0xB1, 0x80, 0xF2, 0xC4, 0xCD, 0xC9, 0xF1, 0xB8, + 0xA9, 0xB4, 0x99, 0x83, 0x0D, 0x35, 0x5D, 0x89, 0xB9, 0xA3, 0x2D, 0x55, 0x7D, 0xB5, 0x93, 0xA3, + 0x0E, 0x16, 0x1E, 0xA9, 0x2C, 0x54, 0x7C, 0xB8, 0xB4, 0xB0, 0xF1, 0x97, 0x83, 0xA8, 0x11, 0x84, + 0xA5, 0x09, 0x98, 0xA3, 0x83, 0xF0, 0xDA, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0xD8, 0xF1, 0xA5, + 0x29, 0x55, 0x7D, 0xA5, 0x85, 0x95, 0x02, 0x1A, 0x2E, 0x3A, 0x56, 0x5A, 0x40, 0x48, 0xF9, 0xF3, + 0xA3, 0xD9, 0xF8, 0xF0, 0x98, 0x83, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0x97, 0x82, 0xA8, 0xF1, + 0x11, 0xF0, 0x98, 0xA2, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0xDA, 0xF3, 0xDE, 0xD8, 0x83, 0xA5, + 0x94, 0x01, 0xD9, 0xA3, 0x02, 0xF1, 0xA2, 0xC3, 0xC5, 0xC7, 0xD8, 0xF1, 0x84, 0x92, 0xA2, 0x4D, + 0xDA, 0x2A, 0xD8, 0x48, 0x69, 0xD9, 0x2A, 0xD8, 0x68, 0x55, 0xDA, 0x32, 0xD8, 0x50, 0x71, 0xD9, + 0x32, 0xD8, 0x70, 0x5D, 0xDA, 0x3A, 0xD8, 0x58, 0x79, 0xD9, 0x3A, 0xD8, 0x78, 0x93, 0xA3, 0x4D, + 0xDA, 0x2A, 0xD8, 0x48, 0x69, 0xD9, 0x2A, 0xD8, 0x68, 0x55, 0xDA, 0x32, 0xD8, 0x50, 0x71, 0xD9, + 0x32, 0xD8, 0x70, 0x5D, 0xDA, 0x3A, 0xD8, 0x58, 0x79, 0xD9, 0x3A, 0xD8, 0x78, 0xA8, 0x8A, 0x9A, + + // bank 5, 256 bytes + 0xF0, 0x28, 0x50, 0x78, 0x9E, 0xF3, 0x88, 0x18, 0xF1, 0x9F, 0x1D, 0x98, 0xA8, 0xD9, 0x08, 0xD8, + 0xC8, 0x9F, 0x12, 0x9E, 0xF3, 0x15, 0xA8, 0xDA, 0x12, 0x10, 0xD8, 0xF1, 0xAF, 0xC8, 0x97, 0x87, + 0x34, 0xB5, 0xB9, 0x94, 0xA4, 0x21, 0xF3, 0xD9, 0x22, 0xD8, 0xF2, 0x2D, 0xF3, 0xD9, 0x2A, 0xD8, + 0xF2, 0x35, 0xF3, 0xD9, 0x32, 0xD8, 0x81, 0xA4, 0x60, 0x60, 0x61, 0xD9, 0x61, 0xD8, 0x6C, 0x68, + 0x69, 0xD9, 0x69, 0xD8, 0x74, 0x70, 0x71, 0xD9, 0x71, 0xD8, 0xB1, 0xA3, 0x84, 0x19, 0x3D, 0x5D, + 0xA3, 0x83, 0x1A, 0x3E, 0x5E, 0x93, 0x10, 0x30, 0x81, 0x10, 0x11, 0xB8, 0xB0, 0xAF, 0x8F, 0x94, + 0xF2, 0xDA, 0x3E, 0xD8, 0xB4, 0x9A, 0xA8, 0x87, 0x29, 0xDA, 0xF8, 0xD8, 0x87, 0x9A, 0x35, 0xDA, + 0xF8, 0xD8, 0x87, 0x9A, 0x3D, 0xDA, 0xF8, 0xD8, 0xB1, 0xB9, 0xA4, 0x98, 0x85, 0x02, 0x2E, 0x56, + 0xA5, 0x81, 0x00, 0x0C, 0x14, 0xA3, 0x97, 0xB0, 0x8A, 0xF1, 0x2D, 0xD9, 0x28, 0xD8, 0x4D, 0xD9, + 0x48, 0xD8, 0x6D, 0xD9, 0x68, 0xD8, 0xB1, 0x84, 0x0D, 0xDA, 0x0E, 0xD8, 0xA3, 0x29, 0x83, 0xDA, + 0x2C, 0x0E, 0xD8, 0xA3, 0x84, 0x49, 0x83, 0xDA, 0x2C, 0x4C, 0x0E, 0xD8, 0xB8, 0xB0, 0x97, 0x86, + 0xA8, 0x31, 0x9B, 0x06, 0x99, 0x07, 0xAB, 0x97, 0x28, 0x88, 0x9B, 0xF0, 0x0C, 0x20, 0x14, 0x40, + 0xB9, 0xA3, 0x8A, 0xC3, 0xC5, 0xC7, 0x9A, 0xA3, 0x28, 0x50, 0x78, 0xF1, 0xB5, 0x93, 0x01, 0xD9, + 0xDF, 0xDF, 0xDF, 0xD8, 0xB8, 0xB4, 0xA8, 0x8C, 0x9C, 0xF0, 0x04, 0x28, 0x51, 0x79, 0x1D, 0x30, + 0x14, 0x38, 0xB2, 0x82, 0xAB, 0xD0, 0x98, 0x2C, 0x50, 0x50, 0x78, 0x78, 0x9B, 0xF1, 0x1A, 0xB0, + 0xF0, 0xB1, 0x83, 0x9C, 0xA8, 0x29, 0x51, 0x79, 0xB0, 0x8B, 0x29, 0x51, 0x79, 0xB1, 0x83, 0x24, + + // bank 6, 256 bytes + 0x70, 0x59, 0xB0, 0x8B, 0x20, 0x58, 0x71, 0xB1, 0x83, 0x44, 0x69, 0x38, 0xB0, 0x8B, 0x39, 0x40, + 0x68, 0xB1, 0x83, 0x64, 0x48, 0x31, 0xB0, 0x8B, 0x30, 0x49, 0x60, 0xA5, 0x88, 0x20, 0x09, 0x71, + 0x58, 0x44, 0x68, 0x11, 0x39, 0x64, 0x49, 0x30, 0x19, 0xF1, 0xAC, 0x00, 0x2C, 0x54, 0x7C, 0xF0, + 0x8C, 0xA8, 0x04, 0x28, 0x50, 0x78, 0xF1, 0x88, 0x97, 0x26, 0xA8, 0x59, 0x98, 0xAC, 0x8C, 0x02, + 0x26, 0x46, 0x66, 0xF0, 0x89, 0x9C, 0xA8, 0x29, 0x51, 0x79, 0x24, 0x70, 0x59, 0x44, 0x69, 0x38, + 0x64, 0x48, 0x31, 0xA9, 0x88, 0x09, 0x20, 0x59, 0x70, 0xAB, 0x11, 0x38, 0x40, 0x69, 0xA8, 0x19, + 0x31, 0x48, 0x60, 0x8C, 0xA8, 0x3C, 0x41, 0x5C, 0x20, 0x7C, 0x00, 0xF1, 0x87, 0x98, 0x19, 0x86, + 0xA8, 0x6E, 0x76, 0x7E, 0xA9, 0x99, 0x88, 0x2D, 0x55, 0x7D, 0x9E, 0xB9, 0xA3, 0x8A, 0x22, 0x8A, + 0x6E, 0x8A, 0x56, 0x8A, 0x5E, 0x9F, 0xB1, 0x83, 0x06, 0x26, 0x46, 0x66, 0x0E, 0x2E, 0x4E, 0x6E, + 0x9D, 0xB8, 0xAD, 0x00, 0x2C, 0x54, 0x7C, 0xF2, 0xB1, 0x8C, 0xB4, 0x99, 0xB9, 0xA3, 0x2D, 0x55, + 0x7D, 0x81, 0x91, 0xAC, 0x38, 0xAD, 0x3A, 0xB5, 0x83, 0x91, 0xAC, 0x2D, 0xD9, 0x28, 0xD8, 0x4D, + 0xD9, 0x48, 0xD8, 0x6D, 0xD9, 0x68, 0xD8, 0x8C, 0x9D, 0xAE, 0x29, 0xD9, 0x04, 0xAE, 0xD8, 0x51, + 0xD9, 0x04, 0xAE, 0xD8, 0x79, 0xD9, 0x04, 0xD8, 0x81, 0xF3, 0x9D, 0xAD, 0x00, 0x8D, 0xAE, 0x19, + 0x81, 0xAD, 0xD9, 0x01, 0xD8, 0xF2, 0xAE, 0xDA, 0x26, 0xD8, 0x8E, 0x91, 0x29, 0x83, 0xA7, 0xD9, + 0xAD, 0xAD, 0xAD, 0xAD, 0xF3, 0x2A, 0xD8, 0xD8, 0xF1, 0xB0, 0xAC, 0x89, 0x91, 0x3E, 0x5E, 0x76, + 0xF3, 0xAC, 0x2E, 0x2E, 0xF1, 0xB1, 0x8C, 0x5A, 0x9C, 0xAC, 0x2C, 0x28, 0x28, 0x28, 0x9C, 0xAC, + + // bank 7, 170 bytes (remainder) + 0x30, 0x18, 0xA8, 0x98, 0x81, 0x28, 0x34, 0x3C, 0x97, 0x24, 0xA7, 0x28, 0x34, 0x3C, 0x9C, 0x24, + 0xF2, 0xB0, 0x89, 0xAC, 0x91, 0x2C, 0x4C, 0x6C, 0x8A, 0x9B, 0x2D, 0xD9, 0xD8, 0xD8, 0x51, 0xD9, + 0xD8, 0xD8, 0x79, 0xD9, 0xD8, 0xD8, 0xF1, 0x9E, 0x88, 0xA3, 0x31, 0xDA, 0xD8, 0xD8, 0x91, 0x2D, + 0xD9, 0x28, 0xD8, 0x4D, 0xD9, 0x48, 0xD8, 0x6D, 0xD9, 0x68, 0xD8, 0xB1, 0x83, 0x93, 0x35, 0x3D, + 0x80, 0x25, 0xDA, 0xD8, 0xD8, 0x85, 0x69, 0xDA, 0xD8, 0xD8, 0xB4, 0x93, 0x81, 0xA3, 0x28, 0x34, + 0x3C, 0xF3, 0xAB, 0x8B, 0xA3, 0x91, 0xB6, 0x09, 0xB4, 0xD9, 0xAB, 0xDE, 0xB0, 0x87, 0x9C, 0xB9, + 0xA3, 0xDD, 0xF1, 0xA3, 0xA3, 0xA3, 0xA3, 0x95, 0xF1, 0xA3, 0xA3, 0xA3, 0x9D, 0xF1, 0xA3, 0xA3, + 0xA3, 0xA3, 0xF2, 0xA3, 0xB4, 0x90, 0x80, 0xF2, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, + 0xA3, 0xA3, 0xB2, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xB0, 0x87, 0xB5, 0x99, 0xF1, 0xA3, 0xA3, + 0xA3, 0x98, 0xF1, 0xA3, 0xA3, 0xA3, 0xA3, 0x97, 0xA3, 0xA3, 0xA3, 0xA3, 0xF3, 0x9B, 0xA3, 0xA3, + 0xDC, 0xB9, 0xA7, 0xF1, 0x26, 0x26, 0x26, 0xD8, 0xD8, 0xFF +}; + +const unsigned char dmpConfig[MPU6050_DMP_CONFIG_SIZE] PROGMEM = { +// BANK OFFSET LENGTH [DATA] + 0x02, 0xEC, 0x04, 0x00, 0x47, 0x7D, 0x1A, // ? + 0x03, 0x82, 0x03, 0x4C, 0xCD, 0x6C, // FCFG_1 inv_set_gyro_calibration + 0x03, 0xB2, 0x03, 0x36, 0x56, 0x76, // FCFG_3 inv_set_gyro_calibration + 0x00, 0x68, 0x04, 0x02, 0xCA, 0xE3, 0x09, // D_0_104 inv_set_gyro_calibration + 0x01, 0x0C, 0x04, 0x00, 0x00, 0x00, 0x00, // D_1_152 inv_set_accel_calibration + 0x03, 0x86, 0x03, 0x0C, 0xC9, 0x2C, // FCFG_2 inv_set_accel_calibration + 0x03, 0x90, 0x03, 0x26, 0x46, 0x66, // (continued)...FCFG_2 inv_set_accel_calibration + 0x00, 0x6C, 0x02, 0x40, 0x00, // D_0_108 inv_set_accel_calibration + + 0x02, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_00 inv_set_compass_calibration + 0x02, 0x44, 0x04, 0x40, 0x00, 0x00, 0x00, // CPASS_MTX_01 + 0x02, 0x48, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_02 + 0x02, 0x4C, 0x04, 0x40, 0x00, 0x00, 0x00, // CPASS_MTX_10 + 0x02, 0x50, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_11 + 0x02, 0x54, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_12 + 0x02, 0x58, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_20 + 0x02, 0x5C, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_21 + 0x02, 0xBC, 0x04, 0xC0, 0x00, 0x00, 0x00, // CPASS_MTX_22 + + 0x01, 0xEC, 0x04, 0x00, 0x00, 0x40, 0x00, // D_1_236 inv_apply_endian_accel + 0x03, 0x86, 0x06, 0x0C, 0xC9, 0x2C, 0x97, 0x97, 0x97, // FCFG_2 inv_set_mpu_sensors + 0x04, 0x22, 0x03, 0x0D, 0x35, 0x5D, // CFG_MOTION_BIAS inv_turn_on_bias_from_no_motion + 0x00, 0xA3, 0x01, 0x00, // ? + 0x04, 0x29, 0x04, 0x87, 0x2D, 0x35, 0x3D, // FCFG_5 inv_set_bias_update + 0x07, 0x62, 0x05, 0xF1, 0x20, 0x28, 0x30, 0x38, // CFG_8 inv_send_quaternion + 0x07, 0x9F, 0x01, 0x30, // CFG_16 inv_set_footer + 0x07, 0x67, 0x01, 0x9A, // CFG_GYRO_SOURCE inv_send_gyro + 0x07, 0x68, 0x04, 0xF1, 0x28, 0x30, 0x38, // CFG_9 inv_send_gyro -> inv_construct3_fifo + 0x07, 0x62, 0x05, 0xF1, 0x20, 0x28, 0x30, 0x38, // ? + 0x02, 0x0C, 0x04, 0x00, 0x00, 0x00, 0x00, // ? + 0x07, 0x83, 0x06, 0xC2, 0xCA, 0xC4, 0xA3, 0xA3, 0xA3, // ? + // SPECIAL 0x01 = enable interrupts + 0x00, 0x00, 0x00, 0x01, // SET INT_ENABLE, SPECIAL INSTRUCTION + 0x07, 0xA7, 0x01, 0xFE, // ? + 0x07, 0x62, 0x05, 0xF1, 0x20, 0x28, 0x30, 0x38, // ? + 0x07, 0x67, 0x01, 0x9A, // ? + 0x07, 0x68, 0x04, 0xF1, 0x28, 0x30, 0x38, // CFG_12 inv_send_accel -> inv_construct3_fifo + 0x07, 0x8D, 0x04, 0xF1, 0x28, 0x30, 0x38, // ??? CFG_12 inv_send_mag -> inv_construct3_fifo + 0x02, 0x16, 0x02, 0x00, 0x03 // D_0_22 inv_set_fifo_rate + + // This very last 0x01 WAS a 0x09, which drops the FIFO rate down to 20 Hz. 0x07 is 25 Hz, + // 0x01 is 100Hz. Going faster than 100Hz (0x00=200Hz) tends to result in very noisy data. + // DMP output frequency is calculated easily using this equation: (200Hz / (1 + value)) + + // It is important to make sure the host processor can keep up with reading and processing + // the FIFO output at the desired rate. Handling FIFO overflow cleanly is also a good idea. +}; + +const unsigned char dmpUpdates[MPU6050_DMP_UPDATES_SIZE] PROGMEM = { + 0x01, 0xB2, 0x02, 0xFF, 0xF5, + 0x01, 0x90, 0x04, 0x0A, 0x0D, 0x97, 0xC0, + 0x00, 0xA3, 0x01, 0x00, + 0x04, 0x29, 0x04, 0x87, 0x2D, 0x35, 0x3D, + 0x01, 0x6A, 0x02, 0x06, 0x00, + 0x01, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x04, 0x40, 0x00, 0x00, 0x00, + 0x02, 0x60, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x08, 0x02, 0x01, 0x20, + 0x01, 0x0A, 0x02, 0x00, 0x4E, + 0x01, 0x02, 0x02, 0xFE, 0xB3, + 0x02, 0x6C, 0x04, 0x00, 0x00, 0x00, 0x00, // READ + 0x02, 0x6C, 0x04, 0xFA, 0xFE, 0x00, 0x00, + 0x02, 0x60, 0x0C, 0xFF, 0xFF, 0xCB, 0x4D, 0x00, 0x01, 0x08, 0xC1, 0xFF, 0xFF, 0xBC, 0x2C, + 0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x02, 0xF8, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x02, 0xFC, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x04, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x04, 0x00, 0x40, 0x00, 0x00 +}; + +uint8_t MPU6050::dmpInitialize() { + // reset device + DEBUG_PRINTLN(F("\n\nResetting MPU6050...")); + reset(); + delay(30); // wait after reset + + // disable sleep mode + DEBUG_PRINTLN(F("Disabling sleep mode...")); + setSleepEnabled(false); + + // get MPU product ID + DEBUG_PRINTLN(F("Getting product ID...")); + //uint8_t productID = 0; //getProductID(); + DEBUG_PRINT(F("Product ID = ")); + DEBUG_PRINT(productID); + + // get MPU hardware revision + DEBUG_PRINTLN(F("Selecting user bank 16...")); + setMemoryBank(0x10, true, true); + DEBUG_PRINTLN(F("Selecting memory byte 6...")); + setMemoryStartAddress(0x06); + DEBUG_PRINTLN(F("Checking hardware revision...")); + uint8_t hwRevision = readMemoryByte(); + DEBUG_PRINT(F("Revision @ user[16][6] = ")); + DEBUG_PRINTLNF(hwRevision, HEX); + DEBUG_PRINTLN(F("Resetting memory bank selection to 0...")); + setMemoryBank(0, false, false); + + // check OTP bank valid + DEBUG_PRINTLN(F("Reading OTP bank valid flag...")); + uint8_t otpValid = getOTPBankValid(); + DEBUG_PRINT(F("OTP bank is ")); + DEBUG_PRINTLN(otpValid ? F("valid!") : F("invalid!")); + + // get X/Y/Z gyro offsets + DEBUG_PRINTLN(F("Reading gyro offset values...")); + int8_t xgOffset = getXGyroOffset(); + int8_t ygOffset = getYGyroOffset(); + int8_t zgOffset = getZGyroOffset(); + DEBUG_PRINT(F("X gyro offset = ")); + DEBUG_PRINTLN(xgOffset); + DEBUG_PRINT(F("Y gyro offset = ")); + DEBUG_PRINTLN(ygOffset); + DEBUG_PRINT(F("Z gyro offset = ")); + DEBUG_PRINTLN(zgOffset); + + I2Cdev::readByte(devAddr, MPU6050_RA_USER_CTRL, buffer); // ? + + DEBUG_PRINTLN(F("Enabling interrupt latch, clear on any read, AUX bypass enabled")); + I2Cdev::writeByte(devAddr, MPU6050_RA_INT_PIN_CFG, 0x32); + + // enable MPU AUX I2C bypass mode + //DEBUG_PRINTLN(F("Enabling AUX I2C bypass mode...")); + //setI2CBypassEnabled(true); + + DEBUG_PRINTLN(F("Setting magnetometer mode to power-down...")); + //mag -> setMode(0); + I2Cdev::writeByte(0x0E, 0x0A, 0x00); + + DEBUG_PRINTLN(F("Setting magnetometer mode to fuse access...")); + //mag -> setMode(0x0F); + I2Cdev::writeByte(0x0E, 0x0A, 0x0F); + + DEBUG_PRINTLN(F("Reading mag magnetometer factory calibration...")); + int8_t asax, asay, asaz; + //mag -> getAdjustment(&asax, &asay, &asaz); + I2Cdev::readBytes(0x0E, 0x10, 3, buffer); + asax = (int8_t)buffer[0]; + asay = (int8_t)buffer[1]; + asaz = (int8_t)buffer[2]; + DEBUG_PRINT(F("Adjustment X/Y/Z = ")); + DEBUG_PRINT(asax); + DEBUG_PRINT(F(" / ")); + DEBUG_PRINT(asay); + DEBUG_PRINT(F(" / ")); + DEBUG_PRINTLN(asaz); + + DEBUG_PRINTLN(F("Setting magnetometer mode to power-down...")); + //mag -> setMode(0); + I2Cdev::writeByte(0x0E, 0x0A, 0x00); + + // load DMP code into memory banks + DEBUG_PRINT(F("Writing DMP code to MPU memory banks (")); + DEBUG_PRINT(MPU6050_DMP_CODE_SIZE); + DEBUG_PRINTLN(F(" bytes)")); + if (writeProgMemoryBlock(dmpMemory, MPU6050_DMP_CODE_SIZE)) { + DEBUG_PRINTLN(F("Success! DMP code written and verified.")); + + DEBUG_PRINTLN(F("Configuring DMP and related settings...")); + + // write DMP configuration + DEBUG_PRINT(F("Writing DMP configuration to MPU memory banks (")); + DEBUG_PRINT(MPU6050_DMP_CONFIG_SIZE); + DEBUG_PRINTLN(F(" bytes in config def)")); + if (writeProgDMPConfigurationSet(dmpConfig, MPU6050_DMP_CONFIG_SIZE)) { + DEBUG_PRINTLN(F("Success! DMP configuration written and verified.")); + + DEBUG_PRINTLN(F("Setting DMP and FIFO_OFLOW interrupts enabled...")); + setIntEnabled(0x12); + + DEBUG_PRINTLN(F("Setting sample rate to 200Hz...")); + setRate(4); // 1khz / (1 + 4) = 200 Hz + + DEBUG_PRINTLN(F("Setting clock source to Z Gyro...")); + setClockSource(MPU6050_CLOCK_PLL_ZGYRO); + + DEBUG_PRINTLN(F("Setting DLPF bandwidth to 42Hz...")); + setDLPFMode(MPU6050_DLPF_BW_42); + + DEBUG_PRINTLN(F("Setting external frame sync to TEMP_OUT_L[0]...")); + setExternalFrameSync(MPU6050_EXT_SYNC_TEMP_OUT_L); + + DEBUG_PRINTLN(F("Setting gyro sensitivity to +/- 2000 deg/sec...")); + setFullScaleGyroRange(MPU6050_GYRO_FS_2000); + + DEBUG_PRINTLN(F("Setting DMP configuration bytes (function unknown)...")); + setDMPConfig1(0x03); + setDMPConfig2(0x00); + + DEBUG_PRINTLN(F("Clearing OTP Bank flag...")); + setOTPBankValid(false); + + DEBUG_PRINTLN(F("Setting X/Y/Z gyro offsets to previous values...")); + setXGyroOffsetTC(xgOffset); + setYGyroOffsetTC(ygOffset); + setZGyroOffsetTC(zgOffset); + + //DEBUG_PRINTLN(F("Setting X/Y/Z gyro user offsets to zero...")); + //setXGyroOffset(0); + //setYGyroOffset(0); + //setZGyroOffset(0); + + DEBUG_PRINTLN(F("Writing final memory update 1/19 (function unknown)...")); + uint8_t dmpUpdate[16], j; + uint16_t pos = 0; + for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); + writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); + + DEBUG_PRINTLN(F("Writing final memory update 2/19 (function unknown)...")); + for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); + writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); + + DEBUG_PRINTLN(F("Resetting FIFO...")); + resetFIFO(); + + DEBUG_PRINTLN(F("Reading FIFO count...")); + uint8_t fifoCount = getFIFOCount(); + + DEBUG_PRINT(F("Current FIFO count=")); + DEBUG_PRINTLN(fifoCount); + uint8_t fifoBuffer[128]; + //getFIFOBytes(fifoBuffer, fifoCount); + + DEBUG_PRINTLN(F("Writing final memory update 3/19 (function unknown)...")); + for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); + writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); + + DEBUG_PRINTLN(F("Writing final memory update 4/19 (function unknown)...")); + for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); + writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); + + DEBUG_PRINTLN(F("Disabling all standby flags...")); + I2Cdev::writeByte(0x68, MPU6050_RA_PWR_MGMT_2, 0x00); + + DEBUG_PRINTLN(F("Setting accelerometer sensitivity to +/- 2g...")); + I2Cdev::writeByte(0x68, MPU6050_RA_ACCEL_CONFIG, 0x00); + + DEBUG_PRINTLN(F("Setting motion detection threshold to 2...")); + setMotionDetectionThreshold(2); + + DEBUG_PRINTLN(F("Setting zero-motion detection threshold to 156...")); + setZeroMotionDetectionThreshold(156); + + DEBUG_PRINTLN(F("Setting motion detection duration to 80...")); + setMotionDetectionDuration(80); + + DEBUG_PRINTLN(F("Setting zero-motion detection duration to 0...")); + setZeroMotionDetectionDuration(0); + + DEBUG_PRINTLN(F("Setting AK8975 to single measurement mode...")); + //mag -> setMode(1); + I2Cdev::writeByte(0x0E, 0x0A, 0x01); + + // setup AK8975 (0x0E) as Slave 0 in read mode + DEBUG_PRINTLN(F("Setting up AK8975 read slave 0...")); + I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV0_ADDR, 0x8E); + I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV0_REG, 0x01); + I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV0_CTRL, 0xDA); + + // setup AK8975 (0x0E) as Slave 2 in write mode + DEBUG_PRINTLN(F("Setting up AK8975 write slave 2...")); + I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV2_ADDR, 0x0E); + I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV2_REG, 0x0A); + I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV2_CTRL, 0x81); + I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV2_DO, 0x01); + + // setup I2C timing/delay control + DEBUG_PRINTLN(F("Setting up slave access delay...")); + I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV4_CTRL, 0x18); + I2Cdev::writeByte(0x68, MPU6050_RA_I2C_MST_DELAY_CTRL, 0x05); + + // enable interrupts + DEBUG_PRINTLN(F("Enabling default interrupt behavior/no bypass...")); + I2Cdev::writeByte(0x68, MPU6050_RA_INT_PIN_CFG, 0x00); + + // enable I2C master mode and reset DMP/FIFO + DEBUG_PRINTLN(F("Enabling I2C master mode...")); + I2Cdev::writeByte(0x68, MPU6050_RA_USER_CTRL, 0x20); + DEBUG_PRINTLN(F("Resetting FIFO...")); + I2Cdev::writeByte(0x68, MPU6050_RA_USER_CTRL, 0x24); + DEBUG_PRINTLN(F("Rewriting I2C master mode enabled because...I don't know")); + I2Cdev::writeByte(0x68, MPU6050_RA_USER_CTRL, 0x20); + DEBUG_PRINTLN(F("Enabling and resetting DMP/FIFO...")); + I2Cdev::writeByte(0x68, MPU6050_RA_USER_CTRL, 0xE8); + + DEBUG_PRINTLN(F("Writing final memory update 5/19 (function unknown)...")); + for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); + writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); + DEBUG_PRINTLN(F("Writing final memory update 6/19 (function unknown)...")); + for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); + writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); + DEBUG_PRINTLN(F("Writing final memory update 7/19 (function unknown)...")); + for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); + writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); + DEBUG_PRINTLN(F("Writing final memory update 8/19 (function unknown)...")); + for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); + writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); + DEBUG_PRINTLN(F("Writing final memory update 9/19 (function unknown)...")); + for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); + writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); + DEBUG_PRINTLN(F("Writing final memory update 10/19 (function unknown)...")); + for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); + writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); + DEBUG_PRINTLN(F("Writing final memory update 11/19 (function unknown)...")); + for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); + writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); + + DEBUG_PRINTLN(F("Reading final memory update 12/19 (function unknown)...")); + for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); + readMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); + #ifdef DEBUG + DEBUG_PRINT(F("Read bytes: ")); + for (j = 0; j < 4; j++) { + DEBUG_PRINTF(dmpUpdate[3 + j], HEX); + DEBUG_PRINT(" "); + } + DEBUG_PRINTLN(""); + #endif + + DEBUG_PRINTLN(F("Writing final memory update 13/19 (function unknown)...")); + for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); + writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); + DEBUG_PRINTLN(F("Writing final memory update 14/19 (function unknown)...")); + for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); + writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); + DEBUG_PRINTLN(F("Writing final memory update 15/19 (function unknown)...")); + for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); + writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); + DEBUG_PRINTLN(F("Writing final memory update 16/19 (function unknown)...")); + for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); + writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); + DEBUG_PRINTLN(F("Writing final memory update 17/19 (function unknown)...")); + for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); + writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); + + DEBUG_PRINTLN(F("Waiting for FIRO count >= 46...")); + while ((fifoCount = getFIFOCount()) < 46); + DEBUG_PRINTLN(F("Reading FIFO...")); + getFIFOBytes(fifoBuffer, min(fifoCount, 128)); // safeguard only 128 bytes + DEBUG_PRINTLN(F("Reading interrupt status...")); + getIntStatus(); + + DEBUG_PRINTLN(F("Writing final memory update 18/19 (function unknown)...")); + for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); + writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); + + DEBUG_PRINTLN(F("Waiting for FIRO count >= 48...")); + while ((fifoCount = getFIFOCount()) < 48); + DEBUG_PRINTLN(F("Reading FIFO...")); + getFIFOBytes(fifoBuffer, min(fifoCount, 128)); // safeguard only 128 bytes + DEBUG_PRINTLN(F("Reading interrupt status...")); + getIntStatus(); + DEBUG_PRINTLN(F("Waiting for FIRO count >= 48...")); + while ((fifoCount = getFIFOCount()) < 48); + DEBUG_PRINTLN(F("Reading FIFO...")); + getFIFOBytes(fifoBuffer, min(fifoCount, 128)); // safeguard only 128 bytes + DEBUG_PRINTLN(F("Reading interrupt status...")); + getIntStatus(); + + DEBUG_PRINTLN(F("Writing final memory update 19/19 (function unknown)...")); + for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); + writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); + + DEBUG_PRINTLN(F("Disabling DMP (you turn it on later)...")); + setDMPEnabled(false); + + DEBUG_PRINTLN(F("Setting up internal 48-byte (default) DMP packet buffer...")); + dmpPacketSize = 48; + /*if ((dmpPacketBuffer = (uint8_t *)malloc(42)) == 0) { + return 3; // TODO: proper error code for no memory + }*/ + + DEBUG_PRINTLN(F("Resetting FIFO and clearing INT status one last time...")); + resetFIFO(); + getIntStatus(); + } else { + DEBUG_PRINTLN(F("ERROR! DMP configuration verification failed.")); + return 2; // configuration block loading failed + } + } else { + DEBUG_PRINTLN(F("ERROR! DMP code verification failed.")); + return 1; // main binary block loading failed + } + return 0; // success +} + +bool MPU6050::dmpPacketAvailable() { + return getFIFOCount() >= dmpGetFIFOPacketSize(); +} + +// uint8_t MPU6050::dmpSetFIFORate(uint8_t fifoRate); +// uint8_t MPU6050::dmpGetFIFORate(); +// uint8_t MPU6050::dmpGetSampleStepSizeMS(); +// uint8_t MPU6050::dmpGetSampleFrequency(); +// int32_t MPU6050::dmpDecodeTemperature(int8_t tempReg); + +//uint8_t MPU6050::dmpRegisterFIFORateProcess(inv_obj_func func, int16_t priority); +//uint8_t MPU6050::dmpUnregisterFIFORateProcess(inv_obj_func func); +//uint8_t MPU6050::dmpRunFIFORateProcesses(); + +// uint8_t MPU6050::dmpSendQuaternion(uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendGyro(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendAccel(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendLinearAccel(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendLinearAccelInWorld(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendControlData(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendSensorData(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendExternalSensorData(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendGravity(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendPacketNumber(uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendQuantizedAccel(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendEIS(uint_fast16_t elements, uint_fast16_t accuracy); + +uint8_t MPU6050::dmpGetAccel(int32_t *data, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + data[0] = (((uint32_t)packet[34] << 24) | ((uint32_t)packet[35] << 16) | ((uint32_t)packet[36] << 8) | packet[37]); + data[1] = (((uint32_t)packet[38] << 24) | ((uint32_t)packet[39] << 16) | ((uint32_t)packet[40] << 8) | packet[41]); + data[2] = (((uint32_t)packet[42] << 24) | ((uint32_t)packet[43] << 16) | ((uint32_t)packet[44] << 8) | packet[45]); + return 0; +} +uint8_t MPU6050::dmpGetAccel(int16_t *data, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + data[0] = (packet[34] << 8) | packet[35]; + data[1] = (packet[38] << 8) | packet[39]; + data[2] = (packet[42] << 8) | packet[43]; + return 0; +} +uint8_t MPU6050::dmpGetAccel(VectorInt16 *v, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + v -> x = (packet[34] << 8) | packet[35]; + v -> y = (packet[38] << 8) | packet[39]; + v -> z = (packet[42] << 8) | packet[43]; + return 0; +} +uint8_t MPU6050::dmpGetQuaternion(int32_t *data, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + data[0] = (((uint32_t)packet[0] << 24) | ((uint32_t)packet[1] << 16) | ((uint32_t)packet[2] << 8) | packet[3]); + data[1] = (((uint32_t)packet[4] << 24) | ((uint32_t)packet[5] << 16) | ((uint32_t)packet[6] << 8) | packet[7]); + data[2] = (((uint32_t)packet[8] << 24) | ((uint32_t)packet[9] << 16) | ((uint32_t)packet[10] << 8) | packet[11]); + data[3] = (((uint32_t)packet[12] << 24) | ((uint32_t)packet[13] << 16) | ((uint32_t)packet[14] << 8) | packet[15]); + return 0; +} +uint8_t MPU6050::dmpGetQuaternion(int16_t *data, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + data[0] = ((packet[0] << 8) | packet[1]); + data[1] = ((packet[4] << 8) | packet[5]); + data[2] = ((packet[8] << 8) | packet[9]); + data[3] = ((packet[12] << 8) | packet[13]); + return 0; +} +uint8_t MPU6050::dmpGetQuaternion(Quaternion *q, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + int16_t qI[4]; + uint8_t status = dmpGetQuaternion(qI, packet); + if (status == 0) { + q -> w = (float)qI[0] / 16384.0f; + q -> x = (float)qI[1] / 16384.0f; + q -> y = (float)qI[2] / 16384.0f; + q -> z = (float)qI[3] / 16384.0f; + return 0; + } + return status; // int16 return value, indicates error if this line is reached +} +// uint8_t MPU6050::dmpGet6AxisQuaternion(long *data, const uint8_t* packet); +// uint8_t MPU6050::dmpGetRelativeQuaternion(long *data, const uint8_t* packet); +uint8_t MPU6050::dmpGetGyro(int32_t *data, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + data[0] = (((uint32_t)packet[16] << 24) | ((uint32_t)packet[17] << 16) | ((uint32_t)packet[18] << 8) | packet[19]); + data[1] = (((uint32_t)packet[20] << 24) | ((uint32_t)packet[21] << 16) | ((uint32_t)packet[22] << 8) | packet[23]); + data[2] = (((uint32_t)packet[24] << 24) | ((uint32_t)packet[25] << 16) | ((uint32_t)packet[26] << 8) | packet[27]); + return 0; +} +uint8_t MPU6050::dmpGetGyro(int16_t *data, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + data[0] = (packet[16] << 8) | packet[17]; + data[1] = (packet[20] << 8) | packet[21]; + data[2] = (packet[24] << 8) | packet[25]; + return 0; +} +uint8_t MPU6050::dmpGetMag(int16_t *data, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + data[0] = (packet[28] << 8) | packet[29]; + data[1] = (packet[30] << 8) | packet[31]; + data[2] = (packet[32] << 8) | packet[33]; + return 0; +} +// uint8_t MPU6050::dmpSetLinearAccelFilterCoefficient(float coef); +// uint8_t MPU6050::dmpGetLinearAccel(long *data, const uint8_t* packet); +uint8_t MPU6050::dmpGetLinearAccel(VectorInt16 *v, VectorInt16 *vRaw, VectorFloat *gravity) { + // get rid of the gravity component (+1g = +4096 in standard DMP FIFO packet) + v -> x = vRaw -> x - gravity -> x*4096; + v -> y = vRaw -> y - gravity -> y*4096; + v -> z = vRaw -> z - gravity -> z*4096; + return 0; +} +// uint8_t MPU6050::dmpGetLinearAccelInWorld(long *data, const uint8_t* packet); +uint8_t MPU6050::dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Quaternion *q) { + // rotate measured 3D acceleration vector into original state + // frame of reference based on orientation quaternion + memcpy(v, vReal, sizeof(VectorInt16)); + v -> rotate(q); + return 0; +} +// uint8_t MPU6050::dmpGetGyroAndAccelSensor(long *data, const uint8_t* packet); +// uint8_t MPU6050::dmpGetGyroSensor(long *data, const uint8_t* packet); +// uint8_t MPU6050::dmpGetControlData(long *data, const uint8_t* packet); +// uint8_t MPU6050::dmpGetTemperature(long *data, const uint8_t* packet); +// uint8_t MPU6050::dmpGetGravity(long *data, const uint8_t* packet); +uint8_t MPU6050::dmpGetGravity(VectorFloat *v, Quaternion *q) { + v -> x = 2 * (q -> x*q -> z - q -> w*q -> y); + v -> y = 2 * (q -> w*q -> x + q -> y*q -> z); + v -> z = q -> w*q -> w - q -> x*q -> x - q -> y*q -> y + q -> z*q -> z; + return 0; +} +// uint8_t MPU6050::dmpGetUnquantizedAccel(long *data, const uint8_t* packet); +// uint8_t MPU6050::dmpGetQuantizedAccel(long *data, const uint8_t* packet); +// uint8_t MPU6050::dmpGetExternalSensorData(long *data, int size, const uint8_t* packet); +// uint8_t MPU6050::dmpGetEIS(long *data, const uint8_t* packet); + +uint8_t MPU6050::dmpGetEuler(float *data, Quaternion *q) { + data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1); // psi + data[1] = -asin(2*q -> x*q -> z + 2*q -> w*q -> y); // theta + data[2] = atan2(2*q -> y*q -> z - 2*q -> w*q -> x, 2*q -> w*q -> w + 2*q -> z*q -> z - 1); // phi + return 0; +} +uint8_t MPU6050::dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity) { + // yaw: (about Z axis) + data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1); + // pitch: (nose up/down, about Y axis) + data[1] = atan(gravity -> x / sqrt(gravity -> y*gravity -> y + gravity -> z*gravity -> z)); + // roll: (tilt left/right, about X axis) + data[2] = atan(gravity -> y / sqrt(gravity -> x*gravity -> x + gravity -> z*gravity -> z)); + return 0; +} + +// uint8_t MPU6050::dmpGetAccelFloat(float *data, const uint8_t* packet); +// uint8_t MPU6050::dmpGetQuaternionFloat(float *data, const uint8_t* packet); + +uint8_t MPU6050::dmpProcessFIFOPacket(const unsigned char *dmpData) { + /*for (uint8_t k = 0; k < dmpPacketSize; k++) { + if (dmpData[k] < 0x10) Serial.print("0"); + Serial.print(dmpData[k], HEX); + Serial.print(" "); + } + Serial.print("\n");*/ + //Serial.println((uint16_t)dmpPacketBuffer); + return 0; +} +uint8_t MPU6050::dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *processed) { + uint8_t status; + uint8_t buf[dmpPacketSize]; + for (uint8_t i = 0; i < numPackets; i++) { + // read packet from FIFO + getFIFOBytes(buf, dmpPacketSize); + + // process packet + if ((status = dmpProcessFIFOPacket(buf)) > 0) return status; + + // increment external process count variable, if supplied + if (processed != 0) *processed++; + } + return 0; +} + +// uint8_t MPU6050::dmpSetFIFOProcessedCallback(void (*func) (void)); + +// uint8_t MPU6050::dmpInitFIFOParam(); +// uint8_t MPU6050::dmpCloseFIFO(); +// uint8_t MPU6050::dmpSetGyroDataSource(uint_fast8_t source); +// uint8_t MPU6050::dmpDecodeQuantizedAccel(); +// uint32_t MPU6050::dmpGetGyroSumOfSquare(); +// uint32_t MPU6050::dmpGetAccelSumOfSquare(); +// void MPU6050::dmpOverrideQuaternion(long *q); +uint16_t MPU6050::dmpGetFIFOPacketSize() { + return dmpPacketSize; +} + +#endif /* _MPU6050_9AXIS_MOTIONAPPS41_H_ */ diff --git a/ESP32_ESP-IDF/components/MPU6050/component.mk b/ESP32_ESP-IDF/components/MPU6050/component.mk new file mode 100644 index 00000000..3d61395f --- /dev/null +++ b/ESP32_ESP-IDF/components/MPU6050/component.mk @@ -0,0 +1,10 @@ +# +# Main component makefile. +# +# This Makefile can be left empty. By default, it will take the sources in the +# src/ directory, compile them and link them into lib(subdirectory_name).a +# in the build directory. This behaviour is entirely configurable, +# please read the ESP-IDF documents if you need to do this. +# + +COMPONENT_ADD_INCLUDEDIRS=. \ No newline at end of file diff --git a/ESP32_ESP-IDF/components/MPU6050/helper_3dmath.h b/ESP32_ESP-IDF/components/MPU6050/helper_3dmath.h new file mode 100644 index 00000000..541f5b95 --- /dev/null +++ b/ESP32_ESP-IDF/components/MPU6050/helper_3dmath.h @@ -0,0 +1,218 @@ +// I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class, 3D math helper +// 6/5/2012 by Jeff Rowberg +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// 2012-06-05 - add 3D math helper file to DMP6 example sketch + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2012 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#ifndef _HELPER_3DMATH_H_ +#define _HELPER_3DMATH_H_ +#include +#include + +class Quaternion { + public: + float w; + float x; + float y; + float z; + + Quaternion() { + w = 1.0f; + x = 0.0f; + y = 0.0f; + z = 0.0f; + } + + Quaternion(float nw, float nx, float ny, float nz) { + w = nw; + x = nx; + y = ny; + z = nz; + } + + Quaternion getProduct(Quaternion q) { + // Quaternion multiplication is defined by: + // (Q1 * Q2).w = (w1w2 - x1x2 - y1y2 - z1z2) + // (Q1 * Q2).x = (w1x2 + x1w2 + y1z2 - z1y2) + // (Q1 * Q2).y = (w1y2 - x1z2 + y1w2 + z1x2) + // (Q1 * Q2).z = (w1z2 + x1y2 - y1x2 + z1w2 + return Quaternion( + w*q.w - x*q.x - y*q.y - z*q.z, // new w + w*q.x + x*q.w + y*q.z - z*q.y, // new x + w*q.y - x*q.z + y*q.w + z*q.x, // new y + w*q.z + x*q.y - y*q.x + z*q.w); // new z + } + + Quaternion getConjugate() { + return Quaternion(w, -x, -y, -z); + } + + float getMagnitude() { + return sqrt(w*w + x*x + y*y + z*z); + } + + void normalize() { + float m = getMagnitude(); + w /= m; + x /= m; + y /= m; + z /= m; + } + + Quaternion getNormalized() { + Quaternion r(w, x, y, z); + r.normalize(); + return r; + } +}; + +class VectorInt16 { + public: + int16_t x; + int16_t y; + int16_t z; + + VectorInt16() { + x = 0; + y = 0; + z = 0; + } + + VectorInt16(int16_t nx, int16_t ny, int16_t nz) { + x = nx; + y = ny; + z = nz; + } + + float getMagnitude() { + return sqrt(x*x + y*y + z*z); + } + + void normalize() { + float m = getMagnitude(); + x /= m; + y /= m; + z /= m; + } + + VectorInt16 getNormalized() { + VectorInt16 r(x, y, z); + r.normalize(); + return r; + } + + void rotate(Quaternion *q) { + // http://www.cprogramming.com/tutorial/3d/quaternions.html + // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/transforms/index.htm + // http://content.gpwiki.org/index.php/OpenGL:Tutorials:Using_Quaternions_to_represent_rotation + // ^ or: http://webcache.googleusercontent.com/search?q=cache:xgJAp3bDNhQJ:content.gpwiki.org/index.php/OpenGL:Tutorials:Using_Quaternions_to_represent_rotation&hl=en&gl=us&strip=1 + + // P_out = q * P_in * conj(q) + // - P_out is the output vector + // - q is the orientation quaternion + // - P_in is the input vector (a*aReal) + // - conj(q) is the conjugate of the orientation quaternion (q=[w,x,y,z], q*=[w,-x,-y,-z]) + Quaternion p(0, x, y, z); + + // quaternion multiplication: q * p, stored back in p + p = q -> getProduct(p); + + // quaternion multiplication: p * conj(q), stored back in p + p = p.getProduct(q -> getConjugate()); + + // p quaternion is now [0, x', y', z'] + x = p.x; + y = p.y; + z = p.z; + } + + VectorInt16 getRotated(Quaternion *q) { + VectorInt16 r(x, y, z); + r.rotate(q); + return r; + } +}; + +class VectorFloat { + public: + float x; + float y; + float z; + + VectorFloat() { + x = 0; + y = 0; + z = 0; + } + + VectorFloat(float nx, float ny, float nz) { + x = nx; + y = ny; + z = nz; + } + + float getMagnitude() { + return sqrt(x*x + y*y + z*z); + } + + void normalize() { + float m = getMagnitude(); + x /= m; + y /= m; + z /= m; + } + + VectorFloat getNormalized() { + VectorFloat r(x, y, z); + r.normalize(); + return r; + } + + void rotate(Quaternion *q) { + Quaternion p(0, x, y, z); + + // quaternion multiplication: q * p, stored back in p + p = q -> getProduct(p); + + // quaternion multiplication: p * conj(q), stored back in p + p = p.getProduct(q -> getConjugate()); + + // p quaternion is now [0, x', y', z'] + x = p.x; + y = p.y; + z = p.z; + } + + VectorFloat getRotated(Quaternion *q) { + VectorFloat r(x, y, z); + r.rotate(q); + return r; + } +}; + +#endif /* _HELPER_3DMATH_H_ */ diff --git a/ESP32_ESP-IDF/main/component.mk b/ESP32_ESP-IDF/main/component.mk new file mode 100644 index 00000000..61f8990c --- /dev/null +++ b/ESP32_ESP-IDF/main/component.mk @@ -0,0 +1,8 @@ +# +# Main component makefile. +# +# This Makefile can be left empty. By default, it will take the sources in the +# src/ directory, compile them and link them into lib(subdirectory_name).a +# in the build directory. This behaviour is entirely configurable, +# please read the ESP-IDF documents if you need to do this. +# diff --git a/ESP32_ESP-IDF/main/example.cpp b/ESP32_ESP-IDF/main/example.cpp new file mode 100644 index 00000000..9a5340c0 --- /dev/null +++ b/ESP32_ESP-IDF/main/example.cpp @@ -0,0 +1,85 @@ +/* + * Display.c + * + * Created on: 14.08.2017 + * Author: darek + */ +#include +#include +#include +#include +#include +#include "mpu6050.h" +#include "MPU6050_6Axis_MotionApps20.h" +#include "sdkconfig.h" + +#define PIN_SDA 22 +#define PIN_CLK 21 + +Quaternion q; // [w, x, y, z] quaternion container +VectorFloat gravity; // [x, y, z] gravity vector +float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector +uint16_t packetSize = 42; // expected DMP packet size (default is 42 bytes) +uint16_t fifoCount; // count of all bytes currently in FIFO +uint8_t fifoBuffer[64]; // FIFO storage buffer +uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU + +void task_initI2C(void *ignore) { + i2c_config_t conf; + conf.mode = I2C_MODE_MASTER; + conf.sda_io_num = (gpio_num_t)PIN_SDA; + conf.scl_io_num = (gpio_num_t)PIN_CLK; + conf.sda_pullup_en = GPIO_PULLUP_ENABLE; + conf.scl_pullup_en = GPIO_PULLUP_ENABLE; + conf.master.clk_speed = 400000; + ESP_ERROR_CHECK(i2c_param_config(I2C_NUM_0, &conf)); + ESP_ERROR_CHECK(i2c_driver_install(I2C_NUM_0, I2C_MODE_MASTER, 0, 0, 0)); + vTaskDelete(NULL); +} + +void task_display(void*){ + MPU6050 mpu = MPU6050(); + mpu.initialize(); + mpu.dmpInitialize(); + + // This need to be setup individually + mpu.setXGyroOffset(220); + mpu.setYGyroOffset(76); + mpu.setZGyroOffset(-85); + mpu.setZAccelOffset(1788); + + mpu.setDMPEnabled(true); + + while(1){ + mpuIntStatus = mpu.getIntStatus(); + // get current FIFO count + fifoCount = mpu.getFIFOCount(); + + if ((mpuIntStatus & 0x10) || fifoCount == 1024) { + // reset so we can continue cleanly + mpu.resetFIFO(); + + // otherwise, check for DMP data ready interrupt frequently) + } else if (mpuIntStatus & 0x02) { + // wait for correct available data length, should be a VERY short wait + while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount(); + + // read a packet from FIFO + + mpu.getFIFOBytes(fifoBuffer, packetSize); + mpu.dmpGetQuaternion(&q, fifoBuffer); + mpu.dmpGetGravity(&gravity, &q); + mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); + printf("YAW: %3.1f, ", ypr[0] * 180/M_PI); + printf("PITCH: %3.1f, ", ypr[1] * 180/M_PI); + printf("ROLL: %3.1f \n", ypr[2] * 180/M_PI); + } + + //Best result is to match with DMP refresh rate + // Its last value in components/MPU6050/MPU6050_6Axis_MotionApps20.h file line 310 + // Now its 0x13, which means DMP is refreshed with 10Hz rate + vTaskDelay(100/portTICK_PERIOD_MS); + } + + vTaskDelete(NULL); +} diff --git a/ESP32_ESP-IDF/main/main.cpp b/ESP32_ESP-IDF/main/main.cpp new file mode 100644 index 00000000..9714a3d8 --- /dev/null +++ b/ESP32_ESP-IDF/main/main.cpp @@ -0,0 +1,17 @@ +#include "freertos/FreeRTOS.h" +#include "sdkconfig.h" +#include "freertos/task.h" + +extern "C" { + void app_main(void); +} + +extern void task_initI2C(void*); +extern void task_display(void*); + +void app_main(void) +{ + xTaskCreate(&task_initI2C, "mpu_task", 2048, NULL, 5, NULL); + vTaskDelay(500/portTICK_PERIOD_MS); + xTaskCreate(&task_display, "disp_task", 8192, NULL, 5, NULL); +} diff --git a/ESP32_ESP-IDF/sdkconfig b/ESP32_ESP-IDF/sdkconfig new file mode 100644 index 00000000..b26c6997 --- /dev/null +++ b/ESP32_ESP-IDF/sdkconfig @@ -0,0 +1,424 @@ +# +# Automatically generated file; DO NOT EDIT. +# Espressif IoT Development Framework Configuration +# + +# +# SDK tool configuration +# +CONFIG_TOOLPREFIX="xtensa-esp32-elf-" +CONFIG_PYTHON="python" + +# +# Bootloader config +# +# CONFIG_LOG_BOOTLOADER_LEVEL_NONE is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_ERROR is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_WARN is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_INFO is not set +CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG=y +# CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE is not set +CONFIG_LOG_BOOTLOADER_LEVEL=4 + +# +# Security features +# +# CONFIG_SECURE_BOOT_ENABLED is not set +# CONFIG_FLASH_ENCRYPTION_ENABLED is not set + +# +# Serial flasher config +# +CONFIG_ESPTOOLPY_PORT="com3" +# CONFIG_ESPTOOLPY_BAUD_115200B is not set +# CONFIG_ESPTOOLPY_BAUD_230400B is not set +CONFIG_ESPTOOLPY_BAUD_921600B=y +# CONFIG_ESPTOOLPY_BAUD_2MB is not set +# CONFIG_ESPTOOLPY_BAUD_OTHER is not set +CONFIG_ESPTOOLPY_BAUD_OTHER_VAL=115200 +CONFIG_ESPTOOLPY_BAUD=921600 +# CONFIG_ESPTOOLPY_COMPRESSED is not set +# CONFIG_FLASHMODE_QIO is not set +# CONFIG_FLASHMODE_QOUT is not set +CONFIG_FLASHMODE_DIO=y +# CONFIG_FLASHMODE_DOUT is not set +CONFIG_ESPTOOLPY_FLASHMODE="dio" +# CONFIG_ESPTOOLPY_FLASHFREQ_80M is not set +CONFIG_ESPTOOLPY_FLASHFREQ_40M=y +# CONFIG_ESPTOOLPY_FLASHFREQ_26M is not set +# CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set +CONFIG_ESPTOOLPY_FLASHFREQ="40m" +# CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_2MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y +# CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE="4MB" +CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y +CONFIG_ESPTOOLPY_BEFORE_RESET=y +# CONFIG_ESPTOOLPY_BEFORE_NORESET is not set +CONFIG_ESPTOOLPY_BEFORE="default_reset" +CONFIG_ESPTOOLPY_AFTER_RESET=y +# CONFIG_ESPTOOLPY_AFTER_NORESET is not set +CONFIG_ESPTOOLPY_AFTER="hard_reset" +# CONFIG_MONITOR_BAUD_9600B is not set +# CONFIG_MONITOR_BAUD_57600B is not set +CONFIG_MONITOR_BAUD_115200B=y +# CONFIG_MONITOR_BAUD_230400B is not set +# CONFIG_MONITOR_BAUD_921600B is not set +# CONFIG_MONITOR_BAUD_2MB is not set +# CONFIG_MONITOR_BAUD_OTHER is not set +CONFIG_MONITOR_BAUD_OTHER_VAL=115200 +CONFIG_MONITOR_BAUD=115200 + +# +# Partition Table +# +CONFIG_PARTITION_TABLE_SINGLE_APP=y +# CONFIG_PARTITION_TABLE_TWO_OTA is not set +# CONFIG_PARTITION_TABLE_CUSTOM is not set +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_CUSTOM_APP_BIN_OFFSET=0x10000 +CONFIG_PARTITION_TABLE_FILENAME="partitions_singleapp.csv" +CONFIG_APP_OFFSET=0x10000 + +# +# Compiler options +# +CONFIG_OPTIMIZATION_LEVEL_DEBUG=y +# CONFIG_OPTIMIZATION_LEVEL_RELEASE is not set +CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y +# CONFIG_OPTIMIZATION_ASSERTIONS_SILENT is not set +# CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED is not set + +# +# Component config +# + +# +# Application Level Tracing +# +# CONFIG_ESP32_APPTRACE_DEST_TRAX is not set +CONFIG_ESP32_APPTRACE_DEST_NONE=y +# CONFIG_ESP32_APPTRACE_ENABLE is not set +CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y + +# +# FreeRTOS SystemView Tracing +# +# CONFIG_AWS_IOT_SDK is not set +# CONFIG_BT_ENABLED is not set +CONFIG_BT_RESERVE_DRAM=0 + +# +# ESP32-specific +# +# CONFIG_ESP32_DEFAULT_CPU_FREQ_80 is not set +# CONFIG_ESP32_DEFAULT_CPU_FREQ_160 is not set +CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y +CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=240 +# CONFIG_MEMMAP_SMP is not set +# CONFIG_MEMMAP_TRACEMEM is not set +# CONFIG_MEMMAP_TRACEMEM_TWOBANKS is not set +# CONFIG_ESP32_TRAX is not set +CONFIG_TRACEMEM_RESERVE_DRAM=0x0 +# CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH is not set +# CONFIG_ESP32_ENABLE_COREDUMP_TO_UART is not set +CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE=y +# CONFIG_ESP32_ENABLE_COREDUMP is not set +# CONFIG_TWO_UNIVERSAL_MAC_ADDRESS is not set +CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS=y +CONFIG_NUMBER_OF_UNIVERSAL_MAC_ADDRESS=4 +CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32 +CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=4096 +CONFIG_MAIN_TASK_STACK_SIZE=4096 +CONFIG_IPC_TASK_STACK_SIZE=1024 +CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF=y +# CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF is not set +# CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR is not set +# CONFIG_NEWLIB_STDIN_LINE_ENDING_CRLF is not set +# CONFIG_NEWLIB_STDIN_LINE_ENDING_LF is not set +CONFIG_NEWLIB_STDIN_LINE_ENDING_CR=y +# CONFIG_NEWLIB_NANO_FORMAT is not set +CONFIG_CONSOLE_UART_DEFAULT=y +# CONFIG_CONSOLE_UART_CUSTOM is not set +# CONFIG_CONSOLE_UART_NONE is not set +CONFIG_CONSOLE_UART_NUM=0 +CONFIG_CONSOLE_UART_BAUDRATE=115200 +# CONFIG_ULP_COPROC_ENABLED is not set +CONFIG_ULP_COPROC_RESERVE_MEM=0 +# CONFIG_ESP32_PANIC_PRINT_HALT is not set +# CONFIG_ESP32_PANIC_PRINT_REBOOT is not set +# CONFIG_ESP32_PANIC_SILENT_REBOOT is not set +CONFIG_ESP32_PANIC_GDBSTUB=y +CONFIG_ESP32_DEBUG_OCDAWARE=y +CONFIG_INT_WDT=y +CONFIG_INT_WDT_TIMEOUT_MS=300 +CONFIG_TASK_WDT=y +# CONFIG_TASK_WDT_PANIC is not set +CONFIG_TASK_WDT_TIMEOUT_S=5 +CONFIG_TASK_WDT_CHECK_IDLE_TASK=y +CONFIG_BROWNOUT_DET=y +CONFIG_BROWNOUT_DET_LVL_SEL_0=y +# CONFIG_BROWNOUT_DET_LVL_SEL_1 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_2 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_3 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_4 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_5 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_6 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_7 is not set +CONFIG_BROWNOUT_DET_LVL=0 +# CONFIG_ESP32_TIME_SYSCALL_USE_RTC is not set +CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1=y +# CONFIG_ESP32_TIME_SYSCALL_USE_FRC1 is not set +# CONFIG_ESP32_TIME_SYSCALL_USE_NONE is not set +CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC=y +# CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL is not set +CONFIG_ESP32_RTC_CLK_CAL_CYCLES=1024 +CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY=2000 +# CONFIG_ESP32_XTAL_FREQ_40 is not set +# CONFIG_ESP32_XTAL_FREQ_26 is not set +CONFIG_ESP32_XTAL_FREQ_AUTO=y +CONFIG_ESP32_XTAL_FREQ=0 +# CONFIG_NO_BLOBS is not set + +# +# Wi-Fi +# +CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=10 +CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=32 +# CONFIG_ESP32_WIFI_STATIC_TX_BUFFER is not set +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER=y +CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=1 +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=32 +CONFIG_ESP32_WIFI_AMPDU_ENABLED=y +CONFIG_ESP32_WIFI_TX_BA_WIN=6 +CONFIG_ESP32_WIFI_RX_BA_WIN=6 +CONFIG_ESP32_WIFI_NVS_ENABLED=y + +# +# PHY +# +CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE=y +# CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION is not set +CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER=20 +CONFIG_ESP32_PHY_MAX_TX_POWER=20 + +# +# ETHERNET +# +CONFIG_DMA_RX_BUF_NUM=10 +CONFIG_DMA_TX_BUF_NUM=10 +# CONFIG_EMAC_L2_TO_L3_RX_BUF_MODE is not set +CONFIG_EMAC_TASK_PRIORITY=20 + +# +# FAT Filesystem support +# +CONFIG_FATFS_CODEPAGE_ASCII=y +# CONFIG_FATFS_CODEPAGE_437 is not set +# CONFIG_FATFS_CODEPAGE_720 is not set +# CONFIG_FATFS_CODEPAGE_737 is not set +# CONFIG_FATFS_CODEPAGE_771 is not set +# CONFIG_FATFS_CODEPAGE_775 is not set +# CONFIG_FATFS_CODEPAGE_850 is not set +# CONFIG_FATFS_CODEPAGE_852 is not set +# CONFIG_FATFS_CODEPAGE_855 is not set +# CONFIG_FATFS_CODEPAGE_857 is not set +# CONFIG_FATFS_CODEPAGE_860 is not set +# CONFIG_FATFS_CODEPAGE_861 is not set +# CONFIG_FATFS_CODEPAGE_862 is not set +# CONFIG_FATFS_CODEPAGE_863 is not set +# CONFIG_FATFS_CODEPAGE_864 is not set +# CONFIG_FATFS_CODEPAGE_865 is not set +# CONFIG_FATFS_CODEPAGE_866 is not set +# CONFIG_FATFS_CODEPAGE_869 is not set +# CONFIG_FATFS_CODEPAGE_932 is not set +# CONFIG_FATFS_CODEPAGE_936 is not set +# CONFIG_FATFS_CODEPAGE_949 is not set +# CONFIG_FATFS_CODEPAGE_950 is not set +CONFIG_FATFS_CODEPAGE=1 +CONFIG_FATFS_MAX_LFN=255 + +# +# FreeRTOS +# +CONFIG_FREERTOS_UNICORE=y +CONFIG_FREERTOS_CORETIMER_0=y +# CONFIG_FREERTOS_CORETIMER_1 is not set +CONFIG_FREERTOS_HZ=1000 +CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y +# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE is not set +# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL is not set +CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY=y +# CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK is not set +CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=1 +# CONFIG_FREERTOS_ASSERT_FAIL_ABORT is not set +CONFIG_FREERTOS_ASSERT_FAIL_PRINT_CONTINUE=y +# CONFIG_FREERTOS_ASSERT_DISABLE is not set +# CONFIG_FREERTOS_BREAK_ON_SCHEDULER_START_JTAG is not set +# CONFIG_ENABLE_MEMORY_DEBUG is not set +CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1024 +CONFIG_FREERTOS_ISR_STACKSIZE=1536 +# CONFIG_FREERTOS_LEGACY_HOOKS is not set +CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16 +# CONFIG_SUPPORT_STATIC_ALLOCATION is not set +CONFIG_TIMER_TASK_PRIORITY=1 +CONFIG_TIMER_TASK_STACK_DEPTH=2048 +CONFIG_TIMER_QUEUE_LENGTH=10 +# CONFIG_FREERTOS_DEBUG_INTERNALS is not set + +# +# Log output +# +# CONFIG_LOG_DEFAULT_LEVEL_NONE is not set +# CONFIG_LOG_DEFAULT_LEVEL_ERROR is not set +# CONFIG_LOG_DEFAULT_LEVEL_WARN is not set +CONFIG_LOG_DEFAULT_LEVEL_INFO=y +# CONFIG_LOG_DEFAULT_LEVEL_DEBUG is not set +# CONFIG_LOG_DEFAULT_LEVEL_VERBOSE is not set +CONFIG_LOG_DEFAULT_LEVEL=3 +CONFIG_LOG_COLORS=y + +# +# LWIP +# +# CONFIG_L2_TO_L3_COPY is not set +CONFIG_LWIP_MAX_SOCKETS=10 +CONFIG_LWIP_THREAD_LOCAL_STORAGE_INDEX=0 +# CONFIG_LWIP_SO_REUSE is not set +# CONFIG_LWIP_SO_RCVBUF is not set +CONFIG_LWIP_DHCP_MAX_NTP_SERVERS=1 +# CONFIG_LWIP_IP_FRAG is not set +# CONFIG_LWIP_IP_REASSEMBLY is not set + +# +# TCP +# +CONFIG_TCP_MAXRTX=12 +CONFIG_TCP_SYNMAXRTX=6 +CONFIG_TCP_MSS=1436 +CONFIG_TCP_SND_BUF_DEFAULT=5744 +CONFIG_TCP_WND_DEFAULT=5744 +CONFIG_TCP_RECVMBOX_SIZE=6 +CONFIG_TCP_QUEUE_OOSEQ=y +CONFIG_TCP_OVERSIZE_MSS=y +# CONFIG_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_TCP_OVERSIZE_DISABLE is not set + +# +# UDP +# +CONFIG_UDP_RECVMBOX_SIZE=6 +CONFIG_LWIP_DHCP_DOES_ARP_CHECK=y +CONFIG_TCPIP_TASK_STACK_SIZE=2560 +# CONFIG_PPP_SUPPORT is not set + +# +# ICMP +# +# CONFIG_LWIP_MULTICAST_PING is not set +# CONFIG_LWIP_BROADCAST_PING is not set + +# +# mbedTLS +# +CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=16384 +# CONFIG_MBEDTLS_DEBUG is not set +CONFIG_MBEDTLS_HARDWARE_AES=y +CONFIG_MBEDTLS_HARDWARE_MPI=y +CONFIG_MBEDTLS_MPI_USE_INTERRUPT=y +CONFIG_MBEDTLS_HARDWARE_SHA=y +CONFIG_MBEDTLS_HAVE_TIME=y +# CONFIG_MBEDTLS_HAVE_TIME_DATE is not set +CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT=y +# CONFIG_MBEDTLS_TLS_SERVER_ONLY is not set +# CONFIG_MBEDTLS_TLS_CLIENT_ONLY is not set +# CONFIG_MBEDTLS_TLS_DISABLED is not set +CONFIG_MBEDTLS_TLS_SERVER=y +CONFIG_MBEDTLS_TLS_CLIENT=y +CONFIG_MBEDTLS_TLS_ENABLED=y + +# +# TLS Key Exchange Methods +# +# CONFIG_MBEDTLS_PSK_MODES is not set +CONFIG_MBEDTLS_KEY_EXCHANGE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA=y +CONFIG_MBEDTLS_SSL_RENEGOTIATION=y +# CONFIG_MBEDTLS_SSL_PROTO_SSL3 is not set +CONFIG_MBEDTLS_SSL_PROTO_TLS1=y +CONFIG_MBEDTLS_SSL_PROTO_TLS1_1=y +CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y +# CONFIG_MBEDTLS_SSL_PROTO_DTLS is not set +CONFIG_MBEDTLS_SSL_ALPN=y +CONFIG_MBEDTLS_SSL_SESSION_TICKETS=y + +# +# Symmetric Ciphers +# +CONFIG_MBEDTLS_AES_C=y +# CONFIG_MBEDTLS_CAMELLIA_C is not set +# CONFIG_MBEDTLS_DES_C is not set +CONFIG_MBEDTLS_RC4_DISABLED=y +# CONFIG_MBEDTLS_RC4_ENABLED_NO_DEFAULT is not set +# CONFIG_MBEDTLS_RC4_ENABLED is not set +# CONFIG_MBEDTLS_BLOWFISH_C is not set +# CONFIG_MBEDTLS_XTEA_C is not set +CONFIG_MBEDTLS_CCM_C=y +CONFIG_MBEDTLS_GCM_C=y +# CONFIG_MBEDTLS_RIPEMD160_C is not set + +# +# Certificates +# +CONFIG_MBEDTLS_PEM_PARSE_C=y +CONFIG_MBEDTLS_PEM_WRITE_C=y +CONFIG_MBEDTLS_X509_CRL_PARSE_C=y +CONFIG_MBEDTLS_X509_CSR_PARSE_C=y +CONFIG_MBEDTLS_ECP_C=y +CONFIG_MBEDTLS_ECDH_C=y +CONFIG_MBEDTLS_ECDSA_C=y +CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED=y +CONFIG_MBEDTLS_ECP_NIST_OPTIM=y + +# +# OpenSSL +# +# CONFIG_OPENSSL_DEBUG is not set +CONFIG_OPENSSL_ASSERT_DO_NOTHING=y +# CONFIG_OPENSSL_ASSERT_EXIT is not set + +# +# SPI Flash driver +# +# CONFIG_SPI_FLASH_ENABLE_COUNTERS is not set +CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y + +# +# tcpip adapter +# +CONFIG_IP_LOST_TIMER_INTERVAL=120 + +# +# Wear Levelling +# +# CONFIG_WL_SECTOR_SIZE_512 is not set +CONFIG_WL_SECTOR_SIZE_4096=y +CONFIG_WL_SECTOR_SIZE=4096 diff --git a/ESP32_ESP-IDF/sdkconfig.old b/ESP32_ESP-IDF/sdkconfig.old new file mode 100644 index 00000000..9d0442cc --- /dev/null +++ b/ESP32_ESP-IDF/sdkconfig.old @@ -0,0 +1,433 @@ +# +# Automatically generated file; DO NOT EDIT. +# Espressif IoT Development Framework Configuration +# + +# +# SDK tool configuration +# +CONFIG_TOOLPREFIX="xtensa-esp32-elf-" +CONFIG_PYTHON="python" + +# +# Bootloader config +# +# CONFIG_LOG_BOOTLOADER_LEVEL_NONE is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_ERROR is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_WARN is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_INFO is not set +CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG=y +# CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE is not set +CONFIG_LOG_BOOTLOADER_LEVEL=4 + +# +# Security features +# +# CONFIG_SECURE_BOOT_ENABLED is not set +# CONFIG_FLASH_ENCRYPTION_ENABLED is not set + +# +# Serial flasher config +# +CONFIG_ESPTOOLPY_PORT="com3" +# CONFIG_ESPTOOLPY_BAUD_115200B is not set +# CONFIG_ESPTOOLPY_BAUD_230400B is not set +CONFIG_ESPTOOLPY_BAUD_921600B=y +# CONFIG_ESPTOOLPY_BAUD_2MB is not set +# CONFIG_ESPTOOLPY_BAUD_OTHER is not set +CONFIG_ESPTOOLPY_BAUD_OTHER_VAL=115200 +CONFIG_ESPTOOLPY_BAUD=921600 +# CONFIG_ESPTOOLPY_COMPRESSED is not set +# CONFIG_FLASHMODE_QIO is not set +# CONFIG_FLASHMODE_QOUT is not set +CONFIG_FLASHMODE_DIO=y +# CONFIG_FLASHMODE_DOUT is not set +CONFIG_ESPTOOLPY_FLASHMODE="dio" +# CONFIG_ESPTOOLPY_FLASHFREQ_80M is not set +CONFIG_ESPTOOLPY_FLASHFREQ_40M=y +# CONFIG_ESPTOOLPY_FLASHFREQ_26M is not set +# CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set +CONFIG_ESPTOOLPY_FLASHFREQ="40m" +# CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_2MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y +# CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE="4MB" +CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y +CONFIG_ESPTOOLPY_BEFORE_RESET=y +# CONFIG_ESPTOOLPY_BEFORE_NORESET is not set +CONFIG_ESPTOOLPY_BEFORE="default_reset" +CONFIG_ESPTOOLPY_AFTER_RESET=y +# CONFIG_ESPTOOLPY_AFTER_NORESET is not set +CONFIG_ESPTOOLPY_AFTER="hard_reset" +# CONFIG_MONITOR_BAUD_9600B is not set +# CONFIG_MONITOR_BAUD_57600B is not set +CONFIG_MONITOR_BAUD_115200B=y +# CONFIG_MONITOR_BAUD_230400B is not set +# CONFIG_MONITOR_BAUD_921600B is not set +# CONFIG_MONITOR_BAUD_2MB is not set +# CONFIG_MONITOR_BAUD_OTHER is not set +CONFIG_MONITOR_BAUD_OTHER_VAL=115200 +CONFIG_MONITOR_BAUD=115200 + +# +# Partition Table +# +CONFIG_PARTITION_TABLE_SINGLE_APP=y +# CONFIG_PARTITION_TABLE_TWO_OTA is not set +# CONFIG_PARTITION_TABLE_CUSTOM is not set +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_CUSTOM_APP_BIN_OFFSET=0x10000 +CONFIG_PARTITION_TABLE_FILENAME="partitions_singleapp.csv" +CONFIG_APP_OFFSET=0x10000 + +# +# Compiler options +# +CONFIG_OPTIMIZATION_LEVEL_DEBUG=y +# CONFIG_OPTIMIZATION_LEVEL_RELEASE is not set +CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y +# CONFIG_OPTIMIZATION_ASSERTIONS_SILENT is not set +# CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED is not set + +# +# Component config +# + +# +# SSD1331 configuration +# +CONFIG_HW_LCD_MOSI_GPIO=23 +CONFIG_HW_LCD_CLK_GPIO=18 +CONFIG_HW_LCD_CS_GPIO=5 +CONFIG_HW_LCD_DC_GPIO=16 +CONFIG_HW_LCD_RESET_GPIO=17 + +# +# Application Level Tracing +# +# CONFIG_ESP32_APPTRACE_DEST_TRAX is not set +CONFIG_ESP32_APPTRACE_DEST_NONE=y +# CONFIG_ESP32_APPTRACE_ENABLE is not set +CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y + +# +# FreeRTOS SystemView Tracing +# +# CONFIG_AWS_IOT_SDK is not set +# CONFIG_BT_ENABLED is not set +CONFIG_BT_RESERVE_DRAM=0 + +# +# ESP32-specific +# +# CONFIG_ESP32_DEFAULT_CPU_FREQ_80 is not set +# CONFIG_ESP32_DEFAULT_CPU_FREQ_160 is not set +CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y +CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=240 +# CONFIG_MEMMAP_SMP is not set +# CONFIG_MEMMAP_TRACEMEM is not set +# CONFIG_MEMMAP_TRACEMEM_TWOBANKS is not set +# CONFIG_ESP32_TRAX is not set +CONFIG_TRACEMEM_RESERVE_DRAM=0x0 +# CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH is not set +# CONFIG_ESP32_ENABLE_COREDUMP_TO_UART is not set +CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE=y +# CONFIG_ESP32_ENABLE_COREDUMP is not set +# CONFIG_TWO_UNIVERSAL_MAC_ADDRESS is not set +CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS=y +CONFIG_NUMBER_OF_UNIVERSAL_MAC_ADDRESS=4 +CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32 +CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=4096 +CONFIG_MAIN_TASK_STACK_SIZE=4096 +CONFIG_IPC_TASK_STACK_SIZE=1024 +CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF=y +# CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF is not set +# CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR is not set +# CONFIG_NEWLIB_STDIN_LINE_ENDING_CRLF is not set +# CONFIG_NEWLIB_STDIN_LINE_ENDING_LF is not set +CONFIG_NEWLIB_STDIN_LINE_ENDING_CR=y +# CONFIG_NEWLIB_NANO_FORMAT is not set +CONFIG_CONSOLE_UART_DEFAULT=y +# CONFIG_CONSOLE_UART_CUSTOM is not set +# CONFIG_CONSOLE_UART_NONE is not set +CONFIG_CONSOLE_UART_NUM=0 +CONFIG_CONSOLE_UART_BAUDRATE=115200 +# CONFIG_ULP_COPROC_ENABLED is not set +CONFIG_ULP_COPROC_RESERVE_MEM=0 +# CONFIG_ESP32_PANIC_PRINT_HALT is not set +# CONFIG_ESP32_PANIC_PRINT_REBOOT is not set +# CONFIG_ESP32_PANIC_SILENT_REBOOT is not set +CONFIG_ESP32_PANIC_GDBSTUB=y +CONFIG_ESP32_DEBUG_OCDAWARE=y +CONFIG_INT_WDT=y +CONFIG_INT_WDT_TIMEOUT_MS=300 +CONFIG_TASK_WDT=y +# CONFIG_TASK_WDT_PANIC is not set +CONFIG_TASK_WDT_TIMEOUT_S=5 +CONFIG_TASK_WDT_CHECK_IDLE_TASK=y +CONFIG_BROWNOUT_DET=y +CONFIG_BROWNOUT_DET_LVL_SEL_0=y +# CONFIG_BROWNOUT_DET_LVL_SEL_1 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_2 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_3 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_4 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_5 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_6 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_7 is not set +CONFIG_BROWNOUT_DET_LVL=0 +# CONFIG_ESP32_TIME_SYSCALL_USE_RTC is not set +CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1=y +# CONFIG_ESP32_TIME_SYSCALL_USE_FRC1 is not set +# CONFIG_ESP32_TIME_SYSCALL_USE_NONE is not set +CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC=y +# CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL is not set +CONFIG_ESP32_RTC_CLK_CAL_CYCLES=1024 +CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY=2000 +# CONFIG_ESP32_XTAL_FREQ_40 is not set +# CONFIG_ESP32_XTAL_FREQ_26 is not set +CONFIG_ESP32_XTAL_FREQ_AUTO=y +CONFIG_ESP32_XTAL_FREQ=0 +# CONFIG_NO_BLOBS is not set + +# +# Wi-Fi +# +CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=10 +CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=32 +# CONFIG_ESP32_WIFI_STATIC_TX_BUFFER is not set +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER=y +CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=1 +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=32 +CONFIG_ESP32_WIFI_AMPDU_ENABLED=y +CONFIG_ESP32_WIFI_TX_BA_WIN=6 +CONFIG_ESP32_WIFI_RX_BA_WIN=6 +CONFIG_ESP32_WIFI_NVS_ENABLED=y + +# +# PHY +# +CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE=y +# CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION is not set +CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER=20 +CONFIG_ESP32_PHY_MAX_TX_POWER=20 + +# +# ETHERNET +# +CONFIG_DMA_RX_BUF_NUM=10 +CONFIG_DMA_TX_BUF_NUM=10 +# CONFIG_EMAC_L2_TO_L3_RX_BUF_MODE is not set +CONFIG_EMAC_TASK_PRIORITY=20 + +# +# FAT Filesystem support +# +CONFIG_FATFS_CODEPAGE_ASCII=y +# CONFIG_FATFS_CODEPAGE_437 is not set +# CONFIG_FATFS_CODEPAGE_720 is not set +# CONFIG_FATFS_CODEPAGE_737 is not set +# CONFIG_FATFS_CODEPAGE_771 is not set +# CONFIG_FATFS_CODEPAGE_775 is not set +# CONFIG_FATFS_CODEPAGE_850 is not set +# CONFIG_FATFS_CODEPAGE_852 is not set +# CONFIG_FATFS_CODEPAGE_855 is not set +# CONFIG_FATFS_CODEPAGE_857 is not set +# CONFIG_FATFS_CODEPAGE_860 is not set +# CONFIG_FATFS_CODEPAGE_861 is not set +# CONFIG_FATFS_CODEPAGE_862 is not set +# CONFIG_FATFS_CODEPAGE_863 is not set +# CONFIG_FATFS_CODEPAGE_864 is not set +# CONFIG_FATFS_CODEPAGE_865 is not set +# CONFIG_FATFS_CODEPAGE_866 is not set +# CONFIG_FATFS_CODEPAGE_869 is not set +# CONFIG_FATFS_CODEPAGE_932 is not set +# CONFIG_FATFS_CODEPAGE_936 is not set +# CONFIG_FATFS_CODEPAGE_949 is not set +# CONFIG_FATFS_CODEPAGE_950 is not set +CONFIG_FATFS_CODEPAGE=1 +CONFIG_FATFS_MAX_LFN=255 + +# +# FreeRTOS +# +CONFIG_FREERTOS_UNICORE=y +CONFIG_FREERTOS_CORETIMER_0=y +# CONFIG_FREERTOS_CORETIMER_1 is not set +CONFIG_FREERTOS_HZ=1000 +CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y +# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE is not set +# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL is not set +CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY=y +# CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK is not set +CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=1 +# CONFIG_FREERTOS_ASSERT_FAIL_ABORT is not set +CONFIG_FREERTOS_ASSERT_FAIL_PRINT_CONTINUE=y +# CONFIG_FREERTOS_ASSERT_DISABLE is not set +# CONFIG_FREERTOS_BREAK_ON_SCHEDULER_START_JTAG is not set +# CONFIG_ENABLE_MEMORY_DEBUG is not set +CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1024 +CONFIG_FREERTOS_ISR_STACKSIZE=1536 +# CONFIG_FREERTOS_LEGACY_HOOKS is not set +CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16 +# CONFIG_SUPPORT_STATIC_ALLOCATION is not set +CONFIG_TIMER_TASK_PRIORITY=1 +CONFIG_TIMER_TASK_STACK_DEPTH=2048 +CONFIG_TIMER_QUEUE_LENGTH=10 +# CONFIG_FREERTOS_DEBUG_INTERNALS is not set + +# +# Log output +# +# CONFIG_LOG_DEFAULT_LEVEL_NONE is not set +# CONFIG_LOG_DEFAULT_LEVEL_ERROR is not set +# CONFIG_LOG_DEFAULT_LEVEL_WARN is not set +CONFIG_LOG_DEFAULT_LEVEL_INFO=y +# CONFIG_LOG_DEFAULT_LEVEL_DEBUG is not set +# CONFIG_LOG_DEFAULT_LEVEL_VERBOSE is not set +CONFIG_LOG_DEFAULT_LEVEL=3 +CONFIG_LOG_COLORS=y + +# +# LWIP +# +# CONFIG_L2_TO_L3_COPY is not set +CONFIG_LWIP_MAX_SOCKETS=10 +CONFIG_LWIP_THREAD_LOCAL_STORAGE_INDEX=0 +# CONFIG_LWIP_SO_REUSE is not set +# CONFIG_LWIP_SO_RCVBUF is not set +CONFIG_LWIP_DHCP_MAX_NTP_SERVERS=1 +# CONFIG_LWIP_IP_FRAG is not set +# CONFIG_LWIP_IP_REASSEMBLY is not set + +# +# TCP +# +CONFIG_TCP_MAXRTX=12 +CONFIG_TCP_SYNMAXRTX=6 +CONFIG_TCP_MSS=1436 +CONFIG_TCP_SND_BUF_DEFAULT=5744 +CONFIG_TCP_WND_DEFAULT=5744 +CONFIG_TCP_RECVMBOX_SIZE=6 +CONFIG_TCP_QUEUE_OOSEQ=y +CONFIG_TCP_OVERSIZE_MSS=y +# CONFIG_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_TCP_OVERSIZE_DISABLE is not set + +# +# UDP +# +CONFIG_UDP_RECVMBOX_SIZE=6 +CONFIG_LWIP_DHCP_DOES_ARP_CHECK=y +CONFIG_TCPIP_TASK_STACK_SIZE=2560 +# CONFIG_PPP_SUPPORT is not set + +# +# ICMP +# +# CONFIG_LWIP_MULTICAST_PING is not set +# CONFIG_LWIP_BROADCAST_PING is not set + +# +# mbedTLS +# +CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=16384 +# CONFIG_MBEDTLS_DEBUG is not set +CONFIG_MBEDTLS_HARDWARE_AES=y +CONFIG_MBEDTLS_HARDWARE_MPI=y +CONFIG_MBEDTLS_MPI_USE_INTERRUPT=y +CONFIG_MBEDTLS_HARDWARE_SHA=y +CONFIG_MBEDTLS_HAVE_TIME=y +# CONFIG_MBEDTLS_HAVE_TIME_DATE is not set +CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT=y +# CONFIG_MBEDTLS_TLS_SERVER_ONLY is not set +# CONFIG_MBEDTLS_TLS_CLIENT_ONLY is not set +# CONFIG_MBEDTLS_TLS_DISABLED is not set +CONFIG_MBEDTLS_TLS_SERVER=y +CONFIG_MBEDTLS_TLS_CLIENT=y +CONFIG_MBEDTLS_TLS_ENABLED=y + +# +# TLS Key Exchange Methods +# +# CONFIG_MBEDTLS_PSK_MODES is not set +CONFIG_MBEDTLS_KEY_EXCHANGE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA=y +CONFIG_MBEDTLS_SSL_RENEGOTIATION=y +# CONFIG_MBEDTLS_SSL_PROTO_SSL3 is not set +CONFIG_MBEDTLS_SSL_PROTO_TLS1=y +CONFIG_MBEDTLS_SSL_PROTO_TLS1_1=y +CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y +# CONFIG_MBEDTLS_SSL_PROTO_DTLS is not set +CONFIG_MBEDTLS_SSL_ALPN=y +CONFIG_MBEDTLS_SSL_SESSION_TICKETS=y + +# +# Symmetric Ciphers +# +CONFIG_MBEDTLS_AES_C=y +# CONFIG_MBEDTLS_CAMELLIA_C is not set +# CONFIG_MBEDTLS_DES_C is not set +CONFIG_MBEDTLS_RC4_DISABLED=y +# CONFIG_MBEDTLS_RC4_ENABLED_NO_DEFAULT is not set +# CONFIG_MBEDTLS_RC4_ENABLED is not set +# CONFIG_MBEDTLS_BLOWFISH_C is not set +# CONFIG_MBEDTLS_XTEA_C is not set +CONFIG_MBEDTLS_CCM_C=y +CONFIG_MBEDTLS_GCM_C=y +# CONFIG_MBEDTLS_RIPEMD160_C is not set + +# +# Certificates +# +CONFIG_MBEDTLS_PEM_PARSE_C=y +CONFIG_MBEDTLS_PEM_WRITE_C=y +CONFIG_MBEDTLS_X509_CRL_PARSE_C=y +CONFIG_MBEDTLS_X509_CSR_PARSE_C=y +CONFIG_MBEDTLS_ECP_C=y +CONFIG_MBEDTLS_ECDH_C=y +CONFIG_MBEDTLS_ECDSA_C=y +CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED=y +CONFIG_MBEDTLS_ECP_NIST_OPTIM=y + +# +# OpenSSL +# +# CONFIG_OPENSSL_DEBUG is not set +CONFIG_OPENSSL_ASSERT_DO_NOTHING=y +# CONFIG_OPENSSL_ASSERT_EXIT is not set + +# +# SPI Flash driver +# +# CONFIG_SPI_FLASH_ENABLE_COUNTERS is not set +CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y + +# +# tcpip adapter +# +CONFIG_IP_LOST_TIMER_INTERVAL=120 + +# +# Wear Levelling +# +# CONFIG_WL_SECTOR_SIZE_512 is not set +CONFIG_WL_SECTOR_SIZE_4096=y +CONFIG_WL_SECTOR_SIZE=4096 From 3b4c8bda900958e7732ac42cd867c08862879e99 Mon Sep 17 00:00:00 2001 From: per1234 Date: Sun, 10 Sep 2017 16:48:52 -0700 Subject: [PATCH 178/335] Fix typos in example sketches --- .../ADS1115/examples/ADS1115_single/ADS1115_single.ino | 2 +- .../AK8975_MPUEVB_heading/AK8975_MPUEVB_heading.ino | 2 +- .../examples/AK8975_MPUEVB_raw/AK8975_MPUEVB_raw.ino | 2 +- Arduino/AK8975/examples/AK8975_raw/AK8975_raw.ino | 2 +- Arduino/BMA150/examples/BMA150_raw/BMA150_raw.ino | 2 +- Arduino/HMC5843/examples/HMC5843_raw/HMC5843_raw.ino | 2 +- .../HMC5883L/examples/HMC5883L_raw/HMC5883L_raw.ino | 2 +- Arduino/ITG3200/examples/ITG3200_raw/ITG3200_raw.ino | 2 +- .../examples/LSM303DLHC_test/LSM303DLHC_test.ino | 10 +++++----- Arduino/MPU6050/examples/IMU_Zero/IMU_Zero.ino | 2 +- Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino | 4 ++-- .../MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino | 4 ++-- Arduino/MPU6050/examples/MPU6050_raw/MPU6050_raw.ino | 2 +- Arduino/MPU9150/examples/MPU9150_raw/MPU9150_raw.ino | 2 +- Arduino/MS5803/examples/test_MS5803/test_MS5803.ino | 2 +- 15 files changed, 21 insertions(+), 21 deletions(-) diff --git a/Arduino/ADS1115/examples/ADS1115_single/ADS1115_single.ino b/Arduino/ADS1115/examples/ADS1115_single/ADS1115_single.ino index 015b56f6..4059ac1e 100644 --- a/Arduino/ADS1115/examples/ADS1115_single/ADS1115_single.ino +++ b/Arduino/ADS1115/examples/ADS1115_single/ADS1115_single.ino @@ -53,7 +53,7 @@ void setup() { // Slow things down so that we can see that the "poll for conversion" code works adc0.setRate(ADS1115_RATE_8); - // Set the gain (PGA) +/- 6.144v + // Set the gain (PGA) +/- 6.144V // Note that any analog input must be higher than –0.3V and less than VDD +0.3 adc0.setGain(ADS1115_PGA_6P144); // ALERT/RDY pin will indicate when conversion is ready diff --git a/Arduino/AK8975/examples/AK8975_MPUEVB_heading/AK8975_MPUEVB_heading.ino b/Arduino/AK8975/examples/AK8975_MPUEVB_heading/AK8975_MPUEVB_heading.ino index aef0e807..10a41ad4 100644 --- a/Arduino/AK8975/examples/AK8975_MPUEVB_heading/AK8975_MPUEVB_heading.ino +++ b/Arduino/AK8975/examples/AK8975_MPUEVB_heading/AK8975_MPUEVB_heading.ino @@ -90,7 +90,7 @@ void setup() { Serial.println("Testing device connections..."); Serial.println(mag.testConnection() ? "AK8975 connection successful" : "AK8975 connection failed"); - // configure Arduino LED for + // configure Arduino LED pin for output pinMode(LED_PIN, OUTPUT); } diff --git a/Arduino/AK8975/examples/AK8975_MPUEVB_raw/AK8975_MPUEVB_raw.ino b/Arduino/AK8975/examples/AK8975_MPUEVB_raw/AK8975_MPUEVB_raw.ino index 630833ea..47f415bc 100644 --- a/Arduino/AK8975/examples/AK8975_MPUEVB_raw/AK8975_MPUEVB_raw.ino +++ b/Arduino/AK8975/examples/AK8975_MPUEVB_raw/AK8975_MPUEVB_raw.ino @@ -89,7 +89,7 @@ void setup() { Serial.println("Testing device connections..."); Serial.println(mag.testConnection() ? "AK8975 connection successful" : "AK8975 connection failed"); - // configure Arduino LED for + // configure Arduino LED pin for output pinMode(LED_PIN, OUTPUT); } diff --git a/Arduino/AK8975/examples/AK8975_raw/AK8975_raw.ino b/Arduino/AK8975/examples/AK8975_raw/AK8975_raw.ino index 49a56af0..55a4d411 100644 --- a/Arduino/AK8975/examples/AK8975_raw/AK8975_raw.ino +++ b/Arduino/AK8975/examples/AK8975_raw/AK8975_raw.ino @@ -68,7 +68,7 @@ void setup() { Serial.println("Testing device connections..."); Serial.println(mag.testConnection() ? "AK8975 connection successful" : "AK8975 connection failed"); - // configure Arduino LED for + // configure Arduino LED pin for output pinMode(LED_PIN, OUTPUT); } diff --git a/Arduino/BMA150/examples/BMA150_raw/BMA150_raw.ino b/Arduino/BMA150/examples/BMA150_raw/BMA150_raw.ino index 23fb931d..c5151c91 100644 --- a/Arduino/BMA150/examples/BMA150_raw/BMA150_raw.ino +++ b/Arduino/BMA150/examples/BMA150_raw/BMA150_raw.ino @@ -64,7 +64,7 @@ void setup() { Serial.println("Testing device connections..."); Serial.println(accel.testConnection() ? "BMA150 connection successful" : "BMA150 connection failed"); - // configure Arduino LED for + // configure Arduino LED pin for output pinMode(LED_PIN, OUTPUT); } diff --git a/Arduino/HMC5843/examples/HMC5843_raw/HMC5843_raw.ino b/Arduino/HMC5843/examples/HMC5843_raw/HMC5843_raw.ino index 7c45f108..e222c822 100644 --- a/Arduino/HMC5843/examples/HMC5843_raw/HMC5843_raw.ino +++ b/Arduino/HMC5843/examples/HMC5843_raw/HMC5843_raw.ino @@ -65,7 +65,7 @@ void setup() { Serial.println("Testing device connections..."); Serial.println(mag.testConnection() ? "HMC5843 connection successful" : "HMC5843 connection failed"); - // configure Arduino LED for + // configure Arduino LED pin for output pinMode(LED_PIN, OUTPUT); } diff --git a/Arduino/HMC5883L/examples/HMC5883L_raw/HMC5883L_raw.ino b/Arduino/HMC5883L/examples/HMC5883L_raw/HMC5883L_raw.ino index 0d346067..0ab1b152 100644 --- a/Arduino/HMC5883L/examples/HMC5883L_raw/HMC5883L_raw.ino +++ b/Arduino/HMC5883L/examples/HMC5883L_raw/HMC5883L_raw.ino @@ -66,7 +66,7 @@ void setup() { Serial.println("Testing device connections..."); Serial.println(mag.testConnection() ? "HMC5883L connection successful" : "HMC5883L connection failed"); - // configure Arduino LED for + // configure Arduino LED pin for output pinMode(LED_PIN, OUTPUT); } diff --git a/Arduino/ITG3200/examples/ITG3200_raw/ITG3200_raw.ino b/Arduino/ITG3200/examples/ITG3200_raw/ITG3200_raw.ino index f4bd7292..02a8476b 100644 --- a/Arduino/ITG3200/examples/ITG3200_raw/ITG3200_raw.ino +++ b/Arduino/ITG3200/examples/ITG3200_raw/ITG3200_raw.ino @@ -66,7 +66,7 @@ void setup() { Serial.println("Testing device connections..."); Serial.println(gyro.testConnection() ? "ITG3200 connection successful" : "ITG3200 connection failed"); - // configure Arduino LED for + // configure Arduino LED pin for output pinMode(LED_PIN, OUTPUT); } diff --git a/Arduino/LSM303DLHC/examples/LSM303DLHC_test/LSM303DLHC_test.ino b/Arduino/LSM303DLHC/examples/LSM303DLHC_test/LSM303DLHC_test.ino index cea4e149..463c25d7 100644 --- a/Arduino/LSM303DLHC/examples/LSM303DLHC_test/LSM303DLHC_test.ino +++ b/Arduino/LSM303DLHC/examples/LSM303DLHC_test/LSM303DLHC_test.ino @@ -71,7 +71,7 @@ void setup() { // set scale to 2Gs accelMag.setAccelFullScale(2); - // set accel data rate to 200hz + // set accel data rate to 200Hz accelMag.setAccelOutputDataRate(200); // test scale @@ -82,7 +82,7 @@ void setup() { Serial.print("Accel Output Data Rate: "); Serial.println(accelMag.getAccelOutputDataRate()); - // set mag data rate to 220hz + // set mag data rate to 220Hz accelMag.setMagOutputDataRate(220); // test mag data rate @@ -108,7 +108,7 @@ void loop() { accelMag.getAcceleration(&ax, &ay, &az); accelMag.getMag(&mx, &my, &mz); - // Serial.print("Accelation:\t"); + // Serial.print("Acceleration:\t"); // Serial.print(ax,HEX); Serial.print("\t"); // Serial.print(ay,HEX); Serial.print("\t"); // Serial.print(az,HEX); @@ -118,7 +118,7 @@ void loop() { // Serial.print(my,HEX); Serial.print("\t"); // Serial.println(mz,HEX); - // Serial.print("Accelation:\t"); + // Serial.print("Acceleration:\t"); // Serial.print(ax); Serial.print("\t"); // Serial.print(ay); Serial.print("\t"); // Serial.print(az); @@ -128,7 +128,7 @@ void loop() { // Serial.print(my); Serial.print("\t"); // Serial.println(mz); - Serial.print("Accelation:\t"); + Serial.print("Acceleration:\t"); Serial.print(ax*0.0000625F,4); Serial.print("\t"); Serial.print(ay*0.0000625F,4); Serial.print("\t"); Serial.print(az*0.0000625F,4); diff --git a/Arduino/MPU6050/examples/IMU_Zero/IMU_Zero.ino b/Arduino/MPU6050/examples/IMU_Zero/IMU_Zero.ino index 2a68983b..0a5d27b2 100644 --- a/Arduino/MPU6050/examples/IMU_Zero/IMU_Zero.ino +++ b/Arduino/MPU6050/examples/IMU_Zero/IMU_Zero.ino @@ -49,7 +49,7 @@ Z acceleration, for which it will report 16384 (that is, 2^14). Your device probably won't do quite this well, but good offsets will all get the baseline outputs close to these target values. - Put the MPU6050 in a flat and horizontal surface, and leave it operating for + Put the MPU6050 on a flat and horizontal surface, and leave it operating for 5-10 minutes so its temperature gets stabilized. Run this program. A "----- done -----" line will indicate that it has done its best. diff --git a/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino b/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino index d755665a..02a4e0d8 100644 --- a/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino +++ b/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino @@ -174,8 +174,8 @@ void setup() { Serial.begin(115200); while (!Serial); // wait for Leonardo enumeration, others continue immediately - // NOTE: 8MHz or slower host processors, like the Teensy @ 3.3v or Ardunio - // Pro Mini running at 3.3v, cannot handle this baud rate reliably due to + // NOTE: 8MHz or slower host processors, like the Teensy @ 3.3V or Arduino + // Pro Mini running at 3.3V, cannot handle this baud rate reliably due to // the baud timing being too misaligned with processor ticks. You must use // 38400 or slower in these cases, or use some kind of external separate // crystal solution for the UART timer. diff --git a/Arduino/MPU6050/examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino b/Arduino/MPU6050/examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino index 9641d72c..8ea3e11f 100644 --- a/Arduino/MPU6050/examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino +++ b/Arduino/MPU6050/examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino @@ -180,8 +180,8 @@ void setup() { // (115200 chosen because it is required for Teapot Demo output, but it's // really up to you depending on your project) Serial.begin(115200); - // NOTE: 8MHz or slower host processors, like the Teensy @ 3.3v or Ardunio - // Pro Mini running at 3.3v, cannot handle this baud rate reliably due to + // NOTE: 8MHz or slower host processors, like the Teensy @ 3.3V or Arduino + // Pro Mini running at 3.3V, cannot handle this baud rate reliably due to // the baud timing being too misaligned with processor ticks. You must use // 38400 or slower in these cases, or use some kind of external separate // crystal solution for the UART timer. diff --git a/Arduino/MPU6050/examples/MPU6050_raw/MPU6050_raw.ino b/Arduino/MPU6050/examples/MPU6050_raw/MPU6050_raw.ino index 28418a96..9d5be00d 100644 --- a/Arduino/MPU6050/examples/MPU6050_raw/MPU6050_raw.ino +++ b/Arduino/MPU6050/examples/MPU6050_raw/MPU6050_raw.ino @@ -113,7 +113,7 @@ void setup() { Serial.print("\n"); */ - // configure Arduino LED for + // configure Arduino LED pin for output pinMode(LED_PIN, OUTPUT); } diff --git a/Arduino/MPU9150/examples/MPU9150_raw/MPU9150_raw.ino b/Arduino/MPU9150/examples/MPU9150_raw/MPU9150_raw.ino index e2c9224c..3fdcbb4b 100644 --- a/Arduino/MPU9150/examples/MPU9150_raw/MPU9150_raw.ino +++ b/Arduino/MPU9150/examples/MPU9150_raw/MPU9150_raw.ino @@ -69,7 +69,7 @@ void setup() { Serial.println("Testing device connections..."); Serial.println(accelGyroMag.testConnection() ? "MPU9150 connection successful" : "MPU9150 connection failed"); - // configure Arduino LED for + // configure Arduino LED pin for output pinMode(LED_PIN, OUTPUT); } diff --git a/Arduino/MS5803/examples/test_MS5803/test_MS5803.ino b/Arduino/MS5803/examples/test_MS5803/test_MS5803.ino index 15bb2f95..8f370e59 100644 --- a/Arduino/MS5803/examples/test_MS5803/test_MS5803.ino +++ b/Arduino/MS5803/examples/test_MS5803/test_MS5803.ino @@ -18,7 +18,7 @@ uint32_t wake_time = millis(); void setup() { Serial.begin(57600); Wire.begin(); - // Start up and get Calubration constants. + // Start up and get Calibration constants. presstemp.initialize(MS_MODEL); if ( presstemp.testConnection() ) Serial.println("We are communicating with MS5803 via I2C."); else Serial.println("I2C Communications with MS5803 failed."); From 0bae02be4a521f0ee0d2397e6646662f4e22566e Mon Sep 17 00:00:00 2001 From: gdsports Date: Wed, 20 Sep 2017 23:39:28 -1000 Subject: [PATCH 179/335] Add support for ESP8266 and OSC Arduino and Processing sketches modified to support quaternion data over Open Sound Control over UDP. Arduino sketch modified to run on ESP8266. --- .../MPU6050_DMP6_ESPWiFi.ino | 370 ++++++++++++++++++ .../Processing/MPUOSCTeapot/MPUOSCTeapot.pde | 188 +++++++++ 2 files changed, 558 insertions(+) create mode 100644 Arduino/MPU6050/examples/MPU6050_DMP6_ESPWiFi/MPU6050_DMP6_ESPWiFi.ino create mode 100644 Arduino/MPU6050/examples/MPU6050_DMP6_ESPWiFi/Processing/MPUOSCTeapot/MPUOSCTeapot.pde diff --git a/Arduino/MPU6050/examples/MPU6050_DMP6_ESPWiFi/MPU6050_DMP6_ESPWiFi.ino b/Arduino/MPU6050/examples/MPU6050_DMP6_ESPWiFi/MPU6050_DMP6_ESPWiFi.ino new file mode 100644 index 00000000..588cf914 --- /dev/null +++ b/Arduino/MPU6050/examples/MPU6050_DMP6_ESPWiFi/MPU6050_DMP6_ESPWiFi.ino @@ -0,0 +1,370 @@ +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2012 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +/* This driver reads quaternion data from the MPU6060 and sends + Open Sound Control messages. + + GY-521 NodeMCU + MPU6050 devkit 1.0 + board Lolin Description + ======= ========== ==================================================== + VCC VU (5V USB) Not available on all boards so use 3.3V if needed. + GND G Ground + SCL D1 (GPIO05) I2C clock + SDA D2 (GPIO04) I2C data + XDA not connected + XCL not connected + AD0 not connected + INT D8 (GPIO15) Interrupt pin + +*/ + +#if defined(ESP8266) +#include +#else +#include +#endif +#include +#include +#include +#include +#include //https://github.com/tzapu/WiFiManager + +// I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files +// for both classes must be in the include path of your project +#include "I2Cdev.h" + +#include "MPU6050_6Axis_MotionApps20.h" +//#include "MPU6050.h" // not necessary if using MotionApps include file + +// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation +// is used in I2Cdev.h +#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE + #include "Wire.h" +#endif + +// class default I2C address is 0x68 +// specific I2C addresses may be passed as a parameter here +// AD0 low = 0x68 (default for SparkFun breakout and InvenSense evaluation board) +// AD0 high = 0x69 +MPU6050 mpu; +//MPU6050 mpu(0x69); // <-- use for AD0 high + +/* ========================================================================= + NOTE: In addition to connection 5/3.3v, GND, SDA, and SCL, this sketch + depends on the MPU-6050's INT pin being connected to the ESP8266 GPIO15 + pin. + * ========================================================================= */ + +// MPU control/status vars +bool dmpReady = false; // set true if DMP init was successful +uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU +uint8_t devStatus; // return status after each device operation (0 = success, !0 = error) +uint16_t packetSize; // expected DMP packet size (default is 42 bytes) +uint16_t fifoCount; // count of all bytes currently in FIFO +uint8_t fifoBuffer[64]; // FIFO storage buffer + +// orientation/motion vars +Quaternion q; // [w, x, y, z] quaternion container +VectorInt16 aa; // [x, y, z] accel sensor measurements +VectorInt16 aaReal; // [x, y, z] gravity-free accel sensor measurements +VectorInt16 aaWorld; // [x, y, z] world-frame accel sensor measurements +VectorFloat gravity; // [x, y, z] gravity vector +#ifdef OUTPUT_READABLE_EULER +float euler[3]; // [psi, theta, phi] Euler angle container +#endif +#ifdef OUTPUT_READABLE_YAWPITCHROLL +float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector +#endif + +// uncomment "OUTPUT_READABLE_QUATERNION" if you want to see the actual +// quaternion components in a [w, x, y, z] format (not best for parsing +// on a remote host such as Processing or something though) +//#define OUTPUT_READABLE_QUATERNION + +// uncomment "OUTPUT_READABLE_EULER" if you want to see Euler angles +// (in degrees) calculated from the quaternions coming from the FIFO. +// Note that Euler angles suffer from gimbal lock (for more info, see +// http://en.wikipedia.org/wiki/Gimbal_lock) +//#define OUTPUT_READABLE_EULER + +// uncomment "OUTPUT_READABLE_YAWPITCHROLL" if you want to see the yaw/ +// pitch/roll angles (in degrees) calculated from the quaternions coming +// from the FIFO. Note this also requires gravity vector calculations. +// Also note that yaw/pitch/roll angles suffer from gimbal lock (for +// more info, see: http://en.wikipedia.org/wiki/Gimbal_lock) +//#define OUTPUT_READABLE_YAWPITCHROLL + +// uncomment "OUTPUT_READABLE_REALACCEL" if you want to see acceleration +// components with gravity removed. This acceleration reference frame is +// not compensated for orientation, so +X is always +X according to the +// sensor, just without the effects of gravity. If you want acceleration +// compensated for orientation, us OUTPUT_READABLE_WORLDACCEL instead. +//#define OUTPUT_READABLE_REALACCEL + +// uncomment "OUTPUT_READABLE_WORLDACCEL" if you want to see acceleration +// components with gravity removed and adjusted for the world frame of +// reference (yaw is relative to initial orientation, since no magnetometer +// is present in this case). Could be quite handy in some cases. +//#define OUTPUT_READABLE_WORLDACCEL + +// uncomment "OUTPUT_TEAPOT_OSC" if you want output that matches the +// format used for the InvenSense teapot demo +#define OUTPUT_TEAPOT_OSC + +#define INTERRUPT_PIN 15 // use pin 15 on ESP8266 + +const char DEVICE_NAME[] = "mpu6050"; + +WiFiUDP Udp; // A UDP instance to let us send and receive packets over UDP +const IPAddress outIp(192, 168, 1, 11); // remote IP to receive OSC +const unsigned int outPort = 9999; // remote port to receive OSC + +// ================================================================ +// === INTERRUPT DETECTION ROUTINE === +// ================================================================ + +volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high +void dmpDataReady() { + mpuInterrupt = true; +} + +void mpu_setup() +{ + // join I2C bus (I2Cdev library doesn't do this automatically) +#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE + Wire.begin(); + Wire.setClock(400000); // 400kHz I2C clock. Comment this line if having compilation difficulties +#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE + Fastwire::setup(400, true); +#endif + + // initialize device + Serial.println(F("Initializing I2C devices...")); + mpu.initialize(); + pinMode(INTERRUPT_PIN, INPUT); + + // verify connection + Serial.println(F("Testing device connections...")); + Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed")); + + // load and configure the DMP + Serial.println(F("Initializing DMP...")); + devStatus = mpu.dmpInitialize(); + + // supply your own gyro offsets here, scaled for min sensitivity + mpu.setXGyroOffset(220); + mpu.setYGyroOffset(76); + mpu.setZGyroOffset(-85); + mpu.setZAccelOffset(1788); // 1688 factory default for my test chip + + // make sure it worked (returns 0 if so) + if (devStatus == 0) { + // turn on the DMP, now that it's ready + Serial.println(F("Enabling DMP...")); + mpu.setDMPEnabled(true); + + // enable Arduino interrupt detection + Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)...")); + attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), dmpDataReady, RISING); + mpuIntStatus = mpu.getIntStatus(); + + // set our DMP Ready flag so the main loop() function knows it's okay to use it + Serial.println(F("DMP ready! Waiting for first interrupt...")); + dmpReady = true; + + // get expected DMP packet size for later comparison + packetSize = mpu.dmpGetFIFOPacketSize(); + } else { + // ERROR! + // 1 = initial memory load failed + // 2 = DMP configuration updates failed + // (if it's going to break, usually the code will be 1) + Serial.print(F("DMP Initialization failed (code ")); + Serial.print(devStatus); + Serial.println(F(")")); + } +} + +void setup(void) +{ + Serial.begin(115200); + Serial.println(F("\nOrientation Sensor OSC output")); Serial.println(); + + //WiFiManager + //Local intialization. Once its business is done, there is no need to keep it around + WiFiManager wifiManager; + //reset saved settings + //wifiManager.resetSettings(); + + //fetches ssid and pass from eeprom and tries to connect + //if it does not connect it starts an access point with the specified name + //and goes into a blocking loop awaiting configuration + wifiManager.autoConnect(DEVICE_NAME); + + Serial.print(F("WiFi connected! IP address: ")); + Serial.println(WiFi.localIP()); + + mpu_setup(); +} + +void mpu_loop() +{ + // if programming failed, don't try to do anything + if (!dmpReady) return; + + // wait for MPU interrupt or extra packet(s) available + if (!mpuInterrupt && fifoCount < packetSize) return; + + // reset interrupt flag and get INT_STATUS byte + mpuInterrupt = false; + mpuIntStatus = mpu.getIntStatus(); + + // get current FIFO count + fifoCount = mpu.getFIFOCount(); + + // check for overflow (this should never happen unless our code is too inefficient) + if ((mpuIntStatus & 0x10) || fifoCount == 1024) { + // reset so we can continue cleanly + mpu.resetFIFO(); + Serial.println(F("FIFO overflow!")); + + // otherwise, check for DMP data ready interrupt (this should happen frequently) + } else if (mpuIntStatus & 0x02) { + // wait for correct available data length, should be a VERY short wait + while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount(); + + // read a packet from FIFO + mpu.getFIFOBytes(fifoBuffer, packetSize); + + // track FIFO count here in case there is > 1 packet available + // (this lets us immediately read more without waiting for an interrupt) + fifoCount -= packetSize; + +#ifdef OUTPUT_READABLE_QUATERNION + // display quaternion values in easy matrix form: w x y z + mpu.dmpGetQuaternion(&q, fifoBuffer); + Serial.print("quat\t"); + Serial.print(q.w); + Serial.print("\t"); + Serial.print(q.x); + Serial.print("\t"); + Serial.print(q.y); + Serial.print("\t"); + Serial.println(q.z); +#endif + +#ifdef OUTPUT_TEAPOT_OSC +#ifndef OUTPUT_READABLE_QUATERNION + // display quaternion values in easy matrix form: w x y z + mpu.dmpGetQuaternion(&q, fifoBuffer); +#endif + // Send OSC message + OSCMessage msg("/imuquat"); + msg.add((float)q.w); + msg.add((float)q.x); + msg.add((float)q.y); + msg.add((float)q.z); + + Udp.beginPacket(outIp, outPort); + msg.send(Udp); + Udp.endPacket(); + + msg.empty(); +#endif + +#ifdef OUTPUT_READABLE_EULER + // display Euler angles in degrees + mpu.dmpGetQuaternion(&q, fifoBuffer); + mpu.dmpGetEuler(euler, &q); + Serial.print("euler\t"); + Serial.print(euler[0] * 180/M_PI); + Serial.print("\t"); + Serial.print(euler[1] * 180/M_PI); + Serial.print("\t"); + Serial.println(euler[2] * 180/M_PI); +#endif + +#ifdef OUTPUT_READABLE_YAWPITCHROLL + // display Euler angles in degrees + mpu.dmpGetQuaternion(&q, fifoBuffer); + mpu.dmpGetGravity(&gravity, &q); + mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); + Serial.print("ypr\t"); + Serial.print(ypr[0] * 180/M_PI); + Serial.print("\t"); + Serial.print(ypr[1] * 180/M_PI); + Serial.print("\t"); + Serial.println(ypr[2] * 180/M_PI); +#endif + +#ifdef OUTPUT_READABLE_REALACCEL + // display real acceleration, adjusted to remove gravity + mpu.dmpGetQuaternion(&q, fifoBuffer); + mpu.dmpGetAccel(&aa, fifoBuffer); + mpu.dmpGetGravity(&gravity, &q); + mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity); + Serial.print("areal\t"); + Serial.print(aaReal.x); + Serial.print("\t"); + Serial.print(aaReal.y); + Serial.print("\t"); + Serial.println(aaReal.z); +#endif + +#ifdef OUTPUT_READABLE_WORLDACCEL + // display initial world-frame acceleration, adjusted to remove gravity + // and rotated based on known orientation from quaternion + mpu.dmpGetQuaternion(&q, fifoBuffer); + mpu.dmpGetAccel(&aa, fifoBuffer); + mpu.dmpGetGravity(&gravity, &q); + mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity); + mpu.dmpGetLinearAccelInWorld(&aaWorld, &aaReal, &q); + Serial.print("aworld\t"); + Serial.print(aaWorld.x); + Serial.print("\t"); + Serial.print(aaWorld.y); + Serial.print("\t"); + Serial.println(aaWorld.z); +#endif + } +} + +/**************************************************************************/ +/* + Arduino loop function, called once 'setup' is complete (your own code + should go here) +*/ +/**************************************************************************/ +void loop(void) +{ + if (WiFi.status() != WL_CONNECTED) { + Serial.println(); + Serial.println("*** Disconnected from AP so rebooting ***"); + Serial.println(); + ESP.reset(); + } + + mpu_loop(); +} diff --git a/Arduino/MPU6050/examples/MPU6050_DMP6_ESPWiFi/Processing/MPUOSCTeapot/MPUOSCTeapot.pde b/Arduino/MPU6050/examples/MPU6050_DMP6_ESPWiFi/Processing/MPUOSCTeapot/MPUOSCTeapot.pde new file mode 100644 index 00000000..dfe65189 --- /dev/null +++ b/Arduino/MPU6050/examples/MPU6050_DMP6_ESPWiFi/Processing/MPUOSCTeapot/MPUOSCTeapot.pde @@ -0,0 +1,188 @@ +// I2C device class (I2Cdev) demonstration Processing sketch for MPU6050 DMP output +// 6/20/2012 by Jeff Rowberg +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// 2012-06-20 - initial release + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2012 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +/** + * MPUOSCTeapot Processing demo for MPU6050 DMP modified for OSC + * https://gitub.com/jrowberg/i2cdevlib + * The original demo uses serial port I/O which has been replaced with + * OSC UDP messages in this sketch. + * + * The MPU6050 is connected to an ESP8266 with battery so it is completely + * wire free. + * + * Tested on Processing 3.3.5 running on Ubuntu Linux 14.04 + * + * Dependencies installed using Library Manager + * + * Open Sound Control library + * oscP5 website at http://www.sojamo.de/oscP5 + * ToxicLibs + * quaternion functions http://toxiclibs.org/ + * + */ + +// Install oscP5 using the IDE library manager. +// From the IDE menu bar, Sketch | Import Library | Add library. +// In the search box type "osc". +import oscP5.*; +import netP5.*; +// Install ToxicLibs using the IDE library manager +// From the IDE menu bar, Sketch | Import Library | Add library. +// In the search box type "toxic". +import toxi.geom.*; +import toxi.processing.*; + +ToxiclibsSupport gfx; + +Quaternion quat = new Quaternion(1, 0, 0, 0); + +OscP5 oscP5; + +void setup() { + // 300px square viewport using OpenGL rendering + size(300, 300, P3D); + gfx = new ToxiclibsSupport(this); + + // setup lights and antialiasing + lights(); + smooth(); + + /* start oscP5, listening for incoming messages at port 9999 */ + oscP5 = new OscP5(this, 9999); + + oscP5.plug(this, "imu", "/imuquat"); +} + +/* incoming osc message are forwarded to the oscEvent method. */ +void oscEvent(OscMessage theOscMessage) { + /* print the address pattern and the typetag of the received OscMessage */ + //print("### received an osc message."); + //print(" addrpattern: "+theOscMessage.addrPattern()); + //println(" typetag: "+theOscMessage.typetag()); +} + +public void imu(float quant_w, float quant_x, float quant_y, float quant_z) { + //println(quant_w, quant_x, quant_y, quant_z); + quat.set(quant_w, quant_x, quant_y, quant_z); +} + +void draw() { + // black background + background(0); + + // translate everything to the middle of the viewport + pushMatrix(); + translate(width / 2, height / 2); + + // 3-step rotation from yaw/pitch/roll angles (gimbal lock!) + // ...and other weirdness I haven't figured out yet + //rotateY(-ypr[0]); + //rotateZ(-ypr[1]); + //rotateX(-ypr[2]); + + // toxiclibs direct angle/axis rotation from quaternion (NO gimbal lock!) + // (axis order [1, 3, 2] and inversion [-1, +1, +1] is a consequence of + // different coordinate system orientation assumptions between Processing + // and InvenSense DMP) + float[] axis = quat.toAxisAngle(); + rotate(axis[0], -axis[1], axis[3], axis[2]); + + // draw main body in red + fill(255, 0, 0, 200); + box(10, 10, 200); + + // draw front-facing tip in blue + fill(0, 0, 255, 200); + pushMatrix(); + translate(0, 0, -120); + rotateX(PI/2); + drawCylinder(0, 20, 20, 8); + popMatrix(); + + // draw wings and tail fin in green + fill(0, 255, 0, 200); + beginShape(TRIANGLES); + vertex(-100, 2, 30); vertex(0, 2, -80); vertex(100, 2, 30); // wing top layer + vertex(-100, -2, 30); vertex(0, -2, -80); vertex(100, -2, 30); // wing bottom layer + vertex(-2, 0, 98); vertex(-2, -30, 98); vertex(-2, 0, 70); // tail left layer + vertex( 2, 0, 98); vertex( 2, -30, 98); vertex( 2, 0, 70); // tail right layer + endShape(); + beginShape(QUADS); + vertex(-100, 2, 30); vertex(-100, -2, 30); vertex( 0, -2, -80); vertex( 0, 2, -80); + vertex( 100, 2, 30); vertex( 100, -2, 30); vertex( 0, -2, -80); vertex( 0, 2, -80); + vertex(-100, 2, 30); vertex(-100, -2, 30); vertex(100, -2, 30); vertex(100, 2, 30); + vertex(-2, 0, 98); vertex(2, 0, 98); vertex(2, -30, 98); vertex(-2, -30, 98); + vertex(-2, 0, 98); vertex(2, 0, 98); vertex(2, 0, 70); vertex(-2, 0, 70); + vertex(-2, -30, 98); vertex(2, -30, 98); vertex(2, 0, 70); vertex(-2, 0, 70); + endShape(); + + popMatrix(); +} + +void drawCylinder(float topRadius, float bottomRadius, float tall, int sides) { + float angle = 0; + float angleIncrement = TWO_PI / sides; + beginShape(QUAD_STRIP); + for (int i = 0; i < sides + 1; ++i) { + vertex(topRadius*cos(angle), 0, topRadius*sin(angle)); + vertex(bottomRadius*cos(angle), tall, bottomRadius*sin(angle)); + angle += angleIncrement; + } + endShape(); + + // If it is not a cone, draw the circular top cap + if (topRadius != 0) { + angle = 0; + beginShape(TRIANGLE_FAN); + + // Center point + vertex(0, 0, 0); + for (int i = 0; i < sides + 1; i++) { + vertex(topRadius * cos(angle), 0, topRadius * sin(angle)); + angle += angleIncrement; + } + endShape(); + } + + // If it is not a cone, draw the circular bottom cap + if (bottomRadius != 0) { + angle = 0; + beginShape(TRIANGLE_FAN); + + // Center point + vertex(0, tall, 0); + for (int i = 0; i < sides + 1; i++) { + vertex(bottomRadius * cos(angle), tall, bottomRadius * sin(angle)); + angle += angleIncrement; + } + endShape(); + } +} From 1e091494b38622b5e82d1b996cc713815766f29f Mon Sep 17 00:00:00 2001 From: Denys Fisher Date: Sun, 5 Nov 2017 12:54:22 +0200 Subject: [PATCH 180/335] init version of port --- STM32/APDS9960/APDS9960.c | 2153 +++++++++++++++++++++++++++++++++++++ STM32/APDS9960/APDS9960.h | 285 +++++ STM32/APDS9960/README.md | 1 + 3 files changed, 2439 insertions(+) create mode 100644 STM32/APDS9960/APDS9960.c create mode 100644 STM32/APDS9960/APDS9960.h create mode 100755 STM32/APDS9960/README.md diff --git a/STM32/APDS9960/APDS9960.c b/STM32/APDS9960/APDS9960.c new file mode 100644 index 00000000..7cab6f7a --- /dev/null +++ b/STM32/APDS9960/APDS9960.c @@ -0,0 +1,2153 @@ +/** + * @author : shmakins (shmakins@Denyss-MacBook-Pro.local) + * @file : APDS9960 + * @created : Thursday Oct 12, 2017 23:44:51 EEST + */ + +#include "APDS9960.h" + +/* Gesture processing */ +void resetGestureParameters(); +bool processGestureData(); +bool decodeGesture(); + +/* Proximity Interrupt Threshold */ +uint8_t getProxIntLowThresh(); +bool setProxIntLowThresh(uint8_t threshold); +uint8_t getProxIntHighThresh(); +bool setProxIntHighThresh(uint8_t threshold); + +/* LED Boost Control */ +uint8_t getLEDBoost(); +bool setLEDBoost(uint8_t boost); + +/* Proximity photodiode select */ +uint8_t getProxGainCompEnable(); +bool setProxGainCompEnable(uint8_t enable); +uint8_t getProxPhotoMask(); +bool setProxPhotoMask(uint8_t mask); + +/* Gesture threshold control */ +uint8_t getGestureEnterThresh(); +bool setGestureEnterThresh(uint8_t threshold); +uint8_t getGestureExitThresh(); +bool setGestureExitThresh(uint8_t threshold); + +/* Gesture LED, gain, and time control */ +uint8_t getGestureWaitTime(); +bool setGestureWaitTime(uint8_t time); + +/* Gesture mode */ +uint8_t getGestureMode(); +bool setGestureMode(uint8_t mode); + +/* Raw I2C Commands */ +bool wireWriteByte(uint8_t val); +bool wireWriteDataByte(uint8_t reg, uint8_t val); +bool wireWriteDataBlock(uint8_t reg, uint8_t *val, unsigned int len); +bool wireReadDataByte(uint8_t reg, uint8_t *val); +int wireReadDataBlock(uint8_t reg, uint8_t *val, unsigned int len); + +/* Members */ +gesture_data_type gesture_data_; +int gesture_ud_delta_; +int gesture_lr_delta_; +int gesture_ud_count_; +int gesture_lr_count_; +int gesture_near_count_; +int gesture_far_count_; +int gesture_state_; +int gesture_motion_; + +/* +SparkFun_APDS9960::SparkFun_APDS9960() +{ + gesture_ud_delta_ = 0; + gesture_lr_delta_ = 0; + + gesture_ud_count_ = 0; + gesture_lr_count_ = 0; + + gesture_near_count_ = 0; + gesture_far_count_ = 0; + + gesture_state_ = 0; + gesture_motion_ = DIR_NONE; +} +*/ + + +/** + * @brief Configures I2C communications and initializes registers to defaults + * + * @return True if initialized successfully. False otherwise. + */ +bool APDS9960_init(I2C_HandleTypeDef *i2c_h) +{ + uint8_t id; + + /* Initialize I2C */ + I2Cdev_init(i2c_h); + //Wire.begin(); + + /* Read ID register and check against known values for APDS-9960 */ + if( !wireReadDataByte(APDS9960_ID, &id) ) { + return false; + } + if( !(id == APDS9960_ID_1 || id == APDS9960_ID_2 || id == APDS9960_ID_3) ) { + return false; + } + + /* Set ENABLE register to 0 (disable all features) */ + if( !APDS9960_setMode(ALL, OFF) ) { + return false; + } + + /* Set default values for ambient light and proximity registers */ + if( !wireWriteDataByte(APDS9960_ATIME, DEFAULT_ATIME) ) { + return false; + } + if( !wireWriteDataByte(APDS9960_WTIME, DEFAULT_WTIME) ) { + return false; + } + if( !wireWriteDataByte(APDS9960_PPULSE, DEFAULT_PROX_PPULSE) ) { + return false; + } + if( !wireWriteDataByte(APDS9960_POFFSET_UR, DEFAULT_POFFSET_UR) ) { + return false; + } + if( !wireWriteDataByte(APDS9960_POFFSET_DL, DEFAULT_POFFSET_DL) ) { + return false; + } + if( !wireWriteDataByte(APDS9960_CONFIG1, DEFAULT_CONFIG1) ) { + return false; + } + if( !APDS9960_setLEDDrive(DEFAULT_LDRIVE) ) { + return false; + } + if( !APDS9960_setProximityGain(DEFAULT_PGAIN) ) { + return false; + } + if( !APDS9960_setAmbientLightGain(DEFAULT_AGAIN) ) { + return false; + } + if( !setProxIntLowThresh(DEFAULT_PILT) ) { + return false; + } + if( !setProxIntHighThresh(DEFAULT_PIHT) ) { + return false; + } + if( !APDS9960_setLightIntLowThreshold(DEFAULT_AILT) ) { + return false; + } + if( !APDS9960_setLightIntHighThreshold(DEFAULT_AIHT) ) { + return false; + } + if( !wireWriteDataByte(APDS9960_PERS, DEFAULT_PERS) ) { + return false; + } + if( !wireWriteDataByte(APDS9960_CONFIG2, DEFAULT_CONFIG2) ) { + return false; + } + if( !wireWriteDataByte(APDS9960_CONFIG3, DEFAULT_CONFIG3) ) { + return false; + } + + /* Set default values for gesture sense registers */ + if( !setGestureEnterThresh(DEFAULT_GPENTH) ) { + return false; + } + if( !setGestureExitThresh(DEFAULT_GEXTH) ) { + return false; + } + if( !wireWriteDataByte(APDS9960_GCONF1, DEFAULT_GCONF1) ) { + return false; + } + if( !APDS9960_setGestureGain(DEFAULT_GGAIN) ) { + return false; + } + if( !APDS9960_setGestureLEDDrive(DEFAULT_GLDRIVE) ) { + return false; + } + if( !setGestureWaitTime(DEFAULT_GWTIME) ) { + return false; + } + if( !wireWriteDataByte(APDS9960_GOFFSET_U, DEFAULT_GOFFSET) ) { + return false; + } + if( !wireWriteDataByte(APDS9960_GOFFSET_D, DEFAULT_GOFFSET) ) { + return false; + } + if( !wireWriteDataByte(APDS9960_GOFFSET_L, DEFAULT_GOFFSET) ) { + return false; + } + if( !wireWriteDataByte(APDS9960_GOFFSET_R, DEFAULT_GOFFSET) ) { + return false; + } + if( !wireWriteDataByte(APDS9960_GPULSE, DEFAULT_GPULSE) ) { + return false; + } + if( !wireWriteDataByte(APDS9960_GCONF3, DEFAULT_GCONF3) ) { + return false; + } + if( !APDS9960_setGestureIntEnable(DEFAULT_GIEN) ) { + return false; + } + +#if 0 + /* Gesture config register dump */ + uint8_t reg; + uint8_t val; + + for(reg = 0x80; reg <= 0xAF; reg++) { + if( (reg != 0x82) && \ + (reg != 0x8A) && \ + (reg != 0x91) && \ + (reg != 0xA8) && \ + (reg != 0xAC) && \ + (reg != 0xAD) ) + { + wireReadDataByte(reg, &val); + LCD_Printf("%x: 0x%x\n", reg, val); + } + } + + for(reg = 0xE4; reg <= 0xE7; reg++) { + wireReadDataByte(reg, &val); + LCD_Printf("%x: 0x%x\n", reg, val); + } +#endif + + return true; +} + +/******************************************************************************* + * Public methods for controlling the APDS-9960 + ******************************************************************************/ + +/** + * @brief Reads and returns the contents of the ENABLE register + * + * @return Contents of the ENABLE register. 0xFF if error. + */ +uint8_t APDS9960_getMode() +{ + uint8_t enable_value; + + /* Read current ENABLE register */ + if( !wireReadDataByte(APDS9960_ENABLE, &enable_value) ) { + return ERROR; + } + + return enable_value; +} + +/** + * @brief Enables or disables a feature in the APDS-9960 + * + * @param[in] mode which feature to enable + * @param[in] enable ON (1) or OFF (0) + * @return True if operation success. False otherwise. + */ +bool APDS9960_setMode(uint8_t mode, uint8_t enable) +{ + uint8_t reg_val; + + /* Read current ENABLE register */ + reg_val = APDS9960_getMode(); + if( reg_val == ERROR ) { + return false; + } + + /* Change bit(s) in ENABLE register */ + enable = enable & 0x01; + if( mode >= 0 && mode <= 6 ) { + if (enable) { + reg_val |= (1 << mode); + } else { + reg_val &= ~(1 << mode); + } + } else if( mode == ALL ) { + if (enable) { + reg_val = 0x7F; + } else { + reg_val = 0x00; + } + } + + /* Write value back to ENABLE register */ + if( !wireWriteDataByte(APDS9960_ENABLE, reg_val) ) { + return false; + } + + return true; +} + +/** + * @brief Starts the light (R/G/B/Ambient) sensor on the APDS-9960 + * + * @param[in] interrupts true to enable hardware interrupt on high or low light + * @return True if sensor enabled correctly. False on error. + */ +bool APDS9960_enableLightSensor() +{ + + /* Set default gain, interrupts, enable power, and enable sensor */ + if( !APDS9960_setAmbientLightGain(DEFAULT_AGAIN) ) { + return false; + } + if( !APDS9960_setAmbientLightIntEnable(1) ) { + return false; + } + if( !APDS9960_enablePower() ){ + return false; + } + if( !APDS9960_setMode(AMBIENT_LIGHT, 1) ) { + return false; + } + + return true; + +} + +/** + * @brief Ends the light sensor on the APDS-9960 + * + * @return True if sensor disabled correctly. False on error. + */ +bool APDS9960_disableLightSensor() +{ + if( !APDS9960_setAmbientLightIntEnable(0) ) { + return false; + } + if( !APDS9960_setMode(AMBIENT_LIGHT, 0) ) { + return false; + } + + return true; +} + +/** + * @brief Starts the proximity sensor on the APDS-9960 + * + * @param[in] interrupts true to enable hardware external interrupt on proximity + * @return True if sensor enabled correctly. False on error. + */ +bool APDS9960_enableProximitySensor() +{ + /* Set default gain, LED, interrupts, enable power, and enable sensor */ + if( !APDS9960_setProximityGain(DEFAULT_PGAIN) ) { + return false; + } + if( !APDS9960_setLEDDrive(DEFAULT_LDRIVE) ) { + return false; + } + if( !APDS9960_setProximityIntEnable(1) ) { + return false; + } + if( !APDS9960_enablePower() ){ + return false; + } + if( !APDS9960_setMode(PROXIMITY, 1) ) { + return false; + } + + return true; +} + +/** + * @brief Ends the proximity sensor on the APDS-9960 + * + * @return True if sensor disabled correctly. False on error. + */ +bool APDS9960_disableProximitySensor() +{ + if( !APDS9960_setProximityIntEnable(0) ) { + return false; + } + if( !APDS9960_setMode(PROXIMITY, 0) ) { + return false; + } + + return true; +} + +/** + * @brief Starts the gesture recognition engine on the APDS-9960 + * + * @param[in] interrupts true to enable hardware external interrupt on gesture + * @return True if engine enabled correctly. False on error. + */ +bool APDS9960_enableGestureSensor() +{ + + /* Enable gesture mode + Set ENABLE to 0 (power off) + Set WTIME to 0xFF + Set AUX to LED_BOOST_300 + Enable PON, WEN, PEN, GEN in ENABLE + */ + resetGestureParameters(); + if( !wireWriteDataByte(APDS9960_WTIME, 0xFF) ) { + return false; + } + if( !wireWriteDataByte(APDS9960_PPULSE, DEFAULT_GESTURE_PPULSE) ) { + return false; + } + if( !setLEDBoost(LED_BOOST_300) ) { + return false; + } + if( !APDS9960_setGestureIntEnable(1) ) { + return false; + } + if( !setGestureMode(1) ) { + return false; + } + if( !APDS9960_enablePower() ){ + return false; + } + if( !APDS9960_setMode(WAIT, 1) ) { + return false; + } + if( !APDS9960_setMode(PROXIMITY, 1) ) { + return false; + } + if( !APDS9960_setMode(GESTURE, 1) ) { + return false; + } + + return true; +} + +/** + * @brief Ends the gesture recognition engine on the APDS-9960 + * + * @return True if engine disabled correctly. False on error. + */ +bool APDS9960_disableGestureSensor() +{ + resetGestureParameters(); + if( !APDS9960_setGestureIntEnable(0) ) { + return false; + } + if( !setGestureMode(0) ) { + return false; + } + if( !APDS9960_setMode(GESTURE, 0) ) { + return false; + } + + return true; +} + +/** + * @brief Determines if there is a gesture available for reading + * + * @return True if gesture available. False otherwise. + */ +bool APDS9960_isGestureAvailable() +{ + uint8_t val; + + /* Read value from GSTATUS register */ + if( !wireReadDataByte(APDS9960_GSTATUS, &val) ) { + // ERROR + return false; + } + + /* Shift and mask out GVALID bit */ + val &= APDS9960_GVALID; + + /* Return true/false based on GVALID bit */ + if( val == 1) { + return true; + } else { + return false; + } +} + +/** + * @brief Processes a gesture event and returns best guessed gesture + * + * @return Number corresponding to gesture. -1 on error. + */ +int APDS9960_readGesture(uint32_t timeout) +{ + uint8_t fifo_level = 0; + uint8_t bytes_read = 0; + uint8_t fifo_data[128]; + uint8_t gstatus; + int motion; + int i; + + /* Make sure that power and gesture is on and data is valid */ + if( !APDS9960_isGestureAvailable() || !(APDS9960_getMode() & 0b01000001) ) { + return DIR_NONE; + } + + /* Keep looping as long as gesture data is valid */ + uint32_t time = HAL_GetTick(); + while( !timeout || HAL_GetTick() < time + timeout ) { + + /* Wait some time to collect next batch of FIFO data */ + HAL_Delay(FIFO_PAUSE_TIME); + + /* Get the contents of the STATUS register. Is data still valid? */ + if( !wireReadDataByte(APDS9960_GSTATUS, &gstatus) ) { + return ERROR; + } + + /* If we have valid data, read in FIFO */ + if( (gstatus & APDS9960_GVALID) == APDS9960_GVALID ) { + + /* Read the current FIFO level */ + if( !wireReadDataByte(APDS9960_GFLVL, &fifo_level) ) { + return ERROR; + } + +#if DEBUG + LCD_Printf("FIFO level: %d\n", fifo_level); +#endif + + /* If there's stuff in the FIFO, read it into our data block */ + if( fifo_level > 0) { + bytes_read = wireReadDataBlock( APDS9960_GFIFO_U, + (uint8_t*)fifo_data, + (fifo_level * 4) ); + if( bytes_read == -1 ) { + return ERROR; + } +#if DEBUG + LCD_Printf("FIFO Dump: "); + for ( i = 0; i < bytes_read; i++ ) { + LCD_Printf("%d ",fifo_data[i]); + } + LCD_Printf("\n"); +#endif + + /* If at least 1 set of data, sort the data into U/D/L/R */ + if( bytes_read >= 4 ) { + for( i = 0; i < bytes_read; i += 4 ) { + gesture_data_.u_data[gesture_data_.index] = \ + fifo_data[i + 0]; + gesture_data_.d_data[gesture_data_.index] = \ + fifo_data[i + 1]; + gesture_data_.l_data[gesture_data_.index] = \ + fifo_data[i + 2]; + gesture_data_.r_data[gesture_data_.index] = \ + fifo_data[i + 3]; + gesture_data_.index++; + gesture_data_.total_gestures++; + } + +#if DEBUG + LCD_Printf("Up Data: "); + for ( i = 0; i < gesture_data_.total_gestures; i++ ) { + LCD_Printf("%d ", gesture_data_.u_data[i]); + } + LCD_Printf("\n"); +#endif + + /* Filter and process gesture data. Decode near/far state */ + if( processGestureData() ) { + if( decodeGesture() ) { + //***TODO: U-Turn Gestures +#if DEBUG + //LCD_Printf("%d", gesture_motion_); +#endif + } + } + + /* Reset data */ + gesture_data_.index = 0; + gesture_data_.total_gestures = 0; + } + } + } else { + + /* Determine best guessed gesture and clean up */ + HAL_Delay(FIFO_PAUSE_TIME); + decodeGesture(); + motion = gesture_motion_; +#if DEBUG + LCD_Printf("END: %d\n", gesture_motion_); +#endif + resetGestureParameters(); + return motion; + } + } + return ERROR; +} + +/** + * Turn the APDS-9960 on + * + * @return True if operation successful. False otherwise. + */ +bool APDS9960_enablePower() +{ + if( !APDS9960_setMode(POWER, 1) ) { + return false; + } + + return true; +} + +/** + * Turn the APDS-9960 off + * + * @return True if operation successful. False otherwise. + */ +bool APDS9960_disablePower() +{ + if( !APDS9960_setMode(POWER, 0) ) { + return false; + } + + return true; +} + +/******************************************************************************* + * Ambient light and color sensor controls + ******************************************************************************/ + +/** + * @brief Reads the ambient (clear) light level as a 16-bit value + * + * @param[out] val value of the light sensor. + * @return True if operation successful. False otherwise. + */ +bool APDS9960_readAmbientLight(uint16_t *val) +{ + uint8_t val_byte; + val = 0; + + /* Read value from clear channel, low byte register */ + if( !wireReadDataByte(APDS9960_CDATAL, &val_byte) ) { + return false; + } + *val = val_byte; + + /* Read value from clear channel, high byte register */ + if( !wireReadDataByte(APDS9960_CDATAH, &val_byte) ) { + return false; + } + val = val + ((uint16_t)val_byte << 8); + + return true; +} + +/** + * @brief Reads the red light level as a 16-bit value + * + * @param[out] val value of the light sensor. + * @return True if operation successful. False otherwise. + */ +bool APDS9960_readRedLight(uint16_t *val) +{ + uint8_t val_byte; + val = 0; + + /* Read value from clear channel, low byte register */ + if( !wireReadDataByte(APDS9960_RDATAL, &val_byte) ) { + return false; + } + *val = val_byte; + + /* Read value from clear channel, high byte register */ + if( !wireReadDataByte(APDS9960_RDATAH, &val_byte) ) { + return false; + } + val = val + ((uint16_t)val_byte << 8); + + return true; +} + +/** + * @brief Reads the green light level as a 16-bit value + * + * @param[out] val value of the light sensor. + * @return True if operation successful. False otherwise. + */ +bool APDS9960_readGreenLight(uint16_t *val) +{ + uint8_t val_byte; + val = 0; + + /* Read value from clear channel, low byte register */ + if( !wireReadDataByte(APDS9960_GDATAL, &val_byte) ) { + return false; + } + *val = val_byte; + + /* Read value from clear channel, high byte register */ + if( !wireReadDataByte(APDS9960_GDATAH, &val_byte) ) { + return false; + } + val = val + ((uint16_t)val_byte << 8); + + return true; +} + +/** + * @brief Reads the red light level as a 16-bit value + * + * @param[out] val value of the light sensor. + * @return True if operation successful. False otherwise. + */ +bool APDS9960_readBlueLight(uint16_t *val) +{ + uint8_t val_byte; + val = 0; + + /* Read value from clear channel, low byte register */ + if( !wireReadDataByte(APDS9960_BDATAL, &val_byte) ) { + return false; + } + *val = val_byte; + + /* Read value from clear channel, high byte register */ + if( !wireReadDataByte(APDS9960_BDATAH, &val_byte) ) { + return false; + } + val = val + ((uint16_t)val_byte << 8); + + return true; +} + +/******************************************************************************* + * Proximity sensor controls + ******************************************************************************/ + +/** + * @brief Reads the proximity level as an 8-bit value + * + * @param[out] val value of the proximity sensor. + * @return True if operation successful. False otherwise. + */ +bool APDS9960_readProximity(uint8_t *val) +{ + val = 0; + + /* Read value from proximity data register */ + if( !wireReadDataByte(APDS9960_PDATA, val) ) { + return false; + } + + return true; +} + +/******************************************************************************* + * High-level gesture controls + ******************************************************************************/ + +/** + * @brief Resets all the parameters in the gesture data member + */ +void resetGestureParameters() +{ + gesture_data_.index = 0; + gesture_data_.total_gestures = 0; + + gesture_ud_delta_ = 0; + gesture_lr_delta_ = 0; + + gesture_ud_count_ = 0; + gesture_lr_count_ = 0; + + gesture_near_count_ = 0; + gesture_far_count_ = 0; + + gesture_state_ = 0; + gesture_motion_ = DIR_NONE; +} + +/** + * @brief Processes the raw gesture data to determine swipe direction + * + * @return True if near or far state seen. False otherwise. + */ +bool processGestureData() +{ + uint8_t u_first = 0; + uint8_t d_first = 0; + uint8_t l_first = 0; + uint8_t r_first = 0; + uint8_t u_last = 0; + uint8_t d_last = 0; + uint8_t l_last = 0; + uint8_t r_last = 0; + int ud_ratio_first; + int lr_ratio_first; + int ud_ratio_last; + int lr_ratio_last; + int ud_delta; + int lr_delta; + int i; + + /* If we have less than 4 total gestures, that's not enough */ + if( gesture_data_.total_gestures <= 4 ) { + return false; + } + + /* Check to make sure our data isn't out of bounds */ + if( (gesture_data_.total_gestures <= 32) && \ + (gesture_data_.total_gestures > 0) ) { + + /* Find the first value in U/D/L/R above the threshold */ + for( i = 0; i < gesture_data_.total_gestures; i++ ) { + if( (gesture_data_.u_data[i] > GESTURE_THRESHOLD_OUT) && + (gesture_data_.d_data[i] > GESTURE_THRESHOLD_OUT) && + (gesture_data_.l_data[i] > GESTURE_THRESHOLD_OUT) && + (gesture_data_.r_data[i] > GESTURE_THRESHOLD_OUT) ) { + + u_first = gesture_data_.u_data[i]; + d_first = gesture_data_.d_data[i]; + l_first = gesture_data_.l_data[i]; + r_first = gesture_data_.r_data[i]; + break; + } + } + + /* If one of the _first values is 0, then there is no good data */ + if( (u_first == 0) || (d_first == 0) || \ + (l_first == 0) || (r_first == 0) ) { + + return false; + } + /* Find the last value in U/D/L/R above the threshold */ + for( i = gesture_data_.total_gestures - 1; i >= 0; i-- ) { +#if DEBUG + LCD_Printf("Finding last: "); + LCD_Printf("U: %f ", gesture_data_.u_data[i]); + LCD_Printf("D: %f ", gesture_data_.d_data[i]); + LCD_Printf("L: %f ", gesture_data_.l_data[i]); + LCD_Printf("R: %f\n", gesture_data_.r_data[i]); +#endif + if( (gesture_data_.u_data[i] > GESTURE_THRESHOLD_OUT) && + (gesture_data_.d_data[i] > GESTURE_THRESHOLD_OUT) && + (gesture_data_.l_data[i] > GESTURE_THRESHOLD_OUT) && + (gesture_data_.r_data[i] > GESTURE_THRESHOLD_OUT) ) { + + u_last = gesture_data_.u_data[i]; + d_last = gesture_data_.d_data[i]; + l_last = gesture_data_.l_data[i]; + r_last = gesture_data_.r_data[i]; + break; + } + } + } + + /* Calculate the first vs. last ratio of up/down and left/right */ + ud_ratio_first = ((u_first - d_first) * 100) / (u_first + d_first); + lr_ratio_first = ((l_first - r_first) * 100) / (l_first + r_first); + ud_ratio_last = ((u_last - d_last) * 100) / (u_last + d_last); + lr_ratio_last = ((l_last - r_last) * 100) / (l_last + r_last); + +#if DEBUG + LCD_Printf("Last Values: "); + LCD_Printf("U: %d ", u_last); + LCD_Printf("D: %d ", d_last); + LCD_Printf("L: %d ", l_last); + LCD_Printf("R: %d\n", r_last); + + LCD_Printf("Ratios: "); + LCD_Printf("UD Fi: %d ", ud_ratio_first); + LCD_Printf("UD La: %d ", ud_ratio_last); + LCD_Printf("LR Fi: %d ", lr_ratio_first); + LCD_Printf("LR La: %d\n", lr_ratio_last); +#endif + + /* Determine the difference between the first and last ratios */ + ud_delta = ud_ratio_last - ud_ratio_first; + lr_delta = lr_ratio_last - lr_ratio_first; + +#if DEBUG + LCD_Printf("Deltas: "); + LCD_Printf("UD: %d", ud_delta); + LCD_Printf("LR: %d", lr_delta); +#endif + + /* Accumulate the UD and LR delta values */ + gesture_ud_delta_ += ud_delta; + gesture_lr_delta_ += lr_delta; + +#if DEBUG + LCD_Printf("Accumulations: "); + LCD_Printf("UD: %d", gesture_ud_delta_); + LCD_Printf("LR: %d", gesture_lr_delta_); +#endif + + /* Determine U/D gesture */ + if( gesture_ud_delta_ >= GESTURE_SENSITIVITY_1 ) { + gesture_ud_count_ = 1; + } else if( gesture_ud_delta_ <= -GESTURE_SENSITIVITY_1 ) { + gesture_ud_count_ = -1; + } else { + gesture_ud_count_ = 0; + } + + /* Determine L/R gesture */ + if( gesture_lr_delta_ >= GESTURE_SENSITIVITY_1 ) { + gesture_lr_count_ = 1; + } else if( gesture_lr_delta_ <= -GESTURE_SENSITIVITY_1 ) { + gesture_lr_count_ = -1; + } else { + gesture_lr_count_ = 0; + } + + /* Determine Near/Far gesture */ + if( (gesture_ud_count_ == 0) && (gesture_lr_count_ == 0) ) { + if( (abs(ud_delta) < GESTURE_SENSITIVITY_2) && \ + (abs(lr_delta) < GESTURE_SENSITIVITY_2) ) { + + if( (ud_delta == 0) && (lr_delta == 0) ) { + gesture_near_count_++; + } else if( (ud_delta != 0) || (lr_delta != 0) ) { + gesture_far_count_++; + } + + if( (gesture_near_count_ >= 10) && (gesture_far_count_ >= 2) ) { + if( (ud_delta == 0) && (lr_delta == 0) ) { + gesture_state_ = NEAR_STATE; + } else if( (ud_delta != 0) && (lr_delta != 0) ) { + gesture_state_ = FAR_STATE; + } + return true; + } + } + } else { + if( (abs(ud_delta) < GESTURE_SENSITIVITY_2) && \ + (abs(lr_delta) < GESTURE_SENSITIVITY_2) ) { + + if( (ud_delta == 0) && (lr_delta == 0) ) { + gesture_near_count_++; + } + + if( gesture_near_count_ >= 10 ) { + gesture_ud_count_ = 0; + gesture_lr_count_ = 0; + gesture_ud_delta_ = 0; + gesture_lr_delta_ = 0; + } + } + } + +#if DEBUG + LCD_Printf("UD_CT: %d", gesture_ud_count_); + LCD_Printf("LR_CT: %d", gesture_lr_count_); + LCD_Printf("NEAR_CT: %d", gesture_near_count_); + LCD_Printf("FAR_CT: %d", gesture_far_count_); + LCD_Printf("----------\n"); +#endif + + return false; +} + +/** + * @brief Determines swipe direction or near/far state + * + * @return True if near/far event. False otherwise. + */ +bool decodeGesture() +{ + /* Return if near or far event is detected */ + if( gesture_state_ == NEAR_STATE ) { + gesture_motion_ = DIR_NEAR; + return true; + } else if ( gesture_state_ == FAR_STATE ) { + gesture_motion_ = DIR_FAR; + return true; + } + + /* Determine swipe direction */ + if( (gesture_ud_count_ == -1) && (gesture_lr_count_ == 0) ) { + gesture_motion_ = DIR_UP; + } else if( (gesture_ud_count_ == 1) && (gesture_lr_count_ == 0) ) { + gesture_motion_ = DIR_DOWN; + } else if( (gesture_ud_count_ == 0) && (gesture_lr_count_ == 1) ) { + gesture_motion_ = DIR_RIGHT; + } else if( (gesture_ud_count_ == 0) && (gesture_lr_count_ == -1) ) { + gesture_motion_ = DIR_LEFT; + } else if( (gesture_ud_count_ == -1) && (gesture_lr_count_ == 1) ) { + if( abs(gesture_ud_delta_) > abs(gesture_lr_delta_) ) { + gesture_motion_ = DIR_UP; + } else { + gesture_motion_ = DIR_RIGHT; + } + } else if( (gesture_ud_count_ == 1) && (gesture_lr_count_ == -1) ) { + if( abs(gesture_ud_delta_) > abs(gesture_lr_delta_) ) { + gesture_motion_ = DIR_DOWN; + } else { + gesture_motion_ = DIR_LEFT; + } + } else if( (gesture_ud_count_ == -1) && (gesture_lr_count_ == -1) ) { + if( abs(gesture_ud_delta_) > abs(gesture_lr_delta_) ) { + gesture_motion_ = DIR_UP; + } else { + gesture_motion_ = DIR_LEFT; + } + } else if( (gesture_ud_count_ == 1) && (gesture_lr_count_ == 1) ) { + if( abs(gesture_ud_delta_) > abs(gesture_lr_delta_) ) { + gesture_motion_ = DIR_DOWN; + } else { + gesture_motion_ = DIR_RIGHT; + } + } else { + return false; + } + + return true; +} + +/******************************************************************************* + * Getters and setters for register values + ******************************************************************************/ + +/** + * @brief Returns the lower threshold for proximity detection + * + * @return lower threshold + */ +uint8_t getProxIntLowThresh() +{ + uint8_t val; + + /* Read value from PILT register */ + if( !wireReadDataByte(APDS9960_PILT, &val) ) { + val = 0; + } + + return val; +} + +/** + * @brief Sets the lower threshold for proximity detection + * + * @param[in] threshold the lower proximity threshold + * @return True if operation successful. False otherwise. + */ +bool setProxIntLowThresh(uint8_t threshold) +{ + if( !wireWriteDataByte(APDS9960_PILT, threshold) ) { + return false; + } + + return true; +} + +/** + * @brief Returns the high threshold for proximity detection + * + * @return high threshold + */ +uint8_t getProxIntHighThresh() +{ + uint8_t val; + + /* Read value from PIHT register */ + if( !wireReadDataByte(APDS9960_PIHT, &val) ) { + val = 0; + } + + return val; +} + +/** + * @brief Sets the high threshold for proximity detection + * + * @param[in] threshold the high proximity threshold + * @return True if operation successful. False otherwise. + */ +bool setProxIntHighThresh(uint8_t threshold) +{ + if( !wireWriteDataByte(APDS9960_PIHT, threshold) ) { + return false; + } + + return true; +} + +/** + * @brief Returns LED drive strength for proximity and ALS + * + * Value LED Current + * 0 100 mA + * 1 50 mA + * 2 25 mA + * 3 12.5 mA + * + * @return the value of the LED drive strength. 0xFF on failure. + */ +uint8_t APDS9960_getLEDDrive() +{ + uint8_t val; + + /* Read value from CONTROL register */ + if( !wireReadDataByte(APDS9960_CONTROL, &val) ) { + return ERROR; + } + + /* Shift and mask out LED drive bits */ + val = (val >> 6) & 0b00000011; + + return val; +} + +/** + * @brief Sets the LED drive strength for proximity and ALS + * + * Value LED Current + * 0 100 mA + * 1 50 mA + * 2 25 mA + * 3 12.5 mA + * + * @param[in] drive the value (0-3) for the LED drive strength + * @return True if operation successful. False otherwise. + */ +bool APDS9960_setLEDDrive(uint8_t drive) +{ + uint8_t val; + + /* Read value from CONTROL register */ + if( !wireReadDataByte(APDS9960_CONTROL, &val) ) { + return false; + } + + /* Set bits in register to given value */ + drive &= 0b00000011; + drive = drive << 6; + val &= 0b00111111; + val |= drive; + + /* Write register value back into CONTROL register */ + if( !wireWriteDataByte(APDS9960_CONTROL, val) ) { + return false; + } + + return true; +} + +/** + * @brief Returns receiver gain for proximity detection + * + * Value Gain + * 0 1x + * 1 2x + * 2 4x + * 3 8x + * + * @return the value of the proximity gain. 0xFF on failure. + */ +uint8_t APDS9960_getProximityGain() +{ + uint8_t val; + + /* Read value from CONTROL register */ + if( !wireReadDataByte(APDS9960_CONTROL, &val) ) { + return ERROR; + } + + /* Shift and mask out PDRIVE bits */ + val = (val >> 2) & 0b00000011; + + return val; +} + +/** + * @brief Sets the receiver gain for proximity detection + * + * Value Gain + * 0 1x + * 1 2x + * 2 4x + * 3 8x + * + * @param[in] drive the value (0-3) for the gain + * @return True if operation successful. False otherwise. + */ +bool APDS9960_setProximityGain(uint8_t drive) +{ + uint8_t val; + + /* Read value from CONTROL register */ + if( !wireReadDataByte(APDS9960_CONTROL, &val) ) { + return false; + } + + /* Set bits in register to given value */ + drive &= 0b00000011; + drive = drive << 2; + val &= 0b11110011; + val |= drive; + + /* Write register value back into CONTROL register */ + if( !wireWriteDataByte(APDS9960_CONTROL, val) ) { + return false; + } + + return true; +} + +/** + * @brief Returns receiver gain for the ambient light sensor (ALS) + * + * Value Gain + * 0 1x + * 1 4x + * 2 16x + * 3 64x + * + * @return the value of the ALS gain. 0xFF on failure. + */ +uint8_t APDS9960_getAmbientLightGain() +{ + uint8_t val; + + /* Read value from CONTROL register */ + if( !wireReadDataByte(APDS9960_CONTROL, &val) ) { + return ERROR; + } + + /* Shift and mask out ADRIVE bits */ + val &= 0b00000011; + + return val; +} + +/** + * @brief Sets the receiver gain for the ambient light sensor (ALS) + * + * Value Gain + * 0 1x + * 1 4x + * 2 16x + * 3 64x + * + * @param[in] drive the value (0-3) for the gain + * @return True if operation successful. False otherwise. + */ +bool APDS9960_setAmbientLightGain(uint8_t drive) +{ + uint8_t val; + + /* Read value from CONTROL register */ + if( !wireReadDataByte(APDS9960_CONTROL, &val) ) { + return false; + } + + /* Set bits in register to given value */ + drive &= 0b00000011; + val &= 0b11111100; + val |= drive; + + /* Write register value back into CONTROL register */ + if( !wireWriteDataByte(APDS9960_CONTROL, val) ) { + return false; + } + + return true; +} + +/** + * @brief Get the current LED boost value + * + * Value Boost Current + * 0 100% + * 1 150% + * 2 200% + * 3 300% + * + * @return The LED boost value. 0xFF on failure. + */ +uint8_t getLEDBoost() +{ + uint8_t val; + + /* Read value from CONFIG2 register */ + if( !wireReadDataByte(APDS9960_CONFIG2, &val) ) { + return ERROR; + } + + /* Shift and mask out LED_BOOST bits */ + val = (val >> 4) & 0b00000011; + + return val; +} + +/** + * @brief Sets the LED current boost value + * + * Value Boost Current + * 0 100% + * 1 150% + * 2 200% + * 3 300% + * + * @param[in] drive the value (0-3) for current boost (100-300%) + * @return True if operation successful. False otherwise. + */ +bool setLEDBoost(uint8_t boost) +{ + uint8_t val; + + /* Read value from CONFIG2 register */ + if( !wireReadDataByte(APDS9960_CONFIG2, &val) ) { + return false; + } + + /* Set bits in register to given value */ + boost &= 0b00000011; + boost = boost << 4; + val &= 0b11001111; + val |= boost; + + /* Write register value back into CONFIG2 register */ + if( !wireWriteDataByte(APDS9960_CONFIG2, val) ) { + return false; + } + + return true; +} + +/** + * @brief Gets proximity gain compensation enable + * + * @return 1 if compensation is enabled. 0 if not. 0xFF on error. + */ +uint8_t getProxGainCompEnable() +{ + uint8_t val; + + /* Read value from CONFIG3 register */ + if( !wireReadDataByte(APDS9960_CONFIG3, &val) ) { + return ERROR; + } + + /* Shift and mask out PCMP bits */ + val = (val >> 5) & 0b00000001; + + return val; +} + +/** + * @brief Sets the proximity gain compensation enable + * + * @param[in] enable 1 to enable compensation. 0 to disable compensation. + * @return True if operation successful. False otherwise. + */ + bool setProxGainCompEnable(uint8_t enable) +{ + uint8_t val; + + /* Read value from CONFIG3 register */ + if( !wireReadDataByte(APDS9960_CONFIG3, &val) ) { + return false; + } + + /* Set bits in register to given value */ + enable &= 0b00000001; + enable = enable << 5; + val &= 0b11011111; + val |= enable; + + /* Write register value back into CONFIG3 register */ + if( !wireWriteDataByte(APDS9960_CONFIG3, val) ) { + return false; + } + + return true; +} + +/** + * @brief Gets the current mask for enabled/disabled proximity photodiodes + * + * 1 = disabled, 0 = enabled + * Bit Photodiode + * 3 UP + * 2 DOWN + * 1 LEFT + * 0 RIGHT + * + * @return Current proximity mask for photodiodes. 0xFF on error. + */ +uint8_t getProxPhotoMask() +{ + uint8_t val; + + /* Read value from CONFIG3 register */ + if( !wireReadDataByte(APDS9960_CONFIG3, &val) ) { + return ERROR; + } + + /* Mask out photodiode enable mask bits */ + val &= 0b00001111; + + return val; +} + +/** + * @brief Sets the mask for enabling/disabling proximity photodiodes + * + * 1 = disabled, 0 = enabled + * Bit Photodiode + * 3 UP + * 2 DOWN + * 1 LEFT + * 0 RIGHT + * + * @param[in] mask 4-bit mask value + * @return True if operation successful. False otherwise. + */ +bool setProxPhotoMask(uint8_t mask) +{ + uint8_t val; + + /* Read value from CONFIG3 register */ + if( !wireReadDataByte(APDS9960_CONFIG3, &val) ) { + return false; + } + + /* Set bits in register to given value */ + mask &= 0b00001111; + val &= 0b11110000; + val |= mask; + + /* Write register value back into CONFIG3 register */ + if( !wireWriteDataByte(APDS9960_CONFIG3, val) ) { + return false; + } + + return true; +} + +/** + * @brief Gets the entry proximity threshold for gesture sensing + * + * @return Current entry proximity threshold. + */ +uint8_t getGestureEnterThresh() +{ + uint8_t val; + + /* Read value from GPENTH register */ + if( !wireReadDataByte(APDS9960_GPENTH, &val) ) { + val = 0; + } + + return val; +} + +/** + * @brief Sets the entry proximity threshold for gesture sensing + * + * @param[in] threshold proximity value needed to start gesture mode + * @return True if operation successful. False otherwise. + */ +bool setGestureEnterThresh(uint8_t threshold) +{ + if( !wireWriteDataByte(APDS9960_GPENTH, threshold) ) { + return false; + } + + return true; +} + +/** + * @brief Gets the exit proximity threshold for gesture sensing + * + * @return Current exit proximity threshold. + */ +uint8_t getGestureExitThresh() +{ + uint8_t val; + + /* Read value from GEXTH register */ + if( !wireReadDataByte(APDS9960_GEXTH, &val) ) { + val = 0; + } + + return val; +} + +/** + * @brief Sets the exit proximity threshold for gesture sensing + * + * @param[in] threshold proximity value needed to end gesture mode + * @return True if operation successful. False otherwise. + */ +bool setGestureExitThresh(uint8_t threshold) +{ + if( !wireWriteDataByte(APDS9960_GEXTH, threshold) ) { + return false; + } + + return true; +} + +/** + * @brief Gets the gain of the photodiode during gesture mode + * + * Value Gain + * 0 1x + * 1 2x + * 2 4x + * 3 8x + * + * @return the current photodiode gain. 0xFF on error. + */ +uint8_t APDS9960_getGestureGain() +{ + uint8_t val; + + /* Read value from GCONF2 register */ + if( !wireReadDataByte(APDS9960_GCONF2, &val) ) { + return ERROR; + } + + /* Shift and mask out GGAIN bits */ + val = (val >> 5) & 0b00000011; + + return val; +} + +/** + * @brief Sets the gain of the photodiode during gesture mode + * + * Value Gain + * 0 1x + * 1 2x + * 2 4x + * 3 8x + * + * @param[in] gain the value for the photodiode gain + * @return True if operation successful. False otherwise. + */ +bool APDS9960_setGestureGain(uint8_t gain) +{ + uint8_t val; + + /* Read value from GCONF2 register */ + if( !wireReadDataByte(APDS9960_GCONF2, &val) ) { + return false; + } + + /* Set bits in register to given value */ + gain &= 0b00000011; + gain = gain << 5; + val &= 0b10011111; + val |= gain; + + /* Write register value back into GCONF2 register */ + if( !wireWriteDataByte(APDS9960_GCONF2, val) ) { + return false; + } + + return true; +} + +/** + * @brief Gets the drive current of the LED during gesture mode + * + * Value LED Current + * 0 100 mA + * 1 50 mA + * 2 25 mA + * 3 12.5 mA + * + * @return the LED drive current value. 0xFF on error. + */ +uint8_t APDS9960_getGestureLEDDrive() +{ + uint8_t val; + + /* Read value from GCONF2 register */ + if( !wireReadDataByte(APDS9960_GCONF2, &val) ) { + return ERROR; + } + + /* Shift and mask out GLDRIVE bits */ + val = (val >> 3) & 0b00000011; + + return val; +} + +/** + * @brief Sets the LED drive current during gesture mode + * + * Value LED Current + * 0 100 mA + * 1 50 mA + * 2 25 mA + * 3 12.5 mA + * + * @param[in] drive the value for the LED drive current + * @return True if operation successful. False otherwise. + */ +bool APDS9960_setGestureLEDDrive(uint8_t drive) +{ + uint8_t val; + + /* Read value from GCONF2 register */ + if( !wireReadDataByte(APDS9960_GCONF2, &val) ) { + return false; + } + + /* Set bits in register to given value */ + drive &= 0b00000011; + drive = drive << 3; + val &= 0b11100111; + val |= drive; + + /* Write register value back into GCONF2 register */ + if( !wireWriteDataByte(APDS9960_GCONF2, val) ) { + return false; + } + + return true; +} + +/** + * @brief Gets the time in low power mode between gesture detections + * + * Value Wait time + * 0 0 ms + * 1 2.8 ms + * 2 5.6 ms + * 3 8.4 ms + * 4 14.0 ms + * 5 22.4 ms + * 6 30.8 ms + * 7 39.2 ms + * + * @return the current wait time between gestures. 0xFF on error. + */ +uint8_t getGestureWaitTime() +{ + uint8_t val; + + /* Read value from GCONF2 register */ + if( !wireReadDataByte(APDS9960_GCONF2, &val) ) { + return ERROR; + } + + /* Mask out GWTIME bits */ + val &= 0b00000111; + + return val; +} + +/** + * @brief Sets the time in low power mode between gesture detections + * + * Value Wait time + * 0 0 ms + * 1 2.8 ms + * 2 5.6 ms + * 3 8.4 ms + * 4 14.0 ms + * 5 22.4 ms + * 6 30.8 ms + * 7 39.2 ms + * + * @param[in] the value for the wait time + * @return True if operation successful. False otherwise. + */ +bool setGestureWaitTime(uint8_t time) +{ + uint8_t val; + + /* Read value from GCONF2 register */ + if( !wireReadDataByte(APDS9960_GCONF2, &val) ) { + return false; + } + + /* Set bits in register to given value */ + time &= 0b00000111; + val &= 0b11111000; + val |= time; + + /* Write register value back into GCONF2 register */ + if( !wireWriteDataByte(APDS9960_GCONF2, val) ) { + return false; + } + + return true; +} + +/** + * @brief Gets the low threshold for ambient light interrupts + * + * @param[out] threshold current low threshold stored on the APDS-9960 + * @return True if operation successful. False otherwise. + */ +bool APDS9960_getLightIntLowThreshold(uint16_t *threshold) +{ + uint8_t val_byte; + threshold = 0; + + /* Read value from ambient light low threshold, low byte register */ + if( !wireReadDataByte(APDS9960_AILTL, &val_byte) ) { + return false; + } + *threshold = val_byte; + + /* Read value from ambient light low threshold, high byte register */ + if( !wireReadDataByte(APDS9960_AILTH, &val_byte) ) { + return false; + } + threshold = threshold + ((uint16_t)val_byte << 8); + + return true; +} + +/** + * @brief Sets the low threshold for ambient light interrupts + * + * @param[in] threshold low threshold value for interrupt to trigger + * @return True if operation successful. False otherwise. + */ +bool APDS9960_setLightIntLowThreshold(uint16_t threshold) +{ + uint8_t val_low; + uint8_t val_high; + + /* Break 16-bit threshold into 2 8-bit values */ + val_low = threshold & 0x00FF; + val_high = (threshold & 0xFF00) >> 8; + + /* Write low byte */ + if( !wireWriteDataByte(APDS9960_AILTL, val_low) ) { + return false; + } + + /* Write high byte */ + if( !wireWriteDataByte(APDS9960_AILTH, val_high) ) { + return false; + } + + return true; +} + +/** + * @brief Gets the high threshold for ambient light interrupts + * + * @param[out] threshold current low threshold stored on the APDS-9960 + * @return True if operation successful. False otherwise. + */ +bool APDS9960_getLightIntHighThreshold(uint16_t *threshold) +{ + uint8_t val_byte; + threshold = 0; + + /* Read value from ambient light high threshold, low byte register */ + if( !wireReadDataByte(APDS9960_AIHTL, &val_byte) ) { + return false; + } + *threshold = val_byte; + + /* Read value from ambient light high threshold, high byte register */ + if( !wireReadDataByte(APDS9960_AIHTH, &val_byte) ) { + return false; + } + threshold = threshold + ((uint16_t)val_byte << 8); + + return true; +} + +/** + * @brief Sets the high threshold for ambient light interrupts + * + * @param[in] threshold high threshold value for interrupt to trigger + * @return True if operation successful. False otherwise. + */ +bool APDS9960_setLightIntHighThreshold(uint16_t threshold) +{ + uint8_t val_low; + uint8_t val_high; + + /* Break 16-bit threshold into 2 8-bit values */ + val_low = threshold & 0x00FF; + val_high = (threshold & 0xFF00) >> 8; + + /* Write low byte */ + if( !wireWriteDataByte(APDS9960_AIHTL, val_low) ) { + return false; + } + + /* Write high byte */ + if( !wireWriteDataByte(APDS9960_AIHTH, val_high) ) { + return false; + } + + return true; +} + +/** + * @brief Gets the low threshold for proximity interrupts + * + * @param[out] threshold current low threshold stored on the APDS-9960 + * @return True if operation successful. False otherwise. + */ +bool APDS9960_getProximityIntLowThreshold(uint8_t *threshold) +{ + threshold = 0; + + /* Read value from proximity low threshold register */ + if( !wireReadDataByte(APDS9960_PILT, threshold) ) { + return false; + } + + return true; +} + +/** + * @brief Sets the low threshold for proximity interrupts + * + * @param[in] threshold low threshold value for interrupt to trigger + * @return True if operation successful. False otherwise. + */ +bool APDS9960_setProximityIntLowThreshold(uint8_t threshold) +{ + + /* Write threshold value to register */ + if( !wireWriteDataByte(APDS9960_PILT, threshold) ) { + return false; + } + + return true; +} + +/** + * @brief Gets the high threshold for proximity interrupts + * + * @param[out] threshold current low threshold stored on the APDS-9960 + * @return True if operation successful. False otherwise. + */ +bool APDS9960_getProximityIntHighThreshold(uint8_t *threshold) +{ + threshold = 0; + + /* Read value from proximity low threshold register */ + if( !wireReadDataByte(APDS9960_PIHT, threshold) ) { + return false; + } + + return true; +} + +/** + * @brief Sets the high threshold for proximity interrupts + * + * @param[in] threshold high threshold value for interrupt to trigger + * @return True if operation successful. False otherwise. + */ +bool APDS9960_setProximityIntHighThreshold(uint8_t threshold) +{ + + /* Write threshold value to register */ + if( !wireWriteDataByte(APDS9960_PIHT, threshold) ) { + return false; + } + + return true; +} + +/** + * @brief Gets if ambient light interrupts are enabled or not + * + * @return 1 if interrupts are enabled, 0 if not. 0xFF on error. + */ +uint8_t APDS9960_getAmbientLightIntEnable() +{ + uint8_t val; + + /* Read value from ENABLE register */ + if( !wireReadDataByte(APDS9960_ENABLE, &val) ) { + return ERROR; + } + + /* Shift and mask out AIEN bit */ + val = (val >> 4) & 0b00000001; + + return val; +} + +/** + * @brief Turns ambient light interrupts on or off + * + * @param[in] enable 1 to enable interrupts, 0 to turn them off + * @return True if operation successful. False otherwise. + */ +bool APDS9960_setAmbientLightIntEnable(uint8_t enable) +{ + uint8_t val; + + /* Read value from ENABLE register */ + if( !wireReadDataByte(APDS9960_ENABLE, &val) ) { + return false; + } + + /* Set bits in register to given value */ + enable &= 0b00000001; + enable = enable << 4; + val &= 0b11101111; + val |= enable; + + /* Write register value back into ENABLE register */ + if( !wireWriteDataByte(APDS9960_ENABLE, val) ) { + return false; + } + + return true; +} + +/** + * @brief Gets if proximity interrupts are enabled or not + * + * @return 1 if interrupts are enabled, 0 if not. 0xFF on error. + */ +uint8_t APDS9960_getProximityIntEnable() +{ + uint8_t val; + + /* Read value from ENABLE register */ + if( !wireReadDataByte(APDS9960_ENABLE, &val) ) { + return ERROR; + } + + /* Shift and mask out PIEN bit */ + val = (val >> 5) & 0b00000001; + + return val; +} + +/** + * @brief Turns proximity interrupts on or off + * + * @param[in] enable 1 to enable interrupts, 0 to turn them off + * @return True if operation successful. False otherwise. + */ +bool APDS9960_setProximityIntEnable(uint8_t enable) +{ + uint8_t val; + + /* Read value from ENABLE register */ + if( !wireReadDataByte(APDS9960_ENABLE, &val) ) { + return false; + } + + /* Set bits in register to given value */ + enable &= 0b00000001; + enable = enable << 5; + val &= 0b11011111; + val |= enable; + + /* Write register value back into ENABLE register */ + if( !wireWriteDataByte(APDS9960_ENABLE, val) ) { + return false; + } + + return true; +} + +/** + * @brief Gets if gesture interrupts are enabled or not + * + * @return 1 if interrupts are enabled, 0 if not. 0xFF on error. + */ +uint8_t APDS9960_getGestureIntEnable() +{ + uint8_t val; + + /* Read value from GCONF4 register */ + if( !wireReadDataByte(APDS9960_GCONF4, &val) ) { + return ERROR; + } + + /* Shift and mask out GIEN bit */ + val = (val >> 1) & 0b00000001; + + return val; +} + +/** + * @brief Turns gesture-related interrupts on or off + * + * @param[in] enable 1 to enable interrupts, 0 to turn them off + * @return True if operation successful. False otherwise. + */ +bool APDS9960_setGestureIntEnable(uint8_t enable) +{ + uint8_t val; + + /* Read value from GCONF4 register */ + if( !wireReadDataByte(APDS9960_GCONF4, &val) ) { + return false; + } + + /* Set bits in register to given value */ + enable &= 0b00000001; + enable = enable << 1; + val &= 0b11111101; + val |= enable; + + /* Write register value back into GCONF4 register */ + if( !wireWriteDataByte(APDS9960_GCONF4, val) ) { + return false; + } + + return true; +} + +/** + * @brief Clears the ambient light interrupt + * + * @return True if operation completed successfully. False otherwise. + */ +bool APDS9960_clearAmbientLightInt() +{ + uint8_t throwaway; + if( !wireReadDataByte(APDS9960_AICLEAR, &throwaway) ) { + return false; + } + + return true; +} + +/** + * @brief Clears the proximity interrupt + * + * @return True if operation completed successfully. False otherwise. + */ +bool APDS9960_clearProximityInt() +{ + uint8_t throwaway; + if( !wireReadDataByte(APDS9960_PICLEAR, &throwaway) ) { + return false; + } + + return true; +} + +/** + * @brief Tells if the gesture state machine is currently running + * + * @return 1 if gesture state machine is running, 0 if not. 0xFF on error. + */ +uint8_t getGestureMode() +{ + uint8_t val; + + /* Read value from GCONF4 register */ + if( !wireReadDataByte(APDS9960_GCONF4, &val) ) { + return ERROR; + } + + /* Mask out GMODE bit */ + val &= 0b00000001; + + return val; +} + +/** + * @brief Tells the state machine to either enter or exit gesture state machine + * + * @param[in] mode 1 to enter gesture state machine, 0 to exit. + * @return True if operation successful. False otherwise. + */ +bool setGestureMode(uint8_t mode) +{ + uint8_t val; + + /* Read value from GCONF4 register */ + if( !wireReadDataByte(APDS9960_GCONF4, &val) ) { + return false; + } + + /* Set bits in register to given value */ + mode &= 0b00000001; + val &= 0b11111110; + val |= mode; + + /* Write register value back into GCONF4 register */ + if( !wireWriteDataByte(APDS9960_GCONF4, val) ) { + return false; + } + + return true; +} + +/******************************************************************************* + * Raw I2C Reads and Writes + ******************************************************************************/ + +/** + * @brief Writes a single byte to the I2C device (no register) + * + * @param[in] val the 1-byte value to write to the I2C device + * @return True if successful write operation. False otherwise. + */ +bool wireWriteByte(uint8_t val) +{ + + return I2Cdev_writeByte(APDS9960_I2C_ADDR, 0, val) != I2C_ERROR; +} + +/** + * @brief Writes a single byte to the I2C device and specified register + * + * @param[in] reg the register in the I2C device to write to + * @param[in] val the 1-byte value to write to the I2C device + * @return True if successful write operation. False otherwise. + */ +bool wireWriteDataByte(uint8_t reg, uint8_t val) +{ + return I2Cdev_writeByte(APDS9960_I2C_ADDR, reg, val) != I2C_ERROR; +} + +/** + * @brief Writes a block (array) of bytes to the I2C device and register + * + * @param[in] reg the register in the I2C device to write to + * @param[in] val pointer to the beginning of the data byte array + * @param[in] len the length (in bytes) of the data to write + * @return True if successful write operation. False otherwise. + */ +bool wireWriteDataBlock( uint8_t reg, + uint8_t *val, + unsigned int len) +{ + + return I2Cdev_writeBytes(APDS9960_I2C_ADDR, reg, len, val) != I2C_ERROR; +} + +/** + * @brief Reads a single byte from the I2C device and specified register + * + * @param[in] reg the register to read from + * @param[out] the value returned from the register + * @return True if successful read operation. False otherwise. + */ +bool wireReadDataByte(uint8_t reg, uint8_t *val) +{ + + return I2Cdev_readByte(APDS9960_I2C_ADDR, reg, val, 1000); +} + +/** + * @brief Reads a block (array) of bytes from the I2C device and register + * + * @param[in] reg the register to read from + * @param[out] val pointer to the beginning of the data + * @param[in] len number of bytes to read + * @return Number of bytes read. -1 on read error. + */ +int wireReadDataBlock( uint8_t reg, + uint8_t *val, + unsigned int len) +{ + return I2Cdev_readBytes(APDS9960_I2C_ADDR, reg, len, val, 1000); +} + diff --git a/STM32/APDS9960/APDS9960.h b/STM32/APDS9960/APDS9960.h new file mode 100644 index 00000000..1f0e8616 --- /dev/null +++ b/STM32/APDS9960/APDS9960.h @@ -0,0 +1,285 @@ +/** + * @author : shmakins (shmakins@Denyss-MacBook-Pro.local) + * @file : APDS9960 + * @created : Thursday Oct 12, 2017 23:22:50 EEST + */ + +#ifndef APDS9960_H + +#define APDS9960_H +#include +#include "I2Cdev.h" +//#define DEBUG 1 + +#ifdef DEBUG +//#include "lcd.h" +#endif + +/* APDS-9960 I2C address */ +#define APDS9960_I2C_ADDR 0x39 + +/* Gesture parameters */ +#define GESTURE_THRESHOLD_OUT 10 +#define GESTURE_SENSITIVITY_1 50 +#define GESTURE_SENSITIVITY_2 20 + +/* Success code for returned values */ +#define ERROR 0xFF +#define I2C_ERROR ((int8_t)-1) + +/* Acceptable device IDs */ +#define APDS9960_ID_1 0xAB +#define APDS9960_ID_2 0x9C +#define APDS9960_ID_3 0xA8 + +/* Misc parameters */ +#define FIFO_PAUSE_TIME 30 // Wait period (ms) between FIFO reads + +/* APDS-9960 register addresses */ +#define APDS9960_ENABLE 0x80 +#define APDS9960_ATIME 0x81 +#define APDS9960_WTIME 0x83 +#define APDS9960_AILTL 0x84 +#define APDS9960_AILTH 0x85 +#define APDS9960_AIHTL 0x86 +#define APDS9960_AIHTH 0x87 +#define APDS9960_PILT 0x89 +#define APDS9960_PIHT 0x8B +#define APDS9960_PERS 0x8C +#define APDS9960_CONFIG1 0x8D +#define APDS9960_PPULSE 0x8E +#define APDS9960_CONTROL 0x8F +#define APDS9960_CONFIG2 0x90 +#define APDS9960_ID 0x92 +#define APDS9960_STATUS 0x93 +#define APDS9960_CDATAL 0x94 +#define APDS9960_CDATAH 0x95 +#define APDS9960_RDATAL 0x96 +#define APDS9960_RDATAH 0x97 +#define APDS9960_GDATAL 0x98 +#define APDS9960_GDATAH 0x99 +#define APDS9960_BDATAL 0x9A +#define APDS9960_BDATAH 0x9B +#define APDS9960_PDATA 0x9C +#define APDS9960_POFFSET_UR 0x9D +#define APDS9960_POFFSET_DL 0x9E +#define APDS9960_CONFIG3 0x9F +#define APDS9960_GPENTH 0xA0 +#define APDS9960_GEXTH 0xA1 +#define APDS9960_GCONF1 0xA2 +#define APDS9960_GCONF2 0xA3 +#define APDS9960_GOFFSET_U 0xA4 +#define APDS9960_GOFFSET_D 0xA5 +#define APDS9960_GOFFSET_L 0xA7 +#define APDS9960_GOFFSET_R 0xA9 +#define APDS9960_GPULSE 0xA6 +#define APDS9960_GCONF3 0xAA +#define APDS9960_GCONF4 0xAB +#define APDS9960_GFLVL 0xAE +#define APDS9960_GSTATUS 0xAF +#define APDS9960_IFORCE 0xE4 +#define APDS9960_PICLEAR 0xE5 +#define APDS9960_CICLEAR 0xE6 +#define APDS9960_AICLEAR 0xE7 +#define APDS9960_GFIFO_U 0xFC +#define APDS9960_GFIFO_D 0xFD +#define APDS9960_GFIFO_L 0xFE +#define APDS9960_GFIFO_R 0xFF + +/* Bit fields */ +#define APDS9960_PON 0b00000001 +#define APDS9960_AEN 0b00000010 +#define APDS9960_PEN 0b00000100 +#define APDS9960_WEN 0b00001000 +#define APSD9960_AIEN 0b00010000 +#define APDS9960_PIEN 0b00100000 +#define APDS9960_GEN 0b01000000 +#define APDS9960_GVALID 0b00000001 + +/* On/Off definitions */ +#define OFF 0 +#define ON 1 + +/* Acceptable parameters for setMode */ +#define POWER 0 +#define AMBIENT_LIGHT 1 +#define PROXIMITY 2 +#define WAIT 3 +#define AMBIENT_LIGHT_INT 4 +#define PROXIMITY_INT 5 +#define GESTURE 6 +#define ALL 7 + +/* LED Drive values */ +#define LED_DRIVE_100MA 0 +#define LED_DRIVE_50MA 1 +#define LED_DRIVE_25MA 2 +#define LED_DRIVE_12_5MA 3 + +/* Proximity Gain (PGAIN) values */ +#define PGAIN_1X 0 +#define PGAIN_2X 1 +#define PGAIN_4X 2 +#define PGAIN_8X 3 + +/* ALS Gain (AGAIN) values */ +#define AGAIN_1X 0 +#define AGAIN_4X 1 +#define AGAIN_16X 2 +#define AGAIN_64X 3 + +/* Gesture Gain (GGAIN) values */ +#define GGAIN_1X 0 +#define GGAIN_2X 1 +#define GGAIN_4X 2 +#define GGAIN_8X 3 + +/* LED Boost values */ +#define LED_BOOST_100 0 +#define LED_BOOST_150 1 +#define LED_BOOST_200 2 +#define LED_BOOST_300 3 + +/* Gesture wait time values */ +#define GWTIME_0MS 0 +#define GWTIME_2_8MS 1 +#define GWTIME_5_6MS 2 +#define GWTIME_8_4MS 3 +#define GWTIME_14_0MS 4 +#define GWTIME_22_4MS 5 +#define GWTIME_30_8MS 6 +#define GWTIME_39_2MS 7 + +/* Default values */ +#define DEFAULT_ATIME 219 // 103ms +#define DEFAULT_WTIME 246 // 27ms +#define DEFAULT_PROX_PPULSE 0x87 // 16us, 8 pulses +#define DEFAULT_GESTURE_PPULSE 0x89 // 16us, 10 pulses +#define DEFAULT_POFFSET_UR 0 // 0 offset +#define DEFAULT_POFFSET_DL 0 // 0 offset +#define DEFAULT_CONFIG1 0x60 // No 12x wait (WTIME) factor +#define DEFAULT_LDRIVE LED_DRIVE_100MA +#define DEFAULT_PGAIN PGAIN_4X +#define DEFAULT_AGAIN AGAIN_4X +#define DEFAULT_PILT 0 // Low proximity threshold +#define DEFAULT_PIHT 50 // High proximity threshold +#define DEFAULT_AILT 0xFFFF // Force interrupt for calibration +#define DEFAULT_AIHT 0 +#define DEFAULT_PERS 0x11 // 2 consecutive prox or ALS for int. +#define DEFAULT_CONFIG2 0x01 // No saturation interrupts or LED boost +#define DEFAULT_CONFIG3 0 // Enable all photodiodes, no SAI +#define DEFAULT_GPENTH 40 // Threshold for entering gesture mode +#define DEFAULT_GEXTH 30 // Threshold for exiting gesture mode +#define DEFAULT_GCONF1 0x40 // 4 gesture events for int., 1 for exit +#define DEFAULT_GGAIN GGAIN_4X +#define DEFAULT_GLDRIVE LED_DRIVE_100MA +#define DEFAULT_GWTIME GWTIME_2_8MS +#define DEFAULT_GOFFSET 0 // No offset scaling for gesture mode +#define DEFAULT_GPULSE 0xC9 // 32us, 10 pulses +#define DEFAULT_GCONF3 0 // All photodiodes active during gesture +#define DEFAULT_GIEN 0 // Disable gesture interrupts + +/* Direction definitions */ +enum { + DIR_NONE, + DIR_LEFT, + DIR_RIGHT, + DIR_UP, + DIR_DOWN, + DIR_NEAR, + DIR_FAR, + DIR_ALL +}; + +/* State definitions */ +enum { + NA_STATE, + NEAR_STATE, + FAR_STATE, + ALL_STATE +}; + +/* Container for gesture data */ +typedef struct gesture_data_type { + uint8_t u_data[32]; + uint8_t d_data[32]; + uint8_t l_data[32]; + uint8_t r_data[32]; + uint8_t index; + uint8_t total_gestures; + uint8_t in_threshold; + uint8_t out_threshold; +} gesture_data_type; + +/* APDS9960 Class */ + +bool APDS9960_init(I2C_HandleTypeDef * hi2c); +uint8_t APDS9960_getMode(); +bool APDS9960_setMode(uint8_t mode, uint8_t enable); + +/* Turn the APDS-9960 on and off */ +bool APDS9960_enablePower(); +bool APDS9960_disablePower(); + +/* Enable or disable specific sensors */ +bool APDS9960_enableLightSensor(); +bool APDS9960_disableLightSensor(); +bool APDS9960_enableProximitySensor(); +bool APDS9960_disableProximitySensor(); +bool APDS9960_enableGestureSensor(); +bool APDS9960_disableGestureSensor(); + +/* LED drive strength control */ +uint8_t APDS9960_getLEDDrive(); +bool APDS9960_setLEDDrive(uint8_t drive); +uint8_t APDS9960_getGestureLEDDrive(); +bool APDS9960_setGestureLEDDrive(uint8_t drive); + +/* Gain control */ +uint8_t APDS9960_getAmbientLightGain(); +bool APDS9960_setAmbientLightGain(uint8_t gain); +uint8_t APDS9960_getProximityGain(); +bool APDS9960_setProximityGain(uint8_t gain); +uint8_t APDS9960_getGestureGain(); +bool APDS9960_setGestureGain(uint8_t gain); + +/* Get and set light interrupt thresholds */ +bool APDS9960_getLightIntLowThreshold(uint16_t *threshold); +bool APDS9960_setLightIntLowThreshold(uint16_t threshold); +bool APDS9960_getLightIntHighThreshold(uint16_t *threshold); +bool APDS9960_setLightIntHighThreshold(uint16_t threshold); + +/* Get and set proximity interrupt thresholds */ +bool APDS9960_getProximityIntLowThreshold(uint8_t *threshold); +bool APDS9960_setProximityIntLowThreshold(uint8_t threshold); +bool APDS9960_getProximityIntHighThreshold(uint8_t *threshold); +bool APDS9960_setProximityIntHighThreshold(uint8_t threshold); + +/* Get and set interrupt enables */ +uint8_t APDS9960_getAmbientLightIntEnable(); +bool APDS9960_setAmbientLightIntEnable(uint8_t enable); +uint8_t APDS9960_getProximityIntEnable(); +bool APDS9960_setProximityIntEnable(uint8_t enable); +uint8_t APDS9960_getGestureIntEnable(); +bool APDS9960_setGestureIntEnable(uint8_t enable); + +/* Clear interrupts */ +bool APDS9960_clearAmbientLightInt(); +bool APDS9960_clearProximityInt(); + +/* Ambient light methods */ +bool APDS9960_readAmbientLight(uint16_t *val); +bool APDS9960_readRedLight(uint16_t *val); +bool APDS9960_readGreenLight(uint16_t *val); +bool APDS9960_readBlueLight(uint16_t *val); + +/* Proximity methods */ +bool APDS9960_readProximity(uint8_t *val); + +/* Gesture methods */ +bool APDS9960_isGestureAvailable(); +int APDS9960_readGesture(); + + +#endif /* end of include guard APDS9960_H */ + diff --git a/STM32/APDS9960/README.md b/STM32/APDS9960/README.md new file mode 100755 index 00000000..9f8ed5ff --- /dev/null +++ b/STM32/APDS9960/README.md @@ -0,0 +1 @@ +Ported to C and HAL for STM32 from [Arduino driver][https://github.com/sparkfun/SparkFun_APDS-9960_Sensor_Arduino_Library] From 4ad4d2492ea37b6fc975599768595d510b9efff9 Mon Sep 17 00:00:00 2001 From: Denys Fisher Date: Sun, 5 Nov 2017 13:02:51 +0200 Subject: [PATCH 181/335] typo fixes - author fix - markdown typo fix # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # On branch master # Your branch is up-to-date with 'origin/master'. # # Changes to be committed: # modified: APDS9960.c # modified: APDS9960.h # modified: README.md # --- STM32/APDS9960/APDS9960.c | 2 +- STM32/APDS9960/APDS9960.h | 2 +- STM32/APDS9960/README.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/STM32/APDS9960/APDS9960.c b/STM32/APDS9960/APDS9960.c index 7cab6f7a..af0991e9 100644 --- a/STM32/APDS9960/APDS9960.c +++ b/STM32/APDS9960/APDS9960.c @@ -1,5 +1,5 @@ /** - * @author : shmakins (shmakins@Denyss-MacBook-Pro.local) + * @author : shmakins (shmakins@gmail.com) * @file : APDS9960 * @created : Thursday Oct 12, 2017 23:44:51 EEST */ diff --git a/STM32/APDS9960/APDS9960.h b/STM32/APDS9960/APDS9960.h index 1f0e8616..2244bd21 100644 --- a/STM32/APDS9960/APDS9960.h +++ b/STM32/APDS9960/APDS9960.h @@ -1,5 +1,5 @@ /** - * @author : shmakins (shmakins@Denyss-MacBook-Pro.local) + * @author : shmakins (shmakins@gmail.com) * @file : APDS9960 * @created : Thursday Oct 12, 2017 23:22:50 EEST */ diff --git a/STM32/APDS9960/README.md b/STM32/APDS9960/README.md index 9f8ed5ff..9dce2115 100755 --- a/STM32/APDS9960/README.md +++ b/STM32/APDS9960/README.md @@ -1 +1 @@ -Ported to C and HAL for STM32 from [Arduino driver][https://github.com/sparkfun/SparkFun_APDS-9960_Sensor_Arduino_Library] +Ported to C and HAL for STM32 from [Arduino driver](https://github.com/sparkfun/SparkFun_APDS-9960_Sensor_Arduino_Library) From c0bd4ac0164c0d9187bd9cb577d86281d5872e0f Mon Sep 17 00:00:00 2001 From: Denys Fisher Date: Sun, 5 Nov 2017 15:57:25 +0200 Subject: [PATCH 182/335] fix read* method, correct refference processing --- STM32/APDS9960/APDS9960.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/STM32/APDS9960/APDS9960.c b/STM32/APDS9960/APDS9960.c index af0991e9..f1fe86dc 100644 --- a/STM32/APDS9960/APDS9960.c +++ b/STM32/APDS9960/APDS9960.c @@ -620,7 +620,7 @@ bool APDS9960_disablePower() bool APDS9960_readAmbientLight(uint16_t *val) { uint8_t val_byte; - val = 0; + *val = 0; /* Read value from clear channel, low byte register */ if( !wireReadDataByte(APDS9960_CDATAL, &val_byte) ) { @@ -632,7 +632,7 @@ bool APDS9960_readAmbientLight(uint16_t *val) if( !wireReadDataByte(APDS9960_CDATAH, &val_byte) ) { return false; } - val = val + ((uint16_t)val_byte << 8); + *val = *val + ((uint16_t)val_byte << 8); return true; } @@ -646,7 +646,7 @@ bool APDS9960_readAmbientLight(uint16_t *val) bool APDS9960_readRedLight(uint16_t *val) { uint8_t val_byte; - val = 0; + *val = 0; /* Read value from clear channel, low byte register */ if( !wireReadDataByte(APDS9960_RDATAL, &val_byte) ) { @@ -658,7 +658,7 @@ bool APDS9960_readRedLight(uint16_t *val) if( !wireReadDataByte(APDS9960_RDATAH, &val_byte) ) { return false; } - val = val + ((uint16_t)val_byte << 8); + *val = *val + ((uint16_t)val_byte << 8); return true; } @@ -672,7 +672,7 @@ bool APDS9960_readRedLight(uint16_t *val) bool APDS9960_readGreenLight(uint16_t *val) { uint8_t val_byte; - val = 0; + *val = 0; /* Read value from clear channel, low byte register */ if( !wireReadDataByte(APDS9960_GDATAL, &val_byte) ) { @@ -684,7 +684,7 @@ bool APDS9960_readGreenLight(uint16_t *val) if( !wireReadDataByte(APDS9960_GDATAH, &val_byte) ) { return false; } - val = val + ((uint16_t)val_byte << 8); + *val = *val + ((uint16_t)val_byte << 8); return true; } @@ -698,7 +698,7 @@ bool APDS9960_readGreenLight(uint16_t *val) bool APDS9960_readBlueLight(uint16_t *val) { uint8_t val_byte; - val = 0; + *val = 0; /* Read value from clear channel, low byte register */ if( !wireReadDataByte(APDS9960_BDATAL, &val_byte) ) { @@ -710,7 +710,7 @@ bool APDS9960_readBlueLight(uint16_t *val) if( !wireReadDataByte(APDS9960_BDATAH, &val_byte) ) { return false; } - val = val + ((uint16_t)val_byte << 8); + *val = *val + ((uint16_t)val_byte << 8); return true; } @@ -727,13 +727,14 @@ bool APDS9960_readBlueLight(uint16_t *val) */ bool APDS9960_readProximity(uint8_t *val) { - val = 0; + uint8_t val_byte; + *val = 0; /* Read value from proximity data register */ - if( !wireReadDataByte(APDS9960_PDATA, val) ) { + if( !wireReadDataByte(APDS9960_PDATA, &val_byte) ) { return false; } - + *val = val_byte; return true; } @@ -1685,7 +1686,7 @@ bool setGestureWaitTime(uint8_t time) bool APDS9960_getLightIntLowThreshold(uint16_t *threshold) { uint8_t val_byte; - threshold = 0; + *threshold = 0; /* Read value from ambient light low threshold, low byte register */ if( !wireReadDataByte(APDS9960_AILTL, &val_byte) ) { @@ -1697,7 +1698,7 @@ bool APDS9960_getLightIntLowThreshold(uint16_t *threshold) if( !wireReadDataByte(APDS9960_AILTH, &val_byte) ) { return false; } - threshold = threshold + ((uint16_t)val_byte << 8); + *threshold = *threshold + ((uint16_t)val_byte << 8); return true; } @@ -1739,7 +1740,7 @@ bool APDS9960_setLightIntLowThreshold(uint16_t threshold) bool APDS9960_getLightIntHighThreshold(uint16_t *threshold) { uint8_t val_byte; - threshold = 0; + *threshold = 0; /* Read value from ambient light high threshold, low byte register */ if( !wireReadDataByte(APDS9960_AIHTL, &val_byte) ) { @@ -1751,7 +1752,7 @@ bool APDS9960_getLightIntHighThreshold(uint16_t *threshold) if( !wireReadDataByte(APDS9960_AIHTH, &val_byte) ) { return false; } - threshold = threshold + ((uint16_t)val_byte << 8); + *threshold = *threshold + ((uint16_t)val_byte << 8); return true; } From c233a5640f9823afdc8a64ff0e1750fe1cf36c01 Mon Sep 17 00:00:00 2001 From: Bernhard Guillon Date: Sat, 11 Nov 2017 12:29:50 +0100 Subject: [PATCH 183/335] ESP32_ESP-IDF: make the example compileable Fix typo of the header file include. Without the following error occurs. CXX build/main/example.o /home/nice/develop/esp32/i2cdevlib/ESP32_ESP-IDF/main/./example.cpp:12:21: fatal error: mpu6050.h: No such file or directory compilation terminated. make[1]: *** [/home/nice/develop/esp32/esp-idf/make/component_wrapper.mk:229: example.o] Error 1 make: *** [/home/nice/develop/esp32//esp-idf/make/project.mk:399: component-main-build] Error 2 --- ESP32_ESP-IDF/main/example.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ESP32_ESP-IDF/main/example.cpp b/ESP32_ESP-IDF/main/example.cpp index 9a5340c0..befaacc5 100644 --- a/ESP32_ESP-IDF/main/example.cpp +++ b/ESP32_ESP-IDF/main/example.cpp @@ -9,7 +9,7 @@ #include #include #include -#include "mpu6050.h" +#include "MPU6050.h" #include "MPU6050_6Axis_MotionApps20.h" #include "sdkconfig.h" From faebd713e3447ef001419a07825dab706d3658df Mon Sep 17 00:00:00 2001 From: Bernhard Guillon Date: Sat, 11 Nov 2017 12:48:34 +0100 Subject: [PATCH 184/335] ESP32_ESP-IDF/components/I2Cdev/I2Cdev.cpp: remove debug leftover Remove the unused variable: uint8_t data2[] = {(uint8_t)(data & 0xff), (uint8_t)(data>>8)}; Because it seems that it is a development leftover. It has just the opponent byteorder then data1 which is used. Without the compiler is complaining about this unused variable. /home/nice/develop/esp32/i2cdevlib/ESP32_ESP-IDF/components/I2Cdev/./I2Cdev.cpp: In static member function 'static bool I2Cdev::writeWord(uint8_t, uint8_t, uint16_t)': /home/nice/develop/esp32/i2cdevlib/ESP32_ESP-IDF/components/I2Cdev/./I2Cdev.cpp:152:10: warning: unused variable 'data2' [-Wunused-variable] uint8_t data2[] = {(uint8_t)(data & 0xff), (uint8_t)(data>>8)}; --- ESP32_ESP-IDF/components/I2Cdev/I2Cdev.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/ESP32_ESP-IDF/components/I2Cdev/I2Cdev.cpp b/ESP32_ESP-IDF/components/I2Cdev/I2Cdev.cpp index 6d03d1e1..7ea8467c 100644 --- a/ESP32_ESP-IDF/components/I2Cdev/I2Cdev.cpp +++ b/ESP32_ESP-IDF/components/I2Cdev/I2Cdev.cpp @@ -149,7 +149,6 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 bool I2Cdev::writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data){ uint8_t data1[] = {(uint8_t)(data>>8), (uint8_t)(data & 0xff)}; - uint8_t data2[] = {(uint8_t)(data & 0xff), (uint8_t)(data>>8)}; writeBytes(devAddr, regAddr, 2, data1); return true; } From e455e497a0d659dc8cf2570dc237f22620340308 Mon Sep 17 00:00:00 2001 From: Jan Jurca Date: Tue, 12 Dec 2017 19:42:40 +0100 Subject: [PATCH 185/335] DS1307 Arduino library - build error caused by non const progmem fixed --- Arduino/DS1307/DS1307.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Arduino/DS1307/DS1307.cpp b/Arduino/DS1307/DS1307.cpp index 1d01761c..c1cfc88a 100644 --- a/Arduino/DS1307/DS1307.cpp +++ b/Arduino/DS1307/DS1307.cpp @@ -360,7 +360,7 @@ void DS1307::setDateTime24(uint16_t year, uint8_t month, uint8_t day, uint8_t ho //////////////////////////////////////////////////////////////////////////////// // utility code, some of this could be exposed in the DateTime API if needed - static uint8_t daysInMonth [] PROGMEM = { 31,28,31,30,31,30,31,31,30,31,30,31 }; + static const uint8_t daysInMonth [] PROGMEM = { 31,28,31,30,31,30,31,31,30,31,30,31 }; // number of days since 2000/01/01, valid for 2001..2099 static uint16_t date2days(uint16_t y, uint8_t m, uint8_t d) { From 463c47880f4bf500864d71fca91bdcc9f795b816 Mon Sep 17 00:00:00 2001 From: Anatoli Arkhipenko Date: Thu, 14 Dec 2017 15:01:41 -0500 Subject: [PATCH 186/335] Added working Arduino-MPU9250 back --- Arduino/MPU9250 | 1 + 1 file changed, 1 insertion(+) create mode 160000 Arduino/MPU9250 diff --git a/Arduino/MPU9250 b/Arduino/MPU9250 new file mode 160000 index 00000000..6b9b2665 --- /dev/null +++ b/Arduino/MPU9250 @@ -0,0 +1 @@ +Subproject commit 6b9b266511377a2dd77806c88328a13d1ccd3ed7 From 16d48ee24c161bc41ea7fc9f23779aa37504e5b5 Mon Sep 17 00:00:00 2001 From: Anatoli Arkhipenko Date: Thu, 14 Dec 2017 15:10:32 -0500 Subject: [PATCH 187/335] Added working MPU9250 back --- Arduino/MPU9250 | 1 - Arduino/MPU9250/BMP180.cpp | 174 + Arduino/MPU9250/BMP180.h | 58 + Arduino/MPU9250/MPU9250.cpp | 3167 +++++++++++++++++ Arduino/MPU9250/MPU9250.h | 1004 ++++++ Arduino/MPU9250/README.md | 23 + .../IMU_10DOF_Test/IMU_10DOF_Test.ino | 291 ++ 7 files changed, 4717 insertions(+), 1 deletion(-) delete mode 160000 Arduino/MPU9250 create mode 100644 Arduino/MPU9250/BMP180.cpp create mode 100644 Arduino/MPU9250/BMP180.h create mode 100644 Arduino/MPU9250/MPU9250.cpp create mode 100644 Arduino/MPU9250/MPU9250.h create mode 100644 Arduino/MPU9250/README.md create mode 100644 Arduino/MPU9250/examples/IMU_10DOF_Test/IMU_10DOF_Test.ino diff --git a/Arduino/MPU9250 b/Arduino/MPU9250 deleted file mode 160000 index 6b9b2665..00000000 --- a/Arduino/MPU9250 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 6b9b266511377a2dd77806c88328a13d1ccd3ed7 diff --git a/Arduino/MPU9250/BMP180.cpp b/Arduino/MPU9250/BMP180.cpp new file mode 100644 index 00000000..aaa9c170 --- /dev/null +++ b/Arduino/MPU9250/BMP180.cpp @@ -0,0 +1,174 @@ +/* + Barometer library V1.0 + 2010 Copyright (c) Seeed Technology Inc. All right reserved. + + Original Author: LG + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#include "BMP180.h" +#include +#include + +void BMP180::init(void) +{ + Wire.begin(); + ac1 = bmp180ReadInt(0xAA); + ac2 = bmp180ReadInt(0xAC); + ac3 = bmp180ReadInt(0xAE); + ac4 = bmp180ReadInt(0xB0); + ac5 = bmp180ReadInt(0xB2); + ac6 = bmp180ReadInt(0xB4); + b1 = bmp180ReadInt(0xB6); + b2 = bmp180ReadInt(0xB8); + mb = bmp180ReadInt(0xBA); + mc = bmp180ReadInt(0xBC); + md = bmp180ReadInt(0xBE); +} +// Read 1 byte from the BMP085 at 'address' +// Return: the read byte; +char BMP180::bmp180Read(unsigned char address) +{ + //Wire.begin(); + unsigned char data; + Wire.beginTransmission(BMP180_ADDRESS); + Wire.write(address); + Wire.endTransmission(); + + Wire.requestFrom(BMP180_ADDRESS, 1); + while(!Wire.available()); + return Wire.read(); +} +// Read 2 bytes from the BMP085 +// First byte will be from 'address' +// Second byte will be from 'address'+1 +int BMP180::bmp180ReadInt(unsigned char address) +{ + unsigned char msb, lsb; + Wire.beginTransmission(BMP180_ADDRESS); + Wire.write(address); + Wire.endTransmission(); + Wire.requestFrom(BMP180_ADDRESS, 2); + while(Wire.available()<2); + msb = Wire.read(); + lsb = Wire.read(); + return (int) msb<<8 | lsb; +} +// Read the uncompensated temperature value +unsigned int BMP180::bmp180ReadUT() +{ + unsigned int ut; + Wire.beginTransmission(BMP180_ADDRESS); + Wire.write(0xF4); + Wire.write(0x2E); + Wire.endTransmission(); + delay(5); + ut = bmp180ReadInt(0xF6); + return ut; +} +// Read the uncompensated pressure value +unsigned long BMP180::bmp180ReadUP() +{ + unsigned char msb, lsb, xlsb; + unsigned long up = 0; + Wire.beginTransmission(BMP180_ADDRESS); + Wire.write(0xF4); + Wire.write(0x34 + (OSS<<6)); + Wire.endTransmission(); + delay(2 + (3<> (8-OSS); + return up; +} +void BMP180::writeRegister(int deviceAddress, byte address, byte val) +{ + Wire.beginTransmission(deviceAddress); // start transmission to device + Wire.write(address); // send register address + Wire.write(val); // send value to write + Wire.endTransmission(); // end transmission +} +int BMP180::readRegister(int deviceAddress, byte address) +{ + int v; + Wire.beginTransmission(deviceAddress); + Wire.write(address); // register to read + Wire.endTransmission(); + + Wire.requestFrom(deviceAddress, 1); // read a byte + + while(!Wire.available()) { + // waiting + } + + v = Wire.read(); + return v; +} +float BMP180::calcAltitude(float pressure) +{ + float A = pressure/101325; + float B = 1/5.25588; + float C = pow(A,B); + C = 1 - C; + C = C /0.0000225577; + return C; +} +float BMP180::bmp180GetTemperature(unsigned int ut) +{ + long x1, x2; + + x1 = (((long)ut - (long)ac6)*(long)ac5) >> 15; + x2 = ((long)mc << 11)/(x1 + md); + PressureCompensate = x1 + x2; + + float temp = ((PressureCompensate + 8)>>4); + temp = temp /10; + + return temp; +} +long BMP180::bmp180GetPressure(unsigned long up) +{ + long x1, x2, x3, b3, b6, p; + unsigned long b4, b7; + b6 = PressureCompensate - 4000; + x1 = (b2 * (b6 * b6)>>12)>>11; + x2 = (ac2 * b6)>>11; + x3 = x1 + x2; + b3 = (((((long)ac1)*4 + x3)<>2; + + // Calculate B4 + x1 = (ac3 * b6)>>13; + x2 = (b1 * ((b6 * b6)>>12))>>16; + x3 = ((x1 + x2) + 2)>>2; + b4 = (ac4 * (unsigned long)(x3 + 32768))>>15; + + b7 = ((unsigned long)(up - b3) * (50000>>OSS)); + if (b7 < 0x80000000) + p = (b7<<1)/b4; + else + p = (b7/b4)<<1; + + x1 = (p>>8) * (p>>8); + x1 = (x1 * 3038)>>16; + x2 = (-7357 * p)>>16; + p += (x1 + x2 + 3791)>>4; + + long temp = p; + return temp; +} + diff --git a/Arduino/MPU9250/BMP180.h b/Arduino/MPU9250/BMP180.h new file mode 100644 index 00000000..b8faac8d --- /dev/null +++ b/Arduino/MPU9250/BMP180.h @@ -0,0 +1,58 @@ +/* + Barometer library V1.0 + 2010 Copyright (c) Seeed Technology Inc. All right reserved. + + Original Author: LG + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#ifndef __BAROMETER_H__ +#define __BAROMETER_H__ + +#include +#include + +const unsigned char OSS = 0; +#define BMP180_ADDRESS 0x77 +class BMP180 +{ +public: + void init(void); + long PressureCompensate; + float bmp180GetTemperature(unsigned int ut); + long bmp180GetPressure(unsigned long up); + float calcAltitude(float pressure); + unsigned int bmp180ReadUT(void); + unsigned long bmp180ReadUP(void); + +private: + int ac1; + int ac2; + int ac3; + unsigned int ac4; + unsigned int ac5; + unsigned int ac6; + int b1; + int b2; + int mb; + int mc; + int md; + char bmp180Read(unsigned char address); + int bmp180ReadInt(unsigned char address); + void writeRegister(int deviceAddress, byte address, byte val); + int readRegister(int deviceAddress, byte address); +}; + +#endif diff --git a/Arduino/MPU9250/MPU9250.cpp b/Arduino/MPU9250/MPU9250.cpp new file mode 100644 index 00000000..62d71fcb --- /dev/null +++ b/Arduino/MPU9250/MPU9250.cpp @@ -0,0 +1,3167 @@ +// I2Cdev library collection - MPU9250 I2C device class +// Based on InvenSense MPU-9250 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00) +// 8/24/2011 by Jeff Rowberg +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// ... - ongoing debug release + +// NOTE: THIS IS ONLY A PARIAL RELEASE. THIS DEVICE CLASS IS CURRENTLY UNDERGOING ACTIVE +// DEVELOPMENT AND IS STILL MISSING SOME IMPORTANT FEATURES. PLEASE KEEP THIS IN MIND IF +// YOU DECIDE TO USE THIS PARTICULAR CODE FOR ANYTHING. + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2012 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#include "MPU9250.h" + +/** Default constructor, uses default I2C address. + * @see MPU9250_DEFAULT_ADDRESS + */ +MPU9250::MPU9250() { + devAddr = MPU9250_DEFAULT_ADDRESS; +} + +/** Specific address constructor. + * @param address I2C address + * @see MPU9250_DEFAULT_ADDRESS + * @see MPU9250_ADDRESS_AD0_LOW + * @see MPU9250_ADDRESS_AD0_HIGH + */ +MPU9250::MPU9250(uint8_t address) { + devAddr = address; +} + +/** Power on and prepare for general usage. + * This will activate the device and take it out of sleep mode (which must be done + * after start-up). This function also sets both the accelerometer and the gyroscope + * to their most sensitive settings, namely +/- 2g and +/- 250 degrees/sec, and sets + * the clock source to use the X Gyro for reference, which is slightly better than + * the default internal clock source. + */ +void MPU9250::initialize() { + setSleepEnabled(false); // thanks to Jack Elston for pointing this one out! + setClockSource(MPU9250_CLOCK_PLL_XGYRO); + setFullScaleGyroRange(MPU9250_GYRO_FS_250); + setFullScaleAccelRange(MPU9250_ACCEL_FS_2); +} + +/** Verify the I2C connection. + * Make sure the device is connected and responds as expected. + * @return True if connection is valid, false otherwise + */ +bool MPU9250::testConnection() { + return getDeviceID() == 0x71; +} + +// AUX_VDDIO register (InvenSense demo code calls this RA_*G_OFFS_TC) + +/** Get the auxiliary I2C supply voltage level. + * When set to 1, the auxiliary I2C bus high logic level is VDD. When cleared to + * 0, the auxiliary I2C bus high logic level is VLOGIC. This does not apply to + * the MPU-6000, which does not have a VLOGIC pin. + * @return I2C supply voltage level (0=VLOGIC, 1=VDD) + */ +uint8_t MPU9250::getAuxVDDIOLevel() { + I2Cdev::readBit(devAddr, MPU9250_RA_YG_OFFS_TC, MPU9250_TC_PWR_MODE_BIT, buffer); + return buffer[0]; +} +/** Set the auxiliary I2C supply voltage level. + * When set to 1, the auxiliary I2C bus high logic level is VDD. When cleared to + * 0, the auxiliary I2C bus high logic level is VLOGIC. This does not apply to + * the MPU-6000, which does not have a VLOGIC pin. + * @param level I2C supply voltage level (0=VLOGIC, 1=VDD) + */ +void MPU9250::setAuxVDDIOLevel(uint8_t level) { + I2Cdev::writeBit(devAddr, MPU9250_RA_YG_OFFS_TC, MPU9250_TC_PWR_MODE_BIT, level); +} + +// SMPLRT_DIV register + +/** Get gyroscope output rate divider. + * The sensor register output, FIFO output, DMP sampling, Motion detection, Zero + * Motion detection, and Free Fall detection are all based on the Sample Rate. + * The Sample Rate is generated by dividing the gyroscope output rate by + * SMPLRT_DIV: + * + * Sample Rate = Gyroscope Output Rate / (1 + SMPLRT_DIV) + * + * where Gyroscope Output Rate = 8kHz when the DLPF is disabled (DLPF_CFG = 0 or + * 7), and 1kHz when the DLPF is enabled (see Register 26). + * + * Note: The accelerometer output rate is 1kHz. This means that for a Sample + * Rate greater than 1kHz, the same accelerometer sample may be output to the + * FIFO, DMP, and sensor registers more than once. + * + * For a diagram of the gyroscope and accelerometer signal paths, see Section 8 + * of the MPU-6000/MPU-9250 Product Specification document. + * + * @return Current sample rate + * @see MPU9250_RA_SMPLRT_DIV + */ +uint8_t MPU9250::getRate() { + I2Cdev::readByte(devAddr, MPU9250_RA_SMPLRT_DIV, buffer); + return buffer[0]; +} +/** Set gyroscope sample rate divider. + * @param rate New sample rate divider + * @see getRate() + * @see MPU9250_RA_SMPLRT_DIV + */ +void MPU9250::setRate(uint8_t rate) { + I2Cdev::writeByte(devAddr, MPU9250_RA_SMPLRT_DIV, rate); +} + +// CONFIG register + +/** Get external FSYNC configuration. + * Configures the external Frame Synchronization (FSYNC) pin sampling. An + * external signal connected to the FSYNC pin can be sampled by configuring + * EXT_SYNC_SET. Signal changes to the FSYNC pin are latched so that short + * strobes may be captured. The latched FSYNC signal will be sampled at the + * Sampling Rate, as defined in register 25. After sampling, the latch will + * reset to the current FSYNC signal state. + * + * The sampled value will be reported in place of the least significant bit in + * a sensor data register determined by the value of EXT_SYNC_SET according to + * the following table. + * + *
+ * EXT_SYNC_SET | FSYNC Bit Location
+ * -------------+-------------------
+ * 0            | Input disabled
+ * 1            | TEMP_OUT_L[0]
+ * 2            | GYRO_XOUT_L[0]
+ * 3            | GYRO_YOUT_L[0]
+ * 4            | GYRO_ZOUT_L[0]
+ * 5            | ACCEL_XOUT_L[0]
+ * 6            | ACCEL_YOUT_L[0]
+ * 7            | ACCEL_ZOUT_L[0]
+ * 
+ * + * @return FSYNC configuration value + */ +uint8_t MPU9250::getExternalFrameSync() { + I2Cdev::readBits(devAddr, MPU9250_RA_CONFIG, MPU9250_CFG_EXT_SYNC_SET_BIT, MPU9250_CFG_EXT_SYNC_SET_LENGTH, buffer); + return buffer[0]; +} +/** Set external FSYNC configuration. + * @see getExternalFrameSync() + * @see MPU9250_RA_CONFIG + * @param sync New FSYNC configuration value + */ +void MPU9250::setExternalFrameSync(uint8_t sync) { + I2Cdev::writeBits(devAddr, MPU9250_RA_CONFIG, MPU9250_CFG_EXT_SYNC_SET_BIT, MPU9250_CFG_EXT_SYNC_SET_LENGTH, sync); +} +/** Get digital low-pass filter configuration. + * The DLPF_CFG parameter sets the digital low pass filter configuration. It + * also determines the internal sampling rate used by the device as shown in + * the table below. + * + * Note: The accelerometer output rate is 1kHz. This means that for a Sample + * Rate greater than 1kHz, the same accelerometer sample may be output to the + * FIFO, DMP, and sensor registers more than once. + * + *
+ *          |   ACCELEROMETER    |           GYROSCOPE
+ * DLPF_CFG | Bandwidth | Delay  | Bandwidth | Delay  | Sample Rate
+ * ---------+-----------+--------+-----------+--------+-------------
+ * 0        | 260Hz     | 0ms    | 256Hz     | 0.98ms | 8kHz
+ * 1        | 184Hz     | 2.0ms  | 188Hz     | 1.9ms  | 1kHz
+ * 2        | 94Hz      | 3.0ms  | 98Hz      | 2.8ms  | 1kHz
+ * 3        | 44Hz      | 4.9ms  | 42Hz      | 4.8ms  | 1kHz
+ * 4        | 21Hz      | 8.5ms  | 20Hz      | 8.3ms  | 1kHz
+ * 5        | 10Hz      | 13.8ms | 10Hz      | 13.4ms | 1kHz
+ * 6        | 5Hz       | 19.0ms | 5Hz       | 18.6ms | 1kHz
+ * 7        |   -- Reserved --   |   -- Reserved --   | Reserved
+ * 
+ * + * @return DLFP configuration + * @see MPU9250_RA_CONFIG + * @see MPU9250_CFG_DLPF_CFG_BIT + * @see MPU9250_CFG_DLPF_CFG_LENGTH + */ +uint8_t MPU9250::getDLPFMode() { + I2Cdev::readBits(devAddr, MPU9250_RA_CONFIG, MPU9250_CFG_DLPF_CFG_BIT, MPU9250_CFG_DLPF_CFG_LENGTH, buffer); + return buffer[0]; +} +/** Set digital low-pass filter configuration. + * @param mode New DLFP configuration setting + * @see getDLPFBandwidth() + * @see MPU9250_DLPF_BW_256 + * @see MPU9250_RA_CONFIG + * @see MPU9250_CFG_DLPF_CFG_BIT + * @see MPU9250_CFG_DLPF_CFG_LENGTH + */ +void MPU9250::setDLPFMode(uint8_t mode) { + I2Cdev::writeBits(devAddr, MPU9250_RA_CONFIG, MPU9250_CFG_DLPF_CFG_BIT, MPU9250_CFG_DLPF_CFG_LENGTH, mode); +} + +// GYRO_CONFIG register + +/** Get full-scale gyroscope range. + * The FS_SEL parameter allows setting the full-scale range of the gyro sensors, + * as described in the table below. + * + *
+ * 0 = +/- 250 degrees/sec
+ * 1 = +/- 500 degrees/sec
+ * 2 = +/- 1000 degrees/sec
+ * 3 = +/- 2000 degrees/sec
+ * 
+ * + * @return Current full-scale gyroscope range setting + * @see MPU9250_GYRO_FS_250 + * @see MPU9250_RA_GYRO_CONFIG + * @see MPU9250_GCONFIG_FS_SEL_BIT + * @see MPU9250_GCONFIG_FS_SEL_LENGTH + */ +uint8_t MPU9250::getFullScaleGyroRange() { + I2Cdev::readBits(devAddr, MPU9250_RA_GYRO_CONFIG, MPU9250_GCONFIG_FS_SEL_BIT, MPU9250_GCONFIG_FS_SEL_LENGTH, buffer); + return buffer[0]; +} +/** Set full-scale gyroscope range. + * @param range New full-scale gyroscope range value + * @see getFullScaleRange() + * @see MPU9250_GYRO_FS_250 + * @see MPU9250_RA_GYRO_CONFIG + * @see MPU9250_GCONFIG_FS_SEL_BIT + * @see MPU9250_GCONFIG_FS_SEL_LENGTH + */ +void MPU9250::setFullScaleGyroRange(uint8_t range) { + I2Cdev::writeBits(devAddr, MPU9250_RA_GYRO_CONFIG, MPU9250_GCONFIG_FS_SEL_BIT, MPU9250_GCONFIG_FS_SEL_LENGTH, range); +} + +// ACCEL_CONFIG register + +/** Get self-test enabled setting for accelerometer X axis. + * @return Self-test enabled value + * @see MPU9250_RA_ACCEL_CONFIG + */ +bool MPU9250::getAccelXSelfTest() { + I2Cdev::readBit(devAddr, MPU9250_RA_ACCEL_CONFIG, MPU9250_ACONFIG_XA_ST_BIT, buffer); + return buffer[0]; +} +/** Get self-test enabled setting for accelerometer X axis. + * @param enabled Self-test enabled value + * @see MPU9250_RA_ACCEL_CONFIG + */ +void MPU9250::setAccelXSelfTest(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9250_RA_ACCEL_CONFIG, MPU9250_ACONFIG_XA_ST_BIT, enabled); +} +/** Get self-test enabled value for accelerometer Y axis. + * @return Self-test enabled value + * @see MPU9250_RA_ACCEL_CONFIG + */ +bool MPU9250::getAccelYSelfTest() { + I2Cdev::readBit(devAddr, MPU9250_RA_ACCEL_CONFIG, MPU9250_ACONFIG_YA_ST_BIT, buffer); + return buffer[0]; +} +/** Get self-test enabled value for accelerometer Y axis. + * @param enabled Self-test enabled value + * @see MPU9250_RA_ACCEL_CONFIG + */ +void MPU9250::setAccelYSelfTest(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9250_RA_ACCEL_CONFIG, MPU9250_ACONFIG_YA_ST_BIT, enabled); +} +/** Get self-test enabled value for accelerometer Z axis. + * @return Self-test enabled value + * @see MPU9250_RA_ACCEL_CONFIG + */ +bool MPU9250::getAccelZSelfTest() { + I2Cdev::readBit(devAddr, MPU9250_RA_ACCEL_CONFIG, MPU9250_ACONFIG_ZA_ST_BIT, buffer); + return buffer[0]; +} +/** Set self-test enabled value for accelerometer Z axis. + * @param enabled Self-test enabled value + * @see MPU9250_RA_ACCEL_CONFIG + */ +void MPU9250::setAccelZSelfTest(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9250_RA_ACCEL_CONFIG, MPU9250_ACONFIG_ZA_ST_BIT, enabled); +} +/** Get full-scale accelerometer range. + * The FS_SEL parameter allows setting the full-scale range of the accelerometer + * sensors, as described in the table below. + * + *
+ * 0 = +/- 2g
+ * 1 = +/- 4g
+ * 2 = +/- 8g
+ * 3 = +/- 16g
+ * 
+ * + * @return Current full-scale accelerometer range setting + * @see MPU9250_ACCEL_FS_2 + * @see MPU9250_RA_ACCEL_CONFIG + * @see MPU9250_ACONFIG_AFS_SEL_BIT + * @see MPU9250_ACONFIG_AFS_SEL_LENGTH + */ +uint8_t MPU9250::getFullScaleAccelRange() { + I2Cdev::readBits(devAddr, MPU9250_RA_ACCEL_CONFIG, MPU9250_ACONFIG_AFS_SEL_BIT, MPU9250_ACONFIG_AFS_SEL_LENGTH, buffer); + return buffer[0]; +} +/** Set full-scale accelerometer range. + * @param range New full-scale accelerometer range setting + * @see getFullScaleAccelRange() + */ +void MPU9250::setFullScaleAccelRange(uint8_t range) { + I2Cdev::writeBits(devAddr, MPU9250_RA_ACCEL_CONFIG, MPU9250_ACONFIG_AFS_SEL_BIT, MPU9250_ACONFIG_AFS_SEL_LENGTH, range); +} +/** Get the high-pass filter configuration. + * The DHPF is a filter module in the path leading to motion detectors (Free + * Fall, Motion threshold, and Zero Motion). The high pass filter output is not + * available to the data registers (see Figure in Section 8 of the MPU-6000/ + * MPU-9250 Product Specification document). + * + * The high pass filter has three modes: + * + *
+ *    Reset: The filter output settles to zero within one sample. This
+ *           effectively disables the high pass filter. This mode may be toggled
+ *           to quickly settle the filter.
+ *
+ *    On:    The high pass filter will pass signals above the cut off frequency.
+ *
+ *    Hold:  When triggered, the filter holds the present sample. The filter
+ *           output will be the difference between the input sample and the held
+ *           sample.
+ * 
+ * + *
+ * ACCEL_HPF | Filter Mode | Cut-off Frequency
+ * ----------+-------------+------------------
+ * 0         | Reset       | None
+ * 1         | On          | 5Hz
+ * 2         | On          | 2.5Hz
+ * 3         | On          | 1.25Hz
+ * 4         | On          | 0.63Hz
+ * 7         | Hold        | None
+ * 
+ * + * @return Current high-pass filter configuration + * @see MPU9250_DHPF_RESET + * @see MPU9250_RA_ACCEL_CONFIG + */ +uint8_t MPU9250::getDHPFMode() { + I2Cdev::readBits(devAddr, MPU9250_RA_ACCEL_CONFIG, MPU9250_ACONFIG_ACCEL_HPF_BIT, MPU9250_ACONFIG_ACCEL_HPF_LENGTH, buffer); + return buffer[0]; +} +/** Set the high-pass filter configuration. + * @param bandwidth New high-pass filter configuration + * @see setDHPFMode() + * @see MPU9250_DHPF_RESET + * @see MPU9250_RA_ACCEL_CONFIG + */ +void MPU9250::setDHPFMode(uint8_t bandwidth) { + I2Cdev::writeBits(devAddr, MPU9250_RA_ACCEL_CONFIG, MPU9250_ACONFIG_ACCEL_HPF_BIT, MPU9250_ACONFIG_ACCEL_HPF_LENGTH, bandwidth); +} + +// FF_THR register + +/** Get free-fall event acceleration threshold. + * This register configures the detection threshold for Free Fall event + * detection. The unit of FF_THR is 1LSB = 2mg. Free Fall is detected when the + * absolute value of the accelerometer measurements for the three axes are each + * less than the detection threshold. This condition increments the Free Fall + * duration counter (Register 30). The Free Fall interrupt is triggered when the + * Free Fall duration counter reaches the time specified in FF_DUR. + * + * For more details on the Free Fall detection interrupt, see Section 8.2 of the + * MPU-6000/MPU-9250 Product Specification document as well as Registers 56 and + * 58 of this document. + * + * @return Current free-fall acceleration threshold value (LSB = 2mg) + * @see MPU9250_RA_FF_THR + */ +uint8_t MPU9250::getFreefallDetectionThreshold() { + I2Cdev::readByte(devAddr, MPU9250_RA_FF_THR, buffer); + return buffer[0]; +} +/** Get free-fall event acceleration threshold. + * @param threshold New free-fall acceleration threshold value (LSB = 2mg) + * @see getFreefallDetectionThreshold() + * @see MPU9250_RA_FF_THR + */ +void MPU9250::setFreefallDetectionThreshold(uint8_t threshold) { + I2Cdev::writeByte(devAddr, MPU9250_RA_FF_THR, threshold); +} + +// FF_DUR register + +/** Get free-fall event duration threshold. + * This register configures the duration counter threshold for Free Fall event + * detection. The duration counter ticks at 1kHz, therefore FF_DUR has a unit + * of 1 LSB = 1 ms. + * + * The Free Fall duration counter increments while the absolute value of the + * accelerometer measurements are each less than the detection threshold + * (Register 29). The Free Fall interrupt is triggered when the Free Fall + * duration counter reaches the time specified in this register. + * + * For more details on the Free Fall detection interrupt, see Section 8.2 of + * the MPU-6000/MPU-9250 Product Specification document as well as Registers 56 + * and 58 of this document. + * + * @return Current free-fall duration threshold value (LSB = 1ms) + * @see MPU9250_RA_FF_DUR + */ +uint8_t MPU9250::getFreefallDetectionDuration() { + I2Cdev::readByte(devAddr, MPU9250_RA_FF_DUR, buffer); + return buffer[0]; +} +/** Get free-fall event duration threshold. + * @param duration New free-fall duration threshold value (LSB = 1ms) + * @see getFreefallDetectionDuration() + * @see MPU9250_RA_FF_DUR + */ +void MPU9250::setFreefallDetectionDuration(uint8_t duration) { + I2Cdev::writeByte(devAddr, MPU9250_RA_FF_DUR, duration); +} + +// MOT_THR register + +/** Get motion detection event acceleration threshold. + * This register configures the detection threshold for Motion interrupt + * generation. The unit of MOT_THR is 1LSB = 2mg. Motion is detected when the + * absolute value of any of the accelerometer measurements exceeds this Motion + * detection threshold. This condition increments the Motion detection duration + * counter (Register 32). The Motion detection interrupt is triggered when the + * Motion Detection counter reaches the time count specified in MOT_DUR + * (Register 32). + * + * The Motion interrupt will indicate the axis and polarity of detected motion + * in MOT_DETECT_STATUS (Register 97). + * + * For more details on the Motion detection interrupt, see Section 8.3 of the + * MPU-6000/MPU-9250 Product Specification document as well as Registers 56 and + * 58 of this document. + * + * @return Current motion detection acceleration threshold value (LSB = 2mg) + * @see MPU9250_RA_MOT_THR + */ +uint8_t MPU9250::getMotionDetectionThreshold() { + I2Cdev::readByte(devAddr, MPU9250_RA_MOT_THR, buffer); + return buffer[0]; +} +/** Set free-fall event acceleration threshold. + * @param threshold New motion detection acceleration threshold value (LSB = 2mg) + * @see getMotionDetectionThreshold() + * @see MPU9250_RA_MOT_THR + */ +void MPU9250::setMotionDetectionThreshold(uint8_t threshold) { + I2Cdev::writeByte(devAddr, MPU9250_RA_MOT_THR, threshold); +} + +// MOT_DUR register + +/** Get motion detection event duration threshold. + * This register configures the duration counter threshold for Motion interrupt + * generation. The duration counter ticks at 1 kHz, therefore MOT_DUR has a unit + * of 1LSB = 1ms. The Motion detection duration counter increments when the + * absolute value of any of the accelerometer measurements exceeds the Motion + * detection threshold (Register 31). The Motion detection interrupt is + * triggered when the Motion detection counter reaches the time count specified + * in this register. + * + * For more details on the Motion detection interrupt, see Section 8.3 of the + * MPU-6000/MPU-9250 Product Specification document. + * + * @return Current motion detection duration threshold value (LSB = 1ms) + * @see MPU9250_RA_MOT_DUR + */ +uint8_t MPU9250::getMotionDetectionDuration() { + I2Cdev::readByte(devAddr, MPU9250_RA_MOT_DUR, buffer); + return buffer[0]; +} +/** Set motion detection event duration threshold. + * @param duration New motion detection duration threshold value (LSB = 1ms) + * @see getMotionDetectionDuration() + * @see MPU9250_RA_MOT_DUR + */ +void MPU9250::setMotionDetectionDuration(uint8_t duration) { + I2Cdev::writeByte(devAddr, MPU9250_RA_MOT_DUR, duration); +} + +// ZRMOT_THR register + +/** Get zero motion detection event acceleration threshold. + * This register configures the detection threshold for Zero Motion interrupt + * generation. The unit of ZRMOT_THR is 1LSB = 2mg. Zero Motion is detected when + * the absolute value of the accelerometer measurements for the 3 axes are each + * less than the detection threshold. This condition increments the Zero Motion + * duration counter (Register 34). The Zero Motion interrupt is triggered when + * the Zero Motion duration counter reaches the time count specified in + * ZRMOT_DUR (Register 34). + * + * Unlike Free Fall or Motion detection, Zero Motion detection triggers an + * interrupt both when Zero Motion is first detected and when Zero Motion is no + * longer detected. + * + * When a zero motion event is detected, a Zero Motion Status will be indicated + * in the MOT_DETECT_STATUS register (Register 97). When a motion-to-zero-motion + * condition is detected, the status bit is set to 1. When a zero-motion-to- + * motion condition is detected, the status bit is set to 0. + * + * For more details on the Zero Motion detection interrupt, see Section 8.4 of + * the MPU-6000/MPU-9250 Product Specification document as well as Registers 56 + * and 58 of this document. + * + * @return Current zero motion detection acceleration threshold value (LSB = 2mg) + * @see MPU9250_RA_ZRMOT_THR + */ +uint8_t MPU9250::getZeroMotionDetectionThreshold() { + I2Cdev::readByte(devAddr, MPU9250_RA_ZRMOT_THR, buffer); + return buffer[0]; +} +/** Set zero motion detection event acceleration threshold. + * @param threshold New zero motion detection acceleration threshold value (LSB = 2mg) + * @see getZeroMotionDetectionThreshold() + * @see MPU9250_RA_ZRMOT_THR + */ +void MPU9250::setZeroMotionDetectionThreshold(uint8_t threshold) { + I2Cdev::writeByte(devAddr, MPU9250_RA_ZRMOT_THR, threshold); +} + +// ZRMOT_DUR register + +/** Get zero motion detection event duration threshold. + * This register configures the duration counter threshold for Zero Motion + * interrupt generation. The duration counter ticks at 16 Hz, therefore + * ZRMOT_DUR has a unit of 1 LSB = 64 ms. The Zero Motion duration counter + * increments while the absolute value of the accelerometer measurements are + * each less than the detection threshold (Register 33). The Zero Motion + * interrupt is triggered when the Zero Motion duration counter reaches the time + * count specified in this register. + * + * For more details on the Zero Motion detection interrupt, see Section 8.4 of + * the MPU-6000/MPU-9250 Product Specification document, as well as Registers 56 + * and 58 of this document. + * + * @return Current zero motion detection duration threshold value (LSB = 64ms) + * @see MPU9250_RA_ZRMOT_DUR + */ +uint8_t MPU9250::getZeroMotionDetectionDuration() { + I2Cdev::readByte(devAddr, MPU9250_RA_ZRMOT_DUR, buffer); + return buffer[0]; +} +/** Set zero motion detection event duration threshold. + * @param duration New zero motion detection duration threshold value (LSB = 1ms) + * @see getZeroMotionDetectionDuration() + * @see MPU9250_RA_ZRMOT_DUR + */ +void MPU9250::setZeroMotionDetectionDuration(uint8_t duration) { + I2Cdev::writeByte(devAddr, MPU9250_RA_ZRMOT_DUR, duration); +} + +// FIFO_EN register + +/** Get temperature FIFO enabled value. + * When set to 1, this bit enables TEMP_OUT_H and TEMP_OUT_L (Registers 65 and + * 66) to be written into the FIFO buffer. + * @return Current temperature FIFO enabled value + * @see MPU9250_RA_FIFO_EN + */ +bool MPU9250::getTempFIFOEnabled() { + I2Cdev::readBit(devAddr, MPU9250_RA_FIFO_EN, MPU9250_TEMP_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set temperature FIFO enabled value. + * @param enabled New temperature FIFO enabled value + * @see getTempFIFOEnabled() + * @see MPU9250_RA_FIFO_EN + */ +void MPU9250::setTempFIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9250_RA_FIFO_EN, MPU9250_TEMP_FIFO_EN_BIT, enabled); +} +/** Get gyroscope X-axis FIFO enabled value. + * When set to 1, this bit enables GYRO_XOUT_H and GYRO_XOUT_L (Registers 67 and + * 68) to be written into the FIFO buffer. + * @return Current gyroscope X-axis FIFO enabled value + * @see MPU9250_RA_FIFO_EN + */ +bool MPU9250::getXGyroFIFOEnabled() { + I2Cdev::readBit(devAddr, MPU9250_RA_FIFO_EN, MPU9250_XG_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set gyroscope X-axis FIFO enabled value. + * @param enabled New gyroscope X-axis FIFO enabled value + * @see getXGyroFIFOEnabled() + * @see MPU9250_RA_FIFO_EN + */ +void MPU9250::setXGyroFIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9250_RA_FIFO_EN, MPU9250_XG_FIFO_EN_BIT, enabled); +} +/** Get gyroscope Y-axis FIFO enabled value. + * When set to 1, this bit enables GYRO_YOUT_H and GYRO_YOUT_L (Registers 69 and + * 70) to be written into the FIFO buffer. + * @return Current gyroscope Y-axis FIFO enabled value + * @see MPU9250_RA_FIFO_EN + */ +bool MPU9250::getYGyroFIFOEnabled() { + I2Cdev::readBit(devAddr, MPU9250_RA_FIFO_EN, MPU9250_YG_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set gyroscope Y-axis FIFO enabled value. + * @param enabled New gyroscope Y-axis FIFO enabled value + * @see getYGyroFIFOEnabled() + * @see MPU9250_RA_FIFO_EN + */ +void MPU9250::setYGyroFIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9250_RA_FIFO_EN, MPU9250_YG_FIFO_EN_BIT, enabled); +} +/** Get gyroscope Z-axis FIFO enabled value. + * When set to 1, this bit enables GYRO_ZOUT_H and GYRO_ZOUT_L (Registers 71 and + * 72) to be written into the FIFO buffer. + * @return Current gyroscope Z-axis FIFO enabled value + * @see MPU9250_RA_FIFO_EN + */ +bool MPU9250::getZGyroFIFOEnabled() { + I2Cdev::readBit(devAddr, MPU9250_RA_FIFO_EN, MPU9250_ZG_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set gyroscope Z-axis FIFO enabled value. + * @param enabled New gyroscope Z-axis FIFO enabled value + * @see getZGyroFIFOEnabled() + * @see MPU9250_RA_FIFO_EN + */ +void MPU9250::setZGyroFIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9250_RA_FIFO_EN, MPU9250_ZG_FIFO_EN_BIT, enabled); +} +/** Get accelerometer FIFO enabled value. + * When set to 1, this bit enables ACCEL_XOUT_H, ACCEL_XOUT_L, ACCEL_YOUT_H, + * ACCEL_YOUT_L, ACCEL_ZOUT_H, and ACCEL_ZOUT_L (Registers 59 to 64) to be + * written into the FIFO buffer. + * @return Current accelerometer FIFO enabled value + * @see MPU9250_RA_FIFO_EN + */ +bool MPU9250::getAccelFIFOEnabled() { + I2Cdev::readBit(devAddr, MPU9250_RA_FIFO_EN, MPU9250_ACCEL_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set accelerometer FIFO enabled value. + * @param enabled New accelerometer FIFO enabled value + * @see getAccelFIFOEnabled() + * @see MPU9250_RA_FIFO_EN + */ +void MPU9250::setAccelFIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9250_RA_FIFO_EN, MPU9250_ACCEL_FIFO_EN_BIT, enabled); +} +/** Get Slave 2 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 2 to be written into the FIFO buffer. + * @return Current Slave 2 FIFO enabled value + * @see MPU9250_RA_FIFO_EN + */ +bool MPU9250::getSlave2FIFOEnabled() { + I2Cdev::readBit(devAddr, MPU9250_RA_FIFO_EN, MPU9250_SLV2_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set Slave 2 FIFO enabled value. + * @param enabled New Slave 2 FIFO enabled value + * @see getSlave2FIFOEnabled() + * @see MPU9250_RA_FIFO_EN + */ +void MPU9250::setSlave2FIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9250_RA_FIFO_EN, MPU9250_SLV2_FIFO_EN_BIT, enabled); +} +/** Get Slave 1 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 1 to be written into the FIFO buffer. + * @return Current Slave 1 FIFO enabled value + * @see MPU9250_RA_FIFO_EN + */ +bool MPU9250::getSlave1FIFOEnabled() { + I2Cdev::readBit(devAddr, MPU9250_RA_FIFO_EN, MPU9250_SLV1_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set Slave 1 FIFO enabled value. + * @param enabled New Slave 1 FIFO enabled value + * @see getSlave1FIFOEnabled() + * @see MPU9250_RA_FIFO_EN + */ +void MPU9250::setSlave1FIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9250_RA_FIFO_EN, MPU9250_SLV1_FIFO_EN_BIT, enabled); +} +/** Get Slave 0 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 0 to be written into the FIFO buffer. + * @return Current Slave 0 FIFO enabled value + * @see MPU9250_RA_FIFO_EN + */ +bool MPU9250::getSlave0FIFOEnabled() { + I2Cdev::readBit(devAddr, MPU9250_RA_FIFO_EN, MPU9250_SLV0_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set Slave 0 FIFO enabled value. + * @param enabled New Slave 0 FIFO enabled value + * @see getSlave0FIFOEnabled() + * @see MPU9250_RA_FIFO_EN + */ +void MPU9250::setSlave0FIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9250_RA_FIFO_EN, MPU9250_SLV0_FIFO_EN_BIT, enabled); +} + +// I2C_MST_CTRL register + +/** Get multi-master enabled value. + * Multi-master capability allows multiple I2C masters to operate on the same + * bus. In circuits where multi-master capability is required, set MULT_MST_EN + * to 1. This will increase current drawn by approximately 30uA. + * + * In circuits where multi-master capability is required, the state of the I2C + * bus must always be monitored by each separate I2C Master. Before an I2C + * Master can assume arbitration of the bus, it must first confirm that no other + * I2C Master has arbitration of the bus. When MULT_MST_EN is set to 1, the + * MPU-60X0's bus arbitration detection logic is turned on, enabling it to + * detect when the bus is available. + * + * @return Current multi-master enabled value + * @see MPU9250_RA_I2C_MST_CTRL + */ +bool MPU9250::getMultiMasterEnabled() { + I2Cdev::readBit(devAddr, MPU9250_RA_I2C_MST_CTRL, MPU9250_MULT_MST_EN_BIT, buffer); + return buffer[0]; +} +/** Set multi-master enabled value. + * @param enabled New multi-master enabled value + * @see getMultiMasterEnabled() + * @see MPU9250_RA_I2C_MST_CTRL + */ +void MPU9250::setMultiMasterEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9250_RA_I2C_MST_CTRL, MPU9250_MULT_MST_EN_BIT, enabled); +} +/** Get wait-for-external-sensor-data enabled value. + * When the WAIT_FOR_ES bit is set to 1, the Data Ready interrupt will be + * delayed until External Sensor data from the Slave Devices are loaded into the + * EXT_SENS_DATA registers. This is used to ensure that both the internal sensor + * data (i.e. from gyro and accel) and external sensor data have been loaded to + * their respective data registers (i.e. the data is synced) when the Data Ready + * interrupt is triggered. + * + * @return Current wait-for-external-sensor-data enabled value + * @see MPU9250_RA_I2C_MST_CTRL + */ +bool MPU9250::getWaitForExternalSensorEnabled() { + I2Cdev::readBit(devAddr, MPU9250_RA_I2C_MST_CTRL, MPU9250_WAIT_FOR_ES_BIT, buffer); + return buffer[0]; +} +/** Set wait-for-external-sensor-data enabled value. + * @param enabled New wait-for-external-sensor-data enabled value + * @see getWaitForExternalSensorEnabled() + * @see MPU9250_RA_I2C_MST_CTRL + */ +void MPU9250::setWaitForExternalSensorEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9250_RA_I2C_MST_CTRL, MPU9250_WAIT_FOR_ES_BIT, enabled); +} +/** Get Slave 3 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 3 to be written into the FIFO buffer. + * @return Current Slave 3 FIFO enabled value + * @see MPU9250_RA_MST_CTRL + */ +bool MPU9250::getSlave3FIFOEnabled() { + I2Cdev::readBit(devAddr, MPU9250_RA_I2C_MST_CTRL, MPU9250_SLV_3_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set Slave 3 FIFO enabled value. + * @param enabled New Slave 3 FIFO enabled value + * @see getSlave3FIFOEnabled() + * @see MPU9250_RA_MST_CTRL + */ +void MPU9250::setSlave3FIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9250_RA_I2C_MST_CTRL, MPU9250_SLV_3_FIFO_EN_BIT, enabled); +} +/** Get slave read/write transition enabled value. + * The I2C_MST_P_NSR bit configures the I2C Master's transition from one slave + * read to the next slave read. If the bit equals 0, there will be a restart + * between reads. If the bit equals 1, there will be a stop followed by a start + * of the following read. When a write transaction follows a read transaction, + * the stop followed by a start of the successive write will be always used. + * + * @return Current slave read/write transition enabled value + * @see MPU9250_RA_I2C_MST_CTRL + */ +bool MPU9250::getSlaveReadWriteTransitionEnabled() { + I2Cdev::readBit(devAddr, MPU9250_RA_I2C_MST_CTRL, MPU9250_I2C_MST_P_NSR_BIT, buffer); + return buffer[0]; +} +/** Set slave read/write transition enabled value. + * @param enabled New slave read/write transition enabled value + * @see getSlaveReadWriteTransitionEnabled() + * @see MPU9250_RA_I2C_MST_CTRL + */ +void MPU9250::setSlaveReadWriteTransitionEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9250_RA_I2C_MST_CTRL, MPU9250_I2C_MST_P_NSR_BIT, enabled); +} +/** Get I2C master clock speed. + * I2C_MST_CLK is a 4 bit unsigned value which configures a divider on the + * MPU-60X0 internal 8MHz clock. It sets the I2C master clock speed according to + * the following table: + * + *
+ * I2C_MST_CLK | I2C Master Clock Speed | 8MHz Clock Divider
+ * ------------+------------------------+-------------------
+ * 0           | 348kHz                 | 23
+ * 1           | 333kHz                 | 24
+ * 2           | 320kHz                 | 25
+ * 3           | 308kHz                 | 26
+ * 4           | 296kHz                 | 27
+ * 5           | 286kHz                 | 28
+ * 6           | 276kHz                 | 29
+ * 7           | 267kHz                 | 30
+ * 8           | 258kHz                 | 31
+ * 9           | 500kHz                 | 16
+ * 10          | 471kHz                 | 17
+ * 11          | 444kHz                 | 18
+ * 12          | 421kHz                 | 19
+ * 13          | 400kHz                 | 20
+ * 14          | 381kHz                 | 21
+ * 15          | 364kHz                 | 22
+ * 
+ * + * @return Current I2C master clock speed + * @see MPU9250_RA_I2C_MST_CTRL + */ +uint8_t MPU9250::getMasterClockSpeed() { + I2Cdev::readBits(devAddr, MPU9250_RA_I2C_MST_CTRL, MPU9250_I2C_MST_CLK_BIT, MPU9250_I2C_MST_CLK_LENGTH, buffer); + return buffer[0]; +} +/** Set I2C master clock speed. + * @reparam speed Current I2C master clock speed + * @see MPU9250_RA_I2C_MST_CTRL + */ +void MPU9250::setMasterClockSpeed(uint8_t speed) { + I2Cdev::writeBits(devAddr, MPU9250_RA_I2C_MST_CTRL, MPU9250_I2C_MST_CLK_BIT, MPU9250_I2C_MST_CLK_LENGTH, speed); +} + +// I2C_SLV* registers (Slave 0-3) + +/** Get the I2C address of the specified slave (0-3). + * Note that Bit 7 (MSB) controls read/write mode. If Bit 7 is set, it's a read + * operation, and if it is cleared, then it's a write operation. The remaining + * bits (6-0) are the 7-bit device address of the slave device. + * + * In read mode, the result of the read is placed in the lowest available + * EXT_SENS_DATA register. For further information regarding the allocation of + * read results, please refer to the EXT_SENS_DATA register description + * (Registers 73 - 96). + * + * The MPU-9250 supports a total of five slaves, but Slave 4 has unique + * characteristics, and so it has its own functions (getSlave4* and setSlave4*). + * + * I2C data transactions are performed at the Sample Rate, as defined in + * Register 25. The user is responsible for ensuring that I2C data transactions + * to and from each enabled Slave can be completed within a single period of the + * Sample Rate. + * + * The I2C slave access rate can be reduced relative to the Sample Rate. This + * reduced access rate is determined by I2C_MST_DLY (Register 52). Whether a + * slave's access rate is reduced relative to the Sample Rate is determined by + * I2C_MST_DELAY_CTRL (Register 103). + * + * The processing order for the slaves is fixed. The sequence followed for + * processing the slaves is Slave 0, Slave 1, Slave 2, Slave 3 and Slave 4. If a + * particular Slave is disabled it will be skipped. + * + * Each slave can either be accessed at the sample rate or at a reduced sample + * rate. In a case where some slaves are accessed at the Sample Rate and some + * slaves are accessed at the reduced rate, the sequence of accessing the slaves + * (Slave 0 to Slave 4) is still followed. However, the reduced rate slaves will + * be skipped if their access rate dictates that they should not be accessed + * during that particular cycle. For further information regarding the reduced + * access rate, please refer to Register 52. Whether a slave is accessed at the + * Sample Rate or at the reduced rate is determined by the Delay Enable bits in + * Register 103. + * + * @param num Slave number (0-3) + * @return Current address for specified slave + * @see MPU9250_RA_I2C_SLV0_ADDR + */ +uint8_t MPU9250::getSlaveAddress(uint8_t num) { + if (num > 3) return 0; + I2Cdev::readByte(devAddr, MPU9250_RA_I2C_SLV0_ADDR + num*3, buffer); + return buffer[0]; +} +/** Set the I2C address of the specified slave (0-3). + * @param num Slave number (0-3) + * @param address New address for specified slave + * @see getSlaveAddress() + * @see MPU9250_RA_I2C_SLV0_ADDR + */ +void MPU9250::setSlaveAddress(uint8_t num, uint8_t address) { + if (num > 3) return; + I2Cdev::writeByte(devAddr, MPU9250_RA_I2C_SLV0_ADDR + num*3, address); +} +/** Get the active internal register for the specified slave (0-3). + * Read/write operations for this slave will be done to whatever internal + * register address is stored in this MPU register. + * + * The MPU-9250 supports a total of five slaves, but Slave 4 has unique + * characteristics, and so it has its own functions. + * + * @param num Slave number (0-3) + * @return Current active register for specified slave + * @see MPU9250_RA_I2C_SLV0_REG + */ +uint8_t MPU9250::getSlaveRegister(uint8_t num) { + if (num > 3) return 0; + I2Cdev::readByte(devAddr, MPU9250_RA_I2C_SLV0_REG + num*3, buffer); + return buffer[0]; +} +/** Set the active internal register for the specified slave (0-3). + * @param num Slave number (0-3) + * @param reg New active register for specified slave + * @see getSlaveRegister() + * @see MPU9250_RA_I2C_SLV0_REG + */ +void MPU9250::setSlaveRegister(uint8_t num, uint8_t reg) { + if (num > 3) return; + I2Cdev::writeByte(devAddr, MPU9250_RA_I2C_SLV0_REG + num*3, reg); +} +/** Get the enabled value for the specified slave (0-3). + * When set to 1, this bit enables Slave 0 for data transfer operations. When + * cleared to 0, this bit disables Slave 0 from data transfer operations. + * @param num Slave number (0-3) + * @return Current enabled value for specified slave + * @see MPU9250_RA_I2C_SLV0_CTRL + */ +bool MPU9250::getSlaveEnabled(uint8_t num) { + if (num > 3) return 0; + I2Cdev::readBit(devAddr, MPU9250_RA_I2C_SLV0_CTRL + num*3, MPU9250_I2C_SLV_EN_BIT, buffer); + return buffer[0]; +} +/** Set the enabled value for the specified slave (0-3). + * @param num Slave number (0-3) + * @param enabled New enabled value for specified slave + * @see getSlaveEnabled() + * @see MPU9250_RA_I2C_SLV0_CTRL + */ +void MPU9250::setSlaveEnabled(uint8_t num, bool enabled) { + if (num > 3) return; + I2Cdev::writeBit(devAddr, MPU9250_RA_I2C_SLV0_CTRL + num*3, MPU9250_I2C_SLV_EN_BIT, enabled); +} +/** Get word pair byte-swapping enabled for the specified slave (0-3). + * When set to 1, this bit enables byte swapping. When byte swapping is enabled, + * the high and low bytes of a word pair are swapped. Please refer to + * I2C_SLV0_GRP for the pairing convention of the word pairs. When cleared to 0, + * bytes transferred to and from Slave 0 will be written to EXT_SENS_DATA + * registers in the order they were transferred. + * + * @param num Slave number (0-3) + * @return Current word pair byte-swapping enabled value for specified slave + * @see MPU9250_RA_I2C_SLV0_CTRL + */ +bool MPU9250::getSlaveWordByteSwap(uint8_t num) { + if (num > 3) return 0; + I2Cdev::readBit(devAddr, MPU9250_RA_I2C_SLV0_CTRL + num*3, MPU9250_I2C_SLV_BYTE_SW_BIT, buffer); + return buffer[0]; +} +/** Set word pair byte-swapping enabled for the specified slave (0-3). + * @param num Slave number (0-3) + * @param enabled New word pair byte-swapping enabled value for specified slave + * @see getSlaveWordByteSwap() + * @see MPU9250_RA_I2C_SLV0_CTRL + */ +void MPU9250::setSlaveWordByteSwap(uint8_t num, bool enabled) { + if (num > 3) return; + I2Cdev::writeBit(devAddr, MPU9250_RA_I2C_SLV0_CTRL + num*3, MPU9250_I2C_SLV_BYTE_SW_BIT, enabled); +} +/** Get write mode for the specified slave (0-3). + * When set to 1, the transaction will read or write data only. When cleared to + * 0, the transaction will write a register address prior to reading or writing + * data. This should equal 0 when specifying the register address within the + * Slave device to/from which the ensuing data transaction will take place. + * + * @param num Slave number (0-3) + * @return Current write mode for specified slave (0 = register address + data, 1 = data only) + * @see MPU9250_RA_I2C_SLV0_CTRL + */ +bool MPU9250::getSlaveWriteMode(uint8_t num) { + if (num > 3) return 0; + I2Cdev::readBit(devAddr, MPU9250_RA_I2C_SLV0_CTRL + num*3, MPU9250_I2C_SLV_REG_DIS_BIT, buffer); + return buffer[0]; +} +/** Set write mode for the specified slave (0-3). + * @param num Slave number (0-3) + * @param mode New write mode for specified slave (0 = register address + data, 1 = data only) + * @see getSlaveWriteMode() + * @see MPU9250_RA_I2C_SLV0_CTRL + */ +void MPU9250::setSlaveWriteMode(uint8_t num, bool mode) { + if (num > 3) return; + I2Cdev::writeBit(devAddr, MPU9250_RA_I2C_SLV0_CTRL + num*3, MPU9250_I2C_SLV_REG_DIS_BIT, mode); +} +/** Get word pair grouping order offset for the specified slave (0-3). + * This sets specifies the grouping order of word pairs received from registers. + * When cleared to 0, bytes from register addresses 0 and 1, 2 and 3, etc (even, + * then odd register addresses) are paired to form a word. When set to 1, bytes + * from register addresses are paired 1 and 2, 3 and 4, etc. (odd, then even + * register addresses) are paired to form a word. + * + * @param num Slave number (0-3) + * @return Current word pair grouping order offset for specified slave + * @see MPU9250_RA_I2C_SLV0_CTRL + */ +bool MPU9250::getSlaveWordGroupOffset(uint8_t num) { + if (num > 3) return 0; + I2Cdev::readBit(devAddr, MPU9250_RA_I2C_SLV0_CTRL + num*3, MPU9250_I2C_SLV_GRP_BIT, buffer); + return buffer[0]; +} +/** Set word pair grouping order offset for the specified slave (0-3). + * @param num Slave number (0-3) + * @param enabled New word pair grouping order offset for specified slave + * @see getSlaveWordGroupOffset() + * @see MPU9250_RA_I2C_SLV0_CTRL + */ +void MPU9250::setSlaveWordGroupOffset(uint8_t num, bool enabled) { + if (num > 3) return; + I2Cdev::writeBit(devAddr, MPU9250_RA_I2C_SLV0_CTRL + num*3, MPU9250_I2C_SLV_GRP_BIT, enabled); +} +/** Get number of bytes to read for the specified slave (0-3). + * Specifies the number of bytes transferred to and from Slave 0. Clearing this + * bit to 0 is equivalent to disabling the register by writing 0 to I2C_SLV0_EN. + * @param num Slave number (0-3) + * @return Number of bytes to read for specified slave + * @see MPU9250_RA_I2C_SLV0_CTRL + */ +uint8_t MPU9250::getSlaveDataLength(uint8_t num) { + if (num > 3) return 0; + I2Cdev::readBits(devAddr, MPU9250_RA_I2C_SLV0_CTRL + num*3, MPU9250_I2C_SLV_LEN_BIT, MPU9250_I2C_SLV_LEN_LENGTH, buffer); + return buffer[0]; +} +/** Set number of bytes to read for the specified slave (0-3). + * @param num Slave number (0-3) + * @param length Number of bytes to read for specified slave + * @see getSlaveDataLength() + * @see MPU9250_RA_I2C_SLV0_CTRL + */ +void MPU9250::setSlaveDataLength(uint8_t num, uint8_t length) { + if (num > 3) return; + I2Cdev::writeBits(devAddr, MPU9250_RA_I2C_SLV0_CTRL + num*3, MPU9250_I2C_SLV_LEN_BIT, MPU9250_I2C_SLV_LEN_LENGTH, length); +} + +// I2C_SLV* registers (Slave 4) + +/** Get the I2C address of Slave 4. + * Note that Bit 7 (MSB) controls read/write mode. If Bit 7 is set, it's a read + * operation, and if it is cleared, then it's a write operation. The remaining + * bits (6-0) are the 7-bit device address of the slave device. + * + * @return Current address for Slave 4 + * @see getSlaveAddress() + * @see MPU9250_RA_I2C_SLV4_ADDR + */ +uint8_t MPU9250::getSlave4Address() { + I2Cdev::readByte(devAddr, MPU9250_RA_I2C_SLV4_ADDR, buffer); + return buffer[0]; +} +/** Set the I2C address of Slave 4. + * @param address New address for Slave 4 + * @see getSlave4Address() + * @see MPU9250_RA_I2C_SLV4_ADDR + */ +void MPU9250::setSlave4Address(uint8_t address) { + I2Cdev::writeByte(devAddr, MPU9250_RA_I2C_SLV4_ADDR, address); +} +/** Get the active internal register for the Slave 4. + * Read/write operations for this slave will be done to whatever internal + * register address is stored in this MPU register. + * + * @return Current active register for Slave 4 + * @see MPU9250_RA_I2C_SLV4_REG + */ +uint8_t MPU9250::getSlave4Register() { + I2Cdev::readByte(devAddr, MPU9250_RA_I2C_SLV4_REG, buffer); + return buffer[0]; +} +/** Set the active internal register for Slave 4. + * @param reg New active register for Slave 4 + * @see getSlave4Register() + * @see MPU9250_RA_I2C_SLV4_REG + */ +void MPU9250::setSlave4Register(uint8_t reg) { + I2Cdev::writeByte(devAddr, MPU9250_RA_I2C_SLV4_REG, reg); +} +/** Set new byte to write to Slave 4. + * This register stores the data to be written into the Slave 4. If I2C_SLV4_RW + * is set 1 (set to read), this register has no effect. + * @param data New byte to write to Slave 4 + * @see MPU9250_RA_I2C_SLV4_DO + */ +void MPU9250::setSlave4OutputByte(uint8_t data) { + I2Cdev::writeByte(devAddr, MPU9250_RA_I2C_SLV4_DO, data); +} +/** Get the enabled value for the Slave 4. + * When set to 1, this bit enables Slave 4 for data transfer operations. When + * cleared to 0, this bit disables Slave 4 from data transfer operations. + * @return Current enabled value for Slave 4 + * @see MPU9250_RA_I2C_SLV4_CTRL + */ +bool MPU9250::getSlave4Enabled() { + I2Cdev::readBit(devAddr, MPU9250_RA_I2C_SLV4_CTRL, MPU9250_I2C_SLV4_EN_BIT, buffer); + return buffer[0]; +} +/** Set the enabled value for Slave 4. + * @param enabled New enabled value for Slave 4 + * @see getSlave4Enabled() + * @see MPU9250_RA_I2C_SLV4_CTRL + */ +void MPU9250::setSlave4Enabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9250_RA_I2C_SLV4_CTRL, MPU9250_I2C_SLV4_EN_BIT, enabled); +} +/** Get the enabled value for Slave 4 transaction interrupts. + * When set to 1, this bit enables the generation of an interrupt signal upon + * completion of a Slave 4 transaction. When cleared to 0, this bit disables the + * generation of an interrupt signal upon completion of a Slave 4 transaction. + * The interrupt status can be observed in Register 54. + * + * @return Current enabled value for Slave 4 transaction interrupts. + * @see MPU9250_RA_I2C_SLV4_CTRL + */ +bool MPU9250::getSlave4InterruptEnabled() { + I2Cdev::readBit(devAddr, MPU9250_RA_I2C_SLV4_CTRL, MPU9250_I2C_SLV4_INT_EN_BIT, buffer); + return buffer[0]; +} +/** Set the enabled value for Slave 4 transaction interrupts. + * @param enabled New enabled value for Slave 4 transaction interrupts. + * @see getSlave4InterruptEnabled() + * @see MPU9250_RA_I2C_SLV4_CTRL + */ +void MPU9250::setSlave4InterruptEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9250_RA_I2C_SLV4_CTRL, MPU9250_I2C_SLV4_INT_EN_BIT, enabled); +} +/** Get write mode for Slave 4. + * When set to 1, the transaction will read or write data only. When cleared to + * 0, the transaction will write a register address prior to reading or writing + * data. This should equal 0 when specifying the register address within the + * Slave device to/from which the ensuing data transaction will take place. + * + * @return Current write mode for Slave 4 (0 = register address + data, 1 = data only) + * @see MPU9250_RA_I2C_SLV4_CTRL + */ +bool MPU9250::getSlave4WriteMode() { + I2Cdev::readBit(devAddr, MPU9250_RA_I2C_SLV4_CTRL, MPU9250_I2C_SLV4_REG_DIS_BIT, buffer); + return buffer[0]; +} +/** Set write mode for the Slave 4. + * @param mode New write mode for Slave 4 (0 = register address + data, 1 = data only) + * @see getSlave4WriteMode() + * @see MPU9250_RA_I2C_SLV4_CTRL + */ +void MPU9250::setSlave4WriteMode(bool mode) { + I2Cdev::writeBit(devAddr, MPU9250_RA_I2C_SLV4_CTRL, MPU9250_I2C_SLV4_REG_DIS_BIT, mode); +} +/** Get Slave 4 master delay value. + * This configures the reduced access rate of I2C slaves relative to the Sample + * Rate. When a slave's access rate is decreased relative to the Sample Rate, + * the slave is accessed every: + * + * 1 / (1 + I2C_MST_DLY) samples + * + * This base Sample Rate in turn is determined by SMPLRT_DIV (register 25) and + * DLPF_CFG (register 26). Whether a slave's access rate is reduced relative to + * the Sample Rate is determined by I2C_MST_DELAY_CTRL (register 103). For + * further information regarding the Sample Rate, please refer to register 25. + * + * @return Current Slave 4 master delay value + * @see MPU9250_RA_I2C_SLV4_CTRL + */ +uint8_t MPU9250::getSlave4MasterDelay() { + I2Cdev::readBits(devAddr, MPU9250_RA_I2C_SLV4_CTRL, MPU9250_I2C_SLV4_MST_DLY_BIT, MPU9250_I2C_SLV4_MST_DLY_LENGTH, buffer); + return buffer[0]; +} +/** Set Slave 4 master delay value. + * @param delay New Slave 4 master delay value + * @see getSlave4MasterDelay() + * @see MPU9250_RA_I2C_SLV4_CTRL + */ +void MPU9250::setSlave4MasterDelay(uint8_t delay) { + I2Cdev::writeBits(devAddr, MPU9250_RA_I2C_SLV4_CTRL, MPU9250_I2C_SLV4_MST_DLY_BIT, MPU9250_I2C_SLV4_MST_DLY_LENGTH, delay); +} +/** Get last available byte read from Slave 4. + * This register stores the data read from Slave 4. This field is populated + * after a read transaction. + * @return Last available byte read from to Slave 4 + * @see MPU9250_RA_I2C_SLV4_DI + */ +uint8_t MPU9250::getSlate4InputByte() { + I2Cdev::readByte(devAddr, MPU9250_RA_I2C_SLV4_DI, buffer); + return buffer[0]; +} + +// I2C_MST_STATUS register + +/** Get FSYNC interrupt status. + * This bit reflects the status of the FSYNC interrupt from an external device + * into the MPU-60X0. This is used as a way to pass an external interrupt + * through the MPU-60X0 to the host application processor. When set to 1, this + * bit will cause an interrupt if FSYNC_INT_EN is asserted in INT_PIN_CFG + * (Register 55). + * @return FSYNC interrupt status + * @see MPU9250_RA_I2C_MST_STATUS + */ +bool MPU9250::getPassthroughStatus() { + I2Cdev::readBit(devAddr, MPU9250_RA_I2C_MST_STATUS, MPU9250_MST_PASS_THROUGH_BIT, buffer); + return buffer[0]; +} +/** Get Slave 4 transaction done status. + * Automatically sets to 1 when a Slave 4 transaction has completed. This + * triggers an interrupt if the I2C_MST_INT_EN bit in the INT_ENABLE register + * (Register 56) is asserted and if the SLV_4_DONE_INT bit is asserted in the + * I2C_SLV4_CTRL register (Register 52). + * @return Slave 4 transaction done status + * @see MPU9250_RA_I2C_MST_STATUS + */ +bool MPU9250::getSlave4IsDone() { + I2Cdev::readBit(devAddr, MPU9250_RA_I2C_MST_STATUS, MPU9250_MST_I2C_SLV4_DONE_BIT, buffer); + return buffer[0]; +} +/** Get master arbitration lost status. + * This bit automatically sets to 1 when the I2C Master has lost arbitration of + * the auxiliary I2C bus (an error condition). This triggers an interrupt if the + * I2C_MST_INT_EN bit in the INT_ENABLE register (Register 56) is asserted. + * @return Master arbitration lost status + * @see MPU9250_RA_I2C_MST_STATUS + */ +bool MPU9250::getLostArbitration() { + I2Cdev::readBit(devAddr, MPU9250_RA_I2C_MST_STATUS, MPU9250_MST_I2C_LOST_ARB_BIT, buffer); + return buffer[0]; +} +/** Get Slave 4 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 4. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 4 NACK interrupt status + * @see MPU9250_RA_I2C_MST_STATUS + */ +bool MPU9250::getSlave4Nack() { + I2Cdev::readBit(devAddr, MPU9250_RA_I2C_MST_STATUS, MPU9250_MST_I2C_SLV4_NACK_BIT, buffer); + return buffer[0]; +} +/** Get Slave 3 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 3. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 3 NACK interrupt status + * @see MPU9250_RA_I2C_MST_STATUS + */ +bool MPU9250::getSlave3Nack() { + I2Cdev::readBit(devAddr, MPU9250_RA_I2C_MST_STATUS, MPU9250_MST_I2C_SLV3_NACK_BIT, buffer); + return buffer[0]; +} +/** Get Slave 2 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 2. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 2 NACK interrupt status + * @see MPU9250_RA_I2C_MST_STATUS + */ +bool MPU9250::getSlave2Nack() { + I2Cdev::readBit(devAddr, MPU9250_RA_I2C_MST_STATUS, MPU9250_MST_I2C_SLV2_NACK_BIT, buffer); + return buffer[0]; +} +/** Get Slave 1 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 1. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 1 NACK interrupt status + * @see MPU9250_RA_I2C_MST_STATUS + */ +bool MPU9250::getSlave1Nack() { + I2Cdev::readBit(devAddr, MPU9250_RA_I2C_MST_STATUS, MPU9250_MST_I2C_SLV1_NACK_BIT, buffer); + return buffer[0]; +} +/** Get Slave 0 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 0. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 0 NACK interrupt status + * @see MPU9250_RA_I2C_MST_STATUS + */ +bool MPU9250::getSlave0Nack() { + I2Cdev::readBit(devAddr, MPU9250_RA_I2C_MST_STATUS, MPU9250_MST_I2C_SLV0_NACK_BIT, buffer); + return buffer[0]; +} + +// INT_PIN_CFG register + +/** Get interrupt logic level mode. + * Will be set 0 for active-high, 1 for active-low. + * @return Current interrupt mode (0=active-high, 1=active-low) + * @see MPU9250_RA_INT_PIN_CFG + * @see MPU9250_INTCFG_INT_LEVEL_BIT + */ +bool MPU9250::getInterruptMode() { + I2Cdev::readBit(devAddr, MPU9250_RA_INT_PIN_CFG, MPU9250_INTCFG_INT_LEVEL_BIT, buffer); + return buffer[0]; +} +/** Set interrupt logic level mode. + * @param mode New interrupt mode (0=active-high, 1=active-low) + * @see getInterruptMode() + * @see MPU9250_RA_INT_PIN_CFG + * @see MPU9250_INTCFG_INT_LEVEL_BIT + */ +void MPU9250::setInterruptMode(bool mode) { + I2Cdev::writeBit(devAddr, MPU9250_RA_INT_PIN_CFG, MPU9250_INTCFG_INT_LEVEL_BIT, mode); +} +/** Get interrupt drive mode. + * Will be set 0 for push-pull, 1 for open-drain. + * @return Current interrupt drive mode (0=push-pull, 1=open-drain) + * @see MPU9250_RA_INT_PIN_CFG + * @see MPU9250_INTCFG_INT_OPEN_BIT + */ +bool MPU9250::getInterruptDrive() { + I2Cdev::readBit(devAddr, MPU9250_RA_INT_PIN_CFG, MPU9250_INTCFG_INT_OPEN_BIT, buffer); + return buffer[0]; +} +/** Set interrupt drive mode. + * @param drive New interrupt drive mode (0=push-pull, 1=open-drain) + * @see getInterruptDrive() + * @see MPU9250_RA_INT_PIN_CFG + * @see MPU9250_INTCFG_INT_OPEN_BIT + */ +void MPU9250::setInterruptDrive(bool drive) { + I2Cdev::writeBit(devAddr, MPU9250_RA_INT_PIN_CFG, MPU9250_INTCFG_INT_OPEN_BIT, drive); +} +/** Get interrupt latch mode. + * Will be set 0 for 50us-pulse, 1 for latch-until-int-cleared. + * @return Current latch mode (0=50us-pulse, 1=latch-until-int-cleared) + * @see MPU9250_RA_INT_PIN_CFG + * @see MPU9250_INTCFG_LATCH_INT_EN_BIT + */ +bool MPU9250::getInterruptLatch() { + I2Cdev::readBit(devAddr, MPU9250_RA_INT_PIN_CFG, MPU9250_INTCFG_LATCH_INT_EN_BIT, buffer); + return buffer[0]; +} +/** Set interrupt latch mode. + * @param latch New latch mode (0=50us-pulse, 1=latch-until-int-cleared) + * @see getInterruptLatch() + * @see MPU9250_RA_INT_PIN_CFG + * @see MPU9250_INTCFG_LATCH_INT_EN_BIT + */ +void MPU9250::setInterruptLatch(bool latch) { + I2Cdev::writeBit(devAddr, MPU9250_RA_INT_PIN_CFG, MPU9250_INTCFG_LATCH_INT_EN_BIT, latch); +} +/** Get interrupt latch clear mode. + * Will be set 0 for status-read-only, 1 for any-register-read. + * @return Current latch clear mode (0=status-read-only, 1=any-register-read) + * @see MPU9250_RA_INT_PIN_CFG + * @see MPU9250_INTCFG_INT_RD_CLEAR_BIT + */ +bool MPU9250::getInterruptLatchClear() { + I2Cdev::readBit(devAddr, MPU9250_RA_INT_PIN_CFG, MPU9250_INTCFG_INT_RD_CLEAR_BIT, buffer); + return buffer[0]; +} +/** Set interrupt latch clear mode. + * @param clear New latch clear mode (0=status-read-only, 1=any-register-read) + * @see getInterruptLatchClear() + * @see MPU9250_RA_INT_PIN_CFG + * @see MPU9250_INTCFG_INT_RD_CLEAR_BIT + */ +void MPU9250::setInterruptLatchClear(bool clear) { + I2Cdev::writeBit(devAddr, MPU9250_RA_INT_PIN_CFG, MPU9250_INTCFG_INT_RD_CLEAR_BIT, clear); +} +/** Get FSYNC interrupt logic level mode. + * @return Current FSYNC interrupt mode (0=active-high, 1=active-low) + * @see getFSyncInterruptMode() + * @see MPU9250_RA_INT_PIN_CFG + * @see MPU9250_INTCFG_FSYNC_INT_LEVEL_BIT + */ +bool MPU9250::getFSyncInterruptLevel() { + I2Cdev::readBit(devAddr, MPU9250_RA_INT_PIN_CFG, MPU9250_INTCFG_FSYNC_INT_LEVEL_BIT, buffer); + return buffer[0]; +} +/** Set FSYNC interrupt logic level mode. + * @param mode New FSYNC interrupt mode (0=active-high, 1=active-low) + * @see getFSyncInterruptMode() + * @see MPU9250_RA_INT_PIN_CFG + * @see MPU9250_INTCFG_FSYNC_INT_LEVEL_BIT + */ +void MPU9250::setFSyncInterruptLevel(bool level) { + I2Cdev::writeBit(devAddr, MPU9250_RA_INT_PIN_CFG, MPU9250_INTCFG_FSYNC_INT_LEVEL_BIT, level); +} +/** Get FSYNC pin interrupt enabled setting. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled setting + * @see MPU9250_RA_INT_PIN_CFG + * @see MPU9250_INTCFG_FSYNC_INT_EN_BIT + */ +bool MPU9250::getFSyncInterruptEnabled() { + I2Cdev::readBit(devAddr, MPU9250_RA_INT_PIN_CFG, MPU9250_INTCFG_FSYNC_INT_EN_BIT, buffer); + return buffer[0]; +} +/** Set FSYNC pin interrupt enabled setting. + * @param enabled New FSYNC pin interrupt enabled setting + * @see getFSyncInterruptEnabled() + * @see MPU9250_RA_INT_PIN_CFG + * @see MPU9250_INTCFG_FSYNC_INT_EN_BIT + */ +void MPU9250::setFSyncInterruptEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9250_RA_INT_PIN_CFG, MPU9250_INTCFG_FSYNC_INT_EN_BIT, enabled); +} +/** Get I2C bypass enabled status. + * When this bit is equal to 1 and I2C_MST_EN (Register 106 bit[5]) is equal to + * 0, the host application processor will be able to directly access the + * auxiliary I2C bus of the MPU-60X0. When this bit is equal to 0, the host + * application processor will not be able to directly access the auxiliary I2C + * bus of the MPU-60X0 regardless of the state of I2C_MST_EN (Register 106 + * bit[5]). + * @return Current I2C bypass enabled status + * @see MPU9250_RA_INT_PIN_CFG + * @see MPU9250_INTCFG_I2C_BYPASS_EN_BIT + */ +bool MPU9250::getI2CBypassEnabled() { + I2Cdev::readBit(devAddr, MPU9250_RA_INT_PIN_CFG, MPU9250_INTCFG_I2C_BYPASS_EN_BIT, buffer); + return buffer[0]; +} +/** Set I2C bypass enabled status. + * When this bit is equal to 1 and I2C_MST_EN (Register 106 bit[5]) is equal to + * 0, the host application processor will be able to directly access the + * auxiliary I2C bus of the MPU-60X0. When this bit is equal to 0, the host + * application processor will not be able to directly access the auxiliary I2C + * bus of the MPU-60X0 regardless of the state of I2C_MST_EN (Register 106 + * bit[5]). + * @param enabled New I2C bypass enabled status + * @see MPU9250_RA_INT_PIN_CFG + * @see MPU9250_INTCFG_I2C_BYPASS_EN_BIT + */ +void MPU9250::setI2CBypassEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9250_RA_INT_PIN_CFG, MPU9250_INTCFG_I2C_BYPASS_EN_BIT, enabled); +} +/** Get reference clock output enabled status. + * When this bit is equal to 1, a reference clock output is provided at the + * CLKOUT pin. When this bit is equal to 0, the clock output is disabled. For + * further information regarding CLKOUT, please refer to the MPU-60X0 Product + * Specification document. + * @return Current reference clock output enabled status + * @see MPU9250_RA_INT_PIN_CFG + * @see MPU9250_INTCFG_CLKOUT_EN_BIT + */ +bool MPU9250::getClockOutputEnabled() { + I2Cdev::readBit(devAddr, MPU9250_RA_INT_PIN_CFG, MPU9250_INTCFG_CLKOUT_EN_BIT, buffer); + return buffer[0]; +} +/** Set reference clock output enabled status. + * When this bit is equal to 1, a reference clock output is provided at the + * CLKOUT pin. When this bit is equal to 0, the clock output is disabled. For + * further information regarding CLKOUT, please refer to the MPU-60X0 Product + * Specification document. + * @param enabled New reference clock output enabled status + * @see MPU9250_RA_INT_PIN_CFG + * @see MPU9250_INTCFG_CLKOUT_EN_BIT + */ +void MPU9250::setClockOutputEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9250_RA_INT_PIN_CFG, MPU9250_INTCFG_CLKOUT_EN_BIT, enabled); +} + +// INT_ENABLE register + +/** Get full interrupt enabled status. + * Full register byte for all interrupts, for quick reading. Each bit will be + * set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU9250_RA_INT_ENABLE + * @see MPU9250_INTERRUPT_FF_BIT + **/ +uint8_t MPU9250::getIntEnabled() { + I2Cdev::readByte(devAddr, MPU9250_RA_INT_ENABLE, buffer); + return buffer[0]; +} +/** Set full interrupt enabled status. + * Full register byte for all interrupts, for quick reading. Each bit should be + * set 0 for disabled, 1 for enabled. + * @param enabled New interrupt enabled status + * @see getIntFreefallEnabled() + * @see MPU9250_RA_INT_ENABLE + * @see MPU9250_INTERRUPT_FF_BIT + **/ +void MPU9250::setIntEnabled(uint8_t enabled) { + I2Cdev::writeByte(devAddr, MPU9250_RA_INT_ENABLE, enabled); +} +/** Get Free Fall interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU9250_RA_INT_ENABLE + * @see MPU9250_INTERRUPT_FF_BIT + **/ +bool MPU9250::getIntFreefallEnabled() { + I2Cdev::readBit(devAddr, MPU9250_RA_INT_ENABLE, MPU9250_INTERRUPT_FF_BIT, buffer); + return buffer[0]; +} +/** Set Free Fall interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntFreefallEnabled() + * @see MPU9250_RA_INT_ENABLE + * @see MPU9250_INTERRUPT_FF_BIT + **/ +void MPU9250::setIntFreefallEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9250_RA_INT_ENABLE, MPU9250_INTERRUPT_FF_BIT, enabled); +} +/** Get Motion Detection interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU9250_RA_INT_ENABLE + * @see MPU9250_INTERRUPT_MOT_BIT + **/ +bool MPU9250::getIntMotionEnabled() { + I2Cdev::readBit(devAddr, MPU9250_RA_INT_ENABLE, MPU9250_INTERRUPT_MOT_BIT, buffer); + return buffer[0]; +} +/** Set Motion Detection interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntMotionEnabled() + * @see MPU9250_RA_INT_ENABLE + * @see MPU9250_INTERRUPT_MOT_BIT + **/ +void MPU9250::setIntMotionEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9250_RA_INT_ENABLE, MPU9250_INTERRUPT_MOT_BIT, enabled); +} +/** Get Zero Motion Detection interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU9250_RA_INT_ENABLE + * @see MPU9250_INTERRUPT_ZMOT_BIT + **/ +bool MPU9250::getIntZeroMotionEnabled() { + I2Cdev::readBit(devAddr, MPU9250_RA_INT_ENABLE, MPU9250_INTERRUPT_ZMOT_BIT, buffer); + return buffer[0]; +} +/** Set Zero Motion Detection interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntZeroMotionEnabled() + * @see MPU9250_RA_INT_ENABLE + * @see MPU9250_INTERRUPT_ZMOT_BIT + **/ +void MPU9250::setIntZeroMotionEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9250_RA_INT_ENABLE, MPU9250_INTERRUPT_ZMOT_BIT, enabled); +} +/** Get FIFO Buffer Overflow interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU9250_RA_INT_ENABLE + * @see MPU9250_INTERRUPT_FIFO_OFLOW_BIT + **/ +bool MPU9250::getIntFIFOBufferOverflowEnabled() { + I2Cdev::readBit(devAddr, MPU9250_RA_INT_ENABLE, MPU9250_INTERRUPT_FIFO_OFLOW_BIT, buffer); + return buffer[0]; +} +/** Set FIFO Buffer Overflow interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntFIFOBufferOverflowEnabled() + * @see MPU9250_RA_INT_ENABLE + * @see MPU9250_INTERRUPT_FIFO_OFLOW_BIT + **/ +void MPU9250::setIntFIFOBufferOverflowEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9250_RA_INT_ENABLE, MPU9250_INTERRUPT_FIFO_OFLOW_BIT, enabled); +} +/** Get I2C Master interrupt enabled status. + * This enables any of the I2C Master interrupt sources to generate an + * interrupt. Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU9250_RA_INT_ENABLE + * @see MPU9250_INTERRUPT_I2C_MST_INT_BIT + **/ +bool MPU9250::getIntI2CMasterEnabled() { + I2Cdev::readBit(devAddr, MPU9250_RA_INT_ENABLE, MPU9250_INTERRUPT_I2C_MST_INT_BIT, buffer); + return buffer[0]; +} +/** Set I2C Master interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntI2CMasterEnabled() + * @see MPU9250_RA_INT_ENABLE + * @see MPU9250_INTERRUPT_I2C_MST_INT_BIT + **/ +void MPU9250::setIntI2CMasterEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9250_RA_INT_ENABLE, MPU9250_INTERRUPT_I2C_MST_INT_BIT, enabled); +} +/** Get Data Ready interrupt enabled setting. + * This event occurs each time a write operation to all of the sensor registers + * has been completed. Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU9250_RA_INT_ENABLE + * @see MPU9250_INTERRUPT_DATA_RDY_BIT + */ +bool MPU9250::getIntDataReadyEnabled() { + I2Cdev::readBit(devAddr, MPU9250_RA_INT_ENABLE, MPU9250_INTERRUPT_DATA_RDY_BIT, buffer); + return buffer[0]; +} +/** Set Data Ready interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntDataReadyEnabled() + * @see MPU9250_RA_INT_CFG + * @see MPU9250_INTERRUPT_DATA_RDY_BIT + */ +void MPU9250::setIntDataReadyEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9250_RA_INT_ENABLE, MPU9250_INTERRUPT_DATA_RDY_BIT, enabled); +} + +// INT_STATUS register + +/** Get full set of interrupt status bits. + * These bits clear to 0 after the register has been read. Very useful + * for getting multiple INT statuses, since each single bit read clears + * all of them because it has to read the whole byte. + * @return Current interrupt status + * @see MPU9250_RA_INT_STATUS + */ +uint8_t MPU9250::getIntStatus() { + I2Cdev::readByte(devAddr, MPU9250_RA_INT_STATUS, buffer); + return buffer[0]; +} +/** Get Free Fall interrupt status. + * This bit automatically sets to 1 when a Free Fall interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU9250_RA_INT_STATUS + * @see MPU9250_INTERRUPT_FF_BIT + */ +bool MPU9250::getIntFreefallStatus() { + I2Cdev::readBit(devAddr, MPU9250_RA_INT_STATUS, MPU9250_INTERRUPT_FF_BIT, buffer); + return buffer[0]; +} +/** Get Motion Detection interrupt status. + * This bit automatically sets to 1 when a Motion Detection interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU9250_RA_INT_STATUS + * @see MPU9250_INTERRUPT_MOT_BIT + */ +bool MPU9250::getIntMotionStatus() { + I2Cdev::readBit(devAddr, MPU9250_RA_INT_STATUS, MPU9250_INTERRUPT_MOT_BIT, buffer); + return buffer[0]; +} +/** Get Zero Motion Detection interrupt status. + * This bit automatically sets to 1 when a Zero Motion Detection interrupt has + * been generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU9250_RA_INT_STATUS + * @see MPU9250_INTERRUPT_ZMOT_BIT + */ +bool MPU9250::getIntZeroMotionStatus() { + I2Cdev::readBit(devAddr, MPU9250_RA_INT_STATUS, MPU9250_INTERRUPT_ZMOT_BIT, buffer); + return buffer[0]; +} +/** Get FIFO Buffer Overflow interrupt status. + * This bit automatically sets to 1 when a Free Fall interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU9250_RA_INT_STATUS + * @see MPU9250_INTERRUPT_FIFO_OFLOW_BIT + */ +bool MPU9250::getIntFIFOBufferOverflowStatus() { + I2Cdev::readBit(devAddr, MPU9250_RA_INT_STATUS, MPU9250_INTERRUPT_FIFO_OFLOW_BIT, buffer); + return buffer[0]; +} +/** Get I2C Master interrupt status. + * This bit automatically sets to 1 when an I2C Master interrupt has been + * generated. For a list of I2C Master interrupts, please refer to Register 54. + * The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU9250_RA_INT_STATUS + * @see MPU9250_INTERRUPT_I2C_MST_INT_BIT + */ +bool MPU9250::getIntI2CMasterStatus() { + I2Cdev::readBit(devAddr, MPU9250_RA_INT_STATUS, MPU9250_INTERRUPT_I2C_MST_INT_BIT, buffer); + return buffer[0]; +} +/** Get Data Ready interrupt status. + * This bit automatically sets to 1 when a Data Ready interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU9250_RA_INT_STATUS + * @see MPU9250_INTERRUPT_DATA_RDY_BIT + */ +bool MPU9250::getIntDataReadyStatus() { + I2Cdev::readBit(devAddr, MPU9250_RA_INT_STATUS, MPU9250_INTERRUPT_DATA_RDY_BIT, buffer); + return buffer[0]; +} + +// ACCEL_*OUT_* registers + +/** Get raw 9-axis motion sensor readings (accel/gyro/compass). + * FUNCTION NOT FULLY IMPLEMENTED YET. + * @param ax 16-bit signed integer container for accelerometer X-axis value + * @param ay 16-bit signed integer container for accelerometer Y-axis value + * @param az 16-bit signed integer container for accelerometer Z-axis value + * @param gx 16-bit signed integer container for gyroscope X-axis value + * @param gy 16-bit signed integer container for gyroscope Y-axis value + * @param gz 16-bit signed integer container for gyroscope Z-axis value + * @param mx 16-bit signed integer container for magnetometer X-axis value + * @param my 16-bit signed integer container for magnetometer Y-axis value + * @param mz 16-bit signed integer container for magnetometer Z-axis value + * @see getMotion6() + * @see getAcceleration() + * @see getRotation() + * @see MPU9250_RA_ACCEL_XOUT_H + */ +void MPU9250::getMotion9(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz, int16_t* mx, int16_t* my, int16_t* mz) { + + //get accel and gyro + getMotion6(ax, ay, az, gx, gy, gz); + + //read mag + I2Cdev::writeByte(devAddr, MPU9250_RA_INT_PIN_CFG, 0x02); //set i2c bypass enable pin to true to access magnetometer + delay(10); + I2Cdev::writeByte(MPU9150_RA_MAG_ADDRESS, 0x0A, 0x01); //enable the magnetometer + delay(10); + I2Cdev::readBytes(MPU9150_RA_MAG_ADDRESS, MPU9150_RA_MAG_XOUT_L, 6, buffer); + *mx = (((int16_t)buffer[1]) << 8) | buffer[0]; + *my = (((int16_t)buffer[3]) << 8) | buffer[2]; + *mz = (((int16_t)buffer[5]) << 8) | buffer[4]; +} +/** Get raw 6-axis motion sensor readings (accel/gyro). + * Retrieves all currently available motion sensor values. + * @param ax 16-bit signed integer container for accelerometer X-axis value + * @param ay 16-bit signed integer container for accelerometer Y-axis value + * @param az 16-bit signed integer container for accelerometer Z-axis value + * @param gx 16-bit signed integer container for gyroscope X-axis value + * @param gy 16-bit signed integer container for gyroscope Y-axis value + * @param gz 16-bit signed integer container for gyroscope Z-axis value + * @see getAcceleration() + * @see getRotation() + * @see MPU9250_RA_ACCEL_XOUT_H + */ +void MPU9250::getMotion6(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz) { + I2Cdev::readBytes(devAddr, MPU9250_RA_ACCEL_XOUT_H, 14, buffer); + *ax = (((int16_t)buffer[0]) << 8) | buffer[1]; + *ay = (((int16_t)buffer[2]) << 8) | buffer[3]; + *az = (((int16_t)buffer[4]) << 8) | buffer[5]; + *gx = (((int16_t)buffer[8]) << 8) | buffer[9]; + *gy = (((int16_t)buffer[10]) << 8) | buffer[11]; + *gz = (((int16_t)buffer[12]) << 8) | buffer[13]; +} +/** Get 3-axis accelerometer readings. + * These registers store the most recent accelerometer measurements. + * Accelerometer measurements are written to these registers at the Sample Rate + * as defined in Register 25. + * + * The accelerometer measurement registers, along with the temperature + * measurement registers, gyroscope measurement registers, and external sensor + * data registers, are composed of two sets of registers: an internal register + * set and a user-facing read register set. + * + * The data within the accelerometer sensors' internal register set is always + * updated at the Sample Rate. Meanwhile, the user-facing read register set + * duplicates the internal register set's data values whenever the serial + * interface is idle. This guarantees that a burst read of sensor registers will + * read measurements from the same sampling instant. Note that if burst reads + * are not used, the user is responsible for ensuring a set of single byte reads + * correspond to a single sampling instant by checking the Data Ready interrupt. + * + * Each 16-bit accelerometer measurement has a full scale defined in ACCEL_FS + * (Register 28). For each full scale setting, the accelerometers' sensitivity + * per LSB in ACCEL_xOUT is shown in the table below: + * + *
+ * AFS_SEL | Full Scale Range | LSB Sensitivity
+ * --------+------------------+----------------
+ * 0       | +/- 2g           | 8192 LSB/mg
+ * 1       | +/- 4g           | 4096 LSB/mg
+ * 2       | +/- 8g           | 2048 LSB/mg
+ * 3       | +/- 16g          | 1024 LSB/mg
+ * 
+ * + * @param x 16-bit signed integer container for X-axis acceleration + * @param y 16-bit signed integer container for Y-axis acceleration + * @param z 16-bit signed integer container for Z-axis acceleration + * @see MPU9250_RA_GYRO_XOUT_H + */ +void MPU9250::getAcceleration(int16_t* x, int16_t* y, int16_t* z) { + I2Cdev::readBytes(devAddr, MPU9250_RA_ACCEL_XOUT_H, 6, buffer); + *x = (((int16_t)buffer[0]) << 8) | buffer[1]; + *y = (((int16_t)buffer[2]) << 8) | buffer[3]; + *z = (((int16_t)buffer[4]) << 8) | buffer[5]; +} +/** Get X-axis accelerometer reading. + * @return X-axis acceleration measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU9250_RA_ACCEL_XOUT_H + */ +int16_t MPU9250::getAccelerationX() { + I2Cdev::readBytes(devAddr, MPU9250_RA_ACCEL_XOUT_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +/** Get Y-axis accelerometer reading. + * @return Y-axis acceleration measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU9250_RA_ACCEL_YOUT_H + */ +int16_t MPU9250::getAccelerationY() { + I2Cdev::readBytes(devAddr, MPU9250_RA_ACCEL_YOUT_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +/** Get Z-axis accelerometer reading. + * @return Z-axis acceleration measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU9250_RA_ACCEL_ZOUT_H + */ +int16_t MPU9250::getAccelerationZ() { + I2Cdev::readBytes(devAddr, MPU9250_RA_ACCEL_ZOUT_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} + +// TEMP_OUT_* registers + +/** Get current internal temperature. + * @return Temperature reading in 16-bit 2's complement format + * @see MPU9250_RA_TEMP_OUT_H + */ +int16_t MPU9250::getTemperature() { + I2Cdev::readBytes(devAddr, MPU9250_RA_TEMP_OUT_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} + +// GYRO_*OUT_* registers + +/** Get 3-axis gyroscope readings. + * These gyroscope measurement registers, along with the accelerometer + * measurement registers, temperature measurement registers, and external sensor + * data registers, are composed of two sets of registers: an internal register + * set and a user-facing read register set. + * The data within the gyroscope sensors' internal register set is always + * updated at the Sample Rate. Meanwhile, the user-facing read register set + * duplicates the internal register set's data values whenever the serial + * interface is idle. This guarantees that a burst read of sensor registers will + * read measurements from the same sampling instant. Note that if burst reads + * are not used, the user is responsible for ensuring a set of single byte reads + * correspond to a single sampling instant by checking the Data Ready interrupt. + * + * Each 16-bit gyroscope measurement has a full scale defined in FS_SEL + * (Register 27). For each full scale setting, the gyroscopes' sensitivity per + * LSB in GYRO_xOUT is shown in the table below: + * + *
+ * FS_SEL | Full Scale Range   | LSB Sensitivity
+ * -------+--------------------+----------------
+ * 0      | +/- 250 degrees/s  | 131 LSB/deg/s
+ * 1      | +/- 500 degrees/s  | 65.5 LSB/deg/s
+ * 2      | +/- 1000 degrees/s | 32.8 LSB/deg/s
+ * 3      | +/- 2000 degrees/s | 16.4 LSB/deg/s
+ * 
+ * + * @param x 16-bit signed integer container for X-axis rotation + * @param y 16-bit signed integer container for Y-axis rotation + * @param z 16-bit signed integer container for Z-axis rotation + * @see getMotion6() + * @see MPU9250_RA_GYRO_XOUT_H + */ +void MPU9250::getRotation(int16_t* x, int16_t* y, int16_t* z) { + I2Cdev::readBytes(devAddr, MPU9250_RA_GYRO_XOUT_H, 6, buffer); + *x = (((int16_t)buffer[0]) << 8) | buffer[1]; + *y = (((int16_t)buffer[2]) << 8) | buffer[3]; + *z = (((int16_t)buffer[4]) << 8) | buffer[5]; +} +/** Get X-axis gyroscope reading. + * @return X-axis rotation measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU9250_RA_GYRO_XOUT_H + */ +int16_t MPU9250::getRotationX() { + I2Cdev::readBytes(devAddr, MPU9250_RA_GYRO_XOUT_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +/** Get Y-axis gyroscope reading. + * @return Y-axis rotation measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU9250_RA_GYRO_YOUT_H + */ +int16_t MPU9250::getRotationY() { + I2Cdev::readBytes(devAddr, MPU9250_RA_GYRO_YOUT_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +/** Get Z-axis gyroscope reading. + * @return Z-axis rotation measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU9250_RA_GYRO_ZOUT_H + */ +int16_t MPU9250::getRotationZ() { + I2Cdev::readBytes(devAddr, MPU9250_RA_GYRO_ZOUT_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} + +// EXT_SENS_DATA_* registers + +/** Read single byte from external sensor data register. + * These registers store data read from external sensors by the Slave 0, 1, 2, + * and 3 on the auxiliary I2C interface. Data read by Slave 4 is stored in + * I2C_SLV4_DI (Register 53). + * + * External sensor data is written to these registers at the Sample Rate as + * defined in Register 25. This access rate can be reduced by using the Slave + * Delay Enable registers (Register 103). + * + * External sensor data registers, along with the gyroscope measurement + * registers, accelerometer measurement registers, and temperature measurement + * registers, are composed of two sets of registers: an internal register set + * and a user-facing read register set. + * + * The data within the external sensors' internal register set is always updated + * at the Sample Rate (or the reduced access rate) whenever the serial interface + * is idle. This guarantees that a burst read of sensor registers will read + * measurements from the same sampling instant. Note that if burst reads are not + * used, the user is responsible for ensuring a set of single byte reads + * correspond to a single sampling instant by checking the Data Ready interrupt. + * + * Data is placed in these external sensor data registers according to + * I2C_SLV0_CTRL, I2C_SLV1_CTRL, I2C_SLV2_CTRL, and I2C_SLV3_CTRL (Registers 39, + * 42, 45, and 48). When more than zero bytes are read (I2C_SLVx_LEN > 0) from + * an enabled slave (I2C_SLVx_EN = 1), the slave is read at the Sample Rate (as + * defined in Register 25) or delayed rate (if specified in Register 52 and + * 103). During each Sample cycle, slave reads are performed in order of Slave + * number. If all slaves are enabled with more than zero bytes to be read, the + * order will be Slave 0, followed by Slave 1, Slave 2, and Slave 3. + * + * Each enabled slave will have EXT_SENS_DATA registers associated with it by + * number of bytes read (I2C_SLVx_LEN) in order of slave number, starting from + * EXT_SENS_DATA_00. Note that this means enabling or disabling a slave may + * change the higher numbered slaves' associated registers. Furthermore, if + * fewer total bytes are being read from the external sensors as a result of + * such a change, then the data remaining in the registers which no longer have + * an associated slave device (i.e. high numbered registers) will remain in + * these previously allocated registers unless reset. + * + * If the sum of the read lengths of all SLVx transactions exceed the number of + * available EXT_SENS_DATA registers, the excess bytes will be dropped. There + * are 24 EXT_SENS_DATA registers and hence the total read lengths between all + * the slaves cannot be greater than 24 or some bytes will be lost. + * + * Note: Slave 4's behavior is distinct from that of Slaves 0-3. For further + * information regarding the characteristics of Slave 4, please refer to + * Registers 49 to 53. + * + * EXAMPLE: + * Suppose that Slave 0 is enabled with 4 bytes to be read (I2C_SLV0_EN = 1 and + * I2C_SLV0_LEN = 4) while Slave 1 is enabled with 2 bytes to be read so that + * I2C_SLV1_EN = 1 and I2C_SLV1_LEN = 2. In such a situation, EXT_SENS_DATA _00 + * through _03 will be associated with Slave 0, while EXT_SENS_DATA _04 and 05 + * will be associated with Slave 1. If Slave 2 is enabled as well, registers + * starting from EXT_SENS_DATA_06 will be allocated to Slave 2. + * + * If Slave 2 is disabled while Slave 3 is enabled in this same situation, then + * registers starting from EXT_SENS_DATA_06 will be allocated to Slave 3 + * instead. + * + * REGISTER ALLOCATION FOR DYNAMIC DISABLE VS. NORMAL DISABLE: + * If a slave is disabled at any time, the space initially allocated to the + * slave in the EXT_SENS_DATA register, will remain associated with that slave. + * This is to avoid dynamic adjustment of the register allocation. + * + * The allocation of the EXT_SENS_DATA registers is recomputed only when (1) all + * slaves are disabled, or (2) the I2C_MST_RST bit is set (Register 106). + * + * This above is also true if one of the slaves gets NACKed and stops + * functioning. + * + * @param position Starting position (0-23) + * @return Byte read from register + */ +uint8_t MPU9250::getExternalSensorByte(int position) { + I2Cdev::readByte(devAddr, MPU9250_RA_EXT_SENS_DATA_00 + position, buffer); + return buffer[0]; +} +/** Read word (2 bytes) from external sensor data registers. + * @param position Starting position (0-21) + * @return Word read from register + * @see getExternalSensorByte() + */ +uint16_t MPU9250::getExternalSensorWord(int position) { + I2Cdev::readBytes(devAddr, MPU9250_RA_EXT_SENS_DATA_00 + position, 2, buffer); + return (((uint16_t)buffer[0]) << 8) | buffer[1]; +} +/** Read double word (4 bytes) from external sensor data registers. + * @param position Starting position (0-20) + * @return Double word read from registers + * @see getExternalSensorByte() + */ +uint32_t MPU9250::getExternalSensorDWord(int position) { + I2Cdev::readBytes(devAddr, MPU9250_RA_EXT_SENS_DATA_00 + position, 4, buffer); + return (((uint32_t)buffer[0]) << 24) | (((uint32_t)buffer[1]) << 16) | (((uint16_t)buffer[2]) << 8) | buffer[3]; +} + +// MOT_DETECT_STATUS register + +/** Get X-axis negative motion detection interrupt status. + * @return Motion detection status + * @see MPU9250_RA_MOT_DETECT_STATUS + * @see MPU9250_MOTION_MOT_XNEG_BIT + */ +bool MPU9250::getXNegMotionDetected() { + I2Cdev::readBit(devAddr, MPU9250_RA_MOT_DETECT_STATUS, MPU9250_MOTION_MOT_XNEG_BIT, buffer); + return buffer[0]; +} +/** Get X-axis positive motion detection interrupt status. + * @return Motion detection status + * @see MPU9250_RA_MOT_DETECT_STATUS + * @see MPU9250_MOTION_MOT_XPOS_BIT + */ +bool MPU9250::getXPosMotionDetected() { + I2Cdev::readBit(devAddr, MPU9250_RA_MOT_DETECT_STATUS, MPU9250_MOTION_MOT_XPOS_BIT, buffer); + return buffer[0]; +} +/** Get Y-axis negative motion detection interrupt status. + * @return Motion detection status + * @see MPU9250_RA_MOT_DETECT_STATUS + * @see MPU9250_MOTION_MOT_YNEG_BIT + */ +bool MPU9250::getYNegMotionDetected() { + I2Cdev::readBit(devAddr, MPU9250_RA_MOT_DETECT_STATUS, MPU9250_MOTION_MOT_YNEG_BIT, buffer); + return buffer[0]; +} +/** Get Y-axis positive motion detection interrupt status. + * @return Motion detection status + * @see MPU9250_RA_MOT_DETECT_STATUS + * @see MPU9250_MOTION_MOT_YPOS_BIT + */ +bool MPU9250::getYPosMotionDetected() { + I2Cdev::readBit(devAddr, MPU9250_RA_MOT_DETECT_STATUS, MPU9250_MOTION_MOT_YPOS_BIT, buffer); + return buffer[0]; +} +/** Get Z-axis negative motion detection interrupt status. + * @return Motion detection status + * @see MPU9250_RA_MOT_DETECT_STATUS + * @see MPU9250_MOTION_MOT_ZNEG_BIT + */ +bool MPU9250::getZNegMotionDetected() { + I2Cdev::readBit(devAddr, MPU9250_RA_MOT_DETECT_STATUS, MPU9250_MOTION_MOT_ZNEG_BIT, buffer); + return buffer[0]; +} +/** Get Z-axis positive motion detection interrupt status. + * @return Motion detection status + * @see MPU9250_RA_MOT_DETECT_STATUS + * @see MPU9250_MOTION_MOT_ZPOS_BIT + */ +bool MPU9250::getZPosMotionDetected() { + I2Cdev::readBit(devAddr, MPU9250_RA_MOT_DETECT_STATUS, MPU9250_MOTION_MOT_ZPOS_BIT, buffer); + return buffer[0]; +} +/** Get zero motion detection interrupt status. + * @return Motion detection status + * @see MPU9250_RA_MOT_DETECT_STATUS + * @see MPU9250_MOTION_MOT_ZRMOT_BIT + */ +bool MPU9250::getZeroMotionDetected() { + I2Cdev::readBit(devAddr, MPU9250_RA_MOT_DETECT_STATUS, MPU9250_MOTION_MOT_ZRMOT_BIT, buffer); + return buffer[0]; +} + +// I2C_SLV*_DO register + +/** Write byte to Data Output container for specified slave. + * This register holds the output data written into Slave when Slave is set to + * write mode. For further information regarding Slave control, please + * refer to Registers 37 to 39 and immediately following. + * @param num Slave number (0-3) + * @param data Byte to write + * @see MPU9250_RA_I2C_SLV0_DO + */ +void MPU9250::setSlaveOutputByte(uint8_t num, uint8_t data) { + if (num > 3) return; + I2Cdev::writeByte(devAddr, MPU9250_RA_I2C_SLV0_DO + num, data); +} + +// I2C_MST_DELAY_CTRL register + +/** Get external data shadow delay enabled status. + * This register is used to specify the timing of external sensor data + * shadowing. When DELAY_ES_SHADOW is set to 1, shadowing of external + * sensor data is delayed until all data has been received. + * @return Current external data shadow delay enabled status. + * @see MPU9250_RA_I2C_MST_DELAY_CTRL + * @see MPU9250_DELAYCTRL_DELAY_ES_SHADOW_BIT + */ +bool MPU9250::getExternalShadowDelayEnabled() { + I2Cdev::readBit(devAddr, MPU9250_RA_I2C_MST_DELAY_CTRL, MPU9250_DELAYCTRL_DELAY_ES_SHADOW_BIT, buffer); + return buffer[0]; +} +/** Set external data shadow delay enabled status. + * @param enabled New external data shadow delay enabled status. + * @see getExternalShadowDelayEnabled() + * @see MPU9250_RA_I2C_MST_DELAY_CTRL + * @see MPU9250_DELAYCTRL_DELAY_ES_SHADOW_BIT + */ +void MPU9250::setExternalShadowDelayEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9250_RA_I2C_MST_DELAY_CTRL, MPU9250_DELAYCTRL_DELAY_ES_SHADOW_BIT, enabled); +} +/** Get slave delay enabled status. + * When a particular slave delay is enabled, the rate of access for the that + * slave device is reduced. When a slave's access rate is decreased relative to + * the Sample Rate, the slave is accessed every: + * + * 1 / (1 + I2C_MST_DLY) Samples + * + * This base Sample Rate in turn is determined by SMPLRT_DIV (register * 25) + * and DLPF_CFG (register 26). + * + * For further information regarding I2C_MST_DLY, please refer to register 52. + * For further information regarding the Sample Rate, please refer to register 25. + * + * @param num Slave number (0-4) + * @return Current slave delay enabled status. + * @see MPU9250_RA_I2C_MST_DELAY_CTRL + * @see MPU9250_DELAYCTRL_I2C_SLV0_DLY_EN_BIT + */ +bool MPU9250::getSlaveDelayEnabled(uint8_t num) { + // MPU9250_DELAYCTRL_I2C_SLV4_DLY_EN_BIT is 4, SLV3 is 3, etc. + if (num > 4) return 0; + I2Cdev::readBit(devAddr, MPU9250_RA_I2C_MST_DELAY_CTRL, num, buffer); + return buffer[0]; +} +/** Set slave delay enabled status. + * @param num Slave number (0-4) + * @param enabled New slave delay enabled status. + * @see MPU9250_RA_I2C_MST_DELAY_CTRL + * @see MPU9250_DELAYCTRL_I2C_SLV0_DLY_EN_BIT + */ +void MPU9250::setSlaveDelayEnabled(uint8_t num, bool enabled) { + I2Cdev::writeBit(devAddr, MPU9250_RA_I2C_MST_DELAY_CTRL, num, enabled); +} + +// SIGNAL_PATH_RESET register + +/** Reset gyroscope signal path. + * The reset will revert the signal path analog to digital converters and + * filters to their power up configurations. + * @see MPU9250_RA_SIGNAL_PATH_RESET + * @see MPU9250_PATHRESET_GYRO_RESET_BIT + */ +void MPU9250::resetGyroscopePath() { + I2Cdev::writeBit(devAddr, MPU9250_RA_SIGNAL_PATH_RESET, MPU9250_PATHRESET_GYRO_RESET_BIT, true); +} +/** Reset accelerometer signal path. + * The reset will revert the signal path analog to digital converters and + * filters to their power up configurations. + * @see MPU9250_RA_SIGNAL_PATH_RESET + * @see MPU9250_PATHRESET_ACCEL_RESET_BIT + */ +void MPU9250::resetAccelerometerPath() { + I2Cdev::writeBit(devAddr, MPU9250_RA_SIGNAL_PATH_RESET, MPU9250_PATHRESET_ACCEL_RESET_BIT, true); +} +/** Reset temperature sensor signal path. + * The reset will revert the signal path analog to digital converters and + * filters to their power up configurations. + * @see MPU9250_RA_SIGNAL_PATH_RESET + * @see MPU9250_PATHRESET_TEMP_RESET_BIT + */ +void MPU9250::resetTemperaturePath() { + I2Cdev::writeBit(devAddr, MPU9250_RA_SIGNAL_PATH_RESET, MPU9250_PATHRESET_TEMP_RESET_BIT, true); +} + +// MOT_DETECT_CTRL register + +/** Get accelerometer power-on delay. + * The accelerometer data path provides samples to the sensor registers, Motion + * detection, Zero Motion detection, and Free Fall detection modules. The + * signal path contains filters which must be flushed on wake-up with new + * samples before the detection modules begin operations. The default wake-up + * delay, of 4ms can be lengthened by up to 3ms. This additional delay is + * specified in ACCEL_ON_DELAY in units of 1 LSB = 1 ms. The user may select + * any value above zero unless instructed otherwise by InvenSense. Please refer + * to Section 8 of the MPU-6000/MPU-9250 Product Specification document for + * further information regarding the detection modules. + * @return Current accelerometer power-on delay + * @see MPU9250_RA_MOT_DETECT_CTRL + * @see MPU9250_DETECT_ACCEL_ON_DELAY_BIT + */ +uint8_t MPU9250::getAccelerometerPowerOnDelay() { + I2Cdev::readBits(devAddr, MPU9250_RA_MOT_DETECT_CTRL, MPU9250_DETECT_ACCEL_ON_DELAY_BIT, MPU9250_DETECT_ACCEL_ON_DELAY_LENGTH, buffer); + return buffer[0]; +} +/** Set accelerometer power-on delay. + * @param delay New accelerometer power-on delay (0-3) + * @see getAccelerometerPowerOnDelay() + * @see MPU9250_RA_MOT_DETECT_CTRL + * @see MPU9250_DETECT_ACCEL_ON_DELAY_BIT + */ +void MPU9250::setAccelerometerPowerOnDelay(uint8_t delay) { + I2Cdev::writeBits(devAddr, MPU9250_RA_MOT_DETECT_CTRL, MPU9250_DETECT_ACCEL_ON_DELAY_BIT, MPU9250_DETECT_ACCEL_ON_DELAY_LENGTH, delay); +} +/** Get Free Fall detection counter decrement configuration. + * Detection is registered by the Free Fall detection module after accelerometer + * measurements meet their respective threshold conditions over a specified + * number of samples. When the threshold conditions are met, the corresponding + * detection counter increments by 1. The user may control the rate at which the + * detection counter decrements when the threshold condition is not met by + * configuring FF_COUNT. The decrement rate can be set according to the + * following table: + * + *
+ * FF_COUNT | Counter Decrement
+ * ---------+------------------
+ * 0        | Reset
+ * 1        | 1
+ * 2        | 2
+ * 3        | 4
+ * 
+ * + * When FF_COUNT is configured to 0 (reset), any non-qualifying sample will + * reset the counter to 0. For further information on Free Fall detection, + * please refer to Registers 29 to 32. + * + * @return Current decrement configuration + * @see MPU9250_RA_MOT_DETECT_CTRL + * @see MPU9250_DETECT_FF_COUNT_BIT + */ +uint8_t MPU9250::getFreefallDetectionCounterDecrement() { + I2Cdev::readBits(devAddr, MPU9250_RA_MOT_DETECT_CTRL, MPU9250_DETECT_FF_COUNT_BIT, MPU9250_DETECT_FF_COUNT_LENGTH, buffer); + return buffer[0]; +} +/** Set Free Fall detection counter decrement configuration. + * @param decrement New decrement configuration value + * @see getFreefallDetectionCounterDecrement() + * @see MPU9250_RA_MOT_DETECT_CTRL + * @see MPU9250_DETECT_FF_COUNT_BIT + */ +void MPU9250::setFreefallDetectionCounterDecrement(uint8_t decrement) { + I2Cdev::writeBits(devAddr, MPU9250_RA_MOT_DETECT_CTRL, MPU9250_DETECT_FF_COUNT_BIT, MPU9250_DETECT_FF_COUNT_LENGTH, decrement); +} +/** Get Motion detection counter decrement configuration. + * Detection is registered by the Motion detection module after accelerometer + * measurements meet their respective threshold conditions over a specified + * number of samples. When the threshold conditions are met, the corresponding + * detection counter increments by 1. The user may control the rate at which the + * detection counter decrements when the threshold condition is not met by + * configuring MOT_COUNT. The decrement rate can be set according to the + * following table: + * + *
+ * MOT_COUNT | Counter Decrement
+ * ----------+------------------
+ * 0         | Reset
+ * 1         | 1
+ * 2         | 2
+ * 3         | 4
+ * 
+ * + * When MOT_COUNT is configured to 0 (reset), any non-qualifying sample will + * reset the counter to 0. For further information on Motion detection, + * please refer to Registers 29 to 32. + * + */ +uint8_t MPU9250::getMotionDetectionCounterDecrement() { + I2Cdev::readBits(devAddr, MPU9250_RA_MOT_DETECT_CTRL, MPU9250_DETECT_MOT_COUNT_BIT, MPU9250_DETECT_MOT_COUNT_LENGTH, buffer); + return buffer[0]; +} +/** Set Motion detection counter decrement configuration. + * @param decrement New decrement configuration value + * @see getMotionDetectionCounterDecrement() + * @see MPU9250_RA_MOT_DETECT_CTRL + * @see MPU9250_DETECT_MOT_COUNT_BIT + */ +void MPU9250::setMotionDetectionCounterDecrement(uint8_t decrement) { + I2Cdev::writeBits(devAddr, MPU9250_RA_MOT_DETECT_CTRL, MPU9250_DETECT_MOT_COUNT_BIT, MPU9250_DETECT_MOT_COUNT_LENGTH, decrement); +} + +// USER_CTRL register + +/** Get FIFO enabled status. + * When this bit is set to 0, the FIFO buffer is disabled. The FIFO buffer + * cannot be written to or read from while disabled. The FIFO buffer's state + * does not change unless the MPU-60X0 is power cycled. + * @return Current FIFO enabled status + * @see MPU9250_RA_USER_CTRL + * @see MPU9250_USERCTRL_FIFO_EN_BIT + */ +bool MPU9250::getFIFOEnabled() { + I2Cdev::readBit(devAddr, MPU9250_RA_USER_CTRL, MPU9250_USERCTRL_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set FIFO enabled status. + * @param enabled New FIFO enabled status + * @see getFIFOEnabled() + * @see MPU9250_RA_USER_CTRL + * @see MPU9250_USERCTRL_FIFO_EN_BIT + */ +void MPU9250::setFIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9250_RA_USER_CTRL, MPU9250_USERCTRL_FIFO_EN_BIT, enabled); +} +/** Get I2C Master Mode enabled status. + * When this mode is enabled, the MPU-60X0 acts as the I2C Master to the + * external sensor slave devices on the auxiliary I2C bus. When this bit is + * cleared to 0, the auxiliary I2C bus lines (AUX_DA and AUX_CL) are logically + * driven by the primary I2C bus (SDA and SCL). This is a precondition to + * enabling Bypass Mode. For further information regarding Bypass Mode, please + * refer to Register 55. + * @return Current I2C Master Mode enabled status + * @see MPU9250_RA_USER_CTRL + * @see MPU9250_USERCTRL_I2C_MST_EN_BIT + */ +bool MPU9250::getI2CMasterModeEnabled() { + I2Cdev::readBit(devAddr, MPU9250_RA_USER_CTRL, MPU9250_USERCTRL_I2C_MST_EN_BIT, buffer); + return buffer[0]; +} +/** Set I2C Master Mode enabled status. + * @param enabled New I2C Master Mode enabled status + * @see getI2CMasterModeEnabled() + * @see MPU9250_RA_USER_CTRL + * @see MPU9250_USERCTRL_I2C_MST_EN_BIT + */ +void MPU9250::setI2CMasterModeEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9250_RA_USER_CTRL, MPU9250_USERCTRL_I2C_MST_EN_BIT, enabled); +} +/** Switch from I2C to SPI mode (MPU-6000 only) + * If this is set, the primary SPI interface will be enabled in place of the + * disabled primary I2C interface. + */ +void MPU9250::switchSPIEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9250_RA_USER_CTRL, MPU9250_USERCTRL_I2C_IF_DIS_BIT, enabled); +} +/** Reset the FIFO. + * This bit resets the FIFO buffer when set to 1 while FIFO_EN equals 0. This + * bit automatically clears to 0 after the reset has been triggered. + * @see MPU9250_RA_USER_CTRL + * @see MPU9250_USERCTRL_FIFO_RESET_BIT + */ +void MPU9250::resetFIFO() { + I2Cdev::writeBit(devAddr, MPU9250_RA_USER_CTRL, MPU9250_USERCTRL_FIFO_RESET_BIT, true); +} +/** Reset the I2C Master. + * This bit resets the I2C Master when set to 1 while I2C_MST_EN equals 0. + * This bit automatically clears to 0 after the reset has been triggered. + * @see MPU9250_RA_USER_CTRL + * @see MPU9250_USERCTRL_I2C_MST_RESET_BIT + */ +void MPU9250::resetI2CMaster() { + I2Cdev::writeBit(devAddr, MPU9250_RA_USER_CTRL, MPU9250_USERCTRL_I2C_MST_RESET_BIT, true); +} +/** Reset all sensor registers and signal paths. + * When set to 1, this bit resets the signal paths for all sensors (gyroscopes, + * accelerometers, and temperature sensor). This operation will also clear the + * sensor registers. This bit automatically clears to 0 after the reset has been + * triggered. + * + * When resetting only the signal path (and not the sensor registers), please + * use Register 104, SIGNAL_PATH_RESET. + * + * @see MPU9250_RA_USER_CTRL + * @see MPU9250_USERCTRL_SIG_COND_RESET_BIT + */ +void MPU9250::resetSensors() { + I2Cdev::writeBit(devAddr, MPU9250_RA_USER_CTRL, MPU9250_USERCTRL_SIG_COND_RESET_BIT, true); +} + +// PWR_MGMT_1 register + +/** Trigger a full device reset. + * A small delay of ~50ms may be desirable after triggering a reset. + * @see MPU9250_RA_PWR_MGMT_1 + * @see MPU9250_PWR1_DEVICE_RESET_BIT + */ +void MPU9250::reset() { + I2Cdev::writeBit(devAddr, MPU9250_RA_PWR_MGMT_1, MPU9250_PWR1_DEVICE_RESET_BIT, true); +} +/** Get sleep mode status. + * Setting the SLEEP bit in the register puts the device into very low power + * sleep mode. In this mode, only the serial interface and internal registers + * remain active, allowing for a very low standby current. Clearing this bit + * puts the device back into normal mode. To save power, the individual standby + * selections for each of the gyros should be used if any gyro axis is not used + * by the application. + * @return Current sleep mode enabled status + * @see MPU9250_RA_PWR_MGMT_1 + * @see MPU9250_PWR1_SLEEP_BIT + */ +bool MPU9250::getSleepEnabled() { + I2Cdev::readBit(devAddr, MPU9250_RA_PWR_MGMT_1, MPU9250_PWR1_SLEEP_BIT, buffer); + return buffer[0]; +} +/** Set sleep mode status. + * @param enabled New sleep mode enabled status + * @see getSleepEnabled() + * @see MPU9250_RA_PWR_MGMT_1 + * @see MPU9250_PWR1_SLEEP_BIT + */ +void MPU9250::setSleepEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9250_RA_PWR_MGMT_1, MPU9250_PWR1_SLEEP_BIT, enabled); +} +/** Get wake cycle enabled status. + * When this bit is set to 1 and SLEEP is disabled, the MPU-60X0 will cycle + * between sleep mode and waking up to take a single sample of data from active + * sensors at a rate determined by LP_WAKE_CTRL (register 108). + * @return Current sleep mode enabled status + * @see MPU9250_RA_PWR_MGMT_1 + * @see MPU9250_PWR1_CYCLE_BIT + */ +bool MPU9250::getWakeCycleEnabled() { + I2Cdev::readBit(devAddr, MPU9250_RA_PWR_MGMT_1, MPU9250_PWR1_CYCLE_BIT, buffer); + return buffer[0]; +} +/** Set wake cycle enabled status. + * @param enabled New sleep mode enabled status + * @see getWakeCycleEnabled() + * @see MPU9250_RA_PWR_MGMT_1 + * @see MPU9250_PWR1_CYCLE_BIT + */ +void MPU9250::setWakeCycleEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU9250_RA_PWR_MGMT_1, MPU9250_PWR1_CYCLE_BIT, enabled); +} +/** Get temperature sensor enabled status. + * Control the usage of the internal temperature sensor. + * + * Note: this register stores the *disabled* value, but for consistency with the + * rest of the code, the function is named and used with standard true/false + * values to indicate whether the sensor is enabled or disabled, respectively. + * + * @return Current temperature sensor enabled status + * @see MPU9250_RA_PWR_MGMT_1 + * @see MPU9250_PWR1_TEMP_DIS_BIT + */ +bool MPU9250::getTempSensorEnabled() { + I2Cdev::readBit(devAddr, MPU9250_RA_PWR_MGMT_1, MPU9250_PWR1_TEMP_DIS_BIT, buffer); + return buffer[0] == 0; // 1 is actually disabled here +} +/** Set temperature sensor enabled status. + * Note: this register stores the *disabled* value, but for consistency with the + * rest of the code, the function is named and used with standard true/false + * values to indicate whether the sensor is enabled or disabled, respectively. + * + * @param enabled New temperature sensor enabled status + * @see getTempSensorEnabled() + * @see MPU9250_RA_PWR_MGMT_1 + * @see MPU9250_PWR1_TEMP_DIS_BIT + */ +void MPU9250::setTempSensorEnabled(bool enabled) { + // 1 is actually disabled here + I2Cdev::writeBit(devAddr, MPU9250_RA_PWR_MGMT_1, MPU9250_PWR1_TEMP_DIS_BIT, !enabled); +} +/** Get clock source setting. + * @return Current clock source setting + * @see MPU9250_RA_PWR_MGMT_1 + * @see MPU9250_PWR1_CLKSEL_BIT + * @see MPU9250_PWR1_CLKSEL_LENGTH + */ +uint8_t MPU9250::getClockSource() { + I2Cdev::readBits(devAddr, MPU9250_RA_PWR_MGMT_1, MPU9250_PWR1_CLKSEL_BIT, MPU9250_PWR1_CLKSEL_LENGTH, buffer); + return buffer[0]; +} +/** Set clock source setting. + * An internal 8MHz oscillator, gyroscope based clock, or external sources can + * be selected as the MPU-60X0 clock source. When the internal 8 MHz oscillator + * or an external source is chosen as the clock source, the MPU-60X0 can operate + * in low power modes with the gyroscopes disabled. + * + * Upon power up, the MPU-60X0 clock source defaults to the internal oscillator. + * However, it is highly recommended that the device be configured to use one of + * the gyroscopes (or an external clock source) as the clock reference for + * improved stability. The clock source can be selected according to the following table: + * + *
+ * CLK_SEL | Clock Source
+ * --------+--------------------------------------
+ * 0       | Internal oscillator
+ * 1       | PLL with X Gyro reference
+ * 2       | PLL with Y Gyro reference
+ * 3       | PLL with Z Gyro reference
+ * 4       | PLL with external 32.768kHz reference
+ * 5       | PLL with external 19.2MHz reference
+ * 6       | Reserved
+ * 7       | Stops the clock and keeps the timing generator in reset
+ * 
+ * + * @param source New clock source setting + * @see getClockSource() + * @see MPU9250_RA_PWR_MGMT_1 + * @see MPU9250_PWR1_CLKSEL_BIT + * @see MPU9250_PWR1_CLKSEL_LENGTH + */ +void MPU9250::setClockSource(uint8_t source) { + I2Cdev::writeBits(devAddr, MPU9250_RA_PWR_MGMT_1, MPU9250_PWR1_CLKSEL_BIT, MPU9250_PWR1_CLKSEL_LENGTH, source); +} + +// PWR_MGMT_2 register + +/** Get wake frequency in Accel-Only Low Power Mode. + * The MPU-60X0 can be put into Accerlerometer Only Low Power Mode by setting + * PWRSEL to 1 in the Power Management 1 register (Register 107). In this mode, + * the device will power off all devices except for the primary I2C interface, + * waking only the accelerometer at fixed intervals to take a single + * measurement. The frequency of wake-ups can be configured with LP_WAKE_CTRL + * as shown below: + * + *
+ * LP_WAKE_CTRL | Wake-up Frequency
+ * -------------+------------------
+ * 0            | 1.25 Hz
+ * 1            | 2.5 Hz
+ * 2            | 5 Hz
+ * 3            | 10 Hz
+ * 
+ *
+ * For further information regarding the MPU-60X0's power modes, please refer to
+ * Register 107.
+ *
+ * @return Current wake frequency
+ * @see MPU9250_RA_PWR_MGMT_2
+ */
+uint8_t MPU9250::getWakeFrequency() {
+    I2Cdev::readBits(devAddr, MPU9250_RA_PWR_MGMT_2, MPU9250_PWR2_LP_WAKE_CTRL_BIT, MPU9250_PWR2_LP_WAKE_CTRL_LENGTH, buffer);
+    return buffer[0];
+}
+/** Set wake frequency in Accel-Only Low Power Mode.
+ * @param frequency New wake frequency
+ * @see MPU9250_RA_PWR_MGMT_2
+ */
+void MPU9250::setWakeFrequency(uint8_t frequency) {
+    I2Cdev::writeBits(devAddr, MPU9250_RA_PWR_MGMT_2, MPU9250_PWR2_LP_WAKE_CTRL_BIT, MPU9250_PWR2_LP_WAKE_CTRL_LENGTH, frequency);
+}
+
+/** Get X-axis accelerometer standby enabled status.
+ * If enabled, the X-axis will not gather or report data (or use power).
+ * @return Current X-axis standby enabled status
+ * @see MPU9250_RA_PWR_MGMT_2
+ * @see MPU9250_PWR2_STBY_XA_BIT
+ */
+bool MPU9250::getStandbyXAccelEnabled() {
+    I2Cdev::readBit(devAddr, MPU9250_RA_PWR_MGMT_2, MPU9250_PWR2_STBY_XA_BIT, buffer);
+    return buffer[0];
+}
+/** Set X-axis accelerometer standby enabled status.
+ * @param New X-axis standby enabled status
+ * @see getStandbyXAccelEnabled()
+ * @see MPU9250_RA_PWR_MGMT_2
+ * @see MPU9250_PWR2_STBY_XA_BIT
+ */
+void MPU9250::setStandbyXAccelEnabled(bool enabled) {
+    I2Cdev::writeBit(devAddr, MPU9250_RA_PWR_MGMT_2, MPU9250_PWR2_STBY_XA_BIT, enabled);
+}
+/** Get Y-axis accelerometer standby enabled status.
+ * If enabled, the Y-axis will not gather or report data (or use power).
+ * @return Current Y-axis standby enabled status
+ * @see MPU9250_RA_PWR_MGMT_2
+ * @see MPU9250_PWR2_STBY_YA_BIT
+ */
+bool MPU9250::getStandbyYAccelEnabled() {
+    I2Cdev::readBit(devAddr, MPU9250_RA_PWR_MGMT_2, MPU9250_PWR2_STBY_YA_BIT, buffer);
+    return buffer[0];
+}
+/** Set Y-axis accelerometer standby enabled status.
+ * @param New Y-axis standby enabled status
+ * @see getStandbyYAccelEnabled()
+ * @see MPU9250_RA_PWR_MGMT_2
+ * @see MPU9250_PWR2_STBY_YA_BIT
+ */
+void MPU9250::setStandbyYAccelEnabled(bool enabled) {
+    I2Cdev::writeBit(devAddr, MPU9250_RA_PWR_MGMT_2, MPU9250_PWR2_STBY_YA_BIT, enabled);
+}
+/** Get Z-axis accelerometer standby enabled status.
+ * If enabled, the Z-axis will not gather or report data (or use power).
+ * @return Current Z-axis standby enabled status
+ * @see MPU9250_RA_PWR_MGMT_2
+ * @see MPU9250_PWR2_STBY_ZA_BIT
+ */
+bool MPU9250::getStandbyZAccelEnabled() {
+    I2Cdev::readBit(devAddr, MPU9250_RA_PWR_MGMT_2, MPU9250_PWR2_STBY_ZA_BIT, buffer);
+    return buffer[0];
+}
+/** Set Z-axis accelerometer standby enabled status.
+ * @param New Z-axis standby enabled status
+ * @see getStandbyZAccelEnabled()
+ * @see MPU9250_RA_PWR_MGMT_2
+ * @see MPU9250_PWR2_STBY_ZA_BIT
+ */
+void MPU9250::setStandbyZAccelEnabled(bool enabled) {
+    I2Cdev::writeBit(devAddr, MPU9250_RA_PWR_MGMT_2, MPU9250_PWR2_STBY_ZA_BIT, enabled);
+}
+/** Get X-axis gyroscope standby enabled status.
+ * If enabled, the X-axis will not gather or report data (or use power).
+ * @return Current X-axis standby enabled status
+ * @see MPU9250_RA_PWR_MGMT_2
+ * @see MPU9250_PWR2_STBY_XG_BIT
+ */
+bool MPU9250::getStandbyXGyroEnabled() {
+    I2Cdev::readBit(devAddr, MPU9250_RA_PWR_MGMT_2, MPU9250_PWR2_STBY_XG_BIT, buffer);
+    return buffer[0];
+}
+/** Set X-axis gyroscope standby enabled status.
+ * @param New X-axis standby enabled status
+ * @see getStandbyXGyroEnabled()
+ * @see MPU9250_RA_PWR_MGMT_2
+ * @see MPU9250_PWR2_STBY_XG_BIT
+ */
+void MPU9250::setStandbyXGyroEnabled(bool enabled) {
+    I2Cdev::writeBit(devAddr, MPU9250_RA_PWR_MGMT_2, MPU9250_PWR2_STBY_XG_BIT, enabled);
+}
+/** Get Y-axis gyroscope standby enabled status.
+ * If enabled, the Y-axis will not gather or report data (or use power).
+ * @return Current Y-axis standby enabled status
+ * @see MPU9250_RA_PWR_MGMT_2
+ * @see MPU9250_PWR2_STBY_YG_BIT
+ */
+bool MPU9250::getStandbyYGyroEnabled() {
+    I2Cdev::readBit(devAddr, MPU9250_RA_PWR_MGMT_2, MPU9250_PWR2_STBY_YG_BIT, buffer);
+    return buffer[0];
+}
+/** Set Y-axis gyroscope standby enabled status.
+ * @param New Y-axis standby enabled status
+ * @see getStandbyYGyroEnabled()
+ * @see MPU9250_RA_PWR_MGMT_2
+ * @see MPU9250_PWR2_STBY_YG_BIT
+ */
+void MPU9250::setStandbyYGyroEnabled(bool enabled) {
+    I2Cdev::writeBit(devAddr, MPU9250_RA_PWR_MGMT_2, MPU9250_PWR2_STBY_YG_BIT, enabled);
+}
+/** Get Z-axis gyroscope standby enabled status.
+ * If enabled, the Z-axis will not gather or report data (or use power).
+ * @return Current Z-axis standby enabled status
+ * @see MPU9250_RA_PWR_MGMT_2
+ * @see MPU9250_PWR2_STBY_ZG_BIT
+ */
+bool MPU9250::getStandbyZGyroEnabled() {
+    I2Cdev::readBit(devAddr, MPU9250_RA_PWR_MGMT_2, MPU9250_PWR2_STBY_ZG_BIT, buffer);
+    return buffer[0];
+}
+/** Set Z-axis gyroscope standby enabled status.
+ * @param New Z-axis standby enabled status
+ * @see getStandbyZGyroEnabled()
+ * @see MPU9250_RA_PWR_MGMT_2
+ * @see MPU9250_PWR2_STBY_ZG_BIT
+ */
+void MPU9250::setStandbyZGyroEnabled(bool enabled) {
+    I2Cdev::writeBit(devAddr, MPU9250_RA_PWR_MGMT_2, MPU9250_PWR2_STBY_ZG_BIT, enabled);
+}
+
+// FIFO_COUNT* registers
+
+/** Get current FIFO buffer size.
+ * This value indicates the number of bytes stored in the FIFO buffer. This
+ * number is in turn the number of bytes that can be read from the FIFO buffer
+ * and it is directly proportional to the number of samples available given the
+ * set of sensor data bound to be stored in the FIFO (register 35 and 36).
+ * @return Current FIFO buffer size
+ */
+uint16_t MPU9250::getFIFOCount() {
+    I2Cdev::readBytes(devAddr, MPU9250_RA_FIFO_COUNTH, 2, buffer);
+    return (((uint16_t)buffer[0]) << 8) | buffer[1];
+}
+
+// FIFO_R_W register
+
+/** Get byte from FIFO buffer.
+ * This register is used to read and write data from the FIFO buffer. Data is
+ * written to the FIFO in order of register number (from lowest to highest). If
+ * all the FIFO enable flags (see below) are enabled and all External Sensor
+ * Data registers (Registers 73 to 96) are associated with a Slave device, the
+ * contents of registers 59 through 96 will be written in order at the Sample
+ * Rate.
+ *
+ * The contents of the sensor data registers (Registers 59 to 96) are written
+ * into the FIFO buffer when their corresponding FIFO enable flags are set to 1
+ * in FIFO_EN (Register 35). An additional flag for the sensor data registers
+ * associated with I2C Slave 3 can be found in I2C_MST_CTRL (Register 36).
+ *
+ * If the FIFO buffer has overflowed, the status bit FIFO_OFLOW_INT is
+ * automatically set to 1. This bit is located in INT_STATUS (Register 58).
+ * When the FIFO buffer has overflowed, the oldest data will be lost and new
+ * data will be written to the FIFO.
+ *
+ * If the FIFO buffer is empty, reading this register will return the last byte
+ * that was previously read from the FIFO until new data is available. The user
+ * should check FIFO_COUNT to ensure that the FIFO buffer is not read when
+ * empty.
+ *
+ * @return Byte from FIFO buffer
+ */
+uint8_t MPU9250::getFIFOByte() {
+    I2Cdev::readByte(devAddr, MPU9250_RA_FIFO_R_W, buffer);
+    return buffer[0];
+}
+void MPU9250::getFIFOBytes(uint8_t *data, uint8_t length) {
+    I2Cdev::readBytes(devAddr, MPU9250_RA_FIFO_R_W, length, data);
+}
+/** Write byte to FIFO buffer.
+ * @see getFIFOByte()
+ * @see MPU9250_RA_FIFO_R_W
+ */
+void MPU9250::setFIFOByte(uint8_t data) {
+    I2Cdev::writeByte(devAddr, MPU9250_RA_FIFO_R_W, data);
+}
+
+// WHO_AM_I register
+
+/** Get Device ID.
+ * This register is used to verify the identity of the device (0b110100, 0x34).
+ * @return Device ID (6 bits only! should be 0x34)
+ * @see MPU9250_RA_WHO_AM_I
+ * @see MPU9250_WHO_AM_I_BIT
+ * @see MPU9250_WHO_AM_I_LENGTH
+ */
+uint8_t MPU9250::getDeviceID() {
+//	#define MPU9250_RA_WHO_AM_I         0x75
+// 	#define MPU9250_WHO_AM_I_BIT        6
+//	#define MPU9250_WHO_AM_I_LENGTH     8
+//    I2Cdev::readBits(devAddr, MPU9250_RA_WHO_AM_I, MPU9250_WHO_AM_I_BIT, MPU9250_WHO_AM_I_LENGTH, buffer);
+//    return buffer[0];
+    I2Cdev::readByte(devAddr, MPU9250_RA_WHO_AM_I, buffer);
+    return buffer[0];
+}
+/** Set Device ID.
+ * Write a new ID into the WHO_AM_I register (no idea why this should ever be
+ * necessary though).
+ * @param id New device ID to set.
+ * @see getDeviceID()
+ * @see MPU9250_RA_WHO_AM_I
+ * @see MPU9250_WHO_AM_I_BIT
+ * @see MPU9250_WHO_AM_I_LENGTH
+ */
+void MPU9250::setDeviceID(uint8_t id) {
+    I2Cdev::writeBits(devAddr, MPU9250_RA_WHO_AM_I, MPU9250_WHO_AM_I_BIT, MPU9250_WHO_AM_I_LENGTH, id);
+}
+
+// ======== UNDOCUMENTED/DMP REGISTERS/METHODS ========
+
+// XG_OFFS_TC register
+
+uint8_t MPU9250::getOTPBankValid() {
+    I2Cdev::readBit(devAddr, MPU9250_RA_XG_OFFS_TC, MPU9250_TC_OTP_BNK_VLD_BIT, buffer);
+    return buffer[0];
+}
+void MPU9250::setOTPBankValid(bool enabled) {
+    I2Cdev::writeBit(devAddr, MPU9250_RA_XG_OFFS_TC, MPU9250_TC_OTP_BNK_VLD_BIT, enabled);
+}
+int8_t MPU9250::getXGyroOffset() {
+    I2Cdev::readBits(devAddr, MPU9250_RA_XG_OFFS_TC, MPU9250_TC_OFFSET_BIT, MPU9250_TC_OFFSET_LENGTH, buffer);
+    return buffer[0];
+}
+void MPU9250::setXGyroOffset(int8_t offset) {
+    I2Cdev::writeBits(devAddr, MPU9250_RA_XG_OFFS_TC, MPU9250_TC_OFFSET_BIT, MPU9250_TC_OFFSET_LENGTH, offset);
+}
+
+// YG_OFFS_TC register
+
+int8_t MPU9250::getYGyroOffset() {
+    I2Cdev::readBits(devAddr, MPU9250_RA_YG_OFFS_TC, MPU9250_TC_OFFSET_BIT, MPU9250_TC_OFFSET_LENGTH, buffer);
+    return buffer[0];
+}
+void MPU9250::setYGyroOffset(int8_t offset) {
+    I2Cdev::writeBits(devAddr, MPU9250_RA_YG_OFFS_TC, MPU9250_TC_OFFSET_BIT, MPU9250_TC_OFFSET_LENGTH, offset);
+}
+
+// ZG_OFFS_TC register
+
+int8_t MPU9250::getZGyroOffset() {
+    I2Cdev::readBits(devAddr, MPU9250_RA_ZG_OFFS_TC, MPU9250_TC_OFFSET_BIT, MPU9250_TC_OFFSET_LENGTH, buffer);
+    return buffer[0];
+}
+void MPU9250::setZGyroOffset(int8_t offset) {
+    I2Cdev::writeBits(devAddr, MPU9250_RA_ZG_OFFS_TC, MPU9250_TC_OFFSET_BIT, MPU9250_TC_OFFSET_LENGTH, offset);
+}
+
+// X_FINE_GAIN register
+
+int8_t MPU9250::getXFineGain() {
+    I2Cdev::readByte(devAddr, MPU9250_RA_X_FINE_GAIN, buffer);
+    return buffer[0];
+}
+void MPU9250::setXFineGain(int8_t gain) {
+    I2Cdev::writeByte(devAddr, MPU9250_RA_X_FINE_GAIN, gain);
+}
+
+// Y_FINE_GAIN register
+
+int8_t MPU9250::getYFineGain() {
+    I2Cdev::readByte(devAddr, MPU9250_RA_Y_FINE_GAIN, buffer);
+    return buffer[0];
+}
+void MPU9250::setYFineGain(int8_t gain) {
+    I2Cdev::writeByte(devAddr, MPU9250_RA_Y_FINE_GAIN, gain);
+}
+
+// Z_FINE_GAIN register
+
+int8_t MPU9250::getZFineGain() {
+    I2Cdev::readByte(devAddr, MPU9250_RA_Z_FINE_GAIN, buffer);
+    return buffer[0];
+}
+void MPU9250::setZFineGain(int8_t gain) {
+    I2Cdev::writeByte(devAddr, MPU9250_RA_Z_FINE_GAIN, gain);
+}
+
+// XA_OFFS_* registers
+
+int16_t MPU9250::getXAccelOffset() {
+    I2Cdev::readBytes(devAddr, MPU9250_RA_XA_OFFS_H, 2, buffer);
+    return ((((int16_t)buffer[0]) << 8) | buffer[1]);
+}
+void MPU9250::setXAccelOffset(int16_t offset) {
+    int16_t bit0 = getXAccelOffset() & 1;
+    int16_t value = offset & 0xFFFE | bit0;
+    
+    I2Cdev::writeWord(devAddr, MPU9250_RA_XA_OFFS_H, value);
+}
+
+// YA_OFFS_* register
+
+int16_t MPU9250::getYAccelOffset() {
+    I2Cdev::readBytes(devAddr, MPU9250_RA_YA_OFFS_H, 2, buffer);
+    return ((((int16_t)buffer[0]) << 8) | buffer[1]);
+}
+void MPU9250::setYAccelOffset(int16_t offset) {
+    int16_t bit0 = getYAccelOffset() & 1;
+    int16_t value = offset & 0xFFFE | bit0;
+
+    I2Cdev::writeWord(devAddr, MPU9250_RA_YA_OFFS_H, value);
+}
+
+// ZA_OFFS_* register
+
+int16_t MPU9250::getZAccelOffset() {
+    I2Cdev::readBytes(devAddr, MPU9250_RA_ZA_OFFS_H, 2, buffer);
+    return ((((int16_t)buffer[0]) << 8) | buffer[1]);
+}
+void MPU9250::setZAccelOffset(int16_t offset) {
+    int16_t bit0 = getZAccelOffset() & 1;
+    int16_t value = offset & 0xFFFE | bit0;
+
+    I2Cdev::writeWord(devAddr, MPU9250_RA_ZA_OFFS_H, value);
+}
+
+// XG_OFFS_USR* registers
+
+int16_t MPU9250::getXGyroOffsetUser() {
+    I2Cdev::readBytes(devAddr, MPU9250_RA_XG_OFFS_USRH, 2, buffer);
+    return (((int16_t)buffer[0]) << 8) | buffer[1];
+}
+void MPU9250::setXGyroOffsetUser(int16_t offset) {
+    I2Cdev::writeWord(devAddr, MPU9250_RA_XG_OFFS_USRH, offset);
+}
+
+// YG_OFFS_USR* register
+
+int16_t MPU9250::getYGyroOffsetUser() {
+    I2Cdev::readBytes(devAddr, MPU9250_RA_YG_OFFS_USRH, 2, buffer);
+    return (((int16_t)buffer[0]) << 8) | buffer[1];
+}
+void MPU9250::setYGyroOffsetUser(int16_t offset) {
+    I2Cdev::writeWord(devAddr, MPU9250_RA_YG_OFFS_USRH, offset);
+}
+
+// ZG_OFFS_USR* register
+
+int16_t MPU9250::getZGyroOffsetUser() {
+    I2Cdev::readBytes(devAddr, MPU9250_RA_ZG_OFFS_USRH, 2, buffer);
+    return (((int16_t)buffer[0]) << 8) | buffer[1];
+}
+void MPU9250::setZGyroOffsetUser(int16_t offset) {
+    I2Cdev::writeWord(devAddr, MPU9250_RA_ZG_OFFS_USRH, offset);
+}
+
+// INT_ENABLE register (DMP functions)
+
+bool MPU9250::getIntPLLReadyEnabled() {
+    I2Cdev::readBit(devAddr, MPU9250_RA_INT_ENABLE, MPU9250_INTERRUPT_PLL_RDY_INT_BIT, buffer);
+    return buffer[0];
+}
+void MPU9250::setIntPLLReadyEnabled(bool enabled) {
+    I2Cdev::writeBit(devAddr, MPU9250_RA_INT_ENABLE, MPU9250_INTERRUPT_PLL_RDY_INT_BIT, enabled);
+}
+bool MPU9250::getIntDMPEnabled() {
+    I2Cdev::readBit(devAddr, MPU9250_RA_INT_ENABLE, MPU9250_INTERRUPT_DMP_INT_BIT, buffer);
+    return buffer[0];
+}
+void MPU9250::setIntDMPEnabled(bool enabled) {
+    I2Cdev::writeBit(devAddr, MPU9250_RA_INT_ENABLE, MPU9250_INTERRUPT_DMP_INT_BIT, enabled);
+}
+
+// DMP_INT_STATUS
+
+bool MPU9250::getDMPInt5Status() {
+    I2Cdev::readBit(devAddr, MPU9250_RA_DMP_INT_STATUS, MPU9250_DMPINT_5_BIT, buffer);
+    return buffer[0];
+}
+bool MPU9250::getDMPInt4Status() {
+    I2Cdev::readBit(devAddr, MPU9250_RA_DMP_INT_STATUS, MPU9250_DMPINT_4_BIT, buffer);
+    return buffer[0];
+}
+bool MPU9250::getDMPInt3Status() {
+    I2Cdev::readBit(devAddr, MPU9250_RA_DMP_INT_STATUS, MPU9250_DMPINT_3_BIT, buffer);
+    return buffer[0];
+}
+bool MPU9250::getDMPInt2Status() {
+    I2Cdev::readBit(devAddr, MPU9250_RA_DMP_INT_STATUS, MPU9250_DMPINT_2_BIT, buffer);
+    return buffer[0];
+}
+bool MPU9250::getDMPInt1Status() {
+    I2Cdev::readBit(devAddr, MPU9250_RA_DMP_INT_STATUS, MPU9250_DMPINT_1_BIT, buffer);
+    return buffer[0];
+}
+bool MPU9250::getDMPInt0Status() {
+    I2Cdev::readBit(devAddr, MPU9250_RA_DMP_INT_STATUS, MPU9250_DMPINT_0_BIT, buffer);
+    return buffer[0];
+}
+
+// INT_STATUS register (DMP functions)
+
+bool MPU9250::getIntPLLReadyStatus() {
+    I2Cdev::readBit(devAddr, MPU9250_RA_INT_STATUS, MPU9250_INTERRUPT_PLL_RDY_INT_BIT, buffer);
+    return buffer[0];
+}
+bool MPU9250::getIntDMPStatus() {
+    I2Cdev::readBit(devAddr, MPU9250_RA_INT_STATUS, MPU9250_INTERRUPT_DMP_INT_BIT, buffer);
+    return buffer[0];
+}
+
+// USER_CTRL register (DMP functions)
+
+bool MPU9250::getDMPEnabled() {
+    I2Cdev::readBit(devAddr, MPU9250_RA_USER_CTRL, MPU9250_USERCTRL_DMP_EN_BIT, buffer);
+    return buffer[0];
+}
+void MPU9250::setDMPEnabled(bool enabled) {
+    I2Cdev::writeBit(devAddr, MPU9250_RA_USER_CTRL, MPU9250_USERCTRL_DMP_EN_BIT, enabled);
+}
+void MPU9250::resetDMP() {
+    I2Cdev::writeBit(devAddr, MPU9250_RA_USER_CTRL, MPU9250_USERCTRL_DMP_RESET_BIT, true);
+}
+
+// BANK_SEL register
+
+void MPU9250::setMemoryBank(uint8_t bank, bool prefetchEnabled, bool userBank) {
+    bank &= 0x1F;
+    if (userBank) bank |= 0x20;
+    if (prefetchEnabled) bank |= 0x40;
+    I2Cdev::writeByte(devAddr, MPU9250_RA_BANK_SEL, bank);
+}
+
+// MEM_START_ADDR register
+
+void MPU9250::setMemoryStartAddress(uint8_t address) {
+    I2Cdev::writeByte(devAddr, MPU9250_RA_MEM_START_ADDR, address);
+}
+
+// MEM_R_W register
+
+uint8_t MPU9250::readMemoryByte() {
+    I2Cdev::readByte(devAddr, MPU9250_RA_MEM_R_W, buffer);
+    return buffer[0];
+}
+void MPU9250::writeMemoryByte(uint8_t data) {
+    I2Cdev::writeByte(devAddr, MPU9250_RA_MEM_R_W, data);
+}
+void MPU9250::readMemoryBlock(uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address) {
+    setMemoryBank(bank);
+    setMemoryStartAddress(address);
+    uint8_t chunkSize;
+    for (uint16_t i = 0; i < dataSize;) {
+        // determine correct chunk size according to bank position and data size
+        chunkSize = MPU9250_DMP_MEMORY_CHUNK_SIZE;
+
+        // make sure we don't go past the data size
+        if (i + chunkSize > dataSize) chunkSize = dataSize - i;
+
+        // make sure this chunk doesn't go past the bank boundary (256 bytes)
+        if (chunkSize > 256 - address) chunkSize = 256 - address;
+
+        // read the chunk of data as specified
+        I2Cdev::readBytes(devAddr, MPU9250_RA_MEM_R_W, chunkSize, data + i);
+        
+        // increase byte index by [chunkSize]
+        i += chunkSize;
+
+        // uint8_t automatically wraps to 0 at 256
+        address += chunkSize;
+
+        // if we aren't done, update bank (if necessary) and address
+        if (i < dataSize) {
+            if (address == 0) bank++;
+            setMemoryBank(bank);
+            setMemoryStartAddress(address);
+        }
+    }
+}
+bool MPU9250::writeMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address, bool verify, bool useProgMem) {
+    setMemoryBank(bank);
+    setMemoryStartAddress(address);
+    uint8_t chunkSize;
+    uint8_t *verifyBuffer;
+    uint8_t *progBuffer;
+    uint16_t i;
+    uint8_t j;
+    if (verify) verifyBuffer = (uint8_t *)malloc(MPU9250_DMP_MEMORY_CHUNK_SIZE);
+    if (useProgMem) progBuffer = (uint8_t *)malloc(MPU9250_DMP_MEMORY_CHUNK_SIZE);
+    for (i = 0; i < dataSize;) {
+        // determine correct chunk size according to bank position and data size
+        chunkSize = MPU9250_DMP_MEMORY_CHUNK_SIZE;
+
+        // make sure we don't go past the data size
+        if (i + chunkSize > dataSize) chunkSize = dataSize - i;
+
+        // make sure this chunk doesn't go past the bank boundary (256 bytes)
+        if (chunkSize > 256 - address) chunkSize = 256 - address;
+        
+        if (useProgMem) {
+            // write the chunk of data as specified
+            for (j = 0; j < chunkSize; j++) progBuffer[j] = pgm_read_byte(data + i + j);
+        } else {
+            // write the chunk of data as specified
+            progBuffer = (uint8_t *)data + i;
+        }
+
+        I2Cdev::writeBytes(devAddr, MPU9250_RA_MEM_R_W, chunkSize, progBuffer);
+
+        // verify data if needed
+        if (verify && verifyBuffer) {
+            setMemoryBank(bank);
+            setMemoryStartAddress(address);
+            I2Cdev::readBytes(devAddr, MPU9250_RA_MEM_R_W, chunkSize, verifyBuffer);
+            if (memcmp(progBuffer, verifyBuffer, chunkSize) != 0) {
+                /*Serial.print("Block write verification error, bank ");
+                Serial.print(bank, DEC);
+                Serial.print(", address ");
+                Serial.print(address, DEC);
+                Serial.print("!\nExpected:");
+                for (j = 0; j < chunkSize; j++) {
+                    Serial.print(" 0x");
+                    if (progBuffer[j] < 16) Serial.print("0");
+                    Serial.print(progBuffer[j], HEX);
+                }
+                Serial.print("\nReceived:");
+                for (uint8_t j = 0; j < chunkSize; j++) {
+                    Serial.print(" 0x");
+                    if (verifyBuffer[i + j] < 16) Serial.print("0");
+                    Serial.print(verifyBuffer[i + j], HEX);
+                }
+                Serial.print("\n");*/
+                free(verifyBuffer);
+                if (useProgMem) free(progBuffer);
+                return false; // uh oh.
+            }
+        }
+
+        // increase byte index by [chunkSize]
+        i += chunkSize;
+
+        // uint8_t automatically wraps to 0 at 256
+        address += chunkSize;
+
+        // if we aren't done, update bank (if necessary) and address
+        if (i < dataSize) {
+            if (address == 0) bank++;
+            setMemoryBank(bank);
+            setMemoryStartAddress(address);
+        }
+    }
+    if (verify) free(verifyBuffer);
+    if (useProgMem) free(progBuffer);
+    return true;
+}
+bool MPU9250::writeProgMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address, bool verify) {
+    return writeMemoryBlock(data, dataSize, bank, address, verify, true);
+}
+bool MPU9250::writeDMPConfigurationSet(const uint8_t *data, uint16_t dataSize, bool useProgMem) {
+    uint8_t *progBuffer, success, special;
+    uint16_t i, j;
+    if (useProgMem) {
+        progBuffer = (uint8_t *)malloc(8); // assume 8-byte blocks, realloc later if necessary
+    }
+
+    // config set data is a long string of blocks with the following structure:
+    // [bank] [offset] [length] [byte[0], byte[1], ..., byte[length]]
+    uint8_t bank, offset, length;
+    for (i = 0; i < dataSize;) {
+        if (useProgMem) {
+            bank = pgm_read_byte(data + i++);
+            offset = pgm_read_byte(data + i++);
+            length = pgm_read_byte(data + i++);
+        } else {
+            bank = data[i++];
+            offset = data[i++];
+            length = data[i++];
+        }
+
+        // write data or perform special action
+        if (length > 0) {
+            // regular block of data to write
+            /*Serial.print("Writing config block to bank ");
+            Serial.print(bank);
+            Serial.print(", offset ");
+            Serial.print(offset);
+            Serial.print(", length=");
+            Serial.println(length);*/
+            if (useProgMem) {
+                if (sizeof(progBuffer) < length) progBuffer = (uint8_t *)realloc(progBuffer, length);
+                for (j = 0; j < length; j++) progBuffer[j] = pgm_read_byte(data + i + j);
+            } else {
+                progBuffer = (uint8_t *)data + i;
+            }
+            success = writeMemoryBlock(progBuffer, length, bank, offset, true);
+            i += length;
+        } else {
+            // special instruction
+            // NOTE: this kind of behavior (what and when to do certain things)
+            // is totally undocumented. This code is in here based on observed
+            // behavior only, and exactly why (or even whether) it has to be here
+            // is anybody's guess for now.
+            if (useProgMem) {
+                special = pgm_read_byte(data + i++);
+            } else {
+                special = data[i++];
+            }
+            /*Serial.print("Special command code ");
+            Serial.print(special, HEX);
+            Serial.println(" found...");*/
+            if (special == 0x01) {
+                // enable DMP-related interrupts
+                
+                //setIntZeroMotionEnabled(true);
+                //setIntFIFOBufferOverflowEnabled(true);
+                //setIntDMPEnabled(true);
+                I2Cdev::writeByte(devAddr, MPU9250_RA_INT_ENABLE, 0x32);  // single operation
+
+                success = true;
+            } else {
+                // unknown special command
+                success = false;
+            }
+        }
+        
+        if (!success) {
+            if (useProgMem) free(progBuffer);
+            return false; // uh oh
+        }
+    }
+    if (useProgMem) free(progBuffer);
+    return true;
+}
+bool MPU9250::writeProgDMPConfigurationSet(const uint8_t *data, uint16_t dataSize) {
+    return writeDMPConfigurationSet(data, dataSize, true);
+}
+
+// DMP_CFG_1 register
+
+uint8_t MPU9250::getDMPConfig1() {
+    I2Cdev::readByte(devAddr, MPU9250_RA_DMP_CFG_1, buffer);
+    return buffer[0];
+}
+void MPU9250::setDMPConfig1(uint8_t config) {
+    I2Cdev::writeByte(devAddr, MPU9250_RA_DMP_CFG_1, config);
+}
+
+// DMP_CFG_2 register
+
+uint8_t MPU9250::getDMPConfig2() {
+    I2Cdev::readByte(devAddr, MPU9250_RA_DMP_CFG_2, buffer);
+    return buffer[0];
+}
+void MPU9250::setDMPConfig2(uint8_t config) {
+    I2Cdev::writeByte(devAddr, MPU9250_RA_DMP_CFG_2, config);
+}
\ No newline at end of file
diff --git a/Arduino/MPU9250/MPU9250.h b/Arduino/MPU9250/MPU9250.h
new file mode 100644
index 00000000..afd59daa
--- /dev/null
+++ b/Arduino/MPU9250/MPU9250.h
@@ -0,0 +1,1004 @@
+// I2Cdev library collection - MPU9250 I2C device class
+// Based on InvenSense MPU-9250 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00)
+// 10/3/2011 by Jeff Rowberg 
+// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
+//
+// Changelog:
+//     ... - ongoing debug release
+
+// NOTE: THIS IS ONLY A PARIAL RELEASE. THIS DEVICE CLASS IS CURRENTLY UNDERGOING ACTIVE
+// DEVELOPMENT AND IS STILL MISSING SOME IMPORTANT FEATURES. PLEASE KEEP THIS IN MIND IF
+// YOU DECIDE TO USE THIS PARTICULAR CODE FOR ANYTHING.
+
+/* ============================================
+I2Cdev device library code is placed under the MIT license
+Copyright (c) 2012 Jeff Rowberg
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+===============================================
+*/
+
+#ifndef _MPU9250_H_
+#define _MPU9250_H_
+
+#include "I2Cdev.h"
+#include 
+
+//Magnetometer Registers
+#define MPU9150_RA_MAG_ADDRESS		0x0C
+#define MPU9150_RA_MAG_XOUT_L		0x03
+#define MPU9150_RA_MAG_XOUT_H		0x04
+#define MPU9150_RA_MAG_YOUT_L		0x05
+#define MPU9150_RA_MAG_YOUT_H		0x06
+#define MPU9150_RA_MAG_ZOUT_L		0x07
+#define MPU9150_RA_MAG_ZOUT_H		0x08
+
+#define MPU9250_ADDRESS_AD0_LOW     0x68 // address pin low (GND), default for InvenSense evaluation board
+#define MPU9250_ADDRESS_AD0_HIGH    0x69 // address pin high (VCC)
+#define MPU9250_DEFAULT_ADDRESS     MPU9250_ADDRESS_AD0_LOW
+
+#define MPU9250_RA_XG_OFFS_TC       0x00 //[7] PWR_MODE, [6:1] XG_OFFS_TC, [0] OTP_BNK_VLD
+#define MPU9250_RA_YG_OFFS_TC       0x01 //[7] PWR_MODE, [6:1] YG_OFFS_TC, [0] OTP_BNK_VLD
+#define MPU9250_RA_ZG_OFFS_TC       0x02 //[7] PWR_MODE, [6:1] ZG_OFFS_TC, [0] OTP_BNK_VLD
+#define MPU9250_RA_X_FINE_GAIN      0x03 //[7:0] X_FINE_GAIN
+#define MPU9250_RA_Y_FINE_GAIN      0x04 //[7:0] Y_FINE_GAIN
+#define MPU9250_RA_Z_FINE_GAIN      0x05 //[7:0] Z_FINE_GAIN
+
+#define MPU9250_RA_XA_OFFS_H        0x77 //[15:0] XA_OFFS
+#define MPU9250_RA_XA_OFFS_L_TC     0x78
+#define MPU9250_RA_YA_OFFS_H        0x7A //[15:0] YA_OFFS
+#define MPU9250_RA_YA_OFFS_L_TC     0x7B
+#define MPU9250_RA_ZA_OFFS_H        0x7D //[15:0] ZA_OFFS
+#define MPU9250_RA_ZA_OFFS_L_TC     0x7E
+
+//#define MPU9250_RA_XA_OFFS_H        0x06 //[15:0] XA_OFFS
+//#define MPU9250_RA_XA_OFFS_L_TC     0x07
+//#define MPU9250_RA_YA_OFFS_H        0x08 //[15:0] YA_OFFS
+//#define MPU9250_RA_YA_OFFS_L_TC     0x09
+//#define MPU9250_RA_ZA_OFFS_H        0x0A //[15:0] ZA_OFFS
+//#define MPU9250_RA_ZA_OFFS_L_TC     0x0B
+
+#define MPU9250_RA_XG_OFFS_USRH     0x13 //[15:0] XG_OFFS_USR
+#define MPU9250_RA_XG_OFFS_USRL     0x14
+#define MPU9250_RA_YG_OFFS_USRH     0x15 //[15:0] YG_OFFS_USR
+#define MPU9250_RA_YG_OFFS_USRL     0x16
+#define MPU9250_RA_ZG_OFFS_USRH     0x17 //[15:0] ZG_OFFS_USR
+#define MPU9250_RA_ZG_OFFS_USRL     0x18
+
+#define MPU9250_RA_SMPLRT_DIV       0x19
+#define MPU9250_RA_CONFIG           0x1A
+#define MPU9250_RA_GYRO_CONFIG      0x1B
+#define MPU9250_RA_ACCEL_CONFIG     0x1C
+#define MPU9250_RA_FF_THR           0x1D
+#define MPU9250_RA_FF_DUR           0x1E
+#define MPU9250_RA_MOT_THR          0x1F
+#define MPU9250_RA_MOT_DUR          0x20
+#define MPU9250_RA_ZRMOT_THR        0x21
+#define MPU9250_RA_ZRMOT_DUR        0x22
+#define MPU9250_RA_FIFO_EN          0x23
+#define MPU9250_RA_I2C_MST_CTRL     0x24
+#define MPU9250_RA_I2C_SLV0_ADDR    0x25
+#define MPU9250_RA_I2C_SLV0_REG     0x26
+#define MPU9250_RA_I2C_SLV0_CTRL    0x27
+#define MPU9250_RA_I2C_SLV1_ADDR    0x28
+#define MPU9250_RA_I2C_SLV1_REG     0x29
+#define MPU9250_RA_I2C_SLV1_CTRL    0x2A
+#define MPU9250_RA_I2C_SLV2_ADDR    0x2B
+#define MPU9250_RA_I2C_SLV2_REG     0x2C
+#define MPU9250_RA_I2C_SLV2_CTRL    0x2D
+#define MPU9250_RA_I2C_SLV3_ADDR    0x2E
+#define MPU9250_RA_I2C_SLV3_REG     0x2F
+#define MPU9250_RA_I2C_SLV3_CTRL    0x30
+#define MPU9250_RA_I2C_SLV4_ADDR    0x31
+#define MPU9250_RA_I2C_SLV4_REG     0x32
+#define MPU9250_RA_I2C_SLV4_DO      0x33
+#define MPU9250_RA_I2C_SLV4_CTRL    0x34
+#define MPU9250_RA_I2C_SLV4_DI      0x35
+#define MPU9250_RA_I2C_MST_STATUS   0x36
+#define MPU9250_RA_INT_PIN_CFG      0x37
+#define MPU9250_RA_INT_ENABLE       0x38
+#define MPU9250_RA_DMP_INT_STATUS   0x39
+#define MPU9250_RA_INT_STATUS       0x3A
+#define MPU9250_RA_ACCEL_XOUT_H     0x3B
+#define MPU9250_RA_ACCEL_XOUT_L     0x3C
+#define MPU9250_RA_ACCEL_YOUT_H     0x3D
+#define MPU9250_RA_ACCEL_YOUT_L     0x3E
+#define MPU9250_RA_ACCEL_ZOUT_H     0x3F
+#define MPU9250_RA_ACCEL_ZOUT_L     0x40
+#define MPU9250_RA_TEMP_OUT_H       0x41
+#define MPU9250_RA_TEMP_OUT_L       0x42
+#define MPU9250_RA_GYRO_XOUT_H      0x43
+#define MPU9250_RA_GYRO_XOUT_L      0x44
+#define MPU9250_RA_GYRO_YOUT_H      0x45
+#define MPU9250_RA_GYRO_YOUT_L      0x46
+#define MPU9250_RA_GYRO_ZOUT_H      0x47
+#define MPU9250_RA_GYRO_ZOUT_L      0x48
+#define MPU9250_RA_EXT_SENS_DATA_00 0x49
+#define MPU9250_RA_EXT_SENS_DATA_01 0x4A
+#define MPU9250_RA_EXT_SENS_DATA_02 0x4B
+#define MPU9250_RA_EXT_SENS_DATA_03 0x4C
+#define MPU9250_RA_EXT_SENS_DATA_04 0x4D
+#define MPU9250_RA_EXT_SENS_DATA_05 0x4E
+#define MPU9250_RA_EXT_SENS_DATA_06 0x4F
+#define MPU9250_RA_EXT_SENS_DATA_07 0x50
+#define MPU9250_RA_EXT_SENS_DATA_08 0x51
+#define MPU9250_RA_EXT_SENS_DATA_09 0x52
+#define MPU9250_RA_EXT_SENS_DATA_10 0x53
+#define MPU9250_RA_EXT_SENS_DATA_11 0x54
+#define MPU9250_RA_EXT_SENS_DATA_12 0x55
+#define MPU9250_RA_EXT_SENS_DATA_13 0x56
+#define MPU9250_RA_EXT_SENS_DATA_14 0x57
+#define MPU9250_RA_EXT_SENS_DATA_15 0x58
+#define MPU9250_RA_EXT_SENS_DATA_16 0x59
+#define MPU9250_RA_EXT_SENS_DATA_17 0x5A
+#define MPU9250_RA_EXT_SENS_DATA_18 0x5B
+#define MPU9250_RA_EXT_SENS_DATA_19 0x5C
+#define MPU9250_RA_EXT_SENS_DATA_20 0x5D
+#define MPU9250_RA_EXT_SENS_DATA_21 0x5E
+#define MPU9250_RA_EXT_SENS_DATA_22 0x5F
+#define MPU9250_RA_EXT_SENS_DATA_23 0x60
+#define MPU9250_RA_MOT_DETECT_STATUS    0x61
+#define MPU9250_RA_I2C_SLV0_DO      0x63
+#define MPU9250_RA_I2C_SLV1_DO      0x64
+#define MPU9250_RA_I2C_SLV2_DO      0x65
+#define MPU9250_RA_I2C_SLV3_DO      0x66
+#define MPU9250_RA_I2C_MST_DELAY_CTRL   0x67
+#define MPU9250_RA_SIGNAL_PATH_RESET    0x68
+#define MPU9250_RA_MOT_DETECT_CTRL      0x69
+#define MPU9250_RA_USER_CTRL        0x6A
+#define MPU9250_RA_PWR_MGMT_1       0x6B
+#define MPU9250_RA_PWR_MGMT_2       0x6C
+#define MPU9250_RA_BANK_SEL         0x6D
+#define MPU9250_RA_MEM_START_ADDR   0x6E
+#define MPU9250_RA_MEM_R_W          0x6F
+#define MPU9250_RA_DMP_CFG_1        0x70
+#define MPU9250_RA_DMP_CFG_2        0x71
+#define MPU9250_RA_FIFO_COUNTH      0x72
+#define MPU9250_RA_FIFO_COUNTL      0x73
+#define MPU9250_RA_FIFO_R_W         0x74
+#define MPU9250_RA_WHO_AM_I         0x75
+
+#define MPU9250_TC_PWR_MODE_BIT     7
+#define MPU9250_TC_OFFSET_BIT       6
+#define MPU9250_TC_OFFSET_LENGTH    6
+#define MPU9250_TC_OTP_BNK_VLD_BIT  0
+
+#define MPU9250_VDDIO_LEVEL_VLOGIC  0
+#define MPU9250_VDDIO_LEVEL_VDD     1
+
+#define MPU9250_CFG_EXT_SYNC_SET_BIT    5
+#define MPU9250_CFG_EXT_SYNC_SET_LENGTH 3
+#define MPU9250_CFG_DLPF_CFG_BIT    2
+#define MPU9250_CFG_DLPF_CFG_LENGTH 3
+
+#define MPU9250_EXT_SYNC_DISABLED       0x0
+#define MPU9250_EXT_SYNC_TEMP_OUT_L     0x1
+#define MPU9250_EXT_SYNC_GYRO_XOUT_L    0x2
+#define MPU9250_EXT_SYNC_GYRO_YOUT_L    0x3
+#define MPU9250_EXT_SYNC_GYRO_ZOUT_L    0x4
+#define MPU9250_EXT_SYNC_ACCEL_XOUT_L   0x5
+#define MPU9250_EXT_SYNC_ACCEL_YOUT_L   0x6
+#define MPU9250_EXT_SYNC_ACCEL_ZOUT_L   0x7
+
+#define MPU9250_DLPF_BW_256         0x00
+#define MPU9250_DLPF_BW_188         0x01
+#define MPU9250_DLPF_BW_98          0x02
+#define MPU9250_DLPF_BW_42          0x03
+#define MPU9250_DLPF_BW_20          0x04
+#define MPU9250_DLPF_BW_10          0x05
+#define MPU9250_DLPF_BW_5           0x06
+
+#define MPU9250_GCONFIG_FS_SEL_BIT      4
+#define MPU9250_GCONFIG_FS_SEL_LENGTH   2
+
+#define MPU9250_GYRO_FS_250         0x00
+#define MPU9250_GYRO_FS_500         0x01
+#define MPU9250_GYRO_FS_1000        0x02
+#define MPU9250_GYRO_FS_2000        0x03
+
+#define MPU9250_ACONFIG_XA_ST_BIT           7
+#define MPU9250_ACONFIG_YA_ST_BIT           6
+#define MPU9250_ACONFIG_ZA_ST_BIT           5
+#define MPU9250_ACONFIG_AFS_SEL_BIT         4
+#define MPU9250_ACONFIG_AFS_SEL_LENGTH      2
+#define MPU9250_ACONFIG_ACCEL_HPF_BIT       2
+#define MPU9250_ACONFIG_ACCEL_HPF_LENGTH    3
+
+#define MPU9250_ACCEL_FS_2          0x00
+#define MPU9250_ACCEL_FS_4          0x01
+#define MPU9250_ACCEL_FS_8          0x02
+#define MPU9250_ACCEL_FS_16         0x03
+
+#define MPU9250_DHPF_RESET          0x00
+#define MPU9250_DHPF_5              0x01
+#define MPU9250_DHPF_2P5            0x02
+#define MPU9250_DHPF_1P25           0x03
+#define MPU9250_DHPF_0P63           0x04
+#define MPU9250_DHPF_HOLD           0x07
+
+#define MPU9250_TEMP_FIFO_EN_BIT    7
+#define MPU9250_XG_FIFO_EN_BIT      6
+#define MPU9250_YG_FIFO_EN_BIT      5
+#define MPU9250_ZG_FIFO_EN_BIT      4
+#define MPU9250_ACCEL_FIFO_EN_BIT   3
+#define MPU9250_SLV2_FIFO_EN_BIT    2
+#define MPU9250_SLV1_FIFO_EN_BIT    1
+#define MPU9250_SLV0_FIFO_EN_BIT    0
+
+#define MPU9250_MULT_MST_EN_BIT     7
+#define MPU9250_WAIT_FOR_ES_BIT     6
+#define MPU9250_SLV_3_FIFO_EN_BIT   5
+#define MPU9250_I2C_MST_P_NSR_BIT   4
+#define MPU9250_I2C_MST_CLK_BIT     3
+#define MPU9250_I2C_MST_CLK_LENGTH  4
+
+#define MPU9250_CLOCK_DIV_348       0x0
+#define MPU9250_CLOCK_DIV_333       0x1
+#define MPU9250_CLOCK_DIV_320       0x2
+#define MPU9250_CLOCK_DIV_308       0x3
+#define MPU9250_CLOCK_DIV_296       0x4
+#define MPU9250_CLOCK_DIV_286       0x5
+#define MPU9250_CLOCK_DIV_276       0x6
+#define MPU9250_CLOCK_DIV_267       0x7
+#define MPU9250_CLOCK_DIV_258       0x8
+#define MPU9250_CLOCK_DIV_500       0x9
+#define MPU9250_CLOCK_DIV_471       0xA
+#define MPU9250_CLOCK_DIV_444       0xB
+#define MPU9250_CLOCK_DIV_421       0xC
+#define MPU9250_CLOCK_DIV_400       0xD
+#define MPU9250_CLOCK_DIV_381       0xE
+#define MPU9250_CLOCK_DIV_364       0xF
+
+#define MPU9250_I2C_SLV_RW_BIT      7
+#define MPU9250_I2C_SLV_ADDR_BIT    6
+#define MPU9250_I2C_SLV_ADDR_LENGTH 7
+#define MPU9250_I2C_SLV_EN_BIT      7
+#define MPU9250_I2C_SLV_BYTE_SW_BIT 6
+#define MPU9250_I2C_SLV_REG_DIS_BIT 5
+#define MPU9250_I2C_SLV_GRP_BIT     4
+#define MPU9250_I2C_SLV_LEN_BIT     3
+#define MPU9250_I2C_SLV_LEN_LENGTH  4
+
+#define MPU9250_I2C_SLV4_RW_BIT         7
+#define MPU9250_I2C_SLV4_ADDR_BIT       6
+#define MPU9250_I2C_SLV4_ADDR_LENGTH    7
+#define MPU9250_I2C_SLV4_EN_BIT         7
+#define MPU9250_I2C_SLV4_INT_EN_BIT     6
+#define MPU9250_I2C_SLV4_REG_DIS_BIT    5
+#define MPU9250_I2C_SLV4_MST_DLY_BIT    4
+#define MPU9250_I2C_SLV4_MST_DLY_LENGTH 5
+
+#define MPU9250_MST_PASS_THROUGH_BIT    7
+#define MPU9250_MST_I2C_SLV4_DONE_BIT   6
+#define MPU9250_MST_I2C_LOST_ARB_BIT    5
+#define MPU9250_MST_I2C_SLV4_NACK_BIT   4
+#define MPU9250_MST_I2C_SLV3_NACK_BIT   3
+#define MPU9250_MST_I2C_SLV2_NACK_BIT   2
+#define MPU9250_MST_I2C_SLV1_NACK_BIT   1
+#define MPU9250_MST_I2C_SLV0_NACK_BIT   0
+
+#define MPU9250_INTCFG_INT_LEVEL_BIT        7
+#define MPU9250_INTCFG_INT_OPEN_BIT         6
+#define MPU9250_INTCFG_LATCH_INT_EN_BIT     5
+#define MPU9250_INTCFG_INT_RD_CLEAR_BIT     4
+#define MPU9250_INTCFG_FSYNC_INT_LEVEL_BIT  3
+#define MPU9250_INTCFG_FSYNC_INT_EN_BIT     2
+#define MPU9250_INTCFG_I2C_BYPASS_EN_BIT    1
+#define MPU9250_INTCFG_CLKOUT_EN_BIT        0
+
+#define MPU9250_INTMODE_ACTIVEHIGH  0x00
+#define MPU9250_INTMODE_ACTIVELOW   0x01
+
+#define MPU9250_INTDRV_PUSHPULL     0x00
+#define MPU9250_INTDRV_OPENDRAIN    0x01
+
+#define MPU9250_INTLATCH_50USPULSE  0x00
+#define MPU9250_INTLATCH_WAITCLEAR  0x01
+
+#define MPU9250_INTCLEAR_STATUSREAD 0x00
+#define MPU9250_INTCLEAR_ANYREAD    0x01
+
+#define MPU9250_INTERRUPT_FF_BIT            7
+#define MPU9250_INTERRUPT_MOT_BIT           6
+#define MPU9250_INTERRUPT_ZMOT_BIT          5
+#define MPU9250_INTERRUPT_FIFO_OFLOW_BIT    4
+#define MPU9250_INTERRUPT_I2C_MST_INT_BIT   3
+#define MPU9250_INTERRUPT_PLL_RDY_INT_BIT   2
+#define MPU9250_INTERRUPT_DMP_INT_BIT       1
+#define MPU9250_INTERRUPT_DATA_RDY_BIT      0
+
+// TODO: figure out what these actually do
+// UMPL source code is not very obivous
+#define MPU9250_DMPINT_5_BIT            5
+#define MPU9250_DMPINT_4_BIT            4
+#define MPU9250_DMPINT_3_BIT            3
+#define MPU9250_DMPINT_2_BIT            2
+#define MPU9250_DMPINT_1_BIT            1
+#define MPU9250_DMPINT_0_BIT            0
+
+#define MPU9250_MOTION_MOT_XNEG_BIT     7
+#define MPU9250_MOTION_MOT_XPOS_BIT     6
+#define MPU9250_MOTION_MOT_YNEG_BIT     5
+#define MPU9250_MOTION_MOT_YPOS_BIT     4
+#define MPU9250_MOTION_MOT_ZNEG_BIT     3
+#define MPU9250_MOTION_MOT_ZPOS_BIT     2
+#define MPU9250_MOTION_MOT_ZRMOT_BIT    0
+
+#define MPU9250_DELAYCTRL_DELAY_ES_SHADOW_BIT   7
+#define MPU9250_DELAYCTRL_I2C_SLV4_DLY_EN_BIT   4
+#define MPU9250_DELAYCTRL_I2C_SLV3_DLY_EN_BIT   3
+#define MPU9250_DELAYCTRL_I2C_SLV2_DLY_EN_BIT   2
+#define MPU9250_DELAYCTRL_I2C_SLV1_DLY_EN_BIT   1
+#define MPU9250_DELAYCTRL_I2C_SLV0_DLY_EN_BIT   0
+
+#define MPU9250_PATHRESET_GYRO_RESET_BIT    2
+#define MPU9250_PATHRESET_ACCEL_RESET_BIT   1
+#define MPU9250_PATHRESET_TEMP_RESET_BIT    0
+
+#define MPU9250_DETECT_ACCEL_ON_DELAY_BIT       5
+#define MPU9250_DETECT_ACCEL_ON_DELAY_LENGTH    2
+#define MPU9250_DETECT_FF_COUNT_BIT             3
+#define MPU9250_DETECT_FF_COUNT_LENGTH          2
+#define MPU9250_DETECT_MOT_COUNT_BIT            1
+#define MPU9250_DETECT_MOT_COUNT_LENGTH         2
+
+#define MPU9250_DETECT_DECREMENT_RESET  0x0
+#define MPU9250_DETECT_DECREMENT_1      0x1
+#define MPU9250_DETECT_DECREMENT_2      0x2
+#define MPU9250_DETECT_DECREMENT_4      0x3
+
+#define MPU9250_USERCTRL_DMP_EN_BIT             7
+#define MPU9250_USERCTRL_FIFO_EN_BIT            6
+#define MPU9250_USERCTRL_I2C_MST_EN_BIT         5
+#define MPU9250_USERCTRL_I2C_IF_DIS_BIT         4
+#define MPU9250_USERCTRL_DMP_RESET_BIT          3
+#define MPU9250_USERCTRL_FIFO_RESET_BIT         2
+#define MPU9250_USERCTRL_I2C_MST_RESET_BIT      1
+#define MPU9250_USERCTRL_SIG_COND_RESET_BIT     0
+
+#define MPU9250_PWR1_DEVICE_RESET_BIT   7
+#define MPU9250_PWR1_SLEEP_BIT          6
+#define MPU9250_PWR1_CYCLE_BIT          5
+#define MPU9250_PWR1_TEMP_DIS_BIT       3
+#define MPU9250_PWR1_CLKSEL_BIT         2
+#define MPU9250_PWR1_CLKSEL_LENGTH      3
+
+#define MPU9250_CLOCK_INTERNAL          0x00
+#define MPU9250_CLOCK_PLL_XGYRO         0x01
+#define MPU9250_CLOCK_PLL_YGYRO         0x02
+#define MPU9250_CLOCK_PLL_ZGYRO         0x03
+#define MPU9250_CLOCK_PLL_EXT32K        0x04
+#define MPU9250_CLOCK_PLL_EXT19M        0x05
+#define MPU9250_CLOCK_KEEP_RESET        0x07
+
+#define MPU9250_PWR2_LP_WAKE_CTRL_BIT       7
+#define MPU9250_PWR2_LP_WAKE_CTRL_LENGTH    2
+#define MPU9250_PWR2_STBY_XA_BIT            5
+#define MPU9250_PWR2_STBY_YA_BIT            4
+#define MPU9250_PWR2_STBY_ZA_BIT            3
+#define MPU9250_PWR2_STBY_XG_BIT            2
+#define MPU9250_PWR2_STBY_YG_BIT            1
+#define MPU9250_PWR2_STBY_ZG_BIT            0
+
+#define MPU9250_WAKE_FREQ_1P25      0x0
+#define MPU9250_WAKE_FREQ_2P5       0x1
+#define MPU9250_WAKE_FREQ_5         0x2
+#define MPU9250_WAKE_FREQ_10        0x3
+
+#define MPU9250_BANKSEL_PRFTCH_EN_BIT       6
+#define MPU9250_BANKSEL_CFG_USER_BANK_BIT   5
+#define MPU9250_BANKSEL_MEM_SEL_BIT         4
+#define MPU9250_BANKSEL_MEM_SEL_LENGTH      5
+
+#define MPU9250_WHO_AM_I_BIT        8
+#define MPU9250_WHO_AM_I_LENGTH     8
+
+#define MPU9250_DMP_MEMORY_BANKS        8
+#define MPU9250_DMP_MEMORY_BANK_SIZE    256
+#define MPU9250_DMP_MEMORY_CHUNK_SIZE   16
+
+// note: DMP code memory blocks defined at end of header file
+
+class MPU9250 {
+    public:
+        MPU9250();
+        MPU9250(uint8_t address);
+
+        void initialize();
+        bool testConnection();
+
+        // AUX_VDDIO register
+        uint8_t getAuxVDDIOLevel();
+        void setAuxVDDIOLevel(uint8_t level);
+
+        // SMPLRT_DIV register
+        uint8_t getRate();
+        void setRate(uint8_t rate);
+
+        // CONFIG register
+        uint8_t getExternalFrameSync();
+        void setExternalFrameSync(uint8_t sync);
+        uint8_t getDLPFMode();
+        void setDLPFMode(uint8_t bandwidth);
+
+        // GYRO_CONFIG register
+        uint8_t getFullScaleGyroRange();
+        void setFullScaleGyroRange(uint8_t range);
+
+        // ACCEL_CONFIG register
+        bool getAccelXSelfTest();
+        void setAccelXSelfTest(bool enabled);
+        bool getAccelYSelfTest();
+        void setAccelYSelfTest(bool enabled);
+        bool getAccelZSelfTest();
+        void setAccelZSelfTest(bool enabled);
+        uint8_t getFullScaleAccelRange();
+        void setFullScaleAccelRange(uint8_t range);
+        uint8_t getDHPFMode();
+        void setDHPFMode(uint8_t mode);
+
+        // FF_THR register
+        uint8_t getFreefallDetectionThreshold();
+        void setFreefallDetectionThreshold(uint8_t threshold);
+
+        // FF_DUR register
+        uint8_t getFreefallDetectionDuration();
+        void setFreefallDetectionDuration(uint8_t duration);
+
+        // MOT_THR register
+        uint8_t getMotionDetectionThreshold();
+        void setMotionDetectionThreshold(uint8_t threshold);
+
+        // MOT_DUR register
+        uint8_t getMotionDetectionDuration();
+        void setMotionDetectionDuration(uint8_t duration);
+
+        // ZRMOT_THR register
+        uint8_t getZeroMotionDetectionThreshold();
+        void setZeroMotionDetectionThreshold(uint8_t threshold);
+
+        // ZRMOT_DUR register
+        uint8_t getZeroMotionDetectionDuration();
+        void setZeroMotionDetectionDuration(uint8_t duration);
+
+        // FIFO_EN register
+        bool getTempFIFOEnabled();
+        void setTempFIFOEnabled(bool enabled);
+        bool getXGyroFIFOEnabled();
+        void setXGyroFIFOEnabled(bool enabled);
+        bool getYGyroFIFOEnabled();
+        void setYGyroFIFOEnabled(bool enabled);
+        bool getZGyroFIFOEnabled();
+        void setZGyroFIFOEnabled(bool enabled);
+        bool getAccelFIFOEnabled();
+        void setAccelFIFOEnabled(bool enabled);
+        bool getSlave2FIFOEnabled();
+        void setSlave2FIFOEnabled(bool enabled);
+        bool getSlave1FIFOEnabled();
+        void setSlave1FIFOEnabled(bool enabled);
+        bool getSlave0FIFOEnabled();
+        void setSlave0FIFOEnabled(bool enabled);
+
+        // I2C_MST_CTRL register
+        bool getMultiMasterEnabled();
+        void setMultiMasterEnabled(bool enabled);
+        bool getWaitForExternalSensorEnabled();
+        void setWaitForExternalSensorEnabled(bool enabled);
+        bool getSlave3FIFOEnabled();
+        void setSlave3FIFOEnabled(bool enabled);
+        bool getSlaveReadWriteTransitionEnabled();
+        void setSlaveReadWriteTransitionEnabled(bool enabled);
+        uint8_t getMasterClockSpeed();
+        void setMasterClockSpeed(uint8_t speed);
+
+        // I2C_SLV* registers (Slave 0-3)
+        uint8_t getSlaveAddress(uint8_t num);
+        void setSlaveAddress(uint8_t num, uint8_t address);
+        uint8_t getSlaveRegister(uint8_t num);
+        void setSlaveRegister(uint8_t num, uint8_t reg);
+        bool getSlaveEnabled(uint8_t num);
+        void setSlaveEnabled(uint8_t num, bool enabled);
+        bool getSlaveWordByteSwap(uint8_t num);
+        void setSlaveWordByteSwap(uint8_t num, bool enabled);
+        bool getSlaveWriteMode(uint8_t num);
+        void setSlaveWriteMode(uint8_t num, bool mode);
+        bool getSlaveWordGroupOffset(uint8_t num);
+        void setSlaveWordGroupOffset(uint8_t num, bool enabled);
+        uint8_t getSlaveDataLength(uint8_t num);
+        void setSlaveDataLength(uint8_t num, uint8_t length);
+
+        // I2C_SLV* registers (Slave 4)
+        uint8_t getSlave4Address();
+        void setSlave4Address(uint8_t address);
+        uint8_t getSlave4Register();
+        void setSlave4Register(uint8_t reg);
+        void setSlave4OutputByte(uint8_t data);
+        bool getSlave4Enabled();
+        void setSlave4Enabled(bool enabled);
+        bool getSlave4InterruptEnabled();
+        void setSlave4InterruptEnabled(bool enabled);
+        bool getSlave4WriteMode();
+        void setSlave4WriteMode(bool mode);
+        uint8_t getSlave4MasterDelay();
+        void setSlave4MasterDelay(uint8_t delay);
+        uint8_t getSlate4InputByte();
+
+        // I2C_MST_STATUS register
+        bool getPassthroughStatus();
+        bool getSlave4IsDone();
+        bool getLostArbitration();
+        bool getSlave4Nack();
+        bool getSlave3Nack();
+        bool getSlave2Nack();
+        bool getSlave1Nack();
+        bool getSlave0Nack();
+
+        // INT_PIN_CFG register
+        bool getInterruptMode();
+        void setInterruptMode(bool mode);
+        bool getInterruptDrive();
+        void setInterruptDrive(bool drive);
+        bool getInterruptLatch();
+        void setInterruptLatch(bool latch);
+        bool getInterruptLatchClear();
+        void setInterruptLatchClear(bool clear);
+        bool getFSyncInterruptLevel();
+        void setFSyncInterruptLevel(bool level);
+        bool getFSyncInterruptEnabled();
+        void setFSyncInterruptEnabled(bool enabled);
+        bool getI2CBypassEnabled();
+        void setI2CBypassEnabled(bool enabled);
+        bool getClockOutputEnabled();
+        void setClockOutputEnabled(bool enabled);
+
+        // INT_ENABLE register
+        uint8_t getIntEnabled();
+        void setIntEnabled(uint8_t enabled);
+        bool getIntFreefallEnabled();
+        void setIntFreefallEnabled(bool enabled);
+        bool getIntMotionEnabled();
+        void setIntMotionEnabled(bool enabled);
+        bool getIntZeroMotionEnabled();
+        void setIntZeroMotionEnabled(bool enabled);
+        bool getIntFIFOBufferOverflowEnabled();
+        void setIntFIFOBufferOverflowEnabled(bool enabled);
+        bool getIntI2CMasterEnabled();
+        void setIntI2CMasterEnabled(bool enabled);
+        bool getIntDataReadyEnabled();
+        void setIntDataReadyEnabled(bool enabled);
+
+        // INT_STATUS register
+        uint8_t getIntStatus();
+        bool getIntFreefallStatus();
+        bool getIntMotionStatus();
+        bool getIntZeroMotionStatus();
+        bool getIntFIFOBufferOverflowStatus();
+        bool getIntI2CMasterStatus();
+        bool getIntDataReadyStatus();
+
+        // ACCEL_*OUT_* registers
+        void getMotion9(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz, int16_t* mx, int16_t* my, int16_t* mz);
+        void getMotion6(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz);
+        void getAcceleration(int16_t* x, int16_t* y, int16_t* z);
+        int16_t getAccelerationX();
+        int16_t getAccelerationY();
+        int16_t getAccelerationZ();
+
+        // TEMP_OUT_* registers
+        int16_t getTemperature();
+
+        // GYRO_*OUT_* registers
+        void getRotation(int16_t* x, int16_t* y, int16_t* z);
+        int16_t getRotationX();
+        int16_t getRotationY();
+        int16_t getRotationZ();
+
+        // EXT_SENS_DATA_* registers
+        uint8_t getExternalSensorByte(int position);
+        uint16_t getExternalSensorWord(int position);
+        uint32_t getExternalSensorDWord(int position);
+
+        // MOT_DETECT_STATUS register
+        bool getXNegMotionDetected();
+        bool getXPosMotionDetected();
+        bool getYNegMotionDetected();
+        bool getYPosMotionDetected();
+        bool getZNegMotionDetected();
+        bool getZPosMotionDetected();
+        bool getZeroMotionDetected();
+
+        // I2C_SLV*_DO register
+        void setSlaveOutputByte(uint8_t num, uint8_t data);
+
+        // I2C_MST_DELAY_CTRL register
+        bool getExternalShadowDelayEnabled();
+        void setExternalShadowDelayEnabled(bool enabled);
+        bool getSlaveDelayEnabled(uint8_t num);
+        void setSlaveDelayEnabled(uint8_t num, bool enabled);
+
+        // SIGNAL_PATH_RESET register
+        void resetGyroscopePath();
+        void resetAccelerometerPath();
+        void resetTemperaturePath();
+
+        // MOT_DETECT_CTRL register
+        uint8_t getAccelerometerPowerOnDelay();
+        void setAccelerometerPowerOnDelay(uint8_t delay);
+        uint8_t getFreefallDetectionCounterDecrement();
+        void setFreefallDetectionCounterDecrement(uint8_t decrement);
+        uint8_t getMotionDetectionCounterDecrement();
+        void setMotionDetectionCounterDecrement(uint8_t decrement);
+
+        // USER_CTRL register
+        bool getFIFOEnabled();
+        void setFIFOEnabled(bool enabled);
+        bool getI2CMasterModeEnabled();
+        void setI2CMasterModeEnabled(bool enabled);
+        void switchSPIEnabled(bool enabled);
+        void resetFIFO();
+        void resetI2CMaster();
+        void resetSensors();
+
+        // PWR_MGMT_1 register
+        void reset();
+        bool getSleepEnabled();
+        void setSleepEnabled(bool enabled);
+        bool getWakeCycleEnabled();
+        void setWakeCycleEnabled(bool enabled);
+        bool getTempSensorEnabled();
+        void setTempSensorEnabled(bool enabled);
+        uint8_t getClockSource();
+        void setClockSource(uint8_t source);
+
+        // PWR_MGMT_2 register
+        uint8_t getWakeFrequency();
+        void setWakeFrequency(uint8_t frequency);
+        bool getStandbyXAccelEnabled();
+        void setStandbyXAccelEnabled(bool enabled);
+        bool getStandbyYAccelEnabled();
+        void setStandbyYAccelEnabled(bool enabled);
+        bool getStandbyZAccelEnabled();
+        void setStandbyZAccelEnabled(bool enabled);
+        bool getStandbyXGyroEnabled();
+        void setStandbyXGyroEnabled(bool enabled);
+        bool getStandbyYGyroEnabled();
+        void setStandbyYGyroEnabled(bool enabled);
+        bool getStandbyZGyroEnabled();
+        void setStandbyZGyroEnabled(bool enabled);
+
+        // FIFO_COUNT_* registers
+        uint16_t getFIFOCount();
+
+        // FIFO_R_W register
+        uint8_t getFIFOByte();
+        void setFIFOByte(uint8_t data);
+        void getFIFOBytes(uint8_t *data, uint8_t length);
+
+        // WHO_AM_I register
+        uint8_t getDeviceID();
+        void setDeviceID(uint8_t id);
+        
+        // ======== UNDOCUMENTED/DMP REGISTERS/METHODS ========
+        
+        // XG_OFFS_TC register
+        uint8_t getOTPBankValid();
+        void setOTPBankValid(bool enabled);
+        int8_t getXGyroOffset();
+        void setXGyroOffset(int8_t offset);
+
+        // YG_OFFS_TC register
+        int8_t getYGyroOffset();
+        void setYGyroOffset(int8_t offset);
+
+        // ZG_OFFS_TC register
+        int8_t getZGyroOffset();
+        void setZGyroOffset(int8_t offset);
+
+        // X_FINE_GAIN register
+        int8_t getXFineGain();
+        void setXFineGain(int8_t gain);
+
+        // Y_FINE_GAIN register
+        int8_t getYFineGain();
+        void setYFineGain(int8_t gain);
+
+        // Z_FINE_GAIN register
+        int8_t getZFineGain();
+        void setZFineGain(int8_t gain);
+
+        // XA_OFFS_* registers
+        int16_t getXAccelOffset();
+        void setXAccelOffset(int16_t offset);
+
+        // YA_OFFS_* register
+        int16_t getYAccelOffset();
+        void setYAccelOffset(int16_t offset);
+
+        // ZA_OFFS_* register
+        int16_t getZAccelOffset();
+        void setZAccelOffset(int16_t offset);
+
+        // XG_OFFS_USR* registers
+        int16_t getXGyroOffsetUser();
+        void setXGyroOffsetUser(int16_t offset);
+
+        // YG_OFFS_USR* register
+        int16_t getYGyroOffsetUser();
+        void setYGyroOffsetUser(int16_t offset);
+
+        // ZG_OFFS_USR* register
+        int16_t getZGyroOffsetUser();
+        void setZGyroOffsetUser(int16_t offset);
+        
+        // INT_ENABLE register (DMP functions)
+        bool getIntPLLReadyEnabled();
+        void setIntPLLReadyEnabled(bool enabled);
+        bool getIntDMPEnabled();
+        void setIntDMPEnabled(bool enabled);
+        
+        // DMP_INT_STATUS
+        bool getDMPInt5Status();
+        bool getDMPInt4Status();
+        bool getDMPInt3Status();
+        bool getDMPInt2Status();
+        bool getDMPInt1Status();
+        bool getDMPInt0Status();
+
+        // INT_STATUS register (DMP functions)
+        bool getIntPLLReadyStatus();
+        bool getIntDMPStatus();
+        
+        // USER_CTRL register (DMP functions)
+        bool getDMPEnabled();
+        void setDMPEnabled(bool enabled);
+        void resetDMP();
+        
+        // BANK_SEL register
+        void setMemoryBank(uint8_t bank, bool prefetchEnabled=false, bool userBank=false);
+        
+        // MEM_START_ADDR register
+        void setMemoryStartAddress(uint8_t address);
+        
+        // MEM_R_W register
+        uint8_t readMemoryByte();
+        void writeMemoryByte(uint8_t data);
+        void readMemoryBlock(uint8_t *data, uint16_t dataSize, uint8_t bank=0, uint8_t address=0);
+        bool writeMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank=0, uint8_t address=0, bool verify=true, bool useProgMem=false);
+        bool writeProgMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank=0, uint8_t address=0, bool verify=true);
+
+        bool writeDMPConfigurationSet(const uint8_t *data, uint16_t dataSize, bool useProgMem=false);
+        bool writeProgDMPConfigurationSet(const uint8_t *data, uint16_t dataSize);
+
+        // DMP_CFG_1 register
+        uint8_t getDMPConfig1();
+        void setDMPConfig1(uint8_t config);
+
+        // DMP_CFG_2 register
+        uint8_t getDMPConfig2();
+        void setDMPConfig2(uint8_t config);
+
+        // special methods for MotionApps 2.0 implementation
+        #ifdef MPU9250_INCLUDE_DMP_MOTIONAPPS20
+            uint8_t *dmpPacketBuffer;
+            uint16_t dmpPacketSize;
+
+            uint8_t dmpInitialize();
+            bool dmpPacketAvailable();
+
+            uint8_t dmpSetFIFORate(uint8_t fifoRate);
+            uint8_t dmpGetFIFORate();
+            uint8_t dmpGetSampleStepSizeMS();
+            uint8_t dmpGetSampleFrequency();
+            int32_t dmpDecodeTemperature(int8_t tempReg);
+            
+            // Register callbacks after a packet of FIFO data is processed
+            //uint8_t dmpRegisterFIFORateProcess(inv_obj_func func, int16_t priority);
+            //uint8_t dmpUnregisterFIFORateProcess(inv_obj_func func);
+            uint8_t dmpRunFIFORateProcesses();
+            
+            // Setup FIFO for various output
+            uint8_t dmpSendQuaternion(uint_fast16_t accuracy);
+            uint8_t dmpSendGyro(uint_fast16_t elements, uint_fast16_t accuracy);
+            uint8_t dmpSendAccel(uint_fast16_t elements, uint_fast16_t accuracy);
+            uint8_t dmpSendLinearAccel(uint_fast16_t elements, uint_fast16_t accuracy);
+            uint8_t dmpSendLinearAccelInWorld(uint_fast16_t elements, uint_fast16_t accuracy);
+            uint8_t dmpSendControlData(uint_fast16_t elements, uint_fast16_t accuracy);
+            uint8_t dmpSendSensorData(uint_fast16_t elements, uint_fast16_t accuracy);
+            uint8_t dmpSendExternalSensorData(uint_fast16_t elements, uint_fast16_t accuracy);
+            uint8_t dmpSendGravity(uint_fast16_t elements, uint_fast16_t accuracy);
+            uint8_t dmpSendPacketNumber(uint_fast16_t accuracy);
+            uint8_t dmpSendQuantizedAccel(uint_fast16_t elements, uint_fast16_t accuracy);
+            uint8_t dmpSendEIS(uint_fast16_t elements, uint_fast16_t accuracy);
+
+            // Get Fixed Point data from FIFO
+            uint8_t dmpGetAccel(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetAccel(int16_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetAccel(VectorInt16 *v, const uint8_t* packet=0);
+            uint8_t dmpGetQuaternion(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetQuaternion(int16_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetQuaternion(Quaternion *q, const uint8_t* packet=0);
+            uint8_t dmpGet6AxisQuaternion(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGet6AxisQuaternion(int16_t *data, const uint8_t* packet=0);
+            uint8_t dmpGet6AxisQuaternion(Quaternion *q, const uint8_t* packet=0);
+            uint8_t dmpGetRelativeQuaternion(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetRelativeQuaternion(int16_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetRelativeQuaternion(Quaternion *data, const uint8_t* packet=0);
+            uint8_t dmpGetGyro(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetGyro(int16_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetGyro(VectorInt16 *v, const uint8_t* packet=0);
+            uint8_t dmpSetLinearAccelFilterCoefficient(float coef);
+            uint8_t dmpGetLinearAccel(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetLinearAccel(int16_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetLinearAccel(VectorInt16 *v, const uint8_t* packet=0);
+            uint8_t dmpGetLinearAccel(VectorInt16 *v, VectorInt16 *vRaw, VectorFloat *gravity);
+            uint8_t dmpGetLinearAccelInWorld(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetLinearAccelInWorld(int16_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetLinearAccelInWorld(VectorInt16 *v, const uint8_t* packet=0);
+            uint8_t dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Quaternion *q);
+            uint8_t dmpGetGyroAndAccelSensor(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetGyroAndAccelSensor(int16_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetGyroAndAccelSensor(VectorInt16 *g, VectorInt16 *a, const uint8_t* packet=0);
+            uint8_t dmpGetGyroSensor(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetGyroSensor(int16_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetGyroSensor(VectorInt16 *v, const uint8_t* packet=0);
+            uint8_t dmpGetControlData(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetTemperature(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetGravity(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetGravity(int16_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetGravity(VectorInt16 *v, const uint8_t* packet=0);
+            uint8_t dmpGetGravity(VectorFloat *v, Quaternion *q);
+            uint8_t dmpGetUnquantizedAccel(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetUnquantizedAccel(int16_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetUnquantizedAccel(VectorInt16 *v, const uint8_t* packet=0);
+            uint8_t dmpGetQuantizedAccel(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetQuantizedAccel(int16_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetQuantizedAccel(VectorInt16 *v, const uint8_t* packet=0);
+            uint8_t dmpGetExternalSensorData(int32_t *data, uint16_t size, const uint8_t* packet=0);
+            uint8_t dmpGetEIS(int32_t *data, const uint8_t* packet=0);
+            
+            uint8_t dmpGetEuler(float *data, Quaternion *q);
+            uint8_t dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity);
+
+            // Get Floating Point data from FIFO
+            uint8_t dmpGetAccelFloat(float *data, const uint8_t* packet=0);
+            uint8_t dmpGetQuaternionFloat(float *data, const uint8_t* packet=0);
+
+            uint8_t dmpProcessFIFOPacket(const unsigned char *dmpData);
+            uint8_t dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *processed=NULL);
+
+            uint8_t dmpSetFIFOProcessedCallback(void (*func) (void));
+
+            uint8_t dmpInitFIFOParam();
+            uint8_t dmpCloseFIFO();
+            uint8_t dmpSetGyroDataSource(uint8_t source);
+            uint8_t dmpDecodeQuantizedAccel();
+            uint32_t dmpGetGyroSumOfSquare();
+            uint32_t dmpGetAccelSumOfSquare();
+            void dmpOverrideQuaternion(long *q);
+            uint16_t dmpGetFIFOPacketSize();
+        #endif
+
+        // special methods for MotionApps 4.1 implementation
+        #ifdef MPU9250_INCLUDE_DMP_MOTIONAPPS41
+            uint8_t *dmpPacketBuffer;
+            uint16_t dmpPacketSize;
+
+            uint8_t dmpInitialize();
+            bool dmpPacketAvailable();
+
+            uint8_t dmpSetFIFORate(uint8_t fifoRate);
+            uint8_t dmpGetFIFORate();
+            uint8_t dmpGetSampleStepSizeMS();
+            uint8_t dmpGetSampleFrequency();
+            int32_t dmpDecodeTemperature(int8_t tempReg);
+            
+            // Register callbacks after a packet of FIFO data is processed
+            //uint8_t dmpRegisterFIFORateProcess(inv_obj_func func, int16_t priority);
+            //uint8_t dmpUnregisterFIFORateProcess(inv_obj_func func);
+            uint8_t dmpRunFIFORateProcesses();
+            
+            // Setup FIFO for various output
+            uint8_t dmpSendQuaternion(uint_fast16_t accuracy);
+            uint8_t dmpSendGyro(uint_fast16_t elements, uint_fast16_t accuracy);
+            uint8_t dmpSendAccel(uint_fast16_t elements, uint_fast16_t accuracy);
+            uint8_t dmpSendLinearAccel(uint_fast16_t elements, uint_fast16_t accuracy);
+            uint8_t dmpSendLinearAccelInWorld(uint_fast16_t elements, uint_fast16_t accuracy);
+            uint8_t dmpSendControlData(uint_fast16_t elements, uint_fast16_t accuracy);
+            uint8_t dmpSendSensorData(uint_fast16_t elements, uint_fast16_t accuracy);
+            uint8_t dmpSendExternalSensorData(uint_fast16_t elements, uint_fast16_t accuracy);
+            uint8_t dmpSendGravity(uint_fast16_t elements, uint_fast16_t accuracy);
+            uint8_t dmpSendPacketNumber(uint_fast16_t accuracy);
+            uint8_t dmpSendQuantizedAccel(uint_fast16_t elements, uint_fast16_t accuracy);
+            uint8_t dmpSendEIS(uint_fast16_t elements, uint_fast16_t accuracy);
+
+            // Get Fixed Point data from FIFO
+            uint8_t dmpGetAccel(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetAccel(int16_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetAccel(VectorInt16 *v, const uint8_t* packet=0);
+            uint8_t dmpGetQuaternion(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetQuaternion(int16_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetQuaternion(Quaternion *q, const uint8_t* packet=0);
+            uint8_t dmpGet6AxisQuaternion(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGet6AxisQuaternion(int16_t *data, const uint8_t* packet=0);
+            uint8_t dmpGet6AxisQuaternion(Quaternion *q, const uint8_t* packet=0);
+            uint8_t dmpGetRelativeQuaternion(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetRelativeQuaternion(int16_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetRelativeQuaternion(Quaternion *data, const uint8_t* packet=0);
+            uint8_t dmpGetGyro(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetGyro(int16_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetGyro(VectorInt16 *v, const uint8_t* packet=0);
+            uint8_t dmpGetMag(int16_t *data, const uint8_t* packet=0);
+            uint8_t dmpSetLinearAccelFilterCoefficient(float coef);
+            uint8_t dmpGetLinearAccel(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetLinearAccel(int16_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetLinearAccel(VectorInt16 *v, const uint8_t* packet=0);
+            uint8_t dmpGetLinearAccel(VectorInt16 *v, VectorInt16 *vRaw, VectorFloat *gravity);
+            uint8_t dmpGetLinearAccelInWorld(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetLinearAccelInWorld(int16_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetLinearAccelInWorld(VectorInt16 *v, const uint8_t* packet=0);
+            uint8_t dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Quaternion *q);
+            uint8_t dmpGetGyroAndAccelSensor(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetGyroAndAccelSensor(int16_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetGyroAndAccelSensor(VectorInt16 *g, VectorInt16 *a, const uint8_t* packet=0);
+            uint8_t dmpGetGyroSensor(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetGyroSensor(int16_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetGyroSensor(VectorInt16 *v, const uint8_t* packet=0);
+            uint8_t dmpGetControlData(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetTemperature(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetGravity(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetGravity(int16_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetGravity(VectorInt16 *v, const uint8_t* packet=0);
+            uint8_t dmpGetGravity(VectorFloat *v, Quaternion *q);
+            uint8_t dmpGetUnquantizedAccel(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetUnquantizedAccel(int16_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetUnquantizedAccel(VectorInt16 *v, const uint8_t* packet=0);
+            uint8_t dmpGetQuantizedAccel(int32_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetQuantizedAccel(int16_t *data, const uint8_t* packet=0);
+            uint8_t dmpGetQuantizedAccel(VectorInt16 *v, const uint8_t* packet=0);
+            uint8_t dmpGetExternalSensorData(int32_t *data, uint16_t size, const uint8_t* packet=0);
+            uint8_t dmpGetEIS(int32_t *data, const uint8_t* packet=0);
+            
+            uint8_t dmpGetEuler(float *data, Quaternion *q);
+            uint8_t dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity);
+
+            // Get Floating Point data from FIFO
+            uint8_t dmpGetAccelFloat(float *data, const uint8_t* packet=0);
+            uint8_t dmpGetQuaternionFloat(float *data, const uint8_t* packet=0);
+
+            uint8_t dmpProcessFIFOPacket(const unsigned char *dmpData);
+            uint8_t dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *processed=NULL);
+
+            uint8_t dmpSetFIFOProcessedCallback(void (*func) (void));
+
+            uint8_t dmpInitFIFOParam();
+            uint8_t dmpCloseFIFO();
+            uint8_t dmpSetGyroDataSource(uint8_t source);
+            uint8_t dmpDecodeQuantizedAccel();
+            uint32_t dmpGetGyroSumOfSquare();
+            uint32_t dmpGetAccelSumOfSquare();
+            void dmpOverrideQuaternion(long *q);
+            uint16_t dmpGetFIFOPacketSize();
+        #endif
+
+    private:
+        uint8_t devAddr;
+        uint8_t buffer[14];
+};
+
+#endif /* _MPU9250_H_ */
diff --git a/Arduino/MPU9250/README.md b/Arduino/MPU9250/README.md
new file mode 100644
index 00000000..982802b5
--- /dev/null
+++ b/Arduino/MPU9250/README.md
@@ -0,0 +1,23 @@
+# IMU_10DOF
+
+This library is for Grove - IMU 10DOF and Xadow - IMU 10DOF modules. All the mentioned modules are combination of MPU-9250 and BMP180. So this library is the combination of:
+
+* Library for MPU9250 - thanks to Jeff Rowberg , the MIT license
+* Library for BMP180 - thanks to LG, LGPL license
+
+
+----
+
+Contributing to this software is warmly welcomed. You can do this basically by
+[forking](https://help.github.com/articles/fork-a-repo), committing modifications and then [pulling requests](https://help.github.com/articles/using-pull-requests) (follow the links above
+for operating guide). Adding change log and your contact into file header is encouraged.
+Thanks for your contribution. + +Seeed Studio is an open hardware facilitation company based in Shenzhen, China.
+Benefiting from local manufacture power and convenient global logistic system,
+we integrate resources to serve new era of innovation. Seeed also works with
+global distributors and partners to push open hardware movement.
+ + + +[![Analytics](https://ga-beacon.appspot.com/UA-46589105-3/IMU_10DOF)](https://github.com/igrigorik/ga-beacon) \ No newline at end of file diff --git a/Arduino/MPU9250/examples/IMU_10DOF_Test/IMU_10DOF_Test.ino b/Arduino/MPU9250/examples/IMU_10DOF_Test/IMU_10DOF_Test.ino new file mode 100644 index 00000000..614ee4cf --- /dev/null +++ b/Arduino/MPU9250/examples/IMU_10DOF_Test/IMU_10DOF_Test.ino @@ -0,0 +1,291 @@ +#include "Wire.h" + +// I2Cdev and MPU9250 must be installed as libraries, or else the .cpp/.h files +// for both classes must be in the include path of your project +#include "I2Cdev.h" +#include "MPU9250.h" +#include "BMP180.h" + +// class default I2C address is 0x68 +// specific I2C addresses may be passed as a parameter here +// AD0 low = 0x68 (default for InvenSense evaluation board) +// AD0 high = 0x69 +MPU9250 accelgyro; +I2Cdev I2C_M; + +uint8_t buffer_m[6]; + + +int16_t ax, ay, az; +int16_t gx, gy, gz; +int16_t mx, my, mz; + + + +float heading; +float tiltheading; + +float Axyz[3]; +float Gxyz[3]; +float Mxyz[3]; + + +#define sample_num_mdate 5000 + +volatile float mx_sample[3]; +volatile float my_sample[3]; +volatile float mz_sample[3]; + +static float mx_centre = 0; +static float my_centre = 0; +static float mz_centre = 0; + +volatile int mx_max = 0; +volatile int my_max = 0; +volatile int mz_max = 0; + +volatile int mx_min = 0; +volatile int my_min = 0; +volatile int mz_min = 0; + +float temperature; +float pressure; +float atm; +float altitude; +BMP180 Barometer; + +void setup() +{ + // join I2C bus (I2Cdev library doesn't do this automatically) + Wire.begin(); + + // initialize serial communication + // (38400 chosen because it works as well at 8MHz as it does at 16MHz, but + // it's really up to you depending on your project) + Serial.begin(38400); + + // initialize device + Serial.println("Initializing I2C devices..."); + accelgyro.initialize(); + Barometer.init(); + + // verify connection + Serial.println("Testing device connections..."); + Serial.println(accelgyro.testConnection() ? "MPU9250 connection successful" : "MPU9250 connection failed"); + + delay(1000); + Serial.println(" "); + + // Mxyz_init_calibrated (); + +} + +void loop() +{ + + getAccel_Data(); + getGyro_Data(); + getCompassDate_calibrated(); // compass data has been calibrated here + getHeading(); //before we use this function we should run 'getCompassDate_calibrated()' frist, so that we can get calibrated data ,then we can get correct angle . + getTiltHeading(); + + Serial.println("calibration parameter: "); + Serial.print(mx_centre); + Serial.print(" "); + Serial.print(my_centre); + Serial.print(" "); + Serial.println(mz_centre); + Serial.println(" "); + + + Serial.println("Acceleration(g) of X,Y,Z:"); + Serial.print(Axyz[0]); + Serial.print(","); + Serial.print(Axyz[1]); + Serial.print(","); + Serial.println(Axyz[2]); + Serial.println("Gyro(degress/s) of X,Y,Z:"); + Serial.print(Gxyz[0]); + Serial.print(","); + Serial.print(Gxyz[1]); + Serial.print(","); + Serial.println(Gxyz[2]); + Serial.println("Compass Value of X,Y,Z:"); + Serial.print(Mxyz[0]); + Serial.print(","); + Serial.print(Mxyz[1]); + Serial.print(","); + Serial.println(Mxyz[2]); + Serial.println("The clockwise angle between the magnetic north and X-Axis:"); + Serial.print(heading); + Serial.println(" "); + Serial.println("The clockwise angle between the magnetic north and the projection of the positive X-Axis in the horizontal plane:"); + Serial.println(tiltheading); + Serial.println(" "); + + temperature = Barometer.bmp180GetTemperature(Barometer.bmp180ReadUT()); //Get the temperature, bmp180ReadUT MUST be called first + pressure = Barometer.bmp180GetPressure(Barometer.bmp180ReadUP());//Get the temperature + altitude = Barometer.calcAltitude(pressure); //Uncompensated caculation - in Meters + atm = pressure / 101325; + + Serial.print("Temperature: "); + Serial.print(temperature, 2); //display 2 decimal places + Serial.println("deg C"); + + Serial.print("Pressure: "); + Serial.print(pressure, 0); //whole number only. + Serial.println(" Pa"); + + Serial.print("Ralated Atmosphere: "); + Serial.println(atm, 4); //display 4 decimal places + + Serial.print("Altitude: "); + Serial.print(altitude, 2); //display 2 decimal places + Serial.println(" m"); + + Serial.println(); + delay(1000); + +} + + +void getHeading(void) +{ + heading = 180 * atan2(Mxyz[1], Mxyz[0]) / PI; + if (heading < 0) heading += 360; +} + +void getTiltHeading(void) +{ + float pitch = asin(-Axyz[0]); + float roll = asin(Axyz[1] / cos(pitch)); + + float xh = Mxyz[0] * cos(pitch) + Mxyz[2] * sin(pitch); + float yh = Mxyz[0] * sin(roll) * sin(pitch) + Mxyz[1] * cos(roll) - Mxyz[2] * sin(roll) * cos(pitch); + float zh = -Mxyz[0] * cos(roll) * sin(pitch) + Mxyz[1] * sin(roll) + Mxyz[2] * cos(roll) * cos(pitch); + tiltheading = 180 * atan2(yh, xh) / PI; + if (yh < 0) tiltheading += 360; +} + + + +void Mxyz_init_calibrated () +{ + + Serial.println(F("Before using 9DOF,we need to calibrate the compass frist,It will takes about 2 minutes.")); + Serial.print(" "); + Serial.println(F("During calibratting ,you should rotate and turn the 9DOF all the time within 2 minutes.")); + Serial.print(" "); + Serial.println(F("If you are ready ,please sent a command data 'ready' to start sample and calibrate.")); + while (!Serial.find("ready")); + Serial.println(" "); + Serial.println("ready"); + Serial.println("Sample starting......"); + Serial.println("waiting ......"); + + get_calibration_Data (); + + Serial.println(" "); + Serial.println("compass calibration parameter "); + Serial.print(mx_centre); + Serial.print(" "); + Serial.print(my_centre); + Serial.print(" "); + Serial.println(mz_centre); + Serial.println(" "); +} + + +void get_calibration_Data () +{ + for (int i = 0; i < sample_num_mdate; i++) + { + get_one_sample_date_mxyz(); + /* + Serial.print(mx_sample[2]); + Serial.print(" "); + Serial.print(my_sample[2]); //you can see the sample data here . + Serial.print(" "); + Serial.println(mz_sample[2]); + */ + + + + if (mx_sample[2] >= mx_sample[1])mx_sample[1] = mx_sample[2]; + if (my_sample[2] >= my_sample[1])my_sample[1] = my_sample[2]; //find max value + if (mz_sample[2] >= mz_sample[1])mz_sample[1] = mz_sample[2]; + + if (mx_sample[2] <= mx_sample[0])mx_sample[0] = mx_sample[2]; + if (my_sample[2] <= my_sample[0])my_sample[0] = my_sample[2]; //find min value + if (mz_sample[2] <= mz_sample[0])mz_sample[0] = mz_sample[2]; + + } + + mx_max = mx_sample[1]; + my_max = my_sample[1]; + mz_max = mz_sample[1]; + + mx_min = mx_sample[0]; + my_min = my_sample[0]; + mz_min = mz_sample[0]; + + + + mx_centre = (mx_max + mx_min) / 2; + my_centre = (my_max + my_min) / 2; + mz_centre = (mz_max + mz_min) / 2; + +} + + + + + + +void get_one_sample_date_mxyz() +{ + getCompass_Data(); + mx_sample[2] = Mxyz[0]; + my_sample[2] = Mxyz[1]; + mz_sample[2] = Mxyz[2]; +} + + +void getAccel_Data(void) +{ + accelgyro.getMotion9(&ax, &ay, &az, &gx, &gy, &gz, &mx, &my, &mz); + Axyz[0] = (double) ax / 16384; + Axyz[1] = (double) ay / 16384; + Axyz[2] = (double) az / 16384; +} + +void getGyro_Data(void) +{ + accelgyro.getMotion9(&ax, &ay, &az, &gx, &gy, &gz, &mx, &my, &mz); + Gxyz[0] = (double) gx * 250 / 32768; + Gxyz[1] = (double) gy * 250 / 32768; + Gxyz[2] = (double) gz * 250 / 32768; +} + +void getCompass_Data(void) +{ + I2C_M.writeByte(MPU9150_RA_MAG_ADDRESS, 0x0A, 0x01); //enable the magnetometer + delay(10); + I2C_M.readBytes(MPU9150_RA_MAG_ADDRESS, MPU9150_RA_MAG_XOUT_L, 6, buffer_m); + + mx = ((int16_t)(buffer_m[1]) << 8) | buffer_m[0] ; + my = ((int16_t)(buffer_m[3]) << 8) | buffer_m[2] ; + mz = ((int16_t)(buffer_m[5]) << 8) | buffer_m[4] ; + + Mxyz[0] = (double) mx * 1200 / 4096; + Mxyz[1] = (double) my * 1200 / 4096; + Mxyz[2] = (double) mz * 1200 / 4096; +} + +void getCompassDate_calibrated () +{ + getCompass_Data(); + Mxyz[0] = Mxyz[0] - mx_centre; + Mxyz[1] = Mxyz[1] - my_centre; + Mxyz[2] = Mxyz[2] - mz_centre; +} From c0c5356dbab5bd0f46bcf945bd58201ff433e731 Mon Sep 17 00:00:00 2001 From: jollepe Date: Thu, 21 Dec 2017 07:37:22 +0100 Subject: [PATCH 188/335] Change the order of ifdef and define When you take the actual example file, and uncomment the line #define OUTPUT_READABLE_YAWPITCHROLL and try to compile this code, you get an error "ypr was not declared in this scope". This is caused by a wrong order of #define and #ifdef. With this patch, it is possible to compile in the correct way. --- .../MPU6050_DMP6_ESPWiFi/MPU6050_DMP6_ESPWiFi.ino | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/Arduino/MPU6050/examples/MPU6050_DMP6_ESPWiFi/MPU6050_DMP6_ESPWiFi.ino b/Arduino/MPU6050/examples/MPU6050_DMP6_ESPWiFi/MPU6050_DMP6_ESPWiFi.ino index 588cf914..08dc43d0 100644 --- a/Arduino/MPU6050/examples/MPU6050_DMP6_ESPWiFi/MPU6050_DMP6_ESPWiFi.ino +++ b/Arduino/MPU6050/examples/MPU6050_DMP6_ESPWiFi/MPU6050_DMP6_ESPWiFi.ino @@ -91,12 +91,7 @@ VectorInt16 aa; // [x, y, z] accel sensor measurements VectorInt16 aaReal; // [x, y, z] gravity-free accel sensor measurements VectorInt16 aaWorld; // [x, y, z] world-frame accel sensor measurements VectorFloat gravity; // [x, y, z] gravity vector -#ifdef OUTPUT_READABLE_EULER -float euler[3]; // [psi, theta, phi] Euler angle container -#endif -#ifdef OUTPUT_READABLE_YAWPITCHROLL -float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector -#endif + // uncomment "OUTPUT_READABLE_QUATERNION" if you want to see the actual // quaternion components in a [w, x, y, z] format (not best for parsing @@ -133,6 +128,14 @@ float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gra // format used for the InvenSense teapot demo #define OUTPUT_TEAPOT_OSC + +#ifdef OUTPUT_READABLE_EULER +float euler[3]; // [psi, theta, phi] Euler angle container +#endif +#ifdef OUTPUT_READABLE_YAWPITCHROLL +float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector +#endif + #define INTERRUPT_PIN 15 // use pin 15 on ESP8266 const char DEVICE_NAME[] = "mpu6050"; From 818dd7a93dac0cfb4260660e8b4958fd6a2d24bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dan=C3=ADel=20Gr=C3=A9tarsson?= Date: Sat, 17 Feb 2018 09:26:46 +0000 Subject: [PATCH 189/335] Fix bug in writeBytes method for nRF51 --- nRF51/I2CDev/I2Cdev.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/nRF51/I2CDev/I2Cdev.cpp b/nRF51/I2CDev/I2Cdev.cpp index a0646057..c278c017 100644 --- a/nRF51/I2CDev/I2Cdev.cpp +++ b/nRF51/I2CDev/I2Cdev.cpp @@ -34,6 +34,7 @@ THE SOFTWARE. extern "C"{ #include "nrf_drv_twi.h" #include "app_util_platform.h" +#include // For memcpy } #include "I2Cdev.h" static nrf_drv_twi_t m_twi=NRF_DRV_TWI_INSTANCE(0); @@ -212,10 +213,15 @@ bool I2Cdev::writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data) { * @return Status of operation (true = success) */ bool I2Cdev::writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t* data) { - if (NRF_SUCCESS!=nrf_drv_twi_tx(&m_twi,devAddr,®Addr,1,true)) - return false; - return NRF_SUCCESS==nrf_drv_twi_tx(&m_twi,devAddr,data,length,false); + const uint8_t buf_len = length+1; // Register address + number of bytes + uint8_t tx_buf[buf_len]; + + tx_buf[0] = regAddr; + memcpy(tx_buf+1, data, length); + + return NRF_SUCCESS == nrf_drv_twi_tx(&m_twi, devAddr, tx_buf, buf_len, true); } + /** Write single word to a 16-bit device register. * @param devAddr I2C slave device address * @param regAddr Register address to write to @@ -225,6 +231,7 @@ bool I2Cdev::writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_ bool I2Cdev::writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data) { return writeWords(devAddr, regAddr, 1, &data); } + /** Write multiple words to a 16-bit device register. * @param devAddr I2C slave device address * @param regAddr First register address to write to From 6e38d7ac40653020f6ebf37577d14c0e70b77ab7 Mon Sep 17 00:00:00 2001 From: Mateus Amarante Araujo Date: Sun, 25 Feb 2018 19:48:34 -0300 Subject: [PATCH 190/335] Basic I2Cdev and MPU6050 libraries for BeagleBone Black --- BeagleBoneBlack/I2Cdev/I2Cdev.cpp | 366 +++ BeagleBoneBlack/I2Cdev/I2Cdev.h | 64 + BeagleBoneBlack/MPU6050/MPU6050.cpp | 3501 +++++++++++++++++++++++++++ BeagleBoneBlack/MPU6050/MPU6050.h | 1018 ++++++++ 4 files changed, 4949 insertions(+) create mode 100644 BeagleBoneBlack/I2Cdev/I2Cdev.cpp create mode 100644 BeagleBoneBlack/I2Cdev/I2Cdev.h create mode 100644 BeagleBoneBlack/MPU6050/MPU6050.cpp create mode 100644 BeagleBoneBlack/MPU6050/MPU6050.h diff --git a/BeagleBoneBlack/I2Cdev/I2Cdev.cpp b/BeagleBoneBlack/I2Cdev/I2Cdev.cpp new file mode 100644 index 00000000..1bb4f6a7 --- /dev/null +++ b/BeagleBoneBlack/I2Cdev/I2Cdev.cpp @@ -0,0 +1,366 @@ +// I2Cdev library collection - Main I2C device class +// Abstracts bit and byte I2C R/W functions into a convenient class +// Based on Arduino's I2Cdev by Jeff Rowberg +// + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#include "I2Cdev.h" +#include + +#define I2C_PATH "/dev/i2c-2" + +I2Cdev::I2Cdev() {} + +void I2Cdev::initialize() {} + +/** Enable or disable I2C, + * @param isEnabled true = enable, false = disable + */ +void I2Cdev::enable(bool isEnabled) +{ +} + +/** Read a single bit from an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param bitNum Bit position to read (0-7) + * @param data Container for single bit value + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) + * @return Status of read operation (true = success) + */ +int8_t I2Cdev::readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data) +{ + uint8_t b; + uint8_t count = readByte(devAddr, regAddr, &b); + *data = b & (1 << bitNum); + return count; +} + +/** Read a single bit from a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param bitNum Bit position to read (0-15) + * @param data Container for single bit value + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) + * @return Status of read operation (true = success) + */ +int8_t I2Cdev::readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data) +{ + uint16_t b; + uint8_t count = readWord(devAddr, regAddr, &b); + *data = b & (1 << bitNum); + return count; +} + +/** Read multiple bits from an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param bitStart First bit position to read (0-7) + * @param length Number of bits to read (not more than 8) + * @param data Container for right-aligned value (i.e. '101' read from any bitStart position will equal 0x05) + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) + * @return Status of read operation (true = success) + */ +int8_t I2Cdev::readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data) +{ + // 01101001 read byte + // 76543210 bit numbers + // xxx args: bitStart=4, length=3 + // 010 masked + // -> 010 shifted + uint8_t count, b; + if ((count = readByte(devAddr, regAddr, &b)) != 0) + { + uint8_t mask = ((1 << length) - 1) << (bitStart - length + 1); + b &= mask; + b >>= (bitStart - length + 1); + *data = b; + } + return count; +} + +/** Read multiple bits from a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param bitStart First bit position to read (0-15) + * @param length Number of bits to read (not more than 16) + * @param data Container for right-aligned value (i.e. '101' read from any bitStart position will equal 0x05) + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) + * @return Status of read operation (1 = success, 0 = failure, -1 = timeout) + */ +int8_t I2Cdev::readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t *data) +{ + // 1101011001101001 read byte + // fedcba9876543210 bit numbers + // xxx args: bitStart=12, length=3 + // 010 masked#include + // -> 010 shifted + uint8_t count; + uint16_t w; + if ((count = readWord(devAddr, regAddr, &w)) != 0) + { + uint16_t mask = ((1 << length) - 1) << (bitStart - length + 1); + w &= mask; + w >>= (bitStart - length + 1); + *data = w; + } + return count; +} + +/** Read single byte from an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param data Container for byte value read from device + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) + * @return Status of read operation (true = success) + */ +int8_t I2Cdev::readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data) +{ + return readBytes(devAddr, regAddr, 1, data); +} + +/** Read single word from a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param data Container for word value read from device + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) + * @return Status of read operation (true = success) + */ +int8_t I2Cdev::readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data) +{ + return readWords(devAddr, regAddr, 1, data); +} + +/** Read multiple bytes from an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr First register regAddr to read from + * @param length Number of bytes to read + * @param data Buffer to store read data in + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) + * @return Number of bytes read (-1 indicates failure) + */ +int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data) +{ + int fd; + + if ((fd = open(I2C_PATH, O_RDWR) < 0)) + { + perror("Failed to open " I2C_PATH); + return -1; + } + + if (ioctl(fd, I2C_SLAVE, devAddr) < 0) + { + fprintf(stderr, "Failed to access slave at %u address\n", devAddr); + return -1; + } + + if (read(fd, data, length) != length) + { + perror("Failed to read data from " I2C_PATH); + return -1; + } + + close(fd); + + return length; +} + +/** Read multiple words from a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr First register regAddr to read from + * @param length Number of words to read + * @param data Buffer to store read data in + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) + * @return Number of words read (-1 indicates failure) + */ +int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data) +{ + if (readBytes(devAddr, regAddr, length * 2, reinterpret_cast(data)) > 0) + return length; + + return -1; +} + +/** write a single bit in an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to write to + * @param bitNum Bit position to write (0-7) + * @param value New bit value to write + * @return Status of operation (true = success) + */ +bool I2Cdev::writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t data) +{ + uint8_t b; + readByte(devAddr, regAddr, &b); + b = (data != 0) ? (b | (1 << bitNum)) : (b & ~(1 << bitNum)); + return writeByte(devAddr, regAddr, b); +} + +/** write a single bit in a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to write to + * @param bitNum Bit position to write (0-15) + * @param value New bit value to write + * @return Status of operation (true = success) + */ +bool I2Cdev::writeBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t data) +{ + uint16_t w; + readWord(devAddr, regAddr, &w); + w = (data != 0) ? (w | (1 << bitNum)) : (w & ~(1 << bitNum)); + return writeWord(devAddr, regAddr, w); +} + +/** Write multiple bits in an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to write to + * @param bitStart First bit position to write (0-7) + * @param length Number of bits to write (not more than 8) + * @param data Right-aligned value to write + * @return Status of operation (true = success) + */ +bool I2Cdev::writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data) +{ + // 010 value to write + // 76543210 bit numbers + // xxx args: bitStart=4, length=3 + // 00011100 mask byte + // 10101111 original value (sample) + // 10100011 original & ~mask + // 10101011 masked | value + uint8_t b; + if (readByte(devAddr, regAddr, &b) != 0) + { + uint8_t mask = ((1 << length) - 1) << (bitStart - length + 1); + data <<= (bitStart - length + 1); // shift data into correct position + data &= mask; // zero all non-important bits in data + b &= ~(mask); // zero all important bits in existing byte + b |= data; // combine data with existing byte + return writeByte(devAddr, regAddr, b); + } + else + { + return false; + } +} + +/** Write multiple bits in a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to write to + * @param bitStart First bit position to write (0-15) + * @param length Number of bits to write (not more than 16) + * @param data Right-aligned value to write + * @return Status of operation (true = success) + */ +bool I2Cdev::writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t data) +{ + // 010 value to write + // fedcba9876543210 bit numbers + // xxx args: bitStart=12, length=3 + // 0001110000000000 mask word + // 1010111110010110 original value (sample) + // 1010001110010110 original & ~mask + // 1010101110010110 masked | value + uint16_t w; + if (readWord(devAddr, regAddr, &w) != 0) + { + uint16_t mask = ((1 << length) - 1) << (bitStart - length + 1); + data <<= (bitStart - length + 1); // shift data into correct position + data &= mask; // zero all non-important bits in data + w &= ~(mask); // zero all important bits in existing word + w |= data; // combine data with existing word + return writeWord(devAddr, regAddr, w); + } + else + { + return false; + } +} + +/** Write single byte to an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register address to write to + * @param data New byte value to write + * @return Status of operation (true = success) + */ +bool I2Cdev::writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data) +{ + return writeBytes(devAddr, regAddr, 1, &data); +} + +/** Write single word to a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register address to write to + * @param data New word value to write + * @return Status of operation (true = success) + */ +bool I2Cdev::writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data) +{ + return writeWords(devAddr, regAddr, 1, &data); +} + +/** Write multiple bytes to an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr First register address to write to + * @param length Number of bytes to write + * @param data Buffer to copy new data from + * @return Status of operation (true = success) + */ +bool I2Cdev::writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data) +{ + int fd; + + if ((fd = open(I2C_PATH, O_RDWR) < 0)) + { + perror("Failed to open " I2C_PATH); + return false; + } + + if (ioctl(fd, I2C_SLAVE, devAddr) < 0) + { + fprintf(stderr, "Failed to access slave at %u address\n", devAddr); + return false; + } + + if (write(fd, data, length) != length) + { + perror("Failed to write into " I2C_PATH); + return false; + } + + close(fd); + + return true; +} + +/** Write multiple words to a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr First register address to write to + * @param length Number of words to write + * @param data Buffer to copy new data from + * @return Status of operation (true = success) + */ +bool I2Cdev::writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data) +{ + return writeBytes(devAddr, regAddr, length * 2, reinterpret_cast(data)); +} \ No newline at end of file diff --git a/BeagleBoneBlack/I2Cdev/I2Cdev.h b/BeagleBoneBlack/I2Cdev/I2Cdev.h new file mode 100644 index 00000000..ac1bb0b9 --- /dev/null +++ b/BeagleBoneBlack/I2Cdev/I2Cdev.h @@ -0,0 +1,64 @@ +// I2Cdev library collection - Main I2C device class +// Abstracts bit and byte I2C R/W functions into a convenient class +// Based on Arduino's I2Cdev by Jeff Rowberg +// + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#ifndef _I2CDEV_H_ +#define _I2CDEV_H_ + +#include +#include +#include +#include +#include + +class I2Cdev +{ +public: + I2Cdev(); + + static void initialize(); + static void enable(bool isEnabled); + + static int8_t readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data); + static int8_t readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data); + static int8_t readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data); + static int8_t readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t *data); + static int8_t readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data); + static int8_t readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data); + static int8_t readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data); + static int8_t readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data); + + static bool writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t data); + static bool writeBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t data); + static bool writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data); + static bool writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t data); + static bool writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data); + static bool writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data); + static bool writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data); + static bool writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data); + + static uint16_t readTimeout; +}; + +#endif /* _I2CDEV_H_ */ diff --git a/BeagleBoneBlack/MPU6050/MPU6050.cpp b/BeagleBoneBlack/MPU6050/MPU6050.cpp new file mode 100644 index 00000000..745dc37d --- /dev/null +++ b/BeagleBoneBlack/MPU6050/MPU6050.cpp @@ -0,0 +1,3501 @@ +// I2Cdev library collection - MPU6050 I2C device class +// Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00) +// 8/24/2011 by Jeff Rowberg +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// ... - ongoing debug release + +// NOTE: THIS IS ONLY A PARIAL RELEASE. THIS DEVICE CLASS IS CURRENTLY UNDERGOING ACTIVE +// DEVELOPMENT AND IS STILL MISSING SOME IMPORTANT FEATURES. PLEASE KEEP THIS IN MIND IF +// YOU DECIDE TO USE THIS PARTICULAR CODE FOR ANYTHING. + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2012 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#include "MPU6050.h" +#include +#include + +/** Default constructor, uses default I2C address. + * @see MPU6050_DEFAULT_ADDRESS + */ +MPU6050::MPU6050() +{ + devAddr = MPU6050_DEFAULT_ADDRESS; +} + +/** Specific address constructor. + * @param address I2C address + * @see MPU6050_DEFAULT_ADDRESS + * @see MPU6050_ADDRESS_AD0_LOW + * @see MPU6050_ADDRESS_AD0_HIGH + */ +MPU6050::MPU6050(uint8_t address) +{ + devAddr = address; +} + +/** Power on and prepare for general usage. + * This will activate the device and take it out of sleep mode (which must be done + * after start-up). This function also sets both the accelerometer and the gyroscope + * to their most sensitive settings, namely +/- 2g and +/- 250 degrees/sec, and sets + * the clock source to use the X Gyro for reference, which is slightly better than + * the default internal clock source. + */ +void MPU6050::initialize() +{ + setClockSource(MPU6050_CLOCK_PLL_XGYRO); + setFullScaleGyroRange(MPU6050_GYRO_FS_250); + setFullScaleAccelRange(MPU6050_ACCEL_FS_2); + setSleepEnabled(false); // thanks to Jack Elston for pointing this one out! +} + +/** Verify the I2C connection. + * Make sure the device is connected and responds as expected. + * @return True if connection is valid, false otherwise + */ +bool MPU6050::testConnection() +{ + return getDeviceID() == 0x34; +} + +// AUX_VDDIO register (InvenSense demo code calls this RA_*G_OFFS_TC) + +/** Get the auxiliary I2C supply voltage level. + * When set to 1, the auxiliary I2C bus high logic level is VDD. When cleared to + * 0, the auxiliary I2C bus high logic level is VLOGIC. This does not apply to + * the MPU-6000, which does not have a VLOGIC pin. + * @return I2C supply voltage level (0=VLOGIC, 1=VDD) + */ +uint8_t MPU6050::getAuxVDDIOLevel() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_PWR_MODE_BIT, buffer); + return buffer[0]; +} +/** Set the auxiliary I2C supply voltage level. + * When set to 1, the auxiliary I2C bus high logic level is VDD. When cleared to + * 0, the auxiliary I2C bus high logic level is VLOGIC. This does not apply to + * the MPU-6000, which does not have a VLOGIC pin. + * @param level I2C supply voltage level (0=VLOGIC, 1=VDD) + */ +void MPU6050::setAuxVDDIOLevel(uint8_t level) +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_PWR_MODE_BIT, level); +} + +// SMPLRT_DIV register + +/** Get gyroscope output rate divider. + * The sensor register output, FIFO output, DMP sampling, Motion detection, Zero + * Motion detection, and Free Fall detection are all based on the Sample Rate. + * The Sample Rate is generated by dividing the gyroscope output rate by + * SMPLRT_DIV: + * + * Sample Rate = Gyroscope Output Rate / (1 + SMPLRT_DIV) + * + * where Gyroscope Output Rate = 8kHz when the DLPF is disabled (DLPF_CFG = 0 or + * 7), and 1kHz when the DLPF is enabled (see Register 26). + * + * Note: The accelerometer output rate is 1kHz. This means that for a Sample + * Rate greater than 1kHz, the same accelerometer sample may be output to the + * FIFO, DMP, and sensor registers more than once. + * + * For a diagram of the gyroscope and accelerometer signal paths, see Section 8 + * of the MPU-6000/MPU-6050 Product Specification document. + * + * @return Current sample rate + * @see MPU6050_RA_SMPLRT_DIV + */ +uint8_t MPU6050::getRate() +{ + I2Cdev::readByte(devAddr, MPU6050_RA_SMPLRT_DIV, buffer); + return buffer[0]; +} +/** Set gyroscope sample rate divider. + * @param rate New sample rate divider + * @see getRate() + * @see MPU6050_RA_SMPLRT_DIV + */ +void MPU6050::setRate(uint8_t rate) +{ + I2Cdev::writeByte(devAddr, MPU6050_RA_SMPLRT_DIV, rate); +} + +// CONFIG register + +/** Get external FSYNC configuration. + * Configures the external Frame Synchronization (FSYNC) pin sampling. An + * external signal connected to the FSYNC pin can be sampled by configuring + * EXT_SYNC_SET. Signal changes to the FSYNC pin are latched so that short + * strobes may be captured. The latched FSYNC signal will be sampled at the + * Sampling Rate, as defined in register 25. After sampling, the latch will + * reset to the current FSYNC signal state. + * + * The sampled value will be reported in place of the least significant bit in + * a sensor data register determined by the value of EXT_SYNC_SET according to + * the following table. + * + *
+ * EXT_SYNC_SET | FSYNC Bit Location
+ * -------------+-------------------
+ * 0            | Input disabled
+ * 1            | TEMP_OUT_L[0]
+ * 2            | GYRO_XOUT_L[0]
+ * 3            | GYRO_YOUT_L[0]
+ * 4            | GYRO_ZOUT_L[0]
+ * 5            | ACCEL_XOUT_L[0]
+ * 6            | ACCEL_YOUT_L[0]
+ * 7            | ACCEL_ZOUT_L[0]
+ * 
+ * + * @return FSYNC configuration value + */ +uint8_t MPU6050::getExternalFrameSync() +{ + I2Cdev::readBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_EXT_SYNC_SET_BIT, MPU6050_CFG_EXT_SYNC_SET_LENGTH, buffer); + return buffer[0]; +} +/** Set external FSYNC configuration. + * @see getExternalFrameSync() + * @see MPU6050_RA_CONFIG + * @param sync New FSYNC configuration value + */ +void MPU6050::setExternalFrameSync(uint8_t sync) +{ + I2Cdev::writeBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_EXT_SYNC_SET_BIT, MPU6050_CFG_EXT_SYNC_SET_LENGTH, sync); +} +/** Get digital low-pass filter configuration. + * The DLPF_CFG parameter sets the digital low pass filter configuration. It + * also determines the internal sampling rate used by the device as shown in + * the table below. + * + * Note: The accelerometer output rate is 1kHz. This means that for a Sample + * Rate greater than 1kHz, the same accelerometer sample may be output to the + * FIFO, DMP, and sensor registers more than once. + * + *
+ *          |   ACCELEROMETER    |           GYROSCOPE
+ * DLPF_CFG | Bandwidth | Delay  | Bandwidth | Delay  | Sample Rate
+ * ---------+-----------+--------+-----------+--------+-------------
+ * 0        | 260Hz     | 0ms    | 256Hz     | 0.98ms | 8kHz
+ * 1        | 184Hz     | 2.0ms  | 188Hz     | 1.9ms  | 1kHz
+ * 2        | 94Hz      | 3.0ms  | 98Hz      | 2.8ms  | 1kHz
+ * 3        | 44Hz      | 4.9ms  | 42Hz      | 4.8ms  | 1kHz
+ * 4        | 21Hz      | 8.5ms  | 20Hz      | 8.3ms  | 1kHz
+ * 5        | 10Hz      | 13.8ms | 10Hz      | 13.4ms | 1kHz
+ * 6        | 5Hz       | 19.0ms | 5Hz       | 18.6ms | 1kHz
+ * 7        |   -- Reserved --   |   -- Reserved --   | Reserved
+ * 
+ * + * @return DLFP configuration + * @see MPU6050_RA_CONFIG + * @see MPU6050_CFG_DLPF_CFG_BIT + * @see MPU6050_CFG_DLPF_CFG_LENGTH + */ +uint8_t MPU6050::getDLPFMode() +{ + I2Cdev::readBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_DLPF_CFG_BIT, MPU6050_CFG_DLPF_CFG_LENGTH, buffer); + return buffer[0]; +} +/** Set digital low-pass filter configuration. + * @param mode New DLFP configuration setting + * @see getDLPFBandwidth() + * @see MPU6050_DLPF_BW_256 + * @see MPU6050_RA_CONFIG + * @see MPU6050_CFG_DLPF_CFG_BIT + * @see MPU6050_CFG_DLPF_CFG_LENGTH + */ +void MPU6050::setDLPFMode(uint8_t mode) +{ + I2Cdev::writeBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_DLPF_CFG_BIT, MPU6050_CFG_DLPF_CFG_LENGTH, mode); +} + +// GYRO_CONFIG register + +/** Get full-scale gyroscope range. + * The FS_SEL parameter allows setting the full-scale range of the gyro sensors, + * as described in the table below. + * + *
+ * 0 = +/- 250 degrees/sec
+ * 1 = +/- 500 degrees/sec
+ * 2 = +/- 1000 degrees/sec
+ * 3 = +/- 2000 degrees/sec
+ * 
+ * + * @return Current full-scale gyroscope range setting + * @see MPU6050_GYRO_FS_250 + * @see MPU6050_RA_GYRO_CONFIG + * @see MPU6050_GCONFIG_FS_SEL_BIT + * @see MPU6050_GCONFIG_FS_SEL_LENGTH + */ +uint8_t MPU6050::getFullScaleGyroRange() +{ + I2Cdev::readBits(devAddr, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, buffer); + return buffer[0]; +} +/** Set full-scale gyroscope range. + * @param range New full-scale gyroscope range value + * @see getFullScaleRange() + * @see MPU6050_GYRO_FS_250 + * @see MPU6050_RA_GYRO_CONFIG + * @see MPU6050_GCONFIG_FS_SEL_BIT + * @see MPU6050_GCONFIG_FS_SEL_LENGTH + */ +void MPU6050::setFullScaleGyroRange(uint8_t range) +{ + I2Cdev::writeBits(devAddr, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, range); +} + +// SELF TEST FACTORY TRIM VALUES + +/** Get self-test factory trim value for accelerometer X axis. + * @return factory trim value + * @see MPU6050_RA_SELF_TEST_X + */ +uint8_t MPU6050::getAccelXSelfTestFactoryTrim() +{ + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_X, &buffer[0]); + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_A, &buffer[1]); + return (buffer[0] >> 3) | ((buffer[1] >> 4) & 0x03); +} + +/** Get self-test factory trim value for accelerometer Y axis. + * @return factory trim value + * @see MPU6050_RA_SELF_TEST_Y + */ +uint8_t MPU6050::getAccelYSelfTestFactoryTrim() +{ + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_Y, &buffer[0]); + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_A, &buffer[1]); + return (buffer[0] >> 3) | ((buffer[1] >> 2) & 0x03); +} + +/** Get self-test factory trim value for accelerometer Z axis. + * @return factory trim value + * @see MPU6050_RA_SELF_TEST_Z + */ +uint8_t MPU6050::getAccelZSelfTestFactoryTrim() +{ + I2Cdev::readBytes(devAddr, MPU6050_RA_SELF_TEST_Z, 2, buffer); + return (buffer[0] >> 3) | (buffer[1] & 0x03); +} + +/** Get self-test factory trim value for gyro X axis. + * @return factory trim value + * @see MPU6050_RA_SELF_TEST_X + */ +uint8_t MPU6050::getGyroXSelfTestFactoryTrim() +{ + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_X, buffer); + return (buffer[0] & 0x1F); +} + +/** Get self-test factory trim value for gyro Y axis. + * @return factory trim value + * @see MPU6050_RA_SELF_TEST_Y + */ +uint8_t MPU6050::getGyroYSelfTestFactoryTrim() +{ + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_Y, buffer); + return (buffer[0] & 0x1F); +} + +/** Get self-test factory trim value for gyro Z axis. + * @return factory trim value + * @see MPU6050_RA_SELF_TEST_Z + */ +uint8_t MPU6050::getGyroZSelfTestFactoryTrim() +{ + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_Z, buffer); + return (buffer[0] & 0x1F); +} + +// ACCEL_CONFIG register + +/** Get self-test enabled setting for accelerometer X axis. + * @return Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +bool MPU6050::getAccelXSelfTest() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_XA_ST_BIT, buffer); + return buffer[0]; +} +/** Get self-test enabled setting for accelerometer X axis. + * @param enabled Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050::setAccelXSelfTest(bool enabled) +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_XA_ST_BIT, enabled); +} +/** Get self-test enabled value for accelerometer Y axis. + * @return Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +bool MPU6050::getAccelYSelfTest() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_YA_ST_BIT, buffer); + return buffer[0]; +} +/** Get self-test enabled value for accelerometer Y axis. + * @param enabled Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050::setAccelYSelfTest(bool enabled) +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_YA_ST_BIT, enabled); +} +/** Get self-test enabled value for accelerometer Z axis. + * @return Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +bool MPU6050::getAccelZSelfTest() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ZA_ST_BIT, buffer); + return buffer[0]; +} +/** Set self-test enabled value for accelerometer Z axis. + * @param enabled Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050::setAccelZSelfTest(bool enabled) +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ZA_ST_BIT, enabled); +} +/** Get full-scale accelerometer range. + * The FS_SEL parameter allows setting the full-scale range of the accelerometer + * sensors, as described in the table below. + * + *
+ * 0 = +/- 2g
+ * 1 = +/- 4g
+ * 2 = +/- 8g
+ * 3 = +/- 16g
+ * 
+ * + * @return Current full-scale accelerometer range setting + * @see MPU6050_ACCEL_FS_2 + * @see MPU6050_RA_ACCEL_CONFIG + * @see MPU6050_ACONFIG_AFS_SEL_BIT + * @see MPU6050_ACONFIG_AFS_SEL_LENGTH + */ +uint8_t MPU6050::getFullScaleAccelRange() +{ + I2Cdev::readBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, buffer); + return buffer[0]; +} +/** Set full-scale accelerometer range. + * @param range New full-scale accelerometer range setting + * @see getFullScaleAccelRange() + */ +void MPU6050::setFullScaleAccelRange(uint8_t range) +{ + I2Cdev::writeBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, range); +} +/** Get the high-pass filter configuration. + * The DHPF is a filter module in the path leading to motion detectors (Free + * Fall, Motion threshold, and Zero Motion). The high pass filter output is not + * available to the data registers (see Figure in Section 8 of the MPU-6000/ + * MPU-6050 Product Specification document). + * + * The high pass filter has three modes: + * + *
+ *    Reset: The filter output settles to zero within one sample. This
+ *           effectively disables the high pass filter. This mode may be toggled
+ *           to quickly settle the filter.
+ *
+ *    On:    The high pass filter will pass signals above the cut off frequency.
+ *
+ *    Hold:  When triggered, the filter holds the present sample. The filter
+ *           output will be the difference between the input sample and the held
+ *           sample.
+ * 
+ * + *
+ * ACCEL_HPF | Filter Mode | Cut-off Frequency
+ * ----------+-------------+------------------
+ * 0         | Reset       | None
+ * 1         | On          | 5Hz
+ * 2         | On          | 2.5Hz
+ * 3         | On          | 1.25Hz
+ * 4         | On          | 0.63Hz
+ * 7         | Hold        | None
+ * 
+ * + * @return Current high-pass filter configuration + * @see MPU6050_DHPF_RESET + * @see MPU6050_RA_ACCEL_CONFIG + */ +uint8_t MPU6050::getDHPFMode() +{ + I2Cdev::readBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ACCEL_HPF_BIT, MPU6050_ACONFIG_ACCEL_HPF_LENGTH, buffer); + return buffer[0]; +} +/** Set the high-pass filter configuration. + * @param bandwidth New high-pass filter configuration + * @see setDHPFMode() + * @see MPU6050_DHPF_RESET + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050::setDHPFMode(uint8_t bandwidth) +{ + I2Cdev::writeBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ACCEL_HPF_BIT, MPU6050_ACONFIG_ACCEL_HPF_LENGTH, bandwidth); +} + +// FF_THR register + +/** Get free-fall event acceleration threshold. + * This register configures the detection threshold for Free Fall event + * detection. The unit of FF_THR is 1LSB = 2mg. Free Fall is detected when the + * absolute value of the accelerometer measurements for the three axes are each + * less than the detection threshold. This condition increments the Free Fall + * duration counter (Register 30). The Free Fall interrupt is triggered when the + * Free Fall duration counter reaches the time specified in FF_DUR. + * + * For more details on the Free Fall detection interrupt, see Section 8.2 of the + * MPU-6000/MPU-6050 Product Specification document as well as Registers 56 and + * 58 of this document. + * + * @return Current free-fall acceleration threshold value (LSB = 2mg) + * @see MPU6050_RA_FF_THR + */ +uint8_t MPU6050::getFreefallDetectionThreshold() +{ + I2Cdev::readByte(devAddr, MPU6050_RA_FF_THR, buffer); + return buffer[0]; +} +/** Get free-fall event acceleration threshold. + * @param threshold New free-fall acceleration threshold value (LSB = 2mg) + * @see getFreefallDetectionThreshold() + * @see MPU6050_RA_FF_THR + */ +void MPU6050::setFreefallDetectionThreshold(uint8_t threshold) +{ + I2Cdev::writeByte(devAddr, MPU6050_RA_FF_THR, threshold); +} + +// FF_DUR register + +/** Get free-fall event duration threshold. + * This register configures the duration counter threshold for Free Fall event + * detection. The duration counter ticks at 1kHz, therefore FF_DUR has a unit + * of 1 LSB = 1 ms. + * + * The Free Fall duration counter increments while the absolute value of the + * accelerometer measurements are each less than the detection threshold + * (Register 29). The Free Fall interrupt is triggered when the Free Fall + * duration counter reaches the time specified in this register. + * + * For more details on the Free Fall detection interrupt, see Section 8.2 of + * the MPU-6000/MPU-6050 Product Specification document as well as Registers 56 + * and 58 of this document. + * + * @return Current free-fall duration threshold value (LSB = 1ms) + * @see MPU6050_RA_FF_DUR + */ +uint8_t MPU6050::getFreefallDetectionDuration() +{ + I2Cdev::readByte(devAddr, MPU6050_RA_FF_DUR, buffer); + return buffer[0]; +} +/** Get free-fall event duration threshold. + * @param duration New free-fall duration threshold value (LSB = 1ms) + * @see getFreefallDetectionDuration() + * @see MPU6050_RA_FF_DUR + */ +void MPU6050::setFreefallDetectionDuration(uint8_t duration) +{ + I2Cdev::writeByte(devAddr, MPU6050_RA_FF_DUR, duration); +} + +// MOT_THR register + +/** Get motion detection event acceleration threshold. + * This register configures the detection threshold for Motion interrupt + * generation. The unit of MOT_THR is 1LSB = 2mg. Motion is detected when the + * absolute value of any of the accelerometer measurements exceeds this Motion + * detection threshold. This condition increments the Motion detection duration + * counter (Register 32). The Motion detection interrupt is triggered when the + * Motion Detection counter reaches the time count specified in MOT_DUR + * (Register 32). + * + * The Motion interrupt will indicate the axis and polarity of detected motion + * in MOT_DETECT_STATUS (Register 97). + * + * For more details on the Motion detection interrupt, see Section 8.3 of the + * MPU-6000/MPU-6050 Product Specification document as well as Registers 56 and + * 58 of this document. + * + * @return Current motion detection acceleration threshold value (LSB = 2mg) + * @see MPU6050_RA_MOT_THR + */ +uint8_t MPU6050::getMotionDetectionThreshold() +{ + I2Cdev::readByte(devAddr, MPU6050_RA_MOT_THR, buffer); + return buffer[0]; +} +/** Set motion detection event acceleration threshold. + * @param threshold New motion detection acceleration threshold value (LSB = 2mg) + * @see getMotionDetectionThreshold() + * @see MPU6050_RA_MOT_THR + */ +void MPU6050::setMotionDetectionThreshold(uint8_t threshold) +{ + I2Cdev::writeByte(devAddr, MPU6050_RA_MOT_THR, threshold); +} + +// MOT_DUR register + +/** Get motion detection event duration threshold. + * This register configures the duration counter threshold for Motion interrupt + * generation. The duration counter ticks at 1 kHz, therefore MOT_DUR has a unit + * of 1LSB = 1ms. The Motion detection duration counter increments when the + * absolute value of any of the accelerometer measurements exceeds the Motion + * detection threshold (Register 31). The Motion detection interrupt is + * triggered when the Motion detection counter reaches the time count specified + * in this register. + * + * For more details on the Motion detection interrupt, see Section 8.3 of the + * MPU-6000/MPU-6050 Product Specification document. + * + * @return Current motion detection duration threshold value (LSB = 1ms) + * @see MPU6050_RA_MOT_DUR + */ +uint8_t MPU6050::getMotionDetectionDuration() +{ + I2Cdev::readByte(devAddr, MPU6050_RA_MOT_DUR, buffer); + return buffer[0]; +} +/** Set motion detection event duration threshold. + * @param duration New motion detection duration threshold value (LSB = 1ms) + * @see getMotionDetectionDuration() + * @see MPU6050_RA_MOT_DUR + */ +void MPU6050::setMotionDetectionDuration(uint8_t duration) +{ + I2Cdev::writeByte(devAddr, MPU6050_RA_MOT_DUR, duration); +} + +// ZRMOT_THR register + +/** Get zero motion detection event acceleration threshold. + * This register configures the detection threshold for Zero Motion interrupt + * generation. The unit of ZRMOT_THR is 1LSB = 2mg. Zero Motion is detected when + * the absolute value of the accelerometer measurements for the 3 axes are each + * less than the detection threshold. This condition increments the Zero Motion + * duration counter (Register 34). The Zero Motion interrupt is triggered when + * the Zero Motion duration counter reaches the time count specified in + * ZRMOT_DUR (Register 34). + * + * Unlike Free Fall or Motion detection, Zero Motion detection triggers an + * interrupt both when Zero Motion is first detected and when Zero Motion is no + * longer detected. + * + * When a zero motion event is detected, a Zero Motion Status will be indicated + * in the MOT_DETECT_STATUS register (Register 97). When a motion-to-zero-motion + * condition is detected, the status bit is set to 1. When a zero-motion-to- + * motion condition is detected, the status bit is set to 0. + * + * For more details on the Zero Motion detection interrupt, see Section 8.4 of + * the MPU-6000/MPU-6050 Product Specification document as well as Registers 56 + * and 58 of this document. + * + * @return Current zero motion detection acceleration threshold value (LSB = 2mg) + * @see MPU6050_RA_ZRMOT_THR + */ +uint8_t MPU6050::getZeroMotionDetectionThreshold() +{ + I2Cdev::readByte(devAddr, MPU6050_RA_ZRMOT_THR, buffer); + return buffer[0]; +} +/** Set zero motion detection event acceleration threshold. + * @param threshold New zero motion detection acceleration threshold value (LSB = 2mg) + * @see getZeroMotionDetectionThreshold() + * @see MPU6050_RA_ZRMOT_THR + */ +void MPU6050::setZeroMotionDetectionThreshold(uint8_t threshold) +{ + I2Cdev::writeByte(devAddr, MPU6050_RA_ZRMOT_THR, threshold); +} + +// ZRMOT_DUR register + +/** Get zero motion detection event duration threshold. + * This register configures the duration counter threshold for Zero Motion + * interrupt generation. The duration counter ticks at 16 Hz, therefore + * ZRMOT_DUR has a unit of 1 LSB = 64 ms. The Zero Motion duration counter + * increments while the absolute value of the accelerometer measurements are + * each less than the detection threshold (Register 33). The Zero Motion + * interrupt is triggered when the Zero Motion duration counter reaches the time + * count specified in this register. + * + * For more details on the Zero Motion detection interrupt, see Section 8.4 of + * the MPU-6000/MPU-6050 Product Specification document, as well as Registers 56 + * and 58 of this document. + * + * @return Current zero motion detection duration threshold value (LSB = 64ms) + * @see MPU6050_RA_ZRMOT_DUR + */ +uint8_t MPU6050::getZeroMotionDetectionDuration() +{ + I2Cdev::readByte(devAddr, MPU6050_RA_ZRMOT_DUR, buffer); + return buffer[0]; +} +/** Set zero motion detection event duration threshold. + * @param duration New zero motion detection duration threshold value (LSB = 1ms) + * @see getZeroMotionDetectionDuration() + * @see MPU6050_RA_ZRMOT_DUR + */ +void MPU6050::setZeroMotionDetectionDuration(uint8_t duration) +{ + I2Cdev::writeByte(devAddr, MPU6050_RA_ZRMOT_DUR, duration); +} + +// FIFO_EN register + +/** Get temperature FIFO enabled value. + * When set to 1, this bit enables TEMP_OUT_H and TEMP_OUT_L (Registers 65 and + * 66) to be written into the FIFO buffer. + * @return Current temperature FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050::getTempFIFOEnabled() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_TEMP_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set temperature FIFO enabled value. + * @param enabled New temperature FIFO enabled value + * @see getTempFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050::setTempFIFOEnabled(bool enabled) +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_TEMP_FIFO_EN_BIT, enabled); +} +/** Get gyroscope X-axis FIFO enabled value. + * When set to 1, this bit enables GYRO_XOUT_H and GYRO_XOUT_L (Registers 67 and + * 68) to be written into the FIFO buffer. + * @return Current gyroscope X-axis FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050::getXGyroFIFOEnabled() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_XG_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set gyroscope X-axis FIFO enabled value. + * @param enabled New gyroscope X-axis FIFO enabled value + * @see getXGyroFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050::setXGyroFIFOEnabled(bool enabled) +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_XG_FIFO_EN_BIT, enabled); +} +/** Get gyroscope Y-axis FIFO enabled value. + * When set to 1, this bit enables GYRO_YOUT_H and GYRO_YOUT_L (Registers 69 and + * 70) to be written into the FIFO buffer. + * @return Current gyroscope Y-axis FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050::getYGyroFIFOEnabled() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_YG_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set gyroscope Y-axis FIFO enabled value. + * @param enabled New gyroscope Y-axis FIFO enabled value + * @see getYGyroFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050::setYGyroFIFOEnabled(bool enabled) +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_YG_FIFO_EN_BIT, enabled); +} +/** Get gyroscope Z-axis FIFO enabled value. + * When set to 1, this bit enables GYRO_ZOUT_H and GYRO_ZOUT_L (Registers 71 and + * 72) to be written into the FIFO buffer. + * @return Current gyroscope Z-axis FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050::getZGyroFIFOEnabled() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ZG_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set gyroscope Z-axis FIFO enabled value. + * @param enabled New gyroscope Z-axis FIFO enabled value + * @see getZGyroFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050::setZGyroFIFOEnabled(bool enabled) +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ZG_FIFO_EN_BIT, enabled); +} +/** Get accelerometer FIFO enabled value. + * When set to 1, this bit enables ACCEL_XOUT_H, ACCEL_XOUT_L, ACCEL_YOUT_H, + * ACCEL_YOUT_L, ACCEL_ZOUT_H, and ACCEL_ZOUT_L (Registers 59 to 64) to be + * written into the FIFO buffer. + * @return Current accelerometer FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050::getAccelFIFOEnabled() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ACCEL_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set accelerometer FIFO enabled value. + * @param enabled New accelerometer FIFO enabled value + * @see getAccelFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050::setAccelFIFOEnabled(bool enabled) +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ACCEL_FIFO_EN_BIT, enabled); +} +/** Get Slave 2 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 2 to be written into the FIFO buffer. + * @return Current Slave 2 FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050::getSlave2FIFOEnabled() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV2_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set Slave 2 FIFO enabled value. + * @param enabled New Slave 2 FIFO enabled value + * @see getSlave2FIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050::setSlave2FIFOEnabled(bool enabled) +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV2_FIFO_EN_BIT, enabled); +} +/** Get Slave 1 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 1 to be written into the FIFO buffer. + * @return Current Slave 1 FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050::getSlave1FIFOEnabled() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV1_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set Slave 1 FIFO enabled value. + * @param enabled New Slave 1 FIFO enabled value + * @see getSlave1FIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050::setSlave1FIFOEnabled(bool enabled) +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV1_FIFO_EN_BIT, enabled); +} +/** Get Slave 0 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 0 to be written into the FIFO buffer. + * @return Current Slave 0 FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050::getSlave0FIFOEnabled() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV0_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set Slave 0 FIFO enabled value. + * @param enabled New Slave 0 FIFO enabled value + * @see getSlave0FIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050::setSlave0FIFOEnabled(bool enabled) +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV0_FIFO_EN_BIT, enabled); +} + +// I2C_MST_CTRL register + +/** Get multi-master enabled value. + * Multi-master capability allows multiple I2C masters to operate on the same + * bus. In circuits where multi-master capability is required, set MULT_MST_EN + * to 1. This will increase current drawn by approximately 30uA. + * + * In circuits where multi-master capability is required, the state of the I2C + * bus must always be monitored by each separate I2C Master. Before an I2C + * Master can assume arbitration of the bus, it must first confirm that no other + * I2C Master has arbitration of the bus. When MULT_MST_EN is set to 1, the + * MPU-60X0's bus arbitration detection logic is turned on, enabling it to + * detect when the bus is available. + * + * @return Current multi-master enabled value + * @see MPU6050_RA_I2C_MST_CTRL + */ +bool MPU6050::getMultiMasterEnabled() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_MULT_MST_EN_BIT, buffer); + return buffer[0]; +} +/** Set multi-master enabled value. + * @param enabled New multi-master enabled value + * @see getMultiMasterEnabled() + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050::setMultiMasterEnabled(bool enabled) +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_MULT_MST_EN_BIT, enabled); +} +/** Get wait-for-external-sensor-data enabled value. + * When the WAIT_FOR_ES bit is set to 1, the Data Ready interrupt will be + * delayed until External Sensor data from the Slave Devices are loaded into the + * EXT_SENS_DATA registers. This is used to ensure that both the internal sensor + * data (i.e. from gyro and accel) and external sensor data have been loaded to + * their respective data registers (i.e. the data is synced) when the Data Ready + * interrupt is triggered. + * + * @return Current wait-for-external-sensor-data enabled value + * @see MPU6050_RA_I2C_MST_CTRL + */ +bool MPU6050::getWaitForExternalSensorEnabled() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_WAIT_FOR_ES_BIT, buffer); + return buffer[0]; +} +/** Set wait-for-external-sensor-data enabled value. + * @param enabled New wait-for-external-sensor-data enabled value + * @see getWaitForExternalSensorEnabled() + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050::setWaitForExternalSensorEnabled(bool enabled) +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_WAIT_FOR_ES_BIT, enabled); +} +/** Get Slave 3 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 3 to be written into the FIFO buffer. + * @return Current Slave 3 FIFO enabled value + * @see MPU6050_RA_MST_CTRL + */ +bool MPU6050::getSlave3FIFOEnabled() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_SLV_3_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set Slave 3 FIFO enabled value. + * @param enabled New Slave 3 FIFO enabled value + * @see getSlave3FIFOEnabled() + * @see MPU6050_RA_MST_CTRL + */ +void MPU6050::setSlave3FIFOEnabled(bool enabled) +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_SLV_3_FIFO_EN_BIT, enabled); +} +/** Get slave read/write transition enabled value. + * The I2C_MST_P_NSR bit configures the I2C Master's transition from one slave + * read to the next slave read. If the bit equals 0, there will be a restart + * between reads. If the bit equals 1, there will be a stop followed by a start + * of the following read. When a write transaction follows a read transaction, + * the stop followed by a start of the successive write will be always used. + * + * @return Current slave read/write transition enabled value + * @see MPU6050_RA_I2C_MST_CTRL + */ +bool MPU6050::getSlaveReadWriteTransitionEnabled() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_P_NSR_BIT, buffer); + return buffer[0]; +} +/** Set slave read/write transition enabled value. + * @param enabled New slave read/write transition enabled value + * @see getSlaveReadWriteTransitionEnabled() + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050::setSlaveReadWriteTransitionEnabled(bool enabled) +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_P_NSR_BIT, enabled); +} +/** Get I2C master clock speed. + * I2C_MST_CLK is a 4 bit unsigned value which configures a divider on the + * MPU-60X0 internal 8MHz clock. It sets the I2C master clock speed according to + * the following table: + * + *
+ * I2C_MST_CLK | I2C Master Clock Speed | 8MHz Clock Divider
+ * ------------+------------------------+-------------------
+ * 0           | 348kHz                 | 23
+ * 1           | 333kHz                 | 24
+ * 2           | 320kHz                 | 25
+ * 3           | 308kHz                 | 26
+ * 4           | 296kHz                 | 27
+ * 5           | 286kHz                 | 28
+ * 6           | 276kHz                 | 29
+ * 7           | 267kHz                 | 30
+ * 8           | 258kHz                 | 31
+ * 9           | 500kHz                 | 16
+ * 10          | 471kHz                 | 17
+ * 11          | 444kHz                 | 18
+ * 12          | 421kHz                 | 19
+ * 13          | 400kHz                 | 20
+ * 14          | 381kHz                 | 21
+ * 15          | 364kHz                 | 22
+ * 
+ * + * @return Current I2C master clock speed + * @see MPU6050_RA_I2C_MST_CTRL + */ +uint8_t MPU6050::getMasterClockSpeed() +{ + I2Cdev::readBits(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_CLK_BIT, MPU6050_I2C_MST_CLK_LENGTH, buffer); + return buffer[0]; +} +/** Set I2C master clock speed. + * @reparam speed Current I2C master clock speed + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050::setMasterClockSpeed(uint8_t speed) +{ + I2Cdev::writeBits(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_CLK_BIT, MPU6050_I2C_MST_CLK_LENGTH, speed); +} + +// I2C_SLV* registers (Slave 0-3) + +/** Get the I2C address of the specified slave (0-3). + * Note that Bit 7 (MSB) controls read/write mode. If Bit 7 is set, it's a read + * operation, and if it is cleared, then it's a write operation. The remaining + * bits (6-0) are the 7-bit device address of the slave device. + * + * In read mode, the result of the read is placed in the lowest available + * EXT_SENS_DATA register. For further information regarding the allocation of + * read results, please refer to the EXT_SENS_DATA register description + * (Registers 73 - 96). + * + * The MPU-6050 supports a total of five slaves, but Slave 4 has unique + * characteristics, and so it has its own functions (getSlave4* and setSlave4*). + * + * I2C data transactions are performed at the Sample Rate, as defined in + * Register 25. The user is responsible for ensuring that I2C data transactions + * to and from each enabled Slave can be completed within a single period of the + * Sample Rate. + * + * The I2C slave access rate can be reduced relative to the Sample Rate. This + * reduced access rate is determined by I2C_MST_DLY (Register 52). Whether a + * slave's access rate is reduced relative to the Sample Rate is determined by + * I2C_MST_DELAY_CTRL (Register 103). + * + * The processing order for the slaves is fixed. The sequence followed for + * processing the slaves is Slave 0, Slave 1, Slave 2, Slave 3 and Slave 4. If a + * particular Slave is disabled it will be skipped. + * + * Each slave can either be accessed at the sample rate or at a reduced sample + * rate. In a case where some slaves are accessed at the Sample Rate and some + * slaves are accessed at the reduced rate, the sequence of accessing the slaves + * (Slave 0 to Slave 4) is still followed. However, the reduced rate slaves will + * be skipped if their access rate dictates that they should not be accessed + * during that particular cycle. For further information regarding the reduced + * access rate, please refer to Register 52. Whether a slave is accessed at the + * Sample Rate or at the reduced rate is determined by the Delay Enable bits in + * Register 103. + * + * @param num Slave number (0-3) + * @return Current address for specified slave + * @see MPU6050_RA_I2C_SLV0_ADDR + */ +uint8_t MPU6050::getSlaveAddress(uint8_t num) +{ + if (num > 3) + return 0; + I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV0_ADDR + num * 3, buffer); + return buffer[0]; +} +/** Set the I2C address of the specified slave (0-3). + * @param num Slave number (0-3) + * @param address New address for specified slave + * @see getSlaveAddress() + * @see MPU6050_RA_I2C_SLV0_ADDR + */ +void MPU6050::setSlaveAddress(uint8_t num, uint8_t address) +{ + if (num > 3) + return; + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV0_ADDR + num * 3, address); +} +/** Get the active internal register for the specified slave (0-3). + * Read/write operations for this slave will be done to whatever internal + * register address is stored in this MPU register. + * + * The MPU-6050 supports a total of five slaves, but Slave 4 has unique + * characteristics, and so it has its own functions. + * + * @param num Slave number (0-3) + * @return Current active register for specified slave + * @see MPU6050_RA_I2C_SLV0_REG + */ +uint8_t MPU6050::getSlaveRegister(uint8_t num) +{ + if (num > 3) + return 0; + I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV0_REG + num * 3, buffer); + return buffer[0]; +} +/** Set the active internal register for the specified slave (0-3). + * @param num Slave number (0-3) + * @param reg New active register for specified slave + * @see getSlaveRegister() + * @see MPU6050_RA_I2C_SLV0_REG + */ +void MPU6050::setSlaveRegister(uint8_t num, uint8_t reg) +{ + if (num > 3) + return; + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV0_REG + num * 3, reg); +} +/** Get the enabled value for the specified slave (0-3). + * When set to 1, this bit enables Slave 0 for data transfer operations. When + * cleared to 0, this bit disables Slave 0 from data transfer operations. + * @param num Slave number (0-3) + * @return Current enabled value for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +bool MPU6050::getSlaveEnabled(uint8_t num) +{ + if (num > 3) + return 0; + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num * 3, MPU6050_I2C_SLV_EN_BIT, buffer); + return buffer[0]; +} +/** Set the enabled value for the specified slave (0-3). + * @param num Slave number (0-3) + * @param enabled New enabled value for specified slave + * @see getSlaveEnabled() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050::setSlaveEnabled(uint8_t num, bool enabled) +{ + if (num > 3) + return; + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num * 3, MPU6050_I2C_SLV_EN_BIT, enabled); +} +/** Get word pair byte-swapping enabled for the specified slave (0-3). + * When set to 1, this bit enables byte swapping. When byte swapping is enabled, + * the high and low bytes of a word pair are swapped. Please refer to + * I2C_SLV0_GRP for the pairing convention of the word pairs. When cleared to 0, + * bytes transferred to and from Slave 0 will be written to EXT_SENS_DATA + * registers in the order they were transferred. + * + * @param num Slave number (0-3) + * @return Current word pair byte-swapping enabled value for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +bool MPU6050::getSlaveWordByteSwap(uint8_t num) +{ + if (num > 3) + return 0; + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num * 3, MPU6050_I2C_SLV_BYTE_SW_BIT, buffer); + return buffer[0]; +} +/** Set word pair byte-swapping enabled for the specified slave (0-3). + * @param num Slave number (0-3) + * @param enabled New word pair byte-swapping enabled value for specified slave + * @see getSlaveWordByteSwap() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050::setSlaveWordByteSwap(uint8_t num, bool enabled) +{ + if (num > 3) + return; + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num * 3, MPU6050_I2C_SLV_BYTE_SW_BIT, enabled); +} +/** Get write mode for the specified slave (0-3). + * When set to 1, the transaction will read or write data only. When cleared to + * 0, the transaction will write a register address prior to reading or writing + * data. This should equal 0 when specifying the register address within the + * Slave device to/from which the ensuing data transaction will take place. + * + * @param num Slave number (0-3) + * @return Current write mode for specified slave (0 = register address + data, 1 = data only) + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +bool MPU6050::getSlaveWriteMode(uint8_t num) +{ + if (num > 3) + return 0; + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num * 3, MPU6050_I2C_SLV_REG_DIS_BIT, buffer); + return buffer[0]; +} +/** Set write mode for the specified slave (0-3). + * @param num Slave number (0-3) + * @param mode New write mode for specified slave (0 = register address + data, 1 = data only) + * @see getSlaveWriteMode() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050::setSlaveWriteMode(uint8_t num, bool mode) +{ + if (num > 3) + return; + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num * 3, MPU6050_I2C_SLV_REG_DIS_BIT, mode); +} +/** Get word pair grouping order offset for the specified slave (0-3). + * This sets specifies the grouping order of word pairs received from registers. + * When cleared to 0, bytes from register addresses 0 and 1, 2 and 3, etc (even, + * then odd register addresses) are paired to form a word. When set to 1, bytes + * from register addresses are paired 1 and 2, 3 and 4, etc. (odd, then even + * register addresses) are paired to form a word. + * + * @param num Slave number (0-3) + * @return Current word pair grouping order offset for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +bool MPU6050::getSlaveWordGroupOffset(uint8_t num) +{ + if (num > 3) + return 0; + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num * 3, MPU6050_I2C_SLV_GRP_BIT, buffer); + return buffer[0]; +} +/** Set word pair grouping order offset for the specified slave (0-3). + * @param num Slave number (0-3) + * @param enabled New word pair grouping order offset for specified slave + * @see getSlaveWordGroupOffset() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050::setSlaveWordGroupOffset(uint8_t num, bool enabled) +{ + if (num > 3) + return; + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num * 3, MPU6050_I2C_SLV_GRP_BIT, enabled); +} +/** Get number of bytes to read for the specified slave (0-3). + * Specifies the number of bytes transferred to and from Slave 0. Clearing this + * bit to 0 is equivalent to disabling the register by writing 0 to I2C_SLV0_EN. + * @param num Slave number (0-3) + * @return Number of bytes to read for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +uint8_t MPU6050::getSlaveDataLength(uint8_t num) +{ + if (num > 3) + return 0; + I2Cdev::readBits(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num * 3, MPU6050_I2C_SLV_LEN_BIT, MPU6050_I2C_SLV_LEN_LENGTH, buffer); + return buffer[0]; +} +/** Set number of bytes to read for the specified slave (0-3). + * @param num Slave number (0-3) + * @param length Number of bytes to read for specified slave + * @see getSlaveDataLength() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050::setSlaveDataLength(uint8_t num, uint8_t length) +{ + if (num > 3) + return; + I2Cdev::writeBits(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num * 3, MPU6050_I2C_SLV_LEN_BIT, MPU6050_I2C_SLV_LEN_LENGTH, length); +} + +// I2C_SLV* registers (Slave 4) + +/** Get the I2C address of Slave 4. + * Note that Bit 7 (MSB) controls read/write mode. If Bit 7 is set, it's a read + * operation, and if it is cleared, then it's a write operation. The remaining + * bits (6-0) are the 7-bit device address of the slave device. + * + * @return Current address for Slave 4 + * @see getSlaveAddress() + * @see MPU6050_RA_I2C_SLV4_ADDR + */ +uint8_t MPU6050::getSlave4Address() +{ + I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV4_ADDR, buffer); + return buffer[0]; +} +/** Set the I2C address of Slave 4. + * @param address New address for Slave 4 + * @see getSlave4Address() + * @see MPU6050_RA_I2C_SLV4_ADDR + */ +void MPU6050::setSlave4Address(uint8_t address) +{ + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV4_ADDR, address); +} +/** Get the active internal register for the Slave 4. + * Read/write operations for this slave will be done to whatever internal + * register address is stored in this MPU register. + * + * @return Current active register for Slave 4 + * @see MPU6050_RA_I2C_SLV4_REG + */ +uint8_t MPU6050::getSlave4Register() +{ + I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV4_REG, buffer); + return buffer[0]; +} +/** Set the active internal register for Slave 4. + * @param reg New active register for Slave 4 + * @see getSlave4Register() + * @see MPU6050_RA_I2C_SLV4_REG + */ +void MPU6050::setSlave4Register(uint8_t reg) +{ + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV4_REG, reg); +} +/** Set new byte to write to Slave 4. + * This register stores the data to be written into the Slave 4. If I2C_SLV4_RW + * is set 1 (set to read), this register has no effect. + * @param data New byte to write to Slave 4 + * @see MPU6050_RA_I2C_SLV4_DO + */ +void MPU6050::setSlave4OutputByte(uint8_t data) +{ + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV4_DO, data); +} +/** Get the enabled value for the Slave 4. + * When set to 1, this bit enables Slave 4 for data transfer operations. When + * cleared to 0, this bit disables Slave 4 from data transfer operations. + * @return Current enabled value for Slave 4 + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +bool MPU6050::getSlave4Enabled() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_EN_BIT, buffer); + return buffer[0]; +} +/** Set the enabled value for Slave 4. + * @param enabled New enabled value for Slave 4 + * @see getSlave4Enabled() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050::setSlave4Enabled(bool enabled) +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_EN_BIT, enabled); +} +/** Get the enabled value for Slave 4 transaction interrupts. + * When set to 1, this bit enables the generation of an interrupt signal upon + * completion of a Slave 4 transaction. When cleared to 0, this bit disables the + * generation of an interrupt signal upon completion of a Slave 4 transaction. + * The interrupt status can be observed in Register 54. + * + * @return Current enabled value for Slave 4 transaction interrupts. + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +bool MPU6050::getSlave4InterruptEnabled() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_INT_EN_BIT, buffer); + return buffer[0]; +} +/** Set the enabled value for Slave 4 transaction interrupts. + * @param enabled New enabled value for Slave 4 transaction interrupts. + * @see getSlave4InterruptEnabled() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050::setSlave4InterruptEnabled(bool enabled) +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_INT_EN_BIT, enabled); +} +/** Get write mode for Slave 4. + * When set to 1, the transaction will read or write data only. When cleared to + * 0, the transaction will write a register address prior to reading or writing + * data. This should equal 0 when specifying the register address within the + * Slave device to/from which the ensuing data transaction will take place. + * + * @return Current write mode for Slave 4 (0 = register address + data, 1 = data only) + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +bool MPU6050::getSlave4WriteMode() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_REG_DIS_BIT, buffer); + return buffer[0]; +} +/** Set write mode for the Slave 4. + * @param mode New write mode for Slave 4 (0 = register address + data, 1 = data only) + * @see getSlave4WriteMode() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050::setSlave4WriteMode(bool mode) +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_REG_DIS_BIT, mode); +} +/** Get Slave 4 master delay value. + * This configures the reduced access rate of I2C slaves relative to the Sample + * Rate. When a slave's access rate is decreased relative to the Sample Rate, + * the slave is accessed every: + * + * 1 / (1 + I2C_MST_DLY) samples + * + * This base Sample Rate in turn is determined by SMPLRT_DIV (register 25) and + * DLPF_CFG (register 26). Whether a slave's access rate is reduced relative to + * the Sample Rate is determined by I2C_MST_DELAY_CTRL (register 103). For + * further information regarding the Sample Rate, please refer to register 25. + * + * @return Current Slave 4 master delay value + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +uint8_t MPU6050::getSlave4MasterDelay() +{ + I2Cdev::readBits(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_MST_DLY_BIT, MPU6050_I2C_SLV4_MST_DLY_LENGTH, buffer); + return buffer[0]; +} +/** Set Slave 4 master delay value. + * @param delay New Slave 4 master delay value + * @see getSlave4MasterDelay() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050::setSlave4MasterDelay(uint8_t delay) +{ + I2Cdev::writeBits(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_MST_DLY_BIT, MPU6050_I2C_SLV4_MST_DLY_LENGTH, delay); +} +/** Get last available byte read from Slave 4. + * This register stores the data read from Slave 4. This field is populated + * after a read transaction. + * @return Last available byte read from to Slave 4 + * @see MPU6050_RA_I2C_SLV4_DI + */ +uint8_t MPU6050::getSlate4InputByte() +{ + I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV4_DI, buffer); + return buffer[0]; +} + +// I2C_MST_STATUS register + +/** Get FSYNC interrupt status. + * This bit reflects the status of the FSYNC interrupt from an external device + * into the MPU-60X0. This is used as a way to pass an external interrupt + * through the MPU-60X0 to the host application processor. When set to 1, this + * bit will cause an interrupt if FSYNC_INT_EN is asserted in INT_PIN_CFG + * (Register 55). + * @return FSYNC interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050::getPassthroughStatus() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_PASS_THROUGH_BIT, buffer); + return buffer[0]; +} +/** Get Slave 4 transaction done status. + * Automatically sets to 1 when a Slave 4 transaction has completed. This + * triggers an interrupt if the I2C_MST_INT_EN bit in the INT_ENABLE register + * (Register 56) is asserted and if the SLV_4_DONE_INT bit is asserted in the + * I2C_SLV4_CTRL register (Register 52). + * @return Slave 4 transaction done status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050::getSlave4IsDone() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV4_DONE_BIT, buffer); + return buffer[0]; +} +/** Get master arbitration lost status. + * This bit automatically sets to 1 when the I2C Master has lost arbitration of + * the auxiliary I2C bus (an error condition). This triggers an interrupt if the + * I2C_MST_INT_EN bit in the INT_ENABLE register (Register 56) is asserted. + * @return Master arbitration lost status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050::getLostArbitration() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_LOST_ARB_BIT, buffer); + return buffer[0]; +} +/** Get Slave 4 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 4. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 4 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050::getSlave4Nack() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV4_NACK_BIT, buffer); + return buffer[0]; +} +/** Get Slave 3 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 3. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 3 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050::getSlave3Nack() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV3_NACK_BIT, buffer); + return buffer[0]; +} +/** Get Slave 2 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 2. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 2 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050::getSlave2Nack() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV2_NACK_BIT, buffer); + return buffer[0]; +} +/** Get Slave 1 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 1. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 1 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050::getSlave1Nack() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV1_NACK_BIT, buffer); + return buffer[0]; +} +/** Get Slave 0 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 0. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 0 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050::getSlave0Nack() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV0_NACK_BIT, buffer); + return buffer[0]; +} + +// INT_PIN_CFG register + +/** Get interrupt logic level mode. + * Will be set 0 for active-high, 1 for active-low. + * @return Current interrupt mode (0=active-high, 1=active-low) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_LEVEL_BIT + */ +bool MPU6050::getInterruptMode() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_LEVEL_BIT, buffer); + return buffer[0]; +} +/** Set interrupt logic level mode. + * @param mode New interrupt mode (0=active-high, 1=active-low) + * @see getInterruptMode() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_LEVEL_BIT + */ +void MPU6050::setInterruptMode(bool mode) +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_LEVEL_BIT, mode); +} +/** Get interrupt drive mode. + * Will be set 0 for push-pull, 1 for open-drain. + * @return Current interrupt drive mode (0=push-pull, 1=open-drain) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_OPEN_BIT + */ +bool MPU6050::getInterruptDrive() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_OPEN_BIT, buffer); + return buffer[0]; +} +/** Set interrupt drive mode. + * @param drive New interrupt drive mode (0=push-pull, 1=open-drain) + * @see getInterruptDrive() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_OPEN_BIT + */ +void MPU6050::setInterruptDrive(bool drive) +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_OPEN_BIT, drive); +} +/** Get interrupt latch mode. + * Will be set 0 for 50us-pulse, 1 for latch-until-int-cleared. + * @return Current latch mode (0=50us-pulse, 1=latch-until-int-cleared) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_LATCH_INT_EN_BIT + */ +bool MPU6050::getInterruptLatch() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_LATCH_INT_EN_BIT, buffer); + return buffer[0]; +} +/** Set interrupt latch mode. + * @param latch New latch mode (0=50us-pulse, 1=latch-until-int-cleared) + * @see getInterruptLatch() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_LATCH_INT_EN_BIT + */ +void MPU6050::setInterruptLatch(bool latch) +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_LATCH_INT_EN_BIT, latch); +} +/** Get interrupt latch clear mode. + * Will be set 0 for status-read-only, 1 for any-register-read. + * @return Current latch clear mode (0=status-read-only, 1=any-register-read) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_RD_CLEAR_BIT + */ +bool MPU6050::getInterruptLatchClear() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_RD_CLEAR_BIT, buffer); + return buffer[0]; +} +/** Set interrupt latch clear mode. + * @param clear New latch clear mode (0=status-read-only, 1=any-register-read) + * @see getInterruptLatchClear() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_RD_CLEAR_BIT + */ +void MPU6050::setInterruptLatchClear(bool clear) +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_RD_CLEAR_BIT, clear); +} +/** Get FSYNC interrupt logic level mode. + * @return Current FSYNC interrupt mode (0=active-high, 1=active-low) + * @see getFSyncInterruptMode() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT + */ +bool MPU6050::getFSyncInterruptLevel() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT, buffer); + return buffer[0]; +} +/** Set FSYNC interrupt logic level mode. + * @param mode New FSYNC interrupt mode (0=active-high, 1=active-low) + * @see getFSyncInterruptMode() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT + */ +void MPU6050::setFSyncInterruptLevel(bool level) +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT, level); +} +/** Get FSYNC pin interrupt enabled setting. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled setting + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_EN_BIT + */ +bool MPU6050::getFSyncInterruptEnabled() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_EN_BIT, buffer); + return buffer[0]; +} +/** Set FSYNC pin interrupt enabled setting. + * @param enabled New FSYNC pin interrupt enabled setting + * @see getFSyncInterruptEnabled() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_EN_BIT + */ +void MPU6050::setFSyncInterruptEnabled(bool enabled) +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_EN_BIT, enabled); +} +/** Get I2C bypass enabled status. + * When this bit is equal to 1 and I2C_MST_EN (Register 106 bit[5]) is equal to + * 0, the host application processor will be able to directly access the + * auxiliary I2C bus of the MPU-60X0. When this bit is equal to 0, the host + * application processor will not be able to directly access the auxiliary I2C + * bus of the MPU-60X0 regardless of the state of I2C_MST_EN (Register 106 + * bit[5]). + * @return Current I2C bypass enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_I2C_BYPASS_EN_BIT + */ +bool MPU6050::getI2CBypassEnabled() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_I2C_BYPASS_EN_BIT, buffer); + return buffer[0]; +} +/** Set I2C bypass enabled status. + * When this bit is equal to 1 and I2C_MST_EN (Register 106 bit[5]) is equal to + * 0, the host application processor will be able to directly access the + * auxiliary I2C bus of the MPU-60X0. When this bit is equal to 0, the host + * application processor will not be able to directly access the auxiliary I2C + * bus of the MPU-60X0 regardless of the state of I2C_MST_EN (Register 106 + * bit[5]). + * @param enabled New I2C bypass enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_I2C_BYPASS_EN_BIT + */ +void MPU6050::setI2CBypassEnabled(bool enabled) +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_I2C_BYPASS_EN_BIT, enabled); +} +/** Get reference clock output enabled status. + * When this bit is equal to 1, a reference clock output is provided at the + * CLKOUT pin. When this bit is equal to 0, the clock output is disabled. For + * further information regarding CLKOUT, please refer to the MPU-60X0 Product + * Specification document. + * @return Current reference clock output enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_CLKOUT_EN_BIT + */ +bool MPU6050::getClockOutputEnabled() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_CLKOUT_EN_BIT, buffer); + return buffer[0]; +} +/** Set reference clock output enabled status. + * When this bit is equal to 1, a reference clock output is provided at the + * CLKOUT pin. When this bit is equal to 0, the clock output is disabled. For + * further information regarding CLKOUT, please refer to the MPU-60X0 Product + * Specification document. + * @param enabled New reference clock output enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_CLKOUT_EN_BIT + */ +void MPU6050::setClockOutputEnabled(bool enabled) +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_CLKOUT_EN_BIT, enabled); +} + +// INT_ENABLE register + +/** Get full interrupt enabled status. + * Full register byte for all interrupts, for quick reading. Each bit will be + * set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +uint8_t MPU6050::getIntEnabled() +{ + I2Cdev::readByte(devAddr, MPU6050_RA_INT_ENABLE, buffer); + return buffer[0]; +} +/** Set full interrupt enabled status. + * Full register byte for all interrupts, for quick reading. Each bit should be + * set 0 for disabled, 1 for enabled. + * @param enabled New interrupt enabled status + * @see getIntFreefallEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +void MPU6050::setIntEnabled(uint8_t enabled) +{ + I2Cdev::writeByte(devAddr, MPU6050_RA_INT_ENABLE, enabled); +} +/** Get Free Fall interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +bool MPU6050::getIntFreefallEnabled() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FF_BIT, buffer); + return buffer[0]; +} +/** Set Free Fall interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntFreefallEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +void MPU6050::setIntFreefallEnabled(bool enabled) +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FF_BIT, enabled); +} +/** Get Motion Detection interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_MOT_BIT + **/ +bool MPU6050::getIntMotionEnabled() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_MOT_BIT, buffer); + return buffer[0]; +} +/** Set Motion Detection interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntMotionEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_MOT_BIT + **/ +void MPU6050::setIntMotionEnabled(bool enabled) +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_MOT_BIT, enabled); +} +/** Get Zero Motion Detection interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_ZMOT_BIT + **/ +bool MPU6050::getIntZeroMotionEnabled() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_ZMOT_BIT, buffer); + return buffer[0]; +} +/** Set Zero Motion Detection interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntZeroMotionEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_ZMOT_BIT + **/ +void MPU6050::setIntZeroMotionEnabled(bool enabled) +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_ZMOT_BIT, enabled); +} +/** Get FIFO Buffer Overflow interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT + **/ +bool MPU6050::getIntFIFOBufferOverflowEnabled() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, buffer); + return buffer[0]; +} +/** Set FIFO Buffer Overflow interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntFIFOBufferOverflowEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT + **/ +void MPU6050::setIntFIFOBufferOverflowEnabled(bool enabled) +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, enabled); +} +/** Get I2C Master interrupt enabled status. + * This enables any of the I2C Master interrupt sources to generate an + * interrupt. Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT + **/ +bool MPU6050::getIntI2CMasterEnabled() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_I2C_MST_INT_BIT, buffer); + return buffer[0]; +} +/** Set I2C Master interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntI2CMasterEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT + **/ +void MPU6050::setIntI2CMasterEnabled(bool enabled) +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_I2C_MST_INT_BIT, enabled); +} +/** Get Data Ready interrupt enabled setting. + * This event occurs each time a write operation to all of the sensor registers + * has been completed. Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_DATA_RDY_BIT + */ +bool MPU6050::getIntDataReadyEnabled() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DATA_RDY_BIT, buffer); + return buffer[0]; +} +/** Set Data Ready interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntDataReadyEnabled() + * @see MPU6050_RA_INT_CFG + * @see MPU6050_INTERRUPT_DATA_RDY_BIT + */ +void MPU6050::setIntDataReadyEnabled(bool enabled) +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DATA_RDY_BIT, enabled); +} + +// INT_STATUS register + +/** Get full set of interrupt status bits. + * These bits clear to 0 after the register has been read. Very useful + * for getting multiple INT statuses, since each single bit read clears + * all of them because it has to read the whole byte. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + */ +uint8_t MPU6050::getIntStatus() +{ + I2Cdev::readByte(devAddr, MPU6050_RA_INT_STATUS, buffer); + return buffer[0]; +} +/** Get Free Fall interrupt status. + * This bit automatically sets to 1 when a Free Fall interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_FF_BIT + */ +bool MPU6050::getIntFreefallStatus() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_FF_BIT, buffer); + return buffer[0]; +} +/** Get Motion Detection interrupt status. + * This bit automatically sets to 1 when a Motion Detection interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_MOT_BIT + */ +bool MPU6050::getIntMotionStatus() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_MOT_BIT, buffer); + return buffer[0]; +} +/** Get Zero Motion Detection interrupt status. + * This bit automatically sets to 1 when a Zero Motion Detection interrupt has + * been generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_ZMOT_BIT + */ +bool MPU6050::getIntZeroMotionStatus() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_ZMOT_BIT, buffer); + return buffer[0]; +} +/** Get FIFO Buffer Overflow interrupt status. + * This bit automatically sets to 1 when a Free Fall interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT + */ +bool MPU6050::getIntFIFOBufferOverflowStatus() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, buffer); + return buffer[0]; +} +/** Get I2C Master interrupt status. + * This bit automatically sets to 1 when an I2C Master interrupt has been + * generated. For a list of I2C Master interrupts, please refer to Register 54. + * The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT + */ +bool MPU6050::getIntI2CMasterStatus() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_I2C_MST_INT_BIT, buffer); + return buffer[0]; +} +/** Get Data Ready interrupt status. + * This bit automatically sets to 1 when a Data Ready interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_DATA_RDY_BIT + */ +bool MPU6050::getIntDataReadyStatus() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_DATA_RDY_BIT, buffer); + return buffer[0]; +} + +// ACCEL_*OUT_* registers + +/** Get raw 9-axis motion sensor readings (accel/gyro/compass). + * FUNCTION NOT FULLY IMPLEMENTED YET. + * @param ax 16-bit signed integer container for accelerometer X-axis value + * @param ay 16-bit signed integer container for accelerometer Y-axis value + * @param az 16-bit signed integer container for accelerometer Z-axis value + * @param gx 16-bit signed integer container for gyroscope X-axis value + * @param gy 16-bit signed integer container for gyroscope Y-axis value + * @param gz 16-bit signed integer container for gyroscope Z-axis value + * @param mx 16-bit signed integer container for magnetometer X-axis value + * @param my 16-bit signed integer container for magnetometer Y-axis value + * @param mz 16-bit signed integer container for magnetometer Z-axis value + * @see getMotion6() + * @see getAcceleration() + * @see getRotation() + * @see MPU6050_RA_ACCEL_XOUT_H + */ +void MPU6050::getMotion9(int16_t *ax, int16_t *ay, int16_t *az, int16_t *gx, int16_t *gy, int16_t *gz, int16_t *mx, int16_t *my, int16_t *mz) +{ + getMotion6(ax, ay, az, gx, gy, gz); + // TODO: magnetometer integration +} +/** Get raw 6-axis motion sensor readings (accel/gyro). + * Retrieves all currently available motion sensor values. + * @param ax 16-bit signed integer container for accelerometer X-axis value + * @param ay 16-bit signed integer container for accelerometer Y-axis value + * @param az 16-bit signed integer container for accelerometer Z-axis value + * @param gx 16-bit signed integer container for gyroscope X-axis value + * @param gy 16-bit signed integer container for gyroscope Y-axis value + * @param gz 16-bit signed integer container for gyroscope Z-axis value + * @see getAcceleration() + * @see getRotation() + * @see MPU6050_RA_ACCEL_XOUT_H + */ +void MPU6050::getMotion6(int16_t *ax, int16_t *ay, int16_t *az, int16_t *gx, int16_t *gy, int16_t *gz) +{ + I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_XOUT_H, 14, buffer); + *ax = (((int16_t)buffer[0]) << 8) | buffer[1]; + *ay = (((int16_t)buffer[2]) << 8) | buffer[3]; + *az = (((int16_t)buffer[4]) << 8) | buffer[5]; + *gx = (((int16_t)buffer[8]) << 8) | buffer[9]; + *gy = (((int16_t)buffer[10]) << 8) | buffer[11]; + *gz = (((int16_t)buffer[12]) << 8) | buffer[13]; +} +/** Get 3-axis accelerometer readings. + * These registers store the most recent accelerometer measurements. + * Accelerometer measurements are written to these registers at the Sample Rate + * as defined in Register 25. + * + * The accelerometer measurement registers, along with the temperature + * measurement registers, gyroscope measurement registers, and external sensor + * data registers, are composed of two sets of registers: an internal register + * set and a user-facing read register set. + * + * The data within the accelerometer sensors' internal register set is always + * updated at the Sample Rate. Meanwhile, the user-facing read register set + * duplicates the internal register set's data values whenever the serial + * interface is idle. This guarantees that a burst read of sensor registers will + * read measurements from the same sampling instant. Note that if burst reads + * are not used, the user is responsible for ensuring a set of single byte reads + * correspond to a single sampling instant by checking the Data Ready interrupt. + * + * Each 16-bit accelerometer measurement has a full scale defined in ACCEL_FS + * (Register 28). For each full scale setting, the accelerometers' sensitivity + * per LSB in ACCEL_xOUT is shown in the table below: + * + *
+ * AFS_SEL | Full Scale Range | LSB Sensitivity
+ * --------+------------------+----------------
+ * 0       | +/- 2g           | 8192 LSB/mg
+ * 1       | +/- 4g           | 4096 LSB/mg
+ * 2       | +/- 8g           | 2048 LSB/mg
+ * 3       | +/- 16g          | 1024 LSB/mg
+ * 
+ * + * @param x 16-bit signed integer container for X-axis acceleration + * @param y 16-bit signed integer container for Y-axis acceleration + * @param z 16-bit signed integer container for Z-axis acceleration + * @see MPU6050_RA_GYRO_XOUT_H + */ +void MPU6050::getAcceleration(int16_t *x, int16_t *y, int16_t *z) +{ + I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_XOUT_H, 6, buffer); + *x = (((int16_t)buffer[0]) << 8) | buffer[1]; + *y = (((int16_t)buffer[2]) << 8) | buffer[3]; + *z = (((int16_t)buffer[4]) << 8) | buffer[5]; +} +/** Get X-axis accelerometer reading. + * @return X-axis acceleration measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_ACCEL_XOUT_H + */ +int16_t MPU6050::getAccelerationX() +{ + I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_XOUT_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +/** Get Y-axis accelerometer reading. + * @return Y-axis acceleration measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_ACCEL_YOUT_H + */ +int16_t MPU6050::getAccelerationY() +{ + I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_YOUT_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +/** Get Z-axis accelerometer reading. + * @return Z-axis acceleration measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_ACCEL_ZOUT_H + */ +int16_t MPU6050::getAccelerationZ() +{ + I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_ZOUT_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} + +// TEMP_OUT_* registers + +/** Get current internal temperature. + * @return Temperature reading in 16-bit 2's complement format + * @see MPU6050_RA_TEMP_OUT_H + */ +int16_t MPU6050::getTemperature() +{ + I2Cdev::readBytes(devAddr, MPU6050_RA_TEMP_OUT_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} + +// GYRO_*OUT_* registers + +/** Get 3-axis gyroscope readings. + * These gyroscope measurement registers, along with the accelerometer + * measurement registers, temperature measurement registers, and external sensor + * data registers, are composed of two sets of registers: an internal register + * set and a user-facing read register set. + * The data within the gyroscope sensors' internal register set is always + * updated at the Sample Rate. Meanwhile, the user-facing read register set + * duplicates the internal register set's data values whenever the serial + * interface is idle. This guarantees that a burst read of sensor registers will + * read measurements from the same sampling instant. Note that if burst reads + * are not used, the user is responsible for ensuring a set of single byte reads + * correspond to a single sampling instant by checking the Data Ready interrupt. + * + * Each 16-bit gyroscope measurement has a full scale defined in FS_SEL + * (Register 27). For each full scale setting, the gyroscopes' sensitivity per + * LSB in GYRO_xOUT is shown in the table below: + * + *
+ * FS_SEL | Full Scale Range   | LSB Sensitivity
+ * -------+--------------------+----------------
+ * 0      | +/- 250 degrees/s  | 131 LSB/deg/s
+ * 1      | +/- 500 degrees/s  | 65.5 LSB/deg/s
+ * 2      | +/- 1000 degrees/s | 32.8 LSB/deg/s
+ * 3      | +/- 2000 degrees/s | 16.4 LSB/deg/s
+ * 
+ * + * @param x 16-bit signed integer container for X-axis rotation + * @param y 16-bit signed integer container for Y-axis rotation + * @param z 16-bit signed integer container for Z-axis rotation + * @see getMotion6() + * @see MPU6050_RA_GYRO_XOUT_H + */ +void MPU6050::getRotation(int16_t *x, int16_t *y, int16_t *z) +{ + I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_XOUT_H, 6, buffer); + *x = (((int16_t)buffer[0]) << 8) | buffer[1]; + *y = (((int16_t)buffer[2]) << 8) | buffer[3]; + *z = (((int16_t)buffer[4]) << 8) | buffer[5]; +} +/** Get X-axis gyroscope reading. + * @return X-axis rotation measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_GYRO_XOUT_H + */ +int16_t MPU6050::getRotationX() +{ + I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_XOUT_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +/** Get Y-axis gyroscope reading. + * @return Y-axis rotation measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_GYRO_YOUT_H + */ +int16_t MPU6050::getRotationY() +{ + I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_YOUT_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +/** Get Z-axis gyroscope reading. + * @return Z-axis rotation measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_GYRO_ZOUT_H + */ +int16_t MPU6050::getRotationZ() +{ + I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_ZOUT_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} + +// EXT_SENS_DATA_* registers + +/** Read single byte from external sensor data register. + * These registers store data read from external sensors by the Slave 0, 1, 2, + * and 3 on the auxiliary I2C interface. Data read by Slave 4 is stored in + * I2C_SLV4_DI (Register 53). + * + * External sensor data is written to these registers at the Sample Rate as + * defined in Register 25. This access rate can be reduced by using the Slave + * Delay Enable registers (Register 103). + * + * External sensor data registers, along with the gyroscope measurement + * registers, accelerometer measurement registers, and temperature measurement + * registers, are composed of two sets of registers: an internal register set + * and a user-facing read register set. + * + * The data within the external sensors' internal register set is always updated + * at the Sample Rate (or the reduced access rate) whenever the serial interface + * is idle. This guarantees that a burst read of sensor registers will read + * measurements from the same sampling instant. Note that if burst reads are not + * used, the user is responsible for ensuring a set of single byte reads + * correspond to a single sampling instant by checking the Data Ready interrupt. + * + * Data is placed in these external sensor data registers according to + * I2C_SLV0_CTRL, I2C_SLV1_CTRL, I2C_SLV2_CTRL, and I2C_SLV3_CTRL (Registers 39, + * 42, 45, and 48). When more than zero bytes are read (I2C_SLVx_LEN > 0) from + * an enabled slave (I2C_SLVx_EN = 1), the slave is read at the Sample Rate (as + * defined in Register 25) or delayed rate (if specified in Register 52 and + * 103). During each Sample cycle, slave reads are performed in order of Slave + * number. If all slaves are enabled with more than zero bytes to be read, the + * order will be Slave 0, followed by Slave 1, Slave 2, and Slave 3. + * + * Each enabled slave will have EXT_SENS_DATA registers associated with it by + * number of bytes read (I2C_SLVx_LEN) in order of slave number, starting from + * EXT_SENS_DATA_00. Note that this means enabling or disabling a slave may + * change the higher numbered slaves' associated registers. Furthermore, if + * fewer total bytes are being read from the external sensors as a result of + * such a change, then the data remaining in the registers which no longer have + * an associated slave device (i.e. high numbered registers) will remain in + * these previously allocated registers unless reset. + * + * If the sum of the read lengths of all SLVx transactions exceed the number of + * available EXT_SENS_DATA registers, the excess bytes will be dropped. There + * are 24 EXT_SENS_DATA registers and hence the total read lengths between all + * the slaves cannot be greater than 24 or some bytes will be lost. + * + * Note: Slave 4's behavior is distinct from that of Slaves 0-3. For further + * information regarding the characteristics of Slave 4, please refer to + * Registers 49 to 53. + * + * EXAMPLE: + * Suppose that Slave 0 is enabled with 4 bytes to be read (I2C_SLV0_EN = 1 and + * I2C_SLV0_LEN = 4) while Slave 1 is enabled with 2 bytes to be read so that + * I2C_SLV1_EN = 1 and I2C_SLV1_LEN = 2. In such a situation, EXT_SENS_DATA _00 + * through _03 will be associated with Slave 0, while EXT_SENS_DATA _04 and 05 + * will be associated with Slave 1. If Slave 2 is enabled as well, registers + * starting from EXT_SENS_DATA_06 will be allocated to Slave 2. + * + * If Slave 2 is disabled while Slave 3 is enabled in this same situation, then + * registers starting from EXT_SENS_DATA_06 will be allocated to Slave 3 + * instead. + * + * REGISTER ALLOCATION FOR DYNAMIC DISABLE VS. NORMAL DISABLE: + * If a slave is disabled at any time, the space initially allocated to the + * slave in the EXT_SENS_DATA register, will remain associated with that slave. + * This is to avoid dynamic adjustment of the register allocation. + * + * The allocation of the EXT_SENS_DATA registers is recomputed only when (1) all + * slaves are disabled, or (2) the I2C_MST_RST bit is set (Register 106). + * + * This above is also true if one of the slaves gets NACKed and stops + * functioning. + * + * @param position Starting position (0-23) + * @return Byte read from register + */ +uint8_t MPU6050::getExternalSensorByte(int position) +{ + I2Cdev::readByte(devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, buffer); + return buffer[0]; +} +/** Read word (2 bytes) from external sensor data registers. + * @param position Starting position (0-21) + * @return Word read from register + * @see getExternalSensorByte() + */ +uint16_t MPU6050::getExternalSensorWord(int position) +{ + I2Cdev::readBytes(devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, 2, buffer); + return (((uint16_t)buffer[0]) << 8) | buffer[1]; +} +/** Read double word (4 bytes) from external sensor data registers. + * @param position Starting position (0-20) + * @return Double word read from registers + * @see getExternalSensorByte() + */ +uint32_t MPU6050::getExternalSensorDWord(int position) +{ + I2Cdev::readBytes(devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, 4, buffer); + return (((uint32_t)buffer[0]) << 24) | (((uint32_t)buffer[1]) << 16) | (((uint16_t)buffer[2]) << 8) | buffer[3]; +} + +// MOT_DETECT_STATUS register + +/** Get full motion detection status register content (all bits). + * @return Motion detection status byte + * @see MPU6050_RA_MOT_DETECT_STATUS + */ +uint8_t MPU6050::getMotionStatus() +{ + I2Cdev::readByte(devAddr, MPU6050_RA_MOT_DETECT_STATUS, buffer); + return buffer[0]; +} +/** Get X-axis negative motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_XNEG_BIT + */ +bool MPU6050::getXNegMotionDetected() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_XNEG_BIT, buffer); + return buffer[0]; +} +/** Get X-axis positive motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_XPOS_BIT + */ +bool MPU6050::getXPosMotionDetected() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_XPOS_BIT, buffer); + return buffer[0]; +} +/** Get Y-axis negative motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_YNEG_BIT + */ +bool MPU6050::getYNegMotionDetected() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_YNEG_BIT, buffer); + return buffer[0]; +} +/** Get Y-axis positive motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_YPOS_BIT + */ +bool MPU6050::getYPosMotionDetected() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_YPOS_BIT, buffer); + return buffer[0]; +} +/** Get Z-axis negative motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_ZNEG_BIT + */ +bool MPU6050::getZNegMotionDetected() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZNEG_BIT, buffer); + return buffer[0]; +} +/** Get Z-axis positive motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_ZPOS_BIT + */ +bool MPU6050::getZPosMotionDetected() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZPOS_BIT, buffer); + return buffer[0]; +} +/** Get zero motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_ZRMOT_BIT + */ +bool MPU6050::getZeroMotionDetected() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZRMOT_BIT, buffer); + return buffer[0]; +} + +// I2C_SLV*_DO register + +/** Write byte to Data Output container for specified slave. + * This register holds the output data written into Slave when Slave is set to + * write mode. For further information regarding Slave control, please + * refer to Registers 37 to 39 and immediately following. + * @param num Slave number (0-3) + * @param data Byte to write + * @see MPU6050_RA_I2C_SLV0_DO + */ +void MPU6050::setSlaveOutputByte(uint8_t num, uint8_t data) +{ + if (num > 3) + return; + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV0_DO + num, data); +} + +// I2C_MST_DELAY_CTRL register + +/** Get external data shadow delay enabled status. + * This register is used to specify the timing of external sensor data + * shadowing. When DELAY_ES_SHADOW is set to 1, shadowing of external + * sensor data is delayed until all data has been received. + * @return Current external data shadow delay enabled status. + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT + */ +bool MPU6050::getExternalShadowDelayEnabled() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT, buffer); + return buffer[0]; +} +/** Set external data shadow delay enabled status. + * @param enabled New external data shadow delay enabled status. + * @see getExternalShadowDelayEnabled() + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT + */ +void MPU6050::setExternalShadowDelayEnabled(bool enabled) +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT, enabled); +} +/** Get slave delay enabled status. + * When a particular slave delay is enabled, the rate of access for the that + * slave device is reduced. When a slave's access rate is decreased relative to + * the Sample Rate, the slave is accessed every: + * + * 1 / (1 + I2C_MST_DLY) Samples + * + * This base Sample Rate in turn is determined by SMPLRT_DIV (register * 25) + * and DLPF_CFG (register 26). + * + * For further information regarding I2C_MST_DLY, please refer to register 52. + * For further information regarding the Sample Rate, please refer to register 25. + * + * @param num Slave number (0-4) + * @return Current slave delay enabled status. + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT + */ +bool MPU6050::getSlaveDelayEnabled(uint8_t num) +{ + // MPU6050_DELAYCTRL_I2C_SLV4_DLY_EN_BIT is 4, SLV3 is 3, etc. + if (num > 4) + return 0; + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, num, buffer); + return buffer[0]; +} +/** Set slave delay enabled status. + * @param num Slave number (0-4) + * @param enabled New slave delay enabled status. + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT + */ +void MPU6050::setSlaveDelayEnabled(uint8_t num, bool enabled) +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, num, enabled); +} + +// SIGNAL_PATH_RESET register + +/** Reset gyroscope signal path. + * The reset will revert the signal path analog to digital converters and + * filters to their power up configurations. + * @see MPU6050_RA_SIGNAL_PATH_RESET + * @see MPU6050_PATHRESET_GYRO_RESET_BIT + */ +void MPU6050::resetGyroscopePath() +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_GYRO_RESET_BIT, true); +} +/** Reset accelerometer signal path. + * The reset will revert the signal path analog to digital converters and + * filters to their power up configurations. + * @see MPU6050_RA_SIGNAL_PATH_RESET + * @see MPU6050_PATHRESET_ACCEL_RESET_BIT + */ +void MPU6050::resetAccelerometerPath() +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_ACCEL_RESET_BIT, true); +} +/** Reset temperature sensor signal path. + * The reset will revert the signal path analog to digital converters and + * filters to their power up configurations. + * @see MPU6050_RA_SIGNAL_PATH_RESET + * @see MPU6050_PATHRESET_TEMP_RESET_BIT + */ +void MPU6050::resetTemperaturePath() +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_TEMP_RESET_BIT, true); +} + +// MOT_DETECT_CTRL register + +/** Get accelerometer power-on delay. + * The accelerometer data path provides samples to the sensor registers, Motion + * detection, Zero Motion detection, and Free Fall detection modules. The + * signal path contains filters which must be flushed on wake-up with new + * samples before the detection modules begin operations. The default wake-up + * delay, of 4ms can be lengthened by up to 3ms. This additional delay is + * specified in ACCEL_ON_DELAY in units of 1 LSB = 1 ms. The user may select + * any value above zero unless instructed otherwise by InvenSense. Please refer + * to Section 8 of the MPU-6000/MPU-6050 Product Specification document for + * further information regarding the detection modules. + * @return Current accelerometer power-on delay + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_ACCEL_ON_DELAY_BIT + */ +uint8_t MPU6050::getAccelerometerPowerOnDelay() +{ + I2Cdev::readBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_ACCEL_ON_DELAY_BIT, MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH, buffer); + return buffer[0]; +} +/** Set accelerometer power-on delay. + * @param delay New accelerometer power-on delay (0-3) + * @see getAccelerometerPowerOnDelay() + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_ACCEL_ON_DELAY_BIT + */ +void MPU6050::setAccelerometerPowerOnDelay(uint8_t delay) +{ + I2Cdev::writeBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_ACCEL_ON_DELAY_BIT, MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH, delay); +} +/** Get Free Fall detection counter decrement configuration. + * Detection is registered by the Free Fall detection module after accelerometer + * measurements meet their respective threshold conditions over a specified + * number of samples. When the threshold conditions are met, the corresponding + * detection counter increments by 1. The user may control the rate at which the + * detection counter decrements when the threshold condition is not met by + * configuring FF_COUNT. The decrement rate can be set according to the + * following table: + * + *
+ * FF_COUNT | Counter Decrement
+ * ---------+------------------
+ * 0        | Reset
+ * 1        | 1
+ * 2        | 2
+ * 3        | 4
+ * 
+ * + * When FF_COUNT is configured to 0 (reset), any non-qualifying sample will + * reset the counter to 0. For further information on Free Fall detection, + * please refer to Registers 29 to 32. + * + * @return Current decrement configuration + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_FF_COUNT_BIT + */ +uint8_t MPU6050::getFreefallDetectionCounterDecrement() +{ + I2Cdev::readBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_FF_COUNT_BIT, MPU6050_DETECT_FF_COUNT_LENGTH, buffer); + return buffer[0]; +} +/** Set Free Fall detection counter decrement configuration. + * @param decrement New decrement configuration value + * @see getFreefallDetectionCounterDecrement() + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_FF_COUNT_BIT + */ +void MPU6050::setFreefallDetectionCounterDecrement(uint8_t decrement) +{ + I2Cdev::writeBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_FF_COUNT_BIT, MPU6050_DETECT_FF_COUNT_LENGTH, decrement); +} +/** Get Motion detection counter decrement configuration. + * Detection is registered by the Motion detection module after accelerometer + * measurements meet their respective threshold conditions over a specified + * number of samples. When the threshold conditions are met, the corresponding + * detection counter increments by 1. The user may control the rate at which the + * detection counter decrements when the threshold condition is not met by + * configuring MOT_COUNT. The decrement rate can be set according to the + * following table: + * + *
+ * MOT_COUNT | Counter Decrement
+ * ----------+------------------
+ * 0         | Reset
+ * 1         | 1
+ * 2         | 2
+ * 3         | 4
+ * 
+ * + * When MOT_COUNT is configured to 0 (reset), any non-qualifying sample will + * reset the counter to 0. For further information on Motion detection, + * please refer to Registers 29 to 32. + * + */ +uint8_t MPU6050::getMotionDetectionCounterDecrement() +{ + I2Cdev::readBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_MOT_COUNT_BIT, MPU6050_DETECT_MOT_COUNT_LENGTH, buffer); + return buffer[0]; +} +/** Set Motion detection counter decrement configuration. + * @param decrement New decrement configuration value + * @see getMotionDetectionCounterDecrement() + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_MOT_COUNT_BIT + */ +void MPU6050::setMotionDetectionCounterDecrement(uint8_t decrement) +{ + I2Cdev::writeBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_MOT_COUNT_BIT, MPU6050_DETECT_MOT_COUNT_LENGTH, decrement); +} + +// USER_CTRL register + +/** Get FIFO enabled status. + * When this bit is set to 0, the FIFO buffer is disabled. The FIFO buffer + * cannot be written to or read from while disabled. The FIFO buffer's state + * does not change unless the MPU-60X0 is power cycled. + * @return Current FIFO enabled status + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_FIFO_EN_BIT + */ +bool MPU6050::getFIFOEnabled() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set FIFO enabled status. + * @param enabled New FIFO enabled status + * @see getFIFOEnabled() + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_FIFO_EN_BIT + */ +void MPU6050::setFIFOEnabled(bool enabled) +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_EN_BIT, enabled); +} +/** Get I2C Master Mode enabled status. + * When this mode is enabled, the MPU-60X0 acts as the I2C Master to the + * external sensor slave devices on the auxiliary I2C bus. When this bit is + * cleared to 0, the auxiliary I2C bus lines (AUX_DA and AUX_CL) are logically + * driven by the primary I2C bus (SDA and SCL). This is a precondition to + * enabling Bypass Mode. For further information regarding Bypass Mode, please + * refer to Register 55. + * @return Current I2C Master Mode enabled status + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_I2C_MST_EN_BIT + */ +bool MPU6050::getI2CMasterModeEnabled() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_EN_BIT, buffer); + return buffer[0]; +} +/** Set I2C Master Mode enabled status. + * @param enabled New I2C Master Mode enabled status + * @see getI2CMasterModeEnabled() + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_I2C_MST_EN_BIT + */ +void MPU6050::setI2CMasterModeEnabled(bool enabled) +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_EN_BIT, enabled); +} +/** Switch from I2C to SPI mode (MPU-6000 only) + * If this is set, the primary SPI interface will be enabled in place of the + * disabled primary I2C interface. + */ +void MPU6050::switchSPIEnabled(bool enabled) +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_IF_DIS_BIT, enabled); +} +/** Reset the FIFO. + * This bit resets the FIFO buffer when set to 1 while FIFO_EN equals 0. This + * bit automatically clears to 0 after the reset has been triggered. + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_FIFO_RESET_BIT + */ +void MPU6050::resetFIFO() +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_RESET_BIT, true); +} +/** Reset the I2C Master. + * This bit resets the I2C Master when set to 1 while I2C_MST_EN equals 0. + * This bit automatically clears to 0 after the reset has been triggered. + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_I2C_MST_RESET_BIT + */ +void MPU6050::resetI2CMaster() +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_RESET_BIT, true); +} +/** Reset all sensor registers and signal paths. + * When set to 1, this bit resets the signal paths for all sensors (gyroscopes, + * accelerometers, and temperature sensor). This operation will also clear the + * sensor registers. This bit automatically clears to 0 after the reset has been + * triggered. + * + * When resetting only the signal path (and not the sensor registers), please + * use Register 104, SIGNAL_PATH_RESET. + * + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_SIG_COND_RESET_BIT + */ +void MPU6050::resetSensors() +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_SIG_COND_RESET_BIT, true); +} + +// PWR_MGMT_1 register + +/** Trigger a full device reset. + * A small delay of ~50ms may be desirable after triggering a reset. + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_DEVICE_RESET_BIT + */ +void MPU6050::reset() +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_DEVICE_RESET_BIT, true); +} +/** Get sleep mode status. + * Setting the SLEEP bit in the register puts the device into very low power + * sleep mode. In this mode, only the serial interface and internal registers + * remain active, allowing for a very low standby current. Clearing this bit + * puts the device back into normal mode. To save power, the individual standby + * selections for each of the gyros should be used if any gyro axis is not used + * by the application. + * @return Current sleep mode enabled status + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_SLEEP_BIT + */ +bool MPU6050::getSleepEnabled() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, buffer); + return buffer[0]; +} +/** Set sleep mode status. + * @param enabled New sleep mode enabled status + * @see getSleepEnabled() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_SLEEP_BIT + */ +void MPU6050::setSleepEnabled(bool enabled) +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, enabled); +} +/** Get wake cycle enabled status. + * When this bit is set to 1 and SLEEP is disabled, the MPU-60X0 will cycle + * between sleep mode and waking up to take a single sample of data from active + * sensors at a rate determined by LP_WAKE_CTRL (register 108). + * @return Current sleep mode enabled status + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CYCLE_BIT + */ +bool MPU6050::getWakeCycleEnabled() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CYCLE_BIT, buffer); + return buffer[0]; +} +/** Set wake cycle enabled status. + * @param enabled New sleep mode enabled status + * @see getWakeCycleEnabled() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CYCLE_BIT + */ +void MPU6050::setWakeCycleEnabled(bool enabled) +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CYCLE_BIT, enabled); +} +/** Get temperature sensor enabled status. + * Control the usage of the internal temperature sensor. + * + * Note: this register stores the *disabled* value, but for consistency with the + * rest of the code, the function is named and used with standard true/false + * values to indicate whether the sensor is enabled or disabled, respectively. + * + * @return Current temperature sensor enabled status + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_TEMP_DIS_BIT + */ +bool MPU6050::getTempSensorEnabled() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_TEMP_DIS_BIT, buffer); + return buffer[0] == 0; // 1 is actually disabled here +} +/** Set temperature sensor enabled status. + * Note: this register stores the *disabled* value, but for consistency with the + * rest of the code, the function is named and used with standard true/false + * values to indicate whether the sensor is enabled or disabled, respectively. + * + * @param enabled New temperature sensor enabled status + * @see getTempSensorEnabled() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_TEMP_DIS_BIT + */ +void MPU6050::setTempSensorEnabled(bool enabled) +{ + // 1 is actually disabled here + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_TEMP_DIS_BIT, !enabled); +} +/** Get clock source setting. + * @return Current clock source setting + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CLKSEL_BIT + * @see MPU6050_PWR1_CLKSEL_LENGTH + */ +uint8_t MPU6050::getClockSource() +{ + I2Cdev::readBits(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, buffer); + return buffer[0]; +} +/** Set clock source setting. + * An internal 8MHz oscillator, gyroscope based clock, or external sources can + * be selected as the MPU-60X0 clock source. When the internal 8 MHz oscillator + * or an external source is chosen as the clock source, the MPU-60X0 can operate + * in low power modes with the gyroscopes disabled. + * + * Upon power up, the MPU-60X0 clock source defaults to the internal oscillator. + * However, it is highly recommended that the device be configured to use one of + * the gyroscopes (or an external clock source) as the clock reference for + * improved stability. The clock source can be selected according to the following table: + * + *
+ * CLK_SEL | Clock Source
+ * --------+--------------------------------------
+ * 0       | Internal oscillator
+ * 1       | PLL with X Gyro reference
+ * 2       | PLL with Y Gyro reference
+ * 3       | PLL with Z Gyro reference
+ * 4       | PLL with external 32.768kHz reference
+ * 5       | PLL with external 19.2MHz reference
+ * 6       | Reserved
+ * 7       | Stops the clock and keeps the timing generator in reset
+ * 
+ * + * @param source New clock source setting + * @see getClockSource() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CLKSEL_BIT + * @see MPU6050_PWR1_CLKSEL_LENGTH + */ +void MPU6050::setClockSource(uint8_t source) +{ + I2Cdev::writeBits(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, source); +} + +// PWR_MGMT_2 register + +/** Get wake frequency in Accel-Only Low Power Mode. + * The MPU-60X0 can be put into Accerlerometer Only Low Power Mode by setting + * PWRSEL to 1 in the Power Management 1 register (Register 107). In this mode, + * the device will power off all devices except for the primary I2C interface, + * waking only the accelerometer at fixed intervals to take a single + * measurement. The frequency of wake-ups can be configured with LP_WAKE_CTRL + * as shown below: + * + *
+ * LP_WAKE_CTRL | Wake-up Frequency
+ * -------------+------------------
+ * 0            | 1.25 Hz
+ * 1            | 2.5 Hz
+ * 2            | 5 Hz
+ * 3            | 10 Hz
+ * 
+ * + * For further information regarding the MPU-60X0's power modes, please refer to + * Register 107. + * + * @return Current wake frequency + * @see MPU6050_RA_PWR_MGMT_2 + */ +uint8_t MPU6050::getWakeFrequency() +{ + I2Cdev::readBits(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_LP_WAKE_CTRL_BIT, MPU6050_PWR2_LP_WAKE_CTRL_LENGTH, buffer); + return buffer[0]; +} +/** Set wake frequency in Accel-Only Low Power Mode. + * @param frequency New wake frequency + * @see MPU6050_RA_PWR_MGMT_2 + */ +void MPU6050::setWakeFrequency(uint8_t frequency) +{ + I2Cdev::writeBits(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_LP_WAKE_CTRL_BIT, MPU6050_PWR2_LP_WAKE_CTRL_LENGTH, frequency); +} + +/** Get X-axis accelerometer standby enabled status. + * If enabled, the X-axis will not gather or report data (or use power). + * @return Current X-axis standby enabled status + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_XA_BIT + */ +bool MPU6050::getStandbyXAccelEnabled() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XA_BIT, buffer); + return buffer[0]; +} +/** Set X-axis accelerometer standby enabled status. + * @param New X-axis standby enabled status + * @see getStandbyXAccelEnabled() + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_XA_BIT + */ +void MPU6050::setStandbyXAccelEnabled(bool enabled) +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XA_BIT, enabled); +} +/** Get Y-axis accelerometer standby enabled status. + * If enabled, the Y-axis will not gather or report data (or use power). + * @return Current Y-axis standby enabled status + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_YA_BIT + */ +bool MPU6050::getStandbyYAccelEnabled() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YA_BIT, buffer); + return buffer[0]; +} +/** Set Y-axis accelerometer standby enabled status. + * @param New Y-axis standby enabled status + * @see getStandbyYAccelEnabled() + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_YA_BIT + */ +void MPU6050::setStandbyYAccelEnabled(bool enabled) +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YA_BIT, enabled); +} +/** Get Z-axis accelerometer standby enabled status. + * If enabled, the Z-axis will not gather or report data (or use power). + * @return Current Z-axis standby enabled status + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_ZA_BIT + */ +bool MPU6050::getStandbyZAccelEnabled() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZA_BIT, buffer); + return buffer[0]; +} +/** Set Z-axis accelerometer standby enabled status. + * @param New Z-axis standby enabled status + * @see getStandbyZAccelEnabled() + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_ZA_BIT + */ +void MPU6050::setStandbyZAccelEnabled(bool enabled) +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZA_BIT, enabled); +} +/** Get X-axis gyroscope standby enabled status. + * If enabled, the X-axis will not gather or report data (or use power). + * @return Current X-axis standby enabled status + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_XG_BIT + */ +bool MPU6050::getStandbyXGyroEnabled() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XG_BIT, buffer); + return buffer[0]; +} +/** Set X-axis gyroscope standby enabled status. + * @param New X-axis standby enabled status + * @see getStandbyXGyroEnabled() + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_XG_BIT + */ +void MPU6050::setStandbyXGyroEnabled(bool enabled) +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XG_BIT, enabled); +} +/** Get Y-axis gyroscope standby enabled status. + * If enabled, the Y-axis will not gather or report data (or use power). + * @return Current Y-axis standby enabled status + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_YG_BIT + */ +bool MPU6050::getStandbyYGyroEnabled() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YG_BIT, buffer); + return buffer[0]; +} +/** Set Y-axis gyroscope standby enabled status. + * @param New Y-axis standby enabled status + * @see getStandbyYGyroEnabled() + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_YG_BIT + */ +void MPU6050::setStandbyYGyroEnabled(bool enabled) +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YG_BIT, enabled); +} +/** Get Z-axis gyroscope standby enabled status. + * If enabled, the Z-axis will not gather or report data (or use power). + * @return Current Z-axis standby enabled status + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_ZG_BIT + */ +bool MPU6050::getStandbyZGyroEnabled() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZG_BIT, buffer); + return buffer[0]; +} +/** Set Z-axis gyroscope standby enabled status. + * @param New Z-axis standby enabled status + * @see getStandbyZGyroEnabled() + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_ZG_BIT + */ +void MPU6050::setStandbyZGyroEnabled(bool enabled) +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZG_BIT, enabled); +} + +// FIFO_COUNT* registers + +/** Get current FIFO buffer size. + * This value indicates the number of bytes stored in the FIFO buffer. This + * number is in turn the number of bytes that can be read from the FIFO buffer + * and it is directly proportional to the number of samples available given the + * set of sensor data bound to be stored in the FIFO (register 35 and 36). + * @return Current FIFO buffer size + */ +uint16_t MPU6050::getFIFOCount() +{ + I2Cdev::readBytes(devAddr, MPU6050_RA_FIFO_COUNTH, 2, buffer); + return (((uint16_t)buffer[0]) << 8) | buffer[1]; +} + +// FIFO_R_W register + +/** Get byte from FIFO buffer. + * This register is used to read and write data from the FIFO buffer. Data is + * written to the FIFO in order of register number (from lowest to highest). If + * all the FIFO enable flags (see below) are enabled and all External Sensor + * Data registers (Registers 73 to 96) are associated with a Slave device, the + * contents of registers 59 through 96 will be written in order at the Sample + * Rate. + * + * The contents of the sensor data registers (Registers 59 to 96) are written + * into the FIFO buffer when their corresponding FIFO enable flags are set to 1 + * in FIFO_EN (Register 35). An additional flag for the sensor data registers + * associated with I2C Slave 3 can be found in I2C_MST_CTRL (Register 36). + * + * If the FIFO buffer has overflowed, the status bit FIFO_OFLOW_INT is + * automatically set to 1. This bit is located in INT_STATUS (Register 58). + * When the FIFO buffer has overflowed, the oldest data will be lost and new + * data will be written to the FIFO. + * + * If the FIFO buffer is empty, reading this register will return the last byte + * that was previously read from the FIFO until new data is available. The user + * should check FIFO_COUNT to ensure that the FIFO buffer is not read when + * empty. + * + * @return Byte from FIFO buffer + */ +uint8_t MPU6050::getFIFOByte() +{ + I2Cdev::readByte(devAddr, MPU6050_RA_FIFO_R_W, buffer); + return buffer[0]; +} +void MPU6050::getFIFOBytes(uint8_t *data, uint8_t length) +{ + if (length > 0) + { + I2Cdev::readBytes(devAddr, MPU6050_RA_FIFO_R_W, length, data); + } + else + { + *data = 0; + } +} +/** Write byte to FIFO buffer. + * @see getFIFOByte() + * @see MPU6050_RA_FIFO_R_W + */ +void MPU6050::setFIFOByte(uint8_t data) +{ + I2Cdev::writeByte(devAddr, MPU6050_RA_FIFO_R_W, data); +} + +// WHO_AM_I register + +/** Get Device ID. + * This register is used to verify the identity of the device (0b110100, 0x34). + * @return Device ID (6 bits only! should be 0x34) + * @see MPU6050_RA_WHO_AM_I + * @see MPU6050_WHO_AM_I_BIT + * @see MPU6050_WHO_AM_I_LENGTH + */ +uint8_t MPU6050::getDeviceID() +{ + I2Cdev::readBits(devAddr, MPU6050_RA_WHO_AM_I, MPU6050_WHO_AM_I_BIT, MPU6050_WHO_AM_I_LENGTH, buffer); + return buffer[0]; +} +/** Set Device ID. + * Write a new ID into the WHO_AM_I register (no idea why this should ever be + * necessary though). + * @param id New device ID to set. + * @see getDeviceID() + * @see MPU6050_RA_WHO_AM_I + * @see MPU6050_WHO_AM_I_BIT + * @see MPU6050_WHO_AM_I_LENGTH + */ +void MPU6050::setDeviceID(uint8_t id) +{ + I2Cdev::writeBits(devAddr, MPU6050_RA_WHO_AM_I, MPU6050_WHO_AM_I_BIT, MPU6050_WHO_AM_I_LENGTH, id); +} + +// ======== UNDOCUMENTED/DMP REGISTERS/METHODS ======== + +// XG_OFFS_TC register + +uint8_t MPU6050::getOTPBankValid() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OTP_BNK_VLD_BIT, buffer); + return buffer[0]; +} +void MPU6050::setOTPBankValid(bool enabled) +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OTP_BNK_VLD_BIT, enabled); +} +int8_t MPU6050::getXGyroOffsetTC() +{ + I2Cdev::readBits(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, buffer); + return buffer[0]; +} +void MPU6050::setXGyroOffsetTC(int8_t offset) +{ + I2Cdev::writeBits(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset); +} + +// YG_OFFS_TC register + +int8_t MPU6050::getYGyroOffsetTC() +{ + I2Cdev::readBits(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, buffer); + return buffer[0]; +} +void MPU6050::setYGyroOffsetTC(int8_t offset) +{ + I2Cdev::writeBits(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset); +} + +// ZG_OFFS_TC register + +int8_t MPU6050::getZGyroOffsetTC() +{ + I2Cdev::readBits(devAddr, MPU6050_RA_ZG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, buffer); + return buffer[0]; +} +void MPU6050::setZGyroOffsetTC(int8_t offset) +{ + I2Cdev::writeBits(devAddr, MPU6050_RA_ZG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset); +} + +// X_FINE_GAIN register + +int8_t MPU6050::getXFineGain() +{ + I2Cdev::readByte(devAddr, MPU6050_RA_X_FINE_GAIN, buffer); + return buffer[0]; +} +void MPU6050::setXFineGain(int8_t gain) +{ + I2Cdev::writeByte(devAddr, MPU6050_RA_X_FINE_GAIN, gain); +} + +// Y_FINE_GAIN register + +int8_t MPU6050::getYFineGain() +{ + I2Cdev::readByte(devAddr, MPU6050_RA_Y_FINE_GAIN, buffer); + return buffer[0]; +} +void MPU6050::setYFineGain(int8_t gain) +{ + I2Cdev::writeByte(devAddr, MPU6050_RA_Y_FINE_GAIN, gain); +} + +// Z_FINE_GAIN register + +int8_t MPU6050::getZFineGain() +{ + I2Cdev::readByte(devAddr, MPU6050_RA_Z_FINE_GAIN, buffer); + return buffer[0]; +} +void MPU6050::setZFineGain(int8_t gain) +{ + I2Cdev::writeByte(devAddr, MPU6050_RA_Z_FINE_GAIN, gain); +} + +// XA_OFFS_* registers + +int16_t MPU6050::getXAccelOffset() +{ + I2Cdev::readBytes(devAddr, MPU6050_RA_XA_OFFS_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +void MPU6050::setXAccelOffset(int16_t offset) +{ + I2Cdev::writeWord(devAddr, MPU6050_RA_XA_OFFS_H, offset); +} + +// YA_OFFS_* register + +int16_t MPU6050::getYAccelOffset() +{ + I2Cdev::readBytes(devAddr, MPU6050_RA_YA_OFFS_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +void MPU6050::setYAccelOffset(int16_t offset) +{ + I2Cdev::writeWord(devAddr, MPU6050_RA_YA_OFFS_H, offset); +} + +// ZA_OFFS_* register + +int16_t MPU6050::getZAccelOffset() +{ + I2Cdev::readBytes(devAddr, MPU6050_RA_ZA_OFFS_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +void MPU6050::setZAccelOffset(int16_t offset) +{ + I2Cdev::writeWord(devAddr, MPU6050_RA_ZA_OFFS_H, offset); +} + +// XG_OFFS_USR* registers + +int16_t MPU6050::getXGyroOffset() +{ + I2Cdev::readBytes(devAddr, MPU6050_RA_XG_OFFS_USRH, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +void MPU6050::setXGyroOffset(int16_t offset) +{ + I2Cdev::writeWord(devAddr, MPU6050_RA_XG_OFFS_USRH, offset); +} + +// YG_OFFS_USR* register + +int16_t MPU6050::getYGyroOffset() +{ + I2Cdev::readBytes(devAddr, MPU6050_RA_YG_OFFS_USRH, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +void MPU6050::setYGyroOffset(int16_t offset) +{ + I2Cdev::writeWord(devAddr, MPU6050_RA_YG_OFFS_USRH, offset); +} + +// ZG_OFFS_USR* register + +int16_t MPU6050::getZGyroOffset() +{ + I2Cdev::readBytes(devAddr, MPU6050_RA_ZG_OFFS_USRH, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +void MPU6050::setZGyroOffset(int16_t offset) +{ + I2Cdev::writeWord(devAddr, MPU6050_RA_ZG_OFFS_USRH, offset); +} + +// INT_ENABLE register (DMP functions) + +bool MPU6050::getIntPLLReadyEnabled() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, buffer); + return buffer[0]; +} +void MPU6050::setIntPLLReadyEnabled(bool enabled) +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, enabled); +} +bool MPU6050::getIntDMPEnabled() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DMP_INT_BIT, buffer); + return buffer[0]; +} +void MPU6050::setIntDMPEnabled(bool enabled) +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DMP_INT_BIT, enabled); +} + +// DMP_INT_STATUS + +bool MPU6050::getDMPInt5Status() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_5_BIT, buffer); + return buffer[0]; +} +bool MPU6050::getDMPInt4Status() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_4_BIT, buffer); + return buffer[0]; +} +bool MPU6050::getDMPInt3Status() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_3_BIT, buffer); + return buffer[0]; +} +bool MPU6050::getDMPInt2Status() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_2_BIT, buffer); + return buffer[0]; +} +bool MPU6050::getDMPInt1Status() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_1_BIT, buffer); + return buffer[0]; +} +bool MPU6050::getDMPInt0Status() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_0_BIT, buffer); + return buffer[0]; +} + +// INT_STATUS register (DMP functions) + +bool MPU6050::getIntPLLReadyStatus() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, buffer); + return buffer[0]; +} +bool MPU6050::getIntDMPStatus() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_DMP_INT_BIT, buffer); + return buffer[0]; +} + +// USER_CTRL register (DMP functions) + +bool MPU6050::getDMPEnabled() +{ + I2Cdev::readBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_EN_BIT, buffer); + return buffer[0]; +} +void MPU6050::setDMPEnabled(bool enabled) +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_EN_BIT, enabled); +} +void MPU6050::resetDMP() +{ + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_RESET_BIT, true); +} + +// BANK_SEL register + +void MPU6050::setMemoryBank(uint8_t bank, bool prefetchEnabled, bool userBank) +{ + bank &= 0x1F; + if (userBank) + bank |= 0x20; + if (prefetchEnabled) + bank |= 0x40; + I2Cdev::writeByte(devAddr, MPU6050_RA_BANK_SEL, bank); +} + +// MEM_START_ADDR register + +void MPU6050::setMemoryStartAddress(uint8_t address) +{ + I2Cdev::writeByte(devAddr, MPU6050_RA_MEM_START_ADDR, address); +} + +// MEM_R_W register + +uint8_t MPU6050::readMemoryByte() +{ + I2Cdev::readByte(devAddr, MPU6050_RA_MEM_R_W, buffer); + return buffer[0]; +} +void MPU6050::writeMemoryByte(uint8_t data) +{ + I2Cdev::writeByte(devAddr, MPU6050_RA_MEM_R_W, data); +} +void MPU6050::readMemoryBlock(uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address) +{ + setMemoryBank(bank); + setMemoryStartAddress(address); + uint8_t chunkSize; + for (uint16_t i = 0; i < dataSize;) + { + // determine correct chunk size according to bank position and data size + chunkSize = MPU6050_DMP_MEMORY_CHUNK_SIZE; + + // make sure we don't go past the data size + if (i + chunkSize > dataSize) + chunkSize = dataSize - i; + + // make sure this chunk doesn't go past the bank boundary (256 bytes) + if (chunkSize > 256 - address) + chunkSize = 256 - address; + + // read the chunk of data as specified + I2Cdev::readBytes(devAddr, MPU6050_RA_MEM_R_W, chunkSize, data + i); + + // increase byte index by [chunkSize] + i += chunkSize; + + // uint8_t automatically wraps to 0 at 256 + address += chunkSize; + + // if we aren't done, update bank (if necessary) and address + if (i < dataSize) + { + if (address == 0) + bank++; + setMemoryBank(bank); + setMemoryStartAddress(address); + } + } +} +bool MPU6050::writeMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address, bool verify) +{ + setMemoryBank(bank); + setMemoryStartAddress(address); + uint8_t chunkSize; + uint8_t *verifyBuffer = 0; + uint8_t *progBuffer = 0; + uint16_t i; + uint8_t j; + if (verify) + verifyBuffer = (uint8_t *)malloc(MPU6050_DMP_MEMORY_CHUNK_SIZE); + + for (i = 0; i < dataSize;) + { + // determine correct chunk size according to bank position and data size + chunkSize = MPU6050_DMP_MEMORY_CHUNK_SIZE; + + // make sure we don't go past the data size + if (i + chunkSize > dataSize) + chunkSize = dataSize - i; + + // make sure this chunk doesn't go past the bank boundary (256 bytes) + if (chunkSize > 256 - address) + chunkSize = 256 - address; + + // write the chunk of data as specified + progBuffer = (uint8_t *)data + i; + + I2Cdev::writeBytes(devAddr, MPU6050_RA_MEM_R_W, chunkSize, progBuffer); + + // verify data if needed + if (verify && verifyBuffer) + { + setMemoryBank(bank); + setMemoryStartAddress(address); + I2Cdev::readBytes(devAddr, MPU6050_RA_MEM_R_W, chunkSize, verifyBuffer); + if (memcmp(progBuffer, verifyBuffer, chunkSize) != 0) + { + /*Serial.print("Block write verification error, bank "); + Serial.print(bank, DEC); + Serial.print(", address "); + Serial.print(address, DEC); + Serial.print("!\nExpected:"); + for (j = 0; j < chunkSize; j++) { + Serial.print(" 0x"); + if (progBuffer[j] < 16) Serial.print("0"); + Serial.print(progBuffer[j], HEX); + } + Serial.print("\nReceived:"); + for (uint8_t j = 0; j < chunkSize; j++) { + Serial.print(" 0x"); + if (verifyBuffer[i + j] < 16) Serial.print("0"); + Serial.print(verifyBuffer[i + j], HEX); + } + Serial.print("\n");*/ + free(verifyBuffer); + + return false; // uh oh. + } + } + + // increase byte index by [chunkSize] + i += chunkSize; + + // uint8_t automatically wraps to 0 at 256 + address += chunkSize; + + // if we aren't done, update bank (if necessary) and address + if (i < dataSize) + { + if (address == 0) + bank++; + setMemoryBank(bank); + setMemoryStartAddress(address); + } + } + if (verify) + free(verifyBuffer); + + return true; +} + +bool MPU6050::writeDMPConfigurationSet(const uint8_t *data, uint16_t dataSize) +{ + uint8_t *progBuffer = 0; + uint8_t success, special; + uint16_t i, j; + + // config set data is a long string of blocks with the following structure: + // [bank] [offset] [length] [byte[0], byte[1], ..., byte[length]] + uint8_t bank, offset, length; + for (i = 0; i < dataSize;) + { + + bank = data[i++]; + offset = data[i++]; + length = data[i++]; + + // write data or perform special action + if (length > 0) + { + // regular block of data to write + /*Serial.print("Writing config block to bank "); + Serial.print(bank); + Serial.print(", offset "); + Serial.print(offset); + Serial.print(", length="); + Serial.println(length);*/ + + progBuffer = (uint8_t *)data + i; + + success = writeMemoryBlock(progBuffer, length, bank, offset, true); + i += length; + } + else + { + // special instruction + // NOTE: this kind of behavior (what and when to do certain things) + // is totally undocumented. This code is in here based on observed + // behavior only, and exactly why (or even whether) it has to be here + // is anybody's guess for now. + + special = data[i++]; + + /*Serial.print("Special command code "); + Serial.print(special, HEX); + Serial.println(" found...");*/ + if (special == 0x01) + { + // enable DMP-related interrupts + + //setIntZeroMotionEnabled(true); + //setIntFIFOBufferOverflowEnabled(true); + //setIntDMPEnabled(true); + I2Cdev::writeByte(devAddr, MPU6050_RA_INT_ENABLE, 0x32); // single operation + + success = true; + } + else + { + // unknown special command + success = false; + } + } + + if (!success) + { + + return false; // uh oh + } + } + + return true; +} + +// DMP_CFG_1 register + +uint8_t MPU6050::getDMPConfig1() +{ + I2Cdev::readByte(devAddr, MPU6050_RA_DMP_CFG_1, buffer); + return buffer[0]; +} +void MPU6050::setDMPConfig1(uint8_t config) +{ + I2Cdev::writeByte(devAddr, MPU6050_RA_DMP_CFG_1, config); +} + +// DMP_CFG_2 register + +uint8_t MPU6050::getDMPConfig2() +{ + I2Cdev::readByte(devAddr, MPU6050_RA_DMP_CFG_2, buffer); + return buffer[0]; +} +void MPU6050::setDMPConfig2(uint8_t config) +{ + I2Cdev::writeByte(devAddr, MPU6050_RA_DMP_CFG_2, config); +} diff --git a/BeagleBoneBlack/MPU6050/MPU6050.h b/BeagleBoneBlack/MPU6050/MPU6050.h new file mode 100644 index 00000000..27549fb0 --- /dev/null +++ b/BeagleBoneBlack/MPU6050/MPU6050.h @@ -0,0 +1,1018 @@ +// I2Cdev library collection - MPU6050 I2C device class +// Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00) +// 10/3/2011 by Jeff Rowberg +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// ... - ongoing debug release + +// NOTE: THIS IS ONLY A PARIAL RELEASE. THIS DEVICE CLASS IS CURRENTLY UNDERGOING ACTIVE +// DEVELOPMENT AND IS STILL MISSING SOME IMPORTANT FEATURES. PLEASE KEEP THIS IN MIND IF +// YOU DECIDE TO USE THIS PARTICULAR CODE FOR ANYTHING. + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2012 Jeff Rowberg +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#ifndef _MPU6050_H_ +#define _MPU6050_H_ + +#include "../I2Cdev/I2Cdev.h" //FIXME + +#define MPU6050_ADDRESS_AD0_LOW 0x68 // address pin low (GND), default for InvenSense evaluation board +#define MPU6050_ADDRESS_AD0_HIGH 0x69 // address pin high (VCC) +#define MPU6050_DEFAULT_ADDRESS MPU6050_ADDRESS_AD0_LOW + +#define MPU6050_RA_XG_OFFS_TC 0x00 //[7] PWR_MODE, [6:1] XG_OFFS_TC, [0] OTP_BNK_VLD +#define MPU6050_RA_YG_OFFS_TC 0x01 //[7] PWR_MODE, [6:1] YG_OFFS_TC, [0] OTP_BNK_VLD +#define MPU6050_RA_ZG_OFFS_TC 0x02 //[7] PWR_MODE, [6:1] ZG_OFFS_TC, [0] OTP_BNK_VLD +#define MPU6050_RA_X_FINE_GAIN 0x03 //[7:0] X_FINE_GAIN +#define MPU6050_RA_Y_FINE_GAIN 0x04 //[7:0] Y_FINE_GAIN +#define MPU6050_RA_Z_FINE_GAIN 0x05 //[7:0] Z_FINE_GAIN +#define MPU6050_RA_XA_OFFS_H 0x06 //[15:0] XA_OFFS +#define MPU6050_RA_XA_OFFS_L_TC 0x07 +#define MPU6050_RA_YA_OFFS_H 0x08 //[15:0] YA_OFFS +#define MPU6050_RA_YA_OFFS_L_TC 0x09 +#define MPU6050_RA_ZA_OFFS_H 0x0A //[15:0] ZA_OFFS +#define MPU6050_RA_ZA_OFFS_L_TC 0x0B +#define MPU6050_RA_SELF_TEST_X 0x0D //[7:5] XA_TEST[4-2], [4:0] XG_TEST[4-0] +#define MPU6050_RA_SELF_TEST_Y 0x0E //[7:5] YA_TEST[4-2], [4:0] YG_TEST[4-0] +#define MPU6050_RA_SELF_TEST_Z 0x0F //[7:5] ZA_TEST[4-2], [4:0] ZG_TEST[4-0] +#define MPU6050_RA_SELF_TEST_A 0x10 //[5:4] XA_TEST[1-0], [3:2] YA_TEST[1-0], [1:0] ZA_TEST[1-0] +#define MPU6050_RA_XG_OFFS_USRH 0x13 //[15:0] XG_OFFS_USR +#define MPU6050_RA_XG_OFFS_USRL 0x14 +#define MPU6050_RA_YG_OFFS_USRH 0x15 //[15:0] YG_OFFS_USR +#define MPU6050_RA_YG_OFFS_USRL 0x16 +#define MPU6050_RA_ZG_OFFS_USRH 0x17 //[15:0] ZG_OFFS_USR +#define MPU6050_RA_ZG_OFFS_USRL 0x18 +#define MPU6050_RA_SMPLRT_DIV 0x19 +#define MPU6050_RA_CONFIG 0x1A +#define MPU6050_RA_GYRO_CONFIG 0x1B +#define MPU6050_RA_ACCEL_CONFIG 0x1C +#define MPU6050_RA_FF_THR 0x1D +#define MPU6050_RA_FF_DUR 0x1E +#define MPU6050_RA_MOT_THR 0x1F +#define MPU6050_RA_MOT_DUR 0x20 +#define MPU6050_RA_ZRMOT_THR 0x21 +#define MPU6050_RA_ZRMOT_DUR 0x22 +#define MPU6050_RA_FIFO_EN 0x23 +#define MPU6050_RA_I2C_MST_CTRL 0x24 +#define MPU6050_RA_I2C_SLV0_ADDR 0x25 +#define MPU6050_RA_I2C_SLV0_REG 0x26 +#define MPU6050_RA_I2C_SLV0_CTRL 0x27 +#define MPU6050_RA_I2C_SLV1_ADDR 0x28 +#define MPU6050_RA_I2C_SLV1_REG 0x29 +#define MPU6050_RA_I2C_SLV1_CTRL 0x2A +#define MPU6050_RA_I2C_SLV2_ADDR 0x2B +#define MPU6050_RA_I2C_SLV2_REG 0x2C +#define MPU6050_RA_I2C_SLV2_CTRL 0x2D +#define MPU6050_RA_I2C_SLV3_ADDR 0x2E +#define MPU6050_RA_I2C_SLV3_REG 0x2F +#define MPU6050_RA_I2C_SLV3_CTRL 0x30 +#define MPU6050_RA_I2C_SLV4_ADDR 0x31 +#define MPU6050_RA_I2C_SLV4_REG 0x32 +#define MPU6050_RA_I2C_SLV4_DO 0x33 +#define MPU6050_RA_I2C_SLV4_CTRL 0x34 +#define MPU6050_RA_I2C_SLV4_DI 0x35 +#define MPU6050_RA_I2C_MST_STATUS 0x36 +#define MPU6050_RA_INT_PIN_CFG 0x37 +#define MPU6050_RA_INT_ENABLE 0x38 +#define MPU6050_RA_DMP_INT_STATUS 0x39 +#define MPU6050_RA_INT_STATUS 0x3A +#define MPU6050_RA_ACCEL_XOUT_H 0x3B +#define MPU6050_RA_ACCEL_XOUT_L 0x3C +#define MPU6050_RA_ACCEL_YOUT_H 0x3D +#define MPU6050_RA_ACCEL_YOUT_L 0x3E +#define MPU6050_RA_ACCEL_ZOUT_H 0x3F +#define MPU6050_RA_ACCEL_ZOUT_L 0x40 +#define MPU6050_RA_TEMP_OUT_H 0x41 +#define MPU6050_RA_TEMP_OUT_L 0x42 +#define MPU6050_RA_GYRO_XOUT_H 0x43 +#define MPU6050_RA_GYRO_XOUT_L 0x44 +#define MPU6050_RA_GYRO_YOUT_H 0x45 +#define MPU6050_RA_GYRO_YOUT_L 0x46 +#define MPU6050_RA_GYRO_ZOUT_H 0x47 +#define MPU6050_RA_GYRO_ZOUT_L 0x48 +#define MPU6050_RA_EXT_SENS_DATA_00 0x49 +#define MPU6050_RA_EXT_SENS_DATA_01 0x4A +#define MPU6050_RA_EXT_SENS_DATA_02 0x4B +#define MPU6050_RA_EXT_SENS_DATA_03 0x4C +#define MPU6050_RA_EXT_SENS_DATA_04 0x4D +#define MPU6050_RA_EXT_SENS_DATA_05 0x4E +#define MPU6050_RA_EXT_SENS_DATA_06 0x4F +#define MPU6050_RA_EXT_SENS_DATA_07 0x50 +#define MPU6050_RA_EXT_SENS_DATA_08 0x51 +#define MPU6050_RA_EXT_SENS_DATA_09 0x52 +#define MPU6050_RA_EXT_SENS_DATA_10 0x53 +#define MPU6050_RA_EXT_SENS_DATA_11 0x54 +#define MPU6050_RA_EXT_SENS_DATA_12 0x55 +#define MPU6050_RA_EXT_SENS_DATA_13 0x56 +#define MPU6050_RA_EXT_SENS_DATA_14 0x57 +#define MPU6050_RA_EXT_SENS_DATA_15 0x58 +#define MPU6050_RA_EXT_SENS_DATA_16 0x59 +#define MPU6050_RA_EXT_SENS_DATA_17 0x5A +#define MPU6050_RA_EXT_SENS_DATA_18 0x5B +#define MPU6050_RA_EXT_SENS_DATA_19 0x5C +#define MPU6050_RA_EXT_SENS_DATA_20 0x5D +#define MPU6050_RA_EXT_SENS_DATA_21 0x5E +#define MPU6050_RA_EXT_SENS_DATA_22 0x5F +#define MPU6050_RA_EXT_SENS_DATA_23 0x60 +#define MPU6050_RA_MOT_DETECT_STATUS 0x61 +#define MPU6050_RA_I2C_SLV0_DO 0x63 +#define MPU6050_RA_I2C_SLV1_DO 0x64 +#define MPU6050_RA_I2C_SLV2_DO 0x65 +#define MPU6050_RA_I2C_SLV3_DO 0x66 +#define MPU6050_RA_I2C_MST_DELAY_CTRL 0x67 +#define MPU6050_RA_SIGNAL_PATH_RESET 0x68 +#define MPU6050_RA_MOT_DETECT_CTRL 0x69 +#define MPU6050_RA_USER_CTRL 0x6A +#define MPU6050_RA_PWR_MGMT_1 0x6B +#define MPU6050_RA_PWR_MGMT_2 0x6C +#define MPU6050_RA_BANK_SEL 0x6D +#define MPU6050_RA_MEM_START_ADDR 0x6E +#define MPU6050_RA_MEM_R_W 0x6F +#define MPU6050_RA_DMP_CFG_1 0x70 +#define MPU6050_RA_DMP_CFG_2 0x71 +#define MPU6050_RA_FIFO_COUNTH 0x72 +#define MPU6050_RA_FIFO_COUNTL 0x73 +#define MPU6050_RA_FIFO_R_W 0x74 +#define MPU6050_RA_WHO_AM_I 0x75 + +#define MPU6050_SELF_TEST_XA_1_BIT 0x07 +#define MPU6050_SELF_TEST_XA_1_LENGTH 0x03 +#define MPU6050_SELF_TEST_XA_2_BIT 0x05 +#define MPU6050_SELF_TEST_XA_2_LENGTH 0x02 +#define MPU6050_SELF_TEST_YA_1_BIT 0x07 +#define MPU6050_SELF_TEST_YA_1_LENGTH 0x03 +#define MPU6050_SELF_TEST_YA_2_BIT 0x03 +#define MPU6050_SELF_TEST_YA_2_LENGTH 0x02 +#define MPU6050_SELF_TEST_ZA_1_BIT 0x07 +#define MPU6050_SELF_TEST_ZA_1_LENGTH 0x03 +#define MPU6050_SELF_TEST_ZA_2_BIT 0x01 +#define MPU6050_SELF_TEST_ZA_2_LENGTH 0x02 + +#define MPU6050_SELF_TEST_XG_1_BIT 0x04 +#define MPU6050_SELF_TEST_XG_1_LENGTH 0x05 +#define MPU6050_SELF_TEST_YG_1_BIT 0x04 +#define MPU6050_SELF_TEST_YG_1_LENGTH 0x05 +#define MPU6050_SELF_TEST_ZG_1_BIT 0x04 +#define MPU6050_SELF_TEST_ZG_1_LENGTH 0x05 + +#define MPU6050_TC_PWR_MODE_BIT 7 +#define MPU6050_TC_OFFSET_BIT 6 +#define MPU6050_TC_OFFSET_LENGTH 6 +#define MPU6050_TC_OTP_BNK_VLD_BIT 0 + +#define MPU6050_VDDIO_LEVEL_VLOGIC 0 +#define MPU6050_VDDIO_LEVEL_VDD 1 + +#define MPU6050_CFG_EXT_SYNC_SET_BIT 5 +#define MPU6050_CFG_EXT_SYNC_SET_LENGTH 3 +#define MPU6050_CFG_DLPF_CFG_BIT 2 +#define MPU6050_CFG_DLPF_CFG_LENGTH 3 + +#define MPU6050_EXT_SYNC_DISABLED 0x0 +#define MPU6050_EXT_SYNC_TEMP_OUT_L 0x1 +#define MPU6050_EXT_SYNC_GYRO_XOUT_L 0x2 +#define MPU6050_EXT_SYNC_GYRO_YOUT_L 0x3 +#define MPU6050_EXT_SYNC_GYRO_ZOUT_L 0x4 +#define MPU6050_EXT_SYNC_ACCEL_XOUT_L 0x5 +#define MPU6050_EXT_SYNC_ACCEL_YOUT_L 0x6 +#define MPU6050_EXT_SYNC_ACCEL_ZOUT_L 0x7 + +#define MPU6050_DLPF_BW_256 0x00 +#define MPU6050_DLPF_BW_188 0x01 +#define MPU6050_DLPF_BW_98 0x02 +#define MPU6050_DLPF_BW_42 0x03 +#define MPU6050_DLPF_BW_20 0x04 +#define MPU6050_DLPF_BW_10 0x05 +#define MPU6050_DLPF_BW_5 0x06 + +#define MPU6050_GCONFIG_FS_SEL_BIT 4 +#define MPU6050_GCONFIG_FS_SEL_LENGTH 2 + +#define MPU6050_GYRO_FS_250 0x00 +#define MPU6050_GYRO_FS_500 0x01 +#define MPU6050_GYRO_FS_1000 0x02 +#define MPU6050_GYRO_FS_2000 0x03 + +#define MPU6050_ACONFIG_XA_ST_BIT 7 +#define MPU6050_ACONFIG_YA_ST_BIT 6 +#define MPU6050_ACONFIG_ZA_ST_BIT 5 +#define MPU6050_ACONFIG_AFS_SEL_BIT 4 +#define MPU6050_ACONFIG_AFS_SEL_LENGTH 2 +#define MPU6050_ACONFIG_ACCEL_HPF_BIT 2 +#define MPU6050_ACONFIG_ACCEL_HPF_LENGTH 3 + +#define MPU6050_ACCEL_FS_2 0x00 +#define MPU6050_ACCEL_FS_4 0x01 +#define MPU6050_ACCEL_FS_8 0x02 +#define MPU6050_ACCEL_FS_16 0x03 + +#define MPU6050_DHPF_RESET 0x00 +#define MPU6050_DHPF_5 0x01 +#define MPU6050_DHPF_2P5 0x02 +#define MPU6050_DHPF_1P25 0x03 +#define MPU6050_DHPF_0P63 0x04 +#define MPU6050_DHPF_HOLD 0x07 + +#define MPU6050_TEMP_FIFO_EN_BIT 7 +#define MPU6050_XG_FIFO_EN_BIT 6 +#define MPU6050_YG_FIFO_EN_BIT 5 +#define MPU6050_ZG_FIFO_EN_BIT 4 +#define MPU6050_ACCEL_FIFO_EN_BIT 3 +#define MPU6050_SLV2_FIFO_EN_BIT 2 +#define MPU6050_SLV1_FIFO_EN_BIT 1 +#define MPU6050_SLV0_FIFO_EN_BIT 0 + +#define MPU6050_MULT_MST_EN_BIT 7 +#define MPU6050_WAIT_FOR_ES_BIT 6 +#define MPU6050_SLV_3_FIFO_EN_BIT 5 +#define MPU6050_I2C_MST_P_NSR_BIT 4 +#define MPU6050_I2C_MST_CLK_BIT 3 +#define MPU6050_I2C_MST_CLK_LENGTH 4 + +#define MPU6050_CLOCK_DIV_348 0x0 +#define MPU6050_CLOCK_DIV_333 0x1 +#define MPU6050_CLOCK_DIV_320 0x2 +#define MPU6050_CLOCK_DIV_308 0x3 +#define MPU6050_CLOCK_DIV_296 0x4 +#define MPU6050_CLOCK_DIV_286 0x5 +#define MPU6050_CLOCK_DIV_276 0x6 +#define MPU6050_CLOCK_DIV_267 0x7 +#define MPU6050_CLOCK_DIV_258 0x8 +#define MPU6050_CLOCK_DIV_500 0x9 +#define MPU6050_CLOCK_DIV_471 0xA +#define MPU6050_CLOCK_DIV_444 0xB +#define MPU6050_CLOCK_DIV_421 0xC +#define MPU6050_CLOCK_DIV_400 0xD +#define MPU6050_CLOCK_DIV_381 0xE +#define MPU6050_CLOCK_DIV_364 0xF + +#define MPU6050_I2C_SLV_RW_BIT 7 +#define MPU6050_I2C_SLV_ADDR_BIT 6 +#define MPU6050_I2C_SLV_ADDR_LENGTH 7 +#define MPU6050_I2C_SLV_EN_BIT 7 +#define MPU6050_I2C_SLV_BYTE_SW_BIT 6 +#define MPU6050_I2C_SLV_REG_DIS_BIT 5 +#define MPU6050_I2C_SLV_GRP_BIT 4 +#define MPU6050_I2C_SLV_LEN_BIT 3 +#define MPU6050_I2C_SLV_LEN_LENGTH 4 + +#define MPU6050_I2C_SLV4_RW_BIT 7 +#define MPU6050_I2C_SLV4_ADDR_BIT 6 +#define MPU6050_I2C_SLV4_ADDR_LENGTH 7 +#define MPU6050_I2C_SLV4_EN_BIT 7 +#define MPU6050_I2C_SLV4_INT_EN_BIT 6 +#define MPU6050_I2C_SLV4_REG_DIS_BIT 5 +#define MPU6050_I2C_SLV4_MST_DLY_BIT 4 +#define MPU6050_I2C_SLV4_MST_DLY_LENGTH 5 + +#define MPU6050_MST_PASS_THROUGH_BIT 7 +#define MPU6050_MST_I2C_SLV4_DONE_BIT 6 +#define MPU6050_MST_I2C_LOST_ARB_BIT 5 +#define MPU6050_MST_I2C_SLV4_NACK_BIT 4 +#define MPU6050_MST_I2C_SLV3_NACK_BIT 3 +#define MPU6050_MST_I2C_SLV2_NACK_BIT 2 +#define MPU6050_MST_I2C_SLV1_NACK_BIT 1 +#define MPU6050_MST_I2C_SLV0_NACK_BIT 0 + +#define MPU6050_INTCFG_INT_LEVEL_BIT 7 +#define MPU6050_INTCFG_INT_OPEN_BIT 6 +#define MPU6050_INTCFG_LATCH_INT_EN_BIT 5 +#define MPU6050_INTCFG_INT_RD_CLEAR_BIT 4 +#define MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT 3 +#define MPU6050_INTCFG_FSYNC_INT_EN_BIT 2 +#define MPU6050_INTCFG_I2C_BYPASS_EN_BIT 1 +#define MPU6050_INTCFG_CLKOUT_EN_BIT 0 + +#define MPU6050_INTMODE_ACTIVEHIGH 0x00 +#define MPU6050_INTMODE_ACTIVELOW 0x01 + +#define MPU6050_INTDRV_PUSHPULL 0x00 +#define MPU6050_INTDRV_OPENDRAIN 0x01 + +#define MPU6050_INTLATCH_50USPULSE 0x00 +#define MPU6050_INTLATCH_WAITCLEAR 0x01 + +#define MPU6050_INTCLEAR_STATUSREAD 0x00 +#define MPU6050_INTCLEAR_ANYREAD 0x01 + +#define MPU6050_INTERRUPT_FF_BIT 7 +#define MPU6050_INTERRUPT_MOT_BIT 6 +#define MPU6050_INTERRUPT_ZMOT_BIT 5 +#define MPU6050_INTERRUPT_FIFO_OFLOW_BIT 4 +#define MPU6050_INTERRUPT_I2C_MST_INT_BIT 3 +#define MPU6050_INTERRUPT_PLL_RDY_INT_BIT 2 +#define MPU6050_INTERRUPT_DMP_INT_BIT 1 +#define MPU6050_INTERRUPT_DATA_RDY_BIT 0 + +// TODO: figure out what these actually do +// UMPL source code is not very obivous +#define MPU6050_DMPINT_5_BIT 5 +#define MPU6050_DMPINT_4_BIT 4 +#define MPU6050_DMPINT_3_BIT 3 +#define MPU6050_DMPINT_2_BIT 2 +#define MPU6050_DMPINT_1_BIT 1 +#define MPU6050_DMPINT_0_BIT 0 + +#define MPU6050_MOTION_MOT_XNEG_BIT 7 +#define MPU6050_MOTION_MOT_XPOS_BIT 6 +#define MPU6050_MOTION_MOT_YNEG_BIT 5 +#define MPU6050_MOTION_MOT_YPOS_BIT 4 +#define MPU6050_MOTION_MOT_ZNEG_BIT 3 +#define MPU6050_MOTION_MOT_ZPOS_BIT 2 +#define MPU6050_MOTION_MOT_ZRMOT_BIT 0 + +#define MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT 7 +#define MPU6050_DELAYCTRL_I2C_SLV4_DLY_EN_BIT 4 +#define MPU6050_DELAYCTRL_I2C_SLV3_DLY_EN_BIT 3 +#define MPU6050_DELAYCTRL_I2C_SLV2_DLY_EN_BIT 2 +#define MPU6050_DELAYCTRL_I2C_SLV1_DLY_EN_BIT 1 +#define MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT 0 + +#define MPU6050_PATHRESET_GYRO_RESET_BIT 2 +#define MPU6050_PATHRESET_ACCEL_RESET_BIT 1 +#define MPU6050_PATHRESET_TEMP_RESET_BIT 0 + +#define MPU6050_DETECT_ACCEL_ON_DELAY_BIT 5 +#define MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH 2 +#define MPU6050_DETECT_FF_COUNT_BIT 3 +#define MPU6050_DETECT_FF_COUNT_LENGTH 2 +#define MPU6050_DETECT_MOT_COUNT_BIT 1 +#define MPU6050_DETECT_MOT_COUNT_LENGTH 2 + +#define MPU6050_DETECT_DECREMENT_RESET 0x0 +#define MPU6050_DETECT_DECREMENT_1 0x1 +#define MPU6050_DETECT_DECREMENT_2 0x2 +#define MPU6050_DETECT_DECREMENT_4 0x3 + +#define MPU6050_USERCTRL_DMP_EN_BIT 7 +#define MPU6050_USERCTRL_FIFO_EN_BIT 6 +#define MPU6050_USERCTRL_I2C_MST_EN_BIT 5 +#define MPU6050_USERCTRL_I2C_IF_DIS_BIT 4 +#define MPU6050_USERCTRL_DMP_RESET_BIT 3 +#define MPU6050_USERCTRL_FIFO_RESET_BIT 2 +#define MPU6050_USERCTRL_I2C_MST_RESET_BIT 1 +#define MPU6050_USERCTRL_SIG_COND_RESET_BIT 0 + +#define MPU6050_PWR1_DEVICE_RESET_BIT 7 +#define MPU6050_PWR1_SLEEP_BIT 6 +#define MPU6050_PWR1_CYCLE_BIT 5 +#define MPU6050_PWR1_TEMP_DIS_BIT 3 +#define MPU6050_PWR1_CLKSEL_BIT 2 +#define MPU6050_PWR1_CLKSEL_LENGTH 3 + +#define MPU6050_CLOCK_INTERNAL 0x00 +#define MPU6050_CLOCK_PLL_XGYRO 0x01 +#define MPU6050_CLOCK_PLL_YGYRO 0x02 +#define MPU6050_CLOCK_PLL_ZGYRO 0x03 +#define MPU6050_CLOCK_PLL_EXT32K 0x04 +#define MPU6050_CLOCK_PLL_EXT19M 0x05 +#define MPU6050_CLOCK_KEEP_RESET 0x07 + +#define MPU6050_PWR2_LP_WAKE_CTRL_BIT 7 +#define MPU6050_PWR2_LP_WAKE_CTRL_LENGTH 2 +#define MPU6050_PWR2_STBY_XA_BIT 5 +#define MPU6050_PWR2_STBY_YA_BIT 4 +#define MPU6050_PWR2_STBY_ZA_BIT 3 +#define MPU6050_PWR2_STBY_XG_BIT 2 +#define MPU6050_PWR2_STBY_YG_BIT 1 +#define MPU6050_PWR2_STBY_ZG_BIT 0 + +#define MPU6050_WAKE_FREQ_1P25 0x0 +#define MPU6050_WAKE_FREQ_2P5 0x1 +#define MPU6050_WAKE_FREQ_5 0x2 +#define MPU6050_WAKE_FREQ_10 0x3 + +#define MPU6050_BANKSEL_PRFTCH_EN_BIT 6 +#define MPU6050_BANKSEL_CFG_USER_BANK_BIT 5 +#define MPU6050_BANKSEL_MEM_SEL_BIT 4 +#define MPU6050_BANKSEL_MEM_SEL_LENGTH 5 + +#define MPU6050_WHO_AM_I_BIT 6 +#define MPU6050_WHO_AM_I_LENGTH 6 + +#define MPU6050_DMP_MEMORY_BANKS 8 +#define MPU6050_DMP_MEMORY_BANK_SIZE 256 +#define MPU6050_DMP_MEMORY_CHUNK_SIZE 16 + +// note: DMP code memory blocks defined at end of header file + +class MPU6050 +{ + public: + MPU6050(); + MPU6050(uint8_t address); + + void initialize(); + bool testConnection(); + + // AUX_VDDIO register + uint8_t getAuxVDDIOLevel(); + void setAuxVDDIOLevel(uint8_t level); + + // SMPLRT_DIV register + uint8_t getRate(); + void setRate(uint8_t rate); + + // CONFIG register + uint8_t getExternalFrameSync(); + void setExternalFrameSync(uint8_t sync); + uint8_t getDLPFMode(); + void setDLPFMode(uint8_t bandwidth); + + // GYRO_CONFIG register + uint8_t getFullScaleGyroRange(); + void setFullScaleGyroRange(uint8_t range); + + // SELF_TEST registers + uint8_t getAccelXSelfTestFactoryTrim(); + uint8_t getAccelYSelfTestFactoryTrim(); + uint8_t getAccelZSelfTestFactoryTrim(); + + uint8_t getGyroXSelfTestFactoryTrim(); + uint8_t getGyroYSelfTestFactoryTrim(); + uint8_t getGyroZSelfTestFactoryTrim(); + + // ACCEL_CONFIG register + bool getAccelXSelfTest(); + void setAccelXSelfTest(bool enabled); + bool getAccelYSelfTest(); + void setAccelYSelfTest(bool enabled); + bool getAccelZSelfTest(); + void setAccelZSelfTest(bool enabled); + uint8_t getFullScaleAccelRange(); + void setFullScaleAccelRange(uint8_t range); + uint8_t getDHPFMode(); + void setDHPFMode(uint8_t mode); + + // FF_THR register + uint8_t getFreefallDetectionThreshold(); + void setFreefallDetectionThreshold(uint8_t threshold); + + // FF_DUR register + uint8_t getFreefallDetectionDuration(); + void setFreefallDetectionDuration(uint8_t duration); + + // MOT_THR register + uint8_t getMotionDetectionThreshold(); + void setMotionDetectionThreshold(uint8_t threshold); + + // MOT_DUR register + uint8_t getMotionDetectionDuration(); + void setMotionDetectionDuration(uint8_t duration); + + // ZRMOT_THR register + uint8_t getZeroMotionDetectionThreshold(); + void setZeroMotionDetectionThreshold(uint8_t threshold); + + // ZRMOT_DUR register + uint8_t getZeroMotionDetectionDuration(); + void setZeroMotionDetectionDuration(uint8_t duration); + + // FIFO_EN register + bool getTempFIFOEnabled(); + void setTempFIFOEnabled(bool enabled); + bool getXGyroFIFOEnabled(); + void setXGyroFIFOEnabled(bool enabled); + bool getYGyroFIFOEnabled(); + void setYGyroFIFOEnabled(bool enabled); + bool getZGyroFIFOEnabled(); + void setZGyroFIFOEnabled(bool enabled); + bool getAccelFIFOEnabled(); + void setAccelFIFOEnabled(bool enabled); + bool getSlave2FIFOEnabled(); + void setSlave2FIFOEnabled(bool enabled); + bool getSlave1FIFOEnabled(); + void setSlave1FIFOEnabled(bool enabled); + bool getSlave0FIFOEnabled(); + void setSlave0FIFOEnabled(bool enabled); + + // I2C_MST_CTRL register + bool getMultiMasterEnabled(); + void setMultiMasterEnabled(bool enabled); + bool getWaitForExternalSensorEnabled(); + void setWaitForExternalSensorEnabled(bool enabled); + bool getSlave3FIFOEnabled(); + void setSlave3FIFOEnabled(bool enabled); + bool getSlaveReadWriteTransitionEnabled(); + void setSlaveReadWriteTransitionEnabled(bool enabled); + uint8_t getMasterClockSpeed(); + void setMasterClockSpeed(uint8_t speed); + + // I2C_SLV* registers (Slave 0-3) + uint8_t getSlaveAddress(uint8_t num); + void setSlaveAddress(uint8_t num, uint8_t address); + uint8_t getSlaveRegister(uint8_t num); + void setSlaveRegister(uint8_t num, uint8_t reg); + bool getSlaveEnabled(uint8_t num); + void setSlaveEnabled(uint8_t num, bool enabled); + bool getSlaveWordByteSwap(uint8_t num); + void setSlaveWordByteSwap(uint8_t num, bool enabled); + bool getSlaveWriteMode(uint8_t num); + void setSlaveWriteMode(uint8_t num, bool mode); + bool getSlaveWordGroupOffset(uint8_t num); + void setSlaveWordGroupOffset(uint8_t num, bool enabled); + uint8_t getSlaveDataLength(uint8_t num); + void setSlaveDataLength(uint8_t num, uint8_t length); + + // I2C_SLV* registers (Slave 4) + uint8_t getSlave4Address(); + void setSlave4Address(uint8_t address); + uint8_t getSlave4Register(); + void setSlave4Register(uint8_t reg); + void setSlave4OutputByte(uint8_t data); + bool getSlave4Enabled(); + void setSlave4Enabled(bool enabled); + bool getSlave4InterruptEnabled(); + void setSlave4InterruptEnabled(bool enabled); + bool getSlave4WriteMode(); + void setSlave4WriteMode(bool mode); + uint8_t getSlave4MasterDelay(); + void setSlave4MasterDelay(uint8_t delay); + uint8_t getSlate4InputByte(); + + // I2C_MST_STATUS register + bool getPassthroughStatus(); + bool getSlave4IsDone(); + bool getLostArbitration(); + bool getSlave4Nack(); + bool getSlave3Nack(); + bool getSlave2Nack(); + bool getSlave1Nack(); + bool getSlave0Nack(); + + // INT_PIN_CFG register + bool getInterruptMode(); + void setInterruptMode(bool mode); + bool getInterruptDrive(); + void setInterruptDrive(bool drive); + bool getInterruptLatch(); + void setInterruptLatch(bool latch); + bool getInterruptLatchClear(); + void setInterruptLatchClear(bool clear); + bool getFSyncInterruptLevel(); + void setFSyncInterruptLevel(bool level); + bool getFSyncInterruptEnabled(); + void setFSyncInterruptEnabled(bool enabled); + bool getI2CBypassEnabled(); + void setI2CBypassEnabled(bool enabled); + bool getClockOutputEnabled(); + void setClockOutputEnabled(bool enabled); + + // INT_ENABLE register + uint8_t getIntEnabled(); + void setIntEnabled(uint8_t enabled); + bool getIntFreefallEnabled(); + void setIntFreefallEnabled(bool enabled); + bool getIntMotionEnabled(); + void setIntMotionEnabled(bool enabled); + bool getIntZeroMotionEnabled(); + void setIntZeroMotionEnabled(bool enabled); + bool getIntFIFOBufferOverflowEnabled(); + void setIntFIFOBufferOverflowEnabled(bool enabled); + bool getIntI2CMasterEnabled(); + void setIntI2CMasterEnabled(bool enabled); + bool getIntDataReadyEnabled(); + void setIntDataReadyEnabled(bool enabled); + + // INT_STATUS register + uint8_t getIntStatus(); + bool getIntFreefallStatus(); + bool getIntMotionStatus(); + bool getIntZeroMotionStatus(); + bool getIntFIFOBufferOverflowStatus(); + bool getIntI2CMasterStatus(); + bool getIntDataReadyStatus(); + + // ACCEL_*OUT_* registers + void getMotion9(int16_t *ax, int16_t *ay, int16_t *az, int16_t *gx, int16_t *gy, int16_t *gz, int16_t *mx, int16_t *my, int16_t *mz); + void getMotion6(int16_t *ax, int16_t *ay, int16_t *az, int16_t *gx, int16_t *gy, int16_t *gz); + void getAcceleration(int16_t *x, int16_t *y, int16_t *z); + int16_t getAccelerationX(); + int16_t getAccelerationY(); + int16_t getAccelerationZ(); + + // TEMP_OUT_* registers + int16_t getTemperature(); + + // GYRO_*OUT_* registers + void getRotation(int16_t *x, int16_t *y, int16_t *z); + int16_t getRotationX(); + int16_t getRotationY(); + int16_t getRotationZ(); + + // EXT_SENS_DATA_* registers + uint8_t getExternalSensorByte(int position); + uint16_t getExternalSensorWord(int position); + uint32_t getExternalSensorDWord(int position); + + // MOT_DETECT_STATUS register + uint8_t getMotionStatus(); + bool getXNegMotionDetected(); + bool getXPosMotionDetected(); + bool getYNegMotionDetected(); + bool getYPosMotionDetected(); + bool getZNegMotionDetected(); + bool getZPosMotionDetected(); + bool getZeroMotionDetected(); + + // I2C_SLV*_DO register + void setSlaveOutputByte(uint8_t num, uint8_t data); + + // I2C_MST_DELAY_CTRL register + bool getExternalShadowDelayEnabled(); + void setExternalShadowDelayEnabled(bool enabled); + bool getSlaveDelayEnabled(uint8_t num); + void setSlaveDelayEnabled(uint8_t num, bool enabled); + + // SIGNAL_PATH_RESET register + void resetGyroscopePath(); + void resetAccelerometerPath(); + void resetTemperaturePath(); + + // MOT_DETECT_CTRL register + uint8_t getAccelerometerPowerOnDelay(); + void setAccelerometerPowerOnDelay(uint8_t delay); + uint8_t getFreefallDetectionCounterDecrement(); + void setFreefallDetectionCounterDecrement(uint8_t decrement); + uint8_t getMotionDetectionCounterDecrement(); + void setMotionDetectionCounterDecrement(uint8_t decrement); + + // USER_CTRL register + bool getFIFOEnabled(); + void setFIFOEnabled(bool enabled); + bool getI2CMasterModeEnabled(); + void setI2CMasterModeEnabled(bool enabled); + void switchSPIEnabled(bool enabled); + void resetFIFO(); + void resetI2CMaster(); + void resetSensors(); + + // PWR_MGMT_1 register + void reset(); + bool getSleepEnabled(); + void setSleepEnabled(bool enabled); + bool getWakeCycleEnabled(); + void setWakeCycleEnabled(bool enabled); + bool getTempSensorEnabled(); + void setTempSensorEnabled(bool enabled); + uint8_t getClockSource(); + void setClockSource(uint8_t source); + + // PWR_MGMT_2 register + uint8_t getWakeFrequency(); + void setWakeFrequency(uint8_t frequency); + bool getStandbyXAccelEnabled(); + void setStandbyXAccelEnabled(bool enabled); + bool getStandbyYAccelEnabled(); + void setStandbyYAccelEnabled(bool enabled); + bool getStandbyZAccelEnabled(); + void setStandbyZAccelEnabled(bool enabled); + bool getStandbyXGyroEnabled(); + void setStandbyXGyroEnabled(bool enabled); + bool getStandbyYGyroEnabled(); + void setStandbyYGyroEnabled(bool enabled); + bool getStandbyZGyroEnabled(); + void setStandbyZGyroEnabled(bool enabled); + + // FIFO_COUNT_* registers + uint16_t getFIFOCount(); + + // FIFO_R_W register + uint8_t getFIFOByte(); + void setFIFOByte(uint8_t data); + void getFIFOBytes(uint8_t *data, uint8_t length); + + // WHO_AM_I register + uint8_t getDeviceID(); + void setDeviceID(uint8_t id); + + // ======== UNDOCUMENTED/DMP REGISTERS/METHODS ======== + + // XG_OFFS_TC register + uint8_t getOTPBankValid(); + void setOTPBankValid(bool enabled); + int8_t getXGyroOffsetTC(); + void setXGyroOffsetTC(int8_t offset); + + // YG_OFFS_TC register + int8_t getYGyroOffsetTC(); + void setYGyroOffsetTC(int8_t offset); + + // ZG_OFFS_TC register + int8_t getZGyroOffsetTC(); + void setZGyroOffsetTC(int8_t offset); + + // X_FINE_GAIN register + int8_t getXFineGain(); + void setXFineGain(int8_t gain); + + // Y_FINE_GAIN register + int8_t getYFineGain(); + void setYFineGain(int8_t gain); + + // Z_FINE_GAIN register + int8_t getZFineGain(); + void setZFineGain(int8_t gain); + + // XA_OFFS_* registers + int16_t getXAccelOffset(); + void setXAccelOffset(int16_t offset); + + // YA_OFFS_* register + int16_t getYAccelOffset(); + void setYAccelOffset(int16_t offset); + + // ZA_OFFS_* register + int16_t getZAccelOffset(); + void setZAccelOffset(int16_t offset); + + // XG_OFFS_USR* registers + int16_t getXGyroOffset(); + void setXGyroOffset(int16_t offset); + + // YG_OFFS_USR* register + int16_t getYGyroOffset(); + void setYGyroOffset(int16_t offset); + + // ZG_OFFS_USR* register + int16_t getZGyroOffset(); + void setZGyroOffset(int16_t offset); + + // INT_ENABLE register (DMP functions) + bool getIntPLLReadyEnabled(); + void setIntPLLReadyEnabled(bool enabled); + bool getIntDMPEnabled(); + void setIntDMPEnabled(bool enabled); + + // DMP_INT_STATUS + bool getDMPInt5Status(); + bool getDMPInt4Status(); + bool getDMPInt3Status(); + bool getDMPInt2Status(); + bool getDMPInt1Status(); + bool getDMPInt0Status(); + + // INT_STATUS register (DMP functions) + bool getIntPLLReadyStatus(); + bool getIntDMPStatus(); + + // USER_CTRL register (DMP functions) + bool getDMPEnabled(); + void setDMPEnabled(bool enabled); + void resetDMP(); + + // BANK_SEL register + void setMemoryBank(uint8_t bank, bool prefetchEnabled = false, bool userBank = false); + + // MEM_START_ADDR register + void setMemoryStartAddress(uint8_t address); + + // MEM_R_W register + uint8_t readMemoryByte(); + void writeMemoryByte(uint8_t data); + void readMemoryBlock(uint8_t *data, uint16_t dataSize, uint8_t bank = 0, uint8_t address = 0); + // bool writeMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank = 0, uint8_t address = 0, bool verify = true, bool useProgMem = false); + bool writeMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank = 0, uint8_t address = 0, bool verify = true); + // bool writeProgMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank = 0, uint8_t address = 0, bool verify = true); + + // bool writeDMPConfigurationSet(const uint8_t *data, uint16_t dataSize, bool useProgMem = false); + bool writeDMPConfigurationSet(const uint8_t *data, uint16_t dataSize); + // bool writeProgDMPConfigurationSet(const uint8_t *data, uint16_t dataSize); + + // DMP_CFG_1 register + uint8_t getDMPConfig1(); + void setDMPConfig1(uint8_t config); + + // DMP_CFG_2 register + uint8_t getDMPConfig2(); + void setDMPConfig2(uint8_t config); + +// special methods for MotionApps 2.0 implementation +#ifdef MPU6050_INCLUDE_DMP_MOTIONAPPS20 + uint8_t *dmpPacketBuffer; + uint16_t dmpPacketSize; + + uint8_t dmpInitialize(); + bool dmpPacketAvailable(); + + uint8_t dmpSetFIFORate(uint8_t fifoRate); + uint8_t dmpGetFIFORate(); + uint8_t dmpGetSampleStepSizeMS(); + uint8_t dmpGetSampleFrequency(); + int32_t dmpDecodeTemperature(int8_t tempReg); + + // Register callbacks after a packet of FIFO data is processed + //uint8_t dmpRegisterFIFORateProcess(inv_obj_func func, int16_t priority); + //uint8_t dmpUnregisterFIFORateProcess(inv_obj_func func); + uint8_t dmpRunFIFORateProcesses(); + + // Setup FIFO for various output + uint8_t dmpSendQuaternion(uint_fast16_t accuracy); + uint8_t dmpSendGyro(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendAccel(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendLinearAccel(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendLinearAccelInWorld(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendControlData(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendSensorData(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendExternalSensorData(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendGravity(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendPacketNumber(uint_fast16_t accuracy); + uint8_t dmpSendQuantizedAccel(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendEIS(uint_fast16_t elements, uint_fast16_t accuracy); + + // Get Fixed Point data from FIFO + uint8_t dmpGetAccel(int32_t *data, const uint8_t *packet = 0); + uint8_t dmpGetAccel(int16_t *data, const uint8_t *packet = 0); + uint8_t dmpGetAccel(VectorInt16 *v, const uint8_t *packet = 0); + uint8_t dmpGetQuaternion(int32_t *data, const uint8_t *packet = 0); + uint8_t dmpGetQuaternion(int16_t *data, const uint8_t *packet = 0); + uint8_t dmpGetQuaternion(Quaternion *q, const uint8_t *packet = 0); + uint8_t dmpGet6AxisQuaternion(int32_t *data, const uint8_t *packet = 0); + uint8_t dmpGet6AxisQuaternion(int16_t *data, const uint8_t *packet = 0); + uint8_t dmpGet6AxisQuaternion(Quaternion *q, const uint8_t *packet = 0); + uint8_t dmpGetRelativeQuaternion(int32_t *data, const uint8_t *packet = 0); + uint8_t dmpGetRelativeQuaternion(int16_t *data, const uint8_t *packet = 0); + uint8_t dmpGetRelativeQuaternion(Quaternion *data, const uint8_t *packet = 0); + uint8_t dmpGetGyro(int32_t *data, const uint8_t *packet = 0); + uint8_t dmpGetGyro(int16_t *data, const uint8_t *packet = 0); + uint8_t dmpGetGyro(VectorInt16 *v, const uint8_t *packet = 0); + uint8_t dmpSetLinearAccelFilterCoefficient(float coef); + uint8_t dmpGetLinearAccel(int32_t *data, const uint8_t *packet = 0); + uint8_t dmpGetLinearAccel(int16_t *data, const uint8_t *packet = 0); + uint8_t dmpGetLinearAccel(VectorInt16 *v, const uint8_t *packet = 0); + uint8_t dmpGetLinearAccel(VectorInt16 *v, VectorInt16 *vRaw, VectorFloat *gravity); + uint8_t dmpGetLinearAccelInWorld(int32_t *data, const uint8_t *packet = 0); + uint8_t dmpGetLinearAccelInWorld(int16_t *data, const uint8_t *packet = 0); + uint8_t dmpGetLinearAccelInWorld(VectorInt16 *v, const uint8_t *packet = 0); + uint8_t dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Quaternion *q); + uint8_t dmpGetGyroAndAccelSensor(int32_t *data, const uint8_t *packet = 0); + uint8_t dmpGetGyroAndAccelSensor(int16_t *data, const uint8_t *packet = 0); + uint8_t dmpGetGyroAndAccelSensor(VectorInt16 *g, VectorInt16 *a, const uint8_t *packet = 0); + uint8_t dmpGetGyroSensor(int32_t *data, const uint8_t *packet = 0); + uint8_t dmpGetGyroSensor(int16_t *data, const uint8_t *packet = 0); + uint8_t dmpGetGyroSensor(VectorInt16 *v, const uint8_t *packet = 0); + uint8_t dmpGetControlData(int32_t *data, const uint8_t *packet = 0); + uint8_t dmpGetTemperature(int32_t *data, const uint8_t *packet = 0); + uint8_t dmpGetGravity(int32_t *data, const uint8_t *packet = 0); + uint8_t dmpGetGravity(int16_t *data, const uint8_t *packet = 0); + uint8_t dmpGetGravity(VectorInt16 *v, const uint8_t *packet = 0); + uint8_t dmpGetGravity(VectorFloat *v, Quaternion *q); + uint8_t dmpGetUnquantizedAccel(int32_t *data, const uint8_t *packet = 0); + uint8_t dmpGetUnquantizedAccel(int16_t *data, const uint8_t *packet = 0); + uint8_t dmpGetUnquantizedAccel(VectorInt16 *v, const uint8_t *packet = 0); + uint8_t dmpGetQuantizedAccel(int32_t *data, const uint8_t *packet = 0); + uint8_t dmpGetQuantizedAccel(int16_t *data, const uint8_t *packet = 0); + uint8_t dmpGetQuantizedAccel(VectorInt16 *v, const uint8_t *packet = 0); + uint8_t dmpGetExternalSensorData(int32_t *data, uint16_t size, const uint8_t *packet = 0); + uint8_t dmpGetEIS(int32_t *data, const uint8_t *packet = 0); + + uint8_t dmpGetEuler(float *data, Quaternion *q); + uint8_t dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity); + + // Get Floating Point data from FIFO + uint8_t dmpGetAccelFloat(float *data, const uint8_t *packet = 0); + uint8_t dmpGetQuaternionFloat(float *data, const uint8_t *packet = 0); + + uint8_t dmpProcessFIFOPacket(const unsigned char *dmpData); + uint8_t dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *processed = NULL); + + uint8_t dmpSetFIFOProcessedCallback(void (*func)(void)); + + uint8_t dmpInitFIFOParam(); + uint8_t dmpCloseFIFO(); + uint8_t dmpSetGyroDataSource(uint8_t source); + uint8_t dmpDecodeQuantizedAccel(); + uint32_t dmpGetGyroSumOfSquare(); + uint32_t dmpGetAccelSumOfSquare(); + void dmpOverrideQuaternion(long *q); + uint16_t dmpGetFIFOPacketSize(); +#endif + +// special methods for MotionApps 4.1 implementation +#ifdef MPU6050_INCLUDE_DMP_MOTIONAPPS41 + uint8_t *dmpPacketBuffer; + uint16_t dmpPacketSize; + + uint8_t dmpInitialize(); + bool dmpPacketAvailable(); + + uint8_t dmpSetFIFORate(uint8_t fifoRate); + uint8_t dmpGetFIFORate(); + uint8_t dmpGetSampleStepSizeMS(); + uint8_t dmpGetSampleFrequency(); + int32_t dmpDecodeTemperature(int8_t tempReg); + + // Register callbacks after a packet of FIFO data is processed + //uint8_t dmpRegisterFIFORateProcess(inv_obj_func func, int16_t priority); + //uint8_t dmpUnregisterFIFORateProcess(inv_obj_func func); + uint8_t dmpRunFIFORateProcesses(); + + // Setup FIFO for various output + uint8_t dmpSendQuaternion(uint_fast16_t accuracy); + uint8_t dmpSendGyro(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendAccel(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendLinearAccel(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendLinearAccelInWorld(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendControlData(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendSensorData(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendExternalSensorData(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendGravity(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendPacketNumber(uint_fast16_t accuracy); + uint8_t dmpSendQuantizedAccel(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendEIS(uint_fast16_t elements, uint_fast16_t accuracy); + + // Get Fixed Point data from FIFO + uint8_t dmpGetAccel(int32_t *data, const uint8_t *packet = 0); + uint8_t dmpGetAccel(int16_t *data, const uint8_t *packet = 0); + uint8_t dmpGetAccel(VectorInt16 *v, const uint8_t *packet = 0); + uint8_t dmpGetQuaternion(int32_t *data, const uint8_t *packet = 0); + uint8_t dmpGetQuaternion(int16_t *data, const uint8_t *packet = 0); + uint8_t dmpGetQuaternion(Quaternion *q, const uint8_t *packet = 0); + uint8_t dmpGet6AxisQuaternion(int32_t *data, const uint8_t *packet = 0); + uint8_t dmpGet6AxisQuaternion(int16_t *data, const uint8_t *packet = 0); + uint8_t dmpGet6AxisQuaternion(Quaternion *q, const uint8_t *packet = 0); + uint8_t dmpGetRelativeQuaternion(int32_t *data, const uint8_t *packet = 0); + uint8_t dmpGetRelativeQuaternion(int16_t *data, const uint8_t *packet = 0); + uint8_t dmpGetRelativeQuaternion(Quaternion *data, const uint8_t *packet = 0); + uint8_t dmpGetGyro(int32_t *data, const uint8_t *packet = 0); + uint8_t dmpGetGyro(int16_t *data, const uint8_t *packet = 0); + uint8_t dmpGetGyro(VectorInt16 *v, const uint8_t *packet = 0); + uint8_t dmpGetMag(int16_t *data, const uint8_t *packet = 0); + uint8_t dmpSetLinearAccelFilterCoefficient(float coef); + uint8_t dmpGetLinearAccel(int32_t *data, const uint8_t *packet = 0); + uint8_t dmpGetLinearAccel(int16_t *data, const uint8_t *packet = 0); + uint8_t dmpGetLinearAccel(VectorInt16 *v, const uint8_t *packet = 0); + uint8_t dmpGetLinearAccel(VectorInt16 *v, VectorInt16 *vRaw, VectorFloat *gravity); + uint8_t dmpGetLinearAccelInWorld(int32_t *data, const uint8_t *packet = 0); + uint8_t dmpGetLinearAccelInWorld(int16_t *data, const uint8_t *packet = 0); + uint8_t dmpGetLinearAccelInWorld(VectorInt16 *v, const uint8_t *packet = 0); + uint8_t dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Quaternion *q); + uint8_t dmpGetGyroAndAccelSensor(int32_t *data, const uint8_t *packet = 0); + uint8_t dmpGetGyroAndAccelSensor(int16_t *data, const uint8_t *packet = 0); + uint8_t dmpGetGyroAndAccelSensor(VectorInt16 *g, VectorInt16 *a, const uint8_t *packet = 0); + uint8_t dmpGetGyroSensor(int32_t *data, const uint8_t *packet = 0); + uint8_t dmpGetGyroSensor(int16_t *data, const uint8_t *packet = 0); + uint8_t dmpGetGyroSensor(VectorInt16 *v, const uint8_t *packet = 0); + uint8_t dmpGetControlData(int32_t *data, const uint8_t *packet = 0); + uint8_t dmpGetTemperature(int32_t *data, const uint8_t *packet = 0); + uint8_t dmpGetGravity(int32_t *data, const uint8_t *packet = 0); + uint8_t dmpGetGravity(int16_t *data, const uint8_t *packet = 0); + uint8_t dmpGetGravity(VectorInt16 *v, const uint8_t *packet = 0); + uint8_t dmpGetGravity(VectorFloat *v, Quaternion *q); + uint8_t dmpGetUnquantizedAccel(int32_t *data, const uint8_t *packet = 0); + uint8_t dmpGetUnquantizedAccel(int16_t *data, const uint8_t *packet = 0); + uint8_t dmpGetUnquantizedAccel(VectorInt16 *v, const uint8_t *packet = 0); + uint8_t dmpGetQuantizedAccel(int32_t *data, const uint8_t *packet = 0); + uint8_t dmpGetQuantizedAccel(int16_t *data, const uint8_t *packet = 0); + uint8_t dmpGetQuantizedAccel(VectorInt16 *v, const uint8_t *packet = 0); + uint8_t dmpGetExternalSensorData(int32_t *data, uint16_t size, const uint8_t *packet = 0); + uint8_t dmpGetEIS(int32_t *data, const uint8_t *packet = 0); + + uint8_t dmpGetEuler(float *data, Quaternion *q); + uint8_t dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity); + + // Get Floating Point data from FIFO + uint8_t dmpGetAccelFloat(float *data, const uint8_t *packet = 0); + uint8_t dmpGetQuaternionFloat(float *data, const uint8_t *packet = 0); + + uint8_t dmpProcessFIFOPacket(const unsigned char *dmpData); + uint8_t dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *processed = NULL); + + uint8_t dmpSetFIFOProcessedCallback(void (*func)(void)); + + uint8_t dmpInitFIFOParam(); + uint8_t dmpCloseFIFO(); + uint8_t dmpSetGyroDataSource(uint8_t source); + uint8_t dmpDecodeQuantizedAccel(); + uint32_t dmpGetGyroSumOfSquare(); + uint32_t dmpGetAccelSumOfSquare(); + void dmpOverrideQuaternion(long *q); + uint16_t dmpGetFIFOPacketSize(); +#endif + + private: + uint8_t devAddr; + uint8_t buffer[14]; +}; + +#endif /* _MPU6050_H_ */ \ No newline at end of file From 91eef05a74e0ab2623eaeb7fee5b70ca65483b8c Mon Sep 17 00:00:00 2001 From: Mateus Amarante Araujo Date: Sun, 25 Feb 2018 21:17:07 -0300 Subject: [PATCH 191/335] Ported MPU6050_calibration.ino skecth to BeagleBone Black --- .../MPU6050/MPU6050_calibration.cpp | 221 ++++++++++++++++++ 1 file changed, 221 insertions(+) create mode 100644 BeagleBoneBlack/MPU6050/MPU6050_calibration.cpp diff --git a/BeagleBoneBlack/MPU6050/MPU6050_calibration.cpp b/BeagleBoneBlack/MPU6050/MPU6050_calibration.cpp new file mode 100644 index 00000000..6eb84766 --- /dev/null +++ b/BeagleBoneBlack/MPU6050/MPU6050_calibration.cpp @@ -0,0 +1,221 @@ + +// Arduino sketch that returns calibration offsets for MPU6050 // Version 1.1 (31th January 2014) +// Done by Luis Ródenas +// Based on the I2Cdev library and previous work by Jeff Rowberg +// Updates (of the library) should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +//TODO: include author info + +// These offsets were meant to calibrate MPU6050's internal DMP, but can be also useful for reading sensors. +// The effect of temperature has not been taken into account so I can't promise that it will work if you +// calibrate indoors and then use it outdoors. Best is to calibrate and use at the same room temperature. + +/* ========== LICENSE ================================== + I2Cdev device library code is placed under the MIT license + Copyright (c) 2011 Jeff Rowberg + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ========================================================= + */ + +// I2Cdev and MPU6050 must be installed as libraries +#include "../I2Cdev/I2Cdev.h" //FIXME +#include "MPU6050.h" +#include +#include + +#define DEFAULT_BUFFER_SIZE 1000 //Amount of readings used to average, make it higher to get more precision but sketch will be slower (default:1000) +#define DEFAULT_ACCEL_DEADZONE 8 //Acelerometer error allowed, make it lower to get more precision, but sketch may not converge (default:8) +#define DEFAULT_GYRO_DEADZONE 1 //Giro error allowed, make it lower to get more precision, but sketch may not converge (default:1) + +struct ImuValues +{ + int16_t ax = 0, ay = 0, az = 0; + int16_t gx = 0, gy = 0, gz = 0; +}; + +void resetOffsets(MPU6050 *mpu); + +//return mean values +ImuValues meansensors(MPU6050 *mpu, int buffersize); + +//return offsets +ImuValues calibration(MPU6050 *mpu, int buffersize, int16_t accel_deadzone, int16_t gyro_deadzone); + +int main() +{ + + int buffersize = DEFAULT_BUFFER_SIZE; + int16_t accel_deadzone = DEFAULT_ACCEL_DEADZONE; + int16_t gyro_deadzone = DEFAULT_GYRO_DEADZONE; + + MPU6050 mpu; + + mpu.initialize(); + + printf("Send any character to start sketch.\n\n"); + getchar(); + usleep(1500*1000); + + // start message + printf("\nMPU6050 Calibration Sketch\n"); + sleep(2); + printf("\nYour MPU6050 should be placed in horizontal position, with package letters facing up. \nDon't touch it until you see a finish message.\n\n"); + sleep(3); + + // verify connection + if (mpu.testConnection()) + { + printf("MPU6050 connection successful\n"); + } + else + { + printf("MPU6050 connection failed\n"); + return -1; + } + + sleep(1); + + resetOffsets(&mpu); + + printf("\nReading sensors for first time...\n"); + + ImuValues mean = meansensors(&mpu, buffersize); + sleep(1); + + printf("\nCalculating offsets...\n"); + ImuValues offsets = calibration(&mpu, buffersize, accel_deadzone, gyro_deadzone); + sleep(1); + + mean = meansensors(&mpu, buffersize); + printf("\nFINISHED\n"); + printf("Sensor readings with offsets:\t%d\t%d\t%d\t%d\n", mean.ax, mean.ay, mean.az, mean.gx, mean.gy, mean.gz); + printf("Your offsets:\t%d\t%d\t%d\t%d\n", offsets.ax, offsets.ay, offsets.az, offsets.gx, offsets.gy, offsets.gz); + printf("\nData is printed as: acelX acelY acelZ giroX giroY giroZ\n"); + printf("Check that your sensor readings are close to 0 0 16384 0 0 0\n"); + printf("If calibration was succesful write down your offsets so you can set them in your projects using something similar to mpu.setXAccelOffset(youroffset)\n"); + + return 0; +} + +void resetOffsets(MPU6050 *imu) +{ + imu->setXAccelOffset(0); + imu->setYAccelOffset(0); + imu->setZAccelOffset(0); + imu->setXGyroOffset(0); + imu->setYGyroOffset(0); + imu->setZGyroOffset(0); +} + +//return mean values +ImuValues meansensors(MPU6050 *mpu, int buffersize) +{ + long i = 0, buff_ax = 0, buff_ay = 0, buff_az = 0, buff_gx = 0, buff_gy = 0, buff_gz = 0; + ImuValues mean; + + while (i < (buffersize + 101)) + { + // read raw accel/gyro measurements from device + mpu->getMotion6(&mean.ax, &mean.ay, &mean.az, &mean.gx, &mean.gy, &mean.gz); + + if (i > 100 && i <= (buffersize + 100)) + { //First 100 measures are discarded + buff_ax = buff_ax + mean.ax; + buff_ay = buff_ay + mean.ay; + buff_az = buff_az + mean.az; + buff_gx = buff_gx + mean.gx; + buff_gy = buff_gy + mean.gy; + buff_gz = buff_gz + mean.gz; + } + if (i == (buffersize + 100)) + { + mean.ax = buff_ax / buffersize; + mean.ay = buff_ay / buffersize; + mean.az = buff_az / buffersize; + mean.gx = buff_gx / buffersize; + mean.gy = buff_gy / buffersize; + mean.gz = buff_gz / buffersize; + } + i++; + usleep(2000); //Needed so we don't get repeated measures + } + + return mean; +} + +ImuValues calibration(MPU6050 *mpu, ImuValues mean, int buffersize, int16_t accel_deadzone, int16_t gyro_deadzone) +{ + ImuValues offset; + + offset.ax = -mean.ax / 8; + offset.ay = -mean.ay / 8; + offset.az = (16384 - mean.az) / 8; + + offset.gx = -mean.gx / 4; + offset.gy = -mean.gy / 4; + offset.gz = -mean.gz / 4; + + while (1) + { + int ready = 0; + mpu->setXAccelOffset(offset.ax); + mpu->setYAccelOffset(offset.ay); + mpu->setZAccelOffset(offset.az); + + mpu->setXGyroOffset(offset.gx); + mpu->setYGyroOffset(offset.gy); + mpu->setZGyroOffset(offset.gz); + + mean = meansensors(mpu, buffersize); + printf("...\n"); + + if (abs(mean.ax) <= accel_deadzone) + ready++; + else + offset.ax = offset.ax - mean.ax / accel_deadzone; + + if (abs(mean.ay) <= accel_deadzone) + ready++; + else + offset.ay = offset.ay - mean.ay / accel_deadzone; + + if (abs(16384 - mean.az) <= accel_deadzone) + ready++; + else + offset.az = offset.az + (16384 - mean.az) / accel_deadzone; + + if (abs(mean.gx) <= gyro_deadzone) + ready++; + else + offset.gx = offset.gx - mean.gx / (gyro_deadzone + 1); + + if (abs(mean.gy) <= gyro_deadzone) + ready++; + else + offset.gy = offset.gy - mean.gy / (gyro_deadzone + 1); + + if (abs(mean.gz) <= gyro_deadzone) + ready++; + else + offset.gz = offset.gz - mean.gz / (gyro_deadzone + 1); + + if (ready == 6) + break; + } +} From 75d23ae976c356e59395fb9abdb86eb4ae29a66f Mon Sep 17 00:00:00 2001 From: Mateus Amarante Araujo Date: Fri, 2 Mar 2018 18:40:26 -0300 Subject: [PATCH 192/335] BeagleBone I2Cdev port - Initial Release --- BeagleBoneBlack/I2Cdev/I2Cdev.cpp | 61 +++-- BeagleBoneBlack/I2Cdev/I2Cdev.h | 16 +- BeagleBoneBlack/MPU6050/MPU6050.h | 2 +- .../MPU6050/MPU6050_calibration.cpp | 221 ------------------ 4 files changed, 56 insertions(+), 244 deletions(-) delete mode 100644 BeagleBoneBlack/MPU6050/MPU6050_calibration.cpp diff --git a/BeagleBoneBlack/I2Cdev/I2Cdev.cpp b/BeagleBoneBlack/I2Cdev/I2Cdev.cpp index 1bb4f6a7..2b2d150b 100644 --- a/BeagleBoneBlack/I2Cdev/I2Cdev.cpp +++ b/BeagleBoneBlack/I2Cdev/I2Cdev.cpp @@ -1,7 +1,10 @@ // I2Cdev library collection - Main I2C device class // Abstracts bit and byte I2C R/W functions into a convenient class // Based on Arduino's I2Cdev by Jeff Rowberg +// BeagleBone Black (potencially other linux boards) port by Mateus Amarante // +// Changelog: +// 2018-03-02 - Initial release /* ============================================ I2Cdev device library code is placed under the MIT license @@ -24,19 +27,22 @@ THE SOFTWARE. */ #include "I2Cdev.h" +#include +#include +#include +#include #include +#include +#include +#include #define I2C_PATH "/dev/i2c-2" -I2Cdev::I2Cdev() {} +I2Cdev::I2Cdev() : I2Cdev(DEFAULT_BBB_I2C_BUS) {} -void I2Cdev::initialize() {} - -/** Enable or disable I2C, - * @param isEnabled true = enable, false = disable - */ -void I2Cdev::enable(bool isEnabled) +I2Cdev::I2Cdev(uint8_t busAddr) { + sprintf(path_, "/dev/i2c-%hhd", busAddr); } /** Read a single bit from an 8-bit device register. @@ -162,7 +168,7 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 { int fd; - if ((fd = open(I2C_PATH, O_RDWR) < 0)) + if ((fd = open(I2C_PATH, O_RDWR)) < 0) { perror("Failed to open " I2C_PATH); return -1; @@ -170,10 +176,15 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 if (ioctl(fd, I2C_SLAVE, devAddr) < 0) { - fprintf(stderr, "Failed to access slave at %u address\n", devAddr); + fprintf(stderr, "Failed to access slave at %u address. %s\n", regAddr, strerror(errno)); return -1; } + if (write(fd, ®Addr, 1) != 1) + { + perror("Failed to write data into " I2C_PATH); + } + if (read(fd, data, length) != length) { perror("Failed to read data from " I2C_PATH); @@ -195,8 +206,16 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 */ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data) { - if (readBytes(devAddr, regAddr, length * 2, reinterpret_cast(data)) > 0) + uint8_t buff[length * 2]; + + if (readBytes(devAddr, regAddr, length * 2, buff) > 0) + { + for (int i = 0; i < length; i++) + { + data[i] = (buff[i * 2] << 8) | buff[i * 2 + 1]; + } return length; + } return -1; } @@ -330,7 +349,7 @@ bool I2Cdev::writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_ { int fd; - if ((fd = open(I2C_PATH, O_RDWR) < 0)) + if ((fd = open(I2C_PATH, O_RDWR)) < 0) { perror("Failed to open " I2C_PATH); return false; @@ -338,11 +357,17 @@ bool I2Cdev::writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_ if (ioctl(fd, I2C_SLAVE, devAddr) < 0) { - fprintf(stderr, "Failed to access slave at %u address\n", devAddr); + fprintf(stderr, "Failed to access slave at %u address. %s\n", regAddr, strerror(errno)); return false; } - if (write(fd, data, length) != length) + uint16_t buff_length = length + 1; + uint8_t buff[buff_length]; + buff[0] = regAddr; + + memcpy(&buff[1], data, length); + + if (write(fd, buff, buff_length) != buff_length) { perror("Failed to write into " I2C_PATH); return false; @@ -362,5 +387,13 @@ bool I2Cdev::writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_ */ bool I2Cdev::writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data) { - return writeBytes(devAddr, regAddr, length * 2, reinterpret_cast(data)); + uint8_t buff[length * 2]; + + for (int i = 0; i < length; i++) + { + buff[2 * i] = (uint8_t)(data[i] >> 8); //MSByte + buff[1 + 2 * i] = (uint8_t)(data[i] >> 0); //LSByte + } + + return writeBytes(devAddr, regAddr, length * 2, buff); } \ No newline at end of file diff --git a/BeagleBoneBlack/I2Cdev/I2Cdev.h b/BeagleBoneBlack/I2Cdev/I2Cdev.h index ac1bb0b9..edf15ba2 100644 --- a/BeagleBoneBlack/I2Cdev/I2Cdev.h +++ b/BeagleBoneBlack/I2Cdev/I2Cdev.h @@ -1,7 +1,10 @@ // I2Cdev library collection - Main I2C device class // Abstracts bit and byte I2C R/W functions into a convenient class // Based on Arduino's I2Cdev by Jeff Rowberg +// BeagleBone Black (potencially other linux boards) port by Mateus Amarante // +// Changelog: +// 2018-03-02 - Initial release /* ============================================ I2Cdev device library code is placed under the MIT license @@ -26,19 +29,15 @@ THE SOFTWARE. #ifndef _I2CDEV_H_ #define _I2CDEV_H_ -#include -#include -#include #include -#include + +#define DEFAULT_BBB_I2C_BUS 2 class I2Cdev { public: I2Cdev(); - - static void initialize(); - static void enable(bool isEnabled); + I2Cdev(uint8_t busAddr); static int8_t readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data); static int8_t readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data); @@ -58,7 +57,8 @@ class I2Cdev static bool writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data); static bool writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data); - static uint16_t readTimeout; +private: + char path_[13]; // Maximum is "/dev/i2c-255" }; #endif /* _I2CDEV_H_ */ diff --git a/BeagleBoneBlack/MPU6050/MPU6050.h b/BeagleBoneBlack/MPU6050/MPU6050.h index 27549fb0..935494f5 100644 --- a/BeagleBoneBlack/MPU6050/MPU6050.h +++ b/BeagleBoneBlack/MPU6050/MPU6050.h @@ -34,7 +34,7 @@ THE SOFTWARE. #ifndef _MPU6050_H_ #define _MPU6050_H_ -#include "../I2Cdev/I2Cdev.h" //FIXME +#include "I2Cdev.h" #define MPU6050_ADDRESS_AD0_LOW 0x68 // address pin low (GND), default for InvenSense evaluation board #define MPU6050_ADDRESS_AD0_HIGH 0x69 // address pin high (VCC) diff --git a/BeagleBoneBlack/MPU6050/MPU6050_calibration.cpp b/BeagleBoneBlack/MPU6050/MPU6050_calibration.cpp deleted file mode 100644 index 6eb84766..00000000 --- a/BeagleBoneBlack/MPU6050/MPU6050_calibration.cpp +++ /dev/null @@ -1,221 +0,0 @@ - -// Arduino sketch that returns calibration offsets for MPU6050 // Version 1.1 (31th January 2014) -// Done by Luis Ródenas -// Based on the I2Cdev library and previous work by Jeff Rowberg -// Updates (of the library) should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib -//TODO: include author info - -// These offsets were meant to calibrate MPU6050's internal DMP, but can be also useful for reading sensors. -// The effect of temperature has not been taken into account so I can't promise that it will work if you -// calibrate indoors and then use it outdoors. Best is to calibrate and use at the same room temperature. - -/* ========== LICENSE ================================== - I2Cdev device library code is placed under the MIT license - Copyright (c) 2011 Jeff Rowberg - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - ========================================================= - */ - -// I2Cdev and MPU6050 must be installed as libraries -#include "../I2Cdev/I2Cdev.h" //FIXME -#include "MPU6050.h" -#include -#include - -#define DEFAULT_BUFFER_SIZE 1000 //Amount of readings used to average, make it higher to get more precision but sketch will be slower (default:1000) -#define DEFAULT_ACCEL_DEADZONE 8 //Acelerometer error allowed, make it lower to get more precision, but sketch may not converge (default:8) -#define DEFAULT_GYRO_DEADZONE 1 //Giro error allowed, make it lower to get more precision, but sketch may not converge (default:1) - -struct ImuValues -{ - int16_t ax = 0, ay = 0, az = 0; - int16_t gx = 0, gy = 0, gz = 0; -}; - -void resetOffsets(MPU6050 *mpu); - -//return mean values -ImuValues meansensors(MPU6050 *mpu, int buffersize); - -//return offsets -ImuValues calibration(MPU6050 *mpu, int buffersize, int16_t accel_deadzone, int16_t gyro_deadzone); - -int main() -{ - - int buffersize = DEFAULT_BUFFER_SIZE; - int16_t accel_deadzone = DEFAULT_ACCEL_DEADZONE; - int16_t gyro_deadzone = DEFAULT_GYRO_DEADZONE; - - MPU6050 mpu; - - mpu.initialize(); - - printf("Send any character to start sketch.\n\n"); - getchar(); - usleep(1500*1000); - - // start message - printf("\nMPU6050 Calibration Sketch\n"); - sleep(2); - printf("\nYour MPU6050 should be placed in horizontal position, with package letters facing up. \nDon't touch it until you see a finish message.\n\n"); - sleep(3); - - // verify connection - if (mpu.testConnection()) - { - printf("MPU6050 connection successful\n"); - } - else - { - printf("MPU6050 connection failed\n"); - return -1; - } - - sleep(1); - - resetOffsets(&mpu); - - printf("\nReading sensors for first time...\n"); - - ImuValues mean = meansensors(&mpu, buffersize); - sleep(1); - - printf("\nCalculating offsets...\n"); - ImuValues offsets = calibration(&mpu, buffersize, accel_deadzone, gyro_deadzone); - sleep(1); - - mean = meansensors(&mpu, buffersize); - printf("\nFINISHED\n"); - printf("Sensor readings with offsets:\t%d\t%d\t%d\t%d\n", mean.ax, mean.ay, mean.az, mean.gx, mean.gy, mean.gz); - printf("Your offsets:\t%d\t%d\t%d\t%d\n", offsets.ax, offsets.ay, offsets.az, offsets.gx, offsets.gy, offsets.gz); - printf("\nData is printed as: acelX acelY acelZ giroX giroY giroZ\n"); - printf("Check that your sensor readings are close to 0 0 16384 0 0 0\n"); - printf("If calibration was succesful write down your offsets so you can set them in your projects using something similar to mpu.setXAccelOffset(youroffset)\n"); - - return 0; -} - -void resetOffsets(MPU6050 *imu) -{ - imu->setXAccelOffset(0); - imu->setYAccelOffset(0); - imu->setZAccelOffset(0); - imu->setXGyroOffset(0); - imu->setYGyroOffset(0); - imu->setZGyroOffset(0); -} - -//return mean values -ImuValues meansensors(MPU6050 *mpu, int buffersize) -{ - long i = 0, buff_ax = 0, buff_ay = 0, buff_az = 0, buff_gx = 0, buff_gy = 0, buff_gz = 0; - ImuValues mean; - - while (i < (buffersize + 101)) - { - // read raw accel/gyro measurements from device - mpu->getMotion6(&mean.ax, &mean.ay, &mean.az, &mean.gx, &mean.gy, &mean.gz); - - if (i > 100 && i <= (buffersize + 100)) - { //First 100 measures are discarded - buff_ax = buff_ax + mean.ax; - buff_ay = buff_ay + mean.ay; - buff_az = buff_az + mean.az; - buff_gx = buff_gx + mean.gx; - buff_gy = buff_gy + mean.gy; - buff_gz = buff_gz + mean.gz; - } - if (i == (buffersize + 100)) - { - mean.ax = buff_ax / buffersize; - mean.ay = buff_ay / buffersize; - mean.az = buff_az / buffersize; - mean.gx = buff_gx / buffersize; - mean.gy = buff_gy / buffersize; - mean.gz = buff_gz / buffersize; - } - i++; - usleep(2000); //Needed so we don't get repeated measures - } - - return mean; -} - -ImuValues calibration(MPU6050 *mpu, ImuValues mean, int buffersize, int16_t accel_deadzone, int16_t gyro_deadzone) -{ - ImuValues offset; - - offset.ax = -mean.ax / 8; - offset.ay = -mean.ay / 8; - offset.az = (16384 - mean.az) / 8; - - offset.gx = -mean.gx / 4; - offset.gy = -mean.gy / 4; - offset.gz = -mean.gz / 4; - - while (1) - { - int ready = 0; - mpu->setXAccelOffset(offset.ax); - mpu->setYAccelOffset(offset.ay); - mpu->setZAccelOffset(offset.az); - - mpu->setXGyroOffset(offset.gx); - mpu->setYGyroOffset(offset.gy); - mpu->setZGyroOffset(offset.gz); - - mean = meansensors(mpu, buffersize); - printf("...\n"); - - if (abs(mean.ax) <= accel_deadzone) - ready++; - else - offset.ax = offset.ax - mean.ax / accel_deadzone; - - if (abs(mean.ay) <= accel_deadzone) - ready++; - else - offset.ay = offset.ay - mean.ay / accel_deadzone; - - if (abs(16384 - mean.az) <= accel_deadzone) - ready++; - else - offset.az = offset.az + (16384 - mean.az) / accel_deadzone; - - if (abs(mean.gx) <= gyro_deadzone) - ready++; - else - offset.gx = offset.gx - mean.gx / (gyro_deadzone + 1); - - if (abs(mean.gy) <= gyro_deadzone) - ready++; - else - offset.gy = offset.gy - mean.gy / (gyro_deadzone + 1); - - if (abs(mean.gz) <= gyro_deadzone) - ready++; - else - offset.gz = offset.gz - mean.gz / (gyro_deadzone + 1); - - if (ready == 6) - break; - } -} From d3028cd440531ef3dd0cb00155944ce101e8ac7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateus=20Amarante=20Ara=C3=BAjo?= Date: Tue, 6 Mar 2018 12:15:07 -0300 Subject: [PATCH 193/335] Fixed busAddr format in path_ string --- BeagleBoneBlack/I2Cdev/I2Cdev.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/BeagleBoneBlack/I2Cdev/I2Cdev.cpp b/BeagleBoneBlack/I2Cdev/I2Cdev.cpp index 2b2d150b..0b2364a6 100644 --- a/BeagleBoneBlack/I2Cdev/I2Cdev.cpp +++ b/BeagleBoneBlack/I2Cdev/I2Cdev.cpp @@ -42,7 +42,7 @@ I2Cdev::I2Cdev() : I2Cdev(DEFAULT_BBB_I2C_BUS) {} I2Cdev::I2Cdev(uint8_t busAddr) { - sprintf(path_, "/dev/i2c-%hhd", busAddr); + sprintf(path_, "/dev/i2c-%hhu", busAddr); } /** Read a single bit from an 8-bit device register. @@ -396,4 +396,4 @@ bool I2Cdev::writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16 } return writeBytes(devAddr, regAddr, length * 2, buff); -} \ No newline at end of file +} From 3899cdd60c54330600a9e34c09847f79f5f56914 Mon Sep 17 00:00:00 2001 From: Mateus Amarante Araujo Date: Mon, 12 Mar 2018 09:54:47 -0300 Subject: [PATCH 194/335] Removed MPU6050. No change against Arduino implementation. --- BeagleBoneBlack/I2Cdev/I2Cdev.cpp | 2 - BeagleBoneBlack/I2Cdev/I2Cdev.h | 2 +- BeagleBoneBlack/MPU6050/MPU6050.cpp | 3501 --------------------------- BeagleBoneBlack/MPU6050/MPU6050.h | 1018 -------- 4 files changed, 1 insertion(+), 4522 deletions(-) delete mode 100644 BeagleBoneBlack/MPU6050/MPU6050.cpp delete mode 100644 BeagleBoneBlack/MPU6050/MPU6050.h diff --git a/BeagleBoneBlack/I2Cdev/I2Cdev.cpp b/BeagleBoneBlack/I2Cdev/I2Cdev.cpp index 0b2364a6..407345c2 100644 --- a/BeagleBoneBlack/I2Cdev/I2Cdev.cpp +++ b/BeagleBoneBlack/I2Cdev/I2Cdev.cpp @@ -36,8 +36,6 @@ THE SOFTWARE. #include #include -#define I2C_PATH "/dev/i2c-2" - I2Cdev::I2Cdev() : I2Cdev(DEFAULT_BBB_I2C_BUS) {} I2Cdev::I2Cdev(uint8_t busAddr) diff --git a/BeagleBoneBlack/I2Cdev/I2Cdev.h b/BeagleBoneBlack/I2Cdev/I2Cdev.h index edf15ba2..245302b5 100644 --- a/BeagleBoneBlack/I2Cdev/I2Cdev.h +++ b/BeagleBoneBlack/I2Cdev/I2Cdev.h @@ -58,7 +58,7 @@ class I2Cdev static bool writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data); private: - char path_[13]; // Maximum is "/dev/i2c-255" + char path_[13]; // up to "/dev/i2c-255" }; #endif /* _I2CDEV_H_ */ diff --git a/BeagleBoneBlack/MPU6050/MPU6050.cpp b/BeagleBoneBlack/MPU6050/MPU6050.cpp deleted file mode 100644 index 745dc37d..00000000 --- a/BeagleBoneBlack/MPU6050/MPU6050.cpp +++ /dev/null @@ -1,3501 +0,0 @@ -// I2Cdev library collection - MPU6050 I2C device class -// Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00) -// 8/24/2011 by Jeff Rowberg -// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib -// -// Changelog: -// ... - ongoing debug release - -// NOTE: THIS IS ONLY A PARIAL RELEASE. THIS DEVICE CLASS IS CURRENTLY UNDERGOING ACTIVE -// DEVELOPMENT AND IS STILL MISSING SOME IMPORTANT FEATURES. PLEASE KEEP THIS IN MIND IF -// YOU DECIDE TO USE THIS PARTICULAR CODE FOR ANYTHING. - -/* ============================================ -I2Cdev device library code is placed under the MIT license -Copyright (c) 2012 Jeff Rowberg - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -=============================================== -*/ - -#include "MPU6050.h" -#include -#include - -/** Default constructor, uses default I2C address. - * @see MPU6050_DEFAULT_ADDRESS - */ -MPU6050::MPU6050() -{ - devAddr = MPU6050_DEFAULT_ADDRESS; -} - -/** Specific address constructor. - * @param address I2C address - * @see MPU6050_DEFAULT_ADDRESS - * @see MPU6050_ADDRESS_AD0_LOW - * @see MPU6050_ADDRESS_AD0_HIGH - */ -MPU6050::MPU6050(uint8_t address) -{ - devAddr = address; -} - -/** Power on and prepare for general usage. - * This will activate the device and take it out of sleep mode (which must be done - * after start-up). This function also sets both the accelerometer and the gyroscope - * to their most sensitive settings, namely +/- 2g and +/- 250 degrees/sec, and sets - * the clock source to use the X Gyro for reference, which is slightly better than - * the default internal clock source. - */ -void MPU6050::initialize() -{ - setClockSource(MPU6050_CLOCK_PLL_XGYRO); - setFullScaleGyroRange(MPU6050_GYRO_FS_250); - setFullScaleAccelRange(MPU6050_ACCEL_FS_2); - setSleepEnabled(false); // thanks to Jack Elston for pointing this one out! -} - -/** Verify the I2C connection. - * Make sure the device is connected and responds as expected. - * @return True if connection is valid, false otherwise - */ -bool MPU6050::testConnection() -{ - return getDeviceID() == 0x34; -} - -// AUX_VDDIO register (InvenSense demo code calls this RA_*G_OFFS_TC) - -/** Get the auxiliary I2C supply voltage level. - * When set to 1, the auxiliary I2C bus high logic level is VDD. When cleared to - * 0, the auxiliary I2C bus high logic level is VLOGIC. This does not apply to - * the MPU-6000, which does not have a VLOGIC pin. - * @return I2C supply voltage level (0=VLOGIC, 1=VDD) - */ -uint8_t MPU6050::getAuxVDDIOLevel() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_PWR_MODE_BIT, buffer); - return buffer[0]; -} -/** Set the auxiliary I2C supply voltage level. - * When set to 1, the auxiliary I2C bus high logic level is VDD. When cleared to - * 0, the auxiliary I2C bus high logic level is VLOGIC. This does not apply to - * the MPU-6000, which does not have a VLOGIC pin. - * @param level I2C supply voltage level (0=VLOGIC, 1=VDD) - */ -void MPU6050::setAuxVDDIOLevel(uint8_t level) -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_PWR_MODE_BIT, level); -} - -// SMPLRT_DIV register - -/** Get gyroscope output rate divider. - * The sensor register output, FIFO output, DMP sampling, Motion detection, Zero - * Motion detection, and Free Fall detection are all based on the Sample Rate. - * The Sample Rate is generated by dividing the gyroscope output rate by - * SMPLRT_DIV: - * - * Sample Rate = Gyroscope Output Rate / (1 + SMPLRT_DIV) - * - * where Gyroscope Output Rate = 8kHz when the DLPF is disabled (DLPF_CFG = 0 or - * 7), and 1kHz when the DLPF is enabled (see Register 26). - * - * Note: The accelerometer output rate is 1kHz. This means that for a Sample - * Rate greater than 1kHz, the same accelerometer sample may be output to the - * FIFO, DMP, and sensor registers more than once. - * - * For a diagram of the gyroscope and accelerometer signal paths, see Section 8 - * of the MPU-6000/MPU-6050 Product Specification document. - * - * @return Current sample rate - * @see MPU6050_RA_SMPLRT_DIV - */ -uint8_t MPU6050::getRate() -{ - I2Cdev::readByte(devAddr, MPU6050_RA_SMPLRT_DIV, buffer); - return buffer[0]; -} -/** Set gyroscope sample rate divider. - * @param rate New sample rate divider - * @see getRate() - * @see MPU6050_RA_SMPLRT_DIV - */ -void MPU6050::setRate(uint8_t rate) -{ - I2Cdev::writeByte(devAddr, MPU6050_RA_SMPLRT_DIV, rate); -} - -// CONFIG register - -/** Get external FSYNC configuration. - * Configures the external Frame Synchronization (FSYNC) pin sampling. An - * external signal connected to the FSYNC pin can be sampled by configuring - * EXT_SYNC_SET. Signal changes to the FSYNC pin are latched so that short - * strobes may be captured. The latched FSYNC signal will be sampled at the - * Sampling Rate, as defined in register 25. After sampling, the latch will - * reset to the current FSYNC signal state. - * - * The sampled value will be reported in place of the least significant bit in - * a sensor data register determined by the value of EXT_SYNC_SET according to - * the following table. - * - *
- * EXT_SYNC_SET | FSYNC Bit Location
- * -------------+-------------------
- * 0            | Input disabled
- * 1            | TEMP_OUT_L[0]
- * 2            | GYRO_XOUT_L[0]
- * 3            | GYRO_YOUT_L[0]
- * 4            | GYRO_ZOUT_L[0]
- * 5            | ACCEL_XOUT_L[0]
- * 6            | ACCEL_YOUT_L[0]
- * 7            | ACCEL_ZOUT_L[0]
- * 
- * - * @return FSYNC configuration value - */ -uint8_t MPU6050::getExternalFrameSync() -{ - I2Cdev::readBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_EXT_SYNC_SET_BIT, MPU6050_CFG_EXT_SYNC_SET_LENGTH, buffer); - return buffer[0]; -} -/** Set external FSYNC configuration. - * @see getExternalFrameSync() - * @see MPU6050_RA_CONFIG - * @param sync New FSYNC configuration value - */ -void MPU6050::setExternalFrameSync(uint8_t sync) -{ - I2Cdev::writeBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_EXT_SYNC_SET_BIT, MPU6050_CFG_EXT_SYNC_SET_LENGTH, sync); -} -/** Get digital low-pass filter configuration. - * The DLPF_CFG parameter sets the digital low pass filter configuration. It - * also determines the internal sampling rate used by the device as shown in - * the table below. - * - * Note: The accelerometer output rate is 1kHz. This means that for a Sample - * Rate greater than 1kHz, the same accelerometer sample may be output to the - * FIFO, DMP, and sensor registers more than once. - * - *
- *          |   ACCELEROMETER    |           GYROSCOPE
- * DLPF_CFG | Bandwidth | Delay  | Bandwidth | Delay  | Sample Rate
- * ---------+-----------+--------+-----------+--------+-------------
- * 0        | 260Hz     | 0ms    | 256Hz     | 0.98ms | 8kHz
- * 1        | 184Hz     | 2.0ms  | 188Hz     | 1.9ms  | 1kHz
- * 2        | 94Hz      | 3.0ms  | 98Hz      | 2.8ms  | 1kHz
- * 3        | 44Hz      | 4.9ms  | 42Hz      | 4.8ms  | 1kHz
- * 4        | 21Hz      | 8.5ms  | 20Hz      | 8.3ms  | 1kHz
- * 5        | 10Hz      | 13.8ms | 10Hz      | 13.4ms | 1kHz
- * 6        | 5Hz       | 19.0ms | 5Hz       | 18.6ms | 1kHz
- * 7        |   -- Reserved --   |   -- Reserved --   | Reserved
- * 
- * - * @return DLFP configuration - * @see MPU6050_RA_CONFIG - * @see MPU6050_CFG_DLPF_CFG_BIT - * @see MPU6050_CFG_DLPF_CFG_LENGTH - */ -uint8_t MPU6050::getDLPFMode() -{ - I2Cdev::readBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_DLPF_CFG_BIT, MPU6050_CFG_DLPF_CFG_LENGTH, buffer); - return buffer[0]; -} -/** Set digital low-pass filter configuration. - * @param mode New DLFP configuration setting - * @see getDLPFBandwidth() - * @see MPU6050_DLPF_BW_256 - * @see MPU6050_RA_CONFIG - * @see MPU6050_CFG_DLPF_CFG_BIT - * @see MPU6050_CFG_DLPF_CFG_LENGTH - */ -void MPU6050::setDLPFMode(uint8_t mode) -{ - I2Cdev::writeBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_DLPF_CFG_BIT, MPU6050_CFG_DLPF_CFG_LENGTH, mode); -} - -// GYRO_CONFIG register - -/** Get full-scale gyroscope range. - * The FS_SEL parameter allows setting the full-scale range of the gyro sensors, - * as described in the table below. - * - *
- * 0 = +/- 250 degrees/sec
- * 1 = +/- 500 degrees/sec
- * 2 = +/- 1000 degrees/sec
- * 3 = +/- 2000 degrees/sec
- * 
- * - * @return Current full-scale gyroscope range setting - * @see MPU6050_GYRO_FS_250 - * @see MPU6050_RA_GYRO_CONFIG - * @see MPU6050_GCONFIG_FS_SEL_BIT - * @see MPU6050_GCONFIG_FS_SEL_LENGTH - */ -uint8_t MPU6050::getFullScaleGyroRange() -{ - I2Cdev::readBits(devAddr, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, buffer); - return buffer[0]; -} -/** Set full-scale gyroscope range. - * @param range New full-scale gyroscope range value - * @see getFullScaleRange() - * @see MPU6050_GYRO_FS_250 - * @see MPU6050_RA_GYRO_CONFIG - * @see MPU6050_GCONFIG_FS_SEL_BIT - * @see MPU6050_GCONFIG_FS_SEL_LENGTH - */ -void MPU6050::setFullScaleGyroRange(uint8_t range) -{ - I2Cdev::writeBits(devAddr, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, range); -} - -// SELF TEST FACTORY TRIM VALUES - -/** Get self-test factory trim value for accelerometer X axis. - * @return factory trim value - * @see MPU6050_RA_SELF_TEST_X - */ -uint8_t MPU6050::getAccelXSelfTestFactoryTrim() -{ - I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_X, &buffer[0]); - I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_A, &buffer[1]); - return (buffer[0] >> 3) | ((buffer[1] >> 4) & 0x03); -} - -/** Get self-test factory trim value for accelerometer Y axis. - * @return factory trim value - * @see MPU6050_RA_SELF_TEST_Y - */ -uint8_t MPU6050::getAccelYSelfTestFactoryTrim() -{ - I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_Y, &buffer[0]); - I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_A, &buffer[1]); - return (buffer[0] >> 3) | ((buffer[1] >> 2) & 0x03); -} - -/** Get self-test factory trim value for accelerometer Z axis. - * @return factory trim value - * @see MPU6050_RA_SELF_TEST_Z - */ -uint8_t MPU6050::getAccelZSelfTestFactoryTrim() -{ - I2Cdev::readBytes(devAddr, MPU6050_RA_SELF_TEST_Z, 2, buffer); - return (buffer[0] >> 3) | (buffer[1] & 0x03); -} - -/** Get self-test factory trim value for gyro X axis. - * @return factory trim value - * @see MPU6050_RA_SELF_TEST_X - */ -uint8_t MPU6050::getGyroXSelfTestFactoryTrim() -{ - I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_X, buffer); - return (buffer[0] & 0x1F); -} - -/** Get self-test factory trim value for gyro Y axis. - * @return factory trim value - * @see MPU6050_RA_SELF_TEST_Y - */ -uint8_t MPU6050::getGyroYSelfTestFactoryTrim() -{ - I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_Y, buffer); - return (buffer[0] & 0x1F); -} - -/** Get self-test factory trim value for gyro Z axis. - * @return factory trim value - * @see MPU6050_RA_SELF_TEST_Z - */ -uint8_t MPU6050::getGyroZSelfTestFactoryTrim() -{ - I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_Z, buffer); - return (buffer[0] & 0x1F); -} - -// ACCEL_CONFIG register - -/** Get self-test enabled setting for accelerometer X axis. - * @return Self-test enabled value - * @see MPU6050_RA_ACCEL_CONFIG - */ -bool MPU6050::getAccelXSelfTest() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_XA_ST_BIT, buffer); - return buffer[0]; -} -/** Get self-test enabled setting for accelerometer X axis. - * @param enabled Self-test enabled value - * @see MPU6050_RA_ACCEL_CONFIG - */ -void MPU6050::setAccelXSelfTest(bool enabled) -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_XA_ST_BIT, enabled); -} -/** Get self-test enabled value for accelerometer Y axis. - * @return Self-test enabled value - * @see MPU6050_RA_ACCEL_CONFIG - */ -bool MPU6050::getAccelYSelfTest() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_YA_ST_BIT, buffer); - return buffer[0]; -} -/** Get self-test enabled value for accelerometer Y axis. - * @param enabled Self-test enabled value - * @see MPU6050_RA_ACCEL_CONFIG - */ -void MPU6050::setAccelYSelfTest(bool enabled) -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_YA_ST_BIT, enabled); -} -/** Get self-test enabled value for accelerometer Z axis. - * @return Self-test enabled value - * @see MPU6050_RA_ACCEL_CONFIG - */ -bool MPU6050::getAccelZSelfTest() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ZA_ST_BIT, buffer); - return buffer[0]; -} -/** Set self-test enabled value for accelerometer Z axis. - * @param enabled Self-test enabled value - * @see MPU6050_RA_ACCEL_CONFIG - */ -void MPU6050::setAccelZSelfTest(bool enabled) -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ZA_ST_BIT, enabled); -} -/** Get full-scale accelerometer range. - * The FS_SEL parameter allows setting the full-scale range of the accelerometer - * sensors, as described in the table below. - * - *
- * 0 = +/- 2g
- * 1 = +/- 4g
- * 2 = +/- 8g
- * 3 = +/- 16g
- * 
- * - * @return Current full-scale accelerometer range setting - * @see MPU6050_ACCEL_FS_2 - * @see MPU6050_RA_ACCEL_CONFIG - * @see MPU6050_ACONFIG_AFS_SEL_BIT - * @see MPU6050_ACONFIG_AFS_SEL_LENGTH - */ -uint8_t MPU6050::getFullScaleAccelRange() -{ - I2Cdev::readBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, buffer); - return buffer[0]; -} -/** Set full-scale accelerometer range. - * @param range New full-scale accelerometer range setting - * @see getFullScaleAccelRange() - */ -void MPU6050::setFullScaleAccelRange(uint8_t range) -{ - I2Cdev::writeBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, range); -} -/** Get the high-pass filter configuration. - * The DHPF is a filter module in the path leading to motion detectors (Free - * Fall, Motion threshold, and Zero Motion). The high pass filter output is not - * available to the data registers (see Figure in Section 8 of the MPU-6000/ - * MPU-6050 Product Specification document). - * - * The high pass filter has three modes: - * - *
- *    Reset: The filter output settles to zero within one sample. This
- *           effectively disables the high pass filter. This mode may be toggled
- *           to quickly settle the filter.
- *
- *    On:    The high pass filter will pass signals above the cut off frequency.
- *
- *    Hold:  When triggered, the filter holds the present sample. The filter
- *           output will be the difference between the input sample and the held
- *           sample.
- * 
- * - *
- * ACCEL_HPF | Filter Mode | Cut-off Frequency
- * ----------+-------------+------------------
- * 0         | Reset       | None
- * 1         | On          | 5Hz
- * 2         | On          | 2.5Hz
- * 3         | On          | 1.25Hz
- * 4         | On          | 0.63Hz
- * 7         | Hold        | None
- * 
- * - * @return Current high-pass filter configuration - * @see MPU6050_DHPF_RESET - * @see MPU6050_RA_ACCEL_CONFIG - */ -uint8_t MPU6050::getDHPFMode() -{ - I2Cdev::readBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ACCEL_HPF_BIT, MPU6050_ACONFIG_ACCEL_HPF_LENGTH, buffer); - return buffer[0]; -} -/** Set the high-pass filter configuration. - * @param bandwidth New high-pass filter configuration - * @see setDHPFMode() - * @see MPU6050_DHPF_RESET - * @see MPU6050_RA_ACCEL_CONFIG - */ -void MPU6050::setDHPFMode(uint8_t bandwidth) -{ - I2Cdev::writeBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ACCEL_HPF_BIT, MPU6050_ACONFIG_ACCEL_HPF_LENGTH, bandwidth); -} - -// FF_THR register - -/** Get free-fall event acceleration threshold. - * This register configures the detection threshold for Free Fall event - * detection. The unit of FF_THR is 1LSB = 2mg. Free Fall is detected when the - * absolute value of the accelerometer measurements for the three axes are each - * less than the detection threshold. This condition increments the Free Fall - * duration counter (Register 30). The Free Fall interrupt is triggered when the - * Free Fall duration counter reaches the time specified in FF_DUR. - * - * For more details on the Free Fall detection interrupt, see Section 8.2 of the - * MPU-6000/MPU-6050 Product Specification document as well as Registers 56 and - * 58 of this document. - * - * @return Current free-fall acceleration threshold value (LSB = 2mg) - * @see MPU6050_RA_FF_THR - */ -uint8_t MPU6050::getFreefallDetectionThreshold() -{ - I2Cdev::readByte(devAddr, MPU6050_RA_FF_THR, buffer); - return buffer[0]; -} -/** Get free-fall event acceleration threshold. - * @param threshold New free-fall acceleration threshold value (LSB = 2mg) - * @see getFreefallDetectionThreshold() - * @see MPU6050_RA_FF_THR - */ -void MPU6050::setFreefallDetectionThreshold(uint8_t threshold) -{ - I2Cdev::writeByte(devAddr, MPU6050_RA_FF_THR, threshold); -} - -// FF_DUR register - -/** Get free-fall event duration threshold. - * This register configures the duration counter threshold for Free Fall event - * detection. The duration counter ticks at 1kHz, therefore FF_DUR has a unit - * of 1 LSB = 1 ms. - * - * The Free Fall duration counter increments while the absolute value of the - * accelerometer measurements are each less than the detection threshold - * (Register 29). The Free Fall interrupt is triggered when the Free Fall - * duration counter reaches the time specified in this register. - * - * For more details on the Free Fall detection interrupt, see Section 8.2 of - * the MPU-6000/MPU-6050 Product Specification document as well as Registers 56 - * and 58 of this document. - * - * @return Current free-fall duration threshold value (LSB = 1ms) - * @see MPU6050_RA_FF_DUR - */ -uint8_t MPU6050::getFreefallDetectionDuration() -{ - I2Cdev::readByte(devAddr, MPU6050_RA_FF_DUR, buffer); - return buffer[0]; -} -/** Get free-fall event duration threshold. - * @param duration New free-fall duration threshold value (LSB = 1ms) - * @see getFreefallDetectionDuration() - * @see MPU6050_RA_FF_DUR - */ -void MPU6050::setFreefallDetectionDuration(uint8_t duration) -{ - I2Cdev::writeByte(devAddr, MPU6050_RA_FF_DUR, duration); -} - -// MOT_THR register - -/** Get motion detection event acceleration threshold. - * This register configures the detection threshold for Motion interrupt - * generation. The unit of MOT_THR is 1LSB = 2mg. Motion is detected when the - * absolute value of any of the accelerometer measurements exceeds this Motion - * detection threshold. This condition increments the Motion detection duration - * counter (Register 32). The Motion detection interrupt is triggered when the - * Motion Detection counter reaches the time count specified in MOT_DUR - * (Register 32). - * - * The Motion interrupt will indicate the axis and polarity of detected motion - * in MOT_DETECT_STATUS (Register 97). - * - * For more details on the Motion detection interrupt, see Section 8.3 of the - * MPU-6000/MPU-6050 Product Specification document as well as Registers 56 and - * 58 of this document. - * - * @return Current motion detection acceleration threshold value (LSB = 2mg) - * @see MPU6050_RA_MOT_THR - */ -uint8_t MPU6050::getMotionDetectionThreshold() -{ - I2Cdev::readByte(devAddr, MPU6050_RA_MOT_THR, buffer); - return buffer[0]; -} -/** Set motion detection event acceleration threshold. - * @param threshold New motion detection acceleration threshold value (LSB = 2mg) - * @see getMotionDetectionThreshold() - * @see MPU6050_RA_MOT_THR - */ -void MPU6050::setMotionDetectionThreshold(uint8_t threshold) -{ - I2Cdev::writeByte(devAddr, MPU6050_RA_MOT_THR, threshold); -} - -// MOT_DUR register - -/** Get motion detection event duration threshold. - * This register configures the duration counter threshold for Motion interrupt - * generation. The duration counter ticks at 1 kHz, therefore MOT_DUR has a unit - * of 1LSB = 1ms. The Motion detection duration counter increments when the - * absolute value of any of the accelerometer measurements exceeds the Motion - * detection threshold (Register 31). The Motion detection interrupt is - * triggered when the Motion detection counter reaches the time count specified - * in this register. - * - * For more details on the Motion detection interrupt, see Section 8.3 of the - * MPU-6000/MPU-6050 Product Specification document. - * - * @return Current motion detection duration threshold value (LSB = 1ms) - * @see MPU6050_RA_MOT_DUR - */ -uint8_t MPU6050::getMotionDetectionDuration() -{ - I2Cdev::readByte(devAddr, MPU6050_RA_MOT_DUR, buffer); - return buffer[0]; -} -/** Set motion detection event duration threshold. - * @param duration New motion detection duration threshold value (LSB = 1ms) - * @see getMotionDetectionDuration() - * @see MPU6050_RA_MOT_DUR - */ -void MPU6050::setMotionDetectionDuration(uint8_t duration) -{ - I2Cdev::writeByte(devAddr, MPU6050_RA_MOT_DUR, duration); -} - -// ZRMOT_THR register - -/** Get zero motion detection event acceleration threshold. - * This register configures the detection threshold for Zero Motion interrupt - * generation. The unit of ZRMOT_THR is 1LSB = 2mg. Zero Motion is detected when - * the absolute value of the accelerometer measurements for the 3 axes are each - * less than the detection threshold. This condition increments the Zero Motion - * duration counter (Register 34). The Zero Motion interrupt is triggered when - * the Zero Motion duration counter reaches the time count specified in - * ZRMOT_DUR (Register 34). - * - * Unlike Free Fall or Motion detection, Zero Motion detection triggers an - * interrupt both when Zero Motion is first detected and when Zero Motion is no - * longer detected. - * - * When a zero motion event is detected, a Zero Motion Status will be indicated - * in the MOT_DETECT_STATUS register (Register 97). When a motion-to-zero-motion - * condition is detected, the status bit is set to 1. When a zero-motion-to- - * motion condition is detected, the status bit is set to 0. - * - * For more details on the Zero Motion detection interrupt, see Section 8.4 of - * the MPU-6000/MPU-6050 Product Specification document as well as Registers 56 - * and 58 of this document. - * - * @return Current zero motion detection acceleration threshold value (LSB = 2mg) - * @see MPU6050_RA_ZRMOT_THR - */ -uint8_t MPU6050::getZeroMotionDetectionThreshold() -{ - I2Cdev::readByte(devAddr, MPU6050_RA_ZRMOT_THR, buffer); - return buffer[0]; -} -/** Set zero motion detection event acceleration threshold. - * @param threshold New zero motion detection acceleration threshold value (LSB = 2mg) - * @see getZeroMotionDetectionThreshold() - * @see MPU6050_RA_ZRMOT_THR - */ -void MPU6050::setZeroMotionDetectionThreshold(uint8_t threshold) -{ - I2Cdev::writeByte(devAddr, MPU6050_RA_ZRMOT_THR, threshold); -} - -// ZRMOT_DUR register - -/** Get zero motion detection event duration threshold. - * This register configures the duration counter threshold for Zero Motion - * interrupt generation. The duration counter ticks at 16 Hz, therefore - * ZRMOT_DUR has a unit of 1 LSB = 64 ms. The Zero Motion duration counter - * increments while the absolute value of the accelerometer measurements are - * each less than the detection threshold (Register 33). The Zero Motion - * interrupt is triggered when the Zero Motion duration counter reaches the time - * count specified in this register. - * - * For more details on the Zero Motion detection interrupt, see Section 8.4 of - * the MPU-6000/MPU-6050 Product Specification document, as well as Registers 56 - * and 58 of this document. - * - * @return Current zero motion detection duration threshold value (LSB = 64ms) - * @see MPU6050_RA_ZRMOT_DUR - */ -uint8_t MPU6050::getZeroMotionDetectionDuration() -{ - I2Cdev::readByte(devAddr, MPU6050_RA_ZRMOT_DUR, buffer); - return buffer[0]; -} -/** Set zero motion detection event duration threshold. - * @param duration New zero motion detection duration threshold value (LSB = 1ms) - * @see getZeroMotionDetectionDuration() - * @see MPU6050_RA_ZRMOT_DUR - */ -void MPU6050::setZeroMotionDetectionDuration(uint8_t duration) -{ - I2Cdev::writeByte(devAddr, MPU6050_RA_ZRMOT_DUR, duration); -} - -// FIFO_EN register - -/** Get temperature FIFO enabled value. - * When set to 1, this bit enables TEMP_OUT_H and TEMP_OUT_L (Registers 65 and - * 66) to be written into the FIFO buffer. - * @return Current temperature FIFO enabled value - * @see MPU6050_RA_FIFO_EN - */ -bool MPU6050::getTempFIFOEnabled() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_TEMP_FIFO_EN_BIT, buffer); - return buffer[0]; -} -/** Set temperature FIFO enabled value. - * @param enabled New temperature FIFO enabled value - * @see getTempFIFOEnabled() - * @see MPU6050_RA_FIFO_EN - */ -void MPU6050::setTempFIFOEnabled(bool enabled) -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_TEMP_FIFO_EN_BIT, enabled); -} -/** Get gyroscope X-axis FIFO enabled value. - * When set to 1, this bit enables GYRO_XOUT_H and GYRO_XOUT_L (Registers 67 and - * 68) to be written into the FIFO buffer. - * @return Current gyroscope X-axis FIFO enabled value - * @see MPU6050_RA_FIFO_EN - */ -bool MPU6050::getXGyroFIFOEnabled() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_XG_FIFO_EN_BIT, buffer); - return buffer[0]; -} -/** Set gyroscope X-axis FIFO enabled value. - * @param enabled New gyroscope X-axis FIFO enabled value - * @see getXGyroFIFOEnabled() - * @see MPU6050_RA_FIFO_EN - */ -void MPU6050::setXGyroFIFOEnabled(bool enabled) -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_XG_FIFO_EN_BIT, enabled); -} -/** Get gyroscope Y-axis FIFO enabled value. - * When set to 1, this bit enables GYRO_YOUT_H and GYRO_YOUT_L (Registers 69 and - * 70) to be written into the FIFO buffer. - * @return Current gyroscope Y-axis FIFO enabled value - * @see MPU6050_RA_FIFO_EN - */ -bool MPU6050::getYGyroFIFOEnabled() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_YG_FIFO_EN_BIT, buffer); - return buffer[0]; -} -/** Set gyroscope Y-axis FIFO enabled value. - * @param enabled New gyroscope Y-axis FIFO enabled value - * @see getYGyroFIFOEnabled() - * @see MPU6050_RA_FIFO_EN - */ -void MPU6050::setYGyroFIFOEnabled(bool enabled) -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_YG_FIFO_EN_BIT, enabled); -} -/** Get gyroscope Z-axis FIFO enabled value. - * When set to 1, this bit enables GYRO_ZOUT_H and GYRO_ZOUT_L (Registers 71 and - * 72) to be written into the FIFO buffer. - * @return Current gyroscope Z-axis FIFO enabled value - * @see MPU6050_RA_FIFO_EN - */ -bool MPU6050::getZGyroFIFOEnabled() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ZG_FIFO_EN_BIT, buffer); - return buffer[0]; -} -/** Set gyroscope Z-axis FIFO enabled value. - * @param enabled New gyroscope Z-axis FIFO enabled value - * @see getZGyroFIFOEnabled() - * @see MPU6050_RA_FIFO_EN - */ -void MPU6050::setZGyroFIFOEnabled(bool enabled) -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ZG_FIFO_EN_BIT, enabled); -} -/** Get accelerometer FIFO enabled value. - * When set to 1, this bit enables ACCEL_XOUT_H, ACCEL_XOUT_L, ACCEL_YOUT_H, - * ACCEL_YOUT_L, ACCEL_ZOUT_H, and ACCEL_ZOUT_L (Registers 59 to 64) to be - * written into the FIFO buffer. - * @return Current accelerometer FIFO enabled value - * @see MPU6050_RA_FIFO_EN - */ -bool MPU6050::getAccelFIFOEnabled() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ACCEL_FIFO_EN_BIT, buffer); - return buffer[0]; -} -/** Set accelerometer FIFO enabled value. - * @param enabled New accelerometer FIFO enabled value - * @see getAccelFIFOEnabled() - * @see MPU6050_RA_FIFO_EN - */ -void MPU6050::setAccelFIFOEnabled(bool enabled) -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ACCEL_FIFO_EN_BIT, enabled); -} -/** Get Slave 2 FIFO enabled value. - * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) - * associated with Slave 2 to be written into the FIFO buffer. - * @return Current Slave 2 FIFO enabled value - * @see MPU6050_RA_FIFO_EN - */ -bool MPU6050::getSlave2FIFOEnabled() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV2_FIFO_EN_BIT, buffer); - return buffer[0]; -} -/** Set Slave 2 FIFO enabled value. - * @param enabled New Slave 2 FIFO enabled value - * @see getSlave2FIFOEnabled() - * @see MPU6050_RA_FIFO_EN - */ -void MPU6050::setSlave2FIFOEnabled(bool enabled) -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV2_FIFO_EN_BIT, enabled); -} -/** Get Slave 1 FIFO enabled value. - * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) - * associated with Slave 1 to be written into the FIFO buffer. - * @return Current Slave 1 FIFO enabled value - * @see MPU6050_RA_FIFO_EN - */ -bool MPU6050::getSlave1FIFOEnabled() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV1_FIFO_EN_BIT, buffer); - return buffer[0]; -} -/** Set Slave 1 FIFO enabled value. - * @param enabled New Slave 1 FIFO enabled value - * @see getSlave1FIFOEnabled() - * @see MPU6050_RA_FIFO_EN - */ -void MPU6050::setSlave1FIFOEnabled(bool enabled) -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV1_FIFO_EN_BIT, enabled); -} -/** Get Slave 0 FIFO enabled value. - * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) - * associated with Slave 0 to be written into the FIFO buffer. - * @return Current Slave 0 FIFO enabled value - * @see MPU6050_RA_FIFO_EN - */ -bool MPU6050::getSlave0FIFOEnabled() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV0_FIFO_EN_BIT, buffer); - return buffer[0]; -} -/** Set Slave 0 FIFO enabled value. - * @param enabled New Slave 0 FIFO enabled value - * @see getSlave0FIFOEnabled() - * @see MPU6050_RA_FIFO_EN - */ -void MPU6050::setSlave0FIFOEnabled(bool enabled) -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV0_FIFO_EN_BIT, enabled); -} - -// I2C_MST_CTRL register - -/** Get multi-master enabled value. - * Multi-master capability allows multiple I2C masters to operate on the same - * bus. In circuits where multi-master capability is required, set MULT_MST_EN - * to 1. This will increase current drawn by approximately 30uA. - * - * In circuits where multi-master capability is required, the state of the I2C - * bus must always be monitored by each separate I2C Master. Before an I2C - * Master can assume arbitration of the bus, it must first confirm that no other - * I2C Master has arbitration of the bus. When MULT_MST_EN is set to 1, the - * MPU-60X0's bus arbitration detection logic is turned on, enabling it to - * detect when the bus is available. - * - * @return Current multi-master enabled value - * @see MPU6050_RA_I2C_MST_CTRL - */ -bool MPU6050::getMultiMasterEnabled() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_MULT_MST_EN_BIT, buffer); - return buffer[0]; -} -/** Set multi-master enabled value. - * @param enabled New multi-master enabled value - * @see getMultiMasterEnabled() - * @see MPU6050_RA_I2C_MST_CTRL - */ -void MPU6050::setMultiMasterEnabled(bool enabled) -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_MULT_MST_EN_BIT, enabled); -} -/** Get wait-for-external-sensor-data enabled value. - * When the WAIT_FOR_ES bit is set to 1, the Data Ready interrupt will be - * delayed until External Sensor data from the Slave Devices are loaded into the - * EXT_SENS_DATA registers. This is used to ensure that both the internal sensor - * data (i.e. from gyro and accel) and external sensor data have been loaded to - * their respective data registers (i.e. the data is synced) when the Data Ready - * interrupt is triggered. - * - * @return Current wait-for-external-sensor-data enabled value - * @see MPU6050_RA_I2C_MST_CTRL - */ -bool MPU6050::getWaitForExternalSensorEnabled() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_WAIT_FOR_ES_BIT, buffer); - return buffer[0]; -} -/** Set wait-for-external-sensor-data enabled value. - * @param enabled New wait-for-external-sensor-data enabled value - * @see getWaitForExternalSensorEnabled() - * @see MPU6050_RA_I2C_MST_CTRL - */ -void MPU6050::setWaitForExternalSensorEnabled(bool enabled) -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_WAIT_FOR_ES_BIT, enabled); -} -/** Get Slave 3 FIFO enabled value. - * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) - * associated with Slave 3 to be written into the FIFO buffer. - * @return Current Slave 3 FIFO enabled value - * @see MPU6050_RA_MST_CTRL - */ -bool MPU6050::getSlave3FIFOEnabled() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_SLV_3_FIFO_EN_BIT, buffer); - return buffer[0]; -} -/** Set Slave 3 FIFO enabled value. - * @param enabled New Slave 3 FIFO enabled value - * @see getSlave3FIFOEnabled() - * @see MPU6050_RA_MST_CTRL - */ -void MPU6050::setSlave3FIFOEnabled(bool enabled) -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_SLV_3_FIFO_EN_BIT, enabled); -} -/** Get slave read/write transition enabled value. - * The I2C_MST_P_NSR bit configures the I2C Master's transition from one slave - * read to the next slave read. If the bit equals 0, there will be a restart - * between reads. If the bit equals 1, there will be a stop followed by a start - * of the following read. When a write transaction follows a read transaction, - * the stop followed by a start of the successive write will be always used. - * - * @return Current slave read/write transition enabled value - * @see MPU6050_RA_I2C_MST_CTRL - */ -bool MPU6050::getSlaveReadWriteTransitionEnabled() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_P_NSR_BIT, buffer); - return buffer[0]; -} -/** Set slave read/write transition enabled value. - * @param enabled New slave read/write transition enabled value - * @see getSlaveReadWriteTransitionEnabled() - * @see MPU6050_RA_I2C_MST_CTRL - */ -void MPU6050::setSlaveReadWriteTransitionEnabled(bool enabled) -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_P_NSR_BIT, enabled); -} -/** Get I2C master clock speed. - * I2C_MST_CLK is a 4 bit unsigned value which configures a divider on the - * MPU-60X0 internal 8MHz clock. It sets the I2C master clock speed according to - * the following table: - * - *
- * I2C_MST_CLK | I2C Master Clock Speed | 8MHz Clock Divider
- * ------------+------------------------+-------------------
- * 0           | 348kHz                 | 23
- * 1           | 333kHz                 | 24
- * 2           | 320kHz                 | 25
- * 3           | 308kHz                 | 26
- * 4           | 296kHz                 | 27
- * 5           | 286kHz                 | 28
- * 6           | 276kHz                 | 29
- * 7           | 267kHz                 | 30
- * 8           | 258kHz                 | 31
- * 9           | 500kHz                 | 16
- * 10          | 471kHz                 | 17
- * 11          | 444kHz                 | 18
- * 12          | 421kHz                 | 19
- * 13          | 400kHz                 | 20
- * 14          | 381kHz                 | 21
- * 15          | 364kHz                 | 22
- * 
- * - * @return Current I2C master clock speed - * @see MPU6050_RA_I2C_MST_CTRL - */ -uint8_t MPU6050::getMasterClockSpeed() -{ - I2Cdev::readBits(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_CLK_BIT, MPU6050_I2C_MST_CLK_LENGTH, buffer); - return buffer[0]; -} -/** Set I2C master clock speed. - * @reparam speed Current I2C master clock speed - * @see MPU6050_RA_I2C_MST_CTRL - */ -void MPU6050::setMasterClockSpeed(uint8_t speed) -{ - I2Cdev::writeBits(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_CLK_BIT, MPU6050_I2C_MST_CLK_LENGTH, speed); -} - -// I2C_SLV* registers (Slave 0-3) - -/** Get the I2C address of the specified slave (0-3). - * Note that Bit 7 (MSB) controls read/write mode. If Bit 7 is set, it's a read - * operation, and if it is cleared, then it's a write operation. The remaining - * bits (6-0) are the 7-bit device address of the slave device. - * - * In read mode, the result of the read is placed in the lowest available - * EXT_SENS_DATA register. For further information regarding the allocation of - * read results, please refer to the EXT_SENS_DATA register description - * (Registers 73 - 96). - * - * The MPU-6050 supports a total of five slaves, but Slave 4 has unique - * characteristics, and so it has its own functions (getSlave4* and setSlave4*). - * - * I2C data transactions are performed at the Sample Rate, as defined in - * Register 25. The user is responsible for ensuring that I2C data transactions - * to and from each enabled Slave can be completed within a single period of the - * Sample Rate. - * - * The I2C slave access rate can be reduced relative to the Sample Rate. This - * reduced access rate is determined by I2C_MST_DLY (Register 52). Whether a - * slave's access rate is reduced relative to the Sample Rate is determined by - * I2C_MST_DELAY_CTRL (Register 103). - * - * The processing order for the slaves is fixed. The sequence followed for - * processing the slaves is Slave 0, Slave 1, Slave 2, Slave 3 and Slave 4. If a - * particular Slave is disabled it will be skipped. - * - * Each slave can either be accessed at the sample rate or at a reduced sample - * rate. In a case where some slaves are accessed at the Sample Rate and some - * slaves are accessed at the reduced rate, the sequence of accessing the slaves - * (Slave 0 to Slave 4) is still followed. However, the reduced rate slaves will - * be skipped if their access rate dictates that they should not be accessed - * during that particular cycle. For further information regarding the reduced - * access rate, please refer to Register 52. Whether a slave is accessed at the - * Sample Rate or at the reduced rate is determined by the Delay Enable bits in - * Register 103. - * - * @param num Slave number (0-3) - * @return Current address for specified slave - * @see MPU6050_RA_I2C_SLV0_ADDR - */ -uint8_t MPU6050::getSlaveAddress(uint8_t num) -{ - if (num > 3) - return 0; - I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV0_ADDR + num * 3, buffer); - return buffer[0]; -} -/** Set the I2C address of the specified slave (0-3). - * @param num Slave number (0-3) - * @param address New address for specified slave - * @see getSlaveAddress() - * @see MPU6050_RA_I2C_SLV0_ADDR - */ -void MPU6050::setSlaveAddress(uint8_t num, uint8_t address) -{ - if (num > 3) - return; - I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV0_ADDR + num * 3, address); -} -/** Get the active internal register for the specified slave (0-3). - * Read/write operations for this slave will be done to whatever internal - * register address is stored in this MPU register. - * - * The MPU-6050 supports a total of five slaves, but Slave 4 has unique - * characteristics, and so it has its own functions. - * - * @param num Slave number (0-3) - * @return Current active register for specified slave - * @see MPU6050_RA_I2C_SLV0_REG - */ -uint8_t MPU6050::getSlaveRegister(uint8_t num) -{ - if (num > 3) - return 0; - I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV0_REG + num * 3, buffer); - return buffer[0]; -} -/** Set the active internal register for the specified slave (0-3). - * @param num Slave number (0-3) - * @param reg New active register for specified slave - * @see getSlaveRegister() - * @see MPU6050_RA_I2C_SLV0_REG - */ -void MPU6050::setSlaveRegister(uint8_t num, uint8_t reg) -{ - if (num > 3) - return; - I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV0_REG + num * 3, reg); -} -/** Get the enabled value for the specified slave (0-3). - * When set to 1, this bit enables Slave 0 for data transfer operations. When - * cleared to 0, this bit disables Slave 0 from data transfer operations. - * @param num Slave number (0-3) - * @return Current enabled value for specified slave - * @see MPU6050_RA_I2C_SLV0_CTRL - */ -bool MPU6050::getSlaveEnabled(uint8_t num) -{ - if (num > 3) - return 0; - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num * 3, MPU6050_I2C_SLV_EN_BIT, buffer); - return buffer[0]; -} -/** Set the enabled value for the specified slave (0-3). - * @param num Slave number (0-3) - * @param enabled New enabled value for specified slave - * @see getSlaveEnabled() - * @see MPU6050_RA_I2C_SLV0_CTRL - */ -void MPU6050::setSlaveEnabled(uint8_t num, bool enabled) -{ - if (num > 3) - return; - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num * 3, MPU6050_I2C_SLV_EN_BIT, enabled); -} -/** Get word pair byte-swapping enabled for the specified slave (0-3). - * When set to 1, this bit enables byte swapping. When byte swapping is enabled, - * the high and low bytes of a word pair are swapped. Please refer to - * I2C_SLV0_GRP for the pairing convention of the word pairs. When cleared to 0, - * bytes transferred to and from Slave 0 will be written to EXT_SENS_DATA - * registers in the order they were transferred. - * - * @param num Slave number (0-3) - * @return Current word pair byte-swapping enabled value for specified slave - * @see MPU6050_RA_I2C_SLV0_CTRL - */ -bool MPU6050::getSlaveWordByteSwap(uint8_t num) -{ - if (num > 3) - return 0; - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num * 3, MPU6050_I2C_SLV_BYTE_SW_BIT, buffer); - return buffer[0]; -} -/** Set word pair byte-swapping enabled for the specified slave (0-3). - * @param num Slave number (0-3) - * @param enabled New word pair byte-swapping enabled value for specified slave - * @see getSlaveWordByteSwap() - * @see MPU6050_RA_I2C_SLV0_CTRL - */ -void MPU6050::setSlaveWordByteSwap(uint8_t num, bool enabled) -{ - if (num > 3) - return; - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num * 3, MPU6050_I2C_SLV_BYTE_SW_BIT, enabled); -} -/** Get write mode for the specified slave (0-3). - * When set to 1, the transaction will read or write data only. When cleared to - * 0, the transaction will write a register address prior to reading or writing - * data. This should equal 0 when specifying the register address within the - * Slave device to/from which the ensuing data transaction will take place. - * - * @param num Slave number (0-3) - * @return Current write mode for specified slave (0 = register address + data, 1 = data only) - * @see MPU6050_RA_I2C_SLV0_CTRL - */ -bool MPU6050::getSlaveWriteMode(uint8_t num) -{ - if (num > 3) - return 0; - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num * 3, MPU6050_I2C_SLV_REG_DIS_BIT, buffer); - return buffer[0]; -} -/** Set write mode for the specified slave (0-3). - * @param num Slave number (0-3) - * @param mode New write mode for specified slave (0 = register address + data, 1 = data only) - * @see getSlaveWriteMode() - * @see MPU6050_RA_I2C_SLV0_CTRL - */ -void MPU6050::setSlaveWriteMode(uint8_t num, bool mode) -{ - if (num > 3) - return; - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num * 3, MPU6050_I2C_SLV_REG_DIS_BIT, mode); -} -/** Get word pair grouping order offset for the specified slave (0-3). - * This sets specifies the grouping order of word pairs received from registers. - * When cleared to 0, bytes from register addresses 0 and 1, 2 and 3, etc (even, - * then odd register addresses) are paired to form a word. When set to 1, bytes - * from register addresses are paired 1 and 2, 3 and 4, etc. (odd, then even - * register addresses) are paired to form a word. - * - * @param num Slave number (0-3) - * @return Current word pair grouping order offset for specified slave - * @see MPU6050_RA_I2C_SLV0_CTRL - */ -bool MPU6050::getSlaveWordGroupOffset(uint8_t num) -{ - if (num > 3) - return 0; - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num * 3, MPU6050_I2C_SLV_GRP_BIT, buffer); - return buffer[0]; -} -/** Set word pair grouping order offset for the specified slave (0-3). - * @param num Slave number (0-3) - * @param enabled New word pair grouping order offset for specified slave - * @see getSlaveWordGroupOffset() - * @see MPU6050_RA_I2C_SLV0_CTRL - */ -void MPU6050::setSlaveWordGroupOffset(uint8_t num, bool enabled) -{ - if (num > 3) - return; - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num * 3, MPU6050_I2C_SLV_GRP_BIT, enabled); -} -/** Get number of bytes to read for the specified slave (0-3). - * Specifies the number of bytes transferred to and from Slave 0. Clearing this - * bit to 0 is equivalent to disabling the register by writing 0 to I2C_SLV0_EN. - * @param num Slave number (0-3) - * @return Number of bytes to read for specified slave - * @see MPU6050_RA_I2C_SLV0_CTRL - */ -uint8_t MPU6050::getSlaveDataLength(uint8_t num) -{ - if (num > 3) - return 0; - I2Cdev::readBits(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num * 3, MPU6050_I2C_SLV_LEN_BIT, MPU6050_I2C_SLV_LEN_LENGTH, buffer); - return buffer[0]; -} -/** Set number of bytes to read for the specified slave (0-3). - * @param num Slave number (0-3) - * @param length Number of bytes to read for specified slave - * @see getSlaveDataLength() - * @see MPU6050_RA_I2C_SLV0_CTRL - */ -void MPU6050::setSlaveDataLength(uint8_t num, uint8_t length) -{ - if (num > 3) - return; - I2Cdev::writeBits(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num * 3, MPU6050_I2C_SLV_LEN_BIT, MPU6050_I2C_SLV_LEN_LENGTH, length); -} - -// I2C_SLV* registers (Slave 4) - -/** Get the I2C address of Slave 4. - * Note that Bit 7 (MSB) controls read/write mode. If Bit 7 is set, it's a read - * operation, and if it is cleared, then it's a write operation. The remaining - * bits (6-0) are the 7-bit device address of the slave device. - * - * @return Current address for Slave 4 - * @see getSlaveAddress() - * @see MPU6050_RA_I2C_SLV4_ADDR - */ -uint8_t MPU6050::getSlave4Address() -{ - I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV4_ADDR, buffer); - return buffer[0]; -} -/** Set the I2C address of Slave 4. - * @param address New address for Slave 4 - * @see getSlave4Address() - * @see MPU6050_RA_I2C_SLV4_ADDR - */ -void MPU6050::setSlave4Address(uint8_t address) -{ - I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV4_ADDR, address); -} -/** Get the active internal register for the Slave 4. - * Read/write operations for this slave will be done to whatever internal - * register address is stored in this MPU register. - * - * @return Current active register for Slave 4 - * @see MPU6050_RA_I2C_SLV4_REG - */ -uint8_t MPU6050::getSlave4Register() -{ - I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV4_REG, buffer); - return buffer[0]; -} -/** Set the active internal register for Slave 4. - * @param reg New active register for Slave 4 - * @see getSlave4Register() - * @see MPU6050_RA_I2C_SLV4_REG - */ -void MPU6050::setSlave4Register(uint8_t reg) -{ - I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV4_REG, reg); -} -/** Set new byte to write to Slave 4. - * This register stores the data to be written into the Slave 4. If I2C_SLV4_RW - * is set 1 (set to read), this register has no effect. - * @param data New byte to write to Slave 4 - * @see MPU6050_RA_I2C_SLV4_DO - */ -void MPU6050::setSlave4OutputByte(uint8_t data) -{ - I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV4_DO, data); -} -/** Get the enabled value for the Slave 4. - * When set to 1, this bit enables Slave 4 for data transfer operations. When - * cleared to 0, this bit disables Slave 4 from data transfer operations. - * @return Current enabled value for Slave 4 - * @see MPU6050_RA_I2C_SLV4_CTRL - */ -bool MPU6050::getSlave4Enabled() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_EN_BIT, buffer); - return buffer[0]; -} -/** Set the enabled value for Slave 4. - * @param enabled New enabled value for Slave 4 - * @see getSlave4Enabled() - * @see MPU6050_RA_I2C_SLV4_CTRL - */ -void MPU6050::setSlave4Enabled(bool enabled) -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_EN_BIT, enabled); -} -/** Get the enabled value for Slave 4 transaction interrupts. - * When set to 1, this bit enables the generation of an interrupt signal upon - * completion of a Slave 4 transaction. When cleared to 0, this bit disables the - * generation of an interrupt signal upon completion of a Slave 4 transaction. - * The interrupt status can be observed in Register 54. - * - * @return Current enabled value for Slave 4 transaction interrupts. - * @see MPU6050_RA_I2C_SLV4_CTRL - */ -bool MPU6050::getSlave4InterruptEnabled() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_INT_EN_BIT, buffer); - return buffer[0]; -} -/** Set the enabled value for Slave 4 transaction interrupts. - * @param enabled New enabled value for Slave 4 transaction interrupts. - * @see getSlave4InterruptEnabled() - * @see MPU6050_RA_I2C_SLV4_CTRL - */ -void MPU6050::setSlave4InterruptEnabled(bool enabled) -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_INT_EN_BIT, enabled); -} -/** Get write mode for Slave 4. - * When set to 1, the transaction will read or write data only. When cleared to - * 0, the transaction will write a register address prior to reading or writing - * data. This should equal 0 when specifying the register address within the - * Slave device to/from which the ensuing data transaction will take place. - * - * @return Current write mode for Slave 4 (0 = register address + data, 1 = data only) - * @see MPU6050_RA_I2C_SLV4_CTRL - */ -bool MPU6050::getSlave4WriteMode() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_REG_DIS_BIT, buffer); - return buffer[0]; -} -/** Set write mode for the Slave 4. - * @param mode New write mode for Slave 4 (0 = register address + data, 1 = data only) - * @see getSlave4WriteMode() - * @see MPU6050_RA_I2C_SLV4_CTRL - */ -void MPU6050::setSlave4WriteMode(bool mode) -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_REG_DIS_BIT, mode); -} -/** Get Slave 4 master delay value. - * This configures the reduced access rate of I2C slaves relative to the Sample - * Rate. When a slave's access rate is decreased relative to the Sample Rate, - * the slave is accessed every: - * - * 1 / (1 + I2C_MST_DLY) samples - * - * This base Sample Rate in turn is determined by SMPLRT_DIV (register 25) and - * DLPF_CFG (register 26). Whether a slave's access rate is reduced relative to - * the Sample Rate is determined by I2C_MST_DELAY_CTRL (register 103). For - * further information regarding the Sample Rate, please refer to register 25. - * - * @return Current Slave 4 master delay value - * @see MPU6050_RA_I2C_SLV4_CTRL - */ -uint8_t MPU6050::getSlave4MasterDelay() -{ - I2Cdev::readBits(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_MST_DLY_BIT, MPU6050_I2C_SLV4_MST_DLY_LENGTH, buffer); - return buffer[0]; -} -/** Set Slave 4 master delay value. - * @param delay New Slave 4 master delay value - * @see getSlave4MasterDelay() - * @see MPU6050_RA_I2C_SLV4_CTRL - */ -void MPU6050::setSlave4MasterDelay(uint8_t delay) -{ - I2Cdev::writeBits(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_MST_DLY_BIT, MPU6050_I2C_SLV4_MST_DLY_LENGTH, delay); -} -/** Get last available byte read from Slave 4. - * This register stores the data read from Slave 4. This field is populated - * after a read transaction. - * @return Last available byte read from to Slave 4 - * @see MPU6050_RA_I2C_SLV4_DI - */ -uint8_t MPU6050::getSlate4InputByte() -{ - I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV4_DI, buffer); - return buffer[0]; -} - -// I2C_MST_STATUS register - -/** Get FSYNC interrupt status. - * This bit reflects the status of the FSYNC interrupt from an external device - * into the MPU-60X0. This is used as a way to pass an external interrupt - * through the MPU-60X0 to the host application processor. When set to 1, this - * bit will cause an interrupt if FSYNC_INT_EN is asserted in INT_PIN_CFG - * (Register 55). - * @return FSYNC interrupt status - * @see MPU6050_RA_I2C_MST_STATUS - */ -bool MPU6050::getPassthroughStatus() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_PASS_THROUGH_BIT, buffer); - return buffer[0]; -} -/** Get Slave 4 transaction done status. - * Automatically sets to 1 when a Slave 4 transaction has completed. This - * triggers an interrupt if the I2C_MST_INT_EN bit in the INT_ENABLE register - * (Register 56) is asserted and if the SLV_4_DONE_INT bit is asserted in the - * I2C_SLV4_CTRL register (Register 52). - * @return Slave 4 transaction done status - * @see MPU6050_RA_I2C_MST_STATUS - */ -bool MPU6050::getSlave4IsDone() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV4_DONE_BIT, buffer); - return buffer[0]; -} -/** Get master arbitration lost status. - * This bit automatically sets to 1 when the I2C Master has lost arbitration of - * the auxiliary I2C bus (an error condition). This triggers an interrupt if the - * I2C_MST_INT_EN bit in the INT_ENABLE register (Register 56) is asserted. - * @return Master arbitration lost status - * @see MPU6050_RA_I2C_MST_STATUS - */ -bool MPU6050::getLostArbitration() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_LOST_ARB_BIT, buffer); - return buffer[0]; -} -/** Get Slave 4 NACK status. - * This bit automatically sets to 1 when the I2C Master receives a NACK in a - * transaction with Slave 4. This triggers an interrupt if the I2C_MST_INT_EN - * bit in the INT_ENABLE register (Register 56) is asserted. - * @return Slave 4 NACK interrupt status - * @see MPU6050_RA_I2C_MST_STATUS - */ -bool MPU6050::getSlave4Nack() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV4_NACK_BIT, buffer); - return buffer[0]; -} -/** Get Slave 3 NACK status. - * This bit automatically sets to 1 when the I2C Master receives a NACK in a - * transaction with Slave 3. This triggers an interrupt if the I2C_MST_INT_EN - * bit in the INT_ENABLE register (Register 56) is asserted. - * @return Slave 3 NACK interrupt status - * @see MPU6050_RA_I2C_MST_STATUS - */ -bool MPU6050::getSlave3Nack() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV3_NACK_BIT, buffer); - return buffer[0]; -} -/** Get Slave 2 NACK status. - * This bit automatically sets to 1 when the I2C Master receives a NACK in a - * transaction with Slave 2. This triggers an interrupt if the I2C_MST_INT_EN - * bit in the INT_ENABLE register (Register 56) is asserted. - * @return Slave 2 NACK interrupt status - * @see MPU6050_RA_I2C_MST_STATUS - */ -bool MPU6050::getSlave2Nack() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV2_NACK_BIT, buffer); - return buffer[0]; -} -/** Get Slave 1 NACK status. - * This bit automatically sets to 1 when the I2C Master receives a NACK in a - * transaction with Slave 1. This triggers an interrupt if the I2C_MST_INT_EN - * bit in the INT_ENABLE register (Register 56) is asserted. - * @return Slave 1 NACK interrupt status - * @see MPU6050_RA_I2C_MST_STATUS - */ -bool MPU6050::getSlave1Nack() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV1_NACK_BIT, buffer); - return buffer[0]; -} -/** Get Slave 0 NACK status. - * This bit automatically sets to 1 when the I2C Master receives a NACK in a - * transaction with Slave 0. This triggers an interrupt if the I2C_MST_INT_EN - * bit in the INT_ENABLE register (Register 56) is asserted. - * @return Slave 0 NACK interrupt status - * @see MPU6050_RA_I2C_MST_STATUS - */ -bool MPU6050::getSlave0Nack() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV0_NACK_BIT, buffer); - return buffer[0]; -} - -// INT_PIN_CFG register - -/** Get interrupt logic level mode. - * Will be set 0 for active-high, 1 for active-low. - * @return Current interrupt mode (0=active-high, 1=active-low) - * @see MPU6050_RA_INT_PIN_CFG - * @see MPU6050_INTCFG_INT_LEVEL_BIT - */ -bool MPU6050::getInterruptMode() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_LEVEL_BIT, buffer); - return buffer[0]; -} -/** Set interrupt logic level mode. - * @param mode New interrupt mode (0=active-high, 1=active-low) - * @see getInterruptMode() - * @see MPU6050_RA_INT_PIN_CFG - * @see MPU6050_INTCFG_INT_LEVEL_BIT - */ -void MPU6050::setInterruptMode(bool mode) -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_LEVEL_BIT, mode); -} -/** Get interrupt drive mode. - * Will be set 0 for push-pull, 1 for open-drain. - * @return Current interrupt drive mode (0=push-pull, 1=open-drain) - * @see MPU6050_RA_INT_PIN_CFG - * @see MPU6050_INTCFG_INT_OPEN_BIT - */ -bool MPU6050::getInterruptDrive() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_OPEN_BIT, buffer); - return buffer[0]; -} -/** Set interrupt drive mode. - * @param drive New interrupt drive mode (0=push-pull, 1=open-drain) - * @see getInterruptDrive() - * @see MPU6050_RA_INT_PIN_CFG - * @see MPU6050_INTCFG_INT_OPEN_BIT - */ -void MPU6050::setInterruptDrive(bool drive) -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_OPEN_BIT, drive); -} -/** Get interrupt latch mode. - * Will be set 0 for 50us-pulse, 1 for latch-until-int-cleared. - * @return Current latch mode (0=50us-pulse, 1=latch-until-int-cleared) - * @see MPU6050_RA_INT_PIN_CFG - * @see MPU6050_INTCFG_LATCH_INT_EN_BIT - */ -bool MPU6050::getInterruptLatch() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_LATCH_INT_EN_BIT, buffer); - return buffer[0]; -} -/** Set interrupt latch mode. - * @param latch New latch mode (0=50us-pulse, 1=latch-until-int-cleared) - * @see getInterruptLatch() - * @see MPU6050_RA_INT_PIN_CFG - * @see MPU6050_INTCFG_LATCH_INT_EN_BIT - */ -void MPU6050::setInterruptLatch(bool latch) -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_LATCH_INT_EN_BIT, latch); -} -/** Get interrupt latch clear mode. - * Will be set 0 for status-read-only, 1 for any-register-read. - * @return Current latch clear mode (0=status-read-only, 1=any-register-read) - * @see MPU6050_RA_INT_PIN_CFG - * @see MPU6050_INTCFG_INT_RD_CLEAR_BIT - */ -bool MPU6050::getInterruptLatchClear() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_RD_CLEAR_BIT, buffer); - return buffer[0]; -} -/** Set interrupt latch clear mode. - * @param clear New latch clear mode (0=status-read-only, 1=any-register-read) - * @see getInterruptLatchClear() - * @see MPU6050_RA_INT_PIN_CFG - * @see MPU6050_INTCFG_INT_RD_CLEAR_BIT - */ -void MPU6050::setInterruptLatchClear(bool clear) -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_RD_CLEAR_BIT, clear); -} -/** Get FSYNC interrupt logic level mode. - * @return Current FSYNC interrupt mode (0=active-high, 1=active-low) - * @see getFSyncInterruptMode() - * @see MPU6050_RA_INT_PIN_CFG - * @see MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT - */ -bool MPU6050::getFSyncInterruptLevel() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT, buffer); - return buffer[0]; -} -/** Set FSYNC interrupt logic level mode. - * @param mode New FSYNC interrupt mode (0=active-high, 1=active-low) - * @see getFSyncInterruptMode() - * @see MPU6050_RA_INT_PIN_CFG - * @see MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT - */ -void MPU6050::setFSyncInterruptLevel(bool level) -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT, level); -} -/** Get FSYNC pin interrupt enabled setting. - * Will be set 0 for disabled, 1 for enabled. - * @return Current interrupt enabled setting - * @see MPU6050_RA_INT_PIN_CFG - * @see MPU6050_INTCFG_FSYNC_INT_EN_BIT - */ -bool MPU6050::getFSyncInterruptEnabled() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_EN_BIT, buffer); - return buffer[0]; -} -/** Set FSYNC pin interrupt enabled setting. - * @param enabled New FSYNC pin interrupt enabled setting - * @see getFSyncInterruptEnabled() - * @see MPU6050_RA_INT_PIN_CFG - * @see MPU6050_INTCFG_FSYNC_INT_EN_BIT - */ -void MPU6050::setFSyncInterruptEnabled(bool enabled) -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_EN_BIT, enabled); -} -/** Get I2C bypass enabled status. - * When this bit is equal to 1 and I2C_MST_EN (Register 106 bit[5]) is equal to - * 0, the host application processor will be able to directly access the - * auxiliary I2C bus of the MPU-60X0. When this bit is equal to 0, the host - * application processor will not be able to directly access the auxiliary I2C - * bus of the MPU-60X0 regardless of the state of I2C_MST_EN (Register 106 - * bit[5]). - * @return Current I2C bypass enabled status - * @see MPU6050_RA_INT_PIN_CFG - * @see MPU6050_INTCFG_I2C_BYPASS_EN_BIT - */ -bool MPU6050::getI2CBypassEnabled() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_I2C_BYPASS_EN_BIT, buffer); - return buffer[0]; -} -/** Set I2C bypass enabled status. - * When this bit is equal to 1 and I2C_MST_EN (Register 106 bit[5]) is equal to - * 0, the host application processor will be able to directly access the - * auxiliary I2C bus of the MPU-60X0. When this bit is equal to 0, the host - * application processor will not be able to directly access the auxiliary I2C - * bus of the MPU-60X0 regardless of the state of I2C_MST_EN (Register 106 - * bit[5]). - * @param enabled New I2C bypass enabled status - * @see MPU6050_RA_INT_PIN_CFG - * @see MPU6050_INTCFG_I2C_BYPASS_EN_BIT - */ -void MPU6050::setI2CBypassEnabled(bool enabled) -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_I2C_BYPASS_EN_BIT, enabled); -} -/** Get reference clock output enabled status. - * When this bit is equal to 1, a reference clock output is provided at the - * CLKOUT pin. When this bit is equal to 0, the clock output is disabled. For - * further information regarding CLKOUT, please refer to the MPU-60X0 Product - * Specification document. - * @return Current reference clock output enabled status - * @see MPU6050_RA_INT_PIN_CFG - * @see MPU6050_INTCFG_CLKOUT_EN_BIT - */ -bool MPU6050::getClockOutputEnabled() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_CLKOUT_EN_BIT, buffer); - return buffer[0]; -} -/** Set reference clock output enabled status. - * When this bit is equal to 1, a reference clock output is provided at the - * CLKOUT pin. When this bit is equal to 0, the clock output is disabled. For - * further information regarding CLKOUT, please refer to the MPU-60X0 Product - * Specification document. - * @param enabled New reference clock output enabled status - * @see MPU6050_RA_INT_PIN_CFG - * @see MPU6050_INTCFG_CLKOUT_EN_BIT - */ -void MPU6050::setClockOutputEnabled(bool enabled) -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_CLKOUT_EN_BIT, enabled); -} - -// INT_ENABLE register - -/** Get full interrupt enabled status. - * Full register byte for all interrupts, for quick reading. Each bit will be - * set 0 for disabled, 1 for enabled. - * @return Current interrupt enabled status - * @see MPU6050_RA_INT_ENABLE - * @see MPU6050_INTERRUPT_FF_BIT - **/ -uint8_t MPU6050::getIntEnabled() -{ - I2Cdev::readByte(devAddr, MPU6050_RA_INT_ENABLE, buffer); - return buffer[0]; -} -/** Set full interrupt enabled status. - * Full register byte for all interrupts, for quick reading. Each bit should be - * set 0 for disabled, 1 for enabled. - * @param enabled New interrupt enabled status - * @see getIntFreefallEnabled() - * @see MPU6050_RA_INT_ENABLE - * @see MPU6050_INTERRUPT_FF_BIT - **/ -void MPU6050::setIntEnabled(uint8_t enabled) -{ - I2Cdev::writeByte(devAddr, MPU6050_RA_INT_ENABLE, enabled); -} -/** Get Free Fall interrupt enabled status. - * Will be set 0 for disabled, 1 for enabled. - * @return Current interrupt enabled status - * @see MPU6050_RA_INT_ENABLE - * @see MPU6050_INTERRUPT_FF_BIT - **/ -bool MPU6050::getIntFreefallEnabled() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FF_BIT, buffer); - return buffer[0]; -} -/** Set Free Fall interrupt enabled status. - * @param enabled New interrupt enabled status - * @see getIntFreefallEnabled() - * @see MPU6050_RA_INT_ENABLE - * @see MPU6050_INTERRUPT_FF_BIT - **/ -void MPU6050::setIntFreefallEnabled(bool enabled) -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FF_BIT, enabled); -} -/** Get Motion Detection interrupt enabled status. - * Will be set 0 for disabled, 1 for enabled. - * @return Current interrupt enabled status - * @see MPU6050_RA_INT_ENABLE - * @see MPU6050_INTERRUPT_MOT_BIT - **/ -bool MPU6050::getIntMotionEnabled() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_MOT_BIT, buffer); - return buffer[0]; -} -/** Set Motion Detection interrupt enabled status. - * @param enabled New interrupt enabled status - * @see getIntMotionEnabled() - * @see MPU6050_RA_INT_ENABLE - * @see MPU6050_INTERRUPT_MOT_BIT - **/ -void MPU6050::setIntMotionEnabled(bool enabled) -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_MOT_BIT, enabled); -} -/** Get Zero Motion Detection interrupt enabled status. - * Will be set 0 for disabled, 1 for enabled. - * @return Current interrupt enabled status - * @see MPU6050_RA_INT_ENABLE - * @see MPU6050_INTERRUPT_ZMOT_BIT - **/ -bool MPU6050::getIntZeroMotionEnabled() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_ZMOT_BIT, buffer); - return buffer[0]; -} -/** Set Zero Motion Detection interrupt enabled status. - * @param enabled New interrupt enabled status - * @see getIntZeroMotionEnabled() - * @see MPU6050_RA_INT_ENABLE - * @see MPU6050_INTERRUPT_ZMOT_BIT - **/ -void MPU6050::setIntZeroMotionEnabled(bool enabled) -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_ZMOT_BIT, enabled); -} -/** Get FIFO Buffer Overflow interrupt enabled status. - * Will be set 0 for disabled, 1 for enabled. - * @return Current interrupt enabled status - * @see MPU6050_RA_INT_ENABLE - * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT - **/ -bool MPU6050::getIntFIFOBufferOverflowEnabled() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, buffer); - return buffer[0]; -} -/** Set FIFO Buffer Overflow interrupt enabled status. - * @param enabled New interrupt enabled status - * @see getIntFIFOBufferOverflowEnabled() - * @see MPU6050_RA_INT_ENABLE - * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT - **/ -void MPU6050::setIntFIFOBufferOverflowEnabled(bool enabled) -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, enabled); -} -/** Get I2C Master interrupt enabled status. - * This enables any of the I2C Master interrupt sources to generate an - * interrupt. Will be set 0 for disabled, 1 for enabled. - * @return Current interrupt enabled status - * @see MPU6050_RA_INT_ENABLE - * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT - **/ -bool MPU6050::getIntI2CMasterEnabled() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_I2C_MST_INT_BIT, buffer); - return buffer[0]; -} -/** Set I2C Master interrupt enabled status. - * @param enabled New interrupt enabled status - * @see getIntI2CMasterEnabled() - * @see MPU6050_RA_INT_ENABLE - * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT - **/ -void MPU6050::setIntI2CMasterEnabled(bool enabled) -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_I2C_MST_INT_BIT, enabled); -} -/** Get Data Ready interrupt enabled setting. - * This event occurs each time a write operation to all of the sensor registers - * has been completed. Will be set 0 for disabled, 1 for enabled. - * @return Current interrupt enabled status - * @see MPU6050_RA_INT_ENABLE - * @see MPU6050_INTERRUPT_DATA_RDY_BIT - */ -bool MPU6050::getIntDataReadyEnabled() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DATA_RDY_BIT, buffer); - return buffer[0]; -} -/** Set Data Ready interrupt enabled status. - * @param enabled New interrupt enabled status - * @see getIntDataReadyEnabled() - * @see MPU6050_RA_INT_CFG - * @see MPU6050_INTERRUPT_DATA_RDY_BIT - */ -void MPU6050::setIntDataReadyEnabled(bool enabled) -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DATA_RDY_BIT, enabled); -} - -// INT_STATUS register - -/** Get full set of interrupt status bits. - * These bits clear to 0 after the register has been read. Very useful - * for getting multiple INT statuses, since each single bit read clears - * all of them because it has to read the whole byte. - * @return Current interrupt status - * @see MPU6050_RA_INT_STATUS - */ -uint8_t MPU6050::getIntStatus() -{ - I2Cdev::readByte(devAddr, MPU6050_RA_INT_STATUS, buffer); - return buffer[0]; -} -/** Get Free Fall interrupt status. - * This bit automatically sets to 1 when a Free Fall interrupt has been - * generated. The bit clears to 0 after the register has been read. - * @return Current interrupt status - * @see MPU6050_RA_INT_STATUS - * @see MPU6050_INTERRUPT_FF_BIT - */ -bool MPU6050::getIntFreefallStatus() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_FF_BIT, buffer); - return buffer[0]; -} -/** Get Motion Detection interrupt status. - * This bit automatically sets to 1 when a Motion Detection interrupt has been - * generated. The bit clears to 0 after the register has been read. - * @return Current interrupt status - * @see MPU6050_RA_INT_STATUS - * @see MPU6050_INTERRUPT_MOT_BIT - */ -bool MPU6050::getIntMotionStatus() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_MOT_BIT, buffer); - return buffer[0]; -} -/** Get Zero Motion Detection interrupt status. - * This bit automatically sets to 1 when a Zero Motion Detection interrupt has - * been generated. The bit clears to 0 after the register has been read. - * @return Current interrupt status - * @see MPU6050_RA_INT_STATUS - * @see MPU6050_INTERRUPT_ZMOT_BIT - */ -bool MPU6050::getIntZeroMotionStatus() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_ZMOT_BIT, buffer); - return buffer[0]; -} -/** Get FIFO Buffer Overflow interrupt status. - * This bit automatically sets to 1 when a Free Fall interrupt has been - * generated. The bit clears to 0 after the register has been read. - * @return Current interrupt status - * @see MPU6050_RA_INT_STATUS - * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT - */ -bool MPU6050::getIntFIFOBufferOverflowStatus() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, buffer); - return buffer[0]; -} -/** Get I2C Master interrupt status. - * This bit automatically sets to 1 when an I2C Master interrupt has been - * generated. For a list of I2C Master interrupts, please refer to Register 54. - * The bit clears to 0 after the register has been read. - * @return Current interrupt status - * @see MPU6050_RA_INT_STATUS - * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT - */ -bool MPU6050::getIntI2CMasterStatus() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_I2C_MST_INT_BIT, buffer); - return buffer[0]; -} -/** Get Data Ready interrupt status. - * This bit automatically sets to 1 when a Data Ready interrupt has been - * generated. The bit clears to 0 after the register has been read. - * @return Current interrupt status - * @see MPU6050_RA_INT_STATUS - * @see MPU6050_INTERRUPT_DATA_RDY_BIT - */ -bool MPU6050::getIntDataReadyStatus() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_DATA_RDY_BIT, buffer); - return buffer[0]; -} - -// ACCEL_*OUT_* registers - -/** Get raw 9-axis motion sensor readings (accel/gyro/compass). - * FUNCTION NOT FULLY IMPLEMENTED YET. - * @param ax 16-bit signed integer container for accelerometer X-axis value - * @param ay 16-bit signed integer container for accelerometer Y-axis value - * @param az 16-bit signed integer container for accelerometer Z-axis value - * @param gx 16-bit signed integer container for gyroscope X-axis value - * @param gy 16-bit signed integer container for gyroscope Y-axis value - * @param gz 16-bit signed integer container for gyroscope Z-axis value - * @param mx 16-bit signed integer container for magnetometer X-axis value - * @param my 16-bit signed integer container for magnetometer Y-axis value - * @param mz 16-bit signed integer container for magnetometer Z-axis value - * @see getMotion6() - * @see getAcceleration() - * @see getRotation() - * @see MPU6050_RA_ACCEL_XOUT_H - */ -void MPU6050::getMotion9(int16_t *ax, int16_t *ay, int16_t *az, int16_t *gx, int16_t *gy, int16_t *gz, int16_t *mx, int16_t *my, int16_t *mz) -{ - getMotion6(ax, ay, az, gx, gy, gz); - // TODO: magnetometer integration -} -/** Get raw 6-axis motion sensor readings (accel/gyro). - * Retrieves all currently available motion sensor values. - * @param ax 16-bit signed integer container for accelerometer X-axis value - * @param ay 16-bit signed integer container for accelerometer Y-axis value - * @param az 16-bit signed integer container for accelerometer Z-axis value - * @param gx 16-bit signed integer container for gyroscope X-axis value - * @param gy 16-bit signed integer container for gyroscope Y-axis value - * @param gz 16-bit signed integer container for gyroscope Z-axis value - * @see getAcceleration() - * @see getRotation() - * @see MPU6050_RA_ACCEL_XOUT_H - */ -void MPU6050::getMotion6(int16_t *ax, int16_t *ay, int16_t *az, int16_t *gx, int16_t *gy, int16_t *gz) -{ - I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_XOUT_H, 14, buffer); - *ax = (((int16_t)buffer[0]) << 8) | buffer[1]; - *ay = (((int16_t)buffer[2]) << 8) | buffer[3]; - *az = (((int16_t)buffer[4]) << 8) | buffer[5]; - *gx = (((int16_t)buffer[8]) << 8) | buffer[9]; - *gy = (((int16_t)buffer[10]) << 8) | buffer[11]; - *gz = (((int16_t)buffer[12]) << 8) | buffer[13]; -} -/** Get 3-axis accelerometer readings. - * These registers store the most recent accelerometer measurements. - * Accelerometer measurements are written to these registers at the Sample Rate - * as defined in Register 25. - * - * The accelerometer measurement registers, along with the temperature - * measurement registers, gyroscope measurement registers, and external sensor - * data registers, are composed of two sets of registers: an internal register - * set and a user-facing read register set. - * - * The data within the accelerometer sensors' internal register set is always - * updated at the Sample Rate. Meanwhile, the user-facing read register set - * duplicates the internal register set's data values whenever the serial - * interface is idle. This guarantees that a burst read of sensor registers will - * read measurements from the same sampling instant. Note that if burst reads - * are not used, the user is responsible for ensuring a set of single byte reads - * correspond to a single sampling instant by checking the Data Ready interrupt. - * - * Each 16-bit accelerometer measurement has a full scale defined in ACCEL_FS - * (Register 28). For each full scale setting, the accelerometers' sensitivity - * per LSB in ACCEL_xOUT is shown in the table below: - * - *
- * AFS_SEL | Full Scale Range | LSB Sensitivity
- * --------+------------------+----------------
- * 0       | +/- 2g           | 8192 LSB/mg
- * 1       | +/- 4g           | 4096 LSB/mg
- * 2       | +/- 8g           | 2048 LSB/mg
- * 3       | +/- 16g          | 1024 LSB/mg
- * 
- * - * @param x 16-bit signed integer container for X-axis acceleration - * @param y 16-bit signed integer container for Y-axis acceleration - * @param z 16-bit signed integer container for Z-axis acceleration - * @see MPU6050_RA_GYRO_XOUT_H - */ -void MPU6050::getAcceleration(int16_t *x, int16_t *y, int16_t *z) -{ - I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_XOUT_H, 6, buffer); - *x = (((int16_t)buffer[0]) << 8) | buffer[1]; - *y = (((int16_t)buffer[2]) << 8) | buffer[3]; - *z = (((int16_t)buffer[4]) << 8) | buffer[5]; -} -/** Get X-axis accelerometer reading. - * @return X-axis acceleration measurement in 16-bit 2's complement format - * @see getMotion6() - * @see MPU6050_RA_ACCEL_XOUT_H - */ -int16_t MPU6050::getAccelerationX() -{ - I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_XOUT_H, 2, buffer); - return (((int16_t)buffer[0]) << 8) | buffer[1]; -} -/** Get Y-axis accelerometer reading. - * @return Y-axis acceleration measurement in 16-bit 2's complement format - * @see getMotion6() - * @see MPU6050_RA_ACCEL_YOUT_H - */ -int16_t MPU6050::getAccelerationY() -{ - I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_YOUT_H, 2, buffer); - return (((int16_t)buffer[0]) << 8) | buffer[1]; -} -/** Get Z-axis accelerometer reading. - * @return Z-axis acceleration measurement in 16-bit 2's complement format - * @see getMotion6() - * @see MPU6050_RA_ACCEL_ZOUT_H - */ -int16_t MPU6050::getAccelerationZ() -{ - I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_ZOUT_H, 2, buffer); - return (((int16_t)buffer[0]) << 8) | buffer[1]; -} - -// TEMP_OUT_* registers - -/** Get current internal temperature. - * @return Temperature reading in 16-bit 2's complement format - * @see MPU6050_RA_TEMP_OUT_H - */ -int16_t MPU6050::getTemperature() -{ - I2Cdev::readBytes(devAddr, MPU6050_RA_TEMP_OUT_H, 2, buffer); - return (((int16_t)buffer[0]) << 8) | buffer[1]; -} - -// GYRO_*OUT_* registers - -/** Get 3-axis gyroscope readings. - * These gyroscope measurement registers, along with the accelerometer - * measurement registers, temperature measurement registers, and external sensor - * data registers, are composed of two sets of registers: an internal register - * set and a user-facing read register set. - * The data within the gyroscope sensors' internal register set is always - * updated at the Sample Rate. Meanwhile, the user-facing read register set - * duplicates the internal register set's data values whenever the serial - * interface is idle. This guarantees that a burst read of sensor registers will - * read measurements from the same sampling instant. Note that if burst reads - * are not used, the user is responsible for ensuring a set of single byte reads - * correspond to a single sampling instant by checking the Data Ready interrupt. - * - * Each 16-bit gyroscope measurement has a full scale defined in FS_SEL - * (Register 27). For each full scale setting, the gyroscopes' sensitivity per - * LSB in GYRO_xOUT is shown in the table below: - * - *
- * FS_SEL | Full Scale Range   | LSB Sensitivity
- * -------+--------------------+----------------
- * 0      | +/- 250 degrees/s  | 131 LSB/deg/s
- * 1      | +/- 500 degrees/s  | 65.5 LSB/deg/s
- * 2      | +/- 1000 degrees/s | 32.8 LSB/deg/s
- * 3      | +/- 2000 degrees/s | 16.4 LSB/deg/s
- * 
- * - * @param x 16-bit signed integer container for X-axis rotation - * @param y 16-bit signed integer container for Y-axis rotation - * @param z 16-bit signed integer container for Z-axis rotation - * @see getMotion6() - * @see MPU6050_RA_GYRO_XOUT_H - */ -void MPU6050::getRotation(int16_t *x, int16_t *y, int16_t *z) -{ - I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_XOUT_H, 6, buffer); - *x = (((int16_t)buffer[0]) << 8) | buffer[1]; - *y = (((int16_t)buffer[2]) << 8) | buffer[3]; - *z = (((int16_t)buffer[4]) << 8) | buffer[5]; -} -/** Get X-axis gyroscope reading. - * @return X-axis rotation measurement in 16-bit 2's complement format - * @see getMotion6() - * @see MPU6050_RA_GYRO_XOUT_H - */ -int16_t MPU6050::getRotationX() -{ - I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_XOUT_H, 2, buffer); - return (((int16_t)buffer[0]) << 8) | buffer[1]; -} -/** Get Y-axis gyroscope reading. - * @return Y-axis rotation measurement in 16-bit 2's complement format - * @see getMotion6() - * @see MPU6050_RA_GYRO_YOUT_H - */ -int16_t MPU6050::getRotationY() -{ - I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_YOUT_H, 2, buffer); - return (((int16_t)buffer[0]) << 8) | buffer[1]; -} -/** Get Z-axis gyroscope reading. - * @return Z-axis rotation measurement in 16-bit 2's complement format - * @see getMotion6() - * @see MPU6050_RA_GYRO_ZOUT_H - */ -int16_t MPU6050::getRotationZ() -{ - I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_ZOUT_H, 2, buffer); - return (((int16_t)buffer[0]) << 8) | buffer[1]; -} - -// EXT_SENS_DATA_* registers - -/** Read single byte from external sensor data register. - * These registers store data read from external sensors by the Slave 0, 1, 2, - * and 3 on the auxiliary I2C interface. Data read by Slave 4 is stored in - * I2C_SLV4_DI (Register 53). - * - * External sensor data is written to these registers at the Sample Rate as - * defined in Register 25. This access rate can be reduced by using the Slave - * Delay Enable registers (Register 103). - * - * External sensor data registers, along with the gyroscope measurement - * registers, accelerometer measurement registers, and temperature measurement - * registers, are composed of two sets of registers: an internal register set - * and a user-facing read register set. - * - * The data within the external sensors' internal register set is always updated - * at the Sample Rate (or the reduced access rate) whenever the serial interface - * is idle. This guarantees that a burst read of sensor registers will read - * measurements from the same sampling instant. Note that if burst reads are not - * used, the user is responsible for ensuring a set of single byte reads - * correspond to a single sampling instant by checking the Data Ready interrupt. - * - * Data is placed in these external sensor data registers according to - * I2C_SLV0_CTRL, I2C_SLV1_CTRL, I2C_SLV2_CTRL, and I2C_SLV3_CTRL (Registers 39, - * 42, 45, and 48). When more than zero bytes are read (I2C_SLVx_LEN > 0) from - * an enabled slave (I2C_SLVx_EN = 1), the slave is read at the Sample Rate (as - * defined in Register 25) or delayed rate (if specified in Register 52 and - * 103). During each Sample cycle, slave reads are performed in order of Slave - * number. If all slaves are enabled with more than zero bytes to be read, the - * order will be Slave 0, followed by Slave 1, Slave 2, and Slave 3. - * - * Each enabled slave will have EXT_SENS_DATA registers associated with it by - * number of bytes read (I2C_SLVx_LEN) in order of slave number, starting from - * EXT_SENS_DATA_00. Note that this means enabling or disabling a slave may - * change the higher numbered slaves' associated registers. Furthermore, if - * fewer total bytes are being read from the external sensors as a result of - * such a change, then the data remaining in the registers which no longer have - * an associated slave device (i.e. high numbered registers) will remain in - * these previously allocated registers unless reset. - * - * If the sum of the read lengths of all SLVx transactions exceed the number of - * available EXT_SENS_DATA registers, the excess bytes will be dropped. There - * are 24 EXT_SENS_DATA registers and hence the total read lengths between all - * the slaves cannot be greater than 24 or some bytes will be lost. - * - * Note: Slave 4's behavior is distinct from that of Slaves 0-3. For further - * information regarding the characteristics of Slave 4, please refer to - * Registers 49 to 53. - * - * EXAMPLE: - * Suppose that Slave 0 is enabled with 4 bytes to be read (I2C_SLV0_EN = 1 and - * I2C_SLV0_LEN = 4) while Slave 1 is enabled with 2 bytes to be read so that - * I2C_SLV1_EN = 1 and I2C_SLV1_LEN = 2. In such a situation, EXT_SENS_DATA _00 - * through _03 will be associated with Slave 0, while EXT_SENS_DATA _04 and 05 - * will be associated with Slave 1. If Slave 2 is enabled as well, registers - * starting from EXT_SENS_DATA_06 will be allocated to Slave 2. - * - * If Slave 2 is disabled while Slave 3 is enabled in this same situation, then - * registers starting from EXT_SENS_DATA_06 will be allocated to Slave 3 - * instead. - * - * REGISTER ALLOCATION FOR DYNAMIC DISABLE VS. NORMAL DISABLE: - * If a slave is disabled at any time, the space initially allocated to the - * slave in the EXT_SENS_DATA register, will remain associated with that slave. - * This is to avoid dynamic adjustment of the register allocation. - * - * The allocation of the EXT_SENS_DATA registers is recomputed only when (1) all - * slaves are disabled, or (2) the I2C_MST_RST bit is set (Register 106). - * - * This above is also true if one of the slaves gets NACKed and stops - * functioning. - * - * @param position Starting position (0-23) - * @return Byte read from register - */ -uint8_t MPU6050::getExternalSensorByte(int position) -{ - I2Cdev::readByte(devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, buffer); - return buffer[0]; -} -/** Read word (2 bytes) from external sensor data registers. - * @param position Starting position (0-21) - * @return Word read from register - * @see getExternalSensorByte() - */ -uint16_t MPU6050::getExternalSensorWord(int position) -{ - I2Cdev::readBytes(devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, 2, buffer); - return (((uint16_t)buffer[0]) << 8) | buffer[1]; -} -/** Read double word (4 bytes) from external sensor data registers. - * @param position Starting position (0-20) - * @return Double word read from registers - * @see getExternalSensorByte() - */ -uint32_t MPU6050::getExternalSensorDWord(int position) -{ - I2Cdev::readBytes(devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, 4, buffer); - return (((uint32_t)buffer[0]) << 24) | (((uint32_t)buffer[1]) << 16) | (((uint16_t)buffer[2]) << 8) | buffer[3]; -} - -// MOT_DETECT_STATUS register - -/** Get full motion detection status register content (all bits). - * @return Motion detection status byte - * @see MPU6050_RA_MOT_DETECT_STATUS - */ -uint8_t MPU6050::getMotionStatus() -{ - I2Cdev::readByte(devAddr, MPU6050_RA_MOT_DETECT_STATUS, buffer); - return buffer[0]; -} -/** Get X-axis negative motion detection interrupt status. - * @return Motion detection status - * @see MPU6050_RA_MOT_DETECT_STATUS - * @see MPU6050_MOTION_MOT_XNEG_BIT - */ -bool MPU6050::getXNegMotionDetected() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_XNEG_BIT, buffer); - return buffer[0]; -} -/** Get X-axis positive motion detection interrupt status. - * @return Motion detection status - * @see MPU6050_RA_MOT_DETECT_STATUS - * @see MPU6050_MOTION_MOT_XPOS_BIT - */ -bool MPU6050::getXPosMotionDetected() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_XPOS_BIT, buffer); - return buffer[0]; -} -/** Get Y-axis negative motion detection interrupt status. - * @return Motion detection status - * @see MPU6050_RA_MOT_DETECT_STATUS - * @see MPU6050_MOTION_MOT_YNEG_BIT - */ -bool MPU6050::getYNegMotionDetected() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_YNEG_BIT, buffer); - return buffer[0]; -} -/** Get Y-axis positive motion detection interrupt status. - * @return Motion detection status - * @see MPU6050_RA_MOT_DETECT_STATUS - * @see MPU6050_MOTION_MOT_YPOS_BIT - */ -bool MPU6050::getYPosMotionDetected() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_YPOS_BIT, buffer); - return buffer[0]; -} -/** Get Z-axis negative motion detection interrupt status. - * @return Motion detection status - * @see MPU6050_RA_MOT_DETECT_STATUS - * @see MPU6050_MOTION_MOT_ZNEG_BIT - */ -bool MPU6050::getZNegMotionDetected() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZNEG_BIT, buffer); - return buffer[0]; -} -/** Get Z-axis positive motion detection interrupt status. - * @return Motion detection status - * @see MPU6050_RA_MOT_DETECT_STATUS - * @see MPU6050_MOTION_MOT_ZPOS_BIT - */ -bool MPU6050::getZPosMotionDetected() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZPOS_BIT, buffer); - return buffer[0]; -} -/** Get zero motion detection interrupt status. - * @return Motion detection status - * @see MPU6050_RA_MOT_DETECT_STATUS - * @see MPU6050_MOTION_MOT_ZRMOT_BIT - */ -bool MPU6050::getZeroMotionDetected() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZRMOT_BIT, buffer); - return buffer[0]; -} - -// I2C_SLV*_DO register - -/** Write byte to Data Output container for specified slave. - * This register holds the output data written into Slave when Slave is set to - * write mode. For further information regarding Slave control, please - * refer to Registers 37 to 39 and immediately following. - * @param num Slave number (0-3) - * @param data Byte to write - * @see MPU6050_RA_I2C_SLV0_DO - */ -void MPU6050::setSlaveOutputByte(uint8_t num, uint8_t data) -{ - if (num > 3) - return; - I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV0_DO + num, data); -} - -// I2C_MST_DELAY_CTRL register - -/** Get external data shadow delay enabled status. - * This register is used to specify the timing of external sensor data - * shadowing. When DELAY_ES_SHADOW is set to 1, shadowing of external - * sensor data is delayed until all data has been received. - * @return Current external data shadow delay enabled status. - * @see MPU6050_RA_I2C_MST_DELAY_CTRL - * @see MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT - */ -bool MPU6050::getExternalShadowDelayEnabled() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT, buffer); - return buffer[0]; -} -/** Set external data shadow delay enabled status. - * @param enabled New external data shadow delay enabled status. - * @see getExternalShadowDelayEnabled() - * @see MPU6050_RA_I2C_MST_DELAY_CTRL - * @see MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT - */ -void MPU6050::setExternalShadowDelayEnabled(bool enabled) -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT, enabled); -} -/** Get slave delay enabled status. - * When a particular slave delay is enabled, the rate of access for the that - * slave device is reduced. When a slave's access rate is decreased relative to - * the Sample Rate, the slave is accessed every: - * - * 1 / (1 + I2C_MST_DLY) Samples - * - * This base Sample Rate in turn is determined by SMPLRT_DIV (register * 25) - * and DLPF_CFG (register 26). - * - * For further information regarding I2C_MST_DLY, please refer to register 52. - * For further information regarding the Sample Rate, please refer to register 25. - * - * @param num Slave number (0-4) - * @return Current slave delay enabled status. - * @see MPU6050_RA_I2C_MST_DELAY_CTRL - * @see MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT - */ -bool MPU6050::getSlaveDelayEnabled(uint8_t num) -{ - // MPU6050_DELAYCTRL_I2C_SLV4_DLY_EN_BIT is 4, SLV3 is 3, etc. - if (num > 4) - return 0; - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, num, buffer); - return buffer[0]; -} -/** Set slave delay enabled status. - * @param num Slave number (0-4) - * @param enabled New slave delay enabled status. - * @see MPU6050_RA_I2C_MST_DELAY_CTRL - * @see MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT - */ -void MPU6050::setSlaveDelayEnabled(uint8_t num, bool enabled) -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, num, enabled); -} - -// SIGNAL_PATH_RESET register - -/** Reset gyroscope signal path. - * The reset will revert the signal path analog to digital converters and - * filters to their power up configurations. - * @see MPU6050_RA_SIGNAL_PATH_RESET - * @see MPU6050_PATHRESET_GYRO_RESET_BIT - */ -void MPU6050::resetGyroscopePath() -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_GYRO_RESET_BIT, true); -} -/** Reset accelerometer signal path. - * The reset will revert the signal path analog to digital converters and - * filters to their power up configurations. - * @see MPU6050_RA_SIGNAL_PATH_RESET - * @see MPU6050_PATHRESET_ACCEL_RESET_BIT - */ -void MPU6050::resetAccelerometerPath() -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_ACCEL_RESET_BIT, true); -} -/** Reset temperature sensor signal path. - * The reset will revert the signal path analog to digital converters and - * filters to their power up configurations. - * @see MPU6050_RA_SIGNAL_PATH_RESET - * @see MPU6050_PATHRESET_TEMP_RESET_BIT - */ -void MPU6050::resetTemperaturePath() -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_TEMP_RESET_BIT, true); -} - -// MOT_DETECT_CTRL register - -/** Get accelerometer power-on delay. - * The accelerometer data path provides samples to the sensor registers, Motion - * detection, Zero Motion detection, and Free Fall detection modules. The - * signal path contains filters which must be flushed on wake-up with new - * samples before the detection modules begin operations. The default wake-up - * delay, of 4ms can be lengthened by up to 3ms. This additional delay is - * specified in ACCEL_ON_DELAY in units of 1 LSB = 1 ms. The user may select - * any value above zero unless instructed otherwise by InvenSense. Please refer - * to Section 8 of the MPU-6000/MPU-6050 Product Specification document for - * further information regarding the detection modules. - * @return Current accelerometer power-on delay - * @see MPU6050_RA_MOT_DETECT_CTRL - * @see MPU6050_DETECT_ACCEL_ON_DELAY_BIT - */ -uint8_t MPU6050::getAccelerometerPowerOnDelay() -{ - I2Cdev::readBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_ACCEL_ON_DELAY_BIT, MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH, buffer); - return buffer[0]; -} -/** Set accelerometer power-on delay. - * @param delay New accelerometer power-on delay (0-3) - * @see getAccelerometerPowerOnDelay() - * @see MPU6050_RA_MOT_DETECT_CTRL - * @see MPU6050_DETECT_ACCEL_ON_DELAY_BIT - */ -void MPU6050::setAccelerometerPowerOnDelay(uint8_t delay) -{ - I2Cdev::writeBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_ACCEL_ON_DELAY_BIT, MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH, delay); -} -/** Get Free Fall detection counter decrement configuration. - * Detection is registered by the Free Fall detection module after accelerometer - * measurements meet their respective threshold conditions over a specified - * number of samples. When the threshold conditions are met, the corresponding - * detection counter increments by 1. The user may control the rate at which the - * detection counter decrements when the threshold condition is not met by - * configuring FF_COUNT. The decrement rate can be set according to the - * following table: - * - *
- * FF_COUNT | Counter Decrement
- * ---------+------------------
- * 0        | Reset
- * 1        | 1
- * 2        | 2
- * 3        | 4
- * 
- * - * When FF_COUNT is configured to 0 (reset), any non-qualifying sample will - * reset the counter to 0. For further information on Free Fall detection, - * please refer to Registers 29 to 32. - * - * @return Current decrement configuration - * @see MPU6050_RA_MOT_DETECT_CTRL - * @see MPU6050_DETECT_FF_COUNT_BIT - */ -uint8_t MPU6050::getFreefallDetectionCounterDecrement() -{ - I2Cdev::readBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_FF_COUNT_BIT, MPU6050_DETECT_FF_COUNT_LENGTH, buffer); - return buffer[0]; -} -/** Set Free Fall detection counter decrement configuration. - * @param decrement New decrement configuration value - * @see getFreefallDetectionCounterDecrement() - * @see MPU6050_RA_MOT_DETECT_CTRL - * @see MPU6050_DETECT_FF_COUNT_BIT - */ -void MPU6050::setFreefallDetectionCounterDecrement(uint8_t decrement) -{ - I2Cdev::writeBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_FF_COUNT_BIT, MPU6050_DETECT_FF_COUNT_LENGTH, decrement); -} -/** Get Motion detection counter decrement configuration. - * Detection is registered by the Motion detection module after accelerometer - * measurements meet their respective threshold conditions over a specified - * number of samples. When the threshold conditions are met, the corresponding - * detection counter increments by 1. The user may control the rate at which the - * detection counter decrements when the threshold condition is not met by - * configuring MOT_COUNT. The decrement rate can be set according to the - * following table: - * - *
- * MOT_COUNT | Counter Decrement
- * ----------+------------------
- * 0         | Reset
- * 1         | 1
- * 2         | 2
- * 3         | 4
- * 
- * - * When MOT_COUNT is configured to 0 (reset), any non-qualifying sample will - * reset the counter to 0. For further information on Motion detection, - * please refer to Registers 29 to 32. - * - */ -uint8_t MPU6050::getMotionDetectionCounterDecrement() -{ - I2Cdev::readBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_MOT_COUNT_BIT, MPU6050_DETECT_MOT_COUNT_LENGTH, buffer); - return buffer[0]; -} -/** Set Motion detection counter decrement configuration. - * @param decrement New decrement configuration value - * @see getMotionDetectionCounterDecrement() - * @see MPU6050_RA_MOT_DETECT_CTRL - * @see MPU6050_DETECT_MOT_COUNT_BIT - */ -void MPU6050::setMotionDetectionCounterDecrement(uint8_t decrement) -{ - I2Cdev::writeBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_MOT_COUNT_BIT, MPU6050_DETECT_MOT_COUNT_LENGTH, decrement); -} - -// USER_CTRL register - -/** Get FIFO enabled status. - * When this bit is set to 0, the FIFO buffer is disabled. The FIFO buffer - * cannot be written to or read from while disabled. The FIFO buffer's state - * does not change unless the MPU-60X0 is power cycled. - * @return Current FIFO enabled status - * @see MPU6050_RA_USER_CTRL - * @see MPU6050_USERCTRL_FIFO_EN_BIT - */ -bool MPU6050::getFIFOEnabled() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_EN_BIT, buffer); - return buffer[0]; -} -/** Set FIFO enabled status. - * @param enabled New FIFO enabled status - * @see getFIFOEnabled() - * @see MPU6050_RA_USER_CTRL - * @see MPU6050_USERCTRL_FIFO_EN_BIT - */ -void MPU6050::setFIFOEnabled(bool enabled) -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_EN_BIT, enabled); -} -/** Get I2C Master Mode enabled status. - * When this mode is enabled, the MPU-60X0 acts as the I2C Master to the - * external sensor slave devices on the auxiliary I2C bus. When this bit is - * cleared to 0, the auxiliary I2C bus lines (AUX_DA and AUX_CL) are logically - * driven by the primary I2C bus (SDA and SCL). This is a precondition to - * enabling Bypass Mode. For further information regarding Bypass Mode, please - * refer to Register 55. - * @return Current I2C Master Mode enabled status - * @see MPU6050_RA_USER_CTRL - * @see MPU6050_USERCTRL_I2C_MST_EN_BIT - */ -bool MPU6050::getI2CMasterModeEnabled() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_EN_BIT, buffer); - return buffer[0]; -} -/** Set I2C Master Mode enabled status. - * @param enabled New I2C Master Mode enabled status - * @see getI2CMasterModeEnabled() - * @see MPU6050_RA_USER_CTRL - * @see MPU6050_USERCTRL_I2C_MST_EN_BIT - */ -void MPU6050::setI2CMasterModeEnabled(bool enabled) -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_EN_BIT, enabled); -} -/** Switch from I2C to SPI mode (MPU-6000 only) - * If this is set, the primary SPI interface will be enabled in place of the - * disabled primary I2C interface. - */ -void MPU6050::switchSPIEnabled(bool enabled) -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_IF_DIS_BIT, enabled); -} -/** Reset the FIFO. - * This bit resets the FIFO buffer when set to 1 while FIFO_EN equals 0. This - * bit automatically clears to 0 after the reset has been triggered. - * @see MPU6050_RA_USER_CTRL - * @see MPU6050_USERCTRL_FIFO_RESET_BIT - */ -void MPU6050::resetFIFO() -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_RESET_BIT, true); -} -/** Reset the I2C Master. - * This bit resets the I2C Master when set to 1 while I2C_MST_EN equals 0. - * This bit automatically clears to 0 after the reset has been triggered. - * @see MPU6050_RA_USER_CTRL - * @see MPU6050_USERCTRL_I2C_MST_RESET_BIT - */ -void MPU6050::resetI2CMaster() -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_RESET_BIT, true); -} -/** Reset all sensor registers and signal paths. - * When set to 1, this bit resets the signal paths for all sensors (gyroscopes, - * accelerometers, and temperature sensor). This operation will also clear the - * sensor registers. This bit automatically clears to 0 after the reset has been - * triggered. - * - * When resetting only the signal path (and not the sensor registers), please - * use Register 104, SIGNAL_PATH_RESET. - * - * @see MPU6050_RA_USER_CTRL - * @see MPU6050_USERCTRL_SIG_COND_RESET_BIT - */ -void MPU6050::resetSensors() -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_SIG_COND_RESET_BIT, true); -} - -// PWR_MGMT_1 register - -/** Trigger a full device reset. - * A small delay of ~50ms may be desirable after triggering a reset. - * @see MPU6050_RA_PWR_MGMT_1 - * @see MPU6050_PWR1_DEVICE_RESET_BIT - */ -void MPU6050::reset() -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_DEVICE_RESET_BIT, true); -} -/** Get sleep mode status. - * Setting the SLEEP bit in the register puts the device into very low power - * sleep mode. In this mode, only the serial interface and internal registers - * remain active, allowing for a very low standby current. Clearing this bit - * puts the device back into normal mode. To save power, the individual standby - * selections for each of the gyros should be used if any gyro axis is not used - * by the application. - * @return Current sleep mode enabled status - * @see MPU6050_RA_PWR_MGMT_1 - * @see MPU6050_PWR1_SLEEP_BIT - */ -bool MPU6050::getSleepEnabled() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, buffer); - return buffer[0]; -} -/** Set sleep mode status. - * @param enabled New sleep mode enabled status - * @see getSleepEnabled() - * @see MPU6050_RA_PWR_MGMT_1 - * @see MPU6050_PWR1_SLEEP_BIT - */ -void MPU6050::setSleepEnabled(bool enabled) -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, enabled); -} -/** Get wake cycle enabled status. - * When this bit is set to 1 and SLEEP is disabled, the MPU-60X0 will cycle - * between sleep mode and waking up to take a single sample of data from active - * sensors at a rate determined by LP_WAKE_CTRL (register 108). - * @return Current sleep mode enabled status - * @see MPU6050_RA_PWR_MGMT_1 - * @see MPU6050_PWR1_CYCLE_BIT - */ -bool MPU6050::getWakeCycleEnabled() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CYCLE_BIT, buffer); - return buffer[0]; -} -/** Set wake cycle enabled status. - * @param enabled New sleep mode enabled status - * @see getWakeCycleEnabled() - * @see MPU6050_RA_PWR_MGMT_1 - * @see MPU6050_PWR1_CYCLE_BIT - */ -void MPU6050::setWakeCycleEnabled(bool enabled) -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CYCLE_BIT, enabled); -} -/** Get temperature sensor enabled status. - * Control the usage of the internal temperature sensor. - * - * Note: this register stores the *disabled* value, but for consistency with the - * rest of the code, the function is named and used with standard true/false - * values to indicate whether the sensor is enabled or disabled, respectively. - * - * @return Current temperature sensor enabled status - * @see MPU6050_RA_PWR_MGMT_1 - * @see MPU6050_PWR1_TEMP_DIS_BIT - */ -bool MPU6050::getTempSensorEnabled() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_TEMP_DIS_BIT, buffer); - return buffer[0] == 0; // 1 is actually disabled here -} -/** Set temperature sensor enabled status. - * Note: this register stores the *disabled* value, but for consistency with the - * rest of the code, the function is named and used with standard true/false - * values to indicate whether the sensor is enabled or disabled, respectively. - * - * @param enabled New temperature sensor enabled status - * @see getTempSensorEnabled() - * @see MPU6050_RA_PWR_MGMT_1 - * @see MPU6050_PWR1_TEMP_DIS_BIT - */ -void MPU6050::setTempSensorEnabled(bool enabled) -{ - // 1 is actually disabled here - I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_TEMP_DIS_BIT, !enabled); -} -/** Get clock source setting. - * @return Current clock source setting - * @see MPU6050_RA_PWR_MGMT_1 - * @see MPU6050_PWR1_CLKSEL_BIT - * @see MPU6050_PWR1_CLKSEL_LENGTH - */ -uint8_t MPU6050::getClockSource() -{ - I2Cdev::readBits(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, buffer); - return buffer[0]; -} -/** Set clock source setting. - * An internal 8MHz oscillator, gyroscope based clock, or external sources can - * be selected as the MPU-60X0 clock source. When the internal 8 MHz oscillator - * or an external source is chosen as the clock source, the MPU-60X0 can operate - * in low power modes with the gyroscopes disabled. - * - * Upon power up, the MPU-60X0 clock source defaults to the internal oscillator. - * However, it is highly recommended that the device be configured to use one of - * the gyroscopes (or an external clock source) as the clock reference for - * improved stability. The clock source can be selected according to the following table: - * - *
- * CLK_SEL | Clock Source
- * --------+--------------------------------------
- * 0       | Internal oscillator
- * 1       | PLL with X Gyro reference
- * 2       | PLL with Y Gyro reference
- * 3       | PLL with Z Gyro reference
- * 4       | PLL with external 32.768kHz reference
- * 5       | PLL with external 19.2MHz reference
- * 6       | Reserved
- * 7       | Stops the clock and keeps the timing generator in reset
- * 
- * - * @param source New clock source setting - * @see getClockSource() - * @see MPU6050_RA_PWR_MGMT_1 - * @see MPU6050_PWR1_CLKSEL_BIT - * @see MPU6050_PWR1_CLKSEL_LENGTH - */ -void MPU6050::setClockSource(uint8_t source) -{ - I2Cdev::writeBits(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, source); -} - -// PWR_MGMT_2 register - -/** Get wake frequency in Accel-Only Low Power Mode. - * The MPU-60X0 can be put into Accerlerometer Only Low Power Mode by setting - * PWRSEL to 1 in the Power Management 1 register (Register 107). In this mode, - * the device will power off all devices except for the primary I2C interface, - * waking only the accelerometer at fixed intervals to take a single - * measurement. The frequency of wake-ups can be configured with LP_WAKE_CTRL - * as shown below: - * - *
- * LP_WAKE_CTRL | Wake-up Frequency
- * -------------+------------------
- * 0            | 1.25 Hz
- * 1            | 2.5 Hz
- * 2            | 5 Hz
- * 3            | 10 Hz
- * 
- * - * For further information regarding the MPU-60X0's power modes, please refer to - * Register 107. - * - * @return Current wake frequency - * @see MPU6050_RA_PWR_MGMT_2 - */ -uint8_t MPU6050::getWakeFrequency() -{ - I2Cdev::readBits(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_LP_WAKE_CTRL_BIT, MPU6050_PWR2_LP_WAKE_CTRL_LENGTH, buffer); - return buffer[0]; -} -/** Set wake frequency in Accel-Only Low Power Mode. - * @param frequency New wake frequency - * @see MPU6050_RA_PWR_MGMT_2 - */ -void MPU6050::setWakeFrequency(uint8_t frequency) -{ - I2Cdev::writeBits(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_LP_WAKE_CTRL_BIT, MPU6050_PWR2_LP_WAKE_CTRL_LENGTH, frequency); -} - -/** Get X-axis accelerometer standby enabled status. - * If enabled, the X-axis will not gather or report data (or use power). - * @return Current X-axis standby enabled status - * @see MPU6050_RA_PWR_MGMT_2 - * @see MPU6050_PWR2_STBY_XA_BIT - */ -bool MPU6050::getStandbyXAccelEnabled() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XA_BIT, buffer); - return buffer[0]; -} -/** Set X-axis accelerometer standby enabled status. - * @param New X-axis standby enabled status - * @see getStandbyXAccelEnabled() - * @see MPU6050_RA_PWR_MGMT_2 - * @see MPU6050_PWR2_STBY_XA_BIT - */ -void MPU6050::setStandbyXAccelEnabled(bool enabled) -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XA_BIT, enabled); -} -/** Get Y-axis accelerometer standby enabled status. - * If enabled, the Y-axis will not gather or report data (or use power). - * @return Current Y-axis standby enabled status - * @see MPU6050_RA_PWR_MGMT_2 - * @see MPU6050_PWR2_STBY_YA_BIT - */ -bool MPU6050::getStandbyYAccelEnabled() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YA_BIT, buffer); - return buffer[0]; -} -/** Set Y-axis accelerometer standby enabled status. - * @param New Y-axis standby enabled status - * @see getStandbyYAccelEnabled() - * @see MPU6050_RA_PWR_MGMT_2 - * @see MPU6050_PWR2_STBY_YA_BIT - */ -void MPU6050::setStandbyYAccelEnabled(bool enabled) -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YA_BIT, enabled); -} -/** Get Z-axis accelerometer standby enabled status. - * If enabled, the Z-axis will not gather or report data (or use power). - * @return Current Z-axis standby enabled status - * @see MPU6050_RA_PWR_MGMT_2 - * @see MPU6050_PWR2_STBY_ZA_BIT - */ -bool MPU6050::getStandbyZAccelEnabled() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZA_BIT, buffer); - return buffer[0]; -} -/** Set Z-axis accelerometer standby enabled status. - * @param New Z-axis standby enabled status - * @see getStandbyZAccelEnabled() - * @see MPU6050_RA_PWR_MGMT_2 - * @see MPU6050_PWR2_STBY_ZA_BIT - */ -void MPU6050::setStandbyZAccelEnabled(bool enabled) -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZA_BIT, enabled); -} -/** Get X-axis gyroscope standby enabled status. - * If enabled, the X-axis will not gather or report data (or use power). - * @return Current X-axis standby enabled status - * @see MPU6050_RA_PWR_MGMT_2 - * @see MPU6050_PWR2_STBY_XG_BIT - */ -bool MPU6050::getStandbyXGyroEnabled() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XG_BIT, buffer); - return buffer[0]; -} -/** Set X-axis gyroscope standby enabled status. - * @param New X-axis standby enabled status - * @see getStandbyXGyroEnabled() - * @see MPU6050_RA_PWR_MGMT_2 - * @see MPU6050_PWR2_STBY_XG_BIT - */ -void MPU6050::setStandbyXGyroEnabled(bool enabled) -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XG_BIT, enabled); -} -/** Get Y-axis gyroscope standby enabled status. - * If enabled, the Y-axis will not gather or report data (or use power). - * @return Current Y-axis standby enabled status - * @see MPU6050_RA_PWR_MGMT_2 - * @see MPU6050_PWR2_STBY_YG_BIT - */ -bool MPU6050::getStandbyYGyroEnabled() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YG_BIT, buffer); - return buffer[0]; -} -/** Set Y-axis gyroscope standby enabled status. - * @param New Y-axis standby enabled status - * @see getStandbyYGyroEnabled() - * @see MPU6050_RA_PWR_MGMT_2 - * @see MPU6050_PWR2_STBY_YG_BIT - */ -void MPU6050::setStandbyYGyroEnabled(bool enabled) -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YG_BIT, enabled); -} -/** Get Z-axis gyroscope standby enabled status. - * If enabled, the Z-axis will not gather or report data (or use power). - * @return Current Z-axis standby enabled status - * @see MPU6050_RA_PWR_MGMT_2 - * @see MPU6050_PWR2_STBY_ZG_BIT - */ -bool MPU6050::getStandbyZGyroEnabled() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZG_BIT, buffer); - return buffer[0]; -} -/** Set Z-axis gyroscope standby enabled status. - * @param New Z-axis standby enabled status - * @see getStandbyZGyroEnabled() - * @see MPU6050_RA_PWR_MGMT_2 - * @see MPU6050_PWR2_STBY_ZG_BIT - */ -void MPU6050::setStandbyZGyroEnabled(bool enabled) -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZG_BIT, enabled); -} - -// FIFO_COUNT* registers - -/** Get current FIFO buffer size. - * This value indicates the number of bytes stored in the FIFO buffer. This - * number is in turn the number of bytes that can be read from the FIFO buffer - * and it is directly proportional to the number of samples available given the - * set of sensor data bound to be stored in the FIFO (register 35 and 36). - * @return Current FIFO buffer size - */ -uint16_t MPU6050::getFIFOCount() -{ - I2Cdev::readBytes(devAddr, MPU6050_RA_FIFO_COUNTH, 2, buffer); - return (((uint16_t)buffer[0]) << 8) | buffer[1]; -} - -// FIFO_R_W register - -/** Get byte from FIFO buffer. - * This register is used to read and write data from the FIFO buffer. Data is - * written to the FIFO in order of register number (from lowest to highest). If - * all the FIFO enable flags (see below) are enabled and all External Sensor - * Data registers (Registers 73 to 96) are associated with a Slave device, the - * contents of registers 59 through 96 will be written in order at the Sample - * Rate. - * - * The contents of the sensor data registers (Registers 59 to 96) are written - * into the FIFO buffer when their corresponding FIFO enable flags are set to 1 - * in FIFO_EN (Register 35). An additional flag for the sensor data registers - * associated with I2C Slave 3 can be found in I2C_MST_CTRL (Register 36). - * - * If the FIFO buffer has overflowed, the status bit FIFO_OFLOW_INT is - * automatically set to 1. This bit is located in INT_STATUS (Register 58). - * When the FIFO buffer has overflowed, the oldest data will be lost and new - * data will be written to the FIFO. - * - * If the FIFO buffer is empty, reading this register will return the last byte - * that was previously read from the FIFO until new data is available. The user - * should check FIFO_COUNT to ensure that the FIFO buffer is not read when - * empty. - * - * @return Byte from FIFO buffer - */ -uint8_t MPU6050::getFIFOByte() -{ - I2Cdev::readByte(devAddr, MPU6050_RA_FIFO_R_W, buffer); - return buffer[0]; -} -void MPU6050::getFIFOBytes(uint8_t *data, uint8_t length) -{ - if (length > 0) - { - I2Cdev::readBytes(devAddr, MPU6050_RA_FIFO_R_W, length, data); - } - else - { - *data = 0; - } -} -/** Write byte to FIFO buffer. - * @see getFIFOByte() - * @see MPU6050_RA_FIFO_R_W - */ -void MPU6050::setFIFOByte(uint8_t data) -{ - I2Cdev::writeByte(devAddr, MPU6050_RA_FIFO_R_W, data); -} - -// WHO_AM_I register - -/** Get Device ID. - * This register is used to verify the identity of the device (0b110100, 0x34). - * @return Device ID (6 bits only! should be 0x34) - * @see MPU6050_RA_WHO_AM_I - * @see MPU6050_WHO_AM_I_BIT - * @see MPU6050_WHO_AM_I_LENGTH - */ -uint8_t MPU6050::getDeviceID() -{ - I2Cdev::readBits(devAddr, MPU6050_RA_WHO_AM_I, MPU6050_WHO_AM_I_BIT, MPU6050_WHO_AM_I_LENGTH, buffer); - return buffer[0]; -} -/** Set Device ID. - * Write a new ID into the WHO_AM_I register (no idea why this should ever be - * necessary though). - * @param id New device ID to set. - * @see getDeviceID() - * @see MPU6050_RA_WHO_AM_I - * @see MPU6050_WHO_AM_I_BIT - * @see MPU6050_WHO_AM_I_LENGTH - */ -void MPU6050::setDeviceID(uint8_t id) -{ - I2Cdev::writeBits(devAddr, MPU6050_RA_WHO_AM_I, MPU6050_WHO_AM_I_BIT, MPU6050_WHO_AM_I_LENGTH, id); -} - -// ======== UNDOCUMENTED/DMP REGISTERS/METHODS ======== - -// XG_OFFS_TC register - -uint8_t MPU6050::getOTPBankValid() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OTP_BNK_VLD_BIT, buffer); - return buffer[0]; -} -void MPU6050::setOTPBankValid(bool enabled) -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OTP_BNK_VLD_BIT, enabled); -} -int8_t MPU6050::getXGyroOffsetTC() -{ - I2Cdev::readBits(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, buffer); - return buffer[0]; -} -void MPU6050::setXGyroOffsetTC(int8_t offset) -{ - I2Cdev::writeBits(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset); -} - -// YG_OFFS_TC register - -int8_t MPU6050::getYGyroOffsetTC() -{ - I2Cdev::readBits(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, buffer); - return buffer[0]; -} -void MPU6050::setYGyroOffsetTC(int8_t offset) -{ - I2Cdev::writeBits(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset); -} - -// ZG_OFFS_TC register - -int8_t MPU6050::getZGyroOffsetTC() -{ - I2Cdev::readBits(devAddr, MPU6050_RA_ZG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, buffer); - return buffer[0]; -} -void MPU6050::setZGyroOffsetTC(int8_t offset) -{ - I2Cdev::writeBits(devAddr, MPU6050_RA_ZG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset); -} - -// X_FINE_GAIN register - -int8_t MPU6050::getXFineGain() -{ - I2Cdev::readByte(devAddr, MPU6050_RA_X_FINE_GAIN, buffer); - return buffer[0]; -} -void MPU6050::setXFineGain(int8_t gain) -{ - I2Cdev::writeByte(devAddr, MPU6050_RA_X_FINE_GAIN, gain); -} - -// Y_FINE_GAIN register - -int8_t MPU6050::getYFineGain() -{ - I2Cdev::readByte(devAddr, MPU6050_RA_Y_FINE_GAIN, buffer); - return buffer[0]; -} -void MPU6050::setYFineGain(int8_t gain) -{ - I2Cdev::writeByte(devAddr, MPU6050_RA_Y_FINE_GAIN, gain); -} - -// Z_FINE_GAIN register - -int8_t MPU6050::getZFineGain() -{ - I2Cdev::readByte(devAddr, MPU6050_RA_Z_FINE_GAIN, buffer); - return buffer[0]; -} -void MPU6050::setZFineGain(int8_t gain) -{ - I2Cdev::writeByte(devAddr, MPU6050_RA_Z_FINE_GAIN, gain); -} - -// XA_OFFS_* registers - -int16_t MPU6050::getXAccelOffset() -{ - I2Cdev::readBytes(devAddr, MPU6050_RA_XA_OFFS_H, 2, buffer); - return (((int16_t)buffer[0]) << 8) | buffer[1]; -} -void MPU6050::setXAccelOffset(int16_t offset) -{ - I2Cdev::writeWord(devAddr, MPU6050_RA_XA_OFFS_H, offset); -} - -// YA_OFFS_* register - -int16_t MPU6050::getYAccelOffset() -{ - I2Cdev::readBytes(devAddr, MPU6050_RA_YA_OFFS_H, 2, buffer); - return (((int16_t)buffer[0]) << 8) | buffer[1]; -} -void MPU6050::setYAccelOffset(int16_t offset) -{ - I2Cdev::writeWord(devAddr, MPU6050_RA_YA_OFFS_H, offset); -} - -// ZA_OFFS_* register - -int16_t MPU6050::getZAccelOffset() -{ - I2Cdev::readBytes(devAddr, MPU6050_RA_ZA_OFFS_H, 2, buffer); - return (((int16_t)buffer[0]) << 8) | buffer[1]; -} -void MPU6050::setZAccelOffset(int16_t offset) -{ - I2Cdev::writeWord(devAddr, MPU6050_RA_ZA_OFFS_H, offset); -} - -// XG_OFFS_USR* registers - -int16_t MPU6050::getXGyroOffset() -{ - I2Cdev::readBytes(devAddr, MPU6050_RA_XG_OFFS_USRH, 2, buffer); - return (((int16_t)buffer[0]) << 8) | buffer[1]; -} -void MPU6050::setXGyroOffset(int16_t offset) -{ - I2Cdev::writeWord(devAddr, MPU6050_RA_XG_OFFS_USRH, offset); -} - -// YG_OFFS_USR* register - -int16_t MPU6050::getYGyroOffset() -{ - I2Cdev::readBytes(devAddr, MPU6050_RA_YG_OFFS_USRH, 2, buffer); - return (((int16_t)buffer[0]) << 8) | buffer[1]; -} -void MPU6050::setYGyroOffset(int16_t offset) -{ - I2Cdev::writeWord(devAddr, MPU6050_RA_YG_OFFS_USRH, offset); -} - -// ZG_OFFS_USR* register - -int16_t MPU6050::getZGyroOffset() -{ - I2Cdev::readBytes(devAddr, MPU6050_RA_ZG_OFFS_USRH, 2, buffer); - return (((int16_t)buffer[0]) << 8) | buffer[1]; -} -void MPU6050::setZGyroOffset(int16_t offset) -{ - I2Cdev::writeWord(devAddr, MPU6050_RA_ZG_OFFS_USRH, offset); -} - -// INT_ENABLE register (DMP functions) - -bool MPU6050::getIntPLLReadyEnabled() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, buffer); - return buffer[0]; -} -void MPU6050::setIntPLLReadyEnabled(bool enabled) -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, enabled); -} -bool MPU6050::getIntDMPEnabled() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DMP_INT_BIT, buffer); - return buffer[0]; -} -void MPU6050::setIntDMPEnabled(bool enabled) -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DMP_INT_BIT, enabled); -} - -// DMP_INT_STATUS - -bool MPU6050::getDMPInt5Status() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_5_BIT, buffer); - return buffer[0]; -} -bool MPU6050::getDMPInt4Status() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_4_BIT, buffer); - return buffer[0]; -} -bool MPU6050::getDMPInt3Status() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_3_BIT, buffer); - return buffer[0]; -} -bool MPU6050::getDMPInt2Status() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_2_BIT, buffer); - return buffer[0]; -} -bool MPU6050::getDMPInt1Status() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_1_BIT, buffer); - return buffer[0]; -} -bool MPU6050::getDMPInt0Status() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_0_BIT, buffer); - return buffer[0]; -} - -// INT_STATUS register (DMP functions) - -bool MPU6050::getIntPLLReadyStatus() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, buffer); - return buffer[0]; -} -bool MPU6050::getIntDMPStatus() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_DMP_INT_BIT, buffer); - return buffer[0]; -} - -// USER_CTRL register (DMP functions) - -bool MPU6050::getDMPEnabled() -{ - I2Cdev::readBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_EN_BIT, buffer); - return buffer[0]; -} -void MPU6050::setDMPEnabled(bool enabled) -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_EN_BIT, enabled); -} -void MPU6050::resetDMP() -{ - I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_RESET_BIT, true); -} - -// BANK_SEL register - -void MPU6050::setMemoryBank(uint8_t bank, bool prefetchEnabled, bool userBank) -{ - bank &= 0x1F; - if (userBank) - bank |= 0x20; - if (prefetchEnabled) - bank |= 0x40; - I2Cdev::writeByte(devAddr, MPU6050_RA_BANK_SEL, bank); -} - -// MEM_START_ADDR register - -void MPU6050::setMemoryStartAddress(uint8_t address) -{ - I2Cdev::writeByte(devAddr, MPU6050_RA_MEM_START_ADDR, address); -} - -// MEM_R_W register - -uint8_t MPU6050::readMemoryByte() -{ - I2Cdev::readByte(devAddr, MPU6050_RA_MEM_R_W, buffer); - return buffer[0]; -} -void MPU6050::writeMemoryByte(uint8_t data) -{ - I2Cdev::writeByte(devAddr, MPU6050_RA_MEM_R_W, data); -} -void MPU6050::readMemoryBlock(uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address) -{ - setMemoryBank(bank); - setMemoryStartAddress(address); - uint8_t chunkSize; - for (uint16_t i = 0; i < dataSize;) - { - // determine correct chunk size according to bank position and data size - chunkSize = MPU6050_DMP_MEMORY_CHUNK_SIZE; - - // make sure we don't go past the data size - if (i + chunkSize > dataSize) - chunkSize = dataSize - i; - - // make sure this chunk doesn't go past the bank boundary (256 bytes) - if (chunkSize > 256 - address) - chunkSize = 256 - address; - - // read the chunk of data as specified - I2Cdev::readBytes(devAddr, MPU6050_RA_MEM_R_W, chunkSize, data + i); - - // increase byte index by [chunkSize] - i += chunkSize; - - // uint8_t automatically wraps to 0 at 256 - address += chunkSize; - - // if we aren't done, update bank (if necessary) and address - if (i < dataSize) - { - if (address == 0) - bank++; - setMemoryBank(bank); - setMemoryStartAddress(address); - } - } -} -bool MPU6050::writeMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address, bool verify) -{ - setMemoryBank(bank); - setMemoryStartAddress(address); - uint8_t chunkSize; - uint8_t *verifyBuffer = 0; - uint8_t *progBuffer = 0; - uint16_t i; - uint8_t j; - if (verify) - verifyBuffer = (uint8_t *)malloc(MPU6050_DMP_MEMORY_CHUNK_SIZE); - - for (i = 0; i < dataSize;) - { - // determine correct chunk size according to bank position and data size - chunkSize = MPU6050_DMP_MEMORY_CHUNK_SIZE; - - // make sure we don't go past the data size - if (i + chunkSize > dataSize) - chunkSize = dataSize - i; - - // make sure this chunk doesn't go past the bank boundary (256 bytes) - if (chunkSize > 256 - address) - chunkSize = 256 - address; - - // write the chunk of data as specified - progBuffer = (uint8_t *)data + i; - - I2Cdev::writeBytes(devAddr, MPU6050_RA_MEM_R_W, chunkSize, progBuffer); - - // verify data if needed - if (verify && verifyBuffer) - { - setMemoryBank(bank); - setMemoryStartAddress(address); - I2Cdev::readBytes(devAddr, MPU6050_RA_MEM_R_W, chunkSize, verifyBuffer); - if (memcmp(progBuffer, verifyBuffer, chunkSize) != 0) - { - /*Serial.print("Block write verification error, bank "); - Serial.print(bank, DEC); - Serial.print(", address "); - Serial.print(address, DEC); - Serial.print("!\nExpected:"); - for (j = 0; j < chunkSize; j++) { - Serial.print(" 0x"); - if (progBuffer[j] < 16) Serial.print("0"); - Serial.print(progBuffer[j], HEX); - } - Serial.print("\nReceived:"); - for (uint8_t j = 0; j < chunkSize; j++) { - Serial.print(" 0x"); - if (verifyBuffer[i + j] < 16) Serial.print("0"); - Serial.print(verifyBuffer[i + j], HEX); - } - Serial.print("\n");*/ - free(verifyBuffer); - - return false; // uh oh. - } - } - - // increase byte index by [chunkSize] - i += chunkSize; - - // uint8_t automatically wraps to 0 at 256 - address += chunkSize; - - // if we aren't done, update bank (if necessary) and address - if (i < dataSize) - { - if (address == 0) - bank++; - setMemoryBank(bank); - setMemoryStartAddress(address); - } - } - if (verify) - free(verifyBuffer); - - return true; -} - -bool MPU6050::writeDMPConfigurationSet(const uint8_t *data, uint16_t dataSize) -{ - uint8_t *progBuffer = 0; - uint8_t success, special; - uint16_t i, j; - - // config set data is a long string of blocks with the following structure: - // [bank] [offset] [length] [byte[0], byte[1], ..., byte[length]] - uint8_t bank, offset, length; - for (i = 0; i < dataSize;) - { - - bank = data[i++]; - offset = data[i++]; - length = data[i++]; - - // write data or perform special action - if (length > 0) - { - // regular block of data to write - /*Serial.print("Writing config block to bank "); - Serial.print(bank); - Serial.print(", offset "); - Serial.print(offset); - Serial.print(", length="); - Serial.println(length);*/ - - progBuffer = (uint8_t *)data + i; - - success = writeMemoryBlock(progBuffer, length, bank, offset, true); - i += length; - } - else - { - // special instruction - // NOTE: this kind of behavior (what and when to do certain things) - // is totally undocumented. This code is in here based on observed - // behavior only, and exactly why (or even whether) it has to be here - // is anybody's guess for now. - - special = data[i++]; - - /*Serial.print("Special command code "); - Serial.print(special, HEX); - Serial.println(" found...");*/ - if (special == 0x01) - { - // enable DMP-related interrupts - - //setIntZeroMotionEnabled(true); - //setIntFIFOBufferOverflowEnabled(true); - //setIntDMPEnabled(true); - I2Cdev::writeByte(devAddr, MPU6050_RA_INT_ENABLE, 0x32); // single operation - - success = true; - } - else - { - // unknown special command - success = false; - } - } - - if (!success) - { - - return false; // uh oh - } - } - - return true; -} - -// DMP_CFG_1 register - -uint8_t MPU6050::getDMPConfig1() -{ - I2Cdev::readByte(devAddr, MPU6050_RA_DMP_CFG_1, buffer); - return buffer[0]; -} -void MPU6050::setDMPConfig1(uint8_t config) -{ - I2Cdev::writeByte(devAddr, MPU6050_RA_DMP_CFG_1, config); -} - -// DMP_CFG_2 register - -uint8_t MPU6050::getDMPConfig2() -{ - I2Cdev::readByte(devAddr, MPU6050_RA_DMP_CFG_2, buffer); - return buffer[0]; -} -void MPU6050::setDMPConfig2(uint8_t config) -{ - I2Cdev::writeByte(devAddr, MPU6050_RA_DMP_CFG_2, config); -} diff --git a/BeagleBoneBlack/MPU6050/MPU6050.h b/BeagleBoneBlack/MPU6050/MPU6050.h deleted file mode 100644 index 935494f5..00000000 --- a/BeagleBoneBlack/MPU6050/MPU6050.h +++ /dev/null @@ -1,1018 +0,0 @@ -// I2Cdev library collection - MPU6050 I2C device class -// Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00) -// 10/3/2011 by Jeff Rowberg -// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib -// -// Changelog: -// ... - ongoing debug release - -// NOTE: THIS IS ONLY A PARIAL RELEASE. THIS DEVICE CLASS IS CURRENTLY UNDERGOING ACTIVE -// DEVELOPMENT AND IS STILL MISSING SOME IMPORTANT FEATURES. PLEASE KEEP THIS IN MIND IF -// YOU DECIDE TO USE THIS PARTICULAR CODE FOR ANYTHING. - -/* ============================================ -I2Cdev device library code is placed under the MIT license -Copyright (c) 2012 Jeff Rowberg -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -=============================================== -*/ - -#ifndef _MPU6050_H_ -#define _MPU6050_H_ - -#include "I2Cdev.h" - -#define MPU6050_ADDRESS_AD0_LOW 0x68 // address pin low (GND), default for InvenSense evaluation board -#define MPU6050_ADDRESS_AD0_HIGH 0x69 // address pin high (VCC) -#define MPU6050_DEFAULT_ADDRESS MPU6050_ADDRESS_AD0_LOW - -#define MPU6050_RA_XG_OFFS_TC 0x00 //[7] PWR_MODE, [6:1] XG_OFFS_TC, [0] OTP_BNK_VLD -#define MPU6050_RA_YG_OFFS_TC 0x01 //[7] PWR_MODE, [6:1] YG_OFFS_TC, [0] OTP_BNK_VLD -#define MPU6050_RA_ZG_OFFS_TC 0x02 //[7] PWR_MODE, [6:1] ZG_OFFS_TC, [0] OTP_BNK_VLD -#define MPU6050_RA_X_FINE_GAIN 0x03 //[7:0] X_FINE_GAIN -#define MPU6050_RA_Y_FINE_GAIN 0x04 //[7:0] Y_FINE_GAIN -#define MPU6050_RA_Z_FINE_GAIN 0x05 //[7:0] Z_FINE_GAIN -#define MPU6050_RA_XA_OFFS_H 0x06 //[15:0] XA_OFFS -#define MPU6050_RA_XA_OFFS_L_TC 0x07 -#define MPU6050_RA_YA_OFFS_H 0x08 //[15:0] YA_OFFS -#define MPU6050_RA_YA_OFFS_L_TC 0x09 -#define MPU6050_RA_ZA_OFFS_H 0x0A //[15:0] ZA_OFFS -#define MPU6050_RA_ZA_OFFS_L_TC 0x0B -#define MPU6050_RA_SELF_TEST_X 0x0D //[7:5] XA_TEST[4-2], [4:0] XG_TEST[4-0] -#define MPU6050_RA_SELF_TEST_Y 0x0E //[7:5] YA_TEST[4-2], [4:0] YG_TEST[4-0] -#define MPU6050_RA_SELF_TEST_Z 0x0F //[7:5] ZA_TEST[4-2], [4:0] ZG_TEST[4-0] -#define MPU6050_RA_SELF_TEST_A 0x10 //[5:4] XA_TEST[1-0], [3:2] YA_TEST[1-0], [1:0] ZA_TEST[1-0] -#define MPU6050_RA_XG_OFFS_USRH 0x13 //[15:0] XG_OFFS_USR -#define MPU6050_RA_XG_OFFS_USRL 0x14 -#define MPU6050_RA_YG_OFFS_USRH 0x15 //[15:0] YG_OFFS_USR -#define MPU6050_RA_YG_OFFS_USRL 0x16 -#define MPU6050_RA_ZG_OFFS_USRH 0x17 //[15:0] ZG_OFFS_USR -#define MPU6050_RA_ZG_OFFS_USRL 0x18 -#define MPU6050_RA_SMPLRT_DIV 0x19 -#define MPU6050_RA_CONFIG 0x1A -#define MPU6050_RA_GYRO_CONFIG 0x1B -#define MPU6050_RA_ACCEL_CONFIG 0x1C -#define MPU6050_RA_FF_THR 0x1D -#define MPU6050_RA_FF_DUR 0x1E -#define MPU6050_RA_MOT_THR 0x1F -#define MPU6050_RA_MOT_DUR 0x20 -#define MPU6050_RA_ZRMOT_THR 0x21 -#define MPU6050_RA_ZRMOT_DUR 0x22 -#define MPU6050_RA_FIFO_EN 0x23 -#define MPU6050_RA_I2C_MST_CTRL 0x24 -#define MPU6050_RA_I2C_SLV0_ADDR 0x25 -#define MPU6050_RA_I2C_SLV0_REG 0x26 -#define MPU6050_RA_I2C_SLV0_CTRL 0x27 -#define MPU6050_RA_I2C_SLV1_ADDR 0x28 -#define MPU6050_RA_I2C_SLV1_REG 0x29 -#define MPU6050_RA_I2C_SLV1_CTRL 0x2A -#define MPU6050_RA_I2C_SLV2_ADDR 0x2B -#define MPU6050_RA_I2C_SLV2_REG 0x2C -#define MPU6050_RA_I2C_SLV2_CTRL 0x2D -#define MPU6050_RA_I2C_SLV3_ADDR 0x2E -#define MPU6050_RA_I2C_SLV3_REG 0x2F -#define MPU6050_RA_I2C_SLV3_CTRL 0x30 -#define MPU6050_RA_I2C_SLV4_ADDR 0x31 -#define MPU6050_RA_I2C_SLV4_REG 0x32 -#define MPU6050_RA_I2C_SLV4_DO 0x33 -#define MPU6050_RA_I2C_SLV4_CTRL 0x34 -#define MPU6050_RA_I2C_SLV4_DI 0x35 -#define MPU6050_RA_I2C_MST_STATUS 0x36 -#define MPU6050_RA_INT_PIN_CFG 0x37 -#define MPU6050_RA_INT_ENABLE 0x38 -#define MPU6050_RA_DMP_INT_STATUS 0x39 -#define MPU6050_RA_INT_STATUS 0x3A -#define MPU6050_RA_ACCEL_XOUT_H 0x3B -#define MPU6050_RA_ACCEL_XOUT_L 0x3C -#define MPU6050_RA_ACCEL_YOUT_H 0x3D -#define MPU6050_RA_ACCEL_YOUT_L 0x3E -#define MPU6050_RA_ACCEL_ZOUT_H 0x3F -#define MPU6050_RA_ACCEL_ZOUT_L 0x40 -#define MPU6050_RA_TEMP_OUT_H 0x41 -#define MPU6050_RA_TEMP_OUT_L 0x42 -#define MPU6050_RA_GYRO_XOUT_H 0x43 -#define MPU6050_RA_GYRO_XOUT_L 0x44 -#define MPU6050_RA_GYRO_YOUT_H 0x45 -#define MPU6050_RA_GYRO_YOUT_L 0x46 -#define MPU6050_RA_GYRO_ZOUT_H 0x47 -#define MPU6050_RA_GYRO_ZOUT_L 0x48 -#define MPU6050_RA_EXT_SENS_DATA_00 0x49 -#define MPU6050_RA_EXT_SENS_DATA_01 0x4A -#define MPU6050_RA_EXT_SENS_DATA_02 0x4B -#define MPU6050_RA_EXT_SENS_DATA_03 0x4C -#define MPU6050_RA_EXT_SENS_DATA_04 0x4D -#define MPU6050_RA_EXT_SENS_DATA_05 0x4E -#define MPU6050_RA_EXT_SENS_DATA_06 0x4F -#define MPU6050_RA_EXT_SENS_DATA_07 0x50 -#define MPU6050_RA_EXT_SENS_DATA_08 0x51 -#define MPU6050_RA_EXT_SENS_DATA_09 0x52 -#define MPU6050_RA_EXT_SENS_DATA_10 0x53 -#define MPU6050_RA_EXT_SENS_DATA_11 0x54 -#define MPU6050_RA_EXT_SENS_DATA_12 0x55 -#define MPU6050_RA_EXT_SENS_DATA_13 0x56 -#define MPU6050_RA_EXT_SENS_DATA_14 0x57 -#define MPU6050_RA_EXT_SENS_DATA_15 0x58 -#define MPU6050_RA_EXT_SENS_DATA_16 0x59 -#define MPU6050_RA_EXT_SENS_DATA_17 0x5A -#define MPU6050_RA_EXT_SENS_DATA_18 0x5B -#define MPU6050_RA_EXT_SENS_DATA_19 0x5C -#define MPU6050_RA_EXT_SENS_DATA_20 0x5D -#define MPU6050_RA_EXT_SENS_DATA_21 0x5E -#define MPU6050_RA_EXT_SENS_DATA_22 0x5F -#define MPU6050_RA_EXT_SENS_DATA_23 0x60 -#define MPU6050_RA_MOT_DETECT_STATUS 0x61 -#define MPU6050_RA_I2C_SLV0_DO 0x63 -#define MPU6050_RA_I2C_SLV1_DO 0x64 -#define MPU6050_RA_I2C_SLV2_DO 0x65 -#define MPU6050_RA_I2C_SLV3_DO 0x66 -#define MPU6050_RA_I2C_MST_DELAY_CTRL 0x67 -#define MPU6050_RA_SIGNAL_PATH_RESET 0x68 -#define MPU6050_RA_MOT_DETECT_CTRL 0x69 -#define MPU6050_RA_USER_CTRL 0x6A -#define MPU6050_RA_PWR_MGMT_1 0x6B -#define MPU6050_RA_PWR_MGMT_2 0x6C -#define MPU6050_RA_BANK_SEL 0x6D -#define MPU6050_RA_MEM_START_ADDR 0x6E -#define MPU6050_RA_MEM_R_W 0x6F -#define MPU6050_RA_DMP_CFG_1 0x70 -#define MPU6050_RA_DMP_CFG_2 0x71 -#define MPU6050_RA_FIFO_COUNTH 0x72 -#define MPU6050_RA_FIFO_COUNTL 0x73 -#define MPU6050_RA_FIFO_R_W 0x74 -#define MPU6050_RA_WHO_AM_I 0x75 - -#define MPU6050_SELF_TEST_XA_1_BIT 0x07 -#define MPU6050_SELF_TEST_XA_1_LENGTH 0x03 -#define MPU6050_SELF_TEST_XA_2_BIT 0x05 -#define MPU6050_SELF_TEST_XA_2_LENGTH 0x02 -#define MPU6050_SELF_TEST_YA_1_BIT 0x07 -#define MPU6050_SELF_TEST_YA_1_LENGTH 0x03 -#define MPU6050_SELF_TEST_YA_2_BIT 0x03 -#define MPU6050_SELF_TEST_YA_2_LENGTH 0x02 -#define MPU6050_SELF_TEST_ZA_1_BIT 0x07 -#define MPU6050_SELF_TEST_ZA_1_LENGTH 0x03 -#define MPU6050_SELF_TEST_ZA_2_BIT 0x01 -#define MPU6050_SELF_TEST_ZA_2_LENGTH 0x02 - -#define MPU6050_SELF_TEST_XG_1_BIT 0x04 -#define MPU6050_SELF_TEST_XG_1_LENGTH 0x05 -#define MPU6050_SELF_TEST_YG_1_BIT 0x04 -#define MPU6050_SELF_TEST_YG_1_LENGTH 0x05 -#define MPU6050_SELF_TEST_ZG_1_BIT 0x04 -#define MPU6050_SELF_TEST_ZG_1_LENGTH 0x05 - -#define MPU6050_TC_PWR_MODE_BIT 7 -#define MPU6050_TC_OFFSET_BIT 6 -#define MPU6050_TC_OFFSET_LENGTH 6 -#define MPU6050_TC_OTP_BNK_VLD_BIT 0 - -#define MPU6050_VDDIO_LEVEL_VLOGIC 0 -#define MPU6050_VDDIO_LEVEL_VDD 1 - -#define MPU6050_CFG_EXT_SYNC_SET_BIT 5 -#define MPU6050_CFG_EXT_SYNC_SET_LENGTH 3 -#define MPU6050_CFG_DLPF_CFG_BIT 2 -#define MPU6050_CFG_DLPF_CFG_LENGTH 3 - -#define MPU6050_EXT_SYNC_DISABLED 0x0 -#define MPU6050_EXT_SYNC_TEMP_OUT_L 0x1 -#define MPU6050_EXT_SYNC_GYRO_XOUT_L 0x2 -#define MPU6050_EXT_SYNC_GYRO_YOUT_L 0x3 -#define MPU6050_EXT_SYNC_GYRO_ZOUT_L 0x4 -#define MPU6050_EXT_SYNC_ACCEL_XOUT_L 0x5 -#define MPU6050_EXT_SYNC_ACCEL_YOUT_L 0x6 -#define MPU6050_EXT_SYNC_ACCEL_ZOUT_L 0x7 - -#define MPU6050_DLPF_BW_256 0x00 -#define MPU6050_DLPF_BW_188 0x01 -#define MPU6050_DLPF_BW_98 0x02 -#define MPU6050_DLPF_BW_42 0x03 -#define MPU6050_DLPF_BW_20 0x04 -#define MPU6050_DLPF_BW_10 0x05 -#define MPU6050_DLPF_BW_5 0x06 - -#define MPU6050_GCONFIG_FS_SEL_BIT 4 -#define MPU6050_GCONFIG_FS_SEL_LENGTH 2 - -#define MPU6050_GYRO_FS_250 0x00 -#define MPU6050_GYRO_FS_500 0x01 -#define MPU6050_GYRO_FS_1000 0x02 -#define MPU6050_GYRO_FS_2000 0x03 - -#define MPU6050_ACONFIG_XA_ST_BIT 7 -#define MPU6050_ACONFIG_YA_ST_BIT 6 -#define MPU6050_ACONFIG_ZA_ST_BIT 5 -#define MPU6050_ACONFIG_AFS_SEL_BIT 4 -#define MPU6050_ACONFIG_AFS_SEL_LENGTH 2 -#define MPU6050_ACONFIG_ACCEL_HPF_BIT 2 -#define MPU6050_ACONFIG_ACCEL_HPF_LENGTH 3 - -#define MPU6050_ACCEL_FS_2 0x00 -#define MPU6050_ACCEL_FS_4 0x01 -#define MPU6050_ACCEL_FS_8 0x02 -#define MPU6050_ACCEL_FS_16 0x03 - -#define MPU6050_DHPF_RESET 0x00 -#define MPU6050_DHPF_5 0x01 -#define MPU6050_DHPF_2P5 0x02 -#define MPU6050_DHPF_1P25 0x03 -#define MPU6050_DHPF_0P63 0x04 -#define MPU6050_DHPF_HOLD 0x07 - -#define MPU6050_TEMP_FIFO_EN_BIT 7 -#define MPU6050_XG_FIFO_EN_BIT 6 -#define MPU6050_YG_FIFO_EN_BIT 5 -#define MPU6050_ZG_FIFO_EN_BIT 4 -#define MPU6050_ACCEL_FIFO_EN_BIT 3 -#define MPU6050_SLV2_FIFO_EN_BIT 2 -#define MPU6050_SLV1_FIFO_EN_BIT 1 -#define MPU6050_SLV0_FIFO_EN_BIT 0 - -#define MPU6050_MULT_MST_EN_BIT 7 -#define MPU6050_WAIT_FOR_ES_BIT 6 -#define MPU6050_SLV_3_FIFO_EN_BIT 5 -#define MPU6050_I2C_MST_P_NSR_BIT 4 -#define MPU6050_I2C_MST_CLK_BIT 3 -#define MPU6050_I2C_MST_CLK_LENGTH 4 - -#define MPU6050_CLOCK_DIV_348 0x0 -#define MPU6050_CLOCK_DIV_333 0x1 -#define MPU6050_CLOCK_DIV_320 0x2 -#define MPU6050_CLOCK_DIV_308 0x3 -#define MPU6050_CLOCK_DIV_296 0x4 -#define MPU6050_CLOCK_DIV_286 0x5 -#define MPU6050_CLOCK_DIV_276 0x6 -#define MPU6050_CLOCK_DIV_267 0x7 -#define MPU6050_CLOCK_DIV_258 0x8 -#define MPU6050_CLOCK_DIV_500 0x9 -#define MPU6050_CLOCK_DIV_471 0xA -#define MPU6050_CLOCK_DIV_444 0xB -#define MPU6050_CLOCK_DIV_421 0xC -#define MPU6050_CLOCK_DIV_400 0xD -#define MPU6050_CLOCK_DIV_381 0xE -#define MPU6050_CLOCK_DIV_364 0xF - -#define MPU6050_I2C_SLV_RW_BIT 7 -#define MPU6050_I2C_SLV_ADDR_BIT 6 -#define MPU6050_I2C_SLV_ADDR_LENGTH 7 -#define MPU6050_I2C_SLV_EN_BIT 7 -#define MPU6050_I2C_SLV_BYTE_SW_BIT 6 -#define MPU6050_I2C_SLV_REG_DIS_BIT 5 -#define MPU6050_I2C_SLV_GRP_BIT 4 -#define MPU6050_I2C_SLV_LEN_BIT 3 -#define MPU6050_I2C_SLV_LEN_LENGTH 4 - -#define MPU6050_I2C_SLV4_RW_BIT 7 -#define MPU6050_I2C_SLV4_ADDR_BIT 6 -#define MPU6050_I2C_SLV4_ADDR_LENGTH 7 -#define MPU6050_I2C_SLV4_EN_BIT 7 -#define MPU6050_I2C_SLV4_INT_EN_BIT 6 -#define MPU6050_I2C_SLV4_REG_DIS_BIT 5 -#define MPU6050_I2C_SLV4_MST_DLY_BIT 4 -#define MPU6050_I2C_SLV4_MST_DLY_LENGTH 5 - -#define MPU6050_MST_PASS_THROUGH_BIT 7 -#define MPU6050_MST_I2C_SLV4_DONE_BIT 6 -#define MPU6050_MST_I2C_LOST_ARB_BIT 5 -#define MPU6050_MST_I2C_SLV4_NACK_BIT 4 -#define MPU6050_MST_I2C_SLV3_NACK_BIT 3 -#define MPU6050_MST_I2C_SLV2_NACK_BIT 2 -#define MPU6050_MST_I2C_SLV1_NACK_BIT 1 -#define MPU6050_MST_I2C_SLV0_NACK_BIT 0 - -#define MPU6050_INTCFG_INT_LEVEL_BIT 7 -#define MPU6050_INTCFG_INT_OPEN_BIT 6 -#define MPU6050_INTCFG_LATCH_INT_EN_BIT 5 -#define MPU6050_INTCFG_INT_RD_CLEAR_BIT 4 -#define MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT 3 -#define MPU6050_INTCFG_FSYNC_INT_EN_BIT 2 -#define MPU6050_INTCFG_I2C_BYPASS_EN_BIT 1 -#define MPU6050_INTCFG_CLKOUT_EN_BIT 0 - -#define MPU6050_INTMODE_ACTIVEHIGH 0x00 -#define MPU6050_INTMODE_ACTIVELOW 0x01 - -#define MPU6050_INTDRV_PUSHPULL 0x00 -#define MPU6050_INTDRV_OPENDRAIN 0x01 - -#define MPU6050_INTLATCH_50USPULSE 0x00 -#define MPU6050_INTLATCH_WAITCLEAR 0x01 - -#define MPU6050_INTCLEAR_STATUSREAD 0x00 -#define MPU6050_INTCLEAR_ANYREAD 0x01 - -#define MPU6050_INTERRUPT_FF_BIT 7 -#define MPU6050_INTERRUPT_MOT_BIT 6 -#define MPU6050_INTERRUPT_ZMOT_BIT 5 -#define MPU6050_INTERRUPT_FIFO_OFLOW_BIT 4 -#define MPU6050_INTERRUPT_I2C_MST_INT_BIT 3 -#define MPU6050_INTERRUPT_PLL_RDY_INT_BIT 2 -#define MPU6050_INTERRUPT_DMP_INT_BIT 1 -#define MPU6050_INTERRUPT_DATA_RDY_BIT 0 - -// TODO: figure out what these actually do -// UMPL source code is not very obivous -#define MPU6050_DMPINT_5_BIT 5 -#define MPU6050_DMPINT_4_BIT 4 -#define MPU6050_DMPINT_3_BIT 3 -#define MPU6050_DMPINT_2_BIT 2 -#define MPU6050_DMPINT_1_BIT 1 -#define MPU6050_DMPINT_0_BIT 0 - -#define MPU6050_MOTION_MOT_XNEG_BIT 7 -#define MPU6050_MOTION_MOT_XPOS_BIT 6 -#define MPU6050_MOTION_MOT_YNEG_BIT 5 -#define MPU6050_MOTION_MOT_YPOS_BIT 4 -#define MPU6050_MOTION_MOT_ZNEG_BIT 3 -#define MPU6050_MOTION_MOT_ZPOS_BIT 2 -#define MPU6050_MOTION_MOT_ZRMOT_BIT 0 - -#define MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT 7 -#define MPU6050_DELAYCTRL_I2C_SLV4_DLY_EN_BIT 4 -#define MPU6050_DELAYCTRL_I2C_SLV3_DLY_EN_BIT 3 -#define MPU6050_DELAYCTRL_I2C_SLV2_DLY_EN_BIT 2 -#define MPU6050_DELAYCTRL_I2C_SLV1_DLY_EN_BIT 1 -#define MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT 0 - -#define MPU6050_PATHRESET_GYRO_RESET_BIT 2 -#define MPU6050_PATHRESET_ACCEL_RESET_BIT 1 -#define MPU6050_PATHRESET_TEMP_RESET_BIT 0 - -#define MPU6050_DETECT_ACCEL_ON_DELAY_BIT 5 -#define MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH 2 -#define MPU6050_DETECT_FF_COUNT_BIT 3 -#define MPU6050_DETECT_FF_COUNT_LENGTH 2 -#define MPU6050_DETECT_MOT_COUNT_BIT 1 -#define MPU6050_DETECT_MOT_COUNT_LENGTH 2 - -#define MPU6050_DETECT_DECREMENT_RESET 0x0 -#define MPU6050_DETECT_DECREMENT_1 0x1 -#define MPU6050_DETECT_DECREMENT_2 0x2 -#define MPU6050_DETECT_DECREMENT_4 0x3 - -#define MPU6050_USERCTRL_DMP_EN_BIT 7 -#define MPU6050_USERCTRL_FIFO_EN_BIT 6 -#define MPU6050_USERCTRL_I2C_MST_EN_BIT 5 -#define MPU6050_USERCTRL_I2C_IF_DIS_BIT 4 -#define MPU6050_USERCTRL_DMP_RESET_BIT 3 -#define MPU6050_USERCTRL_FIFO_RESET_BIT 2 -#define MPU6050_USERCTRL_I2C_MST_RESET_BIT 1 -#define MPU6050_USERCTRL_SIG_COND_RESET_BIT 0 - -#define MPU6050_PWR1_DEVICE_RESET_BIT 7 -#define MPU6050_PWR1_SLEEP_BIT 6 -#define MPU6050_PWR1_CYCLE_BIT 5 -#define MPU6050_PWR1_TEMP_DIS_BIT 3 -#define MPU6050_PWR1_CLKSEL_BIT 2 -#define MPU6050_PWR1_CLKSEL_LENGTH 3 - -#define MPU6050_CLOCK_INTERNAL 0x00 -#define MPU6050_CLOCK_PLL_XGYRO 0x01 -#define MPU6050_CLOCK_PLL_YGYRO 0x02 -#define MPU6050_CLOCK_PLL_ZGYRO 0x03 -#define MPU6050_CLOCK_PLL_EXT32K 0x04 -#define MPU6050_CLOCK_PLL_EXT19M 0x05 -#define MPU6050_CLOCK_KEEP_RESET 0x07 - -#define MPU6050_PWR2_LP_WAKE_CTRL_BIT 7 -#define MPU6050_PWR2_LP_WAKE_CTRL_LENGTH 2 -#define MPU6050_PWR2_STBY_XA_BIT 5 -#define MPU6050_PWR2_STBY_YA_BIT 4 -#define MPU6050_PWR2_STBY_ZA_BIT 3 -#define MPU6050_PWR2_STBY_XG_BIT 2 -#define MPU6050_PWR2_STBY_YG_BIT 1 -#define MPU6050_PWR2_STBY_ZG_BIT 0 - -#define MPU6050_WAKE_FREQ_1P25 0x0 -#define MPU6050_WAKE_FREQ_2P5 0x1 -#define MPU6050_WAKE_FREQ_5 0x2 -#define MPU6050_WAKE_FREQ_10 0x3 - -#define MPU6050_BANKSEL_PRFTCH_EN_BIT 6 -#define MPU6050_BANKSEL_CFG_USER_BANK_BIT 5 -#define MPU6050_BANKSEL_MEM_SEL_BIT 4 -#define MPU6050_BANKSEL_MEM_SEL_LENGTH 5 - -#define MPU6050_WHO_AM_I_BIT 6 -#define MPU6050_WHO_AM_I_LENGTH 6 - -#define MPU6050_DMP_MEMORY_BANKS 8 -#define MPU6050_DMP_MEMORY_BANK_SIZE 256 -#define MPU6050_DMP_MEMORY_CHUNK_SIZE 16 - -// note: DMP code memory blocks defined at end of header file - -class MPU6050 -{ - public: - MPU6050(); - MPU6050(uint8_t address); - - void initialize(); - bool testConnection(); - - // AUX_VDDIO register - uint8_t getAuxVDDIOLevel(); - void setAuxVDDIOLevel(uint8_t level); - - // SMPLRT_DIV register - uint8_t getRate(); - void setRate(uint8_t rate); - - // CONFIG register - uint8_t getExternalFrameSync(); - void setExternalFrameSync(uint8_t sync); - uint8_t getDLPFMode(); - void setDLPFMode(uint8_t bandwidth); - - // GYRO_CONFIG register - uint8_t getFullScaleGyroRange(); - void setFullScaleGyroRange(uint8_t range); - - // SELF_TEST registers - uint8_t getAccelXSelfTestFactoryTrim(); - uint8_t getAccelYSelfTestFactoryTrim(); - uint8_t getAccelZSelfTestFactoryTrim(); - - uint8_t getGyroXSelfTestFactoryTrim(); - uint8_t getGyroYSelfTestFactoryTrim(); - uint8_t getGyroZSelfTestFactoryTrim(); - - // ACCEL_CONFIG register - bool getAccelXSelfTest(); - void setAccelXSelfTest(bool enabled); - bool getAccelYSelfTest(); - void setAccelYSelfTest(bool enabled); - bool getAccelZSelfTest(); - void setAccelZSelfTest(bool enabled); - uint8_t getFullScaleAccelRange(); - void setFullScaleAccelRange(uint8_t range); - uint8_t getDHPFMode(); - void setDHPFMode(uint8_t mode); - - // FF_THR register - uint8_t getFreefallDetectionThreshold(); - void setFreefallDetectionThreshold(uint8_t threshold); - - // FF_DUR register - uint8_t getFreefallDetectionDuration(); - void setFreefallDetectionDuration(uint8_t duration); - - // MOT_THR register - uint8_t getMotionDetectionThreshold(); - void setMotionDetectionThreshold(uint8_t threshold); - - // MOT_DUR register - uint8_t getMotionDetectionDuration(); - void setMotionDetectionDuration(uint8_t duration); - - // ZRMOT_THR register - uint8_t getZeroMotionDetectionThreshold(); - void setZeroMotionDetectionThreshold(uint8_t threshold); - - // ZRMOT_DUR register - uint8_t getZeroMotionDetectionDuration(); - void setZeroMotionDetectionDuration(uint8_t duration); - - // FIFO_EN register - bool getTempFIFOEnabled(); - void setTempFIFOEnabled(bool enabled); - bool getXGyroFIFOEnabled(); - void setXGyroFIFOEnabled(bool enabled); - bool getYGyroFIFOEnabled(); - void setYGyroFIFOEnabled(bool enabled); - bool getZGyroFIFOEnabled(); - void setZGyroFIFOEnabled(bool enabled); - bool getAccelFIFOEnabled(); - void setAccelFIFOEnabled(bool enabled); - bool getSlave2FIFOEnabled(); - void setSlave2FIFOEnabled(bool enabled); - bool getSlave1FIFOEnabled(); - void setSlave1FIFOEnabled(bool enabled); - bool getSlave0FIFOEnabled(); - void setSlave0FIFOEnabled(bool enabled); - - // I2C_MST_CTRL register - bool getMultiMasterEnabled(); - void setMultiMasterEnabled(bool enabled); - bool getWaitForExternalSensorEnabled(); - void setWaitForExternalSensorEnabled(bool enabled); - bool getSlave3FIFOEnabled(); - void setSlave3FIFOEnabled(bool enabled); - bool getSlaveReadWriteTransitionEnabled(); - void setSlaveReadWriteTransitionEnabled(bool enabled); - uint8_t getMasterClockSpeed(); - void setMasterClockSpeed(uint8_t speed); - - // I2C_SLV* registers (Slave 0-3) - uint8_t getSlaveAddress(uint8_t num); - void setSlaveAddress(uint8_t num, uint8_t address); - uint8_t getSlaveRegister(uint8_t num); - void setSlaveRegister(uint8_t num, uint8_t reg); - bool getSlaveEnabled(uint8_t num); - void setSlaveEnabled(uint8_t num, bool enabled); - bool getSlaveWordByteSwap(uint8_t num); - void setSlaveWordByteSwap(uint8_t num, bool enabled); - bool getSlaveWriteMode(uint8_t num); - void setSlaveWriteMode(uint8_t num, bool mode); - bool getSlaveWordGroupOffset(uint8_t num); - void setSlaveWordGroupOffset(uint8_t num, bool enabled); - uint8_t getSlaveDataLength(uint8_t num); - void setSlaveDataLength(uint8_t num, uint8_t length); - - // I2C_SLV* registers (Slave 4) - uint8_t getSlave4Address(); - void setSlave4Address(uint8_t address); - uint8_t getSlave4Register(); - void setSlave4Register(uint8_t reg); - void setSlave4OutputByte(uint8_t data); - bool getSlave4Enabled(); - void setSlave4Enabled(bool enabled); - bool getSlave4InterruptEnabled(); - void setSlave4InterruptEnabled(bool enabled); - bool getSlave4WriteMode(); - void setSlave4WriteMode(bool mode); - uint8_t getSlave4MasterDelay(); - void setSlave4MasterDelay(uint8_t delay); - uint8_t getSlate4InputByte(); - - // I2C_MST_STATUS register - bool getPassthroughStatus(); - bool getSlave4IsDone(); - bool getLostArbitration(); - bool getSlave4Nack(); - bool getSlave3Nack(); - bool getSlave2Nack(); - bool getSlave1Nack(); - bool getSlave0Nack(); - - // INT_PIN_CFG register - bool getInterruptMode(); - void setInterruptMode(bool mode); - bool getInterruptDrive(); - void setInterruptDrive(bool drive); - bool getInterruptLatch(); - void setInterruptLatch(bool latch); - bool getInterruptLatchClear(); - void setInterruptLatchClear(bool clear); - bool getFSyncInterruptLevel(); - void setFSyncInterruptLevel(bool level); - bool getFSyncInterruptEnabled(); - void setFSyncInterruptEnabled(bool enabled); - bool getI2CBypassEnabled(); - void setI2CBypassEnabled(bool enabled); - bool getClockOutputEnabled(); - void setClockOutputEnabled(bool enabled); - - // INT_ENABLE register - uint8_t getIntEnabled(); - void setIntEnabled(uint8_t enabled); - bool getIntFreefallEnabled(); - void setIntFreefallEnabled(bool enabled); - bool getIntMotionEnabled(); - void setIntMotionEnabled(bool enabled); - bool getIntZeroMotionEnabled(); - void setIntZeroMotionEnabled(bool enabled); - bool getIntFIFOBufferOverflowEnabled(); - void setIntFIFOBufferOverflowEnabled(bool enabled); - bool getIntI2CMasterEnabled(); - void setIntI2CMasterEnabled(bool enabled); - bool getIntDataReadyEnabled(); - void setIntDataReadyEnabled(bool enabled); - - // INT_STATUS register - uint8_t getIntStatus(); - bool getIntFreefallStatus(); - bool getIntMotionStatus(); - bool getIntZeroMotionStatus(); - bool getIntFIFOBufferOverflowStatus(); - bool getIntI2CMasterStatus(); - bool getIntDataReadyStatus(); - - // ACCEL_*OUT_* registers - void getMotion9(int16_t *ax, int16_t *ay, int16_t *az, int16_t *gx, int16_t *gy, int16_t *gz, int16_t *mx, int16_t *my, int16_t *mz); - void getMotion6(int16_t *ax, int16_t *ay, int16_t *az, int16_t *gx, int16_t *gy, int16_t *gz); - void getAcceleration(int16_t *x, int16_t *y, int16_t *z); - int16_t getAccelerationX(); - int16_t getAccelerationY(); - int16_t getAccelerationZ(); - - // TEMP_OUT_* registers - int16_t getTemperature(); - - // GYRO_*OUT_* registers - void getRotation(int16_t *x, int16_t *y, int16_t *z); - int16_t getRotationX(); - int16_t getRotationY(); - int16_t getRotationZ(); - - // EXT_SENS_DATA_* registers - uint8_t getExternalSensorByte(int position); - uint16_t getExternalSensorWord(int position); - uint32_t getExternalSensorDWord(int position); - - // MOT_DETECT_STATUS register - uint8_t getMotionStatus(); - bool getXNegMotionDetected(); - bool getXPosMotionDetected(); - bool getYNegMotionDetected(); - bool getYPosMotionDetected(); - bool getZNegMotionDetected(); - bool getZPosMotionDetected(); - bool getZeroMotionDetected(); - - // I2C_SLV*_DO register - void setSlaveOutputByte(uint8_t num, uint8_t data); - - // I2C_MST_DELAY_CTRL register - bool getExternalShadowDelayEnabled(); - void setExternalShadowDelayEnabled(bool enabled); - bool getSlaveDelayEnabled(uint8_t num); - void setSlaveDelayEnabled(uint8_t num, bool enabled); - - // SIGNAL_PATH_RESET register - void resetGyroscopePath(); - void resetAccelerometerPath(); - void resetTemperaturePath(); - - // MOT_DETECT_CTRL register - uint8_t getAccelerometerPowerOnDelay(); - void setAccelerometerPowerOnDelay(uint8_t delay); - uint8_t getFreefallDetectionCounterDecrement(); - void setFreefallDetectionCounterDecrement(uint8_t decrement); - uint8_t getMotionDetectionCounterDecrement(); - void setMotionDetectionCounterDecrement(uint8_t decrement); - - // USER_CTRL register - bool getFIFOEnabled(); - void setFIFOEnabled(bool enabled); - bool getI2CMasterModeEnabled(); - void setI2CMasterModeEnabled(bool enabled); - void switchSPIEnabled(bool enabled); - void resetFIFO(); - void resetI2CMaster(); - void resetSensors(); - - // PWR_MGMT_1 register - void reset(); - bool getSleepEnabled(); - void setSleepEnabled(bool enabled); - bool getWakeCycleEnabled(); - void setWakeCycleEnabled(bool enabled); - bool getTempSensorEnabled(); - void setTempSensorEnabled(bool enabled); - uint8_t getClockSource(); - void setClockSource(uint8_t source); - - // PWR_MGMT_2 register - uint8_t getWakeFrequency(); - void setWakeFrequency(uint8_t frequency); - bool getStandbyXAccelEnabled(); - void setStandbyXAccelEnabled(bool enabled); - bool getStandbyYAccelEnabled(); - void setStandbyYAccelEnabled(bool enabled); - bool getStandbyZAccelEnabled(); - void setStandbyZAccelEnabled(bool enabled); - bool getStandbyXGyroEnabled(); - void setStandbyXGyroEnabled(bool enabled); - bool getStandbyYGyroEnabled(); - void setStandbyYGyroEnabled(bool enabled); - bool getStandbyZGyroEnabled(); - void setStandbyZGyroEnabled(bool enabled); - - // FIFO_COUNT_* registers - uint16_t getFIFOCount(); - - // FIFO_R_W register - uint8_t getFIFOByte(); - void setFIFOByte(uint8_t data); - void getFIFOBytes(uint8_t *data, uint8_t length); - - // WHO_AM_I register - uint8_t getDeviceID(); - void setDeviceID(uint8_t id); - - // ======== UNDOCUMENTED/DMP REGISTERS/METHODS ======== - - // XG_OFFS_TC register - uint8_t getOTPBankValid(); - void setOTPBankValid(bool enabled); - int8_t getXGyroOffsetTC(); - void setXGyroOffsetTC(int8_t offset); - - // YG_OFFS_TC register - int8_t getYGyroOffsetTC(); - void setYGyroOffsetTC(int8_t offset); - - // ZG_OFFS_TC register - int8_t getZGyroOffsetTC(); - void setZGyroOffsetTC(int8_t offset); - - // X_FINE_GAIN register - int8_t getXFineGain(); - void setXFineGain(int8_t gain); - - // Y_FINE_GAIN register - int8_t getYFineGain(); - void setYFineGain(int8_t gain); - - // Z_FINE_GAIN register - int8_t getZFineGain(); - void setZFineGain(int8_t gain); - - // XA_OFFS_* registers - int16_t getXAccelOffset(); - void setXAccelOffset(int16_t offset); - - // YA_OFFS_* register - int16_t getYAccelOffset(); - void setYAccelOffset(int16_t offset); - - // ZA_OFFS_* register - int16_t getZAccelOffset(); - void setZAccelOffset(int16_t offset); - - // XG_OFFS_USR* registers - int16_t getXGyroOffset(); - void setXGyroOffset(int16_t offset); - - // YG_OFFS_USR* register - int16_t getYGyroOffset(); - void setYGyroOffset(int16_t offset); - - // ZG_OFFS_USR* register - int16_t getZGyroOffset(); - void setZGyroOffset(int16_t offset); - - // INT_ENABLE register (DMP functions) - bool getIntPLLReadyEnabled(); - void setIntPLLReadyEnabled(bool enabled); - bool getIntDMPEnabled(); - void setIntDMPEnabled(bool enabled); - - // DMP_INT_STATUS - bool getDMPInt5Status(); - bool getDMPInt4Status(); - bool getDMPInt3Status(); - bool getDMPInt2Status(); - bool getDMPInt1Status(); - bool getDMPInt0Status(); - - // INT_STATUS register (DMP functions) - bool getIntPLLReadyStatus(); - bool getIntDMPStatus(); - - // USER_CTRL register (DMP functions) - bool getDMPEnabled(); - void setDMPEnabled(bool enabled); - void resetDMP(); - - // BANK_SEL register - void setMemoryBank(uint8_t bank, bool prefetchEnabled = false, bool userBank = false); - - // MEM_START_ADDR register - void setMemoryStartAddress(uint8_t address); - - // MEM_R_W register - uint8_t readMemoryByte(); - void writeMemoryByte(uint8_t data); - void readMemoryBlock(uint8_t *data, uint16_t dataSize, uint8_t bank = 0, uint8_t address = 0); - // bool writeMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank = 0, uint8_t address = 0, bool verify = true, bool useProgMem = false); - bool writeMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank = 0, uint8_t address = 0, bool verify = true); - // bool writeProgMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank = 0, uint8_t address = 0, bool verify = true); - - // bool writeDMPConfigurationSet(const uint8_t *data, uint16_t dataSize, bool useProgMem = false); - bool writeDMPConfigurationSet(const uint8_t *data, uint16_t dataSize); - // bool writeProgDMPConfigurationSet(const uint8_t *data, uint16_t dataSize); - - // DMP_CFG_1 register - uint8_t getDMPConfig1(); - void setDMPConfig1(uint8_t config); - - // DMP_CFG_2 register - uint8_t getDMPConfig2(); - void setDMPConfig2(uint8_t config); - -// special methods for MotionApps 2.0 implementation -#ifdef MPU6050_INCLUDE_DMP_MOTIONAPPS20 - uint8_t *dmpPacketBuffer; - uint16_t dmpPacketSize; - - uint8_t dmpInitialize(); - bool dmpPacketAvailable(); - - uint8_t dmpSetFIFORate(uint8_t fifoRate); - uint8_t dmpGetFIFORate(); - uint8_t dmpGetSampleStepSizeMS(); - uint8_t dmpGetSampleFrequency(); - int32_t dmpDecodeTemperature(int8_t tempReg); - - // Register callbacks after a packet of FIFO data is processed - //uint8_t dmpRegisterFIFORateProcess(inv_obj_func func, int16_t priority); - //uint8_t dmpUnregisterFIFORateProcess(inv_obj_func func); - uint8_t dmpRunFIFORateProcesses(); - - // Setup FIFO for various output - uint8_t dmpSendQuaternion(uint_fast16_t accuracy); - uint8_t dmpSendGyro(uint_fast16_t elements, uint_fast16_t accuracy); - uint8_t dmpSendAccel(uint_fast16_t elements, uint_fast16_t accuracy); - uint8_t dmpSendLinearAccel(uint_fast16_t elements, uint_fast16_t accuracy); - uint8_t dmpSendLinearAccelInWorld(uint_fast16_t elements, uint_fast16_t accuracy); - uint8_t dmpSendControlData(uint_fast16_t elements, uint_fast16_t accuracy); - uint8_t dmpSendSensorData(uint_fast16_t elements, uint_fast16_t accuracy); - uint8_t dmpSendExternalSensorData(uint_fast16_t elements, uint_fast16_t accuracy); - uint8_t dmpSendGravity(uint_fast16_t elements, uint_fast16_t accuracy); - uint8_t dmpSendPacketNumber(uint_fast16_t accuracy); - uint8_t dmpSendQuantizedAccel(uint_fast16_t elements, uint_fast16_t accuracy); - uint8_t dmpSendEIS(uint_fast16_t elements, uint_fast16_t accuracy); - - // Get Fixed Point data from FIFO - uint8_t dmpGetAccel(int32_t *data, const uint8_t *packet = 0); - uint8_t dmpGetAccel(int16_t *data, const uint8_t *packet = 0); - uint8_t dmpGetAccel(VectorInt16 *v, const uint8_t *packet = 0); - uint8_t dmpGetQuaternion(int32_t *data, const uint8_t *packet = 0); - uint8_t dmpGetQuaternion(int16_t *data, const uint8_t *packet = 0); - uint8_t dmpGetQuaternion(Quaternion *q, const uint8_t *packet = 0); - uint8_t dmpGet6AxisQuaternion(int32_t *data, const uint8_t *packet = 0); - uint8_t dmpGet6AxisQuaternion(int16_t *data, const uint8_t *packet = 0); - uint8_t dmpGet6AxisQuaternion(Quaternion *q, const uint8_t *packet = 0); - uint8_t dmpGetRelativeQuaternion(int32_t *data, const uint8_t *packet = 0); - uint8_t dmpGetRelativeQuaternion(int16_t *data, const uint8_t *packet = 0); - uint8_t dmpGetRelativeQuaternion(Quaternion *data, const uint8_t *packet = 0); - uint8_t dmpGetGyro(int32_t *data, const uint8_t *packet = 0); - uint8_t dmpGetGyro(int16_t *data, const uint8_t *packet = 0); - uint8_t dmpGetGyro(VectorInt16 *v, const uint8_t *packet = 0); - uint8_t dmpSetLinearAccelFilterCoefficient(float coef); - uint8_t dmpGetLinearAccel(int32_t *data, const uint8_t *packet = 0); - uint8_t dmpGetLinearAccel(int16_t *data, const uint8_t *packet = 0); - uint8_t dmpGetLinearAccel(VectorInt16 *v, const uint8_t *packet = 0); - uint8_t dmpGetLinearAccel(VectorInt16 *v, VectorInt16 *vRaw, VectorFloat *gravity); - uint8_t dmpGetLinearAccelInWorld(int32_t *data, const uint8_t *packet = 0); - uint8_t dmpGetLinearAccelInWorld(int16_t *data, const uint8_t *packet = 0); - uint8_t dmpGetLinearAccelInWorld(VectorInt16 *v, const uint8_t *packet = 0); - uint8_t dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Quaternion *q); - uint8_t dmpGetGyroAndAccelSensor(int32_t *data, const uint8_t *packet = 0); - uint8_t dmpGetGyroAndAccelSensor(int16_t *data, const uint8_t *packet = 0); - uint8_t dmpGetGyroAndAccelSensor(VectorInt16 *g, VectorInt16 *a, const uint8_t *packet = 0); - uint8_t dmpGetGyroSensor(int32_t *data, const uint8_t *packet = 0); - uint8_t dmpGetGyroSensor(int16_t *data, const uint8_t *packet = 0); - uint8_t dmpGetGyroSensor(VectorInt16 *v, const uint8_t *packet = 0); - uint8_t dmpGetControlData(int32_t *data, const uint8_t *packet = 0); - uint8_t dmpGetTemperature(int32_t *data, const uint8_t *packet = 0); - uint8_t dmpGetGravity(int32_t *data, const uint8_t *packet = 0); - uint8_t dmpGetGravity(int16_t *data, const uint8_t *packet = 0); - uint8_t dmpGetGravity(VectorInt16 *v, const uint8_t *packet = 0); - uint8_t dmpGetGravity(VectorFloat *v, Quaternion *q); - uint8_t dmpGetUnquantizedAccel(int32_t *data, const uint8_t *packet = 0); - uint8_t dmpGetUnquantizedAccel(int16_t *data, const uint8_t *packet = 0); - uint8_t dmpGetUnquantizedAccel(VectorInt16 *v, const uint8_t *packet = 0); - uint8_t dmpGetQuantizedAccel(int32_t *data, const uint8_t *packet = 0); - uint8_t dmpGetQuantizedAccel(int16_t *data, const uint8_t *packet = 0); - uint8_t dmpGetQuantizedAccel(VectorInt16 *v, const uint8_t *packet = 0); - uint8_t dmpGetExternalSensorData(int32_t *data, uint16_t size, const uint8_t *packet = 0); - uint8_t dmpGetEIS(int32_t *data, const uint8_t *packet = 0); - - uint8_t dmpGetEuler(float *data, Quaternion *q); - uint8_t dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity); - - // Get Floating Point data from FIFO - uint8_t dmpGetAccelFloat(float *data, const uint8_t *packet = 0); - uint8_t dmpGetQuaternionFloat(float *data, const uint8_t *packet = 0); - - uint8_t dmpProcessFIFOPacket(const unsigned char *dmpData); - uint8_t dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *processed = NULL); - - uint8_t dmpSetFIFOProcessedCallback(void (*func)(void)); - - uint8_t dmpInitFIFOParam(); - uint8_t dmpCloseFIFO(); - uint8_t dmpSetGyroDataSource(uint8_t source); - uint8_t dmpDecodeQuantizedAccel(); - uint32_t dmpGetGyroSumOfSquare(); - uint32_t dmpGetAccelSumOfSquare(); - void dmpOverrideQuaternion(long *q); - uint16_t dmpGetFIFOPacketSize(); -#endif - -// special methods for MotionApps 4.1 implementation -#ifdef MPU6050_INCLUDE_DMP_MOTIONAPPS41 - uint8_t *dmpPacketBuffer; - uint16_t dmpPacketSize; - - uint8_t dmpInitialize(); - bool dmpPacketAvailable(); - - uint8_t dmpSetFIFORate(uint8_t fifoRate); - uint8_t dmpGetFIFORate(); - uint8_t dmpGetSampleStepSizeMS(); - uint8_t dmpGetSampleFrequency(); - int32_t dmpDecodeTemperature(int8_t tempReg); - - // Register callbacks after a packet of FIFO data is processed - //uint8_t dmpRegisterFIFORateProcess(inv_obj_func func, int16_t priority); - //uint8_t dmpUnregisterFIFORateProcess(inv_obj_func func); - uint8_t dmpRunFIFORateProcesses(); - - // Setup FIFO for various output - uint8_t dmpSendQuaternion(uint_fast16_t accuracy); - uint8_t dmpSendGyro(uint_fast16_t elements, uint_fast16_t accuracy); - uint8_t dmpSendAccel(uint_fast16_t elements, uint_fast16_t accuracy); - uint8_t dmpSendLinearAccel(uint_fast16_t elements, uint_fast16_t accuracy); - uint8_t dmpSendLinearAccelInWorld(uint_fast16_t elements, uint_fast16_t accuracy); - uint8_t dmpSendControlData(uint_fast16_t elements, uint_fast16_t accuracy); - uint8_t dmpSendSensorData(uint_fast16_t elements, uint_fast16_t accuracy); - uint8_t dmpSendExternalSensorData(uint_fast16_t elements, uint_fast16_t accuracy); - uint8_t dmpSendGravity(uint_fast16_t elements, uint_fast16_t accuracy); - uint8_t dmpSendPacketNumber(uint_fast16_t accuracy); - uint8_t dmpSendQuantizedAccel(uint_fast16_t elements, uint_fast16_t accuracy); - uint8_t dmpSendEIS(uint_fast16_t elements, uint_fast16_t accuracy); - - // Get Fixed Point data from FIFO - uint8_t dmpGetAccel(int32_t *data, const uint8_t *packet = 0); - uint8_t dmpGetAccel(int16_t *data, const uint8_t *packet = 0); - uint8_t dmpGetAccel(VectorInt16 *v, const uint8_t *packet = 0); - uint8_t dmpGetQuaternion(int32_t *data, const uint8_t *packet = 0); - uint8_t dmpGetQuaternion(int16_t *data, const uint8_t *packet = 0); - uint8_t dmpGetQuaternion(Quaternion *q, const uint8_t *packet = 0); - uint8_t dmpGet6AxisQuaternion(int32_t *data, const uint8_t *packet = 0); - uint8_t dmpGet6AxisQuaternion(int16_t *data, const uint8_t *packet = 0); - uint8_t dmpGet6AxisQuaternion(Quaternion *q, const uint8_t *packet = 0); - uint8_t dmpGetRelativeQuaternion(int32_t *data, const uint8_t *packet = 0); - uint8_t dmpGetRelativeQuaternion(int16_t *data, const uint8_t *packet = 0); - uint8_t dmpGetRelativeQuaternion(Quaternion *data, const uint8_t *packet = 0); - uint8_t dmpGetGyro(int32_t *data, const uint8_t *packet = 0); - uint8_t dmpGetGyro(int16_t *data, const uint8_t *packet = 0); - uint8_t dmpGetGyro(VectorInt16 *v, const uint8_t *packet = 0); - uint8_t dmpGetMag(int16_t *data, const uint8_t *packet = 0); - uint8_t dmpSetLinearAccelFilterCoefficient(float coef); - uint8_t dmpGetLinearAccel(int32_t *data, const uint8_t *packet = 0); - uint8_t dmpGetLinearAccel(int16_t *data, const uint8_t *packet = 0); - uint8_t dmpGetLinearAccel(VectorInt16 *v, const uint8_t *packet = 0); - uint8_t dmpGetLinearAccel(VectorInt16 *v, VectorInt16 *vRaw, VectorFloat *gravity); - uint8_t dmpGetLinearAccelInWorld(int32_t *data, const uint8_t *packet = 0); - uint8_t dmpGetLinearAccelInWorld(int16_t *data, const uint8_t *packet = 0); - uint8_t dmpGetLinearAccelInWorld(VectorInt16 *v, const uint8_t *packet = 0); - uint8_t dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Quaternion *q); - uint8_t dmpGetGyroAndAccelSensor(int32_t *data, const uint8_t *packet = 0); - uint8_t dmpGetGyroAndAccelSensor(int16_t *data, const uint8_t *packet = 0); - uint8_t dmpGetGyroAndAccelSensor(VectorInt16 *g, VectorInt16 *a, const uint8_t *packet = 0); - uint8_t dmpGetGyroSensor(int32_t *data, const uint8_t *packet = 0); - uint8_t dmpGetGyroSensor(int16_t *data, const uint8_t *packet = 0); - uint8_t dmpGetGyroSensor(VectorInt16 *v, const uint8_t *packet = 0); - uint8_t dmpGetControlData(int32_t *data, const uint8_t *packet = 0); - uint8_t dmpGetTemperature(int32_t *data, const uint8_t *packet = 0); - uint8_t dmpGetGravity(int32_t *data, const uint8_t *packet = 0); - uint8_t dmpGetGravity(int16_t *data, const uint8_t *packet = 0); - uint8_t dmpGetGravity(VectorInt16 *v, const uint8_t *packet = 0); - uint8_t dmpGetGravity(VectorFloat *v, Quaternion *q); - uint8_t dmpGetUnquantizedAccel(int32_t *data, const uint8_t *packet = 0); - uint8_t dmpGetUnquantizedAccel(int16_t *data, const uint8_t *packet = 0); - uint8_t dmpGetUnquantizedAccel(VectorInt16 *v, const uint8_t *packet = 0); - uint8_t dmpGetQuantizedAccel(int32_t *data, const uint8_t *packet = 0); - uint8_t dmpGetQuantizedAccel(int16_t *data, const uint8_t *packet = 0); - uint8_t dmpGetQuantizedAccel(VectorInt16 *v, const uint8_t *packet = 0); - uint8_t dmpGetExternalSensorData(int32_t *data, uint16_t size, const uint8_t *packet = 0); - uint8_t dmpGetEIS(int32_t *data, const uint8_t *packet = 0); - - uint8_t dmpGetEuler(float *data, Quaternion *q); - uint8_t dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity); - - // Get Floating Point data from FIFO - uint8_t dmpGetAccelFloat(float *data, const uint8_t *packet = 0); - uint8_t dmpGetQuaternionFloat(float *data, const uint8_t *packet = 0); - - uint8_t dmpProcessFIFOPacket(const unsigned char *dmpData); - uint8_t dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *processed = NULL); - - uint8_t dmpSetFIFOProcessedCallback(void (*func)(void)); - - uint8_t dmpInitFIFOParam(); - uint8_t dmpCloseFIFO(); - uint8_t dmpSetGyroDataSource(uint8_t source); - uint8_t dmpDecodeQuantizedAccel(); - uint32_t dmpGetGyroSumOfSquare(); - uint32_t dmpGetAccelSumOfSquare(); - void dmpOverrideQuaternion(long *q); - uint16_t dmpGetFIFOPacketSize(); -#endif - - private: - uint8_t devAddr; - uint8_t buffer[14]; -}; - -#endif /* _MPU6050_H_ */ \ No newline at end of file From 9e67902cf04a4d9330fc9adde9d723399143f782 Mon Sep 17 00:00:00 2001 From: Jens Hauke Date: Wed, 25 Apr 2018 15:40:41 +0200 Subject: [PATCH 195/335] Implement MPU6050::dmpGetGravity(int16_t *data, const uint8_t* packet); This implements the integer only version of "uint8_t MPU6050::dmpGetGravity(VectorFloat *v, Quaternion *q)". int16_t *data is assumed to be a vector with 3 components int16_t data[3]. +1g corresponds to +8192, sensitivity is 2g. --- Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h | 11 +++++++++++ Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h | 11 +++++++++++ .../components/MPU6050/MPU6050_6Axis_MotionApps20.h | 11 +++++++++++ .../components/MPU6050/MPU6050_9Axis_MotionApps41.h | 11 +++++++++++ MSP430/MPU6050/MPU6050_6Axis_MotionApps20.h | 11 +++++++++++ MSP430/MPU6050/MPU6050_9Axis_MotionApps41.h | 11 +++++++++++ 6 files changed, 66 insertions(+) diff --git a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h index e3e3c0e8..1fdb2e83 100644 --- a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h +++ b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h @@ -675,6 +675,17 @@ uint8_t MPU6050::dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Qu // uint8_t MPU6050::dmpGetControlData(long *data, const uint8_t* packet); // uint8_t MPU6050::dmpGetTemperature(long *data, const uint8_t* packet); // uint8_t MPU6050::dmpGetGravity(long *data, const uint8_t* packet); +uint8_t MPU6050::dmpGetGravity(int16_t *data, const uint8_t* packet) { + /* +1g corresponds to +8192, sensitivity is 2g. */ + int16_t qI[4]; + uint8_t status = dmpGetQuaternion(qI, packet); + data[0] = ((int32_t)qI[1] * qI[3] - (int32_t)qI[0] * qI[2]) / 16384; + data[1] = ((int32_t)qI[0] * qI[1] + (int32_t)qI[2] * qI[3]) / 16384; + data[2] = ((int32_t)qI[0] * qI[0] - (int32_t)qI[1] * qI[1] + - (int32_t)qI[2] * qI[2] + (int32_t)qI[3] * qI[3]) / (2 * 16384); + return status; +} + uint8_t MPU6050::dmpGetGravity(VectorFloat *v, Quaternion *q) { v -> x = 2 * (q -> x*q -> z - q -> w*q -> y); v -> y = 2 * (q -> w*q -> x + q -> y*q -> z); diff --git a/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h b/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h index 016d0b0d..cf025146 100644 --- a/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h +++ b/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h @@ -780,6 +780,17 @@ uint8_t MPU6050::dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Qu // uint8_t MPU6050::dmpGetControlData(long *data, const uint8_t* packet); // uint8_t MPU6050::dmpGetTemperature(long *data, const uint8_t* packet); // uint8_t MPU6050::dmpGetGravity(long *data, const uint8_t* packet); +uint8_t MPU6050::dmpGetGravity(int16_t *data, const uint8_t* packet) { + /* +1g corresponds to +8192, sensitivity is 2g. */ + int16_t qI[4]; + uint8_t status = dmpGetQuaternion(qI, packet); + data[0] = ((int32_t)qI[1] * qI[3] - (int32_t)qI[0] * qI[2]) / 16384; + data[1] = ((int32_t)qI[0] * qI[1] + (int32_t)qI[2] * qI[3]) / 16384; + data[2] = ((int32_t)qI[0] * qI[0] - (int32_t)qI[1] * qI[1] + - (int32_t)qI[2] * qI[2] + (int32_t)qI[3] * qI[3]) / (2 * 16384); + return status; +} + uint8_t MPU6050::dmpGetGravity(VectorFloat *v, Quaternion *q) { v -> x = 2 * (q -> x*q -> z - q -> w*q -> y); v -> y = 2 * (q -> w*q -> x + q -> y*q -> z); diff --git a/ESP32_ESP-IDF/components/MPU6050/MPU6050_6Axis_MotionApps20.h b/ESP32_ESP-IDF/components/MPU6050/MPU6050_6Axis_MotionApps20.h index 8e3d0499..3d018568 100644 --- a/ESP32_ESP-IDF/components/MPU6050/MPU6050_6Axis_MotionApps20.h +++ b/ESP32_ESP-IDF/components/MPU6050/MPU6050_6Axis_MotionApps20.h @@ -680,6 +680,17 @@ uint8_t MPU6050::dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Qu // uint8_t MPU6050::dmpGetControlData(long *data, const uint8_t* packet); // uint8_t MPU6050::dmpGetTemperature(long *data, const uint8_t* packet); // uint8_t MPU6050::dmpGetGravity(long *data, const uint8_t* packet); +uint8_t MPU6050::dmpGetGravity(int16_t *data, const uint8_t* packet) { + /* +1g corresponds to +8192, sensitivity is 2g. */ + int16_t qI[4]; + uint8_t status = dmpGetQuaternion(qI, packet); + data[0] = ((int32_t)qI[1] * qI[3] - (int32_t)qI[0] * qI[2]) / 16384; + data[1] = ((int32_t)qI[0] * qI[1] + (int32_t)qI[2] * qI[3]) / 16384; + data[2] = ((int32_t)qI[0] * qI[0] - (int32_t)qI[1] * qI[1] + - (int32_t)qI[2] * qI[2] + (int32_t)qI[3] * qI[3]) / (2 * 16384); + return status; +} + uint8_t MPU6050::dmpGetGravity(VectorFloat *v, Quaternion *q) { v -> x = 2 * (q -> x*q -> z - q -> w*q -> y); v -> y = 2 * (q -> w*q -> x + q -> y*q -> z); diff --git a/ESP32_ESP-IDF/components/MPU6050/MPU6050_9Axis_MotionApps41.h b/ESP32_ESP-IDF/components/MPU6050/MPU6050_9Axis_MotionApps41.h index 016d0b0d..cf025146 100644 --- a/ESP32_ESP-IDF/components/MPU6050/MPU6050_9Axis_MotionApps41.h +++ b/ESP32_ESP-IDF/components/MPU6050/MPU6050_9Axis_MotionApps41.h @@ -780,6 +780,17 @@ uint8_t MPU6050::dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Qu // uint8_t MPU6050::dmpGetControlData(long *data, const uint8_t* packet); // uint8_t MPU6050::dmpGetTemperature(long *data, const uint8_t* packet); // uint8_t MPU6050::dmpGetGravity(long *data, const uint8_t* packet); +uint8_t MPU6050::dmpGetGravity(int16_t *data, const uint8_t* packet) { + /* +1g corresponds to +8192, sensitivity is 2g. */ + int16_t qI[4]; + uint8_t status = dmpGetQuaternion(qI, packet); + data[0] = ((int32_t)qI[1] * qI[3] - (int32_t)qI[0] * qI[2]) / 16384; + data[1] = ((int32_t)qI[0] * qI[1] + (int32_t)qI[2] * qI[3]) / 16384; + data[2] = ((int32_t)qI[0] * qI[0] - (int32_t)qI[1] * qI[1] + - (int32_t)qI[2] * qI[2] + (int32_t)qI[3] * qI[3]) / (2 * 16384); + return status; +} + uint8_t MPU6050::dmpGetGravity(VectorFloat *v, Quaternion *q) { v -> x = 2 * (q -> x*q -> z - q -> w*q -> y); v -> y = 2 * (q -> w*q -> x + q -> y*q -> z); diff --git a/MSP430/MPU6050/MPU6050_6Axis_MotionApps20.h b/MSP430/MPU6050/MPU6050_6Axis_MotionApps20.h index 6a8afe27..f65807a6 100644 --- a/MSP430/MPU6050/MPU6050_6Axis_MotionApps20.h +++ b/MSP430/MPU6050/MPU6050_6Axis_MotionApps20.h @@ -625,6 +625,17 @@ uint8_t MPU6050::dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Qu // uint8_t MPU6050::dmpGetControlData(long *data, const uint8_t* packet); // uint8_t MPU6050::dmpGetTemperature(long *data, const uint8_t* packet); // uint8_t MPU6050::dmpGetGravity(long *data, const uint8_t* packet); +uint8_t MPU6050::dmpGetGravity(int16_t *data, const uint8_t* packet) { + /* +1g corresponds to +8192, sensitivity is 2g. */ + int16_t qI[4]; + uint8_t status = dmpGetQuaternion(qI, packet); + data[0] = ((int32_t)qI[1] * qI[3] - (int32_t)qI[0] * qI[2]) / 16384; + data[1] = ((int32_t)qI[0] * qI[1] + (int32_t)qI[2] * qI[3]) / 16384; + data[2] = ((int32_t)qI[0] * qI[0] - (int32_t)qI[1] * qI[1] + - (int32_t)qI[2] * qI[2] + (int32_t)qI[3] * qI[3]) / (2 * 16384); + return status; +} + uint8_t MPU6050::dmpGetGravity(VectorFloat *v, Quaternion *q) { v -> x = 2 * (q -> x*q -> z - q -> w*q -> y); v -> y = 2 * (q -> w*q -> x + q -> y*q -> z); diff --git a/MSP430/MPU6050/MPU6050_9Axis_MotionApps41.h b/MSP430/MPU6050/MPU6050_9Axis_MotionApps41.h index aa04e1ba..87151e3b 100644 --- a/MSP430/MPU6050/MPU6050_9Axis_MotionApps41.h +++ b/MSP430/MPU6050/MPU6050_9Axis_MotionApps41.h @@ -736,6 +736,17 @@ uint8_t MPU6050::dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Qu // uint8_t MPU6050::dmpGetControlData(long *data, const uint8_t* packet); // uint8_t MPU6050::dmpGetTemperature(long *data, const uint8_t* packet); // uint8_t MPU6050::dmpGetGravity(long *data, const uint8_t* packet); +uint8_t MPU6050::dmpGetGravity(int16_t *data, const uint8_t* packet) { + /* +1g corresponds to +8192, sensitivity is 2g. */ + int16_t qI[4]; + uint8_t status = dmpGetQuaternion(qI, packet); + data[0] = ((int32_t)qI[1] * qI[3] - (int32_t)qI[0] * qI[2]) / 16384; + data[1] = ((int32_t)qI[0] * qI[1] + (int32_t)qI[2] * qI[3]) / 16384; + data[2] = ((int32_t)qI[0] * qI[0] - (int32_t)qI[1] * qI[1] + - (int32_t)qI[2] * qI[2] + (int32_t)qI[3] * qI[3]) / (2 * 16384); + return status; +} + uint8_t MPU6050::dmpGetGravity(VectorFloat *v, Quaternion *q) { v -> x = 2 * (q -> x*q -> z - q -> w*q -> y); v -> y = 2 * (q -> w*q -> x + q -> y*q -> z); From 3a8a2d6350a41e45b5e281d7ea3212a8e4bf10b1 Mon Sep 17 00:00:00 2001 From: per1234 Date: Sun, 15 Jul 2018 02:25:24 -0700 Subject: [PATCH 196/335] Use a single tab field separator in keywords.txt Each field of keywords.txt is separated by a single true tab. When you use multiple tabs it causes the field to be interpreted as empty. On Arduino IDE 1.6.5 and newer an empty KEYWORD_TOKENTYPE causes the default editor.function.style coloration to be used (as with KEYWORD2, KEYWORD3, LITERAL2). On Arduino IDE 1.6.4 and older it causes the keyword to not be recognized for any special coloration. Reference: https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5:-Library-specification#keywords --- Arduino/IAQ2000/keywords.txt | 4 ++-- Arduino/MS5803/keywords.txt | 30 +++++++++++++++--------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Arduino/IAQ2000/keywords.txt b/Arduino/IAQ2000/keywords.txt index 775b8571..2188577c 100644 --- a/Arduino/IAQ2000/keywords.txt +++ b/Arduino/IAQ2000/keywords.txt @@ -11,9 +11,9 @@ IAQ2000 KEYWORD1 # Methods and Functions (KEYWORD2) ####################################### -initialize KEYWORD2 +initialize KEYWORD2 testConnection KEYWORD2 -getIaq KEYWORD2 +getIaq KEYWORD2 ####################################### # Instances (KEYWORD2) diff --git a/Arduino/MS5803/keywords.txt b/Arduino/MS5803/keywords.txt index 3753408f..c0b9b189 100644 --- a/Arduino/MS5803/keywords.txt +++ b/Arduino/MS5803/keywords.txt @@ -25,18 +25,18 @@ setDebug KEYWORD2 ########################################### # Constants (LITERAL1) ########################################### -MS5803_ADDRESS LITERAL1 -MS5803_ADDRESS_AD0_LOW LITERAL1 -MS5803_ADDRESS_AD0_HIGH LITERAL1 -MS5803_DEFAULT_ADDRESS LITERAL1 -MS5803_RESET LITERAL1 -MS5803_PROM_BASE LITERAL1 -MS5803_PROM_C1 LITERAL1 -MS5803_PROM_C2 LITERAL1 -MS5803_PROM_C3 LITERAL1 -MS5803_PROM_C4 LITERAL1 -MS5803_PROM_C5 LITERAL1 -MS5803_PROM_C6 LITERAL1 -MS5803_PROM_CRC LITERAL1 -MS5803_ADC_READ LITERAL1 -CMD_ADC_CONV LITERAL1 \ No newline at end of file +MS5803_ADDRESS LITERAL1 +MS5803_ADDRESS_AD0_LOW LITERAL1 +MS5803_ADDRESS_AD0_HIGH LITERAL1 +MS5803_DEFAULT_ADDRESS LITERAL1 +MS5803_RESET LITERAL1 +MS5803_PROM_BASE LITERAL1 +MS5803_PROM_C1 LITERAL1 +MS5803_PROM_C2 LITERAL1 +MS5803_PROM_C3 LITERAL1 +MS5803_PROM_C4 LITERAL1 +MS5803_PROM_C5 LITERAL1 +MS5803_PROM_C6 LITERAL1 +MS5803_PROM_CRC LITERAL1 +MS5803_ADC_READ LITERAL1 +CMD_ADC_CONV LITERAL1 \ No newline at end of file From 6be1b56fe894cf548f4a6202c8340db7307ffdad Mon Sep 17 00:00:00 2001 From: paynterf Date: Mon, 27 Aug 2018 18:30:22 -0400 Subject: [PATCH 197/335] Added Shuning (Steve) Bian's SBWire library as an option in I2Cdev.h/cpp --- Arduino/I2Cdev/I2Cdev.cpp | 34 ++++++++++++++++++++-------------- Arduino/I2Cdev/I2Cdev.h | 7 ++++++- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/Arduino/I2Cdev/I2Cdev.cpp b/Arduino/I2Cdev/I2Cdev.cpp index db173b55..e5f19b21 100644 --- a/Arduino/I2Cdev/I2Cdev.cpp +++ b/Arduino/I2Cdev/I2Cdev.cpp @@ -45,7 +45,7 @@ THE SOFTWARE. #include "I2Cdev.h" -#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE +#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE #ifdef I2CDEV_IMPLEMENTATION_WARNINGS #if ARDUINO < 100 @@ -217,7 +217,7 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 int8_t count = 0; uint32_t t1 = millis(); - #if (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE) + #if (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE) #if (ARDUINO < 100) // Arduino v00xx (before v1.0), Wire library @@ -337,7 +337,7 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 int8_t count = 0; uint32_t t1 = millis(); - #if (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE) +#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE #if (ARDUINO < 100) // Arduino v00xx (before v1.0), Wire library @@ -594,7 +594,8 @@ bool I2Cdev::writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_ #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) Wire.beginTransmission(devAddr); Wire.send((uint8_t) regAddr); // send address - #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) + #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100 \ + || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) Wire.beginTransmission(devAddr); Wire.write((uint8_t) regAddr); // send address #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) @@ -608,16 +609,18 @@ bool I2Cdev::writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_ #endif #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) Wire.send((uint8_t) data[i]); - #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) - Wire.write((uint8_t) data[i]); + #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100 \ + || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) + Wire.write((uint8_t) data[i]); #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) Fastwire::write((uint8_t) data[i]); #endif } #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) Wire.endTransmission(); - #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) - status = Wire.endTransmission(); + #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100 \ + || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) + status = Wire.endTransmission(); #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) Fastwire::stop(); //status = Fastwire::endTransmission(); @@ -649,8 +652,9 @@ bool I2Cdev::writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16 #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) Wire.beginTransmission(devAddr); Wire.send(regAddr); // send address - #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) - Wire.beginTransmission(devAddr); + #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100 \ + || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) + Wire.beginTransmission(devAddr); Wire.write(regAddr); // send address #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) Fastwire::beginTransmission(devAddr); @@ -664,8 +668,9 @@ bool I2Cdev::writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16 #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) Wire.send((uint8_t)(data[i] >> 8)); // send MSB Wire.send((uint8_t)data[i++]); // send LSB - #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) - Wire.write((uint8_t)(data[i] >> 8)); // send MSB + #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100 \ + || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) + Wire.write((uint8_t)(data[i] >> 8)); // send MSB Wire.write((uint8_t)data[i++]); // send LSB #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) Fastwire::write((uint8_t)(data[i] >> 8)); // send MSB @@ -675,8 +680,9 @@ bool I2Cdev::writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16 } #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) Wire.endTransmission(); - #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) - status = Wire.endTransmission(); + #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100 \ + || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) + status = Wire.endTransmission(); #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) Fastwire::stop(); //status = Fastwire::endTransmission(); diff --git a/Arduino/I2Cdev/I2Cdev.h b/Arduino/I2Cdev/I2Cdev.h index 4c0a2e7a..875e5824 100644 --- a/Arduino/I2Cdev/I2Cdev.h +++ b/Arduino/I2Cdev/I2Cdev.h @@ -51,7 +51,8 @@ THE SOFTWARE. // I2C interface implementation setting // ----------------------------------------------------------------------------- #ifndef I2CDEV_IMPLEMENTATION -#define I2CDEV_IMPLEMENTATION I2CDEV_ARDUINO_WIRE +//#define I2CDEV_IMPLEMENTATION I2CDEV_ARDUINO_WIRE +#define I2CDEV_IMPLEMENTATION I2CDEV_BUILTIN_SBWIRE //#define I2CDEV_IMPLEMENTATION I2CDEV_BUILTIN_FASTWIRE #endif // I2CDEV_IMPLEMENTATION @@ -67,6 +68,7 @@ THE SOFTWARE. // ^^^ NBWire implementation is still buggy w/some interrupts! #define I2CDEV_BUILTIN_FASTWIRE 3 // FastWire object from Francesco Ferrara's project #define I2CDEV_I2CMASTER_LIBRARY 4 // I2C object from DSSCircuits I2C-Master Library at https://github.com/DSSCircuits/I2C-Master-Library +#define I2CDEV_BUILTIN_SBWIRE 5 // I2C object from Shuning (Steve) Bian's SBWire Library at https://github.com/freespace/SBWire // ----------------------------------------------------------------------------- // Arduino-style "Serial.print" debug constant (uncomment to enable) @@ -85,6 +87,9 @@ THE SOFTWARE. #if I2CDEV_IMPLEMENTATION == I2CDEV_I2CMASTER_LIBRARY #include #endif + #if I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE + #include "SBWire.h" + #endif #endif #ifdef SPARK From 0657acf89f782c38a9264152eb0d33d49fd75f68 Mon Sep 17 00:00:00 2001 From: paynterf Date: Mon, 27 Aug 2018 18:30:22 -0400 Subject: [PATCH 198/335] Added Shuning (Steve) Bian's SBWire library as an option in I2Cdev.h/cpp Changed I2Cdev.h I2CDEV_IMPLEMENTATION back to I2CDEV_ARDUINO_WIRE --- Arduino/I2Cdev/I2Cdev.cpp | 34 ++++++++++++++++++++-------------- Arduino/I2Cdev/I2Cdev.h | 5 +++++ 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/Arduino/I2Cdev/I2Cdev.cpp b/Arduino/I2Cdev/I2Cdev.cpp index db173b55..e5f19b21 100644 --- a/Arduino/I2Cdev/I2Cdev.cpp +++ b/Arduino/I2Cdev/I2Cdev.cpp @@ -45,7 +45,7 @@ THE SOFTWARE. #include "I2Cdev.h" -#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE +#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE #ifdef I2CDEV_IMPLEMENTATION_WARNINGS #if ARDUINO < 100 @@ -217,7 +217,7 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 int8_t count = 0; uint32_t t1 = millis(); - #if (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE) + #if (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE) #if (ARDUINO < 100) // Arduino v00xx (before v1.0), Wire library @@ -337,7 +337,7 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 int8_t count = 0; uint32_t t1 = millis(); - #if (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE) +#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE #if (ARDUINO < 100) // Arduino v00xx (before v1.0), Wire library @@ -594,7 +594,8 @@ bool I2Cdev::writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_ #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) Wire.beginTransmission(devAddr); Wire.send((uint8_t) regAddr); // send address - #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) + #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100 \ + || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) Wire.beginTransmission(devAddr); Wire.write((uint8_t) regAddr); // send address #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) @@ -608,16 +609,18 @@ bool I2Cdev::writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_ #endif #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) Wire.send((uint8_t) data[i]); - #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) - Wire.write((uint8_t) data[i]); + #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100 \ + || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) + Wire.write((uint8_t) data[i]); #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) Fastwire::write((uint8_t) data[i]); #endif } #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) Wire.endTransmission(); - #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) - status = Wire.endTransmission(); + #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100 \ + || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) + status = Wire.endTransmission(); #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) Fastwire::stop(); //status = Fastwire::endTransmission(); @@ -649,8 +652,9 @@ bool I2Cdev::writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16 #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) Wire.beginTransmission(devAddr); Wire.send(regAddr); // send address - #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) - Wire.beginTransmission(devAddr); + #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100 \ + || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) + Wire.beginTransmission(devAddr); Wire.write(regAddr); // send address #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) Fastwire::beginTransmission(devAddr); @@ -664,8 +668,9 @@ bool I2Cdev::writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16 #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) Wire.send((uint8_t)(data[i] >> 8)); // send MSB Wire.send((uint8_t)data[i++]); // send LSB - #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) - Wire.write((uint8_t)(data[i] >> 8)); // send MSB + #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100 \ + || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) + Wire.write((uint8_t)(data[i] >> 8)); // send MSB Wire.write((uint8_t)data[i++]); // send LSB #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) Fastwire::write((uint8_t)(data[i] >> 8)); // send MSB @@ -675,8 +680,9 @@ bool I2Cdev::writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16 } #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) Wire.endTransmission(); - #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) - status = Wire.endTransmission(); + #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100 \ + || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) + status = Wire.endTransmission(); #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) Fastwire::stop(); //status = Fastwire::endTransmission(); diff --git a/Arduino/I2Cdev/I2Cdev.h b/Arduino/I2Cdev/I2Cdev.h index 4c0a2e7a..0bff39ef 100644 --- a/Arduino/I2Cdev/I2Cdev.h +++ b/Arduino/I2Cdev/I2Cdev.h @@ -52,6 +52,7 @@ THE SOFTWARE. // ----------------------------------------------------------------------------- #ifndef I2CDEV_IMPLEMENTATION #define I2CDEV_IMPLEMENTATION I2CDEV_ARDUINO_WIRE +//#define I2CDEV_IMPLEMENTATION I2CDEV_BUILTIN_SBWIRE //#define I2CDEV_IMPLEMENTATION I2CDEV_BUILTIN_FASTWIRE #endif // I2CDEV_IMPLEMENTATION @@ -67,6 +68,7 @@ THE SOFTWARE. // ^^^ NBWire implementation is still buggy w/some interrupts! #define I2CDEV_BUILTIN_FASTWIRE 3 // FastWire object from Francesco Ferrara's project #define I2CDEV_I2CMASTER_LIBRARY 4 // I2C object from DSSCircuits I2C-Master Library at https://github.com/DSSCircuits/I2C-Master-Library +#define I2CDEV_BUILTIN_SBWIRE 5 // I2C object from Shuning (Steve) Bian's SBWire Library at https://github.com/freespace/SBWire // ----------------------------------------------------------------------------- // Arduino-style "Serial.print" debug constant (uncomment to enable) @@ -85,6 +87,9 @@ THE SOFTWARE. #if I2CDEV_IMPLEMENTATION == I2CDEV_I2CMASTER_LIBRARY #include #endif + #if I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE + #include "SBWire.h" + #endif #endif #ifdef SPARK From ceba54af8e32c67c74942340be1b0bbf5bf59e06 Mon Sep 17 00:00:00 2001 From: Alexandr Zarubkin Date: Fri, 1 Dec 2017 11:30:28 +0300 Subject: [PATCH 199/335] Fix #341. Signed-off-by: Alexandr Zarubkin --- Arduino/I2Cdev/I2Cdev.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Arduino/I2Cdev/I2Cdev.cpp b/Arduino/I2Cdev/I2Cdev.cpp index db173b55..98a84c29 100644 --- a/Arduino/I2Cdev/I2Cdev.cpp +++ b/Arduino/I2Cdev/I2Cdev.cpp @@ -225,7 +225,7 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 // I2C/TWI subsystem uses internal buffer that breaks with large data requests // so if user requests more than BUFFER_LENGTH bytes, we have to do it in // smaller chunks instead of all at once - for (uint8_t k = 0; k < length; k += min(length, BUFFER_LENGTH)) { + for (uint8_t k = 0; k < length; k += min((int)length, BUFFER_LENGTH)) { Wire.beginTransmission(devAddr); Wire.send(regAddr); Wire.endTransmission(); @@ -249,7 +249,7 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 // I2C/TWI subsystem uses internal buffer that breaks with large data requests // so if user requests more than BUFFER_LENGTH bytes, we have to do it in // smaller chunks instead of all at once - for (uint8_t k = 0; k < length; k += min(length, BUFFER_LENGTH)) { + for (uint8_t k = 0; k < length; k += min((int)length, BUFFER_LENGTH)) { Wire.beginTransmission(devAddr); Wire.write(regAddr); Wire.endTransmission(); @@ -273,7 +273,7 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 // I2C/TWI subsystem uses internal buffer that breaks with large data requests // so if user requests more than BUFFER_LENGTH bytes, we have to do it in // smaller chunks instead of all at once - for (uint8_t k = 0; k < length; k += min(length, BUFFER_LENGTH)) { + for (uint8_t k = 0; k < length; k += min((int)length, BUFFER_LENGTH)) { Wire.beginTransmission(devAddr); Wire.write(regAddr); Wire.endTransmission(); From b75dc1703bd7336f977ef0183a953be70fb77d92 Mon Sep 17 00:00:00 2001 From: Mateus Amarante Date: Sat, 22 Sep 2018 11:50:08 -0300 Subject: [PATCH 200/335] Fixed remaining I2C_PATH Changed fixed device path I2C_PATH to a generic settable path_ that is defined in constructor. --- BeagleBoneBlack/I2Cdev/I2Cdev.cpp | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/BeagleBoneBlack/I2Cdev/I2Cdev.cpp b/BeagleBoneBlack/I2Cdev/I2Cdev.cpp index 407345c2..bd62ebc9 100644 --- a/BeagleBoneBlack/I2Cdev/I2Cdev.cpp +++ b/BeagleBoneBlack/I2Cdev/I2Cdev.cpp @@ -36,6 +36,10 @@ THE SOFTWARE. #include #include +#define OPEN_ERROR_MSG "Failed to open " +#define WRITE_ERROR_MSG "Failed to write into " +#define READ_ERROR_MSG "Failed to read from " + I2Cdev::I2Cdev() : I2Cdev(DEFAULT_BBB_I2C_BUS) {} I2Cdev::I2Cdev(uint8_t busAddr) @@ -166,9 +170,11 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 { int fd; - if ((fd = open(I2C_PATH, O_RDWR)) < 0) + if ((fd = open(path_, O_RDWR)) < 0) { - perror("Failed to open " I2C_PATH); + char error_msg[sizeof(OPEN_ERROR_MSG) + sizeof(path_)] = OPEN_ERROR_MSG; + + perror(strcat(error_msg, path_)); return -1; } @@ -180,12 +186,16 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 if (write(fd, ®Addr, 1) != 1) { - perror("Failed to write data into " I2C_PATH); + char error_msg[sizeof(WRITE_ERROR_MSG) + sizeof(path_)] = WRITE_ERROR_MSG; + + perror(strcat(error_msg, path_)); } if (read(fd, data, length) != length) { - perror("Failed to read data from " I2C_PATH); + char error_msg[sizeof(READ_ERROR_MSG) + sizeof(path_)] = READ_ERROR_MSG; + + perror(strcat(error_msg, path_)); return -1; } @@ -347,9 +357,11 @@ bool I2Cdev::writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_ { int fd; - if ((fd = open(I2C_PATH, O_RDWR)) < 0) + if ((fd = open(path_, O_RDWR)) < 0) { - perror("Failed to open " I2C_PATH); + char error_msg[sizeof(OPEN_ERROR_MSG) + sizeof(path_)] = OPEN_ERROR_MSG; + + perror(strcat(error_msg, path_)); return false; } @@ -367,7 +379,9 @@ bool I2Cdev::writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_ if (write(fd, buff, buff_length) != buff_length) { - perror("Failed to write into " I2C_PATH); + char error_msg[sizeof(WRITE_ERROR_MSG) + sizeof(path_)] = WRITE_ERROR_MSG; + + perror(strcat(error_msg, path_)); return false; } From 900b8f959e9fa5c3126e0301f8a61d45a4ea99cc Mon Sep 17 00:00:00 2001 From: Jeff Rowberg Date: Mon, 15 Oct 2018 09:32:35 -0400 Subject: [PATCH 201/335] Define BUFFER_LENGTH if not already present Default buffer size for I2C transmissions is 32 if not otherwise set. This is a band-aid fix since there is almost certainly a more efficient way to handle this, possibly by removing the chunking process entirely from the I2Cdev layer if Wire implements it now based on its own internal buffering (not sure). --- Arduino/I2Cdev/I2Cdev.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Arduino/I2Cdev/I2Cdev.cpp b/Arduino/I2Cdev/I2Cdev.cpp index 65c996d1..5094b159 100644 --- a/Arduino/I2Cdev/I2Cdev.cpp +++ b/Arduino/I2Cdev/I2Cdev.cpp @@ -87,6 +87,11 @@ THE SOFTWARE. #endif +#ifndef BUFFER_LENGTH +// band-aid fix for platforms without Wire-defined BUFFER_LENGTH (removed from some official implementations) +#define BUFFER_LENGTH 32 +#endif + /** Default constructor. */ I2Cdev::I2Cdev() { From f6a7ef745e80995ddcaa819a857f7a63cef7d9de Mon Sep 17 00:00:00 2001 From: gdsports Date: Tue, 18 Jun 2019 20:05:07 -0700 Subject: [PATCH 202/335] Add RAM cache attribute to ISR Required starting with ESP8266 board package 2.5.1 https://github.com/esp8266/Arduino/pull/5995 --- .../examples/MPU6050_DMP6_ESPWiFi/MPU6050_DMP6_ESPWiFi.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Arduino/MPU6050/examples/MPU6050_DMP6_ESPWiFi/MPU6050_DMP6_ESPWiFi.ino b/Arduino/MPU6050/examples/MPU6050_DMP6_ESPWiFi/MPU6050_DMP6_ESPWiFi.ino index 588cf914..9b418762 100644 --- a/Arduino/MPU6050/examples/MPU6050_DMP6_ESPWiFi/MPU6050_DMP6_ESPWiFi.ino +++ b/Arduino/MPU6050/examples/MPU6050_DMP6_ESPWiFi/MPU6050_DMP6_ESPWiFi.ino @@ -146,7 +146,7 @@ const unsigned int outPort = 9999; // remote port to receive OSC // ================================================================ volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high -void dmpDataReady() { +void ICACHE_RAM_ATTR dmpDataReady() { mpuInterrupt = true; } From 905c914af7fe86fd636f59c4d6fce31f7eef0bfd Mon Sep 17 00:00:00 2001 From: Homer Creutz Date: Mon, 8 Jul 2019 17:37:19 -0600 Subject: [PATCH 203/335] Simplified Initialization and added Calibration Merged all the messy updates into the Firmware image and simplified the dmpinitialize() funciton Also added Calibration routines --- Arduino/MPU6050/MPU6050.cpp | 89 ++ Arduino/MPU6050/MPU6050.h | 7 + Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h | 1393 ++++++++--------- .../examples/MPU6050_DMP6/MPU6050_DMP6.ino | 27 +- 4 files changed, 723 insertions(+), 793 deletions(-) diff --git a/Arduino/MPU6050/MPU6050.cpp b/Arduino/MPU6050/MPU6050.cpp index 4500e169..547df8e0 100644 --- a/Arduino/MPU6050/MPU6050.cpp +++ b/Arduino/MPU6050/MPU6050.cpp @@ -3203,3 +3203,92 @@ uint8_t MPU6050::getDMPConfig2() { void MPU6050::setDMPConfig2(uint8_t config) { I2Cdev::writeByte(devAddr, MPU6050_RA_DMP_CFG_2, config); } + + +//*************************************************************************************** +//********************** Calibration Routines ********************** +//*************************************************************************************** +/** + @brief Fully calibrate Gyro from ZERO in about 6-7 Loops 600-700 readings +*/ +void MPU6050::CalibrateGyro(int Loops = 6) { + int16_t Reading, Offset; + float Error, PTerm, ITerm[3]; + double kP = 0.3; + double kI = 90; + float x; + x = (100 - map(Loops, 1, 5, 20, 0)) * .01; + kP *= x; + kI *= x; + + PID( 0x43, 0x13, kP, kI, Loops); +} + +/** + @brief Fully calibrate Accel from ZERO in about 6-7 Loops 600-700 readings +*/ +void MPU6050::CalibrateAccel(int Loops = 6) { +// int16_t Reading, Offset; +// float Error, PTerm, ITerm[3]; + double kP = 0.15; + double kI = 8; + float x; + x = (100 - map(Loops, 1, 5, 20, 0)) * .01; + kP *= x; + kI *= x; + PID( 0x3B, 0x06, kP, kI, Loops); +} + +void MPU6050::PID(uint8_t ReadAddress, uint8_t SaveAddress, float kP,float kI, uint8_t Loops) { + int16_t Reading, Offset; + float Error, PTerm, ITerm[3]; + float x; + for (int i = 0; i < 3; i++) { + I2Cdev::readWords(devAddr, SaveAddress + (i * 2), 1, &Reading); // reads 1 or more 16 bit integers (Word) +// MPUi2cReadInt(SaveAddress + (i * 2), &Reading); // XG_OFFSET_H_READ: Load the active Gyro offset to fine tune + ITerm[i] = Reading * 8; + } + for (int L = 0; L < Loops; L++) { + for (int c = 0; c < 100; c++) {// 100 PI Calculations + for (int i = 0; i < 3; i++) { + I2Cdev::readWords(devAddr, ReadAddress + (i * 2), 1, &Reading); // reads 1 or more 16 bit integers (Word) +// MPUi2cReadInt(ReadAddress + (i * 2), &Reading); + if ((ReadAddress == 0x3B)&&(i == 2)) Reading -= 16384; //remove Gravity + if (abs(Reading) < 25000) { + Error = 0 - Reading ; + PTerm = kP * Error; + ITerm[i] += Error * 0.002 * kI; // Integral term 1000 Calculations a second = 0.001 + Offset = round((PTerm + ITerm[i] ) / 8); //Compute PID Output + I2Cdev::writeWords(devAddr, SaveAddress + (i * 2), 1, &Offset); + // MPUi2cWriteInt(SaveAddress + (i * 2), Offset); + } + } + delay(1); + } + Serial.write('.'); + kP *= .95; + kI *= .95; + for (int i = 0; i < 3; i++){ + Offset = round((ITerm[i]) / 8); + I2Cdev::writeWords(devAddr, SaveAddress + (i * 2), 1, &Offset ); + // MPUi2cWriteInt(SaveAddress + (i * 2), round((ITerm[i]) / 8)); // ITerm is more of a running total rather than a reaction. + } + } + resetFIFO(); + resetDMP(); +} +#define printfloatx(Name,Variable,Spaces,Precision,EndTxt) Serial.print(F(Name)); {char S[(Spaces + Precision + 3)];Serial.print(F(" ")); Serial.print(dtostrf((float)Variable,Spaces,Precision ,S));}Serial.print(F(EndTxt));//Name,Variable,Spaces,Precision,EndTxt +void MPU6050::PrintActiveOffsets() { + int16_t Data[3]; + Serial.print(F("// X Accel Y Accel Z Accel X Gyro Y Gyro Z Gyro\nOFFSETS ")); + I2Cdev::readWords(devAddr, 0x06, 3, Data); +// A_OFFSET_H_READ_A_OFFS(Data); + printfloatx("", Data[0], 5, 0, ", "); + printfloatx("", Data[1], 5, 0, ", "); + printfloatx("", Data[2], 5, 0, ", "); + I2Cdev::readWords(devAddr, 0x13, 3, Data); +// XG_OFFSET_H_READ_OFFS_USR(Data); + printfloatx("", Data[0], 5, 0, ", "); + printfloatx("", Data[1], 5, 0, ", "); + printfloatx("", Data[2], 5, 0, "\n"); +} \ No newline at end of file diff --git a/Arduino/MPU6050/MPU6050.h b/Arduino/MPU6050/MPU6050.h index 3dd9a89b..1e4a734f 100644 --- a/Arduino/MPU6050/MPU6050.h +++ b/Arduino/MPU6050/MPU6050.h @@ -820,6 +820,13 @@ class MPU6050 { uint8_t getDMPConfig2(); void setDMPConfig2(uint8_t config); + // Calibration Routines + void CalibrateGyro(int Loops = 6); // Fine tune after setting offsets with less Loops. + void CalibrateAccel(int Loops = 6); // Fine tune after setting offsets with less Loops. + void PID(uint8_t ReadAddress, uint8_t SaveAddress, float kP,float kI, uint8_t Loops); // Does the math + void PrintActiveOffsets(); // See the results of the Calibration + + // special methods for MotionApps 2.0 implementation #ifdef MPU6050_INCLUDE_DMP_MOTIONAPPS20 diff --git a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h index 8b995cf9..487f63cd 100644 --- a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h +++ b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h @@ -1,782 +1,611 @@ -// I2Cdev library collection - MPU6050 I2C device class, 6-axis MotionApps 2.0 implementation -// Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00) -// 5/20/2013 by Jeff Rowberg -// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib -// -// Changelog: -// ... - ongoing debug release - -/* ============================================ -I2Cdev device library code is placed under the MIT license -Copyright (c) 2012 Jeff Rowberg - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -=============================================== -*/ - -#ifndef _MPU6050_6AXIS_MOTIONAPPS20_H_ -#define _MPU6050_6AXIS_MOTIONAPPS20_H_ - -#include "I2Cdev.h" -#include "helper_3dmath.h" - -// MotionApps 2.0 DMP implementation, built using the MPU-6050EVB evaluation board -#define MPU6050_INCLUDE_DMP_MOTIONAPPS20 - -#include "MPU6050.h" - -// Tom Carpenter's conditional PROGMEM code -// http://forum.arduino.cc/index.php?topic=129407.0 -#ifdef __AVR__ - #include -#else - // Teensy 3.0 library conditional PROGMEM code from Paul Stoffregen - #ifndef __PGMSPACE_H_ - #define __PGMSPACE_H_ 1 - #include - - #define PROGMEM - #define PGM_P const char * - #define PSTR(str) (str) - #define F(x) x - - typedef void prog_void; - typedef char prog_char; - typedef unsigned char prog_uchar; - typedef int8_t prog_int8_t; - typedef uint8_t prog_uint8_t; - typedef int16_t prog_int16_t; - typedef uint16_t prog_uint16_t; - typedef int32_t prog_int32_t; - typedef uint32_t prog_uint32_t; - - #define strcpy_P(dest, src) strcpy((dest), (src)) - #define strcat_P(dest, src) strcat((dest), (src)) - #define strcmp_P(a, b) strcmp((a), (b)) - - #define pgm_read_byte(addr) (*(const unsigned char *)(addr)) - #define pgm_read_word(addr) (*(const unsigned short *)(addr)) - #define pgm_read_dword(addr) (*(const unsigned long *)(addr)) - #define pgm_read_float(addr) (*(const float *)(addr)) - - #define pgm_read_byte_near(addr) pgm_read_byte(addr) - #define pgm_read_word_near(addr) pgm_read_word(addr) - #define pgm_read_dword_near(addr) pgm_read_dword(addr) - #define pgm_read_float_near(addr) pgm_read_float(addr) - #define pgm_read_byte_far(addr) pgm_read_byte(addr) - #define pgm_read_word_far(addr) pgm_read_word(addr) - #define pgm_read_dword_far(addr) pgm_read_dword(addr) - #define pgm_read_float_far(addr) pgm_read_float(addr) - #endif -#endif - -/* Source is from the InvenSense MotionApps v2 demo code. Original source is - * unavailable, unless you happen to be amazing as decompiling binary by - * hand (in which case, please contact me, and I'm totally serious). - * - * Also, I'd like to offer many, many thanks to Noah Zerkin for all of the - * DMP reverse-engineering he did to help make this bit of wizardry - * possible. - */ - -// NOTE! Enabling DEBUG adds about 3.3kB to the flash program size. -// Debug output is now working even on ATMega328P MCUs (e.g. Arduino Uno) -// after moving string constants to flash memory storage using the F() -// compiler macro (Arduino IDE 1.0+ required). - -//#define DEBUG -#ifdef DEBUG - #define DEBUG_PRINT(x) Serial.print(x) - #define DEBUG_PRINTF(x, y) Serial.print(x, y) - #define DEBUG_PRINTLN(x) Serial.println(x) - #define DEBUG_PRINTLNF(x, y) Serial.println(x, y) -#else - #define DEBUG_PRINT(x) - #define DEBUG_PRINTF(x, y) - #define DEBUG_PRINTLN(x) - #define DEBUG_PRINTLNF(x, y) -#endif - -#define MPU6050_DMP_CODE_SIZE 1929 // dmpMemory[] -#define MPU6050_DMP_CONFIG_SIZE 192 // dmpConfig[] -#define MPU6050_DMP_UPDATES_SIZE 47 // dmpUpdates[] - -/* ================================================================================================ * - | Default MotionApps v2.0 42-byte FIFO packet structure: | - | | - | [QUAT W][ ][QUAT X][ ][QUAT Y][ ][QUAT Z][ ][GYRO X][ ][GYRO Y][ ] | - | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | - | | - | [GYRO Z][ ][ACC X ][ ][ACC Y ][ ][ACC Z ][ ][ ] | - | 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | - * ================================================================================================ */ - -// this block of memory gets written to the MPU on start-up, and it seems -// to be volatile memory, so it has to be done each time (it only takes ~1 -// second though) -const unsigned char dmpMemory[MPU6050_DMP_CODE_SIZE] PROGMEM = { - // bank 0, 256 bytes - 0xFB, 0x00, 0x00, 0x3E, 0x00, 0x0B, 0x00, 0x36, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, - 0x00, 0x65, 0x00, 0x54, 0xFF, 0xEF, 0x00, 0x00, 0xFA, 0x80, 0x00, 0x0B, 0x12, 0x82, 0x00, 0x01, - 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x28, 0x00, 0x00, 0xFF, 0xFF, 0x45, 0x81, 0xFF, 0xFF, 0xFA, 0x72, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x03, 0xE8, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x7F, 0xFF, 0xFF, 0xFE, 0x80, 0x01, - 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x3E, 0x03, 0x30, 0x40, 0x00, 0x00, 0x00, 0x02, 0xCA, 0xE3, 0x09, 0x3E, 0x80, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, - 0x41, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x2A, 0x00, 0x00, 0x16, 0x55, 0x00, 0x00, 0x21, 0x82, - 0xFD, 0x87, 0x26, 0x50, 0xFD, 0x80, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x05, 0x80, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x6F, 0x00, 0x02, 0x65, 0x32, 0x00, 0x00, 0x5E, 0xC0, - 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFB, 0x8C, 0x6F, 0x5D, 0xFD, 0x5D, 0x08, 0xD9, 0x00, 0x7C, 0x73, 0x3B, 0x00, 0x6C, 0x12, 0xCC, - 0x32, 0x00, 0x13, 0x9D, 0x32, 0x00, 0xD0, 0xD6, 0x32, 0x00, 0x08, 0x00, 0x40, 0x00, 0x01, 0xF4, - 0xFF, 0xE6, 0x80, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0xD6, 0x00, 0x00, 0x27, 0x10, - - // bank 1, 256 bytes - 0xFB, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xFA, 0x36, 0xFF, 0xBC, 0x30, 0x8E, 0x00, 0x05, 0xFB, 0xF0, 0xFF, 0xD9, 0x5B, 0xC8, - 0xFF, 0xD0, 0x9A, 0xBE, 0x00, 0x00, 0x10, 0xA9, 0xFF, 0xF4, 0x1E, 0xB2, 0x00, 0xCE, 0xBB, 0xF7, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x0C, - 0xFF, 0xC2, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0xCF, 0x80, 0x00, 0x40, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x14, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x3F, 0x68, 0xB6, 0x79, 0x35, 0x28, 0xBC, 0xC6, 0x7E, 0xD1, 0x6C, - 0x80, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB2, 0x6A, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x25, 0x4D, 0x00, 0x2F, 0x70, 0x6D, 0x00, 0x00, 0x05, 0xAE, 0x00, 0x0C, 0x02, 0xD0, - - // bank 2, 256 bytes - 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x54, 0xFF, 0xEF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0xFF, 0xEF, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, - 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - - // bank 3, 256 bytes - 0xD8, 0xDC, 0xBA, 0xA2, 0xF1, 0xDE, 0xB2, 0xB8, 0xB4, 0xA8, 0x81, 0x91, 0xF7, 0x4A, 0x90, 0x7F, - 0x91, 0x6A, 0xF3, 0xF9, 0xDB, 0xA8, 0xF9, 0xB0, 0xBA, 0xA0, 0x80, 0xF2, 0xCE, 0x81, 0xF3, 0xC2, - 0xF1, 0xC1, 0xF2, 0xC3, 0xF3, 0xCC, 0xA2, 0xB2, 0x80, 0xF1, 0xC6, 0xD8, 0x80, 0xBA, 0xA7, 0xDF, - 0xDF, 0xDF, 0xF2, 0xA7, 0xC3, 0xCB, 0xC5, 0xB6, 0xF0, 0x87, 0xA2, 0x94, 0x24, 0x48, 0x70, 0x3C, - 0x95, 0x40, 0x68, 0x34, 0x58, 0x9B, 0x78, 0xA2, 0xF1, 0x83, 0x92, 0x2D, 0x55, 0x7D, 0xD8, 0xB1, - 0xB4, 0xB8, 0xA1, 0xD0, 0x91, 0x80, 0xF2, 0x70, 0xF3, 0x70, 0xF2, 0x7C, 0x80, 0xA8, 0xF1, 0x01, - 0xB0, 0x98, 0x87, 0xD9, 0x43, 0xD8, 0x86, 0xC9, 0x88, 0xBA, 0xA1, 0xF2, 0x0E, 0xB8, 0x97, 0x80, - 0xF1, 0xA9, 0xDF, 0xDF, 0xDF, 0xAA, 0xDF, 0xDF, 0xDF, 0xF2, 0xAA, 0xC5, 0xCD, 0xC7, 0xA9, 0x0C, - 0xC9, 0x2C, 0x97, 0x97, 0x97, 0x97, 0xF1, 0xA9, 0x89, 0x26, 0x46, 0x66, 0xB0, 0xB4, 0xBA, 0x80, - 0xAC, 0xDE, 0xF2, 0xCA, 0xF1, 0xB2, 0x8C, 0x02, 0xA9, 0xB6, 0x98, 0x00, 0x89, 0x0E, 0x16, 0x1E, - 0xB8, 0xA9, 0xB4, 0x99, 0x2C, 0x54, 0x7C, 0xB0, 0x8A, 0xA8, 0x96, 0x36, 0x56, 0x76, 0xF1, 0xB9, - 0xAF, 0xB4, 0xB0, 0x83, 0xC0, 0xB8, 0xA8, 0x97, 0x11, 0xB1, 0x8F, 0x98, 0xB9, 0xAF, 0xF0, 0x24, - 0x08, 0x44, 0x10, 0x64, 0x18, 0xF1, 0xA3, 0x29, 0x55, 0x7D, 0xAF, 0x83, 0xB5, 0x93, 0xAF, 0xF0, - 0x00, 0x28, 0x50, 0xF1, 0xA3, 0x86, 0x9F, 0x61, 0xA6, 0xDA, 0xDE, 0xDF, 0xD9, 0xFA, 0xA3, 0x86, - 0x96, 0xDB, 0x31, 0xA6, 0xD9, 0xF8, 0xDF, 0xBA, 0xA6, 0x8F, 0xC2, 0xC5, 0xC7, 0xB2, 0x8C, 0xC1, - 0xB8, 0xA2, 0xDF, 0xDF, 0xDF, 0xA3, 0xDF, 0xDF, 0xDF, 0xD8, 0xD8, 0xF1, 0xB8, 0xA8, 0xB2, 0x86, - - // bank 4, 256 bytes - 0xB4, 0x98, 0x0D, 0x35, 0x5D, 0xB8, 0xAA, 0x98, 0xB0, 0x87, 0x2D, 0x35, 0x3D, 0xB2, 0xB6, 0xBA, - 0xAF, 0x8C, 0x96, 0x19, 0x8F, 0x9F, 0xA7, 0x0E, 0x16, 0x1E, 0xB4, 0x9A, 0xB8, 0xAA, 0x87, 0x2C, - 0x54, 0x7C, 0xB9, 0xA3, 0xDE, 0xDF, 0xDF, 0xA3, 0xB1, 0x80, 0xF2, 0xC4, 0xCD, 0xC9, 0xF1, 0xB8, - 0xA9, 0xB4, 0x99, 0x83, 0x0D, 0x35, 0x5D, 0x89, 0xB9, 0xA3, 0x2D, 0x55, 0x7D, 0xB5, 0x93, 0xA3, - 0x0E, 0x16, 0x1E, 0xA9, 0x2C, 0x54, 0x7C, 0xB8, 0xB4, 0xB0, 0xF1, 0x97, 0x83, 0xA8, 0x11, 0x84, - 0xA5, 0x09, 0x98, 0xA3, 0x83, 0xF0, 0xDA, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0xD8, 0xF1, 0xA5, - 0x29, 0x55, 0x7D, 0xA5, 0x85, 0x95, 0x02, 0x1A, 0x2E, 0x3A, 0x56, 0x5A, 0x40, 0x48, 0xF9, 0xF3, - 0xA3, 0xD9, 0xF8, 0xF0, 0x98, 0x83, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0x97, 0x82, 0xA8, 0xF1, - 0x11, 0xF0, 0x98, 0xA2, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0xDA, 0xF3, 0xDE, 0xD8, 0x83, 0xA5, - 0x94, 0x01, 0xD9, 0xA3, 0x02, 0xF1, 0xA2, 0xC3, 0xC5, 0xC7, 0xD8, 0xF1, 0x84, 0x92, 0xA2, 0x4D, - 0xDA, 0x2A, 0xD8, 0x48, 0x69, 0xD9, 0x2A, 0xD8, 0x68, 0x55, 0xDA, 0x32, 0xD8, 0x50, 0x71, 0xD9, - 0x32, 0xD8, 0x70, 0x5D, 0xDA, 0x3A, 0xD8, 0x58, 0x79, 0xD9, 0x3A, 0xD8, 0x78, 0x93, 0xA3, 0x4D, - 0xDA, 0x2A, 0xD8, 0x48, 0x69, 0xD9, 0x2A, 0xD8, 0x68, 0x55, 0xDA, 0x32, 0xD8, 0x50, 0x71, 0xD9, - 0x32, 0xD8, 0x70, 0x5D, 0xDA, 0x3A, 0xD8, 0x58, 0x79, 0xD9, 0x3A, 0xD8, 0x78, 0xA8, 0x8A, 0x9A, - 0xF0, 0x28, 0x50, 0x78, 0x9E, 0xF3, 0x88, 0x18, 0xF1, 0x9F, 0x1D, 0x98, 0xA8, 0xD9, 0x08, 0xD8, - 0xC8, 0x9F, 0x12, 0x9E, 0xF3, 0x15, 0xA8, 0xDA, 0x12, 0x10, 0xD8, 0xF1, 0xAF, 0xC8, 0x97, 0x87, - - // bank 5, 256 bytes - 0x34, 0xB5, 0xB9, 0x94, 0xA4, 0x21, 0xF3, 0xD9, 0x22, 0xD8, 0xF2, 0x2D, 0xF3, 0xD9, 0x2A, 0xD8, - 0xF2, 0x35, 0xF3, 0xD9, 0x32, 0xD8, 0x81, 0xA4, 0x60, 0x60, 0x61, 0xD9, 0x61, 0xD8, 0x6C, 0x68, - 0x69, 0xD9, 0x69, 0xD8, 0x74, 0x70, 0x71, 0xD9, 0x71, 0xD8, 0xB1, 0xA3, 0x84, 0x19, 0x3D, 0x5D, - 0xA3, 0x83, 0x1A, 0x3E, 0x5E, 0x93, 0x10, 0x30, 0x81, 0x10, 0x11, 0xB8, 0xB0, 0xAF, 0x8F, 0x94, - 0xF2, 0xDA, 0x3E, 0xD8, 0xB4, 0x9A, 0xA8, 0x87, 0x29, 0xDA, 0xF8, 0xD8, 0x87, 0x9A, 0x35, 0xDA, - 0xF8, 0xD8, 0x87, 0x9A, 0x3D, 0xDA, 0xF8, 0xD8, 0xB1, 0xB9, 0xA4, 0x98, 0x85, 0x02, 0x2E, 0x56, - 0xA5, 0x81, 0x00, 0x0C, 0x14, 0xA3, 0x97, 0xB0, 0x8A, 0xF1, 0x2D, 0xD9, 0x28, 0xD8, 0x4D, 0xD9, - 0x48, 0xD8, 0x6D, 0xD9, 0x68, 0xD8, 0xB1, 0x84, 0x0D, 0xDA, 0x0E, 0xD8, 0xA3, 0x29, 0x83, 0xDA, - 0x2C, 0x0E, 0xD8, 0xA3, 0x84, 0x49, 0x83, 0xDA, 0x2C, 0x4C, 0x0E, 0xD8, 0xB8, 0xB0, 0xA8, 0x8A, - 0x9A, 0xF5, 0x20, 0xAA, 0xDA, 0xDF, 0xD8, 0xA8, 0x40, 0xAA, 0xD0, 0xDA, 0xDE, 0xD8, 0xA8, 0x60, - 0xAA, 0xDA, 0xD0, 0xDF, 0xD8, 0xF1, 0x97, 0x86, 0xA8, 0x31, 0x9B, 0x06, 0x99, 0x07, 0xAB, 0x97, - 0x28, 0x88, 0x9B, 0xF0, 0x0C, 0x20, 0x14, 0x40, 0xB8, 0xB0, 0xB4, 0xA8, 0x8C, 0x9C, 0xF0, 0x04, - 0x28, 0x51, 0x79, 0x1D, 0x30, 0x14, 0x38, 0xB2, 0x82, 0xAB, 0xD0, 0x98, 0x2C, 0x50, 0x50, 0x78, - 0x78, 0x9B, 0xF1, 0x1A, 0xB0, 0xF0, 0x8A, 0x9C, 0xA8, 0x29, 0x51, 0x79, 0x8B, 0x29, 0x51, 0x79, - 0x8A, 0x24, 0x70, 0x59, 0x8B, 0x20, 0x58, 0x71, 0x8A, 0x44, 0x69, 0x38, 0x8B, 0x39, 0x40, 0x68, - 0x8A, 0x64, 0x48, 0x31, 0x8B, 0x30, 0x49, 0x60, 0xA5, 0x88, 0x20, 0x09, 0x71, 0x58, 0x44, 0x68, - - // bank 6, 256 bytes - 0x11, 0x39, 0x64, 0x49, 0x30, 0x19, 0xF1, 0xAC, 0x00, 0x2C, 0x54, 0x7C, 0xF0, 0x8C, 0xA8, 0x04, - 0x28, 0x50, 0x78, 0xF1, 0x88, 0x97, 0x26, 0xA8, 0x59, 0x98, 0xAC, 0x8C, 0x02, 0x26, 0x46, 0x66, - 0xF0, 0x89, 0x9C, 0xA8, 0x29, 0x51, 0x79, 0x24, 0x70, 0x59, 0x44, 0x69, 0x38, 0x64, 0x48, 0x31, - 0xA9, 0x88, 0x09, 0x20, 0x59, 0x70, 0xAB, 0x11, 0x38, 0x40, 0x69, 0xA8, 0x19, 0x31, 0x48, 0x60, - 0x8C, 0xA8, 0x3C, 0x41, 0x5C, 0x20, 0x7C, 0x00, 0xF1, 0x87, 0x98, 0x19, 0x86, 0xA8, 0x6E, 0x76, - 0x7E, 0xA9, 0x99, 0x88, 0x2D, 0x55, 0x7D, 0x9E, 0xB9, 0xA3, 0x8A, 0x22, 0x8A, 0x6E, 0x8A, 0x56, - 0x8A, 0x5E, 0x9F, 0xB1, 0x83, 0x06, 0x26, 0x46, 0x66, 0x0E, 0x2E, 0x4E, 0x6E, 0x9D, 0xB8, 0xAD, - 0x00, 0x2C, 0x54, 0x7C, 0xF2, 0xB1, 0x8C, 0xB4, 0x99, 0xB9, 0xA3, 0x2D, 0x55, 0x7D, 0x81, 0x91, - 0xAC, 0x38, 0xAD, 0x3A, 0xB5, 0x83, 0x91, 0xAC, 0x2D, 0xD9, 0x28, 0xD8, 0x4D, 0xD9, 0x48, 0xD8, - 0x6D, 0xD9, 0x68, 0xD8, 0x8C, 0x9D, 0xAE, 0x29, 0xD9, 0x04, 0xAE, 0xD8, 0x51, 0xD9, 0x04, 0xAE, - 0xD8, 0x79, 0xD9, 0x04, 0xD8, 0x81, 0xF3, 0x9D, 0xAD, 0x00, 0x8D, 0xAE, 0x19, 0x81, 0xAD, 0xD9, - 0x01, 0xD8, 0xF2, 0xAE, 0xDA, 0x26, 0xD8, 0x8E, 0x91, 0x29, 0x83, 0xA7, 0xD9, 0xAD, 0xAD, 0xAD, - 0xAD, 0xF3, 0x2A, 0xD8, 0xD8, 0xF1, 0xB0, 0xAC, 0x89, 0x91, 0x3E, 0x5E, 0x76, 0xF3, 0xAC, 0x2E, - 0x2E, 0xF1, 0xB1, 0x8C, 0x5A, 0x9C, 0xAC, 0x2C, 0x28, 0x28, 0x28, 0x9C, 0xAC, 0x30, 0x18, 0xA8, - 0x98, 0x81, 0x28, 0x34, 0x3C, 0x97, 0x24, 0xA7, 0x28, 0x34, 0x3C, 0x9C, 0x24, 0xF2, 0xB0, 0x89, - 0xAC, 0x91, 0x2C, 0x4C, 0x6C, 0x8A, 0x9B, 0x2D, 0xD9, 0xD8, 0xD8, 0x51, 0xD9, 0xD8, 0xD8, 0x79, - - // bank 7, 138 bytes (remainder) - 0xD9, 0xD8, 0xD8, 0xF1, 0x9E, 0x88, 0xA3, 0x31, 0xDA, 0xD8, 0xD8, 0x91, 0x2D, 0xD9, 0x28, 0xD8, - 0x4D, 0xD9, 0x48, 0xD8, 0x6D, 0xD9, 0x68, 0xD8, 0xB1, 0x83, 0x93, 0x35, 0x3D, 0x80, 0x25, 0xDA, - 0xD8, 0xD8, 0x85, 0x69, 0xDA, 0xD8, 0xD8, 0xB4, 0x93, 0x81, 0xA3, 0x28, 0x34, 0x3C, 0xF3, 0xAB, - 0x8B, 0xF8, 0xA3, 0x91, 0xB6, 0x09, 0xB4, 0xD9, 0xAB, 0xDE, 0xFA, 0xB0, 0x87, 0x9C, 0xB9, 0xA3, - 0xDD, 0xF1, 0xA3, 0xA3, 0xA3, 0xA3, 0x95, 0xF1, 0xA3, 0xA3, 0xA3, 0x9D, 0xF1, 0xA3, 0xA3, 0xA3, - 0xA3, 0xF2, 0xA3, 0xB4, 0x90, 0x80, 0xF2, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, - 0xA3, 0xB2, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xB0, 0x87, 0xB5, 0x99, 0xF1, 0xA3, 0xA3, 0xA3, - 0x98, 0xF1, 0xA3, 0xA3, 0xA3, 0xA3, 0x97, 0xA3, 0xA3, 0xA3, 0xA3, 0xF3, 0x9B, 0xA3, 0xA3, 0xDC, - 0xB9, 0xA7, 0xF1, 0x26, 0x26, 0x26, 0xD8, 0xD8, 0xFF -}; - -#ifndef MPU6050_DMP_FIFO_RATE_DIVISOR -#define MPU6050_DMP_FIFO_RATE_DIVISOR 0x01 -#endif - -// thanks to Noah Zerkin for piecing this stuff together! -const unsigned char dmpConfig[MPU6050_DMP_CONFIG_SIZE] PROGMEM = { -// BANK OFFSET LENGTH [DATA] - 0x03, 0x7B, 0x03, 0x4C, 0xCD, 0x6C, // FCFG_1 inv_set_gyro_calibration - 0x03, 0xAB, 0x03, 0x36, 0x56, 0x76, // FCFG_3 inv_set_gyro_calibration - 0x00, 0x68, 0x04, 0x02, 0xCB, 0x47, 0xA2, // D_0_104 inv_set_gyro_calibration - 0x02, 0x18, 0x04, 0x00, 0x05, 0x8B, 0xC1, // D_0_24 inv_set_gyro_calibration - 0x01, 0x0C, 0x04, 0x00, 0x00, 0x00, 0x00, // D_1_152 inv_set_accel_calibration - 0x03, 0x7F, 0x06, 0x0C, 0xC9, 0x2C, 0x97, 0x97, 0x97, // FCFG_2 inv_set_accel_calibration - 0x03, 0x89, 0x03, 0x26, 0x46, 0x66, // FCFG_7 inv_set_accel_calibration - 0x00, 0x6C, 0x02, 0x20, 0x00, // D_0_108 inv_set_accel_calibration - 0x02, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_00 inv_set_compass_calibration - 0x02, 0x44, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_01 - 0x02, 0x48, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_02 - 0x02, 0x4C, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_10 - 0x02, 0x50, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_11 - 0x02, 0x54, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_12 - 0x02, 0x58, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_20 - 0x02, 0x5C, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_21 - 0x02, 0xBC, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_22 - 0x01, 0xEC, 0x04, 0x00, 0x00, 0x40, 0x00, // D_1_236 inv_apply_endian_accel - 0x03, 0x7F, 0x06, 0x0C, 0xC9, 0x2C, 0x97, 0x97, 0x97, // FCFG_2 inv_set_mpu_sensors - 0x04, 0x02, 0x03, 0x0D, 0x35, 0x5D, // CFG_MOTION_BIAS inv_turn_on_bias_from_no_motion - 0x04, 0x09, 0x04, 0x87, 0x2D, 0x35, 0x3D, // FCFG_5 inv_set_bias_update - 0x00, 0xA3, 0x01, 0x00, // D_0_163 inv_set_dead_zone - // SPECIAL 0x01 = enable interrupts - 0x00, 0x00, 0x00, 0x01, // SET INT_ENABLE at i=22, SPECIAL INSTRUCTION - 0x07, 0x86, 0x01, 0xFE, // CFG_6 inv_set_fifo_interupt - 0x07, 0x41, 0x05, 0xF1, 0x20, 0x28, 0x30, 0x38, // CFG_8 inv_send_quaternion - 0x07, 0x7E, 0x01, 0x30, // CFG_16 inv_set_footer - 0x07, 0x46, 0x01, 0x9A, // CFG_GYRO_SOURCE inv_send_gyro - 0x07, 0x47, 0x04, 0xF1, 0x28, 0x30, 0x38, // CFG_9 inv_send_gyro -> inv_construct3_fifo - 0x07, 0x6C, 0x04, 0xF1, 0x28, 0x30, 0x38, // CFG_12 inv_send_accel -> inv_construct3_fifo - 0x02, 0x16, 0x02, 0x00, MPU6050_DMP_FIFO_RATE_DIVISOR // D_0_22 inv_set_fifo_rate - - // This very last 0x01 WAS a 0x09, which drops the FIFO rate down to 20 Hz. 0x07 is 25 Hz, - // 0x01 is 100Hz. Going faster than 100Hz (0x00=200Hz) tends to result in very noisy data. - // DMP output frequency is calculated easily using this equation: (200Hz / (1 + value)) - - // It is important to make sure the host processor can keep up with reading and processing - // the FIFO output at the desired rate. Handling FIFO overflow cleanly is also a good idea. -}; - -const unsigned char dmpUpdates[MPU6050_DMP_UPDATES_SIZE] PROGMEM = { - 0x01, 0xB2, 0x02, 0xFF, 0xFF, - 0x01, 0x90, 0x04, 0x09, 0x23, 0xA1, 0x35, - 0x01, 0x6A, 0x02, 0x06, 0x00, - 0x01, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x60, 0x04, 0x40, 0x00, 0x00, 0x00, - 0x01, 0x62, 0x02, 0x00, 0x00, - 0x00, 0x60, 0x04, 0x00, 0x40, 0x00, 0x00 -}; - -uint8_t MPU6050::dmpInitialize() { - // reset device - DEBUG_PRINTLN(F("\n\nResetting MPU6050...")); - reset(); - delay(30); // wait after reset - - // enable sleep mode and wake cycle - /*Serial.println(F("Enabling sleep mode...")); - setSleepEnabled(true); - Serial.println(F("Enabling wake cycle...")); - setWakeCycleEnabled(true);*/ - - // disable sleep mode - DEBUG_PRINTLN(F("Disabling sleep mode...")); - setSleepEnabled(false); - - // get MPU hardware revision - DEBUG_PRINTLN(F("Selecting user bank 16...")); - setMemoryBank(0x10, true, true); - DEBUG_PRINTLN(F("Selecting memory byte 6...")); - setMemoryStartAddress(0x06); - DEBUG_PRINTLN(F("Checking hardware revision...")); - DEBUG_PRINT(F("Revision @ user[16][6] = ")); - DEBUG_PRINTLNF(readMemoryByte(), HEX); - DEBUG_PRINTLN(F("Resetting memory bank selection to 0...")); - setMemoryBank(0, false, false); - - // check OTP bank valid - DEBUG_PRINTLN(F("Reading OTP bank valid flag...")); - DEBUG_PRINT(F("OTP bank is ")); - DEBUG_PRINTLN(getOTPBankValid() ? F("valid!") : F("invalid!")); - - // get X/Y/Z gyro offsets - DEBUG_PRINTLN(F("Reading gyro offset TC values...")); - int8_t xgOffsetTC = getXGyroOffsetTC(); - int8_t ygOffsetTC = getYGyroOffsetTC(); - int8_t zgOffsetTC = getZGyroOffsetTC(); - DEBUG_PRINT(F("X gyro offset = ")); - DEBUG_PRINTLN(xgOffsetTC); - DEBUG_PRINT(F("Y gyro offset = ")); - DEBUG_PRINTLN(ygOffsetTC); - DEBUG_PRINT(F("Z gyro offset = ")); - DEBUG_PRINTLN(zgOffsetTC); - - // setup weird slave stuff (?) - DEBUG_PRINTLN(F("Setting slave 0 address to 0x7F...")); - setSlaveAddress(0, 0x7F); - DEBUG_PRINTLN(F("Disabling I2C Master mode...")); - setI2CMasterModeEnabled(false); - DEBUG_PRINTLN(F("Setting slave 0 address to 0x68 (self)...")); - setSlaveAddress(0, 0x68); - DEBUG_PRINTLN(F("Resetting I2C Master control...")); - resetI2CMaster(); - delay(20); - - // load DMP code into memory banks - DEBUG_PRINT(F("Writing DMP code to MPU memory banks (")); - DEBUG_PRINT(MPU6050_DMP_CODE_SIZE); - DEBUG_PRINTLN(F(" bytes)")); - if (writeProgMemoryBlock(dmpMemory, MPU6050_DMP_CODE_SIZE)) { - DEBUG_PRINTLN(F("Success! DMP code written and verified.")); - - // write DMP configuration - DEBUG_PRINT(F("Writing DMP configuration to MPU memory banks (")); - DEBUG_PRINT(MPU6050_DMP_CONFIG_SIZE); - DEBUG_PRINTLN(F(" bytes in config def)")); - if (writeProgDMPConfigurationSet(dmpConfig, MPU6050_DMP_CONFIG_SIZE)) { - DEBUG_PRINTLN(F("Success! DMP configuration written and verified.")); - - DEBUG_PRINTLN(F("Setting clock source to Z Gyro...")); - setClockSource(MPU6050_CLOCK_PLL_ZGYRO); - - DEBUG_PRINTLN(F("Setting DMP and FIFO_OFLOW interrupts enabled...")); - setIntEnabled(1< 2...")); - while ((fifoCount = getFIFOCount()) < 3); - - DEBUG_PRINT(F("Current FIFO count=")); - DEBUG_PRINTLN(fifoCount); - DEBUG_PRINTLN(F("Reading FIFO data...")); - getFIFOBytes(fifoBuffer, fifoCount); - - DEBUG_PRINTLN(F("Reading interrupt status...")); - - DEBUG_PRINT(F("Current interrupt status=")); - DEBUG_PRINTLNF(getIntStatus(), HEX); - - DEBUG_PRINTLN(F("Reading final memory update 6/7 (function unknown)...")); - for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); - readMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); - - DEBUG_PRINTLN(F("Waiting for FIFO count > 2...")); - while ((fifoCount = getFIFOCount()) < 3); - - DEBUG_PRINT(F("Current FIFO count=")); - DEBUG_PRINTLN(fifoCount); - - DEBUG_PRINTLN(F("Reading FIFO data...")); - getFIFOBytes(fifoBuffer, fifoCount); - - DEBUG_PRINTLN(F("Reading interrupt status...")); - - DEBUG_PRINT(F("Current interrupt status=")); - DEBUG_PRINTLNF(getIntStatus(), HEX); - - DEBUG_PRINTLN(F("Writing final memory update 7/7 (function unknown)...")); - for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); - writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); - - DEBUG_PRINTLN(F("DMP is good to go! Finally.")); - - DEBUG_PRINTLN(F("Disabling DMP (you turn it on later)...")); - setDMPEnabled(false); - - DEBUG_PRINTLN(F("Setting up internal 42-byte (default) DMP packet buffer...")); - dmpPacketSize = 42; - /*if ((dmpPacketBuffer = (uint8_t *)malloc(42)) == 0) { - return 3; // TODO: proper error code for no memory - }*/ - - DEBUG_PRINTLN(F("Resetting FIFO and clearing INT status one last time...")); - resetFIFO(); - getIntStatus(); - } else { - DEBUG_PRINTLN(F("ERROR! DMP configuration verification failed.")); - return 2; // configuration block loading failed - } - } else { - DEBUG_PRINTLN(F("ERROR! DMP code verification failed.")); - return 1; // main binary block loading failed - } - return 0; // success -} - -bool MPU6050::dmpPacketAvailable() { - return getFIFOCount() >= dmpGetFIFOPacketSize(); -} - -// uint8_t MPU6050::dmpSetFIFORate(uint8_t fifoRate); -// uint8_t MPU6050::dmpGetFIFORate(); -// uint8_t MPU6050::dmpGetSampleStepSizeMS(); -// uint8_t MPU6050::dmpGetSampleFrequency(); -// int32_t MPU6050::dmpDecodeTemperature(int8_t tempReg); - -//uint8_t MPU6050::dmpRegisterFIFORateProcess(inv_obj_func func, int16_t priority); -//uint8_t MPU6050::dmpUnregisterFIFORateProcess(inv_obj_func func); -//uint8_t MPU6050::dmpRunFIFORateProcesses(); - -// uint8_t MPU6050::dmpSendQuaternion(uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendGyro(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendAccel(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendLinearAccel(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendLinearAccelInWorld(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendControlData(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendSensorData(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendExternalSensorData(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendGravity(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendPacketNumber(uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendQuantizedAccel(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendEIS(uint_fast16_t elements, uint_fast16_t accuracy); - -uint8_t MPU6050::dmpGetAccel(int32_t *data, const uint8_t* packet) { - // TODO: accommodate different arrangements of sent data (ONLY default supported now) - if (packet == 0) packet = dmpPacketBuffer; - data[0] = (((uint32_t)packet[28] << 24) | ((uint32_t)packet[29] << 16) | ((uint32_t)packet[30] << 8) | packet[31]); - data[1] = (((uint32_t)packet[32] << 24) | ((uint32_t)packet[33] << 16) | ((uint32_t)packet[34] << 8) | packet[35]); - data[2] = (((uint32_t)packet[36] << 24) | ((uint32_t)packet[37] << 16) | ((uint32_t)packet[38] << 8) | packet[39]); - return 0; -} -uint8_t MPU6050::dmpGetAccel(int16_t *data, const uint8_t* packet) { - // TODO: accommodate different arrangements of sent data (ONLY default supported now) - if (packet == 0) packet = dmpPacketBuffer; - data[0] = (packet[28] << 8) | packet[29]; - data[1] = (packet[32] << 8) | packet[33]; - data[2] = (packet[36] << 8) | packet[37]; - return 0; -} -uint8_t MPU6050::dmpGetAccel(VectorInt16 *v, const uint8_t* packet) { - // TODO: accommodate different arrangements of sent data (ONLY default supported now) - if (packet == 0) packet = dmpPacketBuffer; - v -> x = (packet[28] << 8) | packet[29]; - v -> y = (packet[32] << 8) | packet[33]; - v -> z = (packet[36] << 8) | packet[37]; - return 0; -} -uint8_t MPU6050::dmpGetQuaternion(int32_t *data, const uint8_t* packet) { - // TODO: accommodate different arrangements of sent data (ONLY default supported now) - if (packet == 0) packet = dmpPacketBuffer; - data[0] = (((uint32_t)packet[0] << 24) | ((uint32_t)packet[1] << 16) | ((uint32_t)packet[2] << 8) | packet[3]); - data[1] = (((uint32_t)packet[4] << 24) | ((uint32_t)packet[5] << 16) | ((uint32_t)packet[6] << 8) | packet[7]); - data[2] = (((uint32_t)packet[8] << 24) | ((uint32_t)packet[9] << 16) | ((uint32_t)packet[10] << 8) | packet[11]); - data[3] = (((uint32_t)packet[12] << 24) | ((uint32_t)packet[13] << 16) | ((uint32_t)packet[14] << 8) | packet[15]); - return 0; -} -uint8_t MPU6050::dmpGetQuaternion(int16_t *data, const uint8_t* packet) { - // TODO: accommodate different arrangements of sent data (ONLY default supported now) - if (packet == 0) packet = dmpPacketBuffer; - data[0] = ((packet[0] << 8) | packet[1]); - data[1] = ((packet[4] << 8) | packet[5]); - data[2] = ((packet[8] << 8) | packet[9]); - data[3] = ((packet[12] << 8) | packet[13]); - return 0; -} -uint8_t MPU6050::dmpGetQuaternion(Quaternion *q, const uint8_t* packet) { - // TODO: accommodate different arrangements of sent data (ONLY default supported now) - int16_t qI[4]; - uint8_t status = dmpGetQuaternion(qI, packet); - if (status == 0) { - q -> w = (float)qI[0] / 16384.0f; - q -> x = (float)qI[1] / 16384.0f; - q -> y = (float)qI[2] / 16384.0f; - q -> z = (float)qI[3] / 16384.0f; - return 0; - } - return status; // int16 return value, indicates error if this line is reached -} -// uint8_t MPU6050::dmpGet6AxisQuaternion(long *data, const uint8_t* packet); -// uint8_t MPU6050::dmpGetRelativeQuaternion(long *data, const uint8_t* packet); -uint8_t MPU6050::dmpGetGyro(int32_t *data, const uint8_t* packet) { - // TODO: accommodate different arrangements of sent data (ONLY default supported now) - if (packet == 0) packet = dmpPacketBuffer; - data[0] = (((uint32_t)packet[16] << 24) | ((uint32_t)packet[17] << 16) | ((uint32_t)packet[18] << 8) | packet[19]); - data[1] = (((uint32_t)packet[20] << 24) | ((uint32_t)packet[21] << 16) | ((uint32_t)packet[22] << 8) | packet[23]); - data[2] = (((uint32_t)packet[24] << 24) | ((uint32_t)packet[25] << 16) | ((uint32_t)packet[26] << 8) | packet[27]); - return 0; -} -uint8_t MPU6050::dmpGetGyro(int16_t *data, const uint8_t* packet) { - // TODO: accommodate different arrangements of sent data (ONLY default supported now) - if (packet == 0) packet = dmpPacketBuffer; - data[0] = (packet[16] << 8) | packet[17]; - data[1] = (packet[20] << 8) | packet[21]; - data[2] = (packet[24] << 8) | packet[25]; - return 0; -} -uint8_t MPU6050::dmpGetGyro(VectorInt16 *v, const uint8_t* packet) { - // TODO: accommodate different arrangements of sent data (ONLY default supported now) - if (packet == 0) packet = dmpPacketBuffer; - v -> x = (packet[16] << 8) | packet[17]; - v -> y = (packet[20] << 8) | packet[21]; - v -> z = (packet[24] << 8) | packet[25]; - return 0; -} -// uint8_t MPU6050::dmpSetLinearAccelFilterCoefficient(float coef); -// uint8_t MPU6050::dmpGetLinearAccel(long *data, const uint8_t* packet); -uint8_t MPU6050::dmpGetLinearAccel(VectorInt16 *v, VectorInt16 *vRaw, VectorFloat *gravity) { - // get rid of the gravity component (+1g = +8192 in standard DMP FIFO packet, sensitivity is 2g) - v -> x = vRaw -> x - gravity -> x*8192; - v -> y = vRaw -> y - gravity -> y*8192; - v -> z = vRaw -> z - gravity -> z*8192; - return 0; -} -// uint8_t MPU6050::dmpGetLinearAccelInWorld(long *data, const uint8_t* packet); -uint8_t MPU6050::dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Quaternion *q) { - // rotate measured 3D acceleration vector into original state - // frame of reference based on orientation quaternion - memcpy(v, vReal, sizeof(VectorInt16)); - v -> rotate(q); - return 0; -} -// uint8_t MPU6050::dmpGetGyroAndAccelSensor(long *data, const uint8_t* packet); -// uint8_t MPU6050::dmpGetGyroSensor(long *data, const uint8_t* packet); -// uint8_t MPU6050::dmpGetControlData(long *data, const uint8_t* packet); -// uint8_t MPU6050::dmpGetTemperature(long *data, const uint8_t* packet); -// uint8_t MPU6050::dmpGetGravity(long *data, const uint8_t* packet); -uint8_t MPU6050::dmpGetGravity(int16_t *data, const uint8_t* packet) { - /* +1g corresponds to +8192, sensitivity is 2g. */ - int16_t qI[4]; - uint8_t status = dmpGetQuaternion(qI, packet); - data[0] = ((int32_t)qI[1] * qI[3] - (int32_t)qI[0] * qI[2]) / 16384; - data[1] = ((int32_t)qI[0] * qI[1] + (int32_t)qI[2] * qI[3]) / 16384; - data[2] = ((int32_t)qI[0] * qI[0] - (int32_t)qI[1] * qI[1] - - (int32_t)qI[2] * qI[2] + (int32_t)qI[3] * qI[3]) / (2 * 16384); - return status; -} - -uint8_t MPU6050::dmpGetGravity(VectorFloat *v, Quaternion *q) { - v -> x = 2 * (q -> x*q -> z - q -> w*q -> y); - v -> y = 2 * (q -> w*q -> x + q -> y*q -> z); - v -> z = q -> w*q -> w - q -> x*q -> x - q -> y*q -> y + q -> z*q -> z; - return 0; -} -// uint8_t MPU6050::dmpGetUnquantizedAccel(long *data, const uint8_t* packet); -// uint8_t MPU6050::dmpGetQuantizedAccel(long *data, const uint8_t* packet); -// uint8_t MPU6050::dmpGetExternalSensorData(long *data, int size, const uint8_t* packet); -// uint8_t MPU6050::dmpGetEIS(long *data, const uint8_t* packet); - -uint8_t MPU6050::dmpGetEuler(float *data, Quaternion *q) { - data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1); // psi - data[1] = -asin(2*q -> x*q -> z + 2*q -> w*q -> y); // theta - data[2] = atan2(2*q -> y*q -> z - 2*q -> w*q -> x, 2*q -> w*q -> w + 2*q -> z*q -> z - 1); // phi - return 0; -} - -#ifdef USE_OLD_DMPGETYAWPITCHROLL -uint8_t MPU6050::dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity) { - // yaw: (about Z axis) - data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1); - // pitch: (nose up/down, about Y axis) - data[1] = atan(gravity -> x / sqrt(gravity -> y*gravity -> y + gravity -> z*gravity -> z)); - // roll: (tilt left/right, about X axis) - data[2] = atan(gravity -> y / sqrt(gravity -> x*gravity -> x + gravity -> z*gravity -> z)); - return 0; -} -#else -uint8_t MPU6050::dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity) { - // yaw: (about Z axis) - data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1); - // pitch: (nose up/down, about Y axis) - data[1] = atan2(gravity -> x , sqrt(gravity -> y*gravity -> y + gravity -> z*gravity -> z)); - // roll: (tilt left/right, about X axis) - data[2] = atan2(gravity -> y , gravity -> z); - if (gravity -> z < 0) { - if(data[1] > 0) { - data[1] = PI - data[1]; - } else { - data[1] = -PI - data[1]; - } - } - return 0; -} -#endif - -// uint8_t MPU6050::dmpGetAccelFloat(float *data, const uint8_t* packet); -// uint8_t MPU6050::dmpGetQuaternionFloat(float *data, const uint8_t* packet); - -uint8_t MPU6050::dmpProcessFIFOPacket(const unsigned char *dmpData) { - /*for (uint8_t k = 0; k < dmpPacketSize; k++) { - if (dmpData[k] < 0x10) Serial.print("0"); - Serial.print(dmpData[k], HEX); - Serial.print(" "); - } - Serial.print("\n");*/ - //Serial.println((uint16_t)dmpPacketBuffer); - return 0; -} -uint8_t MPU6050::dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *processed) { - uint8_t status; - uint8_t buf[dmpPacketSize]; - for (uint8_t i = 0; i < numPackets; i++) { - // read packet from FIFO - getFIFOBytes(buf, dmpPacketSize); - - // process packet - if ((status = dmpProcessFIFOPacket(buf)) > 0) return status; - - // increment external process count variable, if supplied - if (processed != 0) (*processed)++; - } - return 0; -} - -// uint8_t MPU6050::dmpSetFIFOProcessedCallback(void (*func) (void)); - -// uint8_t MPU6050::dmpInitFIFOParam(); -// uint8_t MPU6050::dmpCloseFIFO(); -// uint8_t MPU6050::dmpSetGyroDataSource(uint_fast8_t source); -// uint8_t MPU6050::dmpDecodeQuantizedAccel(); -// uint32_t MPU6050::dmpGetGyroSumOfSquare(); -// uint32_t MPU6050::dmpGetAccelSumOfSquare(); -// void MPU6050::dmpOverrideQuaternion(long *q); -uint16_t MPU6050::dmpGetFIFOPacketSize() { - return dmpPacketSize; -} - -#endif /* _MPU6050_6AXIS_MOTIONAPPS20_H_ */ +// I2Cdev library collection - MPU6050 I2C device class, 6-axis MotionApps 2.0 implementation +// Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00) +// 5/20/2013 by Jeff Rowberg +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// ... - ongoing debug release + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2012 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#ifndef _MPU6050_6AXIS_MOTIONAPPS20_H_ +#define _MPU6050_6AXIS_MOTIONAPPS20_H_ + +#include "I2Cdev.h" +#include "helper_3dmath.h" + +// MotionApps 2.0 DMP implementation, built using the MPU-6050EVB evaluation board +#define MPU6050_INCLUDE_DMP_MOTIONAPPS20 + +#include "MPU6050.h" + +// Tom Carpenter's conditional PROGMEM code +// http://forum.arduino.cc/index.php?topic=129407.0 +#ifdef __AVR__ + #include +#else + // Teensy 3.0 library conditional PROGMEM code from Paul Stoffregen + #ifndef __PGMSPACE_H_ + #define __PGMSPACE_H_ 1 + #include + + #define PROGMEM + #define PGM_P const char * + #define PSTR(str) (str) + #define F(x) x + + typedef void prog_void; + typedef char prog_char; + typedef unsigned char prog_uchar; + typedef int8_t prog_int8_t; + typedef uint8_t prog_uint8_t; + typedef int16_t prog_int16_t; + typedef uint16_t prog_uint16_t; + typedef int32_t prog_int32_t; + typedef uint32_t prog_uint32_t; + + #define strcpy_P(dest, src) strcpy((dest), (src)) + #define strcat_P(dest, src) strcat((dest), (src)) + #define strcmp_P(a, b) strcmp((a), (b)) + + #define pgm_read_byte(addr) (*(const unsigned char *)(addr)) + #define pgm_read_word(addr) (*(const unsigned short *)(addr)) + #define pgm_read_dword(addr) (*(const unsigned long *)(addr)) + #define pgm_read_float(addr) (*(const float *)(addr)) + + #define pgm_read_byte_near(addr) pgm_read_byte(addr) + #define pgm_read_word_near(addr) pgm_read_word(addr) + #define pgm_read_dword_near(addr) pgm_read_dword(addr) + #define pgm_read_float_near(addr) pgm_read_float(addr) + #define pgm_read_byte_far(addr) pgm_read_byte(addr) + #define pgm_read_word_far(addr) pgm_read_word(addr) + #define pgm_read_dword_far(addr) pgm_read_dword(addr) + #define pgm_read_float_far(addr) pgm_read_float(addr) + #endif +#endif + +/* Source is from the InvenSense MotionApps v2 demo code. Original source is + * unavailable, unless you happen to be amazing as decompiling binary by + * hand (in which case, please contact me, and I'm totally serious). + * + * Also, I'd like to offer many, many thanks to Noah Zerkin for all of the + * DMP reverse-engineering he did to help make this bit of wizardry + * possible. + */ + +// NOTE! Enabling DEBUG adds about 3.3kB to the flash program size. +// Debug output is now working even on ATMega328P MCUs (e.g. Arduino Uno) +// after moving string constants to flash memory storage using the F() +// compiler macro (Arduino IDE 1.0+ required). + +//#define DEBUG +#ifdef DEBUG + #define DEBUG_PRINT(x) Serial.print(x) + #define DEBUG_PRINTF(x, y) Serial.print(x, y) + #define DEBUG_PRINTLN(x) Serial.println(x) + #define DEBUG_PRINTLNF(x, y) Serial.println(x, y) +#else + #define DEBUG_PRINT(x) + #define DEBUG_PRINTF(x, y) + #define DEBUG_PRINTLN(x) + #define DEBUG_PRINTLNF(x, y) +#endif + +#define MPU6050_DMP_CODE_SIZE 1929 // dmpMemory[] +#define MPU6050_DMP_CONFIG_SIZE 192 // dmpConfig[] +#define MPU6050_DMP_UPDATES_SIZE 47 // dmpUpdates[] + +/* ================================================================================================ * + | Default MotionApps v2.0 42-byte FIFO packet structure: | + | | + | [QUAT W][ ][QUAT X][ ][QUAT Y][ ][QUAT Z][ ][GYRO X][ ][GYRO Y][ ] | + | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | + | | + | [GYRO Z][ ][ACC X ][ ][ACC Y ][ ][ACC Z ][ ][ ] | + | 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | + * ================================================================================================ */ + +// this block of memory gets written to the MPU on start-up, and it seems +// to be volatile memory, so it has to be done each time (it only takes ~1 +// second though) + +// I Only Changed this by applying all the configuration data and capturing it before startup: +// *** this is a capture of the DMP Firmware after all the messy changes were made so we can just load it +const unsigned char dmpMemory[MPU6050_DMP_CODE_SIZE] PROGMEM = { + /* bank # 0 */ + 0xFB, 0x00, 0x00, 0x3E, 0x00, 0x0B, 0x00, 0x36, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x65, 0x00, 0x54, 0xFF, 0xEF, 0x00, 0x00, 0xFA, 0x80, 0x00, 0x0B, 0x12, 0x82, 0x00, 0x01, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x28, 0x00, 0x00, 0xFF, 0xFF, 0x45, 0x81, 0xFF, 0xFF, 0xFA, 0x72, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0xE8, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x7F, 0xFF, 0xFF, 0xFE, 0x80, 0x01, + 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0xCB, 0x47, 0xA2, 0x20, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, + 0x41, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x2A, 0x00, 0x00, 0x16, 0x55, 0x00, 0x00, 0x21, 0x82, + 0xFD, 0x87, 0x26, 0x50, 0xFD, 0x80, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x05, 0x80, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x6F, 0x00, 0x02, 0x65, 0x32, 0x00, 0x00, 0x5E, 0xC0, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFB, 0x8C, 0x6F, 0x5D, 0xFD, 0x5D, 0x08, 0xD9, 0x00, 0x7C, 0x73, 0x3B, 0x00, 0x6C, 0x12, 0xCC, + 0x32, 0x00, 0x13, 0x9D, 0x32, 0x00, 0xD0, 0xD6, 0x32, 0x00, 0x08, 0x00, 0x40, 0x00, 0x01, 0xF4, + 0xFF, 0xE6, 0x80, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0xD6, 0x00, 0x00, 0x27, 0x10, + /* bank # 1 */ + 0xFB, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFA, 0x36, 0xFF, 0xBC, 0x30, 0x8E, 0x00, 0x05, 0xFB, 0xF0, 0xFF, 0xD9, 0x5B, 0xC8, + 0xFF, 0xD0, 0x9A, 0xBE, 0x00, 0x00, 0x10, 0xA9, 0xFF, 0xF4, 0x1E, 0xB2, 0x00, 0xCE, 0xBB, 0xF7, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x0C, + 0xFF, 0xC2, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0xCF, 0x80, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x14, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x09, 0x23, 0xA1, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x3F, 0x68, 0xB6, 0x79, 0x35, 0x28, 0xBC, 0xC6, 0x7E, 0xD1, 0x6C, + 0x80, 0x00, 0xFF, 0xFF, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB2, 0x6A, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, + 0x00, 0x00, 0x25, 0x4D, 0x00, 0x2F, 0x70, 0x6D, 0x00, 0x00, 0x05, 0xAE, 0x00, 0x0C, 0x02, 0xD0, + /* bank # 2 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x54, 0xFF, 0xEF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x44, 0x00, 0x01, 0x00, 0x05, 0x8B, 0xC1, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0xFF, 0xEF, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* bank # 3 */ + 0xD8, 0xDC, 0xBA, 0xA2, 0xF1, 0xDE, 0xB2, 0xB8, 0xB4, 0xA8, 0x81, 0x91, 0xF7, 0x4A, 0x90, 0x7F, + 0x91, 0x6A, 0xF3, 0xF9, 0xDB, 0xA8, 0xF9, 0xB0, 0xBA, 0xA0, 0x80, 0xF2, 0xCE, 0x81, 0xF3, 0xC2, + 0xF1, 0xC1, 0xF2, 0xC3, 0xF3, 0xCC, 0xA2, 0xB2, 0x80, 0xF1, 0xC6, 0xD8, 0x80, 0xBA, 0xA7, 0xDF, + 0xDF, 0xDF, 0xF2, 0xA7, 0xC3, 0xCB, 0xC5, 0xB6, 0xF0, 0x87, 0xA2, 0x94, 0x24, 0x48, 0x70, 0x3C, + 0x95, 0x40, 0x68, 0x34, 0x58, 0x9B, 0x78, 0xA2, 0xF1, 0x83, 0x92, 0x2D, 0x55, 0x7D, 0xD8, 0xB1, + 0xB4, 0xB8, 0xA1, 0xD0, 0x91, 0x80, 0xF2, 0x70, 0xF3, 0x70, 0xF2, 0x7C, 0x80, 0xA8, 0xF1, 0x01, + 0xB0, 0x98, 0x87, 0xD9, 0x43, 0xD8, 0x86, 0xC9, 0x88, 0xBA, 0xA1, 0xF2, 0x0E, 0xB8, 0x97, 0x80, + 0xF1, 0xA9, 0xDF, 0xDF, 0xDF, 0xAA, 0xDF, 0xDF, 0xDF, 0xF2, 0xAA, 0x4C, 0xCD, 0x6C, 0xA9, 0x0C, + 0xC9, 0x2C, 0x97, 0x97, 0x97, 0x97, 0xF1, 0xA9, 0x89, 0x26, 0x46, 0x66, 0xB0, 0xB4, 0xBA, 0x80, + 0xAC, 0xDE, 0xF2, 0xCA, 0xF1, 0xB2, 0x8C, 0x02, 0xA9, 0xB6, 0x98, 0x00, 0x89, 0x0E, 0x16, 0x1E, + 0xB8, 0xA9, 0xB4, 0x99, 0x2C, 0x54, 0x7C, 0xB0, 0x8A, 0xA8, 0x96, 0x36, 0x56, 0x76, 0xF1, 0xB9, + 0xAF, 0xB4, 0xB0, 0x83, 0xC0, 0xB8, 0xA8, 0x97, 0x11, 0xB1, 0x8F, 0x98, 0xB9, 0xAF, 0xF0, 0x24, + 0x08, 0x44, 0x10, 0x64, 0x18, 0xF1, 0xA3, 0x29, 0x55, 0x7D, 0xAF, 0x83, 0xB5, 0x93, 0xAF, 0xF0, + 0x00, 0x28, 0x50, 0xF1, 0xA3, 0x86, 0x9F, 0x61, 0xA6, 0xDA, 0xDE, 0xDF, 0xD9, 0xFA, 0xA3, 0x86, + 0x96, 0xDB, 0x31, 0xA6, 0xD9, 0xF8, 0xDF, 0xBA, 0xA6, 0x8F, 0xC2, 0xC5, 0xC7, 0xB2, 0x8C, 0xC1, + 0xB8, 0xA2, 0xDF, 0xDF, 0xDF, 0xA3, 0xDF, 0xDF, 0xDF, 0xD8, 0xD8, 0xF1, 0xB8, 0xA8, 0xB2, 0x86, + /* bank # 4 */ + 0xB4, 0x98, 0x0D, 0x35, 0x5D, 0xB8, 0xAA, 0x98, 0xB0, 0x87, 0x2D, 0x35, 0x3D, 0xB2, 0xB6, 0xBA, + 0xAF, 0x8C, 0x96, 0x19, 0x8F, 0x9F, 0xA7, 0x0E, 0x16, 0x1E, 0xB4, 0x9A, 0xB8, 0xAA, 0x87, 0x2C, + 0x54, 0x7C, 0xB9, 0xA3, 0xDE, 0xDF, 0xDF, 0xA3, 0xB1, 0x80, 0xF2, 0xC4, 0xCD, 0xC9, 0xF1, 0xB8, + 0xA9, 0xB4, 0x99, 0x83, 0x0D, 0x35, 0x5D, 0x89, 0xB9, 0xA3, 0x2D, 0x55, 0x7D, 0xB5, 0x93, 0xA3, + 0x0E, 0x16, 0x1E, 0xA9, 0x2C, 0x54, 0x7C, 0xB8, 0xB4, 0xB0, 0xF1, 0x97, 0x83, 0xA8, 0x11, 0x84, + 0xA5, 0x09, 0x98, 0xA3, 0x83, 0xF0, 0xDA, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0xD8, 0xF1, 0xA5, + 0x29, 0x55, 0x7D, 0xA5, 0x85, 0x95, 0x02, 0x1A, 0x2E, 0x3A, 0x56, 0x5A, 0x40, 0x48, 0xF9, 0xF3, + 0xA3, 0xD9, 0xF8, 0xF0, 0x98, 0x83, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0x97, 0x82, 0xA8, 0xF1, + 0x11, 0xF0, 0x98, 0xA2, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0xDA, 0xF3, 0xDE, 0xD8, 0x83, 0xA5, + 0x94, 0x01, 0xD9, 0xA3, 0x02, 0xF1, 0xA2, 0xC3, 0xC5, 0xC7, 0xD8, 0xF1, 0x84, 0x92, 0xA2, 0x4D, + 0xDA, 0x2A, 0xD8, 0x48, 0x69, 0xD9, 0x2A, 0xD8, 0x68, 0x55, 0xDA, 0x32, 0xD8, 0x50, 0x71, 0xD9, + 0x32, 0xD8, 0x70, 0x5D, 0xDA, 0x3A, 0xD8, 0x58, 0x79, 0xD9, 0x3A, 0xD8, 0x78, 0x93, 0xA3, 0x4D, + 0xDA, 0x2A, 0xD8, 0x48, 0x69, 0xD9, 0x2A, 0xD8, 0x68, 0x55, 0xDA, 0x32, 0xD8, 0x50, 0x71, 0xD9, + 0x32, 0xD8, 0x70, 0x5D, 0xDA, 0x3A, 0xD8, 0x58, 0x79, 0xD9, 0x3A, 0xD8, 0x78, 0xA8, 0x8A, 0x9A, + 0xF0, 0x28, 0x50, 0x78, 0x9E, 0xF3, 0x88, 0x18, 0xF1, 0x9F, 0x1D, 0x98, 0xA8, 0xD9, 0x08, 0xD8, + 0xC8, 0x9F, 0x12, 0x9E, 0xF3, 0x15, 0xA8, 0xDA, 0x12, 0x10, 0xD8, 0xF1, 0xAF, 0xC8, 0x97, 0x87, + /* bank # 5 */ + 0x34, 0xB5, 0xB9, 0x94, 0xA4, 0x21, 0xF3, 0xD9, 0x22, 0xD8, 0xF2, 0x2D, 0xF3, 0xD9, 0x2A, 0xD8, + 0xF2, 0x35, 0xF3, 0xD9, 0x32, 0xD8, 0x81, 0xA4, 0x60, 0x60, 0x61, 0xD9, 0x61, 0xD8, 0x6C, 0x68, + 0x69, 0xD9, 0x69, 0xD8, 0x74, 0x70, 0x71, 0xD9, 0x71, 0xD8, 0xB1, 0xA3, 0x84, 0x19, 0x3D, 0x5D, + 0xA3, 0x83, 0x1A, 0x3E, 0x5E, 0x93, 0x10, 0x30, 0x81, 0x10, 0x11, 0xB8, 0xB0, 0xAF, 0x8F, 0x94, + 0xF2, 0xDA, 0x3E, 0xD8, 0xB4, 0x9A, 0xA8, 0x87, 0x29, 0xDA, 0xF8, 0xD8, 0x87, 0x9A, 0x35, 0xDA, + 0xF8, 0xD8, 0x87, 0x9A, 0x3D, 0xDA, 0xF8, 0xD8, 0xB1, 0xB9, 0xA4, 0x98, 0x85, 0x02, 0x2E, 0x56, + 0xA5, 0x81, 0x00, 0x0C, 0x14, 0xA3, 0x97, 0xB0, 0x8A, 0xF1, 0x2D, 0xD9, 0x28, 0xD8, 0x4D, 0xD9, + 0x48, 0xD8, 0x6D, 0xD9, 0x68, 0xD8, 0xB1, 0x84, 0x0D, 0xDA, 0x0E, 0xD8, 0xA3, 0x29, 0x83, 0xDA, + 0x2C, 0x0E, 0xD8, 0xA3, 0x84, 0x49, 0x83, 0xDA, 0x2C, 0x4C, 0x0E, 0xD8, 0xB8, 0xB0, 0xA8, 0x8A, + 0x9A, 0xF5, 0x20, 0xAA, 0xDA, 0xDF, 0xD8, 0xA8, 0x40, 0xAA, 0xD0, 0xDA, 0xDE, 0xD8, 0xA8, 0x60, + 0xAA, 0xDA, 0xD0, 0xDF, 0xD8, 0xF1, 0x97, 0x86, 0xA8, 0x31, 0x9B, 0x06, 0x99, 0x07, 0xAB, 0x97, + 0x28, 0x88, 0x9B, 0xF0, 0x0C, 0x20, 0x14, 0x40, 0xB8, 0xB0, 0xB4, 0xA8, 0x8C, 0x9C, 0xF0, 0x04, + 0x28, 0x51, 0x79, 0x1D, 0x30, 0x14, 0x38, 0xB2, 0x82, 0xAB, 0xD0, 0x98, 0x2C, 0x50, 0x50, 0x78, + 0x78, 0x9B, 0xF1, 0x1A, 0xB0, 0xF0, 0x8A, 0x9C, 0xA8, 0x29, 0x51, 0x79, 0x8B, 0x29, 0x51, 0x79, + 0x8A, 0x24, 0x70, 0x59, 0x8B, 0x20, 0x58, 0x71, 0x8A, 0x44, 0x69, 0x38, 0x8B, 0x39, 0x40, 0x68, + 0x8A, 0x64, 0x48, 0x31, 0x8B, 0x30, 0x49, 0x60, 0xA5, 0x88, 0x20, 0x09, 0x71, 0x58, 0x44, 0x68, + /* bank # 6 */ + 0x11, 0x39, 0x64, 0x49, 0x30, 0x19, 0xF1, 0xAC, 0x00, 0x2C, 0x54, 0x7C, 0xF0, 0x8C, 0xA8, 0x04, + 0x28, 0x50, 0x78, 0xF1, 0x88, 0x97, 0x26, 0xA8, 0x59, 0x98, 0xAC, 0x8C, 0x02, 0x26, 0x46, 0x66, + 0xF0, 0x89, 0x9C, 0xA8, 0x29, 0x51, 0x79, 0x24, 0x70, 0x59, 0x44, 0x69, 0x38, 0x64, 0x48, 0x31, + 0xA9, 0x88, 0x09, 0x20, 0x59, 0x70, 0xAB, 0x11, 0x38, 0x40, 0x69, 0xA8, 0x19, 0x31, 0x48, 0x60, + 0x8C, 0xA8, 0x3C, 0x41, 0x5C, 0x20, 0x7C, 0x00, 0xF1, 0x87, 0x98, 0x19, 0x86, 0xA8, 0x6E, 0x76, + 0x7E, 0xA9, 0x99, 0x88, 0x2D, 0x55, 0x7D, 0x9E, 0xB9, 0xA3, 0x8A, 0x22, 0x8A, 0x6E, 0x8A, 0x56, + 0x8A, 0x5E, 0x9F, 0xB1, 0x83, 0x06, 0x26, 0x46, 0x66, 0x0E, 0x2E, 0x4E, 0x6E, 0x9D, 0xB8, 0xAD, + 0x00, 0x2C, 0x54, 0x7C, 0xF2, 0xB1, 0x8C, 0xB4, 0x99, 0xB9, 0xA3, 0x2D, 0x55, 0x7D, 0x81, 0x91, + 0xAC, 0x38, 0xAD, 0x3A, 0xB5, 0x83, 0x91, 0xAC, 0x2D, 0xD9, 0x28, 0xD8, 0x4D, 0xD9, 0x48, 0xD8, + 0x6D, 0xD9, 0x68, 0xD8, 0x8C, 0x9D, 0xAE, 0x29, 0xD9, 0x04, 0xAE, 0xD8, 0x51, 0xD9, 0x04, 0xAE, + 0xD8, 0x79, 0xD9, 0x04, 0xD8, 0x81, 0xF3, 0x9D, 0xAD, 0x00, 0x8D, 0xAE, 0x19, 0x81, 0xAD, 0xD9, + 0x01, 0xD8, 0xF2, 0xAE, 0xDA, 0x26, 0xD8, 0x8E, 0x91, 0x29, 0x83, 0xA7, 0xD9, 0xAD, 0xAD, 0xAD, + 0xAD, 0xF3, 0x2A, 0xD8, 0xD8, 0xF1, 0xB0, 0xAC, 0x89, 0x91, 0x3E, 0x5E, 0x76, 0xF3, 0xAC, 0x2E, + 0x2E, 0xF1, 0xB1, 0x8C, 0x5A, 0x9C, 0xAC, 0x2C, 0x28, 0x28, 0x28, 0x9C, 0xAC, 0x30, 0x18, 0xA8, + 0x98, 0x81, 0x28, 0x34, 0x3C, 0x97, 0x24, 0xA7, 0x28, 0x34, 0x3C, 0x9C, 0x24, 0xF2, 0xB0, 0x89, + 0xAC, 0x91, 0x2C, 0x4C, 0x6C, 0x8A, 0x9B, 0x2D, 0xD9, 0xD8, 0xD8, 0x51, 0xD9, 0xD8, 0xD8, 0x79, + /* bank # 7 */ + 0xD9, 0xD8, 0xD8, 0xF1, 0x9E, 0x88, 0xA3, 0x31, 0xDA, 0xD8, 0xD8, 0x91, 0x2D, 0xD9, 0x28, 0xD8, + 0x4D, 0xD9, 0x48, 0xD8, 0x6D, 0xD9, 0x68, 0xD8, 0xB1, 0x83, 0x93, 0x35, 0x3D, 0x80, 0x25, 0xDA, + 0xD8, 0xD8, 0x85, 0x69, 0xDA, 0xD8, 0xD8, 0xB4, 0x93, 0x81, 0xA3, 0x28, 0x34, 0x3C, 0xF3, 0xAB, + 0x8B, 0xF8, 0xA3, 0x91, 0xB6, 0x09, 0xB4, 0xD9, 0xAB, 0xDE, 0xFA, 0xB0, 0x87, 0x9C, 0xB9, 0xA3, + 0xDD, 0xF1, 0x20, 0x28, 0x30, 0x38, 0x9A, 0xF1, 0x28, 0x30, 0x38, 0x9D, 0xF1, 0xA3, 0xA3, 0xA3, + 0xA3, 0xF2, 0xA3, 0xB4, 0x90, 0x80, 0xF2, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, + 0xA3, 0xB2, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xB0, 0x87, 0xB5, 0x99, 0xF1, 0x28, 0x30, 0x38, + 0x98, 0xF1, 0xA3, 0xA3, 0xA3, 0xA3, 0x97, 0xA3, 0xA3, 0xA3, 0xA3, 0xF3, 0x9B, 0xA3, 0x30, 0xDC, + 0xB9, 0xA7, 0xF1, 0x26, 0x26, 0x26, 0xFE, 0xD8, 0xFF, +}; +#ifndef MPU6050_DMP_FIFO_RATE_DIVISOR +#define MPU6050_DMP_FIFO_RATE_DIVISOR 0x01 // The New instance of the Firmware has this as the default +#endif + +// I Simplified this: +uint8_t MPU6050::dmpInitialize() { + // reset device + DEBUG_PRINTLN(F("\n\nResetting MPU6050...")); + reset(); + delay(30); // wait after reset + + // enable sleep mode and wake cycle + /*Serial.println(F("Enabling sleep mode...")); + setSleepEnabled(true); + Serial.println(F("Enabling wake cycle...")); + setWakeCycleEnabled(true);*/ + + // disable sleep mode + setSleepEnabled(false); + + // get MPU hardware revision + setMemoryBank(0x10, true, true); + setMemoryStartAddress(0x06); + Serial.println(F("Checking hardware revision...")); + Serial.print(F("Revision @ user[16][6] = ")); + Serial.println(readMemoryByte(), HEX); + Serial.println(F("Resetting memory bank selection to 0...")); + setMemoryBank(0, false, false); + + // check OTP bank valid + DEBUG_PRINTLN(F("Reading OTP bank valid flag...")); + DEBUG_PRINT(F("OTP bank is ")); + DEBUG_PRINTLN(getOTPBankValid() ? F("valid!") : F("invalid!")); + + // setup weird slave stuff (?) + DEBUG_PRINTLN(F("Setting slave 0 address to 0x7F...")); + setSlaveAddress(0, 0x7F); + DEBUG_PRINTLN(F("Disabling I2C Master mode...")); + setI2CMasterModeEnabled(false); + DEBUG_PRINTLN(F("Setting slave 0 address to 0x68 (self)...")); + setSlaveAddress(0, 0x68); + DEBUG_PRINTLN(F("Resetting I2C Master control...")); + resetI2CMaster(); + delay(20); + DEBUG_PRINTLN(F("Setting clock source to Z Gyro...")); + setClockSource(MPU6050_CLOCK_PLL_ZGYRO); + + DEBUG_PRINTLN(F("Setting DMP and FIFO_OFLOW interrupts enabled...")); + setIntEnabled(1<= dmpGetFIFOPacketSize(); +} + +// uint8_t MPU6050::dmpSetFIFORate(uint8_t fifoRate); +// uint8_t MPU6050::dmpGetFIFORate(); +// uint8_t MPU6050::dmpGetSampleStepSizeMS(); +// uint8_t MPU6050::dmpGetSampleFrequency(); +// int32_t MPU6050::dmpDecodeTemperature(int8_t tempReg); + +//uint8_t MPU6050::dmpRegisterFIFORateProcess(inv_obj_func func, int16_t priority); +//uint8_t MPU6050::dmpUnregisterFIFORateProcess(inv_obj_func func); +//uint8_t MPU6050::dmpRunFIFORateProcesses(); + +// uint8_t MPU6050::dmpSendQuaternion(uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendGyro(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendAccel(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendLinearAccel(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendLinearAccelInWorld(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendControlData(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendSensorData(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendExternalSensorData(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendGravity(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendPacketNumber(uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendQuantizedAccel(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendEIS(uint_fast16_t elements, uint_fast16_t accuracy); + +uint8_t MPU6050::dmpGetAccel(int32_t *data, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + data[0] = (((uint32_t)packet[28] << 24) | ((uint32_t)packet[29] << 16) | ((uint32_t)packet[30] << 8) | packet[31]); + data[1] = (((uint32_t)packet[32] << 24) | ((uint32_t)packet[33] << 16) | ((uint32_t)packet[34] << 8) | packet[35]); + data[2] = (((uint32_t)packet[36] << 24) | ((uint32_t)packet[37] << 16) | ((uint32_t)packet[38] << 8) | packet[39]); + return 0; +} +uint8_t MPU6050::dmpGetAccel(int16_t *data, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + data[0] = (packet[28] << 8) | packet[29]; + data[1] = (packet[32] << 8) | packet[33]; + data[2] = (packet[36] << 8) | packet[37]; + return 0; +} +uint8_t MPU6050::dmpGetAccel(VectorInt16 *v, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + v -> x = (packet[28] << 8) | packet[29]; + v -> y = (packet[32] << 8) | packet[33]; + v -> z = (packet[36] << 8) | packet[37]; + return 0; +} +uint8_t MPU6050::dmpGetQuaternion(int32_t *data, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + data[0] = (((uint32_t)packet[0] << 24) | ((uint32_t)packet[1] << 16) | ((uint32_t)packet[2] << 8) | packet[3]); + data[1] = (((uint32_t)packet[4] << 24) | ((uint32_t)packet[5] << 16) | ((uint32_t)packet[6] << 8) | packet[7]); + data[2] = (((uint32_t)packet[8] << 24) | ((uint32_t)packet[9] << 16) | ((uint32_t)packet[10] << 8) | packet[11]); + data[3] = (((uint32_t)packet[12] << 24) | ((uint32_t)packet[13] << 16) | ((uint32_t)packet[14] << 8) | packet[15]); + return 0; +} +uint8_t MPU6050::dmpGetQuaternion(int16_t *data, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + data[0] = ((packet[0] << 8) | packet[1]); + data[1] = ((packet[4] << 8) | packet[5]); + data[2] = ((packet[8] << 8) | packet[9]); + data[3] = ((packet[12] << 8) | packet[13]); + return 0; +} +uint8_t MPU6050::dmpGetQuaternion(Quaternion *q, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + int16_t qI[4]; + uint8_t status = dmpGetQuaternion(qI, packet); + if (status == 0) { + q -> w = (float)qI[0] / 16384.0f; + q -> x = (float)qI[1] / 16384.0f; + q -> y = (float)qI[2] / 16384.0f; + q -> z = (float)qI[3] / 16384.0f; + return 0; + } + return status; // int16 return value, indicates error if this line is reached +} +// uint8_t MPU6050::dmpGet6AxisQuaternion(long *data, const uint8_t* packet); +// uint8_t MPU6050::dmpGetRelativeQuaternion(long *data, const uint8_t* packet); +uint8_t MPU6050::dmpGetGyro(int32_t *data, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + data[0] = (((uint32_t)packet[16] << 24) | ((uint32_t)packet[17] << 16) | ((uint32_t)packet[18] << 8) | packet[19]); + data[1] = (((uint32_t)packet[20] << 24) | ((uint32_t)packet[21] << 16) | ((uint32_t)packet[22] << 8) | packet[23]); + data[2] = (((uint32_t)packet[24] << 24) | ((uint32_t)packet[25] << 16) | ((uint32_t)packet[26] << 8) | packet[27]); + return 0; +} +uint8_t MPU6050::dmpGetGyro(int16_t *data, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + data[0] = (packet[16] << 8) | packet[17]; + data[1] = (packet[20] << 8) | packet[21]; + data[2] = (packet[24] << 8) | packet[25]; + return 0; +} +uint8_t MPU6050::dmpGetGyro(VectorInt16 *v, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + v -> x = (packet[16] << 8) | packet[17]; + v -> y = (packet[20] << 8) | packet[21]; + v -> z = (packet[24] << 8) | packet[25]; + return 0; +} +// uint8_t MPU6050::dmpSetLinearAccelFilterCoefficient(float coef); +// uint8_t MPU6050::dmpGetLinearAccel(long *data, const uint8_t* packet); +uint8_t MPU6050::dmpGetLinearAccel(VectorInt16 *v, VectorInt16 *vRaw, VectorFloat *gravity) { + // get rid of the gravity component (+1g = +8192 in standard DMP FIFO packet, sensitivity is 2g) + v -> x = vRaw -> x - gravity -> x*8192; + v -> y = vRaw -> y - gravity -> y*8192; + v -> z = vRaw -> z - gravity -> z*8192; + return 0; +} +// uint8_t MPU6050::dmpGetLinearAccelInWorld(long *data, const uint8_t* packet); +uint8_t MPU6050::dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Quaternion *q) { + // rotate measured 3D acceleration vector into original state + // frame of reference based on orientation quaternion + memcpy(v, vReal, sizeof(VectorInt16)); + v -> rotate(q); + return 0; +} +// uint8_t MPU6050::dmpGetGyroAndAccelSensor(long *data, const uint8_t* packet); +// uint8_t MPU6050::dmpGetGyroSensor(long *data, const uint8_t* packet); +// uint8_t MPU6050::dmpGetControlData(long *data, const uint8_t* packet); +// uint8_t MPU6050::dmpGetTemperature(long *data, const uint8_t* packet); +// uint8_t MPU6050::dmpGetGravity(long *data, const uint8_t* packet); +uint8_t MPU6050::dmpGetGravity(int16_t *data, const uint8_t* packet) { + /* +1g corresponds to +8192, sensitivity is 2g. */ + int16_t qI[4]; + uint8_t status = dmpGetQuaternion(qI, packet); + data[0] = ((int32_t)qI[1] * qI[3] - (int32_t)qI[0] * qI[2]) / 16384; + data[1] = ((int32_t)qI[0] * qI[1] + (int32_t)qI[2] * qI[3]) / 16384; + data[2] = ((int32_t)qI[0] * qI[0] - (int32_t)qI[1] * qI[1] + - (int32_t)qI[2] * qI[2] + (int32_t)qI[3] * qI[3]) / (2 * 16384); + return status; +} + +uint8_t MPU6050::dmpGetGravity(VectorFloat *v, Quaternion *q) { + v -> x = 2 * (q -> x*q -> z - q -> w*q -> y); + v -> y = 2 * (q -> w*q -> x + q -> y*q -> z); + v -> z = q -> w*q -> w - q -> x*q -> x - q -> y*q -> y + q -> z*q -> z; + return 0; +} +// uint8_t MPU6050::dmpGetUnquantizedAccel(long *data, const uint8_t* packet); +// uint8_t MPU6050::dmpGetQuantizedAccel(long *data, const uint8_t* packet); +// uint8_t MPU6050::dmpGetExternalSensorData(long *data, int size, const uint8_t* packet); +// uint8_t MPU6050::dmpGetEIS(long *data, const uint8_t* packet); + +uint8_t MPU6050::dmpGetEuler(float *data, Quaternion *q) { + data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1); // psi + data[1] = -asin(2*q -> x*q -> z + 2*q -> w*q -> y); // theta + data[2] = atan2(2*q -> y*q -> z - 2*q -> w*q -> x, 2*q -> w*q -> w + 2*q -> z*q -> z - 1); // phi + return 0; +} + +#ifdef USE_OLD_DMPGETYAWPITCHROLL +uint8_t MPU6050::dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity) { + // yaw: (about Z axis) + data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1); + // pitch: (nose up/down, about Y axis) + data[1] = atan(gravity -> x / sqrt(gravity -> y*gravity -> y + gravity -> z*gravity -> z)); + // roll: (tilt left/right, about X axis) + data[2] = atan(gravity -> y / sqrt(gravity -> x*gravity -> x + gravity -> z*gravity -> z)); + return 0; +} +#else +uint8_t MPU6050::dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity) { + // yaw: (about Z axis) + data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1); + // pitch: (nose up/down, about Y axis) + data[1] = atan2(gravity -> x , sqrt(gravity -> y*gravity -> y + gravity -> z*gravity -> z)); + // roll: (tilt left/right, about X axis) + data[2] = atan2(gravity -> y , gravity -> z); + if (gravity -> z < 0) { + if(data[1] > 0) { + data[1] = PI - data[1]; + } else { + data[1] = -PI - data[1]; + } + } + return 0; +} +#endif + +// uint8_t MPU6050::dmpGetAccelFloat(float *data, const uint8_t* packet); +// uint8_t MPU6050::dmpGetQuaternionFloat(float *data, const uint8_t* packet); + +uint8_t MPU6050::dmpProcessFIFOPacket(const unsigned char *dmpData) { + /*for (uint8_t k = 0; k < dmpPacketSize; k++) { + if (dmpData[k] < 0x10) Serial.print("0"); + Serial.print(dmpData[k], HEX); + Serial.print(" "); + } + Serial.print("\n");*/ + //Serial.println((uint16_t)dmpPacketBuffer); + return 0; +} +uint8_t MPU6050::dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *processed) { + uint8_t status; + uint8_t buf[dmpPacketSize]; + for (uint8_t i = 0; i < numPackets; i++) { + // read packet from FIFO + getFIFOBytes(buf, dmpPacketSize); + + // process packet + if ((status = dmpProcessFIFOPacket(buf)) > 0) return status; + + // increment external process count variable, if supplied + if (processed != 0) (*processed)++; + } + return 0; +} + +// uint8_t MPU6050::dmpSetFIFOProcessedCallback(void (*func) (void)); + +// uint8_t MPU6050::dmpInitFIFOParam(); +// uint8_t MPU6050::dmpCloseFIFO(); +// uint8_t MPU6050::dmpSetGyroDataSource(uint_fast8_t source); +// uint8_t MPU6050::dmpDecodeQuantizedAccel(); +// uint32_t MPU6050::dmpGetGyroSumOfSquare(); +// uint32_t MPU6050::dmpGetAccelSumOfSquare(); +// void MPU6050::dmpOverrideQuaternion(long *q); +uint16_t MPU6050::dmpGetFIFOPacketSize() { + return dmpPacketSize; +} + +#endif /* _MPU6050_6AXIS_MOTIONAPPS20_H_ */ diff --git a/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino b/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino index 43b578a5..6a0bd13f 100644 --- a/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino +++ b/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino @@ -208,6 +208,10 @@ void setup() { // make sure it worked (returns 0 if so) if (devStatus == 0) { + // Calibration Time: generate offsets and calibrate our MPU6050 + mpu.CalibrateAccel(6); + mpu.CalibrateGyro(6); + mpu.PrintActiveOffsets(); // turn on the DMP, now that it's ready Serial.println(F("Enabling DMP...")); mpu.setDMPEnabled(true); @@ -273,26 +277,27 @@ void loop() { // get current FIFO count fifoCount = mpu.getFIFOCount(); - + if(fifoCount < packetSize){ + // go back and wait we shouldn't be here we got an interrupt from another trigger + // This is blocking don't do it while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount(); + } // check for overflow (this should never happen unless our code is too inefficient) - if ((mpuIntStatus & _BV(MPU6050_INTERRUPT_FIFO_OFLOW_BIT)) || fifoCount >= 1024) { + else if ((mpuIntStatus & _BV(MPU6050_INTERRUPT_FIFO_OFLOW_BIT)) || fifoCount >= 1024) { // reset so we can continue cleanly mpu.resetFIFO(); - fifoCount = mpu.getFIFOCount(); + // fifoCount = mpu.getFIFOCount(); // will be zero after reset no need to ask Serial.println(F("FIFO overflow!")); // otherwise, check for DMP data ready interrupt (this should happen frequently) } else if (mpuIntStatus & _BV(MPU6050_INTERRUPT_DMP_INT_BIT)) { - // wait for correct available data length, should be a VERY short wait - while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount(); // read a packet from FIFO - mpu.getFIFOBytes(fifoBuffer, packetSize); - - // track FIFO count here in case there is > 1 packet available - // (this lets us immediately read more without waiting for an interrupt) - fifoCount -= packetSize; - + while(fifoCount >= packetSize){ // Lets catch to NOW someone is using the dreded delay()! + mpu.getFIFOBytes(fifoBuffer, packetSize); + // track FIFO count here in case there is > 1 packet available + // (this lets us immediately read more without waiting for an interrupt) + fifoCount -= packetSize; + } #ifdef OUTPUT_READABLE_QUATERNION // display quaternion values in easy matrix form: w x y z mpu.dmpGetQuaternion(&q, fifoBuffer); From 631e6e73b84378e22ecb47d5c12b0f4710fe088f Mon Sep 17 00:00:00 2001 From: Homer Creutz Date: Mon, 8 Jul 2019 17:53:51 -0600 Subject: [PATCH 204/335] completed notes and other minor text Changes --- .../examples/MPU6050_DMP6/MPU6050_DMP6.ino | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino b/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino index 6a0bd13f..736fd2a9 100644 --- a/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino +++ b/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino @@ -278,8 +278,8 @@ void loop() { // get current FIFO count fifoCount = mpu.getFIFOCount(); if(fifoCount < packetSize){ - // go back and wait we shouldn't be here we got an interrupt from another trigger - // This is blocking don't do it while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount(); + //Lets go back and wait for another interrupt. We shouldn't be here, we got an interrupt from another event + // This is blocking so don't do it while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount(); } // check for overflow (this should never happen unless our code is too inefficient) else if ((mpuIntStatus & _BV(MPU6050_INTERRUPT_FIFO_OFLOW_BIT)) || fifoCount >= 1024) { @@ -292,12 +292,12 @@ void loop() { } else if (mpuIntStatus & _BV(MPU6050_INTERRUPT_DMP_INT_BIT)) { // read a packet from FIFO - while(fifoCount >= packetSize){ // Lets catch to NOW someone is using the dreded delay()! - mpu.getFIFOBytes(fifoBuffer, packetSize); - // track FIFO count here in case there is > 1 packet available - // (this lets us immediately read more without waiting for an interrupt) - fifoCount -= packetSize; - } + while(fifoCount >= packetSize){ // Lets catch up to NOW, someone is using the dreaded delay()! + mpu.getFIFOBytes(fifoBuffer, packetSize); + // track FIFO count here in case there is > 1 packet available + // (this lets us immediately read more without waiting for an interrupt) + fifoCount -= packetSize; + } #ifdef OUTPUT_READABLE_QUATERNION // display quaternion values in easy matrix form: w x y z mpu.dmpGetQuaternion(&q, fifoBuffer); From 15f0530fe4fb9cf965141d7ca4765ea6a25b1db6 Mon Sep 17 00:00:00 2001 From: Homer Creutz Date: Mon, 8 Jul 2019 17:57:47 -0600 Subject: [PATCH 205/335] Update MPU6050_DMP6.ino --- Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino b/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino index 736fd2a9..7298527d 100644 --- a/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino +++ b/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino @@ -3,6 +3,8 @@ // Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib // // Changelog: +// 2019-07-08 - Added Auto Calibration and offset generator +// - and altered FIFO retrieval sequence to avoid using blocking code // 2016-04-18 - Eliminated a potential infinite loop // 2013-05-08 - added seamless Fastwire support // - added note about gyro calibration From 1d75c2487ac0702b56e50bc35fcd033703fa36cc Mon Sep 17 00:00:00 2001 From: Homer Creutz Date: Mon, 8 Jul 2019 17:59:55 -0600 Subject: [PATCH 206/335] Update MPU6050.cpp --- Arduino/MPU6050/MPU6050.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Arduino/MPU6050/MPU6050.cpp b/Arduino/MPU6050/MPU6050.cpp index 547df8e0..c6ead06b 100644 --- a/Arduino/MPU6050/MPU6050.cpp +++ b/Arduino/MPU6050/MPU6050.cpp @@ -4,6 +4,7 @@ // Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib // // Changelog: +// 2019-07-08 - Added Auto Calibration routine // ... - ongoing debug release // NOTE: THIS IS ONLY A PARIAL RELEASE. THIS DEVICE CLASS IS CURRENTLY UNDERGOING ACTIVE @@ -3291,4 +3292,4 @@ void MPU6050::PrintActiveOffsets() { printfloatx("", Data[0], 5, 0, ", "); printfloatx("", Data[1], 5, 0, ", "); printfloatx("", Data[2], 5, 0, "\n"); -} \ No newline at end of file +} From f9f92d2d96b18885586126dada5982b68e488da6 Mon Sep 17 00:00:00 2001 From: Homer Creutz Date: Mon, 8 Jul 2019 18:03:21 -0600 Subject: [PATCH 207/335] Update MPU6050_6Axis_MotionApps20.h --- Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h index 487f63cd..f15ebc69 100644 --- a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h +++ b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h @@ -4,6 +4,8 @@ // Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib // // Changelog: +// 2019/07/08 - merged all DMP Firmware configuration items into the dmpMemory array +// - Simplified dmpInitialize() to accomidate the dmpmemory array alterations // ... - ongoing debug release /* ============================================ @@ -262,8 +264,10 @@ const unsigned char dmpMemory[MPU6050_DMP_CODE_SIZE] PROGMEM = { 0xA3, 0xF2, 0xA3, 0xB4, 0x90, 0x80, 0xF2, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xB2, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xB0, 0x87, 0xB5, 0x99, 0xF1, 0x28, 0x30, 0x38, 0x98, 0xF1, 0xA3, 0xA3, 0xA3, 0xA3, 0x97, 0xA3, 0xA3, 0xA3, 0xA3, 0xF3, 0x9B, 0xA3, 0x30, 0xDC, - 0xB9, 0xA7, 0xF1, 0x26, 0x26, 0x26, 0xFE, 0xD8, 0xFF, -}; + 0xB9, 0xA7, 0xF1, 0x26, 0x26, 0x26, 0xFE, 0xD8, 0xFF, + +}; + #ifndef MPU6050_DMP_FIFO_RATE_DIVISOR #define MPU6050_DMP_FIFO_RATE_DIVISOR 0x01 // The New instance of the Firmware has this as the default #endif From f5c9a819bc2d4225b461f614df3ec520486743a2 Mon Sep 17 00:00:00 2001 From: Homer Creutz Date: Wed, 10 Jul 2019 00:26:47 -0600 Subject: [PATCH 208/335] Uses Lates DMP firmware V6.1.2 The one feature that I believe will make this a valuable addition: This feature is enabled in the captured DMP firmware image of V6.1.2 Run-time calibration routine. Once a no motion state is detected the gyro calibration will trigger. Calibration will complete within .5 seconds of no motion state detection. using this in addition to the Newly supplied offset generator will keep drift to an absolute minimum. --- .../MPU6050/MPU6050_6Axis_MotionApps_V6_12.h | 613 ++++++++++++++++++ 1 file changed, 613 insertions(+) create mode 100644 Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h diff --git a/Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h b/Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h new file mode 100644 index 00000000..1e15ca28 --- /dev/null +++ b/Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h @@ -0,0 +1,613 @@ +// I2Cdev library collection - MPU6050 I2C device class, 6-axis MotionApps 2.0 implementation +// Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00) +// 5/20/2013 by Jeff Rowberg +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// 2019/7/10 - I incorporated DMP Firmware Version 6.1.2 Latest as of today with many features and bug fixes. +// - Run-time calibration routine is enabled which calibrates after no motion state is detected +// - once no motion state is detected Calibration completes within 0.5 seconds +// - The Drawback is that the firmware image is larger. +// ... - ongoing debug release + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2012 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#ifndef _MPU6050_6AXIS_MOTIONAPPS20_H_ +#define _MPU6050_6AXIS_MOTIONAPPS20_H_ + +#include "I2Cdev.h" +#include "helper_3dmath.h" + +// MotionApps 2.0 DMP implementation, built using the MPU-6050EVB evaluation board +#define MPU6050_INCLUDE_DMP_MOTIONAPPS20 // same definitions Should work with V6.12 + +#include "MPU6050.h" + +// Tom Carpenter's conditional PROGMEM code +// http://forum.arduino.cc/index.php?topic=129407.0 +#ifdef __AVR__ + #include +#else + // Teensy 3.0 library conditional PROGMEM code from Paul Stoffregen + #ifndef __PGMSPACE_H_ + #define __PGMSPACE_H_ 1 + #include + + #define PROGMEM + #define PGM_P const char * + #define PSTR(str) (str) + #define F(x) x + + typedef void prog_void; + typedef char prog_char; + typedef unsigned char prog_uchar; + typedef int8_t prog_int8_t; + typedef uint8_t prog_uint8_t; + typedef int16_t prog_int16_t; + typedef uint16_t prog_uint16_t; + typedef int32_t prog_int32_t; + typedef uint32_t prog_uint32_t; + + #define strcpy_P(dest, src) strcpy((dest), (src)) + #define strcat_P(dest, src) strcat((dest), (src)) + #define strcmp_P(a, b) strcmp((a), (b)) + + #define pgm_read_byte(addr) (*(const unsigned char *)(addr)) + #define pgm_read_word(addr) (*(const unsigned short *)(addr)) + #define pgm_read_dword(addr) (*(const unsigned long *)(addr)) + #define pgm_read_float(addr) (*(const float *)(addr)) + + #define pgm_read_byte_near(addr) pgm_read_byte(addr) + #define pgm_read_word_near(addr) pgm_read_word(addr) + #define pgm_read_dword_near(addr) pgm_read_dword(addr) + #define pgm_read_float_near(addr) pgm_read_float(addr) + #define pgm_read_byte_far(addr) pgm_read_byte(addr) + #define pgm_read_word_far(addr) pgm_read_word(addr) + #define pgm_read_dword_far(addr) pgm_read_dword(addr) + #define pgm_read_float_far(addr) pgm_read_float(addr) + #endif +#endif + +/* Source is from the InvenSense MotionApps v2 demo code. Original source is + * unavailable, unless you happen to be amazing as decompiling binary by + * hand (in which case, please contact me, and I'm totally serious). + * + * Also, I'd like to offer many, many thanks to Noah Zerkin for all of the + * DMP reverse-engineering he did to help make this bit of wizardry + * possible. + */ + +// NOTE! Enabling DEBUG adds about 3.3kB to the flash program size. +// Debug output is now working even on ATMega328P MCUs (e.g. Arduino Uno) +// after moving string constants to flash memory storage using the F() +// compiler macro (Arduino IDE 1.0+ required). + +//#define DEBUG +#ifdef DEBUG + #define DEBUG_PRINT(x) Serial.print(x) + #define DEBUG_PRINTF(x, y) Serial.print(x, y) + #define DEBUG_PRINTLN(x) Serial.println(x) + #define DEBUG_PRINTLNF(x, y) Serial.println(x, y) +#else + #define DEBUG_PRINT(x) + #define DEBUG_PRINTF(x, y) + #define DEBUG_PRINTLN(x) + #define DEBUG_PRINTLNF(x, y) +#endif + +#define MPU6050_DMP_CODE_SIZE 3062 // dmpMemory[] + +/* ================================================================ * + | Default MotionApps v6.12 28-byte FIFO packet structure: | + | | + | [QUAT W][ ][QUAT X][ ][QUAT Y][ ][QUAT Z][ ] | + | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | + | | + | [GYRO X][GYRO Y][GYRO Z][ACC X ][ACC Y ][ACC Z ] | + | 16 17 18 19 20 21 22 23 24 25 26 27 | + * ================================================================ */ + +// this block of memory gets written to the MPU on start-up, and it seems +// to be volatile memory, so it has to be done each time (it only takes ~1 +// second though) + +// *** this is a capture of the DMP Firmware V6.1.2 after all the messy changes were made so we can just load it +const unsigned char dmpMemory[MPU6050_DMP_CODE_SIZE] PROGMEM = { +/* bank # 0 */ +0x00, 0xF8, 0xF6, 0x2A, 0x3F, 0x68, 0xF5, 0x7A, 0x00, 0x06, 0xFF, 0xFE, 0x00, 0x03, 0x00, 0x00, +0x00, 0x65, 0x00, 0x54, 0xFF, 0xEF, 0x00, 0x00, 0xFA, 0x80, 0x00, 0x0B, 0x12, 0x82, 0x00, 0x01, +0x03, 0x0C, 0x30, 0xC3, 0x0A, 0x74, 0x56, 0x2D, 0x0D, 0x62, 0xDB, 0xC7, 0x16, 0xF4, 0xBA, 0x02, +0x38, 0x83, 0xF8, 0x83, 0x30, 0x00, 0xF8, 0x83, 0x25, 0x8E, 0xF8, 0x83, 0x30, 0x00, 0xF8, 0x83, +0xFF, 0xFF, 0xFF, 0xFF, 0x0C, 0xBD, 0xD8, 0x11, 0x24, 0x00, 0x04, 0x00, 0x1A, 0x82, 0x79, 0xA1, +0x00, 0x36, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x38, 0x83, 0x6F, 0xA2, +0x00, 0x3E, 0x03, 0x30, 0x40, 0x00, 0x00, 0x00, 0x02, 0xCA, 0xE3, 0x09, 0x3E, 0x80, 0x00, 0x00, +0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, +0x1F, 0xA4, 0xE8, 0xE4, 0xFF, 0xF5, 0xDC, 0xB9, 0x00, 0x5B, 0x79, 0xCF, 0x1F, 0x3F, 0x78, 0x76, +0x00, 0x86, 0x7C, 0x5A, 0x00, 0x86, 0x23, 0x47, 0xFA, 0xB9, 0x86, 0x31, 0x00, 0x74, 0x87, 0x8A, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x05, 0xFF, 0xFF, 0xE9, 0xA8, 0x00, 0x00, 0x21, 0x82, +0xFA, 0xB8, 0x4D, 0x46, 0xFF, 0xFA, 0xDF, 0x3D, 0xFF, 0xFF, 0xB2, 0xB3, 0x00, 0x00, 0x00, 0x00, +0x3F, 0xFF, 0xBA, 0x98, 0x00, 0x5D, 0xAC, 0x08, 0x00, 0x0A, 0x63, 0x78, 0x00, 0x01, 0x46, 0x21, +0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x42, 0xB5, 0x00, 0x06, 0x00, 0x64, 0x00, 0x64, 0x00, 0x06, +0x14, 0x06, 0x02, 0x9F, 0x0F, 0x47, 0x91, 0x32, 0xD9, 0x0E, 0x9F, 0xC9, 0x1D, 0xCF, 0x4C, 0x34, +0x3B, 0xB6, 0x7A, 0xE8, 0x00, 0x64, 0x00, 0x06, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE, +/* bank # 1 */ +0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x07, 0x00, 0x00, 0xFF, 0xF1, 0x00, 0x00, 0xFA, 0x46, 0x00, 0x00, 0xA2, 0xB8, 0x00, 0x00, +0x10, 0x00, 0x00, 0x00, 0x04, 0xD6, 0x00, 0x00, 0x04, 0xCC, 0x00, 0x00, 0x04, 0xCC, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x06, 0x00, 0x02, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x05, 0x00, 0x64, 0x00, 0x20, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x03, 0x00, +0x00, 0x00, 0x00, 0x32, 0xF8, 0x98, 0x00, 0x00, 0xFF, 0x65, 0x00, 0x00, 0x83, 0x0F, 0x00, 0x00, +0x00, 0x06, 0x00, 0x00, 0xFF, 0xF1, 0x00, 0x00, 0xFA, 0x46, 0x00, 0x00, 0xA2, 0xB8, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, +0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0xB2, 0x6A, 0x00, 0x02, 0x00, 0x00, +0x00, 0x01, 0xFB, 0x83, 0x00, 0x7C, 0x00, 0x00, 0xFB, 0x15, 0xFC, 0x00, 0x1F, 0xB4, 0xFF, 0x83, +0x00, 0x00, 0x00, 0x01, 0x00, 0x65, 0x00, 0x07, 0x00, 0x64, 0x03, 0xE8, 0x00, 0x64, 0x00, 0x28, +0x00, 0x00, 0xFF, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x16, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x10, 0x00, 0x00, 0x2F, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF4, 0x00, 0x00, 0x10, 0x00, +/* bank # 2 */ +0x00, 0x28, 0x00, 0x00, 0xFF, 0xFF, 0x45, 0x81, 0xFF, 0xFF, 0xFA, 0x72, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x01, 0x00, 0x05, 0xBA, 0xC6, 0x00, 0x47, 0x78, 0xA2, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x14, +0x00, 0x00, 0x23, 0xBB, 0x00, 0x2E, 0xA2, 0x5B, 0x00, 0x00, 0x05, 0x68, 0x00, 0x0B, 0xCF, 0x49, +0x00, 0x04, 0xFF, 0xFD, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, +0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x64, 0x00, 0x07, 0x00, 0x08, 0x00, 0x06, 0x00, 0x06, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x2E, 0xA2, 0x5B, 0x00, 0x00, 0x05, 0x68, 0x00, 0x0B, 0xCF, 0x49, 0x00, 0x00, 0x00, 0x00, +0x00, 0xF8, 0xF6, 0x2A, 0x3F, 0x68, 0xF5, 0x7A, 0x00, 0x04, 0xFF, 0xFD, 0x00, 0x02, 0x00, 0x00, +0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x0E, +0xFF, 0xFF, 0xFF, 0xCF, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0xFF, 0xFF, 0xFF, 0x9C, +0x00, 0x00, 0x43, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x64, +0xFF, 0xE5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* bank # 3 */ +0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x24, 0x26, 0xD3, +0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x10, 0x00, 0x96, 0x00, 0x3C, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x9E, 0x65, 0x5D, +0x0C, 0x0A, 0x4E, 0x68, 0xCD, 0xCF, 0x77, 0x09, 0x50, 0x16, 0x67, 0x59, 0xC6, 0x19, 0xCE, 0x82, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x71, 0x1C, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0xD7, 0x84, 0x00, 0x03, 0x00, 0x00, 0x00, +0x00, 0x11, 0xDC, 0x47, 0x03, 0x00, 0x00, 0x00, 0xC7, 0x93, 0x8F, 0x9D, 0x1E, 0x1B, 0x1C, 0x19, +0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0E, 0xDF, 0xA4, 0x38, 0x1F, 0x9E, 0x65, 0x5D, +0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x71, 0x1C, 0x02, 0x03, 0x18, 0x85, 0x00, 0x00, 0x40, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x3F, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xF4, 0xC9, 0xFF, 0xFF, 0xBC, 0xF0, 0x00, 0x01, 0x0C, 0x0F, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xF5, 0xB7, 0xBA, 0xB3, 0x67, 0x7D, 0xDF, 0x7E, 0x72, 0x90, 0x2E, 0x55, 0x4C, 0xF6, 0xE6, 0x88, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* bank # 4 */ +0xD8, 0xDC, 0xB4, 0xB8, 0xB0, 0xD8, 0xB9, 0xAB, 0xF3, 0xF8, 0xFA, 0xB3, 0xB7, 0xBB, 0x8E, 0x9E, +0xAE, 0xF1, 0x32, 0xF5, 0x1B, 0xF1, 0xB4, 0xB8, 0xB0, 0x80, 0x97, 0xF1, 0xA9, 0xDF, 0xDF, 0xDF, +0xAA, 0xDF, 0xDF, 0xDF, 0xF2, 0xAA, 0x4C, 0xCD, 0x6C, 0xA9, 0x0C, 0xC9, 0x2C, 0x97, 0xF1, 0xA9, +0x89, 0x26, 0x46, 0x66, 0xB2, 0x89, 0x99, 0xA9, 0x2D, 0x55, 0x7D, 0xB0, 0xB0, 0x8A, 0xA8, 0x96, +0x36, 0x56, 0x76, 0xF1, 0xBA, 0xA3, 0xB4, 0xB2, 0x80, 0xC0, 0xB8, 0xA8, 0x97, 0x11, 0xB2, 0x83, +0x98, 0xBA, 0xA3, 0xF0, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0xB2, 0xB9, 0xB4, 0x98, 0x83, 0xF1, +0xA3, 0x29, 0x55, 0x7D, 0xBA, 0xB5, 0xB1, 0xA3, 0x83, 0x93, 0xF0, 0x00, 0x28, 0x50, 0xF5, 0xB2, +0xB6, 0xAA, 0x83, 0x93, 0x28, 0x54, 0x7C, 0xF1, 0xB9, 0xA3, 0x82, 0x93, 0x61, 0xBA, 0xA2, 0xDA, +0xDE, 0xDF, 0xDB, 0x81, 0x9A, 0xB9, 0xAE, 0xF5, 0x60, 0x68, 0x70, 0xF1, 0xDA, 0xBA, 0xA2, 0xDF, +0xD9, 0xBA, 0xA2, 0xFA, 0xB9, 0xA3, 0x82, 0x92, 0xDB, 0x31, 0xBA, 0xA2, 0xD9, 0xBA, 0xA2, 0xF8, +0xDF, 0x85, 0xA4, 0xD0, 0xC1, 0xBB, 0xAD, 0x83, 0xC2, 0xC5, 0xC7, 0xB8, 0xA2, 0xDF, 0xDF, 0xDF, +0xBA, 0xA0, 0xDF, 0xDF, 0xDF, 0xD8, 0xD8, 0xF1, 0xB8, 0xAA, 0xB3, 0x8D, 0xB4, 0x98, 0x0D, 0x35, +0x5D, 0xB2, 0xB6, 0xBA, 0xAF, 0x8C, 0x96, 0x19, 0x8F, 0x9F, 0xA7, 0x0E, 0x16, 0x1E, 0xB4, 0x9A, +0xB8, 0xAA, 0x87, 0x2C, 0x54, 0x7C, 0xBA, 0xA4, 0xB0, 0x8A, 0xB6, 0x91, 0x32, 0x56, 0x76, 0xB2, +0x84, 0x94, 0xA4, 0xC8, 0x08, 0xCD, 0xD8, 0xB8, 0xB4, 0xB0, 0xF1, 0x99, 0x82, 0xA8, 0x2D, 0x55, +0x7D, 0x98, 0xA8, 0x0E, 0x16, 0x1E, 0xA2, 0x2C, 0x54, 0x7C, 0x92, 0xA4, 0xF0, 0x2C, 0x50, 0x78, +/* bank # 5 */ +0xF1, 0x84, 0xA8, 0x98, 0xC4, 0xCD, 0xFC, 0xD8, 0x0D, 0xDB, 0xA8, 0xFC, 0x2D, 0xF3, 0xD9, 0xBA, +0xA6, 0xF8, 0xDA, 0xBA, 0xA6, 0xDE, 0xD8, 0xBA, 0xB2, 0xB6, 0x86, 0x96, 0xA6, 0xD0, 0xF3, 0xC8, +0x41, 0xDA, 0xA6, 0xC8, 0xF8, 0xD8, 0xB0, 0xB4, 0xB8, 0x82, 0xA8, 0x92, 0xF5, 0x2C, 0x54, 0x88, +0x98, 0xF1, 0x35, 0xD9, 0xF4, 0x18, 0xD8, 0xF1, 0xA2, 0xD0, 0xF8, 0xF9, 0xA8, 0x84, 0xD9, 0xC7, +0xDF, 0xF8, 0xF8, 0x83, 0xC5, 0xDA, 0xDF, 0x69, 0xDF, 0x83, 0xC1, 0xD8, 0xF4, 0x01, 0x14, 0xF1, +0xA8, 0x82, 0x4E, 0xA8, 0x84, 0xF3, 0x11, 0xD1, 0x82, 0xF5, 0xD9, 0x92, 0x28, 0x97, 0x88, 0xF1, +0x09, 0xF4, 0x1C, 0x1C, 0xD8, 0x84, 0xA8, 0xF3, 0xC0, 0xF9, 0xD1, 0xD9, 0x97, 0x82, 0xF1, 0x29, +0xF4, 0x0D, 0xD8, 0xF3, 0xF9, 0xF9, 0xD1, 0xD9, 0x82, 0xF4, 0xC2, 0x03, 0xD8, 0xDE, 0xDF, 0x1A, +0xD8, 0xF1, 0xA2, 0xFA, 0xF9, 0xA8, 0x84, 0x98, 0xD9, 0xC7, 0xDF, 0xF8, 0xF8, 0xF8, 0x83, 0xC7, +0xDA, 0xDF, 0x69, 0xDF, 0xF8, 0x83, 0xC3, 0xD8, 0xF4, 0x01, 0x14, 0xF1, 0x98, 0xA8, 0x82, 0x2E, +0xA8, 0x84, 0xF3, 0x11, 0xD1, 0x82, 0xF5, 0xD9, 0x92, 0x50, 0x97, 0x88, 0xF1, 0x09, 0xF4, 0x1C, +0xD8, 0x84, 0xA8, 0xF3, 0xC0, 0xF8, 0xF9, 0xD1, 0xD9, 0x97, 0x82, 0xF1, 0x49, 0xF4, 0x0D, 0xD8, +0xF3, 0xF9, 0xF9, 0xD1, 0xD9, 0x82, 0xF4, 0xC4, 0x03, 0xD8, 0xDE, 0xDF, 0xD8, 0xF1, 0xAD, 0x88, +0x98, 0xCC, 0xA8, 0x09, 0xF9, 0xD9, 0x82, 0x92, 0xA8, 0xF5, 0x7C, 0xF1, 0x88, 0x3A, 0xCF, 0x94, +0x4A, 0x6E, 0x98, 0xDB, 0x69, 0x31, 0xDA, 0xAD, 0xF2, 0xDE, 0xF9, 0xD8, 0x87, 0x95, 0xA8, 0xF2, +0x21, 0xD1, 0xDA, 0xA5, 0xF9, 0xF4, 0x17, 0xD9, 0xF1, 0xAE, 0x8E, 0xD0, 0xC0, 0xC3, 0xAE, 0x82, +/* bank # 6 */ +0xC6, 0x84, 0xC3, 0xA8, 0x85, 0x95, 0xC8, 0xA5, 0x88, 0xF2, 0xC0, 0xF1, 0xF4, 0x01, 0x0E, 0xF1, +0x8E, 0x9E, 0xA8, 0xC6, 0x3E, 0x56, 0xF5, 0x54, 0xF1, 0x88, 0x72, 0xF4, 0x01, 0x15, 0xF1, 0x98, +0x45, 0x85, 0x6E, 0xF5, 0x8E, 0x9E, 0x04, 0x88, 0xF1, 0x42, 0x98, 0x5A, 0x8E, 0x9E, 0x06, 0x88, +0x69, 0xF4, 0x01, 0x1C, 0xF1, 0x98, 0x1E, 0x11, 0x08, 0xD0, 0xF5, 0x04, 0xF1, 0x1E, 0x97, 0x02, +0x02, 0x98, 0x36, 0x25, 0xDB, 0xF9, 0xD9, 0x85, 0xA5, 0xF3, 0xC1, 0xDA, 0x85, 0xA5, 0xF3, 0xDF, +0xD8, 0x85, 0x95, 0xA8, 0xF3, 0x09, 0xDA, 0xA5, 0xFA, 0xD8, 0x82, 0x92, 0xA8, 0xF5, 0x78, 0xF1, +0x88, 0x1A, 0x84, 0x9F, 0x26, 0x88, 0x98, 0x21, 0xDA, 0xF4, 0x1D, 0xF3, 0xD8, 0x87, 0x9F, 0x39, +0xD1, 0xAF, 0xD9, 0xDF, 0xDF, 0xFB, 0xF9, 0xF4, 0x0C, 0xF3, 0xD8, 0xFA, 0xD0, 0xF8, 0xDA, 0xF9, +0xF9, 0xD0, 0xDF, 0xD9, 0xF9, 0xD8, 0xF4, 0x0B, 0xD8, 0xF3, 0x87, 0x9F, 0x39, 0xD1, 0xAF, 0xD9, +0xDF, 0xDF, 0xF4, 0x1D, 0xF3, 0xD8, 0xFA, 0xFC, 0xA8, 0x69, 0xF9, 0xF9, 0xAF, 0xD0, 0xDA, 0xDE, +0xFA, 0xD9, 0xF8, 0x8F, 0x9F, 0xA8, 0xF1, 0xCC, 0xF3, 0x98, 0xDB, 0x45, 0xD9, 0xAF, 0xDF, 0xD0, +0xF8, 0xD8, 0xF1, 0x8F, 0x9F, 0xA8, 0xCA, 0xF3, 0x88, 0x09, 0xDA, 0xAF, 0x8F, 0xCB, 0xF8, 0xD8, +0xF2, 0xAD, 0x97, 0x8D, 0x0C, 0xD9, 0xA5, 0xDF, 0xF9, 0xBA, 0xA6, 0xF3, 0xFA, 0xF4, 0x12, 0xF2, +0xD8, 0x95, 0x0D, 0xD1, 0xD9, 0xBA, 0xA6, 0xF3, 0xFA, 0xDA, 0xA5, 0xF2, 0xC1, 0xBA, 0xA6, 0xF3, +0xDF, 0xD8, 0xF1, 0xBA, 0xB2, 0xB6, 0x86, 0x96, 0xA6, 0xD0, 0xCA, 0xF3, 0x49, 0xDA, 0xA6, 0xCB, +0xF8, 0xD8, 0xB0, 0xB4, 0xB8, 0xD8, 0xAD, 0x84, 0xF2, 0xC0, 0xDF, 0xF1, 0x8F, 0xCB, 0xC3, 0xA8, +/* bank # 7 */ +0xB2, 0xB6, 0x86, 0x96, 0xC8, 0xC1, 0xCB, 0xC3, 0xF3, 0xB0, 0xB4, 0x88, 0x98, 0xA8, 0x21, 0xDB, +0x71, 0x8D, 0x9D, 0x71, 0x85, 0x95, 0x21, 0xD9, 0xAD, 0xF2, 0xFA, 0xD8, 0x85, 0x97, 0xA8, 0x28, +0xD9, 0xF4, 0x08, 0xD8, 0xF2, 0x8D, 0x29, 0xDA, 0xF4, 0x05, 0xD9, 0xF2, 0x85, 0xA4, 0xC2, 0xF2, +0xD8, 0xA8, 0x8D, 0x94, 0x01, 0xD1, 0xD9, 0xF4, 0x11, 0xF2, 0xD8, 0x87, 0x21, 0xD8, 0xF4, 0x0A, +0xD8, 0xF2, 0x84, 0x98, 0xA8, 0xC8, 0x01, 0xD1, 0xD9, 0xF4, 0x11, 0xD8, 0xF3, 0xA4, 0xC8, 0xBB, +0xAF, 0xD0, 0xF2, 0xDE, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xD8, 0xF1, 0xB8, 0xF6, +0xB5, 0xB9, 0xB0, 0x8A, 0x95, 0xA3, 0xDE, 0x3C, 0xA3, 0xD9, 0xF8, 0xD8, 0x5C, 0xA3, 0xD9, 0xF8, +0xD8, 0x7C, 0xA3, 0xD9, 0xF8, 0xD8, 0xF8, 0xF9, 0xD1, 0xA5, 0xD9, 0xDF, 0xDA, 0xFA, 0xD8, 0xB1, +0x85, 0x30, 0xF7, 0xD9, 0xDE, 0xD8, 0xF8, 0x30, 0xAD, 0xDA, 0xDE, 0xD8, 0xF2, 0xB4, 0x8C, 0x99, +0xA3, 0x2D, 0x55, 0x7D, 0xA0, 0x83, 0xDF, 0xDF, 0xDF, 0xB5, 0x91, 0xA0, 0xF6, 0x29, 0xD9, 0xFB, +0xD8, 0xA0, 0xFC, 0x29, 0xD9, 0xFA, 0xD8, 0xA0, 0xD0, 0x51, 0xD9, 0xF8, 0xD8, 0xFC, 0x51, 0xD9, +0xF9, 0xD8, 0x79, 0xD9, 0xFB, 0xD8, 0xA0, 0xD0, 0xFC, 0x79, 0xD9, 0xFA, 0xD8, 0xA1, 0xF9, 0xF9, +0xF9, 0xF9, 0xF9, 0xA0, 0xDA, 0xDF, 0xDF, 0xDF, 0xD8, 0xA1, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xAC, +0xDE, 0xF8, 0xAD, 0xDE, 0x83, 0x93, 0xAC, 0x2C, 0x54, 0x7C, 0xF1, 0xA8, 0xDF, 0xDF, 0xDF, 0xF6, +0x9D, 0x2C, 0xDA, 0xA0, 0xDF, 0xD9, 0xFA, 0xDB, 0x2D, 0xF8, 0xD8, 0xA8, 0x50, 0xDA, 0xA0, 0xD0, +0xDE, 0xD9, 0xD0, 0xF8, 0xF8, 0xF8, 0xDB, 0x55, 0xF8, 0xD8, 0xA8, 0x78, 0xDA, 0xA0, 0xD0, 0xDF, +/* bank # 8 */ +0xD9, 0xD0, 0xFA, 0xF8, 0xF8, 0xF8, 0xF8, 0xDB, 0x7D, 0xF8, 0xD8, 0x9C, 0xA8, 0x8C, 0xF5, 0x30, +0xDB, 0x38, 0xD9, 0xD0, 0xDE, 0xDF, 0xA0, 0xD0, 0xDE, 0xDF, 0xD8, 0xA8, 0x48, 0xDB, 0x58, 0xD9, +0xDF, 0xD0, 0xDE, 0xA0, 0xDF, 0xD0, 0xDE, 0xD8, 0xA8, 0x68, 0xDB, 0x70, 0xD9, 0xDF, 0xDF, 0xA0, +0xDF, 0xDF, 0xD8, 0xF1, 0xA8, 0x88, 0x90, 0x2C, 0x54, 0x7C, 0x98, 0xA8, 0xD0, 0x5C, 0x38, 0xD1, +0xDA, 0xF2, 0xAE, 0x8C, 0xDF, 0xF9, 0xD8, 0xB0, 0x87, 0xA8, 0xC1, 0xC1, 0xB1, 0x88, 0xA8, 0xC6, +0xF9, 0xF9, 0xDA, 0x36, 0xD8, 0xA8, 0xF9, 0xDA, 0x36, 0xD8, 0xA8, 0xF9, 0xDA, 0x36, 0xD8, 0xA8, +0xF9, 0xDA, 0x36, 0xD8, 0xA8, 0xF9, 0xDA, 0x36, 0xD8, 0xF7, 0x8D, 0x9D, 0xAD, 0xF8, 0x18, 0xDA, +0xF2, 0xAE, 0xDF, 0xD8, 0xF7, 0xAD, 0xFA, 0x30, 0xD9, 0xA4, 0xDE, 0xF9, 0xD8, 0xF2, 0xAE, 0xDE, +0xFA, 0xF9, 0x83, 0xA7, 0xD9, 0xC3, 0xC5, 0xC7, 0xF1, 0x88, 0x9B, 0xA7, 0x7A, 0xAD, 0xF7, 0xDE, +0xDF, 0xA4, 0xF8, 0x84, 0x94, 0x08, 0xA7, 0x97, 0xF3, 0x00, 0xAE, 0xF2, 0x98, 0x19, 0xA4, 0x88, +0xC6, 0xA3, 0x94, 0x88, 0xF6, 0x32, 0xDF, 0xF2, 0x83, 0x93, 0xDB, 0x09, 0xD9, 0xF2, 0xAA, 0xDF, +0xD8, 0xD8, 0xAE, 0xF8, 0xF9, 0xD1, 0xDA, 0xF3, 0xA4, 0xDE, 0xA7, 0xF1, 0x88, 0x9B, 0x7A, 0xD8, +0xF3, 0x84, 0x94, 0xAE, 0x19, 0xF9, 0xDA, 0xAA, 0xF1, 0xDF, 0xD8, 0xA8, 0x81, 0xC0, 0xC3, 0xC5, +0xC7, 0xA3, 0x92, 0x83, 0xF6, 0x28, 0xAD, 0xDE, 0xD9, 0xF8, 0xD8, 0xA3, 0x50, 0xAD, 0xD9, 0xF8, +0xD8, 0xA3, 0x78, 0xAD, 0xD9, 0xF8, 0xD8, 0xF8, 0xF9, 0xD1, 0xA1, 0xDA, 0xDE, 0xC3, 0xC5, 0xC7, +0xD8, 0xA1, 0x81, 0x94, 0xF8, 0x18, 0xF2, 0xB0, 0x89, 0xAC, 0xC3, 0xC5, 0xC7, 0xF1, 0xD8, 0xB8, +/* bank # 9 */ +0xB4, 0xB0, 0x97, 0x86, 0xA8, 0x31, 0x9B, 0x06, 0x99, 0x07, 0xAB, 0x97, 0x28, 0x88, 0x9B, 0xF0, +0x0C, 0x20, 0x14, 0x40, 0xB0, 0xB4, 0xB8, 0xF0, 0xA8, 0x8A, 0x9A, 0x28, 0x50, 0x78, 0xB7, 0x9B, +0xA8, 0x29, 0x51, 0x79, 0x24, 0x70, 0x59, 0x44, 0x69, 0x38, 0x64, 0x48, 0x31, 0xF1, 0xBB, 0xAB, +0x88, 0x00, 0x2C, 0x54, 0x7C, 0xF0, 0xB3, 0x8B, 0xB8, 0xA8, 0x04, 0x28, 0x50, 0x78, 0xF1, 0xB0, +0x88, 0xB4, 0x97, 0x26, 0xA8, 0x59, 0x98, 0xBB, 0xAB, 0xB3, 0x8B, 0x02, 0x26, 0x46, 0x66, 0xB0, +0xB8, 0xF0, 0x8A, 0x9C, 0xA8, 0x29, 0x51, 0x79, 0x8B, 0x29, 0x51, 0x79, 0x8A, 0x24, 0x70, 0x59, +0x8B, 0x20, 0x58, 0x71, 0x8A, 0x44, 0x69, 0x38, 0x8B, 0x39, 0x40, 0x68, 0x8A, 0x64, 0x48, 0x31, +0x8B, 0x30, 0x49, 0x60, 0x88, 0xF1, 0xAC, 0x00, 0x2C, 0x54, 0x7C, 0xF0, 0x8C, 0xA8, 0x04, 0x28, +0x50, 0x78, 0xF1, 0x88, 0x97, 0x26, 0xA8, 0x59, 0x98, 0xAC, 0x8C, 0x02, 0x26, 0x46, 0x66, 0xF0, +0x89, 0x9C, 0xA8, 0x29, 0x51, 0x79, 0x24, 0x70, 0x59, 0x44, 0x69, 0x38, 0x64, 0x48, 0x31, 0xA9, +0x88, 0x09, 0x20, 0x59, 0x70, 0xAB, 0x11, 0x38, 0x40, 0x69, 0xA8, 0x19, 0x31, 0x48, 0x60, 0x8C, +0xA8, 0x3C, 0x41, 0x5C, 0x20, 0x7C, 0x00, 0xF1, 0x87, 0x98, 0x19, 0x86, 0xA8, 0x6E, 0x76, 0x7E, +0xA9, 0x99, 0x88, 0x2D, 0x55, 0x7D, 0xD8, 0xB1, 0xB5, 0xB9, 0xA3, 0xDF, 0xDF, 0xDF, 0xAE, 0xD0, +0xDF, 0xAA, 0xD0, 0xDE, 0xF2, 0xAB, 0xF8, 0xF9, 0xD9, 0xB0, 0x87, 0xC4, 0xAA, 0xF1, 0xDF, 0xDF, +0xBB, 0xAF, 0xDF, 0xDF, 0xB9, 0xD8, 0xB1, 0xF1, 0xA3, 0x97, 0x8E, 0x60, 0xDF, 0xB0, 0x84, 0xF2, +0xC8, 0xF8, 0xF9, 0xD9, 0xDE, 0xD8, 0x93, 0x85, 0xF1, 0x4A, 0xB1, 0x83, 0xA3, 0x08, 0xB5, 0x83, +/* bank # 10 */ +0x9A, 0x08, 0x10, 0xB7, 0x9F, 0x10, 0xD8, 0xF1, 0xB0, 0xBA, 0xAE, 0xB0, 0x8A, 0xC2, 0xB2, 0xB6, +0x8E, 0x9E, 0xF1, 0xFB, 0xD9, 0xF4, 0x1D, 0xD8, 0xF9, 0xD9, 0x0C, 0xF1, 0xD8, 0xF8, 0xF8, 0xAD, +0x61, 0xD9, 0xAE, 0xFB, 0xD8, 0xF4, 0x0C, 0xF1, 0xD8, 0xF8, 0xF8, 0xAD, 0x19, 0xD9, 0xAE, 0xFB, +0xDF, 0xD8, 0xF4, 0x16, 0xF1, 0xD8, 0xF8, 0xAD, 0x8D, 0x61, 0xD9, 0xF4, 0xF4, 0xAC, 0xF5, 0x9C, +0x9C, 0x8D, 0xDF, 0x2B, 0xBA, 0xB6, 0xAE, 0xFA, 0xF8, 0xF4, 0x0B, 0xD8, 0xF1, 0xAE, 0xD0, 0xF8, +0xAD, 0x51, 0xDA, 0xAE, 0xFA, 0xF8, 0xF1, 0xD8, 0xB9, 0xB1, 0xB6, 0xA3, 0x83, 0x9C, 0x08, 0xB9, +0xB1, 0x83, 0x9A, 0xB5, 0xAA, 0xC0, 0xFD, 0x30, 0x83, 0xB7, 0x9F, 0x10, 0xB5, 0x8B, 0x93, 0xF2, +0x02, 0x02, 0xD1, 0xAB, 0xDA, 0xDE, 0xD8, 0xF1, 0xB0, 0x80, 0xBA, 0xAB, 0xC0, 0xC3, 0xB2, 0x84, +0xC1, 0xC3, 0xD8, 0xB1, 0xB9, 0xF3, 0x8B, 0xA3, 0x91, 0xB6, 0x09, 0xB4, 0xD9, 0xAB, 0xDE, 0xB0, +0x87, 0x9C, 0xB9, 0xA3, 0xDD, 0xF1, 0xB3, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0xB0, 0x87, 0x20, 0x28, +0x30, 0x38, 0xB2, 0x8B, 0xB6, 0x9B, 0xF2, 0xA3, 0xC0, 0xC8, 0xC2, 0xC4, 0xCC, 0xC6, 0xA3, 0xA3, +0xA3, 0xF1, 0xB0, 0x87, 0xB5, 0x9A, 0xD8, 0xF3, 0x9B, 0xA3, 0xA3, 0xDC, 0xBA, 0xAC, 0xDF, 0xB9, +0xA3, 0xFE, 0xF2, 0xAB, 0xC4, 0xAA, 0xF1, 0xDF, 0xDF, 0xBB, 0xAF, 0xDF, 0xDF, 0xA3, 0xA3, 0xA3, +0xD8, 0xD8, 0xD8, 0xBB, 0xB3, 0xB7, 0xF1, 0xAA, 0xF9, 0xDA, 0xFF, 0xD9, 0x80, 0x9A, 0xAA, 0x28, +0xB4, 0x80, 0x98, 0xA7, 0x20, 0xB7, 0x97, 0x87, 0xA8, 0x66, 0x88, 0xF0, 0x79, 0x51, 0xF1, 0x90, +0x2C, 0x87, 0x0C, 0xA7, 0x81, 0x97, 0x62, 0x93, 0xF0, 0x71, 0x71, 0x60, 0x85, 0x94, 0x01, 0x29, +/* bank # 11 */ +0x51, 0x79, 0x90, 0xA5, 0xF1, 0x28, 0x4C, 0x6C, 0x87, 0x0C, 0x95, 0x18, 0x85, 0x78, 0xA3, 0x83, +0x90, 0x28, 0x4C, 0x6C, 0x88, 0x6C, 0xD8, 0xF3, 0xA2, 0x82, 0x00, 0xF2, 0x10, 0xA8, 0x92, 0x19, +0x80, 0xA2, 0xF2, 0xD9, 0x26, 0xD8, 0xF1, 0x88, 0xA8, 0x4D, 0xD9, 0x48, 0xD8, 0x96, 0xA8, 0x39, +0x80, 0xD9, 0x3C, 0xD8, 0x95, 0x80, 0xA8, 0x39, 0xA6, 0x86, 0x98, 0xD9, 0x2C, 0xDA, 0x87, 0xA7, +0x2C, 0xD8, 0xA8, 0x89, 0x95, 0x19, 0xA9, 0x80, 0xD9, 0x38, 0xD8, 0xA8, 0x89, 0x39, 0xA9, 0x80, +0xDA, 0x3C, 0xD8, 0xA8, 0x2E, 0xA8, 0x39, 0x90, 0xD9, 0x0C, 0xD8, 0xA8, 0x95, 0x31, 0x98, 0xD9, +0x0C, 0xD8, 0xA8, 0x09, 0xD9, 0xFF, 0xD8, 0x01, 0xDA, 0xFF, 0xD8, 0x95, 0x39, 0xA9, 0xDA, 0x26, +0xFF, 0xD8, 0x90, 0xA8, 0x0D, 0x89, 0x99, 0xA8, 0x10, 0x80, 0x98, 0x21, 0xDA, 0x2E, 0xD8, 0x89, +0x99, 0xA8, 0x31, 0x80, 0xDA, 0x2E, 0xD8, 0xA8, 0x86, 0x96, 0x31, 0x80, 0xDA, 0x2E, 0xD8, 0xA8, +0x87, 0x31, 0x80, 0xDA, 0x2E, 0xD8, 0xA8, 0x82, 0x92, 0xF3, 0x41, 0x80, 0xF1, 0xD9, 0x2E, 0xD8, +0xA8, 0x82, 0xF3, 0x19, 0x80, 0xF1, 0xD9, 0x2E, 0xD8, 0x82, 0xAC, 0xF3, 0xC0, 0xA2, 0x80, 0x22, +0xF1, 0xA6, 0x2E, 0xA7, 0x2E, 0xA9, 0x22, 0x98, 0xA8, 0x29, 0xDA, 0xAC, 0xDE, 0xFF, 0xD8, 0xA2, +0xF2, 0x2A, 0xF1, 0xA9, 0x2E, 0x82, 0x92, 0xA8, 0xF2, 0x31, 0x80, 0xA6, 0x96, 0xF1, 0xD9, 0x00, +0xAC, 0x8C, 0x9C, 0x0C, 0x30, 0xAC, 0xDE, 0xD0, 0xDE, 0xFF, 0xD8, 0x8C, 0x9C, 0xAC, 0xD0, 0x10, +0xAC, 0xDE, 0x80, 0x92, 0xA2, 0xF2, 0x4C, 0x82, 0xA8, 0xF1, 0xCA, 0xF2, 0x35, 0xF1, 0x96, 0x88, +0xA6, 0xD9, 0x00, 0xD8, 0xF1, 0xFF, +}; + +#ifndef MPU6050_DMP_FIFO_RATE_DIVISOR +#define MPU6050_DMP_FIFO_RATE_DIVISOR 0x01 // The New instance of the Firmware has this as the default +#endif + +// this is the most basic initialization I can create we access the register bytes as few times as needed to get the job done: + + +uint8_t MPU6050::dmpInitialize() { // Lets get it over with fast Write everything once and set it up necely + uint8_t val; + uint16_t ival; + // Reset procedure per instructions in the "MPU-6000/MPU-6050 Register Map and Descriptions" page 41 + I2Cdev::writeBit(devAddr,0x6B, 7, &(val = 1)); //PWR_MGMT_1: reset with 100ms delay + delay(100); + I2Cdev::writeBits(devAddr,0x6A, 2, 3, &(val = 0b111)); // full SIGNAL_PATH_RESET: with another 100ms delay + delay(100); + I2Cdev::writeBytes(devAddr,0x6B, 1, &(val = 0x01)); // 1000 0001 PWR_MGMT_1:Clock Source Select PLL_X_gyro + I2Cdev::writeBytes(devAddr,0x38, 1, &(val = 0x00)); // 0000 0000 INT_ENABLE: no Interrupt + I2Cdev::writeBytes(devAddr,0x23, 1, &(val = 0x00)); // 0000 0000 MPU FIFO_EN: (all off) Using DMP's FIFO instead + I2Cdev::writeBytes(devAddr,0x1C, 1, &(val = 0x00)); // 0000 0000 ACCEL_CONFIG: 0 = Accel Full Scale Select: 2g + I2Cdev::writeBytes(devAddr,0x37, 1, &(val = 0x80)); // 1001 0000 INT_PIN_CFG: ACTL The logic level for int pin is active low. and interrupt status bits are cleared on any read + I2Cdev::writeBytes(devAddr,0x6B, 1, &(val = 0x01)); // 0000 0001 PWR_MGMT_1: Clock Source Select PLL_X_gyro + I2Cdev::writeBytes(devAddr,0x19, 1, &(val = 0x04)); // 0000 0100 SMPLRT_DIV: Divides the internal sample rate 400Hz ( Sample Rate = Gyroscope Output Rate / (1 + SMPLRT_DIV)) + I2Cdev::writeBytes(devAddr,0x1A, 1, &(val = 0x01)); // 0000 0001 CONFIG: Digital Low Pass Filter (DLPF) Configuration 188HZ //Im betting this will be the beat + if (!writeProgMemoryBlock(dmpMemory, MPU6050_DMP_CODE_SIZE)) return 1; // Loads the DMP image into the MPU6050 Memory // Should Never Fail + I2Cdev::writeWords(devAddr, 0x70, 1, &(ival = 0x0400)); // DMP Program Start Address + I2Cdev::writeBytes(devAddr,0x1B, 1, &(val = 0x18)); // 0001 1000 GYRO_CONFIG: 3 = +2000 Deg/sec + I2Cdev::writeBytes(devAddr,0x6A, 1, &(val = 0xC0)); // 1100 1100 USER_CTRL: Enable Fifo and Reset Fifo + I2Cdev::writeBytes(devAddr,0x38, 1, &(val = 0x02)); // 0000 0010 INT_ENABLE: RAW_DMP_INT_EN on + I2Cdev::writeBit(devAddr,0x6A, 2, &(val = 1)); // Reset FIFO one last time just for kicks. (MPUi2cWrite reads 0x6A first and only alters 1 bit and then saves the byte) + setDMPEnabled(false); +/* + dmpPacketSize += 16;//DMP_FEATURE_6X_LP_QUAT + dmpPacketSize += 6;//DMP_FEATURE_SEND_RAW_ACCEL + dmpPacketSize += 6;//DMP_FEATURE_SEND_RAW_GYRO +*/ + dmpPacketSize = 28; + return 0; +} + +bool MPU6050::dmpPacketAvailable() { + return getFIFOCount() >= dmpGetFIFOPacketSize(); +} + +// uint8_t MPU6050::dmpSetFIFORate(uint8_t fifoRate); +// uint8_t MPU6050::dmpGetFIFORate(); +// uint8_t MPU6050::dmpGetSampleStepSizeMS(); +// uint8_t MPU6050::dmpGetSampleFrequency(); +// int32_t MPU6050::dmpDecodeTemperature(int8_t tempReg); + +//uint8_t MPU6050::dmpRegisterFIFORateProcess(inv_obj_func func, int16_t priority); +//uint8_t MPU6050::dmpUnregisterFIFORateProcess(inv_obj_func func); +//uint8_t MPU6050::dmpRunFIFORateProcesses(); + +// uint8_t MPU6050::dmpSendQuaternion(uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendGyro(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendAccel(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendLinearAccel(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendLinearAccelInWorld(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendControlData(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendSensorData(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendExternalSensorData(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendGravity(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendPacketNumber(uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendQuantizedAccel(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendEIS(uint_fast16_t elements, uint_fast16_t accuracy); + +uint8_t MPU6050::dmpGetAccel(int32_t *data, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + data[0] = (((uint32_t)packet[16] << 8) | packet[17]); + data[1] = (((uint32_t)packet[18] << 8) | packet[19]); + data[2] = (((uint32_t)packet[20] << 8) | packet[21]); + return 0; +} +uint8_t MPU6050::dmpGetAccel(int16_t *data, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + data[0] = (packet[16] << 8) | packet[17]; + data[1] = (packet[18] << 8) | packet[19]; + data[2] = (packet[20] << 8) | packet[21]; + return 0; +} +uint8_t MPU6050::dmpGetAccel(VectorInt16 *v, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + v -> x = (packet[16] << 8) | packet[17]; + v -> y = (packet[18] << 8) | packet[19]; + v -> z = (packet[20] << 8) | packet[21]; + return 0; +} +uint8_t MPU6050::dmpGetQuaternion(int32_t *data, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + data[0] = (((uint32_t)packet[0] << 24) | ((uint32_t)packet[1] << 16) | ((uint32_t)packet[2] << 8) | packet[3]); + data[1] = (((uint32_t)packet[4] << 24) | ((uint32_t)packet[5] << 16) | ((uint32_t)packet[6] << 8) | packet[7]); + data[2] = (((uint32_t)packet[8] << 24) | ((uint32_t)packet[9] << 16) | ((uint32_t)packet[10] << 8) | packet[11]); + data[3] = (((uint32_t)packet[12] << 24) | ((uint32_t)packet[13] << 16) | ((uint32_t)packet[14] << 8) | packet[15]); + return 0; +} +uint8_t MPU6050::dmpGetQuaternion(int16_t *data, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + data[0] = ((packet[0] << 8) | packet[1]); + data[1] = ((packet[4] << 8) | packet[5]); + data[2] = ((packet[8] << 8) | packet[9]); + data[3] = ((packet[12] << 8) | packet[13]); + return 0; +} +uint8_t MPU6050::dmpGetQuaternion(Quaternion *q, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + int16_t qI[4]; + uint8_t status = dmpGetQuaternion(qI, packet); + if (status == 0) { + q -> w = (float)qI[0] / 16384.0f; + q -> x = (float)qI[1] / 16384.0f; + q -> y = (float)qI[2] / 16384.0f; + q -> z = (float)qI[3] / 16384.0f; + return 0; + } + return status; // int16 return value, indicates error if this line is reached +} +// uint8_t MPU6050::dmpGet6AxisQuaternion(long *data, const uint8_t* packet); +// uint8_t MPU6050::dmpGetRelativeQuaternion(long *data, const uint8_t* packet); +uint8_t MPU6050::dmpGetGyro(int32_t *data, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + data[0] = (((uint32_t)packet[22] << 8) | packet[23]); + data[1] = (((uint32_t)packet[24] << 8) | packet[25]); + data[2] = (((uint32_t)packet[26] << 8) | packet[27]); + return 0; +} +uint8_t MPU6050::dmpGetGyro(int16_t *data, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + data[0] = (packet[22] << 8) | packet[23]; + data[1] = (packet[24] << 8) | packet[25]; + data[2] = (packet[26] << 8) | packet[27]; + return 0; +} +uint8_t MPU6050::dmpGetGyro(VectorInt16 *v, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + v -> x = (packet[22] << 8) | packet[23]; + v -> y = (packet[24] << 8) | packet[25]; + v -> z = (packet[26] << 8) | packet[27]; + return 0; +} +// uint8_t MPU6050::dmpSetLinearAccelFilterCoefficient(float coef); +// uint8_t MPU6050::dmpGetLinearAccel(long *data, const uint8_t* packet); +uint8_t MPU6050::dmpGetLinearAccel(VectorInt16 *v, VectorInt16 *vRaw, VectorFloat *gravity) { + // get rid of the gravity component (+1g = +8192 in standard DMP FIFO packet, sensitivity is 2g) + v -> x = vRaw -> x - gravity -> x*8192; + v -> y = vRaw -> y - gravity -> y*8192; + v -> z = vRaw -> z - gravity -> z*8192; + return 0; +} +// uint8_t MPU6050::dmpGetLinearAccelInWorld(long *data, const uint8_t* packet); +uint8_t MPU6050::dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Quaternion *q) { + // rotate measured 3D acceleration vector into original state + // frame of reference based on orientation quaternion + memcpy(v, vReal, sizeof(VectorInt16)); + v -> rotate(q); + return 0; +} +// uint8_t MPU6050::dmpGetGyroAndAccelSensor(long *data, const uint8_t* packet); +// uint8_t MPU6050::dmpGetGyroSensor(long *data, const uint8_t* packet); +// uint8_t MPU6050::dmpGetControlData(long *data, const uint8_t* packet); +// uint8_t MPU6050::dmpGetTemperature(long *data, const uint8_t* packet); +// uint8_t MPU6050::dmpGetGravity(long *data, const uint8_t* packet); +uint8_t MPU6050::dmpGetGravity(int16_t *data, const uint8_t* packet) { + /* +1g corresponds to +8192, sensitivity is 2g. */ + int16_t qI[4]; + uint8_t status = dmpGetQuaternion(qI, packet); + data[0] = ((int32_t)qI[1] * qI[3] - (int32_t)qI[0] * qI[2]) / 16384; + data[1] = ((int32_t)qI[0] * qI[1] + (int32_t)qI[2] * qI[3]) / 16384; + data[2] = ((int32_t)qI[0] * qI[0] - (int32_t)qI[1] * qI[1] + - (int32_t)qI[2] * qI[2] + (int32_t)qI[3] * qI[3]) / (2 * 16384); + return status; +} + +uint8_t MPU6050::dmpGetGravity(VectorFloat *v, Quaternion *q) { + v -> x = 2 * (q -> x*q -> z - q -> w*q -> y); + v -> y = 2 * (q -> w*q -> x + q -> y*q -> z); + v -> z = q -> w*q -> w - q -> x*q -> x - q -> y*q -> y + q -> z*q -> z; + return 0; +} +// uint8_t MPU6050::dmpGetUnquantizedAccel(long *data, const uint8_t* packet); +// uint8_t MPU6050::dmpGetQuantizedAccel(long *data, const uint8_t* packet); +// uint8_t MPU6050::dmpGetExternalSensorData(long *data, int size, const uint8_t* packet); +// uint8_t MPU6050::dmpGetEIS(long *data, const uint8_t* packet); + +uint8_t MPU6050::dmpGetEuler(float *data, Quaternion *q) { + data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1); // psi + data[1] = -asin(2*q -> x*q -> z + 2*q -> w*q -> y); // theta + data[2] = atan2(2*q -> y*q -> z - 2*q -> w*q -> x, 2*q -> w*q -> w + 2*q -> z*q -> z - 1); // phi + return 0; +} + +#ifdef USE_OLD_DMPGETYAWPITCHROLL +uint8_t MPU6050::dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity) { + // yaw: (about Z axis) + data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1); + // pitch: (nose up/down, about Y axis) + data[1] = atan(gravity -> x / sqrt(gravity -> y*gravity -> y + gravity -> z*gravity -> z)); + // roll: (tilt left/right, about X axis) + data[2] = atan(gravity -> y / sqrt(gravity -> x*gravity -> x + gravity -> z*gravity -> z)); + return 0; +} +#else +uint8_t MPU6050::dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity) { + // yaw: (about Z axis) + data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1); + // pitch: (nose up/down, about Y axis) + data[1] = atan2(gravity -> x , sqrt(gravity -> y*gravity -> y + gravity -> z*gravity -> z)); + // roll: (tilt left/right, about X axis) + data[2] = atan2(gravity -> y , gravity -> z); + if (gravity -> z < 0) { + if(data[1] > 0) { + data[1] = PI - data[1]; + } else { + data[1] = -PI - data[1]; + } + } + return 0; +} +#endif + +// uint8_t MPU6050::dmpGetAccelFloat(float *data, const uint8_t* packet); +// uint8_t MPU6050::dmpGetQuaternionFloat(float *data, const uint8_t* packet); + +uint8_t MPU6050::dmpProcessFIFOPacket(const unsigned char *dmpData) { + /*for (uint8_t k = 0; k < dmpPacketSize; k++) { + if (dmpData[k] < 0x10) Serial.print("0"); + Serial.print(dmpData[k], HEX); + Serial.print(" "); + } + Serial.print("\n");*/ + //Serial.println((uint16_t)dmpPacketBuffer); + return 0; +} +uint8_t MPU6050::dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *processed) { + uint8_t status; + uint8_t buf[dmpPacketSize]; + for (uint8_t i = 0; i < numPackets; i++) { + // read packet from FIFO + getFIFOBytes(buf, dmpPacketSize); + + // process packet + if ((status = dmpProcessFIFOPacket(buf)) > 0) return status; + + // increment external process count variable, if supplied + if (processed != 0) (*processed)++; + } + return 0; +} + +// uint8_t MPU6050::dmpSetFIFOProcessedCallback(void (*func) (void)); + +// uint8_t MPU6050::dmpInitFIFOParam(); +// uint8_t MPU6050::dmpCloseFIFO(); +// uint8_t MPU6050::dmpSetGyroDataSource(uint_fast8_t source); +// uint8_t MPU6050::dmpDecodeQuantizedAccel(); +// uint32_t MPU6050::dmpGetGyroSumOfSquare(); +// uint32_t MPU6050::dmpGetAccelSumOfSquare(); +// void MPU6050::dmpOverrideQuaternion(long *q); +uint16_t MPU6050::dmpGetFIFOPacketSize() { + return dmpPacketSize; +} + +#endif /* _MPU6050_6AXIS_MOTIONAPPS20_H_ */ From 9c51c63dad91e1d8b5313436e183ee719c0b9309 Mon Sep 17 00:00:00 2001 From: Homer Creutz Date: Wed, 10 Jul 2019 00:36:23 -0600 Subject: [PATCH 209/335] DMP6 example using Firmware V6.12 This uses the newly created MPU6050_6Axis_MotionApps_V6_12.h available from: https://www.invensense.com/developers/software-downloads/#sla_content_45 Feature Description: "Embedded MotionDriver 6.12 is our first ever 9-axis solution not locked to a specific MCU.Version 6.1.2 is an update to 6.1 that includes bug fixes and new libraries. This release is supported across all ARM Mx core architectures and supports the InvenSense MPU-6000, 6050, 6500, 9150, and 9250. The release includes optimized libraries and example projects for M3 and M4 cores as well the generic ARM library for any Mx core and an additional library and project for the TI MSP430. eMD 6.1 also includes a Python client for both visualizing the sensor performance and commands for printing data. This solution will allow you to easily leverage and configure numerous features of the DMP and also benefit from dynamic features in the MPL software library. Libraries specific to IAR, Keil, and GCC are included." --- ...050_DMP6_usingV6.12MPU6050_DMP6_usingV6.12 | 408 ++++++++++++++++++ 1 file changed, 408 insertions(+) create mode 100644 Arduino/MPU6050/examples/MPU6050_DMP6_usingV6.12MPU6050_DMP6_usingV6.12 diff --git a/Arduino/MPU6050/examples/MPU6050_DMP6_usingV6.12MPU6050_DMP6_usingV6.12 b/Arduino/MPU6050/examples/MPU6050_DMP6_usingV6.12MPU6050_DMP6_usingV6.12 new file mode 100644 index 00000000..5e1bb534 --- /dev/null +++ b/Arduino/MPU6050/examples/MPU6050_DMP6_usingV6.12MPU6050_DMP6_usingV6.12 @@ -0,0 +1,408 @@ +// I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class using DMP (MotionApps v2.0) +// 6/21/2012 by Jeff Rowberg +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// 2019-07-10 - Uses the new version of the DMP Firmware V6.12 +// 2016-04-18 - Eliminated a potential infinite loop +// 2013-05-08 - added seamless Fastwire support +// - added note about gyro calibration +// 2012-06-21 - added note about Arduino 1.0.1 + Leonardo compatibility error +// 2012-06-20 - improved FIFO overflow handling and simplified read process +// 2012-06-19 - completely rearranged DMP initialization code and simplification +// 2012-06-13 - pull gyro and accel data from FIFO packet instead of reading directly +// 2012-06-09 - fix broken FIFO read sequence and change interrupt detection to RISING +// 2012-06-05 - add gravity-compensated initial reference frame acceleration output +// - add 3D math helper file to DMP6 example sketch +// - add Euler output and Yaw/Pitch/Roll output formats +// 2012-06-04 - remove accel offset clearing for better results (thanks Sungon Lee) +// 2012-06-01 - fixed gyro sensitivity to be 2000 deg/sec instead of 250 +// 2012-05-30 - basic DMP initialization working + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2012 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +// I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files +// for both classes must be in the include path of your project +#include "I2Cdev.h" + +#include "MPU6050_6Axis_MotionApps_V6_12.h" +//#include "MPU6050.h" // not necessary if using MotionApps include file + +// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation +// is used in I2Cdev.h +#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE + #include "Wire.h" +#endif + +// class default I2C address is 0x68 +// specific I2C addresses may be passed as a parameter here +// AD0 low = 0x68 (default for SparkFun breakout and InvenSense evaluation board) +// AD0 high = 0x69 +MPU6050 mpu; +//MPU6050 mpu(0x69); // <-- use for AD0 high + +/* ========================================================================= + NOTE: In addition to connection 3.3v, GND, SDA, and SCL, this sketch + depends on the MPU-6050's INT pin being connected to the Arduino's + external interrupt #0 pin. On the Arduino Uno and Mega 2560, this is + digital I/O pin 2. + * ========================================================================= */ + +/* ========================================================================= + NOTE: Arduino v1.0.1 with the Leonardo board generates a compile error + when using Serial.write(buf, len). The Teapot output uses this method. + The solution requires a modification to the Arduino USBAPI.h file, which + is fortunately simple, but annoying. This will be fixed in the next IDE + release. For more info, see these links: + + http://arduino.cc/forum/index.php/topic,109987.0.html + http://code.google.com/p/arduino/issues/detail?id=958 + * ========================================================================= */ + + + +// uncomment "OUTPUT_READABLE_QUATERNION" if you want to see the actual +// quaternion components in a [w, x, y, z] format (not best for parsing +// on a remote host such as Processing or something though) +//#define OUTPUT_READABLE_QUATERNION + +// uncomment "OUTPUT_READABLE_EULER" if you want to see Euler angles +// (in degrees) calculated from the quaternions coming from the FIFO. +// Note that Euler angles suffer from gimbal lock (for more info, see +// http://en.wikipedia.org/wiki/Gimbal_lock) +//#define OUTPUT_READABLE_EULER + +// uncomment "OUTPUT_READABLE_YAWPITCHROLL" if you want to see the yaw/ +// pitch/roll angles (in degrees) calculated from the quaternions coming +// from the FIFO. Note this also requires gravity vector calculations. +// Also note that yaw/pitch/roll angles suffer from gimbal lock (for +// more info, see: http://en.wikipedia.org/wiki/Gimbal_lock) +#define OUTPUT_READABLE_YAWPITCHROLL + +// uncomment "OUTPUT_READABLE_REALACCEL" if you want to see acceleration +// components with gravity removed. This acceleration reference frame is +// not compensated for orientation, so +X is always +X according to the +// sensor, just without the effects of gravity. If you want acceleration +// compensated for orientation, us OUTPUT_READABLE_WORLDACCEL instead. +//#define OUTPUT_READABLE_REALACCEL + +// uncomment "OUTPUT_READABLE_WORLDACCEL" if you want to see acceleration +// components with gravity removed and adjusted for the world frame of +// reference (yaw is relative to initial orientation, since no magnetometer +// is present in this case). Could be quite handy in some cases. +//#define OUTPUT_READABLE_WORLDACCEL + +// uncomment "OUTPUT_TEAPOT" if you want output that matches the +// format used for the InvenSense teapot demo +//#define OUTPUT_TEAPOT + + + +#define INTERRUPT_PIN 2 // use pin 2 on Arduino Uno & most boards +#define LED_PIN 13 // (Arduino is 13, Teensy is 11, Teensy++ is 6) +bool blinkState = false; + +// MPU control/status vars +bool dmpReady = false; // set true if DMP init was successful +uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU +uint8_t devStatus; // return status after each device operation (0 = success, !0 = error) +uint16_t packetSize; // expected DMP packet size (default is 42 bytes) +uint16_t fifoCount; // count of all bytes currently in FIFO +uint8_t fifoBuffer[64]; // FIFO storage buffer + +// orientation/motion vars +Quaternion q; // [w, x, y, z] quaternion container +VectorInt16 aa; // [x, y, z] accel sensor measurements +VectorInt16 gy; // [x, y, z] gyro sensor measurements +VectorInt16 aaReal; // [x, y, z] gravity-free accel sensor measurements +VectorInt16 aaWorld; // [x, y, z] world-frame accel sensor measurements +VectorFloat gravity; // [x, y, z] gravity vector +float euler[3]; // [psi, theta, phi] Euler angle container +float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector + +// packet structure for InvenSense teapot demo +uint8_t teapotPacket[14] = { '$', 0x02, 0,0, 0,0, 0,0, 0,0, 0x00, 0x00, '\r', '\n' }; + + + +// ================================================================ +// === INTERRUPT DETECTION ROUTINE === +// ================================================================ + +volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high +void dmpDataReady() { + mpuInterrupt = true; +} + + + +// ================================================================ +// === INITIAL SETUP === +// ================================================================ + +void setup() { + // join I2C bus (I2Cdev library doesn't do this automatically) + #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE + Wire.begin(); + Wire.setClock(400000); // 400kHz I2C clock. Comment this line if having compilation difficulties + #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE + Fastwire::setup(400, true); + #endif + + // initialize serial communication + // (115200 chosen because it is required for Teapot Demo output, but it's + // really up to you depending on your project) + Serial.begin(115200); + while (!Serial); // wait for Leonardo enumeration, others continue immediately + + // NOTE: 8MHz or slower host processors, like the Teensy @ 3.3V or Arduino + // Pro Mini running at 3.3V, cannot handle this baud rate reliably due to + // the baud timing being too misaligned with processor ticks. You must use + // 38400 or slower in these cases, or use some kind of external separate + // crystal solution for the UART timer. + + // initialize device + Serial.println(F("Initializing I2C devices...")); + mpu.initialize(); + pinMode(INTERRUPT_PIN, INPUT); + + // verify connection + Serial.println(F("Testing device connections...")); + Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed")); + + // wait for ready + Serial.println(F("\nSend any character to begin DMP programming and demo: ")); + while (Serial.available() && Serial.read()); // empty buffer + while (!Serial.available()); // wait for data + while (Serial.available() && Serial.read()); // empty buffer again + + // load and configure the DMP + Serial.println(F("Initializing DMP...")); + devStatus = mpu.dmpInitialize(); + + // supply your own gyro offsets here, scaled for min sensitivity + mpu.setXGyroOffset(51); + mpu.setYGyroOffset(8); + mpu.setZGyroOffset(21); + mpu.setXAccelOffset(1150); + mpu.setYAccelOffset(-50); + mpu.setZAccelOffset(1060); + // make sure it worked (returns 0 if so) + if (devStatus == 0) { + // Calibration Time: generate offsets and calibrate our MPU6050 + mpu.CalibrateAccel(6); + mpu.CalibrateGyro(6); + Serial.println(); + mpu.PrintActiveOffsets(); + // turn on the DMP, now that it's ready + Serial.println(F("Enabling DMP...")); + mpu.setDMPEnabled(true); + + // enable Arduino interrupt detection + Serial.print(F("Enabling interrupt detection (Arduino external interrupt ")); + Serial.print(digitalPinToInterrupt(INTERRUPT_PIN)); + Serial.println(F(")...")); + attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), dmpDataReady, RISING); + mpuIntStatus = mpu.getIntStatus(); + + // set our DMP Ready flag so the main loop() function knows it's okay to use it + Serial.println(F("DMP ready! Waiting for first interrupt...")); + dmpReady = true; + + // get expected DMP packet size for later comparison + packetSize = mpu.dmpGetFIFOPacketSize(); + } else { + // ERROR! + // 1 = initial memory load failed + // 2 = DMP configuration updates failed + // (if it's going to break, usually the code will be 1) + Serial.print(F("DMP Initialization failed (code ")); + Serial.print(devStatus); + Serial.println(F(")")); + } + + // configure LED for output + pinMode(LED_PIN, OUTPUT); +} + + + +// ================================================================ +// === MAIN PROGRAM LOOP === +// ================================================================ + +void loop() { + // if programming failed, don't try to do anything + if (!dmpReady) return; + + // wait for MPU interrupt or extra packet(s) available + while (!mpuInterrupt && fifoCount < packetSize) { + if (mpuInterrupt && fifoCount < packetSize) { + // try to get out of the infinite loop + fifoCount = mpu.getFIFOCount(); + } + // other program behavior stuff here + // . + // . + // . + // if you are really paranoid you can frequently test in between other + // stuff to see if mpuInterrupt is true, and if so, "break;" from the + // while() loop to immediately process the MPU data + // . + // . + // . + } + + // reset interrupt flag and get INT_STATUS byte + mpuInterrupt = false; + mpuIntStatus = mpu.getIntStatus(); + + // get current FIFO count + fifoCount = mpu.getFIFOCount(); + + // check for overflow (this should never happen unless our code is too inefficient) + if ((mpuIntStatus & _BV(MPU6050_INTERRUPT_FIFO_OFLOW_BIT)) || fifoCount >= 1024) { + // reset so we can continue cleanly + mpu.resetFIFO(); + fifoCount = mpu.getFIFOCount(); + Serial.println(F("FIFO overflow!")); + + // otherwise, check for DMP data ready interrupt (this should happen frequently) + } else if (mpuIntStatus & _BV(MPU6050_INTERRUPT_DMP_INT_BIT)) { + // wait for correct available data length, should be a VERY short wait + while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount(); + + // read a packet from FIFO + mpu.getFIFOBytes(fifoBuffer, packetSize); + + // track FIFO count here in case there is > 1 packet available + // (this lets us immediately read more without waiting for an interrupt) + fifoCount -= packetSize; + + #ifdef OUTPUT_READABLE_QUATERNION + // display quaternion values in easy matrix form: w x y z + mpu.dmpGetQuaternion(&q, fifoBuffer); + Serial.print("quat\t"); + Serial.print(q.w); + Serial.print("\t"); + Serial.print(q.x); + Serial.print("\t"); + Serial.print(q.y); + Serial.print("\t"); + Serial.println(q.z); + #endif + + #ifdef OUTPUT_READABLE_EULER + // display Euler angles in degrees + mpu.dmpGetQuaternion(&q, fifoBuffer); + mpu.dmpGetEuler(euler, &q); + Serial.print("euler\t"); + Serial.print(euler[0] * 180/M_PI); + Serial.print("\t"); + Serial.print(euler[1] * 180/M_PI); + Serial.print("\t"); + Serial.println(euler[2] * 180/M_PI); + #endif + + #ifdef OUTPUT_READABLE_YAWPITCHROLL + // display Euler angles in degrees + mpu.dmpGetQuaternion(&q, fifoBuffer); + mpu.dmpGetGravity(&gravity, &q); + mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); + Serial.print("ypr\t"); + Serial.print(ypr[0] * 180/M_PI); + Serial.print("\t"); + Serial.print(ypr[1] * 180/M_PI); + Serial.print("\t"); + Serial.print(ypr[2] * 180/M_PI); + /* + mpu.dmpGetAccel(&aa, fifoBuffer); + Serial.print("\tRaw Accl XYZ\t"); + Serial.print(aa.x); + Serial.print("\t"); + Serial.print(aa.y); + Serial.print("\t"); + Serial.print(aa.z); + mpu.dmpGetGyro(&gy, fifoBuffer); + Serial.print("\tRaw Gyro XYZ\t"); + Serial.print(gy.x); + Serial.print("\t"); + Serial.print(gy.y); + Serial.print("\t"); + Serial.print(gy.z); + */ + Serial.println(); + + #endif + + #ifdef OUTPUT_READABLE_REALACCEL + // display real acceleration, adjusted to remove gravity + mpu.dmpGetQuaternion(&q, fifoBuffer); + mpu.dmpGetAccel(&aa, fifoBuffer); + mpu.dmpGetGravity(&gravity, &q); + mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity); + Serial.print("areal\t"); + Serial.print(aaReal.x); + Serial.print("\t"); + Serial.print(aaReal.y); + Serial.print("\t"); + Serial.println(aaReal.z); + #endif + + #ifdef OUTPUT_READABLE_WORLDACCEL + // display initial world-frame acceleration, adjusted to remove gravity + // and rotated based on known orientation from quaternion + mpu.dmpGetQuaternion(&q, fifoBuffer); + mpu.dmpGetAccel(&aa, fifoBuffer); + mpu.dmpGetGravity(&gravity, &q); + mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity); + mpu.dmpGetLinearAccelInWorld(&aaWorld, &aaReal, &q); + Serial.print("aworld\t"); + Serial.print(aaWorld.x); + Serial.print("\t"); + Serial.print(aaWorld.y); + Serial.print("\t"); + Serial.println(aaWorld.z); + #endif + + #ifdef OUTPUT_TEAPOT + // display quaternion values in InvenSense Teapot demo format: + teapotPacket[2] = fifoBuffer[0]; + teapotPacket[3] = fifoBuffer[1]; + teapotPacket[4] = fifoBuffer[4]; + teapotPacket[5] = fifoBuffer[5]; + teapotPacket[6] = fifoBuffer[8]; + teapotPacket[7] = fifoBuffer[9]; + teapotPacket[8] = fifoBuffer[12]; + teapotPacket[9] = fifoBuffer[13]; + Serial.write(teapotPacket, 14); + teapotPacket[11]++; // packetCount, loops at 0xFF on purpose + #endif + + // blink LED to indicate activity + blinkState = !blinkState; + digitalWrite(LED_PIN, blinkState); + } +} From 2ff09947174cc5889c81631aa9d3ac0623a1344e Mon Sep 17 00:00:00 2001 From: Homer Creutz Date: Wed, 10 Jul 2019 00:36:47 -0600 Subject: [PATCH 210/335] Update MPU6050_6Axis_MotionApps_V6_12.h --- Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h b/Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h index 1e15ca28..a95639a3 100644 --- a/Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h +++ b/Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h @@ -4,7 +4,7 @@ // Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib // // Changelog: -// 2019/7/10 - I incorporated DMP Firmware Version 6.1.2 Latest as of today with many features and bug fixes. +// 2019/7/10 - I incorporated DMP Firmware Version 6.12 Latest as of today with many features and bug fixes. // - Run-time calibration routine is enabled which calibrates after no motion state is detected // - once no motion state is detected Calibration completes within 0.5 seconds // - The Drawback is that the firmware image is larger. From 990609773372cfc501f40ad6aad7c6901d43af33 Mon Sep 17 00:00:00 2001 From: Homer Creutz Date: Wed, 10 Jul 2019 00:54:51 -0600 Subject: [PATCH 211/335] Update MPU6050_6Axis_MotionApps_V6_12.h --- Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h b/Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h index a95639a3..57ee208b 100644 --- a/Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h +++ b/Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h @@ -341,13 +341,13 @@ const unsigned char dmpMemory[MPU6050_DMP_CODE_SIZE] PROGMEM = { 0xA6, 0xD9, 0x00, 0xD8, 0xF1, 0xFF, }; +// this divisor is pre configured into the above image and can't be modified at this time. #ifndef MPU6050_DMP_FIFO_RATE_DIVISOR -#define MPU6050_DMP_FIFO_RATE_DIVISOR 0x01 // The New instance of the Firmware has this as the default +#define MPU6050_DMP_FIFO_RATE_DIVISOR 0x01 // The New instance of the Firmware has this as the default #endif -// this is the most basic initialization I can create we access the register bytes as few times as needed to get the job done: - - +// this is the most basic initialization I can create. with the intent that we access the register bytes as few times as needed to get the job done. +// for detailed descriptins of all registers and there purpose google "MPU-6000/MPU-6050 Register Map and Descriptions" uint8_t MPU6050::dmpInitialize() { // Lets get it over with fast Write everything once and set it up necely uint8_t val; uint16_t ival; @@ -370,7 +370,7 @@ uint8_t MPU6050::dmpInitialize() { // Lets get it over with fast Write everythin I2Cdev::writeBytes(devAddr,0x6A, 1, &(val = 0xC0)); // 1100 1100 USER_CTRL: Enable Fifo and Reset Fifo I2Cdev::writeBytes(devAddr,0x38, 1, &(val = 0x02)); // 0000 0010 INT_ENABLE: RAW_DMP_INT_EN on I2Cdev::writeBit(devAddr,0x6A, 2, &(val = 1)); // Reset FIFO one last time just for kicks. (MPUi2cWrite reads 0x6A first and only alters 1 bit and then saves the byte) - setDMPEnabled(false); + setDMPEnabled(false); // disable DMP for compatibility with the MPU6050 library /* dmpPacketSize += 16;//DMP_FEATURE_6X_LP_QUAT dmpPacketSize += 6;//DMP_FEATURE_SEND_RAW_ACCEL From 3a98fb14a518f4d72f71982698eaaf7a85e6717d Mon Sep 17 00:00:00 2001 From: Homer Creutz Date: Wed, 10 Jul 2019 00:58:50 -0600 Subject: [PATCH 212/335] Update MPU6050_6Axis_MotionApps_V6_12.h --- Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h b/Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h index 57ee208b..aa1f9248 100644 --- a/Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h +++ b/Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h @@ -1,10 +1,11 @@ -// I2Cdev library collection - MPU6050 I2C device class, 6-axis MotionApps 2.0 implementation +// I2Cdev library collection - MPU6050 I2C device class, 6-axis MotionApps 6.12 implementation // Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00) // 5/20/2013 by Jeff Rowberg // Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib // // Changelog: // 2019/7/10 - I incorporated DMP Firmware Version 6.12 Latest as of today with many features and bug fixes. +// - MPU6050 Registers have not changed just the DMP Image so that full backwards compatibility is present // - Run-time calibration routine is enabled which calibrates after no motion state is detected // - once no motion state is detected Calibration completes within 0.5 seconds // - The Drawback is that the firmware image is larger. From 99b1c09fe0f7714a3df36ecec617ac453d5130d6 Mon Sep 17 00:00:00 2001 From: Homer Creutz Date: Wed, 10 Jul 2019 01:02:45 -0600 Subject: [PATCH 213/335] Update MPU6050_DMP6_usingV6.12MPU6050_DMP6_usingV6.12 --- .../examples/MPU6050_DMP6_usingV6.12MPU6050_DMP6_usingV6.12 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Arduino/MPU6050/examples/MPU6050_DMP6_usingV6.12MPU6050_DMP6_usingV6.12 b/Arduino/MPU6050/examples/MPU6050_DMP6_usingV6.12MPU6050_DMP6_usingV6.12 index 5e1bb534..31175909 100644 --- a/Arduino/MPU6050/examples/MPU6050_DMP6_usingV6.12MPU6050_DMP6_usingV6.12 +++ b/Arduino/MPU6050/examples/MPU6050_DMP6_usingV6.12MPU6050_DMP6_usingV6.12 @@ -1,9 +1,11 @@ -// I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class using DMP (MotionApps v2.0) +// I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class using DMP (MotionApps v6.12) // 6/21/2012 by Jeff Rowberg // Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib // // Changelog: // 2019-07-10 - Uses the new version of the DMP Firmware V6.12 +// - Note: I believe the Teapot demo is broken with this versin as +// - the fifo buffer structure has changed // 2016-04-18 - Eliminated a potential infinite loop // 2013-05-08 - added seamless Fastwire support // - added note about gyro calibration From be5041694ae4cdbccb7505ac9ae2f60af42052c7 Mon Sep 17 00:00:00 2001 From: Homer Creutz Date: Wed, 10 Jul 2019 01:09:17 -0600 Subject: [PATCH 214/335] Moved File --- .../MPU6050_DMP6_using_DMP_V6.12.ino} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Arduino/MPU6050/examples/{MPU6050_DMP6_usingV6.12MPU6050_DMP6_usingV6.12 => MPU6050_DMP6_using_DMP_V6.12/MPU6050_DMP6_using_DMP_V6.12.ino} (100%) diff --git a/Arduino/MPU6050/examples/MPU6050_DMP6_usingV6.12MPU6050_DMP6_usingV6.12 b/Arduino/MPU6050/examples/MPU6050_DMP6_using_DMP_V6.12/MPU6050_DMP6_using_DMP_V6.12.ino similarity index 100% rename from Arduino/MPU6050/examples/MPU6050_DMP6_usingV6.12MPU6050_DMP6_usingV6.12 rename to Arduino/MPU6050/examples/MPU6050_DMP6_using_DMP_V6.12/MPU6050_DMP6_using_DMP_V6.12.ino From 3f0f9fcad2375502647f3f6cb697df8c05609058 Mon Sep 17 00:00:00 2001 From: Homer Creutz Date: Thu, 11 Jul 2019 09:48:15 -0600 Subject: [PATCH 215/335] Added PID Calibration routine with 2016 code This allows us to compare the optimized PID code with the traditional averaging method original 2016 code. While not totally necessary, it is fast and provides a comparison without degrading the original version. A tidbit on how PID (PI actually) tuning works. When we change the offset in the MPU6050 we can get instant results. This allows us to use Proportional and integral of the PID to discover the ideal offsets. Integral is the key to discovering these offsets, Integral uses the error from set-point (set-point is zero), it takes a fraction of this error (error * ki) and adds it to the integral value. Each reading narrows the error down to the desired offset. The greater the error from set-point, the more we adjust the integral value. The proportional does its part by hiding the noise from the integral math. The derivative is not used because of the noise and because the sensor is stationary. With the noise removed the integral value lands on a solid offset after just 600 readings. At the end of each set of 100 readings, the integral value is used for the actual offsets and the last proportional reading is ignored due to the fact it reacts to any noise. --- .../MPU6050/examples/IMU_Zero/IMU_Zero.ino | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/Arduino/MPU6050/examples/IMU_Zero/IMU_Zero.ino b/Arduino/MPU6050/examples/IMU_Zero/IMU_Zero.ino index 0a5d27b2..a9f46ea9 100644 --- a/Arduino/MPU6050/examples/IMU_Zero/IMU_Zero.ino +++ b/Arduino/MPU6050/examples/IMU_Zero/IMU_Zero.ino @@ -6,6 +6,9 @@ // Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib // // Changelog: +// 2019-07-11 - added PID offset generation at begninning Generates first offsets +// - in @ 6 seconds and completes with 4 more sets @ 10 seconds +// - then continues with origional 2016 calibration code. // 2016-11-25 - added delays to reduce sampling rate to ~200 Hz // added temporizing printing during long computations // 2016-10-25 - requires inequality (Low < Target, High > Target) during expansion @@ -165,6 +168,43 @@ void Initialize() // verify connection Serial.println("Testing device connections..."); Serial.println(accelgyro.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed"); + Serial.println("PID tuning Each Dot = 100 readings"); + /*A tidbit on how PID (PI actually) tuning works. + When we change the offset in the MPU6050 we can get instant results. This allows us to use Proportional and + integral of the PID to discover the ideal offsets. Integral is the key to discovering these offsets, Integral + uses the error from set-point (set-point is zero), it takes a fraction of this error (error * ki) and adds it + to the integral value. Each reading narrows the error down to the desired offset. The greater the error from + set-point, the more we adjust the integral value. The proportional does its part by hiding the noise from the + integral math. The Derivative is not used because of the noise and because the sensor is stationary. With the + noise removed the integral value lands on a solid offset after just 600 readings. At the end of each set of 100 + readings, the integral value is used for the actual offsets and the last proportional reading is ignored due to + the fact it reacts to any noise. + */ + accelgyro.CalibrateAccel(6); + accelgyro.CalibrateGyro(6); + Serial.println("\nat 600 Readings"); + accelgyro.PrintActiveOffsets(); + Serial.println(); + accelgyro.CalibrateAccel(1); + accelgyro.CalibrateGyro(1); + Serial.println("700 Total Readings"); + accelgyro.PrintActiveOffsets(); + Serial.println(); + accelgyro.CalibrateAccel(1); + accelgyro.CalibrateGyro(1); + Serial.println("800 Total Readings"); + accelgyro.PrintActiveOffsets(); + Serial.println(); + accelgyro.CalibrateAccel(1); + accelgyro.CalibrateGyro(1); + Serial.println("900 Total Readings"); + accelgyro.PrintActiveOffsets(); + Serial.println(); + accelgyro.CalibrateAccel(1); + accelgyro.CalibrateGyro(1); + Serial.println("1000 Total Readings"); + accelgyro.PrintActiveOffsets(); + Serial.println("\n\n Any of the above offsets will work nice \n\n Lets proof the PID tuning using another method:"); } // Initialize void SetOffsets(int TheOffsets[6]) From 0e48df8edbf13caa2e88114add32ac482a59d96b Mon Sep 17 00:00:00 2001 From: Homer Creutz Date: Sat, 13 Jul 2019 16:22:00 -0600 Subject: [PATCH 216/335] Bug Fix writeWords() skips every other word I Discovered that writeWords() skips every other word starting with the second int for example: 0x0111 , 0x0222, 0x0333, 0x0444 would be written as: 0x0111, 0x0333, 0xFF2D, 0xFFFF the second is equal to the third value, and third and fourth are from out of bounds memory data and would be random values. --- Arduino/I2Cdev/I2Cdev.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Arduino/I2Cdev/I2Cdev.cpp b/Arduino/I2Cdev/I2Cdev.cpp index 5094b159..a22474dd 100644 --- a/Arduino/I2Cdev/I2Cdev.cpp +++ b/Arduino/I2Cdev/I2Cdev.cpp @@ -665,21 +665,21 @@ bool I2Cdev::writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16 Fastwire::beginTransmission(devAddr); Fastwire::write(regAddr); #endif - for (uint8_t i = 0; i < length * 2; i++) { + for (uint8_t i = 0; i < length; i++) { #ifdef I2CDEV_SERIAL_DEBUG Serial.print(data[i], HEX); if (i + 1 < length) Serial.print(" "); #endif #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) Wire.send((uint8_t)(data[i] >> 8)); // send MSB - Wire.send((uint8_t)data[i++]); // send LSB + Wire.send((uint8_t)data[i]); // send LSB #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100 \ || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) Wire.write((uint8_t)(data[i] >> 8)); // send MSB - Wire.write((uint8_t)data[i++]); // send LSB + Wire.write((uint8_t)data[i]); // send LSB #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) Fastwire::write((uint8_t)(data[i] >> 8)); // send MSB - status = Fastwire::write((uint8_t)data[i++]); // send LSB + status = Fastwire::write((uint8_t)data[i]); // send LSB if (status != 0) break; #endif } From 97e55ea99697cb3cab45863ffae7e0d04f77eadc Mon Sep 17 00:00:00 2001 From: Homer Creutz Date: Sun, 14 Jul 2019 00:04:01 -0600 Subject: [PATCH 217/335] Improved Offset Generation for Both Gyro & Accel Gyro Calibration is now more accurate, My divisor was /8. I Changed it to /4. Note that the ITerm is a floating point number so dividing is more accurate than converting to integer and bit shifting >>3 or >>4. Accel offset storage is also corrected to preserve Bit 0 Which is marked reserved in all the documentation. This could be the temperature compensation bit but I an finding little documentation about it. I didn't notice much improvement by preserving this bit with the MPU6050 but it isn't supposed to be changed so I'm preserving it. NOTE: I tested the Accel Calibration on the MPU9250 (aka MPU6500 with a magnetometer) and failed to set any calibration values that made sense. Gurr! It seems that with the MPU9250, leaving the Accel Calibration at Factory Values and only Calibrating the Gyro provides the most accurate, stable Yaw Pitch and Roll Values. I am Searching for any hopefully working MPU9250 accelerometer calibration code to discover why my attempts are in vain. --- Arduino/MPU6050/MPU6050.cpp | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/Arduino/MPU6050/MPU6050.cpp b/Arduino/MPU6050/MPU6050.cpp index c6ead06b..66d2459a 100644 --- a/Arduino/MPU6050/MPU6050.cpp +++ b/Arduino/MPU6050/MPU6050.cpp @@ -3228,7 +3228,7 @@ void MPU6050::CalibrateGyro(int Loops = 6) { /** @brief Fully calibrate Accel from ZERO in about 6-7 Loops 600-700 readings */ -void MPU6050::CalibrateAccel(int Loops = 6) { +void MPU6050::CalibrateAccel(uint16_t Loops = 6) { // int16_t Reading, Offset; // float Error, PTerm, ITerm[3]; double kP = 0.15; @@ -3242,26 +3242,30 @@ void MPU6050::CalibrateAccel(int Loops = 6) { void MPU6050::PID(uint8_t ReadAddress, uint8_t SaveAddress, float kP,float kI, uint8_t Loops) { int16_t Reading, Offset; + int16_t BitZero[3]; float Error, PTerm, ITerm[3]; - float x; for (int i = 0; i < 3; i++) { - I2Cdev::readWords(devAddr, SaveAddress + (i * 2), 1, &Reading); // reads 1 or more 16 bit integers (Word) -// MPUi2cReadInt(SaveAddress + (i * 2), &Reading); // XG_OFFSET_H_READ: Load the active Gyro offset to fine tune - ITerm[i] = Reading * 8; + I2Cdev::readWords(devAddr, SaveAddress + (i * 2), 1, &Reading); // reads 1 or more 16 bit integers (Word) + if(SaveAddress != 0x13){ + BitZero[i] = Reading & 1; // Capture Bit Zero to properly handle Accelerometer calibration + ITerm[i] = ((int16_t)Reading / 2) * 16; // remove bit 0 while keeping +- bit + } else ITerm[i] = Reading * 4; // Gyro Offset Capture + } for (int L = 0; L < Loops; L++) { for (int c = 0; c < 100; c++) {// 100 PI Calculations for (int i = 0; i < 3; i++) { - I2Cdev::readWords(devAddr, ReadAddress + (i * 2), 1, &Reading); // reads 1 or more 16 bit integers (Word) -// MPUi2cReadInt(ReadAddress + (i * 2), &Reading); + I2Cdev::readWords(devAddr, ReadAddress + (i * 2), 1, &Reading); // reads 1 or more 16 bit integers (Word) if ((ReadAddress == 0x3B)&&(i == 2)) Reading -= 16384; //remove Gravity if (abs(Reading) < 25000) { Error = 0 - Reading ; PTerm = kP * Error; ITerm[i] += Error * 0.002 * kI; // Integral term 1000 Calculations a second = 0.001 - Offset = round((PTerm + ITerm[i] ) / 8); //Compute PID Output - I2Cdev::writeWords(devAddr, SaveAddress + (i * 2), 1, &Offset); - // MPUi2cWriteInt(SaveAddress + (i * 2), Offset); + if(SaveAddress != 0x13){ + Offset = round((PTerm + ITerm[i] ) / 16); //Compute PID Output Accel + Offset = (Offset * 2) | BitZero[i]; // Insert Bit0 Saved at beginning Shift Everything 1 Bit keeping +- + } else Offset = round((PTerm + ITerm[i] ) / 4); //Compute PID Output Gyro + I2Cdev::writeWords(devAddr, SaveAddress + (i * 2), 1, &Offset); } } delay(1); @@ -3270,18 +3274,21 @@ void MPU6050::PID(uint8_t ReadAddress, uint8_t SaveAddress, float kP,float kI, u kP *= .95; kI *= .95; for (int i = 0; i < 3; i++){ - Offset = round((ITerm[i]) / 8); - I2Cdev::writeWords(devAddr, SaveAddress + (i * 2), 1, &Offset ); - // MPUi2cWriteInt(SaveAddress + (i * 2), round((ITerm[i]) / 8)); // ITerm is more of a running total rather than a reaction. - } + if(SaveAddress != 0x13) { + Offset = round((ITerm[i] ) / 16); //Set Offset Accel + Offset = (Offset * 2) | BitZero[i]; // Shift Accel Offset by 1 bit and Insert Bit0 Stored earlier + } else Offset = round((ITerm[i]) / 4); //Set Offset Gyro + I2Cdev::writeWords(devAddr, SaveAddress + (i * 2), 1, &Offset ); + } } resetFIFO(); resetDMP(); } + #define printfloatx(Name,Variable,Spaces,Precision,EndTxt) Serial.print(F(Name)); {char S[(Spaces + Precision + 3)];Serial.print(F(" ")); Serial.print(dtostrf((float)Variable,Spaces,Precision ,S));}Serial.print(F(EndTxt));//Name,Variable,Spaces,Precision,EndTxt void MPU6050::PrintActiveOffsets() { int16_t Data[3]; - Serial.print(F("// X Accel Y Accel Z Accel X Gyro Y Gyro Z Gyro\nOFFSETS ")); + Serial.print(F("\n// X Accel Y Accel Z Accel X Gyro Y Gyro Z Gyro\n//#define OFFSETS ")); I2Cdev::readWords(devAddr, 0x06, 3, Data); // A_OFFSET_H_READ_A_OFFS(Data); printfloatx("", Data[0], 5, 0, ", "); From ac6c8141d5828959543825d30717068426f6f689 Mon Sep 17 00:00:00 2001 From: Homer Creutz Date: Sun, 14 Jul 2019 00:07:00 -0600 Subject: [PATCH 218/335] Improved Offset Generation for Both Gyro & Accel Gyro Calibration is now more accurate, My divisor was /8. I Changed it to /4. Note that the ITerm is a floating point number so dividing is more accurate than converting to integer and bit shifting >>3 or >>4. Accel offset storage is also corrected to preserve Bit 0 Which is marked reserved in all the documentation. This could be the temperature compensation bit but I an finding little documentation about it. I didn't notice much improvement by preserving this bit with the MPU6050 but it isn't supposed to be changed so I'm preserving it. NOTE: I tested the Accel Calibration on the MPU9250 (aka MPU6500 with a magnetometer) and failed to set any calibration values that made sense. Gurr! It seems that with the MPU9250, leaving the Accel Calibration at Factory Values and only Calibrating the Gyro provides the most accurate, stable Yaw Pitch and Roll Values. I am Searching for any hopefully working MPU9250 accelerometer calibration code to discover why my attempts are in vain. --- Arduino/MPU6050/MPU6050.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Arduino/MPU6050/MPU6050.cpp b/Arduino/MPU6050/MPU6050.cpp index 66d2459a..469e2f88 100644 --- a/Arduino/MPU6050/MPU6050.cpp +++ b/Arduino/MPU6050/MPU6050.cpp @@ -3212,7 +3212,7 @@ void MPU6050::setDMPConfig2(uint8_t config) { /** @brief Fully calibrate Gyro from ZERO in about 6-7 Loops 600-700 readings */ -void MPU6050::CalibrateGyro(int Loops = 6) { +void MPU6050::CalibrateGyro(uint16_t Loops = 6) { int16_t Reading, Offset; float Error, PTerm, ITerm[3]; double kP = 0.3; From ce48d555a075aff1e3465693ca9851e36243ce29 Mon Sep 17 00:00:00 2001 From: Homer Creutz Date: Mon, 15 Jul 2019 22:39:04 -0600 Subject: [PATCH 219/335] Fixed Calibration and added MPU9250 Discovered a overflow when larger offsets were needed. I changed to a 32bit int instead of 16 bit int to prevent overflow issue Added MPU6500 and MPU9250 Calibreation!!! --- Arduino/MPU6050/MPU6050.cpp | 126 ++++++++++++++++++++++-------------- Arduino/MPU6050/MPU6050.h | 8 ++- 2 files changed, 82 insertions(+), 52 deletions(-) diff --git a/Arduino/MPU6050/MPU6050.cpp b/Arduino/MPU6050/MPU6050.cpp index 469e2f88..eca685f7 100644 --- a/Arduino/MPU6050/MPU6050.cpp +++ b/Arduino/MPU6050/MPU6050.cpp @@ -3213,8 +3213,6 @@ void MPU6050::setDMPConfig2(uint8_t config) { @brief Fully calibrate Gyro from ZERO in about 6-7 Loops 600-700 readings */ void MPU6050::CalibrateGyro(uint16_t Loops = 6) { - int16_t Reading, Offset; - float Error, PTerm, ITerm[3]; double kP = 0.3; double kI = 90; float x; @@ -3228,68 +3226,96 @@ void MPU6050::CalibrateGyro(uint16_t Loops = 6) { /** @brief Fully calibrate Accel from ZERO in about 6-7 Loops 600-700 readings */ -void MPU6050::CalibrateAccel(uint16_t Loops = 6) { -// int16_t Reading, Offset; -// float Error, PTerm, ITerm[3]; +void MPU6050::CalibrateAccel(uint16_t Loops = 6,uint8_t OffsetSaveAddress = 0x06) { double kP = 0.15; double kI = 8; float x; x = (100 - map(Loops, 1, 5, 20, 0)) * .01; kP *= x; kI *= x; - PID( 0x3B, 0x06, kP, kI, Loops); + PID( 0x3B, OffsetSaveAddress, kP, kI, Loops); } void MPU6050::PID(uint8_t ReadAddress, uint8_t SaveAddress, float kP,float kI, uint8_t Loops) { - int16_t Reading, Offset; - int16_t BitZero[3]; - float Error, PTerm, ITerm[3]; - for (int i = 0; i < 3; i++) { - I2Cdev::readWords(devAddr, SaveAddress + (i * 2), 1, &Reading); // reads 1 or more 16 bit integers (Word) - if(SaveAddress != 0x13){ - BitZero[i] = Reading & 1; // Capture Bit Zero to properly handle Accelerometer calibration - ITerm[i] = ((int16_t)Reading / 2) * 16; // remove bit 0 while keeping +- bit - } else ITerm[i] = Reading * 4; // Gyro Offset Capture - - } - for (int L = 0; L < Loops; L++) { - for (int c = 0; c < 100; c++) {// 100 PI Calculations - for (int i = 0; i < 3; i++) { - I2Cdev::readWords(devAddr, ReadAddress + (i * 2), 1, &Reading); // reads 1 or more 16 bit integers (Word) - if ((ReadAddress == 0x3B)&&(i == 2)) Reading -= 16384; //remove Gravity - if (abs(Reading) < 25000) { - Error = 0 - Reading ; - PTerm = kP * Error; - ITerm[i] += Error * 0.002 * kI; // Integral term 1000 Calculations a second = 0.001 - if(SaveAddress != 0x13){ - Offset = round((PTerm + ITerm[i] ) / 16); //Compute PID Output Accel - Offset = (Offset * 2) | BitZero[i]; // Insert Bit0 Saved at beginning Shift Everything 1 Bit keeping +- - } else Offset = round((PTerm + ITerm[i] ) / 4); //Compute PID Output Gyro - I2Cdev::writeWords(devAddr, SaveAddress + (i * 2), 1, &Offset); - } - } - delay(1); - } - Serial.write('.'); - kP *= .95; - kI *= .95; - for (int i = 0; i < 3; i++){ - if(SaveAddress != 0x13) { - Offset = round((ITerm[i] ) / 16); //Set Offset Accel - Offset = (Offset * 2) | BitZero[i]; // Shift Accel Offset by 1 bit and Insert Bit0 Stored earlier - } else Offset = round((ITerm[i]) / 4); //Set Offset Gyro - I2Cdev::writeWords(devAddr, SaveAddress + (i * 2), 1, &Offset ); - } - } - resetFIFO(); - resetDMP(); + int16_t Reading, Offset; + int16_t BitZero[3]; + uint8_t shift; + float Error, PTerm, ITerm[3]; + for (int i = 0; i < 3; i++) { + shift =(SaveAddress == 0x06)?2:3; + I2Cdev::readWords(devAddr, SaveAddress + (i * shift), 1, &Reading); // reads 1 or more 16 bit integers (Word) + if(SaveAddress != 0x13){ + BitZero[i] = Reading & 1; // Capture Bit Zero to properly handle Accelerometer calibration + ITerm[i] = ((int32_t)Reading/2) * 16; // remove bit 0 while keeping +- bit + } else { + ITerm[i] = Reading * 4; + } + } + for (int L = 0; L < Loops; L++) { + for (int c = 0; c < 100; c++) {// 100 PI Calculations + for (int i = 0; i < 3; i++) { + I2Cdev::readWords(devAddr, ReadAddress + (i * 2), 1, &Reading); // reads 1 or more 16 bit integers (Word) + if ((ReadAddress == 0x3B)&&(i == 2)) Reading -= 16384; //remove Gravity + if (abs(Reading) < 25000) { + Error = 0 - Reading ; + PTerm = kP * Error; + ITerm[i] += Error * 0.001 * kI; // Integral term 1000 Calculations a second = 0.001 + if(SaveAddress != 0x13){ + Offset = round((PTerm + ITerm[i] ) / 16); //Compute PID Output + Offset = (Offset*2) |BitZero[i]; // Insert Bit0 Saved at beginning + if(SaveAddress == 0x06){ + I2Cdev::writeWords(devAddr, SaveAddress + (i * 2), 1, &Offset); + } else { // SaveAddress == 0x77 + I2Cdev::writeWords(devAddr, SaveAddress + (i * 3), 1, &Offset); // 0x77, 0x7A, 0x7D Space every 3 instead of 2 + } + } else { + Offset = round((PTerm + ITerm[i] ) / 4); //Compute PID Output + I2Cdev::writeWords(devAddr, SaveAddress + (i * 2), 1, &Offset); + } + } + // if(SaveAddress != 0x13) PrintActiveOffsets(); + } + delay(1); + } + Serial.write('.'); + kP *= .95; + kI *= .95; + for (int i = 0; i < 3; i++){ + if(SaveAddress != 0x13) { + Offset = round((ITerm[i] ) / 16); //Compute PID Output + Offset = (Offset*2) |BitZero[i]; // Insert Bit0 Saved at beginning + if(SaveAddress == 0x06){ + I2Cdev::writeWords(devAddr, SaveAddress + (i * 2), 1, &Offset); + } else { // SaveAddress == 0x77 + I2Cdev::writeWords(devAddr, SaveAddress + (i * 3), 1, &Offset); // 0x77, 0x7A, 0x7D Space every 3 instead of 2 + } + } else { + Offset = round((ITerm[i]) / 4); + I2Cdev::writeWords(devAddr, SaveAddress + (i * 2), 1, &Offset ); + } + } + } + resetFIFO(); + resetDMP(); } #define printfloatx(Name,Variable,Spaces,Precision,EndTxt) Serial.print(F(Name)); {char S[(Spaces + Precision + 3)];Serial.print(F(" ")); Serial.print(dtostrf((float)Variable,Spaces,Precision ,S));}Serial.print(F(EndTxt));//Name,Variable,Spaces,Precision,EndTxt -void MPU6050::PrintActiveOffsets() { +void MPU6050::PrintActiveOffsets_MPU9250() { + PrintActiveOffsets(0x77); +} +void MPU6050::PrintActiveOffsets_MPU6500() { + PrintActiveOffsets(0x77) +} + +void MPU6050::PrintActiveOffsets(uint8_t AOffsetRegister = 0x06) { int16_t Data[3]; Serial.print(F("\n// X Accel Y Accel Z Accel X Gyro Y Gyro Z Gyro\n//#define OFFSETS ")); - I2Cdev::readWords(devAddr, 0x06, 3, Data); + if(AOffsetRegister == 0x06) I2Cdev::readWords(devAddr, AOffsetRegister, 3, Data); + else { + I2Cdev::readWords(devAddr, AOffsetRegister, 1, Data); + I2Cdev::readWords(devAddr, AOffsetRegister+3, 1, Data+1); // Shifts 3 bytes + I2Cdev::readWords(devAddr, AOffsetRegister+6, 1, Data+2); // Shifts 3 more bytes + } // A_OFFSET_H_READ_A_OFFS(Data); printfloatx("", Data[0], 5, 0, ", "); printfloatx("", Data[1], 5, 0, ", "); diff --git a/Arduino/MPU6050/MPU6050.h b/Arduino/MPU6050/MPU6050.h index 1e4a734f..536f5b59 100644 --- a/Arduino/MPU6050/MPU6050.h +++ b/Arduino/MPU6050/MPU6050.h @@ -822,9 +822,13 @@ class MPU6050 { // Calibration Routines void CalibrateGyro(int Loops = 6); // Fine tune after setting offsets with less Loops. - void CalibrateAccel(int Loops = 6); // Fine tune after setting offsets with less Loops. + void CalibrateAccel(uint8_t Loops = 6,uint8_t OffsetSaveAddress = 0x06); // Fine tune after setting offsets with less Loops. + void CalibrateAccel_MPU9250(int Loops = 6); + void CalibrateAccel_MPU6500(int Loops = 6); void PID(uint8_t ReadAddress, uint8_t SaveAddress, float kP,float kI, uint8_t Loops); // Does the math - void PrintActiveOffsets(); // See the results of the Calibration + void PrintActiveOffsets(uint8_t AOffsetRegister = 0x06) // See the results of the Calibration + void PrintActiveOffsets_MPU6500(); + void PrintActiveOffsets_MPU9250() // special methods for MotionApps 2.0 implementation From e6feebd2e7f5c5f95cd9903f284f77379eebf8c6 Mon Sep 17 00:00:00 2001 From: Homer Creutz Date: Mon, 15 Jul 2019 23:03:10 -0600 Subject: [PATCH 220/335] Corrections --- Arduino/MPU6050/MPU6050.cpp | 8 +++++++- Arduino/MPU6050/MPU6050.h | 10 +++++----- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/Arduino/MPU6050/MPU6050.cpp b/Arduino/MPU6050/MPU6050.cpp index eca685f7..7e704db0 100644 --- a/Arduino/MPU6050/MPU6050.cpp +++ b/Arduino/MPU6050/MPU6050.cpp @@ -3226,6 +3226,12 @@ void MPU6050::CalibrateGyro(uint16_t Loops = 6) { /** @brief Fully calibrate Accel from ZERO in about 6-7 Loops 600-700 readings */ +void MPU6050::CalibrateAccel_MPU9250(uint8_t Loops = 6) { + CalibrateAccel(Loops,0x77); +} +void MPU6050::CalibrateAccel_MPU6500(uint8_t Loops = 6) { + CalibrateAccel(Loops,0x77); +} void MPU6050::CalibrateAccel(uint16_t Loops = 6,uint8_t OffsetSaveAddress = 0x06) { double kP = 0.15; double kI = 8; @@ -3304,7 +3310,7 @@ void MPU6050::PrintActiveOffsets_MPU9250() { PrintActiveOffsets(0x77); } void MPU6050::PrintActiveOffsets_MPU6500() { - PrintActiveOffsets(0x77) + PrintActiveOffsets(0x77); } void MPU6050::PrintActiveOffsets(uint8_t AOffsetRegister = 0x06) { diff --git a/Arduino/MPU6050/MPU6050.h b/Arduino/MPU6050/MPU6050.h index 536f5b59..dfccd280 100644 --- a/Arduino/MPU6050/MPU6050.h +++ b/Arduino/MPU6050/MPU6050.h @@ -821,14 +821,14 @@ class MPU6050 { void setDMPConfig2(uint8_t config); // Calibration Routines - void CalibrateGyro(int Loops = 6); // Fine tune after setting offsets with less Loops. + void CalibrateGyro(uint8_t Loops = 6); // Fine tune after setting offsets with less Loops. void CalibrateAccel(uint8_t Loops = 6,uint8_t OffsetSaveAddress = 0x06); // Fine tune after setting offsets with less Loops. - void CalibrateAccel_MPU9250(int Loops = 6); - void CalibrateAccel_MPU6500(int Loops = 6); + void CalibrateAccel_MPU9250(uint8_t Loops = 6); + void CalibrateAccel_MPU6500(uint8_t Loops = 6); void PID(uint8_t ReadAddress, uint8_t SaveAddress, float kP,float kI, uint8_t Loops); // Does the math - void PrintActiveOffsets(uint8_t AOffsetRegister = 0x06) // See the results of the Calibration + void PrintActiveOffsets(uint8_t AOffsetRegister = 0x06); // See the results of the Calibration void PrintActiveOffsets_MPU6500(); - void PrintActiveOffsets_MPU9250() + void PrintActiveOffsets_MPU9250(); // special methods for MotionApps 2.0 implementation From 1199dc642de06b0ca3a38fa0a0a7da4ee9f912b9 Mon Sep 17 00:00:00 2001 From: Homer Creutz Date: Tue, 16 Jul 2019 05:14:03 -0600 Subject: [PATCH 221/335] Update MPU6050.cpp --- Arduino/MPU6050/MPU6050.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Arduino/MPU6050/MPU6050.cpp b/Arduino/MPU6050/MPU6050.cpp index 7e704db0..fa6722cb 100644 --- a/Arduino/MPU6050/MPU6050.cpp +++ b/Arduino/MPU6050/MPU6050.cpp @@ -3212,7 +3212,7 @@ void MPU6050::setDMPConfig2(uint8_t config) { /** @brief Fully calibrate Gyro from ZERO in about 6-7 Loops 600-700 readings */ -void MPU6050::CalibrateGyro(uint16_t Loops = 6) { +void MPU6050::CalibrateGyro(uint8_t Loops = 6) { double kP = 0.3; double kI = 90; float x; From 276b07ce4843a050295678695e8d2c4fd080bfa6 Mon Sep 17 00:00:00 2001 From: Homer Creutz Date: Tue, 16 Jul 2019 05:17:12 -0600 Subject: [PATCH 222/335] Minor Changes --- Arduino/MPU6050/MPU6050.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Arduino/MPU6050/MPU6050.cpp b/Arduino/MPU6050/MPU6050.cpp index 7e704db0..e64a704a 100644 --- a/Arduino/MPU6050/MPU6050.cpp +++ b/Arduino/MPU6050/MPU6050.cpp @@ -3212,7 +3212,7 @@ void MPU6050::setDMPConfig2(uint8_t config) { /** @brief Fully calibrate Gyro from ZERO in about 6-7 Loops 600-700 readings */ -void MPU6050::CalibrateGyro(uint16_t Loops = 6) { +void MPU6050::CalibrateGyro(uint8_t Loops = 6) { double kP = 0.3; double kI = 90; float x; @@ -3279,7 +3279,6 @@ void MPU6050::PID(uint8_t ReadAddress, uint8_t SaveAddress, float kP,float kI, u I2Cdev::writeWords(devAddr, SaveAddress + (i * 2), 1, &Offset); } } - // if(SaveAddress != 0x13) PrintActiveOffsets(); } delay(1); } @@ -3322,12 +3321,10 @@ void MPU6050::PrintActiveOffsets(uint8_t AOffsetRegister = 0x06) { I2Cdev::readWords(devAddr, AOffsetRegister+3, 1, Data+1); // Shifts 3 bytes I2Cdev::readWords(devAddr, AOffsetRegister+6, 1, Data+2); // Shifts 3 more bytes } -// A_OFFSET_H_READ_A_OFFS(Data); printfloatx("", Data[0], 5, 0, ", "); printfloatx("", Data[1], 5, 0, ", "); printfloatx("", Data[2], 5, 0, ", "); I2Cdev::readWords(devAddr, 0x13, 3, Data); -// XG_OFFSET_H_READ_OFFS_USR(Data); printfloatx("", Data[0], 5, 0, ", "); printfloatx("", Data[1], 5, 0, ", "); printfloatx("", Data[2], 5, 0, "\n"); From 9763aac711d7ed93d3f07fe6a1d8841c877f10aa Mon Sep 17 00:00:00 2001 From: Homer Creutz Date: Tue, 16 Jul 2019 05:21:14 -0600 Subject: [PATCH 223/335] Corrections --- Arduino/MPU6050/MPU6050.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Arduino/MPU6050/MPU6050.cpp b/Arduino/MPU6050/MPU6050.cpp index e64a704a..530795fc 100644 --- a/Arduino/MPU6050/MPU6050.cpp +++ b/Arduino/MPU6050/MPU6050.cpp @@ -3232,7 +3232,7 @@ void MPU6050::CalibrateAccel_MPU9250(uint8_t Loops = 6) { void MPU6050::CalibrateAccel_MPU6500(uint8_t Loops = 6) { CalibrateAccel(Loops,0x77); } -void MPU6050::CalibrateAccel(uint16_t Loops = 6,uint8_t OffsetSaveAddress = 0x06) { +void MPU6050::CalibrateAccel(uint8_t Loops = 6,uint8_t OffsetSaveAddress = 0x06) { double kP = 0.15; double kI = 8; float x; From 1ab3d97639d302d10b2235bf2a32b1f32f1cd6ae Mon Sep 17 00:00:00 2001 From: Jeff Rowberg Date: Wed, 17 Jul 2019 20:47:10 -0400 Subject: [PATCH 224/335] Remove default values from class method implementations --- Arduino/MPU6050/MPU6050.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Arduino/MPU6050/MPU6050.cpp b/Arduino/MPU6050/MPU6050.cpp index 530795fc..e87cc4eb 100644 --- a/Arduino/MPU6050/MPU6050.cpp +++ b/Arduino/MPU6050/MPU6050.cpp @@ -3212,7 +3212,7 @@ void MPU6050::setDMPConfig2(uint8_t config) { /** @brief Fully calibrate Gyro from ZERO in about 6-7 Loops 600-700 readings */ -void MPU6050::CalibrateGyro(uint8_t Loops = 6) { +void MPU6050::CalibrateGyro(uint8_t Loops) { double kP = 0.3; double kI = 90; float x; @@ -3226,13 +3226,13 @@ void MPU6050::CalibrateGyro(uint8_t Loops = 6) { /** @brief Fully calibrate Accel from ZERO in about 6-7 Loops 600-700 readings */ -void MPU6050::CalibrateAccel_MPU9250(uint8_t Loops = 6) { +void MPU6050::CalibrateAccel_MPU9250(uint8_t Loops) { CalibrateAccel(Loops,0x77); } -void MPU6050::CalibrateAccel_MPU6500(uint8_t Loops = 6) { +void MPU6050::CalibrateAccel_MPU6500(uint8_t Loops) { CalibrateAccel(Loops,0x77); } -void MPU6050::CalibrateAccel(uint8_t Loops = 6,uint8_t OffsetSaveAddress = 0x06) { +void MPU6050::CalibrateAccel(uint8_t Loops,uint8_t OffsetSaveAddress) { double kP = 0.15; double kI = 8; float x; From eb93a0b004f761272f4ae7327cb1106ae4af14a8 Mon Sep 17 00:00:00 2001 From: Jeff Rowberg Date: Wed, 17 Jul 2019 20:48:09 -0400 Subject: [PATCH 225/335] Add explicit casts for signed to unsigned pointer conversion --- Arduino/MPU6050/MPU6050.cpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/Arduino/MPU6050/MPU6050.cpp b/Arduino/MPU6050/MPU6050.cpp index e87cc4eb..8e475472 100644 --- a/Arduino/MPU6050/MPU6050.cpp +++ b/Arduino/MPU6050/MPU6050.cpp @@ -3249,7 +3249,7 @@ void MPU6050::PID(uint8_t ReadAddress, uint8_t SaveAddress, float kP,float kI, u float Error, PTerm, ITerm[3]; for (int i = 0; i < 3; i++) { shift =(SaveAddress == 0x06)?2:3; - I2Cdev::readWords(devAddr, SaveAddress + (i * shift), 1, &Reading); // reads 1 or more 16 bit integers (Word) + I2Cdev::readWords(devAddr, SaveAddress + (i * shift), 1, (uint16_t *)&Reading); // reads 1 or more 16 bit integers (Word) if(SaveAddress != 0x13){ BitZero[i] = Reading & 1; // Capture Bit Zero to properly handle Accelerometer calibration ITerm[i] = ((int32_t)Reading/2) * 16; // remove bit 0 while keeping +- bit @@ -3260,7 +3260,7 @@ void MPU6050::PID(uint8_t ReadAddress, uint8_t SaveAddress, float kP,float kI, u for (int L = 0; L < Loops; L++) { for (int c = 0; c < 100; c++) {// 100 PI Calculations for (int i = 0; i < 3; i++) { - I2Cdev::readWords(devAddr, ReadAddress + (i * 2), 1, &Reading); // reads 1 or more 16 bit integers (Word) + I2Cdev::readWords(devAddr, ReadAddress + (i * 2), 1, (uint16_t *)&Reading); // reads 1 or more 16 bit integers (Word) if ((ReadAddress == 0x3B)&&(i == 2)) Reading -= 16384; //remove Gravity if (abs(Reading) < 25000) { Error = 0 - Reading ; @@ -3270,13 +3270,13 @@ void MPU6050::PID(uint8_t ReadAddress, uint8_t SaveAddress, float kP,float kI, u Offset = round((PTerm + ITerm[i] ) / 16); //Compute PID Output Offset = (Offset*2) |BitZero[i]; // Insert Bit0 Saved at beginning if(SaveAddress == 0x06){ - I2Cdev::writeWords(devAddr, SaveAddress + (i * 2), 1, &Offset); + I2Cdev::writeWords(devAddr, SaveAddress + (i * 2), 1, (uint16_t *)&Offset); } else { // SaveAddress == 0x77 - I2Cdev::writeWords(devAddr, SaveAddress + (i * 3), 1, &Offset); // 0x77, 0x7A, 0x7D Space every 3 instead of 2 + I2Cdev::writeWords(devAddr, SaveAddress + (i * 3), 1, (uint16_t *)&Offset); // 0x77, 0x7A, 0x7D Space every 3 instead of 2 } } else { Offset = round((PTerm + ITerm[i] ) / 4); //Compute PID Output - I2Cdev::writeWords(devAddr, SaveAddress + (i * 2), 1, &Offset); + I2Cdev::writeWords(devAddr, SaveAddress + (i * 2), 1, (uint16_t *)&Offset); } } } @@ -3290,13 +3290,13 @@ void MPU6050::PID(uint8_t ReadAddress, uint8_t SaveAddress, float kP,float kI, u Offset = round((ITerm[i] ) / 16); //Compute PID Output Offset = (Offset*2) |BitZero[i]; // Insert Bit0 Saved at beginning if(SaveAddress == 0x06){ - I2Cdev::writeWords(devAddr, SaveAddress + (i * 2), 1, &Offset); + I2Cdev::writeWords(devAddr, SaveAddress + (i * 2), 1, (uint16_t *)&Offset); } else { // SaveAddress == 0x77 - I2Cdev::writeWords(devAddr, SaveAddress + (i * 3), 1, &Offset); // 0x77, 0x7A, 0x7D Space every 3 instead of 2 + I2Cdev::writeWords(devAddr, SaveAddress + (i * 3), 1, (uint16_t *)&Offset); // 0x77, 0x7A, 0x7D Space every 3 instead of 2 } } else { Offset = round((ITerm[i]) / 4); - I2Cdev::writeWords(devAddr, SaveAddress + (i * 2), 1, &Offset ); + I2Cdev::writeWords(devAddr, SaveAddress + (i * 2), 1, (uint16_t *)&Offset ); } } } @@ -3312,19 +3312,19 @@ void MPU6050::PrintActiveOffsets_MPU6500() { PrintActiveOffsets(0x77); } -void MPU6050::PrintActiveOffsets(uint8_t AOffsetRegister = 0x06) { +void MPU6050::PrintActiveOffsets(uint8_t AOffsetRegister) { int16_t Data[3]; Serial.print(F("\n// X Accel Y Accel Z Accel X Gyro Y Gyro Z Gyro\n//#define OFFSETS ")); - if(AOffsetRegister == 0x06) I2Cdev::readWords(devAddr, AOffsetRegister, 3, Data); + if(AOffsetRegister == 0x06) I2Cdev::readWords(devAddr, AOffsetRegister, 3, (uint16_t *)Data); else { - I2Cdev::readWords(devAddr, AOffsetRegister, 1, Data); - I2Cdev::readWords(devAddr, AOffsetRegister+3, 1, Data+1); // Shifts 3 bytes - I2Cdev::readWords(devAddr, AOffsetRegister+6, 1, Data+2); // Shifts 3 more bytes + I2Cdev::readWords(devAddr, AOffsetRegister, 1, (uint16_t *)Data); + I2Cdev::readWords(devAddr, AOffsetRegister+3, 1, (uint16_t *)Data+1); // Shifts 3 bytes + I2Cdev::readWords(devAddr, AOffsetRegister+6, 1, (uint16_t *)Data+2); // Shifts 3 more bytes } printfloatx("", Data[0], 5, 0, ", "); printfloatx("", Data[1], 5, 0, ", "); printfloatx("", Data[2], 5, 0, ", "); - I2Cdev::readWords(devAddr, 0x13, 3, Data); + I2Cdev::readWords(devAddr, 0x13, 3, (uint16_t *)Data); printfloatx("", Data[0], 5, 0, ", "); printfloatx("", Data[1], 5, 0, ", "); printfloatx("", Data[2], 5, 0, "\n"); From 44d28d255999c522fbf796fd502d3e0e26de4045 Mon Sep 17 00:00:00 2001 From: Jeff Rowberg Date: Wed, 17 Jul 2019 20:49:14 -0400 Subject: [PATCH 226/335] Remove reference operator from args that shouldn't be pointers --- Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h b/Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h index aa1f9248..a1eb9679 100644 --- a/Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h +++ b/Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h @@ -353,9 +353,9 @@ uint8_t MPU6050::dmpInitialize() { // Lets get it over with fast Write everythin uint8_t val; uint16_t ival; // Reset procedure per instructions in the "MPU-6000/MPU-6050 Register Map and Descriptions" page 41 - I2Cdev::writeBit(devAddr,0x6B, 7, &(val = 1)); //PWR_MGMT_1: reset with 100ms delay + I2Cdev::writeBit(devAddr,0x6B, 7, (val = 1)); //PWR_MGMT_1: reset with 100ms delay delay(100); - I2Cdev::writeBits(devAddr,0x6A, 2, 3, &(val = 0b111)); // full SIGNAL_PATH_RESET: with another 100ms delay + I2Cdev::writeBits(devAddr,0x6A, 2, 3, (val = 0b111)); // full SIGNAL_PATH_RESET: with another 100ms delay delay(100); I2Cdev::writeBytes(devAddr,0x6B, 1, &(val = 0x01)); // 1000 0001 PWR_MGMT_1:Clock Source Select PLL_X_gyro I2Cdev::writeBytes(devAddr,0x38, 1, &(val = 0x00)); // 0000 0000 INT_ENABLE: no Interrupt @@ -370,7 +370,7 @@ uint8_t MPU6050::dmpInitialize() { // Lets get it over with fast Write everythin I2Cdev::writeBytes(devAddr,0x1B, 1, &(val = 0x18)); // 0001 1000 GYRO_CONFIG: 3 = +2000 Deg/sec I2Cdev::writeBytes(devAddr,0x6A, 1, &(val = 0xC0)); // 1100 1100 USER_CTRL: Enable Fifo and Reset Fifo I2Cdev::writeBytes(devAddr,0x38, 1, &(val = 0x02)); // 0000 0010 INT_ENABLE: RAW_DMP_INT_EN on - I2Cdev::writeBit(devAddr,0x6A, 2, &(val = 1)); // Reset FIFO one last time just for kicks. (MPUi2cWrite reads 0x6A first and only alters 1 bit and then saves the byte) + I2Cdev::writeBit(devAddr,0x6A, 2, (val = 1)); // Reset FIFO one last time just for kicks. (MPUi2cWrite reads 0x6A first and only alters 1 bit and then saves the byte) setDMPEnabled(false); // disable DMP for compatibility with the MPU6050 library /* dmpPacketSize += 16;//DMP_FEATURE_6X_LP_QUAT From fd1b70b9c349f9c018e1cc9f591831fcce049963 Mon Sep 17 00:00:00 2001 From: Homer Creutz Date: Tue, 23 Jul 2019 21:16:01 -0600 Subject: [PATCH 227/335] Faster Better Tuning +plus I found some more bugs with the offset tuning PID loop and so I reworked it. Offset tuning calculations are now super fast and more accurate than before. Added auto detectiion for MPU9250 and MPU6500 so the calibration happens without any direct programming changes. I alos made 1 or two minor coding errors. Origional code "get and setXAccelOffset" can now detect which MPU we are connected to and manage the offsets in their correct registers automatically. --- Arduino/MPU6050/MPU6050.cpp | 148 +++++++++--------- Arduino/MPU6050/MPU6050.h | 13 +- .../MPU6050/MPU6050_6Axis_MotionApps_V6_12.h | 2 +- 3 files changed, 79 insertions(+), 84 deletions(-) diff --git a/Arduino/MPU6050/MPU6050.cpp b/Arduino/MPU6050/MPU6050.cpp index 530795fc..9bbf100c 100644 --- a/Arduino/MPU6050/MPU6050.cpp +++ b/Arduino/MPU6050/MPU6050.cpp @@ -2846,31 +2846,37 @@ void MPU6050::setZFineGain(int8_t gain) { // XA_OFFS_* registers int16_t MPU6050::getXAccelOffset() { - I2Cdev::readBytes(devAddr, MPU6050_RA_XA_OFFS_H, 2, buffer); - return (((int16_t)buffer[0]) << 8) | buffer[1]; + uint8_t SaveAddress = ((getDeviceID() < 0x39 )? MPU6050_RA_XA_OFFS_H:0x77); // MPU6050,MPU9150 Vs MPU6500,MPU9250 + I2Cdev::readBytes(devAddr, SaveAddress, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; } void MPU6050::setXAccelOffset(int16_t offset) { - I2Cdev::writeWord(devAddr, MPU6050_RA_XA_OFFS_H, offset); + uint8_t SaveAddress = ((getDeviceID() < 0x39 )? MPU6050_RA_XA_OFFS_H:0x77); // MPU6050,MPU9150 Vs MPU6500,MPU9250 + I2Cdev::writeWord(devAddr, SaveAddress, offset); } // YA_OFFS_* register int16_t MPU6050::getYAccelOffset() { - I2Cdev::readBytes(devAddr, MPU6050_RA_YA_OFFS_H, 2, buffer); - return (((int16_t)buffer[0]) << 8) | buffer[1]; + uint8_t SaveAddress = ((getDeviceID() < 0x39 )? MPU6050_RA_YA_OFFS_H:0x7A); // MPU6050,MPU9150 Vs MPU6500,MPU9250 + I2Cdev::readBytes(devAddr, SaveAddress, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; } void MPU6050::setYAccelOffset(int16_t offset) { - I2Cdev::writeWord(devAddr, MPU6050_RA_YA_OFFS_H, offset); + uint8_t SaveAddress = ((getDeviceID() < 0x39 )? MPU6050_RA_YA_OFFS_H:0x7A); // MPU6050,MPU9150 Vs MPU6500,MPU9250 + I2Cdev::writeWord(devAddr, SaveAddress, offset); } // ZA_OFFS_* register int16_t MPU6050::getZAccelOffset() { - I2Cdev::readBytes(devAddr, MPU6050_RA_ZA_OFFS_H, 2, buffer); - return (((int16_t)buffer[0]) << 8) | buffer[1]; + uint8_t SaveAddress = ((getDeviceID() < 0x39 )? MPU6050_RA_ZA_OFFS_H:0x7D); // MPU6050,MPU9150 Vs MPU6500,MPU9250 + I2Cdev::readBytes(devAddr, SaveAddress, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; } void MPU6050::setZAccelOffset(int16_t offset) { - I2Cdev::writeWord(devAddr, MPU6050_RA_ZA_OFFS_H, offset); + uint8_t SaveAddress = ((getDeviceID() < 0x39 )? MPU6050_RA_ZA_OFFS_H:0x7D); // MPU6050,MPU9150 Vs MPU6500,MPU9250 + I2Cdev::writeWord(devAddr, SaveAddress, offset); } // XG_OFFS_USR* registers @@ -3212,7 +3218,7 @@ void MPU6050::setDMPConfig2(uint8_t config) { /** @brief Fully calibrate Gyro from ZERO in about 6-7 Loops 600-700 readings */ -void MPU6050::CalibrateGyro(uint8_t Loops = 6) { +void MPU6050::CalibrateGyro(uint8_t Loops ) { double kP = 0.3; double kI = 90; float x; @@ -3220,84 +3226,78 @@ void MPU6050::CalibrateGyro(uint8_t Loops = 6) { kP *= x; kI *= x; - PID( 0x43, 0x13, kP, kI, Loops); + PID( 0x43, kP, kI, Loops); } /** @brief Fully calibrate Accel from ZERO in about 6-7 Loops 600-700 readings */ -void MPU6050::CalibrateAccel_MPU9250(uint8_t Loops = 6) { - CalibrateAccel(Loops,0x77); -} -void MPU6050::CalibrateAccel_MPU6500(uint8_t Loops = 6) { - CalibrateAccel(Loops,0x77); -} -void MPU6050::CalibrateAccel(uint8_t Loops = 6,uint8_t OffsetSaveAddress = 0x06) { - double kP = 0.15; - double kI = 8; - float x; - x = (100 - map(Loops, 1, 5, 20, 0)) * .01; - kP *= x; - kI *= x; - PID( 0x3B, OffsetSaveAddress, kP, kI, Loops); +void MPU6050::CalibrateAccel(uint8_t Loops ) { + + float kP = 0.3; + float kI = 20; + float x; + x = (100 - map(Loops, 1, 5, 20, 0)) * .01; + kP *= x; + kI *= x; + PID( 0x3B, kP, kI, Loops); } -void MPU6050::PID(uint8_t ReadAddress, uint8_t SaveAddress, float kP,float kI, uint8_t Loops) { - int16_t Reading, Offset; +void MPU6050::PID(uint8_t ReadAddress, float kP,float kI, uint8_t Loops){ + uint8_t SaveAddress = (ReadAddress == 0x3B)?((getDeviceID() < 0x39 )? 0x06:0x77):0x13; + + int16_t Data; + float Reading; int16_t BitZero[3]; - uint8_t shift; + uint8_t shift =(SaveAddress == 0x77)?3:2; float Error, PTerm, ITerm[3]; + int16_t eSample; + uint32_t eSum ; + Serial.write('>'); for (int i = 0; i < 3; i++) { - shift =(SaveAddress == 0x06)?2:3; - I2Cdev::readWords(devAddr, SaveAddress + (i * shift), 1, &Reading); // reads 1 or more 16 bit integers (Word) + I2Cdev::readWords(devAddr, SaveAddress + (i * shift), 1, &Data); // reads 1 or more 16 bit integers (Word) if(SaveAddress != 0x13){ - BitZero[i] = Reading & 1; // Capture Bit Zero to properly handle Accelerometer calibration - ITerm[i] = ((int32_t)Reading/2) * 16; // remove bit 0 while keeping +- bit + BitZero[i] = Data & 1; // Capture Bit Zero to properly handle Accelerometer calibration + ITerm[i] = ((float)Reading) * 8; } else { ITerm[i] = Reading * 4; } } for (int L = 0; L < Loops; L++) { + eSample = 0; for (int c = 0; c < 100; c++) {// 100 PI Calculations + eSum = 0; for (int i = 0; i < 3; i++) { - I2Cdev::readWords(devAddr, ReadAddress + (i * 2), 1, &Reading); // reads 1 or more 16 bit integers (Word) - if ((ReadAddress == 0x3B)&&(i == 2)) Reading -= 16384; //remove Gravity - if (abs(Reading) < 25000) { - Error = 0 - Reading ; - PTerm = kP * Error; - ITerm[i] += Error * 0.001 * kI; // Integral term 1000 Calculations a second = 0.001 - if(SaveAddress != 0x13){ - Offset = round((PTerm + ITerm[i] ) / 16); //Compute PID Output - Offset = (Offset*2) |BitZero[i]; // Insert Bit0 Saved at beginning - if(SaveAddress == 0x06){ - I2Cdev::writeWords(devAddr, SaveAddress + (i * 2), 1, &Offset); - } else { // SaveAddress == 0x77 - I2Cdev::writeWords(devAddr, SaveAddress + (i * 3), 1, &Offset); // 0x77, 0x7A, 0x7D Space every 3 instead of 2 - } - } else { - Offset = round((PTerm + ITerm[i] ) / 4); //Compute PID Output - I2Cdev::writeWords(devAddr, SaveAddress + (i * 2), 1, &Offset); - } - } + I2Cdev::readWords(devAddr, ReadAddress + (i * 2), 1, &Data); // reads 1 or more 16 bit integers (Word) + Reading = Data; + if ((ReadAddress == 0x3B)&&(i == 2)) Reading -= 16384; //remove Gravity + Error = -Reading; + eSum += abs(Reading); + PTerm = kP * Error; + ITerm[i] += (Error * 0.001) * kI; // Integral term 1000 Calculations a second = 0.001 + if(SaveAddress != 0x13){ + Data = round((PTerm + ITerm[i] ) / 8); //Compute PID Output + Data = ((Data)&0xFFFE) |BitZero[i]; // Insert Bit0 Saved at beginning + } else Data = round((PTerm + ITerm[i] ) / 4); //Compute PID Output + I2Cdev::writeWords(devAddr, SaveAddress + (i * shift), 1, &Data); + } + if((c == 99) && eSum > 1000){ // Error is still to great to continue + c = 0; + Serial.write('*'); } + if((eSum * ((ReadAddress == 0x3B)?.05: 1)) < 5) eSample++; // Successfully found offsets prepare to advance + if((eSum < 100) && (c > 10) && (eSample >= 10)) break; // Advance to next Loop delay(1); } Serial.write('.'); - kP *= .95; - kI *= .95; + kP *= .75; + kI *= .75; for (int i = 0; i < 3; i++){ if(SaveAddress != 0x13) { - Offset = round((ITerm[i] ) / 16); //Compute PID Output - Offset = (Offset*2) |BitZero[i]; // Insert Bit0 Saved at beginning - if(SaveAddress == 0x06){ - I2Cdev::writeWords(devAddr, SaveAddress + (i * 2), 1, &Offset); - } else { // SaveAddress == 0x77 - I2Cdev::writeWords(devAddr, SaveAddress + (i * 3), 1, &Offset); // 0x77, 0x7A, 0x7D Space every 3 instead of 2 - } - } else { - Offset = round((ITerm[i]) / 4); - I2Cdev::writeWords(devAddr, SaveAddress + (i * 2), 1, &Offset ); - } + Data = round((ITerm[i] ) / 8); //Compute PID Output + Data = ((Data)&0xFFFE) |BitZero[i]; // Insert Bit0 Saved at beginning + } else Data = round((ITerm[i]) / 4); + I2Cdev::writeWords(devAddr, SaveAddress + (i * shift), 1, &Data ); } } resetFIFO(); @@ -3305,26 +3305,24 @@ void MPU6050::PID(uint8_t ReadAddress, uint8_t SaveAddress, float kP,float kI, u } #define printfloatx(Name,Variable,Spaces,Precision,EndTxt) Serial.print(F(Name)); {char S[(Spaces + Precision + 3)];Serial.print(F(" ")); Serial.print(dtostrf((float)Variable,Spaces,Precision ,S));}Serial.print(F(EndTxt));//Name,Variable,Spaces,Precision,EndTxt -void MPU6050::PrintActiveOffsets_MPU9250() { - PrintActiveOffsets(0x77); -} -void MPU6050::PrintActiveOffsets_MPU6500() { - PrintActiveOffsets(0x77); -} - -void MPU6050::PrintActiveOffsets(uint8_t AOffsetRegister = 0x06) { +void MPU6050::PrintActiveOffsets() { + uint8_t AOffsetRegister = (getDeviceID() < 0x39 )? MPU6050_RA_XA_OFFS_H:0x77; int16_t Data[3]; - Serial.print(F("\n// X Accel Y Accel Z Accel X Gyro Y Gyro Z Gyro\n//#define OFFSETS ")); + //Serial.print(F("Offset Register 0x")); + //Serial.print(AOffsetRegister>>4,HEX);Serial.print(AOffsetRegister&0x0F,HEX); + Serial.print(F("\n// X Accel Y Accel Z Accel X Gyro Y Gyro Z Gyro\n//OFFSETS ")); if(AOffsetRegister == 0x06) I2Cdev::readWords(devAddr, AOffsetRegister, 3, Data); else { I2Cdev::readWords(devAddr, AOffsetRegister, 1, Data); - I2Cdev::readWords(devAddr, AOffsetRegister+3, 1, Data+1); // Shifts 3 bytes - I2Cdev::readWords(devAddr, AOffsetRegister+6, 1, Data+2); // Shifts 3 more bytes + I2Cdev::readWords(devAddr, AOffsetRegister+3, 1, Data+1); + I2Cdev::readWords(devAddr, AOffsetRegister+6, 1, Data+2); } + // A_OFFSET_H_READ_A_OFFS(Data); printfloatx("", Data[0], 5, 0, ", "); printfloatx("", Data[1], 5, 0, ", "); printfloatx("", Data[2], 5, 0, ", "); I2Cdev::readWords(devAddr, 0x13, 3, Data); + // XG_OFFSET_H_READ_OFFS_USR(Data); printfloatx("", Data[0], 5, 0, ", "); printfloatx("", Data[1], 5, 0, ", "); printfloatx("", Data[2], 5, 0, "\n"); diff --git a/Arduino/MPU6050/MPU6050.h b/Arduino/MPU6050/MPU6050.h index dfccd280..54e7c8f0 100644 --- a/Arduino/MPU6050/MPU6050.h +++ b/Arduino/MPU6050/MPU6050.h @@ -821,14 +821,11 @@ class MPU6050 { void setDMPConfig2(uint8_t config); // Calibration Routines - void CalibrateGyro(uint8_t Loops = 6); // Fine tune after setting offsets with less Loops. - void CalibrateAccel(uint8_t Loops = 6,uint8_t OffsetSaveAddress = 0x06); // Fine tune after setting offsets with less Loops. - void CalibrateAccel_MPU9250(uint8_t Loops = 6); - void CalibrateAccel_MPU6500(uint8_t Loops = 6); - void PID(uint8_t ReadAddress, uint8_t SaveAddress, float kP,float kI, uint8_t Loops); // Does the math - void PrintActiveOffsets(uint8_t AOffsetRegister = 0x06); // See the results of the Calibration - void PrintActiveOffsets_MPU6500(); - void PrintActiveOffsets_MPU9250(); + void CalibrateGyro(uint8_t Loops = 15); // Fine tune after setting offsets with less Loops. + void CalibrateAccel(uint8_t Loops = 15);// Fine tune after setting offsets with less Loops. + void PID(uint8_t ReadAddress, float kP,float kI, uint8_t Loops); // Does the math + void PrintActiveOffsets(); // See the results of the Calibration + // special methods for MotionApps 2.0 implementation diff --git a/Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h b/Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h index aa1f9248..5bb64ec9 100644 --- a/Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h +++ b/Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h @@ -370,7 +370,7 @@ uint8_t MPU6050::dmpInitialize() { // Lets get it over with fast Write everythin I2Cdev::writeBytes(devAddr,0x1B, 1, &(val = 0x18)); // 0001 1000 GYRO_CONFIG: 3 = +2000 Deg/sec I2Cdev::writeBytes(devAddr,0x6A, 1, &(val = 0xC0)); // 1100 1100 USER_CTRL: Enable Fifo and Reset Fifo I2Cdev::writeBytes(devAddr,0x38, 1, &(val = 0x02)); // 0000 0010 INT_ENABLE: RAW_DMP_INT_EN on - I2Cdev::writeBit(devAddr,0x6A, 2, &(val = 1)); // Reset FIFO one last time just for kicks. (MPUi2cWrite reads 0x6A first and only alters 1 bit and then saves the byte) + I2Cdev::writeBit(devAddr,0x6A, 2, 1); // Reset FIFO one last time just for kicks. (MPUi2cWrite reads 0x6A first and only alters 1 bit and then saves the byte) setDMPEnabled(false); // disable DMP for compatibility with the MPU6050 library /* dmpPacketSize += 16;//DMP_FEATURE_6X_LP_QUAT From 56bd0882d5be2c28f794bdbb70c56ad0c062f034 Mon Sep 17 00:00:00 2001 From: Homer Creutz Date: Sat, 27 Jul 2019 11:31:21 -0600 Subject: [PATCH 228/335] Undefined Variable Reading Fixed Coding Error Correction on Line 3259 Reading = Data; initialised Reading. --- Arduino/MPU6050/MPU6050.cpp | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/Arduino/MPU6050/MPU6050.cpp b/Arduino/MPU6050/MPU6050.cpp index 4edebb86..4879e384 100644 --- a/Arduino/MPU6050/MPU6050.cpp +++ b/Arduino/MPU6050/MPU6050.cpp @@ -3218,9 +3218,7 @@ void MPU6050::setDMPConfig2(uint8_t config) { /** @brief Fully calibrate Gyro from ZERO in about 6-7 Loops 600-700 readings */ - -void MPU6050::CalibrateGyro(uint8_t Loops) { - +void MPU6050::CalibrateGyro(uint8_t Loops ) { double kP = 0.3; double kI = 90; float x; @@ -3234,7 +3232,6 @@ void MPU6050::CalibrateGyro(uint8_t Loops) { /** @brief Fully calibrate Accel from ZERO in about 6-7 Loops 600-700 readings */ - void MPU6050::CalibrateAccel(uint8_t Loops ) { float kP = 0.3; @@ -3244,7 +3241,6 @@ void MPU6050::CalibrateAccel(uint8_t Loops ) { kP *= x; kI *= x; PID( 0x3B, kP, kI, Loops); - } void MPU6050::PID(uint8_t ReadAddress, float kP,float kI, uint8_t Loops){ @@ -3260,6 +3256,7 @@ void MPU6050::PID(uint8_t ReadAddress, float kP,float kI, uint8_t Loops){ Serial.write('>'); for (int i = 0; i < 3; i++) { I2Cdev::readWords(devAddr, SaveAddress + (i * shift), 1, &Data); // reads 1 or more 16 bit integers (Word) + Reading = Data; if(SaveAddress != 0x13){ BitZero[i] = Data & 1; // Capture Bit Zero to properly handle Accelerometer calibration ITerm[i] = ((float)Reading) * 8; @@ -3272,7 +3269,6 @@ void MPU6050::PID(uint8_t ReadAddress, float kP,float kI, uint8_t Loops){ for (int c = 0; c < 100; c++) {// 100 PI Calculations eSum = 0; for (int i = 0; i < 3; i++) { - I2Cdev::readWords(devAddr, ReadAddress + (i * 2), 1, &Data); // reads 1 or more 16 bit integers (Word) Reading = Data; if ((ReadAddress == 0x3B)&&(i == 2)) Reading -= 16384; //remove Gravity @@ -3289,7 +3285,6 @@ void MPU6050::PID(uint8_t ReadAddress, float kP,float kI, uint8_t Loops){ if((c == 99) && eSum > 1000){ // Error is still to great to continue c = 0; Serial.write('*'); - } if((eSum * ((ReadAddress == 0x3B)?.05: 1)) < 5) eSample++; // Successfully found offsets prepare to advance if((eSum < 100) && (c > 10) && (eSample >= 10)) break; // Advance to next Loop @@ -3311,7 +3306,6 @@ void MPU6050::PID(uint8_t ReadAddress, float kP,float kI, uint8_t Loops){ } #define printfloatx(Name,Variable,Spaces,Precision,EndTxt) Serial.print(F(Name)); {char S[(Spaces + Precision + 3)];Serial.print(F(" ")); Serial.print(dtostrf((float)Variable,Spaces,Precision ,S));}Serial.print(F(EndTxt));//Name,Variable,Spaces,Precision,EndTxt - void MPU6050::PrintActiveOffsets() { uint8_t AOffsetRegister = (getDeviceID() < 0x39 )? MPU6050_RA_XA_OFFS_H:0x77; int16_t Data[3]; @@ -3323,15 +3317,13 @@ void MPU6050::PrintActiveOffsets() { I2Cdev::readWords(devAddr, AOffsetRegister, 1, Data); I2Cdev::readWords(devAddr, AOffsetRegister+3, 1, Data+1); I2Cdev::readWords(devAddr, AOffsetRegister+6, 1, Data+2); - } // A_OFFSET_H_READ_A_OFFS(Data); printfloatx("", Data[0], 5, 0, ", "); printfloatx("", Data[1], 5, 0, ", "); printfloatx("", Data[2], 5, 0, ", "); - I2Cdev::readWords(devAddr, 0x13, 3, Data); - + // XG_OFFSET_H_READ_OFFS_USR(Data); printfloatx("", Data[0], 5, 0, ", "); printfloatx("", Data[1], 5, 0, ", "); printfloatx("", Data[2], 5, 0, "\n"); From 1e978b7e17a300098fa498cbe074b5a59b85202d Mon Sep 17 00:00:00 2001 From: Homer Creutz Date: Sun, 28 Jul 2019 22:23:01 -0600 Subject: [PATCH 229/335] Added mpu9255 also Added additional 9255 Calibration My MPU device id excluded some devices that Calibration could handle. --- Arduino/MPU6050/MPU6050.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Arduino/MPU6050/MPU6050.cpp b/Arduino/MPU6050/MPU6050.cpp index 4879e384..f7184445 100644 --- a/Arduino/MPU6050/MPU6050.cpp +++ b/Arduino/MPU6050/MPU6050.cpp @@ -2846,36 +2846,36 @@ void MPU6050::setZFineGain(int8_t gain) { // XA_OFFS_* registers int16_t MPU6050::getXAccelOffset() { - uint8_t SaveAddress = ((getDeviceID() < 0x39 )? MPU6050_RA_XA_OFFS_H:0x77); // MPU6050,MPU9150 Vs MPU6500,MPU9250 + uint8_t SaveAddress = ((getDeviceID() < 0x38 )? MPU6050_RA_XA_OFFS_H:0x77); // MPU6050,MPU9150 Vs MPU6500,MPU9250 I2Cdev::readBytes(devAddr, SaveAddress, 2, buffer); return (((int16_t)buffer[0]) << 8) | buffer[1]; } void MPU6050::setXAccelOffset(int16_t offset) { - uint8_t SaveAddress = ((getDeviceID() < 0x39 )? MPU6050_RA_XA_OFFS_H:0x77); // MPU6050,MPU9150 Vs MPU6500,MPU9250 + uint8_t SaveAddress = ((getDeviceID() < 0x38 )? MPU6050_RA_XA_OFFS_H:0x77); // MPU6050,MPU9150 Vs MPU6500,MPU9250 I2Cdev::writeWord(devAddr, SaveAddress, offset); } // YA_OFFS_* register int16_t MPU6050::getYAccelOffset() { - uint8_t SaveAddress = ((getDeviceID() < 0x39 )? MPU6050_RA_YA_OFFS_H:0x7A); // MPU6050,MPU9150 Vs MPU6500,MPU9250 + uint8_t SaveAddress = ((getDeviceID() < 0x38 )? MPU6050_RA_YA_OFFS_H:0x7A); // MPU6050,MPU9150 Vs MPU6500,MPU9250 I2Cdev::readBytes(devAddr, SaveAddress, 2, buffer); return (((int16_t)buffer[0]) << 8) | buffer[1]; } void MPU6050::setYAccelOffset(int16_t offset) { - uint8_t SaveAddress = ((getDeviceID() < 0x39 )? MPU6050_RA_YA_OFFS_H:0x7A); // MPU6050,MPU9150 Vs MPU6500,MPU9250 + uint8_t SaveAddress = ((getDeviceID() < 0x38 )? MPU6050_RA_YA_OFFS_H:0x7A); // MPU6050,MPU9150 Vs MPU6500,MPU9250 I2Cdev::writeWord(devAddr, SaveAddress, offset); } // ZA_OFFS_* register int16_t MPU6050::getZAccelOffset() { - uint8_t SaveAddress = ((getDeviceID() < 0x39 )? MPU6050_RA_ZA_OFFS_H:0x7D); // MPU6050,MPU9150 Vs MPU6500,MPU9250 + uint8_t SaveAddress = ((getDeviceID() < 0x38 )? MPU6050_RA_ZA_OFFS_H:0x7D); // MPU6050,MPU9150 Vs MPU6500,MPU9250 I2Cdev::readBytes(devAddr, SaveAddress, 2, buffer); return (((int16_t)buffer[0]) << 8) | buffer[1]; } void MPU6050::setZAccelOffset(int16_t offset) { - uint8_t SaveAddress = ((getDeviceID() < 0x39 )? MPU6050_RA_ZA_OFFS_H:0x7D); // MPU6050,MPU9150 Vs MPU6500,MPU9250 + uint8_t SaveAddress = ((getDeviceID() < 0x38 )? MPU6050_RA_ZA_OFFS_H:0x7D); // MPU6050,MPU9150 Vs MPU6500,MPU9250 I2Cdev::writeWord(devAddr, SaveAddress, offset); } @@ -3244,7 +3244,7 @@ void MPU6050::CalibrateAccel(uint8_t Loops ) { } void MPU6050::PID(uint8_t ReadAddress, float kP,float kI, uint8_t Loops){ - uint8_t SaveAddress = (ReadAddress == 0x3B)?((getDeviceID() < 0x39 )? 0x06:0x77):0x13; + uint8_t SaveAddress = (ReadAddress == 0x3B)?((getDeviceID() < 0x38 )? 0x06:0x77):0x13; int16_t Data; float Reading; @@ -3307,7 +3307,7 @@ void MPU6050::PID(uint8_t ReadAddress, float kP,float kI, uint8_t Loops){ #define printfloatx(Name,Variable,Spaces,Precision,EndTxt) Serial.print(F(Name)); {char S[(Spaces + Precision + 3)];Serial.print(F(" ")); Serial.print(dtostrf((float)Variable,Spaces,Precision ,S));}Serial.print(F(EndTxt));//Name,Variable,Spaces,Precision,EndTxt void MPU6050::PrintActiveOffsets() { - uint8_t AOffsetRegister = (getDeviceID() < 0x39 )? MPU6050_RA_XA_OFFS_H:0x77; + uint8_t AOffsetRegister = (getDeviceID() < 0x38 )? MPU6050_RA_XA_OFFS_H:0x77; int16_t Data[3]; //Serial.print(F("Offset Register 0x")); //Serial.print(AOffsetRegister>>4,HEX);Serial.print(AOffsetRegister&0x0F,HEX); From f694e124141e6a228ea884740300ad17871b8bd5 Mon Sep 17 00:00:00 2001 From: Jeff Rowberg Date: Fri, 2 Aug 2019 16:39:29 -0400 Subject: [PATCH 230/335] Add explicit (uint16_t *) typecast to readWords/writeWords calls --- Arduino/MPU6050/MPU6050.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Arduino/MPU6050/MPU6050.cpp b/Arduino/MPU6050/MPU6050.cpp index f7184445..a83ba836 100644 --- a/Arduino/MPU6050/MPU6050.cpp +++ b/Arduino/MPU6050/MPU6050.cpp @@ -3255,7 +3255,7 @@ void MPU6050::PID(uint8_t ReadAddress, float kP,float kI, uint8_t Loops){ uint32_t eSum ; Serial.write('>'); for (int i = 0; i < 3; i++) { - I2Cdev::readWords(devAddr, SaveAddress + (i * shift), 1, &Data); // reads 1 or more 16 bit integers (Word) + I2Cdev::readWords(devAddr, SaveAddress + (i * shift), 1, (uint16_t *)&Data); // reads 1 or more 16 bit integers (Word) Reading = Data; if(SaveAddress != 0x13){ BitZero[i] = Data & 1; // Capture Bit Zero to properly handle Accelerometer calibration @@ -3269,7 +3269,7 @@ void MPU6050::PID(uint8_t ReadAddress, float kP,float kI, uint8_t Loops){ for (int c = 0; c < 100; c++) {// 100 PI Calculations eSum = 0; for (int i = 0; i < 3; i++) { - I2Cdev::readWords(devAddr, ReadAddress + (i * 2), 1, &Data); // reads 1 or more 16 bit integers (Word) + I2Cdev::readWords(devAddr, ReadAddress + (i * 2), 1, (uint16_t *)&Data); // reads 1 or more 16 bit integers (Word) Reading = Data; if ((ReadAddress == 0x3B)&&(i == 2)) Reading -= 16384; //remove Gravity Error = -Reading; @@ -3280,7 +3280,7 @@ void MPU6050::PID(uint8_t ReadAddress, float kP,float kI, uint8_t Loops){ Data = round((PTerm + ITerm[i] ) / 8); //Compute PID Output Data = ((Data)&0xFFFE) |BitZero[i]; // Insert Bit0 Saved at beginning } else Data = round((PTerm + ITerm[i] ) / 4); //Compute PID Output - I2Cdev::writeWords(devAddr, SaveAddress + (i * shift), 1, &Data); + I2Cdev::writeWords(devAddr, SaveAddress + (i * shift), 1, (uint16_t *)&Data); } if((c == 99) && eSum > 1000){ // Error is still to great to continue c = 0; @@ -3298,7 +3298,7 @@ void MPU6050::PID(uint8_t ReadAddress, float kP,float kI, uint8_t Loops){ Data = round((ITerm[i] ) / 8); //Compute PID Output Data = ((Data)&0xFFFE) |BitZero[i]; // Insert Bit0 Saved at beginning } else Data = round((ITerm[i]) / 4); - I2Cdev::writeWords(devAddr, SaveAddress + (i * shift), 1, &Data ); + I2Cdev::writeWords(devAddr, SaveAddress + (i * shift), 1, (uint16_t *)&Data); } } resetFIFO(); @@ -3312,17 +3312,17 @@ void MPU6050::PrintActiveOffsets() { //Serial.print(F("Offset Register 0x")); //Serial.print(AOffsetRegister>>4,HEX);Serial.print(AOffsetRegister&0x0F,HEX); Serial.print(F("\n// X Accel Y Accel Z Accel X Gyro Y Gyro Z Gyro\n//OFFSETS ")); - if(AOffsetRegister == 0x06) I2Cdev::readWords(devAddr, AOffsetRegister, 3, Data); + if(AOffsetRegister == 0x06) I2Cdev::readWords(devAddr, AOffsetRegister, 3, (uint16_t *)Data); else { - I2Cdev::readWords(devAddr, AOffsetRegister, 1, Data); - I2Cdev::readWords(devAddr, AOffsetRegister+3, 1, Data+1); - I2Cdev::readWords(devAddr, AOffsetRegister+6, 1, Data+2); + I2Cdev::readWords(devAddr, AOffsetRegister, 1, (uint16_t *)Data); + I2Cdev::readWords(devAddr, AOffsetRegister+3, 1, (uint16_t *)Data+1); + I2Cdev::readWords(devAddr, AOffsetRegister+6, 1, (uint16_t *)Data+2); } // A_OFFSET_H_READ_A_OFFS(Data); printfloatx("", Data[0], 5, 0, ", "); printfloatx("", Data[1], 5, 0, ", "); printfloatx("", Data[2], 5, 0, ", "); - I2Cdev::readWords(devAddr, 0x13, 3, Data); + I2Cdev::readWords(devAddr, 0x13, 3, (uint16_t *)Data); // XG_OFFSET_H_READ_OFFS_USR(Data); printfloatx("", Data[0], 5, 0, ", "); printfloatx("", Data[1], 5, 0, ", "); From c630e2b17e67b84dcfc20d28943c0b30fa2dd706 Mon Sep 17 00:00:00 2001 From: Jeff Rowberg Date: Fri, 2 Aug 2019 16:40:16 -0400 Subject: [PATCH 231/335] Add braces around printfloatx macro to avoid certain execution flow problems --- Arduino/MPU6050/MPU6050.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Arduino/MPU6050/MPU6050.cpp b/Arduino/MPU6050/MPU6050.cpp index a83ba836..ae7a555e 100644 --- a/Arduino/MPU6050/MPU6050.cpp +++ b/Arduino/MPU6050/MPU6050.cpp @@ -3305,7 +3305,7 @@ void MPU6050::PID(uint8_t ReadAddress, float kP,float kI, uint8_t Loops){ resetDMP(); } -#define printfloatx(Name,Variable,Spaces,Precision,EndTxt) Serial.print(F(Name)); {char S[(Spaces + Precision + 3)];Serial.print(F(" ")); Serial.print(dtostrf((float)Variable,Spaces,Precision ,S));}Serial.print(F(EndTxt));//Name,Variable,Spaces,Precision,EndTxt +#define printfloatx(Name,Variable,Spaces,Precision,EndTxt) { Serial.print(F(Name)); {char S[(Spaces + Precision + 3)];Serial.print(F(" ")); Serial.print(dtostrf((float)Variable,Spaces,Precision ,S));}Serial.print(F(EndTxt)); }//Name,Variable,Spaces,Precision,EndTxt void MPU6050::PrintActiveOffsets() { uint8_t AOffsetRegister = (getDeviceID() < 0x38 )? MPU6050_RA_XA_OFFS_H:0x77; int16_t Data[3]; From 61833a6f555e26ac9f12ce0a36a3c069b03c8e56 Mon Sep 17 00:00:00 2001 From: liyupeng Date: Tue, 10 Sep 2019 01:51:45 +0800 Subject: [PATCH 232/335] esp32 mpu6050 calibration --- ESP32_ESP-IDF/.idea/ESP32_ESP-IDF.iml | 8 ++ ESP32_ESP-IDF/.idea/encodings.xml | 4 + ESP32_ESP-IDF/.idea/misc.xml | 6 + ESP32_ESP-IDF/.idea/modules.xml | 8 ++ ESP32_ESP-IDF/.idea/vcs.xml | 6 + ESP32_ESP-IDF/.idea/workspace.xml | 18 +++ ESP32_ESP-IDF/components/I2Cdev/I2Cdev.cpp | 16 +++ ESP32_ESP-IDF/components/I2Cdev/I2Cdev.h | 2 +- ESP32_ESP-IDF/components/MPU6050/MPU6050.cpp | 121 +++++++++++++++++++ ESP32_ESP-IDF/components/MPU6050/MPU6050.h | 4 + 10 files changed, 192 insertions(+), 1 deletion(-) create mode 100644 ESP32_ESP-IDF/.idea/ESP32_ESP-IDF.iml create mode 100644 ESP32_ESP-IDF/.idea/encodings.xml create mode 100644 ESP32_ESP-IDF/.idea/misc.xml create mode 100644 ESP32_ESP-IDF/.idea/modules.xml create mode 100644 ESP32_ESP-IDF/.idea/vcs.xml create mode 100644 ESP32_ESP-IDF/.idea/workspace.xml diff --git a/ESP32_ESP-IDF/.idea/ESP32_ESP-IDF.iml b/ESP32_ESP-IDF/.idea/ESP32_ESP-IDF.iml new file mode 100644 index 00000000..bc2cd874 --- /dev/null +++ b/ESP32_ESP-IDF/.idea/ESP32_ESP-IDF.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/ESP32_ESP-IDF/.idea/encodings.xml b/ESP32_ESP-IDF/.idea/encodings.xml new file mode 100644 index 00000000..15a15b21 --- /dev/null +++ b/ESP32_ESP-IDF/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/ESP32_ESP-IDF/.idea/misc.xml b/ESP32_ESP-IDF/.idea/misc.xml new file mode 100644 index 00000000..28a804d8 --- /dev/null +++ b/ESP32_ESP-IDF/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/ESP32_ESP-IDF/.idea/modules.xml b/ESP32_ESP-IDF/.idea/modules.xml new file mode 100644 index 00000000..b92c3089 --- /dev/null +++ b/ESP32_ESP-IDF/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/ESP32_ESP-IDF/.idea/vcs.xml b/ESP32_ESP-IDF/.idea/vcs.xml new file mode 100644 index 00000000..6c0b8635 --- /dev/null +++ b/ESP32_ESP-IDF/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/ESP32_ESP-IDF/.idea/workspace.xml b/ESP32_ESP-IDF/.idea/workspace.xml new file mode 100644 index 00000000..8f9f3d89 --- /dev/null +++ b/ESP32_ESP-IDF/.idea/workspace.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ESP32_ESP-IDF/components/I2Cdev/I2Cdev.cpp b/ESP32_ESP-IDF/components/I2Cdev/I2Cdev.cpp index 6d03d1e1..a9a9cf8d 100644 --- a/ESP32_ESP-IDF/components/I2Cdev/I2Cdev.cpp +++ b/ESP32_ESP-IDF/components/I2Cdev/I2Cdev.cpp @@ -253,3 +253,19 @@ bool I2Cdev::writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_ } +/** + * read word + * @param devAddr + * @param regAddr + * @param data + * @param timeout + * @return + */ +int8_t I2Cdev::readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data, uint16_t timeout){ + uint8_t msb[2] = {0,0}; + readBytes(devAddr, regAddr, 2, msb); + *data = (int16_t)((msb[0] << 8) | msb[1]); + return 0; +} + + diff --git a/ESP32_ESP-IDF/components/I2Cdev/I2Cdev.h b/ESP32_ESP-IDF/components/I2Cdev/I2Cdev.h index c88b5fee..f2e8ce13 100644 --- a/ESP32_ESP-IDF/components/I2Cdev/I2Cdev.h +++ b/ESP32_ESP-IDF/components/I2Cdev/I2Cdev.h @@ -60,7 +60,7 @@ class I2Cdev { static int8_t readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout); //TODO static int8_t readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout); static int8_t readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout); - //TODO static int8_t readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout); + static int8_t readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout); static int8_t readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout); //TODO static int8_t readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout); diff --git a/ESP32_ESP-IDF/components/MPU6050/MPU6050.cpp b/ESP32_ESP-IDF/components/MPU6050/MPU6050.cpp index 3aa0ecc4..1bbbbb77 100644 --- a/ESP32_ESP-IDF/components/MPU6050/MPU6050.cpp +++ b/ESP32_ESP-IDF/components/MPU6050/MPU6050.cpp @@ -3232,3 +3232,124 @@ uint8_t MPU6050::getDMPConfig2() { void MPU6050::setDMPConfig2(uint8_t config) { I2Cdev::writeByte(devAddr, MPU6050_RA_DMP_CFG_2, config); } + + + +/** + * calibration + * + */ + + +/** + * + * @param val + * @param I_Min + * @param I_Max + * @param O_Min + * @param O_Max + * @return + */ + +float map(float val, float I_Min, float I_Max, float O_Min, float O_Max){ + return(val/(I_Max-I_Min)*(O_Max-O_Min) + O_Min); +} + + + + + +/** + @brief Fully calibrate Gyro from ZERO in about 6-7 Loops 600-700 readings +*/ +void MPU6050::CalibrateGyro(uint8_t Loops ) { + double kP = 0.3; + double kI = 90; + float x; + x = (100 - map(Loops, 1, 5, 20, 0)) * .01; + kP *= x; + kI *= x; + + PID( 0x43, kP, kI, Loops); +} + +/** + @brief Fully calibrate Accel from ZERO in about 6-7 Loops 600-700 readings +*/ +void MPU6050::CalibrateAccel(uint8_t Loops ) { + + float kP = 0.3; + float kI = 20; + float x; + x = (100 - map(Loops, 1, 5, 20, 0)) * .01; + kP *= x; + kI *= x; + PID( 0x3B, kP, kI, Loops); +} + + +/** + * + * @param ReadAddress + * @param kP + * @param kI + * @param Loops + */ +void MPU6050::PID(uint8_t ReadAddress, float kP,float kI, uint8_t Loops){ + uint8_t SaveAddress = (ReadAddress == 0x3B)?((getDeviceID() < 0x38 )? 0x06:0x77):0x13; + + int16_t Data; + float Reading; + int16_t BitZero[3]; + uint8_t shift =(SaveAddress == 0x77)?3:2; + float Error, PTerm, ITerm[3]; + int16_t eSample; + uint32_t eSum ; + for (int i = 0; i < 3; i++) { + I2Cdev::readWord(devAddr, SaveAddress + (i * shift), (uint16_t *)&Data); // reads 1 or more 16 bit integers (Word) + Reading = Data; + if(SaveAddress != 0x13){ + BitZero[i] = Data & 1; // Capture Bit Zero to properly handle Accelerometer calibration + ITerm[i] = ((float)Reading) * 8; + } else { + ITerm[i] = Reading * 4; + } + } + for (int L = 0; L < Loops; L++) { + eSample = 0; + for (int c = 0; c < 100; c++) {// 100 PI Calculations + eSum = 0; + for (int i = 0; i < 3; i++) { + I2Cdev::readWord(devAddr, ReadAddress + (i * 2), (uint16_t *)&Data); // reads 1 or more 16 bit integers (Word) + Reading = Data; + if ((ReadAddress == 0x3B)&&(i == 2)) Reading -= 16384; //remove Gravity + Error = -Reading; + eSum += abs(Reading); + PTerm = kP * Error; + ITerm[i] += (Error * 0.001) * kI; // Integral term 1000 Calculations a second = 0.001 + if(SaveAddress != 0x13){ + Data = round((PTerm + ITerm[i] ) / 8); //Compute PID Output + Data = ((Data)&0xFFFE) |BitZero[i]; // Insert Bit0 Saved at beginning + } else Data = round((PTerm + ITerm[i] ) / 4); //Compute PID Output + I2Cdev::writeWord(devAddr, SaveAddress + (i * shift),Data); + } + if((c == 99) && eSum > 1000){ // Error is still to great to continue + c = 0; + } + if((eSum * ((ReadAddress == 0x3B)?.05: 1)) < 5) eSample++; // Successfully found offsets prepare to advance + if((eSum < 100) && (c > 10) && (eSample >= 10)) break; // Advance to next Loop +// delay(1); + } + kP *= .75; + kI *= .75; + for (int i = 0; i < 3; i++){ + if(SaveAddress != 0x13) { + Data = round((ITerm[i] ) / 8); //Compute PID Output + Data = ((Data)&0xFFFE) |BitZero[i]; // Insert Bit0 Saved at beginning + } else Data = round((ITerm[i]) / 4); + I2Cdev::writeWord(devAddr, SaveAddress + (i * shift), Data); + } + } + resetFIFO(); + resetDMP(); +} \ No newline at end of file diff --git a/ESP32_ESP-IDF/components/MPU6050/MPU6050.h b/ESP32_ESP-IDF/components/MPU6050/MPU6050.h index bb5fef40..304bfa1e 100644 --- a/ESP32_ESP-IDF/components/MPU6050/MPU6050.h +++ b/ESP32_ESP-IDF/components/MPU6050/MPU6050.h @@ -1026,6 +1026,10 @@ class MPU6050 { uint16_t dmpGetFIFOPacketSize(); #endif + void CalibrateGyro(uint8_t Loops = 15); // Fine tune after setting offsets with less Loops. + void CalibrateAccel(uint8_t Loops = 15);// Fine tune after setting offsets with less Loops. + void PID(uint8_t ReadAddress, float kP,float kI, uint8_t Loops); // Does the + private: uint8_t devAddr; uint8_t buffer[14]; From eb01051441f38c1f606833f70c259918a8326a4b Mon Sep 17 00:00:00 2001 From: Bascy Date: Thu, 17 Oct 2019 22:06:23 +0200 Subject: [PATCH 233/335] Added dependency on Wire I2Cdevlib-Core won't compile in platformIO --- Arduino/I2Cdev/library.json | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Arduino/I2Cdev/library.json b/Arduino/I2Cdev/library.json index d4560960..074266da 100644 --- a/Arduino/I2Cdev/library.json +++ b/Arduino/I2Cdev/library.json @@ -9,5 +9,10 @@ "url": "https://github.com/jrowberg/i2cdevlib.git" }, "frameworks": "arduino", - "platforms": "atmelavr" + "platforms": "atmelavr", + "dependencies": [ + { + "name": "Wire" + } + ] } From c79e9da1234adbc053c58c170440db22fad41ff7 Mon Sep 17 00:00:00 2001 From: Homer Creutz Date: Sat, 26 Oct 2019 23:37:45 -0600 Subject: [PATCH 234/335] Overflow protection and no interrupts Eliminated the headakes from FIFO buffer overflow and No More need for the interrupt pin and attach interrupts After an overflow of the FIFO buffer I correct the damage to the corrupted FIFO buffer eliminating the need to reset the fifo buffer. Just get the latest DMP reading when you need it ignore the rest. One simple function call GetCurrentFIFOPacket() if you need data onec in a blue moon and GetCurrentFIFOPacketTimed() if you want to have the speed of using the interupt pin but don't want to deal with interrupts uses a blink withou delay timer to capture the fifo packet at the moment it is created (auto tunes). Now you can dely() all you want and still get perfect results!!! Z --- Arduino/MPU6050/MPU6050.cpp | 95 ++++++ Arduino/MPU6050/MPU6050.h | 2 + ...050_DMP6_using_DMP_V6.12_No_Interrupts.ino | 286 +++++++++++++++++ ...0_DMP6_using_DMP_V6.12_Overflow_Immune.ino | 290 ++++++++++++++++++ 4 files changed, 673 insertions(+) create mode 100644 Arduino/MPU6050/examples/MPU6050_DMP6_using_DMP_V6.12_No_Interrupts/MPU6050_DMP6_using_DMP_V6.12_No_Interrupts.ino create mode 100644 Arduino/MPU6050/examples/MPU6050_DMP6_using_DMP_V6.12_Overflow_Immune/MPU6050_DMP6_using_DMP_V6.12_Overflow_Immune.ino diff --git a/Arduino/MPU6050/MPU6050.cpp b/Arduino/MPU6050/MPU6050.cpp index ae7a555e..85826e48 100644 --- a/Arduino/MPU6050/MPU6050.cpp +++ b/Arduino/MPU6050/MPU6050.cpp @@ -2740,6 +2740,101 @@ void MPU6050::getFIFOBytes(uint8_t *data, uint8_t length) { *data = 0; } } + +/** Get latest byte from FIFO buffer no matter how much time has passed. + * === GetCurrentFIFOPacket === + * ================================================================ + * Returns 1) when nothing special was done + * 2) when recovering from overflow + * 0) when no valid data is available + * ================================================================ */ + int8_t MPU6050::GetCurrentFIFOPacket(uint8_t *data, uint8_t length) { // overflow proof + uint16_t fifoC; + uint8_t Error; + uint8_t Flag = 0; + uint8_t overflowed = 0; + uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU + do { + if (Error = (fifoC = getFIFOCount()) % length) { + mpuIntStatus = getIntStatus(); + if ( mpuIntStatus & _BV(MPU6050_INTERRUPT_FIFO_OFLOW_BIT)) { + getFIFOBytes(data, Error); // lets remove the overflow portion + getFIFOBytes(data, length); + overflowed = 1; + if (Error = (fifoC = getFIFOCount()) % length) { // there could be some remaining bytes to deal with that arrived after we freed up some space + getFIFOBytes(data, Error); // lets remove the overflow portion again + if ((fifoC = getFIFOCount()) % length) { + resetFIFO(); + return 0; + } + } + } + } + while(fifoC >(2*length)){ // Quickly remove all but 2 packets + getFIFOBytes(data, length); + fifoC -= length; + Flag++; + } + if (fifoC >= length){ // Get the newest and last packet + getFIFOBytes(data, length); + fifoC -= length; + Flag++; + } + } while (fifoC >= length); // always reprocess the last packet for additional data + return (overflowed ? -1:Flag); + } + +int8_t MPU6050::GetCurrentFIFOPacketTimed(uint8_t *data, uint8_t length) { // overflow proof + static unsigned long xTimer; + static int t = 10000; + static int x = 1; + if (micros() - xTimer < (t)) return 0;// This is an auto tuning routine to discover the exact time the fifo buffer is filled + uint16_t fifoC; + uint8_t Error; + uint8_t Flag = 0; + uint8_t overflowed = 0; + uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU + do { + if (Error = (fifoC = getFIFOCount()) % length) { + mpuIntStatus = getIntStatus(); + if ( mpuIntStatus & _BV(MPU6050_INTERRUPT_FIFO_OFLOW_BIT)) { + getFIFOBytes(data, Error); // lets remove the overflow portion + getFIFOBytes(data, length); + overflowed = 1; + if (Error = (fifoC = getFIFOCount()) % length) { // there could be some remaining bytes to deal with that arrived after we freed up some space + getFIFOBytes(data, Error); // lets remove the overflow portion again + if ((fifoC = getFIFOCount()) % length) { + resetFIFO(); + return 0; + } + } + } + } + if(fifoC == 0 && (fifoC = getFIFOCount())){ // no data was present above but now we have it Timing is perfect!!! + x = 0; // Lets stop moving around and changing the timing! + } + while(fifoC >(2*length)){ // Quickly remove all but 2 packets + getFIFOBytes(data, length); + fifoC -= length; + x = 1; // Something caused a delay and everything off again start searching for the sweet spot + } + if (fifoC >= length){ // Get the newest and last packet + getFIFOBytes(data, length); + Flag = 1 + overflowed; + fifoC -= length; + xTimer = micros(); + t -= x; + t = max(t,5000); // we have to limit this if there are external delays to deal with. + + }else{ + t += x; + fifoC = getFIFOCount(); // We didn't have data before but I bet we have it now!!! Lets check + } + } while (fifoC >= length); + return Flag; +} + + /** Write byte to FIFO buffer. * @see getFIFOByte() * @see MPU6050_RA_FIFO_R_W diff --git a/Arduino/MPU6050/MPU6050.h b/Arduino/MPU6050/MPU6050.h index 54e7c8f0..02643f68 100644 --- a/Arduino/MPU6050/MPU6050.h +++ b/Arduino/MPU6050/MPU6050.h @@ -714,6 +714,8 @@ class MPU6050 { // FIFO_R_W register uint8_t getFIFOByte(); + int8_t GetCurrentFIFOPacket(uint8_t *data, uint8_t length); + int8_t GetCurrentFIFOPacketTimed(uint8_t *data, uint8_t length); void setFIFOByte(uint8_t data); void getFIFOBytes(uint8_t *data, uint8_t length); diff --git a/Arduino/MPU6050/examples/MPU6050_DMP6_using_DMP_V6.12_No_Interrupts/MPU6050_DMP6_using_DMP_V6.12_No_Interrupts.ino b/Arduino/MPU6050/examples/MPU6050_DMP6_using_DMP_V6.12_No_Interrupts/MPU6050_DMP6_using_DMP_V6.12_No_Interrupts.ino new file mode 100644 index 00000000..6a5a480b --- /dev/null +++ b/Arduino/MPU6050/examples/MPU6050_DMP6_using_DMP_V6.12_No_Interrupts/MPU6050_DMP6_using_DMP_V6.12_No_Interrupts.ino @@ -0,0 +1,286 @@ +// I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class using DMP (MotionApps v6.12) +// 6/21/2012 by Jeff Rowberg +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// 2019-07-10 - Uses the new version of the DMP Firmware V6.12 +// - Note: I believe the Teapot demo is broken with this versin as +// - the fifo buffer structure has changed +// 2016-04-18 - Eliminated a potential infinite loop +// 2013-05-08 - added seamless Fastwire support +// - added note about gyro calibration +// 2012-06-21 - added note about Arduino 1.0.1 + Leonardo compatibility error +// 2012-06-20 - improved FIFO overflow handling and simplified read process +// 2012-06-19 - completely rearranged DMP initialization code and simplification +// 2012-06-13 - pull gyro and accel data from FIFO packet instead of reading directly +// 2012-06-09 - fix broken FIFO read sequence and change interrupt detection to RISING +// 2012-06-05 - add gravity-compensated initial reference frame acceleration output +// - add 3D math helper file to DMP6 example sketch +// - add Euler output and Yaw/Pitch/Roll output formats +// 2012-06-04 - remove accel offset clearing for better results (thanks Sungon Lee) +// 2012-06-01 - fixed gyro sensitivity to be 2000 deg/sec instead of 250 +// 2012-05-30 - basic DMP initialization working + +/* ============================================ + I2Cdev device library code is placed under the MIT license + Copyright (c) 2012 Jeff Rowberg + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + =============================================== +*/ + +// I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files +// for both classes must be in the include path of your project +#include "I2Cdev.h" + +#include "MPU6050_6Axis_MotionApps_V6_12.h" +//#include "MPU6050.h" // not necessary if using MotionApps include file + +// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation +// is used in I2Cdev.h +#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE +#include "Wire.h" +#endif + +// class default I2C address is 0x68 +// specific I2C addresses may be passed as a parameter here +// AD0 low = 0x68 (default for SparkFun breakout and InvenSense evaluation board) +// AD0 high = 0x69 +MPU6050 mpu; +//MPU6050 mpu(0x69); // <-- use for AD0 high + +/* ========================================================================= + NOTE: In addition to connection 3.3v, GND, SDA, and SCL, this sketch + depends on the MPU-6050's INT pin being connected to the Arduino's + external interrupt #0 pin. On the Arduino Uno and Mega 2560, this is + digital I/O pin 2. + ========================================================================= */ + +/* ========================================================================= + NOTE: Arduino v1.0.1 with the Leonardo board generates a compile error + when using Serial.write(buf, len). The Teapot output uses this method. + The solution requires a modification to the Arduino USBAPI.h file, which + is fortunately simple, but annoying. This will be fixed in the next IDE + release. For more info, see these links: + + http://arduino.cc/forum/index.php/topic,109987.0.html + http://code.google.com/p/arduino/issues/detail?id=958 + ========================================================================= */ + + + +// uncomment "OUTPUT_READABLE_QUATERNION" if you want to see the actual +// quaternion components in a [w, x, y, z] format (not best for parsing +// on a remote host such as Processing or something though) +//#define OUTPUT_READABLE_QUATERNION + +// uncomment "OUTPUT_READABLE_EULER" if you want to see Euler angles +// (in degrees) calculated from the quaternions coming from the FIFO. +// Note that Euler angles suffer from gimbal lock (for more info, see +// http://en.wikipedia.org/wiki/Gimbal_lock) +//#define OUTPUT_READABLE_EULER + +// uncomment "OUTPUT_READABLE_YAWPITCHROLL" if you want to see the yaw/ +// pitch/roll angles (in degrees) calculated from the quaternions coming +// from the FIFO. Note this also requires gravity vector calculations. +// Also note that yaw/pitch/roll angles suffer from gimbal lock (for +// more info, see: http://en.wikipedia.org/wiki/Gimbal_lock) +#define OUTPUT_READABLE_YAWPITCHROLL + +// uncomment "OUTPUT_READABLE_REALACCEL" if you want to see acceleration +// components with gravity removed. This acceleration reference frame is +// not compensated for orientation, so +X is always +X according to the +// sensor, just without the effects of gravity. If you want acceleration +// compensated for orientation, us OUTPUT_READABLE_WORLDACCEL instead. +//#define OUTPUT_READABLE_REALACCEL + +// uncomment "OUTPUT_READABLE_WORLDACCEL" if you want to see acceleration +// components with gravity removed and adjusted for the world frame of +// reference (yaw is relative to initial orientation, since no magnetometer +// is present in this case). Could be quite handy in some cases. +//#define OUTPUT_READABLE_WORLDACCEL + +// uncomment "OUTPUT_TEAPOT" if you want output that matches the +// format used for the InvenSense teapot demo +//#define OUTPUT_TEAPOT + + + +#define INTERRUPT_PIN 2 // use pin 2 on Arduino Uno & most boards +#define LED_PIN 13 // (Arduino is 13, Teensy is 11, Teensy++ is 6) +bool blinkState = false; + +// MPU control/status vars +bool dmpReady = false; // set true if DMP init was successful +uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU +uint8_t devStatus; // return status after each device operation (0 = success, !0 = error) +uint16_t packetSize; // expected DMP packet size (default is 42 bytes) +uint16_t fifoCount; // count of all bytes currently in FIFO +uint8_t fifoBuffer[64]; // FIFO storage buffer + +// orientation/motion vars +Quaternion q; // [w, x, y, z] quaternion container +VectorInt16 aa; // [x, y, z] accel sensor measurements +VectorInt16 gy; // [x, y, z] gyro sensor measurements +VectorInt16 aaReal; // [x, y, z] gravity-free accel sensor measurements +VectorInt16 aaWorld; // [x, y, z] world-frame accel sensor measurements +VectorFloat gravity; // [x, y, z] gravity vector +float euler[3]; // [psi, theta, phi] Euler angle container +float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector + +// packet structure for InvenSense teapot demo +uint8_t teapotPacket[14] = { '$', 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0x00, 0x00, '\r', '\n' }; + + + +// ================================================================ +// === INTERRUPT DETECTION ROUTINE === +// ================================================================ + +volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high +void dmpDataReady() { + mpuInterrupt = true; +} + +// ================================================================ +// === INITIAL SETUP === +// ================================================================ + +void setup() { + // join I2C bus (I2Cdev library doesn't do this automatically) +#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE + Wire.begin(); + Wire.setClock(400000); // 400kHz I2C clock. Comment this line if having compilation difficulties +#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE + Fastwire::setup(400, true); +#endif + + // initialize serial communication + // (115200 chosen because it is required for Teapot Demo output, but it's + // really up to you depending on your project) + Serial.begin(115200); + while (!Serial); // wait for Leonardo enumeration, others continue immediately + + // NOTE: 8MHz or slower host processors, like the Teensy @ 3.3V or Arduino + // Pro Mini running at 3.3V, cannot handle this baud rate reliably due to + // the baud timing being too misaligned with processor ticks. You must use + // 38400 or slower in these cases, or use some kind of external separate + // crystal solution for the UART timer. + + // initialize device + Serial.println(F("Initializing I2C devices...")); + mpu.initialize(); + pinMode(INTERRUPT_PIN, INPUT); + + // verify connection + Serial.println(F("Testing device connections...")); + Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed")); + + // wait for ready + Serial.println(F("\nSend any character to begin DMP programming and demo: ")); + while (Serial.available() && Serial.read()); // empty buffer + while (!Serial.available()); // wait for data + while (Serial.available() && Serial.read()); // empty buffer again + + // load and configure the DMP + Serial.println(F("Initializing DMP...")); + devStatus = mpu.dmpInitialize(); + + // supply your own gyro offsets here, scaled for min sensitivity + mpu.setXGyroOffset(51); + mpu.setYGyroOffset(8); + mpu.setZGyroOffset(21); + mpu.setXAccelOffset(1150); + mpu.setYAccelOffset(-50); + mpu.setZAccelOffset(1060); + // make sure it worked (returns 0 if so) + if (devStatus == 0) { + // Calibration Time: generate offsets and calibrate our MPU6050 + mpu.CalibrateAccel(6); + mpu.CalibrateGyro(6); + Serial.println(); + mpu.PrintActiveOffsets(); + // turn on the DMP, now that it's ready + Serial.println(F("Enabling DMP...")); + mpu.setDMPEnabled(true); + dmpReady = true; + // get expected DMP packet size for later comparison + packetSize = mpu.dmpGetFIFOPacketSize(); + } else { + // ERROR! + // 1 = initial memory load failed + // 2 = DMP configuration updates failed + // (if it's going to break, usually the code will be 1) + Serial.print(F("DMP Initialization failed (code ")); + Serial.print(devStatus); + Serial.println(F(")")); + } + + + // configure LED for output + pinMode(LED_PIN, OUTPUT); + + while (!dmpReady) {}// if programming failed, don't try to do anything +} + +// ================================================================ +// === MAIN PROGRAM LOOP === +// ================================================================ +int loopCtr; +void loop() { + // other fast code can go here. faster the better + loopCtr++; + if (!mpu.GetCurrentFIFOPacket(fifoBuffer, packetSize)) { // returns 0 when no data has arrived. + return ; // nothing to give to the program so return. + } + Serial.print("Loops: "); + Serial.print(loopCtr); + loopCtr = 0; + // display Euler angles in degrees + mpu.dmpGetQuaternion(&q, fifoBuffer); + mpu.dmpGetGravity(&gravity, &q); + mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); + Serial.print(" ypr\t"); + Serial.print(ypr[0] * 180 / M_PI); + Serial.print("\t"); + Serial.print(ypr[1] * 180 / M_PI); + Serial.print("\t"); + Serial.print(ypr[2] * 180 / M_PI); + /* + mpu.dmpGetAccel(&aa, fifoBuffer); + Serial.print("\tRaw Accl XYZ\t"); + Serial.print(aa.x); + Serial.print("\t"); + Serial.print(aa.y); + Serial.print("\t"); + Serial.print(aa.z); + mpu.dmpGetGyro(&gy, fifoBuffer); + Serial.print("\tRaw Gyro XYZ\t"); + Serial.print(gy.x); + Serial.print("\t"); + Serial.print(gy.y); + Serial.print("\t"); + Serial.print(gy.z); + */ + Serial.println(); + // blink LED to indicate activity + blinkState = !blinkState; + digitalWrite(LED_PIN, blinkState); + +} diff --git a/Arduino/MPU6050/examples/MPU6050_DMP6_using_DMP_V6.12_Overflow_Immune/MPU6050_DMP6_using_DMP_V6.12_Overflow_Immune.ino b/Arduino/MPU6050/examples/MPU6050_DMP6_using_DMP_V6.12_Overflow_Immune/MPU6050_DMP6_using_DMP_V6.12_Overflow_Immune.ino new file mode 100644 index 00000000..e507f533 --- /dev/null +++ b/Arduino/MPU6050/examples/MPU6050_DMP6_using_DMP_V6.12_Overflow_Immune/MPU6050_DMP6_using_DMP_V6.12_Overflow_Immune.ino @@ -0,0 +1,290 @@ +// I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class using DMP (MotionApps v6.12) +// 6/21/2012 by Jeff Rowberg +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// 2019-07-10 - Uses the new version of the DMP Firmware V6.12 +// - Note: I believe the Teapot demo is broken with this versin as +// - the fifo buffer structure has changed +// 2016-04-18 - Eliminated a potential infinite loop +// 2013-05-08 - added seamless Fastwire support +// - added note about gyro calibration +// 2012-06-21 - added note about Arduino 1.0.1 + Leonardo compatibility error +// 2012-06-20 - improved FIFO overflow handling and simplified read process +// 2012-06-19 - completely rearranged DMP initialization code and simplification +// 2012-06-13 - pull gyro and accel data from FIFO packet instead of reading directly +// 2012-06-09 - fix broken FIFO read sequence and change interrupt detection to RISING +// 2012-06-05 - add gravity-compensated initial reference frame acceleration output +// - add 3D math helper file to DMP6 example sketch +// - add Euler output and Yaw/Pitch/Roll output formats +// 2012-06-04 - remove accel offset clearing for better results (thanks Sungon Lee) +// 2012-06-01 - fixed gyro sensitivity to be 2000 deg/sec instead of 250 +// 2012-05-30 - basic DMP initialization working + +/* ============================================ + I2Cdev device library code is placed under the MIT license + Copyright (c) 2012 Jeff Rowberg + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + =============================================== +*/ + +// I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files +// for both classes must be in the include path of your project +#include "I2Cdev.h" + +#include "MPU6050_6Axis_MotionApps_V6_12.h" +//#include "MPU6050.h" // not necessary if using MotionApps include file + +// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation +// is used in I2Cdev.h +#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE +#include "Wire.h" +#endif + +// class default I2C address is 0x68 +// specific I2C addresses may be passed as a parameter here +// AD0 low = 0x68 (default for SparkFun breakout and InvenSense evaluation board) +// AD0 high = 0x69 +MPU6050 mpu; +//MPU6050 mpu(0x69); // <-- use for AD0 high + +/* ========================================================================= + NOTE: In addition to connection 3.3v, GND, SDA, and SCL, this sketch + depends on the MPU-6050's INT pin being connected to the Arduino's + external interrupt #0 pin. On the Arduino Uno and Mega 2560, this is + digital I/O pin 2. + ========================================================================= */ + +/* ========================================================================= + NOTE: Arduino v1.0.1 with the Leonardo board generates a compile error + when using Serial.write(buf, len). The Teapot output uses this method. + The solution requires a modification to the Arduino USBAPI.h file, which + is fortunately simple, but annoying. This will be fixed in the next IDE + release. For more info, see these links: + + http://arduino.cc/forum/index.php/topic,109987.0.html + http://code.google.com/p/arduino/issues/detail?id=958 + ========================================================================= */ + + + +// uncomment "OUTPUT_READABLE_QUATERNION" if you want to see the actual +// quaternion components in a [w, x, y, z] format (not best for parsing +// on a remote host such as Processing or something though) +//#define OUTPUT_READABLE_QUATERNION + +// uncomment "OUTPUT_READABLE_EULER" if you want to see Euler angles +// (in degrees) calculated from the quaternions coming from the FIFO. +// Note that Euler angles suffer from gimbal lock (for more info, see +// http://en.wikipedia.org/wiki/Gimbal_lock) +//#define OUTPUT_READABLE_EULER + +// uncomment "OUTPUT_READABLE_YAWPITCHROLL" if you want to see the yaw/ +// pitch/roll angles (in degrees) calculated from the quaternions coming +// from the FIFO. Note this also requires gravity vector calculations. +// Also note that yaw/pitch/roll angles suffer from gimbal lock (for +// more info, see: http://en.wikipedia.org/wiki/Gimbal_lock) +#define OUTPUT_READABLE_YAWPITCHROLL + +// uncomment "OUTPUT_READABLE_REALACCEL" if you want to see acceleration +// components with gravity removed. This acceleration reference frame is +// not compensated for orientation, so +X is always +X according to the +// sensor, just without the effects of gravity. If you want acceleration +// compensated for orientation, us OUTPUT_READABLE_WORLDACCEL instead. +//#define OUTPUT_READABLE_REALACCEL + +// uncomment "OUTPUT_READABLE_WORLDACCEL" if you want to see acceleration +// components with gravity removed and adjusted for the world frame of +// reference (yaw is relative to initial orientation, since no magnetometer +// is present in this case). Could be quite handy in some cases. +//#define OUTPUT_READABLE_WORLDACCEL + +// uncomment "OUTPUT_TEAPOT" if you want output that matches the +// format used for the InvenSense teapot demo +//#define OUTPUT_TEAPOT + + + +#define INTERRUPT_PIN 2 // use pin 2 on Arduino Uno & most boards +#define LED_PIN 13 // (Arduino is 13, Teensy is 11, Teensy++ is 6) +bool blinkState = false; + +// MPU control/status vars +bool dmpReady = false; // set true if DMP init was successful +uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU +uint8_t devStatus; // return status after each device operation (0 = success, !0 = error) +uint16_t packetSize; // expected DMP packet size (default is 42 bytes) +uint16_t fifoCount; // count of all bytes currently in FIFO +uint8_t fifoBuffer[64]; // FIFO storage buffer + +// orientation/motion vars +Quaternion q; // [w, x, y, z] quaternion container +VectorInt16 aa; // [x, y, z] accel sensor measurements +VectorInt16 gy; // [x, y, z] gyro sensor measurements +VectorInt16 aaReal; // [x, y, z] gravity-free accel sensor measurements +VectorInt16 aaWorld; // [x, y, z] world-frame accel sensor measurements +VectorFloat gravity; // [x, y, z] gravity vector +float euler[3]; // [psi, theta, phi] Euler angle container +float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector + +// packet structure for InvenSense teapot demo +uint8_t teapotPacket[14] = { '$', 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0x00, 0x00, '\r', '\n' }; + + + +// ================================================================ +// === INTERRUPT DETECTION ROUTINE === +// ================================================================ + +volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high +void dmpDataReady() { + mpuInterrupt = true; +} + +// ================================================================ +// === INITIAL SETUP === +// ================================================================ + +void setup() { + // join I2C bus (I2Cdev library doesn't do this automatically) +#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE + Wire.begin(); + Wire.setClock(400000); // 400kHz I2C clock. Comment this line if having compilation difficulties +#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE + Fastwire::setup(400, true); +#endif + + // initialize serial communication + // (115200 chosen because it is required for Teapot Demo output, but it's + // really up to you depending on your project) + Serial.begin(115200); + while (!Serial); // wait for Leonardo enumeration, others continue immediately + + // NOTE: 8MHz or slower host processors, like the Teensy @ 3.3V or Arduino + // Pro Mini running at 3.3V, cannot handle this baud rate reliably due to + // the baud timing being too misaligned with processor ticks. You must use + // 38400 or slower in these cases, or use some kind of external separate + // crystal solution for the UART timer. + + // initialize device + Serial.println(F("Initializing I2C devices...")); + mpu.initialize(); + pinMode(INTERRUPT_PIN, INPUT); + + // verify connection + Serial.println(F("Testing device connections...")); + Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed")); + + // wait for ready + Serial.println(F("\nSend any character to begin DMP programming and demo: ")); + while (Serial.available() && Serial.read()); // empty buffer + while (!Serial.available()); // wait for data + while (Serial.available() && Serial.read()); // empty buffer again + + // load and configure the DMP + Serial.println(F("Initializing DMP...")); + devStatus = mpu.dmpInitialize(); + + // supply your own gyro offsets here, scaled for min sensitivity + mpu.setXGyroOffset(51); + mpu.setYGyroOffset(8); + mpu.setZGyroOffset(21); + mpu.setXAccelOffset(1150); + mpu.setYAccelOffset(-50); + mpu.setZAccelOffset(1060); + // make sure it worked (returns 0 if so) + if (devStatus == 0) { + // Calibration Time: generate offsets and calibrate our MPU6050 + mpu.CalibrateAccel(6); + mpu.CalibrateGyro(6); + Serial.println(); + mpu.PrintActiveOffsets(); + // turn on the DMP, now that it's ready + Serial.println(F("Enabling DMP...")); + mpu.setDMPEnabled(true); + dmpReady = true; + // get expected DMP packet size for later comparison + packetSize = mpu.dmpGetFIFOPacketSize(); + } else { + // ERROR! + // 1 = initial memory load failed + // 2 = DMP configuration updates failed + // (if it's going to break, usually the code will be 1) + Serial.print(F("DMP Initialization failed (code ")); + Serial.print(devStatus); + Serial.println(F(")")); + } + + + // configure LED for output + pinMode(LED_PIN, OUTPUT); + + while (!dmpReady) {}// if programming failed, don't try to do anything +} + +// ================================================================ +// === MAIN PROGRAM LOOP === +// ================================================================ +void loop() { + + // Remove this user input and place your code here that can block this as much as you want + // Ultimate blocking code: + // wait for user input + Serial.println(F("\nSend any character to retrieve the latest position from the DMP FIFO Buffer: ")); + while (Serial.available() && Serial.read()); // empty buffer + while (!Serial.available()); // wait for data + // The fifo buffer has definatly overflowed but we can still get the latest packt!!! + if (!mpu.GetCurrentFIFOPacket(fifoBuffer, packetSize)) { // returns 0 if nothing could be revovered or we asked for a packet in less than 10ms from the last request + Serial.print("We Failed to get a good packet of data from the MPU6050"); + return ; // nothing to give to the program so return. This should never happen unless there is other issues involving communication. + } + + // display Euler angles in degrees + mpu.dmpGetQuaternion(&q, fifoBuffer); + mpu.dmpGetGravity(&gravity, &q); + mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); + Serial.print("ypr\t"); + Serial.print(ypr[0] * 180 / M_PI); + Serial.print("\t"); + Serial.print(ypr[1] * 180 / M_PI); + Serial.print("\t"); + Serial.print(ypr[2] * 180 / M_PI); + /* + mpu.dmpGetAccel(&aa, fifoBuffer); + Serial.print("\tRaw Accl XYZ\t"); + Serial.print(aa.x); + Serial.print("\t"); + Serial.print(aa.y); + Serial.print("\t"); + Serial.print(aa.z); + mpu.dmpGetGyro(&gy, fifoBuffer); + Serial.print("\tRaw Gyro XYZ\t"); + Serial.print(gy.x); + Serial.print("\t"); + Serial.print(gy.y); + Serial.print("\t"); + Serial.print(gy.z); + */ + Serial.println(); + // blink LED to indicate activity + blinkState = !blinkState; + digitalWrite(LED_PIN, blinkState); + +} From 6f3b38ebe0f200c571a23a86ce48b7b683000868 Mon Sep 17 00:00:00 2001 From: Simranjit Marok <43681967+SimranMarok@users.noreply.github.com> Date: Sat, 14 Dec 2019 09:05:30 -0500 Subject: [PATCH 235/335] I2CDEV_BUILTIN_FASTWIRE is now fixed Operations done on "intermediate" array in loop were in conflict with its size. --- Arduino/I2Cdev/I2Cdev.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Arduino/I2Cdev/I2Cdev.cpp b/Arduino/I2Cdev/I2Cdev.cpp index a22474dd..95adb404 100644 --- a/Arduino/I2Cdev/I2Cdev.cpp +++ b/Arduino/I2Cdev/I2Cdev.cpp @@ -448,8 +448,8 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 // Fastwire library // no loop required for fastwire - uint16_t intermediate[(uint8_t)length]; - uint8_t status = Fastwire::readBuf(devAddr << 1, regAddr, (uint8_t *)intermediate, (uint8_t)(length * 2)); + uint8_t intermediate[(uint8_t)length*2]; + uint8_t status = Fastwire::readBuf(devAddr << 1, regAddr, intermediate, (uint8_t)(length * 2)); if (status == 0) { count = length; // success for (uint8_t i = 0; i < length; i++) { From 38d814650aac4ed25756b33faddbbd9cfdcb591b Mon Sep 17 00:00:00 2001 From: paynterf Date: Mon, 16 Dec 2019 09:41:41 -0500 Subject: [PATCH 236/335] Added Teensy3.x Wire library section --- Arduino/I2Cdev/I2Cdev.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Arduino/I2Cdev/I2Cdev.h b/Arduino/I2Cdev/I2Cdev.h index 0bff39ef..4d30e24c 100644 --- a/Arduino/I2Cdev/I2Cdev.h +++ b/Arduino/I2Cdev/I2Cdev.h @@ -52,6 +52,7 @@ THE SOFTWARE. // ----------------------------------------------------------------------------- #ifndef I2CDEV_IMPLEMENTATION #define I2CDEV_IMPLEMENTATION I2CDEV_ARDUINO_WIRE +//#define I2CDEV_IMPLEMENTATION I2CDEV_TEENSY_3X_WIRE //#define I2CDEV_IMPLEMENTATION I2CDEV_BUILTIN_SBWIRE //#define I2CDEV_IMPLEMENTATION I2CDEV_BUILTIN_FASTWIRE #endif // I2CDEV_IMPLEMENTATION @@ -83,6 +84,8 @@ THE SOFTWARE. #endif #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE #include + #if I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE + #include #endif #if I2CDEV_IMPLEMENTATION == I2CDEV_I2CMASTER_LIBRARY #include From 97f863e5bf87f48d3fcc7258d5caa5fc9004e6ce Mon Sep 17 00:00:00 2001 From: paynterf Date: Mon, 16 Dec 2019 09:52:46 -0500 Subject: [PATCH 237/335] Fixed typo --- Arduino/I2Cdev/I2Cdev.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Arduino/I2Cdev/I2Cdev.h b/Arduino/I2Cdev/I2Cdev.h index 4d30e24c..4e4d688b 100644 --- a/Arduino/I2Cdev/I2Cdev.h +++ b/Arduino/I2Cdev/I2Cdev.h @@ -84,6 +84,7 @@ THE SOFTWARE. #endif #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE #include + #endif #if I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE #include #endif From a2837e0d66745df9d9b374df41a067a44d490709 Mon Sep 17 00:00:00 2001 From: Jeff Harding Date: Sun, 19 Jan 2020 00:47:53 -0500 Subject: [PATCH 238/335] Complete support for Teensy 3.x --- Arduino/I2Cdev/I2Cdev.cpp | 40 ++++++++++++++++++++++----------------- Arduino/I2Cdev/I2Cdev.h | 2 ++ 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/Arduino/I2Cdev/I2Cdev.cpp b/Arduino/I2Cdev/I2Cdev.cpp index a22474dd..44c5870d 100644 --- a/Arduino/I2Cdev/I2Cdev.cpp +++ b/Arduino/I2Cdev/I2Cdev.cpp @@ -222,7 +222,7 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 int8_t count = 0; uint32_t t1 = millis(); - #if (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE) + #if (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE) #if (ARDUINO < 100) // Arduino v00xx (before v1.0), Wire library @@ -342,7 +342,7 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 int8_t count = 0; uint32_t t1 = millis(); -#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE +#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE #if (ARDUINO < 100) // Arduino v00xx (before v1.0), Wire library @@ -599,8 +599,9 @@ bool I2Cdev::writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_ #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) Wire.beginTransmission(devAddr); Wire.send((uint8_t) regAddr); // send address - #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100 \ - || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) + #elif ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) \ + || (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) \ + || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE) Wire.beginTransmission(devAddr); Wire.write((uint8_t) regAddr); // send address #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) @@ -614,8 +615,9 @@ bool I2Cdev::writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_ #endif #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) Wire.send((uint8_t) data[i]); - #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100 \ - || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) + #elif ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) \ + || (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) \ + || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE) Wire.write((uint8_t) data[i]); #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) Fastwire::write((uint8_t) data[i]); @@ -623,9 +625,10 @@ bool I2Cdev::writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_ } #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) Wire.endTransmission(); - #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100 \ - || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) - status = Wire.endTransmission(); + #elif ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) \ + || (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) \ + || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE) + status = Wire.endTransmission(); #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) Fastwire::stop(); //status = Fastwire::endTransmission(); @@ -657,9 +660,10 @@ bool I2Cdev::writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16 #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) Wire.beginTransmission(devAddr); Wire.send(regAddr); // send address - #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100 \ - || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) - Wire.beginTransmission(devAddr); + #elif ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) \ + || (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) \ + || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE) + Wire.beginTransmission(devAddr); Wire.write(regAddr); // send address #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) Fastwire::beginTransmission(devAddr); @@ -673,8 +677,9 @@ bool I2Cdev::writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16 #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) Wire.send((uint8_t)(data[i] >> 8)); // send MSB Wire.send((uint8_t)data[i]); // send LSB - #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100 \ - || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) + #elif ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) \ + || (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) \ + || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE) Wire.write((uint8_t)(data[i] >> 8)); // send MSB Wire.write((uint8_t)data[i]); // send LSB #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) @@ -685,9 +690,10 @@ bool I2Cdev::writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16 } #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) Wire.endTransmission(); - #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100 \ - || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) - status = Wire.endTransmission(); + #elif ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) \ + || (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) \ + || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE) + status = Wire.endTransmission(); #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) Fastwire::stop(); //status = Fastwire::endTransmission(); diff --git a/Arduino/I2Cdev/I2Cdev.h b/Arduino/I2Cdev/I2Cdev.h index 4e4d688b..682eea35 100644 --- a/Arduino/I2Cdev/I2Cdev.h +++ b/Arduino/I2Cdev/I2Cdev.h @@ -3,6 +3,7 @@ // 2013-06-05 by Jeff Rowberg // // Changelog: +// 2020-01-20 - hardija : complete support for Teensy 3.x // 2015-10-30 - simondlevy : support i2c_t3 for Teensy3.1 // 2013-05-06 - add Francesco Ferrara's Fastwire v0.24 implementation with small modifications // 2013-05-05 - fix issue with writing bit values to words (Sasquatch/Farzanegan) @@ -70,6 +71,7 @@ THE SOFTWARE. #define I2CDEV_BUILTIN_FASTWIRE 3 // FastWire object from Francesco Ferrara's project #define I2CDEV_I2CMASTER_LIBRARY 4 // I2C object from DSSCircuits I2C-Master Library at https://github.com/DSSCircuits/I2C-Master-Library #define I2CDEV_BUILTIN_SBWIRE 5 // I2C object from Shuning (Steve) Bian's SBWire Library at https://github.com/freespace/SBWire +#define I2CDEV_TEENSY_3X_WIRE 6 // Teensy 3.x support using i2c_t3 library // ----------------------------------------------------------------------------- // Arduino-style "Serial.print" debug constant (uncomment to enable) From b17e680eef392fd6e7e1d2614b27b6b45e8e82c9 Mon Sep 17 00:00:00 2001 From: Jeff Harding Date: Sun, 19 Jan 2020 00:52:43 -0500 Subject: [PATCH 239/335] Convert tabs to spaces --- Arduino/I2Cdev/I2Cdev.cpp | 26 +++++++++++++------------- Arduino/I2Cdev/I2Cdev.h | 6 +++--- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Arduino/I2Cdev/I2Cdev.cpp b/Arduino/I2Cdev/I2Cdev.cpp index 44c5870d..de708dbf 100644 --- a/Arduino/I2Cdev/I2Cdev.cpp +++ b/Arduino/I2Cdev/I2Cdev.cpp @@ -599,8 +599,8 @@ bool I2Cdev::writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_ #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) Wire.beginTransmission(devAddr); Wire.send((uint8_t) regAddr); // send address - #elif ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) \ - || (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) \ + #elif ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) \ + || (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) \ || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE) Wire.beginTransmission(devAddr); Wire.write((uint8_t) regAddr); // send address @@ -618,17 +618,17 @@ bool I2Cdev::writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_ #elif ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) \ || (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) \ || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE) - Wire.write((uint8_t) data[i]); + Wire.write((uint8_t) data[i]); #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) Fastwire::write((uint8_t) data[i]); #endif } #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) Wire.endTransmission(); - #elif ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) \ - || (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) \ + #elif ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) \ + || (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) \ || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE) - status = Wire.endTransmission(); + status = Wire.endTransmission(); #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) Fastwire::stop(); //status = Fastwire::endTransmission(); @@ -660,10 +660,10 @@ bool I2Cdev::writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16 #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) Wire.beginTransmission(devAddr); Wire.send(regAddr); // send address - #elif ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) \ - || (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) \ + #elif ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) \ + || (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) \ || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE) - Wire.beginTransmission(devAddr); + Wire.beginTransmission(devAddr); Wire.write(regAddr); // send address #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) Fastwire::beginTransmission(devAddr); @@ -680,7 +680,7 @@ bool I2Cdev::writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16 #elif ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) \ || (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) \ || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE) - Wire.write((uint8_t)(data[i] >> 8)); // send MSB + Wire.write((uint8_t)(data[i] >> 8)); // send MSB Wire.write((uint8_t)data[i]); // send LSB #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) Fastwire::write((uint8_t)(data[i] >> 8)); // send MSB @@ -690,10 +690,10 @@ bool I2Cdev::writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16 } #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) Wire.endTransmission(); - #elif ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) \ - || (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) \ + #elif ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) \ + || (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) \ || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE) - status = Wire.endTransmission(); + status = Wire.endTransmission(); #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) Fastwire::stop(); //status = Fastwire::endTransmission(); diff --git a/Arduino/I2Cdev/I2Cdev.h b/Arduino/I2Cdev/I2Cdev.h index 682eea35..60c31950 100644 --- a/Arduino/I2Cdev/I2Cdev.h +++ b/Arduino/I2Cdev/I2Cdev.h @@ -93,9 +93,9 @@ THE SOFTWARE. #if I2CDEV_IMPLEMENTATION == I2CDEV_I2CMASTER_LIBRARY #include #endif - #if I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE - #include "SBWire.h" - #endif + #if I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE + #include "SBWire.h" + #endif #endif #ifdef SPARK From bed91df6018c4b6a99315a432a83fb284aee106a Mon Sep 17 00:00:00 2001 From: Homer Creutz Date: Tue, 21 Jan 2020 18:51:01 -0700 Subject: [PATCH 240/335] Added a single functrion to handle gathering the latest packet from the DMP generated FIFO Buffer The Added dmpGetCurrentFIFOPacket function: - Handles overflow and all other conditions to retrieve the latest packes in the most efficient way. - This will work with or without interrupt triggering and - All blocking code has no affect on the results as the latest packet is still retrieved after any and all delays no matter how long. - This has been tested over the past several months without any further modifications and should be ready for prime time. The example code has been modified and now uses this function as it is more efficient and more reliable than the current process. ToDo Test the function with ESP32 for the ESPWiFi sketch. and make changes in that example which I believe this would seamlessly improve that sketch once tested. ZHomeSlice --- Arduino/MPU6050/MPU6050.h | 1 + Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h | 36 ++ .../MPU6050/MPU6050_6Axis_MotionApps_V6_12.h | 36 ++ .../MPU6050_DMP6/MPU6050_DMP6.ino | 345 ++++++++++++++++ .../MPU6050_DMP6_using_DMP_V6.12.ino | 368 ++++++++++++++++++ 5 files changed, 786 insertions(+) create mode 100644 Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6/MPU6050_DMP6.ino create mode 100644 Arduino/MPU6050/examples/MPU6050_DMP6_using_DMP_V6.12/MPU6050_DMP6_using_DMP_V6.12/MPU6050_DMP6_using_DMP_V6.12.ino diff --git a/Arduino/MPU6050/MPU6050.h b/Arduino/MPU6050/MPU6050.h index 02643f68..a236a9c9 100644 --- a/Arduino/MPU6050/MPU6050.h +++ b/Arduino/MPU6050/MPU6050.h @@ -927,6 +927,7 @@ class MPU6050 { uint32_t dmpGetAccelSumOfSquare(); void dmpOverrideQuaternion(long *q); uint16_t dmpGetFIFOPacketSize(); + uint8_t dmpGetCurrentFIFOPacket(uint8_t *data); // overflow proof #endif // special methods for MotionApps 4.1 implementation diff --git a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h index f15ebc69..72b7a293 100644 --- a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h +++ b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h @@ -612,4 +612,40 @@ uint16_t MPU6050::dmpGetFIFOPacketSize() { return dmpPacketSize; } + + +uint8_t MPU6050::dmpGetCurrentFIFOPacket(uint8_t *data) { // overflow proof + int16_t fifoC; + // This section of code is for when we allowed more than 1 packet to be acquired + uint8_t length; + length = dmpGetFIFOPacketSize(); + uint32_t BreakTimer = micros(); + do { + if ((fifoC = getFIFOCount()) > length) { + + if (fifoC > 200) { // if you waited to get the FIFO buffer to > 200 bytes it will take longer to get the last packet in the FIFO Buffer than it will take to reset the buffer and wait for the next to arrive + resetFIFO(); // Fixes any overflow corruption + fifoC = 0; + while (!(fifoC = getFIFOCount()) && ((micros() - BreakTimer) <= (11000))); // Get Next New Packet + } else { //We have more than 1 packet but less than 200 bytes of data in the FIFO Buffer + uint8_t Trash[BUFFER_LENGTH]; + while (fifoC = getFIFOCount() > length) { // Test each time just in case the MPU is writing to the FIFO Buffer + fifoC = fifoC - length; // Save the last packet + uint16_t RemoveBytes; + while (fifoC) { // fifo count will reach zero so this is safe + RemoveBytes = min((int)fifoC, BUFFER_LENGTH); // Buffer Length is different than the packet length this will efficiently clear the buffer + getFIFOBytes(Trash, (uint8_t)RemoveBytes); + fifoC -= RemoveBytes; + } + } + } + } + if (!fifoC) return 0; // Called too early no data or we timed out after FIFO Reset + // We have 1 packet + if ((micros() - BreakTimer) > (11000)) return 0; + } while (fifoC != length); + getFIFOBytes(data, length); //Get 1 packet + return 1; +} + #endif /* _MPU6050_6AXIS_MOTIONAPPS20_H_ */ diff --git a/Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h b/Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h index 8e302d02..903611cf 100644 --- a/Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h +++ b/Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h @@ -612,4 +612,40 @@ uint16_t MPU6050::dmpGetFIFOPacketSize() { return dmpPacketSize; } + + +uint8_t MPU6050::dmpGetCurrentFIFOPacket(uint8_t *data) { // overflow proof + int16_t fifoC; + // This section of code is for when we allowed more than 1 packet to be acquired + uint8_t length; + length = dmpGetFIFOPacketSize(); + uint32_t BreakTimer = micros(); + do { + if ((fifoC = getFIFOCount()) > length) { + + if (fifoC > 200) { // if you waited to get the FIFO buffer to > 200 bytes it will take longer to get the last packet in the FIFO Buffer than it will take to reset the buffer and wait for the next to arrive + resetFIFO(); // Fixes any overflow corruption + fifoC = 0; + while (!(fifoC = getFIFOCount()) && ((micros() - BreakTimer) <= (11000))); // Get Next New Packet + } else { //We have more than 1 packet but less than 200 bytes of data in the FIFO Buffer + uint8_t Trash[BUFFER_LENGTH]; + while (fifoC = getFIFOCount() > length) { // Test each time just in case the MPU is writing to the FIFO Buffer + fifoC = fifoC - length; // Save the last packet + uint16_t RemoveBytes; + while (fifoC) { // fifo count will reach zero so this is safe + RemoveBytes = min((int)fifoC, BUFFER_LENGTH); // Buffer Length is different than the packet length this will efficiently clear the buffer + getFIFOBytes(Trash, (uint8_t)RemoveBytes); + fifoC -= RemoveBytes; + } + } + } + } + if (!fifoC) return 0; // Called too early no data or we timed out after FIFO Reset + // We have 1 packet + if ((micros() - BreakTimer) > (11000)) return 0; + } while (fifoC != length); + getFIFOBytes(data, length); //Get 1 packet + return 1; +} + #endif /* _MPU6050_6AXIS_MOTIONAPPS20_H_ */ diff --git a/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6/MPU6050_DMP6.ino b/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6/MPU6050_DMP6.ino new file mode 100644 index 00000000..3ebe2ee6 --- /dev/null +++ b/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6/MPU6050_DMP6.ino @@ -0,0 +1,345 @@ +// I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class using DMP (MotionApps v2.0) +// 6/21/2012 by Jeff Rowberg +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// 2019-07-08 - Added Auto Calibration and offset generator +// - and altered FIFO retrieval sequence to avoid using blocking code +// 2016-04-18 - Eliminated a potential infinite loop +// 2013-05-08 - added seamless Fastwire support +// - added note about gyro calibration +// 2012-06-21 - added note about Arduino 1.0.1 + Leonardo compatibility error +// 2012-06-20 - improved FIFO overflow handling and simplified read process +// 2012-06-19 - completely rearranged DMP initialization code and simplification +// 2012-06-13 - pull gyro and accel data from FIFO packet instead of reading directly +// 2012-06-09 - fix broken FIFO read sequence and change interrupt detection to RISING +// 2012-06-05 - add gravity-compensated initial reference frame acceleration output +// - add 3D math helper file to DMP6 example sketch +// - add Euler output and Yaw/Pitch/Roll output formats +// 2012-06-04 - remove accel offset clearing for better results (thanks Sungon Lee) +// 2012-06-01 - fixed gyro sensitivity to be 2000 deg/sec instead of 250 +// 2012-05-30 - basic DMP initialization working + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2012 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +// I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files +// for both classes must be in the include path of your project +#include "I2Cdev.h" + +#include "MPU6050_6Axis_MotionApps20.h" +//#include "MPU6050.h" // not necessary if using MotionApps include file + +// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation +// is used in I2Cdev.h +#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE + #include "Wire.h" +#endif + +// class default I2C address is 0x68 +// specific I2C addresses may be passed as a parameter here +// AD0 low = 0x68 (default for SparkFun breakout and InvenSense evaluation board) +// AD0 high = 0x69 +MPU6050 mpu; +//MPU6050 mpu(0x69); // <-- use for AD0 high + +/* ========================================================================= + NOTE: In addition to connection 3.3v, GND, SDA, and SCL, this sketch + depends on the MPU-6050's INT pin being connected to the Arduino's + external interrupt #0 pin. On the Arduino Uno and Mega 2560, this is + digital I/O pin 2. + * ========================================================================= */ + +/* ========================================================================= + NOTE: Arduino v1.0.1 with the Leonardo board generates a compile error + when using Serial.write(buf, len). The Teapot output uses this method. + The solution requires a modification to the Arduino USBAPI.h file, which + is fortunately simple, but annoying. This will be fixed in the next IDE + release. For more info, see these links: + + http://arduino.cc/forum/index.php/topic,109987.0.html + http://code.google.com/p/arduino/issues/detail?id=958 + * ========================================================================= */ + + + +// uncomment "OUTPUT_READABLE_QUATERNION" if you want to see the actual +// quaternion components in a [w, x, y, z] format (not best for parsing +// on a remote host such as Processing or something though) +//#define OUTPUT_READABLE_QUATERNION + +// uncomment "OUTPUT_READABLE_EULER" if you want to see Euler angles +// (in degrees) calculated from the quaternions coming from the FIFO. +// Note that Euler angles suffer from gimbal lock (for more info, see +// http://en.wikipedia.org/wiki/Gimbal_lock) +//#define OUTPUT_READABLE_EULER + +// uncomment "OUTPUT_READABLE_YAWPITCHROLL" if you want to see the yaw/ +// pitch/roll angles (in degrees) calculated from the quaternions coming +// from the FIFO. Note this also requires gravity vector calculations. +// Also note that yaw/pitch/roll angles suffer from gimbal lock (for +// more info, see: http://en.wikipedia.org/wiki/Gimbal_lock) +#define OUTPUT_READABLE_YAWPITCHROLL + +// uncomment "OUTPUT_READABLE_REALACCEL" if you want to see acceleration +// components with gravity removed. This acceleration reference frame is +// not compensated for orientation, so +X is always +X according to the +// sensor, just without the effects of gravity. If you want acceleration +// compensated for orientation, us OUTPUT_READABLE_WORLDACCEL instead. +//#define OUTPUT_READABLE_REALACCEL + +// uncomment "OUTPUT_READABLE_WORLDACCEL" if you want to see acceleration +// components with gravity removed and adjusted for the world frame of +// reference (yaw is relative to initial orientation, since no magnetometer +// is present in this case). Could be quite handy in some cases. +//#define OUTPUT_READABLE_WORLDACCEL + +// uncomment "OUTPUT_TEAPOT" if you want output that matches the +// format used for the InvenSense teapot demo +//#define OUTPUT_TEAPOT + + + +#define INTERRUPT_PIN 2 // use pin 2 on Arduino Uno & most boards +#define LED_PIN 13 // (Arduino is 13, Teensy is 11, Teensy++ is 6) +bool blinkState = false; + +// MPU control/status vars +bool dmpReady = false; // set true if DMP init was successful +uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU +uint8_t devStatus; // return status after each device operation (0 = success, !0 = error) +uint16_t packetSize; // expected DMP packet size (default is 42 bytes) +uint16_t fifoCount; // count of all bytes currently in FIFO +uint8_t fifoBuffer[64]; // FIFO storage buffer + +// orientation/motion vars +Quaternion q; // [w, x, y, z] quaternion container +VectorInt16 aa; // [x, y, z] accel sensor measurements +VectorInt16 aaReal; // [x, y, z] gravity-free accel sensor measurements +VectorInt16 aaWorld; // [x, y, z] world-frame accel sensor measurements +VectorFloat gravity; // [x, y, z] gravity vector +float euler[3]; // [psi, theta, phi] Euler angle container +float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector + +// packet structure for InvenSense teapot demo +uint8_t teapotPacket[14] = { '$', 0x02, 0,0, 0,0, 0,0, 0,0, 0x00, 0x00, '\r', '\n' }; + + + +// ================================================================ +// === INTERRUPT DETECTION ROUTINE === +// ================================================================ + +volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high +void dmpDataReady() { + mpuInterrupt = true; +} + + + +// ================================================================ +// === INITIAL SETUP === +// ================================================================ + +void setup() { + // join I2C bus (I2Cdev library doesn't do this automatically) + #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE + Wire.begin(); + Wire.setClock(400000); // 400kHz I2C clock. Comment this line if having compilation difficulties + #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE + Fastwire::setup(400, true); + #endif + + // initialize serial communication + // (115200 chosen because it is required for Teapot Demo output, but it's + // really up to you depending on your project) + Serial.begin(115200); + while (!Serial); // wait for Leonardo enumeration, others continue immediately + + // NOTE: 8MHz or slower host processors, like the Teensy @ 3.3V or Arduino + // Pro Mini running at 3.3V, cannot handle this baud rate reliably due to + // the baud timing being too misaligned with processor ticks. You must use + // 38400 or slower in these cases, or use some kind of external separate + // crystal solution for the UART timer. + + // initialize device + Serial.println(F("Initializing I2C devices...")); + mpu.initialize(); + pinMode(INTERRUPT_PIN, INPUT); + + // verify connection + Serial.println(F("Testing device connections...")); + Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed")); + + // wait for ready + Serial.println(F("\nSend any character to begin DMP programming and demo: ")); + while (Serial.available() && Serial.read()); // empty buffer + while (!Serial.available()); // wait for data + while (Serial.available() && Serial.read()); // empty buffer again + + // load and configure the DMP + Serial.println(F("Initializing DMP...")); + devStatus = mpu.dmpInitialize(); + + // supply your own gyro offsets here, scaled for min sensitivity + mpu.setXGyroOffset(220); + mpu.setYGyroOffset(76); + mpu.setZGyroOffset(-85); + mpu.setZAccelOffset(1788); // 1688 factory default for my test chip + + // make sure it worked (returns 0 if so) + if (devStatus == 0) { + // Calibration Time: generate offsets and calibrate our MPU6050 + mpu.CalibrateAccel(6); + mpu.CalibrateGyro(6); + mpu.PrintActiveOffsets(); + // turn on the DMP, now that it's ready + Serial.println(F("Enabling DMP...")); + mpu.setDMPEnabled(true); + + // enable Arduino interrupt detection + Serial.print(F("Enabling interrupt detection (Arduino external interrupt ")); + Serial.print(digitalPinToInterrupt(INTERRUPT_PIN)); + Serial.println(F(")...")); + attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), dmpDataReady, RISING); + mpuIntStatus = mpu.getIntStatus(); + + // set our DMP Ready flag so the main loop() function knows it's okay to use it + Serial.println(F("DMP ready! Waiting for first interrupt...")); + dmpReady = true; + + // get expected DMP packet size for later comparison + packetSize = mpu.dmpGetFIFOPacketSize(); + } else { + // ERROR! + // 1 = initial memory load failed + // 2 = DMP configuration updates failed + // (if it's going to break, usually the code will be 1) + Serial.print(F("DMP Initialization failed (code ")); + Serial.print(devStatus); + Serial.println(F(")")); + } + + // configure LED for output + pinMode(LED_PIN, OUTPUT); +} + + + +// ================================================================ +// === MAIN PROGRAM LOOP === +// ================================================================ + +void loop() { + // if programming failed, don't try to do anything + if (!dmpReady) return; + // read a packet from FIFO + if (mpu.dmpGetCurrentFIFOPacket(fifoBuffer)) { // Get the Latest packet + #ifdef OUTPUT_READABLE_QUATERNION + // display quaternion values in easy matrix form: w x y z + mpu.dmpGetQuaternion(&q, fifoBuffer); + Serial.print("quat\t"); + Serial.print(q.w); + Serial.print("\t"); + Serial.print(q.x); + Serial.print("\t"); + Serial.print(q.y); + Serial.print("\t"); + Serial.println(q.z); + #endif + + #ifdef OUTPUT_READABLE_EULER + // display Euler angles in degrees + mpu.dmpGetQuaternion(&q, fifoBuffer); + mpu.dmpGetEuler(euler, &q); + Serial.print("euler\t"); + Serial.print(euler[0] * 180/M_PI); + Serial.print("\t"); + Serial.print(euler[1] * 180/M_PI); + Serial.print("\t"); + Serial.println(euler[2] * 180/M_PI); + #endif + + #ifdef OUTPUT_READABLE_YAWPITCHROLL + // display Euler angles in degrees + mpu.dmpGetQuaternion(&q, fifoBuffer); + mpu.dmpGetGravity(&gravity, &q); + mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); + Serial.print("ypr\t"); + Serial.print(ypr[0] * 180/M_PI); + Serial.print("\t"); + Serial.print(ypr[1] * 180/M_PI); + Serial.print("\t"); + Serial.println(ypr[2] * 180/M_PI); + #endif + + #ifdef OUTPUT_READABLE_REALACCEL + // display real acceleration, adjusted to remove gravity + mpu.dmpGetQuaternion(&q, fifoBuffer); + mpu.dmpGetAccel(&aa, fifoBuffer); + mpu.dmpGetGravity(&gravity, &q); + mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity); + Serial.print("areal\t"); + Serial.print(aaReal.x); + Serial.print("\t"); + Serial.print(aaReal.y); + Serial.print("\t"); + Serial.println(aaReal.z); + #endif + + #ifdef OUTPUT_READABLE_WORLDACCEL + // display initial world-frame acceleration, adjusted to remove gravity + // and rotated based on known orientation from quaternion + mpu.dmpGetQuaternion(&q, fifoBuffer); + mpu.dmpGetAccel(&aa, fifoBuffer); + mpu.dmpGetGravity(&gravity, &q); + mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity); + mpu.dmpGetLinearAccelInWorld(&aaWorld, &aaReal, &q); + Serial.print("aworld\t"); + Serial.print(aaWorld.x); + Serial.print("\t"); + Serial.print(aaWorld.y); + Serial.print("\t"); + Serial.println(aaWorld.z); + #endif + + #ifdef OUTPUT_TEAPOT + // display quaternion values in InvenSense Teapot demo format: + teapotPacket[2] = fifoBuffer[0]; + teapotPacket[3] = fifoBuffer[1]; + teapotPacket[4] = fifoBuffer[4]; + teapotPacket[5] = fifoBuffer[5]; + teapotPacket[6] = fifoBuffer[8]; + teapotPacket[7] = fifoBuffer[9]; + teapotPacket[8] = fifoBuffer[12]; + teapotPacket[9] = fifoBuffer[13]; + Serial.write(teapotPacket, 14); + teapotPacket[11]++; // packetCount, loops at 0xFF on purpose + #endif + + // blink LED to indicate activity + blinkState = !blinkState; + digitalWrite(LED_PIN, blinkState); + } +} diff --git a/Arduino/MPU6050/examples/MPU6050_DMP6_using_DMP_V6.12/MPU6050_DMP6_using_DMP_V6.12/MPU6050_DMP6_using_DMP_V6.12.ino b/Arduino/MPU6050/examples/MPU6050_DMP6_using_DMP_V6.12/MPU6050_DMP6_using_DMP_V6.12/MPU6050_DMP6_using_DMP_V6.12.ino new file mode 100644 index 00000000..9a87db5c --- /dev/null +++ b/Arduino/MPU6050/examples/MPU6050_DMP6_using_DMP_V6.12/MPU6050_DMP6_using_DMP_V6.12/MPU6050_DMP6_using_DMP_V6.12.ino @@ -0,0 +1,368 @@ +// I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class using DMP (MotionApps v6.12) +// 6/21/2012 by Jeff Rowberg +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// 2019-07-10 - Uses the new version of the DMP Firmware V6.12 +// - Note: I believe the Teapot demo is broken with this versin as +// - the fifo buffer structure has changed +// 2016-04-18 - Eliminated a potential infinite loop +// 2013-05-08 - added seamless Fastwire support +// - added note about gyro calibration +// 2012-06-21 - added note about Arduino 1.0.1 + Leonardo compatibility error +// 2012-06-20 - improved FIFO overflow handling and simplified read process +// 2012-06-19 - completely rearranged DMP initialization code and simplification +// 2012-06-13 - pull gyro and accel data from FIFO packet instead of reading directly +// 2012-06-09 - fix broken FIFO read sequence and change interrupt detection to RISING +// 2012-06-05 - add gravity-compensated initial reference frame acceleration output +// - add 3D math helper file to DMP6 example sketch +// - add Euler output and Yaw/Pitch/Roll output formats +// 2012-06-04 - remove accel offset clearing for better results (thanks Sungon Lee) +// 2012-06-01 - fixed gyro sensitivity to be 2000 deg/sec instead of 250 +// 2012-05-30 - basic DMP initialization working + +/* ============================================ + I2Cdev device library code is placed under the MIT license + Copyright (c) 2012 Jeff Rowberg + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + =============================================== +*/ + +// I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files +// for both classes must be in the include path of your project +#include "I2Cdev.h" + +#include "MPU6050_6Axis_MotionApps_V6_12.h" +//#include "MPU6050.h" // not necessary if using MotionApps include file + +// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation +// is used in I2Cdev.h +#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE +#include "Wire.h" +#endif + +// class default I2C address is 0x68 +// specific I2C addresses may be passed as a parameter here +// AD0 low = 0x68 (default for SparkFun breakout and InvenSense evaluation board) +// AD0 high = 0x69 +MPU6050 mpu; +//MPU6050 mpu(0x69); // <-- use for AD0 high + +/* ========================================================================= + NOTE: In addition to connection 3.3v, GND, SDA, and SCL, this sketch + depends on the MPU-6050's INT pin being connected to the Arduino's + external interrupt #0 pin. On the Arduino Uno and Mega 2560, this is + digital I/O pin 2. + ========================================================================= */ + +/* ========================================================================= + NOTE: Arduino v1.0.1 with the Leonardo board generates a compile error + when using Serial.write(buf, len). The Teapot output uses this method. + The solution requires a modification to the Arduino USBAPI.h file, which + is fortunately simple, but annoying. This will be fixed in the next IDE + release. For more info, see these links: + + http://arduino.cc/forum/index.php/topic,109987.0.html + http://code.google.com/p/arduino/issues/detail?id=958 + ========================================================================= */ + + + +// uncomment "OUTPUT_READABLE_QUATERNION" if you want to see the actual +// quaternion components in a [w, x, y, z] format (not best for parsing +// on a remote host such as Processing or something though) +//#define OUTPUT_READABLE_QUATERNION + +// uncomment "OUTPUT_READABLE_EULER" if you want to see Euler angles +// (in degrees) calculated from the quaternions coming from the FIFO. +// Note that Euler angles suffer from gimbal lock (for more info, see +// http://en.wikipedia.org/wiki/Gimbal_lock) +//#define OUTPUT_READABLE_EULER + +// uncomment "OUTPUT_READABLE_YAWPITCHROLL" if you want to see the yaw/ +// pitch/roll angles (in degrees) calculated from the quaternions coming +// from the FIFO. Note this also requires gravity vector calculations. +// Also note that yaw/pitch/roll angles suffer from gimbal lock (for +// more info, see: http://en.wikipedia.org/wiki/Gimbal_lock) +#define OUTPUT_READABLE_YAWPITCHROLL + +// uncomment "OUTPUT_READABLE_REALACCEL" if you want to see acceleration +// components with gravity removed. This acceleration reference frame is +// not compensated for orientation, so +X is always +X according to the +// sensor, just without the effects of gravity. If you want acceleration +// compensated for orientation, us OUTPUT_READABLE_WORLDACCEL instead. +//#define OUTPUT_READABLE_REALACCEL + +// uncomment "OUTPUT_READABLE_WORLDACCEL" if you want to see acceleration +// components with gravity removed and adjusted for the world frame of +// reference (yaw is relative to initial orientation, since no magnetometer +// is present in this case). Could be quite handy in some cases. +//#define OUTPUT_READABLE_WORLDACCEL + +// uncomment "OUTPUT_TEAPOT" if you want output that matches the +// format used for the InvenSense teapot demo +//#define OUTPUT_TEAPOT + + + +#define INTERRUPT_PIN 2 // use pin 2 on Arduino Uno & most boards +#define LED_PIN 13 // (Arduino is 13, Teensy is 11, Teensy++ is 6) +bool blinkState = false; + +// MPU control/status vars +bool dmpReady = false; // set true if DMP init was successful +uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU +uint8_t devStatus; // return status after each device operation (0 = success, !0 = error) +uint16_t packetSize; // expected DMP packet size (default is 42 bytes) +uint16_t fifoCount; // count of all bytes currently in FIFO +uint8_t fifoBuffer[64]; // FIFO storage buffer + +// orientation/motion vars +Quaternion q; // [w, x, y, z] quaternion container +VectorInt16 aa; // [x, y, z] accel sensor measurements +VectorInt16 gy; // [x, y, z] gyro sensor measurements +VectorInt16 aaReal; // [x, y, z] gravity-free accel sensor measurements +VectorInt16 aaWorld; // [x, y, z] world-frame accel sensor measurements +VectorFloat gravity; // [x, y, z] gravity vector +float euler[3]; // [psi, theta, phi] Euler angle container +float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector + +// packet structure for InvenSense teapot demo +uint8_t teapotPacket[14] = { '$', 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0x00, 0x00, '\r', '\n' }; + + + +// ================================================================ +// === INTERRUPT DETECTION ROUTINE === +// ================================================================ + +volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high +void dmpDataReady() { + mpuInterrupt = true; +} + + + +// ================================================================ +// === INITIAL SETUP === +// ================================================================ + +void setup() { + // join I2C bus (I2Cdev library doesn't do this automatically) +#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE + Wire.begin(); + Wire.setClock(400000); // 400kHz I2C clock. Comment this line if having compilation difficulties +#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE + Fastwire::setup(400, true); +#endif + + // initialize serial communication + // (115200 chosen because it is required for Teapot Demo output, but it's + // really up to you depending on your project) + Serial.begin(115200); + while (!Serial); // wait for Leonardo enumeration, others continue immediately + + // NOTE: 8MHz or slower host processors, like the Teensy @ 3.3V or Arduino + // Pro Mini running at 3.3V, cannot handle this baud rate reliably due to + // the baud timing being too misaligned with processor ticks. You must use + // 38400 or slower in these cases, or use some kind of external separate + // crystal solution for the UART timer. + + // initialize device + Serial.println(F("Initializing I2C devices...")); + mpu.initialize(); + pinMode(INTERRUPT_PIN, INPUT); + + // verify connection + Serial.println(F("Testing device connections...")); + Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed")); + + // wait for ready + Serial.println(F("\nSend any character to begin DMP programming and demo: ")); + while (Serial.available() && Serial.read()); // empty buffer + while (!Serial.available()); // wait for data + while (Serial.available() && Serial.read()); // empty buffer again + + // load and configure the DMP + Serial.println(F("Initializing DMP...")); + devStatus = mpu.dmpInitialize(); + + // supply your own gyro offsets here, scaled for min sensitivity + mpu.setXGyroOffset(51); + mpu.setYGyroOffset(8); + mpu.setZGyroOffset(21); + mpu.setXAccelOffset(1150); + mpu.setYAccelOffset(-50); + mpu.setZAccelOffset(1060); + // make sure it worked (returns 0 if so) + if (devStatus == 0) { + // Calibration Time: generate offsets and calibrate our MPU6050 + mpu.CalibrateAccel(6); + mpu.CalibrateGyro(6); + Serial.println(); + mpu.PrintActiveOffsets(); + // turn on the DMP, now that it's ready + Serial.println(F("Enabling DMP...")); + mpu.setDMPEnabled(true); + + // enable Arduino interrupt detection + Serial.print(F("Enabling interrupt detection (Arduino external interrupt ")); + Serial.print(digitalPinToInterrupt(INTERRUPT_PIN)); + Serial.println(F(")...")); + attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), dmpDataReady, RISING); + mpuIntStatus = mpu.getIntStatus(); + + // set our DMP Ready flag so the main loop() function knows it's okay to use it + Serial.println(F("DMP ready! Waiting for first interrupt...")); + dmpReady = true; + + // get expected DMP packet size for later comparison + packetSize = mpu.dmpGetFIFOPacketSize(); + } else { + // ERROR! + // 1 = initial memory load failed + // 2 = DMP configuration updates failed + // (if it's going to break, usually the code will be 1) + Serial.print(F("DMP Initialization failed (code ")); + Serial.print(devStatus); + Serial.println(F(")")); + } + + // configure LED for output + pinMode(LED_PIN, OUTPUT); +} + + + +// ================================================================ +// === MAIN PROGRAM LOOP === +// ================================================================ + +void loop() { + // if programming failed, don't try to do anything + if (!dmpReady) return; + // read a packet from FIFO + if (mpu.dmpGetCurrentFIFOPacket(fifoBuffer)) { // Get the Latest packet + +#ifdef OUTPUT_READABLE_QUATERNION + // display quaternion values in easy matrix form: w x y z + mpu.dmpGetQuaternion(&q, fifoBuffer); + Serial.print("quat\t"); + Serial.print(q.w); + Serial.print("\t"); + Serial.print(q.x); + Serial.print("\t"); + Serial.print(q.y); + Serial.print("\t"); + Serial.println(q.z); +#endif + +#ifdef OUTPUT_READABLE_EULER + // display Euler angles in degrees + mpu.dmpGetQuaternion(&q, fifoBuffer); + mpu.dmpGetEuler(euler, &q); + Serial.print("euler\t"); + Serial.print(euler[0] * 180 / M_PI); + Serial.print("\t"); + Serial.print(euler[1] * 180 / M_PI); + Serial.print("\t"); + Serial.println(euler[2] * 180 / M_PI); +#endif + +#ifdef OUTPUT_READABLE_YAWPITCHROLL + // display Euler angles in degrees + mpu.dmpGetQuaternion(&q, fifoBuffer); + mpu.dmpGetGravity(&gravity, &q); + mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); + Serial.print("ypr\t"); + Serial.print(ypr[0] * 180 / M_PI); + Serial.print("\t"); + Serial.print(ypr[1] * 180 / M_PI); + Serial.print("\t"); + Serial.print(ypr[2] * 180 / M_PI); + /* + mpu.dmpGetAccel(&aa, fifoBuffer); + Serial.print("\tRaw Accl XYZ\t"); + Serial.print(aa.x); + Serial.print("\t"); + Serial.print(aa.y); + Serial.print("\t"); + Serial.print(aa.z); + mpu.dmpGetGyro(&gy, fifoBuffer); + Serial.print("\tRaw Gyro XYZ\t"); + Serial.print(gy.x); + Serial.print("\t"); + Serial.print(gy.y); + Serial.print("\t"); + Serial.print(gy.z); + */ + Serial.println(); + +#endif + +#ifdef OUTPUT_READABLE_REALACCEL + // display real acceleration, adjusted to remove gravity + mpu.dmpGetQuaternion(&q, fifoBuffer); + mpu.dmpGetAccel(&aa, fifoBuffer); + mpu.dmpGetGravity(&gravity, &q); + mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity); + Serial.print("areal\t"); + Serial.print(aaReal.x); + Serial.print("\t"); + Serial.print(aaReal.y); + Serial.print("\t"); + Serial.println(aaReal.z); +#endif + +#ifdef OUTPUT_READABLE_WORLDACCEL + // display initial world-frame acceleration, adjusted to remove gravity + // and rotated based on known orientation from quaternion + mpu.dmpGetQuaternion(&q, fifoBuffer); + mpu.dmpGetAccel(&aa, fifoBuffer); + mpu.dmpGetGravity(&gravity, &q); + mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity); + mpu.dmpGetLinearAccelInWorld(&aaWorld, &aaReal, &q); + Serial.print("aworld\t"); + Serial.print(aaWorld.x); + Serial.print("\t"); + Serial.print(aaWorld.y); + Serial.print("\t"); + Serial.println(aaWorld.z); +#endif + +#ifdef OUTPUT_TEAPOT + // display quaternion values in InvenSense Teapot demo format: + teapotPacket[2] = fifoBuffer[0]; + teapotPacket[3] = fifoBuffer[1]; + teapotPacket[4] = fifoBuffer[4]; + teapotPacket[5] = fifoBuffer[5]; + teapotPacket[6] = fifoBuffer[8]; + teapotPacket[7] = fifoBuffer[9]; + teapotPacket[8] = fifoBuffer[12]; + teapotPacket[9] = fifoBuffer[13]; + Serial.write(teapotPacket, 14); + teapotPacket[11]++; // packetCount, loops at 0xFF on purpose +#endif + + // blink LED to indicate activity + blinkState = !blinkState; + digitalWrite(LED_PIN, blinkState); + } +} From 6713bd1dd9add5c76fca404fbeeb9a3343472215 Mon Sep 17 00:00:00 2001 From: Homer Creutz Date: Tue, 21 Jan 2020 21:36:40 -0700 Subject: [PATCH 241/335] Added functrion to gathering the latest packet from the DMP FIFO Buffer The Added dmpGetCurrentFIFOPacket function: - Handles overflow and all other conditions to retrieve the latest packes in the most efficient way. - This will work with or without interrupt triggering and - All blocking code has no affect on the results as the latest packet is still retrieved after any and all delays no matter how long. - This has been tested over the past several months without any further modifications and should be ready for prime time. The example code has been modified and now uses this function as it is more efficient and more reliable than the current process. ToDo Test the function with ESP32 for the ESPWiFi sketch. and make changes in that example which I believe this would seamlessly improve that sketch once tested. ZHomeSlice2 --- Arduino/MPU6050/MPU6050.cpp | 112 +++++------------- Arduino/MPU6050/MPU6050.h | 1 - Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h | 32 +---- .../MPU6050/MPU6050_6Axis_MotionApps_V6_12.h | 32 +---- ...050_DMP6_using_DMP_V6.12_No_Interrupts.ino | 2 - 5 files changed, 31 insertions(+), 148 deletions(-) diff --git a/Arduino/MPU6050/MPU6050.cpp b/Arduino/MPU6050/MPU6050.cpp index 85826e48..68841f5f 100644 --- a/Arduino/MPU6050/MPU6050.cpp +++ b/Arduino/MPU6050/MPU6050.cpp @@ -2749,89 +2749,35 @@ void MPU6050::getFIFOBytes(uint8_t *data, uint8_t length) { * 0) when no valid data is available * ================================================================ */ int8_t MPU6050::GetCurrentFIFOPacket(uint8_t *data, uint8_t length) { // overflow proof - uint16_t fifoC; - uint8_t Error; - uint8_t Flag = 0; - uint8_t overflowed = 0; - uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU - do { - if (Error = (fifoC = getFIFOCount()) % length) { - mpuIntStatus = getIntStatus(); - if ( mpuIntStatus & _BV(MPU6050_INTERRUPT_FIFO_OFLOW_BIT)) { - getFIFOBytes(data, Error); // lets remove the overflow portion - getFIFOBytes(data, length); - overflowed = 1; - if (Error = (fifoC = getFIFOCount()) % length) { // there could be some remaining bytes to deal with that arrived after we freed up some space - getFIFOBytes(data, Error); // lets remove the overflow portion again - if ((fifoC = getFIFOCount()) % length) { - resetFIFO(); - return 0; - } - } - } - } - while(fifoC >(2*length)){ // Quickly remove all but 2 packets - getFIFOBytes(data, length); - fifoC -= length; - Flag++; - } - if (fifoC >= length){ // Get the newest and last packet - getFIFOBytes(data, length); - fifoC -= length; - Flag++; - } - } while (fifoC >= length); // always reprocess the last packet for additional data - return (overflowed ? -1:Flag); - } - -int8_t MPU6050::GetCurrentFIFOPacketTimed(uint8_t *data, uint8_t length) { // overflow proof - static unsigned long xTimer; - static int t = 10000; - static int x = 1; - if (micros() - xTimer < (t)) return 0;// This is an auto tuning routine to discover the exact time the fifo buffer is filled - uint16_t fifoC; - uint8_t Error; - uint8_t Flag = 0; - uint8_t overflowed = 0; - uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU - do { - if (Error = (fifoC = getFIFOCount()) % length) { - mpuIntStatus = getIntStatus(); - if ( mpuIntStatus & _BV(MPU6050_INTERRUPT_FIFO_OFLOW_BIT)) { - getFIFOBytes(data, Error); // lets remove the overflow portion - getFIFOBytes(data, length); - overflowed = 1; - if (Error = (fifoC = getFIFOCount()) % length) { // there could be some remaining bytes to deal with that arrived after we freed up some space - getFIFOBytes(data, Error); // lets remove the overflow portion again - if ((fifoC = getFIFOCount()) % length) { - resetFIFO(); - return 0; - } - } - } - } - if(fifoC == 0 && (fifoC = getFIFOCount())){ // no data was present above but now we have it Timing is perfect!!! - x = 0; // Lets stop moving around and changing the timing! - } - while(fifoC >(2*length)){ // Quickly remove all but 2 packets - getFIFOBytes(data, length); - fifoC -= length; - x = 1; // Something caused a delay and everything off again start searching for the sweet spot - } - if (fifoC >= length){ // Get the newest and last packet - getFIFOBytes(data, length); - Flag = 1 + overflowed; - fifoC -= length; - xTimer = micros(); - t -= x; - t = max(t,5000); // we have to limit this if there are external delays to deal with. - - }else{ - t += x; - fifoC = getFIFOCount(); // We didn't have data before but I bet we have it now!!! Lets check - } - } while (fifoC >= length); - return Flag; + int16_t fifoC; + // This section of code is for when we allowed more than 1 packet to be acquired + uint32_t BreakTimer = micros(); + do { + if ((fifoC = getFIFOCount()) > length) { + + if (fifoC > 200) { // if you waited to get the FIFO buffer to > 200 bytes it will take longer to get the last packet in the FIFO Buffer than it will take to reset the buffer and wait for the next to arrive + resetFIFO(); // Fixes any overflow corruption + fifoC = 0; + while (!(fifoC = getFIFOCount()) && ((micros() - BreakTimer) <= (11000))); // Get Next New Packet + } else { //We have more than 1 packet but less than 200 bytes of data in the FIFO Buffer + uint8_t Trash[BUFFER_LENGTH]; + while (fifoC = getFIFOCount() > length) { // Test each time just in case the MPU is writing to the FIFO Buffer + fifoC = fifoC - length; // Save the last packet + uint16_t RemoveBytes; + while (fifoC) { // fifo count will reach zero so this is safe + RemoveBytes = min((int)fifoC, BUFFER_LENGTH); // Buffer Length is different than the packet length this will efficiently clear the buffer + getFIFOBytes(Trash, (uint8_t)RemoveBytes); + fifoC -= RemoveBytes; + } + } + } + } + if (!fifoC) return 0; // Called too early no data or we timed out after FIFO Reset + // We have 1 packet + if ((micros() - BreakTimer) > (11000)) return 0; + } while (fifoC != length); + getFIFOBytes(data, length); //Get 1 packet + return 1; } diff --git a/Arduino/MPU6050/MPU6050.h b/Arduino/MPU6050/MPU6050.h index a236a9c9..4be352d2 100644 --- a/Arduino/MPU6050/MPU6050.h +++ b/Arduino/MPU6050/MPU6050.h @@ -715,7 +715,6 @@ class MPU6050 { // FIFO_R_W register uint8_t getFIFOByte(); int8_t GetCurrentFIFOPacket(uint8_t *data, uint8_t length); - int8_t GetCurrentFIFOPacketTimed(uint8_t *data, uint8_t length); void setFIFOByte(uint8_t data); void getFIFOBytes(uint8_t *data, uint8_t length); diff --git a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h index 72b7a293..badd084d 100644 --- a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h +++ b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h @@ -615,37 +615,7 @@ uint16_t MPU6050::dmpGetFIFOPacketSize() { uint8_t MPU6050::dmpGetCurrentFIFOPacket(uint8_t *data) { // overflow proof - int16_t fifoC; - // This section of code is for when we allowed more than 1 packet to be acquired - uint8_t length; - length = dmpGetFIFOPacketSize(); - uint32_t BreakTimer = micros(); - do { - if ((fifoC = getFIFOCount()) > length) { - - if (fifoC > 200) { // if you waited to get the FIFO buffer to > 200 bytes it will take longer to get the last packet in the FIFO Buffer than it will take to reset the buffer and wait for the next to arrive - resetFIFO(); // Fixes any overflow corruption - fifoC = 0; - while (!(fifoC = getFIFOCount()) && ((micros() - BreakTimer) <= (11000))); // Get Next New Packet - } else { //We have more than 1 packet but less than 200 bytes of data in the FIFO Buffer - uint8_t Trash[BUFFER_LENGTH]; - while (fifoC = getFIFOCount() > length) { // Test each time just in case the MPU is writing to the FIFO Buffer - fifoC = fifoC - length; // Save the last packet - uint16_t RemoveBytes; - while (fifoC) { // fifo count will reach zero so this is safe - RemoveBytes = min((int)fifoC, BUFFER_LENGTH); // Buffer Length is different than the packet length this will efficiently clear the buffer - getFIFOBytes(Trash, (uint8_t)RemoveBytes); - fifoC -= RemoveBytes; - } - } - } - } - if (!fifoC) return 0; // Called too early no data or we timed out after FIFO Reset - // We have 1 packet - if ((micros() - BreakTimer) > (11000)) return 0; - } while (fifoC != length); - getFIFOBytes(data, length); //Get 1 packet - return 1; + GetCurrentFIFOPacket(*data, dmpGetFIFOPacketSize()); } #endif /* _MPU6050_6AXIS_MOTIONAPPS20_H_ */ diff --git a/Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h b/Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h index 903611cf..c8c8cade 100644 --- a/Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h +++ b/Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h @@ -615,37 +615,7 @@ uint16_t MPU6050::dmpGetFIFOPacketSize() { uint8_t MPU6050::dmpGetCurrentFIFOPacket(uint8_t *data) { // overflow proof - int16_t fifoC; - // This section of code is for when we allowed more than 1 packet to be acquired - uint8_t length; - length = dmpGetFIFOPacketSize(); - uint32_t BreakTimer = micros(); - do { - if ((fifoC = getFIFOCount()) > length) { - - if (fifoC > 200) { // if you waited to get the FIFO buffer to > 200 bytes it will take longer to get the last packet in the FIFO Buffer than it will take to reset the buffer and wait for the next to arrive - resetFIFO(); // Fixes any overflow corruption - fifoC = 0; - while (!(fifoC = getFIFOCount()) && ((micros() - BreakTimer) <= (11000))); // Get Next New Packet - } else { //We have more than 1 packet but less than 200 bytes of data in the FIFO Buffer - uint8_t Trash[BUFFER_LENGTH]; - while (fifoC = getFIFOCount() > length) { // Test each time just in case the MPU is writing to the FIFO Buffer - fifoC = fifoC - length; // Save the last packet - uint16_t RemoveBytes; - while (fifoC) { // fifo count will reach zero so this is safe - RemoveBytes = min((int)fifoC, BUFFER_LENGTH); // Buffer Length is different than the packet length this will efficiently clear the buffer - getFIFOBytes(Trash, (uint8_t)RemoveBytes); - fifoC -= RemoveBytes; - } - } - } - } - if (!fifoC) return 0; // Called too early no data or we timed out after FIFO Reset - // We have 1 packet - if ((micros() - BreakTimer) > (11000)) return 0; - } while (fifoC != length); - getFIFOBytes(data, length); //Get 1 packet - return 1; + GetCurrentFIFOPacket(*data, dmpGetFIFOPacketSize()); } #endif /* _MPU6050_6AXIS_MOTIONAPPS20_H_ */ diff --git a/Arduino/MPU6050/examples/MPU6050_DMP6_using_DMP_V6.12_No_Interrupts/MPU6050_DMP6_using_DMP_V6.12_No_Interrupts.ino b/Arduino/MPU6050/examples/MPU6050_DMP6_using_DMP_V6.12_No_Interrupts/MPU6050_DMP6_using_DMP_V6.12_No_Interrupts.ino index 6a5a480b..2419d0e1 100644 --- a/Arduino/MPU6050/examples/MPU6050_DMP6_using_DMP_V6.12_No_Interrupts/MPU6050_DMP6_using_DMP_V6.12_No_Interrupts.ino +++ b/Arduino/MPU6050/examples/MPU6050_DMP6_using_DMP_V6.12_No_Interrupts/MPU6050_DMP6_using_DMP_V6.12_No_Interrupts.ino @@ -11,8 +11,6 @@ // - added note about gyro calibration // 2012-06-21 - added note about Arduino 1.0.1 + Leonardo compatibility error // 2012-06-20 - improved FIFO overflow handling and simplified read process -// 2012-06-19 - completely rearranged DMP initialization code and simplification -// 2012-06-13 - pull gyro and accel data from FIFO packet instead of reading directly // 2012-06-09 - fix broken FIFO read sequence and change interrupt detection to RISING // 2012-06-05 - add gravity-compensated initial reference frame acceleration output // - add 3D math helper file to DMP6 example sketch From 914bbcf61021ceba2c5cb124a896d442c7f6e369 Mon Sep 17 00:00:00 2001 From: Homer Creutz Date: Wed, 22 Jan 2020 00:28:45 -0700 Subject: [PATCH 242/335] Delete MPU6050_DMP6_using_DMP_V6.12_Overflow_Immune.ino --- ...0_DMP6_using_DMP_V6.12_Overflow_Immune.ino | 290 ------------------ 1 file changed, 290 deletions(-) delete mode 100644 Arduino/MPU6050/examples/MPU6050_DMP6_using_DMP_V6.12_Overflow_Immune/MPU6050_DMP6_using_DMP_V6.12_Overflow_Immune.ino diff --git a/Arduino/MPU6050/examples/MPU6050_DMP6_using_DMP_V6.12_Overflow_Immune/MPU6050_DMP6_using_DMP_V6.12_Overflow_Immune.ino b/Arduino/MPU6050/examples/MPU6050_DMP6_using_DMP_V6.12_Overflow_Immune/MPU6050_DMP6_using_DMP_V6.12_Overflow_Immune.ino deleted file mode 100644 index e507f533..00000000 --- a/Arduino/MPU6050/examples/MPU6050_DMP6_using_DMP_V6.12_Overflow_Immune/MPU6050_DMP6_using_DMP_V6.12_Overflow_Immune.ino +++ /dev/null @@ -1,290 +0,0 @@ -// I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class using DMP (MotionApps v6.12) -// 6/21/2012 by Jeff Rowberg -// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib -// -// Changelog: -// 2019-07-10 - Uses the new version of the DMP Firmware V6.12 -// - Note: I believe the Teapot demo is broken with this versin as -// - the fifo buffer structure has changed -// 2016-04-18 - Eliminated a potential infinite loop -// 2013-05-08 - added seamless Fastwire support -// - added note about gyro calibration -// 2012-06-21 - added note about Arduino 1.0.1 + Leonardo compatibility error -// 2012-06-20 - improved FIFO overflow handling and simplified read process -// 2012-06-19 - completely rearranged DMP initialization code and simplification -// 2012-06-13 - pull gyro and accel data from FIFO packet instead of reading directly -// 2012-06-09 - fix broken FIFO read sequence and change interrupt detection to RISING -// 2012-06-05 - add gravity-compensated initial reference frame acceleration output -// - add 3D math helper file to DMP6 example sketch -// - add Euler output and Yaw/Pitch/Roll output formats -// 2012-06-04 - remove accel offset clearing for better results (thanks Sungon Lee) -// 2012-06-01 - fixed gyro sensitivity to be 2000 deg/sec instead of 250 -// 2012-05-30 - basic DMP initialization working - -/* ============================================ - I2Cdev device library code is placed under the MIT license - Copyright (c) 2012 Jeff Rowberg - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - =============================================== -*/ - -// I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files -// for both classes must be in the include path of your project -#include "I2Cdev.h" - -#include "MPU6050_6Axis_MotionApps_V6_12.h" -//#include "MPU6050.h" // not necessary if using MotionApps include file - -// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation -// is used in I2Cdev.h -#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE -#include "Wire.h" -#endif - -// class default I2C address is 0x68 -// specific I2C addresses may be passed as a parameter here -// AD0 low = 0x68 (default for SparkFun breakout and InvenSense evaluation board) -// AD0 high = 0x69 -MPU6050 mpu; -//MPU6050 mpu(0x69); // <-- use for AD0 high - -/* ========================================================================= - NOTE: In addition to connection 3.3v, GND, SDA, and SCL, this sketch - depends on the MPU-6050's INT pin being connected to the Arduino's - external interrupt #0 pin. On the Arduino Uno and Mega 2560, this is - digital I/O pin 2. - ========================================================================= */ - -/* ========================================================================= - NOTE: Arduino v1.0.1 with the Leonardo board generates a compile error - when using Serial.write(buf, len). The Teapot output uses this method. - The solution requires a modification to the Arduino USBAPI.h file, which - is fortunately simple, but annoying. This will be fixed in the next IDE - release. For more info, see these links: - - http://arduino.cc/forum/index.php/topic,109987.0.html - http://code.google.com/p/arduino/issues/detail?id=958 - ========================================================================= */ - - - -// uncomment "OUTPUT_READABLE_QUATERNION" if you want to see the actual -// quaternion components in a [w, x, y, z] format (not best for parsing -// on a remote host such as Processing or something though) -//#define OUTPUT_READABLE_QUATERNION - -// uncomment "OUTPUT_READABLE_EULER" if you want to see Euler angles -// (in degrees) calculated from the quaternions coming from the FIFO. -// Note that Euler angles suffer from gimbal lock (for more info, see -// http://en.wikipedia.org/wiki/Gimbal_lock) -//#define OUTPUT_READABLE_EULER - -// uncomment "OUTPUT_READABLE_YAWPITCHROLL" if you want to see the yaw/ -// pitch/roll angles (in degrees) calculated from the quaternions coming -// from the FIFO. Note this also requires gravity vector calculations. -// Also note that yaw/pitch/roll angles suffer from gimbal lock (for -// more info, see: http://en.wikipedia.org/wiki/Gimbal_lock) -#define OUTPUT_READABLE_YAWPITCHROLL - -// uncomment "OUTPUT_READABLE_REALACCEL" if you want to see acceleration -// components with gravity removed. This acceleration reference frame is -// not compensated for orientation, so +X is always +X according to the -// sensor, just without the effects of gravity. If you want acceleration -// compensated for orientation, us OUTPUT_READABLE_WORLDACCEL instead. -//#define OUTPUT_READABLE_REALACCEL - -// uncomment "OUTPUT_READABLE_WORLDACCEL" if you want to see acceleration -// components with gravity removed and adjusted for the world frame of -// reference (yaw is relative to initial orientation, since no magnetometer -// is present in this case). Could be quite handy in some cases. -//#define OUTPUT_READABLE_WORLDACCEL - -// uncomment "OUTPUT_TEAPOT" if you want output that matches the -// format used for the InvenSense teapot demo -//#define OUTPUT_TEAPOT - - - -#define INTERRUPT_PIN 2 // use pin 2 on Arduino Uno & most boards -#define LED_PIN 13 // (Arduino is 13, Teensy is 11, Teensy++ is 6) -bool blinkState = false; - -// MPU control/status vars -bool dmpReady = false; // set true if DMP init was successful -uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU -uint8_t devStatus; // return status after each device operation (0 = success, !0 = error) -uint16_t packetSize; // expected DMP packet size (default is 42 bytes) -uint16_t fifoCount; // count of all bytes currently in FIFO -uint8_t fifoBuffer[64]; // FIFO storage buffer - -// orientation/motion vars -Quaternion q; // [w, x, y, z] quaternion container -VectorInt16 aa; // [x, y, z] accel sensor measurements -VectorInt16 gy; // [x, y, z] gyro sensor measurements -VectorInt16 aaReal; // [x, y, z] gravity-free accel sensor measurements -VectorInt16 aaWorld; // [x, y, z] world-frame accel sensor measurements -VectorFloat gravity; // [x, y, z] gravity vector -float euler[3]; // [psi, theta, phi] Euler angle container -float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector - -// packet structure for InvenSense teapot demo -uint8_t teapotPacket[14] = { '$', 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0x00, 0x00, '\r', '\n' }; - - - -// ================================================================ -// === INTERRUPT DETECTION ROUTINE === -// ================================================================ - -volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high -void dmpDataReady() { - mpuInterrupt = true; -} - -// ================================================================ -// === INITIAL SETUP === -// ================================================================ - -void setup() { - // join I2C bus (I2Cdev library doesn't do this automatically) -#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE - Wire.begin(); - Wire.setClock(400000); // 400kHz I2C clock. Comment this line if having compilation difficulties -#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE - Fastwire::setup(400, true); -#endif - - // initialize serial communication - // (115200 chosen because it is required for Teapot Demo output, but it's - // really up to you depending on your project) - Serial.begin(115200); - while (!Serial); // wait for Leonardo enumeration, others continue immediately - - // NOTE: 8MHz or slower host processors, like the Teensy @ 3.3V or Arduino - // Pro Mini running at 3.3V, cannot handle this baud rate reliably due to - // the baud timing being too misaligned with processor ticks. You must use - // 38400 or slower in these cases, or use some kind of external separate - // crystal solution for the UART timer. - - // initialize device - Serial.println(F("Initializing I2C devices...")); - mpu.initialize(); - pinMode(INTERRUPT_PIN, INPUT); - - // verify connection - Serial.println(F("Testing device connections...")); - Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed")); - - // wait for ready - Serial.println(F("\nSend any character to begin DMP programming and demo: ")); - while (Serial.available() && Serial.read()); // empty buffer - while (!Serial.available()); // wait for data - while (Serial.available() && Serial.read()); // empty buffer again - - // load and configure the DMP - Serial.println(F("Initializing DMP...")); - devStatus = mpu.dmpInitialize(); - - // supply your own gyro offsets here, scaled for min sensitivity - mpu.setXGyroOffset(51); - mpu.setYGyroOffset(8); - mpu.setZGyroOffset(21); - mpu.setXAccelOffset(1150); - mpu.setYAccelOffset(-50); - mpu.setZAccelOffset(1060); - // make sure it worked (returns 0 if so) - if (devStatus == 0) { - // Calibration Time: generate offsets and calibrate our MPU6050 - mpu.CalibrateAccel(6); - mpu.CalibrateGyro(6); - Serial.println(); - mpu.PrintActiveOffsets(); - // turn on the DMP, now that it's ready - Serial.println(F("Enabling DMP...")); - mpu.setDMPEnabled(true); - dmpReady = true; - // get expected DMP packet size for later comparison - packetSize = mpu.dmpGetFIFOPacketSize(); - } else { - // ERROR! - // 1 = initial memory load failed - // 2 = DMP configuration updates failed - // (if it's going to break, usually the code will be 1) - Serial.print(F("DMP Initialization failed (code ")); - Serial.print(devStatus); - Serial.println(F(")")); - } - - - // configure LED for output - pinMode(LED_PIN, OUTPUT); - - while (!dmpReady) {}// if programming failed, don't try to do anything -} - -// ================================================================ -// === MAIN PROGRAM LOOP === -// ================================================================ -void loop() { - - // Remove this user input and place your code here that can block this as much as you want - // Ultimate blocking code: - // wait for user input - Serial.println(F("\nSend any character to retrieve the latest position from the DMP FIFO Buffer: ")); - while (Serial.available() && Serial.read()); // empty buffer - while (!Serial.available()); // wait for data - // The fifo buffer has definatly overflowed but we can still get the latest packt!!! - if (!mpu.GetCurrentFIFOPacket(fifoBuffer, packetSize)) { // returns 0 if nothing could be revovered or we asked for a packet in less than 10ms from the last request - Serial.print("We Failed to get a good packet of data from the MPU6050"); - return ; // nothing to give to the program so return. This should never happen unless there is other issues involving communication. - } - - // display Euler angles in degrees - mpu.dmpGetQuaternion(&q, fifoBuffer); - mpu.dmpGetGravity(&gravity, &q); - mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); - Serial.print("ypr\t"); - Serial.print(ypr[0] * 180 / M_PI); - Serial.print("\t"); - Serial.print(ypr[1] * 180 / M_PI); - Serial.print("\t"); - Serial.print(ypr[2] * 180 / M_PI); - /* - mpu.dmpGetAccel(&aa, fifoBuffer); - Serial.print("\tRaw Accl XYZ\t"); - Serial.print(aa.x); - Serial.print("\t"); - Serial.print(aa.y); - Serial.print("\t"); - Serial.print(aa.z); - mpu.dmpGetGyro(&gy, fifoBuffer); - Serial.print("\tRaw Gyro XYZ\t"); - Serial.print(gy.x); - Serial.print("\t"); - Serial.print(gy.y); - Serial.print("\t"); - Serial.print(gy.z); - */ - Serial.println(); - // blink LED to indicate activity - blinkState = !blinkState; - digitalWrite(LED_PIN, blinkState); - -} From dc3b359771ccae21bb0ae5610dc6e5cc82c7a5f1 Mon Sep 17 00:00:00 2001 From: Homer Creutz Date: Wed, 22 Jan 2020 00:29:22 -0700 Subject: [PATCH 243/335] Delete MPU6050_DMP6_using_DMP_V6.12_No_Interrupts.ino --- ...050_DMP6_using_DMP_V6.12_No_Interrupts.ino | 284 ------------------ 1 file changed, 284 deletions(-) delete mode 100644 Arduino/MPU6050/examples/MPU6050_DMP6_using_DMP_V6.12_No_Interrupts/MPU6050_DMP6_using_DMP_V6.12_No_Interrupts.ino diff --git a/Arduino/MPU6050/examples/MPU6050_DMP6_using_DMP_V6.12_No_Interrupts/MPU6050_DMP6_using_DMP_V6.12_No_Interrupts.ino b/Arduino/MPU6050/examples/MPU6050_DMP6_using_DMP_V6.12_No_Interrupts/MPU6050_DMP6_using_DMP_V6.12_No_Interrupts.ino deleted file mode 100644 index 2419d0e1..00000000 --- a/Arduino/MPU6050/examples/MPU6050_DMP6_using_DMP_V6.12_No_Interrupts/MPU6050_DMP6_using_DMP_V6.12_No_Interrupts.ino +++ /dev/null @@ -1,284 +0,0 @@ -// I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class using DMP (MotionApps v6.12) -// 6/21/2012 by Jeff Rowberg -// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib -// -// Changelog: -// 2019-07-10 - Uses the new version of the DMP Firmware V6.12 -// - Note: I believe the Teapot demo is broken with this versin as -// - the fifo buffer structure has changed -// 2016-04-18 - Eliminated a potential infinite loop -// 2013-05-08 - added seamless Fastwire support -// - added note about gyro calibration -// 2012-06-21 - added note about Arduino 1.0.1 + Leonardo compatibility error -// 2012-06-20 - improved FIFO overflow handling and simplified read process -// 2012-06-09 - fix broken FIFO read sequence and change interrupt detection to RISING -// 2012-06-05 - add gravity-compensated initial reference frame acceleration output -// - add 3D math helper file to DMP6 example sketch -// - add Euler output and Yaw/Pitch/Roll output formats -// 2012-06-04 - remove accel offset clearing for better results (thanks Sungon Lee) -// 2012-06-01 - fixed gyro sensitivity to be 2000 deg/sec instead of 250 -// 2012-05-30 - basic DMP initialization working - -/* ============================================ - I2Cdev device library code is placed under the MIT license - Copyright (c) 2012 Jeff Rowberg - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - =============================================== -*/ - -// I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files -// for both classes must be in the include path of your project -#include "I2Cdev.h" - -#include "MPU6050_6Axis_MotionApps_V6_12.h" -//#include "MPU6050.h" // not necessary if using MotionApps include file - -// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation -// is used in I2Cdev.h -#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE -#include "Wire.h" -#endif - -// class default I2C address is 0x68 -// specific I2C addresses may be passed as a parameter here -// AD0 low = 0x68 (default for SparkFun breakout and InvenSense evaluation board) -// AD0 high = 0x69 -MPU6050 mpu; -//MPU6050 mpu(0x69); // <-- use for AD0 high - -/* ========================================================================= - NOTE: In addition to connection 3.3v, GND, SDA, and SCL, this sketch - depends on the MPU-6050's INT pin being connected to the Arduino's - external interrupt #0 pin. On the Arduino Uno and Mega 2560, this is - digital I/O pin 2. - ========================================================================= */ - -/* ========================================================================= - NOTE: Arduino v1.0.1 with the Leonardo board generates a compile error - when using Serial.write(buf, len). The Teapot output uses this method. - The solution requires a modification to the Arduino USBAPI.h file, which - is fortunately simple, but annoying. This will be fixed in the next IDE - release. For more info, see these links: - - http://arduino.cc/forum/index.php/topic,109987.0.html - http://code.google.com/p/arduino/issues/detail?id=958 - ========================================================================= */ - - - -// uncomment "OUTPUT_READABLE_QUATERNION" if you want to see the actual -// quaternion components in a [w, x, y, z] format (not best for parsing -// on a remote host such as Processing or something though) -//#define OUTPUT_READABLE_QUATERNION - -// uncomment "OUTPUT_READABLE_EULER" if you want to see Euler angles -// (in degrees) calculated from the quaternions coming from the FIFO. -// Note that Euler angles suffer from gimbal lock (for more info, see -// http://en.wikipedia.org/wiki/Gimbal_lock) -//#define OUTPUT_READABLE_EULER - -// uncomment "OUTPUT_READABLE_YAWPITCHROLL" if you want to see the yaw/ -// pitch/roll angles (in degrees) calculated from the quaternions coming -// from the FIFO. Note this also requires gravity vector calculations. -// Also note that yaw/pitch/roll angles suffer from gimbal lock (for -// more info, see: http://en.wikipedia.org/wiki/Gimbal_lock) -#define OUTPUT_READABLE_YAWPITCHROLL - -// uncomment "OUTPUT_READABLE_REALACCEL" if you want to see acceleration -// components with gravity removed. This acceleration reference frame is -// not compensated for orientation, so +X is always +X according to the -// sensor, just without the effects of gravity. If you want acceleration -// compensated for orientation, us OUTPUT_READABLE_WORLDACCEL instead. -//#define OUTPUT_READABLE_REALACCEL - -// uncomment "OUTPUT_READABLE_WORLDACCEL" if you want to see acceleration -// components with gravity removed and adjusted for the world frame of -// reference (yaw is relative to initial orientation, since no magnetometer -// is present in this case). Could be quite handy in some cases. -//#define OUTPUT_READABLE_WORLDACCEL - -// uncomment "OUTPUT_TEAPOT" if you want output that matches the -// format used for the InvenSense teapot demo -//#define OUTPUT_TEAPOT - - - -#define INTERRUPT_PIN 2 // use pin 2 on Arduino Uno & most boards -#define LED_PIN 13 // (Arduino is 13, Teensy is 11, Teensy++ is 6) -bool blinkState = false; - -// MPU control/status vars -bool dmpReady = false; // set true if DMP init was successful -uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU -uint8_t devStatus; // return status after each device operation (0 = success, !0 = error) -uint16_t packetSize; // expected DMP packet size (default is 42 bytes) -uint16_t fifoCount; // count of all bytes currently in FIFO -uint8_t fifoBuffer[64]; // FIFO storage buffer - -// orientation/motion vars -Quaternion q; // [w, x, y, z] quaternion container -VectorInt16 aa; // [x, y, z] accel sensor measurements -VectorInt16 gy; // [x, y, z] gyro sensor measurements -VectorInt16 aaReal; // [x, y, z] gravity-free accel sensor measurements -VectorInt16 aaWorld; // [x, y, z] world-frame accel sensor measurements -VectorFloat gravity; // [x, y, z] gravity vector -float euler[3]; // [psi, theta, phi] Euler angle container -float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector - -// packet structure for InvenSense teapot demo -uint8_t teapotPacket[14] = { '$', 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0x00, 0x00, '\r', '\n' }; - - - -// ================================================================ -// === INTERRUPT DETECTION ROUTINE === -// ================================================================ - -volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high -void dmpDataReady() { - mpuInterrupt = true; -} - -// ================================================================ -// === INITIAL SETUP === -// ================================================================ - -void setup() { - // join I2C bus (I2Cdev library doesn't do this automatically) -#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE - Wire.begin(); - Wire.setClock(400000); // 400kHz I2C clock. Comment this line if having compilation difficulties -#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE - Fastwire::setup(400, true); -#endif - - // initialize serial communication - // (115200 chosen because it is required for Teapot Demo output, but it's - // really up to you depending on your project) - Serial.begin(115200); - while (!Serial); // wait for Leonardo enumeration, others continue immediately - - // NOTE: 8MHz or slower host processors, like the Teensy @ 3.3V or Arduino - // Pro Mini running at 3.3V, cannot handle this baud rate reliably due to - // the baud timing being too misaligned with processor ticks. You must use - // 38400 or slower in these cases, or use some kind of external separate - // crystal solution for the UART timer. - - // initialize device - Serial.println(F("Initializing I2C devices...")); - mpu.initialize(); - pinMode(INTERRUPT_PIN, INPUT); - - // verify connection - Serial.println(F("Testing device connections...")); - Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed")); - - // wait for ready - Serial.println(F("\nSend any character to begin DMP programming and demo: ")); - while (Serial.available() && Serial.read()); // empty buffer - while (!Serial.available()); // wait for data - while (Serial.available() && Serial.read()); // empty buffer again - - // load and configure the DMP - Serial.println(F("Initializing DMP...")); - devStatus = mpu.dmpInitialize(); - - // supply your own gyro offsets here, scaled for min sensitivity - mpu.setXGyroOffset(51); - mpu.setYGyroOffset(8); - mpu.setZGyroOffset(21); - mpu.setXAccelOffset(1150); - mpu.setYAccelOffset(-50); - mpu.setZAccelOffset(1060); - // make sure it worked (returns 0 if so) - if (devStatus == 0) { - // Calibration Time: generate offsets and calibrate our MPU6050 - mpu.CalibrateAccel(6); - mpu.CalibrateGyro(6); - Serial.println(); - mpu.PrintActiveOffsets(); - // turn on the DMP, now that it's ready - Serial.println(F("Enabling DMP...")); - mpu.setDMPEnabled(true); - dmpReady = true; - // get expected DMP packet size for later comparison - packetSize = mpu.dmpGetFIFOPacketSize(); - } else { - // ERROR! - // 1 = initial memory load failed - // 2 = DMP configuration updates failed - // (if it's going to break, usually the code will be 1) - Serial.print(F("DMP Initialization failed (code ")); - Serial.print(devStatus); - Serial.println(F(")")); - } - - - // configure LED for output - pinMode(LED_PIN, OUTPUT); - - while (!dmpReady) {}// if programming failed, don't try to do anything -} - -// ================================================================ -// === MAIN PROGRAM LOOP === -// ================================================================ -int loopCtr; -void loop() { - // other fast code can go here. faster the better - loopCtr++; - if (!mpu.GetCurrentFIFOPacket(fifoBuffer, packetSize)) { // returns 0 when no data has arrived. - return ; // nothing to give to the program so return. - } - Serial.print("Loops: "); - Serial.print(loopCtr); - loopCtr = 0; - // display Euler angles in degrees - mpu.dmpGetQuaternion(&q, fifoBuffer); - mpu.dmpGetGravity(&gravity, &q); - mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); - Serial.print(" ypr\t"); - Serial.print(ypr[0] * 180 / M_PI); - Serial.print("\t"); - Serial.print(ypr[1] * 180 / M_PI); - Serial.print("\t"); - Serial.print(ypr[2] * 180 / M_PI); - /* - mpu.dmpGetAccel(&aa, fifoBuffer); - Serial.print("\tRaw Accl XYZ\t"); - Serial.print(aa.x); - Serial.print("\t"); - Serial.print(aa.y); - Serial.print("\t"); - Serial.print(aa.z); - mpu.dmpGetGyro(&gy, fifoBuffer); - Serial.print("\tRaw Gyro XYZ\t"); - Serial.print(gy.x); - Serial.print("\t"); - Serial.print(gy.y); - Serial.print("\t"); - Serial.print(gy.z); - */ - Serial.println(); - // blink LED to indicate activity - blinkState = !blinkState; - digitalWrite(LED_PIN, blinkState); - -} From 8e5809deb623e831b7a4e9869b6ecea25c4ed3f0 Mon Sep 17 00:00:00 2001 From: Homer Creutz Date: Wed, 22 Jan 2020 00:42:10 -0700 Subject: [PATCH 244/335] Finished update --- Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h | 2 +- Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h index badd084d..5572d1aa 100644 --- a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h +++ b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h @@ -615,7 +615,7 @@ uint16_t MPU6050::dmpGetFIFOPacketSize() { uint8_t MPU6050::dmpGetCurrentFIFOPacket(uint8_t *data) { // overflow proof - GetCurrentFIFOPacket(*data, dmpGetFIFOPacketSize()); + return(GetCurrentFIFOPacket(data, dmpPacketSize)); } #endif /* _MPU6050_6AXIS_MOTIONAPPS20_H_ */ diff --git a/Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h b/Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h index c8c8cade..822fa171 100644 --- a/Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h +++ b/Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h @@ -615,7 +615,7 @@ uint16_t MPU6050::dmpGetFIFOPacketSize() { uint8_t MPU6050::dmpGetCurrentFIFOPacket(uint8_t *data) { // overflow proof - GetCurrentFIFOPacket(*data, dmpGetFIFOPacketSize()); + return(GetCurrentFIFOPacket(data, dmpPacketSize)); } #endif /* _MPU6050_6AXIS_MOTIONAPPS20_H_ */ From 0b8d1f7feff3a04578c8e0f4a82f0160072607a8 Mon Sep 17 00:00:00 2001 From: Homer Creutz Date: Wed, 5 Feb 2020 23:02:43 -0700 Subject: [PATCH 245/335] Moved New Files to correc directory --- .../examples/MPU6050_DMP6/MPU6050_DMP6.ino | 48 +- .../MPU6050_DMP6/MPU6050_DMP6.ino | 345 ------------- .../MPU6050_DMP6_using_DMP_V6.12.ino | 476 ++++++++---------- .../MPU6050_DMP6_using_DMP_V6.12.ino | 368 -------------- 4 files changed, 219 insertions(+), 1018 deletions(-) delete mode 100644 Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6/MPU6050_DMP6.ino delete mode 100644 Arduino/MPU6050/examples/MPU6050_DMP6_using_DMP_V6.12/MPU6050_DMP6_using_DMP_V6.12/MPU6050_DMP6_using_DMP_V6.12.ino diff --git a/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino b/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino index 7298527d..3ebe2ee6 100644 --- a/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino +++ b/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino @@ -254,52 +254,8 @@ void setup() { void loop() { // if programming failed, don't try to do anything if (!dmpReady) return; - - // wait for MPU interrupt or extra packet(s) available - while (!mpuInterrupt && fifoCount < packetSize) { - if (mpuInterrupt && fifoCount < packetSize) { - // try to get out of the infinite loop - fifoCount = mpu.getFIFOCount(); - } - // other program behavior stuff here - // . - // . - // . - // if you are really paranoid you can frequently test in between other - // stuff to see if mpuInterrupt is true, and if so, "break;" from the - // while() loop to immediately process the MPU data - // . - // . - // . - } - - // reset interrupt flag and get INT_STATUS byte - mpuInterrupt = false; - mpuIntStatus = mpu.getIntStatus(); - - // get current FIFO count - fifoCount = mpu.getFIFOCount(); - if(fifoCount < packetSize){ - //Lets go back and wait for another interrupt. We shouldn't be here, we got an interrupt from another event - // This is blocking so don't do it while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount(); - } - // check for overflow (this should never happen unless our code is too inefficient) - else if ((mpuIntStatus & _BV(MPU6050_INTERRUPT_FIFO_OFLOW_BIT)) || fifoCount >= 1024) { - // reset so we can continue cleanly - mpu.resetFIFO(); - // fifoCount = mpu.getFIFOCount(); // will be zero after reset no need to ask - Serial.println(F("FIFO overflow!")); - - // otherwise, check for DMP data ready interrupt (this should happen frequently) - } else if (mpuIntStatus & _BV(MPU6050_INTERRUPT_DMP_INT_BIT)) { - - // read a packet from FIFO - while(fifoCount >= packetSize){ // Lets catch up to NOW, someone is using the dreaded delay()! - mpu.getFIFOBytes(fifoBuffer, packetSize); - // track FIFO count here in case there is > 1 packet available - // (this lets us immediately read more without waiting for an interrupt) - fifoCount -= packetSize; - } + // read a packet from FIFO + if (mpu.dmpGetCurrentFIFOPacket(fifoBuffer)) { // Get the Latest packet #ifdef OUTPUT_READABLE_QUATERNION // display quaternion values in easy matrix form: w x y z mpu.dmpGetQuaternion(&q, fifoBuffer); diff --git a/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6/MPU6050_DMP6.ino b/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6/MPU6050_DMP6.ino deleted file mode 100644 index 3ebe2ee6..00000000 --- a/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6/MPU6050_DMP6.ino +++ /dev/null @@ -1,345 +0,0 @@ -// I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class using DMP (MotionApps v2.0) -// 6/21/2012 by Jeff Rowberg -// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib -// -// Changelog: -// 2019-07-08 - Added Auto Calibration and offset generator -// - and altered FIFO retrieval sequence to avoid using blocking code -// 2016-04-18 - Eliminated a potential infinite loop -// 2013-05-08 - added seamless Fastwire support -// - added note about gyro calibration -// 2012-06-21 - added note about Arduino 1.0.1 + Leonardo compatibility error -// 2012-06-20 - improved FIFO overflow handling and simplified read process -// 2012-06-19 - completely rearranged DMP initialization code and simplification -// 2012-06-13 - pull gyro and accel data from FIFO packet instead of reading directly -// 2012-06-09 - fix broken FIFO read sequence and change interrupt detection to RISING -// 2012-06-05 - add gravity-compensated initial reference frame acceleration output -// - add 3D math helper file to DMP6 example sketch -// - add Euler output and Yaw/Pitch/Roll output formats -// 2012-06-04 - remove accel offset clearing for better results (thanks Sungon Lee) -// 2012-06-01 - fixed gyro sensitivity to be 2000 deg/sec instead of 250 -// 2012-05-30 - basic DMP initialization working - -/* ============================================ -I2Cdev device library code is placed under the MIT license -Copyright (c) 2012 Jeff Rowberg - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -=============================================== -*/ - -// I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files -// for both classes must be in the include path of your project -#include "I2Cdev.h" - -#include "MPU6050_6Axis_MotionApps20.h" -//#include "MPU6050.h" // not necessary if using MotionApps include file - -// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation -// is used in I2Cdev.h -#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE - #include "Wire.h" -#endif - -// class default I2C address is 0x68 -// specific I2C addresses may be passed as a parameter here -// AD0 low = 0x68 (default for SparkFun breakout and InvenSense evaluation board) -// AD0 high = 0x69 -MPU6050 mpu; -//MPU6050 mpu(0x69); // <-- use for AD0 high - -/* ========================================================================= - NOTE: In addition to connection 3.3v, GND, SDA, and SCL, this sketch - depends on the MPU-6050's INT pin being connected to the Arduino's - external interrupt #0 pin. On the Arduino Uno and Mega 2560, this is - digital I/O pin 2. - * ========================================================================= */ - -/* ========================================================================= - NOTE: Arduino v1.0.1 with the Leonardo board generates a compile error - when using Serial.write(buf, len). The Teapot output uses this method. - The solution requires a modification to the Arduino USBAPI.h file, which - is fortunately simple, but annoying. This will be fixed in the next IDE - release. For more info, see these links: - - http://arduino.cc/forum/index.php/topic,109987.0.html - http://code.google.com/p/arduino/issues/detail?id=958 - * ========================================================================= */ - - - -// uncomment "OUTPUT_READABLE_QUATERNION" if you want to see the actual -// quaternion components in a [w, x, y, z] format (not best for parsing -// on a remote host such as Processing or something though) -//#define OUTPUT_READABLE_QUATERNION - -// uncomment "OUTPUT_READABLE_EULER" if you want to see Euler angles -// (in degrees) calculated from the quaternions coming from the FIFO. -// Note that Euler angles suffer from gimbal lock (for more info, see -// http://en.wikipedia.org/wiki/Gimbal_lock) -//#define OUTPUT_READABLE_EULER - -// uncomment "OUTPUT_READABLE_YAWPITCHROLL" if you want to see the yaw/ -// pitch/roll angles (in degrees) calculated from the quaternions coming -// from the FIFO. Note this also requires gravity vector calculations. -// Also note that yaw/pitch/roll angles suffer from gimbal lock (for -// more info, see: http://en.wikipedia.org/wiki/Gimbal_lock) -#define OUTPUT_READABLE_YAWPITCHROLL - -// uncomment "OUTPUT_READABLE_REALACCEL" if you want to see acceleration -// components with gravity removed. This acceleration reference frame is -// not compensated for orientation, so +X is always +X according to the -// sensor, just without the effects of gravity. If you want acceleration -// compensated for orientation, us OUTPUT_READABLE_WORLDACCEL instead. -//#define OUTPUT_READABLE_REALACCEL - -// uncomment "OUTPUT_READABLE_WORLDACCEL" if you want to see acceleration -// components with gravity removed and adjusted for the world frame of -// reference (yaw is relative to initial orientation, since no magnetometer -// is present in this case). Could be quite handy in some cases. -//#define OUTPUT_READABLE_WORLDACCEL - -// uncomment "OUTPUT_TEAPOT" if you want output that matches the -// format used for the InvenSense teapot demo -//#define OUTPUT_TEAPOT - - - -#define INTERRUPT_PIN 2 // use pin 2 on Arduino Uno & most boards -#define LED_PIN 13 // (Arduino is 13, Teensy is 11, Teensy++ is 6) -bool blinkState = false; - -// MPU control/status vars -bool dmpReady = false; // set true if DMP init was successful -uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU -uint8_t devStatus; // return status after each device operation (0 = success, !0 = error) -uint16_t packetSize; // expected DMP packet size (default is 42 bytes) -uint16_t fifoCount; // count of all bytes currently in FIFO -uint8_t fifoBuffer[64]; // FIFO storage buffer - -// orientation/motion vars -Quaternion q; // [w, x, y, z] quaternion container -VectorInt16 aa; // [x, y, z] accel sensor measurements -VectorInt16 aaReal; // [x, y, z] gravity-free accel sensor measurements -VectorInt16 aaWorld; // [x, y, z] world-frame accel sensor measurements -VectorFloat gravity; // [x, y, z] gravity vector -float euler[3]; // [psi, theta, phi] Euler angle container -float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector - -// packet structure for InvenSense teapot demo -uint8_t teapotPacket[14] = { '$', 0x02, 0,0, 0,0, 0,0, 0,0, 0x00, 0x00, '\r', '\n' }; - - - -// ================================================================ -// === INTERRUPT DETECTION ROUTINE === -// ================================================================ - -volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high -void dmpDataReady() { - mpuInterrupt = true; -} - - - -// ================================================================ -// === INITIAL SETUP === -// ================================================================ - -void setup() { - // join I2C bus (I2Cdev library doesn't do this automatically) - #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE - Wire.begin(); - Wire.setClock(400000); // 400kHz I2C clock. Comment this line if having compilation difficulties - #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE - Fastwire::setup(400, true); - #endif - - // initialize serial communication - // (115200 chosen because it is required for Teapot Demo output, but it's - // really up to you depending on your project) - Serial.begin(115200); - while (!Serial); // wait for Leonardo enumeration, others continue immediately - - // NOTE: 8MHz or slower host processors, like the Teensy @ 3.3V or Arduino - // Pro Mini running at 3.3V, cannot handle this baud rate reliably due to - // the baud timing being too misaligned with processor ticks. You must use - // 38400 or slower in these cases, or use some kind of external separate - // crystal solution for the UART timer. - - // initialize device - Serial.println(F("Initializing I2C devices...")); - mpu.initialize(); - pinMode(INTERRUPT_PIN, INPUT); - - // verify connection - Serial.println(F("Testing device connections...")); - Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed")); - - // wait for ready - Serial.println(F("\nSend any character to begin DMP programming and demo: ")); - while (Serial.available() && Serial.read()); // empty buffer - while (!Serial.available()); // wait for data - while (Serial.available() && Serial.read()); // empty buffer again - - // load and configure the DMP - Serial.println(F("Initializing DMP...")); - devStatus = mpu.dmpInitialize(); - - // supply your own gyro offsets here, scaled for min sensitivity - mpu.setXGyroOffset(220); - mpu.setYGyroOffset(76); - mpu.setZGyroOffset(-85); - mpu.setZAccelOffset(1788); // 1688 factory default for my test chip - - // make sure it worked (returns 0 if so) - if (devStatus == 0) { - // Calibration Time: generate offsets and calibrate our MPU6050 - mpu.CalibrateAccel(6); - mpu.CalibrateGyro(6); - mpu.PrintActiveOffsets(); - // turn on the DMP, now that it's ready - Serial.println(F("Enabling DMP...")); - mpu.setDMPEnabled(true); - - // enable Arduino interrupt detection - Serial.print(F("Enabling interrupt detection (Arduino external interrupt ")); - Serial.print(digitalPinToInterrupt(INTERRUPT_PIN)); - Serial.println(F(")...")); - attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), dmpDataReady, RISING); - mpuIntStatus = mpu.getIntStatus(); - - // set our DMP Ready flag so the main loop() function knows it's okay to use it - Serial.println(F("DMP ready! Waiting for first interrupt...")); - dmpReady = true; - - // get expected DMP packet size for later comparison - packetSize = mpu.dmpGetFIFOPacketSize(); - } else { - // ERROR! - // 1 = initial memory load failed - // 2 = DMP configuration updates failed - // (if it's going to break, usually the code will be 1) - Serial.print(F("DMP Initialization failed (code ")); - Serial.print(devStatus); - Serial.println(F(")")); - } - - // configure LED for output - pinMode(LED_PIN, OUTPUT); -} - - - -// ================================================================ -// === MAIN PROGRAM LOOP === -// ================================================================ - -void loop() { - // if programming failed, don't try to do anything - if (!dmpReady) return; - // read a packet from FIFO - if (mpu.dmpGetCurrentFIFOPacket(fifoBuffer)) { // Get the Latest packet - #ifdef OUTPUT_READABLE_QUATERNION - // display quaternion values in easy matrix form: w x y z - mpu.dmpGetQuaternion(&q, fifoBuffer); - Serial.print("quat\t"); - Serial.print(q.w); - Serial.print("\t"); - Serial.print(q.x); - Serial.print("\t"); - Serial.print(q.y); - Serial.print("\t"); - Serial.println(q.z); - #endif - - #ifdef OUTPUT_READABLE_EULER - // display Euler angles in degrees - mpu.dmpGetQuaternion(&q, fifoBuffer); - mpu.dmpGetEuler(euler, &q); - Serial.print("euler\t"); - Serial.print(euler[0] * 180/M_PI); - Serial.print("\t"); - Serial.print(euler[1] * 180/M_PI); - Serial.print("\t"); - Serial.println(euler[2] * 180/M_PI); - #endif - - #ifdef OUTPUT_READABLE_YAWPITCHROLL - // display Euler angles in degrees - mpu.dmpGetQuaternion(&q, fifoBuffer); - mpu.dmpGetGravity(&gravity, &q); - mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); - Serial.print("ypr\t"); - Serial.print(ypr[0] * 180/M_PI); - Serial.print("\t"); - Serial.print(ypr[1] * 180/M_PI); - Serial.print("\t"); - Serial.println(ypr[2] * 180/M_PI); - #endif - - #ifdef OUTPUT_READABLE_REALACCEL - // display real acceleration, adjusted to remove gravity - mpu.dmpGetQuaternion(&q, fifoBuffer); - mpu.dmpGetAccel(&aa, fifoBuffer); - mpu.dmpGetGravity(&gravity, &q); - mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity); - Serial.print("areal\t"); - Serial.print(aaReal.x); - Serial.print("\t"); - Serial.print(aaReal.y); - Serial.print("\t"); - Serial.println(aaReal.z); - #endif - - #ifdef OUTPUT_READABLE_WORLDACCEL - // display initial world-frame acceleration, adjusted to remove gravity - // and rotated based on known orientation from quaternion - mpu.dmpGetQuaternion(&q, fifoBuffer); - mpu.dmpGetAccel(&aa, fifoBuffer); - mpu.dmpGetGravity(&gravity, &q); - mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity); - mpu.dmpGetLinearAccelInWorld(&aaWorld, &aaReal, &q); - Serial.print("aworld\t"); - Serial.print(aaWorld.x); - Serial.print("\t"); - Serial.print(aaWorld.y); - Serial.print("\t"); - Serial.println(aaWorld.z); - #endif - - #ifdef OUTPUT_TEAPOT - // display quaternion values in InvenSense Teapot demo format: - teapotPacket[2] = fifoBuffer[0]; - teapotPacket[3] = fifoBuffer[1]; - teapotPacket[4] = fifoBuffer[4]; - teapotPacket[5] = fifoBuffer[5]; - teapotPacket[6] = fifoBuffer[8]; - teapotPacket[7] = fifoBuffer[9]; - teapotPacket[8] = fifoBuffer[12]; - teapotPacket[9] = fifoBuffer[13]; - Serial.write(teapotPacket, 14); - teapotPacket[11]++; // packetCount, loops at 0xFF on purpose - #endif - - // blink LED to indicate activity - blinkState = !blinkState; - digitalWrite(LED_PIN, blinkState); - } -} diff --git a/Arduino/MPU6050/examples/MPU6050_DMP6_using_DMP_V6.12/MPU6050_DMP6_using_DMP_V6.12.ino b/Arduino/MPU6050/examples/MPU6050_DMP6_using_DMP_V6.12/MPU6050_DMP6_using_DMP_V6.12.ino index 31175909..9a87db5c 100644 --- a/Arduino/MPU6050/examples/MPU6050_DMP6_using_DMP_V6.12/MPU6050_DMP6_using_DMP_V6.12.ino +++ b/Arduino/MPU6050/examples/MPU6050_DMP6_using_DMP_V6.12/MPU6050_DMP6_using_DMP_V6.12.ino @@ -4,7 +4,7 @@ // // Changelog: // 2019-07-10 - Uses the new version of the DMP Firmware V6.12 -// - Note: I believe the Teapot demo is broken with this versin as +// - Note: I believe the Teapot demo is broken with this versin as // - the fifo buffer structure has changed // 2016-04-18 - Eliminated a potential infinite loop // 2013-05-08 - added seamless Fastwire support @@ -22,27 +22,27 @@ // 2012-05-30 - basic DMP initialization working /* ============================================ -I2Cdev device library code is placed under the MIT license -Copyright (c) 2012 Jeff Rowberg - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -=============================================== + I2Cdev device library code is placed under the MIT license + Copyright (c) 2012 Jeff Rowberg + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + =============================================== */ // I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files @@ -55,7 +55,7 @@ THE SOFTWARE. // Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation // is used in I2Cdev.h #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE - #include "Wire.h" +#include "Wire.h" #endif // class default I2C address is 0x68 @@ -70,7 +70,7 @@ MPU6050 mpu; depends on the MPU-6050's INT pin being connected to the Arduino's external interrupt #0 pin. On the Arduino Uno and Mega 2560, this is digital I/O pin 2. - * ========================================================================= */ + ========================================================================= */ /* ========================================================================= NOTE: Arduino v1.0.1 with the Leonardo board generates a compile error @@ -81,7 +81,7 @@ MPU6050 mpu; http://arduino.cc/forum/index.php/topic,109987.0.html http://code.google.com/p/arduino/issues/detail?id=958 - * ========================================================================= */ + ========================================================================= */ @@ -145,7 +145,7 @@ float euler[3]; // [psi, theta, phi] Euler angle container float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector // packet structure for InvenSense teapot demo -uint8_t teapotPacket[14] = { '$', 0x02, 0,0, 0,0, 0,0, 0,0, 0x00, 0x00, '\r', '\n' }; +uint8_t teapotPacket[14] = { '$', 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0x00, 0x00, '\r', '\n' }; @@ -155,7 +155,7 @@ uint8_t teapotPacket[14] = { '$', 0x02, 0,0, 0,0, 0,0, 0,0, 0x00, 0x00, '\r', '\ volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high void dmpDataReady() { - mpuInterrupt = true; + mpuInterrupt = true; } @@ -165,88 +165,88 @@ void dmpDataReady() { // ================================================================ void setup() { - // join I2C bus (I2Cdev library doesn't do this automatically) - #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE - Wire.begin(); - Wire.setClock(400000); // 400kHz I2C clock. Comment this line if having compilation difficulties - #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE - Fastwire::setup(400, true); - #endif - - // initialize serial communication - // (115200 chosen because it is required for Teapot Demo output, but it's - // really up to you depending on your project) - Serial.begin(115200); - while (!Serial); // wait for Leonardo enumeration, others continue immediately - - // NOTE: 8MHz or slower host processors, like the Teensy @ 3.3V or Arduino - // Pro Mini running at 3.3V, cannot handle this baud rate reliably due to - // the baud timing being too misaligned with processor ticks. You must use - // 38400 or slower in these cases, or use some kind of external separate - // crystal solution for the UART timer. - - // initialize device - Serial.println(F("Initializing I2C devices...")); - mpu.initialize(); - pinMode(INTERRUPT_PIN, INPUT); - - // verify connection - Serial.println(F("Testing device connections...")); - Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed")); - - // wait for ready - Serial.println(F("\nSend any character to begin DMP programming and demo: ")); - while (Serial.available() && Serial.read()); // empty buffer - while (!Serial.available()); // wait for data - while (Serial.available() && Serial.read()); // empty buffer again - - // load and configure the DMP - Serial.println(F("Initializing DMP...")); - devStatus = mpu.dmpInitialize(); - - // supply your own gyro offsets here, scaled for min sensitivity - mpu.setXGyroOffset(51); - mpu.setYGyroOffset(8); - mpu.setZGyroOffset(21); - mpu.setXAccelOffset(1150); - mpu.setYAccelOffset(-50); - mpu.setZAccelOffset(1060); - // make sure it worked (returns 0 if so) - if (devStatus == 0) { - // Calibration Time: generate offsets and calibrate our MPU6050 - mpu.CalibrateAccel(6); - mpu.CalibrateGyro(6); - Serial.println(); - mpu.PrintActiveOffsets(); - // turn on the DMP, now that it's ready - Serial.println(F("Enabling DMP...")); - mpu.setDMPEnabled(true); - - // enable Arduino interrupt detection - Serial.print(F("Enabling interrupt detection (Arduino external interrupt ")); - Serial.print(digitalPinToInterrupt(INTERRUPT_PIN)); - Serial.println(F(")...")); - attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), dmpDataReady, RISING); - mpuIntStatus = mpu.getIntStatus(); - - // set our DMP Ready flag so the main loop() function knows it's okay to use it - Serial.println(F("DMP ready! Waiting for first interrupt...")); - dmpReady = true; - - // get expected DMP packet size for later comparison - packetSize = mpu.dmpGetFIFOPacketSize(); - } else { - // ERROR! - // 1 = initial memory load failed - // 2 = DMP configuration updates failed - // (if it's going to break, usually the code will be 1) - Serial.print(F("DMP Initialization failed (code ")); - Serial.print(devStatus); - Serial.println(F(")")); - } - - // configure LED for output - pinMode(LED_PIN, OUTPUT); + // join I2C bus (I2Cdev library doesn't do this automatically) +#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE + Wire.begin(); + Wire.setClock(400000); // 400kHz I2C clock. Comment this line if having compilation difficulties +#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE + Fastwire::setup(400, true); +#endif + + // initialize serial communication + // (115200 chosen because it is required for Teapot Demo output, but it's + // really up to you depending on your project) + Serial.begin(115200); + while (!Serial); // wait for Leonardo enumeration, others continue immediately + + // NOTE: 8MHz or slower host processors, like the Teensy @ 3.3V or Arduino + // Pro Mini running at 3.3V, cannot handle this baud rate reliably due to + // the baud timing being too misaligned with processor ticks. You must use + // 38400 or slower in these cases, or use some kind of external separate + // crystal solution for the UART timer. + + // initialize device + Serial.println(F("Initializing I2C devices...")); + mpu.initialize(); + pinMode(INTERRUPT_PIN, INPUT); + + // verify connection + Serial.println(F("Testing device connections...")); + Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed")); + + // wait for ready + Serial.println(F("\nSend any character to begin DMP programming and demo: ")); + while (Serial.available() && Serial.read()); // empty buffer + while (!Serial.available()); // wait for data + while (Serial.available() && Serial.read()); // empty buffer again + + // load and configure the DMP + Serial.println(F("Initializing DMP...")); + devStatus = mpu.dmpInitialize(); + + // supply your own gyro offsets here, scaled for min sensitivity + mpu.setXGyroOffset(51); + mpu.setYGyroOffset(8); + mpu.setZGyroOffset(21); + mpu.setXAccelOffset(1150); + mpu.setYAccelOffset(-50); + mpu.setZAccelOffset(1060); + // make sure it worked (returns 0 if so) + if (devStatus == 0) { + // Calibration Time: generate offsets and calibrate our MPU6050 + mpu.CalibrateAccel(6); + mpu.CalibrateGyro(6); + Serial.println(); + mpu.PrintActiveOffsets(); + // turn on the DMP, now that it's ready + Serial.println(F("Enabling DMP...")); + mpu.setDMPEnabled(true); + + // enable Arduino interrupt detection + Serial.print(F("Enabling interrupt detection (Arduino external interrupt ")); + Serial.print(digitalPinToInterrupt(INTERRUPT_PIN)); + Serial.println(F(")...")); + attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), dmpDataReady, RISING); + mpuIntStatus = mpu.getIntStatus(); + + // set our DMP Ready flag so the main loop() function knows it's okay to use it + Serial.println(F("DMP ready! Waiting for first interrupt...")); + dmpReady = true; + + // get expected DMP packet size for later comparison + packetSize = mpu.dmpGetFIFOPacketSize(); + } else { + // ERROR! + // 1 = initial memory load failed + // 2 = DMP configuration updates failed + // (if it's going to break, usually the code will be 1) + Serial.print(F("DMP Initialization failed (code ")); + Serial.print(devStatus); + Serial.println(F(")")); + } + + // configure LED for output + pinMode(LED_PIN, OUTPUT); } @@ -256,155 +256,113 @@ void setup() { // ================================================================ void loop() { - // if programming failed, don't try to do anything - if (!dmpReady) return; - - // wait for MPU interrupt or extra packet(s) available - while (!mpuInterrupt && fifoCount < packetSize) { - if (mpuInterrupt && fifoCount < packetSize) { - // try to get out of the infinite loop - fifoCount = mpu.getFIFOCount(); - } - // other program behavior stuff here - // . - // . - // . - // if you are really paranoid you can frequently test in between other - // stuff to see if mpuInterrupt is true, and if so, "break;" from the - // while() loop to immediately process the MPU data - // . - // . - // . - } - - // reset interrupt flag and get INT_STATUS byte - mpuInterrupt = false; - mpuIntStatus = mpu.getIntStatus(); + // if programming failed, don't try to do anything + if (!dmpReady) return; + // read a packet from FIFO + if (mpu.dmpGetCurrentFIFOPacket(fifoBuffer)) { // Get the Latest packet + +#ifdef OUTPUT_READABLE_QUATERNION + // display quaternion values in easy matrix form: w x y z + mpu.dmpGetQuaternion(&q, fifoBuffer); + Serial.print("quat\t"); + Serial.print(q.w); + Serial.print("\t"); + Serial.print(q.x); + Serial.print("\t"); + Serial.print(q.y); + Serial.print("\t"); + Serial.println(q.z); +#endif + +#ifdef OUTPUT_READABLE_EULER + // display Euler angles in degrees + mpu.dmpGetQuaternion(&q, fifoBuffer); + mpu.dmpGetEuler(euler, &q); + Serial.print("euler\t"); + Serial.print(euler[0] * 180 / M_PI); + Serial.print("\t"); + Serial.print(euler[1] * 180 / M_PI); + Serial.print("\t"); + Serial.println(euler[2] * 180 / M_PI); +#endif + +#ifdef OUTPUT_READABLE_YAWPITCHROLL + // display Euler angles in degrees + mpu.dmpGetQuaternion(&q, fifoBuffer); + mpu.dmpGetGravity(&gravity, &q); + mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); + Serial.print("ypr\t"); + Serial.print(ypr[0] * 180 / M_PI); + Serial.print("\t"); + Serial.print(ypr[1] * 180 / M_PI); + Serial.print("\t"); + Serial.print(ypr[2] * 180 / M_PI); + /* + mpu.dmpGetAccel(&aa, fifoBuffer); + Serial.print("\tRaw Accl XYZ\t"); + Serial.print(aa.x); + Serial.print("\t"); + Serial.print(aa.y); + Serial.print("\t"); + Serial.print(aa.z); + mpu.dmpGetGyro(&gy, fifoBuffer); + Serial.print("\tRaw Gyro XYZ\t"); + Serial.print(gy.x); + Serial.print("\t"); + Serial.print(gy.y); + Serial.print("\t"); + Serial.print(gy.z); + */ + Serial.println(); + +#endif + +#ifdef OUTPUT_READABLE_REALACCEL + // display real acceleration, adjusted to remove gravity + mpu.dmpGetQuaternion(&q, fifoBuffer); + mpu.dmpGetAccel(&aa, fifoBuffer); + mpu.dmpGetGravity(&gravity, &q); + mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity); + Serial.print("areal\t"); + Serial.print(aaReal.x); + Serial.print("\t"); + Serial.print(aaReal.y); + Serial.print("\t"); + Serial.println(aaReal.z); +#endif + +#ifdef OUTPUT_READABLE_WORLDACCEL + // display initial world-frame acceleration, adjusted to remove gravity + // and rotated based on known orientation from quaternion + mpu.dmpGetQuaternion(&q, fifoBuffer); + mpu.dmpGetAccel(&aa, fifoBuffer); + mpu.dmpGetGravity(&gravity, &q); + mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity); + mpu.dmpGetLinearAccelInWorld(&aaWorld, &aaReal, &q); + Serial.print("aworld\t"); + Serial.print(aaWorld.x); + Serial.print("\t"); + Serial.print(aaWorld.y); + Serial.print("\t"); + Serial.println(aaWorld.z); +#endif + +#ifdef OUTPUT_TEAPOT + // display quaternion values in InvenSense Teapot demo format: + teapotPacket[2] = fifoBuffer[0]; + teapotPacket[3] = fifoBuffer[1]; + teapotPacket[4] = fifoBuffer[4]; + teapotPacket[5] = fifoBuffer[5]; + teapotPacket[6] = fifoBuffer[8]; + teapotPacket[7] = fifoBuffer[9]; + teapotPacket[8] = fifoBuffer[12]; + teapotPacket[9] = fifoBuffer[13]; + Serial.write(teapotPacket, 14); + teapotPacket[11]++; // packetCount, loops at 0xFF on purpose +#endif - // get current FIFO count - fifoCount = mpu.getFIFOCount(); - - // check for overflow (this should never happen unless our code is too inefficient) - if ((mpuIntStatus & _BV(MPU6050_INTERRUPT_FIFO_OFLOW_BIT)) || fifoCount >= 1024) { - // reset so we can continue cleanly - mpu.resetFIFO(); - fifoCount = mpu.getFIFOCount(); - Serial.println(F("FIFO overflow!")); - - // otherwise, check for DMP data ready interrupt (this should happen frequently) - } else if (mpuIntStatus & _BV(MPU6050_INTERRUPT_DMP_INT_BIT)) { - // wait for correct available data length, should be a VERY short wait - while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount(); - - // read a packet from FIFO - mpu.getFIFOBytes(fifoBuffer, packetSize); - - // track FIFO count here in case there is > 1 packet available - // (this lets us immediately read more without waiting for an interrupt) - fifoCount -= packetSize; - - #ifdef OUTPUT_READABLE_QUATERNION - // display quaternion values in easy matrix form: w x y z - mpu.dmpGetQuaternion(&q, fifoBuffer); - Serial.print("quat\t"); - Serial.print(q.w); - Serial.print("\t"); - Serial.print(q.x); - Serial.print("\t"); - Serial.print(q.y); - Serial.print("\t"); - Serial.println(q.z); - #endif - - #ifdef OUTPUT_READABLE_EULER - // display Euler angles in degrees - mpu.dmpGetQuaternion(&q, fifoBuffer); - mpu.dmpGetEuler(euler, &q); - Serial.print("euler\t"); - Serial.print(euler[0] * 180/M_PI); - Serial.print("\t"); - Serial.print(euler[1] * 180/M_PI); - Serial.print("\t"); - Serial.println(euler[2] * 180/M_PI); - #endif - - #ifdef OUTPUT_READABLE_YAWPITCHROLL - // display Euler angles in degrees - mpu.dmpGetQuaternion(&q, fifoBuffer); - mpu.dmpGetGravity(&gravity, &q); - mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); - Serial.print("ypr\t"); - Serial.print(ypr[0] * 180/M_PI); - Serial.print("\t"); - Serial.print(ypr[1] * 180/M_PI); - Serial.print("\t"); - Serial.print(ypr[2] * 180/M_PI); - /* - mpu.dmpGetAccel(&aa, fifoBuffer); - Serial.print("\tRaw Accl XYZ\t"); - Serial.print(aa.x); - Serial.print("\t"); - Serial.print(aa.y); - Serial.print("\t"); - Serial.print(aa.z); - mpu.dmpGetGyro(&gy, fifoBuffer); - Serial.print("\tRaw Gyro XYZ\t"); - Serial.print(gy.x); - Serial.print("\t"); - Serial.print(gy.y); - Serial.print("\t"); - Serial.print(gy.z); - */ - Serial.println(); - - #endif - - #ifdef OUTPUT_READABLE_REALACCEL - // display real acceleration, adjusted to remove gravity - mpu.dmpGetQuaternion(&q, fifoBuffer); - mpu.dmpGetAccel(&aa, fifoBuffer); - mpu.dmpGetGravity(&gravity, &q); - mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity); - Serial.print("areal\t"); - Serial.print(aaReal.x); - Serial.print("\t"); - Serial.print(aaReal.y); - Serial.print("\t"); - Serial.println(aaReal.z); - #endif - - #ifdef OUTPUT_READABLE_WORLDACCEL - // display initial world-frame acceleration, adjusted to remove gravity - // and rotated based on known orientation from quaternion - mpu.dmpGetQuaternion(&q, fifoBuffer); - mpu.dmpGetAccel(&aa, fifoBuffer); - mpu.dmpGetGravity(&gravity, &q); - mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity); - mpu.dmpGetLinearAccelInWorld(&aaWorld, &aaReal, &q); - Serial.print("aworld\t"); - Serial.print(aaWorld.x); - Serial.print("\t"); - Serial.print(aaWorld.y); - Serial.print("\t"); - Serial.println(aaWorld.z); - #endif - - #ifdef OUTPUT_TEAPOT - // display quaternion values in InvenSense Teapot demo format: - teapotPacket[2] = fifoBuffer[0]; - teapotPacket[3] = fifoBuffer[1]; - teapotPacket[4] = fifoBuffer[4]; - teapotPacket[5] = fifoBuffer[5]; - teapotPacket[6] = fifoBuffer[8]; - teapotPacket[7] = fifoBuffer[9]; - teapotPacket[8] = fifoBuffer[12]; - teapotPacket[9] = fifoBuffer[13]; - Serial.write(teapotPacket, 14); - teapotPacket[11]++; // packetCount, loops at 0xFF on purpose - #endif - - // blink LED to indicate activity - blinkState = !blinkState; - digitalWrite(LED_PIN, blinkState); - } + // blink LED to indicate activity + blinkState = !blinkState; + digitalWrite(LED_PIN, blinkState); + } } diff --git a/Arduino/MPU6050/examples/MPU6050_DMP6_using_DMP_V6.12/MPU6050_DMP6_using_DMP_V6.12/MPU6050_DMP6_using_DMP_V6.12.ino b/Arduino/MPU6050/examples/MPU6050_DMP6_using_DMP_V6.12/MPU6050_DMP6_using_DMP_V6.12/MPU6050_DMP6_using_DMP_V6.12.ino deleted file mode 100644 index 9a87db5c..00000000 --- a/Arduino/MPU6050/examples/MPU6050_DMP6_using_DMP_V6.12/MPU6050_DMP6_using_DMP_V6.12/MPU6050_DMP6_using_DMP_V6.12.ino +++ /dev/null @@ -1,368 +0,0 @@ -// I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class using DMP (MotionApps v6.12) -// 6/21/2012 by Jeff Rowberg -// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib -// -// Changelog: -// 2019-07-10 - Uses the new version of the DMP Firmware V6.12 -// - Note: I believe the Teapot demo is broken with this versin as -// - the fifo buffer structure has changed -// 2016-04-18 - Eliminated a potential infinite loop -// 2013-05-08 - added seamless Fastwire support -// - added note about gyro calibration -// 2012-06-21 - added note about Arduino 1.0.1 + Leonardo compatibility error -// 2012-06-20 - improved FIFO overflow handling and simplified read process -// 2012-06-19 - completely rearranged DMP initialization code and simplification -// 2012-06-13 - pull gyro and accel data from FIFO packet instead of reading directly -// 2012-06-09 - fix broken FIFO read sequence and change interrupt detection to RISING -// 2012-06-05 - add gravity-compensated initial reference frame acceleration output -// - add 3D math helper file to DMP6 example sketch -// - add Euler output and Yaw/Pitch/Roll output formats -// 2012-06-04 - remove accel offset clearing for better results (thanks Sungon Lee) -// 2012-06-01 - fixed gyro sensitivity to be 2000 deg/sec instead of 250 -// 2012-05-30 - basic DMP initialization working - -/* ============================================ - I2Cdev device library code is placed under the MIT license - Copyright (c) 2012 Jeff Rowberg - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - =============================================== -*/ - -// I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files -// for both classes must be in the include path of your project -#include "I2Cdev.h" - -#include "MPU6050_6Axis_MotionApps_V6_12.h" -//#include "MPU6050.h" // not necessary if using MotionApps include file - -// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation -// is used in I2Cdev.h -#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE -#include "Wire.h" -#endif - -// class default I2C address is 0x68 -// specific I2C addresses may be passed as a parameter here -// AD0 low = 0x68 (default for SparkFun breakout and InvenSense evaluation board) -// AD0 high = 0x69 -MPU6050 mpu; -//MPU6050 mpu(0x69); // <-- use for AD0 high - -/* ========================================================================= - NOTE: In addition to connection 3.3v, GND, SDA, and SCL, this sketch - depends on the MPU-6050's INT pin being connected to the Arduino's - external interrupt #0 pin. On the Arduino Uno and Mega 2560, this is - digital I/O pin 2. - ========================================================================= */ - -/* ========================================================================= - NOTE: Arduino v1.0.1 with the Leonardo board generates a compile error - when using Serial.write(buf, len). The Teapot output uses this method. - The solution requires a modification to the Arduino USBAPI.h file, which - is fortunately simple, but annoying. This will be fixed in the next IDE - release. For more info, see these links: - - http://arduino.cc/forum/index.php/topic,109987.0.html - http://code.google.com/p/arduino/issues/detail?id=958 - ========================================================================= */ - - - -// uncomment "OUTPUT_READABLE_QUATERNION" if you want to see the actual -// quaternion components in a [w, x, y, z] format (not best for parsing -// on a remote host such as Processing or something though) -//#define OUTPUT_READABLE_QUATERNION - -// uncomment "OUTPUT_READABLE_EULER" if you want to see Euler angles -// (in degrees) calculated from the quaternions coming from the FIFO. -// Note that Euler angles suffer from gimbal lock (for more info, see -// http://en.wikipedia.org/wiki/Gimbal_lock) -//#define OUTPUT_READABLE_EULER - -// uncomment "OUTPUT_READABLE_YAWPITCHROLL" if you want to see the yaw/ -// pitch/roll angles (in degrees) calculated from the quaternions coming -// from the FIFO. Note this also requires gravity vector calculations. -// Also note that yaw/pitch/roll angles suffer from gimbal lock (for -// more info, see: http://en.wikipedia.org/wiki/Gimbal_lock) -#define OUTPUT_READABLE_YAWPITCHROLL - -// uncomment "OUTPUT_READABLE_REALACCEL" if you want to see acceleration -// components with gravity removed. This acceleration reference frame is -// not compensated for orientation, so +X is always +X according to the -// sensor, just without the effects of gravity. If you want acceleration -// compensated for orientation, us OUTPUT_READABLE_WORLDACCEL instead. -//#define OUTPUT_READABLE_REALACCEL - -// uncomment "OUTPUT_READABLE_WORLDACCEL" if you want to see acceleration -// components with gravity removed and adjusted for the world frame of -// reference (yaw is relative to initial orientation, since no magnetometer -// is present in this case). Could be quite handy in some cases. -//#define OUTPUT_READABLE_WORLDACCEL - -// uncomment "OUTPUT_TEAPOT" if you want output that matches the -// format used for the InvenSense teapot demo -//#define OUTPUT_TEAPOT - - - -#define INTERRUPT_PIN 2 // use pin 2 on Arduino Uno & most boards -#define LED_PIN 13 // (Arduino is 13, Teensy is 11, Teensy++ is 6) -bool blinkState = false; - -// MPU control/status vars -bool dmpReady = false; // set true if DMP init was successful -uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU -uint8_t devStatus; // return status after each device operation (0 = success, !0 = error) -uint16_t packetSize; // expected DMP packet size (default is 42 bytes) -uint16_t fifoCount; // count of all bytes currently in FIFO -uint8_t fifoBuffer[64]; // FIFO storage buffer - -// orientation/motion vars -Quaternion q; // [w, x, y, z] quaternion container -VectorInt16 aa; // [x, y, z] accel sensor measurements -VectorInt16 gy; // [x, y, z] gyro sensor measurements -VectorInt16 aaReal; // [x, y, z] gravity-free accel sensor measurements -VectorInt16 aaWorld; // [x, y, z] world-frame accel sensor measurements -VectorFloat gravity; // [x, y, z] gravity vector -float euler[3]; // [psi, theta, phi] Euler angle container -float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector - -// packet structure for InvenSense teapot demo -uint8_t teapotPacket[14] = { '$', 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0x00, 0x00, '\r', '\n' }; - - - -// ================================================================ -// === INTERRUPT DETECTION ROUTINE === -// ================================================================ - -volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high -void dmpDataReady() { - mpuInterrupt = true; -} - - - -// ================================================================ -// === INITIAL SETUP === -// ================================================================ - -void setup() { - // join I2C bus (I2Cdev library doesn't do this automatically) -#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE - Wire.begin(); - Wire.setClock(400000); // 400kHz I2C clock. Comment this line if having compilation difficulties -#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE - Fastwire::setup(400, true); -#endif - - // initialize serial communication - // (115200 chosen because it is required for Teapot Demo output, but it's - // really up to you depending on your project) - Serial.begin(115200); - while (!Serial); // wait for Leonardo enumeration, others continue immediately - - // NOTE: 8MHz or slower host processors, like the Teensy @ 3.3V or Arduino - // Pro Mini running at 3.3V, cannot handle this baud rate reliably due to - // the baud timing being too misaligned with processor ticks. You must use - // 38400 or slower in these cases, or use some kind of external separate - // crystal solution for the UART timer. - - // initialize device - Serial.println(F("Initializing I2C devices...")); - mpu.initialize(); - pinMode(INTERRUPT_PIN, INPUT); - - // verify connection - Serial.println(F("Testing device connections...")); - Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed")); - - // wait for ready - Serial.println(F("\nSend any character to begin DMP programming and demo: ")); - while (Serial.available() && Serial.read()); // empty buffer - while (!Serial.available()); // wait for data - while (Serial.available() && Serial.read()); // empty buffer again - - // load and configure the DMP - Serial.println(F("Initializing DMP...")); - devStatus = mpu.dmpInitialize(); - - // supply your own gyro offsets here, scaled for min sensitivity - mpu.setXGyroOffset(51); - mpu.setYGyroOffset(8); - mpu.setZGyroOffset(21); - mpu.setXAccelOffset(1150); - mpu.setYAccelOffset(-50); - mpu.setZAccelOffset(1060); - // make sure it worked (returns 0 if so) - if (devStatus == 0) { - // Calibration Time: generate offsets and calibrate our MPU6050 - mpu.CalibrateAccel(6); - mpu.CalibrateGyro(6); - Serial.println(); - mpu.PrintActiveOffsets(); - // turn on the DMP, now that it's ready - Serial.println(F("Enabling DMP...")); - mpu.setDMPEnabled(true); - - // enable Arduino interrupt detection - Serial.print(F("Enabling interrupt detection (Arduino external interrupt ")); - Serial.print(digitalPinToInterrupt(INTERRUPT_PIN)); - Serial.println(F(")...")); - attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), dmpDataReady, RISING); - mpuIntStatus = mpu.getIntStatus(); - - // set our DMP Ready flag so the main loop() function knows it's okay to use it - Serial.println(F("DMP ready! Waiting for first interrupt...")); - dmpReady = true; - - // get expected DMP packet size for later comparison - packetSize = mpu.dmpGetFIFOPacketSize(); - } else { - // ERROR! - // 1 = initial memory load failed - // 2 = DMP configuration updates failed - // (if it's going to break, usually the code will be 1) - Serial.print(F("DMP Initialization failed (code ")); - Serial.print(devStatus); - Serial.println(F(")")); - } - - // configure LED for output - pinMode(LED_PIN, OUTPUT); -} - - - -// ================================================================ -// === MAIN PROGRAM LOOP === -// ================================================================ - -void loop() { - // if programming failed, don't try to do anything - if (!dmpReady) return; - // read a packet from FIFO - if (mpu.dmpGetCurrentFIFOPacket(fifoBuffer)) { // Get the Latest packet - -#ifdef OUTPUT_READABLE_QUATERNION - // display quaternion values in easy matrix form: w x y z - mpu.dmpGetQuaternion(&q, fifoBuffer); - Serial.print("quat\t"); - Serial.print(q.w); - Serial.print("\t"); - Serial.print(q.x); - Serial.print("\t"); - Serial.print(q.y); - Serial.print("\t"); - Serial.println(q.z); -#endif - -#ifdef OUTPUT_READABLE_EULER - // display Euler angles in degrees - mpu.dmpGetQuaternion(&q, fifoBuffer); - mpu.dmpGetEuler(euler, &q); - Serial.print("euler\t"); - Serial.print(euler[0] * 180 / M_PI); - Serial.print("\t"); - Serial.print(euler[1] * 180 / M_PI); - Serial.print("\t"); - Serial.println(euler[2] * 180 / M_PI); -#endif - -#ifdef OUTPUT_READABLE_YAWPITCHROLL - // display Euler angles in degrees - mpu.dmpGetQuaternion(&q, fifoBuffer); - mpu.dmpGetGravity(&gravity, &q); - mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); - Serial.print("ypr\t"); - Serial.print(ypr[0] * 180 / M_PI); - Serial.print("\t"); - Serial.print(ypr[1] * 180 / M_PI); - Serial.print("\t"); - Serial.print(ypr[2] * 180 / M_PI); - /* - mpu.dmpGetAccel(&aa, fifoBuffer); - Serial.print("\tRaw Accl XYZ\t"); - Serial.print(aa.x); - Serial.print("\t"); - Serial.print(aa.y); - Serial.print("\t"); - Serial.print(aa.z); - mpu.dmpGetGyro(&gy, fifoBuffer); - Serial.print("\tRaw Gyro XYZ\t"); - Serial.print(gy.x); - Serial.print("\t"); - Serial.print(gy.y); - Serial.print("\t"); - Serial.print(gy.z); - */ - Serial.println(); - -#endif - -#ifdef OUTPUT_READABLE_REALACCEL - // display real acceleration, adjusted to remove gravity - mpu.dmpGetQuaternion(&q, fifoBuffer); - mpu.dmpGetAccel(&aa, fifoBuffer); - mpu.dmpGetGravity(&gravity, &q); - mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity); - Serial.print("areal\t"); - Serial.print(aaReal.x); - Serial.print("\t"); - Serial.print(aaReal.y); - Serial.print("\t"); - Serial.println(aaReal.z); -#endif - -#ifdef OUTPUT_READABLE_WORLDACCEL - // display initial world-frame acceleration, adjusted to remove gravity - // and rotated based on known orientation from quaternion - mpu.dmpGetQuaternion(&q, fifoBuffer); - mpu.dmpGetAccel(&aa, fifoBuffer); - mpu.dmpGetGravity(&gravity, &q); - mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity); - mpu.dmpGetLinearAccelInWorld(&aaWorld, &aaReal, &q); - Serial.print("aworld\t"); - Serial.print(aaWorld.x); - Serial.print("\t"); - Serial.print(aaWorld.y); - Serial.print("\t"); - Serial.println(aaWorld.z); -#endif - -#ifdef OUTPUT_TEAPOT - // display quaternion values in InvenSense Teapot demo format: - teapotPacket[2] = fifoBuffer[0]; - teapotPacket[3] = fifoBuffer[1]; - teapotPacket[4] = fifoBuffer[4]; - teapotPacket[5] = fifoBuffer[5]; - teapotPacket[6] = fifoBuffer[8]; - teapotPacket[7] = fifoBuffer[9]; - teapotPacket[8] = fifoBuffer[12]; - teapotPacket[9] = fifoBuffer[13]; - Serial.write(teapotPacket, 14); - teapotPacket[11]++; // packetCount, loops at 0xFF on purpose -#endif - - // blink LED to indicate activity - blinkState = !blinkState; - digitalWrite(LED_PIN, blinkState); - } -} From fbde122cc56f70d9cae1c73d0296db7538e41163 Mon Sep 17 00:00:00 2001 From: Andreas Rettig Date: Fri, 21 Feb 2020 20:14:50 +0100 Subject: [PATCH 246/335] Fix missing parentheses which make fifoC always 0 or 1 and cause endless loop --- Arduino/MPU6050/MPU6050.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Arduino/MPU6050/MPU6050.cpp b/Arduino/MPU6050/MPU6050.cpp index 68841f5f..f8c127da 100644 --- a/Arduino/MPU6050/MPU6050.cpp +++ b/Arduino/MPU6050/MPU6050.cpp @@ -2761,7 +2761,7 @@ void MPU6050::getFIFOBytes(uint8_t *data, uint8_t length) { while (!(fifoC = getFIFOCount()) && ((micros() - BreakTimer) <= (11000))); // Get Next New Packet } else { //We have more than 1 packet but less than 200 bytes of data in the FIFO Buffer uint8_t Trash[BUFFER_LENGTH]; - while (fifoC = getFIFOCount() > length) { // Test each time just in case the MPU is writing to the FIFO Buffer + while ((fifoC = getFIFOCount()) > length) { // Test each time just in case the MPU is writing to the FIFO Buffer fifoC = fifoC - length; // Save the last packet uint16_t RemoveBytes; while (fifoC) { // fifo count will reach zero so this is safe From 8ab3323056201bc6d7075b41cabd3c75eae4846f Mon Sep 17 00:00:00 2001 From: Bernhard Guillon Date: Tue, 25 Feb 2020 21:19:17 +0100 Subject: [PATCH 247/335] ES32_ESP-IDF: support new cmake based buildsystem --- ESP32_ESP-IDF/components/I2Cdev/CMakeLists.txt | 3 +++ ESP32_ESP-IDF/components/MPU6050/CMakeLists.txt | 4 ++++ 2 files changed, 7 insertions(+) create mode 100644 ESP32_ESP-IDF/components/I2Cdev/CMakeLists.txt create mode 100644 ESP32_ESP-IDF/components/MPU6050/CMakeLists.txt diff --git a/ESP32_ESP-IDF/components/I2Cdev/CMakeLists.txt b/ESP32_ESP-IDF/components/I2Cdev/CMakeLists.txt new file mode 100644 index 00000000..bfe2fc9a --- /dev/null +++ b/ESP32_ESP-IDF/components/I2Cdev/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register(SRCS "I2Cdev.cpp" + INCLUDE_DIRS "." +) \ No newline at end of file diff --git a/ESP32_ESP-IDF/components/MPU6050/CMakeLists.txt b/ESP32_ESP-IDF/components/MPU6050/CMakeLists.txt new file mode 100644 index 00000000..38d04eb4 --- /dev/null +++ b/ESP32_ESP-IDF/components/MPU6050/CMakeLists.txt @@ -0,0 +1,4 @@ +idf_component_register(SRCS "MPU6050.cpp" + INCLUDE_DIRS "." + REQUIRES I2Cdev +) \ No newline at end of file From f56c546bdc242c9d7e0c1cb9840dc4ff4f607ebd Mon Sep 17 00:00:00 2001 From: Bernhard Guillon Date: Tue, 25 Feb 2020 22:01:08 +0100 Subject: [PATCH 248/335] ES32_ESP-IDF: use i2c_ack_type_t for i2c master communication --- ESP32_ESP-IDF/components/I2Cdev/I2Cdev.cpp | 4 ++-- ESP32_ESP-IDF/components/MPU6050/MPU6050.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ESP32_ESP-IDF/components/I2Cdev/I2Cdev.cpp b/ESP32_ESP-IDF/components/I2Cdev/I2Cdev.cpp index a9a9cf8d..54a92272 100644 --- a/ESP32_ESP-IDF/components/I2Cdev/I2Cdev.cpp +++ b/ESP32_ESP-IDF/components/I2Cdev/I2Cdev.cpp @@ -135,9 +135,9 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 ESP_ERROR_CHECK(i2c_master_write_byte(cmd, (devAddr << 1) | I2C_MASTER_READ, 1)); if(length>1) - ESP_ERROR_CHECK(i2c_master_read(cmd, data, length-1, 0)); + ESP_ERROR_CHECK(i2c_master_read(cmd, data, length-1, I2C_MASTER_ACK)); - ESP_ERROR_CHECK(i2c_master_read_byte(cmd, data+length-1, 1)); + ESP_ERROR_CHECK(i2c_master_read_byte(cmd, data+length-1, I2C_MASTER_NACK)); ESP_ERROR_CHECK(i2c_master_stop(cmd)); ESP_ERROR_CHECK(i2c_master_cmd_begin(I2C_NUM, cmd, 1000/portTICK_PERIOD_MS)); diff --git a/ESP32_ESP-IDF/components/MPU6050/MPU6050.cpp b/ESP32_ESP-IDF/components/MPU6050/MPU6050.cpp index 1bbbbb77..61f5c7e1 100644 --- a/ESP32_ESP-IDF/components/MPU6050/MPU6050.cpp +++ b/ESP32_ESP-IDF/components/MPU6050/MPU6050.cpp @@ -49,9 +49,9 @@ void MPU6050::ReadRegister(uint8_t reg, uint8_t *data, uint8_t len){ ESP_ERROR_CHECK(i2c_master_write_byte(cmd, (dev << 1) | I2C_MASTER_READ, 1)); if(len>1) - ESP_ERROR_CHECK(i2c_master_read(cmd, data, len, 0)); + ESP_ERROR_CHECK(i2c_master_read(cmd, data, len, I2C_MASTER_ACK)); - ESP_ERROR_CHECK(i2c_master_read_byte(cmd, data+len-1, 1)); + ESP_ERROR_CHECK(i2c_master_read_byte(cmd, data+len-1, I2C_MASTER_NACK)); ESP_ERROR_CHECK(i2c_master_stop(cmd)); ESP_ERROR_CHECK(i2c_master_cmd_begin(I2C_NUM, cmd, 1000)); From 3bf6cc9d54fd9712f78e4c2e3f05515795a6ef40 Mon Sep 17 00:00:00 2001 From: Xavier GRIFFON Date: Mon, 9 Mar 2020 21:30:17 +0100 Subject: [PATCH 249/335] Added a parameter to define the Timeout of GetCurrentFIFOPacket --- Arduino/MPU6050/MPU6050.cpp | 21 +++++++++++++++++++-- Arduino/MPU6050/MPU6050.h | 5 +++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/Arduino/MPU6050/MPU6050.cpp b/Arduino/MPU6050/MPU6050.cpp index f8c127da..64b19d12 100644 --- a/Arduino/MPU6050/MPU6050.cpp +++ b/Arduino/MPU6050/MPU6050.cpp @@ -2741,6 +2741,22 @@ void MPU6050::getFIFOBytes(uint8_t *data, uint8_t length) { } } +/** Get timeout to get a packet from FIFO buffer. + * @return Current timeout to get a packet from FIFO buffer + * @see MPU6050_FIFO_DEFAULT_TIMEOUT + */ +uint32_t MPU6050::getFIFOTimeout() { + return fifoTimeout; +} + +/** Set timeout to get a packet from FIFO buffer. + * @param New timeout to get a packet from FIFO buffer + * @see MPU6050_FIFO_DEFAULT_TIMEOUT + */ +void MPU6050::setFIFOTimeout(uint32_t fifoTimeout) { + this->fifoTimeout = fifoTimeout; +} + /** Get latest byte from FIFO buffer no matter how much time has passed. * === GetCurrentFIFOPacket === * ================================================================ @@ -2753,12 +2769,13 @@ void MPU6050::getFIFOBytes(uint8_t *data, uint8_t length) { // This section of code is for when we allowed more than 1 packet to be acquired uint32_t BreakTimer = micros(); do { + if ((micros() - BreakTimer) > (getFIFOTimeout())) return 0; if ((fifoC = getFIFOCount()) > length) { if (fifoC > 200) { // if you waited to get the FIFO buffer to > 200 bytes it will take longer to get the last packet in the FIFO Buffer than it will take to reset the buffer and wait for the next to arrive resetFIFO(); // Fixes any overflow corruption fifoC = 0; - while (!(fifoC = getFIFOCount()) && ((micros() - BreakTimer) <= (11000))); // Get Next New Packet + while (!(fifoC = getFIFOCount()) && ((micros() - BreakTimer) <= (getFIFOTimeout()))); // Get Next New Packet } else { //We have more than 1 packet but less than 200 bytes of data in the FIFO Buffer uint8_t Trash[BUFFER_LENGTH]; while ((fifoC = getFIFOCount()) > length) { // Test each time just in case the MPU is writing to the FIFO Buffer @@ -2774,7 +2791,7 @@ void MPU6050::getFIFOBytes(uint8_t *data, uint8_t length) { } if (!fifoC) return 0; // Called too early no data or we timed out after FIFO Reset // We have 1 packet - if ((micros() - BreakTimer) > (11000)) return 0; + } while (fifoC != length); getFIFOBytes(data, length); //Get 1 packet return 1; diff --git a/Arduino/MPU6050/MPU6050.h b/Arduino/MPU6050/MPU6050.h index 4be352d2..d2482650 100644 --- a/Arduino/MPU6050/MPU6050.h +++ b/Arduino/MPU6050/MPU6050.h @@ -431,6 +431,8 @@ THE SOFTWARE. #define MPU6050_DMP_MEMORY_BANK_SIZE 256 #define MPU6050_DMP_MEMORY_CHUNK_SIZE 16 +#define MPU6050_FIFO_DEFAULT_TIMEOUT 11000 + // note: DMP code memory blocks defined at end of header file class MPU6050 { @@ -717,6 +719,8 @@ class MPU6050 { int8_t GetCurrentFIFOPacket(uint8_t *data, uint8_t length); void setFIFOByte(uint8_t data); void getFIFOBytes(uint8_t *data, uint8_t length); + void setFIFOTimeout(uint32_t fifoTimeout); + uint32_t getFIFOTimeout(); // WHO_AM_I register uint8_t getDeviceID(); @@ -1032,6 +1036,7 @@ class MPU6050 { private: uint8_t devAddr; uint8_t buffer[14]; + uint32_t fifoTimeout = MPU6050_FIFO_DEFAULT_TIMEOUT; #if defined(MPU6050_INCLUDE_DMP_MOTIONAPPS20) or defined(MPU6050_INCLUDE_DMP_MOTIONAPPS41) uint8_t *dmpPacketBuffer; uint16_t dmpPacketSize; From 34247f688770c9e19c0b1315ba8d42dbc96bcba6 Mon Sep 17 00:00:00 2001 From: Xavier GRIFFON Date: Wed, 11 Mar 2020 20:09:39 +0100 Subject: [PATCH 250/335] Check if packet received before checking timeout --- Arduino/MPU6050/MPU6050.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Arduino/MPU6050/MPU6050.cpp b/Arduino/MPU6050/MPU6050.cpp index 64b19d12..425af4c6 100644 --- a/Arduino/MPU6050/MPU6050.cpp +++ b/Arduino/MPU6050/MPU6050.cpp @@ -2768,8 +2768,8 @@ void MPU6050::setFIFOTimeout(uint32_t fifoTimeout) { int16_t fifoC; // This section of code is for when we allowed more than 1 packet to be acquired uint32_t BreakTimer = micros(); + bool packetReceived = false; do { - if ((micros() - BreakTimer) > (getFIFOTimeout())) return 0; if ((fifoC = getFIFOCount()) > length) { if (fifoC > 200) { // if you waited to get the FIFO buffer to > 200 bytes it will take longer to get the last packet in the FIFO Buffer than it will take to reset the buffer and wait for the next to arrive @@ -2791,8 +2791,9 @@ void MPU6050::setFIFOTimeout(uint32_t fifoTimeout) { } if (!fifoC) return 0; // Called too early no data or we timed out after FIFO Reset // We have 1 packet - - } while (fifoC != length); + packetReceived = fifoC == length; + if (!packetReceived && (micros() - BreakTimer) > (getFIFOTimeout())) return 0; + } while (!packetReceived); getFIFOBytes(data, length); //Get 1 packet return 1; } From 788ecc1614a189ab0fc894ae7d2c7144742922c0 Mon Sep 17 00:00:00 2001 From: Josef Adamcik Date: Sun, 19 Apr 2020 12:01:55 +0200 Subject: [PATCH 251/335] Allow MPU6050 for Arduino to compile on ESP32 with arduino core including DMP support --- Arduino/MPU6050/MPU6050.h | 5 +++++ Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h | 2 ++ Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h | 4 +++- Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h | 2 ++ 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/Arduino/MPU6050/MPU6050.h b/Arduino/MPU6050/MPU6050.h index 4be352d2..bab7ec2c 100644 --- a/Arduino/MPU6050/MPU6050.h +++ b/Arduino/MPU6050/MPU6050.h @@ -44,6 +44,11 @@ THE SOFTWARE. #ifdef __AVR__ #include +#elif defined(ESP32) + #include + #ifndef BUFFER_LENGTH + #define BUFFER_LENGTH 32 + #endif #else //#define PROGMEM /* empty */ //#define pgm_read_byte(x) (*(x)) diff --git a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h index 5572d1aa..0f7f08a5 100644 --- a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h +++ b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h @@ -47,6 +47,8 @@ THE SOFTWARE. // http://forum.arduino.cc/index.php?topic=129407.0 #ifdef __AVR__ #include +#elif defined(ESP32) + #include #else // Teensy 3.0 library conditional PROGMEM code from Paul Stoffregen #ifndef __PGMSPACE_H_ diff --git a/Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h b/Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h index 822fa171..2595f4b5 100644 --- a/Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h +++ b/Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h @@ -49,7 +49,9 @@ THE SOFTWARE. // Tom Carpenter's conditional PROGMEM code // http://forum.arduino.cc/index.php?topic=129407.0 #ifdef __AVR__ - #include + #include . +#elif defined(ESP32) + #include #else // Teensy 3.0 library conditional PROGMEM code from Paul Stoffregen #ifndef __PGMSPACE_H_ diff --git a/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h b/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h index 763a49b9..3e2608b7 100644 --- a/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h +++ b/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h @@ -45,6 +45,8 @@ THE SOFTWARE. // http://forum.arduino.cc/index.php?topic=129407.0 #ifdef __AVR__ #include +#elif defined(ESP32) + #include #else // Teensy 3.0 library conditional PROGMEM code from Paul Stoffregen #ifndef __PGMSPACE_H_ From c20923d2442013a2f01fe2eb81aca1216ee22ebd Mon Sep 17 00:00:00 2001 From: Shreyas Gokhale Date: Mon, 25 May 2020 12:20:59 +0200 Subject: [PATCH 252/335] ES32_ESP-IDF: Updated includes in example code --- ESP32_ESP-IDF/main/example.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ESP32_ESP-IDF/main/example.cpp b/ESP32_ESP-IDF/main/example.cpp index 9a5340c0..befaacc5 100644 --- a/ESP32_ESP-IDF/main/example.cpp +++ b/ESP32_ESP-IDF/main/example.cpp @@ -9,7 +9,7 @@ #include #include #include -#include "mpu6050.h" +#include "MPU6050.h" #include "MPU6050_6Axis_MotionApps20.h" #include "sdkconfig.h" From 2b05015f951c3c6df18dac1c13524ed6e8275a60 Mon Sep 17 00:00:00 2001 From: Kirk Rudolph <17368049+kirkrudolph@users.noreply.github.com> Date: Sun, 7 Jun 2020 22:32:53 -0500 Subject: [PATCH 253/335] Added and --- ESP32_ESP-IDF/CMakeLists.txt | 8 ++++++++ ESP32_ESP-IDF/main/CMakeLists.txt | 4 ++++ 2 files changed, 12 insertions(+) create mode 100644 ESP32_ESP-IDF/CMakeLists.txt create mode 100644 ESP32_ESP-IDF/main/CMakeLists.txt diff --git a/ESP32_ESP-IDF/CMakeLists.txt b/ESP32_ESP-IDF/CMakeLists.txt new file mode 100644 index 00000000..d31555b9 --- /dev/null +++ b/ESP32_ESP-IDF/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.5) + + + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(ESP32_ESP-IDF) \ No newline at end of file diff --git a/ESP32_ESP-IDF/main/CMakeLists.txt b/ESP32_ESP-IDF/main/CMakeLists.txt new file mode 100644 index 00000000..b3f17500 --- /dev/null +++ b/ESP32_ESP-IDF/main/CMakeLists.txt @@ -0,0 +1,4 @@ +set(COMPONENT_SRCS "main.cpp example.cpp") +set(COMPONENT_ADD_INCLUDEDIRS ".") + +register_component() From 2e62dd3eb05bc205c68feaa2533894b7135595ff Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 15 Sep 2020 15:46:43 +0200 Subject: [PATCH 254/335] remove unused Arduino functions for RPi --- RaspberryPi_bcm2835/MPU6050/MPU6050.cpp | 3213 +++++++++++++++++ RaspberryPi_bcm2835/MPU6050/MPU6050.h | 1032 ++++++ .../MPU6050/examples/IMU_zero.cpp | 349 ++ .../MPU6050/examples/MPU6050_example_1.cpp | 2 +- 4 files changed, 4595 insertions(+), 1 deletion(-) create mode 100644 RaspberryPi_bcm2835/MPU6050/MPU6050.cpp create mode 100644 RaspberryPi_bcm2835/MPU6050/MPU6050.h create mode 100644 RaspberryPi_bcm2835/MPU6050/examples/IMU_zero.cpp diff --git a/RaspberryPi_bcm2835/MPU6050/MPU6050.cpp b/RaspberryPi_bcm2835/MPU6050/MPU6050.cpp new file mode 100644 index 00000000..fe433e9f --- /dev/null +++ b/RaspberryPi_bcm2835/MPU6050/MPU6050.cpp @@ -0,0 +1,3213 @@ +// I2Cdev library collection - MPU6050 I2C device class +// Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00) +// 8/24/2011 by Jeff Rowberg +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// ... - ongoing debug release + +// NOTE: THIS IS ONLY A PARIAL RELEASE. THIS DEVICE CLASS IS CURRENTLY UNDERGOING ACTIVE +// DEVELOPMENT AND IS STILL MISSING SOME IMPORTANT FEATURES. PLEASE KEEP THIS IN MIND IF +// YOU DECIDE TO USE THIS PARTICULAR CODE FOR ANYTHING. + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2012 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#include "MPU6050.h" + +/** Default constructor, uses default I2C address. + * @see MPU6050_DEFAULT_ADDRESS + */ +MPU6050::MPU6050() { + devAddr = MPU6050_DEFAULT_ADDRESS; +} + +/** Specific address constructor. + * @param address I2C address + * @see MPU6050_DEFAULT_ADDRESS + * @see MPU6050_ADDRESS_AD0_LOW + * @see MPU6050_ADDRESS_AD0_HIGH + */ +MPU6050::MPU6050(uint8_t address) { + devAddr = address; +} + +/** Power on and prepare for general usage. + * This will activate the device and take it out of sleep mode (which must be done + * after start-up). This function also sets both the accelerometer and the gyroscope + * to their most sensitive settings, namely +/- 2g and +/- 250 degrees/sec, and sets + * the clock source to use the X Gyro for reference, which is slightly better than + * the default internal clock source. + */ +void MPU6050::initialize() { + setClockSource(MPU6050_CLOCK_PLL_XGYRO); + setFullScaleGyroRange(MPU6050_GYRO_FS_250); + setFullScaleAccelRange(MPU6050_ACCEL_FS_2); + setSleepEnabled(false); // thanks to Jack Elston for pointing this one out! +} + +/** Verify the I2C connection. + * Make sure the device is connected and responds as expected. + * @return True if connection is valid, false otherwise + */ +bool MPU6050::testConnection() { + return getDeviceID() == 0x34; +} + +// AUX_VDDIO register (InvenSense demo code calls this RA_*G_OFFS_TC) + +/** Get the auxiliary I2C supply voltage level. + * When set to 1, the auxiliary I2C bus high logic level is VDD. When cleared to + * 0, the auxiliary I2C bus high logic level is VLOGIC. This does not apply to + * the MPU-6000, which does not have a VLOGIC pin. + * @return I2C supply voltage level (0=VLOGIC, 1=VDD) + */ +uint8_t MPU6050::getAuxVDDIOLevel() { + I2Cdev::readBit(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_PWR_MODE_BIT, buffer); + return buffer[0]; +} +/** Set the auxiliary I2C supply voltage level. + * When set to 1, the auxiliary I2C bus high logic level is VDD. When cleared to + * 0, the auxiliary I2C bus high logic level is VLOGIC. This does not apply to + * the MPU-6000, which does not have a VLOGIC pin. + * @param level I2C supply voltage level (0=VLOGIC, 1=VDD) + */ +void MPU6050::setAuxVDDIOLevel(uint8_t level) { + I2Cdev::writeBit(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_PWR_MODE_BIT, level); +} + +// SMPLRT_DIV register + +/** Get gyroscope output rate divider. + * The sensor register output, FIFO output, DMP sampling, Motion detection, Zero + * Motion detection, and Free Fall detection are all based on the Sample Rate. + * The Sample Rate is generated by dividing the gyroscope output rate by + * SMPLRT_DIV: + * + * Sample Rate = Gyroscope Output Rate / (1 + SMPLRT_DIV) + * + * where Gyroscope Output Rate = 8kHz when the DLPF is disabled (DLPF_CFG = 0 or + * 7), and 1kHz when the DLPF is enabled (see Register 26). + * + * Note: The accelerometer output rate is 1kHz. This means that for a Sample + * Rate greater than 1kHz, the same accelerometer sample may be output to the + * FIFO, DMP, and sensor registers more than once. + * + * For a diagram of the gyroscope and accelerometer signal paths, see Section 8 + * of the MPU-6000/MPU-6050 Product Specification document. + * + * @return Current sample rate + * @see MPU6050_RA_SMPLRT_DIV + */ +uint8_t MPU6050::getRate() { + I2Cdev::readByte(devAddr, MPU6050_RA_SMPLRT_DIV, buffer); + return buffer[0]; +} +/** Set gyroscope sample rate divider. + * @param rate New sample rate divider + * @see getRate() + * @see MPU6050_RA_SMPLRT_DIV + */ +void MPU6050::setRate(uint8_t rate) { + I2Cdev::writeByte(devAddr, MPU6050_RA_SMPLRT_DIV, rate); +} + +// CONFIG register + +/** Get external FSYNC configuration. + * Configures the external Frame Synchronization (FSYNC) pin sampling. An + * external signal connected to the FSYNC pin can be sampled by configuring + * EXT_SYNC_SET. Signal changes to the FSYNC pin are latched so that short + * strobes may be captured. The latched FSYNC signal will be sampled at the + * Sampling Rate, as defined in register 25. After sampling, the latch will + * reset to the current FSYNC signal state. + * + * The sampled value will be reported in place of the least significant bit in + * a sensor data register determined by the value of EXT_SYNC_SET according to + * the following table. + * + *
+ * EXT_SYNC_SET | FSYNC Bit Location
+ * -------------+-------------------
+ * 0            | Input disabled
+ * 1            | TEMP_OUT_L[0]
+ * 2            | GYRO_XOUT_L[0]
+ * 3            | GYRO_YOUT_L[0]
+ * 4            | GYRO_ZOUT_L[0]
+ * 5            | ACCEL_XOUT_L[0]
+ * 6            | ACCEL_YOUT_L[0]
+ * 7            | ACCEL_ZOUT_L[0]
+ * 
+ * + * @return FSYNC configuration value + */ +uint8_t MPU6050::getExternalFrameSync() { + I2Cdev::readBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_EXT_SYNC_SET_BIT, MPU6050_CFG_EXT_SYNC_SET_LENGTH, buffer); + return buffer[0]; +} +/** Set external FSYNC configuration. + * @see getExternalFrameSync() + * @see MPU6050_RA_CONFIG + * @param sync New FSYNC configuration value + */ +void MPU6050::setExternalFrameSync(uint8_t sync) { + I2Cdev::writeBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_EXT_SYNC_SET_BIT, MPU6050_CFG_EXT_SYNC_SET_LENGTH, sync); +} +/** Get digital low-pass filter configuration. + * The DLPF_CFG parameter sets the digital low pass filter configuration. It + * also determines the internal sampling rate used by the device as shown in + * the table below. + * + * Note: The accelerometer output rate is 1kHz. This means that for a Sample + * Rate greater than 1kHz, the same accelerometer sample may be output to the + * FIFO, DMP, and sensor registers more than once. + * + *
+ *          |   ACCELEROMETER    |           GYROSCOPE
+ * DLPF_CFG | Bandwidth | Delay  | Bandwidth | Delay  | Sample Rate
+ * ---------+-----------+--------+-----------+--------+-------------
+ * 0        | 260Hz     | 0ms    | 256Hz     | 0.98ms | 8kHz
+ * 1        | 184Hz     | 2.0ms  | 188Hz     | 1.9ms  | 1kHz
+ * 2        | 94Hz      | 3.0ms  | 98Hz      | 2.8ms  | 1kHz
+ * 3        | 44Hz      | 4.9ms  | 42Hz      | 4.8ms  | 1kHz
+ * 4        | 21Hz      | 8.5ms  | 20Hz      | 8.3ms  | 1kHz
+ * 5        | 10Hz      | 13.8ms | 10Hz      | 13.4ms | 1kHz
+ * 6        | 5Hz       | 19.0ms | 5Hz       | 18.6ms | 1kHz
+ * 7        |   -- Reserved --   |   -- Reserved --   | Reserved
+ * 
+ * + * @return DLFP configuration + * @see MPU6050_RA_CONFIG + * @see MPU6050_CFG_DLPF_CFG_BIT + * @see MPU6050_CFG_DLPF_CFG_LENGTH + */ +uint8_t MPU6050::getDLPFMode() { + I2Cdev::readBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_DLPF_CFG_BIT, MPU6050_CFG_DLPF_CFG_LENGTH, buffer); + return buffer[0]; +} +/** Set digital low-pass filter configuration. + * @param mode New DLFP configuration setting + * @see getDLPFBandwidth() + * @see MPU6050_DLPF_BW_256 + * @see MPU6050_RA_CONFIG + * @see MPU6050_CFG_DLPF_CFG_BIT + * @see MPU6050_CFG_DLPF_CFG_LENGTH + */ +void MPU6050::setDLPFMode(uint8_t mode) { + I2Cdev::writeBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_DLPF_CFG_BIT, MPU6050_CFG_DLPF_CFG_LENGTH, mode); +} + +// GYRO_CONFIG register + +/** Get full-scale gyroscope range. + * The FS_SEL parameter allows setting the full-scale range of the gyro sensors, + * as described in the table below. + * + *
+ * 0 = +/- 250 degrees/sec
+ * 1 = +/- 500 degrees/sec
+ * 2 = +/- 1000 degrees/sec
+ * 3 = +/- 2000 degrees/sec
+ * 
+ * + * @return Current full-scale gyroscope range setting + * @see MPU6050_GYRO_FS_250 + * @see MPU6050_RA_GYRO_CONFIG + * @see MPU6050_GCONFIG_FS_SEL_BIT + * @see MPU6050_GCONFIG_FS_SEL_LENGTH + */ +uint8_t MPU6050::getFullScaleGyroRange() { + I2Cdev::readBits(devAddr, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, buffer); + return buffer[0]; +} +/** Set full-scale gyroscope range. + * @param range New full-scale gyroscope range value + * @see getFullScaleRange() + * @see MPU6050_GYRO_FS_250 + * @see MPU6050_RA_GYRO_CONFIG + * @see MPU6050_GCONFIG_FS_SEL_BIT + * @see MPU6050_GCONFIG_FS_SEL_LENGTH + */ +void MPU6050::setFullScaleGyroRange(uint8_t range) { + I2Cdev::writeBits(devAddr, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, range); +} + +// SELF TEST FACTORY TRIM VALUES + +/** Get self-test factory trim value for accelerometer X axis. + * @return factory trim value + * @see MPU6050_RA_SELF_TEST_X + */ +uint8_t MPU6050::getAccelXSelfTestFactoryTrim() { + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_X, &buffer[0]); + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_A, &buffer[1]); + return (buffer[0]>>3) | ((buffer[1]>>4) & 0x03); +} + +/** Get self-test factory trim value for accelerometer Y axis. + * @return factory trim value + * @see MPU6050_RA_SELF_TEST_Y + */ +uint8_t MPU6050::getAccelYSelfTestFactoryTrim() { + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_Y, &buffer[0]); + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_A, &buffer[1]); + return (buffer[0]>>3) | ((buffer[1]>>2) & 0x03); +} + +/** Get self-test factory trim value for accelerometer Z axis. + * @return factory trim value + * @see MPU6050_RA_SELF_TEST_Z + */ +uint8_t MPU6050::getAccelZSelfTestFactoryTrim() { + I2Cdev::readBytes(devAddr, MPU6050_RA_SELF_TEST_Z, 2, buffer); + return (buffer[0]>>3) | (buffer[1] & 0x03); +} + +/** Get self-test factory trim value for gyro X axis. + * @return factory trim value + * @see MPU6050_RA_SELF_TEST_X + */ +uint8_t MPU6050::getGyroXSelfTestFactoryTrim() { + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_X, buffer); + return (buffer[0] & 0x1F); +} + +/** Get self-test factory trim value for gyro Y axis. + * @return factory trim value + * @see MPU6050_RA_SELF_TEST_Y + */ +uint8_t MPU6050::getGyroYSelfTestFactoryTrim() { + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_Y, buffer); + return (buffer[0] & 0x1F); +} + +/** Get self-test factory trim value for gyro Z axis. + * @return factory trim value + * @see MPU6050_RA_SELF_TEST_Z + */ +uint8_t MPU6050::getGyroZSelfTestFactoryTrim() { + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_Z, buffer); + return (buffer[0] & 0x1F); +} + +// ACCEL_CONFIG register + +/** Get self-test enabled setting for accelerometer X axis. + * @return Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +bool MPU6050::getAccelXSelfTest() { + I2Cdev::readBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_XA_ST_BIT, buffer); + return buffer[0]; +} +/** Get self-test enabled setting for accelerometer X axis. + * @param enabled Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050::setAccelXSelfTest(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_XA_ST_BIT, enabled); +} +/** Get self-test enabled value for accelerometer Y axis. + * @return Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +bool MPU6050::getAccelYSelfTest() { + I2Cdev::readBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_YA_ST_BIT, buffer); + return buffer[0]; +} +/** Get self-test enabled value for accelerometer Y axis. + * @param enabled Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050::setAccelYSelfTest(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_YA_ST_BIT, enabled); +} +/** Get self-test enabled value for accelerometer Z axis. + * @return Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +bool MPU6050::getAccelZSelfTest() { + I2Cdev::readBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ZA_ST_BIT, buffer); + return buffer[0]; +} +/** Set self-test enabled value for accelerometer Z axis. + * @param enabled Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050::setAccelZSelfTest(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ZA_ST_BIT, enabled); +} +/** Get full-scale accelerometer range. + * The FS_SEL parameter allows setting the full-scale range of the accelerometer + * sensors, as described in the table below. + * + *
+ * 0 = +/- 2g
+ * 1 = +/- 4g
+ * 2 = +/- 8g
+ * 3 = +/- 16g
+ * 
+ * + * @return Current full-scale accelerometer range setting + * @see MPU6050_ACCEL_FS_2 + * @see MPU6050_RA_ACCEL_CONFIG + * @see MPU6050_ACONFIG_AFS_SEL_BIT + * @see MPU6050_ACONFIG_AFS_SEL_LENGTH + */ +uint8_t MPU6050::getFullScaleAccelRange() { + I2Cdev::readBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, buffer); + return buffer[0]; +} +/** Set full-scale accelerometer range. + * @param range New full-scale accelerometer range setting + * @see getFullScaleAccelRange() + */ +void MPU6050::setFullScaleAccelRange(uint8_t range) { + I2Cdev::writeBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, range); +} +/** Get the high-pass filter configuration. + * The DHPF is a filter module in the path leading to motion detectors (Free + * Fall, Motion threshold, and Zero Motion). The high pass filter output is not + * available to the data registers (see Figure in Section 8 of the MPU-6000/ + * MPU-6050 Product Specification document). + * + * The high pass filter has three modes: + * + *
+ *    Reset: The filter output settles to zero within one sample. This
+ *           effectively disables the high pass filter. This mode may be toggled
+ *           to quickly settle the filter.
+ *
+ *    On:    The high pass filter will pass signals above the cut off frequency.
+ *
+ *    Hold:  When triggered, the filter holds the present sample. The filter
+ *           output will be the difference between the input sample and the held
+ *           sample.
+ * 
+ * + *
+ * ACCEL_HPF | Filter Mode | Cut-off Frequency
+ * ----------+-------------+------------------
+ * 0         | Reset       | None
+ * 1         | On          | 5Hz
+ * 2         | On          | 2.5Hz
+ * 3         | On          | 1.25Hz
+ * 4         | On          | 0.63Hz
+ * 7         | Hold        | None
+ * 
+ * + * @return Current high-pass filter configuration + * @see MPU6050_DHPF_RESET + * @see MPU6050_RA_ACCEL_CONFIG + */ +uint8_t MPU6050::getDHPFMode() { + I2Cdev::readBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ACCEL_HPF_BIT, MPU6050_ACONFIG_ACCEL_HPF_LENGTH, buffer); + return buffer[0]; +} +/** Set the high-pass filter configuration. + * @param bandwidth New high-pass filter configuration + * @see setDHPFMode() + * @see MPU6050_DHPF_RESET + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050::setDHPFMode(uint8_t bandwidth) { + I2Cdev::writeBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ACCEL_HPF_BIT, MPU6050_ACONFIG_ACCEL_HPF_LENGTH, bandwidth); +} + +// FF_THR register + +/** Get free-fall event acceleration threshold. + * This register configures the detection threshold for Free Fall event + * detection. The unit of FF_THR is 1LSB = 2mg. Free Fall is detected when the + * absolute value of the accelerometer measurements for the three axes are each + * less than the detection threshold. This condition increments the Free Fall + * duration counter (Register 30). The Free Fall interrupt is triggered when the + * Free Fall duration counter reaches the time specified in FF_DUR. + * + * For more details on the Free Fall detection interrupt, see Section 8.2 of the + * MPU-6000/MPU-6050 Product Specification document as well as Registers 56 and + * 58 of this document. + * + * @return Current free-fall acceleration threshold value (LSB = 2mg) + * @see MPU6050_RA_FF_THR + */ +uint8_t MPU6050::getFreefallDetectionThreshold() { + I2Cdev::readByte(devAddr, MPU6050_RA_FF_THR, buffer); + return buffer[0]; +} +/** Get free-fall event acceleration threshold. + * @param threshold New free-fall acceleration threshold value (LSB = 2mg) + * @see getFreefallDetectionThreshold() + * @see MPU6050_RA_FF_THR + */ +void MPU6050::setFreefallDetectionThreshold(uint8_t threshold) { + I2Cdev::writeByte(devAddr, MPU6050_RA_FF_THR, threshold); +} + +// FF_DUR register + +/** Get free-fall event duration threshold. + * This register configures the duration counter threshold for Free Fall event + * detection. The duration counter ticks at 1kHz, therefore FF_DUR has a unit + * of 1 LSB = 1 ms. + * + * The Free Fall duration counter increments while the absolute value of the + * accelerometer measurements are each less than the detection threshold + * (Register 29). The Free Fall interrupt is triggered when the Free Fall + * duration counter reaches the time specified in this register. + * + * For more details on the Free Fall detection interrupt, see Section 8.2 of + * the MPU-6000/MPU-6050 Product Specification document as well as Registers 56 + * and 58 of this document. + * + * @return Current free-fall duration threshold value (LSB = 1ms) + * @see MPU6050_RA_FF_DUR + */ +uint8_t MPU6050::getFreefallDetectionDuration() { + I2Cdev::readByte(devAddr, MPU6050_RA_FF_DUR, buffer); + return buffer[0]; +} +/** Get free-fall event duration threshold. + * @param duration New free-fall duration threshold value (LSB = 1ms) + * @see getFreefallDetectionDuration() + * @see MPU6050_RA_FF_DUR + */ +void MPU6050::setFreefallDetectionDuration(uint8_t duration) { + I2Cdev::writeByte(devAddr, MPU6050_RA_FF_DUR, duration); +} + +// MOT_THR register + +/** Get motion detection event acceleration threshold. + * This register configures the detection threshold for Motion interrupt + * generation. The unit of MOT_THR is 1LSB = 2mg. Motion is detected when the + * absolute value of any of the accelerometer measurements exceeds this Motion + * detection threshold. This condition increments the Motion detection duration + * counter (Register 32). The Motion detection interrupt is triggered when the + * Motion Detection counter reaches the time count specified in MOT_DUR + * (Register 32). + * + * The Motion interrupt will indicate the axis and polarity of detected motion + * in MOT_DETECT_STATUS (Register 97). + * + * For more details on the Motion detection interrupt, see Section 8.3 of the + * MPU-6000/MPU-6050 Product Specification document as well as Registers 56 and + * 58 of this document. + * + * @return Current motion detection acceleration threshold value (LSB = 2mg) + * @see MPU6050_RA_MOT_THR + */ +uint8_t MPU6050::getMotionDetectionThreshold() { + I2Cdev::readByte(devAddr, MPU6050_RA_MOT_THR, buffer); + return buffer[0]; +} +/** Set motion detection event acceleration threshold. + * @param threshold New motion detection acceleration threshold value (LSB = 2mg) + * @see getMotionDetectionThreshold() + * @see MPU6050_RA_MOT_THR + */ +void MPU6050::setMotionDetectionThreshold(uint8_t threshold) { + I2Cdev::writeByte(devAddr, MPU6050_RA_MOT_THR, threshold); +} + +// MOT_DUR register + +/** Get motion detection event duration threshold. + * This register configures the duration counter threshold for Motion interrupt + * generation. The duration counter ticks at 1 kHz, therefore MOT_DUR has a unit + * of 1LSB = 1ms. The Motion detection duration counter increments when the + * absolute value of any of the accelerometer measurements exceeds the Motion + * detection threshold (Register 31). The Motion detection interrupt is + * triggered when the Motion detection counter reaches the time count specified + * in this register. + * + * For more details on the Motion detection interrupt, see Section 8.3 of the + * MPU-6000/MPU-6050 Product Specification document. + * + * @return Current motion detection duration threshold value (LSB = 1ms) + * @see MPU6050_RA_MOT_DUR + */ +uint8_t MPU6050::getMotionDetectionDuration() { + I2Cdev::readByte(devAddr, MPU6050_RA_MOT_DUR, buffer); + return buffer[0]; +} +/** Set motion detection event duration threshold. + * @param duration New motion detection duration threshold value (LSB = 1ms) + * @see getMotionDetectionDuration() + * @see MPU6050_RA_MOT_DUR + */ +void MPU6050::setMotionDetectionDuration(uint8_t duration) { + I2Cdev::writeByte(devAddr, MPU6050_RA_MOT_DUR, duration); +} + +// ZRMOT_THR register + +/** Get zero motion detection event acceleration threshold. + * This register configures the detection threshold for Zero Motion interrupt + * generation. The unit of ZRMOT_THR is 1LSB = 2mg. Zero Motion is detected when + * the absolute value of the accelerometer measurements for the 3 axes are each + * less than the detection threshold. This condition increments the Zero Motion + * duration counter (Register 34). The Zero Motion interrupt is triggered when + * the Zero Motion duration counter reaches the time count specified in + * ZRMOT_DUR (Register 34). + * + * Unlike Free Fall or Motion detection, Zero Motion detection triggers an + * interrupt both when Zero Motion is first detected and when Zero Motion is no + * longer detected. + * + * When a zero motion event is detected, a Zero Motion Status will be indicated + * in the MOT_DETECT_STATUS register (Register 97). When a motion-to-zero-motion + * condition is detected, the status bit is set to 1. When a zero-motion-to- + * motion condition is detected, the status bit is set to 0. + * + * For more details on the Zero Motion detection interrupt, see Section 8.4 of + * the MPU-6000/MPU-6050 Product Specification document as well as Registers 56 + * and 58 of this document. + * + * @return Current zero motion detection acceleration threshold value (LSB = 2mg) + * @see MPU6050_RA_ZRMOT_THR + */ +uint8_t MPU6050::getZeroMotionDetectionThreshold() { + I2Cdev::readByte(devAddr, MPU6050_RA_ZRMOT_THR, buffer); + return buffer[0]; +} +/** Set zero motion detection event acceleration threshold. + * @param threshold New zero motion detection acceleration threshold value (LSB = 2mg) + * @see getZeroMotionDetectionThreshold() + * @see MPU6050_RA_ZRMOT_THR + */ +void MPU6050::setZeroMotionDetectionThreshold(uint8_t threshold) { + I2Cdev::writeByte(devAddr, MPU6050_RA_ZRMOT_THR, threshold); +} + +// ZRMOT_DUR register + +/** Get zero motion detection event duration threshold. + * This register configures the duration counter threshold for Zero Motion + * interrupt generation. The duration counter ticks at 16 Hz, therefore + * ZRMOT_DUR has a unit of 1 LSB = 64 ms. The Zero Motion duration counter + * increments while the absolute value of the accelerometer measurements are + * each less than the detection threshold (Register 33). The Zero Motion + * interrupt is triggered when the Zero Motion duration counter reaches the time + * count specified in this register. + * + * For more details on the Zero Motion detection interrupt, see Section 8.4 of + * the MPU-6000/MPU-6050 Product Specification document, as well as Registers 56 + * and 58 of this document. + * + * @return Current zero motion detection duration threshold value (LSB = 64ms) + * @see MPU6050_RA_ZRMOT_DUR + */ +uint8_t MPU6050::getZeroMotionDetectionDuration() { + I2Cdev::readByte(devAddr, MPU6050_RA_ZRMOT_DUR, buffer); + return buffer[0]; +} +/** Set zero motion detection event duration threshold. + * @param duration New zero motion detection duration threshold value (LSB = 1ms) + * @see getZeroMotionDetectionDuration() + * @see MPU6050_RA_ZRMOT_DUR + */ +void MPU6050::setZeroMotionDetectionDuration(uint8_t duration) { + I2Cdev::writeByte(devAddr, MPU6050_RA_ZRMOT_DUR, duration); +} + +// FIFO_EN register + +/** Get temperature FIFO enabled value. + * When set to 1, this bit enables TEMP_OUT_H and TEMP_OUT_L (Registers 65 and + * 66) to be written into the FIFO buffer. + * @return Current temperature FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050::getTempFIFOEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_TEMP_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set temperature FIFO enabled value. + * @param enabled New temperature FIFO enabled value + * @see getTempFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050::setTempFIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_TEMP_FIFO_EN_BIT, enabled); +} +/** Get gyroscope X-axis FIFO enabled value. + * When set to 1, this bit enables GYRO_XOUT_H and GYRO_XOUT_L (Registers 67 and + * 68) to be written into the FIFO buffer. + * @return Current gyroscope X-axis FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050::getXGyroFIFOEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_XG_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set gyroscope X-axis FIFO enabled value. + * @param enabled New gyroscope X-axis FIFO enabled value + * @see getXGyroFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050::setXGyroFIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_XG_FIFO_EN_BIT, enabled); +} +/** Get gyroscope Y-axis FIFO enabled value. + * When set to 1, this bit enables GYRO_YOUT_H and GYRO_YOUT_L (Registers 69 and + * 70) to be written into the FIFO buffer. + * @return Current gyroscope Y-axis FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050::getYGyroFIFOEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_YG_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set gyroscope Y-axis FIFO enabled value. + * @param enabled New gyroscope Y-axis FIFO enabled value + * @see getYGyroFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050::setYGyroFIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_YG_FIFO_EN_BIT, enabled); +} +/** Get gyroscope Z-axis FIFO enabled value. + * When set to 1, this bit enables GYRO_ZOUT_H and GYRO_ZOUT_L (Registers 71 and + * 72) to be written into the FIFO buffer. + * @return Current gyroscope Z-axis FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050::getZGyroFIFOEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ZG_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set gyroscope Z-axis FIFO enabled value. + * @param enabled New gyroscope Z-axis FIFO enabled value + * @see getZGyroFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050::setZGyroFIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ZG_FIFO_EN_BIT, enabled); +} +/** Get accelerometer FIFO enabled value. + * When set to 1, this bit enables ACCEL_XOUT_H, ACCEL_XOUT_L, ACCEL_YOUT_H, + * ACCEL_YOUT_L, ACCEL_ZOUT_H, and ACCEL_ZOUT_L (Registers 59 to 64) to be + * written into the FIFO buffer. + * @return Current accelerometer FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050::getAccelFIFOEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ACCEL_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set accelerometer FIFO enabled value. + * @param enabled New accelerometer FIFO enabled value + * @see getAccelFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050::setAccelFIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ACCEL_FIFO_EN_BIT, enabled); +} +/** Get Slave 2 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 2 to be written into the FIFO buffer. + * @return Current Slave 2 FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050::getSlave2FIFOEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV2_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set Slave 2 FIFO enabled value. + * @param enabled New Slave 2 FIFO enabled value + * @see getSlave2FIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050::setSlave2FIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV2_FIFO_EN_BIT, enabled); +} +/** Get Slave 1 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 1 to be written into the FIFO buffer. + * @return Current Slave 1 FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050::getSlave1FIFOEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV1_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set Slave 1 FIFO enabled value. + * @param enabled New Slave 1 FIFO enabled value + * @see getSlave1FIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050::setSlave1FIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV1_FIFO_EN_BIT, enabled); +} +/** Get Slave 0 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 0 to be written into the FIFO buffer. + * @return Current Slave 0 FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050::getSlave0FIFOEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV0_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set Slave 0 FIFO enabled value. + * @param enabled New Slave 0 FIFO enabled value + * @see getSlave0FIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050::setSlave0FIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV0_FIFO_EN_BIT, enabled); +} + +// I2C_MST_CTRL register + +/** Get multi-master enabled value. + * Multi-master capability allows multiple I2C masters to operate on the same + * bus. In circuits where multi-master capability is required, set MULT_MST_EN + * to 1. This will increase current drawn by approximately 30uA. + * + * In circuits where multi-master capability is required, the state of the I2C + * bus must always be monitored by each separate I2C Master. Before an I2C + * Master can assume arbitration of the bus, it must first confirm that no other + * I2C Master has arbitration of the bus. When MULT_MST_EN is set to 1, the + * MPU-60X0's bus arbitration detection logic is turned on, enabling it to + * detect when the bus is available. + * + * @return Current multi-master enabled value + * @see MPU6050_RA_I2C_MST_CTRL + */ +bool MPU6050::getMultiMasterEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_MULT_MST_EN_BIT, buffer); + return buffer[0]; +} +/** Set multi-master enabled value. + * @param enabled New multi-master enabled value + * @see getMultiMasterEnabled() + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050::setMultiMasterEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_MULT_MST_EN_BIT, enabled); +} +/** Get wait-for-external-sensor-data enabled value. + * When the WAIT_FOR_ES bit is set to 1, the Data Ready interrupt will be + * delayed until External Sensor data from the Slave Devices are loaded into the + * EXT_SENS_DATA registers. This is used to ensure that both the internal sensor + * data (i.e. from gyro and accel) and external sensor data have been loaded to + * their respective data registers (i.e. the data is synced) when the Data Ready + * interrupt is triggered. + * + * @return Current wait-for-external-sensor-data enabled value + * @see MPU6050_RA_I2C_MST_CTRL + */ +bool MPU6050::getWaitForExternalSensorEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_WAIT_FOR_ES_BIT, buffer); + return buffer[0]; +} +/** Set wait-for-external-sensor-data enabled value. + * @param enabled New wait-for-external-sensor-data enabled value + * @see getWaitForExternalSensorEnabled() + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050::setWaitForExternalSensorEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_WAIT_FOR_ES_BIT, enabled); +} +/** Get Slave 3 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 3 to be written into the FIFO buffer. + * @return Current Slave 3 FIFO enabled value + * @see MPU6050_RA_MST_CTRL + */ +bool MPU6050::getSlave3FIFOEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_SLV_3_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set Slave 3 FIFO enabled value. + * @param enabled New Slave 3 FIFO enabled value + * @see getSlave3FIFOEnabled() + * @see MPU6050_RA_MST_CTRL + */ +void MPU6050::setSlave3FIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_SLV_3_FIFO_EN_BIT, enabled); +} +/** Get slave read/write transition enabled value. + * The I2C_MST_P_NSR bit configures the I2C Master's transition from one slave + * read to the next slave read. If the bit equals 0, there will be a restart + * between reads. If the bit equals 1, there will be a stop followed by a start + * of the following read. When a write transaction follows a read transaction, + * the stop followed by a start of the successive write will be always used. + * + * @return Current slave read/write transition enabled value + * @see MPU6050_RA_I2C_MST_CTRL + */ +bool MPU6050::getSlaveReadWriteTransitionEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_P_NSR_BIT, buffer); + return buffer[0]; +} +/** Set slave read/write transition enabled value. + * @param enabled New slave read/write transition enabled value + * @see getSlaveReadWriteTransitionEnabled() + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050::setSlaveReadWriteTransitionEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_P_NSR_BIT, enabled); +} +/** Get I2C master clock speed. + * I2C_MST_CLK is a 4 bit unsigned value which configures a divider on the + * MPU-60X0 internal 8MHz clock. It sets the I2C master clock speed according to + * the following table: + * + *
+ * I2C_MST_CLK | I2C Master Clock Speed | 8MHz Clock Divider
+ * ------------+------------------------+-------------------
+ * 0           | 348kHz                 | 23
+ * 1           | 333kHz                 | 24
+ * 2           | 320kHz                 | 25
+ * 3           | 308kHz                 | 26
+ * 4           | 296kHz                 | 27
+ * 5           | 286kHz                 | 28
+ * 6           | 276kHz                 | 29
+ * 7           | 267kHz                 | 30
+ * 8           | 258kHz                 | 31
+ * 9           | 500kHz                 | 16
+ * 10          | 471kHz                 | 17
+ * 11          | 444kHz                 | 18
+ * 12          | 421kHz                 | 19
+ * 13          | 400kHz                 | 20
+ * 14          | 381kHz                 | 21
+ * 15          | 364kHz                 | 22
+ * 
+ * + * @return Current I2C master clock speed + * @see MPU6050_RA_I2C_MST_CTRL + */ +uint8_t MPU6050::getMasterClockSpeed() { + I2Cdev::readBits(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_CLK_BIT, MPU6050_I2C_MST_CLK_LENGTH, buffer); + return buffer[0]; +} +/** Set I2C master clock speed. + * @reparam speed Current I2C master clock speed + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050::setMasterClockSpeed(uint8_t speed) { + I2Cdev::writeBits(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_CLK_BIT, MPU6050_I2C_MST_CLK_LENGTH, speed); +} + +// I2C_SLV* registers (Slave 0-3) + +/** Get the I2C address of the specified slave (0-3). + * Note that Bit 7 (MSB) controls read/write mode. If Bit 7 is set, it's a read + * operation, and if it is cleared, then it's a write operation. The remaining + * bits (6-0) are the 7-bit device address of the slave device. + * + * In read mode, the result of the read is placed in the lowest available + * EXT_SENS_DATA register. For further information regarding the allocation of + * read results, please refer to the EXT_SENS_DATA register description + * (Registers 73 - 96). + * + * The MPU-6050 supports a total of five slaves, but Slave 4 has unique + * characteristics, and so it has its own functions (getSlave4* and setSlave4*). + * + * I2C data transactions are performed at the Sample Rate, as defined in + * Register 25. The user is responsible for ensuring that I2C data transactions + * to and from each enabled Slave can be completed within a single period of the + * Sample Rate. + * + * The I2C slave access rate can be reduced relative to the Sample Rate. This + * reduced access rate is determined by I2C_MST_DLY (Register 52). Whether a + * slave's access rate is reduced relative to the Sample Rate is determined by + * I2C_MST_DELAY_CTRL (Register 103). + * + * The processing order for the slaves is fixed. The sequence followed for + * processing the slaves is Slave 0, Slave 1, Slave 2, Slave 3 and Slave 4. If a + * particular Slave is disabled it will be skipped. + * + * Each slave can either be accessed at the sample rate or at a reduced sample + * rate. In a case where some slaves are accessed at the Sample Rate and some + * slaves are accessed at the reduced rate, the sequence of accessing the slaves + * (Slave 0 to Slave 4) is still followed. However, the reduced rate slaves will + * be skipped if their access rate dictates that they should not be accessed + * during that particular cycle. For further information regarding the reduced + * access rate, please refer to Register 52. Whether a slave is accessed at the + * Sample Rate or at the reduced rate is determined by the Delay Enable bits in + * Register 103. + * + * @param num Slave number (0-3) + * @return Current address for specified slave + * @see MPU6050_RA_I2C_SLV0_ADDR + */ +uint8_t MPU6050::getSlaveAddress(uint8_t num) { + if (num > 3) return 0; + I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV0_ADDR + num*3, buffer); + return buffer[0]; +} +/** Set the I2C address of the specified slave (0-3). + * @param num Slave number (0-3) + * @param address New address for specified slave + * @see getSlaveAddress() + * @see MPU6050_RA_I2C_SLV0_ADDR + */ +void MPU6050::setSlaveAddress(uint8_t num, uint8_t address) { + if (num > 3) return; + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV0_ADDR + num*3, address); +} +/** Get the active internal register for the specified slave (0-3). + * Read/write operations for this slave will be done to whatever internal + * register address is stored in this MPU register. + * + * The MPU-6050 supports a total of five slaves, but Slave 4 has unique + * characteristics, and so it has its own functions. + * + * @param num Slave number (0-3) + * @return Current active register for specified slave + * @see MPU6050_RA_I2C_SLV0_REG + */ +uint8_t MPU6050::getSlaveRegister(uint8_t num) { + if (num > 3) return 0; + I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV0_REG + num*3, buffer); + return buffer[0]; +} +/** Set the active internal register for the specified slave (0-3). + * @param num Slave number (0-3) + * @param reg New active register for specified slave + * @see getSlaveRegister() + * @see MPU6050_RA_I2C_SLV0_REG + */ +void MPU6050::setSlaveRegister(uint8_t num, uint8_t reg) { + if (num > 3) return; + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV0_REG + num*3, reg); +} +/** Get the enabled value for the specified slave (0-3). + * When set to 1, this bit enables Slave 0 for data transfer operations. When + * cleared to 0, this bit disables Slave 0 from data transfer operations. + * @param num Slave number (0-3) + * @return Current enabled value for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +bool MPU6050::getSlaveEnabled(uint8_t num) { + if (num > 3) return 0; + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_EN_BIT, buffer); + return buffer[0]; +} +/** Set the enabled value for the specified slave (0-3). + * @param num Slave number (0-3) + * @param enabled New enabled value for specified slave + * @see getSlaveEnabled() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050::setSlaveEnabled(uint8_t num, bool enabled) { + if (num > 3) return; + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_EN_BIT, enabled); +} +/** Get word pair byte-swapping enabled for the specified slave (0-3). + * When set to 1, this bit enables byte swapping. When byte swapping is enabled, + * the high and low bytes of a word pair are swapped. Please refer to + * I2C_SLV0_GRP for the pairing convention of the word pairs. When cleared to 0, + * bytes transferred to and from Slave 0 will be written to EXT_SENS_DATA + * registers in the order they were transferred. + * + * @param num Slave number (0-3) + * @return Current word pair byte-swapping enabled value for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +bool MPU6050::getSlaveWordByteSwap(uint8_t num) { + if (num > 3) return 0; + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_BYTE_SW_BIT, buffer); + return buffer[0]; +} +/** Set word pair byte-swapping enabled for the specified slave (0-3). + * @param num Slave number (0-3) + * @param enabled New word pair byte-swapping enabled value for specified slave + * @see getSlaveWordByteSwap() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050::setSlaveWordByteSwap(uint8_t num, bool enabled) { + if (num > 3) return; + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_BYTE_SW_BIT, enabled); +} +/** Get write mode for the specified slave (0-3). + * When set to 1, the transaction will read or write data only. When cleared to + * 0, the transaction will write a register address prior to reading or writing + * data. This should equal 0 when specifying the register address within the + * Slave device to/from which the ensuing data transaction will take place. + * + * @param num Slave number (0-3) + * @return Current write mode for specified slave (0 = register address + data, 1 = data only) + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +bool MPU6050::getSlaveWriteMode(uint8_t num) { + if (num > 3) return 0; + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_REG_DIS_BIT, buffer); + return buffer[0]; +} +/** Set write mode for the specified slave (0-3). + * @param num Slave number (0-3) + * @param mode New write mode for specified slave (0 = register address + data, 1 = data only) + * @see getSlaveWriteMode() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050::setSlaveWriteMode(uint8_t num, bool mode) { + if (num > 3) return; + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_REG_DIS_BIT, mode); +} +/** Get word pair grouping order offset for the specified slave (0-3). + * This sets specifies the grouping order of word pairs received from registers. + * When cleared to 0, bytes from register addresses 0 and 1, 2 and 3, etc (even, + * then odd register addresses) are paired to form a word. When set to 1, bytes + * from register addresses are paired 1 and 2, 3 and 4, etc. (odd, then even + * register addresses) are paired to form a word. + * + * @param num Slave number (0-3) + * @return Current word pair grouping order offset for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +bool MPU6050::getSlaveWordGroupOffset(uint8_t num) { + if (num > 3) return 0; + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_GRP_BIT, buffer); + return buffer[0]; +} +/** Set word pair grouping order offset for the specified slave (0-3). + * @param num Slave number (0-3) + * @param enabled New word pair grouping order offset for specified slave + * @see getSlaveWordGroupOffset() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050::setSlaveWordGroupOffset(uint8_t num, bool enabled) { + if (num > 3) return; + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_GRP_BIT, enabled); +} +/** Get number of bytes to read for the specified slave (0-3). + * Specifies the number of bytes transferred to and from Slave 0. Clearing this + * bit to 0 is equivalent to disabling the register by writing 0 to I2C_SLV0_EN. + * @param num Slave number (0-3) + * @return Number of bytes to read for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +uint8_t MPU6050::getSlaveDataLength(uint8_t num) { + if (num > 3) return 0; + I2Cdev::readBits(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_LEN_BIT, MPU6050_I2C_SLV_LEN_LENGTH, buffer); + return buffer[0]; +} +/** Set number of bytes to read for the specified slave (0-3). + * @param num Slave number (0-3) + * @param length Number of bytes to read for specified slave + * @see getSlaveDataLength() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050::setSlaveDataLength(uint8_t num, uint8_t length) { + if (num > 3) return; + I2Cdev::writeBits(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_LEN_BIT, MPU6050_I2C_SLV_LEN_LENGTH, length); +} + +// I2C_SLV* registers (Slave 4) + +/** Get the I2C address of Slave 4. + * Note that Bit 7 (MSB) controls read/write mode. If Bit 7 is set, it's a read + * operation, and if it is cleared, then it's a write operation. The remaining + * bits (6-0) are the 7-bit device address of the slave device. + * + * @return Current address for Slave 4 + * @see getSlaveAddress() + * @see MPU6050_RA_I2C_SLV4_ADDR + */ +uint8_t MPU6050::getSlave4Address() { + I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV4_ADDR, buffer); + return buffer[0]; +} +/** Set the I2C address of Slave 4. + * @param address New address for Slave 4 + * @see getSlave4Address() + * @see MPU6050_RA_I2C_SLV4_ADDR + */ +void MPU6050::setSlave4Address(uint8_t address) { + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV4_ADDR, address); +} +/** Get the active internal register for the Slave 4. + * Read/write operations for this slave will be done to whatever internal + * register address is stored in this MPU register. + * + * @return Current active register for Slave 4 + * @see MPU6050_RA_I2C_SLV4_REG + */ +uint8_t MPU6050::getSlave4Register() { + I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV4_REG, buffer); + return buffer[0]; +} +/** Set the active internal register for Slave 4. + * @param reg New active register for Slave 4 + * @see getSlave4Register() + * @see MPU6050_RA_I2C_SLV4_REG + */ +void MPU6050::setSlave4Register(uint8_t reg) { + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV4_REG, reg); +} +/** Set new byte to write to Slave 4. + * This register stores the data to be written into the Slave 4. If I2C_SLV4_RW + * is set 1 (set to read), this register has no effect. + * @param data New byte to write to Slave 4 + * @see MPU6050_RA_I2C_SLV4_DO + */ +void MPU6050::setSlave4OutputByte(uint8_t data) { + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV4_DO, data); +} +/** Get the enabled value for the Slave 4. + * When set to 1, this bit enables Slave 4 for data transfer operations. When + * cleared to 0, this bit disables Slave 4 from data transfer operations. + * @return Current enabled value for Slave 4 + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +bool MPU6050::getSlave4Enabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_EN_BIT, buffer); + return buffer[0]; +} +/** Set the enabled value for Slave 4. + * @param enabled New enabled value for Slave 4 + * @see getSlave4Enabled() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050::setSlave4Enabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_EN_BIT, enabled); +} +/** Get the enabled value for Slave 4 transaction interrupts. + * When set to 1, this bit enables the generation of an interrupt signal upon + * completion of a Slave 4 transaction. When cleared to 0, this bit disables the + * generation of an interrupt signal upon completion of a Slave 4 transaction. + * The interrupt status can be observed in Register 54. + * + * @return Current enabled value for Slave 4 transaction interrupts. + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +bool MPU6050::getSlave4InterruptEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_INT_EN_BIT, buffer); + return buffer[0]; +} +/** Set the enabled value for Slave 4 transaction interrupts. + * @param enabled New enabled value for Slave 4 transaction interrupts. + * @see getSlave4InterruptEnabled() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050::setSlave4InterruptEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_INT_EN_BIT, enabled); +} +/** Get write mode for Slave 4. + * When set to 1, the transaction will read or write data only. When cleared to + * 0, the transaction will write a register address prior to reading or writing + * data. This should equal 0 when specifying the register address within the + * Slave device to/from which the ensuing data transaction will take place. + * + * @return Current write mode for Slave 4 (0 = register address + data, 1 = data only) + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +bool MPU6050::getSlave4WriteMode() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_REG_DIS_BIT, buffer); + return buffer[0]; +} +/** Set write mode for the Slave 4. + * @param mode New write mode for Slave 4 (0 = register address + data, 1 = data only) + * @see getSlave4WriteMode() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050::setSlave4WriteMode(bool mode) { + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_REG_DIS_BIT, mode); +} +/** Get Slave 4 master delay value. + * This configures the reduced access rate of I2C slaves relative to the Sample + * Rate. When a slave's access rate is decreased relative to the Sample Rate, + * the slave is accessed every: + * + * 1 / (1 + I2C_MST_DLY) samples + * + * This base Sample Rate in turn is determined by SMPLRT_DIV (register 25) and + * DLPF_CFG (register 26). Whether a slave's access rate is reduced relative to + * the Sample Rate is determined by I2C_MST_DELAY_CTRL (register 103). For + * further information regarding the Sample Rate, please refer to register 25. + * + * @return Current Slave 4 master delay value + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +uint8_t MPU6050::getSlave4MasterDelay() { + I2Cdev::readBits(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_MST_DLY_BIT, MPU6050_I2C_SLV4_MST_DLY_LENGTH, buffer); + return buffer[0]; +} +/** Set Slave 4 master delay value. + * @param delay New Slave 4 master delay value + * @see getSlave4MasterDelay() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050::setSlave4MasterDelay(uint8_t delay) { + I2Cdev::writeBits(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_MST_DLY_BIT, MPU6050_I2C_SLV4_MST_DLY_LENGTH, delay); +} +/** Get last available byte read from Slave 4. + * This register stores the data read from Slave 4. This field is populated + * after a read transaction. + * @return Last available byte read from to Slave 4 + * @see MPU6050_RA_I2C_SLV4_DI + */ +uint8_t MPU6050::getSlate4InputByte() { + I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV4_DI, buffer); + return buffer[0]; +} + +// I2C_MST_STATUS register + +/** Get FSYNC interrupt status. + * This bit reflects the status of the FSYNC interrupt from an external device + * into the MPU-60X0. This is used as a way to pass an external interrupt + * through the MPU-60X0 to the host application processor. When set to 1, this + * bit will cause an interrupt if FSYNC_INT_EN is asserted in INT_PIN_CFG + * (Register 55). + * @return FSYNC interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050::getPassthroughStatus() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_PASS_THROUGH_BIT, buffer); + return buffer[0]; +} +/** Get Slave 4 transaction done status. + * Automatically sets to 1 when a Slave 4 transaction has completed. This + * triggers an interrupt if the I2C_MST_INT_EN bit in the INT_ENABLE register + * (Register 56) is asserted and if the SLV_4_DONE_INT bit is asserted in the + * I2C_SLV4_CTRL register (Register 52). + * @return Slave 4 transaction done status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050::getSlave4IsDone() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV4_DONE_BIT, buffer); + return buffer[0]; +} +/** Get master arbitration lost status. + * This bit automatically sets to 1 when the I2C Master has lost arbitration of + * the auxiliary I2C bus (an error condition). This triggers an interrupt if the + * I2C_MST_INT_EN bit in the INT_ENABLE register (Register 56) is asserted. + * @return Master arbitration lost status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050::getLostArbitration() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_LOST_ARB_BIT, buffer); + return buffer[0]; +} +/** Get Slave 4 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 4. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 4 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050::getSlave4Nack() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV4_NACK_BIT, buffer); + return buffer[0]; +} +/** Get Slave 3 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 3. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 3 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050::getSlave3Nack() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV3_NACK_BIT, buffer); + return buffer[0]; +} +/** Get Slave 2 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 2. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 2 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050::getSlave2Nack() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV2_NACK_BIT, buffer); + return buffer[0]; +} +/** Get Slave 1 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 1. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 1 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050::getSlave1Nack() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV1_NACK_BIT, buffer); + return buffer[0]; +} +/** Get Slave 0 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 0. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 0 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050::getSlave0Nack() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV0_NACK_BIT, buffer); + return buffer[0]; +} + +// INT_PIN_CFG register + +/** Get interrupt logic level mode. + * Will be set 0 for active-high, 1 for active-low. + * @return Current interrupt mode (0=active-high, 1=active-low) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_LEVEL_BIT + */ +bool MPU6050::getInterruptMode() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_LEVEL_BIT, buffer); + return buffer[0]; +} +/** Set interrupt logic level mode. + * @param mode New interrupt mode (0=active-high, 1=active-low) + * @see getInterruptMode() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_LEVEL_BIT + */ +void MPU6050::setInterruptMode(bool mode) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_LEVEL_BIT, mode); +} +/** Get interrupt drive mode. + * Will be set 0 for push-pull, 1 for open-drain. + * @return Current interrupt drive mode (0=push-pull, 1=open-drain) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_OPEN_BIT + */ +bool MPU6050::getInterruptDrive() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_OPEN_BIT, buffer); + return buffer[0]; +} +/** Set interrupt drive mode. + * @param drive New interrupt drive mode (0=push-pull, 1=open-drain) + * @see getInterruptDrive() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_OPEN_BIT + */ +void MPU6050::setInterruptDrive(bool drive) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_OPEN_BIT, drive); +} +/** Get interrupt latch mode. + * Will be set 0 for 50us-pulse, 1 for latch-until-int-cleared. + * @return Current latch mode (0=50us-pulse, 1=latch-until-int-cleared) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_LATCH_INT_EN_BIT + */ +bool MPU6050::getInterruptLatch() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_LATCH_INT_EN_BIT, buffer); + return buffer[0]; +} +/** Set interrupt latch mode. + * @param latch New latch mode (0=50us-pulse, 1=latch-until-int-cleared) + * @see getInterruptLatch() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_LATCH_INT_EN_BIT + */ +void MPU6050::setInterruptLatch(bool latch) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_LATCH_INT_EN_BIT, latch); +} +/** Get interrupt latch clear mode. + * Will be set 0 for status-read-only, 1 for any-register-read. + * @return Current latch clear mode (0=status-read-only, 1=any-register-read) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_RD_CLEAR_BIT + */ +bool MPU6050::getInterruptLatchClear() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_RD_CLEAR_BIT, buffer); + return buffer[0]; +} +/** Set interrupt latch clear mode. + * @param clear New latch clear mode (0=status-read-only, 1=any-register-read) + * @see getInterruptLatchClear() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_RD_CLEAR_BIT + */ +void MPU6050::setInterruptLatchClear(bool clear) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_RD_CLEAR_BIT, clear); +} +/** Get FSYNC interrupt logic level mode. + * @return Current FSYNC interrupt mode (0=active-high, 1=active-low) + * @see getFSyncInterruptMode() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT + */ +bool MPU6050::getFSyncInterruptLevel() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT, buffer); + return buffer[0]; +} +/** Set FSYNC interrupt logic level mode. + * @param mode New FSYNC interrupt mode (0=active-high, 1=active-low) + * @see getFSyncInterruptMode() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT + */ +void MPU6050::setFSyncInterruptLevel(bool level) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT, level); +} +/** Get FSYNC pin interrupt enabled setting. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled setting + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_EN_BIT + */ +bool MPU6050::getFSyncInterruptEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_EN_BIT, buffer); + return buffer[0]; +} +/** Set FSYNC pin interrupt enabled setting. + * @param enabled New FSYNC pin interrupt enabled setting + * @see getFSyncInterruptEnabled() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_EN_BIT + */ +void MPU6050::setFSyncInterruptEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_EN_BIT, enabled); +} +/** Get I2C bypass enabled status. + * When this bit is equal to 1 and I2C_MST_EN (Register 106 bit[5]) is equal to + * 0, the host application processor will be able to directly access the + * auxiliary I2C bus of the MPU-60X0. When this bit is equal to 0, the host + * application processor will not be able to directly access the auxiliary I2C + * bus of the MPU-60X0 regardless of the state of I2C_MST_EN (Register 106 + * bit[5]). + * @return Current I2C bypass enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_I2C_BYPASS_EN_BIT + */ +bool MPU6050::getI2CBypassEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_I2C_BYPASS_EN_BIT, buffer); + return buffer[0]; +} +/** Set I2C bypass enabled status. + * When this bit is equal to 1 and I2C_MST_EN (Register 106 bit[5]) is equal to + * 0, the host application processor will be able to directly access the + * auxiliary I2C bus of the MPU-60X0. When this bit is equal to 0, the host + * application processor will not be able to directly access the auxiliary I2C + * bus of the MPU-60X0 regardless of the state of I2C_MST_EN (Register 106 + * bit[5]). + * @param enabled New I2C bypass enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_I2C_BYPASS_EN_BIT + */ +void MPU6050::setI2CBypassEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_I2C_BYPASS_EN_BIT, enabled); +} +/** Get reference clock output enabled status. + * When this bit is equal to 1, a reference clock output is provided at the + * CLKOUT pin. When this bit is equal to 0, the clock output is disabled. For + * further information regarding CLKOUT, please refer to the MPU-60X0 Product + * Specification document. + * @return Current reference clock output enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_CLKOUT_EN_BIT + */ +bool MPU6050::getClockOutputEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_CLKOUT_EN_BIT, buffer); + return buffer[0]; +} +/** Set reference clock output enabled status. + * When this bit is equal to 1, a reference clock output is provided at the + * CLKOUT pin. When this bit is equal to 0, the clock output is disabled. For + * further information regarding CLKOUT, please refer to the MPU-60X0 Product + * Specification document. + * @param enabled New reference clock output enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_CLKOUT_EN_BIT + */ +void MPU6050::setClockOutputEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_CLKOUT_EN_BIT, enabled); +} + +// INT_ENABLE register + +/** Get full interrupt enabled status. + * Full register byte for all interrupts, for quick reading. Each bit will be + * set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +uint8_t MPU6050::getIntEnabled() { + I2Cdev::readByte(devAddr, MPU6050_RA_INT_ENABLE, buffer); + return buffer[0]; +} +/** Set full interrupt enabled status. + * Full register byte for all interrupts, for quick reading. Each bit should be + * set 0 for disabled, 1 for enabled. + * @param enabled New interrupt enabled status + * @see getIntFreefallEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +void MPU6050::setIntEnabled(uint8_t enabled) { + I2Cdev::writeByte(devAddr, MPU6050_RA_INT_ENABLE, enabled); +} +/** Get Free Fall interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +bool MPU6050::getIntFreefallEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FF_BIT, buffer); + return buffer[0]; +} +/** Set Free Fall interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntFreefallEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +void MPU6050::setIntFreefallEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FF_BIT, enabled); +} +/** Get Motion Detection interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_MOT_BIT + **/ +bool MPU6050::getIntMotionEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_MOT_BIT, buffer); + return buffer[0]; +} +/** Set Motion Detection interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntMotionEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_MOT_BIT + **/ +void MPU6050::setIntMotionEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_MOT_BIT, enabled); +} +/** Get Zero Motion Detection interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_ZMOT_BIT + **/ +bool MPU6050::getIntZeroMotionEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_ZMOT_BIT, buffer); + return buffer[0]; +} +/** Set Zero Motion Detection interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntZeroMotionEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_ZMOT_BIT + **/ +void MPU6050::setIntZeroMotionEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_ZMOT_BIT, enabled); +} +/** Get FIFO Buffer Overflow interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT + **/ +bool MPU6050::getIntFIFOBufferOverflowEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, buffer); + return buffer[0]; +} +/** Set FIFO Buffer Overflow interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntFIFOBufferOverflowEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT + **/ +void MPU6050::setIntFIFOBufferOverflowEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, enabled); +} +/** Get I2C Master interrupt enabled status. + * This enables any of the I2C Master interrupt sources to generate an + * interrupt. Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT + **/ +bool MPU6050::getIntI2CMasterEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_I2C_MST_INT_BIT, buffer); + return buffer[0]; +} +/** Set I2C Master interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntI2CMasterEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT + **/ +void MPU6050::setIntI2CMasterEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_I2C_MST_INT_BIT, enabled); +} +/** Get Data Ready interrupt enabled setting. + * This event occurs each time a write operation to all of the sensor registers + * has been completed. Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_DATA_RDY_BIT + */ +bool MPU6050::getIntDataReadyEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DATA_RDY_BIT, buffer); + return buffer[0]; +} +/** Set Data Ready interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntDataReadyEnabled() + * @see MPU6050_RA_INT_CFG + * @see MPU6050_INTERRUPT_DATA_RDY_BIT + */ +void MPU6050::setIntDataReadyEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DATA_RDY_BIT, enabled); +} + +// INT_STATUS register + +/** Get full set of interrupt status bits. + * These bits clear to 0 after the register has been read. Very useful + * for getting multiple INT statuses, since each single bit read clears + * all of them because it has to read the whole byte. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + */ +uint8_t MPU6050::getIntStatus() { + I2Cdev::readByte(devAddr, MPU6050_RA_INT_STATUS, buffer); + return buffer[0]; +} +/** Get Free Fall interrupt status. + * This bit automatically sets to 1 when a Free Fall interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_FF_BIT + */ +bool MPU6050::getIntFreefallStatus() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_FF_BIT, buffer); + return buffer[0]; +} +/** Get Motion Detection interrupt status. + * This bit automatically sets to 1 when a Motion Detection interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_MOT_BIT + */ +bool MPU6050::getIntMotionStatus() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_MOT_BIT, buffer); + return buffer[0]; +} +/** Get Zero Motion Detection interrupt status. + * This bit automatically sets to 1 when a Zero Motion Detection interrupt has + * been generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_ZMOT_BIT + */ +bool MPU6050::getIntZeroMotionStatus() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_ZMOT_BIT, buffer); + return buffer[0]; +} +/** Get FIFO Buffer Overflow interrupt status. + * This bit automatically sets to 1 when a Free Fall interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT + */ +bool MPU6050::getIntFIFOBufferOverflowStatus() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, buffer); + return buffer[0]; +} +/** Get I2C Master interrupt status. + * This bit automatically sets to 1 when an I2C Master interrupt has been + * generated. For a list of I2C Master interrupts, please refer to Register 54. + * The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT + */ +bool MPU6050::getIntI2CMasterStatus() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_I2C_MST_INT_BIT, buffer); + return buffer[0]; +} +/** Get Data Ready interrupt status. + * This bit automatically sets to 1 when a Data Ready interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_DATA_RDY_BIT + */ +bool MPU6050::getIntDataReadyStatus() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_DATA_RDY_BIT, buffer); + return buffer[0]; +} + +// ACCEL_*OUT_* registers + +/** Get raw 9-axis motion sensor readings (accel/gyro/compass). + * FUNCTION NOT FULLY IMPLEMENTED YET. + * @param ax 16-bit signed integer container for accelerometer X-axis value + * @param ay 16-bit signed integer container for accelerometer Y-axis value + * @param az 16-bit signed integer container for accelerometer Z-axis value + * @param gx 16-bit signed integer container for gyroscope X-axis value + * @param gy 16-bit signed integer container for gyroscope Y-axis value + * @param gz 16-bit signed integer container for gyroscope Z-axis value + * @param mx 16-bit signed integer container for magnetometer X-axis value + * @param my 16-bit signed integer container for magnetometer Y-axis value + * @param mz 16-bit signed integer container for magnetometer Z-axis value + * @see getMotion6() + * @see getAcceleration() + * @see getRotation() + * @see MPU6050_RA_ACCEL_XOUT_H + */ +void MPU6050::getMotion9(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz, int16_t* mx, int16_t* my, int16_t* mz) { + getMotion6(ax, ay, az, gx, gy, gz); + // TODO: magnetometer integration +} +/** Get raw 6-axis motion sensor readings (accel/gyro). + * Retrieves all currently available motion sensor values. + * @param ax 16-bit signed integer container for accelerometer X-axis value + * @param ay 16-bit signed integer container for accelerometer Y-axis value + * @param az 16-bit signed integer container for accelerometer Z-axis value + * @param gx 16-bit signed integer container for gyroscope X-axis value + * @param gy 16-bit signed integer container for gyroscope Y-axis value + * @param gz 16-bit signed integer container for gyroscope Z-axis value + * @see getAcceleration() + * @see getRotation() + * @see MPU6050_RA_ACCEL_XOUT_H + */ +void MPU6050::getMotion6(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz) { + I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_XOUT_H, 14, buffer); + *ax = (((int16_t)buffer[0]) << 8) | buffer[1]; + *ay = (((int16_t)buffer[2]) << 8) | buffer[3]; + *az = (((int16_t)buffer[4]) << 8) | buffer[5]; + *gx = (((int16_t)buffer[8]) << 8) | buffer[9]; + *gy = (((int16_t)buffer[10]) << 8) | buffer[11]; + *gz = (((int16_t)buffer[12]) << 8) | buffer[13]; +} +/** Get 3-axis accelerometer readings. + * These registers store the most recent accelerometer measurements. + * Accelerometer measurements are written to these registers at the Sample Rate + * as defined in Register 25. + * + * The accelerometer measurement registers, along with the temperature + * measurement registers, gyroscope measurement registers, and external sensor + * data registers, are composed of two sets of registers: an internal register + * set and a user-facing read register set. + * + * The data within the accelerometer sensors' internal register set is always + * updated at the Sample Rate. Meanwhile, the user-facing read register set + * duplicates the internal register set's data values whenever the serial + * interface is idle. This guarantees that a burst read of sensor registers will + * read measurements from the same sampling instant. Note that if burst reads + * are not used, the user is responsible for ensuring a set of single byte reads + * correspond to a single sampling instant by checking the Data Ready interrupt. + * + * Each 16-bit accelerometer measurement has a full scale defined in ACCEL_FS + * (Register 28). For each full scale setting, the accelerometers' sensitivity + * per LSB in ACCEL_xOUT is shown in the table below: + * + *
+ * AFS_SEL | Full Scale Range | LSB Sensitivity
+ * --------+------------------+----------------
+ * 0       | +/- 2g           | 8192 LSB/mg
+ * 1       | +/- 4g           | 4096 LSB/mg
+ * 2       | +/- 8g           | 2048 LSB/mg
+ * 3       | +/- 16g          | 1024 LSB/mg
+ * 
+ * + * @param x 16-bit signed integer container for X-axis acceleration + * @param y 16-bit signed integer container for Y-axis acceleration + * @param z 16-bit signed integer container for Z-axis acceleration + * @see MPU6050_RA_GYRO_XOUT_H + */ +void MPU6050::getAcceleration(int16_t* x, int16_t* y, int16_t* z) { + I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_XOUT_H, 6, buffer); + *x = (((int16_t)buffer[0]) << 8) | buffer[1]; + *y = (((int16_t)buffer[2]) << 8) | buffer[3]; + *z = (((int16_t)buffer[4]) << 8) | buffer[5]; +} +/** Get X-axis accelerometer reading. + * @return X-axis acceleration measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_ACCEL_XOUT_H + */ +int16_t MPU6050::getAccelerationX() { + I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_XOUT_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +/** Get Y-axis accelerometer reading. + * @return Y-axis acceleration measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_ACCEL_YOUT_H + */ +int16_t MPU6050::getAccelerationY() { + I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_YOUT_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +/** Get Z-axis accelerometer reading. + * @return Z-axis acceleration measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_ACCEL_ZOUT_H + */ +int16_t MPU6050::getAccelerationZ() { + I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_ZOUT_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} + +// TEMP_OUT_* registers + +/** Get current internal temperature. + * @return Temperature reading in 16-bit 2's complement format + * @see MPU6050_RA_TEMP_OUT_H + */ +int16_t MPU6050::getTemperature() { + I2Cdev::readBytes(devAddr, MPU6050_RA_TEMP_OUT_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} + +// GYRO_*OUT_* registers + +/** Get 3-axis gyroscope readings. + * These gyroscope measurement registers, along with the accelerometer + * measurement registers, temperature measurement registers, and external sensor + * data registers, are composed of two sets of registers: an internal register + * set and a user-facing read register set. + * The data within the gyroscope sensors' internal register set is always + * updated at the Sample Rate. Meanwhile, the user-facing read register set + * duplicates the internal register set's data values whenever the serial + * interface is idle. This guarantees that a burst read of sensor registers will + * read measurements from the same sampling instant. Note that if burst reads + * are not used, the user is responsible for ensuring a set of single byte reads + * correspond to a single sampling instant by checking the Data Ready interrupt. + * + * Each 16-bit gyroscope measurement has a full scale defined in FS_SEL + * (Register 27). For each full scale setting, the gyroscopes' sensitivity per + * LSB in GYRO_xOUT is shown in the table below: + * + *
+ * FS_SEL | Full Scale Range   | LSB Sensitivity
+ * -------+--------------------+----------------
+ * 0      | +/- 250 degrees/s  | 131 LSB/deg/s
+ * 1      | +/- 500 degrees/s  | 65.5 LSB/deg/s
+ * 2      | +/- 1000 degrees/s | 32.8 LSB/deg/s
+ * 3      | +/- 2000 degrees/s | 16.4 LSB/deg/s
+ * 
+ * + * @param x 16-bit signed integer container for X-axis rotation + * @param y 16-bit signed integer container for Y-axis rotation + * @param z 16-bit signed integer container for Z-axis rotation + * @see getMotion6() + * @see MPU6050_RA_GYRO_XOUT_H + */ +void MPU6050::getRotation(int16_t* x, int16_t* y, int16_t* z) { + I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_XOUT_H, 6, buffer); + *x = (((int16_t)buffer[0]) << 8) | buffer[1]; + *y = (((int16_t)buffer[2]) << 8) | buffer[3]; + *z = (((int16_t)buffer[4]) << 8) | buffer[5]; +} +/** Get X-axis gyroscope reading. + * @return X-axis rotation measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_GYRO_XOUT_H + */ +int16_t MPU6050::getRotationX() { + I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_XOUT_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +/** Get Y-axis gyroscope reading. + * @return Y-axis rotation measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_GYRO_YOUT_H + */ +int16_t MPU6050::getRotationY() { + I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_YOUT_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +/** Get Z-axis gyroscope reading. + * @return Z-axis rotation measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_GYRO_ZOUT_H + */ +int16_t MPU6050::getRotationZ() { + I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_ZOUT_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} + +// EXT_SENS_DATA_* registers + +/** Read single byte from external sensor data register. + * These registers store data read from external sensors by the Slave 0, 1, 2, + * and 3 on the auxiliary I2C interface. Data read by Slave 4 is stored in + * I2C_SLV4_DI (Register 53). + * + * External sensor data is written to these registers at the Sample Rate as + * defined in Register 25. This access rate can be reduced by using the Slave + * Delay Enable registers (Register 103). + * + * External sensor data registers, along with the gyroscope measurement + * registers, accelerometer measurement registers, and temperature measurement + * registers, are composed of two sets of registers: an internal register set + * and a user-facing read register set. + * + * The data within the external sensors' internal register set is always updated + * at the Sample Rate (or the reduced access rate) whenever the serial interface + * is idle. This guarantees that a burst read of sensor registers will read + * measurements from the same sampling instant. Note that if burst reads are not + * used, the user is responsible for ensuring a set of single byte reads + * correspond to a single sampling instant by checking the Data Ready interrupt. + * + * Data is placed in these external sensor data registers according to + * I2C_SLV0_CTRL, I2C_SLV1_CTRL, I2C_SLV2_CTRL, and I2C_SLV3_CTRL (Registers 39, + * 42, 45, and 48). When more than zero bytes are read (I2C_SLVx_LEN > 0) from + * an enabled slave (I2C_SLVx_EN = 1), the slave is read at the Sample Rate (as + * defined in Register 25) or delayed rate (if specified in Register 52 and + * 103). During each Sample cycle, slave reads are performed in order of Slave + * number. If all slaves are enabled with more than zero bytes to be read, the + * order will be Slave 0, followed by Slave 1, Slave 2, and Slave 3. + * + * Each enabled slave will have EXT_SENS_DATA registers associated with it by + * number of bytes read (I2C_SLVx_LEN) in order of slave number, starting from + * EXT_SENS_DATA_00. Note that this means enabling or disabling a slave may + * change the higher numbered slaves' associated registers. Furthermore, if + * fewer total bytes are being read from the external sensors as a result of + * such a change, then the data remaining in the registers which no longer have + * an associated slave device (i.e. high numbered registers) will remain in + * these previously allocated registers unless reset. + * + * If the sum of the read lengths of all SLVx transactions exceed the number of + * available EXT_SENS_DATA registers, the excess bytes will be dropped. There + * are 24 EXT_SENS_DATA registers and hence the total read lengths between all + * the slaves cannot be greater than 24 or some bytes will be lost. + * + * Note: Slave 4's behavior is distinct from that of Slaves 0-3. For further + * information regarding the characteristics of Slave 4, please refer to + * Registers 49 to 53. + * + * EXAMPLE: + * Suppose that Slave 0 is enabled with 4 bytes to be read (I2C_SLV0_EN = 1 and + * I2C_SLV0_LEN = 4) while Slave 1 is enabled with 2 bytes to be read so that + * I2C_SLV1_EN = 1 and I2C_SLV1_LEN = 2. In such a situation, EXT_SENS_DATA _00 + * through _03 will be associated with Slave 0, while EXT_SENS_DATA _04 and 05 + * will be associated with Slave 1. If Slave 2 is enabled as well, registers + * starting from EXT_SENS_DATA_06 will be allocated to Slave 2. + * + * If Slave 2 is disabled while Slave 3 is enabled in this same situation, then + * registers starting from EXT_SENS_DATA_06 will be allocated to Slave 3 + * instead. + * + * REGISTER ALLOCATION FOR DYNAMIC DISABLE VS. NORMAL DISABLE: + * If a slave is disabled at any time, the space initially allocated to the + * slave in the EXT_SENS_DATA register, will remain associated with that slave. + * This is to avoid dynamic adjustment of the register allocation. + * + * The allocation of the EXT_SENS_DATA registers is recomputed only when (1) all + * slaves are disabled, or (2) the I2C_MST_RST bit is set (Register 106). + * + * This above is also true if one of the slaves gets NACKed and stops + * functioning. + * + * @param position Starting position (0-23) + * @return Byte read from register + */ +uint8_t MPU6050::getExternalSensorByte(int position) { + I2Cdev::readByte(devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, buffer); + return buffer[0]; +} +/** Read word (2 bytes) from external sensor data registers. + * @param position Starting position (0-21) + * @return Word read from register + * @see getExternalSensorByte() + */ +uint16_t MPU6050::getExternalSensorWord(int position) { + I2Cdev::readBytes(devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, 2, buffer); + return (((uint16_t)buffer[0]) << 8) | buffer[1]; +} +/** Read double word (4 bytes) from external sensor data registers. + * @param position Starting position (0-20) + * @return Double word read from registers + * @see getExternalSensorByte() + */ +uint32_t MPU6050::getExternalSensorDWord(int position) { + I2Cdev::readBytes(devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, 4, buffer); + return (((uint32_t)buffer[0]) << 24) | (((uint32_t)buffer[1]) << 16) | (((uint16_t)buffer[2]) << 8) | buffer[3]; +} + +// MOT_DETECT_STATUS register + +/** Get full motion detection status register content (all bits). + * @return Motion detection status byte + * @see MPU6050_RA_MOT_DETECT_STATUS + */ +uint8_t MPU6050::getMotionStatus() { + I2Cdev::readByte(devAddr, MPU6050_RA_MOT_DETECT_STATUS, buffer); + return buffer[0]; +} +/** Get X-axis negative motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_XNEG_BIT + */ +bool MPU6050::getXNegMotionDetected() { + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_XNEG_BIT, buffer); + return buffer[0]; +} +/** Get X-axis positive motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_XPOS_BIT + */ +bool MPU6050::getXPosMotionDetected() { + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_XPOS_BIT, buffer); + return buffer[0]; +} +/** Get Y-axis negative motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_YNEG_BIT + */ +bool MPU6050::getYNegMotionDetected() { + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_YNEG_BIT, buffer); + return buffer[0]; +} +/** Get Y-axis positive motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_YPOS_BIT + */ +bool MPU6050::getYPosMotionDetected() { + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_YPOS_BIT, buffer); + return buffer[0]; +} +/** Get Z-axis negative motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_ZNEG_BIT + */ +bool MPU6050::getZNegMotionDetected() { + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZNEG_BIT, buffer); + return buffer[0]; +} +/** Get Z-axis positive motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_ZPOS_BIT + */ +bool MPU6050::getZPosMotionDetected() { + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZPOS_BIT, buffer); + return buffer[0]; +} +/** Get zero motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_ZRMOT_BIT + */ +bool MPU6050::getZeroMotionDetected() { + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZRMOT_BIT, buffer); + return buffer[0]; +} + +// I2C_SLV*_DO register + +/** Write byte to Data Output container for specified slave. + * This register holds the output data written into Slave when Slave is set to + * write mode. For further information regarding Slave control, please + * refer to Registers 37 to 39 and immediately following. + * @param num Slave number (0-3) + * @param data Byte to write + * @see MPU6050_RA_I2C_SLV0_DO + */ +void MPU6050::setSlaveOutputByte(uint8_t num, uint8_t data) { + if (num > 3) return; + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV0_DO + num, data); +} + +// I2C_MST_DELAY_CTRL register + +/** Get external data shadow delay enabled status. + * This register is used to specify the timing of external sensor data + * shadowing. When DELAY_ES_SHADOW is set to 1, shadowing of external + * sensor data is delayed until all data has been received. + * @return Current external data shadow delay enabled status. + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT + */ +bool MPU6050::getExternalShadowDelayEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT, buffer); + return buffer[0]; +} +/** Set external data shadow delay enabled status. + * @param enabled New external data shadow delay enabled status. + * @see getExternalShadowDelayEnabled() + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT + */ +void MPU6050::setExternalShadowDelayEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT, enabled); +} +/** Get slave delay enabled status. + * When a particular slave delay is enabled, the rate of access for the that + * slave device is reduced. When a slave's access rate is decreased relative to + * the Sample Rate, the slave is accessed every: + * + * 1 / (1 + I2C_MST_DLY) Samples + * + * This base Sample Rate in turn is determined by SMPLRT_DIV (register * 25) + * and DLPF_CFG (register 26). + * + * For further information regarding I2C_MST_DLY, please refer to register 52. + * For further information regarding the Sample Rate, please refer to register 25. + * + * @param num Slave number (0-4) + * @return Current slave delay enabled status. + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT + */ +bool MPU6050::getSlaveDelayEnabled(uint8_t num) { + // MPU6050_DELAYCTRL_I2C_SLV4_DLY_EN_BIT is 4, SLV3 is 3, etc. + if (num > 4) return 0; + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, num, buffer); + return buffer[0]; +} +/** Set slave delay enabled status. + * @param num Slave number (0-4) + * @param enabled New slave delay enabled status. + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT + */ +void MPU6050::setSlaveDelayEnabled(uint8_t num, bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, num, enabled); +} + +// SIGNAL_PATH_RESET register + +/** Reset gyroscope signal path. + * The reset will revert the signal path analog to digital converters and + * filters to their power up configurations. + * @see MPU6050_RA_SIGNAL_PATH_RESET + * @see MPU6050_PATHRESET_GYRO_RESET_BIT + */ +void MPU6050::resetGyroscopePath() { + I2Cdev::writeBit(devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_GYRO_RESET_BIT, true); +} +/** Reset accelerometer signal path. + * The reset will revert the signal path analog to digital converters and + * filters to their power up configurations. + * @see MPU6050_RA_SIGNAL_PATH_RESET + * @see MPU6050_PATHRESET_ACCEL_RESET_BIT + */ +void MPU6050::resetAccelerometerPath() { + I2Cdev::writeBit(devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_ACCEL_RESET_BIT, true); +} +/** Reset temperature sensor signal path. + * The reset will revert the signal path analog to digital converters and + * filters to their power up configurations. + * @see MPU6050_RA_SIGNAL_PATH_RESET + * @see MPU6050_PATHRESET_TEMP_RESET_BIT + */ +void MPU6050::resetTemperaturePath() { + I2Cdev::writeBit(devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_TEMP_RESET_BIT, true); +} + +// MOT_DETECT_CTRL register + +/** Get accelerometer power-on delay. + * The accelerometer data path provides samples to the sensor registers, Motion + * detection, Zero Motion detection, and Free Fall detection modules. The + * signal path contains filters which must be flushed on wake-up with new + * samples before the detection modules begin operations. The default wake-up + * delay, of 4ms can be lengthened by up to 3ms. This additional delay is + * specified in ACCEL_ON_DELAY in units of 1 LSB = 1 ms. The user may select + * any value above zero unless instructed otherwise by InvenSense. Please refer + * to Section 8 of the MPU-6000/MPU-6050 Product Specification document for + * further information regarding the detection modules. + * @return Current accelerometer power-on delay + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_ACCEL_ON_DELAY_BIT + */ +uint8_t MPU6050::getAccelerometerPowerOnDelay() { + I2Cdev::readBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_ACCEL_ON_DELAY_BIT, MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH, buffer); + return buffer[0]; +} +/** Set accelerometer power-on delay. + * @param delay New accelerometer power-on delay (0-3) + * @see getAccelerometerPowerOnDelay() + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_ACCEL_ON_DELAY_BIT + */ +void MPU6050::setAccelerometerPowerOnDelay(uint8_t delay) { + I2Cdev::writeBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_ACCEL_ON_DELAY_BIT, MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH, delay); +} +/** Get Free Fall detection counter decrement configuration. + * Detection is registered by the Free Fall detection module after accelerometer + * measurements meet their respective threshold conditions over a specified + * number of samples. When the threshold conditions are met, the corresponding + * detection counter increments by 1. The user may control the rate at which the + * detection counter decrements when the threshold condition is not met by + * configuring FF_COUNT. The decrement rate can be set according to the + * following table: + * + *
+ * FF_COUNT | Counter Decrement
+ * ---------+------------------
+ * 0        | Reset
+ * 1        | 1
+ * 2        | 2
+ * 3        | 4
+ * 
+ * + * When FF_COUNT is configured to 0 (reset), any non-qualifying sample will + * reset the counter to 0. For further information on Free Fall detection, + * please refer to Registers 29 to 32. + * + * @return Current decrement configuration + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_FF_COUNT_BIT + */ +uint8_t MPU6050::getFreefallDetectionCounterDecrement() { + I2Cdev::readBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_FF_COUNT_BIT, MPU6050_DETECT_FF_COUNT_LENGTH, buffer); + return buffer[0]; +} +/** Set Free Fall detection counter decrement configuration. + * @param decrement New decrement configuration value + * @see getFreefallDetectionCounterDecrement() + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_FF_COUNT_BIT + */ +void MPU6050::setFreefallDetectionCounterDecrement(uint8_t decrement) { + I2Cdev::writeBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_FF_COUNT_BIT, MPU6050_DETECT_FF_COUNT_LENGTH, decrement); +} +/** Get Motion detection counter decrement configuration. + * Detection is registered by the Motion detection module after accelerometer + * measurements meet their respective threshold conditions over a specified + * number of samples. When the threshold conditions are met, the corresponding + * detection counter increments by 1. The user may control the rate at which the + * detection counter decrements when the threshold condition is not met by + * configuring MOT_COUNT. The decrement rate can be set according to the + * following table: + * + *
+ * MOT_COUNT | Counter Decrement
+ * ----------+------------------
+ * 0         | Reset
+ * 1         | 1
+ * 2         | 2
+ * 3         | 4
+ * 
+ * + * When MOT_COUNT is configured to 0 (reset), any non-qualifying sample will + * reset the counter to 0. For further information on Motion detection, + * please refer to Registers 29 to 32. + * + */ +uint8_t MPU6050::getMotionDetectionCounterDecrement() { + I2Cdev::readBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_MOT_COUNT_BIT, MPU6050_DETECT_MOT_COUNT_LENGTH, buffer); + return buffer[0]; +} +/** Set Motion detection counter decrement configuration. + * @param decrement New decrement configuration value + * @see getMotionDetectionCounterDecrement() + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_MOT_COUNT_BIT + */ +void MPU6050::setMotionDetectionCounterDecrement(uint8_t decrement) { + I2Cdev::writeBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_MOT_COUNT_BIT, MPU6050_DETECT_MOT_COUNT_LENGTH, decrement); +} + +// USER_CTRL register + +/** Get FIFO enabled status. + * When this bit is set to 0, the FIFO buffer is disabled. The FIFO buffer + * cannot be written to or read from while disabled. The FIFO buffer's state + * does not change unless the MPU-60X0 is power cycled. + * @return Current FIFO enabled status + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_FIFO_EN_BIT + */ +bool MPU6050::getFIFOEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set FIFO enabled status. + * @param enabled New FIFO enabled status + * @see getFIFOEnabled() + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_FIFO_EN_BIT + */ +void MPU6050::setFIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_EN_BIT, enabled); +} +/** Get I2C Master Mode enabled status. + * When this mode is enabled, the MPU-60X0 acts as the I2C Master to the + * external sensor slave devices on the auxiliary I2C bus. When this bit is + * cleared to 0, the auxiliary I2C bus lines (AUX_DA and AUX_CL) are logically + * driven by the primary I2C bus (SDA and SCL). This is a precondition to + * enabling Bypass Mode. For further information regarding Bypass Mode, please + * refer to Register 55. + * @return Current I2C Master Mode enabled status + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_I2C_MST_EN_BIT + */ +bool MPU6050::getI2CMasterModeEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_EN_BIT, buffer); + return buffer[0]; +} +/** Set I2C Master Mode enabled status. + * @param enabled New I2C Master Mode enabled status + * @see getI2CMasterModeEnabled() + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_I2C_MST_EN_BIT + */ +void MPU6050::setI2CMasterModeEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_EN_BIT, enabled); +} +/** Switch from I2C to SPI mode (MPU-6000 only) + * If this is set, the primary SPI interface will be enabled in place of the + * disabled primary I2C interface. + */ +void MPU6050::switchSPIEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_IF_DIS_BIT, enabled); +} +/** Reset the FIFO. + * This bit resets the FIFO buffer when set to 1 while FIFO_EN equals 0. This + * bit automatically clears to 0 after the reset has been triggered. + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_FIFO_RESET_BIT + */ +void MPU6050::resetFIFO() { + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_RESET_BIT, true); +} +/** Reset the I2C Master. + * This bit resets the I2C Master when set to 1 while I2C_MST_EN equals 0. + * This bit automatically clears to 0 after the reset has been triggered. + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_I2C_MST_RESET_BIT + */ +void MPU6050::resetI2CMaster() { + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_RESET_BIT, true); +} +/** Reset all sensor registers and signal paths. + * When set to 1, this bit resets the signal paths for all sensors (gyroscopes, + * accelerometers, and temperature sensor). This operation will also clear the + * sensor registers. This bit automatically clears to 0 after the reset has been + * triggered. + * + * When resetting only the signal path (and not the sensor registers), please + * use Register 104, SIGNAL_PATH_RESET. + * + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_SIG_COND_RESET_BIT + */ +void MPU6050::resetSensors() { + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_SIG_COND_RESET_BIT, true); +} + +// PWR_MGMT_1 register + +/** Trigger a full device reset. + * A small delay of ~50ms may be desirable after triggering a reset. + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_DEVICE_RESET_BIT + */ +void MPU6050::reset() { + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_DEVICE_RESET_BIT, true); +} +/** Get sleep mode status. + * Setting the SLEEP bit in the register puts the device into very low power + * sleep mode. In this mode, only the serial interface and internal registers + * remain active, allowing for a very low standby current. Clearing this bit + * puts the device back into normal mode. To save power, the individual standby + * selections for each of the gyros should be used if any gyro axis is not used + * by the application. + * @return Current sleep mode enabled status + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_SLEEP_BIT + */ +bool MPU6050::getSleepEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, buffer); + return buffer[0]; +} +/** Set sleep mode status. + * @param enabled New sleep mode enabled status + * @see getSleepEnabled() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_SLEEP_BIT + */ +void MPU6050::setSleepEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, enabled); +} +/** Get wake cycle enabled status. + * When this bit is set to 1 and SLEEP is disabled, the MPU-60X0 will cycle + * between sleep mode and waking up to take a single sample of data from active + * sensors at a rate determined by LP_WAKE_CTRL (register 108). + * @return Current sleep mode enabled status + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CYCLE_BIT + */ +bool MPU6050::getWakeCycleEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CYCLE_BIT, buffer); + return buffer[0]; +} +/** Set wake cycle enabled status. + * @param enabled New sleep mode enabled status + * @see getWakeCycleEnabled() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CYCLE_BIT + */ +void MPU6050::setWakeCycleEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CYCLE_BIT, enabled); +} +/** Get temperature sensor enabled status. + * Control the usage of the internal temperature sensor. + * + * Note: this register stores the *disabled* value, but for consistency with the + * rest of the code, the function is named and used with standard true/false + * values to indicate whether the sensor is enabled or disabled, respectively. + * + * @return Current temperature sensor enabled status + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_TEMP_DIS_BIT + */ +bool MPU6050::getTempSensorEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_TEMP_DIS_BIT, buffer); + return buffer[0] == 0; // 1 is actually disabled here +} +/** Set temperature sensor enabled status. + * Note: this register stores the *disabled* value, but for consistency with the + * rest of the code, the function is named and used with standard true/false + * values to indicate whether the sensor is enabled or disabled, respectively. + * + * @param enabled New temperature sensor enabled status + * @see getTempSensorEnabled() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_TEMP_DIS_BIT + */ +void MPU6050::setTempSensorEnabled(bool enabled) { + // 1 is actually disabled here + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_TEMP_DIS_BIT, !enabled); +} +/** Get clock source setting. + * @return Current clock source setting + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CLKSEL_BIT + * @see MPU6050_PWR1_CLKSEL_LENGTH + */ +uint8_t MPU6050::getClockSource() { + I2Cdev::readBits(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, buffer); + return buffer[0]; +} +/** Set clock source setting. + * An internal 8MHz oscillator, gyroscope based clock, or external sources can + * be selected as the MPU-60X0 clock source. When the internal 8 MHz oscillator + * or an external source is chosen as the clock source, the MPU-60X0 can operate + * in low power modes with the gyroscopes disabled. + * + * Upon power up, the MPU-60X0 clock source defaults to the internal oscillator. + * However, it is highly recommended that the device be configured to use one of + * the gyroscopes (or an external clock source) as the clock reference for + * improved stability. The clock source can be selected according to the following table: + * + *
+ * CLK_SEL | Clock Source
+ * --------+--------------------------------------
+ * 0       | Internal oscillator
+ * 1       | PLL with X Gyro reference
+ * 2       | PLL with Y Gyro reference
+ * 3       | PLL with Z Gyro reference
+ * 4       | PLL with external 32.768kHz reference
+ * 5       | PLL with external 19.2MHz reference
+ * 6       | Reserved
+ * 7       | Stops the clock and keeps the timing generator in reset
+ * 
+ * + * @param source New clock source setting + * @see getClockSource() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CLKSEL_BIT + * @see MPU6050_PWR1_CLKSEL_LENGTH + */ +void MPU6050::setClockSource(uint8_t source) { + I2Cdev::writeBits(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, source); +} + +// PWR_MGMT_2 register + +/** Get wake frequency in Accel-Only Low Power Mode. + * The MPU-60X0 can be put into Accerlerometer Only Low Power Mode by setting + * PWRSEL to 1 in the Power Management 1 register (Register 107). In this mode, + * the device will power off all devices except for the primary I2C interface, + * waking only the accelerometer at fixed intervals to take a single + * measurement. The frequency of wake-ups can be configured with LP_WAKE_CTRL + * as shown below: + * + *
+ * LP_WAKE_CTRL | Wake-up Frequency
+ * -------------+------------------
+ * 0            | 1.25 Hz
+ * 1            | 2.5 Hz
+ * 2            | 5 Hz
+ * 3            | 10 Hz
+ * 
+ * + * For further information regarding the MPU-60X0's power modes, please refer to + * Register 107. + * + * @return Current wake frequency + * @see MPU6050_RA_PWR_MGMT_2 + */ +uint8_t MPU6050::getWakeFrequency() { + I2Cdev::readBits(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_LP_WAKE_CTRL_BIT, MPU6050_PWR2_LP_WAKE_CTRL_LENGTH, buffer); + return buffer[0]; +} +/** Set wake frequency in Accel-Only Low Power Mode. + * @param frequency New wake frequency + * @see MPU6050_RA_PWR_MGMT_2 + */ +void MPU6050::setWakeFrequency(uint8_t frequency) { + I2Cdev::writeBits(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_LP_WAKE_CTRL_BIT, MPU6050_PWR2_LP_WAKE_CTRL_LENGTH, frequency); +} + +/** Get X-axis accelerometer standby enabled status. + * If enabled, the X-axis will not gather or report data (or use power). + * @return Current X-axis standby enabled status + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_XA_BIT + */ +bool MPU6050::getStandbyXAccelEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XA_BIT, buffer); + return buffer[0]; +} +/** Set X-axis accelerometer standby enabled status. + * @param New X-axis standby enabled status + * @see getStandbyXAccelEnabled() + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_XA_BIT + */ +void MPU6050::setStandbyXAccelEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XA_BIT, enabled); +} +/** Get Y-axis accelerometer standby enabled status. + * If enabled, the Y-axis will not gather or report data (or use power). + * @return Current Y-axis standby enabled status + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_YA_BIT + */ +bool MPU6050::getStandbyYAccelEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YA_BIT, buffer); + return buffer[0]; +} +/** Set Y-axis accelerometer standby enabled status. + * @param New Y-axis standby enabled status + * @see getStandbyYAccelEnabled() + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_YA_BIT + */ +void MPU6050::setStandbyYAccelEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YA_BIT, enabled); +} +/** Get Z-axis accelerometer standby enabled status. + * If enabled, the Z-axis will not gather or report data (or use power). + * @return Current Z-axis standby enabled status + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_ZA_BIT + */ +bool MPU6050::getStandbyZAccelEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZA_BIT, buffer); + return buffer[0]; +} +/** Set Z-axis accelerometer standby enabled status. + * @param New Z-axis standby enabled status + * @see getStandbyZAccelEnabled() + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_ZA_BIT + */ +void MPU6050::setStandbyZAccelEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZA_BIT, enabled); +} +/** Get X-axis gyroscope standby enabled status. + * If enabled, the X-axis will not gather or report data (or use power). + * @return Current X-axis standby enabled status + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_XG_BIT + */ +bool MPU6050::getStandbyXGyroEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XG_BIT, buffer); + return buffer[0]; +} +/** Set X-axis gyroscope standby enabled status. + * @param New X-axis standby enabled status + * @see getStandbyXGyroEnabled() + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_XG_BIT + */ +void MPU6050::setStandbyXGyroEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XG_BIT, enabled); +} +/** Get Y-axis gyroscope standby enabled status. + * If enabled, the Y-axis will not gather or report data (or use power). + * @return Current Y-axis standby enabled status + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_YG_BIT + */ +bool MPU6050::getStandbyYGyroEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YG_BIT, buffer); + return buffer[0]; +} +/** Set Y-axis gyroscope standby enabled status. + * @param New Y-axis standby enabled status + * @see getStandbyYGyroEnabled() + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_YG_BIT + */ +void MPU6050::setStandbyYGyroEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YG_BIT, enabled); +} +/** Get Z-axis gyroscope standby enabled status. + * If enabled, the Z-axis will not gather or report data (or use power). + * @return Current Z-axis standby enabled status + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_ZG_BIT + */ +bool MPU6050::getStandbyZGyroEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZG_BIT, buffer); + return buffer[0]; +} +/** Set Z-axis gyroscope standby enabled status. + * @param New Z-axis standby enabled status + * @see getStandbyZGyroEnabled() + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_ZG_BIT + */ +void MPU6050::setStandbyZGyroEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZG_BIT, enabled); +} + +// FIFO_COUNT* registers + +/** Get current FIFO buffer size. + * This value indicates the number of bytes stored in the FIFO buffer. This + * number is in turn the number of bytes that can be read from the FIFO buffer + * and it is directly proportional to the number of samples available given the + * set of sensor data bound to be stored in the FIFO (register 35 and 36). + * @return Current FIFO buffer size + */ +uint16_t MPU6050::getFIFOCount() { + I2Cdev::readBytes(devAddr, MPU6050_RA_FIFO_COUNTH, 2, buffer); + return (((uint16_t)buffer[0]) << 8) | buffer[1]; +} + +// FIFO_R_W register + +/** Get byte from FIFO buffer. + * This register is used to read and write data from the FIFO buffer. Data is + * written to the FIFO in order of register number (from lowest to highest). If + * all the FIFO enable flags (see below) are enabled and all External Sensor + * Data registers (Registers 73 to 96) are associated with a Slave device, the + * contents of registers 59 through 96 will be written in order at the Sample + * Rate. + * + * The contents of the sensor data registers (Registers 59 to 96) are written + * into the FIFO buffer when their corresponding FIFO enable flags are set to 1 + * in FIFO_EN (Register 35). An additional flag for the sensor data registers + * associated with I2C Slave 3 can be found in I2C_MST_CTRL (Register 36). + * + * If the FIFO buffer has overflowed, the status bit FIFO_OFLOW_INT is + * automatically set to 1. This bit is located in INT_STATUS (Register 58). + * When the FIFO buffer has overflowed, the oldest data will be lost and new + * data will be written to the FIFO. + * + * If the FIFO buffer is empty, reading this register will return the last byte + * that was previously read from the FIFO until new data is available. The user + * should check FIFO_COUNT to ensure that the FIFO buffer is not read when + * empty. + * + * @return Byte from FIFO buffer + */ +uint8_t MPU6050::getFIFOByte() { + I2Cdev::readByte(devAddr, MPU6050_RA_FIFO_R_W, buffer); + return buffer[0]; +} +void MPU6050::getFIFOBytes(uint8_t *data, uint8_t length) { + if(length > 0){ + I2Cdev::readBytes(devAddr, MPU6050_RA_FIFO_R_W, length, data); + } else { + *data = 0; + } +} +/** Write byte to FIFO buffer. + * @see getFIFOByte() + * @see MPU6050_RA_FIFO_R_W + */ +void MPU6050::setFIFOByte(uint8_t data) { + I2Cdev::writeByte(devAddr, MPU6050_RA_FIFO_R_W, data); +} + +// WHO_AM_I register + +/** Get Device ID. + * This register is used to verify the identity of the device (0b110100, 0x34). + * @return Device ID (6 bits only! should be 0x34) + * @see MPU6050_RA_WHO_AM_I + * @see MPU6050_WHO_AM_I_BIT + * @see MPU6050_WHO_AM_I_LENGTH + */ +uint8_t MPU6050::getDeviceID() { + I2Cdev::readBits(devAddr, MPU6050_RA_WHO_AM_I, MPU6050_WHO_AM_I_BIT, MPU6050_WHO_AM_I_LENGTH, buffer); + return buffer[0]; +} +/** Set Device ID. + * Write a new ID into the WHO_AM_I register (no idea why this should ever be + * necessary though). + * @param id New device ID to set. + * @see getDeviceID() + * @see MPU6050_RA_WHO_AM_I + * @see MPU6050_WHO_AM_I_BIT + * @see MPU6050_WHO_AM_I_LENGTH + */ +void MPU6050::setDeviceID(uint8_t id) { + I2Cdev::writeBits(devAddr, MPU6050_RA_WHO_AM_I, MPU6050_WHO_AM_I_BIT, MPU6050_WHO_AM_I_LENGTH, id); +} + +// ======== UNDOCUMENTED/DMP REGISTERS/METHODS ======== + +// XG_OFFS_TC register + +uint8_t MPU6050::getOTPBankValid() { + I2Cdev::readBit(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OTP_BNK_VLD_BIT, buffer); + return buffer[0]; +} +void MPU6050::setOTPBankValid(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OTP_BNK_VLD_BIT, enabled); +} +int8_t MPU6050::getXGyroOffsetTC() { + I2Cdev::readBits(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, buffer); + return buffer[0]; +} +void MPU6050::setXGyroOffsetTC(int8_t offset) { + I2Cdev::writeBits(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset); +} + +// YG_OFFS_TC register + +int8_t MPU6050::getYGyroOffsetTC() { + I2Cdev::readBits(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, buffer); + return buffer[0]; +} +void MPU6050::setYGyroOffsetTC(int8_t offset) { + I2Cdev::writeBits(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset); +} + +// ZG_OFFS_TC register + +int8_t MPU6050::getZGyroOffsetTC() { + I2Cdev::readBits(devAddr, MPU6050_RA_ZG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, buffer); + return buffer[0]; +} +void MPU6050::setZGyroOffsetTC(int8_t offset) { + I2Cdev::writeBits(devAddr, MPU6050_RA_ZG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset); +} + +// X_FINE_GAIN register + +int8_t MPU6050::getXFineGain() { + I2Cdev::readByte(devAddr, MPU6050_RA_X_FINE_GAIN, buffer); + return buffer[0]; +} +void MPU6050::setXFineGain(int8_t gain) { + I2Cdev::writeByte(devAddr, MPU6050_RA_X_FINE_GAIN, gain); +} + +// Y_FINE_GAIN register + +int8_t MPU6050::getYFineGain() { + I2Cdev::readByte(devAddr, MPU6050_RA_Y_FINE_GAIN, buffer); + return buffer[0]; +} +void MPU6050::setYFineGain(int8_t gain) { + I2Cdev::writeByte(devAddr, MPU6050_RA_Y_FINE_GAIN, gain); +} + +// Z_FINE_GAIN register + +int8_t MPU6050::getZFineGain() { + I2Cdev::readByte(devAddr, MPU6050_RA_Z_FINE_GAIN, buffer); + return buffer[0]; +} +void MPU6050::setZFineGain(int8_t gain) { + I2Cdev::writeByte(devAddr, MPU6050_RA_Z_FINE_GAIN, gain); +} + +// XA_OFFS_* registers + +int16_t MPU6050::getXAccelOffset() { + I2Cdev::readBytes(devAddr, MPU6050_RA_XA_OFFS_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +void MPU6050::setXAccelOffset(int16_t offset) { + I2Cdev::writeWord(devAddr, MPU6050_RA_XA_OFFS_H, offset); +} + +// YA_OFFS_* register + +int16_t MPU6050::getYAccelOffset() { + I2Cdev::readBytes(devAddr, MPU6050_RA_YA_OFFS_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +void MPU6050::setYAccelOffset(int16_t offset) { + I2Cdev::writeWord(devAddr, MPU6050_RA_YA_OFFS_H, offset); +} + +// ZA_OFFS_* register + +int16_t MPU6050::getZAccelOffset() { + I2Cdev::readBytes(devAddr, MPU6050_RA_ZA_OFFS_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +void MPU6050::setZAccelOffset(int16_t offset) { + I2Cdev::writeWord(devAddr, MPU6050_RA_ZA_OFFS_H, offset); +} + +// XG_OFFS_USR* registers + +int16_t MPU6050::getXGyroOffset() { + I2Cdev::readBytes(devAddr, MPU6050_RA_XG_OFFS_USRH, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +void MPU6050::setXGyroOffset(int16_t offset) { + I2Cdev::writeWord(devAddr, MPU6050_RA_XG_OFFS_USRH, offset); +} + +// YG_OFFS_USR* register + +int16_t MPU6050::getYGyroOffset() { + I2Cdev::readBytes(devAddr, MPU6050_RA_YG_OFFS_USRH, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +void MPU6050::setYGyroOffset(int16_t offset) { + I2Cdev::writeWord(devAddr, MPU6050_RA_YG_OFFS_USRH, offset); +} + +// ZG_OFFS_USR* register + +int16_t MPU6050::getZGyroOffset() { + I2Cdev::readBytes(devAddr, MPU6050_RA_ZG_OFFS_USRH, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +void MPU6050::setZGyroOffset(int16_t offset) { + I2Cdev::writeWord(devAddr, MPU6050_RA_ZG_OFFS_USRH, offset); +} + +// INT_ENABLE register (DMP functions) + +bool MPU6050::getIntPLLReadyEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, buffer); + return buffer[0]; +} +void MPU6050::setIntPLLReadyEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, enabled); +} +bool MPU6050::getIntDMPEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DMP_INT_BIT, buffer); + return buffer[0]; +} +void MPU6050::setIntDMPEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DMP_INT_BIT, enabled); +} + +// DMP_INT_STATUS + +bool MPU6050::getDMPInt5Status() { + I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_5_BIT, buffer); + return buffer[0]; +} +bool MPU6050::getDMPInt4Status() { + I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_4_BIT, buffer); + return buffer[0]; +} +bool MPU6050::getDMPInt3Status() { + I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_3_BIT, buffer); + return buffer[0]; +} +bool MPU6050::getDMPInt2Status() { + I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_2_BIT, buffer); + return buffer[0]; +} +bool MPU6050::getDMPInt1Status() { + I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_1_BIT, buffer); + return buffer[0]; +} +bool MPU6050::getDMPInt0Status() { + I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_0_BIT, buffer); + return buffer[0]; +} + +// INT_STATUS register (DMP functions) + +bool MPU6050::getIntPLLReadyStatus() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, buffer); + return buffer[0]; +} +bool MPU6050::getIntDMPStatus() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_DMP_INT_BIT, buffer); + return buffer[0]; +} + +// USER_CTRL register (DMP functions) + +bool MPU6050::getDMPEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_EN_BIT, buffer); + return buffer[0]; +} +void MPU6050::setDMPEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_EN_BIT, enabled); +} +void MPU6050::resetDMP() { + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_RESET_BIT, true); +} + +// BANK_SEL register + +void MPU6050::setMemoryBank(uint8_t bank, bool prefetchEnabled, bool userBank) { + bank &= 0x1F; + if (userBank) bank |= 0x20; + if (prefetchEnabled) bank |= 0x40; + I2Cdev::writeByte(devAddr, MPU6050_RA_BANK_SEL, bank); +} + +// MEM_START_ADDR register + +void MPU6050::setMemoryStartAddress(uint8_t address) { + I2Cdev::writeByte(devAddr, MPU6050_RA_MEM_START_ADDR, address); +} + +// MEM_R_W register + +uint8_t MPU6050::readMemoryByte() { + I2Cdev::readByte(devAddr, MPU6050_RA_MEM_R_W, buffer); + return buffer[0]; +} +void MPU6050::writeMemoryByte(uint8_t data) { + I2Cdev::writeByte(devAddr, MPU6050_RA_MEM_R_W, data); +} +void MPU6050::readMemoryBlock(uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address) { + setMemoryBank(bank); + setMemoryStartAddress(address); + uint8_t chunkSize; + for (uint16_t i = 0; i < dataSize;) { + // determine correct chunk size according to bank position and data size + chunkSize = MPU6050_DMP_MEMORY_CHUNK_SIZE; + + // make sure we don't go past the data size + if (i + chunkSize > dataSize) chunkSize = dataSize - i; + + // make sure this chunk doesn't go past the bank boundary (256 bytes) + if (chunkSize > 256 - address) chunkSize = 256 - address; + + // read the chunk of data as specified + I2Cdev::readBytes(devAddr, MPU6050_RA_MEM_R_W, chunkSize, data + i); + + // increase byte index by [chunkSize] + i += chunkSize; + + // uint8_t automatically wraps to 0 at 256 + address += chunkSize; + + // if we aren't done, update bank (if necessary) and address + if (i < dataSize) { + if (address == 0) bank++; + setMemoryBank(bank); + setMemoryStartAddress(address); + } + } +} +bool MPU6050::writeMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address, bool verify, bool useProgMem) { + setMemoryBank(bank); + setMemoryStartAddress(address); + uint8_t chunkSize; + uint8_t *verifyBuffer; + uint8_t *progBuffer=0; + uint16_t i; + uint8_t j; + if (verify) verifyBuffer = (uint8_t *)malloc(MPU6050_DMP_MEMORY_CHUNK_SIZE); + if (useProgMem) progBuffer = (uint8_t *)malloc(MPU6050_DMP_MEMORY_CHUNK_SIZE); + for (i = 0; i < dataSize;) { + // determine correct chunk size according to bank position and data size + chunkSize = MPU6050_DMP_MEMORY_CHUNK_SIZE; + + // make sure we don't go past the data size + if (i + chunkSize > dataSize) chunkSize = dataSize - i; + + // make sure this chunk doesn't go past the bank boundary (256 bytes) + if (chunkSize > 256 - address) chunkSize = 256 - address; + + if (useProgMem) { + // write the chunk of data as specified + for (j = 0; j < chunkSize; j++) progBuffer[j] = pgm_read_byte(data + i + j); + } else { + // write the chunk of data as specified + progBuffer = (uint8_t *)data + i; + } + + I2Cdev::writeBytes(devAddr, MPU6050_RA_MEM_R_W, chunkSize, progBuffer); + + // verify data if needed + if (verify && verifyBuffer) { + setMemoryBank(bank); + setMemoryStartAddress(address); + I2Cdev::readBytes(devAddr, MPU6050_RA_MEM_R_W, chunkSize, verifyBuffer); + if (memcmp(progBuffer, verifyBuffer, chunkSize) != 0) { + /*Serial.print("Block write verification error, bank "); + Serial.print(bank, DEC); + Serial.print(", address "); + Serial.print(address, DEC); + Serial.print("!\nExpected:"); + for (j = 0; j < chunkSize; j++) { + Serial.print(" 0x"); + if (progBuffer[j] < 16) Serial.print("0"); + Serial.print(progBuffer[j], HEX); + } + Serial.print("\nReceived:"); + for (uint8_t j = 0; j < chunkSize; j++) { + Serial.print(" 0x"); + if (verifyBuffer[i + j] < 16) Serial.print("0"); + Serial.print(verifyBuffer[i + j], HEX); + } + Serial.print("\n");*/ + free(verifyBuffer); + if (useProgMem) free(progBuffer); + return false; // uh oh. + } + } + + // increase byte index by [chunkSize] + i += chunkSize; + + // uint8_t automatically wraps to 0 at 256 + address += chunkSize; + + // if we aren't done, update bank (if necessary) and address + if (i < dataSize) { + if (address == 0) bank++; + setMemoryBank(bank); + setMemoryStartAddress(address); + } + } + if (verify) free(verifyBuffer); + if (useProgMem) free(progBuffer); + return true; +} +bool MPU6050::writeProgMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address, bool verify) { + return writeMemoryBlock(data, dataSize, bank, address, verify, true); +} +bool MPU6050::writeDMPConfigurationSet(const uint8_t *data, uint16_t dataSize, bool useProgMem) { + uint8_t *progBuffer = 0; + uint8_t success, special; + uint16_t i, j; + if (useProgMem) { + progBuffer = (uint8_t *)malloc(8); // assume 8-byte blocks, realloc later if necessary + } + + // config set data is a long string of blocks with the following structure: + // [bank] [offset] [length] [byte[0], byte[1], ..., byte[length]] + uint8_t bank, offset, length; + for (i = 0; i < dataSize;) { + if (useProgMem) { + bank = pgm_read_byte(data + i++); + offset = pgm_read_byte(data + i++); + length = pgm_read_byte(data + i++); + } else { + bank = data[i++]; + offset = data[i++]; + length = data[i++]; + } + + // write data or perform special action + if (length > 0) { + // regular block of data to write + /*Serial.print("Writing config block to bank "); + Serial.print(bank); + Serial.print(", offset "); + Serial.print(offset); + Serial.print(", length="); + Serial.println(length);*/ + if (useProgMem) { + if (sizeof(progBuffer) < length) progBuffer = (uint8_t *)realloc(progBuffer, length); + for (j = 0; j < length; j++) progBuffer[j] = pgm_read_byte(data + i + j); + } else { + progBuffer = (uint8_t *)data + i; + } + success = writeMemoryBlock(progBuffer, length, bank, offset, true); + i += length; + } else { + // special instruction + // NOTE: this kind of behavior (what and when to do certain things) + // is totally undocumented. This code is in here based on observed + // behavior only, and exactly why (or even whether) it has to be here + // is anybody's guess for now. + if (useProgMem) { + special = pgm_read_byte(data + i++); + } else { + special = data[i++]; + } + /*Serial.print("Special command code "); + Serial.print(special, HEX); + Serial.println(" found...");*/ + if (special == 0x01) { + // enable DMP-related interrupts + + //setIntZeroMotionEnabled(true); + //setIntFIFOBufferOverflowEnabled(true); + //setIntDMPEnabled(true); + I2Cdev::writeByte(devAddr, MPU6050_RA_INT_ENABLE, 0x32); // single operation + + success = true; + } else { + // unknown special command + success = false; + } + } + + if (!success) { + if (useProgMem) free(progBuffer); + return false; // uh oh + } + } + if (useProgMem) free(progBuffer); + return true; +} +bool MPU6050::writeProgDMPConfigurationSet(const uint8_t *data, uint16_t dataSize) { + return writeDMPConfigurationSet(data, dataSize, true); +} + +// DMP_CFG_1 register + +uint8_t MPU6050::getDMPConfig1() { + I2Cdev::readByte(devAddr, MPU6050_RA_DMP_CFG_1, buffer); + return buffer[0]; +} +void MPU6050::setDMPConfig1(uint8_t config) { + I2Cdev::writeByte(devAddr, MPU6050_RA_DMP_CFG_1, config); +} + +// DMP_CFG_2 register + +uint8_t MPU6050::getDMPConfig2() { + I2Cdev::readByte(devAddr, MPU6050_RA_DMP_CFG_2, buffer); + return buffer[0]; +} +void MPU6050::setDMPConfig2(uint8_t config) { + I2Cdev::writeByte(devAddr, MPU6050_RA_DMP_CFG_2, config); +} \ No newline at end of file diff --git a/RaspberryPi_bcm2835/MPU6050/MPU6050.h b/RaspberryPi_bcm2835/MPU6050/MPU6050.h new file mode 100644 index 00000000..c3f878a3 --- /dev/null +++ b/RaspberryPi_bcm2835/MPU6050/MPU6050.h @@ -0,0 +1,1032 @@ +// I2Cdev library collection - MPU6050 I2C device class +// Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00) +// 10/3/2011 by Jeff Rowberg +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// ... - ongoing debug release + +// NOTE: THIS IS ONLY A PARIAL RELEASE. THIS DEVICE CLASS IS CURRENTLY UNDERGOING ACTIVE +// DEVELOPMENT AND IS STILL MISSING SOME IMPORTANT FEATURES. PLEASE KEEP THIS IN MIND IF +// YOU DECIDE TO USE THIS PARTICULAR CODE FOR ANYTHING. + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2012 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#ifndef _MPU6050_H_ +#define _MPU6050_H_ + +#include "I2Cdev.h" + +// supporting link: http://forum.arduino.cc/index.php?&topic=143444.msg1079517#msg1079517 +// also: http://forum.arduino.cc/index.php?&topic=141571.msg1062899#msg1062899s + +#ifdef __AVR__ +#include +#else +#define PROGMEM /* empty */ +#define pgm_read_byte(x) (*(x)) +#define pgm_read_word(x) (*(x)) +#define pgm_read_float(x) (*(x)) +#define PSTR(STR) STR +#endif + + +#define MPU6050_ADDRESS_AD0_LOW 0x68 // address pin low (GND), default for InvenSense evaluation board +#define MPU6050_ADDRESS_AD0_HIGH 0x69 // address pin high (VCC) +#define MPU6050_DEFAULT_ADDRESS MPU6050_ADDRESS_AD0_LOW + +#define MPU6050_RA_XG_OFFS_TC 0x00 //[7] PWR_MODE, [6:1] XG_OFFS_TC, [0] OTP_BNK_VLD +#define MPU6050_RA_YG_OFFS_TC 0x01 //[7] PWR_MODE, [6:1] YG_OFFS_TC, [0] OTP_BNK_VLD +#define MPU6050_RA_ZG_OFFS_TC 0x02 //[7] PWR_MODE, [6:1] ZG_OFFS_TC, [0] OTP_BNK_VLD +#define MPU6050_RA_X_FINE_GAIN 0x03 //[7:0] X_FINE_GAIN +#define MPU6050_RA_Y_FINE_GAIN 0x04 //[7:0] Y_FINE_GAIN +#define MPU6050_RA_Z_FINE_GAIN 0x05 //[7:0] Z_FINE_GAIN +#define MPU6050_RA_XA_OFFS_H 0x06 //[15:0] XA_OFFS +#define MPU6050_RA_XA_OFFS_L_TC 0x07 +#define MPU6050_RA_YA_OFFS_H 0x08 //[15:0] YA_OFFS +#define MPU6050_RA_YA_OFFS_L_TC 0x09 +#define MPU6050_RA_ZA_OFFS_H 0x0A //[15:0] ZA_OFFS +#define MPU6050_RA_ZA_OFFS_L_TC 0x0B +#define MPU6050_RA_SELF_TEST_X 0x0D //[7:5] XA_TEST[4-2], [4:0] XG_TEST[4-0] +#define MPU6050_RA_SELF_TEST_Y 0x0E //[7:5] YA_TEST[4-2], [4:0] YG_TEST[4-0] +#define MPU6050_RA_SELF_TEST_Z 0x0F //[7:5] ZA_TEST[4-2], [4:0] ZG_TEST[4-0] +#define MPU6050_RA_SELF_TEST_A 0x10 //[5:4] XA_TEST[1-0], [3:2] YA_TEST[1-0], [1:0] ZA_TEST[1-0] +#define MPU6050_RA_XG_OFFS_USRH 0x13 //[15:0] XG_OFFS_USR +#define MPU6050_RA_XG_OFFS_USRL 0x14 +#define MPU6050_RA_YG_OFFS_USRH 0x15 //[15:0] YG_OFFS_USR +#define MPU6050_RA_YG_OFFS_USRL 0x16 +#define MPU6050_RA_ZG_OFFS_USRH 0x17 //[15:0] ZG_OFFS_USR +#define MPU6050_RA_ZG_OFFS_USRL 0x18 +#define MPU6050_RA_SMPLRT_DIV 0x19 +#define MPU6050_RA_CONFIG 0x1A +#define MPU6050_RA_GYRO_CONFIG 0x1B +#define MPU6050_RA_ACCEL_CONFIG 0x1C +#define MPU6050_RA_FF_THR 0x1D +#define MPU6050_RA_FF_DUR 0x1E +#define MPU6050_RA_MOT_THR 0x1F +#define MPU6050_RA_MOT_DUR 0x20 +#define MPU6050_RA_ZRMOT_THR 0x21 +#define MPU6050_RA_ZRMOT_DUR 0x22 +#define MPU6050_RA_FIFO_EN 0x23 +#define MPU6050_RA_I2C_MST_CTRL 0x24 +#define MPU6050_RA_I2C_SLV0_ADDR 0x25 +#define MPU6050_RA_I2C_SLV0_REG 0x26 +#define MPU6050_RA_I2C_SLV0_CTRL 0x27 +#define MPU6050_RA_I2C_SLV1_ADDR 0x28 +#define MPU6050_RA_I2C_SLV1_REG 0x29 +#define MPU6050_RA_I2C_SLV1_CTRL 0x2A +#define MPU6050_RA_I2C_SLV2_ADDR 0x2B +#define MPU6050_RA_I2C_SLV2_REG 0x2C +#define MPU6050_RA_I2C_SLV2_CTRL 0x2D +#define MPU6050_RA_I2C_SLV3_ADDR 0x2E +#define MPU6050_RA_I2C_SLV3_REG 0x2F +#define MPU6050_RA_I2C_SLV3_CTRL 0x30 +#define MPU6050_RA_I2C_SLV4_ADDR 0x31 +#define MPU6050_RA_I2C_SLV4_REG 0x32 +#define MPU6050_RA_I2C_SLV4_DO 0x33 +#define MPU6050_RA_I2C_SLV4_CTRL 0x34 +#define MPU6050_RA_I2C_SLV4_DI 0x35 +#define MPU6050_RA_I2C_MST_STATUS 0x36 +#define MPU6050_RA_INT_PIN_CFG 0x37 +#define MPU6050_RA_INT_ENABLE 0x38 +#define MPU6050_RA_DMP_INT_STATUS 0x39 +#define MPU6050_RA_INT_STATUS 0x3A +#define MPU6050_RA_ACCEL_XOUT_H 0x3B +#define MPU6050_RA_ACCEL_XOUT_L 0x3C +#define MPU6050_RA_ACCEL_YOUT_H 0x3D +#define MPU6050_RA_ACCEL_YOUT_L 0x3E +#define MPU6050_RA_ACCEL_ZOUT_H 0x3F +#define MPU6050_RA_ACCEL_ZOUT_L 0x40 +#define MPU6050_RA_TEMP_OUT_H 0x41 +#define MPU6050_RA_TEMP_OUT_L 0x42 +#define MPU6050_RA_GYRO_XOUT_H 0x43 +#define MPU6050_RA_GYRO_XOUT_L 0x44 +#define MPU6050_RA_GYRO_YOUT_H 0x45 +#define MPU6050_RA_GYRO_YOUT_L 0x46 +#define MPU6050_RA_GYRO_ZOUT_H 0x47 +#define MPU6050_RA_GYRO_ZOUT_L 0x48 +#define MPU6050_RA_EXT_SENS_DATA_00 0x49 +#define MPU6050_RA_EXT_SENS_DATA_01 0x4A +#define MPU6050_RA_EXT_SENS_DATA_02 0x4B +#define MPU6050_RA_EXT_SENS_DATA_03 0x4C +#define MPU6050_RA_EXT_SENS_DATA_04 0x4D +#define MPU6050_RA_EXT_SENS_DATA_05 0x4E +#define MPU6050_RA_EXT_SENS_DATA_06 0x4F +#define MPU6050_RA_EXT_SENS_DATA_07 0x50 +#define MPU6050_RA_EXT_SENS_DATA_08 0x51 +#define MPU6050_RA_EXT_SENS_DATA_09 0x52 +#define MPU6050_RA_EXT_SENS_DATA_10 0x53 +#define MPU6050_RA_EXT_SENS_DATA_11 0x54 +#define MPU6050_RA_EXT_SENS_DATA_12 0x55 +#define MPU6050_RA_EXT_SENS_DATA_13 0x56 +#define MPU6050_RA_EXT_SENS_DATA_14 0x57 +#define MPU6050_RA_EXT_SENS_DATA_15 0x58 +#define MPU6050_RA_EXT_SENS_DATA_16 0x59 +#define MPU6050_RA_EXT_SENS_DATA_17 0x5A +#define MPU6050_RA_EXT_SENS_DATA_18 0x5B +#define MPU6050_RA_EXT_SENS_DATA_19 0x5C +#define MPU6050_RA_EXT_SENS_DATA_20 0x5D +#define MPU6050_RA_EXT_SENS_DATA_21 0x5E +#define MPU6050_RA_EXT_SENS_DATA_22 0x5F +#define MPU6050_RA_EXT_SENS_DATA_23 0x60 +#define MPU6050_RA_MOT_DETECT_STATUS 0x61 +#define MPU6050_RA_I2C_SLV0_DO 0x63 +#define MPU6050_RA_I2C_SLV1_DO 0x64 +#define MPU6050_RA_I2C_SLV2_DO 0x65 +#define MPU6050_RA_I2C_SLV3_DO 0x66 +#define MPU6050_RA_I2C_MST_DELAY_CTRL 0x67 +#define MPU6050_RA_SIGNAL_PATH_RESET 0x68 +#define MPU6050_RA_MOT_DETECT_CTRL 0x69 +#define MPU6050_RA_USER_CTRL 0x6A +#define MPU6050_RA_PWR_MGMT_1 0x6B +#define MPU6050_RA_PWR_MGMT_2 0x6C +#define MPU6050_RA_BANK_SEL 0x6D +#define MPU6050_RA_MEM_START_ADDR 0x6E +#define MPU6050_RA_MEM_R_W 0x6F +#define MPU6050_RA_DMP_CFG_1 0x70 +#define MPU6050_RA_DMP_CFG_2 0x71 +#define MPU6050_RA_FIFO_COUNTH 0x72 +#define MPU6050_RA_FIFO_COUNTL 0x73 +#define MPU6050_RA_FIFO_R_W 0x74 +#define MPU6050_RA_WHO_AM_I 0x75 + +#define MPU6050_SELF_TEST_XA_1_BIT 0x07 +#define MPU6050_SELF_TEST_XA_1_LENGTH 0x03 +#define MPU6050_SELF_TEST_XA_2_BIT 0x05 +#define MPU6050_SELF_TEST_XA_2_LENGTH 0x02 +#define MPU6050_SELF_TEST_YA_1_BIT 0x07 +#define MPU6050_SELF_TEST_YA_1_LENGTH 0x03 +#define MPU6050_SELF_TEST_YA_2_BIT 0x03 +#define MPU6050_SELF_TEST_YA_2_LENGTH 0x02 +#define MPU6050_SELF_TEST_ZA_1_BIT 0x07 +#define MPU6050_SELF_TEST_ZA_1_LENGTH 0x03 +#define MPU6050_SELF_TEST_ZA_2_BIT 0x01 +#define MPU6050_SELF_TEST_ZA_2_LENGTH 0x02 + +#define MPU6050_SELF_TEST_XG_1_BIT 0x04 +#define MPU6050_SELF_TEST_XG_1_LENGTH 0x05 +#define MPU6050_SELF_TEST_YG_1_BIT 0x04 +#define MPU6050_SELF_TEST_YG_1_LENGTH 0x05 +#define MPU6050_SELF_TEST_ZG_1_BIT 0x04 +#define MPU6050_SELF_TEST_ZG_1_LENGTH 0x05 + +#define MPU6050_TC_PWR_MODE_BIT 7 +#define MPU6050_TC_OFFSET_BIT 6 +#define MPU6050_TC_OFFSET_LENGTH 6 +#define MPU6050_TC_OTP_BNK_VLD_BIT 0 + +#define MPU6050_VDDIO_LEVEL_VLOGIC 0 +#define MPU6050_VDDIO_LEVEL_VDD 1 + +#define MPU6050_CFG_EXT_SYNC_SET_BIT 5 +#define MPU6050_CFG_EXT_SYNC_SET_LENGTH 3 +#define MPU6050_CFG_DLPF_CFG_BIT 2 +#define MPU6050_CFG_DLPF_CFG_LENGTH 3 + +#define MPU6050_EXT_SYNC_DISABLED 0x0 +#define MPU6050_EXT_SYNC_TEMP_OUT_L 0x1 +#define MPU6050_EXT_SYNC_GYRO_XOUT_L 0x2 +#define MPU6050_EXT_SYNC_GYRO_YOUT_L 0x3 +#define MPU6050_EXT_SYNC_GYRO_ZOUT_L 0x4 +#define MPU6050_EXT_SYNC_ACCEL_XOUT_L 0x5 +#define MPU6050_EXT_SYNC_ACCEL_YOUT_L 0x6 +#define MPU6050_EXT_SYNC_ACCEL_ZOUT_L 0x7 + +#define MPU6050_DLPF_BW_256 0x00 +#define MPU6050_DLPF_BW_188 0x01 +#define MPU6050_DLPF_BW_98 0x02 +#define MPU6050_DLPF_BW_42 0x03 +#define MPU6050_DLPF_BW_20 0x04 +#define MPU6050_DLPF_BW_10 0x05 +#define MPU6050_DLPF_BW_5 0x06 + +#define MPU6050_GCONFIG_FS_SEL_BIT 4 +#define MPU6050_GCONFIG_FS_SEL_LENGTH 2 + +#define MPU6050_GYRO_FS_250 0x00 +#define MPU6050_GYRO_FS_500 0x01 +#define MPU6050_GYRO_FS_1000 0x02 +#define MPU6050_GYRO_FS_2000 0x03 + +#define MPU6050_ACONFIG_XA_ST_BIT 7 +#define MPU6050_ACONFIG_YA_ST_BIT 6 +#define MPU6050_ACONFIG_ZA_ST_BIT 5 +#define MPU6050_ACONFIG_AFS_SEL_BIT 4 +#define MPU6050_ACONFIG_AFS_SEL_LENGTH 2 +#define MPU6050_ACONFIG_ACCEL_HPF_BIT 2 +#define MPU6050_ACONFIG_ACCEL_HPF_LENGTH 3 + +#define MPU6050_ACCEL_FS_2 0x00 +#define MPU6050_ACCEL_FS_4 0x01 +#define MPU6050_ACCEL_FS_8 0x02 +#define MPU6050_ACCEL_FS_16 0x03 + +#define MPU6050_DHPF_RESET 0x00 +#define MPU6050_DHPF_5 0x01 +#define MPU6050_DHPF_2P5 0x02 +#define MPU6050_DHPF_1P25 0x03 +#define MPU6050_DHPF_0P63 0x04 +#define MPU6050_DHPF_HOLD 0x07 + +#define MPU6050_TEMP_FIFO_EN_BIT 7 +#define MPU6050_XG_FIFO_EN_BIT 6 +#define MPU6050_YG_FIFO_EN_BIT 5 +#define MPU6050_ZG_FIFO_EN_BIT 4 +#define MPU6050_ACCEL_FIFO_EN_BIT 3 +#define MPU6050_SLV2_FIFO_EN_BIT 2 +#define MPU6050_SLV1_FIFO_EN_BIT 1 +#define MPU6050_SLV0_FIFO_EN_BIT 0 + +#define MPU6050_MULT_MST_EN_BIT 7 +#define MPU6050_WAIT_FOR_ES_BIT 6 +#define MPU6050_SLV_3_FIFO_EN_BIT 5 +#define MPU6050_I2C_MST_P_NSR_BIT 4 +#define MPU6050_I2C_MST_CLK_BIT 3 +#define MPU6050_I2C_MST_CLK_LENGTH 4 + +#define MPU6050_CLOCK_DIV_348 0x0 +#define MPU6050_CLOCK_DIV_333 0x1 +#define MPU6050_CLOCK_DIV_320 0x2 +#define MPU6050_CLOCK_DIV_308 0x3 +#define MPU6050_CLOCK_DIV_296 0x4 +#define MPU6050_CLOCK_DIV_286 0x5 +#define MPU6050_CLOCK_DIV_276 0x6 +#define MPU6050_CLOCK_DIV_267 0x7 +#define MPU6050_CLOCK_DIV_258 0x8 +#define MPU6050_CLOCK_DIV_500 0x9 +#define MPU6050_CLOCK_DIV_471 0xA +#define MPU6050_CLOCK_DIV_444 0xB +#define MPU6050_CLOCK_DIV_421 0xC +#define MPU6050_CLOCK_DIV_400 0xD +#define MPU6050_CLOCK_DIV_381 0xE +#define MPU6050_CLOCK_DIV_364 0xF + +#define MPU6050_I2C_SLV_RW_BIT 7 +#define MPU6050_I2C_SLV_ADDR_BIT 6 +#define MPU6050_I2C_SLV_ADDR_LENGTH 7 +#define MPU6050_I2C_SLV_EN_BIT 7 +#define MPU6050_I2C_SLV_BYTE_SW_BIT 6 +#define MPU6050_I2C_SLV_REG_DIS_BIT 5 +#define MPU6050_I2C_SLV_GRP_BIT 4 +#define MPU6050_I2C_SLV_LEN_BIT 3 +#define MPU6050_I2C_SLV_LEN_LENGTH 4 + +#define MPU6050_I2C_SLV4_RW_BIT 7 +#define MPU6050_I2C_SLV4_ADDR_BIT 6 +#define MPU6050_I2C_SLV4_ADDR_LENGTH 7 +#define MPU6050_I2C_SLV4_EN_BIT 7 +#define MPU6050_I2C_SLV4_INT_EN_BIT 6 +#define MPU6050_I2C_SLV4_REG_DIS_BIT 5 +#define MPU6050_I2C_SLV4_MST_DLY_BIT 4 +#define MPU6050_I2C_SLV4_MST_DLY_LENGTH 5 + +#define MPU6050_MST_PASS_THROUGH_BIT 7 +#define MPU6050_MST_I2C_SLV4_DONE_BIT 6 +#define MPU6050_MST_I2C_LOST_ARB_BIT 5 +#define MPU6050_MST_I2C_SLV4_NACK_BIT 4 +#define MPU6050_MST_I2C_SLV3_NACK_BIT 3 +#define MPU6050_MST_I2C_SLV2_NACK_BIT 2 +#define MPU6050_MST_I2C_SLV1_NACK_BIT 1 +#define MPU6050_MST_I2C_SLV0_NACK_BIT 0 + +#define MPU6050_INTCFG_INT_LEVEL_BIT 7 +#define MPU6050_INTCFG_INT_OPEN_BIT 6 +#define MPU6050_INTCFG_LATCH_INT_EN_BIT 5 +#define MPU6050_INTCFG_INT_RD_CLEAR_BIT 4 +#define MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT 3 +#define MPU6050_INTCFG_FSYNC_INT_EN_BIT 2 +#define MPU6050_INTCFG_I2C_BYPASS_EN_BIT 1 +#define MPU6050_INTCFG_CLKOUT_EN_BIT 0 + +#define MPU6050_INTMODE_ACTIVEHIGH 0x00 +#define MPU6050_INTMODE_ACTIVELOW 0x01 + +#define MPU6050_INTDRV_PUSHPULL 0x00 +#define MPU6050_INTDRV_OPENDRAIN 0x01 + +#define MPU6050_INTLATCH_50USPULSE 0x00 +#define MPU6050_INTLATCH_WAITCLEAR 0x01 + +#define MPU6050_INTCLEAR_STATUSREAD 0x00 +#define MPU6050_INTCLEAR_ANYREAD 0x01 + +#define MPU6050_INTERRUPT_FF_BIT 7 +#define MPU6050_INTERRUPT_MOT_BIT 6 +#define MPU6050_INTERRUPT_ZMOT_BIT 5 +#define MPU6050_INTERRUPT_FIFO_OFLOW_BIT 4 +#define MPU6050_INTERRUPT_I2C_MST_INT_BIT 3 +#define MPU6050_INTERRUPT_PLL_RDY_INT_BIT 2 +#define MPU6050_INTERRUPT_DMP_INT_BIT 1 +#define MPU6050_INTERRUPT_DATA_RDY_BIT 0 + +// TODO: figure out what these actually do +// UMPL source code is not very obivous +#define MPU6050_DMPINT_5_BIT 5 +#define MPU6050_DMPINT_4_BIT 4 +#define MPU6050_DMPINT_3_BIT 3 +#define MPU6050_DMPINT_2_BIT 2 +#define MPU6050_DMPINT_1_BIT 1 +#define MPU6050_DMPINT_0_BIT 0 + +#define MPU6050_MOTION_MOT_XNEG_BIT 7 +#define MPU6050_MOTION_MOT_XPOS_BIT 6 +#define MPU6050_MOTION_MOT_YNEG_BIT 5 +#define MPU6050_MOTION_MOT_YPOS_BIT 4 +#define MPU6050_MOTION_MOT_ZNEG_BIT 3 +#define MPU6050_MOTION_MOT_ZPOS_BIT 2 +#define MPU6050_MOTION_MOT_ZRMOT_BIT 0 + +#define MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT 7 +#define MPU6050_DELAYCTRL_I2C_SLV4_DLY_EN_BIT 4 +#define MPU6050_DELAYCTRL_I2C_SLV3_DLY_EN_BIT 3 +#define MPU6050_DELAYCTRL_I2C_SLV2_DLY_EN_BIT 2 +#define MPU6050_DELAYCTRL_I2C_SLV1_DLY_EN_BIT 1 +#define MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT 0 + +#define MPU6050_PATHRESET_GYRO_RESET_BIT 2 +#define MPU6050_PATHRESET_ACCEL_RESET_BIT 1 +#define MPU6050_PATHRESET_TEMP_RESET_BIT 0 + +#define MPU6050_DETECT_ACCEL_ON_DELAY_BIT 5 +#define MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH 2 +#define MPU6050_DETECT_FF_COUNT_BIT 3 +#define MPU6050_DETECT_FF_COUNT_LENGTH 2 +#define MPU6050_DETECT_MOT_COUNT_BIT 1 +#define MPU6050_DETECT_MOT_COUNT_LENGTH 2 + +#define MPU6050_DETECT_DECREMENT_RESET 0x0 +#define MPU6050_DETECT_DECREMENT_1 0x1 +#define MPU6050_DETECT_DECREMENT_2 0x2 +#define MPU6050_DETECT_DECREMENT_4 0x3 + +#define MPU6050_USERCTRL_DMP_EN_BIT 7 +#define MPU6050_USERCTRL_FIFO_EN_BIT 6 +#define MPU6050_USERCTRL_I2C_MST_EN_BIT 5 +#define MPU6050_USERCTRL_I2C_IF_DIS_BIT 4 +#define MPU6050_USERCTRL_DMP_RESET_BIT 3 +#define MPU6050_USERCTRL_FIFO_RESET_BIT 2 +#define MPU6050_USERCTRL_I2C_MST_RESET_BIT 1 +#define MPU6050_USERCTRL_SIG_COND_RESET_BIT 0 + +#define MPU6050_PWR1_DEVICE_RESET_BIT 7 +#define MPU6050_PWR1_SLEEP_BIT 6 +#define MPU6050_PWR1_CYCLE_BIT 5 +#define MPU6050_PWR1_TEMP_DIS_BIT 3 +#define MPU6050_PWR1_CLKSEL_BIT 2 +#define MPU6050_PWR1_CLKSEL_LENGTH 3 + +#define MPU6050_CLOCK_INTERNAL 0x00 +#define MPU6050_CLOCK_PLL_XGYRO 0x01 +#define MPU6050_CLOCK_PLL_YGYRO 0x02 +#define MPU6050_CLOCK_PLL_ZGYRO 0x03 +#define MPU6050_CLOCK_PLL_EXT32K 0x04 +#define MPU6050_CLOCK_PLL_EXT19M 0x05 +#define MPU6050_CLOCK_KEEP_RESET 0x07 + +#define MPU6050_PWR2_LP_WAKE_CTRL_BIT 7 +#define MPU6050_PWR2_LP_WAKE_CTRL_LENGTH 2 +#define MPU6050_PWR2_STBY_XA_BIT 5 +#define MPU6050_PWR2_STBY_YA_BIT 4 +#define MPU6050_PWR2_STBY_ZA_BIT 3 +#define MPU6050_PWR2_STBY_XG_BIT 2 +#define MPU6050_PWR2_STBY_YG_BIT 1 +#define MPU6050_PWR2_STBY_ZG_BIT 0 + +#define MPU6050_WAKE_FREQ_1P25 0x0 +#define MPU6050_WAKE_FREQ_2P5 0x1 +#define MPU6050_WAKE_FREQ_5 0x2 +#define MPU6050_WAKE_FREQ_10 0x3 + +#define MPU6050_BANKSEL_PRFTCH_EN_BIT 6 +#define MPU6050_BANKSEL_CFG_USER_BANK_BIT 5 +#define MPU6050_BANKSEL_MEM_SEL_BIT 4 +#define MPU6050_BANKSEL_MEM_SEL_LENGTH 5 + +#define MPU6050_WHO_AM_I_BIT 6 +#define MPU6050_WHO_AM_I_LENGTH 6 + +#define MPU6050_DMP_MEMORY_BANKS 8 +#define MPU6050_DMP_MEMORY_BANK_SIZE 256 +#define MPU6050_DMP_MEMORY_CHUNK_SIZE 16 + +// note: DMP code memory blocks defined at end of header file + +class MPU6050 { + public: + MPU6050(); + MPU6050(uint8_t address); + + void initialize(); + bool testConnection(); + + // AUX_VDDIO register + uint8_t getAuxVDDIOLevel(); + void setAuxVDDIOLevel(uint8_t level); + + // SMPLRT_DIV register + uint8_t getRate(); + void setRate(uint8_t rate); + + // CONFIG register + uint8_t getExternalFrameSync(); + void setExternalFrameSync(uint8_t sync); + uint8_t getDLPFMode(); + void setDLPFMode(uint8_t bandwidth); + + // GYRO_CONFIG register + uint8_t getFullScaleGyroRange(); + void setFullScaleGyroRange(uint8_t range); + + // SELF_TEST registers + uint8_t getAccelXSelfTestFactoryTrim(); + uint8_t getAccelYSelfTestFactoryTrim(); + uint8_t getAccelZSelfTestFactoryTrim(); + + uint8_t getGyroXSelfTestFactoryTrim(); + uint8_t getGyroYSelfTestFactoryTrim(); + uint8_t getGyroZSelfTestFactoryTrim(); + + // ACCEL_CONFIG register + bool getAccelXSelfTest(); + void setAccelXSelfTest(bool enabled); + bool getAccelYSelfTest(); + void setAccelYSelfTest(bool enabled); + bool getAccelZSelfTest(); + void setAccelZSelfTest(bool enabled); + uint8_t getFullScaleAccelRange(); + void setFullScaleAccelRange(uint8_t range); + uint8_t getDHPFMode(); + void setDHPFMode(uint8_t mode); + + // FF_THR register + uint8_t getFreefallDetectionThreshold(); + void setFreefallDetectionThreshold(uint8_t threshold); + + // FF_DUR register + uint8_t getFreefallDetectionDuration(); + void setFreefallDetectionDuration(uint8_t duration); + + // MOT_THR register + uint8_t getMotionDetectionThreshold(); + void setMotionDetectionThreshold(uint8_t threshold); + + // MOT_DUR register + uint8_t getMotionDetectionDuration(); + void setMotionDetectionDuration(uint8_t duration); + + // ZRMOT_THR register + uint8_t getZeroMotionDetectionThreshold(); + void setZeroMotionDetectionThreshold(uint8_t threshold); + + // ZRMOT_DUR register + uint8_t getZeroMotionDetectionDuration(); + void setZeroMotionDetectionDuration(uint8_t duration); + + // FIFO_EN register + bool getTempFIFOEnabled(); + void setTempFIFOEnabled(bool enabled); + bool getXGyroFIFOEnabled(); + void setXGyroFIFOEnabled(bool enabled); + bool getYGyroFIFOEnabled(); + void setYGyroFIFOEnabled(bool enabled); + bool getZGyroFIFOEnabled(); + void setZGyroFIFOEnabled(bool enabled); + bool getAccelFIFOEnabled(); + void setAccelFIFOEnabled(bool enabled); + bool getSlave2FIFOEnabled(); + void setSlave2FIFOEnabled(bool enabled); + bool getSlave1FIFOEnabled(); + void setSlave1FIFOEnabled(bool enabled); + bool getSlave0FIFOEnabled(); + void setSlave0FIFOEnabled(bool enabled); + + // I2C_MST_CTRL register + bool getMultiMasterEnabled(); + void setMultiMasterEnabled(bool enabled); + bool getWaitForExternalSensorEnabled(); + void setWaitForExternalSensorEnabled(bool enabled); + bool getSlave3FIFOEnabled(); + void setSlave3FIFOEnabled(bool enabled); + bool getSlaveReadWriteTransitionEnabled(); + void setSlaveReadWriteTransitionEnabled(bool enabled); + uint8_t getMasterClockSpeed(); + void setMasterClockSpeed(uint8_t speed); + + // I2C_SLV* registers (Slave 0-3) + uint8_t getSlaveAddress(uint8_t num); + void setSlaveAddress(uint8_t num, uint8_t address); + uint8_t getSlaveRegister(uint8_t num); + void setSlaveRegister(uint8_t num, uint8_t reg); + bool getSlaveEnabled(uint8_t num); + void setSlaveEnabled(uint8_t num, bool enabled); + bool getSlaveWordByteSwap(uint8_t num); + void setSlaveWordByteSwap(uint8_t num, bool enabled); + bool getSlaveWriteMode(uint8_t num); + void setSlaveWriteMode(uint8_t num, bool mode); + bool getSlaveWordGroupOffset(uint8_t num); + void setSlaveWordGroupOffset(uint8_t num, bool enabled); + uint8_t getSlaveDataLength(uint8_t num); + void setSlaveDataLength(uint8_t num, uint8_t length); + + // I2C_SLV* registers (Slave 4) + uint8_t getSlave4Address(); + void setSlave4Address(uint8_t address); + uint8_t getSlave4Register(); + void setSlave4Register(uint8_t reg); + void setSlave4OutputByte(uint8_t data); + bool getSlave4Enabled(); + void setSlave4Enabled(bool enabled); + bool getSlave4InterruptEnabled(); + void setSlave4InterruptEnabled(bool enabled); + bool getSlave4WriteMode(); + void setSlave4WriteMode(bool mode); + uint8_t getSlave4MasterDelay(); + void setSlave4MasterDelay(uint8_t delay); + uint8_t getSlate4InputByte(); + + // I2C_MST_STATUS register + bool getPassthroughStatus(); + bool getSlave4IsDone(); + bool getLostArbitration(); + bool getSlave4Nack(); + bool getSlave3Nack(); + bool getSlave2Nack(); + bool getSlave1Nack(); + bool getSlave0Nack(); + + // INT_PIN_CFG register + bool getInterruptMode(); + void setInterruptMode(bool mode); + bool getInterruptDrive(); + void setInterruptDrive(bool drive); + bool getInterruptLatch(); + void setInterruptLatch(bool latch); + bool getInterruptLatchClear(); + void setInterruptLatchClear(bool clear); + bool getFSyncInterruptLevel(); + void setFSyncInterruptLevel(bool level); + bool getFSyncInterruptEnabled(); + void setFSyncInterruptEnabled(bool enabled); + bool getI2CBypassEnabled(); + void setI2CBypassEnabled(bool enabled); + bool getClockOutputEnabled(); + void setClockOutputEnabled(bool enabled); + + // INT_ENABLE register + uint8_t getIntEnabled(); + void setIntEnabled(uint8_t enabled); + bool getIntFreefallEnabled(); + void setIntFreefallEnabled(bool enabled); + bool getIntMotionEnabled(); + void setIntMotionEnabled(bool enabled); + bool getIntZeroMotionEnabled(); + void setIntZeroMotionEnabled(bool enabled); + bool getIntFIFOBufferOverflowEnabled(); + void setIntFIFOBufferOverflowEnabled(bool enabled); + bool getIntI2CMasterEnabled(); + void setIntI2CMasterEnabled(bool enabled); + bool getIntDataReadyEnabled(); + void setIntDataReadyEnabled(bool enabled); + + // INT_STATUS register + uint8_t getIntStatus(); + bool getIntFreefallStatus(); + bool getIntMotionStatus(); + bool getIntZeroMotionStatus(); + bool getIntFIFOBufferOverflowStatus(); + bool getIntI2CMasterStatus(); + bool getIntDataReadyStatus(); + + // ACCEL_*OUT_* registers + void getMotion9(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz, int16_t* mx, int16_t* my, int16_t* mz); + void getMotion6(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz); + void getAcceleration(int16_t* x, int16_t* y, int16_t* z); + int16_t getAccelerationX(); + int16_t getAccelerationY(); + int16_t getAccelerationZ(); + + // TEMP_OUT_* registers + int16_t getTemperature(); + + // GYRO_*OUT_* registers + void getRotation(int16_t* x, int16_t* y, int16_t* z); + int16_t getRotationX(); + int16_t getRotationY(); + int16_t getRotationZ(); + + // EXT_SENS_DATA_* registers + uint8_t getExternalSensorByte(int position); + uint16_t getExternalSensorWord(int position); + uint32_t getExternalSensorDWord(int position); + + // MOT_DETECT_STATUS register + uint8_t getMotionStatus(); + bool getXNegMotionDetected(); + bool getXPosMotionDetected(); + bool getYNegMotionDetected(); + bool getYPosMotionDetected(); + bool getZNegMotionDetected(); + bool getZPosMotionDetected(); + bool getZeroMotionDetected(); + + // I2C_SLV*_DO register + void setSlaveOutputByte(uint8_t num, uint8_t data); + + // I2C_MST_DELAY_CTRL register + bool getExternalShadowDelayEnabled(); + void setExternalShadowDelayEnabled(bool enabled); + bool getSlaveDelayEnabled(uint8_t num); + void setSlaveDelayEnabled(uint8_t num, bool enabled); + + // SIGNAL_PATH_RESET register + void resetGyroscopePath(); + void resetAccelerometerPath(); + void resetTemperaturePath(); + + // MOT_DETECT_CTRL register + uint8_t getAccelerometerPowerOnDelay(); + void setAccelerometerPowerOnDelay(uint8_t delay); + uint8_t getFreefallDetectionCounterDecrement(); + void setFreefallDetectionCounterDecrement(uint8_t decrement); + uint8_t getMotionDetectionCounterDecrement(); + void setMotionDetectionCounterDecrement(uint8_t decrement); + + // USER_CTRL register + bool getFIFOEnabled(); + void setFIFOEnabled(bool enabled); + bool getI2CMasterModeEnabled(); + void setI2CMasterModeEnabled(bool enabled); + void switchSPIEnabled(bool enabled); + void resetFIFO(); + void resetI2CMaster(); + void resetSensors(); + + // PWR_MGMT_1 register + void reset(); + bool getSleepEnabled(); + void setSleepEnabled(bool enabled); + bool getWakeCycleEnabled(); + void setWakeCycleEnabled(bool enabled); + bool getTempSensorEnabled(); + void setTempSensorEnabled(bool enabled); + uint8_t getClockSource(); + void setClockSource(uint8_t source); + + // PWR_MGMT_2 register + uint8_t getWakeFrequency(); + void setWakeFrequency(uint8_t frequency); + bool getStandbyXAccelEnabled(); + void setStandbyXAccelEnabled(bool enabled); + bool getStandbyYAccelEnabled(); + void setStandbyYAccelEnabled(bool enabled); + bool getStandbyZAccelEnabled(); + void setStandbyZAccelEnabled(bool enabled); + bool getStandbyXGyroEnabled(); + void setStandbyXGyroEnabled(bool enabled); + bool getStandbyYGyroEnabled(); + void setStandbyYGyroEnabled(bool enabled); + bool getStandbyZGyroEnabled(); + void setStandbyZGyroEnabled(bool enabled); + + // FIFO_COUNT_* registers + uint16_t getFIFOCount(); + + // FIFO_R_W register + uint8_t getFIFOByte(); + void setFIFOByte(uint8_t data); + void getFIFOBytes(uint8_t *data, uint8_t length); + + // WHO_AM_I register + uint8_t getDeviceID(); + void setDeviceID(uint8_t id); + + // ======== UNDOCUMENTED/DMP REGISTERS/METHODS ======== + + // XG_OFFS_TC register + uint8_t getOTPBankValid(); + void setOTPBankValid(bool enabled); + int8_t getXGyroOffsetTC(); + void setXGyroOffsetTC(int8_t offset); + + // YG_OFFS_TC register + int8_t getYGyroOffsetTC(); + void setYGyroOffsetTC(int8_t offset); + + // ZG_OFFS_TC register + int8_t getZGyroOffsetTC(); + void setZGyroOffsetTC(int8_t offset); + + // X_FINE_GAIN register + int8_t getXFineGain(); + void setXFineGain(int8_t gain); + + // Y_FINE_GAIN register + int8_t getYFineGain(); + void setYFineGain(int8_t gain); + + // Z_FINE_GAIN register + int8_t getZFineGain(); + void setZFineGain(int8_t gain); + + // XA_OFFS_* registers + int16_t getXAccelOffset(); + void setXAccelOffset(int16_t offset); + + // YA_OFFS_* register + int16_t getYAccelOffset(); + void setYAccelOffset(int16_t offset); + + // ZA_OFFS_* register + int16_t getZAccelOffset(); + void setZAccelOffset(int16_t offset); + + // XG_OFFS_USR* registers + int16_t getXGyroOffset(); + void setXGyroOffset(int16_t offset); + + // YG_OFFS_USR* register + int16_t getYGyroOffset(); + void setYGyroOffset(int16_t offset); + + // ZG_OFFS_USR* register + int16_t getZGyroOffset(); + void setZGyroOffset(int16_t offset); + + // INT_ENABLE register (DMP functions) + bool getIntPLLReadyEnabled(); + void setIntPLLReadyEnabled(bool enabled); + bool getIntDMPEnabled(); + void setIntDMPEnabled(bool enabled); + + // DMP_INT_STATUS + bool getDMPInt5Status(); + bool getDMPInt4Status(); + bool getDMPInt3Status(); + bool getDMPInt2Status(); + bool getDMPInt1Status(); + bool getDMPInt0Status(); + + // INT_STATUS register (DMP functions) + bool getIntPLLReadyStatus(); + bool getIntDMPStatus(); + + // USER_CTRL register (DMP functions) + bool getDMPEnabled(); + void setDMPEnabled(bool enabled); + void resetDMP(); + + // BANK_SEL register + void setMemoryBank(uint8_t bank, bool prefetchEnabled=false, bool userBank=false); + + // MEM_START_ADDR register + void setMemoryStartAddress(uint8_t address); + + // MEM_R_W register + uint8_t readMemoryByte(); + void writeMemoryByte(uint8_t data); + void readMemoryBlock(uint8_t *data, uint16_t dataSize, uint8_t bank=0, uint8_t address=0); + bool writeMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank=0, uint8_t address=0, bool verify=true, bool useProgMem=false); + bool writeProgMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank=0, uint8_t address=0, bool verify=true); + + bool writeDMPConfigurationSet(const uint8_t *data, uint16_t dataSize, bool useProgMem=false); + bool writeProgDMPConfigurationSet(const uint8_t *data, uint16_t dataSize); + + // DMP_CFG_1 register + uint8_t getDMPConfig1(); + void setDMPConfig1(uint8_t config); + + // DMP_CFG_2 register + uint8_t getDMPConfig2(); + void setDMPConfig2(uint8_t config); + + // special methods for MotionApps 2.0 implementation + #ifdef MPU6050_INCLUDE_DMP_MOTIONAPPS20 + uint8_t *dmpPacketBuffer; + uint16_t dmpPacketSize; + + uint8_t dmpInitialize(); + bool dmpPacketAvailable(); + + uint8_t dmpSetFIFORate(uint8_t fifoRate); + uint8_t dmpGetFIFORate(); + uint8_t dmpGetSampleStepSizeMS(); + uint8_t dmpGetSampleFrequency(); + int32_t dmpDecodeTemperature(int8_t tempReg); + + // Register callbacks after a packet of FIFO data is processed + //uint8_t dmpRegisterFIFORateProcess(inv_obj_func func, int16_t priority); + //uint8_t dmpUnregisterFIFORateProcess(inv_obj_func func); + uint8_t dmpRunFIFORateProcesses(); + + // Setup FIFO for various output + uint8_t dmpSendQuaternion(uint_fast16_t accuracy); + uint8_t dmpSendGyro(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendAccel(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendLinearAccel(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendLinearAccelInWorld(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendControlData(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendSensorData(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendExternalSensorData(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendGravity(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendPacketNumber(uint_fast16_t accuracy); + uint8_t dmpSendQuantizedAccel(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendEIS(uint_fast16_t elements, uint_fast16_t accuracy); + + // Get Fixed Point data from FIFO + uint8_t dmpGetAccel(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetAccel(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetAccel(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetQuaternion(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetQuaternion(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetQuaternion(Quaternion *q, const uint8_t* packet=0); + uint8_t dmpGet6AxisQuaternion(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGet6AxisQuaternion(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGet6AxisQuaternion(Quaternion *q, const uint8_t* packet=0); + uint8_t dmpGetRelativeQuaternion(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetRelativeQuaternion(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetRelativeQuaternion(Quaternion *data, const uint8_t* packet=0); + uint8_t dmpGetGyro(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyro(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyro(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpSetLinearAccelFilterCoefficient(float coef); + uint8_t dmpGetLinearAccel(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetLinearAccel(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetLinearAccel(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetLinearAccel(VectorInt16 *v, VectorInt16 *vRaw, VectorFloat *gravity); + uint8_t dmpGetLinearAccelInWorld(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetLinearAccelInWorld(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetLinearAccelInWorld(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Quaternion *q); + uint8_t dmpGetGyroAndAccelSensor(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyroAndAccelSensor(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyroAndAccelSensor(VectorInt16 *g, VectorInt16 *a, const uint8_t* packet=0); + uint8_t dmpGetGyroSensor(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyroSensor(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyroSensor(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetControlData(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetTemperature(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetGravity(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetGravity(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetGravity(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetGravity(VectorFloat *v, Quaternion *q); + uint8_t dmpGetUnquantizedAccel(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetUnquantizedAccel(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetUnquantizedAccel(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetQuantizedAccel(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetQuantizedAccel(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetQuantizedAccel(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetExternalSensorData(int32_t *data, uint16_t size, const uint8_t* packet=0); + uint8_t dmpGetEIS(int32_t *data, const uint8_t* packet=0); + + uint8_t dmpGetEuler(float *data, Quaternion *q); + uint8_t dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity); + + // Get Floating Point data from FIFO + uint8_t dmpGetAccelFloat(float *data, const uint8_t* packet=0); + uint8_t dmpGetQuaternionFloat(float *data, const uint8_t* packet=0); + + uint8_t dmpProcessFIFOPacket(const unsigned char *dmpData); + uint8_t dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *processed=NULL); + + uint8_t dmpSetFIFOProcessedCallback(void (*func) (void)); + + uint8_t dmpInitFIFOParam(); + uint8_t dmpCloseFIFO(); + uint8_t dmpSetGyroDataSource(uint8_t source); + uint8_t dmpDecodeQuantizedAccel(); + uint32_t dmpGetGyroSumOfSquare(); + uint32_t dmpGetAccelSumOfSquare(); + void dmpOverrideQuaternion(long *q); + uint16_t dmpGetFIFOPacketSize(); + #endif + + // special methods for MotionApps 4.1 implementation + #ifdef MPU6050_INCLUDE_DMP_MOTIONAPPS41 + uint8_t *dmpPacketBuffer; + uint16_t dmpPacketSize; + + uint8_t dmpInitialize(); + bool dmpPacketAvailable(); + + uint8_t dmpSetFIFORate(uint8_t fifoRate); + uint8_t dmpGetFIFORate(); + uint8_t dmpGetSampleStepSizeMS(); + uint8_t dmpGetSampleFrequency(); + int32_t dmpDecodeTemperature(int8_t tempReg); + + // Register callbacks after a packet of FIFO data is processed + //uint8_t dmpRegisterFIFORateProcess(inv_obj_func func, int16_t priority); + //uint8_t dmpUnregisterFIFORateProcess(inv_obj_func func); + uint8_t dmpRunFIFORateProcesses(); + + // Setup FIFO for various output + uint8_t dmpSendQuaternion(uint_fast16_t accuracy); + uint8_t dmpSendGyro(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendAccel(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendLinearAccel(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendLinearAccelInWorld(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendControlData(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendSensorData(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendExternalSensorData(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendGravity(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendPacketNumber(uint_fast16_t accuracy); + uint8_t dmpSendQuantizedAccel(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendEIS(uint_fast16_t elements, uint_fast16_t accuracy); + + // Get Fixed Point data from FIFO + uint8_t dmpGetAccel(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetAccel(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetAccel(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetQuaternion(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetQuaternion(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetQuaternion(Quaternion *q, const uint8_t* packet=0); + uint8_t dmpGet6AxisQuaternion(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGet6AxisQuaternion(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGet6AxisQuaternion(Quaternion *q, const uint8_t* packet=0); + uint8_t dmpGetRelativeQuaternion(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetRelativeQuaternion(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetRelativeQuaternion(Quaternion *data, const uint8_t* packet=0); + uint8_t dmpGetGyro(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyro(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyro(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetMag(int16_t *data, const uint8_t* packet=0); + uint8_t dmpSetLinearAccelFilterCoefficient(float coef); + uint8_t dmpGetLinearAccel(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetLinearAccel(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetLinearAccel(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetLinearAccel(VectorInt16 *v, VectorInt16 *vRaw, VectorFloat *gravity); + uint8_t dmpGetLinearAccelInWorld(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetLinearAccelInWorld(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetLinearAccelInWorld(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Quaternion *q); + uint8_t dmpGetGyroAndAccelSensor(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyroAndAccelSensor(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyroAndAccelSensor(VectorInt16 *g, VectorInt16 *a, const uint8_t* packet=0); + uint8_t dmpGetGyroSensor(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyroSensor(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyroSensor(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetControlData(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetTemperature(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetGravity(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetGravity(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetGravity(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetGravity(VectorFloat *v, Quaternion *q); + uint8_t dmpGetUnquantizedAccel(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetUnquantizedAccel(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetUnquantizedAccel(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetQuantizedAccel(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetQuantizedAccel(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetQuantizedAccel(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetExternalSensorData(int32_t *data, uint16_t size, const uint8_t* packet=0); + uint8_t dmpGetEIS(int32_t *data, const uint8_t* packet=0); + + uint8_t dmpGetEuler(float *data, Quaternion *q); + uint8_t dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity); + + // Get Floating Point data from FIFO + uint8_t dmpGetAccelFloat(float *data, const uint8_t* packet=0); + uint8_t dmpGetQuaternionFloat(float *data, const uint8_t* packet=0); + + uint8_t dmpProcessFIFOPacket(const unsigned char *dmpData); + uint8_t dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *processed=NULL); + + uint8_t dmpSetFIFOProcessedCallback(void (*func) (void)); + + uint8_t dmpInitFIFOParam(); + uint8_t dmpCloseFIFO(); + uint8_t dmpSetGyroDataSource(uint8_t source); + uint8_t dmpDecodeQuantizedAccel(); + uint32_t dmpGetGyroSumOfSquare(); + uint32_t dmpGetAccelSumOfSquare(); + void dmpOverrideQuaternion(long *q); + uint16_t dmpGetFIFOPacketSize(); + #endif + + private: + uint8_t devAddr; + uint8_t buffer[14]; +}; + +#endif /* _MPU6050_H_ */ \ No newline at end of file diff --git a/RaspberryPi_bcm2835/MPU6050/examples/IMU_zero.cpp b/RaspberryPi_bcm2835/MPU6050/examples/IMU_zero.cpp new file mode 100644 index 00000000..1d72afc1 --- /dev/null +++ b/RaspberryPi_bcm2835/MPU6050/examples/IMU_zero.cpp @@ -0,0 +1,349 @@ +/* +I2Cdev library collection - MPU6050 RPi calibration program +Based on the example in Arduino/MPU6050/ + +============================================== +I2Cdev device library code is placed under the MIT license + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== + +To compile on a Raspberry Pi (1 or 2 or 3) + 1. install the bcm2835 library, see http://www.airspayce.com/mikem/bcm2835/index.html + 2. enable i2c on your RPi , see https://learn.adafruit.com/adafruits-raspberry-pi-lesson-4-gpio-setup/configuring-i2c + 3. connect your i2c devices + 4. then from bash + $ PATH_I2CDEVLIB=~/i2cdevlib/ + $ gcc -o IMU_zero ${PATH_I2CDEVLIB}RaspberryPi_bcm2835/MPU6050/examples/IMU_zero.cpp \ + -I ${PATH_I2CDEVLIB}RaspberryPi_bcm2835/I2Cdev ${PATH_I2CDEVLIB}RaspberryPi_bcm2835/I2Cdev/I2Cdev.cpp \ + -I ${PATH_I2CDEVLIB}RaspberryPi_bcm2835/MPU6050/ ${PATH_I2CDEVLIB}RaspberryPi_bcm2835/MPU6050/MPU6050.cpp -l bcm2835 -l m + $ sudo ./IMU_zero + +If an MPU6050 + * is an ideal member of its tribe, + * is properly warmed up, + * is at rest in a neutral position, + * is in a location where the pull of gravity is exactly 1g, and + * has been loaded with the best possible offsets, +then it will report 0 for all accelerations and displacements, except for +Z acceleration, for which it will report 16384 (that is, 2^14). Your device +probably won't do quite this well, but good offsets will all get the baseline +outputs close to these target values. + + Put the MPU6050 on a flat and horizontal surface, and leave it operating for +5-10 minutes so its temperature gets stabilized. + + Run this program. A "----- done -----" line will indicate that it has done its best. +With the current accuracy-related constants (NFast = 1000, NSlow = 10000), it will take +a few minutes to get there. + + Along the way, it will generate a dozen or so lines of output, showing that for each +of the 6 desired offsets, it is + * first, trying to find two estimates, one too low and one too high, and + * then, closing in until the bracket can't be made smaller. + + The line just above the "done" line will look something like + [567,567] --> [-1,2] [-2223,-2223] --> [0,1] [1131,1132] --> [16374,16404] [155,156] --> [-1,1] [-25,-24] --> [0,3] [5,6] --> [0,4] +As will have been shown in interspersed header lines, the six groups making up this +line describe the optimum offsets for the X acceleration, Y acceleration, Z acceleration, +X gyro, Y gyro, and Z gyro, respectively. In the sample shown just above, the trial showed +that +567 was the best offset for the X acceleration, -2223 was best for Y acceleration, +and so on. + + The need for the delay between readings (usDelay) was brought to attention by Nikolaus Doppelhammer. +=============================================== +*/ + + +#include +#include +#include +#include "I2Cdev.h" +#include "MPU6050.h" +#include + +// class default I2C address is 0x68 +// specific I2C addresses may be passed as a parameter here +// AD0 low = 0x68 (default for InvenSense evaluation board) +// AD0 high = 0x69 +MPU6050 accelgyro; +//MPU6050 accelgyro(0x69); // <-- use for AD0 high + + +const char LBRACKET = '['; +const char RBRACKET = ']'; +const char COMMA = ','; +const char BLANK = ' '; +const char PERIOD = '.'; + +const int iAx = 0; +const int iAy = 1; +const int iAz = 2; +const int iGx = 3; +const int iGy = 4; +const int iGz = 5; + +const int usDelay = 3150; // empirical, to hold sampling to 200 Hz +const int NFast = 1000; // the bigger, the better (but slower) +const int NSlow = 10000; // .. +const int LinesBetweenHeaders = 5; + + +int LowValue[6]; +int HighValue[6]; +int Smoothed[6]; +int LowOffset[6]; +int HighOffset[6]; +int Target[6]; +int LinesOut; +int N; + + +void ForceHeader() +{ + LinesOut = 99; +} + +void GetSmoothed() +{ + int16_t RawValue[6]; + int i; + long Sums[6]; + for (i = iAx; i <= iGz; i++) + { + Sums[i] = 0; + } + // unsigned long Start = micros(); + + for (i = 1; i <= N; i++) + { + // get sums + accelgyro.getMotion6(&RawValue[iAx], &RawValue[iAy], &RawValue[iAz], + &RawValue[iGx], &RawValue[iGy], &RawValue[iGz]); + if ((i % 500) == 0) + { + printf("%c", PERIOD); + } + delayMicroseconds(usDelay); + for (int j = iAx; j <= iGz; j++) + { + Sums[j] = Sums[j] + RawValue[j]; + } + } // get sums + // unsigned long usForN = micros() - Start; + // printf(" reading at %d Hz\n", 1000000/((usForN+N/2)/N)); + for (i = iAx; i <= iGz; i++) + { + Smoothed[i] = (Sums[i] + N/2) / N ; + } +} // GetSmoothed + +void Initialize() +{ + // initialize device + printf("Initializing I2C devices...\n"); + I2Cdev::initialize(); + + // verify connection + printf("Testing device connections...\n"); + if(!accelgyro.testConnection()) + { + printf("MPU6050 connection failed\n"); + return; + } + + printf("MPU6050 connection successful\n"); + accelgyro.initialize(); + printf("Initialization done!\n"); +} // Initialize + +void SetAveraging(int NewN) +{ + N = NewN; + printf("averaging %d readings each time\n", N); +} // SetAveraging + +void SetOffsets(int TheOffsets[6]) +{ + accelgyro.setXAccelOffset(TheOffsets [iAx]); + accelgyro.setYAccelOffset(TheOffsets [iAy]); + accelgyro.setZAccelOffset(TheOffsets [iAz]); + accelgyro.setXGyroOffset (TheOffsets [iGx]); + accelgyro.setYGyroOffset (TheOffsets [iGy]); + accelgyro.setZGyroOffset (TheOffsets [iGz]); +} // SetOffsets + +void ShowProgress() +{ + if (LinesOut >= LinesBetweenHeaders) + { + // show header + printf("\tXAccel\t\t\tYAccel\t\t\t\tZAccel\t\t\tXGyro\t\t\tYGyro\t\t\tZGyro\n"); + LinesOut = 0; + } // show header + printf("%c", BLANK); + for (int i = iAx; i <= iGz; i++) + { + printf("%c%d%c%d] --> [%d%c%d", LBRACKET, LowOffset[i], COMMA, HighOffset[i], + LowValue[i], COMMA, HighValue[i]); + if (i == iGz) + { + printf("%c\n", RBRACKET); + } + else + { + printf("]\t"); + } + } + LinesOut++; +} // ShowProgress + +void PullBracketsIn() +{ + bool AllBracketsNarrow; + bool StillWorking; + int NewOffset[6]; + + printf("\nclosing in:\n"); + AllBracketsNarrow = false; + ForceHeader(); + StillWorking = true; + while (StillWorking) + { + StillWorking = false; + if (AllBracketsNarrow && (N == NFast)) + { + SetAveraging(NSlow); + } + else + { + AllBracketsNarrow = true; + }// tentative + for (int i = iAx; i <= iGz; i++) + { + if (HighOffset[i] <= (LowOffset[i]+1)) + { + NewOffset[i] = LowOffset[i]; + } + else + { + // binary search + StillWorking = true; + NewOffset[i] = (LowOffset[i] + HighOffset[i]) / 2; + if (HighOffset[i] > (LowOffset[i] + 10)) + { + AllBracketsNarrow = false; + } + } // binary search + } + SetOffsets(NewOffset); + GetSmoothed(); + for (int i = iAx; i <= iGz; i++) + { + // closing in + if (Smoothed[i] > Target[i]) + { + // use lower half + HighOffset[i] = NewOffset[i]; + HighValue[i] = Smoothed[i]; + } // use lower half + else + { + // use upper half + LowOffset[i] = NewOffset[i]; + LowValue[i] = Smoothed[i]; + } // use upper half + } // closing in + ShowProgress(); + } // still working +} // PullBracketsIn + +void PullBracketsOut() +{ + bool Done = false; + int NextLowOffset[6]; + int NextHighOffset[6]; + + printf("expanding:\n"); + ForceHeader(); + + while (!Done) + { + Done = true; + SetOffsets(LowOffset); + GetSmoothed(); + for (int i = iAx; i <= iGz; i++) + { + // got low values + LowValue[i] = Smoothed[i]; + if (LowValue[i] >= Target[i]) + { + Done = false; + NextLowOffset[i] = LowOffset[i] - 1000; + } + else + { + NextLowOffset[i] = LowOffset[i]; + } + } // got low values + + SetOffsets(HighOffset); + GetSmoothed(); + for (int i = iAx; i <= iGz; i++) + { + // got high values + HighValue[i] = Smoothed[i]; + if (HighValue[i] <= Target[i]) + { + Done = false; + NextHighOffset[i] = HighOffset[i] + 1000; + } + else + { + NextHighOffset[i] = HighOffset[i]; + } + } // got high values + ShowProgress(); + for (int i = iAx; i <= iGz; i++) + { + LowOffset[i] = NextLowOffset[i]; // had to wait until ShowProgress done + HighOffset[i] = NextHighOffset[i]; // .. + } + } // keep going +} // PullBracketsOut + + + +int main(int argc, char **argv) +{ + Initialize(); + for (int i = iAx; i <= iGz; i++) + { // set targets and initial guesses + Target[i] = 0; // must fix for ZAccel + HighOffset[i] = 0; + LowOffset[i] = 0; + } // set targets and initial guesses + Target[iAz] = 16384; + SetAveraging(NFast); + PullBracketsOut(); + PullBracketsIn(); + + printf("-------------- done --------------\n\n"); + return 0; +} diff --git a/RaspberryPi_bcm2835/MPU6050/examples/MPU6050_example_1.cpp b/RaspberryPi_bcm2835/MPU6050/examples/MPU6050_example_1.cpp index caad584c..5e4b6ac8 100644 --- a/RaspberryPi_bcm2835/MPU6050/examples/MPU6050_example_1.cpp +++ b/RaspberryPi_bcm2835/MPU6050/examples/MPU6050_example_1.cpp @@ -32,7 +32,7 @@ To compile on a Raspberry Pi (1 or 2) $ PATH_I2CDEVLIB=~/i2cdevlib/ $ gcc -o MPU6050_example_1 ${PATH_I2CDEVLIB}RaspberryPi_bcm2835/MPU6050/examples/MPU6050_example_1.cpp \ -I ${PATH_I2CDEVLIB}RaspberryPi_bcm2835/I2Cdev ${PATH_I2CDEVLIB}RaspberryPi_bcm2835/I2Cdev/I2Cdev.cpp \ - -I ${PATH_I2CDEVLIB}/Arduino/MPU6050/ ${PATH_I2CDEVLIB}/Arduino/MPU6050/MPU6050.cpp -l bcm2835 -l m + -I ${PATH_I2CDEVLIB}RaspberryPi_bcm2835/MPU6050/ ${PATH_I2CDEVLIB}RaspberryPi_bcm2835/MPU6050/MPU6050.cpp -l bcm2835 -l m $ sudo ./MPU6050_example_1 */ From b33a2cb664f608aad51f8123353ecb96de69b500 Mon Sep 17 00:00:00 2001 From: Mikael Johansson Date: Wed, 21 Oct 2020 21:37:54 +0200 Subject: [PATCH 255/335] Fixed compilation problem on Maixduino platform which lacks BUFFER_LENGTH by coping workaround from I2Cdev.cpp --- Arduino/MPU6050/MPU6050.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Arduino/MPU6050/MPU6050.cpp b/Arduino/MPU6050/MPU6050.cpp index f8c127da..267fca98 100644 --- a/Arduino/MPU6050/MPU6050.cpp +++ b/Arduino/MPU6050/MPU6050.cpp @@ -37,6 +37,11 @@ THE SOFTWARE. #include "MPU6050.h" +#ifndef BUFFER_LENGTH +// band-aid fix for platforms without Wire-defined BUFFER_LENGTH (removed from some official implementations) +#define BUFFER_LENGTH 32 +#endif + /** Specific address constructor. * @param address I2C address, uses default I2C address if none is specified * @see MPU6050_DEFAULT_ADDRESS From 415edcf87ee48e814f5c5d2e164375826665aed5 Mon Sep 17 00:00:00 2001 From: Drzony Date: Fri, 6 Nov 2020 14:39:43 +0100 Subject: [PATCH 256/335] Fixed NAN to int32_t conversion --- Arduino/BMP085/BMP085.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Arduino/BMP085/BMP085.cpp b/Arduino/BMP085/BMP085.cpp index 255858fb..f186d74f 100644 --- a/Arduino/BMP085/BMP085.cpp +++ b/Arduino/BMP085/BMP085.cpp @@ -250,7 +250,7 @@ int32_t BMP085::getPressure() { p = p + (X1 + X2 + 3791) / 2^4 */ uint32_t up = getRawPressure(); - if(up == 0) return NAN; + if(up == 0) return 0; uint8_t oss = (measureMode & 0xC0) >> 6; int32_t p; int32_t b6 = b5 - 4000; From eb5a9ba34d6e0bf83f1c7d920bc73fb68dda1633 Mon Sep 17 00:00:00 2001 From: Drzony Date: Fri, 6 Nov 2020 14:40:23 +0100 Subject: [PATCH 257/335] Modified library.json files to be usable on all platforms --- Arduino/AD7746/library.json | 2 +- Arduino/ADS1115/library.json | 2 +- Arduino/ADXL345/library.json | 2 +- Arduino/AK8963/library.json | 2 +- Arduino/AK8975/library.json | 2 +- Arduino/BMA150/library.json | 2 +- Arduino/BMP085/library.json | 2 +- Arduino/DS1307/library.json | 2 +- Arduino/HMC5843/library.json | 2 +- Arduino/HMC5883L/library.json | 2 +- Arduino/HTU21D/library.json | 2 +- Arduino/I2Cdev/library.json | 2 +- Arduino/IAQ2000/library.json | 2 +- Arduino/ITG3200/library.json | 2 +- Arduino/L3G4200D/library.json | 2 +- Arduino/LM73/library.json | 2 +- Arduino/MPR121/library.json | 2 +- Arduino/MPU6050/library.json | 2 +- Arduino/MPU9150/library.json | 2 +- Arduino/SSD1308/library.json | 2 +- Arduino/TCA6424A/library.json | 2 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/Arduino/AD7746/library.json b/Arduino/AD7746/library.json index 70940ff0..0065cef3 100644 --- a/Arduino/AD7746/library.json +++ b/Arduino/AD7746/library.json @@ -14,5 +14,5 @@ "frameworks": "arduino" }, "frameworks": "arduino", - "platforms": "atmelavr" + "platforms": "*" } diff --git a/Arduino/ADS1115/library.json b/Arduino/ADS1115/library.json index e3e65531..493cb1ff 100644 --- a/Arduino/ADS1115/library.json +++ b/Arduino/ADS1115/library.json @@ -14,5 +14,5 @@ "frameworks": "arduino" }, "frameworks": "arduino", - "platforms": "atmelavr" + "platforms": "*" } diff --git a/Arduino/ADXL345/library.json b/Arduino/ADXL345/library.json index bb714182..26d250bf 100644 --- a/Arduino/ADXL345/library.json +++ b/Arduino/ADXL345/library.json @@ -14,5 +14,5 @@ "frameworks": "arduino" }, "frameworks": "arduino", - "platforms": "atmelavr" + "platforms": "*" } diff --git a/Arduino/AK8963/library.json b/Arduino/AK8963/library.json index 69da4f27..c6db7829 100644 --- a/Arduino/AK8963/library.json +++ b/Arduino/AK8963/library.json @@ -16,5 +16,5 @@ } ], "frameworks": "arduino", - "platforms": "atmelavr" + "platforms": "*" } diff --git a/Arduino/AK8975/library.json b/Arduino/AK8975/library.json index 0010d1ef..b879c39b 100644 --- a/Arduino/AK8975/library.json +++ b/Arduino/AK8975/library.json @@ -20,5 +20,5 @@ } ], "frameworks": "arduino", - "platforms": "atmelavr" + "platforms": "*" } diff --git a/Arduino/BMA150/library.json b/Arduino/BMA150/library.json index bd28c410..e4d50fcf 100644 --- a/Arduino/BMA150/library.json +++ b/Arduino/BMA150/library.json @@ -14,5 +14,5 @@ "frameworks": "arduino" }, "frameworks": "arduino", - "platforms": "atmelavr" + "platforms": "*" } diff --git a/Arduino/BMP085/library.json b/Arduino/BMP085/library.json index a29ef252..a9059ba9 100644 --- a/Arduino/BMP085/library.json +++ b/Arduino/BMP085/library.json @@ -14,5 +14,5 @@ "frameworks": "arduino" }, "frameworks": "arduino", - "platforms": "atmelavr" + "platforms": "*" } diff --git a/Arduino/DS1307/library.json b/Arduino/DS1307/library.json index 8dba5473..79955581 100644 --- a/Arduino/DS1307/library.json +++ b/Arduino/DS1307/library.json @@ -14,5 +14,5 @@ "frameworks": "arduino" }, "frameworks": "arduino", - "platforms": "atmelavr" + "platforms": "*" } diff --git a/Arduino/HMC5843/library.json b/Arduino/HMC5843/library.json index 51f6926e..f3aea49b 100644 --- a/Arduino/HMC5843/library.json +++ b/Arduino/HMC5843/library.json @@ -14,5 +14,5 @@ "frameworks": "arduino" }, "frameworks": "arduino", - "platforms": "atmelavr" + "platforms": "*" } diff --git a/Arduino/HMC5883L/library.json b/Arduino/HMC5883L/library.json index 14614e9b..06448562 100644 --- a/Arduino/HMC5883L/library.json +++ b/Arduino/HMC5883L/library.json @@ -14,5 +14,5 @@ "frameworks": "arduino" }, "frameworks": "arduino", - "platforms": "atmelavr" + "platforms": "*" } diff --git a/Arduino/HTU21D/library.json b/Arduino/HTU21D/library.json index 6afea2ab..1736f263 100644 --- a/Arduino/HTU21D/library.json +++ b/Arduino/HTU21D/library.json @@ -14,5 +14,5 @@ "frameworks": "arduino" }, "frameworks": "arduino", - "platforms": "atmelavr" + "platforms": "*" } diff --git a/Arduino/I2Cdev/library.json b/Arduino/I2Cdev/library.json index 074266da..5c5eab8f 100644 --- a/Arduino/I2Cdev/library.json +++ b/Arduino/I2Cdev/library.json @@ -9,7 +9,7 @@ "url": "https://github.com/jrowberg/i2cdevlib.git" }, "frameworks": "arduino", - "platforms": "atmelavr", + "platforms": "*", "dependencies": [ { "name": "Wire" diff --git a/Arduino/IAQ2000/library.json b/Arduino/IAQ2000/library.json index 5eb15957..12d70f8b 100644 --- a/Arduino/IAQ2000/library.json +++ b/Arduino/IAQ2000/library.json @@ -14,5 +14,5 @@ "frameworks": "arduino" }, "frameworks": "arduino", - "platforms": "atmelavr" + "platforms": "*" } diff --git a/Arduino/ITG3200/library.json b/Arduino/ITG3200/library.json index 398dfcdf..c4a69b66 100644 --- a/Arduino/ITG3200/library.json +++ b/Arduino/ITG3200/library.json @@ -14,5 +14,5 @@ "frameworks": "arduino" }, "frameworks": "arduino", - "platforms": "atmelavr" + "platforms": "*" } diff --git a/Arduino/L3G4200D/library.json b/Arduino/L3G4200D/library.json index f899e316..185d66fa 100644 --- a/Arduino/L3G4200D/library.json +++ b/Arduino/L3G4200D/library.json @@ -14,5 +14,5 @@ "frameworks": "arduino" }, "frameworks": "arduino", - "platforms": "atmelavr" + "platforms": "*" } diff --git a/Arduino/LM73/library.json b/Arduino/LM73/library.json index f547a772..a1afad4c 100644 --- a/Arduino/LM73/library.json +++ b/Arduino/LM73/library.json @@ -14,5 +14,5 @@ "frameworks": "arduino" }, "frameworks": "arduino", - "platforms": "atmelavr" + "platforms": "*" } diff --git a/Arduino/MPR121/library.json b/Arduino/MPR121/library.json index afce11bb..dbe47d8b 100644 --- a/Arduino/MPR121/library.json +++ b/Arduino/MPR121/library.json @@ -14,5 +14,5 @@ "frameworks": "arduino" }, "frameworks": "arduino", - "platforms": "atmelavr" + "platforms": "*" } diff --git a/Arduino/MPU6050/library.json b/Arduino/MPU6050/library.json index 174b4529..e89e10cb 100644 --- a/Arduino/MPU6050/library.json +++ b/Arduino/MPU6050/library.json @@ -14,5 +14,5 @@ "frameworks": "arduino" }, "frameworks": "arduino", - "platforms": "atmelavr" + "platforms": "*" } diff --git a/Arduino/MPU9150/library.json b/Arduino/MPU9150/library.json index 38cde7e1..abf665ae 100644 --- a/Arduino/MPU9150/library.json +++ b/Arduino/MPU9150/library.json @@ -14,5 +14,5 @@ "frameworks": "arduino" }, "frameworks": "arduino", - "platforms": "atmelavr" + "platforms": "*" } diff --git a/Arduino/SSD1308/library.json b/Arduino/SSD1308/library.json index 9e0db1cd..ede7dff1 100644 --- a/Arduino/SSD1308/library.json +++ b/Arduino/SSD1308/library.json @@ -14,5 +14,5 @@ "frameworks": "arduino" }, "frameworks": "arduino", - "platforms": "atmelavr" + "platforms": "*" } diff --git a/Arduino/TCA6424A/library.json b/Arduino/TCA6424A/library.json index a0779dfb..0b97b21b 100644 --- a/Arduino/TCA6424A/library.json +++ b/Arduino/TCA6424A/library.json @@ -14,5 +14,5 @@ "frameworks": "arduino" }, "frameworks": "arduino", - "platforms": "atmelavr" + "platforms": "*" } From 10bcf2b49f82feec316871ac360a7e0be25b45f8 Mon Sep 17 00:00:00 2001 From: Jeff Rowberg Date: Fri, 22 Jan 2021 11:53:52 -0500 Subject: [PATCH 258/335] Fix leftover debug output to use debug macros --- Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h index 5572d1aa..ee14f98a 100644 --- a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h +++ b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h @@ -291,10 +291,10 @@ uint8_t MPU6050::dmpInitialize() { // get MPU hardware revision setMemoryBank(0x10, true, true); setMemoryStartAddress(0x06); - Serial.println(F("Checking hardware revision...")); - Serial.print(F("Revision @ user[16][6] = ")); - Serial.println(readMemoryByte(), HEX); - Serial.println(F("Resetting memory bank selection to 0...")); + DEBUG_PRINTLN(F("Checking hardware revision...")); + DEBUG_PRINT(F("Revision @ user[16][6] = ")); + DEBUG_PRINTLN(readMemoryByte()); + DEBUG_PRINTLN(F("Resetting memory bank selection to 0...")); setMemoryBank(0, false, false); // check OTP bank valid From 1e01283140b408a3c0597b9c07f0af5c841fbca1 Mon Sep 17 00:00:00 2001 From: devourer66 <57077168+devourer66@users.noreply.github.com> Date: Sun, 7 Mar 2021 16:17:47 +0300 Subject: [PATCH 259/335] Added 3d plane model to a Processing example for MPU6050 --- .../MPUplane/MPUplane.pde | 189 ++ .../MPUplane/data/biplane.obj | 2239 +++++++++++++++++ .../MPUplane/data/diffuse_512.png | Bin 0 -> 361095 bytes 3 files changed, 2428 insertions(+) create mode 100644 Arduino/MPU6050/examples/MPU6050_DMP6_using_DMP_V6.12/MPUplane/MPUplane.pde create mode 100644 Arduino/MPU6050/examples/MPU6050_DMP6_using_DMP_V6.12/MPUplane/data/biplane.obj create mode 100644 Arduino/MPU6050/examples/MPU6050_DMP6_using_DMP_V6.12/MPUplane/data/diffuse_512.png diff --git a/Arduino/MPU6050/examples/MPU6050_DMP6_using_DMP_V6.12/MPUplane/MPUplane.pde b/Arduino/MPU6050/examples/MPU6050_DMP6_using_DMP_V6.12/MPUplane/MPUplane.pde new file mode 100644 index 00000000..ce4a6fda --- /dev/null +++ b/Arduino/MPU6050/examples/MPU6050_DMP6_using_DMP_V6.12/MPUplane/MPUplane.pde @@ -0,0 +1,189 @@ +// I2C device class (I2Cdev) demonstration Processing sketch for MPU6050 DMP output +// 6/20/2012 by Jeff Rowberg +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// 2012-06-20 - initial release +// 2016-10-28 - Changed to bi-plane 3d model based on tutorial at +// https://forum.processing.org/two/discussion/24350/display-obj-file-in-3d +// https://opengameart.org/content/low-poly-biplane + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2012 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +import processing.serial.*; +//import processing.opengl.*; +import toxi.geom.*; +import toxi.processing.*; + +// NOTE: requires ToxicLibs to be installed in order to run properly. +// 1. Download from http://toxiclibs.org/downloads +// 2. Extract into [userdir]/Processing/libraries +// (location may be different on Mac/Linux) +// 3. Run and bask in awesomeness + +ToxiclibsSupport gfx; + +Serial port; // The serial port +char[] teapotPacket = new char[14]; // InvenSense Teapot packet +int serialCount = 0; // current packet byte position +int synced = 0; +int interval = 0; + +float[] q = new float[4]; +Quaternion quat = new Quaternion(1, 0, 0, 0); + +float[] gravity = new float[3]; +float[] euler = new float[3]; +float[] ypr = new float[3]; + + +PShape plane; // 3d model + +void setup() { + // 640x480 px square viewport + size(640, 480, P3D); + gfx = new ToxiclibsSupport(this); + + // setup lights and antialiasing + lights(); + smooth(); + + // display serial port list for debugging/clarity + println(Serial.list()); + + // get a specific serial port + String portName = "COM12"; + + // open the serial port + port = new Serial(this, portName, 115200); + + // send single character to trigger DMP init/start + // (expected by MPU6050_DMP6 example Arduino sketch) + port.write('r'); + + // Load Plane object + // The file must be in the \data folder + // of the current sketch to load successfully + plane = loadShape("biplane.obj"); + + + // apply its texture and set orientation + PImage img1=loadImage("diffuse_512.png"); + plane.setTexture(img1); + plane.scale(30); + plane.rotateX(PI); + plane.rotateY(PI+HALF_PI); + + +} + +void draw() { + if (millis() - interval > 1000) { + // resend single character to trigger DMP init/start + // in case the MPU is halted/reset while applet is running + port.write('r'); + interval = millis(); + } + + // black background + background(0); + + + // translate everything to the middle of the viewport + pushMatrix(); + translate(width / 2, height / 2); + + // toxiclibs direct angle/axis rotation from quaternion (NO gimbal lock!) + // (axis order [1, 3, 2] and inversion [-1, +1, +1] is a consequence of + // different coordinate system orientation assumptions between Processing + // and InvenSense DMP) + float[] axis = quat.toAxisAngle(); + rotate(axis[0], -axis[1], axis[3], axis[2]); + + // draw plane + shape(plane, 0, 0); + + popMatrix(); +} + +void serialEvent(Serial port) { + interval = millis(); + while (port.available() > 0) { + int ch = port.read(); + + if (synced == 0 && ch != '$') return; // initial synchronization - also used to resync/realign if needed + synced = 1; + print ((char)ch); + + if ((serialCount == 1 && ch != 2) + || (serialCount == 12 && ch != '\r') + || (serialCount == 13 && ch != '\n')) { + serialCount = 0; + synced = 0; + return; + } + + if (serialCount > 0 || ch == '$') { + teapotPacket[serialCount++] = (char)ch; + if (serialCount == 14) { + serialCount = 0; // restart packet byte position + + // get quaternion from data packet + q[0] = ((teapotPacket[2] << 8) | teapotPacket[3]) / 16384.0f; + q[1] = ((teapotPacket[4] << 8) | teapotPacket[5]) / 16384.0f; + q[2] = ((teapotPacket[6] << 8) | teapotPacket[7]) / 16384.0f; + q[3] = ((teapotPacket[8] << 8) | teapotPacket[9]) / 16384.0f; + for (int i = 0; i < 4; i++) if (q[i] >= 2) q[i] = -4 + q[i]; + + // set our toxilibs quaternion to new data + quat.set(q[0], q[1], q[2], q[3]); + + + // below calculations unnecessary for orientation only using toxilibs + + // calculate gravity vector + gravity[0] = 2 * (q[1]*q[3] - q[0]*q[2]); + gravity[1] = 2 * (q[0]*q[1] + q[2]*q[3]); + gravity[2] = q[0]*q[0] - q[1]*q[1] - q[2]*q[2] + q[3]*q[3]; + + // calculate Euler angles + euler[0] = atan2(2*q[1]*q[2] - 2*q[0]*q[3], 2*q[0]*q[0] + 2*q[1]*q[1] - 1); + euler[1] = -asin(2*q[1]*q[3] + 2*q[0]*q[2]); + euler[2] = atan2(2*q[2]*q[3] - 2*q[0]*q[1], 2*q[0]*q[0] + 2*q[3]*q[3] - 1); + + // calculate yaw/pitch/roll angles + ypr[0] = atan2(2*q[1]*q[2] - 2*q[0]*q[3], 2*q[0]*q[0] + 2*q[1]*q[1] - 1); + ypr[1] = atan(gravity[0] / sqrt(gravity[1]*gravity[1] + gravity[2]*gravity[2])); + ypr[2] = atan(gravity[1] / sqrt(gravity[0]*gravity[0] + gravity[2]*gravity[2])); + + // output various components for debugging + println("q:\t" + round(q[0]*100.0f)/100.0f + "\t" + round(q[1]*100.0f)/100.0f + "\t" + round(q[2]*100.0f)/100.0f + "\t" + round(q[3]*100.0f)/100.0f); + println("euler:\t" + euler[0]*180.0f/PI + "\t" + euler[1]*180.0f/PI + "\t" + euler[2]*180.0f/PI); + println("ypr:\t" + ypr[0]*180.0f/PI + "\t" + ypr[1]*180.0f/PI + "\t" + ypr[2]*180.0f/PI); + + } + } + } +} diff --git a/Arduino/MPU6050/examples/MPU6050_DMP6_using_DMP_V6.12/MPUplane/data/biplane.obj b/Arduino/MPU6050/examples/MPU6050_DMP6_using_DMP_V6.12/MPUplane/data/biplane.obj new file mode 100644 index 00000000..6867928e --- /dev/null +++ b/Arduino/MPU6050/examples/MPU6050_DMP6_using_DMP_V6.12/MPUplane/data/biplane.obj @@ -0,0 +1,2239 @@ +v 4.500000 0.176989 0.367522 +v 4.500000 0.318923 0.254332 +v 4.500000 0.397690 0.090770 +v 4.500000 0.397690 -0.090770 +v 4.500000 0.318923 -0.254333 +v 4.500000 0.176989 -0.367521 +v 4.500000 0.000000 -0.407918 +v 4.500000 -0.176989 -0.367521 +v 4.500000 -0.318923 -0.254332 +v 4.500000 -0.397691 -0.090770 +v 4.500000 -0.397691 0.090770 +v 4.500000 -0.318923 0.254333 +v 4.500001 -0.176989 0.367522 +v 4.500000 0.000000 0.407918 +v 2.700000 0.259478 0.538812 +v 2.700000 0.467563 0.372869 +v 2.700000 0.583042 0.133076 +v 2.700000 0.583042 -0.133076 +v 2.700000 0.467563 -0.372869 +v 2.700000 0.259478 -0.538812 +v 2.700000 0.000000 -0.598036 +v 2.700000 -0.259478 -0.538812 +v 2.700000 -0.467563 -0.372869 +v 2.700000 -0.583042 -0.133075 +v 2.700000 -0.583042 0.133075 +v 2.700000 -0.467563 0.372870 +v 2.700000 -0.259478 0.538812 +v 2.700000 0.000000 0.598036 +v 0.900000 0.323112 0.670950 +v 0.900000 0.582229 0.464312 +v 0.900000 0.726027 0.165711 +v 0.900000 0.726027 -0.165711 +v 0.900000 0.582229 -0.464312 +v 0.900000 0.323113 -0.670950 +v 0.900000 0.000000 -0.744698 +v 0.900000 -0.323112 -0.670950 +v 0.900000 -0.582229 -0.464312 +v 0.900000 -0.726027 -0.165711 +v 0.900000 -0.726027 0.165711 +v 0.900000 -0.582229 0.464312 +v 0.900000 -0.323113 0.670950 +v 0.900000 0.000000 0.744699 +v -0.900000 0.384390 0.798195 +v -0.900000 0.692647 0.552368 +v -0.475444 0.863717 0.197138 +v -0.475445 0.863717 -0.197138 +v -0.900000 0.692647 -0.552368 +v -0.900000 0.384390 -0.798194 +v -0.900000 0.000000 -0.885929 +v -0.900000 -0.384390 -0.798195 +v -0.900000 -0.692647 -0.552368 +v -0.900000 -0.863717 -0.197138 +v -0.900000 -0.863717 0.197138 +v -0.900000 -0.692647 0.552368 +v -0.900000 -0.384390 0.798195 +v -0.900000 0.000000 0.885929 +v -2.700000 0.433883 0.900969 +v -2.700000 0.781831 0.623490 +v -2.885778 0.974928 0.222521 +v -2.885778 0.974928 -0.222521 +v -2.700000 0.781832 -0.623490 +v -2.699999 0.433884 -0.900969 +v -2.699999 0.000000 -1.000000 +v -2.700000 -0.433883 -0.900969 +v -2.700000 -0.781831 -0.623490 +v -2.700000 -0.974928 -0.222521 +v -2.700000 -0.974928 0.222521 +v -2.700000 -0.781832 0.623489 +v -2.700000 -0.433884 0.900969 +v -2.700000 0.000000 1.000000 +v 4.500000 0.000000 -0.000000 +v -5.181942 0.000000 -0.000000 +v 5.269916 1.092397 0.090771 +v 5.269916 1.092397 -0.090770 +v 3.399458 1.972455 0.000001 +v 5.551387 0.000000 -0.000000 +v 4.141554 0.176989 1.784806 +v 4.500000 0.318923 1.235124 +v 2.700000 0.467563 1.342699 +v 3.058446 0.259478 1.802116 +v 4.500000 0.318923 -1.235123 +v 4.141554 0.176989 -1.784806 +v 3.058446 0.259478 -1.802116 +v 2.700000 0.467563 -1.342699 +v -1.300000 1.103771 0.487962 +v -1.125000 1.252653 0.195352 +v -2.475000 1.333997 0.213918 +v -2.300000 1.156989 0.519851 +v -1.125000 1.252653 -0.195351 +v -2.475000 1.333997 -0.213917 +v -1.300000 1.103772 -0.487962 +v -2.300000 1.156989 -0.519851 +v -1.799999 1.281724 0.398879 +v -1.125000 1.187470 0.380784 +v -1.800000 1.350005 0.204635 +v -2.475000 1.262618 0.416974 +v -1.800000 1.156763 0.540666 +v -1.800000 1.372766 0.000000 +v -1.125000 1.274381 0.000000 +v -1.800000 1.350006 -0.204634 +v -2.475000 1.357790 0.000000 +v -1.800000 1.281724 -0.398879 +v -1.125000 1.187470 -0.380784 +v -1.800000 1.156763 -0.540666 +v -2.475000 1.262618 -0.416974 +v -0.825593 1.004904 0.374753 +v -0.475445 0.778182 0.374753 +v -0.825593 1.069055 0.192257 +v -1.125000 0.951901 0.516854 +v -2.700000 1.105101 0.423005 +v -2.885779 0.878380 0.423006 +v -2.475000 1.021542 0.564478 +v -2.700000 1.177512 0.217012 +v -1.800000 0.963961 0.587929 +v -1.800000 0.737239 0.587929 +v -0.825593 1.090439 0.000000 +v -0.475445 0.863717 0.000000 +v -0.825593 1.069055 -0.192257 +v -2.700000 1.201650 0.000000 +v -2.885779 0.974928 0.000000 +v -2.700000 1.177513 -0.217012 +v -0.825592 1.004904 -0.374753 +v -0.475444 0.778182 -0.374753 +v -1.125000 0.951901 -0.516854 +v -1.800000 0.963961 -0.587929 +v -1.800000 0.737239 -0.587929 +v -2.475000 1.021542 -0.564478 +v -2.700000 1.105101 -0.423005 +v -2.885778 0.878380 -0.423005 +v 2.700000 0.583042 0.000000 +v 0.900000 0.726027 0.005801 +v -5.181943 -0.629401 -0.501931 +v -4.986976 -0.781831 -0.623490 +v -5.181942 -0.784850 -0.179137 +v -4.986976 -0.974928 -0.222521 +v -5.181942 -0.784850 0.179137 +v -4.986976 -0.974928 0.222521 +v -5.181942 -0.629401 0.501930 +v -4.986977 -0.781831 0.623490 +v -5.181942 -0.349291 0.725311 +v -4.986976 -0.433884 0.900969 +v -4.986976 0.000000 1.000000 +v -5.181942 0.000000 0.805034 +v -5.181942 0.629401 -0.501930 +v -4.987885 0.789991 -0.606546 +v -4.986976 0.781832 -0.623490 +v -5.181942 0.349291 -0.725310 +v -4.986977 0.433884 -0.900968 +v -4.986976 0.433884 0.900969 +v -5.181942 0.349291 0.725311 +v -4.986976 0.781831 0.623490 +v -4.987885 0.789991 0.606546 +v -5.181942 0.629401 0.501931 +v -4.986976 0.974928 0.222521 +v -5.181942 0.784301 0.179012 +v -5.181942 0.000000 -0.805034 +v -4.986976 0.000000 -1.000000 +v -5.181942 -0.349291 -0.725310 +v -4.986976 -0.433884 -0.900969 +v -5.181942 0.784301 -0.179011 +v -4.986976 0.974928 -0.222521 +v -5.181942 0.779962 0.000001 +v -4.986976 0.974928 0.000000 +vt 0.455704 0.153054 +vt 0.419776 0.128644 +vt 0.383319 0.143119 +vt 0.328896 0.143119 +vt 0.292439 0.128644 +vt 0.256511 0.153054 +vt 0.245563 0.201018 +vt 0.256511 0.248981 +vt 0.287184 0.287445 +vt 0.331509 0.308790 +vt 0.380706 0.308790 +vt 0.425031 0.287445 +vt 0.455704 0.248981 +vt 0.466652 0.201018 +vt 0.005173 0.359445 +vt 0.016095 0.354912 +vt 0.061664 0.354281 +vt 0.166522 0.327467 +vt 0.186034 0.323730 +vt 0.219371 0.310411 +vt 0.248725 0.289652 +vt 0.263886 0.273262 +vt 0.275993 0.321494 +vt 0.305445 0.321494 +vt 0.334898 0.321494 +vt 0.364351 0.321494 +vt 0.393803 0.321494 +vt 0.423256 0.321494 +vt 0.452709 0.321494 +vt 0.019054 0.449768 +vt 0.082140 0.442189 +vt 0.099276 0.445505 +vt 0.128729 0.445505 +vt 0.158182 0.445505 +vt 0.187634 0.445505 +vt 0.217087 0.445505 +vt 0.246540 0.445505 +vt 0.275993 0.445505 +vt 0.305445 0.445505 +vt 0.334898 0.445505 +vt 0.364351 0.445505 +vt 0.393803 0.445505 +vt 0.423256 0.445505 +vt 0.452709 0.445505 +vt 0.040371 0.569517 +vt 0.069824 0.569517 +vt 0.099276 0.569517 +vt 0.128729 0.569517 +vt 0.158182 0.569517 +vt 0.187634 0.569517 +vt 0.217087 0.569517 +vt 0.246540 0.569517 +vt 0.275993 0.569517 +vt 0.305445 0.569517 +vt 0.334898 0.569517 +vt 0.364351 0.569517 +vt 0.393803 0.569517 +vt 0.423256 0.569517 +vt 0.452709 0.569517 +vt 0.040371 0.693528 +vt 0.073505 0.709029 +vt 0.099276 0.685777 +vt 0.128729 0.685777 +vt 0.154500 0.709029 +vt 0.187634 0.693528 +vt 0.217087 0.693528 +vt 0.246540 0.693528 +vt 0.275993 0.693528 +vt 0.305445 0.693528 +vt 0.334898 0.693528 +vt 0.364351 0.693528 +vt 0.393803 0.693528 +vt 0.423256 0.693528 +vt 0.452709 0.693528 +vt 0.040371 0.817539 +vt 0.073505 0.802038 +vt 0.154500 0.802038 +vt 0.356107 0.180046 +vt 0.098756 0.319100 +vt 0.114003 0.445505 +vt 0.087917 0.323202 +vt 0.360587 0.109025 +vt 0.356108 0.136215 +vt 0.351628 0.109025 +vt 0.023534 0.441375 +vt 0.044323 0.425256 +vt 0.082140 0.442189 +vt 0.019054 0.449768 +vt 0.204695 0.353513 +vt 0.203181 0.378966 +vt 0.187634 0.445505 +vt 0.158182 0.445505 +vt 0.076369 0.721086 +vt 0.099276 0.709029 +vt 0.099276 0.802038 +vt 0.076369 0.789982 +vt 0.128729 0.709029 +vt 0.128729 0.802038 +vt 0.151637 0.721086 +vt 0.151637 0.789982 +vt 0.084550 0.755534 +vt 0.084550 0.709029 +vt 0.099276 0.755534 +vt 0.084550 0.802038 +vt 0.073505 0.755534 +vt 0.114003 0.755534 +vt 0.114003 0.709029 +vt 0.128729 0.755534 +vt 0.114003 0.802038 +vt 0.143455 0.755534 +vt 0.143455 0.709029 +vt 0.154500 0.755534 +vt 0.143455 0.802038 +vt 0.084550 0.693528 +vt 0.084550 0.693528 +vt 0.099276 0.693528 +vt 0.073505 0.709029 +vt 0.084550 0.817539 +vt 0.073505 0.802038 +vt 0.099276 0.817539 +vt 0.069824 0.755534 +vt 0.069824 0.755534 +vt 0.114003 0.693528 +vt 0.114003 0.693528 +vt 0.128729 0.693528 +vt 0.114003 0.817539 +vt 0.128729 0.817539 +vt 0.143455 0.693528 +vt 0.143455 0.693528 +vt 0.154500 0.709029 +vt 0.158182 0.755534 +vt 0.158182 0.755534 +vt 0.154500 0.802038 +vt 0.143455 0.817539 +vt 0.114003 0.445505 +vt 0.113487 0.569517 +vt 0.084550 0.817539 +vt 0.063450 0.938935 +vt 0.275993 0.817539 +vt 0.060733 0.120401 +vt 0.305445 0.817539 +vt 0.104650 0.099252 +vt 0.334898 0.817539 +vt 0.153395 0.099252 +vt 0.364351 0.817539 +vt 0.197313 0.120401 +vt 0.423256 0.925429 +vt 0.393803 0.817539 +vt 0.423256 0.817539 +vt 0.143455 0.817539 +vt 0.060733 0.291667 +vt 0.030341 0.253557 +vt 0.449688 0.935863 +vt 0.452709 0.817539 +vt 0.053984 0.934786 +vt 0.017895 0.932919 +vt 0.100219 0.950069 +vt 0.102123 0.931740 +vt 0.099276 0.825290 +vt 0.217087 0.817539 +vt 0.187634 0.817539 +vt 0.019494 0.206034 +vt 0.030341 0.158511 +vt 0.246540 0.817539 +vt 0.104667 0.312738 +vt 0.129023 0.201653 +vt 0.128729 0.825290 +vt 0.114003 0.817539 +vt 0.129023 0.312124 +vt 0.275993 0.931809 +vt 0.273121 0.941551 +vt 0.249411 0.941551 +vt 0.278864 0.941551 +vt 0.305445 0.931809 +vt 0.302574 0.941551 +vt 0.308316 0.941551 +vt 0.334898 0.931809 +vt 0.332027 0.941551 +vt 0.337769 0.941551 +vt 0.364351 0.931809 +vt 0.361480 0.941551 +vt 0.367222 0.941551 +vt 0.396310 0.932910 +vt 0.390932 0.941551 +vt 0.227704 0.158511 +vt 0.153378 0.312738 +vt 0.066951 0.949302 +vt 0.411698 0.969294 +vt 0.007495 0.983733 +vt 0.156937 0.931070 +vt 0.155311 0.941551 +vt 0.131609 0.941551 +vt 0.161053 0.941551 +vt 0.187634 0.931809 +vt 0.184763 0.941551 +vt 0.190506 0.941551 +vt 0.217087 0.931809 +vt 0.214216 0.941551 +vt 0.437979 0.994491 +vt 0.197313 0.291667 +vt 0.050289 0.993403 +vt 0.393883 0.992961 +vt 0.238551 0.206034 +vt 0.102156 0.941551 +vt 0.114003 0.931021 +vt 0.219958 0.941551 +vt 0.246540 0.931809 +vt 0.243669 0.941551 +vt 0.128729 0.931680 +vt 0.125850 0.941551 +vt 0.114003 0.941551 +vt 0.158299 0.939937 +vt 0.157893 0.930592 +vt 0.227704 0.253557 +vt 0.046355 0.992034 +vt 0.421247 0.969294 +vn 0.089573 0.940981 0.326392 +vn 0.089573 0.940981 0.326392 +vn 0.089573 0.940981 0.326392 +vn 0.089573 0.940981 0.326392 +vn 0.089574 0.940981 -0.326392 +vn 0.089574 0.940981 -0.326392 +vn 0.089574 0.940981 -0.326392 +vn 0.089574 0.940981 -0.326392 +vn 0.150361 -0.955640 -0.253265 +vn 0.180233 0.000001 -0.983624 +vn 0.091281 0.000000 -0.995825 +vn -0.150994 -0.690915 -0.706992 +vn 0.180233 -0.426779 -0.886214 +vn 0.091281 -0.432073 -0.897208 +vn 0.180233 -0.769028 -0.613280 +vn 0.091281 -0.778567 -0.620887 +vn 0.180233 -0.958962 -0.218877 +vn 0.091281 -0.970858 -0.221593 +vn 0.180233 -0.958962 0.218877 +vn 0.091281 -0.970858 0.221592 +vn 0.180233 -0.769028 0.613280 +vn 0.091281 -0.778567 0.620887 +vn 0.180234 -0.426778 0.886214 +vn 0.091281 -0.432072 0.897208 +vn 0.180233 -0.000000 0.983624 +vn 0.091281 0.000000 0.995825 +vn 0.150361 -0.955640 0.253265 +vn 0.016625 -0.653805 0.756481 +vn 0.079554 0.000000 -0.996831 +vn 0.079554 0.432509 -0.898113 +vn 0.079554 -0.432508 -0.898113 +vn 0.079554 -0.779353 -0.621514 +vn 0.079554 -0.971838 -0.221816 +vn 0.079554 -0.971838 0.221816 +vn 0.079554 -0.779354 0.621514 +vn 0.079554 -0.432509 0.898113 +vn 0.079554 0.000000 0.996831 +vn 0.070121 -0.432816 -0.898751 +vn 0.070121 0.000000 -0.997539 +vn 0.070121 -0.779907 -0.621955 +vn 0.070121 -0.972528 -0.221973 +vn 0.070121 -0.972528 0.221973 +vn 0.070121 -0.779907 0.621955 +vn 0.070121 -0.432816 0.898751 +vn 0.130833 0.712633 0.689229 +vn 0.130833 0.712633 0.689229 +vn 0.130833 0.712633 0.689229 +vn 0.130833 0.712633 0.689229 +vn 0.143365 0.983605 0.109401 +vn 0.143365 0.983605 0.109401 +vn 0.143365 0.983605 0.109401 +vn 0.143365 0.983605 0.109401 +vn 0.139254 0.934218 -0.328397 +vn 0.139254 0.934218 -0.328397 +vn 0.139254 0.934218 -0.328397 +vn 0.139254 0.934218 -0.328397 +vn 0.026848 -0.433727 -0.900644 +vn 0.026848 0.000000 -0.999640 +vn 0.026848 -0.781550 -0.623265 +vn 0.026848 -0.974576 -0.222441 +vn 0.026848 -0.974577 0.222441 +vn 0.026848 -0.781550 0.623265 +vn 0.026848 -0.433728 0.900644 +vn -0.064587 -0.972892 -0.222057 +vn -0.064587 -0.780199 -0.622188 +vn -0.064587 -0.972892 0.222056 +vn -0.064587 -0.780199 0.622188 +vn -0.064587 -0.432978 0.899088 +vn 0.870350 -0.485974 0.079502 +vn 1.000000 -0.000000 -0.000000 +vn 1.000000 0.000002 -0.000003 +vn 0.870349 -0.485975 -0.079503 +vn 1.000000 -0.000003 0.000000 +vn 0.733799 -0.670454 0.109683 +vn 0.733799 -0.670454 0.109683 +vn 0.082297 0.996608 0.000000 +vn 0.082297 0.996608 0.000000 +vn 0.082297 0.996608 0.000000 +vn 0.082297 0.996608 0.000000 +vn -0.842065 -0.522167 0.135162 +vn -0.842065 -0.522167 0.135162 +vn -0.842065 -0.522167 0.135162 +vn -0.842065 -0.522167 0.135162 +vn -0.057129 -0.998367 0.000000 +vn -0.057129 -0.998367 0.000000 +vn 0.733799 -0.670455 -0.109683 +vn 0.733799 -0.670455 -0.109683 +vn -0.057129 -0.998367 -0.000000 +vn -0.057129 -0.998367 -0.000000 +vn -0.045744 0.737399 -0.673906 +vn -0.842065 -0.522167 -0.135162 +vn -0.842065 -0.522167 -0.135162 +vn 0.082297 0.996608 0.000000 +vn 0.082297 0.996608 0.000000 +vn 0.082297 0.996608 0.000000 +vn 0.082297 0.996608 0.000000 +vn 0.139254 0.934218 0.328398 +vn 0.139254 0.934218 0.328398 +vn 0.139254 0.934218 0.328398 +vn 0.139254 0.934218 0.328398 +vn -0.017811 0.943260 0.331576 +vn -0.017811 0.943260 0.331576 +vn -0.017811 0.943260 0.331576 +vn -0.017811 0.943260 0.331576 +vn -0.013215 0.722929 0.690796 +vn -0.013215 0.722929 0.690796 +vn -0.013215 0.722929 0.690796 +vn -0.013215 0.722929 0.690796 +vn 0.143365 0.983605 -0.109401 +vn 0.143365 0.983605 -0.109401 +vn 0.143365 0.983605 -0.109401 +vn 0.143365 0.983605 -0.109401 +vn -0.022046 0.993630 -0.110516 +vn -0.022046 0.993630 -0.110516 +vn -0.022046 0.993630 -0.110516 +vn -0.022046 0.993630 -0.110516 +vn -0.022046 0.993630 0.110516 +vn -0.022046 0.993630 0.110516 +vn -0.022046 0.993630 0.110516 +vn -0.022046 0.993630 0.110516 +vn 0.130833 0.712634 -0.689229 +vn 0.130833 0.712634 -0.689229 +vn 0.130833 0.712634 -0.689229 +vn 0.130833 0.712634 -0.689229 +vn -0.013215 0.722930 -0.690795 +vn -0.013215 0.722930 -0.690795 +vn -0.013215 0.722930 -0.690795 +vn -0.013215 0.722930 -0.690795 +vn -0.017811 0.943260 -0.331576 +vn -0.017811 0.943260 -0.331576 +vn -0.017811 0.943260 -0.331576 +vn -0.017811 0.943260 -0.331576 +vn -0.545911 0.790429 -0.277854 +vn -0.545911 0.790429 -0.277854 +vn -0.545911 0.790429 -0.277854 +vn -0.545911 0.790429 -0.277854 +vn -0.264463 0.503333 -0.822627 +vn -0.264463 0.503333 -0.822627 +vn -0.264463 0.503333 -0.822627 +vn -0.264463 0.503333 -0.822627 +vn 0.071428 0.391121 -0.917563 +vn -0.022348 0.280539 -0.959582 +vn -0.022348 0.280539 -0.959582 +vn -0.022348 0.280539 -0.959582 +vn -0.022348 0.280539 -0.959582 +vn -0.727792 0.633269 -0.263228 +vn -0.727792 0.633269 -0.263228 +vn -0.727792 0.633269 -0.263228 +vn -0.727792 0.633270 -0.263228 +vn 0.024936 0.422951 -0.905809 +vn 0.020457 0.652869 -0.757194 +vn 0.064463 0.552835 -0.830794 +vn -0.064587 0.432978 -0.899088 +vn -0.051952 0.691351 -0.720648 +vn -0.430065 0.475818 -0.767230 +vn -0.430065 0.475818 -0.767230 +vn -0.430065 0.475818 -0.767230 +vn -0.430065 0.475818 -0.767230 +vn 0.015304 0.118231 -0.992868 +vn 0.015304 0.118231 -0.992868 +vn 0.015304 0.118231 -0.992868 +vn 0.015304 0.118231 -0.992868 +vn -0.064587 -0.432978 -0.899088 +vn -0.064587 0.000000 -0.997912 +vn -0.567759 0.818150 -0.090998 +vn -0.567759 0.818150 -0.090998 +vn -0.567759 0.818150 -0.090998 +vn -0.567759 0.818150 -0.090998 +vn -0.755415 0.654260 -0.035929 +vn -0.755415 0.654260 -0.035929 +vn -0.755415 0.654260 -0.035929 +vn -0.755415 0.654260 -0.035929 +vn 0.000000 0.900969 -0.433884 +vn -0.072505 0.898614 -0.432707 +vn -0.082933 0.960669 -0.265023 +vn 0.000000 0.964593 -0.263742 +vn -0.924988 0.164874 0.342364 +vn -0.927519 0.290707 0.234942 +vn -1.000000 -0.000000 0.000000 +vn -0.925651 0.362381 0.108856 +vn -0.924989 -0.000000 -0.379995 +vn -0.924988 -0.164873 -0.342365 +vn -0.924989 -0.297092 -0.236923 +vn -0.924989 -0.370468 -0.084556 +vn -0.924989 -0.370467 0.084557 +vn -0.924989 -0.297092 0.236923 +vn -0.924989 -0.164874 0.342363 +vn -0.924989 0.000000 0.379995 +vn -0.727792 0.633269 0.263229 +vn -0.727792 0.633269 0.263229 +vn -0.727792 0.633269 0.263229 +vn -0.727792 0.633269 0.263229 +vn -0.545911 0.790429 0.277853 +vn -0.545911 0.790429 0.277853 +vn -0.545911 0.790429 0.277853 +vn -0.545911 0.790429 0.277853 +vn -0.755415 0.654260 0.035930 +vn -0.755415 0.654260 0.035930 +vn -0.755415 0.654260 0.035930 +vn -0.755415 0.654260 0.035930 +vn -0.567759 0.818150 0.090998 +vn -0.567759 0.818150 0.090998 +vn -0.567759 0.818150 0.090998 +vn -0.567759 0.818150 0.090998 +vn -0.076076 0.997102 0.000000 +vn -0.082933 0.960669 0.265024 +vn 0.000000 0.964593 0.263742 +vn 0.000000 1.000000 0.000000 +vn -0.942446 0.334359 0.000000 +vn -0.925651 0.362381 -0.108857 +vn -0.927519 0.290707 -0.234942 +vn -0.924989 0.164874 -0.342364 +vn -0.072505 0.898614 0.432707 +vn 0.000000 0.900969 0.433884 +vn 0.070121 -0.000000 0.997539 +vn 0.026848 -0.000000 0.999640 +vn -0.064587 0.000000 0.997912 +vn 0.015304 0.118232 0.992868 +vn 0.015304 0.118232 0.992868 +vn 0.015304 0.118232 0.992868 +vn 0.015304 0.118232 0.992868 +vn -0.022348 0.280539 0.959583 +vn -0.022348 0.280539 0.959583 +vn -0.022348 0.280539 0.959583 +vn -0.022348 0.280539 0.959583 +vn -0.051952 0.691351 0.720648 +vn -0.064587 0.432978 0.899088 +vn 0.024936 0.422951 0.905809 +vn 0.020457 0.652869 0.757194 +vn -0.430065 0.475818 0.767230 +vn -0.430065 0.475818 0.767230 +vn -0.430065 0.475818 0.767230 +vn -0.430065 0.475818 0.767230 +vn -0.264462 0.503332 0.822628 +vn -0.264462 0.503332 0.822628 +vn -0.264462 0.503332 0.822628 +vn -0.264462 0.503332 0.822628 +vn 0.079554 0.432509 0.898113 +vn 0.081210 0.779249 0.621431 +vn 0.083582 0.756709 0.648386 +vn 0.090884 0.864154 0.494952 +vn 0.074379 0.588458 0.805099 +vn 0.299258 0.416890 0.858282 +vn 0.299258 0.416890 0.858282 +vn 0.299258 0.416890 0.858282 +vn 0.299258 0.416890 0.858282 +vn 0.502967 0.815394 0.286628 +vn 0.502967 0.815394 0.286628 +vn 0.502967 0.815394 0.286628 +vn 0.502967 0.815394 0.286628 +vn 0.296862 0.477629 0.826888 +vn 0.296862 0.477629 0.826888 +vn 0.296862 0.477629 0.826888 +vn 0.296862 0.477629 0.826888 +vn 0.071428 0.391121 0.917564 +vn 0.064463 0.552834 0.830794 +vn 0.070946 0.105332 0.991903 +vn 0.070946 0.105332 0.991903 +vn 0.115643 0.269922 0.955913 +vn 0.115643 0.269922 0.955913 +vn 0.115643 0.269922 0.955913 +vn 0.115643 0.269922 0.955913 +vn 0.083582 0.756710 -0.648386 +vn 0.090884 0.864154 -0.494952 +vn 0.074379 0.588458 -0.805099 +vn 0.070946 0.105332 -0.991903 +vn 0.070946 0.105332 -0.991903 +vn 0.299258 0.416891 -0.858281 +vn 0.299258 0.416891 -0.858281 +vn 0.299258 0.416891 -0.858281 +vn 0.299258 0.416891 -0.858281 +vn 0.296862 0.477628 -0.826888 +vn 0.296862 0.477628 -0.826888 +vn 0.296862 0.477628 -0.826888 +vn 0.296862 0.477628 -0.826888 +vn 0.115643 0.269922 -0.955913 +vn 0.115643 0.269922 -0.955913 +vn 0.115643 0.269922 -0.955913 +vn 0.115643 0.269922 -0.955913 +vn 0.102431 0.896230 0.431601 +vn 0.102431 0.896230 0.431601 +vn 0.102431 0.896230 0.431601 +vn 0.102431 0.896230 0.431601 +vn 0.425735 0.904848 0.000000 +vn 0.425735 0.904848 0.000000 +vn 0.425735 0.904848 0.000000 +vn 0.102431 0.896230 -0.431601 +vn 0.102431 0.896230 -0.431601 +vn 0.102431 0.896230 -0.431601 +vn 0.102431 0.896230 -0.431601 +vn 0.968371 0.249514 0.000000 +vn 0.968371 0.249514 0.000000 +vn 0.968371 0.249514 0.000000 +vn 0.004416 0.060621 -0.998151 +vn 0.004416 0.060621 -0.998151 +vn 0.004416 0.060621 -0.998151 +vn 0.004416 0.060621 -0.998151 +vn -0.893202 0.449656 0.000001 +vn -0.893202 0.449656 0.000001 +vn -0.893202 0.449656 0.000001 +vn 0.004416 0.060620 0.998151 +vn 0.004416 0.060620 0.998151 +vn 0.004416 0.060620 0.998151 +vn 0.004416 0.060620 0.998151 +vn 0.043031 -0.112813 0.992684 +vn 0.043031 -0.112813 0.992684 +vn 0.043031 -0.112813 0.992684 +vn 0.043031 -0.112813 0.992684 +vn 0.043030 -0.112812 -0.992684 +vn 0.043030 -0.112812 -0.992684 +vn 0.043030 -0.112812 -0.992684 +vn 0.043030 -0.112812 -0.992684 +vn 0.524265 0.850274 0.046693 +vn 0.524265 0.850274 0.046693 +vn 0.524265 0.850274 0.046693 +vn 0.524265 0.850274 0.046693 +vn 0.521127 0.848248 -0.094347 +vn 0.521127 0.848248 -0.094347 +vn 0.521127 0.848248 -0.094347 +vn 0.521127 0.848248 -0.094347 +vn 0.521127 0.848248 0.094347 +vn 0.521127 0.848248 0.094347 +vn 0.521127 0.848248 0.094346 +vn 0.521127 0.848248 0.094347 +vn 0.090218 0.955033 0.282440 +vn 0.080965 0.951518 0.296745 +vn 0.493255 0.803255 0.333887 +vn 0.493255 0.803255 0.333887 +vn 0.493255 0.803255 0.333887 +vn 0.493255 0.803255 0.333887 +vn 0.102044 0.959117 0.263971 +vn 0.089030 0.996029 0.000000 +vn 0.079187 0.996860 0.000000 +vn 0.080989 0.952672 -0.293015 +vn 0.090239 0.956082 -0.278863 +vn 0.102059 0.960038 -0.260596 +vn 0.099608 0.995027 -0.000000 +vn 0.493255 0.803256 -0.333886 +vn 0.493255 0.803256 -0.333886 +vn 0.493255 0.803256 -0.333886 +vn 0.493255 0.803256 -0.333886 +vn 0.524265 0.850274 -0.046693 +vn 0.524265 0.850274 -0.046693 +vn 0.524265 0.850274 -0.046693 +vn 0.524265 0.850274 -0.046693 +vn 0.502968 0.815395 -0.286627 +vn 0.502968 0.815395 -0.286627 +vn 0.502968 0.815395 -0.286627 +vn 0.502968 0.815395 -0.286627 +vn -0.893202 0.449656 0.000002 +vn -0.893202 0.449656 0.000002 +vn -0.893202 0.449656 0.000002 +s off +f 77/85/1 78/86/2 79/87/3 80/88/4 +f 81/89/5 82/90/6 83/91/7 84/92/8 +s 1 +f 6/20/9 7/21/10 21/36/11 20/35/12 +f 7/21/10 8/22/13 22/37/14 21/36/11 +f 8/22/13 9/23/15 23/38/16 22/37/14 +f 9/23/15 10/24/17 24/39/18 23/38/16 +f 10/24/17 11/25/19 25/40/20 24/39/18 +f 11/25/19 12/26/21 26/41/22 25/40/20 +f 12/26/21 13/27/23 27/42/24 26/41/22 +f 13/27/23 14/28/25 28/43/26 27/42/24 +f 14/28/25 1/29/27 15/44/28 28/43/26 +f 20/35/12 21/36/11 35/51/29 34/50/30 +f 21/36/11 22/37/14 36/52/31 35/51/29 +f 22/37/14 23/38/16 37/53/32 36/52/31 +f 23/38/16 24/39/18 38/54/33 37/53/32 +f 24/39/18 25/40/20 39/55/34 38/54/33 +f 25/40/20 26/41/22 40/56/35 39/55/34 +f 26/41/22 27/42/24 41/57/36 40/56/35 +f 27/42/24 28/43/26 42/58/37 41/57/36 +f 35/51/29 36/52/31 50/67/38 49/66/39 +f 36/52/31 37/53/32 51/68/40 50/67/38 +f 37/53/32 38/54/33 52/69/41 51/68/40 +f 38/54/33 39/55/34 53/70/42 52/69/41 +f 39/55/34 40/56/35 54/71/43 53/70/42 +f 40/56/35 41/57/36 55/72/44 54/71/43 +s off +f 97/105/45 85/93/46 94/102/47 93/101/48 +f 95/103/49 86/94/50 99/107/51 98/106/52 +f 100/108/53 89/97/54 103/111/55 102/110/56 +s 1 +f 49/66/39 50/67/38 64/164/57 63/160/58 +f 50/67/38 51/68/40 65/139/59 64/164/57 +f 51/68/40 52/69/41 66/141/60 65/139/59 +f 52/69/41 53/70/42 67/143/61 66/141/60 +f 53/70/42 54/71/43 68/145/62 67/143/61 +f 54/71/43 55/72/44 69/148/63 68/145/62 +f 65/139/59 66/141/60 135/174/64 133/170/65 +f 66/141/60 67/143/61 137/177/66 135/174/64 +f 67/143/61 68/145/62 139/180/67 137/177/66 +f 68/145/62 69/148/63 141/183/68 139/180/67 +f 2/2/69 1/1/27 71/78/70 +f 3/3/71 2/2/69 71/78/70 +f 5/5/72 4/4/73 71/78/70 +f 6/6/9 5/5/72 71/78/70 +f 7/7/10 6/6/9 71/78/70 +f 8/8/13 7/7/10 71/78/70 +f 9/9/15 8/8/13 71/78/70 +f 10/10/17 9/9/15 71/78/70 +f 11/11/19 10/10/17 71/78/70 +f 12/12/21 11/11/19 71/78/70 +f 13/13/23 12/12/21 71/78/70 +f 14/14/25 13/13/23 71/78/70 +f 1/1/27 14/14/25 71/78/70 +f 1/15/27 2/16/69 78/86/74 77/85/75 +s off +f 2/16/76 16/31/77 79/87/78 78/86/79 +f 16/31/80 15/30/81 80/88/82 79/87/83 +s 1 +f 15/30/28 1/15/27 77/85/84 80/88/85 +f 5/19/72 6/20/9 82/90/86 81/89/87 +f 6/20/9 20/35/12 83/91/88 82/90/89 +f 20/35/12 19/34/90 84/92/91 83/91/92 +s off +f 19/34/93 5/19/94 81/89/95 84/92/96 +f 94/102/97 86/94/98 95/103/99 93/101/100 +f 95/103/101 87/95/102 96/104/103 93/101/104 +f 96/104/105 88/96/106 97/105/107 93/101/108 +f 99/107/109 89/97/110 100/108/111 98/106/112 +f 100/108/113 90/98/114 101/109/115 98/106/116 +f 101/109/117 87/95/118 95/103/119 98/106/120 +f 103/111/121 91/99/122 104/112/123 102/110/124 +f 104/112/125 92/100/126 105/113/127 102/110/128 +f 105/113/129 90/98/130 100/108/131 102/110/132 +f 121/127/133 90/98/134 105/113/135 128/134/136 +f 105/113/137 92/100/138 127/133/139 128/134/140 +s 1 +f 48/65/141 34/50/30 35/51/29 49/66/39 +s off +f 125/131/142 127/133/143 92/100/144 104/112/145 +f 128/134/146 129/150/147 60/167/148 121/127/149 +s 1 +f 62/161/150 61/77/151 126/132/152 48/65/141 +f 63/160/58 62/161/150 48/65/141 49/66/39 +f 148/194/153 146/213/154 61/77/151 62/161/150 +s off +f 128/134/155 127/133/156 61/77/157 129/150/158 +f 126/132/159 61/77/160 127/133/161 125/131/162 +s 1 +f 159/207/163 157/197/164 63/160/58 64/164/57 +f 133/170/65 159/207/163 64/164/57 65/139/59 +s off +f 119/126/165 101/109/166 90/98/167 121/127/168 +f 121/127/169 60/167/170 120/168/171 119/126/172 +s 1 +f 63/160/58 157/197/164 148/194/153 62/161/150 +f 129/150/173 145/190/174 161/209/175 60/167/176 +f 150/214/177 153/200/178 72/166/179 +f 153/200/178 155/186/180 72/166/179 +f 156/162/181 158/163/182 72/166/179 +f 158/163/182 132/140/183 72/166/179 +f 132/140/183 134/142/184 72/166/179 +f 134/142/184 136/144/185 72/166/179 +f 136/144/185 138/146/186 72/166/179 +f 138/146/186 140/185/187 72/166/179 +f 140/185/187 143/203/188 72/166/179 +f 143/203/188 150/214/177 72/166/179 +s off +f 110/118/189 113/120/190 59/159/191 111/137/192 +f 96/104/193 87/95/194 113/120/195 110/118/196 +f 120/168/197 59/159/198 113/120/199 119/126/200 +f 119/126/201 113/120/202 87/95/203 101/109/204 +s 1 +f 163/205/205 154/158/206 59/159/207 120/168/208 +f 155/186/180 162/169/209 72/166/179 +f 160/165/210 144/151/211 72/166/179 +f 144/151/211 147/152/212 72/166/179 +f 147/152/212 156/162/181 72/166/179 +f 154/158/206 152/138/213 111/137/214 59/159/207 +f 161/209/175 163/205/205 120/168/208 60/167/176 +f 72/166/179 162/169/209 160/165/210 +f 55/72/44 41/57/36 42/58/37 56/73/215 +f 69/148/63 55/72/44 56/73/215 70/149/216 +f 142/147/217 141/183/68 69/148/63 70/149/216 +s off +f 112/119/218 58/76/219 115/122/220 114/121/221 +f 114/121/222 97/105/223 88/96/224 112/119/225 +s 1 +f 151/155/226 149/156/227 57/75/228 58/76/229 +f 111/137/214 152/138/213 151/155/226 58/76/229 +f 149/153/227 142/147/217 70/149/216 57/154/228 +s off +f 110/118/230 111/137/231 58/76/232 112/119/233 +f 112/119/234 88/96/235 96/104/236 110/118/237 +s 1 +f 29/45/238 15/30/28 16/31/239 30/46/240 +f 42/58/37 28/43/26 15/44/28 29/59/238 +f 30/46/240 107/115/241 44/61/242 +s off +f 106/114/243 109/117/244 44/61/245 107/115/246 +f 108/116/247 86/94/248 94/102/249 106/114/250 +f 94/102/251 85/93/252 109/117/253 106/114/254 +s 1 +f 44/61/242 43/60/255 29/45/238 30/46/240 +f 43/74/255 56/73/215 42/58/37 29/59/238 +f 115/122/256 58/76/229 57/75/228 43/60/255 +f 57/154/228 70/149/216 56/73/215 43/74/255 +f 115/122/256 44/61/242 109/117/257 114/121/258 +s off +f 114/121/259 109/117/260 85/93/261 97/105/262 +s 1 +f 115/122/256 43/60/255 44/61/242 +f 33/49/263 19/34/90 20/35/12 34/50/30 +f 123/129/264 33/49/263 47/64/265 +f 48/65/141 47/64/265 33/49/263 34/50/30 +f 124/130/266 47/64/265 126/132/152 125/131/267 +s off +f 122/128/268 123/129/269 47/64/270 124/130/271 +f 124/130/272 91/99/273 103/111/274 122/128/275 +f 125/131/276 104/112/277 91/99/278 124/130/279 +s 1 +f 48/65/141 126/132/152 47/64/265 +s off +f 16/31/280 2/16/281 3/17/282 17/32/283 +f 73/81/284 74/79/285 75/80/286 +f 18/33/287 4/18/288 5/19/289 19/34/290 +f 74/84/291 73/82/292 76/83/293 +f 4/18/294 18/33/295 75/80/296 74/79/297 +f 130/135/298 75/80/299 18/33/300 +f 75/80/301 17/32/302 3/17/303 73/81/304 +f 3/3/305 71/78/306 76/83/307 73/82/308 +f 76/83/309 71/78/310 4/4/311 74/84/312 +f 108/116/313 45/62/314 117/124/315 116/123/316 +f 116/123/317 118/125/318 89/97/319 99/107/320 +f 116/123/321 99/107/322 86/94/323 108/116/324 +s 1 +f 31/47/325 30/46/240 16/31/239 17/32/326 +s off +f 106/114/327 107/115/328 45/62/329 108/116/330 +s 1 +f 107/115/241 30/46/240 31/47/325 45/62/331 +f 131/136/332 130/135/333 18/33/334 32/48/335 +f 33/49/263 32/48/335 18/33/334 19/34/90 +f 32/48/335 46/63/336 117/124/337 131/136/332 +s off +f 122/128/338 118/125/339 46/63/340 123/129/341 +f 117/124/342 46/63/343 118/125/344 116/123/345 +f 103/111/346 89/97/347 118/125/348 122/128/349 +s 1 +f 32/48/335 33/49/263 123/129/264 46/63/336 +f 131/136/332 117/124/337 45/62/331 31/47/325 +f 130/135/333 131/136/332 31/47/325 17/32/326 +s off +f 75/80/350 130/135/351 17/32/352 +s 1 +f 146/213/154 145/190/174 129/150/173 61/77/151 +f 133/170/65 132/171/183 158/172/182 159/207/163 +f 132/173/183 133/170/65 135/174/64 134/175/184 +f 134/176/184 135/174/64 137/177/66 136/178/185 +f 136/179/185 137/177/66 139/180/67 138/181/186 +f 138/182/186 139/180/67 141/183/68 140/184/187 +f 140/202/187 141/183/68 142/147/217 143/188/188 +f 143/216/188 142/147/217 149/153/227 150/199/177 +f 145/190/174 144/191/211 160/192/210 161/209/175 +f 144/193/211 146/213/154 148/194/153 147/195/212 +f 147/196/212 148/194/153 157/197/164 156/198/181 +f 150/189/177 149/156/227 151/155/226 153/215/178 +f 153/187/178 152/138/213 154/158/206 155/157/180 +f 155/204/180 154/158/206 163/205/205 162/211/209 +f 156/206/181 157/197/164 159/207/163 158/208/182 +f 161/209/175 160/210/210 162/211/209 163/205/205 +f 144/212/211 145/190/174 146/213/154 +f 151/155/226 152/138/213 153/201/178 +v -4.526886 2.025292 -6.500000 +v -4.526886 2.025292 6.500000 +v -2.453123 1.990687 -6.229743 +v -2.453123 1.990687 6.229743 +v -4.716847 1.835833 -6.500000 +v -4.716847 1.835833 6.500000 +v -2.453123 1.835833 6.229743 +v -2.453123 1.835833 -6.229743 +v -4.526886 2.025292 5.055555 +v -2.453123 1.835833 5.055555 +v -4.853122 1.835833 5.055555 +v -4.526886 2.025292 3.611111 +v -2.453123 1.990687 3.611111 +v -2.453123 1.835833 3.611111 +v -4.853122 1.835833 3.611111 +v -4.526886 2.025292 2.166667 +v -2.453123 1.835833 2.166667 +v -4.853123 1.835833 2.166667 +v -4.526886 2.025292 0.722222 +v -2.453123 1.990687 0.722222 +v -2.453123 1.835833 0.722222 +v -4.853123 1.835833 0.722222 +v -4.526886 2.025292 -0.722222 +v -2.453123 1.990687 -0.722222 +v -2.453123 1.835833 -0.722222 +v -4.853123 1.835833 -0.722222 +v -4.526886 2.025292 -2.166667 +v -2.453123 1.835833 -2.166667 +v -4.853123 1.835833 -2.166667 +v -4.526886 2.025292 -3.611112 +v -2.453123 1.990687 -3.611112 +v -2.453123 1.835833 -3.611112 +v -4.853123 1.835833 -3.611112 +v -4.526886 2.025292 -5.055555 +v -2.453123 1.835833 -5.055556 +v -4.853123 1.835833 -5.055556 +vt 0.616150 0.306151 +vt 0.610251 0.992489 +vt 0.731520 0.325838 +vt 0.725886 0.974777 +vt 0.591047 0.313683 +vt 0.585284 0.984520 +vt 0.476020 0.976054 +vt 0.481594 0.320254 +vt 0.605471 0.315123 +vt 0.599736 0.983336 +vt 0.717845 0.974434 +vt 0.723467 0.326044 +vt 0.579649 0.910291 +vt 0.724217 0.318026 +vt 0.720447 0.913504 +vt 0.472481 0.914051 +vt 0.598060 0.909419 +vt 0.578999 0.836511 +vt 0.718456 0.982458 +vt 0.730267 0.838710 +vt 0.471391 0.837979 +vt 0.722220 0.838546 +vt 0.598433 0.836444 +vt 0.579018 0.761838 +vt 0.602520 0.389018 +vt 0.723365 0.763360 +vt 0.470415 0.761959 +vt 0.598696 0.761928 +vt 0.579544 0.686680 +vt 0.476998 0.382224 +vt 0.732302 0.688095 +vt 0.471265 0.685937 +vt 0.724215 0.688011 +vt 0.599234 0.686836 +vt 0.580196 0.611444 +vt 0.725022 0.387043 +vt 0.732967 0.612676 +vt 0.471912 0.610366 +vt 0.724881 0.612612 +vt 0.599876 0.611634 +vt 0.580951 0.536288 +vt 0.584126 0.387830 +vt 0.725344 0.537251 +vt 0.472346 0.534318 +vt 0.600626 0.536533 +vt 0.582223 0.461596 +vt 0.601648 0.461993 +vt 0.733547 0.462028 +vt 0.474637 0.458282 +vt 0.725502 0.462044 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.050020 0.997007 0.058958 +vn 0.050020 0.997007 0.058958 +vn 0.050020 0.997007 0.058958 +vn 0.050020 0.997007 0.058958 +vn -0.591510 0.805815 -0.027903 +vn -0.591510 0.805815 -0.027903 +vn -0.591510 0.805815 -0.027903 +vn -0.591510 0.805815 -0.027903 +vn 0.122841 -0.067773 0.990110 +vn 0.122841 -0.067773 0.990110 +vn 0.122841 -0.067773 0.990110 +vn 0.122841 -0.067773 0.990110 +vn 1.000000 0.000000 0.000000 +vn 1.000000 0.000000 0.000000 +vn 1.000000 0.000000 0.000000 +vn 0.122841 -0.067773 -0.990110 +vn 0.122841 -0.067773 -0.990110 +vn 0.122841 -0.067773 -0.990110 +vn 0.122841 -0.067773 -0.990110 +vn 0.050020 0.997006 -0.058958 +vn 0.050020 0.997007 -0.058958 +vn 0.050020 0.997007 -0.058958 +vn 0.050020 0.997007 -0.058958 +vn 1.000000 0.000000 0.000000 +vn 1.000000 0.000000 0.000000 +vn 1.000000 0.000000 0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn -0.591512 0.805814 0.027903 +vn -0.591512 0.805814 0.027903 +vn -0.591511 0.805814 0.027903 +vn -0.591512 0.805814 0.027903 +vn 0.053867 0.997117 0.053449 +vn 0.053867 0.997117 0.053449 +vn 0.053867 0.997117 0.053449 +vn 0.053867 0.997117 0.053449 +vn 1.000000 0.000000 0.000000 +vn 1.000000 0.000000 0.000000 +vn 1.000000 0.000000 0.000000 +vn 0.000000 -1.000000 0.000000 +vn 0.000000 -1.000000 0.000000 +vn 0.000000 -1.000000 0.000000 +vn 0.000000 -1.000000 0.000000 +vn -0.502197 0.864753 0.000000 +vn -0.502197 0.864753 0.000000 +vn -0.502197 0.864753 0.000000 +vn -0.502197 0.864753 0.000000 +vn 0.053867 0.997117 -0.053449 +vn 0.053867 0.997117 -0.053449 +vn 0.053867 0.997117 -0.053449 +vn 0.053867 0.997117 -0.053449 +vn 1.000000 0.000000 0.000000 +vn 1.000000 0.000000 0.000000 +vn 1.000000 0.000000 0.000000 +vn 0.000000 -1.000000 0.000000 +vn 0.000000 -1.000000 0.000000 +vn 0.000000 -1.000000 0.000000 +vn 0.000000 -1.000000 0.000000 +vn -0.502196 0.864754 0.000000 +vn -0.502196 0.864754 0.000000 +vn -0.502196 0.864754 0.000000 +vn -0.502196 0.864754 0.000000 +vn 0.053867 0.997117 0.053449 +vn 0.053867 0.997117 0.053449 +vn 0.053867 0.997117 0.053449 +vn 0.053867 0.997117 0.053449 +vn 1.000000 0.000000 0.000000 +vn 1.000000 0.000000 0.000000 +vn 1.000000 0.000000 0.000000 +vn 0.000000 -1.000000 0.000000 +vn 0.000000 -1.000000 0.000000 +vn 0.000000 -1.000000 0.000000 +vn 0.000000 -1.000000 0.000000 +vn -0.502196 0.864754 0.000000 +vn -0.502196 0.864754 0.000000 +vn -0.502196 0.864754 0.000000 +vn -0.502196 0.864754 0.000000 +vn 0.016684 0.999861 0.000000 +vn 0.016684 0.999861 0.000000 +vn 0.016684 0.999861 0.000000 +vn 0.016684 0.999861 0.000000 +vn 1.000000 0.000000 0.000000 +vn 1.000000 0.000000 0.000000 +vn 1.000000 0.000000 0.000000 +vn 1.000000 0.000000 0.000000 +vn 0.000000 -1.000000 0.000000 +vn 0.000000 -1.000000 0.000000 +vn 0.000000 -1.000000 0.000000 +vn 0.000000 -1.000000 0.000000 +vn -0.502196 0.864754 0.000000 +vn -0.502196 0.864754 0.000000 +vn -0.502196 0.864754 0.000000 +vn -0.502196 0.864754 0.000000 +vn 0.053867 0.997117 -0.053449 +vn 0.053867 0.997117 -0.053449 +vn 0.053867 0.997117 -0.053449 +vn 0.053867 0.997117 -0.053449 +vn 1.000000 0.000000 0.000000 +vn 1.000000 0.000000 0.000000 +vn 1.000000 0.000000 0.000000 +vn 0.000000 -1.000000 0.000000 +vn 0.000000 -1.000000 0.000000 +vn 0.000000 -1.000000 0.000000 +vn 0.000000 -1.000000 0.000000 +vn -0.502196 0.864754 0.000000 +vn -0.502196 0.864754 0.000000 +vn -0.502196 0.864754 0.000000 +vn -0.502196 0.864754 0.000000 +vn 0.053867 0.997117 0.053449 +vn 0.053867 0.997117 0.053449 +vn 0.053867 0.997117 0.053449 +vn 0.053867 0.997117 0.053449 +vn 1.000000 0.000000 0.000000 +vn 1.000000 0.000000 0.000000 +vn 1.000000 0.000000 0.000000 +vn 0.000000 -1.000000 0.000000 +vn 0.000000 -1.000000 0.000000 +vn 0.000000 -1.000000 0.000000 +vn 0.000000 -1.000000 0.000000 +vn -0.502196 0.864754 0.000000 +vn -0.502196 0.864754 0.000000 +vn -0.502196 0.864754 0.000000 +vn -0.502196 0.864754 0.000000 +vn 0.053867 0.997117 -0.053449 +vn 0.053867 0.997117 -0.053449 +vn 0.053867 0.997117 -0.053449 +vn 0.053867 0.997117 -0.053449 +vn 1.000000 0.000000 0.000000 +vn 1.000000 0.000000 0.000000 +vn 1.000000 0.000000 0.000000 +vn 0.000000 -1.000000 0.000000 +vn 0.000000 -1.000000 0.000000 +vn 0.000000 -1.000000 0.000000 +vn 0.000000 -1.000000 0.000000 +vn -0.502196 0.864754 0.000000 +vn -0.502196 0.864754 0.000000 +vn -0.502196 0.864754 0.000000 +vn -0.502196 0.864754 0.000000 +s off +f 168/225/353 171/228/354 198/252/355 199/241/356 +f 164/221/357 197/258/358 198/246/359 166/224/360 +f 164/221/361 168/225/362 199/241/363 197/258/364 +f 165/218/365 169/226/366 170/227/367 167/235/368 +f 198/252/369 171/228/370 166/219/371 +f 166/230/372 171/228/373 168/225/374 164/217/375 +f 172/229/376 165/222/377 167/223/378 173/232/379 +f 167/220/380 170/227/381 173/231/382 +f 174/233/383 173/231/384 170/227/385 169/226/386 +f 172/229/387 174/233/388 169/226/389 165/222/390 +f 175/234/391 172/229/392 173/232/393 176/237/394 +f 173/231/395 177/238/396 176/236/397 +f 178/239/398 177/238/399 173/231/400 174/233/401 +f 175/234/402 178/239/403 174/233/404 172/229/405 +f 179/240/406 175/234/407 176/237/408 180/243/409 +f 176/236/410 177/238/411 180/242/412 +f 181/244/413 180/242/414 177/238/415 178/239/416 +f 179/240/417 181/244/418 178/239/419 175/234/420 +f 182/245/421 179/240/422 180/243/423 183/248/424 +f 180/242/425 184/249/426 183/247/427 +f 185/250/428 184/249/429 180/242/430 181/244/431 +f 182/245/432 185/250/433 181/244/434 179/240/435 +f 186/251/436 182/245/437 183/248/438 187/254/439 +f 183/247/440 184/249/441 188/255/442 187/253/443 +f 189/256/444 188/255/445 184/249/446 185/250/447 +f 186/251/448 189/256/449 185/250/450 182/245/451 +f 190/257/452 186/251/453 187/254/454 191/260/455 +f 187/253/456 188/255/457 191/259/458 +f 192/261/459 191/259/460 188/255/461 189/256/462 +f 190/257/463 192/261/464 189/256/465 186/251/466 +f 193/262/467 190/257/468 191/260/469 194/265/470 +f 191/259/471 195/266/472 194/264/473 +f 196/263/474 195/266/475 191/259/476 192/261/477 +f 193/262/478 196/263/479 192/261/480 190/257/481 +f 197/258/482 193/262/483 194/265/484 198/246/485 +f 194/264/486 195/266/487 198/252/488 +f 199/241/489 198/252/490 195/266/491 196/263/492 +f 197/258/493 199/241/494 196/263/495 193/262/496 +v -3.559415 -0.491252 -6.500000 +v -3.559415 -0.491252 6.500000 +v -1.485652 -0.525856 -6.229743 +v -1.485653 -0.525856 6.229743 +v -3.749376 -0.680711 -6.500000 +v -3.749376 -0.680711 6.500000 +v -1.485653 -0.680711 6.229743 +v -1.485652 -0.680711 -6.229743 +v -3.559415 -0.491252 5.055555 +v -1.485652 -0.680711 5.055555 +v -3.885653 -0.680711 5.055555 +v -3.559415 -0.491252 3.611110 +v -1.485652 -0.525856 3.611110 +v -1.485652 -0.680711 3.611110 +v -3.885652 -0.680711 3.611110 +v -3.559415 -0.491252 2.166667 +v -1.485652 -0.680711 2.166667 +v -3.885653 -0.680711 2.166667 +v -3.559415 -0.491252 0.722222 +v -1.485652 -0.525856 0.722222 +v -1.485652 -0.680711 0.722222 +v -3.885652 -0.680711 0.722222 +v -3.559416 -0.491252 -0.722223 +v -1.485652 -0.525856 -0.722222 +v -1.485652 -0.680711 -0.722222 +v -3.885653 -0.680711 -0.722223 +v -3.559416 -0.491252 -2.166667 +v -1.485652 -0.680711 -2.166667 +v -3.885653 -0.680711 -2.166667 +v -3.559415 -0.491252 -3.611112 +v -1.485652 -0.525856 -3.611111 +v -1.485652 -0.680711 -3.611111 +v -3.885653 -0.680711 -3.611111 +v -3.559415 -0.491252 -5.055556 +v -1.485652 -0.680711 -5.055556 +v -3.885652 -0.680711 -5.055556 +vt 0.878803 0.306151 +vt 0.872904 0.992489 +vt 0.994173 0.325838 +vt 0.988539 0.974777 +vt 0.853700 0.313683 +vt 0.847937 0.984520 +vt 0.738673 0.976054 +vt 0.744247 0.320254 +vt 0.868124 0.315123 +vt 0.862389 0.983336 +vt 0.980498 0.974434 +vt 0.986120 0.326044 +vt 0.842302 0.910291 +vt 0.986870 0.318026 +vt 0.983099 0.913504 +vt 0.735134 0.914051 +vt 0.860713 0.909419 +vt 0.841652 0.836511 +vt 0.981109 0.982458 +vt 0.992920 0.838710 +vt 0.734044 0.837979 +vt 0.984873 0.838546 +vt 0.861086 0.836444 +vt 0.841671 0.761838 +vt 0.865172 0.389018 +vt 0.986018 0.763360 +vt 0.733068 0.761959 +vt 0.861349 0.761928 +vt 0.842197 0.686680 +vt 0.739650 0.382224 +vt 0.994955 0.688095 +vt 0.733917 0.685937 +vt 0.986868 0.688011 +vt 0.861887 0.686836 +vt 0.842849 0.611444 +vt 0.987675 0.387043 +vt 0.995620 0.612676 +vt 0.734565 0.610366 +vt 0.987534 0.612612 +vt 0.862529 0.611634 +vt 0.843604 0.536288 +vt 0.846779 0.387830 +vt 0.987996 0.537251 +vt 0.734999 0.534318 +vt 0.863279 0.536533 +vt 0.844876 0.461596 +vt 0.864301 0.461993 +vt 0.996200 0.462028 +vt 0.737290 0.458282 +vt 0.988155 0.462044 +vn 0.000000 -1.000000 0.000000 +vn 0.000000 -1.000000 0.000000 +vn 0.000000 -1.000000 0.000000 +vn 0.000000 -1.000000 0.000000 +vn 0.050020 0.997007 0.058959 +vn 0.050020 0.997007 0.058959 +vn 0.050020 0.997006 0.058959 +vn 0.050020 0.997007 0.058959 +vn -0.591510 0.805815 -0.027903 +vn -0.591510 0.805815 -0.027903 +vn -0.591510 0.805815 -0.027903 +vn -0.591510 0.805815 -0.027903 +vn 0.122841 -0.067773 0.990110 +vn 0.122841 -0.067773 0.990110 +vn 0.122841 -0.067773 0.990110 +vn 0.122841 -0.067773 0.990110 +vn 1.000000 0.000000 -0.000000 +vn 1.000000 0.000000 -0.000000 +vn 1.000000 0.000000 -0.000000 +vn 0.122841 -0.067772 -0.990110 +vn 0.122841 -0.067772 -0.990110 +vn 0.122841 -0.067772 -0.990110 +vn 0.122841 -0.067772 -0.990110 +vn 0.050020 0.997007 -0.058959 +vn 0.050020 0.997007 -0.058959 +vn 0.050020 0.997007 -0.058959 +vn 0.050020 0.997007 -0.058959 +vn 1.000000 0.000000 0.000001 +vn 1.000000 0.000000 0.000001 +vn 1.000000 0.000000 0.000001 +vn 0.000000 -1.000000 0.000000 +vn 0.000000 -1.000000 0.000000 +vn 0.000000 -1.000000 0.000000 +vn 0.000000 -1.000000 0.000000 +vn -0.591510 0.805815 0.027903 +vn -0.591510 0.805815 0.027903 +vn -0.591510 0.805815 0.027903 +vn -0.591510 0.805815 0.027903 +vn 0.053867 0.997117 0.053449 +vn 0.053867 0.997117 0.053449 +vn 0.053867 0.997117 0.053449 +vn 0.053867 0.997117 0.053449 +vn 1.000000 0.000000 0.000000 +vn 1.000000 0.000000 0.000000 +vn 1.000000 0.000000 0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn -0.502195 0.864754 -0.000000 +vn -0.502195 0.864754 -0.000000 +vn -0.502195 0.864754 -0.000000 +vn -0.502195 0.864754 -0.000000 +vn 0.053867 0.997117 -0.053449 +vn 0.053867 0.997117 -0.053449 +vn 0.053867 0.997117 -0.053449 +vn 0.053867 0.997117 -0.053449 +vn 1.000000 0.000000 -0.000000 +vn 1.000000 0.000000 -0.000000 +vn 1.000000 0.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn -0.502196 0.864754 0.000000 +vn -0.502196 0.864754 0.000000 +vn -0.502196 0.864754 0.000000 +vn -0.502196 0.864754 0.000000 +vn 0.053867 0.997117 0.053449 +vn 0.053867 0.997117 0.053449 +vn 0.053867 0.997117 0.053449 +vn 0.053867 0.997117 0.053449 +vn 1.000000 0.000000 0.000000 +vn 1.000000 0.000000 0.000000 +vn 1.000000 0.000000 0.000000 +vn 0.000000 -1.000000 0.000000 +vn 0.000000 -1.000000 0.000000 +vn 0.000000 -1.000000 0.000000 +vn 0.000000 -1.000000 0.000000 +vn -0.502196 0.864754 -0.000000 +vn -0.502196 0.864754 -0.000000 +vn -0.502196 0.864754 -0.000000 +vn -0.502196 0.864754 -0.000000 +vn 0.016684 0.999861 0.000000 +vn 0.016684 0.999861 0.000000 +vn 0.016684 0.999861 0.000000 +vn 0.016684 0.999861 0.000000 +vn 1.000000 0.000000 -0.000000 +vn 1.000000 0.000000 -0.000000 +vn 1.000000 0.000000 -0.000000 +vn 1.000000 0.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn -0.502196 0.864754 0.000000 +vn -0.502196 0.864754 0.000000 +vn -0.502196 0.864754 0.000000 +vn -0.502196 0.864754 0.000000 +vn 0.053867 0.997117 -0.053449 +vn 0.053867 0.997117 -0.053449 +vn 0.053867 0.997117 -0.053449 +vn 0.053867 0.997117 -0.053449 +vn 1.000000 0.000000 0.000000 +vn 1.000000 0.000000 0.000000 +vn 1.000000 0.000000 0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn -0.502196 0.864754 -0.000000 +vn -0.502196 0.864754 -0.000000 +vn -0.502196 0.864754 -0.000000 +vn -0.502196 0.864754 -0.000000 +vn 0.053867 0.997117 0.053449 +vn 0.053867 0.997117 0.053449 +vn 0.053867 0.997117 0.053449 +vn 0.053867 0.997117 0.053449 +vn 1.000000 0.000000 -0.000000 +vn 1.000000 0.000000 -0.000000 +vn 1.000000 0.000000 -0.000000 +vn 0.000000 -1.000000 0.000000 +vn 0.000000 -1.000000 0.000000 +vn 0.000000 -1.000000 0.000000 +vn 0.000000 -1.000000 0.000000 +vn -0.502196 0.864754 -0.000000 +vn -0.502196 0.864754 -0.000000 +vn -0.502196 0.864754 -0.000000 +vn -0.502196 0.864754 -0.000000 +vn 0.053867 0.997117 -0.053449 +vn 0.053867 0.997117 -0.053449 +vn 0.053867 0.997117 -0.053449 +vn 0.053867 0.997117 -0.053449 +vn 1.000000 0.000000 0.000000 +vn 1.000000 0.000000 0.000000 +vn 1.000000 0.000000 0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn -0.502196 0.864754 -0.000000 +vn -0.502196 0.864754 -0.000000 +vn -0.502196 0.864754 -0.000000 +vn -0.502196 0.864754 -0.000000 +s off +f 204/275/497 207/278/498 234/302/499 235/291/500 +f 200/271/501 233/308/502 234/296/503 202/274/504 +f 200/271/505 204/275/506 235/291/507 233/308/508 +f 201/268/509 205/276/510 206/277/511 203/285/512 +f 234/302/513 207/278/514 202/269/515 +f 202/280/516 207/278/517 204/275/518 200/267/519 +f 208/279/520 201/272/521 203/273/522 209/282/523 +f 203/270/524 206/277/525 209/281/526 +f 210/283/527 209/281/528 206/277/529 205/276/530 +f 208/279/531 210/283/532 205/276/533 201/272/534 +f 211/284/535 208/279/536 209/282/537 212/287/538 +f 209/281/539 213/288/540 212/286/541 +f 214/289/542 213/288/543 209/281/544 210/283/545 +f 211/284/546 214/289/547 210/283/548 208/279/549 +f 215/290/550 211/284/551 212/287/552 216/293/553 +f 212/286/554 213/288/555 216/292/556 +f 217/294/557 216/292/558 213/288/559 214/289/560 +f 215/290/561 217/294/562 214/289/563 211/284/564 +f 218/295/565 215/290/566 216/293/567 219/298/568 +f 216/292/569 220/299/570 219/297/571 +f 221/300/572 220/299/573 216/292/574 217/294/575 +f 218/295/576 221/300/577 217/294/578 215/290/579 +f 222/301/580 218/295/581 219/298/582 223/304/583 +f 219/297/584 220/299/585 224/305/586 223/303/587 +f 225/306/588 224/305/589 220/299/590 221/300/591 +f 222/301/592 225/306/593 221/300/594 218/295/595 +f 226/307/596 222/301/597 223/304/598 227/310/599 +f 223/303/600 224/305/601 227/309/602 +f 228/311/603 227/309/604 224/305/605 225/306/606 +f 226/307/607 228/311/608 225/306/609 222/301/610 +f 229/312/611 226/307/612 227/310/613 230/315/614 +f 227/309/615 231/316/616 230/314/617 +f 232/313/618 231/316/619 227/309/620 228/311/621 +f 229/312/622 232/313/623 228/311/624 226/307/625 +f 233/308/626 229/312/627 230/315/628 234/296/629 +f 230/314/630 231/316/631 234/302/632 +f 235/291/633 234/302/634 231/316/635 232/313/636 +f 233/308/637 235/291/638 232/313/639 229/312/640 +v -4.142218 0.492005 -0.689421 +v -4.278798 0.483220 -0.711072 +v -4.229631 0.565988 -0.611412 +v -4.039907 1.892682 -1.903144 +v -4.176487 1.883898 -1.924795 +v -4.127320 1.966665 -1.825134 +vt 0.475306 0.012993 +vt 0.524059 0.012993 +vt 0.572811 0.012993 +vt 0.621564 0.012993 +vt 0.475306 0.232930 +vt 0.524059 0.232930 +vt 0.572811 0.232930 +vt 0.621564 0.232930 +vn 0.159359 -0.653124 -0.740293 +vn 0.159359 -0.653124 -0.740293 +vn 0.159359 -0.653124 -0.740293 +vn 0.159359 -0.653124 -0.740293 +vn -0.933302 0.271664 0.234831 +vn -0.933302 0.271664 0.234831 +vn -0.933302 0.271664 0.234831 +vn -0.933302 0.271664 0.234831 +vn 0.773945 0.381464 0.505464 +vn 0.773945 0.381464 0.505464 +vn 0.773945 0.381464 0.505464 +vn 0.773945 0.381464 0.505464 +s off +f 236/317/641 237/318/642 240/322/643 239/321/644 +f 237/318/645 238/319/646 241/323/647 240/322/648 +f 238/319/649 236/320/650 239/324/651 241/323/652 +v -3.239272 0.526544 -0.759048 +v -3.375609 0.514178 -0.780479 +v -3.327950 0.606955 -0.689259 +v -3.143238 1.854496 -2.131890 +v -3.279576 1.842130 -2.153321 +v -3.231915 1.934906 -2.062101 +vt 0.475306 0.012993 +vt 0.524059 0.012993 +vt 0.572811 0.012993 +vt 0.621564 0.012993 +vt 0.475306 0.232930 +vt 0.524059 0.232930 +vt 0.572811 0.232930 +vt 0.621564 0.232930 +vn 0.171460 -0.714084 -0.678738 +vn 0.171460 -0.714084 -0.678738 +vn 0.171460 -0.714084 -0.678738 +vn 0.171460 -0.714084 -0.678738 +vn -0.937813 0.279982 0.205223 +vn -0.937813 0.279982 0.205223 +vn -0.937813 0.279982 0.205223 +vn -0.937813 0.279982 0.205223 +vn 0.766343 0.434134 0.473546 +vn 0.766343 0.434134 0.473546 +vn 0.766343 0.434134 0.473546 +vn 0.766343 0.434134 0.473546 +s off +f 242/325/653 243/326/654 246/330/655 245/329/656 +f 243/326/657 244/327/658 247/331/659 246/330/660 +f 244/327/661 242/328/662 245/332/663 247/331/664 +v -3.163166 -0.512404 -4.366673 +v -3.288760 -0.570938 -4.366673 +v -3.225963 -0.541671 -4.246673 +v -4.291037 1.907626 -4.366673 +v -4.416630 1.849092 -4.366673 +v -4.353833 1.878359 -4.246673 +vt 0.475306 0.012993 +vt 0.524059 0.012993 +vt 0.572811 0.012993 +vt 0.621564 0.012993 +vt 0.475306 0.232930 +vt 0.524059 0.232930 +vt 0.572811 0.232930 +vt 0.621564 0.232930 +vn 0.000000 -0.000001 -1.000000 +vn 0.000000 -0.000001 -1.000000 +vn 0.000000 -0.000001 -1.000000 +vn 0.000000 -0.000001 -1.000000 +vn -0.784961 -0.365836 0.500000 +vn -0.784961 -0.365836 0.500000 +vn -0.784961 -0.365836 0.500000 +vn -0.784961 -0.365836 0.500000 +vn 0.784961 0.365837 0.500000 +vn 0.784961 0.365837 0.500000 +vn 0.784961 0.365837 0.500000 +vn 0.784961 0.365837 0.500000 +s off +f 248/333/665 249/334/666 252/338/667 251/337/668 +f 249/334/669 250/335/670 253/339/671 252/338/672 +f 250/335/673 248/336/674 251/340/675 253/339/676 +v -2.090913 -0.552991 -4.366673 +v -2.216506 -0.611525 -4.366673 +v -2.153710 -0.582258 -4.246673 +v -3.269892 1.976702 -4.366673 +v -3.395485 1.918168 -4.366673 +v -3.332688 1.947435 -4.246673 +vt 0.475306 0.012993 +vt 0.524059 0.012993 +vt 0.572811 0.012993 +vt 0.621564 0.012993 +vt 0.475306 0.232930 +vt 0.524059 0.232930 +vt 0.572811 0.232930 +vt 0.621564 0.232930 +vn -0.000005 0.000000 -1.000000 +vn -0.000005 0.000000 -1.000000 +vn -0.000005 0.000000 -1.000000 +vn -0.000005 0.000000 -1.000000 +vn -0.784960 -0.365836 0.500001 +vn -0.784960 -0.365836 0.500001 +vn -0.784960 -0.365836 0.500001 +vn -0.784960 -0.365836 0.500001 +vn 0.784962 0.365835 0.499999 +vn 0.784962 0.365835 0.499999 +vn 0.784962 0.365835 0.499999 +vn 0.784962 0.365835 0.499999 +s off +f 254/341/677 255/342/678 258/346/679 257/345/680 +f 255/342/681 256/343/682 259/347/683 258/346/684 +f 256/343/685 254/344/686 257/348/687 259/347/688 +v -4.142218 0.492005 0.689421 +v -4.278798 0.483220 0.711072 +v -4.229631 0.565988 0.611412 +v -4.039907 1.892682 1.903144 +v -4.176487 1.883898 1.924795 +v -4.127320 1.966665 1.825134 +vt 0.475306 0.012993 +vt 0.524059 0.012993 +vt 0.572811 0.012993 +vt 0.621564 0.012993 +vt 0.475306 0.232930 +vt 0.524059 0.232930 +vt 0.572811 0.232930 +vt 0.621564 0.232930 +vn -0.159359 0.653124 -0.740293 +vn -0.159359 0.653124 -0.740293 +vn -0.159359 0.653124 -0.740293 +vn -0.159359 0.653124 -0.740293 +vn 0.933302 -0.271664 0.234831 +vn 0.933302 -0.271664 0.234831 +vn 0.933302 -0.271664 0.234831 +vn 0.933302 -0.271664 0.234831 +vn -0.773945 -0.381464 0.505464 +vn -0.773945 -0.381464 0.505464 +vn -0.773945 -0.381464 0.505464 +vn -0.773945 -0.381464 0.505464 +s off +f 260/349/689 261/350/690 264/354/691 263/353/692 +f 261/350/693 262/351/694 265/355/695 264/354/696 +f 262/351/697 260/352/698 263/356/699 265/355/700 +v -3.239272 0.526544 0.759048 +v -3.375609 0.514178 0.780479 +v -3.327950 0.606955 0.689259 +v -3.143239 1.854496 2.131890 +v -3.279576 1.842130 2.153321 +v -3.231915 1.934906 2.062101 +vt 0.475306 0.012993 +vt 0.524059 0.012993 +vt 0.572811 0.012993 +vt 0.621564 0.012993 +vt 0.475306 0.232930 +vt 0.524059 0.232930 +vt 0.572811 0.232930 +vt 0.621564 0.232930 +vn -0.171462 0.714082 -0.678739 +vn -0.171462 0.714082 -0.678739 +vn -0.171462 0.714082 -0.678739 +vn -0.171462 0.714082 -0.678739 +vn 0.937813 -0.279982 0.205223 +vn 0.937813 -0.279982 0.205223 +vn 0.937813 -0.279982 0.205223 +vn 0.937813 -0.279982 0.205223 +vn -0.766344 -0.434134 0.473546 +vn -0.766344 -0.434133 0.473546 +vn -0.766344 -0.434134 0.473546 +vn -0.766344 -0.434133 0.473546 +s off +f 266/357/701 267/358/702 270/362/703 269/361/704 +f 267/358/705 268/359/706 271/363/707 270/362/708 +f 268/359/709 266/360/710 269/364/711 271/363/712 +v -3.163167 -0.512404 4.366673 +v -3.288760 -0.570938 4.366673 +v -3.225963 -0.541671 4.246673 +v -4.291037 1.907626 4.366672 +v -4.416630 1.849092 4.366673 +v -4.353833 1.878359 4.246673 +vt 0.475306 0.012993 +vt 0.524059 0.012993 +vt 0.572811 0.012993 +vt 0.621564 0.012993 +vt 0.475306 0.232930 +vt 0.524059 0.232930 +vt 0.572811 0.232930 +vt 0.621564 0.232930 +vn 0.000000 -0.000001 -1.000000 +vn 0.000000 -0.000001 -1.000000 +vn 0.000000 -0.000001 -1.000000 +vn 0.000000 -0.000001 -1.000000 +vn 0.784961 0.365836 0.500000 +vn 0.784961 0.365836 0.500000 +vn 0.784961 0.365836 0.500000 +vn 0.784961 0.365836 0.500000 +vn -0.784963 -0.365836 0.499998 +vn -0.784963 -0.365836 0.499998 +vn -0.784963 -0.365836 0.499998 +vn -0.784963 -0.365836 0.499998 +s off +f 272/365/713 273/366/714 276/370/715 275/369/716 +f 273/366/717 274/367/718 277/371/719 276/370/720 +f 274/367/721 272/368/722 275/372/723 277/371/724 +v -2.090913 -0.552991 4.366673 +v -2.216506 -0.611525 4.366673 +v -2.153710 -0.582258 4.246673 +v -3.269892 1.976702 4.366673 +v -3.395485 1.918168 4.366673 +v -3.332688 1.947435 4.246673 +vt 0.475306 0.012993 +vt 0.524059 0.012993 +vt 0.572811 0.012993 +vt 0.621564 0.012993 +vt 0.475306 0.232930 +vt 0.524059 0.232930 +vt 0.572811 0.232930 +vt 0.621564 0.232930 +vn 0.000005 0.000000 -1.000000 +vn 0.000005 0.000000 -1.000000 +vn 0.000005 0.000000 -1.000000 +vn 0.000005 0.000000 -1.000000 +vn 0.784961 0.365837 0.499999 +vn 0.784961 0.365837 0.499999 +vn 0.784961 0.365837 0.499999 +vn 0.784961 0.365837 0.499999 +vn -0.784962 -0.365835 0.500000 +vn -0.784962 -0.365835 0.500000 +vn -0.784962 -0.365835 0.500000 +vn -0.784962 -0.365835 0.500000 +s off +f 278/373/725 279/374/726 282/378/727 281/377/728 +f 279/374/729 280/375/730 283/379/731 282/378/732 +f 280/375/733 278/376/734 281/380/735 283/379/736 +v -5.517155 0.803553 -1.563271 +v -5.487778 -0.252819 -0.145963 +v -5.274500 -0.974333 1.464671 +v -5.274499 0.952056 -1.477533 +v -5.487779 0.252819 0.145963 +v -5.517155 -0.781276 1.576133 +v -5.303876 0.252819 0.145963 +v -5.303876 -0.252819 -0.145963 +v -5.502548 0.333527 -0.821039 +v -5.374407 0.570041 -0.684488 +v -5.289107 0.544277 -0.699363 +v -5.417247 0.307763 -0.835914 +v -5.374407 -0.585636 0.675485 +v -5.502548 -0.320803 0.828386 +v -5.417247 -0.292169 0.844918 +v -5.289107 -0.557001 0.692017 +vt 0.751894 0.271249 +vt 0.688242 0.270269 +vt 0.624590 0.269288 +vt 0.742593 0.186217 +vt 0.689223 0.206617 +vt 0.636506 0.184582 +vt 0.690203 0.142965 +vt 0.723500 0.047977 +vt 0.691184 0.079313 +vt 0.659848 0.046996 +vt 0.692165 0.015661 +vt 0.715908 0.196417 +vt 0.720068 0.270759 +vt 0.716398 0.164591 +vt 0.707342 0.063645 +vt 0.707832 0.031819 +vt 0.662864 0.195599 +vt 0.656416 0.269778 +vt 0.663355 0.163773 +vt 0.675516 0.063154 +vt 0.676006 0.031328 +vn -0.990061 0.139469 -0.018114 +vn -0.822500 0.528726 0.209628 +vn 0.317694 0.344286 -0.883481 +vn -0.317702 0.592979 -0.739893 +vn 0.822500 -0.445906 -0.353075 +vn 0.990061 -0.054049 -0.129840 +vn -0.948960 0.273223 0.157558 +vn -0.948215 -0.273253 -0.161933 +vn -0.991413 -0.129753 0.016270 +vn -0.842918 -0.500011 -0.198694 +vn 0.260994 -0.414547 0.871799 +vn -0.260998 -0.547769 0.794877 +vn 0.948215 0.276863 0.155677 +vn 0.842917 0.422079 0.333676 +vn 0.948960 -0.273060 -0.157838 +vn 0.991413 0.050787 0.120506 +s 1 +f 292/393/737 293/392/738 287/384/739 284/381/740 +f 295/395/741 292/396/737 284/388/740 +f 294/394/742 295/395/741 284/388/740 287/384/739 +f 293/392/738 294/394/742 287/384/739 +f 288/385/743 293/392/738 292/393/737 285/382/744 +f 297/397/745 296/398/746 286/383/747 289/386/748 +f 290/387/749 294/394/742 293/392/738 288/385/743 +f 298/399/750 297/397/745 289/386/748 +f 291/389/751 295/395/741 294/394/742 290/387/749 +f 299/400/752 298/399/750 289/386/748 286/390/747 +f 285/391/744 292/396/737 295/395/741 291/389/751 +f 296/401/746 299/400/752 286/390/747 +f 296/398/746 297/397/745 288/385/743 285/382/744 +f 299/400/752 296/401/746 285/391/744 291/389/751 +f 298/399/750 299/400/752 291/389/751 290/387/749 +f 297/397/745 298/399/750 290/387/749 288/385/743 +v -4.728155 0.086603 0.050000 +v -4.728154 0.086603 -0.050000 +v -4.728155 0.000000 -0.100000 +v -4.728154 -0.086603 -0.050000 +v -4.728155 -0.086603 0.050000 +v -4.728154 0.000000 0.100000 +v -5.628155 0.086603 0.050000 +v -5.628154 0.086603 -0.050000 +v -5.628155 0.000000 -0.100000 +v -5.628154 -0.086603 -0.050000 +v -5.628155 -0.086603 0.050000 +v -5.628154 0.000000 0.100000 +v -5.628154 0.000000 -0.000000 +vt 0.988488 0.024988 +vt 0.988520 0.041334 +vt 0.988552 0.057679 +vt 0.988584 0.074025 +vt 0.988616 0.090371 +vt 0.988648 0.106717 +vt 0.988680 0.123062 +vt 0.841008 0.025277 +vt 0.841040 0.041623 +vt 0.841072 0.057968 +vt 0.841104 0.074314 +vt 0.841136 0.090659 +vt 0.841168 0.107005 +vt 0.841200 0.123351 +vt 0.830926 0.091661 +vt 0.830824 0.039274 +vt 0.785404 0.013169 +vt 0.740087 0.039452 +vt 0.740190 0.091839 +vt 0.785609 0.117943 +vt 0.787602 0.065552 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn -0.000000 0.499997 -0.866027 +vn -0.000000 0.499997 -0.866027 +vn -0.000000 0.499997 -0.866027 +vn -0.000000 0.499997 -0.866027 +vn 0.000000 -0.499999 -0.866026 +vn 0.000000 -0.499999 -0.866026 +vn 0.000000 -0.499999 -0.866026 +vn 0.000000 -0.499999 -0.866026 +vn 0.000000 -1.000000 0.000000 +vn 0.000000 -1.000000 0.000000 +vn 0.000000 -1.000000 0.000000 +vn 0.000000 -1.000000 0.000000 +vn 0.000000 -0.499997 0.866027 +vn 0.000000 -0.499997 0.866027 +vn 0.000000 -0.499997 0.866027 +vn 0.000000 -0.499997 0.866027 +vn 0.000000 0.499999 0.866026 +vn 0.000000 0.499999 0.866026 +vn 0.000000 0.499999 0.866026 +vn 0.000000 0.499999 0.866026 +vn -1.000000 -0.000007 -0.000005 +vn -1.000000 0.000003 -0.000002 +vn -1.000000 0.000001 -0.000002 +vn -1.000000 0.000003 0.000005 +vn -1.000000 0.000000 -0.000002 +vn -1.000000 0.000007 -0.000005 +vn -1.000000 0.000000 0.000000 +s off +f 300/402/753 301/403/754 307/410/755 306/409/756 +f 301/403/757 302/404/758 308/411/759 307/410/760 +f 302/404/761 303/405/762 309/412/763 308/411/764 +f 303/405/765 304/406/766 310/413/767 309/412/768 +f 304/406/769 305/407/770 311/414/771 310/413/772 +f 305/407/773 300/408/774 306/415/775 311/414/776 +s 1 +f 306/420/777 307/419/778 312/422/779 +f 307/419/778 308/418/780 312/422/779 +f 308/418/780 309/417/781 312/422/779 +f 309/417/781 310/416/782 312/422/779 +f 310/416/782 311/421/783 312/422/779 +f 311/421/783 306/420/777 312/422/779 +v -3.373292 -2.034549 -1.257066 +v -3.511857 -2.034549 -1.257066 +v -3.442574 -2.094549 -1.153143 +v -3.373292 -0.302498 -0.257066 +v -3.511857 -0.302498 -0.257066 +v -3.442574 -0.362498 -0.153143 +vt 0.475306 0.012993 +vt 0.524059 0.012993 +vt 0.572811 0.012993 +vt 0.621564 0.012993 +vt 0.475306 0.232930 +vt 0.524059 0.232930 +vt 0.572811 0.232930 +vt 0.621564 0.232930 +vn 0.866025 0.250000 -0.433013 +vn -0.866027 0.250000 -0.433011 +vn -0.866026 0.250000 -0.433011 +vn 0.866025 0.250001 -0.433013 +vn -0.000000 -0.499999 0.866026 +vn -0.000000 -0.499999 0.866026 +s 1 +f 313/423/784 314/424/785 317/428/786 316/427/787 +f 314/424/785 315/425/788 318/429/789 317/428/786 +f 315/425/788 313/426/784 316/430/787 318/429/789 +v -3.250543 -1.665037 -1.076869 +v -3.141562 -1.815037 -1.076869 +v -3.141562 -2.000447 -1.076869 +v -3.250544 -2.150447 -1.076869 +v -3.426880 -2.207742 -1.076869 +v -3.603215 -2.150447 -1.076869 +v -3.712196 -2.000447 -1.076869 +v -3.712196 -1.815037 -1.076869 +v -3.603215 -1.665037 -1.076869 +v -3.426879 -1.607742 -1.076869 +v -3.250543 -1.665037 -1.376869 +v -3.141562 -1.815037 -1.376869 +v -3.141562 -2.000447 -1.376869 +v -3.250544 -2.150447 -1.376869 +v -3.426880 -2.207742 -1.376870 +v -3.603215 -2.150447 -1.376869 +v -3.712196 -2.000447 -1.376870 +v -3.712196 -1.815037 -1.376869 +v -3.603215 -1.665037 -1.376869 +v -3.426879 -1.607742 -1.376869 +v -3.426879 -1.907742 -1.076869 +v -3.426879 -1.907742 -1.271261 +vt 0.252891 0.122706 +vt 0.283344 0.107201 +vt 0.298868 0.076756 +vt 0.293532 0.043002 +vt 0.269375 0.018830 +vt 0.235623 0.013474 +vt 0.205170 0.028980 +vt 0.189646 0.059424 +vt 0.194982 0.093179 +vt 0.219140 0.117351 +vt 0.987153 0.141536 +vt 0.986865 0.156219 +vt 0.986578 0.170901 +vt 0.986290 0.185584 +vt 0.986003 0.200266 +vt 0.985715 0.214949 +vt 0.985428 0.229631 +vt 0.985140 0.244313 +vt 0.984853 0.258995 +vt 0.984565 0.273678 +vt 0.984278 0.288360 +vt 0.766365 0.137213 +vt 0.766077 0.151896 +vt 0.765790 0.166578 +vt 0.765503 0.181260 +vt 0.765215 0.195943 +vt 0.764927 0.210625 +vt 0.764640 0.225307 +vt 0.764352 0.239990 +vt 0.764065 0.254672 +vt 0.763777 0.269355 +vt 0.763490 0.284037 +vt 0.498215 0.317674 +vt 0.521155 0.305994 +vt 0.532848 0.283062 +vt 0.528828 0.257636 +vt 0.510632 0.239429 +vt 0.485208 0.235394 +vt 0.462269 0.247074 +vt 0.450576 0.270006 +vt 0.454595 0.295432 +vt 0.472792 0.313640 +vt 0.246228 0.069095 +vt 0.493196 0.277291 +vn 0.545745 0.751153 0.371391 +vn 0.883034 0.286915 0.371391 +vn 0.859567 0.279290 -0.427950 +vn 0.531242 0.731191 -0.427951 +vn 0.883033 -0.286916 0.371391 +vn 0.859567 -0.279291 -0.427951 +vn 0.545744 -0.751154 0.371391 +vn 0.531242 -0.731191 -0.427951 +vn -0.000000 -0.928477 0.371390 +vn -0.000000 -0.903802 -0.427952 +vn -0.545746 -0.751153 0.371391 +vn -0.531243 -0.731191 -0.427950 +vn -0.883034 -0.286914 0.371391 +vn -0.859567 -0.279289 -0.427952 +vn -0.883034 0.286915 0.371390 +vn -0.859567 0.279290 -0.427951 +vn -0.545745 0.751153 0.371391 +vn -0.531242 0.731191 -0.427951 +vn 0.000000 0.928477 0.371390 +vn 0.000000 0.903802 -0.427951 +vn -0.000000 -0.000000 1.000000 +vn 0.000000 0.000000 -1.000000 +s 1 +f 319/441/790 320/442/791 330/453/792 329/452/793 +f 320/442/791 321/443/794 331/454/795 330/453/792 +f 321/443/794 322/444/796 332/455/797 331/454/795 +f 322/444/796 323/445/798 333/456/799 332/455/797 +f 323/445/798 324/446/800 334/457/801 333/456/799 +f 324/446/800 325/447/802 335/458/803 334/457/801 +f 325/447/802 326/448/804 336/459/805 335/458/803 +f 326/448/804 327/449/806 337/460/807 336/459/805 +f 327/449/806 328/450/808 338/461/809 337/460/807 +f 328/450/808 319/451/790 329/462/793 338/461/809 +f 320/432/791 319/431/790 339/473/810 +f 321/433/794 320/432/791 339/473/810 +f 322/434/796 321/433/794 339/473/810 +f 323/435/798 322/434/796 339/473/810 +f 324/436/800 323/435/798 339/473/810 +f 325/437/802 324/436/800 339/473/810 +f 326/438/804 325/437/802 339/473/810 +f 327/439/806 326/438/804 339/473/810 +f 328/440/808 327/439/806 339/473/810 +f 319/431/790 328/440/808 339/473/810 +f 329/471/793 330/470/792 340/474/811 +f 330/470/792 331/469/795 340/474/811 +f 331/469/795 332/468/797 340/474/811 +f 332/468/797 333/467/799 340/474/811 +f 333/467/799 334/466/801 340/474/811 +f 334/466/801 335/465/803 340/474/811 +f 335/465/803 336/464/805 340/474/811 +f 336/464/805 337/463/807 340/474/811 +f 337/463/807 338/472/809 340/474/811 +f 338/472/809 329/471/793 340/474/811 +v -3.373292 -2.034549 1.257066 +v -3.511857 -2.034549 1.257066 +v -3.442574 -2.094549 1.153143 +v -3.373292 -0.302498 0.257066 +v -3.511857 -0.302498 0.257066 +v -3.442574 -0.362498 0.153143 +vt 0.475306 0.012993 +vt 0.524059 0.012993 +vt 0.572811 0.012993 +vt 0.621564 0.012993 +vt 0.475306 0.232930 +vt 0.524059 0.232930 +vt 0.572811 0.232930 +vt 0.621564 0.232930 +vn -0.866025 -0.250000 -0.433013 +vn 0.866027 -0.249999 -0.433011 +vn 0.866026 -0.249999 -0.433011 +vn -0.866025 -0.250001 -0.433014 +vn 0.000000 0.500000 0.866025 +vn -0.000000 0.500000 0.866026 +s 1 +f 341/475/812 342/476/813 345/480/814 344/479/815 +f 342/476/813 343/477/816 346/481/817 345/480/814 +f 343/477/816 341/478/812 344/482/815 346/481/817 +v -3.250543 -1.665037 1.076869 +v -3.141562 -1.815037 1.076869 +v -3.141562 -2.000447 1.076869 +v -3.250543 -2.150447 1.076869 +v -3.426879 -2.207742 1.076869 +v -3.603214 -2.150447 1.076869 +v -3.712196 -2.000447 1.076869 +v -3.712196 -1.815037 1.076869 +v -3.603214 -1.665037 1.076869 +v -3.426879 -1.607742 1.076869 +v -3.250544 -1.665037 1.376869 +v -3.141562 -1.815037 1.376869 +v -3.141562 -2.000447 1.376869 +v -3.250544 -2.150447 1.376869 +v -3.426879 -2.207742 1.376869 +v -3.603215 -2.150447 1.376869 +v -3.712196 -2.000447 1.376869 +v -3.712196 -1.815037 1.376869 +v -3.603215 -1.665037 1.376869 +v -3.426879 -1.607742 1.376869 +v -3.426879 -1.907742 1.076869 +v -3.426879 -1.907742 1.271261 +vt 0.252891 0.122706 +vt 0.283344 0.107201 +vt 0.298868 0.076756 +vt 0.293532 0.043002 +vt 0.269375 0.018830 +vt 0.235623 0.013474 +vt 0.205170 0.028980 +vt 0.189646 0.059424 +vt 0.194982 0.093179 +vt 0.219140 0.117351 +vt 0.987153 0.141536 +vt 0.986865 0.156219 +vt 0.986578 0.170901 +vt 0.986290 0.185584 +vt 0.986003 0.200266 +vt 0.985715 0.214949 +vt 0.985428 0.229631 +vt 0.985140 0.244313 +vt 0.984853 0.258995 +vt 0.984565 0.273678 +vt 0.984278 0.288360 +vt 0.766365 0.137213 +vt 0.766077 0.151896 +vt 0.765790 0.166578 +vt 0.765503 0.181260 +vt 0.765215 0.195943 +vt 0.764927 0.210625 +vt 0.764640 0.225307 +vt 0.764352 0.239990 +vt 0.764065 0.254672 +vt 0.763777 0.269355 +vt 0.763490 0.284037 +vt 0.498215 0.317674 +vt 0.521155 0.305994 +vt 0.532848 0.283062 +vt 0.528828 0.257636 +vt 0.510632 0.239429 +vt 0.485208 0.235394 +vt 0.462269 0.247074 +vt 0.450576 0.270006 +vt 0.454595 0.295432 +vt 0.472792 0.313640 +vt 0.246228 0.069095 +vt 0.493196 0.277291 +vn -0.545745 -0.751153 0.371390 +vn -0.883034 -0.286915 0.371390 +vn -0.859567 -0.279290 -0.427951 +vn -0.531241 -0.731192 -0.427951 +vn -0.883034 0.286915 0.371390 +vn -0.859567 0.279290 -0.427952 +vn -0.545745 0.751154 0.371390 +vn -0.531240 0.731191 -0.427952 +vn 0.000000 0.928477 0.371391 +vn -0.000000 0.903802 -0.427952 +vn 0.545745 0.751153 0.371392 +vn 0.531242 0.731191 -0.427951 +vn 0.883034 0.286914 0.371391 +vn 0.859567 0.279290 -0.427951 +vn 0.883034 -0.286915 0.371391 +vn 0.859567 -0.279290 -0.427951 +vn 0.545745 -0.751154 0.371391 +vn 0.531242 -0.731191 -0.427950 +vn 0.000000 -0.928477 0.371391 +vn -0.000000 -0.903802 -0.427951 +vn -0.000000 0.000000 1.000000 +vn 0.000000 0.000000 -1.000000 +s 1 +f 347/493/818 348/494/819 358/505/820 357/504/821 +f 348/494/819 349/495/822 359/506/823 358/505/820 +f 349/495/822 350/496/824 360/507/825 359/506/823 +f 350/496/824 351/497/826 361/508/827 360/507/825 +f 351/497/826 352/498/828 362/509/829 361/508/827 +f 352/498/828 353/499/830 363/510/831 362/509/829 +f 353/499/830 354/500/832 364/511/833 363/510/831 +f 354/500/832 355/501/834 365/512/835 364/511/833 +f 355/501/834 356/502/836 366/513/837 365/512/835 +f 356/502/836 347/503/818 357/514/821 366/513/837 +f 348/484/819 347/483/818 367/525/838 +f 349/485/822 348/484/819 367/525/838 +f 350/486/824 349/485/822 367/525/838 +f 351/487/826 350/486/824 367/525/838 +f 352/488/828 351/487/826 367/525/838 +f 353/489/830 352/488/828 367/525/838 +f 354/490/832 353/489/830 367/525/838 +f 355/491/834 354/490/832 367/525/838 +f 356/492/836 355/491/834 367/525/838 +f 347/483/818 356/492/836 367/525/838 +f 357/523/821 358/522/820 368/526/839 +f 358/522/820 359/521/823 368/526/839 +f 359/521/823 360/520/825 368/526/839 +f 360/520/825 361/519/827 368/526/839 +f 361/519/827 362/518/829 368/526/839 +f 362/518/829 363/517/831 368/526/839 +f 363/517/831 364/516/833 368/526/839 +f 364/516/833 365/515/835 368/526/839 +f 365/515/835 366/524/837 368/526/839 +f 366/524/837 357/523/821 368/526/839 +v 3.068942 -0.472892 0.150000 +v 3.068942 -0.658302 0.150000 +v 2.959961 -0.808302 0.150000 +v 2.783625 -0.865597 0.150000 +v 2.607290 -0.808302 0.150000 +v 2.498308 -0.658302 0.150000 +v 2.498308 -0.472892 0.150000 +v 3.068942 -0.472892 -0.150000 +v 3.068942 -0.658302 -0.150000 +v 2.959961 -0.808302 -0.150000 +v 2.783625 -0.865597 -0.150000 +v 2.607290 -0.808302 -0.150000 +v 2.498308 -0.658302 -0.150000 +v 2.498308 -0.472892 -0.150000 +v 2.783625 -0.565597 0.150000 +v 2.783625 -0.565597 -0.044391 +vt 0.283344 0.107201 +vt 0.298868 0.076756 +vt 0.293532 0.043002 +vt 0.269375 0.018830 +vt 0.235623 0.013474 +vt 0.205170 0.028980 +vt 0.189646 0.059424 +vt 0.986865 0.156219 +vt 0.986578 0.170901 +vt 0.986290 0.185584 +vt 0.986003 0.200266 +vt 0.985715 0.214949 +vt 0.985428 0.229631 +vt 0.985140 0.244313 +vt 0.766077 0.151896 +vt 0.765790 0.166578 +vt 0.765503 0.181260 +vt 0.765215 0.195943 +vt 0.764927 0.210625 +vt 0.764640 0.225307 +vt 0.764352 0.239990 +vt 0.521155 0.305994 +vt 0.532848 0.283062 +vt 0.528828 0.257636 +vt 0.510632 0.239429 +vt 0.485208 0.235394 +vt 0.462269 0.247074 +vt 0.450576 0.270006 +vt 0.246228 0.069095 +vt 0.493196 0.277291 +vn 0.934652 0.000000 0.355563 +vn 0.883034 -0.286915 0.371391 +vn 0.859567 -0.279290 -0.427951 +vn 0.911810 0.000000 -0.410612 +vn 0.545745 -0.751153 0.371391 +vn 0.531242 -0.731191 -0.427951 +vn -0.000000 -0.928477 0.371391 +vn -0.000000 -0.903802 -0.427951 +vn -0.545745 -0.751154 0.371391 +vn -0.531241 -0.731191 -0.427951 +vn -0.883034 -0.286915 0.371391 +vn -0.859567 -0.279291 -0.427951 +vn -0.934652 0.000000 0.355563 +vn -0.911810 0.000000 -0.410612 +vn 0.000000 0.000000 1.000000 +vn 0.000000 0.186532 -0.982449 +s 1 +f 369/534/840 370/535/841 377/542/842 376/541/843 +f 370/535/841 371/536/844 378/543/845 377/542/842 +f 371/536/844 372/537/846 379/544/847 378/543/845 +f 372/537/846 373/538/848 380/545/849 379/544/847 +f 373/538/848 374/539/850 381/546/851 380/545/849 +f 374/539/850 375/540/852 382/547/853 381/546/851 +f 370/528/841 369/527/840 383/555/854 +f 371/529/844 370/528/841 383/555/854 +f 372/530/846 371/529/844 383/555/854 +f 373/531/848 372/530/846 383/555/854 +f 374/532/850 373/531/848 383/555/854 +f 375/533/852 374/532/850 383/555/854 +f 376/554/843 377/553/842 384/556/855 +f 377/553/842 378/552/845 384/556/855 +f 378/552/845 379/551/847 384/556/855 +f 379/551/847 380/550/849 384/556/855 +f 380/550/849 381/549/851 384/556/855 +f 381/549/851 382/548/853 384/556/855 diff --git a/Arduino/MPU6050/examples/MPU6050_DMP6_using_DMP_V6.12/MPUplane/data/diffuse_512.png b/Arduino/MPU6050/examples/MPU6050_DMP6_using_DMP_V6.12/MPUplane/data/diffuse_512.png new file mode 100644 index 0000000000000000000000000000000000000000..930d910b947a7e494fc5430018e4f2dc33344fee GIT binary patch literal 361095 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

U5qFeB;E@mN(p95UK+~c+orTlU99_FAxn?B(Q{ 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%0D2-ixWH}v0<%Rx_c@>-~UASg~gI~q6F4I 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

bYExGB<> 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 literal 0 HcmV?d00001 From 335c88b432cf53df2261551f64095446091c6461 Mon Sep 17 00:00:00 2001 From: Hasi123 Date: Thu, 8 Apr 2021 21:15:40 +0200 Subject: [PATCH 260/335] Fastwire I2C freq fix I noticed, that any read and write took 2 times as much time on 8 Mhz compared to 16 Mhz. This commit fixes this issue and makes the I2C frequency F_CPU dependent. --- Arduino/I2Cdev/I2Cdev.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Arduino/I2Cdev/I2Cdev.cpp b/Arduino/I2Cdev/I2Cdev.cpp index 55256240..42c37340 100644 --- a/Arduino/I2Cdev/I2Cdev.cpp +++ b/Arduino/I2Cdev/I2Cdev.cpp @@ -753,7 +753,7 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; #endif TWSR = 0; // no prescaler => prescaler = 1 - TWBR = ((16000L / khz) - 16) / 2; // change the I2C clock rate + TWBR = F_CPU / 2000 / khz - 8; // change the I2C clock rate TWCR = 1 << TWEN; // enable twi module, no interrupt } From 2b991297a03a6430b6d1a898f385a154fecbae1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josef=20Adam=C4=8D=C3=ADk?= Date: Thu, 24 Jun 2021 08:49:16 +0200 Subject: [PATCH 261/335] Update MPU6050_6Axis_MotionApps_V6_12.h remove the misplaced dot as commented --- Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h b/Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h index 2595f4b5..b08516e1 100644 --- a/Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h +++ b/Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h @@ -49,7 +49,7 @@ THE SOFTWARE. // Tom Carpenter's conditional PROGMEM code // http://forum.arduino.cc/index.php?topic=129407.0 #ifdef __AVR__ - #include . + #include #elif defined(ESP32) #include #else From a83fac7440f8fb00a35ca224a837f1362ef7675e Mon Sep 17 00:00:00 2001 From: Ibrahim Bendebka <38193798+SB3NDER@users.noreply.github.com> Date: Thu, 29 Jul 2021 16:25:33 +0200 Subject: [PATCH 262/335] Fixed gravity value according to accel range --- Arduino/MPU6050/MPU6050.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Arduino/MPU6050/MPU6050.cpp b/Arduino/MPU6050/MPU6050.cpp index 267fca98..f19711bb 100644 --- a/Arduino/MPU6050/MPU6050.cpp +++ b/Arduino/MPU6050/MPU6050.cpp @@ -3298,7 +3298,9 @@ void MPU6050::PID(uint8_t ReadAddress, float kP,float kI, uint8_t Loops){ uint8_t shift =(SaveAddress == 0x77)?3:2; float Error, PTerm, ITerm[3]; int16_t eSample; - uint32_t eSum ; + uint32_t eSum; + uint16_t gravity; + if (ReadAddress == 0x3B) gravity = 16384 >> getFullScaleAccelRange(); Serial.write('>'); for (int i = 0; i < 3; i++) { I2Cdev::readWords(devAddr, SaveAddress + (i * shift), 1, (uint16_t *)&Data); // reads 1 or more 16 bit integers (Word) @@ -3317,7 +3319,7 @@ void MPU6050::PID(uint8_t ReadAddress, float kP,float kI, uint8_t Loops){ for (int i = 0; i < 3; i++) { I2Cdev::readWords(devAddr, ReadAddress + (i * 2), 1, (uint16_t *)&Data); // reads 1 or more 16 bit integers (Word) Reading = Data; - if ((ReadAddress == 0x3B)&&(i == 2)) Reading -= 16384; //remove Gravity + if ((ReadAddress == 0x3B)&&(i == 2)) Reading -= gravity; //remove Gravity Error = -Reading; eSum += abs(Reading); PTerm = kP * Error; From b4ed5eb444cef1413d890aa8ac6cbf5766264b2f Mon Sep 17 00:00:00 2001 From: DasK Date: Wed, 25 Aug 2021 14:53:30 +0100 Subject: [PATCH 263/335] Nasty bug in STM32/I2Cdev.c It took me like 6 hours to track it down --- STM32/I2Cdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/STM32/I2Cdev.c b/STM32/I2Cdev.c index 5be44cf3..3770dba3 100644 --- a/STM32/I2Cdev.c +++ b/STM32/I2Cdev.c @@ -264,7 +264,7 @@ int8_t I2Cdev_writeWord(uint8_t dev_addr, uint8_t reg_addr, uint16_t data) { int8_t err; uint8_t ts_data[3] = {reg_addr, (data >> 8) & 0xFF, data & 0xFF}; - err = i2c_transmit_nack(reg_addr, ts_data, 3); + err = i2c_transmit_nack(dev_addr, ts_data, 3); return err; } From 251badeb15f550dea418f1265adb2bcf3a0aee0e Mon Sep 17 00:00:00 2001 From: Jeff Rowberg Date: Mon, 20 Sep 2021 22:08:01 -0400 Subject: [PATCH 264/335] Implement platform-safe BUFFER_LENGTH detection --- Arduino/I2Cdev/I2Cdev.cpp | 35 +++++++++++++++-------------------- Arduino/I2Cdev/I2Cdev.h | 13 +++++++++++++ Arduino/MPU6050/MPU6050.cpp | 9 ++------- Arduino/MPU6050/MPU6050.h | 3 --- MSP430/I2Cdev/I2Cdev.cpp | 30 +++++++++++++++--------------- 5 files changed, 45 insertions(+), 45 deletions(-) diff --git a/Arduino/I2Cdev/I2Cdev.cpp b/Arduino/I2Cdev/I2Cdev.cpp index 42c37340..e39ffe6d 100644 --- a/Arduino/I2Cdev/I2Cdev.cpp +++ b/Arduino/I2Cdev/I2Cdev.cpp @@ -87,11 +87,6 @@ THE SOFTWARE. #endif -#ifndef BUFFER_LENGTH -// band-aid fix for platforms without Wire-defined BUFFER_LENGTH (removed from some official implementations) -#define BUFFER_LENGTH 32 -#endif - /** Default constructor. */ I2Cdev::I2Cdev() { @@ -228,14 +223,14 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 // Arduino v00xx (before v1.0), Wire library // I2C/TWI subsystem uses internal buffer that breaks with large data requests - // so if user requests more than BUFFER_LENGTH bytes, we have to do it in + // so if user requests more than I2CDEVLIB_WIRE_BUFFER_LENGTH bytes, we have to do it in // smaller chunks instead of all at once - for (uint8_t k = 0; k < length; k += min((int)length, BUFFER_LENGTH)) { + for (uint8_t k = 0; k < length; k += min((int)length, I2CDEVLIB_WIRE_BUFFER_LENGTH)) { Wire.beginTransmission(devAddr); Wire.send(regAddr); Wire.endTransmission(); Wire.beginTransmission(devAddr); - Wire.requestFrom(devAddr, (uint8_t)min(length - k, BUFFER_LENGTH)); + Wire.requestFrom(devAddr, (uint8_t)min(length - k, I2CDEVLIB_WIRE_BUFFER_LENGTH)); for (; Wire.available() && (timeout == 0 || millis() - t1 < timeout); count++) { data[count] = Wire.receive(); @@ -252,14 +247,14 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 // Adds standardized write() and read() stream methods instead of send() and receive() // I2C/TWI subsystem uses internal buffer that breaks with large data requests - // so if user requests more than BUFFER_LENGTH bytes, we have to do it in + // so if user requests more than I2CDEVLIB_WIRE_BUFFER_LENGTH bytes, we have to do it in // smaller chunks instead of all at once - for (uint8_t k = 0; k < length; k += min((int)length, BUFFER_LENGTH)) { + for (uint8_t k = 0; k < length; k += min((int)length, I2CDEVLIB_WIRE_BUFFER_LENGTH)) { Wire.beginTransmission(devAddr); Wire.write(regAddr); Wire.endTransmission(); Wire.beginTransmission(devAddr); - Wire.requestFrom(devAddr, (uint8_t)min(length - k, BUFFER_LENGTH)); + Wire.requestFrom(devAddr, (uint8_t)min(length - k, I2CDEVLIB_WIRE_BUFFER_LENGTH)); for (; Wire.available() && (timeout == 0 || millis() - t1 < timeout); count++) { data[count] = Wire.read(); @@ -276,14 +271,14 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 // Adds official support for repeated start condition, yay! // I2C/TWI subsystem uses internal buffer that breaks with large data requests - // so if user requests more than BUFFER_LENGTH bytes, we have to do it in + // so if user requests more than I2CDEVLIB_WIRE_BUFFER_LENGTH bytes, we have to do it in // smaller chunks instead of all at once - for (uint8_t k = 0; k < length; k += min((int)length, BUFFER_LENGTH)) { + for (uint8_t k = 0; k < length; k += min((int)length, I2CDEVLIB_WIRE_BUFFER_LENGTH)) { Wire.beginTransmission(devAddr); Wire.write(regAddr); Wire.endTransmission(); Wire.beginTransmission(devAddr); - Wire.requestFrom(devAddr, (uint8_t)min(length - k, BUFFER_LENGTH)); + Wire.requestFrom(devAddr, (uint8_t)min(length - k, I2CDEVLIB_WIRE_BUFFER_LENGTH)); for (; Wire.available() && (timeout == 0 || millis() - t1 < timeout); count++) { data[count] = Wire.read(); @@ -348,9 +343,9 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 // Arduino v00xx (before v1.0), Wire library // I2C/TWI subsystem uses internal buffer that breaks with large data requests - // so if user requests more than BUFFER_LENGTH bytes, we have to do it in + // so if user requests more than I2CDEVLIB_WIRE_BUFFER_LENGTH bytes, we have to do it in // smaller chunks instead of all at once - for (uint8_t k = 0; k < length * 2; k += min(length * 2, BUFFER_LENGTH)) { + for (uint8_t k = 0; k < length * 2; k += min(length * 2, I2CDEVLIB_WIRE_BUFFER_LENGTH)) { Wire.beginTransmission(devAddr); Wire.send(regAddr); Wire.endTransmission(); @@ -381,9 +376,9 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 // Adds standardized write() and read() stream methods instead of send() and receive() // I2C/TWI subsystem uses internal buffer that breaks with large data requests - // so if user requests more than BUFFER_LENGTH bytes, we have to do it in + // so if user requests more than I2CDEVLIB_WIRE_BUFFER_LENGTH bytes, we have to do it in // smaller chunks instead of all at once - for (uint8_t k = 0; k < length * 2; k += min(length * 2, BUFFER_LENGTH)) { + for (uint8_t k = 0; k < length * 2; k += min(length * 2, I2CDEVLIB_WIRE_BUFFER_LENGTH)) { Wire.beginTransmission(devAddr); Wire.write(regAddr); Wire.endTransmission(); @@ -414,9 +409,9 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 // Adds official support for repeated start condition, yay! // I2C/TWI subsystem uses internal buffer that breaks with large data requests - // so if user requests more than BUFFER_LENGTH bytes, we have to do it in + // so if user requests more than I2CDEVLIB_WIRE_BUFFER_LENGTH bytes, we have to do it in // smaller chunks instead of all at once - for (uint8_t k = 0; k < length * 2; k += min(length * 2, BUFFER_LENGTH)) { + for (uint8_t k = 0; k < length * 2; k += min(length * 2, I2CDEVLIB_WIRE_BUFFER_LENGTH)) { Wire.beginTransmission(devAddr); Wire.write(regAddr); Wire.endTransmission(); diff --git a/Arduino/I2Cdev/I2Cdev.h b/Arduino/I2Cdev/I2Cdev.h index 60c31950..c0dd3e1c 100644 --- a/Arduino/I2Cdev/I2Cdev.h +++ b/Arduino/I2Cdev/I2Cdev.h @@ -103,6 +103,19 @@ THE SOFTWARE. #define ARDUINO 101 #endif +#if defined(I2C_BUFFER_LENGTH) + // Arduino ESP32 core Wire uses this + #define I2CDEVLIB_WIRE_BUFFER_LENGTH I2C_BUFFER_LENGTH +#elif defined(BUFFER_LENGTH) + // Arduino AVR core Wire and many others use this + #define I2CDEVLIB_WIRE_BUFFER_LENGTH BUFFER_LENGTH +#elif defined(SERIAL_BUFFER_SIZE) + // Arduino SAMD core Wire uses this + #define I2CDEVLIB_WIRE_BUFFER_LENGTH SERIAL_BUFFER_SIZE +#else + // should be a safe fallback, though possibly inefficient + #define I2CDEVLIB_WIRE_BUFFER_LENGTH 32 +#endif // 1000ms default read timeout (modify with "I2Cdev::readTimeout = [ms];") #define I2CDEV_DEFAULT_READ_TIMEOUT 1000 diff --git a/Arduino/MPU6050/MPU6050.cpp b/Arduino/MPU6050/MPU6050.cpp index 267fca98..f3e2660f 100644 --- a/Arduino/MPU6050/MPU6050.cpp +++ b/Arduino/MPU6050/MPU6050.cpp @@ -37,11 +37,6 @@ THE SOFTWARE. #include "MPU6050.h" -#ifndef BUFFER_LENGTH -// band-aid fix for platforms without Wire-defined BUFFER_LENGTH (removed from some official implementations) -#define BUFFER_LENGTH 32 -#endif - /** Specific address constructor. * @param address I2C address, uses default I2C address if none is specified * @see MPU6050_DEFAULT_ADDRESS @@ -2765,12 +2760,12 @@ void MPU6050::getFIFOBytes(uint8_t *data, uint8_t length) { fifoC = 0; while (!(fifoC = getFIFOCount()) && ((micros() - BreakTimer) <= (11000))); // Get Next New Packet } else { //We have more than 1 packet but less than 200 bytes of data in the FIFO Buffer - uint8_t Trash[BUFFER_LENGTH]; + uint8_t Trash[I2CDEVLIB_WIRE_BUFFER_LENGTH]; while ((fifoC = getFIFOCount()) > length) { // Test each time just in case the MPU is writing to the FIFO Buffer fifoC = fifoC - length; // Save the last packet uint16_t RemoveBytes; while (fifoC) { // fifo count will reach zero so this is safe - RemoveBytes = min((int)fifoC, BUFFER_LENGTH); // Buffer Length is different than the packet length this will efficiently clear the buffer + RemoveBytes = min((int)fifoC, I2CDEVLIB_WIRE_BUFFER_LENGTH); // Buffer Length is different than the packet length this will efficiently clear the buffer getFIFOBytes(Trash, (uint8_t)RemoveBytes); fifoC -= RemoveBytes; } diff --git a/Arduino/MPU6050/MPU6050.h b/Arduino/MPU6050/MPU6050.h index bab7ec2c..5f27f428 100644 --- a/Arduino/MPU6050/MPU6050.h +++ b/Arduino/MPU6050/MPU6050.h @@ -46,9 +46,6 @@ THE SOFTWARE. #include #elif defined(ESP32) #include - #ifndef BUFFER_LENGTH - #define BUFFER_LENGTH 32 - #endif #else //#define PROGMEM /* empty */ //#define pgm_read_byte(x) (*(x)) diff --git a/MSP430/I2Cdev/I2Cdev.cpp b/MSP430/I2Cdev/I2Cdev.cpp index 7c37a8ee..f69ab6f1 100644 --- a/MSP430/I2Cdev/I2Cdev.cpp +++ b/MSP430/I2Cdev/I2Cdev.cpp @@ -224,14 +224,14 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 // Arduino v00xx (before v1.0), Wire library // I2C/TWI subsystem uses internal buffer that breaks with large data requests - // so if user requests more than BUFFER_LENGTH bytes, we have to do it in + // so if user requests more than I2CDEVLIB_WIRE_BUFFER_LENGTH bytes, we have to do it in // smaller chunks instead of all at once - for (uint8_t k = 0; k < length; k += min(length, BUFFER_LENGTH)) { + for (uint8_t k = 0; k < length; k += min(length, I2CDEVLIB_WIRE_BUFFER_LENGTH)) { Wire.beginTransmission(devAddr); Wire.send(regAddr); Wire.endTransmission(); Wire.beginTransmission(devAddr); - Wire.requestFrom(devAddr, (uint8_t)min(length - k, BUFFER_LENGTH)); + Wire.requestFrom(devAddr, (uint8_t)min(length - k, I2CDEVLIB_WIRE_BUFFER_LENGTH)); for (; Wire.available() && (timeout == 0 || millis() - t1 < timeout); count++) { data[count] = Wire.receive(); @@ -248,14 +248,14 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 // Adds standardized write() and read() stream methods instead of send() and receive() // I2C/TWI subsystem uses internal buffer that breaks with large data requests - // so if user requests more than BUFFER_LENGTH bytes, we have to do it in + // so if user requests more than I2CDEVLIB_WIRE_BUFFER_LENGTH bytes, we have to do it in // smaller chunks instead of all at once - for (uint8_t k = 0; k < length; k += min(length, BUFFER_LENGTH)) { + for (uint8_t k = 0; k < length; k += min(length, I2CDEVLIB_WIRE_BUFFER_LENGTH)) { Wire.beginTransmission(devAddr); Wire.write(regAddr); Wire.endTransmission(); Wire.beginTransmission(devAddr); - Wire.requestFrom(devAddr, (uint8_t)min(length - k, BUFFER_LENGTH)); + Wire.requestFrom(devAddr, (uint8_t)min(length - k, I2CDEVLIB_WIRE_BUFFER_LENGTH)); for (; Wire.available() && (timeout == 0 || millis() - t1 < timeout); count++) { data[count] = Wire.read(); @@ -272,14 +272,14 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 // Adds official support for repeated start condition, yay! // I2C/TWI subsystem uses internal buffer that breaks with large data requests - // so if user requests more than BUFFER_LENGTH bytes, we have to do it in + // so if user requests more than I2CDEVLIB_WIRE_BUFFER_LENGTH bytes, we have to do it in // smaller chunks instead of all at once - for (uint8_t k = 0; k < length; k += min(length, BUFFER_LENGTH)) { + for (uint8_t k = 0; k < length; k += min(length, I2CDEVLIB_WIRE_BUFFER_LENGTH)) { Wire.beginTransmission(devAddr); Wire.write(regAddr); Wire.endTransmission(); Wire.beginTransmission(devAddr); - Wire.requestFrom(devAddr, (uint8_t)min(length - k, BUFFER_LENGTH)); + Wire.requestFrom(devAddr, (uint8_t)min(length - k, I2CDEVLIB_WIRE_BUFFER_LENGTH)); for (; Wire.available() && (timeout == 0 || millis() - t1 < timeout); count++) { data[count] = Wire.read(); @@ -351,9 +351,9 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 // Arduino v00xx (before v1.0), Wire library // I2C/TWI subsystem uses internal buffer that breaks with large data requests - // so if user requests more than BUFFER_LENGTH bytes, we have to do it in + // so if user requests more than I2CDEVLIB_WIRE_BUFFER_LENGTH bytes, we have to do it in // smaller chunks instead of all at once - for (uint8_t k = 0; k < length * 2; k += min(length * 2, BUFFER_LENGTH)) { + for (uint8_t k = 0; k < length * 2; k += min(length * 2, I2CDEVLIB_WIRE_BUFFER_LENGTH)) { Wire.beginTransmission(devAddr); Wire.send(regAddr); Wire.endTransmission(); @@ -384,9 +384,9 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 // Adds standardized write() and read() stream methods instead of send() and receive() // I2C/TWI subsystem uses internal buffer that breaks with large data requests - // so if user requests more than BUFFER_LENGTH bytes, we have to do it in + // so if user requests more than I2CDEVLIB_WIRE_BUFFER_LENGTH bytes, we have to do it in // smaller chunks instead of all at once - for (uint8_t k = 0; k < length * 2; k += min(length * 2, BUFFER_LENGTH)) { + for (uint8_t k = 0; k < length * 2; k += min(length * 2, I2CDEVLIB_WIRE_BUFFER_LENGTH)) { Wire.beginTransmission(devAddr); Wire.write(regAddr); Wire.endTransmission(); @@ -417,9 +417,9 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 // Adds official support for repeated start condition, yay! // I2C/TWI subsystem uses internal buffer that breaks with large data requests - // so if user requests more than BUFFER_LENGTH bytes, we have to do it in + // so if user requests more than I2CDEVLIB_WIRE_BUFFER_LENGTH bytes, we have to do it in // smaller chunks instead of all at once - for (uint8_t k = 0; k < length * 2; k += min(length * 2, BUFFER_LENGTH)) { + for (uint8_t k = 0; k < length * 2; k += min(length * 2, I2CDEVLIB_WIRE_BUFFER_LENGTH)) { Wire.beginTransmission(devAddr); Wire.write(regAddr); Wire.endTransmission(); From 9f43aa7efbd23545ceb688c86ba4a864fc463a59 Mon Sep 17 00:00:00 2001 From: Jeff Rowberg Date: Mon, 20 Sep 2021 22:08:57 -0400 Subject: [PATCH 265/335] Remove unsafe _BV macro dependency --- Arduino/I2Cdev/I2Cdev.cpp | 14 +++++++------- Arduino/I2Cdev/I2Cdev.h | 6 +++--- .../MPU6050_DMP6_Ethernet.ino | 4 ++-- MSP430/I2Cdev/I2Cdev.cpp | 14 +++++++------- MSP430/I2Cdev/I2Cdev.h | 6 +++--- 5 files changed, 22 insertions(+), 22 deletions(-) diff --git a/Arduino/I2Cdev/I2Cdev.cpp b/Arduino/I2Cdev/I2Cdev.cpp index e39ffe6d..c0b1670e 100644 --- a/Arduino/I2Cdev/I2Cdev.cpp +++ b/Arduino/I2Cdev/I2Cdev.cpp @@ -988,7 +988,7 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; TWBR = ((CPU_FREQ / TWI_FREQ) - 16) / 2; // bitrate register // enable twi module, acks, and twi interrupt - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA); + TWCR = (1 << TWEN) | (1 << TWIE) | (1 << TWEA); /* TWEN - TWI Enable Bit TWIE - TWI Interrupt Enable @@ -1057,7 +1057,7 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; } void twii_SetStart() { - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTA); + TWCR = (1 << TWEN) | (1 << TWIE) | (1 << TWEA) | (1 << TWINT) | (1 << TWSTA); } void twi_write01() { @@ -1140,19 +1140,19 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; void twi_reply(uint8_t ack) { // transmit master read ready signal, with or without ack if (ack){ - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT) | _BV(TWEA); + TWCR = (1 << TWEN) | (1 << TWIE) | (1 << TWINT) | (1 << TWEA); } else { - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT); + TWCR = (1 << TWEN) | (1 << TWIE) | (1 << TWINT); } } void twi_stop(void) { // send stop condition - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTO); + TWCR = (1 << TWEN) | (1 << TWIE) | (1 << TWEA) | (1 << TWINT) | (1 << TWSTO); // wait for stop condition to be exectued on bus // TWINT is not set after a stop condition! - while (TWCR & _BV(TWSTO)) { + while (TWCR & (1 << TWSTO)) { continue; } @@ -1162,7 +1162,7 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; void twi_releaseBus(void) { // release bus - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT); + TWCR = (1 << TWEN) | (1 << TWIE) | (1 << TWEA) | (1 << TWINT); // update twi state twi_state = TWI_READY; diff --git a/Arduino/I2Cdev/I2Cdev.h b/Arduino/I2Cdev/I2Cdev.h index c0dd3e1c..bc1a9cca 100644 --- a/Arduino/I2Cdev/I2Cdev.h +++ b/Arduino/I2Cdev/I2Cdev.h @@ -253,7 +253,7 @@ class I2Cdev { /* TWI Status is in TWSR, in the top 5 bits: TWS7 - TWS3 */ - #define TW_STATUS_MASK (_BV(TWS7)|_BV(TWS6)|_BV(TWS5)|_BV(TWS4)|_BV(TWS3)) + #define TW_STATUS_MASK ((1 << TWS7)|(1 << TWS6)|(1 << TWS5)|(1 << TWS4)|(1 << TWS3)) #define TW_STATUS (TWSR & TW_STATUS_MASK) #define TW_START 0x08 #define TW_REP_START 0x10 @@ -288,11 +288,11 @@ class I2Cdev { //#define _SFR_BYTE(sfr) _MMIO_BYTE(_SFR_ADDR(sfr)) #ifndef sbi // set bit - #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) + #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= (1 << bit)) #endif // sbi #ifndef cbi // clear bit - #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) + #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~(1 << bit)) #endif // cbi extern TwoWire Wire; diff --git a/Arduino/MPU6050/examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino b/Arduino/MPU6050/examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino index 412e03d9..b2e2081d 100644 --- a/Arduino/MPU6050/examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino +++ b/Arduino/MPU6050/examples/MPU6050_DMP6_Ethernet/MPU6050_DMP6_Ethernet.ino @@ -281,14 +281,14 @@ void loop() { fifoCount = mpu.getFIFOCount(); // check for overflow (this should never happen unless our code is too inefficient) - if ((mpuIntStatus & _BV(MPU6050_INTERRUPT_FIFO_OFLOW_BIT)) || fifoCount >= 1024) { + if ((mpuIntStatus & (1 << MPU6050_INTERRUPT_FIFO_OFLOW_BIT)) || fifoCount >= 1024) { // reset so we can continue cleanly mpu.resetFIFO(); fifoCount = mpu.getFIFOCount(); Serial.println(F("FIFO overflow!")); // otherwise, check for DMP data ready interrupt (this should happen frequently) - } else if (mpuIntStatus & _BV(MPU6050_INTERRUPT_DMP_INT_BIT)) { + } else if (mpuIntStatus & (1 << MPU6050_INTERRUPT_DMP_INT_BIT)) { // wait for correct available data length, should be a VERY short wait while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount(); diff --git a/MSP430/I2Cdev/I2Cdev.cpp b/MSP430/I2Cdev/I2Cdev.cpp index f69ab6f1..7613b70e 100644 --- a/MSP430/I2Cdev/I2Cdev.cpp +++ b/MSP430/I2Cdev/I2Cdev.cpp @@ -966,7 +966,7 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; TWBR = ((CPU_FREQ / TWI_FREQ) - 16) / 2; // bitrate register // enable twi module, acks, and twi interrupt - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA); + TWCR = (1 << TWEN) | (1 << TWIE) | (1 << TWEA); /* TWEN - TWI Enable Bit TWIE - TWI Interrupt Enable @@ -1035,7 +1035,7 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; } void twii_SetStart() { - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTA); + TWCR = (1 << TWEN) | (1 << TWIE) | (1 << TWEA) | (1 << TWINT) | (1 << TWSTA); } void twi_write01() { @@ -1118,19 +1118,19 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; void twi_reply(uint8_t ack) { // transmit master read ready signal, with or without ack if (ack){ - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT) | _BV(TWEA); + TWCR = (1 << TWEN) | (1 << TWIE) | (1 << TWINT) | (1 << TWEA); } else { - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT); + TWCR = (1 << TWEN) | (1 << TWIE) | (1 << TWINT); } } void twi_stop(void) { // send stop condition - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTO); + TWCR = (1 << TWEN) | (1 << TWIE) | (1 << TWEA) | (1 << TWINT) | (1 << TWSTO); // wait for stop condition to be exectued on bus // TWINT is not set after a stop condition! - while (TWCR & _BV(TWSTO)) { + while (TWCR & (1 << TWSTO)) { continue; } @@ -1140,7 +1140,7 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; void twi_releaseBus(void) { // release bus - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT); + TWCR = (1 << TWEN) | (1 << TWIE) | (1 << TWEA) | (1 << TWINT); // update twi state twi_state = TWI_READY; diff --git a/MSP430/I2Cdev/I2Cdev.h b/MSP430/I2Cdev/I2Cdev.h index daf01322..c3a32a08 100644 --- a/MSP430/I2Cdev/I2Cdev.h +++ b/MSP430/I2Cdev/I2Cdev.h @@ -213,7 +213,7 @@ class I2Cdev { /* TWI Status is in TWSR, in the top 5 bits: TWS7 - TWS3 */ - #define TW_STATUS_MASK (_BV(TWS7)|_BV(TWS6)|_BV(TWS5)|_BV(TWS4)|_BV(TWS3)) + #define TW_STATUS_MASK ((1 << TWS7)|(1 << TWS6)|(1 << TWS5)|(1 << TWS4)|(1 << TWS3)) #define TW_STATUS (TWSR & TW_STATUS_MASK) #define TW_START 0x08 #define TW_REP_START 0x10 @@ -248,11 +248,11 @@ class I2Cdev { //#define _SFR_BYTE(sfr) _MMIO_BYTE(_SFR_ADDR(sfr)) #ifndef sbi // set bit - #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) + #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= (1 << bit)) #endif // sbi #ifndef cbi // clear bit - #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) + #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~(1 << bit)) #endif // cbi extern TwoWire Wire; From 322103972b5e00f4309334ab24d002f5cdcedc83 Mon Sep 17 00:00:00 2001 From: Jeff Rowberg Date: Mon, 20 Sep 2021 22:09:27 -0400 Subject: [PATCH 266/335] Fix inline multiplication overflow warning --- Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h index 5de85c92..db0b3cf8 100644 --- a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h +++ b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h @@ -521,7 +521,7 @@ uint8_t MPU6050::dmpGetGravity(int16_t *data, const uint8_t* packet) { data[0] = ((int32_t)qI[1] * qI[3] - (int32_t)qI[0] * qI[2]) / 16384; data[1] = ((int32_t)qI[0] * qI[1] + (int32_t)qI[2] * qI[3]) / 16384; data[2] = ((int32_t)qI[0] * qI[0] - (int32_t)qI[1] * qI[1] - - (int32_t)qI[2] * qI[2] + (int32_t)qI[3] * qI[3]) / (2 * 16384); + - (int32_t)qI[2] * qI[2] + (int32_t)qI[3] * qI[3]) / (int32_t)(2 * 16384); return status; } From 660971dcf9f5170326fa9f09a7cee1b3d8c3c81d Mon Sep 17 00:00:00 2001 From: Jeff Rowberg Date: Mon, 20 Sep 2021 22:09:45 -0400 Subject: [PATCH 267/335] Fix unused parameter warnings --- Arduino/MPU6050/MPU6050.cpp | 4 ++++ Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h | 1 + Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h | 1 + 3 files changed, 6 insertions(+) diff --git a/Arduino/MPU6050/MPU6050.cpp b/Arduino/MPU6050/MPU6050.cpp index f3e2660f..d0e330d4 100644 --- a/Arduino/MPU6050/MPU6050.cpp +++ b/Arduino/MPU6050/MPU6050.cpp @@ -1767,6 +1767,10 @@ bool MPU6050::getIntDataReadyStatus() { * @see MPU6050_RA_ACCEL_XOUT_H */ void MPU6050::getMotion9(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz, int16_t* mx, int16_t* my, int16_t* mz) { + (void)mx; // unused parameter + (void)my; // unused parameter + (void)mz; // unused parameter + getMotion6(ax, ay, az, gx, gy, gz); // TODO: magnetometer integration } diff --git a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h index db0b3cf8..9cf54c66 100644 --- a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h +++ b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h @@ -576,6 +576,7 @@ uint8_t MPU6050::dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gra // uint8_t MPU6050::dmpGetQuaternionFloat(float *data, const uint8_t* packet); uint8_t MPU6050::dmpProcessFIFOPacket(const unsigned char *dmpData) { + (void)dmpData; // unused parameter /*for (uint8_t k = 0; k < dmpPacketSize; k++) { if (dmpData[k] < 0x10) Serial.print("0"); Serial.print(dmpData[k], HEX); diff --git a/Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h b/Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h index b08516e1..6f069f82 100644 --- a/Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h +++ b/Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h @@ -576,6 +576,7 @@ uint8_t MPU6050::dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gra // uint8_t MPU6050::dmpGetQuaternionFloat(float *data, const uint8_t* packet); uint8_t MPU6050::dmpProcessFIFOPacket(const unsigned char *dmpData) { + (void)dmpData; // unused parameter /*for (uint8_t k = 0; k < dmpPacketSize; k++) { if (dmpData[k] < 0x10) Serial.print("0"); Serial.print(dmpData[k], HEX); From 9c63fa20b495eceb09b695a646f2a183c063ecb8 Mon Sep 17 00:00:00 2001 From: Jeff Rowberg Date: Mon, 20 Sep 2021 22:10:12 -0400 Subject: [PATCH 268/335] Eliminate dependency on dtostrf() function --- Arduino/MPU6050/MPU6050.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/Arduino/MPU6050/MPU6050.cpp b/Arduino/MPU6050/MPU6050.cpp index d0e330d4..0d5acbc1 100644 --- a/Arduino/MPU6050/MPU6050.cpp +++ b/Arduino/MPU6050/MPU6050.cpp @@ -3350,13 +3350,12 @@ void MPU6050::PID(uint8_t ReadAddress, float kP,float kI, uint8_t Loops){ resetDMP(); } -#define printfloatx(Name,Variable,Spaces,Precision,EndTxt) { Serial.print(F(Name)); {char S[(Spaces + Precision + 3)];Serial.print(F(" ")); Serial.print(dtostrf((float)Variable,Spaces,Precision ,S));}Serial.print(F(EndTxt)); }//Name,Variable,Spaces,Precision,EndTxt void MPU6050::PrintActiveOffsets() { uint8_t AOffsetRegister = (getDeviceID() < 0x38 )? MPU6050_RA_XA_OFFS_H:0x77; int16_t Data[3]; //Serial.print(F("Offset Register 0x")); //Serial.print(AOffsetRegister>>4,HEX);Serial.print(AOffsetRegister&0x0F,HEX); - Serial.print(F("\n// X Accel Y Accel Z Accel X Gyro Y Gyro Z Gyro\n//OFFSETS ")); + Serial.print(F("\n// X Accel Y Accel Z Accel X Gyro Y Gyro Z Gyro\n// OFFSETS ")); if(AOffsetRegister == 0x06) I2Cdev::readWords(devAddr, AOffsetRegister, 3, (uint16_t *)Data); else { I2Cdev::readWords(devAddr, AOffsetRegister, 1, (uint16_t *)Data); @@ -3364,12 +3363,12 @@ void MPU6050::PrintActiveOffsets() { I2Cdev::readWords(devAddr, AOffsetRegister+6, 1, (uint16_t *)Data+2); } // A_OFFSET_H_READ_A_OFFS(Data); - printfloatx("", Data[0], 5, 0, ", "); - printfloatx("", Data[1], 5, 0, ", "); - printfloatx("", Data[2], 5, 0, ", "); + Serial.print((float)Data[0], 5); Serial.print(", "); + Serial.print((float)Data[1], 5); Serial.print(", "); + Serial.print((float)Data[2], 5); Serial.print(", "); I2Cdev::readWords(devAddr, 0x13, 3, (uint16_t *)Data); // XG_OFFSET_H_READ_OFFS_USR(Data); - printfloatx("", Data[0], 5, 0, ", "); - printfloatx("", Data[1], 5, 0, ", "); - printfloatx("", Data[2], 5, 0, "\n"); + Serial.print((float)Data[0], 5); Serial.print(", "); + Serial.print((float)Data[1], 5); Serial.print(", "); + Serial.print((float)Data[2], 5); Serial.print("\n"); } From 4f057f582f92530b3b98dcd3723c543ae4f944e9 Mon Sep 17 00:00:00 2001 From: Jeff Rowberg Date: Tue, 21 Sep 2021 11:07:23 -0400 Subject: [PATCH 269/335] Allow external definition of I2C buffer length --- Arduino/I2Cdev/I2Cdev.h | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/Arduino/I2Cdev/I2Cdev.h b/Arduino/I2Cdev/I2Cdev.h index bc1a9cca..ef290e01 100644 --- a/Arduino/I2Cdev/I2Cdev.h +++ b/Arduino/I2Cdev/I2Cdev.h @@ -103,18 +103,20 @@ THE SOFTWARE. #define ARDUINO 101 #endif -#if defined(I2C_BUFFER_LENGTH) - // Arduino ESP32 core Wire uses this - #define I2CDEVLIB_WIRE_BUFFER_LENGTH I2C_BUFFER_LENGTH -#elif defined(BUFFER_LENGTH) - // Arduino AVR core Wire and many others use this - #define I2CDEVLIB_WIRE_BUFFER_LENGTH BUFFER_LENGTH -#elif defined(SERIAL_BUFFER_SIZE) - // Arduino SAMD core Wire uses this - #define I2CDEVLIB_WIRE_BUFFER_LENGTH SERIAL_BUFFER_SIZE -#else - // should be a safe fallback, though possibly inefficient - #define I2CDEVLIB_WIRE_BUFFER_LENGTH 32 +#ifndef I2CDEVLIB_WIRE_BUFFER_LENGTH + #if defined(I2C_BUFFER_LENGTH) + // Arduino ESP32 core Wire uses this + #define I2CDEVLIB_WIRE_BUFFER_LENGTH I2C_BUFFER_LENGTH + #elif defined(BUFFER_LENGTH) + // Arduino AVR core Wire and many others use this + #define I2CDEVLIB_WIRE_BUFFER_LENGTH BUFFER_LENGTH + #elif defined(SERIAL_BUFFER_SIZE) + // Arduino SAMD core Wire uses this + #define I2CDEVLIB_WIRE_BUFFER_LENGTH SERIAL_BUFFER_SIZE + #else + // should be a safe fallback, though possibly inefficient + #define I2CDEVLIB_WIRE_BUFFER_LENGTH 32 + #endif #endif // 1000ms default read timeout (modify with "I2Cdev::readTimeout = [ms];") From 955f0b3c093ce511649738212aa80d097875be92 Mon Sep 17 00:00:00 2001 From: Jeff Rowberg Date: Thu, 23 Sep 2021 07:36:14 -0400 Subject: [PATCH 270/335] Fix corner case infinite loop with large buffer length --- Arduino/I2Cdev/I2Cdev.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Arduino/I2Cdev/I2Cdev.cpp b/Arduino/I2Cdev/I2Cdev.cpp index c0b1670e..365edd51 100644 --- a/Arduino/I2Cdev/I2Cdev.cpp +++ b/Arduino/I2Cdev/I2Cdev.cpp @@ -225,12 +225,12 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 // I2C/TWI subsystem uses internal buffer that breaks with large data requests // so if user requests more than I2CDEVLIB_WIRE_BUFFER_LENGTH bytes, we have to do it in // smaller chunks instead of all at once - for (uint8_t k = 0; k < length; k += min((int)length, I2CDEVLIB_WIRE_BUFFER_LENGTH)) { + for (int k = 0; k < length; k += min((int)length, I2CDEVLIB_WIRE_BUFFER_LENGTH)) { Wire.beginTransmission(devAddr); Wire.send(regAddr); Wire.endTransmission(); Wire.beginTransmission(devAddr); - Wire.requestFrom(devAddr, (uint8_t)min(length - k, I2CDEVLIB_WIRE_BUFFER_LENGTH)); + Wire.requestFrom(devAddr, (int)min(length - k, I2CDEVLIB_WIRE_BUFFER_LENGTH)); for (; Wire.available() && (timeout == 0 || millis() - t1 < timeout); count++) { data[count] = Wire.receive(); @@ -249,12 +249,12 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 // I2C/TWI subsystem uses internal buffer that breaks with large data requests // so if user requests more than I2CDEVLIB_WIRE_BUFFER_LENGTH bytes, we have to do it in // smaller chunks instead of all at once - for (uint8_t k = 0; k < length; k += min((int)length, I2CDEVLIB_WIRE_BUFFER_LENGTH)) { + for (int k = 0; k < length; k += min((int)length, I2CDEVLIB_WIRE_BUFFER_LENGTH)) { Wire.beginTransmission(devAddr); Wire.write(regAddr); Wire.endTransmission(); Wire.beginTransmission(devAddr); - Wire.requestFrom(devAddr, (uint8_t)min(length - k, I2CDEVLIB_WIRE_BUFFER_LENGTH)); + Wire.requestFrom(devAddr, (int)min(length - k, I2CDEVLIB_WIRE_BUFFER_LENGTH)); for (; Wire.available() && (timeout == 0 || millis() - t1 < timeout); count++) { data[count] = Wire.read(); @@ -273,12 +273,12 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 // I2C/TWI subsystem uses internal buffer that breaks with large data requests // so if user requests more than I2CDEVLIB_WIRE_BUFFER_LENGTH bytes, we have to do it in // smaller chunks instead of all at once - for (uint8_t k = 0; k < length; k += min((int)length, I2CDEVLIB_WIRE_BUFFER_LENGTH)) { + for (int k = 0; k < length; k += min((int)length, I2CDEVLIB_WIRE_BUFFER_LENGTH)) { Wire.beginTransmission(devAddr); Wire.write(regAddr); Wire.endTransmission(); Wire.beginTransmission(devAddr); - Wire.requestFrom(devAddr, (uint8_t)min(length - k, I2CDEVLIB_WIRE_BUFFER_LENGTH)); + Wire.requestFrom(devAddr, (int)min(length - k, I2CDEVLIB_WIRE_BUFFER_LENGTH)); for (; Wire.available() && (timeout == 0 || millis() - t1 < timeout); count++) { data[count] = Wire.read(); From 84fa895446d35f7a0908fe2f3a5f91502657e817 Mon Sep 17 00:00:00 2001 From: Jeff Rowberg Date: Thu, 23 Sep 2021 07:43:45 -0400 Subject: [PATCH 271/335] Remove hard-coded slave address from DMP 4.1 init --- Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h | 32 ++++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h b/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h index 3e2608b7..94d2f559 100644 --- a/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h +++ b/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h @@ -502,10 +502,10 @@ uint8_t MPU6050::dmpInitialize() { writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); DEBUG_PRINTLN(F("Disabling all standby flags...")); - I2Cdev::writeByte(0x68, MPU6050_RA_PWR_MGMT_2, 0x00); + I2Cdev::writeByte(devAddr, MPU6050_RA_PWR_MGMT_2, 0x00); DEBUG_PRINTLN(F("Setting accelerometer sensitivity to +/- 2g...")); - I2Cdev::writeByte(0x68, MPU6050_RA_ACCEL_CONFIG, 0x00); + I2Cdev::writeByte(devAddr, MPU6050_RA_ACCEL_CONFIG, 0x00); DEBUG_PRINTLN(F("Setting motion detection threshold to 2...")); setMotionDetectionThreshold(2); @@ -525,35 +525,35 @@ uint8_t MPU6050::dmpInitialize() { // setup AK8975 (0x0E) as Slave 0 in read mode DEBUG_PRINTLN(F("Setting up AK8975 read slave 0...")); - I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV0_ADDR, 0x8E); - I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV0_REG, 0x01); - I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV0_CTRL, 0xDA); + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV0_ADDR, 0x8E); + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV0_REG, 0x01); + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV0_CTRL, 0xDA); // setup AK8975 (0x0E) as Slave 2 in write mode DEBUG_PRINTLN(F("Setting up AK8975 write slave 2...")); - I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV2_ADDR, 0x0E); - I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV2_REG, 0x0A); - I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV2_CTRL, 0x81); - I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV2_DO, 0x01); + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV2_ADDR, 0x0E); + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV2_REG, 0x0A); + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV2_CTRL, 0x81); + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV2_DO, 0x01); // setup I2C timing/delay control DEBUG_PRINTLN(F("Setting up slave access delay...")); - I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV4_CTRL, 0x18); - I2Cdev::writeByte(0x68, MPU6050_RA_I2C_MST_DELAY_CTRL, 0x05); + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV4_CTRL, 0x18); + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, 0x05); // enable interrupts DEBUG_PRINTLN(F("Enabling default interrupt behavior/no bypass...")); - I2Cdev::writeByte(0x68, MPU6050_RA_INT_PIN_CFG, 0x00); + I2Cdev::writeByte(devAddr, MPU6050_RA_INT_PIN_CFG, 0x00); // enable I2C master mode and reset DMP/FIFO DEBUG_PRINTLN(F("Enabling I2C master mode...")); - I2Cdev::writeByte(0x68, MPU6050_RA_USER_CTRL, 0x20); + I2Cdev::writeByte(devAddr, MPU6050_RA_USER_CTRL, 0x20); DEBUG_PRINTLN(F("Resetting FIFO...")); - I2Cdev::writeByte(0x68, MPU6050_RA_USER_CTRL, 0x24); + I2Cdev::writeByte(devAddr, MPU6050_RA_USER_CTRL, 0x24); DEBUG_PRINTLN(F("Rewriting I2C master mode enabled because...I don't know")); - I2Cdev::writeByte(0x68, MPU6050_RA_USER_CTRL, 0x20); + I2Cdev::writeByte(devAddr, MPU6050_RA_USER_CTRL, 0x20); DEBUG_PRINTLN(F("Enabling and resetting DMP/FIFO...")); - I2Cdev::writeByte(0x68, MPU6050_RA_USER_CTRL, 0xE8); + I2Cdev::writeByte(devAddr, MPU6050_RA_USER_CTRL, 0xE8); DEBUG_PRINTLN(F("Writing final memory update 5/19 (function unknown)...")); for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); From 02dcdb166f04b5f7f449501a45f6a59c2b681f82 Mon Sep 17 00:00:00 2001 From: Jeff Rowberg Date: Thu, 23 Sep 2021 08:05:38 -0400 Subject: [PATCH 272/335] Correct AFS_SEL scale in comments --- Arduino/MPU6050/MPU6050.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Arduino/MPU6050/MPU6050.cpp b/Arduino/MPU6050/MPU6050.cpp index 0d5acbc1..02fe3f8f 100644 --- a/Arduino/MPU6050/MPU6050.cpp +++ b/Arduino/MPU6050/MPU6050.cpp @@ -1820,10 +1820,10 @@ void MPU6050::getMotion6(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int *

  * AFS_SEL | Full Scale Range | LSB Sensitivity
  * --------+------------------+----------------
- * 0       | +/- 2g           | 8192 LSB/mg
- * 1       | +/- 4g           | 4096 LSB/mg
- * 2       | +/- 8g           | 2048 LSB/mg
- * 3       | +/- 16g          | 1024 LSB/mg
+ * 0       | +/- 2g           | 16384 LSB/mg
+ * 1       | +/- 4g           | 8192 LSB/mg
+ * 2       | +/- 8g           | 4096 LSB/mg
+ * 3       | +/- 16g          | 2048 LSB/mg
  * 
* * @param x 16-bit signed integer container for X-axis acceleration From 99ec465f35192940cab5376317e37fe7338a642f Mon Sep 17 00:00:00 2001 From: Jeff Rowberg Date: Mon, 27 Sep 2021 21:49:25 -0400 Subject: [PATCH 273/335] Prevent uninitialized variable compiler warning --- Arduino/MPU6050/MPU6050.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Arduino/MPU6050/MPU6050.cpp b/Arduino/MPU6050/MPU6050.cpp index 3d9f523e..07df9ccd 100644 --- a/Arduino/MPU6050/MPU6050.cpp +++ b/Arduino/MPU6050/MPU6050.cpp @@ -3316,7 +3316,7 @@ void MPU6050::PID(uint8_t ReadAddress, float kP,float kI, uint8_t Loops){ float Error, PTerm, ITerm[3]; int16_t eSample; uint32_t eSum; - uint16_t gravity; + uint16_t gravity = 8192; // prevent uninitialized compiler warning if (ReadAddress == 0x3B) gravity = 16384 >> getFullScaleAccelRange(); Serial.write('>'); for (int i = 0; i < 3; i++) { From 78ba827377d8309c9d3421530a1177dcd5d9400d Mon Sep 17 00:00:00 2001 From: Jeff Rowberg Date: Mon, 27 Sep 2021 21:58:30 -0400 Subject: [PATCH 274/335] Change main MPU6050 class to MPU6050_Base class --- Arduino/MPU6050/MPU6050.cpp | 549 ++++++++++++++++++------------------ Arduino/MPU6050/MPU6050.h | 8 +- 2 files changed, 278 insertions(+), 279 deletions(-) diff --git a/Arduino/MPU6050/MPU6050.cpp b/Arduino/MPU6050/MPU6050.cpp index 07df9ccd..c3212efa 100644 --- a/Arduino/MPU6050/MPU6050.cpp +++ b/Arduino/MPU6050/MPU6050.cpp @@ -4,6 +4,7 @@ // Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib // // Changelog: +// 2021-09-27 - split implementations out of header files, finally // 2019-07-08 - Added Auto Calibration routine // ... - ongoing debug release @@ -43,7 +44,7 @@ THE SOFTWARE. * @see MPU6050_ADDRESS_AD0_LOW * @see MPU6050_ADDRESS_AD0_HIGH */ -MPU6050::MPU6050(uint8_t address):devAddr(address) { +MPU6050_Base::MPU6050_Base(uint8_t address):devAddr(address) { } /** Power on and prepare for general usage. @@ -53,7 +54,7 @@ MPU6050::MPU6050(uint8_t address):devAddr(address) { * the clock source to use the X Gyro for reference, which is slightly better than * the default internal clock source. */ -void MPU6050::initialize() { +void MPU6050_Base::initialize() { setClockSource(MPU6050_CLOCK_PLL_XGYRO); setFullScaleGyroRange(MPU6050_GYRO_FS_250); setFullScaleAccelRange(MPU6050_ACCEL_FS_2); @@ -64,7 +65,7 @@ void MPU6050::initialize() { * Make sure the device is connected and responds as expected. * @return True if connection is valid, false otherwise */ -bool MPU6050::testConnection() { +bool MPU6050_Base::testConnection() { return getDeviceID() == 0x34; } @@ -76,7 +77,7 @@ bool MPU6050::testConnection() { * the MPU-6000, which does not have a VLOGIC pin. * @return I2C supply voltage level (0=VLOGIC, 1=VDD) */ -uint8_t MPU6050::getAuxVDDIOLevel() { +uint8_t MPU6050_Base::getAuxVDDIOLevel() { I2Cdev::readBit(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_PWR_MODE_BIT, buffer); return buffer[0]; } @@ -86,7 +87,7 @@ uint8_t MPU6050::getAuxVDDIOLevel() { * the MPU-6000, which does not have a VLOGIC pin. * @param level I2C supply voltage level (0=VLOGIC, 1=VDD) */ -void MPU6050::setAuxVDDIOLevel(uint8_t level) { +void MPU6050_Base::setAuxVDDIOLevel(uint8_t level) { I2Cdev::writeBit(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_PWR_MODE_BIT, level); } @@ -113,7 +114,7 @@ void MPU6050::setAuxVDDIOLevel(uint8_t level) { * @return Current sample rate * @see MPU6050_RA_SMPLRT_DIV */ -uint8_t MPU6050::getRate() { +uint8_t MPU6050_Base::getRate() { I2Cdev::readByte(devAddr, MPU6050_RA_SMPLRT_DIV, buffer); return buffer[0]; } @@ -122,7 +123,7 @@ uint8_t MPU6050::getRate() { * @see getRate() * @see MPU6050_RA_SMPLRT_DIV */ -void MPU6050::setRate(uint8_t rate) { +void MPU6050_Base::setRate(uint8_t rate) { I2Cdev::writeByte(devAddr, MPU6050_RA_SMPLRT_DIV, rate); } @@ -155,7 +156,7 @@ void MPU6050::setRate(uint8_t rate) { * * @return FSYNC configuration value */ -uint8_t MPU6050::getExternalFrameSync() { +uint8_t MPU6050_Base::getExternalFrameSync() { I2Cdev::readBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_EXT_SYNC_SET_BIT, MPU6050_CFG_EXT_SYNC_SET_LENGTH, buffer); return buffer[0]; } @@ -164,7 +165,7 @@ uint8_t MPU6050::getExternalFrameSync() { * @see MPU6050_RA_CONFIG * @param sync New FSYNC configuration value */ -void MPU6050::setExternalFrameSync(uint8_t sync) { +void MPU6050_Base::setExternalFrameSync(uint8_t sync) { I2Cdev::writeBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_EXT_SYNC_SET_BIT, MPU6050_CFG_EXT_SYNC_SET_LENGTH, sync); } /** Get digital low-pass filter configuration. @@ -195,7 +196,7 @@ void MPU6050::setExternalFrameSync(uint8_t sync) { * @see MPU6050_CFG_DLPF_CFG_BIT * @see MPU6050_CFG_DLPF_CFG_LENGTH */ -uint8_t MPU6050::getDLPFMode() { +uint8_t MPU6050_Base::getDLPFMode() { I2Cdev::readBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_DLPF_CFG_BIT, MPU6050_CFG_DLPF_CFG_LENGTH, buffer); return buffer[0]; } @@ -207,7 +208,7 @@ uint8_t MPU6050::getDLPFMode() { * @see MPU6050_CFG_DLPF_CFG_BIT * @see MPU6050_CFG_DLPF_CFG_LENGTH */ -void MPU6050::setDLPFMode(uint8_t mode) { +void MPU6050_Base::setDLPFMode(uint8_t mode) { I2Cdev::writeBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_DLPF_CFG_BIT, MPU6050_CFG_DLPF_CFG_LENGTH, mode); } @@ -230,7 +231,7 @@ void MPU6050::setDLPFMode(uint8_t mode) { * @see MPU6050_GCONFIG_FS_SEL_BIT * @see MPU6050_GCONFIG_FS_SEL_LENGTH */ -uint8_t MPU6050::getFullScaleGyroRange() { +uint8_t MPU6050_Base::getFullScaleGyroRange() { I2Cdev::readBits(devAddr, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, buffer); return buffer[0]; } @@ -242,7 +243,7 @@ uint8_t MPU6050::getFullScaleGyroRange() { * @see MPU6050_GCONFIG_FS_SEL_BIT * @see MPU6050_GCONFIG_FS_SEL_LENGTH */ -void MPU6050::setFullScaleGyroRange(uint8_t range) { +void MPU6050_Base::setFullScaleGyroRange(uint8_t range) { I2Cdev::writeBits(devAddr, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, range); } @@ -252,7 +253,7 @@ void MPU6050::setFullScaleGyroRange(uint8_t range) { * @return factory trim value * @see MPU6050_RA_SELF_TEST_X */ -uint8_t MPU6050::getAccelXSelfTestFactoryTrim() { +uint8_t MPU6050_Base::getAccelXSelfTestFactoryTrim() { I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_X, &buffer[0]); I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_A, &buffer[1]); return (buffer[0]>>3) | ((buffer[1]>>4) & 0x03); @@ -262,7 +263,7 @@ uint8_t MPU6050::getAccelXSelfTestFactoryTrim() { * @return factory trim value * @see MPU6050_RA_SELF_TEST_Y */ -uint8_t MPU6050::getAccelYSelfTestFactoryTrim() { +uint8_t MPU6050_Base::getAccelYSelfTestFactoryTrim() { I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_Y, &buffer[0]); I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_A, &buffer[1]); return (buffer[0]>>3) | ((buffer[1]>>2) & 0x03); @@ -272,7 +273,7 @@ uint8_t MPU6050::getAccelYSelfTestFactoryTrim() { * @return factory trim value * @see MPU6050_RA_SELF_TEST_Z */ -uint8_t MPU6050::getAccelZSelfTestFactoryTrim() { +uint8_t MPU6050_Base::getAccelZSelfTestFactoryTrim() { I2Cdev::readBytes(devAddr, MPU6050_RA_SELF_TEST_Z, 2, buffer); return (buffer[0]>>3) | (buffer[1] & 0x03); } @@ -281,7 +282,7 @@ uint8_t MPU6050::getAccelZSelfTestFactoryTrim() { * @return factory trim value * @see MPU6050_RA_SELF_TEST_X */ -uint8_t MPU6050::getGyroXSelfTestFactoryTrim() { +uint8_t MPU6050_Base::getGyroXSelfTestFactoryTrim() { I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_X, buffer); return (buffer[0] & 0x1F); } @@ -290,7 +291,7 @@ uint8_t MPU6050::getGyroXSelfTestFactoryTrim() { * @return factory trim value * @see MPU6050_RA_SELF_TEST_Y */ -uint8_t MPU6050::getGyroYSelfTestFactoryTrim() { +uint8_t MPU6050_Base::getGyroYSelfTestFactoryTrim() { I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_Y, buffer); return (buffer[0] & 0x1F); } @@ -299,7 +300,7 @@ uint8_t MPU6050::getGyroYSelfTestFactoryTrim() { * @return factory trim value * @see MPU6050_RA_SELF_TEST_Z */ -uint8_t MPU6050::getGyroZSelfTestFactoryTrim() { +uint8_t MPU6050_Base::getGyroZSelfTestFactoryTrim() { I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_Z, buffer); return (buffer[0] & 0x1F); } @@ -310,7 +311,7 @@ uint8_t MPU6050::getGyroZSelfTestFactoryTrim() { * @return Self-test enabled value * @see MPU6050_RA_ACCEL_CONFIG */ -bool MPU6050::getAccelXSelfTest() { +bool MPU6050_Base::getAccelXSelfTest() { I2Cdev::readBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_XA_ST_BIT, buffer); return buffer[0]; } @@ -318,14 +319,14 @@ bool MPU6050::getAccelXSelfTest() { * @param enabled Self-test enabled value * @see MPU6050_RA_ACCEL_CONFIG */ -void MPU6050::setAccelXSelfTest(bool enabled) { +void MPU6050_Base::setAccelXSelfTest(bool enabled) { I2Cdev::writeBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_XA_ST_BIT, enabled); } /** Get self-test enabled value for accelerometer Y axis. * @return Self-test enabled value * @see MPU6050_RA_ACCEL_CONFIG */ -bool MPU6050::getAccelYSelfTest() { +bool MPU6050_Base::getAccelYSelfTest() { I2Cdev::readBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_YA_ST_BIT, buffer); return buffer[0]; } @@ -333,14 +334,14 @@ bool MPU6050::getAccelYSelfTest() { * @param enabled Self-test enabled value * @see MPU6050_RA_ACCEL_CONFIG */ -void MPU6050::setAccelYSelfTest(bool enabled) { +void MPU6050_Base::setAccelYSelfTest(bool enabled) { I2Cdev::writeBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_YA_ST_BIT, enabled); } /** Get self-test enabled value for accelerometer Z axis. * @return Self-test enabled value * @see MPU6050_RA_ACCEL_CONFIG */ -bool MPU6050::getAccelZSelfTest() { +bool MPU6050_Base::getAccelZSelfTest() { I2Cdev::readBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ZA_ST_BIT, buffer); return buffer[0]; } @@ -348,7 +349,7 @@ bool MPU6050::getAccelZSelfTest() { * @param enabled Self-test enabled value * @see MPU6050_RA_ACCEL_CONFIG */ -void MPU6050::setAccelZSelfTest(bool enabled) { +void MPU6050_Base::setAccelZSelfTest(bool enabled) { I2Cdev::writeBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ZA_ST_BIT, enabled); } /** Get full-scale accelerometer range. @@ -368,7 +369,7 @@ void MPU6050::setAccelZSelfTest(bool enabled) { * @see MPU6050_ACONFIG_AFS_SEL_BIT * @see MPU6050_ACONFIG_AFS_SEL_LENGTH */ -uint8_t MPU6050::getFullScaleAccelRange() { +uint8_t MPU6050_Base::getFullScaleAccelRange() { I2Cdev::readBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, buffer); return buffer[0]; } @@ -376,7 +377,7 @@ uint8_t MPU6050::getFullScaleAccelRange() { * @param range New full-scale accelerometer range setting * @see getFullScaleAccelRange() */ -void MPU6050::setFullScaleAccelRange(uint8_t range) { +void MPU6050_Base::setFullScaleAccelRange(uint8_t range) { I2Cdev::writeBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, range); } /** Get the high-pass filter configuration. @@ -414,7 +415,7 @@ void MPU6050::setFullScaleAccelRange(uint8_t range) { * @see MPU6050_DHPF_RESET * @see MPU6050_RA_ACCEL_CONFIG */ -uint8_t MPU6050::getDHPFMode() { +uint8_t MPU6050_Base::getDHPFMode() { I2Cdev::readBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ACCEL_HPF_BIT, MPU6050_ACONFIG_ACCEL_HPF_LENGTH, buffer); return buffer[0]; } @@ -424,7 +425,7 @@ uint8_t MPU6050::getDHPFMode() { * @see MPU6050_DHPF_RESET * @see MPU6050_RA_ACCEL_CONFIG */ -void MPU6050::setDHPFMode(uint8_t bandwidth) { +void MPU6050_Base::setDHPFMode(uint8_t bandwidth) { I2Cdev::writeBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ACCEL_HPF_BIT, MPU6050_ACONFIG_ACCEL_HPF_LENGTH, bandwidth); } @@ -445,7 +446,7 @@ void MPU6050::setDHPFMode(uint8_t bandwidth) { * @return Current free-fall acceleration threshold value (LSB = 2mg) * @see MPU6050_RA_FF_THR */ -uint8_t MPU6050::getFreefallDetectionThreshold() { +uint8_t MPU6050_Base::getFreefallDetectionThreshold() { I2Cdev::readByte(devAddr, MPU6050_RA_FF_THR, buffer); return buffer[0]; } @@ -454,7 +455,7 @@ uint8_t MPU6050::getFreefallDetectionThreshold() { * @see getFreefallDetectionThreshold() * @see MPU6050_RA_FF_THR */ -void MPU6050::setFreefallDetectionThreshold(uint8_t threshold) { +void MPU6050_Base::setFreefallDetectionThreshold(uint8_t threshold) { I2Cdev::writeByte(devAddr, MPU6050_RA_FF_THR, threshold); } @@ -477,7 +478,7 @@ void MPU6050::setFreefallDetectionThreshold(uint8_t threshold) { * @return Current free-fall duration threshold value (LSB = 1ms) * @see MPU6050_RA_FF_DUR */ -uint8_t MPU6050::getFreefallDetectionDuration() { +uint8_t MPU6050_Base::getFreefallDetectionDuration() { I2Cdev::readByte(devAddr, MPU6050_RA_FF_DUR, buffer); return buffer[0]; } @@ -486,7 +487,7 @@ uint8_t MPU6050::getFreefallDetectionDuration() { * @see getFreefallDetectionDuration() * @see MPU6050_RA_FF_DUR */ -void MPU6050::setFreefallDetectionDuration(uint8_t duration) { +void MPU6050_Base::setFreefallDetectionDuration(uint8_t duration) { I2Cdev::writeByte(devAddr, MPU6050_RA_FF_DUR, duration); } @@ -511,7 +512,7 @@ void MPU6050::setFreefallDetectionDuration(uint8_t duration) { * @return Current motion detection acceleration threshold value (LSB = 2mg) * @see MPU6050_RA_MOT_THR */ -uint8_t MPU6050::getMotionDetectionThreshold() { +uint8_t MPU6050_Base::getMotionDetectionThreshold() { I2Cdev::readByte(devAddr, MPU6050_RA_MOT_THR, buffer); return buffer[0]; } @@ -520,7 +521,7 @@ uint8_t MPU6050::getMotionDetectionThreshold() { * @see getMotionDetectionThreshold() * @see MPU6050_RA_MOT_THR */ -void MPU6050::setMotionDetectionThreshold(uint8_t threshold) { +void MPU6050_Base::setMotionDetectionThreshold(uint8_t threshold) { I2Cdev::writeByte(devAddr, MPU6050_RA_MOT_THR, threshold); } @@ -541,7 +542,7 @@ void MPU6050::setMotionDetectionThreshold(uint8_t threshold) { * @return Current motion detection duration threshold value (LSB = 1ms) * @see MPU6050_RA_MOT_DUR */ -uint8_t MPU6050::getMotionDetectionDuration() { +uint8_t MPU6050_Base::getMotionDetectionDuration() { I2Cdev::readByte(devAddr, MPU6050_RA_MOT_DUR, buffer); return buffer[0]; } @@ -550,7 +551,7 @@ uint8_t MPU6050::getMotionDetectionDuration() { * @see getMotionDetectionDuration() * @see MPU6050_RA_MOT_DUR */ -void MPU6050::setMotionDetectionDuration(uint8_t duration) { +void MPU6050_Base::setMotionDetectionDuration(uint8_t duration) { I2Cdev::writeByte(devAddr, MPU6050_RA_MOT_DUR, duration); } @@ -581,7 +582,7 @@ void MPU6050::setMotionDetectionDuration(uint8_t duration) { * @return Current zero motion detection acceleration threshold value (LSB = 2mg) * @see MPU6050_RA_ZRMOT_THR */ -uint8_t MPU6050::getZeroMotionDetectionThreshold() { +uint8_t MPU6050_Base::getZeroMotionDetectionThreshold() { I2Cdev::readByte(devAddr, MPU6050_RA_ZRMOT_THR, buffer); return buffer[0]; } @@ -590,7 +591,7 @@ uint8_t MPU6050::getZeroMotionDetectionThreshold() { * @see getZeroMotionDetectionThreshold() * @see MPU6050_RA_ZRMOT_THR */ -void MPU6050::setZeroMotionDetectionThreshold(uint8_t threshold) { +void MPU6050_Base::setZeroMotionDetectionThreshold(uint8_t threshold) { I2Cdev::writeByte(devAddr, MPU6050_RA_ZRMOT_THR, threshold); } @@ -612,7 +613,7 @@ void MPU6050::setZeroMotionDetectionThreshold(uint8_t threshold) { * @return Current zero motion detection duration threshold value (LSB = 64ms) * @see MPU6050_RA_ZRMOT_DUR */ -uint8_t MPU6050::getZeroMotionDetectionDuration() { +uint8_t MPU6050_Base::getZeroMotionDetectionDuration() { I2Cdev::readByte(devAddr, MPU6050_RA_ZRMOT_DUR, buffer); return buffer[0]; } @@ -621,7 +622,7 @@ uint8_t MPU6050::getZeroMotionDetectionDuration() { * @see getZeroMotionDetectionDuration() * @see MPU6050_RA_ZRMOT_DUR */ -void MPU6050::setZeroMotionDetectionDuration(uint8_t duration) { +void MPU6050_Base::setZeroMotionDetectionDuration(uint8_t duration) { I2Cdev::writeByte(devAddr, MPU6050_RA_ZRMOT_DUR, duration); } @@ -633,7 +634,7 @@ void MPU6050::setZeroMotionDetectionDuration(uint8_t duration) { * @return Current temperature FIFO enabled value * @see MPU6050_RA_FIFO_EN */ -bool MPU6050::getTempFIFOEnabled() { +bool MPU6050_Base::getTempFIFOEnabled() { I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_TEMP_FIFO_EN_BIT, buffer); return buffer[0]; } @@ -642,7 +643,7 @@ bool MPU6050::getTempFIFOEnabled() { * @see getTempFIFOEnabled() * @see MPU6050_RA_FIFO_EN */ -void MPU6050::setTempFIFOEnabled(bool enabled) { +void MPU6050_Base::setTempFIFOEnabled(bool enabled) { I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_TEMP_FIFO_EN_BIT, enabled); } /** Get gyroscope X-axis FIFO enabled value. @@ -651,7 +652,7 @@ void MPU6050::setTempFIFOEnabled(bool enabled) { * @return Current gyroscope X-axis FIFO enabled value * @see MPU6050_RA_FIFO_EN */ -bool MPU6050::getXGyroFIFOEnabled() { +bool MPU6050_Base::getXGyroFIFOEnabled() { I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_XG_FIFO_EN_BIT, buffer); return buffer[0]; } @@ -660,7 +661,7 @@ bool MPU6050::getXGyroFIFOEnabled() { * @see getXGyroFIFOEnabled() * @see MPU6050_RA_FIFO_EN */ -void MPU6050::setXGyroFIFOEnabled(bool enabled) { +void MPU6050_Base::setXGyroFIFOEnabled(bool enabled) { I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_XG_FIFO_EN_BIT, enabled); } /** Get gyroscope Y-axis FIFO enabled value. @@ -669,7 +670,7 @@ void MPU6050::setXGyroFIFOEnabled(bool enabled) { * @return Current gyroscope Y-axis FIFO enabled value * @see MPU6050_RA_FIFO_EN */ -bool MPU6050::getYGyroFIFOEnabled() { +bool MPU6050_Base::getYGyroFIFOEnabled() { I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_YG_FIFO_EN_BIT, buffer); return buffer[0]; } @@ -678,7 +679,7 @@ bool MPU6050::getYGyroFIFOEnabled() { * @see getYGyroFIFOEnabled() * @see MPU6050_RA_FIFO_EN */ -void MPU6050::setYGyroFIFOEnabled(bool enabled) { +void MPU6050_Base::setYGyroFIFOEnabled(bool enabled) { I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_YG_FIFO_EN_BIT, enabled); } /** Get gyroscope Z-axis FIFO enabled value. @@ -687,7 +688,7 @@ void MPU6050::setYGyroFIFOEnabled(bool enabled) { * @return Current gyroscope Z-axis FIFO enabled value * @see MPU6050_RA_FIFO_EN */ -bool MPU6050::getZGyroFIFOEnabled() { +bool MPU6050_Base::getZGyroFIFOEnabled() { I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ZG_FIFO_EN_BIT, buffer); return buffer[0]; } @@ -696,7 +697,7 @@ bool MPU6050::getZGyroFIFOEnabled() { * @see getZGyroFIFOEnabled() * @see MPU6050_RA_FIFO_EN */ -void MPU6050::setZGyroFIFOEnabled(bool enabled) { +void MPU6050_Base::setZGyroFIFOEnabled(bool enabled) { I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ZG_FIFO_EN_BIT, enabled); } /** Get accelerometer FIFO enabled value. @@ -706,7 +707,7 @@ void MPU6050::setZGyroFIFOEnabled(bool enabled) { * @return Current accelerometer FIFO enabled value * @see MPU6050_RA_FIFO_EN */ -bool MPU6050::getAccelFIFOEnabled() { +bool MPU6050_Base::getAccelFIFOEnabled() { I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ACCEL_FIFO_EN_BIT, buffer); return buffer[0]; } @@ -715,7 +716,7 @@ bool MPU6050::getAccelFIFOEnabled() { * @see getAccelFIFOEnabled() * @see MPU6050_RA_FIFO_EN */ -void MPU6050::setAccelFIFOEnabled(bool enabled) { +void MPU6050_Base::setAccelFIFOEnabled(bool enabled) { I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ACCEL_FIFO_EN_BIT, enabled); } /** Get Slave 2 FIFO enabled value. @@ -724,7 +725,7 @@ void MPU6050::setAccelFIFOEnabled(bool enabled) { * @return Current Slave 2 FIFO enabled value * @see MPU6050_RA_FIFO_EN */ -bool MPU6050::getSlave2FIFOEnabled() { +bool MPU6050_Base::getSlave2FIFOEnabled() { I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV2_FIFO_EN_BIT, buffer); return buffer[0]; } @@ -733,7 +734,7 @@ bool MPU6050::getSlave2FIFOEnabled() { * @see getSlave2FIFOEnabled() * @see MPU6050_RA_FIFO_EN */ -void MPU6050::setSlave2FIFOEnabled(bool enabled) { +void MPU6050_Base::setSlave2FIFOEnabled(bool enabled) { I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV2_FIFO_EN_BIT, enabled); } /** Get Slave 1 FIFO enabled value. @@ -742,7 +743,7 @@ void MPU6050::setSlave2FIFOEnabled(bool enabled) { * @return Current Slave 1 FIFO enabled value * @see MPU6050_RA_FIFO_EN */ -bool MPU6050::getSlave1FIFOEnabled() { +bool MPU6050_Base::getSlave1FIFOEnabled() { I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV1_FIFO_EN_BIT, buffer); return buffer[0]; } @@ -751,7 +752,7 @@ bool MPU6050::getSlave1FIFOEnabled() { * @see getSlave1FIFOEnabled() * @see MPU6050_RA_FIFO_EN */ -void MPU6050::setSlave1FIFOEnabled(bool enabled) { +void MPU6050_Base::setSlave1FIFOEnabled(bool enabled) { I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV1_FIFO_EN_BIT, enabled); } /** Get Slave 0 FIFO enabled value. @@ -760,7 +761,7 @@ void MPU6050::setSlave1FIFOEnabled(bool enabled) { * @return Current Slave 0 FIFO enabled value * @see MPU6050_RA_FIFO_EN */ -bool MPU6050::getSlave0FIFOEnabled() { +bool MPU6050_Base::getSlave0FIFOEnabled() { I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV0_FIFO_EN_BIT, buffer); return buffer[0]; } @@ -769,7 +770,7 @@ bool MPU6050::getSlave0FIFOEnabled() { * @see getSlave0FIFOEnabled() * @see MPU6050_RA_FIFO_EN */ -void MPU6050::setSlave0FIFOEnabled(bool enabled) { +void MPU6050_Base::setSlave0FIFOEnabled(bool enabled) { I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV0_FIFO_EN_BIT, enabled); } @@ -790,7 +791,7 @@ void MPU6050::setSlave0FIFOEnabled(bool enabled) { * @return Current multi-master enabled value * @see MPU6050_RA_I2C_MST_CTRL */ -bool MPU6050::getMultiMasterEnabled() { +bool MPU6050_Base::getMultiMasterEnabled() { I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_MULT_MST_EN_BIT, buffer); return buffer[0]; } @@ -799,7 +800,7 @@ bool MPU6050::getMultiMasterEnabled() { * @see getMultiMasterEnabled() * @see MPU6050_RA_I2C_MST_CTRL */ -void MPU6050::setMultiMasterEnabled(bool enabled) { +void MPU6050_Base::setMultiMasterEnabled(bool enabled) { I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_MULT_MST_EN_BIT, enabled); } /** Get wait-for-external-sensor-data enabled value. @@ -813,7 +814,7 @@ void MPU6050::setMultiMasterEnabled(bool enabled) { * @return Current wait-for-external-sensor-data enabled value * @see MPU6050_RA_I2C_MST_CTRL */ -bool MPU6050::getWaitForExternalSensorEnabled() { +bool MPU6050_Base::getWaitForExternalSensorEnabled() { I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_WAIT_FOR_ES_BIT, buffer); return buffer[0]; } @@ -822,7 +823,7 @@ bool MPU6050::getWaitForExternalSensorEnabled() { * @see getWaitForExternalSensorEnabled() * @see MPU6050_RA_I2C_MST_CTRL */ -void MPU6050::setWaitForExternalSensorEnabled(bool enabled) { +void MPU6050_Base::setWaitForExternalSensorEnabled(bool enabled) { I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_WAIT_FOR_ES_BIT, enabled); } /** Get Slave 3 FIFO enabled value. @@ -831,7 +832,7 @@ void MPU6050::setWaitForExternalSensorEnabled(bool enabled) { * @return Current Slave 3 FIFO enabled value * @see MPU6050_RA_MST_CTRL */ -bool MPU6050::getSlave3FIFOEnabled() { +bool MPU6050_Base::getSlave3FIFOEnabled() { I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_SLV_3_FIFO_EN_BIT, buffer); return buffer[0]; } @@ -840,7 +841,7 @@ bool MPU6050::getSlave3FIFOEnabled() { * @see getSlave3FIFOEnabled() * @see MPU6050_RA_MST_CTRL */ -void MPU6050::setSlave3FIFOEnabled(bool enabled) { +void MPU6050_Base::setSlave3FIFOEnabled(bool enabled) { I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_SLV_3_FIFO_EN_BIT, enabled); } /** Get slave read/write transition enabled value. @@ -853,7 +854,7 @@ void MPU6050::setSlave3FIFOEnabled(bool enabled) { * @return Current slave read/write transition enabled value * @see MPU6050_RA_I2C_MST_CTRL */ -bool MPU6050::getSlaveReadWriteTransitionEnabled() { +bool MPU6050_Base::getSlaveReadWriteTransitionEnabled() { I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_P_NSR_BIT, buffer); return buffer[0]; } @@ -862,7 +863,7 @@ bool MPU6050::getSlaveReadWriteTransitionEnabled() { * @see getSlaveReadWriteTransitionEnabled() * @see MPU6050_RA_I2C_MST_CTRL */ -void MPU6050::setSlaveReadWriteTransitionEnabled(bool enabled) { +void MPU6050_Base::setSlaveReadWriteTransitionEnabled(bool enabled) { I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_P_NSR_BIT, enabled); } /** Get I2C master clock speed. @@ -894,7 +895,7 @@ void MPU6050::setSlaveReadWriteTransitionEnabled(bool enabled) { * @return Current I2C master clock speed * @see MPU6050_RA_I2C_MST_CTRL */ -uint8_t MPU6050::getMasterClockSpeed() { +uint8_t MPU6050_Base::getMasterClockSpeed() { I2Cdev::readBits(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_CLK_BIT, MPU6050_I2C_MST_CLK_LENGTH, buffer); return buffer[0]; } @@ -902,7 +903,7 @@ uint8_t MPU6050::getMasterClockSpeed() { * @reparam speed Current I2C master clock speed * @see MPU6050_RA_I2C_MST_CTRL */ -void MPU6050::setMasterClockSpeed(uint8_t speed) { +void MPU6050_Base::setMasterClockSpeed(uint8_t speed) { I2Cdev::writeBits(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_CLK_BIT, MPU6050_I2C_MST_CLK_LENGTH, speed); } @@ -949,7 +950,7 @@ void MPU6050::setMasterClockSpeed(uint8_t speed) { * @return Current address for specified slave * @see MPU6050_RA_I2C_SLV0_ADDR */ -uint8_t MPU6050::getSlaveAddress(uint8_t num) { +uint8_t MPU6050_Base::getSlaveAddress(uint8_t num) { if (num > 3) return 0; I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV0_ADDR + num*3, buffer); return buffer[0]; @@ -960,7 +961,7 @@ uint8_t MPU6050::getSlaveAddress(uint8_t num) { * @see getSlaveAddress() * @see MPU6050_RA_I2C_SLV0_ADDR */ -void MPU6050::setSlaveAddress(uint8_t num, uint8_t address) { +void MPU6050_Base::setSlaveAddress(uint8_t num, uint8_t address) { if (num > 3) return; I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV0_ADDR + num*3, address); } @@ -975,7 +976,7 @@ void MPU6050::setSlaveAddress(uint8_t num, uint8_t address) { * @return Current active register for specified slave * @see MPU6050_RA_I2C_SLV0_REG */ -uint8_t MPU6050::getSlaveRegister(uint8_t num) { +uint8_t MPU6050_Base::getSlaveRegister(uint8_t num) { if (num > 3) return 0; I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV0_REG + num*3, buffer); return buffer[0]; @@ -986,7 +987,7 @@ uint8_t MPU6050::getSlaveRegister(uint8_t num) { * @see getSlaveRegister() * @see MPU6050_RA_I2C_SLV0_REG */ -void MPU6050::setSlaveRegister(uint8_t num, uint8_t reg) { +void MPU6050_Base::setSlaveRegister(uint8_t num, uint8_t reg) { if (num > 3) return; I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV0_REG + num*3, reg); } @@ -997,7 +998,7 @@ void MPU6050::setSlaveRegister(uint8_t num, uint8_t reg) { * @return Current enabled value for specified slave * @see MPU6050_RA_I2C_SLV0_CTRL */ -bool MPU6050::getSlaveEnabled(uint8_t num) { +bool MPU6050_Base::getSlaveEnabled(uint8_t num) { if (num > 3) return 0; I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_EN_BIT, buffer); return buffer[0]; @@ -1008,7 +1009,7 @@ bool MPU6050::getSlaveEnabled(uint8_t num) { * @see getSlaveEnabled() * @see MPU6050_RA_I2C_SLV0_CTRL */ -void MPU6050::setSlaveEnabled(uint8_t num, bool enabled) { +void MPU6050_Base::setSlaveEnabled(uint8_t num, bool enabled) { if (num > 3) return; I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_EN_BIT, enabled); } @@ -1023,7 +1024,7 @@ void MPU6050::setSlaveEnabled(uint8_t num, bool enabled) { * @return Current word pair byte-swapping enabled value for specified slave * @see MPU6050_RA_I2C_SLV0_CTRL */ -bool MPU6050::getSlaveWordByteSwap(uint8_t num) { +bool MPU6050_Base::getSlaveWordByteSwap(uint8_t num) { if (num > 3) return 0; I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_BYTE_SW_BIT, buffer); return buffer[0]; @@ -1034,7 +1035,7 @@ bool MPU6050::getSlaveWordByteSwap(uint8_t num) { * @see getSlaveWordByteSwap() * @see MPU6050_RA_I2C_SLV0_CTRL */ -void MPU6050::setSlaveWordByteSwap(uint8_t num, bool enabled) { +void MPU6050_Base::setSlaveWordByteSwap(uint8_t num, bool enabled) { if (num > 3) return; I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_BYTE_SW_BIT, enabled); } @@ -1048,7 +1049,7 @@ void MPU6050::setSlaveWordByteSwap(uint8_t num, bool enabled) { * @return Current write mode for specified slave (0 = register address + data, 1 = data only) * @see MPU6050_RA_I2C_SLV0_CTRL */ -bool MPU6050::getSlaveWriteMode(uint8_t num) { +bool MPU6050_Base::getSlaveWriteMode(uint8_t num) { if (num > 3) return 0; I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_REG_DIS_BIT, buffer); return buffer[0]; @@ -1059,7 +1060,7 @@ bool MPU6050::getSlaveWriteMode(uint8_t num) { * @see getSlaveWriteMode() * @see MPU6050_RA_I2C_SLV0_CTRL */ -void MPU6050::setSlaveWriteMode(uint8_t num, bool mode) { +void MPU6050_Base::setSlaveWriteMode(uint8_t num, bool mode) { if (num > 3) return; I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_REG_DIS_BIT, mode); } @@ -1074,7 +1075,7 @@ void MPU6050::setSlaveWriteMode(uint8_t num, bool mode) { * @return Current word pair grouping order offset for specified slave * @see MPU6050_RA_I2C_SLV0_CTRL */ -bool MPU6050::getSlaveWordGroupOffset(uint8_t num) { +bool MPU6050_Base::getSlaveWordGroupOffset(uint8_t num) { if (num > 3) return 0; I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_GRP_BIT, buffer); return buffer[0]; @@ -1085,7 +1086,7 @@ bool MPU6050::getSlaveWordGroupOffset(uint8_t num) { * @see getSlaveWordGroupOffset() * @see MPU6050_RA_I2C_SLV0_CTRL */ -void MPU6050::setSlaveWordGroupOffset(uint8_t num, bool enabled) { +void MPU6050_Base::setSlaveWordGroupOffset(uint8_t num, bool enabled) { if (num > 3) return; I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_GRP_BIT, enabled); } @@ -1096,7 +1097,7 @@ void MPU6050::setSlaveWordGroupOffset(uint8_t num, bool enabled) { * @return Number of bytes to read for specified slave * @see MPU6050_RA_I2C_SLV0_CTRL */ -uint8_t MPU6050::getSlaveDataLength(uint8_t num) { +uint8_t MPU6050_Base::getSlaveDataLength(uint8_t num) { if (num > 3) return 0; I2Cdev::readBits(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_LEN_BIT, MPU6050_I2C_SLV_LEN_LENGTH, buffer); return buffer[0]; @@ -1107,7 +1108,7 @@ uint8_t MPU6050::getSlaveDataLength(uint8_t num) { * @see getSlaveDataLength() * @see MPU6050_RA_I2C_SLV0_CTRL */ -void MPU6050::setSlaveDataLength(uint8_t num, uint8_t length) { +void MPU6050_Base::setSlaveDataLength(uint8_t num, uint8_t length) { if (num > 3) return; I2Cdev::writeBits(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_LEN_BIT, MPU6050_I2C_SLV_LEN_LENGTH, length); } @@ -1123,7 +1124,7 @@ void MPU6050::setSlaveDataLength(uint8_t num, uint8_t length) { * @see getSlaveAddress() * @see MPU6050_RA_I2C_SLV4_ADDR */ -uint8_t MPU6050::getSlave4Address() { +uint8_t MPU6050_Base::getSlave4Address() { I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV4_ADDR, buffer); return buffer[0]; } @@ -1132,7 +1133,7 @@ uint8_t MPU6050::getSlave4Address() { * @see getSlave4Address() * @see MPU6050_RA_I2C_SLV4_ADDR */ -void MPU6050::setSlave4Address(uint8_t address) { +void MPU6050_Base::setSlave4Address(uint8_t address) { I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV4_ADDR, address); } /** Get the active internal register for the Slave 4. @@ -1142,7 +1143,7 @@ void MPU6050::setSlave4Address(uint8_t address) { * @return Current active register for Slave 4 * @see MPU6050_RA_I2C_SLV4_REG */ -uint8_t MPU6050::getSlave4Register() { +uint8_t MPU6050_Base::getSlave4Register() { I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV4_REG, buffer); return buffer[0]; } @@ -1151,7 +1152,7 @@ uint8_t MPU6050::getSlave4Register() { * @see getSlave4Register() * @see MPU6050_RA_I2C_SLV4_REG */ -void MPU6050::setSlave4Register(uint8_t reg) { +void MPU6050_Base::setSlave4Register(uint8_t reg) { I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV4_REG, reg); } /** Set new byte to write to Slave 4. @@ -1160,7 +1161,7 @@ void MPU6050::setSlave4Register(uint8_t reg) { * @param data New byte to write to Slave 4 * @see MPU6050_RA_I2C_SLV4_DO */ -void MPU6050::setSlave4OutputByte(uint8_t data) { +void MPU6050_Base::setSlave4OutputByte(uint8_t data) { I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV4_DO, data); } /** Get the enabled value for the Slave 4. @@ -1169,7 +1170,7 @@ void MPU6050::setSlave4OutputByte(uint8_t data) { * @return Current enabled value for Slave 4 * @see MPU6050_RA_I2C_SLV4_CTRL */ -bool MPU6050::getSlave4Enabled() { +bool MPU6050_Base::getSlave4Enabled() { I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_EN_BIT, buffer); return buffer[0]; } @@ -1178,7 +1179,7 @@ bool MPU6050::getSlave4Enabled() { * @see getSlave4Enabled() * @see MPU6050_RA_I2C_SLV4_CTRL */ -void MPU6050::setSlave4Enabled(bool enabled) { +void MPU6050_Base::setSlave4Enabled(bool enabled) { I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_EN_BIT, enabled); } /** Get the enabled value for Slave 4 transaction interrupts. @@ -1190,7 +1191,7 @@ void MPU6050::setSlave4Enabled(bool enabled) { * @return Current enabled value for Slave 4 transaction interrupts. * @see MPU6050_RA_I2C_SLV4_CTRL */ -bool MPU6050::getSlave4InterruptEnabled() { +bool MPU6050_Base::getSlave4InterruptEnabled() { I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_INT_EN_BIT, buffer); return buffer[0]; } @@ -1199,7 +1200,7 @@ bool MPU6050::getSlave4InterruptEnabled() { * @see getSlave4InterruptEnabled() * @see MPU6050_RA_I2C_SLV4_CTRL */ -void MPU6050::setSlave4InterruptEnabled(bool enabled) { +void MPU6050_Base::setSlave4InterruptEnabled(bool enabled) { I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_INT_EN_BIT, enabled); } /** Get write mode for Slave 4. @@ -1211,7 +1212,7 @@ void MPU6050::setSlave4InterruptEnabled(bool enabled) { * @return Current write mode for Slave 4 (0 = register address + data, 1 = data only) * @see MPU6050_RA_I2C_SLV4_CTRL */ -bool MPU6050::getSlave4WriteMode() { +bool MPU6050_Base::getSlave4WriteMode() { I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_REG_DIS_BIT, buffer); return buffer[0]; } @@ -1220,7 +1221,7 @@ bool MPU6050::getSlave4WriteMode() { * @see getSlave4WriteMode() * @see MPU6050_RA_I2C_SLV4_CTRL */ -void MPU6050::setSlave4WriteMode(bool mode) { +void MPU6050_Base::setSlave4WriteMode(bool mode) { I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_REG_DIS_BIT, mode); } /** Get Slave 4 master delay value. @@ -1238,7 +1239,7 @@ void MPU6050::setSlave4WriteMode(bool mode) { * @return Current Slave 4 master delay value * @see MPU6050_RA_I2C_SLV4_CTRL */ -uint8_t MPU6050::getSlave4MasterDelay() { +uint8_t MPU6050_Base::getSlave4MasterDelay() { I2Cdev::readBits(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_MST_DLY_BIT, MPU6050_I2C_SLV4_MST_DLY_LENGTH, buffer); return buffer[0]; } @@ -1247,7 +1248,7 @@ uint8_t MPU6050::getSlave4MasterDelay() { * @see getSlave4MasterDelay() * @see MPU6050_RA_I2C_SLV4_CTRL */ -void MPU6050::setSlave4MasterDelay(uint8_t delay) { +void MPU6050_Base::setSlave4MasterDelay(uint8_t delay) { I2Cdev::writeBits(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_MST_DLY_BIT, MPU6050_I2C_SLV4_MST_DLY_LENGTH, delay); } /** Get last available byte read from Slave 4. @@ -1256,7 +1257,7 @@ void MPU6050::setSlave4MasterDelay(uint8_t delay) { * @return Last available byte read from to Slave 4 * @see MPU6050_RA_I2C_SLV4_DI */ -uint8_t MPU6050::getSlate4InputByte() { +uint8_t MPU6050_Base::getSlate4InputByte() { I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV4_DI, buffer); return buffer[0]; } @@ -1272,7 +1273,7 @@ uint8_t MPU6050::getSlate4InputByte() { * @return FSYNC interrupt status * @see MPU6050_RA_I2C_MST_STATUS */ -bool MPU6050::getPassthroughStatus() { +bool MPU6050_Base::getPassthroughStatus() { I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_PASS_THROUGH_BIT, buffer); return buffer[0]; } @@ -1284,7 +1285,7 @@ bool MPU6050::getPassthroughStatus() { * @return Slave 4 transaction done status * @see MPU6050_RA_I2C_MST_STATUS */ -bool MPU6050::getSlave4IsDone() { +bool MPU6050_Base::getSlave4IsDone() { I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV4_DONE_BIT, buffer); return buffer[0]; } @@ -1295,7 +1296,7 @@ bool MPU6050::getSlave4IsDone() { * @return Master arbitration lost status * @see MPU6050_RA_I2C_MST_STATUS */ -bool MPU6050::getLostArbitration() { +bool MPU6050_Base::getLostArbitration() { I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_LOST_ARB_BIT, buffer); return buffer[0]; } @@ -1306,7 +1307,7 @@ bool MPU6050::getLostArbitration() { * @return Slave 4 NACK interrupt status * @see MPU6050_RA_I2C_MST_STATUS */ -bool MPU6050::getSlave4Nack() { +bool MPU6050_Base::getSlave4Nack() { I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV4_NACK_BIT, buffer); return buffer[0]; } @@ -1317,7 +1318,7 @@ bool MPU6050::getSlave4Nack() { * @return Slave 3 NACK interrupt status * @see MPU6050_RA_I2C_MST_STATUS */ -bool MPU6050::getSlave3Nack() { +bool MPU6050_Base::getSlave3Nack() { I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV3_NACK_BIT, buffer); return buffer[0]; } @@ -1328,7 +1329,7 @@ bool MPU6050::getSlave3Nack() { * @return Slave 2 NACK interrupt status * @see MPU6050_RA_I2C_MST_STATUS */ -bool MPU6050::getSlave2Nack() { +bool MPU6050_Base::getSlave2Nack() { I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV2_NACK_BIT, buffer); return buffer[0]; } @@ -1339,7 +1340,7 @@ bool MPU6050::getSlave2Nack() { * @return Slave 1 NACK interrupt status * @see MPU6050_RA_I2C_MST_STATUS */ -bool MPU6050::getSlave1Nack() { +bool MPU6050_Base::getSlave1Nack() { I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV1_NACK_BIT, buffer); return buffer[0]; } @@ -1350,7 +1351,7 @@ bool MPU6050::getSlave1Nack() { * @return Slave 0 NACK interrupt status * @see MPU6050_RA_I2C_MST_STATUS */ -bool MPU6050::getSlave0Nack() { +bool MPU6050_Base::getSlave0Nack() { I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV0_NACK_BIT, buffer); return buffer[0]; } @@ -1363,7 +1364,7 @@ bool MPU6050::getSlave0Nack() { * @see MPU6050_RA_INT_PIN_CFG * @see MPU6050_INTCFG_INT_LEVEL_BIT */ -bool MPU6050::getInterruptMode() { +bool MPU6050_Base::getInterruptMode() { I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_LEVEL_BIT, buffer); return buffer[0]; } @@ -1373,7 +1374,7 @@ bool MPU6050::getInterruptMode() { * @see MPU6050_RA_INT_PIN_CFG * @see MPU6050_INTCFG_INT_LEVEL_BIT */ -void MPU6050::setInterruptMode(bool mode) { +void MPU6050_Base::setInterruptMode(bool mode) { I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_LEVEL_BIT, mode); } /** Get interrupt drive mode. @@ -1382,7 +1383,7 @@ void MPU6050::setInterruptMode(bool mode) { * @see MPU6050_RA_INT_PIN_CFG * @see MPU6050_INTCFG_INT_OPEN_BIT */ -bool MPU6050::getInterruptDrive() { +bool MPU6050_Base::getInterruptDrive() { I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_OPEN_BIT, buffer); return buffer[0]; } @@ -1392,7 +1393,7 @@ bool MPU6050::getInterruptDrive() { * @see MPU6050_RA_INT_PIN_CFG * @see MPU6050_INTCFG_INT_OPEN_BIT */ -void MPU6050::setInterruptDrive(bool drive) { +void MPU6050_Base::setInterruptDrive(bool drive) { I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_OPEN_BIT, drive); } /** Get interrupt latch mode. @@ -1401,7 +1402,7 @@ void MPU6050::setInterruptDrive(bool drive) { * @see MPU6050_RA_INT_PIN_CFG * @see MPU6050_INTCFG_LATCH_INT_EN_BIT */ -bool MPU6050::getInterruptLatch() { +bool MPU6050_Base::getInterruptLatch() { I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_LATCH_INT_EN_BIT, buffer); return buffer[0]; } @@ -1411,7 +1412,7 @@ bool MPU6050::getInterruptLatch() { * @see MPU6050_RA_INT_PIN_CFG * @see MPU6050_INTCFG_LATCH_INT_EN_BIT */ -void MPU6050::setInterruptLatch(bool latch) { +void MPU6050_Base::setInterruptLatch(bool latch) { I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_LATCH_INT_EN_BIT, latch); } /** Get interrupt latch clear mode. @@ -1420,7 +1421,7 @@ void MPU6050::setInterruptLatch(bool latch) { * @see MPU6050_RA_INT_PIN_CFG * @see MPU6050_INTCFG_INT_RD_CLEAR_BIT */ -bool MPU6050::getInterruptLatchClear() { +bool MPU6050_Base::getInterruptLatchClear() { I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_RD_CLEAR_BIT, buffer); return buffer[0]; } @@ -1430,7 +1431,7 @@ bool MPU6050::getInterruptLatchClear() { * @see MPU6050_RA_INT_PIN_CFG * @see MPU6050_INTCFG_INT_RD_CLEAR_BIT */ -void MPU6050::setInterruptLatchClear(bool clear) { +void MPU6050_Base::setInterruptLatchClear(bool clear) { I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_RD_CLEAR_BIT, clear); } /** Get FSYNC interrupt logic level mode. @@ -1439,7 +1440,7 @@ void MPU6050::setInterruptLatchClear(bool clear) { * @see MPU6050_RA_INT_PIN_CFG * @see MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT */ -bool MPU6050::getFSyncInterruptLevel() { +bool MPU6050_Base::getFSyncInterruptLevel() { I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT, buffer); return buffer[0]; } @@ -1449,7 +1450,7 @@ bool MPU6050::getFSyncInterruptLevel() { * @see MPU6050_RA_INT_PIN_CFG * @see MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT */ -void MPU6050::setFSyncInterruptLevel(bool level) { +void MPU6050_Base::setFSyncInterruptLevel(bool level) { I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT, level); } /** Get FSYNC pin interrupt enabled setting. @@ -1458,7 +1459,7 @@ void MPU6050::setFSyncInterruptLevel(bool level) { * @see MPU6050_RA_INT_PIN_CFG * @see MPU6050_INTCFG_FSYNC_INT_EN_BIT */ -bool MPU6050::getFSyncInterruptEnabled() { +bool MPU6050_Base::getFSyncInterruptEnabled() { I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_EN_BIT, buffer); return buffer[0]; } @@ -1468,7 +1469,7 @@ bool MPU6050::getFSyncInterruptEnabled() { * @see MPU6050_RA_INT_PIN_CFG * @see MPU6050_INTCFG_FSYNC_INT_EN_BIT */ -void MPU6050::setFSyncInterruptEnabled(bool enabled) { +void MPU6050_Base::setFSyncInterruptEnabled(bool enabled) { I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_EN_BIT, enabled); } /** Get I2C bypass enabled status. @@ -1482,7 +1483,7 @@ void MPU6050::setFSyncInterruptEnabled(bool enabled) { * @see MPU6050_RA_INT_PIN_CFG * @see MPU6050_INTCFG_I2C_BYPASS_EN_BIT */ -bool MPU6050::getI2CBypassEnabled() { +bool MPU6050_Base::getI2CBypassEnabled() { I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_I2C_BYPASS_EN_BIT, buffer); return buffer[0]; } @@ -1497,7 +1498,7 @@ bool MPU6050::getI2CBypassEnabled() { * @see MPU6050_RA_INT_PIN_CFG * @see MPU6050_INTCFG_I2C_BYPASS_EN_BIT */ -void MPU6050::setI2CBypassEnabled(bool enabled) { +void MPU6050_Base::setI2CBypassEnabled(bool enabled) { I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_I2C_BYPASS_EN_BIT, enabled); } /** Get reference clock output enabled status. @@ -1509,7 +1510,7 @@ void MPU6050::setI2CBypassEnabled(bool enabled) { * @see MPU6050_RA_INT_PIN_CFG * @see MPU6050_INTCFG_CLKOUT_EN_BIT */ -bool MPU6050::getClockOutputEnabled() { +bool MPU6050_Base::getClockOutputEnabled() { I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_CLKOUT_EN_BIT, buffer); return buffer[0]; } @@ -1522,7 +1523,7 @@ bool MPU6050::getClockOutputEnabled() { * @see MPU6050_RA_INT_PIN_CFG * @see MPU6050_INTCFG_CLKOUT_EN_BIT */ -void MPU6050::setClockOutputEnabled(bool enabled) { +void MPU6050_Base::setClockOutputEnabled(bool enabled) { I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_CLKOUT_EN_BIT, enabled); } @@ -1535,7 +1536,7 @@ void MPU6050::setClockOutputEnabled(bool enabled) { * @see MPU6050_RA_INT_ENABLE * @see MPU6050_INTERRUPT_FF_BIT **/ -uint8_t MPU6050::getIntEnabled() { +uint8_t MPU6050_Base::getIntEnabled() { I2Cdev::readByte(devAddr, MPU6050_RA_INT_ENABLE, buffer); return buffer[0]; } @@ -1547,7 +1548,7 @@ uint8_t MPU6050::getIntEnabled() { * @see MPU6050_RA_INT_ENABLE * @see MPU6050_INTERRUPT_FF_BIT **/ -void MPU6050::setIntEnabled(uint8_t enabled) { +void MPU6050_Base::setIntEnabled(uint8_t enabled) { I2Cdev::writeByte(devAddr, MPU6050_RA_INT_ENABLE, enabled); } /** Get Free Fall interrupt enabled status. @@ -1556,7 +1557,7 @@ void MPU6050::setIntEnabled(uint8_t enabled) { * @see MPU6050_RA_INT_ENABLE * @see MPU6050_INTERRUPT_FF_BIT **/ -bool MPU6050::getIntFreefallEnabled() { +bool MPU6050_Base::getIntFreefallEnabled() { I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FF_BIT, buffer); return buffer[0]; } @@ -1566,7 +1567,7 @@ bool MPU6050::getIntFreefallEnabled() { * @see MPU6050_RA_INT_ENABLE * @see MPU6050_INTERRUPT_FF_BIT **/ -void MPU6050::setIntFreefallEnabled(bool enabled) { +void MPU6050_Base::setIntFreefallEnabled(bool enabled) { I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FF_BIT, enabled); } /** Get Motion Detection interrupt enabled status. @@ -1575,7 +1576,7 @@ void MPU6050::setIntFreefallEnabled(bool enabled) { * @see MPU6050_RA_INT_ENABLE * @see MPU6050_INTERRUPT_MOT_BIT **/ -bool MPU6050::getIntMotionEnabled() { +bool MPU6050_Base::getIntMotionEnabled() { I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_MOT_BIT, buffer); return buffer[0]; } @@ -1585,7 +1586,7 @@ bool MPU6050::getIntMotionEnabled() { * @see MPU6050_RA_INT_ENABLE * @see MPU6050_INTERRUPT_MOT_BIT **/ -void MPU6050::setIntMotionEnabled(bool enabled) { +void MPU6050_Base::setIntMotionEnabled(bool enabled) { I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_MOT_BIT, enabled); } /** Get Zero Motion Detection interrupt enabled status. @@ -1594,7 +1595,7 @@ void MPU6050::setIntMotionEnabled(bool enabled) { * @see MPU6050_RA_INT_ENABLE * @see MPU6050_INTERRUPT_ZMOT_BIT **/ -bool MPU6050::getIntZeroMotionEnabled() { +bool MPU6050_Base::getIntZeroMotionEnabled() { I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_ZMOT_BIT, buffer); return buffer[0]; } @@ -1604,7 +1605,7 @@ bool MPU6050::getIntZeroMotionEnabled() { * @see MPU6050_RA_INT_ENABLE * @see MPU6050_INTERRUPT_ZMOT_BIT **/ -void MPU6050::setIntZeroMotionEnabled(bool enabled) { +void MPU6050_Base::setIntZeroMotionEnabled(bool enabled) { I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_ZMOT_BIT, enabled); } /** Get FIFO Buffer Overflow interrupt enabled status. @@ -1613,7 +1614,7 @@ void MPU6050::setIntZeroMotionEnabled(bool enabled) { * @see MPU6050_RA_INT_ENABLE * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT **/ -bool MPU6050::getIntFIFOBufferOverflowEnabled() { +bool MPU6050_Base::getIntFIFOBufferOverflowEnabled() { I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, buffer); return buffer[0]; } @@ -1623,7 +1624,7 @@ bool MPU6050::getIntFIFOBufferOverflowEnabled() { * @see MPU6050_RA_INT_ENABLE * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT **/ -void MPU6050::setIntFIFOBufferOverflowEnabled(bool enabled) { +void MPU6050_Base::setIntFIFOBufferOverflowEnabled(bool enabled) { I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, enabled); } /** Get I2C Master interrupt enabled status. @@ -1633,7 +1634,7 @@ void MPU6050::setIntFIFOBufferOverflowEnabled(bool enabled) { * @see MPU6050_RA_INT_ENABLE * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT **/ -bool MPU6050::getIntI2CMasterEnabled() { +bool MPU6050_Base::getIntI2CMasterEnabled() { I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_I2C_MST_INT_BIT, buffer); return buffer[0]; } @@ -1643,7 +1644,7 @@ bool MPU6050::getIntI2CMasterEnabled() { * @see MPU6050_RA_INT_ENABLE * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT **/ -void MPU6050::setIntI2CMasterEnabled(bool enabled) { +void MPU6050_Base::setIntI2CMasterEnabled(bool enabled) { I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_I2C_MST_INT_BIT, enabled); } /** Get Data Ready interrupt enabled setting. @@ -1653,7 +1654,7 @@ void MPU6050::setIntI2CMasterEnabled(bool enabled) { * @see MPU6050_RA_INT_ENABLE * @see MPU6050_INTERRUPT_DATA_RDY_BIT */ -bool MPU6050::getIntDataReadyEnabled() { +bool MPU6050_Base::getIntDataReadyEnabled() { I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DATA_RDY_BIT, buffer); return buffer[0]; } @@ -1663,7 +1664,7 @@ bool MPU6050::getIntDataReadyEnabled() { * @see MPU6050_RA_INT_CFG * @see MPU6050_INTERRUPT_DATA_RDY_BIT */ -void MPU6050::setIntDataReadyEnabled(bool enabled) { +void MPU6050_Base::setIntDataReadyEnabled(bool enabled) { I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DATA_RDY_BIT, enabled); } @@ -1676,7 +1677,7 @@ void MPU6050::setIntDataReadyEnabled(bool enabled) { * @return Current interrupt status * @see MPU6050_RA_INT_STATUS */ -uint8_t MPU6050::getIntStatus() { +uint8_t MPU6050_Base::getIntStatus() { I2Cdev::readByte(devAddr, MPU6050_RA_INT_STATUS, buffer); return buffer[0]; } @@ -1687,7 +1688,7 @@ uint8_t MPU6050::getIntStatus() { * @see MPU6050_RA_INT_STATUS * @see MPU6050_INTERRUPT_FF_BIT */ -bool MPU6050::getIntFreefallStatus() { +bool MPU6050_Base::getIntFreefallStatus() { I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_FF_BIT, buffer); return buffer[0]; } @@ -1698,7 +1699,7 @@ bool MPU6050::getIntFreefallStatus() { * @see MPU6050_RA_INT_STATUS * @see MPU6050_INTERRUPT_MOT_BIT */ -bool MPU6050::getIntMotionStatus() { +bool MPU6050_Base::getIntMotionStatus() { I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_MOT_BIT, buffer); return buffer[0]; } @@ -1709,7 +1710,7 @@ bool MPU6050::getIntMotionStatus() { * @see MPU6050_RA_INT_STATUS * @see MPU6050_INTERRUPT_ZMOT_BIT */ -bool MPU6050::getIntZeroMotionStatus() { +bool MPU6050_Base::getIntZeroMotionStatus() { I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_ZMOT_BIT, buffer); return buffer[0]; } @@ -1720,7 +1721,7 @@ bool MPU6050::getIntZeroMotionStatus() { * @see MPU6050_RA_INT_STATUS * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT */ -bool MPU6050::getIntFIFOBufferOverflowStatus() { +bool MPU6050_Base::getIntFIFOBufferOverflowStatus() { I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, buffer); return buffer[0]; } @@ -1732,7 +1733,7 @@ bool MPU6050::getIntFIFOBufferOverflowStatus() { * @see MPU6050_RA_INT_STATUS * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT */ -bool MPU6050::getIntI2CMasterStatus() { +bool MPU6050_Base::getIntI2CMasterStatus() { I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_I2C_MST_INT_BIT, buffer); return buffer[0]; } @@ -1743,7 +1744,7 @@ bool MPU6050::getIntI2CMasterStatus() { * @see MPU6050_RA_INT_STATUS * @see MPU6050_INTERRUPT_DATA_RDY_BIT */ -bool MPU6050::getIntDataReadyStatus() { +bool MPU6050_Base::getIntDataReadyStatus() { I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_DATA_RDY_BIT, buffer); return buffer[0]; } @@ -1766,7 +1767,7 @@ bool MPU6050::getIntDataReadyStatus() { * @see getRotation() * @see MPU6050_RA_ACCEL_XOUT_H */ -void MPU6050::getMotion9(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz, int16_t* mx, int16_t* my, int16_t* mz) { +void MPU6050_Base::getMotion9(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz, int16_t* mx, int16_t* my, int16_t* mz) { (void)mx; // unused parameter (void)my; // unused parameter (void)mz; // unused parameter @@ -1786,7 +1787,7 @@ void MPU6050::getMotion9(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int * @see getRotation() * @see MPU6050_RA_ACCEL_XOUT_H */ -void MPU6050::getMotion6(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz) { +void MPU6050_Base::getMotion6(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz) { I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_XOUT_H, 14, buffer); *ax = (((int16_t)buffer[0]) << 8) | buffer[1]; *ay = (((int16_t)buffer[2]) << 8) | buffer[3]; @@ -1831,7 +1832,7 @@ void MPU6050::getMotion6(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int * @param z 16-bit signed integer container for Z-axis acceleration * @see MPU6050_RA_GYRO_XOUT_H */ -void MPU6050::getAcceleration(int16_t* x, int16_t* y, int16_t* z) { +void MPU6050_Base::getAcceleration(int16_t* x, int16_t* y, int16_t* z) { I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_XOUT_H, 6, buffer); *x = (((int16_t)buffer[0]) << 8) | buffer[1]; *y = (((int16_t)buffer[2]) << 8) | buffer[3]; @@ -1842,7 +1843,7 @@ void MPU6050::getAcceleration(int16_t* x, int16_t* y, int16_t* z) { * @see getMotion6() * @see MPU6050_RA_ACCEL_XOUT_H */ -int16_t MPU6050::getAccelerationX() { +int16_t MPU6050_Base::getAccelerationX() { I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_XOUT_H, 2, buffer); return (((int16_t)buffer[0]) << 8) | buffer[1]; } @@ -1851,7 +1852,7 @@ int16_t MPU6050::getAccelerationX() { * @see getMotion6() * @see MPU6050_RA_ACCEL_YOUT_H */ -int16_t MPU6050::getAccelerationY() { +int16_t MPU6050_Base::getAccelerationY() { I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_YOUT_H, 2, buffer); return (((int16_t)buffer[0]) << 8) | buffer[1]; } @@ -1860,7 +1861,7 @@ int16_t MPU6050::getAccelerationY() { * @see getMotion6() * @see MPU6050_RA_ACCEL_ZOUT_H */ -int16_t MPU6050::getAccelerationZ() { +int16_t MPU6050_Base::getAccelerationZ() { I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_ZOUT_H, 2, buffer); return (((int16_t)buffer[0]) << 8) | buffer[1]; } @@ -1871,7 +1872,7 @@ int16_t MPU6050::getAccelerationZ() { * @return Temperature reading in 16-bit 2's complement format * @see MPU6050_RA_TEMP_OUT_H */ -int16_t MPU6050::getTemperature() { +int16_t MPU6050_Base::getTemperature() { I2Cdev::readBytes(devAddr, MPU6050_RA_TEMP_OUT_H, 2, buffer); return (((int16_t)buffer[0]) << 8) | buffer[1]; } @@ -1910,7 +1911,7 @@ int16_t MPU6050::getTemperature() { * @see getMotion6() * @see MPU6050_RA_GYRO_XOUT_H */ -void MPU6050::getRotation(int16_t* x, int16_t* y, int16_t* z) { +void MPU6050_Base::getRotation(int16_t* x, int16_t* y, int16_t* z) { I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_XOUT_H, 6, buffer); *x = (((int16_t)buffer[0]) << 8) | buffer[1]; *y = (((int16_t)buffer[2]) << 8) | buffer[3]; @@ -1921,7 +1922,7 @@ void MPU6050::getRotation(int16_t* x, int16_t* y, int16_t* z) { * @see getMotion6() * @see MPU6050_RA_GYRO_XOUT_H */ -int16_t MPU6050::getRotationX() { +int16_t MPU6050_Base::getRotationX() { I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_XOUT_H, 2, buffer); return (((int16_t)buffer[0]) << 8) | buffer[1]; } @@ -1930,7 +1931,7 @@ int16_t MPU6050::getRotationX() { * @see getMotion6() * @see MPU6050_RA_GYRO_YOUT_H */ -int16_t MPU6050::getRotationY() { +int16_t MPU6050_Base::getRotationY() { I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_YOUT_H, 2, buffer); return (((int16_t)buffer[0]) << 8) | buffer[1]; } @@ -1939,7 +1940,7 @@ int16_t MPU6050::getRotationY() { * @see getMotion6() * @see MPU6050_RA_GYRO_ZOUT_H */ -int16_t MPU6050::getRotationZ() { +int16_t MPU6050_Base::getRotationZ() { I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_ZOUT_H, 2, buffer); return (((int16_t)buffer[0]) << 8) | buffer[1]; } @@ -2020,7 +2021,7 @@ int16_t MPU6050::getRotationZ() { * @param position Starting position (0-23) * @return Byte read from register */ -uint8_t MPU6050::getExternalSensorByte(int position) { +uint8_t MPU6050_Base::getExternalSensorByte(int position) { I2Cdev::readByte(devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, buffer); return buffer[0]; } @@ -2029,7 +2030,7 @@ uint8_t MPU6050::getExternalSensorByte(int position) { * @return Word read from register * @see getExternalSensorByte() */ -uint16_t MPU6050::getExternalSensorWord(int position) { +uint16_t MPU6050_Base::getExternalSensorWord(int position) { I2Cdev::readBytes(devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, 2, buffer); return (((uint16_t)buffer[0]) << 8) | buffer[1]; } @@ -2038,7 +2039,7 @@ uint16_t MPU6050::getExternalSensorWord(int position) { * @return Double word read from registers * @see getExternalSensorByte() */ -uint32_t MPU6050::getExternalSensorDWord(int position) { +uint32_t MPU6050_Base::getExternalSensorDWord(int position) { I2Cdev::readBytes(devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, 4, buffer); return (((uint32_t)buffer[0]) << 24) | (((uint32_t)buffer[1]) << 16) | (((uint16_t)buffer[2]) << 8) | buffer[3]; } @@ -2049,7 +2050,7 @@ uint32_t MPU6050::getExternalSensorDWord(int position) { * @return Motion detection status byte * @see MPU6050_RA_MOT_DETECT_STATUS */ -uint8_t MPU6050::getMotionStatus() { +uint8_t MPU6050_Base::getMotionStatus() { I2Cdev::readByte(devAddr, MPU6050_RA_MOT_DETECT_STATUS, buffer); return buffer[0]; } @@ -2058,7 +2059,7 @@ uint8_t MPU6050::getMotionStatus() { * @see MPU6050_RA_MOT_DETECT_STATUS * @see MPU6050_MOTION_MOT_XNEG_BIT */ -bool MPU6050::getXNegMotionDetected() { +bool MPU6050_Base::getXNegMotionDetected() { I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_XNEG_BIT, buffer); return buffer[0]; } @@ -2067,7 +2068,7 @@ bool MPU6050::getXNegMotionDetected() { * @see MPU6050_RA_MOT_DETECT_STATUS * @see MPU6050_MOTION_MOT_XPOS_BIT */ -bool MPU6050::getXPosMotionDetected() { +bool MPU6050_Base::getXPosMotionDetected() { I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_XPOS_BIT, buffer); return buffer[0]; } @@ -2076,7 +2077,7 @@ bool MPU6050::getXPosMotionDetected() { * @see MPU6050_RA_MOT_DETECT_STATUS * @see MPU6050_MOTION_MOT_YNEG_BIT */ -bool MPU6050::getYNegMotionDetected() { +bool MPU6050_Base::getYNegMotionDetected() { I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_YNEG_BIT, buffer); return buffer[0]; } @@ -2085,7 +2086,7 @@ bool MPU6050::getYNegMotionDetected() { * @see MPU6050_RA_MOT_DETECT_STATUS * @see MPU6050_MOTION_MOT_YPOS_BIT */ -bool MPU6050::getYPosMotionDetected() { +bool MPU6050_Base::getYPosMotionDetected() { I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_YPOS_BIT, buffer); return buffer[0]; } @@ -2094,7 +2095,7 @@ bool MPU6050::getYPosMotionDetected() { * @see MPU6050_RA_MOT_DETECT_STATUS * @see MPU6050_MOTION_MOT_ZNEG_BIT */ -bool MPU6050::getZNegMotionDetected() { +bool MPU6050_Base::getZNegMotionDetected() { I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZNEG_BIT, buffer); return buffer[0]; } @@ -2103,7 +2104,7 @@ bool MPU6050::getZNegMotionDetected() { * @see MPU6050_RA_MOT_DETECT_STATUS * @see MPU6050_MOTION_MOT_ZPOS_BIT */ -bool MPU6050::getZPosMotionDetected() { +bool MPU6050_Base::getZPosMotionDetected() { I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZPOS_BIT, buffer); return buffer[0]; } @@ -2112,7 +2113,7 @@ bool MPU6050::getZPosMotionDetected() { * @see MPU6050_RA_MOT_DETECT_STATUS * @see MPU6050_MOTION_MOT_ZRMOT_BIT */ -bool MPU6050::getZeroMotionDetected() { +bool MPU6050_Base::getZeroMotionDetected() { I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZRMOT_BIT, buffer); return buffer[0]; } @@ -2127,7 +2128,7 @@ bool MPU6050::getZeroMotionDetected() { * @param data Byte to write * @see MPU6050_RA_I2C_SLV0_DO */ -void MPU6050::setSlaveOutputByte(uint8_t num, uint8_t data) { +void MPU6050_Base::setSlaveOutputByte(uint8_t num, uint8_t data) { if (num > 3) return; I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV0_DO + num, data); } @@ -2142,7 +2143,7 @@ void MPU6050::setSlaveOutputByte(uint8_t num, uint8_t data) { * @see MPU6050_RA_I2C_MST_DELAY_CTRL * @see MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT */ -bool MPU6050::getExternalShadowDelayEnabled() { +bool MPU6050_Base::getExternalShadowDelayEnabled() { I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT, buffer); return buffer[0]; } @@ -2152,7 +2153,7 @@ bool MPU6050::getExternalShadowDelayEnabled() { * @see MPU6050_RA_I2C_MST_DELAY_CTRL * @see MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT */ -void MPU6050::setExternalShadowDelayEnabled(bool enabled) { +void MPU6050_Base::setExternalShadowDelayEnabled(bool enabled) { I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT, enabled); } /** Get slave delay enabled status. @@ -2173,7 +2174,7 @@ void MPU6050::setExternalShadowDelayEnabled(bool enabled) { * @see MPU6050_RA_I2C_MST_DELAY_CTRL * @see MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT */ -bool MPU6050::getSlaveDelayEnabled(uint8_t num) { +bool MPU6050_Base::getSlaveDelayEnabled(uint8_t num) { // MPU6050_DELAYCTRL_I2C_SLV4_DLY_EN_BIT is 4, SLV3 is 3, etc. if (num > 4) return 0; I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, num, buffer); @@ -2185,7 +2186,7 @@ bool MPU6050::getSlaveDelayEnabled(uint8_t num) { * @see MPU6050_RA_I2C_MST_DELAY_CTRL * @see MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT */ -void MPU6050::setSlaveDelayEnabled(uint8_t num, bool enabled) { +void MPU6050_Base::setSlaveDelayEnabled(uint8_t num, bool enabled) { I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, num, enabled); } @@ -2197,7 +2198,7 @@ void MPU6050::setSlaveDelayEnabled(uint8_t num, bool enabled) { * @see MPU6050_RA_SIGNAL_PATH_RESET * @see MPU6050_PATHRESET_GYRO_RESET_BIT */ -void MPU6050::resetGyroscopePath() { +void MPU6050_Base::resetGyroscopePath() { I2Cdev::writeBit(devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_GYRO_RESET_BIT, true); } /** Reset accelerometer signal path. @@ -2206,7 +2207,7 @@ void MPU6050::resetGyroscopePath() { * @see MPU6050_RA_SIGNAL_PATH_RESET * @see MPU6050_PATHRESET_ACCEL_RESET_BIT */ -void MPU6050::resetAccelerometerPath() { +void MPU6050_Base::resetAccelerometerPath() { I2Cdev::writeBit(devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_ACCEL_RESET_BIT, true); } /** Reset temperature sensor signal path. @@ -2215,7 +2216,7 @@ void MPU6050::resetAccelerometerPath() { * @see MPU6050_RA_SIGNAL_PATH_RESET * @see MPU6050_PATHRESET_TEMP_RESET_BIT */ -void MPU6050::resetTemperaturePath() { +void MPU6050_Base::resetTemperaturePath() { I2Cdev::writeBit(devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_TEMP_RESET_BIT, true); } @@ -2235,7 +2236,7 @@ void MPU6050::resetTemperaturePath() { * @see MPU6050_RA_MOT_DETECT_CTRL * @see MPU6050_DETECT_ACCEL_ON_DELAY_BIT */ -uint8_t MPU6050::getAccelerometerPowerOnDelay() { +uint8_t MPU6050_Base::getAccelerometerPowerOnDelay() { I2Cdev::readBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_ACCEL_ON_DELAY_BIT, MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH, buffer); return buffer[0]; } @@ -2245,7 +2246,7 @@ uint8_t MPU6050::getAccelerometerPowerOnDelay() { * @see MPU6050_RA_MOT_DETECT_CTRL * @see MPU6050_DETECT_ACCEL_ON_DELAY_BIT */ -void MPU6050::setAccelerometerPowerOnDelay(uint8_t delay) { +void MPU6050_Base::setAccelerometerPowerOnDelay(uint8_t delay) { I2Cdev::writeBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_ACCEL_ON_DELAY_BIT, MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH, delay); } /** Get Free Fall detection counter decrement configuration. @@ -2274,7 +2275,7 @@ void MPU6050::setAccelerometerPowerOnDelay(uint8_t delay) { * @see MPU6050_RA_MOT_DETECT_CTRL * @see MPU6050_DETECT_FF_COUNT_BIT */ -uint8_t MPU6050::getFreefallDetectionCounterDecrement() { +uint8_t MPU6050_Base::getFreefallDetectionCounterDecrement() { I2Cdev::readBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_FF_COUNT_BIT, MPU6050_DETECT_FF_COUNT_LENGTH, buffer); return buffer[0]; } @@ -2284,7 +2285,7 @@ uint8_t MPU6050::getFreefallDetectionCounterDecrement() { * @see MPU6050_RA_MOT_DETECT_CTRL * @see MPU6050_DETECT_FF_COUNT_BIT */ -void MPU6050::setFreefallDetectionCounterDecrement(uint8_t decrement) { +void MPU6050_Base::setFreefallDetectionCounterDecrement(uint8_t decrement) { I2Cdev::writeBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_FF_COUNT_BIT, MPU6050_DETECT_FF_COUNT_LENGTH, decrement); } /** Get Motion detection counter decrement configuration. @@ -2310,7 +2311,7 @@ void MPU6050::setFreefallDetectionCounterDecrement(uint8_t decrement) { * please refer to Registers 29 to 32. * */ -uint8_t MPU6050::getMotionDetectionCounterDecrement() { +uint8_t MPU6050_Base::getMotionDetectionCounterDecrement() { I2Cdev::readBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_MOT_COUNT_BIT, MPU6050_DETECT_MOT_COUNT_LENGTH, buffer); return buffer[0]; } @@ -2320,7 +2321,7 @@ uint8_t MPU6050::getMotionDetectionCounterDecrement() { * @see MPU6050_RA_MOT_DETECT_CTRL * @see MPU6050_DETECT_MOT_COUNT_BIT */ -void MPU6050::setMotionDetectionCounterDecrement(uint8_t decrement) { +void MPU6050_Base::setMotionDetectionCounterDecrement(uint8_t decrement) { I2Cdev::writeBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_MOT_COUNT_BIT, MPU6050_DETECT_MOT_COUNT_LENGTH, decrement); } @@ -2334,7 +2335,7 @@ void MPU6050::setMotionDetectionCounterDecrement(uint8_t decrement) { * @see MPU6050_RA_USER_CTRL * @see MPU6050_USERCTRL_FIFO_EN_BIT */ -bool MPU6050::getFIFOEnabled() { +bool MPU6050_Base::getFIFOEnabled() { I2Cdev::readBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_EN_BIT, buffer); return buffer[0]; } @@ -2344,7 +2345,7 @@ bool MPU6050::getFIFOEnabled() { * @see MPU6050_RA_USER_CTRL * @see MPU6050_USERCTRL_FIFO_EN_BIT */ -void MPU6050::setFIFOEnabled(bool enabled) { +void MPU6050_Base::setFIFOEnabled(bool enabled) { I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_EN_BIT, enabled); } /** Get I2C Master Mode enabled status. @@ -2358,7 +2359,7 @@ void MPU6050::setFIFOEnabled(bool enabled) { * @see MPU6050_RA_USER_CTRL * @see MPU6050_USERCTRL_I2C_MST_EN_BIT */ -bool MPU6050::getI2CMasterModeEnabled() { +bool MPU6050_Base::getI2CMasterModeEnabled() { I2Cdev::readBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_EN_BIT, buffer); return buffer[0]; } @@ -2368,14 +2369,14 @@ bool MPU6050::getI2CMasterModeEnabled() { * @see MPU6050_RA_USER_CTRL * @see MPU6050_USERCTRL_I2C_MST_EN_BIT */ -void MPU6050::setI2CMasterModeEnabled(bool enabled) { +void MPU6050_Base::setI2CMasterModeEnabled(bool enabled) { I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_EN_BIT, enabled); } /** Switch from I2C to SPI mode (MPU-6000 only) * If this is set, the primary SPI interface will be enabled in place of the * disabled primary I2C interface. */ -void MPU6050::switchSPIEnabled(bool enabled) { +void MPU6050_Base::switchSPIEnabled(bool enabled) { I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_IF_DIS_BIT, enabled); } /** Reset the FIFO. @@ -2384,7 +2385,7 @@ void MPU6050::switchSPIEnabled(bool enabled) { * @see MPU6050_RA_USER_CTRL * @see MPU6050_USERCTRL_FIFO_RESET_BIT */ -void MPU6050::resetFIFO() { +void MPU6050_Base::resetFIFO() { I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_RESET_BIT, true); } /** Reset the I2C Master. @@ -2393,7 +2394,7 @@ void MPU6050::resetFIFO() { * @see MPU6050_RA_USER_CTRL * @see MPU6050_USERCTRL_I2C_MST_RESET_BIT */ -void MPU6050::resetI2CMaster() { +void MPU6050_Base::resetI2CMaster() { I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_RESET_BIT, true); } /** Reset all sensor registers and signal paths. @@ -2408,7 +2409,7 @@ void MPU6050::resetI2CMaster() { * @see MPU6050_RA_USER_CTRL * @see MPU6050_USERCTRL_SIG_COND_RESET_BIT */ -void MPU6050::resetSensors() { +void MPU6050_Base::resetSensors() { I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_SIG_COND_RESET_BIT, true); } @@ -2419,7 +2420,7 @@ void MPU6050::resetSensors() { * @see MPU6050_RA_PWR_MGMT_1 * @see MPU6050_PWR1_DEVICE_RESET_BIT */ -void MPU6050::reset() { +void MPU6050_Base::reset() { I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_DEVICE_RESET_BIT, true); } /** Get sleep mode status. @@ -2433,7 +2434,7 @@ void MPU6050::reset() { * @see MPU6050_RA_PWR_MGMT_1 * @see MPU6050_PWR1_SLEEP_BIT */ -bool MPU6050::getSleepEnabled() { +bool MPU6050_Base::getSleepEnabled() { I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, buffer); return buffer[0]; } @@ -2443,7 +2444,7 @@ bool MPU6050::getSleepEnabled() { * @see MPU6050_RA_PWR_MGMT_1 * @see MPU6050_PWR1_SLEEP_BIT */ -void MPU6050::setSleepEnabled(bool enabled) { +void MPU6050_Base::setSleepEnabled(bool enabled) { I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, enabled); } /** Get wake cycle enabled status. @@ -2454,7 +2455,7 @@ void MPU6050::setSleepEnabled(bool enabled) { * @see MPU6050_RA_PWR_MGMT_1 * @see MPU6050_PWR1_CYCLE_BIT */ -bool MPU6050::getWakeCycleEnabled() { +bool MPU6050_Base::getWakeCycleEnabled() { I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CYCLE_BIT, buffer); return buffer[0]; } @@ -2464,7 +2465,7 @@ bool MPU6050::getWakeCycleEnabled() { * @see MPU6050_RA_PWR_MGMT_1 * @see MPU6050_PWR1_CYCLE_BIT */ -void MPU6050::setWakeCycleEnabled(bool enabled) { +void MPU6050_Base::setWakeCycleEnabled(bool enabled) { I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CYCLE_BIT, enabled); } /** Get temperature sensor enabled status. @@ -2478,7 +2479,7 @@ void MPU6050::setWakeCycleEnabled(bool enabled) { * @see MPU6050_RA_PWR_MGMT_1 * @see MPU6050_PWR1_TEMP_DIS_BIT */ -bool MPU6050::getTempSensorEnabled() { +bool MPU6050_Base::getTempSensorEnabled() { I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_TEMP_DIS_BIT, buffer); return buffer[0] == 0; // 1 is actually disabled here } @@ -2492,7 +2493,7 @@ bool MPU6050::getTempSensorEnabled() { * @see MPU6050_RA_PWR_MGMT_1 * @see MPU6050_PWR1_TEMP_DIS_BIT */ -void MPU6050::setTempSensorEnabled(bool enabled) { +void MPU6050_Base::setTempSensorEnabled(bool enabled) { // 1 is actually disabled here I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_TEMP_DIS_BIT, !enabled); } @@ -2502,7 +2503,7 @@ void MPU6050::setTempSensorEnabled(bool enabled) { * @see MPU6050_PWR1_CLKSEL_BIT * @see MPU6050_PWR1_CLKSEL_LENGTH */ -uint8_t MPU6050::getClockSource() { +uint8_t MPU6050_Base::getClockSource() { I2Cdev::readBits(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, buffer); return buffer[0]; } @@ -2536,7 +2537,7 @@ uint8_t MPU6050::getClockSource() { * @see MPU6050_PWR1_CLKSEL_BIT * @see MPU6050_PWR1_CLKSEL_LENGTH */ -void MPU6050::setClockSource(uint8_t source) { +void MPU6050_Base::setClockSource(uint8_t source) { I2Cdev::writeBits(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, source); } @@ -2565,7 +2566,7 @@ void MPU6050::setClockSource(uint8_t source) { * @return Current wake frequency * @see MPU6050_RA_PWR_MGMT_2 */ -uint8_t MPU6050::getWakeFrequency() { +uint8_t MPU6050_Base::getWakeFrequency() { I2Cdev::readBits(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_LP_WAKE_CTRL_BIT, MPU6050_PWR2_LP_WAKE_CTRL_LENGTH, buffer); return buffer[0]; } @@ -2573,7 +2574,7 @@ uint8_t MPU6050::getWakeFrequency() { * @param frequency New wake frequency * @see MPU6050_RA_PWR_MGMT_2 */ -void MPU6050::setWakeFrequency(uint8_t frequency) { +void MPU6050_Base::setWakeFrequency(uint8_t frequency) { I2Cdev::writeBits(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_LP_WAKE_CTRL_BIT, MPU6050_PWR2_LP_WAKE_CTRL_LENGTH, frequency); } @@ -2583,7 +2584,7 @@ void MPU6050::setWakeFrequency(uint8_t frequency) { * @see MPU6050_RA_PWR_MGMT_2 * @see MPU6050_PWR2_STBY_XA_BIT */ -bool MPU6050::getStandbyXAccelEnabled() { +bool MPU6050_Base::getStandbyXAccelEnabled() { I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XA_BIT, buffer); return buffer[0]; } @@ -2593,7 +2594,7 @@ bool MPU6050::getStandbyXAccelEnabled() { * @see MPU6050_RA_PWR_MGMT_2 * @see MPU6050_PWR2_STBY_XA_BIT */ -void MPU6050::setStandbyXAccelEnabled(bool enabled) { +void MPU6050_Base::setStandbyXAccelEnabled(bool enabled) { I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XA_BIT, enabled); } /** Get Y-axis accelerometer standby enabled status. @@ -2602,7 +2603,7 @@ void MPU6050::setStandbyXAccelEnabled(bool enabled) { * @see MPU6050_RA_PWR_MGMT_2 * @see MPU6050_PWR2_STBY_YA_BIT */ -bool MPU6050::getStandbyYAccelEnabled() { +bool MPU6050_Base::getStandbyYAccelEnabled() { I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YA_BIT, buffer); return buffer[0]; } @@ -2612,7 +2613,7 @@ bool MPU6050::getStandbyYAccelEnabled() { * @see MPU6050_RA_PWR_MGMT_2 * @see MPU6050_PWR2_STBY_YA_BIT */ -void MPU6050::setStandbyYAccelEnabled(bool enabled) { +void MPU6050_Base::setStandbyYAccelEnabled(bool enabled) { I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YA_BIT, enabled); } /** Get Z-axis accelerometer standby enabled status. @@ -2621,7 +2622,7 @@ void MPU6050::setStandbyYAccelEnabled(bool enabled) { * @see MPU6050_RA_PWR_MGMT_2 * @see MPU6050_PWR2_STBY_ZA_BIT */ -bool MPU6050::getStandbyZAccelEnabled() { +bool MPU6050_Base::getStandbyZAccelEnabled() { I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZA_BIT, buffer); return buffer[0]; } @@ -2631,7 +2632,7 @@ bool MPU6050::getStandbyZAccelEnabled() { * @see MPU6050_RA_PWR_MGMT_2 * @see MPU6050_PWR2_STBY_ZA_BIT */ -void MPU6050::setStandbyZAccelEnabled(bool enabled) { +void MPU6050_Base::setStandbyZAccelEnabled(bool enabled) { I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZA_BIT, enabled); } /** Get X-axis gyroscope standby enabled status. @@ -2640,7 +2641,7 @@ void MPU6050::setStandbyZAccelEnabled(bool enabled) { * @see MPU6050_RA_PWR_MGMT_2 * @see MPU6050_PWR2_STBY_XG_BIT */ -bool MPU6050::getStandbyXGyroEnabled() { +bool MPU6050_Base::getStandbyXGyroEnabled() { I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XG_BIT, buffer); return buffer[0]; } @@ -2650,7 +2651,7 @@ bool MPU6050::getStandbyXGyroEnabled() { * @see MPU6050_RA_PWR_MGMT_2 * @see MPU6050_PWR2_STBY_XG_BIT */ -void MPU6050::setStandbyXGyroEnabled(bool enabled) { +void MPU6050_Base::setStandbyXGyroEnabled(bool enabled) { I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XG_BIT, enabled); } /** Get Y-axis gyroscope standby enabled status. @@ -2659,7 +2660,7 @@ void MPU6050::setStandbyXGyroEnabled(bool enabled) { * @see MPU6050_RA_PWR_MGMT_2 * @see MPU6050_PWR2_STBY_YG_BIT */ -bool MPU6050::getStandbyYGyroEnabled() { +bool MPU6050_Base::getStandbyYGyroEnabled() { I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YG_BIT, buffer); return buffer[0]; } @@ -2669,7 +2670,7 @@ bool MPU6050::getStandbyYGyroEnabled() { * @see MPU6050_RA_PWR_MGMT_2 * @see MPU6050_PWR2_STBY_YG_BIT */ -void MPU6050::setStandbyYGyroEnabled(bool enabled) { +void MPU6050_Base::setStandbyYGyroEnabled(bool enabled) { I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YG_BIT, enabled); } /** Get Z-axis gyroscope standby enabled status. @@ -2678,7 +2679,7 @@ void MPU6050::setStandbyYGyroEnabled(bool enabled) { * @see MPU6050_RA_PWR_MGMT_2 * @see MPU6050_PWR2_STBY_ZG_BIT */ -bool MPU6050::getStandbyZGyroEnabled() { +bool MPU6050_Base::getStandbyZGyroEnabled() { I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZG_BIT, buffer); return buffer[0]; } @@ -2688,7 +2689,7 @@ bool MPU6050::getStandbyZGyroEnabled() { * @see MPU6050_RA_PWR_MGMT_2 * @see MPU6050_PWR2_STBY_ZG_BIT */ -void MPU6050::setStandbyZGyroEnabled(bool enabled) { +void MPU6050_Base::setStandbyZGyroEnabled(bool enabled) { I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZG_BIT, enabled); } @@ -2701,7 +2702,7 @@ void MPU6050::setStandbyZGyroEnabled(bool enabled) { * set of sensor data bound to be stored in the FIFO (register 35 and 36). * @return Current FIFO buffer size */ -uint16_t MPU6050::getFIFOCount() { +uint16_t MPU6050_Base::getFIFOCount() { I2Cdev::readBytes(devAddr, MPU6050_RA_FIFO_COUNTH, 2, buffer); return (((uint16_t)buffer[0]) << 8) | buffer[1]; } @@ -2733,11 +2734,11 @@ uint16_t MPU6050::getFIFOCount() { * * @return Byte from FIFO buffer */ -uint8_t MPU6050::getFIFOByte() { +uint8_t MPU6050_Base::getFIFOByte() { I2Cdev::readByte(devAddr, MPU6050_RA_FIFO_R_W, buffer); return buffer[0]; } -void MPU6050::getFIFOBytes(uint8_t *data, uint8_t length) { +void MPU6050_Base::getFIFOBytes(uint8_t *data, uint8_t length) { if(length > 0){ I2Cdev::readBytes(devAddr, MPU6050_RA_FIFO_R_W, length, data); } else { @@ -2749,7 +2750,7 @@ void MPU6050::getFIFOBytes(uint8_t *data, uint8_t length) { * @return Current timeout to get a packet from FIFO buffer * @see MPU6050_FIFO_DEFAULT_TIMEOUT */ -uint32_t MPU6050::getFIFOTimeout() { +uint32_t MPU6050_Base::getFIFOTimeout() { return fifoTimeout; } @@ -2757,7 +2758,7 @@ uint32_t MPU6050::getFIFOTimeout() { * @param New timeout to get a packet from FIFO buffer * @see MPU6050_FIFO_DEFAULT_TIMEOUT */ -void MPU6050::setFIFOTimeout(uint32_t fifoTimeout) { +void MPU6050_Base::setFIFOTimeout(uint32_t fifoTimeout) { this->fifoTimeout = fifoTimeout; } @@ -2768,7 +2769,7 @@ void MPU6050::setFIFOTimeout(uint32_t fifoTimeout) { * 2) when recovering from overflow * 0) when no valid data is available * ================================================================ */ - int8_t MPU6050::GetCurrentFIFOPacket(uint8_t *data, uint8_t length) { // overflow proof + int8_t MPU6050_Base::GetCurrentFIFOPacket(uint8_t *data, uint8_t length) { // overflow proof int16_t fifoC; // This section of code is for when we allowed more than 1 packet to be acquired uint32_t BreakTimer = micros(); @@ -2807,7 +2808,7 @@ void MPU6050::setFIFOTimeout(uint32_t fifoTimeout) { * @see getFIFOByte() * @see MPU6050_RA_FIFO_R_W */ -void MPU6050::setFIFOByte(uint8_t data) { +void MPU6050_Base::setFIFOByte(uint8_t data) { I2Cdev::writeByte(devAddr, MPU6050_RA_FIFO_R_W, data); } @@ -2820,7 +2821,7 @@ void MPU6050::setFIFOByte(uint8_t data) { * @see MPU6050_WHO_AM_I_BIT * @see MPU6050_WHO_AM_I_LENGTH */ -uint8_t MPU6050::getDeviceID() { +uint8_t MPU6050_Base::getDeviceID() { I2Cdev::readBits(devAddr, MPU6050_RA_WHO_AM_I, MPU6050_WHO_AM_I_BIT, MPU6050_WHO_AM_I_LENGTH, buffer); return buffer[0]; } @@ -2833,7 +2834,7 @@ uint8_t MPU6050::getDeviceID() { * @see MPU6050_WHO_AM_I_BIT * @see MPU6050_WHO_AM_I_LENGTH */ -void MPU6050::setDeviceID(uint8_t id) { +void MPU6050_Base::setDeviceID(uint8_t id) { I2Cdev::writeBits(devAddr, MPU6050_RA_WHO_AM_I, MPU6050_WHO_AM_I_BIT, MPU6050_WHO_AM_I_LENGTH, id); } @@ -2841,208 +2842,208 @@ void MPU6050::setDeviceID(uint8_t id) { // XG_OFFS_TC register -uint8_t MPU6050::getOTPBankValid() { +uint8_t MPU6050_Base::getOTPBankValid() { I2Cdev::readBit(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OTP_BNK_VLD_BIT, buffer); return buffer[0]; } -void MPU6050::setOTPBankValid(bool enabled) { +void MPU6050_Base::setOTPBankValid(bool enabled) { I2Cdev::writeBit(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OTP_BNK_VLD_BIT, enabled); } -int8_t MPU6050::getXGyroOffsetTC() { +int8_t MPU6050_Base::getXGyroOffsetTC() { I2Cdev::readBits(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, buffer); return buffer[0]; } -void MPU6050::setXGyroOffsetTC(int8_t offset) { +void MPU6050_Base::setXGyroOffsetTC(int8_t offset) { I2Cdev::writeBits(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset); } // YG_OFFS_TC register -int8_t MPU6050::getYGyroOffsetTC() { +int8_t MPU6050_Base::getYGyroOffsetTC() { I2Cdev::readBits(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, buffer); return buffer[0]; } -void MPU6050::setYGyroOffsetTC(int8_t offset) { +void MPU6050_Base::setYGyroOffsetTC(int8_t offset) { I2Cdev::writeBits(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset); } // ZG_OFFS_TC register -int8_t MPU6050::getZGyroOffsetTC() { +int8_t MPU6050_Base::getZGyroOffsetTC() { I2Cdev::readBits(devAddr, MPU6050_RA_ZG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, buffer); return buffer[0]; } -void MPU6050::setZGyroOffsetTC(int8_t offset) { +void MPU6050_Base::setZGyroOffsetTC(int8_t offset) { I2Cdev::writeBits(devAddr, MPU6050_RA_ZG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset); } // X_FINE_GAIN register -int8_t MPU6050::getXFineGain() { +int8_t MPU6050_Base::getXFineGain() { I2Cdev::readByte(devAddr, MPU6050_RA_X_FINE_GAIN, buffer); return buffer[0]; } -void MPU6050::setXFineGain(int8_t gain) { +void MPU6050_Base::setXFineGain(int8_t gain) { I2Cdev::writeByte(devAddr, MPU6050_RA_X_FINE_GAIN, gain); } // Y_FINE_GAIN register -int8_t MPU6050::getYFineGain() { +int8_t MPU6050_Base::getYFineGain() { I2Cdev::readByte(devAddr, MPU6050_RA_Y_FINE_GAIN, buffer); return buffer[0]; } -void MPU6050::setYFineGain(int8_t gain) { +void MPU6050_Base::setYFineGain(int8_t gain) { I2Cdev::writeByte(devAddr, MPU6050_RA_Y_FINE_GAIN, gain); } // Z_FINE_GAIN register -int8_t MPU6050::getZFineGain() { +int8_t MPU6050_Base::getZFineGain() { I2Cdev::readByte(devAddr, MPU6050_RA_Z_FINE_GAIN, buffer); return buffer[0]; } -void MPU6050::setZFineGain(int8_t gain) { +void MPU6050_Base::setZFineGain(int8_t gain) { I2Cdev::writeByte(devAddr, MPU6050_RA_Z_FINE_GAIN, gain); } // XA_OFFS_* registers -int16_t MPU6050::getXAccelOffset() { +int16_t MPU6050_Base::getXAccelOffset() { uint8_t SaveAddress = ((getDeviceID() < 0x38 )? MPU6050_RA_XA_OFFS_H:0x77); // MPU6050,MPU9150 Vs MPU6500,MPU9250 I2Cdev::readBytes(devAddr, SaveAddress, 2, buffer); return (((int16_t)buffer[0]) << 8) | buffer[1]; } -void MPU6050::setXAccelOffset(int16_t offset) { +void MPU6050_Base::setXAccelOffset(int16_t offset) { uint8_t SaveAddress = ((getDeviceID() < 0x38 )? MPU6050_RA_XA_OFFS_H:0x77); // MPU6050,MPU9150 Vs MPU6500,MPU9250 I2Cdev::writeWord(devAddr, SaveAddress, offset); } // YA_OFFS_* register -int16_t MPU6050::getYAccelOffset() { +int16_t MPU6050_Base::getYAccelOffset() { uint8_t SaveAddress = ((getDeviceID() < 0x38 )? MPU6050_RA_YA_OFFS_H:0x7A); // MPU6050,MPU9150 Vs MPU6500,MPU9250 I2Cdev::readBytes(devAddr, SaveAddress, 2, buffer); return (((int16_t)buffer[0]) << 8) | buffer[1]; } -void MPU6050::setYAccelOffset(int16_t offset) { +void MPU6050_Base::setYAccelOffset(int16_t offset) { uint8_t SaveAddress = ((getDeviceID() < 0x38 )? MPU6050_RA_YA_OFFS_H:0x7A); // MPU6050,MPU9150 Vs MPU6500,MPU9250 I2Cdev::writeWord(devAddr, SaveAddress, offset); } // ZA_OFFS_* register -int16_t MPU6050::getZAccelOffset() { +int16_t MPU6050_Base::getZAccelOffset() { uint8_t SaveAddress = ((getDeviceID() < 0x38 )? MPU6050_RA_ZA_OFFS_H:0x7D); // MPU6050,MPU9150 Vs MPU6500,MPU9250 I2Cdev::readBytes(devAddr, SaveAddress, 2, buffer); return (((int16_t)buffer[0]) << 8) | buffer[1]; } -void MPU6050::setZAccelOffset(int16_t offset) { +void MPU6050_Base::setZAccelOffset(int16_t offset) { uint8_t SaveAddress = ((getDeviceID() < 0x38 )? MPU6050_RA_ZA_OFFS_H:0x7D); // MPU6050,MPU9150 Vs MPU6500,MPU9250 I2Cdev::writeWord(devAddr, SaveAddress, offset); } // XG_OFFS_USR* registers -int16_t MPU6050::getXGyroOffset() { +int16_t MPU6050_Base::getXGyroOffset() { I2Cdev::readBytes(devAddr, MPU6050_RA_XG_OFFS_USRH, 2, buffer); return (((int16_t)buffer[0]) << 8) | buffer[1]; } -void MPU6050::setXGyroOffset(int16_t offset) { +void MPU6050_Base::setXGyroOffset(int16_t offset) { I2Cdev::writeWord(devAddr, MPU6050_RA_XG_OFFS_USRH, offset); } // YG_OFFS_USR* register -int16_t MPU6050::getYGyroOffset() { +int16_t MPU6050_Base::getYGyroOffset() { I2Cdev::readBytes(devAddr, MPU6050_RA_YG_OFFS_USRH, 2, buffer); return (((int16_t)buffer[0]) << 8) | buffer[1]; } -void MPU6050::setYGyroOffset(int16_t offset) { +void MPU6050_Base::setYGyroOffset(int16_t offset) { I2Cdev::writeWord(devAddr, MPU6050_RA_YG_OFFS_USRH, offset); } // ZG_OFFS_USR* register -int16_t MPU6050::getZGyroOffset() { +int16_t MPU6050_Base::getZGyroOffset() { I2Cdev::readBytes(devAddr, MPU6050_RA_ZG_OFFS_USRH, 2, buffer); return (((int16_t)buffer[0]) << 8) | buffer[1]; } -void MPU6050::setZGyroOffset(int16_t offset) { +void MPU6050_Base::setZGyroOffset(int16_t offset) { I2Cdev::writeWord(devAddr, MPU6050_RA_ZG_OFFS_USRH, offset); } // INT_ENABLE register (DMP functions) -bool MPU6050::getIntPLLReadyEnabled() { +bool MPU6050_Base::getIntPLLReadyEnabled() { I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, buffer); return buffer[0]; } -void MPU6050::setIntPLLReadyEnabled(bool enabled) { +void MPU6050_Base::setIntPLLReadyEnabled(bool enabled) { I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, enabled); } -bool MPU6050::getIntDMPEnabled() { +bool MPU6050_Base::getIntDMPEnabled() { I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DMP_INT_BIT, buffer); return buffer[0]; } -void MPU6050::setIntDMPEnabled(bool enabled) { +void MPU6050_Base::setIntDMPEnabled(bool enabled) { I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DMP_INT_BIT, enabled); } // DMP_INT_STATUS -bool MPU6050::getDMPInt5Status() { +bool MPU6050_Base::getDMPInt5Status() { I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_5_BIT, buffer); return buffer[0]; } -bool MPU6050::getDMPInt4Status() { +bool MPU6050_Base::getDMPInt4Status() { I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_4_BIT, buffer); return buffer[0]; } -bool MPU6050::getDMPInt3Status() { +bool MPU6050_Base::getDMPInt3Status() { I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_3_BIT, buffer); return buffer[0]; } -bool MPU6050::getDMPInt2Status() { +bool MPU6050_Base::getDMPInt2Status() { I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_2_BIT, buffer); return buffer[0]; } -bool MPU6050::getDMPInt1Status() { +bool MPU6050_Base::getDMPInt1Status() { I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_1_BIT, buffer); return buffer[0]; } -bool MPU6050::getDMPInt0Status() { +bool MPU6050_Base::getDMPInt0Status() { I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_0_BIT, buffer); return buffer[0]; } // INT_STATUS register (DMP functions) -bool MPU6050::getIntPLLReadyStatus() { +bool MPU6050_Base::getIntPLLReadyStatus() { I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, buffer); return buffer[0]; } -bool MPU6050::getIntDMPStatus() { +bool MPU6050_Base::getIntDMPStatus() { I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_DMP_INT_BIT, buffer); return buffer[0]; } // USER_CTRL register (DMP functions) -bool MPU6050::getDMPEnabled() { +bool MPU6050_Base::getDMPEnabled() { I2Cdev::readBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_EN_BIT, buffer); return buffer[0]; } -void MPU6050::setDMPEnabled(bool enabled) { +void MPU6050_Base::setDMPEnabled(bool enabled) { I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_EN_BIT, enabled); } -void MPU6050::resetDMP() { +void MPU6050_Base::resetDMP() { I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_RESET_BIT, true); } // BANK_SEL register -void MPU6050::setMemoryBank(uint8_t bank, bool prefetchEnabled, bool userBank) { +void MPU6050_Base::setMemoryBank(uint8_t bank, bool prefetchEnabled, bool userBank) { bank &= 0x1F; if (userBank) bank |= 0x20; if (prefetchEnabled) bank |= 0x40; @@ -3051,20 +3052,20 @@ void MPU6050::setMemoryBank(uint8_t bank, bool prefetchEnabled, bool userBank) { // MEM_START_ADDR register -void MPU6050::setMemoryStartAddress(uint8_t address) { +void MPU6050_Base::setMemoryStartAddress(uint8_t address) { I2Cdev::writeByte(devAddr, MPU6050_RA_MEM_START_ADDR, address); } // MEM_R_W register -uint8_t MPU6050::readMemoryByte() { +uint8_t MPU6050_Base::readMemoryByte() { I2Cdev::readByte(devAddr, MPU6050_RA_MEM_R_W, buffer); return buffer[0]; } -void MPU6050::writeMemoryByte(uint8_t data) { +void MPU6050_Base::writeMemoryByte(uint8_t data) { I2Cdev::writeByte(devAddr, MPU6050_RA_MEM_R_W, data); } -void MPU6050::readMemoryBlock(uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address) { +void MPU6050_Base::readMemoryBlock(uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address) { setMemoryBank(bank); setMemoryStartAddress(address); uint8_t chunkSize; @@ -3095,7 +3096,7 @@ void MPU6050::readMemoryBlock(uint8_t *data, uint16_t dataSize, uint8_t bank, ui } } } -bool MPU6050::writeMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address, bool verify, bool useProgMem) { +bool MPU6050_Base::writeMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address, bool verify, bool useProgMem) { setMemoryBank(bank); setMemoryStartAddress(address); uint8_t chunkSize; @@ -3171,10 +3172,10 @@ bool MPU6050::writeMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t b if (useProgMem) free(progBuffer); return true; } -bool MPU6050::writeProgMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address, bool verify) { +bool MPU6050_Base::writeProgMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address, bool verify) { return writeMemoryBlock(data, dataSize, bank, address, verify, true); } -bool MPU6050::writeDMPConfigurationSet(const uint8_t *data, uint16_t dataSize, bool useProgMem) { +bool MPU6050_Base::writeDMPConfigurationSet(const uint8_t *data, uint16_t dataSize, bool useProgMem) { uint8_t *progBuffer = 0; uint8_t success, special; uint16_t i, j; @@ -3250,27 +3251,27 @@ bool MPU6050::writeDMPConfigurationSet(const uint8_t *data, uint16_t dataSize, b if (useProgMem) free(progBuffer); return true; } -bool MPU6050::writeProgDMPConfigurationSet(const uint8_t *data, uint16_t dataSize) { +bool MPU6050_Base::writeProgDMPConfigurationSet(const uint8_t *data, uint16_t dataSize) { return writeDMPConfigurationSet(data, dataSize, true); } // DMP_CFG_1 register -uint8_t MPU6050::getDMPConfig1() { +uint8_t MPU6050_Base::getDMPConfig1() { I2Cdev::readByte(devAddr, MPU6050_RA_DMP_CFG_1, buffer); return buffer[0]; } -void MPU6050::setDMPConfig1(uint8_t config) { +void MPU6050_Base::setDMPConfig1(uint8_t config) { I2Cdev::writeByte(devAddr, MPU6050_RA_DMP_CFG_1, config); } // DMP_CFG_2 register -uint8_t MPU6050::getDMPConfig2() { +uint8_t MPU6050_Base::getDMPConfig2() { I2Cdev::readByte(devAddr, MPU6050_RA_DMP_CFG_2, buffer); return buffer[0]; } -void MPU6050::setDMPConfig2(uint8_t config) { +void MPU6050_Base::setDMPConfig2(uint8_t config) { I2Cdev::writeByte(devAddr, MPU6050_RA_DMP_CFG_2, config); } @@ -3281,7 +3282,7 @@ void MPU6050::setDMPConfig2(uint8_t config) { /** @brief Fully calibrate Gyro from ZERO in about 6-7 Loops 600-700 readings */ -void MPU6050::CalibrateGyro(uint8_t Loops ) { +void MPU6050_Base::CalibrateGyro(uint8_t Loops ) { double kP = 0.3; double kI = 90; float x; @@ -3295,7 +3296,7 @@ void MPU6050::CalibrateGyro(uint8_t Loops ) { /** @brief Fully calibrate Accel from ZERO in about 6-7 Loops 600-700 readings */ -void MPU6050::CalibrateAccel(uint8_t Loops ) { +void MPU6050_Base::CalibrateAccel(uint8_t Loops ) { float kP = 0.3; float kI = 20; @@ -3306,7 +3307,7 @@ void MPU6050::CalibrateAccel(uint8_t Loops ) { PID( 0x3B, kP, kI, Loops); } -void MPU6050::PID(uint8_t ReadAddress, float kP,float kI, uint8_t Loops){ +void MPU6050_Base::PID(uint8_t ReadAddress, float kP,float kI, uint8_t Loops){ uint8_t SaveAddress = (ReadAddress == 0x3B)?((getDeviceID() < 0x38 )? 0x06:0x77):0x13; int16_t Data; @@ -3370,7 +3371,7 @@ void MPU6050::PID(uint8_t ReadAddress, float kP,float kI, uint8_t Loops){ resetDMP(); } -void MPU6050::PrintActiveOffsets() { +void MPU6050_Base::PrintActiveOffsets() { uint8_t AOffsetRegister = (getDeviceID() < 0x38 )? MPU6050_RA_XA_OFFS_H:0x77; int16_t Data[3]; //Serial.print(F("Offset Register 0x")); diff --git a/Arduino/MPU6050/MPU6050.h b/Arduino/MPU6050/MPU6050.h index 53470aac..36a36973 100644 --- a/Arduino/MPU6050/MPU6050.h +++ b/Arduino/MPU6050/MPU6050.h @@ -435,11 +435,9 @@ THE SOFTWARE. #define MPU6050_FIFO_DEFAULT_TIMEOUT 11000 -// note: DMP code memory blocks defined at end of header file - -class MPU6050 { +class MPU6050_Base { public: - MPU6050(uint8_t address=MPU6050_DEFAULT_ADDRESS); + MPU6050_Base(uint8_t address=MPU6050_DEFAULT_ADDRESS); void initialize(); bool testConnection(); @@ -1035,7 +1033,7 @@ class MPU6050 { uint16_t dmpGetFIFOPacketSize(); #endif - private: + protected: uint8_t devAddr; uint8_t buffer[14]; uint32_t fifoTimeout = MPU6050_FIFO_DEFAULT_TIMEOUT; From 8eda2ce663c05c7b490778fadf1a1f5848e1b268 Mon Sep 17 00:00:00 2001 From: Jeff Rowberg Date: Mon, 27 Sep 2021 21:59:03 -0400 Subject: [PATCH 275/335] Split all DMP implementations out into subclasses --- Arduino/MPU6050/MPU6050.h | 208 +--- .../MPU6050/MPU6050_6Axis_MotionApps20.cpp | 616 +++++++++++ Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h | 687 ++----------- ...6_12.h => MPU6050_6Axis_MotionApps612.cpp} | 25 +- Arduino/MPU6050/MPU6050_6Axis_MotionApps612.h | 151 +++ .../MPU6050/MPU6050_9Axis_MotionApps41.cpp | 887 ++++++++++++++++ Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h | 958 ++---------------- .../MPU6050_DMP6_using_DMP_V6.12.ino | 2 +- 8 files changed, 1883 insertions(+), 1651 deletions(-) create mode 100644 Arduino/MPU6050/MPU6050_6Axis_MotionApps20.cpp rename Arduino/MPU6050/{MPU6050_6Axis_MotionApps_V6_12.h => MPU6050_6Axis_MotionApps612.cpp} (97%) create mode 100644 Arduino/MPU6050/MPU6050_6Axis_MotionApps612.h create mode 100644 Arduino/MPU6050/MPU6050_9Axis_MotionApps41.cpp diff --git a/Arduino/MPU6050/MPU6050.h b/Arduino/MPU6050/MPU6050.h index 36a36973..45d05059 100644 --- a/Arduino/MPU6050/MPU6050.h +++ b/Arduino/MPU6050/MPU6050.h @@ -4,6 +4,7 @@ // Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib // // Changelog: +// 2021/09/27 - split implementations out of header files, finally // ... - ongoing debug release // NOTE: THIS IS ONLY A PARIAL RELEASE. THIS DEVICE CLASS IS CURRENTLY UNDERGOING ACTIVE @@ -38,6 +39,7 @@ THE SOFTWARE. #define _MPU6050_H_ #include "I2Cdev.h" +#include "helper_3dmath.h" // supporting link: http://forum.arduino.cc/index.php?&topic=143444.msg1079517#msg1079517 // also: http://forum.arduino.cc/index.php?&topic=141571.msg1062899#msg1062899s @@ -831,216 +833,10 @@ class MPU6050_Base { void PID(uint8_t ReadAddress, float kP,float kI, uint8_t Loops); // Does the math void PrintActiveOffsets(); // See the results of the Calibration - - - // special methods for MotionApps 2.0 implementation - #ifdef MPU6050_INCLUDE_DMP_MOTIONAPPS20 - - uint8_t dmpInitialize(); - bool dmpPacketAvailable(); - - uint8_t dmpSetFIFORate(uint8_t fifoRate); - uint8_t dmpGetFIFORate(); - uint8_t dmpGetSampleStepSizeMS(); - uint8_t dmpGetSampleFrequency(); - int32_t dmpDecodeTemperature(int8_t tempReg); - - // Register callbacks after a packet of FIFO data is processed - //uint8_t dmpRegisterFIFORateProcess(inv_obj_func func, int16_t priority); - //uint8_t dmpUnregisterFIFORateProcess(inv_obj_func func); - uint8_t dmpRunFIFORateProcesses(); - - // Setup FIFO for various output - uint8_t dmpSendQuaternion(uint_fast16_t accuracy); - uint8_t dmpSendGyro(uint_fast16_t elements, uint_fast16_t accuracy); - uint8_t dmpSendAccel(uint_fast16_t elements, uint_fast16_t accuracy); - uint8_t dmpSendLinearAccel(uint_fast16_t elements, uint_fast16_t accuracy); - uint8_t dmpSendLinearAccelInWorld(uint_fast16_t elements, uint_fast16_t accuracy); - uint8_t dmpSendControlData(uint_fast16_t elements, uint_fast16_t accuracy); - uint8_t dmpSendSensorData(uint_fast16_t elements, uint_fast16_t accuracy); - uint8_t dmpSendExternalSensorData(uint_fast16_t elements, uint_fast16_t accuracy); - uint8_t dmpSendGravity(uint_fast16_t elements, uint_fast16_t accuracy); - uint8_t dmpSendPacketNumber(uint_fast16_t accuracy); - uint8_t dmpSendQuantizedAccel(uint_fast16_t elements, uint_fast16_t accuracy); - uint8_t dmpSendEIS(uint_fast16_t elements, uint_fast16_t accuracy); - - // Get Fixed Point data from FIFO - uint8_t dmpGetAccel(int32_t *data, const uint8_t* packet=0); - uint8_t dmpGetAccel(int16_t *data, const uint8_t* packet=0); - uint8_t dmpGetAccel(VectorInt16 *v, const uint8_t* packet=0); - uint8_t dmpGetQuaternion(int32_t *data, const uint8_t* packet=0); - uint8_t dmpGetQuaternion(int16_t *data, const uint8_t* packet=0); - uint8_t dmpGetQuaternion(Quaternion *q, const uint8_t* packet=0); - uint8_t dmpGet6AxisQuaternion(int32_t *data, const uint8_t* packet=0); - uint8_t dmpGet6AxisQuaternion(int16_t *data, const uint8_t* packet=0); - uint8_t dmpGet6AxisQuaternion(Quaternion *q, const uint8_t* packet=0); - uint8_t dmpGetRelativeQuaternion(int32_t *data, const uint8_t* packet=0); - uint8_t dmpGetRelativeQuaternion(int16_t *data, const uint8_t* packet=0); - uint8_t dmpGetRelativeQuaternion(Quaternion *data, const uint8_t* packet=0); - uint8_t dmpGetGyro(int32_t *data, const uint8_t* packet=0); - uint8_t dmpGetGyro(int16_t *data, const uint8_t* packet=0); - uint8_t dmpGetGyro(VectorInt16 *v, const uint8_t* packet=0); - uint8_t dmpSetLinearAccelFilterCoefficient(float coef); - uint8_t dmpGetLinearAccel(int32_t *data, const uint8_t* packet=0); - uint8_t dmpGetLinearAccel(int16_t *data, const uint8_t* packet=0); - uint8_t dmpGetLinearAccel(VectorInt16 *v, const uint8_t* packet=0); - uint8_t dmpGetLinearAccel(VectorInt16 *v, VectorInt16 *vRaw, VectorFloat *gravity); - uint8_t dmpGetLinearAccelInWorld(int32_t *data, const uint8_t* packet=0); - uint8_t dmpGetLinearAccelInWorld(int16_t *data, const uint8_t* packet=0); - uint8_t dmpGetLinearAccelInWorld(VectorInt16 *v, const uint8_t* packet=0); - uint8_t dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Quaternion *q); - uint8_t dmpGetGyroAndAccelSensor(int32_t *data, const uint8_t* packet=0); - uint8_t dmpGetGyroAndAccelSensor(int16_t *data, const uint8_t* packet=0); - uint8_t dmpGetGyroAndAccelSensor(VectorInt16 *g, VectorInt16 *a, const uint8_t* packet=0); - uint8_t dmpGetGyroSensor(int32_t *data, const uint8_t* packet=0); - uint8_t dmpGetGyroSensor(int16_t *data, const uint8_t* packet=0); - uint8_t dmpGetGyroSensor(VectorInt16 *v, const uint8_t* packet=0); - uint8_t dmpGetControlData(int32_t *data, const uint8_t* packet=0); - uint8_t dmpGetTemperature(int32_t *data, const uint8_t* packet=0); - uint8_t dmpGetGravity(int32_t *data, const uint8_t* packet=0); - uint8_t dmpGetGravity(int16_t *data, const uint8_t* packet=0); - uint8_t dmpGetGravity(VectorInt16 *v, const uint8_t* packet=0); - uint8_t dmpGetGravity(VectorFloat *v, Quaternion *q); - uint8_t dmpGetUnquantizedAccel(int32_t *data, const uint8_t* packet=0); - uint8_t dmpGetUnquantizedAccel(int16_t *data, const uint8_t* packet=0); - uint8_t dmpGetUnquantizedAccel(VectorInt16 *v, const uint8_t* packet=0); - uint8_t dmpGetQuantizedAccel(int32_t *data, const uint8_t* packet=0); - uint8_t dmpGetQuantizedAccel(int16_t *data, const uint8_t* packet=0); - uint8_t dmpGetQuantizedAccel(VectorInt16 *v, const uint8_t* packet=0); - uint8_t dmpGetExternalSensorData(int32_t *data, uint16_t size, const uint8_t* packet=0); - uint8_t dmpGetEIS(int32_t *data, const uint8_t* packet=0); - - uint8_t dmpGetEuler(float *data, Quaternion *q); - uint8_t dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity); - - // Get Floating Point data from FIFO - uint8_t dmpGetAccelFloat(float *data, const uint8_t* packet=0); - uint8_t dmpGetQuaternionFloat(float *data, const uint8_t* packet=0); - - uint8_t dmpProcessFIFOPacket(const unsigned char *dmpData); - uint8_t dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *processed=NULL); - - uint8_t dmpSetFIFOProcessedCallback(void (*func) (void)); - - uint8_t dmpInitFIFOParam(); - uint8_t dmpCloseFIFO(); - uint8_t dmpSetGyroDataSource(uint8_t source); - uint8_t dmpDecodeQuantizedAccel(); - uint32_t dmpGetGyroSumOfSquare(); - uint32_t dmpGetAccelSumOfSquare(); - void dmpOverrideQuaternion(long *q); - uint16_t dmpGetFIFOPacketSize(); - uint8_t dmpGetCurrentFIFOPacket(uint8_t *data); // overflow proof - #endif - - // special methods for MotionApps 4.1 implementation - #ifdef MPU6050_INCLUDE_DMP_MOTIONAPPS41 - - uint8_t dmpInitialize(); - bool dmpPacketAvailable(); - - uint8_t dmpSetFIFORate(uint8_t fifoRate); - uint8_t dmpGetFIFORate(); - uint8_t dmpGetSampleStepSizeMS(); - uint8_t dmpGetSampleFrequency(); - int32_t dmpDecodeTemperature(int8_t tempReg); - - // Register callbacks after a packet of FIFO data is processed - //uint8_t dmpRegisterFIFORateProcess(inv_obj_func func, int16_t priority); - //uint8_t dmpUnregisterFIFORateProcess(inv_obj_func func); - uint8_t dmpRunFIFORateProcesses(); - - // Setup FIFO for various output - uint8_t dmpSendQuaternion(uint_fast16_t accuracy); - uint8_t dmpSendGyro(uint_fast16_t elements, uint_fast16_t accuracy); - uint8_t dmpSendAccel(uint_fast16_t elements, uint_fast16_t accuracy); - uint8_t dmpSendLinearAccel(uint_fast16_t elements, uint_fast16_t accuracy); - uint8_t dmpSendLinearAccelInWorld(uint_fast16_t elements, uint_fast16_t accuracy); - uint8_t dmpSendControlData(uint_fast16_t elements, uint_fast16_t accuracy); - uint8_t dmpSendSensorData(uint_fast16_t elements, uint_fast16_t accuracy); - uint8_t dmpSendExternalSensorData(uint_fast16_t elements, uint_fast16_t accuracy); - uint8_t dmpSendGravity(uint_fast16_t elements, uint_fast16_t accuracy); - uint8_t dmpSendPacketNumber(uint_fast16_t accuracy); - uint8_t dmpSendQuantizedAccel(uint_fast16_t elements, uint_fast16_t accuracy); - uint8_t dmpSendEIS(uint_fast16_t elements, uint_fast16_t accuracy); - - // Get Fixed Point data from FIFO - uint8_t dmpGetAccel(int32_t *data, const uint8_t* packet=0); - uint8_t dmpGetAccel(int16_t *data, const uint8_t* packet=0); - uint8_t dmpGetAccel(VectorInt16 *v, const uint8_t* packet=0); - uint8_t dmpGetQuaternion(int32_t *data, const uint8_t* packet=0); - uint8_t dmpGetQuaternion(int16_t *data, const uint8_t* packet=0); - uint8_t dmpGetQuaternion(Quaternion *q, const uint8_t* packet=0); - uint8_t dmpGet6AxisQuaternion(int32_t *data, const uint8_t* packet=0); - uint8_t dmpGet6AxisQuaternion(int16_t *data, const uint8_t* packet=0); - uint8_t dmpGet6AxisQuaternion(Quaternion *q, const uint8_t* packet=0); - uint8_t dmpGetRelativeQuaternion(int32_t *data, const uint8_t* packet=0); - uint8_t dmpGetRelativeQuaternion(int16_t *data, const uint8_t* packet=0); - uint8_t dmpGetRelativeQuaternion(Quaternion *data, const uint8_t* packet=0); - uint8_t dmpGetGyro(int32_t *data, const uint8_t* packet=0); - uint8_t dmpGetGyro(int16_t *data, const uint8_t* packet=0); - uint8_t dmpGetGyro(VectorInt16 *v, const uint8_t* packet=0); - uint8_t dmpGetMag(int16_t *data, const uint8_t* packet=0); - uint8_t dmpSetLinearAccelFilterCoefficient(float coef); - uint8_t dmpGetLinearAccel(int32_t *data, const uint8_t* packet=0); - uint8_t dmpGetLinearAccel(int16_t *data, const uint8_t* packet=0); - uint8_t dmpGetLinearAccel(VectorInt16 *v, const uint8_t* packet=0); - uint8_t dmpGetLinearAccel(VectorInt16 *v, VectorInt16 *vRaw, VectorFloat *gravity); - uint8_t dmpGetLinearAccelInWorld(int32_t *data, const uint8_t* packet=0); - uint8_t dmpGetLinearAccelInWorld(int16_t *data, const uint8_t* packet=0); - uint8_t dmpGetLinearAccelInWorld(VectorInt16 *v, const uint8_t* packet=0); - uint8_t dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Quaternion *q); - uint8_t dmpGetGyroAndAccelSensor(int32_t *data, const uint8_t* packet=0); - uint8_t dmpGetGyroAndAccelSensor(int16_t *data, const uint8_t* packet=0); - uint8_t dmpGetGyroAndAccelSensor(VectorInt16 *g, VectorInt16 *a, const uint8_t* packet=0); - uint8_t dmpGetGyroSensor(int32_t *data, const uint8_t* packet=0); - uint8_t dmpGetGyroSensor(int16_t *data, const uint8_t* packet=0); - uint8_t dmpGetGyroSensor(VectorInt16 *v, const uint8_t* packet=0); - uint8_t dmpGetControlData(int32_t *data, const uint8_t* packet=0); - uint8_t dmpGetTemperature(int32_t *data, const uint8_t* packet=0); - uint8_t dmpGetGravity(int32_t *data, const uint8_t* packet=0); - uint8_t dmpGetGravity(int16_t *data, const uint8_t* packet=0); - uint8_t dmpGetGravity(VectorInt16 *v, const uint8_t* packet=0); - uint8_t dmpGetGravity(VectorFloat *v, Quaternion *q); - uint8_t dmpGetUnquantizedAccel(int32_t *data, const uint8_t* packet=0); - uint8_t dmpGetUnquantizedAccel(int16_t *data, const uint8_t* packet=0); - uint8_t dmpGetUnquantizedAccel(VectorInt16 *v, const uint8_t* packet=0); - uint8_t dmpGetQuantizedAccel(int32_t *data, const uint8_t* packet=0); - uint8_t dmpGetQuantizedAccel(int16_t *data, const uint8_t* packet=0); - uint8_t dmpGetQuantizedAccel(VectorInt16 *v, const uint8_t* packet=0); - uint8_t dmpGetExternalSensorData(int32_t *data, uint16_t size, const uint8_t* packet=0); - uint8_t dmpGetEIS(int32_t *data, const uint8_t* packet=0); - - uint8_t dmpGetEuler(float *data, Quaternion *q); - uint8_t dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity); - - // Get Floating Point data from FIFO - uint8_t dmpGetAccelFloat(float *data, const uint8_t* packet=0); - uint8_t dmpGetQuaternionFloat(float *data, const uint8_t* packet=0); - - uint8_t dmpProcessFIFOPacket(const unsigned char *dmpData); - uint8_t dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *processed=NULL); - - uint8_t dmpSetFIFOProcessedCallback(void (*func) (void)); - - uint8_t dmpInitFIFOParam(); - uint8_t dmpCloseFIFO(); - uint8_t dmpSetGyroDataSource(uint8_t source); - uint8_t dmpDecodeQuantizedAccel(); - uint32_t dmpGetGyroSumOfSquare(); - uint32_t dmpGetAccelSumOfSquare(); - void dmpOverrideQuaternion(long *q); - uint16_t dmpGetFIFOPacketSize(); - #endif - protected: uint8_t devAddr; uint8_t buffer[14]; uint32_t fifoTimeout = MPU6050_FIFO_DEFAULT_TIMEOUT; - #if defined(MPU6050_INCLUDE_DMP_MOTIONAPPS20) or defined(MPU6050_INCLUDE_DMP_MOTIONAPPS41) - uint8_t *dmpPacketBuffer; - uint16_t dmpPacketSize; - #endif }; #endif /* _MPU6050_H_ */ diff --git a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.cpp b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.cpp new file mode 100644 index 00000000..3a896745 --- /dev/null +++ b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.cpp @@ -0,0 +1,616 @@ +// I2Cdev library collection - MPU6050 I2C device class, 6-axis MotionApps 2.0 implementation +// Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00) +// 5/20/2013 by Jeff Rowberg +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// 2021/09/27 - split implementations out of header files, finally +// 2019/07/08 - merged all DMP Firmware configuration items into the dmpMemory array +// - Simplified dmpInitialize() to accomidate the dmpmemory array alterations + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2021 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +// MotionApps 2.0 DMP implementation, built using the MPU-6050EVB evaluation board +#define MPU6050_INCLUDE_DMP_MOTIONAPPS20 + +#include "MPU6050_6Axis_MotionApps20.h" + +// Tom Carpenter's conditional PROGMEM code +// http://forum.arduino.cc/index.php?topic=129407.0 +#ifdef __AVR__ + #include +#elif defined(ESP32) + #include +#else + // Teensy 3.0 library conditional PROGMEM code from Paul Stoffregen + #ifndef __PGMSPACE_H_ + #define __PGMSPACE_H_ 1 + #include + + #define PROGMEM + #define PGM_P const char * + #define PSTR(str) (str) + #define F(x) x + + typedef void prog_void; + typedef char prog_char; + typedef unsigned char prog_uchar; + typedef int8_t prog_int8_t; + typedef uint8_t prog_uint8_t; + typedef int16_t prog_int16_t; + typedef uint16_t prog_uint16_t; + typedef int32_t prog_int32_t; + typedef uint32_t prog_uint32_t; + + #define strcpy_P(dest, src) strcpy((dest), (src)) + #define strcat_P(dest, src) strcat((dest), (src)) + #define strcmp_P(a, b) strcmp((a), (b)) + + #define pgm_read_byte(addr) (*(const unsigned char *)(addr)) + #define pgm_read_word(addr) (*(const unsigned short *)(addr)) + #define pgm_read_dword(addr) (*(const unsigned long *)(addr)) + #define pgm_read_float(addr) (*(const float *)(addr)) + + #define pgm_read_byte_near(addr) pgm_read_byte(addr) + #define pgm_read_word_near(addr) pgm_read_word(addr) + #define pgm_read_dword_near(addr) pgm_read_dword(addr) + #define pgm_read_float_near(addr) pgm_read_float(addr) + #define pgm_read_byte_far(addr) pgm_read_byte(addr) + #define pgm_read_word_far(addr) pgm_read_word(addr) + #define pgm_read_dword_far(addr) pgm_read_dword(addr) + #define pgm_read_float_far(addr) pgm_read_float(addr) + #endif +#endif + +/* Source is from the InvenSense MotionApps v2 demo code. Original source is + * unavailable, unless you happen to be amazing as decompiling binary by + * hand (in which case, please contact me, and I'm totally serious). + * + * Also, I'd like to offer many, many thanks to Noah Zerkin for all of the + * DMP reverse-engineering he did to help make this bit of wizardry + * possible. + */ + +// NOTE! Enabling DEBUG adds about 3.3kB to the flash program size. +// Debug output is now working even on ATMega328P MCUs (e.g. Arduino Uno) +// after moving string constants to flash memory storage using the F() +// compiler macro (Arduino IDE 1.0+ required). + +//#define DEBUG +#ifdef DEBUG + #define DEBUG_PRINT(x) Serial.print(x) + #define DEBUG_PRINTF(x, y) Serial.print(x, y) + #define DEBUG_PRINTLN(x) Serial.println(x) + #define DEBUG_PRINTLNF(x, y) Serial.println(x, y) +#else + #define DEBUG_PRINT(x) + #define DEBUG_PRINTF(x, y) + #define DEBUG_PRINTLN(x) + #define DEBUG_PRINTLNF(x, y) +#endif + +#define MPU6050_DMP_CODE_SIZE 1929 // dmpMemory[] +#define MPU6050_DMP_CONFIG_SIZE 192 // dmpConfig[] +#define MPU6050_DMP_UPDATES_SIZE 47 // dmpUpdates[] + +/* ================================================================================================ * + | Default MotionApps v2.0 42-byte FIFO packet structure: | + | | + | [QUAT W][ ][QUAT X][ ][QUAT Y][ ][QUAT Z][ ][GYRO X][ ][GYRO Y][ ] | + | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | + | | + | [GYRO Z][ ][ACC X ][ ][ACC Y ][ ][ACC Z ][ ][ ] | + | 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | + * ================================================================================================ */ + +// this block of memory gets written to the MPU on start-up, and it seems +// to be volatile memory, so it has to be done each time (it only takes ~1 +// second though) + +// I Only Changed this by applying all the configuration data and capturing it before startup: +// *** this is a capture of the DMP Firmware after all the messy changes were made so we can just load it +static const unsigned char dmpMemory[MPU6050_DMP_CODE_SIZE] PROGMEM = { + /* bank # 0 */ + 0xFB, 0x00, 0x00, 0x3E, 0x00, 0x0B, 0x00, 0x36, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x65, 0x00, 0x54, 0xFF, 0xEF, 0x00, 0x00, 0xFA, 0x80, 0x00, 0x0B, 0x12, 0x82, 0x00, 0x01, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x28, 0x00, 0x00, 0xFF, 0xFF, 0x45, 0x81, 0xFF, 0xFF, 0xFA, 0x72, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0xE8, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x7F, 0xFF, 0xFF, 0xFE, 0x80, 0x01, + 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0xCB, 0x47, 0xA2, 0x20, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, + 0x41, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x2A, 0x00, 0x00, 0x16, 0x55, 0x00, 0x00, 0x21, 0x82, + 0xFD, 0x87, 0x26, 0x50, 0xFD, 0x80, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x05, 0x80, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x6F, 0x00, 0x02, 0x65, 0x32, 0x00, 0x00, 0x5E, 0xC0, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFB, 0x8C, 0x6F, 0x5D, 0xFD, 0x5D, 0x08, 0xD9, 0x00, 0x7C, 0x73, 0x3B, 0x00, 0x6C, 0x12, 0xCC, + 0x32, 0x00, 0x13, 0x9D, 0x32, 0x00, 0xD0, 0xD6, 0x32, 0x00, 0x08, 0x00, 0x40, 0x00, 0x01, 0xF4, + 0xFF, 0xE6, 0x80, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0xD6, 0x00, 0x00, 0x27, 0x10, + /* bank # 1 */ + 0xFB, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFA, 0x36, 0xFF, 0xBC, 0x30, 0x8E, 0x00, 0x05, 0xFB, 0xF0, 0xFF, 0xD9, 0x5B, 0xC8, + 0xFF, 0xD0, 0x9A, 0xBE, 0x00, 0x00, 0x10, 0xA9, 0xFF, 0xF4, 0x1E, 0xB2, 0x00, 0xCE, 0xBB, 0xF7, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x0C, + 0xFF, 0xC2, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0xCF, 0x80, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x14, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x09, 0x23, 0xA1, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x3F, 0x68, 0xB6, 0x79, 0x35, 0x28, 0xBC, 0xC6, 0x7E, 0xD1, 0x6C, + 0x80, 0x00, 0xFF, 0xFF, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB2, 0x6A, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, + 0x00, 0x00, 0x25, 0x4D, 0x00, 0x2F, 0x70, 0x6D, 0x00, 0x00, 0x05, 0xAE, 0x00, 0x0C, 0x02, 0xD0, + /* bank # 2 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x54, 0xFF, 0xEF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x44, 0x00, 0x01, 0x00, 0x05, 0x8B, 0xC1, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0xFF, 0xEF, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* bank # 3 */ + 0xD8, 0xDC, 0xBA, 0xA2, 0xF1, 0xDE, 0xB2, 0xB8, 0xB4, 0xA8, 0x81, 0x91, 0xF7, 0x4A, 0x90, 0x7F, + 0x91, 0x6A, 0xF3, 0xF9, 0xDB, 0xA8, 0xF9, 0xB0, 0xBA, 0xA0, 0x80, 0xF2, 0xCE, 0x81, 0xF3, 0xC2, + 0xF1, 0xC1, 0xF2, 0xC3, 0xF3, 0xCC, 0xA2, 0xB2, 0x80, 0xF1, 0xC6, 0xD8, 0x80, 0xBA, 0xA7, 0xDF, + 0xDF, 0xDF, 0xF2, 0xA7, 0xC3, 0xCB, 0xC5, 0xB6, 0xF0, 0x87, 0xA2, 0x94, 0x24, 0x48, 0x70, 0x3C, + 0x95, 0x40, 0x68, 0x34, 0x58, 0x9B, 0x78, 0xA2, 0xF1, 0x83, 0x92, 0x2D, 0x55, 0x7D, 0xD8, 0xB1, + 0xB4, 0xB8, 0xA1, 0xD0, 0x91, 0x80, 0xF2, 0x70, 0xF3, 0x70, 0xF2, 0x7C, 0x80, 0xA8, 0xF1, 0x01, + 0xB0, 0x98, 0x87, 0xD9, 0x43, 0xD8, 0x86, 0xC9, 0x88, 0xBA, 0xA1, 0xF2, 0x0E, 0xB8, 0x97, 0x80, + 0xF1, 0xA9, 0xDF, 0xDF, 0xDF, 0xAA, 0xDF, 0xDF, 0xDF, 0xF2, 0xAA, 0x4C, 0xCD, 0x6C, 0xA9, 0x0C, + 0xC9, 0x2C, 0x97, 0x97, 0x97, 0x97, 0xF1, 0xA9, 0x89, 0x26, 0x46, 0x66, 0xB0, 0xB4, 0xBA, 0x80, + 0xAC, 0xDE, 0xF2, 0xCA, 0xF1, 0xB2, 0x8C, 0x02, 0xA9, 0xB6, 0x98, 0x00, 0x89, 0x0E, 0x16, 0x1E, + 0xB8, 0xA9, 0xB4, 0x99, 0x2C, 0x54, 0x7C, 0xB0, 0x8A, 0xA8, 0x96, 0x36, 0x56, 0x76, 0xF1, 0xB9, + 0xAF, 0xB4, 0xB0, 0x83, 0xC0, 0xB8, 0xA8, 0x97, 0x11, 0xB1, 0x8F, 0x98, 0xB9, 0xAF, 0xF0, 0x24, + 0x08, 0x44, 0x10, 0x64, 0x18, 0xF1, 0xA3, 0x29, 0x55, 0x7D, 0xAF, 0x83, 0xB5, 0x93, 0xAF, 0xF0, + 0x00, 0x28, 0x50, 0xF1, 0xA3, 0x86, 0x9F, 0x61, 0xA6, 0xDA, 0xDE, 0xDF, 0xD9, 0xFA, 0xA3, 0x86, + 0x96, 0xDB, 0x31, 0xA6, 0xD9, 0xF8, 0xDF, 0xBA, 0xA6, 0x8F, 0xC2, 0xC5, 0xC7, 0xB2, 0x8C, 0xC1, + 0xB8, 0xA2, 0xDF, 0xDF, 0xDF, 0xA3, 0xDF, 0xDF, 0xDF, 0xD8, 0xD8, 0xF1, 0xB8, 0xA8, 0xB2, 0x86, + /* bank # 4 */ + 0xB4, 0x98, 0x0D, 0x35, 0x5D, 0xB8, 0xAA, 0x98, 0xB0, 0x87, 0x2D, 0x35, 0x3D, 0xB2, 0xB6, 0xBA, + 0xAF, 0x8C, 0x96, 0x19, 0x8F, 0x9F, 0xA7, 0x0E, 0x16, 0x1E, 0xB4, 0x9A, 0xB8, 0xAA, 0x87, 0x2C, + 0x54, 0x7C, 0xB9, 0xA3, 0xDE, 0xDF, 0xDF, 0xA3, 0xB1, 0x80, 0xF2, 0xC4, 0xCD, 0xC9, 0xF1, 0xB8, + 0xA9, 0xB4, 0x99, 0x83, 0x0D, 0x35, 0x5D, 0x89, 0xB9, 0xA3, 0x2D, 0x55, 0x7D, 0xB5, 0x93, 0xA3, + 0x0E, 0x16, 0x1E, 0xA9, 0x2C, 0x54, 0x7C, 0xB8, 0xB4, 0xB0, 0xF1, 0x97, 0x83, 0xA8, 0x11, 0x84, + 0xA5, 0x09, 0x98, 0xA3, 0x83, 0xF0, 0xDA, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0xD8, 0xF1, 0xA5, + 0x29, 0x55, 0x7D, 0xA5, 0x85, 0x95, 0x02, 0x1A, 0x2E, 0x3A, 0x56, 0x5A, 0x40, 0x48, 0xF9, 0xF3, + 0xA3, 0xD9, 0xF8, 0xF0, 0x98, 0x83, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0x97, 0x82, 0xA8, 0xF1, + 0x11, 0xF0, 0x98, 0xA2, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0xDA, 0xF3, 0xDE, 0xD8, 0x83, 0xA5, + 0x94, 0x01, 0xD9, 0xA3, 0x02, 0xF1, 0xA2, 0xC3, 0xC5, 0xC7, 0xD8, 0xF1, 0x84, 0x92, 0xA2, 0x4D, + 0xDA, 0x2A, 0xD8, 0x48, 0x69, 0xD9, 0x2A, 0xD8, 0x68, 0x55, 0xDA, 0x32, 0xD8, 0x50, 0x71, 0xD9, + 0x32, 0xD8, 0x70, 0x5D, 0xDA, 0x3A, 0xD8, 0x58, 0x79, 0xD9, 0x3A, 0xD8, 0x78, 0x93, 0xA3, 0x4D, + 0xDA, 0x2A, 0xD8, 0x48, 0x69, 0xD9, 0x2A, 0xD8, 0x68, 0x55, 0xDA, 0x32, 0xD8, 0x50, 0x71, 0xD9, + 0x32, 0xD8, 0x70, 0x5D, 0xDA, 0x3A, 0xD8, 0x58, 0x79, 0xD9, 0x3A, 0xD8, 0x78, 0xA8, 0x8A, 0x9A, + 0xF0, 0x28, 0x50, 0x78, 0x9E, 0xF3, 0x88, 0x18, 0xF1, 0x9F, 0x1D, 0x98, 0xA8, 0xD9, 0x08, 0xD8, + 0xC8, 0x9F, 0x12, 0x9E, 0xF3, 0x15, 0xA8, 0xDA, 0x12, 0x10, 0xD8, 0xF1, 0xAF, 0xC8, 0x97, 0x87, + /* bank # 5 */ + 0x34, 0xB5, 0xB9, 0x94, 0xA4, 0x21, 0xF3, 0xD9, 0x22, 0xD8, 0xF2, 0x2D, 0xF3, 0xD9, 0x2A, 0xD8, + 0xF2, 0x35, 0xF3, 0xD9, 0x32, 0xD8, 0x81, 0xA4, 0x60, 0x60, 0x61, 0xD9, 0x61, 0xD8, 0x6C, 0x68, + 0x69, 0xD9, 0x69, 0xD8, 0x74, 0x70, 0x71, 0xD9, 0x71, 0xD8, 0xB1, 0xA3, 0x84, 0x19, 0x3D, 0x5D, + 0xA3, 0x83, 0x1A, 0x3E, 0x5E, 0x93, 0x10, 0x30, 0x81, 0x10, 0x11, 0xB8, 0xB0, 0xAF, 0x8F, 0x94, + 0xF2, 0xDA, 0x3E, 0xD8, 0xB4, 0x9A, 0xA8, 0x87, 0x29, 0xDA, 0xF8, 0xD8, 0x87, 0x9A, 0x35, 0xDA, + 0xF8, 0xD8, 0x87, 0x9A, 0x3D, 0xDA, 0xF8, 0xD8, 0xB1, 0xB9, 0xA4, 0x98, 0x85, 0x02, 0x2E, 0x56, + 0xA5, 0x81, 0x00, 0x0C, 0x14, 0xA3, 0x97, 0xB0, 0x8A, 0xF1, 0x2D, 0xD9, 0x28, 0xD8, 0x4D, 0xD9, + 0x48, 0xD8, 0x6D, 0xD9, 0x68, 0xD8, 0xB1, 0x84, 0x0D, 0xDA, 0x0E, 0xD8, 0xA3, 0x29, 0x83, 0xDA, + 0x2C, 0x0E, 0xD8, 0xA3, 0x84, 0x49, 0x83, 0xDA, 0x2C, 0x4C, 0x0E, 0xD8, 0xB8, 0xB0, 0xA8, 0x8A, + 0x9A, 0xF5, 0x20, 0xAA, 0xDA, 0xDF, 0xD8, 0xA8, 0x40, 0xAA, 0xD0, 0xDA, 0xDE, 0xD8, 0xA8, 0x60, + 0xAA, 0xDA, 0xD0, 0xDF, 0xD8, 0xF1, 0x97, 0x86, 0xA8, 0x31, 0x9B, 0x06, 0x99, 0x07, 0xAB, 0x97, + 0x28, 0x88, 0x9B, 0xF0, 0x0C, 0x20, 0x14, 0x40, 0xB8, 0xB0, 0xB4, 0xA8, 0x8C, 0x9C, 0xF0, 0x04, + 0x28, 0x51, 0x79, 0x1D, 0x30, 0x14, 0x38, 0xB2, 0x82, 0xAB, 0xD0, 0x98, 0x2C, 0x50, 0x50, 0x78, + 0x78, 0x9B, 0xF1, 0x1A, 0xB0, 0xF0, 0x8A, 0x9C, 0xA8, 0x29, 0x51, 0x79, 0x8B, 0x29, 0x51, 0x79, + 0x8A, 0x24, 0x70, 0x59, 0x8B, 0x20, 0x58, 0x71, 0x8A, 0x44, 0x69, 0x38, 0x8B, 0x39, 0x40, 0x68, + 0x8A, 0x64, 0x48, 0x31, 0x8B, 0x30, 0x49, 0x60, 0xA5, 0x88, 0x20, 0x09, 0x71, 0x58, 0x44, 0x68, + /* bank # 6 */ + 0x11, 0x39, 0x64, 0x49, 0x30, 0x19, 0xF1, 0xAC, 0x00, 0x2C, 0x54, 0x7C, 0xF0, 0x8C, 0xA8, 0x04, + 0x28, 0x50, 0x78, 0xF1, 0x88, 0x97, 0x26, 0xA8, 0x59, 0x98, 0xAC, 0x8C, 0x02, 0x26, 0x46, 0x66, + 0xF0, 0x89, 0x9C, 0xA8, 0x29, 0x51, 0x79, 0x24, 0x70, 0x59, 0x44, 0x69, 0x38, 0x64, 0x48, 0x31, + 0xA9, 0x88, 0x09, 0x20, 0x59, 0x70, 0xAB, 0x11, 0x38, 0x40, 0x69, 0xA8, 0x19, 0x31, 0x48, 0x60, + 0x8C, 0xA8, 0x3C, 0x41, 0x5C, 0x20, 0x7C, 0x00, 0xF1, 0x87, 0x98, 0x19, 0x86, 0xA8, 0x6E, 0x76, + 0x7E, 0xA9, 0x99, 0x88, 0x2D, 0x55, 0x7D, 0x9E, 0xB9, 0xA3, 0x8A, 0x22, 0x8A, 0x6E, 0x8A, 0x56, + 0x8A, 0x5E, 0x9F, 0xB1, 0x83, 0x06, 0x26, 0x46, 0x66, 0x0E, 0x2E, 0x4E, 0x6E, 0x9D, 0xB8, 0xAD, + 0x00, 0x2C, 0x54, 0x7C, 0xF2, 0xB1, 0x8C, 0xB4, 0x99, 0xB9, 0xA3, 0x2D, 0x55, 0x7D, 0x81, 0x91, + 0xAC, 0x38, 0xAD, 0x3A, 0xB5, 0x83, 0x91, 0xAC, 0x2D, 0xD9, 0x28, 0xD8, 0x4D, 0xD9, 0x48, 0xD8, + 0x6D, 0xD9, 0x68, 0xD8, 0x8C, 0x9D, 0xAE, 0x29, 0xD9, 0x04, 0xAE, 0xD8, 0x51, 0xD9, 0x04, 0xAE, + 0xD8, 0x79, 0xD9, 0x04, 0xD8, 0x81, 0xF3, 0x9D, 0xAD, 0x00, 0x8D, 0xAE, 0x19, 0x81, 0xAD, 0xD9, + 0x01, 0xD8, 0xF2, 0xAE, 0xDA, 0x26, 0xD8, 0x8E, 0x91, 0x29, 0x83, 0xA7, 0xD9, 0xAD, 0xAD, 0xAD, + 0xAD, 0xF3, 0x2A, 0xD8, 0xD8, 0xF1, 0xB0, 0xAC, 0x89, 0x91, 0x3E, 0x5E, 0x76, 0xF3, 0xAC, 0x2E, + 0x2E, 0xF1, 0xB1, 0x8C, 0x5A, 0x9C, 0xAC, 0x2C, 0x28, 0x28, 0x28, 0x9C, 0xAC, 0x30, 0x18, 0xA8, + 0x98, 0x81, 0x28, 0x34, 0x3C, 0x97, 0x24, 0xA7, 0x28, 0x34, 0x3C, 0x9C, 0x24, 0xF2, 0xB0, 0x89, + 0xAC, 0x91, 0x2C, 0x4C, 0x6C, 0x8A, 0x9B, 0x2D, 0xD9, 0xD8, 0xD8, 0x51, 0xD9, 0xD8, 0xD8, 0x79, + /* bank # 7 */ + 0xD9, 0xD8, 0xD8, 0xF1, 0x9E, 0x88, 0xA3, 0x31, 0xDA, 0xD8, 0xD8, 0x91, 0x2D, 0xD9, 0x28, 0xD8, + 0x4D, 0xD9, 0x48, 0xD8, 0x6D, 0xD9, 0x68, 0xD8, 0xB1, 0x83, 0x93, 0x35, 0x3D, 0x80, 0x25, 0xDA, + 0xD8, 0xD8, 0x85, 0x69, 0xDA, 0xD8, 0xD8, 0xB4, 0x93, 0x81, 0xA3, 0x28, 0x34, 0x3C, 0xF3, 0xAB, + 0x8B, 0xF8, 0xA3, 0x91, 0xB6, 0x09, 0xB4, 0xD9, 0xAB, 0xDE, 0xFA, 0xB0, 0x87, 0x9C, 0xB9, 0xA3, + 0xDD, 0xF1, 0x20, 0x28, 0x30, 0x38, 0x9A, 0xF1, 0x28, 0x30, 0x38, 0x9D, 0xF1, 0xA3, 0xA3, 0xA3, + 0xA3, 0xF2, 0xA3, 0xB4, 0x90, 0x80, 0xF2, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, + 0xA3, 0xB2, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xB0, 0x87, 0xB5, 0x99, 0xF1, 0x28, 0x30, 0x38, + 0x98, 0xF1, 0xA3, 0xA3, 0xA3, 0xA3, 0x97, 0xA3, 0xA3, 0xA3, 0xA3, 0xF3, 0x9B, 0xA3, 0x30, 0xDC, + 0xB9, 0xA7, 0xF1, 0x26, 0x26, 0x26, 0xFE, 0xD8, 0xFF, + +}; + +#ifndef MPU6050_DMP_FIFO_RATE_DIVISOR +#define MPU6050_DMP_FIFO_RATE_DIVISOR 0x01 // The New instance of the Firmware has this as the default +#endif + +// I Simplified this: +uint8_t MPU6050_6Axis_MotionApps20::dmpInitialize() { + // reset device + DEBUG_PRINTLN(F("\n\nResetting MPU6050...")); + reset(); + delay(30); // wait after reset + + // enable sleep mode and wake cycle + /*Serial.println(F("Enabling sleep mode...")); + setSleepEnabled(true); + Serial.println(F("Enabling wake cycle...")); + setWakeCycleEnabled(true);*/ + + // disable sleep mode + setSleepEnabled(false); + + // get MPU hardware revision + setMemoryBank(0x10, true, true); + setMemoryStartAddress(0x06); + DEBUG_PRINTLN(F("Checking hardware revision...")); + DEBUG_PRINT(F("Revision @ user[16][6] = ")); + DEBUG_PRINTLN(readMemoryByte()); + DEBUG_PRINTLN(F("Resetting memory bank selection to 0...")); + setMemoryBank(0, false, false); + + // check OTP bank valid + DEBUG_PRINTLN(F("Reading OTP bank valid flag...")); + DEBUG_PRINT(F("OTP bank is ")); + DEBUG_PRINTLN(getOTPBankValid() ? F("valid!") : F("invalid!")); + + // setup weird slave stuff (?) + DEBUG_PRINTLN(F("Setting slave 0 address to 0x7F...")); + setSlaveAddress(0, 0x7F); + DEBUG_PRINTLN(F("Disabling I2C Master mode...")); + setI2CMasterModeEnabled(false); + DEBUG_PRINTLN(F("Setting slave 0 address to 0x68 (self)...")); + setSlaveAddress(0, 0x68); + DEBUG_PRINTLN(F("Resetting I2C Master control...")); + resetI2CMaster(); + delay(20); + DEBUG_PRINTLN(F("Setting clock source to Z Gyro...")); + setClockSource(MPU6050_CLOCK_PLL_ZGYRO); + + DEBUG_PRINTLN(F("Setting DMP and FIFO_OFLOW interrupts enabled...")); + setIntEnabled(1<= dmpGetFIFOPacketSize(); +} + +// uint8_t MPU6050_6Axis_MotionApps20::dmpSetFIFORate(uint8_t fifoRate); +// uint8_t MPU6050_6Axis_MotionApps20::dmpGetFIFORate(); +// uint8_t MPU6050_6Axis_MotionApps20::dmpGetSampleStepSizeMS(); +// uint8_t MPU6050_6Axis_MotionApps20::dmpGetSampleFrequency(); +// int32_t MPU6050_6Axis_MotionApps20::dmpDecodeTemperature(int8_t tempReg); + +//uint8_t MPU6050_6Axis_MotionApps20::dmpRegisterFIFORateProcess(inv_obj_func func, int16_t priority); +//uint8_t MPU6050_6Axis_MotionApps20::dmpUnregisterFIFORateProcess(inv_obj_func func); +//uint8_t MPU6050_6Axis_MotionApps20::dmpRunFIFORateProcesses(); + +// uint8_t MPU6050_6Axis_MotionApps20::dmpSendQuaternion(uint_fast16_t accuracy); +// uint8_t MPU6050_6Axis_MotionApps20::dmpSendGyro(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050_6Axis_MotionApps20::dmpSendAccel(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050_6Axis_MotionApps20::dmpSendLinearAccel(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050_6Axis_MotionApps20::dmpSendLinearAccelInWorld(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050_6Axis_MotionApps20::dmpSendControlData(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050_6Axis_MotionApps20::dmpSendSensorData(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050_6Axis_MotionApps20::dmpSendExternalSensorData(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050_6Axis_MotionApps20::dmpSendGravity(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050_6Axis_MotionApps20::dmpSendPacketNumber(uint_fast16_t accuracy); +// uint8_t MPU6050_6Axis_MotionApps20::dmpSendQuantizedAccel(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050_6Axis_MotionApps20::dmpSendEIS(uint_fast16_t elements, uint_fast16_t accuracy); + +uint8_t MPU6050_6Axis_MotionApps20::dmpGetAccel(int32_t *data, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + data[0] = (((uint32_t)packet[28] << 24) | ((uint32_t)packet[29] << 16) | ((uint32_t)packet[30] << 8) | packet[31]); + data[1] = (((uint32_t)packet[32] << 24) | ((uint32_t)packet[33] << 16) | ((uint32_t)packet[34] << 8) | packet[35]); + data[2] = (((uint32_t)packet[36] << 24) | ((uint32_t)packet[37] << 16) | ((uint32_t)packet[38] << 8) | packet[39]); + return 0; +} +uint8_t MPU6050_6Axis_MotionApps20::dmpGetAccel(int16_t *data, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + data[0] = (packet[28] << 8) | packet[29]; + data[1] = (packet[32] << 8) | packet[33]; + data[2] = (packet[36] << 8) | packet[37]; + return 0; +} +uint8_t MPU6050_6Axis_MotionApps20::dmpGetAccel(VectorInt16 *v, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + v -> x = (packet[28] << 8) | packet[29]; + v -> y = (packet[32] << 8) | packet[33]; + v -> z = (packet[36] << 8) | packet[37]; + return 0; +} +uint8_t MPU6050_6Axis_MotionApps20::dmpGetQuaternion(int32_t *data, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + data[0] = (((uint32_t)packet[0] << 24) | ((uint32_t)packet[1] << 16) | ((uint32_t)packet[2] << 8) | packet[3]); + data[1] = (((uint32_t)packet[4] << 24) | ((uint32_t)packet[5] << 16) | ((uint32_t)packet[6] << 8) | packet[7]); + data[2] = (((uint32_t)packet[8] << 24) | ((uint32_t)packet[9] << 16) | ((uint32_t)packet[10] << 8) | packet[11]); + data[3] = (((uint32_t)packet[12] << 24) | ((uint32_t)packet[13] << 16) | ((uint32_t)packet[14] << 8) | packet[15]); + return 0; +} +uint8_t MPU6050_6Axis_MotionApps20::dmpGetQuaternion(int16_t *data, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + data[0] = ((packet[0] << 8) | packet[1]); + data[1] = ((packet[4] << 8) | packet[5]); + data[2] = ((packet[8] << 8) | packet[9]); + data[3] = ((packet[12] << 8) | packet[13]); + return 0; +} +uint8_t MPU6050_6Axis_MotionApps20::dmpGetQuaternion(Quaternion *q, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + int16_t qI[4]; + uint8_t status = dmpGetQuaternion(qI, packet); + if (status == 0) { + q -> w = (float)qI[0] / 16384.0f; + q -> x = (float)qI[1] / 16384.0f; + q -> y = (float)qI[2] / 16384.0f; + q -> z = (float)qI[3] / 16384.0f; + return 0; + } + return status; // int16 return value, indicates error if this line is reached +} +// uint8_t MPU6050_6Axis_MotionApps20::dmpGet6AxisQuaternion(long *data, const uint8_t* packet); +// uint8_t MPU6050_6Axis_MotionApps20::dmpGetRelativeQuaternion(long *data, const uint8_t* packet); +uint8_t MPU6050_6Axis_MotionApps20::dmpGetGyro(int32_t *data, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + data[0] = (((uint32_t)packet[16] << 24) | ((uint32_t)packet[17] << 16) | ((uint32_t)packet[18] << 8) | packet[19]); + data[1] = (((uint32_t)packet[20] << 24) | ((uint32_t)packet[21] << 16) | ((uint32_t)packet[22] << 8) | packet[23]); + data[2] = (((uint32_t)packet[24] << 24) | ((uint32_t)packet[25] << 16) | ((uint32_t)packet[26] << 8) | packet[27]); + return 0; +} +uint8_t MPU6050_6Axis_MotionApps20::dmpGetGyro(int16_t *data, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + data[0] = (packet[16] << 8) | packet[17]; + data[1] = (packet[20] << 8) | packet[21]; + data[2] = (packet[24] << 8) | packet[25]; + return 0; +} +uint8_t MPU6050_6Axis_MotionApps20::dmpGetGyro(VectorInt16 *v, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + v -> x = (packet[16] << 8) | packet[17]; + v -> y = (packet[20] << 8) | packet[21]; + v -> z = (packet[24] << 8) | packet[25]; + return 0; +} +// uint8_t MPU6050_6Axis_MotionApps20::dmpSetLinearAccelFilterCoefficient(float coef); +// uint8_t MPU6050_6Axis_MotionApps20::dmpGetLinearAccel(long *data, const uint8_t* packet); +uint8_t MPU6050_6Axis_MotionApps20::dmpGetLinearAccel(VectorInt16 *v, VectorInt16 *vRaw, VectorFloat *gravity) { + // get rid of the gravity component (+1g = +8192 in standard DMP FIFO packet, sensitivity is 2g) + v -> x = vRaw -> x - gravity -> x*8192; + v -> y = vRaw -> y - gravity -> y*8192; + v -> z = vRaw -> z - gravity -> z*8192; + return 0; +} +// uint8_t MPU6050_6Axis_MotionApps20::dmpGetLinearAccelInWorld(long *data, const uint8_t* packet); +uint8_t MPU6050_6Axis_MotionApps20::dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Quaternion *q) { + // rotate measured 3D acceleration vector into original state + // frame of reference based on orientation quaternion + memcpy(v, vReal, sizeof(VectorInt16)); + v -> rotate(q); + return 0; +} +// uint8_t MPU6050_6Axis_MotionApps20::dmpGetGyroAndAccelSensor(long *data, const uint8_t* packet); +// uint8_t MPU6050_6Axis_MotionApps20::dmpGetGyroSensor(long *data, const uint8_t* packet); +// uint8_t MPU6050_6Axis_MotionApps20::dmpGetControlData(long *data, const uint8_t* packet); +// uint8_t MPU6050_6Axis_MotionApps20::dmpGetTemperature(long *data, const uint8_t* packet); +// uint8_t MPU6050_6Axis_MotionApps20::dmpGetGravity(long *data, const uint8_t* packet); +uint8_t MPU6050_6Axis_MotionApps20::dmpGetGravity(int16_t *data, const uint8_t* packet) { + /* +1g corresponds to +8192, sensitivity is 2g. */ + int16_t qI[4]; + uint8_t status = dmpGetQuaternion(qI, packet); + data[0] = ((int32_t)qI[1] * qI[3] - (int32_t)qI[0] * qI[2]) / 16384; + data[1] = ((int32_t)qI[0] * qI[1] + (int32_t)qI[2] * qI[3]) / 16384; + data[2] = ((int32_t)qI[0] * qI[0] - (int32_t)qI[1] * qI[1] + - (int32_t)qI[2] * qI[2] + (int32_t)qI[3] * qI[3]) / (int32_t)(2 * 16384L); + return status; +} + +uint8_t MPU6050_6Axis_MotionApps20::dmpGetGravity(VectorFloat *v, Quaternion *q) { + v -> x = 2 * (q -> x*q -> z - q -> w*q -> y); + v -> y = 2 * (q -> w*q -> x + q -> y*q -> z); + v -> z = q -> w*q -> w - q -> x*q -> x - q -> y*q -> y + q -> z*q -> z; + return 0; +} +// uint8_t MPU6050_6Axis_MotionApps20::dmpGetUnquantizedAccel(long *data, const uint8_t* packet); +// uint8_t MPU6050_6Axis_MotionApps20::dmpGetQuantizedAccel(long *data, const uint8_t* packet); +// uint8_t MPU6050_6Axis_MotionApps20::dmpGetExternalSensorData(long *data, int size, const uint8_t* packet); +// uint8_t MPU6050_6Axis_MotionApps20::dmpGetEIS(long *data, const uint8_t* packet); + +uint8_t MPU6050_6Axis_MotionApps20::dmpGetEuler(float *data, Quaternion *q) { + data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1); // psi + data[1] = -asin(2*q -> x*q -> z + 2*q -> w*q -> y); // theta + data[2] = atan2(2*q -> y*q -> z - 2*q -> w*q -> x, 2*q -> w*q -> w + 2*q -> z*q -> z - 1); // phi + return 0; +} + +#ifdef USE_OLD_DMPGETYAWPITCHROLL +uint8_t MPU6050_6Axis_MotionApps20::dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity) { + // yaw: (about Z axis) + data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1); + // pitch: (nose up/down, about Y axis) + data[1] = atan(gravity -> x / sqrt(gravity -> y*gravity -> y + gravity -> z*gravity -> z)); + // roll: (tilt left/right, about X axis) + data[2] = atan(gravity -> y / sqrt(gravity -> x*gravity -> x + gravity -> z*gravity -> z)); + return 0; +} +#else +uint8_t MPU6050_6Axis_MotionApps20::dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity) { + // yaw: (about Z axis) + data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1); + // pitch: (nose up/down, about Y axis) + data[1] = atan2(gravity -> x , sqrt(gravity -> y*gravity -> y + gravity -> z*gravity -> z)); + // roll: (tilt left/right, about X axis) + data[2] = atan2(gravity -> y , gravity -> z); + if (gravity -> z < 0) { + if(data[1] > 0) { + data[1] = PI - data[1]; + } else { + data[1] = -PI - data[1]; + } + } + return 0; +} +#endif + +// uint8_t MPU6050_6Axis_MotionApps20::dmpGetAccelFloat(float *data, const uint8_t* packet); +// uint8_t MPU6050_6Axis_MotionApps20::dmpGetQuaternionFloat(float *data, const uint8_t* packet); + +uint8_t MPU6050_6Axis_MotionApps20::dmpProcessFIFOPacket(const unsigned char *dmpData) { + (void)dmpData; // unused parameter + /*for (uint8_t k = 0; k < dmpPacketSize; k++) { + if (dmpData[k] < 0x10) Serial.print("0"); + Serial.print(dmpData[k], HEX); + Serial.print(" "); + } + Serial.print("\n");*/ + //Serial.println((uint16_t)dmpPacketBuffer); + return 0; +} +uint8_t MPU6050_6Axis_MotionApps20::dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *processed) { + uint8_t status; + uint8_t buf[dmpPacketSize]; + for (uint8_t i = 0; i < numPackets; i++) { + // read packet from FIFO + getFIFOBytes(buf, dmpPacketSize); + + // process packet + if ((status = dmpProcessFIFOPacket(buf)) > 0) return status; + + // increment external process count variable, if supplied + if (processed != 0) (*processed)++; + } + return 0; +} + +// uint8_t MPU6050_6Axis_MotionApps20::dmpSetFIFOProcessedCallback(void (*func) (void)); + +// uint8_t MPU6050_6Axis_MotionApps20::dmpInitFIFOParam(); +// uint8_t MPU6050_6Axis_MotionApps20::dmpCloseFIFO(); +// uint8_t MPU6050_6Axis_MotionApps20::dmpSetGyroDataSource(uint_fast8_t source); +// uint8_t MPU6050_6Axis_MotionApps20::dmpDecodeQuantizedAccel(); +// uint32_t MPU6050_6Axis_MotionApps20::dmpGetGyroSumOfSquare(); +// uint32_t MPU6050_6Axis_MotionApps20::dmpGetAccelSumOfSquare(); +// void MPU6050_6Axis_MotionApps20::dmpOverrideQuaternion(long *q); +uint16_t MPU6050_6Axis_MotionApps20::dmpGetFIFOPacketSize() { + return dmpPacketSize; +} + + + +uint8_t MPU6050_6Axis_MotionApps20::dmpGetCurrentFIFOPacket(uint8_t *data) { // overflow proof + return(GetCurrentFIFOPacket(data, dmpPacketSize)); +} diff --git a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h index 9cf54c66..e4b370c9 100644 --- a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h +++ b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h @@ -1,13 +1,16 @@ -// I2Cdev library collection - MPU6050 I2C device class, 6-axis MotionApps 2.0 implementation +// I2Cdev library collection - MPU6050 I2C device class // Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00) -// 5/20/2013 by Jeff Rowberg +// 10/3/2011 by Jeff Rowberg // Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib // // Changelog: -// 2019/07/08 - merged all DMP Firmware configuration items into the dmpMemory array -// - Simplified dmpInitialize() to accomidate the dmpmemory array alterations +// 2021/09/27 - split implementations out of header files, finally // ... - ongoing debug release +// NOTE: THIS IS ONLY A PARIAL RELEASE. THIS DEVICE CLASS IS CURRENTLY UNDERGOING ACTIVE +// DEVELOPMENT AND IS STILL MISSING SOME IMPORTANT FEATURES. PLEASE KEEP THIS IN MIND IF +// YOU DECIDE TO USE THIS PARTICULAR CODE FOR ANYTHING. + /* ============================================ I2Cdev device library code is placed under the MIT license Copyright (c) 2012 Jeff Rowberg @@ -35,590 +38,114 @@ THE SOFTWARE. #ifndef _MPU6050_6AXIS_MOTIONAPPS20_H_ #define _MPU6050_6AXIS_MOTIONAPPS20_H_ -#include "I2Cdev.h" -#include "helper_3dmath.h" - -// MotionApps 2.0 DMP implementation, built using the MPU-6050EVB evaluation board -#define MPU6050_INCLUDE_DMP_MOTIONAPPS20 - #include "MPU6050.h" -// Tom Carpenter's conditional PROGMEM code -// http://forum.arduino.cc/index.php?topic=129407.0 -#ifdef __AVR__ - #include -#elif defined(ESP32) - #include -#else - // Teensy 3.0 library conditional PROGMEM code from Paul Stoffregen - #ifndef __PGMSPACE_H_ - #define __PGMSPACE_H_ 1 - #include - - #define PROGMEM - #define PGM_P const char * - #define PSTR(str) (str) - #define F(x) x +class MPU6050_6Axis_MotionApps20 : public MPU6050_Base { + public: + uint8_t dmpInitialize(); + bool dmpPacketAvailable(); - typedef void prog_void; - typedef char prog_char; - typedef unsigned char prog_uchar; - typedef int8_t prog_int8_t; - typedef uint8_t prog_uint8_t; - typedef int16_t prog_int16_t; - typedef uint16_t prog_uint16_t; - typedef int32_t prog_int32_t; - typedef uint32_t prog_uint32_t; + uint8_t dmpSetFIFORate(uint8_t fifoRate); + uint8_t dmpGetFIFORate(); + uint8_t dmpGetSampleStepSizeMS(); + uint8_t dmpGetSampleFrequency(); + int32_t dmpDecodeTemperature(int8_t tempReg); - #define strcpy_P(dest, src) strcpy((dest), (src)) - #define strcat_P(dest, src) strcat((dest), (src)) - #define strcmp_P(a, b) strcmp((a), (b)) + // Register callbacks after a packet of FIFO data is processed + //uint8_t dmpRegisterFIFORateProcess(inv_obj_func func, int16_t priority); + //uint8_t dmpUnregisterFIFORateProcess(inv_obj_func func); + uint8_t dmpRunFIFORateProcesses(); - #define pgm_read_byte(addr) (*(const unsigned char *)(addr)) - #define pgm_read_word(addr) (*(const unsigned short *)(addr)) - #define pgm_read_dword(addr) (*(const unsigned long *)(addr)) - #define pgm_read_float(addr) (*(const float *)(addr)) + // Setup FIFO for various output + uint8_t dmpSendQuaternion(uint_fast16_t accuracy); + uint8_t dmpSendGyro(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendAccel(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendLinearAccel(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendLinearAccelInWorld(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendControlData(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendSensorData(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendExternalSensorData(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendGravity(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendPacketNumber(uint_fast16_t accuracy); + uint8_t dmpSendQuantizedAccel(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendEIS(uint_fast16_t elements, uint_fast16_t accuracy); + + // Get Fixed Point data from FIFO + uint8_t dmpGetAccel(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetAccel(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetAccel(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetQuaternion(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetQuaternion(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetQuaternion(Quaternion *q, const uint8_t* packet=0); + uint8_t dmpGet6AxisQuaternion(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGet6AxisQuaternion(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGet6AxisQuaternion(Quaternion *q, const uint8_t* packet=0); + uint8_t dmpGetRelativeQuaternion(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetRelativeQuaternion(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetRelativeQuaternion(Quaternion *data, const uint8_t* packet=0); + uint8_t dmpGetGyro(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyro(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyro(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpSetLinearAccelFilterCoefficient(float coef); + uint8_t dmpGetLinearAccel(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetLinearAccel(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetLinearAccel(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetLinearAccel(VectorInt16 *v, VectorInt16 *vRaw, VectorFloat *gravity); + uint8_t dmpGetLinearAccelInWorld(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetLinearAccelInWorld(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetLinearAccelInWorld(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Quaternion *q); + uint8_t dmpGetGyroAndAccelSensor(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyroAndAccelSensor(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyroAndAccelSensor(VectorInt16 *g, VectorInt16 *a, const uint8_t* packet=0); + uint8_t dmpGetGyroSensor(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyroSensor(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyroSensor(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetControlData(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetTemperature(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetGravity(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetGravity(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetGravity(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetGravity(VectorFloat *v, Quaternion *q); + uint8_t dmpGetUnquantizedAccel(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetUnquantizedAccel(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetUnquantizedAccel(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetQuantizedAccel(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetQuantizedAccel(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetQuantizedAccel(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetExternalSensorData(int32_t *data, uint16_t size, const uint8_t* packet=0); + uint8_t dmpGetEIS(int32_t *data, const uint8_t* packet=0); - #define pgm_read_byte_near(addr) pgm_read_byte(addr) - #define pgm_read_word_near(addr) pgm_read_word(addr) - #define pgm_read_dword_near(addr) pgm_read_dword(addr) - #define pgm_read_float_near(addr) pgm_read_float(addr) - #define pgm_read_byte_far(addr) pgm_read_byte(addr) - #define pgm_read_word_far(addr) pgm_read_word(addr) - #define pgm_read_dword_far(addr) pgm_read_dword(addr) - #define pgm_read_float_far(addr) pgm_read_float(addr) - #endif -#endif - -/* Source is from the InvenSense MotionApps v2 demo code. Original source is - * unavailable, unless you happen to be amazing as decompiling binary by - * hand (in which case, please contact me, and I'm totally serious). - * - * Also, I'd like to offer many, many thanks to Noah Zerkin for all of the - * DMP reverse-engineering he did to help make this bit of wizardry - * possible. - */ - -// NOTE! Enabling DEBUG adds about 3.3kB to the flash program size. -// Debug output is now working even on ATMega328P MCUs (e.g. Arduino Uno) -// after moving string constants to flash memory storage using the F() -// compiler macro (Arduino IDE 1.0+ required). - -//#define DEBUG -#ifdef DEBUG - #define DEBUG_PRINT(x) Serial.print(x) - #define DEBUG_PRINTF(x, y) Serial.print(x, y) - #define DEBUG_PRINTLN(x) Serial.println(x) - #define DEBUG_PRINTLNF(x, y) Serial.println(x, y) -#else - #define DEBUG_PRINT(x) - #define DEBUG_PRINTF(x, y) - #define DEBUG_PRINTLN(x) - #define DEBUG_PRINTLNF(x, y) -#endif - -#define MPU6050_DMP_CODE_SIZE 1929 // dmpMemory[] -#define MPU6050_DMP_CONFIG_SIZE 192 // dmpConfig[] -#define MPU6050_DMP_UPDATES_SIZE 47 // dmpUpdates[] - -/* ================================================================================================ * - | Default MotionApps v2.0 42-byte FIFO packet structure: | - | | - | [QUAT W][ ][QUAT X][ ][QUAT Y][ ][QUAT Z][ ][GYRO X][ ][GYRO Y][ ] | - | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | - | | - | [GYRO Z][ ][ACC X ][ ][ACC Y ][ ][ACC Z ][ ][ ] | - | 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | - * ================================================================================================ */ - -// this block of memory gets written to the MPU on start-up, and it seems -// to be volatile memory, so it has to be done each time (it only takes ~1 -// second though) - -// I Only Changed this by applying all the configuration data and capturing it before startup: -// *** this is a capture of the DMP Firmware after all the messy changes were made so we can just load it -const unsigned char dmpMemory[MPU6050_DMP_CODE_SIZE] PROGMEM = { - /* bank # 0 */ - 0xFB, 0x00, 0x00, 0x3E, 0x00, 0x0B, 0x00, 0x36, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, - 0x00, 0x65, 0x00, 0x54, 0xFF, 0xEF, 0x00, 0x00, 0xFA, 0x80, 0x00, 0x0B, 0x12, 0x82, 0x00, 0x01, - 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x28, 0x00, 0x00, 0xFF, 0xFF, 0x45, 0x81, 0xFF, 0xFF, 0xFA, 0x72, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x03, 0xE8, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x7F, 0xFF, 0xFF, 0xFE, 0x80, 0x01, - 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0xCB, 0x47, 0xA2, 0x20, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, - 0x41, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x2A, 0x00, 0x00, 0x16, 0x55, 0x00, 0x00, 0x21, 0x82, - 0xFD, 0x87, 0x26, 0x50, 0xFD, 0x80, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x05, 0x80, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x6F, 0x00, 0x02, 0x65, 0x32, 0x00, 0x00, 0x5E, 0xC0, - 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFB, 0x8C, 0x6F, 0x5D, 0xFD, 0x5D, 0x08, 0xD9, 0x00, 0x7C, 0x73, 0x3B, 0x00, 0x6C, 0x12, 0xCC, - 0x32, 0x00, 0x13, 0x9D, 0x32, 0x00, 0xD0, 0xD6, 0x32, 0x00, 0x08, 0x00, 0x40, 0x00, 0x01, 0xF4, - 0xFF, 0xE6, 0x80, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0xD6, 0x00, 0x00, 0x27, 0x10, - /* bank # 1 */ - 0xFB, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xFA, 0x36, 0xFF, 0xBC, 0x30, 0x8E, 0x00, 0x05, 0xFB, 0xF0, 0xFF, 0xD9, 0x5B, 0xC8, - 0xFF, 0xD0, 0x9A, 0xBE, 0x00, 0x00, 0x10, 0xA9, 0xFF, 0xF4, 0x1E, 0xB2, 0x00, 0xCE, 0xBB, 0xF7, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x0C, - 0xFF, 0xC2, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0xCF, 0x80, 0x00, 0x40, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x14, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x09, 0x23, 0xA1, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x3F, 0x68, 0xB6, 0x79, 0x35, 0x28, 0xBC, 0xC6, 0x7E, 0xD1, 0x6C, - 0x80, 0x00, 0xFF, 0xFF, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB2, 0x6A, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, - 0x00, 0x00, 0x25, 0x4D, 0x00, 0x2F, 0x70, 0x6D, 0x00, 0x00, 0x05, 0xAE, 0x00, 0x0C, 0x02, 0xD0, - /* bank # 2 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x54, 0xFF, 0xEF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x44, 0x00, 0x01, 0x00, 0x05, 0x8B, 0xC1, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0xFF, 0xEF, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* bank # 3 */ - 0xD8, 0xDC, 0xBA, 0xA2, 0xF1, 0xDE, 0xB2, 0xB8, 0xB4, 0xA8, 0x81, 0x91, 0xF7, 0x4A, 0x90, 0x7F, - 0x91, 0x6A, 0xF3, 0xF9, 0xDB, 0xA8, 0xF9, 0xB0, 0xBA, 0xA0, 0x80, 0xF2, 0xCE, 0x81, 0xF3, 0xC2, - 0xF1, 0xC1, 0xF2, 0xC3, 0xF3, 0xCC, 0xA2, 0xB2, 0x80, 0xF1, 0xC6, 0xD8, 0x80, 0xBA, 0xA7, 0xDF, - 0xDF, 0xDF, 0xF2, 0xA7, 0xC3, 0xCB, 0xC5, 0xB6, 0xF0, 0x87, 0xA2, 0x94, 0x24, 0x48, 0x70, 0x3C, - 0x95, 0x40, 0x68, 0x34, 0x58, 0x9B, 0x78, 0xA2, 0xF1, 0x83, 0x92, 0x2D, 0x55, 0x7D, 0xD8, 0xB1, - 0xB4, 0xB8, 0xA1, 0xD0, 0x91, 0x80, 0xF2, 0x70, 0xF3, 0x70, 0xF2, 0x7C, 0x80, 0xA8, 0xF1, 0x01, - 0xB0, 0x98, 0x87, 0xD9, 0x43, 0xD8, 0x86, 0xC9, 0x88, 0xBA, 0xA1, 0xF2, 0x0E, 0xB8, 0x97, 0x80, - 0xF1, 0xA9, 0xDF, 0xDF, 0xDF, 0xAA, 0xDF, 0xDF, 0xDF, 0xF2, 0xAA, 0x4C, 0xCD, 0x6C, 0xA9, 0x0C, - 0xC9, 0x2C, 0x97, 0x97, 0x97, 0x97, 0xF1, 0xA9, 0x89, 0x26, 0x46, 0x66, 0xB0, 0xB4, 0xBA, 0x80, - 0xAC, 0xDE, 0xF2, 0xCA, 0xF1, 0xB2, 0x8C, 0x02, 0xA9, 0xB6, 0x98, 0x00, 0x89, 0x0E, 0x16, 0x1E, - 0xB8, 0xA9, 0xB4, 0x99, 0x2C, 0x54, 0x7C, 0xB0, 0x8A, 0xA8, 0x96, 0x36, 0x56, 0x76, 0xF1, 0xB9, - 0xAF, 0xB4, 0xB0, 0x83, 0xC0, 0xB8, 0xA8, 0x97, 0x11, 0xB1, 0x8F, 0x98, 0xB9, 0xAF, 0xF0, 0x24, - 0x08, 0x44, 0x10, 0x64, 0x18, 0xF1, 0xA3, 0x29, 0x55, 0x7D, 0xAF, 0x83, 0xB5, 0x93, 0xAF, 0xF0, - 0x00, 0x28, 0x50, 0xF1, 0xA3, 0x86, 0x9F, 0x61, 0xA6, 0xDA, 0xDE, 0xDF, 0xD9, 0xFA, 0xA3, 0x86, - 0x96, 0xDB, 0x31, 0xA6, 0xD9, 0xF8, 0xDF, 0xBA, 0xA6, 0x8F, 0xC2, 0xC5, 0xC7, 0xB2, 0x8C, 0xC1, - 0xB8, 0xA2, 0xDF, 0xDF, 0xDF, 0xA3, 0xDF, 0xDF, 0xDF, 0xD8, 0xD8, 0xF1, 0xB8, 0xA8, 0xB2, 0x86, - /* bank # 4 */ - 0xB4, 0x98, 0x0D, 0x35, 0x5D, 0xB8, 0xAA, 0x98, 0xB0, 0x87, 0x2D, 0x35, 0x3D, 0xB2, 0xB6, 0xBA, - 0xAF, 0x8C, 0x96, 0x19, 0x8F, 0x9F, 0xA7, 0x0E, 0x16, 0x1E, 0xB4, 0x9A, 0xB8, 0xAA, 0x87, 0x2C, - 0x54, 0x7C, 0xB9, 0xA3, 0xDE, 0xDF, 0xDF, 0xA3, 0xB1, 0x80, 0xF2, 0xC4, 0xCD, 0xC9, 0xF1, 0xB8, - 0xA9, 0xB4, 0x99, 0x83, 0x0D, 0x35, 0x5D, 0x89, 0xB9, 0xA3, 0x2D, 0x55, 0x7D, 0xB5, 0x93, 0xA3, - 0x0E, 0x16, 0x1E, 0xA9, 0x2C, 0x54, 0x7C, 0xB8, 0xB4, 0xB0, 0xF1, 0x97, 0x83, 0xA8, 0x11, 0x84, - 0xA5, 0x09, 0x98, 0xA3, 0x83, 0xF0, 0xDA, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0xD8, 0xF1, 0xA5, - 0x29, 0x55, 0x7D, 0xA5, 0x85, 0x95, 0x02, 0x1A, 0x2E, 0x3A, 0x56, 0x5A, 0x40, 0x48, 0xF9, 0xF3, - 0xA3, 0xD9, 0xF8, 0xF0, 0x98, 0x83, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0x97, 0x82, 0xA8, 0xF1, - 0x11, 0xF0, 0x98, 0xA2, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0xDA, 0xF3, 0xDE, 0xD8, 0x83, 0xA5, - 0x94, 0x01, 0xD9, 0xA3, 0x02, 0xF1, 0xA2, 0xC3, 0xC5, 0xC7, 0xD8, 0xF1, 0x84, 0x92, 0xA2, 0x4D, - 0xDA, 0x2A, 0xD8, 0x48, 0x69, 0xD9, 0x2A, 0xD8, 0x68, 0x55, 0xDA, 0x32, 0xD8, 0x50, 0x71, 0xD9, - 0x32, 0xD8, 0x70, 0x5D, 0xDA, 0x3A, 0xD8, 0x58, 0x79, 0xD9, 0x3A, 0xD8, 0x78, 0x93, 0xA3, 0x4D, - 0xDA, 0x2A, 0xD8, 0x48, 0x69, 0xD9, 0x2A, 0xD8, 0x68, 0x55, 0xDA, 0x32, 0xD8, 0x50, 0x71, 0xD9, - 0x32, 0xD8, 0x70, 0x5D, 0xDA, 0x3A, 0xD8, 0x58, 0x79, 0xD9, 0x3A, 0xD8, 0x78, 0xA8, 0x8A, 0x9A, - 0xF0, 0x28, 0x50, 0x78, 0x9E, 0xF3, 0x88, 0x18, 0xF1, 0x9F, 0x1D, 0x98, 0xA8, 0xD9, 0x08, 0xD8, - 0xC8, 0x9F, 0x12, 0x9E, 0xF3, 0x15, 0xA8, 0xDA, 0x12, 0x10, 0xD8, 0xF1, 0xAF, 0xC8, 0x97, 0x87, - /* bank # 5 */ - 0x34, 0xB5, 0xB9, 0x94, 0xA4, 0x21, 0xF3, 0xD9, 0x22, 0xD8, 0xF2, 0x2D, 0xF3, 0xD9, 0x2A, 0xD8, - 0xF2, 0x35, 0xF3, 0xD9, 0x32, 0xD8, 0x81, 0xA4, 0x60, 0x60, 0x61, 0xD9, 0x61, 0xD8, 0x6C, 0x68, - 0x69, 0xD9, 0x69, 0xD8, 0x74, 0x70, 0x71, 0xD9, 0x71, 0xD8, 0xB1, 0xA3, 0x84, 0x19, 0x3D, 0x5D, - 0xA3, 0x83, 0x1A, 0x3E, 0x5E, 0x93, 0x10, 0x30, 0x81, 0x10, 0x11, 0xB8, 0xB0, 0xAF, 0x8F, 0x94, - 0xF2, 0xDA, 0x3E, 0xD8, 0xB4, 0x9A, 0xA8, 0x87, 0x29, 0xDA, 0xF8, 0xD8, 0x87, 0x9A, 0x35, 0xDA, - 0xF8, 0xD8, 0x87, 0x9A, 0x3D, 0xDA, 0xF8, 0xD8, 0xB1, 0xB9, 0xA4, 0x98, 0x85, 0x02, 0x2E, 0x56, - 0xA5, 0x81, 0x00, 0x0C, 0x14, 0xA3, 0x97, 0xB0, 0x8A, 0xF1, 0x2D, 0xD9, 0x28, 0xD8, 0x4D, 0xD9, - 0x48, 0xD8, 0x6D, 0xD9, 0x68, 0xD8, 0xB1, 0x84, 0x0D, 0xDA, 0x0E, 0xD8, 0xA3, 0x29, 0x83, 0xDA, - 0x2C, 0x0E, 0xD8, 0xA3, 0x84, 0x49, 0x83, 0xDA, 0x2C, 0x4C, 0x0E, 0xD8, 0xB8, 0xB0, 0xA8, 0x8A, - 0x9A, 0xF5, 0x20, 0xAA, 0xDA, 0xDF, 0xD8, 0xA8, 0x40, 0xAA, 0xD0, 0xDA, 0xDE, 0xD8, 0xA8, 0x60, - 0xAA, 0xDA, 0xD0, 0xDF, 0xD8, 0xF1, 0x97, 0x86, 0xA8, 0x31, 0x9B, 0x06, 0x99, 0x07, 0xAB, 0x97, - 0x28, 0x88, 0x9B, 0xF0, 0x0C, 0x20, 0x14, 0x40, 0xB8, 0xB0, 0xB4, 0xA8, 0x8C, 0x9C, 0xF0, 0x04, - 0x28, 0x51, 0x79, 0x1D, 0x30, 0x14, 0x38, 0xB2, 0x82, 0xAB, 0xD0, 0x98, 0x2C, 0x50, 0x50, 0x78, - 0x78, 0x9B, 0xF1, 0x1A, 0xB0, 0xF0, 0x8A, 0x9C, 0xA8, 0x29, 0x51, 0x79, 0x8B, 0x29, 0x51, 0x79, - 0x8A, 0x24, 0x70, 0x59, 0x8B, 0x20, 0x58, 0x71, 0x8A, 0x44, 0x69, 0x38, 0x8B, 0x39, 0x40, 0x68, - 0x8A, 0x64, 0x48, 0x31, 0x8B, 0x30, 0x49, 0x60, 0xA5, 0x88, 0x20, 0x09, 0x71, 0x58, 0x44, 0x68, - /* bank # 6 */ - 0x11, 0x39, 0x64, 0x49, 0x30, 0x19, 0xF1, 0xAC, 0x00, 0x2C, 0x54, 0x7C, 0xF0, 0x8C, 0xA8, 0x04, - 0x28, 0x50, 0x78, 0xF1, 0x88, 0x97, 0x26, 0xA8, 0x59, 0x98, 0xAC, 0x8C, 0x02, 0x26, 0x46, 0x66, - 0xF0, 0x89, 0x9C, 0xA8, 0x29, 0x51, 0x79, 0x24, 0x70, 0x59, 0x44, 0x69, 0x38, 0x64, 0x48, 0x31, - 0xA9, 0x88, 0x09, 0x20, 0x59, 0x70, 0xAB, 0x11, 0x38, 0x40, 0x69, 0xA8, 0x19, 0x31, 0x48, 0x60, - 0x8C, 0xA8, 0x3C, 0x41, 0x5C, 0x20, 0x7C, 0x00, 0xF1, 0x87, 0x98, 0x19, 0x86, 0xA8, 0x6E, 0x76, - 0x7E, 0xA9, 0x99, 0x88, 0x2D, 0x55, 0x7D, 0x9E, 0xB9, 0xA3, 0x8A, 0x22, 0x8A, 0x6E, 0x8A, 0x56, - 0x8A, 0x5E, 0x9F, 0xB1, 0x83, 0x06, 0x26, 0x46, 0x66, 0x0E, 0x2E, 0x4E, 0x6E, 0x9D, 0xB8, 0xAD, - 0x00, 0x2C, 0x54, 0x7C, 0xF2, 0xB1, 0x8C, 0xB4, 0x99, 0xB9, 0xA3, 0x2D, 0x55, 0x7D, 0x81, 0x91, - 0xAC, 0x38, 0xAD, 0x3A, 0xB5, 0x83, 0x91, 0xAC, 0x2D, 0xD9, 0x28, 0xD8, 0x4D, 0xD9, 0x48, 0xD8, - 0x6D, 0xD9, 0x68, 0xD8, 0x8C, 0x9D, 0xAE, 0x29, 0xD9, 0x04, 0xAE, 0xD8, 0x51, 0xD9, 0x04, 0xAE, - 0xD8, 0x79, 0xD9, 0x04, 0xD8, 0x81, 0xF3, 0x9D, 0xAD, 0x00, 0x8D, 0xAE, 0x19, 0x81, 0xAD, 0xD9, - 0x01, 0xD8, 0xF2, 0xAE, 0xDA, 0x26, 0xD8, 0x8E, 0x91, 0x29, 0x83, 0xA7, 0xD9, 0xAD, 0xAD, 0xAD, - 0xAD, 0xF3, 0x2A, 0xD8, 0xD8, 0xF1, 0xB0, 0xAC, 0x89, 0x91, 0x3E, 0x5E, 0x76, 0xF3, 0xAC, 0x2E, - 0x2E, 0xF1, 0xB1, 0x8C, 0x5A, 0x9C, 0xAC, 0x2C, 0x28, 0x28, 0x28, 0x9C, 0xAC, 0x30, 0x18, 0xA8, - 0x98, 0x81, 0x28, 0x34, 0x3C, 0x97, 0x24, 0xA7, 0x28, 0x34, 0x3C, 0x9C, 0x24, 0xF2, 0xB0, 0x89, - 0xAC, 0x91, 0x2C, 0x4C, 0x6C, 0x8A, 0x9B, 0x2D, 0xD9, 0xD8, 0xD8, 0x51, 0xD9, 0xD8, 0xD8, 0x79, - /* bank # 7 */ - 0xD9, 0xD8, 0xD8, 0xF1, 0x9E, 0x88, 0xA3, 0x31, 0xDA, 0xD8, 0xD8, 0x91, 0x2D, 0xD9, 0x28, 0xD8, - 0x4D, 0xD9, 0x48, 0xD8, 0x6D, 0xD9, 0x68, 0xD8, 0xB1, 0x83, 0x93, 0x35, 0x3D, 0x80, 0x25, 0xDA, - 0xD8, 0xD8, 0x85, 0x69, 0xDA, 0xD8, 0xD8, 0xB4, 0x93, 0x81, 0xA3, 0x28, 0x34, 0x3C, 0xF3, 0xAB, - 0x8B, 0xF8, 0xA3, 0x91, 0xB6, 0x09, 0xB4, 0xD9, 0xAB, 0xDE, 0xFA, 0xB0, 0x87, 0x9C, 0xB9, 0xA3, - 0xDD, 0xF1, 0x20, 0x28, 0x30, 0x38, 0x9A, 0xF1, 0x28, 0x30, 0x38, 0x9D, 0xF1, 0xA3, 0xA3, 0xA3, - 0xA3, 0xF2, 0xA3, 0xB4, 0x90, 0x80, 0xF2, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, - 0xA3, 0xB2, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xB0, 0x87, 0xB5, 0x99, 0xF1, 0x28, 0x30, 0x38, - 0x98, 0xF1, 0xA3, 0xA3, 0xA3, 0xA3, 0x97, 0xA3, 0xA3, 0xA3, 0xA3, 0xF3, 0x9B, 0xA3, 0x30, 0xDC, - 0xB9, 0xA7, 0xF1, 0x26, 0x26, 0x26, 0xFE, 0xD8, 0xFF, - + uint8_t dmpGetEuler(float *data, Quaternion *q); + uint8_t dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity); + + // Get Floating Point data from FIFO + uint8_t dmpGetAccelFloat(float *data, const uint8_t* packet=0); + uint8_t dmpGetQuaternionFloat(float *data, const uint8_t* packet=0); + + uint8_t dmpProcessFIFOPacket(const unsigned char *dmpData); + uint8_t dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *processed=NULL); + + uint8_t dmpSetFIFOProcessedCallback(void (*func) (void)); + + uint8_t dmpInitFIFOParam(); + uint8_t dmpCloseFIFO(); + uint8_t dmpSetGyroDataSource(uint8_t source); + uint8_t dmpDecodeQuantizedAccel(); + uint32_t dmpGetGyroSumOfSquare(); + uint32_t dmpGetAccelSumOfSquare(); + void dmpOverrideQuaternion(long *q); + uint16_t dmpGetFIFOPacketSize(); + uint8_t dmpGetCurrentFIFOPacket(uint8_t *data); // overflow proof + + private: + uint8_t *dmpPacketBuffer; + uint16_t dmpPacketSize; }; -#ifndef MPU6050_DMP_FIFO_RATE_DIVISOR -#define MPU6050_DMP_FIFO_RATE_DIVISOR 0x01 // The New instance of the Firmware has this as the default +#ifndef I2CDEVLIB_MPU6050_TYPEDEF +#define I2CDEVLIB_MPU6050_TYPEDEF +typedef MPU6050_6Axis_MotionApps20 MPU6050; #endif -// I Simplified this: -uint8_t MPU6050::dmpInitialize() { - // reset device - DEBUG_PRINTLN(F("\n\nResetting MPU6050...")); - reset(); - delay(30); // wait after reset - - // enable sleep mode and wake cycle - /*Serial.println(F("Enabling sleep mode...")); - setSleepEnabled(true); - Serial.println(F("Enabling wake cycle...")); - setWakeCycleEnabled(true);*/ - - // disable sleep mode - setSleepEnabled(false); - - // get MPU hardware revision - setMemoryBank(0x10, true, true); - setMemoryStartAddress(0x06); - DEBUG_PRINTLN(F("Checking hardware revision...")); - DEBUG_PRINT(F("Revision @ user[16][6] = ")); - DEBUG_PRINTLN(readMemoryByte()); - DEBUG_PRINTLN(F("Resetting memory bank selection to 0...")); - setMemoryBank(0, false, false); - - // check OTP bank valid - DEBUG_PRINTLN(F("Reading OTP bank valid flag...")); - DEBUG_PRINT(F("OTP bank is ")); - DEBUG_PRINTLN(getOTPBankValid() ? F("valid!") : F("invalid!")); - - // setup weird slave stuff (?) - DEBUG_PRINTLN(F("Setting slave 0 address to 0x7F...")); - setSlaveAddress(0, 0x7F); - DEBUG_PRINTLN(F("Disabling I2C Master mode...")); - setI2CMasterModeEnabled(false); - DEBUG_PRINTLN(F("Setting slave 0 address to 0x68 (self)...")); - setSlaveAddress(0, 0x68); - DEBUG_PRINTLN(F("Resetting I2C Master control...")); - resetI2CMaster(); - delay(20); - DEBUG_PRINTLN(F("Setting clock source to Z Gyro...")); - setClockSource(MPU6050_CLOCK_PLL_ZGYRO); - - DEBUG_PRINTLN(F("Setting DMP and FIFO_OFLOW interrupts enabled...")); - setIntEnabled(1<= dmpGetFIFOPacketSize(); -} - -// uint8_t MPU6050::dmpSetFIFORate(uint8_t fifoRate); -// uint8_t MPU6050::dmpGetFIFORate(); -// uint8_t MPU6050::dmpGetSampleStepSizeMS(); -// uint8_t MPU6050::dmpGetSampleFrequency(); -// int32_t MPU6050::dmpDecodeTemperature(int8_t tempReg); - -//uint8_t MPU6050::dmpRegisterFIFORateProcess(inv_obj_func func, int16_t priority); -//uint8_t MPU6050::dmpUnregisterFIFORateProcess(inv_obj_func func); -//uint8_t MPU6050::dmpRunFIFORateProcesses(); - -// uint8_t MPU6050::dmpSendQuaternion(uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendGyro(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendAccel(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendLinearAccel(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendLinearAccelInWorld(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendControlData(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendSensorData(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendExternalSensorData(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendGravity(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendPacketNumber(uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendQuantizedAccel(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendEIS(uint_fast16_t elements, uint_fast16_t accuracy); - -uint8_t MPU6050::dmpGetAccel(int32_t *data, const uint8_t* packet) { - // TODO: accommodate different arrangements of sent data (ONLY default supported now) - if (packet == 0) packet = dmpPacketBuffer; - data[0] = (((uint32_t)packet[28] << 24) | ((uint32_t)packet[29] << 16) | ((uint32_t)packet[30] << 8) | packet[31]); - data[1] = (((uint32_t)packet[32] << 24) | ((uint32_t)packet[33] << 16) | ((uint32_t)packet[34] << 8) | packet[35]); - data[2] = (((uint32_t)packet[36] << 24) | ((uint32_t)packet[37] << 16) | ((uint32_t)packet[38] << 8) | packet[39]); - return 0; -} -uint8_t MPU6050::dmpGetAccel(int16_t *data, const uint8_t* packet) { - // TODO: accommodate different arrangements of sent data (ONLY default supported now) - if (packet == 0) packet = dmpPacketBuffer; - data[0] = (packet[28] << 8) | packet[29]; - data[1] = (packet[32] << 8) | packet[33]; - data[2] = (packet[36] << 8) | packet[37]; - return 0; -} -uint8_t MPU6050::dmpGetAccel(VectorInt16 *v, const uint8_t* packet) { - // TODO: accommodate different arrangements of sent data (ONLY default supported now) - if (packet == 0) packet = dmpPacketBuffer; - v -> x = (packet[28] << 8) | packet[29]; - v -> y = (packet[32] << 8) | packet[33]; - v -> z = (packet[36] << 8) | packet[37]; - return 0; -} -uint8_t MPU6050::dmpGetQuaternion(int32_t *data, const uint8_t* packet) { - // TODO: accommodate different arrangements of sent data (ONLY default supported now) - if (packet == 0) packet = dmpPacketBuffer; - data[0] = (((uint32_t)packet[0] << 24) | ((uint32_t)packet[1] << 16) | ((uint32_t)packet[2] << 8) | packet[3]); - data[1] = (((uint32_t)packet[4] << 24) | ((uint32_t)packet[5] << 16) | ((uint32_t)packet[6] << 8) | packet[7]); - data[2] = (((uint32_t)packet[8] << 24) | ((uint32_t)packet[9] << 16) | ((uint32_t)packet[10] << 8) | packet[11]); - data[3] = (((uint32_t)packet[12] << 24) | ((uint32_t)packet[13] << 16) | ((uint32_t)packet[14] << 8) | packet[15]); - return 0; -} -uint8_t MPU6050::dmpGetQuaternion(int16_t *data, const uint8_t* packet) { - // TODO: accommodate different arrangements of sent data (ONLY default supported now) - if (packet == 0) packet = dmpPacketBuffer; - data[0] = ((packet[0] << 8) | packet[1]); - data[1] = ((packet[4] << 8) | packet[5]); - data[2] = ((packet[8] << 8) | packet[9]); - data[3] = ((packet[12] << 8) | packet[13]); - return 0; -} -uint8_t MPU6050::dmpGetQuaternion(Quaternion *q, const uint8_t* packet) { - // TODO: accommodate different arrangements of sent data (ONLY default supported now) - int16_t qI[4]; - uint8_t status = dmpGetQuaternion(qI, packet); - if (status == 0) { - q -> w = (float)qI[0] / 16384.0f; - q -> x = (float)qI[1] / 16384.0f; - q -> y = (float)qI[2] / 16384.0f; - q -> z = (float)qI[3] / 16384.0f; - return 0; - } - return status; // int16 return value, indicates error if this line is reached -} -// uint8_t MPU6050::dmpGet6AxisQuaternion(long *data, const uint8_t* packet); -// uint8_t MPU6050::dmpGetRelativeQuaternion(long *data, const uint8_t* packet); -uint8_t MPU6050::dmpGetGyro(int32_t *data, const uint8_t* packet) { - // TODO: accommodate different arrangements of sent data (ONLY default supported now) - if (packet == 0) packet = dmpPacketBuffer; - data[0] = (((uint32_t)packet[16] << 24) | ((uint32_t)packet[17] << 16) | ((uint32_t)packet[18] << 8) | packet[19]); - data[1] = (((uint32_t)packet[20] << 24) | ((uint32_t)packet[21] << 16) | ((uint32_t)packet[22] << 8) | packet[23]); - data[2] = (((uint32_t)packet[24] << 24) | ((uint32_t)packet[25] << 16) | ((uint32_t)packet[26] << 8) | packet[27]); - return 0; -} -uint8_t MPU6050::dmpGetGyro(int16_t *data, const uint8_t* packet) { - // TODO: accommodate different arrangements of sent data (ONLY default supported now) - if (packet == 0) packet = dmpPacketBuffer; - data[0] = (packet[16] << 8) | packet[17]; - data[1] = (packet[20] << 8) | packet[21]; - data[2] = (packet[24] << 8) | packet[25]; - return 0; -} -uint8_t MPU6050::dmpGetGyro(VectorInt16 *v, const uint8_t* packet) { - // TODO: accommodate different arrangements of sent data (ONLY default supported now) - if (packet == 0) packet = dmpPacketBuffer; - v -> x = (packet[16] << 8) | packet[17]; - v -> y = (packet[20] << 8) | packet[21]; - v -> z = (packet[24] << 8) | packet[25]; - return 0; -} -// uint8_t MPU6050::dmpSetLinearAccelFilterCoefficient(float coef); -// uint8_t MPU6050::dmpGetLinearAccel(long *data, const uint8_t* packet); -uint8_t MPU6050::dmpGetLinearAccel(VectorInt16 *v, VectorInt16 *vRaw, VectorFloat *gravity) { - // get rid of the gravity component (+1g = +8192 in standard DMP FIFO packet, sensitivity is 2g) - v -> x = vRaw -> x - gravity -> x*8192; - v -> y = vRaw -> y - gravity -> y*8192; - v -> z = vRaw -> z - gravity -> z*8192; - return 0; -} -// uint8_t MPU6050::dmpGetLinearAccelInWorld(long *data, const uint8_t* packet); -uint8_t MPU6050::dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Quaternion *q) { - // rotate measured 3D acceleration vector into original state - // frame of reference based on orientation quaternion - memcpy(v, vReal, sizeof(VectorInt16)); - v -> rotate(q); - return 0; -} -// uint8_t MPU6050::dmpGetGyroAndAccelSensor(long *data, const uint8_t* packet); -// uint8_t MPU6050::dmpGetGyroSensor(long *data, const uint8_t* packet); -// uint8_t MPU6050::dmpGetControlData(long *data, const uint8_t* packet); -// uint8_t MPU6050::dmpGetTemperature(long *data, const uint8_t* packet); -// uint8_t MPU6050::dmpGetGravity(long *data, const uint8_t* packet); -uint8_t MPU6050::dmpGetGravity(int16_t *data, const uint8_t* packet) { - /* +1g corresponds to +8192, sensitivity is 2g. */ - int16_t qI[4]; - uint8_t status = dmpGetQuaternion(qI, packet); - data[0] = ((int32_t)qI[1] * qI[3] - (int32_t)qI[0] * qI[2]) / 16384; - data[1] = ((int32_t)qI[0] * qI[1] + (int32_t)qI[2] * qI[3]) / 16384; - data[2] = ((int32_t)qI[0] * qI[0] - (int32_t)qI[1] * qI[1] - - (int32_t)qI[2] * qI[2] + (int32_t)qI[3] * qI[3]) / (int32_t)(2 * 16384); - return status; -} - -uint8_t MPU6050::dmpGetGravity(VectorFloat *v, Quaternion *q) { - v -> x = 2 * (q -> x*q -> z - q -> w*q -> y); - v -> y = 2 * (q -> w*q -> x + q -> y*q -> z); - v -> z = q -> w*q -> w - q -> x*q -> x - q -> y*q -> y + q -> z*q -> z; - return 0; -} -// uint8_t MPU6050::dmpGetUnquantizedAccel(long *data, const uint8_t* packet); -// uint8_t MPU6050::dmpGetQuantizedAccel(long *data, const uint8_t* packet); -// uint8_t MPU6050::dmpGetExternalSensorData(long *data, int size, const uint8_t* packet); -// uint8_t MPU6050::dmpGetEIS(long *data, const uint8_t* packet); - -uint8_t MPU6050::dmpGetEuler(float *data, Quaternion *q) { - data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1); // psi - data[1] = -asin(2*q -> x*q -> z + 2*q -> w*q -> y); // theta - data[2] = atan2(2*q -> y*q -> z - 2*q -> w*q -> x, 2*q -> w*q -> w + 2*q -> z*q -> z - 1); // phi - return 0; -} - -#ifdef USE_OLD_DMPGETYAWPITCHROLL -uint8_t MPU6050::dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity) { - // yaw: (about Z axis) - data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1); - // pitch: (nose up/down, about Y axis) - data[1] = atan(gravity -> x / sqrt(gravity -> y*gravity -> y + gravity -> z*gravity -> z)); - // roll: (tilt left/right, about X axis) - data[2] = atan(gravity -> y / sqrt(gravity -> x*gravity -> x + gravity -> z*gravity -> z)); - return 0; -} -#else -uint8_t MPU6050::dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity) { - // yaw: (about Z axis) - data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1); - // pitch: (nose up/down, about Y axis) - data[1] = atan2(gravity -> x , sqrt(gravity -> y*gravity -> y + gravity -> z*gravity -> z)); - // roll: (tilt left/right, about X axis) - data[2] = atan2(gravity -> y , gravity -> z); - if (gravity -> z < 0) { - if(data[1] > 0) { - data[1] = PI - data[1]; - } else { - data[1] = -PI - data[1]; - } - } - return 0; -} -#endif - -// uint8_t MPU6050::dmpGetAccelFloat(float *data, const uint8_t* packet); -// uint8_t MPU6050::dmpGetQuaternionFloat(float *data, const uint8_t* packet); - -uint8_t MPU6050::dmpProcessFIFOPacket(const unsigned char *dmpData) { - (void)dmpData; // unused parameter - /*for (uint8_t k = 0; k < dmpPacketSize; k++) { - if (dmpData[k] < 0x10) Serial.print("0"); - Serial.print(dmpData[k], HEX); - Serial.print(" "); - } - Serial.print("\n");*/ - //Serial.println((uint16_t)dmpPacketBuffer); - return 0; -} -uint8_t MPU6050::dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *processed) { - uint8_t status; - uint8_t buf[dmpPacketSize]; - for (uint8_t i = 0; i < numPackets; i++) { - // read packet from FIFO - getFIFOBytes(buf, dmpPacketSize); - - // process packet - if ((status = dmpProcessFIFOPacket(buf)) > 0) return status; - - // increment external process count variable, if supplied - if (processed != 0) (*processed)++; - } - return 0; -} - -// uint8_t MPU6050::dmpSetFIFOProcessedCallback(void (*func) (void)); - -// uint8_t MPU6050::dmpInitFIFOParam(); -// uint8_t MPU6050::dmpCloseFIFO(); -// uint8_t MPU6050::dmpSetGyroDataSource(uint_fast8_t source); -// uint8_t MPU6050::dmpDecodeQuantizedAccel(); -// uint32_t MPU6050::dmpGetGyroSumOfSquare(); -// uint32_t MPU6050::dmpGetAccelSumOfSquare(); -// void MPU6050::dmpOverrideQuaternion(long *q); -uint16_t MPU6050::dmpGetFIFOPacketSize() { - return dmpPacketSize; -} - - - -uint8_t MPU6050::dmpGetCurrentFIFOPacket(uint8_t *data) { // overflow proof - return(GetCurrentFIFOPacket(data, dmpPacketSize)); -} - #endif /* _MPU6050_6AXIS_MOTIONAPPS20_H_ */ diff --git a/Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h b/Arduino/MPU6050/MPU6050_6Axis_MotionApps612.cpp similarity index 97% rename from Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h rename to Arduino/MPU6050/MPU6050_6Axis_MotionApps612.cpp index 6f069f82..fa91c7a9 100644 --- a/Arduino/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h +++ b/Arduino/MPU6050/MPU6050_6Axis_MotionApps612.cpp @@ -4,11 +4,12 @@ // Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib // // Changelog: -// 2019/7/10 - I incorporated DMP Firmware Version 6.12 Latest as of today with many features and bug fixes. -// - MPU6050 Registers have not changed just the DMP Image so that full backwards compatibility is present -// - Run-time calibration routine is enabled which calibrates after no motion state is detected -// - once no motion state is detected Calibration completes within 0.5 seconds -// - The Drawback is that the firmware image is larger. +// 2021/09/27 - split implementations out of header files, finally +// 2019/07/10 - I incorporated DMP Firmware Version 6.12 Latest as of today with many features and bug fixes. +// - MPU6050 Registers have not changed just the DMP Image so that full backwards compatibility is present +// - Run-time calibration routine is enabled which calibrates after no motion state is detected +// - once no motion state is detected Calibration completes within 0.5 seconds +// - The Drawback is that the firmware image is larger. // ... - ongoing debug release /* ============================================ @@ -35,16 +36,10 @@ THE SOFTWARE. =============================================== */ -#ifndef _MPU6050_6AXIS_MOTIONAPPS20_H_ -#define _MPU6050_6AXIS_MOTIONAPPS20_H_ - -#include "I2Cdev.h" -#include "helper_3dmath.h" - // MotionApps 2.0 DMP implementation, built using the MPU-6050EVB evaluation board -#define MPU6050_INCLUDE_DMP_MOTIONAPPS20 // same definitions Should work with V6.12 +#define MPU6050_INCLUDE_DMP_MOTIONAPPS612 -#include "MPU6050.h" +#include "MPU6050_6Axis_MotionApps612.h" // Tom Carpenter's conditional PROGMEM code // http://forum.arduino.cc/index.php?topic=129407.0 @@ -521,7 +516,7 @@ uint8_t MPU6050::dmpGetGravity(int16_t *data, const uint8_t* packet) { data[0] = ((int32_t)qI[1] * qI[3] - (int32_t)qI[0] * qI[2]) / 16384; data[1] = ((int32_t)qI[0] * qI[1] + (int32_t)qI[2] * qI[3]) / 16384; data[2] = ((int32_t)qI[0] * qI[0] - (int32_t)qI[1] * qI[1] - - (int32_t)qI[2] * qI[2] + (int32_t)qI[3] * qI[3]) / (2 * 16384); + - (int32_t)qI[2] * qI[2] + (int32_t)qI[3] * qI[3]) / (int32_t)(2 * 16384L); return status; } @@ -620,5 +615,3 @@ uint16_t MPU6050::dmpGetFIFOPacketSize() { uint8_t MPU6050::dmpGetCurrentFIFOPacket(uint8_t *data) { // overflow proof return(GetCurrentFIFOPacket(data, dmpPacketSize)); } - -#endif /* _MPU6050_6AXIS_MOTIONAPPS20_H_ */ diff --git a/Arduino/MPU6050/MPU6050_6Axis_MotionApps612.h b/Arduino/MPU6050/MPU6050_6Axis_MotionApps612.h new file mode 100644 index 00000000..8557c576 --- /dev/null +++ b/Arduino/MPU6050/MPU6050_6Axis_MotionApps612.h @@ -0,0 +1,151 @@ +// I2Cdev library collection - MPU6050 I2C device class +// Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00) +// 10/3/2011 by Jeff Rowberg +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// 2021/09/27 - split implementations out of header files, finally +// ... - ongoing debug release + +// NOTE: THIS IS ONLY A PARIAL RELEASE. THIS DEVICE CLASS IS CURRENTLY UNDERGOING ACTIVE +// DEVELOPMENT AND IS STILL MISSING SOME IMPORTANT FEATURES. PLEASE KEEP THIS IN MIND IF +// YOU DECIDE TO USE THIS PARTICULAR CODE FOR ANYTHING. + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2012 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#ifndef _MPU6050_6AXIS_MOTIONAPPS612_H_ +#define _MPU6050_6AXIS_MOTIONAPPS612_H_ + +#include "MPU6050.h" + +class MPU6050_6Axis_MotionApps612 : public MPU6050_Base { + public: + uint8_t dmpInitialize(); + bool dmpPacketAvailable(); + + uint8_t dmpSetFIFORate(uint8_t fifoRate); + uint8_t dmpGetFIFORate(); + uint8_t dmpGetSampleStepSizeMS(); + uint8_t dmpGetSampleFrequency(); + int32_t dmpDecodeTemperature(int8_t tempReg); + + // Register callbacks after a packet of FIFO data is processed + //uint8_t dmpRegisterFIFORateProcess(inv_obj_func func, int16_t priority); + //uint8_t dmpUnregisterFIFORateProcess(inv_obj_func func); + uint8_t dmpRunFIFORateProcesses(); + + // Setup FIFO for various output + uint8_t dmpSendQuaternion(uint_fast16_t accuracy); + uint8_t dmpSendGyro(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendAccel(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendLinearAccel(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendLinearAccelInWorld(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendControlData(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendSensorData(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendExternalSensorData(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendGravity(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendPacketNumber(uint_fast16_t accuracy); + uint8_t dmpSendQuantizedAccel(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendEIS(uint_fast16_t elements, uint_fast16_t accuracy); + + // Get Fixed Point data from FIFO + uint8_t dmpGetAccel(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetAccel(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetAccel(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetQuaternion(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetQuaternion(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetQuaternion(Quaternion *q, const uint8_t* packet=0); + uint8_t dmpGet6AxisQuaternion(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGet6AxisQuaternion(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGet6AxisQuaternion(Quaternion *q, const uint8_t* packet=0); + uint8_t dmpGetRelativeQuaternion(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetRelativeQuaternion(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetRelativeQuaternion(Quaternion *data, const uint8_t* packet=0); + uint8_t dmpGetGyro(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyro(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyro(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpSetLinearAccelFilterCoefficient(float coef); + uint8_t dmpGetLinearAccel(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetLinearAccel(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetLinearAccel(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetLinearAccel(VectorInt16 *v, VectorInt16 *vRaw, VectorFloat *gravity); + uint8_t dmpGetLinearAccelInWorld(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetLinearAccelInWorld(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetLinearAccelInWorld(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Quaternion *q); + uint8_t dmpGetGyroAndAccelSensor(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyroAndAccelSensor(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyroAndAccelSensor(VectorInt16 *g, VectorInt16 *a, const uint8_t* packet=0); + uint8_t dmpGetGyroSensor(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyroSensor(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyroSensor(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetControlData(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetTemperature(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetGravity(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetGravity(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetGravity(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetGravity(VectorFloat *v, Quaternion *q); + uint8_t dmpGetUnquantizedAccel(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetUnquantizedAccel(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetUnquantizedAccel(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetQuantizedAccel(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetQuantizedAccel(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetQuantizedAccel(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetExternalSensorData(int32_t *data, uint16_t size, const uint8_t* packet=0); + uint8_t dmpGetEIS(int32_t *data, const uint8_t* packet=0); + + uint8_t dmpGetEuler(float *data, Quaternion *q); + uint8_t dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity); + + // Get Floating Point data from FIFO + uint8_t dmpGetAccelFloat(float *data, const uint8_t* packet=0); + uint8_t dmpGetQuaternionFloat(float *data, const uint8_t* packet=0); + + uint8_t dmpProcessFIFOPacket(const unsigned char *dmpData); + uint8_t dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *processed=NULL); + + uint8_t dmpSetFIFOProcessedCallback(void (*func) (void)); + + uint8_t dmpInitFIFOParam(); + uint8_t dmpCloseFIFO(); + uint8_t dmpSetGyroDataSource(uint8_t source); + uint8_t dmpDecodeQuantizedAccel(); + uint32_t dmpGetGyroSumOfSquare(); + uint32_t dmpGetAccelSumOfSquare(); + void dmpOverrideQuaternion(long *q); + uint16_t dmpGetFIFOPacketSize(); + uint8_t dmpGetCurrentFIFOPacket(uint8_t *data); // overflow proof + + private: + uint8_t *dmpPacketBuffer; + uint16_t dmpPacketSize; +}; + +#ifndef I2CDEVLIB_MPU6050_TYPEDEF +#define I2CDEVLIB_MPU6050_TYPEDEF +typedef MPU6050_6Axis_MotionApps612 MPU6050; +#endif + +#endif /* _MPU6050_6AXIS_MOTIONAPPS612_H_ */ diff --git a/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.cpp b/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.cpp new file mode 100644 index 00000000..a722d3e6 --- /dev/null +++ b/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.cpp @@ -0,0 +1,887 @@ +// I2Cdev library collection - MPU6050 I2C device class, 9-axis MotionApps 4.1 implementation +// Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00) +// 6/18/2012 by Jeff Rowberg +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// 2021/09/27 - split implementations out of header files, finally + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2021 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +// MotionApps 4.1 DMP implementation, built using the MPU-9150 "MotionFit" board +#define MPU6050_INCLUDE_DMP_MOTIONAPPS41 + +#include "MPU6050_9Axis_MotionApps41.h" + +// Tom Carpenter's conditional PROGMEM code +// http://forum.arduino.cc/index.php?topic=129407.0 +#ifdef __AVR__ + #include +#elif defined(ESP32) + #include +#else + // Teensy 3.0 library conditional PROGMEM code from Paul Stoffregen + #ifndef __PGMSPACE_H_ + #define __PGMSPACE_H_ 1 + #include + + #define PROGMEM + #define PGM_P const char * + #define PSTR(str) (str) + #define F(x) x + + typedef void prog_void; + typedef char prog_char; + //typedef unsigned char prog_uchar; + typedef int8_t prog_int8_t; + typedef uint8_t prog_uint8_t; + typedef int16_t prog_int16_t; + typedef uint16_t prog_uint16_t; + typedef int32_t prog_int32_t; + typedef uint32_t prog_uint32_t; + + #define strcpy_P(dest, src) strcpy((dest), (src)) + #define strcat_P(dest, src) strcat((dest), (src)) + #define strcmp_P(a, b) strcmp((a), (b)) + + #define pgm_read_byte(addr) (*(const unsigned char *)(addr)) + #define pgm_read_word(addr) (*(const unsigned short *)(addr)) + #define pgm_read_dword(addr) (*(const unsigned long *)(addr)) + #define pgm_read_float(addr) (*(const float *)(addr)) + + #define pgm_read_byte_near(addr) pgm_read_byte(addr) + #define pgm_read_word_near(addr) pgm_read_word(addr) + #define pgm_read_dword_near(addr) pgm_read_dword(addr) + #define pgm_read_float_near(addr) pgm_read_float(addr) + #define pgm_read_byte_far(addr) pgm_read_byte(addr) + #define pgm_read_word_far(addr) pgm_read_word(addr) + #define pgm_read_dword_far(addr) pgm_read_dword(addr) + #define pgm_read_float_far(addr) pgm_read_float(addr) + #endif +#endif + +// NOTE! Enabling DEBUG adds about 3.3kB to the flash program size. +// Debug output is now working even on ATMega328P MCUs (e.g. Arduino Uno) +// after moving string constants to flash memory storage using the F() +// compiler macro (Arduino IDE 1.0+ required). + +//#define DEBUG +#ifdef DEBUG + #define DEBUG_PRINT(x) Serial.print(x) + #define DEBUG_PRINTF(x, y) Serial.print(x, y) + #define DEBUG_PRINTLN(x) Serial.println(x) + #define DEBUG_PRINTLNF(x, y) Serial.println(x, y) +#else + #define DEBUG_PRINT(x) + #define DEBUG_PRINTF(x, y) + #define DEBUG_PRINTLN(x) + #define DEBUG_PRINTLNF(x, y) +#endif + +#define MPU6050_DMP_CODE_SIZE 1962 // dmpMemory[] +#define MPU6050_DMP_CONFIG_SIZE 232 // dmpConfig[] +#define MPU6050_DMP_UPDATES_SIZE 140 // dmpUpdates[] + +/* ================================================================================================ * + | Default MotionApps v4.1 48-byte FIFO packet structure: | + | | + | [QUAT W][ ][QUAT X][ ][QUAT Y][ ][QUAT Z][ ][GYRO X][ ][GYRO Y][ ] | + | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | + | | + | [GYRO Z][ ][MAG X ][MAG Y ][MAG Z ][ACC X ][ ][ACC Y ][ ][ACC Z ][ ][ ] | + | 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | + * ================================================================================================ */ + +// this block of memory gets written to the MPU on start-up, and it seems +// to be volatile memory, so it has to be done each time (it only takes ~1 +// second though) +static const unsigned char dmpMemory[MPU6050_DMP_CODE_SIZE] PROGMEM = { + // bank 0, 256 bytes + 0xFB, 0x00, 0x00, 0x3E, 0x00, 0x0B, 0x00, 0x36, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x65, 0x00, 0x54, 0xFF, 0xEF, 0x00, 0x00, 0xFA, 0x80, 0x00, 0x0B, 0x12, 0x82, 0x00, 0x01, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x28, 0x00, 0x00, 0xFF, 0xFF, 0x45, 0x81, 0xFF, 0xFF, 0xFA, 0x72, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0xE8, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x7F, 0xFF, 0xFF, 0xFE, 0x80, 0x01, + 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3E, 0x03, 0x30, 0x40, 0x00, 0x00, 0x00, 0x02, 0xCA, 0xE3, 0x09, 0x3E, 0x80, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, + 0x41, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x2A, 0x00, 0x00, 0x16, 0x55, 0x00, 0x00, 0x21, 0x82, + 0xFD, 0x87, 0x26, 0x50, 0xFD, 0x80, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x05, 0x80, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x6F, 0x00, 0x02, 0x65, 0x32, 0x00, 0x00, 0x5E, 0xC0, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFB, 0x8C, 0x6F, 0x5D, 0xFD, 0x5D, 0x08, 0xD9, 0x00, 0x7C, 0x73, 0x3B, 0x00, 0x6C, 0x12, 0xCC, + 0x32, 0x00, 0x13, 0x9D, 0x32, 0x00, 0xD0, 0xD6, 0x32, 0x00, 0x08, 0x00, 0x40, 0x00, 0x01, 0xF4, + 0xFF, 0xE6, 0x80, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0xD6, 0x00, 0x00, 0x27, 0x10, + + // bank 1, 256 bytes + 0xFB, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFA, 0x36, 0xFF, 0xBC, 0x30, 0x8E, 0x00, 0x05, 0xFB, 0xF0, 0xFF, 0xD9, 0x5B, 0xC8, + 0xFF, 0xD0, 0x9A, 0xBE, 0x00, 0x00, 0x10, 0xA9, 0xFF, 0xF4, 0x1E, 0xB2, 0x00, 0xCE, 0xBB, 0xF7, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x0C, + 0xFF, 0xC2, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0xCF, 0x80, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x14, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x3F, 0x68, 0xB6, 0x79, 0x35, 0x28, 0xBC, 0xC6, 0x7E, 0xD1, 0x6C, + 0x80, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB2, 0x6A, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x25, 0x4D, 0x00, 0x2F, 0x70, 0x6D, 0x00, 0x00, 0x05, 0xAE, 0x00, 0x0C, 0x02, 0xD0, + + // bank 2, 256 bytes + 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x54, 0xFF, 0xEF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0xFF, 0xEF, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x78, 0xA2, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + // bank 3, 256 bytes + 0xD8, 0xDC, 0xF4, 0xD8, 0xB9, 0xAB, 0xF3, 0xF8, 0xFA, 0xF1, 0xBA, 0xA2, 0xDE, 0xB2, 0xB8, 0xB4, + 0xA8, 0x81, 0x98, 0xF7, 0x4A, 0x90, 0x7F, 0x91, 0x6A, 0xF3, 0xF9, 0xDB, 0xA8, 0xF9, 0xB0, 0xBA, + 0xA0, 0x80, 0xF2, 0xCE, 0x81, 0xF3, 0xC2, 0xF1, 0xC1, 0xF2, 0xC3, 0xF3, 0xCC, 0xA2, 0xB2, 0x80, + 0xF1, 0xC6, 0xD8, 0x80, 0xBA, 0xA7, 0xDF, 0xDF, 0xDF, 0xF2, 0xA7, 0xC3, 0xCB, 0xC5, 0xB6, 0xF0, + 0x87, 0xA2, 0x94, 0x24, 0x48, 0x70, 0x3C, 0x95, 0x40, 0x68, 0x34, 0x58, 0x9B, 0x78, 0xA2, 0xF1, + 0x83, 0x92, 0x2D, 0x55, 0x7D, 0xD8, 0xB1, 0xB4, 0xB8, 0xA1, 0xD0, 0x91, 0x80, 0xF2, 0x70, 0xF3, + 0x70, 0xF2, 0x7C, 0x80, 0xA8, 0xF1, 0x01, 0xB0, 0x98, 0x87, 0xD9, 0x43, 0xD8, 0x86, 0xC9, 0x88, + 0xBA, 0xA1, 0xF2, 0x0E, 0xB8, 0x97, 0x80, 0xF1, 0xA9, 0xDF, 0xDF, 0xDF, 0xAA, 0xDF, 0xDF, 0xDF, + 0xF2, 0xAA, 0xC5, 0xCD, 0xC7, 0xA9, 0x0C, 0xC9, 0x2C, 0x97, 0x97, 0x97, 0x97, 0xF1, 0xA9, 0x89, + 0x26, 0x46, 0x66, 0xB0, 0xB4, 0xBA, 0x80, 0xAC, 0xDE, 0xF2, 0xCA, 0xF1, 0xB2, 0x8C, 0x02, 0xA9, + 0xB6, 0x98, 0x00, 0x89, 0x0E, 0x16, 0x1E, 0xB8, 0xA9, 0xB4, 0x99, 0x2C, 0x54, 0x7C, 0xB0, 0x8A, + 0xA8, 0x96, 0x36, 0x56, 0x76, 0xF1, 0xB9, 0xAF, 0xB4, 0xB0, 0x83, 0xC0, 0xB8, 0xA8, 0x97, 0x11, + 0xB1, 0x8F, 0x98, 0xB9, 0xAF, 0xF0, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0xF1, 0xA3, 0x29, 0x55, + 0x7D, 0xAF, 0x83, 0xB5, 0x93, 0xF0, 0x00, 0x28, 0x50, 0xF5, 0xBA, 0xAD, 0x8F, 0x9F, 0x28, 0x54, + 0x7C, 0xB9, 0xF1, 0xA3, 0x86, 0x9F, 0x61, 0xA6, 0xDA, 0xDE, 0xDF, 0xDB, 0xB2, 0xB6, 0x8E, 0x9D, + 0xAE, 0xF5, 0x60, 0x68, 0x70, 0xB1, 0xB5, 0xF1, 0xDA, 0xA6, 0xDF, 0xD9, 0xA6, 0xFA, 0xA3, 0x86, + + // bank 4, 256 bytes + 0x96, 0xDB, 0x31, 0xA6, 0xD9, 0xF8, 0xDF, 0xBA, 0xA6, 0x8F, 0xC2, 0xC5, 0xC7, 0xB2, 0x8C, 0xC1, + 0xB8, 0xA2, 0xDF, 0xDF, 0xDF, 0xA3, 0xDF, 0xDF, 0xDF, 0xD8, 0xD8, 0xF1, 0xB8, 0xA8, 0xB2, 0x86, + 0xB4, 0x98, 0x0D, 0x35, 0x5D, 0xB8, 0xAA, 0x98, 0xB0, 0x87, 0x2D, 0x35, 0x3D, 0xB2, 0xB6, 0xBA, + 0xAF, 0x8C, 0x96, 0x19, 0x8F, 0x9F, 0xA7, 0x0E, 0x16, 0x1E, 0xB4, 0x9A, 0xB8, 0xAA, 0x87, 0x2C, + 0x54, 0x7C, 0xB9, 0xA3, 0xDE, 0xDF, 0xDF, 0xA3, 0xB1, 0x80, 0xF2, 0xC4, 0xCD, 0xC9, 0xF1, 0xB8, + 0xA9, 0xB4, 0x99, 0x83, 0x0D, 0x35, 0x5D, 0x89, 0xB9, 0xA3, 0x2D, 0x55, 0x7D, 0xB5, 0x93, 0xA3, + 0x0E, 0x16, 0x1E, 0xA9, 0x2C, 0x54, 0x7C, 0xB8, 0xB4, 0xB0, 0xF1, 0x97, 0x83, 0xA8, 0x11, 0x84, + 0xA5, 0x09, 0x98, 0xA3, 0x83, 0xF0, 0xDA, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0xD8, 0xF1, 0xA5, + 0x29, 0x55, 0x7D, 0xA5, 0x85, 0x95, 0x02, 0x1A, 0x2E, 0x3A, 0x56, 0x5A, 0x40, 0x48, 0xF9, 0xF3, + 0xA3, 0xD9, 0xF8, 0xF0, 0x98, 0x83, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0x97, 0x82, 0xA8, 0xF1, + 0x11, 0xF0, 0x98, 0xA2, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0xDA, 0xF3, 0xDE, 0xD8, 0x83, 0xA5, + 0x94, 0x01, 0xD9, 0xA3, 0x02, 0xF1, 0xA2, 0xC3, 0xC5, 0xC7, 0xD8, 0xF1, 0x84, 0x92, 0xA2, 0x4D, + 0xDA, 0x2A, 0xD8, 0x48, 0x69, 0xD9, 0x2A, 0xD8, 0x68, 0x55, 0xDA, 0x32, 0xD8, 0x50, 0x71, 0xD9, + 0x32, 0xD8, 0x70, 0x5D, 0xDA, 0x3A, 0xD8, 0x58, 0x79, 0xD9, 0x3A, 0xD8, 0x78, 0x93, 0xA3, 0x4D, + 0xDA, 0x2A, 0xD8, 0x48, 0x69, 0xD9, 0x2A, 0xD8, 0x68, 0x55, 0xDA, 0x32, 0xD8, 0x50, 0x71, 0xD9, + 0x32, 0xD8, 0x70, 0x5D, 0xDA, 0x3A, 0xD8, 0x58, 0x79, 0xD9, 0x3A, 0xD8, 0x78, 0xA8, 0x8A, 0x9A, + + // bank 5, 256 bytes + 0xF0, 0x28, 0x50, 0x78, 0x9E, 0xF3, 0x88, 0x18, 0xF1, 0x9F, 0x1D, 0x98, 0xA8, 0xD9, 0x08, 0xD8, + 0xC8, 0x9F, 0x12, 0x9E, 0xF3, 0x15, 0xA8, 0xDA, 0x12, 0x10, 0xD8, 0xF1, 0xAF, 0xC8, 0x97, 0x87, + 0x34, 0xB5, 0xB9, 0x94, 0xA4, 0x21, 0xF3, 0xD9, 0x22, 0xD8, 0xF2, 0x2D, 0xF3, 0xD9, 0x2A, 0xD8, + 0xF2, 0x35, 0xF3, 0xD9, 0x32, 0xD8, 0x81, 0xA4, 0x60, 0x60, 0x61, 0xD9, 0x61, 0xD8, 0x6C, 0x68, + 0x69, 0xD9, 0x69, 0xD8, 0x74, 0x70, 0x71, 0xD9, 0x71, 0xD8, 0xB1, 0xA3, 0x84, 0x19, 0x3D, 0x5D, + 0xA3, 0x83, 0x1A, 0x3E, 0x5E, 0x93, 0x10, 0x30, 0x81, 0x10, 0x11, 0xB8, 0xB0, 0xAF, 0x8F, 0x94, + 0xF2, 0xDA, 0x3E, 0xD8, 0xB4, 0x9A, 0xA8, 0x87, 0x29, 0xDA, 0xF8, 0xD8, 0x87, 0x9A, 0x35, 0xDA, + 0xF8, 0xD8, 0x87, 0x9A, 0x3D, 0xDA, 0xF8, 0xD8, 0xB1, 0xB9, 0xA4, 0x98, 0x85, 0x02, 0x2E, 0x56, + 0xA5, 0x81, 0x00, 0x0C, 0x14, 0xA3, 0x97, 0xB0, 0x8A, 0xF1, 0x2D, 0xD9, 0x28, 0xD8, 0x4D, 0xD9, + 0x48, 0xD8, 0x6D, 0xD9, 0x68, 0xD8, 0xB1, 0x84, 0x0D, 0xDA, 0x0E, 0xD8, 0xA3, 0x29, 0x83, 0xDA, + 0x2C, 0x0E, 0xD8, 0xA3, 0x84, 0x49, 0x83, 0xDA, 0x2C, 0x4C, 0x0E, 0xD8, 0xB8, 0xB0, 0x97, 0x86, + 0xA8, 0x31, 0x9B, 0x06, 0x99, 0x07, 0xAB, 0x97, 0x28, 0x88, 0x9B, 0xF0, 0x0C, 0x20, 0x14, 0x40, + 0xB9, 0xA3, 0x8A, 0xC3, 0xC5, 0xC7, 0x9A, 0xA3, 0x28, 0x50, 0x78, 0xF1, 0xB5, 0x93, 0x01, 0xD9, + 0xDF, 0xDF, 0xDF, 0xD8, 0xB8, 0xB4, 0xA8, 0x8C, 0x9C, 0xF0, 0x04, 0x28, 0x51, 0x79, 0x1D, 0x30, + 0x14, 0x38, 0xB2, 0x82, 0xAB, 0xD0, 0x98, 0x2C, 0x50, 0x50, 0x78, 0x78, 0x9B, 0xF1, 0x1A, 0xB0, + 0xF0, 0xB1, 0x83, 0x9C, 0xA8, 0x29, 0x51, 0x79, 0xB0, 0x8B, 0x29, 0x51, 0x79, 0xB1, 0x83, 0x24, + + // bank 6, 256 bytes + 0x70, 0x59, 0xB0, 0x8B, 0x20, 0x58, 0x71, 0xB1, 0x83, 0x44, 0x69, 0x38, 0xB0, 0x8B, 0x39, 0x40, + 0x68, 0xB1, 0x83, 0x64, 0x48, 0x31, 0xB0, 0x8B, 0x30, 0x49, 0x60, 0xA5, 0x88, 0x20, 0x09, 0x71, + 0x58, 0x44, 0x68, 0x11, 0x39, 0x64, 0x49, 0x30, 0x19, 0xF1, 0xAC, 0x00, 0x2C, 0x54, 0x7C, 0xF0, + 0x8C, 0xA8, 0x04, 0x28, 0x50, 0x78, 0xF1, 0x88, 0x97, 0x26, 0xA8, 0x59, 0x98, 0xAC, 0x8C, 0x02, + 0x26, 0x46, 0x66, 0xF0, 0x89, 0x9C, 0xA8, 0x29, 0x51, 0x79, 0x24, 0x70, 0x59, 0x44, 0x69, 0x38, + 0x64, 0x48, 0x31, 0xA9, 0x88, 0x09, 0x20, 0x59, 0x70, 0xAB, 0x11, 0x38, 0x40, 0x69, 0xA8, 0x19, + 0x31, 0x48, 0x60, 0x8C, 0xA8, 0x3C, 0x41, 0x5C, 0x20, 0x7C, 0x00, 0xF1, 0x87, 0x98, 0x19, 0x86, + 0xA8, 0x6E, 0x76, 0x7E, 0xA9, 0x99, 0x88, 0x2D, 0x55, 0x7D, 0x9E, 0xB9, 0xA3, 0x8A, 0x22, 0x8A, + 0x6E, 0x8A, 0x56, 0x8A, 0x5E, 0x9F, 0xB1, 0x83, 0x06, 0x26, 0x46, 0x66, 0x0E, 0x2E, 0x4E, 0x6E, + 0x9D, 0xB8, 0xAD, 0x00, 0x2C, 0x54, 0x7C, 0xF2, 0xB1, 0x8C, 0xB4, 0x99, 0xB9, 0xA3, 0x2D, 0x55, + 0x7D, 0x81, 0x91, 0xAC, 0x38, 0xAD, 0x3A, 0xB5, 0x83, 0x91, 0xAC, 0x2D, 0xD9, 0x28, 0xD8, 0x4D, + 0xD9, 0x48, 0xD8, 0x6D, 0xD9, 0x68, 0xD8, 0x8C, 0x9D, 0xAE, 0x29, 0xD9, 0x04, 0xAE, 0xD8, 0x51, + 0xD9, 0x04, 0xAE, 0xD8, 0x79, 0xD9, 0x04, 0xD8, 0x81, 0xF3, 0x9D, 0xAD, 0x00, 0x8D, 0xAE, 0x19, + 0x81, 0xAD, 0xD9, 0x01, 0xD8, 0xF2, 0xAE, 0xDA, 0x26, 0xD8, 0x8E, 0x91, 0x29, 0x83, 0xA7, 0xD9, + 0xAD, 0xAD, 0xAD, 0xAD, 0xF3, 0x2A, 0xD8, 0xD8, 0xF1, 0xB0, 0xAC, 0x89, 0x91, 0x3E, 0x5E, 0x76, + 0xF3, 0xAC, 0x2E, 0x2E, 0xF1, 0xB1, 0x8C, 0x5A, 0x9C, 0xAC, 0x2C, 0x28, 0x28, 0x28, 0x9C, 0xAC, + + // bank 7, 170 bytes (remainder) + 0x30, 0x18, 0xA8, 0x98, 0x81, 0x28, 0x34, 0x3C, 0x97, 0x24, 0xA7, 0x28, 0x34, 0x3C, 0x9C, 0x24, + 0xF2, 0xB0, 0x89, 0xAC, 0x91, 0x2C, 0x4C, 0x6C, 0x8A, 0x9B, 0x2D, 0xD9, 0xD8, 0xD8, 0x51, 0xD9, + 0xD8, 0xD8, 0x79, 0xD9, 0xD8, 0xD8, 0xF1, 0x9E, 0x88, 0xA3, 0x31, 0xDA, 0xD8, 0xD8, 0x91, 0x2D, + 0xD9, 0x28, 0xD8, 0x4D, 0xD9, 0x48, 0xD8, 0x6D, 0xD9, 0x68, 0xD8, 0xB1, 0x83, 0x93, 0x35, 0x3D, + 0x80, 0x25, 0xDA, 0xD8, 0xD8, 0x85, 0x69, 0xDA, 0xD8, 0xD8, 0xB4, 0x93, 0x81, 0xA3, 0x28, 0x34, + 0x3C, 0xF3, 0xAB, 0x8B, 0xA3, 0x91, 0xB6, 0x09, 0xB4, 0xD9, 0xAB, 0xDE, 0xB0, 0x87, 0x9C, 0xB9, + 0xA3, 0xDD, 0xF1, 0xA3, 0xA3, 0xA3, 0xA3, 0x95, 0xF1, 0xA3, 0xA3, 0xA3, 0x9D, 0xF1, 0xA3, 0xA3, + 0xA3, 0xA3, 0xF2, 0xA3, 0xB4, 0x90, 0x80, 0xF2, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, + 0xA3, 0xA3, 0xB2, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xB0, 0x87, 0xB5, 0x99, 0xF1, 0xA3, 0xA3, + 0xA3, 0x98, 0xF1, 0xA3, 0xA3, 0xA3, 0xA3, 0x97, 0xA3, 0xA3, 0xA3, 0xA3, 0xF3, 0x9B, 0xA3, 0xA3, + 0xDC, 0xB9, 0xA7, 0xF1, 0x26, 0x26, 0x26, 0xD8, 0xD8, 0xFF +}; + +#ifndef MPU6050_DMP_FIFO_RATE_DIVISOR +#define MPU6050_DMP_FIFO_RATE_DIVISOR 0x03 +#endif + +static const unsigned char dmpConfig[MPU6050_DMP_CONFIG_SIZE] PROGMEM = { +// BANK OFFSET LENGTH [DATA] + 0x02, 0xEC, 0x04, 0x00, 0x47, 0x7D, 0x1A, // ? + 0x03, 0x82, 0x03, 0x4C, 0xCD, 0x6C, // FCFG_1 inv_set_gyro_calibration + 0x03, 0xB2, 0x03, 0x36, 0x56, 0x76, // FCFG_3 inv_set_gyro_calibration + 0x00, 0x68, 0x04, 0x02, 0xCA, 0xE3, 0x09, // D_0_104 inv_set_gyro_calibration + 0x01, 0x0C, 0x04, 0x00, 0x00, 0x00, 0x00, // D_1_152 inv_set_accel_calibration + 0x03, 0x86, 0x03, 0x0C, 0xC9, 0x2C, // FCFG_2 inv_set_accel_calibration + 0x03, 0x90, 0x03, 0x26, 0x46, 0x66, // (continued)...FCFG_2 inv_set_accel_calibration + 0x00, 0x6C, 0x02, 0x40, 0x00, // D_0_108 inv_set_accel_calibration + + 0x02, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_00 inv_set_compass_calibration + 0x02, 0x44, 0x04, 0x40, 0x00, 0x00, 0x00, // CPASS_MTX_01 + 0x02, 0x48, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_02 + 0x02, 0x4C, 0x04, 0x40, 0x00, 0x00, 0x00, // CPASS_MTX_10 + 0x02, 0x50, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_11 + 0x02, 0x54, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_12 + 0x02, 0x58, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_20 + 0x02, 0x5C, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_21 + 0x02, 0xBC, 0x04, 0xC0, 0x00, 0x00, 0x00, // CPASS_MTX_22 + + 0x01, 0xEC, 0x04, 0x00, 0x00, 0x40, 0x00, // D_1_236 inv_apply_endian_accel + 0x03, 0x86, 0x06, 0x0C, 0xC9, 0x2C, 0x97, 0x97, 0x97, // FCFG_2 inv_set_mpu_sensors + 0x04, 0x22, 0x03, 0x0D, 0x35, 0x5D, // CFG_MOTION_BIAS inv_turn_on_bias_from_no_motion + 0x00, 0xA3, 0x01, 0x00, // ? + 0x04, 0x29, 0x04, 0x87, 0x2D, 0x35, 0x3D, // FCFG_5 inv_set_bias_update + 0x07, 0x62, 0x05, 0xF1, 0x20, 0x28, 0x30, 0x38, // CFG_8 inv_send_quaternion + 0x07, 0x9F, 0x01, 0x30, // CFG_16 inv_set_footer + 0x07, 0x67, 0x01, 0x9A, // CFG_GYRO_SOURCE inv_send_gyro + 0x07, 0x68, 0x04, 0xF1, 0x28, 0x30, 0x38, // CFG_9 inv_send_gyro -> inv_construct3_fifo + 0x07, 0x62, 0x05, 0xF1, 0x20, 0x28, 0x30, 0x38, // ? + 0x02, 0x0C, 0x04, 0x00, 0x00, 0x00, 0x00, // ? + 0x07, 0x83, 0x06, 0xC2, 0xCA, 0xC4, 0xA3, 0xA3, 0xA3, // ? + // SPECIAL 0x01 = enable interrupts + 0x00, 0x00, 0x00, 0x01, // SET INT_ENABLE, SPECIAL INSTRUCTION + 0x07, 0xA7, 0x01, 0xFE, // ? + 0x07, 0x62, 0x05, 0xF1, 0x20, 0x28, 0x30, 0x38, // ? + 0x07, 0x67, 0x01, 0x9A, // ? + 0x07, 0x68, 0x04, 0xF1, 0x28, 0x30, 0x38, // CFG_12 inv_send_accel -> inv_construct3_fifo + 0x07, 0x8D, 0x04, 0xF1, 0x28, 0x30, 0x38, // ??? CFG_12 inv_send_mag -> inv_construct3_fifo + 0x02, 0x16, 0x02, 0x00, MPU6050_DMP_FIFO_RATE_DIVISOR // D_0_22 inv_set_fifo_rate + + // This very last 0x03 WAS a 0x09, which drops the FIFO rate down to 20 Hz. 0x07 is 25 Hz, + // 0x01 is 100Hz. Going faster than 100Hz (0x00=200Hz) tends to result in very noisy data. + // DMP output frequency is calculated easily using this equation: (200Hz / (1 + value)) + + // It is important to make sure the host processor can keep up with reading and processing + // the FIFO output at the desired rate. Handling FIFO overflow cleanly is also a good idea. +}; + +const unsigned char dmpUpdates[MPU6050_DMP_UPDATES_SIZE] PROGMEM = { + 0x01, 0xB2, 0x02, 0xFF, 0xF5, + 0x01, 0x90, 0x04, 0x0A, 0x0D, 0x97, 0xC0, + 0x00, 0xA3, 0x01, 0x00, + 0x04, 0x29, 0x04, 0x87, 0x2D, 0x35, 0x3D, + 0x01, 0x6A, 0x02, 0x06, 0x00, + 0x01, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x04, 0x40, 0x00, 0x00, 0x00, + 0x02, 0x60, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x08, 0x02, 0x01, 0x20, + 0x01, 0x0A, 0x02, 0x00, 0x4E, + 0x01, 0x02, 0x02, 0xFE, 0xB3, + 0x02, 0x6C, 0x04, 0x00, 0x00, 0x00, 0x00, // READ + 0x02, 0x6C, 0x04, 0xFA, 0xFE, 0x00, 0x00, + 0x02, 0x60, 0x0C, 0xFF, 0xFF, 0xCB, 0x4D, 0x00, 0x01, 0x08, 0xC1, 0xFF, 0xFF, 0xBC, 0x2C, + 0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x02, 0xF8, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x02, 0xFC, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x04, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x04, 0x00, 0x40, 0x00, 0x00 +}; + +uint8_t MPU6050_9Axis_MotionApps41::dmpInitialize() { + // reset device + DEBUG_PRINTLN(F("\n\nResetting MPU6050...")); + reset(); + delay(30); // wait after reset + + // disable sleep mode + DEBUG_PRINTLN(F("Disabling sleep mode...")); + setSleepEnabled(false); + + // get MPU product ID + DEBUG_PRINTLN(F("Getting product ID...")); + //uint8_t productID = 0; //getProductID(); + DEBUG_PRINT(F("Product ID = ")); + DEBUG_PRINT(productID); + + // get MPU hardware revision + DEBUG_PRINTLN(F("Selecting user bank 16...")); + setMemoryBank(0x10, true, true); + DEBUG_PRINTLN(F("Selecting memory byte 6...")); + setMemoryStartAddress(0x06); + DEBUG_PRINTLN(F("Checking hardware revision...")); + uint8_t hwRevision = readMemoryByte(); + (void)hwRevision; // suppress unused variable compile warning + DEBUG_PRINT(F("Revision @ user[16][6] = ")); + DEBUG_PRINTLNF(hwRevision, HEX); + DEBUG_PRINTLN(F("Resetting memory bank selection to 0...")); + setMemoryBank(0, false, false); + + // check OTP bank valid + DEBUG_PRINTLN(F("Reading OTP bank valid flag...")); + uint8_t otpValid = getOTPBankValid(); + (void)otpValid; // suppress unused variable compile warning + DEBUG_PRINT(F("OTP bank is ")); + DEBUG_PRINTLN(otpValid ? F("valid!") : F("invalid!")); + + // get X/Y/Z gyro offsets + DEBUG_PRINTLN(F("Reading gyro offset values...")); + int8_t xgOffset = getXGyroOffset(); + int8_t ygOffset = getYGyroOffset(); + int8_t zgOffset = getZGyroOffset(); + DEBUG_PRINT(F("X gyro offset = ")); + DEBUG_PRINTLN(xgOffset); + DEBUG_PRINT(F("Y gyro offset = ")); + DEBUG_PRINTLN(ygOffset); + DEBUG_PRINT(F("Z gyro offset = ")); + DEBUG_PRINTLN(zgOffset); + + I2Cdev::readByte(devAddr, MPU6050_RA_USER_CTRL, buffer); // ? + + DEBUG_PRINTLN(F("Enabling interrupt latch, clear on any read, AUX bypass enabled")); + I2Cdev::writeByte(devAddr, MPU6050_RA_INT_PIN_CFG, 0x32); + + // enable MPU AUX I2C bypass mode + //DEBUG_PRINTLN(F("Enabling AUX I2C bypass mode...")); + //setI2CBypassEnabled(true); + + DEBUG_PRINTLN(F("Setting magnetometer mode to power-down...")); + //mag -> setMode(0); + I2Cdev::writeByte(0x0E, 0x0A, 0x00); + + DEBUG_PRINTLN(F("Setting magnetometer mode to fuse access...")); + //mag -> setMode(0x0F); + I2Cdev::writeByte(0x0E, 0x0A, 0x0F); + + DEBUG_PRINTLN(F("Reading mag magnetometer factory calibration...")); + int8_t asax, asay, asaz; + //mag -> getAdjustment(&asax, &asay, &asaz); + I2Cdev::readBytes(0x0E, 0x10, 3, buffer); + asax = (int8_t)buffer[0]; + asay = (int8_t)buffer[1]; + asaz = (int8_t)buffer[2]; + (void)asax; // suppress unused variable compiler warning + (void)asay; // suppress unused variable compiler warning + (void)asaz; // suppress unused variable compiler warning + DEBUG_PRINT(F("Adjustment X/Y/Z = ")); + DEBUG_PRINT(asax); + DEBUG_PRINT(F(" / ")); + DEBUG_PRINT(asay); + DEBUG_PRINT(F(" / ")); + DEBUG_PRINTLN(asaz); + + DEBUG_PRINTLN(F("Setting magnetometer mode to power-down...")); + //mag -> setMode(0); + I2Cdev::writeByte(0x0E, 0x0A, 0x00); + + // load DMP code into memory banks + DEBUG_PRINT(F("Writing DMP code to MPU memory banks (")); + DEBUG_PRINT(MPU6050_DMP_CODE_SIZE); + DEBUG_PRINTLN(F(" bytes)")); + if (writeProgMemoryBlock(dmpMemory, MPU6050_DMP_CODE_SIZE)) { + DEBUG_PRINTLN(F("Success! DMP code written and verified.")); + + DEBUG_PRINTLN(F("Configuring DMP and related settings...")); + + // write DMP configuration + DEBUG_PRINT(F("Writing DMP configuration to MPU memory banks (")); + DEBUG_PRINT(MPU6050_DMP_CONFIG_SIZE); + DEBUG_PRINTLN(F(" bytes in config def)")); + if (writeProgDMPConfigurationSet(dmpConfig, MPU6050_DMP_CONFIG_SIZE)) { + DEBUG_PRINTLN(F("Success! DMP configuration written and verified.")); + + DEBUG_PRINTLN(F("Setting DMP and FIFO_OFLOW interrupts enabled...")); + setIntEnabled(1< setMode(1); + I2Cdev::writeByte(0x0E, 0x0A, 0x01); + + // setup AK8975 (0x0E) as Slave 0 in read mode + DEBUG_PRINTLN(F("Setting up AK8975 read slave 0...")); + I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV0_ADDR, 0x8E); + I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV0_REG, 0x01); + I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV0_CTRL, 0xDA); + + // setup AK8975 (0x0E) as Slave 2 in write mode + DEBUG_PRINTLN(F("Setting up AK8975 write slave 2...")); + I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV2_ADDR, 0x0E); + I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV2_REG, 0x0A); + I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV2_CTRL, 0x81); + I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV2_DO, 0x01); + + // setup I2C timing/delay control + DEBUG_PRINTLN(F("Setting up slave access delay...")); + I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV4_CTRL, 0x18); + I2Cdev::writeByte(0x68, MPU6050_RA_I2C_MST_DELAY_CTRL, 0x05); + + // enable interrupts + DEBUG_PRINTLN(F("Enabling default interrupt behavior/no bypass...")); + I2Cdev::writeByte(0x68, MPU6050_RA_INT_PIN_CFG, 0x00); + + // enable I2C master mode and reset DMP/FIFO + DEBUG_PRINTLN(F("Enabling I2C master mode...")); + I2Cdev::writeByte(0x68, MPU6050_RA_USER_CTRL, 0x20); + DEBUG_PRINTLN(F("Resetting FIFO...")); + I2Cdev::writeByte(0x68, MPU6050_RA_USER_CTRL, 0x24); + DEBUG_PRINTLN(F("Rewriting I2C master mode enabled because...I don't know")); + I2Cdev::writeByte(0x68, MPU6050_RA_USER_CTRL, 0x20); + DEBUG_PRINTLN(F("Enabling and resetting DMP/FIFO...")); + I2Cdev::writeByte(0x68, MPU6050_RA_USER_CTRL, 0xE8); + + DEBUG_PRINTLN(F("Writing final memory update 5/19 (function unknown)...")); + for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); + writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); + DEBUG_PRINTLN(F("Writing final memory update 6/19 (function unknown)...")); + for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); + writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); + DEBUG_PRINTLN(F("Writing final memory update 7/19 (function unknown)...")); + for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); + writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); + DEBUG_PRINTLN(F("Writing final memory update 8/19 (function unknown)...")); + for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); + writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); + DEBUG_PRINTLN(F("Writing final memory update 9/19 (function unknown)...")); + for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); + writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); + DEBUG_PRINTLN(F("Writing final memory update 10/19 (function unknown)...")); + for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); + writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); + DEBUG_PRINTLN(F("Writing final memory update 11/19 (function unknown)...")); + for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); + writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); + + DEBUG_PRINTLN(F("Reading final memory update 12/19 (function unknown)...")); + for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); + readMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); + #ifdef DEBUG + DEBUG_PRINT(F("Read bytes: ")); + for (j = 0; j < 4; j++) { + DEBUG_PRINTF(dmpUpdate[3 + j], HEX); + DEBUG_PRINT(" "); + } + DEBUG_PRINTLN(""); + #endif + + DEBUG_PRINTLN(F("Writing final memory update 13/19 (function unknown)...")); + for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); + writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); + DEBUG_PRINTLN(F("Writing final memory update 14/19 (function unknown)...")); + for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); + writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); + DEBUG_PRINTLN(F("Writing final memory update 15/19 (function unknown)...")); + for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); + writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); + DEBUG_PRINTLN(F("Writing final memory update 16/19 (function unknown)...")); + for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); + writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); + DEBUG_PRINTLN(F("Writing final memory update 17/19 (function unknown)...")); + for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); + writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); + + DEBUG_PRINTLN(F("Waiting for FIRO count >= 46...")); + while ((fifoCount = getFIFOCount()) < 46); + DEBUG_PRINTLN(F("Reading FIFO...")); + getFIFOBytes(fifoBuffer, min(fifoCount, 128)); // safeguard only 128 bytes + DEBUG_PRINTLN(F("Reading interrupt status...")); + getIntStatus(); + + DEBUG_PRINTLN(F("Writing final memory update 18/19 (function unknown)...")); + for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); + writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); + + DEBUG_PRINTLN(F("Waiting for FIRO count >= 48...")); + while ((fifoCount = getFIFOCount()) < 48); + DEBUG_PRINTLN(F("Reading FIFO...")); + getFIFOBytes(fifoBuffer, min(fifoCount, 128)); // safeguard only 128 bytes + DEBUG_PRINTLN(F("Reading interrupt status...")); + getIntStatus(); + DEBUG_PRINTLN(F("Waiting for FIRO count >= 48...")); + while ((fifoCount = getFIFOCount()) < 48); + DEBUG_PRINTLN(F("Reading FIFO...")); + getFIFOBytes(fifoBuffer, min(fifoCount, 128)); // safeguard only 128 bytes + DEBUG_PRINTLN(F("Reading interrupt status...")); + getIntStatus(); + + DEBUG_PRINTLN(F("Writing final memory update 19/19 (function unknown)...")); + for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); + writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); + + DEBUG_PRINTLN(F("Disabling DMP (you turn it on later)...")); + setDMPEnabled(false); + + DEBUG_PRINTLN(F("Setting up internal 48-byte (default) DMP packet buffer...")); + dmpPacketSize = 48; + /*if ((dmpPacketBuffer = (uint8_t *)malloc(42)) == 0) { + return 3; // TODO: proper error code for no memory + }*/ + + DEBUG_PRINTLN(F("Resetting FIFO and clearing INT status one last time...")); + resetFIFO(); + getIntStatus(); + } else { + DEBUG_PRINTLN(F("ERROR! DMP configuration verification failed.")); + return 2; // configuration block loading failed + } + } else { + DEBUG_PRINTLN(F("ERROR! DMP code verification failed.")); + return 1; // main binary block loading failed + } + return 0; // success +} + +bool MPU6050_9Axis_MotionApps41::dmpPacketAvailable() { + return getFIFOCount() >= dmpGetFIFOPacketSize(); +} + +// uint8_t MPU6050_9Axis_MotionApps41::dmpSetFIFORate(uint8_t fifoRate); +// uint8_t MPU6050_9Axis_MotionApps41::dmpGetFIFORate(); +// uint8_t MPU6050_9Axis_MotionApps41::dmpGetSampleStepSizeMS(); +// uint8_t MPU6050_9Axis_MotionApps41::dmpGetSampleFrequency(); +// int32_t MPU6050_9Axis_MotionApps41::dmpDecodeTemperature(int8_t tempReg); + +//uint8_t MPU6050_9Axis_MotionApps41::dmpRegisterFIFORateProcess(inv_obj_func func, int16_t priority); +//uint8_t MPU6050_9Axis_MotionApps41::dmpUnregisterFIFORateProcess(inv_obj_func func); +//uint8_t MPU6050_9Axis_MotionApps41::dmpRunFIFORateProcesses(); + +// uint8_t MPU6050_9Axis_MotionApps41::dmpSendQuaternion(uint_fast16_t accuracy); +// uint8_t MPU6050_9Axis_MotionApps41::dmpSendGyro(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050_9Axis_MotionApps41::dmpSendAccel(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050_9Axis_MotionApps41::dmpSendLinearAccel(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050_9Axis_MotionApps41::dmpSendLinearAccelInWorld(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050_9Axis_MotionApps41::dmpSendControlData(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050_9Axis_MotionApps41::dmpSendSensorData(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050_9Axis_MotionApps41::dmpSendExternalSensorData(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050_9Axis_MotionApps41::dmpSendGravity(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050_9Axis_MotionApps41::dmpSendPacketNumber(uint_fast16_t accuracy); +// uint8_t MPU6050_9Axis_MotionApps41::dmpSendQuantizedAccel(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050_9Axis_MotionApps41::dmpSendEIS(uint_fast16_t elements, uint_fast16_t accuracy); + +uint8_t MPU6050_9Axis_MotionApps41::dmpGetAccel(int32_t *data, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + data[0] = (((uint32_t)packet[34] << 24) | ((uint32_t)packet[35] << 16) | ((uint32_t)packet[36] << 8) | packet[37]); + data[1] = (((uint32_t)packet[38] << 24) | ((uint32_t)packet[39] << 16) | ((uint32_t)packet[40] << 8) | packet[41]); + data[2] = (((uint32_t)packet[42] << 24) | ((uint32_t)packet[43] << 16) | ((uint32_t)packet[44] << 8) | packet[45]); + return 0; +} +uint8_t MPU6050_9Axis_MotionApps41::dmpGetAccel(int16_t *data, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + data[0] = (packet[34] << 8) | packet[35]; + data[1] = (packet[38] << 8) | packet[39]; + data[2] = (packet[42] << 8) | packet[43]; + return 0; +} +uint8_t MPU6050_9Axis_MotionApps41::dmpGetAccel(VectorInt16 *v, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + v -> x = (packet[34] << 8) | packet[35]; + v -> y = (packet[38] << 8) | packet[39]; + v -> z = (packet[42] << 8) | packet[43]; + return 0; +} +uint8_t MPU6050_9Axis_MotionApps41::dmpGetQuaternion(int32_t *data, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + data[0] = (((uint32_t)packet[0] << 24) | ((uint32_t)packet[1] << 16) | ((uint32_t)packet[2] << 8) | packet[3]); + data[1] = (((uint32_t)packet[4] << 24) | ((uint32_t)packet[5] << 16) | ((uint32_t)packet[6] << 8) | packet[7]); + data[2] = (((uint32_t)packet[8] << 24) | ((uint32_t)packet[9] << 16) | ((uint32_t)packet[10] << 8) | packet[11]); + data[3] = (((uint32_t)packet[12] << 24) | ((uint32_t)packet[13] << 16) | ((uint32_t)packet[14] << 8) | packet[15]); + return 0; +} +uint8_t MPU6050_9Axis_MotionApps41::dmpGetQuaternion(int16_t *data, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + data[0] = ((packet[0] << 8) | packet[1]); + data[1] = ((packet[4] << 8) | packet[5]); + data[2] = ((packet[8] << 8) | packet[9]); + data[3] = ((packet[12] << 8) | packet[13]); + return 0; +} +uint8_t MPU6050_9Axis_MotionApps41::dmpGetQuaternion(Quaternion *q, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + int16_t qI[4]; + uint8_t status = dmpGetQuaternion(qI, packet); + if (status == 0) { + q -> w = (float)qI[0] / 16384.0f; + q -> x = (float)qI[1] / 16384.0f; + q -> y = (float)qI[2] / 16384.0f; + q -> z = (float)qI[3] / 16384.0f; + return 0; + } + return status; // int16 return value, indicates error if this line is reached +} +// uint8_t MPU6050_9Axis_MotionApps41::dmpGet6AxisQuaternion(long *data, const uint8_t* packet); +// uint8_t MPU6050_9Axis_MotionApps41::dmpGetRelativeQuaternion(long *data, const uint8_t* packet); +uint8_t MPU6050_9Axis_MotionApps41::dmpGetGyro(int32_t *data, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + data[0] = (((uint32_t)packet[16] << 24) | ((uint32_t)packet[17] << 16) | ((uint32_t)packet[18] << 8) | packet[19]); + data[1] = (((uint32_t)packet[20] << 24) | ((uint32_t)packet[21] << 16) | ((uint32_t)packet[22] << 8) | packet[23]); + data[2] = (((uint32_t)packet[24] << 24) | ((uint32_t)packet[25] << 16) | ((uint32_t)packet[26] << 8) | packet[27]); + return 0; +} +uint8_t MPU6050_9Axis_MotionApps41::dmpGetGyro(int16_t *data, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + data[0] = (packet[16] << 8) | packet[17]; + data[1] = (packet[20] << 8) | packet[21]; + data[2] = (packet[24] << 8) | packet[25]; + return 0; +} +uint8_t MPU6050_9Axis_MotionApps41::dmpGetMag(int16_t *data, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + data[0] = (packet[28] << 8) | packet[29]; + data[1] = (packet[30] << 8) | packet[31]; + data[2] = (packet[32] << 8) | packet[33]; + return 0; +} +// uint8_t MPU6050_9Axis_MotionApps41::dmpSetLinearAccelFilterCoefficient(float coef); +// uint8_t MPU6050_9Axis_MotionApps41::dmpGetLinearAccel(long *data, const uint8_t* packet); +uint8_t MPU6050_9Axis_MotionApps41::dmpGetLinearAccel(VectorInt16 *v, VectorInt16 *vRaw, VectorFloat *gravity) { + // get rid of the gravity component (+1g = +4096 in standard DMP FIFO packet) + v -> x = vRaw -> x - gravity -> x*4096; + v -> y = vRaw -> y - gravity -> y*4096; + v -> z = vRaw -> z - gravity -> z*4096; + return 0; +} +// uint8_t MPU6050_9Axis_MotionApps41::dmpGetLinearAccelInWorld(long *data, const uint8_t* packet); +uint8_t MPU6050_9Axis_MotionApps41::dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Quaternion *q) { + // rotate measured 3D acceleration vector into original state + // frame of reference based on orientation quaternion + memcpy(v, vReal, sizeof(VectorInt16)); + v -> rotate(q); + return 0; +} +// uint8_t MPU6050_9Axis_MotionApps41::dmpGetGyroAndAccelSensor(long *data, const uint8_t* packet); +// uint8_t MPU6050_9Axis_MotionApps41::dmpGetGyroSensor(long *data, const uint8_t* packet); +// uint8_t MPU6050_9Axis_MotionApps41::dmpGetControlData(long *data, const uint8_t* packet); +// uint8_t MPU6050_9Axis_MotionApps41::dmpGetTemperature(long *data, const uint8_t* packet); +// uint8_t MPU6050_9Axis_MotionApps41::dmpGetGravity(long *data, const uint8_t* packet); +uint8_t MPU6050_9Axis_MotionApps41::dmpGetGravity(int16_t *data, const uint8_t* packet) { + /* +1g corresponds to +8192, sensitivity is 2g. */ + int16_t qI[4]; + uint8_t status = dmpGetQuaternion(qI, packet); + data[0] = ((int32_t)qI[1] * qI[3] - (int32_t)qI[0] * qI[2]) / 16384; + data[1] = ((int32_t)qI[0] * qI[1] + (int32_t)qI[2] * qI[3]) / 16384; + data[2] = ((int32_t)qI[0] * qI[0] - (int32_t)qI[1] * qI[1] + - (int32_t)qI[2] * qI[2] + (int32_t)qI[3] * qI[3]) / (int32_t)(2 * 16384L); + return status; +} + +uint8_t MPU6050_9Axis_MotionApps41::dmpGetGravity(VectorFloat *v, Quaternion *q) { + v -> x = 2 * (q -> x*q -> z - q -> w*q -> y); + v -> y = 2 * (q -> w*q -> x + q -> y*q -> z); + v -> z = q -> w*q -> w - q -> x*q -> x - q -> y*q -> y + q -> z*q -> z; + return 0; +} +// uint8_t MPU6050_9Axis_MotionApps41::dmpGetUnquantizedAccel(long *data, const uint8_t* packet); +// uint8_t MPU6050_9Axis_MotionApps41::dmpGetQuantizedAccel(long *data, const uint8_t* packet); +// uint8_t MPU6050_9Axis_MotionApps41::dmpGetExternalSensorData(long *data, int size, const uint8_t* packet); +// uint8_t MPU6050_9Axis_MotionApps41::dmpGetEIS(long *data, const uint8_t* packet); + +uint8_t MPU6050_9Axis_MotionApps41::dmpGetEuler(float *data, Quaternion *q) { + data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1); // psi + data[1] = -asin(2*q -> x*q -> z + 2*q -> w*q -> y); // theta + data[2] = atan2(2*q -> y*q -> z - 2*q -> w*q -> x, 2*q -> w*q -> w + 2*q -> z*q -> z - 1); // phi + return 0; +} + +#ifdef USE_OLD_DMPGETYAWPITCHROLL +uint8_t MPU6050_9Axis_MotionApps41::dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity) { + // yaw: (about Z axis) + data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1); + // pitch: (nose up/down, about Y axis) + data[1] = atan(gravity -> x / sqrt(gravity -> y*gravity -> y + gravity -> z*gravity -> z)); + // roll: (tilt left/right, about X axis) + data[2] = atan(gravity -> y / sqrt(gravity -> x*gravity -> x + gravity -> z*gravity -> z)); + return 0; +} +#else +uint8_t MPU6050_9Axis_MotionApps41::dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity) { + // yaw: (about Z axis) + data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1); + // pitch: (nose up/down, about Y axis) + data[1] = atan2(gravity -> x , sqrt(gravity -> y*gravity -> y + gravity -> z*gravity -> z)); + // roll: (tilt left/right, about X axis) + data[2] = atan2(gravity -> y , gravity -> z); + if(gravity->z<0) { + if(data[1]>0) { + data[1] = PI - data[1]; + } else { + data[1] = -PI - data[1]; + } + } + return 0; +} +#endif + +// uint8_t MPU6050_9Axis_MotionApps41::dmpGetAccelFloat(float *data, const uint8_t* packet); +// uint8_t MPU6050_9Axis_MotionApps41::dmpGetQuaternionFloat(float *data, const uint8_t* packet); + +uint8_t MPU6050_9Axis_MotionApps41::dmpProcessFIFOPacket(const unsigned char *dmpData) { + (void)dmpData; // suppress unused variable compiler warning + /*for (uint8_t k = 0; k < dmpPacketSize; k++) { + if (dmpData[k] < 0x10) Serial.print("0"); + Serial.print(dmpData[k], HEX); + Serial.print(" "); + } + Serial.print("\n");*/ + //Serial.println((uint16_t)dmpPacketBuffer); + return 0; +} +uint8_t MPU6050_9Axis_MotionApps41::dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *processed) { + uint8_t status; + uint8_t buf[dmpPacketSize]; + for (uint8_t i = 0; i < numPackets; i++) { + // read packet from FIFO + getFIFOBytes(buf, dmpPacketSize); + + // process packet + if ((status = dmpProcessFIFOPacket(buf)) > 0) return status; + + // increment external process count variable, if supplied + if (processed != 0) (*processed)++; + } + return 0; +} + +// uint8_t MPU6050_9Axis_MotionApps41::dmpSetFIFOProcessedCallback(void (*func) (void)); + +// uint8_t MPU6050_9Axis_MotionApps41::dmpInitFIFOParam(); +// uint8_t MPU6050_9Axis_MotionApps41::dmpCloseFIFO(); +// uint8_t MPU6050_9Axis_MotionApps41::dmpSetGyroDataSource(uint_fast8_t source); +// uint8_t MPU6050_9Axis_MotionApps41::dmpDecodeQuantizedAccel(); +// uint32_t MPU6050_9Axis_MotionApps41::dmpGetGyroSumOfSquare(); +// uint32_t MPU6050_9Axis_MotionApps41::dmpGetAccelSumOfSquare(); +// void MPU6050_9Axis_MotionApps41::dmpOverrideQuaternion(long *q); +uint16_t MPU6050_9Axis_MotionApps41::dmpGetFIFOPacketSize() { + return dmpPacketSize; +} diff --git a/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h b/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h index eedc2777..14ff50b1 100644 --- a/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h +++ b/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h @@ -1,11 +1,16 @@ -// I2Cdev library collection - MPU6050 I2C device class, 9-axis MotionApps 4.1 implementation +// I2Cdev library collection - MPU6050 I2C device class // Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00) -// 6/18/2012 by Jeff Rowberg +// 10/3/2011 by Jeff Rowberg // Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib // // Changelog: +// 2021/09/27 - split implementations out of header files, finally // ... - ongoing debug release +// NOTE: THIS IS ONLY A PARIAL RELEASE. THIS DEVICE CLASS IS CURRENTLY UNDERGOING ACTIVE +// DEVELOPMENT AND IS STILL MISSING SOME IMPORTANT FEATURES. PLEASE KEEP THIS IN MIND IF +// YOU DECIDE TO USE THIS PARTICULAR CODE FOR ANYTHING. + /* ============================================ I2Cdev device library code is placed under the MIT license Copyright (c) 2012 Jeff Rowberg @@ -30,860 +35,117 @@ THE SOFTWARE. =============================================== */ -#ifndef _MPU6050_9AXIS_MOTIONAPPS41_H_ -#define _MPU6050_9AXIS_MOTIONAPPS41_H_ - -#include "I2Cdev.h" -#include "helper_3dmath.h" - -// MotionApps 4.1 DMP implementation, built using the MPU-9150 "MotionFit" board -#define MPU6050_INCLUDE_DMP_MOTIONAPPS41 +#ifndef _MPU6050_6AXIS_MOTIONAPPS41_H_ +#define _MPU6050_6AXIS_MOTIONAPPS41_H_ #include "MPU6050.h" -// Tom Carpenter's conditional PROGMEM code -// http://forum.arduino.cc/index.php?topic=129407.0 -#ifdef __AVR__ - #include -#elif defined(ESP32) - #include -#else - // Teensy 3.0 library conditional PROGMEM code from Paul Stoffregen - #ifndef __PGMSPACE_H_ - #define __PGMSPACE_H_ 1 - #include +class MPU6050_9Axis_MotionApps41 : public MPU6050_Base { + public: + uint8_t dmpInitialize(); + bool dmpPacketAvailable(); - #define PROGMEM - #define PGM_P const char * - #define PSTR(str) (str) - #define F(x) x - - typedef void prog_void; - typedef char prog_char; - //typedef unsigned char prog_uchar; - typedef int8_t prog_int8_t; - typedef uint8_t prog_uint8_t; - typedef int16_t prog_int16_t; - typedef uint16_t prog_uint16_t; - typedef int32_t prog_int32_t; - typedef uint32_t prog_uint32_t; + uint8_t dmpSetFIFORate(uint8_t fifoRate); + uint8_t dmpGetFIFORate(); + uint8_t dmpGetSampleStepSizeMS(); + uint8_t dmpGetSampleFrequency(); + int32_t dmpDecodeTemperature(int8_t tempReg); - #define strcpy_P(dest, src) strcpy((dest), (src)) - #define strcat_P(dest, src) strcat((dest), (src)) - #define strcmp_P(a, b) strcmp((a), (b)) + // Register callbacks after a packet of FIFO data is processed + //uint8_t dmpRegisterFIFORateProcess(inv_obj_func func, int16_t priority); + //uint8_t dmpUnregisterFIFORateProcess(inv_obj_func func); + uint8_t dmpRunFIFORateProcesses(); - #define pgm_read_byte(addr) (*(const unsigned char *)(addr)) - #define pgm_read_word(addr) (*(const unsigned short *)(addr)) - #define pgm_read_dword(addr) (*(const unsigned long *)(addr)) - #define pgm_read_float(addr) (*(const float *)(addr)) + // Setup FIFO for various output + uint8_t dmpSendQuaternion(uint_fast16_t accuracy); + uint8_t dmpSendGyro(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendAccel(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendLinearAccel(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendLinearAccelInWorld(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendControlData(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendSensorData(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendExternalSensorData(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendGravity(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendPacketNumber(uint_fast16_t accuracy); + uint8_t dmpSendQuantizedAccel(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendEIS(uint_fast16_t elements, uint_fast16_t accuracy); + + // Get Fixed Point data from FIFO + uint8_t dmpGetAccel(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetAccel(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetAccel(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetQuaternion(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetQuaternion(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetQuaternion(Quaternion *q, const uint8_t* packet=0); + uint8_t dmpGet6AxisQuaternion(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGet6AxisQuaternion(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGet6AxisQuaternion(Quaternion *q, const uint8_t* packet=0); + uint8_t dmpGetRelativeQuaternion(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetRelativeQuaternion(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetRelativeQuaternion(Quaternion *data, const uint8_t* packet=0); + uint8_t dmpGetGyro(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyro(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyro(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetMag(int16_t *data, const uint8_t* packet=0); + uint8_t dmpSetLinearAccelFilterCoefficient(float coef); + uint8_t dmpGetLinearAccel(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetLinearAccel(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetLinearAccel(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetLinearAccel(VectorInt16 *v, VectorInt16 *vRaw, VectorFloat *gravity); + uint8_t dmpGetLinearAccelInWorld(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetLinearAccelInWorld(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetLinearAccelInWorld(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Quaternion *q); + uint8_t dmpGetGyroAndAccelSensor(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyroAndAccelSensor(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyroAndAccelSensor(VectorInt16 *g, VectorInt16 *a, const uint8_t* packet=0); + uint8_t dmpGetGyroSensor(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyroSensor(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyroSensor(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetControlData(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetTemperature(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetGravity(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetGravity(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetGravity(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetGravity(VectorFloat *v, Quaternion *q); + uint8_t dmpGetUnquantizedAccel(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetUnquantizedAccel(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetUnquantizedAccel(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetQuantizedAccel(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetQuantizedAccel(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetQuantizedAccel(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetExternalSensorData(int32_t *data, uint16_t size, const uint8_t* packet=0); + uint8_t dmpGetEIS(int32_t *data, const uint8_t* packet=0); - #define pgm_read_byte_near(addr) pgm_read_byte(addr) - #define pgm_read_word_near(addr) pgm_read_word(addr) - #define pgm_read_dword_near(addr) pgm_read_dword(addr) - #define pgm_read_float_near(addr) pgm_read_float(addr) - #define pgm_read_byte_far(addr) pgm_read_byte(addr) - #define pgm_read_word_far(addr) pgm_read_word(addr) - #define pgm_read_dword_far(addr) pgm_read_dword(addr) - #define pgm_read_float_far(addr) pgm_read_float(addr) - #endif -#endif - -// NOTE! Enabling DEBUG adds about 3.3kB to the flash program size. -// Debug output is now working even on ATMega328P MCUs (e.g. Arduino Uno) -// after moving string constants to flash memory storage using the F() -// compiler macro (Arduino IDE 1.0+ required). - -//#define DEBUG -#ifdef DEBUG - #define DEBUG_PRINT(x) Serial.print(x) - #define DEBUG_PRINTF(x, y) Serial.print(x, y) - #define DEBUG_PRINTLN(x) Serial.println(x) - #define DEBUG_PRINTLNF(x, y) Serial.println(x, y) -#else - #define DEBUG_PRINT(x) - #define DEBUG_PRINTF(x, y) - #define DEBUG_PRINTLN(x) - #define DEBUG_PRINTLNF(x, y) -#endif - -#define MPU6050_DMP_CODE_SIZE 1962 // dmpMemory[] -#define MPU6050_DMP_CONFIG_SIZE 232 // dmpConfig[] -#define MPU6050_DMP_UPDATES_SIZE 140 // dmpUpdates[] - -/* ================================================================================================ * - | Default MotionApps v4.1 48-byte FIFO packet structure: | - | | - | [QUAT W][ ][QUAT X][ ][QUAT Y][ ][QUAT Z][ ][GYRO X][ ][GYRO Y][ ] | - | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | - | | - | [GYRO Z][ ][MAG X ][MAG Y ][MAG Z ][ACC X ][ ][ACC Y ][ ][ACC Z ][ ][ ] | - | 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | - * ================================================================================================ */ - -// this block of memory gets written to the MPU on start-up, and it seems -// to be volatile memory, so it has to be done each time (it only takes ~1 -// second though) -const unsigned char dmpMemory[MPU6050_DMP_CODE_SIZE] PROGMEM = { - // bank 0, 256 bytes - 0xFB, 0x00, 0x00, 0x3E, 0x00, 0x0B, 0x00, 0x36, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, - 0x00, 0x65, 0x00, 0x54, 0xFF, 0xEF, 0x00, 0x00, 0xFA, 0x80, 0x00, 0x0B, 0x12, 0x82, 0x00, 0x01, - 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x28, 0x00, 0x00, 0xFF, 0xFF, 0x45, 0x81, 0xFF, 0xFF, 0xFA, 0x72, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x03, 0xE8, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x7F, 0xFF, 0xFF, 0xFE, 0x80, 0x01, - 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x3E, 0x03, 0x30, 0x40, 0x00, 0x00, 0x00, 0x02, 0xCA, 0xE3, 0x09, 0x3E, 0x80, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, - 0x41, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x2A, 0x00, 0x00, 0x16, 0x55, 0x00, 0x00, 0x21, 0x82, - 0xFD, 0x87, 0x26, 0x50, 0xFD, 0x80, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x05, 0x80, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x6F, 0x00, 0x02, 0x65, 0x32, 0x00, 0x00, 0x5E, 0xC0, - 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFB, 0x8C, 0x6F, 0x5D, 0xFD, 0x5D, 0x08, 0xD9, 0x00, 0x7C, 0x73, 0x3B, 0x00, 0x6C, 0x12, 0xCC, - 0x32, 0x00, 0x13, 0x9D, 0x32, 0x00, 0xD0, 0xD6, 0x32, 0x00, 0x08, 0x00, 0x40, 0x00, 0x01, 0xF4, - 0xFF, 0xE6, 0x80, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0xD6, 0x00, 0x00, 0x27, 0x10, - - // bank 1, 256 bytes - 0xFB, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xFA, 0x36, 0xFF, 0xBC, 0x30, 0x8E, 0x00, 0x05, 0xFB, 0xF0, 0xFF, 0xD9, 0x5B, 0xC8, - 0xFF, 0xD0, 0x9A, 0xBE, 0x00, 0x00, 0x10, 0xA9, 0xFF, 0xF4, 0x1E, 0xB2, 0x00, 0xCE, 0xBB, 0xF7, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x0C, - 0xFF, 0xC2, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0xCF, 0x80, 0x00, 0x40, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x14, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x3F, 0x68, 0xB6, 0x79, 0x35, 0x28, 0xBC, 0xC6, 0x7E, 0xD1, 0x6C, - 0x80, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB2, 0x6A, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x25, 0x4D, 0x00, 0x2F, 0x70, 0x6D, 0x00, 0x00, 0x05, 0xAE, 0x00, 0x0C, 0x02, 0xD0, - - // bank 2, 256 bytes - 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x54, 0xFF, 0xEF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0xFF, 0xEF, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, - 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x78, 0xA2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - - // bank 3, 256 bytes - 0xD8, 0xDC, 0xF4, 0xD8, 0xB9, 0xAB, 0xF3, 0xF8, 0xFA, 0xF1, 0xBA, 0xA2, 0xDE, 0xB2, 0xB8, 0xB4, - 0xA8, 0x81, 0x98, 0xF7, 0x4A, 0x90, 0x7F, 0x91, 0x6A, 0xF3, 0xF9, 0xDB, 0xA8, 0xF9, 0xB0, 0xBA, - 0xA0, 0x80, 0xF2, 0xCE, 0x81, 0xF3, 0xC2, 0xF1, 0xC1, 0xF2, 0xC3, 0xF3, 0xCC, 0xA2, 0xB2, 0x80, - 0xF1, 0xC6, 0xD8, 0x80, 0xBA, 0xA7, 0xDF, 0xDF, 0xDF, 0xF2, 0xA7, 0xC3, 0xCB, 0xC5, 0xB6, 0xF0, - 0x87, 0xA2, 0x94, 0x24, 0x48, 0x70, 0x3C, 0x95, 0x40, 0x68, 0x34, 0x58, 0x9B, 0x78, 0xA2, 0xF1, - 0x83, 0x92, 0x2D, 0x55, 0x7D, 0xD8, 0xB1, 0xB4, 0xB8, 0xA1, 0xD0, 0x91, 0x80, 0xF2, 0x70, 0xF3, - 0x70, 0xF2, 0x7C, 0x80, 0xA8, 0xF1, 0x01, 0xB0, 0x98, 0x87, 0xD9, 0x43, 0xD8, 0x86, 0xC9, 0x88, - 0xBA, 0xA1, 0xF2, 0x0E, 0xB8, 0x97, 0x80, 0xF1, 0xA9, 0xDF, 0xDF, 0xDF, 0xAA, 0xDF, 0xDF, 0xDF, - 0xF2, 0xAA, 0xC5, 0xCD, 0xC7, 0xA9, 0x0C, 0xC9, 0x2C, 0x97, 0x97, 0x97, 0x97, 0xF1, 0xA9, 0x89, - 0x26, 0x46, 0x66, 0xB0, 0xB4, 0xBA, 0x80, 0xAC, 0xDE, 0xF2, 0xCA, 0xF1, 0xB2, 0x8C, 0x02, 0xA9, - 0xB6, 0x98, 0x00, 0x89, 0x0E, 0x16, 0x1E, 0xB8, 0xA9, 0xB4, 0x99, 0x2C, 0x54, 0x7C, 0xB0, 0x8A, - 0xA8, 0x96, 0x36, 0x56, 0x76, 0xF1, 0xB9, 0xAF, 0xB4, 0xB0, 0x83, 0xC0, 0xB8, 0xA8, 0x97, 0x11, - 0xB1, 0x8F, 0x98, 0xB9, 0xAF, 0xF0, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0xF1, 0xA3, 0x29, 0x55, - 0x7D, 0xAF, 0x83, 0xB5, 0x93, 0xF0, 0x00, 0x28, 0x50, 0xF5, 0xBA, 0xAD, 0x8F, 0x9F, 0x28, 0x54, - 0x7C, 0xB9, 0xF1, 0xA3, 0x86, 0x9F, 0x61, 0xA6, 0xDA, 0xDE, 0xDF, 0xDB, 0xB2, 0xB6, 0x8E, 0x9D, - 0xAE, 0xF5, 0x60, 0x68, 0x70, 0xB1, 0xB5, 0xF1, 0xDA, 0xA6, 0xDF, 0xD9, 0xA6, 0xFA, 0xA3, 0x86, - - // bank 4, 256 bytes - 0x96, 0xDB, 0x31, 0xA6, 0xD9, 0xF8, 0xDF, 0xBA, 0xA6, 0x8F, 0xC2, 0xC5, 0xC7, 0xB2, 0x8C, 0xC1, - 0xB8, 0xA2, 0xDF, 0xDF, 0xDF, 0xA3, 0xDF, 0xDF, 0xDF, 0xD8, 0xD8, 0xF1, 0xB8, 0xA8, 0xB2, 0x86, - 0xB4, 0x98, 0x0D, 0x35, 0x5D, 0xB8, 0xAA, 0x98, 0xB0, 0x87, 0x2D, 0x35, 0x3D, 0xB2, 0xB6, 0xBA, - 0xAF, 0x8C, 0x96, 0x19, 0x8F, 0x9F, 0xA7, 0x0E, 0x16, 0x1E, 0xB4, 0x9A, 0xB8, 0xAA, 0x87, 0x2C, - 0x54, 0x7C, 0xB9, 0xA3, 0xDE, 0xDF, 0xDF, 0xA3, 0xB1, 0x80, 0xF2, 0xC4, 0xCD, 0xC9, 0xF1, 0xB8, - 0xA9, 0xB4, 0x99, 0x83, 0x0D, 0x35, 0x5D, 0x89, 0xB9, 0xA3, 0x2D, 0x55, 0x7D, 0xB5, 0x93, 0xA3, - 0x0E, 0x16, 0x1E, 0xA9, 0x2C, 0x54, 0x7C, 0xB8, 0xB4, 0xB0, 0xF1, 0x97, 0x83, 0xA8, 0x11, 0x84, - 0xA5, 0x09, 0x98, 0xA3, 0x83, 0xF0, 0xDA, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0xD8, 0xF1, 0xA5, - 0x29, 0x55, 0x7D, 0xA5, 0x85, 0x95, 0x02, 0x1A, 0x2E, 0x3A, 0x56, 0x5A, 0x40, 0x48, 0xF9, 0xF3, - 0xA3, 0xD9, 0xF8, 0xF0, 0x98, 0x83, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0x97, 0x82, 0xA8, 0xF1, - 0x11, 0xF0, 0x98, 0xA2, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0xDA, 0xF3, 0xDE, 0xD8, 0x83, 0xA5, - 0x94, 0x01, 0xD9, 0xA3, 0x02, 0xF1, 0xA2, 0xC3, 0xC5, 0xC7, 0xD8, 0xF1, 0x84, 0x92, 0xA2, 0x4D, - 0xDA, 0x2A, 0xD8, 0x48, 0x69, 0xD9, 0x2A, 0xD8, 0x68, 0x55, 0xDA, 0x32, 0xD8, 0x50, 0x71, 0xD9, - 0x32, 0xD8, 0x70, 0x5D, 0xDA, 0x3A, 0xD8, 0x58, 0x79, 0xD9, 0x3A, 0xD8, 0x78, 0x93, 0xA3, 0x4D, - 0xDA, 0x2A, 0xD8, 0x48, 0x69, 0xD9, 0x2A, 0xD8, 0x68, 0x55, 0xDA, 0x32, 0xD8, 0x50, 0x71, 0xD9, - 0x32, 0xD8, 0x70, 0x5D, 0xDA, 0x3A, 0xD8, 0x58, 0x79, 0xD9, 0x3A, 0xD8, 0x78, 0xA8, 0x8A, 0x9A, - - // bank 5, 256 bytes - 0xF0, 0x28, 0x50, 0x78, 0x9E, 0xF3, 0x88, 0x18, 0xF1, 0x9F, 0x1D, 0x98, 0xA8, 0xD9, 0x08, 0xD8, - 0xC8, 0x9F, 0x12, 0x9E, 0xF3, 0x15, 0xA8, 0xDA, 0x12, 0x10, 0xD8, 0xF1, 0xAF, 0xC8, 0x97, 0x87, - 0x34, 0xB5, 0xB9, 0x94, 0xA4, 0x21, 0xF3, 0xD9, 0x22, 0xD8, 0xF2, 0x2D, 0xF3, 0xD9, 0x2A, 0xD8, - 0xF2, 0x35, 0xF3, 0xD9, 0x32, 0xD8, 0x81, 0xA4, 0x60, 0x60, 0x61, 0xD9, 0x61, 0xD8, 0x6C, 0x68, - 0x69, 0xD9, 0x69, 0xD8, 0x74, 0x70, 0x71, 0xD9, 0x71, 0xD8, 0xB1, 0xA3, 0x84, 0x19, 0x3D, 0x5D, - 0xA3, 0x83, 0x1A, 0x3E, 0x5E, 0x93, 0x10, 0x30, 0x81, 0x10, 0x11, 0xB8, 0xB0, 0xAF, 0x8F, 0x94, - 0xF2, 0xDA, 0x3E, 0xD8, 0xB4, 0x9A, 0xA8, 0x87, 0x29, 0xDA, 0xF8, 0xD8, 0x87, 0x9A, 0x35, 0xDA, - 0xF8, 0xD8, 0x87, 0x9A, 0x3D, 0xDA, 0xF8, 0xD8, 0xB1, 0xB9, 0xA4, 0x98, 0x85, 0x02, 0x2E, 0x56, - 0xA5, 0x81, 0x00, 0x0C, 0x14, 0xA3, 0x97, 0xB0, 0x8A, 0xF1, 0x2D, 0xD9, 0x28, 0xD8, 0x4D, 0xD9, - 0x48, 0xD8, 0x6D, 0xD9, 0x68, 0xD8, 0xB1, 0x84, 0x0D, 0xDA, 0x0E, 0xD8, 0xA3, 0x29, 0x83, 0xDA, - 0x2C, 0x0E, 0xD8, 0xA3, 0x84, 0x49, 0x83, 0xDA, 0x2C, 0x4C, 0x0E, 0xD8, 0xB8, 0xB0, 0x97, 0x86, - 0xA8, 0x31, 0x9B, 0x06, 0x99, 0x07, 0xAB, 0x97, 0x28, 0x88, 0x9B, 0xF0, 0x0C, 0x20, 0x14, 0x40, - 0xB9, 0xA3, 0x8A, 0xC3, 0xC5, 0xC7, 0x9A, 0xA3, 0x28, 0x50, 0x78, 0xF1, 0xB5, 0x93, 0x01, 0xD9, - 0xDF, 0xDF, 0xDF, 0xD8, 0xB8, 0xB4, 0xA8, 0x8C, 0x9C, 0xF0, 0x04, 0x28, 0x51, 0x79, 0x1D, 0x30, - 0x14, 0x38, 0xB2, 0x82, 0xAB, 0xD0, 0x98, 0x2C, 0x50, 0x50, 0x78, 0x78, 0x9B, 0xF1, 0x1A, 0xB0, - 0xF0, 0xB1, 0x83, 0x9C, 0xA8, 0x29, 0x51, 0x79, 0xB0, 0x8B, 0x29, 0x51, 0x79, 0xB1, 0x83, 0x24, - - // bank 6, 256 bytes - 0x70, 0x59, 0xB0, 0x8B, 0x20, 0x58, 0x71, 0xB1, 0x83, 0x44, 0x69, 0x38, 0xB0, 0x8B, 0x39, 0x40, - 0x68, 0xB1, 0x83, 0x64, 0x48, 0x31, 0xB0, 0x8B, 0x30, 0x49, 0x60, 0xA5, 0x88, 0x20, 0x09, 0x71, - 0x58, 0x44, 0x68, 0x11, 0x39, 0x64, 0x49, 0x30, 0x19, 0xF1, 0xAC, 0x00, 0x2C, 0x54, 0x7C, 0xF0, - 0x8C, 0xA8, 0x04, 0x28, 0x50, 0x78, 0xF1, 0x88, 0x97, 0x26, 0xA8, 0x59, 0x98, 0xAC, 0x8C, 0x02, - 0x26, 0x46, 0x66, 0xF0, 0x89, 0x9C, 0xA8, 0x29, 0x51, 0x79, 0x24, 0x70, 0x59, 0x44, 0x69, 0x38, - 0x64, 0x48, 0x31, 0xA9, 0x88, 0x09, 0x20, 0x59, 0x70, 0xAB, 0x11, 0x38, 0x40, 0x69, 0xA8, 0x19, - 0x31, 0x48, 0x60, 0x8C, 0xA8, 0x3C, 0x41, 0x5C, 0x20, 0x7C, 0x00, 0xF1, 0x87, 0x98, 0x19, 0x86, - 0xA8, 0x6E, 0x76, 0x7E, 0xA9, 0x99, 0x88, 0x2D, 0x55, 0x7D, 0x9E, 0xB9, 0xA3, 0x8A, 0x22, 0x8A, - 0x6E, 0x8A, 0x56, 0x8A, 0x5E, 0x9F, 0xB1, 0x83, 0x06, 0x26, 0x46, 0x66, 0x0E, 0x2E, 0x4E, 0x6E, - 0x9D, 0xB8, 0xAD, 0x00, 0x2C, 0x54, 0x7C, 0xF2, 0xB1, 0x8C, 0xB4, 0x99, 0xB9, 0xA3, 0x2D, 0x55, - 0x7D, 0x81, 0x91, 0xAC, 0x38, 0xAD, 0x3A, 0xB5, 0x83, 0x91, 0xAC, 0x2D, 0xD9, 0x28, 0xD8, 0x4D, - 0xD9, 0x48, 0xD8, 0x6D, 0xD9, 0x68, 0xD8, 0x8C, 0x9D, 0xAE, 0x29, 0xD9, 0x04, 0xAE, 0xD8, 0x51, - 0xD9, 0x04, 0xAE, 0xD8, 0x79, 0xD9, 0x04, 0xD8, 0x81, 0xF3, 0x9D, 0xAD, 0x00, 0x8D, 0xAE, 0x19, - 0x81, 0xAD, 0xD9, 0x01, 0xD8, 0xF2, 0xAE, 0xDA, 0x26, 0xD8, 0x8E, 0x91, 0x29, 0x83, 0xA7, 0xD9, - 0xAD, 0xAD, 0xAD, 0xAD, 0xF3, 0x2A, 0xD8, 0xD8, 0xF1, 0xB0, 0xAC, 0x89, 0x91, 0x3E, 0x5E, 0x76, - 0xF3, 0xAC, 0x2E, 0x2E, 0xF1, 0xB1, 0x8C, 0x5A, 0x9C, 0xAC, 0x2C, 0x28, 0x28, 0x28, 0x9C, 0xAC, - - // bank 7, 170 bytes (remainder) - 0x30, 0x18, 0xA8, 0x98, 0x81, 0x28, 0x34, 0x3C, 0x97, 0x24, 0xA7, 0x28, 0x34, 0x3C, 0x9C, 0x24, - 0xF2, 0xB0, 0x89, 0xAC, 0x91, 0x2C, 0x4C, 0x6C, 0x8A, 0x9B, 0x2D, 0xD9, 0xD8, 0xD8, 0x51, 0xD9, - 0xD8, 0xD8, 0x79, 0xD9, 0xD8, 0xD8, 0xF1, 0x9E, 0x88, 0xA3, 0x31, 0xDA, 0xD8, 0xD8, 0x91, 0x2D, - 0xD9, 0x28, 0xD8, 0x4D, 0xD9, 0x48, 0xD8, 0x6D, 0xD9, 0x68, 0xD8, 0xB1, 0x83, 0x93, 0x35, 0x3D, - 0x80, 0x25, 0xDA, 0xD8, 0xD8, 0x85, 0x69, 0xDA, 0xD8, 0xD8, 0xB4, 0x93, 0x81, 0xA3, 0x28, 0x34, - 0x3C, 0xF3, 0xAB, 0x8B, 0xA3, 0x91, 0xB6, 0x09, 0xB4, 0xD9, 0xAB, 0xDE, 0xB0, 0x87, 0x9C, 0xB9, - 0xA3, 0xDD, 0xF1, 0xA3, 0xA3, 0xA3, 0xA3, 0x95, 0xF1, 0xA3, 0xA3, 0xA3, 0x9D, 0xF1, 0xA3, 0xA3, - 0xA3, 0xA3, 0xF2, 0xA3, 0xB4, 0x90, 0x80, 0xF2, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, - 0xA3, 0xA3, 0xB2, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xB0, 0x87, 0xB5, 0x99, 0xF1, 0xA3, 0xA3, - 0xA3, 0x98, 0xF1, 0xA3, 0xA3, 0xA3, 0xA3, 0x97, 0xA3, 0xA3, 0xA3, 0xA3, 0xF3, 0x9B, 0xA3, 0xA3, - 0xDC, 0xB9, 0xA7, 0xF1, 0x26, 0x26, 0x26, 0xD8, 0xD8, 0xFF -}; - -#ifndef MPU6050_DMP_FIFO_RATE_DIVISOR -#define MPU6050_DMP_FIFO_RATE_DIVISOR 0x03 -#endif - -const unsigned char dmpConfig[MPU6050_DMP_CONFIG_SIZE] PROGMEM = { -// BANK OFFSET LENGTH [DATA] - 0x02, 0xEC, 0x04, 0x00, 0x47, 0x7D, 0x1A, // ? - 0x03, 0x82, 0x03, 0x4C, 0xCD, 0x6C, // FCFG_1 inv_set_gyro_calibration - 0x03, 0xB2, 0x03, 0x36, 0x56, 0x76, // FCFG_3 inv_set_gyro_calibration - 0x00, 0x68, 0x04, 0x02, 0xCA, 0xE3, 0x09, // D_0_104 inv_set_gyro_calibration - 0x01, 0x0C, 0x04, 0x00, 0x00, 0x00, 0x00, // D_1_152 inv_set_accel_calibration - 0x03, 0x86, 0x03, 0x0C, 0xC9, 0x2C, // FCFG_2 inv_set_accel_calibration - 0x03, 0x90, 0x03, 0x26, 0x46, 0x66, // (continued)...FCFG_2 inv_set_accel_calibration - 0x00, 0x6C, 0x02, 0x40, 0x00, // D_0_108 inv_set_accel_calibration - - 0x02, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_00 inv_set_compass_calibration - 0x02, 0x44, 0x04, 0x40, 0x00, 0x00, 0x00, // CPASS_MTX_01 - 0x02, 0x48, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_02 - 0x02, 0x4C, 0x04, 0x40, 0x00, 0x00, 0x00, // CPASS_MTX_10 - 0x02, 0x50, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_11 - 0x02, 0x54, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_12 - 0x02, 0x58, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_20 - 0x02, 0x5C, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_21 - 0x02, 0xBC, 0x04, 0xC0, 0x00, 0x00, 0x00, // CPASS_MTX_22 - - 0x01, 0xEC, 0x04, 0x00, 0x00, 0x40, 0x00, // D_1_236 inv_apply_endian_accel - 0x03, 0x86, 0x06, 0x0C, 0xC9, 0x2C, 0x97, 0x97, 0x97, // FCFG_2 inv_set_mpu_sensors - 0x04, 0x22, 0x03, 0x0D, 0x35, 0x5D, // CFG_MOTION_BIAS inv_turn_on_bias_from_no_motion - 0x00, 0xA3, 0x01, 0x00, // ? - 0x04, 0x29, 0x04, 0x87, 0x2D, 0x35, 0x3D, // FCFG_5 inv_set_bias_update - 0x07, 0x62, 0x05, 0xF1, 0x20, 0x28, 0x30, 0x38, // CFG_8 inv_send_quaternion - 0x07, 0x9F, 0x01, 0x30, // CFG_16 inv_set_footer - 0x07, 0x67, 0x01, 0x9A, // CFG_GYRO_SOURCE inv_send_gyro - 0x07, 0x68, 0x04, 0xF1, 0x28, 0x30, 0x38, // CFG_9 inv_send_gyro -> inv_construct3_fifo - 0x07, 0x62, 0x05, 0xF1, 0x20, 0x28, 0x30, 0x38, // ? - 0x02, 0x0C, 0x04, 0x00, 0x00, 0x00, 0x00, // ? - 0x07, 0x83, 0x06, 0xC2, 0xCA, 0xC4, 0xA3, 0xA3, 0xA3, // ? - // SPECIAL 0x01 = enable interrupts - 0x00, 0x00, 0x00, 0x01, // SET INT_ENABLE, SPECIAL INSTRUCTION - 0x07, 0xA7, 0x01, 0xFE, // ? - 0x07, 0x62, 0x05, 0xF1, 0x20, 0x28, 0x30, 0x38, // ? - 0x07, 0x67, 0x01, 0x9A, // ? - 0x07, 0x68, 0x04, 0xF1, 0x28, 0x30, 0x38, // CFG_12 inv_send_accel -> inv_construct3_fifo - 0x07, 0x8D, 0x04, 0xF1, 0x28, 0x30, 0x38, // ??? CFG_12 inv_send_mag -> inv_construct3_fifo - 0x02, 0x16, 0x02, 0x00, MPU6050_DMP_FIFO_RATE_DIVISOR // D_0_22 inv_set_fifo_rate - - // This very last 0x03 WAS a 0x09, which drops the FIFO rate down to 20 Hz. 0x07 is 25 Hz, - // 0x01 is 100Hz. Going faster than 100Hz (0x00=200Hz) tends to result in very noisy data. - // DMP output frequency is calculated easily using this equation: (200Hz / (1 + value)) - - // It is important to make sure the host processor can keep up with reading and processing - // the FIFO output at the desired rate. Handling FIFO overflow cleanly is also a good idea. -}; - -const unsigned char dmpUpdates[MPU6050_DMP_UPDATES_SIZE] PROGMEM = { - 0x01, 0xB2, 0x02, 0xFF, 0xF5, - 0x01, 0x90, 0x04, 0x0A, 0x0D, 0x97, 0xC0, - 0x00, 0xA3, 0x01, 0x00, - 0x04, 0x29, 0x04, 0x87, 0x2D, 0x35, 0x3D, - 0x01, 0x6A, 0x02, 0x06, 0x00, - 0x01, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x60, 0x04, 0x40, 0x00, 0x00, 0x00, - 0x02, 0x60, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x08, 0x02, 0x01, 0x20, - 0x01, 0x0A, 0x02, 0x00, 0x4E, - 0x01, 0x02, 0x02, 0xFE, 0xB3, - 0x02, 0x6C, 0x04, 0x00, 0x00, 0x00, 0x00, // READ - 0x02, 0x6C, 0x04, 0xFA, 0xFE, 0x00, 0x00, - 0x02, 0x60, 0x0C, 0xFF, 0xFF, 0xCB, 0x4D, 0x00, 0x01, 0x08, 0xC1, 0xFF, 0xFF, 0xBC, 0x2C, - 0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x02, 0xF8, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x02, 0xFC, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x60, 0x04, 0x40, 0x00, 0x00, 0x00, - 0x00, 0x60, 0x04, 0x00, 0x40, 0x00, 0x00 + uint8_t dmpGetEuler(float *data, Quaternion *q); + uint8_t dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity); + + // Get Floating Point data from FIFO + uint8_t dmpGetAccelFloat(float *data, const uint8_t* packet=0); + uint8_t dmpGetQuaternionFloat(float *data, const uint8_t* packet=0); + + uint8_t dmpProcessFIFOPacket(const unsigned char *dmpData); + uint8_t dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *processed=NULL); + + uint8_t dmpSetFIFOProcessedCallback(void (*func) (void)); + + uint8_t dmpInitFIFOParam(); + uint8_t dmpCloseFIFO(); + uint8_t dmpSetGyroDataSource(uint8_t source); + uint8_t dmpDecodeQuantizedAccel(); + uint32_t dmpGetGyroSumOfSquare(); + uint32_t dmpGetAccelSumOfSquare(); + void dmpOverrideQuaternion(long *q); + uint16_t dmpGetFIFOPacketSize(); + + private: + uint8_t *dmpPacketBuffer; + uint16_t dmpPacketSize; }; -uint8_t MPU6050::dmpInitialize() { - // reset device - DEBUG_PRINTLN(F("\n\nResetting MPU6050...")); - reset(); - delay(30); // wait after reset - - // disable sleep mode - DEBUG_PRINTLN(F("Disabling sleep mode...")); - setSleepEnabled(false); - - // get MPU product ID - DEBUG_PRINTLN(F("Getting product ID...")); - //uint8_t productID = 0; //getProductID(); - DEBUG_PRINT(F("Product ID = ")); - DEBUG_PRINT(productID); - - // get MPU hardware revision - DEBUG_PRINTLN(F("Selecting user bank 16...")); - setMemoryBank(0x10, true, true); - DEBUG_PRINTLN(F("Selecting memory byte 6...")); - setMemoryStartAddress(0x06); - DEBUG_PRINTLN(F("Checking hardware revision...")); - uint8_t hwRevision = readMemoryByte(); - DEBUG_PRINT(F("Revision @ user[16][6] = ")); - DEBUG_PRINTLNF(hwRevision, HEX); - DEBUG_PRINTLN(F("Resetting memory bank selection to 0...")); - setMemoryBank(0, false, false); - - // check OTP bank valid - DEBUG_PRINTLN(F("Reading OTP bank valid flag...")); - uint8_t otpValid = getOTPBankValid(); - DEBUG_PRINT(F("OTP bank is ")); - DEBUG_PRINTLN(otpValid ? F("valid!") : F("invalid!")); - - // get X/Y/Z gyro offsets - DEBUG_PRINTLN(F("Reading gyro offset values...")); - int8_t xgOffset = getXGyroOffset(); - int8_t ygOffset = getYGyroOffset(); - int8_t zgOffset = getZGyroOffset(); - DEBUG_PRINT(F("X gyro offset = ")); - DEBUG_PRINTLN(xgOffset); - DEBUG_PRINT(F("Y gyro offset = ")); - DEBUG_PRINTLN(ygOffset); - DEBUG_PRINT(F("Z gyro offset = ")); - DEBUG_PRINTLN(zgOffset); - - I2Cdev::readByte(devAddr, MPU6050_RA_USER_CTRL, buffer); // ? - - DEBUG_PRINTLN(F("Enabling interrupt latch, clear on any read, AUX bypass enabled")); - I2Cdev::writeByte(devAddr, MPU6050_RA_INT_PIN_CFG, 0x32); - - // enable MPU AUX I2C bypass mode - //DEBUG_PRINTLN(F("Enabling AUX I2C bypass mode...")); - //setI2CBypassEnabled(true); - - DEBUG_PRINTLN(F("Setting magnetometer mode to power-down...")); - //mag -> setMode(0); - I2Cdev::writeByte(0x0E, 0x0A, 0x00); - - DEBUG_PRINTLN(F("Setting magnetometer mode to fuse access...")); - //mag -> setMode(0x0F); - I2Cdev::writeByte(0x0E, 0x0A, 0x0F); - - DEBUG_PRINTLN(F("Reading mag magnetometer factory calibration...")); - int8_t asax, asay, asaz; - //mag -> getAdjustment(&asax, &asay, &asaz); - I2Cdev::readBytes(0x0E, 0x10, 3, buffer); - asax = (int8_t)buffer[0]; - asay = (int8_t)buffer[1]; - asaz = (int8_t)buffer[2]; - DEBUG_PRINT(F("Adjustment X/Y/Z = ")); - DEBUG_PRINT(asax); - DEBUG_PRINT(F(" / ")); - DEBUG_PRINT(asay); - DEBUG_PRINT(F(" / ")); - DEBUG_PRINTLN(asaz); - - DEBUG_PRINTLN(F("Setting magnetometer mode to power-down...")); - //mag -> setMode(0); - I2Cdev::writeByte(0x0E, 0x0A, 0x00); - - // load DMP code into memory banks - DEBUG_PRINT(F("Writing DMP code to MPU memory banks (")); - DEBUG_PRINT(MPU6050_DMP_CODE_SIZE); - DEBUG_PRINTLN(F(" bytes)")); - if (writeProgMemoryBlock(dmpMemory, MPU6050_DMP_CODE_SIZE)) { - DEBUG_PRINTLN(F("Success! DMP code written and verified.")); - - DEBUG_PRINTLN(F("Configuring DMP and related settings...")); - - // write DMP configuration - DEBUG_PRINT(F("Writing DMP configuration to MPU memory banks (")); - DEBUG_PRINT(MPU6050_DMP_CONFIG_SIZE); - DEBUG_PRINTLN(F(" bytes in config def)")); - if (writeProgDMPConfigurationSet(dmpConfig, MPU6050_DMP_CONFIG_SIZE)) { - DEBUG_PRINTLN(F("Success! DMP configuration written and verified.")); - - DEBUG_PRINTLN(F("Setting DMP and FIFO_OFLOW interrupts enabled...")); - setIntEnabled(1< setMode(1); - I2Cdev::writeByte(0x0E, 0x0A, 0x01); - - // setup AK8975 (0x0E) as Slave 0 in read mode - DEBUG_PRINTLN(F("Setting up AK8975 read slave 0...")); - I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV0_ADDR, 0x8E); - I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV0_REG, 0x01); - I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV0_CTRL, 0xDA); - - // setup AK8975 (0x0E) as Slave 2 in write mode - DEBUG_PRINTLN(F("Setting up AK8975 write slave 2...")); - I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV2_ADDR, 0x0E); - I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV2_REG, 0x0A); - I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV2_CTRL, 0x81); - I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV2_DO, 0x01); - - // setup I2C timing/delay control - DEBUG_PRINTLN(F("Setting up slave access delay...")); - I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV4_CTRL, 0x18); - I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, 0x05); - - // enable interrupts - DEBUG_PRINTLN(F("Enabling default interrupt behavior/no bypass...")); - I2Cdev::writeByte(devAddr, MPU6050_RA_INT_PIN_CFG, 0x00); - - // enable I2C master mode and reset DMP/FIFO - DEBUG_PRINTLN(F("Enabling I2C master mode...")); - I2Cdev::writeByte(devAddr, MPU6050_RA_USER_CTRL, 0x20); - DEBUG_PRINTLN(F("Resetting FIFO...")); - I2Cdev::writeByte(devAddr, MPU6050_RA_USER_CTRL, 0x24); - DEBUG_PRINTLN(F("Rewriting I2C master mode enabled because...I don't know")); - I2Cdev::writeByte(devAddr, MPU6050_RA_USER_CTRL, 0x20); - DEBUG_PRINTLN(F("Enabling and resetting DMP/FIFO...")); - I2Cdev::writeByte(devAddr, MPU6050_RA_USER_CTRL, 0xE8); - - DEBUG_PRINTLN(F("Writing final memory update 5/19 (function unknown)...")); - for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); - writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); - DEBUG_PRINTLN(F("Writing final memory update 6/19 (function unknown)...")); - for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); - writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); - DEBUG_PRINTLN(F("Writing final memory update 7/19 (function unknown)...")); - for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); - writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); - DEBUG_PRINTLN(F("Writing final memory update 8/19 (function unknown)...")); - for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); - writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); - DEBUG_PRINTLN(F("Writing final memory update 9/19 (function unknown)...")); - for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); - writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); - DEBUG_PRINTLN(F("Writing final memory update 10/19 (function unknown)...")); - for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); - writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); - DEBUG_PRINTLN(F("Writing final memory update 11/19 (function unknown)...")); - for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); - writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); - - DEBUG_PRINTLN(F("Reading final memory update 12/19 (function unknown)...")); - for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); - readMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); - #ifdef DEBUG - DEBUG_PRINT(F("Read bytes: ")); - for (j = 0; j < 4; j++) { - DEBUG_PRINTF(dmpUpdate[3 + j], HEX); - DEBUG_PRINT(" "); - } - DEBUG_PRINTLN(""); - #endif - - DEBUG_PRINTLN(F("Writing final memory update 13/19 (function unknown)...")); - for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); - writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); - DEBUG_PRINTLN(F("Writing final memory update 14/19 (function unknown)...")); - for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); - writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); - DEBUG_PRINTLN(F("Writing final memory update 15/19 (function unknown)...")); - for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); - writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); - DEBUG_PRINTLN(F("Writing final memory update 16/19 (function unknown)...")); - for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); - writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); - DEBUG_PRINTLN(F("Writing final memory update 17/19 (function unknown)...")); - for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); - writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); - - DEBUG_PRINTLN(F("Waiting for FIRO count >= 46...")); - while ((fifoCount = getFIFOCount()) < 46); - DEBUG_PRINTLN(F("Reading FIFO...")); - getFIFOBytes(fifoBuffer, min(fifoCount, 128)); // safeguard only 128 bytes - DEBUG_PRINTLN(F("Reading interrupt status...")); - getIntStatus(); - - DEBUG_PRINTLN(F("Writing final memory update 18/19 (function unknown)...")); - for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); - writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); - - DEBUG_PRINTLN(F("Waiting for FIRO count >= 48...")); - while ((fifoCount = getFIFOCount()) < 48); - DEBUG_PRINTLN(F("Reading FIFO...")); - getFIFOBytes(fifoBuffer, min(fifoCount, 128)); // safeguard only 128 bytes - DEBUG_PRINTLN(F("Reading interrupt status...")); - getIntStatus(); - DEBUG_PRINTLN(F("Waiting for FIRO count >= 48...")); - while ((fifoCount = getFIFOCount()) < 48); - DEBUG_PRINTLN(F("Reading FIFO...")); - getFIFOBytes(fifoBuffer, min(fifoCount, 128)); // safeguard only 128 bytes - DEBUG_PRINTLN(F("Reading interrupt status...")); - getIntStatus(); - - DEBUG_PRINTLN(F("Writing final memory update 19/19 (function unknown)...")); - for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); - writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); - - DEBUG_PRINTLN(F("Disabling DMP (you turn it on later)...")); - setDMPEnabled(false); - - DEBUG_PRINTLN(F("Setting up internal 48-byte (default) DMP packet buffer...")); - dmpPacketSize = 48; - /*if ((dmpPacketBuffer = (uint8_t *)malloc(42)) == 0) { - return 3; // TODO: proper error code for no memory - }*/ - - DEBUG_PRINTLN(F("Resetting FIFO and clearing INT status one last time...")); - resetFIFO(); - getIntStatus(); - } else { - DEBUG_PRINTLN(F("ERROR! DMP configuration verification failed.")); - return 2; // configuration block loading failed - } - } else { - DEBUG_PRINTLN(F("ERROR! DMP code verification failed.")); - return 1; // main binary block loading failed - } - return 0; // success -} - -bool MPU6050::dmpPacketAvailable() { - return getFIFOCount() >= dmpGetFIFOPacketSize(); -} - -// uint8_t MPU6050::dmpSetFIFORate(uint8_t fifoRate); -// uint8_t MPU6050::dmpGetFIFORate(); -// uint8_t MPU6050::dmpGetSampleStepSizeMS(); -// uint8_t MPU6050::dmpGetSampleFrequency(); -// int32_t MPU6050::dmpDecodeTemperature(int8_t tempReg); - -//uint8_t MPU6050::dmpRegisterFIFORateProcess(inv_obj_func func, int16_t priority); -//uint8_t MPU6050::dmpUnregisterFIFORateProcess(inv_obj_func func); -//uint8_t MPU6050::dmpRunFIFORateProcesses(); - -// uint8_t MPU6050::dmpSendQuaternion(uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendGyro(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendAccel(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendLinearAccel(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendLinearAccelInWorld(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendControlData(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendSensorData(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendExternalSensorData(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendGravity(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendPacketNumber(uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendQuantizedAccel(uint_fast16_t elements, uint_fast16_t accuracy); -// uint8_t MPU6050::dmpSendEIS(uint_fast16_t elements, uint_fast16_t accuracy); - -uint8_t MPU6050::dmpGetAccel(int32_t *data, const uint8_t* packet) { - // TODO: accommodate different arrangements of sent data (ONLY default supported now) - if (packet == 0) packet = dmpPacketBuffer; - data[0] = (((uint32_t)packet[34] << 24) | ((uint32_t)packet[35] << 16) | ((uint32_t)packet[36] << 8) | packet[37]); - data[1] = (((uint32_t)packet[38] << 24) | ((uint32_t)packet[39] << 16) | ((uint32_t)packet[40] << 8) | packet[41]); - data[2] = (((uint32_t)packet[42] << 24) | ((uint32_t)packet[43] << 16) | ((uint32_t)packet[44] << 8) | packet[45]); - return 0; -} -uint8_t MPU6050::dmpGetAccel(int16_t *data, const uint8_t* packet) { - // TODO: accommodate different arrangements of sent data (ONLY default supported now) - if (packet == 0) packet = dmpPacketBuffer; - data[0] = (packet[34] << 8) | packet[35]; - data[1] = (packet[38] << 8) | packet[39]; - data[2] = (packet[42] << 8) | packet[43]; - return 0; -} -uint8_t MPU6050::dmpGetAccel(VectorInt16 *v, const uint8_t* packet) { - // TODO: accommodate different arrangements of sent data (ONLY default supported now) - if (packet == 0) packet = dmpPacketBuffer; - v -> x = (packet[34] << 8) | packet[35]; - v -> y = (packet[38] << 8) | packet[39]; - v -> z = (packet[42] << 8) | packet[43]; - return 0; -} -uint8_t MPU6050::dmpGetQuaternion(int32_t *data, const uint8_t* packet) { - // TODO: accommodate different arrangements of sent data (ONLY default supported now) - if (packet == 0) packet = dmpPacketBuffer; - data[0] = (((uint32_t)packet[0] << 24) | ((uint32_t)packet[1] << 16) | ((uint32_t)packet[2] << 8) | packet[3]); - data[1] = (((uint32_t)packet[4] << 24) | ((uint32_t)packet[5] << 16) | ((uint32_t)packet[6] << 8) | packet[7]); - data[2] = (((uint32_t)packet[8] << 24) | ((uint32_t)packet[9] << 16) | ((uint32_t)packet[10] << 8) | packet[11]); - data[3] = (((uint32_t)packet[12] << 24) | ((uint32_t)packet[13] << 16) | ((uint32_t)packet[14] << 8) | packet[15]); - return 0; -} -uint8_t MPU6050::dmpGetQuaternion(int16_t *data, const uint8_t* packet) { - // TODO: accommodate different arrangements of sent data (ONLY default supported now) - if (packet == 0) packet = dmpPacketBuffer; - data[0] = ((packet[0] << 8) | packet[1]); - data[1] = ((packet[4] << 8) | packet[5]); - data[2] = ((packet[8] << 8) | packet[9]); - data[3] = ((packet[12] << 8) | packet[13]); - return 0; -} -uint8_t MPU6050::dmpGetQuaternion(Quaternion *q, const uint8_t* packet) { - // TODO: accommodate different arrangements of sent data (ONLY default supported now) - int16_t qI[4]; - uint8_t status = dmpGetQuaternion(qI, packet); - if (status == 0) { - q -> w = (float)qI[0] / 16384.0f; - q -> x = (float)qI[1] / 16384.0f; - q -> y = (float)qI[2] / 16384.0f; - q -> z = (float)qI[3] / 16384.0f; - return 0; - } - return status; // int16 return value, indicates error if this line is reached -} -// uint8_t MPU6050::dmpGet6AxisQuaternion(long *data, const uint8_t* packet); -// uint8_t MPU6050::dmpGetRelativeQuaternion(long *data, const uint8_t* packet); -uint8_t MPU6050::dmpGetGyro(int32_t *data, const uint8_t* packet) { - // TODO: accommodate different arrangements of sent data (ONLY default supported now) - if (packet == 0) packet = dmpPacketBuffer; - data[0] = (((uint32_t)packet[16] << 24) | ((uint32_t)packet[17] << 16) | ((uint32_t)packet[18] << 8) | packet[19]); - data[1] = (((uint32_t)packet[20] << 24) | ((uint32_t)packet[21] << 16) | ((uint32_t)packet[22] << 8) | packet[23]); - data[2] = (((uint32_t)packet[24] << 24) | ((uint32_t)packet[25] << 16) | ((uint32_t)packet[26] << 8) | packet[27]); - return 0; -} -uint8_t MPU6050::dmpGetGyro(int16_t *data, const uint8_t* packet) { - // TODO: accommodate different arrangements of sent data (ONLY default supported now) - if (packet == 0) packet = dmpPacketBuffer; - data[0] = (packet[16] << 8) | packet[17]; - data[1] = (packet[20] << 8) | packet[21]; - data[2] = (packet[24] << 8) | packet[25]; - return 0; -} -uint8_t MPU6050::dmpGetMag(int16_t *data, const uint8_t* packet) { - // TODO: accommodate different arrangements of sent data (ONLY default supported now) - if (packet == 0) packet = dmpPacketBuffer; - data[0] = (packet[28] << 8) | packet[29]; - data[1] = (packet[30] << 8) | packet[31]; - data[2] = (packet[32] << 8) | packet[33]; - return 0; -} -// uint8_t MPU6050::dmpSetLinearAccelFilterCoefficient(float coef); -// uint8_t MPU6050::dmpGetLinearAccel(long *data, const uint8_t* packet); -uint8_t MPU6050::dmpGetLinearAccel(VectorInt16 *v, VectorInt16 *vRaw, VectorFloat *gravity) { - // get rid of the gravity component (+1g = +4096 in standard DMP FIFO packet) - v -> x = vRaw -> x - gravity -> x*4096; - v -> y = vRaw -> y - gravity -> y*4096; - v -> z = vRaw -> z - gravity -> z*4096; - return 0; -} -// uint8_t MPU6050::dmpGetLinearAccelInWorld(long *data, const uint8_t* packet); -uint8_t MPU6050::dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Quaternion *q) { - // rotate measured 3D acceleration vector into original state - // frame of reference based on orientation quaternion - memcpy(v, vReal, sizeof(VectorInt16)); - v -> rotate(q); - return 0; -} -// uint8_t MPU6050::dmpGetGyroAndAccelSensor(long *data, const uint8_t* packet); -// uint8_t MPU6050::dmpGetGyroSensor(long *data, const uint8_t* packet); -// uint8_t MPU6050::dmpGetControlData(long *data, const uint8_t* packet); -// uint8_t MPU6050::dmpGetTemperature(long *data, const uint8_t* packet); -// uint8_t MPU6050::dmpGetGravity(long *data, const uint8_t* packet); -uint8_t MPU6050::dmpGetGravity(int16_t *data, const uint8_t* packet) { - /* +1g corresponds to +8192, sensitivity is 2g. */ - int16_t qI[4]; - uint8_t status = dmpGetQuaternion(qI, packet); - data[0] = ((int32_t)qI[1] * qI[3] - (int32_t)qI[0] * qI[2]) / 16384; - data[1] = ((int32_t)qI[0] * qI[1] + (int32_t)qI[2] * qI[3]) / 16384; - data[2] = ((int32_t)qI[0] * qI[0] - (int32_t)qI[1] * qI[1] - - (int32_t)qI[2] * qI[2] + (int32_t)qI[3] * qI[3]) / (2 * 16384); - return status; -} - -uint8_t MPU6050::dmpGetGravity(VectorFloat *v, Quaternion *q) { - v -> x = 2 * (q -> x*q -> z - q -> w*q -> y); - v -> y = 2 * (q -> w*q -> x + q -> y*q -> z); - v -> z = q -> w*q -> w - q -> x*q -> x - q -> y*q -> y + q -> z*q -> z; - return 0; -} -// uint8_t MPU6050::dmpGetUnquantizedAccel(long *data, const uint8_t* packet); -// uint8_t MPU6050::dmpGetQuantizedAccel(long *data, const uint8_t* packet); -// uint8_t MPU6050::dmpGetExternalSensorData(long *data, int size, const uint8_t* packet); -// uint8_t MPU6050::dmpGetEIS(long *data, const uint8_t* packet); - -uint8_t MPU6050::dmpGetEuler(float *data, Quaternion *q) { - data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1); // psi - data[1] = -asin(2*q -> x*q -> z + 2*q -> w*q -> y); // theta - data[2] = atan2(2*q -> y*q -> z - 2*q -> w*q -> x, 2*q -> w*q -> w + 2*q -> z*q -> z - 1); // phi - return 0; -} - -#ifdef USE_OLD_DMPGETYAWPITCHROLL -uint8_t MPU6050::dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity) { - // yaw: (about Z axis) - data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1); - // pitch: (nose up/down, about Y axis) - data[1] = atan(gravity -> x / sqrt(gravity -> y*gravity -> y + gravity -> z*gravity -> z)); - // roll: (tilt left/right, about X axis) - data[2] = atan(gravity -> y / sqrt(gravity -> x*gravity -> x + gravity -> z*gravity -> z)); - return 0; -} -#else -uint8_t MPU6050::dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity) { - // yaw: (about Z axis) - data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1); - // pitch: (nose up/down, about Y axis) - data[1] = atan2(gravity -> x , sqrt(gravity -> y*gravity -> y + gravity -> z*gravity -> z)); - // roll: (tilt left/right, about X axis) - data[2] = atan2(gravity -> y , gravity -> z); - if(gravity->z<0) { - if(data[1]>0) { - data[1] = PI - data[1]; - } else { - data[1] = -PI - data[1]; - } - } - return 0; -} +#ifndef I2CDEVLIB_MPU6050_TYPEDEF +#define I2CDEVLIB_MPU6050_TYPEDEF +typedef MPU6050_9Axis_MotionApps41 MPU6050; #endif -// uint8_t MPU6050::dmpGetAccelFloat(float *data, const uint8_t* packet); -// uint8_t MPU6050::dmpGetQuaternionFloat(float *data, const uint8_t* packet); - -uint8_t MPU6050::dmpProcessFIFOPacket(const unsigned char *dmpData) { - /*for (uint8_t k = 0; k < dmpPacketSize; k++) { - if (dmpData[k] < 0x10) Serial.print("0"); - Serial.print(dmpData[k], HEX); - Serial.print(" "); - } - Serial.print("\n");*/ - //Serial.println((uint16_t)dmpPacketBuffer); - return 0; -} -uint8_t MPU6050::dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *processed) { - uint8_t status; - uint8_t buf[dmpPacketSize]; - for (uint8_t i = 0; i < numPackets; i++) { - // read packet from FIFO - getFIFOBytes(buf, dmpPacketSize); - - // process packet - if ((status = dmpProcessFIFOPacket(buf)) > 0) return status; - - // increment external process count variable, if supplied - if (processed != 0) (*processed)++; - } - return 0; -} - -// uint8_t MPU6050::dmpSetFIFOProcessedCallback(void (*func) (void)); - -// uint8_t MPU6050::dmpInitFIFOParam(); -// uint8_t MPU6050::dmpCloseFIFO(); -// uint8_t MPU6050::dmpSetGyroDataSource(uint_fast8_t source); -// uint8_t MPU6050::dmpDecodeQuantizedAccel(); -// uint32_t MPU6050::dmpGetGyroSumOfSquare(); -// uint32_t MPU6050::dmpGetAccelSumOfSquare(); -// void MPU6050::dmpOverrideQuaternion(long *q); -uint16_t MPU6050::dmpGetFIFOPacketSize() { - return dmpPacketSize; -} - -#endif /* _MPU6050_9AXIS_MOTIONAPPS41_H_ */ +#endif /* _MPU6050_6AXIS_MOTIONAPPS41_H_ */ diff --git a/Arduino/MPU6050/examples/MPU6050_DMP6_using_DMP_V6.12/MPU6050_DMP6_using_DMP_V6.12.ino b/Arduino/MPU6050/examples/MPU6050_DMP6_using_DMP_V6.12/MPU6050_DMP6_using_DMP_V6.12.ino index 9a87db5c..fd7ebf96 100644 --- a/Arduino/MPU6050/examples/MPU6050_DMP6_using_DMP_V6.12/MPU6050_DMP6_using_DMP_V6.12.ino +++ b/Arduino/MPU6050/examples/MPU6050_DMP6_using_DMP_V6.12/MPU6050_DMP6_using_DMP_V6.12.ino @@ -49,7 +49,7 @@ // for both classes must be in the include path of your project #include "I2Cdev.h" -#include "MPU6050_6Axis_MotionApps_V6_12.h" +#include "MPU6050_6Axis_MotionApps612.h" //#include "MPU6050.h" // not necessary if using MotionApps include file // Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation From b8aee9c201e27e866eaf15c0585376bcba4e4d95 Mon Sep 17 00:00:00 2001 From: Jeff Rowberg Date: Tue, 28 Sep 2021 07:48:57 -0400 Subject: [PATCH 276/335] Remove dependency on min() in MPU6050 code --- Arduino/MPU6050/MPU6050.cpp | 2 +- Arduino/MPU6050/MPU6050_9Axis_MotionApps41.cpp | 6 +++--- Arduino/MPU9150/MPU9150_9Axis_MotionApps41.h | 6 +++--- .../components/MPU6050/MPU6050_9Axis_MotionApps41.h | 6 +++--- MSP430/MPU6050/MPU6050_9Axis_MotionApps41.h | 6 +++--- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Arduino/MPU6050/MPU6050.cpp b/Arduino/MPU6050/MPU6050.cpp index c3212efa..3fd4973c 100644 --- a/Arduino/MPU6050/MPU6050.cpp +++ b/Arduino/MPU6050/MPU6050.cpp @@ -2787,7 +2787,7 @@ void MPU6050_Base::setFIFOTimeout(uint32_t fifoTimeout) { fifoC = fifoC - length; // Save the last packet uint16_t RemoveBytes; while (fifoC) { // fifo count will reach zero so this is safe - RemoveBytes = min((int)fifoC, I2CDEVLIB_WIRE_BUFFER_LENGTH); // Buffer Length is different than the packet length this will efficiently clear the buffer + RemoveBytes = (fifoC < I2CDEVLIB_WIRE_BUFFER_LENGTH) ? fifoC : I2CDEVLIB_WIRE_BUFFER_LENGTH; // Buffer Length is different than the packet length this will efficiently clear the buffer getFIFOBytes(Trash, (uint8_t)RemoveBytes); fifoC -= RemoveBytes; } diff --git a/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.cpp b/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.cpp index a722d3e6..2a11fe55 100644 --- a/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.cpp +++ b/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.cpp @@ -607,7 +607,7 @@ uint8_t MPU6050_9Axis_MotionApps41::dmpInitialize() { DEBUG_PRINTLN(F("Waiting for FIRO count >= 46...")); while ((fifoCount = getFIFOCount()) < 46); DEBUG_PRINTLN(F("Reading FIFO...")); - getFIFOBytes(fifoBuffer, min(fifoCount, 128)); // safeguard only 128 bytes + getFIFOBytes(fifoBuffer, (fifoCount < 128) ? fifoCount : 128); // safeguard only 128 bytes DEBUG_PRINTLN(F("Reading interrupt status...")); getIntStatus(); @@ -618,13 +618,13 @@ uint8_t MPU6050_9Axis_MotionApps41::dmpInitialize() { DEBUG_PRINTLN(F("Waiting for FIRO count >= 48...")); while ((fifoCount = getFIFOCount()) < 48); DEBUG_PRINTLN(F("Reading FIFO...")); - getFIFOBytes(fifoBuffer, min(fifoCount, 128)); // safeguard only 128 bytes + getFIFOBytes(fifoBuffer, (fifoCount < 128) ? fifoCount : 128); // safeguard only 128 bytes DEBUG_PRINTLN(F("Reading interrupt status...")); getIntStatus(); DEBUG_PRINTLN(F("Waiting for FIRO count >= 48...")); while ((fifoCount = getFIFOCount()) < 48); DEBUG_PRINTLN(F("Reading FIFO...")); - getFIFOBytes(fifoBuffer, min(fifoCount, 128)); // safeguard only 128 bytes + getFIFOBytes(fifoBuffer, (fifoCount < 128) ? fifoCount : 128); // safeguard only 128 bytes DEBUG_PRINTLN(F("Reading interrupt status...")); getIntStatus(); diff --git a/Arduino/MPU9150/MPU9150_9Axis_MotionApps41.h b/Arduino/MPU9150/MPU9150_9Axis_MotionApps41.h index 54606ee0..ce8e57dc 100644 --- a/Arduino/MPU9150/MPU9150_9Axis_MotionApps41.h +++ b/Arduino/MPU9150/MPU9150_9Axis_MotionApps41.h @@ -602,7 +602,7 @@ uint8_t MPU9150::dmpInitialize() { DEBUG_PRINTLN(F("Waiting for FIRO count >= 46...")); while ((fifoCount = getFIFOCount()) < 46); DEBUG_PRINTLN(F("Reading FIFO...")); - getFIFOBytes(fifoBuffer, min(fifoCount, 128)); // safeguard only 128 bytes + getFIFOBytes(fifoBuffer, (fifoCount < 128) ? fifoCount : 128); // safeguard only 128 bytes DEBUG_PRINTLN(F("Reading interrupt status...")); getIntStatus(); @@ -613,13 +613,13 @@ uint8_t MPU9150::dmpInitialize() { DEBUG_PRINTLN(F("Waiting for FIRO count >= 48...")); while ((fifoCount = getFIFOCount()) < 48); DEBUG_PRINTLN(F("Reading FIFO...")); - getFIFOBytes(fifoBuffer, min(fifoCount, 128)); // safeguard only 128 bytes + getFIFOBytes(fifoBuffer, (fifoCount < 128) ? fifoCount : 128); // safeguard only 128 bytes DEBUG_PRINTLN(F("Reading interrupt status...")); getIntStatus(); DEBUG_PRINTLN(F("Waiting for FIRO count >= 48...")); while ((fifoCount = getFIFOCount()) < 48); DEBUG_PRINTLN(F("Reading FIFO...")); - getFIFOBytes(fifoBuffer, min(fifoCount, 128)); // safeguard only 128 bytes + getFIFOBytes(fifoBuffer, (fifoCount < 128) ? fifoCount : 128); // safeguard only 128 bytes DEBUG_PRINTLN(F("Reading interrupt status...")); getIntStatus(); diff --git a/ESP32_ESP-IDF/components/MPU6050/MPU6050_9Axis_MotionApps41.h b/ESP32_ESP-IDF/components/MPU6050/MPU6050_9Axis_MotionApps41.h index cf025146..b86a476e 100644 --- a/ESP32_ESP-IDF/components/MPU6050/MPU6050_9Axis_MotionApps41.h +++ b/ESP32_ESP-IDF/components/MPU6050/MPU6050_9Axis_MotionApps41.h @@ -602,7 +602,7 @@ uint8_t MPU6050::dmpInitialize() { DEBUG_PRINTLN(F("Waiting for FIRO count >= 46...")); while ((fifoCount = getFIFOCount()) < 46); DEBUG_PRINTLN(F("Reading FIFO...")); - getFIFOBytes(fifoBuffer, min(fifoCount, 128)); // safeguard only 128 bytes + getFIFOBytes(fifoBuffer, (fifoCount < 128) ? fifoCount : 128); // safeguard only 128 bytes DEBUG_PRINTLN(F("Reading interrupt status...")); getIntStatus(); @@ -613,13 +613,13 @@ uint8_t MPU6050::dmpInitialize() { DEBUG_PRINTLN(F("Waiting for FIRO count >= 48...")); while ((fifoCount = getFIFOCount()) < 48); DEBUG_PRINTLN(F("Reading FIFO...")); - getFIFOBytes(fifoBuffer, min(fifoCount, 128)); // safeguard only 128 bytes + getFIFOBytes(fifoBuffer, (fifoCount < 128) ? fifoCount : 128); // safeguard only 128 bytes DEBUG_PRINTLN(F("Reading interrupt status...")); getIntStatus(); DEBUG_PRINTLN(F("Waiting for FIRO count >= 48...")); while ((fifoCount = getFIFOCount()) < 48); DEBUG_PRINTLN(F("Reading FIFO...")); - getFIFOBytes(fifoBuffer, min(fifoCount, 128)); // safeguard only 128 bytes + getFIFOBytes(fifoBuffer, (fifoCount < 128) ? fifoCount : 128); // safeguard only 128 bytes DEBUG_PRINTLN(F("Reading interrupt status...")); getIntStatus(); diff --git a/MSP430/MPU6050/MPU6050_9Axis_MotionApps41.h b/MSP430/MPU6050/MPU6050_9Axis_MotionApps41.h index bd1e3899..722fabae 100644 --- a/MSP430/MPU6050/MPU6050_9Axis_MotionApps41.h +++ b/MSP430/MPU6050/MPU6050_9Axis_MotionApps41.h @@ -558,7 +558,7 @@ uint8_t MPU6050::dmpInitialize() { DEBUG_PRINTLN(F("Waiting for FIRO count >= 46...")); while ((fifoCount = getFIFOCount()) < 46); DEBUG_PRINTLN(F("Reading FIFO...")); - getFIFOBytes(fifoBuffer, min(fifoCount, 128)); // safeguard only 128 bytes + getFIFOBytes(fifoBuffer, (fifoCount < 128) ? fifoCount : 128); // safeguard only 128 bytes DEBUG_PRINTLN(F("Reading interrupt status...")); getIntStatus(); @@ -569,13 +569,13 @@ uint8_t MPU6050::dmpInitialize() { DEBUG_PRINTLN(F("Waiting for FIRO count >= 48...")); while ((fifoCount = getFIFOCount()) < 48); DEBUG_PRINTLN(F("Reading FIFO...")); - getFIFOBytes(fifoBuffer, min(fifoCount, 128)); // safeguard only 128 bytes + getFIFOBytes(fifoBuffer, (fifoCount < 128) ? fifoCount : 128); // safeguard only 128 bytes DEBUG_PRINTLN(F("Reading interrupt status...")); getIntStatus(); DEBUG_PRINTLN(F("Waiting for FIRO count >= 48...")); while ((fifoCount = getFIFOCount()) < 48); DEBUG_PRINTLN(F("Reading FIFO...")); - getFIFOBytes(fifoBuffer, min(fifoCount, 128)); // safeguard only 128 bytes + getFIFOBytes(fifoBuffer, (fifoCount < 128) ? fifoCount : 128); // safeguard only 128 bytes DEBUG_PRINTLN(F("Reading interrupt status...")); getIntStatus(); From 7693ed9b3c20822636b5209bc61368ab40984795 Mon Sep 17 00:00:00 2001 From: Jeff Rowberg Date: Tue, 28 Sep 2021 16:28:33 -0400 Subject: [PATCH 277/335] Eliminate ambiguous argument compiler warning --- Arduino/I2Cdev/I2Cdev.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Arduino/I2Cdev/I2Cdev.cpp b/Arduino/I2Cdev/I2Cdev.cpp index 365edd51..cffed8a0 100644 --- a/Arduino/I2Cdev/I2Cdev.cpp +++ b/Arduino/I2Cdev/I2Cdev.cpp @@ -230,7 +230,7 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 Wire.send(regAddr); Wire.endTransmission(); Wire.beginTransmission(devAddr); - Wire.requestFrom(devAddr, (int)min(length - k, I2CDEVLIB_WIRE_BUFFER_LENGTH)); + Wire.requestFrom((uint8_t)devAddr, (uint8_t)min((int)length - k, I2CDEVLIB_WIRE_BUFFER_LENGTH)); for (; Wire.available() && (timeout == 0 || millis() - t1 < timeout); count++) { data[count] = Wire.receive(); @@ -254,7 +254,7 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 Wire.write(regAddr); Wire.endTransmission(); Wire.beginTransmission(devAddr); - Wire.requestFrom(devAddr, (int)min(length - k, I2CDEVLIB_WIRE_BUFFER_LENGTH)); + Wire.requestFrom((uint8_t)devAddr, (uint8_t)min((int)length - k, I2CDEVLIB_WIRE_BUFFER_LENGTH)); for (; Wire.available() && (timeout == 0 || millis() - t1 < timeout); count++) { data[count] = Wire.read(); @@ -278,7 +278,7 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 Wire.write(regAddr); Wire.endTransmission(); Wire.beginTransmission(devAddr); - Wire.requestFrom(devAddr, (int)min(length - k, I2CDEVLIB_WIRE_BUFFER_LENGTH)); + Wire.requestFrom((uint8_t)devAddr, (uint8_t)min((int)length - k, I2CDEVLIB_WIRE_BUFFER_LENGTH)); for (; Wire.available() && (timeout == 0 || millis() - t1 < timeout); count++) { data[count] = Wire.read(); From 7fec0f5dd6f99c0507d9d02594a96f1298b36547 Mon Sep 17 00:00:00 2001 From: Jeff Rowberg Date: Tue, 28 Sep 2021 16:35:04 -0400 Subject: [PATCH 278/335] Allow custom Wire object as transaction argument --- Arduino/I2Cdev/I2Cdev.cpp | 221 +++++++++++++++++++++----------------- Arduino/I2Cdev/I2Cdev.h | 35 +++--- 2 files changed, 138 insertions(+), 118 deletions(-) diff --git a/Arduino/I2Cdev/I2Cdev.cpp b/Arduino/I2Cdev/I2Cdev.cpp index cffed8a0..892274ba 100644 --- a/Arduino/I2Cdev/I2Cdev.cpp +++ b/Arduino/I2Cdev/I2Cdev.cpp @@ -3,6 +3,9 @@ // 2013-06-05 by Jeff Rowberg // // Changelog: +// 2021-09-28 - allow custom Wire object as transaction function argument +// 2020-01-20 - hardija : complete support for Teensy 3.x +// 2015-10-30 - simondlevy : support i2c_t3 for Teensy3.1 // 2013-05-06 - add Francesco Ferrara's Fastwire v0.24 implementation with small modifications // 2013-05-05 - fix issue with writing bit values to words (Sasquatch/Farzanegan) // 2012-06-09 - fix major issue with reading > 32 bytes at a time with Arduino Wire @@ -100,9 +103,9 @@ I2Cdev::I2Cdev() { * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) * @return Status of read operation (true = success) */ -int8_t I2Cdev::readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data, uint16_t timeout) { +int8_t I2Cdev::readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data, uint16_t timeout, void *wireObj) { uint8_t b; - uint8_t count = readByte(devAddr, regAddr, &b, timeout); + uint8_t count = readByte(devAddr, regAddr, &b, timeout, wireObj); *data = b & (1 << bitNum); return count; } @@ -115,9 +118,9 @@ int8_t I2Cdev::readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) * @return Status of read operation (true = success) */ -int8_t I2Cdev::readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data, uint16_t timeout) { +int8_t I2Cdev::readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data, uint16_t timeout, void *wireObj) { uint16_t b; - uint8_t count = readWord(devAddr, regAddr, &b, timeout); + uint8_t count = readWord(devAddr, regAddr, &b, timeout, wireObj); *data = b & (1 << bitNum); return count; } @@ -131,14 +134,14 @@ int8_t I2Cdev::readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16 * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) * @return Status of read operation (true = success) */ -int8_t I2Cdev::readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data, uint16_t timeout) { +int8_t I2Cdev::readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data, uint16_t timeout, void *wireObj) { // 01101001 read byte // 76543210 bit numbers // xxx args: bitStart=4, length=3 // 010 masked // -> 010 shifted uint8_t count, b; - if ((count = readByte(devAddr, regAddr, &b, timeout)) != 0) { + if ((count = readByte(devAddr, regAddr, &b, timeout, wireObj)) != 0) { uint8_t mask = ((1 << length) - 1) << (bitStart - length + 1); b &= mask; b >>= (bitStart - length + 1); @@ -156,7 +159,7 @@ int8_t I2Cdev::readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) * @return Status of read operation (1 = success, 0 = failure, -1 = timeout) */ -int8_t I2Cdev::readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t *data, uint16_t timeout) { +int8_t I2Cdev::readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t *data, uint16_t timeout, void *wireObj) { // 1101011001101001 read byte // fedcba9876543210 bit numbers // xxx args: bitStart=12, length=3 @@ -164,7 +167,7 @@ int8_t I2Cdev::readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uin // -> 010 shifted uint8_t count; uint16_t w; - if ((count = readWord(devAddr, regAddr, &w, timeout)) != 0) { + if ((count = readWord(devAddr, regAddr, &w, timeout, wireObj)) != 0) { uint16_t mask = ((1 << length) - 1) << (bitStart - length + 1); w &= mask; w >>= (bitStart - length + 1); @@ -180,8 +183,8 @@ int8_t I2Cdev::readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uin * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) * @return Status of read operation (true = success) */ -int8_t I2Cdev::readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint16_t timeout) { - return readBytes(devAddr, regAddr, 1, data, timeout); +int8_t I2Cdev::readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint16_t timeout, void *wireObj) { + return readBytes(devAddr, regAddr, 1, data, timeout, wireObj); } /** Read single word from a 16-bit device register. @@ -191,8 +194,8 @@ int8_t I2Cdev::readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint16_ * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) * @return Status of read operation (true = success) */ -int8_t I2Cdev::readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data, uint16_t timeout) { - return readWords(devAddr, regAddr, 1, data, timeout); +int8_t I2Cdev::readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data, uint16_t timeout, void *wireObj) { + return readWords(devAddr, regAddr, 1, data, timeout, wireObj); } /** Read multiple bytes from an 8-bit device register. @@ -203,7 +206,7 @@ int8_t I2Cdev::readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data, uint16 * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) * @return Number of bytes read (-1 indicates failure) */ -int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data, uint16_t timeout) { +int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data, uint16_t timeout, void *wireObj) { #ifdef I2CDEV_SERIAL_DEBUG Serial.print("I2C (0x"); Serial.print(devAddr, HEX); @@ -218,6 +221,8 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 uint32_t t1 = millis(); #if (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE) + TwoWire *useWire = &Wire; + if (wireObj) useWire = (TwoWire *)wireObj; #if (ARDUINO < 100) // Arduino v00xx (before v1.0), Wire library @@ -226,21 +231,21 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 // so if user requests more than I2CDEVLIB_WIRE_BUFFER_LENGTH bytes, we have to do it in // smaller chunks instead of all at once for (int k = 0; k < length; k += min((int)length, I2CDEVLIB_WIRE_BUFFER_LENGTH)) { - Wire.beginTransmission(devAddr); - Wire.send(regAddr); - Wire.endTransmission(); - Wire.beginTransmission(devAddr); - Wire.requestFrom((uint8_t)devAddr, (uint8_t)min((int)length - k, I2CDEVLIB_WIRE_BUFFER_LENGTH)); - - for (; Wire.available() && (timeout == 0 || millis() - t1 < timeout); count++) { - data[count] = Wire.receive(); + useWire->beginTransmission(devAddr); + useWire->send(regAddr); + useWire->endTransmission(); + useWire->beginTransmission(devAddr); + useWire->requestFrom((uint8_t)devAddr, (uint8_t)min((int)length - k, I2CDEVLIB_WIRE_BUFFER_LENGTH)); + + for (; useWire->available() && (timeout == 0 || millis() - t1 < timeout); count++) { + data[count] = useWire->receive(); #ifdef I2CDEV_SERIAL_DEBUG Serial.print(data[count], HEX); if (count + 1 < length) Serial.print(" "); #endif } - Wire.endTransmission(); + useWire->endTransmission(); } #elif (ARDUINO == 100) // Arduino v1.0.0, Wire library @@ -250,21 +255,21 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 // so if user requests more than I2CDEVLIB_WIRE_BUFFER_LENGTH bytes, we have to do it in // smaller chunks instead of all at once for (int k = 0; k < length; k += min((int)length, I2CDEVLIB_WIRE_BUFFER_LENGTH)) { - Wire.beginTransmission(devAddr); - Wire.write(regAddr); - Wire.endTransmission(); - Wire.beginTransmission(devAddr); - Wire.requestFrom((uint8_t)devAddr, (uint8_t)min((int)length - k, I2CDEVLIB_WIRE_BUFFER_LENGTH)); + useWire->beginTransmission(devAddr); + useWire->write(regAddr); + useWire->endTransmission(); + useWire->beginTransmission(devAddr); + useWire->requestFrom((uint8_t)devAddr, (uint8_t)min((int)length - k, I2CDEVLIB_WIRE_BUFFER_LENGTH)); - for (; Wire.available() && (timeout == 0 || millis() - t1 < timeout); count++) { - data[count] = Wire.read(); + for (; useWire->available() && (timeout == 0 || millis() - t1 < timeout); count++) { + data[count] = useWire->read(); #ifdef I2CDEV_SERIAL_DEBUG Serial.print(data[count], HEX); if (count + 1 < length) Serial.print(" "); #endif } - Wire.endTransmission(); + useWire->endTransmission(); } #elif (ARDUINO > 100) // Arduino v1.0.1+, Wire library @@ -274,14 +279,14 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 // so if user requests more than I2CDEVLIB_WIRE_BUFFER_LENGTH bytes, we have to do it in // smaller chunks instead of all at once for (int k = 0; k < length; k += min((int)length, I2CDEVLIB_WIRE_BUFFER_LENGTH)) { - Wire.beginTransmission(devAddr); - Wire.write(regAddr); - Wire.endTransmission(); - Wire.beginTransmission(devAddr); - Wire.requestFrom((uint8_t)devAddr, (uint8_t)min((int)length - k, I2CDEVLIB_WIRE_BUFFER_LENGTH)); + useWire->beginTransmission(devAddr); + useWire->write(regAddr); + useWire->endTransmission(); + useWire->beginTransmission(devAddr); + useWire->requestFrom((uint8_t)devAddr, (uint8_t)min((int)length - k, I2CDEVLIB_WIRE_BUFFER_LENGTH)); - for (; Wire.available() && (timeout == 0 || millis() - t1 < timeout); count++) { - data[count] = Wire.read(); + for (; useWire->available() && (timeout == 0 || millis() - t1 < timeout); count++) { + data[count] = useWire->read(); #ifdef I2CDEV_SERIAL_DEBUG Serial.print(data[count], HEX); if (count + 1 < length) Serial.print(" "); @@ -323,7 +328,7 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) * @return Number of words read (-1 indicates failure) */ -int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data, uint16_t timeout) { +int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data, uint16_t timeout, void *wireObj) { #ifdef I2CDEV_SERIAL_DEBUG Serial.print("I2C (0x"); Serial.print(devAddr, HEX); @@ -338,6 +343,8 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 uint32_t t1 = millis(); #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE + TwoWire *useWire = &Wire; + if (wireObj) useWire = (TwoWire *)wireObj; #if (ARDUINO < 100) // Arduino v00xx (before v1.0), Wire library @@ -346,20 +353,20 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 // so if user requests more than I2CDEVLIB_WIRE_BUFFER_LENGTH bytes, we have to do it in // smaller chunks instead of all at once for (uint8_t k = 0; k < length * 2; k += min(length * 2, I2CDEVLIB_WIRE_BUFFER_LENGTH)) { - Wire.beginTransmission(devAddr); - Wire.send(regAddr); - Wire.endTransmission(); - Wire.beginTransmission(devAddr); - Wire.requestFrom(devAddr, (uint8_t)(length * 2)); // length=words, this wants bytes + useWire->beginTransmission(devAddr); + useWire->send(regAddr); + useWire->endTransmission(); + useWire->beginTransmission(devAddr); + useWire->requestFrom(devAddr, (uint8_t)(length * 2)); // length=words, this wants bytes bool msb = true; // starts with MSB, then LSB - for (; Wire.available() && count < length && (timeout == 0 || millis() - t1 < timeout);) { + for (; useWire->available() && count < length && (timeout == 0 || millis() - t1 < timeout);) { if (msb) { // first byte is bits 15-8 (MSb=15) - data[count] = Wire.receive() << 8; + data[count] = useWire->receive() << 8; } else { // second byte is bits 7-0 (LSb=0) - data[count] |= Wire.receive(); + data[count] |= useWire->receive(); #ifdef I2CDEV_SERIAL_DEBUG Serial.print(data[count], HEX); if (count + 1 < length) Serial.print(" "); @@ -369,7 +376,7 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 msb = !msb; } - Wire.endTransmission(); + useWire->endTransmission(); } #elif (ARDUINO == 100) // Arduino v1.0.0, Wire library @@ -379,20 +386,20 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 // so if user requests more than I2CDEVLIB_WIRE_BUFFER_LENGTH bytes, we have to do it in // smaller chunks instead of all at once for (uint8_t k = 0; k < length * 2; k += min(length * 2, I2CDEVLIB_WIRE_BUFFER_LENGTH)) { - Wire.beginTransmission(devAddr); - Wire.write(regAddr); - Wire.endTransmission(); - Wire.beginTransmission(devAddr); - Wire.requestFrom(devAddr, (uint8_t)(length * 2)); // length=words, this wants bytes + useWire->beginTransmission(devAddr); + useWire->write(regAddr); + useWire->endTransmission(); + useWire->beginTransmission(devAddr); + useWire->requestFrom(devAddr, (uint8_t)(length * 2)); // length=words, this wants bytes bool msb = true; // starts with MSB, then LSB - for (; Wire.available() && count < length && (timeout == 0 || millis() - t1 < timeout);) { + for (; useWire->available() && count < length && (timeout == 0 || millis() - t1 < timeout);) { if (msb) { // first byte is bits 15-8 (MSb=15) - data[count] = Wire.read() << 8; + data[count] = useWire->read() << 8; } else { // second byte is bits 7-0 (LSb=0) - data[count] |= Wire.read(); + data[count] |= useWire->read(); #ifdef I2CDEV_SERIAL_DEBUG Serial.print(data[count], HEX); if (count + 1 < length) Serial.print(" "); @@ -402,7 +409,7 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 msb = !msb; } - Wire.endTransmission(); + useWire->endTransmission(); } #elif (ARDUINO > 100) // Arduino v1.0.1+, Wire library @@ -412,20 +419,20 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 // so if user requests more than I2CDEVLIB_WIRE_BUFFER_LENGTH bytes, we have to do it in // smaller chunks instead of all at once for (uint8_t k = 0; k < length * 2; k += min(length * 2, I2CDEVLIB_WIRE_BUFFER_LENGTH)) { - Wire.beginTransmission(devAddr); - Wire.write(regAddr); - Wire.endTransmission(); - Wire.beginTransmission(devAddr); - Wire.requestFrom(devAddr, (uint8_t)(length * 2)); // length=words, this wants bytes + useWire->beginTransmission(devAddr); + useWire->write(regAddr); + useWire->endTransmission(); + useWire->beginTransmission(devAddr); + useWire->requestFrom(devAddr, (uint8_t)(length * 2)); // length=words, this wants bytes bool msb = true; // starts with MSB, then LSB - for (; Wire.available() && count < length && (timeout == 0 || millis() - t1 < timeout);) { + for (; useWire->available() && count < length && (timeout == 0 || millis() - t1 < timeout);) { if (msb) { // first byte is bits 15-8 (MSb=15) - data[count] = Wire.read() << 8; + data[count] = useWire->read() << 8; } else { // second byte is bits 7-0 (LSb=0) - data[count] |= Wire.read(); + data[count] |= useWire->read(); #ifdef I2CDEV_SERIAL_DEBUG Serial.print(data[count], HEX); if (count + 1 < length) Serial.print(" "); @@ -435,7 +442,7 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 msb = !msb; } - Wire.endTransmission(); + useWire->endTransmission(); } #endif @@ -474,11 +481,11 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 * @param value New bit value to write * @return Status of operation (true = success) */ -bool I2Cdev::writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t data) { +bool I2Cdev::writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t data, void *wireObj) { uint8_t b; - readByte(devAddr, regAddr, &b); + readByte(devAddr, regAddr, &b, I2Cdev::readTimeout, wireObj); b = (data != 0) ? (b | (1 << bitNum)) : (b & ~(1 << bitNum)); - return writeByte(devAddr, regAddr, b); + return writeByte(devAddr, regAddr, b, wireObj); } /** write a single bit in a 16-bit device register. @@ -488,11 +495,11 @@ bool I2Cdev::writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t * @param value New bit value to write * @return Status of operation (true = success) */ -bool I2Cdev::writeBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t data) { +bool I2Cdev::writeBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t data, void *wireObj) { uint16_t w; - readWord(devAddr, regAddr, &w); + readWord(devAddr, regAddr, &w, I2Cdev::readTimeout, wireObj); w = (data != 0) ? (w | (1 << bitNum)) : (w & ~(1 << bitNum)); - return writeWord(devAddr, regAddr, w); + return writeWord(devAddr, regAddr, w, wireObj); } /** Write multiple bits in an 8-bit device register. @@ -503,7 +510,7 @@ bool I2Cdev::writeBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_ * @param data Right-aligned value to write * @return Status of operation (true = success) */ -bool I2Cdev::writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data) { +bool I2Cdev::writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data, void *wireObj) { // 010 value to write // 76543210 bit numbers // xxx args: bitStart=4, length=3 @@ -512,13 +519,13 @@ bool I2Cdev::writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8 // 10100011 original & ~mask // 10101011 masked | value uint8_t b; - if (readByte(devAddr, regAddr, &b) != 0) { + if (readByte(devAddr, regAddr, &b, I2Cdev::readTimeout, wireObj) != 0) { uint8_t mask = ((1 << length) - 1) << (bitStart - length + 1); data <<= (bitStart - length + 1); // shift data into correct position data &= mask; // zero all non-important bits in data b &= ~(mask); // zero all important bits in existing byte b |= data; // combine data with existing byte - return writeByte(devAddr, regAddr, b); + return writeByte(devAddr, regAddr, b, wireObj); } else { return false; } @@ -532,7 +539,7 @@ bool I2Cdev::writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8 * @param data Right-aligned value to write * @return Status of operation (true = success) */ -bool I2Cdev::writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t data) { +bool I2Cdev::writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t data, void *wireObj) { // 010 value to write // fedcba9876543210 bit numbers // xxx args: bitStart=12, length=3 @@ -541,13 +548,13 @@ bool I2Cdev::writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint // 1010001110010110 original & ~mask // 1010101110010110 masked | value uint16_t w; - if (readWord(devAddr, regAddr, &w) != 0) { + if (readWord(devAddr, regAddr, &w, I2Cdev::readTimeout, wireObj) != 0) { uint16_t mask = ((1 << length) - 1) << (bitStart - length + 1); data <<= (bitStart - length + 1); // shift data into correct position data &= mask; // zero all non-important bits in data w &= ~(mask); // zero all important bits in existing word w |= data; // combine data with existing word - return writeWord(devAddr, regAddr, w); + return writeWord(devAddr, regAddr, w, wireObj); } else { return false; } @@ -559,8 +566,8 @@ bool I2Cdev::writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint * @param data New byte value to write * @return Status of operation (true = success) */ -bool I2Cdev::writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data) { - return writeBytes(devAddr, regAddr, 1, &data); +bool I2Cdev::writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data, void *wireObj) { + return writeBytes(devAddr, regAddr, 1, &data, wireObj); } /** Write single word to a 16-bit device register. @@ -569,8 +576,8 @@ bool I2Cdev::writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data) { * @param data New word value to write * @return Status of operation (true = success) */ -bool I2Cdev::writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data) { - return writeWords(devAddr, regAddr, 1, &data); +bool I2Cdev::writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data, void *wireObj) { + return writeWords(devAddr, regAddr, 1, &data, wireObj); } /** Write multiple bytes to an 8-bit device register. @@ -580,7 +587,7 @@ bool I2Cdev::writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data) { * @param data Buffer to copy new data from * @return Status of operation (true = success) */ -bool I2Cdev::writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t* data) { +bool I2Cdev::writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t* data, void *wireObj) { #ifdef I2CDEV_SERIAL_DEBUG Serial.print("I2C (0x"); Serial.print(devAddr, HEX); @@ -591,14 +598,20 @@ bool I2Cdev::writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_ Serial.print("..."); #endif uint8_t status = 0; + +#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE + TwoWire *useWire = &Wire; + if (wireObj) useWire = (TwoWire *)wireObj; +#endif + #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) - Wire.beginTransmission(devAddr); - Wire.send((uint8_t) regAddr); // send address + useWire->beginTransmission(devAddr); + useWire->send((uint8_t) regAddr); // send address #elif ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) \ || (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) \ || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE) - Wire.beginTransmission(devAddr); - Wire.write((uint8_t) regAddr); // send address + useWire->beginTransmission(devAddr); + useWire->write((uint8_t) regAddr); // send address #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) Fastwire::beginTransmission(devAddr); Fastwire::write(regAddr); @@ -609,21 +622,21 @@ bool I2Cdev::writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_ if (i + 1 < length) Serial.print(" "); #endif #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) - Wire.send((uint8_t) data[i]); + useWire->send((uint8_t) data[i]); #elif ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) \ || (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) \ || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE) - Wire.write((uint8_t) data[i]); + useWire->write((uint8_t) data[i]); #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) Fastwire::write((uint8_t) data[i]); #endif } #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) - Wire.endTransmission(); + useWire->endTransmission(); #elif ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) \ || (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) \ || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE) - status = Wire.endTransmission(); + status = useWire->endTransmission(); #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) Fastwire::stop(); //status = Fastwire::endTransmission(); @@ -641,7 +654,7 @@ bool I2Cdev::writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_ * @param data Buffer to copy new data from * @return Status of operation (true = success) */ -bool I2Cdev::writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t* data) { +bool I2Cdev::writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t* data, void *wireObj) { #ifdef I2CDEV_SERIAL_DEBUG Serial.print("I2C (0x"); Serial.print(devAddr, HEX); @@ -652,14 +665,20 @@ bool I2Cdev::writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16 Serial.print("..."); #endif uint8_t status = 0; + +#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE + TwoWire *useWire = &Wire; + if (wireObj) useWire = (TwoWire *)wireObj; +#endif + #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) - Wire.beginTransmission(devAddr); - Wire.send(regAddr); // send address + useWire->beginTransmission(devAddr); + useWire->send(regAddr); // send address #elif ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) \ || (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) \ || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE) - Wire.beginTransmission(devAddr); - Wire.write(regAddr); // send address + useWire->beginTransmission(devAddr); + useWire->write(regAddr); // send address #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) Fastwire::beginTransmission(devAddr); Fastwire::write(regAddr); @@ -670,13 +689,13 @@ bool I2Cdev::writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16 if (i + 1 < length) Serial.print(" "); #endif #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) - Wire.send((uint8_t)(data[i] >> 8)); // send MSB - Wire.send((uint8_t)data[i]); // send LSB + useWire->send((uint8_t)(data[i] >> 8)); // send MSB + useWire->send((uint8_t)data[i]); // send LSB #elif ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) \ || (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) \ || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE) - Wire.write((uint8_t)(data[i] >> 8)); // send MSB - Wire.write((uint8_t)data[i]); // send LSB + useWire->write((uint8_t)(data[i] >> 8)); // send MSB + useWire->write((uint8_t)data[i]); // send LSB #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) Fastwire::write((uint8_t)(data[i] >> 8)); // send MSB status = Fastwire::write((uint8_t)data[i]); // send LSB @@ -684,11 +703,11 @@ bool I2Cdev::writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16 #endif } #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) - Wire.endTransmission(); + useWire->endTransmission(); #elif ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) \ || (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) \ || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE) - status = Wire.endTransmission(); + status = useWire->endTransmission(); #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) Fastwire::stop(); //status = Fastwire::endTransmission(); diff --git a/Arduino/I2Cdev/I2Cdev.h b/Arduino/I2Cdev/I2Cdev.h index 61ee65a1..5b59c56f 100644 --- a/Arduino/I2Cdev/I2Cdev.h +++ b/Arduino/I2Cdev/I2Cdev.h @@ -3,6 +3,7 @@ // 2013-06-05 by Jeff Rowberg // // Changelog: +// 2021-09-28 - allow custom Wire object as transaction function argument // 2020-01-20 - hardija : complete support for Teensy 3.x // 2015-10-30 - simondlevy : support i2c_t3 for Teensy3.1 // 2013-05-06 - add Francesco Ferrara's Fastwire v0.24 implementation with small modifications @@ -132,23 +133,23 @@ class I2Cdev { public: I2Cdev(); - static int8_t readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout); - static int8_t readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout); - static int8_t readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout); - static int8_t readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout); - static int8_t readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout); - static int8_t readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout); - static int8_t readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout); - static int8_t readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout); - - static bool writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t data); - static bool writeBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t data); - static bool writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data); - static bool writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t data); - static bool writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data); - static bool writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data); - static bool writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data); - static bool writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data); + static int8_t readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout, void *wireObj=0); + static int8_t readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout, void *wireObj=0); + static int8_t readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout, void *wireObj=0); + static int8_t readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout, void *wireObj=0); + static int8_t readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout, void *wireObj=0); + static int8_t readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout, void *wireObj=0); + static int8_t readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout, void *wireObj=0); + static int8_t readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout, void *wireObj=0); + + static bool writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t data, void *wireObj=0); + static bool writeBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t data, void *wireObj=0); + static bool writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data, void *wireObj=0); + static bool writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t data, void *wireObj=0); + static bool writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data, void *wireObj=0); + static bool writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data, void *wireObj=0); + static bool writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data, void *wireObj=0); + static bool writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data, void *wireObj=0); static uint16_t readTimeout; }; From 4deebfb610e0bfdb5e58cffa8c8f07760dccfedb Mon Sep 17 00:00:00 2001 From: Jeff Rowberg Date: Tue, 28 Sep 2021 22:12:12 -0400 Subject: [PATCH 279/335] Fix MPU6050 typedef problems when not using MotionApps --- Arduino/MPU6050/MPU6050.h | 5 +++++ Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h | 6 +++--- Arduino/MPU6050/MPU6050_6Axis_MotionApps612.h | 6 +++--- Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h | 6 +++--- 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/Arduino/MPU6050/MPU6050.h b/Arduino/MPU6050/MPU6050.h index 45d05059..d44ee38c 100644 --- a/Arduino/MPU6050/MPU6050.h +++ b/Arduino/MPU6050/MPU6050.h @@ -839,4 +839,9 @@ class MPU6050_Base { uint32_t fifoTimeout = MPU6050_FIFO_DEFAULT_TIMEOUT; }; +#ifndef I2CDEVLIB_MPU6050_TYPEDEF +#define I2CDEVLIB_MPU6050_TYPEDEF +typedef MPU6050_Base MPU6050; +#endif + #endif /* _MPU6050_H_ */ diff --git a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h index e4b370c9..d5552898 100644 --- a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h +++ b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h @@ -38,6 +38,9 @@ THE SOFTWARE. #ifndef _MPU6050_6AXIS_MOTIONAPPS20_H_ #define _MPU6050_6AXIS_MOTIONAPPS20_H_ +// take ownership of the "MPU6050" typedef +#define I2CDEVLIB_MPU6050_TYPEDEF + #include "MPU6050.h" class MPU6050_6Axis_MotionApps20 : public MPU6050_Base { @@ -143,9 +146,6 @@ class MPU6050_6Axis_MotionApps20 : public MPU6050_Base { uint16_t dmpPacketSize; }; -#ifndef I2CDEVLIB_MPU6050_TYPEDEF -#define I2CDEVLIB_MPU6050_TYPEDEF typedef MPU6050_6Axis_MotionApps20 MPU6050; -#endif #endif /* _MPU6050_6AXIS_MOTIONAPPS20_H_ */ diff --git a/Arduino/MPU6050/MPU6050_6Axis_MotionApps612.h b/Arduino/MPU6050/MPU6050_6Axis_MotionApps612.h index 8557c576..74cdae44 100644 --- a/Arduino/MPU6050/MPU6050_6Axis_MotionApps612.h +++ b/Arduino/MPU6050/MPU6050_6Axis_MotionApps612.h @@ -38,6 +38,9 @@ THE SOFTWARE. #ifndef _MPU6050_6AXIS_MOTIONAPPS612_H_ #define _MPU6050_6AXIS_MOTIONAPPS612_H_ +// take ownership of the "MPU6050" typedef +#define I2CDEVLIB_MPU6050_TYPEDEF + #include "MPU6050.h" class MPU6050_6Axis_MotionApps612 : public MPU6050_Base { @@ -143,9 +146,6 @@ class MPU6050_6Axis_MotionApps612 : public MPU6050_Base { uint16_t dmpPacketSize; }; -#ifndef I2CDEVLIB_MPU6050_TYPEDEF -#define I2CDEVLIB_MPU6050_TYPEDEF typedef MPU6050_6Axis_MotionApps612 MPU6050; -#endif #endif /* _MPU6050_6AXIS_MOTIONAPPS612_H_ */ diff --git a/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h b/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h index 14ff50b1..7668d4c4 100644 --- a/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h +++ b/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h @@ -38,6 +38,9 @@ THE SOFTWARE. #ifndef _MPU6050_6AXIS_MOTIONAPPS41_H_ #define _MPU6050_6AXIS_MOTIONAPPS41_H_ +// take ownership of the "MPU6050" typedef +#define I2CDEVLIB_MPU6050_TYPEDEF + #include "MPU6050.h" class MPU6050_9Axis_MotionApps41 : public MPU6050_Base { @@ -143,9 +146,6 @@ class MPU6050_9Axis_MotionApps41 : public MPU6050_Base { uint16_t dmpPacketSize; }; -#ifndef I2CDEVLIB_MPU6050_TYPEDEF -#define I2CDEVLIB_MPU6050_TYPEDEF typedef MPU6050_9Axis_MotionApps41 MPU6050; -#endif #endif /* _MPU6050_6AXIS_MOTIONAPPS41_H_ */ From da71c0469cd63316963a9871f732f40d624680b0 Mon Sep 17 00:00:00 2001 From: Jeff Rowberg Date: Tue, 28 Sep 2021 22:13:10 -0400 Subject: [PATCH 280/335] Support multiple Wire objects in MPU6050 device code --- Arduino/MPU6050/MPU6050.cpp | 548 +++++++++--------- Arduino/MPU6050/MPU6050.h | 3 +- .../MPU6050/MPU6050_6Axis_MotionApps612.cpp | 30 +- .../MPU6050/MPU6050_9Axis_MotionApps41.cpp | 46 +- .../examples/MPU6050_raw/MPU6050_raw.ino | 1 + 5 files changed, 315 insertions(+), 313 deletions(-) diff --git a/Arduino/MPU6050/MPU6050.cpp b/Arduino/MPU6050/MPU6050.cpp index 3fd4973c..ecdfe04d 100644 --- a/Arduino/MPU6050/MPU6050.cpp +++ b/Arduino/MPU6050/MPU6050.cpp @@ -44,7 +44,7 @@ THE SOFTWARE. * @see MPU6050_ADDRESS_AD0_LOW * @see MPU6050_ADDRESS_AD0_HIGH */ -MPU6050_Base::MPU6050_Base(uint8_t address):devAddr(address) { +MPU6050_Base::MPU6050_Base(uint8_t address, void *wireObj):devAddr(address), wireObj(wireObj) { } /** Power on and prepare for general usage. @@ -78,7 +78,7 @@ bool MPU6050_Base::testConnection() { * @return I2C supply voltage level (0=VLOGIC, 1=VDD) */ uint8_t MPU6050_Base::getAuxVDDIOLevel() { - I2Cdev::readBit(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_PWR_MODE_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_PWR_MODE_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set the auxiliary I2C supply voltage level. @@ -88,7 +88,7 @@ uint8_t MPU6050_Base::getAuxVDDIOLevel() { * @param level I2C supply voltage level (0=VLOGIC, 1=VDD) */ void MPU6050_Base::setAuxVDDIOLevel(uint8_t level) { - I2Cdev::writeBit(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_PWR_MODE_BIT, level); + I2Cdev::writeBit(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_PWR_MODE_BIT, level, wireObj); } // SMPLRT_DIV register @@ -115,7 +115,7 @@ void MPU6050_Base::setAuxVDDIOLevel(uint8_t level) { * @see MPU6050_RA_SMPLRT_DIV */ uint8_t MPU6050_Base::getRate() { - I2Cdev::readByte(devAddr, MPU6050_RA_SMPLRT_DIV, buffer); + I2Cdev::readByte(devAddr, MPU6050_RA_SMPLRT_DIV, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set gyroscope sample rate divider. @@ -124,7 +124,7 @@ uint8_t MPU6050_Base::getRate() { * @see MPU6050_RA_SMPLRT_DIV */ void MPU6050_Base::setRate(uint8_t rate) { - I2Cdev::writeByte(devAddr, MPU6050_RA_SMPLRT_DIV, rate); + I2Cdev::writeByte(devAddr, MPU6050_RA_SMPLRT_DIV, rate, wireObj); } // CONFIG register @@ -157,7 +157,7 @@ void MPU6050_Base::setRate(uint8_t rate) { * @return FSYNC configuration value */ uint8_t MPU6050_Base::getExternalFrameSync() { - I2Cdev::readBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_EXT_SYNC_SET_BIT, MPU6050_CFG_EXT_SYNC_SET_LENGTH, buffer); + I2Cdev::readBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_EXT_SYNC_SET_BIT, MPU6050_CFG_EXT_SYNC_SET_LENGTH, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set external FSYNC configuration. @@ -166,7 +166,7 @@ uint8_t MPU6050_Base::getExternalFrameSync() { * @param sync New FSYNC configuration value */ void MPU6050_Base::setExternalFrameSync(uint8_t sync) { - I2Cdev::writeBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_EXT_SYNC_SET_BIT, MPU6050_CFG_EXT_SYNC_SET_LENGTH, sync); + I2Cdev::writeBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_EXT_SYNC_SET_BIT, MPU6050_CFG_EXT_SYNC_SET_LENGTH, sync, wireObj); } /** Get digital low-pass filter configuration. * The DLPF_CFG parameter sets the digital low pass filter configuration. It @@ -197,7 +197,7 @@ void MPU6050_Base::setExternalFrameSync(uint8_t sync) { * @see MPU6050_CFG_DLPF_CFG_LENGTH */ uint8_t MPU6050_Base::getDLPFMode() { - I2Cdev::readBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_DLPF_CFG_BIT, MPU6050_CFG_DLPF_CFG_LENGTH, buffer); + I2Cdev::readBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_DLPF_CFG_BIT, MPU6050_CFG_DLPF_CFG_LENGTH, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set digital low-pass filter configuration. @@ -209,7 +209,7 @@ uint8_t MPU6050_Base::getDLPFMode() { * @see MPU6050_CFG_DLPF_CFG_LENGTH */ void MPU6050_Base::setDLPFMode(uint8_t mode) { - I2Cdev::writeBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_DLPF_CFG_BIT, MPU6050_CFG_DLPF_CFG_LENGTH, mode); + I2Cdev::writeBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_DLPF_CFG_BIT, MPU6050_CFG_DLPF_CFG_LENGTH, mode, wireObj); } // GYRO_CONFIG register @@ -232,7 +232,7 @@ void MPU6050_Base::setDLPFMode(uint8_t mode) { * @see MPU6050_GCONFIG_FS_SEL_LENGTH */ uint8_t MPU6050_Base::getFullScaleGyroRange() { - I2Cdev::readBits(devAddr, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, buffer); + I2Cdev::readBits(devAddr, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set full-scale gyroscope range. @@ -244,7 +244,7 @@ uint8_t MPU6050_Base::getFullScaleGyroRange() { * @see MPU6050_GCONFIG_FS_SEL_LENGTH */ void MPU6050_Base::setFullScaleGyroRange(uint8_t range) { - I2Cdev::writeBits(devAddr, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, range); + I2Cdev::writeBits(devAddr, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, range, wireObj); } // SELF TEST FACTORY TRIM VALUES @@ -254,8 +254,8 @@ void MPU6050_Base::setFullScaleGyroRange(uint8_t range) { * @see MPU6050_RA_SELF_TEST_X */ uint8_t MPU6050_Base::getAccelXSelfTestFactoryTrim() { - I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_X, &buffer[0]); - I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_A, &buffer[1]); + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_X, &buffer[0], I2Cdev::readTimeout, wireObj); + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_A, &buffer[1], I2Cdev::readTimeout, wireObj); return (buffer[0]>>3) | ((buffer[1]>>4) & 0x03); } @@ -264,8 +264,8 @@ uint8_t MPU6050_Base::getAccelXSelfTestFactoryTrim() { * @see MPU6050_RA_SELF_TEST_Y */ uint8_t MPU6050_Base::getAccelYSelfTestFactoryTrim() { - I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_Y, &buffer[0]); - I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_A, &buffer[1]); + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_Y, &buffer[0], I2Cdev::readTimeout, wireObj); + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_A, &buffer[1], I2Cdev::readTimeout, wireObj); return (buffer[0]>>3) | ((buffer[1]>>2) & 0x03); } @@ -274,7 +274,7 @@ uint8_t MPU6050_Base::getAccelYSelfTestFactoryTrim() { * @see MPU6050_RA_SELF_TEST_Z */ uint8_t MPU6050_Base::getAccelZSelfTestFactoryTrim() { - I2Cdev::readBytes(devAddr, MPU6050_RA_SELF_TEST_Z, 2, buffer); + I2Cdev::readBytes(devAddr, MPU6050_RA_SELF_TEST_Z, 2, buffer, I2Cdev::readTimeout, wireObj); return (buffer[0]>>3) | (buffer[1] & 0x03); } @@ -283,7 +283,7 @@ uint8_t MPU6050_Base::getAccelZSelfTestFactoryTrim() { * @see MPU6050_RA_SELF_TEST_X */ uint8_t MPU6050_Base::getGyroXSelfTestFactoryTrim() { - I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_X, buffer); + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_X, buffer, I2Cdev::readTimeout, wireObj); return (buffer[0] & 0x1F); } @@ -292,7 +292,7 @@ uint8_t MPU6050_Base::getGyroXSelfTestFactoryTrim() { * @see MPU6050_RA_SELF_TEST_Y */ uint8_t MPU6050_Base::getGyroYSelfTestFactoryTrim() { - I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_Y, buffer); + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_Y, buffer, I2Cdev::readTimeout, wireObj); return (buffer[0] & 0x1F); } @@ -301,7 +301,7 @@ uint8_t MPU6050_Base::getGyroYSelfTestFactoryTrim() { * @see MPU6050_RA_SELF_TEST_Z */ uint8_t MPU6050_Base::getGyroZSelfTestFactoryTrim() { - I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_Z, buffer); + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_Z, buffer, I2Cdev::readTimeout, wireObj); return (buffer[0] & 0x1F); } @@ -312,7 +312,7 @@ uint8_t MPU6050_Base::getGyroZSelfTestFactoryTrim() { * @see MPU6050_RA_ACCEL_CONFIG */ bool MPU6050_Base::getAccelXSelfTest() { - I2Cdev::readBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_XA_ST_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_XA_ST_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Get self-test enabled setting for accelerometer X axis. @@ -320,14 +320,14 @@ bool MPU6050_Base::getAccelXSelfTest() { * @see MPU6050_RA_ACCEL_CONFIG */ void MPU6050_Base::setAccelXSelfTest(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_XA_ST_BIT, enabled); + I2Cdev::writeBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_XA_ST_BIT, enabled, wireObj); } /** Get self-test enabled value for accelerometer Y axis. * @return Self-test enabled value * @see MPU6050_RA_ACCEL_CONFIG */ bool MPU6050_Base::getAccelYSelfTest() { - I2Cdev::readBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_YA_ST_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_YA_ST_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Get self-test enabled value for accelerometer Y axis. @@ -335,14 +335,14 @@ bool MPU6050_Base::getAccelYSelfTest() { * @see MPU6050_RA_ACCEL_CONFIG */ void MPU6050_Base::setAccelYSelfTest(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_YA_ST_BIT, enabled); + I2Cdev::writeBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_YA_ST_BIT, enabled, wireObj); } /** Get self-test enabled value for accelerometer Z axis. * @return Self-test enabled value * @see MPU6050_RA_ACCEL_CONFIG */ bool MPU6050_Base::getAccelZSelfTest() { - I2Cdev::readBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ZA_ST_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ZA_ST_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set self-test enabled value for accelerometer Z axis. @@ -350,7 +350,7 @@ bool MPU6050_Base::getAccelZSelfTest() { * @see MPU6050_RA_ACCEL_CONFIG */ void MPU6050_Base::setAccelZSelfTest(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ZA_ST_BIT, enabled); + I2Cdev::writeBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ZA_ST_BIT, enabled, wireObj); } /** Get full-scale accelerometer range. * The FS_SEL parameter allows setting the full-scale range of the accelerometer @@ -370,7 +370,7 @@ void MPU6050_Base::setAccelZSelfTest(bool enabled) { * @see MPU6050_ACONFIG_AFS_SEL_LENGTH */ uint8_t MPU6050_Base::getFullScaleAccelRange() { - I2Cdev::readBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, buffer); + I2Cdev::readBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set full-scale accelerometer range. @@ -378,7 +378,7 @@ uint8_t MPU6050_Base::getFullScaleAccelRange() { * @see getFullScaleAccelRange() */ void MPU6050_Base::setFullScaleAccelRange(uint8_t range) { - I2Cdev::writeBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, range); + I2Cdev::writeBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, range, wireObj); } /** Get the high-pass filter configuration. * The DHPF is a filter module in the path leading to motion detectors (Free @@ -416,7 +416,7 @@ void MPU6050_Base::setFullScaleAccelRange(uint8_t range) { * @see MPU6050_RA_ACCEL_CONFIG */ uint8_t MPU6050_Base::getDHPFMode() { - I2Cdev::readBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ACCEL_HPF_BIT, MPU6050_ACONFIG_ACCEL_HPF_LENGTH, buffer); + I2Cdev::readBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ACCEL_HPF_BIT, MPU6050_ACONFIG_ACCEL_HPF_LENGTH, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set the high-pass filter configuration. @@ -426,7 +426,7 @@ uint8_t MPU6050_Base::getDHPFMode() { * @see MPU6050_RA_ACCEL_CONFIG */ void MPU6050_Base::setDHPFMode(uint8_t bandwidth) { - I2Cdev::writeBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ACCEL_HPF_BIT, MPU6050_ACONFIG_ACCEL_HPF_LENGTH, bandwidth); + I2Cdev::writeBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ACCEL_HPF_BIT, MPU6050_ACONFIG_ACCEL_HPF_LENGTH, bandwidth, wireObj); } // FF_THR register @@ -447,7 +447,7 @@ void MPU6050_Base::setDHPFMode(uint8_t bandwidth) { * @see MPU6050_RA_FF_THR */ uint8_t MPU6050_Base::getFreefallDetectionThreshold() { - I2Cdev::readByte(devAddr, MPU6050_RA_FF_THR, buffer); + I2Cdev::readByte(devAddr, MPU6050_RA_FF_THR, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Get free-fall event acceleration threshold. @@ -456,7 +456,7 @@ uint8_t MPU6050_Base::getFreefallDetectionThreshold() { * @see MPU6050_RA_FF_THR */ void MPU6050_Base::setFreefallDetectionThreshold(uint8_t threshold) { - I2Cdev::writeByte(devAddr, MPU6050_RA_FF_THR, threshold); + I2Cdev::writeByte(devAddr, MPU6050_RA_FF_THR, threshold, wireObj); } // FF_DUR register @@ -479,7 +479,7 @@ void MPU6050_Base::setFreefallDetectionThreshold(uint8_t threshold) { * @see MPU6050_RA_FF_DUR */ uint8_t MPU6050_Base::getFreefallDetectionDuration() { - I2Cdev::readByte(devAddr, MPU6050_RA_FF_DUR, buffer); + I2Cdev::readByte(devAddr, MPU6050_RA_FF_DUR, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Get free-fall event duration threshold. @@ -488,7 +488,7 @@ uint8_t MPU6050_Base::getFreefallDetectionDuration() { * @see MPU6050_RA_FF_DUR */ void MPU6050_Base::setFreefallDetectionDuration(uint8_t duration) { - I2Cdev::writeByte(devAddr, MPU6050_RA_FF_DUR, duration); + I2Cdev::writeByte(devAddr, MPU6050_RA_FF_DUR, duration, wireObj); } // MOT_THR register @@ -513,7 +513,7 @@ void MPU6050_Base::setFreefallDetectionDuration(uint8_t duration) { * @see MPU6050_RA_MOT_THR */ uint8_t MPU6050_Base::getMotionDetectionThreshold() { - I2Cdev::readByte(devAddr, MPU6050_RA_MOT_THR, buffer); + I2Cdev::readByte(devAddr, MPU6050_RA_MOT_THR, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set motion detection event acceleration threshold. @@ -522,7 +522,7 @@ uint8_t MPU6050_Base::getMotionDetectionThreshold() { * @see MPU6050_RA_MOT_THR */ void MPU6050_Base::setMotionDetectionThreshold(uint8_t threshold) { - I2Cdev::writeByte(devAddr, MPU6050_RA_MOT_THR, threshold); + I2Cdev::writeByte(devAddr, MPU6050_RA_MOT_THR, threshold, wireObj); } // MOT_DUR register @@ -543,7 +543,7 @@ void MPU6050_Base::setMotionDetectionThreshold(uint8_t threshold) { * @see MPU6050_RA_MOT_DUR */ uint8_t MPU6050_Base::getMotionDetectionDuration() { - I2Cdev::readByte(devAddr, MPU6050_RA_MOT_DUR, buffer); + I2Cdev::readByte(devAddr, MPU6050_RA_MOT_DUR, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set motion detection event duration threshold. @@ -552,7 +552,7 @@ uint8_t MPU6050_Base::getMotionDetectionDuration() { * @see MPU6050_RA_MOT_DUR */ void MPU6050_Base::setMotionDetectionDuration(uint8_t duration) { - I2Cdev::writeByte(devAddr, MPU6050_RA_MOT_DUR, duration); + I2Cdev::writeByte(devAddr, MPU6050_RA_MOT_DUR, duration, wireObj); } // ZRMOT_THR register @@ -583,7 +583,7 @@ void MPU6050_Base::setMotionDetectionDuration(uint8_t duration) { * @see MPU6050_RA_ZRMOT_THR */ uint8_t MPU6050_Base::getZeroMotionDetectionThreshold() { - I2Cdev::readByte(devAddr, MPU6050_RA_ZRMOT_THR, buffer); + I2Cdev::readByte(devAddr, MPU6050_RA_ZRMOT_THR, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set zero motion detection event acceleration threshold. @@ -592,7 +592,7 @@ uint8_t MPU6050_Base::getZeroMotionDetectionThreshold() { * @see MPU6050_RA_ZRMOT_THR */ void MPU6050_Base::setZeroMotionDetectionThreshold(uint8_t threshold) { - I2Cdev::writeByte(devAddr, MPU6050_RA_ZRMOT_THR, threshold); + I2Cdev::writeByte(devAddr, MPU6050_RA_ZRMOT_THR, threshold, wireObj); } // ZRMOT_DUR register @@ -614,7 +614,7 @@ void MPU6050_Base::setZeroMotionDetectionThreshold(uint8_t threshold) { * @see MPU6050_RA_ZRMOT_DUR */ uint8_t MPU6050_Base::getZeroMotionDetectionDuration() { - I2Cdev::readByte(devAddr, MPU6050_RA_ZRMOT_DUR, buffer); + I2Cdev::readByte(devAddr, MPU6050_RA_ZRMOT_DUR, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set zero motion detection event duration threshold. @@ -623,7 +623,7 @@ uint8_t MPU6050_Base::getZeroMotionDetectionDuration() { * @see MPU6050_RA_ZRMOT_DUR */ void MPU6050_Base::setZeroMotionDetectionDuration(uint8_t duration) { - I2Cdev::writeByte(devAddr, MPU6050_RA_ZRMOT_DUR, duration); + I2Cdev::writeByte(devAddr, MPU6050_RA_ZRMOT_DUR, duration, wireObj); } // FIFO_EN register @@ -635,7 +635,7 @@ void MPU6050_Base::setZeroMotionDetectionDuration(uint8_t duration) { * @see MPU6050_RA_FIFO_EN */ bool MPU6050_Base::getTempFIFOEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_TEMP_FIFO_EN_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_TEMP_FIFO_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set temperature FIFO enabled value. @@ -644,7 +644,7 @@ bool MPU6050_Base::getTempFIFOEnabled() { * @see MPU6050_RA_FIFO_EN */ void MPU6050_Base::setTempFIFOEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_TEMP_FIFO_EN_BIT, enabled); + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_TEMP_FIFO_EN_BIT, enabled, wireObj); } /** Get gyroscope X-axis FIFO enabled value. * When set to 1, this bit enables GYRO_XOUT_H and GYRO_XOUT_L (Registers 67 and @@ -653,7 +653,7 @@ void MPU6050_Base::setTempFIFOEnabled(bool enabled) { * @see MPU6050_RA_FIFO_EN */ bool MPU6050_Base::getXGyroFIFOEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_XG_FIFO_EN_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_XG_FIFO_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set gyroscope X-axis FIFO enabled value. @@ -662,7 +662,7 @@ bool MPU6050_Base::getXGyroFIFOEnabled() { * @see MPU6050_RA_FIFO_EN */ void MPU6050_Base::setXGyroFIFOEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_XG_FIFO_EN_BIT, enabled); + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_XG_FIFO_EN_BIT, enabled, wireObj); } /** Get gyroscope Y-axis FIFO enabled value. * When set to 1, this bit enables GYRO_YOUT_H and GYRO_YOUT_L (Registers 69 and @@ -671,7 +671,7 @@ void MPU6050_Base::setXGyroFIFOEnabled(bool enabled) { * @see MPU6050_RA_FIFO_EN */ bool MPU6050_Base::getYGyroFIFOEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_YG_FIFO_EN_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_YG_FIFO_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set gyroscope Y-axis FIFO enabled value. @@ -680,7 +680,7 @@ bool MPU6050_Base::getYGyroFIFOEnabled() { * @see MPU6050_RA_FIFO_EN */ void MPU6050_Base::setYGyroFIFOEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_YG_FIFO_EN_BIT, enabled); + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_YG_FIFO_EN_BIT, enabled, wireObj); } /** Get gyroscope Z-axis FIFO enabled value. * When set to 1, this bit enables GYRO_ZOUT_H and GYRO_ZOUT_L (Registers 71 and @@ -689,7 +689,7 @@ void MPU6050_Base::setYGyroFIFOEnabled(bool enabled) { * @see MPU6050_RA_FIFO_EN */ bool MPU6050_Base::getZGyroFIFOEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ZG_FIFO_EN_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ZG_FIFO_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set gyroscope Z-axis FIFO enabled value. @@ -698,7 +698,7 @@ bool MPU6050_Base::getZGyroFIFOEnabled() { * @see MPU6050_RA_FIFO_EN */ void MPU6050_Base::setZGyroFIFOEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ZG_FIFO_EN_BIT, enabled); + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ZG_FIFO_EN_BIT, enabled, wireObj); } /** Get accelerometer FIFO enabled value. * When set to 1, this bit enables ACCEL_XOUT_H, ACCEL_XOUT_L, ACCEL_YOUT_H, @@ -708,7 +708,7 @@ void MPU6050_Base::setZGyroFIFOEnabled(bool enabled) { * @see MPU6050_RA_FIFO_EN */ bool MPU6050_Base::getAccelFIFOEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ACCEL_FIFO_EN_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ACCEL_FIFO_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set accelerometer FIFO enabled value. @@ -717,7 +717,7 @@ bool MPU6050_Base::getAccelFIFOEnabled() { * @see MPU6050_RA_FIFO_EN */ void MPU6050_Base::setAccelFIFOEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ACCEL_FIFO_EN_BIT, enabled); + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ACCEL_FIFO_EN_BIT, enabled, wireObj); } /** Get Slave 2 FIFO enabled value. * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) @@ -726,7 +726,7 @@ void MPU6050_Base::setAccelFIFOEnabled(bool enabled) { * @see MPU6050_RA_FIFO_EN */ bool MPU6050_Base::getSlave2FIFOEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV2_FIFO_EN_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV2_FIFO_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set Slave 2 FIFO enabled value. @@ -735,7 +735,7 @@ bool MPU6050_Base::getSlave2FIFOEnabled() { * @see MPU6050_RA_FIFO_EN */ void MPU6050_Base::setSlave2FIFOEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV2_FIFO_EN_BIT, enabled); + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV2_FIFO_EN_BIT, enabled, wireObj); } /** Get Slave 1 FIFO enabled value. * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) @@ -744,7 +744,7 @@ void MPU6050_Base::setSlave2FIFOEnabled(bool enabled) { * @see MPU6050_RA_FIFO_EN */ bool MPU6050_Base::getSlave1FIFOEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV1_FIFO_EN_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV1_FIFO_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set Slave 1 FIFO enabled value. @@ -753,7 +753,7 @@ bool MPU6050_Base::getSlave1FIFOEnabled() { * @see MPU6050_RA_FIFO_EN */ void MPU6050_Base::setSlave1FIFOEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV1_FIFO_EN_BIT, enabled); + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV1_FIFO_EN_BIT, enabled, wireObj); } /** Get Slave 0 FIFO enabled value. * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) @@ -762,7 +762,7 @@ void MPU6050_Base::setSlave1FIFOEnabled(bool enabled) { * @see MPU6050_RA_FIFO_EN */ bool MPU6050_Base::getSlave0FIFOEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV0_FIFO_EN_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV0_FIFO_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set Slave 0 FIFO enabled value. @@ -771,7 +771,7 @@ bool MPU6050_Base::getSlave0FIFOEnabled() { * @see MPU6050_RA_FIFO_EN */ void MPU6050_Base::setSlave0FIFOEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV0_FIFO_EN_BIT, enabled); + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV0_FIFO_EN_BIT, enabled, wireObj); } // I2C_MST_CTRL register @@ -792,7 +792,7 @@ void MPU6050_Base::setSlave0FIFOEnabled(bool enabled) { * @see MPU6050_RA_I2C_MST_CTRL */ bool MPU6050_Base::getMultiMasterEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_MULT_MST_EN_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_MULT_MST_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set multi-master enabled value. @@ -801,7 +801,7 @@ bool MPU6050_Base::getMultiMasterEnabled() { * @see MPU6050_RA_I2C_MST_CTRL */ void MPU6050_Base::setMultiMasterEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_MULT_MST_EN_BIT, enabled); + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_MULT_MST_EN_BIT, enabled, wireObj); } /** Get wait-for-external-sensor-data enabled value. * When the WAIT_FOR_ES bit is set to 1, the Data Ready interrupt will be @@ -815,7 +815,7 @@ void MPU6050_Base::setMultiMasterEnabled(bool enabled) { * @see MPU6050_RA_I2C_MST_CTRL */ bool MPU6050_Base::getWaitForExternalSensorEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_WAIT_FOR_ES_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_WAIT_FOR_ES_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set wait-for-external-sensor-data enabled value. @@ -824,7 +824,7 @@ bool MPU6050_Base::getWaitForExternalSensorEnabled() { * @see MPU6050_RA_I2C_MST_CTRL */ void MPU6050_Base::setWaitForExternalSensorEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_WAIT_FOR_ES_BIT, enabled); + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_WAIT_FOR_ES_BIT, enabled, wireObj); } /** Get Slave 3 FIFO enabled value. * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) @@ -833,7 +833,7 @@ void MPU6050_Base::setWaitForExternalSensorEnabled(bool enabled) { * @see MPU6050_RA_MST_CTRL */ bool MPU6050_Base::getSlave3FIFOEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_SLV_3_FIFO_EN_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_SLV_3_FIFO_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set Slave 3 FIFO enabled value. @@ -842,7 +842,7 @@ bool MPU6050_Base::getSlave3FIFOEnabled() { * @see MPU6050_RA_MST_CTRL */ void MPU6050_Base::setSlave3FIFOEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_SLV_3_FIFO_EN_BIT, enabled); + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_SLV_3_FIFO_EN_BIT, enabled, wireObj); } /** Get slave read/write transition enabled value. * The I2C_MST_P_NSR bit configures the I2C Master's transition from one slave @@ -855,7 +855,7 @@ void MPU6050_Base::setSlave3FIFOEnabled(bool enabled) { * @see MPU6050_RA_I2C_MST_CTRL */ bool MPU6050_Base::getSlaveReadWriteTransitionEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_P_NSR_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_P_NSR_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set slave read/write transition enabled value. @@ -864,7 +864,7 @@ bool MPU6050_Base::getSlaveReadWriteTransitionEnabled() { * @see MPU6050_RA_I2C_MST_CTRL */ void MPU6050_Base::setSlaveReadWriteTransitionEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_P_NSR_BIT, enabled); + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_P_NSR_BIT, enabled, wireObj); } /** Get I2C master clock speed. * I2C_MST_CLK is a 4 bit unsigned value which configures a divider on the @@ -896,7 +896,7 @@ void MPU6050_Base::setSlaveReadWriteTransitionEnabled(bool enabled) { * @see MPU6050_RA_I2C_MST_CTRL */ uint8_t MPU6050_Base::getMasterClockSpeed() { - I2Cdev::readBits(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_CLK_BIT, MPU6050_I2C_MST_CLK_LENGTH, buffer); + I2Cdev::readBits(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_CLK_BIT, MPU6050_I2C_MST_CLK_LENGTH, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set I2C master clock speed. @@ -904,7 +904,7 @@ uint8_t MPU6050_Base::getMasterClockSpeed() { * @see MPU6050_RA_I2C_MST_CTRL */ void MPU6050_Base::setMasterClockSpeed(uint8_t speed) { - I2Cdev::writeBits(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_CLK_BIT, MPU6050_I2C_MST_CLK_LENGTH, speed); + I2Cdev::writeBits(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_CLK_BIT, MPU6050_I2C_MST_CLK_LENGTH, speed, wireObj); } // I2C_SLV* registers (Slave 0-3) @@ -952,7 +952,7 @@ void MPU6050_Base::setMasterClockSpeed(uint8_t speed) { */ uint8_t MPU6050_Base::getSlaveAddress(uint8_t num) { if (num > 3) return 0; - I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV0_ADDR + num*3, buffer); + I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV0_ADDR + num*3, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set the I2C address of the specified slave (0-3). @@ -963,7 +963,7 @@ uint8_t MPU6050_Base::getSlaveAddress(uint8_t num) { */ void MPU6050_Base::setSlaveAddress(uint8_t num, uint8_t address) { if (num > 3) return; - I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV0_ADDR + num*3, address); + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV0_ADDR + num*3, address, wireObj); } /** Get the active internal register for the specified slave (0-3). * Read/write operations for this slave will be done to whatever internal @@ -978,7 +978,7 @@ void MPU6050_Base::setSlaveAddress(uint8_t num, uint8_t address) { */ uint8_t MPU6050_Base::getSlaveRegister(uint8_t num) { if (num > 3) return 0; - I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV0_REG + num*3, buffer); + I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV0_REG + num*3, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set the active internal register for the specified slave (0-3). @@ -989,7 +989,7 @@ uint8_t MPU6050_Base::getSlaveRegister(uint8_t num) { */ void MPU6050_Base::setSlaveRegister(uint8_t num, uint8_t reg) { if (num > 3) return; - I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV0_REG + num*3, reg); + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV0_REG + num*3, reg, wireObj); } /** Get the enabled value for the specified slave (0-3). * When set to 1, this bit enables Slave 0 for data transfer operations. When @@ -1000,7 +1000,7 @@ void MPU6050_Base::setSlaveRegister(uint8_t num, uint8_t reg) { */ bool MPU6050_Base::getSlaveEnabled(uint8_t num) { if (num > 3) return 0; - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_EN_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set the enabled value for the specified slave (0-3). @@ -1011,7 +1011,7 @@ bool MPU6050_Base::getSlaveEnabled(uint8_t num) { */ void MPU6050_Base::setSlaveEnabled(uint8_t num, bool enabled) { if (num > 3) return; - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_EN_BIT, enabled); + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_EN_BIT, enabled, wireObj); } /** Get word pair byte-swapping enabled for the specified slave (0-3). * When set to 1, this bit enables byte swapping. When byte swapping is enabled, @@ -1026,7 +1026,7 @@ void MPU6050_Base::setSlaveEnabled(uint8_t num, bool enabled) { */ bool MPU6050_Base::getSlaveWordByteSwap(uint8_t num) { if (num > 3) return 0; - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_BYTE_SW_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_BYTE_SW_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set word pair byte-swapping enabled for the specified slave (0-3). @@ -1037,7 +1037,7 @@ bool MPU6050_Base::getSlaveWordByteSwap(uint8_t num) { */ void MPU6050_Base::setSlaveWordByteSwap(uint8_t num, bool enabled) { if (num > 3) return; - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_BYTE_SW_BIT, enabled); + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_BYTE_SW_BIT, enabled, wireObj); } /** Get write mode for the specified slave (0-3). * When set to 1, the transaction will read or write data only. When cleared to @@ -1051,7 +1051,7 @@ void MPU6050_Base::setSlaveWordByteSwap(uint8_t num, bool enabled) { */ bool MPU6050_Base::getSlaveWriteMode(uint8_t num) { if (num > 3) return 0; - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_REG_DIS_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_REG_DIS_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set write mode for the specified slave (0-3). @@ -1062,7 +1062,7 @@ bool MPU6050_Base::getSlaveWriteMode(uint8_t num) { */ void MPU6050_Base::setSlaveWriteMode(uint8_t num, bool mode) { if (num > 3) return; - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_REG_DIS_BIT, mode); + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_REG_DIS_BIT, mode, wireObj); } /** Get word pair grouping order offset for the specified slave (0-3). * This sets specifies the grouping order of word pairs received from registers. @@ -1077,7 +1077,7 @@ void MPU6050_Base::setSlaveWriteMode(uint8_t num, bool mode) { */ bool MPU6050_Base::getSlaveWordGroupOffset(uint8_t num) { if (num > 3) return 0; - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_GRP_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_GRP_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set word pair grouping order offset for the specified slave (0-3). @@ -1088,7 +1088,7 @@ bool MPU6050_Base::getSlaveWordGroupOffset(uint8_t num) { */ void MPU6050_Base::setSlaveWordGroupOffset(uint8_t num, bool enabled) { if (num > 3) return; - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_GRP_BIT, enabled); + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_GRP_BIT, enabled, wireObj); } /** Get number of bytes to read for the specified slave (0-3). * Specifies the number of bytes transferred to and from Slave 0. Clearing this @@ -1099,7 +1099,7 @@ void MPU6050_Base::setSlaveWordGroupOffset(uint8_t num, bool enabled) { */ uint8_t MPU6050_Base::getSlaveDataLength(uint8_t num) { if (num > 3) return 0; - I2Cdev::readBits(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_LEN_BIT, MPU6050_I2C_SLV_LEN_LENGTH, buffer); + I2Cdev::readBits(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_LEN_BIT, MPU6050_I2C_SLV_LEN_LENGTH, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set number of bytes to read for the specified slave (0-3). @@ -1110,7 +1110,7 @@ uint8_t MPU6050_Base::getSlaveDataLength(uint8_t num) { */ void MPU6050_Base::setSlaveDataLength(uint8_t num, uint8_t length) { if (num > 3) return; - I2Cdev::writeBits(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_LEN_BIT, MPU6050_I2C_SLV_LEN_LENGTH, length); + I2Cdev::writeBits(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_LEN_BIT, MPU6050_I2C_SLV_LEN_LENGTH, length, wireObj); } // I2C_SLV* registers (Slave 4) @@ -1125,7 +1125,7 @@ void MPU6050_Base::setSlaveDataLength(uint8_t num, uint8_t length) { * @see MPU6050_RA_I2C_SLV4_ADDR */ uint8_t MPU6050_Base::getSlave4Address() { - I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV4_ADDR, buffer); + I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV4_ADDR, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set the I2C address of Slave 4. @@ -1134,7 +1134,7 @@ uint8_t MPU6050_Base::getSlave4Address() { * @see MPU6050_RA_I2C_SLV4_ADDR */ void MPU6050_Base::setSlave4Address(uint8_t address) { - I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV4_ADDR, address); + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV4_ADDR, address, wireObj); } /** Get the active internal register for the Slave 4. * Read/write operations for this slave will be done to whatever internal @@ -1144,7 +1144,7 @@ void MPU6050_Base::setSlave4Address(uint8_t address) { * @see MPU6050_RA_I2C_SLV4_REG */ uint8_t MPU6050_Base::getSlave4Register() { - I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV4_REG, buffer); + I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV4_REG, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set the active internal register for Slave 4. @@ -1153,7 +1153,7 @@ uint8_t MPU6050_Base::getSlave4Register() { * @see MPU6050_RA_I2C_SLV4_REG */ void MPU6050_Base::setSlave4Register(uint8_t reg) { - I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV4_REG, reg); + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV4_REG, reg, wireObj); } /** Set new byte to write to Slave 4. * This register stores the data to be written into the Slave 4. If I2C_SLV4_RW @@ -1162,7 +1162,7 @@ void MPU6050_Base::setSlave4Register(uint8_t reg) { * @see MPU6050_RA_I2C_SLV4_DO */ void MPU6050_Base::setSlave4OutputByte(uint8_t data) { - I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV4_DO, data); + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV4_DO, data, wireObj); } /** Get the enabled value for the Slave 4. * When set to 1, this bit enables Slave 4 for data transfer operations. When @@ -1171,7 +1171,7 @@ void MPU6050_Base::setSlave4OutputByte(uint8_t data) { * @see MPU6050_RA_I2C_SLV4_CTRL */ bool MPU6050_Base::getSlave4Enabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_EN_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set the enabled value for Slave 4. @@ -1180,7 +1180,7 @@ bool MPU6050_Base::getSlave4Enabled() { * @see MPU6050_RA_I2C_SLV4_CTRL */ void MPU6050_Base::setSlave4Enabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_EN_BIT, enabled); + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_EN_BIT, enabled, wireObj); } /** Get the enabled value for Slave 4 transaction interrupts. * When set to 1, this bit enables the generation of an interrupt signal upon @@ -1192,7 +1192,7 @@ void MPU6050_Base::setSlave4Enabled(bool enabled) { * @see MPU6050_RA_I2C_SLV4_CTRL */ bool MPU6050_Base::getSlave4InterruptEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_INT_EN_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_INT_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set the enabled value for Slave 4 transaction interrupts. @@ -1201,7 +1201,7 @@ bool MPU6050_Base::getSlave4InterruptEnabled() { * @see MPU6050_RA_I2C_SLV4_CTRL */ void MPU6050_Base::setSlave4InterruptEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_INT_EN_BIT, enabled); + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_INT_EN_BIT, enabled, wireObj); } /** Get write mode for Slave 4. * When set to 1, the transaction will read or write data only. When cleared to @@ -1213,7 +1213,7 @@ void MPU6050_Base::setSlave4InterruptEnabled(bool enabled) { * @see MPU6050_RA_I2C_SLV4_CTRL */ bool MPU6050_Base::getSlave4WriteMode() { - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_REG_DIS_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_REG_DIS_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set write mode for the Slave 4. @@ -1222,7 +1222,7 @@ bool MPU6050_Base::getSlave4WriteMode() { * @see MPU6050_RA_I2C_SLV4_CTRL */ void MPU6050_Base::setSlave4WriteMode(bool mode) { - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_REG_DIS_BIT, mode); + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_REG_DIS_BIT, mode, wireObj); } /** Get Slave 4 master delay value. * This configures the reduced access rate of I2C slaves relative to the Sample @@ -1240,7 +1240,7 @@ void MPU6050_Base::setSlave4WriteMode(bool mode) { * @see MPU6050_RA_I2C_SLV4_CTRL */ uint8_t MPU6050_Base::getSlave4MasterDelay() { - I2Cdev::readBits(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_MST_DLY_BIT, MPU6050_I2C_SLV4_MST_DLY_LENGTH, buffer); + I2Cdev::readBits(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_MST_DLY_BIT, MPU6050_I2C_SLV4_MST_DLY_LENGTH, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set Slave 4 master delay value. @@ -1249,7 +1249,7 @@ uint8_t MPU6050_Base::getSlave4MasterDelay() { * @see MPU6050_RA_I2C_SLV4_CTRL */ void MPU6050_Base::setSlave4MasterDelay(uint8_t delay) { - I2Cdev::writeBits(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_MST_DLY_BIT, MPU6050_I2C_SLV4_MST_DLY_LENGTH, delay); + I2Cdev::writeBits(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_MST_DLY_BIT, MPU6050_I2C_SLV4_MST_DLY_LENGTH, delay, wireObj); } /** Get last available byte read from Slave 4. * This register stores the data read from Slave 4. This field is populated @@ -1258,7 +1258,7 @@ void MPU6050_Base::setSlave4MasterDelay(uint8_t delay) { * @see MPU6050_RA_I2C_SLV4_DI */ uint8_t MPU6050_Base::getSlate4InputByte() { - I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV4_DI, buffer); + I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV4_DI, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } @@ -1274,7 +1274,7 @@ uint8_t MPU6050_Base::getSlate4InputByte() { * @see MPU6050_RA_I2C_MST_STATUS */ bool MPU6050_Base::getPassthroughStatus() { - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_PASS_THROUGH_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_PASS_THROUGH_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Get Slave 4 transaction done status. @@ -1286,7 +1286,7 @@ bool MPU6050_Base::getPassthroughStatus() { * @see MPU6050_RA_I2C_MST_STATUS */ bool MPU6050_Base::getSlave4IsDone() { - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV4_DONE_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV4_DONE_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Get master arbitration lost status. @@ -1297,7 +1297,7 @@ bool MPU6050_Base::getSlave4IsDone() { * @see MPU6050_RA_I2C_MST_STATUS */ bool MPU6050_Base::getLostArbitration() { - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_LOST_ARB_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_LOST_ARB_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Get Slave 4 NACK status. @@ -1308,7 +1308,7 @@ bool MPU6050_Base::getLostArbitration() { * @see MPU6050_RA_I2C_MST_STATUS */ bool MPU6050_Base::getSlave4Nack() { - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV4_NACK_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV4_NACK_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Get Slave 3 NACK status. @@ -1319,7 +1319,7 @@ bool MPU6050_Base::getSlave4Nack() { * @see MPU6050_RA_I2C_MST_STATUS */ bool MPU6050_Base::getSlave3Nack() { - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV3_NACK_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV3_NACK_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Get Slave 2 NACK status. @@ -1330,7 +1330,7 @@ bool MPU6050_Base::getSlave3Nack() { * @see MPU6050_RA_I2C_MST_STATUS */ bool MPU6050_Base::getSlave2Nack() { - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV2_NACK_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV2_NACK_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Get Slave 1 NACK status. @@ -1341,7 +1341,7 @@ bool MPU6050_Base::getSlave2Nack() { * @see MPU6050_RA_I2C_MST_STATUS */ bool MPU6050_Base::getSlave1Nack() { - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV1_NACK_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV1_NACK_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Get Slave 0 NACK status. @@ -1352,7 +1352,7 @@ bool MPU6050_Base::getSlave1Nack() { * @see MPU6050_RA_I2C_MST_STATUS */ bool MPU6050_Base::getSlave0Nack() { - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV0_NACK_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV0_NACK_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } @@ -1365,7 +1365,7 @@ bool MPU6050_Base::getSlave0Nack() { * @see MPU6050_INTCFG_INT_LEVEL_BIT */ bool MPU6050_Base::getInterruptMode() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_LEVEL_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_LEVEL_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set interrupt logic level mode. @@ -1375,7 +1375,7 @@ bool MPU6050_Base::getInterruptMode() { * @see MPU6050_INTCFG_INT_LEVEL_BIT */ void MPU6050_Base::setInterruptMode(bool mode) { - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_LEVEL_BIT, mode); + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_LEVEL_BIT, mode, wireObj); } /** Get interrupt drive mode. * Will be set 0 for push-pull, 1 for open-drain. @@ -1384,7 +1384,7 @@ void MPU6050_Base::setInterruptMode(bool mode) { * @see MPU6050_INTCFG_INT_OPEN_BIT */ bool MPU6050_Base::getInterruptDrive() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_OPEN_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_OPEN_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set interrupt drive mode. @@ -1394,7 +1394,7 @@ bool MPU6050_Base::getInterruptDrive() { * @see MPU6050_INTCFG_INT_OPEN_BIT */ void MPU6050_Base::setInterruptDrive(bool drive) { - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_OPEN_BIT, drive); + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_OPEN_BIT, drive, wireObj); } /** Get interrupt latch mode. * Will be set 0 for 50us-pulse, 1 for latch-until-int-cleared. @@ -1403,7 +1403,7 @@ void MPU6050_Base::setInterruptDrive(bool drive) { * @see MPU6050_INTCFG_LATCH_INT_EN_BIT */ bool MPU6050_Base::getInterruptLatch() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_LATCH_INT_EN_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_LATCH_INT_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set interrupt latch mode. @@ -1413,7 +1413,7 @@ bool MPU6050_Base::getInterruptLatch() { * @see MPU6050_INTCFG_LATCH_INT_EN_BIT */ void MPU6050_Base::setInterruptLatch(bool latch) { - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_LATCH_INT_EN_BIT, latch); + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_LATCH_INT_EN_BIT, latch, wireObj); } /** Get interrupt latch clear mode. * Will be set 0 for status-read-only, 1 for any-register-read. @@ -1422,7 +1422,7 @@ void MPU6050_Base::setInterruptLatch(bool latch) { * @see MPU6050_INTCFG_INT_RD_CLEAR_BIT */ bool MPU6050_Base::getInterruptLatchClear() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_RD_CLEAR_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_RD_CLEAR_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set interrupt latch clear mode. @@ -1432,7 +1432,7 @@ bool MPU6050_Base::getInterruptLatchClear() { * @see MPU6050_INTCFG_INT_RD_CLEAR_BIT */ void MPU6050_Base::setInterruptLatchClear(bool clear) { - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_RD_CLEAR_BIT, clear); + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_RD_CLEAR_BIT, clear, wireObj); } /** Get FSYNC interrupt logic level mode. * @return Current FSYNC interrupt mode (0=active-high, 1=active-low) @@ -1441,7 +1441,7 @@ void MPU6050_Base::setInterruptLatchClear(bool clear) { * @see MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT */ bool MPU6050_Base::getFSyncInterruptLevel() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set FSYNC interrupt logic level mode. @@ -1451,7 +1451,7 @@ bool MPU6050_Base::getFSyncInterruptLevel() { * @see MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT */ void MPU6050_Base::setFSyncInterruptLevel(bool level) { - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT, level); + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT, level, wireObj); } /** Get FSYNC pin interrupt enabled setting. * Will be set 0 for disabled, 1 for enabled. @@ -1460,7 +1460,7 @@ void MPU6050_Base::setFSyncInterruptLevel(bool level) { * @see MPU6050_INTCFG_FSYNC_INT_EN_BIT */ bool MPU6050_Base::getFSyncInterruptEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_EN_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set FSYNC pin interrupt enabled setting. @@ -1470,7 +1470,7 @@ bool MPU6050_Base::getFSyncInterruptEnabled() { * @see MPU6050_INTCFG_FSYNC_INT_EN_BIT */ void MPU6050_Base::setFSyncInterruptEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_EN_BIT, enabled); + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_EN_BIT, enabled, wireObj); } /** Get I2C bypass enabled status. * When this bit is equal to 1 and I2C_MST_EN (Register 106 bit[5]) is equal to @@ -1484,7 +1484,7 @@ void MPU6050_Base::setFSyncInterruptEnabled(bool enabled) { * @see MPU6050_INTCFG_I2C_BYPASS_EN_BIT */ bool MPU6050_Base::getI2CBypassEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_I2C_BYPASS_EN_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_I2C_BYPASS_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set I2C bypass enabled status. @@ -1499,7 +1499,7 @@ bool MPU6050_Base::getI2CBypassEnabled() { * @see MPU6050_INTCFG_I2C_BYPASS_EN_BIT */ void MPU6050_Base::setI2CBypassEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_I2C_BYPASS_EN_BIT, enabled); + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_I2C_BYPASS_EN_BIT, enabled, wireObj); } /** Get reference clock output enabled status. * When this bit is equal to 1, a reference clock output is provided at the @@ -1511,7 +1511,7 @@ void MPU6050_Base::setI2CBypassEnabled(bool enabled) { * @see MPU6050_INTCFG_CLKOUT_EN_BIT */ bool MPU6050_Base::getClockOutputEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_CLKOUT_EN_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_CLKOUT_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set reference clock output enabled status. @@ -1524,7 +1524,7 @@ bool MPU6050_Base::getClockOutputEnabled() { * @see MPU6050_INTCFG_CLKOUT_EN_BIT */ void MPU6050_Base::setClockOutputEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_CLKOUT_EN_BIT, enabled); + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_CLKOUT_EN_BIT, enabled, wireObj); } // INT_ENABLE register @@ -1537,7 +1537,7 @@ void MPU6050_Base::setClockOutputEnabled(bool enabled) { * @see MPU6050_INTERRUPT_FF_BIT **/ uint8_t MPU6050_Base::getIntEnabled() { - I2Cdev::readByte(devAddr, MPU6050_RA_INT_ENABLE, buffer); + I2Cdev::readByte(devAddr, MPU6050_RA_INT_ENABLE, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set full interrupt enabled status. @@ -1549,7 +1549,7 @@ uint8_t MPU6050_Base::getIntEnabled() { * @see MPU6050_INTERRUPT_FF_BIT **/ void MPU6050_Base::setIntEnabled(uint8_t enabled) { - I2Cdev::writeByte(devAddr, MPU6050_RA_INT_ENABLE, enabled); + I2Cdev::writeByte(devAddr, MPU6050_RA_INT_ENABLE, enabled, wireObj); } /** Get Free Fall interrupt enabled status. * Will be set 0 for disabled, 1 for enabled. @@ -1558,7 +1558,7 @@ void MPU6050_Base::setIntEnabled(uint8_t enabled) { * @see MPU6050_INTERRUPT_FF_BIT **/ bool MPU6050_Base::getIntFreefallEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FF_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FF_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set Free Fall interrupt enabled status. @@ -1568,7 +1568,7 @@ bool MPU6050_Base::getIntFreefallEnabled() { * @see MPU6050_INTERRUPT_FF_BIT **/ void MPU6050_Base::setIntFreefallEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FF_BIT, enabled); + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FF_BIT, enabled, wireObj); } /** Get Motion Detection interrupt enabled status. * Will be set 0 for disabled, 1 for enabled. @@ -1577,7 +1577,7 @@ void MPU6050_Base::setIntFreefallEnabled(bool enabled) { * @see MPU6050_INTERRUPT_MOT_BIT **/ bool MPU6050_Base::getIntMotionEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_MOT_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_MOT_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set Motion Detection interrupt enabled status. @@ -1587,7 +1587,7 @@ bool MPU6050_Base::getIntMotionEnabled() { * @see MPU6050_INTERRUPT_MOT_BIT **/ void MPU6050_Base::setIntMotionEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_MOT_BIT, enabled); + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_MOT_BIT, enabled, wireObj); } /** Get Zero Motion Detection interrupt enabled status. * Will be set 0 for disabled, 1 for enabled. @@ -1596,7 +1596,7 @@ void MPU6050_Base::setIntMotionEnabled(bool enabled) { * @see MPU6050_INTERRUPT_ZMOT_BIT **/ bool MPU6050_Base::getIntZeroMotionEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_ZMOT_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_ZMOT_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set Zero Motion Detection interrupt enabled status. @@ -1606,7 +1606,7 @@ bool MPU6050_Base::getIntZeroMotionEnabled() { * @see MPU6050_INTERRUPT_ZMOT_BIT **/ void MPU6050_Base::setIntZeroMotionEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_ZMOT_BIT, enabled); + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_ZMOT_BIT, enabled, wireObj); } /** Get FIFO Buffer Overflow interrupt enabled status. * Will be set 0 for disabled, 1 for enabled. @@ -1615,7 +1615,7 @@ void MPU6050_Base::setIntZeroMotionEnabled(bool enabled) { * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT **/ bool MPU6050_Base::getIntFIFOBufferOverflowEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set FIFO Buffer Overflow interrupt enabled status. @@ -1625,7 +1625,7 @@ bool MPU6050_Base::getIntFIFOBufferOverflowEnabled() { * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT **/ void MPU6050_Base::setIntFIFOBufferOverflowEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, enabled); + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, enabled, wireObj); } /** Get I2C Master interrupt enabled status. * This enables any of the I2C Master interrupt sources to generate an @@ -1635,7 +1635,7 @@ void MPU6050_Base::setIntFIFOBufferOverflowEnabled(bool enabled) { * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT **/ bool MPU6050_Base::getIntI2CMasterEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_I2C_MST_INT_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_I2C_MST_INT_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set I2C Master interrupt enabled status. @@ -1645,7 +1645,7 @@ bool MPU6050_Base::getIntI2CMasterEnabled() { * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT **/ void MPU6050_Base::setIntI2CMasterEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_I2C_MST_INT_BIT, enabled); + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_I2C_MST_INT_BIT, enabled, wireObj); } /** Get Data Ready interrupt enabled setting. * This event occurs each time a write operation to all of the sensor registers @@ -1655,7 +1655,7 @@ void MPU6050_Base::setIntI2CMasterEnabled(bool enabled) { * @see MPU6050_INTERRUPT_DATA_RDY_BIT */ bool MPU6050_Base::getIntDataReadyEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DATA_RDY_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DATA_RDY_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set Data Ready interrupt enabled status. @@ -1665,7 +1665,7 @@ bool MPU6050_Base::getIntDataReadyEnabled() { * @see MPU6050_INTERRUPT_DATA_RDY_BIT */ void MPU6050_Base::setIntDataReadyEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DATA_RDY_BIT, enabled); + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DATA_RDY_BIT, enabled, wireObj); } // INT_STATUS register @@ -1678,7 +1678,7 @@ void MPU6050_Base::setIntDataReadyEnabled(bool enabled) { * @see MPU6050_RA_INT_STATUS */ uint8_t MPU6050_Base::getIntStatus() { - I2Cdev::readByte(devAddr, MPU6050_RA_INT_STATUS, buffer); + I2Cdev::readByte(devAddr, MPU6050_RA_INT_STATUS, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Get Free Fall interrupt status. @@ -1689,7 +1689,7 @@ uint8_t MPU6050_Base::getIntStatus() { * @see MPU6050_INTERRUPT_FF_BIT */ bool MPU6050_Base::getIntFreefallStatus() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_FF_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_FF_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Get Motion Detection interrupt status. @@ -1700,7 +1700,7 @@ bool MPU6050_Base::getIntFreefallStatus() { * @see MPU6050_INTERRUPT_MOT_BIT */ bool MPU6050_Base::getIntMotionStatus() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_MOT_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_MOT_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Get Zero Motion Detection interrupt status. @@ -1711,7 +1711,7 @@ bool MPU6050_Base::getIntMotionStatus() { * @see MPU6050_INTERRUPT_ZMOT_BIT */ bool MPU6050_Base::getIntZeroMotionStatus() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_ZMOT_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_ZMOT_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Get FIFO Buffer Overflow interrupt status. @@ -1722,7 +1722,7 @@ bool MPU6050_Base::getIntZeroMotionStatus() { * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT */ bool MPU6050_Base::getIntFIFOBufferOverflowStatus() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Get I2C Master interrupt status. @@ -1734,7 +1734,7 @@ bool MPU6050_Base::getIntFIFOBufferOverflowStatus() { * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT */ bool MPU6050_Base::getIntI2CMasterStatus() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_I2C_MST_INT_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_I2C_MST_INT_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Get Data Ready interrupt status. @@ -1745,7 +1745,7 @@ bool MPU6050_Base::getIntI2CMasterStatus() { * @see MPU6050_INTERRUPT_DATA_RDY_BIT */ bool MPU6050_Base::getIntDataReadyStatus() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_DATA_RDY_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_DATA_RDY_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } @@ -1788,7 +1788,7 @@ void MPU6050_Base::getMotion9(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx * @see MPU6050_RA_ACCEL_XOUT_H */ void MPU6050_Base::getMotion6(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz) { - I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_XOUT_H, 14, buffer); + I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_XOUT_H, 14, buffer, I2Cdev::readTimeout, wireObj); *ax = (((int16_t)buffer[0]) << 8) | buffer[1]; *ay = (((int16_t)buffer[2]) << 8) | buffer[3]; *az = (((int16_t)buffer[4]) << 8) | buffer[5]; @@ -1833,7 +1833,7 @@ void MPU6050_Base::getMotion6(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx * @see MPU6050_RA_GYRO_XOUT_H */ void MPU6050_Base::getAcceleration(int16_t* x, int16_t* y, int16_t* z) { - I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_XOUT_H, 6, buffer); + I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_XOUT_H, 6, buffer, I2Cdev::readTimeout, wireObj); *x = (((int16_t)buffer[0]) << 8) | buffer[1]; *y = (((int16_t)buffer[2]) << 8) | buffer[3]; *z = (((int16_t)buffer[4]) << 8) | buffer[5]; @@ -1844,7 +1844,7 @@ void MPU6050_Base::getAcceleration(int16_t* x, int16_t* y, int16_t* z) { * @see MPU6050_RA_ACCEL_XOUT_H */ int16_t MPU6050_Base::getAccelerationX() { - I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_XOUT_H, 2, buffer); + I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_XOUT_H, 2, buffer, I2Cdev::readTimeout, wireObj); return (((int16_t)buffer[0]) << 8) | buffer[1]; } /** Get Y-axis accelerometer reading. @@ -1853,7 +1853,7 @@ int16_t MPU6050_Base::getAccelerationX() { * @see MPU6050_RA_ACCEL_YOUT_H */ int16_t MPU6050_Base::getAccelerationY() { - I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_YOUT_H, 2, buffer); + I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_YOUT_H, 2, buffer, I2Cdev::readTimeout, wireObj); return (((int16_t)buffer[0]) << 8) | buffer[1]; } /** Get Z-axis accelerometer reading. @@ -1862,7 +1862,7 @@ int16_t MPU6050_Base::getAccelerationY() { * @see MPU6050_RA_ACCEL_ZOUT_H */ int16_t MPU6050_Base::getAccelerationZ() { - I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_ZOUT_H, 2, buffer); + I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_ZOUT_H, 2, buffer, I2Cdev::readTimeout, wireObj); return (((int16_t)buffer[0]) << 8) | buffer[1]; } @@ -1873,7 +1873,7 @@ int16_t MPU6050_Base::getAccelerationZ() { * @see MPU6050_RA_TEMP_OUT_H */ int16_t MPU6050_Base::getTemperature() { - I2Cdev::readBytes(devAddr, MPU6050_RA_TEMP_OUT_H, 2, buffer); + I2Cdev::readBytes(devAddr, MPU6050_RA_TEMP_OUT_H, 2, buffer, I2Cdev::readTimeout, wireObj); return (((int16_t)buffer[0]) << 8) | buffer[1]; } @@ -1912,7 +1912,7 @@ int16_t MPU6050_Base::getTemperature() { * @see MPU6050_RA_GYRO_XOUT_H */ void MPU6050_Base::getRotation(int16_t* x, int16_t* y, int16_t* z) { - I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_XOUT_H, 6, buffer); + I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_XOUT_H, 6, buffer, I2Cdev::readTimeout, wireObj); *x = (((int16_t)buffer[0]) << 8) | buffer[1]; *y = (((int16_t)buffer[2]) << 8) | buffer[3]; *z = (((int16_t)buffer[4]) << 8) | buffer[5]; @@ -1923,7 +1923,7 @@ void MPU6050_Base::getRotation(int16_t* x, int16_t* y, int16_t* z) { * @see MPU6050_RA_GYRO_XOUT_H */ int16_t MPU6050_Base::getRotationX() { - I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_XOUT_H, 2, buffer); + I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_XOUT_H, 2, buffer, I2Cdev::readTimeout, wireObj); return (((int16_t)buffer[0]) << 8) | buffer[1]; } /** Get Y-axis gyroscope reading. @@ -1932,7 +1932,7 @@ int16_t MPU6050_Base::getRotationX() { * @see MPU6050_RA_GYRO_YOUT_H */ int16_t MPU6050_Base::getRotationY() { - I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_YOUT_H, 2, buffer); + I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_YOUT_H, 2, buffer, I2Cdev::readTimeout, wireObj); return (((int16_t)buffer[0]) << 8) | buffer[1]; } /** Get Z-axis gyroscope reading. @@ -1941,7 +1941,7 @@ int16_t MPU6050_Base::getRotationY() { * @see MPU6050_RA_GYRO_ZOUT_H */ int16_t MPU6050_Base::getRotationZ() { - I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_ZOUT_H, 2, buffer); + I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_ZOUT_H, 2, buffer, I2Cdev::readTimeout, wireObj); return (((int16_t)buffer[0]) << 8) | buffer[1]; } @@ -2022,7 +2022,7 @@ int16_t MPU6050_Base::getRotationZ() { * @return Byte read from register */ uint8_t MPU6050_Base::getExternalSensorByte(int position) { - I2Cdev::readByte(devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, buffer); + I2Cdev::readByte(devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Read word (2 bytes) from external sensor data registers. @@ -2031,7 +2031,7 @@ uint8_t MPU6050_Base::getExternalSensorByte(int position) { * @see getExternalSensorByte() */ uint16_t MPU6050_Base::getExternalSensorWord(int position) { - I2Cdev::readBytes(devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, 2, buffer); + I2Cdev::readBytes(devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, 2, buffer, I2Cdev::readTimeout, wireObj); return (((uint16_t)buffer[0]) << 8) | buffer[1]; } /** Read double word (4 bytes) from external sensor data registers. @@ -2040,7 +2040,7 @@ uint16_t MPU6050_Base::getExternalSensorWord(int position) { * @see getExternalSensorByte() */ uint32_t MPU6050_Base::getExternalSensorDWord(int position) { - I2Cdev::readBytes(devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, 4, buffer); + I2Cdev::readBytes(devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, 4, buffer, I2Cdev::readTimeout, wireObj); return (((uint32_t)buffer[0]) << 24) | (((uint32_t)buffer[1]) << 16) | (((uint16_t)buffer[2]) << 8) | buffer[3]; } @@ -2051,7 +2051,7 @@ uint32_t MPU6050_Base::getExternalSensorDWord(int position) { * @see MPU6050_RA_MOT_DETECT_STATUS */ uint8_t MPU6050_Base::getMotionStatus() { - I2Cdev::readByte(devAddr, MPU6050_RA_MOT_DETECT_STATUS, buffer); + I2Cdev::readByte(devAddr, MPU6050_RA_MOT_DETECT_STATUS, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Get X-axis negative motion detection interrupt status. @@ -2060,7 +2060,7 @@ uint8_t MPU6050_Base::getMotionStatus() { * @see MPU6050_MOTION_MOT_XNEG_BIT */ bool MPU6050_Base::getXNegMotionDetected() { - I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_XNEG_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_XNEG_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Get X-axis positive motion detection interrupt status. @@ -2069,7 +2069,7 @@ bool MPU6050_Base::getXNegMotionDetected() { * @see MPU6050_MOTION_MOT_XPOS_BIT */ bool MPU6050_Base::getXPosMotionDetected() { - I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_XPOS_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_XPOS_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Get Y-axis negative motion detection interrupt status. @@ -2078,7 +2078,7 @@ bool MPU6050_Base::getXPosMotionDetected() { * @see MPU6050_MOTION_MOT_YNEG_BIT */ bool MPU6050_Base::getYNegMotionDetected() { - I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_YNEG_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_YNEG_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Get Y-axis positive motion detection interrupt status. @@ -2087,7 +2087,7 @@ bool MPU6050_Base::getYNegMotionDetected() { * @see MPU6050_MOTION_MOT_YPOS_BIT */ bool MPU6050_Base::getYPosMotionDetected() { - I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_YPOS_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_YPOS_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Get Z-axis negative motion detection interrupt status. @@ -2096,7 +2096,7 @@ bool MPU6050_Base::getYPosMotionDetected() { * @see MPU6050_MOTION_MOT_ZNEG_BIT */ bool MPU6050_Base::getZNegMotionDetected() { - I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZNEG_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZNEG_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Get Z-axis positive motion detection interrupt status. @@ -2105,7 +2105,7 @@ bool MPU6050_Base::getZNegMotionDetected() { * @see MPU6050_MOTION_MOT_ZPOS_BIT */ bool MPU6050_Base::getZPosMotionDetected() { - I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZPOS_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZPOS_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Get zero motion detection interrupt status. @@ -2114,7 +2114,7 @@ bool MPU6050_Base::getZPosMotionDetected() { * @see MPU6050_MOTION_MOT_ZRMOT_BIT */ bool MPU6050_Base::getZeroMotionDetected() { - I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZRMOT_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZRMOT_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } @@ -2130,7 +2130,7 @@ bool MPU6050_Base::getZeroMotionDetected() { */ void MPU6050_Base::setSlaveOutputByte(uint8_t num, uint8_t data) { if (num > 3) return; - I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV0_DO + num, data); + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV0_DO + num, data, wireObj); } // I2C_MST_DELAY_CTRL register @@ -2144,7 +2144,7 @@ void MPU6050_Base::setSlaveOutputByte(uint8_t num, uint8_t data) { * @see MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT */ bool MPU6050_Base::getExternalShadowDelayEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set external data shadow delay enabled status. @@ -2154,7 +2154,7 @@ bool MPU6050_Base::getExternalShadowDelayEnabled() { * @see MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT */ void MPU6050_Base::setExternalShadowDelayEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT, enabled); + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT, enabled, wireObj); } /** Get slave delay enabled status. * When a particular slave delay is enabled, the rate of access for the that @@ -2177,7 +2177,7 @@ void MPU6050_Base::setExternalShadowDelayEnabled(bool enabled) { bool MPU6050_Base::getSlaveDelayEnabled(uint8_t num) { // MPU6050_DELAYCTRL_I2C_SLV4_DLY_EN_BIT is 4, SLV3 is 3, etc. if (num > 4) return 0; - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, num, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, num, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set slave delay enabled status. @@ -2187,7 +2187,7 @@ bool MPU6050_Base::getSlaveDelayEnabled(uint8_t num) { * @see MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT */ void MPU6050_Base::setSlaveDelayEnabled(uint8_t num, bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, num, enabled); + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, num, enabled, wireObj); } // SIGNAL_PATH_RESET register @@ -2199,7 +2199,7 @@ void MPU6050_Base::setSlaveDelayEnabled(uint8_t num, bool enabled) { * @see MPU6050_PATHRESET_GYRO_RESET_BIT */ void MPU6050_Base::resetGyroscopePath() { - I2Cdev::writeBit(devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_GYRO_RESET_BIT, true); + I2Cdev::writeBit(devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_GYRO_RESET_BIT, true, wireObj); } /** Reset accelerometer signal path. * The reset will revert the signal path analog to digital converters and @@ -2208,7 +2208,7 @@ void MPU6050_Base::resetGyroscopePath() { * @see MPU6050_PATHRESET_ACCEL_RESET_BIT */ void MPU6050_Base::resetAccelerometerPath() { - I2Cdev::writeBit(devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_ACCEL_RESET_BIT, true); + I2Cdev::writeBit(devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_ACCEL_RESET_BIT, true, wireObj); } /** Reset temperature sensor signal path. * The reset will revert the signal path analog to digital converters and @@ -2217,7 +2217,7 @@ void MPU6050_Base::resetAccelerometerPath() { * @see MPU6050_PATHRESET_TEMP_RESET_BIT */ void MPU6050_Base::resetTemperaturePath() { - I2Cdev::writeBit(devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_TEMP_RESET_BIT, true); + I2Cdev::writeBit(devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_TEMP_RESET_BIT, true, wireObj); } // MOT_DETECT_CTRL register @@ -2237,7 +2237,7 @@ void MPU6050_Base::resetTemperaturePath() { * @see MPU6050_DETECT_ACCEL_ON_DELAY_BIT */ uint8_t MPU6050_Base::getAccelerometerPowerOnDelay() { - I2Cdev::readBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_ACCEL_ON_DELAY_BIT, MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH, buffer); + I2Cdev::readBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_ACCEL_ON_DELAY_BIT, MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set accelerometer power-on delay. @@ -2247,7 +2247,7 @@ uint8_t MPU6050_Base::getAccelerometerPowerOnDelay() { * @see MPU6050_DETECT_ACCEL_ON_DELAY_BIT */ void MPU6050_Base::setAccelerometerPowerOnDelay(uint8_t delay) { - I2Cdev::writeBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_ACCEL_ON_DELAY_BIT, MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH, delay); + I2Cdev::writeBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_ACCEL_ON_DELAY_BIT, MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH, delay, wireObj); } /** Get Free Fall detection counter decrement configuration. * Detection is registered by the Free Fall detection module after accelerometer @@ -2276,7 +2276,7 @@ void MPU6050_Base::setAccelerometerPowerOnDelay(uint8_t delay) { * @see MPU6050_DETECT_FF_COUNT_BIT */ uint8_t MPU6050_Base::getFreefallDetectionCounterDecrement() { - I2Cdev::readBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_FF_COUNT_BIT, MPU6050_DETECT_FF_COUNT_LENGTH, buffer); + I2Cdev::readBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_FF_COUNT_BIT, MPU6050_DETECT_FF_COUNT_LENGTH, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set Free Fall detection counter decrement configuration. @@ -2286,7 +2286,7 @@ uint8_t MPU6050_Base::getFreefallDetectionCounterDecrement() { * @see MPU6050_DETECT_FF_COUNT_BIT */ void MPU6050_Base::setFreefallDetectionCounterDecrement(uint8_t decrement) { - I2Cdev::writeBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_FF_COUNT_BIT, MPU6050_DETECT_FF_COUNT_LENGTH, decrement); + I2Cdev::writeBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_FF_COUNT_BIT, MPU6050_DETECT_FF_COUNT_LENGTH, decrement, wireObj); } /** Get Motion detection counter decrement configuration. * Detection is registered by the Motion detection module after accelerometer @@ -2312,7 +2312,7 @@ void MPU6050_Base::setFreefallDetectionCounterDecrement(uint8_t decrement) { * */ uint8_t MPU6050_Base::getMotionDetectionCounterDecrement() { - I2Cdev::readBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_MOT_COUNT_BIT, MPU6050_DETECT_MOT_COUNT_LENGTH, buffer); + I2Cdev::readBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_MOT_COUNT_BIT, MPU6050_DETECT_MOT_COUNT_LENGTH, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set Motion detection counter decrement configuration. @@ -2322,7 +2322,7 @@ uint8_t MPU6050_Base::getMotionDetectionCounterDecrement() { * @see MPU6050_DETECT_MOT_COUNT_BIT */ void MPU6050_Base::setMotionDetectionCounterDecrement(uint8_t decrement) { - I2Cdev::writeBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_MOT_COUNT_BIT, MPU6050_DETECT_MOT_COUNT_LENGTH, decrement); + I2Cdev::writeBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_MOT_COUNT_BIT, MPU6050_DETECT_MOT_COUNT_LENGTH, decrement, wireObj); } // USER_CTRL register @@ -2336,7 +2336,7 @@ void MPU6050_Base::setMotionDetectionCounterDecrement(uint8_t decrement) { * @see MPU6050_USERCTRL_FIFO_EN_BIT */ bool MPU6050_Base::getFIFOEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_EN_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set FIFO enabled status. @@ -2346,7 +2346,7 @@ bool MPU6050_Base::getFIFOEnabled() { * @see MPU6050_USERCTRL_FIFO_EN_BIT */ void MPU6050_Base::setFIFOEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_EN_BIT, enabled); + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_EN_BIT, enabled, wireObj); } /** Get I2C Master Mode enabled status. * When this mode is enabled, the MPU-60X0 acts as the I2C Master to the @@ -2360,7 +2360,7 @@ void MPU6050_Base::setFIFOEnabled(bool enabled) { * @see MPU6050_USERCTRL_I2C_MST_EN_BIT */ bool MPU6050_Base::getI2CMasterModeEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_EN_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set I2C Master Mode enabled status. @@ -2370,14 +2370,14 @@ bool MPU6050_Base::getI2CMasterModeEnabled() { * @see MPU6050_USERCTRL_I2C_MST_EN_BIT */ void MPU6050_Base::setI2CMasterModeEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_EN_BIT, enabled); + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_EN_BIT, enabled, wireObj); } /** Switch from I2C to SPI mode (MPU-6000 only) * If this is set, the primary SPI interface will be enabled in place of the * disabled primary I2C interface. */ void MPU6050_Base::switchSPIEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_IF_DIS_BIT, enabled); + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_IF_DIS_BIT, enabled, wireObj); } /** Reset the FIFO. * This bit resets the FIFO buffer when set to 1 while FIFO_EN equals 0. This @@ -2386,7 +2386,7 @@ void MPU6050_Base::switchSPIEnabled(bool enabled) { * @see MPU6050_USERCTRL_FIFO_RESET_BIT */ void MPU6050_Base::resetFIFO() { - I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_RESET_BIT, true); + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_RESET_BIT, true, wireObj); } /** Reset the I2C Master. * This bit resets the I2C Master when set to 1 while I2C_MST_EN equals 0. @@ -2395,7 +2395,7 @@ void MPU6050_Base::resetFIFO() { * @see MPU6050_USERCTRL_I2C_MST_RESET_BIT */ void MPU6050_Base::resetI2CMaster() { - I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_RESET_BIT, true); + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_RESET_BIT, true, wireObj); } /** Reset all sensor registers and signal paths. * When set to 1, this bit resets the signal paths for all sensors (gyroscopes, @@ -2410,7 +2410,7 @@ void MPU6050_Base::resetI2CMaster() { * @see MPU6050_USERCTRL_SIG_COND_RESET_BIT */ void MPU6050_Base::resetSensors() { - I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_SIG_COND_RESET_BIT, true); + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_SIG_COND_RESET_BIT, true, wireObj); } // PWR_MGMT_1 register @@ -2421,7 +2421,7 @@ void MPU6050_Base::resetSensors() { * @see MPU6050_PWR1_DEVICE_RESET_BIT */ void MPU6050_Base::reset() { - I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_DEVICE_RESET_BIT, true); + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_DEVICE_RESET_BIT, true, wireObj); } /** Get sleep mode status. * Setting the SLEEP bit in the register puts the device into very low power @@ -2435,7 +2435,7 @@ void MPU6050_Base::reset() { * @see MPU6050_PWR1_SLEEP_BIT */ bool MPU6050_Base::getSleepEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set sleep mode status. @@ -2445,7 +2445,7 @@ bool MPU6050_Base::getSleepEnabled() { * @see MPU6050_PWR1_SLEEP_BIT */ void MPU6050_Base::setSleepEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, enabled); + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, enabled, wireObj); } /** Get wake cycle enabled status. * When this bit is set to 1 and SLEEP is disabled, the MPU-60X0 will cycle @@ -2456,7 +2456,7 @@ void MPU6050_Base::setSleepEnabled(bool enabled) { * @see MPU6050_PWR1_CYCLE_BIT */ bool MPU6050_Base::getWakeCycleEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CYCLE_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CYCLE_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set wake cycle enabled status. @@ -2466,7 +2466,7 @@ bool MPU6050_Base::getWakeCycleEnabled() { * @see MPU6050_PWR1_CYCLE_BIT */ void MPU6050_Base::setWakeCycleEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CYCLE_BIT, enabled); + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CYCLE_BIT, enabled, wireObj); } /** Get temperature sensor enabled status. * Control the usage of the internal temperature sensor. @@ -2480,7 +2480,7 @@ void MPU6050_Base::setWakeCycleEnabled(bool enabled) { * @see MPU6050_PWR1_TEMP_DIS_BIT */ bool MPU6050_Base::getTempSensorEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_TEMP_DIS_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_TEMP_DIS_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0] == 0; // 1 is actually disabled here } /** Set temperature sensor enabled status. @@ -2495,7 +2495,7 @@ bool MPU6050_Base::getTempSensorEnabled() { */ void MPU6050_Base::setTempSensorEnabled(bool enabled) { // 1 is actually disabled here - I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_TEMP_DIS_BIT, !enabled); + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_TEMP_DIS_BIT, !enabled, wireObj); } /** Get clock source setting. * @return Current clock source setting @@ -2504,7 +2504,7 @@ void MPU6050_Base::setTempSensorEnabled(bool enabled) { * @see MPU6050_PWR1_CLKSEL_LENGTH */ uint8_t MPU6050_Base::getClockSource() { - I2Cdev::readBits(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, buffer); + I2Cdev::readBits(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set clock source setting. @@ -2538,7 +2538,7 @@ uint8_t MPU6050_Base::getClockSource() { * @see MPU6050_PWR1_CLKSEL_LENGTH */ void MPU6050_Base::setClockSource(uint8_t source) { - I2Cdev::writeBits(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, source); + I2Cdev::writeBits(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, source, wireObj); } // PWR_MGMT_2 register @@ -2567,7 +2567,7 @@ void MPU6050_Base::setClockSource(uint8_t source) { * @see MPU6050_RA_PWR_MGMT_2 */ uint8_t MPU6050_Base::getWakeFrequency() { - I2Cdev::readBits(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_LP_WAKE_CTRL_BIT, MPU6050_PWR2_LP_WAKE_CTRL_LENGTH, buffer); + I2Cdev::readBits(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_LP_WAKE_CTRL_BIT, MPU6050_PWR2_LP_WAKE_CTRL_LENGTH, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set wake frequency in Accel-Only Low Power Mode. @@ -2575,7 +2575,7 @@ uint8_t MPU6050_Base::getWakeFrequency() { * @see MPU6050_RA_PWR_MGMT_2 */ void MPU6050_Base::setWakeFrequency(uint8_t frequency) { - I2Cdev::writeBits(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_LP_WAKE_CTRL_BIT, MPU6050_PWR2_LP_WAKE_CTRL_LENGTH, frequency); + I2Cdev::writeBits(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_LP_WAKE_CTRL_BIT, MPU6050_PWR2_LP_WAKE_CTRL_LENGTH, frequency, wireObj); } /** Get X-axis accelerometer standby enabled status. @@ -2585,7 +2585,7 @@ void MPU6050_Base::setWakeFrequency(uint8_t frequency) { * @see MPU6050_PWR2_STBY_XA_BIT */ bool MPU6050_Base::getStandbyXAccelEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XA_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XA_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set X-axis accelerometer standby enabled status. @@ -2595,7 +2595,7 @@ bool MPU6050_Base::getStandbyXAccelEnabled() { * @see MPU6050_PWR2_STBY_XA_BIT */ void MPU6050_Base::setStandbyXAccelEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XA_BIT, enabled); + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XA_BIT, enabled, wireObj); } /** Get Y-axis accelerometer standby enabled status. * If enabled, the Y-axis will not gather or report data (or use power). @@ -2604,7 +2604,7 @@ void MPU6050_Base::setStandbyXAccelEnabled(bool enabled) { * @see MPU6050_PWR2_STBY_YA_BIT */ bool MPU6050_Base::getStandbyYAccelEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YA_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YA_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set Y-axis accelerometer standby enabled status. @@ -2614,7 +2614,7 @@ bool MPU6050_Base::getStandbyYAccelEnabled() { * @see MPU6050_PWR2_STBY_YA_BIT */ void MPU6050_Base::setStandbyYAccelEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YA_BIT, enabled); + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YA_BIT, enabled, wireObj); } /** Get Z-axis accelerometer standby enabled status. * If enabled, the Z-axis will not gather or report data (or use power). @@ -2623,7 +2623,7 @@ void MPU6050_Base::setStandbyYAccelEnabled(bool enabled) { * @see MPU6050_PWR2_STBY_ZA_BIT */ bool MPU6050_Base::getStandbyZAccelEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZA_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZA_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set Z-axis accelerometer standby enabled status. @@ -2633,7 +2633,7 @@ bool MPU6050_Base::getStandbyZAccelEnabled() { * @see MPU6050_PWR2_STBY_ZA_BIT */ void MPU6050_Base::setStandbyZAccelEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZA_BIT, enabled); + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZA_BIT, enabled, wireObj); } /** Get X-axis gyroscope standby enabled status. * If enabled, the X-axis will not gather or report data (or use power). @@ -2642,7 +2642,7 @@ void MPU6050_Base::setStandbyZAccelEnabled(bool enabled) { * @see MPU6050_PWR2_STBY_XG_BIT */ bool MPU6050_Base::getStandbyXGyroEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XG_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XG_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set X-axis gyroscope standby enabled status. @@ -2652,7 +2652,7 @@ bool MPU6050_Base::getStandbyXGyroEnabled() { * @see MPU6050_PWR2_STBY_XG_BIT */ void MPU6050_Base::setStandbyXGyroEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XG_BIT, enabled); + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XG_BIT, enabled, wireObj); } /** Get Y-axis gyroscope standby enabled status. * If enabled, the Y-axis will not gather or report data (or use power). @@ -2661,7 +2661,7 @@ void MPU6050_Base::setStandbyXGyroEnabled(bool enabled) { * @see MPU6050_PWR2_STBY_YG_BIT */ bool MPU6050_Base::getStandbyYGyroEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YG_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YG_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set Y-axis gyroscope standby enabled status. @@ -2671,7 +2671,7 @@ bool MPU6050_Base::getStandbyYGyroEnabled() { * @see MPU6050_PWR2_STBY_YG_BIT */ void MPU6050_Base::setStandbyYGyroEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YG_BIT, enabled); + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YG_BIT, enabled, wireObj); } /** Get Z-axis gyroscope standby enabled status. * If enabled, the Z-axis will not gather or report data (or use power). @@ -2680,7 +2680,7 @@ void MPU6050_Base::setStandbyYGyroEnabled(bool enabled) { * @see MPU6050_PWR2_STBY_ZG_BIT */ bool MPU6050_Base::getStandbyZGyroEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZG_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZG_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set Z-axis gyroscope standby enabled status. @@ -2690,7 +2690,7 @@ bool MPU6050_Base::getStandbyZGyroEnabled() { * @see MPU6050_PWR2_STBY_ZG_BIT */ void MPU6050_Base::setStandbyZGyroEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZG_BIT, enabled); + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZG_BIT, enabled, wireObj); } // FIFO_COUNT* registers @@ -2703,7 +2703,7 @@ void MPU6050_Base::setStandbyZGyroEnabled(bool enabled) { * @return Current FIFO buffer size */ uint16_t MPU6050_Base::getFIFOCount() { - I2Cdev::readBytes(devAddr, MPU6050_RA_FIFO_COUNTH, 2, buffer); + I2Cdev::readBytes(devAddr, MPU6050_RA_FIFO_COUNTH, 2, buffer, I2Cdev::readTimeout, wireObj); return (((uint16_t)buffer[0]) << 8) | buffer[1]; } @@ -2735,12 +2735,12 @@ uint16_t MPU6050_Base::getFIFOCount() { * @return Byte from FIFO buffer */ uint8_t MPU6050_Base::getFIFOByte() { - I2Cdev::readByte(devAddr, MPU6050_RA_FIFO_R_W, buffer); + I2Cdev::readByte(devAddr, MPU6050_RA_FIFO_R_W, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } void MPU6050_Base::getFIFOBytes(uint8_t *data, uint8_t length) { if(length > 0){ - I2Cdev::readBytes(devAddr, MPU6050_RA_FIFO_R_W, length, data); + I2Cdev::readBytes(devAddr, MPU6050_RA_FIFO_R_W, length, data, I2Cdev::readTimeout, wireObj); } else { *data = 0; } @@ -2809,7 +2809,7 @@ void MPU6050_Base::setFIFOTimeout(uint32_t fifoTimeout) { * @see MPU6050_RA_FIFO_R_W */ void MPU6050_Base::setFIFOByte(uint8_t data) { - I2Cdev::writeByte(devAddr, MPU6050_RA_FIFO_R_W, data); + I2Cdev::writeByte(devAddr, MPU6050_RA_FIFO_R_W, data, wireObj); } // WHO_AM_I register @@ -2822,7 +2822,7 @@ void MPU6050_Base::setFIFOByte(uint8_t data) { * @see MPU6050_WHO_AM_I_LENGTH */ uint8_t MPU6050_Base::getDeviceID() { - I2Cdev::readBits(devAddr, MPU6050_RA_WHO_AM_I, MPU6050_WHO_AM_I_BIT, MPU6050_WHO_AM_I_LENGTH, buffer); + I2Cdev::readBits(devAddr, MPU6050_RA_WHO_AM_I, MPU6050_WHO_AM_I_BIT, MPU6050_WHO_AM_I_LENGTH, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } /** Set Device ID. @@ -2835,7 +2835,7 @@ uint8_t MPU6050_Base::getDeviceID() { * @see MPU6050_WHO_AM_I_LENGTH */ void MPU6050_Base::setDeviceID(uint8_t id) { - I2Cdev::writeBits(devAddr, MPU6050_RA_WHO_AM_I, MPU6050_WHO_AM_I_BIT, MPU6050_WHO_AM_I_LENGTH, id); + I2Cdev::writeBits(devAddr, MPU6050_RA_WHO_AM_I, MPU6050_WHO_AM_I_BIT, MPU6050_WHO_AM_I_LENGTH, id, wireObj); } // ======== UNDOCUMENTED/DMP REGISTERS/METHODS ======== @@ -2843,202 +2843,202 @@ void MPU6050_Base::setDeviceID(uint8_t id) { // XG_OFFS_TC register uint8_t MPU6050_Base::getOTPBankValid() { - I2Cdev::readBit(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OTP_BNK_VLD_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OTP_BNK_VLD_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } void MPU6050_Base::setOTPBankValid(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OTP_BNK_VLD_BIT, enabled); + I2Cdev::writeBit(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OTP_BNK_VLD_BIT, enabled, wireObj); } int8_t MPU6050_Base::getXGyroOffsetTC() { - I2Cdev::readBits(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, buffer); + I2Cdev::readBits(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } void MPU6050_Base::setXGyroOffsetTC(int8_t offset) { - I2Cdev::writeBits(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset); + I2Cdev::writeBits(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset, wireObj); } // YG_OFFS_TC register int8_t MPU6050_Base::getYGyroOffsetTC() { - I2Cdev::readBits(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, buffer); + I2Cdev::readBits(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } void MPU6050_Base::setYGyroOffsetTC(int8_t offset) { - I2Cdev::writeBits(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset); + I2Cdev::writeBits(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset, wireObj); } // ZG_OFFS_TC register int8_t MPU6050_Base::getZGyroOffsetTC() { - I2Cdev::readBits(devAddr, MPU6050_RA_ZG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, buffer); + I2Cdev::readBits(devAddr, MPU6050_RA_ZG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } void MPU6050_Base::setZGyroOffsetTC(int8_t offset) { - I2Cdev::writeBits(devAddr, MPU6050_RA_ZG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset); + I2Cdev::writeBits(devAddr, MPU6050_RA_ZG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset, wireObj); } // X_FINE_GAIN register int8_t MPU6050_Base::getXFineGain() { - I2Cdev::readByte(devAddr, MPU6050_RA_X_FINE_GAIN, buffer); + I2Cdev::readByte(devAddr, MPU6050_RA_X_FINE_GAIN, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } void MPU6050_Base::setXFineGain(int8_t gain) { - I2Cdev::writeByte(devAddr, MPU6050_RA_X_FINE_GAIN, gain); + I2Cdev::writeByte(devAddr, MPU6050_RA_X_FINE_GAIN, gain, wireObj); } // Y_FINE_GAIN register int8_t MPU6050_Base::getYFineGain() { - I2Cdev::readByte(devAddr, MPU6050_RA_Y_FINE_GAIN, buffer); + I2Cdev::readByte(devAddr, MPU6050_RA_Y_FINE_GAIN, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } void MPU6050_Base::setYFineGain(int8_t gain) { - I2Cdev::writeByte(devAddr, MPU6050_RA_Y_FINE_GAIN, gain); + I2Cdev::writeByte(devAddr, MPU6050_RA_Y_FINE_GAIN, gain, wireObj); } // Z_FINE_GAIN register int8_t MPU6050_Base::getZFineGain() { - I2Cdev::readByte(devAddr, MPU6050_RA_Z_FINE_GAIN, buffer); + I2Cdev::readByte(devAddr, MPU6050_RA_Z_FINE_GAIN, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } void MPU6050_Base::setZFineGain(int8_t gain) { - I2Cdev::writeByte(devAddr, MPU6050_RA_Z_FINE_GAIN, gain); + I2Cdev::writeByte(devAddr, MPU6050_RA_Z_FINE_GAIN, gain, wireObj); } // XA_OFFS_* registers int16_t MPU6050_Base::getXAccelOffset() { uint8_t SaveAddress = ((getDeviceID() < 0x38 )? MPU6050_RA_XA_OFFS_H:0x77); // MPU6050,MPU9150 Vs MPU6500,MPU9250 - I2Cdev::readBytes(devAddr, SaveAddress, 2, buffer); + I2Cdev::readBytes(devAddr, SaveAddress, 2, buffer, I2Cdev::readTimeout, wireObj); return (((int16_t)buffer[0]) << 8) | buffer[1]; } void MPU6050_Base::setXAccelOffset(int16_t offset) { uint8_t SaveAddress = ((getDeviceID() < 0x38 )? MPU6050_RA_XA_OFFS_H:0x77); // MPU6050,MPU9150 Vs MPU6500,MPU9250 - I2Cdev::writeWord(devAddr, SaveAddress, offset); + I2Cdev::writeWord(devAddr, SaveAddress, offset, wireObj); } // YA_OFFS_* register int16_t MPU6050_Base::getYAccelOffset() { uint8_t SaveAddress = ((getDeviceID() < 0x38 )? MPU6050_RA_YA_OFFS_H:0x7A); // MPU6050,MPU9150 Vs MPU6500,MPU9250 - I2Cdev::readBytes(devAddr, SaveAddress, 2, buffer); + I2Cdev::readBytes(devAddr, SaveAddress, 2, buffer, I2Cdev::readTimeout, wireObj); return (((int16_t)buffer[0]) << 8) | buffer[1]; } void MPU6050_Base::setYAccelOffset(int16_t offset) { uint8_t SaveAddress = ((getDeviceID() < 0x38 )? MPU6050_RA_YA_OFFS_H:0x7A); // MPU6050,MPU9150 Vs MPU6500,MPU9250 - I2Cdev::writeWord(devAddr, SaveAddress, offset); + I2Cdev::writeWord(devAddr, SaveAddress, offset, wireObj); } // ZA_OFFS_* register int16_t MPU6050_Base::getZAccelOffset() { uint8_t SaveAddress = ((getDeviceID() < 0x38 )? MPU6050_RA_ZA_OFFS_H:0x7D); // MPU6050,MPU9150 Vs MPU6500,MPU9250 - I2Cdev::readBytes(devAddr, SaveAddress, 2, buffer); + I2Cdev::readBytes(devAddr, SaveAddress, 2, buffer, I2Cdev::readTimeout, wireObj); return (((int16_t)buffer[0]) << 8) | buffer[1]; } void MPU6050_Base::setZAccelOffset(int16_t offset) { uint8_t SaveAddress = ((getDeviceID() < 0x38 )? MPU6050_RA_ZA_OFFS_H:0x7D); // MPU6050,MPU9150 Vs MPU6500,MPU9250 - I2Cdev::writeWord(devAddr, SaveAddress, offset); + I2Cdev::writeWord(devAddr, SaveAddress, offset, wireObj); } // XG_OFFS_USR* registers int16_t MPU6050_Base::getXGyroOffset() { - I2Cdev::readBytes(devAddr, MPU6050_RA_XG_OFFS_USRH, 2, buffer); + I2Cdev::readBytes(devAddr, MPU6050_RA_XG_OFFS_USRH, 2, buffer, I2Cdev::readTimeout, wireObj); return (((int16_t)buffer[0]) << 8) | buffer[1]; } void MPU6050_Base::setXGyroOffset(int16_t offset) { - I2Cdev::writeWord(devAddr, MPU6050_RA_XG_OFFS_USRH, offset); + I2Cdev::writeWord(devAddr, MPU6050_RA_XG_OFFS_USRH, offset, wireObj); } // YG_OFFS_USR* register int16_t MPU6050_Base::getYGyroOffset() { - I2Cdev::readBytes(devAddr, MPU6050_RA_YG_OFFS_USRH, 2, buffer); + I2Cdev::readBytes(devAddr, MPU6050_RA_YG_OFFS_USRH, 2, buffer, I2Cdev::readTimeout, wireObj); return (((int16_t)buffer[0]) << 8) | buffer[1]; } void MPU6050_Base::setYGyroOffset(int16_t offset) { - I2Cdev::writeWord(devAddr, MPU6050_RA_YG_OFFS_USRH, offset); + I2Cdev::writeWord(devAddr, MPU6050_RA_YG_OFFS_USRH, offset, wireObj); } // ZG_OFFS_USR* register int16_t MPU6050_Base::getZGyroOffset() { - I2Cdev::readBytes(devAddr, MPU6050_RA_ZG_OFFS_USRH, 2, buffer); + I2Cdev::readBytes(devAddr, MPU6050_RA_ZG_OFFS_USRH, 2, buffer, I2Cdev::readTimeout, wireObj); return (((int16_t)buffer[0]) << 8) | buffer[1]; } void MPU6050_Base::setZGyroOffset(int16_t offset) { - I2Cdev::writeWord(devAddr, MPU6050_RA_ZG_OFFS_USRH, offset); + I2Cdev::writeWord(devAddr, MPU6050_RA_ZG_OFFS_USRH, offset, wireObj); } // INT_ENABLE register (DMP functions) bool MPU6050_Base::getIntPLLReadyEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } void MPU6050_Base::setIntPLLReadyEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, enabled); + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, enabled, wireObj); } bool MPU6050_Base::getIntDMPEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DMP_INT_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DMP_INT_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } void MPU6050_Base::setIntDMPEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DMP_INT_BIT, enabled); + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DMP_INT_BIT, enabled, wireObj); } // DMP_INT_STATUS bool MPU6050_Base::getDMPInt5Status() { - I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_5_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_5_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } bool MPU6050_Base::getDMPInt4Status() { - I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_4_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_4_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } bool MPU6050_Base::getDMPInt3Status() { - I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_3_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_3_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } bool MPU6050_Base::getDMPInt2Status() { - I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_2_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_2_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } bool MPU6050_Base::getDMPInt1Status() { - I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_1_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_1_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } bool MPU6050_Base::getDMPInt0Status() { - I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_0_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_0_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } // INT_STATUS register (DMP functions) bool MPU6050_Base::getIntPLLReadyStatus() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } bool MPU6050_Base::getIntDMPStatus() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_DMP_INT_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_DMP_INT_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } // USER_CTRL register (DMP functions) bool MPU6050_Base::getDMPEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_EN_BIT, buffer); + I2Cdev::readBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } void MPU6050_Base::setDMPEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_EN_BIT, enabled); + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_EN_BIT, enabled, wireObj); } void MPU6050_Base::resetDMP() { - I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_RESET_BIT, true); + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_RESET_BIT, true, wireObj); } // BANK_SEL register @@ -3047,23 +3047,23 @@ void MPU6050_Base::setMemoryBank(uint8_t bank, bool prefetchEnabled, bool userBa bank &= 0x1F; if (userBank) bank |= 0x20; if (prefetchEnabled) bank |= 0x40; - I2Cdev::writeByte(devAddr, MPU6050_RA_BANK_SEL, bank); + I2Cdev::writeByte(devAddr, MPU6050_RA_BANK_SEL, bank, wireObj); } // MEM_START_ADDR register void MPU6050_Base::setMemoryStartAddress(uint8_t address) { - I2Cdev::writeByte(devAddr, MPU6050_RA_MEM_START_ADDR, address); + I2Cdev::writeByte(devAddr, MPU6050_RA_MEM_START_ADDR, address, wireObj); } // MEM_R_W register uint8_t MPU6050_Base::readMemoryByte() { - I2Cdev::readByte(devAddr, MPU6050_RA_MEM_R_W, buffer); + I2Cdev::readByte(devAddr, MPU6050_RA_MEM_R_W, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } void MPU6050_Base::writeMemoryByte(uint8_t data) { - I2Cdev::writeByte(devAddr, MPU6050_RA_MEM_R_W, data); + I2Cdev::writeByte(devAddr, MPU6050_RA_MEM_R_W, data, wireObj); } void MPU6050_Base::readMemoryBlock(uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address) { setMemoryBank(bank); @@ -3080,7 +3080,7 @@ void MPU6050_Base::readMemoryBlock(uint8_t *data, uint16_t dataSize, uint8_t ban if (chunkSize > 256 - address) chunkSize = 256 - address; // read the chunk of data as specified - I2Cdev::readBytes(devAddr, MPU6050_RA_MEM_R_W, chunkSize, data + i); + I2Cdev::readBytes(devAddr, MPU6050_RA_MEM_R_W, chunkSize, data + i, I2Cdev::readTimeout, wireObj); // increase byte index by [chunkSize] i += chunkSize; @@ -3124,13 +3124,13 @@ bool MPU6050_Base::writeMemoryBlock(const uint8_t *data, uint16_t dataSize, uint progBuffer = (uint8_t *)data + i; } - I2Cdev::writeBytes(devAddr, MPU6050_RA_MEM_R_W, chunkSize, progBuffer); + I2Cdev::writeBytes(devAddr, MPU6050_RA_MEM_R_W, chunkSize, progBuffer, wireObj); // verify data if needed if (verify && verifyBuffer) { setMemoryBank(bank); setMemoryStartAddress(address); - I2Cdev::readBytes(devAddr, MPU6050_RA_MEM_R_W, chunkSize, verifyBuffer); + I2Cdev::readBytes(devAddr, MPU6050_RA_MEM_R_W, chunkSize, verifyBuffer, I2Cdev::readTimeout, wireObj); if (memcmp(progBuffer, verifyBuffer, chunkSize) != 0) { /*Serial.print("Block write verification error, bank "); Serial.print(bank, DEC); @@ -3234,7 +3234,7 @@ bool MPU6050_Base::writeDMPConfigurationSet(const uint8_t *data, uint16_t dataSi //setIntZeroMotionEnabled(true); //setIntFIFOBufferOverflowEnabled(true); //setIntDMPEnabled(true); - I2Cdev::writeByte(devAddr, MPU6050_RA_INT_ENABLE, 0x32); // single operation + I2Cdev::writeByte(devAddr, MPU6050_RA_INT_ENABLE, 0x32, wireObj); // single operation success = true; } else { @@ -3258,21 +3258,21 @@ bool MPU6050_Base::writeProgDMPConfigurationSet(const uint8_t *data, uint16_t da // DMP_CFG_1 register uint8_t MPU6050_Base::getDMPConfig1() { - I2Cdev::readByte(devAddr, MPU6050_RA_DMP_CFG_1, buffer); + I2Cdev::readByte(devAddr, MPU6050_RA_DMP_CFG_1, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } void MPU6050_Base::setDMPConfig1(uint8_t config) { - I2Cdev::writeByte(devAddr, MPU6050_RA_DMP_CFG_1, config); + I2Cdev::writeByte(devAddr, MPU6050_RA_DMP_CFG_1, config, wireObj); } // DMP_CFG_2 register uint8_t MPU6050_Base::getDMPConfig2() { - I2Cdev::readByte(devAddr, MPU6050_RA_DMP_CFG_2, buffer); + I2Cdev::readByte(devAddr, MPU6050_RA_DMP_CFG_2, buffer, I2Cdev::readTimeout, wireObj); return buffer[0]; } void MPU6050_Base::setDMPConfig2(uint8_t config) { - I2Cdev::writeByte(devAddr, MPU6050_RA_DMP_CFG_2, config); + I2Cdev::writeByte(devAddr, MPU6050_RA_DMP_CFG_2, config, wireObj); } @@ -3321,7 +3321,7 @@ void MPU6050_Base::PID(uint8_t ReadAddress, float kP,float kI, uint8_t Loops){ if (ReadAddress == 0x3B) gravity = 16384 >> getFullScaleAccelRange(); Serial.write('>'); for (int i = 0; i < 3; i++) { - I2Cdev::readWords(devAddr, SaveAddress + (i * shift), 1, (uint16_t *)&Data); // reads 1 or more 16 bit integers (Word) + I2Cdev::readWords(devAddr, SaveAddress + (i * shift), 1, (uint16_t *)&Data, I2Cdev::readTimeout, wireObj); // reads 1 or more 16 bit integers (Word) Reading = Data; if(SaveAddress != 0x13){ BitZero[i] = Data & 1; // Capture Bit Zero to properly handle Accelerometer calibration @@ -3335,7 +3335,7 @@ void MPU6050_Base::PID(uint8_t ReadAddress, float kP,float kI, uint8_t Loops){ for (int c = 0; c < 100; c++) {// 100 PI Calculations eSum = 0; for (int i = 0; i < 3; i++) { - I2Cdev::readWords(devAddr, ReadAddress + (i * 2), 1, (uint16_t *)&Data); // reads 1 or more 16 bit integers (Word) + I2Cdev::readWords(devAddr, ReadAddress + (i * 2), 1, (uint16_t *)&Data, I2Cdev::readTimeout, wireObj); // reads 1 or more 16 bit integers (Word) Reading = Data; if ((ReadAddress == 0x3B)&&(i == 2)) Reading -= gravity; //remove Gravity Error = -Reading; @@ -3346,7 +3346,7 @@ void MPU6050_Base::PID(uint8_t ReadAddress, float kP,float kI, uint8_t Loops){ Data = round((PTerm + ITerm[i] ) / 8); //Compute PID Output Data = ((Data)&0xFFFE) |BitZero[i]; // Insert Bit0 Saved at beginning } else Data = round((PTerm + ITerm[i] ) / 4); //Compute PID Output - I2Cdev::writeWords(devAddr, SaveAddress + (i * shift), 1, (uint16_t *)&Data); + I2Cdev::writeWords(devAddr, SaveAddress + (i * shift), 1, (uint16_t *)&Data, wireObj); } if((c == 99) && eSum > 1000){ // Error is still to great to continue c = 0; @@ -3364,7 +3364,7 @@ void MPU6050_Base::PID(uint8_t ReadAddress, float kP,float kI, uint8_t Loops){ Data = round((ITerm[i] ) / 8); //Compute PID Output Data = ((Data)&0xFFFE) |BitZero[i]; // Insert Bit0 Saved at beginning } else Data = round((ITerm[i]) / 4); - I2Cdev::writeWords(devAddr, SaveAddress + (i * shift), 1, (uint16_t *)&Data); + I2Cdev::writeWords(devAddr, SaveAddress + (i * shift), 1, (uint16_t *)&Data, wireObj); } } resetFIFO(); @@ -3377,17 +3377,17 @@ void MPU6050_Base::PrintActiveOffsets() { //Serial.print(F("Offset Register 0x")); //Serial.print(AOffsetRegister>>4,HEX);Serial.print(AOffsetRegister&0x0F,HEX); Serial.print(F("\n// X Accel Y Accel Z Accel X Gyro Y Gyro Z Gyro\n// OFFSETS ")); - if(AOffsetRegister == 0x06) I2Cdev::readWords(devAddr, AOffsetRegister, 3, (uint16_t *)Data); + if(AOffsetRegister == 0x06) I2Cdev::readWords(devAddr, AOffsetRegister, 3, (uint16_t *)Data, I2Cdev::readTimeout, wireObj); else { - I2Cdev::readWords(devAddr, AOffsetRegister, 1, (uint16_t *)Data); - I2Cdev::readWords(devAddr, AOffsetRegister+3, 1, (uint16_t *)Data+1); - I2Cdev::readWords(devAddr, AOffsetRegister+6, 1, (uint16_t *)Data+2); + I2Cdev::readWords(devAddr, AOffsetRegister, 1, (uint16_t *)Data, I2Cdev::readTimeout, wireObj); + I2Cdev::readWords(devAddr, AOffsetRegister+3, 1, (uint16_t *)Data+1, I2Cdev::readTimeout, wireObj); + I2Cdev::readWords(devAddr, AOffsetRegister+6, 1, (uint16_t *)Data+2, I2Cdev::readTimeout, wireObj); } // A_OFFSET_H_READ_A_OFFS(Data); Serial.print((float)Data[0], 5); Serial.print(", "); Serial.print((float)Data[1], 5); Serial.print(", "); Serial.print((float)Data[2], 5); Serial.print(", "); - I2Cdev::readWords(devAddr, 0x13, 3, (uint16_t *)Data); + I2Cdev::readWords(devAddr, 0x13, 3, (uint16_t *)Data, I2Cdev::readTimeout, wireObj); // XG_OFFSET_H_READ_OFFS_USR(Data); Serial.print((float)Data[0], 5); Serial.print(", "); Serial.print((float)Data[1], 5); Serial.print(", "); diff --git a/Arduino/MPU6050/MPU6050.h b/Arduino/MPU6050/MPU6050.h index d44ee38c..888d4db9 100644 --- a/Arduino/MPU6050/MPU6050.h +++ b/Arduino/MPU6050/MPU6050.h @@ -439,7 +439,7 @@ THE SOFTWARE. class MPU6050_Base { public: - MPU6050_Base(uint8_t address=MPU6050_DEFAULT_ADDRESS); + MPU6050_Base(uint8_t address=MPU6050_DEFAULT_ADDRESS, void *wireObj=0); void initialize(); bool testConnection(); @@ -835,6 +835,7 @@ class MPU6050_Base { protected: uint8_t devAddr; + void *wireObj; uint8_t buffer[14]; uint32_t fifoTimeout = MPU6050_FIFO_DEFAULT_TIMEOUT; }; diff --git a/Arduino/MPU6050/MPU6050_6Axis_MotionApps612.cpp b/Arduino/MPU6050/MPU6050_6Axis_MotionApps612.cpp index fa91c7a9..3fb53e4d 100644 --- a/Arduino/MPU6050/MPU6050_6Axis_MotionApps612.cpp +++ b/Arduino/MPU6050/MPU6050_6Axis_MotionApps612.cpp @@ -350,24 +350,24 @@ uint8_t MPU6050::dmpInitialize() { // Lets get it over with fast Write everythin uint8_t val; uint16_t ival; // Reset procedure per instructions in the "MPU-6000/MPU-6050 Register Map and Descriptions" page 41 - I2Cdev::writeBit(devAddr,0x6B, 7, (val = 1)); //PWR_MGMT_1: reset with 100ms delay + I2Cdev::writeBit(devAddr,0x6B, 7, (val = 1), wireObj); //PWR_MGMT_1: reset with 100ms delay delay(100); - I2Cdev::writeBits(devAddr,0x6A, 2, 3, (val = 0b111)); // full SIGNAL_PATH_RESET: with another 100ms delay + I2Cdev::writeBits(devAddr,0x6A, 2, 3, (val = 0b111), wireObj); // full SIGNAL_PATH_RESET: with another 100ms delay delay(100); - I2Cdev::writeBytes(devAddr,0x6B, 1, &(val = 0x01)); // 1000 0001 PWR_MGMT_1:Clock Source Select PLL_X_gyro - I2Cdev::writeBytes(devAddr,0x38, 1, &(val = 0x00)); // 0000 0000 INT_ENABLE: no Interrupt - I2Cdev::writeBytes(devAddr,0x23, 1, &(val = 0x00)); // 0000 0000 MPU FIFO_EN: (all off) Using DMP's FIFO instead - I2Cdev::writeBytes(devAddr,0x1C, 1, &(val = 0x00)); // 0000 0000 ACCEL_CONFIG: 0 = Accel Full Scale Select: 2g - I2Cdev::writeBytes(devAddr,0x37, 1, &(val = 0x80)); // 1001 0000 INT_PIN_CFG: ACTL The logic level for int pin is active low. and interrupt status bits are cleared on any read - I2Cdev::writeBytes(devAddr,0x6B, 1, &(val = 0x01)); // 0000 0001 PWR_MGMT_1: Clock Source Select PLL_X_gyro - I2Cdev::writeBytes(devAddr,0x19, 1, &(val = 0x04)); // 0000 0100 SMPLRT_DIV: Divides the internal sample rate 400Hz ( Sample Rate = Gyroscope Output Rate / (1 + SMPLRT_DIV)) - I2Cdev::writeBytes(devAddr,0x1A, 1, &(val = 0x01)); // 0000 0001 CONFIG: Digital Low Pass Filter (DLPF) Configuration 188HZ //Im betting this will be the beat + I2Cdev::writeBytes(devAddr,0x6B, 1, &(val = 0x01), wireObj); // 1000 0001 PWR_MGMT_1:Clock Source Select PLL_X_gyro + I2Cdev::writeBytes(devAddr,0x38, 1, &(val = 0x00), wireObj); // 0000 0000 INT_ENABLE: no Interrupt + I2Cdev::writeBytes(devAddr,0x23, 1, &(val = 0x00), wireObj); // 0000 0000 MPU FIFO_EN: (all off) Using DMP's FIFO instead + I2Cdev::writeBytes(devAddr,0x1C, 1, &(val = 0x00), wireObj); // 0000 0000 ACCEL_CONFIG: 0 = Accel Full Scale Select: 2g + I2Cdev::writeBytes(devAddr,0x37, 1, &(val = 0x80), wireObj); // 1001 0000 INT_PIN_CFG: ACTL The logic level for int pin is active low. and interrupt status bits are cleared on any read + I2Cdev::writeBytes(devAddr,0x6B, 1, &(val = 0x01), wireObj); // 0000 0001 PWR_MGMT_1: Clock Source Select PLL_X_gyro + I2Cdev::writeBytes(devAddr,0x19, 1, &(val = 0x04), wireObj); // 0000 0100 SMPLRT_DIV: Divides the internal sample rate 400Hz ( Sample Rate = Gyroscope Output Rate / (1 + SMPLRT_DIV)) + I2Cdev::writeBytes(devAddr,0x1A, 1, &(val = 0x01), wireObj); // 0000 0001 CONFIG: Digital Low Pass Filter (DLPF) Configuration 188HZ //Im betting this will be the beat if (!writeProgMemoryBlock(dmpMemory, MPU6050_DMP_CODE_SIZE)) return 1; // Loads the DMP image into the MPU6050 Memory // Should Never Fail - I2Cdev::writeWords(devAddr, 0x70, 1, &(ival = 0x0400)); // DMP Program Start Address - I2Cdev::writeBytes(devAddr,0x1B, 1, &(val = 0x18)); // 0001 1000 GYRO_CONFIG: 3 = +2000 Deg/sec - I2Cdev::writeBytes(devAddr,0x6A, 1, &(val = 0xC0)); // 1100 1100 USER_CTRL: Enable Fifo and Reset Fifo - I2Cdev::writeBytes(devAddr,0x38, 1, &(val = 0x02)); // 0000 0010 INT_ENABLE: RAW_DMP_INT_EN on - I2Cdev::writeBit(devAddr,0x6A, 2, 1); // Reset FIFO one last time just for kicks. (MPUi2cWrite reads 0x6A first and only alters 1 bit and then saves the byte) + I2Cdev::writeWords(devAddr, 0x70, 1, &(ival = 0x0400), wireObj); // DMP Program Start Address + I2Cdev::writeBytes(devAddr,0x1B, 1, &(val = 0x18), wireObj); // 0001 1000 GYRO_CONFIG: 3 = +2000 Deg/sec + I2Cdev::writeBytes(devAddr,0x6A, 1, &(val = 0xC0), wireObj); // 1100 1100 USER_CTRL: Enable Fifo and Reset Fifo + I2Cdev::writeBytes(devAddr,0x38, 1, &(val = 0x02), wireObj); // 0000 0010 INT_ENABLE: RAW_DMP_INT_EN on + I2Cdev::writeBit(devAddr,0x6A, 2, 1, wireObj); // Reset FIFO one last time just for kicks. (MPUi2cWrite reads 0x6A first and only alters 1 bit and then saves the byte) setDMPEnabled(false); // disable DMP for compatibility with the MPU6050 library /* diff --git a/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.cpp b/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.cpp index 2a11fe55..d85d74a5 100644 --- a/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.cpp +++ b/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.cpp @@ -382,10 +382,10 @@ uint8_t MPU6050_9Axis_MotionApps41::dmpInitialize() { DEBUG_PRINT(F("Z gyro offset = ")); DEBUG_PRINTLN(zgOffset); - I2Cdev::readByte(devAddr, MPU6050_RA_USER_CTRL, buffer); // ? + I2Cdev::readByte(devAddr, MPU6050_RA_USER_CTRL, buffer, I2Cdev::readTimeout, wireObj); // ? DEBUG_PRINTLN(F("Enabling interrupt latch, clear on any read, AUX bypass enabled")); - I2Cdev::writeByte(devAddr, MPU6050_RA_INT_PIN_CFG, 0x32); + I2Cdev::writeByte(devAddr, MPU6050_RA_INT_PIN_CFG, 0x32, wireObj); // enable MPU AUX I2C bypass mode //DEBUG_PRINTLN(F("Enabling AUX I2C bypass mode...")); @@ -393,16 +393,16 @@ uint8_t MPU6050_9Axis_MotionApps41::dmpInitialize() { DEBUG_PRINTLN(F("Setting magnetometer mode to power-down...")); //mag -> setMode(0); - I2Cdev::writeByte(0x0E, 0x0A, 0x00); + I2Cdev::writeByte(0x0E, 0x0A, 0x00, wireObj); DEBUG_PRINTLN(F("Setting magnetometer mode to fuse access...")); //mag -> setMode(0x0F); - I2Cdev::writeByte(0x0E, 0x0A, 0x0F); + I2Cdev::writeByte(0x0E, 0x0A, 0x0F, wireObj); DEBUG_PRINTLN(F("Reading mag magnetometer factory calibration...")); int8_t asax, asay, asaz; //mag -> getAdjustment(&asax, &asay, &asaz); - I2Cdev::readBytes(0x0E, 0x10, 3, buffer); + I2Cdev::readBytes(0x0E, 0x10, 3, buffer, I2Cdev::readTimeout, wireObj); asax = (int8_t)buffer[0]; asay = (int8_t)buffer[1]; asaz = (int8_t)buffer[2]; @@ -418,7 +418,7 @@ uint8_t MPU6050_9Axis_MotionApps41::dmpInitialize() { DEBUG_PRINTLN(F("Setting magnetometer mode to power-down...")); //mag -> setMode(0); - I2Cdev::writeByte(0x0E, 0x0A, 0x00); + I2Cdev::writeByte(0x0E, 0x0A, 0x00, wireObj); // load DMP code into memory banks DEBUG_PRINT(F("Writing DMP code to MPU memory banks (")); @@ -501,10 +501,10 @@ uint8_t MPU6050_9Axis_MotionApps41::dmpInitialize() { writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); DEBUG_PRINTLN(F("Disabling all standby flags...")); - I2Cdev::writeByte(0x68, MPU6050_RA_PWR_MGMT_2, 0x00); + I2Cdev::writeByte(0x68, MPU6050_RA_PWR_MGMT_2, 0x00, wireObj); DEBUG_PRINTLN(F("Setting accelerometer sensitivity to +/- 2g...")); - I2Cdev::writeByte(0x68, MPU6050_RA_ACCEL_CONFIG, 0x00); + I2Cdev::writeByte(0x68, MPU6050_RA_ACCEL_CONFIG, 0x00, wireObj); DEBUG_PRINTLN(F("Setting motion detection threshold to 2...")); setMotionDetectionThreshold(2); @@ -520,39 +520,39 @@ uint8_t MPU6050_9Axis_MotionApps41::dmpInitialize() { DEBUG_PRINTLN(F("Setting AK8975 to single measurement mode...")); //mag -> setMode(1); - I2Cdev::writeByte(0x0E, 0x0A, 0x01); + I2Cdev::writeByte(0x0E, 0x0A, 0x01, wireObj); // setup AK8975 (0x0E) as Slave 0 in read mode DEBUG_PRINTLN(F("Setting up AK8975 read slave 0...")); - I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV0_ADDR, 0x8E); - I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV0_REG, 0x01); - I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV0_CTRL, 0xDA); + I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV0_ADDR, 0x8E, wireObj); + I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV0_REG, 0x01, wireObj); + I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV0_CTRL, 0xDA, wireObj); // setup AK8975 (0x0E) as Slave 2 in write mode DEBUG_PRINTLN(F("Setting up AK8975 write slave 2...")); - I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV2_ADDR, 0x0E); - I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV2_REG, 0x0A); - I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV2_CTRL, 0x81); - I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV2_DO, 0x01); + I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV2_ADDR, 0x0E, wireObj); + I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV2_REG, 0x0A, wireObj); + I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV2_CTRL, 0x81, wireObj); + I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV2_DO, 0x01, wireObj); // setup I2C timing/delay control DEBUG_PRINTLN(F("Setting up slave access delay...")); - I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV4_CTRL, 0x18); - I2Cdev::writeByte(0x68, MPU6050_RA_I2C_MST_DELAY_CTRL, 0x05); + I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV4_CTRL, 0x18, wireObj); + I2Cdev::writeByte(0x68, MPU6050_RA_I2C_MST_DELAY_CTRL, 0x05, wireObj); // enable interrupts DEBUG_PRINTLN(F("Enabling default interrupt behavior/no bypass...")); - I2Cdev::writeByte(0x68, MPU6050_RA_INT_PIN_CFG, 0x00); + I2Cdev::writeByte(0x68, MPU6050_RA_INT_PIN_CFG, 0x00, wireObj); // enable I2C master mode and reset DMP/FIFO DEBUG_PRINTLN(F("Enabling I2C master mode...")); - I2Cdev::writeByte(0x68, MPU6050_RA_USER_CTRL, 0x20); + I2Cdev::writeByte(0x68, MPU6050_RA_USER_CTRL, 0x20, wireObj); DEBUG_PRINTLN(F("Resetting FIFO...")); - I2Cdev::writeByte(0x68, MPU6050_RA_USER_CTRL, 0x24); + I2Cdev::writeByte(0x68, MPU6050_RA_USER_CTRL, 0x24, wireObj); DEBUG_PRINTLN(F("Rewriting I2C master mode enabled because...I don't know")); - I2Cdev::writeByte(0x68, MPU6050_RA_USER_CTRL, 0x20); + I2Cdev::writeByte(0x68, MPU6050_RA_USER_CTRL, 0x20, wireObj); DEBUG_PRINTLN(F("Enabling and resetting DMP/FIFO...")); - I2Cdev::writeByte(0x68, MPU6050_RA_USER_CTRL, 0xE8); + I2Cdev::writeByte(0x68, MPU6050_RA_USER_CTRL, 0xE8, wireObj); DEBUG_PRINTLN(F("Writing final memory update 5/19 (function unknown)...")); for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); diff --git a/Arduino/MPU6050/examples/MPU6050_raw/MPU6050_raw.ino b/Arduino/MPU6050/examples/MPU6050_raw/MPU6050_raw.ino index 3e2d2a70..596f0750 100644 --- a/Arduino/MPU6050/examples/MPU6050_raw/MPU6050_raw.ino +++ b/Arduino/MPU6050/examples/MPU6050_raw/MPU6050_raw.ino @@ -48,6 +48,7 @@ THE SOFTWARE. // AD0 high = 0x69 MPU6050 accelgyro; //MPU6050 accelgyro(0x69); // <-- use for AD0 high +//MPU6050 accelgyro(0x68, &Wire1); // <-- use for AD0 low, but 2nd Wire (TWI/I2C) object int16_t ax, ay, az; int16_t gx, gy, gz; From 9cf0bd3af138057e3c9a24c8f5bc00fe41c9eed7 Mon Sep 17 00:00:00 2001 From: Jeff Rowberg Date: Wed, 29 Sep 2021 13:37:22 -0400 Subject: [PATCH 281/335] Fix DMP-specific class constructors for proper init --- Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h | 2 ++ Arduino/MPU6050/MPU6050_6Axis_MotionApps612.h | 2 ++ Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h | 2 ++ 3 files changed, 6 insertions(+) diff --git a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h index d5552898..dfe7c8e9 100644 --- a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h +++ b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h @@ -45,6 +45,8 @@ THE SOFTWARE. class MPU6050_6Axis_MotionApps20 : public MPU6050_Base { public: + MPU6050_6Axis_MotionApps20(uint8_t address=MPU6050_DEFAULT_ADDRESS, void *wireObj=0) : MPU6050_Base(address, wireObj) { } + uint8_t dmpInitialize(); bool dmpPacketAvailable(); diff --git a/Arduino/MPU6050/MPU6050_6Axis_MotionApps612.h b/Arduino/MPU6050/MPU6050_6Axis_MotionApps612.h index 74cdae44..87be1b29 100644 --- a/Arduino/MPU6050/MPU6050_6Axis_MotionApps612.h +++ b/Arduino/MPU6050/MPU6050_6Axis_MotionApps612.h @@ -45,6 +45,8 @@ THE SOFTWARE. class MPU6050_6Axis_MotionApps612 : public MPU6050_Base { public: + MPU6050_6Axis_MotionApps612(uint8_t address=MPU6050_DEFAULT_ADDRESS, void *wireObj=0) : MPU6050_Base(address, wireObj) { } + uint8_t dmpInitialize(); bool dmpPacketAvailable(); diff --git a/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h b/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h index 7668d4c4..bd7aab90 100644 --- a/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h +++ b/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h @@ -45,6 +45,8 @@ THE SOFTWARE. class MPU6050_9Axis_MotionApps41 : public MPU6050_Base { public: + MPU6050_9Axis_MotionApps41(uint8_t address=MPU6050_DEFAULT_ADDRESS, void *wireObj=0) : MPU6050_Base(address, wireObj) { } + uint8_t dmpInitialize(); bool dmpPacketAvailable(); From 1d2d440050f6726978fdb8cbff6f8da4cddacf74 Mon Sep 17 00:00:00 2001 From: Jeff Rowberg Date: Wed, 29 Sep 2021 14:02:09 -0400 Subject: [PATCH 282/335] Correct tabs to spaces because I'm that picky --- Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h | 2 +- Arduino/MPU6050/MPU6050_6Axis_MotionApps612.h | 2 +- Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h index dfe7c8e9..0dc9379e 100644 --- a/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h +++ b/Arduino/MPU6050/MPU6050_6Axis_MotionApps20.h @@ -45,7 +45,7 @@ THE SOFTWARE. class MPU6050_6Axis_MotionApps20 : public MPU6050_Base { public: - MPU6050_6Axis_MotionApps20(uint8_t address=MPU6050_DEFAULT_ADDRESS, void *wireObj=0) : MPU6050_Base(address, wireObj) { } + MPU6050_6Axis_MotionApps20(uint8_t address=MPU6050_DEFAULT_ADDRESS, void *wireObj=0) : MPU6050_Base(address, wireObj) { } uint8_t dmpInitialize(); bool dmpPacketAvailable(); diff --git a/Arduino/MPU6050/MPU6050_6Axis_MotionApps612.h b/Arduino/MPU6050/MPU6050_6Axis_MotionApps612.h index 87be1b29..56e3bb35 100644 --- a/Arduino/MPU6050/MPU6050_6Axis_MotionApps612.h +++ b/Arduino/MPU6050/MPU6050_6Axis_MotionApps612.h @@ -45,7 +45,7 @@ THE SOFTWARE. class MPU6050_6Axis_MotionApps612 : public MPU6050_Base { public: - MPU6050_6Axis_MotionApps612(uint8_t address=MPU6050_DEFAULT_ADDRESS, void *wireObj=0) : MPU6050_Base(address, wireObj) { } + MPU6050_6Axis_MotionApps612(uint8_t address=MPU6050_DEFAULT_ADDRESS, void *wireObj=0) : MPU6050_Base(address, wireObj) { } uint8_t dmpInitialize(); bool dmpPacketAvailable(); diff --git a/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h b/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h index bd7aab90..6d3576e9 100644 --- a/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h +++ b/Arduino/MPU6050/MPU6050_9Axis_MotionApps41.h @@ -45,7 +45,7 @@ THE SOFTWARE. class MPU6050_9Axis_MotionApps41 : public MPU6050_Base { public: - MPU6050_9Axis_MotionApps41(uint8_t address=MPU6050_DEFAULT_ADDRESS, void *wireObj=0) : MPU6050_Base(address, wireObj) { } + MPU6050_9Axis_MotionApps41(uint8_t address=MPU6050_DEFAULT_ADDRESS, void *wireObj=0) : MPU6050_Base(address, wireObj) { } uint8_t dmpInitialize(); bool dmpPacketAvailable(); From b85f0c17df1571386ac0095377a216cc02830719 Mon Sep 17 00:00:00 2001 From: Jeff Rowberg Date: Wed, 29 Sep 2021 14:55:03 -0400 Subject: [PATCH 283/335] Rename STM32 temporarily for merging ancient PR --- README => README.old | 0 {STM32 => STM32MDK}/HMC5883/HMC5883L.c | 0 {STM32 => STM32MDK}/HMC5883/HMC5883L.h | 0 {STM32 => STM32MDK}/I2Cdev.c | 0 {STM32 => STM32MDK}/I2Cdev.h | 0 {STM32 => STM32MDK}/MPU6050/MPU6050.c | 0 {STM32 => STM32MDK}/MPU6050/MPU6050.h | 0 {STM32 => STM32MDK}/README.md | 0 8 files changed, 0 insertions(+), 0 deletions(-) rename README => README.old (100%) rename {STM32 => STM32MDK}/HMC5883/HMC5883L.c (100%) rename {STM32 => STM32MDK}/HMC5883/HMC5883L.h (100%) rename {STM32 => STM32MDK}/I2Cdev.c (100%) rename {STM32 => STM32MDK}/I2Cdev.h (100%) rename {STM32 => STM32MDK}/MPU6050/MPU6050.c (100%) rename {STM32 => STM32MDK}/MPU6050/MPU6050.h (100%) rename {STM32 => STM32MDK}/README.md (100%) diff --git a/README b/README.old similarity index 100% rename from README rename to README.old diff --git a/STM32/HMC5883/HMC5883L.c b/STM32MDK/HMC5883/HMC5883L.c similarity index 100% rename from STM32/HMC5883/HMC5883L.c rename to STM32MDK/HMC5883/HMC5883L.c diff --git a/STM32/HMC5883/HMC5883L.h b/STM32MDK/HMC5883/HMC5883L.h similarity index 100% rename from STM32/HMC5883/HMC5883L.h rename to STM32MDK/HMC5883/HMC5883L.h diff --git a/STM32/I2Cdev.c b/STM32MDK/I2Cdev.c similarity index 100% rename from STM32/I2Cdev.c rename to STM32MDK/I2Cdev.c diff --git a/STM32/I2Cdev.h b/STM32MDK/I2Cdev.h similarity index 100% rename from STM32/I2Cdev.h rename to STM32MDK/I2Cdev.h diff --git a/STM32/MPU6050/MPU6050.c b/STM32MDK/MPU6050/MPU6050.c similarity index 100% rename from STM32/MPU6050/MPU6050.c rename to STM32MDK/MPU6050/MPU6050.c diff --git a/STM32/MPU6050/MPU6050.h b/STM32MDK/MPU6050/MPU6050.h similarity index 100% rename from STM32/MPU6050/MPU6050.h rename to STM32MDK/MPU6050/MPU6050.h diff --git a/STM32/README.md b/STM32MDK/README.md similarity index 100% rename from STM32/README.md rename to STM32MDK/README.md From 58f9de378e542ddabf6fdade26c2a4e06f60c1bc Mon Sep 17 00:00:00 2001 From: Jeff Rowberg Date: Wed, 29 Sep 2021 15:00:11 -0400 Subject: [PATCH 284/335] Rename new STM32 to STM32HAL --- README.md | 5 ----- {STM32 => STM32HAL}/APDS9960/APDS9960.c | 0 {STM32 => STM32HAL}/APDS9960/APDS9960.h | 0 {STM32 => STM32HAL}/APDS9960/README.md | 0 {STM32 => STM32HAL}/BMP085/BMP085.c | 0 {STM32 => STM32HAL}/BMP085/BMP085.h | 0 {STM32 => STM32HAL}/HMC5883L/HMC5883L.c | 0 {STM32 => STM32HAL}/HMC5883L/HMC5883L.h | 0 {STM32 => STM32HAL}/I2Cdev/I2Cdev.c | 0 {STM32 => STM32HAL}/I2Cdev/I2Cdev.h | 0 {STM32 => STM32HAL}/MPU6050/MPU6050.c | 0 {STM32 => STM32HAL}/MPU6050/MPU6050.h | 0 {STM32 => STM32HAL}/README.md | 0 13 files changed, 5 deletions(-) delete mode 100644 README.md rename {STM32 => STM32HAL}/APDS9960/APDS9960.c (100%) rename {STM32 => STM32HAL}/APDS9960/APDS9960.h (100%) rename {STM32 => STM32HAL}/APDS9960/README.md (100%) rename {STM32 => STM32HAL}/BMP085/BMP085.c (100%) rename {STM32 => STM32HAL}/BMP085/BMP085.h (100%) rename {STM32 => STM32HAL}/HMC5883L/HMC5883L.c (100%) rename {STM32 => STM32HAL}/HMC5883L/HMC5883L.h (100%) rename {STM32 => STM32HAL}/I2Cdev/I2Cdev.c (100%) rename {STM32 => STM32HAL}/I2Cdev/I2Cdev.h (100%) rename {STM32 => STM32HAL}/MPU6050/MPU6050.c (100%) rename {STM32 => STM32HAL}/MPU6050/MPU6050.h (100%) rename {STM32 => STM32HAL}/README.md (100%) diff --git a/README.md b/README.md deleted file mode 100644 index 50fbb01e..00000000 --- a/README.md +++ /dev/null @@ -1,5 +0,0 @@ -#i2cdevlib ported to STM32 HAL - -See details inside STM32/ - -_Note: for details about this project, please visit: http://www.i2cdevlib.com_ diff --git a/STM32/APDS9960/APDS9960.c b/STM32HAL/APDS9960/APDS9960.c similarity index 100% rename from STM32/APDS9960/APDS9960.c rename to STM32HAL/APDS9960/APDS9960.c diff --git a/STM32/APDS9960/APDS9960.h b/STM32HAL/APDS9960/APDS9960.h similarity index 100% rename from STM32/APDS9960/APDS9960.h rename to STM32HAL/APDS9960/APDS9960.h diff --git a/STM32/APDS9960/README.md b/STM32HAL/APDS9960/README.md similarity index 100% rename from STM32/APDS9960/README.md rename to STM32HAL/APDS9960/README.md diff --git a/STM32/BMP085/BMP085.c b/STM32HAL/BMP085/BMP085.c similarity index 100% rename from STM32/BMP085/BMP085.c rename to STM32HAL/BMP085/BMP085.c diff --git a/STM32/BMP085/BMP085.h b/STM32HAL/BMP085/BMP085.h similarity index 100% rename from STM32/BMP085/BMP085.h rename to STM32HAL/BMP085/BMP085.h diff --git a/STM32/HMC5883L/HMC5883L.c b/STM32HAL/HMC5883L/HMC5883L.c similarity index 100% rename from STM32/HMC5883L/HMC5883L.c rename to STM32HAL/HMC5883L/HMC5883L.c diff --git a/STM32/HMC5883L/HMC5883L.h b/STM32HAL/HMC5883L/HMC5883L.h similarity index 100% rename from STM32/HMC5883L/HMC5883L.h rename to STM32HAL/HMC5883L/HMC5883L.h diff --git a/STM32/I2Cdev/I2Cdev.c b/STM32HAL/I2Cdev/I2Cdev.c similarity index 100% rename from STM32/I2Cdev/I2Cdev.c rename to STM32HAL/I2Cdev/I2Cdev.c diff --git a/STM32/I2Cdev/I2Cdev.h b/STM32HAL/I2Cdev/I2Cdev.h similarity index 100% rename from STM32/I2Cdev/I2Cdev.h rename to STM32HAL/I2Cdev/I2Cdev.h diff --git a/STM32/MPU6050/MPU6050.c b/STM32HAL/MPU6050/MPU6050.c similarity index 100% rename from STM32/MPU6050/MPU6050.c rename to STM32HAL/MPU6050/MPU6050.c diff --git a/STM32/MPU6050/MPU6050.h b/STM32HAL/MPU6050/MPU6050.h similarity index 100% rename from STM32/MPU6050/MPU6050.h rename to STM32HAL/MPU6050/MPU6050.h diff --git a/STM32/README.md b/STM32HAL/README.md similarity index 100% rename from STM32/README.md rename to STM32HAL/README.md From 978d6145ca89c79e69322aaf92a25ced6f5c2d04 Mon Sep 17 00:00:00 2001 From: Jeff Rowberg Date: Wed, 29 Sep 2021 15:00:37 -0400 Subject: [PATCH 285/335] Rename STM32MDK back to original STM32 --- {STM32MDK => STM32}/HMC5883/HMC5883L.c | 0 {STM32MDK => STM32}/HMC5883/HMC5883L.h | 0 {STM32MDK => STM32}/I2Cdev.c | 0 {STM32MDK => STM32}/I2Cdev.h | 0 {STM32MDK => STM32}/MPU6050/MPU6050.c | 0 {STM32MDK => STM32}/MPU6050/MPU6050.h | 0 {STM32MDK => STM32}/README.md | 0 7 files changed, 0 insertions(+), 0 deletions(-) rename {STM32MDK => STM32}/HMC5883/HMC5883L.c (100%) rename {STM32MDK => STM32}/HMC5883/HMC5883L.h (100%) rename {STM32MDK => STM32}/I2Cdev.c (100%) rename {STM32MDK => STM32}/I2Cdev.h (100%) rename {STM32MDK => STM32}/MPU6050/MPU6050.c (100%) rename {STM32MDK => STM32}/MPU6050/MPU6050.h (100%) rename {STM32MDK => STM32}/README.md (100%) diff --git a/STM32MDK/HMC5883/HMC5883L.c b/STM32/HMC5883/HMC5883L.c similarity index 100% rename from STM32MDK/HMC5883/HMC5883L.c rename to STM32/HMC5883/HMC5883L.c diff --git a/STM32MDK/HMC5883/HMC5883L.h b/STM32/HMC5883/HMC5883L.h similarity index 100% rename from STM32MDK/HMC5883/HMC5883L.h rename to STM32/HMC5883/HMC5883L.h diff --git a/STM32MDK/I2Cdev.c b/STM32/I2Cdev.c similarity index 100% rename from STM32MDK/I2Cdev.c rename to STM32/I2Cdev.c diff --git a/STM32MDK/I2Cdev.h b/STM32/I2Cdev.h similarity index 100% rename from STM32MDK/I2Cdev.h rename to STM32/I2Cdev.h diff --git a/STM32MDK/MPU6050/MPU6050.c b/STM32/MPU6050/MPU6050.c similarity index 100% rename from STM32MDK/MPU6050/MPU6050.c rename to STM32/MPU6050/MPU6050.c diff --git a/STM32MDK/MPU6050/MPU6050.h b/STM32/MPU6050/MPU6050.h similarity index 100% rename from STM32MDK/MPU6050/MPU6050.h rename to STM32/MPU6050/MPU6050.h diff --git a/STM32MDK/README.md b/STM32/README.md similarity index 100% rename from STM32MDK/README.md rename to STM32/README.md From 4a637cce6649106d3f6e887015ce986a0dde1893 Mon Sep 17 00:00:00 2001 From: Jeff Rowberg Date: Wed, 29 Sep 2021 15:39:07 -0400 Subject: [PATCH 286/335] Update main README documentation --- README.md | 40 ++++++++++++++++++++++++++++++++++++++++ README.old | 17 ----------------- 2 files changed, 40 insertions(+), 17 deletions(-) create mode 100644 README.md delete mode 100644 README.old diff --git a/README.md b/README.md new file mode 100644 index 00000000..f1ea8561 --- /dev/null +++ b/README.md @@ -0,0 +1,40 @@ +# I2C Device Library + +The I2C Device Library (i2cdevlib) is a collection of mostly uniform and well-documented classes to provide simple and intuitive interfaces to I2C devices. Each device is built to make use of the generic "I2Cdev" class, which abstracts the I2C bit- and byte-level communication away from each specific device class, making it easy to keep the device class clean while providing a simple way to modify just one class to port the I2C communication code onto different platforms (Arduino, PIC, MSP430, Jennic, simple bit-banging, etc.). Device classes are designed to provide complete coverage of all functionality described by each device's documentation, plus any generic convenience functions that are helpful. + +There are examples in many of the classes that demonstrate basic usage patterns. The I2Cdev class is built to be used statically, reducing the memory requirement if you have multiple I2C devices in your project. Only one instance of the I2Cdev class is required. Recent additions as of late 2021 have also made it possible to pass in non-default `Wire` objects (in the Arduino environment) to allow using multiple I2C transceivers at the same time, specifically because of the number of people who wanted to use up to four MPU-6050 IMUs without I2C mux ICs involved. + +Documentation for each class is created using Doxygen-style comments placed in each class definition file, based on the information available in each device's datasheet. This documentation is available in HTML format on the i2cdevlib.com website, which also holds helpful information for most of the classes present here on the repository. + +## Installation + +Due to my...ahem...unfortunate ignorance way back when I first created this project, the entire codebase (all platforms, cores, and device libraries) are all inside of this one giant repository. That means there's no easy IDE integration the way most libraries work in the Arduino world and elsewhere. Instead, do the following: + +1. Clone or [download a .zip archive](https://github.com/jrowberg/i2cdevlib/archive/refs/heads/master.zip) of the repo +2. Move or copy the relevant core and device drivers into your project tree or library subfolder
(For Arduino, this means the `/Arduino/I2Cdev` and `/Arduino/MPU6050` folders, for example) +3. Rescan libraries or restart your IDE if necessary + +For both usage and development, I've found that it's best to clone using the git client of your choice, and then create symlinks as needed from the master repository sources into your development location(s). This is usually more intuitive for people who use Linux, but it can be done in Windows as well using the `mklink /D` command. See [this page](https://www.howtogeek.com/howto/16226/complete-guide-to-symbolic-links-symlinks-on-windows-or-linux/) for a set of Windows-specific instructions with screenshots. + +## Usage + +Exact usage varies from device to device, but most (especially the more popular ones) include example projects demonstrating the basics. Refer to those examples for the best material currently available. + +## Contributing + +Want a library for a device that isn't up on the repository? You can either request it in the discussion area for this repo on Github, or fork the code and write it yourself. + +Realistically, Option B is more reliable. Try to mimic the structure and code conventions of the existing codebase as much as possible. If you go this route, please use the following approach: + +1. Fork the repository to your own user +2. Create a new branch specific to your new code +3. Write, test, and commit your new code +4. Submit a pull request from your branch back to the original source + +I and a few others will review the pull request and comment as needed, and then hopefully merge it. + +
+ +***Note: additional details about this project can be found at https://www.i2cdevlib.com*** + +***Another note: this project has a fledgling successor that aims to [address all of its shortcomings](https://community.perilib.io/t/perilib-i2cdevlib-reborn/15), which can be found at https://github.com/perilib*** diff --git a/README.old b/README.old deleted file mode 100644 index 41001e3e..00000000 --- a/README.old +++ /dev/null @@ -1,17 +0,0 @@ -Jennic platform added! - -============================================================================ -Note: for details about this project, please visit: http://www.i2cdevlib.com -============================================================================ - -The I2C Device Library (i2cdevlib) is a collection of uniform and well-documented classes to provide simple and intuitive interfaces to I2C devices. Each device is built to make use of the generic "I2Cdev" class, which abstracts the I2C bit- and byte-level communication away from each specific device class, making it easy to keep the device class clean while providing a simple way to modify just one class to port the I2C communication code onto different platforms (Arduino, PIC, MSP430, Jennic, simple bit-banging, etc.). Device classes are designed to provide complete coverage of all functionality described by each device's documentation, plus any generic convenience functions that are helpful. - -The code is written primarily to support the Arduino/Wiring implementation, but it may be useful in other circumstances. There are multiple I2C/TWI implementations selectable in the I2Cdev.h header file if the default Arduino "Wire.h" is not available or preferable for any reason. - -There are examples in many of the classes that demonstrate basic usage patterns. The I2Cdev class is built to be used statically, reducing the memory requirement if you have multiple I2C devices in your project. Only one instance of the I2Cdev class is required. - -Documentation for each class is created using Doxygen-style comments placed in each class definition file, based on the information available in each device's datasheet. This documentation is available in HTML format on the i2cdevlib.com website, which also holds helpful information for most of the classes present here on the repository. - -To use the library, just place the I2Cdev .cpp/.h or .c/.h source files and any device library .cpp/.h or .c/.h source files in the same folder as your sketch (or a suitable place relative to your project build tool), and include just the device library headers that you need. Arduino users will also need to include in your main sketch source file. Create a single device object (e.g. "ADXL345 accel();"), place any appropriate init function calls in your setup() routine (e.g. "accel.initialize();"), and off you go! See the example sketches inside many of the device class directories for reference. - -Want a library for a device that isn't up on the repository? Request it, or fork the code and contribute! Better yet, send me a device on a breakout board to test the code during development. No guarantees on how fast I can get it done, but I'd love to make this the biggest consistent and well-documented I2C device library around. From 209500b4643bd0e619f00981e2e87a3e0ab03b30 Mon Sep 17 00:00:00 2001 From: Gino Date: Wed, 29 Sep 2021 16:41:00 -0300 Subject: [PATCH 287/335] I2Cdev port for Raspberry Pi Pico --- RP2040/I2Cdev/I2Cdev.cpp | 346 +++++++++++++++++++++++++++++++++++++++ RP2040/I2Cdev/I2Cdev.h | 87 ++++++++++ 2 files changed, 433 insertions(+) create mode 100644 RP2040/I2Cdev/I2Cdev.cpp create mode 100644 RP2040/I2Cdev/I2Cdev.h diff --git a/RP2040/I2Cdev/I2Cdev.cpp b/RP2040/I2Cdev/I2Cdev.cpp new file mode 100644 index 00000000..87abecdd --- /dev/null +++ b/RP2040/I2Cdev/I2Cdev.cpp @@ -0,0 +1,346 @@ +// I2Cdev library collection - Main I2C device class +// Abstracts bit and byte I2C R/W functions into a convenient class +// 2013-06-05 by Jeff Rowberg +// +// Changelog: +// 2013-05-06 - add Francesco Ferrara's Fastwire v0.24 implementation with small modifications +// 2013-05-05 - fix issue with writing bit values to words (Sasquatch/Farzanegan) +// 2012-06-09 - fix major issue with reading > 32 bytes at a time with Arduino Wire +// - add compiler warnings when using outdated or IDE or limited I2Cdev implementation +// 2011-11-01 - fix write*Bits mask calculation (thanks sasquatch @ Arduino forums) +// 2011-10-03 - added automatic Arduino version detection for ease of use +// 2011-10-02 - added Gene Knight's NBWire TwoWire class implementation with small modifications +// 2011-08-31 - added support for Arduino 1.0 Wire library (methods are different from 0.x) +// 2011-08-03 - added optional timeout parameter to read* methods to easily change from default +// 2011-08-02 - added support for 16-bit registers +// - fixed incorrect Doxygen comments on some methods +// - added timeout value for read operations (thanks mem @ Arduino forums) +// 2011-07-30 - changed read/write function structures to return success or byte counts +// - made all methods static for multi-device memory savings +// 2011-07-28 - initial release + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2013 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#include "I2Cdev.h" + +/** Default constructor. + */ +I2Cdev::I2Cdev() { +} + +/** Read a single bit from an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param bitNum Bit position to read (0-7) + * @param data Container for single bit value + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) + * @return Status of read operation (true = success) + */ +int8_t I2Cdev::readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data, uint32_t timeout) { + uint8_t b; + uint8_t count = readByte(devAddr, regAddr, &b, timeout); + *data = b & (1 << bitNum); + return count; +} + +/** Read a single bit from a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param bitNum Bit position to read (0-15) + * @param data Container for single bit value + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) + * @return Status of read operation (true = success) + */ +int8_t I2Cdev::readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data, uint32_t timeout) { + uint16_t b; + uint8_t count = readWord(devAddr, regAddr, &b, timeout); + *data = b & (1 << bitNum); + return count; +} + +/** Read multiple bits from an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param bitStart First bit position to read (0-7) + * @param length Number of bits to read (not more than 8) + * @param data Container for right-aligned value (i.e. '101' read from any bitStart position will equal 0x05) + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) + * @return Status of read operation (true = success) + */ +int8_t I2Cdev::readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data, uint32_t timeout) { + // 01101001 read byte + // 76543210 bit numbers + // xxx args: bitStart=4, length=3 + // 010 masked + // -> 010 shifted + uint8_t count, b; + if ((count = readByte(devAddr, regAddr, &b, timeout)) != 0) { + uint8_t mask = ((1 << length) - 1) << (bitStart - length + 1); + b &= mask; + b >>= (bitStart - length + 1); + *data = b; + } + return count; +} + +/** Read multiple bits from a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param bitStart First bit position to read (0-15) + * @param length Number of bits to read (not more than 16) + * @param data Container for right-aligned value (i.e. '101' read from any bitStart position will equal 0x05) + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) + * @return Status of read operation (1 = success, 0 = failure, -1 = timeout) + */ +int8_t I2Cdev::readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t *data, uint32_t timeout) { + // 1101011001101001 read byte + // fedcba9876543210 bit numbers + // xxx args: bitStart=12, length=3 + // 010 masked + // -> 010 shifted + uint8_t count; + uint16_t w; + if ((count = readWord(devAddr, regAddr, &w, timeout)) != 0) { + uint16_t mask = ((1 << length) - 1) << (bitStart - length + 1); + w &= mask; + w >>= (bitStart - length + 1); + *data = w; + } + return count; +} + +/** Read single byte from an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param data Container for byte value read from device + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) + * @return Status of read operation (true = success) + */ +int8_t I2Cdev::readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint32_t timeout) { + return readBytes(devAddr, regAddr, 1, data, timeout); +} + +/** Read single word from a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param data Container for word value read from device + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) + * @return Status of read operation (true = success) + */ +int8_t I2Cdev::readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data, uint32_t timeout) { + return readWords(devAddr, regAddr, 1, data, timeout); +} + +/** Read multiple bytes from an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr First register regAddr to read from + * @param length Number of bytes to read + * @param data Buffer to store read data in + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) + * @return Number of bytes read (-1 indicates failure) + */ +int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data, uint32_t timeout) { + int8_t count = 0; + + i2c_write_blocking(i2c_default, devAddr, ®Addr, 1, true); + count = i2c_read_timeout_us(i2c_default, devAddr, data, length, false, timeout * 1000); + + return count; +} + +/** Read multiple words from a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr First register regAddr to read from + * @param length Number of words to read + * @param data Buffer to store read data in + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) + * @return Number of words read (-1 indicates failure) + */ +int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data, uint32_t timeout) { + int8_t count = 0, j = 0; + uint8_t data_buf[length*2]; + + i2c_write_blocking(i2c_default, devAddr, ®Addr, 1, true); + count = i2c_read_timeout_us(i2c_default, devAddr, data_buf, length*2, false, timeout * 1000); + for(int i=0; i> 8; + data_buf[j+1] = data[i]; + j++; + } + status = i2c_write_blocking(i2c_default, devAddr, data_buf, new_len, false); + + return status; +} + +/** Default timeout value for read operations. + * Set this to 0 to disable timeout detection. + */ +uint32_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; \ No newline at end of file diff --git a/RP2040/I2Cdev/I2Cdev.h b/RP2040/I2Cdev/I2Cdev.h new file mode 100644 index 00000000..51aadc6c --- /dev/null +++ b/RP2040/I2Cdev/I2Cdev.h @@ -0,0 +1,87 @@ +// I2Cdev library collection - Main I2C device class header file +// Abstracts bit and byte I2C R/W functions into a convenient class +// 2013-06-05 by Jeff Rowberg +// +// Changelog: +// 2020-01-20 - hardija : complete support for Teensy 3.x +// 2015-10-30 - simondlevy : support i2c_t3 for Teensy3.1 +// 2013-05-06 - add Francesco Ferrara's Fastwire v0.24 implementation with small modifications +// 2013-05-05 - fix issue with writing bit values to words (Sasquatch/Farzanegan) +// 2012-06-09 - fix major issue with reading > 32 bytes at a time with Arduino Wire +// - add compiler warnings when using outdated or IDE or limited I2Cdev implementation +// 2011-11-01 - fix write*Bits mask calculation (thanks sasquatch @ Arduino forums) +// 2011-10-03 - added automatic Arduino version detection for ease of use +// 2011-10-02 - added Gene Knight's NBWire TwoWire class implementation with small modifications +// 2011-08-31 - added support for Arduino 1.0 Wire library (methods are different from 0.x) +// 2011-08-03 - added optional timeout parameter to read* methods to easily change from default +// 2011-08-02 - added support for 16-bit registers +// - fixed incorrect Doxygen comments on some methods +// - added timeout value for read operations (thanks mem @ Arduino forums) +// 2011-07-30 - changed read/write function structures to return success or byte counts +// - made all methods static for multi-device memory savings +// 2011-07-28 - initial release + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2013 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#ifndef _I2CDEV_PICO_WRAPPER_H_ +#define _I2CDEV_PICO_WRAPPER_H_ + +#include +#include +#include +#include +#include "pico/stdlib.h" +#include "hardware/i2c.h" + +// 1000ms default read timeout (modify with "I2Cdev::readTimeout = [ms];") +#define I2CDEV_DEFAULT_READ_TIMEOUT ((uint32_t)1000000) // RP2040 I2C functions with timeout uses microseconds so we have to multiply by 10^3 + +class I2Cdev { + public: + I2Cdev(); + + static int8_t readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data, uint32_t timeout=I2Cdev::readTimeout); + static int8_t readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data, uint32_t timeout=I2Cdev::readTimeout); + static int8_t readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data, uint32_t timeout=I2Cdev::readTimeout); + static int8_t readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t *data, uint32_t timeout=I2Cdev::readTimeout); + static int8_t readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint32_t timeout=I2Cdev::readTimeout); + static int8_t readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data, uint32_t timeout=I2Cdev::readTimeout); + static int8_t readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data, uint32_t timeout=I2Cdev::readTimeout); + static int8_t readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data, uint32_t timeout=I2Cdev::readTimeout); + + static bool writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t data); + static bool writeBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t data); + static bool writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data); + static bool writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t data); + static bool writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data); + static bool writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data); + static bool writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data); + static bool writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data); + + static uint32_t readTimeout; + +}; + +#endif /* _I2CDEV_PICO_WRAPPER_H_ */ From a3388e9c014431fde3e8416badb028029fe9c4fc Mon Sep 17 00:00:00 2001 From: Gino Date: Wed, 29 Sep 2021 16:42:19 -0300 Subject: [PATCH 288/335] MPU6050 library port with DMP V6.12 support and examples. --- RP2040/MPU6050/MPU6050.cpp | 3386 +++++++++++++++++ RP2040/MPU6050/MPU6050.h | 1030 +++++ .../MPU6050/MPU6050_6Axis_MotionApps_V6_12.h | 561 +++ RP2040/MPU6050/examples/README.md | 10 + .../.vscode/c_cpp_properties.json | 18 + .../mpu6050_DMP_V6.12/.vscode/extensions.json | 7 + .../mpu6050_DMP_V6.12/.vscode/launch.json | 29 + .../mpu6050_DMP_V6.12/.vscode/settings.json | 16 + .../examples/mpu6050_DMP_V6.12/CMakeLists.txt | 36 + .../mpu6050_DMP_V6.12/mpu6050_DMP_port.cpp | 124 + .../mpu6050_DMP_V6.12/pico_sdk_import.cmake | 62 + .../.vscode/c_cpp_properties.json | 18 + .../.vscode/extensions.json | 7 + .../mpu6050_calibration/.vscode/launch.json | 29 + .../mpu6050_calibration/.vscode/settings.json | 32 + .../mpu6050_calibration/CMakeLists.txt | 35 + .../mpu6050_i2c_calibration.c | 408 ++ .../mpu6050_calibration/pico_sdk_import.cmake | 62 + RP2040/MPU6050/helper_3dmath.h | 218 ++ 19 files changed, 6088 insertions(+) create mode 100644 RP2040/MPU6050/MPU6050.cpp create mode 100644 RP2040/MPU6050/MPU6050.h create mode 100644 RP2040/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h create mode 100644 RP2040/MPU6050/examples/README.md create mode 100644 RP2040/MPU6050/examples/mpu6050_DMP_V6.12/.vscode/c_cpp_properties.json create mode 100644 RP2040/MPU6050/examples/mpu6050_DMP_V6.12/.vscode/extensions.json create mode 100644 RP2040/MPU6050/examples/mpu6050_DMP_V6.12/.vscode/launch.json create mode 100644 RP2040/MPU6050/examples/mpu6050_DMP_V6.12/.vscode/settings.json create mode 100644 RP2040/MPU6050/examples/mpu6050_DMP_V6.12/CMakeLists.txt create mode 100644 RP2040/MPU6050/examples/mpu6050_DMP_V6.12/mpu6050_DMP_port.cpp create mode 100644 RP2040/MPU6050/examples/mpu6050_DMP_V6.12/pico_sdk_import.cmake create mode 100644 RP2040/MPU6050/examples/mpu6050_calibration/.vscode/c_cpp_properties.json create mode 100644 RP2040/MPU6050/examples/mpu6050_calibration/.vscode/extensions.json create mode 100644 RP2040/MPU6050/examples/mpu6050_calibration/.vscode/launch.json create mode 100644 RP2040/MPU6050/examples/mpu6050_calibration/.vscode/settings.json create mode 100644 RP2040/MPU6050/examples/mpu6050_calibration/CMakeLists.txt create mode 100644 RP2040/MPU6050/examples/mpu6050_calibration/mpu6050_i2c_calibration.c create mode 100644 RP2040/MPU6050/examples/mpu6050_calibration/pico_sdk_import.cmake create mode 100644 RP2040/MPU6050/helper_3dmath.h diff --git a/RP2040/MPU6050/MPU6050.cpp b/RP2040/MPU6050/MPU6050.cpp new file mode 100644 index 00000000..8b85e76e --- /dev/null +++ b/RP2040/MPU6050/MPU6050.cpp @@ -0,0 +1,3386 @@ +// I2Cdev library collection - MPU6050 I2C device class +// Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00) +// 8/24/2011 by Jeff Rowberg +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// 2019-07-08 - Added Auto Calibration routine +// ... - ongoing debug release + +// NOTE: THIS IS ONLY A PARIAL RELEASE. THIS DEVICE CLASS IS CURRENTLY UNDERGOING ACTIVE +// DEVELOPMENT AND IS STILL MISSING SOME IMPORTANT FEATURES. PLEASE KEEP THIS IN MIND IF +// YOU DECIDE TO USE THIS PARTICULAR CODE FOR ANYTHING. + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2012 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#include "MPU6050.h" + + +#ifndef BUFFER_LENGTH +// band-aid fix for platforms without Wire-defined BUFFER_LENGTH (removed from some official implementations) +#define BUFFER_LENGTH 32 +#endif + +static int addr = 0x68; + +int16_t map(int16_t x, int16_t in_min, int16_t in_max, int16_t out_min, int16_t out_max) { + return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; +} + +/** Specific address constructor. + * @param address I2C address, uses default I2C address if none is specified + * @see MPU6050_DEFAULT_ADDRESS + * @see MPU6050_ADDRESS_AD0_LOW + * @see MPU6050_ADDRESS_AD0_HIGH + */ +MPU6050::MPU6050(uint8_t address):devAddr(address) { +} + +/** Power on and prepare for general usage. + * This will activate the device and take it out of sleep mode (which must be done + * after start-up). This function also sets both the accelerometer and the gyroscope + * to their most sensitive settings, namely +/- 2g and +/- 250 degrees/sec, and sets + * the clock source to use the X Gyro for reference, which is slightly better than + * the default internal clock source. + */ +void MPU6050::initialize() { + setClockSource(MPU6050_CLOCK_PLL_XGYRO); + setFullScaleGyroRange(MPU6050_GYRO_FS_250); + setFullScaleAccelRange(MPU6050_ACCEL_FS_2); + // Set offsets + /*setXAccelOffset(-457); + setYAccelOffset(319); + setZAccelOffset(1392); + setXGyroOffset(7); + setYGyroOffset(-198); + setZGyroOffset(-57);*/ + setSleepEnabled(false); // thanks to Jack Elston for pointing this one out! +} + +/** Verify the I2C connection. + * Make sure the device is connected and responds as expected. + * @return True if connection is valid, false otherwise + */ +bool MPU6050::testConnection() { + return getDeviceID() == 0x34; +} + +// AUX_VDDIO register (InvenSense demo code calls this RA_*G_OFFS_TC) + +/** Get the auxiliary I2C supply voltage level. + * When set to 1, the auxiliary I2C bus high logic level is VDD. When cleared to + * 0, the auxiliary I2C bus high logic level is VLOGIC. This does not apply to + * the MPU-6000, which does not have a VLOGIC pin. + * @return I2C supply voltage level (0=VLOGIC, 1=VDD) + */ +uint8_t MPU6050::getAuxVDDIOLevel() { + I2Cdev::readBit(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_PWR_MODE_BIT, buffer); + return buffer[0]; +} +/** Set the auxiliary I2C supply voltage level. + * When set to 1, the auxiliary I2C bus high logic level is VDD. When cleared to + * 0, the auxiliary I2C bus high logic level is VLOGIC. This does not apply to + * the MPU-6000, which does not have a VLOGIC pin. + * @param level I2C supply voltage level (0=VLOGIC, 1=VDD) + */ +void MPU6050::setAuxVDDIOLevel(uint8_t level) { + I2Cdev::writeBit(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_PWR_MODE_BIT, level); +} + +// SMPLRT_DIV register + +/** Get gyroscope output rate divider. + * The sensor register output, FIFO output, DMP sampling, Motion detection, Zero + * Motion detection, and Free Fall detection are all based on the Sample Rate. + * The Sample Rate is generated by dividing the gyroscope output rate by + * SMPLRT_DIV: + * + * Sample Rate = Gyroscope Output Rate / (1 + SMPLRT_DIV) + * + * where Gyroscope Output Rate = 8kHz when the DLPF is disabled (DLPF_CFG = 0 or + * 7), and 1kHz when the DLPF is enabled (see Register 26). + * + * Note: The accelerometer output rate is 1kHz. This means that for a Sample + * Rate greater than 1kHz, the same accelerometer sample may be output to the + * FIFO, DMP, and sensor registers more than once. + * + * For a diagram of the gyroscope and accelerometer signal paths, see Section 8 + * of the MPU-6000/MPU-6050 Product Specification document. + * + * @return Current sample rate + * @see MPU6050_RA_SMPLRT_DIV + */ +uint8_t MPU6050::getRate() { + I2Cdev::readByte(devAddr, MPU6050_RA_SMPLRT_DIV, buffer); + return buffer[0]; +} +/** Set gyroscope sample rate divider. + * @param rate New sample rate divider + * @see getRate() + * @see MPU6050_RA_SMPLRT_DIV + */ +void MPU6050::setRate(uint8_t rate) { + I2Cdev::writeByte(devAddr, MPU6050_RA_SMPLRT_DIV, rate); +} + +// CONFIG register + +/** Get external FSYNC configuration. + * Configures the external Frame Synchronization (FSYNC) pin sampling. An + * external signal connected to the FSYNC pin can be sampled by configuring + * EXT_SYNC_SET. Signal changes to the FSYNC pin are latched so that short + * strobes may be captured. The latched FSYNC signal will be sampled at the + * Sampling Rate, as defined in register 25. After sampling, the latch will + * reset to the current FSYNC signal state. + * + * The sampled value will be reported in place of the least significant bit in + * a sensor data register determined by the value of EXT_SYNC_SET according to + * the following table. + * + *
+ * EXT_SYNC_SET | FSYNC Bit Location
+ * -------------+-------------------
+ * 0            | Input disabled
+ * 1            | TEMP_OUT_L[0]
+ * 2            | GYRO_XOUT_L[0]
+ * 3            | GYRO_YOUT_L[0]
+ * 4            | GYRO_ZOUT_L[0]
+ * 5            | ACCEL_XOUT_L[0]
+ * 6            | ACCEL_YOUT_L[0]
+ * 7            | ACCEL_ZOUT_L[0]
+ * 
+ * + * @return FSYNC configuration value + */ +uint8_t MPU6050::getExternalFrameSync() { + I2Cdev::readBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_EXT_SYNC_SET_BIT, MPU6050_CFG_EXT_SYNC_SET_LENGTH, buffer); + return buffer[0]; +} +/** Set external FSYNC configuration. + * @see getExternalFrameSync() + * @see MPU6050_RA_CONFIG + * @param sync New FSYNC configuration value + */ +void MPU6050::setExternalFrameSync(uint8_t sync) { + I2Cdev::writeBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_EXT_SYNC_SET_BIT, MPU6050_CFG_EXT_SYNC_SET_LENGTH, sync); +} +/** Get digital low-pass filter configuration. + * The DLPF_CFG parameter sets the digital low pass filter configuration. It + * also determines the internal sampling rate used by the device as shown in + * the table below. + * + * Note: The accelerometer output rate is 1kHz. This means that for a Sample + * Rate greater than 1kHz, the same accelerometer sample may be output to the + * FIFO, DMP, and sensor registers more than once. + * + *
+ *          |   ACCELEROMETER    |           GYROSCOPE
+ * DLPF_CFG | Bandwidth | Delay  | Bandwidth | Delay  | Sample Rate
+ * ---------+-----------+--------+-----------+--------+-------------
+ * 0        | 260Hz     | 0ms    | 256Hz     | 0.98ms | 8kHz
+ * 1        | 184Hz     | 2.0ms  | 188Hz     | 1.9ms  | 1kHz
+ * 2        | 94Hz      | 3.0ms  | 98Hz      | 2.8ms  | 1kHz
+ * 3        | 44Hz      | 4.9ms  | 42Hz      | 4.8ms  | 1kHz
+ * 4        | 21Hz      | 8.5ms  | 20Hz      | 8.3ms  | 1kHz
+ * 5        | 10Hz      | 13.8ms | 10Hz      | 13.4ms | 1kHz
+ * 6        | 5Hz       | 19.0ms | 5Hz       | 18.6ms | 1kHz
+ * 7        |   -- Reserved --   |   -- Reserved --   | Reserved
+ * 
+ * + * @return DLFP configuration + * @see MPU6050_RA_CONFIG + * @see MPU6050_CFG_DLPF_CFG_BIT + * @see MPU6050_CFG_DLPF_CFG_LENGTH + */ +uint8_t MPU6050::getDLPFMode() { + I2Cdev::readBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_DLPF_CFG_BIT, MPU6050_CFG_DLPF_CFG_LENGTH, buffer); + return buffer[0]; +} +/** Set digital low-pass filter configuration. + * @param mode New DLFP configuration setting + * @see getDLPFBandwidth() + * @see MPU6050_DLPF_BW_256 + * @see MPU6050_RA_CONFIG + * @see MPU6050_CFG_DLPF_CFG_BIT + * @see MPU6050_CFG_DLPF_CFG_LENGTH + */ +void MPU6050::setDLPFMode(uint8_t mode) { + I2Cdev::writeBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_DLPF_CFG_BIT, MPU6050_CFG_DLPF_CFG_LENGTH, mode); +} + +// GYRO_CONFIG register + +/** Get full-scale gyroscope range. + * The FS_SEL parameter allows setting the full-scale range of the gyro sensors, + * as described in the table below. + * + *
+ * 0 = +/- 250 degrees/sec
+ * 1 = +/- 500 degrees/sec
+ * 2 = +/- 1000 degrees/sec
+ * 3 = +/- 2000 degrees/sec
+ * 
+ * + * @return Current full-scale gyroscope range setting + * @see MPU6050_GYRO_FS_250 + * @see MPU6050_RA_GYRO_CONFIG + * @see MPU6050_GCONFIG_FS_SEL_BIT + * @see MPU6050_GCONFIG_FS_SEL_LENGTH + */ +uint8_t MPU6050::getFullScaleGyroRange() { + I2Cdev::readBits(devAddr, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, buffer); + return buffer[0]; +} +/** Set full-scale gyroscope range. + * @param range New full-scale gyroscope range value + * @see getFullScaleRange() + * @see MPU6050_GYRO_FS_250 + * @see MPU6050_RA_GYRO_CONFIG + * @see MPU6050_GCONFIG_FS_SEL_BIT + * @see MPU6050_GCONFIG_FS_SEL_LENGTH + */ +void MPU6050::setFullScaleGyroRange(uint8_t range) { + I2Cdev::writeBits(devAddr, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, range); +} + +// SELF TEST FACTORY TRIM VALUES + +/** Get self-test factory trim value for accelerometer X axis. + * @return factory trim value + * @see MPU6050_RA_SELF_TEST_X + */ +uint8_t MPU6050::getAccelXSelfTestFactoryTrim() { + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_X, &buffer[0]); + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_A, &buffer[1]); + return (buffer[0]>>3) | ((buffer[1]>>4) & 0x03); +} + +/** Get self-test factory trim value for accelerometer Y axis. + * @return factory trim value + * @see MPU6050_RA_SELF_TEST_Y + */ +uint8_t MPU6050::getAccelYSelfTestFactoryTrim() { + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_Y, &buffer[0]); + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_A, &buffer[1]); + return (buffer[0]>>3) | ((buffer[1]>>2) & 0x03); +} + +/** Get self-test factory trim value for accelerometer Z axis. + * @return factory trim value + * @see MPU6050_RA_SELF_TEST_Z + */ +uint8_t MPU6050::getAccelZSelfTestFactoryTrim() { + I2Cdev::readBytes(devAddr, MPU6050_RA_SELF_TEST_Z, 2, buffer); + return (buffer[0]>>3) | (buffer[1] & 0x03); +} + +/** Get self-test factory trim value for gyro X axis. + * @return factory trim value + * @see MPU6050_RA_SELF_TEST_X + */ +uint8_t MPU6050::getGyroXSelfTestFactoryTrim() { + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_X, buffer); + return (buffer[0] & 0x1F); +} + +/** Get self-test factory trim value for gyro Y axis. + * @return factory trim value + * @see MPU6050_RA_SELF_TEST_Y + */ +uint8_t MPU6050::getGyroYSelfTestFactoryTrim() { + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_Y, buffer); + return (buffer[0] & 0x1F); +} + +/** Get self-test factory trim value for gyro Z axis. + * @return factory trim value + * @see MPU6050_RA_SELF_TEST_Z + */ +uint8_t MPU6050::getGyroZSelfTestFactoryTrim() { + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_Z, buffer); + return (buffer[0] & 0x1F); +} + +// ACCEL_CONFIG register + +/** Get self-test enabled setting for accelerometer X axis. + * @return Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +bool MPU6050::getAccelXSelfTest() { + I2Cdev::readBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_XA_ST_BIT, buffer); + return buffer[0]; +} +/** Get self-test enabled setting for accelerometer X axis. + * @param enabled Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050::setAccelXSelfTest(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_XA_ST_BIT, enabled); +} +/** Get self-test enabled value for accelerometer Y axis. + * @return Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +bool MPU6050::getAccelYSelfTest() { + I2Cdev::readBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_YA_ST_BIT, buffer); + return buffer[0]; +} +/** Get self-test enabled value for accelerometer Y axis. + * @param enabled Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050::setAccelYSelfTest(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_YA_ST_BIT, enabled); +} +/** Get self-test enabled value for accelerometer Z axis. + * @return Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +bool MPU6050::getAccelZSelfTest() { + I2Cdev::readBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ZA_ST_BIT, buffer); + return buffer[0]; +} +/** Set self-test enabled value for accelerometer Z axis. + * @param enabled Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050::setAccelZSelfTest(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ZA_ST_BIT, enabled); +} +/** Get full-scale accelerometer range. + * The FS_SEL parameter allows setting the full-scale range of the accelerometer + * sensors, as described in the table below. + * + *
+ * 0 = +/- 2g
+ * 1 = +/- 4g
+ * 2 = +/- 8g
+ * 3 = +/- 16g
+ * 
+ * + * @return Current full-scale accelerometer range setting + * @see MPU6050_ACCEL_FS_2 + * @see MPU6050_RA_ACCEL_CONFIG + * @see MPU6050_ACONFIG_AFS_SEL_BIT + * @see MPU6050_ACONFIG_AFS_SEL_LENGTH + */ +uint8_t MPU6050::getFullScaleAccelRange() { + I2Cdev::readBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, buffer); + return buffer[0]; +} +/** Set full-scale accelerometer range. + * @param range New full-scale accelerometer range setting + * @see getFullScaleAccelRange() + */ +void MPU6050::setFullScaleAccelRange(uint8_t range) { + I2Cdev::writeBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, range); +} +/** Get the high-pass filter configuration. + * The DHPF is a filter module in the path leading to motion detectors (Free + * Fall, Motion threshold, and Zero Motion). The high pass filter output is not + * available to the data registers (see Figure in Section 8 of the MPU-6000/ + * MPU-6050 Product Specification document). + * + * The high pass filter has three modes: + * + *
+ *    Reset: The filter output settles to zero within one sample. This
+ *           effectively disables the high pass filter. This mode may be toggled
+ *           to quickly settle the filter.
+ *
+ *    On:    The high pass filter will pass signals above the cut off frequency.
+ *
+ *    Hold:  When triggered, the filter holds the present sample. The filter
+ *           output will be the difference between the input sample and the held
+ *           sample.
+ * 
+ * + *
+ * ACCEL_HPF | Filter Mode | Cut-off Frequency
+ * ----------+-------------+------------------
+ * 0         | Reset       | None
+ * 1         | On          | 5Hz
+ * 2         | On          | 2.5Hz
+ * 3         | On          | 1.25Hz
+ * 4         | On          | 0.63Hz
+ * 7         | Hold        | None
+ * 
+ * + * @return Current high-pass filter configuration + * @see MPU6050_DHPF_RESET + * @see MPU6050_RA_ACCEL_CONFIG + */ +uint8_t MPU6050::getDHPFMode() { + I2Cdev::readBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ACCEL_HPF_BIT, MPU6050_ACONFIG_ACCEL_HPF_LENGTH, buffer); + return buffer[0]; +} +/** Set the high-pass filter configuration. + * @param bandwidth New high-pass filter configuration + * @see setDHPFMode() + * @see MPU6050_DHPF_RESET + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050::setDHPFMode(uint8_t bandwidth) { + I2Cdev::writeBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ACCEL_HPF_BIT, MPU6050_ACONFIG_ACCEL_HPF_LENGTH, bandwidth); +} + +// FF_THR register + +/** Get free-fall event acceleration threshold. + * This register configures the detection threshold for Free Fall event + * detection. The unit of FF_THR is 1LSB = 2mg. Free Fall is detected when the + * absolute value of the accelerometer measurements for the three axes are each + * less than the detection threshold. This condition increments the Free Fall + * duration counter (Register 30). The Free Fall interrupt is triggered when the + * Free Fall duration counter reaches the time specified in FF_DUR. + * + * For more details on the Free Fall detection interrupt, see Section 8.2 of the + * MPU-6000/MPU-6050 Product Specification document as well as Registers 56 and + * 58 of this document. + * + * @return Current free-fall acceleration threshold value (LSB = 2mg) + * @see MPU6050_RA_FF_THR + */ +uint8_t MPU6050::getFreefallDetectionThreshold() { + I2Cdev::readByte(devAddr, MPU6050_RA_FF_THR, buffer); + return buffer[0]; +} +/** Get free-fall event acceleration threshold. + * @param threshold New free-fall acceleration threshold value (LSB = 2mg) + * @see getFreefallDetectionThreshold() + * @see MPU6050_RA_FF_THR + */ +void MPU6050::setFreefallDetectionThreshold(uint8_t threshold) { + I2Cdev::writeByte(devAddr, MPU6050_RA_FF_THR, threshold); +} + +// FF_DUR register + +/** Get free-fall event duration threshold. + * This register configures the duration counter threshold for Free Fall event + * detection. The duration counter ticks at 1kHz, therefore FF_DUR has a unit + * of 1 LSB = 1 ms. + * + * The Free Fall duration counter increments while the absolute value of the + * accelerometer measurements are each less than the detection threshold + * (Register 29). The Free Fall interrupt is triggered when the Free Fall + * duration counter reaches the time specified in this register. + * + * For more details on the Free Fall detection interrupt, see Section 8.2 of + * the MPU-6000/MPU-6050 Product Specification document as well as Registers 56 + * and 58 of this document. + * + * @return Current free-fall duration threshold value (LSB = 1ms) + * @see MPU6050_RA_FF_DUR + */ +uint8_t MPU6050::getFreefallDetectionDuration() { + I2Cdev::readByte(devAddr, MPU6050_RA_FF_DUR, buffer); + return buffer[0]; +} +/** Get free-fall event duration threshold. + * @param duration New free-fall duration threshold value (LSB = 1ms) + * @see getFreefallDetectionDuration() + * @see MPU6050_RA_FF_DUR + */ +void MPU6050::setFreefallDetectionDuration(uint8_t duration) { + I2Cdev::writeByte(devAddr, MPU6050_RA_FF_DUR, duration); +} + +// MOT_THR register + +/** Get motion detection event acceleration threshold. + * This register configures the detection threshold for Motion interrupt + * generation. The unit of MOT_THR is 1LSB = 2mg. Motion is detected when the + * absolute value of any of the accelerometer measurements exceeds this Motion + * detection threshold. This condition increments the Motion detection duration + * counter (Register 32). The Motion detection interrupt is triggered when the + * Motion Detection counter reaches the time count specified in MOT_DUR + * (Register 32). + * + * The Motion interrupt will indicate the axis and polarity of detected motion + * in MOT_DETECT_STATUS (Register 97). + * + * For more details on the Motion detection interrupt, see Section 8.3 of the + * MPU-6000/MPU-6050 Product Specification document as well as Registers 56 and + * 58 of this document. + * + * @return Current motion detection acceleration threshold value (LSB = 2mg) + * @see MPU6050_RA_MOT_THR + */ +uint8_t MPU6050::getMotionDetectionThreshold() { + I2Cdev::readByte(devAddr, MPU6050_RA_MOT_THR, buffer); + return buffer[0]; +} +/** Set motion detection event acceleration threshold. + * @param threshold New motion detection acceleration threshold value (LSB = 2mg) + * @see getMotionDetectionThreshold() + * @see MPU6050_RA_MOT_THR + */ +void MPU6050::setMotionDetectionThreshold(uint8_t threshold) { + I2Cdev::writeByte(devAddr, MPU6050_RA_MOT_THR, threshold); +} + +// MOT_DUR register + +/** Get motion detection event duration threshold. + * This register configures the duration counter threshold for Motion interrupt + * generation. The duration counter ticks at 1 kHz, therefore MOT_DUR has a unit + * of 1LSB = 1ms. The Motion detection duration counter increments when the + * absolute value of any of the accelerometer measurements exceeds the Motion + * detection threshold (Register 31). The Motion detection interrupt is + * triggered when the Motion detection counter reaches the time count specified + * in this register. + * + * For more details on the Motion detection interrupt, see Section 8.3 of the + * MPU-6000/MPU-6050 Product Specification document. + * + * @return Current motion detection duration threshold value (LSB = 1ms) + * @see MPU6050_RA_MOT_DUR + */ +uint8_t MPU6050::getMotionDetectionDuration() { + I2Cdev::readByte(devAddr, MPU6050_RA_MOT_DUR, buffer); + return buffer[0]; +} +/** Set motion detection event duration threshold. + * @param duration New motion detection duration threshold value (LSB = 1ms) + * @see getMotionDetectionDuration() + * @see MPU6050_RA_MOT_DUR + */ +void MPU6050::setMotionDetectionDuration(uint8_t duration) { + I2Cdev::writeByte(devAddr, MPU6050_RA_MOT_DUR, duration); +} + +// ZRMOT_THR register + +/** Get zero motion detection event acceleration threshold. + * This register configures the detection threshold for Zero Motion interrupt + * generation. The unit of ZRMOT_THR is 1LSB = 2mg. Zero Motion is detected when + * the absolute value of the accelerometer measurements for the 3 axes are each + * less than the detection threshold. This condition increments the Zero Motion + * duration counter (Register 34). The Zero Motion interrupt is triggered when + * the Zero Motion duration counter reaches the time count specified in + * ZRMOT_DUR (Register 34). + * + * Unlike Free Fall or Motion detection, Zero Motion detection triggers an + * interrupt both when Zero Motion is first detected and when Zero Motion is no + * longer detected. + * + * When a zero motion event is detected, a Zero Motion Status will be indicated + * in the MOT_DETECT_STATUS register (Register 97). When a motion-to-zero-motion + * condition is detected, the status bit is set to 1. When a zero-motion-to- + * motion condition is detected, the status bit is set to 0. + * + * For more details on the Zero Motion detection interrupt, see Section 8.4 of + * the MPU-6000/MPU-6050 Product Specification document as well as Registers 56 + * and 58 of this document. + * + * @return Current zero motion detection acceleration threshold value (LSB = 2mg) + * @see MPU6050_RA_ZRMOT_THR + */ +uint8_t MPU6050::getZeroMotionDetectionThreshold() { + I2Cdev::readByte(devAddr, MPU6050_RA_ZRMOT_THR, buffer); + return buffer[0]; +} +/** Set zero motion detection event acceleration threshold. + * @param threshold New zero motion detection acceleration threshold value (LSB = 2mg) + * @see getZeroMotionDetectionThreshold() + * @see MPU6050_RA_ZRMOT_THR + */ +void MPU6050::setZeroMotionDetectionThreshold(uint8_t threshold) { + I2Cdev::writeByte(devAddr, MPU6050_RA_ZRMOT_THR, threshold); +} + +// ZRMOT_DUR register + +/** Get zero motion detection event duration threshold. + * This register configures the duration counter threshold for Zero Motion + * interrupt generation. The duration counter ticks at 16 Hz, therefore + * ZRMOT_DUR has a unit of 1 LSB = 64 ms. The Zero Motion duration counter + * increments while the absolute value of the accelerometer measurements are + * each less than the detection threshold (Register 33). The Zero Motion + * interrupt is triggered when the Zero Motion duration counter reaches the time + * count specified in this register. + * + * For more details on the Zero Motion detection interrupt, see Section 8.4 of + * the MPU-6000/MPU-6050 Product Specification document, as well as Registers 56 + * and 58 of this document. + * + * @return Current zero motion detection duration threshold value (LSB = 64ms) + * @see MPU6050_RA_ZRMOT_DUR + */ +uint8_t MPU6050::getZeroMotionDetectionDuration() { + I2Cdev::readByte(devAddr, MPU6050_RA_ZRMOT_DUR, buffer); + return buffer[0]; +} +/** Set zero motion detection event duration threshold. + * @param duration New zero motion detection duration threshold value (LSB = 1ms) + * @see getZeroMotionDetectionDuration() + * @see MPU6050_RA_ZRMOT_DUR + */ +void MPU6050::setZeroMotionDetectionDuration(uint8_t duration) { + I2Cdev::writeByte(devAddr, MPU6050_RA_ZRMOT_DUR, duration); +} + +// FIFO_EN register + +/** Get temperature FIFO enabled value. + * When set to 1, this bit enables TEMP_OUT_H and TEMP_OUT_L (Registers 65 and + * 66) to be written into the FIFO buffer. + * @return Current temperature FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050::getTempFIFOEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_TEMP_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set temperature FIFO enabled value. + * @param enabled New temperature FIFO enabled value + * @see getTempFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050::setTempFIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_TEMP_FIFO_EN_BIT, enabled); +} +/** Get gyroscope X-axis FIFO enabled value. + * When set to 1, this bit enables GYRO_XOUT_H and GYRO_XOUT_L (Registers 67 and + * 68) to be written into the FIFO buffer. + * @return Current gyroscope X-axis FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050::getXGyroFIFOEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_XG_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set gyroscope X-axis FIFO enabled value. + * @param enabled New gyroscope X-axis FIFO enabled value + * @see getXGyroFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050::setXGyroFIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_XG_FIFO_EN_BIT, enabled); +} +/** Get gyroscope Y-axis FIFO enabled value. + * When set to 1, this bit enables GYRO_YOUT_H and GYRO_YOUT_L (Registers 69 and + * 70) to be written into the FIFO buffer. + * @return Current gyroscope Y-axis FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050::getYGyroFIFOEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_YG_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set gyroscope Y-axis FIFO enabled value. + * @param enabled New gyroscope Y-axis FIFO enabled value + * @see getYGyroFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050::setYGyroFIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_YG_FIFO_EN_BIT, enabled); +} +/** Get gyroscope Z-axis FIFO enabled value. + * When set to 1, this bit enables GYRO_ZOUT_H and GYRO_ZOUT_L (Registers 71 and + * 72) to be written into the FIFO buffer. + * @return Current gyroscope Z-axis FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050::getZGyroFIFOEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ZG_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set gyroscope Z-axis FIFO enabled value. + * @param enabled New gyroscope Z-axis FIFO enabled value + * @see getZGyroFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050::setZGyroFIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ZG_FIFO_EN_BIT, enabled); +} +/** Get accelerometer FIFO enabled value. + * When set to 1, this bit enables ACCEL_XOUT_H, ACCEL_XOUT_L, ACCEL_YOUT_H, + * ACCEL_YOUT_L, ACCEL_ZOUT_H, and ACCEL_ZOUT_L (Registers 59 to 64) to be + * written into the FIFO buffer. + * @return Current accelerometer FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050::getAccelFIFOEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ACCEL_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set accelerometer FIFO enabled value. + * @param enabled New accelerometer FIFO enabled value + * @see getAccelFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050::setAccelFIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ACCEL_FIFO_EN_BIT, enabled); +} +/** Get Slave 2 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 2 to be written into the FIFO buffer. + * @return Current Slave 2 FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050::getSlave2FIFOEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV2_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set Slave 2 FIFO enabled value. + * @param enabled New Slave 2 FIFO enabled value + * @see getSlave2FIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050::setSlave2FIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV2_FIFO_EN_BIT, enabled); +} +/** Get Slave 1 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 1 to be written into the FIFO buffer. + * @return Current Slave 1 FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050::getSlave1FIFOEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV1_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set Slave 1 FIFO enabled value. + * @param enabled New Slave 1 FIFO enabled value + * @see getSlave1FIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050::setSlave1FIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV1_FIFO_EN_BIT, enabled); +} +/** Get Slave 0 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 0 to be written into the FIFO buffer. + * @return Current Slave 0 FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050::getSlave0FIFOEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV0_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set Slave 0 FIFO enabled value. + * @param enabled New Slave 0 FIFO enabled value + * @see getSlave0FIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050::setSlave0FIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV0_FIFO_EN_BIT, enabled); +} + +// I2C_MST_CTRL register + +/** Get multi-master enabled value. + * Multi-master capability allows multiple I2C masters to operate on the same + * bus. In circuits where multi-master capability is required, set MULT_MST_EN + * to 1. This will increase current drawn by approximately 30uA. + * + * In circuits where multi-master capability is required, the state of the I2C + * bus must always be monitored by each separate I2C Master. Before an I2C + * Master can assume arbitration of the bus, it must first confirm that no other + * I2C Master has arbitration of the bus. When MULT_MST_EN is set to 1, the + * MPU-60X0's bus arbitration detection logic is turned on, enabling it to + * detect when the bus is available. + * + * @return Current multi-master enabled value + * @see MPU6050_RA_I2C_MST_CTRL + */ +bool MPU6050::getMultiMasterEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_MULT_MST_EN_BIT, buffer); + return buffer[0]; +} +/** Set multi-master enabled value. + * @param enabled New multi-master enabled value + * @see getMultiMasterEnabled() + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050::setMultiMasterEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_MULT_MST_EN_BIT, enabled); +} +/** Get wait-for-external-sensor-data enabled value. + * When the WAIT_FOR_ES bit is set to 1, the Data Ready interrupt will be + * delayed until External Sensor data from the Slave Devices are loaded into the + * EXT_SENS_DATA registers. This is used to ensure that both the internal sensor + * data (i.e. from gyro and accel) and external sensor data have been loaded to + * their respective data registers (i.e. the data is synced) when the Data Ready + * interrupt is triggered. + * + * @return Current wait-for-external-sensor-data enabled value + * @see MPU6050_RA_I2C_MST_CTRL + */ +bool MPU6050::getWaitForExternalSensorEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_WAIT_FOR_ES_BIT, buffer); + return buffer[0]; +} +/** Set wait-for-external-sensor-data enabled value. + * @param enabled New wait-for-external-sensor-data enabled value + * @see getWaitForExternalSensorEnabled() + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050::setWaitForExternalSensorEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_WAIT_FOR_ES_BIT, enabled); +} +/** Get Slave 3 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 3 to be written into the FIFO buffer. + * @return Current Slave 3 FIFO enabled value + * @see MPU6050_RA_MST_CTRL + */ +bool MPU6050::getSlave3FIFOEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_SLV_3_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set Slave 3 FIFO enabled value. + * @param enabled New Slave 3 FIFO enabled value + * @see getSlave3FIFOEnabled() + * @see MPU6050_RA_MST_CTRL + */ +void MPU6050::setSlave3FIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_SLV_3_FIFO_EN_BIT, enabled); +} +/** Get slave read/write transition enabled value. + * The I2C_MST_P_NSR bit configures the I2C Master's transition from one slave + * read to the next slave read. If the bit equals 0, there will be a restart + * between reads. If the bit equals 1, there will be a stop followed by a start + * of the following read. When a write transaction follows a read transaction, + * the stop followed by a start of the successive write will be always used. + * + * @return Current slave read/write transition enabled value + * @see MPU6050_RA_I2C_MST_CTRL + */ +bool MPU6050::getSlaveReadWriteTransitionEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_P_NSR_BIT, buffer); + return buffer[0]; +} +/** Set slave read/write transition enabled value. + * @param enabled New slave read/write transition enabled value + * @see getSlaveReadWriteTransitionEnabled() + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050::setSlaveReadWriteTransitionEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_P_NSR_BIT, enabled); +} +/** Get I2C master clock speed. + * I2C_MST_CLK is a 4 bit unsigned value which configures a divider on the + * MPU-60X0 internal 8MHz clock. It sets the I2C master clock speed according to + * the following table: + * + *
+ * I2C_MST_CLK | I2C Master Clock Speed | 8MHz Clock Divider
+ * ------------+------------------------+-------------------
+ * 0           | 348kHz                 | 23
+ * 1           | 333kHz                 | 24
+ * 2           | 320kHz                 | 25
+ * 3           | 308kHz                 | 26
+ * 4           | 296kHz                 | 27
+ * 5           | 286kHz                 | 28
+ * 6           | 276kHz                 | 29
+ * 7           | 267kHz                 | 30
+ * 8           | 258kHz                 | 31
+ * 9           | 500kHz                 | 16
+ * 10          | 471kHz                 | 17
+ * 11          | 444kHz                 | 18
+ * 12          | 421kHz                 | 19
+ * 13          | 400kHz                 | 20
+ * 14          | 381kHz                 | 21
+ * 15          | 364kHz                 | 22
+ * 
+ * + * @return Current I2C master clock speed + * @see MPU6050_RA_I2C_MST_CTRL + */ +uint8_t MPU6050::getMasterClockSpeed() { + I2Cdev::readBits(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_CLK_BIT, MPU6050_I2C_MST_CLK_LENGTH, buffer); + return buffer[0]; +} +/** Set I2C master clock speed. + * @reparam speed Current I2C master clock speed + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050::setMasterClockSpeed(uint8_t speed) { + I2Cdev::writeBits(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_CLK_BIT, MPU6050_I2C_MST_CLK_LENGTH, speed); +} + +// I2C_SLV* registers (Slave 0-3) + +/** Get the I2C address of the specified slave (0-3). + * Note that Bit 7 (MSB) controls read/write mode. If Bit 7 is set, it's a read + * operation, and if it is cleared, then it's a write operation. The remaining + * bits (6-0) are the 7-bit device address of the slave device. + * + * In read mode, the result of the read is placed in the lowest available + * EXT_SENS_DATA register. For further information regarding the allocation of + * read results, please refer to the EXT_SENS_DATA register description + * (Registers 73 - 96). + * + * The MPU-6050 supports a total of five slaves, but Slave 4 has unique + * characteristics, and so it has its own functions (getSlave4* and setSlave4*). + * + * I2C data transactions are performed at the Sample Rate, as defined in + * Register 25. The user is responsible for ensuring that I2C data transactions + * to and from each enabled Slave can be completed within a single period of the + * Sample Rate. + * + * The I2C slave access rate can be reduced relative to the Sample Rate. This + * reduced access rate is determined by I2C_MST_DLY (Register 52). Whether a + * slave's access rate is reduced relative to the Sample Rate is determined by + * I2C_MST_DELAY_CTRL (Register 103). + * + * The processing order for the slaves is fixed. The sequence followed for + * processing the slaves is Slave 0, Slave 1, Slave 2, Slave 3 and Slave 4. If a + * particular Slave is disabled it will be skipped. + * + * Each slave can either be accessed at the sample rate or at a reduced sample + * rate. In a case where some slaves are accessed at the Sample Rate and some + * slaves are accessed at the reduced rate, the sequence of accessing the slaves + * (Slave 0 to Slave 4) is still followed. However, the reduced rate slaves will + * be skipped if their access rate dictates that they should not be accessed + * during that particular cycle. For further information regarding the reduced + * access rate, please refer to Register 52. Whether a slave is accessed at the + * Sample Rate or at the reduced rate is determined by the Delay Enable bits in + * Register 103. + * + * @param num Slave number (0-3) + * @return Current address for specified slave + * @see MPU6050_RA_I2C_SLV0_ADDR + */ +uint8_t MPU6050::getSlaveAddress(uint8_t num) { + if (num > 3) return 0; + I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV0_ADDR + num*3, buffer); + return buffer[0]; +} +/** Set the I2C address of the specified slave (0-3). + * @param num Slave number (0-3) + * @param address New address for specified slave + * @see getSlaveAddress() + * @see MPU6050_RA_I2C_SLV0_ADDR + */ +void MPU6050::setSlaveAddress(uint8_t num, uint8_t address) { + if (num > 3) return; + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV0_ADDR + num*3, address); +} +/** Get the active internal register for the specified slave (0-3). + * Read/write operations for this slave will be done to whatever internal + * register address is stored in this MPU register. + * + * The MPU-6050 supports a total of five slaves, but Slave 4 has unique + * characteristics, and so it has its own functions. + * + * @param num Slave number (0-3) + * @return Current active register for specified slave + * @see MPU6050_RA_I2C_SLV0_REG + */ +uint8_t MPU6050::getSlaveRegister(uint8_t num) { + if (num > 3) return 0; + I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV0_REG + num*3, buffer); + return buffer[0]; +} +/** Set the active internal register for the specified slave (0-3). + * @param num Slave number (0-3) + * @param reg New active register for specified slave + * @see getSlaveRegister() + * @see MPU6050_RA_I2C_SLV0_REG + */ +void MPU6050::setSlaveRegister(uint8_t num, uint8_t reg) { + if (num > 3) return; + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV0_REG + num*3, reg); +} +/** Get the enabled value for the specified slave (0-3). + * When set to 1, this bit enables Slave 0 for data transfer operations. When + * cleared to 0, this bit disables Slave 0 from data transfer operations. + * @param num Slave number (0-3) + * @return Current enabled value for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +bool MPU6050::getSlaveEnabled(uint8_t num) { + if (num > 3) return 0; + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_EN_BIT, buffer); + return buffer[0]; +} +/** Set the enabled value for the specified slave (0-3). + * @param num Slave number (0-3) + * @param enabled New enabled value for specified slave + * @see getSlaveEnabled() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050::setSlaveEnabled(uint8_t num, bool enabled) { + if (num > 3) return; + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_EN_BIT, enabled); +} +/** Get word pair byte-swapping enabled for the specified slave (0-3). + * When set to 1, this bit enables byte swapping. When byte swapping is enabled, + * the high and low bytes of a word pair are swapped. Please refer to + * I2C_SLV0_GRP for the pairing convention of the word pairs. When cleared to 0, + * bytes transferred to and from Slave 0 will be written to EXT_SENS_DATA + * registers in the order they were transferred. + * + * @param num Slave number (0-3) + * @return Current word pair byte-swapping enabled value for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +bool MPU6050::getSlaveWordByteSwap(uint8_t num) { + if (num > 3) return 0; + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_BYTE_SW_BIT, buffer); + return buffer[0]; +} +/** Set word pair byte-swapping enabled for the specified slave (0-3). + * @param num Slave number (0-3) + * @param enabled New word pair byte-swapping enabled value for specified slave + * @see getSlaveWordByteSwap() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050::setSlaveWordByteSwap(uint8_t num, bool enabled) { + if (num > 3) return; + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_BYTE_SW_BIT, enabled); +} +/** Get write mode for the specified slave (0-3). + * When set to 1, the transaction will read or write data only. When cleared to + * 0, the transaction will write a register address prior to reading or writing + * data. This should equal 0 when specifying the register address within the + * Slave device to/from which the ensuing data transaction will take place. + * + * @param num Slave number (0-3) + * @return Current write mode for specified slave (0 = register address + data, 1 = data only) + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +bool MPU6050::getSlaveWriteMode(uint8_t num) { + if (num > 3) return 0; + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_REG_DIS_BIT, buffer); + return buffer[0]; +} +/** Set write mode for the specified slave (0-3). + * @param num Slave number (0-3) + * @param mode New write mode for specified slave (0 = register address + data, 1 = data only) + * @see getSlaveWriteMode() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050::setSlaveWriteMode(uint8_t num, bool mode) { + if (num > 3) return; + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_REG_DIS_BIT, mode); +} +/** Get word pair grouping order offset for the specified slave (0-3). + * This sets specifies the grouping order of word pairs received from registers. + * When cleared to 0, bytes from register addresses 0 and 1, 2 and 3, etc (even, + * then odd register addresses) are paired to form a word. When set to 1, bytes + * from register addresses are paired 1 and 2, 3 and 4, etc. (odd, then even + * register addresses) are paired to form a word. + * + * @param num Slave number (0-3) + * @return Current word pair grouping order offset for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +bool MPU6050::getSlaveWordGroupOffset(uint8_t num) { + if (num > 3) return 0; + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_GRP_BIT, buffer); + return buffer[0]; +} +/** Set word pair grouping order offset for the specified slave (0-3). + * @param num Slave number (0-3) + * @param enabled New word pair grouping order offset for specified slave + * @see getSlaveWordGroupOffset() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050::setSlaveWordGroupOffset(uint8_t num, bool enabled) { + if (num > 3) return; + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_GRP_BIT, enabled); +} +/** Get number of bytes to read for the specified slave (0-3). + * Specifies the number of bytes transferred to and from Slave 0. Clearing this + * bit to 0 is equivalent to disabling the register by writing 0 to I2C_SLV0_EN. + * @param num Slave number (0-3) + * @return Number of bytes to read for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +uint8_t MPU6050::getSlaveDataLength(uint8_t num) { + if (num > 3) return 0; + I2Cdev::readBits(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_LEN_BIT, MPU6050_I2C_SLV_LEN_LENGTH, buffer); + return buffer[0]; +} +/** Set number of bytes to read for the specified slave (0-3). + * @param num Slave number (0-3) + * @param length Number of bytes to read for specified slave + * @see getSlaveDataLength() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050::setSlaveDataLength(uint8_t num, uint8_t length) { + if (num > 3) return; + I2Cdev::writeBits(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_LEN_BIT, MPU6050_I2C_SLV_LEN_LENGTH, length); +} + +// I2C_SLV* registers (Slave 4) + +/** Get the I2C address of Slave 4. + * Note that Bit 7 (MSB) controls read/write mode. If Bit 7 is set, it's a read + * operation, and if it is cleared, then it's a write operation. The remaining + * bits (6-0) are the 7-bit device address of the slave device. + * + * @return Current address for Slave 4 + * @see getSlaveAddress() + * @see MPU6050_RA_I2C_SLV4_ADDR + */ +uint8_t MPU6050::getSlave4Address() { + I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV4_ADDR, buffer); + return buffer[0]; +} +/** Set the I2C address of Slave 4. + * @param address New address for Slave 4 + * @see getSlave4Address() + * @see MPU6050_RA_I2C_SLV4_ADDR + */ +void MPU6050::setSlave4Address(uint8_t address) { + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV4_ADDR, address); +} +/** Get the active internal register for the Slave 4. + * Read/write operations for this slave will be done to whatever internal + * register address is stored in this MPU register. + * + * @return Current active register for Slave 4 + * @see MPU6050_RA_I2C_SLV4_REG + */ +uint8_t MPU6050::getSlave4Register() { + I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV4_REG, buffer); + return buffer[0]; +} +/** Set the active internal register for Slave 4. + * @param reg New active register for Slave 4 + * @see getSlave4Register() + * @see MPU6050_RA_I2C_SLV4_REG + */ +void MPU6050::setSlave4Register(uint8_t reg) { + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV4_REG, reg); +} +/** Set new byte to write to Slave 4. + * This register stores the data to be written into the Slave 4. If I2C_SLV4_RW + * is set 1 (set to read), this register has no effect. + * @param data New byte to write to Slave 4 + * @see MPU6050_RA_I2C_SLV4_DO + */ +void MPU6050::setSlave4OutputByte(uint8_t data) { + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV4_DO, data); +} +/** Get the enabled value for the Slave 4. + * When set to 1, this bit enables Slave 4 for data transfer operations. When + * cleared to 0, this bit disables Slave 4 from data transfer operations. + * @return Current enabled value for Slave 4 + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +bool MPU6050::getSlave4Enabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_EN_BIT, buffer); + return buffer[0]; +} +/** Set the enabled value for Slave 4. + * @param enabled New enabled value for Slave 4 + * @see getSlave4Enabled() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050::setSlave4Enabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_EN_BIT, enabled); +} +/** Get the enabled value for Slave 4 transaction interrupts. + * When set to 1, this bit enables the generation of an interrupt signal upon + * completion of a Slave 4 transaction. When cleared to 0, this bit disables the + * generation of an interrupt signal upon completion of a Slave 4 transaction. + * The interrupt status can be observed in Register 54. + * + * @return Current enabled value for Slave 4 transaction interrupts. + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +bool MPU6050::getSlave4InterruptEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_INT_EN_BIT, buffer); + return buffer[0]; +} +/** Set the enabled value for Slave 4 transaction interrupts. + * @param enabled New enabled value for Slave 4 transaction interrupts. + * @see getSlave4InterruptEnabled() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050::setSlave4InterruptEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_INT_EN_BIT, enabled); +} +/** Get write mode for Slave 4. + * When set to 1, the transaction will read or write data only. When cleared to + * 0, the transaction will write a register address prior to reading or writing + * data. This should equal 0 when specifying the register address within the + * Slave device to/from which the ensuing data transaction will take place. + * + * @return Current write mode for Slave 4 (0 = register address + data, 1 = data only) + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +bool MPU6050::getSlave4WriteMode() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_REG_DIS_BIT, buffer); + return buffer[0]; +} +/** Set write mode for the Slave 4. + * @param mode New write mode for Slave 4 (0 = register address + data, 1 = data only) + * @see getSlave4WriteMode() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050::setSlave4WriteMode(bool mode) { + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_REG_DIS_BIT, mode); +} +/** Get Slave 4 master delay value. + * This configures the reduced access rate of I2C slaves relative to the Sample + * Rate. When a slave's access rate is decreased relative to the Sample Rate, + * the slave is accessed every: + * + * 1 / (1 + I2C_MST_DLY) samples + * + * This base Sample Rate in turn is determined by SMPLRT_DIV (register 25) and + * DLPF_CFG (register 26). Whether a slave's access rate is reduced relative to + * the Sample Rate is determined by I2C_MST_DELAY_CTRL (register 103). For + * further information regarding the Sample Rate, please refer to register 25. + * + * @return Current Slave 4 master delay value + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +uint8_t MPU6050::getSlave4MasterDelay() { + I2Cdev::readBits(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_MST_DLY_BIT, MPU6050_I2C_SLV4_MST_DLY_LENGTH, buffer); + return buffer[0]; +} +/** Set Slave 4 master delay value. + * @param delay New Slave 4 master delay value + * @see getSlave4MasterDelay() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050::setSlave4MasterDelay(uint8_t delay) { + I2Cdev::writeBits(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_MST_DLY_BIT, MPU6050_I2C_SLV4_MST_DLY_LENGTH, delay); +} +/** Get last available byte read from Slave 4. + * This register stores the data read from Slave 4. This field is populated + * after a read transaction. + * @return Last available byte read from to Slave 4 + * @see MPU6050_RA_I2C_SLV4_DI + */ +uint8_t MPU6050::getSlate4InputByte() { + I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV4_DI, buffer); + return buffer[0]; +} + +// I2C_MST_STATUS register + +/** Get FSYNC interrupt status. + * This bit reflects the status of the FSYNC interrupt from an external device + * into the MPU-60X0. This is used as a way to pass an external interrupt + * through the MPU-60X0 to the host application processor. When set to 1, this + * bit will cause an interrupt if FSYNC_INT_EN is asserted in INT_PIN_CFG + * (Register 55). + * @return FSYNC interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050::getPassthroughStatus() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_PASS_THROUGH_BIT, buffer); + return buffer[0]; +} +/** Get Slave 4 transaction done status. + * Automatically sets to 1 when a Slave 4 transaction has completed. This + * triggers an interrupt if the I2C_MST_INT_EN bit in the INT_ENABLE register + * (Register 56) is asserted and if the SLV_4_DONE_INT bit is asserted in the + * I2C_SLV4_CTRL register (Register 52). + * @return Slave 4 transaction done status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050::getSlave4IsDone() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV4_DONE_BIT, buffer); + return buffer[0]; +} +/** Get master arbitration lost status. + * This bit automatically sets to 1 when the I2C Master has lost arbitration of + * the auxiliary I2C bus (an error condition). This triggers an interrupt if the + * I2C_MST_INT_EN bit in the INT_ENABLE register (Register 56) is asserted. + * @return Master arbitration lost status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050::getLostArbitration() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_LOST_ARB_BIT, buffer); + return buffer[0]; +} +/** Get Slave 4 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 4. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 4 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050::getSlave4Nack() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV4_NACK_BIT, buffer); + return buffer[0]; +} +/** Get Slave 3 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 3. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 3 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050::getSlave3Nack() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV3_NACK_BIT, buffer); + return buffer[0]; +} +/** Get Slave 2 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 2. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 2 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050::getSlave2Nack() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV2_NACK_BIT, buffer); + return buffer[0]; +} +/** Get Slave 1 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 1. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 1 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050::getSlave1Nack() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV1_NACK_BIT, buffer); + return buffer[0]; +} +/** Get Slave 0 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 0. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 0 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050::getSlave0Nack() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV0_NACK_BIT, buffer); + return buffer[0]; +} + +// INT_PIN_CFG register + +/** Get interrupt logic level mode. + * Will be set 0 for active-high, 1 for active-low. + * @return Current interrupt mode (0=active-high, 1=active-low) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_LEVEL_BIT + */ +bool MPU6050::getInterruptMode() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_LEVEL_BIT, buffer); + return buffer[0]; +} +/** Set interrupt logic level mode. + * @param mode New interrupt mode (0=active-high, 1=active-low) + * @see getInterruptMode() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_LEVEL_BIT + */ +void MPU6050::setInterruptMode(bool mode) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_LEVEL_BIT, mode); +} +/** Get interrupt drive mode. + * Will be set 0 for push-pull, 1 for open-drain. + * @return Current interrupt drive mode (0=push-pull, 1=open-drain) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_OPEN_BIT + */ +bool MPU6050::getInterruptDrive() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_OPEN_BIT, buffer); + return buffer[0]; +} +/** Set interrupt drive mode. + * @param drive New interrupt drive mode (0=push-pull, 1=open-drain) + * @see getInterruptDrive() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_OPEN_BIT + */ +void MPU6050::setInterruptDrive(bool drive) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_OPEN_BIT, drive); +} +/** Get interrupt latch mode. + * Will be set 0 for 50us-pulse, 1 for latch-until-int-cleared. + * @return Current latch mode (0=50us-pulse, 1=latch-until-int-cleared) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_LATCH_INT_EN_BIT + */ +bool MPU6050::getInterruptLatch() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_LATCH_INT_EN_BIT, buffer); + return buffer[0]; +} +/** Set interrupt latch mode. + * @param latch New latch mode (0=50us-pulse, 1=latch-until-int-cleared) + * @see getInterruptLatch() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_LATCH_INT_EN_BIT + */ +void MPU6050::setInterruptLatch(bool latch) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_LATCH_INT_EN_BIT, latch); +} +/** Get interrupt latch clear mode. + * Will be set 0 for status-read-only, 1 for any-register-read. + * @return Current latch clear mode (0=status-read-only, 1=any-register-read) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_RD_CLEAR_BIT + */ +bool MPU6050::getInterruptLatchClear() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_RD_CLEAR_BIT, buffer); + return buffer[0]; +} +/** Set interrupt latch clear mode. + * @param clear New latch clear mode (0=status-read-only, 1=any-register-read) + * @see getInterruptLatchClear() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_RD_CLEAR_BIT + */ +void MPU6050::setInterruptLatchClear(bool clear) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_RD_CLEAR_BIT, clear); +} +/** Get FSYNC interrupt logic level mode. + * @return Current FSYNC interrupt mode (0=active-high, 1=active-low) + * @see getFSyncInterruptMode() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT + */ +bool MPU6050::getFSyncInterruptLevel() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT, buffer); + return buffer[0]; +} +/** Set FSYNC interrupt logic level mode. + * @param mode New FSYNC interrupt mode (0=active-high, 1=active-low) + * @see getFSyncInterruptMode() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT + */ +void MPU6050::setFSyncInterruptLevel(bool level) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT, level); +} +/** Get FSYNC pin interrupt enabled setting. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled setting + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_EN_BIT + */ +bool MPU6050::getFSyncInterruptEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_EN_BIT, buffer); + return buffer[0]; +} +/** Set FSYNC pin interrupt enabled setting. + * @param enabled New FSYNC pin interrupt enabled setting + * @see getFSyncInterruptEnabled() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_EN_BIT + */ +void MPU6050::setFSyncInterruptEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_EN_BIT, enabled); +} +/** Get I2C bypass enabled status. + * When this bit is equal to 1 and I2C_MST_EN (Register 106 bit[5]) is equal to + * 0, the host application processor will be able to directly access the + * auxiliary I2C bus of the MPU-60X0. When this bit is equal to 0, the host + * application processor will not be able to directly access the auxiliary I2C + * bus of the MPU-60X0 regardless of the state of I2C_MST_EN (Register 106 + * bit[5]). + * @return Current I2C bypass enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_I2C_BYPASS_EN_BIT + */ +bool MPU6050::getI2CBypassEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_I2C_BYPASS_EN_BIT, buffer); + return buffer[0]; +} +/** Set I2C bypass enabled status. + * When this bit is equal to 1 and I2C_MST_EN (Register 106 bit[5]) is equal to + * 0, the host application processor will be able to directly access the + * auxiliary I2C bus of the MPU-60X0. When this bit is equal to 0, the host + * application processor will not be able to directly access the auxiliary I2C + * bus of the MPU-60X0 regardless of the state of I2C_MST_EN (Register 106 + * bit[5]). + * @param enabled New I2C bypass enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_I2C_BYPASS_EN_BIT + */ +void MPU6050::setI2CBypassEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_I2C_BYPASS_EN_BIT, enabled); +} +/** Get reference clock output enabled status. + * When this bit is equal to 1, a reference clock output is provided at the + * CLKOUT pin. When this bit is equal to 0, the clock output is disabled. For + * further information regarding CLKOUT, please refer to the MPU-60X0 Product + * Specification document. + * @return Current reference clock output enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_CLKOUT_EN_BIT + */ +bool MPU6050::getClockOutputEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_CLKOUT_EN_BIT, buffer); + return buffer[0]; +} +/** Set reference clock output enabled status. + * When this bit is equal to 1, a reference clock output is provided at the + * CLKOUT pin. When this bit is equal to 0, the clock output is disabled. For + * further information regarding CLKOUT, please refer to the MPU-60X0 Product + * Specification document. + * @param enabled New reference clock output enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_CLKOUT_EN_BIT + */ +void MPU6050::setClockOutputEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_CLKOUT_EN_BIT, enabled); +} + +// INT_ENABLE register + +/** Get full interrupt enabled status. + * Full register byte for all interrupts, for quick reading. Each bit will be + * set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +uint8_t MPU6050::getIntEnabled() { + I2Cdev::readByte(devAddr, MPU6050_RA_INT_ENABLE, buffer); + return buffer[0]; +} +/** Set full interrupt enabled status. + * Full register byte for all interrupts, for quick reading. Each bit should be + * set 0 for disabled, 1 for enabled. + * @param enabled New interrupt enabled status + * @see getIntFreefallEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +void MPU6050::setIntEnabled(uint8_t enabled) { + I2Cdev::writeByte(devAddr, MPU6050_RA_INT_ENABLE, enabled); +} +/** Get Free Fall interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +bool MPU6050::getIntFreefallEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FF_BIT, buffer); + return buffer[0]; +} +/** Set Free Fall interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntFreefallEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +void MPU6050::setIntFreefallEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FF_BIT, enabled); +} +/** Get Motion Detection interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_MOT_BIT + **/ +bool MPU6050::getIntMotionEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_MOT_BIT, buffer); + return buffer[0]; +} +/** Set Motion Detection interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntMotionEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_MOT_BIT + **/ +void MPU6050::setIntMotionEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_MOT_BIT, enabled); +} +/** Get Zero Motion Detection interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_ZMOT_BIT + **/ +bool MPU6050::getIntZeroMotionEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_ZMOT_BIT, buffer); + return buffer[0]; +} +/** Set Zero Motion Detection interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntZeroMotionEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_ZMOT_BIT + **/ +void MPU6050::setIntZeroMotionEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_ZMOT_BIT, enabled); +} +/** Get FIFO Buffer Overflow interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT + **/ +bool MPU6050::getIntFIFOBufferOverflowEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, buffer); + return buffer[0]; +} +/** Set FIFO Buffer Overflow interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntFIFOBufferOverflowEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT + **/ +void MPU6050::setIntFIFOBufferOverflowEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, enabled); +} +/** Get I2C Master interrupt enabled status. + * This enables any of the I2C Master interrupt sources to generate an + * interrupt. Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT + **/ +bool MPU6050::getIntI2CMasterEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_I2C_MST_INT_BIT, buffer); + return buffer[0]; +} +/** Set I2C Master interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntI2CMasterEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT + **/ +void MPU6050::setIntI2CMasterEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_I2C_MST_INT_BIT, enabled); +} +/** Get Data Ready interrupt enabled setting. + * This event occurs each time a write operation to all of the sensor registers + * has been completed. Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_DATA_RDY_BIT + */ +bool MPU6050::getIntDataReadyEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DATA_RDY_BIT, buffer); + return buffer[0]; +} +/** Set Data Ready interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntDataReadyEnabled() + * @see MPU6050_RA_INT_CFG + * @see MPU6050_INTERRUPT_DATA_RDY_BIT + */ +void MPU6050::setIntDataReadyEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DATA_RDY_BIT, enabled); +} + +// INT_STATUS register + +/** Get full set of interrupt status bits. + * These bits clear to 0 after the register has been read. Very useful + * for getting multiple INT statuses, since each single bit read clears + * all of them because it has to read the whole byte. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + */ +uint8_t MPU6050::getIntStatus() { + I2Cdev::readByte(devAddr, MPU6050_RA_INT_STATUS, buffer); + return buffer[0]; +} +/** Get Free Fall interrupt status. + * This bit automatically sets to 1 when a Free Fall interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_FF_BIT + */ +bool MPU6050::getIntFreefallStatus() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_FF_BIT, buffer); + return buffer[0]; +} +/** Get Motion Detection interrupt status. + * This bit automatically sets to 1 when a Motion Detection interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_MOT_BIT + */ +bool MPU6050::getIntMotionStatus() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_MOT_BIT, buffer); + return buffer[0]; +} +/** Get Zero Motion Detection interrupt status. + * This bit automatically sets to 1 when a Zero Motion Detection interrupt has + * been generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_ZMOT_BIT + */ +bool MPU6050::getIntZeroMotionStatus() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_ZMOT_BIT, buffer); + return buffer[0]; +} +/** Get FIFO Buffer Overflow interrupt status. + * This bit automatically sets to 1 when a Free Fall interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT + */ +bool MPU6050::getIntFIFOBufferOverflowStatus() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, buffer); + return buffer[0]; +} +/** Get I2C Master interrupt status. + * This bit automatically sets to 1 when an I2C Master interrupt has been + * generated. For a list of I2C Master interrupts, please refer to Register 54. + * The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT + */ +bool MPU6050::getIntI2CMasterStatus() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_I2C_MST_INT_BIT, buffer); + return buffer[0]; +} +/** Get Data Ready interrupt status. + * This bit automatically sets to 1 when a Data Ready interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_DATA_RDY_BIT + */ +bool MPU6050::getIntDataReadyStatus() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_DATA_RDY_BIT, buffer); + return buffer[0]; +} + +// ACCEL_*OUT_* registers + +/** Get raw 9-axis motion sensor readings (accel/gyro/compass). + * FUNCTION NOT FULLY IMPLEMENTED YET. + * @param ax 16-bit signed integer container for accelerometer X-axis value + * @param ay 16-bit signed integer container for accelerometer Y-axis value + * @param az 16-bit signed integer container for accelerometer Z-axis value + * @param gx 16-bit signed integer container for gyroscope X-axis value + * @param gy 16-bit signed integer container for gyroscope Y-axis value + * @param gz 16-bit signed integer container for gyroscope Z-axis value + * @param mx 16-bit signed integer container for magnetometer X-axis value + * @param my 16-bit signed integer container for magnetometer Y-axis value + * @param mz 16-bit signed integer container for magnetometer Z-axis value + * @see getMotion6() + * @see getAcceleration() + * @see getRotation() + * @see MPU6050_RA_ACCEL_XOUT_H + */ +void MPU6050::getMotion9(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz, int16_t* mx, int16_t* my, int16_t* mz) { + getMotion6(ax, ay, az, gx, gy, gz); + // TODO: magnetometer integration +} +/** Get raw 6-axis motion sensor readings (accel/gyro). + * Retrieves all currently available motion sensor values. + * @param ax 16-bit signed integer container for accelerometer X-axis value + * @param ay 16-bit signed integer container for accelerometer Y-axis value + * @param az 16-bit signed integer container for accelerometer Z-axis value + * @param gx 16-bit signed integer container for gyroscope X-axis value + * @param gy 16-bit signed integer container for gyroscope Y-axis value + * @param gz 16-bit signed integer container for gyroscope Z-axis value + * @see getAcceleration() + * @see getRotation() + * @see MPU6050_RA_ACCEL_XOUT_H + */ +void MPU6050::getMotion6(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz) { + I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_XOUT_H, 14, buffer); + *ax = (((int16_t)buffer[0]) << 8) | buffer[1]; + *ay = (((int16_t)buffer[2]) << 8) | buffer[3]; + *az = (((int16_t)buffer[4]) << 8) | buffer[5]; + *gx = (((int16_t)buffer[8]) << 8) | buffer[9]; + *gy = (((int16_t)buffer[10]) << 8) | buffer[11]; + *gz = (((int16_t)buffer[12]) << 8) | buffer[13]; +} +/** Get 3-axis accelerometer readings. + * These registers store the most recent accelerometer measurements. + * Accelerometer measurements are written to these registers at the Sample Rate + * as defined in Register 25. + * + * The accelerometer measurement registers, along with the temperature + * measurement registers, gyroscope measurement registers, and external sensor + * data registers, are composed of two sets of registers: an internal register + * set and a user-facing read register set. + * + * The data within the accelerometer sensors' internal register set is always + * updated at the Sample Rate. Meanwhile, the user-facing read register set + * duplicates the internal register set's data values whenever the serial + * interface is idle. This guarantees that a burst read of sensor registers will + * read measurements from the same sampling instant. Note that if burst reads + * are not used, the user is responsible for ensuring a set of single byte reads + * correspond to a single sampling instant by checking the Data Ready interrupt. + * + * Each 16-bit accelerometer measurement has a full scale defined in ACCEL_FS + * (Register 28). For each full scale setting, the accelerometers' sensitivity + * per LSB in ACCEL_xOUT is shown in the table below: + * + *
+ * AFS_SEL | Full Scale Range | LSB Sensitivity
+ * --------+------------------+----------------
+ * 0       | +/- 2g           | 8192 LSB/mg
+ * 1       | +/- 4g           | 4096 LSB/mg
+ * 2       | +/- 8g           | 2048 LSB/mg
+ * 3       | +/- 16g          | 1024 LSB/mg
+ * 
+ * + * @param x 16-bit signed integer container for X-axis acceleration + * @param y 16-bit signed integer container for Y-axis acceleration + * @param z 16-bit signed integer container for Z-axis acceleration + * @see MPU6050_RA_GYRO_XOUT_H + */ +void MPU6050::getAcceleration(int16_t* x, int16_t* y, int16_t* z) { + I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_XOUT_H, 6, buffer); + *x = (((int16_t)buffer[0]) << 8) | buffer[1]; + *y = (((int16_t)buffer[2]) << 8) | buffer[3]; + *z = (((int16_t)buffer[4]) << 8) | buffer[5]; +} +/** Get X-axis accelerometer reading. + * @return X-axis acceleration measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_ACCEL_XOUT_H + */ +int16_t MPU6050::getAccelerationX() { + I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_XOUT_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +/** Get Y-axis accelerometer reading. + * @return Y-axis acceleration measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_ACCEL_YOUT_H + */ +int16_t MPU6050::getAccelerationY() { + I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_YOUT_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +/** Get Z-axis accelerometer reading. + * @return Z-axis acceleration measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_ACCEL_ZOUT_H + */ +int16_t MPU6050::getAccelerationZ() { + I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_ZOUT_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} + +// TEMP_OUT_* registers + +/** Get current internal temperature. + * @return Temperature reading in 16-bit 2's complement format + * @see MPU6050_RA_TEMP_OUT_H + */ +int16_t MPU6050::getTemperature() { + I2Cdev::readBytes(devAddr, MPU6050_RA_TEMP_OUT_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} + +// GYRO_*OUT_* registers + +/** Get 3-axis gyroscope readings. + * These gyroscope measurement registers, along with the accelerometer + * measurement registers, temperature measurement registers, and external sensor + * data registers, are composed of two sets of registers: an internal register + * set and a user-facing read register set. + * The data within the gyroscope sensors' internal register set is always + * updated at the Sample Rate. Meanwhile, the user-facing read register set + * duplicates the internal register set's data values whenever the serial + * interface is idle. This guarantees that a burst read of sensor registers will + * read measurements from the same sampling instant. Note that if burst reads + * are not used, the user is responsible for ensuring a set of single byte reads + * correspond to a single sampling instant by checking the Data Ready interrupt. + * + * Each 16-bit gyroscope measurement has a full scale defined in FS_SEL + * (Register 27). For each full scale setting, the gyroscopes' sensitivity per + * LSB in GYRO_xOUT is shown in the table below: + * + *
+ * FS_SEL | Full Scale Range   | LSB Sensitivity
+ * -------+--------------------+----------------
+ * 0      | +/- 250 degrees/s  | 131 LSB/deg/s
+ * 1      | +/- 500 degrees/s  | 65.5 LSB/deg/s
+ * 2      | +/- 1000 degrees/s | 32.8 LSB/deg/s
+ * 3      | +/- 2000 degrees/s | 16.4 LSB/deg/s
+ * 
+ * + * @param x 16-bit signed integer container for X-axis rotation + * @param y 16-bit signed integer container for Y-axis rotation + * @param z 16-bit signed integer container for Z-axis rotation + * @see getMotion6() + * @see MPU6050_RA_GYRO_XOUT_H + */ +void MPU6050::getRotation(int16_t* x, int16_t* y, int16_t* z) { + I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_XOUT_H, 6, buffer); + *x = (((int16_t)buffer[0]) << 8) | buffer[1]; + *y = (((int16_t)buffer[2]) << 8) | buffer[3]; + *z = (((int16_t)buffer[4]) << 8) | buffer[5]; +} +/** Get X-axis gyroscope reading. + * @return X-axis rotation measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_GYRO_XOUT_H + */ +int16_t MPU6050::getRotationX() { + I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_XOUT_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +/** Get Y-axis gyroscope reading. + * @return Y-axis rotation measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_GYRO_YOUT_H + */ +int16_t MPU6050::getRotationY() { + I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_YOUT_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +/** Get Z-axis gyroscope reading. + * @return Z-axis rotation measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_GYRO_ZOUT_H + */ +int16_t MPU6050::getRotationZ() { + I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_ZOUT_H, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} + +// EXT_SENS_DATA_* registers + +/** Read single byte from external sensor data register. + * These registers store data read from external sensors by the Slave 0, 1, 2, + * and 3 on the auxiliary I2C interface. Data read by Slave 4 is stored in + * I2C_SLV4_DI (Register 53). + * + * External sensor data is written to these registers at the Sample Rate as + * defined in Register 25. This access rate can be reduced by using the Slave + * Delay Enable registers (Register 103). + * + * External sensor data registers, along with the gyroscope measurement + * registers, accelerometer measurement registers, and temperature measurement + * registers, are composed of two sets of registers: an internal register set + * and a user-facing read register set. + * + * The data within the external sensors' internal register set is always updated + * at the Sample Rate (or the reduced access rate) whenever the serial interface + * is idle. This guarantees that a burst read of sensor registers will read + * measurements from the same sampling instant. Note that if burst reads are not + * used, the user is responsible for ensuring a set of single byte reads + * correspond to a single sampling instant by checking the Data Ready interrupt. + * + * Data is placed in these external sensor data registers according to + * I2C_SLV0_CTRL, I2C_SLV1_CTRL, I2C_SLV2_CTRL, and I2C_SLV3_CTRL (Registers 39, + * 42, 45, and 48). When more than zero bytes are read (I2C_SLVx_LEN > 0) from + * an enabled slave (I2C_SLVx_EN = 1), the slave is read at the Sample Rate (as + * defined in Register 25) or delayed rate (if specified in Register 52 and + * 103). During each Sample cycle, slave reads are performed in order of Slave + * number. If all slaves are enabled with more than zero bytes to be read, the + * order will be Slave 0, followed by Slave 1, Slave 2, and Slave 3. + * + * Each enabled slave will have EXT_SENS_DATA registers associated with it by + * number of bytes read (I2C_SLVx_LEN) in order of slave number, starting from + * EXT_SENS_DATA_00. Note that this means enabling or disabling a slave may + * change the higher numbered slaves' associated registers. Furthermore, if + * fewer total bytes are being read from the external sensors as a result of + * such a change, then the data remaining in the registers which no longer have + * an associated slave device (i.e. high numbered registers) will remain in + * these previously allocated registers unless reset. + * + * If the sum of the read lengths of all SLVx transactions exceed the number of + * available EXT_SENS_DATA registers, the excess bytes will be dropped. There + * are 24 EXT_SENS_DATA registers and hence the total read lengths between all + * the slaves cannot be greater than 24 or some bytes will be lost. + * + * Note: Slave 4's behavior is distinct from that of Slaves 0-3. For further + * information regarding the characteristics of Slave 4, please refer to + * Registers 49 to 53. + * + * EXAMPLE: + * Suppose that Slave 0 is enabled with 4 bytes to be read (I2C_SLV0_EN = 1 and + * I2C_SLV0_LEN = 4) while Slave 1 is enabled with 2 bytes to be read so that + * I2C_SLV1_EN = 1 and I2C_SLV1_LEN = 2. In such a situation, EXT_SENS_DATA _00 + * through _03 will be associated with Slave 0, while EXT_SENS_DATA _04 and 05 + * will be associated with Slave 1. If Slave 2 is enabled as well, registers + * starting from EXT_SENS_DATA_06 will be allocated to Slave 2. + * + * If Slave 2 is disabled while Slave 3 is enabled in this same situation, then + * registers starting from EXT_SENS_DATA_06 will be allocated to Slave 3 + * instead. + * + * REGISTER ALLOCATION FOR DYNAMIC DISABLE VS. NORMAL DISABLE: + * If a slave is disabled at any time, the space initially allocated to the + * slave in the EXT_SENS_DATA register, will remain associated with that slave. + * This is to avoid dynamic adjustment of the register allocation. + * + * The allocation of the EXT_SENS_DATA registers is recomputed only when (1) all + * slaves are disabled, or (2) the I2C_MST_RST bit is set (Register 106). + * + * This above is also true if one of the slaves gets NACKed and stops + * functioning. + * + * @param position Starting position (0-23) + * @return Byte read from register + */ +uint8_t MPU6050::getExternalSensorByte(int position) { + I2Cdev::readByte(devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, buffer); + return buffer[0]; +} +/** Read word (2 bytes) from external sensor data registers. + * @param position Starting position (0-21) + * @return Word read from register + * @see getExternalSensorByte() + */ +uint16_t MPU6050::getExternalSensorWord(int position) { + I2Cdev::readBytes(devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, 2, buffer); + return (((uint16_t)buffer[0]) << 8) | buffer[1]; +} +/** Read double word (4 bytes) from external sensor data registers. + * @param position Starting position (0-20) + * @return Double word read from registers + * @see getExternalSensorByte() + */ +uint32_t MPU6050::getExternalSensorDWord(int position) { + I2Cdev::readBytes(devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, 4, buffer); + return (((uint32_t)buffer[0]) << 24) | (((uint32_t)buffer[1]) << 16) | (((uint16_t)buffer[2]) << 8) | buffer[3]; +} + +// MOT_DETECT_STATUS register + +/** Get full motion detection status register content (all bits). + * @return Motion detection status byte + * @see MPU6050_RA_MOT_DETECT_STATUS + */ +uint8_t MPU6050::getMotionStatus() { + I2Cdev::readByte(devAddr, MPU6050_RA_MOT_DETECT_STATUS, buffer); + return buffer[0]; +} +/** Get X-axis negative motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_XNEG_BIT + */ +bool MPU6050::getXNegMotionDetected() { + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_XNEG_BIT, buffer); + return buffer[0]; +} +/** Get X-axis positive motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_XPOS_BIT + */ +bool MPU6050::getXPosMotionDetected() { + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_XPOS_BIT, buffer); + return buffer[0]; +} +/** Get Y-axis negative motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_YNEG_BIT + */ +bool MPU6050::getYNegMotionDetected() { + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_YNEG_BIT, buffer); + return buffer[0]; +} +/** Get Y-axis positive motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_YPOS_BIT + */ +bool MPU6050::getYPosMotionDetected() { + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_YPOS_BIT, buffer); + return buffer[0]; +} +/** Get Z-axis negative motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_ZNEG_BIT + */ +bool MPU6050::getZNegMotionDetected() { + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZNEG_BIT, buffer); + return buffer[0]; +} +/** Get Z-axis positive motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_ZPOS_BIT + */ +bool MPU6050::getZPosMotionDetected() { + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZPOS_BIT, buffer); + return buffer[0]; +} +/** Get zero motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_ZRMOT_BIT + */ +bool MPU6050::getZeroMotionDetected() { + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZRMOT_BIT, buffer); + return buffer[0]; +} + +// I2C_SLV*_DO register + +/** Write byte to Data Output container for specified slave. + * This register holds the output data written into Slave when Slave is set to + * write mode. For further information regarding Slave control, please + * refer to Registers 37 to 39 and immediately following. + * @param num Slave number (0-3) + * @param data Byte to write + * @see MPU6050_RA_I2C_SLV0_DO + */ +void MPU6050::setSlaveOutputByte(uint8_t num, uint8_t data) { + if (num > 3) return; + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV0_DO + num, data); +} + +// I2C_MST_DELAY_CTRL register + +/** Get external data shadow delay enabled status. + * This register is used to specify the timing of external sensor data + * shadowing. When DELAY_ES_SHADOW is set to 1, shadowing of external + * sensor data is delayed until all data has been received. + * @return Current external data shadow delay enabled status. + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT + */ +bool MPU6050::getExternalShadowDelayEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT, buffer); + return buffer[0]; +} +/** Set external data shadow delay enabled status. + * @param enabled New external data shadow delay enabled status. + * @see getExternalShadowDelayEnabled() + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT + */ +void MPU6050::setExternalShadowDelayEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT, enabled); +} +/** Get slave delay enabled status. + * When a particular slave delay is enabled, the rate of access for the that + * slave device is reduced. When a slave's access rate is decreased relative to + * the Sample Rate, the slave is accessed every: + * + * 1 / (1 + I2C_MST_DLY) Samples + * + * This base Sample Rate in turn is determined by SMPLRT_DIV (register * 25) + * and DLPF_CFG (register 26). + * + * For further information regarding I2C_MST_DLY, please refer to register 52. + * For further information regarding the Sample Rate, please refer to register 25. + * + * @param num Slave number (0-4) + * @return Current slave delay enabled status. + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT + */ +bool MPU6050::getSlaveDelayEnabled(uint8_t num) { + // MPU6050_DELAYCTRL_I2C_SLV4_DLY_EN_BIT is 4, SLV3 is 3, etc. + if (num > 4) return 0; + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, num, buffer); + return buffer[0]; +} +/** Set slave delay enabled status. + * @param num Slave number (0-4) + * @param enabled New slave delay enabled status. + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT + */ +void MPU6050::setSlaveDelayEnabled(uint8_t num, bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, num, enabled); +} + +// SIGNAL_PATH_RESET register + +/** Reset gyroscope signal path. + * The reset will revert the signal path analog to digital converters and + * filters to their power up configurations. + * @see MPU6050_RA_SIGNAL_PATH_RESET + * @see MPU6050_PATHRESET_GYRO_RESET_BIT + */ +void MPU6050::resetGyroscopePath() { + I2Cdev::writeBit(devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_GYRO_RESET_BIT, true); +} +/** Reset accelerometer signal path. + * The reset will revert the signal path analog to digital converters and + * filters to their power up configurations. + * @see MPU6050_RA_SIGNAL_PATH_RESET + * @see MPU6050_PATHRESET_ACCEL_RESET_BIT + */ +void MPU6050::resetAccelerometerPath() { + I2Cdev::writeBit(devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_ACCEL_RESET_BIT, true); +} +/** Reset temperature sensor signal path. + * The reset will revert the signal path analog to digital converters and + * filters to their power up configurations. + * @see MPU6050_RA_SIGNAL_PATH_RESET + * @see MPU6050_PATHRESET_TEMP_RESET_BIT + */ +void MPU6050::resetTemperaturePath() { + I2Cdev::writeBit(devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_TEMP_RESET_BIT, true); +} + +// MOT_DETECT_CTRL register + +/** Get accelerometer power-on delay. + * The accelerometer data path provides samples to the sensor registers, Motion + * detection, Zero Motion detection, and Free Fall detection modules. The + * signal path contains filters which must be flushed on wake-up with new + * samples before the detection modules begin operations. The default wake-up + * delay, of 4ms can be lengthened by up to 3ms. This additional delay is + * specified in ACCEL_ON_DELAY in units of 1 LSB = 1 ms. The user may select + * any value above zero unless instructed otherwise by InvenSense. Please refer + * to Section 8 of the MPU-6000/MPU-6050 Product Specification document for + * further information regarding the detection modules. + * @return Current accelerometer power-on delay + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_ACCEL_ON_DELAY_BIT + */ +uint8_t MPU6050::getAccelerometerPowerOnDelay() { + I2Cdev::readBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_ACCEL_ON_DELAY_BIT, MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH, buffer); + return buffer[0]; +} +/** Set accelerometer power-on delay. + * @param delay New accelerometer power-on delay (0-3) + * @see getAccelerometerPowerOnDelay() + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_ACCEL_ON_DELAY_BIT + */ +void MPU6050::setAccelerometerPowerOnDelay(uint8_t delay) { + I2Cdev::writeBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_ACCEL_ON_DELAY_BIT, MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH, delay); +} +/** Get Free Fall detection counter decrement configuration. + * Detection is registered by the Free Fall detection module after accelerometer + * measurements meet their respective threshold conditions over a specified + * number of samples. When the threshold conditions are met, the corresponding + * detection counter increments by 1. The user may control the rate at which the + * detection counter decrements when the threshold condition is not met by + * configuring FF_COUNT. The decrement rate can be set according to the + * following table: + * + *
+ * FF_COUNT | Counter Decrement
+ * ---------+------------------
+ * 0        | Reset
+ * 1        | 1
+ * 2        | 2
+ * 3        | 4
+ * 
+ * + * When FF_COUNT is configured to 0 (reset), any non-qualifying sample will + * reset the counter to 0. For further information on Free Fall detection, + * please refer to Registers 29 to 32. + * + * @return Current decrement configuration + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_FF_COUNT_BIT + */ +uint8_t MPU6050::getFreefallDetectionCounterDecrement() { + I2Cdev::readBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_FF_COUNT_BIT, MPU6050_DETECT_FF_COUNT_LENGTH, buffer); + return buffer[0]; +} +/** Set Free Fall detection counter decrement configuration. + * @param decrement New decrement configuration value + * @see getFreefallDetectionCounterDecrement() + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_FF_COUNT_BIT + */ +void MPU6050::setFreefallDetectionCounterDecrement(uint8_t decrement) { + I2Cdev::writeBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_FF_COUNT_BIT, MPU6050_DETECT_FF_COUNT_LENGTH, decrement); +} +/** Get Motion detection counter decrement configuration. + * Detection is registered by the Motion detection module after accelerometer + * measurements meet their respective threshold conditions over a specified + * number of samples. When the threshold conditions are met, the corresponding + * detection counter increments by 1. The user may control the rate at which the + * detection counter decrements when the threshold condition is not met by + * configuring MOT_COUNT. The decrement rate can be set according to the + * following table: + * + *
+ * MOT_COUNT | Counter Decrement
+ * ----------+------------------
+ * 0         | Reset
+ * 1         | 1
+ * 2         | 2
+ * 3         | 4
+ * 
+ * + * When MOT_COUNT is configured to 0 (reset), any non-qualifying sample will + * reset the counter to 0. For further information on Motion detection, + * please refer to Registers 29 to 32. + * + */ +uint8_t MPU6050::getMotionDetectionCounterDecrement() { + I2Cdev::readBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_MOT_COUNT_BIT, MPU6050_DETECT_MOT_COUNT_LENGTH, buffer); + return buffer[0]; +} +/** Set Motion detection counter decrement configuration. + * @param decrement New decrement configuration value + * @see getMotionDetectionCounterDecrement() + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_MOT_COUNT_BIT + */ +void MPU6050::setMotionDetectionCounterDecrement(uint8_t decrement) { + I2Cdev::writeBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_MOT_COUNT_BIT, MPU6050_DETECT_MOT_COUNT_LENGTH, decrement); +} + +// USER_CTRL register + +/** Get FIFO enabled status. + * When this bit is set to 0, the FIFO buffer is disabled. The FIFO buffer + * cannot be written to or read from while disabled. The FIFO buffer's state + * does not change unless the MPU-60X0 is power cycled. + * @return Current FIFO enabled status + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_FIFO_EN_BIT + */ +bool MPU6050::getFIFOEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_EN_BIT, buffer); + return buffer[0]; +} +/** Set FIFO enabled status. + * @param enabled New FIFO enabled status + * @see getFIFOEnabled() + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_FIFO_EN_BIT + */ +void MPU6050::setFIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_EN_BIT, enabled); +} +/** Get I2C Master Mode enabled status. + * When this mode is enabled, the MPU-60X0 acts as the I2C Master to the + * external sensor slave devices on the auxiliary I2C bus. When this bit is + * cleared to 0, the auxiliary I2C bus lines (AUX_DA and AUX_CL) are logically + * driven by the primary I2C bus (SDA and SCL). This is a precondition to + * enabling Bypass Mode. For further information regarding Bypass Mode, please + * refer to Register 55. + * @return Current I2C Master Mode enabled status + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_I2C_MST_EN_BIT + */ +bool MPU6050::getI2CMasterModeEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_EN_BIT, buffer); + return buffer[0]; +} +/** Set I2C Master Mode enabled status. + * @param enabled New I2C Master Mode enabled status + * @see getI2CMasterModeEnabled() + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_I2C_MST_EN_BIT + */ +void MPU6050::setI2CMasterModeEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_EN_BIT, enabled); +} +/** Switch from I2C to SPI mode (MPU-6000 only) + * If this is set, the primary SPI interface will be enabled in place of the + * disabled primary I2C interface. + */ +void MPU6050::switchSPIEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_IF_DIS_BIT, enabled); +} +/** Reset the FIFO. + * This bit resets the FIFO buffer when set to 1 while FIFO_EN equals 0. This + * bit automatically clears to 0 after the reset has been triggered. + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_FIFO_RESET_BIT + */ +void MPU6050::resetFIFO() { + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_RESET_BIT, true); +} +/** Reset the I2C Master. + * This bit resets the I2C Master when set to 1 while I2C_MST_EN equals 0. + * This bit automatically clears to 0 after the reset has been triggered. + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_I2C_MST_RESET_BIT + */ +void MPU6050::resetI2CMaster() { + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_RESET_BIT, true); +} +/** Reset all sensor registers and signal paths. + * When set to 1, this bit resets the signal paths for all sensors (gyroscopes, + * accelerometers, and temperature sensor). This operation will also clear the + * sensor registers. This bit automatically clears to 0 after the reset has been + * triggered. + * + * When resetting only the signal path (and not the sensor registers), please + * use Register 104, SIGNAL_PATH_RESET. + * + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_SIG_COND_RESET_BIT + */ +void MPU6050::resetSensors() { + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_SIG_COND_RESET_BIT, true); +} + +// PWR_MGMT_1 register + +/** Trigger a full device reset. + * A small delay of ~50ms may be desirable after triggering a reset. + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_DEVICE_RESET_BIT + */ +void MPU6050::reset() { + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_DEVICE_RESET_BIT, true); +} +/** Get sleep mode status. + * Setting the SLEEP bit in the register puts the device into very low power + * sleep mode. In this mode, only the serial interface and internal registers + * remain active, allowing for a very low standby current. Clearing this bit + * puts the device back into normal mode. To save power, the individual standby + * selections for each of the gyros should be used if any gyro axis is not used + * by the application. + * @return Current sleep mode enabled status + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_SLEEP_BIT + */ +bool MPU6050::getSleepEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, buffer); + return buffer[0]; +} +/** Set sleep mode status. + * @param enabled New sleep mode enabled status + * @see getSleepEnabled() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_SLEEP_BIT + */ +void MPU6050::setSleepEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, enabled); +} +/** Get wake cycle enabled status. + * When this bit is set to 1 and SLEEP is disabled, the MPU-60X0 will cycle + * between sleep mode and waking up to take a single sample of data from active + * sensors at a rate determined by LP_WAKE_CTRL (register 108). + * @return Current sleep mode enabled status + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CYCLE_BIT + */ +bool MPU6050::getWakeCycleEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CYCLE_BIT, buffer); + return buffer[0]; +} +/** Set wake cycle enabled status. + * @param enabled New sleep mode enabled status + * @see getWakeCycleEnabled() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CYCLE_BIT + */ +void MPU6050::setWakeCycleEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CYCLE_BIT, enabled); +} +/** Get temperature sensor enabled status. + * Control the usage of the internal temperature sensor. + * + * Note: this register stores the *disabled* value, but for consistency with the + * rest of the code, the function is named and used with standard true/false + * values to indicate whether the sensor is enabled or disabled, respectively. + * + * @return Current temperature sensor enabled status + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_TEMP_DIS_BIT + */ +bool MPU6050::getTempSensorEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_TEMP_DIS_BIT, buffer); + return buffer[0] == 0; // 1 is actually disabled here +} +/** Set temperature sensor enabled status. + * Note: this register stores the *disabled* value, but for consistency with the + * rest of the code, the function is named and used with standard true/false + * values to indicate whether the sensor is enabled or disabled, respectively. + * + * @param enabled New temperature sensor enabled status + * @see getTempSensorEnabled() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_TEMP_DIS_BIT + */ +void MPU6050::setTempSensorEnabled(bool enabled) { + // 1 is actually disabled here + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_TEMP_DIS_BIT, !enabled); +} +/** Get clock source setting. + * @return Current clock source setting + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CLKSEL_BIT + * @see MPU6050_PWR1_CLKSEL_LENGTH + */ +uint8_t MPU6050::getClockSource() { + I2Cdev::readBits(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, buffer); + return buffer[0]; +} +/** Set clock source setting. + * An internal 8MHz oscillator, gyroscope based clock, or external sources can + * be selected as the MPU-60X0 clock source. When the internal 8 MHz oscillator + * or an external source is chosen as the clock source, the MPU-60X0 can operate + * in low power modes with the gyroscopes disabled. + * + * Upon power up, the MPU-60X0 clock source defaults to the internal oscillator. + * However, it is highly recommended that the device be configured to use one of + * the gyroscopes (or an external clock source) as the clock reference for + * improved stability. The clock source can be selected according to the following table: + * + *
+ * CLK_SEL | Clock Source
+ * --------+--------------------------------------
+ * 0       | Internal oscillator
+ * 1       | PLL with X Gyro reference
+ * 2       | PLL with Y Gyro reference
+ * 3       | PLL with Z Gyro reference
+ * 4       | PLL with external 32.768kHz reference
+ * 5       | PLL with external 19.2MHz reference
+ * 6       | Reserved
+ * 7       | Stops the clock and keeps the timing generator in reset
+ * 
+ * + * @param source New clock source setting + * @see getClockSource() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CLKSEL_BIT + * @see MPU6050_PWR1_CLKSEL_LENGTH + */ +void MPU6050::setClockSource(uint8_t source) { + I2Cdev::writeBits(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, source); +} + +// PWR_MGMT_2 register + +/** Get wake frequency in Accel-Only Low Power Mode. + * The MPU-60X0 can be put into Accerlerometer Only Low Power Mode by setting + * PWRSEL to 1 in the Power Management 1 register (Register 107). In this mode, + * the device will power off all devices except for the primary I2C interface, + * waking only the accelerometer at fixed intervals to take a single + * measurement. The frequency of wake-ups can be configured with LP_WAKE_CTRL + * as shown below: + * + *
+ * LP_WAKE_CTRL | Wake-up Frequency
+ * -------------+------------------
+ * 0            | 1.25 Hz
+ * 1            | 2.5 Hz
+ * 2            | 5 Hz
+ * 3            | 10 Hz
+ * 
+ * + * For further information regarding the MPU-60X0's power modes, please refer to + * Register 107. + * + * @return Current wake frequency + * @see MPU6050_RA_PWR_MGMT_2 + */ +uint8_t MPU6050::getWakeFrequency() { + I2Cdev::readBits(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_LP_WAKE_CTRL_BIT, MPU6050_PWR2_LP_WAKE_CTRL_LENGTH, buffer); + return buffer[0]; +} +/** Set wake frequency in Accel-Only Low Power Mode. + * @param frequency New wake frequency + * @see MPU6050_RA_PWR_MGMT_2 + */ +void MPU6050::setWakeFrequency(uint8_t frequency) { + I2Cdev::writeBits(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_LP_WAKE_CTRL_BIT, MPU6050_PWR2_LP_WAKE_CTRL_LENGTH, frequency); +} + +/** Get X-axis accelerometer standby enabled status. + * If enabled, the X-axis will not gather or report data (or use power). + * @return Current X-axis standby enabled status + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_XA_BIT + */ +bool MPU6050::getStandbyXAccelEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XA_BIT, buffer); + return buffer[0]; +} +/** Set X-axis accelerometer standby enabled status. + * @param New X-axis standby enabled status + * @see getStandbyXAccelEnabled() + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_XA_BIT + */ +void MPU6050::setStandbyXAccelEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XA_BIT, enabled); +} +/** Get Y-axis accelerometer standby enabled status. + * If enabled, the Y-axis will not gather or report data (or use power). + * @return Current Y-axis standby enabled status + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_YA_BIT + */ +bool MPU6050::getStandbyYAccelEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YA_BIT, buffer); + return buffer[0]; +} +/** Set Y-axis accelerometer standby enabled status. + * @param New Y-axis standby enabled status + * @see getStandbyYAccelEnabled() + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_YA_BIT + */ +void MPU6050::setStandbyYAccelEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YA_BIT, enabled); +} +/** Get Z-axis accelerometer standby enabled status. + * If enabled, the Z-axis will not gather or report data (or use power). + * @return Current Z-axis standby enabled status + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_ZA_BIT + */ +bool MPU6050::getStandbyZAccelEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZA_BIT, buffer); + return buffer[0]; +} +/** Set Z-axis accelerometer standby enabled status. + * @param New Z-axis standby enabled status + * @see getStandbyZAccelEnabled() + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_ZA_BIT + */ +void MPU6050::setStandbyZAccelEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZA_BIT, enabled); +} +/** Get X-axis gyroscope standby enabled status. + * If enabled, the X-axis will not gather or report data (or use power). + * @return Current X-axis standby enabled status + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_XG_BIT + */ +bool MPU6050::getStandbyXGyroEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XG_BIT, buffer); + return buffer[0]; +} +/** Set X-axis gyroscope standby enabled status. + * @param New X-axis standby enabled status + * @see getStandbyXGyroEnabled() + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_XG_BIT + */ +void MPU6050::setStandbyXGyroEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XG_BIT, enabled); +} +/** Get Y-axis gyroscope standby enabled status. + * If enabled, the Y-axis will not gather or report data (or use power). + * @return Current Y-axis standby enabled status + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_YG_BIT + */ +bool MPU6050::getStandbyYGyroEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YG_BIT, buffer); + return buffer[0]; +} +/** Set Y-axis gyroscope standby enabled status. + * @param New Y-axis standby enabled status + * @see getStandbyYGyroEnabled() + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_YG_BIT + */ +void MPU6050::setStandbyYGyroEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YG_BIT, enabled); +} +/** Get Z-axis gyroscope standby enabled status. + * If enabled, the Z-axis will not gather or report data (or use power). + * @return Current Z-axis standby enabled status + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_ZG_BIT + */ +bool MPU6050::getStandbyZGyroEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZG_BIT, buffer); + return buffer[0]; +} +/** Set Z-axis gyroscope standby enabled status. + * @param New Z-axis standby enabled status + * @see getStandbyZGyroEnabled() + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_ZG_BIT + */ +void MPU6050::setStandbyZGyroEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZG_BIT, enabled); +} + +// FIFO_COUNT* registers + +/** Get current FIFO buffer size. + * This value indicates the number of bytes stored in the FIFO buffer. This + * number is in turn the number of bytes that can be read from the FIFO buffer + * and it is directly proportional to the number of samples available given the + * set of sensor data bound to be stored in the FIFO (register 35 and 36). + * @return Current FIFO buffer size + */ +uint16_t MPU6050::getFIFOCount() { + I2Cdev::readBytes(devAddr, MPU6050_RA_FIFO_COUNTH, 2, buffer); + return (((uint16_t)buffer[0]) << 8) | buffer[1]; +} + +// FIFO_R_W register + +/** Get byte from FIFO buffer. + * This register is used to read and write data from the FIFO buffer. Data is + * written to the FIFO in order of register number (from lowest to highest). If + * all the FIFO enable flags (see below) are enabled and all External Sensor + * Data registers (Registers 73 to 96) are associated with a Slave device, the + * contents of registers 59 through 96 will be written in order at the Sample + * Rate. + * + * The contents of the sensor data registers (Registers 59 to 96) are written + * into the FIFO buffer when their corresponding FIFO enable flags are set to 1 + * in FIFO_EN (Register 35). An additional flag for the sensor data registers + * associated with I2C Slave 3 can be found in I2C_MST_CTRL (Register 36). + * + * If the FIFO buffer has overflowed, the status bit FIFO_OFLOW_INT is + * automatically set to 1. This bit is located in INT_STATUS (Register 58). + * When the FIFO buffer has overflowed, the oldest data will be lost and new + * data will be written to the FIFO. + * + * If the FIFO buffer is empty, reading this register will return the last byte + * that was previously read from the FIFO until new data is available. The user + * should check FIFO_COUNT to ensure that the FIFO buffer is not read when + * empty. + * + * @return Byte from FIFO buffer + */ +uint8_t MPU6050::getFIFOByte() { + I2Cdev::readByte(devAddr, MPU6050_RA_FIFO_R_W, buffer); + return buffer[0]; +} +void MPU6050::getFIFOBytes(uint8_t *data, uint8_t length) { + if(length > 0){ + I2Cdev::readBytes(devAddr, MPU6050_RA_FIFO_R_W, length, data); + } else { + *data = 0; + } +} + +/** Get latest byte from FIFO buffer no matter how much time has passed. + * === GetCurrentFIFOPacket === + * ================================================================ + * Returns 1) when nothing special was done + * 2) when recovering from overflow + * 0) when no valid data is available + * ================================================================ */ + int8_t MPU6050::GetCurrentFIFOPacket(uint8_t *data, uint8_t length) { // overflow proof + int16_t fifoC; + // This section of code is for when we allowed more than 1 packet to be acquired + //uint32_t BreakTimer = micros(); + uint32_t BreakTimer = time_us_32(); + do { + if ((fifoC = getFIFOCount()) > length) { + + if (fifoC > 200) { // if you waited to get the FIFO buffer to > 200 bytes it will take longer to get the last packet in the FIFO Buffer than it will take to reset the buffer and wait for the next to arrive + resetFIFO(); // Fixes any overflow corruption + fifoC = 0; + while (!(fifoC = getFIFOCount()) && ((time_us_32() - BreakTimer) <= (11000))); // Get Next New Packet + } else { //We have more than 1 packet but less than 200 bytes of data in the FIFO Buffer + uint8_t Trash[BUFFER_LENGTH]; + while ((fifoC = getFIFOCount()) > length) { // Test each time just in case the MPU is writing to the FIFO Buffer + fifoC = fifoC - length; // Save the last packet + uint16_t RemoveBytes; + while (fifoC) { // fifo count will reach zero so this is safe + RemoveBytes = MIN((int)fifoC, BUFFER_LENGTH); // Buffer Length is different than the packet length this will efficiently clear the buffer + getFIFOBytes(Trash, (uint8_t)RemoveBytes); + fifoC -= RemoveBytes; + } + } + } + } + if (!fifoC) return 0; // Called too early no data or we timed out after FIFO Reset + // We have 1 packet + if ((time_us_32() - BreakTimer) > (11000)) return 0; + } while (fifoC != length); + getFIFOBytes(data, length); //Get 1 packet + return 1; +} + + +/** Write byte to FIFO buffer. + * @see getFIFOByte() + * @see MPU6050_RA_FIFO_R_W + */ +void MPU6050::setFIFOByte(uint8_t data) { + I2Cdev::writeByte(devAddr, MPU6050_RA_FIFO_R_W, data); +} + +// WHO_AM_I register + +/** Get Device ID. + * This register is used to verify the identity of the device (0b110100, 0x34). + * @return Device ID (6 bits only! should be 0x34) + * @see MPU6050_RA_WHO_AM_I + * @see MPU6050_WHO_AM_I_BIT + * @see MPU6050_WHO_AM_I_LENGTH + */ +uint8_t MPU6050::getDeviceID() { + I2Cdev::readBits(devAddr, MPU6050_RA_WHO_AM_I, MPU6050_WHO_AM_I_BIT, MPU6050_WHO_AM_I_LENGTH, buffer); + return buffer[0]; +} +/** Set Device ID. + * Write a new ID into the WHO_AM_I register (no idea why this should ever be + * necessary though). + * @param id New device ID to set. + * @see getDeviceID() + * @see MPU6050_RA_WHO_AM_I + * @see MPU6050_WHO_AM_I_BIT + * @see MPU6050_WHO_AM_I_LENGTH + */ +void MPU6050::setDeviceID(uint8_t id) { + I2Cdev::writeBits(devAddr, MPU6050_RA_WHO_AM_I, MPU6050_WHO_AM_I_BIT, MPU6050_WHO_AM_I_LENGTH, id); +} + +// ======== UNDOCUMENTED/DMP REGISTERS/METHODS ======== + +// XG_OFFS_TC register + +uint8_t MPU6050::getOTPBankValid() { + I2Cdev::readBit(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OTP_BNK_VLD_BIT, buffer); + return buffer[0]; +} +void MPU6050::setOTPBankValid(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OTP_BNK_VLD_BIT, enabled); +} +int8_t MPU6050::getXGyroOffsetTC() { + I2Cdev::readBits(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, buffer); + return buffer[0]; +} +void MPU6050::setXGyroOffsetTC(int8_t offset) { + I2Cdev::writeBits(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset); +} + +// YG_OFFS_TC register + +int8_t MPU6050::getYGyroOffsetTC() { + I2Cdev::readBits(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, buffer); + return buffer[0]; +} +void MPU6050::setYGyroOffsetTC(int8_t offset) { + I2Cdev::writeBits(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset); +} + +// ZG_OFFS_TC register + +int8_t MPU6050::getZGyroOffsetTC() { + I2Cdev::readBits(devAddr, MPU6050_RA_ZG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, buffer); + return buffer[0]; +} +void MPU6050::setZGyroOffsetTC(int8_t offset) { + I2Cdev::writeBits(devAddr, MPU6050_RA_ZG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset); +} + +// X_FINE_GAIN register + +int8_t MPU6050::getXFineGain() { + I2Cdev::readByte(devAddr, MPU6050_RA_X_FINE_GAIN, buffer); + return buffer[0]; +} +void MPU6050::setXFineGain(int8_t gain) { + I2Cdev::writeByte(devAddr, MPU6050_RA_X_FINE_GAIN, gain); +} + +// Y_FINE_GAIN register + +int8_t MPU6050::getYFineGain() { + I2Cdev::readByte(devAddr, MPU6050_RA_Y_FINE_GAIN, buffer); + return buffer[0]; +} +void MPU6050::setYFineGain(int8_t gain) { + I2Cdev::writeByte(devAddr, MPU6050_RA_Y_FINE_GAIN, gain); +} + +// Z_FINE_GAIN register + +int8_t MPU6050::getZFineGain() { + I2Cdev::readByte(devAddr, MPU6050_RA_Z_FINE_GAIN, buffer); + return buffer[0]; +} +void MPU6050::setZFineGain(int8_t gain) { + I2Cdev::writeByte(devAddr, MPU6050_RA_Z_FINE_GAIN, gain); +} + +// XA_OFFS_* registers + +int16_t MPU6050::getXAccelOffset() { + uint8_t SaveAddress = ((getDeviceID() < 0x38 )? MPU6050_RA_XA_OFFS_H:0x77); // MPU6050,MPU9150 Vs MPU6500,MPU9250 + I2Cdev::readBytes(devAddr, SaveAddress, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +void MPU6050::setXAccelOffset(int16_t offset) { + uint8_t SaveAddress = ((getDeviceID() < 0x38 )? MPU6050_RA_XA_OFFS_H:0x77); // MPU6050,MPU9150 Vs MPU6500,MPU9250 + I2Cdev::writeWord(devAddr, SaveAddress, offset); +} + +// YA_OFFS_* register + +int16_t MPU6050::getYAccelOffset() { + uint8_t SaveAddress = ((getDeviceID() < 0x38 )? MPU6050_RA_YA_OFFS_H:0x7A); // MPU6050,MPU9150 Vs MPU6500,MPU9250 + I2Cdev::readBytes(devAddr, SaveAddress, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +void MPU6050::setYAccelOffset(int16_t offset) { + uint8_t SaveAddress = ((getDeviceID() < 0x38 )? MPU6050_RA_YA_OFFS_H:0x7A); // MPU6050,MPU9150 Vs MPU6500,MPU9250 + I2Cdev::writeWord(devAddr, SaveAddress, offset); +} + +// ZA_OFFS_* register + +int16_t MPU6050::getZAccelOffset() { + uint8_t SaveAddress = ((getDeviceID() < 0x38 )? MPU6050_RA_ZA_OFFS_H:0x7D); // MPU6050,MPU9150 Vs MPU6500,MPU9250 + I2Cdev::readBytes(devAddr, SaveAddress, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +void MPU6050::setZAccelOffset(int16_t offset) { + uint8_t SaveAddress = ((getDeviceID() < 0x38 )? MPU6050_RA_ZA_OFFS_H:0x7D); // MPU6050,MPU9150 Vs MPU6500,MPU9250 + I2Cdev::writeWord(devAddr, SaveAddress, offset); +} + +// XG_OFFS_USR* registers + +int16_t MPU6050::getXGyroOffset() { + I2Cdev::readBytes(devAddr, MPU6050_RA_XG_OFFS_USRH, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +void MPU6050::setXGyroOffset(int16_t offset) { + I2Cdev::writeWord(devAddr, MPU6050_RA_XG_OFFS_USRH, offset); +} + +// YG_OFFS_USR* register + +int16_t MPU6050::getYGyroOffset() { + I2Cdev::readBytes(devAddr, MPU6050_RA_YG_OFFS_USRH, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +void MPU6050::setYGyroOffset(int16_t offset) { + I2Cdev::writeWord(devAddr, MPU6050_RA_YG_OFFS_USRH, offset); +} + +// ZG_OFFS_USR* register + +int16_t MPU6050::getZGyroOffset() { + I2Cdev::readBytes(devAddr, MPU6050_RA_ZG_OFFS_USRH, 2, buffer); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +void MPU6050::setZGyroOffset(int16_t offset) { + I2Cdev::writeWord(devAddr, MPU6050_RA_ZG_OFFS_USRH, offset); +} + +// INT_ENABLE register (DMP functions) + +bool MPU6050::getIntPLLReadyEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, buffer); + return buffer[0]; +} +void MPU6050::setIntPLLReadyEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, enabled); +} +bool MPU6050::getIntDMPEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DMP_INT_BIT, buffer); + return buffer[0]; +} +void MPU6050::setIntDMPEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DMP_INT_BIT, enabled); +} + +// DMP_INT_STATUS + +bool MPU6050::getDMPInt5Status() { + I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_5_BIT, buffer); + return buffer[0]; +} +bool MPU6050::getDMPInt4Status() { + I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_4_BIT, buffer); + return buffer[0]; +} +bool MPU6050::getDMPInt3Status() { + I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_3_BIT, buffer); + return buffer[0]; +} +bool MPU6050::getDMPInt2Status() { + I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_2_BIT, buffer); + return buffer[0]; +} +bool MPU6050::getDMPInt1Status() { + I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_1_BIT, buffer); + return buffer[0]; +} +bool MPU6050::getDMPInt0Status() { + I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_0_BIT, buffer); + return buffer[0]; +} + +// INT_STATUS register (DMP functions) + +bool MPU6050::getIntPLLReadyStatus() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, buffer); + return buffer[0]; +} +bool MPU6050::getIntDMPStatus() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_DMP_INT_BIT, buffer); + return buffer[0]; +} + +// USER_CTRL register (DMP functions) + +bool MPU6050::getDMPEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_EN_BIT, buffer); + return buffer[0]; +} +void MPU6050::setDMPEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_EN_BIT, enabled); +} +void MPU6050::resetDMP() { + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_RESET_BIT, true); +} + +// BANK_SEL register + +void MPU6050::setMemoryBank(uint8_t bank, bool prefetchEnabled, bool userBank) { + bank &= 0x1F; + if (userBank) bank |= 0x20; + if (prefetchEnabled) bank |= 0x40; + I2Cdev::writeByte(devAddr, MPU6050_RA_BANK_SEL, bank); +} + +// MEM_START_ADDR register + +void MPU6050::setMemoryStartAddress(uint8_t address) { + I2Cdev::writeByte(devAddr, MPU6050_RA_MEM_START_ADDR, address); +} + +// MEM_R_W register + +uint8_t MPU6050::readMemoryByte() { + I2Cdev::readByte(devAddr, MPU6050_RA_MEM_R_W, buffer); + return buffer[0]; +} +void MPU6050::writeMemoryByte(uint8_t data) { + I2Cdev::writeByte(devAddr, MPU6050_RA_MEM_R_W, data); +} +void MPU6050::readMemoryBlock(uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address) { + setMemoryBank(bank); + setMemoryStartAddress(address); + uint8_t chunkSize; + for (uint16_t i = 0; i < dataSize;) { + // determine correct chunk size according to bank position and data size + chunkSize = MPU6050_DMP_MEMORY_CHUNK_SIZE; + + // make sure we don't go past the data size + if (i + chunkSize > dataSize) chunkSize = dataSize - i; + + // make sure this chunk doesn't go past the bank boundary (256 bytes) + if (chunkSize > 256 - address) chunkSize = 256 - address; + + // read the chunk of data as specified + I2Cdev::readBytes(devAddr, MPU6050_RA_MEM_R_W, chunkSize, data + i); + + // increase byte index by [chunkSize] + i += chunkSize; + + // uint8_t automatically wraps to 0 at 256 + address += chunkSize; + + // if we aren't done, update bank (if necessary) and address + if (i < dataSize) { + if (address == 0) bank++; + setMemoryBank(bank); + setMemoryStartAddress(address); + } + } +} +bool MPU6050::writeMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address, bool verify, bool useProgMem) { + setMemoryBank(bank); + setMemoryStartAddress(address); + uint8_t chunkSize; + uint8_t *verifyBuffer=0; + uint8_t *progBuffer=0; + uint16_t i; + uint8_t j; + if (verify) verifyBuffer = (uint8_t *)malloc(MPU6050_DMP_MEMORY_CHUNK_SIZE); + if (useProgMem) progBuffer = (uint8_t *)malloc(MPU6050_DMP_MEMORY_CHUNK_SIZE); + for (i = 0; i < dataSize;) { + // determine correct chunk size according to bank position and data size + chunkSize = MPU6050_DMP_MEMORY_CHUNK_SIZE; + + // make sure we don't go past the data size + if (i + chunkSize > dataSize) chunkSize = dataSize - i; + + // make sure this chunk doesn't go past the bank boundary (256 bytes) + if (chunkSize > 256 - address) chunkSize = 256 - address; + + if (useProgMem) { + // write the chunk of data as specified + //for (j = 0; j < chunkSize; j++) progBuffer[j] = pgm_read_byte(data + i + j); + } else { + // write the chunk of data as specified + progBuffer = (uint8_t *)data + i; + } + + I2Cdev::writeBytes(devAddr, MPU6050_RA_MEM_R_W, chunkSize, progBuffer); + + // verify data if needed + if (verify && verifyBuffer) { + setMemoryBank(bank); + setMemoryStartAddress(address); + I2Cdev::readBytes(devAddr, MPU6050_RA_MEM_R_W, chunkSize, verifyBuffer); + if (memcmp(progBuffer, verifyBuffer, chunkSize) != 0) { + /*Serial.print("Block write verification error, bank "); + Serial.print(bank, DEC); + Serial.print(", address "); + Serial.print(address, DEC); + Serial.print("!\nExpected:"); + for (j = 0; j < chunkSize; j++) { + Serial.print(" 0x"); + if (progBuffer[j] < 16) Serial.print("0"); + Serial.print(progBuffer[j], HEX); + } + Serial.print("\nReceived:"); + for (uint8_t j = 0; j < chunkSize; j++) { + Serial.print(" 0x"); + if (verifyBuffer[i + j] < 16) Serial.print("0"); + Serial.print(verifyBuffer[i + j], HEX); + } + Serial.print("\n");*/ + free(verifyBuffer); + if (useProgMem) free(progBuffer); + return false; // uh oh. + } + } + + // increase byte index by [chunkSize] + i += chunkSize; + + // uint8_t automatically wraps to 0 at 256 + address += chunkSize; + + // if we aren't done, update bank (if necessary) and address + if (i < dataSize) { + if (address == 0) bank++; + setMemoryBank(bank); + setMemoryStartAddress(address); + } + } + if (verify) free(verifyBuffer); + if (useProgMem) free(progBuffer); + return true; +} +bool MPU6050::writeProgMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address, bool verify) { + return writeMemoryBlock(data, dataSize, bank, address, verify, false); +} +bool MPU6050::writeDMPConfigurationSet(const uint8_t *data, uint16_t dataSize, bool useProgMem) { + uint8_t *progBuffer = 0; + uint8_t success, special; + uint16_t i, j; + if (useProgMem) { + progBuffer = (uint8_t *)malloc(8); // assume 8-byte blocks, realloc later if necessary + } + + // config set data is a long string of blocks with the following structure: + // [bank] [offset] [length] [byte[0], byte[1], ..., byte[length]] + uint8_t bank, offset, length; + for (i = 0; i < dataSize;) { + if (useProgMem) { + /* + bank = pgm_read_byte(data + i++); + offset = pgm_read_byte(data + i++); + length = pgm_read_byte(data + i++); + */ + } else { + bank = data[i++]; + offset = data[i++]; + length = data[i++]; + } + + // write data or perform special action + if (length > 0) { + // regular block of data to write + /*Serial.print("Writing config block to bank "); + Serial.print(bank); + Serial.print(", offset "); + Serial.print(offset); + Serial.print(", length="); + Serial.println(length);*/ + if (useProgMem) { + if (sizeof(progBuffer) < length) progBuffer = (uint8_t *)realloc(progBuffer, length); + //for (j = 0; j < length; j++) progBuffer[j] = pgm_read_byte(data + i + j); + } else { + progBuffer = (uint8_t *)data + i; + } + success = writeMemoryBlock(progBuffer, length, bank, offset, true); + i += length; + } else { + // special instruction + // NOTE: this kind of behavior (what and when to do certain things) + // is totally undocumented. This code is in here based on observed + // behavior only, and exactly why (or even whether) it has to be here + // is anybody's guess for now. + if (useProgMem) { + //special = pgm_read_byte(data + i++); + } else { + special = data[i++]; + } + /*Serial.print("Special command code "); + Serial.print(special, HEX); + Serial.println(" found...");*/ + if (special == 0x01) { + // enable DMP-related interrupts + + //setIntZeroMotionEnabled(true); + //setIntFIFOBufferOverflowEnabled(true); + //setIntDMPEnabled(true); + I2Cdev::writeByte(devAddr, MPU6050_RA_INT_ENABLE, 0x32); // single operation + + success = true; + } else { + // unknown special command + success = false; + } + } + + if (!success) { + if (useProgMem) free(progBuffer); + return false; // uh oh + } + } + if (useProgMem) free(progBuffer); + return true; +} +bool MPU6050::writeProgDMPConfigurationSet(const uint8_t *data, uint16_t dataSize) { + return writeDMPConfigurationSet(data, dataSize, false); +} + +// DMP_CFG_1 register + +uint8_t MPU6050::getDMPConfig1() { + I2Cdev::readByte(devAddr, MPU6050_RA_DMP_CFG_1, buffer); + return buffer[0]; +} +void MPU6050::setDMPConfig1(uint8_t config) { + I2Cdev::writeByte(devAddr, MPU6050_RA_DMP_CFG_1, config); +} + +// DMP_CFG_2 register + +uint8_t MPU6050::getDMPConfig2() { + I2Cdev::readByte(devAddr, MPU6050_RA_DMP_CFG_2, buffer); + return buffer[0]; +} +void MPU6050::setDMPConfig2(uint8_t config) { + I2Cdev::writeByte(devAddr, MPU6050_RA_DMP_CFG_2, config); +} + + +//*************************************************************************************** +//********************** Calibration Routines ********************** +//*************************************************************************************** +/** + @brief Fully calibrate Gyro from ZERO in about 6-7 Loops 600-700 readings +*/ +void MPU6050::CalibrateGyro(uint8_t Loops ) { + double kP = 0.3; + double kI = 90; + float x; + x = (100 - map(Loops, 1, 5, 20, 0)) * .01; + kP *= x; + kI *= x; + + PID( 0x43, kP, kI, Loops); +} + +/** + @brief Fully calibrate Accel from ZERO in about 6-7 Loops 600-700 readings +*/ +void MPU6050::CalibrateAccel(uint8_t Loops ) { + + float kP = 0.3; + float kI = 20; + float x; + x = (100 - map(Loops, 1, 5, 20, 0)) * .01; + kP *= x; + kI *= x; + PID( 0x3B, kP, kI, Loops); +} + +void MPU6050::PID(uint8_t ReadAddress, float kP,float kI, uint8_t Loops){ + uint8_t SaveAddress = (ReadAddress == 0x3B)?((getDeviceID() < 0x38 )? 0x06:0x77):0x13; + + int16_t Data; + float Reading; + int16_t BitZero[3]; + uint8_t shift =(SaveAddress == 0x77)?3:2; + float Error, PTerm, ITerm[3]; + int16_t eSample; + uint32_t eSum ; + printf(">"); + for (int i = 0; i < 3; i++) { + I2Cdev::readWords(devAddr, SaveAddress + (i * shift), 1, (uint16_t *)&Data); // reads 1 or more 16 bit integers (Word) + Reading = Data; + if(SaveAddress != 0x13){ + BitZero[i] = Data & 1; // Capture Bit Zero to properly handle Accelerometer calibration + ITerm[i] = ((float)Reading) * 8; + } else { + ITerm[i] = Reading * 4; + } + } + for (int L = 0; L < Loops; L++) { + eSample = 0; + for (int c = 0; c < 100; c++) {// 100 PI Calculations + eSum = 0; + for (int i = 0; i < 3; i++) { + I2Cdev::readWords(devAddr, ReadAddress + (i * 2), 1, (uint16_t *)&Data); // reads 1 or more 16 bit integers (Word) + Reading = Data; + if ((ReadAddress == 0x3B)&&(i == 2)) Reading -= 16384; //remove Gravity + Error = -Reading; + eSum += abs(Reading); + PTerm = kP * Error; + ITerm[i] += (Error * 0.001) * kI; // Integral term 1000 Calculations a second = 0.001 + if(SaveAddress != 0x13){ + Data = round((PTerm + ITerm[i] ) / 8); //Compute PID Output + Data = ((Data)&0xFFFE) |BitZero[i]; // Insert Bit0 Saved at beginning + } else Data = round((PTerm + ITerm[i] ) / 4); //Compute PID Output + I2Cdev::writeWords(devAddr, SaveAddress + (i * shift), 1, (uint16_t *)&Data); + } + if((c == 99) && eSum > 1000){ // Error is still to great to continue + c = 0; + printf("*"); + } + if((eSum * ((ReadAddress == 0x3B)?.05: 1)) < 5) eSample++; // Successfully found offsets prepare to advance + if((eSum < 100) && (c > 10) && (eSample >= 10)) break; // Advance to next Loop + sleep_ms(1); + } + printf("."); + kP *= .75; + kI *= .75; + for (int i = 0; i < 3; i++){ + if(SaveAddress != 0x13) { + Data = round((ITerm[i] ) / 8); //Compute PID Output + Data = ((Data)&0xFFFE) |BitZero[i]; // Insert Bit0 Saved at beginning + } else Data = round((ITerm[i]) / 4); + I2Cdev::writeWords(devAddr, SaveAddress + (i * shift), 1, (uint16_t *)&Data); + } + } + resetFIFO(); + resetDMP(); +} + +void MPU6050::PrintActiveOffsets() { + uint8_t AOffsetRegister = (getDeviceID() < 0x38 )? MPU6050_RA_XA_OFFS_H:0x77; + int16_t Data[3]; + if(AOffsetRegister == 0x06) I2Cdev::readWords(devAddr, AOffsetRegister, 3, (uint16_t *)Data); + else { + I2Cdev::readWords(devAddr, AOffsetRegister, 1, (uint16_t *)Data); + I2Cdev::readWords(devAddr, AOffsetRegister+3, 1, (uint16_t *)Data+1); + I2Cdev::readWords(devAddr, AOffsetRegister+6, 1, (uint16_t *)Data+2); + } + printf("\nOffset Values on device:\n"); + // A_OFFSET_H_READ_A_OFFS(Data); + printf("Acc. X = %d, Y = %d, Z = %d\n", Data[0], Data[1], Data[2]); + I2Cdev::readWords(devAddr, 0x13, 3, (uint16_t *)Data); + // XG_OFFSET_H_READ_OFFS_USR(Data); + printf("Gyro. X = %d, Y = %d, Z = %d\n", Data[0], Data[1], Data[2]); +} diff --git a/RP2040/MPU6050/MPU6050.h b/RP2040/MPU6050/MPU6050.h new file mode 100644 index 00000000..880c64be --- /dev/null +++ b/RP2040/MPU6050/MPU6050.h @@ -0,0 +1,1030 @@ +// I2Cdev library collection - MPU6050 I2C device class +// Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00) +// 10/3/2011 by Jeff Rowberg +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// ... - ongoing debug release + +// NOTE: THIS IS ONLY A PARIAL RELEASE. THIS DEVICE CLASS IS CURRENTLY UNDERGOING ACTIVE +// DEVELOPMENT AND IS STILL MISSING SOME IMPORTANT FEATURES. PLEASE KEEP THIS IN MIND IF +// YOU DECIDE TO USE THIS PARTICULAR CODE FOR ANYTHING. + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2012 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#ifndef _MPU6050_H_ +#define _MPU6050_H_ + +#include "I2Cdev.h" + + +#define MPU6050_ADDRESS_AD0_LOW 0x68 // address pin low (GND), default for InvenSense evaluation board +#define MPU6050_ADDRESS_AD0_HIGH 0x69 // address pin high (VCC) +#define MPU6050_DEFAULT_ADDRESS MPU6050_ADDRESS_AD0_LOW + +#define MPU6050_RA_XG_OFFS_TC 0x00 //[7] PWR_MODE, [6:1] XG_OFFS_TC, [0] OTP_BNK_VLD +#define MPU6050_RA_YG_OFFS_TC 0x01 //[7] PWR_MODE, [6:1] YG_OFFS_TC, [0] OTP_BNK_VLD +#define MPU6050_RA_ZG_OFFS_TC 0x02 //[7] PWR_MODE, [6:1] ZG_OFFS_TC, [0] OTP_BNK_VLD +#define MPU6050_RA_X_FINE_GAIN 0x03 //[7:0] X_FINE_GAIN +#define MPU6050_RA_Y_FINE_GAIN 0x04 //[7:0] Y_FINE_GAIN +#define MPU6050_RA_Z_FINE_GAIN 0x05 //[7:0] Z_FINE_GAIN +#define MPU6050_RA_XA_OFFS_H 0x06 //[15:0] XA_OFFS +#define MPU6050_RA_XA_OFFS_L_TC 0x07 +#define MPU6050_RA_YA_OFFS_H 0x08 //[15:0] YA_OFFS +#define MPU6050_RA_YA_OFFS_L_TC 0x09 +#define MPU6050_RA_ZA_OFFS_H 0x0A //[15:0] ZA_OFFS +#define MPU6050_RA_ZA_OFFS_L_TC 0x0B +#define MPU6050_RA_SELF_TEST_X 0x0D //[7:5] XA_TEST[4-2], [4:0] XG_TEST[4-0] +#define MPU6050_RA_SELF_TEST_Y 0x0E //[7:5] YA_TEST[4-2], [4:0] YG_TEST[4-0] +#define MPU6050_RA_SELF_TEST_Z 0x0F //[7:5] ZA_TEST[4-2], [4:0] ZG_TEST[4-0] +#define MPU6050_RA_SELF_TEST_A 0x10 //[5:4] XA_TEST[1-0], [3:2] YA_TEST[1-0], [1:0] ZA_TEST[1-0] +#define MPU6050_RA_XG_OFFS_USRH 0x13 //[15:0] XG_OFFS_USR +#define MPU6050_RA_XG_OFFS_USRL 0x14 +#define MPU6050_RA_YG_OFFS_USRH 0x15 //[15:0] YG_OFFS_USR +#define MPU6050_RA_YG_OFFS_USRL 0x16 +#define MPU6050_RA_ZG_OFFS_USRH 0x17 //[15:0] ZG_OFFS_USR +#define MPU6050_RA_ZG_OFFS_USRL 0x18 +#define MPU6050_RA_SMPLRT_DIV 0x19 +#define MPU6050_RA_CONFIG 0x1A +#define MPU6050_RA_GYRO_CONFIG 0x1B +#define MPU6050_RA_ACCEL_CONFIG 0x1C +#define MPU6050_RA_FF_THR 0x1D +#define MPU6050_RA_FF_DUR 0x1E +#define MPU6050_RA_MOT_THR 0x1F +#define MPU6050_RA_MOT_DUR 0x20 +#define MPU6050_RA_ZRMOT_THR 0x21 +#define MPU6050_RA_ZRMOT_DUR 0x22 +#define MPU6050_RA_FIFO_EN 0x23 +#define MPU6050_RA_I2C_MST_CTRL 0x24 +#define MPU6050_RA_I2C_SLV0_ADDR 0x25 +#define MPU6050_RA_I2C_SLV0_REG 0x26 +#define MPU6050_RA_I2C_SLV0_CTRL 0x27 +#define MPU6050_RA_I2C_SLV1_ADDR 0x28 +#define MPU6050_RA_I2C_SLV1_REG 0x29 +#define MPU6050_RA_I2C_SLV1_CTRL 0x2A +#define MPU6050_RA_I2C_SLV2_ADDR 0x2B +#define MPU6050_RA_I2C_SLV2_REG 0x2C +#define MPU6050_RA_I2C_SLV2_CTRL 0x2D +#define MPU6050_RA_I2C_SLV3_ADDR 0x2E +#define MPU6050_RA_I2C_SLV3_REG 0x2F +#define MPU6050_RA_I2C_SLV3_CTRL 0x30 +#define MPU6050_RA_I2C_SLV4_ADDR 0x31 +#define MPU6050_RA_I2C_SLV4_REG 0x32 +#define MPU6050_RA_I2C_SLV4_DO 0x33 +#define MPU6050_RA_I2C_SLV4_CTRL 0x34 +#define MPU6050_RA_I2C_SLV4_DI 0x35 +#define MPU6050_RA_I2C_MST_STATUS 0x36 +#define MPU6050_RA_INT_PIN_CFG 0x37 +#define MPU6050_RA_INT_ENABLE 0x38 +#define MPU6050_RA_DMP_INT_STATUS 0x39 +#define MPU6050_RA_INT_STATUS 0x3A +#define MPU6050_RA_ACCEL_XOUT_H 0x3B +#define MPU6050_RA_ACCEL_XOUT_L 0x3C +#define MPU6050_RA_ACCEL_YOUT_H 0x3D +#define MPU6050_RA_ACCEL_YOUT_L 0x3E +#define MPU6050_RA_ACCEL_ZOUT_H 0x3F +#define MPU6050_RA_ACCEL_ZOUT_L 0x40 +#define MPU6050_RA_TEMP_OUT_H 0x41 +#define MPU6050_RA_TEMP_OUT_L 0x42 +#define MPU6050_RA_GYRO_XOUT_H 0x43 +#define MPU6050_RA_GYRO_XOUT_L 0x44 +#define MPU6050_RA_GYRO_YOUT_H 0x45 +#define MPU6050_RA_GYRO_YOUT_L 0x46 +#define MPU6050_RA_GYRO_ZOUT_H 0x47 +#define MPU6050_RA_GYRO_ZOUT_L 0x48 +#define MPU6050_RA_EXT_SENS_DATA_00 0x49 +#define MPU6050_RA_EXT_SENS_DATA_01 0x4A +#define MPU6050_RA_EXT_SENS_DATA_02 0x4B +#define MPU6050_RA_EXT_SENS_DATA_03 0x4C +#define MPU6050_RA_EXT_SENS_DATA_04 0x4D +#define MPU6050_RA_EXT_SENS_DATA_05 0x4E +#define MPU6050_RA_EXT_SENS_DATA_06 0x4F +#define MPU6050_RA_EXT_SENS_DATA_07 0x50 +#define MPU6050_RA_EXT_SENS_DATA_08 0x51 +#define MPU6050_RA_EXT_SENS_DATA_09 0x52 +#define MPU6050_RA_EXT_SENS_DATA_10 0x53 +#define MPU6050_RA_EXT_SENS_DATA_11 0x54 +#define MPU6050_RA_EXT_SENS_DATA_12 0x55 +#define MPU6050_RA_EXT_SENS_DATA_13 0x56 +#define MPU6050_RA_EXT_SENS_DATA_14 0x57 +#define MPU6050_RA_EXT_SENS_DATA_15 0x58 +#define MPU6050_RA_EXT_SENS_DATA_16 0x59 +#define MPU6050_RA_EXT_SENS_DATA_17 0x5A +#define MPU6050_RA_EXT_SENS_DATA_18 0x5B +#define MPU6050_RA_EXT_SENS_DATA_19 0x5C +#define MPU6050_RA_EXT_SENS_DATA_20 0x5D +#define MPU6050_RA_EXT_SENS_DATA_21 0x5E +#define MPU6050_RA_EXT_SENS_DATA_22 0x5F +#define MPU6050_RA_EXT_SENS_DATA_23 0x60 +#define MPU6050_RA_MOT_DETECT_STATUS 0x61 +#define MPU6050_RA_I2C_SLV0_DO 0x63 +#define MPU6050_RA_I2C_SLV1_DO 0x64 +#define MPU6050_RA_I2C_SLV2_DO 0x65 +#define MPU6050_RA_I2C_SLV3_DO 0x66 +#define MPU6050_RA_I2C_MST_DELAY_CTRL 0x67 +#define MPU6050_RA_SIGNAL_PATH_RESET 0x68 +#define MPU6050_RA_MOT_DETECT_CTRL 0x69 +#define MPU6050_RA_USER_CTRL 0x6A +#define MPU6050_RA_PWR_MGMT_1 0x6B +#define MPU6050_RA_PWR_MGMT_2 0x6C +#define MPU6050_RA_BANK_SEL 0x6D +#define MPU6050_RA_MEM_START_ADDR 0x6E +#define MPU6050_RA_MEM_R_W 0x6F +#define MPU6050_RA_DMP_CFG_1 0x70 +#define MPU6050_RA_DMP_CFG_2 0x71 +#define MPU6050_RA_FIFO_COUNTH 0x72 +#define MPU6050_RA_FIFO_COUNTL 0x73 +#define MPU6050_RA_FIFO_R_W 0x74 +#define MPU6050_RA_WHO_AM_I 0x75 + +#define MPU6050_SELF_TEST_XA_1_BIT 0x07 +#define MPU6050_SELF_TEST_XA_1_LENGTH 0x03 +#define MPU6050_SELF_TEST_XA_2_BIT 0x05 +#define MPU6050_SELF_TEST_XA_2_LENGTH 0x02 +#define MPU6050_SELF_TEST_YA_1_BIT 0x07 +#define MPU6050_SELF_TEST_YA_1_LENGTH 0x03 +#define MPU6050_SELF_TEST_YA_2_BIT 0x03 +#define MPU6050_SELF_TEST_YA_2_LENGTH 0x02 +#define MPU6050_SELF_TEST_ZA_1_BIT 0x07 +#define MPU6050_SELF_TEST_ZA_1_LENGTH 0x03 +#define MPU6050_SELF_TEST_ZA_2_BIT 0x01 +#define MPU6050_SELF_TEST_ZA_2_LENGTH 0x02 + +#define MPU6050_SELF_TEST_XG_1_BIT 0x04 +#define MPU6050_SELF_TEST_XG_1_LENGTH 0x05 +#define MPU6050_SELF_TEST_YG_1_BIT 0x04 +#define MPU6050_SELF_TEST_YG_1_LENGTH 0x05 +#define MPU6050_SELF_TEST_ZG_1_BIT 0x04 +#define MPU6050_SELF_TEST_ZG_1_LENGTH 0x05 + +#define MPU6050_TC_PWR_MODE_BIT 7 +#define MPU6050_TC_OFFSET_BIT 6 +#define MPU6050_TC_OFFSET_LENGTH 6 +#define MPU6050_TC_OTP_BNK_VLD_BIT 0 + +#define MPU6050_VDDIO_LEVEL_VLOGIC 0 +#define MPU6050_VDDIO_LEVEL_VDD 1 + +#define MPU6050_CFG_EXT_SYNC_SET_BIT 5 +#define MPU6050_CFG_EXT_SYNC_SET_LENGTH 3 +#define MPU6050_CFG_DLPF_CFG_BIT 2 +#define MPU6050_CFG_DLPF_CFG_LENGTH 3 + +#define MPU6050_EXT_SYNC_DISABLED 0x0 +#define MPU6050_EXT_SYNC_TEMP_OUT_L 0x1 +#define MPU6050_EXT_SYNC_GYRO_XOUT_L 0x2 +#define MPU6050_EXT_SYNC_GYRO_YOUT_L 0x3 +#define MPU6050_EXT_SYNC_GYRO_ZOUT_L 0x4 +#define MPU6050_EXT_SYNC_ACCEL_XOUT_L 0x5 +#define MPU6050_EXT_SYNC_ACCEL_YOUT_L 0x6 +#define MPU6050_EXT_SYNC_ACCEL_ZOUT_L 0x7 + +#define MPU6050_DLPF_BW_256 0x00 +#define MPU6050_DLPF_BW_188 0x01 +#define MPU6050_DLPF_BW_98 0x02 +#define MPU6050_DLPF_BW_42 0x03 +#define MPU6050_DLPF_BW_20 0x04 +#define MPU6050_DLPF_BW_10 0x05 +#define MPU6050_DLPF_BW_5 0x06 + +#define MPU6050_GCONFIG_FS_SEL_BIT 4 +#define MPU6050_GCONFIG_FS_SEL_LENGTH 2 + +#define MPU6050_GYRO_FS_250 0x00 +#define MPU6050_GYRO_FS_500 0x01 +#define MPU6050_GYRO_FS_1000 0x02 +#define MPU6050_GYRO_FS_2000 0x03 + +#define MPU6050_ACONFIG_XA_ST_BIT 7 +#define MPU6050_ACONFIG_YA_ST_BIT 6 +#define MPU6050_ACONFIG_ZA_ST_BIT 5 +#define MPU6050_ACONFIG_AFS_SEL_BIT 4 +#define MPU6050_ACONFIG_AFS_SEL_LENGTH 2 +#define MPU6050_ACONFIG_ACCEL_HPF_BIT 2 +#define MPU6050_ACONFIG_ACCEL_HPF_LENGTH 3 + +#define MPU6050_ACCEL_FS_2 0x00 +#define MPU6050_ACCEL_FS_4 0x01 +#define MPU6050_ACCEL_FS_8 0x02 +#define MPU6050_ACCEL_FS_16 0x03 + +#define MPU6050_DHPF_RESET 0x00 +#define MPU6050_DHPF_5 0x01 +#define MPU6050_DHPF_2P5 0x02 +#define MPU6050_DHPF_1P25 0x03 +#define MPU6050_DHPF_0P63 0x04 +#define MPU6050_DHPF_HOLD 0x07 + +#define MPU6050_TEMP_FIFO_EN_BIT 7 +#define MPU6050_XG_FIFO_EN_BIT 6 +#define MPU6050_YG_FIFO_EN_BIT 5 +#define MPU6050_ZG_FIFO_EN_BIT 4 +#define MPU6050_ACCEL_FIFO_EN_BIT 3 +#define MPU6050_SLV2_FIFO_EN_BIT 2 +#define MPU6050_SLV1_FIFO_EN_BIT 1 +#define MPU6050_SLV0_FIFO_EN_BIT 0 + +#define MPU6050_MULT_MST_EN_BIT 7 +#define MPU6050_WAIT_FOR_ES_BIT 6 +#define MPU6050_SLV_3_FIFO_EN_BIT 5 +#define MPU6050_I2C_MST_P_NSR_BIT 4 +#define MPU6050_I2C_MST_CLK_BIT 3 +#define MPU6050_I2C_MST_CLK_LENGTH 4 + +#define MPU6050_CLOCK_DIV_348 0x0 +#define MPU6050_CLOCK_DIV_333 0x1 +#define MPU6050_CLOCK_DIV_320 0x2 +#define MPU6050_CLOCK_DIV_308 0x3 +#define MPU6050_CLOCK_DIV_296 0x4 +#define MPU6050_CLOCK_DIV_286 0x5 +#define MPU6050_CLOCK_DIV_276 0x6 +#define MPU6050_CLOCK_DIV_267 0x7 +#define MPU6050_CLOCK_DIV_258 0x8 +#define MPU6050_CLOCK_DIV_500 0x9 +#define MPU6050_CLOCK_DIV_471 0xA +#define MPU6050_CLOCK_DIV_444 0xB +#define MPU6050_CLOCK_DIV_421 0xC +#define MPU6050_CLOCK_DIV_400 0xD +#define MPU6050_CLOCK_DIV_381 0xE +#define MPU6050_CLOCK_DIV_364 0xF + +#define MPU6050_I2C_SLV_RW_BIT 7 +#define MPU6050_I2C_SLV_ADDR_BIT 6 +#define MPU6050_I2C_SLV_ADDR_LENGTH 7 +#define MPU6050_I2C_SLV_EN_BIT 7 +#define MPU6050_I2C_SLV_BYTE_SW_BIT 6 +#define MPU6050_I2C_SLV_REG_DIS_BIT 5 +#define MPU6050_I2C_SLV_GRP_BIT 4 +#define MPU6050_I2C_SLV_LEN_BIT 3 +#define MPU6050_I2C_SLV_LEN_LENGTH 4 + +#define MPU6050_I2C_SLV4_RW_BIT 7 +#define MPU6050_I2C_SLV4_ADDR_BIT 6 +#define MPU6050_I2C_SLV4_ADDR_LENGTH 7 +#define MPU6050_I2C_SLV4_EN_BIT 7 +#define MPU6050_I2C_SLV4_INT_EN_BIT 6 +#define MPU6050_I2C_SLV4_REG_DIS_BIT 5 +#define MPU6050_I2C_SLV4_MST_DLY_BIT 4 +#define MPU6050_I2C_SLV4_MST_DLY_LENGTH 5 + +#define MPU6050_MST_PASS_THROUGH_BIT 7 +#define MPU6050_MST_I2C_SLV4_DONE_BIT 6 +#define MPU6050_MST_I2C_LOST_ARB_BIT 5 +#define MPU6050_MST_I2C_SLV4_NACK_BIT 4 +#define MPU6050_MST_I2C_SLV3_NACK_BIT 3 +#define MPU6050_MST_I2C_SLV2_NACK_BIT 2 +#define MPU6050_MST_I2C_SLV1_NACK_BIT 1 +#define MPU6050_MST_I2C_SLV0_NACK_BIT 0 + +#define MPU6050_INTCFG_INT_LEVEL_BIT 7 +#define MPU6050_INTCFG_INT_OPEN_BIT 6 +#define MPU6050_INTCFG_LATCH_INT_EN_BIT 5 +#define MPU6050_INTCFG_INT_RD_CLEAR_BIT 4 +#define MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT 3 +#define MPU6050_INTCFG_FSYNC_INT_EN_BIT 2 +#define MPU6050_INTCFG_I2C_BYPASS_EN_BIT 1 +#define MPU6050_INTCFG_CLKOUT_EN_BIT 0 + +#define MPU6050_INTMODE_ACTIVEHIGH 0x00 +#define MPU6050_INTMODE_ACTIVELOW 0x01 + +#define MPU6050_INTDRV_PUSHPULL 0x00 +#define MPU6050_INTDRV_OPENDRAIN 0x01 + +#define MPU6050_INTLATCH_50USPULSE 0x00 +#define MPU6050_INTLATCH_WAITCLEAR 0x01 + +#define MPU6050_INTCLEAR_STATUSREAD 0x00 +#define MPU6050_INTCLEAR_ANYREAD 0x01 + +#define MPU6050_INTERRUPT_FF_BIT 7 +#define MPU6050_INTERRUPT_MOT_BIT 6 +#define MPU6050_INTERRUPT_ZMOT_BIT 5 +#define MPU6050_INTERRUPT_FIFO_OFLOW_BIT 4 +#define MPU6050_INTERRUPT_I2C_MST_INT_BIT 3 +#define MPU6050_INTERRUPT_PLL_RDY_INT_BIT 2 +#define MPU6050_INTERRUPT_DMP_INT_BIT 1 +#define MPU6050_INTERRUPT_DATA_RDY_BIT 0 + +// TODO: figure out what these actually do +// UMPL source code is not very obivous +#define MPU6050_DMPINT_5_BIT 5 +#define MPU6050_DMPINT_4_BIT 4 +#define MPU6050_DMPINT_3_BIT 3 +#define MPU6050_DMPINT_2_BIT 2 +#define MPU6050_DMPINT_1_BIT 1 +#define MPU6050_DMPINT_0_BIT 0 + +#define MPU6050_MOTION_MOT_XNEG_BIT 7 +#define MPU6050_MOTION_MOT_XPOS_BIT 6 +#define MPU6050_MOTION_MOT_YNEG_BIT 5 +#define MPU6050_MOTION_MOT_YPOS_BIT 4 +#define MPU6050_MOTION_MOT_ZNEG_BIT 3 +#define MPU6050_MOTION_MOT_ZPOS_BIT 2 +#define MPU6050_MOTION_MOT_ZRMOT_BIT 0 + +#define MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT 7 +#define MPU6050_DELAYCTRL_I2C_SLV4_DLY_EN_BIT 4 +#define MPU6050_DELAYCTRL_I2C_SLV3_DLY_EN_BIT 3 +#define MPU6050_DELAYCTRL_I2C_SLV2_DLY_EN_BIT 2 +#define MPU6050_DELAYCTRL_I2C_SLV1_DLY_EN_BIT 1 +#define MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT 0 + +#define MPU6050_PATHRESET_GYRO_RESET_BIT 2 +#define MPU6050_PATHRESET_ACCEL_RESET_BIT 1 +#define MPU6050_PATHRESET_TEMP_RESET_BIT 0 + +#define MPU6050_DETECT_ACCEL_ON_DELAY_BIT 5 +#define MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH 2 +#define MPU6050_DETECT_FF_COUNT_BIT 3 +#define MPU6050_DETECT_FF_COUNT_LENGTH 2 +#define MPU6050_DETECT_MOT_COUNT_BIT 1 +#define MPU6050_DETECT_MOT_COUNT_LENGTH 2 + +#define MPU6050_DETECT_DECREMENT_RESET 0x0 +#define MPU6050_DETECT_DECREMENT_1 0x1 +#define MPU6050_DETECT_DECREMENT_2 0x2 +#define MPU6050_DETECT_DECREMENT_4 0x3 + +#define MPU6050_USERCTRL_DMP_EN_BIT 7 +#define MPU6050_USERCTRL_FIFO_EN_BIT 6 +#define MPU6050_USERCTRL_I2C_MST_EN_BIT 5 +#define MPU6050_USERCTRL_I2C_IF_DIS_BIT 4 +#define MPU6050_USERCTRL_DMP_RESET_BIT 3 +#define MPU6050_USERCTRL_FIFO_RESET_BIT 2 +#define MPU6050_USERCTRL_I2C_MST_RESET_BIT 1 +#define MPU6050_USERCTRL_SIG_COND_RESET_BIT 0 + +#define MPU6050_PWR1_DEVICE_RESET_BIT 7 +#define MPU6050_PWR1_SLEEP_BIT 6 +#define MPU6050_PWR1_CYCLE_BIT 5 +#define MPU6050_PWR1_TEMP_DIS_BIT 3 +#define MPU6050_PWR1_CLKSEL_BIT 2 +#define MPU6050_PWR1_CLKSEL_LENGTH 3 + +#define MPU6050_CLOCK_INTERNAL 0x00 +#define MPU6050_CLOCK_PLL_XGYRO 0x01 +#define MPU6050_CLOCK_PLL_YGYRO 0x02 +#define MPU6050_CLOCK_PLL_ZGYRO 0x03 +#define MPU6050_CLOCK_PLL_EXT32K 0x04 +#define MPU6050_CLOCK_PLL_EXT19M 0x05 +#define MPU6050_CLOCK_KEEP_RESET 0x07 + +#define MPU6050_PWR2_LP_WAKE_CTRL_BIT 7 +#define MPU6050_PWR2_LP_WAKE_CTRL_LENGTH 2 +#define MPU6050_PWR2_STBY_XA_BIT 5 +#define MPU6050_PWR2_STBY_YA_BIT 4 +#define MPU6050_PWR2_STBY_ZA_BIT 3 +#define MPU6050_PWR2_STBY_XG_BIT 2 +#define MPU6050_PWR2_STBY_YG_BIT 1 +#define MPU6050_PWR2_STBY_ZG_BIT 0 + +#define MPU6050_WAKE_FREQ_1P25 0x0 +#define MPU6050_WAKE_FREQ_2P5 0x1 +#define MPU6050_WAKE_FREQ_5 0x2 +#define MPU6050_WAKE_FREQ_10 0x3 + +#define MPU6050_BANKSEL_PRFTCH_EN_BIT 6 +#define MPU6050_BANKSEL_CFG_USER_BANK_BIT 5 +#define MPU6050_BANKSEL_MEM_SEL_BIT 4 +#define MPU6050_BANKSEL_MEM_SEL_LENGTH 5 + +#define MPU6050_WHO_AM_I_BIT 6 +#define MPU6050_WHO_AM_I_LENGTH 6 + +#define MPU6050_DMP_MEMORY_BANKS 8 +#define MPU6050_DMP_MEMORY_BANK_SIZE 256 +#define MPU6050_DMP_MEMORY_CHUNK_SIZE 16 + +// note: DMP code memory blocks defined at end of header file + +class MPU6050 { + public: + MPU6050(uint8_t address=MPU6050_DEFAULT_ADDRESS); + + void initialize(); + bool testConnection(); + + // AUX_VDDIO register + uint8_t getAuxVDDIOLevel(); + void setAuxVDDIOLevel(uint8_t level); + + // SMPLRT_DIV register + uint8_t getRate(); + void setRate(uint8_t rate); + + // CONFIG register + uint8_t getExternalFrameSync(); + void setExternalFrameSync(uint8_t sync); + uint8_t getDLPFMode(); + void setDLPFMode(uint8_t bandwidth); + + // GYRO_CONFIG register + uint8_t getFullScaleGyroRange(); + void setFullScaleGyroRange(uint8_t range); + + // SELF_TEST registers + uint8_t getAccelXSelfTestFactoryTrim(); + uint8_t getAccelYSelfTestFactoryTrim(); + uint8_t getAccelZSelfTestFactoryTrim(); + + uint8_t getGyroXSelfTestFactoryTrim(); + uint8_t getGyroYSelfTestFactoryTrim(); + uint8_t getGyroZSelfTestFactoryTrim(); + + // ACCEL_CONFIG register + bool getAccelXSelfTest(); + void setAccelXSelfTest(bool enabled); + bool getAccelYSelfTest(); + void setAccelYSelfTest(bool enabled); + bool getAccelZSelfTest(); + void setAccelZSelfTest(bool enabled); + uint8_t getFullScaleAccelRange(); + void setFullScaleAccelRange(uint8_t range); + uint8_t getDHPFMode(); + void setDHPFMode(uint8_t mode); + + // FF_THR register + uint8_t getFreefallDetectionThreshold(); + void setFreefallDetectionThreshold(uint8_t threshold); + + // FF_DUR register + uint8_t getFreefallDetectionDuration(); + void setFreefallDetectionDuration(uint8_t duration); + + // MOT_THR register + uint8_t getMotionDetectionThreshold(); + void setMotionDetectionThreshold(uint8_t threshold); + + // MOT_DUR register + uint8_t getMotionDetectionDuration(); + void setMotionDetectionDuration(uint8_t duration); + + // ZRMOT_THR register + uint8_t getZeroMotionDetectionThreshold(); + void setZeroMotionDetectionThreshold(uint8_t threshold); + + // ZRMOT_DUR register + uint8_t getZeroMotionDetectionDuration(); + void setZeroMotionDetectionDuration(uint8_t duration); + + // FIFO_EN register + bool getTempFIFOEnabled(); + void setTempFIFOEnabled(bool enabled); + bool getXGyroFIFOEnabled(); + void setXGyroFIFOEnabled(bool enabled); + bool getYGyroFIFOEnabled(); + void setYGyroFIFOEnabled(bool enabled); + bool getZGyroFIFOEnabled(); + void setZGyroFIFOEnabled(bool enabled); + bool getAccelFIFOEnabled(); + void setAccelFIFOEnabled(bool enabled); + bool getSlave2FIFOEnabled(); + void setSlave2FIFOEnabled(bool enabled); + bool getSlave1FIFOEnabled(); + void setSlave1FIFOEnabled(bool enabled); + bool getSlave0FIFOEnabled(); + void setSlave0FIFOEnabled(bool enabled); + + // I2C_MST_CTRL register + bool getMultiMasterEnabled(); + void setMultiMasterEnabled(bool enabled); + bool getWaitForExternalSensorEnabled(); + void setWaitForExternalSensorEnabled(bool enabled); + bool getSlave3FIFOEnabled(); + void setSlave3FIFOEnabled(bool enabled); + bool getSlaveReadWriteTransitionEnabled(); + void setSlaveReadWriteTransitionEnabled(bool enabled); + uint8_t getMasterClockSpeed(); + void setMasterClockSpeed(uint8_t speed); + + // I2C_SLV* registers (Slave 0-3) + uint8_t getSlaveAddress(uint8_t num); + void setSlaveAddress(uint8_t num, uint8_t address); + uint8_t getSlaveRegister(uint8_t num); + void setSlaveRegister(uint8_t num, uint8_t reg); + bool getSlaveEnabled(uint8_t num); + void setSlaveEnabled(uint8_t num, bool enabled); + bool getSlaveWordByteSwap(uint8_t num); + void setSlaveWordByteSwap(uint8_t num, bool enabled); + bool getSlaveWriteMode(uint8_t num); + void setSlaveWriteMode(uint8_t num, bool mode); + bool getSlaveWordGroupOffset(uint8_t num); + void setSlaveWordGroupOffset(uint8_t num, bool enabled); + uint8_t getSlaveDataLength(uint8_t num); + void setSlaveDataLength(uint8_t num, uint8_t length); + + // I2C_SLV* registers (Slave 4) + uint8_t getSlave4Address(); + void setSlave4Address(uint8_t address); + uint8_t getSlave4Register(); + void setSlave4Register(uint8_t reg); + void setSlave4OutputByte(uint8_t data); + bool getSlave4Enabled(); + void setSlave4Enabled(bool enabled); + bool getSlave4InterruptEnabled(); + void setSlave4InterruptEnabled(bool enabled); + bool getSlave4WriteMode(); + void setSlave4WriteMode(bool mode); + uint8_t getSlave4MasterDelay(); + void setSlave4MasterDelay(uint8_t delay); + uint8_t getSlate4InputByte(); + + // I2C_MST_STATUS register + bool getPassthroughStatus(); + bool getSlave4IsDone(); + bool getLostArbitration(); + bool getSlave4Nack(); + bool getSlave3Nack(); + bool getSlave2Nack(); + bool getSlave1Nack(); + bool getSlave0Nack(); + + // INT_PIN_CFG register + bool getInterruptMode(); + void setInterruptMode(bool mode); + bool getInterruptDrive(); + void setInterruptDrive(bool drive); + bool getInterruptLatch(); + void setInterruptLatch(bool latch); + bool getInterruptLatchClear(); + void setInterruptLatchClear(bool clear); + bool getFSyncInterruptLevel(); + void setFSyncInterruptLevel(bool level); + bool getFSyncInterruptEnabled(); + void setFSyncInterruptEnabled(bool enabled); + bool getI2CBypassEnabled(); + void setI2CBypassEnabled(bool enabled); + bool getClockOutputEnabled(); + void setClockOutputEnabled(bool enabled); + + // INT_ENABLE register + uint8_t getIntEnabled(); + void setIntEnabled(uint8_t enabled); + bool getIntFreefallEnabled(); + void setIntFreefallEnabled(bool enabled); + bool getIntMotionEnabled(); + void setIntMotionEnabled(bool enabled); + bool getIntZeroMotionEnabled(); + void setIntZeroMotionEnabled(bool enabled); + bool getIntFIFOBufferOverflowEnabled(); + void setIntFIFOBufferOverflowEnabled(bool enabled); + bool getIntI2CMasterEnabled(); + void setIntI2CMasterEnabled(bool enabled); + bool getIntDataReadyEnabled(); + void setIntDataReadyEnabled(bool enabled); + + // INT_STATUS register + uint8_t getIntStatus(); + bool getIntFreefallStatus(); + bool getIntMotionStatus(); + bool getIntZeroMotionStatus(); + bool getIntFIFOBufferOverflowStatus(); + bool getIntI2CMasterStatus(); + bool getIntDataReadyStatus(); + + // ACCEL_*OUT_* registers + void getMotion9(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz, int16_t* mx, int16_t* my, int16_t* mz); + void getMotion6(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz); + void getAcceleration(int16_t* x, int16_t* y, int16_t* z); + int16_t getAccelerationX(); + int16_t getAccelerationY(); + int16_t getAccelerationZ(); + + // TEMP_OUT_* registers + int16_t getTemperature(); + + // GYRO_*OUT_* registers + void getRotation(int16_t* x, int16_t* y, int16_t* z); + int16_t getRotationX(); + int16_t getRotationY(); + int16_t getRotationZ(); + + // EXT_SENS_DATA_* registers + uint8_t getExternalSensorByte(int position); + uint16_t getExternalSensorWord(int position); + uint32_t getExternalSensorDWord(int position); + + // MOT_DETECT_STATUS register + uint8_t getMotionStatus(); + bool getXNegMotionDetected(); + bool getXPosMotionDetected(); + bool getYNegMotionDetected(); + bool getYPosMotionDetected(); + bool getZNegMotionDetected(); + bool getZPosMotionDetected(); + bool getZeroMotionDetected(); + + // I2C_SLV*_DO register + void setSlaveOutputByte(uint8_t num, uint8_t data); + + // I2C_MST_DELAY_CTRL register + bool getExternalShadowDelayEnabled(); + void setExternalShadowDelayEnabled(bool enabled); + bool getSlaveDelayEnabled(uint8_t num); + void setSlaveDelayEnabled(uint8_t num, bool enabled); + + // SIGNAL_PATH_RESET register + void resetGyroscopePath(); + void resetAccelerometerPath(); + void resetTemperaturePath(); + + // MOT_DETECT_CTRL register + uint8_t getAccelerometerPowerOnDelay(); + void setAccelerometerPowerOnDelay(uint8_t delay); + uint8_t getFreefallDetectionCounterDecrement(); + void setFreefallDetectionCounterDecrement(uint8_t decrement); + uint8_t getMotionDetectionCounterDecrement(); + void setMotionDetectionCounterDecrement(uint8_t decrement); + + // USER_CTRL register + bool getFIFOEnabled(); + void setFIFOEnabled(bool enabled); + bool getI2CMasterModeEnabled(); + void setI2CMasterModeEnabled(bool enabled); + void switchSPIEnabled(bool enabled); + void resetFIFO(); + void resetI2CMaster(); + void resetSensors(); + + // PWR_MGMT_1 register + void reset(); + bool getSleepEnabled(); + void setSleepEnabled(bool enabled); + bool getWakeCycleEnabled(); + void setWakeCycleEnabled(bool enabled); + bool getTempSensorEnabled(); + void setTempSensorEnabled(bool enabled); + uint8_t getClockSource(); + void setClockSource(uint8_t source); + + // PWR_MGMT_2 register + uint8_t getWakeFrequency(); + void setWakeFrequency(uint8_t frequency); + bool getStandbyXAccelEnabled(); + void setStandbyXAccelEnabled(bool enabled); + bool getStandbyYAccelEnabled(); + void setStandbyYAccelEnabled(bool enabled); + bool getStandbyZAccelEnabled(); + void setStandbyZAccelEnabled(bool enabled); + bool getStandbyXGyroEnabled(); + void setStandbyXGyroEnabled(bool enabled); + bool getStandbyYGyroEnabled(); + void setStandbyYGyroEnabled(bool enabled); + bool getStandbyZGyroEnabled(); + void setStandbyZGyroEnabled(bool enabled); + + // FIFO_COUNT_* registers + uint16_t getFIFOCount(); + + // FIFO_R_W register + uint8_t getFIFOByte(); + int8_t GetCurrentFIFOPacket(uint8_t *data, uint8_t length); + void setFIFOByte(uint8_t data); + void getFIFOBytes(uint8_t *data, uint8_t length); + + // WHO_AM_I register + uint8_t getDeviceID(); + void setDeviceID(uint8_t id); + + // ======== UNDOCUMENTED/DMP REGISTERS/METHODS ======== + + // XG_OFFS_TC register + uint8_t getOTPBankValid(); + void setOTPBankValid(bool enabled); + int8_t getXGyroOffsetTC(); + void setXGyroOffsetTC(int8_t offset); + + // YG_OFFS_TC register + int8_t getYGyroOffsetTC(); + void setYGyroOffsetTC(int8_t offset); + + // ZG_OFFS_TC register + int8_t getZGyroOffsetTC(); + void setZGyroOffsetTC(int8_t offset); + + // X_FINE_GAIN register + int8_t getXFineGain(); + void setXFineGain(int8_t gain); + + // Y_FINE_GAIN register + int8_t getYFineGain(); + void setYFineGain(int8_t gain); + + // Z_FINE_GAIN register + int8_t getZFineGain(); + void setZFineGain(int8_t gain); + + // XA_OFFS_* registers + int16_t getXAccelOffset(); + void setXAccelOffset(int16_t offset); + + // YA_OFFS_* register + int16_t getYAccelOffset(); + void setYAccelOffset(int16_t offset); + + // ZA_OFFS_* register + int16_t getZAccelOffset(); + void setZAccelOffset(int16_t offset); + + // XG_OFFS_USR* registers + int16_t getXGyroOffset(); + void setXGyroOffset(int16_t offset); + + // YG_OFFS_USR* register + int16_t getYGyroOffset(); + void setYGyroOffset(int16_t offset); + + // ZG_OFFS_USR* register + int16_t getZGyroOffset(); + void setZGyroOffset(int16_t offset); + + // INT_ENABLE register (DMP functions) + bool getIntPLLReadyEnabled(); + void setIntPLLReadyEnabled(bool enabled); + bool getIntDMPEnabled(); + void setIntDMPEnabled(bool enabled); + + // DMP_INT_STATUS + bool getDMPInt5Status(); + bool getDMPInt4Status(); + bool getDMPInt3Status(); + bool getDMPInt2Status(); + bool getDMPInt1Status(); + bool getDMPInt0Status(); + + // INT_STATUS register (DMP functions) + bool getIntPLLReadyStatus(); + bool getIntDMPStatus(); + + // USER_CTRL register (DMP functions) + bool getDMPEnabled(); + void setDMPEnabled(bool enabled); + void resetDMP(); + + // BANK_SEL register + void setMemoryBank(uint8_t bank, bool prefetchEnabled=false, bool userBank=false); + + // MEM_START_ADDR register + void setMemoryStartAddress(uint8_t address); + + // MEM_R_W register + uint8_t readMemoryByte(); + void writeMemoryByte(uint8_t data); + void readMemoryBlock(uint8_t *data, uint16_t dataSize, uint8_t bank=0, uint8_t address=0); + bool writeMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank=0, uint8_t address=0, bool verify=true, bool useProgMem=false); + bool writeProgMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank=0, uint8_t address=0, bool verify=true); + + bool writeDMPConfigurationSet(const uint8_t *data, uint16_t dataSize, bool useProgMem=false); + bool writeProgDMPConfigurationSet(const uint8_t *data, uint16_t dataSize); + + // DMP_CFG_1 register + uint8_t getDMPConfig1(); + void setDMPConfig1(uint8_t config); + + // DMP_CFG_2 register + uint8_t getDMPConfig2(); + void setDMPConfig2(uint8_t config); + + + // Calibration Routines + void CalibrateGyro(uint8_t Loops = 15); // Fine tune after setting offsets with less Loops. + void CalibrateAccel(uint8_t Loops = 15);// Fine tune after setting offsets with less Loops. + void PID(uint8_t ReadAddress, float kP,float kI, uint8_t Loops); // Does the math + void PrintActiveOffsets(); // See the results of the Calibration + + + + + // special methods for MotionApps 2.0 implementation + #ifdef MPU6050_INCLUDE_DMP_MOTIONAPPS20 + + uint8_t dmpInitialize(); + bool dmpPacketAvailable(); + + uint8_t dmpSetFIFORate(uint8_t fifoRate); + uint8_t dmpGetFIFORate(); + uint8_t dmpGetSampleStepSizeMS(); + uint8_t dmpGetSampleFrequency(); + int32_t dmpDecodeTemperature(int8_t tempReg); + + // Register callbacks after a packet of FIFO data is processed + //uint8_t dmpRegisterFIFORateProcess(inv_obj_func func, int16_t priority); + //uint8_t dmpUnregisterFIFORateProcess(inv_obj_func func); + uint8_t dmpRunFIFORateProcesses(); + + // Setup FIFO for various output + uint8_t dmpSendQuaternion(uint_fast16_t accuracy); + uint8_t dmpSendGyro(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendAccel(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendLinearAccel(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendLinearAccelInWorld(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendControlData(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendSensorData(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendExternalSensorData(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendGravity(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendPacketNumber(uint_fast16_t accuracy); + uint8_t dmpSendQuantizedAccel(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendEIS(uint_fast16_t elements, uint_fast16_t accuracy); + + // Get Fixed Point data from FIFO + uint8_t dmpGetAccel(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetAccel(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetAccel(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetQuaternion(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetQuaternion(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetQuaternion(Quaternion *q, const uint8_t* packet=0); + uint8_t dmpGet6AxisQuaternion(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGet6AxisQuaternion(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGet6AxisQuaternion(Quaternion *q, const uint8_t* packet=0); + uint8_t dmpGetRelativeQuaternion(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetRelativeQuaternion(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetRelativeQuaternion(Quaternion *data, const uint8_t* packet=0); + uint8_t dmpGetGyro(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyro(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyro(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpSetLinearAccelFilterCoefficient(float coef); + uint8_t dmpGetLinearAccel(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetLinearAccel(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetLinearAccel(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetLinearAccel(VectorInt16 *v, VectorInt16 *vRaw, VectorFloat *gravity); + uint8_t dmpGetLinearAccelInWorld(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetLinearAccelInWorld(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetLinearAccelInWorld(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Quaternion *q); + uint8_t dmpGetGyroAndAccelSensor(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyroAndAccelSensor(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyroAndAccelSensor(VectorInt16 *g, VectorInt16 *a, const uint8_t* packet=0); + uint8_t dmpGetGyroSensor(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyroSensor(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyroSensor(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetControlData(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetTemperature(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetGravity(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetGravity(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetGravity(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetGravity(VectorFloat *v, Quaternion *q); + uint8_t dmpGetUnquantizedAccel(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetUnquantizedAccel(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetUnquantizedAccel(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetQuantizedAccel(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetQuantizedAccel(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetQuantizedAccel(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetExternalSensorData(int32_t *data, uint16_t size, const uint8_t* packet=0); + uint8_t dmpGetEIS(int32_t *data, const uint8_t* packet=0); + + uint8_t dmpGetEuler(float *data, Quaternion *q); + uint8_t dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity); + + // Get Floating Point data from FIFO + uint8_t dmpGetAccelFloat(float *data, const uint8_t* packet=0); + uint8_t dmpGetQuaternionFloat(float *data, const uint8_t* packet=0); + + uint8_t dmpProcessFIFOPacket(const unsigned char *dmpData); + uint8_t dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *processed=NULL); + + uint8_t dmpSetFIFOProcessedCallback(void (*func) (void)); + + uint8_t dmpInitFIFOParam(); + uint8_t dmpCloseFIFO(); + uint8_t dmpSetGyroDataSource(uint8_t source); + uint8_t dmpDecodeQuantizedAccel(); + uint32_t dmpGetGyroSumOfSquare(); + uint32_t dmpGetAccelSumOfSquare(); + void dmpOverrideQuaternion(long *q); + uint16_t dmpGetFIFOPacketSize(); + uint8_t dmpGetCurrentFIFOPacket(uint8_t *data); // overflow proof + #endif + + // special methods for MotionApps 4.1 implementation + #ifdef MPU6050_INCLUDE_DMP_MOTIONAPPS41 + + uint8_t dmpInitialize(); + bool dmpPacketAvailable(); + + uint8_t dmpSetFIFORate(uint8_t fifoRate); + uint8_t dmpGetFIFORate(); + uint8_t dmpGetSampleStepSizeMS(); + uint8_t dmpGetSampleFrequency(); + int32_t dmpDecodeTemperature(int8_t tempReg); + + // Register callbacks after a packet of FIFO data is processed + //uint8_t dmpRegisterFIFORateProcess(inv_obj_func func, int16_t priority); + //uint8_t dmpUnregisterFIFORateProcess(inv_obj_func func); + uint8_t dmpRunFIFORateProcesses(); + + // Setup FIFO for various output + uint8_t dmpSendQuaternion(uint_fast16_t accuracy); + uint8_t dmpSendGyro(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendAccel(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendLinearAccel(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendLinearAccelInWorld(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendControlData(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendSensorData(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendExternalSensorData(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendGravity(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendPacketNumber(uint_fast16_t accuracy); + uint8_t dmpSendQuantizedAccel(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendEIS(uint_fast16_t elements, uint_fast16_t accuracy); + + // Get Fixed Point data from FIFO + uint8_t dmpGetAccel(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetAccel(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetAccel(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetQuaternion(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetQuaternion(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetQuaternion(Quaternion *q, const uint8_t* packet=0); + uint8_t dmpGet6AxisQuaternion(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGet6AxisQuaternion(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGet6AxisQuaternion(Quaternion *q, const uint8_t* packet=0); + uint8_t dmpGetRelativeQuaternion(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetRelativeQuaternion(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetRelativeQuaternion(Quaternion *data, const uint8_t* packet=0); + uint8_t dmpGetGyro(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyro(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyro(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetMag(int16_t *data, const uint8_t* packet=0); + uint8_t dmpSetLinearAccelFilterCoefficient(float coef); + uint8_t dmpGetLinearAccel(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetLinearAccel(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetLinearAccel(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetLinearAccel(VectorInt16 *v, VectorInt16 *vRaw, VectorFloat *gravity); + uint8_t dmpGetLinearAccelInWorld(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetLinearAccelInWorld(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetLinearAccelInWorld(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Quaternion *q); + uint8_t dmpGetGyroAndAccelSensor(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyroAndAccelSensor(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyroAndAccelSensor(VectorInt16 *g, VectorInt16 *a, const uint8_t* packet=0); + uint8_t dmpGetGyroSensor(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyroSensor(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyroSensor(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetControlData(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetTemperature(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetGravity(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetGravity(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetGravity(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetGravity(VectorFloat *v, Quaternion *q); + uint8_t dmpGetUnquantizedAccel(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetUnquantizedAccel(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetUnquantizedAccel(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetQuantizedAccel(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetQuantizedAccel(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetQuantizedAccel(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetExternalSensorData(int32_t *data, uint16_t size, const uint8_t* packet=0); + uint8_t dmpGetEIS(int32_t *data, const uint8_t* packet=0); + + uint8_t dmpGetEuler(float *data, Quaternion *q); + uint8_t dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity); + + // Get Floating Point data from FIFO + uint8_t dmpGetAccelFloat(float *data, const uint8_t* packet=0); + uint8_t dmpGetQuaternionFloat(float *data, const uint8_t* packet=0); + + uint8_t dmpProcessFIFOPacket(const unsigned char *dmpData); + uint8_t dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *processed=NULL); + + uint8_t dmpSetFIFOProcessedCallback(void (*func) (void)); + + uint8_t dmpInitFIFOParam(); + uint8_t dmpCloseFIFO(); + uint8_t dmpSetGyroDataSource(uint8_t source); + uint8_t dmpDecodeQuantizedAccel(); + uint32_t dmpGetGyroSumOfSquare(); + uint32_t dmpGetAccelSumOfSquare(); + void dmpOverrideQuaternion(long *q); + uint16_t dmpGetFIFOPacketSize(); + #endif + + private: + uint8_t devAddr; + uint8_t buffer[14]; + #if defined(MPU6050_INCLUDE_DMP_MOTIONAPPS20) or defined(MPU6050_INCLUDE_DMP_MOTIONAPPS41) + uint8_t *dmpPacketBuffer; + uint16_t dmpPacketSize; + #endif +}; + +#endif /* _MPU6050_H_ */ diff --git a/RP2040/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h b/RP2040/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h new file mode 100644 index 00000000..92d093dd --- /dev/null +++ b/RP2040/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h @@ -0,0 +1,561 @@ +// I2Cdev library collection - MPU6050 I2C device class, 6-axis MotionApps 6.12 implementation +// Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00) +// 5/20/2013 by Jeff Rowberg +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// 2019/7/10 - I incorporated DMP Firmware Version 6.12 Latest as of today with many features and bug fixes. +// - MPU6050 Registers have not changed just the DMP Image so that full backwards compatibility is present +// - Run-time calibration routine is enabled which calibrates after no motion state is detected +// - once no motion state is detected Calibration completes within 0.5 seconds +// - The Drawback is that the firmware image is larger. +// ... - ongoing debug release + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2012 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#ifndef _MPU6050_6AXIS_MOTIONAPPS20_H_ +#define _MPU6050_6AXIS_MOTIONAPPS20_H_ + +#include "I2Cdev.h" +#include "helper_3dmath.h" +#include "pico/double.h" + +// MotionApps 2.0 DMP implementation, built using the MPU-6050EVB evaluation board +#define MPU6050_INCLUDE_DMP_MOTIONAPPS20 // same definitions Should work with V6.12 + +#include "MPU6050.h" + +#define PI 3.1415926535897932384626433832795 + +/* Source is from the InvenSense MotionApps v2 demo code. Original source is + * unavailable, unless you happen to be amazing as decompiling binary by + * hand (in which case, please contact me, and I'm totally serious). + * + * Also, I'd like to offer many, many thanks to Noah Zerkin for all of the + * DMP reverse-engineering he did to help make this bit of wizardry + * possible. + */ + +#define MPU6050_DMP_CODE_SIZE 3062 // dmpMemory[] + +/* ================================================================ * + | Default MotionApps v6.12 28-byte FIFO packet structure: | + | | + | [QUAT W][ ][QUAT X][ ][QUAT Y][ ][QUAT Z][ ] | + | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | + | | + | [GYRO X][GYRO Y][GYRO Z][ACC X ][ACC Y ][ACC Z ] | + | 16 17 18 19 20 21 22 23 24 25 26 27 | + * ================================================================ */ + +// this block of memory gets written to the MPU on start-up, and it seems +// to be volatile memory, so it has to be done each time (it only takes ~1 +// second though) + +// *** this is a capture of the DMP Firmware V6.1.2 after all the messy changes were made so we can just load it +const unsigned char dmpMemory[MPU6050_DMP_CODE_SIZE] = { +/* bank # 0 */ +0x00, 0xF8, 0xF6, 0x2A, 0x3F, 0x68, 0xF5, 0x7A, 0x00, 0x06, 0xFF, 0xFE, 0x00, 0x03, 0x00, 0x00, +0x00, 0x65, 0x00, 0x54, 0xFF, 0xEF, 0x00, 0x00, 0xFA, 0x80, 0x00, 0x0B, 0x12, 0x82, 0x00, 0x01, +0x03, 0x0C, 0x30, 0xC3, 0x0A, 0x74, 0x56, 0x2D, 0x0D, 0x62, 0xDB, 0xC7, 0x16, 0xF4, 0xBA, 0x02, +0x38, 0x83, 0xF8, 0x83, 0x30, 0x00, 0xF8, 0x83, 0x25, 0x8E, 0xF8, 0x83, 0x30, 0x00, 0xF8, 0x83, +0xFF, 0xFF, 0xFF, 0xFF, 0x0C, 0xBD, 0xD8, 0x11, 0x24, 0x00, 0x04, 0x00, 0x1A, 0x82, 0x79, 0xA1, +0x00, 0x36, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x38, 0x83, 0x6F, 0xA2, +0x00, 0x3E, 0x03, 0x30, 0x40, 0x00, 0x00, 0x00, 0x02, 0xCA, 0xE3, 0x09, 0x3E, 0x80, 0x00, 0x00, +0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, +0x1F, 0xA4, 0xE8, 0xE4, 0xFF, 0xF5, 0xDC, 0xB9, 0x00, 0x5B, 0x79, 0xCF, 0x1F, 0x3F, 0x78, 0x76, +0x00, 0x86, 0x7C, 0x5A, 0x00, 0x86, 0x23, 0x47, 0xFA, 0xB9, 0x86, 0x31, 0x00, 0x74, 0x87, 0x8A, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x05, 0xFF, 0xFF, 0xE9, 0xA8, 0x00, 0x00, 0x21, 0x82, +0xFA, 0xB8, 0x4D, 0x46, 0xFF, 0xFA, 0xDF, 0x3D, 0xFF, 0xFF, 0xB2, 0xB3, 0x00, 0x00, 0x00, 0x00, +0x3F, 0xFF, 0xBA, 0x98, 0x00, 0x5D, 0xAC, 0x08, 0x00, 0x0A, 0x63, 0x78, 0x00, 0x01, 0x46, 0x21, +0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x42, 0xB5, 0x00, 0x06, 0x00, 0x64, 0x00, 0x64, 0x00, 0x06, +0x14, 0x06, 0x02, 0x9F, 0x0F, 0x47, 0x91, 0x32, 0xD9, 0x0E, 0x9F, 0xC9, 0x1D, 0xCF, 0x4C, 0x34, +0x3B, 0xB6, 0x7A, 0xE8, 0x00, 0x64, 0x00, 0x06, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE, +/* bank # 1 */ +0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x07, 0x00, 0x00, 0xFF, 0xF1, 0x00, 0x00, 0xFA, 0x46, 0x00, 0x00, 0xA2, 0xB8, 0x00, 0x00, +0x10, 0x00, 0x00, 0x00, 0x04, 0xD6, 0x00, 0x00, 0x04, 0xCC, 0x00, 0x00, 0x04, 0xCC, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x06, 0x00, 0x02, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x05, 0x00, 0x64, 0x00, 0x20, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x03, 0x00, +0x00, 0x00, 0x00, 0x32, 0xF8, 0x98, 0x00, 0x00, 0xFF, 0x65, 0x00, 0x00, 0x83, 0x0F, 0x00, 0x00, +0x00, 0x06, 0x00, 0x00, 0xFF, 0xF1, 0x00, 0x00, 0xFA, 0x46, 0x00, 0x00, 0xA2, 0xB8, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, +0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0xB2, 0x6A, 0x00, 0x02, 0x00, 0x00, +0x00, 0x01, 0xFB, 0x83, 0x00, 0x7C, 0x00, 0x00, 0xFB, 0x15, 0xFC, 0x00, 0x1F, 0xB4, 0xFF, 0x83, +0x00, 0x00, 0x00, 0x01, 0x00, 0x65, 0x00, 0x07, 0x00, 0x64, 0x03, 0xE8, 0x00, 0x64, 0x00, 0x28, +0x00, 0x00, 0xFF, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x16, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x10, 0x00, 0x00, 0x2F, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF4, 0x00, 0x00, 0x10, 0x00, +/* bank # 2 */ +0x00, 0x28, 0x00, 0x00, 0xFF, 0xFF, 0x45, 0x81, 0xFF, 0xFF, 0xFA, 0x72, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x01, 0x00, 0x05, 0xBA, 0xC6, 0x00, 0x47, 0x78, 0xA2, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x14, +0x00, 0x00, 0x23, 0xBB, 0x00, 0x2E, 0xA2, 0x5B, 0x00, 0x00, 0x05, 0x68, 0x00, 0x0B, 0xCF, 0x49, +0x00, 0x04, 0xFF, 0xFD, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, +0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x64, 0x00, 0x07, 0x00, 0x08, 0x00, 0x06, 0x00, 0x06, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x2E, 0xA2, 0x5B, 0x00, 0x00, 0x05, 0x68, 0x00, 0x0B, 0xCF, 0x49, 0x00, 0x00, 0x00, 0x00, +0x00, 0xF8, 0xF6, 0x2A, 0x3F, 0x68, 0xF5, 0x7A, 0x00, 0x04, 0xFF, 0xFD, 0x00, 0x02, 0x00, 0x00, +0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x0E, +0xFF, 0xFF, 0xFF, 0xCF, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0xFF, 0xFF, 0xFF, 0x9C, +0x00, 0x00, 0x43, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x64, +0xFF, 0xE5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* bank # 3 */ +0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x24, 0x26, 0xD3, +0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x10, 0x00, 0x96, 0x00, 0x3C, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x9E, 0x65, 0x5D, +0x0C, 0x0A, 0x4E, 0x68, 0xCD, 0xCF, 0x77, 0x09, 0x50, 0x16, 0x67, 0x59, 0xC6, 0x19, 0xCE, 0x82, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x71, 0x1C, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0xD7, 0x84, 0x00, 0x03, 0x00, 0x00, 0x00, +0x00, 0x11, 0xDC, 0x47, 0x03, 0x00, 0x00, 0x00, 0xC7, 0x93, 0x8F, 0x9D, 0x1E, 0x1B, 0x1C, 0x19, +0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0E, 0xDF, 0xA4, 0x38, 0x1F, 0x9E, 0x65, 0x5D, +0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x71, 0x1C, 0x02, 0x03, 0x18, 0x85, 0x00, 0x00, 0x40, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x3F, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xF4, 0xC9, 0xFF, 0xFF, 0xBC, 0xF0, 0x00, 0x01, 0x0C, 0x0F, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xF5, 0xB7, 0xBA, 0xB3, 0x67, 0x7D, 0xDF, 0x7E, 0x72, 0x90, 0x2E, 0x55, 0x4C, 0xF6, 0xE6, 0x88, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* bank # 4 */ +0xD8, 0xDC, 0xB4, 0xB8, 0xB0, 0xD8, 0xB9, 0xAB, 0xF3, 0xF8, 0xFA, 0xB3, 0xB7, 0xBB, 0x8E, 0x9E, +0xAE, 0xF1, 0x32, 0xF5, 0x1B, 0xF1, 0xB4, 0xB8, 0xB0, 0x80, 0x97, 0xF1, 0xA9, 0xDF, 0xDF, 0xDF, +0xAA, 0xDF, 0xDF, 0xDF, 0xF2, 0xAA, 0x4C, 0xCD, 0x6C, 0xA9, 0x0C, 0xC9, 0x2C, 0x97, 0xF1, 0xA9, +0x89, 0x26, 0x46, 0x66, 0xB2, 0x89, 0x99, 0xA9, 0x2D, 0x55, 0x7D, 0xB0, 0xB0, 0x8A, 0xA8, 0x96, +0x36, 0x56, 0x76, 0xF1, 0xBA, 0xA3, 0xB4, 0xB2, 0x80, 0xC0, 0xB8, 0xA8, 0x97, 0x11, 0xB2, 0x83, +0x98, 0xBA, 0xA3, 0xF0, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0xB2, 0xB9, 0xB4, 0x98, 0x83, 0xF1, +0xA3, 0x29, 0x55, 0x7D, 0xBA, 0xB5, 0xB1, 0xA3, 0x83, 0x93, 0xF0, 0x00, 0x28, 0x50, 0xF5, 0xB2, +0xB6, 0xAA, 0x83, 0x93, 0x28, 0x54, 0x7C, 0xF1, 0xB9, 0xA3, 0x82, 0x93, 0x61, 0xBA, 0xA2, 0xDA, +0xDE, 0xDF, 0xDB, 0x81, 0x9A, 0xB9, 0xAE, 0xF5, 0x60, 0x68, 0x70, 0xF1, 0xDA, 0xBA, 0xA2, 0xDF, +0xD9, 0xBA, 0xA2, 0xFA, 0xB9, 0xA3, 0x82, 0x92, 0xDB, 0x31, 0xBA, 0xA2, 0xD9, 0xBA, 0xA2, 0xF8, +0xDF, 0x85, 0xA4, 0xD0, 0xC1, 0xBB, 0xAD, 0x83, 0xC2, 0xC5, 0xC7, 0xB8, 0xA2, 0xDF, 0xDF, 0xDF, +0xBA, 0xA0, 0xDF, 0xDF, 0xDF, 0xD8, 0xD8, 0xF1, 0xB8, 0xAA, 0xB3, 0x8D, 0xB4, 0x98, 0x0D, 0x35, +0x5D, 0xB2, 0xB6, 0xBA, 0xAF, 0x8C, 0x96, 0x19, 0x8F, 0x9F, 0xA7, 0x0E, 0x16, 0x1E, 0xB4, 0x9A, +0xB8, 0xAA, 0x87, 0x2C, 0x54, 0x7C, 0xBA, 0xA4, 0xB0, 0x8A, 0xB6, 0x91, 0x32, 0x56, 0x76, 0xB2, +0x84, 0x94, 0xA4, 0xC8, 0x08, 0xCD, 0xD8, 0xB8, 0xB4, 0xB0, 0xF1, 0x99, 0x82, 0xA8, 0x2D, 0x55, +0x7D, 0x98, 0xA8, 0x0E, 0x16, 0x1E, 0xA2, 0x2C, 0x54, 0x7C, 0x92, 0xA4, 0xF0, 0x2C, 0x50, 0x78, +/* bank # 5 */ +0xF1, 0x84, 0xA8, 0x98, 0xC4, 0xCD, 0xFC, 0xD8, 0x0D, 0xDB, 0xA8, 0xFC, 0x2D, 0xF3, 0xD9, 0xBA, +0xA6, 0xF8, 0xDA, 0xBA, 0xA6, 0xDE, 0xD8, 0xBA, 0xB2, 0xB6, 0x86, 0x96, 0xA6, 0xD0, 0xF3, 0xC8, +0x41, 0xDA, 0xA6, 0xC8, 0xF8, 0xD8, 0xB0, 0xB4, 0xB8, 0x82, 0xA8, 0x92, 0xF5, 0x2C, 0x54, 0x88, +0x98, 0xF1, 0x35, 0xD9, 0xF4, 0x18, 0xD8, 0xF1, 0xA2, 0xD0, 0xF8, 0xF9, 0xA8, 0x84, 0xD9, 0xC7, +0xDF, 0xF8, 0xF8, 0x83, 0xC5, 0xDA, 0xDF, 0x69, 0xDF, 0x83, 0xC1, 0xD8, 0xF4, 0x01, 0x14, 0xF1, +0xA8, 0x82, 0x4E, 0xA8, 0x84, 0xF3, 0x11, 0xD1, 0x82, 0xF5, 0xD9, 0x92, 0x28, 0x97, 0x88, 0xF1, +0x09, 0xF4, 0x1C, 0x1C, 0xD8, 0x84, 0xA8, 0xF3, 0xC0, 0xF9, 0xD1, 0xD9, 0x97, 0x82, 0xF1, 0x29, +0xF4, 0x0D, 0xD8, 0xF3, 0xF9, 0xF9, 0xD1, 0xD9, 0x82, 0xF4, 0xC2, 0x03, 0xD8, 0xDE, 0xDF, 0x1A, +0xD8, 0xF1, 0xA2, 0xFA, 0xF9, 0xA8, 0x84, 0x98, 0xD9, 0xC7, 0xDF, 0xF8, 0xF8, 0xF8, 0x83, 0xC7, +0xDA, 0xDF, 0x69, 0xDF, 0xF8, 0x83, 0xC3, 0xD8, 0xF4, 0x01, 0x14, 0xF1, 0x98, 0xA8, 0x82, 0x2E, +0xA8, 0x84, 0xF3, 0x11, 0xD1, 0x82, 0xF5, 0xD9, 0x92, 0x50, 0x97, 0x88, 0xF1, 0x09, 0xF4, 0x1C, +0xD8, 0x84, 0xA8, 0xF3, 0xC0, 0xF8, 0xF9, 0xD1, 0xD9, 0x97, 0x82, 0xF1, 0x49, 0xF4, 0x0D, 0xD8, +0xF3, 0xF9, 0xF9, 0xD1, 0xD9, 0x82, 0xF4, 0xC4, 0x03, 0xD8, 0xDE, 0xDF, 0xD8, 0xF1, 0xAD, 0x88, +0x98, 0xCC, 0xA8, 0x09, 0xF9, 0xD9, 0x82, 0x92, 0xA8, 0xF5, 0x7C, 0xF1, 0x88, 0x3A, 0xCF, 0x94, +0x4A, 0x6E, 0x98, 0xDB, 0x69, 0x31, 0xDA, 0xAD, 0xF2, 0xDE, 0xF9, 0xD8, 0x87, 0x95, 0xA8, 0xF2, +0x21, 0xD1, 0xDA, 0xA5, 0xF9, 0xF4, 0x17, 0xD9, 0xF1, 0xAE, 0x8E, 0xD0, 0xC0, 0xC3, 0xAE, 0x82, +/* bank # 6 */ +0xC6, 0x84, 0xC3, 0xA8, 0x85, 0x95, 0xC8, 0xA5, 0x88, 0xF2, 0xC0, 0xF1, 0xF4, 0x01, 0x0E, 0xF1, +0x8E, 0x9E, 0xA8, 0xC6, 0x3E, 0x56, 0xF5, 0x54, 0xF1, 0x88, 0x72, 0xF4, 0x01, 0x15, 0xF1, 0x98, +0x45, 0x85, 0x6E, 0xF5, 0x8E, 0x9E, 0x04, 0x88, 0xF1, 0x42, 0x98, 0x5A, 0x8E, 0x9E, 0x06, 0x88, +0x69, 0xF4, 0x01, 0x1C, 0xF1, 0x98, 0x1E, 0x11, 0x08, 0xD0, 0xF5, 0x04, 0xF1, 0x1E, 0x97, 0x02, +0x02, 0x98, 0x36, 0x25, 0xDB, 0xF9, 0xD9, 0x85, 0xA5, 0xF3, 0xC1, 0xDA, 0x85, 0xA5, 0xF3, 0xDF, +0xD8, 0x85, 0x95, 0xA8, 0xF3, 0x09, 0xDA, 0xA5, 0xFA, 0xD8, 0x82, 0x92, 0xA8, 0xF5, 0x78, 0xF1, +0x88, 0x1A, 0x84, 0x9F, 0x26, 0x88, 0x98, 0x21, 0xDA, 0xF4, 0x1D, 0xF3, 0xD8, 0x87, 0x9F, 0x39, +0xD1, 0xAF, 0xD9, 0xDF, 0xDF, 0xFB, 0xF9, 0xF4, 0x0C, 0xF3, 0xD8, 0xFA, 0xD0, 0xF8, 0xDA, 0xF9, +0xF9, 0xD0, 0xDF, 0xD9, 0xF9, 0xD8, 0xF4, 0x0B, 0xD8, 0xF3, 0x87, 0x9F, 0x39, 0xD1, 0xAF, 0xD9, +0xDF, 0xDF, 0xF4, 0x1D, 0xF3, 0xD8, 0xFA, 0xFC, 0xA8, 0x69, 0xF9, 0xF9, 0xAF, 0xD0, 0xDA, 0xDE, +0xFA, 0xD9, 0xF8, 0x8F, 0x9F, 0xA8, 0xF1, 0xCC, 0xF3, 0x98, 0xDB, 0x45, 0xD9, 0xAF, 0xDF, 0xD0, +0xF8, 0xD8, 0xF1, 0x8F, 0x9F, 0xA8, 0xCA, 0xF3, 0x88, 0x09, 0xDA, 0xAF, 0x8F, 0xCB, 0xF8, 0xD8, +0xF2, 0xAD, 0x97, 0x8D, 0x0C, 0xD9, 0xA5, 0xDF, 0xF9, 0xBA, 0xA6, 0xF3, 0xFA, 0xF4, 0x12, 0xF2, +0xD8, 0x95, 0x0D, 0xD1, 0xD9, 0xBA, 0xA6, 0xF3, 0xFA, 0xDA, 0xA5, 0xF2, 0xC1, 0xBA, 0xA6, 0xF3, +0xDF, 0xD8, 0xF1, 0xBA, 0xB2, 0xB6, 0x86, 0x96, 0xA6, 0xD0, 0xCA, 0xF3, 0x49, 0xDA, 0xA6, 0xCB, +0xF8, 0xD8, 0xB0, 0xB4, 0xB8, 0xD8, 0xAD, 0x84, 0xF2, 0xC0, 0xDF, 0xF1, 0x8F, 0xCB, 0xC3, 0xA8, +/* bank # 7 */ +0xB2, 0xB6, 0x86, 0x96, 0xC8, 0xC1, 0xCB, 0xC3, 0xF3, 0xB0, 0xB4, 0x88, 0x98, 0xA8, 0x21, 0xDB, +0x71, 0x8D, 0x9D, 0x71, 0x85, 0x95, 0x21, 0xD9, 0xAD, 0xF2, 0xFA, 0xD8, 0x85, 0x97, 0xA8, 0x28, +0xD9, 0xF4, 0x08, 0xD8, 0xF2, 0x8D, 0x29, 0xDA, 0xF4, 0x05, 0xD9, 0xF2, 0x85, 0xA4, 0xC2, 0xF2, +0xD8, 0xA8, 0x8D, 0x94, 0x01, 0xD1, 0xD9, 0xF4, 0x11, 0xF2, 0xD8, 0x87, 0x21, 0xD8, 0xF4, 0x0A, +0xD8, 0xF2, 0x84, 0x98, 0xA8, 0xC8, 0x01, 0xD1, 0xD9, 0xF4, 0x11, 0xD8, 0xF3, 0xA4, 0xC8, 0xBB, +0xAF, 0xD0, 0xF2, 0xDE, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xD8, 0xF1, 0xB8, 0xF6, +0xB5, 0xB9, 0xB0, 0x8A, 0x95, 0xA3, 0xDE, 0x3C, 0xA3, 0xD9, 0xF8, 0xD8, 0x5C, 0xA3, 0xD9, 0xF8, +0xD8, 0x7C, 0xA3, 0xD9, 0xF8, 0xD8, 0xF8, 0xF9, 0xD1, 0xA5, 0xD9, 0xDF, 0xDA, 0xFA, 0xD8, 0xB1, +0x85, 0x30, 0xF7, 0xD9, 0xDE, 0xD8, 0xF8, 0x30, 0xAD, 0xDA, 0xDE, 0xD8, 0xF2, 0xB4, 0x8C, 0x99, +0xA3, 0x2D, 0x55, 0x7D, 0xA0, 0x83, 0xDF, 0xDF, 0xDF, 0xB5, 0x91, 0xA0, 0xF6, 0x29, 0xD9, 0xFB, +0xD8, 0xA0, 0xFC, 0x29, 0xD9, 0xFA, 0xD8, 0xA0, 0xD0, 0x51, 0xD9, 0xF8, 0xD8, 0xFC, 0x51, 0xD9, +0xF9, 0xD8, 0x79, 0xD9, 0xFB, 0xD8, 0xA0, 0xD0, 0xFC, 0x79, 0xD9, 0xFA, 0xD8, 0xA1, 0xF9, 0xF9, +0xF9, 0xF9, 0xF9, 0xA0, 0xDA, 0xDF, 0xDF, 0xDF, 0xD8, 0xA1, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xAC, +0xDE, 0xF8, 0xAD, 0xDE, 0x83, 0x93, 0xAC, 0x2C, 0x54, 0x7C, 0xF1, 0xA8, 0xDF, 0xDF, 0xDF, 0xF6, +0x9D, 0x2C, 0xDA, 0xA0, 0xDF, 0xD9, 0xFA, 0xDB, 0x2D, 0xF8, 0xD8, 0xA8, 0x50, 0xDA, 0xA0, 0xD0, +0xDE, 0xD9, 0xD0, 0xF8, 0xF8, 0xF8, 0xDB, 0x55, 0xF8, 0xD8, 0xA8, 0x78, 0xDA, 0xA0, 0xD0, 0xDF, +/* bank # 8 */ +0xD9, 0xD0, 0xFA, 0xF8, 0xF8, 0xF8, 0xF8, 0xDB, 0x7D, 0xF8, 0xD8, 0x9C, 0xA8, 0x8C, 0xF5, 0x30, +0xDB, 0x38, 0xD9, 0xD0, 0xDE, 0xDF, 0xA0, 0xD0, 0xDE, 0xDF, 0xD8, 0xA8, 0x48, 0xDB, 0x58, 0xD9, +0xDF, 0xD0, 0xDE, 0xA0, 0xDF, 0xD0, 0xDE, 0xD8, 0xA8, 0x68, 0xDB, 0x70, 0xD9, 0xDF, 0xDF, 0xA0, +0xDF, 0xDF, 0xD8, 0xF1, 0xA8, 0x88, 0x90, 0x2C, 0x54, 0x7C, 0x98, 0xA8, 0xD0, 0x5C, 0x38, 0xD1, +0xDA, 0xF2, 0xAE, 0x8C, 0xDF, 0xF9, 0xD8, 0xB0, 0x87, 0xA8, 0xC1, 0xC1, 0xB1, 0x88, 0xA8, 0xC6, +0xF9, 0xF9, 0xDA, 0x36, 0xD8, 0xA8, 0xF9, 0xDA, 0x36, 0xD8, 0xA8, 0xF9, 0xDA, 0x36, 0xD8, 0xA8, +0xF9, 0xDA, 0x36, 0xD8, 0xA8, 0xF9, 0xDA, 0x36, 0xD8, 0xF7, 0x8D, 0x9D, 0xAD, 0xF8, 0x18, 0xDA, +0xF2, 0xAE, 0xDF, 0xD8, 0xF7, 0xAD, 0xFA, 0x30, 0xD9, 0xA4, 0xDE, 0xF9, 0xD8, 0xF2, 0xAE, 0xDE, +0xFA, 0xF9, 0x83, 0xA7, 0xD9, 0xC3, 0xC5, 0xC7, 0xF1, 0x88, 0x9B, 0xA7, 0x7A, 0xAD, 0xF7, 0xDE, +0xDF, 0xA4, 0xF8, 0x84, 0x94, 0x08, 0xA7, 0x97, 0xF3, 0x00, 0xAE, 0xF2, 0x98, 0x19, 0xA4, 0x88, +0xC6, 0xA3, 0x94, 0x88, 0xF6, 0x32, 0xDF, 0xF2, 0x83, 0x93, 0xDB, 0x09, 0xD9, 0xF2, 0xAA, 0xDF, +0xD8, 0xD8, 0xAE, 0xF8, 0xF9, 0xD1, 0xDA, 0xF3, 0xA4, 0xDE, 0xA7, 0xF1, 0x88, 0x9B, 0x7A, 0xD8, +0xF3, 0x84, 0x94, 0xAE, 0x19, 0xF9, 0xDA, 0xAA, 0xF1, 0xDF, 0xD8, 0xA8, 0x81, 0xC0, 0xC3, 0xC5, +0xC7, 0xA3, 0x92, 0x83, 0xF6, 0x28, 0xAD, 0xDE, 0xD9, 0xF8, 0xD8, 0xA3, 0x50, 0xAD, 0xD9, 0xF8, +0xD8, 0xA3, 0x78, 0xAD, 0xD9, 0xF8, 0xD8, 0xF8, 0xF9, 0xD1, 0xA1, 0xDA, 0xDE, 0xC3, 0xC5, 0xC7, +0xD8, 0xA1, 0x81, 0x94, 0xF8, 0x18, 0xF2, 0xB0, 0x89, 0xAC, 0xC3, 0xC5, 0xC7, 0xF1, 0xD8, 0xB8, +/* bank # 9 */ +0xB4, 0xB0, 0x97, 0x86, 0xA8, 0x31, 0x9B, 0x06, 0x99, 0x07, 0xAB, 0x97, 0x28, 0x88, 0x9B, 0xF0, +0x0C, 0x20, 0x14, 0x40, 0xB0, 0xB4, 0xB8, 0xF0, 0xA8, 0x8A, 0x9A, 0x28, 0x50, 0x78, 0xB7, 0x9B, +0xA8, 0x29, 0x51, 0x79, 0x24, 0x70, 0x59, 0x44, 0x69, 0x38, 0x64, 0x48, 0x31, 0xF1, 0xBB, 0xAB, +0x88, 0x00, 0x2C, 0x54, 0x7C, 0xF0, 0xB3, 0x8B, 0xB8, 0xA8, 0x04, 0x28, 0x50, 0x78, 0xF1, 0xB0, +0x88, 0xB4, 0x97, 0x26, 0xA8, 0x59, 0x98, 0xBB, 0xAB, 0xB3, 0x8B, 0x02, 0x26, 0x46, 0x66, 0xB0, +0xB8, 0xF0, 0x8A, 0x9C, 0xA8, 0x29, 0x51, 0x79, 0x8B, 0x29, 0x51, 0x79, 0x8A, 0x24, 0x70, 0x59, +0x8B, 0x20, 0x58, 0x71, 0x8A, 0x44, 0x69, 0x38, 0x8B, 0x39, 0x40, 0x68, 0x8A, 0x64, 0x48, 0x31, +0x8B, 0x30, 0x49, 0x60, 0x88, 0xF1, 0xAC, 0x00, 0x2C, 0x54, 0x7C, 0xF0, 0x8C, 0xA8, 0x04, 0x28, +0x50, 0x78, 0xF1, 0x88, 0x97, 0x26, 0xA8, 0x59, 0x98, 0xAC, 0x8C, 0x02, 0x26, 0x46, 0x66, 0xF0, +0x89, 0x9C, 0xA8, 0x29, 0x51, 0x79, 0x24, 0x70, 0x59, 0x44, 0x69, 0x38, 0x64, 0x48, 0x31, 0xA9, +0x88, 0x09, 0x20, 0x59, 0x70, 0xAB, 0x11, 0x38, 0x40, 0x69, 0xA8, 0x19, 0x31, 0x48, 0x60, 0x8C, +0xA8, 0x3C, 0x41, 0x5C, 0x20, 0x7C, 0x00, 0xF1, 0x87, 0x98, 0x19, 0x86, 0xA8, 0x6E, 0x76, 0x7E, +0xA9, 0x99, 0x88, 0x2D, 0x55, 0x7D, 0xD8, 0xB1, 0xB5, 0xB9, 0xA3, 0xDF, 0xDF, 0xDF, 0xAE, 0xD0, +0xDF, 0xAA, 0xD0, 0xDE, 0xF2, 0xAB, 0xF8, 0xF9, 0xD9, 0xB0, 0x87, 0xC4, 0xAA, 0xF1, 0xDF, 0xDF, +0xBB, 0xAF, 0xDF, 0xDF, 0xB9, 0xD8, 0xB1, 0xF1, 0xA3, 0x97, 0x8E, 0x60, 0xDF, 0xB0, 0x84, 0xF2, +0xC8, 0xF8, 0xF9, 0xD9, 0xDE, 0xD8, 0x93, 0x85, 0xF1, 0x4A, 0xB1, 0x83, 0xA3, 0x08, 0xB5, 0x83, +/* bank # 10 */ +0x9A, 0x08, 0x10, 0xB7, 0x9F, 0x10, 0xD8, 0xF1, 0xB0, 0xBA, 0xAE, 0xB0, 0x8A, 0xC2, 0xB2, 0xB6, +0x8E, 0x9E, 0xF1, 0xFB, 0xD9, 0xF4, 0x1D, 0xD8, 0xF9, 0xD9, 0x0C, 0xF1, 0xD8, 0xF8, 0xF8, 0xAD, +0x61, 0xD9, 0xAE, 0xFB, 0xD8, 0xF4, 0x0C, 0xF1, 0xD8, 0xF8, 0xF8, 0xAD, 0x19, 0xD9, 0xAE, 0xFB, +0xDF, 0xD8, 0xF4, 0x16, 0xF1, 0xD8, 0xF8, 0xAD, 0x8D, 0x61, 0xD9, 0xF4, 0xF4, 0xAC, 0xF5, 0x9C, +0x9C, 0x8D, 0xDF, 0x2B, 0xBA, 0xB6, 0xAE, 0xFA, 0xF8, 0xF4, 0x0B, 0xD8, 0xF1, 0xAE, 0xD0, 0xF8, +0xAD, 0x51, 0xDA, 0xAE, 0xFA, 0xF8, 0xF1, 0xD8, 0xB9, 0xB1, 0xB6, 0xA3, 0x83, 0x9C, 0x08, 0xB9, +0xB1, 0x83, 0x9A, 0xB5, 0xAA, 0xC0, 0xFD, 0x30, 0x83, 0xB7, 0x9F, 0x10, 0xB5, 0x8B, 0x93, 0xF2, +0x02, 0x02, 0xD1, 0xAB, 0xDA, 0xDE, 0xD8, 0xF1, 0xB0, 0x80, 0xBA, 0xAB, 0xC0, 0xC3, 0xB2, 0x84, +0xC1, 0xC3, 0xD8, 0xB1, 0xB9, 0xF3, 0x8B, 0xA3, 0x91, 0xB6, 0x09, 0xB4, 0xD9, 0xAB, 0xDE, 0xB0, +0x87, 0x9C, 0xB9, 0xA3, 0xDD, 0xF1, 0xB3, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0xB0, 0x87, 0x20, 0x28, +0x30, 0x38, 0xB2, 0x8B, 0xB6, 0x9B, 0xF2, 0xA3, 0xC0, 0xC8, 0xC2, 0xC4, 0xCC, 0xC6, 0xA3, 0xA3, +0xA3, 0xF1, 0xB0, 0x87, 0xB5, 0x9A, 0xD8, 0xF3, 0x9B, 0xA3, 0xA3, 0xDC, 0xBA, 0xAC, 0xDF, 0xB9, +0xA3, 0xFE, 0xF2, 0xAB, 0xC4, 0xAA, 0xF1, 0xDF, 0xDF, 0xBB, 0xAF, 0xDF, 0xDF, 0xA3, 0xA3, 0xA3, +0xD8, 0xD8, 0xD8, 0xBB, 0xB3, 0xB7, 0xF1, 0xAA, 0xF9, 0xDA, 0xFF, 0xD9, 0x80, 0x9A, 0xAA, 0x28, +0xB4, 0x80, 0x98, 0xA7, 0x20, 0xB7, 0x97, 0x87, 0xA8, 0x66, 0x88, 0xF0, 0x79, 0x51, 0xF1, 0x90, +0x2C, 0x87, 0x0C, 0xA7, 0x81, 0x97, 0x62, 0x93, 0xF0, 0x71, 0x71, 0x60, 0x85, 0x94, 0x01, 0x29, +/* bank # 11 */ +0x51, 0x79, 0x90, 0xA5, 0xF1, 0x28, 0x4C, 0x6C, 0x87, 0x0C, 0x95, 0x18, 0x85, 0x78, 0xA3, 0x83, +0x90, 0x28, 0x4C, 0x6C, 0x88, 0x6C, 0xD8, 0xF3, 0xA2, 0x82, 0x00, 0xF2, 0x10, 0xA8, 0x92, 0x19, +0x80, 0xA2, 0xF2, 0xD9, 0x26, 0xD8, 0xF1, 0x88, 0xA8, 0x4D, 0xD9, 0x48, 0xD8, 0x96, 0xA8, 0x39, +0x80, 0xD9, 0x3C, 0xD8, 0x95, 0x80, 0xA8, 0x39, 0xA6, 0x86, 0x98, 0xD9, 0x2C, 0xDA, 0x87, 0xA7, +0x2C, 0xD8, 0xA8, 0x89, 0x95, 0x19, 0xA9, 0x80, 0xD9, 0x38, 0xD8, 0xA8, 0x89, 0x39, 0xA9, 0x80, +0xDA, 0x3C, 0xD8, 0xA8, 0x2E, 0xA8, 0x39, 0x90, 0xD9, 0x0C, 0xD8, 0xA8, 0x95, 0x31, 0x98, 0xD9, +0x0C, 0xD8, 0xA8, 0x09, 0xD9, 0xFF, 0xD8, 0x01, 0xDA, 0xFF, 0xD8, 0x95, 0x39, 0xA9, 0xDA, 0x26, +0xFF, 0xD8, 0x90, 0xA8, 0x0D, 0x89, 0x99, 0xA8, 0x10, 0x80, 0x98, 0x21, 0xDA, 0x2E, 0xD8, 0x89, +0x99, 0xA8, 0x31, 0x80, 0xDA, 0x2E, 0xD8, 0xA8, 0x86, 0x96, 0x31, 0x80, 0xDA, 0x2E, 0xD8, 0xA8, +0x87, 0x31, 0x80, 0xDA, 0x2E, 0xD8, 0xA8, 0x82, 0x92, 0xF3, 0x41, 0x80, 0xF1, 0xD9, 0x2E, 0xD8, +0xA8, 0x82, 0xF3, 0x19, 0x80, 0xF1, 0xD9, 0x2E, 0xD8, 0x82, 0xAC, 0xF3, 0xC0, 0xA2, 0x80, 0x22, +0xF1, 0xA6, 0x2E, 0xA7, 0x2E, 0xA9, 0x22, 0x98, 0xA8, 0x29, 0xDA, 0xAC, 0xDE, 0xFF, 0xD8, 0xA2, +0xF2, 0x2A, 0xF1, 0xA9, 0x2E, 0x82, 0x92, 0xA8, 0xF2, 0x31, 0x80, 0xA6, 0x96, 0xF1, 0xD9, 0x00, +0xAC, 0x8C, 0x9C, 0x0C, 0x30, 0xAC, 0xDE, 0xD0, 0xDE, 0xFF, 0xD8, 0x8C, 0x9C, 0xAC, 0xD0, 0x10, +0xAC, 0xDE, 0x80, 0x92, 0xA2, 0xF2, 0x4C, 0x82, 0xA8, 0xF1, 0xCA, 0xF2, 0x35, 0xF1, 0x96, 0x88, +0xA6, 0xD9, 0x00, 0xD8, 0xF1, 0xFF, +}; + +// this divisor is pre configured into the above image and can't be modified at this time. +#ifndef MPU6050_DMP_FIFO_RATE_DIVISOR +#define MPU6050_DMP_FIFO_RATE_DIVISOR 0x01 // The New instance of the Firmware has this as the default +#endif + +// this is the most basic initialization I can create. with the intent that we access the register bytes as few times as needed to get the job done. +// for detailed descriptins of all registers and there purpose google "MPU-6000/MPU-6050 Register Map and Descriptions" +uint8_t MPU6050::dmpInitialize() { // Lets get it over with fast Write everything once and set it up necely + uint8_t val; + uint16_t ival; + // Reset procedure per instructions in the "MPU-6000/MPU-6050 Register Map and Descriptions" page 41 + I2Cdev::writeBit(devAddr,0x6B, 7, (val = 1)); //PWR_MGMT_1: reset with 100ms delay + sleep_ms(100); + I2Cdev::writeBits(devAddr,0x6A, 2, 3, (val = 0b111)); // full SIGNAL_PATH_RESET: with another 100ms delay + sleep_ms(100); + I2Cdev::writeBytes(devAddr,0x6B, 1, &(val = 0x01)); // 1000 0001 PWR_MGMT_1:Clock Source Select PLL_X_gyro + I2Cdev::writeBytes(devAddr,0x38, 1, &(val = 0x00)); // 0000 0000 INT_ENABLE: no Interrupt + I2Cdev::writeBytes(devAddr,0x23, 1, &(val = 0x00)); // 0000 0000 MPU FIFO_EN: (all off) Using DMP's FIFO instead + I2Cdev::writeBytes(devAddr,0x1C, 1, &(val = 0x00)); // 0000 0000 ACCEL_CONFIG: 0 = Accel Full Scale Select: 2g + I2Cdev::writeBytes(devAddr,0x37, 1, &(val = 0x80)); // 1001 0000 INT_PIN_CFG: ACTL The logic level for int pin is active low. and interrupt status bits are cleared on any read + I2Cdev::writeBytes(devAddr,0x6B, 1, &(val = 0x01)); // 0000 0001 PWR_MGMT_1: Clock Source Select PLL_X_gyro + I2Cdev::writeBytes(devAddr,0x19, 1, &(val = 0x04)); // 0000 0100 SMPLRT_DIV: Divides the internal sample rate 400Hz ( Sample Rate = Gyroscope Output Rate / (1 + SMPLRT_DIV)) + I2Cdev::writeBytes(devAddr,0x1A, 1, &(val = 0x01)); // 0000 0001 CONFIG: Digital Low Pass Filter (DLPF) Configuration 188HZ //Im betting this will be the beat + if (!writeProgMemoryBlock(dmpMemory, MPU6050_DMP_CODE_SIZE)) return 1; // Loads the DMP image into the MPU6050 Memory // Should Never Fail + I2Cdev::writeWords(devAddr, 0x70, 1, &(ival = 0x0400)); // DMP Program Start Address + I2Cdev::writeBytes(devAddr,0x1B, 1, &(val = 0x18)); // 0001 1000 GYRO_CONFIG: 3 = +2000 Deg/sec + I2Cdev::writeBytes(devAddr,0x6A, 1, &(val = 0xC0)); // 1100 1100 USER_CTRL: Enable Fifo and Reset Fifo + I2Cdev::writeBytes(devAddr,0x38, 1, &(val = 0x02)); // 0000 0010 INT_ENABLE: RAW_DMP_INT_EN on + I2Cdev::writeBit(devAddr,0x6A, 2, 1); // Reset FIFO one last time just for kicks. (MPUi2cWrite reads 0x6A first and only alters 1 bit and then saves the byte) + + setDMPEnabled(false); // disable DMP for compatibility with the MPU6050 library +/* + dmpPacketSize += 16;//DMP_FEATURE_6X_LP_QUAT + dmpPacketSize += 6;//DMP_FEATURE_SEND_RAW_ACCEL + dmpPacketSize += 6;//DMP_FEATURE_SEND_RAW_GYRO +*/ + dmpPacketSize = 28; + return 0; +} + +bool MPU6050::dmpPacketAvailable() { + return getFIFOCount() >= dmpGetFIFOPacketSize(); +} + +// uint8_t MPU6050::dmpSetFIFORate(uint8_t fifoRate); +// uint8_t MPU6050::dmpGetFIFORate(); +// uint8_t MPU6050::dmpGetSampleStepSizeMS(); +// uint8_t MPU6050::dmpGetSampleFrequency(); +// int32_t MPU6050::dmpDecodeTemperature(int8_t tempReg); + +//uint8_t MPU6050::dmpRegisterFIFORateProcess(inv_obj_func func, int16_t priority); +//uint8_t MPU6050::dmpUnregisterFIFORateProcess(inv_obj_func func); +//uint8_t MPU6050::dmpRunFIFORateProcesses(); + +// uint8_t MPU6050::dmpSendQuaternion(uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendGyro(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendAccel(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendLinearAccel(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendLinearAccelInWorld(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendControlData(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendSensorData(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendExternalSensorData(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendGravity(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendPacketNumber(uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendQuantizedAccel(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050::dmpSendEIS(uint_fast16_t elements, uint_fast16_t accuracy); + +uint8_t MPU6050::dmpGetAccel(int32_t *data, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + data[0] = (((uint32_t)packet[16] << 8) | packet[17]); + data[1] = (((uint32_t)packet[18] << 8) | packet[19]); + data[2] = (((uint32_t)packet[20] << 8) | packet[21]); + return 0; +} +uint8_t MPU6050::dmpGetAccel(int16_t *data, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + data[0] = (packet[16] << 8) | packet[17]; + data[1] = (packet[18] << 8) | packet[19]; + data[2] = (packet[20] << 8) | packet[21]; + return 0; +} +uint8_t MPU6050::dmpGetAccel(VectorInt16 *v, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + v -> x = (packet[16] << 8) | packet[17]; + v -> y = (packet[18] << 8) | packet[19]; + v -> z = (packet[20] << 8) | packet[21]; + return 0; +} +uint8_t MPU6050::dmpGetQuaternion(int32_t *data, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + data[0] = (((uint32_t)packet[0] << 24) | ((uint32_t)packet[1] << 16) | ((uint32_t)packet[2] << 8) | packet[3]); + data[1] = (((uint32_t)packet[4] << 24) | ((uint32_t)packet[5] << 16) | ((uint32_t)packet[6] << 8) | packet[7]); + data[2] = (((uint32_t)packet[8] << 24) | ((uint32_t)packet[9] << 16) | ((uint32_t)packet[10] << 8) | packet[11]); + data[3] = (((uint32_t)packet[12] << 24) | ((uint32_t)packet[13] << 16) | ((uint32_t)packet[14] << 8) | packet[15]); + return 0; +} +uint8_t MPU6050::dmpGetQuaternion(int16_t *data, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + data[0] = ((packet[0] << 8) | packet[1]); + data[1] = ((packet[4] << 8) | packet[5]); + data[2] = ((packet[8] << 8) | packet[9]); + data[3] = ((packet[12] << 8) | packet[13]); + return 0; +} +uint8_t MPU6050::dmpGetQuaternion(Quaternion *q, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + int16_t qI[4]; + uint8_t status = dmpGetQuaternion(qI, packet); + if (status == 0) { + q -> w = (float)qI[0] / 16384.0f; + q -> x = (float)qI[1] / 16384.0f; + q -> y = (float)qI[2] / 16384.0f; + q -> z = (float)qI[3] / 16384.0f; + return 0; + } + return status; // int16 return value, indicates error if this line is reached +} +// uint8_t MPU6050::dmpGet6AxisQuaternion(long *data, const uint8_t* packet); +// uint8_t MPU6050::dmpGetRelativeQuaternion(long *data, const uint8_t* packet); +uint8_t MPU6050::dmpGetGyro(int32_t *data, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + data[0] = (((uint32_t)packet[22] << 8) | packet[23]); + data[1] = (((uint32_t)packet[24] << 8) | packet[25]); + data[2] = (((uint32_t)packet[26] << 8) | packet[27]); + return 0; +} +uint8_t MPU6050::dmpGetGyro(int16_t *data, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + data[0] = (packet[22] << 8) | packet[23]; + data[1] = (packet[24] << 8) | packet[25]; + data[2] = (packet[26] << 8) | packet[27]; + return 0; +} +uint8_t MPU6050::dmpGetGyro(VectorInt16 *v, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + v -> x = (packet[22] << 8) | packet[23]; + v -> y = (packet[24] << 8) | packet[25]; + v -> z = (packet[26] << 8) | packet[27]; + return 0; +} +// uint8_t MPU6050::dmpSetLinearAccelFilterCoefficient(float coef); +// uint8_t MPU6050::dmpGetLinearAccel(long *data, const uint8_t* packet); +uint8_t MPU6050::dmpGetLinearAccel(VectorInt16 *v, VectorInt16 *vRaw, VectorFloat *gravity) { + // get rid of the gravity component (+1g = +8192 in standard DMP FIFO packet, sensitivity is 2g) + v -> x = vRaw -> x - gravity -> x*8192; + v -> y = vRaw -> y - gravity -> y*8192; + v -> z = vRaw -> z - gravity -> z*8192; + return 0; +} +// uint8_t MPU6050::dmpGetLinearAccelInWorld(long *data, const uint8_t* packet); +uint8_t MPU6050::dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Quaternion *q) { + // rotate measured 3D acceleration vector into original state + // frame of reference based on orientation quaternion + memcpy(v, vReal, sizeof(VectorInt16)); + v -> rotate(q); + return 0; +} +// uint8_t MPU6050::dmpGetGyroAndAccelSensor(long *data, const uint8_t* packet); +// uint8_t MPU6050::dmpGetGyroSensor(long *data, const uint8_t* packet); +// uint8_t MPU6050::dmpGetControlData(long *data, const uint8_t* packet); +// uint8_t MPU6050::dmpGetTemperature(long *data, const uint8_t* packet); +// uint8_t MPU6050::dmpGetGravity(long *data, const uint8_t* packet); +uint8_t MPU6050::dmpGetGravity(int16_t *data, const uint8_t* packet) { + /* +1g corresponds to +8192, sensitivity is 2g. */ + int16_t qI[4]; + uint8_t status = dmpGetQuaternion(qI, packet); + data[0] = ((int32_t)qI[1] * qI[3] - (int32_t)qI[0] * qI[2]) / 16384; + data[1] = ((int32_t)qI[0] * qI[1] + (int32_t)qI[2] * qI[3]) / 16384; + data[2] = ((int32_t)qI[0] * qI[0] - (int32_t)qI[1] * qI[1] + - (int32_t)qI[2] * qI[2] + (int32_t)qI[3] * qI[3]) / (2 * 16384); + return status; +} + +uint8_t MPU6050::dmpGetGravity(VectorFloat *v, Quaternion *q) { + v -> x = 2 * (q -> x*q -> z - q -> w*q -> y); + v -> y = 2 * (q -> w*q -> x + q -> y*q -> z); + v -> z = q -> w*q -> w - q -> x*q -> x - q -> y*q -> y + q -> z*q -> z; + return 0; +} +// uint8_t MPU6050::dmpGetUnquantizedAccel(long *data, const uint8_t* packet); +// uint8_t MPU6050::dmpGetQuantizedAccel(long *data, const uint8_t* packet); +// uint8_t MPU6050::dmpGetExternalSensorData(long *data, int size, const uint8_t* packet); +// uint8_t MPU6050::dmpGetEIS(long *data, const uint8_t* packet); + +uint8_t MPU6050::dmpGetEuler(float *data, Quaternion *q) { + data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1); // psi + data[1] = -asin(2*q -> x*q -> z + 2*q -> w*q -> y); // theta + data[2] = atan2(2*q -> y*q -> z - 2*q -> w*q -> x, 2*q -> w*q -> w + 2*q -> z*q -> z - 1); // phi + return 0; +} + +#ifdef USE_OLD_DMPGETYAWPITCHROLL +uint8_t MPU6050::dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity) { + // yaw: (about Z axis) + data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1); + // pitch: (nose up/down, about Y axis) + data[1] = atan(gravity -> x / sqrt(gravity -> y*gravity -> y + gravity -> z*gravity -> z)); + // roll: (tilt left/right, about X axis) + data[2] = atan(gravity -> y / sqrt(gravity -> x*gravity -> x + gravity -> z*gravity -> z)); + return 0; +} +#else +uint8_t MPU6050::dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity) { + // yaw: (about Z axis) + data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1); + // pitch: (nose up/down, about Y axis) + data[1] = atan2(gravity -> x , sqrt(gravity -> y*gravity -> y + gravity -> z*gravity -> z)); + // roll: (tilt left/right, about X axis) + data[2] = atan2(gravity -> y , gravity -> z); + if (gravity -> z < 0) { + if(data[1] > 0) { + data[1] = PI - data[1]; + } else { + data[1] = -PI - data[1]; + } + } + return 0; +} +#endif + +// uint8_t MPU6050::dmpGetAccelFloat(float *data, const uint8_t* packet); +// uint8_t MPU6050::dmpGetQuaternionFloat(float *data, const uint8_t* packet); + +uint8_t MPU6050::dmpProcessFIFOPacket(const unsigned char *dmpData) { + /*for (uint8_t k = 0; k < dmpPacketSize; k++) { + if (dmpData[k] < 0x10) Serial.print("0"); + Serial.print(dmpData[k], HEX); + Serial.print(" "); + } + Serial.print("\n");*/ + //Serial.println((uint16_t)dmpPacketBuffer); + return 0; +} +uint8_t MPU6050::dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *processed) { + uint8_t status; + uint8_t buf[dmpPacketSize]; + for (uint8_t i = 0; i < numPackets; i++) { + // read packet from FIFO + getFIFOBytes(buf, dmpPacketSize); + + // process packet + if ((status = dmpProcessFIFOPacket(buf)) > 0) return status; + + // increment external process count variable, if supplied + if (processed != 0) (*processed)++; + } + return 0; +} + +// uint8_t MPU6050::dmpSetFIFOProcessedCallback(void (*func) (void)); + +// uint8_t MPU6050::dmpInitFIFOParam(); +// uint8_t MPU6050::dmpCloseFIFO(); +// uint8_t MPU6050::dmpSetGyroDataSource(uint_fast8_t source); +// uint8_t MPU6050::dmpDecodeQuantizedAccel(); +// uint32_t MPU6050::dmpGetGyroSumOfSquare(); +// uint32_t MPU6050::dmpGetAccelSumOfSquare(); +// void MPU6050::dmpOverrideQuaternion(long *q); +uint16_t MPU6050::dmpGetFIFOPacketSize() { + return dmpPacketSize; +} + + + +uint8_t MPU6050::dmpGetCurrentFIFOPacket(uint8_t *data) { // overflow proof + return(GetCurrentFIFOPacket(data, dmpPacketSize)); +} + +#endif /* _MPU6050_6AXIS_MOTIONAPPS20_H_ */ diff --git a/RP2040/MPU6050/examples/README.md b/RP2040/MPU6050/examples/README.md new file mode 100644 index 00000000..ac9abf30 --- /dev/null +++ b/RP2040/MPU6050/examples/README.md @@ -0,0 +1,10 @@ +These are examples for the Raspberry Pi Pico development board, have VS Code support and serial output through USB. You will have to edit the include paths so they match the ones on your computer, but VS Code should warn you about it if you don't. +Also, you must have the libraries files (I2Cdev.h, I2Cdev.cpp, MPU6050.h, MPU6050.cpp, MPU6050\_6Axis\_MotionApps\_V6\_12.h, helper\_3dmath.h) inside the example folder (whichever you want to build), unless you modify the CMakeLists.txt and specify the path. + +#### Instructions for building examples +1. ```cd``` to the folder of the example you want to build. +2. ```mkdir build && cd build``` +3. ```cmake ..``` +4. ```make``` +5. Copy the uf2 file to your Pico board, using ```cp``` or the file explorer you have. +6. ```sudo minicom -D /dev/ttyACM0``` to watch the serial output. Use ```sudo```, otherwise minicom will fail to open the device and show no warnings. On Windows you can use PuTTY, choosing the COM port that was assigned (check the Device Manager) and a baudrate of 115200. diff --git a/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/.vscode/c_cpp_properties.json b/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/.vscode/c_cpp_properties.json new file mode 100644 index 00000000..e385a5e2 --- /dev/null +++ b/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/.vscode/c_cpp_properties.json @@ -0,0 +1,18 @@ +{ + "configurations": [ + { + "name": "Linux", + "includePath": [ + "${workspaceFolder}/**", + "${env:PICO_SDK_PATH}/**" + ], + "defines": [], + "compilerPath": "/usr/bin/arm-none-eabi-gcc", + "cStandard": "gnu17", + "cppStandard": "gnu++14", + "intelliSenseMode": "linux-gcc-arm", + "configurationProvider" : "ms-vscode.cmake-tools" + } + ], + "version": 4 +} diff --git a/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/.vscode/extensions.json b/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/.vscode/extensions.json new file mode 100644 index 00000000..5acb2833 --- /dev/null +++ b/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/.vscode/extensions.json @@ -0,0 +1,7 @@ +{ + "recommendations": [ + "marus25.cortex-debug", + "ms-vscode.cmake-tools", + "ms-vscode.cpptools" + ] +} diff --git a/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/.vscode/launch.json b/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/.vscode/launch.json new file mode 100644 index 00000000..8eaaa7a7 --- /dev/null +++ b/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/.vscode/launch.json @@ -0,0 +1,29 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Cortex Debug", + "cwd": "${workspaceRoot}", + "executable": "${command:cmake.launchTargetPath}", + "request": "launch", + "type": "cortex-debug", + "servertype": "openocd", + "gdbPath": "gdb-multiarch", + "device": "RP2040", + "configFiles": [ + "interface/raspberrypi-swd.cfg", + "target/rp2040.cfg" + ], + "svdFile": "${env:PICO_SDK_PATH}/src/rp2040/hardware_regs/rp2040.svd", + "runToMain": true, + // Give restart the same functionality as runToMain + "postRestartCommands": [ + "break main", + "continue" + ] + } + ] +} diff --git a/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/.vscode/settings.json b/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/.vscode/settings.json new file mode 100644 index 00000000..7ca58bd3 --- /dev/null +++ b/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/.vscode/settings.json @@ -0,0 +1,16 @@ +{ + "cmake.configureOnOpen": false, + "cmake.statusbar.advanced": { + "debug" : { + "visibility": "hidden" + }, "launch" : { + "visibility": "hidden" + }, + "build" : { + "visibility": "hidden" + }, + "buildTarget" : { + "visibility": "hidden" + }, + }, +} diff --git a/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/CMakeLists.txt b/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/CMakeLists.txt new file mode 100644 index 00000000..646890a2 --- /dev/null +++ b/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/CMakeLists.txt @@ -0,0 +1,36 @@ +# Generated Cmake Pico project file + +cmake_minimum_required(VERSION 3.13) + +set(CMAKE_C_STANDARD 11) +set(CMAKE_CXX_STANDARD 17) + +# Pull in Raspberry Pi Pico SDK (must be before project) +include(pico_sdk_import.cmake) + +project(mpu6050_DMP_port C CXX ASM) + +# Initialise the Raspberry Pi Pico SDK +pico_sdk_init() + +# Add executable. Default name is the project name, version 0.1 + +add_executable(mpu6050_DMP_port mpu6050_DMP_port.cpp I2Cdev.cpp MPU6050.cpp ) + +pico_set_program_name(mpu6050_DMP_port "mpu6050_DMP_port") +pico_set_program_version(mpu6050_DMP_port "0.1") + +pico_enable_stdio_uart(mpu6050_DMP_port 0) +pico_enable_stdio_usb(mpu6050_DMP_port 1) + +# Add the standard library to the build +target_link_libraries(mpu6050_DMP_port pico_stdlib) + +# Add any user requested libraries +target_link_libraries(mpu6050_DMP_port + hardware_i2c + pico_double + ) + +pico_add_extra_outputs(mpu6050_DMP_port) + diff --git a/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/mpu6050_DMP_port.cpp b/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/mpu6050_DMP_port.cpp new file mode 100644 index 00000000..992acf1e --- /dev/null +++ b/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/mpu6050_DMP_port.cpp @@ -0,0 +1,124 @@ +#include +#include "pico/stdlib.h" +#include "hardware/i2c.h" +#include "MPU6050_6Axis_MotionApps_V6_12.h" + +MPU6050 mpu; + +//#define OUTPUT_READABLE_YAWPITCHROLL +//#define OUTPUT_READABLE_REALACCEL +//#define OUTPUT_READABLE_WORLDACCEL +#define OUTPUT_READABLE_CUSTOM + + +bool dmpReady = false; // set true if DMP init was successful +uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU +uint8_t devStatus; // return status after each device operation (0 = success, !0 = error) +uint16_t packetSize; // expected DMP packet size (default is 42 bytes) +uint16_t fifoCount; // count of all bytes currently in FIFO +uint8_t fifoBuffer[64]; // FIFO storage buffer + +Quaternion q; // [w, x, y, z] quaternion container +VectorInt16 aa; // [x, y, z] accel sensor measurements +VectorInt16 gy; // [x, y, z] gyro sensor measurements +VectorInt16 aaReal; // [x, y, z] gravity-free accel sensor measurements +VectorInt16 aaWorld; // [x, y, z] world-frame accel sensor measurements +VectorFloat gravity; // [x, y, z] gravity vector +float euler[3]; // [psi, theta, phi] Euler angle container +float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector +float yaw, pitch, roll; + +volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high +void dmpDataReady() { + mpuInterrupt = true; +} + +int main() { + stdio_init_all(); + // This example will use I2C0 on the default SDA and SCL pins (4, 5 on a Pico) + i2c_init(i2c_default, 400 * 1000); + gpio_set_function(PICO_DEFAULT_I2C_SDA_PIN, GPIO_FUNC_I2C); + gpio_set_function(PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C); + gpio_pull_up(PICO_DEFAULT_I2C_SDA_PIN); + gpio_pull_up(PICO_DEFAULT_I2C_SCL_PIN); + // Make the I2C pins available to picotool + + sleep_ms(5000); // So you have time to launch the serial monitor + + // ================================================================ + // === INITIAL SETUP === + // ================================================================ + + mpu.initialize(); + devStatus = mpu.dmpInitialize(); + if (devStatus == 0) + { + mpu.setDMPEnabled(true); // turn on the DMP, now that it's ready + mpuIntStatus = mpu.getIntStatus(); + dmpReady = true; // set our DMP Ready flag so the main loop() function knows it's okay to use it + packetSize = mpu.dmpGetFIFOPacketSize(); // get expected DMP packet size for later comparison + } + else + { // ERROR! 1 = initial memory load failed 2 = DMP configuration updates failed (if it's going to break, usually the code will be 1) + printf("DMP Initialization failed (code %d)", devStatus); + sleep_ms(2000); + } + yaw = 0.0; + pitch = 0.0; + roll = 0.0; + + // ================================================================ + // === MAIN PROGRAM LOOP === + // ================================================================ + + while(1){ + + if (!dmpReady); // if programming failed, don't try to do anything + mpuInterrupt = true; + fifoCount = mpu.getFIFOCount(); // get current FIFO count + if ((mpuIntStatus & 0x10) || fifoCount == 1024) // check for overflow (this should never happen unless our code is too inefficient) + { + mpu.resetFIFO(); // reset so we can continue cleanly + printf("FIFO overflow!"); + } + else if (mpuIntStatus & 0x01) // otherwise, check for DMP data ready interrupt (this should happen frequently) + { + while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount(); // wait for correct available data length, should be a VERY short wait + mpu.getFIFOBytes(fifoBuffer, packetSize); // read a packet from FIFO + fifoCount -= packetSize; // track FIFO count here in case there is > 1 packet available + #ifdef OUTPUT_READABLE_YAWPITCHROLL // display Euler angles in degrees + mpu.dmpGetQuaternion(&q, fifoBuffer); + mpu.dmpGetGravity(&gravity, &q); + mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); + yaw = ypr[0] * 180 / PI; + pitch = ypr[1] * 180 / PI; + roll = ypr[2] * 180 / PI; + printf("ypr: %f,\t %f,\t %f\n", yaw, pitch, roll); + #endif + #ifdef OUTPUT_READABLE_REALACCEL + // display real acceleration, adjusted to remove gravity + mpu.dmpGetQuaternion(&q, fifoBuffer); + mpu.dmpGetAccel(&aa, fifoBuffer); + mpu.dmpGetGravity(&gravity, &q); + mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity); + printf("areal: %d,\t %d,\t %d\n", aaReal.x, aaReal.y, aaReal.z); + #endif + #ifdef OUTPUT_READABLE_WORLDACCEL + // display initial world-frame acceleration, adjusted to remove gravity + // and rotated based on known orientation from quaternion + mpu.dmpGetQuaternion(&q, fifoBuffer); + mpu.dmpGetAccel(&aa, fifoBuffer); + mpu.dmpGetGravity(&gravity, &q); + mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity); + mpu.dmpGetLinearAccelInWorld(&aaWorld, &aaReal, &q); + printf("aworld: %d,\t %d,\t %d\n", aaWorld.x, aaWorld.y, aaWorld.z); + #endif + #ifdef OUTPUT_READABLE_CUSTOM + mpu.dmpGetQuaternion(&q, fifoBuffer); + printf("W: %f\t X: %f\t Y: %f\t Z: %f\n", q.w, q.x, q.y, q.z); + #endif + } + } + + return 0; +} diff --git a/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/pico_sdk_import.cmake b/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/pico_sdk_import.cmake new file mode 100644 index 00000000..28efe9ea --- /dev/null +++ b/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/pico_sdk_import.cmake @@ -0,0 +1,62 @@ +# This is a copy of /external/pico_sdk_import.cmake + +# This can be dropped into an external project to help locate this SDK +# It should be include()ed prior to project() + +if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH)) + set(PICO_SDK_PATH $ENV{PICO_SDK_PATH}) + message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')") +endif () + +if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT)) + set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT}) + message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')") +endif () + +if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH)) + set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH}) + message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')") +endif () + +set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK") +set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable") +set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK") + +if (NOT PICO_SDK_PATH) + if (PICO_SDK_FETCH_FROM_GIT) + include(FetchContent) + set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR}) + if (PICO_SDK_FETCH_FROM_GIT_PATH) + get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}") + endif () + FetchContent_Declare( + pico_sdk + GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk + GIT_TAG master + ) + if (NOT pico_sdk) + message("Downloading Raspberry Pi Pico SDK") + FetchContent_Populate(pico_sdk) + set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR}) + endif () + set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE}) + else () + message(FATAL_ERROR + "SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git." + ) + endif () +endif () + +get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}") +if (NOT EXISTS ${PICO_SDK_PATH}) + message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found") +endif () + +set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake) +if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE}) + message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK") +endif () + +set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE) + +include(${PICO_SDK_INIT_CMAKE_FILE}) diff --git a/RP2040/MPU6050/examples/mpu6050_calibration/.vscode/c_cpp_properties.json b/RP2040/MPU6050/examples/mpu6050_calibration/.vscode/c_cpp_properties.json new file mode 100644 index 00000000..e385a5e2 --- /dev/null +++ b/RP2040/MPU6050/examples/mpu6050_calibration/.vscode/c_cpp_properties.json @@ -0,0 +1,18 @@ +{ + "configurations": [ + { + "name": "Linux", + "includePath": [ + "${workspaceFolder}/**", + "${env:PICO_SDK_PATH}/**" + ], + "defines": [], + "compilerPath": "/usr/bin/arm-none-eabi-gcc", + "cStandard": "gnu17", + "cppStandard": "gnu++14", + "intelliSenseMode": "linux-gcc-arm", + "configurationProvider" : "ms-vscode.cmake-tools" + } + ], + "version": 4 +} diff --git a/RP2040/MPU6050/examples/mpu6050_calibration/.vscode/extensions.json b/RP2040/MPU6050/examples/mpu6050_calibration/.vscode/extensions.json new file mode 100644 index 00000000..5acb2833 --- /dev/null +++ b/RP2040/MPU6050/examples/mpu6050_calibration/.vscode/extensions.json @@ -0,0 +1,7 @@ +{ + "recommendations": [ + "marus25.cortex-debug", + "ms-vscode.cmake-tools", + "ms-vscode.cpptools" + ] +} diff --git a/RP2040/MPU6050/examples/mpu6050_calibration/.vscode/launch.json b/RP2040/MPU6050/examples/mpu6050_calibration/.vscode/launch.json new file mode 100644 index 00000000..8eaaa7a7 --- /dev/null +++ b/RP2040/MPU6050/examples/mpu6050_calibration/.vscode/launch.json @@ -0,0 +1,29 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Cortex Debug", + "cwd": "${workspaceRoot}", + "executable": "${command:cmake.launchTargetPath}", + "request": "launch", + "type": "cortex-debug", + "servertype": "openocd", + "gdbPath": "gdb-multiarch", + "device": "RP2040", + "configFiles": [ + "interface/raspberrypi-swd.cfg", + "target/rp2040.cfg" + ], + "svdFile": "${env:PICO_SDK_PATH}/src/rp2040/hardware_regs/rp2040.svd", + "runToMain": true, + // Give restart the same functionality as runToMain + "postRestartCommands": [ + "break main", + "continue" + ] + } + ] +} diff --git a/RP2040/MPU6050/examples/mpu6050_calibration/.vscode/settings.json b/RP2040/MPU6050/examples/mpu6050_calibration/.vscode/settings.json new file mode 100644 index 00000000..bdc3b361 --- /dev/null +++ b/RP2040/MPU6050/examples/mpu6050_calibration/.vscode/settings.json @@ -0,0 +1,32 @@ +{ + "cmake.configureOnOpen": false, + "cmake.statusbar.advanced": { + "debug" : { + "visibility": "hidden" + }, "launch" : { + "visibility": "hidden" + }, + "build" : { + "visibility": "hidden" + }, + "buildTarget" : { + "visibility": "hidden" + }, + }, + "files.associations": { + "stdlib.h": "c", + "*.tcc": "c", + "cmath": "c", + "numeric": "c", + "cinttypes": "c", + "cstdlib": "c", + "memory": "cpp", + "random": "cpp", + "optional": "cpp", + "binary_info.h": "c", + "double.h": "c", + "array": "cpp", + "string": "cpp", + "string_view": "cpp" + }, +} diff --git a/RP2040/MPU6050/examples/mpu6050_calibration/CMakeLists.txt b/RP2040/MPU6050/examples/mpu6050_calibration/CMakeLists.txt new file mode 100644 index 00000000..deb09162 --- /dev/null +++ b/RP2040/MPU6050/examples/mpu6050_calibration/CMakeLists.txt @@ -0,0 +1,35 @@ +# Generated Cmake Pico project file + +cmake_minimum_required(VERSION 3.13) + +set(CMAKE_C_STANDARD 11) +set(CMAKE_CXX_STANDARD 17) + +# Pull in Raspberry Pi Pico SDK (must be before project) +include(pico_sdk_import.cmake) + +project(mpu6050_i2c_calibration C CXX ASM) + +# Initialise the Raspberry Pi Pico SDK +pico_sdk_init() + +# Add executable. Default name is the project name, version 0.1 + +add_executable(mpu6050_i2c_calibration mpu6050_i2c_calibration.c ) + +pico_set_program_name(mpu6050_i2c_calibration "mpu6050_i2c_calibration") +pico_set_program_version(mpu6050_i2c_calibration "0.1") + +pico_enable_stdio_uart(mpu6050_i2c_calibration 0) +pico_enable_stdio_usb(mpu6050_i2c_calibration 1) + +# Add the standard library to the build +target_link_libraries(mpu6050_i2c_calibration pico_stdlib) + +# Add any user requested libraries +target_link_libraries(mpu6050_i2c_calibration + hardware_i2c + ) + +pico_add_extra_outputs(mpu6050_i2c_calibration) + diff --git a/RP2040/MPU6050/examples/mpu6050_calibration/mpu6050_i2c_calibration.c b/RP2040/MPU6050/examples/mpu6050_calibration/mpu6050_i2c_calibration.c new file mode 100644 index 00000000..66d73e18 --- /dev/null +++ b/RP2040/MPU6050/examples/mpu6050_calibration/mpu6050_i2c_calibration.c @@ -0,0 +1,408 @@ +#include +#include +#include "pico/stdlib.h" +#include "hardware/i2c.h" + + +/* Example code to talk to a MPU6050 MEMS accelerometer and gyroscope + + This is taking to simple approach of simply reading registers. It's perfectly + possible to link up an interrupt line and set things up to read from the + inbuilt FIFO to make it more useful. + + NOTE: Ensure the device is capable of being driven at 3.3v NOT 5v. The Pico + GPIO (and therefor I2C) cannot be used at 5v. + + You will need to use a level shifter on the I2C lines if you want to run the + board at 5v. + + Connections on Raspberry Pi Pico board, other boards may vary. + + GPIO PICO_DEFAULT_I2C_SDA_PIN (On Pico this is 4 (pin 6)) -> SDA on MPU6050 board + GPIO PICO_DEFAULT_I2C_SCK_PIN (On Pico this is 5 (pin 7)) -> SCL on MPU6050 board + 3.3v (pin 36) -> VCC on MPU6050 board + GND (pin 38) -> GND on MPU6050 board +*/ + +#define GYRO_CONFIG_REG 0x1B +#define ACCEL_CONFIG_REG 0x1C +#define ACCEL_OUT_START_REG 0x3B +#define TEMP_OUT_REG 0x41 +#define GYRO_OUT_START_REG 0x43 +#define PWR_MGMT_1_REG 0x6B +/* +Offset Registers +*/ +#define MPU6050_XA_OFFS_H 0x06 //[15:0] XA_OFFS +#define MPU6050_XA_OFFS_L_TC 0x07 +#define MPU6050_YA_OFFS_H 0x08 //[15:0] YA_OFFS +#define MPU6050_YA_OFFS_L_TC 0x09 +#define MPU6050_ZA_OFFS_H 0x0A //[15:0] ZA_OFFS +#define MPU6050_ZA_OFFS_L_TC 0x0B +#define MPU6050_XG_OFFS_USRH 0x13 //[15:0] XG_OFFS_USR +#define MPU6050_XG_OFFS_USRL 0x14 +#define MPU6050_YG_OFFS_USRH 0x15 //[15:0] YG_OFFS_USR +#define MPU6050_YG_OFFS_USRL 0x16 +#define MPU6050_ZG_OFFS_USRH 0x17 //[15:0] ZG_OFFS_USR +#define MPU6050_ZG_OFFS_USRL 0x18 + +/* +Calibration macros +*/ +#define MAX_DISCARD_SAMPLES 100 +#define MAX_CALIBRATION_SAMPLES (uint16_t)10000 + +// By default these devices are on bus address 0x68 +static int addr = 0x68; + +/* + * The calibration offsets of each sensor in each axis. + * Default values are set to 0. + */ +int16_t accelerometerXOffset = 0; +int16_t accelerometerYOffset = 0; +int16_t accelerometerZOffset = 0; +int16_t gyroscopeXOffset = 0; +int16_t gyroscopeYOffset = 0; +int16_t gyroscopeZOffset = 0; + +int16_t accel_gyro_avg[6] = {INT16_MAX, INT16_MAX, INT16_MAX, INT16_MAX, INT16_MAX, INT16_MAX}; + +void setXAccelOffset(int16_t offset); + +void setYAccelOffset(int16_t offset); + +void setZAccelOffset(int16_t offset); + +void setXGyroOffset(int16_t offset); + +void setYGyroOffset(int16_t offset); + +void setZGyroOffset(int16_t offset); + +int getDeviceOffsets(int16_t *accel_gyro_offsets); + +int16_t getXAccelOffset(); + +int16_t getYAccelOffset(); + +int16_t getZAccelOffset(); + +int16_t getXGyroOffset(); + +int16_t getYGyroOffset(); + +int16_t getZGyroOffset(); + +static void mpu6050_reset() { + // Two byte reset. First byte register, second byte data + // There are a load more options to set up the device in different ways that could be added here + uint8_t buf[] = {PWR_MGMT_1_REG, 0x01}; + i2c_write_blocking(i2c_default, addr, buf, 2, false); + /* Set Gyroscope range */ + buf[0] = GYRO_CONFIG_REG; + buf[1] = 0x00; + i2c_write_blocking(i2c_default, addr, buf, 2, false); + /* Set Accelerometer range */ + buf[0] = ACCEL_CONFIG_REG; + buf[1] = 0x00; + i2c_write_blocking(i2c_default, addr, buf, 2, false); +} + +static void mpu6050_read_raw_accel(int16_t accel[3]){ + uint8_t buffer[6]; + + // Start reading acceleration registers from register 0x3B for 6 bytes + uint8_t val = ACCEL_OUT_START_REG; + i2c_write_blocking(i2c_default, addr, &val, 1, true); // true to keep master control of bus + i2c_read_blocking(i2c_default, addr, buffer, 6, false); + + for (int i = 0; i < 3; i++) { + accel[i] = (buffer[i * 2] << 8 | buffer[(i * 2) + 1]); + } +} + +static void mpu6050_read_raw_gyro(int16_t gyro[3]){ + uint8_t buffer[6]; + + // Read gyro data from reg 0x43 for 6 bytes + // The register is auto incrementing on each read + uint8_t val = GYRO_OUT_START_REG; + i2c_write_blocking(i2c_default, addr, &val, 1, true); + i2c_read_blocking(i2c_default, addr, buffer, 6, false); // False - finished with bus + + for (int i = 0; i < 3; i++) { + gyro[i] = (buffer[i * 2] << 8 | buffer[(i * 2) + 1]); + } +} + +static void mpu6050_read_raw_temperature(int16_t *temp){ + uint8_t buffer[6]; + + // Read temperature from reg 0x41 for 2 bytes + // The register is auto incrementing on each read + uint8_t val = TEMP_OUT_REG; + i2c_write_blocking(i2c_default, addr, &val, 1, true); + i2c_read_blocking(i2c_default, addr, buffer, 2, false); // False - finished with bus + + *temp = buffer[0] << 8 | buffer[1]; +} + +static void mpu6050_read_raw(int16_t accel[3], int16_t gyro[3], int16_t *temp) { + // For this particular device, we send the device the register we want to read + // first, then subsequently read from the device. The register is auto incrementing + // so we don't need to keep sending the register we want, just the first. + + mpu6050_read_raw_accel(accel); + mpu6050_read_raw_gyro(gyro); + mpu6050_read_raw_temperature(temp); +} + +static void mpu6050_discard_values(){ + int16_t buffer[3]; + + for(int i=0; i> 8), (uint8_t)offset}; + i2c_write_blocking(i2c_default, addr, buf, 3, false); +} + +void setYAccelOffset(int16_t offset){ + uint8_t buf[] = {MPU6050_YA_OFFS_H, (uint8_t)(offset >> 8), (uint8_t)offset}; + i2c_write_blocking(i2c_default, addr, buf, 3, false); +} + +void setZAccelOffset(int16_t offset){ + uint8_t buf[] = {MPU6050_ZA_OFFS_H, (uint8_t)(offset >> 8), (uint8_t)offset}; + i2c_write_blocking(i2c_default, addr, buf, 3, false); +} + +void setXGyroOffset(int16_t offset){ + uint8_t buf[] = {MPU6050_XG_OFFS_USRH, (uint8_t)(offset >> 8), (uint8_t)offset}; + i2c_write_blocking(i2c_default, addr, buf, 3, false); +} + +void setYGyroOffset(int16_t offset){ + uint8_t buf[] = {MPU6050_YG_OFFS_USRH, (uint8_t)(offset >> 8), (uint8_t)offset}; + i2c_write_blocking(i2c_default, addr, buf, 3, false); +} + +void setZGyroOffset(int16_t offset){ + uint8_t buf[] = {MPU6050_ZG_OFFS_USRH, (uint8_t)(offset >> 8), (uint8_t)offset}; + i2c_write_blocking(i2c_default, addr, buf, 3, false); +} + +int16_t getXAccelOffset(){ + uint8_t buffer[6], val = MPU6050_XA_OFFS_H; + i2c_write_blocking(i2c_default, addr, &val, 1, true); + i2c_read_blocking(i2c_default, addr, buffer, 2, false); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} + +int16_t getYAccelOffset(){ + uint8_t buffer[6], val = MPU6050_YA_OFFS_H; + i2c_write_blocking(i2c_default, addr, &val, 1, true); + i2c_read_blocking(i2c_default, addr, buffer, 2, false); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} + +int16_t getZAccelOffset(){ + uint8_t buffer[6], val = MPU6050_ZA_OFFS_H; + i2c_write_blocking(i2c_default, addr, &val, 1, true); + i2c_read_blocking(i2c_default, addr, buffer, 2, false); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} + +int16_t getXGyroOffset(){ + uint8_t buffer[6], val = MPU6050_XG_OFFS_USRH; + i2c_write_blocking(i2c_default, addr, &val, 1, true); + i2c_read_blocking(i2c_default, addr, buffer, 2, false); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} + +int16_t getYGyroOffset(){ + uint8_t buffer[6], val = MPU6050_YG_OFFS_USRH; + i2c_write_blocking(i2c_default, addr, &val, 1, true); + i2c_read_blocking(i2c_default, addr, buffer, 2, false); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} + +int16_t getZGyroOffset(){ + uint8_t buffer[6], val = MPU6050_ZG_OFFS_USRH; + i2c_write_blocking(i2c_default, addr, &val, 1, true); + i2c_read_blocking(i2c_default, addr, buffer, 2, false); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} + +int getDeviceOffsets(int16_t *accel_gyro_offsets){ + accel_gyro_offsets[0] = getXAccelOffset(); + accel_gyro_offsets[1] = getYAccelOffset(); + accel_gyro_offsets[2] = getZAccelOffset(); + accel_gyro_offsets[3] = getXGyroOffset(); + accel_gyro_offsets[4] = getYGyroOffset(); + accel_gyro_offsets[5] = getZGyroOffset(); + + return 0; +} + +int main() { + stdio_init_all(); + + printf("Hello, MPU6050! Reading raw data from registers...\n"); + + /* This example will use I2C0 on the default SDA and SCL pins (4, 5 on a Pico) */ + i2c_init(i2c_default, 400 * 1000); + gpio_set_function(PICO_DEFAULT_I2C_SDA_PIN, GPIO_FUNC_I2C); + gpio_set_function(PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C); + gpio_pull_up(PICO_DEFAULT_I2C_SDA_PIN); + gpio_pull_up(PICO_DEFAULT_I2C_SCL_PIN); + + mpu6050_reset(); + + int16_t acceleration[3], gyro[3], temp; + int16_t accel_gyro_offsets[6] = {0, 0, 0, 0, 0, 0}; + char op; + int16_t mask_16bit = 0x0001, mask_bit[3] = {0, 0, 0}; + + while(1){ + printf("\nSelect option: \n" + "1. Read raw values\n" + "2. Calibrate device\n" + "3. Read offset values\n" + "4. Manually set offset values\n" + "5. Get average readings\n" + "0. Terminate program\n\n"); + op = getchar(); + + if(op == '1'){ + while (1) { + mpu6050_read_raw(acceleration, gyro, &temp); + printf("Acc. X = %f, Y = %f, Z = %f\n", acceleration[0]/16384.0, acceleration[1]/16384.0, acceleration[2]/16384.0); + printf("Gyro. X = %f, Y = %f, Z = %f\n", gyro[0]/131.0, gyro[1]/131.0, gyro[2]/131.0); + /* + Temperature is simple so use the datasheet calculation to get deg C. + Note this is chip temperature. + */ + printf("Temp. = %f\n", (temp / 340.0) + 36.53); + + sleep_ms(100); + } + } + else if(op == '2'){ + mpu6050_discard_values(); + printf("Computing averages, please wait...\n"); + mpu6050_average(MAX_CALIBRATION_SAMPLES); + printf("\nAverage Values\n"); + printf("Acc. X = %d, Y = %d, Z = %d\n", accel_gyro_avg[0], accel_gyro_avg[1], accel_gyro_avg[2]); + printf("Gyro. X = %d, Y = %d, Z = %d\n", accel_gyro_avg[3], accel_gyro_avg[4], accel_gyro_avg[5]); + /*printf("\nAcc. X = %f, Y = %f, Z = %f\n", acceleration[0]/16384.0, acceleration[1]/16384.0, acceleration[2]/16384.0); + printf("Gyro. X = %f, Y = %f, Z = %f\n\n", gyro[0]/131.0, gyro[1]/131.0, gyro[2]/131.0);*/ + + if(getDeviceOffsets(accel_gyro_offsets)) + return -1; + + for(int i=0; i<3; i++){ + if(accel_gyro_offsets[i] & mask_16bit) + mask_bit[i] = mask_16bit; + } + + accelerometerXOffset = (accel_gyro_offsets[0] - (accel_gyro_avg[0] / 8)) | mask_bit[0]; + accelerometerYOffset = (accel_gyro_offsets[1] - (accel_gyro_avg[1] / 8)) | mask_bit[1]; + /* Accelerometer Z Offset drifts and gets bigger, cause? */ + accelerometerZOffset = (accel_gyro_offsets[2] - ((16384 - accel_gyro_avg[2]) / 8)) | mask_bit[2]; + + gyroscopeXOffset -= (accel_gyro_avg[3] / 4); + gyroscopeYOffset -= (accel_gyro_avg[4] / 4); + gyroscopeZOffset -= (accel_gyro_avg[5] / 4); + + printf("\nCalculated Offset Values\n"); + printf("Acc. X = %d, Y = %d, Z = %d\n", accelerometerXOffset, accelerometerYOffset, accelerometerZOffset); + printf("Gyro. X = %d, Y = %d, Z = %d\n", gyroscopeXOffset, gyroscopeYOffset, gyroscopeZOffset); + printf("\nWritting offset values to device...\n"); + setXAccelOffset(accelerometerXOffset); + setYAccelOffset(accelerometerYOffset); + setZAccelOffset(accelerometerZOffset); + setXGyroOffset(gyroscopeXOffset); + setYGyroOffset(gyroscopeYOffset); + setZGyroOffset(gyroscopeZOffset); + mpu6050_average(1000); + printf("\nNEW Average Values\n"); + printf("Acc. X = %d, Y = %d, Z = %d\n", accel_gyro_avg[0], accel_gyro_avg[1], accel_gyro_avg[2]); + printf("Gyro. X = %d, Y = %d, Z = %d\n", accel_gyro_avg[3], accel_gyro_avg[4], accel_gyro_avg[5]); + } + else if(op == '3'){ + if(getDeviceOffsets(accel_gyro_offsets)) + return -1; + + printf("\nOffset Values on device:\n"); + printf("Acc. X = %d, Y = %d, Z = %d\n", accel_gyro_offsets[0], accel_gyro_offsets[1], accel_gyro_offsets[2]); + printf("Gyro. X = %d, Y = %d, Z = %d\n", accel_gyro_offsets[3], accel_gyro_offsets[4], accel_gyro_offsets[5]); + } + else if(op =='4'){ + setXAccelOffset(0); + setYAccelOffset(0); + setZAccelOffset(0); + setXGyroOffset(0); + setYGyroOffset(0); + setZGyroOffset(0); + /*setXAccelOffset(-457); + setYAccelOffset(319); + setZAccelOffset(1392); + setXGyroOffset(7); + setYGyroOffset(-198); + setZGyroOffset(-57);*/ + } + else if(op == '5'){ + /* Get average from 1000 readings */ + mpu6050_average(1000); + printf("\nAverage Values\n"); + printf("Acc. X = %d, Y = %d, Z = %d\n", accel_gyro_avg[0], accel_gyro_avg[1], accel_gyro_avg[2]); + printf("Gyro. X = %d, Y = %d, Z = %d\n", accel_gyro_avg[3], accel_gyro_avg[4], accel_gyro_avg[5]); + } + else if(op == '0'){ + return 0; + } + else{ + printf("\nInvalid option!\n"); + } + } + return 0; +} diff --git a/RP2040/MPU6050/examples/mpu6050_calibration/pico_sdk_import.cmake b/RP2040/MPU6050/examples/mpu6050_calibration/pico_sdk_import.cmake new file mode 100644 index 00000000..28efe9ea --- /dev/null +++ b/RP2040/MPU6050/examples/mpu6050_calibration/pico_sdk_import.cmake @@ -0,0 +1,62 @@ +# This is a copy of /external/pico_sdk_import.cmake + +# This can be dropped into an external project to help locate this SDK +# It should be include()ed prior to project() + +if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH)) + set(PICO_SDK_PATH $ENV{PICO_SDK_PATH}) + message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')") +endif () + +if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT)) + set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT}) + message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')") +endif () + +if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH)) + set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH}) + message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')") +endif () + +set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK") +set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable") +set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK") + +if (NOT PICO_SDK_PATH) + if (PICO_SDK_FETCH_FROM_GIT) + include(FetchContent) + set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR}) + if (PICO_SDK_FETCH_FROM_GIT_PATH) + get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}") + endif () + FetchContent_Declare( + pico_sdk + GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk + GIT_TAG master + ) + if (NOT pico_sdk) + message("Downloading Raspberry Pi Pico SDK") + FetchContent_Populate(pico_sdk) + set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR}) + endif () + set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE}) + else () + message(FATAL_ERROR + "SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git." + ) + endif () +endif () + +get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}") +if (NOT EXISTS ${PICO_SDK_PATH}) + message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found") +endif () + +set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake) +if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE}) + message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK") +endif () + +set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE) + +include(${PICO_SDK_INIT_CMAKE_FILE}) diff --git a/RP2040/MPU6050/helper_3dmath.h b/RP2040/MPU6050/helper_3dmath.h new file mode 100644 index 00000000..cf56aec1 --- /dev/null +++ b/RP2040/MPU6050/helper_3dmath.h @@ -0,0 +1,218 @@ +// I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class, 3D math helper +// 6/5/2012 by Jeff Rowberg +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// 2012-06-05 - add 3D math helper file to DMP6 example sketch + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2012 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#ifndef _HELPER_3DMATH_H_ +#define _HELPER_3DMATH_H_ + +#include + +class Quaternion { + public: + float w; + float x; + float y; + float z; + + Quaternion() { + w = 1.0f; + x = 0.0f; + y = 0.0f; + z = 0.0f; + } + + Quaternion(float nw, float nx, float ny, float nz) { + w = nw; + x = nx; + y = ny; + z = nz; + } + + Quaternion getProduct(Quaternion q) { + // Quaternion multiplication is defined by: + // (Q1 * Q2).w = (w1w2 - x1x2 - y1y2 - z1z2) + // (Q1 * Q2).x = (w1x2 + x1w2 + y1z2 - z1y2) + // (Q1 * Q2).y = (w1y2 - x1z2 + y1w2 + z1x2) + // (Q1 * Q2).z = (w1z2 + x1y2 - y1x2 + z1w2 + return Quaternion( + w*q.w - x*q.x - y*q.y - z*q.z, // new w + w*q.x + x*q.w + y*q.z - z*q.y, // new x + w*q.y - x*q.z + y*q.w + z*q.x, // new y + w*q.z + x*q.y - y*q.x + z*q.w); // new z + } + + Quaternion getConjugate() { + return Quaternion(w, -x, -y, -z); + } + + float getMagnitude() { + return sqrt(w*w + x*x + y*y + z*z); + } + + void normalize() { + float m = getMagnitude(); + w /= m; + x /= m; + y /= m; + z /= m; + } + + Quaternion getNormalized() { + Quaternion r(w, x, y, z); + r.normalize(); + return r; + } +}; + +class VectorInt16 { + public: + int16_t x; + int16_t y; + int16_t z; + + VectorInt16() { + x = 0; + y = 0; + z = 0; + } + + VectorInt16(int16_t nx, int16_t ny, int16_t nz) { + x = nx; + y = ny; + z = nz; + } + + float getMagnitude() { + return sqrt(x*x + y*y + z*z); + } + + void normalize() { + float m = getMagnitude(); + x /= m; + y /= m; + z /= m; + } + + VectorInt16 getNormalized() { + VectorInt16 r(x, y, z); + r.normalize(); + return r; + } + + void rotate(Quaternion *q) { + // http://www.cprogramming.com/tutorial/3d/quaternions.html + // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/transforms/index.htm + // http://content.gpwiki.org/index.php/OpenGL:Tutorials:Using_Quaternions_to_represent_rotation + // ^ or: http://webcache.googleusercontent.com/search?q=cache:xgJAp3bDNhQJ:content.gpwiki.org/index.php/OpenGL:Tutorials:Using_Quaternions_to_represent_rotation&hl=en&gl=us&strip=1 + + // P_out = q * P_in * conj(q) + // - P_out is the output vector + // - q is the orientation quaternion + // - P_in is the input vector (a*aReal) + // - conj(q) is the conjugate of the orientation quaternion (q=[w,x,y,z], q*=[w,-x,-y,-z]) + Quaternion p(0, x, y, z); + + // quaternion multiplication: q * p, stored back in p + p = q -> getProduct(p); + + // quaternion multiplication: p * conj(q), stored back in p + p = p.getProduct(q -> getConjugate()); + + // p quaternion is now [0, x', y', z'] + x = p.x; + y = p.y; + z = p.z; + } + + VectorInt16 getRotated(Quaternion *q) { + VectorInt16 r(x, y, z); + r.rotate(q); + return r; + } +}; + +class VectorFloat { + public: + float x; + float y; + float z; + + VectorFloat() { + x = 0; + y = 0; + z = 0; + } + + VectorFloat(float nx, float ny, float nz) { + x = nx; + y = ny; + z = nz; + } + + float getMagnitude() { + return sqrt(x*x + y*y + z*z); + } + + void normalize() { + float m = getMagnitude(); + x /= m; + y /= m; + z /= m; + } + + VectorFloat getNormalized() { + VectorFloat r(x, y, z); + r.normalize(); + return r; + } + + void rotate(Quaternion *q) { + Quaternion p(0, x, y, z); + + // quaternion multiplication: q * p, stored back in p + p = q -> getProduct(p); + + // quaternion multiplication: p * conj(q), stored back in p + p = p.getProduct(q -> getConjugate()); + + // p quaternion is now [0, x', y', z'] + x = p.x; + y = p.y; + z = p.z; + } + + VectorFloat getRotated(Quaternion *q) { + VectorFloat r(x, y, z); + r.rotate(q); + return r; + } +}; + +#endif /* _HELPER_3DMATH_H_ */ \ No newline at end of file From 8479da67eea4e1a5f489b57b69fb153a1d21ef75 Mon Sep 17 00:00:00 2001 From: Gino Date: Wed, 29 Sep 2021 20:32:06 -0300 Subject: [PATCH 289/335] Updated comments header. --- RP2040/I2Cdev/I2Cdev.cpp | 19 +++---------------- RP2040/I2Cdev/I2Cdev.h | 23 ++++------------------- RP2040/MPU6050/MPU6050.h | 6 ++++-- 3 files changed, 11 insertions(+), 37 deletions(-) diff --git a/RP2040/I2Cdev/I2Cdev.cpp b/RP2040/I2Cdev/I2Cdev.cpp index 87abecdd..acfb8c2b 100644 --- a/RP2040/I2Cdev/I2Cdev.cpp +++ b/RP2040/I2Cdev/I2Cdev.cpp @@ -1,23 +1,10 @@ +// Raspberry Pi Pico port for: // I2Cdev library collection - Main I2C device class // Abstracts bit and byte I2C R/W functions into a convenient class // 2013-06-05 by Jeff Rowberg // // Changelog: -// 2013-05-06 - add Francesco Ferrara's Fastwire v0.24 implementation with small modifications -// 2013-05-05 - fix issue with writing bit values to words (Sasquatch/Farzanegan) -// 2012-06-09 - fix major issue with reading > 32 bytes at a time with Arduino Wire -// - add compiler warnings when using outdated or IDE or limited I2Cdev implementation -// 2011-11-01 - fix write*Bits mask calculation (thanks sasquatch @ Arduino forums) -// 2011-10-03 - added automatic Arduino version detection for ease of use -// 2011-10-02 - added Gene Knight's NBWire TwoWire class implementation with small modifications -// 2011-08-31 - added support for Arduino 1.0 Wire library (methods are different from 0.x) -// 2011-08-03 - added optional timeout parameter to read* methods to easily change from default -// 2011-08-02 - added support for 16-bit registers -// - fixed incorrect Doxygen comments on some methods -// - added timeout value for read operations (thanks mem @ Arduino forums) -// 2011-07-30 - changed read/write function structures to return success or byte counts -// - made all methods static for multi-device memory savings -// 2011-07-28 - initial release +// 2021-09-29 - Initial port release by Gino Ipóliti. /* ============================================ I2Cdev device library code is placed under the MIT license @@ -343,4 +330,4 @@ bool I2Cdev::writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16 /** Default timeout value for read operations. * Set this to 0 to disable timeout detection. */ -uint32_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; \ No newline at end of file +uint32_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; diff --git a/RP2040/I2Cdev/I2Cdev.h b/RP2040/I2Cdev/I2Cdev.h index 51aadc6c..2a314ee0 100644 --- a/RP2040/I2Cdev/I2Cdev.h +++ b/RP2040/I2Cdev/I2Cdev.h @@ -1,25 +1,10 @@ -// I2Cdev library collection - Main I2C device class header file +// Raspberry Pi Pico port for: +// I2Cdev library collection - Main I2C device class // Abstracts bit and byte I2C R/W functions into a convenient class // 2013-06-05 by Jeff Rowberg // // Changelog: -// 2020-01-20 - hardija : complete support for Teensy 3.x -// 2015-10-30 - simondlevy : support i2c_t3 for Teensy3.1 -// 2013-05-06 - add Francesco Ferrara's Fastwire v0.24 implementation with small modifications -// 2013-05-05 - fix issue with writing bit values to words (Sasquatch/Farzanegan) -// 2012-06-09 - fix major issue with reading > 32 bytes at a time with Arduino Wire -// - add compiler warnings when using outdated or IDE or limited I2Cdev implementation -// 2011-11-01 - fix write*Bits mask calculation (thanks sasquatch @ Arduino forums) -// 2011-10-03 - added automatic Arduino version detection for ease of use -// 2011-10-02 - added Gene Knight's NBWire TwoWire class implementation with small modifications -// 2011-08-31 - added support for Arduino 1.0 Wire library (methods are different from 0.x) -// 2011-08-03 - added optional timeout parameter to read* methods to easily change from default -// 2011-08-02 - added support for 16-bit registers -// - fixed incorrect Doxygen comments on some methods -// - added timeout value for read operations (thanks mem @ Arduino forums) -// 2011-07-30 - changed read/write function structures to return success or byte counts -// - made all methods static for multi-device memory savings -// 2011-07-28 - initial release +// 2021-09-29 - Initial port release by Gino Ipóliti. /* ============================================ I2Cdev device library code is placed under the MIT license @@ -56,7 +41,7 @@ THE SOFTWARE. #include "hardware/i2c.h" // 1000ms default read timeout (modify with "I2Cdev::readTimeout = [ms];") -#define I2CDEV_DEFAULT_READ_TIMEOUT ((uint32_t)1000000) // RP2040 I2C functions with timeout uses microseconds so we have to multiply by 10^3 +#define I2CDEV_DEFAULT_READ_TIMEOUT ((uint32_t)1000000) // RP2040 I2C functions with timeout use microseconds so we have to multiply by 10^3 class I2Cdev { public: diff --git a/RP2040/MPU6050/MPU6050.h b/RP2040/MPU6050/MPU6050.h index 880c64be..1ea3c65f 100644 --- a/RP2040/MPU6050/MPU6050.h +++ b/RP2040/MPU6050/MPU6050.h @@ -1,12 +1,14 @@ -// I2Cdev library collection - MPU6050 I2C device class +// I2Cdev library collection +// Raspberry Pi Pico port for: MPU6050 I2C device class // Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00) // 10/3/2011 by Jeff Rowberg // Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib // // Changelog: +// 2021-09-29 - Initial port release by Gino Ipóliti. // ... - ongoing debug release -// NOTE: THIS IS ONLY A PARIAL RELEASE. THIS DEVICE CLASS IS CURRENTLY UNDERGOING ACTIVE +// NOTE: THIS IS ONLY A PARTIAL RELEASE. THIS DEVICE CLASS IS CURRENTLY UNDERGOING ACTIVE // DEVELOPMENT AND IS STILL MISSING SOME IMPORTANT FEATURES. PLEASE KEEP THIS IN MIND IF // YOU DECIDE TO USE THIS PARTICULAR CODE FOR ANYTHING. From 407e38f66733fa1428f710fb1e27789401f9a72e Mon Sep 17 00:00:00 2001 From: Gino Date: Wed, 29 Sep 2021 20:32:51 -0300 Subject: [PATCH 290/335] Also updated comments header. --- RP2040/MPU6050/MPU6050.cpp | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/RP2040/MPU6050/MPU6050.cpp b/RP2040/MPU6050/MPU6050.cpp index 8b85e76e..f15d2208 100644 --- a/RP2040/MPU6050/MPU6050.cpp +++ b/RP2040/MPU6050/MPU6050.cpp @@ -1,13 +1,15 @@ -// I2Cdev library collection - MPU6050 I2C device class +// I2Cdev library collection +// Raspberry Pi Pico port for: MPU6050 I2C device class // Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00) // 8/24/2011 by Jeff Rowberg // Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib // // Changelog: -// 2019-07-08 - Added Auto Calibration routine +// 2021-09-29 - Initial port release by Gino Ipóliti. +// 2019-07-08 - Added Auto Calibration routine // ... - ongoing debug release -// NOTE: THIS IS ONLY A PARIAL RELEASE. THIS DEVICE CLASS IS CURRENTLY UNDERGOING ACTIVE +// NOTE: THIS IS ONLY A PARTIAL RELEASE. THIS DEVICE CLASS IS CURRENTLY UNDERGOING ACTIVE // DEVELOPMENT AND IS STILL MISSING SOME IMPORTANT FEATURES. PLEASE KEEP THIS IN MIND IF // YOU DECIDE TO USE THIS PARTICULAR CODE FOR ANYTHING. @@ -69,13 +71,6 @@ void MPU6050::initialize() { setClockSource(MPU6050_CLOCK_PLL_XGYRO); setFullScaleGyroRange(MPU6050_GYRO_FS_250); setFullScaleAccelRange(MPU6050_ACCEL_FS_2); - // Set offsets - /*setXAccelOffset(-457); - setYAccelOffset(319); - setZAccelOffset(1392); - setXGyroOffset(7); - setYGyroOffset(-198); - setZGyroOffset(-57);*/ setSleepEnabled(false); // thanks to Jack Elston for pointing this one out! } From f86b5eb25f3fdd1932932098a1613b5eb89f3243 Mon Sep 17 00:00:00 2001 From: Gino Date: Wed, 29 Sep 2021 20:36:02 -0300 Subject: [PATCH 291/335] Updated comments header and improved PI definition. --- RP2040/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/RP2040/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h b/RP2040/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h index 92d093dd..7a8dcf93 100644 --- a/RP2040/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h +++ b/RP2040/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h @@ -1,9 +1,11 @@ -// I2Cdev library collection - MPU6050 I2C device class, 6-axis MotionApps 6.12 implementation +// I2Cdev library collection +// Raspberry Pi Pico port for: MPU6050 I2C device class, 6-axis MotionApps 6.12 implementation // Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00) // 5/20/2013 by Jeff Rowberg // Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib // // Changelog: +// 2021-09-29 - Initial port release by Gino Ipóliti. // 2019/7/10 - I incorporated DMP Firmware Version 6.12 Latest as of today with many features and bug fixes. // - MPU6050 Registers have not changed just the DMP Image so that full backwards compatibility is present // - Run-time calibration routine is enabled which calibrates after no motion state is detected @@ -47,7 +49,7 @@ THE SOFTWARE. #include "MPU6050.h" -#define PI 3.1415926535897932384626433832795 +const double PI = 3.1415926535897932384626433832795 /* Source is from the InvenSense MotionApps v2 demo code. Original source is * unavailable, unless you happen to be amazing as decompiling binary by From 8528d3d74a7475cdefbb940b542d2d9f1b162896 Mon Sep 17 00:00:00 2001 From: Gino Date: Wed, 29 Sep 2021 20:43:23 -0300 Subject: [PATCH 292/335] Removed VS Code related files, updated readme and replaced calibration example. --- RP2040/MPU6050/examples/README.md | 4 +- .../.vscode/c_cpp_properties.json | 18 - .../mpu6050_DMP_V6.12/.vscode/extensions.json | 7 - .../mpu6050_DMP_V6.12/.vscode/launch.json | 29 -- .../mpu6050_DMP_V6.12/.vscode/settings.json | 16 - .../.vscode/c_cpp_properties.json | 18 - .../.vscode/extensions.json | 7 - .../mpu6050_calibration/.vscode/launch.json | 29 -- .../mpu6050_calibration/.vscode/settings.json | 32 -- .../mpu6050_calibration/CMakeLists.txt | 18 +- .../mpu6050_calibration.cpp | 233 ++++++++++ .../mpu6050_i2c_calibration.c | 408 ------------------ 12 files changed, 244 insertions(+), 575 deletions(-) delete mode 100644 RP2040/MPU6050/examples/mpu6050_DMP_V6.12/.vscode/c_cpp_properties.json delete mode 100644 RP2040/MPU6050/examples/mpu6050_DMP_V6.12/.vscode/extensions.json delete mode 100644 RP2040/MPU6050/examples/mpu6050_DMP_V6.12/.vscode/launch.json delete mode 100644 RP2040/MPU6050/examples/mpu6050_DMP_V6.12/.vscode/settings.json delete mode 100644 RP2040/MPU6050/examples/mpu6050_calibration/.vscode/c_cpp_properties.json delete mode 100644 RP2040/MPU6050/examples/mpu6050_calibration/.vscode/extensions.json delete mode 100644 RP2040/MPU6050/examples/mpu6050_calibration/.vscode/launch.json delete mode 100644 RP2040/MPU6050/examples/mpu6050_calibration/.vscode/settings.json create mode 100644 RP2040/MPU6050/examples/mpu6050_calibration/mpu6050_calibration.cpp delete mode 100644 RP2040/MPU6050/examples/mpu6050_calibration/mpu6050_i2c_calibration.c diff --git a/RP2040/MPU6050/examples/README.md b/RP2040/MPU6050/examples/README.md index ac9abf30..fc9f414f 100644 --- a/RP2040/MPU6050/examples/README.md +++ b/RP2040/MPU6050/examples/README.md @@ -1,5 +1,5 @@ -These are examples for the Raspberry Pi Pico development board, have VS Code support and serial output through USB. You will have to edit the include paths so they match the ones on your computer, but VS Code should warn you about it if you don't. -Also, you must have the libraries files (I2Cdev.h, I2Cdev.cpp, MPU6050.h, MPU6050.cpp, MPU6050\_6Axis\_MotionApps\_V6\_12.h, helper\_3dmath.h) inside the example folder (whichever you want to build), unless you modify the CMakeLists.txt and specify the path. +These are examples for the Raspberry Pi Pico development board and have serial output enabled through USB. +Also, if the libraries files (I2Cdev.h, I2Cdev.cpp, MPU6050.h, MPU6050.cpp, MPU6050\_6Axis\_MotionApps\_V6\_12.h, helper\_3dmath.h) are not in a common include directory, you will have to copy them to the example folder (whichever you want to build), unless you modify the CMakeLists.txt and specify the path. #### Instructions for building examples 1. ```cd``` to the folder of the example you want to build. diff --git a/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/.vscode/c_cpp_properties.json b/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/.vscode/c_cpp_properties.json deleted file mode 100644 index e385a5e2..00000000 --- a/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/.vscode/c_cpp_properties.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "configurations": [ - { - "name": "Linux", - "includePath": [ - "${workspaceFolder}/**", - "${env:PICO_SDK_PATH}/**" - ], - "defines": [], - "compilerPath": "/usr/bin/arm-none-eabi-gcc", - "cStandard": "gnu17", - "cppStandard": "gnu++14", - "intelliSenseMode": "linux-gcc-arm", - "configurationProvider" : "ms-vscode.cmake-tools" - } - ], - "version": 4 -} diff --git a/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/.vscode/extensions.json b/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/.vscode/extensions.json deleted file mode 100644 index 5acb2833..00000000 --- a/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/.vscode/extensions.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "recommendations": [ - "marus25.cortex-debug", - "ms-vscode.cmake-tools", - "ms-vscode.cpptools" - ] -} diff --git a/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/.vscode/launch.json b/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/.vscode/launch.json deleted file mode 100644 index 8eaaa7a7..00000000 --- a/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/.vscode/launch.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "name": "Cortex Debug", - "cwd": "${workspaceRoot}", - "executable": "${command:cmake.launchTargetPath}", - "request": "launch", - "type": "cortex-debug", - "servertype": "openocd", - "gdbPath": "gdb-multiarch", - "device": "RP2040", - "configFiles": [ - "interface/raspberrypi-swd.cfg", - "target/rp2040.cfg" - ], - "svdFile": "${env:PICO_SDK_PATH}/src/rp2040/hardware_regs/rp2040.svd", - "runToMain": true, - // Give restart the same functionality as runToMain - "postRestartCommands": [ - "break main", - "continue" - ] - } - ] -} diff --git a/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/.vscode/settings.json b/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/.vscode/settings.json deleted file mode 100644 index 7ca58bd3..00000000 --- a/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/.vscode/settings.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "cmake.configureOnOpen": false, - "cmake.statusbar.advanced": { - "debug" : { - "visibility": "hidden" - }, "launch" : { - "visibility": "hidden" - }, - "build" : { - "visibility": "hidden" - }, - "buildTarget" : { - "visibility": "hidden" - }, - }, -} diff --git a/RP2040/MPU6050/examples/mpu6050_calibration/.vscode/c_cpp_properties.json b/RP2040/MPU6050/examples/mpu6050_calibration/.vscode/c_cpp_properties.json deleted file mode 100644 index e385a5e2..00000000 --- a/RP2040/MPU6050/examples/mpu6050_calibration/.vscode/c_cpp_properties.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "configurations": [ - { - "name": "Linux", - "includePath": [ - "${workspaceFolder}/**", - "${env:PICO_SDK_PATH}/**" - ], - "defines": [], - "compilerPath": "/usr/bin/arm-none-eabi-gcc", - "cStandard": "gnu17", - "cppStandard": "gnu++14", - "intelliSenseMode": "linux-gcc-arm", - "configurationProvider" : "ms-vscode.cmake-tools" - } - ], - "version": 4 -} diff --git a/RP2040/MPU6050/examples/mpu6050_calibration/.vscode/extensions.json b/RP2040/MPU6050/examples/mpu6050_calibration/.vscode/extensions.json deleted file mode 100644 index 5acb2833..00000000 --- a/RP2040/MPU6050/examples/mpu6050_calibration/.vscode/extensions.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "recommendations": [ - "marus25.cortex-debug", - "ms-vscode.cmake-tools", - "ms-vscode.cpptools" - ] -} diff --git a/RP2040/MPU6050/examples/mpu6050_calibration/.vscode/launch.json b/RP2040/MPU6050/examples/mpu6050_calibration/.vscode/launch.json deleted file mode 100644 index 8eaaa7a7..00000000 --- a/RP2040/MPU6050/examples/mpu6050_calibration/.vscode/launch.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "name": "Cortex Debug", - "cwd": "${workspaceRoot}", - "executable": "${command:cmake.launchTargetPath}", - "request": "launch", - "type": "cortex-debug", - "servertype": "openocd", - "gdbPath": "gdb-multiarch", - "device": "RP2040", - "configFiles": [ - "interface/raspberrypi-swd.cfg", - "target/rp2040.cfg" - ], - "svdFile": "${env:PICO_SDK_PATH}/src/rp2040/hardware_regs/rp2040.svd", - "runToMain": true, - // Give restart the same functionality as runToMain - "postRestartCommands": [ - "break main", - "continue" - ] - } - ] -} diff --git a/RP2040/MPU6050/examples/mpu6050_calibration/.vscode/settings.json b/RP2040/MPU6050/examples/mpu6050_calibration/.vscode/settings.json deleted file mode 100644 index bdc3b361..00000000 --- a/RP2040/MPU6050/examples/mpu6050_calibration/.vscode/settings.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "cmake.configureOnOpen": false, - "cmake.statusbar.advanced": { - "debug" : { - "visibility": "hidden" - }, "launch" : { - "visibility": "hidden" - }, - "build" : { - "visibility": "hidden" - }, - "buildTarget" : { - "visibility": "hidden" - }, - }, - "files.associations": { - "stdlib.h": "c", - "*.tcc": "c", - "cmath": "c", - "numeric": "c", - "cinttypes": "c", - "cstdlib": "c", - "memory": "cpp", - "random": "cpp", - "optional": "cpp", - "binary_info.h": "c", - "double.h": "c", - "array": "cpp", - "string": "cpp", - "string_view": "cpp" - }, -} diff --git a/RP2040/MPU6050/examples/mpu6050_calibration/CMakeLists.txt b/RP2040/MPU6050/examples/mpu6050_calibration/CMakeLists.txt index deb09162..c25fd7bb 100644 --- a/RP2040/MPU6050/examples/mpu6050_calibration/CMakeLists.txt +++ b/RP2040/MPU6050/examples/mpu6050_calibration/CMakeLists.txt @@ -8,28 +8,28 @@ set(CMAKE_CXX_STANDARD 17) # Pull in Raspberry Pi Pico SDK (must be before project) include(pico_sdk_import.cmake) -project(mpu6050_i2c_calibration C CXX ASM) +project(mpu6050_calibration C CXX ASM) # Initialise the Raspberry Pi Pico SDK pico_sdk_init() # Add executable. Default name is the project name, version 0.1 -add_executable(mpu6050_i2c_calibration mpu6050_i2c_calibration.c ) +add_executable(mpu6050_calibration mpu6050_calibration.cpp I2Cdev.cpp MPU6050.cpp ) -pico_set_program_name(mpu6050_i2c_calibration "mpu6050_i2c_calibration") -pico_set_program_version(mpu6050_i2c_calibration "0.1") +pico_set_program_name(mpu6050_calibration "mpu6050_calibration") +pico_set_program_version(mpu6050_calibration "0.1") -pico_enable_stdio_uart(mpu6050_i2c_calibration 0) -pico_enable_stdio_usb(mpu6050_i2c_calibration 1) +pico_enable_stdio_uart(mpu6050_calibration 0) +pico_enable_stdio_usb(mpu6050_calibration 1) # Add the standard library to the build -target_link_libraries(mpu6050_i2c_calibration pico_stdlib) +target_link_libraries(mpu6050_calibration pico_stdlib) # Add any user requested libraries -target_link_libraries(mpu6050_i2c_calibration +target_link_libraries(mpu6050_calibration hardware_i2c ) -pico_add_extra_outputs(mpu6050_i2c_calibration) +pico_add_extra_outputs(mpu6050_calibration) diff --git a/RP2040/MPU6050/examples/mpu6050_calibration/mpu6050_calibration.cpp b/RP2040/MPU6050/examples/mpu6050_calibration/mpu6050_calibration.cpp new file mode 100644 index 00000000..eb748bf4 --- /dev/null +++ b/RP2040/MPU6050/examples/mpu6050_calibration/mpu6050_calibration.cpp @@ -0,0 +1,233 @@ +#include +#include "pico/stdlib.h" +#include "hardware/i2c.h" +#include "MPU6050.h" + +MPU6050 accelgyro; + +const int iAx = 0; +const int iAy = 1; +const int iAz = 2; +const int iGx = 3; +const int iGy = 4; +const int iGz = 5; + +const int usDelay = 3150; // empirical, to hold sampling to 200 Hz +const int NFast = 1000; // the bigger, the better (but slower) +const int NSlow = 10000; // .. + int LowValue[6]; + int HighValue[6]; + int Smoothed[6]; + int LowOffset[6]; + int HighOffset[6]; + int Target[6]; + int N; + +void GetSmoothed(){ int16_t RawValue[6]; + int i; + long Sums[6]; + for (i = iAx; i <= iGz; i++) + { Sums[i] = 0; } + + for (i = 1; i <= N; i++) + { // get sums + accelgyro.getMotion6(&RawValue[iAx], &RawValue[iAy], &RawValue[iAz], + &RawValue[iGx], &RawValue[iGy], &RawValue[iGz]); + if ((i % 500) == 0) + printf("."); + sleep_us(usDelay); + for (int j = iAx; j <= iGz; j++) + Sums[j] = Sums[j] + RawValue[j]; + } // get sums + for (i = iAx; i <= iGz; i++) + { Smoothed[i] = (Sums[i] + N/2) / N ; } +} // GetSmoothed + +void Initialize(){ + printf("Initializing I2C devices...\n"); + accelgyro.initialize(); + + // verify connection + printf("Testing device connections...\n"); + if(accelgyro.testConnection()) printf("MPU6050 connection successful\n"); + else {printf("MPU6050 connection failed\n");} + printf("\nPID tuning Each Dot = 100 readings"); + /*A tidbit on how PID (PI actually) tuning works. + When we change the offset in the MPU6050 we can get instant results. This allows us to use Proportional and + integral of the PID to discover the ideal offsets. Integral is the key to discovering these offsets, Integral + uses the error from set-point (set-point is zero), it takes a fraction of this error (error * ki) and adds it + to the integral value. Each reading narrows the error down to the desired offset. The greater the error from + set-point, the more we adjust the integral value. The proportional does its part by hiding the noise from the + integral math. The Derivative is not used because of the noise and because the sensor is stationary. With the + noise removed the integral value lands on a solid offset after just 600 readings. At the end of each set of 100 + readings, the integral value is used for the actual offsets and the last proportional reading is ignored due to + the fact it reacts to any noise. + */ + accelgyro.CalibrateAccel(6); + accelgyro.CalibrateGyro(6); + printf("\nat 600 Readings"); + accelgyro.PrintActiveOffsets(); + printf("\n"); + accelgyro.CalibrateAccel(1); + accelgyro.CalibrateGyro(1); + printf("700 Total Readings"); + accelgyro.PrintActiveOffsets(); + printf("\n"); + accelgyro.CalibrateAccel(1); + accelgyro.CalibrateGyro(1); + printf("800 Total Readings"); + accelgyro.PrintActiveOffsets(); + printf("\n"); + accelgyro.CalibrateAccel(1); + accelgyro.CalibrateGyro(1); + printf("900 Total Readings"); + accelgyro.PrintActiveOffsets(); + printf("\n"); + accelgyro.CalibrateAccel(1); + accelgyro.CalibrateGyro(1); + printf("1000 Total Readings"); + accelgyro.PrintActiveOffsets(); + printf("\n\nAny of the above offsets will work nice\nLets proof the PID tuning using another method:"); +} // Initialize + +void SetOffsets(int TheOffsets[6]){ + accelgyro.setXAccelOffset(TheOffsets[iAx]); + accelgyro.setYAccelOffset(TheOffsets[iAy]); + accelgyro.setZAccelOffset(TheOffsets[iAz]); + accelgyro.setXGyroOffset(TheOffsets[iGx]); + accelgyro.setYGyroOffset(TheOffsets[iGy]); + accelgyro.setZGyroOffset(TheOffsets[iGz]); +} // SetOffsets + +// The following may show up as a mess in the terminal unless it is on fullscreen +void ShowProgress(){ + printf("\nXAccel\t\t\tYAccel\t\t\tZAccel\t\t\tXGyro\t\t\tYGyro\t\t\tZGyro\n"); + for (int i = iAx; i <= iGz; i++){ + printf("[%d,%d] --> [%d,%d]\t", LowOffset[i], HighOffset[i], LowValue[i], HighValue[i]); + } + printf("\n"); +} // ShowProgress + +void SetAveraging(int NewN){ + N = NewN; + printf("\nAveraging %d readings each time\n", N); +} // SetAveraging + +void PullBracketsIn(){ + bool AllBracketsNarrow; + bool StillWorking; + int NewOffset[6]; + + printf("\nClosing in:\n"); + AllBracketsNarrow = false; + StillWorking = true; + while (StillWorking) + { StillWorking = false; + if (AllBracketsNarrow && (N == NFast)) + { SetAveraging(NSlow); } + else + { AllBracketsNarrow = true; }// tentative + for (int i = iAx; i <= iGz; i++) + { if (HighOffset[i] <= (LowOffset[i]+1)) + { NewOffset[i] = LowOffset[i]; } + else + { // binary search + StillWorking = true; + NewOffset[i] = (LowOffset[i] + HighOffset[i]) / 2; + if (HighOffset[i] > (LowOffset[i] + 10)) + { AllBracketsNarrow = false; } + } // binary search + } + SetOffsets(NewOffset); + GetSmoothed(); + for (int i = iAx; i <= iGz; i++) + { // closing in + if (Smoothed[i] > Target[i]) + { // use lower half + HighOffset[i] = NewOffset[i]; + HighValue[i] = Smoothed[i]; + } // use lower half + else + { // use upper half + LowOffset[i] = NewOffset[i]; + LowValue[i] = Smoothed[i]; + } // use upper half + } // closing in + ShowProgress(); + } // still working + +} // PullBracketsIn + +void PullBracketsOut(){ + bool Done = false; + int NextLowOffset[6]; + int NextHighOffset[6]; + + printf("\nExpanding:\n"); + + while (!Done) + { Done = true; + SetOffsets(LowOffset); + GetSmoothed(); + for (int i = iAx; i <= iGz; i++) + { // got low values + LowValue[i] = Smoothed[i]; + if (LowValue[i] >= Target[i]) + { Done = false; + NextLowOffset[i] = LowOffset[i] - 1000; + } + else + { NextLowOffset[i] = LowOffset[i]; } + } // got low values + + SetOffsets(HighOffset); + GetSmoothed(); + for (int i = iAx; i <= iGz; i++) + { // got high values + HighValue[i] = Smoothed[i]; + if (HighValue[i] <= Target[i]) + { Done = false; + NextHighOffset[i] = HighOffset[i] + 1000; + } + else + { NextHighOffset[i] = HighOffset[i]; } + } // got high values + ShowProgress(); + for (int i = iAx; i <= iGz; i++) + { LowOffset[i] = NextLowOffset[i]; // had to wait until ShowProgress done + HighOffset[i] = NextHighOffset[i]; // .. + } + } // keep going +} // PullBracketsOut + +int main() +{ + stdio_init_all(); + + // I2C Initialisation. Using it at 400Khz. + i2c_init(i2c_default, 400*1000); + + gpio_set_function(PICO_DEFAULT_I2C_SDA_PIN, GPIO_FUNC_I2C); + gpio_set_function(PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C); + gpio_pull_up(PICO_DEFAULT_I2C_SDA_PIN); + gpio_pull_up(PICO_DEFAULT_I2C_SCL_PIN); + + sleep_ms(3000); + + Initialize(); + for (int i = iAx; i <= iGz; i++) + { // set targets and initial guesses + Target[i] = 0; // must fix for ZAccel + HighOffset[i] = 0; + LowOffset[i] = 0; + } // set targets and initial guesses + Target[iAz] = 16384; + SetAveraging(NFast); + + PullBracketsOut(); + PullBracketsIn(); + + printf("\n\n-------------- done --------------"); + + return 0; +} diff --git a/RP2040/MPU6050/examples/mpu6050_calibration/mpu6050_i2c_calibration.c b/RP2040/MPU6050/examples/mpu6050_calibration/mpu6050_i2c_calibration.c deleted file mode 100644 index 66d73e18..00000000 --- a/RP2040/MPU6050/examples/mpu6050_calibration/mpu6050_i2c_calibration.c +++ /dev/null @@ -1,408 +0,0 @@ -#include -#include -#include "pico/stdlib.h" -#include "hardware/i2c.h" - - -/* Example code to talk to a MPU6050 MEMS accelerometer and gyroscope - - This is taking to simple approach of simply reading registers. It's perfectly - possible to link up an interrupt line and set things up to read from the - inbuilt FIFO to make it more useful. - - NOTE: Ensure the device is capable of being driven at 3.3v NOT 5v. The Pico - GPIO (and therefor I2C) cannot be used at 5v. - - You will need to use a level shifter on the I2C lines if you want to run the - board at 5v. - - Connections on Raspberry Pi Pico board, other boards may vary. - - GPIO PICO_DEFAULT_I2C_SDA_PIN (On Pico this is 4 (pin 6)) -> SDA on MPU6050 board - GPIO PICO_DEFAULT_I2C_SCK_PIN (On Pico this is 5 (pin 7)) -> SCL on MPU6050 board - 3.3v (pin 36) -> VCC on MPU6050 board - GND (pin 38) -> GND on MPU6050 board -*/ - -#define GYRO_CONFIG_REG 0x1B -#define ACCEL_CONFIG_REG 0x1C -#define ACCEL_OUT_START_REG 0x3B -#define TEMP_OUT_REG 0x41 -#define GYRO_OUT_START_REG 0x43 -#define PWR_MGMT_1_REG 0x6B -/* -Offset Registers -*/ -#define MPU6050_XA_OFFS_H 0x06 //[15:0] XA_OFFS -#define MPU6050_XA_OFFS_L_TC 0x07 -#define MPU6050_YA_OFFS_H 0x08 //[15:0] YA_OFFS -#define MPU6050_YA_OFFS_L_TC 0x09 -#define MPU6050_ZA_OFFS_H 0x0A //[15:0] ZA_OFFS -#define MPU6050_ZA_OFFS_L_TC 0x0B -#define MPU6050_XG_OFFS_USRH 0x13 //[15:0] XG_OFFS_USR -#define MPU6050_XG_OFFS_USRL 0x14 -#define MPU6050_YG_OFFS_USRH 0x15 //[15:0] YG_OFFS_USR -#define MPU6050_YG_OFFS_USRL 0x16 -#define MPU6050_ZG_OFFS_USRH 0x17 //[15:0] ZG_OFFS_USR -#define MPU6050_ZG_OFFS_USRL 0x18 - -/* -Calibration macros -*/ -#define MAX_DISCARD_SAMPLES 100 -#define MAX_CALIBRATION_SAMPLES (uint16_t)10000 - -// By default these devices are on bus address 0x68 -static int addr = 0x68; - -/* - * The calibration offsets of each sensor in each axis. - * Default values are set to 0. - */ -int16_t accelerometerXOffset = 0; -int16_t accelerometerYOffset = 0; -int16_t accelerometerZOffset = 0; -int16_t gyroscopeXOffset = 0; -int16_t gyroscopeYOffset = 0; -int16_t gyroscopeZOffset = 0; - -int16_t accel_gyro_avg[6] = {INT16_MAX, INT16_MAX, INT16_MAX, INT16_MAX, INT16_MAX, INT16_MAX}; - -void setXAccelOffset(int16_t offset); - -void setYAccelOffset(int16_t offset); - -void setZAccelOffset(int16_t offset); - -void setXGyroOffset(int16_t offset); - -void setYGyroOffset(int16_t offset); - -void setZGyroOffset(int16_t offset); - -int getDeviceOffsets(int16_t *accel_gyro_offsets); - -int16_t getXAccelOffset(); - -int16_t getYAccelOffset(); - -int16_t getZAccelOffset(); - -int16_t getXGyroOffset(); - -int16_t getYGyroOffset(); - -int16_t getZGyroOffset(); - -static void mpu6050_reset() { - // Two byte reset. First byte register, second byte data - // There are a load more options to set up the device in different ways that could be added here - uint8_t buf[] = {PWR_MGMT_1_REG, 0x01}; - i2c_write_blocking(i2c_default, addr, buf, 2, false); - /* Set Gyroscope range */ - buf[0] = GYRO_CONFIG_REG; - buf[1] = 0x00; - i2c_write_blocking(i2c_default, addr, buf, 2, false); - /* Set Accelerometer range */ - buf[0] = ACCEL_CONFIG_REG; - buf[1] = 0x00; - i2c_write_blocking(i2c_default, addr, buf, 2, false); -} - -static void mpu6050_read_raw_accel(int16_t accel[3]){ - uint8_t buffer[6]; - - // Start reading acceleration registers from register 0x3B for 6 bytes - uint8_t val = ACCEL_OUT_START_REG; - i2c_write_blocking(i2c_default, addr, &val, 1, true); // true to keep master control of bus - i2c_read_blocking(i2c_default, addr, buffer, 6, false); - - for (int i = 0; i < 3; i++) { - accel[i] = (buffer[i * 2] << 8 | buffer[(i * 2) + 1]); - } -} - -static void mpu6050_read_raw_gyro(int16_t gyro[3]){ - uint8_t buffer[6]; - - // Read gyro data from reg 0x43 for 6 bytes - // The register is auto incrementing on each read - uint8_t val = GYRO_OUT_START_REG; - i2c_write_blocking(i2c_default, addr, &val, 1, true); - i2c_read_blocking(i2c_default, addr, buffer, 6, false); // False - finished with bus - - for (int i = 0; i < 3; i++) { - gyro[i] = (buffer[i * 2] << 8 | buffer[(i * 2) + 1]); - } -} - -static void mpu6050_read_raw_temperature(int16_t *temp){ - uint8_t buffer[6]; - - // Read temperature from reg 0x41 for 2 bytes - // The register is auto incrementing on each read - uint8_t val = TEMP_OUT_REG; - i2c_write_blocking(i2c_default, addr, &val, 1, true); - i2c_read_blocking(i2c_default, addr, buffer, 2, false); // False - finished with bus - - *temp = buffer[0] << 8 | buffer[1]; -} - -static void mpu6050_read_raw(int16_t accel[3], int16_t gyro[3], int16_t *temp) { - // For this particular device, we send the device the register we want to read - // first, then subsequently read from the device. The register is auto incrementing - // so we don't need to keep sending the register we want, just the first. - - mpu6050_read_raw_accel(accel); - mpu6050_read_raw_gyro(gyro); - mpu6050_read_raw_temperature(temp); -} - -static void mpu6050_discard_values(){ - int16_t buffer[3]; - - for(int i=0; i> 8), (uint8_t)offset}; - i2c_write_blocking(i2c_default, addr, buf, 3, false); -} - -void setYAccelOffset(int16_t offset){ - uint8_t buf[] = {MPU6050_YA_OFFS_H, (uint8_t)(offset >> 8), (uint8_t)offset}; - i2c_write_blocking(i2c_default, addr, buf, 3, false); -} - -void setZAccelOffset(int16_t offset){ - uint8_t buf[] = {MPU6050_ZA_OFFS_H, (uint8_t)(offset >> 8), (uint8_t)offset}; - i2c_write_blocking(i2c_default, addr, buf, 3, false); -} - -void setXGyroOffset(int16_t offset){ - uint8_t buf[] = {MPU6050_XG_OFFS_USRH, (uint8_t)(offset >> 8), (uint8_t)offset}; - i2c_write_blocking(i2c_default, addr, buf, 3, false); -} - -void setYGyroOffset(int16_t offset){ - uint8_t buf[] = {MPU6050_YG_OFFS_USRH, (uint8_t)(offset >> 8), (uint8_t)offset}; - i2c_write_blocking(i2c_default, addr, buf, 3, false); -} - -void setZGyroOffset(int16_t offset){ - uint8_t buf[] = {MPU6050_ZG_OFFS_USRH, (uint8_t)(offset >> 8), (uint8_t)offset}; - i2c_write_blocking(i2c_default, addr, buf, 3, false); -} - -int16_t getXAccelOffset(){ - uint8_t buffer[6], val = MPU6050_XA_OFFS_H; - i2c_write_blocking(i2c_default, addr, &val, 1, true); - i2c_read_blocking(i2c_default, addr, buffer, 2, false); - return (((int16_t)buffer[0]) << 8) | buffer[1]; -} - -int16_t getYAccelOffset(){ - uint8_t buffer[6], val = MPU6050_YA_OFFS_H; - i2c_write_blocking(i2c_default, addr, &val, 1, true); - i2c_read_blocking(i2c_default, addr, buffer, 2, false); - return (((int16_t)buffer[0]) << 8) | buffer[1]; -} - -int16_t getZAccelOffset(){ - uint8_t buffer[6], val = MPU6050_ZA_OFFS_H; - i2c_write_blocking(i2c_default, addr, &val, 1, true); - i2c_read_blocking(i2c_default, addr, buffer, 2, false); - return (((int16_t)buffer[0]) << 8) | buffer[1]; -} - -int16_t getXGyroOffset(){ - uint8_t buffer[6], val = MPU6050_XG_OFFS_USRH; - i2c_write_blocking(i2c_default, addr, &val, 1, true); - i2c_read_blocking(i2c_default, addr, buffer, 2, false); - return (((int16_t)buffer[0]) << 8) | buffer[1]; -} - -int16_t getYGyroOffset(){ - uint8_t buffer[6], val = MPU6050_YG_OFFS_USRH; - i2c_write_blocking(i2c_default, addr, &val, 1, true); - i2c_read_blocking(i2c_default, addr, buffer, 2, false); - return (((int16_t)buffer[0]) << 8) | buffer[1]; -} - -int16_t getZGyroOffset(){ - uint8_t buffer[6], val = MPU6050_ZG_OFFS_USRH; - i2c_write_blocking(i2c_default, addr, &val, 1, true); - i2c_read_blocking(i2c_default, addr, buffer, 2, false); - return (((int16_t)buffer[0]) << 8) | buffer[1]; -} - -int getDeviceOffsets(int16_t *accel_gyro_offsets){ - accel_gyro_offsets[0] = getXAccelOffset(); - accel_gyro_offsets[1] = getYAccelOffset(); - accel_gyro_offsets[2] = getZAccelOffset(); - accel_gyro_offsets[3] = getXGyroOffset(); - accel_gyro_offsets[4] = getYGyroOffset(); - accel_gyro_offsets[5] = getZGyroOffset(); - - return 0; -} - -int main() { - stdio_init_all(); - - printf("Hello, MPU6050! Reading raw data from registers...\n"); - - /* This example will use I2C0 on the default SDA and SCL pins (4, 5 on a Pico) */ - i2c_init(i2c_default, 400 * 1000); - gpio_set_function(PICO_DEFAULT_I2C_SDA_PIN, GPIO_FUNC_I2C); - gpio_set_function(PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C); - gpio_pull_up(PICO_DEFAULT_I2C_SDA_PIN); - gpio_pull_up(PICO_DEFAULT_I2C_SCL_PIN); - - mpu6050_reset(); - - int16_t acceleration[3], gyro[3], temp; - int16_t accel_gyro_offsets[6] = {0, 0, 0, 0, 0, 0}; - char op; - int16_t mask_16bit = 0x0001, mask_bit[3] = {0, 0, 0}; - - while(1){ - printf("\nSelect option: \n" - "1. Read raw values\n" - "2. Calibrate device\n" - "3. Read offset values\n" - "4. Manually set offset values\n" - "5. Get average readings\n" - "0. Terminate program\n\n"); - op = getchar(); - - if(op == '1'){ - while (1) { - mpu6050_read_raw(acceleration, gyro, &temp); - printf("Acc. X = %f, Y = %f, Z = %f\n", acceleration[0]/16384.0, acceleration[1]/16384.0, acceleration[2]/16384.0); - printf("Gyro. X = %f, Y = %f, Z = %f\n", gyro[0]/131.0, gyro[1]/131.0, gyro[2]/131.0); - /* - Temperature is simple so use the datasheet calculation to get deg C. - Note this is chip temperature. - */ - printf("Temp. = %f\n", (temp / 340.0) + 36.53); - - sleep_ms(100); - } - } - else if(op == '2'){ - mpu6050_discard_values(); - printf("Computing averages, please wait...\n"); - mpu6050_average(MAX_CALIBRATION_SAMPLES); - printf("\nAverage Values\n"); - printf("Acc. X = %d, Y = %d, Z = %d\n", accel_gyro_avg[0], accel_gyro_avg[1], accel_gyro_avg[2]); - printf("Gyro. X = %d, Y = %d, Z = %d\n", accel_gyro_avg[3], accel_gyro_avg[4], accel_gyro_avg[5]); - /*printf("\nAcc. X = %f, Y = %f, Z = %f\n", acceleration[0]/16384.0, acceleration[1]/16384.0, acceleration[2]/16384.0); - printf("Gyro. X = %f, Y = %f, Z = %f\n\n", gyro[0]/131.0, gyro[1]/131.0, gyro[2]/131.0);*/ - - if(getDeviceOffsets(accel_gyro_offsets)) - return -1; - - for(int i=0; i<3; i++){ - if(accel_gyro_offsets[i] & mask_16bit) - mask_bit[i] = mask_16bit; - } - - accelerometerXOffset = (accel_gyro_offsets[0] - (accel_gyro_avg[0] / 8)) | mask_bit[0]; - accelerometerYOffset = (accel_gyro_offsets[1] - (accel_gyro_avg[1] / 8)) | mask_bit[1]; - /* Accelerometer Z Offset drifts and gets bigger, cause? */ - accelerometerZOffset = (accel_gyro_offsets[2] - ((16384 - accel_gyro_avg[2]) / 8)) | mask_bit[2]; - - gyroscopeXOffset -= (accel_gyro_avg[3] / 4); - gyroscopeYOffset -= (accel_gyro_avg[4] / 4); - gyroscopeZOffset -= (accel_gyro_avg[5] / 4); - - printf("\nCalculated Offset Values\n"); - printf("Acc. X = %d, Y = %d, Z = %d\n", accelerometerXOffset, accelerometerYOffset, accelerometerZOffset); - printf("Gyro. X = %d, Y = %d, Z = %d\n", gyroscopeXOffset, gyroscopeYOffset, gyroscopeZOffset); - printf("\nWritting offset values to device...\n"); - setXAccelOffset(accelerometerXOffset); - setYAccelOffset(accelerometerYOffset); - setZAccelOffset(accelerometerZOffset); - setXGyroOffset(gyroscopeXOffset); - setYGyroOffset(gyroscopeYOffset); - setZGyroOffset(gyroscopeZOffset); - mpu6050_average(1000); - printf("\nNEW Average Values\n"); - printf("Acc. X = %d, Y = %d, Z = %d\n", accel_gyro_avg[0], accel_gyro_avg[1], accel_gyro_avg[2]); - printf("Gyro. X = %d, Y = %d, Z = %d\n", accel_gyro_avg[3], accel_gyro_avg[4], accel_gyro_avg[5]); - } - else if(op == '3'){ - if(getDeviceOffsets(accel_gyro_offsets)) - return -1; - - printf("\nOffset Values on device:\n"); - printf("Acc. X = %d, Y = %d, Z = %d\n", accel_gyro_offsets[0], accel_gyro_offsets[1], accel_gyro_offsets[2]); - printf("Gyro. X = %d, Y = %d, Z = %d\n", accel_gyro_offsets[3], accel_gyro_offsets[4], accel_gyro_offsets[5]); - } - else if(op =='4'){ - setXAccelOffset(0); - setYAccelOffset(0); - setZAccelOffset(0); - setXGyroOffset(0); - setYGyroOffset(0); - setZGyroOffset(0); - /*setXAccelOffset(-457); - setYAccelOffset(319); - setZAccelOffset(1392); - setXGyroOffset(7); - setYGyroOffset(-198); - setZGyroOffset(-57);*/ - } - else if(op == '5'){ - /* Get average from 1000 readings */ - mpu6050_average(1000); - printf("\nAverage Values\n"); - printf("Acc. X = %d, Y = %d, Z = %d\n", accel_gyro_avg[0], accel_gyro_avg[1], accel_gyro_avg[2]); - printf("Gyro. X = %d, Y = %d, Z = %d\n", accel_gyro_avg[3], accel_gyro_avg[4], accel_gyro_avg[5]); - } - else if(op == '0'){ - return 0; - } - else{ - printf("\nInvalid option!\n"); - } - } - return 0; -} From e415e82b528c4521b2b2a8a6a573f9bf8c20fc11 Mon Sep 17 00:00:00 2001 From: Robotechnic <45141234+Robotechnic@users.noreply.github.com> Date: Fri, 24 Dec 2021 11:53:28 +0100 Subject: [PATCH 293/335] make the pico blink his led until usb connection is established --- .../examples/mpu6050_DMP_V6.12/mpu6050_DMP_port.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/mpu6050_DMP_port.cpp b/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/mpu6050_DMP_port.cpp index 992acf1e..31ff420f 100644 --- a/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/mpu6050_DMP_port.cpp +++ b/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/mpu6050_DMP_port.cpp @@ -42,8 +42,16 @@ int main() { gpio_pull_up(PICO_DEFAULT_I2C_SDA_PIN); gpio_pull_up(PICO_DEFAULT_I2C_SCL_PIN); // Make the I2C pins available to picotool - - sleep_ms(5000); // So you have time to launch the serial monitor + + // setup blink led + gpio_init(PICO_DEFAULT_LED_PIN); + gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT); + while (!stdio_usb_connected()) { // blink the pico's led until usb connection is established + gpio_put(PICO_DEFAULT_LED_PIN, 1); + sleep_ms(250); + gpio_put(PICO_DEFAULT_LED_PIN, 0); + sleep_ms(250); + } // ================================================================ // === INITIAL SETUP === From cbcdb7b3200e621871e74098df8e7e1ef26a7e9b Mon Sep 17 00:00:00 2001 From: Robotechnic <45141234+Robotechnic@users.noreply.github.com> Date: Fri, 24 Dec 2021 11:55:55 +0100 Subject: [PATCH 294/335] make pico's default led blink until usb connection is established --- .../mpu6050_calibration/mpu6050_calibration.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/RP2040/MPU6050/examples/mpu6050_calibration/mpu6050_calibration.cpp b/RP2040/MPU6050/examples/mpu6050_calibration/mpu6050_calibration.cpp index eb748bf4..987a1d2f 100644 --- a/RP2040/MPU6050/examples/mpu6050_calibration/mpu6050_calibration.cpp +++ b/RP2040/MPU6050/examples/mpu6050_calibration/mpu6050_calibration.cpp @@ -212,7 +212,15 @@ int main() gpio_pull_up(PICO_DEFAULT_I2C_SDA_PIN); gpio_pull_up(PICO_DEFAULT_I2C_SCL_PIN); - sleep_ms(3000); + // setup blink led + gpio_init(PICO_DEFAULT_LED_PIN); + gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT); + while (!stdio_usb_connected()) { // blink the pico's led until usb connection is established + gpio_put(PICO_DEFAULT_LED_PIN, 1); + sleep_ms(250); + gpio_put(PICO_DEFAULT_LED_PIN, 0); + sleep_ms(250); + } Initialize(); for (int i = iAx; i <= iGz; i++) From 758ca4e9fef8d601a05d8727943e50c36a665fdf Mon Sep 17 00:00:00 2001 From: weisseruebe Date: Wed, 26 Jan 2022 17:34:40 +0100 Subject: [PATCH 295/335] Fix comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit See https://invensense.tdk.com/wp-content/uploads/2015/02/MPU-6000-Register-Map1.pdf 4.29 Register 108 – Power Management 2 --- Arduino/MPU6050/MPU6050.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Arduino/MPU6050/MPU6050.cpp b/Arduino/MPU6050/MPU6050.cpp index ecdfe04d..182879f8 100644 --- a/Arduino/MPU6050/MPU6050.cpp +++ b/Arduino/MPU6050/MPU6050.cpp @@ -2556,8 +2556,8 @@ void MPU6050_Base::setClockSource(uint8_t source) { * -------------+------------------ * 0 | 1.25 Hz * 1 | 2.5 Hz - * 2 | 5 Hz - * 3 | 10 Hz + * 2 | 20 Hz + * 3 | 40 Hz *
* * For further information regarding the MPU-60X0's power modes, please refer to From 6bf64572ef8443925481bc39837fab05b3ebfe43 Mon Sep 17 00:00:00 2001 From: i164j9 Date: Mon, 7 Mar 2022 15:09:53 -0600 Subject: [PATCH 296/335] cleaned up the data format from PrintActiveOffsets() made the format easier to read and understand from the perspective of someone looking at the data for the first time. --- Arduino/MPU6050/MPU6050.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Arduino/MPU6050/MPU6050.cpp b/Arduino/MPU6050/MPU6050.cpp index 182879f8..865b109f 100644 --- a/Arduino/MPU6050/MPU6050.cpp +++ b/Arduino/MPU6050/MPU6050.cpp @@ -3376,7 +3376,7 @@ void MPU6050_Base::PrintActiveOffsets() { int16_t Data[3]; //Serial.print(F("Offset Register 0x")); //Serial.print(AOffsetRegister>>4,HEX);Serial.print(AOffsetRegister&0x0F,HEX); - Serial.print(F("\n// X Accel Y Accel Z Accel X Gyro Y Gyro Z Gyro\n// OFFSETS ")); + Serial.print(F("\n\n//\t\tX Accel\t\tY Accel\t\tZ Accel\t\tX Gyro\t\tY Gyro\t\tZ Gyro\n// OFFSETS\t")); if(AOffsetRegister == 0x06) I2Cdev::readWords(devAddr, AOffsetRegister, 3, (uint16_t *)Data, I2Cdev::readTimeout, wireObj); else { I2Cdev::readWords(devAddr, AOffsetRegister, 1, (uint16_t *)Data, I2Cdev::readTimeout, wireObj); @@ -3384,12 +3384,12 @@ void MPU6050_Base::PrintActiveOffsets() { I2Cdev::readWords(devAddr, AOffsetRegister+6, 1, (uint16_t *)Data+2, I2Cdev::readTimeout, wireObj); } // A_OFFSET_H_READ_A_OFFS(Data); - Serial.print((float)Data[0], 5); Serial.print(", "); - Serial.print((float)Data[1], 5); Serial.print(", "); - Serial.print((float)Data[2], 5); Serial.print(", "); + Serial.print((float)Data[0], 5); Serial.print(",\t"); + Serial.print((float)Data[1], 5); Serial.print(",\t"); + Serial.print((float)Data[2], 5); Serial.print(",\t"); I2Cdev::readWords(devAddr, 0x13, 3, (uint16_t *)Data, I2Cdev::readTimeout, wireObj); // XG_OFFSET_H_READ_OFFS_USR(Data); - Serial.print((float)Data[0], 5); Serial.print(", "); - Serial.print((float)Data[1], 5); Serial.print(", "); - Serial.print((float)Data[2], 5); Serial.print("\n"); + Serial.print((float)Data[0], 5); Serial.print(",\t"); + Serial.print((float)Data[1], 5); Serial.print(",\t"); + Serial.print((float)Data[2], 5); Serial.print("\n\n"); } From e81d5477575d19cd16d2e26104e1c8830b26c225 Mon Sep 17 00:00:00 2001 From: Homer Creutz Date: Sat, 12 Mar 2022 15:01:23 -0700 Subject: [PATCH 297/335] Per @pstumbler -- Known Bug: Resolution Including the DMP_FEATURE_TAP I enabled it directly in the DMP Image. * Known Bug - * There is a known issue in which if you do not enable DMP_FEATURE_TAP * then the interrupts will be at 200Hz even if fifo rate * is set at a different rate. To avoid this issue include the DMP_FEATURE_TAP --- Arduino/MPU6050/MPU6050_6Axis_MotionApps612.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Arduino/MPU6050/MPU6050_6Axis_MotionApps612.cpp b/Arduino/MPU6050/MPU6050_6Axis_MotionApps612.cpp index 3fb53e4d..b7b17b2e 100644 --- a/Arduino/MPU6050/MPU6050_6Axis_MotionApps612.cpp +++ b/Arduino/MPU6050/MPU6050_6Axis_MotionApps612.cpp @@ -315,7 +315,7 @@ const unsigned char dmpMemory[MPU6050_DMP_CODE_SIZE] PROGMEM = { 0xC1, 0xC3, 0xD8, 0xB1, 0xB9, 0xF3, 0x8B, 0xA3, 0x91, 0xB6, 0x09, 0xB4, 0xD9, 0xAB, 0xDE, 0xB0, 0x87, 0x9C, 0xB9, 0xA3, 0xDD, 0xF1, 0xB3, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0xB0, 0x87, 0x20, 0x28, 0x30, 0x38, 0xB2, 0x8B, 0xB6, 0x9B, 0xF2, 0xA3, 0xC0, 0xC8, 0xC2, 0xC4, 0xCC, 0xC6, 0xA3, 0xA3, -0xA3, 0xF1, 0xB0, 0x87, 0xB5, 0x9A, 0xD8, 0xF3, 0x9B, 0xA3, 0xA3, 0xDC, 0xBA, 0xAC, 0xDF, 0xB9, +0xA3, 0xF1, 0xB0, 0x87, 0xB5, 0x9A, 0x20, 0xF3, 0x9B, 0xA3, 0xA3, 0xDC, 0xBA, 0xAC, 0xDF, 0xB9, //change 2742 from 0xD8 to 0x20 Including the DMP_FEATURE_TAP -- known issue in which if you do not enable DMP_FEATURE_TAP then the interrupts will be at 200Hz even if fifo rate 0xA3, 0xFE, 0xF2, 0xAB, 0xC4, 0xAA, 0xF1, 0xDF, 0xDF, 0xBB, 0xAF, 0xDF, 0xDF, 0xA3, 0xA3, 0xA3, 0xD8, 0xD8, 0xD8, 0xBB, 0xB3, 0xB7, 0xF1, 0xAA, 0xF9, 0xDA, 0xFF, 0xD9, 0x80, 0x9A, 0xAA, 0x28, 0xB4, 0x80, 0x98, 0xA7, 0x20, 0xB7, 0x97, 0x87, 0xA8, 0x66, 0x88, 0xF0, 0x79, 0x51, 0xF1, 0x90, From a96bbbb726d03cdc393b8a29a8d42a921c37b308 Mon Sep 17 00:00:00 2001 From: Homer Creutz Date: Tue, 15 Mar 2022 11:15:35 -0600 Subject: [PATCH 298/335] Reverting back until I have time to fully test The Interrupt fix causes other issues with the FIFO Packet size. Reverting back to the prior state until I can make this correction. Sorry, I thought this was going to be simple :) --- Arduino/MPU6050/MPU6050_6Axis_MotionApps612.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Arduino/MPU6050/MPU6050_6Axis_MotionApps612.cpp b/Arduino/MPU6050/MPU6050_6Axis_MotionApps612.cpp index b7b17b2e..2e036ddf 100644 --- a/Arduino/MPU6050/MPU6050_6Axis_MotionApps612.cpp +++ b/Arduino/MPU6050/MPU6050_6Axis_MotionApps612.cpp @@ -315,7 +315,7 @@ const unsigned char dmpMemory[MPU6050_DMP_CODE_SIZE] PROGMEM = { 0xC1, 0xC3, 0xD8, 0xB1, 0xB9, 0xF3, 0x8B, 0xA3, 0x91, 0xB6, 0x09, 0xB4, 0xD9, 0xAB, 0xDE, 0xB0, 0x87, 0x9C, 0xB9, 0xA3, 0xDD, 0xF1, 0xB3, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0xB0, 0x87, 0x20, 0x28, 0x30, 0x38, 0xB2, 0x8B, 0xB6, 0x9B, 0xF2, 0xA3, 0xC0, 0xC8, 0xC2, 0xC4, 0xCC, 0xC6, 0xA3, 0xA3, -0xA3, 0xF1, 0xB0, 0x87, 0xB5, 0x9A, 0x20, 0xF3, 0x9B, 0xA3, 0xA3, 0xDC, 0xBA, 0xAC, 0xDF, 0xB9, //change 2742 from 0xD8 to 0x20 Including the DMP_FEATURE_TAP -- known issue in which if you do not enable DMP_FEATURE_TAP then the interrupts will be at 200Hz even if fifo rate +0xA3, 0xF1, 0xB0, 0x87, 0xB5, 0x9A, 0xD8, 0xF3, 0x9B, 0xA3, 0xA3, 0xDC, 0xBA, 0xAC, 0xDF, 0xB9, //Reverted back as packet size changes causing isues... TODO:change 2742 from 0xD8 to 0x20 Including the DMP_FEATURE_TAP -- known issue in which if you do not enable DMP_FEATURE_TAP then the interrupts will be at 200Hz even if fifo rate 0xA3, 0xFE, 0xF2, 0xAB, 0xC4, 0xAA, 0xF1, 0xDF, 0xDF, 0xBB, 0xAF, 0xDF, 0xDF, 0xA3, 0xA3, 0xA3, 0xD8, 0xD8, 0xD8, 0xBB, 0xB3, 0xB7, 0xF1, 0xAA, 0xF9, 0xDA, 0xFF, 0xD9, 0x80, 0x9A, 0xAA, 0x28, 0xB4, 0x80, 0x98, 0xA7, 0x20, 0xB7, 0x97, 0x87, 0xA8, 0x66, 0x88, 0xF0, 0x79, 0x51, 0xF1, 0x90, From 7cc6d850c1d236514e996eb01fdc6b7d00e4c534 Mon Sep 17 00:00:00 2001 From: meneraing Date: Sun, 10 Apr 2022 19:09:06 -0300 Subject: [PATCH 299/335] Added missing semicolon. --- RP2040/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RP2040/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h b/RP2040/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h index 7a8dcf93..0df64e7a 100644 --- a/RP2040/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h +++ b/RP2040/MPU6050/MPU6050_6Axis_MotionApps_V6_12.h @@ -49,7 +49,7 @@ THE SOFTWARE. #include "MPU6050.h" -const double PI = 3.1415926535897932384626433832795 +const double PI = 3.1415926535897932384626433832795; /* Source is from the InvenSense MotionApps v2 demo code. Original source is * unavailable, unless you happen to be amazing as decompiling binary by From 6f13aa45bf86d8546481d1c30fbfe9c4f4769100 Mon Sep 17 00:00:00 2001 From: i164j9 Date: Sun, 10 Apr 2022 19:48:27 -0500 Subject: [PATCH 300/335] Update MPU6050.cpp added the ability to return the offsets so they can be passed as arguments, for "self calibration" its a little hacky but it works. its a copy of PrintActiveOffsets() with all of the print statements removed. --- Arduino/MPU6050/MPU6050.cpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/Arduino/MPU6050/MPU6050.cpp b/Arduino/MPU6050/MPU6050.cpp index 182879f8..be0d05a1 100644 --- a/Arduino/MPU6050/MPU6050.cpp +++ b/Arduino/MPU6050/MPU6050.cpp @@ -3371,6 +3371,29 @@ void MPU6050_Base::PID(uint8_t ReadAddress, float kP,float kI, uint8_t Loops){ resetDMP(); } +float * MPU6050_Base::GetActiveOffsets() { + + uint8_t AOffsetRegister = (getDeviceID() < 0x38 )? MPU6050_RA_XA_OFFS_H:0x77; + int16_t Data[6]{0}; + int16_t Data1[3]{0}; + if(AOffsetRegister == 0x06) I2Cdev::readWords(devAddr, AOffsetRegister, 3, (uint16_t *)Data, I2Cdev::readTimeout, wireObj); + else { + I2Cdev::readWords(devAddr, AOffsetRegister, 1, (uint16_t *)Data, I2Cdev::readTimeout, wireObj); + I2Cdev::readWords(devAddr, AOffsetRegister+3, 1, (uint16_t *)Data+1, I2Cdev::readTimeout, wireObj); + I2Cdev::readWords(devAddr, AOffsetRegister+6, 1, (uint16_t *)Data+2, I2Cdev::readTimeout, wireObj); + } + delay(500); + I2Cdev::readWords(devAddr, 0x13, 3, (uint16_t *)Data1, I2Cdev::readTimeout, wireObj); + delay(500); + Data[3] = Data1[0]; + Data[4] = Data1[1]; + Data[5] = Data1[2]; + for(uint i = 0; i < 6; i++){ + offsets[i] = Data[i]; + } + return offsets; +} + void MPU6050_Base::PrintActiveOffsets() { uint8_t AOffsetRegister = (getDeviceID() < 0x38 )? MPU6050_RA_XA_OFFS_H:0x77; int16_t Data[3]; From fb18f3a33e6d57fc34ff3465214e429e951d8c03 Mon Sep 17 00:00:00 2001 From: i164j9 Date: Sun, 10 Apr 2022 19:50:43 -0500 Subject: [PATCH 301/335] Update MPU6050.h data storage for GetActiveOffsets() --- Arduino/MPU6050/MPU6050.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Arduino/MPU6050/MPU6050.h b/Arduino/MPU6050/MPU6050.h index 888d4db9..a6122dbc 100644 --- a/Arduino/MPU6050/MPU6050.h +++ b/Arduino/MPU6050/MPU6050.h @@ -838,6 +838,9 @@ class MPU6050_Base { void *wireObj; uint8_t buffer[14]; uint32_t fifoTimeout = MPU6050_FIFO_DEFAULT_TIMEOUT; + + private: + float offsets[6]; }; #ifndef I2CDEVLIB_MPU6050_TYPEDEF From fc2fb4461ac48a8ec4caf587569eee5cb720d298 Mon Sep 17 00:00:00 2001 From: i164j9 Date: Mon, 11 Apr 2022 07:54:21 -0500 Subject: [PATCH 302/335] Update MPU6050.cpp removed two delay()'s --- Arduino/MPU6050/MPU6050.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/Arduino/MPU6050/MPU6050.cpp b/Arduino/MPU6050/MPU6050.cpp index be0d05a1..0d2cec80 100644 --- a/Arduino/MPU6050/MPU6050.cpp +++ b/Arduino/MPU6050/MPU6050.cpp @@ -3382,9 +3382,7 @@ float * MPU6050_Base::GetActiveOffsets() { I2Cdev::readWords(devAddr, AOffsetRegister+3, 1, (uint16_t *)Data+1, I2Cdev::readTimeout, wireObj); I2Cdev::readWords(devAddr, AOffsetRegister+6, 1, (uint16_t *)Data+2, I2Cdev::readTimeout, wireObj); } - delay(500); I2Cdev::readWords(devAddr, 0x13, 3, (uint16_t *)Data1, I2Cdev::readTimeout, wireObj); - delay(500); Data[3] = Data1[0]; Data[4] = Data1[1]; Data[5] = Data1[2]; From cadc520a408dae8f6ab22ac8915f6a74b1d422aa Mon Sep 17 00:00:00 2001 From: i164j9 Date: Mon, 11 Apr 2022 08:51:12 -0500 Subject: [PATCH 303/335] Update MPU6050.cpp Adopted the changes by ZHomeSlice and changed the return type to int16_t. --- Arduino/MPU6050/MPU6050.cpp | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/Arduino/MPU6050/MPU6050.cpp b/Arduino/MPU6050/MPU6050.cpp index 0d2cec80..c5da9581 100644 --- a/Arduino/MPU6050/MPU6050.cpp +++ b/Arduino/MPU6050/MPU6050.cpp @@ -3371,23 +3371,18 @@ void MPU6050_Base::PID(uint8_t ReadAddress, float kP,float kI, uint8_t Loops){ resetDMP(); } -float * MPU6050_Base::GetActiveOffsets() { - - uint8_t AOffsetRegister = (getDeviceID() < 0x38 )? MPU6050_RA_XA_OFFS_H:0x77; - int16_t Data[6]{0}; - int16_t Data1[3]{0}; - if(AOffsetRegister == 0x06) I2Cdev::readWords(devAddr, AOffsetRegister, 3, (uint16_t *)Data, I2Cdev::readTimeout, wireObj); - else { - I2Cdev::readWords(devAddr, AOffsetRegister, 1, (uint16_t *)Data, I2Cdev::readTimeout, wireObj); - I2Cdev::readWords(devAddr, AOffsetRegister+3, 1, (uint16_t *)Data+1, I2Cdev::readTimeout, wireObj); - I2Cdev::readWords(devAddr, AOffsetRegister+6, 1, (uint16_t *)Data+2, I2Cdev::readTimeout, wireObj); - } - I2Cdev::readWords(devAddr, 0x13, 3, (uint16_t *)Data1, I2Cdev::readTimeout, wireObj); - Data[3] = Data1[0]; - Data[4] = Data1[1]; - Data[5] = Data1[2]; +int16_t * MPU6050_Base::GetActiveOffsets() { + uint8_t AOffsetRegister = (getDeviceID() < 0x38 )? MPU6050_RA_XA_OFFS_H:0x77; + int16_t Data[6]{0}; + if(AOffsetRegister == 0x06) I2Cdev::readWords(devAddr, AOffsetRegister, 3, (uint16_t *)Data, I2Cdev::readTimeout, wireObj); + else { + I2Cdev::readWords(devAddr, AOffsetRegister, 1, (uint16_t *)Data, I2Cdev::readTimeout, wireObj); + I2Cdev::readWords(devAddr, AOffsetRegister+3, 1, (uint16_t *)(Data+1), I2Cdev::readTimeout, wireObj); + I2Cdev::readWords(devAddr, AOffsetRegister+6, 1, (uint16_t *)(Data+2), I2Cdev::readTimeout, wireObj); + } + I2Cdev::readWords(devAddr, 0x13, 3, (uint16_t *)(Data+3), I2Cdev::readTimeout, wireObj); for(uint i = 0; i < 6; i++){ - offsets[i] = Data[i]; + offsets[i] = (float)Data[i]; } return offsets; } From 0b625e2df49612fb714df5cdb503b4ed046c79ff Mon Sep 17 00:00:00 2001 From: i164j9 Date: Mon, 11 Apr 2022 08:55:40 -0500 Subject: [PATCH 304/335] Update MPU6050.h changed datatype to int16_t --- Arduino/MPU6050/MPU6050.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Arduino/MPU6050/MPU6050.h b/Arduino/MPU6050/MPU6050.h index a6122dbc..82d1f1eb 100644 --- a/Arduino/MPU6050/MPU6050.h +++ b/Arduino/MPU6050/MPU6050.h @@ -832,6 +832,7 @@ class MPU6050_Base { void CalibrateAccel(uint8_t Loops = 15);// Fine tune after setting offsets with less Loops. void PID(uint8_t ReadAddress, float kP,float kI, uint8_t Loops); // Does the math void PrintActiveOffsets(); // See the results of the Calibration + int16_t GetActiveOffsets(); protected: uint8_t devAddr; @@ -840,7 +841,7 @@ class MPU6050_Base { uint32_t fifoTimeout = MPU6050_FIFO_DEFAULT_TIMEOUT; private: - float offsets[6]; + int16_t offsets[6]; }; #ifndef I2CDEVLIB_MPU6050_TYPEDEF From e93a3331b9d7e533cfcd2a2028916519075fadd5 Mon Sep 17 00:00:00 2001 From: i164j9 Date: Mon, 11 Apr 2022 09:05:24 -0500 Subject: [PATCH 305/335] Update MPU6050.cpp removed the type cast i accidentally put back --- Arduino/MPU6050/MPU6050.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Arduino/MPU6050/MPU6050.cpp b/Arduino/MPU6050/MPU6050.cpp index c5da9581..90e7a3ca 100644 --- a/Arduino/MPU6050/MPU6050.cpp +++ b/Arduino/MPU6050/MPU6050.cpp @@ -3382,7 +3382,7 @@ int16_t * MPU6050_Base::GetActiveOffsets() { } I2Cdev::readWords(devAddr, 0x13, 3, (uint16_t *)(Data+3), I2Cdev::readTimeout, wireObj); for(uint i = 0; i < 6; i++){ - offsets[i] = (float)Data[i]; + offsets[i] = Data[i]; } return offsets; } From 1c8596393e293ccc33f0db65306948e27446da2f Mon Sep 17 00:00:00 2001 From: Homer Creutz Date: Tue, 12 Apr 2022 18:50:16 -0600 Subject: [PATCH 306/335] PrintActiveOffsets can be simplified GetActiveOffsets was duplicated in PrintActiveOffsets so we can simplify further the function PrintActiveOffsets and eliminate duplicating code. --- Arduino/MPU6050/MPU6050.cpp | 40 ++++++++++++------------------------- 1 file changed, 13 insertions(+), 27 deletions(-) diff --git a/Arduino/MPU6050/MPU6050.cpp b/Arduino/MPU6050/MPU6050.cpp index edf478e0..ae145004 100644 --- a/Arduino/MPU6050/MPU6050.cpp +++ b/Arduino/MPU6050/MPU6050.cpp @@ -3373,39 +3373,25 @@ void MPU6050_Base::PID(uint8_t ReadAddress, float kP,float kI, uint8_t Loops){ int16_t * MPU6050_Base::GetActiveOffsets() { uint8_t AOffsetRegister = (getDeviceID() < 0x38 )? MPU6050_RA_XA_OFFS_H:0x77; - int16_t Data[6]{0}; - if(AOffsetRegister == 0x06) I2Cdev::readWords(devAddr, AOffsetRegister, 3, (uint16_t *)Data, I2Cdev::readTimeout, wireObj); + if(AOffsetRegister == 0x06) I2Cdev::readWords(devAddr, AOffsetRegister, 3, (uint16_t *)offsets, I2Cdev::readTimeout, wireObj); else { - I2Cdev::readWords(devAddr, AOffsetRegister, 1, (uint16_t *)Data, I2Cdev::readTimeout, wireObj); - I2Cdev::readWords(devAddr, AOffsetRegister+3, 1, (uint16_t *)(Data+1), I2Cdev::readTimeout, wireObj); - I2Cdev::readWords(devAddr, AOffsetRegister+6, 1, (uint16_t *)(Data+2), I2Cdev::readTimeout, wireObj); - } - I2Cdev::readWords(devAddr, 0x13, 3, (uint16_t *)(Data+3), I2Cdev::readTimeout, wireObj); - for(uint i = 0; i < 6; i++){ - offsets[i] = Data[i]; + I2Cdev::readWords(devAddr, AOffsetRegister, 1, (uint16_t *)offsets, I2Cdev::readTimeout, wireObj); + I2Cdev::readWords(devAddr, AOffsetRegister+3, 1, (uint16_t *)(offsets+1), I2Cdev::readTimeout, wireObj); + I2Cdev::readWords(devAddr, AOffsetRegister+6, 1, (uint16_t *)(offsets+2), I2Cdev::readTimeout, wireObj); } + I2Cdev::readWords(devAddr, 0x13, 3, (uint16_t *)(offsets+3), I2Cdev::readTimeout, wireObj); return offsets; } void MPU6050_Base::PrintActiveOffsets() { - uint8_t AOffsetRegister = (getDeviceID() < 0x38 )? MPU6050_RA_XA_OFFS_H:0x77; - int16_t Data[3]; - //Serial.print(F("Offset Register 0x")); - //Serial.print(AOffsetRegister>>4,HEX);Serial.print(AOffsetRegister&0x0F,HEX); - Serial.print(F("\n\n//\t\tX Accel\t\tY Accel\t\tZ Accel\t\tX Gyro\t\tY Gyro\t\tZ Gyro\n// OFFSETS\t")); - if(AOffsetRegister == 0x06) I2Cdev::readWords(devAddr, AOffsetRegister, 3, (uint16_t *)Data, I2Cdev::readTimeout, wireObj); - else { - I2Cdev::readWords(devAddr, AOffsetRegister, 1, (uint16_t *)Data, I2Cdev::readTimeout, wireObj); - I2Cdev::readWords(devAddr, AOffsetRegister+3, 1, (uint16_t *)Data+1, I2Cdev::readTimeout, wireObj); - I2Cdev::readWords(devAddr, AOffsetRegister+6, 1, (uint16_t *)Data+2, I2Cdev::readTimeout, wireObj); - } + GetActiveOffsets(); // A_OFFSET_H_READ_A_OFFS(Data); - Serial.print((float)Data[0], 5); Serial.print(",\t"); - Serial.print((float)Data[1], 5); Serial.print(",\t"); - Serial.print((float)Data[2], 5); Serial.print(",\t"); - I2Cdev::readWords(devAddr, 0x13, 3, (uint16_t *)Data, I2Cdev::readTimeout, wireObj); + Serial.print((float)offsets[0], 5); Serial.print(",\t"); + Serial.print((float)offsets[1], 5); Serial.print(",\t"); + Serial.print((float)offsets[2], 5); Serial.print(",\t"); + // XG_OFFSET_H_READ_OFFS_USR(Data); - Serial.print((float)Data[0], 5); Serial.print(",\t"); - Serial.print((float)Data[1], 5); Serial.print(",\t"); - Serial.print((float)Data[2], 5); Serial.print("\n\n"); + Serial.print((float)offsets[3], 5); Serial.print(",\t"); + Serial.print((float)offsets[4], 5); Serial.print(",\t"); + Serial.print((float)offsets[5], 5); Serial.print("\n\n"); } From 030c61d4e0fc66fe77c47f357a27a28c301ed189 Mon Sep 17 00:00:00 2001 From: eaglehail Date: Wed, 13 Apr 2022 22:28:36 -0400 Subject: [PATCH 307/335] Update MPU6050.h Add * to GetActiveOffsets header. --- Arduino/MPU6050/MPU6050.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Arduino/MPU6050/MPU6050.h b/Arduino/MPU6050/MPU6050.h index 82d1f1eb..7cbbb9dd 100644 --- a/Arduino/MPU6050/MPU6050.h +++ b/Arduino/MPU6050/MPU6050.h @@ -832,7 +832,7 @@ class MPU6050_Base { void CalibrateAccel(uint8_t Loops = 15);// Fine tune after setting offsets with less Loops. void PID(uint8_t ReadAddress, float kP,float kI, uint8_t Loops); // Does the math void PrintActiveOffsets(); // See the results of the Calibration - int16_t GetActiveOffsets(); + int16_t * GetActiveOffsets(); protected: uint8_t devAddr; From c29a25d543baa596a2d7c03f20ac9fb41639b8f4 Mon Sep 17 00:00:00 2001 From: Giampaolo Mancini Date: Wed, 1 Jun 2022 15:03:11 +0200 Subject: [PATCH 308/335] Fix readAll methods on TCA6424A.cpp Hi, the TCA6424A::readAll() methods seem to miss the auto-increment parameter, making it read only the first bank. --- Arduino/TCA6424A/TCA6424A.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Arduino/TCA6424A/TCA6424A.cpp b/Arduino/TCA6424A/TCA6424A.cpp index 851ee6b5..3edc84a3 100644 --- a/Arduino/TCA6424A/TCA6424A.cpp +++ b/Arduino/TCA6424A/TCA6424A.cpp @@ -87,7 +87,7 @@ uint8_t TCA6424A::readBank(uint8_t bank) { * @param banks Container for all bank's pin values (P00-P27) */ void TCA6424A::readAll(uint8_t *banks) { - I2Cdev::readBytes(devAddr, TCA6424A_RA_INPUT0, 3, banks); + I2Cdev::readBytes(devAddr, TCA6424A_RA_INPUT0 | TCA6424A_AUTO_INCREMENT, 3, banks); } /** Get all pin logic levels from all banks. * Reads into individual 1-byte containers. @@ -96,7 +96,7 @@ void TCA6424A::readAll(uint8_t *banks) { * @param bank2 Container for Bank 2's pin values (P20-P27) */ void TCA6424A::readAll(uint8_t *bank0, uint8_t *bank1, uint8_t *bank2) { - I2Cdev::readBytes(devAddr, TCA6424A_RA_INPUT0, 3, buffer); + I2Cdev::readBytes(devAddr, TCA6424A_RA_INPUT0 | TCA6424A_AUTO_INCREMENT, 3, buffer); *bank0 = buffer[0]; *bank1 = buffer[1]; *bank2 = buffer[2]; From acad019a9978c3e8b2d2ca86faad685fc6c1c687 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Fri, 3 Jun 2022 14:04:56 +0000 Subject: [PATCH 309/335] Bump version to 1.0.0 --- Arduino/AD7746/library.json | 4 ++-- Arduino/ADS1115/library.json | 4 ++-- Arduino/ADXL345/library.json | 4 ++-- Arduino/AK8963/library.json | 10 ++++------ Arduino/AK8975/library.json | 15 +++++---------- Arduino/BMA150/library.json | 4 ++-- Arduino/BMP085/library.json | 4 ++-- Arduino/DS1307/library.json | 4 ++-- Arduino/HMC5843/library.json | 4 ++-- Arduino/HMC5883L/library.json | 4 ++-- Arduino/HTU21D/library.json | 4 ++-- Arduino/I2Cdev/library.json | 9 ++++----- Arduino/IAQ2000/library.json | 4 ++-- Arduino/ITG3200/library.json | 4 ++-- Arduino/L3G4200D/library.json | 4 ++-- Arduino/LM73/library.json | 4 ++-- Arduino/MPR121/library.json | 4 ++-- Arduino/MPU6050/library.json | 4 ++-- Arduino/MPU9150/library.json | 4 ++-- Arduino/SSD1308/library.json | 4 ++-- Arduino/TCA6424A/library.json | 4 ++-- MSP430/AK8975/library.json | 1 + MSP430/I2Cdev/library.json | 1 + MSP430/MPU6050/library.json | 1 + 24 files changed, 52 insertions(+), 57 deletions(-) diff --git a/Arduino/AD7746/library.json b/Arduino/AD7746/library.json index 0065cef3..7050cfed 100644 --- a/Arduino/AD7746/library.json +++ b/Arduino/AD7746/library.json @@ -1,5 +1,6 @@ { "name": "I2Cdevlib-AD7746", + "version": "1.0.0", "keywords": "capacitance, converter, sensor, i2cdevlib, i2c", "description": "The AD7745/AD7746 are 24-Bit Capacitance-to-Digital Converter with Temperature Sensor", "include": "Arduino/AD7746", @@ -10,8 +11,7 @@ }, "dependencies": { - "name": "I2Cdevlib-Core", - "frameworks": "arduino" + "jrowberg/I2Cdevlib-Core": "*" }, "frameworks": "arduino", "platforms": "*" diff --git a/Arduino/ADS1115/library.json b/Arduino/ADS1115/library.json index 493cb1ff..50dad5c9 100644 --- a/Arduino/ADS1115/library.json +++ b/Arduino/ADS1115/library.json @@ -1,5 +1,6 @@ { "name": "I2Cdevlib-ADS1115", + "version": "1.0.0", "keywords": "MUX, PGA, comparator, oscillator, reference, i2cdevlib, i2c", "description": "ADS1115 is 16-Bit ADC with Integrated MUX, PGA, Comparator, Oscillator, and Reference", "include": "Arduino/ADS1115", @@ -10,8 +11,7 @@ }, "dependencies": { - "name": "I2Cdevlib-Core", - "frameworks": "arduino" + "jrowberg/I2Cdevlib-Core": "*" }, "frameworks": "arduino", "platforms": "*" diff --git a/Arduino/ADXL345/library.json b/Arduino/ADXL345/library.json index 26d250bf..90ef2108 100644 --- a/Arduino/ADXL345/library.json +++ b/Arduino/ADXL345/library.json @@ -1,5 +1,6 @@ { "name": "I2Cdevlib-ADXL345", + "version": "1.0.0", "keywords": "accelerometer, sensor, i2cdevlib, i2c", "description": "The ADXL345 is a small, thin, ultralow power, 3-axis accelerometer with high resolution (13-bit) measurement", "include": "Arduino/ADXL345", @@ -10,8 +11,7 @@ }, "dependencies": { - "name": "I2Cdevlib-Core", - "frameworks": "arduino" + "jrowberg/I2Cdevlib-Core": "*" }, "frameworks": "arduino", "platforms": "*" diff --git a/Arduino/AK8963/library.json b/Arduino/AK8963/library.json index c6db7829..2d1e96e1 100644 --- a/Arduino/AK8963/library.json +++ b/Arduino/AK8963/library.json @@ -1,5 +1,6 @@ { "name": "I2Cdevlib-AK8963", + "version": "1.0.0", "keywords": "compass, sensor, i2cdevlib, i2c", "description": "AK8963 is 3-axis electronic compass IC with high sensitive Hall sensor technology", "include": "Arduino/AK8963", @@ -9,12 +10,9 @@ "url": "https://github.com/jrowberg/i2cdevlib.git" }, "dependencies": - [ - { - "name": "I2Cdevlib-Core", - "frameworks": "arduino" - } - ], + { + "jrowberg/I2Cdevlib-Core": "*" + }, "frameworks": "arduino", "platforms": "*" } diff --git a/Arduino/AK8975/library.json b/Arduino/AK8975/library.json index b879c39b..ff39cdae 100644 --- a/Arduino/AK8975/library.json +++ b/Arduino/AK8975/library.json @@ -1,5 +1,6 @@ { "name": "I2Cdevlib-AK8975", + "version": "1.0.0", "keywords": "compass, sensor, i2cdevlib, i2c", "description": "AK8975 is 3-axis electronic compass IC with high sensitive Hall sensor technology", "include": "Arduino/AK8975", @@ -9,16 +10,10 @@ "url": "https://github.com/jrowberg/i2cdevlib.git" }, "dependencies": - [ - { - "name": "I2Cdevlib-Core", - "frameworks": "arduino" - }, - { - "name": "I2Cdevlib-MPU6050", - "frameworks": "arduino" - } - ], + { + "jrowberg/I2Cdevlib-Core": "*", + "jrowberg/I2Cdevlib-MPU6050": "*" + }, "frameworks": "arduino", "platforms": "*" } diff --git a/Arduino/BMA150/library.json b/Arduino/BMA150/library.json index e4d50fcf..693e1a53 100644 --- a/Arduino/BMA150/library.json +++ b/Arduino/BMA150/library.json @@ -1,5 +1,6 @@ { "name": "I2Cdevlib-BMA150", + "version": "1.0.0", "keywords": "accelerometer, sensor, i2cdevlib, i2c", "description": "The BMA150 is a triaxial, low-g acceleration sensor IC with digital output for consumer market applications", "include": "Arduino/BMA150", @@ -10,8 +11,7 @@ }, "dependencies": { - "name": "I2Cdevlib-Core", - "frameworks": "arduino" + "jrowberg/I2Cdevlib-Core": "*" }, "frameworks": "arduino", "platforms": "*" diff --git a/Arduino/BMP085/library.json b/Arduino/BMP085/library.json index a9059ba9..9d7d4901 100644 --- a/Arduino/BMP085/library.json +++ b/Arduino/BMP085/library.json @@ -1,5 +1,6 @@ { "name": "I2Cdevlib-BMP085", + "version": "1.0.0", "keywords": "altimeter, altitude, barometer, pressure, temperature, sensor, i2cdevlib, i2c", "description": "The BMP085 is barometric pressure, temperature and altitude sensor", "include": "Arduino/BMP085", @@ -10,8 +11,7 @@ }, "dependencies": { - "name": "I2Cdevlib-Core", - "frameworks": "arduino" + "jrowberg/I2Cdevlib-Core": "*" }, "frameworks": "arduino", "platforms": "*" diff --git a/Arduino/DS1307/library.json b/Arduino/DS1307/library.json index 79955581..4a37b19c 100644 --- a/Arduino/DS1307/library.json +++ b/Arduino/DS1307/library.json @@ -1,5 +1,6 @@ { "name": "I2Cdevlib-DS1307", + "version": "1.0.0", "keywords": "rtc, time, clock, i2cdevlib, i2c", "description": "The DS1307 serial real-time clock (RTC) is a low-power, full binary-coded decimal (BCD) clock/calendar plus 56 bytes of NV SRAM", "include": "Arduino/DS1307", @@ -10,8 +11,7 @@ }, "dependencies": { - "name": "I2Cdevlib-Core", - "frameworks": "arduino" + "jrowberg/I2Cdevlib-Core": "*" }, "frameworks": "arduino", "platforms": "*" diff --git a/Arduino/HMC5843/library.json b/Arduino/HMC5843/library.json index f3aea49b..04feb72d 100644 --- a/Arduino/HMC5843/library.json +++ b/Arduino/HMC5843/library.json @@ -1,5 +1,6 @@ { "name": "I2Cdevlib-HMC5843", + "version": "1.0.0", "keywords": "magnetometer, compass, sensor, i2cdevlib, i2c", "description": "The HMC5843 is 3-Axis digital compass/magnetometer", "include": "Arduino/HMC5843", @@ -10,8 +11,7 @@ }, "dependencies": { - "name": "I2Cdevlib-Core", - "frameworks": "arduino" + "jrowberg/I2Cdevlib-Core": "*" }, "frameworks": "arduino", "platforms": "*" diff --git a/Arduino/HMC5883L/library.json b/Arduino/HMC5883L/library.json index 06448562..abe9cd9a 100644 --- a/Arduino/HMC5883L/library.json +++ b/Arduino/HMC5883L/library.json @@ -1,5 +1,6 @@ { "name": "I2Cdevlib-HMC5883L", + "version": "1.0.0", "keywords": "magnetometer, compass, sensor, i2cdevlib, i2c", "description": "The HMC5883L is 3-Axis digital compass/magnetometer", "include": "Arduino/HMC5883L", @@ -10,8 +11,7 @@ }, "dependencies": { - "name": "I2Cdevlib-Core", - "frameworks": "arduino" + "jrowberg/I2Cdevlib-Core": "*" }, "frameworks": "arduino", "platforms": "*" diff --git a/Arduino/HTU21D/library.json b/Arduino/HTU21D/library.json index 1736f263..f087b3a3 100644 --- a/Arduino/HTU21D/library.json +++ b/Arduino/HTU21D/library.json @@ -1,5 +1,6 @@ { "name": "I2Cdevlib-HTU21D”, + "version": "1.0.0", "keywords": “temperature, humidity, i2cdevlib, i2c", "description": "HTU21D is 12-Bit humidity and 14-bit temperature sensor", "include": "Arduino/HTU21D", @@ -10,8 +11,7 @@ }, "dependencies": { - "name": "I2Cdevlib-Core", - "frameworks": "arduino" + "jrowberg/I2Cdevlib-Core": "*" }, "frameworks": "arduino", "platforms": "*" diff --git a/Arduino/I2Cdev/library.json b/Arduino/I2Cdev/library.json index 5c5eab8f..87a6d879 100644 --- a/Arduino/I2Cdev/library.json +++ b/Arduino/I2Cdev/library.json @@ -1,5 +1,6 @@ { "name": "I2Cdevlib-Core", + "version": "1.0.0", "keywords": "i2cdevlib, i2c", "description": "The I2C Device Library (I2Cdevlib) is a collection of uniform and well-documented classes to provide simple and intuitive interfaces to I2C devices.", "include": "Arduino/I2Cdev", @@ -10,9 +11,7 @@ }, "frameworks": "arduino", "platforms": "*", - "dependencies": [ - { - "name": "Wire" - } - ] + "dependencies": { + "Wire": "*" + } } diff --git a/Arduino/IAQ2000/library.json b/Arduino/IAQ2000/library.json index 12d70f8b..dfcd93c6 100644 --- a/Arduino/IAQ2000/library.json +++ b/Arduino/IAQ2000/library.json @@ -1,5 +1,6 @@ { "name": "I2Cdevlib-IAQ2000", + "version": "1.0.0", "keywords": "co2, carbon, dioxide, sensor, i2cdevlib, i2c", "description": "The iAQ-2000 Indoor Air Quality Module is a sensitive, low-cost solution for detecting poor air quality", "include": "Arduino/IAQ2000", @@ -10,8 +11,7 @@ }, "dependencies": { - "name": "I2Cdevlib-Core", - "frameworks": "arduino" + "jrowberg/I2Cdevlib-Core": "*" }, "frameworks": "arduino", "platforms": "*" diff --git a/Arduino/ITG3200/library.json b/Arduino/ITG3200/library.json index c4a69b66..23b4f1b7 100644 --- a/Arduino/ITG3200/library.json +++ b/Arduino/ITG3200/library.json @@ -1,5 +1,6 @@ { "name": "I2Cdevlib-ITG3200", + "version": "1.0.0", "keywords": "gyroscope, sensor, i2cdevlib, i2c", "description": "The ITG-3200 is groundbreaking 3-axis, digital output MEMS gyroscope", "include": "Arduino/ITG3200", @@ -10,8 +11,7 @@ }, "dependencies": { - "name": "I2Cdevlib-Core", - "frameworks": "arduino" + "jrowberg/I2Cdevlib-Core": "*" }, "frameworks": "arduino", "platforms": "*" diff --git a/Arduino/L3G4200D/library.json b/Arduino/L3G4200D/library.json index 185d66fa..7ffe66eb 100644 --- a/Arduino/L3G4200D/library.json +++ b/Arduino/L3G4200D/library.json @@ -1,5 +1,6 @@ { "name": "I2Cdevlib-L3G4200D", + "version": "1.0.0", "keywords": "accelerometer, sensor, i2cdevlib, i2c", "description": "The L3G4200D is a low-power three-axis angular rate sensor able to provide unprecedented stablility of zero rate level and sensitivity over temperature and time", "include": "Arduino/L3G4200D", @@ -10,8 +11,7 @@ }, "dependencies": { - "name": "I2Cdevlib-Core", - "frameworks": "arduino" + "jrowberg/I2Cdevlib-Core": "*" }, "frameworks": "arduino", "platforms": "*" diff --git a/Arduino/LM73/library.json b/Arduino/LM73/library.json index a1afad4c..490ec364 100644 --- a/Arduino/LM73/library.json +++ b/Arduino/LM73/library.json @@ -1,5 +1,6 @@ { "name": "I2Cdevlib-LM73", + "version": "1.0.0", "keywords": "temperature, sensor, i2cdevlib, i2c", "description": "The LM73 is an integrated, digital-output temperature sensor featuring an incremental Delta-Sigma ADC", "include": "Arduino/LM73", @@ -10,8 +11,7 @@ }, "dependencies": { - "name": "I2Cdevlib-Core", - "frameworks": "arduino" + "jrowberg/I2Cdevlib-Core": "*" }, "frameworks": "arduino", "platforms": "*" diff --git a/Arduino/MPR121/library.json b/Arduino/MPR121/library.json index dbe47d8b..877ebe3c 100644 --- a/Arduino/MPR121/library.json +++ b/Arduino/MPR121/library.json @@ -1,5 +1,6 @@ { "name": "I2Cdevlib-MPR121", + "version": "1.0.0", "keywords": "touch, capacitance, proximity, sensor, i2cdevlib, i2c", "description": "The MPR121 is a 12-bit proximity capacitive touch sensor", "include": "Arduino/MPR121", @@ -10,8 +11,7 @@ }, "dependencies": { - "name": "I2Cdevlib-Core", - "frameworks": "arduino" + "jrowberg/I2Cdevlib-Core": "*" }, "frameworks": "arduino", "platforms": "*" diff --git a/Arduino/MPU6050/library.json b/Arduino/MPU6050/library.json index e89e10cb..3b5ad90a 100644 --- a/Arduino/MPU6050/library.json +++ b/Arduino/MPU6050/library.json @@ -1,5 +1,6 @@ { "name": "I2Cdevlib-MPU6050", + "version": "1.0.0", "keywords": "gyroscope, accelerometer, sensor, i2cdevlib, i2c", "description": "The MPU6050 combines a 3-axis gyroscope and a 3-axis accelerometer on the same silicon die together with an onboard Digital Motion Processor(DMP) which processes complex 6-axis MotionFusion algorithms", "include": "Arduino/MPU6050", @@ -10,8 +11,7 @@ }, "dependencies": { - "name": "I2Cdevlib-Core", - "frameworks": "arduino" + "jrowberg/I2Cdevlib-Core": "*" }, "frameworks": "arduino", "platforms": "*" diff --git a/Arduino/MPU9150/library.json b/Arduino/MPU9150/library.json index abf665ae..dcabbee4 100644 --- a/Arduino/MPU9150/library.json +++ b/Arduino/MPU9150/library.json @@ -1,5 +1,6 @@ { "name": "I2Cdevlib-MPU9150", + "version": "1.0.0", "keywords": "gyroscope, accelerometer, compass, sensor, i2cdevlib, i2c", "description": "The MPU-9150 combines two chips: the MPU-6050, which contains a 3-axis gyroscope, 3-axis accelerometer and the AK8975, a 3-axis digital compass", "include": "Arduino/MPU9150", @@ -10,8 +11,7 @@ }, "dependencies": { - "name": "I2Cdevlib-Core", - "frameworks": "arduino" + "jrowberg/I2Cdevlib-Core": "*" }, "frameworks": "arduino", "platforms": "*" diff --git a/Arduino/SSD1308/library.json b/Arduino/SSD1308/library.json index ede7dff1..8fb684fe 100644 --- a/Arduino/SSD1308/library.json +++ b/Arduino/SSD1308/library.json @@ -1,5 +1,6 @@ { "name": "I2Cdevlib-SSD1308", + "version": "1.0.0", "keywords": "oled, pled, display, driver, i2cdevlib, i2c", "description": "SSD1308 is a single-chip CMOS OLED/PLED driver with controller for organic / polymer light emitting diode dot-matrix graphic display system", "include": "Arduino/SSD1308", @@ -10,8 +11,7 @@ }, "dependencies": { - "name": "I2Cdevlib-Core", - "frameworks": "arduino" + "jrowberg/I2Cdevlib-Core": "*" }, "frameworks": "arduino", "platforms": "*" diff --git a/Arduino/TCA6424A/library.json b/Arduino/TCA6424A/library.json index 0b97b21b..53018378 100644 --- a/Arduino/TCA6424A/library.json +++ b/Arduino/TCA6424A/library.json @@ -1,5 +1,6 @@ { "name": "I2Cdevlib-TCA6424A", + "version": "1.0.0", "keywords": "io, expander, i2cdevlib, i2c", "description": "The TCA6424A is a low-voltage 24-Bit I2C and SMBus I/O expander with interrupt output, reset and configuration registers", "include": "Arduino/TCA6424A", @@ -10,8 +11,7 @@ }, "dependencies": { - "name": "I2Cdevlib-Core", - "frameworks": "arduino" + "jrowberg/I2Cdevlib-Core": "*" }, "frameworks": "arduino", "platforms": "*" diff --git a/MSP430/AK8975/library.json b/MSP430/AK8975/library.json index 09f3e41a..44c22b94 100644 --- a/MSP430/AK8975/library.json +++ b/MSP430/AK8975/library.json @@ -1,5 +1,6 @@ { "name": "I2Cdevlib-AK8975", + "version": "1.0.0", "keywords": "compass, sensor, i2cdevlib, i2c", "description": "AK8975 is 3-axis electronic compass IC with high sensitive Hall sensor technology", "include": "MSP430/AK8975", diff --git a/MSP430/I2Cdev/library.json b/MSP430/I2Cdev/library.json index 98e0963f..99bbece1 100644 --- a/MSP430/I2Cdev/library.json +++ b/MSP430/I2Cdev/library.json @@ -1,5 +1,6 @@ { "name": "I2Cdevlib-Core", + "version": "1.0.0", "keywords": "i2cdevlib, i2c", "description": "The I2C Device Library (I2Cdevlib) is a collection of uniform and well-documented classes to provide simple and intuitive interfaces to I2C devices.", "include": "MSP430/I2Cdev", diff --git a/MSP430/MPU6050/library.json b/MSP430/MPU6050/library.json index d77b98e4..15e3cfbb 100644 --- a/MSP430/MPU6050/library.json +++ b/MSP430/MPU6050/library.json @@ -1,5 +1,6 @@ { "name": "I2Cdevlib-MPU6050", + "version": "1.0.0", "keywords": "gyroscope, accelerometer, sensor, i2cdevlib, i2c", "description": "The MPU6050 combines a 3-axis gyroscope and a 3-axis accelerometer on the same silicon die together with an onboard Digital Motion Processor(DMP) which processes complex 6-axis MotionFusion algorithms", "include": "MSP430/MPU6050", From 3dc0d85cdd100e1dc6c7cb7ce1eda1ee71ef450b Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Fri, 3 Jun 2022 17:08:29 +0300 Subject: [PATCH 310/335] Fix broken manifest --- Arduino/HTU21D/library.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Arduino/HTU21D/library.json b/Arduino/HTU21D/library.json index f087b3a3..f85f0d23 100644 --- a/Arduino/HTU21D/library.json +++ b/Arduino/HTU21D/library.json @@ -1,7 +1,7 @@ { - "name": "I2Cdevlib-HTU21D”, + "name": "I2Cdevlib-HTU21D", "version": "1.0.0", - "keywords": “temperature, humidity, i2cdevlib, i2c", + "keywords": "temperature, humidity, i2cdevlib, i2c", "description": "HTU21D is 12-Bit humidity and 14-bit temperature sensor", "include": "Arduino/HTU21D", "repository": From f8a6798fc19d5820c386249b7de526b58ad6476d Mon Sep 17 00:00:00 2001 From: brand17 <36546021+brand17@users.noreply.github.com> Date: Sun, 3 Jul 2022 19:00:02 +0300 Subject: [PATCH 311/335] brand17_patch --- .../MPU6050/MPU6050_6Axis_MotionApps20.h | 319 +++++++++--------- ESP32_ESP-IDF/main/example.cpp | 6 +- 2 files changed, 159 insertions(+), 166 deletions(-) diff --git a/ESP32_ESP-IDF/components/MPU6050/MPU6050_6Axis_MotionApps20.h b/ESP32_ESP-IDF/components/MPU6050/MPU6050_6Axis_MotionApps20.h index 3d018568..7ec8da74 100644 --- a/ESP32_ESP-IDF/components/MPU6050/MPU6050_6Axis_MotionApps20.h +++ b/ESP32_ESP-IDF/components/MPU6050/MPU6050_6Axis_MotionApps20.h @@ -136,142 +136,135 @@ THE SOFTWARE. // to be volatile memory, so it has to be done each time (it only takes ~1 // second though) const unsigned char dmpMemory[MPU6050_DMP_CODE_SIZE] = { - // bank 0, 256 bytes - 0xFB, 0x00, 0x00, 0x3E, 0x00, 0x0B, 0x00, 0x36, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, - 0x00, 0x65, 0x00, 0x54, 0xFF, 0xEF, 0x00, 0x00, 0xFA, 0x80, 0x00, 0x0B, 0x12, 0x82, 0x00, 0x01, - 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x28, 0x00, 0x00, 0xFF, 0xFF, 0x45, 0x81, 0xFF, 0xFF, 0xFA, 0x72, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x03, 0xE8, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x7F, 0xFF, 0xFF, 0xFE, 0x80, 0x01, - 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x3E, 0x03, 0x30, 0x40, 0x00, 0x00, 0x00, 0x02, 0xCA, 0xE3, 0x09, 0x3E, 0x80, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, - 0x41, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x2A, 0x00, 0x00, 0x16, 0x55, 0x00, 0x00, 0x21, 0x82, - 0xFD, 0x87, 0x26, 0x50, 0xFD, 0x80, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x05, 0x80, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x6F, 0x00, 0x02, 0x65, 0x32, 0x00, 0x00, 0x5E, 0xC0, - 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFB, 0x8C, 0x6F, 0x5D, 0xFD, 0x5D, 0x08, 0xD9, 0x00, 0x7C, 0x73, 0x3B, 0x00, 0x6C, 0x12, 0xCC, - 0x32, 0x00, 0x13, 0x9D, 0x32, 0x00, 0xD0, 0xD6, 0x32, 0x00, 0x08, 0x00, 0x40, 0x00, 0x01, 0xF4, - 0xFF, 0xE6, 0x80, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0xD6, 0x00, 0x00, 0x27, 0x10, - - // bank 1, 256 bytes - 0xFB, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xFA, 0x36, 0xFF, 0xBC, 0x30, 0x8E, 0x00, 0x05, 0xFB, 0xF0, 0xFF, 0xD9, 0x5B, 0xC8, - 0xFF, 0xD0, 0x9A, 0xBE, 0x00, 0x00, 0x10, 0xA9, 0xFF, 0xF4, 0x1E, 0xB2, 0x00, 0xCE, 0xBB, 0xF7, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x0C, - 0xFF, 0xC2, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0xCF, 0x80, 0x00, 0x40, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x14, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x3F, 0x68, 0xB6, 0x79, 0x35, 0x28, 0xBC, 0xC6, 0x7E, 0xD1, 0x6C, - 0x80, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB2, 0x6A, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x25, 0x4D, 0x00, 0x2F, 0x70, 0x6D, 0x00, 0x00, 0x05, 0xAE, 0x00, 0x0C, 0x02, 0xD0, - - // bank 2, 256 bytes - 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x54, 0xFF, 0xEF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0xFF, 0xEF, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, - 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - - // bank 3, 256 bytes - 0xD8, 0xDC, 0xBA, 0xA2, 0xF1, 0xDE, 0xB2, 0xB8, 0xB4, 0xA8, 0x81, 0x91, 0xF7, 0x4A, 0x90, 0x7F, - 0x91, 0x6A, 0xF3, 0xF9, 0xDB, 0xA8, 0xF9, 0xB0, 0xBA, 0xA0, 0x80, 0xF2, 0xCE, 0x81, 0xF3, 0xC2, - 0xF1, 0xC1, 0xF2, 0xC3, 0xF3, 0xCC, 0xA2, 0xB2, 0x80, 0xF1, 0xC6, 0xD8, 0x80, 0xBA, 0xA7, 0xDF, - 0xDF, 0xDF, 0xF2, 0xA7, 0xC3, 0xCB, 0xC5, 0xB6, 0xF0, 0x87, 0xA2, 0x94, 0x24, 0x48, 0x70, 0x3C, - 0x95, 0x40, 0x68, 0x34, 0x58, 0x9B, 0x78, 0xA2, 0xF1, 0x83, 0x92, 0x2D, 0x55, 0x7D, 0xD8, 0xB1, - 0xB4, 0xB8, 0xA1, 0xD0, 0x91, 0x80, 0xF2, 0x70, 0xF3, 0x70, 0xF2, 0x7C, 0x80, 0xA8, 0xF1, 0x01, - 0xB0, 0x98, 0x87, 0xD9, 0x43, 0xD8, 0x86, 0xC9, 0x88, 0xBA, 0xA1, 0xF2, 0x0E, 0xB8, 0x97, 0x80, - 0xF1, 0xA9, 0xDF, 0xDF, 0xDF, 0xAA, 0xDF, 0xDF, 0xDF, 0xF2, 0xAA, 0xC5, 0xCD, 0xC7, 0xA9, 0x0C, - 0xC9, 0x2C, 0x97, 0x97, 0x97, 0x97, 0xF1, 0xA9, 0x89, 0x26, 0x46, 0x66, 0xB0, 0xB4, 0xBA, 0x80, - 0xAC, 0xDE, 0xF2, 0xCA, 0xF1, 0xB2, 0x8C, 0x02, 0xA9, 0xB6, 0x98, 0x00, 0x89, 0x0E, 0x16, 0x1E, - 0xB8, 0xA9, 0xB4, 0x99, 0x2C, 0x54, 0x7C, 0xB0, 0x8A, 0xA8, 0x96, 0x36, 0x56, 0x76, 0xF1, 0xB9, - 0xAF, 0xB4, 0xB0, 0x83, 0xC0, 0xB8, 0xA8, 0x97, 0x11, 0xB1, 0x8F, 0x98, 0xB9, 0xAF, 0xF0, 0x24, - 0x08, 0x44, 0x10, 0x64, 0x18, 0xF1, 0xA3, 0x29, 0x55, 0x7D, 0xAF, 0x83, 0xB5, 0x93, 0xAF, 0xF0, - 0x00, 0x28, 0x50, 0xF1, 0xA3, 0x86, 0x9F, 0x61, 0xA6, 0xDA, 0xDE, 0xDF, 0xD9, 0xFA, 0xA3, 0x86, - 0x96, 0xDB, 0x31, 0xA6, 0xD9, 0xF8, 0xDF, 0xBA, 0xA6, 0x8F, 0xC2, 0xC5, 0xC7, 0xB2, 0x8C, 0xC1, - 0xB8, 0xA2, 0xDF, 0xDF, 0xDF, 0xA3, 0xDF, 0xDF, 0xDF, 0xD8, 0xD8, 0xF1, 0xB8, 0xA8, 0xB2, 0x86, - - // bank 4, 256 bytes - 0xB4, 0x98, 0x0D, 0x35, 0x5D, 0xB8, 0xAA, 0x98, 0xB0, 0x87, 0x2D, 0x35, 0x3D, 0xB2, 0xB6, 0xBA, - 0xAF, 0x8C, 0x96, 0x19, 0x8F, 0x9F, 0xA7, 0x0E, 0x16, 0x1E, 0xB4, 0x9A, 0xB8, 0xAA, 0x87, 0x2C, - 0x54, 0x7C, 0xB9, 0xA3, 0xDE, 0xDF, 0xDF, 0xA3, 0xB1, 0x80, 0xF2, 0xC4, 0xCD, 0xC9, 0xF1, 0xB8, - 0xA9, 0xB4, 0x99, 0x83, 0x0D, 0x35, 0x5D, 0x89, 0xB9, 0xA3, 0x2D, 0x55, 0x7D, 0xB5, 0x93, 0xA3, - 0x0E, 0x16, 0x1E, 0xA9, 0x2C, 0x54, 0x7C, 0xB8, 0xB4, 0xB0, 0xF1, 0x97, 0x83, 0xA8, 0x11, 0x84, - 0xA5, 0x09, 0x98, 0xA3, 0x83, 0xF0, 0xDA, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0xD8, 0xF1, 0xA5, - 0x29, 0x55, 0x7D, 0xA5, 0x85, 0x95, 0x02, 0x1A, 0x2E, 0x3A, 0x56, 0x5A, 0x40, 0x48, 0xF9, 0xF3, - 0xA3, 0xD9, 0xF8, 0xF0, 0x98, 0x83, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0x97, 0x82, 0xA8, 0xF1, - 0x11, 0xF0, 0x98, 0xA2, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0xDA, 0xF3, 0xDE, 0xD8, 0x83, 0xA5, - 0x94, 0x01, 0xD9, 0xA3, 0x02, 0xF1, 0xA2, 0xC3, 0xC5, 0xC7, 0xD8, 0xF1, 0x84, 0x92, 0xA2, 0x4D, - 0xDA, 0x2A, 0xD8, 0x48, 0x69, 0xD9, 0x2A, 0xD8, 0x68, 0x55, 0xDA, 0x32, 0xD8, 0x50, 0x71, 0xD9, - 0x32, 0xD8, 0x70, 0x5D, 0xDA, 0x3A, 0xD8, 0x58, 0x79, 0xD9, 0x3A, 0xD8, 0x78, 0x93, 0xA3, 0x4D, - 0xDA, 0x2A, 0xD8, 0x48, 0x69, 0xD9, 0x2A, 0xD8, 0x68, 0x55, 0xDA, 0x32, 0xD8, 0x50, 0x71, 0xD9, - 0x32, 0xD8, 0x70, 0x5D, 0xDA, 0x3A, 0xD8, 0x58, 0x79, 0xD9, 0x3A, 0xD8, 0x78, 0xA8, 0x8A, 0x9A, - 0xF0, 0x28, 0x50, 0x78, 0x9E, 0xF3, 0x88, 0x18, 0xF1, 0x9F, 0x1D, 0x98, 0xA8, 0xD9, 0x08, 0xD8, - 0xC8, 0x9F, 0x12, 0x9E, 0xF3, 0x15, 0xA8, 0xDA, 0x12, 0x10, 0xD8, 0xF1, 0xAF, 0xC8, 0x97, 0x87, - - // bank 5, 256 bytes - 0x34, 0xB5, 0xB9, 0x94, 0xA4, 0x21, 0xF3, 0xD9, 0x22, 0xD8, 0xF2, 0x2D, 0xF3, 0xD9, 0x2A, 0xD8, - 0xF2, 0x35, 0xF3, 0xD9, 0x32, 0xD8, 0x81, 0xA4, 0x60, 0x60, 0x61, 0xD9, 0x61, 0xD8, 0x6C, 0x68, - 0x69, 0xD9, 0x69, 0xD8, 0x74, 0x70, 0x71, 0xD9, 0x71, 0xD8, 0xB1, 0xA3, 0x84, 0x19, 0x3D, 0x5D, - 0xA3, 0x83, 0x1A, 0x3E, 0x5E, 0x93, 0x10, 0x30, 0x81, 0x10, 0x11, 0xB8, 0xB0, 0xAF, 0x8F, 0x94, - 0xF2, 0xDA, 0x3E, 0xD8, 0xB4, 0x9A, 0xA8, 0x87, 0x29, 0xDA, 0xF8, 0xD8, 0x87, 0x9A, 0x35, 0xDA, - 0xF8, 0xD8, 0x87, 0x9A, 0x3D, 0xDA, 0xF8, 0xD8, 0xB1, 0xB9, 0xA4, 0x98, 0x85, 0x02, 0x2E, 0x56, - 0xA5, 0x81, 0x00, 0x0C, 0x14, 0xA3, 0x97, 0xB0, 0x8A, 0xF1, 0x2D, 0xD9, 0x28, 0xD8, 0x4D, 0xD9, - 0x48, 0xD8, 0x6D, 0xD9, 0x68, 0xD8, 0xB1, 0x84, 0x0D, 0xDA, 0x0E, 0xD8, 0xA3, 0x29, 0x83, 0xDA, - 0x2C, 0x0E, 0xD8, 0xA3, 0x84, 0x49, 0x83, 0xDA, 0x2C, 0x4C, 0x0E, 0xD8, 0xB8, 0xB0, 0xA8, 0x8A, - 0x9A, 0xF5, 0x20, 0xAA, 0xDA, 0xDF, 0xD8, 0xA8, 0x40, 0xAA, 0xD0, 0xDA, 0xDE, 0xD8, 0xA8, 0x60, - 0xAA, 0xDA, 0xD0, 0xDF, 0xD8, 0xF1, 0x97, 0x86, 0xA8, 0x31, 0x9B, 0x06, 0x99, 0x07, 0xAB, 0x97, - 0x28, 0x88, 0x9B, 0xF0, 0x0C, 0x20, 0x14, 0x40, 0xB8, 0xB0, 0xB4, 0xA8, 0x8C, 0x9C, 0xF0, 0x04, - 0x28, 0x51, 0x79, 0x1D, 0x30, 0x14, 0x38, 0xB2, 0x82, 0xAB, 0xD0, 0x98, 0x2C, 0x50, 0x50, 0x78, - 0x78, 0x9B, 0xF1, 0x1A, 0xB0, 0xF0, 0x8A, 0x9C, 0xA8, 0x29, 0x51, 0x79, 0x8B, 0x29, 0x51, 0x79, - 0x8A, 0x24, 0x70, 0x59, 0x8B, 0x20, 0x58, 0x71, 0x8A, 0x44, 0x69, 0x38, 0x8B, 0x39, 0x40, 0x68, - 0x8A, 0x64, 0x48, 0x31, 0x8B, 0x30, 0x49, 0x60, 0xA5, 0x88, 0x20, 0x09, 0x71, 0x58, 0x44, 0x68, - - // bank 6, 256 bytes - 0x11, 0x39, 0x64, 0x49, 0x30, 0x19, 0xF1, 0xAC, 0x00, 0x2C, 0x54, 0x7C, 0xF0, 0x8C, 0xA8, 0x04, - 0x28, 0x50, 0x78, 0xF1, 0x88, 0x97, 0x26, 0xA8, 0x59, 0x98, 0xAC, 0x8C, 0x02, 0x26, 0x46, 0x66, - 0xF0, 0x89, 0x9C, 0xA8, 0x29, 0x51, 0x79, 0x24, 0x70, 0x59, 0x44, 0x69, 0x38, 0x64, 0x48, 0x31, - 0xA9, 0x88, 0x09, 0x20, 0x59, 0x70, 0xAB, 0x11, 0x38, 0x40, 0x69, 0xA8, 0x19, 0x31, 0x48, 0x60, - 0x8C, 0xA8, 0x3C, 0x41, 0x5C, 0x20, 0x7C, 0x00, 0xF1, 0x87, 0x98, 0x19, 0x86, 0xA8, 0x6E, 0x76, - 0x7E, 0xA9, 0x99, 0x88, 0x2D, 0x55, 0x7D, 0x9E, 0xB9, 0xA3, 0x8A, 0x22, 0x8A, 0x6E, 0x8A, 0x56, - 0x8A, 0x5E, 0x9F, 0xB1, 0x83, 0x06, 0x26, 0x46, 0x66, 0x0E, 0x2E, 0x4E, 0x6E, 0x9D, 0xB8, 0xAD, - 0x00, 0x2C, 0x54, 0x7C, 0xF2, 0xB1, 0x8C, 0xB4, 0x99, 0xB9, 0xA3, 0x2D, 0x55, 0x7D, 0x81, 0x91, - 0xAC, 0x38, 0xAD, 0x3A, 0xB5, 0x83, 0x91, 0xAC, 0x2D, 0xD9, 0x28, 0xD8, 0x4D, 0xD9, 0x48, 0xD8, - 0x6D, 0xD9, 0x68, 0xD8, 0x8C, 0x9D, 0xAE, 0x29, 0xD9, 0x04, 0xAE, 0xD8, 0x51, 0xD9, 0x04, 0xAE, - 0xD8, 0x79, 0xD9, 0x04, 0xD8, 0x81, 0xF3, 0x9D, 0xAD, 0x00, 0x8D, 0xAE, 0x19, 0x81, 0xAD, 0xD9, - 0x01, 0xD8, 0xF2, 0xAE, 0xDA, 0x26, 0xD8, 0x8E, 0x91, 0x29, 0x83, 0xA7, 0xD9, 0xAD, 0xAD, 0xAD, - 0xAD, 0xF3, 0x2A, 0xD8, 0xD8, 0xF1, 0xB0, 0xAC, 0x89, 0x91, 0x3E, 0x5E, 0x76, 0xF3, 0xAC, 0x2E, - 0x2E, 0xF1, 0xB1, 0x8C, 0x5A, 0x9C, 0xAC, 0x2C, 0x28, 0x28, 0x28, 0x9C, 0xAC, 0x30, 0x18, 0xA8, - 0x98, 0x81, 0x28, 0x34, 0x3C, 0x97, 0x24, 0xA7, 0x28, 0x34, 0x3C, 0x9C, 0x24, 0xF2, 0xB0, 0x89, - 0xAC, 0x91, 0x2C, 0x4C, 0x6C, 0x8A, 0x9B, 0x2D, 0xD9, 0xD8, 0xD8, 0x51, 0xD9, 0xD8, 0xD8, 0x79, - - // bank 7, 138 bytes (remainder) - 0xD9, 0xD8, 0xD8, 0xF1, 0x9E, 0x88, 0xA3, 0x31, 0xDA, 0xD8, 0xD8, 0x91, 0x2D, 0xD9, 0x28, 0xD8, - 0x4D, 0xD9, 0x48, 0xD8, 0x6D, 0xD9, 0x68, 0xD8, 0xB1, 0x83, 0x93, 0x35, 0x3D, 0x80, 0x25, 0xDA, - 0xD8, 0xD8, 0x85, 0x69, 0xDA, 0xD8, 0xD8, 0xB4, 0x93, 0x81, 0xA3, 0x28, 0x34, 0x3C, 0xF3, 0xAB, - 0x8B, 0xF8, 0xA3, 0x91, 0xB6, 0x09, 0xB4, 0xD9, 0xAB, 0xDE, 0xFA, 0xB0, 0x87, 0x9C, 0xB9, 0xA3, - 0xDD, 0xF1, 0xA3, 0xA3, 0xA3, 0xA3, 0x95, 0xF1, 0xA3, 0xA3, 0xA3, 0x9D, 0xF1, 0xA3, 0xA3, 0xA3, - 0xA3, 0xF2, 0xA3, 0xB4, 0x90, 0x80, 0xF2, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, - 0xA3, 0xB2, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xB0, 0x87, 0xB5, 0x99, 0xF1, 0xA3, 0xA3, 0xA3, - 0x98, 0xF1, 0xA3, 0xA3, 0xA3, 0xA3, 0x97, 0xA3, 0xA3, 0xA3, 0xA3, 0xF3, 0x9B, 0xA3, 0xA3, 0xDC, - 0xB9, 0xA7, 0xF1, 0x26, 0x26, 0x26, 0xD8, 0xD8, 0xFF + /* bank # 0 */ + 0xFB, 0x00, 0x00, 0x3E, 0x00, 0x0B, 0x00, 0x36, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x65, 0x00, 0x54, 0xFF, 0xEF, 0x00, 0x00, 0xFA, 0x80, 0x00, 0x0B, 0x12, 0x82, 0x00, 0x01, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x28, 0x00, 0x00, 0xFF, 0xFF, 0x45, 0x81, 0xFF, 0xFF, 0xFA, 0x72, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0xE8, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x7F, 0xFF, 0xFF, 0xFE, 0x80, 0x01, + 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0xCB, 0x47, 0xA2, 0x20, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, + 0x41, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x2A, 0x00, 0x00, 0x16, 0x55, 0x00, 0x00, 0x21, 0x82, + 0xFD, 0x87, 0x26, 0x50, 0xFD, 0x80, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x05, 0x80, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x6F, 0x00, 0x02, 0x65, 0x32, 0x00, 0x00, 0x5E, 0xC0, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFB, 0x8C, 0x6F, 0x5D, 0xFD, 0x5D, 0x08, 0xD9, 0x00, 0x7C, 0x73, 0x3B, 0x00, 0x6C, 0x12, 0xCC, + 0x32, 0x00, 0x13, 0x9D, 0x32, 0x00, 0xD0, 0xD6, 0x32, 0x00, 0x08, 0x00, 0x40, 0x00, 0x01, 0xF4, + 0xFF, 0xE6, 0x80, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0xD6, 0x00, 0x00, 0x27, 0x10, + /* bank # 1 */ + 0xFB, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFA, 0x36, 0xFF, 0xBC, 0x30, 0x8E, 0x00, 0x05, 0xFB, 0xF0, 0xFF, 0xD9, 0x5B, 0xC8, + 0xFF, 0xD0, 0x9A, 0xBE, 0x00, 0x00, 0x10, 0xA9, 0xFF, 0xF4, 0x1E, 0xB2, 0x00, 0xCE, 0xBB, 0xF7, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x0C, + 0xFF, 0xC2, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0xCF, 0x80, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x14, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x09, 0x23, 0xA1, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x3F, 0x68, 0xB6, 0x79, 0x35, 0x28, 0xBC, 0xC6, 0x7E, 0xD1, 0x6C, + 0x80, 0x00, 0xFF, 0xFF, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB2, 0x6A, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, + 0x00, 0x00, 0x25, 0x4D, 0x00, 0x2F, 0x70, 0x6D, 0x00, 0x00, 0x05, 0xAE, 0x00, 0x0C, 0x02, 0xD0, + /* bank # 2 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x54, 0xFF, 0xEF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x44, 0x00, 0x01, 0x00, 0x05, 0x8B, 0xC1, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0xFF, 0xEF, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* bank # 3 */ + 0xD8, 0xDC, 0xBA, 0xA2, 0xF1, 0xDE, 0xB2, 0xB8, 0xB4, 0xA8, 0x81, 0x91, 0xF7, 0x4A, 0x90, 0x7F, + 0x91, 0x6A, 0xF3, 0xF9, 0xDB, 0xA8, 0xF9, 0xB0, 0xBA, 0xA0, 0x80, 0xF2, 0xCE, 0x81, 0xF3, 0xC2, + 0xF1, 0xC1, 0xF2, 0xC3, 0xF3, 0xCC, 0xA2, 0xB2, 0x80, 0xF1, 0xC6, 0xD8, 0x80, 0xBA, 0xA7, 0xDF, + 0xDF, 0xDF, 0xF2, 0xA7, 0xC3, 0xCB, 0xC5, 0xB6, 0xF0, 0x87, 0xA2, 0x94, 0x24, 0x48, 0x70, 0x3C, + 0x95, 0x40, 0x68, 0x34, 0x58, 0x9B, 0x78, 0xA2, 0xF1, 0x83, 0x92, 0x2D, 0x55, 0x7D, 0xD8, 0xB1, + 0xB4, 0xB8, 0xA1, 0xD0, 0x91, 0x80, 0xF2, 0x70, 0xF3, 0x70, 0xF2, 0x7C, 0x80, 0xA8, 0xF1, 0x01, + 0xB0, 0x98, 0x87, 0xD9, 0x43, 0xD8, 0x86, 0xC9, 0x88, 0xBA, 0xA1, 0xF2, 0x0E, 0xB8, 0x97, 0x80, + 0xF1, 0xA9, 0xDF, 0xDF, 0xDF, 0xAA, 0xDF, 0xDF, 0xDF, 0xF2, 0xAA, 0x4C, 0xCD, 0x6C, 0xA9, 0x0C, + 0xC9, 0x2C, 0x97, 0x97, 0x97, 0x97, 0xF1, 0xA9, 0x89, 0x26, 0x46, 0x66, 0xB0, 0xB4, 0xBA, 0x80, + 0xAC, 0xDE, 0xF2, 0xCA, 0xF1, 0xB2, 0x8C, 0x02, 0xA9, 0xB6, 0x98, 0x00, 0x89, 0x0E, 0x16, 0x1E, + 0xB8, 0xA9, 0xB4, 0x99, 0x2C, 0x54, 0x7C, 0xB0, 0x8A, 0xA8, 0x96, 0x36, 0x56, 0x76, 0xF1, 0xB9, + 0xAF, 0xB4, 0xB0, 0x83, 0xC0, 0xB8, 0xA8, 0x97, 0x11, 0xB1, 0x8F, 0x98, 0xB9, 0xAF, 0xF0, 0x24, + 0x08, 0x44, 0x10, 0x64, 0x18, 0xF1, 0xA3, 0x29, 0x55, 0x7D, 0xAF, 0x83, 0xB5, 0x93, 0xAF, 0xF0, + 0x00, 0x28, 0x50, 0xF1, 0xA3, 0x86, 0x9F, 0x61, 0xA6, 0xDA, 0xDE, 0xDF, 0xD9, 0xFA, 0xA3, 0x86, + 0x96, 0xDB, 0x31, 0xA6, 0xD9, 0xF8, 0xDF, 0xBA, 0xA6, 0x8F, 0xC2, 0xC5, 0xC7, 0xB2, 0x8C, 0xC1, + 0xB8, 0xA2, 0xDF, 0xDF, 0xDF, 0xA3, 0xDF, 0xDF, 0xDF, 0xD8, 0xD8, 0xF1, 0xB8, 0xA8, 0xB2, 0x86, + /* bank # 4 */ + 0xB4, 0x98, 0x0D, 0x35, 0x5D, 0xB8, 0xAA, 0x98, 0xB0, 0x87, 0x2D, 0x35, 0x3D, 0xB2, 0xB6, 0xBA, + 0xAF, 0x8C, 0x96, 0x19, 0x8F, 0x9F, 0xA7, 0x0E, 0x16, 0x1E, 0xB4, 0x9A, 0xB8, 0xAA, 0x87, 0x2C, + 0x54, 0x7C, 0xB9, 0xA3, 0xDE, 0xDF, 0xDF, 0xA3, 0xB1, 0x80, 0xF2, 0xC4, 0xCD, 0xC9, 0xF1, 0xB8, + 0xA9, 0xB4, 0x99, 0x83, 0x0D, 0x35, 0x5D, 0x89, 0xB9, 0xA3, 0x2D, 0x55, 0x7D, 0xB5, 0x93, 0xA3, + 0x0E, 0x16, 0x1E, 0xA9, 0x2C, 0x54, 0x7C, 0xB8, 0xB4, 0xB0, 0xF1, 0x97, 0x83, 0xA8, 0x11, 0x84, + 0xA5, 0x09, 0x98, 0xA3, 0x83, 0xF0, 0xDA, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0xD8, 0xF1, 0xA5, + 0x29, 0x55, 0x7D, 0xA5, 0x85, 0x95, 0x02, 0x1A, 0x2E, 0x3A, 0x56, 0x5A, 0x40, 0x48, 0xF9, 0xF3, + 0xA3, 0xD9, 0xF8, 0xF0, 0x98, 0x83, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0x97, 0x82, 0xA8, 0xF1, + 0x11, 0xF0, 0x98, 0xA2, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0xDA, 0xF3, 0xDE, 0xD8, 0x83, 0xA5, + 0x94, 0x01, 0xD9, 0xA3, 0x02, 0xF1, 0xA2, 0xC3, 0xC5, 0xC7, 0xD8, 0xF1, 0x84, 0x92, 0xA2, 0x4D, + 0xDA, 0x2A, 0xD8, 0x48, 0x69, 0xD9, 0x2A, 0xD8, 0x68, 0x55, 0xDA, 0x32, 0xD8, 0x50, 0x71, 0xD9, + 0x32, 0xD8, 0x70, 0x5D, 0xDA, 0x3A, 0xD8, 0x58, 0x79, 0xD9, 0x3A, 0xD8, 0x78, 0x93, 0xA3, 0x4D, + 0xDA, 0x2A, 0xD8, 0x48, 0x69, 0xD9, 0x2A, 0xD8, 0x68, 0x55, 0xDA, 0x32, 0xD8, 0x50, 0x71, 0xD9, + 0x32, 0xD8, 0x70, 0x5D, 0xDA, 0x3A, 0xD8, 0x58, 0x79, 0xD9, 0x3A, 0xD8, 0x78, 0xA8, 0x8A, 0x9A, + 0xF0, 0x28, 0x50, 0x78, 0x9E, 0xF3, 0x88, 0x18, 0xF1, 0x9F, 0x1D, 0x98, 0xA8, 0xD9, 0x08, 0xD8, + 0xC8, 0x9F, 0x12, 0x9E, 0xF3, 0x15, 0xA8, 0xDA, 0x12, 0x10, 0xD8, 0xF1, 0xAF, 0xC8, 0x97, 0x87, + /* bank # 5 */ + 0x34, 0xB5, 0xB9, 0x94, 0xA4, 0x21, 0xF3, 0xD9, 0x22, 0xD8, 0xF2, 0x2D, 0xF3, 0xD9, 0x2A, 0xD8, + 0xF2, 0x35, 0xF3, 0xD9, 0x32, 0xD8, 0x81, 0xA4, 0x60, 0x60, 0x61, 0xD9, 0x61, 0xD8, 0x6C, 0x68, + 0x69, 0xD9, 0x69, 0xD8, 0x74, 0x70, 0x71, 0xD9, 0x71, 0xD8, 0xB1, 0xA3, 0x84, 0x19, 0x3D, 0x5D, + 0xA3, 0x83, 0x1A, 0x3E, 0x5E, 0x93, 0x10, 0x30, 0x81, 0x10, 0x11, 0xB8, 0xB0, 0xAF, 0x8F, 0x94, + 0xF2, 0xDA, 0x3E, 0xD8, 0xB4, 0x9A, 0xA8, 0x87, 0x29, 0xDA, 0xF8, 0xD8, 0x87, 0x9A, 0x35, 0xDA, + 0xF8, 0xD8, 0x87, 0x9A, 0x3D, 0xDA, 0xF8, 0xD8, 0xB1, 0xB9, 0xA4, 0x98, 0x85, 0x02, 0x2E, 0x56, + 0xA5, 0x81, 0x00, 0x0C, 0x14, 0xA3, 0x97, 0xB0, 0x8A, 0xF1, 0x2D, 0xD9, 0x28, 0xD8, 0x4D, 0xD9, + 0x48, 0xD8, 0x6D, 0xD9, 0x68, 0xD8, 0xB1, 0x84, 0x0D, 0xDA, 0x0E, 0xD8, 0xA3, 0x29, 0x83, 0xDA, + 0x2C, 0x0E, 0xD8, 0xA3, 0x84, 0x49, 0x83, 0xDA, 0x2C, 0x4C, 0x0E, 0xD8, 0xB8, 0xB0, 0xA8, 0x8A, + 0x9A, 0xF5, 0x20, 0xAA, 0xDA, 0xDF, 0xD8, 0xA8, 0x40, 0xAA, 0xD0, 0xDA, 0xDE, 0xD8, 0xA8, 0x60, + 0xAA, 0xDA, 0xD0, 0xDF, 0xD8, 0xF1, 0x97, 0x86, 0xA8, 0x31, 0x9B, 0x06, 0x99, 0x07, 0xAB, 0x97, + 0x28, 0x88, 0x9B, 0xF0, 0x0C, 0x20, 0x14, 0x40, 0xB8, 0xB0, 0xB4, 0xA8, 0x8C, 0x9C, 0xF0, 0x04, + 0x28, 0x51, 0x79, 0x1D, 0x30, 0x14, 0x38, 0xB2, 0x82, 0xAB, 0xD0, 0x98, 0x2C, 0x50, 0x50, 0x78, + 0x78, 0x9B, 0xF1, 0x1A, 0xB0, 0xF0, 0x8A, 0x9C, 0xA8, 0x29, 0x51, 0x79, 0x8B, 0x29, 0x51, 0x79, + 0x8A, 0x24, 0x70, 0x59, 0x8B, 0x20, 0x58, 0x71, 0x8A, 0x44, 0x69, 0x38, 0x8B, 0x39, 0x40, 0x68, + 0x8A, 0x64, 0x48, 0x31, 0x8B, 0x30, 0x49, 0x60, 0xA5, 0x88, 0x20, 0x09, 0x71, 0x58, 0x44, 0x68, + /* bank # 6 */ + 0x11, 0x39, 0x64, 0x49, 0x30, 0x19, 0xF1, 0xAC, 0x00, 0x2C, 0x54, 0x7C, 0xF0, 0x8C, 0xA8, 0x04, + 0x28, 0x50, 0x78, 0xF1, 0x88, 0x97, 0x26, 0xA8, 0x59, 0x98, 0xAC, 0x8C, 0x02, 0x26, 0x46, 0x66, + 0xF0, 0x89, 0x9C, 0xA8, 0x29, 0x51, 0x79, 0x24, 0x70, 0x59, 0x44, 0x69, 0x38, 0x64, 0x48, 0x31, + 0xA9, 0x88, 0x09, 0x20, 0x59, 0x70, 0xAB, 0x11, 0x38, 0x40, 0x69, 0xA8, 0x19, 0x31, 0x48, 0x60, + 0x8C, 0xA8, 0x3C, 0x41, 0x5C, 0x20, 0x7C, 0x00, 0xF1, 0x87, 0x98, 0x19, 0x86, 0xA8, 0x6E, 0x76, + 0x7E, 0xA9, 0x99, 0x88, 0x2D, 0x55, 0x7D, 0x9E, 0xB9, 0xA3, 0x8A, 0x22, 0x8A, 0x6E, 0x8A, 0x56, + 0x8A, 0x5E, 0x9F, 0xB1, 0x83, 0x06, 0x26, 0x46, 0x66, 0x0E, 0x2E, 0x4E, 0x6E, 0x9D, 0xB8, 0xAD, + 0x00, 0x2C, 0x54, 0x7C, 0xF2, 0xB1, 0x8C, 0xB4, 0x99, 0xB9, 0xA3, 0x2D, 0x55, 0x7D, 0x81, 0x91, + 0xAC, 0x38, 0xAD, 0x3A, 0xB5, 0x83, 0x91, 0xAC, 0x2D, 0xD9, 0x28, 0xD8, 0x4D, 0xD9, 0x48, 0xD8, + 0x6D, 0xD9, 0x68, 0xD8, 0x8C, 0x9D, 0xAE, 0x29, 0xD9, 0x04, 0xAE, 0xD8, 0x51, 0xD9, 0x04, 0xAE, + 0xD8, 0x79, 0xD9, 0x04, 0xD8, 0x81, 0xF3, 0x9D, 0xAD, 0x00, 0x8D, 0xAE, 0x19, 0x81, 0xAD, 0xD9, + 0x01, 0xD8, 0xF2, 0xAE, 0xDA, 0x26, 0xD8, 0x8E, 0x91, 0x29, 0x83, 0xA7, 0xD9, 0xAD, 0xAD, 0xAD, + 0xAD, 0xF3, 0x2A, 0xD8, 0xD8, 0xF1, 0xB0, 0xAC, 0x89, 0x91, 0x3E, 0x5E, 0x76, 0xF3, 0xAC, 0x2E, + 0x2E, 0xF1, 0xB1, 0x8C, 0x5A, 0x9C, 0xAC, 0x2C, 0x28, 0x28, 0x28, 0x9C, 0xAC, 0x30, 0x18, 0xA8, + 0x98, 0x81, 0x28, 0x34, 0x3C, 0x97, 0x24, 0xA7, 0x28, 0x34, 0x3C, 0x9C, 0x24, 0xF2, 0xB0, 0x89, + 0xAC, 0x91, 0x2C, 0x4C, 0x6C, 0x8A, 0x9B, 0x2D, 0xD9, 0xD8, 0xD8, 0x51, 0xD9, 0xD8, 0xD8, 0x79, + /* bank # 7 */ + 0xD9, 0xD8, 0xD8, 0xF1, 0x9E, 0x88, 0xA3, 0x31, 0xDA, 0xD8, 0xD8, 0x91, 0x2D, 0xD9, 0x28, 0xD8, + 0x4D, 0xD9, 0x48, 0xD8, 0x6D, 0xD9, 0x68, 0xD8, 0xB1, 0x83, 0x93, 0x35, 0x3D, 0x80, 0x25, 0xDA, + 0xD8, 0xD8, 0x85, 0x69, 0xDA, 0xD8, 0xD8, 0xB4, 0x93, 0x81, 0xA3, 0x28, 0x34, 0x3C, 0xF3, 0xAB, + 0x8B, 0xF8, 0xA3, 0x91, 0xB6, 0x09, 0xB4, 0xD9, 0xAB, 0xDE, 0xFA, 0xB0, 0x87, 0x9C, 0xB9, 0xA3, + 0xDD, 0xF1, 0x20, 0x28, 0x30, 0x38, 0x9A, 0xF1, 0x28, 0x30, 0x38, 0x9D, 0xF1, 0xA3, 0xA3, 0xA3, + 0xA3, 0xF2, 0xA3, 0xB4, 0x90, 0x80, 0xF2, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, + 0xA3, 0xB2, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xB0, 0x87, 0xB5, 0x99, 0xF1, 0x28, 0x30, 0x38, + 0x98, 0xF1, 0xA3, 0xA3, 0xA3, 0xA3, 0x97, 0xA3, 0xA3, 0xA3, 0xA3, 0xF3, 0x9B, 0xA3, 0x30, 0xDC, + 0xB9, 0xA7, 0xF1, 0x26, 0x26, 0x26, 0xFE, 0xD8, 0xFF, }; // thanks to Noah Zerkin for piecing this stuff together! @@ -390,10 +383,10 @@ uint8_t MPU6050::dmpInitialize() { DEBUG_PRINTLN(F("Success! DMP code written and verified.")); // write DMP configuration - DEBUG_PRINTLN(F("Writing DMP configuration to MPU memory banks (")); - DEBUG_PRINT(MPU6050_DMP_CONFIG_SIZE); - DEBUG_PRINTLN(F(" bytes in config def)")); - if (writeProgDMPConfigurationSet(dmpConfig, MPU6050_DMP_CONFIG_SIZE)) { + // DEBUG_PRINTLN(F("Writing DMP configuration to MPU memory banks (")); + // DEBUG_PRINT(MPU6050_DMP_CONFIG_SIZE); + // DEBUG_PRINTLN(F(" bytes in config def)")); + if (true) { DEBUG_PRINTLN(F("Success! DMP configuration written and verified.")); DEBUG_PRINTLN(F("Setting clock source to Z Gyro...")); @@ -433,15 +426,15 @@ uint8_t MPU6050::dmpInitialize() { //setYGyroOffset(0); //setZGyroOffset(0); - DEBUG_PRINTLN(F("Writing final memory update 1/7 (function unknown)...")); - uint8_t dmpUpdate[16], j; - uint16_t pos = 0; - for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); - writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); + // DEBUG_PRINTLN(F("Writing final memory update 1/7 (function unknown)...")); + // uint8_t dmpUpdate[16], j; + // uint16_t pos = 0; + // for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); + // writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); - DEBUG_PRINTLN(F("Writing final memory update 2/7 (function unknown)...")); - for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); - writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); + // DEBUG_PRINTLN(F("Writing final memory update 2/7 (function unknown)...")); + // for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); + // writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); DEBUG_PRINTLN(F("Resetting FIFO...")); resetFIFO(); @@ -478,17 +471,17 @@ uint8_t MPU6050::dmpInitialize() { DEBUG_PRINTLN(F("Resetting DMP...")); resetDMP(); - DEBUG_PRINTLN(F("Writing final memory update 3/7 (function unknown)...")); - for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); - writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); + // DEBUG_PRINTLN(F("Writing final memory update 3/7 (function unknown)...")); + // for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); + // writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); - DEBUG_PRINTLN(F("Writing final memory update 4/7 (function unknown)...")); - for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); - writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); + // DEBUG_PRINTLN(F("Writing final memory update 4/7 (function unknown)...")); + // for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); + // writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); - DEBUG_PRINTLN(F("Writing final memory update 5/7 (function unknown)...")); - for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); - writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); + // DEBUG_PRINTLN(F("Writing final memory update 5/7 (function unknown)...")); + // for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); + // writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); DEBUG_PRINTLN(F("Waiting for FIFO count > 2...")); while ((fifoCount = getFIFOCount()) < 3); @@ -503,9 +496,9 @@ uint8_t MPU6050::dmpInitialize() { DEBUG_PRINTLN(F("Current interrupt status=")); DEBUG_PRINTLNF(getIntStatus(), HEX); - DEBUG_PRINTLN(F("Reading final memory update 6/7 (function unknown)...")); - for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); - readMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); + // DEBUG_PRINTLN(F("Reading final memory update 6/7 (function unknown)...")); + // for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); + // readMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); DEBUG_PRINTLN(F("Waiting for FIFO count > 2...")); while ((fifoCount = getFIFOCount()) < 3); @@ -521,9 +514,9 @@ uint8_t MPU6050::dmpInitialize() { DEBUG_PRINTLN(F("Current interrupt status=")); DEBUG_PRINTLNF(getIntStatus(), HEX); - DEBUG_PRINTLN(F("Writing final memory update 7/7 (function unknown)...")); - for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); - writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); + // DEBUG_PRINTLN(F("Writing final memory update 7/7 (function unknown)...")); + // for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]); + // writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]); DEBUG_PRINTLN(F("DMP is good to go! Finally.")); diff --git a/ESP32_ESP-IDF/main/example.cpp b/ESP32_ESP-IDF/main/example.cpp index befaacc5..49f832c8 100644 --- a/ESP32_ESP-IDF/main/example.cpp +++ b/ESP32_ESP-IDF/main/example.cpp @@ -13,8 +13,8 @@ #include "MPU6050_6Axis_MotionApps20.h" #include "sdkconfig.h" -#define PIN_SDA 22 -#define PIN_CLK 21 +#define PIN_SDA 21 +#define PIN_CLK 22 Quaternion q; // [w, x, y, z] quaternion container VectorFloat gravity; // [x, y, z] gravity vector @@ -78,7 +78,7 @@ void task_display(void*){ //Best result is to match with DMP refresh rate // Its last value in components/MPU6050/MPU6050_6Axis_MotionApps20.h file line 310 // Now its 0x13, which means DMP is refreshed with 10Hz rate - vTaskDelay(100/portTICK_PERIOD_MS); + vTaskDelay(5/portTICK_PERIOD_MS); } vTaskDelete(NULL); From 529b381d5231cff4e9254b572e1b0366af1c367c Mon Sep 17 00:00:00 2001 From: brand17 <36546021+brand17@users.noreply.github.com> Date: Sun, 3 Jul 2022 20:56:14 +0300 Subject: [PATCH 312/335] calibration added --- .gitignore | 4 +- ESP32_ESP-IDF/.vscode/c_cpp_properties.json | 28 + ESP32_ESP-IDF/.vscode/settings.json | 4 + ESP32_ESP-IDF/main/example.cpp | 10 +- ESP32_ESP-IDF/sdkconfig | 1251 ++++++++++++++++--- 5 files changed, 1142 insertions(+), 155 deletions(-) create mode 100644 ESP32_ESP-IDF/.vscode/c_cpp_properties.json create mode 100644 ESP32_ESP-IDF/.vscode/settings.json diff --git a/.gitignore b/.gitignore index 8c1a6502..b377ff6d 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,6 @@ PIC18/MPU6050/Examples/MPU6050_raw.X/build/ /dsPIC30F/I2Cdev/testMCC.X/nbproject/private/ /dsPIC30F/MPU6050/Examples/MPU6050_example.X/nbproject/private/ /dsPIC30F/MPU6050/Examples/MPU6050_example.X/build/default/ -/dsPIC30F/MPU6050/Examples/MPU6050_example.X/dist/default/ \ No newline at end of file +/dsPIC30F/MPU6050/Examples/MPU6050_example.X/dist/default/ +ESP32_ESP-IDF/build/ +ESP32_ESP-IDF/sdkconfig \ No newline at end of file diff --git a/ESP32_ESP-IDF/.vscode/c_cpp_properties.json b/ESP32_ESP-IDF/.vscode/c_cpp_properties.json new file mode 100644 index 00000000..fabd55d9 --- /dev/null +++ b/ESP32_ESP-IDF/.vscode/c_cpp_properties.json @@ -0,0 +1,28 @@ +{ + "configurations": [ + { + "name": "ESP-IDF", + "compilerPath": "C:\\Espressif\\tools\\xtensa-esp32-elf\\esp-2021r2-patch3-8.4.0\\xtensa-esp32-elf\\bin\\xtensa-esp32-elf-gcc.exe", + "cStandard": "c11", + "cppStandard": "c++17", + "includePath": [ + "${config:idf.espIdfPath}/components/**", + "${config:idf.espIdfPathWin}/components/**", + "${config:idf.espAdfPath}/components/**", + "${config:idf.espAdfPathWin}/components/**", + "${workspaceFolder}/**" + ], + "browse": { + "path": [ + "${config:idf.espIdfPath}/components", + "${config:idf.espIdfPathWin}/components", + "${config:idf.espAdfPath}/components/**", + "${config:idf.espAdfPathWin}/components/**", + "${workspaceFolder}" + ], + "limitSymbolsToIncludedHeaders": false + } + } + ], + "version": 4 +} diff --git a/ESP32_ESP-IDF/.vscode/settings.json b/ESP32_ESP-IDF/.vscode/settings.json new file mode 100644 index 00000000..8d2f4595 --- /dev/null +++ b/ESP32_ESP-IDF/.vscode/settings.json @@ -0,0 +1,4 @@ +{ + "idf.flashType": "UART", + "idf.portWin": "COM10" +} \ No newline at end of file diff --git a/ESP32_ESP-IDF/main/example.cpp b/ESP32_ESP-IDF/main/example.cpp index 49f832c8..3407d212 100644 --- a/ESP32_ESP-IDF/main/example.cpp +++ b/ESP32_ESP-IDF/main/example.cpp @@ -43,10 +43,12 @@ void task_display(void*){ mpu.dmpInitialize(); // This need to be setup individually - mpu.setXGyroOffset(220); - mpu.setYGyroOffset(76); - mpu.setZGyroOffset(-85); - mpu.setZAccelOffset(1788); + // mpu.setXGyroOffset(220); + // mpu.setYGyroOffset(76); + // mpu.setZGyroOffset(-85); + // mpu.setZAccelOffset(1788); + mpu.CalibrateAccel(6); + mpu.CalibrateGyro(6); mpu.setDMPEnabled(true); diff --git a/ESP32_ESP-IDF/sdkconfig b/ESP32_ESP-IDF/sdkconfig index b26c6997..12586c85 100644 --- a/ESP32_ESP-IDF/sdkconfig +++ b/ESP32_ESP-IDF/sdkconfig @@ -1,47 +1,89 @@ # -# Automatically generated file; DO NOT EDIT. -# Espressif IoT Development Framework Configuration +# Automatically generated file. DO NOT EDIT. +# Espressif IoT Development Framework (ESP-IDF) Project Configuration # +CONFIG_IDF_CMAKE=y +CONFIG_IDF_TARGET_ARCH_XTENSA=y +CONFIG_IDF_TARGET="esp32" +CONFIG_IDF_TARGET_ESP32=y +CONFIG_IDF_FIRMWARE_CHIP_ID=0x0000 # # SDK tool configuration # -CONFIG_TOOLPREFIX="xtensa-esp32-elf-" -CONFIG_PYTHON="python" +CONFIG_SDK_TOOLPREFIX="xtensa-esp32-elf-" +# CONFIG_SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS is not set +# end of SDK tool configuration + +# +# Build type +# +CONFIG_APP_BUILD_TYPE_APP_2NDBOOT=y +# CONFIG_APP_BUILD_TYPE_ELF_RAM is not set +CONFIG_APP_BUILD_GENERATE_BINARIES=y +CONFIG_APP_BUILD_BOOTLOADER=y +CONFIG_APP_BUILD_USE_FLASH_SECTIONS=y +# end of Build type + +# +# Application manager +# +CONFIG_APP_COMPILE_TIME_DATE=y +# CONFIG_APP_EXCLUDE_PROJECT_VER_VAR is not set +# CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR is not set +# CONFIG_APP_PROJECT_VER_FROM_CONFIG is not set +CONFIG_APP_RETRIEVE_LEN_ELF_SHA=16 +# end of Application manager # # Bootloader config # -# CONFIG_LOG_BOOTLOADER_LEVEL_NONE is not set -# CONFIG_LOG_BOOTLOADER_LEVEL_ERROR is not set -# CONFIG_LOG_BOOTLOADER_LEVEL_WARN is not set -# CONFIG_LOG_BOOTLOADER_LEVEL_INFO is not set -CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG=y -# CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE is not set -CONFIG_LOG_BOOTLOADER_LEVEL=4 +CONFIG_BOOTLOADER_OFFSET_IN_FLASH=0x1000 +CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_DEBUG is not set +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_PERF is not set +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_NONE is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_NONE is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_ERROR is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_WARN is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_INFO is not set +CONFIG_BOOTLOADER_LOG_LEVEL_DEBUG=y +# CONFIG_BOOTLOADER_LOG_LEVEL_VERBOSE is not set +CONFIG_BOOTLOADER_LOG_LEVEL=4 +# CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_8V is not set +CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V=y +# CONFIG_BOOTLOADER_FACTORY_RESET is not set +# CONFIG_BOOTLOADER_APP_TEST is not set +CONFIG_BOOTLOADER_WDT_ENABLE=y +# CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE is not set +CONFIG_BOOTLOADER_WDT_TIME_MS=9000 +# CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE is not set +# CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP is not set +# CONFIG_BOOTLOADER_SKIP_VALIDATE_ON_POWER_ON is not set +# CONFIG_BOOTLOADER_SKIP_VALIDATE_ALWAYS is not set +CONFIG_BOOTLOADER_RESERVE_RTC_SIZE=0 +# CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC is not set +CONFIG_BOOTLOADER_FLASH_XMC_SUPPORT=y +# end of Bootloader config # # Security features # -# CONFIG_SECURE_BOOT_ENABLED is not set -# CONFIG_FLASH_ENCRYPTION_ENABLED is not set +# CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT is not set +# CONFIG_SECURE_BOOT is not set +# CONFIG_SECURE_FLASH_ENC_ENABLED is not set +# end of Security features # # Serial flasher config # -CONFIG_ESPTOOLPY_PORT="com3" -# CONFIG_ESPTOOLPY_BAUD_115200B is not set -# CONFIG_ESPTOOLPY_BAUD_230400B is not set -CONFIG_ESPTOOLPY_BAUD_921600B=y -# CONFIG_ESPTOOLPY_BAUD_2MB is not set -# CONFIG_ESPTOOLPY_BAUD_OTHER is not set CONFIG_ESPTOOLPY_BAUD_OTHER_VAL=115200 -CONFIG_ESPTOOLPY_BAUD=921600 -# CONFIG_ESPTOOLPY_COMPRESSED is not set -# CONFIG_FLASHMODE_QIO is not set -# CONFIG_FLASHMODE_QOUT is not set -CONFIG_FLASHMODE_DIO=y -# CONFIG_FLASHMODE_DOUT is not set +# CONFIG_ESPTOOLPY_NO_STUB is not set +# CONFIG_ESPTOOLPY_FLASHMODE_QIO is not set +# CONFIG_ESPTOOLPY_FLASHMODE_QOUT is not set +CONFIG_ESPTOOLPY_FLASHMODE_DIO=y +# CONFIG_ESPTOOLPY_FLASHMODE_DOUT is not set +CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_STR=y CONFIG_ESPTOOLPY_FLASHMODE="dio" # CONFIG_ESPTOOLPY_FLASHFREQ_80M is not set CONFIG_ESPTOOLPY_FLASHFREQ_40M=y @@ -61,35 +103,54 @@ CONFIG_ESPTOOLPY_BEFORE="default_reset" CONFIG_ESPTOOLPY_AFTER_RESET=y # CONFIG_ESPTOOLPY_AFTER_NORESET is not set CONFIG_ESPTOOLPY_AFTER="hard_reset" -# CONFIG_MONITOR_BAUD_9600B is not set -# CONFIG_MONITOR_BAUD_57600B is not set -CONFIG_MONITOR_BAUD_115200B=y -# CONFIG_MONITOR_BAUD_230400B is not set -# CONFIG_MONITOR_BAUD_921600B is not set -# CONFIG_MONITOR_BAUD_2MB is not set -# CONFIG_MONITOR_BAUD_OTHER is not set -CONFIG_MONITOR_BAUD_OTHER_VAL=115200 -CONFIG_MONITOR_BAUD=115200 +# CONFIG_ESPTOOLPY_MONITOR_BAUD_CONSOLE is not set +# CONFIG_ESPTOOLPY_MONITOR_BAUD_9600B is not set +# CONFIG_ESPTOOLPY_MONITOR_BAUD_57600B is not set +CONFIG_ESPTOOLPY_MONITOR_BAUD_115200B=y +# CONFIG_ESPTOOLPY_MONITOR_BAUD_230400B is not set +# CONFIG_ESPTOOLPY_MONITOR_BAUD_921600B is not set +# CONFIG_ESPTOOLPY_MONITOR_BAUD_2MB is not set +# CONFIG_ESPTOOLPY_MONITOR_BAUD_OTHER is not set +CONFIG_ESPTOOLPY_MONITOR_BAUD_OTHER_VAL=115200 +CONFIG_ESPTOOLPY_MONITOR_BAUD=115200 +# end of Serial flasher config # # Partition Table # CONFIG_PARTITION_TABLE_SINGLE_APP=y +# CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE is not set # CONFIG_PARTITION_TABLE_TWO_OTA is not set # CONFIG_PARTITION_TABLE_CUSTOM is not set CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" -CONFIG_PARTITION_TABLE_CUSTOM_APP_BIN_OFFSET=0x10000 CONFIG_PARTITION_TABLE_FILENAME="partitions_singleapp.csv" -CONFIG_APP_OFFSET=0x10000 +CONFIG_PARTITION_TABLE_OFFSET=0x8000 +CONFIG_PARTITION_TABLE_MD5=y +# end of Partition Table # # Compiler options # -CONFIG_OPTIMIZATION_LEVEL_DEBUG=y -# CONFIG_OPTIMIZATION_LEVEL_RELEASE is not set -CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y -# CONFIG_OPTIMIZATION_ASSERTIONS_SILENT is not set -# CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED is not set +CONFIG_COMPILER_OPTIMIZATION_DEFAULT=y +# CONFIG_COMPILER_OPTIMIZATION_SIZE is not set +# CONFIG_COMPILER_OPTIMIZATION_PERF is not set +# CONFIG_COMPILER_OPTIMIZATION_NONE is not set +CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y +# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT is not set +# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE is not set +CONFIG_COMPILER_OPTIMIZATION_ASSERTION_LEVEL=2 +# CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT is not set +CONFIG_COMPILER_HIDE_PATHS_MACROS=y +# CONFIG_COMPILER_CXX_EXCEPTIONS is not set +# CONFIG_COMPILER_CXX_RTTI is not set +CONFIG_COMPILER_STACK_CHECK_MODE_NONE=y +# CONFIG_COMPILER_STACK_CHECK_MODE_NORM is not set +# CONFIG_COMPILER_STACK_CHECK_MODE_STRONG is not set +# CONFIG_COMPILER_STACK_CHECK_MODE_ALL is not set +# CONFIG_COMPILER_WARN_WRITE_STRINGS is not set +# CONFIG_COMPILER_DISABLE_GCC8_WARNINGS is not set +# CONFIG_COMPILER_DUMP_RTL_FILES is not set +# end of Compiler options # # Component config @@ -98,125 +159,417 @@ CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y # # Application Level Tracing # -# CONFIG_ESP32_APPTRACE_DEST_TRAX is not set -CONFIG_ESP32_APPTRACE_DEST_NONE=y -# CONFIG_ESP32_APPTRACE_ENABLE is not set -CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y +# CONFIG_APPTRACE_DEST_JTAG is not set +CONFIG_APPTRACE_DEST_NONE=y +CONFIG_APPTRACE_LOCK_ENABLE=y +# end of Application Level Tracing + +# +# ESP-ASIO +# +# CONFIG_ASIO_SSL_SUPPORT is not set +# end of ESP-ASIO # -# FreeRTOS SystemView Tracing +# Bluetooth # -# CONFIG_AWS_IOT_SDK is not set # CONFIG_BT_ENABLED is not set -CONFIG_BT_RESERVE_DRAM=0 +# end of Bluetooth + +# +# CoAP Configuration +# +CONFIG_COAP_MBEDTLS_PSK=y +# CONFIG_COAP_MBEDTLS_PKI is not set +# CONFIG_COAP_MBEDTLS_DEBUG is not set +CONFIG_COAP_LOG_DEFAULT_LEVEL=0 +# end of CoAP Configuration + +# +# Driver configurations +# + +# +# ADC configuration +# +# CONFIG_ADC_FORCE_XPD_FSM is not set +CONFIG_ADC_DISABLE_DAC=y +# end of ADC configuration + +# +# MCPWM configuration +# +# CONFIG_MCPWM_ISR_IN_IRAM is not set +# end of MCPWM configuration + +# +# SPI configuration +# +# CONFIG_SPI_MASTER_IN_IRAM is not set +CONFIG_SPI_MASTER_ISR_IN_IRAM=y +# CONFIG_SPI_SLAVE_IN_IRAM is not set +CONFIG_SPI_SLAVE_ISR_IN_IRAM=y +# end of SPI configuration + +# +# TWAI configuration +# +# CONFIG_TWAI_ISR_IN_IRAM is not set +# CONFIG_TWAI_ERRATA_FIX_BUS_OFF_REC is not set +# CONFIG_TWAI_ERRATA_FIX_TX_INTR_LOST is not set +# CONFIG_TWAI_ERRATA_FIX_RX_FRAME_INVALID is not set +# CONFIG_TWAI_ERRATA_FIX_RX_FIFO_CORRUPT is not set +# end of TWAI configuration + +# +# UART configuration +# +# CONFIG_UART_ISR_IN_IRAM is not set +# end of UART configuration + +# +# RTCIO configuration +# +# CONFIG_RTCIO_SUPPORT_RTC_GPIO_DESC is not set +# end of RTCIO configuration + +# +# GPIO Configuration +# +# CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL is not set +# end of GPIO Configuration + +# +# GDMA Configuration +# +# CONFIG_GDMA_CTRL_FUNC_IN_IRAM is not set +# CONFIG_GDMA_ISR_IRAM_SAFE is not set +# end of GDMA Configuration +# end of Driver configurations + +# +# eFuse Bit Manager +# +# CONFIG_EFUSE_CUSTOM_TABLE is not set +# CONFIG_EFUSE_VIRTUAL is not set +# CONFIG_EFUSE_CODE_SCHEME_COMPAT_NONE is not set +CONFIG_EFUSE_CODE_SCHEME_COMPAT_3_4=y +# CONFIG_EFUSE_CODE_SCHEME_COMPAT_REPEAT is not set +CONFIG_EFUSE_MAX_BLK_LEN=192 +# end of eFuse Bit Manager + +# +# ESP-TLS +# +CONFIG_ESP_TLS_USING_MBEDTLS=y +# CONFIG_ESP_TLS_USE_SECURE_ELEMENT is not set +# CONFIG_ESP_TLS_SERVER is not set +# CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS is not set +# CONFIG_ESP_TLS_PSK_VERIFICATION is not set +# CONFIG_ESP_TLS_INSECURE is not set +# end of ESP-TLS # # ESP32-specific # +CONFIG_ESP32_REV_MIN_0=y +# CONFIG_ESP32_REV_MIN_1 is not set +# CONFIG_ESP32_REV_MIN_2 is not set +# CONFIG_ESP32_REV_MIN_3 is not set +CONFIG_ESP32_REV_MIN=0 # CONFIG_ESP32_DEFAULT_CPU_FREQ_80 is not set # CONFIG_ESP32_DEFAULT_CPU_FREQ_160 is not set CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=240 -# CONFIG_MEMMAP_SMP is not set -# CONFIG_MEMMAP_TRACEMEM is not set -# CONFIG_MEMMAP_TRACEMEM_TWOBANKS is not set +# CONFIG_ESP32_SPIRAM_SUPPORT is not set # CONFIG_ESP32_TRAX is not set -CONFIG_TRACEMEM_RESERVE_DRAM=0x0 -# CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH is not set -# CONFIG_ESP32_ENABLE_COREDUMP_TO_UART is not set -CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE=y -# CONFIG_ESP32_ENABLE_COREDUMP is not set -# CONFIG_TWO_UNIVERSAL_MAC_ADDRESS is not set -CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS=y -CONFIG_NUMBER_OF_UNIVERSAL_MAC_ADDRESS=4 -CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32 -CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=4096 -CONFIG_MAIN_TASK_STACK_SIZE=4096 -CONFIG_IPC_TASK_STACK_SIZE=1024 -CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF=y -# CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF is not set -# CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR is not set -# CONFIG_NEWLIB_STDIN_LINE_ENDING_CRLF is not set -# CONFIG_NEWLIB_STDIN_LINE_ENDING_LF is not set -CONFIG_NEWLIB_STDIN_LINE_ENDING_CR=y -# CONFIG_NEWLIB_NANO_FORMAT is not set -CONFIG_CONSOLE_UART_DEFAULT=y -# CONFIG_CONSOLE_UART_CUSTOM is not set -# CONFIG_CONSOLE_UART_NONE is not set -CONFIG_CONSOLE_UART_NUM=0 -CONFIG_CONSOLE_UART_BAUDRATE=115200 -# CONFIG_ULP_COPROC_ENABLED is not set -CONFIG_ULP_COPROC_RESERVE_MEM=0 -# CONFIG_ESP32_PANIC_PRINT_HALT is not set -# CONFIG_ESP32_PANIC_PRINT_REBOOT is not set -# CONFIG_ESP32_PANIC_SILENT_REBOOT is not set -CONFIG_ESP32_PANIC_GDBSTUB=y +CONFIG_ESP32_TRACEMEM_RESERVE_DRAM=0x0 +# CONFIG_ESP32_ULP_COPROC_ENABLED is not set +CONFIG_ESP32_ULP_COPROC_RESERVE_MEM=0 CONFIG_ESP32_DEBUG_OCDAWARE=y -CONFIG_INT_WDT=y -CONFIG_INT_WDT_TIMEOUT_MS=300 -CONFIG_TASK_WDT=y -# CONFIG_TASK_WDT_PANIC is not set -CONFIG_TASK_WDT_TIMEOUT_S=5 -CONFIG_TASK_WDT_CHECK_IDLE_TASK=y -CONFIG_BROWNOUT_DET=y -CONFIG_BROWNOUT_DET_LVL_SEL_0=y -# CONFIG_BROWNOUT_DET_LVL_SEL_1 is not set -# CONFIG_BROWNOUT_DET_LVL_SEL_2 is not set -# CONFIG_BROWNOUT_DET_LVL_SEL_3 is not set -# CONFIG_BROWNOUT_DET_LVL_SEL_4 is not set -# CONFIG_BROWNOUT_DET_LVL_SEL_5 is not set -# CONFIG_BROWNOUT_DET_LVL_SEL_6 is not set -# CONFIG_BROWNOUT_DET_LVL_SEL_7 is not set -CONFIG_BROWNOUT_DET_LVL=0 -# CONFIG_ESP32_TIME_SYSCALL_USE_RTC is not set +CONFIG_ESP32_BROWNOUT_DET=y +CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_0=y +# CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_1 is not set +# CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_2 is not set +# CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_3 is not set +# CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_4 is not set +# CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_5 is not set +# CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_6 is not set +# CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_7 is not set +CONFIG_ESP32_BROWNOUT_DET_LVL=0 CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1=y +# CONFIG_ESP32_TIME_SYSCALL_USE_RTC is not set # CONFIG_ESP32_TIME_SYSCALL_USE_FRC1 is not set # CONFIG_ESP32_TIME_SYSCALL_USE_NONE is not set -CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC=y -# CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL is not set +CONFIG_ESP32_RTC_CLK_SRC_INT_RC=y +# CONFIG_ESP32_RTC_CLK_SRC_EXT_CRYS is not set +# CONFIG_ESP32_RTC_CLK_SRC_EXT_OSC is not set +# CONFIG_ESP32_RTC_CLK_SRC_INT_8MD256 is not set CONFIG_ESP32_RTC_CLK_CAL_CYCLES=1024 CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY=2000 # CONFIG_ESP32_XTAL_FREQ_40 is not set # CONFIG_ESP32_XTAL_FREQ_26 is not set CONFIG_ESP32_XTAL_FREQ_AUTO=y CONFIG_ESP32_XTAL_FREQ=0 -# CONFIG_NO_BLOBS is not set +# CONFIG_ESP32_DISABLE_BASIC_ROM_CONSOLE is not set +# CONFIG_ESP32_NO_BLOBS is not set +# CONFIG_ESP32_COMPATIBLE_PRE_V2_1_BOOTLOADERS is not set +# CONFIG_ESP32_COMPATIBLE_PRE_V3_1_BOOTLOADERS is not set +# CONFIG_ESP32_RTCDATA_IN_FAST_MEM is not set +# CONFIG_ESP32_USE_FIXED_STATIC_RAM_SIZE is not set +CONFIG_ESP32_DPORT_DIS_INTERRUPT_LVL=5 +# CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY is not set +# end of ESP32-specific + +# +# ADC-Calibration +# +CONFIG_ADC_CAL_EFUSE_TP_ENABLE=y +CONFIG_ADC_CAL_EFUSE_VREF_ENABLE=y +CONFIG_ADC_CAL_LUT_ENABLE=y +# end of ADC-Calibration + +# +# Common ESP-related +# +CONFIG_ESP_ERR_TO_NAME_LOOKUP=y +# end of Common ESP-related + +# +# Ethernet +# +CONFIG_ETH_ENABLED=y +CONFIG_ETH_USE_ESP32_EMAC=y +CONFIG_ETH_PHY_INTERFACE_RMII=y +CONFIG_ETH_RMII_CLK_INPUT=y +# CONFIG_ETH_RMII_CLK_OUTPUT is not set +CONFIG_ETH_RMII_CLK_IN_GPIO=0 +CONFIG_ETH_DMA_BUFFER_SIZE=512 +CONFIG_ETH_DMA_RX_BUFFER_NUM=10 +CONFIG_ETH_DMA_TX_BUFFER_NUM=10 +CONFIG_ETH_USE_SPI_ETHERNET=y +# CONFIG_ETH_SPI_ETHERNET_DM9051 is not set +# CONFIG_ETH_SPI_ETHERNET_W5500 is not set +# CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL is not set +# CONFIG_ETH_USE_OPENETH is not set +# end of Ethernet + +# +# Event Loop Library +# +# CONFIG_ESP_EVENT_LOOP_PROFILING is not set +CONFIG_ESP_EVENT_POST_FROM_ISR=y +CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR=y +# end of Event Loop Library + +# +# GDB Stub +# +CONFIG_ESP_GDBSTUB_ENABLED=y +CONFIG_ESP_GDBSTUB_SUPPORT_TASKS=y +CONFIG_ESP_GDBSTUB_MAX_TASKS=32 +# end of GDB Stub + +# +# ESP HTTP client +# +CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y +# CONFIG_ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH is not set +CONFIG_ESP_HTTP_CLIENT_ENABLE_DIGEST_AUTH=y +# end of ESP HTTP client + +# +# HTTP Server +# +CONFIG_HTTPD_MAX_REQ_HDR_LEN=512 +CONFIG_HTTPD_MAX_URI_LEN=512 +CONFIG_HTTPD_ERR_RESP_NO_DELAY=y +CONFIG_HTTPD_PURGE_BUF_LEN=32 +# CONFIG_HTTPD_LOG_PURGE_DATA is not set +# CONFIG_HTTPD_WS_SUPPORT is not set +# end of HTTP Server + +# +# ESP HTTPS OTA +# +# CONFIG_OTA_ALLOW_HTTP is not set +# end of ESP HTTPS OTA + +# +# ESP HTTPS server +# +# CONFIG_ESP_HTTPS_SERVER_ENABLE is not set +# end of ESP HTTPS server + +# +# Hardware Settings +# + +# +# MAC Config +# +CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_STA=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_AP=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_BT=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_ETH=y +# CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES_TWO is not set +CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES_FOUR=y +CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES=4 +# end of MAC Config + +# +# Sleep Config +# +CONFIG_ESP_SLEEP_POWER_DOWN_FLASH=y +CONFIG_ESP_SLEEP_RTC_BUS_ISO_WORKAROUND=y +# CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND is not set +# CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND is not set +# end of Sleep Config + +# +# RTC Clock Config +# +# end of RTC Clock Config +# end of Hardware Settings + +# +# IPC (Inter-Processor Call) +# +CONFIG_ESP_IPC_TASK_STACK_SIZE=1024 +# end of IPC (Inter-Processor Call) + +# +# LCD and Touch Panel +# + +# +# LCD Peripheral Configuration +# +CONFIG_LCD_PANEL_IO_FORMAT_BUF_SIZE=32 +# end of LCD Peripheral Configuration +# end of LCD and Touch Panel + +# +# ESP NETIF Adapter +# +CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL=120 +CONFIG_ESP_NETIF_TCPIP_LWIP=y +# CONFIG_ESP_NETIF_LOOPBACK is not set +CONFIG_ESP_NETIF_TCPIP_ADAPTER_COMPATIBLE_LAYER=y +# end of ESP NETIF Adapter + +# +# PHY +# +CONFIG_ESP_PHY_CALIBRATION_AND_DATA_STORAGE=y +# CONFIG_ESP_PHY_INIT_DATA_IN_PARTITION is not set +CONFIG_ESP_PHY_MAX_WIFI_TX_POWER=20 +CONFIG_ESP_PHY_MAX_TX_POWER=20 +CONFIG_ESP_PHY_REDUCE_TX_POWER=y +# end of PHY + +# +# Power Management +# +# CONFIG_PM_ENABLE is not set +# end of Power Management + +# +# ESP System Settings +# +# CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT is not set +# CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT is not set +# CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT is not set +CONFIG_ESP_SYSTEM_PANIC_GDBSTUB=y +# CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME is not set +CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE=y +CONFIG_ESP_SYSTEM_RTC_FAST_MEM_AS_HEAP_DEPCHECK=y +CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP=y + +# +# Memory protection +# +# end of Memory protection + +CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE=32 +CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=4096 +CONFIG_ESP_MAIN_TASK_STACK_SIZE=4096 +CONFIG_ESP_MAIN_TASK_AFFINITY_CPU0=y +# CONFIG_ESP_MAIN_TASK_AFFINITY_NO_AFFINITY is not set +CONFIG_ESP_MAIN_TASK_AFFINITY=0x0 +CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE=2048 +CONFIG_ESP_CONSOLE_UART_DEFAULT=y +# CONFIG_ESP_CONSOLE_UART_CUSTOM is not set +# CONFIG_ESP_CONSOLE_NONE is not set +CONFIG_ESP_CONSOLE_UART=y +CONFIG_ESP_CONSOLE_MULTIPLE_UART=y +CONFIG_ESP_CONSOLE_UART_NUM=0 +CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200 +CONFIG_ESP_INT_WDT=y +CONFIG_ESP_INT_WDT_TIMEOUT_MS=300 +CONFIG_ESP_TASK_WDT=y +# CONFIG_ESP_TASK_WDT_PANIC is not set +CONFIG_ESP_TASK_WDT_TIMEOUT_S=5 +CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0=y +# CONFIG_ESP_PANIC_HANDLER_IRAM is not set +# CONFIG_ESP_DEBUG_STUBS_ENABLE is not set +# CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_5 is not set +CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_4=y +# end of ESP System Settings + +# +# High resolution timer (esp_timer) +# +# CONFIG_ESP_TIMER_PROFILING is not set +CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER=y +CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER=y +CONFIG_ESP_TIMER_TASK_STACK_SIZE=3584 +CONFIG_ESP_TIMER_INTERRUPT_LEVEL=1 +# CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD is not set +# CONFIG_ESP_TIMER_IMPL_FRC2 is not set +CONFIG_ESP_TIMER_IMPL_TG0_LAC=y +# end of High resolution timer (esp_timer) # # Wi-Fi # +CONFIG_ESP32_WIFI_ENABLED=y CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=10 CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=32 # CONFIG_ESP32_WIFI_STATIC_TX_BUFFER is not set CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER=y CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=1 CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=32 -CONFIG_ESP32_WIFI_AMPDU_ENABLED=y +# CONFIG_ESP32_WIFI_CSI_ENABLED is not set +CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y CONFIG_ESP32_WIFI_TX_BA_WIN=6 +CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y CONFIG_ESP32_WIFI_RX_BA_WIN=6 CONFIG_ESP32_WIFI_NVS_ENABLED=y +CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN=752 +CONFIG_ESP32_WIFI_MGMT_SBUF_NUM=32 +CONFIG_ESP32_WIFI_IRAM_OPT=y +CONFIG_ESP32_WIFI_RX_IRAM_OPT=y +CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE=y +# CONFIG_ESP_WIFI_SLP_IRAM_OPT is not set +# CONFIG_ESP_WIFI_STA_DISCONNECTED_PM_ENABLE is not set +# CONFIG_ESP_WIFI_GMAC_SUPPORT is not set +CONFIG_ESP_WIFI_SOFTAP_SUPPORT=y +# end of Wi-Fi # -# PHY +# Core dump # -CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE=y -# CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION is not set -CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER=20 -CONFIG_ESP32_PHY_MAX_TX_POWER=20 - -# -# ETHERNET -# -CONFIG_DMA_RX_BUF_NUM=10 -CONFIG_DMA_TX_BUF_NUM=10 -# CONFIG_EMAC_L2_TO_L3_RX_BUF_MODE is not set -CONFIG_EMAC_TASK_PRIORITY=20 +# CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH is not set +# CONFIG_ESP_COREDUMP_ENABLE_TO_UART is not set +CONFIG_ESP_COREDUMP_ENABLE_TO_NONE=y +# end of Core dump # # FAT Filesystem support # -CONFIG_FATFS_CODEPAGE_ASCII=y -# CONFIG_FATFS_CODEPAGE_437 is not set +# CONFIG_FATFS_CODEPAGE_DYNAMIC is not set +CONFIG_FATFS_CODEPAGE_437=y # CONFIG_FATFS_CODEPAGE_720 is not set # CONFIG_FATFS_CODEPAGE_737 is not set # CONFIG_FATFS_CODEPAGE_771 is not set @@ -237,36 +590,124 @@ CONFIG_FATFS_CODEPAGE_ASCII=y # CONFIG_FATFS_CODEPAGE_936 is not set # CONFIG_FATFS_CODEPAGE_949 is not set # CONFIG_FATFS_CODEPAGE_950 is not set -CONFIG_FATFS_CODEPAGE=1 -CONFIG_FATFS_MAX_LFN=255 +CONFIG_FATFS_CODEPAGE=437 +CONFIG_FATFS_LFN_NONE=y +# CONFIG_FATFS_LFN_HEAP is not set +# CONFIG_FATFS_LFN_STACK is not set +CONFIG_FATFS_FS_LOCK=0 +CONFIG_FATFS_TIMEOUT_MS=10000 +CONFIG_FATFS_PER_FILE_CACHE=y +# CONFIG_FATFS_USE_FASTSEEK is not set +# end of FAT Filesystem support + +# +# Modbus configuration +# +CONFIG_FMB_COMM_MODE_TCP_EN=y +CONFIG_FMB_TCP_PORT_DEFAULT=502 +CONFIG_FMB_TCP_PORT_MAX_CONN=5 +CONFIG_FMB_TCP_CONNECTION_TOUT_SEC=20 +CONFIG_FMB_COMM_MODE_RTU_EN=y +CONFIG_FMB_COMM_MODE_ASCII_EN=y +CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND=150 +CONFIG_FMB_MASTER_DELAY_MS_CONVERT=200 +CONFIG_FMB_QUEUE_LENGTH=20 +CONFIG_FMB_PORT_TASK_STACK_SIZE=4096 +CONFIG_FMB_SERIAL_BUF_SIZE=256 +CONFIG_FMB_SERIAL_ASCII_BITS_PER_SYMB=8 +CONFIG_FMB_SERIAL_ASCII_TIMEOUT_RESPOND_MS=1000 +CONFIG_FMB_PORT_TASK_PRIO=10 +CONFIG_FMB_PORT_TASK_AFFINITY=0x7FFFFFFF +CONFIG_FMB_CONTROLLER_SLAVE_ID_SUPPORT=y +CONFIG_FMB_CONTROLLER_SLAVE_ID=0x00112233 +CONFIG_FMB_CONTROLLER_NOTIFY_TIMEOUT=20 +CONFIG_FMB_CONTROLLER_NOTIFY_QUEUE_SIZE=20 +CONFIG_FMB_CONTROLLER_STACK_SIZE=4096 +CONFIG_FMB_EVENT_QUEUE_TIMEOUT=20 +# CONFIG_FMB_TIMER_PORT_ENABLED is not set +CONFIG_FMB_TIMER_GROUP=0 +CONFIG_FMB_TIMER_INDEX=0 +CONFIG_FMB_MASTER_TIMER_GROUP=0 +CONFIG_FMB_MASTER_TIMER_INDEX=0 +# CONFIG_FMB_TIMER_ISR_IN_IRAM is not set +# end of Modbus configuration # # FreeRTOS # CONFIG_FREERTOS_UNICORE=y +CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF +CONFIG_FREERTOS_TICK_SUPPORT_CORETIMER=y CONFIG_FREERTOS_CORETIMER_0=y # CONFIG_FREERTOS_CORETIMER_1 is not set +CONFIG_FREERTOS_SYSTICK_USES_CCOUNT=y +CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y # CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE is not set # CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL is not set CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY=y # CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK is not set +CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=1 # CONFIG_FREERTOS_ASSERT_FAIL_ABORT is not set CONFIG_FREERTOS_ASSERT_FAIL_PRINT_CONTINUE=y # CONFIG_FREERTOS_ASSERT_DISABLE is not set -# CONFIG_FREERTOS_BREAK_ON_SCHEDULER_START_JTAG is not set -# CONFIG_ENABLE_MEMORY_DEBUG is not set CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1024 CONFIG_FREERTOS_ISR_STACKSIZE=1536 # CONFIG_FREERTOS_LEGACY_HOOKS is not set CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16 -# CONFIG_SUPPORT_STATIC_ALLOCATION is not set -CONFIG_TIMER_TASK_PRIORITY=1 -CONFIG_TIMER_TASK_STACK_DEPTH=2048 -CONFIG_TIMER_QUEUE_LENGTH=10 -# CONFIG_FREERTOS_DEBUG_INTERNALS is not set +CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y +# CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP is not set +CONFIG_FREERTOS_TIMER_TASK_PRIORITY=1 +CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=2048 +CONFIG_FREERTOS_TIMER_QUEUE_LENGTH=10 +CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=0 +# CONFIG_FREERTOS_USE_TRACE_FACILITY is not set +# CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS is not set +CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=y +CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER=y +# CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE is not set +# CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH is not set +CONFIG_FREERTOS_DEBUG_OCDAWARE=y +# CONFIG_FREERTOS_FPU_IN_ISR is not set +CONFIG_FREERTOS_ENABLE_TASK_SNAPSHOT=y +# CONFIG_FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH is not set +# end of FreeRTOS + +# +# Hardware Abstraction Layer (HAL) and Low Level (LL) +# +CONFIG_HAL_ASSERTION_EQUALS_SYSTEM=y +# CONFIG_HAL_ASSERTION_DISABLE is not set +# CONFIG_HAL_ASSERTION_SILIENT is not set +# CONFIG_HAL_ASSERTION_ENABLE is not set +CONFIG_HAL_DEFAULT_ASSERTION_LEVEL=2 +# end of Hardware Abstraction Layer (HAL) and Low Level (LL) + +# +# Heap memory debugging +# +CONFIG_HEAP_POISONING_DISABLED=y +# CONFIG_HEAP_POISONING_LIGHT is not set +# CONFIG_HEAP_POISONING_COMPREHENSIVE is not set +CONFIG_HEAP_TRACING_OFF=y +# CONFIG_HEAP_TRACING_STANDALONE is not set +# CONFIG_HEAP_TRACING_TOHOST is not set +# CONFIG_HEAP_ABORT_WHEN_ALLOCATION_FAILS is not set +# end of Heap memory debugging + +# +# jsmn +# +# CONFIG_JSMN_PARENT_LINKS is not set +# CONFIG_JSMN_STRICT is not set +# end of jsmn + +# +# libsodium +# +# end of libsodium # # Log output @@ -278,59 +719,198 @@ CONFIG_LOG_DEFAULT_LEVEL_INFO=y # CONFIG_LOG_DEFAULT_LEVEL_DEBUG is not set # CONFIG_LOG_DEFAULT_LEVEL_VERBOSE is not set CONFIG_LOG_DEFAULT_LEVEL=3 +CONFIG_LOG_MAXIMUM_EQUALS_DEFAULT=y +# CONFIG_LOG_MAXIMUM_LEVEL_DEBUG is not set +# CONFIG_LOG_MAXIMUM_LEVEL_VERBOSE is not set +CONFIG_LOG_MAXIMUM_LEVEL=3 CONFIG_LOG_COLORS=y +CONFIG_LOG_TIMESTAMP_SOURCE_RTOS=y +# CONFIG_LOG_TIMESTAMP_SOURCE_SYSTEM is not set +# end of Log output # # LWIP # -# CONFIG_L2_TO_L3_COPY is not set +CONFIG_LWIP_LOCAL_HOSTNAME="espressif" +# CONFIG_LWIP_NETIF_API is not set +# CONFIG_LWIP_TCPIP_CORE_LOCKING is not set +CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y +# CONFIG_LWIP_L2_TO_L3_COPY is not set +# CONFIG_LWIP_IRAM_OPTIMIZATION is not set +CONFIG_LWIP_TIMERS_ONDEMAND=y CONFIG_LWIP_MAX_SOCKETS=10 -CONFIG_LWIP_THREAD_LOCAL_STORAGE_INDEX=0 +# CONFIG_LWIP_USE_ONLY_LWIP_SELECT is not set +# CONFIG_LWIP_SO_LINGER is not set # CONFIG_LWIP_SO_REUSE is not set # CONFIG_LWIP_SO_RCVBUF is not set -CONFIG_LWIP_DHCP_MAX_NTP_SERVERS=1 -# CONFIG_LWIP_IP_FRAG is not set -# CONFIG_LWIP_IP_REASSEMBLY is not set +# CONFIG_LWIP_NETBUF_RECVINFO is not set +CONFIG_LWIP_IP4_FRAG=y +CONFIG_LWIP_IP6_FRAG=y +# CONFIG_LWIP_IP4_REASSEMBLY is not set +# CONFIG_LWIP_IP6_REASSEMBLY is not set +# CONFIG_LWIP_IP_FORWARD is not set +# CONFIG_LWIP_STATS is not set +# CONFIG_LWIP_ETHARP_TRUST_IP_MAC is not set +CONFIG_LWIP_ESP_GRATUITOUS_ARP=y +CONFIG_LWIP_GARP_TMR_INTERVAL=60 +CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=32 +CONFIG_LWIP_DHCP_DOES_ARP_CHECK=y +# CONFIG_LWIP_DHCP_DISABLE_CLIENT_ID is not set +CONFIG_LWIP_DHCP_DISABLE_VENDOR_CLASS_ID=y +# CONFIG_LWIP_DHCP_RESTORE_LAST_IP is not set +CONFIG_LWIP_DHCP_OPTIONS_LEN=68 + +# +# DHCP server +# +CONFIG_LWIP_DHCPS=y +CONFIG_LWIP_DHCPS_LEASE_UNIT=60 +CONFIG_LWIP_DHCPS_MAX_STATION_NUM=8 +# end of DHCP server + +# CONFIG_LWIP_AUTOIP is not set +CONFIG_LWIP_IPV6=y +# CONFIG_LWIP_IPV6_AUTOCONFIG is not set +CONFIG_LWIP_IPV6_NUM_ADDRESSES=3 +# CONFIG_LWIP_IPV6_FORWARD is not set +# CONFIG_LWIP_NETIF_STATUS_CALLBACK is not set +CONFIG_LWIP_NETIF_LOOPBACK=y +CONFIG_LWIP_LOOPBACK_MAX_PBUFS=8 # # TCP # -CONFIG_TCP_MAXRTX=12 -CONFIG_TCP_SYNMAXRTX=6 -CONFIG_TCP_MSS=1436 -CONFIG_TCP_SND_BUF_DEFAULT=5744 -CONFIG_TCP_WND_DEFAULT=5744 -CONFIG_TCP_RECVMBOX_SIZE=6 -CONFIG_TCP_QUEUE_OOSEQ=y -CONFIG_TCP_OVERSIZE_MSS=y -# CONFIG_TCP_OVERSIZE_QUARTER_MSS is not set -# CONFIG_TCP_OVERSIZE_DISABLE is not set +CONFIG_LWIP_MAX_ACTIVE_TCP=16 +CONFIG_LWIP_MAX_LISTENING_TCP=16 +CONFIG_LWIP_TCP_HIGH_SPEED_RETRANSMISSION=y +CONFIG_LWIP_TCP_MAXRTX=12 +CONFIG_LWIP_TCP_SYNMAXRTX=6 +CONFIG_LWIP_TCP_MSS=1436 +CONFIG_LWIP_TCP_TMR_INTERVAL=250 +CONFIG_LWIP_TCP_MSL=60000 +CONFIG_LWIP_TCP_SND_BUF_DEFAULT=5744 +CONFIG_LWIP_TCP_WND_DEFAULT=5744 +CONFIG_LWIP_TCP_RECVMBOX_SIZE=6 +CONFIG_LWIP_TCP_QUEUE_OOSEQ=y +# CONFIG_LWIP_TCP_SACK_OUT is not set +# CONFIG_LWIP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES is not set +CONFIG_LWIP_TCP_OVERSIZE_MSS=y +# CONFIG_LWIP_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_LWIP_TCP_OVERSIZE_DISABLE is not set +CONFIG_LWIP_TCP_RTO_TIME=1500 +# end of TCP # # UDP # -CONFIG_UDP_RECVMBOX_SIZE=6 -CONFIG_LWIP_DHCP_DOES_ARP_CHECK=y -CONFIG_TCPIP_TASK_STACK_SIZE=2560 -# CONFIG_PPP_SUPPORT is not set +CONFIG_LWIP_MAX_UDP_PCBS=16 +CONFIG_LWIP_UDP_RECVMBOX_SIZE=6 +# end of UDP + +# +# Checksums +# +# CONFIG_LWIP_CHECKSUM_CHECK_IP is not set +# CONFIG_LWIP_CHECKSUM_CHECK_UDP is not set +CONFIG_LWIP_CHECKSUM_CHECK_ICMP=y +# end of Checksums + +CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=2560 +CONFIG_LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY=y +# CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU0 is not set +CONFIG_LWIP_TCPIP_TASK_AFFINITY=0x7FFFFFFF +# CONFIG_LWIP_PPP_SUPPORT is not set +CONFIG_LWIP_IPV6_MEMP_NUM_ND6_QUEUE=3 +CONFIG_LWIP_IPV6_ND6_NUM_NEIGHBORS=5 +# CONFIG_LWIP_SLIP_SUPPORT is not set # # ICMP # +CONFIG_LWIP_ICMP=y # CONFIG_LWIP_MULTICAST_PING is not set # CONFIG_LWIP_BROADCAST_PING is not set +# end of ICMP + +# +# LWIP RAW API +# +CONFIG_LWIP_MAX_RAW_PCBS=16 +# end of LWIP RAW API + +# +# SNTP +# +CONFIG_LWIP_SNTP_MAX_SERVERS=1 +# CONFIG_LWIP_DHCP_GET_NTP_SRV is not set +CONFIG_LWIP_SNTP_UPDATE_DELAY=3600000 +# end of SNTP + +CONFIG_LWIP_ESP_LWIP_ASSERT=y + +# +# Hooks +# +# CONFIG_LWIP_HOOK_TCP_ISN_NONE is not set +CONFIG_LWIP_HOOK_TCP_ISN_DEFAULT=y +# CONFIG_LWIP_HOOK_TCP_ISN_CUSTOM is not set +CONFIG_LWIP_HOOK_IP6_ROUTE_NONE=y +# CONFIG_LWIP_HOOK_IP6_ROUTE_DEFAULT is not set +# CONFIG_LWIP_HOOK_IP6_ROUTE_CUSTOM is not set +CONFIG_LWIP_HOOK_ND6_GET_GW_NONE=y +# CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT is not set +# CONFIG_LWIP_HOOK_ND6_GET_GW_CUSTOM is not set +CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_NONE=y +# CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_DEFAULT is not set +# CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_CUSTOM is not set +# end of Hooks + +# CONFIG_LWIP_DEBUG is not set +# end of LWIP # # mbedTLS # -CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=16384 +CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y +# CONFIG_MBEDTLS_DEFAULT_MEM_ALLOC is not set +# CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC is not set +CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y +CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN=16384 +CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=4096 +# CONFIG_MBEDTLS_DYNAMIC_BUFFER is not set # CONFIG_MBEDTLS_DEBUG is not set + +# +# mbedTLS v2.28.x related +# +# CONFIG_MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH is not set +# CONFIG_MBEDTLS_X509_TRUSTED_CERT_CALLBACK is not set +# CONFIG_MBEDTLS_SSL_CONTEXT_SERIALIZATION is not set +CONFIG_MBEDTLS_SSL_KEEP_PEER_CERTIFICATE=y +# end of mbedTLS v2.28.x related + +# +# Certificate Bundle +# +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=y +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=y +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN is not set +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_NONE is not set +# CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE is not set +# end of Certificate Bundle + +# CONFIG_MBEDTLS_ECP_RESTARTABLE is not set +# CONFIG_MBEDTLS_CMAC_C is not set CONFIG_MBEDTLS_HARDWARE_AES=y CONFIG_MBEDTLS_HARDWARE_MPI=y -CONFIG_MBEDTLS_MPI_USE_INTERRUPT=y CONFIG_MBEDTLS_HARDWARE_SHA=y +CONFIG_MBEDTLS_ROM_MD5=y +# CONFIG_MBEDTLS_ATCA_HW_ECDSA_SIGN is not set +# CONFIG_MBEDTLS_ATCA_HW_ECDSA_VERIFY is not set CONFIG_MBEDTLS_HAVE_TIME=y # CONFIG_MBEDTLS_HAVE_TIME_DATE is not set +CONFIG_MBEDTLS_ECDSA_DETERMINISTIC=y +CONFIG_MBEDTLS_SHA512_C=y CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT=y # CONFIG_MBEDTLS_TLS_SERVER_ONLY is not set # CONFIG_MBEDTLS_TLS_CLIENT_ONLY is not set @@ -350,14 +930,20 @@ CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA=y CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA=y CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA=y CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA=y +# end of TLS Key Exchange Methods + CONFIG_MBEDTLS_SSL_RENEGOTIATION=y # CONFIG_MBEDTLS_SSL_PROTO_SSL3 is not set CONFIG_MBEDTLS_SSL_PROTO_TLS1=y CONFIG_MBEDTLS_SSL_PROTO_TLS1_1=y CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y +# CONFIG_MBEDTLS_SSL_PROTO_GMTSSL1_1 is not set # CONFIG_MBEDTLS_SSL_PROTO_DTLS is not set CONFIG_MBEDTLS_SSL_ALPN=y -CONFIG_MBEDTLS_SSL_SESSION_TICKETS=y +CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS=y +CONFIG_MBEDTLS_X509_CHECK_KEY_USAGE=y +CONFIG_MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE=y +CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS=y # # Symmetric Ciphers @@ -372,6 +958,9 @@ CONFIG_MBEDTLS_RC4_DISABLED=y # CONFIG_MBEDTLS_XTEA_C is not set CONFIG_MBEDTLS_CCM_C=y CONFIG_MBEDTLS_GCM_C=y +# CONFIG_MBEDTLS_NIST_KW_C is not set +# end of Symmetric Ciphers + # CONFIG_MBEDTLS_RIPEMD160_C is not set # @@ -381,9 +970,12 @@ CONFIG_MBEDTLS_PEM_PARSE_C=y CONFIG_MBEDTLS_PEM_WRITE_C=y CONFIG_MBEDTLS_X509_CRL_PARSE_C=y CONFIG_MBEDTLS_X509_CSR_PARSE_C=y +# end of Certificates + CONFIG_MBEDTLS_ECP_C=y CONFIG_MBEDTLS_ECDH_C=y CONFIG_MBEDTLS_ECDSA_C=y +# CONFIG_MBEDTLS_ECJPAKE_C is not set CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED=y CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED=y CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED=y @@ -397,24 +989,197 @@ CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED=y CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED=y CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED=y CONFIG_MBEDTLS_ECP_NIST_OPTIM=y +# CONFIG_MBEDTLS_POLY1305_C is not set +# CONFIG_MBEDTLS_CHACHA20_C is not set +# CONFIG_MBEDTLS_HKDF_C is not set +# CONFIG_MBEDTLS_THREADING_C is not set +# CONFIG_MBEDTLS_LARGE_KEY_SOFTWARE_MPI is not set +# CONFIG_MBEDTLS_SECURITY_RISKS is not set +# end of mbedTLS + +# +# mDNS +# +CONFIG_MDNS_MAX_SERVICES=10 +CONFIG_MDNS_TASK_PRIORITY=1 +CONFIG_MDNS_TASK_STACK_SIZE=4096 +# CONFIG_MDNS_TASK_AFFINITY_NO_AFFINITY is not set +CONFIG_MDNS_TASK_AFFINITY_CPU0=y +CONFIG_MDNS_TASK_AFFINITY=0x0 +CONFIG_MDNS_SERVICE_ADD_TIMEOUT_MS=2000 +# CONFIG_MDNS_STRICT_MODE is not set +CONFIG_MDNS_TIMER_PERIOD_MS=100 +# CONFIG_MDNS_NETWORKING_SOCKET is not set +CONFIG_MDNS_MULTIPLE_INSTANCE=y +# end of mDNS + +# +# ESP-MQTT Configurations +# +CONFIG_MQTT_PROTOCOL_311=y +CONFIG_MQTT_TRANSPORT_SSL=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE=y +# CONFIG_MQTT_MSG_ID_INCREMENTAL is not set +# CONFIG_MQTT_SKIP_PUBLISH_IF_DISCONNECTED is not set +# CONFIG_MQTT_REPORT_DELETED_MESSAGES is not set +# CONFIG_MQTT_USE_CUSTOM_CONFIG is not set +# CONFIG_MQTT_TASK_CORE_SELECTION_ENABLED is not set +# CONFIG_MQTT_CUSTOM_OUTBOX is not set +# end of ESP-MQTT Configurations + +# +# Newlib +# +CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF=y +# CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF is not set +# CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR is not set +# CONFIG_NEWLIB_STDIN_LINE_ENDING_CRLF is not set +# CONFIG_NEWLIB_STDIN_LINE_ENDING_LF is not set +CONFIG_NEWLIB_STDIN_LINE_ENDING_CR=y +# CONFIG_NEWLIB_NANO_FORMAT is not set +# end of Newlib + +# +# NVS +# +# end of NVS # # OpenSSL # # CONFIG_OPENSSL_DEBUG is not set +CONFIG_OPENSSL_ERROR_STACK=y CONFIG_OPENSSL_ASSERT_DO_NOTHING=y # CONFIG_OPENSSL_ASSERT_EXIT is not set +# end of OpenSSL + +# +# OpenThread +# +# CONFIG_OPENTHREAD_ENABLED is not set +# end of OpenThread + +# +# PThreads +# +CONFIG_PTHREAD_TASK_PRIO_DEFAULT=5 +CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 +CONFIG_PTHREAD_STACK_MIN=768 +CONFIG_PTHREAD_TASK_CORE_DEFAULT=-1 +CONFIG_PTHREAD_TASK_NAME_DEFAULT="pthread" +# end of PThreads # # SPI Flash driver # +# CONFIG_SPI_FLASH_VERIFY_WRITE is not set # CONFIG_SPI_FLASH_ENABLE_COUNTERS is not set CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y +CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS=y +# CONFIG_SPI_FLASH_DANGEROUS_WRITE_FAILS is not set +# CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED is not set +# CONFIG_SPI_FLASH_USE_LEGACY_IMPL is not set +# CONFIG_SPI_FLASH_SHARE_SPI1_BUS is not set +# CONFIG_SPI_FLASH_BYPASS_BLOCK_ERASE is not set +CONFIG_SPI_FLASH_YIELD_DURING_ERASE=y +CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS=20 +CONFIG_SPI_FLASH_ERASE_YIELD_TICKS=1 +CONFIG_SPI_FLASH_WRITE_CHUNK_SIZE=8192 +# CONFIG_SPI_FLASH_SIZE_OVERRIDE is not set +# CONFIG_SPI_FLASH_CHECK_ERASE_TIMEOUT_DISABLED is not set +# CONFIG_SPI_FLASH_OVERRIDE_CHIP_DRIVER_LIST is not set + +# +# Auto-detect flash chips +# +CONFIG_SPI_FLASH_SUPPORT_ISSI_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_MXIC_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_GD_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_WINBOND_CHIP=y +# CONFIG_SPI_FLASH_SUPPORT_BOYA_CHIP is not set +# CONFIG_SPI_FLASH_SUPPORT_TH_CHIP is not set +# end of Auto-detect flash chips + +CONFIG_SPI_FLASH_ENABLE_ENCRYPTED_READ_WRITE=y +# end of SPI Flash driver + +# +# SPIFFS Configuration +# +CONFIG_SPIFFS_MAX_PARTITIONS=3 + +# +# SPIFFS Cache Configuration +# +CONFIG_SPIFFS_CACHE=y +CONFIG_SPIFFS_CACHE_WR=y +# CONFIG_SPIFFS_CACHE_STATS is not set +# end of SPIFFS Cache Configuration + +CONFIG_SPIFFS_PAGE_CHECK=y +CONFIG_SPIFFS_GC_MAX_RUNS=10 +# CONFIG_SPIFFS_GC_STATS is not set +CONFIG_SPIFFS_PAGE_SIZE=256 +CONFIG_SPIFFS_OBJ_NAME_LEN=32 +# CONFIG_SPIFFS_FOLLOW_SYMLINKS is not set +CONFIG_SPIFFS_USE_MAGIC=y +CONFIG_SPIFFS_USE_MAGIC_LENGTH=y +CONFIG_SPIFFS_META_LENGTH=4 +CONFIG_SPIFFS_USE_MTIME=y + +# +# Debug Configuration +# +# CONFIG_SPIFFS_DBG is not set +# CONFIG_SPIFFS_API_DBG is not set +# CONFIG_SPIFFS_GC_DBG is not set +# CONFIG_SPIFFS_CACHE_DBG is not set +# CONFIG_SPIFFS_CHECK_DBG is not set +# CONFIG_SPIFFS_TEST_VISUALISATION is not set +# end of Debug Configuration +# end of SPIFFS Configuration + +# +# TCP Transport +# + +# +# Websocket +# +CONFIG_WS_TRANSPORT=y +CONFIG_WS_BUFFER_SIZE=1024 +# end of Websocket +# end of TCP Transport # -# tcpip adapter +# Unity unit testing library # -CONFIG_IP_LOST_TIMER_INTERVAL=120 +CONFIG_UNITY_ENABLE_FLOAT=y +CONFIG_UNITY_ENABLE_DOUBLE=y +# CONFIG_UNITY_ENABLE_64BIT is not set +# CONFIG_UNITY_ENABLE_COLOR is not set +CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y +# CONFIG_UNITY_ENABLE_FIXTURE is not set +# CONFIG_UNITY_ENABLE_BACKTRACE_ON_FAIL is not set +# end of Unity unit testing library + +# +# Virtual file system +# +CONFIG_VFS_SUPPORT_IO=y +CONFIG_VFS_SUPPORT_DIR=y +CONFIG_VFS_SUPPORT_SELECT=y +CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT=y +CONFIG_VFS_SUPPORT_TERMIOS=y + +# +# Host File System I/O (Semihosting) +# +CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS=1 +CONFIG_VFS_SEMIHOSTFS_HOST_PATH_MAX_LEN=128 +# end of Host File System I/O (Semihosting) +# end of Virtual file system # # Wear Levelling @@ -422,3 +1187,189 @@ CONFIG_IP_LOST_TIMER_INTERVAL=120 # CONFIG_WL_SECTOR_SIZE_512 is not set CONFIG_WL_SECTOR_SIZE_4096=y CONFIG_WL_SECTOR_SIZE=4096 +# end of Wear Levelling + +# +# Wi-Fi Provisioning Manager +# +CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES=16 +CONFIG_WIFI_PROV_AUTOSTOP_TIMEOUT=30 +# end of Wi-Fi Provisioning Manager + +# +# Supplicant +# +CONFIG_WPA_MBEDTLS_CRYPTO=y +# CONFIG_WPA_WAPI_PSK is not set +# CONFIG_WPA_SUITE_B_192 is not set +# CONFIG_WPA_DEBUG_PRINT is not set +# CONFIG_WPA_TESTING_OPTIONS is not set +# CONFIG_WPA_WPS_STRICT is not set +# CONFIG_WPA_11KV_SUPPORT is not set +# end of Supplicant +# end of Component config + +# +# Compatibility options +# +# CONFIG_LEGACY_INCLUDE_COMMON_HEADERS is not set +# end of Compatibility options + +# Deprecated options for backward compatibility +CONFIG_TOOLPREFIX="xtensa-esp32-elf-" +# CONFIG_LOG_BOOTLOADER_LEVEL_NONE is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_ERROR is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_WARN is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_INFO is not set +CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG=y +# CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE is not set +CONFIG_LOG_BOOTLOADER_LEVEL=4 +# CONFIG_APP_ROLLBACK_ENABLE is not set +# CONFIG_FLASH_ENCRYPTION_ENABLED is not set +# CONFIG_FLASHMODE_QIO is not set +# CONFIG_FLASHMODE_QOUT is not set +CONFIG_FLASHMODE_DIO=y +# CONFIG_FLASHMODE_DOUT is not set +# CONFIG_MONITOR_BAUD_9600B is not set +# CONFIG_MONITOR_BAUD_57600B is not set +CONFIG_MONITOR_BAUD_115200B=y +# CONFIG_MONITOR_BAUD_230400B is not set +# CONFIG_MONITOR_BAUD_921600B is not set +# CONFIG_MONITOR_BAUD_2MB is not set +# CONFIG_MONITOR_BAUD_OTHER is not set +CONFIG_MONITOR_BAUD_OTHER_VAL=115200 +CONFIG_MONITOR_BAUD=115200 +CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG=y +# CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE is not set +CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y +# CONFIG_OPTIMIZATION_ASSERTIONS_SILENT is not set +# CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED is not set +CONFIG_OPTIMIZATION_ASSERTION_LEVEL=2 +# CONFIG_CXX_EXCEPTIONS is not set +CONFIG_STACK_CHECK_NONE=y +# CONFIG_STACK_CHECK_NORM is not set +# CONFIG_STACK_CHECK_STRONG is not set +# CONFIG_STACK_CHECK_ALL is not set +# CONFIG_WARN_WRITE_STRINGS is not set +# CONFIG_DISABLE_GCC8_WARNINGS is not set +# CONFIG_ESP32_APPTRACE_DEST_TRAX is not set +CONFIG_ESP32_APPTRACE_DEST_NONE=y +CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y +CONFIG_ADC2_DISABLE_DAC=y +# CONFIG_SPIRAM_SUPPORT is not set +CONFIG_TRACEMEM_RESERVE_DRAM=0x0 +# CONFIG_ULP_COPROC_ENABLED is not set +CONFIG_ULP_COPROC_RESERVE_MEM=0 +CONFIG_BROWNOUT_DET=y +CONFIG_BROWNOUT_DET_LVL_SEL_0=y +# CONFIG_BROWNOUT_DET_LVL_SEL_1 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_2 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_3 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_4 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_5 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_6 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_7 is not set +CONFIG_BROWNOUT_DET_LVL=0 +CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC=y +# CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL is not set +# CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_OSC is not set +# CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_8MD256 is not set +# CONFIG_DISABLE_BASIC_ROM_CONSOLE is not set +# CONFIG_NO_BLOBS is not set +# CONFIG_COMPATIBLE_PRE_V2_1_BOOTLOADERS is not set +# CONFIG_EVENT_LOOP_PROFILING is not set +CONFIG_POST_EVENTS_FROM_ISR=y +CONFIG_POST_EVENTS_FROM_IRAM_ISR=y +CONFIG_GDBSTUB_SUPPORT_TASKS=y +CONFIG_GDBSTUB_MAX_TASKS=32 +# CONFIG_TWO_UNIVERSAL_MAC_ADDRESS is not set +CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS=y +CONFIG_NUMBER_OF_UNIVERSAL_MAC_ADDRESS=4 +CONFIG_ESP_SYSTEM_PD_FLASH=y +# CONFIG_ESP32C3_LIGHTSLEEP_GPIO_RESET_WORKAROUND is not set +CONFIG_IPC_TASK_STACK_SIZE=1024 +CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE=y +# CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION is not set +CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER=20 +CONFIG_ESP32_PHY_MAX_TX_POWER=20 +CONFIG_ESP32_REDUCE_PHY_TX_POWER=y +# CONFIG_ESP32S2_PANIC_PRINT_HALT is not set +# CONFIG_ESP32S2_PANIC_PRINT_REBOOT is not set +# CONFIG_ESP32S2_PANIC_SILENT_REBOOT is not set +CONFIG_ESP32S2_PANIC_GDBSTUB=y +CONFIG_ESP32S2_ALLOW_RTC_FAST_MEM_AS_HEAP=y +CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32 +CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=4096 +CONFIG_MAIN_TASK_STACK_SIZE=4096 +CONFIG_CONSOLE_UART_DEFAULT=y +# CONFIG_CONSOLE_UART_CUSTOM is not set +# CONFIG_ESP_CONSOLE_UART_NONE is not set +CONFIG_CONSOLE_UART=y +CONFIG_CONSOLE_UART_NUM=0 +CONFIG_CONSOLE_UART_BAUDRATE=115200 +CONFIG_INT_WDT=y +CONFIG_INT_WDT_TIMEOUT_MS=300 +CONFIG_TASK_WDT=y +# CONFIG_TASK_WDT_PANIC is not set +CONFIG_TASK_WDT_TIMEOUT_S=5 +CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0=y +# CONFIG_ESP32_DEBUG_STUBS_ENABLE is not set +CONFIG_TIMER_TASK_STACK_SIZE=3584 +# CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH is not set +# CONFIG_ESP32_ENABLE_COREDUMP_TO_UART is not set +CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE=y +CONFIG_MB_MASTER_TIMEOUT_MS_RESPOND=150 +CONFIG_MB_MASTER_DELAY_MS_CONVERT=200 +CONFIG_MB_QUEUE_LENGTH=20 +CONFIG_MB_SERIAL_TASK_STACK_SIZE=4096 +CONFIG_MB_SERIAL_BUF_SIZE=256 +CONFIG_MB_SERIAL_TASK_PRIO=10 +CONFIG_MB_CONTROLLER_SLAVE_ID_SUPPORT=y +CONFIG_MB_CONTROLLER_SLAVE_ID=0x00112233 +CONFIG_MB_CONTROLLER_NOTIFY_TIMEOUT=20 +CONFIG_MB_CONTROLLER_NOTIFY_QUEUE_SIZE=20 +CONFIG_MB_CONTROLLER_STACK_SIZE=4096 +CONFIG_MB_EVENT_QUEUE_TIMEOUT=20 +# CONFIG_MB_TIMER_PORT_ENABLED is not set +CONFIG_MB_TIMER_GROUP=0 +CONFIG_MB_TIMER_INDEX=0 +# CONFIG_ENABLE_STATIC_TASK_CLEAN_UP_HOOK is not set +CONFIG_TIMER_TASK_PRIORITY=1 +CONFIG_TIMER_TASK_STACK_DEPTH=2048 +CONFIG_TIMER_QUEUE_LENGTH=10 +# CONFIG_L2_TO_L3_COPY is not set +# CONFIG_USE_ONLY_LWIP_SELECT is not set +CONFIG_ESP_GRATUITOUS_ARP=y +CONFIG_GARP_TMR_INTERVAL=60 +CONFIG_TCPIP_RECVMBOX_SIZE=32 +CONFIG_TCP_MAXRTX=12 +CONFIG_TCP_SYNMAXRTX=6 +CONFIG_TCP_MSS=1436 +CONFIG_TCP_MSL=60000 +CONFIG_TCP_SND_BUF_DEFAULT=5744 +CONFIG_TCP_WND_DEFAULT=5744 +CONFIG_TCP_RECVMBOX_SIZE=6 +CONFIG_TCP_QUEUE_OOSEQ=y +# CONFIG_ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES is not set +CONFIG_TCP_OVERSIZE_MSS=y +# CONFIG_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_TCP_OVERSIZE_DISABLE is not set +CONFIG_UDP_RECVMBOX_SIZE=6 +CONFIG_TCPIP_TASK_STACK_SIZE=2560 +CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY=y +# CONFIG_TCPIP_TASK_AFFINITY_CPU0 is not set +CONFIG_TCPIP_TASK_AFFINITY=0x7FFFFFFF +# CONFIG_PPP_SUPPORT is not set +CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT=5 +CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 +CONFIG_ESP32_PTHREAD_STACK_MIN=768 +CONFIG_ESP32_PTHREAD_TASK_CORE_DEFAULT=-1 +CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT="pthread" +CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS=y +# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_FAILS is not set +# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED is not set +CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT=y +CONFIG_SUPPORT_TERMIOS=y +CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS=1 +CONFIG_SEMIHOSTFS_HOST_PATH_MAX_LEN=128 +# End of deprecated options From 531c997a187fdbd4f36ec85c7aafb0178f7552f7 Mon Sep 17 00:00:00 2001 From: brand17 <36546021+brand17@users.noreply.github.com> Date: Sun, 3 Jul 2022 22:23:28 +0300 Subject: [PATCH 313/335] fifo rate added --- .../components/MPU6050/MPU6050_6Axis_MotionApps20.h | 8 ++++++++ ESP32_ESP-IDF/main/example.cpp | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/ESP32_ESP-IDF/components/MPU6050/MPU6050_6Axis_MotionApps20.h b/ESP32_ESP-IDF/components/MPU6050/MPU6050_6Axis_MotionApps20.h index 7ec8da74..66426c58 100644 --- a/ESP32_ESP-IDF/components/MPU6050/MPU6050_6Axis_MotionApps20.h +++ b/ESP32_ESP-IDF/components/MPU6050/MPU6050_6Axis_MotionApps20.h @@ -320,6 +320,10 @@ const unsigned char dmpUpdates[MPU6050_DMP_UPDATES_SIZE] = { 0x00, 0x60, 0x04, 0x00, 0x40, 0x00, 0x00 }; +#ifndef MPU6050_DMP_FIFO_RATE_DIVISOR +#define MPU6050_DMP_FIFO_RATE_DIVISOR 0x00 // The New instance of the Firmware has this as the default +#endif + uint8_t MPU6050::dmpInitialize() { // reset device DEBUG_PRINTLN(F("\n\nResetting MPU6050...")); @@ -382,6 +386,10 @@ uint8_t MPU6050::dmpInitialize() { if (writeProgMemoryBlock(dmpMemory, MPU6050_DMP_CODE_SIZE)) { DEBUG_PRINTLN(F("Success! DMP code written and verified.")); + // Set the FIFO Rate Divisor int the DMP Firmware Memory + unsigned char dmpUpdate[] = {0x00, MPU6050_DMP_FIFO_RATE_DIVISOR}; + writeMemoryBlock(dmpUpdate, 0x02, 0x02, 0x16); // Lets write the dmpUpdate data to the Firmware image, we have 2 bytes to write in bank 0x02 with the Offset 0x16 + // write DMP configuration // DEBUG_PRINTLN(F("Writing DMP configuration to MPU memory banks (")); // DEBUG_PRINT(MPU6050_DMP_CONFIG_SIZE); diff --git a/ESP32_ESP-IDF/main/example.cpp b/ESP32_ESP-IDF/main/example.cpp index 3407d212..1724fa06 100644 --- a/ESP32_ESP-IDF/main/example.cpp +++ b/ESP32_ESP-IDF/main/example.cpp @@ -80,7 +80,7 @@ void task_display(void*){ //Best result is to match with DMP refresh rate // Its last value in components/MPU6050/MPU6050_6Axis_MotionApps20.h file line 310 // Now its 0x13, which means DMP is refreshed with 10Hz rate - vTaskDelay(5/portTICK_PERIOD_MS); + // vTaskDelay(5/portTICK_PERIOD_MS); } vTaskDelete(NULL); From 3dac0096f2ae66835edf8172fb00505df3f8f04c Mon Sep 17 00:00:00 2001 From: Jeff Rowberg Date: Thu, 7 Jul 2022 14:09:09 -0400 Subject: [PATCH 314/335] Delete ESP32_ESP-IDF/.vscode directory --- ESP32_ESP-IDF/.vscode/c_cpp_properties.json | 28 --------------------- ESP32_ESP-IDF/.vscode/settings.json | 4 --- 2 files changed, 32 deletions(-) delete mode 100644 ESP32_ESP-IDF/.vscode/c_cpp_properties.json delete mode 100644 ESP32_ESP-IDF/.vscode/settings.json diff --git a/ESP32_ESP-IDF/.vscode/c_cpp_properties.json b/ESP32_ESP-IDF/.vscode/c_cpp_properties.json deleted file mode 100644 index fabd55d9..00000000 --- a/ESP32_ESP-IDF/.vscode/c_cpp_properties.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "configurations": [ - { - "name": "ESP-IDF", - "compilerPath": "C:\\Espressif\\tools\\xtensa-esp32-elf\\esp-2021r2-patch3-8.4.0\\xtensa-esp32-elf\\bin\\xtensa-esp32-elf-gcc.exe", - "cStandard": "c11", - "cppStandard": "c++17", - "includePath": [ - "${config:idf.espIdfPath}/components/**", - "${config:idf.espIdfPathWin}/components/**", - "${config:idf.espAdfPath}/components/**", - "${config:idf.espAdfPathWin}/components/**", - "${workspaceFolder}/**" - ], - "browse": { - "path": [ - "${config:idf.espIdfPath}/components", - "${config:idf.espIdfPathWin}/components", - "${config:idf.espAdfPath}/components/**", - "${config:idf.espAdfPathWin}/components/**", - "${workspaceFolder}" - ], - "limitSymbolsToIncludedHeaders": false - } - } - ], - "version": 4 -} diff --git a/ESP32_ESP-IDF/.vscode/settings.json b/ESP32_ESP-IDF/.vscode/settings.json deleted file mode 100644 index 8d2f4595..00000000 --- a/ESP32_ESP-IDF/.vscode/settings.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "idf.flashType": "UART", - "idf.portWin": "COM10" -} \ No newline at end of file From 92bb11355f5a72509b9148947becc872bda17730 Mon Sep 17 00:00:00 2001 From: Jacob Geigle Date: Sat, 6 Aug 2022 10:14:45 +0900 Subject: [PATCH 315/335] Corrected gravity constants for FIFO processing to match 2g values --- Arduino/MPU6050/MPU6050_6Axis_MotionApps612.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Arduino/MPU6050/MPU6050_6Axis_MotionApps612.cpp b/Arduino/MPU6050/MPU6050_6Axis_MotionApps612.cpp index 2e036ddf..2cd11134 100644 --- a/Arduino/MPU6050/MPU6050_6Axis_MotionApps612.cpp +++ b/Arduino/MPU6050/MPU6050_6Axis_MotionApps612.cpp @@ -490,10 +490,10 @@ uint8_t MPU6050::dmpGetGyro(VectorInt16 *v, const uint8_t* packet) { // uint8_t MPU6050::dmpSetLinearAccelFilterCoefficient(float coef); // uint8_t MPU6050::dmpGetLinearAccel(long *data, const uint8_t* packet); uint8_t MPU6050::dmpGetLinearAccel(VectorInt16 *v, VectorInt16 *vRaw, VectorFloat *gravity) { - // get rid of the gravity component (+1g = +8192 in standard DMP FIFO packet, sensitivity is 2g) - v -> x = vRaw -> x - gravity -> x*8192; - v -> y = vRaw -> y - gravity -> y*8192; - v -> z = vRaw -> z - gravity -> z*8192; + // get rid of the gravity component (+1g = +16384 in standard DMP FIFO packet, sensitivity is 2g) + v -> x = vRaw -> x - gravity -> x*16384; + v -> y = vRaw -> y - gravity -> y*16384; + v -> z = vRaw -> z - gravity -> z*16384; return 0; } // uint8_t MPU6050::dmpGetLinearAccelInWorld(long *data, const uint8_t* packet); @@ -510,7 +510,7 @@ uint8_t MPU6050::dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Qu // uint8_t MPU6050::dmpGetTemperature(long *data, const uint8_t* packet); // uint8_t MPU6050::dmpGetGravity(long *data, const uint8_t* packet); uint8_t MPU6050::dmpGetGravity(int16_t *data, const uint8_t* packet) { - /* +1g corresponds to +8192, sensitivity is 2g. */ + /* +1g corresponds to +16384, sensitivity is 2g. */ int16_t qI[4]; uint8_t status = dmpGetQuaternion(qI, packet); data[0] = ((int32_t)qI[1] * qI[3] - (int32_t)qI[0] * qI[2]) / 16384; From 4cd868f9e4bae21010c87cad10be2dac9cbbb2c4 Mon Sep 17 00:00:00 2001 From: mjcross Date: Sat, 13 Aug 2022 08:06:14 +0100 Subject: [PATCH 316/335] Show how to use calibration data Explain where/how to initialise the accelerometer and gyro offsets --- RP2040/MPU6050/examples/README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/RP2040/MPU6050/examples/README.md b/RP2040/MPU6050/examples/README.md index fc9f414f..49587d77 100644 --- a/RP2040/MPU6050/examples/README.md +++ b/RP2040/MPU6050/examples/README.md @@ -8,3 +8,8 @@ Also, if the libraries files (I2Cdev.h, I2Cdev.cpp, MPU6050.h, MPU6050.cpp, MPU6 4. ```make``` 5. Copy the uf2 file to your Pico board, using ```cp``` or the file explorer you have. 6. ```sudo minicom -D /dev/ttyACM0``` to watch the serial output. Use ```sudo```, otherwise minicom will fail to open the device and show no warnings. On Windows you can use PuTTY, choosing the COM port that was assigned (check the Device Manager) and a baudrate of 115200. + +#### Sensor calibration +You will get better results if you measure the gyro and accelerometer offsets for your sensor *(e.g. with the accompanying calibration example)*. Set the initial offsets using `mpu.setXAccelOffset()` and friends in mpu6050_DMP_port.cpp after the call to `mpu.dmpInitialize()`. + +Alternatively you could call `mpu.CalibrateAccel(6)` and `mpu.CalibrateGyro(6)` in the same location (6 loops should be enough). From eae2846a5566785b0abcf4578dddc81cafc44fb3 Mon Sep 17 00:00:00 2001 From: mjcross Date: Sat, 13 Aug 2022 08:24:44 +0100 Subject: [PATCH 317/335] Fix incorrect pin numbers Default SDA/SCL on the Pico is on pins 6, 7 not 4, 5. Also added a comment about calibration. --- .../mpu6050_DMP_V6.12/mpu6050_DMP_port.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/mpu6050_DMP_port.cpp b/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/mpu6050_DMP_port.cpp index 31ff420f..20665e49 100644 --- a/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/mpu6050_DMP_port.cpp +++ b/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/mpu6050_DMP_port.cpp @@ -35,7 +35,7 @@ void dmpDataReady() { int main() { stdio_init_all(); - // This example will use I2C0 on the default SDA and SCL pins (4, 5 on a Pico) + // This example will use I2C0 on the default SDA and SCL (pins 6, 7 on a Pico) i2c_init(i2c_default, 400 * 1000); gpio_set_function(PICO_DEFAULT_I2C_SDA_PIN, GPIO_FUNC_I2C); gpio_set_function(PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C); @@ -59,6 +59,19 @@ int main() { mpu.initialize(); devStatus = mpu.dmpInitialize(); + + /* --- if you have calibration data then set the sensor offsets here --- */ + // mpu.setXAccelOffset(); + // mpu.setYAccelOffset(); + // mpu.setZAccelOffset(); + // mpu.setXGyroOffset(); + // mpu.setYGyroOffset(); + // mpu.setZGyroOffset(); + + /* --- alternatively you can try this (6 loops should be enough) --- */ + // mpu.CalibrateAccel(6); + // mpu.CalibrateGyro(6); + if (devStatus == 0) { mpu.setDMPEnabled(true); // turn on the DMP, now that it's ready From 98a3b4ec838223fd5316de54203a6dc88718cd00 Mon Sep 17 00:00:00 2001 From: Jeff Rowberg Date: Thu, 13 Oct 2022 22:56:35 -0400 Subject: [PATCH 318/335] Remove extra begin/endTransmission calls during reads Fixes #670 and #672 --- Arduino/I2Cdev/I2Cdev.cpp | 19 ------------------- MSP430/I2Cdev/I2Cdev.cpp | 21 --------------------- 2 files changed, 40 deletions(-) diff --git a/Arduino/I2Cdev/I2Cdev.cpp b/Arduino/I2Cdev/I2Cdev.cpp index 892274ba..233e4099 100644 --- a/Arduino/I2Cdev/I2Cdev.cpp +++ b/Arduino/I2Cdev/I2Cdev.cpp @@ -234,9 +234,7 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 useWire->beginTransmission(devAddr); useWire->send(regAddr); useWire->endTransmission(); - useWire->beginTransmission(devAddr); useWire->requestFrom((uint8_t)devAddr, (uint8_t)min((int)length - k, I2CDEVLIB_WIRE_BUFFER_LENGTH)); - for (; useWire->available() && (timeout == 0 || millis() - t1 < timeout); count++) { data[count] = useWire->receive(); #ifdef I2CDEV_SERIAL_DEBUG @@ -244,8 +242,6 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 if (count + 1 < length) Serial.print(" "); #endif } - - useWire->endTransmission(); } #elif (ARDUINO == 100) // Arduino v1.0.0, Wire library @@ -258,9 +254,7 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 useWire->beginTransmission(devAddr); useWire->write(regAddr); useWire->endTransmission(); - useWire->beginTransmission(devAddr); useWire->requestFrom((uint8_t)devAddr, (uint8_t)min((int)length - k, I2CDEVLIB_WIRE_BUFFER_LENGTH)); - for (; useWire->available() && (timeout == 0 || millis() - t1 < timeout); count++) { data[count] = useWire->read(); #ifdef I2CDEV_SERIAL_DEBUG @@ -268,8 +262,6 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 if (count + 1 < length) Serial.print(" "); #endif } - - useWire->endTransmission(); } #elif (ARDUINO > 100) // Arduino v1.0.1+, Wire library @@ -282,9 +274,7 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 useWire->beginTransmission(devAddr); useWire->write(regAddr); useWire->endTransmission(); - useWire->beginTransmission(devAddr); useWire->requestFrom((uint8_t)devAddr, (uint8_t)min((int)length - k, I2CDEVLIB_WIRE_BUFFER_LENGTH)); - for (; useWire->available() && (timeout == 0 || millis() - t1 < timeout); count++) { data[count] = useWire->read(); #ifdef I2CDEV_SERIAL_DEBUG @@ -356,7 +346,6 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 useWire->beginTransmission(devAddr); useWire->send(regAddr); useWire->endTransmission(); - useWire->beginTransmission(devAddr); useWire->requestFrom(devAddr, (uint8_t)(length * 2)); // length=words, this wants bytes bool msb = true; // starts with MSB, then LSB @@ -375,8 +364,6 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 } msb = !msb; } - - useWire->endTransmission(); } #elif (ARDUINO == 100) // Arduino v1.0.0, Wire library @@ -389,7 +376,6 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 useWire->beginTransmission(devAddr); useWire->write(regAddr); useWire->endTransmission(); - useWire->beginTransmission(devAddr); useWire->requestFrom(devAddr, (uint8_t)(length * 2)); // length=words, this wants bytes bool msb = true; // starts with MSB, then LSB @@ -408,8 +394,6 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 } msb = !msb; } - - useWire->endTransmission(); } #elif (ARDUINO > 100) // Arduino v1.0.1+, Wire library @@ -422,7 +406,6 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 useWire->beginTransmission(devAddr); useWire->write(regAddr); useWire->endTransmission(); - useWire->beginTransmission(devAddr); useWire->requestFrom(devAddr, (uint8_t)(length * 2)); // length=words, this wants bytes bool msb = true; // starts with MSB, then LSB @@ -441,8 +424,6 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 } msb = !msb; } - - useWire->endTransmission(); } #endif diff --git a/MSP430/I2Cdev/I2Cdev.cpp b/MSP430/I2Cdev/I2Cdev.cpp index 7613b70e..6e539f79 100644 --- a/MSP430/I2Cdev/I2Cdev.cpp +++ b/MSP430/I2Cdev/I2Cdev.cpp @@ -230,9 +230,7 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 Wire.beginTransmission(devAddr); Wire.send(regAddr); Wire.endTransmission(); - Wire.beginTransmission(devAddr); Wire.requestFrom(devAddr, (uint8_t)min(length - k, I2CDEVLIB_WIRE_BUFFER_LENGTH)); - for (; Wire.available() && (timeout == 0 || millis() - t1 < timeout); count++) { data[count] = Wire.receive(); #ifdef I2CDEV_SERIAL_DEBUG @@ -240,8 +238,6 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 if (count + 1 < length) Serial.print(" "); #endif } - - Wire.endTransmission(); } #elif (ARDUINO == 100) // Arduino v1.0.0, Wire library @@ -254,9 +250,7 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 Wire.beginTransmission(devAddr); Wire.write(regAddr); Wire.endTransmission(); - Wire.beginTransmission(devAddr); Wire.requestFrom(devAddr, (uint8_t)min(length - k, I2CDEVLIB_WIRE_BUFFER_LENGTH)); - for (; Wire.available() && (timeout == 0 || millis() - t1 < timeout); count++) { data[count] = Wire.read(); #ifdef I2CDEV_SERIAL_DEBUG @@ -264,8 +258,6 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 if (count + 1 < length) Serial.print(" "); #endif } - - Wire.endTransmission(); } #elif (ARDUINO > 100) // Arduino v1.0.1+, Wire library @@ -278,9 +270,7 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 Wire.beginTransmission(devAddr); Wire.write(regAddr); Wire.endTransmission(); - Wire.beginTransmission(devAddr); Wire.requestFrom(devAddr, (uint8_t)min(length - k, I2CDEVLIB_WIRE_BUFFER_LENGTH)); - for (; Wire.available() && (timeout == 0 || millis() - t1 < timeout); count++) { data[count] = Wire.read(); #ifdef I2CDEV_SERIAL_DEBUG @@ -288,8 +278,6 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 if (count + 1 < length) Serial.print(" "); #endif } - - Wire.endTransmission(); } #endif @@ -357,7 +345,6 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 Wire.beginTransmission(devAddr); Wire.send(regAddr); Wire.endTransmission(); - Wire.beginTransmission(devAddr); Wire.requestFrom(devAddr, (uint8_t)(length * 2)); // length=words, this wants bytes bool msb = true; // starts with MSB, then LSB @@ -376,8 +363,6 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 } msb = !msb; } - - Wire.endTransmission(); } #elif (ARDUINO == 100) // Arduino v1.0.0, Wire library @@ -390,7 +375,6 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 Wire.beginTransmission(devAddr); Wire.write(regAddr); Wire.endTransmission(); - Wire.beginTransmission(devAddr); Wire.requestFrom(devAddr, (uint8_t)(length * 2)); // length=words, this wants bytes bool msb = true; // starts with MSB, then LSB @@ -409,8 +393,6 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 } msb = !msb; } - - Wire.endTransmission(); } #elif (ARDUINO > 100) // Arduino v1.0.1+, Wire library @@ -423,7 +405,6 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 Wire.beginTransmission(devAddr); Wire.write(regAddr); Wire.endTransmission(); - Wire.beginTransmission(devAddr); Wire.requestFrom(devAddr, (uint8_t)(length * 2)); // length=words, this wants bytes bool msb = true; // starts with MSB, then LSB @@ -442,8 +423,6 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 } msb = !msb; } - - Wire.endTransmission(); } #endif From 7a4b096e985dccb5d4d62d21a607d2740e56c7da Mon Sep 17 00:00:00 2001 From: naum Date: Fri, 25 Nov 2022 22:13:10 -0500 Subject: [PATCH 319/335] Fixing bug in int8_t I2Cdev::readWords() Issue #718 --- RP2040/I2Cdev/I2Cdev.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/RP2040/I2Cdev/I2Cdev.cpp b/RP2040/I2Cdev/I2Cdev.cpp index acfb8c2b..7d833592 100644 --- a/RP2040/I2Cdev/I2Cdev.cpp +++ b/RP2040/I2Cdev/I2Cdev.cpp @@ -166,14 +166,13 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 * @return Number of words read (-1 indicates failure) */ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data, uint32_t timeout) { - int8_t count = 0, j = 0; + int8_t count = 0; uint8_t data_buf[length*2]; i2c_write_blocking(i2c_default, devAddr, ®Addr, 1, true); count = i2c_read_timeout_us(i2c_default, devAddr, data_buf, length*2, false, timeout * 1000); for(int i=0; i Date: Mon, 28 Nov 2022 18:17:18 -0500 Subject: [PATCH 320/335] pico_sdk_import_1.4.0 New copy of pico_sdk_import.cmake from pico_sdk version 1.4.0 Wed Jun 29 22:56:27 2022 --- .../mpu6050_DMP_V6.12/pico_sdk_import.cmake | 21 ++++++++++++++----- .../mpu6050_calibration/pico_sdk_import.cmake | 21 ++++++++++++++----- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/pico_sdk_import.cmake b/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/pico_sdk_import.cmake index 28efe9ea..65f8a6f7 100644 --- a/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/pico_sdk_import.cmake +++ b/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/pico_sdk_import.cmake @@ -29,11 +29,22 @@ if (NOT PICO_SDK_PATH) if (PICO_SDK_FETCH_FROM_GIT_PATH) get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}") endif () - FetchContent_Declare( - pico_sdk - GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk - GIT_TAG master - ) + # GIT_SUBMODULES_RECURSE was added in 3.17 + if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.17.0") + FetchContent_Declare( + pico_sdk + GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk + GIT_TAG master + GIT_SUBMODULES_RECURSE FALSE + ) + else () + FetchContent_Declare( + pico_sdk + GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk + GIT_TAG master + ) + endif () + if (NOT pico_sdk) message("Downloading Raspberry Pi Pico SDK") FetchContent_Populate(pico_sdk) diff --git a/RP2040/MPU6050/examples/mpu6050_calibration/pico_sdk_import.cmake b/RP2040/MPU6050/examples/mpu6050_calibration/pico_sdk_import.cmake index 28efe9ea..65f8a6f7 100644 --- a/RP2040/MPU6050/examples/mpu6050_calibration/pico_sdk_import.cmake +++ b/RP2040/MPU6050/examples/mpu6050_calibration/pico_sdk_import.cmake @@ -29,11 +29,22 @@ if (NOT PICO_SDK_PATH) if (PICO_SDK_FETCH_FROM_GIT_PATH) get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}") endif () - FetchContent_Declare( - pico_sdk - GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk - GIT_TAG master - ) + # GIT_SUBMODULES_RECURSE was added in 3.17 + if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.17.0") + FetchContent_Declare( + pico_sdk + GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk + GIT_TAG master + GIT_SUBMODULES_RECURSE FALSE + ) + else () + FetchContent_Declare( + pico_sdk + GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk + GIT_TAG master + ) + endif () + if (NOT pico_sdk) message("Downloading Raspberry Pi Pico SDK") FetchContent_Populate(pico_sdk) From 70984d58bec52b975cc745416077795ec176c9f0 Mon Sep 17 00:00:00 2001 From: naum Date: Sun, 27 Nov 2022 22:06:24 -0500 Subject: [PATCH 321/335] fixing problem "MPU6050/examples/ do not support PICO W" issue 721 MPU6050/examples/ do not support PICO W --- RP2040/MPU6050/examples/README.md | 11 ++-- .../examples/mpu6050_DMP_V6.12/CMakeLists.txt | 33 ++++++------ .../mpu6050_DMP_V6.12/mpu6050_DMP_port.cpp | 50 ++++++++++++++++--- .../mpu6050_calibration/CMakeLists.txt | 34 +++++++------ .../mpu6050_calibration.cpp | 49 +++++++++++++++--- 5 files changed, 127 insertions(+), 50 deletions(-) diff --git a/RP2040/MPU6050/examples/README.md b/RP2040/MPU6050/examples/README.md index 49587d77..4bc90006 100644 --- a/RP2040/MPU6050/examples/README.md +++ b/RP2040/MPU6050/examples/README.md @@ -3,11 +3,12 @@ Also, if the libraries files (I2Cdev.h, I2Cdev.cpp, MPU6050.h, MPU6050.cpp, MPU6 #### Instructions for building examples 1. ```cd``` to the folder of the example you want to build. -2. ```mkdir build && cd build``` -3. ```cmake ..``` -4. ```make``` -5. Copy the uf2 file to your Pico board, using ```cp``` or the file explorer you have. -6. ```sudo minicom -D /dev/ttyACM0``` to watch the serial output. Use ```sudo```, otherwise minicom will fail to open the device and show no warnings. On Windows you can use PuTTY, choosing the COM port that was assigned (check the Device Manager) and a baudrate of 115200. +2. If you have PICO W (PICO board with Infineon CYW43439 wireless chip), you need to uncommented 3 lines in CMakeLists.txt file. +3. ```mkdir build && cd build``` +4. ```cmake ..``` +5. ```make``` +6. Copy the uf2 file to your Pico board, using ```cp``` or the file explorer you have. +7. ```sudo minicom -D /dev/ttyACM0``` to watch the serial output. Use ```sudo```, otherwise minicom will fail to open the device and show no warnings. On Windows you can use PuTTY, choosing the COM port that was assigned (check the Device Manager) and a baudrate of 115200. #### Sensor calibration You will get better results if you measure the gyro and accelerometer offsets for your sensor *(e.g. with the accompanying calibration example)*. Set the initial offsets using `mpu.setXAccelOffset()` and friends in mpu6050_DMP_port.cpp after the call to `mpu.dmpInitialize()`. diff --git a/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/CMakeLists.txt b/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/CMakeLists.txt index 646890a2..8214ca67 100644 --- a/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/CMakeLists.txt +++ b/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/CMakeLists.txt @@ -1,21 +1,33 @@ # Generated Cmake Pico project file cmake_minimum_required(VERSION 3.13) - -set(CMAKE_C_STANDARD 11) -set(CMAKE_CXX_STANDARD 17) - -# Pull in Raspberry Pi Pico SDK (must be before project) +# Pull in SDK (must be before project) +# set(PICO_BOARD pico_w) # Needed only for PICO W +# set(CYW43_LWIP 1) # Needed only for PICO W include(pico_sdk_import.cmake) project(mpu6050_DMP_port C CXX ASM) +set(CMAKE_C_STANDARD 11) +set(CMAKE_CXX_STANDARD 17) # Initialise the Raspberry Pi Pico SDK pico_sdk_init() # Add executable. Default name is the project name, version 0.1 -add_executable(mpu6050_DMP_port mpu6050_DMP_port.cpp I2Cdev.cpp MPU6050.cpp ) +add_executable(mpu6050_DMP_port + mpu6050_DMP_port.cpp + MPU6050.cpp + I2Cdev.cpp + ) + +# Add any user requested libraries +target_link_libraries(mpu6050_DMP_port + pico_stdlib + # pico_cyw43_arch_none # we need Wifi to access the GPIO. Needed only for PICO W + hardware_i2c + pico_double + ) pico_set_program_name(mpu6050_DMP_port "mpu6050_DMP_port") pico_set_program_version(mpu6050_DMP_port "0.1") @@ -23,14 +35,7 @@ pico_set_program_version(mpu6050_DMP_port "0.1") pico_enable_stdio_uart(mpu6050_DMP_port 0) pico_enable_stdio_usb(mpu6050_DMP_port 1) -# Add the standard library to the build -target_link_libraries(mpu6050_DMP_port pico_stdlib) - -# Add any user requested libraries -target_link_libraries(mpu6050_DMP_port - hardware_i2c - pico_double - ) +# create map/bin/hex file etc. pico_add_extra_outputs(mpu6050_DMP_port) diff --git a/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/mpu6050_DMP_port.cpp b/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/mpu6050_DMP_port.cpp index 20665e49..bc9c1725 100644 --- a/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/mpu6050_DMP_port.cpp +++ b/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/mpu6050_DMP_port.cpp @@ -1,6 +1,9 @@ #include #include "pico/stdlib.h" #include "hardware/i2c.h" +#ifndef PICO_DEFAULT_LED_PIN // PICO w with WiFi +#include "pico/cyw43_arch.h" +#endif #include "MPU6050_6Axis_MotionApps_V6_12.h" MPU6050 mpu; @@ -33,6 +36,42 @@ void dmpDataReady() { mpuInterrupt = true; } +void initLED() { +#ifndef PICO_DEFAULT_LED_PIN // PICO w with WiFi + printf ("we have board with wifi (pico w) \n"); + if (cyw43_arch_init()) { + printf("WiFi init failed"); + exit(3); + } +#else + printf ("we have board without wifi\n"); + gpio_init(PICO_DEFAULT_LED_PIN); + gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT); +#endif // PICO_DEFAULT_LED_PIN + +} // initLED() + +void waitForUsbConnect() { +#ifdef _PICO_STDIO_USB_H // We are using PICO_STDIO_USB. Have to wait for connection. + +#ifndef PICO_DEFAULT_LED_PIN + while (!stdio_usb_connected()) { // blink the pico's led until usb connection is established + cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 0); + sleep_ms(250); + cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 1); + sleep_ms(250); + } +#else + while (!stdio_usb_connected()) { // blink the pico's led until usb connection is established + gpio_put(PICO_DEFAULT_LED_PIN, 0); + sleep_ms(250); + gpio_put(PICO_DEFAULT_LED_PIN, 1); + sleep_ms(250); + } +#endif // PICO_DEFAULT_LED_PIN +#endif // _PICO_STDIO_USB_H +} // waitForUsbConnect + int main() { stdio_init_all(); // This example will use I2C0 on the default SDA and SCL (pins 6, 7 on a Pico) @@ -44,14 +83,9 @@ int main() { // Make the I2C pins available to picotool // setup blink led - gpio_init(PICO_DEFAULT_LED_PIN); - gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT); - while (!stdio_usb_connected()) { // blink the pico's led until usb connection is established - gpio_put(PICO_DEFAULT_LED_PIN, 1); - sleep_ms(250); - gpio_put(PICO_DEFAULT_LED_PIN, 0); - sleep_ms(250); - } + // setup blink led + initLED(); + waitForUsbConnect(); // ================================================================ // === INITIAL SETUP === diff --git a/RP2040/MPU6050/examples/mpu6050_calibration/CMakeLists.txt b/RP2040/MPU6050/examples/mpu6050_calibration/CMakeLists.txt index c25fd7bb..7429697e 100644 --- a/RP2040/MPU6050/examples/mpu6050_calibration/CMakeLists.txt +++ b/RP2040/MPU6050/examples/mpu6050_calibration/CMakeLists.txt @@ -1,21 +1,32 @@ # Generated Cmake Pico project file cmake_minimum_required(VERSION 3.13) - -set(CMAKE_C_STANDARD 11) -set(CMAKE_CXX_STANDARD 17) - -# Pull in Raspberry Pi Pico SDK (must be before project) +# Pull in SDK (must be before project) +# set(PICO_BOARD pico_w) # Needed only for PICO W +# set(CYW43_LWIP 1) # Needed only for PICO W include(pico_sdk_import.cmake) project(mpu6050_calibration C CXX ASM) +set(CMAKE_C_STANDARD 11) +set(CMAKE_CXX_STANDARD 17) # Initialise the Raspberry Pi Pico SDK pico_sdk_init() # Add executable. Default name is the project name, version 0.1 -add_executable(mpu6050_calibration mpu6050_calibration.cpp I2Cdev.cpp MPU6050.cpp ) +add_executable( mpu6050_calibration + mpu6050_calibration.cpp + MPU6050.cpp + I2Cdev.cpp + ) + +# Add any user requested libraries +target_link_libraries( mpu6050_calibration + pico_stdlib + # pico_cyw43_arch_none # we need Wifi to access the GPIO. Needed only for PICO W + hardware_i2c + ) pico_set_program_name(mpu6050_calibration "mpu6050_calibration") pico_set_program_version(mpu6050_calibration "0.1") @@ -23,13 +34,6 @@ pico_set_program_version(mpu6050_calibration "0.1") pico_enable_stdio_uart(mpu6050_calibration 0) pico_enable_stdio_usb(mpu6050_calibration 1) -# Add the standard library to the build -target_link_libraries(mpu6050_calibration pico_stdlib) - -# Add any user requested libraries -target_link_libraries(mpu6050_calibration - hardware_i2c - ) - -pico_add_extra_outputs(mpu6050_calibration) +# create map/bin/hex file etc. +pico_add_extra_outputs( mpu6050_calibration) diff --git a/RP2040/MPU6050/examples/mpu6050_calibration/mpu6050_calibration.cpp b/RP2040/MPU6050/examples/mpu6050_calibration/mpu6050_calibration.cpp index 987a1d2f..4ac496d6 100644 --- a/RP2040/MPU6050/examples/mpu6050_calibration/mpu6050_calibration.cpp +++ b/RP2040/MPU6050/examples/mpu6050_calibration/mpu6050_calibration.cpp @@ -1,6 +1,9 @@ #include #include "pico/stdlib.h" #include "hardware/i2c.h" +#ifndef PICO_DEFAULT_LED_PIN // PICO w with WiFi +#include "pico/cyw43_arch.h" +#endif #include "MPU6050.h" MPU6050 accelgyro; @@ -200,6 +203,42 @@ void PullBracketsOut(){ } // keep going } // PullBracketsOut +void initLED() { +#ifndef PICO_DEFAULT_LED_PIN // PICO w with WiFi + printf ("we have board with wifi (pico w) \n"); + if (cyw43_arch_init()) { + printf("WiFi init failed"); + exit(3); + } +#else + printf ("we have board without wifi\n"); + gpio_init(PICO_DEFAULT_LED_PIN); + gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT); +#endif // PICO_DEFAULT_LED_PIN + +} // initLED() + +void waitForUsbConnect() { +#ifdef _PICO_STDIO_USB_H // We are using PICO_STDIO_USB. Have to wait for connection. + +#ifndef PICO_DEFAULT_LED_PIN + while (!stdio_usb_connected()) { // blink the pico's led until usb connection is established + cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 0); + sleep_ms(250); + cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 1); + sleep_ms(250); + } +#else + while (!stdio_usb_connected()) { // blink the pico's led until usb connection is established + gpio_put(PICO_DEFAULT_LED_PIN, 0); + sleep_ms(250); + gpio_put(PICO_DEFAULT_LED_PIN, 1); + sleep_ms(250); + } +#endif // PICO_DEFAULT_LED_PIN +#endif // _PICO_STDIO_USB_H +} // waitForUsbConnect + int main() { stdio_init_all(); @@ -213,14 +252,8 @@ int main() gpio_pull_up(PICO_DEFAULT_I2C_SCL_PIN); // setup blink led - gpio_init(PICO_DEFAULT_LED_PIN); - gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT); - while (!stdio_usb_connected()) { // blink the pico's led until usb connection is established - gpio_put(PICO_DEFAULT_LED_PIN, 1); - sleep_ms(250); - gpio_put(PICO_DEFAULT_LED_PIN, 0); - sleep_ms(250); - } + initLED(); + waitForUsbConnect(); Initialize(); for (int i = iAx; i <= iGz; i++) From 19801c2a3b37917a7690775e5364180164c30706 Mon Sep 17 00:00:00 2001 From: naum Date: Sat, 3 Dec 2022 21:06:45 -0500 Subject: [PATCH 322/335] bug in I2Cdev::writeWords #726 I2Cdev::writeWords work incorrectly if len is greater than 1. --- RP2040/I2Cdev/I2Cdev.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RP2040/I2Cdev/I2Cdev.cpp b/RP2040/I2Cdev/I2Cdev.cpp index acfb8c2b..3958f182 100644 --- a/RP2040/I2Cdev/I2Cdev.cpp +++ b/RP2040/I2Cdev/I2Cdev.cpp @@ -320,7 +320,7 @@ bool I2Cdev::writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16 for(int i=0; i> 8; data_buf[j+1] = data[i]; - j++; + j += 2; } status = i2c_write_blocking(i2c_default, devAddr, data_buf, new_len, false); From 430122f19ddd58ea58d46223a6a0551b75485dd7 Mon Sep 17 00:00:00 2001 From: Sudarshan Patil <91423165+OptifySudarshanPatil@users.noreply.github.com> Date: Fri, 3 Feb 2023 14:11:20 +0530 Subject: [PATCH 323/335] Added Extra function for AD7745 --- Arduino/AD7746/AD7746.cpp | 4 ++++ Arduino/AD7746/AD7746.h | 1 + 2 files changed, 5 insertions(+) diff --git a/Arduino/AD7746/AD7746.cpp b/Arduino/AD7746/AD7746.cpp index bf56e68f..44a18f4f 100755 --- a/Arduino/AD7746/AD7746.cpp +++ b/Arduino/AD7746/AD7746.cpp @@ -132,3 +132,7 @@ void AD7746::writeCapDacARegister(uint8_t data) { void AD7746::writeCapDacBRegister(uint8_t data) { I2Cdev::writeByte(devAddr, AD7746_RA_CAP_DAC_B, data); } + +void AD7746::writeAD7745Register(uint8_t addr,uint8_t data) { + I2Cdev::writeByte(devAddr, addr, data); +} diff --git a/Arduino/AD7746/AD7746.h b/Arduino/AD7746/AD7746.h index 98c4160f..b1af7cdc 100755 --- a/Arduino/AD7746/AD7746.h +++ b/Arduino/AD7746/AD7746.h @@ -176,6 +176,7 @@ class AD7746 { void writeConfigurationRegister(uint8_t data); void writeCapDacARegister(uint8_t data); void writeCapDacBRegister(uint8_t data); + void writeAD7745Register(uint8_t addr,uint8_t data); private: From 17105a3067c949daf815591f2419e72d34ab75bf Mon Sep 17 00:00:00 2001 From: Sudarshan Patil <91423165+OptifySudarshanPatil@users.noreply.github.com> Date: Wed, 8 Feb 2023 18:16:00 +0530 Subject: [PATCH 324/335] renamed to generic name --- Arduino/AD7746/AD7746.cpp | 2 +- Arduino/AD7746/AD7746.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Arduino/AD7746/AD7746.cpp b/Arduino/AD7746/AD7746.cpp index 44a18f4f..dd019a59 100755 --- a/Arduino/AD7746/AD7746.cpp +++ b/Arduino/AD7746/AD7746.cpp @@ -133,6 +133,6 @@ void AD7746::writeCapDacBRegister(uint8_t data) { I2Cdev::writeByte(devAddr, AD7746_RA_CAP_DAC_B, data); } -void AD7746::writeAD7745Register(uint8_t addr,uint8_t data) { +void AD7746::write_register(uint8_t addr,uint8_t data) { I2Cdev::writeByte(devAddr, addr, data); } diff --git a/Arduino/AD7746/AD7746.h b/Arduino/AD7746/AD7746.h index b1af7cdc..6b69f254 100755 --- a/Arduino/AD7746/AD7746.h +++ b/Arduino/AD7746/AD7746.h @@ -176,7 +176,7 @@ class AD7746 { void writeConfigurationRegister(uint8_t data); void writeCapDacARegister(uint8_t data); void writeCapDacBRegister(uint8_t data); - void writeAD7745Register(uint8_t addr,uint8_t data); + void write_register(uint8_t addr,uint8_t data); private: From 2a0d98f709bbf3a3c052aa8d73f74d30295e5689 Mon Sep 17 00:00:00 2001 From: Jeff Rowberg Date: Sat, 25 Feb 2023 13:42:48 -0500 Subject: [PATCH 325/335] Bump PlatformIO version for I2Cdev core to 1.0.1 --- Arduino/I2Cdev/library.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Arduino/I2Cdev/library.json b/Arduino/I2Cdev/library.json index 87a6d879..336e9d06 100644 --- a/Arduino/I2Cdev/library.json +++ b/Arduino/I2Cdev/library.json @@ -1,6 +1,6 @@ { "name": "I2Cdevlib-Core", - "version": "1.0.0", + "version": "1.0.1", "keywords": "i2cdevlib, i2c", "description": "The I2C Device Library (I2Cdevlib) is a collection of uniform and well-documented classes to provide simple and intuitive interfaces to I2C devices.", "include": "Arduino/I2Cdev", From 10d0877dcb0282e68e94ca827af8ff7fcf39731f Mon Sep 17 00:00:00 2001 From: nekomona Date: Sun, 28 May 2023 21:37:08 +0800 Subject: [PATCH 326/335] Fix count overflow on readBytes/readWords --- Arduino/I2Cdev/I2Cdev.cpp | 4 ++-- Arduino/IAQ2000/IAQ2000.cpp | 2 +- MSP430/I2Cdev/I2Cdev.cpp | 4 ++-- PIC18/I2Cdev/I2Cdev.c | 4 ++-- RP2040/I2Cdev/I2Cdev.cpp | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Arduino/I2Cdev/I2Cdev.cpp b/Arduino/I2Cdev/I2Cdev.cpp index 233e4099..40b5dfc4 100644 --- a/Arduino/I2Cdev/I2Cdev.cpp +++ b/Arduino/I2Cdev/I2Cdev.cpp @@ -217,7 +217,7 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 Serial.print("..."); #endif - int8_t count = 0; + uint8_t count = 0; uint32_t t1 = millis(); #if (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE) @@ -329,7 +329,7 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 Serial.print("..."); #endif - int8_t count = 0; + uint8_t count = 0; uint32_t t1 = millis(); #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE diff --git a/Arduino/IAQ2000/IAQ2000.cpp b/Arduino/IAQ2000/IAQ2000.cpp index e3a2cdfc..8e44b9cb 100755 --- a/Arduino/IAQ2000/IAQ2000.cpp +++ b/Arduino/IAQ2000/IAQ2000.cpp @@ -113,7 +113,7 @@ int8_t IAQ2000::readAllBytes(uint8_t devAddr, uint8_t length, uint8_t *data, uin Serial.print(" bytes..."); #endif - int8_t count = 0; + uint8_t count = 0; Wire.requestFrom(devAddr, length); diff --git a/MSP430/I2Cdev/I2Cdev.cpp b/MSP430/I2Cdev/I2Cdev.cpp index 6e539f79..cbc0fbe0 100644 --- a/MSP430/I2Cdev/I2Cdev.cpp +++ b/MSP430/I2Cdev/I2Cdev.cpp @@ -215,7 +215,7 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 Serial.print("..."); #endif - int8_t count = 0; + uint8_t count = 0; uint32_t t1 = millis(); #if (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE) @@ -330,7 +330,7 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 Serial.print("..."); #endif - int8_t count = 0; + uint8_t count = 0; uint32_t t1 = millis(); #if (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE) diff --git a/PIC18/I2Cdev/I2Cdev.c b/PIC18/I2Cdev/I2Cdev.c index d8082e33..1d865343 100644 --- a/PIC18/I2Cdev/I2Cdev.c +++ b/PIC18/I2Cdev/I2Cdev.c @@ -41,7 +41,7 @@ THE SOFTWARE. * @return Number of bytes read (-1 indicates failure) */ int8_t I2Cdev_readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data) { - int8_t count = 0; + uint8_t count = 0; // S IdleI2C(); @@ -104,7 +104,7 @@ int8_t I2Cdev_readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data) { * @return Number of words read (-1 indicates failure) */ int8_t I2Cdev_readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data) { - int8_t count = 0; + uint8_t count = 0; // S IdleI2C(); diff --git a/RP2040/I2Cdev/I2Cdev.cpp b/RP2040/I2Cdev/I2Cdev.cpp index 55893802..0452d79d 100644 --- a/RP2040/I2Cdev/I2Cdev.cpp +++ b/RP2040/I2Cdev/I2Cdev.cpp @@ -149,7 +149,7 @@ int8_t I2Cdev::readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data, uint32 * @return Number of bytes read (-1 indicates failure) */ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data, uint32_t timeout) { - int8_t count = 0; + uint8_t count = 0; i2c_write_blocking(i2c_default, devAddr, ®Addr, 1, true); count = i2c_read_timeout_us(i2c_default, devAddr, data, length, false, timeout * 1000); @@ -166,7 +166,7 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 * @return Number of words read (-1 indicates failure) */ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data, uint32_t timeout) { - int8_t count = 0; + uint8_t count = 0; uint8_t data_buf[length*2]; i2c_write_blocking(i2c_default, devAddr, ®Addr, 1, true); From 655dffb0bf6e8f28b8d8a1103edd94f70400e90e Mon Sep 17 00:00:00 2001 From: Hananja from Raspberry Pi Zero 2 W Date: Thu, 1 Feb 2024 09:01:52 +0100 Subject: [PATCH 327/335] Copy Arduino I2Cdev --- LinuxI2CDev/I2Cdev/I2Cdev.cpp | 1469 +++++++++++++++++++++++++++++++++ LinuxI2CDev/I2Cdev/I2Cdev.h | 311 +++++++ 2 files changed, 1780 insertions(+) create mode 100644 LinuxI2CDev/I2Cdev/I2Cdev.cpp create mode 100644 LinuxI2CDev/I2Cdev/I2Cdev.h diff --git a/LinuxI2CDev/I2Cdev/I2Cdev.cpp b/LinuxI2CDev/I2Cdev/I2Cdev.cpp new file mode 100644 index 00000000..40b5dfc4 --- /dev/null +++ b/LinuxI2CDev/I2Cdev/I2Cdev.cpp @@ -0,0 +1,1469 @@ +// I2Cdev library collection - Main I2C device class +// Abstracts bit and byte I2C R/W functions into a convenient class +// 2013-06-05 by Jeff Rowberg +// +// Changelog: +// 2021-09-28 - allow custom Wire object as transaction function argument +// 2020-01-20 - hardija : complete support for Teensy 3.x +// 2015-10-30 - simondlevy : support i2c_t3 for Teensy3.1 +// 2013-05-06 - add Francesco Ferrara's Fastwire v0.24 implementation with small modifications +// 2013-05-05 - fix issue with writing bit values to words (Sasquatch/Farzanegan) +// 2012-06-09 - fix major issue with reading > 32 bytes at a time with Arduino Wire +// - add compiler warnings when using outdated or IDE or limited I2Cdev implementation +// 2011-11-01 - fix write*Bits mask calculation (thanks sasquatch @ Arduino forums) +// 2011-10-03 - added automatic Arduino version detection for ease of use +// 2011-10-02 - added Gene Knight's NBWire TwoWire class implementation with small modifications +// 2011-08-31 - added support for Arduino 1.0 Wire library (methods are different from 0.x) +// 2011-08-03 - added optional timeout parameter to read* methods to easily change from default +// 2011-08-02 - added support for 16-bit registers +// - fixed incorrect Doxygen comments on some methods +// - added timeout value for read operations (thanks mem @ Arduino forums) +// 2011-07-30 - changed read/write function structures to return success or byte counts +// - made all methods static for multi-device memory savings +// 2011-07-28 - initial release + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2013 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#include "I2Cdev.h" + +#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE + + #ifdef I2CDEV_IMPLEMENTATION_WARNINGS + #if ARDUINO < 100 + #warning Using outdated Arduino IDE with Wire library is functionally limiting. + #warning Arduino IDE v1.6.5+ with I2Cdev Fastwire implementation is recommended. + #warning This I2Cdev implementation does not support: + #warning - Repeated starts conditions + #warning - Timeout detection (some Wire requests block forever) + #elif ARDUINO == 100 + #warning Using outdated Arduino IDE with Wire library is functionally limiting. + #warning Arduino IDE v1.6.5+ with I2Cdev Fastwire implementation is recommended. + #warning This I2Cdev implementation does not support: + #warning - Repeated starts conditions + #warning - Timeout detection (some Wire requests block forever) + #elif ARDUINO > 100 + /*#warning Using current Arduino IDE with Wire library is functionally limiting. + #warning Arduino IDE v1.6.5+ with I2CDEV_BUILTIN_FASTWIRE implementation is recommended. + #warning This I2Cdev implementation does not support: + #warning - Timeout detection (some Wire requests block forever)*/ + #endif + #endif + +#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE + + //#error The I2CDEV_BUILTIN_FASTWIRE implementation is known to be broken right now. Patience, Iago! + +#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE + + #ifdef I2CDEV_IMPLEMENTATION_WARNINGS + #warning Using I2CDEV_BUILTIN_NBWIRE implementation may adversely affect interrupt detection. + #warning This I2Cdev implementation does not support: + #warning - Repeated starts conditions + #endif + + // NBWire implementation based heavily on code by Gene Knight + // Originally posted on the Arduino forum at http://arduino.cc/forum/index.php/topic,70705.0.html + // Originally offered to the i2cdevlib project at http://arduino.cc/forum/index.php/topic,68210.30.html + TwoWire Wire; + +#endif + +/** Default constructor. + */ +I2Cdev::I2Cdev() { +} + +/** Read a single bit from an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param bitNum Bit position to read (0-7) + * @param data Container for single bit value + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) + * @return Status of read operation (true = success) + */ +int8_t I2Cdev::readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data, uint16_t timeout, void *wireObj) { + uint8_t b; + uint8_t count = readByte(devAddr, regAddr, &b, timeout, wireObj); + *data = b & (1 << bitNum); + return count; +} + +/** Read a single bit from a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param bitNum Bit position to read (0-15) + * @param data Container for single bit value + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) + * @return Status of read operation (true = success) + */ +int8_t I2Cdev::readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data, uint16_t timeout, void *wireObj) { + uint16_t b; + uint8_t count = readWord(devAddr, regAddr, &b, timeout, wireObj); + *data = b & (1 << bitNum); + return count; +} + +/** Read multiple bits from an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param bitStart First bit position to read (0-7) + * @param length Number of bits to read (not more than 8) + * @param data Container for right-aligned value (i.e. '101' read from any bitStart position will equal 0x05) + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) + * @return Status of read operation (true = success) + */ +int8_t I2Cdev::readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data, uint16_t timeout, void *wireObj) { + // 01101001 read byte + // 76543210 bit numbers + // xxx args: bitStart=4, length=3 + // 010 masked + // -> 010 shifted + uint8_t count, b; + if ((count = readByte(devAddr, regAddr, &b, timeout, wireObj)) != 0) { + uint8_t mask = ((1 << length) - 1) << (bitStart - length + 1); + b &= mask; + b >>= (bitStart - length + 1); + *data = b; + } + return count; +} + +/** Read multiple bits from a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param bitStart First bit position to read (0-15) + * @param length Number of bits to read (not more than 16) + * @param data Container for right-aligned value (i.e. '101' read from any bitStart position will equal 0x05) + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) + * @return Status of read operation (1 = success, 0 = failure, -1 = timeout) + */ +int8_t I2Cdev::readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t *data, uint16_t timeout, void *wireObj) { + // 1101011001101001 read byte + // fedcba9876543210 bit numbers + // xxx args: bitStart=12, length=3 + // 010 masked + // -> 010 shifted + uint8_t count; + uint16_t w; + if ((count = readWord(devAddr, regAddr, &w, timeout, wireObj)) != 0) { + uint16_t mask = ((1 << length) - 1) << (bitStart - length + 1); + w &= mask; + w >>= (bitStart - length + 1); + *data = w; + } + return count; +} + +/** Read single byte from an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param data Container for byte value read from device + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) + * @return Status of read operation (true = success) + */ +int8_t I2Cdev::readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint16_t timeout, void *wireObj) { + return readBytes(devAddr, regAddr, 1, data, timeout, wireObj); +} + +/** Read single word from a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param data Container for word value read from device + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) + * @return Status of read operation (true = success) + */ +int8_t I2Cdev::readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data, uint16_t timeout, void *wireObj) { + return readWords(devAddr, regAddr, 1, data, timeout, wireObj); +} + +/** Read multiple bytes from an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr First register regAddr to read from + * @param length Number of bytes to read + * @param data Buffer to store read data in + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) + * @return Number of bytes read (-1 indicates failure) + */ +int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data, uint16_t timeout, void *wireObj) { + #ifdef I2CDEV_SERIAL_DEBUG + Serial.print("I2C (0x"); + Serial.print(devAddr, HEX); + Serial.print(") reading "); + Serial.print(length, DEC); + Serial.print(" bytes from 0x"); + Serial.print(regAddr, HEX); + Serial.print("..."); + #endif + + uint8_t count = 0; + uint32_t t1 = millis(); + + #if (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE) + TwoWire *useWire = &Wire; + if (wireObj) useWire = (TwoWire *)wireObj; + + #if (ARDUINO < 100) + // Arduino v00xx (before v1.0), Wire library + + // I2C/TWI subsystem uses internal buffer that breaks with large data requests + // so if user requests more than I2CDEVLIB_WIRE_BUFFER_LENGTH bytes, we have to do it in + // smaller chunks instead of all at once + for (int k = 0; k < length; k += min((int)length, I2CDEVLIB_WIRE_BUFFER_LENGTH)) { + useWire->beginTransmission(devAddr); + useWire->send(regAddr); + useWire->endTransmission(); + useWire->requestFrom((uint8_t)devAddr, (uint8_t)min((int)length - k, I2CDEVLIB_WIRE_BUFFER_LENGTH)); + for (; useWire->available() && (timeout == 0 || millis() - t1 < timeout); count++) { + data[count] = useWire->receive(); + #ifdef I2CDEV_SERIAL_DEBUG + Serial.print(data[count], HEX); + if (count + 1 < length) Serial.print(" "); + #endif + } + } + #elif (ARDUINO == 100) + // Arduino v1.0.0, Wire library + // Adds standardized write() and read() stream methods instead of send() and receive() + + // I2C/TWI subsystem uses internal buffer that breaks with large data requests + // so if user requests more than I2CDEVLIB_WIRE_BUFFER_LENGTH bytes, we have to do it in + // smaller chunks instead of all at once + for (int k = 0; k < length; k += min((int)length, I2CDEVLIB_WIRE_BUFFER_LENGTH)) { + useWire->beginTransmission(devAddr); + useWire->write(regAddr); + useWire->endTransmission(); + useWire->requestFrom((uint8_t)devAddr, (uint8_t)min((int)length - k, I2CDEVLIB_WIRE_BUFFER_LENGTH)); + for (; useWire->available() && (timeout == 0 || millis() - t1 < timeout); count++) { + data[count] = useWire->read(); + #ifdef I2CDEV_SERIAL_DEBUG + Serial.print(data[count], HEX); + if (count + 1 < length) Serial.print(" "); + #endif + } + } + #elif (ARDUINO > 100) + // Arduino v1.0.1+, Wire library + // Adds official support for repeated start condition, yay! + + // I2C/TWI subsystem uses internal buffer that breaks with large data requests + // so if user requests more than I2CDEVLIB_WIRE_BUFFER_LENGTH bytes, we have to do it in + // smaller chunks instead of all at once + for (int k = 0; k < length; k += min((int)length, I2CDEVLIB_WIRE_BUFFER_LENGTH)) { + useWire->beginTransmission(devAddr); + useWire->write(regAddr); + useWire->endTransmission(); + useWire->requestFrom((uint8_t)devAddr, (uint8_t)min((int)length - k, I2CDEVLIB_WIRE_BUFFER_LENGTH)); + for (; useWire->available() && (timeout == 0 || millis() - t1 < timeout); count++) { + data[count] = useWire->read(); + #ifdef I2CDEV_SERIAL_DEBUG + Serial.print(data[count], HEX); + if (count + 1 < length) Serial.print(" "); + #endif + } + } + #endif + + #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) + + // Fastwire library + // no loop required for fastwire + uint8_t status = Fastwire::readBuf(devAddr << 1, regAddr, data, length); + if (status == 0) { + count = length; // success + } else { + count = -1; // error + } + + #endif + + // check for timeout + if (timeout > 0 && millis() - t1 >= timeout && count < length) count = -1; // timeout + + #ifdef I2CDEV_SERIAL_DEBUG + Serial.print(". Done ("); + Serial.print(count, DEC); + Serial.println(" read)."); + #endif + + return count; +} + +/** Read multiple words from a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr First register regAddr to read from + * @param length Number of words to read + * @param data Buffer to store read data in + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) + * @return Number of words read (-1 indicates failure) + */ +int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data, uint16_t timeout, void *wireObj) { + #ifdef I2CDEV_SERIAL_DEBUG + Serial.print("I2C (0x"); + Serial.print(devAddr, HEX); + Serial.print(") reading "); + Serial.print(length, DEC); + Serial.print(" words from 0x"); + Serial.print(regAddr, HEX); + Serial.print("..."); + #endif + + uint8_t count = 0; + uint32_t t1 = millis(); + +#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE + TwoWire *useWire = &Wire; + if (wireObj) useWire = (TwoWire *)wireObj; + + #if (ARDUINO < 100) + // Arduino v00xx (before v1.0), Wire library + + // I2C/TWI subsystem uses internal buffer that breaks with large data requests + // so if user requests more than I2CDEVLIB_WIRE_BUFFER_LENGTH bytes, we have to do it in + // smaller chunks instead of all at once + for (uint8_t k = 0; k < length * 2; k += min(length * 2, I2CDEVLIB_WIRE_BUFFER_LENGTH)) { + useWire->beginTransmission(devAddr); + useWire->send(regAddr); + useWire->endTransmission(); + useWire->requestFrom(devAddr, (uint8_t)(length * 2)); // length=words, this wants bytes + + bool msb = true; // starts with MSB, then LSB + for (; useWire->available() && count < length && (timeout == 0 || millis() - t1 < timeout);) { + if (msb) { + // first byte is bits 15-8 (MSb=15) + data[count] = useWire->receive() << 8; + } else { + // second byte is bits 7-0 (LSb=0) + data[count] |= useWire->receive(); + #ifdef I2CDEV_SERIAL_DEBUG + Serial.print(data[count], HEX); + if (count + 1 < length) Serial.print(" "); + #endif + count++; + } + msb = !msb; + } + } + #elif (ARDUINO == 100) + // Arduino v1.0.0, Wire library + // Adds standardized write() and read() stream methods instead of send() and receive() + + // I2C/TWI subsystem uses internal buffer that breaks with large data requests + // so if user requests more than I2CDEVLIB_WIRE_BUFFER_LENGTH bytes, we have to do it in + // smaller chunks instead of all at once + for (uint8_t k = 0; k < length * 2; k += min(length * 2, I2CDEVLIB_WIRE_BUFFER_LENGTH)) { + useWire->beginTransmission(devAddr); + useWire->write(regAddr); + useWire->endTransmission(); + useWire->requestFrom(devAddr, (uint8_t)(length * 2)); // length=words, this wants bytes + + bool msb = true; // starts with MSB, then LSB + for (; useWire->available() && count < length && (timeout == 0 || millis() - t1 < timeout);) { + if (msb) { + // first byte is bits 15-8 (MSb=15) + data[count] = useWire->read() << 8; + } else { + // second byte is bits 7-0 (LSb=0) + data[count] |= useWire->read(); + #ifdef I2CDEV_SERIAL_DEBUG + Serial.print(data[count], HEX); + if (count + 1 < length) Serial.print(" "); + #endif + count++; + } + msb = !msb; + } + } + #elif (ARDUINO > 100) + // Arduino v1.0.1+, Wire library + // Adds official support for repeated start condition, yay! + + // I2C/TWI subsystem uses internal buffer that breaks with large data requests + // so if user requests more than I2CDEVLIB_WIRE_BUFFER_LENGTH bytes, we have to do it in + // smaller chunks instead of all at once + for (uint8_t k = 0; k < length * 2; k += min(length * 2, I2CDEVLIB_WIRE_BUFFER_LENGTH)) { + useWire->beginTransmission(devAddr); + useWire->write(regAddr); + useWire->endTransmission(); + useWire->requestFrom(devAddr, (uint8_t)(length * 2)); // length=words, this wants bytes + + bool msb = true; // starts with MSB, then LSB + for (; useWire->available() && count < length && (timeout == 0 || millis() - t1 < timeout);) { + if (msb) { + // first byte is bits 15-8 (MSb=15) + data[count] = useWire->read() << 8; + } else { + // second byte is bits 7-0 (LSb=0) + data[count] |= useWire->read(); + #ifdef I2CDEV_SERIAL_DEBUG + Serial.print(data[count], HEX); + if (count + 1 < length) Serial.print(" "); + #endif + count++; + } + msb = !msb; + } + } + #endif + + #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) + + // Fastwire library + // no loop required for fastwire + uint8_t intermediate[(uint8_t)length*2]; + uint8_t status = Fastwire::readBuf(devAddr << 1, regAddr, intermediate, (uint8_t)(length * 2)); + if (status == 0) { + count = length; // success + for (uint8_t i = 0; i < length; i++) { + data[i] = (intermediate[2*i] << 8) | intermediate[2*i + 1]; + } + } else { + count = -1; // error + } + + #endif + + if (timeout > 0 && millis() - t1 >= timeout && count < length) count = -1; // timeout + + #ifdef I2CDEV_SERIAL_DEBUG + Serial.print(". Done ("); + Serial.print(count, DEC); + Serial.println(" read)."); + #endif + + return count; +} + +/** write a single bit in an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to write to + * @param bitNum Bit position to write (0-7) + * @param value New bit value to write + * @return Status of operation (true = success) + */ +bool I2Cdev::writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t data, void *wireObj) { + uint8_t b; + readByte(devAddr, regAddr, &b, I2Cdev::readTimeout, wireObj); + b = (data != 0) ? (b | (1 << bitNum)) : (b & ~(1 << bitNum)); + return writeByte(devAddr, regAddr, b, wireObj); +} + +/** write a single bit in a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to write to + * @param bitNum Bit position to write (0-15) + * @param value New bit value to write + * @return Status of operation (true = success) + */ +bool I2Cdev::writeBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t data, void *wireObj) { + uint16_t w; + readWord(devAddr, regAddr, &w, I2Cdev::readTimeout, wireObj); + w = (data != 0) ? (w | (1 << bitNum)) : (w & ~(1 << bitNum)); + return writeWord(devAddr, regAddr, w, wireObj); +} + +/** Write multiple bits in an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to write to + * @param bitStart First bit position to write (0-7) + * @param length Number of bits to write (not more than 8) + * @param data Right-aligned value to write + * @return Status of operation (true = success) + */ +bool I2Cdev::writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data, void *wireObj) { + // 010 value to write + // 76543210 bit numbers + // xxx args: bitStart=4, length=3 + // 00011100 mask byte + // 10101111 original value (sample) + // 10100011 original & ~mask + // 10101011 masked | value + uint8_t b; + if (readByte(devAddr, regAddr, &b, I2Cdev::readTimeout, wireObj) != 0) { + uint8_t mask = ((1 << length) - 1) << (bitStart - length + 1); + data <<= (bitStart - length + 1); // shift data into correct position + data &= mask; // zero all non-important bits in data + b &= ~(mask); // zero all important bits in existing byte + b |= data; // combine data with existing byte + return writeByte(devAddr, regAddr, b, wireObj); + } else { + return false; + } +} + +/** Write multiple bits in a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to write to + * @param bitStart First bit position to write (0-15) + * @param length Number of bits to write (not more than 16) + * @param data Right-aligned value to write + * @return Status of operation (true = success) + */ +bool I2Cdev::writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t data, void *wireObj) { + // 010 value to write + // fedcba9876543210 bit numbers + // xxx args: bitStart=12, length=3 + // 0001110000000000 mask word + // 1010111110010110 original value (sample) + // 1010001110010110 original & ~mask + // 1010101110010110 masked | value + uint16_t w; + if (readWord(devAddr, regAddr, &w, I2Cdev::readTimeout, wireObj) != 0) { + uint16_t mask = ((1 << length) - 1) << (bitStart - length + 1); + data <<= (bitStart - length + 1); // shift data into correct position + data &= mask; // zero all non-important bits in data + w &= ~(mask); // zero all important bits in existing word + w |= data; // combine data with existing word + return writeWord(devAddr, regAddr, w, wireObj); + } else { + return false; + } +} + +/** Write single byte to an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register address to write to + * @param data New byte value to write + * @return Status of operation (true = success) + */ +bool I2Cdev::writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data, void *wireObj) { + return writeBytes(devAddr, regAddr, 1, &data, wireObj); +} + +/** Write single word to a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register address to write to + * @param data New word value to write + * @return Status of operation (true = success) + */ +bool I2Cdev::writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data, void *wireObj) { + return writeWords(devAddr, regAddr, 1, &data, wireObj); +} + +/** Write multiple bytes to an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr First register address to write to + * @param length Number of bytes to write + * @param data Buffer to copy new data from + * @return Status of operation (true = success) + */ +bool I2Cdev::writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t* data, void *wireObj) { + #ifdef I2CDEV_SERIAL_DEBUG + Serial.print("I2C (0x"); + Serial.print(devAddr, HEX); + Serial.print(") writing "); + Serial.print(length, DEC); + Serial.print(" bytes to 0x"); + Serial.print(regAddr, HEX); + Serial.print("..."); + #endif + uint8_t status = 0; + +#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE + TwoWire *useWire = &Wire; + if (wireObj) useWire = (TwoWire *)wireObj; +#endif + + #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) + useWire->beginTransmission(devAddr); + useWire->send((uint8_t) regAddr); // send address + #elif ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) \ + || (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) \ + || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE) + useWire->beginTransmission(devAddr); + useWire->write((uint8_t) regAddr); // send address + #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) + Fastwire::beginTransmission(devAddr); + Fastwire::write(regAddr); + #endif + for (uint8_t i = 0; i < length; i++) { + #ifdef I2CDEV_SERIAL_DEBUG + Serial.print(data[i], HEX); + if (i + 1 < length) Serial.print(" "); + #endif + #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) + useWire->send((uint8_t) data[i]); + #elif ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) \ + || (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) \ + || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE) + useWire->write((uint8_t) data[i]); + #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) + Fastwire::write((uint8_t) data[i]); + #endif + } + #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) + useWire->endTransmission(); + #elif ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) \ + || (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) \ + || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE) + status = useWire->endTransmission(); + #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) + Fastwire::stop(); + //status = Fastwire::endTransmission(); + #endif + #ifdef I2CDEV_SERIAL_DEBUG + Serial.println(". Done."); + #endif + return status == 0; +} + +/** Write multiple words to a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr First register address to write to + * @param length Number of words to write + * @param data Buffer to copy new data from + * @return Status of operation (true = success) + */ +bool I2Cdev::writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t* data, void *wireObj) { + #ifdef I2CDEV_SERIAL_DEBUG + Serial.print("I2C (0x"); + Serial.print(devAddr, HEX); + Serial.print(") writing "); + Serial.print(length, DEC); + Serial.print(" words to 0x"); + Serial.print(regAddr, HEX); + Serial.print("..."); + #endif + uint8_t status = 0; + +#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE + TwoWire *useWire = &Wire; + if (wireObj) useWire = (TwoWire *)wireObj; +#endif + + #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) + useWire->beginTransmission(devAddr); + useWire->send(regAddr); // send address + #elif ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) \ + || (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) \ + || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE) + useWire->beginTransmission(devAddr); + useWire->write(regAddr); // send address + #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) + Fastwire::beginTransmission(devAddr); + Fastwire::write(regAddr); + #endif + for (uint8_t i = 0; i < length; i++) { + #ifdef I2CDEV_SERIAL_DEBUG + Serial.print(data[i], HEX); + if (i + 1 < length) Serial.print(" "); + #endif + #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) + useWire->send((uint8_t)(data[i] >> 8)); // send MSB + useWire->send((uint8_t)data[i]); // send LSB + #elif ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) \ + || (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) \ + || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE) + useWire->write((uint8_t)(data[i] >> 8)); // send MSB + useWire->write((uint8_t)data[i]); // send LSB + #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) + Fastwire::write((uint8_t)(data[i] >> 8)); // send MSB + status = Fastwire::write((uint8_t)data[i]); // send LSB + if (status != 0) break; + #endif + } + #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) + useWire->endTransmission(); + #elif ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) \ + || (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) \ + || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE) + status = useWire->endTransmission(); + #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) + Fastwire::stop(); + //status = Fastwire::endTransmission(); + #endif + #ifdef I2CDEV_SERIAL_DEBUG + Serial.println(". Done."); + #endif + return status == 0; +} + +/** Default timeout value for read operations. + * Set this to 0 to disable timeout detection. + */ +uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; + +#if I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE + // I2C library + ////////////////////// + // Copyright(C) 2012 + // Francesco Ferrara + // ferrara[at]libero[point]it + ////////////////////// + + /* + FastWire + - 0.24 added stop + - 0.23 added reset + + This is a library to help faster programs to read I2C devices. + Copyright(C) 2012 Francesco Ferrara + occhiobello at gmail dot com + [used by Jeff Rowberg for I2Cdevlib with permission] + */ + + boolean Fastwire::waitInt() { + int l = 250; + while (!(TWCR & (1 << TWINT)) && l-- > 0); + return l > 0; + } + + void Fastwire::setup(int khz, boolean pullup) { + TWCR = 0; + #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega328P__) + // activate internal pull-ups for twi (PORTC bits 4 & 5) + // as per note from atmega8 manual pg167 + if (pullup) PORTC |= ((1 << 4) | (1 << 5)); + else PORTC &= ~((1 << 4) | (1 << 5)); + #elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__) + // activate internal pull-ups for twi (PORTC bits 0 & 1) + if (pullup) PORTC |= ((1 << 0) | (1 << 1)); + else PORTC &= ~((1 << 0) | (1 << 1)); + #else + // activate internal pull-ups for twi (PORTD bits 0 & 1) + // as per note from atmega128 manual pg204 + if (pullup) PORTD |= ((1 << 0) | (1 << 1)); + else PORTD &= ~((1 << 0) | (1 << 1)); + #endif + + TWSR = 0; // no prescaler => prescaler = 1 + TWBR = F_CPU / 2000 / khz - 8; // change the I2C clock rate + TWCR = 1 << TWEN; // enable twi module, no interrupt + } + + // added by Jeff Rowberg 2013-05-07: + // Arduino Wire-style "beginTransmission" function + // (takes 7-bit device address like the Wire method, NOT 8-bit: 0x68, not 0xD0/0xD1) + byte Fastwire::beginTransmission(byte device) { + byte twst, retry; + retry = 2; + do { + TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO) | (1 << TWSTA); + if (!waitInt()) return 1; + twst = TWSR & 0xF8; + if (twst != TW_START && twst != TW_REP_START) return 2; + + //Serial.print(device, HEX); + //Serial.print(" "); + TWDR = device << 1; // send device address without read bit (1) + TWCR = (1 << TWINT) | (1 << TWEN); + if (!waitInt()) return 3; + twst = TWSR & 0xF8; + } while (twst == TW_MT_SLA_NACK && retry-- > 0); + if (twst != TW_MT_SLA_ACK) return 4; + return 0; + } + + byte Fastwire::writeBuf(byte device, byte address, byte *data, byte num) { + byte twst, retry; + + retry = 2; + do { + TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO) | (1 << TWSTA); + if (!waitInt()) return 1; + twst = TWSR & 0xF8; + if (twst != TW_START && twst != TW_REP_START) return 2; + + //Serial.print(device, HEX); + //Serial.print(" "); + TWDR = device & 0xFE; // send device address without read bit (1) + TWCR = (1 << TWINT) | (1 << TWEN); + if (!waitInt()) return 3; + twst = TWSR & 0xF8; + } while (twst == TW_MT_SLA_NACK && retry-- > 0); + if (twst != TW_MT_SLA_ACK) return 4; + + //Serial.print(address, HEX); + //Serial.print(" "); + TWDR = address; // send data to the previously addressed device + TWCR = (1 << TWINT) | (1 << TWEN); + if (!waitInt()) return 5; + twst = TWSR & 0xF8; + if (twst != TW_MT_DATA_ACK) return 6; + + for (byte i = 0; i < num; i++) { + //Serial.print(data[i], HEX); + //Serial.print(" "); + TWDR = data[i]; // send data to the previously addressed device + TWCR = (1 << TWINT) | (1 << TWEN); + if (!waitInt()) return 7; + twst = TWSR & 0xF8; + if (twst != TW_MT_DATA_ACK) return 8; + } + //Serial.print("\n"); + + return 0; + } + + byte Fastwire::write(byte value) { + byte twst; + //Serial.println(value, HEX); + TWDR = value; // send data + TWCR = (1 << TWINT) | (1 << TWEN); + if (!waitInt()) return 1; + twst = TWSR & 0xF8; + if (twst != TW_MT_DATA_ACK) return 2; + return 0; + } + + byte Fastwire::readBuf(byte device, byte address, byte *data, byte num) { + byte twst, retry; + + retry = 2; + do { + TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO) | (1 << TWSTA); + if (!waitInt()) return 16; + twst = TWSR & 0xF8; + if (twst != TW_START && twst != TW_REP_START) return 17; + + //Serial.print(device, HEX); + //Serial.print(" "); + TWDR = device & 0xfe; // send device address to write + TWCR = (1 << TWINT) | (1 << TWEN); + if (!waitInt()) return 18; + twst = TWSR & 0xF8; + } while (twst == TW_MT_SLA_NACK && retry-- > 0); + if (twst != TW_MT_SLA_ACK) return 19; + + //Serial.print(address, HEX); + //Serial.print(" "); + TWDR = address; // send data to the previously addressed device + TWCR = (1 << TWINT) | (1 << TWEN); + if (!waitInt()) return 20; + twst = TWSR & 0xF8; + if (twst != TW_MT_DATA_ACK) return 21; + + /***/ + + retry = 2; + do { + TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO) | (1 << TWSTA); + if (!waitInt()) return 22; + twst = TWSR & 0xF8; + if (twst != TW_START && twst != TW_REP_START) return 23; + + //Serial.print(device, HEX); + //Serial.print(" "); + TWDR = device | 0x01; // send device address with the read bit (1) + TWCR = (1 << TWINT) | (1 << TWEN); + if (!waitInt()) return 24; + twst = TWSR & 0xF8; + } while (twst == TW_MR_SLA_NACK && retry-- > 0); + if (twst != TW_MR_SLA_ACK) return 25; + + for (uint8_t i = 0; i < num; i++) { + if (i == num - 1) + TWCR = (1 << TWINT) | (1 << TWEN); + else + TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA); + if (!waitInt()) return 26; + twst = TWSR & 0xF8; + if (twst != TW_MR_DATA_ACK && twst != TW_MR_DATA_NACK) return twst; + data[i] = TWDR; + //Serial.print(data[i], HEX); + //Serial.print(" "); + } + //Serial.print("\n"); + stop(); + + return 0; + } + + void Fastwire::reset() { + TWCR = 0; + } + + byte Fastwire::stop() { + TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO); + if (!waitInt()) return 1; + return 0; + } +#endif + +#if I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE + // NBWire implementation based heavily on code by Gene Knight + // Originally posted on the Arduino forum at http://arduino.cc/forum/index.php/topic,70705.0.html + // Originally offered to the i2cdevlib project at http://arduino.cc/forum/index.php/topic,68210.30.html + + /* + call this version 1.0 + + Offhand, the only funky part that I can think of is in nbrequestFrom, where the buffer + length and index are set *before* the data is actually read. The problem is that these + are variables local to the TwoWire object, and by the time we actually have read the + data, and know what the length actually is, we have no simple access to the object's + variables. The actual bytes read *is* given to the callback function, though. + + The ISR code for a slave receiver is commented out. I don't have that setup, and can't + verify it at this time. Save it for 2.0! + + The handling of the read and write processes here is much like in the demo sketch code: + the process is broken down into sequential functions, where each registers the next as a + callback, essentially. + + For example, for the Read process, twi_read00 just returns if TWI is not yet in a + ready state. When there's another interrupt, and the interface *is* ready, then it + sets up the read, starts it, and registers twi_read01 as the function to call after + the *next* interrupt. twi_read01, then, just returns if the interface is still in a + "reading" state. When the reading is done, it copies the information to the buffer, + cleans up, and calls the user-requested callback function with the actual number of + bytes read. + + The writing is similar. + + Questions, comments and problems can go to Gene@Telobot.com. + + Thumbs Up! + Gene Knight + + */ + + uint8_t TwoWire::rxBuffer[NBWIRE_BUFFER_LENGTH]; + uint8_t TwoWire::rxBufferIndex = 0; + uint8_t TwoWire::rxBufferLength = 0; + + uint8_t TwoWire::txAddress = 0; + uint8_t TwoWire::txBuffer[NBWIRE_BUFFER_LENGTH]; + uint8_t TwoWire::txBufferIndex = 0; + uint8_t TwoWire::txBufferLength = 0; + + //uint8_t TwoWire::transmitting = 0; + void (*TwoWire::user_onRequest)(void); + void (*TwoWire::user_onReceive)(int); + + static volatile uint8_t twi_transmitting; + static volatile uint8_t twi_state; + static uint8_t twi_slarw; + static volatile uint8_t twi_error; + static uint8_t twi_masterBuffer[TWI_BUFFER_LENGTH]; + static volatile uint8_t twi_masterBufferIndex; + static uint8_t twi_masterBufferLength; + static uint8_t twi_rxBuffer[TWI_BUFFER_LENGTH]; + static volatile uint8_t twi_rxBufferIndex; + //static volatile uint8_t twi_Interrupt_Continue_Command; + static volatile uint8_t twi_Return_Value; + static volatile uint8_t twi_Done; + void (*twi_cbendTransmissionDone)(int); + void (*twi_cbreadFromDone)(int); + + void twi_init() { + // initialize state + twi_state = TWI_READY; + + // activate internal pull-ups for twi + // as per note from atmega8 manual pg167 + sbi(PORTC, 4); + sbi(PORTC, 5); + + // initialize twi prescaler and bit rate + cbi(TWSR, TWPS0); // TWI Status Register - Prescaler bits + cbi(TWSR, TWPS1); + + /* twi bit rate formula from atmega128 manual pg 204 + SCL Frequency = CPU Clock Frequency / (16 + (2 * TWBR)) + note: TWBR should be 10 or higher for master mode + It is 72 for a 16mhz Wiring board with 100kHz TWI */ + + TWBR = ((CPU_FREQ / TWI_FREQ) - 16) / 2; // bitrate register + // enable twi module, acks, and twi interrupt + + TWCR = (1 << TWEN) | (1 << TWIE) | (1 << TWEA); + + /* TWEN - TWI Enable Bit + TWIE - TWI Interrupt Enable + TWEA - TWI Enable Acknowledge Bit + TWINT - TWI Interrupt Flag + TWSTA - TWI Start Condition + */ + } + + typedef struct { + uint8_t address; + uint8_t* data; + uint8_t length; + uint8_t wait; + uint8_t i; + } twi_Write_Vars; + + twi_Write_Vars *ptwv = 0; + static void (*fNextInterruptFunction)(void) = 0; + + void twi_Finish(byte bRetVal) { + if (ptwv) { + free(ptwv); + ptwv = 0; + } + twi_Done = 0xFF; + twi_Return_Value = bRetVal; + fNextInterruptFunction = 0; + } + + uint8_t twii_WaitForDone(uint16_t timeout) { + uint32_t endMillis = millis() + timeout; + while (!twi_Done && (timeout == 0 || millis() < endMillis)) continue; + return twi_Return_Value; + } + + void twii_SetState(uint8_t ucState) { + twi_state = ucState; + } + + void twii_SetError(uint8_t ucError) { + twi_error = ucError ; + } + + void twii_InitBuffer(uint8_t ucPos, uint8_t ucLength) { + twi_masterBufferIndex = 0; + twi_masterBufferLength = ucLength; + } + + void twii_CopyToBuf(uint8_t* pData, uint8_t ucLength) { + uint8_t i; + for (i = 0; i < ucLength; ++i) { + twi_masterBuffer[i] = pData[i]; + } + } + + void twii_CopyFromBuf(uint8_t *pData, uint8_t ucLength) { + uint8_t i; + for (i = 0; i < ucLength; ++i) { + pData[i] = twi_masterBuffer[i]; + } + } + + void twii_SetSlaRW(uint8_t ucSlaRW) { + twi_slarw = ucSlaRW; + } + + void twii_SetStart() { + TWCR = (1 << TWEN) | (1 << TWIE) | (1 << TWEA) | (1 << TWINT) | (1 << TWSTA); + } + + void twi_write01() { + if (TWI_MTX == twi_state) return; // blocking test + twi_transmitting = 0 ; + if (twi_error == 0xFF) + twi_Finish (0); // success + else if (twi_error == TW_MT_SLA_NACK) + twi_Finish (2); // error: address send, nack received + else if (twi_error == TW_MT_DATA_NACK) + twi_Finish (3); // error: data send, nack received + else + twi_Finish (4); // other twi error + if (twi_cbendTransmissionDone) return twi_cbendTransmissionDone(twi_Return_Value); + return; + } + + + void twi_write00() { + if (TWI_READY != twi_state) return; // blocking test + if (TWI_BUFFER_LENGTH < ptwv -> length) { + twi_Finish(1); // end write with error 1 + return; + } + twi_Done = 0x00; // show as working + twii_SetState(TWI_MTX); // to transmitting + twii_SetError(0xFF); // to No Error + twii_InitBuffer(0, ptwv -> length); // pointer and length + twii_CopyToBuf(ptwv -> data, ptwv -> length); // get the data + twii_SetSlaRW((ptwv -> address << 1) | TW_WRITE); // write command + twii_SetStart(); // start the cycle + fNextInterruptFunction = twi_write01; // next routine + return twi_write01(); + } + + void twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait) { + uint8_t i; + ptwv = (twi_Write_Vars *)malloc(sizeof(twi_Write_Vars)); + ptwv -> address = address; + ptwv -> data = data; + ptwv -> length = length; + ptwv -> wait = wait; + fNextInterruptFunction = twi_write00; + return twi_write00(); + } + + void twi_read01() { + if (TWI_MRX == twi_state) return; // blocking test + if (twi_masterBufferIndex < ptwv -> length) ptwv -> length = twi_masterBufferIndex; + twii_CopyFromBuf(ptwv -> data, ptwv -> length); + twi_Finish(ptwv -> length); + if (twi_cbreadFromDone) return twi_cbreadFromDone(twi_Return_Value); + return; + } + + void twi_read00() { + if (TWI_READY != twi_state) return; // blocking test + if (TWI_BUFFER_LENGTH < ptwv -> length) twi_Finish(0); // error return + twi_Done = 0x00; // show as working + twii_SetState(TWI_MRX); // reading + twii_SetError(0xFF); // reset error + twii_InitBuffer(0, ptwv -> length - 1); // init to one less than length + twii_SetSlaRW((ptwv -> address << 1) | TW_READ); // read command + twii_SetStart(); // start cycle + fNextInterruptFunction = twi_read01; + return twi_read01(); + } + + void twi_readFrom(uint8_t address, uint8_t* data, uint8_t length) { + uint8_t i; + + ptwv = (twi_Write_Vars *)malloc(sizeof(twi_Write_Vars)); + ptwv -> address = address; + ptwv -> data = data; + ptwv -> length = length; + fNextInterruptFunction = twi_read00; + return twi_read00(); + } + + void twi_reply(uint8_t ack) { + // transmit master read ready signal, with or without ack + if (ack){ + TWCR = (1 << TWEN) | (1 << TWIE) | (1 << TWINT) | (1 << TWEA); + } else { + TWCR = (1 << TWEN) | (1 << TWIE) | (1 << TWINT); + } + } + + void twi_stop(void) { + // send stop condition + TWCR = (1 << TWEN) | (1 << TWIE) | (1 << TWEA) | (1 << TWINT) | (1 << TWSTO); + + // wait for stop condition to be exectued on bus + // TWINT is not set after a stop condition! + while (TWCR & (1 << TWSTO)) { + continue; + } + + // update twi state + twi_state = TWI_READY; + } + + void twi_releaseBus(void) { + // release bus + TWCR = (1 << TWEN) | (1 << TWIE) | (1 << TWEA) | (1 << TWINT); + + // update twi state + twi_state = TWI_READY; + } + + SIGNAL(TWI_vect) { + switch (TW_STATUS) { + // All Master + case TW_START: // sent start condition + case TW_REP_START: // sent repeated start condition + // copy device address and r/w bit to output register and ack + TWDR = twi_slarw; + twi_reply(1); + break; + + // Master Transmitter + case TW_MT_SLA_ACK: // slave receiver acked address + case TW_MT_DATA_ACK: // slave receiver acked data + // if there is data to send, send it, otherwise stop + if (twi_masterBufferIndex < twi_masterBufferLength) { + // copy data to output register and ack + TWDR = twi_masterBuffer[twi_masterBufferIndex++]; + twi_reply(1); + } else { + twi_stop(); + } + break; + + case TW_MT_SLA_NACK: // address sent, nack received + twi_error = TW_MT_SLA_NACK; + twi_stop(); + break; + + case TW_MT_DATA_NACK: // data sent, nack received + twi_error = TW_MT_DATA_NACK; + twi_stop(); + break; + + case TW_MT_ARB_LOST: // lost bus arbitration + twi_error = TW_MT_ARB_LOST; + twi_releaseBus(); + break; + + // Master Receiver + case TW_MR_DATA_ACK: // data received, ack sent + // put byte into buffer + twi_masterBuffer[twi_masterBufferIndex++] = TWDR; + + case TW_MR_SLA_ACK: // address sent, ack received + // ack if more bytes are expected, otherwise nack + if (twi_masterBufferIndex < twi_masterBufferLength) { + twi_reply(1); + } else { + twi_reply(0); + } + break; + + case TW_MR_DATA_NACK: // data received, nack sent + // put final byte into buffer + twi_masterBuffer[twi_masterBufferIndex++] = TWDR; + + case TW_MR_SLA_NACK: // address sent, nack received + twi_stop(); + break; + + // TW_MR_ARB_LOST handled by TW_MT_ARB_LOST case + + // Slave Receiver (NOT IMPLEMENTED YET) + /* + case TW_SR_SLA_ACK: // addressed, returned ack + case TW_SR_GCALL_ACK: // addressed generally, returned ack + case TW_SR_ARB_LOST_SLA_ACK: // lost arbitration, returned ack + case TW_SR_ARB_LOST_GCALL_ACK: // lost arbitration, returned ack + // enter slave receiver mode + twi_state = TWI_SRX; + + // indicate that rx buffer can be overwritten and ack + twi_rxBufferIndex = 0; + twi_reply(1); + break; + + case TW_SR_DATA_ACK: // data received, returned ack + case TW_SR_GCALL_DATA_ACK: // data received generally, returned ack + // if there is still room in the rx buffer + if (twi_rxBufferIndex < TWI_BUFFER_LENGTH) { + // put byte in buffer and ack + twi_rxBuffer[twi_rxBufferIndex++] = TWDR; + twi_reply(1); + } else { + // otherwise nack + twi_reply(0); + } + break; + + case TW_SR_STOP: // stop or repeated start condition received + // put a null char after data if there's room + if (twi_rxBufferIndex < TWI_BUFFER_LENGTH) { + twi_rxBuffer[twi_rxBufferIndex] = 0; + } + + // sends ack and stops interface for clock stretching + twi_stop(); + + // callback to user defined callback + twi_onSlaveReceive(twi_rxBuffer, twi_rxBufferIndex); + + // since we submit rx buffer to "wire" library, we can reset it + twi_rxBufferIndex = 0; + + // ack future responses and leave slave receiver state + twi_releaseBus(); + break; + + case TW_SR_DATA_NACK: // data received, returned nack + case TW_SR_GCALL_DATA_NACK: // data received generally, returned nack + // nack back at master + twi_reply(0); + break; + + // Slave Transmitter + case TW_ST_SLA_ACK: // addressed, returned ack + case TW_ST_ARB_LOST_SLA_ACK: // arbitration lost, returned ack + // enter slave transmitter mode + twi_state = TWI_STX; + + // ready the tx buffer index for iteration + twi_txBufferIndex = 0; + + // set tx buffer length to be zero, to verify if user changes it + twi_txBufferLength = 0; + + // request for txBuffer to be filled and length to be set + // note: user must call twi_transmit(bytes, length) to do this + twi_onSlaveTransmit(); + + // if they didn't change buffer & length, initialize it + if (0 == twi_txBufferLength) { + twi_txBufferLength = 1; + twi_txBuffer[0] = 0x00; + } + + // transmit first byte from buffer, fall through + + case TW_ST_DATA_ACK: // byte sent, ack returned + // copy data to output register + TWDR = twi_txBuffer[twi_txBufferIndex++]; + + // if there is more to send, ack, otherwise nack + if (twi_txBufferIndex < twi_txBufferLength) { + twi_reply(1); + } else { + twi_reply(0); + } + break; + + case TW_ST_DATA_NACK: // received nack, we are done + case TW_ST_LAST_DATA: // received ack, but we are done already! + // ack future responses + twi_reply(1); + // leave slave receiver state + twi_state = TWI_READY; + break; + */ + + // all + case TW_NO_INFO: // no state information + break; + + case TW_BUS_ERROR: // bus error, illegal stop/start + twi_error = TW_BUS_ERROR; + twi_stop(); + break; + } + + if (fNextInterruptFunction) return fNextInterruptFunction(); + } + + TwoWire::TwoWire() { } + + void TwoWire::begin(void) { + rxBufferIndex = 0; + rxBufferLength = 0; + + txBufferIndex = 0; + txBufferLength = 0; + + twi_init(); + } + + void TwoWire::beginTransmission(uint8_t address) { + //beginTransmission((uint8_t)address); + + // indicate that we are transmitting + twi_transmitting = 1; + + // set address of targeted slave + txAddress = address; + + // reset tx buffer iterator vars + txBufferIndex = 0; + txBufferLength = 0; + } + + uint8_t TwoWire::endTransmission(uint16_t timeout) { + // transmit buffer (blocking) + //int8_t ret = + twi_cbendTransmissionDone = NULL; + twi_writeTo(txAddress, txBuffer, txBufferLength, 1); + int8_t ret = twii_WaitForDone(timeout); + + // reset tx buffer iterator vars + txBufferIndex = 0; + txBufferLength = 0; + + // indicate that we are done transmitting + // twi_transmitting = 0; + return ret; + } + + void TwoWire::nbendTransmission(void (*function)(int)) { + twi_cbendTransmissionDone = function; + twi_writeTo(txAddress, txBuffer, txBufferLength, 1); + return; + } + + void TwoWire::send(uint8_t data) { + if (twi_transmitting) { + // in master transmitter mode + // don't bother if buffer is full + if (txBufferLength >= NBWIRE_BUFFER_LENGTH) { + return; + } + + // put byte in tx buffer + txBuffer[txBufferIndex] = data; + ++txBufferIndex; + + // update amount in buffer + txBufferLength = txBufferIndex; + } else { + // in slave send mode + // reply to master + //twi_transmit(&data, 1); + } + } + + uint8_t TwoWire::receive(void) { + // default to returning null char + // for people using with char strings + uint8_t value = 0; + + // get each successive byte on each call + if (rxBufferIndex < rxBufferLength) { + value = rxBuffer[rxBufferIndex]; + ++rxBufferIndex; + } + + return value; + } + + uint8_t TwoWire::requestFrom(uint8_t address, int quantity, uint16_t timeout) { + // clamp to buffer length + if (quantity > NBWIRE_BUFFER_LENGTH) { + quantity = NBWIRE_BUFFER_LENGTH; + } + + // perform blocking read into buffer + twi_cbreadFromDone = NULL; + twi_readFrom(address, rxBuffer, quantity); + uint8_t read = twii_WaitForDone(timeout); + + // set rx buffer iterator vars + rxBufferIndex = 0; + rxBufferLength = read; + + return read; + } + + void TwoWire::nbrequestFrom(uint8_t address, int quantity, void (*function)(int)) { + // clamp to buffer length + if (quantity > NBWIRE_BUFFER_LENGTH) { + quantity = NBWIRE_BUFFER_LENGTH; + } + + // perform blocking read into buffer + twi_cbreadFromDone = function; + twi_readFrom(address, rxBuffer, quantity); + //uint8_t read = twii_WaitForDone(); + + // set rx buffer iterator vars + //rxBufferIndex = 0; + //rxBufferLength = read; + + rxBufferIndex = 0; + rxBufferLength = quantity; // this is a hack + + return; //read; + } + + uint8_t TwoWire::available(void) { + return rxBufferLength - rxBufferIndex; + } + +#endif diff --git a/LinuxI2CDev/I2Cdev/I2Cdev.h b/LinuxI2CDev/I2Cdev/I2Cdev.h new file mode 100644 index 00000000..5b59c56f --- /dev/null +++ b/LinuxI2CDev/I2Cdev/I2Cdev.h @@ -0,0 +1,311 @@ +// I2Cdev library collection - Main I2C device class header file +// Abstracts bit and byte I2C R/W functions into a convenient class +// 2013-06-05 by Jeff Rowberg +// +// Changelog: +// 2021-09-28 - allow custom Wire object as transaction function argument +// 2020-01-20 - hardija : complete support for Teensy 3.x +// 2015-10-30 - simondlevy : support i2c_t3 for Teensy3.1 +// 2013-05-06 - add Francesco Ferrara's Fastwire v0.24 implementation with small modifications +// 2013-05-05 - fix issue with writing bit values to words (Sasquatch/Farzanegan) +// 2012-06-09 - fix major issue with reading > 32 bytes at a time with Arduino Wire +// - add compiler warnings when using outdated or IDE or limited I2Cdev implementation +// 2011-11-01 - fix write*Bits mask calculation (thanks sasquatch @ Arduino forums) +// 2011-10-03 - added automatic Arduino version detection for ease of use +// 2011-10-02 - added Gene Knight's NBWire TwoWire class implementation with small modifications +// 2011-08-31 - added support for Arduino 1.0 Wire library (methods are different from 0.x) +// 2011-08-03 - added optional timeout parameter to read* methods to easily change from default +// 2011-08-02 - added support for 16-bit registers +// - fixed incorrect Doxygen comments on some methods +// - added timeout value for read operations (thanks mem @ Arduino forums) +// 2011-07-30 - changed read/write function structures to return success or byte counts +// - made all methods static for multi-device memory savings +// 2011-07-28 - initial release + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2013 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#ifndef _I2CDEV_H_ +#define _I2CDEV_H_ + +// ----------------------------------------------------------------------------- +// Enable deprecated pgmspace typedefs in avr-libc +// ----------------------------------------------------------------------------- +#define __PROG_TYPES_COMPAT__ + +// ----------------------------------------------------------------------------- +// I2C interface implementation setting +// ----------------------------------------------------------------------------- +#ifndef I2CDEV_IMPLEMENTATION +#define I2CDEV_IMPLEMENTATION I2CDEV_ARDUINO_WIRE +//#define I2CDEV_IMPLEMENTATION I2CDEV_TEENSY_3X_WIRE +//#define I2CDEV_IMPLEMENTATION I2CDEV_BUILTIN_SBWIRE +//#define I2CDEV_IMPLEMENTATION I2CDEV_BUILTIN_FASTWIRE +#endif // I2CDEV_IMPLEMENTATION + +// comment this out if you are using a non-optimal IDE/implementation setting +// but want the compiler to shut up about it +#define I2CDEV_IMPLEMENTATION_WARNINGS + +// ----------------------------------------------------------------------------- +// I2C interface implementation options +// ----------------------------------------------------------------------------- +#define I2CDEV_ARDUINO_WIRE 1 // Wire object from Arduino +#define I2CDEV_BUILTIN_NBWIRE 2 // Tweaked Wire object from Gene Knight's NBWire project + // ^^^ NBWire implementation is still buggy w/some interrupts! +#define I2CDEV_BUILTIN_FASTWIRE 3 // FastWire object from Francesco Ferrara's project +#define I2CDEV_I2CMASTER_LIBRARY 4 // I2C object from DSSCircuits I2C-Master Library at https://github.com/DSSCircuits/I2C-Master-Library +#define I2CDEV_BUILTIN_SBWIRE 5 // I2C object from Shuning (Steve) Bian's SBWire Library at https://github.com/freespace/SBWire +#define I2CDEV_TEENSY_3X_WIRE 6 // Teensy 3.x support using i2c_t3 library + +// ----------------------------------------------------------------------------- +// Arduino-style "Serial.print" debug constant (uncomment to enable) +// ----------------------------------------------------------------------------- +//#define I2CDEV_SERIAL_DEBUG + +#ifdef ARDUINO + #if ARDUINO < 100 + #include "WProgram.h" + #else + #include "Arduino.h" + #endif + #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE + #include + #endif + #if I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE + #include + #endif + #if I2CDEV_IMPLEMENTATION == I2CDEV_I2CMASTER_LIBRARY + #include + #endif + #if I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE + #include "SBWire.h" + #endif +#endif + +#ifdef SPARK + #include "application.h" + #define ARDUINO 101 + #define BUFFER_LENGTH 32 +#endif + +#ifndef I2CDEVLIB_WIRE_BUFFER_LENGTH + #if defined(I2C_BUFFER_LENGTH) + // Arduino ESP32 core Wire uses this + #define I2CDEVLIB_WIRE_BUFFER_LENGTH I2C_BUFFER_LENGTH + #elif defined(BUFFER_LENGTH) + // Arduino AVR core Wire and many others use this + #define I2CDEVLIB_WIRE_BUFFER_LENGTH BUFFER_LENGTH + #elif defined(SERIAL_BUFFER_SIZE) + // Arduino SAMD core Wire uses this + #define I2CDEVLIB_WIRE_BUFFER_LENGTH SERIAL_BUFFER_SIZE + #else + // should be a safe fallback, though possibly inefficient + #define I2CDEVLIB_WIRE_BUFFER_LENGTH 32 + #endif +#endif + +// 1000ms default read timeout (modify with "I2Cdev::readTimeout = [ms];") +#define I2CDEV_DEFAULT_READ_TIMEOUT 1000 + +class I2Cdev { + public: + I2Cdev(); + + static int8_t readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout, void *wireObj=0); + static int8_t readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout, void *wireObj=0); + static int8_t readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout, void *wireObj=0); + static int8_t readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout, void *wireObj=0); + static int8_t readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout, void *wireObj=0); + static int8_t readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout, void *wireObj=0); + static int8_t readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout, void *wireObj=0); + static int8_t readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout, void *wireObj=0); + + static bool writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t data, void *wireObj=0); + static bool writeBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t data, void *wireObj=0); + static bool writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data, void *wireObj=0); + static bool writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t data, void *wireObj=0); + static bool writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data, void *wireObj=0); + static bool writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data, void *wireObj=0); + static bool writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data, void *wireObj=0); + static bool writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data, void *wireObj=0); + + static uint16_t readTimeout; +}; + +#if I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE + ////////////////////// + // FastWire 0.24 + // This is a library to help faster programs to read I2C devices. + // Copyright(C) 2012 + // Francesco Ferrara + ////////////////////// + + /* Master */ + #define TW_START 0x08 + #define TW_REP_START 0x10 + + /* Master Transmitter */ + #define TW_MT_SLA_ACK 0x18 + #define TW_MT_SLA_NACK 0x20 + #define TW_MT_DATA_ACK 0x28 + #define TW_MT_DATA_NACK 0x30 + #define TW_MT_ARB_LOST 0x38 + + /* Master Receiver */ + #define TW_MR_ARB_LOST 0x38 + #define TW_MR_SLA_ACK 0x40 + #define TW_MR_SLA_NACK 0x48 + #define TW_MR_DATA_ACK 0x50 + #define TW_MR_DATA_NACK 0x58 + + #define TW_OK 0 + #define TW_ERROR 1 + + class Fastwire { + private: + static boolean waitInt(); + + public: + static void setup(int khz, boolean pullup); + static byte beginTransmission(byte device); + static byte write(byte value); + static byte writeBuf(byte device, byte address, byte *data, byte num); + static byte readBuf(byte device, byte address, byte *data, byte num); + static void reset(); + static byte stop(); + }; +#endif + +#if I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE + // NBWire implementation based heavily on code by Gene Knight + // Originally posted on the Arduino forum at http://arduino.cc/forum/index.php/topic,70705.0.html + // Originally offered to the i2cdevlib project at http://arduino.cc/forum/index.php/topic,68210.30.html + + #define NBWIRE_BUFFER_LENGTH 32 + + class TwoWire { + private: + static uint8_t rxBuffer[]; + static uint8_t rxBufferIndex; + static uint8_t rxBufferLength; + + static uint8_t txAddress; + static uint8_t txBuffer[]; + static uint8_t txBufferIndex; + static uint8_t txBufferLength; + + // static uint8_t transmitting; + static void (*user_onRequest)(void); + static void (*user_onReceive)(int); + static void onRequestService(void); + static void onReceiveService(uint8_t*, int); + + public: + TwoWire(); + void begin(); + void begin(uint8_t); + void begin(int); + void beginTransmission(uint8_t); + //void beginTransmission(int); + uint8_t endTransmission(uint16_t timeout=0); + void nbendTransmission(void (*function)(int)) ; + uint8_t requestFrom(uint8_t, int, uint16_t timeout=0); + //uint8_t requestFrom(int, int); + void nbrequestFrom(uint8_t, int, void (*function)(int)); + void send(uint8_t); + void send(uint8_t*, uint8_t); + //void send(int); + void send(char*); + uint8_t available(void); + uint8_t receive(void); + void onReceive(void (*)(int)); + void onRequest(void (*)(void)); + }; + + #define TWI_READY 0 + #define TWI_MRX 1 + #define TWI_MTX 2 + #define TWI_SRX 3 + #define TWI_STX 4 + + #define TW_WRITE 0 + #define TW_READ 1 + + #define TW_MT_SLA_NACK 0x20 + #define TW_MT_DATA_NACK 0x30 + + #define CPU_FREQ 16000000L + #define TWI_FREQ 100000L + #define TWI_BUFFER_LENGTH 32 + + /* TWI Status is in TWSR, in the top 5 bits: TWS7 - TWS3 */ + + #define TW_STATUS_MASK ((1 << TWS7)|(1 << TWS6)|(1 << TWS5)|(1 << TWS4)|(1 << TWS3)) + #define TW_STATUS (TWSR & TW_STATUS_MASK) + #define TW_START 0x08 + #define TW_REP_START 0x10 + #define TW_MT_SLA_ACK 0x18 + #define TW_MT_SLA_NACK 0x20 + #define TW_MT_DATA_ACK 0x28 + #define TW_MT_DATA_NACK 0x30 + #define TW_MT_ARB_LOST 0x38 + #define TW_MR_ARB_LOST 0x38 + #define TW_MR_SLA_ACK 0x40 + #define TW_MR_SLA_NACK 0x48 + #define TW_MR_DATA_ACK 0x50 + #define TW_MR_DATA_NACK 0x58 + #define TW_ST_SLA_ACK 0xA8 + #define TW_ST_ARB_LOST_SLA_ACK 0xB0 + #define TW_ST_DATA_ACK 0xB8 + #define TW_ST_DATA_NACK 0xC0 + #define TW_ST_LAST_DATA 0xC8 + #define TW_SR_SLA_ACK 0x60 + #define TW_SR_ARB_LOST_SLA_ACK 0x68 + #define TW_SR_GCALL_ACK 0x70 + #define TW_SR_ARB_LOST_GCALL_ACK 0x78 + #define TW_SR_DATA_ACK 0x80 + #define TW_SR_DATA_NACK 0x88 + #define TW_SR_GCALL_DATA_ACK 0x90 + #define TW_SR_GCALL_DATA_NACK 0x98 + #define TW_SR_STOP 0xA0 + #define TW_NO_INFO 0xF8 + #define TW_BUS_ERROR 0x00 + + //#define _MMIO_BYTE(mem_addr) (*(volatile uint8_t *)(mem_addr)) + //#define _SFR_BYTE(sfr) _MMIO_BYTE(_SFR_ADDR(sfr)) + + #ifndef sbi // set bit + #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= (1 << bit)) + #endif // sbi + + #ifndef cbi // clear bit + #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~(1 << bit)) + #endif // cbi + + extern TwoWire Wire; + +#endif // I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE + +#endif /* _I2CDEV_H_ */ From 2b6a40d4c471780ddb99c5f94c32fe656e062ba3 Mon Sep 17 00:00:00 2001 From: Hananja from Raspberry Pi Zero 2 W Date: Thu, 1 Feb 2024 09:09:12 +0100 Subject: [PATCH 328/335] Modify for linux i2c dev --- LinuxI2CDev/I2Cdev/I2Cdev.cpp | 1226 ++------------------------------- LinuxI2CDev/I2Cdev/I2Cdev.h | 217 +----- 2 files changed, 77 insertions(+), 1366 deletions(-) diff --git a/LinuxI2CDev/I2Cdev/I2Cdev.cpp b/LinuxI2CDev/I2Cdev/I2Cdev.cpp index 40b5dfc4..a18b0250 100644 --- a/LinuxI2CDev/I2Cdev/I2Cdev.cpp +++ b/LinuxI2CDev/I2Cdev/I2Cdev.cpp @@ -48,53 +48,23 @@ THE SOFTWARE. #include "I2Cdev.h" -#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE - - #ifdef I2CDEV_IMPLEMENTATION_WARNINGS - #if ARDUINO < 100 - #warning Using outdated Arduino IDE with Wire library is functionally limiting. - #warning Arduino IDE v1.6.5+ with I2Cdev Fastwire implementation is recommended. - #warning This I2Cdev implementation does not support: - #warning - Repeated starts conditions - #warning - Timeout detection (some Wire requests block forever) - #elif ARDUINO == 100 - #warning Using outdated Arduino IDE with Wire library is functionally limiting. - #warning Arduino IDE v1.6.5+ with I2Cdev Fastwire implementation is recommended. - #warning This I2Cdev implementation does not support: - #warning - Repeated starts conditions - #warning - Timeout detection (some Wire requests block forever) - #elif ARDUINO > 100 - /*#warning Using current Arduino IDE with Wire library is functionally limiting. - #warning Arduino IDE v1.6.5+ with I2CDEV_BUILTIN_FASTWIRE implementation is recommended. - #warning This I2Cdev implementation does not support: - #warning - Timeout detection (some Wire requests block forever)*/ - #endif - #endif - -#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE - - //#error The I2CDEV_BUILTIN_FASTWIRE implementation is known to be broken right now. Patience, Iago! - -#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE - - #ifdef I2CDEV_IMPLEMENTATION_WARNINGS - #warning Using I2CDEV_BUILTIN_NBWIRE implementation may adversely affect interrupt detection. - #warning This I2Cdev implementation does not support: - #warning - Repeated starts conditions - #endif - - // NBWire implementation based heavily on code by Gene Knight - // Originally posted on the Arduino forum at http://arduino.cc/forum/index.php/topic,70705.0.html - // Originally offered to the i2cdevlib project at http://arduino.cc/forum/index.php/topic,68210.30.html - TwoWire Wire; - -#endif - +#include +#include +#include +#include +#include +#include +#include + +static const char* i2cDev = NULL; /** Default constructor. */ I2Cdev::I2Cdev() { } +void I2Cdev::initialize(const char* devPath) { + i2cDev = devPath; +} /** Read a single bit from an 8-bit device register. * @param devAddr I2C slave device address * @param regAddr Register regAddr to read from @@ -207,107 +177,29 @@ int8_t I2Cdev::readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data, uint16 * @return Number of bytes read (-1 indicates failure) */ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data, uint16_t timeout, void *wireObj) { - #ifdef I2CDEV_SERIAL_DEBUG - Serial.print("I2C (0x"); - Serial.print(devAddr, HEX); - Serial.print(") reading "); - Serial.print(length, DEC); - Serial.print(" bytes from 0x"); - Serial.print(regAddr, HEX); - Serial.print("..."); - #endif - - uint8_t count = 0; - uint32_t t1 = millis(); - - #if (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE) - TwoWire *useWire = &Wire; - if (wireObj) useWire = (TwoWire *)wireObj; - - #if (ARDUINO < 100) - // Arduino v00xx (before v1.0), Wire library - - // I2C/TWI subsystem uses internal buffer that breaks with large data requests - // so if user requests more than I2CDEVLIB_WIRE_BUFFER_LENGTH bytes, we have to do it in - // smaller chunks instead of all at once - for (int k = 0; k < length; k += min((int)length, I2CDEVLIB_WIRE_BUFFER_LENGTH)) { - useWire->beginTransmission(devAddr); - useWire->send(regAddr); - useWire->endTransmission(); - useWire->requestFrom((uint8_t)devAddr, (uint8_t)min((int)length - k, I2CDEVLIB_WIRE_BUFFER_LENGTH)); - for (; useWire->available() && (timeout == 0 || millis() - t1 < timeout); count++) { - data[count] = useWire->receive(); - #ifdef I2CDEV_SERIAL_DEBUG - Serial.print(data[count], HEX); - if (count + 1 < length) Serial.print(" "); - #endif - } - } - #elif (ARDUINO == 100) - // Arduino v1.0.0, Wire library - // Adds standardized write() and read() stream methods instead of send() and receive() - - // I2C/TWI subsystem uses internal buffer that breaks with large data requests - // so if user requests more than I2CDEVLIB_WIRE_BUFFER_LENGTH bytes, we have to do it in - // smaller chunks instead of all at once - for (int k = 0; k < length; k += min((int)length, I2CDEVLIB_WIRE_BUFFER_LENGTH)) { - useWire->beginTransmission(devAddr); - useWire->write(regAddr); - useWire->endTransmission(); - useWire->requestFrom((uint8_t)devAddr, (uint8_t)min((int)length - k, I2CDEVLIB_WIRE_BUFFER_LENGTH)); - for (; useWire->available() && (timeout == 0 || millis() - t1 < timeout); count++) { - data[count] = useWire->read(); - #ifdef I2CDEV_SERIAL_DEBUG - Serial.print(data[count], HEX); - if (count + 1 < length) Serial.print(" "); - #endif - } - } - #elif (ARDUINO > 100) - // Arduino v1.0.1+, Wire library - // Adds official support for repeated start condition, yay! - - // I2C/TWI subsystem uses internal buffer that breaks with large data requests - // so if user requests more than I2CDEVLIB_WIRE_BUFFER_LENGTH bytes, we have to do it in - // smaller chunks instead of all at once - for (int k = 0; k < length; k += min((int)length, I2CDEVLIB_WIRE_BUFFER_LENGTH)) { - useWire->beginTransmission(devAddr); - useWire->write(regAddr); - useWire->endTransmission(); - useWire->requestFrom((uint8_t)devAddr, (uint8_t)min((int)length - k, I2CDEVLIB_WIRE_BUFFER_LENGTH)); - for (; useWire->available() && (timeout == 0 || millis() - t1 < timeout); count++) { - data[count] = useWire->read(); - #ifdef I2CDEV_SERIAL_DEBUG - Serial.print(data[count], HEX); - if (count + 1 < length) Serial.print(" "); - #endif - } - } - #endif - - #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) - - // Fastwire library - // no loop required for fastwire - uint8_t status = Fastwire::readBuf(devAddr << 1, regAddr, data, length); - if (status == 0) { - count = length; // success - } else { - count = -1; // error - } - - #endif - - // check for timeout - if (timeout > 0 && millis() - t1 >= timeout && count < length) count = -1; // timeout - - #ifdef I2CDEV_SERIAL_DEBUG - Serial.print(". Done ("); - Serial.print(count, DEC); - Serial.println(" read)."); - #endif - - return count; + int fd = open(i2cDev, O_RDWR); + if (fd < 0) { + fprintf(stderr, "Failed to open i2c device %s: %s\n", i2cDev, strerror(errno)); + return -1; + } + if (ioctl(fd, I2C_SLAVE, (unsigned long) devAddr) < 0) { + fprintf(stderr, "Failed to set i2c address to %u: %s\n", devAddr, strerror(errno)); + close(fd); + return -1; + } + if (timeout != 0 && ioctl(fd, I2C_TIMEOUT, (unsigned long) timeout / 100) < 0) { + fprintf(stderr, "Failed to set i2c timeout: %s\n", strerror(errno)); + } + if (write(fd, ®Addr, 1) != 1) { + fprintf(stderr, "Failed to write reg: %s\n", strerror(errno)); + } + if (read(fd, data, length) != length) { + fprintf(stderr, "Failed to read reg: %s\n", strerror(errno)); + close(fd); + return -1; + } + close(fd); + return length; } /** Read multiple words from a 16-bit device register. @@ -319,140 +211,18 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 * @return Number of words read (-1 indicates failure) */ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data, uint16_t timeout, void *wireObj) { - #ifdef I2CDEV_SERIAL_DEBUG - Serial.print("I2C (0x"); - Serial.print(devAddr, HEX); - Serial.print(") reading "); - Serial.print(length, DEC); - Serial.print(" words from 0x"); - Serial.print(regAddr, HEX); - Serial.print("..."); - #endif - - uint8_t count = 0; - uint32_t t1 = millis(); + uint8_t buff[length * 2]; -#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE - TwoWire *useWire = &Wire; - if (wireObj) useWire = (TwoWire *)wireObj; - - #if (ARDUINO < 100) - // Arduino v00xx (before v1.0), Wire library - - // I2C/TWI subsystem uses internal buffer that breaks with large data requests - // so if user requests more than I2CDEVLIB_WIRE_BUFFER_LENGTH bytes, we have to do it in - // smaller chunks instead of all at once - for (uint8_t k = 0; k < length * 2; k += min(length * 2, I2CDEVLIB_WIRE_BUFFER_LENGTH)) { - useWire->beginTransmission(devAddr); - useWire->send(regAddr); - useWire->endTransmission(); - useWire->requestFrom(devAddr, (uint8_t)(length * 2)); // length=words, this wants bytes - - bool msb = true; // starts with MSB, then LSB - for (; useWire->available() && count < length && (timeout == 0 || millis() - t1 < timeout);) { - if (msb) { - // first byte is bits 15-8 (MSb=15) - data[count] = useWire->receive() << 8; - } else { - // second byte is bits 7-0 (LSb=0) - data[count] |= useWire->receive(); - #ifdef I2CDEV_SERIAL_DEBUG - Serial.print(data[count], HEX); - if (count + 1 < length) Serial.print(" "); - #endif - count++; - } - msb = !msb; - } - } - #elif (ARDUINO == 100) - // Arduino v1.0.0, Wire library - // Adds standardized write() and read() stream methods instead of send() and receive() - - // I2C/TWI subsystem uses internal buffer that breaks with large data requests - // so if user requests more than I2CDEVLIB_WIRE_BUFFER_LENGTH bytes, we have to do it in - // smaller chunks instead of all at once - for (uint8_t k = 0; k < length * 2; k += min(length * 2, I2CDEVLIB_WIRE_BUFFER_LENGTH)) { - useWire->beginTransmission(devAddr); - useWire->write(regAddr); - useWire->endTransmission(); - useWire->requestFrom(devAddr, (uint8_t)(length * 2)); // length=words, this wants bytes - - bool msb = true; // starts with MSB, then LSB - for (; useWire->available() && count < length && (timeout == 0 || millis() - t1 < timeout);) { - if (msb) { - // first byte is bits 15-8 (MSb=15) - data[count] = useWire->read() << 8; - } else { - // second byte is bits 7-0 (LSb=0) - data[count] |= useWire->read(); - #ifdef I2CDEV_SERIAL_DEBUG - Serial.print(data[count], HEX); - if (count + 1 < length) Serial.print(" "); - #endif - count++; - } - msb = !msb; - } - } - #elif (ARDUINO > 100) - // Arduino v1.0.1+, Wire library - // Adds official support for repeated start condition, yay! - - // I2C/TWI subsystem uses internal buffer that breaks with large data requests - // so if user requests more than I2CDEVLIB_WIRE_BUFFER_LENGTH bytes, we have to do it in - // smaller chunks instead of all at once - for (uint8_t k = 0; k < length * 2; k += min(length * 2, I2CDEVLIB_WIRE_BUFFER_LENGTH)) { - useWire->beginTransmission(devAddr); - useWire->write(regAddr); - useWire->endTransmission(); - useWire->requestFrom(devAddr, (uint8_t)(length * 2)); // length=words, this wants bytes - - bool msb = true; // starts with MSB, then LSB - for (; useWire->available() && count < length && (timeout == 0 || millis() - t1 < timeout);) { - if (msb) { - // first byte is bits 15-8 (MSb=15) - data[count] = useWire->read() << 8; - } else { - // second byte is bits 7-0 (LSb=0) - data[count] |= useWire->read(); - #ifdef I2CDEV_SERIAL_DEBUG - Serial.print(data[count], HEX); - if (count + 1 < length) Serial.print(" "); - #endif - count++; - } - msb = !msb; - } - } - #endif - - #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) - - // Fastwire library - // no loop required for fastwire - uint8_t intermediate[(uint8_t)length*2]; - uint8_t status = Fastwire::readBuf(devAddr << 1, regAddr, intermediate, (uint8_t)(length * 2)); - if (status == 0) { - count = length; // success - for (uint8_t i = 0; i < length; i++) { - data[i] = (intermediate[2*i] << 8) | intermediate[2*i + 1]; - } - } else { - count = -1; // error + if (readBytes(devAddr, regAddr, length * 2, buff, timeout, wireObj) > 0) + { + for (int i = 0; i < length; i++) + { + data[i] = (buff[i * 2] << 8) | buff[i * 2 + 1]; } + return length; + } - #endif - - if (timeout > 0 && millis() - t1 >= timeout && count < length) count = -1; // timeout - - #ifdef I2CDEV_SERIAL_DEBUG - Serial.print(". Done ("); - Serial.print(count, DEC); - Serial.println(" read)."); - #endif - - return count; + return -1; } /** write a single bit in an 8-bit device register. @@ -569,63 +339,30 @@ bool I2Cdev::writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data, void *wi * @return Status of operation (true = success) */ bool I2Cdev::writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t* data, void *wireObj) { - #ifdef I2CDEV_SERIAL_DEBUG - Serial.print("I2C (0x"); - Serial.print(devAddr, HEX); - Serial.print(") writing "); - Serial.print(length, DEC); - Serial.print(" bytes to 0x"); - Serial.print(regAddr, HEX); - Serial.print("..."); - #endif - uint8_t status = 0; - -#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE - TwoWire *useWire = &Wire; - if (wireObj) useWire = (TwoWire *)wireObj; -#endif - - #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) - useWire->beginTransmission(devAddr); - useWire->send((uint8_t) regAddr); // send address - #elif ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) \ - || (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) \ - || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE) - useWire->beginTransmission(devAddr); - useWire->write((uint8_t) regAddr); // send address - #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) - Fastwire::beginTransmission(devAddr); - Fastwire::write(regAddr); - #endif - for (uint8_t i = 0; i < length; i++) { - #ifdef I2CDEV_SERIAL_DEBUG - Serial.print(data[i], HEX); - if (i + 1 < length) Serial.print(" "); - #endif - #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) - useWire->send((uint8_t) data[i]); - #elif ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) \ - || (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) \ - || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE) - useWire->write((uint8_t) data[i]); - #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) - Fastwire::write((uint8_t) data[i]); - #endif + int fd = open(i2cDev, O_RDWR); + if (fd < 0) { + fprintf(stderr, "Failed to open i2c device %s: %s\n", i2cDev, strerror(errno)); + return -1; + } + if (ioctl(fd, I2C_SLAVE, (unsigned long) devAddr) < 0) { + fprintf(stderr, "Failed to set i2c address to %u: %s\n", devAddr, strerror(errno)); + close(fd); + return -1; + } + uint16_t buff_length = length + 1; + uint8_t buff[buff_length]; + buff[0] = regAddr; + + memcpy(&buff[1], data, length); + + if (write(fd, buff, buff_length) != buff_length) + { + fprintf(stderr, "Failed to write reg: %s\n", strerror(errno)); + close(fd); + return false; } - #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) - useWire->endTransmission(); - #elif ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) \ - || (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) \ - || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE) - status = useWire->endTransmission(); - #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) - Fastwire::stop(); - //status = Fastwire::endTransmission(); - #endif - #ifdef I2CDEV_SERIAL_DEBUG - Serial.println(". Done."); - #endif - return status == 0; + close(fd); + return true; } /** Write multiple words to a 16-bit device register. @@ -636,67 +373,15 @@ bool I2Cdev::writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_ * @return Status of operation (true = success) */ bool I2Cdev::writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t* data, void *wireObj) { - #ifdef I2CDEV_SERIAL_DEBUG - Serial.print("I2C (0x"); - Serial.print(devAddr, HEX); - Serial.print(") writing "); - Serial.print(length, DEC); - Serial.print(" words to 0x"); - Serial.print(regAddr, HEX); - Serial.print("..."); - #endif - uint8_t status = 0; + uint8_t buff[length * 2]; -#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE - TwoWire *useWire = &Wire; - if (wireObj) useWire = (TwoWire *)wireObj; -#endif - - #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) - useWire->beginTransmission(devAddr); - useWire->send(regAddr); // send address - #elif ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) \ - || (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) \ - || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE) - useWire->beginTransmission(devAddr); - useWire->write(regAddr); // send address - #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) - Fastwire::beginTransmission(devAddr); - Fastwire::write(regAddr); - #endif - for (uint8_t i = 0; i < length; i++) { - #ifdef I2CDEV_SERIAL_DEBUG - Serial.print(data[i], HEX); - if (i + 1 < length) Serial.print(" "); - #endif - #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) - useWire->send((uint8_t)(data[i] >> 8)); // send MSB - useWire->send((uint8_t)data[i]); // send LSB - #elif ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) \ - || (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) \ - || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE) - useWire->write((uint8_t)(data[i] >> 8)); // send MSB - useWire->write((uint8_t)data[i]); // send LSB - #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) - Fastwire::write((uint8_t)(data[i] >> 8)); // send MSB - status = Fastwire::write((uint8_t)data[i]); // send LSB - if (status != 0) break; - #endif + for (int i = 0; i < length; i++) + { + buff[2 * i] = (uint8_t)(data[i] >> 8); //MSByte + buff[1 + 2 * i] = (uint8_t)(data[i] >> 0); //LSByte } - #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) - useWire->endTransmission(); - #elif ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) \ - || (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) \ - || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE) - status = useWire->endTransmission(); - #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) - Fastwire::stop(); - //status = Fastwire::endTransmission(); - #endif - #ifdef I2CDEV_SERIAL_DEBUG - Serial.println(". Done."); - #endif - return status == 0; + + return writeBytes(devAddr, regAddr, length * 2, buff, wireObj); } /** Default timeout value for read operations. @@ -704,766 +389,3 @@ bool I2Cdev::writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16 */ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; -#if I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE - // I2C library - ////////////////////// - // Copyright(C) 2012 - // Francesco Ferrara - // ferrara[at]libero[point]it - ////////////////////// - - /* - FastWire - - 0.24 added stop - - 0.23 added reset - - This is a library to help faster programs to read I2C devices. - Copyright(C) 2012 Francesco Ferrara - occhiobello at gmail dot com - [used by Jeff Rowberg for I2Cdevlib with permission] - */ - - boolean Fastwire::waitInt() { - int l = 250; - while (!(TWCR & (1 << TWINT)) && l-- > 0); - return l > 0; - } - - void Fastwire::setup(int khz, boolean pullup) { - TWCR = 0; - #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega328P__) - // activate internal pull-ups for twi (PORTC bits 4 & 5) - // as per note from atmega8 manual pg167 - if (pullup) PORTC |= ((1 << 4) | (1 << 5)); - else PORTC &= ~((1 << 4) | (1 << 5)); - #elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__) - // activate internal pull-ups for twi (PORTC bits 0 & 1) - if (pullup) PORTC |= ((1 << 0) | (1 << 1)); - else PORTC &= ~((1 << 0) | (1 << 1)); - #else - // activate internal pull-ups for twi (PORTD bits 0 & 1) - // as per note from atmega128 manual pg204 - if (pullup) PORTD |= ((1 << 0) | (1 << 1)); - else PORTD &= ~((1 << 0) | (1 << 1)); - #endif - - TWSR = 0; // no prescaler => prescaler = 1 - TWBR = F_CPU / 2000 / khz - 8; // change the I2C clock rate - TWCR = 1 << TWEN; // enable twi module, no interrupt - } - - // added by Jeff Rowberg 2013-05-07: - // Arduino Wire-style "beginTransmission" function - // (takes 7-bit device address like the Wire method, NOT 8-bit: 0x68, not 0xD0/0xD1) - byte Fastwire::beginTransmission(byte device) { - byte twst, retry; - retry = 2; - do { - TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO) | (1 << TWSTA); - if (!waitInt()) return 1; - twst = TWSR & 0xF8; - if (twst != TW_START && twst != TW_REP_START) return 2; - - //Serial.print(device, HEX); - //Serial.print(" "); - TWDR = device << 1; // send device address without read bit (1) - TWCR = (1 << TWINT) | (1 << TWEN); - if (!waitInt()) return 3; - twst = TWSR & 0xF8; - } while (twst == TW_MT_SLA_NACK && retry-- > 0); - if (twst != TW_MT_SLA_ACK) return 4; - return 0; - } - - byte Fastwire::writeBuf(byte device, byte address, byte *data, byte num) { - byte twst, retry; - - retry = 2; - do { - TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO) | (1 << TWSTA); - if (!waitInt()) return 1; - twst = TWSR & 0xF8; - if (twst != TW_START && twst != TW_REP_START) return 2; - - //Serial.print(device, HEX); - //Serial.print(" "); - TWDR = device & 0xFE; // send device address without read bit (1) - TWCR = (1 << TWINT) | (1 << TWEN); - if (!waitInt()) return 3; - twst = TWSR & 0xF8; - } while (twst == TW_MT_SLA_NACK && retry-- > 0); - if (twst != TW_MT_SLA_ACK) return 4; - - //Serial.print(address, HEX); - //Serial.print(" "); - TWDR = address; // send data to the previously addressed device - TWCR = (1 << TWINT) | (1 << TWEN); - if (!waitInt()) return 5; - twst = TWSR & 0xF8; - if (twst != TW_MT_DATA_ACK) return 6; - - for (byte i = 0; i < num; i++) { - //Serial.print(data[i], HEX); - //Serial.print(" "); - TWDR = data[i]; // send data to the previously addressed device - TWCR = (1 << TWINT) | (1 << TWEN); - if (!waitInt()) return 7; - twst = TWSR & 0xF8; - if (twst != TW_MT_DATA_ACK) return 8; - } - //Serial.print("\n"); - - return 0; - } - - byte Fastwire::write(byte value) { - byte twst; - //Serial.println(value, HEX); - TWDR = value; // send data - TWCR = (1 << TWINT) | (1 << TWEN); - if (!waitInt()) return 1; - twst = TWSR & 0xF8; - if (twst != TW_MT_DATA_ACK) return 2; - return 0; - } - - byte Fastwire::readBuf(byte device, byte address, byte *data, byte num) { - byte twst, retry; - - retry = 2; - do { - TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO) | (1 << TWSTA); - if (!waitInt()) return 16; - twst = TWSR & 0xF8; - if (twst != TW_START && twst != TW_REP_START) return 17; - - //Serial.print(device, HEX); - //Serial.print(" "); - TWDR = device & 0xfe; // send device address to write - TWCR = (1 << TWINT) | (1 << TWEN); - if (!waitInt()) return 18; - twst = TWSR & 0xF8; - } while (twst == TW_MT_SLA_NACK && retry-- > 0); - if (twst != TW_MT_SLA_ACK) return 19; - - //Serial.print(address, HEX); - //Serial.print(" "); - TWDR = address; // send data to the previously addressed device - TWCR = (1 << TWINT) | (1 << TWEN); - if (!waitInt()) return 20; - twst = TWSR & 0xF8; - if (twst != TW_MT_DATA_ACK) return 21; - - /***/ - - retry = 2; - do { - TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO) | (1 << TWSTA); - if (!waitInt()) return 22; - twst = TWSR & 0xF8; - if (twst != TW_START && twst != TW_REP_START) return 23; - - //Serial.print(device, HEX); - //Serial.print(" "); - TWDR = device | 0x01; // send device address with the read bit (1) - TWCR = (1 << TWINT) | (1 << TWEN); - if (!waitInt()) return 24; - twst = TWSR & 0xF8; - } while (twst == TW_MR_SLA_NACK && retry-- > 0); - if (twst != TW_MR_SLA_ACK) return 25; - - for (uint8_t i = 0; i < num; i++) { - if (i == num - 1) - TWCR = (1 << TWINT) | (1 << TWEN); - else - TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA); - if (!waitInt()) return 26; - twst = TWSR & 0xF8; - if (twst != TW_MR_DATA_ACK && twst != TW_MR_DATA_NACK) return twst; - data[i] = TWDR; - //Serial.print(data[i], HEX); - //Serial.print(" "); - } - //Serial.print("\n"); - stop(); - - return 0; - } - - void Fastwire::reset() { - TWCR = 0; - } - - byte Fastwire::stop() { - TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO); - if (!waitInt()) return 1; - return 0; - } -#endif - -#if I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE - // NBWire implementation based heavily on code by Gene Knight - // Originally posted on the Arduino forum at http://arduino.cc/forum/index.php/topic,70705.0.html - // Originally offered to the i2cdevlib project at http://arduino.cc/forum/index.php/topic,68210.30.html - - /* - call this version 1.0 - - Offhand, the only funky part that I can think of is in nbrequestFrom, where the buffer - length and index are set *before* the data is actually read. The problem is that these - are variables local to the TwoWire object, and by the time we actually have read the - data, and know what the length actually is, we have no simple access to the object's - variables. The actual bytes read *is* given to the callback function, though. - - The ISR code for a slave receiver is commented out. I don't have that setup, and can't - verify it at this time. Save it for 2.0! - - The handling of the read and write processes here is much like in the demo sketch code: - the process is broken down into sequential functions, where each registers the next as a - callback, essentially. - - For example, for the Read process, twi_read00 just returns if TWI is not yet in a - ready state. When there's another interrupt, and the interface *is* ready, then it - sets up the read, starts it, and registers twi_read01 as the function to call after - the *next* interrupt. twi_read01, then, just returns if the interface is still in a - "reading" state. When the reading is done, it copies the information to the buffer, - cleans up, and calls the user-requested callback function with the actual number of - bytes read. - - The writing is similar. - - Questions, comments and problems can go to Gene@Telobot.com. - - Thumbs Up! - Gene Knight - - */ - - uint8_t TwoWire::rxBuffer[NBWIRE_BUFFER_LENGTH]; - uint8_t TwoWire::rxBufferIndex = 0; - uint8_t TwoWire::rxBufferLength = 0; - - uint8_t TwoWire::txAddress = 0; - uint8_t TwoWire::txBuffer[NBWIRE_BUFFER_LENGTH]; - uint8_t TwoWire::txBufferIndex = 0; - uint8_t TwoWire::txBufferLength = 0; - - //uint8_t TwoWire::transmitting = 0; - void (*TwoWire::user_onRequest)(void); - void (*TwoWire::user_onReceive)(int); - - static volatile uint8_t twi_transmitting; - static volatile uint8_t twi_state; - static uint8_t twi_slarw; - static volatile uint8_t twi_error; - static uint8_t twi_masterBuffer[TWI_BUFFER_LENGTH]; - static volatile uint8_t twi_masterBufferIndex; - static uint8_t twi_masterBufferLength; - static uint8_t twi_rxBuffer[TWI_BUFFER_LENGTH]; - static volatile uint8_t twi_rxBufferIndex; - //static volatile uint8_t twi_Interrupt_Continue_Command; - static volatile uint8_t twi_Return_Value; - static volatile uint8_t twi_Done; - void (*twi_cbendTransmissionDone)(int); - void (*twi_cbreadFromDone)(int); - - void twi_init() { - // initialize state - twi_state = TWI_READY; - - // activate internal pull-ups for twi - // as per note from atmega8 manual pg167 - sbi(PORTC, 4); - sbi(PORTC, 5); - - // initialize twi prescaler and bit rate - cbi(TWSR, TWPS0); // TWI Status Register - Prescaler bits - cbi(TWSR, TWPS1); - - /* twi bit rate formula from atmega128 manual pg 204 - SCL Frequency = CPU Clock Frequency / (16 + (2 * TWBR)) - note: TWBR should be 10 or higher for master mode - It is 72 for a 16mhz Wiring board with 100kHz TWI */ - - TWBR = ((CPU_FREQ / TWI_FREQ) - 16) / 2; // bitrate register - // enable twi module, acks, and twi interrupt - - TWCR = (1 << TWEN) | (1 << TWIE) | (1 << TWEA); - - /* TWEN - TWI Enable Bit - TWIE - TWI Interrupt Enable - TWEA - TWI Enable Acknowledge Bit - TWINT - TWI Interrupt Flag - TWSTA - TWI Start Condition - */ - } - - typedef struct { - uint8_t address; - uint8_t* data; - uint8_t length; - uint8_t wait; - uint8_t i; - } twi_Write_Vars; - - twi_Write_Vars *ptwv = 0; - static void (*fNextInterruptFunction)(void) = 0; - - void twi_Finish(byte bRetVal) { - if (ptwv) { - free(ptwv); - ptwv = 0; - } - twi_Done = 0xFF; - twi_Return_Value = bRetVal; - fNextInterruptFunction = 0; - } - - uint8_t twii_WaitForDone(uint16_t timeout) { - uint32_t endMillis = millis() + timeout; - while (!twi_Done && (timeout == 0 || millis() < endMillis)) continue; - return twi_Return_Value; - } - - void twii_SetState(uint8_t ucState) { - twi_state = ucState; - } - - void twii_SetError(uint8_t ucError) { - twi_error = ucError ; - } - - void twii_InitBuffer(uint8_t ucPos, uint8_t ucLength) { - twi_masterBufferIndex = 0; - twi_masterBufferLength = ucLength; - } - - void twii_CopyToBuf(uint8_t* pData, uint8_t ucLength) { - uint8_t i; - for (i = 0; i < ucLength; ++i) { - twi_masterBuffer[i] = pData[i]; - } - } - - void twii_CopyFromBuf(uint8_t *pData, uint8_t ucLength) { - uint8_t i; - for (i = 0; i < ucLength; ++i) { - pData[i] = twi_masterBuffer[i]; - } - } - - void twii_SetSlaRW(uint8_t ucSlaRW) { - twi_slarw = ucSlaRW; - } - - void twii_SetStart() { - TWCR = (1 << TWEN) | (1 << TWIE) | (1 << TWEA) | (1 << TWINT) | (1 << TWSTA); - } - - void twi_write01() { - if (TWI_MTX == twi_state) return; // blocking test - twi_transmitting = 0 ; - if (twi_error == 0xFF) - twi_Finish (0); // success - else if (twi_error == TW_MT_SLA_NACK) - twi_Finish (2); // error: address send, nack received - else if (twi_error == TW_MT_DATA_NACK) - twi_Finish (3); // error: data send, nack received - else - twi_Finish (4); // other twi error - if (twi_cbendTransmissionDone) return twi_cbendTransmissionDone(twi_Return_Value); - return; - } - - - void twi_write00() { - if (TWI_READY != twi_state) return; // blocking test - if (TWI_BUFFER_LENGTH < ptwv -> length) { - twi_Finish(1); // end write with error 1 - return; - } - twi_Done = 0x00; // show as working - twii_SetState(TWI_MTX); // to transmitting - twii_SetError(0xFF); // to No Error - twii_InitBuffer(0, ptwv -> length); // pointer and length - twii_CopyToBuf(ptwv -> data, ptwv -> length); // get the data - twii_SetSlaRW((ptwv -> address << 1) | TW_WRITE); // write command - twii_SetStart(); // start the cycle - fNextInterruptFunction = twi_write01; // next routine - return twi_write01(); - } - - void twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait) { - uint8_t i; - ptwv = (twi_Write_Vars *)malloc(sizeof(twi_Write_Vars)); - ptwv -> address = address; - ptwv -> data = data; - ptwv -> length = length; - ptwv -> wait = wait; - fNextInterruptFunction = twi_write00; - return twi_write00(); - } - - void twi_read01() { - if (TWI_MRX == twi_state) return; // blocking test - if (twi_masterBufferIndex < ptwv -> length) ptwv -> length = twi_masterBufferIndex; - twii_CopyFromBuf(ptwv -> data, ptwv -> length); - twi_Finish(ptwv -> length); - if (twi_cbreadFromDone) return twi_cbreadFromDone(twi_Return_Value); - return; - } - - void twi_read00() { - if (TWI_READY != twi_state) return; // blocking test - if (TWI_BUFFER_LENGTH < ptwv -> length) twi_Finish(0); // error return - twi_Done = 0x00; // show as working - twii_SetState(TWI_MRX); // reading - twii_SetError(0xFF); // reset error - twii_InitBuffer(0, ptwv -> length - 1); // init to one less than length - twii_SetSlaRW((ptwv -> address << 1) | TW_READ); // read command - twii_SetStart(); // start cycle - fNextInterruptFunction = twi_read01; - return twi_read01(); - } - - void twi_readFrom(uint8_t address, uint8_t* data, uint8_t length) { - uint8_t i; - - ptwv = (twi_Write_Vars *)malloc(sizeof(twi_Write_Vars)); - ptwv -> address = address; - ptwv -> data = data; - ptwv -> length = length; - fNextInterruptFunction = twi_read00; - return twi_read00(); - } - - void twi_reply(uint8_t ack) { - // transmit master read ready signal, with or without ack - if (ack){ - TWCR = (1 << TWEN) | (1 << TWIE) | (1 << TWINT) | (1 << TWEA); - } else { - TWCR = (1 << TWEN) | (1 << TWIE) | (1 << TWINT); - } - } - - void twi_stop(void) { - // send stop condition - TWCR = (1 << TWEN) | (1 << TWIE) | (1 << TWEA) | (1 << TWINT) | (1 << TWSTO); - - // wait for stop condition to be exectued on bus - // TWINT is not set after a stop condition! - while (TWCR & (1 << TWSTO)) { - continue; - } - - // update twi state - twi_state = TWI_READY; - } - - void twi_releaseBus(void) { - // release bus - TWCR = (1 << TWEN) | (1 << TWIE) | (1 << TWEA) | (1 << TWINT); - - // update twi state - twi_state = TWI_READY; - } - - SIGNAL(TWI_vect) { - switch (TW_STATUS) { - // All Master - case TW_START: // sent start condition - case TW_REP_START: // sent repeated start condition - // copy device address and r/w bit to output register and ack - TWDR = twi_slarw; - twi_reply(1); - break; - - // Master Transmitter - case TW_MT_SLA_ACK: // slave receiver acked address - case TW_MT_DATA_ACK: // slave receiver acked data - // if there is data to send, send it, otherwise stop - if (twi_masterBufferIndex < twi_masterBufferLength) { - // copy data to output register and ack - TWDR = twi_masterBuffer[twi_masterBufferIndex++]; - twi_reply(1); - } else { - twi_stop(); - } - break; - - case TW_MT_SLA_NACK: // address sent, nack received - twi_error = TW_MT_SLA_NACK; - twi_stop(); - break; - - case TW_MT_DATA_NACK: // data sent, nack received - twi_error = TW_MT_DATA_NACK; - twi_stop(); - break; - - case TW_MT_ARB_LOST: // lost bus arbitration - twi_error = TW_MT_ARB_LOST; - twi_releaseBus(); - break; - - // Master Receiver - case TW_MR_DATA_ACK: // data received, ack sent - // put byte into buffer - twi_masterBuffer[twi_masterBufferIndex++] = TWDR; - - case TW_MR_SLA_ACK: // address sent, ack received - // ack if more bytes are expected, otherwise nack - if (twi_masterBufferIndex < twi_masterBufferLength) { - twi_reply(1); - } else { - twi_reply(0); - } - break; - - case TW_MR_DATA_NACK: // data received, nack sent - // put final byte into buffer - twi_masterBuffer[twi_masterBufferIndex++] = TWDR; - - case TW_MR_SLA_NACK: // address sent, nack received - twi_stop(); - break; - - // TW_MR_ARB_LOST handled by TW_MT_ARB_LOST case - - // Slave Receiver (NOT IMPLEMENTED YET) - /* - case TW_SR_SLA_ACK: // addressed, returned ack - case TW_SR_GCALL_ACK: // addressed generally, returned ack - case TW_SR_ARB_LOST_SLA_ACK: // lost arbitration, returned ack - case TW_SR_ARB_LOST_GCALL_ACK: // lost arbitration, returned ack - // enter slave receiver mode - twi_state = TWI_SRX; - - // indicate that rx buffer can be overwritten and ack - twi_rxBufferIndex = 0; - twi_reply(1); - break; - - case TW_SR_DATA_ACK: // data received, returned ack - case TW_SR_GCALL_DATA_ACK: // data received generally, returned ack - // if there is still room in the rx buffer - if (twi_rxBufferIndex < TWI_BUFFER_LENGTH) { - // put byte in buffer and ack - twi_rxBuffer[twi_rxBufferIndex++] = TWDR; - twi_reply(1); - } else { - // otherwise nack - twi_reply(0); - } - break; - - case TW_SR_STOP: // stop or repeated start condition received - // put a null char after data if there's room - if (twi_rxBufferIndex < TWI_BUFFER_LENGTH) { - twi_rxBuffer[twi_rxBufferIndex] = 0; - } - - // sends ack and stops interface for clock stretching - twi_stop(); - - // callback to user defined callback - twi_onSlaveReceive(twi_rxBuffer, twi_rxBufferIndex); - - // since we submit rx buffer to "wire" library, we can reset it - twi_rxBufferIndex = 0; - - // ack future responses and leave slave receiver state - twi_releaseBus(); - break; - - case TW_SR_DATA_NACK: // data received, returned nack - case TW_SR_GCALL_DATA_NACK: // data received generally, returned nack - // nack back at master - twi_reply(0); - break; - - // Slave Transmitter - case TW_ST_SLA_ACK: // addressed, returned ack - case TW_ST_ARB_LOST_SLA_ACK: // arbitration lost, returned ack - // enter slave transmitter mode - twi_state = TWI_STX; - - // ready the tx buffer index for iteration - twi_txBufferIndex = 0; - - // set tx buffer length to be zero, to verify if user changes it - twi_txBufferLength = 0; - - // request for txBuffer to be filled and length to be set - // note: user must call twi_transmit(bytes, length) to do this - twi_onSlaveTransmit(); - - // if they didn't change buffer & length, initialize it - if (0 == twi_txBufferLength) { - twi_txBufferLength = 1; - twi_txBuffer[0] = 0x00; - } - - // transmit first byte from buffer, fall through - - case TW_ST_DATA_ACK: // byte sent, ack returned - // copy data to output register - TWDR = twi_txBuffer[twi_txBufferIndex++]; - - // if there is more to send, ack, otherwise nack - if (twi_txBufferIndex < twi_txBufferLength) { - twi_reply(1); - } else { - twi_reply(0); - } - break; - - case TW_ST_DATA_NACK: // received nack, we are done - case TW_ST_LAST_DATA: // received ack, but we are done already! - // ack future responses - twi_reply(1); - // leave slave receiver state - twi_state = TWI_READY; - break; - */ - - // all - case TW_NO_INFO: // no state information - break; - - case TW_BUS_ERROR: // bus error, illegal stop/start - twi_error = TW_BUS_ERROR; - twi_stop(); - break; - } - - if (fNextInterruptFunction) return fNextInterruptFunction(); - } - - TwoWire::TwoWire() { } - - void TwoWire::begin(void) { - rxBufferIndex = 0; - rxBufferLength = 0; - - txBufferIndex = 0; - txBufferLength = 0; - - twi_init(); - } - - void TwoWire::beginTransmission(uint8_t address) { - //beginTransmission((uint8_t)address); - - // indicate that we are transmitting - twi_transmitting = 1; - - // set address of targeted slave - txAddress = address; - - // reset tx buffer iterator vars - txBufferIndex = 0; - txBufferLength = 0; - } - - uint8_t TwoWire::endTransmission(uint16_t timeout) { - // transmit buffer (blocking) - //int8_t ret = - twi_cbendTransmissionDone = NULL; - twi_writeTo(txAddress, txBuffer, txBufferLength, 1); - int8_t ret = twii_WaitForDone(timeout); - - // reset tx buffer iterator vars - txBufferIndex = 0; - txBufferLength = 0; - - // indicate that we are done transmitting - // twi_transmitting = 0; - return ret; - } - - void TwoWire::nbendTransmission(void (*function)(int)) { - twi_cbendTransmissionDone = function; - twi_writeTo(txAddress, txBuffer, txBufferLength, 1); - return; - } - - void TwoWire::send(uint8_t data) { - if (twi_transmitting) { - // in master transmitter mode - // don't bother if buffer is full - if (txBufferLength >= NBWIRE_BUFFER_LENGTH) { - return; - } - - // put byte in tx buffer - txBuffer[txBufferIndex] = data; - ++txBufferIndex; - - // update amount in buffer - txBufferLength = txBufferIndex; - } else { - // in slave send mode - // reply to master - //twi_transmit(&data, 1); - } - } - - uint8_t TwoWire::receive(void) { - // default to returning null char - // for people using with char strings - uint8_t value = 0; - - // get each successive byte on each call - if (rxBufferIndex < rxBufferLength) { - value = rxBuffer[rxBufferIndex]; - ++rxBufferIndex; - } - - return value; - } - - uint8_t TwoWire::requestFrom(uint8_t address, int quantity, uint16_t timeout) { - // clamp to buffer length - if (quantity > NBWIRE_BUFFER_LENGTH) { - quantity = NBWIRE_BUFFER_LENGTH; - } - - // perform blocking read into buffer - twi_cbreadFromDone = NULL; - twi_readFrom(address, rxBuffer, quantity); - uint8_t read = twii_WaitForDone(timeout); - - // set rx buffer iterator vars - rxBufferIndex = 0; - rxBufferLength = read; - - return read; - } - - void TwoWire::nbrequestFrom(uint8_t address, int quantity, void (*function)(int)) { - // clamp to buffer length - if (quantity > NBWIRE_BUFFER_LENGTH) { - quantity = NBWIRE_BUFFER_LENGTH; - } - - // perform blocking read into buffer - twi_cbreadFromDone = function; - twi_readFrom(address, rxBuffer, quantity); - //uint8_t read = twii_WaitForDone(); - - // set rx buffer iterator vars - //rxBufferIndex = 0; - //rxBufferLength = read; - - rxBufferIndex = 0; - rxBufferLength = quantity; // this is a hack - - return; //read; - } - - uint8_t TwoWire::available(void) { - return rxBufferLength - rxBufferIndex; - } - -#endif diff --git a/LinuxI2CDev/I2Cdev/I2Cdev.h b/LinuxI2CDev/I2Cdev/I2Cdev.h index 5b59c56f..e6881570 100644 --- a/LinuxI2CDev/I2Cdev/I2Cdev.h +++ b/LinuxI2CDev/I2Cdev/I2Cdev.h @@ -49,66 +49,7 @@ THE SOFTWARE. #ifndef _I2CDEV_H_ #define _I2CDEV_H_ -// ----------------------------------------------------------------------------- -// Enable deprecated pgmspace typedefs in avr-libc -// ----------------------------------------------------------------------------- -#define __PROG_TYPES_COMPAT__ - -// ----------------------------------------------------------------------------- -// I2C interface implementation setting -// ----------------------------------------------------------------------------- -#ifndef I2CDEV_IMPLEMENTATION -#define I2CDEV_IMPLEMENTATION I2CDEV_ARDUINO_WIRE -//#define I2CDEV_IMPLEMENTATION I2CDEV_TEENSY_3X_WIRE -//#define I2CDEV_IMPLEMENTATION I2CDEV_BUILTIN_SBWIRE -//#define I2CDEV_IMPLEMENTATION I2CDEV_BUILTIN_FASTWIRE -#endif // I2CDEV_IMPLEMENTATION - -// comment this out if you are using a non-optimal IDE/implementation setting -// but want the compiler to shut up about it -#define I2CDEV_IMPLEMENTATION_WARNINGS - -// ----------------------------------------------------------------------------- -// I2C interface implementation options -// ----------------------------------------------------------------------------- -#define I2CDEV_ARDUINO_WIRE 1 // Wire object from Arduino -#define I2CDEV_BUILTIN_NBWIRE 2 // Tweaked Wire object from Gene Knight's NBWire project - // ^^^ NBWire implementation is still buggy w/some interrupts! -#define I2CDEV_BUILTIN_FASTWIRE 3 // FastWire object from Francesco Ferrara's project -#define I2CDEV_I2CMASTER_LIBRARY 4 // I2C object from DSSCircuits I2C-Master Library at https://github.com/DSSCircuits/I2C-Master-Library -#define I2CDEV_BUILTIN_SBWIRE 5 // I2C object from Shuning (Steve) Bian's SBWire Library at https://github.com/freespace/SBWire -#define I2CDEV_TEENSY_3X_WIRE 6 // Teensy 3.x support using i2c_t3 library - -// ----------------------------------------------------------------------------- -// Arduino-style "Serial.print" debug constant (uncomment to enable) -// ----------------------------------------------------------------------------- -//#define I2CDEV_SERIAL_DEBUG - -#ifdef ARDUINO - #if ARDUINO < 100 - #include "WProgram.h" - #else - #include "Arduino.h" - #endif - #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE - #include - #endif - #if I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE - #include - #endif - #if I2CDEV_IMPLEMENTATION == I2CDEV_I2CMASTER_LIBRARY - #include - #endif - #if I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE - #include "SBWire.h" - #endif -#endif - -#ifdef SPARK - #include "application.h" - #define ARDUINO 101 - #define BUFFER_LENGTH 32 -#endif +#include #ifndef I2CDEVLIB_WIRE_BUFFER_LENGTH #if defined(I2C_BUFFER_LENGTH) @@ -126,6 +67,7 @@ THE SOFTWARE. #endif #endif +// ----------------------------------------------------------------------------- // 1000ms default read timeout (modify with "I2Cdev::readTimeout = [ms];") #define I2CDEV_DEFAULT_READ_TIMEOUT 1000 @@ -133,6 +75,7 @@ class I2Cdev { public: I2Cdev(); + static void initialize(const char* i2cDev); static int8_t readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout, void *wireObj=0); static int8_t readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout, void *wireObj=0); static int8_t readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout, void *wireObj=0); @@ -154,158 +97,4 @@ class I2Cdev { static uint16_t readTimeout; }; -#if I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE - ////////////////////// - // FastWire 0.24 - // This is a library to help faster programs to read I2C devices. - // Copyright(C) 2012 - // Francesco Ferrara - ////////////////////// - - /* Master */ - #define TW_START 0x08 - #define TW_REP_START 0x10 - - /* Master Transmitter */ - #define TW_MT_SLA_ACK 0x18 - #define TW_MT_SLA_NACK 0x20 - #define TW_MT_DATA_ACK 0x28 - #define TW_MT_DATA_NACK 0x30 - #define TW_MT_ARB_LOST 0x38 - - /* Master Receiver */ - #define TW_MR_ARB_LOST 0x38 - #define TW_MR_SLA_ACK 0x40 - #define TW_MR_SLA_NACK 0x48 - #define TW_MR_DATA_ACK 0x50 - #define TW_MR_DATA_NACK 0x58 - - #define TW_OK 0 - #define TW_ERROR 1 - - class Fastwire { - private: - static boolean waitInt(); - - public: - static void setup(int khz, boolean pullup); - static byte beginTransmission(byte device); - static byte write(byte value); - static byte writeBuf(byte device, byte address, byte *data, byte num); - static byte readBuf(byte device, byte address, byte *data, byte num); - static void reset(); - static byte stop(); - }; -#endif - -#if I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE - // NBWire implementation based heavily on code by Gene Knight - // Originally posted on the Arduino forum at http://arduino.cc/forum/index.php/topic,70705.0.html - // Originally offered to the i2cdevlib project at http://arduino.cc/forum/index.php/topic,68210.30.html - - #define NBWIRE_BUFFER_LENGTH 32 - - class TwoWire { - private: - static uint8_t rxBuffer[]; - static uint8_t rxBufferIndex; - static uint8_t rxBufferLength; - - static uint8_t txAddress; - static uint8_t txBuffer[]; - static uint8_t txBufferIndex; - static uint8_t txBufferLength; - - // static uint8_t transmitting; - static void (*user_onRequest)(void); - static void (*user_onReceive)(int); - static void onRequestService(void); - static void onReceiveService(uint8_t*, int); - - public: - TwoWire(); - void begin(); - void begin(uint8_t); - void begin(int); - void beginTransmission(uint8_t); - //void beginTransmission(int); - uint8_t endTransmission(uint16_t timeout=0); - void nbendTransmission(void (*function)(int)) ; - uint8_t requestFrom(uint8_t, int, uint16_t timeout=0); - //uint8_t requestFrom(int, int); - void nbrequestFrom(uint8_t, int, void (*function)(int)); - void send(uint8_t); - void send(uint8_t*, uint8_t); - //void send(int); - void send(char*); - uint8_t available(void); - uint8_t receive(void); - void onReceive(void (*)(int)); - void onRequest(void (*)(void)); - }; - - #define TWI_READY 0 - #define TWI_MRX 1 - #define TWI_MTX 2 - #define TWI_SRX 3 - #define TWI_STX 4 - - #define TW_WRITE 0 - #define TW_READ 1 - - #define TW_MT_SLA_NACK 0x20 - #define TW_MT_DATA_NACK 0x30 - - #define CPU_FREQ 16000000L - #define TWI_FREQ 100000L - #define TWI_BUFFER_LENGTH 32 - - /* TWI Status is in TWSR, in the top 5 bits: TWS7 - TWS3 */ - - #define TW_STATUS_MASK ((1 << TWS7)|(1 << TWS6)|(1 << TWS5)|(1 << TWS4)|(1 << TWS3)) - #define TW_STATUS (TWSR & TW_STATUS_MASK) - #define TW_START 0x08 - #define TW_REP_START 0x10 - #define TW_MT_SLA_ACK 0x18 - #define TW_MT_SLA_NACK 0x20 - #define TW_MT_DATA_ACK 0x28 - #define TW_MT_DATA_NACK 0x30 - #define TW_MT_ARB_LOST 0x38 - #define TW_MR_ARB_LOST 0x38 - #define TW_MR_SLA_ACK 0x40 - #define TW_MR_SLA_NACK 0x48 - #define TW_MR_DATA_ACK 0x50 - #define TW_MR_DATA_NACK 0x58 - #define TW_ST_SLA_ACK 0xA8 - #define TW_ST_ARB_LOST_SLA_ACK 0xB0 - #define TW_ST_DATA_ACK 0xB8 - #define TW_ST_DATA_NACK 0xC0 - #define TW_ST_LAST_DATA 0xC8 - #define TW_SR_SLA_ACK 0x60 - #define TW_SR_ARB_LOST_SLA_ACK 0x68 - #define TW_SR_GCALL_ACK 0x70 - #define TW_SR_ARB_LOST_GCALL_ACK 0x78 - #define TW_SR_DATA_ACK 0x80 - #define TW_SR_DATA_NACK 0x88 - #define TW_SR_GCALL_DATA_ACK 0x90 - #define TW_SR_GCALL_DATA_NACK 0x98 - #define TW_SR_STOP 0xA0 - #define TW_NO_INFO 0xF8 - #define TW_BUS_ERROR 0x00 - - //#define _MMIO_BYTE(mem_addr) (*(volatile uint8_t *)(mem_addr)) - //#define _SFR_BYTE(sfr) _MMIO_BYTE(_SFR_ADDR(sfr)) - - #ifndef sbi // set bit - #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= (1 << bit)) - #endif // sbi - - #ifndef cbi // clear bit - #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~(1 << bit)) - #endif // cbi - - extern TwoWire Wire; - -#endif // I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE - #endif /* _I2CDEV_H_ */ From 69c9f64b623b3c6f391d6e04da95c2f327454370 Mon Sep 17 00:00:00 2001 From: Hananja from Raspberry Pi Zero 2 W Date: Thu, 1 Feb 2024 09:11:01 +0100 Subject: [PATCH 329/335] Copy Arduino MPU6050 --- LinuxI2CDev/MPU6050/MPU6050.cpp | 3397 +++++++++++++++++ LinuxI2CDev/MPU6050/MPU6050.h | 852 +++++ .../MPU6050/MPU6050_6Axis_MotionApps20.cpp | 616 +++ .../MPU6050/MPU6050_6Axis_MotionApps20.h | 153 + LinuxI2CDev/MPU6050/helper_3dmath.h | 216 ++ 5 files changed, 5234 insertions(+) create mode 100644 LinuxI2CDev/MPU6050/MPU6050.cpp create mode 100644 LinuxI2CDev/MPU6050/MPU6050.h create mode 100644 LinuxI2CDev/MPU6050/MPU6050_6Axis_MotionApps20.cpp create mode 100644 LinuxI2CDev/MPU6050/MPU6050_6Axis_MotionApps20.h create mode 100644 LinuxI2CDev/MPU6050/helper_3dmath.h diff --git a/LinuxI2CDev/MPU6050/MPU6050.cpp b/LinuxI2CDev/MPU6050/MPU6050.cpp new file mode 100644 index 00000000..ae145004 --- /dev/null +++ b/LinuxI2CDev/MPU6050/MPU6050.cpp @@ -0,0 +1,3397 @@ +// I2Cdev library collection - MPU6050 I2C device class +// Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00) +// 8/24/2011 by Jeff Rowberg +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// 2021-09-27 - split implementations out of header files, finally +// 2019-07-08 - Added Auto Calibration routine +// ... - ongoing debug release + +// NOTE: THIS IS ONLY A PARIAL RELEASE. THIS DEVICE CLASS IS CURRENTLY UNDERGOING ACTIVE +// DEVELOPMENT AND IS STILL MISSING SOME IMPORTANT FEATURES. PLEASE KEEP THIS IN MIND IF +// YOU DECIDE TO USE THIS PARTICULAR CODE FOR ANYTHING. + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2012 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#include "MPU6050.h" + +/** Specific address constructor. + * @param address I2C address, uses default I2C address if none is specified + * @see MPU6050_DEFAULT_ADDRESS + * @see MPU6050_ADDRESS_AD0_LOW + * @see MPU6050_ADDRESS_AD0_HIGH + */ +MPU6050_Base::MPU6050_Base(uint8_t address, void *wireObj):devAddr(address), wireObj(wireObj) { +} + +/** Power on and prepare for general usage. + * This will activate the device and take it out of sleep mode (which must be done + * after start-up). This function also sets both the accelerometer and the gyroscope + * to their most sensitive settings, namely +/- 2g and +/- 250 degrees/sec, and sets + * the clock source to use the X Gyro for reference, which is slightly better than + * the default internal clock source. + */ +void MPU6050_Base::initialize() { + setClockSource(MPU6050_CLOCK_PLL_XGYRO); + setFullScaleGyroRange(MPU6050_GYRO_FS_250); + setFullScaleAccelRange(MPU6050_ACCEL_FS_2); + setSleepEnabled(false); // thanks to Jack Elston for pointing this one out! +} + +/** Verify the I2C connection. + * Make sure the device is connected and responds as expected. + * @return True if connection is valid, false otherwise + */ +bool MPU6050_Base::testConnection() { + return getDeviceID() == 0x34; +} + +// AUX_VDDIO register (InvenSense demo code calls this RA_*G_OFFS_TC) + +/** Get the auxiliary I2C supply voltage level. + * When set to 1, the auxiliary I2C bus high logic level is VDD. When cleared to + * 0, the auxiliary I2C bus high logic level is VLOGIC. This does not apply to + * the MPU-6000, which does not have a VLOGIC pin. + * @return I2C supply voltage level (0=VLOGIC, 1=VDD) + */ +uint8_t MPU6050_Base::getAuxVDDIOLevel() { + I2Cdev::readBit(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_PWR_MODE_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set the auxiliary I2C supply voltage level. + * When set to 1, the auxiliary I2C bus high logic level is VDD. When cleared to + * 0, the auxiliary I2C bus high logic level is VLOGIC. This does not apply to + * the MPU-6000, which does not have a VLOGIC pin. + * @param level I2C supply voltage level (0=VLOGIC, 1=VDD) + */ +void MPU6050_Base::setAuxVDDIOLevel(uint8_t level) { + I2Cdev::writeBit(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_PWR_MODE_BIT, level, wireObj); +} + +// SMPLRT_DIV register + +/** Get gyroscope output rate divider. + * The sensor register output, FIFO output, DMP sampling, Motion detection, Zero + * Motion detection, and Free Fall detection are all based on the Sample Rate. + * The Sample Rate is generated by dividing the gyroscope output rate by + * SMPLRT_DIV: + * + * Sample Rate = Gyroscope Output Rate / (1 + SMPLRT_DIV) + * + * where Gyroscope Output Rate = 8kHz when the DLPF is disabled (DLPF_CFG = 0 or + * 7), and 1kHz when the DLPF is enabled (see Register 26). + * + * Note: The accelerometer output rate is 1kHz. This means that for a Sample + * Rate greater than 1kHz, the same accelerometer sample may be output to the + * FIFO, DMP, and sensor registers more than once. + * + * For a diagram of the gyroscope and accelerometer signal paths, see Section 8 + * of the MPU-6000/MPU-6050 Product Specification document. + * + * @return Current sample rate + * @see MPU6050_RA_SMPLRT_DIV + */ +uint8_t MPU6050_Base::getRate() { + I2Cdev::readByte(devAddr, MPU6050_RA_SMPLRT_DIV, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set gyroscope sample rate divider. + * @param rate New sample rate divider + * @see getRate() + * @see MPU6050_RA_SMPLRT_DIV + */ +void MPU6050_Base::setRate(uint8_t rate) { + I2Cdev::writeByte(devAddr, MPU6050_RA_SMPLRT_DIV, rate, wireObj); +} + +// CONFIG register + +/** Get external FSYNC configuration. + * Configures the external Frame Synchronization (FSYNC) pin sampling. An + * external signal connected to the FSYNC pin can be sampled by configuring + * EXT_SYNC_SET. Signal changes to the FSYNC pin are latched so that short + * strobes may be captured. The latched FSYNC signal will be sampled at the + * Sampling Rate, as defined in register 25. After sampling, the latch will + * reset to the current FSYNC signal state. + * + * The sampled value will be reported in place of the least significant bit in + * a sensor data register determined by the value of EXT_SYNC_SET according to + * the following table. + * + *
+ * EXT_SYNC_SET | FSYNC Bit Location
+ * -------------+-------------------
+ * 0            | Input disabled
+ * 1            | TEMP_OUT_L[0]
+ * 2            | GYRO_XOUT_L[0]
+ * 3            | GYRO_YOUT_L[0]
+ * 4            | GYRO_ZOUT_L[0]
+ * 5            | ACCEL_XOUT_L[0]
+ * 6            | ACCEL_YOUT_L[0]
+ * 7            | ACCEL_ZOUT_L[0]
+ * 
+ * + * @return FSYNC configuration value + */ +uint8_t MPU6050_Base::getExternalFrameSync() { + I2Cdev::readBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_EXT_SYNC_SET_BIT, MPU6050_CFG_EXT_SYNC_SET_LENGTH, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set external FSYNC configuration. + * @see getExternalFrameSync() + * @see MPU6050_RA_CONFIG + * @param sync New FSYNC configuration value + */ +void MPU6050_Base::setExternalFrameSync(uint8_t sync) { + I2Cdev::writeBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_EXT_SYNC_SET_BIT, MPU6050_CFG_EXT_SYNC_SET_LENGTH, sync, wireObj); +} +/** Get digital low-pass filter configuration. + * The DLPF_CFG parameter sets the digital low pass filter configuration. It + * also determines the internal sampling rate used by the device as shown in + * the table below. + * + * Note: The accelerometer output rate is 1kHz. This means that for a Sample + * Rate greater than 1kHz, the same accelerometer sample may be output to the + * FIFO, DMP, and sensor registers more than once. + * + *
+ *          |   ACCELEROMETER    |           GYROSCOPE
+ * DLPF_CFG | Bandwidth | Delay  | Bandwidth | Delay  | Sample Rate
+ * ---------+-----------+--------+-----------+--------+-------------
+ * 0        | 260Hz     | 0ms    | 256Hz     | 0.98ms | 8kHz
+ * 1        | 184Hz     | 2.0ms  | 188Hz     | 1.9ms  | 1kHz
+ * 2        | 94Hz      | 3.0ms  | 98Hz      | 2.8ms  | 1kHz
+ * 3        | 44Hz      | 4.9ms  | 42Hz      | 4.8ms  | 1kHz
+ * 4        | 21Hz      | 8.5ms  | 20Hz      | 8.3ms  | 1kHz
+ * 5        | 10Hz      | 13.8ms | 10Hz      | 13.4ms | 1kHz
+ * 6        | 5Hz       | 19.0ms | 5Hz       | 18.6ms | 1kHz
+ * 7        |   -- Reserved --   |   -- Reserved --   | Reserved
+ * 
+ * + * @return DLFP configuration + * @see MPU6050_RA_CONFIG + * @see MPU6050_CFG_DLPF_CFG_BIT + * @see MPU6050_CFG_DLPF_CFG_LENGTH + */ +uint8_t MPU6050_Base::getDLPFMode() { + I2Cdev::readBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_DLPF_CFG_BIT, MPU6050_CFG_DLPF_CFG_LENGTH, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set digital low-pass filter configuration. + * @param mode New DLFP configuration setting + * @see getDLPFBandwidth() + * @see MPU6050_DLPF_BW_256 + * @see MPU6050_RA_CONFIG + * @see MPU6050_CFG_DLPF_CFG_BIT + * @see MPU6050_CFG_DLPF_CFG_LENGTH + */ +void MPU6050_Base::setDLPFMode(uint8_t mode) { + I2Cdev::writeBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_DLPF_CFG_BIT, MPU6050_CFG_DLPF_CFG_LENGTH, mode, wireObj); +} + +// GYRO_CONFIG register + +/** Get full-scale gyroscope range. + * The FS_SEL parameter allows setting the full-scale range of the gyro sensors, + * as described in the table below. + * + *
+ * 0 = +/- 250 degrees/sec
+ * 1 = +/- 500 degrees/sec
+ * 2 = +/- 1000 degrees/sec
+ * 3 = +/- 2000 degrees/sec
+ * 
+ * + * @return Current full-scale gyroscope range setting + * @see MPU6050_GYRO_FS_250 + * @see MPU6050_RA_GYRO_CONFIG + * @see MPU6050_GCONFIG_FS_SEL_BIT + * @see MPU6050_GCONFIG_FS_SEL_LENGTH + */ +uint8_t MPU6050_Base::getFullScaleGyroRange() { + I2Cdev::readBits(devAddr, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set full-scale gyroscope range. + * @param range New full-scale gyroscope range value + * @see getFullScaleRange() + * @see MPU6050_GYRO_FS_250 + * @see MPU6050_RA_GYRO_CONFIG + * @see MPU6050_GCONFIG_FS_SEL_BIT + * @see MPU6050_GCONFIG_FS_SEL_LENGTH + */ +void MPU6050_Base::setFullScaleGyroRange(uint8_t range) { + I2Cdev::writeBits(devAddr, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, range, wireObj); +} + +// SELF TEST FACTORY TRIM VALUES + +/** Get self-test factory trim value for accelerometer X axis. + * @return factory trim value + * @see MPU6050_RA_SELF_TEST_X + */ +uint8_t MPU6050_Base::getAccelXSelfTestFactoryTrim() { + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_X, &buffer[0], I2Cdev::readTimeout, wireObj); + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_A, &buffer[1], I2Cdev::readTimeout, wireObj); + return (buffer[0]>>3) | ((buffer[1]>>4) & 0x03); +} + +/** Get self-test factory trim value for accelerometer Y axis. + * @return factory trim value + * @see MPU6050_RA_SELF_TEST_Y + */ +uint8_t MPU6050_Base::getAccelYSelfTestFactoryTrim() { + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_Y, &buffer[0], I2Cdev::readTimeout, wireObj); + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_A, &buffer[1], I2Cdev::readTimeout, wireObj); + return (buffer[0]>>3) | ((buffer[1]>>2) & 0x03); +} + +/** Get self-test factory trim value for accelerometer Z axis. + * @return factory trim value + * @see MPU6050_RA_SELF_TEST_Z + */ +uint8_t MPU6050_Base::getAccelZSelfTestFactoryTrim() { + I2Cdev::readBytes(devAddr, MPU6050_RA_SELF_TEST_Z, 2, buffer, I2Cdev::readTimeout, wireObj); + return (buffer[0]>>3) | (buffer[1] & 0x03); +} + +/** Get self-test factory trim value for gyro X axis. + * @return factory trim value + * @see MPU6050_RA_SELF_TEST_X + */ +uint8_t MPU6050_Base::getGyroXSelfTestFactoryTrim() { + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_X, buffer, I2Cdev::readTimeout, wireObj); + return (buffer[0] & 0x1F); +} + +/** Get self-test factory trim value for gyro Y axis. + * @return factory trim value + * @see MPU6050_RA_SELF_TEST_Y + */ +uint8_t MPU6050_Base::getGyroYSelfTestFactoryTrim() { + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_Y, buffer, I2Cdev::readTimeout, wireObj); + return (buffer[0] & 0x1F); +} + +/** Get self-test factory trim value for gyro Z axis. + * @return factory trim value + * @see MPU6050_RA_SELF_TEST_Z + */ +uint8_t MPU6050_Base::getGyroZSelfTestFactoryTrim() { + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_Z, buffer, I2Cdev::readTimeout, wireObj); + return (buffer[0] & 0x1F); +} + +// ACCEL_CONFIG register + +/** Get self-test enabled setting for accelerometer X axis. + * @return Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +bool MPU6050_Base::getAccelXSelfTest() { + I2Cdev::readBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_XA_ST_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Get self-test enabled setting for accelerometer X axis. + * @param enabled Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050_Base::setAccelXSelfTest(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_XA_ST_BIT, enabled, wireObj); +} +/** Get self-test enabled value for accelerometer Y axis. + * @return Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +bool MPU6050_Base::getAccelYSelfTest() { + I2Cdev::readBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_YA_ST_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Get self-test enabled value for accelerometer Y axis. + * @param enabled Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050_Base::setAccelYSelfTest(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_YA_ST_BIT, enabled, wireObj); +} +/** Get self-test enabled value for accelerometer Z axis. + * @return Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +bool MPU6050_Base::getAccelZSelfTest() { + I2Cdev::readBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ZA_ST_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set self-test enabled value for accelerometer Z axis. + * @param enabled Self-test enabled value + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050_Base::setAccelZSelfTest(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ZA_ST_BIT, enabled, wireObj); +} +/** Get full-scale accelerometer range. + * The FS_SEL parameter allows setting the full-scale range of the accelerometer + * sensors, as described in the table below. + * + *
+ * 0 = +/- 2g
+ * 1 = +/- 4g
+ * 2 = +/- 8g
+ * 3 = +/- 16g
+ * 
+ * + * @return Current full-scale accelerometer range setting + * @see MPU6050_ACCEL_FS_2 + * @see MPU6050_RA_ACCEL_CONFIG + * @see MPU6050_ACONFIG_AFS_SEL_BIT + * @see MPU6050_ACONFIG_AFS_SEL_LENGTH + */ +uint8_t MPU6050_Base::getFullScaleAccelRange() { + I2Cdev::readBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set full-scale accelerometer range. + * @param range New full-scale accelerometer range setting + * @see getFullScaleAccelRange() + */ +void MPU6050_Base::setFullScaleAccelRange(uint8_t range) { + I2Cdev::writeBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, range, wireObj); +} +/** Get the high-pass filter configuration. + * The DHPF is a filter module in the path leading to motion detectors (Free + * Fall, Motion threshold, and Zero Motion). The high pass filter output is not + * available to the data registers (see Figure in Section 8 of the MPU-6000/ + * MPU-6050 Product Specification document). + * + * The high pass filter has three modes: + * + *
+ *    Reset: The filter output settles to zero within one sample. This
+ *           effectively disables the high pass filter. This mode may be toggled
+ *           to quickly settle the filter.
+ *
+ *    On:    The high pass filter will pass signals above the cut off frequency.
+ *
+ *    Hold:  When triggered, the filter holds the present sample. The filter
+ *           output will be the difference between the input sample and the held
+ *           sample.
+ * 
+ * + *
+ * ACCEL_HPF | Filter Mode | Cut-off Frequency
+ * ----------+-------------+------------------
+ * 0         | Reset       | None
+ * 1         | On          | 5Hz
+ * 2         | On          | 2.5Hz
+ * 3         | On          | 1.25Hz
+ * 4         | On          | 0.63Hz
+ * 7         | Hold        | None
+ * 
+ * + * @return Current high-pass filter configuration + * @see MPU6050_DHPF_RESET + * @see MPU6050_RA_ACCEL_CONFIG + */ +uint8_t MPU6050_Base::getDHPFMode() { + I2Cdev::readBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ACCEL_HPF_BIT, MPU6050_ACONFIG_ACCEL_HPF_LENGTH, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set the high-pass filter configuration. + * @param bandwidth New high-pass filter configuration + * @see setDHPFMode() + * @see MPU6050_DHPF_RESET + * @see MPU6050_RA_ACCEL_CONFIG + */ +void MPU6050_Base::setDHPFMode(uint8_t bandwidth) { + I2Cdev::writeBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ACCEL_HPF_BIT, MPU6050_ACONFIG_ACCEL_HPF_LENGTH, bandwidth, wireObj); +} + +// FF_THR register + +/** Get free-fall event acceleration threshold. + * This register configures the detection threshold for Free Fall event + * detection. The unit of FF_THR is 1LSB = 2mg. Free Fall is detected when the + * absolute value of the accelerometer measurements for the three axes are each + * less than the detection threshold. This condition increments the Free Fall + * duration counter (Register 30). The Free Fall interrupt is triggered when the + * Free Fall duration counter reaches the time specified in FF_DUR. + * + * For more details on the Free Fall detection interrupt, see Section 8.2 of the + * MPU-6000/MPU-6050 Product Specification document as well as Registers 56 and + * 58 of this document. + * + * @return Current free-fall acceleration threshold value (LSB = 2mg) + * @see MPU6050_RA_FF_THR + */ +uint8_t MPU6050_Base::getFreefallDetectionThreshold() { + I2Cdev::readByte(devAddr, MPU6050_RA_FF_THR, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Get free-fall event acceleration threshold. + * @param threshold New free-fall acceleration threshold value (LSB = 2mg) + * @see getFreefallDetectionThreshold() + * @see MPU6050_RA_FF_THR + */ +void MPU6050_Base::setFreefallDetectionThreshold(uint8_t threshold) { + I2Cdev::writeByte(devAddr, MPU6050_RA_FF_THR, threshold, wireObj); +} + +// FF_DUR register + +/** Get free-fall event duration threshold. + * This register configures the duration counter threshold for Free Fall event + * detection. The duration counter ticks at 1kHz, therefore FF_DUR has a unit + * of 1 LSB = 1 ms. + * + * The Free Fall duration counter increments while the absolute value of the + * accelerometer measurements are each less than the detection threshold + * (Register 29). The Free Fall interrupt is triggered when the Free Fall + * duration counter reaches the time specified in this register. + * + * For more details on the Free Fall detection interrupt, see Section 8.2 of + * the MPU-6000/MPU-6050 Product Specification document as well as Registers 56 + * and 58 of this document. + * + * @return Current free-fall duration threshold value (LSB = 1ms) + * @see MPU6050_RA_FF_DUR + */ +uint8_t MPU6050_Base::getFreefallDetectionDuration() { + I2Cdev::readByte(devAddr, MPU6050_RA_FF_DUR, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Get free-fall event duration threshold. + * @param duration New free-fall duration threshold value (LSB = 1ms) + * @see getFreefallDetectionDuration() + * @see MPU6050_RA_FF_DUR + */ +void MPU6050_Base::setFreefallDetectionDuration(uint8_t duration) { + I2Cdev::writeByte(devAddr, MPU6050_RA_FF_DUR, duration, wireObj); +} + +// MOT_THR register + +/** Get motion detection event acceleration threshold. + * This register configures the detection threshold for Motion interrupt + * generation. The unit of MOT_THR is 1LSB = 2mg. Motion is detected when the + * absolute value of any of the accelerometer measurements exceeds this Motion + * detection threshold. This condition increments the Motion detection duration + * counter (Register 32). The Motion detection interrupt is triggered when the + * Motion Detection counter reaches the time count specified in MOT_DUR + * (Register 32). + * + * The Motion interrupt will indicate the axis and polarity of detected motion + * in MOT_DETECT_STATUS (Register 97). + * + * For more details on the Motion detection interrupt, see Section 8.3 of the + * MPU-6000/MPU-6050 Product Specification document as well as Registers 56 and + * 58 of this document. + * + * @return Current motion detection acceleration threshold value (LSB = 2mg) + * @see MPU6050_RA_MOT_THR + */ +uint8_t MPU6050_Base::getMotionDetectionThreshold() { + I2Cdev::readByte(devAddr, MPU6050_RA_MOT_THR, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set motion detection event acceleration threshold. + * @param threshold New motion detection acceleration threshold value (LSB = 2mg) + * @see getMotionDetectionThreshold() + * @see MPU6050_RA_MOT_THR + */ +void MPU6050_Base::setMotionDetectionThreshold(uint8_t threshold) { + I2Cdev::writeByte(devAddr, MPU6050_RA_MOT_THR, threshold, wireObj); +} + +// MOT_DUR register + +/** Get motion detection event duration threshold. + * This register configures the duration counter threshold for Motion interrupt + * generation. The duration counter ticks at 1 kHz, therefore MOT_DUR has a unit + * of 1LSB = 1ms. The Motion detection duration counter increments when the + * absolute value of any of the accelerometer measurements exceeds the Motion + * detection threshold (Register 31). The Motion detection interrupt is + * triggered when the Motion detection counter reaches the time count specified + * in this register. + * + * For more details on the Motion detection interrupt, see Section 8.3 of the + * MPU-6000/MPU-6050 Product Specification document. + * + * @return Current motion detection duration threshold value (LSB = 1ms) + * @see MPU6050_RA_MOT_DUR + */ +uint8_t MPU6050_Base::getMotionDetectionDuration() { + I2Cdev::readByte(devAddr, MPU6050_RA_MOT_DUR, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set motion detection event duration threshold. + * @param duration New motion detection duration threshold value (LSB = 1ms) + * @see getMotionDetectionDuration() + * @see MPU6050_RA_MOT_DUR + */ +void MPU6050_Base::setMotionDetectionDuration(uint8_t duration) { + I2Cdev::writeByte(devAddr, MPU6050_RA_MOT_DUR, duration, wireObj); +} + +// ZRMOT_THR register + +/** Get zero motion detection event acceleration threshold. + * This register configures the detection threshold for Zero Motion interrupt + * generation. The unit of ZRMOT_THR is 1LSB = 2mg. Zero Motion is detected when + * the absolute value of the accelerometer measurements for the 3 axes are each + * less than the detection threshold. This condition increments the Zero Motion + * duration counter (Register 34). The Zero Motion interrupt is triggered when + * the Zero Motion duration counter reaches the time count specified in + * ZRMOT_DUR (Register 34). + * + * Unlike Free Fall or Motion detection, Zero Motion detection triggers an + * interrupt both when Zero Motion is first detected and when Zero Motion is no + * longer detected. + * + * When a zero motion event is detected, a Zero Motion Status will be indicated + * in the MOT_DETECT_STATUS register (Register 97). When a motion-to-zero-motion + * condition is detected, the status bit is set to 1. When a zero-motion-to- + * motion condition is detected, the status bit is set to 0. + * + * For more details on the Zero Motion detection interrupt, see Section 8.4 of + * the MPU-6000/MPU-6050 Product Specification document as well as Registers 56 + * and 58 of this document. + * + * @return Current zero motion detection acceleration threshold value (LSB = 2mg) + * @see MPU6050_RA_ZRMOT_THR + */ +uint8_t MPU6050_Base::getZeroMotionDetectionThreshold() { + I2Cdev::readByte(devAddr, MPU6050_RA_ZRMOT_THR, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set zero motion detection event acceleration threshold. + * @param threshold New zero motion detection acceleration threshold value (LSB = 2mg) + * @see getZeroMotionDetectionThreshold() + * @see MPU6050_RA_ZRMOT_THR + */ +void MPU6050_Base::setZeroMotionDetectionThreshold(uint8_t threshold) { + I2Cdev::writeByte(devAddr, MPU6050_RA_ZRMOT_THR, threshold, wireObj); +} + +// ZRMOT_DUR register + +/** Get zero motion detection event duration threshold. + * This register configures the duration counter threshold for Zero Motion + * interrupt generation. The duration counter ticks at 16 Hz, therefore + * ZRMOT_DUR has a unit of 1 LSB = 64 ms. The Zero Motion duration counter + * increments while the absolute value of the accelerometer measurements are + * each less than the detection threshold (Register 33). The Zero Motion + * interrupt is triggered when the Zero Motion duration counter reaches the time + * count specified in this register. + * + * For more details on the Zero Motion detection interrupt, see Section 8.4 of + * the MPU-6000/MPU-6050 Product Specification document, as well as Registers 56 + * and 58 of this document. + * + * @return Current zero motion detection duration threshold value (LSB = 64ms) + * @see MPU6050_RA_ZRMOT_DUR + */ +uint8_t MPU6050_Base::getZeroMotionDetectionDuration() { + I2Cdev::readByte(devAddr, MPU6050_RA_ZRMOT_DUR, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set zero motion detection event duration threshold. + * @param duration New zero motion detection duration threshold value (LSB = 1ms) + * @see getZeroMotionDetectionDuration() + * @see MPU6050_RA_ZRMOT_DUR + */ +void MPU6050_Base::setZeroMotionDetectionDuration(uint8_t duration) { + I2Cdev::writeByte(devAddr, MPU6050_RA_ZRMOT_DUR, duration, wireObj); +} + +// FIFO_EN register + +/** Get temperature FIFO enabled value. + * When set to 1, this bit enables TEMP_OUT_H and TEMP_OUT_L (Registers 65 and + * 66) to be written into the FIFO buffer. + * @return Current temperature FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_Base::getTempFIFOEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_TEMP_FIFO_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set temperature FIFO enabled value. + * @param enabled New temperature FIFO enabled value + * @see getTempFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_Base::setTempFIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_TEMP_FIFO_EN_BIT, enabled, wireObj); +} +/** Get gyroscope X-axis FIFO enabled value. + * When set to 1, this bit enables GYRO_XOUT_H and GYRO_XOUT_L (Registers 67 and + * 68) to be written into the FIFO buffer. + * @return Current gyroscope X-axis FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_Base::getXGyroFIFOEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_XG_FIFO_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set gyroscope X-axis FIFO enabled value. + * @param enabled New gyroscope X-axis FIFO enabled value + * @see getXGyroFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_Base::setXGyroFIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_XG_FIFO_EN_BIT, enabled, wireObj); +} +/** Get gyroscope Y-axis FIFO enabled value. + * When set to 1, this bit enables GYRO_YOUT_H and GYRO_YOUT_L (Registers 69 and + * 70) to be written into the FIFO buffer. + * @return Current gyroscope Y-axis FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_Base::getYGyroFIFOEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_YG_FIFO_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set gyroscope Y-axis FIFO enabled value. + * @param enabled New gyroscope Y-axis FIFO enabled value + * @see getYGyroFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_Base::setYGyroFIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_YG_FIFO_EN_BIT, enabled, wireObj); +} +/** Get gyroscope Z-axis FIFO enabled value. + * When set to 1, this bit enables GYRO_ZOUT_H and GYRO_ZOUT_L (Registers 71 and + * 72) to be written into the FIFO buffer. + * @return Current gyroscope Z-axis FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_Base::getZGyroFIFOEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ZG_FIFO_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set gyroscope Z-axis FIFO enabled value. + * @param enabled New gyroscope Z-axis FIFO enabled value + * @see getZGyroFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_Base::setZGyroFIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ZG_FIFO_EN_BIT, enabled, wireObj); +} +/** Get accelerometer FIFO enabled value. + * When set to 1, this bit enables ACCEL_XOUT_H, ACCEL_XOUT_L, ACCEL_YOUT_H, + * ACCEL_YOUT_L, ACCEL_ZOUT_H, and ACCEL_ZOUT_L (Registers 59 to 64) to be + * written into the FIFO buffer. + * @return Current accelerometer FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_Base::getAccelFIFOEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ACCEL_FIFO_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set accelerometer FIFO enabled value. + * @param enabled New accelerometer FIFO enabled value + * @see getAccelFIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_Base::setAccelFIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ACCEL_FIFO_EN_BIT, enabled, wireObj); +} +/** Get Slave 2 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 2 to be written into the FIFO buffer. + * @return Current Slave 2 FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_Base::getSlave2FIFOEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV2_FIFO_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set Slave 2 FIFO enabled value. + * @param enabled New Slave 2 FIFO enabled value + * @see getSlave2FIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_Base::setSlave2FIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV2_FIFO_EN_BIT, enabled, wireObj); +} +/** Get Slave 1 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 1 to be written into the FIFO buffer. + * @return Current Slave 1 FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_Base::getSlave1FIFOEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV1_FIFO_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set Slave 1 FIFO enabled value. + * @param enabled New Slave 1 FIFO enabled value + * @see getSlave1FIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_Base::setSlave1FIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV1_FIFO_EN_BIT, enabled, wireObj); +} +/** Get Slave 0 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 0 to be written into the FIFO buffer. + * @return Current Slave 0 FIFO enabled value + * @see MPU6050_RA_FIFO_EN + */ +bool MPU6050_Base::getSlave0FIFOEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV0_FIFO_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set Slave 0 FIFO enabled value. + * @param enabled New Slave 0 FIFO enabled value + * @see getSlave0FIFOEnabled() + * @see MPU6050_RA_FIFO_EN + */ +void MPU6050_Base::setSlave0FIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV0_FIFO_EN_BIT, enabled, wireObj); +} + +// I2C_MST_CTRL register + +/** Get multi-master enabled value. + * Multi-master capability allows multiple I2C masters to operate on the same + * bus. In circuits where multi-master capability is required, set MULT_MST_EN + * to 1. This will increase current drawn by approximately 30uA. + * + * In circuits where multi-master capability is required, the state of the I2C + * bus must always be monitored by each separate I2C Master. Before an I2C + * Master can assume arbitration of the bus, it must first confirm that no other + * I2C Master has arbitration of the bus. When MULT_MST_EN is set to 1, the + * MPU-60X0's bus arbitration detection logic is turned on, enabling it to + * detect when the bus is available. + * + * @return Current multi-master enabled value + * @see MPU6050_RA_I2C_MST_CTRL + */ +bool MPU6050_Base::getMultiMasterEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_MULT_MST_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set multi-master enabled value. + * @param enabled New multi-master enabled value + * @see getMultiMasterEnabled() + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050_Base::setMultiMasterEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_MULT_MST_EN_BIT, enabled, wireObj); +} +/** Get wait-for-external-sensor-data enabled value. + * When the WAIT_FOR_ES bit is set to 1, the Data Ready interrupt will be + * delayed until External Sensor data from the Slave Devices are loaded into the + * EXT_SENS_DATA registers. This is used to ensure that both the internal sensor + * data (i.e. from gyro and accel) and external sensor data have been loaded to + * their respective data registers (i.e. the data is synced) when the Data Ready + * interrupt is triggered. + * + * @return Current wait-for-external-sensor-data enabled value + * @see MPU6050_RA_I2C_MST_CTRL + */ +bool MPU6050_Base::getWaitForExternalSensorEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_WAIT_FOR_ES_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set wait-for-external-sensor-data enabled value. + * @param enabled New wait-for-external-sensor-data enabled value + * @see getWaitForExternalSensorEnabled() + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050_Base::setWaitForExternalSensorEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_WAIT_FOR_ES_BIT, enabled, wireObj); +} +/** Get Slave 3 FIFO enabled value. + * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) + * associated with Slave 3 to be written into the FIFO buffer. + * @return Current Slave 3 FIFO enabled value + * @see MPU6050_RA_MST_CTRL + */ +bool MPU6050_Base::getSlave3FIFOEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_SLV_3_FIFO_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set Slave 3 FIFO enabled value. + * @param enabled New Slave 3 FIFO enabled value + * @see getSlave3FIFOEnabled() + * @see MPU6050_RA_MST_CTRL + */ +void MPU6050_Base::setSlave3FIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_SLV_3_FIFO_EN_BIT, enabled, wireObj); +} +/** Get slave read/write transition enabled value. + * The I2C_MST_P_NSR bit configures the I2C Master's transition from one slave + * read to the next slave read. If the bit equals 0, there will be a restart + * between reads. If the bit equals 1, there will be a stop followed by a start + * of the following read. When a write transaction follows a read transaction, + * the stop followed by a start of the successive write will be always used. + * + * @return Current slave read/write transition enabled value + * @see MPU6050_RA_I2C_MST_CTRL + */ +bool MPU6050_Base::getSlaveReadWriteTransitionEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_P_NSR_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set slave read/write transition enabled value. + * @param enabled New slave read/write transition enabled value + * @see getSlaveReadWriteTransitionEnabled() + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050_Base::setSlaveReadWriteTransitionEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_P_NSR_BIT, enabled, wireObj); +} +/** Get I2C master clock speed. + * I2C_MST_CLK is a 4 bit unsigned value which configures a divider on the + * MPU-60X0 internal 8MHz clock. It sets the I2C master clock speed according to + * the following table: + * + *
+ * I2C_MST_CLK | I2C Master Clock Speed | 8MHz Clock Divider
+ * ------------+------------------------+-------------------
+ * 0           | 348kHz                 | 23
+ * 1           | 333kHz                 | 24
+ * 2           | 320kHz                 | 25
+ * 3           | 308kHz                 | 26
+ * 4           | 296kHz                 | 27
+ * 5           | 286kHz                 | 28
+ * 6           | 276kHz                 | 29
+ * 7           | 267kHz                 | 30
+ * 8           | 258kHz                 | 31
+ * 9           | 500kHz                 | 16
+ * 10          | 471kHz                 | 17
+ * 11          | 444kHz                 | 18
+ * 12          | 421kHz                 | 19
+ * 13          | 400kHz                 | 20
+ * 14          | 381kHz                 | 21
+ * 15          | 364kHz                 | 22
+ * 
+ * + * @return Current I2C master clock speed + * @see MPU6050_RA_I2C_MST_CTRL + */ +uint8_t MPU6050_Base::getMasterClockSpeed() { + I2Cdev::readBits(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_CLK_BIT, MPU6050_I2C_MST_CLK_LENGTH, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set I2C master clock speed. + * @reparam speed Current I2C master clock speed + * @see MPU6050_RA_I2C_MST_CTRL + */ +void MPU6050_Base::setMasterClockSpeed(uint8_t speed) { + I2Cdev::writeBits(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_CLK_BIT, MPU6050_I2C_MST_CLK_LENGTH, speed, wireObj); +} + +// I2C_SLV* registers (Slave 0-3) + +/** Get the I2C address of the specified slave (0-3). + * Note that Bit 7 (MSB) controls read/write mode. If Bit 7 is set, it's a read + * operation, and if it is cleared, then it's a write operation. The remaining + * bits (6-0) are the 7-bit device address of the slave device. + * + * In read mode, the result of the read is placed in the lowest available + * EXT_SENS_DATA register. For further information regarding the allocation of + * read results, please refer to the EXT_SENS_DATA register description + * (Registers 73 - 96). + * + * The MPU-6050 supports a total of five slaves, but Slave 4 has unique + * characteristics, and so it has its own functions (getSlave4* and setSlave4*). + * + * I2C data transactions are performed at the Sample Rate, as defined in + * Register 25. The user is responsible for ensuring that I2C data transactions + * to and from each enabled Slave can be completed within a single period of the + * Sample Rate. + * + * The I2C slave access rate can be reduced relative to the Sample Rate. This + * reduced access rate is determined by I2C_MST_DLY (Register 52). Whether a + * slave's access rate is reduced relative to the Sample Rate is determined by + * I2C_MST_DELAY_CTRL (Register 103). + * + * The processing order for the slaves is fixed. The sequence followed for + * processing the slaves is Slave 0, Slave 1, Slave 2, Slave 3 and Slave 4. If a + * particular Slave is disabled it will be skipped. + * + * Each slave can either be accessed at the sample rate or at a reduced sample + * rate. In a case where some slaves are accessed at the Sample Rate and some + * slaves are accessed at the reduced rate, the sequence of accessing the slaves + * (Slave 0 to Slave 4) is still followed. However, the reduced rate slaves will + * be skipped if their access rate dictates that they should not be accessed + * during that particular cycle. For further information regarding the reduced + * access rate, please refer to Register 52. Whether a slave is accessed at the + * Sample Rate or at the reduced rate is determined by the Delay Enable bits in + * Register 103. + * + * @param num Slave number (0-3) + * @return Current address for specified slave + * @see MPU6050_RA_I2C_SLV0_ADDR + */ +uint8_t MPU6050_Base::getSlaveAddress(uint8_t num) { + if (num > 3) return 0; + I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV0_ADDR + num*3, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set the I2C address of the specified slave (0-3). + * @param num Slave number (0-3) + * @param address New address for specified slave + * @see getSlaveAddress() + * @see MPU6050_RA_I2C_SLV0_ADDR + */ +void MPU6050_Base::setSlaveAddress(uint8_t num, uint8_t address) { + if (num > 3) return; + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV0_ADDR + num*3, address, wireObj); +} +/** Get the active internal register for the specified slave (0-3). + * Read/write operations for this slave will be done to whatever internal + * register address is stored in this MPU register. + * + * The MPU-6050 supports a total of five slaves, but Slave 4 has unique + * characteristics, and so it has its own functions. + * + * @param num Slave number (0-3) + * @return Current active register for specified slave + * @see MPU6050_RA_I2C_SLV0_REG + */ +uint8_t MPU6050_Base::getSlaveRegister(uint8_t num) { + if (num > 3) return 0; + I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV0_REG + num*3, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set the active internal register for the specified slave (0-3). + * @param num Slave number (0-3) + * @param reg New active register for specified slave + * @see getSlaveRegister() + * @see MPU6050_RA_I2C_SLV0_REG + */ +void MPU6050_Base::setSlaveRegister(uint8_t num, uint8_t reg) { + if (num > 3) return; + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV0_REG + num*3, reg, wireObj); +} +/** Get the enabled value for the specified slave (0-3). + * When set to 1, this bit enables Slave 0 for data transfer operations. When + * cleared to 0, this bit disables Slave 0 from data transfer operations. + * @param num Slave number (0-3) + * @return Current enabled value for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +bool MPU6050_Base::getSlaveEnabled(uint8_t num) { + if (num > 3) return 0; + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set the enabled value for the specified slave (0-3). + * @param num Slave number (0-3) + * @param enabled New enabled value for specified slave + * @see getSlaveEnabled() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050_Base::setSlaveEnabled(uint8_t num, bool enabled) { + if (num > 3) return; + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_EN_BIT, enabled, wireObj); +} +/** Get word pair byte-swapping enabled for the specified slave (0-3). + * When set to 1, this bit enables byte swapping. When byte swapping is enabled, + * the high and low bytes of a word pair are swapped. Please refer to + * I2C_SLV0_GRP for the pairing convention of the word pairs. When cleared to 0, + * bytes transferred to and from Slave 0 will be written to EXT_SENS_DATA + * registers in the order they were transferred. + * + * @param num Slave number (0-3) + * @return Current word pair byte-swapping enabled value for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +bool MPU6050_Base::getSlaveWordByteSwap(uint8_t num) { + if (num > 3) return 0; + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_BYTE_SW_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set word pair byte-swapping enabled for the specified slave (0-3). + * @param num Slave number (0-3) + * @param enabled New word pair byte-swapping enabled value for specified slave + * @see getSlaveWordByteSwap() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050_Base::setSlaveWordByteSwap(uint8_t num, bool enabled) { + if (num > 3) return; + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_BYTE_SW_BIT, enabled, wireObj); +} +/** Get write mode for the specified slave (0-3). + * When set to 1, the transaction will read or write data only. When cleared to + * 0, the transaction will write a register address prior to reading or writing + * data. This should equal 0 when specifying the register address within the + * Slave device to/from which the ensuing data transaction will take place. + * + * @param num Slave number (0-3) + * @return Current write mode for specified slave (0 = register address + data, 1 = data only) + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +bool MPU6050_Base::getSlaveWriteMode(uint8_t num) { + if (num > 3) return 0; + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_REG_DIS_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set write mode for the specified slave (0-3). + * @param num Slave number (0-3) + * @param mode New write mode for specified slave (0 = register address + data, 1 = data only) + * @see getSlaveWriteMode() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050_Base::setSlaveWriteMode(uint8_t num, bool mode) { + if (num > 3) return; + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_REG_DIS_BIT, mode, wireObj); +} +/** Get word pair grouping order offset for the specified slave (0-3). + * This sets specifies the grouping order of word pairs received from registers. + * When cleared to 0, bytes from register addresses 0 and 1, 2 and 3, etc (even, + * then odd register addresses) are paired to form a word. When set to 1, bytes + * from register addresses are paired 1 and 2, 3 and 4, etc. (odd, then even + * register addresses) are paired to form a word. + * + * @param num Slave number (0-3) + * @return Current word pair grouping order offset for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +bool MPU6050_Base::getSlaveWordGroupOffset(uint8_t num) { + if (num > 3) return 0; + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_GRP_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set word pair grouping order offset for the specified slave (0-3). + * @param num Slave number (0-3) + * @param enabled New word pair grouping order offset for specified slave + * @see getSlaveWordGroupOffset() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050_Base::setSlaveWordGroupOffset(uint8_t num, bool enabled) { + if (num > 3) return; + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_GRP_BIT, enabled, wireObj); +} +/** Get number of bytes to read for the specified slave (0-3). + * Specifies the number of bytes transferred to and from Slave 0. Clearing this + * bit to 0 is equivalent to disabling the register by writing 0 to I2C_SLV0_EN. + * @param num Slave number (0-3) + * @return Number of bytes to read for specified slave + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +uint8_t MPU6050_Base::getSlaveDataLength(uint8_t num) { + if (num > 3) return 0; + I2Cdev::readBits(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_LEN_BIT, MPU6050_I2C_SLV_LEN_LENGTH, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set number of bytes to read for the specified slave (0-3). + * @param num Slave number (0-3) + * @param length Number of bytes to read for specified slave + * @see getSlaveDataLength() + * @see MPU6050_RA_I2C_SLV0_CTRL + */ +void MPU6050_Base::setSlaveDataLength(uint8_t num, uint8_t length) { + if (num > 3) return; + I2Cdev::writeBits(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_LEN_BIT, MPU6050_I2C_SLV_LEN_LENGTH, length, wireObj); +} + +// I2C_SLV* registers (Slave 4) + +/** Get the I2C address of Slave 4. + * Note that Bit 7 (MSB) controls read/write mode. If Bit 7 is set, it's a read + * operation, and if it is cleared, then it's a write operation. The remaining + * bits (6-0) are the 7-bit device address of the slave device. + * + * @return Current address for Slave 4 + * @see getSlaveAddress() + * @see MPU6050_RA_I2C_SLV4_ADDR + */ +uint8_t MPU6050_Base::getSlave4Address() { + I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV4_ADDR, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set the I2C address of Slave 4. + * @param address New address for Slave 4 + * @see getSlave4Address() + * @see MPU6050_RA_I2C_SLV4_ADDR + */ +void MPU6050_Base::setSlave4Address(uint8_t address) { + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV4_ADDR, address, wireObj); +} +/** Get the active internal register for the Slave 4. + * Read/write operations for this slave will be done to whatever internal + * register address is stored in this MPU register. + * + * @return Current active register for Slave 4 + * @see MPU6050_RA_I2C_SLV4_REG + */ +uint8_t MPU6050_Base::getSlave4Register() { + I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV4_REG, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set the active internal register for Slave 4. + * @param reg New active register for Slave 4 + * @see getSlave4Register() + * @see MPU6050_RA_I2C_SLV4_REG + */ +void MPU6050_Base::setSlave4Register(uint8_t reg) { + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV4_REG, reg, wireObj); +} +/** Set new byte to write to Slave 4. + * This register stores the data to be written into the Slave 4. If I2C_SLV4_RW + * is set 1 (set to read), this register has no effect. + * @param data New byte to write to Slave 4 + * @see MPU6050_RA_I2C_SLV4_DO + */ +void MPU6050_Base::setSlave4OutputByte(uint8_t data) { + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV4_DO, data, wireObj); +} +/** Get the enabled value for the Slave 4. + * When set to 1, this bit enables Slave 4 for data transfer operations. When + * cleared to 0, this bit disables Slave 4 from data transfer operations. + * @return Current enabled value for Slave 4 + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +bool MPU6050_Base::getSlave4Enabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set the enabled value for Slave 4. + * @param enabled New enabled value for Slave 4 + * @see getSlave4Enabled() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050_Base::setSlave4Enabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_EN_BIT, enabled, wireObj); +} +/** Get the enabled value for Slave 4 transaction interrupts. + * When set to 1, this bit enables the generation of an interrupt signal upon + * completion of a Slave 4 transaction. When cleared to 0, this bit disables the + * generation of an interrupt signal upon completion of a Slave 4 transaction. + * The interrupt status can be observed in Register 54. + * + * @return Current enabled value for Slave 4 transaction interrupts. + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +bool MPU6050_Base::getSlave4InterruptEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_INT_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set the enabled value for Slave 4 transaction interrupts. + * @param enabled New enabled value for Slave 4 transaction interrupts. + * @see getSlave4InterruptEnabled() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050_Base::setSlave4InterruptEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_INT_EN_BIT, enabled, wireObj); +} +/** Get write mode for Slave 4. + * When set to 1, the transaction will read or write data only. When cleared to + * 0, the transaction will write a register address prior to reading or writing + * data. This should equal 0 when specifying the register address within the + * Slave device to/from which the ensuing data transaction will take place. + * + * @return Current write mode for Slave 4 (0 = register address + data, 1 = data only) + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +bool MPU6050_Base::getSlave4WriteMode() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_REG_DIS_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set write mode for the Slave 4. + * @param mode New write mode for Slave 4 (0 = register address + data, 1 = data only) + * @see getSlave4WriteMode() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050_Base::setSlave4WriteMode(bool mode) { + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_REG_DIS_BIT, mode, wireObj); +} +/** Get Slave 4 master delay value. + * This configures the reduced access rate of I2C slaves relative to the Sample + * Rate. When a slave's access rate is decreased relative to the Sample Rate, + * the slave is accessed every: + * + * 1 / (1 + I2C_MST_DLY) samples + * + * This base Sample Rate in turn is determined by SMPLRT_DIV (register 25) and + * DLPF_CFG (register 26). Whether a slave's access rate is reduced relative to + * the Sample Rate is determined by I2C_MST_DELAY_CTRL (register 103). For + * further information regarding the Sample Rate, please refer to register 25. + * + * @return Current Slave 4 master delay value + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +uint8_t MPU6050_Base::getSlave4MasterDelay() { + I2Cdev::readBits(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_MST_DLY_BIT, MPU6050_I2C_SLV4_MST_DLY_LENGTH, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set Slave 4 master delay value. + * @param delay New Slave 4 master delay value + * @see getSlave4MasterDelay() + * @see MPU6050_RA_I2C_SLV4_CTRL + */ +void MPU6050_Base::setSlave4MasterDelay(uint8_t delay) { + I2Cdev::writeBits(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_MST_DLY_BIT, MPU6050_I2C_SLV4_MST_DLY_LENGTH, delay, wireObj); +} +/** Get last available byte read from Slave 4. + * This register stores the data read from Slave 4. This field is populated + * after a read transaction. + * @return Last available byte read from to Slave 4 + * @see MPU6050_RA_I2C_SLV4_DI + */ +uint8_t MPU6050_Base::getSlate4InputByte() { + I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV4_DI, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} + +// I2C_MST_STATUS register + +/** Get FSYNC interrupt status. + * This bit reflects the status of the FSYNC interrupt from an external device + * into the MPU-60X0. This is used as a way to pass an external interrupt + * through the MPU-60X0 to the host application processor. When set to 1, this + * bit will cause an interrupt if FSYNC_INT_EN is asserted in INT_PIN_CFG + * (Register 55). + * @return FSYNC interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_Base::getPassthroughStatus() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_PASS_THROUGH_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Get Slave 4 transaction done status. + * Automatically sets to 1 when a Slave 4 transaction has completed. This + * triggers an interrupt if the I2C_MST_INT_EN bit in the INT_ENABLE register + * (Register 56) is asserted and if the SLV_4_DONE_INT bit is asserted in the + * I2C_SLV4_CTRL register (Register 52). + * @return Slave 4 transaction done status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_Base::getSlave4IsDone() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV4_DONE_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Get master arbitration lost status. + * This bit automatically sets to 1 when the I2C Master has lost arbitration of + * the auxiliary I2C bus (an error condition). This triggers an interrupt if the + * I2C_MST_INT_EN bit in the INT_ENABLE register (Register 56) is asserted. + * @return Master arbitration lost status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_Base::getLostArbitration() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_LOST_ARB_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Get Slave 4 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 4. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 4 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_Base::getSlave4Nack() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV4_NACK_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Get Slave 3 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 3. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 3 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_Base::getSlave3Nack() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV3_NACK_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Get Slave 2 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 2. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 2 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_Base::getSlave2Nack() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV2_NACK_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Get Slave 1 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 1. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 1 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_Base::getSlave1Nack() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV1_NACK_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Get Slave 0 NACK status. + * This bit automatically sets to 1 when the I2C Master receives a NACK in a + * transaction with Slave 0. This triggers an interrupt if the I2C_MST_INT_EN + * bit in the INT_ENABLE register (Register 56) is asserted. + * @return Slave 0 NACK interrupt status + * @see MPU6050_RA_I2C_MST_STATUS + */ +bool MPU6050_Base::getSlave0Nack() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV0_NACK_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} + +// INT_PIN_CFG register + +/** Get interrupt logic level mode. + * Will be set 0 for active-high, 1 for active-low. + * @return Current interrupt mode (0=active-high, 1=active-low) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_LEVEL_BIT + */ +bool MPU6050_Base::getInterruptMode() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_LEVEL_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set interrupt logic level mode. + * @param mode New interrupt mode (0=active-high, 1=active-low) + * @see getInterruptMode() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_LEVEL_BIT + */ +void MPU6050_Base::setInterruptMode(bool mode) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_LEVEL_BIT, mode, wireObj); +} +/** Get interrupt drive mode. + * Will be set 0 for push-pull, 1 for open-drain. + * @return Current interrupt drive mode (0=push-pull, 1=open-drain) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_OPEN_BIT + */ +bool MPU6050_Base::getInterruptDrive() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_OPEN_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set interrupt drive mode. + * @param drive New interrupt drive mode (0=push-pull, 1=open-drain) + * @see getInterruptDrive() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_OPEN_BIT + */ +void MPU6050_Base::setInterruptDrive(bool drive) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_OPEN_BIT, drive, wireObj); +} +/** Get interrupt latch mode. + * Will be set 0 for 50us-pulse, 1 for latch-until-int-cleared. + * @return Current latch mode (0=50us-pulse, 1=latch-until-int-cleared) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_LATCH_INT_EN_BIT + */ +bool MPU6050_Base::getInterruptLatch() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_LATCH_INT_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set interrupt latch mode. + * @param latch New latch mode (0=50us-pulse, 1=latch-until-int-cleared) + * @see getInterruptLatch() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_LATCH_INT_EN_BIT + */ +void MPU6050_Base::setInterruptLatch(bool latch) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_LATCH_INT_EN_BIT, latch, wireObj); +} +/** Get interrupt latch clear mode. + * Will be set 0 for status-read-only, 1 for any-register-read. + * @return Current latch clear mode (0=status-read-only, 1=any-register-read) + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_RD_CLEAR_BIT + */ +bool MPU6050_Base::getInterruptLatchClear() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_RD_CLEAR_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set interrupt latch clear mode. + * @param clear New latch clear mode (0=status-read-only, 1=any-register-read) + * @see getInterruptLatchClear() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_INT_RD_CLEAR_BIT + */ +void MPU6050_Base::setInterruptLatchClear(bool clear) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_RD_CLEAR_BIT, clear, wireObj); +} +/** Get FSYNC interrupt logic level mode. + * @return Current FSYNC interrupt mode (0=active-high, 1=active-low) + * @see getFSyncInterruptMode() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT + */ +bool MPU6050_Base::getFSyncInterruptLevel() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set FSYNC interrupt logic level mode. + * @param mode New FSYNC interrupt mode (0=active-high, 1=active-low) + * @see getFSyncInterruptMode() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT + */ +void MPU6050_Base::setFSyncInterruptLevel(bool level) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT, level, wireObj); +} +/** Get FSYNC pin interrupt enabled setting. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled setting + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_EN_BIT + */ +bool MPU6050_Base::getFSyncInterruptEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set FSYNC pin interrupt enabled setting. + * @param enabled New FSYNC pin interrupt enabled setting + * @see getFSyncInterruptEnabled() + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_FSYNC_INT_EN_BIT + */ +void MPU6050_Base::setFSyncInterruptEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_EN_BIT, enabled, wireObj); +} +/** Get I2C bypass enabled status. + * When this bit is equal to 1 and I2C_MST_EN (Register 106 bit[5]) is equal to + * 0, the host application processor will be able to directly access the + * auxiliary I2C bus of the MPU-60X0. When this bit is equal to 0, the host + * application processor will not be able to directly access the auxiliary I2C + * bus of the MPU-60X0 regardless of the state of I2C_MST_EN (Register 106 + * bit[5]). + * @return Current I2C bypass enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_I2C_BYPASS_EN_BIT + */ +bool MPU6050_Base::getI2CBypassEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_I2C_BYPASS_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set I2C bypass enabled status. + * When this bit is equal to 1 and I2C_MST_EN (Register 106 bit[5]) is equal to + * 0, the host application processor will be able to directly access the + * auxiliary I2C bus of the MPU-60X0. When this bit is equal to 0, the host + * application processor will not be able to directly access the auxiliary I2C + * bus of the MPU-60X0 regardless of the state of I2C_MST_EN (Register 106 + * bit[5]). + * @param enabled New I2C bypass enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_I2C_BYPASS_EN_BIT + */ +void MPU6050_Base::setI2CBypassEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_I2C_BYPASS_EN_BIT, enabled, wireObj); +} +/** Get reference clock output enabled status. + * When this bit is equal to 1, a reference clock output is provided at the + * CLKOUT pin. When this bit is equal to 0, the clock output is disabled. For + * further information regarding CLKOUT, please refer to the MPU-60X0 Product + * Specification document. + * @return Current reference clock output enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_CLKOUT_EN_BIT + */ +bool MPU6050_Base::getClockOutputEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_CLKOUT_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set reference clock output enabled status. + * When this bit is equal to 1, a reference clock output is provided at the + * CLKOUT pin. When this bit is equal to 0, the clock output is disabled. For + * further information regarding CLKOUT, please refer to the MPU-60X0 Product + * Specification document. + * @param enabled New reference clock output enabled status + * @see MPU6050_RA_INT_PIN_CFG + * @see MPU6050_INTCFG_CLKOUT_EN_BIT + */ +void MPU6050_Base::setClockOutputEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_CLKOUT_EN_BIT, enabled, wireObj); +} + +// INT_ENABLE register + +/** Get full interrupt enabled status. + * Full register byte for all interrupts, for quick reading. Each bit will be + * set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +uint8_t MPU6050_Base::getIntEnabled() { + I2Cdev::readByte(devAddr, MPU6050_RA_INT_ENABLE, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set full interrupt enabled status. + * Full register byte for all interrupts, for quick reading. Each bit should be + * set 0 for disabled, 1 for enabled. + * @param enabled New interrupt enabled status + * @see getIntFreefallEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +void MPU6050_Base::setIntEnabled(uint8_t enabled) { + I2Cdev::writeByte(devAddr, MPU6050_RA_INT_ENABLE, enabled, wireObj); +} +/** Get Free Fall interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +bool MPU6050_Base::getIntFreefallEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FF_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set Free Fall interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntFreefallEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FF_BIT + **/ +void MPU6050_Base::setIntFreefallEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FF_BIT, enabled, wireObj); +} +/** Get Motion Detection interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_MOT_BIT + **/ +bool MPU6050_Base::getIntMotionEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_MOT_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set Motion Detection interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntMotionEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_MOT_BIT + **/ +void MPU6050_Base::setIntMotionEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_MOT_BIT, enabled, wireObj); +} +/** Get Zero Motion Detection interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_ZMOT_BIT + **/ +bool MPU6050_Base::getIntZeroMotionEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_ZMOT_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set Zero Motion Detection interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntZeroMotionEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_ZMOT_BIT + **/ +void MPU6050_Base::setIntZeroMotionEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_ZMOT_BIT, enabled, wireObj); +} +/** Get FIFO Buffer Overflow interrupt enabled status. + * Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT + **/ +bool MPU6050_Base::getIntFIFOBufferOverflowEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set FIFO Buffer Overflow interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntFIFOBufferOverflowEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT + **/ +void MPU6050_Base::setIntFIFOBufferOverflowEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, enabled, wireObj); +} +/** Get I2C Master interrupt enabled status. + * This enables any of the I2C Master interrupt sources to generate an + * interrupt. Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT + **/ +bool MPU6050_Base::getIntI2CMasterEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_I2C_MST_INT_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set I2C Master interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntI2CMasterEnabled() + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT + **/ +void MPU6050_Base::setIntI2CMasterEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_I2C_MST_INT_BIT, enabled, wireObj); +} +/** Get Data Ready interrupt enabled setting. + * This event occurs each time a write operation to all of the sensor registers + * has been completed. Will be set 0 for disabled, 1 for enabled. + * @return Current interrupt enabled status + * @see MPU6050_RA_INT_ENABLE + * @see MPU6050_INTERRUPT_DATA_RDY_BIT + */ +bool MPU6050_Base::getIntDataReadyEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DATA_RDY_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set Data Ready interrupt enabled status. + * @param enabled New interrupt enabled status + * @see getIntDataReadyEnabled() + * @see MPU6050_RA_INT_CFG + * @see MPU6050_INTERRUPT_DATA_RDY_BIT + */ +void MPU6050_Base::setIntDataReadyEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DATA_RDY_BIT, enabled, wireObj); +} + +// INT_STATUS register + +/** Get full set of interrupt status bits. + * These bits clear to 0 after the register has been read. Very useful + * for getting multiple INT statuses, since each single bit read clears + * all of them because it has to read the whole byte. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + */ +uint8_t MPU6050_Base::getIntStatus() { + I2Cdev::readByte(devAddr, MPU6050_RA_INT_STATUS, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Get Free Fall interrupt status. + * This bit automatically sets to 1 when a Free Fall interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_FF_BIT + */ +bool MPU6050_Base::getIntFreefallStatus() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_FF_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Get Motion Detection interrupt status. + * This bit automatically sets to 1 when a Motion Detection interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_MOT_BIT + */ +bool MPU6050_Base::getIntMotionStatus() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_MOT_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Get Zero Motion Detection interrupt status. + * This bit automatically sets to 1 when a Zero Motion Detection interrupt has + * been generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_ZMOT_BIT + */ +bool MPU6050_Base::getIntZeroMotionStatus() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_ZMOT_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Get FIFO Buffer Overflow interrupt status. + * This bit automatically sets to 1 when a Free Fall interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT + */ +bool MPU6050_Base::getIntFIFOBufferOverflowStatus() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Get I2C Master interrupt status. + * This bit automatically sets to 1 when an I2C Master interrupt has been + * generated. For a list of I2C Master interrupts, please refer to Register 54. + * The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT + */ +bool MPU6050_Base::getIntI2CMasterStatus() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_I2C_MST_INT_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Get Data Ready interrupt status. + * This bit automatically sets to 1 when a Data Ready interrupt has been + * generated. The bit clears to 0 after the register has been read. + * @return Current interrupt status + * @see MPU6050_RA_INT_STATUS + * @see MPU6050_INTERRUPT_DATA_RDY_BIT + */ +bool MPU6050_Base::getIntDataReadyStatus() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_DATA_RDY_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} + +// ACCEL_*OUT_* registers + +/** Get raw 9-axis motion sensor readings (accel/gyro/compass). + * FUNCTION NOT FULLY IMPLEMENTED YET. + * @param ax 16-bit signed integer container for accelerometer X-axis value + * @param ay 16-bit signed integer container for accelerometer Y-axis value + * @param az 16-bit signed integer container for accelerometer Z-axis value + * @param gx 16-bit signed integer container for gyroscope X-axis value + * @param gy 16-bit signed integer container for gyroscope Y-axis value + * @param gz 16-bit signed integer container for gyroscope Z-axis value + * @param mx 16-bit signed integer container for magnetometer X-axis value + * @param my 16-bit signed integer container for magnetometer Y-axis value + * @param mz 16-bit signed integer container for magnetometer Z-axis value + * @see getMotion6() + * @see getAcceleration() + * @see getRotation() + * @see MPU6050_RA_ACCEL_XOUT_H + */ +void MPU6050_Base::getMotion9(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz, int16_t* mx, int16_t* my, int16_t* mz) { + (void)mx; // unused parameter + (void)my; // unused parameter + (void)mz; // unused parameter + + getMotion6(ax, ay, az, gx, gy, gz); + // TODO: magnetometer integration +} +/** Get raw 6-axis motion sensor readings (accel/gyro). + * Retrieves all currently available motion sensor values. + * @param ax 16-bit signed integer container for accelerometer X-axis value + * @param ay 16-bit signed integer container for accelerometer Y-axis value + * @param az 16-bit signed integer container for accelerometer Z-axis value + * @param gx 16-bit signed integer container for gyroscope X-axis value + * @param gy 16-bit signed integer container for gyroscope Y-axis value + * @param gz 16-bit signed integer container for gyroscope Z-axis value + * @see getAcceleration() + * @see getRotation() + * @see MPU6050_RA_ACCEL_XOUT_H + */ +void MPU6050_Base::getMotion6(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz) { + I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_XOUT_H, 14, buffer, I2Cdev::readTimeout, wireObj); + *ax = (((int16_t)buffer[0]) << 8) | buffer[1]; + *ay = (((int16_t)buffer[2]) << 8) | buffer[3]; + *az = (((int16_t)buffer[4]) << 8) | buffer[5]; + *gx = (((int16_t)buffer[8]) << 8) | buffer[9]; + *gy = (((int16_t)buffer[10]) << 8) | buffer[11]; + *gz = (((int16_t)buffer[12]) << 8) | buffer[13]; +} +/** Get 3-axis accelerometer readings. + * These registers store the most recent accelerometer measurements. + * Accelerometer measurements are written to these registers at the Sample Rate + * as defined in Register 25. + * + * The accelerometer measurement registers, along with the temperature + * measurement registers, gyroscope measurement registers, and external sensor + * data registers, are composed of two sets of registers: an internal register + * set and a user-facing read register set. + * + * The data within the accelerometer sensors' internal register set is always + * updated at the Sample Rate. Meanwhile, the user-facing read register set + * duplicates the internal register set's data values whenever the serial + * interface is idle. This guarantees that a burst read of sensor registers will + * read measurements from the same sampling instant. Note that if burst reads + * are not used, the user is responsible for ensuring a set of single byte reads + * correspond to a single sampling instant by checking the Data Ready interrupt. + * + * Each 16-bit accelerometer measurement has a full scale defined in ACCEL_FS + * (Register 28). For each full scale setting, the accelerometers' sensitivity + * per LSB in ACCEL_xOUT is shown in the table below: + * + *
+ * AFS_SEL | Full Scale Range | LSB Sensitivity
+ * --------+------------------+----------------
+ * 0       | +/- 2g           | 16384 LSB/mg
+ * 1       | +/- 4g           | 8192 LSB/mg
+ * 2       | +/- 8g           | 4096 LSB/mg
+ * 3       | +/- 16g          | 2048 LSB/mg
+ * 
+ * + * @param x 16-bit signed integer container for X-axis acceleration + * @param y 16-bit signed integer container for Y-axis acceleration + * @param z 16-bit signed integer container for Z-axis acceleration + * @see MPU6050_RA_GYRO_XOUT_H + */ +void MPU6050_Base::getAcceleration(int16_t* x, int16_t* y, int16_t* z) { + I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_XOUT_H, 6, buffer, I2Cdev::readTimeout, wireObj); + *x = (((int16_t)buffer[0]) << 8) | buffer[1]; + *y = (((int16_t)buffer[2]) << 8) | buffer[3]; + *z = (((int16_t)buffer[4]) << 8) | buffer[5]; +} +/** Get X-axis accelerometer reading. + * @return X-axis acceleration measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_ACCEL_XOUT_H + */ +int16_t MPU6050_Base::getAccelerationX() { + I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_XOUT_H, 2, buffer, I2Cdev::readTimeout, wireObj); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +/** Get Y-axis accelerometer reading. + * @return Y-axis acceleration measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_ACCEL_YOUT_H + */ +int16_t MPU6050_Base::getAccelerationY() { + I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_YOUT_H, 2, buffer, I2Cdev::readTimeout, wireObj); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +/** Get Z-axis accelerometer reading. + * @return Z-axis acceleration measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_ACCEL_ZOUT_H + */ +int16_t MPU6050_Base::getAccelerationZ() { + I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_ZOUT_H, 2, buffer, I2Cdev::readTimeout, wireObj); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} + +// TEMP_OUT_* registers + +/** Get current internal temperature. + * @return Temperature reading in 16-bit 2's complement format + * @see MPU6050_RA_TEMP_OUT_H + */ +int16_t MPU6050_Base::getTemperature() { + I2Cdev::readBytes(devAddr, MPU6050_RA_TEMP_OUT_H, 2, buffer, I2Cdev::readTimeout, wireObj); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} + +// GYRO_*OUT_* registers + +/** Get 3-axis gyroscope readings. + * These gyroscope measurement registers, along with the accelerometer + * measurement registers, temperature measurement registers, and external sensor + * data registers, are composed of two sets of registers: an internal register + * set and a user-facing read register set. + * The data within the gyroscope sensors' internal register set is always + * updated at the Sample Rate. Meanwhile, the user-facing read register set + * duplicates the internal register set's data values whenever the serial + * interface is idle. This guarantees that a burst read of sensor registers will + * read measurements from the same sampling instant. Note that if burst reads + * are not used, the user is responsible for ensuring a set of single byte reads + * correspond to a single sampling instant by checking the Data Ready interrupt. + * + * Each 16-bit gyroscope measurement has a full scale defined in FS_SEL + * (Register 27). For each full scale setting, the gyroscopes' sensitivity per + * LSB in GYRO_xOUT is shown in the table below: + * + *
+ * FS_SEL | Full Scale Range   | LSB Sensitivity
+ * -------+--------------------+----------------
+ * 0      | +/- 250 degrees/s  | 131 LSB/deg/s
+ * 1      | +/- 500 degrees/s  | 65.5 LSB/deg/s
+ * 2      | +/- 1000 degrees/s | 32.8 LSB/deg/s
+ * 3      | +/- 2000 degrees/s | 16.4 LSB/deg/s
+ * 
+ * + * @param x 16-bit signed integer container for X-axis rotation + * @param y 16-bit signed integer container for Y-axis rotation + * @param z 16-bit signed integer container for Z-axis rotation + * @see getMotion6() + * @see MPU6050_RA_GYRO_XOUT_H + */ +void MPU6050_Base::getRotation(int16_t* x, int16_t* y, int16_t* z) { + I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_XOUT_H, 6, buffer, I2Cdev::readTimeout, wireObj); + *x = (((int16_t)buffer[0]) << 8) | buffer[1]; + *y = (((int16_t)buffer[2]) << 8) | buffer[3]; + *z = (((int16_t)buffer[4]) << 8) | buffer[5]; +} +/** Get X-axis gyroscope reading. + * @return X-axis rotation measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_GYRO_XOUT_H + */ +int16_t MPU6050_Base::getRotationX() { + I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_XOUT_H, 2, buffer, I2Cdev::readTimeout, wireObj); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +/** Get Y-axis gyroscope reading. + * @return Y-axis rotation measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_GYRO_YOUT_H + */ +int16_t MPU6050_Base::getRotationY() { + I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_YOUT_H, 2, buffer, I2Cdev::readTimeout, wireObj); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +/** Get Z-axis gyroscope reading. + * @return Z-axis rotation measurement in 16-bit 2's complement format + * @see getMotion6() + * @see MPU6050_RA_GYRO_ZOUT_H + */ +int16_t MPU6050_Base::getRotationZ() { + I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_ZOUT_H, 2, buffer, I2Cdev::readTimeout, wireObj); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} + +// EXT_SENS_DATA_* registers + +/** Read single byte from external sensor data register. + * These registers store data read from external sensors by the Slave 0, 1, 2, + * and 3 on the auxiliary I2C interface. Data read by Slave 4 is stored in + * I2C_SLV4_DI (Register 53). + * + * External sensor data is written to these registers at the Sample Rate as + * defined in Register 25. This access rate can be reduced by using the Slave + * Delay Enable registers (Register 103). + * + * External sensor data registers, along with the gyroscope measurement + * registers, accelerometer measurement registers, and temperature measurement + * registers, are composed of two sets of registers: an internal register set + * and a user-facing read register set. + * + * The data within the external sensors' internal register set is always updated + * at the Sample Rate (or the reduced access rate) whenever the serial interface + * is idle. This guarantees that a burst read of sensor registers will read + * measurements from the same sampling instant. Note that if burst reads are not + * used, the user is responsible for ensuring a set of single byte reads + * correspond to a single sampling instant by checking the Data Ready interrupt. + * + * Data is placed in these external sensor data registers according to + * I2C_SLV0_CTRL, I2C_SLV1_CTRL, I2C_SLV2_CTRL, and I2C_SLV3_CTRL (Registers 39, + * 42, 45, and 48). When more than zero bytes are read (I2C_SLVx_LEN > 0) from + * an enabled slave (I2C_SLVx_EN = 1), the slave is read at the Sample Rate (as + * defined in Register 25) or delayed rate (if specified in Register 52 and + * 103). During each Sample cycle, slave reads are performed in order of Slave + * number. If all slaves are enabled with more than zero bytes to be read, the + * order will be Slave 0, followed by Slave 1, Slave 2, and Slave 3. + * + * Each enabled slave will have EXT_SENS_DATA registers associated with it by + * number of bytes read (I2C_SLVx_LEN) in order of slave number, starting from + * EXT_SENS_DATA_00. Note that this means enabling or disabling a slave may + * change the higher numbered slaves' associated registers. Furthermore, if + * fewer total bytes are being read from the external sensors as a result of + * such a change, then the data remaining in the registers which no longer have + * an associated slave device (i.e. high numbered registers) will remain in + * these previously allocated registers unless reset. + * + * If the sum of the read lengths of all SLVx transactions exceed the number of + * available EXT_SENS_DATA registers, the excess bytes will be dropped. There + * are 24 EXT_SENS_DATA registers and hence the total read lengths between all + * the slaves cannot be greater than 24 or some bytes will be lost. + * + * Note: Slave 4's behavior is distinct from that of Slaves 0-3. For further + * information regarding the characteristics of Slave 4, please refer to + * Registers 49 to 53. + * + * EXAMPLE: + * Suppose that Slave 0 is enabled with 4 bytes to be read (I2C_SLV0_EN = 1 and + * I2C_SLV0_LEN = 4) while Slave 1 is enabled with 2 bytes to be read so that + * I2C_SLV1_EN = 1 and I2C_SLV1_LEN = 2. In such a situation, EXT_SENS_DATA _00 + * through _03 will be associated with Slave 0, while EXT_SENS_DATA _04 and 05 + * will be associated with Slave 1. If Slave 2 is enabled as well, registers + * starting from EXT_SENS_DATA_06 will be allocated to Slave 2. + * + * If Slave 2 is disabled while Slave 3 is enabled in this same situation, then + * registers starting from EXT_SENS_DATA_06 will be allocated to Slave 3 + * instead. + * + * REGISTER ALLOCATION FOR DYNAMIC DISABLE VS. NORMAL DISABLE: + * If a slave is disabled at any time, the space initially allocated to the + * slave in the EXT_SENS_DATA register, will remain associated with that slave. + * This is to avoid dynamic adjustment of the register allocation. + * + * The allocation of the EXT_SENS_DATA registers is recomputed only when (1) all + * slaves are disabled, or (2) the I2C_MST_RST bit is set (Register 106). + * + * This above is also true if one of the slaves gets NACKed and stops + * functioning. + * + * @param position Starting position (0-23) + * @return Byte read from register + */ +uint8_t MPU6050_Base::getExternalSensorByte(int position) { + I2Cdev::readByte(devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Read word (2 bytes) from external sensor data registers. + * @param position Starting position (0-21) + * @return Word read from register + * @see getExternalSensorByte() + */ +uint16_t MPU6050_Base::getExternalSensorWord(int position) { + I2Cdev::readBytes(devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, 2, buffer, I2Cdev::readTimeout, wireObj); + return (((uint16_t)buffer[0]) << 8) | buffer[1]; +} +/** Read double word (4 bytes) from external sensor data registers. + * @param position Starting position (0-20) + * @return Double word read from registers + * @see getExternalSensorByte() + */ +uint32_t MPU6050_Base::getExternalSensorDWord(int position) { + I2Cdev::readBytes(devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, 4, buffer, I2Cdev::readTimeout, wireObj); + return (((uint32_t)buffer[0]) << 24) | (((uint32_t)buffer[1]) << 16) | (((uint16_t)buffer[2]) << 8) | buffer[3]; +} + +// MOT_DETECT_STATUS register + +/** Get full motion detection status register content (all bits). + * @return Motion detection status byte + * @see MPU6050_RA_MOT_DETECT_STATUS + */ +uint8_t MPU6050_Base::getMotionStatus() { + I2Cdev::readByte(devAddr, MPU6050_RA_MOT_DETECT_STATUS, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Get X-axis negative motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_XNEG_BIT + */ +bool MPU6050_Base::getXNegMotionDetected() { + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_XNEG_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Get X-axis positive motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_XPOS_BIT + */ +bool MPU6050_Base::getXPosMotionDetected() { + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_XPOS_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Get Y-axis negative motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_YNEG_BIT + */ +bool MPU6050_Base::getYNegMotionDetected() { + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_YNEG_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Get Y-axis positive motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_YPOS_BIT + */ +bool MPU6050_Base::getYPosMotionDetected() { + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_YPOS_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Get Z-axis negative motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_ZNEG_BIT + */ +bool MPU6050_Base::getZNegMotionDetected() { + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZNEG_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Get Z-axis positive motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_ZPOS_BIT + */ +bool MPU6050_Base::getZPosMotionDetected() { + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZPOS_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Get zero motion detection interrupt status. + * @return Motion detection status + * @see MPU6050_RA_MOT_DETECT_STATUS + * @see MPU6050_MOTION_MOT_ZRMOT_BIT + */ +bool MPU6050_Base::getZeroMotionDetected() { + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZRMOT_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} + +// I2C_SLV*_DO register + +/** Write byte to Data Output container for specified slave. + * This register holds the output data written into Slave when Slave is set to + * write mode. For further information regarding Slave control, please + * refer to Registers 37 to 39 and immediately following. + * @param num Slave number (0-3) + * @param data Byte to write + * @see MPU6050_RA_I2C_SLV0_DO + */ +void MPU6050_Base::setSlaveOutputByte(uint8_t num, uint8_t data) { + if (num > 3) return; + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV0_DO + num, data, wireObj); +} + +// I2C_MST_DELAY_CTRL register + +/** Get external data shadow delay enabled status. + * This register is used to specify the timing of external sensor data + * shadowing. When DELAY_ES_SHADOW is set to 1, shadowing of external + * sensor data is delayed until all data has been received. + * @return Current external data shadow delay enabled status. + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT + */ +bool MPU6050_Base::getExternalShadowDelayEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set external data shadow delay enabled status. + * @param enabled New external data shadow delay enabled status. + * @see getExternalShadowDelayEnabled() + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT + */ +void MPU6050_Base::setExternalShadowDelayEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT, enabled, wireObj); +} +/** Get slave delay enabled status. + * When a particular slave delay is enabled, the rate of access for the that + * slave device is reduced. When a slave's access rate is decreased relative to + * the Sample Rate, the slave is accessed every: + * + * 1 / (1 + I2C_MST_DLY) Samples + * + * This base Sample Rate in turn is determined by SMPLRT_DIV (register * 25) + * and DLPF_CFG (register 26). + * + * For further information regarding I2C_MST_DLY, please refer to register 52. + * For further information regarding the Sample Rate, please refer to register 25. + * + * @param num Slave number (0-4) + * @return Current slave delay enabled status. + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT + */ +bool MPU6050_Base::getSlaveDelayEnabled(uint8_t num) { + // MPU6050_DELAYCTRL_I2C_SLV4_DLY_EN_BIT is 4, SLV3 is 3, etc. + if (num > 4) return 0; + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, num, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set slave delay enabled status. + * @param num Slave number (0-4) + * @param enabled New slave delay enabled status. + * @see MPU6050_RA_I2C_MST_DELAY_CTRL + * @see MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT + */ +void MPU6050_Base::setSlaveDelayEnabled(uint8_t num, bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, num, enabled, wireObj); +} + +// SIGNAL_PATH_RESET register + +/** Reset gyroscope signal path. + * The reset will revert the signal path analog to digital converters and + * filters to their power up configurations. + * @see MPU6050_RA_SIGNAL_PATH_RESET + * @see MPU6050_PATHRESET_GYRO_RESET_BIT + */ +void MPU6050_Base::resetGyroscopePath() { + I2Cdev::writeBit(devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_GYRO_RESET_BIT, true, wireObj); +} +/** Reset accelerometer signal path. + * The reset will revert the signal path analog to digital converters and + * filters to their power up configurations. + * @see MPU6050_RA_SIGNAL_PATH_RESET + * @see MPU6050_PATHRESET_ACCEL_RESET_BIT + */ +void MPU6050_Base::resetAccelerometerPath() { + I2Cdev::writeBit(devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_ACCEL_RESET_BIT, true, wireObj); +} +/** Reset temperature sensor signal path. + * The reset will revert the signal path analog to digital converters and + * filters to their power up configurations. + * @see MPU6050_RA_SIGNAL_PATH_RESET + * @see MPU6050_PATHRESET_TEMP_RESET_BIT + */ +void MPU6050_Base::resetTemperaturePath() { + I2Cdev::writeBit(devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_TEMP_RESET_BIT, true, wireObj); +} + +// MOT_DETECT_CTRL register + +/** Get accelerometer power-on delay. + * The accelerometer data path provides samples to the sensor registers, Motion + * detection, Zero Motion detection, and Free Fall detection modules. The + * signal path contains filters which must be flushed on wake-up with new + * samples before the detection modules begin operations. The default wake-up + * delay, of 4ms can be lengthened by up to 3ms. This additional delay is + * specified in ACCEL_ON_DELAY in units of 1 LSB = 1 ms. The user may select + * any value above zero unless instructed otherwise by InvenSense. Please refer + * to Section 8 of the MPU-6000/MPU-6050 Product Specification document for + * further information regarding the detection modules. + * @return Current accelerometer power-on delay + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_ACCEL_ON_DELAY_BIT + */ +uint8_t MPU6050_Base::getAccelerometerPowerOnDelay() { + I2Cdev::readBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_ACCEL_ON_DELAY_BIT, MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set accelerometer power-on delay. + * @param delay New accelerometer power-on delay (0-3) + * @see getAccelerometerPowerOnDelay() + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_ACCEL_ON_DELAY_BIT + */ +void MPU6050_Base::setAccelerometerPowerOnDelay(uint8_t delay) { + I2Cdev::writeBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_ACCEL_ON_DELAY_BIT, MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH, delay, wireObj); +} +/** Get Free Fall detection counter decrement configuration. + * Detection is registered by the Free Fall detection module after accelerometer + * measurements meet their respective threshold conditions over a specified + * number of samples. When the threshold conditions are met, the corresponding + * detection counter increments by 1. The user may control the rate at which the + * detection counter decrements when the threshold condition is not met by + * configuring FF_COUNT. The decrement rate can be set according to the + * following table: + * + *
+ * FF_COUNT | Counter Decrement
+ * ---------+------------------
+ * 0        | Reset
+ * 1        | 1
+ * 2        | 2
+ * 3        | 4
+ * 
+ * + * When FF_COUNT is configured to 0 (reset), any non-qualifying sample will + * reset the counter to 0. For further information on Free Fall detection, + * please refer to Registers 29 to 32. + * + * @return Current decrement configuration + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_FF_COUNT_BIT + */ +uint8_t MPU6050_Base::getFreefallDetectionCounterDecrement() { + I2Cdev::readBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_FF_COUNT_BIT, MPU6050_DETECT_FF_COUNT_LENGTH, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set Free Fall detection counter decrement configuration. + * @param decrement New decrement configuration value + * @see getFreefallDetectionCounterDecrement() + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_FF_COUNT_BIT + */ +void MPU6050_Base::setFreefallDetectionCounterDecrement(uint8_t decrement) { + I2Cdev::writeBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_FF_COUNT_BIT, MPU6050_DETECT_FF_COUNT_LENGTH, decrement, wireObj); +} +/** Get Motion detection counter decrement configuration. + * Detection is registered by the Motion detection module after accelerometer + * measurements meet their respective threshold conditions over a specified + * number of samples. When the threshold conditions are met, the corresponding + * detection counter increments by 1. The user may control the rate at which the + * detection counter decrements when the threshold condition is not met by + * configuring MOT_COUNT. The decrement rate can be set according to the + * following table: + * + *
+ * MOT_COUNT | Counter Decrement
+ * ----------+------------------
+ * 0         | Reset
+ * 1         | 1
+ * 2         | 2
+ * 3         | 4
+ * 
+ * + * When MOT_COUNT is configured to 0 (reset), any non-qualifying sample will + * reset the counter to 0. For further information on Motion detection, + * please refer to Registers 29 to 32. + * + */ +uint8_t MPU6050_Base::getMotionDetectionCounterDecrement() { + I2Cdev::readBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_MOT_COUNT_BIT, MPU6050_DETECT_MOT_COUNT_LENGTH, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set Motion detection counter decrement configuration. + * @param decrement New decrement configuration value + * @see getMotionDetectionCounterDecrement() + * @see MPU6050_RA_MOT_DETECT_CTRL + * @see MPU6050_DETECT_MOT_COUNT_BIT + */ +void MPU6050_Base::setMotionDetectionCounterDecrement(uint8_t decrement) { + I2Cdev::writeBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_MOT_COUNT_BIT, MPU6050_DETECT_MOT_COUNT_LENGTH, decrement, wireObj); +} + +// USER_CTRL register + +/** Get FIFO enabled status. + * When this bit is set to 0, the FIFO buffer is disabled. The FIFO buffer + * cannot be written to or read from while disabled. The FIFO buffer's state + * does not change unless the MPU-60X0 is power cycled. + * @return Current FIFO enabled status + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_FIFO_EN_BIT + */ +bool MPU6050_Base::getFIFOEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set FIFO enabled status. + * @param enabled New FIFO enabled status + * @see getFIFOEnabled() + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_FIFO_EN_BIT + */ +void MPU6050_Base::setFIFOEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_EN_BIT, enabled, wireObj); +} +/** Get I2C Master Mode enabled status. + * When this mode is enabled, the MPU-60X0 acts as the I2C Master to the + * external sensor slave devices on the auxiliary I2C bus. When this bit is + * cleared to 0, the auxiliary I2C bus lines (AUX_DA and AUX_CL) are logically + * driven by the primary I2C bus (SDA and SCL). This is a precondition to + * enabling Bypass Mode. For further information regarding Bypass Mode, please + * refer to Register 55. + * @return Current I2C Master Mode enabled status + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_I2C_MST_EN_BIT + */ +bool MPU6050_Base::getI2CMasterModeEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set I2C Master Mode enabled status. + * @param enabled New I2C Master Mode enabled status + * @see getI2CMasterModeEnabled() + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_I2C_MST_EN_BIT + */ +void MPU6050_Base::setI2CMasterModeEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_EN_BIT, enabled, wireObj); +} +/** Switch from I2C to SPI mode (MPU-6000 only) + * If this is set, the primary SPI interface will be enabled in place of the + * disabled primary I2C interface. + */ +void MPU6050_Base::switchSPIEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_IF_DIS_BIT, enabled, wireObj); +} +/** Reset the FIFO. + * This bit resets the FIFO buffer when set to 1 while FIFO_EN equals 0. This + * bit automatically clears to 0 after the reset has been triggered. + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_FIFO_RESET_BIT + */ +void MPU6050_Base::resetFIFO() { + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_RESET_BIT, true, wireObj); +} +/** Reset the I2C Master. + * This bit resets the I2C Master when set to 1 while I2C_MST_EN equals 0. + * This bit automatically clears to 0 after the reset has been triggered. + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_I2C_MST_RESET_BIT + */ +void MPU6050_Base::resetI2CMaster() { + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_RESET_BIT, true, wireObj); +} +/** Reset all sensor registers and signal paths. + * When set to 1, this bit resets the signal paths for all sensors (gyroscopes, + * accelerometers, and temperature sensor). This operation will also clear the + * sensor registers. This bit automatically clears to 0 after the reset has been + * triggered. + * + * When resetting only the signal path (and not the sensor registers), please + * use Register 104, SIGNAL_PATH_RESET. + * + * @see MPU6050_RA_USER_CTRL + * @see MPU6050_USERCTRL_SIG_COND_RESET_BIT + */ +void MPU6050_Base::resetSensors() { + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_SIG_COND_RESET_BIT, true, wireObj); +} + +// PWR_MGMT_1 register + +/** Trigger a full device reset. + * A small delay of ~50ms may be desirable after triggering a reset. + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_DEVICE_RESET_BIT + */ +void MPU6050_Base::reset() { + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_DEVICE_RESET_BIT, true, wireObj); +} +/** Get sleep mode status. + * Setting the SLEEP bit in the register puts the device into very low power + * sleep mode. In this mode, only the serial interface and internal registers + * remain active, allowing for a very low standby current. Clearing this bit + * puts the device back into normal mode. To save power, the individual standby + * selections for each of the gyros should be used if any gyro axis is not used + * by the application. + * @return Current sleep mode enabled status + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_SLEEP_BIT + */ +bool MPU6050_Base::getSleepEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set sleep mode status. + * @param enabled New sleep mode enabled status + * @see getSleepEnabled() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_SLEEP_BIT + */ +void MPU6050_Base::setSleepEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, enabled, wireObj); +} +/** Get wake cycle enabled status. + * When this bit is set to 1 and SLEEP is disabled, the MPU-60X0 will cycle + * between sleep mode and waking up to take a single sample of data from active + * sensors at a rate determined by LP_WAKE_CTRL (register 108). + * @return Current sleep mode enabled status + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CYCLE_BIT + */ +bool MPU6050_Base::getWakeCycleEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CYCLE_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set wake cycle enabled status. + * @param enabled New sleep mode enabled status + * @see getWakeCycleEnabled() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CYCLE_BIT + */ +void MPU6050_Base::setWakeCycleEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CYCLE_BIT, enabled, wireObj); +} +/** Get temperature sensor enabled status. + * Control the usage of the internal temperature sensor. + * + * Note: this register stores the *disabled* value, but for consistency with the + * rest of the code, the function is named and used with standard true/false + * values to indicate whether the sensor is enabled or disabled, respectively. + * + * @return Current temperature sensor enabled status + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_TEMP_DIS_BIT + */ +bool MPU6050_Base::getTempSensorEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_TEMP_DIS_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0] == 0; // 1 is actually disabled here +} +/** Set temperature sensor enabled status. + * Note: this register stores the *disabled* value, but for consistency with the + * rest of the code, the function is named and used with standard true/false + * values to indicate whether the sensor is enabled or disabled, respectively. + * + * @param enabled New temperature sensor enabled status + * @see getTempSensorEnabled() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_TEMP_DIS_BIT + */ +void MPU6050_Base::setTempSensorEnabled(bool enabled) { + // 1 is actually disabled here + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_TEMP_DIS_BIT, !enabled, wireObj); +} +/** Get clock source setting. + * @return Current clock source setting + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CLKSEL_BIT + * @see MPU6050_PWR1_CLKSEL_LENGTH + */ +uint8_t MPU6050_Base::getClockSource() { + I2Cdev::readBits(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set clock source setting. + * An internal 8MHz oscillator, gyroscope based clock, or external sources can + * be selected as the MPU-60X0 clock source. When the internal 8 MHz oscillator + * or an external source is chosen as the clock source, the MPU-60X0 can operate + * in low power modes with the gyroscopes disabled. + * + * Upon power up, the MPU-60X0 clock source defaults to the internal oscillator. + * However, it is highly recommended that the device be configured to use one of + * the gyroscopes (or an external clock source) as the clock reference for + * improved stability. The clock source can be selected according to the following table: + * + *
+ * CLK_SEL | Clock Source
+ * --------+--------------------------------------
+ * 0       | Internal oscillator
+ * 1       | PLL with X Gyro reference
+ * 2       | PLL with Y Gyro reference
+ * 3       | PLL with Z Gyro reference
+ * 4       | PLL with external 32.768kHz reference
+ * 5       | PLL with external 19.2MHz reference
+ * 6       | Reserved
+ * 7       | Stops the clock and keeps the timing generator in reset
+ * 
+ * + * @param source New clock source setting + * @see getClockSource() + * @see MPU6050_RA_PWR_MGMT_1 + * @see MPU6050_PWR1_CLKSEL_BIT + * @see MPU6050_PWR1_CLKSEL_LENGTH + */ +void MPU6050_Base::setClockSource(uint8_t source) { + I2Cdev::writeBits(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, source, wireObj); +} + +// PWR_MGMT_2 register + +/** Get wake frequency in Accel-Only Low Power Mode. + * The MPU-60X0 can be put into Accerlerometer Only Low Power Mode by setting + * PWRSEL to 1 in the Power Management 1 register (Register 107). In this mode, + * the device will power off all devices except for the primary I2C interface, + * waking only the accelerometer at fixed intervals to take a single + * measurement. The frequency of wake-ups can be configured with LP_WAKE_CTRL + * as shown below: + * + *
+ * LP_WAKE_CTRL | Wake-up Frequency
+ * -------------+------------------
+ * 0            | 1.25 Hz
+ * 1            | 2.5 Hz
+ * 2            | 20 Hz
+ * 3            | 40 Hz
+ * 
+ * + * For further information regarding the MPU-60X0's power modes, please refer to + * Register 107. + * + * @return Current wake frequency + * @see MPU6050_RA_PWR_MGMT_2 + */ +uint8_t MPU6050_Base::getWakeFrequency() { + I2Cdev::readBits(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_LP_WAKE_CTRL_BIT, MPU6050_PWR2_LP_WAKE_CTRL_LENGTH, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set wake frequency in Accel-Only Low Power Mode. + * @param frequency New wake frequency + * @see MPU6050_RA_PWR_MGMT_2 + */ +void MPU6050_Base::setWakeFrequency(uint8_t frequency) { + I2Cdev::writeBits(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_LP_WAKE_CTRL_BIT, MPU6050_PWR2_LP_WAKE_CTRL_LENGTH, frequency, wireObj); +} + +/** Get X-axis accelerometer standby enabled status. + * If enabled, the X-axis will not gather or report data (or use power). + * @return Current X-axis standby enabled status + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_XA_BIT + */ +bool MPU6050_Base::getStandbyXAccelEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XA_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set X-axis accelerometer standby enabled status. + * @param New X-axis standby enabled status + * @see getStandbyXAccelEnabled() + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_XA_BIT + */ +void MPU6050_Base::setStandbyXAccelEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XA_BIT, enabled, wireObj); +} +/** Get Y-axis accelerometer standby enabled status. + * If enabled, the Y-axis will not gather or report data (or use power). + * @return Current Y-axis standby enabled status + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_YA_BIT + */ +bool MPU6050_Base::getStandbyYAccelEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YA_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set Y-axis accelerometer standby enabled status. + * @param New Y-axis standby enabled status + * @see getStandbyYAccelEnabled() + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_YA_BIT + */ +void MPU6050_Base::setStandbyYAccelEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YA_BIT, enabled, wireObj); +} +/** Get Z-axis accelerometer standby enabled status. + * If enabled, the Z-axis will not gather or report data (or use power). + * @return Current Z-axis standby enabled status + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_ZA_BIT + */ +bool MPU6050_Base::getStandbyZAccelEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZA_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set Z-axis accelerometer standby enabled status. + * @param New Z-axis standby enabled status + * @see getStandbyZAccelEnabled() + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_ZA_BIT + */ +void MPU6050_Base::setStandbyZAccelEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZA_BIT, enabled, wireObj); +} +/** Get X-axis gyroscope standby enabled status. + * If enabled, the X-axis will not gather or report data (or use power). + * @return Current X-axis standby enabled status + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_XG_BIT + */ +bool MPU6050_Base::getStandbyXGyroEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XG_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set X-axis gyroscope standby enabled status. + * @param New X-axis standby enabled status + * @see getStandbyXGyroEnabled() + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_XG_BIT + */ +void MPU6050_Base::setStandbyXGyroEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XG_BIT, enabled, wireObj); +} +/** Get Y-axis gyroscope standby enabled status. + * If enabled, the Y-axis will not gather or report data (or use power). + * @return Current Y-axis standby enabled status + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_YG_BIT + */ +bool MPU6050_Base::getStandbyYGyroEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YG_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set Y-axis gyroscope standby enabled status. + * @param New Y-axis standby enabled status + * @see getStandbyYGyroEnabled() + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_YG_BIT + */ +void MPU6050_Base::setStandbyYGyroEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YG_BIT, enabled, wireObj); +} +/** Get Z-axis gyroscope standby enabled status. + * If enabled, the Z-axis will not gather or report data (or use power). + * @return Current Z-axis standby enabled status + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_ZG_BIT + */ +bool MPU6050_Base::getStandbyZGyroEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZG_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set Z-axis gyroscope standby enabled status. + * @param New Z-axis standby enabled status + * @see getStandbyZGyroEnabled() + * @see MPU6050_RA_PWR_MGMT_2 + * @see MPU6050_PWR2_STBY_ZG_BIT + */ +void MPU6050_Base::setStandbyZGyroEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZG_BIT, enabled, wireObj); +} + +// FIFO_COUNT* registers + +/** Get current FIFO buffer size. + * This value indicates the number of bytes stored in the FIFO buffer. This + * number is in turn the number of bytes that can be read from the FIFO buffer + * and it is directly proportional to the number of samples available given the + * set of sensor data bound to be stored in the FIFO (register 35 and 36). + * @return Current FIFO buffer size + */ +uint16_t MPU6050_Base::getFIFOCount() { + I2Cdev::readBytes(devAddr, MPU6050_RA_FIFO_COUNTH, 2, buffer, I2Cdev::readTimeout, wireObj); + return (((uint16_t)buffer[0]) << 8) | buffer[1]; +} + +// FIFO_R_W register + +/** Get byte from FIFO buffer. + * This register is used to read and write data from the FIFO buffer. Data is + * written to the FIFO in order of register number (from lowest to highest). If + * all the FIFO enable flags (see below) are enabled and all External Sensor + * Data registers (Registers 73 to 96) are associated with a Slave device, the + * contents of registers 59 through 96 will be written in order at the Sample + * Rate. + * + * The contents of the sensor data registers (Registers 59 to 96) are written + * into the FIFO buffer when their corresponding FIFO enable flags are set to 1 + * in FIFO_EN (Register 35). An additional flag for the sensor data registers + * associated with I2C Slave 3 can be found in I2C_MST_CTRL (Register 36). + * + * If the FIFO buffer has overflowed, the status bit FIFO_OFLOW_INT is + * automatically set to 1. This bit is located in INT_STATUS (Register 58). + * When the FIFO buffer has overflowed, the oldest data will be lost and new + * data will be written to the FIFO. + * + * If the FIFO buffer is empty, reading this register will return the last byte + * that was previously read from the FIFO until new data is available. The user + * should check FIFO_COUNT to ensure that the FIFO buffer is not read when + * empty. + * + * @return Byte from FIFO buffer + */ +uint8_t MPU6050_Base::getFIFOByte() { + I2Cdev::readByte(devAddr, MPU6050_RA_FIFO_R_W, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +void MPU6050_Base::getFIFOBytes(uint8_t *data, uint8_t length) { + if(length > 0){ + I2Cdev::readBytes(devAddr, MPU6050_RA_FIFO_R_W, length, data, I2Cdev::readTimeout, wireObj); + } else { + *data = 0; + } +} + +/** Get timeout to get a packet from FIFO buffer. + * @return Current timeout to get a packet from FIFO buffer + * @see MPU6050_FIFO_DEFAULT_TIMEOUT + */ +uint32_t MPU6050_Base::getFIFOTimeout() { + return fifoTimeout; +} + +/** Set timeout to get a packet from FIFO buffer. + * @param New timeout to get a packet from FIFO buffer + * @see MPU6050_FIFO_DEFAULT_TIMEOUT + */ +void MPU6050_Base::setFIFOTimeout(uint32_t fifoTimeout) { + this->fifoTimeout = fifoTimeout; +} + +/** Get latest byte from FIFO buffer no matter how much time has passed. + * === GetCurrentFIFOPacket === + * ================================================================ + * Returns 1) when nothing special was done + * 2) when recovering from overflow + * 0) when no valid data is available + * ================================================================ */ + int8_t MPU6050_Base::GetCurrentFIFOPacket(uint8_t *data, uint8_t length) { // overflow proof + int16_t fifoC; + // This section of code is for when we allowed more than 1 packet to be acquired + uint32_t BreakTimer = micros(); + bool packetReceived = false; + do { + if ((fifoC = getFIFOCount()) > length) { + + if (fifoC > 200) { // if you waited to get the FIFO buffer to > 200 bytes it will take longer to get the last packet in the FIFO Buffer than it will take to reset the buffer and wait for the next to arrive + resetFIFO(); // Fixes any overflow corruption + fifoC = 0; + while (!(fifoC = getFIFOCount()) && ((micros() - BreakTimer) <= (getFIFOTimeout()))); // Get Next New Packet + } else { //We have more than 1 packet but less than 200 bytes of data in the FIFO Buffer + uint8_t Trash[I2CDEVLIB_WIRE_BUFFER_LENGTH]; + while ((fifoC = getFIFOCount()) > length) { // Test each time just in case the MPU is writing to the FIFO Buffer + fifoC = fifoC - length; // Save the last packet + uint16_t RemoveBytes; + while (fifoC) { // fifo count will reach zero so this is safe + RemoveBytes = (fifoC < I2CDEVLIB_WIRE_BUFFER_LENGTH) ? fifoC : I2CDEVLIB_WIRE_BUFFER_LENGTH; // Buffer Length is different than the packet length this will efficiently clear the buffer + getFIFOBytes(Trash, (uint8_t)RemoveBytes); + fifoC -= RemoveBytes; + } + } + } + } + if (!fifoC) return 0; // Called too early no data or we timed out after FIFO Reset + // We have 1 packet + packetReceived = fifoC == length; + if (!packetReceived && (micros() - BreakTimer) > (getFIFOTimeout())) return 0; + } while (!packetReceived); + getFIFOBytes(data, length); //Get 1 packet + return 1; +} + + +/** Write byte to FIFO buffer. + * @see getFIFOByte() + * @see MPU6050_RA_FIFO_R_W + */ +void MPU6050_Base::setFIFOByte(uint8_t data) { + I2Cdev::writeByte(devAddr, MPU6050_RA_FIFO_R_W, data, wireObj); +} + +// WHO_AM_I register + +/** Get Device ID. + * This register is used to verify the identity of the device (0b110100, 0x34). + * @return Device ID (6 bits only! should be 0x34) + * @see MPU6050_RA_WHO_AM_I + * @see MPU6050_WHO_AM_I_BIT + * @see MPU6050_WHO_AM_I_LENGTH + */ +uint8_t MPU6050_Base::getDeviceID() { + I2Cdev::readBits(devAddr, MPU6050_RA_WHO_AM_I, MPU6050_WHO_AM_I_BIT, MPU6050_WHO_AM_I_LENGTH, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +/** Set Device ID. + * Write a new ID into the WHO_AM_I register (no idea why this should ever be + * necessary though). + * @param id New device ID to set. + * @see getDeviceID() + * @see MPU6050_RA_WHO_AM_I + * @see MPU6050_WHO_AM_I_BIT + * @see MPU6050_WHO_AM_I_LENGTH + */ +void MPU6050_Base::setDeviceID(uint8_t id) { + I2Cdev::writeBits(devAddr, MPU6050_RA_WHO_AM_I, MPU6050_WHO_AM_I_BIT, MPU6050_WHO_AM_I_LENGTH, id, wireObj); +} + +// ======== UNDOCUMENTED/DMP REGISTERS/METHODS ======== + +// XG_OFFS_TC register + +uint8_t MPU6050_Base::getOTPBankValid() { + I2Cdev::readBit(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OTP_BNK_VLD_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +void MPU6050_Base::setOTPBankValid(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OTP_BNK_VLD_BIT, enabled, wireObj); +} +int8_t MPU6050_Base::getXGyroOffsetTC() { + I2Cdev::readBits(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +void MPU6050_Base::setXGyroOffsetTC(int8_t offset) { + I2Cdev::writeBits(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset, wireObj); +} + +// YG_OFFS_TC register + +int8_t MPU6050_Base::getYGyroOffsetTC() { + I2Cdev::readBits(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +void MPU6050_Base::setYGyroOffsetTC(int8_t offset) { + I2Cdev::writeBits(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset, wireObj); +} + +// ZG_OFFS_TC register + +int8_t MPU6050_Base::getZGyroOffsetTC() { + I2Cdev::readBits(devAddr, MPU6050_RA_ZG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +void MPU6050_Base::setZGyroOffsetTC(int8_t offset) { + I2Cdev::writeBits(devAddr, MPU6050_RA_ZG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset, wireObj); +} + +// X_FINE_GAIN register + +int8_t MPU6050_Base::getXFineGain() { + I2Cdev::readByte(devAddr, MPU6050_RA_X_FINE_GAIN, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +void MPU6050_Base::setXFineGain(int8_t gain) { + I2Cdev::writeByte(devAddr, MPU6050_RA_X_FINE_GAIN, gain, wireObj); +} + +// Y_FINE_GAIN register + +int8_t MPU6050_Base::getYFineGain() { + I2Cdev::readByte(devAddr, MPU6050_RA_Y_FINE_GAIN, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +void MPU6050_Base::setYFineGain(int8_t gain) { + I2Cdev::writeByte(devAddr, MPU6050_RA_Y_FINE_GAIN, gain, wireObj); +} + +// Z_FINE_GAIN register + +int8_t MPU6050_Base::getZFineGain() { + I2Cdev::readByte(devAddr, MPU6050_RA_Z_FINE_GAIN, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +void MPU6050_Base::setZFineGain(int8_t gain) { + I2Cdev::writeByte(devAddr, MPU6050_RA_Z_FINE_GAIN, gain, wireObj); +} + +// XA_OFFS_* registers + +int16_t MPU6050_Base::getXAccelOffset() { + uint8_t SaveAddress = ((getDeviceID() < 0x38 )? MPU6050_RA_XA_OFFS_H:0x77); // MPU6050,MPU9150 Vs MPU6500,MPU9250 + I2Cdev::readBytes(devAddr, SaveAddress, 2, buffer, I2Cdev::readTimeout, wireObj); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +void MPU6050_Base::setXAccelOffset(int16_t offset) { + uint8_t SaveAddress = ((getDeviceID() < 0x38 )? MPU6050_RA_XA_OFFS_H:0x77); // MPU6050,MPU9150 Vs MPU6500,MPU9250 + I2Cdev::writeWord(devAddr, SaveAddress, offset, wireObj); +} + +// YA_OFFS_* register + +int16_t MPU6050_Base::getYAccelOffset() { + uint8_t SaveAddress = ((getDeviceID() < 0x38 )? MPU6050_RA_YA_OFFS_H:0x7A); // MPU6050,MPU9150 Vs MPU6500,MPU9250 + I2Cdev::readBytes(devAddr, SaveAddress, 2, buffer, I2Cdev::readTimeout, wireObj); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +void MPU6050_Base::setYAccelOffset(int16_t offset) { + uint8_t SaveAddress = ((getDeviceID() < 0x38 )? MPU6050_RA_YA_OFFS_H:0x7A); // MPU6050,MPU9150 Vs MPU6500,MPU9250 + I2Cdev::writeWord(devAddr, SaveAddress, offset, wireObj); +} + +// ZA_OFFS_* register + +int16_t MPU6050_Base::getZAccelOffset() { + uint8_t SaveAddress = ((getDeviceID() < 0x38 )? MPU6050_RA_ZA_OFFS_H:0x7D); // MPU6050,MPU9150 Vs MPU6500,MPU9250 + I2Cdev::readBytes(devAddr, SaveAddress, 2, buffer, I2Cdev::readTimeout, wireObj); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +void MPU6050_Base::setZAccelOffset(int16_t offset) { + uint8_t SaveAddress = ((getDeviceID() < 0x38 )? MPU6050_RA_ZA_OFFS_H:0x7D); // MPU6050,MPU9150 Vs MPU6500,MPU9250 + I2Cdev::writeWord(devAddr, SaveAddress, offset, wireObj); +} + +// XG_OFFS_USR* registers + +int16_t MPU6050_Base::getXGyroOffset() { + I2Cdev::readBytes(devAddr, MPU6050_RA_XG_OFFS_USRH, 2, buffer, I2Cdev::readTimeout, wireObj); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +void MPU6050_Base::setXGyroOffset(int16_t offset) { + I2Cdev::writeWord(devAddr, MPU6050_RA_XG_OFFS_USRH, offset, wireObj); +} + +// YG_OFFS_USR* register + +int16_t MPU6050_Base::getYGyroOffset() { + I2Cdev::readBytes(devAddr, MPU6050_RA_YG_OFFS_USRH, 2, buffer, I2Cdev::readTimeout, wireObj); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +void MPU6050_Base::setYGyroOffset(int16_t offset) { + I2Cdev::writeWord(devAddr, MPU6050_RA_YG_OFFS_USRH, offset, wireObj); +} + +// ZG_OFFS_USR* register + +int16_t MPU6050_Base::getZGyroOffset() { + I2Cdev::readBytes(devAddr, MPU6050_RA_ZG_OFFS_USRH, 2, buffer, I2Cdev::readTimeout, wireObj); + return (((int16_t)buffer[0]) << 8) | buffer[1]; +} +void MPU6050_Base::setZGyroOffset(int16_t offset) { + I2Cdev::writeWord(devAddr, MPU6050_RA_ZG_OFFS_USRH, offset, wireObj); +} + +// INT_ENABLE register (DMP functions) + +bool MPU6050_Base::getIntPLLReadyEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +void MPU6050_Base::setIntPLLReadyEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, enabled, wireObj); +} +bool MPU6050_Base::getIntDMPEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DMP_INT_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +void MPU6050_Base::setIntDMPEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DMP_INT_BIT, enabled, wireObj); +} + +// DMP_INT_STATUS + +bool MPU6050_Base::getDMPInt5Status() { + I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_5_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +bool MPU6050_Base::getDMPInt4Status() { + I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_4_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +bool MPU6050_Base::getDMPInt3Status() { + I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_3_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +bool MPU6050_Base::getDMPInt2Status() { + I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_2_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +bool MPU6050_Base::getDMPInt1Status() { + I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_1_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +bool MPU6050_Base::getDMPInt0Status() { + I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_0_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} + +// INT_STATUS register (DMP functions) + +bool MPU6050_Base::getIntPLLReadyStatus() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +bool MPU6050_Base::getIntDMPStatus() { + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_DMP_INT_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} + +// USER_CTRL register (DMP functions) + +bool MPU6050_Base::getDMPEnabled() { + I2Cdev::readBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +void MPU6050_Base::setDMPEnabled(bool enabled) { + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_EN_BIT, enabled, wireObj); +} +void MPU6050_Base::resetDMP() { + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_RESET_BIT, true, wireObj); +} + +// BANK_SEL register + +void MPU6050_Base::setMemoryBank(uint8_t bank, bool prefetchEnabled, bool userBank) { + bank &= 0x1F; + if (userBank) bank |= 0x20; + if (prefetchEnabled) bank |= 0x40; + I2Cdev::writeByte(devAddr, MPU6050_RA_BANK_SEL, bank, wireObj); +} + +// MEM_START_ADDR register + +void MPU6050_Base::setMemoryStartAddress(uint8_t address) { + I2Cdev::writeByte(devAddr, MPU6050_RA_MEM_START_ADDR, address, wireObj); +} + +// MEM_R_W register + +uint8_t MPU6050_Base::readMemoryByte() { + I2Cdev::readByte(devAddr, MPU6050_RA_MEM_R_W, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +void MPU6050_Base::writeMemoryByte(uint8_t data) { + I2Cdev::writeByte(devAddr, MPU6050_RA_MEM_R_W, data, wireObj); +} +void MPU6050_Base::readMemoryBlock(uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address) { + setMemoryBank(bank); + setMemoryStartAddress(address); + uint8_t chunkSize; + for (uint16_t i = 0; i < dataSize;) { + // determine correct chunk size according to bank position and data size + chunkSize = MPU6050_DMP_MEMORY_CHUNK_SIZE; + + // make sure we don't go past the data size + if (i + chunkSize > dataSize) chunkSize = dataSize - i; + + // make sure this chunk doesn't go past the bank boundary (256 bytes) + if (chunkSize > 256 - address) chunkSize = 256 - address; + + // read the chunk of data as specified + I2Cdev::readBytes(devAddr, MPU6050_RA_MEM_R_W, chunkSize, data + i, I2Cdev::readTimeout, wireObj); + + // increase byte index by [chunkSize] + i += chunkSize; + + // uint8_t automatically wraps to 0 at 256 + address += chunkSize; + + // if we aren't done, update bank (if necessary) and address + if (i < dataSize) { + if (address == 0) bank++; + setMemoryBank(bank); + setMemoryStartAddress(address); + } + } +} +bool MPU6050_Base::writeMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address, bool verify, bool useProgMem) { + setMemoryBank(bank); + setMemoryStartAddress(address); + uint8_t chunkSize; + uint8_t *verifyBuffer=0; + uint8_t *progBuffer=0; + uint16_t i; + uint8_t j; + if (verify) verifyBuffer = (uint8_t *)malloc(MPU6050_DMP_MEMORY_CHUNK_SIZE); + if (useProgMem) progBuffer = (uint8_t *)malloc(MPU6050_DMP_MEMORY_CHUNK_SIZE); + for (i = 0; i < dataSize;) { + // determine correct chunk size according to bank position and data size + chunkSize = MPU6050_DMP_MEMORY_CHUNK_SIZE; + + // make sure we don't go past the data size + if (i + chunkSize > dataSize) chunkSize = dataSize - i; + + // make sure this chunk doesn't go past the bank boundary (256 bytes) + if (chunkSize > 256 - address) chunkSize = 256 - address; + + if (useProgMem) { + // write the chunk of data as specified + for (j = 0; j < chunkSize; j++) progBuffer[j] = pgm_read_byte(data + i + j); + } else { + // write the chunk of data as specified + progBuffer = (uint8_t *)data + i; + } + + I2Cdev::writeBytes(devAddr, MPU6050_RA_MEM_R_W, chunkSize, progBuffer, wireObj); + + // verify data if needed + if (verify && verifyBuffer) { + setMemoryBank(bank); + setMemoryStartAddress(address); + I2Cdev::readBytes(devAddr, MPU6050_RA_MEM_R_W, chunkSize, verifyBuffer, I2Cdev::readTimeout, wireObj); + if (memcmp(progBuffer, verifyBuffer, chunkSize) != 0) { + /*Serial.print("Block write verification error, bank "); + Serial.print(bank, DEC); + Serial.print(", address "); + Serial.print(address, DEC); + Serial.print("!\nExpected:"); + for (j = 0; j < chunkSize; j++) { + Serial.print(" 0x"); + if (progBuffer[j] < 16) Serial.print("0"); + Serial.print(progBuffer[j], HEX); + } + Serial.print("\nReceived:"); + for (uint8_t j = 0; j < chunkSize; j++) { + Serial.print(" 0x"); + if (verifyBuffer[i + j] < 16) Serial.print("0"); + Serial.print(verifyBuffer[i + j], HEX); + } + Serial.print("\n");*/ + free(verifyBuffer); + if (useProgMem) free(progBuffer); + return false; // uh oh. + } + } + + // increase byte index by [chunkSize] + i += chunkSize; + + // uint8_t automatically wraps to 0 at 256 + address += chunkSize; + + // if we aren't done, update bank (if necessary) and address + if (i < dataSize) { + if (address == 0) bank++; + setMemoryBank(bank); + setMemoryStartAddress(address); + } + } + if (verify) free(verifyBuffer); + if (useProgMem) free(progBuffer); + return true; +} +bool MPU6050_Base::writeProgMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address, bool verify) { + return writeMemoryBlock(data, dataSize, bank, address, verify, true); +} +bool MPU6050_Base::writeDMPConfigurationSet(const uint8_t *data, uint16_t dataSize, bool useProgMem) { + uint8_t *progBuffer = 0; + uint8_t success, special; + uint16_t i, j; + if (useProgMem) { + progBuffer = (uint8_t *)malloc(8); // assume 8-byte blocks, realloc later if necessary + } + + // config set data is a long string of blocks with the following structure: + // [bank] [offset] [length] [byte[0], byte[1], ..., byte[length]] + uint8_t bank, offset, length; + for (i = 0; i < dataSize;) { + if (useProgMem) { + bank = pgm_read_byte(data + i++); + offset = pgm_read_byte(data + i++); + length = pgm_read_byte(data + i++); + } else { + bank = data[i++]; + offset = data[i++]; + length = data[i++]; + } + + // write data or perform special action + if (length > 0) { + // regular block of data to write + /*Serial.print("Writing config block to bank "); + Serial.print(bank); + Serial.print(", offset "); + Serial.print(offset); + Serial.print(", length="); + Serial.println(length);*/ + if (useProgMem) { + if (sizeof(progBuffer) < length) progBuffer = (uint8_t *)realloc(progBuffer, length); + for (j = 0; j < length; j++) progBuffer[j] = pgm_read_byte(data + i + j); + } else { + progBuffer = (uint8_t *)data + i; + } + success = writeMemoryBlock(progBuffer, length, bank, offset, true); + i += length; + } else { + // special instruction + // NOTE: this kind of behavior (what and when to do certain things) + // is totally undocumented. This code is in here based on observed + // behavior only, and exactly why (or even whether) it has to be here + // is anybody's guess for now. + if (useProgMem) { + special = pgm_read_byte(data + i++); + } else { + special = data[i++]; + } + /*Serial.print("Special command code "); + Serial.print(special, HEX); + Serial.println(" found...");*/ + if (special == 0x01) { + // enable DMP-related interrupts + + //setIntZeroMotionEnabled(true); + //setIntFIFOBufferOverflowEnabled(true); + //setIntDMPEnabled(true); + I2Cdev::writeByte(devAddr, MPU6050_RA_INT_ENABLE, 0x32, wireObj); // single operation + + success = true; + } else { + // unknown special command + success = false; + } + } + + if (!success) { + if (useProgMem) free(progBuffer); + return false; // uh oh + } + } + if (useProgMem) free(progBuffer); + return true; +} +bool MPU6050_Base::writeProgDMPConfigurationSet(const uint8_t *data, uint16_t dataSize) { + return writeDMPConfigurationSet(data, dataSize, true); +} + +// DMP_CFG_1 register + +uint8_t MPU6050_Base::getDMPConfig1() { + I2Cdev::readByte(devAddr, MPU6050_RA_DMP_CFG_1, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +void MPU6050_Base::setDMPConfig1(uint8_t config) { + I2Cdev::writeByte(devAddr, MPU6050_RA_DMP_CFG_1, config, wireObj); +} + +// DMP_CFG_2 register + +uint8_t MPU6050_Base::getDMPConfig2() { + I2Cdev::readByte(devAddr, MPU6050_RA_DMP_CFG_2, buffer, I2Cdev::readTimeout, wireObj); + return buffer[0]; +} +void MPU6050_Base::setDMPConfig2(uint8_t config) { + I2Cdev::writeByte(devAddr, MPU6050_RA_DMP_CFG_2, config, wireObj); +} + + +//*************************************************************************************** +//********************** Calibration Routines ********************** +//*************************************************************************************** +/** + @brief Fully calibrate Gyro from ZERO in about 6-7 Loops 600-700 readings +*/ +void MPU6050_Base::CalibrateGyro(uint8_t Loops ) { + double kP = 0.3; + double kI = 90; + float x; + x = (100 - map(Loops, 1, 5, 20, 0)) * .01; + kP *= x; + kI *= x; + + PID( 0x43, kP, kI, Loops); +} + +/** + @brief Fully calibrate Accel from ZERO in about 6-7 Loops 600-700 readings +*/ +void MPU6050_Base::CalibrateAccel(uint8_t Loops ) { + + float kP = 0.3; + float kI = 20; + float x; + x = (100 - map(Loops, 1, 5, 20, 0)) * .01; + kP *= x; + kI *= x; + PID( 0x3B, kP, kI, Loops); +} + +void MPU6050_Base::PID(uint8_t ReadAddress, float kP,float kI, uint8_t Loops){ + uint8_t SaveAddress = (ReadAddress == 0x3B)?((getDeviceID() < 0x38 )? 0x06:0x77):0x13; + + int16_t Data; + float Reading; + int16_t BitZero[3]; + uint8_t shift =(SaveAddress == 0x77)?3:2; + float Error, PTerm, ITerm[3]; + int16_t eSample; + uint32_t eSum; + uint16_t gravity = 8192; // prevent uninitialized compiler warning + if (ReadAddress == 0x3B) gravity = 16384 >> getFullScaleAccelRange(); + Serial.write('>'); + for (int i = 0; i < 3; i++) { + I2Cdev::readWords(devAddr, SaveAddress + (i * shift), 1, (uint16_t *)&Data, I2Cdev::readTimeout, wireObj); // reads 1 or more 16 bit integers (Word) + Reading = Data; + if(SaveAddress != 0x13){ + BitZero[i] = Data & 1; // Capture Bit Zero to properly handle Accelerometer calibration + ITerm[i] = ((float)Reading) * 8; + } else { + ITerm[i] = Reading * 4; + } + } + for (int L = 0; L < Loops; L++) { + eSample = 0; + for (int c = 0; c < 100; c++) {// 100 PI Calculations + eSum = 0; + for (int i = 0; i < 3; i++) { + I2Cdev::readWords(devAddr, ReadAddress + (i * 2), 1, (uint16_t *)&Data, I2Cdev::readTimeout, wireObj); // reads 1 or more 16 bit integers (Word) + Reading = Data; + if ((ReadAddress == 0x3B)&&(i == 2)) Reading -= gravity; //remove Gravity + Error = -Reading; + eSum += abs(Reading); + PTerm = kP * Error; + ITerm[i] += (Error * 0.001) * kI; // Integral term 1000 Calculations a second = 0.001 + if(SaveAddress != 0x13){ + Data = round((PTerm + ITerm[i] ) / 8); //Compute PID Output + Data = ((Data)&0xFFFE) |BitZero[i]; // Insert Bit0 Saved at beginning + } else Data = round((PTerm + ITerm[i] ) / 4); //Compute PID Output + I2Cdev::writeWords(devAddr, SaveAddress + (i * shift), 1, (uint16_t *)&Data, wireObj); + } + if((c == 99) && eSum > 1000){ // Error is still to great to continue + c = 0; + Serial.write('*'); + } + if((eSum * ((ReadAddress == 0x3B)?.05: 1)) < 5) eSample++; // Successfully found offsets prepare to advance + if((eSum < 100) && (c > 10) && (eSample >= 10)) break; // Advance to next Loop + delay(1); + } + Serial.write('.'); + kP *= .75; + kI *= .75; + for (int i = 0; i < 3; i++){ + if(SaveAddress != 0x13) { + Data = round((ITerm[i] ) / 8); //Compute PID Output + Data = ((Data)&0xFFFE) |BitZero[i]; // Insert Bit0 Saved at beginning + } else Data = round((ITerm[i]) / 4); + I2Cdev::writeWords(devAddr, SaveAddress + (i * shift), 1, (uint16_t *)&Data, wireObj); + } + } + resetFIFO(); + resetDMP(); +} + +int16_t * MPU6050_Base::GetActiveOffsets() { + uint8_t AOffsetRegister = (getDeviceID() < 0x38 )? MPU6050_RA_XA_OFFS_H:0x77; + if(AOffsetRegister == 0x06) I2Cdev::readWords(devAddr, AOffsetRegister, 3, (uint16_t *)offsets, I2Cdev::readTimeout, wireObj); + else { + I2Cdev::readWords(devAddr, AOffsetRegister, 1, (uint16_t *)offsets, I2Cdev::readTimeout, wireObj); + I2Cdev::readWords(devAddr, AOffsetRegister+3, 1, (uint16_t *)(offsets+1), I2Cdev::readTimeout, wireObj); + I2Cdev::readWords(devAddr, AOffsetRegister+6, 1, (uint16_t *)(offsets+2), I2Cdev::readTimeout, wireObj); + } + I2Cdev::readWords(devAddr, 0x13, 3, (uint16_t *)(offsets+3), I2Cdev::readTimeout, wireObj); + return offsets; +} + +void MPU6050_Base::PrintActiveOffsets() { + GetActiveOffsets(); + // A_OFFSET_H_READ_A_OFFS(Data); + Serial.print((float)offsets[0], 5); Serial.print(",\t"); + Serial.print((float)offsets[1], 5); Serial.print(",\t"); + Serial.print((float)offsets[2], 5); Serial.print(",\t"); + + // XG_OFFSET_H_READ_OFFS_USR(Data); + Serial.print((float)offsets[3], 5); Serial.print(",\t"); + Serial.print((float)offsets[4], 5); Serial.print(",\t"); + Serial.print((float)offsets[5], 5); Serial.print("\n\n"); +} diff --git a/LinuxI2CDev/MPU6050/MPU6050.h b/LinuxI2CDev/MPU6050/MPU6050.h new file mode 100644 index 00000000..7cbbb9dd --- /dev/null +++ b/LinuxI2CDev/MPU6050/MPU6050.h @@ -0,0 +1,852 @@ +// I2Cdev library collection - MPU6050 I2C device class +// Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00) +// 10/3/2011 by Jeff Rowberg +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// 2021/09/27 - split implementations out of header files, finally +// ... - ongoing debug release + +// NOTE: THIS IS ONLY A PARIAL RELEASE. THIS DEVICE CLASS IS CURRENTLY UNDERGOING ACTIVE +// DEVELOPMENT AND IS STILL MISSING SOME IMPORTANT FEATURES. PLEASE KEEP THIS IN MIND IF +// YOU DECIDE TO USE THIS PARTICULAR CODE FOR ANYTHING. + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2012 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#ifndef _MPU6050_H_ +#define _MPU6050_H_ + +#include "I2Cdev.h" +#include "helper_3dmath.h" + +// supporting link: http://forum.arduino.cc/index.php?&topic=143444.msg1079517#msg1079517 +// also: http://forum.arduino.cc/index.php?&topic=141571.msg1062899#msg1062899s + +#ifdef __AVR__ +#include +#elif defined(ESP32) + #include +#else +//#define PROGMEM /* empty */ +//#define pgm_read_byte(x) (*(x)) +//#define pgm_read_word(x) (*(x)) +//#define pgm_read_float(x) (*(x)) +//#define PSTR(STR) STR +#endif + + +#define MPU6050_ADDRESS_AD0_LOW 0x68 // address pin low (GND), default for InvenSense evaluation board +#define MPU6050_ADDRESS_AD0_HIGH 0x69 // address pin high (VCC) +#define MPU6050_DEFAULT_ADDRESS MPU6050_ADDRESS_AD0_LOW + +#define MPU6050_RA_XG_OFFS_TC 0x00 //[7] PWR_MODE, [6:1] XG_OFFS_TC, [0] OTP_BNK_VLD +#define MPU6050_RA_YG_OFFS_TC 0x01 //[7] PWR_MODE, [6:1] YG_OFFS_TC, [0] OTP_BNK_VLD +#define MPU6050_RA_ZG_OFFS_TC 0x02 //[7] PWR_MODE, [6:1] ZG_OFFS_TC, [0] OTP_BNK_VLD +#define MPU6050_RA_X_FINE_GAIN 0x03 //[7:0] X_FINE_GAIN +#define MPU6050_RA_Y_FINE_GAIN 0x04 //[7:0] Y_FINE_GAIN +#define MPU6050_RA_Z_FINE_GAIN 0x05 //[7:0] Z_FINE_GAIN +#define MPU6050_RA_XA_OFFS_H 0x06 //[15:0] XA_OFFS +#define MPU6050_RA_XA_OFFS_L_TC 0x07 +#define MPU6050_RA_YA_OFFS_H 0x08 //[15:0] YA_OFFS +#define MPU6050_RA_YA_OFFS_L_TC 0x09 +#define MPU6050_RA_ZA_OFFS_H 0x0A //[15:0] ZA_OFFS +#define MPU6050_RA_ZA_OFFS_L_TC 0x0B +#define MPU6050_RA_SELF_TEST_X 0x0D //[7:5] XA_TEST[4-2], [4:0] XG_TEST[4-0] +#define MPU6050_RA_SELF_TEST_Y 0x0E //[7:5] YA_TEST[4-2], [4:0] YG_TEST[4-0] +#define MPU6050_RA_SELF_TEST_Z 0x0F //[7:5] ZA_TEST[4-2], [4:0] ZG_TEST[4-0] +#define MPU6050_RA_SELF_TEST_A 0x10 //[5:4] XA_TEST[1-0], [3:2] YA_TEST[1-0], [1:0] ZA_TEST[1-0] +#define MPU6050_RA_XG_OFFS_USRH 0x13 //[15:0] XG_OFFS_USR +#define MPU6050_RA_XG_OFFS_USRL 0x14 +#define MPU6050_RA_YG_OFFS_USRH 0x15 //[15:0] YG_OFFS_USR +#define MPU6050_RA_YG_OFFS_USRL 0x16 +#define MPU6050_RA_ZG_OFFS_USRH 0x17 //[15:0] ZG_OFFS_USR +#define MPU6050_RA_ZG_OFFS_USRL 0x18 +#define MPU6050_RA_SMPLRT_DIV 0x19 +#define MPU6050_RA_CONFIG 0x1A +#define MPU6050_RA_GYRO_CONFIG 0x1B +#define MPU6050_RA_ACCEL_CONFIG 0x1C +#define MPU6050_RA_FF_THR 0x1D +#define MPU6050_RA_FF_DUR 0x1E +#define MPU6050_RA_MOT_THR 0x1F +#define MPU6050_RA_MOT_DUR 0x20 +#define MPU6050_RA_ZRMOT_THR 0x21 +#define MPU6050_RA_ZRMOT_DUR 0x22 +#define MPU6050_RA_FIFO_EN 0x23 +#define MPU6050_RA_I2C_MST_CTRL 0x24 +#define MPU6050_RA_I2C_SLV0_ADDR 0x25 +#define MPU6050_RA_I2C_SLV0_REG 0x26 +#define MPU6050_RA_I2C_SLV0_CTRL 0x27 +#define MPU6050_RA_I2C_SLV1_ADDR 0x28 +#define MPU6050_RA_I2C_SLV1_REG 0x29 +#define MPU6050_RA_I2C_SLV1_CTRL 0x2A +#define MPU6050_RA_I2C_SLV2_ADDR 0x2B +#define MPU6050_RA_I2C_SLV2_REG 0x2C +#define MPU6050_RA_I2C_SLV2_CTRL 0x2D +#define MPU6050_RA_I2C_SLV3_ADDR 0x2E +#define MPU6050_RA_I2C_SLV3_REG 0x2F +#define MPU6050_RA_I2C_SLV3_CTRL 0x30 +#define MPU6050_RA_I2C_SLV4_ADDR 0x31 +#define MPU6050_RA_I2C_SLV4_REG 0x32 +#define MPU6050_RA_I2C_SLV4_DO 0x33 +#define MPU6050_RA_I2C_SLV4_CTRL 0x34 +#define MPU6050_RA_I2C_SLV4_DI 0x35 +#define MPU6050_RA_I2C_MST_STATUS 0x36 +#define MPU6050_RA_INT_PIN_CFG 0x37 +#define MPU6050_RA_INT_ENABLE 0x38 +#define MPU6050_RA_DMP_INT_STATUS 0x39 +#define MPU6050_RA_INT_STATUS 0x3A +#define MPU6050_RA_ACCEL_XOUT_H 0x3B +#define MPU6050_RA_ACCEL_XOUT_L 0x3C +#define MPU6050_RA_ACCEL_YOUT_H 0x3D +#define MPU6050_RA_ACCEL_YOUT_L 0x3E +#define MPU6050_RA_ACCEL_ZOUT_H 0x3F +#define MPU6050_RA_ACCEL_ZOUT_L 0x40 +#define MPU6050_RA_TEMP_OUT_H 0x41 +#define MPU6050_RA_TEMP_OUT_L 0x42 +#define MPU6050_RA_GYRO_XOUT_H 0x43 +#define MPU6050_RA_GYRO_XOUT_L 0x44 +#define MPU6050_RA_GYRO_YOUT_H 0x45 +#define MPU6050_RA_GYRO_YOUT_L 0x46 +#define MPU6050_RA_GYRO_ZOUT_H 0x47 +#define MPU6050_RA_GYRO_ZOUT_L 0x48 +#define MPU6050_RA_EXT_SENS_DATA_00 0x49 +#define MPU6050_RA_EXT_SENS_DATA_01 0x4A +#define MPU6050_RA_EXT_SENS_DATA_02 0x4B +#define MPU6050_RA_EXT_SENS_DATA_03 0x4C +#define MPU6050_RA_EXT_SENS_DATA_04 0x4D +#define MPU6050_RA_EXT_SENS_DATA_05 0x4E +#define MPU6050_RA_EXT_SENS_DATA_06 0x4F +#define MPU6050_RA_EXT_SENS_DATA_07 0x50 +#define MPU6050_RA_EXT_SENS_DATA_08 0x51 +#define MPU6050_RA_EXT_SENS_DATA_09 0x52 +#define MPU6050_RA_EXT_SENS_DATA_10 0x53 +#define MPU6050_RA_EXT_SENS_DATA_11 0x54 +#define MPU6050_RA_EXT_SENS_DATA_12 0x55 +#define MPU6050_RA_EXT_SENS_DATA_13 0x56 +#define MPU6050_RA_EXT_SENS_DATA_14 0x57 +#define MPU6050_RA_EXT_SENS_DATA_15 0x58 +#define MPU6050_RA_EXT_SENS_DATA_16 0x59 +#define MPU6050_RA_EXT_SENS_DATA_17 0x5A +#define MPU6050_RA_EXT_SENS_DATA_18 0x5B +#define MPU6050_RA_EXT_SENS_DATA_19 0x5C +#define MPU6050_RA_EXT_SENS_DATA_20 0x5D +#define MPU6050_RA_EXT_SENS_DATA_21 0x5E +#define MPU6050_RA_EXT_SENS_DATA_22 0x5F +#define MPU6050_RA_EXT_SENS_DATA_23 0x60 +#define MPU6050_RA_MOT_DETECT_STATUS 0x61 +#define MPU6050_RA_I2C_SLV0_DO 0x63 +#define MPU6050_RA_I2C_SLV1_DO 0x64 +#define MPU6050_RA_I2C_SLV2_DO 0x65 +#define MPU6050_RA_I2C_SLV3_DO 0x66 +#define MPU6050_RA_I2C_MST_DELAY_CTRL 0x67 +#define MPU6050_RA_SIGNAL_PATH_RESET 0x68 +#define MPU6050_RA_MOT_DETECT_CTRL 0x69 +#define MPU6050_RA_USER_CTRL 0x6A +#define MPU6050_RA_PWR_MGMT_1 0x6B +#define MPU6050_RA_PWR_MGMT_2 0x6C +#define MPU6050_RA_BANK_SEL 0x6D +#define MPU6050_RA_MEM_START_ADDR 0x6E +#define MPU6050_RA_MEM_R_W 0x6F +#define MPU6050_RA_DMP_CFG_1 0x70 +#define MPU6050_RA_DMP_CFG_2 0x71 +#define MPU6050_RA_FIFO_COUNTH 0x72 +#define MPU6050_RA_FIFO_COUNTL 0x73 +#define MPU6050_RA_FIFO_R_W 0x74 +#define MPU6050_RA_WHO_AM_I 0x75 + +#define MPU6050_SELF_TEST_XA_1_BIT 0x07 +#define MPU6050_SELF_TEST_XA_1_LENGTH 0x03 +#define MPU6050_SELF_TEST_XA_2_BIT 0x05 +#define MPU6050_SELF_TEST_XA_2_LENGTH 0x02 +#define MPU6050_SELF_TEST_YA_1_BIT 0x07 +#define MPU6050_SELF_TEST_YA_1_LENGTH 0x03 +#define MPU6050_SELF_TEST_YA_2_BIT 0x03 +#define MPU6050_SELF_TEST_YA_2_LENGTH 0x02 +#define MPU6050_SELF_TEST_ZA_1_BIT 0x07 +#define MPU6050_SELF_TEST_ZA_1_LENGTH 0x03 +#define MPU6050_SELF_TEST_ZA_2_BIT 0x01 +#define MPU6050_SELF_TEST_ZA_2_LENGTH 0x02 + +#define MPU6050_SELF_TEST_XG_1_BIT 0x04 +#define MPU6050_SELF_TEST_XG_1_LENGTH 0x05 +#define MPU6050_SELF_TEST_YG_1_BIT 0x04 +#define MPU6050_SELF_TEST_YG_1_LENGTH 0x05 +#define MPU6050_SELF_TEST_ZG_1_BIT 0x04 +#define MPU6050_SELF_TEST_ZG_1_LENGTH 0x05 + +#define MPU6050_TC_PWR_MODE_BIT 7 +#define MPU6050_TC_OFFSET_BIT 6 +#define MPU6050_TC_OFFSET_LENGTH 6 +#define MPU6050_TC_OTP_BNK_VLD_BIT 0 + +#define MPU6050_VDDIO_LEVEL_VLOGIC 0 +#define MPU6050_VDDIO_LEVEL_VDD 1 + +#define MPU6050_CFG_EXT_SYNC_SET_BIT 5 +#define MPU6050_CFG_EXT_SYNC_SET_LENGTH 3 +#define MPU6050_CFG_DLPF_CFG_BIT 2 +#define MPU6050_CFG_DLPF_CFG_LENGTH 3 + +#define MPU6050_EXT_SYNC_DISABLED 0x0 +#define MPU6050_EXT_SYNC_TEMP_OUT_L 0x1 +#define MPU6050_EXT_SYNC_GYRO_XOUT_L 0x2 +#define MPU6050_EXT_SYNC_GYRO_YOUT_L 0x3 +#define MPU6050_EXT_SYNC_GYRO_ZOUT_L 0x4 +#define MPU6050_EXT_SYNC_ACCEL_XOUT_L 0x5 +#define MPU6050_EXT_SYNC_ACCEL_YOUT_L 0x6 +#define MPU6050_EXT_SYNC_ACCEL_ZOUT_L 0x7 + +#define MPU6050_DLPF_BW_256 0x00 +#define MPU6050_DLPF_BW_188 0x01 +#define MPU6050_DLPF_BW_98 0x02 +#define MPU6050_DLPF_BW_42 0x03 +#define MPU6050_DLPF_BW_20 0x04 +#define MPU6050_DLPF_BW_10 0x05 +#define MPU6050_DLPF_BW_5 0x06 + +#define MPU6050_GCONFIG_FS_SEL_BIT 4 +#define MPU6050_GCONFIG_FS_SEL_LENGTH 2 + +#define MPU6050_GYRO_FS_250 0x00 +#define MPU6050_GYRO_FS_500 0x01 +#define MPU6050_GYRO_FS_1000 0x02 +#define MPU6050_GYRO_FS_2000 0x03 + +#define MPU6050_ACONFIG_XA_ST_BIT 7 +#define MPU6050_ACONFIG_YA_ST_BIT 6 +#define MPU6050_ACONFIG_ZA_ST_BIT 5 +#define MPU6050_ACONFIG_AFS_SEL_BIT 4 +#define MPU6050_ACONFIG_AFS_SEL_LENGTH 2 +#define MPU6050_ACONFIG_ACCEL_HPF_BIT 2 +#define MPU6050_ACONFIG_ACCEL_HPF_LENGTH 3 + +#define MPU6050_ACCEL_FS_2 0x00 +#define MPU6050_ACCEL_FS_4 0x01 +#define MPU6050_ACCEL_FS_8 0x02 +#define MPU6050_ACCEL_FS_16 0x03 + +#define MPU6050_DHPF_RESET 0x00 +#define MPU6050_DHPF_5 0x01 +#define MPU6050_DHPF_2P5 0x02 +#define MPU6050_DHPF_1P25 0x03 +#define MPU6050_DHPF_0P63 0x04 +#define MPU6050_DHPF_HOLD 0x07 + +#define MPU6050_TEMP_FIFO_EN_BIT 7 +#define MPU6050_XG_FIFO_EN_BIT 6 +#define MPU6050_YG_FIFO_EN_BIT 5 +#define MPU6050_ZG_FIFO_EN_BIT 4 +#define MPU6050_ACCEL_FIFO_EN_BIT 3 +#define MPU6050_SLV2_FIFO_EN_BIT 2 +#define MPU6050_SLV1_FIFO_EN_BIT 1 +#define MPU6050_SLV0_FIFO_EN_BIT 0 + +#define MPU6050_MULT_MST_EN_BIT 7 +#define MPU6050_WAIT_FOR_ES_BIT 6 +#define MPU6050_SLV_3_FIFO_EN_BIT 5 +#define MPU6050_I2C_MST_P_NSR_BIT 4 +#define MPU6050_I2C_MST_CLK_BIT 3 +#define MPU6050_I2C_MST_CLK_LENGTH 4 + +#define MPU6050_CLOCK_DIV_348 0x0 +#define MPU6050_CLOCK_DIV_333 0x1 +#define MPU6050_CLOCK_DIV_320 0x2 +#define MPU6050_CLOCK_DIV_308 0x3 +#define MPU6050_CLOCK_DIV_296 0x4 +#define MPU6050_CLOCK_DIV_286 0x5 +#define MPU6050_CLOCK_DIV_276 0x6 +#define MPU6050_CLOCK_DIV_267 0x7 +#define MPU6050_CLOCK_DIV_258 0x8 +#define MPU6050_CLOCK_DIV_500 0x9 +#define MPU6050_CLOCK_DIV_471 0xA +#define MPU6050_CLOCK_DIV_444 0xB +#define MPU6050_CLOCK_DIV_421 0xC +#define MPU6050_CLOCK_DIV_400 0xD +#define MPU6050_CLOCK_DIV_381 0xE +#define MPU6050_CLOCK_DIV_364 0xF + +#define MPU6050_I2C_SLV_RW_BIT 7 +#define MPU6050_I2C_SLV_ADDR_BIT 6 +#define MPU6050_I2C_SLV_ADDR_LENGTH 7 +#define MPU6050_I2C_SLV_EN_BIT 7 +#define MPU6050_I2C_SLV_BYTE_SW_BIT 6 +#define MPU6050_I2C_SLV_REG_DIS_BIT 5 +#define MPU6050_I2C_SLV_GRP_BIT 4 +#define MPU6050_I2C_SLV_LEN_BIT 3 +#define MPU6050_I2C_SLV_LEN_LENGTH 4 + +#define MPU6050_I2C_SLV4_RW_BIT 7 +#define MPU6050_I2C_SLV4_ADDR_BIT 6 +#define MPU6050_I2C_SLV4_ADDR_LENGTH 7 +#define MPU6050_I2C_SLV4_EN_BIT 7 +#define MPU6050_I2C_SLV4_INT_EN_BIT 6 +#define MPU6050_I2C_SLV4_REG_DIS_BIT 5 +#define MPU6050_I2C_SLV4_MST_DLY_BIT 4 +#define MPU6050_I2C_SLV4_MST_DLY_LENGTH 5 + +#define MPU6050_MST_PASS_THROUGH_BIT 7 +#define MPU6050_MST_I2C_SLV4_DONE_BIT 6 +#define MPU6050_MST_I2C_LOST_ARB_BIT 5 +#define MPU6050_MST_I2C_SLV4_NACK_BIT 4 +#define MPU6050_MST_I2C_SLV3_NACK_BIT 3 +#define MPU6050_MST_I2C_SLV2_NACK_BIT 2 +#define MPU6050_MST_I2C_SLV1_NACK_BIT 1 +#define MPU6050_MST_I2C_SLV0_NACK_BIT 0 + +#define MPU6050_INTCFG_INT_LEVEL_BIT 7 +#define MPU6050_INTCFG_INT_OPEN_BIT 6 +#define MPU6050_INTCFG_LATCH_INT_EN_BIT 5 +#define MPU6050_INTCFG_INT_RD_CLEAR_BIT 4 +#define MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT 3 +#define MPU6050_INTCFG_FSYNC_INT_EN_BIT 2 +#define MPU6050_INTCFG_I2C_BYPASS_EN_BIT 1 +#define MPU6050_INTCFG_CLKOUT_EN_BIT 0 + +#define MPU6050_INTMODE_ACTIVEHIGH 0x00 +#define MPU6050_INTMODE_ACTIVELOW 0x01 + +#define MPU6050_INTDRV_PUSHPULL 0x00 +#define MPU6050_INTDRV_OPENDRAIN 0x01 + +#define MPU6050_INTLATCH_50USPULSE 0x00 +#define MPU6050_INTLATCH_WAITCLEAR 0x01 + +#define MPU6050_INTCLEAR_STATUSREAD 0x00 +#define MPU6050_INTCLEAR_ANYREAD 0x01 + +#define MPU6050_INTERRUPT_FF_BIT 7 +#define MPU6050_INTERRUPT_MOT_BIT 6 +#define MPU6050_INTERRUPT_ZMOT_BIT 5 +#define MPU6050_INTERRUPT_FIFO_OFLOW_BIT 4 +#define MPU6050_INTERRUPT_I2C_MST_INT_BIT 3 +#define MPU6050_INTERRUPT_PLL_RDY_INT_BIT 2 +#define MPU6050_INTERRUPT_DMP_INT_BIT 1 +#define MPU6050_INTERRUPT_DATA_RDY_BIT 0 + +// TODO: figure out what these actually do +// UMPL source code is not very obivous +#define MPU6050_DMPINT_5_BIT 5 +#define MPU6050_DMPINT_4_BIT 4 +#define MPU6050_DMPINT_3_BIT 3 +#define MPU6050_DMPINT_2_BIT 2 +#define MPU6050_DMPINT_1_BIT 1 +#define MPU6050_DMPINT_0_BIT 0 + +#define MPU6050_MOTION_MOT_XNEG_BIT 7 +#define MPU6050_MOTION_MOT_XPOS_BIT 6 +#define MPU6050_MOTION_MOT_YNEG_BIT 5 +#define MPU6050_MOTION_MOT_YPOS_BIT 4 +#define MPU6050_MOTION_MOT_ZNEG_BIT 3 +#define MPU6050_MOTION_MOT_ZPOS_BIT 2 +#define MPU6050_MOTION_MOT_ZRMOT_BIT 0 + +#define MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT 7 +#define MPU6050_DELAYCTRL_I2C_SLV4_DLY_EN_BIT 4 +#define MPU6050_DELAYCTRL_I2C_SLV3_DLY_EN_BIT 3 +#define MPU6050_DELAYCTRL_I2C_SLV2_DLY_EN_BIT 2 +#define MPU6050_DELAYCTRL_I2C_SLV1_DLY_EN_BIT 1 +#define MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT 0 + +#define MPU6050_PATHRESET_GYRO_RESET_BIT 2 +#define MPU6050_PATHRESET_ACCEL_RESET_BIT 1 +#define MPU6050_PATHRESET_TEMP_RESET_BIT 0 + +#define MPU6050_DETECT_ACCEL_ON_DELAY_BIT 5 +#define MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH 2 +#define MPU6050_DETECT_FF_COUNT_BIT 3 +#define MPU6050_DETECT_FF_COUNT_LENGTH 2 +#define MPU6050_DETECT_MOT_COUNT_BIT 1 +#define MPU6050_DETECT_MOT_COUNT_LENGTH 2 + +#define MPU6050_DETECT_DECREMENT_RESET 0x0 +#define MPU6050_DETECT_DECREMENT_1 0x1 +#define MPU6050_DETECT_DECREMENT_2 0x2 +#define MPU6050_DETECT_DECREMENT_4 0x3 + +#define MPU6050_USERCTRL_DMP_EN_BIT 7 +#define MPU6050_USERCTRL_FIFO_EN_BIT 6 +#define MPU6050_USERCTRL_I2C_MST_EN_BIT 5 +#define MPU6050_USERCTRL_I2C_IF_DIS_BIT 4 +#define MPU6050_USERCTRL_DMP_RESET_BIT 3 +#define MPU6050_USERCTRL_FIFO_RESET_BIT 2 +#define MPU6050_USERCTRL_I2C_MST_RESET_BIT 1 +#define MPU6050_USERCTRL_SIG_COND_RESET_BIT 0 + +#define MPU6050_PWR1_DEVICE_RESET_BIT 7 +#define MPU6050_PWR1_SLEEP_BIT 6 +#define MPU6050_PWR1_CYCLE_BIT 5 +#define MPU6050_PWR1_TEMP_DIS_BIT 3 +#define MPU6050_PWR1_CLKSEL_BIT 2 +#define MPU6050_PWR1_CLKSEL_LENGTH 3 + +#define MPU6050_CLOCK_INTERNAL 0x00 +#define MPU6050_CLOCK_PLL_XGYRO 0x01 +#define MPU6050_CLOCK_PLL_YGYRO 0x02 +#define MPU6050_CLOCK_PLL_ZGYRO 0x03 +#define MPU6050_CLOCK_PLL_EXT32K 0x04 +#define MPU6050_CLOCK_PLL_EXT19M 0x05 +#define MPU6050_CLOCK_KEEP_RESET 0x07 + +#define MPU6050_PWR2_LP_WAKE_CTRL_BIT 7 +#define MPU6050_PWR2_LP_WAKE_CTRL_LENGTH 2 +#define MPU6050_PWR2_STBY_XA_BIT 5 +#define MPU6050_PWR2_STBY_YA_BIT 4 +#define MPU6050_PWR2_STBY_ZA_BIT 3 +#define MPU6050_PWR2_STBY_XG_BIT 2 +#define MPU6050_PWR2_STBY_YG_BIT 1 +#define MPU6050_PWR2_STBY_ZG_BIT 0 + +#define MPU6050_WAKE_FREQ_1P25 0x0 +#define MPU6050_WAKE_FREQ_2P5 0x1 +#define MPU6050_WAKE_FREQ_5 0x2 +#define MPU6050_WAKE_FREQ_10 0x3 + +#define MPU6050_BANKSEL_PRFTCH_EN_BIT 6 +#define MPU6050_BANKSEL_CFG_USER_BANK_BIT 5 +#define MPU6050_BANKSEL_MEM_SEL_BIT 4 +#define MPU6050_BANKSEL_MEM_SEL_LENGTH 5 + +#define MPU6050_WHO_AM_I_BIT 6 +#define MPU6050_WHO_AM_I_LENGTH 6 + +#define MPU6050_DMP_MEMORY_BANKS 8 +#define MPU6050_DMP_MEMORY_BANK_SIZE 256 +#define MPU6050_DMP_MEMORY_CHUNK_SIZE 16 + +#define MPU6050_FIFO_DEFAULT_TIMEOUT 11000 + +class MPU6050_Base { + public: + MPU6050_Base(uint8_t address=MPU6050_DEFAULT_ADDRESS, void *wireObj=0); + + void initialize(); + bool testConnection(); + + // AUX_VDDIO register + uint8_t getAuxVDDIOLevel(); + void setAuxVDDIOLevel(uint8_t level); + + // SMPLRT_DIV register + uint8_t getRate(); + void setRate(uint8_t rate); + + // CONFIG register + uint8_t getExternalFrameSync(); + void setExternalFrameSync(uint8_t sync); + uint8_t getDLPFMode(); + void setDLPFMode(uint8_t bandwidth); + + // GYRO_CONFIG register + uint8_t getFullScaleGyroRange(); + void setFullScaleGyroRange(uint8_t range); + + // SELF_TEST registers + uint8_t getAccelXSelfTestFactoryTrim(); + uint8_t getAccelYSelfTestFactoryTrim(); + uint8_t getAccelZSelfTestFactoryTrim(); + + uint8_t getGyroXSelfTestFactoryTrim(); + uint8_t getGyroYSelfTestFactoryTrim(); + uint8_t getGyroZSelfTestFactoryTrim(); + + // ACCEL_CONFIG register + bool getAccelXSelfTest(); + void setAccelXSelfTest(bool enabled); + bool getAccelYSelfTest(); + void setAccelYSelfTest(bool enabled); + bool getAccelZSelfTest(); + void setAccelZSelfTest(bool enabled); + uint8_t getFullScaleAccelRange(); + void setFullScaleAccelRange(uint8_t range); + uint8_t getDHPFMode(); + void setDHPFMode(uint8_t mode); + + // FF_THR register + uint8_t getFreefallDetectionThreshold(); + void setFreefallDetectionThreshold(uint8_t threshold); + + // FF_DUR register + uint8_t getFreefallDetectionDuration(); + void setFreefallDetectionDuration(uint8_t duration); + + // MOT_THR register + uint8_t getMotionDetectionThreshold(); + void setMotionDetectionThreshold(uint8_t threshold); + + // MOT_DUR register + uint8_t getMotionDetectionDuration(); + void setMotionDetectionDuration(uint8_t duration); + + // ZRMOT_THR register + uint8_t getZeroMotionDetectionThreshold(); + void setZeroMotionDetectionThreshold(uint8_t threshold); + + // ZRMOT_DUR register + uint8_t getZeroMotionDetectionDuration(); + void setZeroMotionDetectionDuration(uint8_t duration); + + // FIFO_EN register + bool getTempFIFOEnabled(); + void setTempFIFOEnabled(bool enabled); + bool getXGyroFIFOEnabled(); + void setXGyroFIFOEnabled(bool enabled); + bool getYGyroFIFOEnabled(); + void setYGyroFIFOEnabled(bool enabled); + bool getZGyroFIFOEnabled(); + void setZGyroFIFOEnabled(bool enabled); + bool getAccelFIFOEnabled(); + void setAccelFIFOEnabled(bool enabled); + bool getSlave2FIFOEnabled(); + void setSlave2FIFOEnabled(bool enabled); + bool getSlave1FIFOEnabled(); + void setSlave1FIFOEnabled(bool enabled); + bool getSlave0FIFOEnabled(); + void setSlave0FIFOEnabled(bool enabled); + + // I2C_MST_CTRL register + bool getMultiMasterEnabled(); + void setMultiMasterEnabled(bool enabled); + bool getWaitForExternalSensorEnabled(); + void setWaitForExternalSensorEnabled(bool enabled); + bool getSlave3FIFOEnabled(); + void setSlave3FIFOEnabled(bool enabled); + bool getSlaveReadWriteTransitionEnabled(); + void setSlaveReadWriteTransitionEnabled(bool enabled); + uint8_t getMasterClockSpeed(); + void setMasterClockSpeed(uint8_t speed); + + // I2C_SLV* registers (Slave 0-3) + uint8_t getSlaveAddress(uint8_t num); + void setSlaveAddress(uint8_t num, uint8_t address); + uint8_t getSlaveRegister(uint8_t num); + void setSlaveRegister(uint8_t num, uint8_t reg); + bool getSlaveEnabled(uint8_t num); + void setSlaveEnabled(uint8_t num, bool enabled); + bool getSlaveWordByteSwap(uint8_t num); + void setSlaveWordByteSwap(uint8_t num, bool enabled); + bool getSlaveWriteMode(uint8_t num); + void setSlaveWriteMode(uint8_t num, bool mode); + bool getSlaveWordGroupOffset(uint8_t num); + void setSlaveWordGroupOffset(uint8_t num, bool enabled); + uint8_t getSlaveDataLength(uint8_t num); + void setSlaveDataLength(uint8_t num, uint8_t length); + + // I2C_SLV* registers (Slave 4) + uint8_t getSlave4Address(); + void setSlave4Address(uint8_t address); + uint8_t getSlave4Register(); + void setSlave4Register(uint8_t reg); + void setSlave4OutputByte(uint8_t data); + bool getSlave4Enabled(); + void setSlave4Enabled(bool enabled); + bool getSlave4InterruptEnabled(); + void setSlave4InterruptEnabled(bool enabled); + bool getSlave4WriteMode(); + void setSlave4WriteMode(bool mode); + uint8_t getSlave4MasterDelay(); + void setSlave4MasterDelay(uint8_t delay); + uint8_t getSlate4InputByte(); + + // I2C_MST_STATUS register + bool getPassthroughStatus(); + bool getSlave4IsDone(); + bool getLostArbitration(); + bool getSlave4Nack(); + bool getSlave3Nack(); + bool getSlave2Nack(); + bool getSlave1Nack(); + bool getSlave0Nack(); + + // INT_PIN_CFG register + bool getInterruptMode(); + void setInterruptMode(bool mode); + bool getInterruptDrive(); + void setInterruptDrive(bool drive); + bool getInterruptLatch(); + void setInterruptLatch(bool latch); + bool getInterruptLatchClear(); + void setInterruptLatchClear(bool clear); + bool getFSyncInterruptLevel(); + void setFSyncInterruptLevel(bool level); + bool getFSyncInterruptEnabled(); + void setFSyncInterruptEnabled(bool enabled); + bool getI2CBypassEnabled(); + void setI2CBypassEnabled(bool enabled); + bool getClockOutputEnabled(); + void setClockOutputEnabled(bool enabled); + + // INT_ENABLE register + uint8_t getIntEnabled(); + void setIntEnabled(uint8_t enabled); + bool getIntFreefallEnabled(); + void setIntFreefallEnabled(bool enabled); + bool getIntMotionEnabled(); + void setIntMotionEnabled(bool enabled); + bool getIntZeroMotionEnabled(); + void setIntZeroMotionEnabled(bool enabled); + bool getIntFIFOBufferOverflowEnabled(); + void setIntFIFOBufferOverflowEnabled(bool enabled); + bool getIntI2CMasterEnabled(); + void setIntI2CMasterEnabled(bool enabled); + bool getIntDataReadyEnabled(); + void setIntDataReadyEnabled(bool enabled); + + // INT_STATUS register + uint8_t getIntStatus(); + bool getIntFreefallStatus(); + bool getIntMotionStatus(); + bool getIntZeroMotionStatus(); + bool getIntFIFOBufferOverflowStatus(); + bool getIntI2CMasterStatus(); + bool getIntDataReadyStatus(); + + // ACCEL_*OUT_* registers + void getMotion9(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz, int16_t* mx, int16_t* my, int16_t* mz); + void getMotion6(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz); + void getAcceleration(int16_t* x, int16_t* y, int16_t* z); + int16_t getAccelerationX(); + int16_t getAccelerationY(); + int16_t getAccelerationZ(); + + // TEMP_OUT_* registers + int16_t getTemperature(); + + // GYRO_*OUT_* registers + void getRotation(int16_t* x, int16_t* y, int16_t* z); + int16_t getRotationX(); + int16_t getRotationY(); + int16_t getRotationZ(); + + // EXT_SENS_DATA_* registers + uint8_t getExternalSensorByte(int position); + uint16_t getExternalSensorWord(int position); + uint32_t getExternalSensorDWord(int position); + + // MOT_DETECT_STATUS register + uint8_t getMotionStatus(); + bool getXNegMotionDetected(); + bool getXPosMotionDetected(); + bool getYNegMotionDetected(); + bool getYPosMotionDetected(); + bool getZNegMotionDetected(); + bool getZPosMotionDetected(); + bool getZeroMotionDetected(); + + // I2C_SLV*_DO register + void setSlaveOutputByte(uint8_t num, uint8_t data); + + // I2C_MST_DELAY_CTRL register + bool getExternalShadowDelayEnabled(); + void setExternalShadowDelayEnabled(bool enabled); + bool getSlaveDelayEnabled(uint8_t num); + void setSlaveDelayEnabled(uint8_t num, bool enabled); + + // SIGNAL_PATH_RESET register + void resetGyroscopePath(); + void resetAccelerometerPath(); + void resetTemperaturePath(); + + // MOT_DETECT_CTRL register + uint8_t getAccelerometerPowerOnDelay(); + void setAccelerometerPowerOnDelay(uint8_t delay); + uint8_t getFreefallDetectionCounterDecrement(); + void setFreefallDetectionCounterDecrement(uint8_t decrement); + uint8_t getMotionDetectionCounterDecrement(); + void setMotionDetectionCounterDecrement(uint8_t decrement); + + // USER_CTRL register + bool getFIFOEnabled(); + void setFIFOEnabled(bool enabled); + bool getI2CMasterModeEnabled(); + void setI2CMasterModeEnabled(bool enabled); + void switchSPIEnabled(bool enabled); + void resetFIFO(); + void resetI2CMaster(); + void resetSensors(); + + // PWR_MGMT_1 register + void reset(); + bool getSleepEnabled(); + void setSleepEnabled(bool enabled); + bool getWakeCycleEnabled(); + void setWakeCycleEnabled(bool enabled); + bool getTempSensorEnabled(); + void setTempSensorEnabled(bool enabled); + uint8_t getClockSource(); + void setClockSource(uint8_t source); + + // PWR_MGMT_2 register + uint8_t getWakeFrequency(); + void setWakeFrequency(uint8_t frequency); + bool getStandbyXAccelEnabled(); + void setStandbyXAccelEnabled(bool enabled); + bool getStandbyYAccelEnabled(); + void setStandbyYAccelEnabled(bool enabled); + bool getStandbyZAccelEnabled(); + void setStandbyZAccelEnabled(bool enabled); + bool getStandbyXGyroEnabled(); + void setStandbyXGyroEnabled(bool enabled); + bool getStandbyYGyroEnabled(); + void setStandbyYGyroEnabled(bool enabled); + bool getStandbyZGyroEnabled(); + void setStandbyZGyroEnabled(bool enabled); + + // FIFO_COUNT_* registers + uint16_t getFIFOCount(); + + // FIFO_R_W register + uint8_t getFIFOByte(); + int8_t GetCurrentFIFOPacket(uint8_t *data, uint8_t length); + void setFIFOByte(uint8_t data); + void getFIFOBytes(uint8_t *data, uint8_t length); + void setFIFOTimeout(uint32_t fifoTimeout); + uint32_t getFIFOTimeout(); + + // WHO_AM_I register + uint8_t getDeviceID(); + void setDeviceID(uint8_t id); + + // ======== UNDOCUMENTED/DMP REGISTERS/METHODS ======== + + // XG_OFFS_TC register + uint8_t getOTPBankValid(); + void setOTPBankValid(bool enabled); + int8_t getXGyroOffsetTC(); + void setXGyroOffsetTC(int8_t offset); + + // YG_OFFS_TC register + int8_t getYGyroOffsetTC(); + void setYGyroOffsetTC(int8_t offset); + + // ZG_OFFS_TC register + int8_t getZGyroOffsetTC(); + void setZGyroOffsetTC(int8_t offset); + + // X_FINE_GAIN register + int8_t getXFineGain(); + void setXFineGain(int8_t gain); + + // Y_FINE_GAIN register + int8_t getYFineGain(); + void setYFineGain(int8_t gain); + + // Z_FINE_GAIN register + int8_t getZFineGain(); + void setZFineGain(int8_t gain); + + // XA_OFFS_* registers + int16_t getXAccelOffset(); + void setXAccelOffset(int16_t offset); + + // YA_OFFS_* register + int16_t getYAccelOffset(); + void setYAccelOffset(int16_t offset); + + // ZA_OFFS_* register + int16_t getZAccelOffset(); + void setZAccelOffset(int16_t offset); + + // XG_OFFS_USR* registers + int16_t getXGyroOffset(); + void setXGyroOffset(int16_t offset); + + // YG_OFFS_USR* register + int16_t getYGyroOffset(); + void setYGyroOffset(int16_t offset); + + // ZG_OFFS_USR* register + int16_t getZGyroOffset(); + void setZGyroOffset(int16_t offset); + + // INT_ENABLE register (DMP functions) + bool getIntPLLReadyEnabled(); + void setIntPLLReadyEnabled(bool enabled); + bool getIntDMPEnabled(); + void setIntDMPEnabled(bool enabled); + + // DMP_INT_STATUS + bool getDMPInt5Status(); + bool getDMPInt4Status(); + bool getDMPInt3Status(); + bool getDMPInt2Status(); + bool getDMPInt1Status(); + bool getDMPInt0Status(); + + // INT_STATUS register (DMP functions) + bool getIntPLLReadyStatus(); + bool getIntDMPStatus(); + + // USER_CTRL register (DMP functions) + bool getDMPEnabled(); + void setDMPEnabled(bool enabled); + void resetDMP(); + + // BANK_SEL register + void setMemoryBank(uint8_t bank, bool prefetchEnabled=false, bool userBank=false); + + // MEM_START_ADDR register + void setMemoryStartAddress(uint8_t address); + + // MEM_R_W register + uint8_t readMemoryByte(); + void writeMemoryByte(uint8_t data); + void readMemoryBlock(uint8_t *data, uint16_t dataSize, uint8_t bank=0, uint8_t address=0); + bool writeMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank=0, uint8_t address=0, bool verify=true, bool useProgMem=false); + bool writeProgMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank=0, uint8_t address=0, bool verify=true); + + bool writeDMPConfigurationSet(const uint8_t *data, uint16_t dataSize, bool useProgMem=false); + bool writeProgDMPConfigurationSet(const uint8_t *data, uint16_t dataSize); + + // DMP_CFG_1 register + uint8_t getDMPConfig1(); + void setDMPConfig1(uint8_t config); + + // DMP_CFG_2 register + uint8_t getDMPConfig2(); + void setDMPConfig2(uint8_t config); + + // Calibration Routines + void CalibrateGyro(uint8_t Loops = 15); // Fine tune after setting offsets with less Loops. + void CalibrateAccel(uint8_t Loops = 15);// Fine tune after setting offsets with less Loops. + void PID(uint8_t ReadAddress, float kP,float kI, uint8_t Loops); // Does the math + void PrintActiveOffsets(); // See the results of the Calibration + int16_t * GetActiveOffsets(); + + protected: + uint8_t devAddr; + void *wireObj; + uint8_t buffer[14]; + uint32_t fifoTimeout = MPU6050_FIFO_DEFAULT_TIMEOUT; + + private: + int16_t offsets[6]; +}; + +#ifndef I2CDEVLIB_MPU6050_TYPEDEF +#define I2CDEVLIB_MPU6050_TYPEDEF +typedef MPU6050_Base MPU6050; +#endif + +#endif /* _MPU6050_H_ */ diff --git a/LinuxI2CDev/MPU6050/MPU6050_6Axis_MotionApps20.cpp b/LinuxI2CDev/MPU6050/MPU6050_6Axis_MotionApps20.cpp new file mode 100644 index 00000000..3a896745 --- /dev/null +++ b/LinuxI2CDev/MPU6050/MPU6050_6Axis_MotionApps20.cpp @@ -0,0 +1,616 @@ +// I2Cdev library collection - MPU6050 I2C device class, 6-axis MotionApps 2.0 implementation +// Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00) +// 5/20/2013 by Jeff Rowberg +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// 2021/09/27 - split implementations out of header files, finally +// 2019/07/08 - merged all DMP Firmware configuration items into the dmpMemory array +// - Simplified dmpInitialize() to accomidate the dmpmemory array alterations + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2021 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +// MotionApps 2.0 DMP implementation, built using the MPU-6050EVB evaluation board +#define MPU6050_INCLUDE_DMP_MOTIONAPPS20 + +#include "MPU6050_6Axis_MotionApps20.h" + +// Tom Carpenter's conditional PROGMEM code +// http://forum.arduino.cc/index.php?topic=129407.0 +#ifdef __AVR__ + #include +#elif defined(ESP32) + #include +#else + // Teensy 3.0 library conditional PROGMEM code from Paul Stoffregen + #ifndef __PGMSPACE_H_ + #define __PGMSPACE_H_ 1 + #include + + #define PROGMEM + #define PGM_P const char * + #define PSTR(str) (str) + #define F(x) x + + typedef void prog_void; + typedef char prog_char; + typedef unsigned char prog_uchar; + typedef int8_t prog_int8_t; + typedef uint8_t prog_uint8_t; + typedef int16_t prog_int16_t; + typedef uint16_t prog_uint16_t; + typedef int32_t prog_int32_t; + typedef uint32_t prog_uint32_t; + + #define strcpy_P(dest, src) strcpy((dest), (src)) + #define strcat_P(dest, src) strcat((dest), (src)) + #define strcmp_P(a, b) strcmp((a), (b)) + + #define pgm_read_byte(addr) (*(const unsigned char *)(addr)) + #define pgm_read_word(addr) (*(const unsigned short *)(addr)) + #define pgm_read_dword(addr) (*(const unsigned long *)(addr)) + #define pgm_read_float(addr) (*(const float *)(addr)) + + #define pgm_read_byte_near(addr) pgm_read_byte(addr) + #define pgm_read_word_near(addr) pgm_read_word(addr) + #define pgm_read_dword_near(addr) pgm_read_dword(addr) + #define pgm_read_float_near(addr) pgm_read_float(addr) + #define pgm_read_byte_far(addr) pgm_read_byte(addr) + #define pgm_read_word_far(addr) pgm_read_word(addr) + #define pgm_read_dword_far(addr) pgm_read_dword(addr) + #define pgm_read_float_far(addr) pgm_read_float(addr) + #endif +#endif + +/* Source is from the InvenSense MotionApps v2 demo code. Original source is + * unavailable, unless you happen to be amazing as decompiling binary by + * hand (in which case, please contact me, and I'm totally serious). + * + * Also, I'd like to offer many, many thanks to Noah Zerkin for all of the + * DMP reverse-engineering he did to help make this bit of wizardry + * possible. + */ + +// NOTE! Enabling DEBUG adds about 3.3kB to the flash program size. +// Debug output is now working even on ATMega328P MCUs (e.g. Arduino Uno) +// after moving string constants to flash memory storage using the F() +// compiler macro (Arduino IDE 1.0+ required). + +//#define DEBUG +#ifdef DEBUG + #define DEBUG_PRINT(x) Serial.print(x) + #define DEBUG_PRINTF(x, y) Serial.print(x, y) + #define DEBUG_PRINTLN(x) Serial.println(x) + #define DEBUG_PRINTLNF(x, y) Serial.println(x, y) +#else + #define DEBUG_PRINT(x) + #define DEBUG_PRINTF(x, y) + #define DEBUG_PRINTLN(x) + #define DEBUG_PRINTLNF(x, y) +#endif + +#define MPU6050_DMP_CODE_SIZE 1929 // dmpMemory[] +#define MPU6050_DMP_CONFIG_SIZE 192 // dmpConfig[] +#define MPU6050_DMP_UPDATES_SIZE 47 // dmpUpdates[] + +/* ================================================================================================ * + | Default MotionApps v2.0 42-byte FIFO packet structure: | + | | + | [QUAT W][ ][QUAT X][ ][QUAT Y][ ][QUAT Z][ ][GYRO X][ ][GYRO Y][ ] | + | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | + | | + | [GYRO Z][ ][ACC X ][ ][ACC Y ][ ][ACC Z ][ ][ ] | + | 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | + * ================================================================================================ */ + +// this block of memory gets written to the MPU on start-up, and it seems +// to be volatile memory, so it has to be done each time (it only takes ~1 +// second though) + +// I Only Changed this by applying all the configuration data and capturing it before startup: +// *** this is a capture of the DMP Firmware after all the messy changes were made so we can just load it +static const unsigned char dmpMemory[MPU6050_DMP_CODE_SIZE] PROGMEM = { + /* bank # 0 */ + 0xFB, 0x00, 0x00, 0x3E, 0x00, 0x0B, 0x00, 0x36, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x65, 0x00, 0x54, 0xFF, 0xEF, 0x00, 0x00, 0xFA, 0x80, 0x00, 0x0B, 0x12, 0x82, 0x00, 0x01, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x28, 0x00, 0x00, 0xFF, 0xFF, 0x45, 0x81, 0xFF, 0xFF, 0xFA, 0x72, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0xE8, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x7F, 0xFF, 0xFF, 0xFE, 0x80, 0x01, + 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0xCB, 0x47, 0xA2, 0x20, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, + 0x41, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x2A, 0x00, 0x00, 0x16, 0x55, 0x00, 0x00, 0x21, 0x82, + 0xFD, 0x87, 0x26, 0x50, 0xFD, 0x80, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x05, 0x80, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x6F, 0x00, 0x02, 0x65, 0x32, 0x00, 0x00, 0x5E, 0xC0, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFB, 0x8C, 0x6F, 0x5D, 0xFD, 0x5D, 0x08, 0xD9, 0x00, 0x7C, 0x73, 0x3B, 0x00, 0x6C, 0x12, 0xCC, + 0x32, 0x00, 0x13, 0x9D, 0x32, 0x00, 0xD0, 0xD6, 0x32, 0x00, 0x08, 0x00, 0x40, 0x00, 0x01, 0xF4, + 0xFF, 0xE6, 0x80, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0xD6, 0x00, 0x00, 0x27, 0x10, + /* bank # 1 */ + 0xFB, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFA, 0x36, 0xFF, 0xBC, 0x30, 0x8E, 0x00, 0x05, 0xFB, 0xF0, 0xFF, 0xD9, 0x5B, 0xC8, + 0xFF, 0xD0, 0x9A, 0xBE, 0x00, 0x00, 0x10, 0xA9, 0xFF, 0xF4, 0x1E, 0xB2, 0x00, 0xCE, 0xBB, 0xF7, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x0C, + 0xFF, 0xC2, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0xCF, 0x80, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x14, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x09, 0x23, 0xA1, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x3F, 0x68, 0xB6, 0x79, 0x35, 0x28, 0xBC, 0xC6, 0x7E, 0xD1, 0x6C, + 0x80, 0x00, 0xFF, 0xFF, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB2, 0x6A, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, + 0x00, 0x00, 0x25, 0x4D, 0x00, 0x2F, 0x70, 0x6D, 0x00, 0x00, 0x05, 0xAE, 0x00, 0x0C, 0x02, 0xD0, + /* bank # 2 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x54, 0xFF, 0xEF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x44, 0x00, 0x01, 0x00, 0x05, 0x8B, 0xC1, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0xFF, 0xEF, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* bank # 3 */ + 0xD8, 0xDC, 0xBA, 0xA2, 0xF1, 0xDE, 0xB2, 0xB8, 0xB4, 0xA8, 0x81, 0x91, 0xF7, 0x4A, 0x90, 0x7F, + 0x91, 0x6A, 0xF3, 0xF9, 0xDB, 0xA8, 0xF9, 0xB0, 0xBA, 0xA0, 0x80, 0xF2, 0xCE, 0x81, 0xF3, 0xC2, + 0xF1, 0xC1, 0xF2, 0xC3, 0xF3, 0xCC, 0xA2, 0xB2, 0x80, 0xF1, 0xC6, 0xD8, 0x80, 0xBA, 0xA7, 0xDF, + 0xDF, 0xDF, 0xF2, 0xA7, 0xC3, 0xCB, 0xC5, 0xB6, 0xF0, 0x87, 0xA2, 0x94, 0x24, 0x48, 0x70, 0x3C, + 0x95, 0x40, 0x68, 0x34, 0x58, 0x9B, 0x78, 0xA2, 0xF1, 0x83, 0x92, 0x2D, 0x55, 0x7D, 0xD8, 0xB1, + 0xB4, 0xB8, 0xA1, 0xD0, 0x91, 0x80, 0xF2, 0x70, 0xF3, 0x70, 0xF2, 0x7C, 0x80, 0xA8, 0xF1, 0x01, + 0xB0, 0x98, 0x87, 0xD9, 0x43, 0xD8, 0x86, 0xC9, 0x88, 0xBA, 0xA1, 0xF2, 0x0E, 0xB8, 0x97, 0x80, + 0xF1, 0xA9, 0xDF, 0xDF, 0xDF, 0xAA, 0xDF, 0xDF, 0xDF, 0xF2, 0xAA, 0x4C, 0xCD, 0x6C, 0xA9, 0x0C, + 0xC9, 0x2C, 0x97, 0x97, 0x97, 0x97, 0xF1, 0xA9, 0x89, 0x26, 0x46, 0x66, 0xB0, 0xB4, 0xBA, 0x80, + 0xAC, 0xDE, 0xF2, 0xCA, 0xF1, 0xB2, 0x8C, 0x02, 0xA9, 0xB6, 0x98, 0x00, 0x89, 0x0E, 0x16, 0x1E, + 0xB8, 0xA9, 0xB4, 0x99, 0x2C, 0x54, 0x7C, 0xB0, 0x8A, 0xA8, 0x96, 0x36, 0x56, 0x76, 0xF1, 0xB9, + 0xAF, 0xB4, 0xB0, 0x83, 0xC0, 0xB8, 0xA8, 0x97, 0x11, 0xB1, 0x8F, 0x98, 0xB9, 0xAF, 0xF0, 0x24, + 0x08, 0x44, 0x10, 0x64, 0x18, 0xF1, 0xA3, 0x29, 0x55, 0x7D, 0xAF, 0x83, 0xB5, 0x93, 0xAF, 0xF0, + 0x00, 0x28, 0x50, 0xF1, 0xA3, 0x86, 0x9F, 0x61, 0xA6, 0xDA, 0xDE, 0xDF, 0xD9, 0xFA, 0xA3, 0x86, + 0x96, 0xDB, 0x31, 0xA6, 0xD9, 0xF8, 0xDF, 0xBA, 0xA6, 0x8F, 0xC2, 0xC5, 0xC7, 0xB2, 0x8C, 0xC1, + 0xB8, 0xA2, 0xDF, 0xDF, 0xDF, 0xA3, 0xDF, 0xDF, 0xDF, 0xD8, 0xD8, 0xF1, 0xB8, 0xA8, 0xB2, 0x86, + /* bank # 4 */ + 0xB4, 0x98, 0x0D, 0x35, 0x5D, 0xB8, 0xAA, 0x98, 0xB0, 0x87, 0x2D, 0x35, 0x3D, 0xB2, 0xB6, 0xBA, + 0xAF, 0x8C, 0x96, 0x19, 0x8F, 0x9F, 0xA7, 0x0E, 0x16, 0x1E, 0xB4, 0x9A, 0xB8, 0xAA, 0x87, 0x2C, + 0x54, 0x7C, 0xB9, 0xA3, 0xDE, 0xDF, 0xDF, 0xA3, 0xB1, 0x80, 0xF2, 0xC4, 0xCD, 0xC9, 0xF1, 0xB8, + 0xA9, 0xB4, 0x99, 0x83, 0x0D, 0x35, 0x5D, 0x89, 0xB9, 0xA3, 0x2D, 0x55, 0x7D, 0xB5, 0x93, 0xA3, + 0x0E, 0x16, 0x1E, 0xA9, 0x2C, 0x54, 0x7C, 0xB8, 0xB4, 0xB0, 0xF1, 0x97, 0x83, 0xA8, 0x11, 0x84, + 0xA5, 0x09, 0x98, 0xA3, 0x83, 0xF0, 0xDA, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0xD8, 0xF1, 0xA5, + 0x29, 0x55, 0x7D, 0xA5, 0x85, 0x95, 0x02, 0x1A, 0x2E, 0x3A, 0x56, 0x5A, 0x40, 0x48, 0xF9, 0xF3, + 0xA3, 0xD9, 0xF8, 0xF0, 0x98, 0x83, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0x97, 0x82, 0xA8, 0xF1, + 0x11, 0xF0, 0x98, 0xA2, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0xDA, 0xF3, 0xDE, 0xD8, 0x83, 0xA5, + 0x94, 0x01, 0xD9, 0xA3, 0x02, 0xF1, 0xA2, 0xC3, 0xC5, 0xC7, 0xD8, 0xF1, 0x84, 0x92, 0xA2, 0x4D, + 0xDA, 0x2A, 0xD8, 0x48, 0x69, 0xD9, 0x2A, 0xD8, 0x68, 0x55, 0xDA, 0x32, 0xD8, 0x50, 0x71, 0xD9, + 0x32, 0xD8, 0x70, 0x5D, 0xDA, 0x3A, 0xD8, 0x58, 0x79, 0xD9, 0x3A, 0xD8, 0x78, 0x93, 0xA3, 0x4D, + 0xDA, 0x2A, 0xD8, 0x48, 0x69, 0xD9, 0x2A, 0xD8, 0x68, 0x55, 0xDA, 0x32, 0xD8, 0x50, 0x71, 0xD9, + 0x32, 0xD8, 0x70, 0x5D, 0xDA, 0x3A, 0xD8, 0x58, 0x79, 0xD9, 0x3A, 0xD8, 0x78, 0xA8, 0x8A, 0x9A, + 0xF0, 0x28, 0x50, 0x78, 0x9E, 0xF3, 0x88, 0x18, 0xF1, 0x9F, 0x1D, 0x98, 0xA8, 0xD9, 0x08, 0xD8, + 0xC8, 0x9F, 0x12, 0x9E, 0xF3, 0x15, 0xA8, 0xDA, 0x12, 0x10, 0xD8, 0xF1, 0xAF, 0xC8, 0x97, 0x87, + /* bank # 5 */ + 0x34, 0xB5, 0xB9, 0x94, 0xA4, 0x21, 0xF3, 0xD9, 0x22, 0xD8, 0xF2, 0x2D, 0xF3, 0xD9, 0x2A, 0xD8, + 0xF2, 0x35, 0xF3, 0xD9, 0x32, 0xD8, 0x81, 0xA4, 0x60, 0x60, 0x61, 0xD9, 0x61, 0xD8, 0x6C, 0x68, + 0x69, 0xD9, 0x69, 0xD8, 0x74, 0x70, 0x71, 0xD9, 0x71, 0xD8, 0xB1, 0xA3, 0x84, 0x19, 0x3D, 0x5D, + 0xA3, 0x83, 0x1A, 0x3E, 0x5E, 0x93, 0x10, 0x30, 0x81, 0x10, 0x11, 0xB8, 0xB0, 0xAF, 0x8F, 0x94, + 0xF2, 0xDA, 0x3E, 0xD8, 0xB4, 0x9A, 0xA8, 0x87, 0x29, 0xDA, 0xF8, 0xD8, 0x87, 0x9A, 0x35, 0xDA, + 0xF8, 0xD8, 0x87, 0x9A, 0x3D, 0xDA, 0xF8, 0xD8, 0xB1, 0xB9, 0xA4, 0x98, 0x85, 0x02, 0x2E, 0x56, + 0xA5, 0x81, 0x00, 0x0C, 0x14, 0xA3, 0x97, 0xB0, 0x8A, 0xF1, 0x2D, 0xD9, 0x28, 0xD8, 0x4D, 0xD9, + 0x48, 0xD8, 0x6D, 0xD9, 0x68, 0xD8, 0xB1, 0x84, 0x0D, 0xDA, 0x0E, 0xD8, 0xA3, 0x29, 0x83, 0xDA, + 0x2C, 0x0E, 0xD8, 0xA3, 0x84, 0x49, 0x83, 0xDA, 0x2C, 0x4C, 0x0E, 0xD8, 0xB8, 0xB0, 0xA8, 0x8A, + 0x9A, 0xF5, 0x20, 0xAA, 0xDA, 0xDF, 0xD8, 0xA8, 0x40, 0xAA, 0xD0, 0xDA, 0xDE, 0xD8, 0xA8, 0x60, + 0xAA, 0xDA, 0xD0, 0xDF, 0xD8, 0xF1, 0x97, 0x86, 0xA8, 0x31, 0x9B, 0x06, 0x99, 0x07, 0xAB, 0x97, + 0x28, 0x88, 0x9B, 0xF0, 0x0C, 0x20, 0x14, 0x40, 0xB8, 0xB0, 0xB4, 0xA8, 0x8C, 0x9C, 0xF0, 0x04, + 0x28, 0x51, 0x79, 0x1D, 0x30, 0x14, 0x38, 0xB2, 0x82, 0xAB, 0xD0, 0x98, 0x2C, 0x50, 0x50, 0x78, + 0x78, 0x9B, 0xF1, 0x1A, 0xB0, 0xF0, 0x8A, 0x9C, 0xA8, 0x29, 0x51, 0x79, 0x8B, 0x29, 0x51, 0x79, + 0x8A, 0x24, 0x70, 0x59, 0x8B, 0x20, 0x58, 0x71, 0x8A, 0x44, 0x69, 0x38, 0x8B, 0x39, 0x40, 0x68, + 0x8A, 0x64, 0x48, 0x31, 0x8B, 0x30, 0x49, 0x60, 0xA5, 0x88, 0x20, 0x09, 0x71, 0x58, 0x44, 0x68, + /* bank # 6 */ + 0x11, 0x39, 0x64, 0x49, 0x30, 0x19, 0xF1, 0xAC, 0x00, 0x2C, 0x54, 0x7C, 0xF0, 0x8C, 0xA8, 0x04, + 0x28, 0x50, 0x78, 0xF1, 0x88, 0x97, 0x26, 0xA8, 0x59, 0x98, 0xAC, 0x8C, 0x02, 0x26, 0x46, 0x66, + 0xF0, 0x89, 0x9C, 0xA8, 0x29, 0x51, 0x79, 0x24, 0x70, 0x59, 0x44, 0x69, 0x38, 0x64, 0x48, 0x31, + 0xA9, 0x88, 0x09, 0x20, 0x59, 0x70, 0xAB, 0x11, 0x38, 0x40, 0x69, 0xA8, 0x19, 0x31, 0x48, 0x60, + 0x8C, 0xA8, 0x3C, 0x41, 0x5C, 0x20, 0x7C, 0x00, 0xF1, 0x87, 0x98, 0x19, 0x86, 0xA8, 0x6E, 0x76, + 0x7E, 0xA9, 0x99, 0x88, 0x2D, 0x55, 0x7D, 0x9E, 0xB9, 0xA3, 0x8A, 0x22, 0x8A, 0x6E, 0x8A, 0x56, + 0x8A, 0x5E, 0x9F, 0xB1, 0x83, 0x06, 0x26, 0x46, 0x66, 0x0E, 0x2E, 0x4E, 0x6E, 0x9D, 0xB8, 0xAD, + 0x00, 0x2C, 0x54, 0x7C, 0xF2, 0xB1, 0x8C, 0xB4, 0x99, 0xB9, 0xA3, 0x2D, 0x55, 0x7D, 0x81, 0x91, + 0xAC, 0x38, 0xAD, 0x3A, 0xB5, 0x83, 0x91, 0xAC, 0x2D, 0xD9, 0x28, 0xD8, 0x4D, 0xD9, 0x48, 0xD8, + 0x6D, 0xD9, 0x68, 0xD8, 0x8C, 0x9D, 0xAE, 0x29, 0xD9, 0x04, 0xAE, 0xD8, 0x51, 0xD9, 0x04, 0xAE, + 0xD8, 0x79, 0xD9, 0x04, 0xD8, 0x81, 0xF3, 0x9D, 0xAD, 0x00, 0x8D, 0xAE, 0x19, 0x81, 0xAD, 0xD9, + 0x01, 0xD8, 0xF2, 0xAE, 0xDA, 0x26, 0xD8, 0x8E, 0x91, 0x29, 0x83, 0xA7, 0xD9, 0xAD, 0xAD, 0xAD, + 0xAD, 0xF3, 0x2A, 0xD8, 0xD8, 0xF1, 0xB0, 0xAC, 0x89, 0x91, 0x3E, 0x5E, 0x76, 0xF3, 0xAC, 0x2E, + 0x2E, 0xF1, 0xB1, 0x8C, 0x5A, 0x9C, 0xAC, 0x2C, 0x28, 0x28, 0x28, 0x9C, 0xAC, 0x30, 0x18, 0xA8, + 0x98, 0x81, 0x28, 0x34, 0x3C, 0x97, 0x24, 0xA7, 0x28, 0x34, 0x3C, 0x9C, 0x24, 0xF2, 0xB0, 0x89, + 0xAC, 0x91, 0x2C, 0x4C, 0x6C, 0x8A, 0x9B, 0x2D, 0xD9, 0xD8, 0xD8, 0x51, 0xD9, 0xD8, 0xD8, 0x79, + /* bank # 7 */ + 0xD9, 0xD8, 0xD8, 0xF1, 0x9E, 0x88, 0xA3, 0x31, 0xDA, 0xD8, 0xD8, 0x91, 0x2D, 0xD9, 0x28, 0xD8, + 0x4D, 0xD9, 0x48, 0xD8, 0x6D, 0xD9, 0x68, 0xD8, 0xB1, 0x83, 0x93, 0x35, 0x3D, 0x80, 0x25, 0xDA, + 0xD8, 0xD8, 0x85, 0x69, 0xDA, 0xD8, 0xD8, 0xB4, 0x93, 0x81, 0xA3, 0x28, 0x34, 0x3C, 0xF3, 0xAB, + 0x8B, 0xF8, 0xA3, 0x91, 0xB6, 0x09, 0xB4, 0xD9, 0xAB, 0xDE, 0xFA, 0xB0, 0x87, 0x9C, 0xB9, 0xA3, + 0xDD, 0xF1, 0x20, 0x28, 0x30, 0x38, 0x9A, 0xF1, 0x28, 0x30, 0x38, 0x9D, 0xF1, 0xA3, 0xA3, 0xA3, + 0xA3, 0xF2, 0xA3, 0xB4, 0x90, 0x80, 0xF2, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, + 0xA3, 0xB2, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xB0, 0x87, 0xB5, 0x99, 0xF1, 0x28, 0x30, 0x38, + 0x98, 0xF1, 0xA3, 0xA3, 0xA3, 0xA3, 0x97, 0xA3, 0xA3, 0xA3, 0xA3, 0xF3, 0x9B, 0xA3, 0x30, 0xDC, + 0xB9, 0xA7, 0xF1, 0x26, 0x26, 0x26, 0xFE, 0xD8, 0xFF, + +}; + +#ifndef MPU6050_DMP_FIFO_RATE_DIVISOR +#define MPU6050_DMP_FIFO_RATE_DIVISOR 0x01 // The New instance of the Firmware has this as the default +#endif + +// I Simplified this: +uint8_t MPU6050_6Axis_MotionApps20::dmpInitialize() { + // reset device + DEBUG_PRINTLN(F("\n\nResetting MPU6050...")); + reset(); + delay(30); // wait after reset + + // enable sleep mode and wake cycle + /*Serial.println(F("Enabling sleep mode...")); + setSleepEnabled(true); + Serial.println(F("Enabling wake cycle...")); + setWakeCycleEnabled(true);*/ + + // disable sleep mode + setSleepEnabled(false); + + // get MPU hardware revision + setMemoryBank(0x10, true, true); + setMemoryStartAddress(0x06); + DEBUG_PRINTLN(F("Checking hardware revision...")); + DEBUG_PRINT(F("Revision @ user[16][6] = ")); + DEBUG_PRINTLN(readMemoryByte()); + DEBUG_PRINTLN(F("Resetting memory bank selection to 0...")); + setMemoryBank(0, false, false); + + // check OTP bank valid + DEBUG_PRINTLN(F("Reading OTP bank valid flag...")); + DEBUG_PRINT(F("OTP bank is ")); + DEBUG_PRINTLN(getOTPBankValid() ? F("valid!") : F("invalid!")); + + // setup weird slave stuff (?) + DEBUG_PRINTLN(F("Setting slave 0 address to 0x7F...")); + setSlaveAddress(0, 0x7F); + DEBUG_PRINTLN(F("Disabling I2C Master mode...")); + setI2CMasterModeEnabled(false); + DEBUG_PRINTLN(F("Setting slave 0 address to 0x68 (self)...")); + setSlaveAddress(0, 0x68); + DEBUG_PRINTLN(F("Resetting I2C Master control...")); + resetI2CMaster(); + delay(20); + DEBUG_PRINTLN(F("Setting clock source to Z Gyro...")); + setClockSource(MPU6050_CLOCK_PLL_ZGYRO); + + DEBUG_PRINTLN(F("Setting DMP and FIFO_OFLOW interrupts enabled...")); + setIntEnabled(1<= dmpGetFIFOPacketSize(); +} + +// uint8_t MPU6050_6Axis_MotionApps20::dmpSetFIFORate(uint8_t fifoRate); +// uint8_t MPU6050_6Axis_MotionApps20::dmpGetFIFORate(); +// uint8_t MPU6050_6Axis_MotionApps20::dmpGetSampleStepSizeMS(); +// uint8_t MPU6050_6Axis_MotionApps20::dmpGetSampleFrequency(); +// int32_t MPU6050_6Axis_MotionApps20::dmpDecodeTemperature(int8_t tempReg); + +//uint8_t MPU6050_6Axis_MotionApps20::dmpRegisterFIFORateProcess(inv_obj_func func, int16_t priority); +//uint8_t MPU6050_6Axis_MotionApps20::dmpUnregisterFIFORateProcess(inv_obj_func func); +//uint8_t MPU6050_6Axis_MotionApps20::dmpRunFIFORateProcesses(); + +// uint8_t MPU6050_6Axis_MotionApps20::dmpSendQuaternion(uint_fast16_t accuracy); +// uint8_t MPU6050_6Axis_MotionApps20::dmpSendGyro(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050_6Axis_MotionApps20::dmpSendAccel(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050_6Axis_MotionApps20::dmpSendLinearAccel(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050_6Axis_MotionApps20::dmpSendLinearAccelInWorld(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050_6Axis_MotionApps20::dmpSendControlData(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050_6Axis_MotionApps20::dmpSendSensorData(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050_6Axis_MotionApps20::dmpSendExternalSensorData(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050_6Axis_MotionApps20::dmpSendGravity(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050_6Axis_MotionApps20::dmpSendPacketNumber(uint_fast16_t accuracy); +// uint8_t MPU6050_6Axis_MotionApps20::dmpSendQuantizedAccel(uint_fast16_t elements, uint_fast16_t accuracy); +// uint8_t MPU6050_6Axis_MotionApps20::dmpSendEIS(uint_fast16_t elements, uint_fast16_t accuracy); + +uint8_t MPU6050_6Axis_MotionApps20::dmpGetAccel(int32_t *data, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + data[0] = (((uint32_t)packet[28] << 24) | ((uint32_t)packet[29] << 16) | ((uint32_t)packet[30] << 8) | packet[31]); + data[1] = (((uint32_t)packet[32] << 24) | ((uint32_t)packet[33] << 16) | ((uint32_t)packet[34] << 8) | packet[35]); + data[2] = (((uint32_t)packet[36] << 24) | ((uint32_t)packet[37] << 16) | ((uint32_t)packet[38] << 8) | packet[39]); + return 0; +} +uint8_t MPU6050_6Axis_MotionApps20::dmpGetAccel(int16_t *data, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + data[0] = (packet[28] << 8) | packet[29]; + data[1] = (packet[32] << 8) | packet[33]; + data[2] = (packet[36] << 8) | packet[37]; + return 0; +} +uint8_t MPU6050_6Axis_MotionApps20::dmpGetAccel(VectorInt16 *v, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + v -> x = (packet[28] << 8) | packet[29]; + v -> y = (packet[32] << 8) | packet[33]; + v -> z = (packet[36] << 8) | packet[37]; + return 0; +} +uint8_t MPU6050_6Axis_MotionApps20::dmpGetQuaternion(int32_t *data, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + data[0] = (((uint32_t)packet[0] << 24) | ((uint32_t)packet[1] << 16) | ((uint32_t)packet[2] << 8) | packet[3]); + data[1] = (((uint32_t)packet[4] << 24) | ((uint32_t)packet[5] << 16) | ((uint32_t)packet[6] << 8) | packet[7]); + data[2] = (((uint32_t)packet[8] << 24) | ((uint32_t)packet[9] << 16) | ((uint32_t)packet[10] << 8) | packet[11]); + data[3] = (((uint32_t)packet[12] << 24) | ((uint32_t)packet[13] << 16) | ((uint32_t)packet[14] << 8) | packet[15]); + return 0; +} +uint8_t MPU6050_6Axis_MotionApps20::dmpGetQuaternion(int16_t *data, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + data[0] = ((packet[0] << 8) | packet[1]); + data[1] = ((packet[4] << 8) | packet[5]); + data[2] = ((packet[8] << 8) | packet[9]); + data[3] = ((packet[12] << 8) | packet[13]); + return 0; +} +uint8_t MPU6050_6Axis_MotionApps20::dmpGetQuaternion(Quaternion *q, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + int16_t qI[4]; + uint8_t status = dmpGetQuaternion(qI, packet); + if (status == 0) { + q -> w = (float)qI[0] / 16384.0f; + q -> x = (float)qI[1] / 16384.0f; + q -> y = (float)qI[2] / 16384.0f; + q -> z = (float)qI[3] / 16384.0f; + return 0; + } + return status; // int16 return value, indicates error if this line is reached +} +// uint8_t MPU6050_6Axis_MotionApps20::dmpGet6AxisQuaternion(long *data, const uint8_t* packet); +// uint8_t MPU6050_6Axis_MotionApps20::dmpGetRelativeQuaternion(long *data, const uint8_t* packet); +uint8_t MPU6050_6Axis_MotionApps20::dmpGetGyro(int32_t *data, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + data[0] = (((uint32_t)packet[16] << 24) | ((uint32_t)packet[17] << 16) | ((uint32_t)packet[18] << 8) | packet[19]); + data[1] = (((uint32_t)packet[20] << 24) | ((uint32_t)packet[21] << 16) | ((uint32_t)packet[22] << 8) | packet[23]); + data[2] = (((uint32_t)packet[24] << 24) | ((uint32_t)packet[25] << 16) | ((uint32_t)packet[26] << 8) | packet[27]); + return 0; +} +uint8_t MPU6050_6Axis_MotionApps20::dmpGetGyro(int16_t *data, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + data[0] = (packet[16] << 8) | packet[17]; + data[1] = (packet[20] << 8) | packet[21]; + data[2] = (packet[24] << 8) | packet[25]; + return 0; +} +uint8_t MPU6050_6Axis_MotionApps20::dmpGetGyro(VectorInt16 *v, const uint8_t* packet) { + // TODO: accommodate different arrangements of sent data (ONLY default supported now) + if (packet == 0) packet = dmpPacketBuffer; + v -> x = (packet[16] << 8) | packet[17]; + v -> y = (packet[20] << 8) | packet[21]; + v -> z = (packet[24] << 8) | packet[25]; + return 0; +} +// uint8_t MPU6050_6Axis_MotionApps20::dmpSetLinearAccelFilterCoefficient(float coef); +// uint8_t MPU6050_6Axis_MotionApps20::dmpGetLinearAccel(long *data, const uint8_t* packet); +uint8_t MPU6050_6Axis_MotionApps20::dmpGetLinearAccel(VectorInt16 *v, VectorInt16 *vRaw, VectorFloat *gravity) { + // get rid of the gravity component (+1g = +8192 in standard DMP FIFO packet, sensitivity is 2g) + v -> x = vRaw -> x - gravity -> x*8192; + v -> y = vRaw -> y - gravity -> y*8192; + v -> z = vRaw -> z - gravity -> z*8192; + return 0; +} +// uint8_t MPU6050_6Axis_MotionApps20::dmpGetLinearAccelInWorld(long *data, const uint8_t* packet); +uint8_t MPU6050_6Axis_MotionApps20::dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Quaternion *q) { + // rotate measured 3D acceleration vector into original state + // frame of reference based on orientation quaternion + memcpy(v, vReal, sizeof(VectorInt16)); + v -> rotate(q); + return 0; +} +// uint8_t MPU6050_6Axis_MotionApps20::dmpGetGyroAndAccelSensor(long *data, const uint8_t* packet); +// uint8_t MPU6050_6Axis_MotionApps20::dmpGetGyroSensor(long *data, const uint8_t* packet); +// uint8_t MPU6050_6Axis_MotionApps20::dmpGetControlData(long *data, const uint8_t* packet); +// uint8_t MPU6050_6Axis_MotionApps20::dmpGetTemperature(long *data, const uint8_t* packet); +// uint8_t MPU6050_6Axis_MotionApps20::dmpGetGravity(long *data, const uint8_t* packet); +uint8_t MPU6050_6Axis_MotionApps20::dmpGetGravity(int16_t *data, const uint8_t* packet) { + /* +1g corresponds to +8192, sensitivity is 2g. */ + int16_t qI[4]; + uint8_t status = dmpGetQuaternion(qI, packet); + data[0] = ((int32_t)qI[1] * qI[3] - (int32_t)qI[0] * qI[2]) / 16384; + data[1] = ((int32_t)qI[0] * qI[1] + (int32_t)qI[2] * qI[3]) / 16384; + data[2] = ((int32_t)qI[0] * qI[0] - (int32_t)qI[1] * qI[1] + - (int32_t)qI[2] * qI[2] + (int32_t)qI[3] * qI[3]) / (int32_t)(2 * 16384L); + return status; +} + +uint8_t MPU6050_6Axis_MotionApps20::dmpGetGravity(VectorFloat *v, Quaternion *q) { + v -> x = 2 * (q -> x*q -> z - q -> w*q -> y); + v -> y = 2 * (q -> w*q -> x + q -> y*q -> z); + v -> z = q -> w*q -> w - q -> x*q -> x - q -> y*q -> y + q -> z*q -> z; + return 0; +} +// uint8_t MPU6050_6Axis_MotionApps20::dmpGetUnquantizedAccel(long *data, const uint8_t* packet); +// uint8_t MPU6050_6Axis_MotionApps20::dmpGetQuantizedAccel(long *data, const uint8_t* packet); +// uint8_t MPU6050_6Axis_MotionApps20::dmpGetExternalSensorData(long *data, int size, const uint8_t* packet); +// uint8_t MPU6050_6Axis_MotionApps20::dmpGetEIS(long *data, const uint8_t* packet); + +uint8_t MPU6050_6Axis_MotionApps20::dmpGetEuler(float *data, Quaternion *q) { + data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1); // psi + data[1] = -asin(2*q -> x*q -> z + 2*q -> w*q -> y); // theta + data[2] = atan2(2*q -> y*q -> z - 2*q -> w*q -> x, 2*q -> w*q -> w + 2*q -> z*q -> z - 1); // phi + return 0; +} + +#ifdef USE_OLD_DMPGETYAWPITCHROLL +uint8_t MPU6050_6Axis_MotionApps20::dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity) { + // yaw: (about Z axis) + data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1); + // pitch: (nose up/down, about Y axis) + data[1] = atan(gravity -> x / sqrt(gravity -> y*gravity -> y + gravity -> z*gravity -> z)); + // roll: (tilt left/right, about X axis) + data[2] = atan(gravity -> y / sqrt(gravity -> x*gravity -> x + gravity -> z*gravity -> z)); + return 0; +} +#else +uint8_t MPU6050_6Axis_MotionApps20::dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity) { + // yaw: (about Z axis) + data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1); + // pitch: (nose up/down, about Y axis) + data[1] = atan2(gravity -> x , sqrt(gravity -> y*gravity -> y + gravity -> z*gravity -> z)); + // roll: (tilt left/right, about X axis) + data[2] = atan2(gravity -> y , gravity -> z); + if (gravity -> z < 0) { + if(data[1] > 0) { + data[1] = PI - data[1]; + } else { + data[1] = -PI - data[1]; + } + } + return 0; +} +#endif + +// uint8_t MPU6050_6Axis_MotionApps20::dmpGetAccelFloat(float *data, const uint8_t* packet); +// uint8_t MPU6050_6Axis_MotionApps20::dmpGetQuaternionFloat(float *data, const uint8_t* packet); + +uint8_t MPU6050_6Axis_MotionApps20::dmpProcessFIFOPacket(const unsigned char *dmpData) { + (void)dmpData; // unused parameter + /*for (uint8_t k = 0; k < dmpPacketSize; k++) { + if (dmpData[k] < 0x10) Serial.print("0"); + Serial.print(dmpData[k], HEX); + Serial.print(" "); + } + Serial.print("\n");*/ + //Serial.println((uint16_t)dmpPacketBuffer); + return 0; +} +uint8_t MPU6050_6Axis_MotionApps20::dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *processed) { + uint8_t status; + uint8_t buf[dmpPacketSize]; + for (uint8_t i = 0; i < numPackets; i++) { + // read packet from FIFO + getFIFOBytes(buf, dmpPacketSize); + + // process packet + if ((status = dmpProcessFIFOPacket(buf)) > 0) return status; + + // increment external process count variable, if supplied + if (processed != 0) (*processed)++; + } + return 0; +} + +// uint8_t MPU6050_6Axis_MotionApps20::dmpSetFIFOProcessedCallback(void (*func) (void)); + +// uint8_t MPU6050_6Axis_MotionApps20::dmpInitFIFOParam(); +// uint8_t MPU6050_6Axis_MotionApps20::dmpCloseFIFO(); +// uint8_t MPU6050_6Axis_MotionApps20::dmpSetGyroDataSource(uint_fast8_t source); +// uint8_t MPU6050_6Axis_MotionApps20::dmpDecodeQuantizedAccel(); +// uint32_t MPU6050_6Axis_MotionApps20::dmpGetGyroSumOfSquare(); +// uint32_t MPU6050_6Axis_MotionApps20::dmpGetAccelSumOfSquare(); +// void MPU6050_6Axis_MotionApps20::dmpOverrideQuaternion(long *q); +uint16_t MPU6050_6Axis_MotionApps20::dmpGetFIFOPacketSize() { + return dmpPacketSize; +} + + + +uint8_t MPU6050_6Axis_MotionApps20::dmpGetCurrentFIFOPacket(uint8_t *data) { // overflow proof + return(GetCurrentFIFOPacket(data, dmpPacketSize)); +} diff --git a/LinuxI2CDev/MPU6050/MPU6050_6Axis_MotionApps20.h b/LinuxI2CDev/MPU6050/MPU6050_6Axis_MotionApps20.h new file mode 100644 index 00000000..0dc9379e --- /dev/null +++ b/LinuxI2CDev/MPU6050/MPU6050_6Axis_MotionApps20.h @@ -0,0 +1,153 @@ +// I2Cdev library collection - MPU6050 I2C device class +// Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00) +// 10/3/2011 by Jeff Rowberg +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// 2021/09/27 - split implementations out of header files, finally +// ... - ongoing debug release + +// NOTE: THIS IS ONLY A PARIAL RELEASE. THIS DEVICE CLASS IS CURRENTLY UNDERGOING ACTIVE +// DEVELOPMENT AND IS STILL MISSING SOME IMPORTANT FEATURES. PLEASE KEEP THIS IN MIND IF +// YOU DECIDE TO USE THIS PARTICULAR CODE FOR ANYTHING. + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2012 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#ifndef _MPU6050_6AXIS_MOTIONAPPS20_H_ +#define _MPU6050_6AXIS_MOTIONAPPS20_H_ + +// take ownership of the "MPU6050" typedef +#define I2CDEVLIB_MPU6050_TYPEDEF + +#include "MPU6050.h" + +class MPU6050_6Axis_MotionApps20 : public MPU6050_Base { + public: + MPU6050_6Axis_MotionApps20(uint8_t address=MPU6050_DEFAULT_ADDRESS, void *wireObj=0) : MPU6050_Base(address, wireObj) { } + + uint8_t dmpInitialize(); + bool dmpPacketAvailable(); + + uint8_t dmpSetFIFORate(uint8_t fifoRate); + uint8_t dmpGetFIFORate(); + uint8_t dmpGetSampleStepSizeMS(); + uint8_t dmpGetSampleFrequency(); + int32_t dmpDecodeTemperature(int8_t tempReg); + + // Register callbacks after a packet of FIFO data is processed + //uint8_t dmpRegisterFIFORateProcess(inv_obj_func func, int16_t priority); + //uint8_t dmpUnregisterFIFORateProcess(inv_obj_func func); + uint8_t dmpRunFIFORateProcesses(); + + // Setup FIFO for various output + uint8_t dmpSendQuaternion(uint_fast16_t accuracy); + uint8_t dmpSendGyro(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendAccel(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendLinearAccel(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendLinearAccelInWorld(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendControlData(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendSensorData(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendExternalSensorData(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendGravity(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendPacketNumber(uint_fast16_t accuracy); + uint8_t dmpSendQuantizedAccel(uint_fast16_t elements, uint_fast16_t accuracy); + uint8_t dmpSendEIS(uint_fast16_t elements, uint_fast16_t accuracy); + + // Get Fixed Point data from FIFO + uint8_t dmpGetAccel(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetAccel(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetAccel(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetQuaternion(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetQuaternion(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetQuaternion(Quaternion *q, const uint8_t* packet=0); + uint8_t dmpGet6AxisQuaternion(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGet6AxisQuaternion(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGet6AxisQuaternion(Quaternion *q, const uint8_t* packet=0); + uint8_t dmpGetRelativeQuaternion(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetRelativeQuaternion(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetRelativeQuaternion(Quaternion *data, const uint8_t* packet=0); + uint8_t dmpGetGyro(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyro(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyro(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpSetLinearAccelFilterCoefficient(float coef); + uint8_t dmpGetLinearAccel(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetLinearAccel(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetLinearAccel(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetLinearAccel(VectorInt16 *v, VectorInt16 *vRaw, VectorFloat *gravity); + uint8_t dmpGetLinearAccelInWorld(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetLinearAccelInWorld(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetLinearAccelInWorld(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Quaternion *q); + uint8_t dmpGetGyroAndAccelSensor(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyroAndAccelSensor(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyroAndAccelSensor(VectorInt16 *g, VectorInt16 *a, const uint8_t* packet=0); + uint8_t dmpGetGyroSensor(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyroSensor(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetGyroSensor(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetControlData(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetTemperature(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetGravity(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetGravity(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetGravity(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetGravity(VectorFloat *v, Quaternion *q); + uint8_t dmpGetUnquantizedAccel(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetUnquantizedAccel(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetUnquantizedAccel(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetQuantizedAccel(int32_t *data, const uint8_t* packet=0); + uint8_t dmpGetQuantizedAccel(int16_t *data, const uint8_t* packet=0); + uint8_t dmpGetQuantizedAccel(VectorInt16 *v, const uint8_t* packet=0); + uint8_t dmpGetExternalSensorData(int32_t *data, uint16_t size, const uint8_t* packet=0); + uint8_t dmpGetEIS(int32_t *data, const uint8_t* packet=0); + + uint8_t dmpGetEuler(float *data, Quaternion *q); + uint8_t dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity); + + // Get Floating Point data from FIFO + uint8_t dmpGetAccelFloat(float *data, const uint8_t* packet=0); + uint8_t dmpGetQuaternionFloat(float *data, const uint8_t* packet=0); + + uint8_t dmpProcessFIFOPacket(const unsigned char *dmpData); + uint8_t dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *processed=NULL); + + uint8_t dmpSetFIFOProcessedCallback(void (*func) (void)); + + uint8_t dmpInitFIFOParam(); + uint8_t dmpCloseFIFO(); + uint8_t dmpSetGyroDataSource(uint8_t source); + uint8_t dmpDecodeQuantizedAccel(); + uint32_t dmpGetGyroSumOfSquare(); + uint32_t dmpGetAccelSumOfSquare(); + void dmpOverrideQuaternion(long *q); + uint16_t dmpGetFIFOPacketSize(); + uint8_t dmpGetCurrentFIFOPacket(uint8_t *data); // overflow proof + + private: + uint8_t *dmpPacketBuffer; + uint16_t dmpPacketSize; +}; + +typedef MPU6050_6Axis_MotionApps20 MPU6050; + +#endif /* _MPU6050_6AXIS_MOTIONAPPS20_H_ */ diff --git a/LinuxI2CDev/MPU6050/helper_3dmath.h b/LinuxI2CDev/MPU6050/helper_3dmath.h new file mode 100644 index 00000000..9ed260ec --- /dev/null +++ b/LinuxI2CDev/MPU6050/helper_3dmath.h @@ -0,0 +1,216 @@ +// I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class, 3D math helper +// 6/5/2012 by Jeff Rowberg +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// 2012-06-05 - add 3D math helper file to DMP6 example sketch + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2012 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#ifndef _HELPER_3DMATH_H_ +#define _HELPER_3DMATH_H_ + +class Quaternion { + public: + float w; + float x; + float y; + float z; + + Quaternion() { + w = 1.0f; + x = 0.0f; + y = 0.0f; + z = 0.0f; + } + + Quaternion(float nw, float nx, float ny, float nz) { + w = nw; + x = nx; + y = ny; + z = nz; + } + + Quaternion getProduct(Quaternion q) { + // Quaternion multiplication is defined by: + // (Q1 * Q2).w = (w1w2 - x1x2 - y1y2 - z1z2) + // (Q1 * Q2).x = (w1x2 + x1w2 + y1z2 - z1y2) + // (Q1 * Q2).y = (w1y2 - x1z2 + y1w2 + z1x2) + // (Q1 * Q2).z = (w1z2 + x1y2 - y1x2 + z1w2 + return Quaternion( + w*q.w - x*q.x - y*q.y - z*q.z, // new w + w*q.x + x*q.w + y*q.z - z*q.y, // new x + w*q.y - x*q.z + y*q.w + z*q.x, // new y + w*q.z + x*q.y - y*q.x + z*q.w); // new z + } + + Quaternion getConjugate() { + return Quaternion(w, -x, -y, -z); + } + + float getMagnitude() { + return sqrt(w*w + x*x + y*y + z*z); + } + + void normalize() { + float m = getMagnitude(); + w /= m; + x /= m; + y /= m; + z /= m; + } + + Quaternion getNormalized() { + Quaternion r(w, x, y, z); + r.normalize(); + return r; + } +}; + +class VectorInt16 { + public: + int16_t x; + int16_t y; + int16_t z; + + VectorInt16() { + x = 0; + y = 0; + z = 0; + } + + VectorInt16(int16_t nx, int16_t ny, int16_t nz) { + x = nx; + y = ny; + z = nz; + } + + float getMagnitude() { + return sqrt(x*x + y*y + z*z); + } + + void normalize() { + float m = getMagnitude(); + x /= m; + y /= m; + z /= m; + } + + VectorInt16 getNormalized() { + VectorInt16 r(x, y, z); + r.normalize(); + return r; + } + + void rotate(Quaternion *q) { + // http://www.cprogramming.com/tutorial/3d/quaternions.html + // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/transforms/index.htm + // http://content.gpwiki.org/index.php/OpenGL:Tutorials:Using_Quaternions_to_represent_rotation + // ^ or: http://webcache.googleusercontent.com/search?q=cache:xgJAp3bDNhQJ:content.gpwiki.org/index.php/OpenGL:Tutorials:Using_Quaternions_to_represent_rotation&hl=en&gl=us&strip=1 + + // P_out = q * P_in * conj(q) + // - P_out is the output vector + // - q is the orientation quaternion + // - P_in is the input vector (a*aReal) + // - conj(q) is the conjugate of the orientation quaternion (q=[w,x,y,z], q*=[w,-x,-y,-z]) + Quaternion p(0, x, y, z); + + // quaternion multiplication: q * p, stored back in p + p = q -> getProduct(p); + + // quaternion multiplication: p * conj(q), stored back in p + p = p.getProduct(q -> getConjugate()); + + // p quaternion is now [0, x', y', z'] + x = p.x; + y = p.y; + z = p.z; + } + + VectorInt16 getRotated(Quaternion *q) { + VectorInt16 r(x, y, z); + r.rotate(q); + return r; + } +}; + +class VectorFloat { + public: + float x; + float y; + float z; + + VectorFloat() { + x = 0; + y = 0; + z = 0; + } + + VectorFloat(float nx, float ny, float nz) { + x = nx; + y = ny; + z = nz; + } + + float getMagnitude() { + return sqrt(x*x + y*y + z*z); + } + + void normalize() { + float m = getMagnitude(); + x /= m; + y /= m; + z /= m; + } + + VectorFloat getNormalized() { + VectorFloat r(x, y, z); + r.normalize(); + return r; + } + + void rotate(Quaternion *q) { + Quaternion p(0, x, y, z); + + // quaternion multiplication: q * p, stored back in p + p = q -> getProduct(p); + + // quaternion multiplication: p * conj(q), stored back in p + p = p.getProduct(q -> getConjugate()); + + // p quaternion is now [0, x', y', z'] + x = p.x; + y = p.y; + z = p.z; + } + + VectorFloat getRotated(Quaternion *q) { + VectorFloat r(x, y, z); + r.rotate(q); + return r; + } +}; + +#endif /* _HELPER_3DMATH_H_ */ \ No newline at end of file From 0a2db6ec10774ca4bb96131bf298cdf3d13df2bf Mon Sep 17 00:00:00 2001 From: Hananja from Raspberry Pi Zero 2 W Date: Thu, 1 Feb 2024 09:32:43 +0100 Subject: [PATCH 330/335] Modify for Linux --- LinuxI2CDev/MPU6050/MPU6050.cpp | 50 ++++--- .../MPU6050/MPU6050_6Axis_MotionApps20.cpp | 137 ++++++------------ LinuxI2CDev/MPU6050/helper_3dmath.h | 4 +- 3 files changed, 78 insertions(+), 113 deletions(-) diff --git a/LinuxI2CDev/MPU6050/MPU6050.cpp b/LinuxI2CDev/MPU6050/MPU6050.cpp index ae145004..bb9548aa 100644 --- a/LinuxI2CDev/MPU6050/MPU6050.cpp +++ b/LinuxI2CDev/MPU6050/MPU6050.cpp @@ -37,6 +37,12 @@ THE SOFTWARE. */ #include "MPU6050.h" +#include +#include +#include +#include +#include +#include /** Specific address constructor. * @param address I2C address, uses default I2C address if none is specified @@ -2762,6 +2768,14 @@ void MPU6050_Base::setFIFOTimeout(uint32_t fifoTimeout) { this->fifoTimeout = fifoTimeout; } +/** Replacement for Arduino micros(). + * @return Number of microseconds since process start + */ +static uint32_t micros() { + struct timespec ts; + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts); + return ts.tv_sec * 1000000 + ts.tv_nsec / 1000; +} /** Get latest byte from FIFO buffer no matter how much time has passed. * === GetCurrentFIFOPacket === * ================================================================ @@ -3118,7 +3132,7 @@ bool MPU6050_Base::writeMemoryBlock(const uint8_t *data, uint16_t dataSize, uint if (useProgMem) { // write the chunk of data as specified - for (j = 0; j < chunkSize; j++) progBuffer[j] = pgm_read_byte(data + i + j); + for (j = 0; j < chunkSize; j++) progBuffer[j] = *(data + i + j); } else { // write the chunk of data as specified progBuffer = (uint8_t *)data + i; @@ -3188,9 +3202,9 @@ bool MPU6050_Base::writeDMPConfigurationSet(const uint8_t *data, uint16_t dataSi uint8_t bank, offset, length; for (i = 0; i < dataSize;) { if (useProgMem) { - bank = pgm_read_byte(data + i++); - offset = pgm_read_byte(data + i++); - length = pgm_read_byte(data + i++); + bank = *(data + i++); + offset = *(data + i++); + length = *(data + i++); } else { bank = data[i++]; offset = data[i++]; @@ -3208,7 +3222,7 @@ bool MPU6050_Base::writeDMPConfigurationSet(const uint8_t *data, uint16_t dataSi Serial.println(length);*/ if (useProgMem) { if (sizeof(progBuffer) < length) progBuffer = (uint8_t *)realloc(progBuffer, length); - for (j = 0; j < length; j++) progBuffer[j] = pgm_read_byte(data + i + j); + for (j = 0; j < length; j++) progBuffer[j] = *(data + i + j); } else { progBuffer = (uint8_t *)data + i; } @@ -3221,7 +3235,7 @@ bool MPU6050_Base::writeDMPConfigurationSet(const uint8_t *data, uint16_t dataSi // behavior only, and exactly why (or even whether) it has to be here // is anybody's guess for now. if (useProgMem) { - special = pgm_read_byte(data + i++); + special = *(data + i++); } else { special = data[i++]; } @@ -3275,7 +3289,12 @@ void MPU6050_Base::setDMPConfig2(uint8_t config) { I2Cdev::writeByte(devAddr, MPU6050_RA_DMP_CFG_2, config, wireObj); } - +/* Replacement for Arduino map() + * @see https://www.arduino.cc/reference/en/language/functions/math/map/ + */ +long map(long x, long in_min, long in_max, long out_min, long out_max) { + return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; +} //*************************************************************************************** //********************** Calibration Routines ********************** //*************************************************************************************** @@ -3319,7 +3338,6 @@ void MPU6050_Base::PID(uint8_t ReadAddress, float kP,float kI, uint8_t Loops){ uint32_t eSum; uint16_t gravity = 8192; // prevent uninitialized compiler warning if (ReadAddress == 0x3B) gravity = 16384 >> getFullScaleAccelRange(); - Serial.write('>'); for (int i = 0; i < 3; i++) { I2Cdev::readWords(devAddr, SaveAddress + (i * shift), 1, (uint16_t *)&Data, I2Cdev::readTimeout, wireObj); // reads 1 or more 16 bit integers (Word) Reading = Data; @@ -3350,13 +3368,11 @@ void MPU6050_Base::PID(uint8_t ReadAddress, float kP,float kI, uint8_t Loops){ } if((c == 99) && eSum > 1000){ // Error is still to great to continue c = 0; - Serial.write('*'); } if((eSum * ((ReadAddress == 0x3B)?.05: 1)) < 5) eSample++; // Successfully found offsets prepare to advance if((eSum < 100) && (c > 10) && (eSample >= 10)) break; // Advance to next Loop - delay(1); + usleep(1000); } - Serial.write('.'); kP *= .75; kI *= .75; for (int i = 0; i < 3; i++){ @@ -3386,12 +3402,12 @@ int16_t * MPU6050_Base::GetActiveOffsets() { void MPU6050_Base::PrintActiveOffsets() { GetActiveOffsets(); // A_OFFSET_H_READ_A_OFFS(Data); - Serial.print((float)offsets[0], 5); Serial.print(",\t"); - Serial.print((float)offsets[1], 5); Serial.print(",\t"); - Serial.print((float)offsets[2], 5); Serial.print(",\t"); + fprintf(stderr, "%.5f,\t", (float)offsets[0]); + fprintf(stderr, "%.5f,\t", (float)offsets[1]); + fprintf(stderr, "%.5f,\t", (float)offsets[2]); // XG_OFFSET_H_READ_OFFS_USR(Data); - Serial.print((float)offsets[3], 5); Serial.print(",\t"); - Serial.print((float)offsets[4], 5); Serial.print(",\t"); - Serial.print((float)offsets[5], 5); Serial.print("\n\n"); + fprintf(stderr, "%.5f,\t", (float)offsets[3]); + fprintf(stderr, "%.5f,\t", (float)offsets[4]); + fprintf(stderr, "%.5f\n\n", (float)offsets[5]); } diff --git a/LinuxI2CDev/MPU6050/MPU6050_6Axis_MotionApps20.cpp b/LinuxI2CDev/MPU6050/MPU6050_6Axis_MotionApps20.cpp index 3a896745..32e7bc46 100644 --- a/LinuxI2CDev/MPU6050/MPU6050_6Axis_MotionApps20.cpp +++ b/LinuxI2CDev/MPU6050/MPU6050_6Axis_MotionApps20.cpp @@ -36,53 +36,10 @@ THE SOFTWARE. #define MPU6050_INCLUDE_DMP_MOTIONAPPS20 #include "MPU6050_6Axis_MotionApps20.h" - -// Tom Carpenter's conditional PROGMEM code -// http://forum.arduino.cc/index.php?topic=129407.0 -#ifdef __AVR__ - #include -#elif defined(ESP32) - #include -#else - // Teensy 3.0 library conditional PROGMEM code from Paul Stoffregen - #ifndef __PGMSPACE_H_ - #define __PGMSPACE_H_ 1 - #include - - #define PROGMEM - #define PGM_P const char * - #define PSTR(str) (str) - #define F(x) x - - typedef void prog_void; - typedef char prog_char; - typedef unsigned char prog_uchar; - typedef int8_t prog_int8_t; - typedef uint8_t prog_uint8_t; - typedef int16_t prog_int16_t; - typedef uint16_t prog_uint16_t; - typedef int32_t prog_int32_t; - typedef uint32_t prog_uint32_t; - - #define strcpy_P(dest, src) strcpy((dest), (src)) - #define strcat_P(dest, src) strcat((dest), (src)) - #define strcmp_P(a, b) strcmp((a), (b)) - - #define pgm_read_byte(addr) (*(const unsigned char *)(addr)) - #define pgm_read_word(addr) (*(const unsigned short *)(addr)) - #define pgm_read_dword(addr) (*(const unsigned long *)(addr)) - #define pgm_read_float(addr) (*(const float *)(addr)) - - #define pgm_read_byte_near(addr) pgm_read_byte(addr) - #define pgm_read_word_near(addr) pgm_read_word(addr) - #define pgm_read_dword_near(addr) pgm_read_dword(addr) - #define pgm_read_float_near(addr) pgm_read_float(addr) - #define pgm_read_byte_far(addr) pgm_read_byte(addr) - #define pgm_read_word_far(addr) pgm_read_word(addr) - #define pgm_read_dword_far(addr) pgm_read_dword(addr) - #define pgm_read_float_far(addr) pgm_read_float(addr) - #endif -#endif +#include +#include +#include +#include /* Source is from the InvenSense MotionApps v2 demo code. Original source is * unavailable, unless you happen to be amazing as decompiling binary by @@ -100,15 +57,9 @@ THE SOFTWARE. //#define DEBUG #ifdef DEBUG - #define DEBUG_PRINT(x) Serial.print(x) - #define DEBUG_PRINTF(x, y) Serial.print(x, y) - #define DEBUG_PRINTLN(x) Serial.println(x) - #define DEBUG_PRINTLNF(x, y) Serial.println(x, y) + #define DEBUG_PRINTF(...) fprintf(stderr, __VA_ARGS__) #else - #define DEBUG_PRINT(x) - #define DEBUG_PRINTF(x, y) - #define DEBUG_PRINTLN(x) - #define DEBUG_PRINTLNF(x, y) + #define DEBUG_PRINTF(...) #endif #define MPU6050_DMP_CODE_SIZE 1929 // dmpMemory[] @@ -131,7 +82,7 @@ THE SOFTWARE. // I Only Changed this by applying all the configuration data and capturing it before startup: // *** this is a capture of the DMP Firmware after all the messy changes were made so we can just load it -static const unsigned char dmpMemory[MPU6050_DMP_CODE_SIZE] PROGMEM = { +static const unsigned char dmpMemory[MPU6050_DMP_CODE_SIZE] = { /* bank # 0 */ 0xFB, 0x00, 0x00, 0x3E, 0x00, 0x0B, 0x00, 0x36, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, 0x00, 0x65, 0x00, 0x54, 0xFF, 0xEF, 0x00, 0x00, 0xFA, 0x80, 0x00, 0x0B, 0x12, 0x82, 0x00, 0x01, @@ -271,14 +222,14 @@ static const unsigned char dmpMemory[MPU6050_DMP_CODE_SIZE] PROGMEM = { // I Simplified this: uint8_t MPU6050_6Axis_MotionApps20::dmpInitialize() { // reset device - DEBUG_PRINTLN(F("\n\nResetting MPU6050...")); + DEBUG_PRINTF("\nResetting MPU6050...\n"); reset(); - delay(30); // wait after reset + usleep(30000); // wait after reset // enable sleep mode and wake cycle - /*Serial.println(F("Enabling sleep mode...")); + /*Serial.println("Enabling sleep mode..."); setSleepEnabled(true); - Serial.println(F("Enabling wake cycle...")); + Serial.println("Enabling wake cycle..."); setWakeCycleEnabled(true);*/ // disable sleep mode @@ -287,51 +238,47 @@ uint8_t MPU6050_6Axis_MotionApps20::dmpInitialize() { // get MPU hardware revision setMemoryBank(0x10, true, true); setMemoryStartAddress(0x06); - DEBUG_PRINTLN(F("Checking hardware revision...")); - DEBUG_PRINT(F("Revision @ user[16][6] = ")); - DEBUG_PRINTLN(readMemoryByte()); - DEBUG_PRINTLN(F("Resetting memory bank selection to 0...")); + DEBUG_PRINTF("Checking hardware revision...\n"); + DEBUG_PRINTF("Revision @ user[16][6] = %hhx\n", readMemoryByte()); + DEBUG_PRINTF("Resetting memory bank selection to 0...\n"); setMemoryBank(0, false, false); // check OTP bank valid - DEBUG_PRINTLN(F("Reading OTP bank valid flag...")); - DEBUG_PRINT(F("OTP bank is ")); - DEBUG_PRINTLN(getOTPBankValid() ? F("valid!") : F("invalid!")); + DEBUG_PRINTF("Reading OTP bank valid flag...\n"); + DEBUG_PRINTF("OTP bank is %s\n", getOTPBankValid() ? "valid!" : "invalid!"); // setup weird slave stuff (?) - DEBUG_PRINTLN(F("Setting slave 0 address to 0x7F...")); + DEBUG_PRINTF("Setting slave 0 address to 0x7F...\n"); setSlaveAddress(0, 0x7F); - DEBUG_PRINTLN(F("Disabling I2C Master mode...")); + DEBUG_PRINTF("Disabling I2C Master mode...\n"); setI2CMasterModeEnabled(false); - DEBUG_PRINTLN(F("Setting slave 0 address to 0x68 (self)...")); + DEBUG_PRINTF("Setting slave 0 address to 0x68 (self)...\n"); setSlaveAddress(0, 0x68); - DEBUG_PRINTLN(F("Resetting I2C Master control...")); + DEBUG_PRINTF("Resetting I2C Master control...\n"); resetI2CMaster(); - delay(20); - DEBUG_PRINTLN(F("Setting clock source to Z Gyro...")); + usleep(20000); + DEBUG_PRINTF("Setting clock source to Z Gyro...\n"); setClockSource(MPU6050_CLOCK_PLL_ZGYRO); - DEBUG_PRINTLN(F("Setting DMP and FIFO_OFLOW interrupts enabled...")); + DEBUG_PRINTF("Setting DMP and FIFO_OFLOW interrupts enabled...\n"); setIntEnabled(1< y , gravity -> z); if (gravity -> z < 0) { if(data[1] > 0) { - data[1] = PI - data[1]; + data[1] = M_PI - data[1]; } else { - data[1] = -PI - data[1]; + data[1] = -M_PI - data[1]; } } return 0; diff --git a/LinuxI2CDev/MPU6050/helper_3dmath.h b/LinuxI2CDev/MPU6050/helper_3dmath.h index 9ed260ec..b8f20d47 100644 --- a/LinuxI2CDev/MPU6050/helper_3dmath.h +++ b/LinuxI2CDev/MPU6050/helper_3dmath.h @@ -32,6 +32,8 @@ THE SOFTWARE. #ifndef _HELPER_3DMATH_H_ #define _HELPER_3DMATH_H_ +#include + class Quaternion { public: float w; @@ -213,4 +215,4 @@ class VectorFloat { } }; -#endif /* _HELPER_3DMATH_H_ */ \ No newline at end of file +#endif /* _HELPER_3DMATH_H_ */ From b388531934977d18a7b1c532f942952cef0d97c7 Mon Sep 17 00:00:00 2001 From: Hananja from Raspberry Pi Zero 2 W Date: Fri, 16 Feb 2024 10:37:22 +0100 Subject: [PATCH 331/335] Remove wireObj argument --- LinuxI2CDev/I2Cdev/I2Cdev.cpp | 68 +-- LinuxI2CDev/I2Cdev/I2Cdev.h | 32 +- LinuxI2CDev/MPU6050/MPU6050.cpp | 548 +++++++++--------- LinuxI2CDev/MPU6050/MPU6050.h | 18 +- .../MPU6050/MPU6050_6Axis_MotionApps20.h | 2 +- 5 files changed, 326 insertions(+), 342 deletions(-) diff --git a/LinuxI2CDev/I2Cdev/I2Cdev.cpp b/LinuxI2CDev/I2Cdev/I2Cdev.cpp index a18b0250..600bf2fc 100644 --- a/LinuxI2CDev/I2Cdev/I2Cdev.cpp +++ b/LinuxI2CDev/I2Cdev/I2Cdev.cpp @@ -73,9 +73,9 @@ void I2Cdev::initialize(const char* devPath) { * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) * @return Status of read operation (true = success) */ -int8_t I2Cdev::readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data, uint16_t timeout, void *wireObj) { +int8_t I2Cdev::readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data, uint16_t timeout) { uint8_t b; - uint8_t count = readByte(devAddr, regAddr, &b, timeout, wireObj); + uint8_t count = readByte(devAddr, regAddr, &b, timeout); *data = b & (1 << bitNum); return count; } @@ -88,9 +88,9 @@ int8_t I2Cdev::readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) * @return Status of read operation (true = success) */ -int8_t I2Cdev::readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data, uint16_t timeout, void *wireObj) { +int8_t I2Cdev::readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data, uint16_t timeout) { uint16_t b; - uint8_t count = readWord(devAddr, regAddr, &b, timeout, wireObj); + uint8_t count = readWord(devAddr, regAddr, &b, timeout); *data = b & (1 << bitNum); return count; } @@ -104,14 +104,14 @@ int8_t I2Cdev::readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16 * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) * @return Status of read operation (true = success) */ -int8_t I2Cdev::readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data, uint16_t timeout, void *wireObj) { +int8_t I2Cdev::readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data, uint16_t timeout) { // 01101001 read byte // 76543210 bit numbers // xxx args: bitStart=4, length=3 // 010 masked // -> 010 shifted uint8_t count, b; - if ((count = readByte(devAddr, regAddr, &b, timeout, wireObj)) != 0) { + if ((count = readByte(devAddr, regAddr, &b, timeout)) != 0) { uint8_t mask = ((1 << length) - 1) << (bitStart - length + 1); b &= mask; b >>= (bitStart - length + 1); @@ -129,7 +129,7 @@ int8_t I2Cdev::readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) * @return Status of read operation (1 = success, 0 = failure, -1 = timeout) */ -int8_t I2Cdev::readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t *data, uint16_t timeout, void *wireObj) { +int8_t I2Cdev::readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t *data, uint16_t timeout) { // 1101011001101001 read byte // fedcba9876543210 bit numbers // xxx args: bitStart=12, length=3 @@ -137,7 +137,7 @@ int8_t I2Cdev::readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uin // -> 010 shifted uint8_t count; uint16_t w; - if ((count = readWord(devAddr, regAddr, &w, timeout, wireObj)) != 0) { + if ((count = readWord(devAddr, regAddr, &w, timeout)) != 0) { uint16_t mask = ((1 << length) - 1) << (bitStart - length + 1); w &= mask; w >>= (bitStart - length + 1); @@ -153,8 +153,8 @@ int8_t I2Cdev::readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uin * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) * @return Status of read operation (true = success) */ -int8_t I2Cdev::readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint16_t timeout, void *wireObj) { - return readBytes(devAddr, regAddr, 1, data, timeout, wireObj); +int8_t I2Cdev::readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint16_t timeout) { + return readBytes(devAddr, regAddr, 1, data, timeout); } /** Read single word from a 16-bit device register. @@ -164,8 +164,8 @@ int8_t I2Cdev::readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint16_ * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) * @return Status of read operation (true = success) */ -int8_t I2Cdev::readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data, uint16_t timeout, void *wireObj) { - return readWords(devAddr, regAddr, 1, data, timeout, wireObj); +int8_t I2Cdev::readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data, uint16_t timeout) { + return readWords(devAddr, regAddr, 1, data, timeout); } /** Read multiple bytes from an 8-bit device register. @@ -176,7 +176,7 @@ int8_t I2Cdev::readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data, uint16 * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) * @return Number of bytes read (-1 indicates failure) */ -int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data, uint16_t timeout, void *wireObj) { +int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data, uint16_t timeout) { int fd = open(i2cDev, O_RDWR); if (fd < 0) { fprintf(stderr, "Failed to open i2c device %s: %s\n", i2cDev, strerror(errno)); @@ -210,10 +210,10 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) * @return Number of words read (-1 indicates failure) */ -int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data, uint16_t timeout, void *wireObj) { +int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data, uint16_t timeout) { uint8_t buff[length * 2]; - if (readBytes(devAddr, regAddr, length * 2, buff, timeout, wireObj) > 0) + if (readBytes(devAddr, regAddr, length * 2, buff, timeout) > 0) { for (int i = 0; i < length; i++) { @@ -232,11 +232,11 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 * @param value New bit value to write * @return Status of operation (true = success) */ -bool I2Cdev::writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t data, void *wireObj) { +bool I2Cdev::writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t data) { uint8_t b; - readByte(devAddr, regAddr, &b, I2Cdev::readTimeout, wireObj); + readByte(devAddr, regAddr, &b, I2Cdev::readTimeout); b = (data != 0) ? (b | (1 << bitNum)) : (b & ~(1 << bitNum)); - return writeByte(devAddr, regAddr, b, wireObj); + return writeByte(devAddr, regAddr, b); } /** write a single bit in a 16-bit device register. @@ -246,11 +246,11 @@ bool I2Cdev::writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t * @param value New bit value to write * @return Status of operation (true = success) */ -bool I2Cdev::writeBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t data, void *wireObj) { +bool I2Cdev::writeBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t data) { uint16_t w; - readWord(devAddr, regAddr, &w, I2Cdev::readTimeout, wireObj); + readWord(devAddr, regAddr, &w, I2Cdev::readTimeout); w = (data != 0) ? (w | (1 << bitNum)) : (w & ~(1 << bitNum)); - return writeWord(devAddr, regAddr, w, wireObj); + return writeWord(devAddr, regAddr, w); } /** Write multiple bits in an 8-bit device register. @@ -261,7 +261,7 @@ bool I2Cdev::writeBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_ * @param data Right-aligned value to write * @return Status of operation (true = success) */ -bool I2Cdev::writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data, void *wireObj) { +bool I2Cdev::writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data) { // 010 value to write // 76543210 bit numbers // xxx args: bitStart=4, length=3 @@ -270,13 +270,13 @@ bool I2Cdev::writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8 // 10100011 original & ~mask // 10101011 masked | value uint8_t b; - if (readByte(devAddr, regAddr, &b, I2Cdev::readTimeout, wireObj) != 0) { + if (readByte(devAddr, regAddr, &b, I2Cdev::readTimeout) != 0) { uint8_t mask = ((1 << length) - 1) << (bitStart - length + 1); data <<= (bitStart - length + 1); // shift data into correct position data &= mask; // zero all non-important bits in data b &= ~(mask); // zero all important bits in existing byte b |= data; // combine data with existing byte - return writeByte(devAddr, regAddr, b, wireObj); + return writeByte(devAddr, regAddr, b); } else { return false; } @@ -290,7 +290,7 @@ bool I2Cdev::writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8 * @param data Right-aligned value to write * @return Status of operation (true = success) */ -bool I2Cdev::writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t data, void *wireObj) { +bool I2Cdev::writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t data) { // 010 value to write // fedcba9876543210 bit numbers // xxx args: bitStart=12, length=3 @@ -299,13 +299,13 @@ bool I2Cdev::writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint // 1010001110010110 original & ~mask // 1010101110010110 masked | value uint16_t w; - if (readWord(devAddr, regAddr, &w, I2Cdev::readTimeout, wireObj) != 0) { + if (readWord(devAddr, regAddr, &w, I2Cdev::readTimeout) != 0) { uint16_t mask = ((1 << length) - 1) << (bitStart - length + 1); data <<= (bitStart - length + 1); // shift data into correct position data &= mask; // zero all non-important bits in data w &= ~(mask); // zero all important bits in existing word w |= data; // combine data with existing word - return writeWord(devAddr, regAddr, w, wireObj); + return writeWord(devAddr, regAddr, w); } else { return false; } @@ -317,8 +317,8 @@ bool I2Cdev::writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint * @param data New byte value to write * @return Status of operation (true = success) */ -bool I2Cdev::writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data, void *wireObj) { - return writeBytes(devAddr, regAddr, 1, &data, wireObj); +bool I2Cdev::writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data) { + return writeBytes(devAddr, regAddr, 1, &data); } /** Write single word to a 16-bit device register. @@ -327,8 +327,8 @@ bool I2Cdev::writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data, void *wir * @param data New word value to write * @return Status of operation (true = success) */ -bool I2Cdev::writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data, void *wireObj) { - return writeWords(devAddr, regAddr, 1, &data, wireObj); +bool I2Cdev::writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data) { + return writeWords(devAddr, regAddr, 1, &data); } /** Write multiple bytes to an 8-bit device register. @@ -338,7 +338,7 @@ bool I2Cdev::writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data, void *wi * @param data Buffer to copy new data from * @return Status of operation (true = success) */ -bool I2Cdev::writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t* data, void *wireObj) { +bool I2Cdev::writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t* data) { int fd = open(i2cDev, O_RDWR); if (fd < 0) { fprintf(stderr, "Failed to open i2c device %s: %s\n", i2cDev, strerror(errno)); @@ -372,7 +372,7 @@ bool I2Cdev::writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_ * @param data Buffer to copy new data from * @return Status of operation (true = success) */ -bool I2Cdev::writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t* data, void *wireObj) { +bool I2Cdev::writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t* data) { uint8_t buff[length * 2]; for (int i = 0; i < length; i++) @@ -381,7 +381,7 @@ bool I2Cdev::writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16 buff[1 + 2 * i] = (uint8_t)(data[i] >> 0); //LSByte } - return writeBytes(devAddr, regAddr, length * 2, buff, wireObj); + return writeBytes(devAddr, regAddr, length * 2, buff); } /** Default timeout value for read operations. diff --git a/LinuxI2CDev/I2Cdev/I2Cdev.h b/LinuxI2CDev/I2Cdev/I2Cdev.h index e6881570..79fd3f01 100644 --- a/LinuxI2CDev/I2Cdev/I2Cdev.h +++ b/LinuxI2CDev/I2Cdev/I2Cdev.h @@ -76,23 +76,23 @@ class I2Cdev { I2Cdev(); static void initialize(const char* i2cDev); - static int8_t readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout, void *wireObj=0); - static int8_t readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout, void *wireObj=0); - static int8_t readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout, void *wireObj=0); - static int8_t readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout, void *wireObj=0); - static int8_t readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout, void *wireObj=0); - static int8_t readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout, void *wireObj=0); - static int8_t readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout, void *wireObj=0); - static int8_t readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout, void *wireObj=0); + static int8_t readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout); + static int8_t readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout); + static int8_t readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout); + static int8_t readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout); + static int8_t readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout); + static int8_t readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout); + static int8_t readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout); + static int8_t readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout); - static bool writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t data, void *wireObj=0); - static bool writeBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t data, void *wireObj=0); - static bool writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data, void *wireObj=0); - static bool writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t data, void *wireObj=0); - static bool writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data, void *wireObj=0); - static bool writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data, void *wireObj=0); - static bool writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data, void *wireObj=0); - static bool writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data, void *wireObj=0); + static bool writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t data); + static bool writeBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t data); + static bool writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data); + static bool writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t data); + static bool writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data); + static bool writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data); + static bool writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data); + static bool writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data); static uint16_t readTimeout; }; diff --git a/LinuxI2CDev/MPU6050/MPU6050.cpp b/LinuxI2CDev/MPU6050/MPU6050.cpp index bb9548aa..6ea4a676 100644 --- a/LinuxI2CDev/MPU6050/MPU6050.cpp +++ b/LinuxI2CDev/MPU6050/MPU6050.cpp @@ -50,7 +50,7 @@ THE SOFTWARE. * @see MPU6050_ADDRESS_AD0_LOW * @see MPU6050_ADDRESS_AD0_HIGH */ -MPU6050_Base::MPU6050_Base(uint8_t address, void *wireObj):devAddr(address), wireObj(wireObj) { +MPU6050_Base::MPU6050_Base(uint8_t address):devAddr(address) { } /** Power on and prepare for general usage. @@ -84,7 +84,7 @@ bool MPU6050_Base::testConnection() { * @return I2C supply voltage level (0=VLOGIC, 1=VDD) */ uint8_t MPU6050_Base::getAuxVDDIOLevel() { - I2Cdev::readBit(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_PWR_MODE_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_PWR_MODE_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set the auxiliary I2C supply voltage level. @@ -94,7 +94,7 @@ uint8_t MPU6050_Base::getAuxVDDIOLevel() { * @param level I2C supply voltage level (0=VLOGIC, 1=VDD) */ void MPU6050_Base::setAuxVDDIOLevel(uint8_t level) { - I2Cdev::writeBit(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_PWR_MODE_BIT, level, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_PWR_MODE_BIT, level); } // SMPLRT_DIV register @@ -121,7 +121,7 @@ void MPU6050_Base::setAuxVDDIOLevel(uint8_t level) { * @see MPU6050_RA_SMPLRT_DIV */ uint8_t MPU6050_Base::getRate() { - I2Cdev::readByte(devAddr, MPU6050_RA_SMPLRT_DIV, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readByte(devAddr, MPU6050_RA_SMPLRT_DIV, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set gyroscope sample rate divider. @@ -130,7 +130,7 @@ uint8_t MPU6050_Base::getRate() { * @see MPU6050_RA_SMPLRT_DIV */ void MPU6050_Base::setRate(uint8_t rate) { - I2Cdev::writeByte(devAddr, MPU6050_RA_SMPLRT_DIV, rate, wireObj); + I2Cdev::writeByte(devAddr, MPU6050_RA_SMPLRT_DIV, rate); } // CONFIG register @@ -163,7 +163,7 @@ void MPU6050_Base::setRate(uint8_t rate) { * @return FSYNC configuration value */ uint8_t MPU6050_Base::getExternalFrameSync() { - I2Cdev::readBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_EXT_SYNC_SET_BIT, MPU6050_CFG_EXT_SYNC_SET_LENGTH, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_EXT_SYNC_SET_BIT, MPU6050_CFG_EXT_SYNC_SET_LENGTH, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set external FSYNC configuration. @@ -172,7 +172,7 @@ uint8_t MPU6050_Base::getExternalFrameSync() { * @param sync New FSYNC configuration value */ void MPU6050_Base::setExternalFrameSync(uint8_t sync) { - I2Cdev::writeBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_EXT_SYNC_SET_BIT, MPU6050_CFG_EXT_SYNC_SET_LENGTH, sync, wireObj); + I2Cdev::writeBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_EXT_SYNC_SET_BIT, MPU6050_CFG_EXT_SYNC_SET_LENGTH, sync); } /** Get digital low-pass filter configuration. * The DLPF_CFG parameter sets the digital low pass filter configuration. It @@ -203,7 +203,7 @@ void MPU6050_Base::setExternalFrameSync(uint8_t sync) { * @see MPU6050_CFG_DLPF_CFG_LENGTH */ uint8_t MPU6050_Base::getDLPFMode() { - I2Cdev::readBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_DLPF_CFG_BIT, MPU6050_CFG_DLPF_CFG_LENGTH, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_DLPF_CFG_BIT, MPU6050_CFG_DLPF_CFG_LENGTH, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set digital low-pass filter configuration. @@ -215,7 +215,7 @@ uint8_t MPU6050_Base::getDLPFMode() { * @see MPU6050_CFG_DLPF_CFG_LENGTH */ void MPU6050_Base::setDLPFMode(uint8_t mode) { - I2Cdev::writeBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_DLPF_CFG_BIT, MPU6050_CFG_DLPF_CFG_LENGTH, mode, wireObj); + I2Cdev::writeBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_DLPF_CFG_BIT, MPU6050_CFG_DLPF_CFG_LENGTH, mode); } // GYRO_CONFIG register @@ -238,7 +238,7 @@ void MPU6050_Base::setDLPFMode(uint8_t mode) { * @see MPU6050_GCONFIG_FS_SEL_LENGTH */ uint8_t MPU6050_Base::getFullScaleGyroRange() { - I2Cdev::readBits(devAddr, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBits(devAddr, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set full-scale gyroscope range. @@ -250,7 +250,7 @@ uint8_t MPU6050_Base::getFullScaleGyroRange() { * @see MPU6050_GCONFIG_FS_SEL_LENGTH */ void MPU6050_Base::setFullScaleGyroRange(uint8_t range) { - I2Cdev::writeBits(devAddr, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, range, wireObj); + I2Cdev::writeBits(devAddr, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, range); } // SELF TEST FACTORY TRIM VALUES @@ -260,8 +260,8 @@ void MPU6050_Base::setFullScaleGyroRange(uint8_t range) { * @see MPU6050_RA_SELF_TEST_X */ uint8_t MPU6050_Base::getAccelXSelfTestFactoryTrim() { - I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_X, &buffer[0], I2Cdev::readTimeout, wireObj); - I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_A, &buffer[1], I2Cdev::readTimeout, wireObj); + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_X, &buffer[0], I2Cdev::readTimeout); + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_A, &buffer[1], I2Cdev::readTimeout); return (buffer[0]>>3) | ((buffer[1]>>4) & 0x03); } @@ -270,8 +270,8 @@ uint8_t MPU6050_Base::getAccelXSelfTestFactoryTrim() { * @see MPU6050_RA_SELF_TEST_Y */ uint8_t MPU6050_Base::getAccelYSelfTestFactoryTrim() { - I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_Y, &buffer[0], I2Cdev::readTimeout, wireObj); - I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_A, &buffer[1], I2Cdev::readTimeout, wireObj); + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_Y, &buffer[0], I2Cdev::readTimeout); + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_A, &buffer[1], I2Cdev::readTimeout); return (buffer[0]>>3) | ((buffer[1]>>2) & 0x03); } @@ -280,7 +280,7 @@ uint8_t MPU6050_Base::getAccelYSelfTestFactoryTrim() { * @see MPU6050_RA_SELF_TEST_Z */ uint8_t MPU6050_Base::getAccelZSelfTestFactoryTrim() { - I2Cdev::readBytes(devAddr, MPU6050_RA_SELF_TEST_Z, 2, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBytes(devAddr, MPU6050_RA_SELF_TEST_Z, 2, buffer, I2Cdev::readTimeout); return (buffer[0]>>3) | (buffer[1] & 0x03); } @@ -289,7 +289,7 @@ uint8_t MPU6050_Base::getAccelZSelfTestFactoryTrim() { * @see MPU6050_RA_SELF_TEST_X */ uint8_t MPU6050_Base::getGyroXSelfTestFactoryTrim() { - I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_X, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_X, buffer, I2Cdev::readTimeout); return (buffer[0] & 0x1F); } @@ -298,7 +298,7 @@ uint8_t MPU6050_Base::getGyroXSelfTestFactoryTrim() { * @see MPU6050_RA_SELF_TEST_Y */ uint8_t MPU6050_Base::getGyroYSelfTestFactoryTrim() { - I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_Y, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_Y, buffer, I2Cdev::readTimeout); return (buffer[0] & 0x1F); } @@ -307,7 +307,7 @@ uint8_t MPU6050_Base::getGyroYSelfTestFactoryTrim() { * @see MPU6050_RA_SELF_TEST_Z */ uint8_t MPU6050_Base::getGyroZSelfTestFactoryTrim() { - I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_Z, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readByte(devAddr, MPU6050_RA_SELF_TEST_Z, buffer, I2Cdev::readTimeout); return (buffer[0] & 0x1F); } @@ -318,7 +318,7 @@ uint8_t MPU6050_Base::getGyroZSelfTestFactoryTrim() { * @see MPU6050_RA_ACCEL_CONFIG */ bool MPU6050_Base::getAccelXSelfTest() { - I2Cdev::readBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_XA_ST_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_XA_ST_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Get self-test enabled setting for accelerometer X axis. @@ -326,14 +326,14 @@ bool MPU6050_Base::getAccelXSelfTest() { * @see MPU6050_RA_ACCEL_CONFIG */ void MPU6050_Base::setAccelXSelfTest(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_XA_ST_BIT, enabled, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_XA_ST_BIT, enabled); } /** Get self-test enabled value for accelerometer Y axis. * @return Self-test enabled value * @see MPU6050_RA_ACCEL_CONFIG */ bool MPU6050_Base::getAccelYSelfTest() { - I2Cdev::readBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_YA_ST_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_YA_ST_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Get self-test enabled value for accelerometer Y axis. @@ -341,14 +341,14 @@ bool MPU6050_Base::getAccelYSelfTest() { * @see MPU6050_RA_ACCEL_CONFIG */ void MPU6050_Base::setAccelYSelfTest(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_YA_ST_BIT, enabled, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_YA_ST_BIT, enabled); } /** Get self-test enabled value for accelerometer Z axis. * @return Self-test enabled value * @see MPU6050_RA_ACCEL_CONFIG */ bool MPU6050_Base::getAccelZSelfTest() { - I2Cdev::readBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ZA_ST_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ZA_ST_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set self-test enabled value for accelerometer Z axis. @@ -356,7 +356,7 @@ bool MPU6050_Base::getAccelZSelfTest() { * @see MPU6050_RA_ACCEL_CONFIG */ void MPU6050_Base::setAccelZSelfTest(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ZA_ST_BIT, enabled, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ZA_ST_BIT, enabled); } /** Get full-scale accelerometer range. * The FS_SEL parameter allows setting the full-scale range of the accelerometer @@ -376,7 +376,7 @@ void MPU6050_Base::setAccelZSelfTest(bool enabled) { * @see MPU6050_ACONFIG_AFS_SEL_LENGTH */ uint8_t MPU6050_Base::getFullScaleAccelRange() { - I2Cdev::readBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set full-scale accelerometer range. @@ -384,7 +384,7 @@ uint8_t MPU6050_Base::getFullScaleAccelRange() { * @see getFullScaleAccelRange() */ void MPU6050_Base::setFullScaleAccelRange(uint8_t range) { - I2Cdev::writeBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, range, wireObj); + I2Cdev::writeBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, range); } /** Get the high-pass filter configuration. * The DHPF is a filter module in the path leading to motion detectors (Free @@ -422,7 +422,7 @@ void MPU6050_Base::setFullScaleAccelRange(uint8_t range) { * @see MPU6050_RA_ACCEL_CONFIG */ uint8_t MPU6050_Base::getDHPFMode() { - I2Cdev::readBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ACCEL_HPF_BIT, MPU6050_ACONFIG_ACCEL_HPF_LENGTH, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ACCEL_HPF_BIT, MPU6050_ACONFIG_ACCEL_HPF_LENGTH, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set the high-pass filter configuration. @@ -432,7 +432,7 @@ uint8_t MPU6050_Base::getDHPFMode() { * @see MPU6050_RA_ACCEL_CONFIG */ void MPU6050_Base::setDHPFMode(uint8_t bandwidth) { - I2Cdev::writeBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ACCEL_HPF_BIT, MPU6050_ACONFIG_ACCEL_HPF_LENGTH, bandwidth, wireObj); + I2Cdev::writeBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ACCEL_HPF_BIT, MPU6050_ACONFIG_ACCEL_HPF_LENGTH, bandwidth); } // FF_THR register @@ -453,7 +453,7 @@ void MPU6050_Base::setDHPFMode(uint8_t bandwidth) { * @see MPU6050_RA_FF_THR */ uint8_t MPU6050_Base::getFreefallDetectionThreshold() { - I2Cdev::readByte(devAddr, MPU6050_RA_FF_THR, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readByte(devAddr, MPU6050_RA_FF_THR, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Get free-fall event acceleration threshold. @@ -462,7 +462,7 @@ uint8_t MPU6050_Base::getFreefallDetectionThreshold() { * @see MPU6050_RA_FF_THR */ void MPU6050_Base::setFreefallDetectionThreshold(uint8_t threshold) { - I2Cdev::writeByte(devAddr, MPU6050_RA_FF_THR, threshold, wireObj); + I2Cdev::writeByte(devAddr, MPU6050_RA_FF_THR, threshold); } // FF_DUR register @@ -485,7 +485,7 @@ void MPU6050_Base::setFreefallDetectionThreshold(uint8_t threshold) { * @see MPU6050_RA_FF_DUR */ uint8_t MPU6050_Base::getFreefallDetectionDuration() { - I2Cdev::readByte(devAddr, MPU6050_RA_FF_DUR, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readByte(devAddr, MPU6050_RA_FF_DUR, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Get free-fall event duration threshold. @@ -494,7 +494,7 @@ uint8_t MPU6050_Base::getFreefallDetectionDuration() { * @see MPU6050_RA_FF_DUR */ void MPU6050_Base::setFreefallDetectionDuration(uint8_t duration) { - I2Cdev::writeByte(devAddr, MPU6050_RA_FF_DUR, duration, wireObj); + I2Cdev::writeByte(devAddr, MPU6050_RA_FF_DUR, duration); } // MOT_THR register @@ -519,7 +519,7 @@ void MPU6050_Base::setFreefallDetectionDuration(uint8_t duration) { * @see MPU6050_RA_MOT_THR */ uint8_t MPU6050_Base::getMotionDetectionThreshold() { - I2Cdev::readByte(devAddr, MPU6050_RA_MOT_THR, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readByte(devAddr, MPU6050_RA_MOT_THR, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set motion detection event acceleration threshold. @@ -528,7 +528,7 @@ uint8_t MPU6050_Base::getMotionDetectionThreshold() { * @see MPU6050_RA_MOT_THR */ void MPU6050_Base::setMotionDetectionThreshold(uint8_t threshold) { - I2Cdev::writeByte(devAddr, MPU6050_RA_MOT_THR, threshold, wireObj); + I2Cdev::writeByte(devAddr, MPU6050_RA_MOT_THR, threshold); } // MOT_DUR register @@ -549,7 +549,7 @@ void MPU6050_Base::setMotionDetectionThreshold(uint8_t threshold) { * @see MPU6050_RA_MOT_DUR */ uint8_t MPU6050_Base::getMotionDetectionDuration() { - I2Cdev::readByte(devAddr, MPU6050_RA_MOT_DUR, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readByte(devAddr, MPU6050_RA_MOT_DUR, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set motion detection event duration threshold. @@ -558,7 +558,7 @@ uint8_t MPU6050_Base::getMotionDetectionDuration() { * @see MPU6050_RA_MOT_DUR */ void MPU6050_Base::setMotionDetectionDuration(uint8_t duration) { - I2Cdev::writeByte(devAddr, MPU6050_RA_MOT_DUR, duration, wireObj); + I2Cdev::writeByte(devAddr, MPU6050_RA_MOT_DUR, duration); } // ZRMOT_THR register @@ -589,7 +589,7 @@ void MPU6050_Base::setMotionDetectionDuration(uint8_t duration) { * @see MPU6050_RA_ZRMOT_THR */ uint8_t MPU6050_Base::getZeroMotionDetectionThreshold() { - I2Cdev::readByte(devAddr, MPU6050_RA_ZRMOT_THR, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readByte(devAddr, MPU6050_RA_ZRMOT_THR, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set zero motion detection event acceleration threshold. @@ -598,7 +598,7 @@ uint8_t MPU6050_Base::getZeroMotionDetectionThreshold() { * @see MPU6050_RA_ZRMOT_THR */ void MPU6050_Base::setZeroMotionDetectionThreshold(uint8_t threshold) { - I2Cdev::writeByte(devAddr, MPU6050_RA_ZRMOT_THR, threshold, wireObj); + I2Cdev::writeByte(devAddr, MPU6050_RA_ZRMOT_THR, threshold); } // ZRMOT_DUR register @@ -620,7 +620,7 @@ void MPU6050_Base::setZeroMotionDetectionThreshold(uint8_t threshold) { * @see MPU6050_RA_ZRMOT_DUR */ uint8_t MPU6050_Base::getZeroMotionDetectionDuration() { - I2Cdev::readByte(devAddr, MPU6050_RA_ZRMOT_DUR, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readByte(devAddr, MPU6050_RA_ZRMOT_DUR, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set zero motion detection event duration threshold. @@ -629,7 +629,7 @@ uint8_t MPU6050_Base::getZeroMotionDetectionDuration() { * @see MPU6050_RA_ZRMOT_DUR */ void MPU6050_Base::setZeroMotionDetectionDuration(uint8_t duration) { - I2Cdev::writeByte(devAddr, MPU6050_RA_ZRMOT_DUR, duration, wireObj); + I2Cdev::writeByte(devAddr, MPU6050_RA_ZRMOT_DUR, duration); } // FIFO_EN register @@ -641,7 +641,7 @@ void MPU6050_Base::setZeroMotionDetectionDuration(uint8_t duration) { * @see MPU6050_RA_FIFO_EN */ bool MPU6050_Base::getTempFIFOEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_TEMP_FIFO_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_TEMP_FIFO_EN_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set temperature FIFO enabled value. @@ -650,7 +650,7 @@ bool MPU6050_Base::getTempFIFOEnabled() { * @see MPU6050_RA_FIFO_EN */ void MPU6050_Base::setTempFIFOEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_TEMP_FIFO_EN_BIT, enabled, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_TEMP_FIFO_EN_BIT, enabled); } /** Get gyroscope X-axis FIFO enabled value. * When set to 1, this bit enables GYRO_XOUT_H and GYRO_XOUT_L (Registers 67 and @@ -659,7 +659,7 @@ void MPU6050_Base::setTempFIFOEnabled(bool enabled) { * @see MPU6050_RA_FIFO_EN */ bool MPU6050_Base::getXGyroFIFOEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_XG_FIFO_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_XG_FIFO_EN_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set gyroscope X-axis FIFO enabled value. @@ -668,7 +668,7 @@ bool MPU6050_Base::getXGyroFIFOEnabled() { * @see MPU6050_RA_FIFO_EN */ void MPU6050_Base::setXGyroFIFOEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_XG_FIFO_EN_BIT, enabled, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_XG_FIFO_EN_BIT, enabled); } /** Get gyroscope Y-axis FIFO enabled value. * When set to 1, this bit enables GYRO_YOUT_H and GYRO_YOUT_L (Registers 69 and @@ -677,7 +677,7 @@ void MPU6050_Base::setXGyroFIFOEnabled(bool enabled) { * @see MPU6050_RA_FIFO_EN */ bool MPU6050_Base::getYGyroFIFOEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_YG_FIFO_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_YG_FIFO_EN_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set gyroscope Y-axis FIFO enabled value. @@ -686,7 +686,7 @@ bool MPU6050_Base::getYGyroFIFOEnabled() { * @see MPU6050_RA_FIFO_EN */ void MPU6050_Base::setYGyroFIFOEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_YG_FIFO_EN_BIT, enabled, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_YG_FIFO_EN_BIT, enabled); } /** Get gyroscope Z-axis FIFO enabled value. * When set to 1, this bit enables GYRO_ZOUT_H and GYRO_ZOUT_L (Registers 71 and @@ -695,7 +695,7 @@ void MPU6050_Base::setYGyroFIFOEnabled(bool enabled) { * @see MPU6050_RA_FIFO_EN */ bool MPU6050_Base::getZGyroFIFOEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ZG_FIFO_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ZG_FIFO_EN_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set gyroscope Z-axis FIFO enabled value. @@ -704,7 +704,7 @@ bool MPU6050_Base::getZGyroFIFOEnabled() { * @see MPU6050_RA_FIFO_EN */ void MPU6050_Base::setZGyroFIFOEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ZG_FIFO_EN_BIT, enabled, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ZG_FIFO_EN_BIT, enabled); } /** Get accelerometer FIFO enabled value. * When set to 1, this bit enables ACCEL_XOUT_H, ACCEL_XOUT_L, ACCEL_YOUT_H, @@ -714,7 +714,7 @@ void MPU6050_Base::setZGyroFIFOEnabled(bool enabled) { * @see MPU6050_RA_FIFO_EN */ bool MPU6050_Base::getAccelFIFOEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ACCEL_FIFO_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ACCEL_FIFO_EN_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set accelerometer FIFO enabled value. @@ -723,7 +723,7 @@ bool MPU6050_Base::getAccelFIFOEnabled() { * @see MPU6050_RA_FIFO_EN */ void MPU6050_Base::setAccelFIFOEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ACCEL_FIFO_EN_BIT, enabled, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_ACCEL_FIFO_EN_BIT, enabled); } /** Get Slave 2 FIFO enabled value. * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) @@ -732,7 +732,7 @@ void MPU6050_Base::setAccelFIFOEnabled(bool enabled) { * @see MPU6050_RA_FIFO_EN */ bool MPU6050_Base::getSlave2FIFOEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV2_FIFO_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV2_FIFO_EN_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set Slave 2 FIFO enabled value. @@ -741,7 +741,7 @@ bool MPU6050_Base::getSlave2FIFOEnabled() { * @see MPU6050_RA_FIFO_EN */ void MPU6050_Base::setSlave2FIFOEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV2_FIFO_EN_BIT, enabled, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV2_FIFO_EN_BIT, enabled); } /** Get Slave 1 FIFO enabled value. * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) @@ -750,7 +750,7 @@ void MPU6050_Base::setSlave2FIFOEnabled(bool enabled) { * @see MPU6050_RA_FIFO_EN */ bool MPU6050_Base::getSlave1FIFOEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV1_FIFO_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV1_FIFO_EN_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set Slave 1 FIFO enabled value. @@ -759,7 +759,7 @@ bool MPU6050_Base::getSlave1FIFOEnabled() { * @see MPU6050_RA_FIFO_EN */ void MPU6050_Base::setSlave1FIFOEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV1_FIFO_EN_BIT, enabled, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV1_FIFO_EN_BIT, enabled); } /** Get Slave 0 FIFO enabled value. * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) @@ -768,7 +768,7 @@ void MPU6050_Base::setSlave1FIFOEnabled(bool enabled) { * @see MPU6050_RA_FIFO_EN */ bool MPU6050_Base::getSlave0FIFOEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV0_FIFO_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV0_FIFO_EN_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set Slave 0 FIFO enabled value. @@ -777,7 +777,7 @@ bool MPU6050_Base::getSlave0FIFOEnabled() { * @see MPU6050_RA_FIFO_EN */ void MPU6050_Base::setSlave0FIFOEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV0_FIFO_EN_BIT, enabled, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_FIFO_EN, MPU6050_SLV0_FIFO_EN_BIT, enabled); } // I2C_MST_CTRL register @@ -798,7 +798,7 @@ void MPU6050_Base::setSlave0FIFOEnabled(bool enabled) { * @see MPU6050_RA_I2C_MST_CTRL */ bool MPU6050_Base::getMultiMasterEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_MULT_MST_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_MULT_MST_EN_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set multi-master enabled value. @@ -807,7 +807,7 @@ bool MPU6050_Base::getMultiMasterEnabled() { * @see MPU6050_RA_I2C_MST_CTRL */ void MPU6050_Base::setMultiMasterEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_MULT_MST_EN_BIT, enabled, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_MULT_MST_EN_BIT, enabled); } /** Get wait-for-external-sensor-data enabled value. * When the WAIT_FOR_ES bit is set to 1, the Data Ready interrupt will be @@ -821,7 +821,7 @@ void MPU6050_Base::setMultiMasterEnabled(bool enabled) { * @see MPU6050_RA_I2C_MST_CTRL */ bool MPU6050_Base::getWaitForExternalSensorEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_WAIT_FOR_ES_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_WAIT_FOR_ES_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set wait-for-external-sensor-data enabled value. @@ -830,7 +830,7 @@ bool MPU6050_Base::getWaitForExternalSensorEnabled() { * @see MPU6050_RA_I2C_MST_CTRL */ void MPU6050_Base::setWaitForExternalSensorEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_WAIT_FOR_ES_BIT, enabled, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_WAIT_FOR_ES_BIT, enabled); } /** Get Slave 3 FIFO enabled value. * When set to 1, this bit enables EXT_SENS_DATA registers (Registers 73 to 96) @@ -839,7 +839,7 @@ void MPU6050_Base::setWaitForExternalSensorEnabled(bool enabled) { * @see MPU6050_RA_MST_CTRL */ bool MPU6050_Base::getSlave3FIFOEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_SLV_3_FIFO_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_SLV_3_FIFO_EN_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set Slave 3 FIFO enabled value. @@ -848,7 +848,7 @@ bool MPU6050_Base::getSlave3FIFOEnabled() { * @see MPU6050_RA_MST_CTRL */ void MPU6050_Base::setSlave3FIFOEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_SLV_3_FIFO_EN_BIT, enabled, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_SLV_3_FIFO_EN_BIT, enabled); } /** Get slave read/write transition enabled value. * The I2C_MST_P_NSR bit configures the I2C Master's transition from one slave @@ -861,7 +861,7 @@ void MPU6050_Base::setSlave3FIFOEnabled(bool enabled) { * @see MPU6050_RA_I2C_MST_CTRL */ bool MPU6050_Base::getSlaveReadWriteTransitionEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_P_NSR_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_P_NSR_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set slave read/write transition enabled value. @@ -870,7 +870,7 @@ bool MPU6050_Base::getSlaveReadWriteTransitionEnabled() { * @see MPU6050_RA_I2C_MST_CTRL */ void MPU6050_Base::setSlaveReadWriteTransitionEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_P_NSR_BIT, enabled, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_P_NSR_BIT, enabled); } /** Get I2C master clock speed. * I2C_MST_CLK is a 4 bit unsigned value which configures a divider on the @@ -902,7 +902,7 @@ void MPU6050_Base::setSlaveReadWriteTransitionEnabled(bool enabled) { * @see MPU6050_RA_I2C_MST_CTRL */ uint8_t MPU6050_Base::getMasterClockSpeed() { - I2Cdev::readBits(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_CLK_BIT, MPU6050_I2C_MST_CLK_LENGTH, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBits(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_CLK_BIT, MPU6050_I2C_MST_CLK_LENGTH, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set I2C master clock speed. @@ -910,7 +910,7 @@ uint8_t MPU6050_Base::getMasterClockSpeed() { * @see MPU6050_RA_I2C_MST_CTRL */ void MPU6050_Base::setMasterClockSpeed(uint8_t speed) { - I2Cdev::writeBits(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_CLK_BIT, MPU6050_I2C_MST_CLK_LENGTH, speed, wireObj); + I2Cdev::writeBits(devAddr, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_CLK_BIT, MPU6050_I2C_MST_CLK_LENGTH, speed); } // I2C_SLV* registers (Slave 0-3) @@ -958,7 +958,7 @@ void MPU6050_Base::setMasterClockSpeed(uint8_t speed) { */ uint8_t MPU6050_Base::getSlaveAddress(uint8_t num) { if (num > 3) return 0; - I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV0_ADDR + num*3, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV0_ADDR + num*3, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set the I2C address of the specified slave (0-3). @@ -969,7 +969,7 @@ uint8_t MPU6050_Base::getSlaveAddress(uint8_t num) { */ void MPU6050_Base::setSlaveAddress(uint8_t num, uint8_t address) { if (num > 3) return; - I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV0_ADDR + num*3, address, wireObj); + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV0_ADDR + num*3, address); } /** Get the active internal register for the specified slave (0-3). * Read/write operations for this slave will be done to whatever internal @@ -984,7 +984,7 @@ void MPU6050_Base::setSlaveAddress(uint8_t num, uint8_t address) { */ uint8_t MPU6050_Base::getSlaveRegister(uint8_t num) { if (num > 3) return 0; - I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV0_REG + num*3, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV0_REG + num*3, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set the active internal register for the specified slave (0-3). @@ -995,7 +995,7 @@ uint8_t MPU6050_Base::getSlaveRegister(uint8_t num) { */ void MPU6050_Base::setSlaveRegister(uint8_t num, uint8_t reg) { if (num > 3) return; - I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV0_REG + num*3, reg, wireObj); + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV0_REG + num*3, reg); } /** Get the enabled value for the specified slave (0-3). * When set to 1, this bit enables Slave 0 for data transfer operations. When @@ -1006,7 +1006,7 @@ void MPU6050_Base::setSlaveRegister(uint8_t num, uint8_t reg) { */ bool MPU6050_Base::getSlaveEnabled(uint8_t num) { if (num > 3) return 0; - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_EN_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set the enabled value for the specified slave (0-3). @@ -1017,7 +1017,7 @@ bool MPU6050_Base::getSlaveEnabled(uint8_t num) { */ void MPU6050_Base::setSlaveEnabled(uint8_t num, bool enabled) { if (num > 3) return; - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_EN_BIT, enabled, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_EN_BIT, enabled); } /** Get word pair byte-swapping enabled for the specified slave (0-3). * When set to 1, this bit enables byte swapping. When byte swapping is enabled, @@ -1032,7 +1032,7 @@ void MPU6050_Base::setSlaveEnabled(uint8_t num, bool enabled) { */ bool MPU6050_Base::getSlaveWordByteSwap(uint8_t num) { if (num > 3) return 0; - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_BYTE_SW_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_BYTE_SW_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set word pair byte-swapping enabled for the specified slave (0-3). @@ -1043,7 +1043,7 @@ bool MPU6050_Base::getSlaveWordByteSwap(uint8_t num) { */ void MPU6050_Base::setSlaveWordByteSwap(uint8_t num, bool enabled) { if (num > 3) return; - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_BYTE_SW_BIT, enabled, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_BYTE_SW_BIT, enabled); } /** Get write mode for the specified slave (0-3). * When set to 1, the transaction will read or write data only. When cleared to @@ -1057,7 +1057,7 @@ void MPU6050_Base::setSlaveWordByteSwap(uint8_t num, bool enabled) { */ bool MPU6050_Base::getSlaveWriteMode(uint8_t num) { if (num > 3) return 0; - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_REG_DIS_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_REG_DIS_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set write mode for the specified slave (0-3). @@ -1068,7 +1068,7 @@ bool MPU6050_Base::getSlaveWriteMode(uint8_t num) { */ void MPU6050_Base::setSlaveWriteMode(uint8_t num, bool mode) { if (num > 3) return; - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_REG_DIS_BIT, mode, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_REG_DIS_BIT, mode); } /** Get word pair grouping order offset for the specified slave (0-3). * This sets specifies the grouping order of word pairs received from registers. @@ -1083,7 +1083,7 @@ void MPU6050_Base::setSlaveWriteMode(uint8_t num, bool mode) { */ bool MPU6050_Base::getSlaveWordGroupOffset(uint8_t num) { if (num > 3) return 0; - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_GRP_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_GRP_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set word pair grouping order offset for the specified slave (0-3). @@ -1094,7 +1094,7 @@ bool MPU6050_Base::getSlaveWordGroupOffset(uint8_t num) { */ void MPU6050_Base::setSlaveWordGroupOffset(uint8_t num, bool enabled) { if (num > 3) return; - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_GRP_BIT, enabled, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_GRP_BIT, enabled); } /** Get number of bytes to read for the specified slave (0-3). * Specifies the number of bytes transferred to and from Slave 0. Clearing this @@ -1105,7 +1105,7 @@ void MPU6050_Base::setSlaveWordGroupOffset(uint8_t num, bool enabled) { */ uint8_t MPU6050_Base::getSlaveDataLength(uint8_t num) { if (num > 3) return 0; - I2Cdev::readBits(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_LEN_BIT, MPU6050_I2C_SLV_LEN_LENGTH, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBits(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_LEN_BIT, MPU6050_I2C_SLV_LEN_LENGTH, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set number of bytes to read for the specified slave (0-3). @@ -1116,7 +1116,7 @@ uint8_t MPU6050_Base::getSlaveDataLength(uint8_t num) { */ void MPU6050_Base::setSlaveDataLength(uint8_t num, uint8_t length) { if (num > 3) return; - I2Cdev::writeBits(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_LEN_BIT, MPU6050_I2C_SLV_LEN_LENGTH, length, wireObj); + I2Cdev::writeBits(devAddr, MPU6050_RA_I2C_SLV0_CTRL + num*3, MPU6050_I2C_SLV_LEN_BIT, MPU6050_I2C_SLV_LEN_LENGTH, length); } // I2C_SLV* registers (Slave 4) @@ -1131,7 +1131,7 @@ void MPU6050_Base::setSlaveDataLength(uint8_t num, uint8_t length) { * @see MPU6050_RA_I2C_SLV4_ADDR */ uint8_t MPU6050_Base::getSlave4Address() { - I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV4_ADDR, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV4_ADDR, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set the I2C address of Slave 4. @@ -1140,7 +1140,7 @@ uint8_t MPU6050_Base::getSlave4Address() { * @see MPU6050_RA_I2C_SLV4_ADDR */ void MPU6050_Base::setSlave4Address(uint8_t address) { - I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV4_ADDR, address, wireObj); + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV4_ADDR, address); } /** Get the active internal register for the Slave 4. * Read/write operations for this slave will be done to whatever internal @@ -1150,7 +1150,7 @@ void MPU6050_Base::setSlave4Address(uint8_t address) { * @see MPU6050_RA_I2C_SLV4_REG */ uint8_t MPU6050_Base::getSlave4Register() { - I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV4_REG, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV4_REG, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set the active internal register for Slave 4. @@ -1159,7 +1159,7 @@ uint8_t MPU6050_Base::getSlave4Register() { * @see MPU6050_RA_I2C_SLV4_REG */ void MPU6050_Base::setSlave4Register(uint8_t reg) { - I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV4_REG, reg, wireObj); + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV4_REG, reg); } /** Set new byte to write to Slave 4. * This register stores the data to be written into the Slave 4. If I2C_SLV4_RW @@ -1168,7 +1168,7 @@ void MPU6050_Base::setSlave4Register(uint8_t reg) { * @see MPU6050_RA_I2C_SLV4_DO */ void MPU6050_Base::setSlave4OutputByte(uint8_t data) { - I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV4_DO, data, wireObj); + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV4_DO, data); } /** Get the enabled value for the Slave 4. * When set to 1, this bit enables Slave 4 for data transfer operations. When @@ -1177,7 +1177,7 @@ void MPU6050_Base::setSlave4OutputByte(uint8_t data) { * @see MPU6050_RA_I2C_SLV4_CTRL */ bool MPU6050_Base::getSlave4Enabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_EN_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set the enabled value for Slave 4. @@ -1186,7 +1186,7 @@ bool MPU6050_Base::getSlave4Enabled() { * @see MPU6050_RA_I2C_SLV4_CTRL */ void MPU6050_Base::setSlave4Enabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_EN_BIT, enabled, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_EN_BIT, enabled); } /** Get the enabled value for Slave 4 transaction interrupts. * When set to 1, this bit enables the generation of an interrupt signal upon @@ -1198,7 +1198,7 @@ void MPU6050_Base::setSlave4Enabled(bool enabled) { * @see MPU6050_RA_I2C_SLV4_CTRL */ bool MPU6050_Base::getSlave4InterruptEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_INT_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_INT_EN_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set the enabled value for Slave 4 transaction interrupts. @@ -1207,7 +1207,7 @@ bool MPU6050_Base::getSlave4InterruptEnabled() { * @see MPU6050_RA_I2C_SLV4_CTRL */ void MPU6050_Base::setSlave4InterruptEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_INT_EN_BIT, enabled, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_INT_EN_BIT, enabled); } /** Get write mode for Slave 4. * When set to 1, the transaction will read or write data only. When cleared to @@ -1219,7 +1219,7 @@ void MPU6050_Base::setSlave4InterruptEnabled(bool enabled) { * @see MPU6050_RA_I2C_SLV4_CTRL */ bool MPU6050_Base::getSlave4WriteMode() { - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_REG_DIS_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_REG_DIS_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set write mode for the Slave 4. @@ -1228,7 +1228,7 @@ bool MPU6050_Base::getSlave4WriteMode() { * @see MPU6050_RA_I2C_SLV4_CTRL */ void MPU6050_Base::setSlave4WriteMode(bool mode) { - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_REG_DIS_BIT, mode, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_REG_DIS_BIT, mode); } /** Get Slave 4 master delay value. * This configures the reduced access rate of I2C slaves relative to the Sample @@ -1246,7 +1246,7 @@ void MPU6050_Base::setSlave4WriteMode(bool mode) { * @see MPU6050_RA_I2C_SLV4_CTRL */ uint8_t MPU6050_Base::getSlave4MasterDelay() { - I2Cdev::readBits(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_MST_DLY_BIT, MPU6050_I2C_SLV4_MST_DLY_LENGTH, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBits(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_MST_DLY_BIT, MPU6050_I2C_SLV4_MST_DLY_LENGTH, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set Slave 4 master delay value. @@ -1255,7 +1255,7 @@ uint8_t MPU6050_Base::getSlave4MasterDelay() { * @see MPU6050_RA_I2C_SLV4_CTRL */ void MPU6050_Base::setSlave4MasterDelay(uint8_t delay) { - I2Cdev::writeBits(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_MST_DLY_BIT, MPU6050_I2C_SLV4_MST_DLY_LENGTH, delay, wireObj); + I2Cdev::writeBits(devAddr, MPU6050_RA_I2C_SLV4_CTRL, MPU6050_I2C_SLV4_MST_DLY_BIT, MPU6050_I2C_SLV4_MST_DLY_LENGTH, delay); } /** Get last available byte read from Slave 4. * This register stores the data read from Slave 4. This field is populated @@ -1264,7 +1264,7 @@ void MPU6050_Base::setSlave4MasterDelay(uint8_t delay) { * @see MPU6050_RA_I2C_SLV4_DI */ uint8_t MPU6050_Base::getSlate4InputByte() { - I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV4_DI, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readByte(devAddr, MPU6050_RA_I2C_SLV4_DI, buffer, I2Cdev::readTimeout); return buffer[0]; } @@ -1280,7 +1280,7 @@ uint8_t MPU6050_Base::getSlate4InputByte() { * @see MPU6050_RA_I2C_MST_STATUS */ bool MPU6050_Base::getPassthroughStatus() { - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_PASS_THROUGH_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_PASS_THROUGH_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Get Slave 4 transaction done status. @@ -1292,7 +1292,7 @@ bool MPU6050_Base::getPassthroughStatus() { * @see MPU6050_RA_I2C_MST_STATUS */ bool MPU6050_Base::getSlave4IsDone() { - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV4_DONE_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV4_DONE_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Get master arbitration lost status. @@ -1303,7 +1303,7 @@ bool MPU6050_Base::getSlave4IsDone() { * @see MPU6050_RA_I2C_MST_STATUS */ bool MPU6050_Base::getLostArbitration() { - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_LOST_ARB_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_LOST_ARB_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Get Slave 4 NACK status. @@ -1314,7 +1314,7 @@ bool MPU6050_Base::getLostArbitration() { * @see MPU6050_RA_I2C_MST_STATUS */ bool MPU6050_Base::getSlave4Nack() { - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV4_NACK_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV4_NACK_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Get Slave 3 NACK status. @@ -1325,7 +1325,7 @@ bool MPU6050_Base::getSlave4Nack() { * @see MPU6050_RA_I2C_MST_STATUS */ bool MPU6050_Base::getSlave3Nack() { - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV3_NACK_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV3_NACK_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Get Slave 2 NACK status. @@ -1336,7 +1336,7 @@ bool MPU6050_Base::getSlave3Nack() { * @see MPU6050_RA_I2C_MST_STATUS */ bool MPU6050_Base::getSlave2Nack() { - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV2_NACK_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV2_NACK_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Get Slave 1 NACK status. @@ -1347,7 +1347,7 @@ bool MPU6050_Base::getSlave2Nack() { * @see MPU6050_RA_I2C_MST_STATUS */ bool MPU6050_Base::getSlave1Nack() { - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV1_NACK_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV1_NACK_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Get Slave 0 NACK status. @@ -1358,7 +1358,7 @@ bool MPU6050_Base::getSlave1Nack() { * @see MPU6050_RA_I2C_MST_STATUS */ bool MPU6050_Base::getSlave0Nack() { - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV0_NACK_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_STATUS, MPU6050_MST_I2C_SLV0_NACK_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } @@ -1371,7 +1371,7 @@ bool MPU6050_Base::getSlave0Nack() { * @see MPU6050_INTCFG_INT_LEVEL_BIT */ bool MPU6050_Base::getInterruptMode() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_LEVEL_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_LEVEL_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set interrupt logic level mode. @@ -1381,7 +1381,7 @@ bool MPU6050_Base::getInterruptMode() { * @see MPU6050_INTCFG_INT_LEVEL_BIT */ void MPU6050_Base::setInterruptMode(bool mode) { - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_LEVEL_BIT, mode, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_LEVEL_BIT, mode); } /** Get interrupt drive mode. * Will be set 0 for push-pull, 1 for open-drain. @@ -1390,7 +1390,7 @@ void MPU6050_Base::setInterruptMode(bool mode) { * @see MPU6050_INTCFG_INT_OPEN_BIT */ bool MPU6050_Base::getInterruptDrive() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_OPEN_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_OPEN_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set interrupt drive mode. @@ -1400,7 +1400,7 @@ bool MPU6050_Base::getInterruptDrive() { * @see MPU6050_INTCFG_INT_OPEN_BIT */ void MPU6050_Base::setInterruptDrive(bool drive) { - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_OPEN_BIT, drive, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_OPEN_BIT, drive); } /** Get interrupt latch mode. * Will be set 0 for 50us-pulse, 1 for latch-until-int-cleared. @@ -1409,7 +1409,7 @@ void MPU6050_Base::setInterruptDrive(bool drive) { * @see MPU6050_INTCFG_LATCH_INT_EN_BIT */ bool MPU6050_Base::getInterruptLatch() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_LATCH_INT_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_LATCH_INT_EN_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set interrupt latch mode. @@ -1419,7 +1419,7 @@ bool MPU6050_Base::getInterruptLatch() { * @see MPU6050_INTCFG_LATCH_INT_EN_BIT */ void MPU6050_Base::setInterruptLatch(bool latch) { - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_LATCH_INT_EN_BIT, latch, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_LATCH_INT_EN_BIT, latch); } /** Get interrupt latch clear mode. * Will be set 0 for status-read-only, 1 for any-register-read. @@ -1428,7 +1428,7 @@ void MPU6050_Base::setInterruptLatch(bool latch) { * @see MPU6050_INTCFG_INT_RD_CLEAR_BIT */ bool MPU6050_Base::getInterruptLatchClear() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_RD_CLEAR_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_RD_CLEAR_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set interrupt latch clear mode. @@ -1438,7 +1438,7 @@ bool MPU6050_Base::getInterruptLatchClear() { * @see MPU6050_INTCFG_INT_RD_CLEAR_BIT */ void MPU6050_Base::setInterruptLatchClear(bool clear) { - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_RD_CLEAR_BIT, clear, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_RD_CLEAR_BIT, clear); } /** Get FSYNC interrupt logic level mode. * @return Current FSYNC interrupt mode (0=active-high, 1=active-low) @@ -1447,7 +1447,7 @@ void MPU6050_Base::setInterruptLatchClear(bool clear) { * @see MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT */ bool MPU6050_Base::getFSyncInterruptLevel() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set FSYNC interrupt logic level mode. @@ -1457,7 +1457,7 @@ bool MPU6050_Base::getFSyncInterruptLevel() { * @see MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT */ void MPU6050_Base::setFSyncInterruptLevel(bool level) { - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT, level, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT, level); } /** Get FSYNC pin interrupt enabled setting. * Will be set 0 for disabled, 1 for enabled. @@ -1466,7 +1466,7 @@ void MPU6050_Base::setFSyncInterruptLevel(bool level) { * @see MPU6050_INTCFG_FSYNC_INT_EN_BIT */ bool MPU6050_Base::getFSyncInterruptEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_EN_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set FSYNC pin interrupt enabled setting. @@ -1476,7 +1476,7 @@ bool MPU6050_Base::getFSyncInterruptEnabled() { * @see MPU6050_INTCFG_FSYNC_INT_EN_BIT */ void MPU6050_Base::setFSyncInterruptEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_EN_BIT, enabled, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_FSYNC_INT_EN_BIT, enabled); } /** Get I2C bypass enabled status. * When this bit is equal to 1 and I2C_MST_EN (Register 106 bit[5]) is equal to @@ -1490,7 +1490,7 @@ void MPU6050_Base::setFSyncInterruptEnabled(bool enabled) { * @see MPU6050_INTCFG_I2C_BYPASS_EN_BIT */ bool MPU6050_Base::getI2CBypassEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_I2C_BYPASS_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_I2C_BYPASS_EN_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set I2C bypass enabled status. @@ -1505,7 +1505,7 @@ bool MPU6050_Base::getI2CBypassEnabled() { * @see MPU6050_INTCFG_I2C_BYPASS_EN_BIT */ void MPU6050_Base::setI2CBypassEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_I2C_BYPASS_EN_BIT, enabled, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_I2C_BYPASS_EN_BIT, enabled); } /** Get reference clock output enabled status. * When this bit is equal to 1, a reference clock output is provided at the @@ -1517,7 +1517,7 @@ void MPU6050_Base::setI2CBypassEnabled(bool enabled) { * @see MPU6050_INTCFG_CLKOUT_EN_BIT */ bool MPU6050_Base::getClockOutputEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_CLKOUT_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_CLKOUT_EN_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set reference clock output enabled status. @@ -1530,7 +1530,7 @@ bool MPU6050_Base::getClockOutputEnabled() { * @see MPU6050_INTCFG_CLKOUT_EN_BIT */ void MPU6050_Base::setClockOutputEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_CLKOUT_EN_BIT, enabled, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_CLKOUT_EN_BIT, enabled); } // INT_ENABLE register @@ -1543,7 +1543,7 @@ void MPU6050_Base::setClockOutputEnabled(bool enabled) { * @see MPU6050_INTERRUPT_FF_BIT **/ uint8_t MPU6050_Base::getIntEnabled() { - I2Cdev::readByte(devAddr, MPU6050_RA_INT_ENABLE, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readByte(devAddr, MPU6050_RA_INT_ENABLE, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set full interrupt enabled status. @@ -1555,7 +1555,7 @@ uint8_t MPU6050_Base::getIntEnabled() { * @see MPU6050_INTERRUPT_FF_BIT **/ void MPU6050_Base::setIntEnabled(uint8_t enabled) { - I2Cdev::writeByte(devAddr, MPU6050_RA_INT_ENABLE, enabled, wireObj); + I2Cdev::writeByte(devAddr, MPU6050_RA_INT_ENABLE, enabled); } /** Get Free Fall interrupt enabled status. * Will be set 0 for disabled, 1 for enabled. @@ -1564,7 +1564,7 @@ void MPU6050_Base::setIntEnabled(uint8_t enabled) { * @see MPU6050_INTERRUPT_FF_BIT **/ bool MPU6050_Base::getIntFreefallEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FF_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FF_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set Free Fall interrupt enabled status. @@ -1574,7 +1574,7 @@ bool MPU6050_Base::getIntFreefallEnabled() { * @see MPU6050_INTERRUPT_FF_BIT **/ void MPU6050_Base::setIntFreefallEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FF_BIT, enabled, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FF_BIT, enabled); } /** Get Motion Detection interrupt enabled status. * Will be set 0 for disabled, 1 for enabled. @@ -1583,7 +1583,7 @@ void MPU6050_Base::setIntFreefallEnabled(bool enabled) { * @see MPU6050_INTERRUPT_MOT_BIT **/ bool MPU6050_Base::getIntMotionEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_MOT_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_MOT_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set Motion Detection interrupt enabled status. @@ -1593,7 +1593,7 @@ bool MPU6050_Base::getIntMotionEnabled() { * @see MPU6050_INTERRUPT_MOT_BIT **/ void MPU6050_Base::setIntMotionEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_MOT_BIT, enabled, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_MOT_BIT, enabled); } /** Get Zero Motion Detection interrupt enabled status. * Will be set 0 for disabled, 1 for enabled. @@ -1602,7 +1602,7 @@ void MPU6050_Base::setIntMotionEnabled(bool enabled) { * @see MPU6050_INTERRUPT_ZMOT_BIT **/ bool MPU6050_Base::getIntZeroMotionEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_ZMOT_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_ZMOT_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set Zero Motion Detection interrupt enabled status. @@ -1612,7 +1612,7 @@ bool MPU6050_Base::getIntZeroMotionEnabled() { * @see MPU6050_INTERRUPT_ZMOT_BIT **/ void MPU6050_Base::setIntZeroMotionEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_ZMOT_BIT, enabled, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_ZMOT_BIT, enabled); } /** Get FIFO Buffer Overflow interrupt enabled status. * Will be set 0 for disabled, 1 for enabled. @@ -1621,7 +1621,7 @@ void MPU6050_Base::setIntZeroMotionEnabled(bool enabled) { * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT **/ bool MPU6050_Base::getIntFIFOBufferOverflowEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set FIFO Buffer Overflow interrupt enabled status. @@ -1631,7 +1631,7 @@ bool MPU6050_Base::getIntFIFOBufferOverflowEnabled() { * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT **/ void MPU6050_Base::setIntFIFOBufferOverflowEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, enabled, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, enabled); } /** Get I2C Master interrupt enabled status. * This enables any of the I2C Master interrupt sources to generate an @@ -1641,7 +1641,7 @@ void MPU6050_Base::setIntFIFOBufferOverflowEnabled(bool enabled) { * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT **/ bool MPU6050_Base::getIntI2CMasterEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_I2C_MST_INT_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_I2C_MST_INT_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set I2C Master interrupt enabled status. @@ -1651,7 +1651,7 @@ bool MPU6050_Base::getIntI2CMasterEnabled() { * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT **/ void MPU6050_Base::setIntI2CMasterEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_I2C_MST_INT_BIT, enabled, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_I2C_MST_INT_BIT, enabled); } /** Get Data Ready interrupt enabled setting. * This event occurs each time a write operation to all of the sensor registers @@ -1661,7 +1661,7 @@ void MPU6050_Base::setIntI2CMasterEnabled(bool enabled) { * @see MPU6050_INTERRUPT_DATA_RDY_BIT */ bool MPU6050_Base::getIntDataReadyEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DATA_RDY_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DATA_RDY_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set Data Ready interrupt enabled status. @@ -1671,7 +1671,7 @@ bool MPU6050_Base::getIntDataReadyEnabled() { * @see MPU6050_INTERRUPT_DATA_RDY_BIT */ void MPU6050_Base::setIntDataReadyEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DATA_RDY_BIT, enabled, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DATA_RDY_BIT, enabled); } // INT_STATUS register @@ -1684,7 +1684,7 @@ void MPU6050_Base::setIntDataReadyEnabled(bool enabled) { * @see MPU6050_RA_INT_STATUS */ uint8_t MPU6050_Base::getIntStatus() { - I2Cdev::readByte(devAddr, MPU6050_RA_INT_STATUS, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readByte(devAddr, MPU6050_RA_INT_STATUS, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Get Free Fall interrupt status. @@ -1695,7 +1695,7 @@ uint8_t MPU6050_Base::getIntStatus() { * @see MPU6050_INTERRUPT_FF_BIT */ bool MPU6050_Base::getIntFreefallStatus() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_FF_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_FF_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Get Motion Detection interrupt status. @@ -1706,7 +1706,7 @@ bool MPU6050_Base::getIntFreefallStatus() { * @see MPU6050_INTERRUPT_MOT_BIT */ bool MPU6050_Base::getIntMotionStatus() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_MOT_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_MOT_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Get Zero Motion Detection interrupt status. @@ -1717,7 +1717,7 @@ bool MPU6050_Base::getIntMotionStatus() { * @see MPU6050_INTERRUPT_ZMOT_BIT */ bool MPU6050_Base::getIntZeroMotionStatus() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_ZMOT_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_ZMOT_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Get FIFO Buffer Overflow interrupt status. @@ -1728,7 +1728,7 @@ bool MPU6050_Base::getIntZeroMotionStatus() { * @see MPU6050_INTERRUPT_FIFO_OFLOW_BIT */ bool MPU6050_Base::getIntFIFOBufferOverflowStatus() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_FIFO_OFLOW_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Get I2C Master interrupt status. @@ -1740,7 +1740,7 @@ bool MPU6050_Base::getIntFIFOBufferOverflowStatus() { * @see MPU6050_INTERRUPT_I2C_MST_INT_BIT */ bool MPU6050_Base::getIntI2CMasterStatus() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_I2C_MST_INT_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_I2C_MST_INT_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Get Data Ready interrupt status. @@ -1751,7 +1751,7 @@ bool MPU6050_Base::getIntI2CMasterStatus() { * @see MPU6050_INTERRUPT_DATA_RDY_BIT */ bool MPU6050_Base::getIntDataReadyStatus() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_DATA_RDY_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_DATA_RDY_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } @@ -1794,7 +1794,7 @@ void MPU6050_Base::getMotion9(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx * @see MPU6050_RA_ACCEL_XOUT_H */ void MPU6050_Base::getMotion6(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz) { - I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_XOUT_H, 14, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_XOUT_H, 14, buffer, I2Cdev::readTimeout); *ax = (((int16_t)buffer[0]) << 8) | buffer[1]; *ay = (((int16_t)buffer[2]) << 8) | buffer[3]; *az = (((int16_t)buffer[4]) << 8) | buffer[5]; @@ -1839,7 +1839,7 @@ void MPU6050_Base::getMotion6(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx * @see MPU6050_RA_GYRO_XOUT_H */ void MPU6050_Base::getAcceleration(int16_t* x, int16_t* y, int16_t* z) { - I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_XOUT_H, 6, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_XOUT_H, 6, buffer, I2Cdev::readTimeout); *x = (((int16_t)buffer[0]) << 8) | buffer[1]; *y = (((int16_t)buffer[2]) << 8) | buffer[3]; *z = (((int16_t)buffer[4]) << 8) | buffer[5]; @@ -1850,7 +1850,7 @@ void MPU6050_Base::getAcceleration(int16_t* x, int16_t* y, int16_t* z) { * @see MPU6050_RA_ACCEL_XOUT_H */ int16_t MPU6050_Base::getAccelerationX() { - I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_XOUT_H, 2, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_XOUT_H, 2, buffer, I2Cdev::readTimeout); return (((int16_t)buffer[0]) << 8) | buffer[1]; } /** Get Y-axis accelerometer reading. @@ -1859,7 +1859,7 @@ int16_t MPU6050_Base::getAccelerationX() { * @see MPU6050_RA_ACCEL_YOUT_H */ int16_t MPU6050_Base::getAccelerationY() { - I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_YOUT_H, 2, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_YOUT_H, 2, buffer, I2Cdev::readTimeout); return (((int16_t)buffer[0]) << 8) | buffer[1]; } /** Get Z-axis accelerometer reading. @@ -1868,7 +1868,7 @@ int16_t MPU6050_Base::getAccelerationY() { * @see MPU6050_RA_ACCEL_ZOUT_H */ int16_t MPU6050_Base::getAccelerationZ() { - I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_ZOUT_H, 2, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_ZOUT_H, 2, buffer, I2Cdev::readTimeout); return (((int16_t)buffer[0]) << 8) | buffer[1]; } @@ -1879,7 +1879,7 @@ int16_t MPU6050_Base::getAccelerationZ() { * @see MPU6050_RA_TEMP_OUT_H */ int16_t MPU6050_Base::getTemperature() { - I2Cdev::readBytes(devAddr, MPU6050_RA_TEMP_OUT_H, 2, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBytes(devAddr, MPU6050_RA_TEMP_OUT_H, 2, buffer, I2Cdev::readTimeout); return (((int16_t)buffer[0]) << 8) | buffer[1]; } @@ -1918,7 +1918,7 @@ int16_t MPU6050_Base::getTemperature() { * @see MPU6050_RA_GYRO_XOUT_H */ void MPU6050_Base::getRotation(int16_t* x, int16_t* y, int16_t* z) { - I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_XOUT_H, 6, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_XOUT_H, 6, buffer, I2Cdev::readTimeout); *x = (((int16_t)buffer[0]) << 8) | buffer[1]; *y = (((int16_t)buffer[2]) << 8) | buffer[3]; *z = (((int16_t)buffer[4]) << 8) | buffer[5]; @@ -1929,7 +1929,7 @@ void MPU6050_Base::getRotation(int16_t* x, int16_t* y, int16_t* z) { * @see MPU6050_RA_GYRO_XOUT_H */ int16_t MPU6050_Base::getRotationX() { - I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_XOUT_H, 2, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_XOUT_H, 2, buffer, I2Cdev::readTimeout); return (((int16_t)buffer[0]) << 8) | buffer[1]; } /** Get Y-axis gyroscope reading. @@ -1938,7 +1938,7 @@ int16_t MPU6050_Base::getRotationX() { * @see MPU6050_RA_GYRO_YOUT_H */ int16_t MPU6050_Base::getRotationY() { - I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_YOUT_H, 2, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_YOUT_H, 2, buffer, I2Cdev::readTimeout); return (((int16_t)buffer[0]) << 8) | buffer[1]; } /** Get Z-axis gyroscope reading. @@ -1947,7 +1947,7 @@ int16_t MPU6050_Base::getRotationY() { * @see MPU6050_RA_GYRO_ZOUT_H */ int16_t MPU6050_Base::getRotationZ() { - I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_ZOUT_H, 2, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBytes(devAddr, MPU6050_RA_GYRO_ZOUT_H, 2, buffer, I2Cdev::readTimeout); return (((int16_t)buffer[0]) << 8) | buffer[1]; } @@ -2028,7 +2028,7 @@ int16_t MPU6050_Base::getRotationZ() { * @return Byte read from register */ uint8_t MPU6050_Base::getExternalSensorByte(int position) { - I2Cdev::readByte(devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readByte(devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Read word (2 bytes) from external sensor data registers. @@ -2037,7 +2037,7 @@ uint8_t MPU6050_Base::getExternalSensorByte(int position) { * @see getExternalSensorByte() */ uint16_t MPU6050_Base::getExternalSensorWord(int position) { - I2Cdev::readBytes(devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, 2, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBytes(devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, 2, buffer, I2Cdev::readTimeout); return (((uint16_t)buffer[0]) << 8) | buffer[1]; } /** Read double word (4 bytes) from external sensor data registers. @@ -2046,7 +2046,7 @@ uint16_t MPU6050_Base::getExternalSensorWord(int position) { * @see getExternalSensorByte() */ uint32_t MPU6050_Base::getExternalSensorDWord(int position) { - I2Cdev::readBytes(devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, 4, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBytes(devAddr, MPU6050_RA_EXT_SENS_DATA_00 + position, 4, buffer, I2Cdev::readTimeout); return (((uint32_t)buffer[0]) << 24) | (((uint32_t)buffer[1]) << 16) | (((uint16_t)buffer[2]) << 8) | buffer[3]; } @@ -2057,7 +2057,7 @@ uint32_t MPU6050_Base::getExternalSensorDWord(int position) { * @see MPU6050_RA_MOT_DETECT_STATUS */ uint8_t MPU6050_Base::getMotionStatus() { - I2Cdev::readByte(devAddr, MPU6050_RA_MOT_DETECT_STATUS, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readByte(devAddr, MPU6050_RA_MOT_DETECT_STATUS, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Get X-axis negative motion detection interrupt status. @@ -2066,7 +2066,7 @@ uint8_t MPU6050_Base::getMotionStatus() { * @see MPU6050_MOTION_MOT_XNEG_BIT */ bool MPU6050_Base::getXNegMotionDetected() { - I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_XNEG_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_XNEG_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Get X-axis positive motion detection interrupt status. @@ -2075,7 +2075,7 @@ bool MPU6050_Base::getXNegMotionDetected() { * @see MPU6050_MOTION_MOT_XPOS_BIT */ bool MPU6050_Base::getXPosMotionDetected() { - I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_XPOS_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_XPOS_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Get Y-axis negative motion detection interrupt status. @@ -2084,7 +2084,7 @@ bool MPU6050_Base::getXPosMotionDetected() { * @see MPU6050_MOTION_MOT_YNEG_BIT */ bool MPU6050_Base::getYNegMotionDetected() { - I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_YNEG_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_YNEG_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Get Y-axis positive motion detection interrupt status. @@ -2093,7 +2093,7 @@ bool MPU6050_Base::getYNegMotionDetected() { * @see MPU6050_MOTION_MOT_YPOS_BIT */ bool MPU6050_Base::getYPosMotionDetected() { - I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_YPOS_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_YPOS_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Get Z-axis negative motion detection interrupt status. @@ -2102,7 +2102,7 @@ bool MPU6050_Base::getYPosMotionDetected() { * @see MPU6050_MOTION_MOT_ZNEG_BIT */ bool MPU6050_Base::getZNegMotionDetected() { - I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZNEG_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZNEG_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Get Z-axis positive motion detection interrupt status. @@ -2111,7 +2111,7 @@ bool MPU6050_Base::getZNegMotionDetected() { * @see MPU6050_MOTION_MOT_ZPOS_BIT */ bool MPU6050_Base::getZPosMotionDetected() { - I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZPOS_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZPOS_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Get zero motion detection interrupt status. @@ -2120,7 +2120,7 @@ bool MPU6050_Base::getZPosMotionDetected() { * @see MPU6050_MOTION_MOT_ZRMOT_BIT */ bool MPU6050_Base::getZeroMotionDetected() { - I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZRMOT_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_MOT_DETECT_STATUS, MPU6050_MOTION_MOT_ZRMOT_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } @@ -2136,7 +2136,7 @@ bool MPU6050_Base::getZeroMotionDetected() { */ void MPU6050_Base::setSlaveOutputByte(uint8_t num, uint8_t data) { if (num > 3) return; - I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV0_DO + num, data, wireObj); + I2Cdev::writeByte(devAddr, MPU6050_RA_I2C_SLV0_DO + num, data); } // I2C_MST_DELAY_CTRL register @@ -2150,7 +2150,7 @@ void MPU6050_Base::setSlaveOutputByte(uint8_t num, uint8_t data) { * @see MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT */ bool MPU6050_Base::getExternalShadowDelayEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set external data shadow delay enabled status. @@ -2160,7 +2160,7 @@ bool MPU6050_Base::getExternalShadowDelayEnabled() { * @see MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT */ void MPU6050_Base::setExternalShadowDelayEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT, enabled, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT, enabled); } /** Get slave delay enabled status. * When a particular slave delay is enabled, the rate of access for the that @@ -2183,7 +2183,7 @@ void MPU6050_Base::setExternalShadowDelayEnabled(bool enabled) { bool MPU6050_Base::getSlaveDelayEnabled(uint8_t num) { // MPU6050_DELAYCTRL_I2C_SLV4_DLY_EN_BIT is 4, SLV3 is 3, etc. if (num > 4) return 0; - I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, num, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, num, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set slave delay enabled status. @@ -2193,7 +2193,7 @@ bool MPU6050_Base::getSlaveDelayEnabled(uint8_t num) { * @see MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT */ void MPU6050_Base::setSlaveDelayEnabled(uint8_t num, bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, num, enabled, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_I2C_MST_DELAY_CTRL, num, enabled); } // SIGNAL_PATH_RESET register @@ -2205,7 +2205,7 @@ void MPU6050_Base::setSlaveDelayEnabled(uint8_t num, bool enabled) { * @see MPU6050_PATHRESET_GYRO_RESET_BIT */ void MPU6050_Base::resetGyroscopePath() { - I2Cdev::writeBit(devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_GYRO_RESET_BIT, true, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_GYRO_RESET_BIT, true); } /** Reset accelerometer signal path. * The reset will revert the signal path analog to digital converters and @@ -2214,7 +2214,7 @@ void MPU6050_Base::resetGyroscopePath() { * @see MPU6050_PATHRESET_ACCEL_RESET_BIT */ void MPU6050_Base::resetAccelerometerPath() { - I2Cdev::writeBit(devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_ACCEL_RESET_BIT, true, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_ACCEL_RESET_BIT, true); } /** Reset temperature sensor signal path. * The reset will revert the signal path analog to digital converters and @@ -2223,7 +2223,7 @@ void MPU6050_Base::resetAccelerometerPath() { * @see MPU6050_PATHRESET_TEMP_RESET_BIT */ void MPU6050_Base::resetTemperaturePath() { - I2Cdev::writeBit(devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_TEMP_RESET_BIT, true, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_SIGNAL_PATH_RESET, MPU6050_PATHRESET_TEMP_RESET_BIT, true); } // MOT_DETECT_CTRL register @@ -2243,7 +2243,7 @@ void MPU6050_Base::resetTemperaturePath() { * @see MPU6050_DETECT_ACCEL_ON_DELAY_BIT */ uint8_t MPU6050_Base::getAccelerometerPowerOnDelay() { - I2Cdev::readBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_ACCEL_ON_DELAY_BIT, MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_ACCEL_ON_DELAY_BIT, MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set accelerometer power-on delay. @@ -2253,7 +2253,7 @@ uint8_t MPU6050_Base::getAccelerometerPowerOnDelay() { * @see MPU6050_DETECT_ACCEL_ON_DELAY_BIT */ void MPU6050_Base::setAccelerometerPowerOnDelay(uint8_t delay) { - I2Cdev::writeBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_ACCEL_ON_DELAY_BIT, MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH, delay, wireObj); + I2Cdev::writeBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_ACCEL_ON_DELAY_BIT, MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH, delay); } /** Get Free Fall detection counter decrement configuration. * Detection is registered by the Free Fall detection module after accelerometer @@ -2282,7 +2282,7 @@ void MPU6050_Base::setAccelerometerPowerOnDelay(uint8_t delay) { * @see MPU6050_DETECT_FF_COUNT_BIT */ uint8_t MPU6050_Base::getFreefallDetectionCounterDecrement() { - I2Cdev::readBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_FF_COUNT_BIT, MPU6050_DETECT_FF_COUNT_LENGTH, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_FF_COUNT_BIT, MPU6050_DETECT_FF_COUNT_LENGTH, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set Free Fall detection counter decrement configuration. @@ -2292,7 +2292,7 @@ uint8_t MPU6050_Base::getFreefallDetectionCounterDecrement() { * @see MPU6050_DETECT_FF_COUNT_BIT */ void MPU6050_Base::setFreefallDetectionCounterDecrement(uint8_t decrement) { - I2Cdev::writeBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_FF_COUNT_BIT, MPU6050_DETECT_FF_COUNT_LENGTH, decrement, wireObj); + I2Cdev::writeBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_FF_COUNT_BIT, MPU6050_DETECT_FF_COUNT_LENGTH, decrement); } /** Get Motion detection counter decrement configuration. * Detection is registered by the Motion detection module after accelerometer @@ -2318,7 +2318,7 @@ void MPU6050_Base::setFreefallDetectionCounterDecrement(uint8_t decrement) { * */ uint8_t MPU6050_Base::getMotionDetectionCounterDecrement() { - I2Cdev::readBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_MOT_COUNT_BIT, MPU6050_DETECT_MOT_COUNT_LENGTH, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_MOT_COUNT_BIT, MPU6050_DETECT_MOT_COUNT_LENGTH, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set Motion detection counter decrement configuration. @@ -2328,7 +2328,7 @@ uint8_t MPU6050_Base::getMotionDetectionCounterDecrement() { * @see MPU6050_DETECT_MOT_COUNT_BIT */ void MPU6050_Base::setMotionDetectionCounterDecrement(uint8_t decrement) { - I2Cdev::writeBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_MOT_COUNT_BIT, MPU6050_DETECT_MOT_COUNT_LENGTH, decrement, wireObj); + I2Cdev::writeBits(devAddr, MPU6050_RA_MOT_DETECT_CTRL, MPU6050_DETECT_MOT_COUNT_BIT, MPU6050_DETECT_MOT_COUNT_LENGTH, decrement); } // USER_CTRL register @@ -2342,7 +2342,7 @@ void MPU6050_Base::setMotionDetectionCounterDecrement(uint8_t decrement) { * @see MPU6050_USERCTRL_FIFO_EN_BIT */ bool MPU6050_Base::getFIFOEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_EN_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set FIFO enabled status. @@ -2352,7 +2352,7 @@ bool MPU6050_Base::getFIFOEnabled() { * @see MPU6050_USERCTRL_FIFO_EN_BIT */ void MPU6050_Base::setFIFOEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_EN_BIT, enabled, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_EN_BIT, enabled); } /** Get I2C Master Mode enabled status. * When this mode is enabled, the MPU-60X0 acts as the I2C Master to the @@ -2366,7 +2366,7 @@ void MPU6050_Base::setFIFOEnabled(bool enabled) { * @see MPU6050_USERCTRL_I2C_MST_EN_BIT */ bool MPU6050_Base::getI2CMasterModeEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_EN_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set I2C Master Mode enabled status. @@ -2376,14 +2376,14 @@ bool MPU6050_Base::getI2CMasterModeEnabled() { * @see MPU6050_USERCTRL_I2C_MST_EN_BIT */ void MPU6050_Base::setI2CMasterModeEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_EN_BIT, enabled, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_EN_BIT, enabled); } /** Switch from I2C to SPI mode (MPU-6000 only) * If this is set, the primary SPI interface will be enabled in place of the * disabled primary I2C interface. */ void MPU6050_Base::switchSPIEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_IF_DIS_BIT, enabled, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_IF_DIS_BIT, enabled); } /** Reset the FIFO. * This bit resets the FIFO buffer when set to 1 while FIFO_EN equals 0. This @@ -2392,7 +2392,7 @@ void MPU6050_Base::switchSPIEnabled(bool enabled) { * @see MPU6050_USERCTRL_FIFO_RESET_BIT */ void MPU6050_Base::resetFIFO() { - I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_RESET_BIT, true, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_FIFO_RESET_BIT, true); } /** Reset the I2C Master. * This bit resets the I2C Master when set to 1 while I2C_MST_EN equals 0. @@ -2401,7 +2401,7 @@ void MPU6050_Base::resetFIFO() { * @see MPU6050_USERCTRL_I2C_MST_RESET_BIT */ void MPU6050_Base::resetI2CMaster() { - I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_RESET_BIT, true, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_RESET_BIT, true); } /** Reset all sensor registers and signal paths. * When set to 1, this bit resets the signal paths for all sensors (gyroscopes, @@ -2416,7 +2416,7 @@ void MPU6050_Base::resetI2CMaster() { * @see MPU6050_USERCTRL_SIG_COND_RESET_BIT */ void MPU6050_Base::resetSensors() { - I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_SIG_COND_RESET_BIT, true, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_SIG_COND_RESET_BIT, true); } // PWR_MGMT_1 register @@ -2427,7 +2427,7 @@ void MPU6050_Base::resetSensors() { * @see MPU6050_PWR1_DEVICE_RESET_BIT */ void MPU6050_Base::reset() { - I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_DEVICE_RESET_BIT, true, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_DEVICE_RESET_BIT, true); } /** Get sleep mode status. * Setting the SLEEP bit in the register puts the device into very low power @@ -2441,7 +2441,7 @@ void MPU6050_Base::reset() { * @see MPU6050_PWR1_SLEEP_BIT */ bool MPU6050_Base::getSleepEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set sleep mode status. @@ -2451,7 +2451,7 @@ bool MPU6050_Base::getSleepEnabled() { * @see MPU6050_PWR1_SLEEP_BIT */ void MPU6050_Base::setSleepEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, enabled, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, enabled); } /** Get wake cycle enabled status. * When this bit is set to 1 and SLEEP is disabled, the MPU-60X0 will cycle @@ -2462,7 +2462,7 @@ void MPU6050_Base::setSleepEnabled(bool enabled) { * @see MPU6050_PWR1_CYCLE_BIT */ bool MPU6050_Base::getWakeCycleEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CYCLE_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CYCLE_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set wake cycle enabled status. @@ -2472,7 +2472,7 @@ bool MPU6050_Base::getWakeCycleEnabled() { * @see MPU6050_PWR1_CYCLE_BIT */ void MPU6050_Base::setWakeCycleEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CYCLE_BIT, enabled, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CYCLE_BIT, enabled); } /** Get temperature sensor enabled status. * Control the usage of the internal temperature sensor. @@ -2486,7 +2486,7 @@ void MPU6050_Base::setWakeCycleEnabled(bool enabled) { * @see MPU6050_PWR1_TEMP_DIS_BIT */ bool MPU6050_Base::getTempSensorEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_TEMP_DIS_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_TEMP_DIS_BIT, buffer, I2Cdev::readTimeout); return buffer[0] == 0; // 1 is actually disabled here } /** Set temperature sensor enabled status. @@ -2501,7 +2501,7 @@ bool MPU6050_Base::getTempSensorEnabled() { */ void MPU6050_Base::setTempSensorEnabled(bool enabled) { // 1 is actually disabled here - I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_TEMP_DIS_BIT, !enabled, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_TEMP_DIS_BIT, !enabled); } /** Get clock source setting. * @return Current clock source setting @@ -2510,7 +2510,7 @@ void MPU6050_Base::setTempSensorEnabled(bool enabled) { * @see MPU6050_PWR1_CLKSEL_LENGTH */ uint8_t MPU6050_Base::getClockSource() { - I2Cdev::readBits(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBits(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set clock source setting. @@ -2544,7 +2544,7 @@ uint8_t MPU6050_Base::getClockSource() { * @see MPU6050_PWR1_CLKSEL_LENGTH */ void MPU6050_Base::setClockSource(uint8_t source) { - I2Cdev::writeBits(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, source, wireObj); + I2Cdev::writeBits(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, source); } // PWR_MGMT_2 register @@ -2573,7 +2573,7 @@ void MPU6050_Base::setClockSource(uint8_t source) { * @see MPU6050_RA_PWR_MGMT_2 */ uint8_t MPU6050_Base::getWakeFrequency() { - I2Cdev::readBits(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_LP_WAKE_CTRL_BIT, MPU6050_PWR2_LP_WAKE_CTRL_LENGTH, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBits(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_LP_WAKE_CTRL_BIT, MPU6050_PWR2_LP_WAKE_CTRL_LENGTH, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set wake frequency in Accel-Only Low Power Mode. @@ -2581,7 +2581,7 @@ uint8_t MPU6050_Base::getWakeFrequency() { * @see MPU6050_RA_PWR_MGMT_2 */ void MPU6050_Base::setWakeFrequency(uint8_t frequency) { - I2Cdev::writeBits(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_LP_WAKE_CTRL_BIT, MPU6050_PWR2_LP_WAKE_CTRL_LENGTH, frequency, wireObj); + I2Cdev::writeBits(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_LP_WAKE_CTRL_BIT, MPU6050_PWR2_LP_WAKE_CTRL_LENGTH, frequency); } /** Get X-axis accelerometer standby enabled status. @@ -2591,7 +2591,7 @@ void MPU6050_Base::setWakeFrequency(uint8_t frequency) { * @see MPU6050_PWR2_STBY_XA_BIT */ bool MPU6050_Base::getStandbyXAccelEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XA_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XA_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set X-axis accelerometer standby enabled status. @@ -2601,7 +2601,7 @@ bool MPU6050_Base::getStandbyXAccelEnabled() { * @see MPU6050_PWR2_STBY_XA_BIT */ void MPU6050_Base::setStandbyXAccelEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XA_BIT, enabled, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XA_BIT, enabled); } /** Get Y-axis accelerometer standby enabled status. * If enabled, the Y-axis will not gather or report data (or use power). @@ -2610,7 +2610,7 @@ void MPU6050_Base::setStandbyXAccelEnabled(bool enabled) { * @see MPU6050_PWR2_STBY_YA_BIT */ bool MPU6050_Base::getStandbyYAccelEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YA_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YA_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set Y-axis accelerometer standby enabled status. @@ -2620,7 +2620,7 @@ bool MPU6050_Base::getStandbyYAccelEnabled() { * @see MPU6050_PWR2_STBY_YA_BIT */ void MPU6050_Base::setStandbyYAccelEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YA_BIT, enabled, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YA_BIT, enabled); } /** Get Z-axis accelerometer standby enabled status. * If enabled, the Z-axis will not gather or report data (or use power). @@ -2629,7 +2629,7 @@ void MPU6050_Base::setStandbyYAccelEnabled(bool enabled) { * @see MPU6050_PWR2_STBY_ZA_BIT */ bool MPU6050_Base::getStandbyZAccelEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZA_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZA_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set Z-axis accelerometer standby enabled status. @@ -2639,7 +2639,7 @@ bool MPU6050_Base::getStandbyZAccelEnabled() { * @see MPU6050_PWR2_STBY_ZA_BIT */ void MPU6050_Base::setStandbyZAccelEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZA_BIT, enabled, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZA_BIT, enabled); } /** Get X-axis gyroscope standby enabled status. * If enabled, the X-axis will not gather or report data (or use power). @@ -2648,7 +2648,7 @@ void MPU6050_Base::setStandbyZAccelEnabled(bool enabled) { * @see MPU6050_PWR2_STBY_XG_BIT */ bool MPU6050_Base::getStandbyXGyroEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XG_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XG_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set X-axis gyroscope standby enabled status. @@ -2658,7 +2658,7 @@ bool MPU6050_Base::getStandbyXGyroEnabled() { * @see MPU6050_PWR2_STBY_XG_BIT */ void MPU6050_Base::setStandbyXGyroEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XG_BIT, enabled, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_XG_BIT, enabled); } /** Get Y-axis gyroscope standby enabled status. * If enabled, the Y-axis will not gather or report data (or use power). @@ -2667,7 +2667,7 @@ void MPU6050_Base::setStandbyXGyroEnabled(bool enabled) { * @see MPU6050_PWR2_STBY_YG_BIT */ bool MPU6050_Base::getStandbyYGyroEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YG_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YG_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set Y-axis gyroscope standby enabled status. @@ -2677,7 +2677,7 @@ bool MPU6050_Base::getStandbyYGyroEnabled() { * @see MPU6050_PWR2_STBY_YG_BIT */ void MPU6050_Base::setStandbyYGyroEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YG_BIT, enabled, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_YG_BIT, enabled); } /** Get Z-axis gyroscope standby enabled status. * If enabled, the Z-axis will not gather or report data (or use power). @@ -2686,7 +2686,7 @@ void MPU6050_Base::setStandbyYGyroEnabled(bool enabled) { * @see MPU6050_PWR2_STBY_ZG_BIT */ bool MPU6050_Base::getStandbyZGyroEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZG_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZG_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set Z-axis gyroscope standby enabled status. @@ -2696,7 +2696,7 @@ bool MPU6050_Base::getStandbyZGyroEnabled() { * @see MPU6050_PWR2_STBY_ZG_BIT */ void MPU6050_Base::setStandbyZGyroEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZG_BIT, enabled, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_2, MPU6050_PWR2_STBY_ZG_BIT, enabled); } // FIFO_COUNT* registers @@ -2709,7 +2709,7 @@ void MPU6050_Base::setStandbyZGyroEnabled(bool enabled) { * @return Current FIFO buffer size */ uint16_t MPU6050_Base::getFIFOCount() { - I2Cdev::readBytes(devAddr, MPU6050_RA_FIFO_COUNTH, 2, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBytes(devAddr, MPU6050_RA_FIFO_COUNTH, 2, buffer, I2Cdev::readTimeout); return (((uint16_t)buffer[0]) << 8) | buffer[1]; } @@ -2741,12 +2741,12 @@ uint16_t MPU6050_Base::getFIFOCount() { * @return Byte from FIFO buffer */ uint8_t MPU6050_Base::getFIFOByte() { - I2Cdev::readByte(devAddr, MPU6050_RA_FIFO_R_W, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readByte(devAddr, MPU6050_RA_FIFO_R_W, buffer, I2Cdev::readTimeout); return buffer[0]; } void MPU6050_Base::getFIFOBytes(uint8_t *data, uint8_t length) { if(length > 0){ - I2Cdev::readBytes(devAddr, MPU6050_RA_FIFO_R_W, length, data, I2Cdev::readTimeout, wireObj); + I2Cdev::readBytes(devAddr, MPU6050_RA_FIFO_R_W, length, data, I2Cdev::readTimeout); } else { *data = 0; } @@ -2823,7 +2823,7 @@ static uint32_t micros() { * @see MPU6050_RA_FIFO_R_W */ void MPU6050_Base::setFIFOByte(uint8_t data) { - I2Cdev::writeByte(devAddr, MPU6050_RA_FIFO_R_W, data, wireObj); + I2Cdev::writeByte(devAddr, MPU6050_RA_FIFO_R_W, data); } // WHO_AM_I register @@ -2836,7 +2836,7 @@ void MPU6050_Base::setFIFOByte(uint8_t data) { * @see MPU6050_WHO_AM_I_LENGTH */ uint8_t MPU6050_Base::getDeviceID() { - I2Cdev::readBits(devAddr, MPU6050_RA_WHO_AM_I, MPU6050_WHO_AM_I_BIT, MPU6050_WHO_AM_I_LENGTH, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBits(devAddr, MPU6050_RA_WHO_AM_I, MPU6050_WHO_AM_I_BIT, MPU6050_WHO_AM_I_LENGTH, buffer, I2Cdev::readTimeout); return buffer[0]; } /** Set Device ID. @@ -2849,7 +2849,7 @@ uint8_t MPU6050_Base::getDeviceID() { * @see MPU6050_WHO_AM_I_LENGTH */ void MPU6050_Base::setDeviceID(uint8_t id) { - I2Cdev::writeBits(devAddr, MPU6050_RA_WHO_AM_I, MPU6050_WHO_AM_I_BIT, MPU6050_WHO_AM_I_LENGTH, id, wireObj); + I2Cdev::writeBits(devAddr, MPU6050_RA_WHO_AM_I, MPU6050_WHO_AM_I_BIT, MPU6050_WHO_AM_I_LENGTH, id); } // ======== UNDOCUMENTED/DMP REGISTERS/METHODS ======== @@ -2857,202 +2857,202 @@ void MPU6050_Base::setDeviceID(uint8_t id) { // XG_OFFS_TC register uint8_t MPU6050_Base::getOTPBankValid() { - I2Cdev::readBit(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OTP_BNK_VLD_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OTP_BNK_VLD_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } void MPU6050_Base::setOTPBankValid(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OTP_BNK_VLD_BIT, enabled, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OTP_BNK_VLD_BIT, enabled); } int8_t MPU6050_Base::getXGyroOffsetTC() { - I2Cdev::readBits(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBits(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, buffer, I2Cdev::readTimeout); return buffer[0]; } void MPU6050_Base::setXGyroOffsetTC(int8_t offset) { - I2Cdev::writeBits(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset, wireObj); + I2Cdev::writeBits(devAddr, MPU6050_RA_XG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset); } // YG_OFFS_TC register int8_t MPU6050_Base::getYGyroOffsetTC() { - I2Cdev::readBits(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBits(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, buffer, I2Cdev::readTimeout); return buffer[0]; } void MPU6050_Base::setYGyroOffsetTC(int8_t offset) { - I2Cdev::writeBits(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset, wireObj); + I2Cdev::writeBits(devAddr, MPU6050_RA_YG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset); } // ZG_OFFS_TC register int8_t MPU6050_Base::getZGyroOffsetTC() { - I2Cdev::readBits(devAddr, MPU6050_RA_ZG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBits(devAddr, MPU6050_RA_ZG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, buffer, I2Cdev::readTimeout); return buffer[0]; } void MPU6050_Base::setZGyroOffsetTC(int8_t offset) { - I2Cdev::writeBits(devAddr, MPU6050_RA_ZG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset, wireObj); + I2Cdev::writeBits(devAddr, MPU6050_RA_ZG_OFFS_TC, MPU6050_TC_OFFSET_BIT, MPU6050_TC_OFFSET_LENGTH, offset); } // X_FINE_GAIN register int8_t MPU6050_Base::getXFineGain() { - I2Cdev::readByte(devAddr, MPU6050_RA_X_FINE_GAIN, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readByte(devAddr, MPU6050_RA_X_FINE_GAIN, buffer, I2Cdev::readTimeout); return buffer[0]; } void MPU6050_Base::setXFineGain(int8_t gain) { - I2Cdev::writeByte(devAddr, MPU6050_RA_X_FINE_GAIN, gain, wireObj); + I2Cdev::writeByte(devAddr, MPU6050_RA_X_FINE_GAIN, gain); } // Y_FINE_GAIN register int8_t MPU6050_Base::getYFineGain() { - I2Cdev::readByte(devAddr, MPU6050_RA_Y_FINE_GAIN, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readByte(devAddr, MPU6050_RA_Y_FINE_GAIN, buffer, I2Cdev::readTimeout); return buffer[0]; } void MPU6050_Base::setYFineGain(int8_t gain) { - I2Cdev::writeByte(devAddr, MPU6050_RA_Y_FINE_GAIN, gain, wireObj); + I2Cdev::writeByte(devAddr, MPU6050_RA_Y_FINE_GAIN, gain); } // Z_FINE_GAIN register int8_t MPU6050_Base::getZFineGain() { - I2Cdev::readByte(devAddr, MPU6050_RA_Z_FINE_GAIN, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readByte(devAddr, MPU6050_RA_Z_FINE_GAIN, buffer, I2Cdev::readTimeout); return buffer[0]; } void MPU6050_Base::setZFineGain(int8_t gain) { - I2Cdev::writeByte(devAddr, MPU6050_RA_Z_FINE_GAIN, gain, wireObj); + I2Cdev::writeByte(devAddr, MPU6050_RA_Z_FINE_GAIN, gain); } // XA_OFFS_* registers int16_t MPU6050_Base::getXAccelOffset() { uint8_t SaveAddress = ((getDeviceID() < 0x38 )? MPU6050_RA_XA_OFFS_H:0x77); // MPU6050,MPU9150 Vs MPU6500,MPU9250 - I2Cdev::readBytes(devAddr, SaveAddress, 2, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBytes(devAddr, SaveAddress, 2, buffer, I2Cdev::readTimeout); return (((int16_t)buffer[0]) << 8) | buffer[1]; } void MPU6050_Base::setXAccelOffset(int16_t offset) { uint8_t SaveAddress = ((getDeviceID() < 0x38 )? MPU6050_RA_XA_OFFS_H:0x77); // MPU6050,MPU9150 Vs MPU6500,MPU9250 - I2Cdev::writeWord(devAddr, SaveAddress, offset, wireObj); + I2Cdev::writeWord(devAddr, SaveAddress, offset); } // YA_OFFS_* register int16_t MPU6050_Base::getYAccelOffset() { uint8_t SaveAddress = ((getDeviceID() < 0x38 )? MPU6050_RA_YA_OFFS_H:0x7A); // MPU6050,MPU9150 Vs MPU6500,MPU9250 - I2Cdev::readBytes(devAddr, SaveAddress, 2, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBytes(devAddr, SaveAddress, 2, buffer, I2Cdev::readTimeout); return (((int16_t)buffer[0]) << 8) | buffer[1]; } void MPU6050_Base::setYAccelOffset(int16_t offset) { uint8_t SaveAddress = ((getDeviceID() < 0x38 )? MPU6050_RA_YA_OFFS_H:0x7A); // MPU6050,MPU9150 Vs MPU6500,MPU9250 - I2Cdev::writeWord(devAddr, SaveAddress, offset, wireObj); + I2Cdev::writeWord(devAddr, SaveAddress, offset); } // ZA_OFFS_* register int16_t MPU6050_Base::getZAccelOffset() { uint8_t SaveAddress = ((getDeviceID() < 0x38 )? MPU6050_RA_ZA_OFFS_H:0x7D); // MPU6050,MPU9150 Vs MPU6500,MPU9250 - I2Cdev::readBytes(devAddr, SaveAddress, 2, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBytes(devAddr, SaveAddress, 2, buffer, I2Cdev::readTimeout); return (((int16_t)buffer[0]) << 8) | buffer[1]; } void MPU6050_Base::setZAccelOffset(int16_t offset) { uint8_t SaveAddress = ((getDeviceID() < 0x38 )? MPU6050_RA_ZA_OFFS_H:0x7D); // MPU6050,MPU9150 Vs MPU6500,MPU9250 - I2Cdev::writeWord(devAddr, SaveAddress, offset, wireObj); + I2Cdev::writeWord(devAddr, SaveAddress, offset); } // XG_OFFS_USR* registers int16_t MPU6050_Base::getXGyroOffset() { - I2Cdev::readBytes(devAddr, MPU6050_RA_XG_OFFS_USRH, 2, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBytes(devAddr, MPU6050_RA_XG_OFFS_USRH, 2, buffer, I2Cdev::readTimeout); return (((int16_t)buffer[0]) << 8) | buffer[1]; } void MPU6050_Base::setXGyroOffset(int16_t offset) { - I2Cdev::writeWord(devAddr, MPU6050_RA_XG_OFFS_USRH, offset, wireObj); + I2Cdev::writeWord(devAddr, MPU6050_RA_XG_OFFS_USRH, offset); } // YG_OFFS_USR* register int16_t MPU6050_Base::getYGyroOffset() { - I2Cdev::readBytes(devAddr, MPU6050_RA_YG_OFFS_USRH, 2, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBytes(devAddr, MPU6050_RA_YG_OFFS_USRH, 2, buffer, I2Cdev::readTimeout); return (((int16_t)buffer[0]) << 8) | buffer[1]; } void MPU6050_Base::setYGyroOffset(int16_t offset) { - I2Cdev::writeWord(devAddr, MPU6050_RA_YG_OFFS_USRH, offset, wireObj); + I2Cdev::writeWord(devAddr, MPU6050_RA_YG_OFFS_USRH, offset); } // ZG_OFFS_USR* register int16_t MPU6050_Base::getZGyroOffset() { - I2Cdev::readBytes(devAddr, MPU6050_RA_ZG_OFFS_USRH, 2, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBytes(devAddr, MPU6050_RA_ZG_OFFS_USRH, 2, buffer, I2Cdev::readTimeout); return (((int16_t)buffer[0]) << 8) | buffer[1]; } void MPU6050_Base::setZGyroOffset(int16_t offset) { - I2Cdev::writeWord(devAddr, MPU6050_RA_ZG_OFFS_USRH, offset, wireObj); + I2Cdev::writeWord(devAddr, MPU6050_RA_ZG_OFFS_USRH, offset); } // INT_ENABLE register (DMP functions) bool MPU6050_Base::getIntPLLReadyEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } void MPU6050_Base::setIntPLLReadyEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, enabled, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, enabled); } bool MPU6050_Base::getIntDMPEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DMP_INT_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DMP_INT_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } void MPU6050_Base::setIntDMPEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DMP_INT_BIT, enabled, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DMP_INT_BIT, enabled); } // DMP_INT_STATUS bool MPU6050_Base::getDMPInt5Status() { - I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_5_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_5_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } bool MPU6050_Base::getDMPInt4Status() { - I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_4_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_4_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } bool MPU6050_Base::getDMPInt3Status() { - I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_3_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_3_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } bool MPU6050_Base::getDMPInt2Status() { - I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_2_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_2_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } bool MPU6050_Base::getDMPInt1Status() { - I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_1_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_1_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } bool MPU6050_Base::getDMPInt0Status() { - I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_0_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_DMP_INT_STATUS, MPU6050_DMPINT_0_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } // INT_STATUS register (DMP functions) bool MPU6050_Base::getIntPLLReadyStatus() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_PLL_RDY_INT_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } bool MPU6050_Base::getIntDMPStatus() { - I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_DMP_INT_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_INT_STATUS, MPU6050_INTERRUPT_DMP_INT_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } // USER_CTRL register (DMP functions) bool MPU6050_Base::getDMPEnabled() { - I2Cdev::readBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_EN_BIT, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_EN_BIT, buffer, I2Cdev::readTimeout); return buffer[0]; } void MPU6050_Base::setDMPEnabled(bool enabled) { - I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_EN_BIT, enabled, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_EN_BIT, enabled); } void MPU6050_Base::resetDMP() { - I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_RESET_BIT, true, wireObj); + I2Cdev::writeBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_DMP_RESET_BIT, true); } // BANK_SEL register @@ -3061,23 +3061,23 @@ void MPU6050_Base::setMemoryBank(uint8_t bank, bool prefetchEnabled, bool userBa bank &= 0x1F; if (userBank) bank |= 0x20; if (prefetchEnabled) bank |= 0x40; - I2Cdev::writeByte(devAddr, MPU6050_RA_BANK_SEL, bank, wireObj); + I2Cdev::writeByte(devAddr, MPU6050_RA_BANK_SEL, bank); } // MEM_START_ADDR register void MPU6050_Base::setMemoryStartAddress(uint8_t address) { - I2Cdev::writeByte(devAddr, MPU6050_RA_MEM_START_ADDR, address, wireObj); + I2Cdev::writeByte(devAddr, MPU6050_RA_MEM_START_ADDR, address); } // MEM_R_W register uint8_t MPU6050_Base::readMemoryByte() { - I2Cdev::readByte(devAddr, MPU6050_RA_MEM_R_W, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readByte(devAddr, MPU6050_RA_MEM_R_W, buffer, I2Cdev::readTimeout); return buffer[0]; } void MPU6050_Base::writeMemoryByte(uint8_t data) { - I2Cdev::writeByte(devAddr, MPU6050_RA_MEM_R_W, data, wireObj); + I2Cdev::writeByte(devAddr, MPU6050_RA_MEM_R_W, data); } void MPU6050_Base::readMemoryBlock(uint8_t *data, uint16_t dataSize, uint8_t bank, uint8_t address) { setMemoryBank(bank); @@ -3094,7 +3094,7 @@ void MPU6050_Base::readMemoryBlock(uint8_t *data, uint16_t dataSize, uint8_t ban if (chunkSize > 256 - address) chunkSize = 256 - address; // read the chunk of data as specified - I2Cdev::readBytes(devAddr, MPU6050_RA_MEM_R_W, chunkSize, data + i, I2Cdev::readTimeout, wireObj); + I2Cdev::readBytes(devAddr, MPU6050_RA_MEM_R_W, chunkSize, data + i, I2Cdev::readTimeout); // increase byte index by [chunkSize] i += chunkSize; @@ -3138,13 +3138,13 @@ bool MPU6050_Base::writeMemoryBlock(const uint8_t *data, uint16_t dataSize, uint progBuffer = (uint8_t *)data + i; } - I2Cdev::writeBytes(devAddr, MPU6050_RA_MEM_R_W, chunkSize, progBuffer, wireObj); + I2Cdev::writeBytes(devAddr, MPU6050_RA_MEM_R_W, chunkSize, progBuffer); // verify data if needed if (verify && verifyBuffer) { setMemoryBank(bank); setMemoryStartAddress(address); - I2Cdev::readBytes(devAddr, MPU6050_RA_MEM_R_W, chunkSize, verifyBuffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readBytes(devAddr, MPU6050_RA_MEM_R_W, chunkSize, verifyBuffer, I2Cdev::readTimeout); if (memcmp(progBuffer, verifyBuffer, chunkSize) != 0) { /*Serial.print("Block write verification error, bank "); Serial.print(bank, DEC); @@ -3248,7 +3248,7 @@ bool MPU6050_Base::writeDMPConfigurationSet(const uint8_t *data, uint16_t dataSi //setIntZeroMotionEnabled(true); //setIntFIFOBufferOverflowEnabled(true); //setIntDMPEnabled(true); - I2Cdev::writeByte(devAddr, MPU6050_RA_INT_ENABLE, 0x32, wireObj); // single operation + I2Cdev::writeByte(devAddr, MPU6050_RA_INT_ENABLE, 0x32); // single operation success = true; } else { @@ -3272,21 +3272,21 @@ bool MPU6050_Base::writeProgDMPConfigurationSet(const uint8_t *data, uint16_t da // DMP_CFG_1 register uint8_t MPU6050_Base::getDMPConfig1() { - I2Cdev::readByte(devAddr, MPU6050_RA_DMP_CFG_1, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readByte(devAddr, MPU6050_RA_DMP_CFG_1, buffer, I2Cdev::readTimeout); return buffer[0]; } void MPU6050_Base::setDMPConfig1(uint8_t config) { - I2Cdev::writeByte(devAddr, MPU6050_RA_DMP_CFG_1, config, wireObj); + I2Cdev::writeByte(devAddr, MPU6050_RA_DMP_CFG_1, config); } // DMP_CFG_2 register uint8_t MPU6050_Base::getDMPConfig2() { - I2Cdev::readByte(devAddr, MPU6050_RA_DMP_CFG_2, buffer, I2Cdev::readTimeout, wireObj); + I2Cdev::readByte(devAddr, MPU6050_RA_DMP_CFG_2, buffer, I2Cdev::readTimeout); return buffer[0]; } void MPU6050_Base::setDMPConfig2(uint8_t config) { - I2Cdev::writeByte(devAddr, MPU6050_RA_DMP_CFG_2, config, wireObj); + I2Cdev::writeByte(devAddr, MPU6050_RA_DMP_CFG_2, config); } /* Replacement for Arduino map() @@ -3339,7 +3339,7 @@ void MPU6050_Base::PID(uint8_t ReadAddress, float kP,float kI, uint8_t Loops){ uint16_t gravity = 8192; // prevent uninitialized compiler warning if (ReadAddress == 0x3B) gravity = 16384 >> getFullScaleAccelRange(); for (int i = 0; i < 3; i++) { - I2Cdev::readWords(devAddr, SaveAddress + (i * shift), 1, (uint16_t *)&Data, I2Cdev::readTimeout, wireObj); // reads 1 or more 16 bit integers (Word) + I2Cdev::readWords(devAddr, SaveAddress + (i * shift), 1, (uint16_t *)&Data, I2Cdev::readTimeout); // reads 1 or more 16 bit integers (Word) Reading = Data; if(SaveAddress != 0x13){ BitZero[i] = Data & 1; // Capture Bit Zero to properly handle Accelerometer calibration @@ -3353,7 +3353,7 @@ void MPU6050_Base::PID(uint8_t ReadAddress, float kP,float kI, uint8_t Loops){ for (int c = 0; c < 100; c++) {// 100 PI Calculations eSum = 0; for (int i = 0; i < 3; i++) { - I2Cdev::readWords(devAddr, ReadAddress + (i * 2), 1, (uint16_t *)&Data, I2Cdev::readTimeout, wireObj); // reads 1 or more 16 bit integers (Word) + I2Cdev::readWords(devAddr, ReadAddress + (i * 2), 1, (uint16_t *)&Data, I2Cdev::readTimeout); // reads 1 or more 16 bit integers (Word) Reading = Data; if ((ReadAddress == 0x3B)&&(i == 2)) Reading -= gravity; //remove Gravity Error = -Reading; @@ -3364,7 +3364,7 @@ void MPU6050_Base::PID(uint8_t ReadAddress, float kP,float kI, uint8_t Loops){ Data = round((PTerm + ITerm[i] ) / 8); //Compute PID Output Data = ((Data)&0xFFFE) |BitZero[i]; // Insert Bit0 Saved at beginning } else Data = round((PTerm + ITerm[i] ) / 4); //Compute PID Output - I2Cdev::writeWords(devAddr, SaveAddress + (i * shift), 1, (uint16_t *)&Data, wireObj); + I2Cdev::writeWords(devAddr, SaveAddress + (i * shift), 1, (uint16_t *)&Data); } if((c == 99) && eSum > 1000){ // Error is still to great to continue c = 0; @@ -3380,7 +3380,7 @@ void MPU6050_Base::PID(uint8_t ReadAddress, float kP,float kI, uint8_t Loops){ Data = round((ITerm[i] ) / 8); //Compute PID Output Data = ((Data)&0xFFFE) |BitZero[i]; // Insert Bit0 Saved at beginning } else Data = round((ITerm[i]) / 4); - I2Cdev::writeWords(devAddr, SaveAddress + (i * shift), 1, (uint16_t *)&Data, wireObj); + I2Cdev::writeWords(devAddr, SaveAddress + (i * shift), 1, (uint16_t *)&Data); } } resetFIFO(); @@ -3389,13 +3389,13 @@ void MPU6050_Base::PID(uint8_t ReadAddress, float kP,float kI, uint8_t Loops){ int16_t * MPU6050_Base::GetActiveOffsets() { uint8_t AOffsetRegister = (getDeviceID() < 0x38 )? MPU6050_RA_XA_OFFS_H:0x77; - if(AOffsetRegister == 0x06) I2Cdev::readWords(devAddr, AOffsetRegister, 3, (uint16_t *)offsets, I2Cdev::readTimeout, wireObj); + if(AOffsetRegister == 0x06) I2Cdev::readWords(devAddr, AOffsetRegister, 3, (uint16_t *)offsets, I2Cdev::readTimeout); else { - I2Cdev::readWords(devAddr, AOffsetRegister, 1, (uint16_t *)offsets, I2Cdev::readTimeout, wireObj); - I2Cdev::readWords(devAddr, AOffsetRegister+3, 1, (uint16_t *)(offsets+1), I2Cdev::readTimeout, wireObj); - I2Cdev::readWords(devAddr, AOffsetRegister+6, 1, (uint16_t *)(offsets+2), I2Cdev::readTimeout, wireObj); + I2Cdev::readWords(devAddr, AOffsetRegister, 1, (uint16_t *)offsets, I2Cdev::readTimeout); + I2Cdev::readWords(devAddr, AOffsetRegister+3, 1, (uint16_t *)(offsets+1), I2Cdev::readTimeout); + I2Cdev::readWords(devAddr, AOffsetRegister+6, 1, (uint16_t *)(offsets+2), I2Cdev::readTimeout); } - I2Cdev::readWords(devAddr, 0x13, 3, (uint16_t *)(offsets+3), I2Cdev::readTimeout, wireObj); + I2Cdev::readWords(devAddr, 0x13, 3, (uint16_t *)(offsets+3), I2Cdev::readTimeout); return offsets; } diff --git a/LinuxI2CDev/MPU6050/MPU6050.h b/LinuxI2CDev/MPU6050/MPU6050.h index 7cbbb9dd..12edd61f 100644 --- a/LinuxI2CDev/MPU6050/MPU6050.h +++ b/LinuxI2CDev/MPU6050/MPU6050.h @@ -41,22 +41,6 @@ THE SOFTWARE. #include "I2Cdev.h" #include "helper_3dmath.h" -// supporting link: http://forum.arduino.cc/index.php?&topic=143444.msg1079517#msg1079517 -// also: http://forum.arduino.cc/index.php?&topic=141571.msg1062899#msg1062899s - -#ifdef __AVR__ -#include -#elif defined(ESP32) - #include -#else -//#define PROGMEM /* empty */ -//#define pgm_read_byte(x) (*(x)) -//#define pgm_read_word(x) (*(x)) -//#define pgm_read_float(x) (*(x)) -//#define PSTR(STR) STR -#endif - - #define MPU6050_ADDRESS_AD0_LOW 0x68 // address pin low (GND), default for InvenSense evaluation board #define MPU6050_ADDRESS_AD0_HIGH 0x69 // address pin high (VCC) #define MPU6050_DEFAULT_ADDRESS MPU6050_ADDRESS_AD0_LOW @@ -439,7 +423,7 @@ THE SOFTWARE. class MPU6050_Base { public: - MPU6050_Base(uint8_t address=MPU6050_DEFAULT_ADDRESS, void *wireObj=0); + MPU6050_Base(uint8_t address=MPU6050_DEFAULT_ADDRESS); void initialize(); bool testConnection(); diff --git a/LinuxI2CDev/MPU6050/MPU6050_6Axis_MotionApps20.h b/LinuxI2CDev/MPU6050/MPU6050_6Axis_MotionApps20.h index 0dc9379e..71a84667 100644 --- a/LinuxI2CDev/MPU6050/MPU6050_6Axis_MotionApps20.h +++ b/LinuxI2CDev/MPU6050/MPU6050_6Axis_MotionApps20.h @@ -45,7 +45,7 @@ THE SOFTWARE. class MPU6050_6Axis_MotionApps20 : public MPU6050_Base { public: - MPU6050_6Axis_MotionApps20(uint8_t address=MPU6050_DEFAULT_ADDRESS, void *wireObj=0) : MPU6050_Base(address, wireObj) { } + MPU6050_6Axis_MotionApps20(uint8_t address=MPU6050_DEFAULT_ADDRESS) : MPU6050_Base(address) { } uint8_t dmpInitialize(); bool dmpPacketAvailable(); From 695639381e3a6f191c363b2caddd8ce9fb0f3079 Mon Sep 17 00:00:00 2001 From: mzltn <99272834+mzltn@users.noreply.github.com> Date: Sun, 15 Dec 2024 23:37:43 +0100 Subject: [PATCH 332/335] Add driver for QMC5883L magnetometer --- STM32/QMC5883L/QMC5883L.c | 69 +++++++++++++++++++++++++++++ STM32/QMC5883L/QMC5883L.h | 91 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 160 insertions(+) create mode 100644 STM32/QMC5883L/QMC5883L.c create mode 100644 STM32/QMC5883L/QMC5883L.h diff --git a/STM32/QMC5883L/QMC5883L.c b/STM32/QMC5883L/QMC5883L.c new file mode 100644 index 00000000..e0bf2232 --- /dev/null +++ b/STM32/QMC5883L/QMC5883L.c @@ -0,0 +1,69 @@ +// I2Cdev library collection - QMC5883L I2C device class header file +// Based on QST QMC5883L datasheet 1.0, 02/2016 +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2011 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ +#include +#include + +static const uint8_t chip_addr = QMC5883L_DEFAULT_ADDR; + +bool QMC5883L_soft_reset() { + if (I2Cdev_writeByte(chip_addr, QMC5883L_REG_CTRL_2, 0x80) == 0) return false; + return true; +} + +bool QMC5883L_fbr_set(uint8_t fbr) { + if (I2Cdev_writeByte(chip_addr, QMC5883L_REG_SR_PERIOD, fbr) == 0) return false; + return true; +} + +bool QMC5883L_control_1_set(uint8_t value) { + if (I2Cdev_writeByte(chip_addr, QMC5883L_REG_CTRL_1, value) == 0) return false; + return true; +} + +bool QMC5883L_statusGet(uint8_t *data) { + if (I2Cdev_readByte(chip_addr, QMC5883L_REG_STATUS, data) == 0) return false; + return true; +} + +bool QMC5883L_magGet(int16_t *v_mag) { + uint8_t bytes[6]; + if (I2Cdev_readBytes(chip_addr, QMC5883L_REG_DATA_X_LSB, 6, bytes) == 0) return false; + + v_mag[0] = (((uint16_t)bytes[1]) << 8) | bytes[0]; + v_mag[1] = (((uint16_t)bytes[3]) << 8) | bytes[2]; + v_mag[2] = (((uint16_t)bytes[5]) << 8) | bytes[4]; + + return true; +} + +bool QMC5883L_tempGet(int16_t *temp) { + uint8_t bytes[2]; + if (I2Cdev_readBytes(chip_addr, QMC5883L_REG_TEMP_LSB, 2, bytes) == 0) return false; + + *temp = (((uint16_t)bytes[1]) << 8) | bytes[0]; + + return true; +} diff --git a/STM32/QMC5883L/QMC5883L.h b/STM32/QMC5883L/QMC5883L.h new file mode 100644 index 00000000..db929656 --- /dev/null +++ b/STM32/QMC5883L/QMC5883L.h @@ -0,0 +1,91 @@ +// I2Cdev library collection - QMC5883L I2C device class header file +// Based on QST QMC5883L datasheet 1.0, 02/2016 +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2011 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +=============================================== +*/ + +#ifndef _QMC5883L_H_ +#define _QMC5883L_H_ + +#include +#include + +#define QMC5883L_DEFAULT_ADDR 0x0D + +/* register addresses */ +#define QMC5883L_REG_DATA_X_LSB 0x00 +#define QMC5883L_REG_DATA_X_MSB 0x01 +#define QMC5883L_REG_DATA_Y_LSB 0x02 +#define QMC5883L_REG_DATA_Y_MSB 0x03 +#define QMC5883L_REG_DATA_Z_LSB 0x04 +#define QMC5883L_REG_DATA_Z_MSB 0x05 +#define QMC5883L_REG_STATUS 0x06 +#define QMC5883L_REG_TEMP_LSB 0x07 +#define QMC5883L_REG_TEMP_MSB 0x08 +#define QMC5883L_REG_CTRL_1 0x09 +#define QMC5883L_REG_CTRL_2 0x0A +#define QMC5883L_REG_SR_PERIOD 0x0B + +/* values for control_1 register */ +#define QMC5883L_OVERSAMPLE_512 0b00 +#define QMC5883L_OVERSAMPLE_256 0b01 +#define QMC5883L_OVERSAMPLE_128 0b10 +#define QMC5883L_OVERSAMPLE_64 0b11 + +#define QMC5883L_SCALE_2G 0b00 +#define QMC5883L_SCALE_8G 0b01 + +#define QMC5883L_OUTPUT_RATE_10HZ 0b00 +#define QMC5883L_OUTPUT_RATE_50HZ 0b01 +#define QMC5883L_OUTPUT_RATE_100HZ 0b10 +#define QMC5883L_OUTPUT_RATE_200HZ 0b11 + +#define QMC5883L_MODE_STBY 0b00 +#define QMC5883L_MODE_CONT 0b01 + +#define QMC5883L_CTRL1_VALUE(_mode_, _output_rate_, _scale_, _oversample_) \ + ((_mode_) | ((_output_rate_) << 2) | ((_scale_) << 4) | ((_oversample_) << 6)) + +/* QMC5883L_soft_reset: does a soft reset */ +bool QMC5883L_soft_reset(); + +/* QMC5883L_fbr_set: SET/RESET Period FBR; recommended value: 1 */ +bool QMC5883L_fbr_set(uint8_t fbr); + +/* QMC5883L_control_1_set: set value for control register (mode, output rate, scale, oversampling) */ +bool QMC5883L_control_1_set(uint8_t value); + +bool QMC5883L_statusGet(uint8_t *data); + +/* QMC5883L_magGet: + * parameters: + * v_mag: int16_t array of length 3 + * returns: + * success: true + * failure: false + */ +bool QMC5883L_magGet(int16_t *v_mag); + +bool QMC5883L_tempGet(int16_t *temp); + +#endif From 4ee3e3c12ed864c4838728b7574397c1de3961fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hasan=20F=C4=B1rat=20Keskin?= <52783312+spacemonochrome@users.noreply.github.com> Date: Mon, 28 Apr 2025 00:18:24 +0300 Subject: [PATCH 333/335] Update I2Cdev.h For Build Error --- STM32HAL/I2Cdev/I2Cdev.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/STM32HAL/I2Cdev/I2Cdev.h b/STM32HAL/I2Cdev/I2Cdev.h index 330a92fc..4302a63f 100644 --- a/STM32HAL/I2Cdev/I2Cdev.h +++ b/STM32HAL/I2Cdev/I2Cdev.h @@ -47,7 +47,7 @@ typedef int bool; #define true 1 #define false 0 -uint16_t I2Cdev_readTimeout; +extern uint16_t I2Cdev_readTimeout; // 1000ms default read timeout (modify with "I2Cdev::readTimeout = [ms];") #define I2CDEV_DEFAULT_READ_TIMEOUT 1000 From 2adfb3b2852910fe83c95e487505a6c7956ecffe Mon Sep 17 00:00:00 2001 From: Nathan Lewis Date: Sat, 14 Jun 2025 20:56:42 -0700 Subject: [PATCH 334/335] RP2040: Fix paths in CMakeLists.txt, add example build dirs to gitignore --- .gitignore | 4 +++- RP2040/MPU6050/examples/mpu6050_DMP_V6.12/CMakeLists.txt | 9 +++++++-- .../MPU6050/examples/mpu6050_calibration/CMakeLists.txt | 9 +++++++-- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index b377ff6d..599cc1a3 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,6 @@ PIC18/MPU6050/Examples/MPU6050_raw.X/build/ /dsPIC30F/MPU6050/Examples/MPU6050_example.X/build/default/ /dsPIC30F/MPU6050/Examples/MPU6050_example.X/dist/default/ ESP32_ESP-IDF/build/ -ESP32_ESP-IDF/sdkconfig \ No newline at end of file +ESP32_ESP-IDF/sdkconfig +/RP2040/MPU6050/examples/mpu6050_calibration +/RP2040/MPU6050/examples/mpu6050_DMP_V6.12 diff --git a/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/CMakeLists.txt b/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/CMakeLists.txt index 8214ca67..41f24dec 100644 --- a/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/CMakeLists.txt +++ b/RP2040/MPU6050/examples/mpu6050_DMP_V6.12/CMakeLists.txt @@ -17,8 +17,13 @@ pico_sdk_init() add_executable(mpu6050_DMP_port mpu6050_DMP_port.cpp - MPU6050.cpp - I2Cdev.cpp + ../../MPU6050.cpp + ../../../I2Cdev/I2Cdev.cpp + ) + +target_include_directories(mpu6050_DMP_port PRIVATE + ${CMAKE_CURRENT_LIST_DIR}/../../ + ${CMAKE_CURRENT_LIST_DIR}/../../../I2Cdev ) # Add any user requested libraries diff --git a/RP2040/MPU6050/examples/mpu6050_calibration/CMakeLists.txt b/RP2040/MPU6050/examples/mpu6050_calibration/CMakeLists.txt index 7429697e..da6892d3 100644 --- a/RP2040/MPU6050/examples/mpu6050_calibration/CMakeLists.txt +++ b/RP2040/MPU6050/examples/mpu6050_calibration/CMakeLists.txt @@ -17,8 +17,13 @@ pico_sdk_init() add_executable( mpu6050_calibration mpu6050_calibration.cpp - MPU6050.cpp - I2Cdev.cpp + ../../MPU6050.cpp + ../../../I2Cdev/I2Cdev.cpp + ) + +target_include_directories(mpu6050_calibration PRIVATE + ${CMAKE_CURRENT_LIST_DIR}/../../ + ${CMAKE_CURRENT_LIST_DIR}/../../../I2Cdev ) # Add any user requested libraries From 7e787fe83f896d3e2446f3da6d36258edc387610 Mon Sep 17 00:00:00 2001 From: Sudarshan Patil <91423165+OptifySudarshanPatil@users.noreply.github.com> Date: Mon, 4 Aug 2025 17:17:11 +0530 Subject: [PATCH 335/335] Added read_register for AD7746 --- Arduino/AD7746/AD7746.cpp | 4 ++++ Arduino/AD7746/AD7746.h | 1 + 2 files changed, 5 insertions(+) diff --git a/Arduino/AD7746/AD7746.cpp b/Arduino/AD7746/AD7746.cpp index dd019a59..53efa828 100755 --- a/Arduino/AD7746/AD7746.cpp +++ b/Arduino/AD7746/AD7746.cpp @@ -136,3 +136,7 @@ void AD7746::writeCapDacBRegister(uint8_t data) { void AD7746::write_register(uint8_t addr,uint8_t data) { I2Cdev::writeByte(devAddr, addr, data); } + +void AD7746::read_register(uint8_t addr, uint8_t *data) { + I2Cdev::readByte(devAddr, addr, data); +} diff --git a/Arduino/AD7746/AD7746.h b/Arduino/AD7746/AD7746.h index 6b69f254..5ca3f112 100755 --- a/Arduino/AD7746/AD7746.h +++ b/Arduino/AD7746/AD7746.h @@ -177,6 +177,7 @@ class AD7746 { void writeCapDacARegister(uint8_t data); void writeCapDacBRegister(uint8_t data); void write_register(uint8_t addr,uint8_t data); + void read_register(uint8_t addr, uint8_t *data); private: