blob: b61cbb60cf563e8a82ca2ad37dd0ca89e82972e1 [file] [log] [blame]
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define ADK_INTERNAL
#include "fwk.h"
#include "baro.h"
#include "I2C.h"
static struct {
int16_t AC1;
int16_t AC2;
int16_t AC3;
uint16_t AC4;
uint16_t AC5;
uint16_t AC6;
int16_t B1;
int16_t B2;
int16_t MB;
int16_t MC;
int16_t MD;
} baro;
#define BARO_REG_CTRL 0xF4
#define BARO_REG_OUT_MSB 0xF6
#define BARO_REG_OUT_LSB 0xF7
#define BARO_REG_OUT_XLSB 0xF8
#define BARO_SCO 0x20
char baroInit(void){ //0 on failure
if(i2cSingleRead(1, 0x77, 0xD0) != 0x55) return 0; //not found
baro.AC1 = (i2cSingleRead(1, 0x77, 0xAA) << 8) | i2cSingleRead(1, 0x77, 0xAB);
baro.AC2 = (i2cSingleRead(1, 0x77, 0xAC) << 8) | i2cSingleRead(1, 0x77, 0xAD);
baro.AC3 = (i2cSingleRead(1, 0x77, 0xAE) << 8) | i2cSingleRead(1, 0x77, 0xAF);
baro.AC4 = (i2cSingleRead(1, 0x77, 0xB0) << 8) | i2cSingleRead(1, 0x77, 0xA1);
baro.AC5 = (i2cSingleRead(1, 0x77, 0xB2) << 8) | i2cSingleRead(1, 0x77, 0xA3);
baro.AC6 = (i2cSingleRead(1, 0x77, 0xB4) << 8) | i2cSingleRead(1, 0x77, 0xA5);
baro.B1 = (i2cSingleRead(1, 0x77, 0xB6) << 8) | i2cSingleRead(1, 0x77, 0xA7);
baro.B2 = (i2cSingleRead(1, 0x77, 0xB8) << 8) | i2cSingleRead(1, 0x77, 0xA9);
baro.MB = (i2cSingleRead(1, 0x77, 0xBA) << 8) | i2cSingleRead(1, 0x77, 0xBB);
baro.MC = (i2cSingleRead(1, 0x77, 0xBC) << 8) | i2cSingleRead(1, 0x77, 0xBD);
baro.MD = (i2cSingleRead(1, 0x77, 0xBE) << 8) | i2cSingleRead(1, 0x77, 0xBF);
return 1;
}
void baroRead(uint8_t oss, long* kPa, long* decicelsius){
long ut, up, x1, x2, x3, b3, b4, b5, b6, p, t;
unsigned long b7;
// Read uncompensated temp
oss = oss & 0x03; // Mask off to protect bits
i2cSingleWrite(1, 0x77, BARO_REG_CTRL, 0x2E);
while(i2cSingleRead(1, 0x77, BARO_REG_CTRL) & BARO_SCO) {}
ut = (i2cSingleRead(1, 0x77, BARO_REG_OUT_MSB) << 8) | i2cSingleRead(1, 0x77, BARO_REG_OUT_LSB);
// Read uncompensated pressure
i2cSingleWrite(1, 0x77, BARO_REG_CTRL, 0x34 | (oss << 6));
while(i2cSingleRead(1, 0x77, BARO_REG_CTRL) & BARO_SCO) {}
up = ((i2cSingleRead(1, 0x77, BARO_REG_OUT_MSB) << 16) | (i2cSingleRead(1, 0x77, BARO_REG_OUT_LSB) << 8)
| i2cSingleRead(1, 0x77, BARO_REG_OUT_XLSB)) >> (8 - oss);
// Calculate true temperature (in 0.1 degrees C)
x1 = ((ut - baro.AC6) * baro.AC5) >> 15;
x2 = (baro.MC << 11) / (x1 + baro.MD);
b5 = x1 + x2;
t = (b5 + 8) >> 4;
if(decicelsius) *decicelsius = t;
// Calculate true pressure
b6 = b5 - 4000;
x1 = (baro.B2 * ((b6 * b6) >> 12)) >> 11;
x2 = (baro.AC2 * b6) >> 11;
x3 = x1 + x2;
b3 = (((baro.AC1 * 4 + x3) << oss) + 2) / 4;
x1 = (baro.AC3 * b6) >> 13;
x2 = (baro.B1 * ((b6 * b6) >> 12)) >> 16;
x3 = ((x1 + x2) + 2) >> 2;
b4 = (baro.AC4 * (unsigned long)(x3 + 32768)) >> 15;
b7 = ((unsigned long)up - b3) * (50000 >> oss);
if (b7 < 0x80000000) {
p = (b7 * 2) / b4;
} else {
p = (b7 / b4) * 2;
}
x1 = ((p >> 3) * (p >> 3)) >> 10; // Split because they seem to be using floating point in the datasheet example
x1 = (x1 * 3038) >> 16;
x2 = (-7357 * p) >> 16;
p = p + ((x1 + x2 + 3791) >> 4);
if(kPa) *kPa = p;
}