78 lines
2.2 KiB
C
78 lines
2.2 KiB
C
|
/* BMP280 value compensation code, from the datasheet. */
|
||
|
|
||
|
#include "bmp280_comp.h"
|
||
|
|
||
|
// calibration value cache. Values are set externally in bmp280.c
|
||
|
|
||
|
uint16_t dig_T1;
|
||
|
int16_t dig_T2;
|
||
|
int16_t dig_T3;
|
||
|
|
||
|
uint16_t dig_P1;
|
||
|
int16_t dig_P2;
|
||
|
int16_t dig_P3;
|
||
|
int16_t dig_P4;
|
||
|
int16_t dig_P5;
|
||
|
int16_t dig_P6;
|
||
|
int16_t dig_P7;
|
||
|
int16_t dig_P8;
|
||
|
int16_t dig_P9;
|
||
|
|
||
|
|
||
|
typedef int32_t BMP280_S32_t;
|
||
|
typedef uint32_t BMP280_U32_t;
|
||
|
typedef int64_t BMP280_S64_t;
|
||
|
|
||
|
|
||
|
// Returns temperature in DegC, resolution is 0.01 DegC. Output value of “5123” equals 51.23 DegC.
|
||
|
// t_fine carries fine temperature as global value
|
||
|
BMP280_S32_t t_fine;
|
||
|
|
||
|
static BMP280_S32_t bmp280_compensate_T_int32(BMP280_S32_t adc_T)
|
||
|
{
|
||
|
BMP280_S32_t var1, var2, T;
|
||
|
var1 = ((((adc_T>>3) - ((BMP280_S32_t)dig_T1<<1))) * ((BMP280_S32_t)dig_T2)) >> 11;
|
||
|
var2 = (((((adc_T>>4) - ((BMP280_S32_t)dig_T1)) * ((adc_T>>4) - ((BMP280_S32_t)dig_T1))) >> 12) * ((BMP280_S32_t)dig_T3)) >> 14;
|
||
|
t_fine = var1 + var2;
|
||
|
T = (t_fine * 5 + 128) >> 8;
|
||
|
return T;
|
||
|
}
|
||
|
|
||
|
// Returns pressure in Pa as unsigned 32 bit integer in Q24.8 format (24 integer bits and 8 fractional bits).
|
||
|
// Output value of “24674867” represents 24674867/256 = 96386.2 Pa = 963.862 hPa
|
||
|
static BMP280_U32_t bmp280_compensate_P_int64(BMP280_S32_t adc_P)
|
||
|
{
|
||
|
BMP280_S64_t var1, var2, p;
|
||
|
var1 = ((BMP280_S64_t)t_fine) - 128000;
|
||
|
var2 = var1 * var1 * (BMP280_S64_t)dig_P6;
|
||
|
var2 = var2 + ((var1*(BMP280_S64_t)dig_P5)<<17);
|
||
|
var2 = var2 + (((BMP280_S64_t)dig_P4)<<35);
|
||
|
var1 = ((var1 * var1 * (BMP280_S64_t)dig_P3)>>8) + ((var1 * (BMP280_S64_t)dig_P2)<<12);
|
||
|
var1 = (((((BMP280_S64_t)1)<<47)+var1))*((BMP280_S64_t)dig_P1)>>33;
|
||
|
if (var1 == 0) {
|
||
|
return 0; // avoid exception caused by division by zero
|
||
|
}
|
||
|
p = 1048576-adc_P;
|
||
|
p = (((p<<31)-var2)*3125)/var1;
|
||
|
var1 = (((BMP280_S64_t)dig_P9) * (p>>13) * (p>>13)) >> 25;
|
||
|
var2 = (((BMP280_S64_t)dig_P8) * p) >> 19;
|
||
|
p = ((p + var1 + var2) >> 8) + (((BMP280_S64_t)dig_P7)<<4);
|
||
|
return (BMP280_U32_t)p;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
fxp_t bmp280_comp_temperature(int32_t adc)
|
||
|
{
|
||
|
int32_t compensated = bmp280_compensate_T_int32(adc);
|
||
|
|
||
|
return ((fxp_t)compensated << POINTPOS) / 100L;
|
||
|
}
|
||
|
|
||
|
fxp_t bmp280_comp_pressure(int32_t adc)
|
||
|
{
|
||
|
uint32_t compensated = bmp280_compensate_P_int64(adc);
|
||
|
|
||
|
return (fxp_t)(((uint64_t)compensated << (POINTPOS - 8L)) / 100);
|
||
|
}
|