
#define BMP085_ADDR   (0x77<<1) 
#define BMP085_AC1      0xAA
#define BMP085_AC2      0xAC
#define BMP085_AC3      0xAE
#define BMP085_AC4      0xB0
#define BMP085_AC5      0xB2
#define BMP085_AC6      0xB4
#define BMP085_B1       0xB6
#define BMP085_B2       0xB8
#define BMP085_MB       0xBA
#define BMP085_MC       0xBC
#define BMP085_MD       0xBE
#define BMP085_CTRL     0xF4 
#define BMP085_CTRLOUT  0xF6 /* output 0xF6=MSB */
#define BMP085_READTEMP 0x2E
#define BMP085_READPRES 0x34

/* oversampling = oss. No samples, conv-time ,cur, resolution  
oss #    ms   uA  Pa  m 
------------------------
0   1   4.5   3   6  0.5
1   2   7.5   5   5  0.4
2   4  13.5   7   4  0.3
3   8  25.5  12   3  0.25
*/

struct {
  int16_t ac1;
  int16_t ac2;
  int16_t ac3;
  int16_t b1;
  int16_t b2; 
  int16_t b5;  /* Raw temp */
  int16_t mb; 
  int16_t mc; 
  int16_t md;
  uint16_t ac4; 
  uint16_t ac5; 
  uint16_t ac6;
  int32_t temp;
  int32_t pres;
  double alt;
  uint8_t cali;
} b85;

void bmp085_calbr(void) 
{
	uint8_t buf[2];
	memset(buf, 0, sizeof(buf));

	i2c_read_mem(BMP085_ADDR, BMP085_AC1, buf, 2);
	b85.ac1 = ((int)buf[0] <<8 | ((int) buf[1]));
	i2c_read_mem(BMP085_ADDR, BMP085_AC2, buf, 2);
	b85.ac2 = ((int)buf[0] <<8 | ((int) buf[1]));
	i2c_read_mem(BMP085_ADDR, BMP085_AC3, buf, 2);
	b85.ac3 = ((int)buf[0] <<8 | ((int) buf[1]));
	i2c_read_mem(BMP085_ADDR, BMP085_AC4, buf, 2);
	b85.ac4 = ((uint8_t)buf[0] <<8 | ((uint8_t) buf[1]));
	i2c_read_mem(BMP085_ADDR, BMP085_AC5, buf, 2);
	b85.ac5 = ((uint8_t)buf[0] <<8 | ((uint8_t) buf[1]));
	i2c_read_mem(BMP085_ADDR, BMP085_AC6, buf, 2);
	b85.ac6 = ((uint8_t)buf[0] <<8 | ((uint8_t) buf[1]));
	i2c_read_mem(BMP085_ADDR, BMP085_B1, buf, 2);
	b85.b1 = ((int)buf[0] <<8 | ((int) buf[1]));
	i2c_read_mem(BMP085_ADDR, BMP085_B2, buf, 2);
	b85.b2 = ((int)buf[0] <<8 | ((int) buf[1]));
	i2c_read_mem(BMP085_ADDR, BMP085_MB, buf, 2);
	b85.mb = ((int)buf[0] <<8 | ((int) buf[1]));
	i2c_read_mem(BMP085_ADDR, BMP085_MC, buf, 2);
	b85.mc = ((int)buf[0] <<8 | ((int) buf[1]));
	i2c_read_mem(BMP085_ADDR, BMP085_MD, buf, 2);
	b85.md = ((int)buf[0] <<8 | ((int) buf[1]));
}

void bmp085_read(uint8_t oss, int8_t temp, uint8_t npres, int8_t alt)
{
  int32_t  ut, up, x1, x2, x3, b3, b6, p;
  uint32_t  pres, b4, b7;
  uint8_t  i, buf[3];
  memset(buf, 0, sizeof(buf));

  /* Get calibration values only once */ 
  if(b85.cali == 0) {
    bmp085_calbr();
    b85.cali = 1; 
  }

  if( temp) {
    i2c_write_mem(BMP085_ADDR, BMP085_CTRL, BMP085_READTEMP);
    delay_ms(5); /* min. 4.5ms for temp */
    i2c_read_mem(BMP085_ADDR, BMP085_CTRLOUT, buf, 2);
    ut = ((int32_t)buf[0] << 8 | ((int32_t)buf[1])); /* uncompensated temp value */

    x1 = (ut - b85.ac6) * b85.ac5 >> 15;  /* Calculate true temp*/
    x2 = ((int32_t ) b85.mc << 11) / (x1 + b85.md);
    b85.b5 = x1 + x2;
    b85.temp = (b85.b5 + 8) >> 4;
  }

  for(i = 0, pres = 0; i < npres; i++) {

    /* read raw pressure */
    i2c_write_mem(BMP085_ADDR, BMP085_CTRL, BMP085_READPRES + (oss << 6));
    delay_ms(2 + (3 << oss));
    i2c_read_mem(BMP085_ADDR, BMP085_CTRLOUT, buf, 3);

    /* calculate true pressure */
    up = ((((int32_t)buf[0] <<16) | ((int32_t)buf[1] <<8) | ((int32_t)buf[2])) >> (8 - oss)); 
    b6 = b85.b5 - 4000;
    x1 = (b85.b2 * (b6 * b6) >> 12) >> 11; 
    x2 = b85.ac2 * b6 >> 11;
    x3 = x1 + x2;
    b3 = ((( (int32_t) b85.ac1 * 4 + x3) << oss) + 2) >> 2; /* BUG i Bosh Code */
    x1 = b85.ac3 * b6 >> 13;
    x2 = (b85.b1 * (b6 * b6 >> 12)) >> 16;
    x3 = ((x1 + x2) + 2) >> 2;
    b4 = (b85.ac4 * (uint32_t ) (x3 + 32768)) >> 15;
    b7 = ((uint32_t ) up - b3) * (50000 >> oss);
    p = b7 < 0x80000000 ? (b7 * 2) / b4 : (b7 / b4) * 2;
    x1 = (p >> 8) * (p >> 8);
    x1 = (x1 * 3038) >> 16;
    x2 = (-7357 * p) >> 16;
    pres += p + ((x1 + x2 + 3791) >> 4);
  }
  if(npres) 
    b85.pres = (uint32_t ) pres/npres;

  if(alt && b85.pres)
     b85.alt = ((1 - pow(b85.pres/(double)101325, 0.1903 )) / 0.0000225577);
}
