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 *baro,
29 char name[DEVICE_NAME_LENGTH],
30 GPIO_TypeDef *port,
31 unsigned long cs,
32 float tempSensitivity,
33 float pressSensitivity
34) {
35 SPI_init(&baro->base, SENSOR_BARO, SPI1, MODE8, port, 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 volatile uint8_t counter = 0;
58
59 BMP581_writeRegister(baro, BMP581_ODR_CFG, BMP581_ODR_CFG_DEEP_DIS); // Disable deep sleep
60 for (uint32_t i = 0; i < 0x1FFFF; i++) {
61 counter++;
62 } // 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 uint8_t OSRCFG = BMP581_readRegister(baro, BMP581_OSR_CFG);
66 BMP581_writeRegister(baro, BMP581_OSR_CFG, (BMP581_OSR_CFG_RESERVED & OSRCFG) | BMP581_OSR_CFG_PRESS_EN | BMP581_OSR_CFG_OSR_P_16);
67
68 // Set ground pressure reading on init
69 for (uint32_t i = 0; i < 0x1FFFF; i++) {
70 counter++;
71 } // Wait for at least t_reconf
72 baro->readPress(baro, &baro->groundPress); // Read current pressure
73
74 DeviceHandle_t handle;
75 strcpy(handle.name, name);
76 handle.device = baro;
77 return handle;
78}
79
80/******************************** DEVICE METHODS ********************************/
81
82/* =============================================================================== */
89void BMP581_update(BMP581 *baro) {
90 baro->readRawTemp(baro, baro->rawTemp);
91 baro->processRawTemp(baro, baro->rawTemp, &baro->temp);
92
93 baro->readRawPress(baro, baro->rawPress);
94 baro->processRawPress(baro, baro->rawPress, &baro->press);
95}
96
97/* =============================================================================== */
105void BMP581_readTemp(BMP581 *baro, float *out) {
106 uint8_t bytes[BMP581_DATA_TOTAL];
107 baro->readRawTemp(baro, bytes);
108 baro->processRawTemp(baro, bytes, out);
109}
110
111/* =============================================================================== */
120void BMP581_processRawTemp(BMP581 *baro, uint8_t *bytes, float *out) {
121 *out = baro->tempSensitivity * (int32_t)(((uint32_t)bytes[0] << 16) | ((uint32_t)bytes[1] << 8) | bytes[0]);
122}
123
124/* =============================================================================== */
132void BMP581_readRawTemp(BMP581 *baro, uint8_t *out) {
133 out[0] = BMP581_readRegister(baro, BMP581_TEMPERATURE_MSB); // temp high
134 out[1] = BMP581_readRegister(baro, BMP581_TEMPERATURE_LSB); // temp low
135 out[2] = BMP581_readRegister(baro, BMP581_TEMPERATURE_XLSB); // temp mid
136}
137
138/* =============================================================================== */
146void BMP581_readPress(BMP581 *baro, float *out) {
147 uint8_t bytes[BMP581_DATA_TOTAL];
148 baro->readRawPress(baro, bytes);
149 baro->processRawPress(baro, bytes, out);
150}
151
152/* =============================================================================== */
160void BMP581_processRawPress(BMP581 *baro, uint8_t *bytes, float *out) {
161 *out = baro->pressSensitivity * (int32_t)(((uint32_t)bytes[0] << 16) | ((uint32_t)bytes[1] << 8) | bytes[0]);
162}
163
164/* =============================================================================== */
172void BMP581_readRawPress(BMP581 *baro, uint8_t *out) {
173 uint8_t tmp[BMP581_DATA_SIZE];
174 BMP581_readRegisters(baro, BMP581_PRESSURE_XLSB, BMP581_DATA_SIZE, tmp);
175 out[0] = tmp[2]; // temp high
176 out[1] = tmp[1]; // temp low
177 out[2] = tmp[0]; // temp mid
178}
179
180/******************************** INTERFACE METHODS ********************************/
181
182void BMP581_writeRegister(BMP581 *baro, uint8_t address, uint8_t data) {
183 SPI spi = baro->base;
184
185 spi.port->ODR &= ~spi.cs;
186
187 // Send read command and address
188 uint8_t payload = address & 0x7F; // Load payload with address and read command
189 spi.transmit(&spi, payload); // Transmit payload
190 spi.transmit(&spi, data); // Transmit dummy data and read response data
191
192 spi.port->ODR |= spi.cs;
193}
194
195uint8_t BMP581_readRegister(BMP581 *baro, uint8_t address) {
196 uint8_t response = 0;
197 SPI spi = baro->base;
198
199 spi.port->ODR &= ~spi.cs;
200
201 // Send read command and address
202 uint8_t payload = address | 0x80; // Load payload with address and read command
203 response = spi.transmit(&spi, payload); // Transmit payload
204 response = spi.transmit(&spi, 0xFF); // Transmit dummy data and read response data
205
206 spi.port->ODR |= spi.cs;
207
208 return response;
209}
210
211void BMP581_readRegisters(BMP581 *baro, uint8_t address, uint8_t count, uint8_t *out) {
212 SPI spi = baro->base;
213
214 spi.port->ODR &= ~spi.cs;
215
216 // Send read command and address
217 uint8_t payload = address | 0x80; // Load payload with address and read command
218 spi.transmit(&spi, payload); // Transmit payload
219
220 // Auto increment read through registers
221 for (uint8_t i = 0; i < count; i++) {
222 out[i] = spi.transmit(&spi, 0xFF);
223 }
224
225 spi.port->ODR |= spi.cs;
226}
void BMP581_readRawPress(BMP581 *, uint8_t *)
Definition bmp581.c:172
void BMP581_readTemp(BMP581 *, float *)
Read the temperature from the BMP581 sensor.
Definition bmp581.c:105
void BMP581_processRawTemp(BMP581 *, uint8_t *, float *)
Processes raw temperature data from BMP581 sensor.
Definition bmp581.c:120
void BMP581_readRawTemp(BMP581 *, uint8_t *)
Definition bmp581.c:132
void BMP581_processRawPress(BMP581 *, uint8_t *, float *)
Definition bmp581.c:160
void BMP581_update(BMP581 *)
Updates the BMP581 barometer readings.
Definition bmp581.c:89
void BMP581_readPress(BMP581 *, float *)
Definition bmp581.c:146
DeviceHandle_t BMP581_init(BMP581 *baro, char name[DEVICE_NAME_LENGTH], GPIO_TypeDef *port, unsigned long cs, float tempSensitivity, float pressSensitivity)
Initialiser for a BMP581 barometer.
Definition bmp581.c:27
void SPI_init(SPI *, DeviceType, SPI_TypeDef *, DataFormat, GPIO_TypeDef *, unsigned long)
Initialiser for an SPI device interface.
Definition spi.c:32
@ SENSOR_BARO
Barometer.
Definition spi.h:31
Struct definition for SPI interface. Provides the interface for API consumers to interact with the SP...
Definition spi.h:49
uint16_t(* transmit)(struct SPI *, uint16_t)
SPI transmit method.
Definition spi.h:56
GPIO_TypeDef * port
Pointer to GPIO port struct.
Definition spi.h:52
unsigned long cs
Device chip select address.
Definition spi.h:53