4 * Calculations used in this code taken from iNav's SPL006 (sic) implementation
5 * https://github.com/iNavFlight/inav/pull/5028
7 * Code reused under GPL License, see the iNav project for full license information
8 * https://github.com/iNavFlight/inav
11 #include "baro_spl06.h"
13 uint8_t SPL06::oversampleToRegVal(const uint8_t oversamples
) const
17 default: // fallthrough
29 int32_t SPL06::oversampleToScaleFactor(const uint8_t oversamples
) const
33 default: // falthrough
34 case 1: return 524288;
35 case 2: return 1572864;
36 case 4: return 3670016;
37 case 8: return 7864320;
38 case 16: return 253952;
39 case 32: return 516096;
40 case 64: return 1040384;
41 case 128: return 2088960;
45 void SPL06::initialize()
50 // Step 1: Load calibration data
52 readRegister(SPL06_MODE_AND_STATUS_REG
, &status
, sizeof(status
));
53 if (((status
& SPL06_MEAS_CFG_COEFFS_RDY
) == 0) || ((status
& SPL06_MEAS_CFG_SENSOR_RDY
) == 0))
56 uint8_t caldata
[SPL06_CALIB_COEFFS_LEN
];
57 readRegister(SPL06_CALIB_COEFFS_START
, caldata
, sizeof(caldata
));
59 m_calib
.c0
= (caldata
[0] & 0x80 ? 0xF000 : 0) | ((uint16_t)caldata
[0] << 4) | (((uint16_t)caldata
[1] & 0xF0) >> 4);
60 m_calib
.c1
= ((caldata
[1] & 0x8 ? 0xF000 : 0) | ((uint16_t)caldata
[1] & 0x0F) << 8) | (uint16_t)caldata
[2];
61 m_calib
.c00
= (caldata
[3] & 0x80 ? 0xFFF00000 : 0) | ((uint32_t)caldata
[3] << 12) | ((uint32_t)caldata
[4] << 4) | (((uint32_t)caldata
[5] & 0xF0) >> 4);
62 m_calib
.c10
= (caldata
[5] & 0x8 ? 0xFFF00000 : 0) | (((uint32_t)caldata
[5] & 0x0F) << 16) | ((uint32_t)caldata
[6] << 8) | (uint32_t)caldata
[7];
63 m_calib
.c01
= ((uint16_t)caldata
[8] << 8) | ((uint16_t)caldata
[9]);
64 m_calib
.c11
= ((uint16_t)caldata
[10] << 8) | (uint16_t)caldata
[11];
65 m_calib
.c20
= ((uint16_t)caldata
[12] << 8) | (uint16_t)caldata
[13];
66 m_calib
.c21
= ((uint16_t)caldata
[14] << 8) | (uint16_t)caldata
[15];
67 m_calib
.c30
= ((uint16_t)caldata
[16] << 8) | (uint16_t)caldata
[17];
69 // Step 2: Set up oversampling and FIFO
71 reg_value
= SPL06_TEMP_USE_EXT_SENSOR
| oversampleToRegVal(OVERSAMPLING_TEMPERATURE
);
72 writeRegister(SPL06_TEMPERATURE_CFG_REG
, ®_value
, sizeof(reg_value
));
74 reg_value
= oversampleToRegVal(OVERSAMPLING_PRESSURE
);
75 writeRegister(SPL06_PRESSURE_CFG_REG
, ®_value
, sizeof(reg_value
));
78 if (OVERSAMPLING_TEMPERATURE
> 8)
79 reg_value
|= SPL06_TEMPERATURE_RESULT_BIT_SHIFT
;
80 if (OVERSAMPLING_PRESSURE
> 8)
81 reg_value
|= SPL06_PRESSURE_RESULT_BIT_SHIFT
;
82 writeRegister(SPL06_INT_AND_FIFO_CFG_REG
, ®_value
, sizeof(reg_value
));
88 uint8_t SPL06::getTemperatureDuration()
90 return SPL06_MEASUREMENT_TIME(OVERSAMPLING_TEMPERATURE
);
93 void SPL06::startTemperature()
95 uint8_t reg_value
= SPL06_MEAS_TEMPERATURE
;
96 writeRegister(SPL06_MODE_AND_STATUS_REG
, ®_value
, sizeof(reg_value
));
99 int32_t SPL06::getTemperature()
102 readRegister(SPL06_MODE_AND_STATUS_REG
, &status
, sizeof(status
));
103 if ((status
& SPL06_MEAS_CFG_TEMPERATURE_RDY
) == 0)
104 return TEMPERATURE_INVALID
;
106 uint8_t data
[SPL06_TEMPERATURE_LEN
];
107 readRegister(SPL06_TEMPERATURE_START_REG
, data
, sizeof(data
));
109 // Unpack and descale
110 int32_t uncorr_temp
= (int32_t)((data
[0] & 0x80 ? 0xFF000000 : 0) | (((uint32_t)(data
[0])) << 16) | (((uint32_t)(data
[1])) << 8) | ((uint32_t)data
[2]));
111 m_temperatureLast
= (float)uncorr_temp
/ oversampleToScaleFactor(OVERSAMPLING_TEMPERATURE
);
113 // Adjust for calibration
114 const float temp_comp
= (float)m_calib
.c0
/ 2 + m_temperatureLast
* m_calib
.c1
;
116 return temp_comp
* 100;
119 uint8_t SPL06::getPressureDuration()
121 return SPL06_MEASUREMENT_TIME(OVERSAMPLING_PRESSURE
);
124 void SPL06::startPressure()
126 uint8_t reg_value
= SPL06_MEAS_PRESSURE
;
127 writeRegister(SPL06_MODE_AND_STATUS_REG
, ®_value
, sizeof(reg_value
));
130 uint32_t SPL06::getPressure()
133 readRegister(SPL06_MODE_AND_STATUS_REG
, &status
, sizeof(status
));
134 if ((status
& SPL06_MEAS_CFG_PRESSURE_RDY
) == 0)
135 return PRESSURE_INVALID
;
137 uint8_t data
[SPL06_PRESSURE_LEN
];
138 readRegister(SPL06_PRESSURE_START_REG
, data
, sizeof(data
));
140 // Unpack and descale
141 int32_t uncorr_press
= (int32_t)((data
[0] & 0x80 ? 0xFF000000 : 0) | (((uint32_t)(data
[0])) << 16) | (((uint32_t)(data
[1])) << 8) | ((uint32_t)data
[2]));
142 const float p_raw_sc
= (float)uncorr_press
/ oversampleToScaleFactor(OVERSAMPLING_PRESSURE
);
144 // Adjust for calibration and temperature
145 const float pressure_cal
= (float)m_calib
.c00
+ p_raw_sc
* ((float)m_calib
.c10
+ p_raw_sc
* ((float)m_calib
.c20
+ p_raw_sc
* m_calib
.c30
));
146 const float p_temp_comp
= m_temperatureLast
* ((float)m_calib
.c01
+ p_raw_sc
* ((float)m_calib
.c11
+ p_raw_sc
* m_calib
.c21
));
148 return (pressure_cal
+ p_temp_comp
) * 10.0;
153 // Assumes Wire.begin() has already been called
156 // SPL06 can have two addresses based on the SDO pin.
157 // check primary address
158 m_address
= SPL06_I2C_ADDR
;
159 readRegister(SPL06_CHIP_ID_REG
, &chipid
, sizeof(chipid
));
160 if (chipid
== SPL06_DEFAULT_CHIP_ID
)
163 // check alternate address
164 m_address
= SPL06_I2C_ADDR_ALT
;
165 readRegister(SPL06_CHIP_ID_REG
, &chipid
, sizeof(chipid
));
166 return chipid
== SPL06_DEFAULT_CHIP_ID
;