/****************************************************************************
* BMP180.cpp - BMP180/I2C (Digital Pressure Sensor) library for Arduino     *
* Copyright 2010-2012 Filipe Vieira & various contributors                  *
*                                                                           *
* This file is part of BMP180 Arduino library.                              *
*                                                                           *
* This library is free software: you can redistribute it and/or modify      *
* it under the terms of the GNU Lesser General Public License as published  *
* by the Free Software Foundation, either version 3 of the License, or      *
* (at your option) any later version.                                       *
*                                                                           *
* 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 Lesser General Public License for more details.                       *
*                                                                           *
* You should have received a copy of the GNU Lesser General Public License  *
* along with this program.  If not, see <http://www.gnu.org/licenses/>.     *
****************************************************************************/
/****************************************************************************
* Tested on Arduino Mega with BMP180 Breakout                               *
* SDA   -> pin 20   (no pull up resistors)                                  *
* SCL   -> pin 21   (no pull up resistors)                                  *
* XCLR  -> not connected                                                    *
* EOC   -> not connected                                                    *
* GND   -> pin GND                                                          *
* VCC   -> pin 3.3V                                                         *
* NOTE: SCL and SDA needs pull-up resistors for each I2C bus.               *
*  2.2kOhm..10kOhm, typ. 4.7kOhm                                            *
*****************************************************************************/
#include <Wire.h>
#include <BMP180.h>


// ask for temperature measruement
void BMP180::startTemperature(){
writemem(CONTROL, READ_TEMPERATURE);
}
// 4.5ms delay to read temperature
void BMP180::readTemperature(){
  long ut,x1,x2;
  readmem(CONTROL_OUTPUT, 2, _buff); 
  ut = ((long)_buff[0] << 8 | ((long)_buff[1]));    // uncompensated temperature value
  
  // calculate temperature
  x1 = ((long)ut - ac6) * ac5 >> 15;
  x2 = ((long)mc << 11) / (x1 + md);
  b5 = x1 + x2;
}

void BMP180::getTemperature(int32_t *_Temperature) {                         // force b5 update
  *_Temperature = ((b5 + 8) >> 4);
}

// ask for pressure measurement  //
void BMP180::startPressure() {
 writemem(CONTROL, READ_PRESSURE+(OSS << 6));
}
// needs b5 to be calculated first by calling read temperature // delay depends on oversampling
void BMP180::readPressure(long *_TruePressure) {
  long up,x1,x2,x3,b3,b6,p;
  unsigned long b4,b7;
  int32_t tmp; 
  readmem(CONTROL_OUTPUT, 3, _buff);  
  up = ((((long)_buff[0] <<16) | ((long)_buff[1] <<8) | ((long)_buff[2])) >> (8-OSS)); // uncompensated pressure value
  
  // calculate true pressure
  b6 = b5 - 4000;             // b5 is updated by calcTrueTemperature().
  x1 = (b2* (b6 * b6 >> 12)) >> 11;
  x2 = ac2 * b6 >> 11;
  x3 = x1 + x2;
  tmp = ac1;
  tmp = (tmp * 4 + x3) << OSS;
  b3 = (tmp + 2) >> 2;
  x1 = ac3 * b6 >> 13;
  x2 = (b1 * (b6 * b6 >> 12)) >> 16;
  x3 = ((x1 + x2) + 2) >> 2;
  b4 = (ac4 * (uint32_t) (x3 + 32768)) >> 15;
  b7 = ((uint32_t)up - b3) * (50000 >> OSS);
  p = b7 < 0x80000000 ? (b7 << 1) / b4 : (b7 / b4) << 1;
  x1 = (p >> 8) * (p >> 8);
  x1 = (x1 * 3038) >> 16;
  x2 = (-7357 * p) >> 16;
  *_TruePressure = p + ((x1 + x2 + 3791) >> 4);
}

void BMP180::getAltitude(long *P, float *P0, float *_meters){
   *_meters = 4946.54 *(-pow(*P, 0.1902632) + pow(*P0, 0.1902632)) ;  
  }

void BMP180::onetimepressure(long *press){
   startTemperature();  
   delay(5); // 4.5 ms wair for temperature reading
   readTemperature();
   startPressure();
   delay(5);
   readPressure(press);
}


//PRIVATE methods

void BMP180::getCalData() {
  readmem(CAL_AC1, 2, _buff);
  ac1 = ((int)_buff[0] <<8 | ((int)_buff[1]));
  readmem(CAL_AC2, 2, _buff);
  ac2 = ((int)_buff[0] <<8 | ((int)_buff[1]));
  readmem(CAL_AC3, 2, _buff);
  ac3 = ((int)_buff[0] <<8 | ((int)_buff[1]));
  readmem(CAL_AC4, 2, _buff);
  ac4 = ((unsigned int)_buff[0] <<8 | ((unsigned int)_buff[1]));
  readmem(CAL_AC5, 2, _buff);
  ac5 = ((unsigned int)_buff[0] <<8 | ((unsigned int)_buff[1]));
  readmem(CAL_AC6, 2, _buff);
  ac6 = ((unsigned int)_buff[0] <<8 | ((unsigned int)_buff[1])); 
  readmem(CAL_B1, 2, _buff);
  b1 = ((int)_buff[0] <<8 | ((int)_buff[1])); 
  readmem(CAL_B2, 2, _buff);
  b2 = ((int)_buff[0] <<8 | ((int)_buff[1])); 
  readmem(CAL_MB, 2, _buff);
  mb = ((int)_buff[0] <<8 | ((int)_buff[1]));
  readmem(CAL_MC, 2, _buff);
  mc = ((int)_buff[0] <<8 | ((int)_buff[1]));
  readmem(CAL_MD, 2, _buff);
  md = ((int)_buff[0] <<8 | ((int)_buff[1])); 
}


void BMP180::writemem(uint8_t _addr, uint8_t _val) {
  Wire.beginTransmission( _dev_address);   // start transmission to device 
  Wire.write(_addr); // send register address
  Wire.write(_val); // send value to write  
  Wire.endTransmission(); // end transmission
}

void BMP180::readmem(uint8_t _addr, uint8_t _nbytes, uint8_t __buff[]) {
  Wire.beginTransmission( _dev_address); // start transmission to device 
  Wire.write(_addr); // sends register address to read from
  Wire.endTransmission(); // end transmission
  
  Wire.beginTransmission( _dev_address); // start transmission to device 
  Wire.requestFrom( _dev_address, _nbytes);// send data n-bytes read
  uint8_t i = 0; 
  while (Wire.available()) {
    __buff[i] = Wire.read(); // receive DATA
    i++;
  }
  Wire.endTransmission(); // end transmission
}


