Skip to content

Commit 7be7877

Browse files
committed
bmp581: stream: Add FIFO Watermark support
Configurable through dts property: fifo-watermark. Signed-off-by: Luis Ubieda <luisf@croxel.com>
1 parent ddb5a0d commit 7be7877

File tree

6 files changed

+294
-71
lines changed

6 files changed

+294
-71
lines changed

drivers/sensor/bosch/bmp581/bmp581.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -702,7 +702,18 @@ static DEVICE_API(sensor, bmp581_driver_api) = {
702702

703703
#define BMP581_INIT(i) \
704704
\
705-
RTIO_DEFINE(bmp581_rtio_ctx_##i, 8, 8); \
705+
BUILD_ASSERT(!IS_ENABLED(CONFIG_BMP581_STREAM) || \
706+
DT_INST_NODE_HAS_PROP(i, fifo_watermark), \
707+
"Streaming requires fifo-watermark property. Please set it in the" \
708+
"device-tree node properties"); \
709+
BUILD_ASSERT(COND_CODE_1(DT_INST_NODE_HAS_PROP(i, fifo_watermark), \
710+
((DT_INST_PROP(i, fifo_watermark) > 0) && \
711+
(DT_INST_PROP(i, fifo_watermark) < 16)), \
712+
(true)), \
713+
"fifo-watermark must be between 1 and 15. Please set it in " \
714+
"the device-tree node properties"); \
715+
\
716+
RTIO_DEFINE(bmp581_rtio_ctx_##i, 16, 16); \
706717
I2C_DT_IODEV_DEFINE(bmp581_bus_##i, DT_DRV_INST(i)); \
707718
\
708719
static struct bmp581_data bmp581_data_##i = { \
@@ -715,6 +726,9 @@ static DEVICE_API(sensor, bmp581_driver_api) = {
715726
.iir_p = DT_INST_PROP(i, press_iir), \
716727
.power_mode = DT_INST_PROP(i, power_mode), \
717728
}, \
729+
.stream = { \
730+
.fifo_thres = DT_INST_PROP_OR(i, fifo_watermark, 0), \
731+
}, \
718732
}; \
719733
\
720734
static const struct bmp581_config bmp581_config_##i = { \

drivers/sensor/bosch/bmp581/bmp581.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,11 @@
120120
#define BMP5_FIFO_MAX_THRESHOLD_P_T_MODE 0x0F
121121
#define BMP5_FIFO_MAX_THRESHOLD_P_MODE 0x1F
122122

123+
#define BMP5_FIFO_FRAME_SEL_OFF 0
124+
#define BMP5_FIFO_FRAME_SEL_TEMP 1
125+
#define BMP5_FIFO_FRAME_SEL_PRESS 2
126+
#define BMP5_FIFO_FRAME_SEL_ALL 3
127+
123128
/* Macro is used to bypass both iir_t and iir_p together */
124129
#define BMP5_IIR_BYPASS 0xC0
125130

@@ -239,9 +244,12 @@
239244
#define BMP5_FIFO_DEC_SEL_MSK 0x1C
240245
#define BMP5_FIFO_DEC_SEL_POS 2
241246

242-
#define BMP5_FIFO_COUNT_MSK 0x3F
247+
/* This driver only supports both Pressure and Temperature FIFO mode. */
248+
#define BMP5_FIFO_COUNT_MSK BMP5_FIFO_MAX_THRESHOLD_P_T_MODE
249+
#define BMP5_FIFO_COUNT_POS 0
243250

244251
#define BMP5_FIFO_FRAME_SEL_MSK 0x03
252+
#define BMP5_FIFO_FRAME_SEL_POS 0
245253

246254
/* Out-of-range configuration */
247255
#define BMP5_OOR_THR_P_LSB_MSK 0x0000FF
@@ -316,10 +324,18 @@ struct bmp581_sample {
316324
struct sensor_value temperature;
317325
};
318326

327+
/** Aligned with register bitmask to easily match on data-readout */
328+
enum bmp581_event {
329+
BMP581_EVENT_DRDY = BIT(0),
330+
BMP581_EVENT_FIFO_WM = BIT(2),
331+
};
332+
319333
struct bmp581_stream {
320334
const struct device *dev;
321335
struct gpio_callback cb;
322336
struct rtio_iodev_sqe *iodev_sqe;
337+
enum bmp581_event enabled_mask;
338+
uint8_t fifo_thres;
323339
atomic_t state;
324340
};
325341

drivers/sensor/bosch/bmp581/bmp581_decoder.c

Lines changed: 75 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ int bmp581_encode(const struct device *dev,
4949

5050
if (trigger_status) {
5151
edata->header.channels |= bmp581_encode_channel(SENSOR_CHAN_ALL);
52+
edata->header.fifo_count = data->stream.fifo_thres;
5253
} else {
5354
const struct sensor_chan_spec *const channels = read_config->channels;
5455
size_t num_channels = read_config->count;
@@ -63,7 +64,7 @@ int bmp581_encode(const struct device *dev,
6364
return err;
6465
}
6566

66-
edata->header.events = trigger_status ? BIT(0) : 0;
67+
edata->header.events = trigger_status;
6768
edata->header.timestamp = sensor_clock_cycles_to_ns(cycles);
6869

6970
return 0;
@@ -86,7 +87,11 @@ static int bmp581_decoder_get_frame_count(const uint8_t *buffer,
8687
return -ENODATA;
8788
}
8889

89-
*frame_count = 1;
90+
if (edata->header.events & BMP581_EVENT_FIFO_WM) {
91+
*frame_count = edata->header.fifo_count;
92+
} else {
93+
*frame_count = 1;
94+
}
9095
return 0;
9196
}
9297

@@ -105,53 +110,40 @@ static int bmp581_decoder_get_size_info(struct sensor_chan_spec chan_spec,
105110
}
106111
}
107112

108-
static int bmp581_decoder_decode(const uint8_t *buffer,
109-
struct sensor_chan_spec chan_spec,
110-
uint32_t *fit,
111-
uint16_t max_count,
112-
void *data_out)
113+
static int bmp581_convert_raw_to_q31_value(const struct bmp581_encoded_header *header,
114+
struct sensor_chan_spec *chan_spec,
115+
const struct bmp581_frame *frame,
116+
uint32_t *fit,
117+
struct sensor_q31_data *out)
113118
{
114-
const struct bmp581_encoded_data *edata = (const struct bmp581_encoded_data *)buffer;
115-
uint8_t channel_request;
116-
117-
if (*fit != 0) {
118-
return 0;
119-
}
120-
121-
if (max_count == 0 || chan_spec.chan_idx != 0) {
122-
return -EINVAL;
123-
}
124-
125-
channel_request = bmp581_encode_channel(chan_spec.chan_type);
126-
if ((channel_request & edata->header.channels) != channel_request) {
119+
if (((header->events & BMP581_EVENT_FIFO_WM) != 0) && (*fit >= header->fifo_count)) {
120+
return -ENODATA;
121+
} else if (((header->events & BMP581_EVENT_FIFO_WM) == 0) && (*fit != 0)) {
127122
return -ENODATA;
123+
} else {
124+
/* Empty for completeness */
128125
}
129126

130-
struct sensor_q31_data *out = data_out;
131-
132-
out->header.base_timestamp_ns = edata->header.timestamp;
133-
out->header.reading_count = 1;
134-
135-
switch (chan_spec.chan_type) {
127+
switch (chan_spec->chan_type) {
136128
case SENSOR_CHAN_AMBIENT_TEMP: {
137129
/* Temperature is in data[2:0], data[2] is integer part */
138-
uint32_t raw_temp = ((uint32_t)edata->payload[2] << 16) |
139-
((uint16_t)edata->payload[1] << 8) |
140-
edata->payload[0];
130+
uint32_t raw_temp = ((uint32_t)frame[*fit].payload[2] << 16) |
131+
((uint16_t)frame[*fit].payload[1] << 8) |
132+
frame[*fit].payload[0];
141133
int32_t raw_temp_signed = sign_extend(raw_temp, 23);
142134

143135
out->shift = (31 - 16); /* 16 left shifts gives us the value in celsius */
144-
out->readings[0].value = raw_temp_signed;
136+
out->readings[*fit].value = raw_temp_signed;
145137
break;
146138
}
147-
case SENSOR_CHAN_PRESS:
148-
if (!edata->header.press_en) {
139+
case SENSOR_CHAN_PRESS: {
140+
if (!header->press_en) {
149141
return -ENODATA;
150142
}
151143
/* Shift by 10 bits because we'll divide by 1000 to make it kPa */
152-
uint64_t raw_press = (((uint32_t)edata->payload[5] << 16) |
153-
((uint16_t)edata->payload[4] << 8) |
154-
edata->payload[3]);
144+
uint64_t raw_press = (((uint32_t)frame[*fit].payload[5] << 16) |
145+
((uint16_t)frame[*fit].payload[4] << 8) |
146+
frame[*fit].payload[3]);
155147

156148
int64_t raw_press_signed = sign_extend_64(raw_press, 23);
157149

@@ -163,21 +155,65 @@ static int bmp581_decoder_decode(const uint8_t *buffer,
163155
* converting to kPa. Hence, left-shift 16 spaces.
164156
*/
165157
out->shift = (31 - 6 - 10);
166-
out->readings[0].value = (int32_t)raw_press_signed;
158+
out->readings[*fit].value = (int32_t)raw_press_signed;
167159
break;
160+
}
168161
default:
169162
return -EINVAL;
170163
}
171164

172-
*fit = 1;
173-
return 1;
165+
*fit = (*fit) + 1;
166+
return 0;
167+
}
168+
169+
static int bmp581_decoder_decode(const uint8_t *buffer,
170+
struct sensor_chan_spec chan_spec,
171+
uint32_t *fit,
172+
uint16_t max_count,
173+
void *data_out)
174+
{
175+
const struct bmp581_encoded_data *edata = (const struct bmp581_encoded_data *)buffer;
176+
uint8_t channel_request;
177+
178+
if (max_count == 0 || chan_spec.chan_idx != 0) {
179+
return -EINVAL;
180+
}
181+
182+
channel_request = bmp581_encode_channel(chan_spec.chan_type);
183+
if ((channel_request & edata->header.channels) != channel_request) {
184+
return -ENODATA;
185+
}
186+
187+
struct sensor_q31_data *out = data_out;
188+
189+
out->header.base_timestamp_ns = edata->header.timestamp;
190+
out->header.reading_count = 1;
191+
192+
int err;
193+
uint32_t fit_0 = *fit;
194+
195+
do {
196+
err = bmp581_convert_raw_to_q31_value(&edata->header, &chan_spec,
197+
edata->frame, fit, out);
198+
} while ((err == 0) && (*fit < max_count));
199+
200+
if (*fit == fit_0 || err != 0) {
201+
return err;
202+
}
203+
204+
out->header.reading_count = *fit;
205+
return *fit - fit_0;
174206
}
175207

176208
static bool bmp581_decoder_has_trigger(const uint8_t *buffer, enum sensor_trigger_type trigger)
177209
{
178210
const struct bmp581_encoded_data *edata = (const struct bmp581_encoded_data *)buffer;
179211

180-
if ((trigger == SENSOR_TRIG_DATA_READY) && (edata->header.events != 0)) {
212+
if (((trigger == SENSOR_TRIG_DATA_READY) &&
213+
(edata->header.events & BMP581_EVENT_DRDY)) ||
214+
((trigger == SENSOR_TRIG_FIFO_WATERMARK) &&
215+
(edata->header.events & BMP581_EVENT_FIFO_WM))) {
216+
return true;
181217
return true;
182218
}
183219

drivers/sensor/bosch/bmp581/bmp581_decoder.h

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,50 @@
1212
#include <zephyr/drivers/sensor.h>
1313
#include "bmp581.h"
1414

15-
struct bmp581_encoded_data {
16-
struct {
15+
struct bmp581_encoded_header {
1716
uint8_t channels;
1817
uint8_t events;
1918
uint64_t timestamp;
2019
uint8_t press_en;
21-
} header;
22-
uint8_t payload[6]; /* 3 bytes temp + 3 bytes press */
20+
uint8_t fifo_count;
21+
};
22+
23+
struct bmp581_frame {
24+
uint8_t payload[6];
2325
};
2426

27+
struct bmp581_encoded_data {
28+
struct bmp581_encoded_header header;
29+
union {
30+
uint8_t payload[6]; /* 3 bytes temp + 3 bytes press */
31+
struct bmp581_frame frame[0]; /* Used for FIFO frames */
32+
};
33+
};
34+
35+
static inline enum bmp581_event bmp581_encode_events_bitmask(
36+
const struct sensor_stream_trigger *const triggers,
37+
size_t count)
38+
{
39+
enum bmp581_event result = 0;
40+
41+
for (size_t i = 0 ; i < count ; i++) {
42+
switch (triggers[i].trigger) {
43+
case SENSOR_TRIG_DATA_READY:
44+
result |= ((triggers[i].opt == SENSOR_STREAM_DATA_INCLUDE) ?
45+
BMP581_EVENT_DRDY : 0);
46+
break;
47+
case SENSOR_TRIG_FIFO_WATERMARK:
48+
result |= ((triggers[i].opt == SENSOR_STREAM_DATA_INCLUDE) ?
49+
BMP581_EVENT_FIFO_WM : 0);
50+
break;
51+
default:
52+
break;
53+
}
54+
}
55+
56+
return result;
57+
}
58+
2559
int bmp581_encode(const struct device *dev,
2660
const struct sensor_read_config *read_config,
2761
uint8_t trigger_status,

0 commit comments

Comments
 (0)