Driving

Dependencies:   FSR LIS3DH USBDevice mbed

Fork of MMA8452_Demo by Ivan Rush

main.cpp

Committer:
ashleymills
Date:
2014-03-05
Revision:
3:2a8e59a590db
Parent:
2:0630128bdb32
Child:
5:756f9b157319

File content as of revision 3:2a8e59a590db:

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

DigitalOut myled(LED1);

Serial pc(USBTX,USBRX);

#define LOG(...) pc.printf(__VA_ARGS__); pc.printf("\r\n");
#define LOGX(...) pc.printf(__VA_ARGS__);

void printByte(char b) {
   LOG("%d%d%d%d%d%d%d%d",
       (b&0x80)>>7,
       (b&0x40)>>6,
       (b&0x20)>>5,
       (b&0x10)>>4,
       (b&0x08)>>3,
       (b&0x04)>>2,
       (b&0x02)>>1,
       (b&0x01)
   );
}

void sampleMMA8452Raw(MMA8452 *acc, int nsamples) {
   int samples = 0;
   int bufLen = 6;
   char buffer[6];
   memset(&buffer,0x00,bufLen);
   while(samples<nsamples) {
      if(!acc->isXYZReady()) {
         wait(0.01);
         continue;
      }
      memset(&buffer,0x00,bufLen);
      acc->readXYZRaw(buffer);
      LOGX("Sample %d of %d: ",samples,nsamples);
      for(int i=0; i<bufLen; i++) {
         LOGX("%.2x ",buffer[i]);
      }
      LOG(" ");
      samples++;
   }
}

void sampleMMA8452Counts(MMA8452 *acc, int nsamples) {
   int samples = 0;
   int bufLen = 6;
   char buffer[6];
   int x = 0, y = 0, z = 0;
   memset(&buffer,0x00,bufLen);
   while(samples<nsamples) {
      if(!acc->isXYZReady()) {
         wait(0.01);
         continue;
      }
      memset(&buffer,0x00,bufLen);
      if(acc->readXYZCounts(&x,&y,&z)) {
         LOG("Error reading sample");
         break;
      }
      LOG("Sample %d of %d: %d, %d, %d",samples,nsamples,x,y,z);
      samples++;
   }
}

void sampleMMA8452Gravities(MMA8452 *acc, int nsamples) {
   int samples = 0;
   int bufLen = 6;
   char buffer[6];
   double x = 0, y = 0, z = 0;
   memset(&buffer,0x00,bufLen);
   while(samples<nsamples) {
      if(!acc->isXYZReady()) {
         wait(0.01);
         continue;
      }
      memset(&buffer,0x00,bufLen);
      if(acc->readXYZGravity(&x,&y,&z)) {
         LOG("Error reading sample");
         break;
      }
      LOG("Sample %d of %d: %lf, %lf, %lf",samples,nsamples,x,y,z);
      samples++;
   }
}

int test() {
    MMA8452 acc(p28, p27, 40000);
    
    acc.debugRegister(MMA8452_CTRL_REG_1);
    
    LOG("Entering standby");
    if(acc.standby()) {
       LOG("Error putting MMA8452 in standby");
       return false;
    }
    
    acc.debugRegister(MMA8452_CTRL_REG_1);
    
    LOG("Activating MMA8452");
    if(acc.activate()) {
       LOG("Error activating MMA8452");
       return false;
    }
    
    char devID = 0;
    if(acc.getDeviceID(&devID)) {
       LOG("Error getting device ID");
       return false;
    }
    LOG("DeviceID: 0x%x",devID);
    if(devID!=0x2a) {
       LOG("Error, fetched device ID: 0x%x does not match expected 0x2a",devID);
       return false;
    } else {
       LOG("Device ID OK");
    }
    
    // test setting dynamic range
    MMA8452::DynamicRange setRange = MMA8452::DYNAMIC_RANGE_UNKNOWN;
    MMA8452::DynamicRange readRange = MMA8452::DYNAMIC_RANGE_UNKNOWN;
    for(int i=0; i<=(int)MMA8452::DYNAMIC_RANGE_8G; i++) {
       setRange = (MMA8452::DynamicRange)i;
       if(acc.setDynamicRange(setRange)) {
          LOG("Error setting dynamic range. Failing.");
          return false;
       }
       readRange = acc.getDynamicRange();
       if(readRange!=setRange) {
          LOG("Read dynamic range: 0x%x does not match set: 0x%x",readRange,setRange);
          return false;
       }
       LOG("Success on dynamic range %d",i);
    }
    
    // test setting data rate
    for(int i=0; i<=(int)MMA8452::RATE_1_563; i++) {
       if(acc.setDataRate((MMA8452::DataRateHz)i)) {
          LOG("Error setting data rate. Failing.");
          return false;
       }
       if(acc.getDataRate()!=(MMA8452::DataRateHz)i) {
          LOG("Read data rate: 0x%x does not match set: 0x%x",acc.getDataRate(),(MMA8452::DataRateHz)i);
          return false;
       }
       LOG("Success on data rate %d",i);
    }
    
    // set bit depth to 8 and read some values
    LOG("Sampling at BIT_DEPTH_8");
    acc.setBitDepth(MMA8452::BIT_DEPTH_8);
    sampleMMA8452Raw(&acc,10);
    
    // set bit depth to 12 and read some values
    LOG("Sampling at BIT_DEPTH_12");
    acc.setDataRate(MMA8452::RATE_100);
    acc.setBitDepth(MMA8452::BIT_DEPTH_12);
    sampleMMA8452Raw(&acc,10);
   
    LOG("Sampling counts");
    acc.setDynamicRange(MMA8452::DYNAMIC_RANGE_2G);
    sampleMMA8452Counts(&acc,100);

    LOG("Samping gravities");
    acc.setBitDepth(MMA8452::BIT_DEPTH_8);
    acc.setDynamicRange(MMA8452::DYNAMIC_RANGE_4G);
    sampleMMA8452Gravities(&acc,2000);

    return true;
}

void loop() {
   while(1) {
      wait(1);
   }
}

void u16d(uint16_t n) {
   int shift = 16;
   uint16_t mask = 0x8000;
   while(--shift>=0) {
      LOGX("%d",(n&mask)>>shift);
      mask >>= 1;
   }
   LOG(" ");
}

int eightBitToSigned(char *buf) {
   return (int8_t)*buf;
}

int twelveBitToSigned(char *buf) {
   //LOG("Doing twos complement conversion for 0x%x 0x%x",buf[0],buf[1]);
   
   // cheat by using the int16_t internal type
   // all we need to do is convert to little-endian format and shift right
   int16_t x = 0;
   ((char*)&x)[1] = buf[0];
   ((char*)&x)[0] = buf[1];
   // note this only works because the below is an arithmetic right shift
   return x>>4; 

   // for reference, here is the full conversion, in case you port this somewhere where the above won't work
   /*
   uint16_t number = 0x0000;
   //u16d(number);
   int negative = false;
   
   // bit depth 12, is spread over two bytes
   // put it into a uint16_t for easy manipulation
   number |= (buf[0]<<8);
   number |= buf[1];

   // if this is a negative number take the twos complement
   if(number&0x8000) {
       negative = true;
       // flip all bits (doesn't matter about lower 4 bits)
       number ^= 0xFFFF;

       // add 1 (but do so in a way that deals with overflow and respects our current leftwise shift)
       number += 0x0010;
   }
   
   // shifting down the result by 4 bits gives us the absolute number
   number >>= 4;

   int result = number;
   if(negative) {
      result *= -1;
   }
   return result;
   */
}

int twosCompTest() {
    // 12 bits of number gives 2048 steps
    int16_t i = -2047;
    while(1) {
       //LOG("number: %d",i);
       //u16d(number);
       uint16_t shiftedNumber = i<<4;
       //LOG("shifted:");
       //u16d(shiftedNumber);
       // ARM is little endian whereas 12 bit 2's comp rep is big endian
       uint16_t flippedNumber = 0x0000;
       //LOG("switching bytes");
       //u16d(flippedNumber);
       ((char*)&flippedNumber)[0] = ((char*)&shiftedNumber)[1];
       
       //u16d(flippedNumber);
       ((char*)&flippedNumber)[1] = ((char*)&shiftedNumber)[0]; 
       
       //u16d(flippedNumber);
       int value = twelveBitToSigned((char*)&flippedNumber);
       //LOG("%d converts to %d",i,value);
       if(i!=value) {
          return false;
       }
       if(i==2047) {
          break;
       }
       i++;
    }
    
    int8_t n = -127;
    while(1) {
       int value = eightBitToSigned((char*)&n);
       //LOG("%d converts to %d",n,value);
       if(n!=value) {
          return false;
       }
       if(n==127) {
          break;
       }
       n++;
    }
 
    return true;
}

int main() {
    pc.baud(115200);
    LOG("Begin");
    if(!twosCompTest()) {
       LOG("twos comp test failed");
       loop();
    }
    LOG("twos comp test passed");
    //loop();
    for(int i=0; i<20; i++) {
       LOG(" ");
    }
    if(!test()) {
       LOG("FAIL.");
       loop();
    }
    LOG("Tests passed");
    loop();
}