mirror of
https://github.com/eclipse/upm.git
synced 2025-07-27 06:01:16 +03:00
bmp280, bme280: Initial implementation
This library adds support for both the BMP280 and BME280 sesnors from Bosch. The BME is virtually identical to the BMP280 aside from some slight register changes and adding support for a humidity sensor. The BMP280 is an absolute barometric pressure sensor especially designed for mobile applications. The sensor module is housed in an extremely compact 8-pin metal-lid LGA package with a footprint of only 2.0 × 2.5 mm2 and 0.95 mm package height. Its small dimensions and its low power consumption of 2.7 μA @1Hz allow the implementation in battery driven devices such as mobile phones, GPS modules or watches. The BME280 is as combined digital humidity, pressure and temperature sensor based on proven sensing principles. The sensor module is housed in an extremely compact metal-lid LGA package with a footprint of only 2.5 × 2.5 mm2 with a height of 0.93 mm. Its small dimensions and its low power consumption allow the implementation in battery driven devices such as handsets, GPS modules or watches. The BME280 is register and performance compatible to the Bosch Sensortec BMP280 digital pressure sensor These drivers support both I2C and SPI operation. When using SPI on an Edison with the arduino breakout board, you must specify a CS of -1 to the constructor, and connect the chip's CS pin to arduino pin 10. Signed-off-by: Jon Trulson <jtrulson@ics.com> Signed-off-by: Noel Eck <noel.eck@intel.com>
This commit is contained in:
576
src/bmp280/bmp280.cxx
Normal file
576
src/bmp280/bmp280.cxx
Normal file
@ -0,0 +1,576 @@
|
||||
/*
|
||||
* Author: Jon Trulson <jtrulson@ics.com>
|
||||
* Copyright (c) 2016 Intel Corporation.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bmp280.hpp"
|
||||
|
||||
using namespace upm;
|
||||
using namespace std;
|
||||
|
||||
// Uncomment the following to use test data as specified in the
|
||||
// datasheet, section 3.12. This really only tests the compensation
|
||||
// algorithm.
|
||||
|
||||
// #define BMP280_USE_TEST_DATA
|
||||
|
||||
// conversion from fahrenheit to celcius and back
|
||||
|
||||
static float f2c(float f)
|
||||
{
|
||||
return ((f - 32.0) / (9.0 / 5.0));
|
||||
}
|
||||
|
||||
static float c2f(float c)
|
||||
{
|
||||
return (c * (9.0 / 5.0) + 32.0);
|
||||
}
|
||||
|
||||
BMP280::BMP280(int bus, int addr, int cs, uint8_t theChipID) :
|
||||
m_i2c(0), m_spi(0), m_gpioCS(0)
|
||||
{
|
||||
|
||||
m_addr = addr;
|
||||
|
||||
m_temperature = 0;
|
||||
m_pressure = 0;
|
||||
m_isSPI = false;
|
||||
|
||||
clearData();
|
||||
|
||||
if (addr < 0)
|
||||
m_isSPI = true;
|
||||
|
||||
mraa::Result rv;
|
||||
|
||||
if (m_isSPI)
|
||||
{
|
||||
m_spi = new mraa::Spi(bus);
|
||||
|
||||
// Only create cs context if we are actually using a valid pin.
|
||||
// A hardware controlled pin should specify cs as -1.
|
||||
if (cs >= 0)
|
||||
{
|
||||
m_gpioCS = new mraa::Gpio(cs);
|
||||
m_gpioCS->dir(mraa::DIR_OUT);
|
||||
}
|
||||
|
||||
m_spi->mode(mraa::SPI_MODE0);
|
||||
m_spi->frequency(5000000);
|
||||
|
||||
// toggle it on/off so chip switches into SPI mode. For a hw CS
|
||||
// pin, the first SPI transaction should accomplish this.
|
||||
csOn();
|
||||
usleep(10000);
|
||||
csOff();
|
||||
}
|
||||
else
|
||||
{
|
||||
// I2C
|
||||
m_i2c = new mraa::I2c(bus);
|
||||
|
||||
if ((rv = m_i2c->address(m_addr)) != mraa::SUCCESS)
|
||||
{
|
||||
throw std::runtime_error(string(__FUNCTION__) +
|
||||
": I2c.address() failed");
|
||||
}
|
||||
}
|
||||
|
||||
// check the chip id
|
||||
|
||||
uint8_t chipID = readReg(REG_CHIPID);
|
||||
if (chipID != theChipID)
|
||||
{
|
||||
throw std::runtime_error(string(__FUNCTION__)
|
||||
+ ": invalid chip ID. Expected "
|
||||
+ std::to_string(int(theChipID))
|
||||
+ ", got "
|
||||
+ std::to_string(int(chipID)));
|
||||
}
|
||||
|
||||
// set sleep mode for now
|
||||
setMeasureMode(MODE_SLEEP);
|
||||
|
||||
// read calibration data
|
||||
readCalibrationData();
|
||||
|
||||
// set the default mode to the highest resolution mode
|
||||
setUsageMode(USAGE_MODE_INDOOR_NAV);
|
||||
}
|
||||
|
||||
BMP280::~BMP280()
|
||||
{
|
||||
if (m_i2c)
|
||||
delete m_i2c;
|
||||
|
||||
if (m_spi)
|
||||
delete m_spi;
|
||||
|
||||
if (m_gpioCS)
|
||||
delete m_gpioCS;
|
||||
}
|
||||
|
||||
void BMP280::update()
|
||||
{
|
||||
int32_t temp = 0;
|
||||
int32_t pres = 0;
|
||||
|
||||
const int dataLen = 6;
|
||||
uint8_t data[dataLen];
|
||||
memset(data, 0, dataLen);
|
||||
|
||||
// If we are using a forced mode, then we need to manually trigger
|
||||
// the measurement, and wait for it to complete.
|
||||
|
||||
if (m_mode == MODE_FORCED)
|
||||
{
|
||||
// bmp280 measure mode will return to sleep after completion...
|
||||
setMeasureMode(MODE_FORCED);
|
||||
|
||||
uint8_t stat;
|
||||
do
|
||||
{
|
||||
usleep(10000); // 10ms
|
||||
stat = readReg(REG_STATUS);
|
||||
} while (stat & STATUS_MEASURING);
|
||||
}
|
||||
|
||||
int rv;
|
||||
if ((rv = readRegs(REG_PRESSURE_MSB, data, dataLen)) != dataLen)
|
||||
{
|
||||
throw std::runtime_error(std::string(__FUNCTION__)
|
||||
+ ": readRegs() failed, returned "
|
||||
+ std::to_string(rv));
|
||||
}
|
||||
|
||||
// 20 bits unsigned stored in a 32bit signed quanty
|
||||
|
||||
#if defined(BMP280_USE_TEST_DATA)
|
||||
// taken from datasheet, section 3.12
|
||||
temp = 519888;
|
||||
pres = 415148;
|
||||
#else
|
||||
temp = ( (data[5] >> 4) | (data[4] << 4) | (data[3] << 12) );
|
||||
pres = ( (data[2] >> 4) | (data[1] << 4) | (data[0] << 12) );
|
||||
#endif
|
||||
|
||||
m_temperature = float(bmp280_compensate_T_int32(temp));
|
||||
m_temperature /= 100.0;
|
||||
|
||||
m_pressure = float(bmp280_compensate_P_int64(pres));
|
||||
m_pressure /= 256.0;
|
||||
}
|
||||
|
||||
float BMP280::getAltitude(float sealLevelhPA)
|
||||
{
|
||||
// adapted from the NOAA pdf: pressureAltitude.pdf
|
||||
return 44307.69 * (1.0 - pow((m_pressure/100.0) / sealLevelhPA, 0.190284));
|
||||
}
|
||||
|
||||
uint8_t BMP280::readReg(uint8_t reg)
|
||||
{
|
||||
if (m_isSPI)
|
||||
{
|
||||
reg |= 0x80; // needed for read
|
||||
uint8_t pkt[2] = {reg, 0};
|
||||
|
||||
csOn();
|
||||
if (m_spi->transfer(pkt, pkt, 2))
|
||||
{
|
||||
csOff();
|
||||
throw std::runtime_error(string(__FUNCTION__)
|
||||
+ ": Spi.transfer() failed");
|
||||
}
|
||||
csOff();
|
||||
|
||||
#if 0
|
||||
cerr << "readReg: " << std::hex << "p0: " << (int)pkt[0] << " p1: "
|
||||
<< (int)pkt[1] << endl;
|
||||
#endif // 0
|
||||
|
||||
return pkt[1];
|
||||
}
|
||||
else
|
||||
return m_i2c->readReg(reg);
|
||||
}
|
||||
|
||||
int BMP280::readRegs(uint8_t reg, uint8_t *buffer, int len)
|
||||
{
|
||||
if (m_isSPI)
|
||||
{
|
||||
reg |= 0x80; // needed for read
|
||||
|
||||
uint8_t sbuf[len + 1];
|
||||
memset((char *)sbuf, 0, len + 1);
|
||||
sbuf[0] = reg;
|
||||
|
||||
// We need to do it this way for edison - ie: use a single
|
||||
// transfer rather than breaking it up into two like we used to.
|
||||
// This means a buffer copy is now required, but that's the way
|
||||
// it goes.
|
||||
|
||||
csOn();
|
||||
if (m_spi->transfer(sbuf, sbuf, len + 1))
|
||||
{
|
||||
csOff();
|
||||
throw std::runtime_error(string(__FUNCTION__)
|
||||
+ ": Spi.transfer(buf) failed");
|
||||
}
|
||||
csOff();
|
||||
|
||||
// now copy it into user buffer
|
||||
for (int i=0; i<len; i++)
|
||||
buffer[i] = sbuf[i + 1];
|
||||
|
||||
// so... did this work on edison????
|
||||
|
||||
#if 0
|
||||
cerr << "readRegs(): " << std::hex;
|
||||
for (int i=0; i<len; i++)
|
||||
cerr << (int)buffer[i] << " ";
|
||||
cerr << endl;
|
||||
#endif // 0
|
||||
|
||||
return len;
|
||||
}
|
||||
else
|
||||
return m_i2c->readBytesReg(reg, buffer, len);
|
||||
}
|
||||
|
||||
void BMP280::writeReg(uint8_t reg, uint8_t val)
|
||||
{
|
||||
if (m_isSPI)
|
||||
{
|
||||
reg &= 0x7f; // mask off 0x80 for writing
|
||||
uint8_t pkt[2] = {reg, val};
|
||||
|
||||
csOn();
|
||||
if (m_spi->transfer(pkt, NULL, 2))
|
||||
{
|
||||
csOff();
|
||||
throw std::runtime_error(string(__FUNCTION__)
|
||||
+ ": Spi.transfer() failed");
|
||||
}
|
||||
csOff();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
mraa::Result rv;
|
||||
if ((rv = m_i2c->writeReg(reg, val)) != mraa::SUCCESS)
|
||||
{
|
||||
throw std::runtime_error(std::string(__FUNCTION__)
|
||||
+ ": I2c.writeReg() failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BMP280::clearData()
|
||||
{
|
||||
m_t_fine = 0;
|
||||
|
||||
m_dig_T1 = 0;
|
||||
m_dig_T2 = 0;
|
||||
m_dig_T3 = 0;
|
||||
|
||||
m_dig_P1 = 0;
|
||||
m_dig_P2 = 0;
|
||||
m_dig_P3 = 0;
|
||||
m_dig_P4 = 0;
|
||||
m_dig_P5 = 0;
|
||||
m_dig_P6 = 0;
|
||||
m_dig_P7 = 0;
|
||||
m_dig_P8 = 0;
|
||||
m_dig_P9 = 0;
|
||||
}
|
||||
|
||||
uint8_t BMP280::getChipID()
|
||||
{
|
||||
|
||||
return readReg(REG_CHIPID);
|
||||
}
|
||||
|
||||
void BMP280::reset()
|
||||
{
|
||||
writeReg(REG_RESET, BMP280_RESET_BYTE);
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
|
||||
void BMP280::readCalibrationData()
|
||||
{
|
||||
#if defined(BMP280_USE_TEST_DATA)
|
||||
cerr << "WARNING: Test data is being used" << endl;
|
||||
// This data is taken from the datasheet, section 3.12
|
||||
m_dig_T1 = 27504;
|
||||
m_dig_T2 = 26435;
|
||||
m_dig_T3 = -1000;
|
||||
|
||||
m_dig_P1 = 36477;
|
||||
m_dig_P2 = -10685;
|
||||
m_dig_P3 = 3024;
|
||||
m_dig_P4 = 2855;
|
||||
m_dig_P5 = 140;
|
||||
m_dig_P6 = -7;
|
||||
m_dig_P7 = 15500;
|
||||
m_dig_P8 = -14600;
|
||||
m_dig_P9 = 6000;
|
||||
|
||||
#else
|
||||
|
||||
uint8_t calibData[CALIBRATION_BYTES];
|
||||
readRegs(REG_CALIB00, calibData, CALIBRATION_BYTES);
|
||||
|
||||
m_dig_T1 = uint16_t((calibData[1] << 8) | calibData[0]);
|
||||
m_dig_T2 = int16_t((calibData[3] << 8) | calibData[2]);
|
||||
m_dig_T3 = int16_t((calibData[5] << 8) | calibData[4]);
|
||||
|
||||
# if 0
|
||||
cerr << std::dec << "T1: " << (int)m_dig_T1
|
||||
<< " T2: " << (int)m_dig_T2
|
||||
<< " T3: " << (int)m_dig_T3
|
||||
<< endl;
|
||||
# endif // 0
|
||||
|
||||
m_dig_P1 = uint16_t((calibData[7] << 8) | calibData[6]);
|
||||
m_dig_P2 = int16_t((calibData[9] << 8) | calibData[8]);
|
||||
m_dig_P3 = int16_t((calibData[11] << 8) | calibData[10]);
|
||||
m_dig_P4 = int16_t((calibData[13] << 8) | calibData[12]);
|
||||
m_dig_P5 = int16_t((calibData[15] << 8) | calibData[14]);
|
||||
m_dig_P6 = int16_t((calibData[17] << 8) | calibData[16]);
|
||||
m_dig_P7 = int16_t((calibData[19] << 8) | calibData[18]);
|
||||
m_dig_P8 = int16_t((calibData[21] << 8) | calibData[20]);
|
||||
m_dig_P9 = int16_t((calibData[23] << 8) | calibData[22]);
|
||||
|
||||
# if 0
|
||||
cerr << std::dec << "P1: " << (int)m_dig_P1
|
||||
<< " P2: " << (int)m_dig_P2
|
||||
<< " P3: " << (int)m_dig_P3
|
||||
<< " P4: " << (int)m_dig_P4
|
||||
<< " P5: " << (int)m_dig_P5
|
||||
<< endl;
|
||||
cerr << std::dec << "P6: " << (int)m_dig_P6
|
||||
<< " P7: " << (int)m_dig_P7
|
||||
<< " P8: " << (int)m_dig_P8
|
||||
<< " P9: " << (int)m_dig_P9
|
||||
<< endl;
|
||||
# endif // 0
|
||||
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
float BMP280::getTemperature(bool fahrenheit)
|
||||
{
|
||||
if (fahrenheit)
|
||||
return c2f(m_temperature);
|
||||
else
|
||||
return m_temperature;
|
||||
}
|
||||
|
||||
float BMP280::getPressure()
|
||||
{
|
||||
return m_pressure;
|
||||
}
|
||||
|
||||
void BMP280::setFilter(FILTER_T filter)
|
||||
{
|
||||
uint8_t reg = readReg(REG_CONFIG);
|
||||
|
||||
reg &= ~(_CONFIG_FILTER_MASK << _CONFIG_FILTER_SHIFT);
|
||||
reg |= (filter << _CONFIG_FILTER_SHIFT);
|
||||
|
||||
writeReg(REG_CONFIG, reg);
|
||||
}
|
||||
|
||||
void BMP280::setTimerStandby(T_SB_T tsb)
|
||||
{
|
||||
uint8_t reg = readReg(REG_CONFIG);
|
||||
|
||||
reg &= ~(_CONFIG_T_SB_MASK << _CONFIG_T_SB_SHIFT);
|
||||
reg |= (tsb << _CONFIG_T_SB_SHIFT);
|
||||
|
||||
writeReg(REG_CONFIG, reg);
|
||||
}
|
||||
|
||||
void BMP280::setMeasureMode(MODES_T mode)
|
||||
{
|
||||
uint8_t reg = readReg(REG_CTRL_MEAS);
|
||||
|
||||
reg &= ~(_CTRL_MEAS_MODE_MASK << _CTRL_MEAS_MODE_SHIFT);
|
||||
reg |= (mode << _CTRL_MEAS_MODE_SHIFT);
|
||||
|
||||
writeReg(REG_CTRL_MEAS, reg);
|
||||
m_mode = mode;
|
||||
}
|
||||
|
||||
void BMP280::setOversampleRatePressure(OSRS_P_T rate)
|
||||
{
|
||||
uint8_t reg = readReg(REG_CTRL_MEAS);
|
||||
|
||||
reg &= ~(_CTRL_MEAS_OSRS_P_MASK << _CTRL_MEAS_OSRS_P_SHIFT);
|
||||
reg |= (rate << _CTRL_MEAS_OSRS_P_SHIFT);
|
||||
|
||||
writeReg(REG_CTRL_MEAS, reg);
|
||||
}
|
||||
|
||||
void BMP280::setOversampleRateTemperature(OSRS_T_T rate)
|
||||
{
|
||||
uint8_t reg = readReg(REG_CTRL_MEAS);
|
||||
|
||||
reg &= ~(_CTRL_MEAS_OSRS_T_MASK << _CTRL_MEAS_OSRS_T_SHIFT);
|
||||
reg |= (rate << _CTRL_MEAS_OSRS_T_SHIFT);
|
||||
|
||||
writeReg(REG_CTRL_MEAS, reg);
|
||||
}
|
||||
|
||||
uint8_t BMP280::getStatus()
|
||||
{
|
||||
return readReg(REG_STATUS);
|
||||
}
|
||||
|
||||
void BMP280::setUsageMode(USAGE_MODE_T mode)
|
||||
{
|
||||
// set up the regs for the given usage mode. These settings come
|
||||
// from the recomendations in the BMP280 datasheet, section 3.4
|
||||
// Filter Selection.
|
||||
|
||||
m_temperature = 0;
|
||||
m_pressure = 0;
|
||||
|
||||
// set sleep mode first
|
||||
setMeasureMode(MODE_SLEEP);
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case USAGE_MODE_HANDHELD_LOW_POWER:
|
||||
setOversampleRatePressure(OSRS_P_OVERSAMPLING_16);
|
||||
setOversampleRateTemperature(OSRS_T_OVERSAMPLING_2);
|
||||
setFilter(FILTER_4);
|
||||
setMeasureMode(MODE_NORMAL);
|
||||
|
||||
break;
|
||||
|
||||
case USAGE_MODE_HANDHELD_DYNAMIC:
|
||||
setOversampleRatePressure(OSRS_P_OVERSAMPLING_4);
|
||||
setOversampleRateTemperature(OSRS_T_OVERSAMPLING_1);
|
||||
setFilter(FILTER_16);
|
||||
setMeasureMode(MODE_NORMAL);
|
||||
|
||||
break;
|
||||
|
||||
case USAGE_MODE_WEATHER_MONITOR:
|
||||
setOversampleRatePressure(OSRS_P_OVERSAMPLING_1);
|
||||
setOversampleRateTemperature(OSRS_T_OVERSAMPLING_1);
|
||||
setFilter(FILTER_OFF);
|
||||
setMeasureMode(MODE_FORCED);
|
||||
|
||||
break;
|
||||
|
||||
case USAGE_MODE_FLOOR_CHG_DETECT:
|
||||
setOversampleRatePressure(OSRS_P_OVERSAMPLING_4);
|
||||
setOversampleRateTemperature(OSRS_T_OVERSAMPLING_1);
|
||||
setFilter(FILTER_4);
|
||||
setMeasureMode(MODE_NORMAL);
|
||||
|
||||
break;
|
||||
|
||||
case USAGE_MODE_DROP_DETECT:
|
||||
setOversampleRatePressure(OSRS_P_OVERSAMPLING_2);
|
||||
setOversampleRateTemperature(OSRS_T_OVERSAMPLING_1);
|
||||
setFilter(FILTER_OFF);
|
||||
setMeasureMode(MODE_NORMAL);
|
||||
|
||||
break;
|
||||
|
||||
case USAGE_MODE_INDOOR_NAV:
|
||||
setOversampleRatePressure(OSRS_P_OVERSAMPLING_16);
|
||||
setOversampleRateTemperature(OSRS_T_OVERSAMPLING_2);
|
||||
setFilter(FILTER_16);
|
||||
setMeasureMode(MODE_NORMAL);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
throw std::logic_error(string(__FUNCTION__)
|
||||
+ ": invalid mode specified");
|
||||
}
|
||||
}
|
||||
|
||||
void BMP280::csOn()
|
||||
{
|
||||
if (m_gpioCS)
|
||||
m_gpioCS->write(0);
|
||||
}
|
||||
|
||||
void BMP280::csOff()
|
||||
{
|
||||
if (m_gpioCS)
|
||||
m_gpioCS->write(1);
|
||||
}
|
||||
|
||||
// These functions come from the BMP280 datasheet, section 3.11.3
|
||||
|
||||
// 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
|
||||
int32_t BMP280::bmp280_compensate_T_int32(int32_t adc_T)
|
||||
{
|
||||
int32_t var1, var2, T;
|
||||
var1 = ((((adc_T>>3) - ((int32_t)m_dig_T1<<1))) * ((int32_t)m_dig_T2)) >> 11;
|
||||
var2 = (((((adc_T>>4) - ((int32_t)m_dig_T1)) * ((adc_T>>4) - ((int32_t)m_dig_T1))) >> 12) *
|
||||
((int32_t)m_dig_T3)) >> 14;
|
||||
m_t_fine = var1 + var2;
|
||||
T = (m_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
|
||||
uint32_t BMP280::bmp280_compensate_P_int64(int32_t adc_P)
|
||||
{
|
||||
int64_t var1, var2, p;
|
||||
var1 = ((int64_t)m_t_fine) - 128000;
|
||||
var2 = var1 * var1 * (int64_t)m_dig_P6;
|
||||
var2 = var2 + ((var1*(int64_t)m_dig_P5)<<17);
|
||||
var2 = var2 + (((int64_t)m_dig_P4)<<35);
|
||||
var1 = ((var1 * var1 * (int64_t)m_dig_P3)>>8) + ((var1 * (int64_t)m_dig_P2)<<12);
|
||||
var1 = (((((int64_t)1)<<47)+var1))*((int64_t)m_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 = (((int64_t)m_dig_P9) * (p>>13) * (p>>13)) >> 25;
|
||||
var2 = (((int64_t)m_dig_P8) * p) >> 19;
|
||||
p = ((p + var1 + var2) >> 8) + (((int64_t)m_dig_P7)<<4);
|
||||
return (uint32_t)p;
|
||||
}
|
Reference in New Issue
Block a user