LCOV - code coverage report
Current view: top level - AP_Baro - AP_Baro_MS5611.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 100 243 41.2 %
Date: 2026-09-09 11:02:08 Functions: 11 22 50.0 %

          Line data    Source code
       1             : /*
       2             :    This program is free software: you can redistribute it and/or modify
       3             :    it under the terms of the GNU General Public License as published by
       4             :    the Free Software Foundation, either version 3 of the License, or
       5             :    (at your option) any later version.
       6             : 
       7             :    This program is distributed in the hope that it will be useful,
       8             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
       9             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      10             :    GNU General Public License for more details.
      11             : 
      12             :    You should have received a copy of the GNU General Public License
      13             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      14             :  */
      15             : #include "AP_Baro_MS5611.h"
      16             : 
      17             : #if AP_BARO_MS56XX_ENABLED
      18             : 
      19             : #include <stdio.h>
      20             : 
      21             : #include <AP_Math/AP_Math.h>
      22             : #include <AP_Math/crc.h>
      23             : #include <AP_BoardConfig/AP_BoardConfig.h>
      24             : 
      25             : extern const AP_HAL::HAL &hal;
      26             : 
      27             : static const uint8_t CMD_MS56XX_RESET = 0x1E;
      28             : static const uint8_t CMD_MS56XX_READ_ADC = 0x00;
      29             : 
      30             : /* PROM start address */
      31             : static const uint8_t CMD_MS56XX_PROM = 0xA0;
      32             : 
      33             : /* write to one of these addresses to start pressure conversion */
      34             : #define ADDR_CMD_CONVERT_D1_OSR256  0x40
      35             : #define ADDR_CMD_CONVERT_D1_OSR512  0x42
      36             : #define ADDR_CMD_CONVERT_D1_OSR1024 0x44
      37             : #define ADDR_CMD_CONVERT_D1_OSR2048 0x46
      38             : #define ADDR_CMD_CONVERT_D1_OSR4096 0x48
      39             : 
      40             : /* write to one of these addresses to start temperature conversion */
      41             : #define ADDR_CMD_CONVERT_D2_OSR256  0x50
      42             : #define ADDR_CMD_CONVERT_D2_OSR512  0x52
      43             : #define ADDR_CMD_CONVERT_D2_OSR1024 0x54
      44             : #define ADDR_CMD_CONVERT_D2_OSR2048 0x56
      45             : #define ADDR_CMD_CONVERT_D2_OSR4096 0x58
      46             : 
      47             : /*
      48             :   use an OSR of 1024 to reduce the self-heating effect of the
      49             :   sensor. Information from MS tells us that some individual sensors
      50             :   are quite sensitive to this effect and that reducing the OSR can
      51             :   make a big difference
      52             :  */
      53             : static const uint8_t ADDR_CMD_CONVERT_PRESSURE = ADDR_CMD_CONVERT_D1_OSR1024;
      54             : static const uint8_t ADDR_CMD_CONVERT_TEMPERATURE = ADDR_CMD_CONVERT_D2_OSR1024;
      55             : 
      56             : /*
      57             :   constructor
      58             :  */
      59          83 : AP_Baro_MS56XX::AP_Baro_MS56XX(AP_Baro &baro, AP_HAL::Device &dev)
      60             :     : AP_Baro_Backend(baro)
      61          83 :     , _dev(&dev)
      62             : {
      63          83 : }
      64             : 
      65             : // convenience methods for derivative classes to call.  Will free
      66             : // sensor if it can't init it.
      67          83 : AP_Baro_Backend *AP_Baro_MS56XX::_probe(AP_Baro &baro, AP_Baro_MS56XX *sensor)
      68             : {
      69          83 :     if (!sensor || !sensor->_init()) {
      70          82 :         delete sensor;
      71          82 :         return nullptr;
      72             :     }
      73           1 :     return sensor;
      74             : }
      75             : 
      76             : #if AP_BARO_MS5611_ENABLED
      77          83 : AP_Baro_Backend *AP_Baro_MS5611::probe(AP_Baro &baro, AP_HAL::Device &dev)
      78             : {
      79             : #if AP_BARO_MS5607_ENABLED
      80             :     /*
      81             :       cope with vendors substituting a MS5607 for a MS5611 on Pixhawk1 'clone' boards
      82             :      */
      83          83 :     if (AP::baro().option_enabled(AP_Baro::Options::TreatMS5611AsMS5607)) {
      84           0 :         return _probe(baro, NEW_NOTHROW AP_Baro_MS5607(baro, dev));
      85             :     }
      86             : #endif  // AP_BARO_MS5607_ENABLED
      87             : 
      88          83 :     return _probe(baro, NEW_NOTHROW AP_Baro_MS5611(baro, dev));
      89             : }
      90             : #endif  // AP_BARO_MS5611_ENABLED
      91             : 
      92             : #if AP_BARO_MS5607_ENABLED
      93           0 : AP_Baro_Backend *AP_Baro_MS5607::probe(AP_Baro &baro, AP_HAL::Device &dev)
      94             : {
      95           0 :     return _probe(baro, NEW_NOTHROW AP_Baro_MS5607(baro, dev));
      96             : }
      97             : #endif  // AP_BARO_MS5607_ENABLED
      98             : 
      99             : #if AP_BARO_MS5637_ENABLED
     100           0 : AP_Baro_Backend *AP_Baro_MS5637::probe(AP_Baro &baro, AP_HAL::Device &dev)
     101             : {
     102           0 :     return _probe(baro, NEW_NOTHROW AP_Baro_MS5637(baro, dev));
     103             : }
     104             : #endif  // AP_BARO_MS5637_ENABLED
     105             : 
     106             : #if AP_BARO_MS5837_ENABLED
     107           0 : AP_Baro_Backend *AP_Baro_MS5837::probe(AP_Baro &baro, AP_HAL::Device &dev)
     108             : {
     109           0 :     return _probe(baro, NEW_NOTHROW AP_Baro_MS5837(baro, dev));
     110             : }
     111             : 
     112           0 : bool AP_Baro_MS5837::_init()
     113             : {
     114           0 :     if (!AP_Baro_MS56XX::_init()) {
     115           0 :         return false;
     116             :     }
     117           0 :     _frontend.set_type(_instance, AP_Baro::BARO_TYPE_WATER);
     118             :     // Use pressure sensitivity as a proxy for range determination
     119             :     // High sensitivity for the same number size implies the lower-range sensor variant
     120             :     // Threshold determined from datasheet example values and some sample sensors
     121           0 :     uint16_t pressure_sensitivity = _cal_reg.c1;
     122           0 :     if (pressure_sensitivity > MS5837_30BA_02BA_SELECTION_THRESHOLD) {
     123           0 :         _subtype = DEVTYPE_BARO_MS5837_02BA;
     124             :     } else {
     125           0 :         _subtype = DEVTYPE_BARO_MS5837_30BA;
     126             :     }
     127           0 :     return true;
     128             : }
     129             : #endif // AP_BARO_MS5837_ENABLED
     130             : 
     131          83 : bool AP_Baro_MS56XX::_init()
     132             : {
     133          83 :     if (!_dev) {
     134           0 :         return false;
     135             :     }
     136             : 
     137          83 :     _dev->get_semaphore()->take_blocking();
     138             : 
     139             :     // high retries for init
     140          83 :     _dev->set_retries(10);
     141             :     
     142             :     uint16_t prom[8];
     143             : 
     144          83 :     _dev->transfer(&CMD_MS56XX_RESET, 1, nullptr, 0);
     145          83 :     hal.scheduler->delay(4);
     146             : 
     147          83 :     if (!_read_prom(prom)) {
     148          82 :         _dev->get_semaphore()->give();
     149          82 :         return false;
     150             :     }
     151             : 
     152           1 :     printf("%s found on bus %u address 0x%02x\n", name(), _dev->bus_num(), _dev->get_bus_address());
     153             : 
     154             :     // Save factory calibration coefficients
     155           1 :     _cal_reg.c1 = prom[1];
     156           1 :     _cal_reg.c2 = prom[2];
     157           1 :     _cal_reg.c3 = prom[3];
     158           1 :     _cal_reg.c4 = prom[4];
     159           1 :     _cal_reg.c5 = prom[5];
     160           1 :     _cal_reg.c6 = prom[6];
     161             : 
     162             :     // Send a command to read temperature first
     163           1 :     _dev->transfer(&ADDR_CMD_CONVERT_TEMPERATURE, 1, nullptr, 0);
     164           1 :     _state = 0;
     165             : 
     166           1 :     memset(&_accum, 0, sizeof(_accum));
     167             : 
     168           1 :     _instance = _frontend.register_sensor();
     169             : 
     170           1 :     _dev->set_device_type(devtype());
     171           1 :     set_bus_id(_instance, _dev->get_bus_id());
     172             : 
     173             :     // lower retries for run
     174           1 :     _dev->set_retries(3);
     175             :     
     176           1 :     _dev->get_semaphore()->give();
     177             : 
     178             :     /* Request 100Hz update */
     179           1 :     _dev->register_periodic_callback(10 * AP_USEC_PER_MSEC,
     180             :                                      FUNCTOR_BIND_MEMBER(&AP_Baro_MS56XX::_timer, void));
     181           1 :     return true;
     182             : }
     183             : 
     184         664 : uint16_t AP_Baro_MS56XX::_read_prom_word(uint8_t word)
     185             : {
     186         664 :     const uint8_t reg = CMD_MS56XX_PROM + (word << 1);
     187             :     uint8_t val[2];
     188         664 :     if (!_dev->transfer(&reg, 1, val, sizeof(val))) {
     189         164 :         return 0;
     190             :     }
     191         500 :     return (val[0] << 8) | val[1];
     192             : }
     193             : 
     194       24152 : uint32_t AP_Baro_MS56XX::_read_adc()
     195             : {
     196             :     uint8_t val[3];
     197       24152 :     if (!_dev->transfer(&CMD_MS56XX_READ_ADC, 1, val, sizeof(val))) {
     198           0 :         return 0;
     199             :     }
     200       24152 :     return (val[0] << 16) | (val[1] << 8) | val[2];
     201             : }
     202             : 
     203          83 : bool AP_Baro_MS56XX::_read_prom_5611(uint16_t prom[8])
     204             : {
     205             :     /*
     206             :      * MS5611-01BA datasheet, CYCLIC REDUNDANCY CHECK (CRC): "MS5611-01BA
     207             :      * contains a PROM memory with 128-Bit. A 4-bit CRC has been implemented
     208             :      * to check the data validity in memory."
     209             :      *
     210             :      * CRC field must me removed for CRC-4 calculation.
     211             :      */
     212          83 :     bool all_zero = true;
     213         747 :     for (uint8_t i = 0; i < 8; i++) {
     214         664 :         prom[i] = _read_prom_word(i);
     215         664 :         if (prom[i] != 0) {
     216         418 :             all_zero = false;
     217             :         }
     218             :     }
     219             : 
     220          83 :     if (all_zero) {
     221           0 :         return false;
     222             :     }
     223             : 
     224             :     /* save the read crc */
     225          83 :     const uint16_t crc_read = prom[7] & 0xf;
     226             : 
     227             :     /* remove CRC byte */
     228          83 :     prom[7] &= 0xff00;
     229             : 
     230          83 :     return crc_read == crc_crc4(prom);
     231             : }
     232             : 
     233           0 : bool AP_Baro_MS56XX::_read_prom_5637(uint16_t prom[8])
     234             : {
     235             :     /*
     236             :      * MS5637-02BA03 datasheet, CYCLIC REDUNDANCY CHECK (CRC): "MS5637
     237             :      * contains a PROM memory with 112-Bit. A 4-bit CRC has been implemented
     238             :      * to check the data validity in memory."
     239             :      *
     240             :      * 8th PROM word must be zeroed and CRC field removed for CRC-4
     241             :      * calculation.
     242             :      */
     243           0 :     bool all_zero = true;
     244           0 :     for (uint8_t i = 0; i < 7; i++) {
     245           0 :         prom[i] = _read_prom_word(i);
     246           0 :         if (prom[i] != 0) {
     247           0 :             all_zero = false;
     248             :         }
     249             :     }
     250             : 
     251           0 :     if (all_zero) {
     252           0 :         return false;
     253             :     }
     254             : 
     255           0 :     prom[7] = 0;
     256             : 
     257             :     /* save the read crc */
     258           0 :     const uint16_t crc_read = (prom[0] & 0xf000) >> 12;
     259             : 
     260             :     /* remove CRC byte */
     261           0 :     prom[0] &= ~0xf000;
     262             : 
     263           0 :     return crc_read == crc_crc4(prom);
     264             : }
     265             : 
     266             : /*
     267             :  * Read the sensor with a state machine
     268             :  * We read one time temperature (state=0) and then 4 times pressure (states 1-4)
     269             :  *
     270             :  * Temperature is used to calculate the compensated pressure and doesn't vary
     271             :  * as fast as pressure. Hence we reuse the same temperature for 4 samples of
     272             :  * pressure.
     273             : */
     274       24152 : void AP_Baro_MS56XX::_timer(void)
     275             : {
     276             :     uint8_t next_cmd;
     277             :     uint8_t next_state;
     278       24152 :     uint32_t adc_val = _read_adc();
     279             : 
     280             :     /*
     281             :      * If read fails, re-initiate a read command for current state or we are
     282             :      * stuck
     283             :      */
     284       24152 :     if (adc_val == 0) {
     285           0 :         next_state = _state;
     286             :     } else {
     287       24152 :         next_state = (_state + 1) % 5;
     288             :     }
     289             : 
     290       24152 :     next_cmd = next_state == 0 ? ADDR_CMD_CONVERT_TEMPERATURE
     291             :                                : ADDR_CMD_CONVERT_PRESSURE;
     292       24152 :     if (!_dev->transfer(&next_cmd, 1, nullptr, 0)) {
     293           0 :         return;
     294             :     }
     295             : 
     296             :     /* if we had a failed read we are all done */
     297       24152 :     if (adc_val == 0 || adc_val == 0xFFFFFF) {
     298             :         // a failed read can mean the next returned value will be
     299             :         // corrupt, we must discard it. This copes with MISO being
     300             :         // pulled either high or low
     301           0 :         _discard_next = true;
     302           0 :         return;
     303             :     }
     304             : 
     305       24152 :     if (_discard_next) {
     306           0 :         _discard_next = false;
     307           0 :         _state = next_state;
     308           0 :         return;
     309             :     }
     310             : 
     311       24152 :     WITH_SEMAPHORE(_sem);
     312             : 
     313       24152 :     if (_state == 0) {
     314        4831 :         _update_and_wrap_accumulator(&_accum.s_D2, adc_val,
     315             :                                      &_accum.d2_count, 32);
     316       19321 :     } else if (pressure_ok(adc_val)) {
     317       19321 :         _update_and_wrap_accumulator(&_accum.s_D1, adc_val,
     318             :                                      &_accum.d1_count, 128);
     319             :     }
     320             :     
     321       24152 :     _state = next_state;
     322       24152 : }
     323             : 
     324       24152 : void AP_Baro_MS56XX::_update_and_wrap_accumulator(uint32_t *accum, uint32_t val,
     325             :                                                   uint8_t *count, uint8_t max_count)
     326             : {
     327       24152 :     *accum += val;
     328       24152 :     *count += 1;
     329       24152 :     if (*count == max_count) {
     330           0 :         *count = max_count / 2;
     331           0 :         *accum = *accum / 2;
     332             :     }
     333       24152 : }
     334             : 
     335        2403 : void AP_Baro_MS56XX::update()
     336             : {
     337             :     uint32_t sD1, sD2;
     338             :     uint8_t d1count, d2count;
     339             : 
     340             :     {
     341        2403 :         WITH_SEMAPHORE(_sem);
     342             : 
     343        2403 :         if (_accum.d1_count == 0) {
     344           0 :             return;
     345             :         }
     346             : 
     347        2403 :         sD1 = _accum.s_D1;
     348        2403 :         sD2 = _accum.s_D2;
     349        2403 :         d1count = _accum.d1_count;
     350        2403 :         d2count = _accum.d2_count;
     351        2403 :         memset(&_accum, 0, sizeof(_accum));
     352        2403 :     }
     353             : 
     354        2403 :     if (d1count != 0) {
     355        2403 :         _D1 = ((float)sD1) / d1count;
     356             :     }
     357        2403 :     if (d2count != 0) {
     358        2403 :         _D2 = ((float)sD2) / d2count;
     359             :     }
     360             : 
     361        2403 :     _calculate();
     362             : }
     363             : 
     364             : #if AP_BARO_MS5611_ENABLED
     365             : // Calculate Temperature and compensated Pressure in real units (Celsius degrees*100, mbar*100).
     366        2403 : void AP_Baro_MS5611::_calculate()
     367             : {
     368             :     float dT;
     369             :     float TEMP;
     370             :     float OFF;
     371             :     float SENS;
     372             : 
     373             :     // we do the calculations using floating point allows us to take advantage
     374             :     // of the averaging of D1 and D1 over multiple samples, giving us more
     375             :     // precision
     376        2403 :     dT = _D2-(((uint32_t)_cal_reg.c5)<<8);
     377        2403 :     TEMP = (dT * _cal_reg.c6)/8388608;
     378        2403 :     OFF = _cal_reg.c2 * 65536.0f + (_cal_reg.c4 * dT) / 128;
     379        2403 :     SENS = _cal_reg.c1 * 32768.0f + (_cal_reg.c3 * dT) / 256;
     380             : 
     381        2403 :     TEMP += 2000;
     382             : 
     383        2403 :     if (TEMP < 2000) {
     384             :         // second order temperature compensation when under 20 degrees C
     385           0 :         float T2 = (dT*dT) / 0x80000000;
     386           0 :         float Aux = sq(TEMP-2000.0);
     387           0 :         float OFF2 = 2.5f*Aux;
     388           0 :         float SENS2 = 1.25f*Aux;
     389           0 :         if (TEMP < -1500) {
     390             :             // extra compensation for temperatures below -15C
     391           0 :             OFF2 += 7 * sq(TEMP+1500);
     392           0 :             SENS2 += sq(TEMP+1500) * 11.0*0.5;
     393             :         }
     394           0 :         TEMP = TEMP - T2;
     395           0 :         OFF = OFF - OFF2;
     396           0 :         SENS = SENS - SENS2;
     397             :     }
     398             : 
     399             : 
     400        2403 :     float pressure = (_D1*SENS/2097152 - OFF)/32768;
     401        2403 :     float temperature = TEMP * 0.01f;
     402        2403 :     _copy_to_frontend(_instance, pressure, temperature);
     403        2403 : }
     404             : #endif  // AP_BARO_MS5611_ENABLED
     405             : 
     406             : #if AP_BARO_MS5607_ENABLED
     407             : // Calculate Temperature and compensated Pressure in real units (Celsius degrees*100, mbar*100).
     408           0 : void AP_Baro_MS5607::_calculate()
     409             : {
     410             :     float dT;
     411             :     float TEMP;
     412             :     float OFF;
     413             :     float SENS;
     414             : 
     415             :     // we do the calculations using floating point allows us to take advantage
     416             :     // of the averaging of D1 and D1 over multiple samples, giving us more
     417             :     // precision
     418           0 :     dT = _D2-(((uint32_t)_cal_reg.c5)<<8);
     419           0 :     TEMP = (dT * _cal_reg.c6)/8388608;
     420           0 :     OFF = _cal_reg.c2 * 131072.0f + (_cal_reg.c4 * dT) / 64;
     421           0 :     SENS = _cal_reg.c1 * 65536.0f + (_cal_reg.c3 * dT) / 128;
     422             : 
     423           0 :     TEMP += 2000;
     424             : 
     425           0 :     if (TEMP < 2000) {
     426             :         // second order temperature compensation when under 20 degrees C
     427           0 :         float T2 = (dT*dT) / 0x80000000;
     428           0 :         float Aux = sq(TEMP-2000);
     429           0 :         float OFF2 = 61.0f*Aux/16.0f;
     430           0 :         float SENS2 = 2.0f*Aux;
     431           0 :         if (TEMP < -1500) {
     432           0 :             OFF2 += 15 * sq(TEMP+1500);
     433           0 :             SENS2 += 8 * sq(TEMP+1500);
     434             :         }
     435           0 :         TEMP = TEMP - T2;
     436           0 :         OFF = OFF - OFF2;
     437           0 :         SENS = SENS - SENS2;
     438             :     }
     439             : 
     440           0 :     float pressure = (_D1*SENS/2097152 - OFF)/32768;
     441           0 :     float temperature = TEMP * 0.01f;
     442           0 :     _copy_to_frontend(_instance, pressure, temperature);
     443           0 : }
     444             : #endif  // AP_BARO_MS5607_ENABLED
     445             : 
     446             : #if AP_BARO_MS5637_ENABLED
     447             : // Calculate Temperature and compensated Pressure in real units (Celsius degrees*100, mbar*100).
     448           0 : void AP_Baro_MS5637::_calculate()
     449             : {
     450             :     int32_t dT, TEMP;
     451             :     int64_t OFF, SENS;
     452           0 :     int32_t raw_pressure = _D1;
     453           0 :     int32_t raw_temperature = _D2;
     454             : 
     455           0 :     dT = raw_temperature - (((uint32_t)_cal_reg.c5) << 8);
     456           0 :     TEMP = 2000 + ((int64_t)dT * (int64_t)_cal_reg.c6) / 8388608;
     457           0 :     OFF = (int64_t)_cal_reg.c2 * (int64_t)131072 + ((int64_t)_cal_reg.c4 * (int64_t)dT) / (int64_t)64;
     458           0 :     SENS = (int64_t)_cal_reg.c1 * (int64_t)65536 + ((int64_t)_cal_reg.c3 * (int64_t)dT) / (int64_t)128;
     459             : 
     460           0 :     if (TEMP < 2000) {
     461             :         // second order temperature compensation when under 20 degrees C
     462           0 :         int32_t T2 = ((int64_t)3 * ((int64_t)dT * (int64_t)dT) / (int64_t)8589934592);
     463           0 :         int64_t aux = (TEMP - 2000) * (TEMP - 2000);
     464           0 :         int64_t OFF2 = 61 * aux / 16;
     465           0 :         int64_t SENS2 = 29 * aux / 16;
     466             : 
     467           0 :         if (TEMP < -1500) {
     468           0 :             OFF2 += 17 * sq(TEMP+1500);
     469           0 :             SENS2 += 9 * sq(TEMP+1500);
     470             :         }
     471             :         
     472           0 :         TEMP = TEMP - T2;
     473           0 :         OFF = OFF - OFF2;
     474           0 :         SENS = SENS - SENS2;
     475             :     }
     476             : 
     477           0 :     int32_t pressure = ((int64_t)raw_pressure * SENS / (int64_t)2097152 - OFF) / (int64_t)32768;
     478           0 :     float temperature = TEMP * 0.01f;
     479           0 :     _copy_to_frontend(_instance, (float)pressure, temperature);
     480           0 : }
     481             : #endif  // AP_BARO_MS5637_ENABLED
     482             : 
     483             : #if AP_BARO_MS5837_ENABLED
     484             : // Calculate Temperature and compensated Pressure in real units (Celsius degrees*100, mbar*100).
     485           0 : void AP_Baro_MS5837::_calculate()
     486             : {
     487           0 :     if (_subtype == DEVTYPE_BARO_MS5837_02BA) {
     488           0 :         _calculate_5837_02ba();
     489             :     } else {
     490           0 :         _calculate_5837_30ba();
     491             :     }
     492           0 : }
     493             : 
     494             : // Calculate Temperature and compensated Pressure in real units (Celsius degrees*100, mbar*100).
     495           0 : void AP_Baro_MS5837::_calculate_5837_30ba()
     496             : {
     497             :     int32_t dT, TEMP, T2;
     498             :     int64_t OFF, OFF2, SENS, SENS2;
     499           0 :     int32_t raw_pressure = _D1;
     500           0 :     int32_t raw_temperature = _D2;
     501             : 
     502           0 :     dT = raw_temperature - ((uint32_t)_cal_reg.c5 << 8);
     503           0 :     TEMP = 2000 + ((int64_t)dT * (int64_t)_cal_reg.c6) / 8388608;
     504           0 :     OFF = (int64_t)_cal_reg.c2 * (int64_t)65536 + ((int64_t)_cal_reg.c4 * (int64_t)dT) / (int64_t)128;
     505           0 :     SENS = (int64_t)_cal_reg.c1 * (int64_t)32768 + ((int64_t)_cal_reg.c3 * (int64_t)dT) / (int64_t)256;
     506             : 
     507           0 :     int64_t aux = sq(TEMP - 2000);
     508           0 :     if (TEMP < 2000) {
     509             :         // second order "low temperature" compensation when under 20 degrees C
     510           0 :         T2 = (int64_t)3 * sq((int64_t)dT) / (int64_t)8589934592;
     511           0 :         OFF2 = 3 * aux / 2;
     512           0 :         SENS2 = 5 * aux / 8;
     513             : 
     514           0 :         if (TEMP < -1500) {
     515             :             // "very low temperature" compensation, when under -15 degrees C
     516           0 :             OFF2 += 7 * sq(TEMP+1500);
     517           0 :             SENS2 += 4 * sq(TEMP+1500);
     518             :         }
     519             :     } else {
     520             :         // "high temperature" compensation, when at or over 20 degrees C
     521           0 :         T2 = (int64_t)2 * sq((int64_t)dT) / (int64_t)137438953472;
     522           0 :         OFF2 = aux / 16;
     523           0 :         SENS2 = 0;
     524             :     }
     525           0 :     TEMP = TEMP - T2;
     526           0 :     OFF = OFF - OFF2;
     527           0 :     SENS = SENS - SENS2;
     528             : 
     529           0 :     int32_t pressure = ((int64_t)raw_pressure * SENS / (int64_t)2097152 - OFF) / (int64_t)8192;
     530           0 :     pressure = pressure * 10; // MS5837 only reports to 0.1 mbar
     531           0 :     float temperature = TEMP * 0.01f;
     532             : 
     533           0 :     _copy_to_frontend(_instance, (float)pressure, temperature);
     534           0 : }
     535             : // Calculate Temperature and compensated Pressure in real units (Celsius degrees*100, mbar*100).
     536           0 : void AP_Baro_MS5837::_calculate_5837_02ba() {
     537           0 :     int32_t dT = _D2 - ((int32_t)_cal_reg.c5 << 8);
     538           0 :     int32_t TEMP = 2000 + ((dT * _cal_reg.c6) >> 23);
     539             : 
     540           0 :     int64_t OFF = ((int64_t)_cal_reg.c2 << 17) + (((int64_t)_cal_reg.c4 * dT) >> 6);
     541           0 :     int64_t SENS = ((int64_t)_cal_reg.c1 << 16) + (((int64_t)_cal_reg.c3 * dT) >> 7);
     542             : 
     543           0 :     if (TEMP < 2000) {
     544             :         // Second-order compensation
     545           0 :         int32_t T2 = ((int64_t)11 * (int64_t)sq((int64_t)dT)) >> 35;
     546           0 :         int64_t aux = sq(TEMP - 2000);
     547           0 :         int64_t OFF2 = 31 * aux >> 3;
     548           0 :         int64_t SENS2 = 63 * aux >> 5;
     549             : 
     550           0 :         TEMP -= T2;
     551           0 :         OFF -= OFF2;
     552           0 :         SENS -= SENS2;
     553             :     }
     554             : 
     555             :     // Cast _D1 to int64_t before performing multiplication and shift
     556           0 :     int64_t pressure = ((((int64_t)_D1 * SENS) >> 21) - OFF) >> 15;
     557             : 
     558             :     // Update frontend with calculated values
     559           0 :     _copy_to_frontend(_instance, (float)pressure, (float)TEMP / 100);
     560           0 : }
     561             : 
     562           0 : AP_Baro_Backend::DevTypes AP_Baro_MS5837::devtype() const {
     563           0 :     return _subtype;
     564             : }
     565             : 
     566             : #endif  // AP_BARO_MS5837_ENABLED
     567             : 
     568             : #endif  // AP_BARO_MS56XX_ENABLED

Generated by: LCOV version 1.14