mbed implementation of the FreeIMU IMU for HobbyKing's 10DOF board

Dependents:   testHK10DOF

Files at this revision

API Documentation at this revision

Comitter:
pommzorz
Date:
Wed Jul 17 18:50:28 2013 +0000
Child:
1:85fcfcb7b137
Commit message:
mbed implementation of the FreeIMU imu for the HobbyKing 10DOF board

Changed in this revision

ADXL345_I2C.cpp Show annotated file Show diff for this revision Revisions of this file
ADXL345_I2C.h Show annotated file Show diff for this revision Revisions of this file
BMP085.cpp Show annotated file Show diff for this revision Revisions of this file
BMP085.h Show annotated file Show diff for this revision Revisions of this file
HK10DOF.cpp Show annotated file Show diff for this revision Revisions of this file
HK10DOF.h Show annotated file Show diff for this revision Revisions of this file
HMC5883L.cpp Show annotated file Show diff for this revision Revisions of this file
HMC5883L.h Show annotated file Show diff for this revision Revisions of this file
L3G4200D.cpp Show annotated file Show diff for this revision Revisions of this file
L3G4200D.h Show annotated file Show diff for this revision Revisions of this file
helper_3dmath.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ADXL345_I2C.cpp	Wed Jul 17 18:50:28 2013 +0000
@@ -0,0 +1,447 @@
+/**
+ * @author Peter Swanson
+ * A personal note from me: Jesus Christ has changed my life so much it blows my mind. I say this because
+ *                  today, religion is thought of as something that you do or believe and has about as
+ *                  little impact on a person as their political stance. But for me, God gives me daily
+ *                  strength and has filled my life with the satisfaction that I could never find in any
+ *                  of the other things that I once looked for it in. 
+ * If your interested, heres verse that changed my life:
+ *      Rom 8:1-3: "Therefore, there is now no condemnation for those who are in Christ Jesus,
+ *                  because through Christ Jesus, the law of the Spirit who gives life has set
+ *                  me free from the law of sin (which brings...) and death. For what the law 
+ *                  was powerless to do in that it was weakened by the flesh, God did by sending
+ *                  His own Son in the likeness of sinful flesh to be a sin offering. And so He
+ *                  condemned sin in the flesh in order that the righteous requirements of the 
+ *                  (God's) law might be fully met in us, who live not according to the flesh
+ *                  but according to the Spirit."
+ *
+ *  A special thanks to Ewout van Bekkum for all his patient help in developing this library!
+ *
+ * @section 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.
+ *
+ * @section DESCRIPTION
+ *
+ * ADXL345, triple axis, I2C interface, accelerometer.
+ *
+ * Datasheet:
+ *
+ * http://www.analog.com/static/imported-files/data_sheets/ADXL345.pdf
+ */  
+ 
+/**
+ * Includes
+ */
+#include "ADXL345_I2C.h"
+
+//#include "mbed.h"
+
+ADXL345_I2C::ADXL345_I2C(PinName sda, PinName scl) : i2c_(sda, scl) {
+
+    //400kHz, allowing us to use the fastest data rates.
+    i2c_.frequency(400000); //400000  
+// initialize the BW data rate
+    char tx[2];
+    tx[0] = ADXL345_BW_RATE_REG;
+    tx[1] = ADXL345_1600HZ; //value greater than or equal to 0x0A is written into the rate bits (Bit D3 through Bit D0) in the BW_RATE register 
+ i2c_.write( ADXL345_I2C_WRITE , tx, 2);  
+
+//Data format (for +-16g) - This is done by setting Bit D3 of the DATA_FORMAT register (Address 0x31) and writing a value of 0x03 to the range bits (Bit D1 and Bit D0) of the DATA_FORMAT register (Address 0x31).
+   
+ char rx[2];
+    rx[0] = ADXL345_DATA_FORMAT_REG;
+    rx[1] = 0x0B; 
+     // full res and +_16g
+ i2c_.write( ADXL345_I2C_WRITE , rx, 2); 
+ 
+ // Set Offset  - programmed into the OFSX, OFSY, and OFXZ registers, respectively, as 0xFD, 0x03 and 0xFE.
+  char x[2];
+    x[0] = ADXL345_OFSX_REG ;
+    x[1] = 0xFD; 
+ i2c_.write( ADXL345_I2C_WRITE , x, 2);
+  char y[2];
+    y[0] = ADXL345_OFSY_REG ;
+    y[1] = 0x03; 
+ i2c_.write( ADXL345_I2C_WRITE , y, 2);
+ char z[2];
+    z[0] = ADXL345_OFSZ_REG ;
+    z[1] = 0xFE; 
+ i2c_.write( ADXL345_I2C_WRITE , z, 2);
+}
+
+
+char ADXL345_I2C::SingleByteRead(char address){   
+   char tx = address;
+   char output; 
+    i2c_.write( ADXL345_I2C_WRITE , &tx, 1);  //tell it what you want to read
+    i2c_.read( ADXL345_I2C_READ , &output, 1);    //tell it where to store the data
+    return output;
+  
+}
+
+
+/*
+***info on the i2c_.write***
+address     8-bit I2C slave address [ addr | 0 ]
+data        Pointer to the byte-array data to send
+length        Number of bytes to send
+repeated    Repeated start, true - do not send stop at end
+returns     0 on success (ack), or non-0 on failure (nack)
+*/
+
+int ADXL345_I2C::SingleByteWrite(char address, char data){ 
+   int ack = 0;
+   char tx[2];
+   tx[0] = address;
+   tx[1] = data;
+   return   ack | i2c_.write( ADXL345_I2C_WRITE , tx, 2);   
+}
+
+
+
+void ADXL345_I2C::multiByteRead(char address, char* output, int size) {
+    i2c_.write( ADXL345_I2C_WRITE, &address, 1);  //tell it where to read from
+    i2c_.read( ADXL345_I2C_READ , output, size);      //tell it where to store the data read
+}
+
+
+int ADXL345_I2C::multiByteWrite(char address, char* ptr_data, int size) {
+        int ack;
+   
+               ack = i2c_.write( ADXL345_I2C_WRITE, &address, 1);  //tell it where to write to
+        return ack | i2c_.write( ADXL345_I2C_READ, ptr_data, size);  //tell it what data to write
+                                    
+}
+
+
+void ADXL345_I2C::getOutput(int16_t* readings){
+    char buffer[6];    
+    multiByteRead(ADXL345_DATAX0_REG, buffer, 6);
+    
+    readings[0] = (int)buffer[1] << 8 | (int)buffer[0];
+    readings[1] = (int)buffer[3] << 8 | (int)buffer[2];
+    readings[2] = (int)buffer[5] << 8 | (int)buffer[4];
+
+}
+
+/*
+
+void ADXL345_I2C::getOutput(int* readings){
+    char buffer[6];    
+    multiByteRead(ADXL345_DATAX0_REG, buffer, 6);
+    
+    readings[0] = (int)buffer[1] << 8 | (int)buffer[0];
+    readings[1] = (int)buffer[3] << 8 | (int)buffer[2];
+    readings[2] = (int)buffer[5] << 8 | (int)buffer[4];
+
+}
+*/
+
+void ADXL345_I2C::getOutput(int16_t* x, int16_t* y, int16_t* z) {
+  int16_t *readings;
+  getOutput(readings);
+
+  // each axis reading comes in 10 bit resolution, ie 2 bytes.  Least Significat Byte first!!
+  // thus we are converting both bytes in to one int
+  *x = readings[0];  
+  *y = readings[1]; 
+  *z = readings[2]; 
+}
+
+
+char ADXL345_I2C::getDeviceID() {  
+    return SingleByteRead(ADXL345_DEVID_REG);
+    }
+//
+int ADXL345_I2C::setPowerMode(char mode) { 
+
+    //Get the current register contents, so we don't clobber the rate value.
+    char registerContents = (mode << 4) | SingleByteRead(ADXL345_BW_RATE_REG);
+
+   return SingleByteWrite(ADXL345_BW_RATE_REG, registerContents);
+
+}
+
+char ADXL345_I2C::getPowerControl() {    
+    return SingleByteRead(ADXL345_POWER_CTL_REG);
+}
+
+int ADXL345_I2C::setPowerControl(char settings) {    
+    return SingleByteWrite(ADXL345_POWER_CTL_REG, settings);
+
+}
+
+
+
+char ADXL345_I2C::getDataFormatControl(void){
+
+    return SingleByteRead(ADXL345_DATA_FORMAT_REG);
+}
+
+int ADXL345_I2C::setDataFormatControl(char settings){
+
+   return SingleByteWrite(ADXL345_DATA_FORMAT_REG, settings);
+    
+}
+
+int ADXL345_I2C::setDataRate(char rate) {
+
+    //Get the current register contents, so we don't clobber the power bit.
+    char registerContents = SingleByteRead(ADXL345_BW_RATE_REG);
+
+    registerContents &= 0x10;
+    registerContents |= rate;
+
+    return SingleByteWrite(ADXL345_BW_RATE_REG, registerContents);
+
+}
+
+
+char ADXL345_I2C::getOffset(char axis) {     
+
+    char address = 0;
+
+    if (axis == ADXL345_X) {
+        address = ADXL345_OFSX_REG;
+    } else if (axis == ADXL345_Y) {
+        address = ADXL345_OFSY_REG;
+    } else if (axis == ADXL345_Z) {
+        address = ADXL345_OFSZ_REG;
+    }
+
+   return SingleByteRead(address);
+}
+
+int ADXL345_I2C::setOffset(char axis, char offset) {        
+
+    char address = 0;
+
+    if (axis == ADXL345_X) {
+        address = ADXL345_OFSX_REG;
+    } else if (axis == ADXL345_Y) {
+        address = ADXL345_OFSY_REG;
+    } else if (axis == ADXL345_Z) {
+        address = ADXL345_OFSZ_REG;
+    }
+
+   return SingleByteWrite(address, offset);
+
+}
+
+
+char ADXL345_I2C::getFifoControl(void){
+
+    return SingleByteRead(ADXL345_FIFO_CTL);
+
+}
+
+int ADXL345_I2C::setFifoControl(char settings){
+   return SingleByteWrite(ADXL345_FIFO_STATUS, settings);
+
+}
+
+char ADXL345_I2C::getFifoStatus(void){
+
+    return SingleByteRead(ADXL345_FIFO_STATUS);
+
+}
+
+
+
+char ADXL345_I2C::getTapThreshold(void) {
+
+    return SingleByteRead(ADXL345_THRESH_TAP_REG);
+}
+
+int ADXL345_I2C::setTapThreshold(char threshold) {   
+
+   return SingleByteWrite(ADXL345_THRESH_TAP_REG, threshold);
+
+}
+
+
+float ADXL345_I2C::getTapDuration(void) {     
+
+    return (float)SingleByteRead(ADXL345_DUR_REG)*625;
+}
+
+int ADXL345_I2C::setTapDuration(short int duration_us) {
+
+    short int tapDuration = duration_us / 625;
+    char tapChar[2];
+     tapChar[0] = (tapDuration & 0x00FF);
+     tapChar[1] = (tapDuration >> 8) & 0x00FF;
+    return multiByteWrite(ADXL345_DUR_REG, tapChar, 2);
+
+}
+
+float ADXL345_I2C::getTapLatency(void) {
+
+    return (float)SingleByteRead(ADXL345_LATENT_REG)*1.25;
+}
+
+int ADXL345_I2C::setTapLatency(short int latency_ms) {
+
+    latency_ms = latency_ms / 1.25;
+    char latChar[2];
+     latChar[0] = (latency_ms & 0x00FF);
+     latChar[1] = (latency_ms << 8) & 0xFF00;
+    return multiByteWrite(ADXL345_LATENT_REG, latChar, 2);
+
+}
+
+float ADXL345_I2C::getWindowTime(void) {
+
+    return (float)SingleByteRead(ADXL345_WINDOW_REG)*1.25;
+}
+
+int ADXL345_I2C::setWindowTime(short int window_ms) {
+
+    window_ms = window_ms / 1.25;
+    char windowChar[2];
+    windowChar[0] = (window_ms & 0x00FF);
+    windowChar[1] = ((window_ms << 8) & 0xFF00);
+   return multiByteWrite(ADXL345_WINDOW_REG, windowChar, 2);
+
+}
+
+char ADXL345_I2C::getActivityThreshold(void) {
+
+    return SingleByteRead(ADXL345_THRESH_ACT_REG);
+}
+
+int ADXL345_I2C::setActivityThreshold(char threshold) {
+    return SingleByteWrite(ADXL345_THRESH_ACT_REG, threshold);
+
+}
+
+char ADXL345_I2C::getInactivityThreshold(void) {
+    return SingleByteRead(ADXL345_THRESH_INACT_REG);
+       
+}
+
+//int FUNCTION(short int * ptr_Output)
+//short int FUNCTION ()
+
+int ADXL345_I2C::setInactivityThreshold(char threshold) {
+    return SingleByteWrite(ADXL345_THRESH_INACT_REG, threshold);
+
+}
+
+char ADXL345_I2C::getTimeInactivity(void) {
+
+    return SingleByteRead(ADXL345_TIME_INACT_REG);
+
+}
+
+int ADXL345_I2C::setTimeInactivity(char timeInactivity) {
+    return SingleByteWrite(ADXL345_TIME_INACT_REG, timeInactivity);
+
+}
+
+char ADXL345_I2C::getActivityInactivityControl(void) {
+
+    return SingleByteRead(ADXL345_ACT_INACT_CTL_REG);
+
+}
+
+int ADXL345_I2C::setActivityInactivityControl(char settings) {
+    return SingleByteWrite(ADXL345_ACT_INACT_CTL_REG, settings);
+    
+}
+
+char ADXL345_I2C::getFreefallThreshold(void) {
+
+    return SingleByteRead(ADXL345_THRESH_FF_REG);
+
+}
+
+int ADXL345_I2C::setFreefallThreshold(char threshold) {
+   return SingleByteWrite(ADXL345_THRESH_FF_REG, threshold);
+
+}
+
+char ADXL345_I2C::getFreefallTime(void) {
+
+    return SingleByteRead(ADXL345_TIME_FF_REG)*5;
+
+}
+
+int ADXL345_I2C::setFreefallTime(short int freefallTime_ms) {
+     freefallTime_ms = freefallTime_ms / 5;
+     char fallChar[2];
+     fallChar[0] = (freefallTime_ms & 0x00FF);
+     fallChar[1] = (freefallTime_ms << 8) & 0xFF00;
+    
+    return multiByteWrite(ADXL345_TIME_FF_REG, fallChar, 2);
+
+}
+
+char ADXL345_I2C::getTapAxisControl(void) {
+
+    return SingleByteRead(ADXL345_TAP_AXES_REG);
+
+}
+
+int ADXL345_I2C::setTapAxisControl(char settings) {
+   return SingleByteWrite(ADXL345_TAP_AXES_REG, settings);
+
+}
+
+char ADXL345_I2C::getTapSource(void) {
+
+    return SingleByteRead(ADXL345_ACT_TAP_STATUS_REG);
+
+}
+
+
+
+char ADXL345_I2C::getInterruptEnableControl(void) {
+
+    return SingleByteRead(ADXL345_INT_ENABLE_REG);
+
+}
+
+int ADXL345_I2C::setInterruptEnableControl(char settings) {
+   return SingleByteWrite(ADXL345_INT_ENABLE_REG, settings);
+
+}
+
+char ADXL345_I2C::getInterruptMappingControl(void) {
+
+    return SingleByteRead(ADXL345_INT_MAP_REG);
+
+}
+
+int ADXL345_I2C::setInterruptMappingControl(char settings) {
+    return SingleByteWrite(ADXL345_INT_MAP_REG, settings);
+
+}
+
+char ADXL345_I2C::getInterruptSource(void){
+
+    return SingleByteRead(ADXL345_INT_SOURCE_REG);
+
+}
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ADXL345_I2C.h	Wed Jul 17 18:50:28 2013 +0000
@@ -0,0 +1,579 @@
+/**
+ * @author Peter Swanson
+ * A personal note from me: Jesus Christ has changed my life so much it blows my mind. I say this because
+ *                  today, religion is thought of as something that you do or believe and has about as
+ *                  little impact on a person as their political stance. But for me, God gives me daily
+ *                  strength and has filled my life with the satisfaction that I could never find in any
+ *                  of the other things that I once looked for it in. 
+ * If your interested, heres verse that changed my life:
+ *      Rom 8:1-3: "Therefore, there is now no condemnation for those who are in Christ Jesus,
+ *                  because through Christ Jesus, the law of the Spirit who gives life has set
+ *                  me free from the law of sin (which brings...) and death. For what the law 
+ *                  was powerless to do in that it was weakened by the flesh, God did by sending
+ *                  His own Son in the likeness of sinful flesh to be a sin offering. And so He
+ *                  condemned sin in the flesh in order that the righteous requirements of the 
+ *                  (God's) law might be fully met in us, who live not according to the flesh
+ *                  but according to the Spirit."
+ *
+ *  A special thanks to Ewout van Bekkum for all his patient help in developing this library!
+ *
+ * @section 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.
+ *
+ * @section DESCRIPTION
+ *
+ * ADXL345, triple axis, I2C interface, accelerometer.
+ *
+ * Datasheet:
+ *
+ * http://www.analog.com/static/imported-files/data_sheets/ADXL345.pdf
+ */  
+
+
+
+#ifndef ADXL345_I2C_H
+#define ADXL345_I2C_H
+
+/**
+ * Includes
+ */
+#include "mbed.h"
+
+/**
+ * Defines
+ */
+//Registers.
+#define ADXL345_DEVID_REG          0x00
+#define ADXL345_THRESH_TAP_REG     0x1D
+#define ADXL345_OFSX_REG           0x1E
+#define ADXL345_OFSY_REG           0x1F
+#define ADXL345_OFSZ_REG           0x20
+#define ADXL345_DUR_REG            0x21
+#define ADXL345_LATENT_REG         0x22
+#define ADXL345_WINDOW_REG         0x23
+#define ADXL345_THRESH_ACT_REG     0x24
+#define ADXL345_THRESH_INACT_REG   0x25
+#define ADXL345_TIME_INACT_REG     0x26
+#define ADXL345_ACT_INACT_CTL_REG  0x27
+#define ADXL345_THRESH_FF_REG      0x28
+#define ADXL345_TIME_FF_REG        0x29
+#define ADXL345_TAP_AXES_REG       0x2A
+#define ADXL345_ACT_TAP_STATUS_REG 0x2B
+#define ADXL345_BW_RATE_REG        0x2C
+#define ADXL345_POWER_CTL_REG      0x2D
+#define ADXL345_INT_ENABLE_REG     0x2E
+#define ADXL345_INT_MAP_REG        0x2F
+#define ADXL345_INT_SOURCE_REG     0x30
+#define ADXL345_DATA_FORMAT_REG    0x31
+#define ADXL345_DATAX0_REG         0x32
+#define ADXL345_DATAX1_REG         0x33
+#define ADXL345_DATAY0_REG         0x34
+#define ADXL345_DATAY1_REG         0x35
+#define ADXL345_DATAZ0_REG         0x36
+#define ADXL345_DATAZ1_REG         0x37
+#define ADXL345_FIFO_CTL           0x38
+#define ADXL345_FIFO_STATUS        0x39
+
+//Data rate codes.
+#define ADXL345_3200HZ      0x0F
+#define ADXL345_1600HZ      0x0E
+#define ADXL345_800HZ       0x0D
+#define ADXL345_400HZ       0x0C
+#define ADXL345_200HZ       0x0B
+#define ADXL345_100HZ       0x0A
+#define ADXL345_50HZ        0x09
+#define ADXL345_25HZ        0x08
+#define ADXL345_12HZ5       0x07
+#define ADXL345_6HZ25       0x06
+
+// read or write bytes
+#define ADXL345_I2C_READ    0xA7  
+#define ADXL345_I2C_WRITE   0xA6 
+#define ADXL345_I2C_ADDRESS 0x53   //the ADXL345 7-bit address is 0x53 when ALT ADDRESS is low as it is on the sparkfun chip: when ALT ADDRESS is high the address is 0x1D
+
+/////////////when ALT ADDRESS pin is high:
+//#define ADXL345_I2C_READ    0x3B   
+//#define ADXL345_I2C_WRITE   0x3A
+//#define ADXL345_I2C_ADDRESS 0x1D 
+
+#define ADXL345_X           0x00
+#define ADXL345_Y           0x01
+#define ADXL345_Z           0x02
+
+
+
+// modes
+#define MeasurementMode     0x08
+
+
+
+
+
+
+
+class ADXL345_I2C {
+
+public:
+
+    /**
+     * Constructor.
+     *
+     * @param mosi mbed pin to use for SDA line of I2C interface.
+     * @param sck mbed pin to use for SCL line of I2C interface.
+     */
+    ADXL345_I2C(PinName sda, PinName scl);
+
+    /**
+     * Get the output of all three axes.
+     *
+     * @param Pointer to a buffer to hold the accelerometer value for the
+     *        x-axis, y-axis and z-axis [in that order].
+     */
+    void getOutput(int16_t* readings);
+    void getOutput(int16_t* x, int16_t* y, int16_t* z);
+
+    /**
+     * Read the device ID register on the device.
+     *
+     * @return The device ID code [0xE5]
+     */
+    char getDeviceID(void);
+
+
+    
+     /**
+     * Set the power mode.
+     *
+     * @param mode 0 -> Normal operation.
+     *             1 -> Reduced power operation.
+     */     
+int setPowerMode(char mode);
+  
+     /**
+     * Set the power control settings.
+     *
+     * See datasheet for details.
+     *
+     * @param The control byte to write to the POWER_CTL register.
+     */
+ int setPowerControl(char settings);     
+      /**
+     * Get the power control settings.
+     *
+     * See datasheet for details.
+     *
+     * @return The contents of the POWER_CTL register.
+     */
+    char getPowerControl(void);
+
+       
+    /**
+     * Get the data format settings.
+     *
+     * @return The contents of the DATA_FORMAT register.
+     */
+     
+    char getDataFormatControl(void);
+    
+    /**
+     * Set the data format settings.
+     *
+     * @param settings The control byte to write to the DATA_FORMAT register.
+     */
+    int setDataFormatControl(char settings);
+  
+       /**
+     * Set the data rate.
+     *
+     * @param rate The rate code (see #defines or datasheet).
+     */
+    int setDataRate(char rate);
+    
+
+       /**
+     * Get the current offset for a particular axis.
+     *
+     * @param axis 0x00 -> X-axis
+     *             0x01 -> Y-axis
+     *             0x02 -> Z-axis
+     * @return The current offset as an 8-bit 2's complement number with scale
+     *         factor 15.6mg/LSB.
+     */
+     
+       char getOffset(char axis);
+
+    /**
+     * Set the offset for a particular axis.
+     *
+     * @param axis 0x00 -> X-axis
+     *             0x01 -> Y-axis
+     *             0x02 -> Z-axis
+     * @param offset The offset as an 8-bit 2's complement number with scale
+     *               factor 15.6mg/LSB.
+     */
+    int setOffset(char axis, char offset);
+
+
+    
+    /**
+     * Get the FIFO control settings.
+     *
+     * @return The contents of the FIFO_CTL register.
+     */
+    char getFifoControl(void);
+    
+    /**
+     * Set the FIFO control settings.
+     *
+     * @param The control byte to write to the FIFO_CTL register.
+     */
+    int setFifoControl(char settings);
+    
+    /**
+     * Get FIFO status.
+     *
+     * @return The contents of the FIFO_STATUS register.
+     */
+    char getFifoStatus(void);
+    
+    /**
+     * Read the tap threshold on the device.
+     *
+     * @return The tap threshold as an 8-bit number with a scale factor of
+     *         62.5mg/LSB.
+     */
+    char getTapThreshold(void);
+
+    /**
+     * Set the tap threshold.
+     *
+     * @param The tap threshold as an 8-bit number with a scale factor of
+     *        62.5mg/LSB.
+     */
+    int setTapThreshold(char threshold);
+
+    /**
+     * Get the tap duration required to trigger an event.
+     *
+     * @return The max time that an event must be above the tap threshold to
+     *         qualify as a tap event, in microseconds.
+     */
+    float getTapDuration(void);
+
+    /**
+     * Set the tap duration required to trigger an event.
+     *
+     * @param duration_us The max time that an event must be above the tap
+     *                    threshold to qualify as a tap event, in microseconds.
+     *                    Time will be normalized by the scale factor which is
+     *                    625us/LSB. A value of 0 disables the single/double
+     *                    tap functions.
+     */
+    int setTapDuration(short int duration_us);
+
+    /**
+     * Get the tap latency between the detection of a tap and the time window.
+     *
+     * @return The wait time from the detection of a tap event to the start of
+     *         the time window during which a possible second tap event can be
+     *         detected in milliseconds.
+     */
+    float getTapLatency(void);
+
+    /**
+     * Set the tap latency between the detection of a tap and the time window.
+     *
+     * @param latency_ms The wait time from the detection of a tap event to the
+     *                   start of the time window during which a possible
+     *                   second tap event can be detected in milliseconds.
+     *                   A value of 0 disables the double tap function.
+     */
+    int setTapLatency(short int latency_ms);
+
+    /**
+     * Get the time of window between tap latency and a double tap.
+     *
+     * @return The amount of time after the expiration of the latency time
+     *         during which a second valid tap can begin, in milliseconds.
+     */
+    float getWindowTime(void);
+
+    /**
+     * Set the time of the window between tap latency and a double tap.
+     *
+     * @param window_ms The amount of time after the expiration of the latency
+     *                  time during which a second valid tap can begin,
+     *                  in milliseconds.
+     */
+    int setWindowTime(short int window_ms);
+
+    /**
+     * Get the threshold value for detecting activity.
+     *
+     * @return The threshold value for detecting activity as an 8-bit number.
+     *         Scale factor is 62.5mg/LSB.
+     */
+     char getActivityThreshold(void);
+
+    /**
+     * Set the threshold value for detecting activity.
+     *
+     * @param threshold The threshold value for detecting activity as an 8-bit
+     *                  number. Scale factor is 62.5mg/LSB. A value of 0 may
+     *                  result in undesirable behavior if the activity
+     *                  interrupt is enabled.
+     */
+    int setActivityThreshold(char threshold);
+
+    /**
+     * Get the threshold value for detecting inactivity.
+     *
+     * @return The threshold value for detecting inactivity as an 8-bit number.
+     *         Scale factor is 62.5mg/LSB.
+     */
+     char getInactivityThreshold(void);
+
+    /**
+     * Set the threshold value for detecting inactivity.
+     *
+     * @param threshold The threshold value for detecting inactivity as an
+     *                  8-bit number. Scale factor is 62.5mg/LSB.
+     */
+    int setInactivityThreshold(char threshold);
+
+    /**
+     * Get the time required for inactivity to be declared.
+     *
+     * @return The amount of time that acceleration must be less than the
+     *         inactivity threshold for inactivity to be declared, in
+     *         seconds.
+     */
+     char getTimeInactivity(void);
+    
+    /**
+     * Set the time required for inactivity to be declared.
+     *
+     * @param inactivity The amount of time that acceleration must be less than
+     *                   the inactivity threshold for inactivity to be
+     *                   declared, in seconds. A value of 0 results in an
+     *                   interrupt when the output data is less than the
+     *                   threshold inactivity.
+     */
+    int setTimeInactivity(char timeInactivity);
+    
+    /**
+     * Get the activity/inactivity control settings.
+     *
+     *      D7            D6             D5            D4
+     * +-----------+--------------+--------------+--------------+
+     * | ACT ac/dc | ACT_X enable | ACT_Y enable | ACT_Z enable |
+     * +-----------+--------------+--------------+--------------+
+     *
+     *        D3             D2               D1              D0
+     * +-------------+----------------+----------------+----------------+
+     * | INACT ac/dc | INACT_X enable | INACT_Y enable | INACT_Z enable |
+     * +-------------+----------------+----------------+----------------+
+     *
+     * See datasheet for details.
+     *
+     * @return The contents of the ACT_INACT_CTL register.
+     */
+     char getActivityInactivityControl(void);
+    
+    /**
+     * Set the activity/inactivity control settings.
+     *
+     *      D7            D6             D5            D4
+     * +-----------+--------------+--------------+--------------+
+     * | ACT ac/dc | ACT_X enable | ACT_Y enable | ACT_Z enable |
+     * +-----------+--------------+--------------+--------------+
+     *
+     *        D3             D2               D1              D0
+     * +-------------+----------------+----------------+----------------+
+     * | INACT ac/dc | INACT_X enable | INACT_Y enable | INACT_Z enable |
+     * +-------------+----------------+----------------+----------------+
+     *
+     * See datasheet for details.
+     *
+     * @param settings The control byte to write to the ACT_INACT_CTL register.
+     */
+    int setActivityInactivityControl(char settings);
+    
+    /**
+     * Get the threshold for free fall detection.
+     *
+     * @return The threshold value for free-fall detection, as an 8-bit number,
+     *         with scale factor 62.5mg/LSB.
+     */
+     char getFreefallThreshold(void);
+    
+    /**
+     * Set the threshold for free fall detection.
+     *
+     * @return The threshold value for free-fall detection, as an 8-bit number,
+     *         with scale factor 62.5mg/LSB. A value of 0 may result in 
+     *         undesirable behavior if the free-fall interrupt is enabled.
+     *         Values between 300 mg and 600 mg (0x05 to 0x09) are recommended.
+     */
+    int setFreefallThreshold(char threshold);
+    
+    /**
+     * Get the time required to generate a free fall interrupt.
+     *
+     * @return The minimum time that the value of all axes must be less than
+     *         the freefall threshold to generate a free-fall interrupt, in
+     *         milliseconds.
+     */
+     char getFreefallTime(void);
+    
+    /**
+     * Set the time required to generate a free fall interrupt.
+     *
+     * @return The minimum time that the value of all axes must be less than
+     *         the freefall threshold to generate a free-fall interrupt, in
+     *         milliseconds. A value of 0 may result in undesirable behavior
+     *         if the free-fall interrupt is enabled. Values between 100 ms 
+     *         and 350 ms (0x14 to 0x46) are recommended.
+     */
+    int setFreefallTime(short int freefallTime_ms);
+    
+    /**
+     * Get the axis tap settings.
+     *
+     *      D3           D2            D1             D0
+     * +----------+--------------+--------------+--------------+
+     * | Suppress | TAP_X enable | TAP_Y enable | TAP_Z enable |
+     * +----------+--------------+--------------+--------------+
+     *
+     * (D7-D4 are 0s).
+     *
+     * See datasheet for more details.
+     *
+     * @return The contents of the TAP_AXES register.
+     */ 
+     char getTapAxisControl(void);
+    
+    /**
+     * Set the axis tap settings.
+     *
+     *      D3           D2            D1             D0
+     * +----------+--------------+--------------+--------------+
+     * | Suppress | TAP_X enable | TAP_Y enable | TAP_Z enable |
+     * +----------+--------------+--------------+--------------+
+     *
+     * (D7-D4 are 0s).
+     *
+     * See datasheet for more details.
+     *
+     * @param The control byte to write to the TAP_AXES register.
+     */
+    int setTapAxisControl(char settings);
+    
+    /**
+     * Get the source of a tap.
+     *
+     * @return The contents of the ACT_TAP_STATUS register.
+     */
+     char getTapSource(void);
+    
+     /**
+     * Get the interrupt enable settings.
+     *
+     * @return The contents of the INT_ENABLE register.
+     */
+
+     char getInterruptEnableControl(void);
+    
+    /**
+     * Set the interrupt enable settings.
+     *
+     * @param settings The control byte to write to the INT_ENABLE register.
+     */
+    int setInterruptEnableControl(char settings);
+    
+    /**
+     * Get the interrupt mapping settings.
+     *
+     * @return The contents of the INT_MAP register.
+     */
+     char getInterruptMappingControl(void);
+    
+    /**
+     * Set the interrupt mapping settings.
+     *
+     * @param settings The control byte to write to the INT_MAP register.
+     */
+    int setInterruptMappingControl(char settings);
+    
+    /**
+     * Get the interrupt source.
+     *
+     * @return The contents of the INT_SOURCE register.
+     */
+     char getInterruptSource(void);
+    
+   
+private:
+
+    I2C i2c_;
+    
+
+    /**
+     * Read one byte from a register on the device.
+     *
+     * @param: - the address to be read from
+     *
+     * @return: the value of the data read
+     */
+    char SingleByteRead(char address);
+
+    /**
+     * Write one byte to a register on the device.
+     *
+     * @param:
+        - address of the register to write to.
+        - the value of the data to store
+     */
+  
+   
+   int SingleByteWrite(char address, char data);
+
+    /**
+     * Read several consecutive bytes on the device and store them in a given location.
+     *
+     * @param startAddress: The address of the first register to read from.
+     * @param ptr_output: a pointer to the location to store the data being read
+     * @param size: The number of bytes to read.
+     */
+    void multiByteRead(char startAddress, char* ptr_output, int size);
+
+    /**
+     * Write several consecutive bytes  on the device.
+     *
+     * @param startAddress: The address of the first register to write to.
+     * @param ptr_data: Pointer to a location which contains the data to write.
+     * @param size: The number of bytes to write.
+     */
+    int multiByteWrite(char startAddress, char* ptr_data, int size);
+
+};
+
+#endif /* ADXL345_I2C_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BMP085.cpp	Wed Jul 17 18:50:28 2013 +0000
@@ -0,0 +1,171 @@
+/*
+ * BMP085.cpp
+ *
+ *  Created on: 13 juil. 2013
+ *      Author: Vincent
+ */
+
+#include "BMP085.h"
+#include <new>
+
+BMP085::BMP085(PinName sda, PinName scl) : i2c_(*reinterpret_cast<I2C*>(i2cRaw))
+{
+    // Placement new to avoid additional heap memory allocation.
+    new(i2cRaw) I2C(sda, scl);
+
+    pressure = 101300;
+    temperature = 298;
+}
+
+BMP085::~BMP085()
+{
+    // If the I2C object is initialized in the buffer in this object, call destructor of it.
+    if(&i2c_ == reinterpret_cast<I2C*>(&i2cRaw))
+        reinterpret_cast<I2C*>(&i2cRaw)->~I2C();
+}
+
+// oversampling setting
+// 0 = ultra low power
+// 1 = standard
+// 2 = high
+// 3 = ultra high resolution
+const unsigned char oversampling_setting = 3; //oversampling for measurement
+const unsigned char pressure_conversiontime[4] = {4.5, 7.5, 13.5, 25.5 };  // delays for oversampling settings 0, 1, 2 and 3
+
+// sensor registers from the BOSCH BMP085 datasheet
+short ac1;
+short ac2;
+short ac3;
+unsigned short ac4;
+unsigned short ac5;
+unsigned short ac6;
+short b1;
+short b2;
+short mb;
+short mc;
+short md;
+
+void BMP085::writeRegister(unsigned char r, unsigned char v)
+{
+  char cmd1[2];
+  cmd1[0] = r;
+  cmd1[1] = v;
+  i2c_.write(I2C_ADDRESS,cmd1, 2);
+}
+
+// read a 16 bit register
+int BMP085::readIntRegister(unsigned char r)
+{
+  char cmd1[2];
+  char cmd2[1];
+  //unsigned char msb, lsb;
+  cmd2[0] = r;
+  i2c_.write(I2C_ADDRESS,cmd2, 1);
+  i2c_.read(I2C_ADDRESS, cmd1, 2);
+  return (((int)cmd1[0]<<8) | ((int)cmd1[1]));
+}
+
+// read uncompensated temperature value
+unsigned int BMP085::readUT() {
+  writeRegister(0xf4,0x2e);
+  wait(0.0045); // the datasheet suggests 4.5 ms
+  return readIntRegister(0xf6);
+
+}
+
+// read uncompensated pressure value
+long BMP085::readUP() {
+  writeRegister(0xf4,0x34+(oversampling_setting<<6));
+  wait(pressure_conversiontime[oversampling_setting]*0.001);
+
+  //unsigned char msb, lsb, xlsb;
+  char cmd1[3];
+  char cmd0[1];
+  cmd0[0] = 0xf6;
+  i2c_.write(I2C_ADDRESS,cmd0, 1);
+  i2c_.read(I2C_ADDRESS, cmd1, 3);
+  return (((long)cmd1[0]<<16) | ((long)cmd1[1]<<8) | ((long)cmd1[2])) >>(8-oversampling_setting);
+
+}
+
+// Below there are the utility functions to get data from the sensor.
+
+// read temperature and pressure from sensor
+void BMP085::readSensor() {
+
+  long ut= readUT();
+  long up = readUP();
+
+
+  int x1, x2, x3, b3, b5, b6, p;
+  unsigned int b4, b7;
+  //calculate true temperature
+  x1 = ((long)ut - ac6) * ac5 >> 15;
+  x2 = ((long) mc << 11) / (x1 + md);
+  b5 = x1 + x2;
+  temperature = (b5 + 8) >> 4;
+
+  //calculate true pressure
+  b6 = b5 - 4000;
+  x1 = (b2 * (b6 * b6 >> 12)) >> 11;
+  x2 = ac2 * b6 >> 11;
+  x3 = x1 + x2;
+
+  if (oversampling_setting == 3) b3 = ((int32_t) ac1 * 4 + x3 + 2) << 1;
+  if (oversampling_setting == 2) b3 = ((int32_t) ac1 * 4 + x3 + 2);
+  if (oversampling_setting == 1) b3 = ((int32_t) ac1 * 4 + x3 + 2) >> 1;
+  if (oversampling_setting == 0) b3 = ((int32_t) ac1 * 4 + x3 + 2) >> 2;
+
+  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 >> oversampling_setting);
+  p = b7 < 0x80000000 ? (b7 * 2) / b4 : (b7 / b4) * 2;
+
+  x1 = (p >> 8) * (p >> 8);
+  x1 = (x1 * 3038) >> 16;
+  x2 = (-7357 * p) >> 16;
+  pressure = p + ((x1 + x2 + 3791) >> 4);
+}
+
+void  BMP085::getCalibrationData() {
+  ac1 = readIntRegister(0xAA);
+  ac2 = readIntRegister(0xAC);
+  ac3 = readIntRegister(0xAE);
+  ac4 = readIntRegister(0xB0);
+  ac5 = readIntRegister(0xB2);
+  ac6 = readIntRegister(0xB4);
+  b1 = readIntRegister(0xB6);
+  b2 = readIntRegister(0xB8);
+  mb = readIntRegister(0xBA);
+  mc = readIntRegister(0xBC);
+  md = readIntRegister(0xBE);
+}
+
+float BMP085::press(void)
+{
+    return(pressure);
+}
+
+float BMP085::temp(void)
+{
+    return(temperature);
+}
+
+float BMP085::altitud(void)
+{
+    //press();
+   // temp();
+    float To=298;
+    float ho=0;
+    float Po=101325;
+    //ecuacion
+    float c=(To-0.0065*ho);
+    float e=(pressure/Po);
+    float d=exp(0.19082*log(e));
+    float b=c*d;
+    float alt=153.84615*(To-b);
+    return(alt);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BMP085.h	Wed Jul 17 18:50:28 2013 +0000
@@ -0,0 +1,67 @@
+/*
+ * BMP085.h
+ *
+ *  Created on: 13 juil. 2013
+ *      Author: Vincent
+ */
+
+#ifndef BMP085_H_
+#define BMP085_H_
+
+#include "mbed.h"
+
+class BMP085{
+
+public :
+
+    static const int I2C_ADDRESS = 0xEE;  // sensor address
+
+    BMP085(PinName sda, PinName scl);
+
+
+    BMP085(I2C &i2c) : i2c_(i2c) {
+        //init();
+    }
+
+    ~BMP085();
+
+    void writeRegister(unsigned char r, unsigned char v);
+
+    // read a 16 bit register
+    int readIntRegister(unsigned char r);
+
+    // read uncompensated temperature value
+    unsigned int readUT();
+
+
+    // read uncompensated pressure value
+    long readUP();
+
+    // Below there are the utility functions to get data from the sensor.
+
+    // read temperature and pressure from sensor
+    void readSensor();
+
+    void  getCalibrationData();
+
+    float press(void);
+
+    float temp(void);
+
+    float altitud(void);
+
+
+private :
+
+    I2C &i2c_;
+    // variables to keep the values
+    float temperature;
+    float pressure;
+
+
+    char i2cRaw[sizeof(I2C)];
+};
+
+
+#endif /* BMP085_H_ */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HK10DOF.cpp	Wed Jul 17 18:50:28 2013 +0000
@@ -0,0 +1,550 @@
+/*
+FreeIMU.cpp - A libre and easy to use orientation sensing library for Arduino
+Copyright (C) 2011-2012 Fabio Varesano <fabio at varesano dot net>
+ported for HobbyKing's 10DOF stick on a mbed platform by Aloïs Wolff(wolffalois@gmail.com)
+
+Development of this code has been supported by the Department of Computer Science,
+Universita' degli Studi di Torino, Italy within the Piemonte Project
+http://www.piemonte.di.unito.it/
+
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the version 3 GNU General Public License as
+published by the Free Software Foundation.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+
+//#define DEBUG
+
+
+#include "HK10DOF.h"
+#include "helper_3dmath.h"
+#include <math.h>  
+
+// #include "WireUtils.h"
+//#include "DebugUtils.h"
+//#include "vector_math.h"
+
+#define     M_PI 3.1415926535897932384626433832795
+
+HK10DOF::HK10DOF(PinName sda, PinName scl) : acc(sda,scl), magn(sda,scl),gyro(sda,scl), baro(sda,scl),pc(USBTX,USBRX)
+{
+
+    pc.baud(921600);
+    
+    // initialize quaternion
+    q0 = 1.0f;
+    q1 = 0.0f;
+    q2 = 0.0f;
+    q3 = 0.0f;
+    exInt = 0.0;
+    eyInt = 0.0;
+    ezInt = 0.0;
+    twoKp = twoKpDef;
+    twoKi = twoKiDef;
+    integralFBx = 0.0f,  integralFBy = 0.0f, integralFBz = 0.0f;
+
+
+#ifndef CALIBRATION_H
+    // initialize scale factors to neutral values
+    acc_scale_x = 1;
+    acc_scale_y = 1;
+    acc_scale_z = 1;
+    magn_scale_x = 1;
+    magn_scale_y = 1;
+    magn_scale_z = 1;
+#else
+    // get values from global variables of same name defined in calibration.h
+    acc_off_x = ::acc_off_x;
+    acc_off_y = ::acc_off_y;
+    acc_off_z = ::acc_off_z;
+    acc_scale_x = ::acc_scale_x;
+    acc_scale_y = ::acc_scale_y;
+    acc_scale_z = ::acc_scale_z;
+    magn_off_x = ::magn_off_x;
+    magn_off_y = ::magn_off_y;
+    magn_off_z = ::magn_off_z;
+    magn_scale_x = ::magn_scale_x;
+    magn_scale_y = ::magn_scale_y;
+    magn_scale_z = ::magn_scale_z;
+#endif
+}
+
+
+
+
+/**
+ * Initialize the FreeIMU I2C bus, sensors and performs gyro offsets calibration
+*/
+
+void HK10DOF::init(bool fastmode)
+{
+
+
+         //Sensors Initialization
+     pc.printf("Initializing sensors...\n\r");
+     magn.init();
+     baro.getCalibrationData();
+     acc.setPowerControl(0x00);
+     wait_ms(10);
+     acc.setDataFormatControl(0x0B);
+     wait_ms(10);
+     acc.setPowerControl(MeasurementMode);
+     wait_ms(10);
+    pc.printf("Sensors OK!\n\r");
+
+    update.start();
+    int dt_us=0;
+    pc.printf("ZeroGyro\n\r");
+    // zero gyro
+    //zeroGyro();
+    gyro.zeroCalibrate(128,5);
+    pc.printf("ZeroGyro OK, CalLoad...\n\r");
+    // load calibration from eeprom
+    calLoad();
+
+}
+
+void HK10DOF::calLoad()
+{
+
+    
+    acc_off_x = 0;
+    acc_off_y = 0;
+    acc_off_z = 0;
+    acc_scale_x = 1;
+    acc_scale_y = 1;
+    acc_scale_z = 1;
+
+    magn_off_x = 0;
+    magn_off_y = 0;
+    magn_off_z = 0;
+    magn_scale_x = 1;
+    magn_scale_y = 1;
+    magn_scale_z = 1;
+}
+
+void HK10DOF::getRawValues(int16_t * raw_values)
+{
+    int16_t raw3[3];
+    int raw[3];
+    
+    pc.printf("GetRaw IN \n\r");
+
+    acc.getOutput(&raw_values[0], &raw_values[1], &raw_values[2]);
+    pc.printf("GotACC\n\r");
+    
+    gyro.read(raw);
+    
+    raw_values[3]=(int16_t)raw[0];
+    raw_values[4]=(int16_t)raw[1];
+    raw_values[5]=(int16_t)raw[2];
+    pc.printf("GotGYRO\n\r");
+    
+
+    magn.getXYZ(raw3);
+    raw_values[6]=raw3[0];
+    raw_values[7]=raw3[1];
+    raw_values[8]=raw3[2];
+    pc.printf("GotMAG\n\r");
+    
+
+
+    baro.readSensor();
+    raw_values[9]=(int16_t)baro.temp();
+    raw_values[10]=(int16_t)baro.press();
+    pc.printf("GotBARO\n\r");
+    
+
+}
+
+
+/**
+ * Populates values with calibrated readings from the sensors
+*/
+void HK10DOF::getValues(float * values)
+{
+
+    int16_t accval[3];
+    float     gyrval[3];
+    acc.getOutput(accval);
+    values[0] = (float) accval[0];
+    values[1] = (float) accval[1];
+    values[2] = (float) accval[2];
+    
+    gyro.readFin(gyrval);
+    values[3] =  gyrval[0];
+    values[4] =  gyrval[1];
+    values[5] =  gyrval[2];
+    
+    magn.getXYZ(accval);
+    values[6]=accval[0];
+    values[7]=accval[1];
+    values[8]=accval[2];
+
+
+#warning Accelerometer calibration active: have you calibrated your device?
+    // remove offsets and scale accelerometer (calibration)
+    values[0] = (values[0] - acc_off_x) / acc_scale_x;
+    values[1] = (values[1] - acc_off_y) / acc_scale_y;
+    values[2] = (values[2] - acc_off_z) / acc_scale_z;
+
+    // calibration
+#warning Magnetometer calibration active: have you calibrated your device?
+    values[6] = (values[6] - magn_off_x) / magn_scale_x;
+    values[7] = (values[7] - magn_off_y) / magn_scale_y;
+    values[8] = (values[8] - magn_off_z) / magn_scale_z;
+
+    
+    
+}
+
+
+/**
+ * Computes gyro offsets
+*/
+void HK10DOF::zeroGyro()
+{
+    const int totSamples = 3;
+    int16_t raw[11];
+    float tmpOffsets[] = {0,0,0};
+
+    for (int i = 0; i < totSamples; i++) {
+        getRawValues(raw);
+        tmpOffsets[0] += raw[3];
+        tmpOffsets[1] += raw[4];
+        tmpOffsets[2] += raw[5];
+    }
+
+    gyro_off_x = tmpOffsets[0] / totSamples;
+    gyro_off_y = tmpOffsets[1] / totSamples;
+    gyro_off_z = tmpOffsets[2] / totSamples;
+}
+
+
+/**
+ * Quaternion implementation of the 'DCM filter' [Mayhony et al].  Incorporates the magnetic distortion
+ * compensation algorithms from Sebastian Madgwick's filter which eliminates the need for a reference
+ * direction of flux (bx bz) to be predefined and limits the effect of magnetic distortions to yaw
+ * axis only.
+ *
+ * @see: http://www.x-io.co.uk/node/8#open_source_ahrs_and_imu_algorithms
+*/
+//#if IS_9DOM()
+void  HK10DOF::AHRSupdate(float gx, float gy, float gz, float ax, float ay, float az, float mx, float my, float mz)
+{
+
+    float recipNorm;
+    float q0q0, q0q1, q0q2, q0q3, q1q1, q1q2, q1q3, q2q2, q2q3, q3q3;
+    float halfex = 0.0f, halfey = 0.0f, halfez = 0.0f;
+    float qa, qb, qc;
+
+    // Auxiliary variables to avoid repeated arithmetic
+    q0q0 = q0 * q0;
+    q0q1 = q0 * q1;
+    q0q2 = q0 * q2;
+    q0q3 = q0 * q3;
+    q1q1 = q1 * q1;
+    q1q2 = q1 * q2;
+    q1q3 = q1 * q3;
+    q2q2 = q2 * q2;
+    q2q3 = q2 * q3;
+    q3q3 = q3 * q3;
+
+    // Use magnetometer measurement only when valid (avoids NaN in magnetometer normalisation)
+    if((mx != 0.0f) && (my != 0.0f) && (mz != 0.0f)) {
+        float hx, hy, bx, bz;
+        float halfwx, halfwy, halfwz;
+
+        // Normalise magnetometer measurement
+        recipNorm = invSqrt(mx * mx + my * my + mz * mz);
+        mx *= recipNorm;
+        my *= recipNorm;
+        mz *= recipNorm;
+
+        // Reference direction of Earth's magnetic field
+        hx = 2.0f * (mx * (0.5f - q2q2 - q3q3) + my * (q1q2 - q0q3) + mz * (q1q3 + q0q2));
+        hy = 2.0f * (mx * (q1q2 + q0q3) + my * (0.5f - q1q1 - q3q3) + mz * (q2q3 - q0q1));
+        bx = sqrt(hx * hx + hy * hy);
+        bz = 2.0f * (mx * (q1q3 - q0q2) + my * (q2q3 + q0q1) + mz * (0.5f - q1q1 - q2q2));
+
+        // Estimated direction of magnetic field
+        halfwx = bx * (0.5f - q2q2 - q3q3) + bz * (q1q3 - q0q2);
+        halfwy = bx * (q1q2 - q0q3) + bz * (q0q1 + q2q3);
+        halfwz = bx * (q0q2 + q1q3) + bz * (0.5f - q1q1 - q2q2);
+
+        // Error is sum of cross product between estimated direction and measured direction of field vectors
+        halfex = (my * halfwz - mz * halfwy);
+        halfey = (mz * halfwx - mx * halfwz);
+        halfez = (mx * halfwy - my * halfwx);
+    }
+
+
+    // Compute feedback only if accelerometer measurement valid (avoids NaN in accelerometer normalisation)
+    if((ax != 0.0f) && (ay != 0.0f) && (az != 0.0f)) {
+        float halfvx, halfvy, halfvz;
+
+        // Normalise accelerometer measurement
+        recipNorm = invSqrt(ax * ax + ay * ay + az * az);
+        ax *= recipNorm;
+        ay *= recipNorm;
+        az *= recipNorm;
+
+        // Estimated direction of gravity
+        halfvx = q1q3 - q0q2;
+        halfvy = q0q1 + q2q3;
+        halfvz = q0q0 - 0.5f + q3q3;
+
+        // Error is sum of cross product between estimated direction and measured direction of field vectors
+        halfex += (ay * halfvz - az * halfvy);
+        halfey += (az * halfvx - ax * halfvz);
+        halfez += (ax * halfvy - ay * halfvx);
+    }
+
+    // Apply feedback only when valid data has been gathered from the accelerometer or magnetometer
+    if(halfex != 0.0f && halfey != 0.0f && halfez != 0.0f) {
+        // Compute and apply integral feedback if enabled
+        if(twoKi > 0.0f) {
+            integralFBx += twoKi * halfex * (1.0f / sampleFreq);  // integral error scaled by Ki
+            integralFBy += twoKi * halfey * (1.0f / sampleFreq);
+            integralFBz += twoKi * halfez * (1.0f / sampleFreq);
+            gx += integralFBx;  // apply integral feedback
+            gy += integralFBy;
+            gz += integralFBz;
+        } else {
+            integralFBx = 0.0f; // prevent integral windup
+            integralFBy = 0.0f;
+            integralFBz = 0.0f;
+        }
+
+        // Apply proportional feedback
+        gx += twoKp * halfex;
+        gy += twoKp * halfey;
+        gz += twoKp * halfez;
+    }
+
+    // Integrate rate of change of quaternion
+    gx *= (0.5f * (1.0f / sampleFreq));   // pre-multiply common factors
+    gy *= (0.5f * (1.0f / sampleFreq));
+    gz *= (0.5f * (1.0f / sampleFreq));
+    qa = q0;
+    qb = q1;
+    qc = q2;
+    q0 += (-qb * gx - qc * gy - q3 * gz);
+    q1 += (qa * gx + qc * gz - q3 * gy);
+    q2 += (qa * gy - qb * gz + q3 * gx);
+    q3 += (qa * gz + qb * gy - qc * gx);
+
+    // Normalise quaternion
+    recipNorm = invSqrt(q0 * q0 + q1 * q1 + q2 * q2 + q3 * q3);
+    q0 *= recipNorm;
+    q1 *= recipNorm;
+    q2 *= recipNorm;
+    q3 *= recipNorm;
+}
+
+
+/**
+ * Populates array q with a quaternion representing the IMU orientation with respect to the Earth
+ *
+ * @param q the quaternion to populate
+*/
+void HK10DOF::getQ(float * q)
+{
+    float val[9];
+    getValues(val);
+    /*
+        DEBUG_PRINT(val[3] * M_PI/180);
+        DEBUG_PRINT(val[4] * M_PI/180);
+        DEBUG_PRINT(val[5] * M_PI/180);
+        DEBUG_PRINT(val[0]);
+        DEBUG_PRINT(val[1]);
+        DEBUG_PRINT(val[2]);
+        DEBUG_PRINT(val[6]);
+        DEBUG_PRINT(val[7]);
+        DEBUG_PRINT(val[8]);
+    */
+
+    dt_us=update.read_us();
+    sampleFreq = 1.0 / ((dt_us) / 1000000.0);
+    update.reset();
+
+
+
+    // gyro values are expressed in deg/sec, the * M_PI/180 will convert it to radians/sec
+    AHRSupdate(val[3] * M_PI/180, val[4] * M_PI/180, val[5] * M_PI/180, val[0], val[1], val[2], val[6], val[7], val[8]);
+
+
+
+    q[0] = q0;
+    q[1] = q1;
+    q[2] = q2;
+    q[3] = q3;
+}
+
+
+
+const float def_sea_press = 1013.25;
+
+/**
+ * Returns an altitude estimate from baromether readings only using sea_press as current sea level pressure
+*/
+float HK10DOF::getBaroAlt(float sea_press)
+{
+    //float temp,press,res;
+    baro.readSensor();
+    //temp=(float)baro.temp();
+    //press=(float)baro.press();
+    
+    
+
+    return baro.altitud();
+    //return(temp,press);
+}
+
+/**
+ * Returns an altitude estimate from baromether readings only using a default sea level pressure
+*/
+float HK10DOF::getBaroAlt()
+{
+    return getBaroAlt(def_sea_press);
+}
+
+
+/**
+ * Compensates the accelerometer readings in the 3D vector acc expressed in the sensor frame for gravity
+ * @param acc the accelerometer readings to compensate for gravity
+ * @param q the quaternion orientation of the sensor board with respect to the world
+*/
+void HK10DOF::gravityCompensateAcc(float * acc, float * q)
+{
+    float g[3];
+
+    // get expected direction of gravity in the sensor frame
+    g[0] = 2 * (q[1] * q[3] - q[0] * q[2]);
+    g[1] = 2 * (q[0] * q[1] + q[2] * q[3]);
+    g[2] = q[0] * q[0] - q[1] * q[1] - q[2] * q[2] + q[3] * q[3];
+
+    // compensate accelerometer readings with the expected direction of gravity
+    acc[0] = acc[0] - g[0];
+    acc[1] = acc[1] - g[1];
+    acc[2] = acc[2] - g[2];
+}
+
+
+
+/**
+ * Returns the Euler angles in radians defined in the Aerospace sequence.
+ * See Sebastian O.H. Madwick report "An efficient orientation filter for
+ * inertial and intertial/magnetic sensor arrays" Chapter 2 Quaternion representation
+ *
+ * @param angles three floats array which will be populated by the Euler angles in radians
+*/
+void HK10DOF::getEulerRad(float * angles)
+{
+    float q[4]; // quaternion
+    getQ(q);
+    angles[0] = atan2(2 * q[1] * q[2] - 2 * q[0] * q[3], 2 * q[0]*q[0] + 2 * q[1] * q[1] - 1); // psi
+    angles[1] = -asin(2 * q[1] * q[3] + 2 * q[0] * q[2]); // theta
+    angles[2] = atan2(2 * q[2] * q[3] - 2 * q[0] * q[1], 2 * q[0] * q[0] + 2 * q[3] * q[3] - 1); // phi
+}
+
+
+/**
+ * Returns the Euler angles in degrees defined with the Aerospace sequence.
+ * See Sebastian O.H. Madwick report "An efficient orientation filter for
+ * inertial and intertial/magnetic sensor arrays" Chapter 2 Quaternion representation
+ *
+ * @param angles three floats array which will be populated by the Euler angles in degrees
+*/
+void HK10DOF::getEuler(float * angles)
+{
+    getEulerRad(angles);
+    arr3_rad_to_deg(angles);
+}
+
+
+/**
+ * Returns the yaw pitch and roll angles, respectively defined as the angles in radians between
+ * the Earth North and the IMU X axis (yaw), the Earth ground plane and the IMU X axis (pitch)
+ * and the Earth ground plane and the IMU Y axis.
+ *
+ * @note This is not an Euler representation: the rotations aren't consecutive rotations but only
+ * angles from Earth and the IMU. For Euler representation Yaw, Pitch and Roll see HK10DOF::getEuler
+ *
+ * @param ypr three floats array which will be populated by Yaw, Pitch and Roll angles in radians
+*/
+void HK10DOF::getYawPitchRollRad(float * ypr)
+{
+    float q[4]; // quaternion
+    float gx, gy, gz; // estimated gravity direction
+    getQ(q);
+
+    gx = 2 * (q[1]*q[3] - q[0]*q[2]);
+    gy = 2 * (q[0]*q[1] + q[2]*q[3]);
+    gz = q[0]*q[0] - q[1]*q[1] - q[2]*q[2] + q[3]*q[3];
+
+    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(gx / sqrt(gy*gy + gz*gz));
+    ypr[2] = atan(gy / sqrt(gx*gx + gz*gz));
+}
+
+
+/**
+ * Returns the yaw pitch and roll angles, respectively defined as the angles in degrees between
+ * the Earth North and the IMU X axis (yaw), the Earth ground plane and the IMU X axis (pitch)
+ * and the Earth ground plane and the IMU Y axis.
+ *
+ * @note This is not an Euler representation: the rotations aren't consecutive rotations but only
+ * angles from Earth and the IMU. For Euler representation Yaw, Pitch and Roll see HK10DOF::getEuler
+ *
+ * @param ypr three floats array which will be populated by Yaw, Pitch and Roll angles in degrees
+*/
+void HK10DOF::getYawPitchRoll(float * ypr)
+{
+    getYawPitchRollRad(ypr);
+    arr3_rad_to_deg(ypr);
+}
+
+
+/**
+ * Converts a 3 elements array arr of angles expressed in radians into degrees
+*/
+void arr3_rad_to_deg(float * arr)
+{
+    arr[0] *= 180/M_PI;
+    arr[1] *= 180/M_PI;
+    arr[2] *= 180/M_PI;
+}
+
+
+/**
+ * Fast inverse square root implementation
+ * @see http://en.wikipedia.org/wiki/Fast_inverse_square_root
+*/
+float invSqrt(float number)
+{
+    volatile long i;
+    volatile float x, y;
+    volatile const float f = 1.5F;
+
+    x = number * 0.5F;
+    y = number;
+    i = * ( long * ) &y;
+    i = 0x5f375a86 - ( i >> 1 );
+    y = * ( float * ) &i;
+    y = y * ( f - ( x * y * y ) );
+    return y;
+}
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HK10DOF.h	Wed Jul 17 18:50:28 2013 +0000
@@ -0,0 +1,171 @@
+/*
+FreeIMU.h - A libre and easy to use orientation sensing library for Arduino
+Copyright (C) 2011 Fabio Varesano <fabio at varesano dot net>
+
+Development of this code has been supported by the Department of Computer Science,
+Universita' degli Studi di Torino, Italy within the Piemonte Project
+http://www.piemonte.di.unito.it/
+
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the version 3 GNU General Public License as
+published by the Free Software Foundation.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef HK10DOF_h
+#define HK10DOF_h
+
+// Uncomment the appropriated version of FreeIMU you are using
+//#define FREEIMU_v01
+//#define FREEIMU_v02
+//#define FREEIMU_v03
+//#define FREEIMU_v035
+//#define FREEIMU_v035_MS
+//#define FREEIMU_v035_BMP
+#define FREEIMU_v04
+
+
+
+#define FREEIMU_LIB_VERSION "20121122"
+
+#define FREEIMU_DEVELOPER "Fabio Varesano - varesano.net"
+
+#if F_CPU == 16000000L
+  #define FREEIMU_FREQ "16 MHz"
+#elif F_CPU == 8000000L
+  #define FREEIMU_FREQ "8 MHz"
+#endif
+
+
+// board IDs
+
+
+#define FREEIMU_ID "Zboub"
+
+//#define IS_6DOM() (defined(SEN_10121) || defined(GEN_MPU6050))
+#define IS_9DOM() 
+//#define HAS_AXIS_ALIGNED() (defined(FREEIMU_v01) || defined(FREEIMU_v02) || defined(FREEIMU_v03) || defined(FREEIMU_v035) || defined(FREEIMU_v035_MS) || defined(FREEIMU_v035_BMP) || defined(FREEIMU_v04) || defined(SEN_10121) || defined(SEN_10736))
+
+
+
+
+#include "mbed.h"
+
+//#include "calibration.h"
+/*
+#ifndef CALIBRATION_H
+#include <EEPROM.h>
+#endif
+#define FREEIMU_EEPROM_BASE 0x0A
+#define FREEIMU_EEPROM_SIGNATURE 0x19
+*/
+
+//include des biblis des senseurs
+
+ #include "ADXL345_I2C.h"
+ #include "HMC5883L.h"
+ #include "BMP085.h"
+ #include "L3G4200D.h"
+ 
+  // default I2C 7-bit addresses of the sensors
+  #define FIMU_ACC_ADDR ADXL345_ADDR_ALT_LOW // SDO connected to GND
+//#define FIMU_ADXL345_DEF_ADDR ADXL345_ADDR_ALT_HIGH // SDO connected to GND
+
+#define FIMU_BMA180_DEF_ADDR BMA180_ADDRESS_SDO_LOW
+#define FIMU_ITG3200_DEF_ADDR ITG3200_ADDR_AD0_LOW // AD0 connected to GND
+// HMC5843 address is fixed so don't bother to define it
+
+/*
+#define twoKpDef  (2.0f * 0.5f) // 2 * proportional gain
+#define twoKiDef  (2.0f * 0.1f) // 2 * integral gain
+*/
+#define twoKpDef  (2.0f * 5.0f) // 2 * proportional gain
+#define twoKiDef  (2.0f * 0.1f) // 2 * integral gain
+
+
+#ifndef cbi
+#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
+#endif
+
+class HK10DOF
+{
+  public:
+    HK10DOF(PinName sda, PinName scl);
+    //I2C i2c_;
+    
+    //void init();
+    //void init(bool fastmode);
+    //void init(int accgyro_addr, bool fastmode);
+    void init(bool fastmode);
+    #ifndef CALIBRATION_H
+    void calLoad();
+    #endif
+    void zeroGyro();
+    void getRawValues(int16_t * raw_values);
+    void getValues(float * values);
+    void getQ(float * q);
+    void getEuler(float * angles);
+    void getYawPitchRoll(float * ypr);
+    void getEulerRad(float * angles);
+    void getYawPitchRollRad(float * ypr);
+    
+      float getBaroAlt();
+      float getBaroAlt(float sea_press);
+      //float getEstimatedAlt();
+      //float getEstimatedAlt(float sea_press);
+    
+    void gravityCompensateAcc(float * acc, float * q);
+    
+    // we make them public so that users can interact directly with device classes
+    
+      ADXL345_I2C acc;
+      HMC5883L magn;
+      BMP085 baro;
+      L3G4200D gyro;
+      Serial pc;    
+      
+
+    
+    
+    int* raw_acc, raw_gyro, raw_magn;
+    // calibration parameters
+    int16_t gyro_off_x, gyro_off_y, gyro_off_z;
+    int16_t acc_off_x, acc_off_y, acc_off_z, magn_off_x, magn_off_y, magn_off_z;
+    float acc_scale_x, acc_scale_y, acc_scale_z, magn_scale_x, magn_scale_y, magn_scale_z;
+    
+  private:
+    Timer update;
+    int dt_us;
+    
+    void AHRSupdate(float gx, float gy, float gz, float ax, float ay, float az, float mx, float my, float mz);
+    
+    //void AHRSupdate(float gx, float gy, float gz, float ax, float ay, float az); for 6DOF sensors
+   
+    //float q0, q1, q2, q3; // quaternion elements representing the estimated orientation
+    float iq0, iq1, iq2, iq3;
+    float exInt, eyInt, ezInt;  // scaled integral error
+    volatile float twoKp;      // 2 * proportional gain (Kp)
+    volatile float twoKi;      // 2 * integral gain (Ki)
+    volatile float q0, q1, q2, q3; // quaternion of sensor frame relative to auxiliary frame
+    volatile float integralFBx,  integralFBy, integralFBz;
+    //unsigned long lastUpdate, now; // sample period expressed in milliseconds
+    float sampleFreq; // half the sample period expressed in seconds
+    
+};
+
+float invSqrt(float number);
+void arr3_rad_to_deg(float * arr);
+
+
+
+#endif // FreeIMU_h
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HMC5883L.cpp	Wed Jul 17 18:50:28 2013 +0000
@@ -0,0 +1,147 @@
+/*
+ * @file HMC5883L.cpp
+ * @author Tyler Weaver
+ *
+ * @section 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.
+ *
+ * @section DESCRIPTION
+ *
+ * HMC5883L 3-Axis Digital Compas IC
+ * For use with the Sparkfun 9 Degrees of Freedom - Sensor Stick
+ *
+ * Datasheet:
+ *
+ * http://dlnmh9ip6v2uc.cloudfront.net/datasheets/Sensors/Magneto/HMC5883L-FDS.pdf
+ */
+
+#include "HMC5883L.h"
+#include <new>
+
+HMC5883L::HMC5883L(PinName sda, PinName scl) : i2c_(*reinterpret_cast<I2C*>(i2cRaw))
+{
+    // Placement new to avoid additional heap memory allocation.
+    new(i2cRaw) I2C(sda, scl);
+    
+    init();
+}
+
+HMC5883L::~HMC5883L()
+{
+    // If the I2C object is initialized in the buffer in this object, call destructor of it.
+    if(&i2c_ == reinterpret_cast<I2C*>(&i2cRaw))
+        reinterpret_cast<I2C*>(&i2cRaw)->~I2C();
+}
+
+void HMC5883L::init()
+{
+    // init - configure your setup here
+    setConfigurationA(AVG8_SAMPLES | OUTPUT_RATE_15); // 8 sample average, 15Hz, normal mode
+    setConfigurationB(0x20); // default 
+    setMode(CONTINUOUS_MODE); // continuous sample mode
+}
+
+void HMC5883L::setConfigurationA(char config)
+{
+    char cmd[2];
+    cmd[0] = CONFIG_A_REG; // register a address
+    cmd[1] = config;
+    
+    i2c_.write(I2C_ADDRESS, cmd, 2);
+}
+
+void HMC5883L::setConfigurationB(char config)
+{
+    char cmd[2];
+    cmd[0] = CONFIG_B_REG; // register b address
+    cmd[1] = config;
+    
+    i2c_.write(I2C_ADDRESS, cmd, 2);
+}
+
+char HMC5883L::getConfigurationA()
+{
+    char cmd[2];
+    cmd[0] = CONFIG_A_REG; // register a address
+    i2c_.write(I2C_ADDRESS, cmd, 1, true);
+    i2c_.read(I2C_ADDRESS, &cmd[1], 1, false);
+    return cmd[1];
+}
+
+char HMC5883L::getConfigurationB()
+{
+    char cmd[2];
+    cmd[0] = CONFIG_A_REG; // register b address
+    i2c_.write(I2C_ADDRESS, cmd, 1, true);
+    i2c_.read(I2C_ADDRESS, &cmd[1], 1, false);
+    return cmd[1];
+}
+
+void HMC5883L::setMode(char mode = SINGLE_MODE)
+{
+    char cmd[2];
+    cmd[0] = MODE_REG; // mode register address
+    cmd[1] = mode;
+    i2c_.write(I2C_ADDRESS,cmd,2);
+}
+
+char HMC5883L::getMode()
+{
+    char cmd[2];
+    cmd[0] = MODE_REG; // mode register
+    i2c_.write(I2C_ADDRESS, cmd, 1, true);
+    i2c_.read(I2C_ADDRESS, &cmd[1], 1, false);
+    return cmd[1];
+}
+
+char HMC5883L::getStatus()
+{
+    char cmd[2];
+    cmd[0] = STATUS_REG; // status register
+    i2c_.write(I2C_ADDRESS, cmd, 1, true);
+    i2c_.read(I2C_ADDRESS, &cmd[1], 1, false);
+    return cmd[1];
+}
+
+void HMC5883L::getXYZ(int16_t output[3])
+{
+    char cmd[2];
+    char data[6];
+    cmd[0] = 0x03; // starting point for reading
+    i2c_.write(I2C_ADDRESS, cmd, 1, true); // set the pointer to the start of x
+    i2c_.read(I2C_ADDRESS, data, 6, false);
+    
+    for(int i = 0; i < 3; i++) // fill the output variables
+        output[i] = int16_t(((unsigned char)data[i*2] << 8) | (unsigned char)data[i*2+1]);
+}
+
+double HMC5883L::getHeadingXY()
+{
+    int16_t raw_data[3];
+    getXYZ(raw_data);
+    double heading = atan2(static_cast<double>(raw_data[2]), static_cast<double>(raw_data[0])); // heading = arctan(Y/X)
+    
+    // TODO: declenation angle compensation
+    
+    if(heading < 0.0) // fix sign
+        heading += PI2;
+        
+    if(heading > PI2) // fix overflow
+        heading -= PI2;
+        
+    return heading;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HMC5883L.h	Wed Jul 17 18:50:28 2013 +0000
@@ -0,0 +1,246 @@
+/*
+ * @file HMC5883L.h
+ * @author Tyler Weaver
+ *
+ * @section 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.
+ *
+ * @section DESCRIPTION
+ *
+ * HMC5883L 3-Axis Digital Compas IC
+ * For use with the Sparkfun 9 Degrees of Freedom - Sensor Stick
+ *
+ * Datasheet:
+ *
+ * http://dlnmh9ip6v2uc.cloudfront.net/datasheets/Sensors/Magneto/HMC5883L-FDS.pdf
+ */
+
+#ifndef HMC5883L_H
+#define HMC5883L_H
+
+#include "mbed.h"
+
+/*
+* Defines
+*/
+
+//-----------
+// Registers
+//-----------
+#define CONFIG_A_REG    0x00
+#define CONFIG_B_REG    0x01
+#define MODE_REG        0x02
+#define OUTPUT_REG      0x03
+#define STATUS_REG      0x09
+
+// configuration register a
+#define AVG1_SAMPLES    0x00
+#define AVG2_SAMPLES    0x20
+#define AVG4_SAMPLES    0x80
+#define AVG8_SAMPLES    0xC0
+
+#define OUTPUT_RATE_0_75    0x00
+#define OUTPUT_RATE_1_5     0x04
+#define OUTPUT_RATE_3       0x08
+#define OUTPUT_RATE_7_5     0x0C
+#define OUTPUT_RATE_15      0x10
+#define OUTPUT_RATE_30      0x14
+#define OUTPUT_RATE_75      0x18
+
+#define NORMAL_MEASUREMENT  0x00
+#define POSITIVE_BIAS       0x01
+#define NEGATIVE_BIAS       0x02
+
+// mode register
+#define CONTINUOUS_MODE     0x00
+#define SINGLE_MODE         0x01
+#define IDLE_MODE           0x02
+
+// status register
+#define STATUS_LOCK         0x02
+#define STATUS_READY        0x01
+
+// Utility
+#ifndef M_PI
+#define M_PI 3.1415926535897932384626433832795
+#endif
+
+#define PI2         (2*M_PI)
+#define RAD_TO_DEG  (180.0/M_PI)
+#define DEG_TO_RAD  (M_PI/180.0)
+
+/**
+ * The HMC5883L 3-Axis Digital Compass IC
+ */
+class HMC5883L
+{
+
+public:
+
+    /**
+     * The I2C address that can be passed directly to i2c object (it's already shifted 1 bit left).
+     */
+    static const int I2C_ADDRESS = 0x3D;
+
+    /**
+     * Constructor.
+     *
+     * Calls init function
+     *
+     * @param sda - mbed pin to use for the SDA I2C line.
+     * @param scl - mbed pin to use for the SCL I2C line.
+     */
+    HMC5883L(PinName sda, PinName scl);
+
+    /**
+    * Constructor that accepts external i2c interface object.
+    * 
+    * Calls init function
+    *
+    * @param i2c The I2C interface object to use.
+    */
+    HMC5883L(I2C &i2c) : i2c_(i2c) {
+        init();
+    }
+
+    ~HMC5883L();
+    
+    /**
+    * Initalize function called by all constructors.
+    * 
+    * Place startup code in here.
+    */
+    void init();
+    
+    /**
+    * Function for setting configuration register A
+    *
+    * Defined constants should be ored together to create value.
+    * Defualt is 0x10 - 1 Sample per output, 15Hz Data output rate, normal measurement mode
+    *
+    * Refer to datasheet for instructions for setting Configuration Register A.
+    *
+    * @param config the value to place in Configuration Register A
+    */
+    void setConfigurationA(char);
+    
+    /**
+    * Function for retrieving the contents of configuration register A
+    * 
+    * @returns Configuration Register A
+    */
+    char getConfigurationA();
+    
+    /**
+    * Function for setting configuration register B
+    *
+    * Configuration Register B is for setting the device gain.
+    * Default value is 0x20
+    * 
+    * Refer to datasheet for instructions for setting Configuration Register B
+    *
+    * @param config the value to place in Configuration Register B
+    */
+    void setConfigurationB(char);
+    
+    /**
+    * Function for retrieving the contents of configuration register B
+    * 
+    * @returns Configuration Register B
+    */
+    char getConfigurationB();
+    
+    /**
+    * Funciton for setting the mode register
+    * 
+    * Constants: CONTINUOUS_MODE, SINGLE_MODE, IDLE_MODE
+    * 
+    * When you send a the Single-Measurement Mode instruction to the mode register
+    * a single measurement is made, the RDY bit is set in the status register,
+    * and the mode is placed in idle mode.
+    *
+    * When in Continous-Measurement Mode the device continuously performs measurements
+    * and places the results in teh data register.  After being placed in this mode
+    * it takes two periods at the rate set in the data output rate before the first
+    * sample is avaliable.
+    *
+    * Refer to datasheet for more detailed instructions for setting the mode register.
+    *  
+    * @param mode the value for setting in the Mode Register
+    */
+    void setMode(char);
+    
+    /**
+    * Function for retrieving the contents of mode register
+    * 
+    * @returns mode register
+    */
+    char getMode();
+    
+    /**
+    * Function for retriaval of the raw data
+    *
+    * @param output buffer that is atleast 3 in length
+    */
+    void getXYZ(int16_t raw[3]);
+    
+    /**
+    * Function for retrieving the contents of status register
+    * 
+    * Bit1: LOCK, Bit0: RDY
+    *
+    * @returns status register
+    */
+    char getStatus();
+    
+    /**
+    * Function for getting radian heading using 2-dimensional calculation.
+    * 
+    * Compass must be held flat and away from an magnetic field generating
+    * devices such as cell phones and speakers.
+    *
+    * TODO: declenation angle compensation
+    * 
+    * @returns heading in radians
+    */
+    double getHeadingXY();
+    
+    /**
+    * Function for getting degree heading using 2-dimensional calculation.
+    * 
+    * Compass must be held flat and away from an magnetic field generating
+    * devices such as cell phones and speakers.
+    *
+    * TODO: declenation angle compensation
+    * 
+    * @returns heading in degrees
+    */
+    double getHeadingXYDeg() {
+        return (getHeadingXY() * RAD_TO_DEG);
+    }
+
+private:
+
+    I2C &i2c_;
+
+    /**
+     * The raw buffer for allocating I2C object in its own without heap memory.
+     */
+    char i2cRaw[sizeof(I2C)];
+};
+
+#endif // HMC5883L
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/L3G4200D.cpp	Wed Jul 17 18:50:28 2013 +0000
@@ -0,0 +1,165 @@
+/**
+ * Copyright (c) 2011 Pololu Corporation.  For more information, see
+ * 
+ * http://www.pololu.com/
+ * http://forum.pololu.com/
+ * 
+ * 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 "mbed.h"
+#include "L3G4200D.h"
+#include <math.h>
+
+// Defines ////////////////////////////////////////////////////////////////
+
+// The Arduino two-wire interface uses a 7-bit number for the address, 
+// and sets the last bit correctly based on reads and writes
+// mbed I2C libraries take the 7-bit address shifted left 1 bit
+// #define GYR_ADDRESS (0xD2 >> 1)
+#define GYR_ADDRESS 0xD2
+
+// Public Methods //////////////////////////////////////////////////////////////
+
+// Constructor
+L3G4200D::L3G4200D(PinName sda, PinName scl):
+    _device(sda, scl)
+{
+    _device.frequency(400000);
+    // Turns on the L3G4200D's gyro and places it in normal mode.
+    // 0x0F = 0b00001111
+    // Normal power mode, all axes enabled
+    writeReg(L3G4200D_CTRL_REG1, 0x0F);
+    writeReg(L3G4200D_CTRL_REG4, 0x20); // 2000 dps full scale
+    
+    setGains(1.0,1.0,1.0);
+    setOffsets(0.0,0.0,0.0);
+
+}
+
+// Writes a gyro register
+void L3G4200D::writeReg(byte reg, byte value)
+{
+    data[0] = reg;
+    data[1] = value;
+    
+    _device.write(GYR_ADDRESS, data, 2);
+}
+
+// Reads a gyro register
+byte L3G4200D::readReg(byte reg)
+{
+    byte value = 0;
+    
+    _device.write(GYR_ADDRESS, &reg, 1);
+    _device.read(GYR_ADDRESS, &value, 1);
+
+    return value;
+}
+
+void L3G4200D::setGains(float _Xgain, float _Ygain, float _Zgain) {
+  gains[0] = _Xgain;
+  gains[1] = _Ygain;
+  gains[2] = _Zgain;
+}
+
+void L3G4200D::setOffsets(int _Xoffset, int _Yoffset, int _Zoffset) {
+  offsets[0] = _Xoffset;
+  offsets[1] = _Yoffset;
+  offsets[2] = _Zoffset;
+}
+
+void L3G4200D::setRevPolarity(bool _Xpol, bool _Ypol, bool _Zpol) {
+  polarities[0] = _Xpol ? -1 : 1;
+  polarities[1] = _Ypol ? -1 : 1;
+  polarities[2] = _Zpol ? -1 : 1;
+}
+
+
+void L3G4200D::zeroCalibrate(unsigned int totSamples, unsigned int sampleDelayMS) {
+  int xyz[3]; 
+  float tmpOffsets[] = {0,0,0};
+
+  for (int i = 0;i < totSamples;i++){
+    wait_ms(sampleDelayMS);
+    read(xyz);
+    tmpOffsets[0] += xyz[0];
+    tmpOffsets[1] += xyz[1];
+    tmpOffsets[2] += xyz[2];  
+  }
+  setOffsets(-tmpOffsets[0] / totSamples, -tmpOffsets[1] / totSamples, -tmpOffsets[2] / totSamples);
+}
+
+
+// Reads the 3 gyro channels and stores them in vector g
+void L3G4200D::read(int *g)
+{
+    // assert the MSB of the address to get the gyro 
+    // to do slave-transmit subaddress updating.
+    data[0] = L3G4200D_OUT_X_L | (1 << 7);
+    _device.write(GYR_ADDRESS, data, 1); 
+
+//    Wire.requestFrom(GYR_ADDRESS, 6);
+//    while (Wire.available() < 6);
+    
+    _device.read(GYR_ADDRESS, data, 6); 
+
+    uint8_t xla = data[0];
+    uint8_t xha = data[1];
+    uint8_t yla = data[2];
+    uint8_t yha = data[3];
+    uint8_t zla = data[4];
+    uint8_t zha = data[5];
+
+    g[0] = (short) (yha << 8 | yla);
+    g[1] = (short) (xha << 8 | xla);
+    g[2] = (short) (zha << 8 | zla);
+}
+
+void L3G4200D::readRawCal(int *_GyroXYZ) {
+  read(_GyroXYZ);
+  _GyroXYZ[0] += offsets[0];
+  _GyroXYZ[1] += offsets[1];
+  _GyroXYZ[2] += offsets[2];
+}
+
+
+
+void L3G4200D::read3(int x, int y, int z) {
+  int* readings;
+  read(readings);
+
+  // each axis reading comes in 10 bit resolution, ie 2 bytes.  Least Significat Byte first!!
+  // thus we are converting both bytes in to one int
+  x = readings[0];  
+  y = readings[1]; 
+  z = readings[2]; 
+}
+
+void L3G4200D::readFin(float *_GyroXYZ){
+  int xyz[3];
+  
+  readRawCal(xyz); // x,y,z will contain calibrated integer values from the sensor
+  _GyroXYZ[0] =  xyz[0] / 14.375 * polarities[0] * gains[0];
+  _GyroXYZ[1] =  xyz[1]/ 14.375 * polarities[1] * gains[1];
+  _GyroXYZ[2] =  xyz[2] / 14.375 * polarities[2] * gains[2];
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/L3G4200D.h	Wed Jul 17 18:50:28 2013 +0000
@@ -0,0 +1,119 @@
+/* Copyright (c) 2011 Pololu Corporation.  For more information, see
+ * 
+ * http://www.pololu.com/
+ * http://forum.pololu.com/
+ * 
+ * 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 __L3G4200D_H
+#define __L3G4200D_H
+
+#include "mbed.h"
+
+// register addresses
+
+#define L3G4200D_WHO_AM_I      0x0F
+
+#define L3G4200D_CTRL_REG1     0x20
+#define L3G4200D_CTRL_REG2     0x21
+#define L3G4200D_CTRL_REG3     0x22
+#define L3G4200D_CTRL_REG4     0x23
+#define L3G4200D_CTRL_REG5     0x24
+#define L3G4200D_REFERENCE     0x25
+#define L3G4200D_OUT_TEMP      0x26
+#define L3G4200D_STATUS_REG    0x27
+
+#define L3G4200D_OUT_X_L       0x28
+#define L3G4200D_OUT_X_H       0x29
+#define L3G4200D_OUT_Y_L       0x2A
+#define L3G4200D_OUT_Y_H       0x2B
+#define L3G4200D_OUT_Z_L       0x2C
+#define L3G4200D_OUT_Z_H       0x2D
+
+#define L3G4200D_FIFO_CTRL_REG 0x2E
+#define L3G4200D_FIFO_SRC_REG  0x2F
+
+#define L3G4200D_INT1_CFG      0x30
+#define L3G4200D_INT1_SRC      0x31
+#define L3G4200D_INT1_THS_XH   0x32
+#define L3G4200D_INT1_THS_XL   0x33
+#define L3G4200D_INT1_THS_YH   0x34
+#define L3G4200D_INT1_THS_YL   0x35
+#define L3G4200D_INT1_THS_ZH   0x36
+#define L3G4200D_INT1_THS_ZL   0x37
+#define L3G4200D_INT1_DURATION 0x38
+
+typedef char byte;
+
+/** Interface library for the ST L3G4200D 3-axis gyro
+ *
+ * Ported from Pololu L3G4200D library for Arduino by
+ * Michael Shimniok http://bot-thoughts.com
+ *
+ * @code
+ * #include "mbed.h"
+ * #include "L3G4200D.h"
+ * L3G4200D gyro(p28, p27);
+ * ...
+ * int g[3];
+ * gyro.read(g);
+ * @endcode
+ */
+class L3G4200D
+{
+    public:
+        /** Create a new L3G4200D I2C interface
+         * @param sda is the pin for the I2C SDA line
+         * @param scl is the pin for the I2C SCL line
+         */
+        L3G4200D(PinName sda, PinName scl);
+        
+        /** Read gyro values
+         * @param g Array containing x, y, and z gyro values
+         * @return g Array containing x, y, and z gyro values
+         */
+        void read(int *g);
+        void read3(int x, int y, int z);
+        void zeroCalibrate(unsigned int totSamples, unsigned int sampleDelayMS);
+        void readRawCal(int *_GyroXYZ);
+        void readFin(float *_GyroXYZ); // includes gain and offset
+        
+    private:
+        float gains[3]; 
+        int offsets[3];
+        float polarities[3];
+        
+        void setGains(float _Xgain, float _Ygain, float _Zgain);
+        void setOffsets(int _Xoffset, int _Yoffset, int _Zoffset);
+        void setRevPolarity(bool _Xpol, bool _Ypol, bool _Zpol);  // true = Reversed  false = default
+    
+    
+        byte data[6];
+        int _rates[3];
+        I2C _device;
+        void writeReg(byte reg, byte value);
+        byte readReg(byte reg);
+        void enableDefault(void);
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/helper_3dmath.h	Wed Jul 17 18:50:28 2013 +0000
@@ -0,0 +1,216 @@
+// I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class, 3D math helper
+// 6/5/2012 by Jeff Rowberg <jeff@rowberg.net>
+// 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((float)(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_ */