Library for driving the MMA8452 accelerometer over I2C

Dependents:   MMA8452_Test MMA8452_Demo Dualing_Tanks IMU-Controlled_MP3_Player ... more

Here is a simple example:

#include "mbed.h"
#include "MMA8452.h"

int main() {
   Serial pc(USBTX,USBRX);
   pc.baud(115200);
   double x = 0, y = 0, z = 0;

   MMA8452 acc(p28, p27, 40000);
   acc.setBitDepth(MMA8452::BIT_DEPTH_12);
   acc.setDynamicRange(MMA8452::DYNAMIC_RANGE_4G);
   acc.setDataRate(MMA8452::RATE_100);
   
   while(1) {
      if(!acc.isXYZReady()) {
         wait(0.01);
         continue;
      }
      acc.readXYZGravity(&x,&y,&z);
      pc.printf("Gravities: %lf %lf %lf\r\n",x,y,z);
   }
}

An easy way to test that this actually works is to run the loop above and hold the MMA8452 parallel to the ground along the respective axis (and upsidedown in each axis). You will see 1G on the respective axis and 0G on the others.

Files at this revision

API Documentation at this revision

Comitter:
ashleymills
Date:
Tue Mar 04 16:23:40 2014 +0000
Parent:
10:ca9ba7ad4e94
Child:
12:172540ff6b8b
Commit message:
Started a major rewrite of this library.

Changed in this revision

MMA8452.cpp Show annotated file Show diff for this revision Revisions of this file
MMA8452.h Show annotated file Show diff for this revision Revisions of this file
--- a/MMA8452.cpp	Tue Mar 04 11:14:34 2014 +0000
+++ b/MMA8452.cpp	Tue Mar 04 16:23:40 2014 +0000
@@ -1,4 +1,4 @@
-// Author: Nicholas Herriot
+// Author: Nicholas Herriot, Ashley Mills
 /* Copyright (c) 2013 Vodafone, MIT License
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
@@ -17,15 +17,20 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
-# include "MMA8452.h"
+#include "MMA8452.h"
+#include "mbed.h"
+
+extern Serial pc;
 
 // Connect module at I2C address using I2C port pins sda and scl
-MMA8452::MMA8452(PinName sda, PinName scl,int frequency) : m_i2c(sda, scl) , m_frequency(frequency) {
-    //m_i2c.frequency(m_frequency);
-    
-    // setup read and write addresses to avoid duplication
-   _readAddress   = (MMA8452_ADDRESS<<1) | 0x01;
-   _writeAddress  = (MMA8452_ADDRESS<<1) & 0xFE;
+MMA8452::MMA8452(PinName sda, PinName scl, int frequency) : _i2c(sda, scl) , _frequency(frequency) {
+   DBG("Creating MMA8452");
+   _i2c.frequency(_frequency);
+   
+   // setup read and write addresses to avoid duplication
+   _readAddress   = MMA8452_ADDRESS | 0x01;
+   _writeAddress  = MMA8452_ADDRESS & 0xFE;
+   DBG("Done");
 }
 
 
@@ -34,99 +39,93 @@
 
 // Setting the control register bit 1 to true to activate the MMA8452
 int MMA8452::activate() {
-    // set control register 1 to active
-    char init[2] = {CTRL_REG_1,ACTIVE};
-    
     // perform write and return error code
-    return m_i2c.write(_writeAddress,init,2);
+    return logicalORRegister(CTRL_REG_1,MMA8452_ACTIVE_MASK);
 }
 
-
-// Get 'Fast Read Mode' called F_READ. If bit 1 is set '1' then F_READ is active. Fast read will skip LSB when reading xyz
-// resisters from 0x01 to 0x06. When F_READ is '0' then all 6 registers will be read.
-
-int MMA8452::get_CTRL_Reg1(int* dst)
-{   
-   return readRegister(CTRL_REG_1,dst); 
+// Setting the control register bit 1 to 0 to standby the MMA8452
+int MMA8452::standby() {
+    // perform write and return error code
+    return logicalANDRegister(CTRL_REG_1,MMA8452_STANDBY_MASK);
 }
 
-// Setting the control register bit 1 to true to activate the MMA8452
-int MMA8452::standby()
-{
-    // set control register 1 to standby
-    char init[2] = {CTRL_REG_1,STANDBY};
-    
-    // write to the register and return the error code
-    return m_i2c.write(_writeAddress,init,2);
+// this reads a register, applies a bitmask with logical AND, sets a value with logical OR,
+// and optionally goes into and out of standby at the beginning and end of the function respectively
+int MMA8452::maskAndApplyRegister(char reg, char mask, char value, int toggleActivation) {
+   if(toggleActivation) {
+       if(standby()) {
+          return 1;
+       }
+   }
+   
+   // read from register
+   char oldValue = 0;
+   if(readRegister(reg,&oldValue)) {
+      return 1;
+   }
+   
+   // apply bitmask
+   oldValue &= mask;
+   
+   // set value
+   oldValue |= value;
+   
+   // write back to register
+   if(writeRegister(reg,oldValue)) {
+      return 1;
+   }
+   
+   if(toggleActivation) {
+       if(activate()) {
+          return 1;
+       }
+   }
+   return 0;
 }
 
-
-
-// Device initialization
-void MMA8452::init()
-{
-    
-    writeRegister(INTSU_STATUS, 0x10);      // automatic interrupt after every measurement
-    writeRegister(SR_STATUS, 0x00);         // 120 Samples/Second
-    writeRegister(MODE_STATUS, 0x01);       // Active Mode
-    
+int MMA8452::setDynamicRange(DynamicRange range, int toggleActivation) {
+   return maskAndApplyRegister(
+      MMA8452_XYZ_DATA_CFG,
+      MMA8452_DYNAMIC_RANGE_MASK,
+      range,
+      toggleActivation
+   );
 }
 
-// Get real time status of device - it can be STANDBY, WAKE or SLEEP
-int MMA8452::getSystemMode(int *dst)
-{
-    return readRegister(SYSMOD,dst);
+int MMA8452::setDataRate(DataRateHz dataRate, int toggleActivation) {
+   return maskAndApplyRegister(
+       MMA8452_CTRL_REG_1,
+       MMA8452_DATA_RATE_MASK,
+       dataRate<<MMA8452_DATA_RATE_MASK_SHIFT,
+       toggleActivation
+   );
 }
 
-
-
-// Get real time status of device - it can be STANDBY, WAKE or SLEEP
-int MMA8452::getStatus(int* dst)
-{
-    return readRegister(STATUS,dst);
+int MMA8452::setBitDepth(BitDepth depth,int toggleActivation) {
+   return maskAndApplyRegister(
+      MMA8452_CTRL_REG_1,
+      MMA8452_BIT_DEPTH_MASK,
+      depth<<MMA8452_BIT_DEPTH_MASK_SHIFT,
+      toggleActivation
+   );
 }
 
 
 // Get device ID 
-int MMA8452::getDeviceID(int *dst)
+int MMA8452::getDeviceID(char *dst)
 {
     return readRegister(WHO_AM_I,dst);
 }
 
 
-/*
-// Reads x data
-int MMA8452::read_x(int& xaxisLSB)
-{
-    char mcu_address = (MMA8452_ADDRESS<<1);
-    m_i2c.start();
-    if( m_i2c.write( mcu_address & 0xFE) == 0)          // just good practice to force bit 1 to a '0' by ANDing with 0xFE
-    {
-        return 1;                                       // we failed to write the mcu address on the bus to initiate dialogue 
-    }
-    if( m_i2c.write( OUT_X_MSB) == 0) 
-    {
-        return 1;                                       // we failed to write 'X axis LSB' to the chip
-    }
-    m_i2c.start();
-    if( m_i2c.write( mcu_address | 0x01) == 0)          // this is asking to read the slave mcu address - even though it's a 'write' method!!! Crap API...
-    {
-        return 1;                                       // we failed to request a read from that mcu - this really is just writing the mcu vaule on the bus
-    }
-    xaxisLSB  = m_i2c.read(0);
-    m_i2c.stop();
-    return 0;
-}
-*/
-
 int MMA8452::readRaw(char src, char *dst, int len) {
     // this is the register we want to get data from               
     char register_address[1];
     register_address[0] = src;
     
-    if(m_i2c.write(_writeAddress,register_address,1,true) == 0)
+    if(_i2c.write(_writeAddress,register_address,1,true) == 0)
     {
-        if(m_i2c.read(_readAddress,dst,len)==0)
+        if(_i2c.read(_readAddress,dst,len)==0)
         {
            return 0;
         }
@@ -144,8 +143,7 @@
 // is set to '0'. It returns '0' success '1' fail. This method does nothing to the registers - just returns
 // the raw data.
 //int MMA8452::read_x(int& xaxisLSB)
-int MMA8452::readRawX(char *xaxis)
-{   
+int MMA8452::readRawX(char *xaxis) {   
     return readRaw(OUT_X_MSB,xaxis,2);  
 }
 
@@ -178,37 +176,57 @@
 {
     char mcu_address = (MMA8452_ADDRESS <<1);
 
-    m_i2c.start();                  // Start
-    m_i2c.write(mcu_address);              // A write to device 0x98
-    m_i2c.write(OUT_Y_MSB);             // Register to read
-    m_i2c.start();                  
-    m_i2c.write(mcu_address);              // Read from device 0x99
-    int y = m_i2c.read(0);         // Read the data
-    m_i2c.stop();
+    _i2c.start();                  // Start
+    _i2c.write(mcu_address);              // A write to device 0x98
+    _i2c.write(OUT_Y_MSB);             // Register to read
+    _i2c.start();                  
+    _i2c.write(mcu_address);              // Read from device 0x99
+    int y = _i2c.read(0);         // Read the data
+    _i2c.stop();
     
     return y; 
 
 }
 
-
 // Reads z data
 int MMA8452::read_z()
 {
     char mcu_address = (MMA8452_ADDRESS <<1);
     
-    m_i2c.start();                  // Start
-    m_i2c.write(mcu_address);              // A write to device 0x98
-    m_i2c.write(OUT_Z_MSB);             // Register to read
-    m_i2c.start();                  
-    m_i2c.write(mcu_address);              // Read from device 0x99
-    int z = m_i2c.read(0);         // Read the data
-    m_i2c.stop();
+    _i2c.start();                  // Start
+    _i2c.write(mcu_address);              // A write to device 0x98
+    _i2c.write(OUT_Z_MSB);             // Register to read
+    _i2c.start();                  
+    _i2c.write(mcu_address);              // Read from device 0x99
+    int z = _i2c.read(0);         // Read the data
+    _i2c.stop();
     
     return z;
 
 }
 
 
+MMA8452::DynamicRange MMA8452::getDynamicRange() {
+   char rval = 0;
+   if(readRegister(MMA8452_CTRL_REG_1,&rval)) {
+      return MMA8452::DYNAMIC_RANGE_UNKNOWN;
+   }
+   rval &= (MMA8452_DYNAMIC_RANGE_MASK^0xFF);
+   return (MMA8452::DynamicRange)rval;
+}
+
+MMA8452::DataRateHz MMA8452::getDataRate() {
+   char rval = 0;
+   if(readRegister(MMA8452_CTRL_REG_1,&rval)) {
+      return MMA8452::RATE_UNKNOWN;
+   }
+   // logical AND with inverse of mask
+   rval = rval&(MMA8452_DATA_RATE_MASK^0xFF);
+   // shift back into position
+   rval >>= MMA8452_DATA_RATE_MASK_SHIFT;
+   return (MMA8452::DataRateHz)rval;
+}
+
 // Reads xyz
 int MMA8452::readRawXYZ(char *x, char *y, char *z) 
 {
@@ -217,12 +235,12 @@
     char mcu_address = (MMA8452_ADDRESS <<1);
     char register_buffer[6] ={0,0,0,0,0,0};
     const char Addr_X = OUT_X_MSB;
-    m_i2c.write(mcu_address);              // A write to device 0x98
-    m_i2c.write(MMA8452_ADDRESS, &Addr_X, 1);         // Pointer to the OUT_X_MSB register
+    _i2c.write(mcu_address);              // A write to device 0x98
+    _i2c.write(MMA8452_ADDRESS, &Addr_X, 1);         // Pointer to the OUT_X_MSB register
     
-    if(m_i2c.write(mcu_address,&Addr_X,1) == 0)
+    if(_i2c.write(mcu_address,&Addr_X,1) == 0)
     {
-        if(m_i2c.read(mcu_address,register_buffer,6) == 0)
+        if(_i2c.read(mcu_address,register_buffer,6) == 0)
         {
             *x = register_buffer[1];
             *y = register_buffer[3];
@@ -241,47 +259,159 @@
 
 }
 
-        // Write register (The device must be placed in Standby Mode to change the value of the registers) 
-void MMA8452::writeRegister(char addr, char data)
-{
+// apply an AND mask to a register. read register value, apply mask, write it back
+int MMA8452::logicalANDRegister(char addr, char mask) {
+   char value = 0;
+   // read register value
+   if(readRegister(addr,&value)) {
+      return 0;
+   }
+   // apply mask
+   value &= mask;
+   return writeRegister(addr,value);
+}
+
+
+// apply an OR mask to a register. read register value, apply mask, write it back
+int MMA8452::logicalORRegister(char addr, char mask) {
+   char value = 0;
+   // read register value
+   if(readRegister(addr,&value)) {
+      return 0;
+   }
+   // apply mask
+   value |= mask;
+   return writeRegister(addr,value);
+}
+
 
-    char cmd[2] = {0, 0};
-    
-    cmd[0] = MODE_STATUS;
-    cmd[1] = 0x00;                      // Standby Mode on
-    m_i2c.write(MMA8452_ADDRESS, cmd, 2);
-  
-    cmd[0] = addr;
-    cmd[1] = data;                      // New value of the register
-    m_i2c.write(MMA8452_ADDRESS, cmd, 2); 
-      
-    cmd[0] = MODE_STATUS;
-    cmd[1] = 0x01;                      // Active Mode on
-    m_i2c.write(MMA8452_ADDRESS, cmd, 2);
-                  
+// apply an OR mask to a register. read register value, apply mask, write it back
+int MMA8452::logicalXORRegister(char addr, char mask) {
+   char value = 0;
+   // read register value
+   if(readRegister(addr,&value)) {
+      return 0;
+   }
+   // apply mask
+   value ^= mask;
+   return writeRegister(addr,value);
+}
+
+// Write register (The device must be placed in Standby Mode to change the value of the registers) 
+int MMA8452::writeRegister(char addr, char data) {
+    // what this actually does is the following
+    // 1. tell I2C bus to start transaction
+    // 2. tell slave we want to write (slave address & write flag)
+    // 3. send the write address
+    // 4. send the data to write
+    // 5. tell I2C bus to end transaction
+
+    // we can wrap this up in the I2C library write function
+    char buf[2] = {0,0};
+    buf[0] = addr;
+    buf[1] = data;
+    return _i2c.write(MMA8452_ADDRESS, buf,2);
+    // note, could also do return writeRegister(addr,&data,1);
 }
 
-        // Read from specified MMA7660FC register
-int MMA8452::readRegister(char addr, int *dst)
-{
+
+int MMA8452::writeRegister(char addr, char *data, int nbytes) {
+    // writing multiple bytes is a little bit annoying because
+    // the I2C library doesn't support sending the address separately
+    // so we just do it manually
     
-    m_i2c.start();
-    if( m_i2c.write(_writeAddress) == 0)
-    {
-        return 1;                                   // we failed to write the mcu address on the bus to initiate dialogue 
+    // 1. tell I2C bus to start transaction
+    _i2c.start();
+    // 2. tell slave we want to write (slave address & write flag)
+    if(_i2c.write(_writeAddress)!=1) {
+       return 1;
+    }
+    // 3. send the write address
+    if(_i2c.write(addr)!=1) {
+       return 1;
+    }
+    // 4. send the data to write
+    for(int i=0; i<nbytes; i++) {
+       if(_i2c.write(data[i])!=1) {
+          return 1;
+       }
+    }
+    // 5. tell I2C bus to end transaction
+    _i2c.stop();
+    return 0;
+}
+
+int MMA8452::readRegister(char addr, char *dst, int nbytes) {
+    // this is a bit odd, but basically proceeds like this
+    // 1. Send a start command
+    // 2. Tell the slave we want to write (slave address & write flag)
+    // 3. Send the address of the register (addr)
+    // 4. Send another start command to delineate read portion
+    // 5. Tell the slave we want to read (slave address & read flag)
+    // 6. Read the register value bytes
+    // 7. Send a stop command
+    
+    // we can wrap this process in the I2C library read and write commands
+    if(_i2c.write(MMA8452_ADDRESS,&addr,1,true)) {
+       return 1;
     }
-    if( m_i2c.write(addr) == 0) 
-    {
-        return 1;                                       // we failed to write 'status' to the chip
-    }
-    m_i2c.start();
-    if( m_i2c.write(_readAddress) == 0)          // this is asking to read the slave mcu address - even though it's a 'write' method!!! Crap API...
-    {
-        return 1;                                       // we failed to request a read from that mcu - this really is just writing the mcu vaule on the bus
-    }
-    *dst = m_i2c.read(0);
-    m_i2c.stop();      
- 
-    return 0;
-    
+    return _i2c.read(MMA8452_ADDRESS,dst,nbytes);
+}
+
+// most registers are 1 byte, so here is a convenience function
+int MMA8452::readRegister(char addr, char *dst) {
+    return readRegister(addr,dst,1);
 }
+
+void MMA8452::debugRegister(char reg) {
+   // get register value
+   char v = 0;
+   if(readRegister(reg,&v)) {
+      DBG("Error reading control register");
+      return;
+   }
+   // print out details
+   switch(reg) {
+      case MMA8452_CTRL_REG_1:
+         DBG("CTRL_REG_1 has value: 0x%x",v);
+         DBG(" 7  ALSP_RATE_1: %d",(v&0x80)>>7);
+         DBG(" 6  ALSP_RATE_0: %d",(v&0x40)>>6);
+         DBG(" 5  DR2: %d",        (v&0x20)>>5);
+         DBG(" 4  DR1: %d",        (v&0x10)>>4);
+         DBG(" 3  DR0: %d",        (v&0x08)>>3);
+         DBG(" 2  LNOISE: %d",     (v&0x04)>>2);
+         DBG(" 1  FREAD: %d",      (v&0x02)>>1);
+         DBG(" 0  ACTIVE: %d",     (v&0x01));
+      break;
+        
+      case MMA8452_XYZ_DATA_CFG:
+         DBG("XYZ_DATA_CFG has value: 0x%x",v);
+         DBG(" 7  Unused: %d", (v&0x80)>>7);
+         DBG(" 6  0: %d",      (v&0x40)>>6);
+         DBG(" 5  0: %d",      (v&0x20)>>5);
+         DBG(" 4  HPF_Out: %d",(v&0x10)>>4);
+         DBG(" 3  0: %d",      (v&0x08)>>3);
+         DBG(" 2  0: %d",      (v&0x04)>>2);
+         DBG(" 1  FS1: %d",    (v&0x02)>>1);
+         DBG(" 0  FS0: %d",    (v&0x01));
+         switch(v&0x03) {
+            case 0:
+               DBG("Dynamic range: 2G");
+            break;
+            case 1:
+               DBG("Dynamic range: 4G");
+            break;
+            case 2:
+               DBG("Dynamic range: 8G");
+            break;
+            default:
+               DBG("Unknown dynamic range");
+            break;
+         }
+      break;
+      
+      default:
+         DBG("Unknown register address: 0x%x",reg);
+      break;
+   }
+}
\ No newline at end of file
--- a/MMA8452.h	Tue Mar 04 11:14:34 2014 +0000
+++ b/MMA8452.h	Tue Mar 04 16:23:40 2014 +0000
@@ -20,6 +20,10 @@
 // the SparkFun breakout board defaults to 1, set to 0 if SA0 jumper on the bottom of the board is set
 // see the Table 10. I2C Device Address Sequence in Freescale MMA8452Q pdf
 
+
+#define DBG(...) pc.printf(__VA_ARGS__); pc.printf("\r\n");
+#define DBGX(...) pc.print(__VA_ARGS__);
+
 //#define SA0 1
 //#if SA0
   //#define MMA8452_ADDRESS 0x3A  // SA0 is high, 0x1C if low - it should be 0x1D, but we shift now to save shifting in the code
@@ -64,9 +68,9 @@
 // More info on MCU Master address can be found on section 5.10.1 of http://www.freescale.com/webapp/sps/site/prod_summary.jsp?code=MMA8452Q
 #define SA0 1
 #if SA0
-  #define MMA8452_ADDRESS 0x1D  // SA0 is high, 0x1C if low - 
+  #define MMA8452_ADDRESS 0x3A // 0x1D<<1  // SA0 is high, 0x1C if low - 
 #else
-  #define MMA8452_ADDRESS 0x1C
+  #define MMA8452_ADDRESS 0x38 // 0x1C<<1
 #endif
 
 // Register descriptions found in section 6 of pdf
@@ -116,21 +120,53 @@
 #define PDET_STATUS 0x09        // Tap/Pulse Detection Register (Read/Write)
 #define PD_STATUS 0xA           // Tap/Pulse Debounce Count Register (Read/Write)
  
+#define MMA8452_ACTIVE_MASK 0x01
+#define MMA8452_STANDBY_MASK 0xFE
+ 
+#define MMA8452_XYZ_DATA_CFG 0x0E
+#define MMA8452_CTRL_REG_1 0x2A
+
+#define MMA8452_DYNAMIC_RANGE_MASK 0xFC
+
+
+#define MMA8452_DATA_RATE_MASK 0xC7
+#define MMA8452_DATA_RATE_MASK_SHIFT 0x03
+
+#define MMA8452_WRITE_MASK 0xFE
+#define MMA8452_READ_MASK 0x01
+
+#define MMA8452_BIT_DEPTH_MASK 0xFD
+#define MMA8452_BIT_DEPTH_MASK_SHIFT 0x01
+ 
 class MMA8452         
 {        
     public:
     
-       enum OperationalMode {
-           MODE_STANDBY,
-           MODE_ACTIVE_2G,
-           MODE_ACTIVE_4G,
-           MODE_ACTIVE_8G
+       enum DynamicRange {
+           DYNAMIC_RANGE_2G=0x00,
+           DYNAMIC_RANGE_4G,
+           DYNAMIC_RANGE_8G,
+           DYNAMIC_RANGE_UNKNOWN
        };
         
        enum BitDepth {
-           BIT_DEPTH_8,
-           BIT_DEPTH_12
+           BIT_DEPTH_12=0x00,
+           BIT_DEPTH_8 // 1 sets fast read mode, hence the inversion
        };
+       
+       enum DataRateHz {
+          RATE_800=0x00,
+          RATE_400,
+          RATE_200,
+          RATE_100,
+          RATE_50,
+          RATE_12_5,
+          RATE_6_25,
+          RATE_1_563,
+          RATE_UNKNOWN
+       };
+       
+       //void setDynamicRange(
         
        /** Create an accelerometer object connected to the specified I2C object
         *
@@ -145,26 +181,8 @@
         *
         */
       ~MMA8452();
-            
-      /** Get system mode of the MMA8452 (not required)
-        *   returns 0 for success in reading the system mode of the chip
-        *   returns 1 for failure in reading the system mode of the chip
-        *   -currently no retries or waiting is done, this method tries 1 time then exits.
-        *
-        *   This method is used to find out the system mode of the chip ACTIVE = 0x00 or STANDBY = 0x01
-      */
-      int getSystemMode(int *dst);    
       
-      /** Get status of the MMA8452 (not required)
-        *   returns 0 for success in reading the status of the chip
-        *   returns 1 for failure in reading the status of  the chip
-        *   -currrently no retries or waiting is done, this method tries 1 time then exits.
-        *
-        *   This method is used to find out the real time status of the device it shows if
-        *   x,y and z values have been overwritten before they have been read since a change happened.
-        *   
-      */
-      int getStatus(int *dst);
+      //int setOperationMode(OperationMode m);
       
       
       /** Activate the MMA8452 (required)
@@ -195,7 +213,7 @@
         *   This will return the state of the control register 1. This holds and sets values for auto wake, sleep mode
         *   output data rate, fast read mode and active/standby. More info on 6.7 of pdf for MMA8452 Freescale doc.
       */
-      int get_CTRL_Reg1(int* dst);
+      int get_CTRL_Reg1(char* dst);
       
       
        /** Initialization of device MMA8452 (required)
@@ -208,7 +226,7 @@
         * return 0 for success or
         * return 1 for failure.
         */        
-      int getDeviceID(int *dst);  
+      int getDeviceID(char* dst);  
       
       int read_y();
       
@@ -246,24 +264,36 @@
          * @param addr The internal registeraddress of the MMA8452
          * @returns The value of the register
          */
-      int readRegister(char addr, int *dst);
+      int readRegister(char addr, char *dst);
+      
+      int readRegister(char addr, char *dst, int nbytes);
         
         /** Write to specified MMA8452 register
         *
         * @param addr The internal registeraddress of the MMA8452
         * @param data New value of the register
         */    
-      void writeRegister(char addr, char data);
+      int writeRegister(char addr, char data);
+      int writeRegister(char addr, char *data, int nbytes);
+      
+      int logicalANDRegister(char addr, char mask);
+      int logicalORRegister(char addr, char mask);
+      int logicalXORRegister(char addr, char mask);
       
-      int setOperationalMode(OperationalMode m);
-      int setBitDepth(BitDepth b);
+      int setDynamicRange(DynamicRange range, int toggleActivation=1);
+      int setBitDepth(BitDepth depth, int toggleActivation=1);
+      int setDataRate(DataRateHz dataRate, int toggleActivation=1);
+      DynamicRange getDynamicRange();
+      DataRateHz getDataRate();
+      
+      void debugRegister(char reg);
    
     private:
       int readRaw(char src, char *dst, int len);
-    
+      int maskAndApplyRegister(char reg, char mask, char value, int toggleActivation);
     
-      I2C m_i2c;
-      int m_frequency;
+      I2C _i2c;
+      int _frequency;
       int _readAddress;
       int _writeAddress;