High resolution barometer and altimeter using i2c mode. Adapted to FreeIMU interface

Dependents:   FreeIMU FreeIMU_external_magnetometer FreeIMU

Fork of ms5611 by Kevin Braun

Revision:
8:f3660f819e54
Parent:
7:8545a1d1d1e4
Child:
9:9f1d38b8d7c3
--- a/MS561101BA.cpp	Sat Nov 02 17:23:33 2013 +0000
+++ b/MS561101BA.cpp	Sat Nov 09 08:51:15 2013 +0000
@@ -24,48 +24,57 @@
 */
 
 #include "mbed.h"
+#include "rtos.h"
+#include "MODI2C.h"
 #include "MS561101BA.h"
-#define CONVERSION_TIME 12000l // conversion time in microseconds
 
-MS561101BA::MS561101BA():i2c(I2C_SDA,I2C_SCL){
-}
+#ifndef I2C_SDA
+    #define I2C_SDA p28
+    #define I2C_SCL p27
+#endif
 
-MS561101BA::MS561101BA(I2C _i2c):i2c(_i2c) {
-  ;
+MS561101BA::MS561101BA():i2c(I2C_SDA,I2C_SCL),_thread(&MS561101BA::samplingthread_stub, this),sem(0){
+    zero = 0;
+    MS561101BA_RESET = 0x1E;
+    _OSR = NULL;
 }
 
 void MS561101BA::init(uint8_t address) {  
-lastPresConv=0;
-lastTempConv=0;
+    lastPresConv=0;
+    lastTempConv=0;
   t.start();
-  _addr =  address;
+  _addr =  address << 1;
  
   reset(); // reset the device to populate its internal PROM registers
-  wait_ms(500); // some safety time
+  Thread::wait(500); // some safety time
   readPROM(); // reads the PROM into object variables for later use
 }
 
-float MS561101BA::getPressure(uint8_t OSR) {
+void MS561101BA::samplingthread_stub(void const *p) {
+  MS561101BA *instance = (MS561101BA*)p;
+  instance->samplingthread();
+}
+
+float MS561101BA::getPressure() {
   // see datasheet page 7 for formulas
   
-  uint32_t rawPress = rawPressure(OSR);
-  if(rawPress == NULL) {
+  if(pressCache == NULL) {
     return NULL;
   }
   
-  int32_t dT = getDeltaTemp(OSR);
+  int32_t dT = getDeltaTemp();
   if(dT == NULL) {
     return NULL;
   }
   
   int64_t off  = ((uint32_t)_Cal[1] <<16) + (((int64_t)dT * _Cal[3]) >> 7);
   int64_t sens = ((uint32_t)_Cal[0] <<15) + (((int64_t)dT * _Cal[2]) >> 8);
-  return ((( (rawPress * sens ) >> 21) - off) >> 15) / 100.0;
+  return ((( (pressCache * sens ) >> 21) - off) >> 15) / 100.0;
 }
 
-float MS561101BA::getTemperature(uint8_t OSR) {
+float MS561101BA::getTemperature() {
   // see datasheet page 7 for formulas
-  int64_t dT = getDeltaTemp(OSR);
+  int64_t dT = getDeltaTemp();
   
   if(dT != NULL) {
     return (2000 + ((dT * _Cal[5]) >> 23)) / 100.0;
@@ -75,98 +84,77 @@
   }
 }
 
-int32_t MS561101BA::getDeltaTemp(uint8_t OSR) {
-  uint32_t rawTemp = rawTemperature(OSR);
-  if(rawTemp != NULL) {
-    return (int32_t)(rawTemp - ((uint32_t)_Cal[4] << 8));
+int32_t MS561101BA::getDeltaTemp() {
+  if(tempCache != NULL) {
+    return (int32_t)(tempCache - ((uint32_t)_Cal[4] << 8));
   }
   else {
     return NULL;
   }
 }
 
-//TODO: avoid duplicated code between rawPressure and rawTemperature methods
-//TODO: possible race condition between readings.. serious headache doing this.. help appreciated!
+void MS561101BA::samplingthread(){
+    Thread::signal_wait(0x1);
+    for (;;){
+        char command = MS561101BA_D1 + _OSR;
+        startConversion(&command);
+        Thread::wait(13);
+        getConversion();
+        sem.wait();
+        pressCache = conversion;
+        command = MS561101BA_D2 + _OSR;
+        startConversion(&command);
+        Thread::wait(13);
+        getConversion();
+        sem.wait();
+        tempCache = conversion;
+        Thread::yield();
+    }
+}
 
-uint32_t MS561101BA::rawPressure(uint8_t OSR) {
-  uint32_t now = t.read_us();
-  if(lastPresConv != 0 && (now - lastPresConv) >= CONVERSION_TIME) {
-    lastPresConv = 0;
-    pressCache = getConversion(MS561101BA_D1 + OSR);
-  }
-  else {
-    if(lastPresConv == 0 && lastTempConv == 0) {
-      startConversion(MS561101BA_D1 + OSR);
-      lastPresConv = now;
-    }
-  }
-  return pressCache;
+void MS561101BA::start_sampling(uint8_t OSR){
+    _OSR = OSR;
+    _thread.signal_set(0x1);
 }
 
-uint32_t MS561101BA::rawTemperature(uint8_t OSR) {
-  unsigned long now = t.read_us();
-  if(lastTempConv != 0 && (now - lastTempConv) >= CONVERSION_TIME) {
-    lastTempConv = 0;
-    tempCache = getConversion(MS561101BA_D2 + OSR);
-  }
-  else {
-    if(lastTempConv == 0 && lastPresConv == 0) { // no conversions in progress
-      startConversion(MS561101BA_D2 + OSR);
-      lastTempConv = now;
-    }
-  }
-  return tempCache;
+int MS561101BA::rawTemperature(){
+    return tempCache;
 }
 
+int MS561101BA::rawPressure(){
+    return pressCache;
+}
 
 // see page 11 of the datasheet
-void MS561101BA::startConversion(uint8_t command) {
+void MS561101BA::startConversion(char *command) {
   // initialize pressure conversion
-  i2c.start();
-  i2c.write(_addr<<1);
-  i2c.write(command);
-  i2c.stop();
+  i2c.write(_addr, (char*)command, 1);
 }
 
-uint32_t MS561101BA::getConversion(uint8_t command) {
-  uint32_t conversion = 0;
-  
-  // start read sequence
-  /*Wire.beginTransmission(_addr);
-  Wire.write(0);
-  Wire.endTransmission();*/
-  i2c.start();
-  i2c.write(_addr<<1);
-  i2c.write(0);
-  i2c.stop();
-  
-  //Wire.beginTransmission(_addr);
-  //Wire.requestFrom(_addr, (uint8_t) MS561101BA_D1D2_SIZE);
-  char cobuf[3];
-  if (i2c.read((_addr<<1)+1, cobuf, MS561101BA_D1D2_SIZE)!=0) {conversion=0xFFFFFFFF;}else{
-    conversion = (cobuf[0] << 16) + (cobuf[1] << 8) + cobuf[2];
-  }
-  return conversion;
+uint32_t getConversion_fin(uint32_t param){
+    MS561101BA* ins = (MS561101BA*)param;
+    ins->conversion = (ins->cobuf[0] << 16) + (ins->cobuf[1] << 8) + ins->cobuf[2];
+    ins->sem.release();
+    return 0;
 }
 
+void MS561101BA::getConversion() {
+  i2c.write(_addr, (char*)&zero, 1);
+  i2c.read_nb(_addr, (char*)cobuf, MS561101BA_D1D2_SIZE, &getConversion_fin, this);
+}
 
 /**
  * Reads factory calibration and store it into object variables.
 */
 int MS561101BA::readPROM() {
   for (int i=0;i<MS561101BA_PROM_REG_COUNT;i++) {
-    /*Wire.beginTransmission(_addr);
-    Wire.write(MS561101BA_PROM_BASE_ADDR + (i * MS561101BA_PROM_REG_SIZE));
-    Wire.endTransmission();*/
-    i2c.start();
-    i2c.write(_addr<<1);
-    i2c.write(MS561101BA_PROM_BASE_ADDR + (i * MS561101BA_PROM_REG_SIZE));
-    i2c.stop();
+    char a = MS561101BA_PROM_BASE_ADDR + (i * MS561101BA_PROM_REG_SIZE);
+    i2c.write(_addr, &a, 1);
     
     char tmp[2];
-    if (i2c.read((_addr<<1)+1, tmp, MS561101BA_PROM_REG_SIZE)!=0) return -1;
-    _Cal[i] = tmp[0]<<8 | tmp[1];
-    wait_ms(200);
+    if (i2c.read(_addr, tmp, MS561101BA_PROM_REG_SIZE)!=0) return -1;
+    _Cal[i] = tmp[0] <<8 | tmp[1];
+    Thread::wait(200);
   }
   return 0;
 }
@@ -177,11 +165,5 @@
  * populates its internal registers with the values read from the PROM.
 */
 void MS561101BA::reset() {
-  /*Wire.beginTransmission(_addr);
-  Wire.write(MS561101BA_RESET);
-  Wire.endTransmission();*/
-  i2c.start();
-  i2c.write(_addr<<1);
-  i2c.write(MS561101BA_RESET);
-  i2c.stop();
+  i2c.write(_addr, (char*)&MS561101BA_RESET, 1);
 }