122 lines
5 KiB
C
122 lines
5 KiB
C
// Copyright 2026 A.M. Rowsell <amr@frzn.dev>
|
|
// SPDX-License-Identifier: MIT
|
|
#include "inc/bmp.h"
|
|
|
|
float bmp_cal_data_fp[15];
|
|
|
|
int getBMPData(i2c_inst_t *i2c, float *temperature, float *pressure) {
|
|
uint8_t rawMeasurements[7];
|
|
uint32_t rawTemp;
|
|
uint32_t rawPress;
|
|
i2c_write_blocking(i2c, BMP_ADDR, &BMP_STATUS, 1, true);
|
|
i2c_read_blocking(i2c, BMP_ADDR, rawMeasurements, 7,
|
|
false); // read status & 6 data bytes
|
|
if ((rawMeasurements[0] & 0x60) != 0x60) {
|
|
// no measurements ready
|
|
return 1;
|
|
}
|
|
rawPress = (rawMeasurements[3] << 16) | (rawMeasurements[2] << 8) |
|
|
rawMeasurements[1];
|
|
rawTemp = (rawMeasurements[6] << 16) | (rawMeasurements[5] << 8) |
|
|
rawMeasurements[4];
|
|
// now for the crazy math
|
|
|
|
float partial_data1;
|
|
float partial_data2;
|
|
float t_lin;
|
|
|
|
partial_data1 = (float)(rawTemp - bmp_cal_data_fp[PAR_T1]);
|
|
partial_data2 = (float)(partial_data1 * bmp_cal_data_fp[PAR_T2]);
|
|
t_lin =
|
|
partial_data2 + (partial_data1 * partial_data1) * bmp_cal_data_fp[PAR_T3];
|
|
// t_lin is compensated temperature
|
|
|
|
float comp_press;
|
|
float partial_data3;
|
|
float partial_data4;
|
|
float partial_out1;
|
|
float partial_out2;
|
|
|
|
partial_data1 = bmp_cal_data_fp[PAR_P6] * t_lin;
|
|
partial_data2 = bmp_cal_data_fp[PAR_P7] * (t_lin * t_lin);
|
|
partial_data3 = bmp_cal_data_fp[PAR_P8] * (t_lin * t_lin * t_lin);
|
|
partial_out1 =
|
|
bmp_cal_data_fp[PAR_P5] + partial_data1 + partial_data2 + partial_data3;
|
|
|
|
partial_data1 = bmp_cal_data_fp[PAR_P2] * t_lin;
|
|
partial_data2 = bmp_cal_data_fp[PAR_P3] * (t_lin * t_lin);
|
|
partial_data3 = bmp_cal_data_fp[PAR_P4] * (t_lin * t_lin * t_lin);
|
|
partial_out2 = (float)rawPress * (bmp_cal_data_fp[PAR_P1] + partial_data1 +
|
|
partial_data2 + partial_data3);
|
|
|
|
partial_data1 = (float)rawPress * (float)rawPress;
|
|
partial_data2 = bmp_cal_data_fp[PAR_P9] + bmp_cal_data_fp[PAR_P10] * t_lin;
|
|
partial_data3 = partial_data1 * partial_data2;
|
|
partial_data4 =
|
|
partial_data3 + ((float)rawPress * (float)rawPress * (float)rawPress) *
|
|
bmp_cal_data_fp[PAR_P11];
|
|
comp_press = partial_out1 + partial_out2 + partial_data4;
|
|
|
|
*temperature = t_lin;
|
|
*pressure = comp_press;
|
|
return 0;
|
|
}
|
|
|
|
int getBMPCalData(i2c_inst_t *i2c, bmp_cal_data_t *calData) {
|
|
uint8_t rawValues[21];
|
|
i2c_write_blocking(i2c, BMP_ADDR, &BMP_CAL_ADDR, 1, true);
|
|
i2c_read_blocking(i2c, BMP_ADDR, rawValues, BMP_CAL_LEN, false);
|
|
|
|
calData->NVM_PAR_T1 = (uint16_t)((rawValues[1] << 8) | rawValues[0]);
|
|
calData->NVM_PAR_T2 = (uint16_t)((rawValues[3] << 8) | rawValues[2]);
|
|
calData->NVM_PAR_T3 = (int8_t)(rawValues[4]);
|
|
calData->NVM_PAR_P1 = ((int16_t)(rawValues[6] << 8) | (int16_t)rawValues[5]);
|
|
calData->NVM_PAR_P2 = ((int16_t)(rawValues[8] << 8) | (int16_t)rawValues[7]);
|
|
calData->NVM_PAR_P3 = (int8_t)(rawValues[9]);
|
|
calData->NVM_PAR_P4 = (int8_t)(rawValues[10]);
|
|
calData->NVM_PAR_P5 = (uint16_t)((rawValues[12] << 8) | rawValues[11]);
|
|
calData->NVM_PAR_P6 = (uint16_t)((rawValues[14] << 8) | rawValues[13]);
|
|
calData->NVM_PAR_P7 = (int8_t)(rawValues[15]);
|
|
calData->NVM_PAR_P8 = (int8_t)(rawValues[16]);
|
|
calData->NVM_PAR_P9 =
|
|
((int16_t)(rawValues[18] << 8) | (int16_t)rawValues[17]);
|
|
calData->NVM_PAR_P10 = (int8_t)(rawValues[19]);
|
|
calData->NVM_PAR_P11 = (int8_t)(rawValues[20]);
|
|
|
|
// convert cal values to floating point, adjusted values
|
|
bmp_cal_data_fp[PAR_T1] = (float)calData->NVM_PAR_T1 * 256.0f;
|
|
bmp_cal_data_fp[PAR_T2] = (float)calData->NVM_PAR_T2 / 1073741824.0f;
|
|
bmp_cal_data_fp[PAR_T3] = (float)calData->NVM_PAR_T3 / 281474976710656.0f;
|
|
bmp_cal_data_fp[PAR_P1] =
|
|
((float)calData->NVM_PAR_P1 - 16384.0f) / 1048576.0f;
|
|
bmp_cal_data_fp[PAR_P2] =
|
|
((float)calData->NVM_PAR_P2 - 16384.0f) / 536870912.0f;
|
|
bmp_cal_data_fp[PAR_P3] = (float)calData->NVM_PAR_P3 / 4294967296.0f;
|
|
bmp_cal_data_fp[PAR_P4] = (float)calData->NVM_PAR_P4 / 137438953472.0f;
|
|
bmp_cal_data_fp[PAR_P5] = (float)calData->NVM_PAR_P5 * 8.0f;
|
|
bmp_cal_data_fp[PAR_P6] = (float)calData->NVM_PAR_P6 / 64.0f;
|
|
bmp_cal_data_fp[PAR_P7] = (float)calData->NVM_PAR_P7 / 256.0f;
|
|
bmp_cal_data_fp[PAR_P8] = (float)calData->NVM_PAR_P8 / 32768.0f;
|
|
bmp_cal_data_fp[PAR_P9] = (float)calData->NVM_PAR_P9 / 281474976710656.0f;
|
|
bmp_cal_data_fp[PAR_P10] = (float)calData->NVM_PAR_P10 / 281474976710656.0f;
|
|
bmp_cal_data_fp[PAR_P11] =
|
|
(float)calData->NVM_PAR_P11 / 36893488147419103232.0f;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int initBMP(i2c_inst_t *i2c) {
|
|
static const uint8_t BMP_RESET[2] = {0x7E, 0xB6};
|
|
static const uint8_t BMP_SETUP[6] = {0x1C, 0x0B, 0x1D, 0x08, 0x1F, 0x0A};
|
|
static const uint8_t BMP_START[2] = {0x1B, 0x33};
|
|
|
|
bmp_cal_data_t bmpRawCalValues;
|
|
i2c_write_blocking(i2c, BMP_ADDR, BMP_RESET, 2, false); // send reset
|
|
sleep_ms(2); // wait for reset to complete
|
|
getBMPCalData(i2c, &bmpRawCalValues);
|
|
i2c_write_blocking(i2c, BMP_ADDR, BMP_SETUP, 6,
|
|
false); // set up sampling parameters
|
|
i2c_write_blocking(i2c, BMP_ADDR, BMP_START, 2,
|
|
false); // start automatic measurements
|
|
return 0;
|
|
}
|