Loading...
Searching...
No Matches
bmp581.c
1/***********************************************************************************
2 * @file BMP581.c *
3 * @author Matt Ricci *
4 * @addtogroup BMP581 *
5 * *
6 * @todo Add altitude calculation method *
7 * @todo Document implementation *
8 * @todo Move private interface methods (read/write register) to static functions *
9 * with internal prototypes. *
10 * @todo Replace giga loops with hardware timer *
11 * @{ *
12 ***********************************************************************************/
13
14#include "bmp581.h"
15
16/* =============================================================================== */
28 BMP581_t *baro,
29 SPI_t *spi,
30 GPIOpin_t cs,
31 float tempSensitivity,
32 float pressSensitivity
33) {
34 baro->spi = spi;
35 baro->cs = cs;
36 baro->tempSensitivity = tempSensitivity;
37 baro->base.sensitivity = pressSensitivity;
38 baro->base.tempDataSize = BMP581_DATA_SIZE;
39 baro->base.pressDataSize = BMP581_DATA_SIZE;
40 baro->base.update = BMP581_update;
41 baro->base.readTemp = BMP581_readTemp;
44 baro->base.readPress = BMP581_readPress;
47 baro->base.rawPress = baro->rawPress;
48 baro->base.rawTemp = baro->rawTemp;
49
50 // Initial dummy read
51 BMP581_readRegister(baro, 0x01);
52
53 // Soft reset device
54 BMP581_writeRegister(baro, BMP581_CMD, 0xB6);
55
56 while (BMP581_readRegister(baro, BMP581_CHIP_ID) == 0x00); // Check chip ID
57 while (BMP581_readRegister(baro, BMP581_INT_STATUS) != 0x10); // Wait for POR complete
58 while (!(BMP581_readRegister(baro, BMP581_STATUS) & BMP581_STATUS_NVM_RDY)); // Check device status NVM ready
59 while ((BMP581_readRegister(baro, BMP581_STATUS) & BMP581_STATUS_NVM_ERR)); // Check device status NVM err
60
61 BMP581_writeRegister(baro, BMP581_ODR_CFG, BMP581_ODR_CFG_DEEP_DIS); // Disable deep sleep
62 for (uint32_t i = 0; i < 0x1FFFF; i++); // Wait for at least t_standby
63 BMP581_writeRegister(baro, BMP581_ODR_CFG, BMP581_ODR_CFG_DEEP_DIS | BMP581_ODR_CFG_PWR_CONTINUOUS); // Set continuous sample
64
65 // Read OSR config for reserved bits and enable pressure measurement with 16x oversampling
66 uint8_t OSRCFG = BMP581_readRegister(baro, BMP581_OSR_CFG);
67 BMP581_writeRegister(baro, BMP581_OSR_CFG, (BMP581_OSR_CFG_RESERVED & OSRCFG) | BMP581_OSR_CFG_PRESS_EN | BMP581_OSR_CFG_OSR_P_16);
68
69 // Set ground pressure reading on init
70 for (uint32_t i = 0; i < 0x1FFFF; i++); // Wait for at least t_reconf
71 baro->base.readPress((Baro_t *)baro, &baro->base.groundPress); // Read current pressure
72
73 return *baro;
74}
75
76/******************************** DEVICE METHODS ********************************/
77
78/* =============================================================================== */
85void BMP581_update(Baro_t *baro) {
86 baro->readRawTemp(baro, baro->rawTemp);
87 baro->processRawTemp(baro, baro->rawTemp, &baro->temp);
88
89 baro->readRawPress(baro, baro->rawPress);
90 baro->processRawPress(baro, baro->rawPress, &baro->press);
91}
92
93/* =============================================================================== */
101void BMP581_readTemp(Baro_t *baro, float *out) {
102 uint8_t bytes[BMP581_DATA_TOTAL];
103 baro->readRawTemp(baro, bytes);
104 baro->processRawTemp(baro, bytes, out);
105}
106
107/* =============================================================================== */
116void BMP581_processRawTemp(Baro_t *baro, uint8_t *bytes, float *out) {
117 *out = ((BMP581_t *)baro)->tempSensitivity * (int32_t)(((uint32_t)bytes[0] << 16) | ((uint32_t)bytes[1] << 8) | bytes[0]);
118}
119
120/* =============================================================================== */
128void BMP581_readRawTemp(Baro_t *baro, uint8_t *out) {
129 out[0] = BMP581_readRegister((BMP581_t *)baro, BMP581_TEMPERATURE_MSB); // temp high
130 out[1] = BMP581_readRegister((BMP581_t *)baro, BMP581_TEMPERATURE_LSB); // temp low
131 out[2] = BMP581_readRegister((BMP581_t *)baro, BMP581_TEMPERATURE_XLSB); // temp mid
132}
133
134/* =============================================================================== */
142void BMP581_readPress(Baro_t *baro, float *out) {
143 uint8_t bytes[BMP581_DATA_TOTAL];
144 baro->readRawPress(baro, bytes);
145 baro->processRawPress(baro, bytes, out);
146}
147
148/* =============================================================================== */
156void BMP581_processRawPress(Baro_t *baro, uint8_t *bytes, float *out) {
157 *out = ((BMP581_t *)baro)->base.sensitivity * (int32_t)(((uint32_t)bytes[0] << 16) | ((uint32_t)bytes[1] << 8) | bytes[0]);
158}
159
160/* =============================================================================== */
168void BMP581_readRawPress(Baro_t *baro, uint8_t *out) {
169 uint8_t tmp[BMP581_DATA_SIZE];
170 BMP581_readRegisters((BMP581_t *)baro, BMP581_PRESSURE_XLSB, BMP581_DATA_SIZE, tmp);
171 out[0] = tmp[2]; // temp high
172 out[1] = tmp[1]; // temp low
173 out[2] = tmp[0]; // temp mid
174}
175
176/******************************** INTERFACE METHODS ********************************/
177
178void BMP581_writeRegister(BMP581_t *baro, uint8_t address, uint8_t data) {
179 SPI_t *spi = baro->spi;
180 GPIOpin_t cs = baro->cs;
181
182 cs.reset(&cs);
183
184 // Send read command and address
185 uint8_t payload = address & 0x7F; // Load payload with address and read command
186 spi->transmit(spi, payload); // Transmit payload
187 spi->transmit(spi, data); // Transmit dummy data and read response data
188
189 cs.set(&cs);
190}
191
192uint8_t BMP581_readRegister(BMP581_t *baro, uint8_t address) {
193 uint8_t response = 0;
194 SPI_t *spi = baro->spi;
195 GPIOpin_t cs = baro->cs;
196
197 cs.reset(&cs);
198
199 // Send read command and address
200 uint8_t payload = address | 0x80; // Load payload with address and read command
201 response = spi->transmit(spi, payload); // Transmit payload
202 response = spi->transmit(spi, 0xFF); // Transmit dummy data and read response data
203
204 cs.set(&cs);
205
206 return response;
207}
208
209void BMP581_readRegisters(BMP581_t *baro, uint8_t address, uint8_t count, uint8_t *out) {
210 SPI_t *spi = baro->spi;
211 GPIOpin_t cs = baro->cs;
212
213 cs.reset(&cs);
214
215 // Send read command and address
216 uint8_t payload = address | 0x80; // Load payload with address and read command
217 spi->transmit(spi, payload); // Transmit payload
218
219 // Auto increment read through registers
220 for (uint8_t i = 0; i < count; i++) {
221 out[i] = spi->transmit(spi, 0xFF);
222 }
223
224 cs.set(&cs);
225}
void(* readPress)(struct Baro *baro, float *out)
Pointer to readPress method.
Definition barometer.h:51
uint8_t * rawTemp
Pointer to driver defined raw temperature data array.
Definition barometer.h:112
void(* readTemp)(struct Baro *baro, float *out)
Pointer to readTemp method.
Definition barometer.h:38
void(* readRawPress)(struct Baro *baro, uint8_t *out)
Pointer to readRawPress method.
Definition barometer.h:77
float temp
Last read processed temperature value.
Definition barometer.h:115
uint8_t pressDataSize
Size of raw pressure data in bytes.
Definition barometer.h:109
float press
Last read processed pressure value.
Definition barometer.h:114
float groundPress
Stored ground pressure reading.
Definition barometer.h:113
void(* processRawTemp)(struct Baro *baro, uint8_t *bytes, float *out)
Pointer to processRawTemp method.
Definition barometer.h:92
void(* processRawPress)(struct Baro *baro, uint8_t *bytes, float *out)
Pointer to processRawPress method.
Definition barometer.h:107
void(* readRawTemp)(struct Baro *baro, uint8_t *out)
Pointer to readRawTemp method.
Definition barometer.h:64
uint8_t tempDataSize
Size of raw temperature data in bytes.
Definition barometer.h:110
uint8_t * rawPress
Pointer to driver defined raw pressure data array.
Definition barometer.h:111
void(* update)(struct Baro *baro)
Pointer to update method.
Definition barometer.h:25
void BMP581_readTemp(Baro_t *, float *)
Read the temperature from the BMP581 sensor.
Definition bmp581.c:101
void BMP581_processRawTemp(Baro_t *, uint8_t *, float *)
Processes raw temperature data from BMP581 sensor.
Definition bmp581.c:116
void BMP581_readRawTemp(Baro_t *, uint8_t *)
Definition bmp581.c:128
BMP581_t BMP581_init(BMP581_t *baro, SPI_t *spi, GPIOpin_t cs, float tempSensitivity, float pressSensitivity)
Initialiser for a BMP581 barometer.
Definition bmp581.c:27
void BMP581_readPress(Baro_t *, float *)
Definition bmp581.c:142
void BMP581_readRawPress(Baro_t *, uint8_t *)
Definition bmp581.c:168
void BMP581_update(Baro_t *)
Updates the BMP581 barometer readings.
Definition bmp581.c:85
void BMP581_processRawPress(Baro_t *, uint8_t *, float *)
Definition bmp581.c:156
void(* set)(struct GPIOpin *)
Definition gpiopin.h:155
void(* reset)(struct GPIOpin *)
Definition gpiopin.h:156
Struct definition for a GPIO pin.
Definition gpiopin.h:151
uint16_t(* transmit)(struct SPI *, uint16_t)
SPI transmit method.
Definition spi.h:139
Struct definition for SPI interface. Provides the interface for API consumers to interact with the SP...
Definition spi.h:134