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->base = spi;
35 baro->cs = cs;
36 baro->tempSensitivity = tempSensitivity;
37 baro->pressSensitivity = pressSensitivity;
38 baro->update = BMP581_update;
39 baro->readTemp = BMP581_readTemp;
40 baro->readRawTemp = BMP581_readRawTemp;
41 baro->processRawTemp = BMP581_processRawTemp;
42 baro->readPress = BMP581_readPress;
43 baro->readRawPress = BMP581_readRawPress;
44 baro->processRawPress = BMP581_processRawPress;
45
46 // Initial dummy read
47 BMP581_readRegister(baro, 0x01);
48
49 // Soft reset device
50 BMP581_writeRegister(baro, BMP581_CMD, 0xB6);
51
52 while (BMP581_readRegister(baro, BMP581_CHIP_ID) == 0x00); // Check chip ID
53 while (BMP581_readRegister(baro, BMP581_INT_STATUS) != 0x10); // Wait for POR complete
54 while (!(BMP581_readRegister(baro, BMP581_STATUS) & BMP581_STATUS_NVM_RDY)); // Check device status NVM ready
55 while ((BMP581_readRegister(baro, BMP581_STATUS) & BMP581_STATUS_NVM_ERR)); // Check device status NVM err
56
57 BMP581_writeRegister(baro, BMP581_ODR_CFG, BMP581_ODR_CFG_DEEP_DIS); // Disable deep sleep
58 for (uint32_t i = 0; i < 0x1FFFF; i++); // Wait for at least t_standby
59 BMP581_writeRegister(baro, BMP581_ODR_CFG, BMP581_ODR_CFG_DEEP_DIS | BMP581_ODR_CFG_PWR_CONTINUOUS); // Set continuous sample
60
61 // Read OSR config for reserved bits and enable pressure measurement with 16x oversampling
62 uint8_t OSRCFG = BMP581_readRegister(baro, BMP581_OSR_CFG);
63 BMP581_writeRegister(baro, BMP581_OSR_CFG, (BMP581_OSR_CFG_RESERVED & OSRCFG) | BMP581_OSR_CFG_PRESS_EN | BMP581_OSR_CFG_OSR_P_16);
64
65 // Set ground pressure reading on init
66 for (uint32_t i = 0; i < 0x1FFFF; i++); // Wait for at least t_reconf
67 baro->readPress(baro, &baro->groundPress); // Read current pressure
68
69 return *baro;
70}
71
72/******************************** DEVICE METHODS ********************************/
73
74/* =============================================================================== */
82 baro->readRawTemp(baro, baro->rawTemp);
83 baro->processRawTemp(baro, baro->rawTemp, &baro->temp);
84
85 baro->readRawPress(baro, baro->rawPress);
86 baro->processRawPress(baro, baro->rawPress, &baro->press);
87}
88
89/* =============================================================================== */
97void BMP581_readTemp(BMP581_t *baro, float *out) {
98 uint8_t bytes[BMP581_DATA_TOTAL];
99 baro->readRawTemp(baro, bytes);
100 baro->processRawTemp(baro, bytes, out);
101}
102
103/* =============================================================================== */
112void BMP581_processRawTemp(BMP581_t *baro, uint8_t *bytes, float *out) {
113 *out = baro->tempSensitivity * (int32_t)(((uint32_t)bytes[0] << 16) | ((uint32_t)bytes[1] << 8) | bytes[0]);
114}
115
116/* =============================================================================== */
124void BMP581_readRawTemp(BMP581_t *baro, uint8_t *out) {
125 out[0] = BMP581_readRegister(baro, BMP581_TEMPERATURE_MSB); // temp high
126 out[1] = BMP581_readRegister(baro, BMP581_TEMPERATURE_LSB); // temp low
127 out[2] = BMP581_readRegister(baro, BMP581_TEMPERATURE_XLSB); // temp mid
128}
129
130/* =============================================================================== */
138void BMP581_readPress(BMP581_t *baro, float *out) {
139 uint8_t bytes[BMP581_DATA_TOTAL];
140 baro->readRawPress(baro, bytes);
141 baro->processRawPress(baro, bytes, out);
142}
143
144/* =============================================================================== */
152void BMP581_processRawPress(BMP581_t *baro, uint8_t *bytes, float *out) {
153 *out = baro->pressSensitivity * (int32_t)(((uint32_t)bytes[0] << 16) | ((uint32_t)bytes[1] << 8) | bytes[0]);
154}
155
156/* =============================================================================== */
164void BMP581_readRawPress(BMP581_t *baro, uint8_t *out) {
165 uint8_t tmp[BMP581_DATA_SIZE];
166 BMP581_readRegisters(baro, BMP581_PRESSURE_XLSB, BMP581_DATA_SIZE, tmp);
167 out[0] = tmp[2]; // temp high
168 out[1] = tmp[1]; // temp low
169 out[2] = tmp[0]; // temp mid
170}
171
172/******************************** INTERFACE METHODS ********************************/
173
174void BMP581_writeRegister(BMP581_t *baro, uint8_t address, uint8_t data) {
175 SPI_t *spi = baro->base;
176 GPIOpin_t cs = baro->cs;
177
178 cs.reset(&cs);
179
180 // Send read command and address
181 uint8_t payload = address & 0x7F; // Load payload with address and read command
182 spi->transmit(spi, payload); // Transmit payload
183 spi->transmit(spi, data); // Transmit dummy data and read response data
184
185 cs.set(&cs);
186}
187
188uint8_t BMP581_readRegister(BMP581_t *baro, uint8_t address) {
189 uint8_t response = 0;
190 SPI_t *spi = baro->base;
191 GPIOpin_t cs = baro->cs;
192
193 cs.reset(&cs);
194
195 // Send read command and address
196 uint8_t payload = address | 0x80; // Load payload with address and read command
197 response = spi->transmit(spi, payload); // Transmit payload
198 response = spi->transmit(spi, 0xFF); // Transmit dummy data and read response data
199
200 cs.set(&cs);
201
202 return response;
203}
204
205void BMP581_readRegisters(BMP581_t *baro, uint8_t address, uint8_t count, uint8_t *out) {
206 SPI_t *spi = baro->base;
207 GPIOpin_t cs = baro->cs;
208
209 cs.reset(&cs);
210
211 // Send read command and address
212 uint8_t payload = address | 0x80; // Load payload with address and read command
213 spi->transmit(spi, payload); // Transmit payload
214
215 // Auto increment read through registers
216 for (uint8_t i = 0; i < count; i++) {
217 out[i] = spi->transmit(spi, 0xFF);
218 }
219
220 cs.set(&cs);
221}
void BMP581_readRawPress(BMP581_t *, uint8_t *)
Definition bmp581.c:164
void BMP581_readTemp(BMP581_t *, float *)
Read the temperature from the BMP581 sensor.
Definition bmp581.c:97
void BMP581_update(BMP581_t *)
Updates the BMP581 barometer readings.
Definition bmp581.c:81
void BMP581_readPress(BMP581_t *, float *)
Definition bmp581.c:138
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_readRawTemp(BMP581_t *, uint8_t *)
Definition bmp581.c:124
void BMP581_processRawTemp(BMP581_t *, uint8_t *, float *)
Processes raw temperature data from BMP581 sensor.
Definition bmp581.c:112
void BMP581_processRawPress(BMP581_t *, uint8_t *, float *)
Definition bmp581.c:152
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