1 /*
2  * Copyright (c) 2024 Intel Corporation
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 
6 #include "bme280.h"
7 #include <math.h>
8 
bme280_decoder_get_frame_count(const uint8_t * buffer,struct sensor_chan_spec chan_spec,uint16_t * frame_count)9 static int bme280_decoder_get_frame_count(const uint8_t *buffer, struct sensor_chan_spec chan_spec,
10 					  uint16_t *frame_count)
11 {
12 	const struct bme280_encoded_data *edata = (const struct bme280_encoded_data *)buffer;
13 	int32_t ret = -ENOTSUP;
14 
15 	if (chan_spec.chan_idx != 0) {
16 		return ret;
17 	}
18 
19 	/* This sensor lacks a FIFO; there will always only be one frame at a time. */
20 	switch (chan_spec.chan_type) {
21 	case SENSOR_CHAN_AMBIENT_TEMP:
22 		*frame_count = edata->has_temp ? 1 : 0;
23 		break;
24 	case SENSOR_CHAN_PRESS:
25 		*frame_count = edata->has_press ? 1 : 0;
26 		break;
27 	case SENSOR_CHAN_HUMIDITY:
28 		*frame_count = edata->has_humidity ? 1 : 0;
29 		break;
30 	default:
31 		return ret;
32 	}
33 
34 	if (*frame_count > 0) {
35 		ret = 0;
36 	}
37 
38 	return ret;
39 }
40 
bme280_decoder_get_size_info(struct sensor_chan_spec chan_spec,size_t * base_size,size_t * frame_size)41 static int bme280_decoder_get_size_info(struct sensor_chan_spec chan_spec, size_t *base_size,
42 					size_t *frame_size)
43 {
44 	switch (chan_spec.chan_type) {
45 	case SENSOR_CHAN_AMBIENT_TEMP:
46 	case SENSOR_CHAN_HUMIDITY:
47 	case SENSOR_CHAN_PRESS:
48 		*base_size = sizeof(struct sensor_q31_sample_data);
49 		*frame_size = sizeof(struct sensor_q31_sample_data);
50 		return 0;
51 	default:
52 		return -ENOTSUP;
53 	}
54 }
55 
bme280_decoder_decode(const uint8_t * buffer,struct sensor_chan_spec chan_spec,uint32_t * fit,uint16_t max_count,void * data_out)56 static int bme280_decoder_decode(const uint8_t *buffer, struct sensor_chan_spec chan_spec,
57 				 uint32_t *fit, uint16_t max_count, void *data_out)
58 {
59 	const struct bme280_encoded_data *edata = (const struct bme280_encoded_data *)buffer;
60 
61 	if (*fit != 0) {
62 		return 0;
63 	}
64 
65 	struct sensor_q31_data *out = data_out;
66 
67 	out->header.base_timestamp_ns = edata->header.timestamp;
68 	out->header.reading_count = 1;
69 
70 	switch (chan_spec.chan_type) {
71 	case SENSOR_CHAN_AMBIENT_TEMP:
72 		if (edata->has_temp) {
73 			int32_t readq = edata->reading.comp_temp * pow(2, 31 - BME280_TEMP_SHIFT);
74 			int32_t convq = BME280_TEMP_CONV * pow(2, 31 - BME280_TEMP_SHIFT);
75 
76 			out->readings[0].temperature =
77 				(int32_t)((((int64_t)readq) << (31 - BME280_TEMP_SHIFT)) /
78 					  ((int64_t)convq));
79 			out->shift = BME280_TEMP_SHIFT;
80 		} else {
81 			return -ENODATA;
82 		}
83 		break;
84 	case SENSOR_CHAN_PRESS:
85 		if (edata->has_press) {
86 			int32_t readq = edata->reading.comp_press;
87 			int32_t convq = BME280_PRESS_CONV_KPA * pow(2, 31 - BME280_PRESS_SHIFT);
88 
89 			out->readings[0].pressure =
90 				(int32_t)((((int64_t)readq) << (31 - BME280_PRESS_SHIFT)) /
91 					  ((int64_t)convq));
92 			out->shift = BME280_PRESS_SHIFT;
93 		} else {
94 			return -ENODATA;
95 		}
96 		break;
97 	case SENSOR_CHAN_HUMIDITY:
98 		if (edata->has_humidity) {
99 			out->readings[0].humidity = edata->reading.comp_humidity;
100 			out->shift = BME280_HUM_SHIFT;
101 		} else {
102 			return -ENODATA;
103 		}
104 		break;
105 	default:
106 		return -EINVAL;
107 	}
108 
109 	*fit = 1;
110 
111 	return 1;
112 }
113 
114 SENSOR_DECODER_API_DT_DEFINE() = {
115 	.get_frame_count = bme280_decoder_get_frame_count,
116 	.get_size_info = bme280_decoder_get_size_info,
117 	.decode = bme280_decoder_decode,
118 };
119 
bme280_get_decoder(const struct device * dev,const struct sensor_decoder_api ** decoder)120 int bme280_get_decoder(const struct device *dev, const struct sensor_decoder_api **decoder)
121 {
122 	ARG_UNUSED(dev);
123 	*decoder = &SENSOR_DECODER_NAME();
124 
125 	return 0;
126 }
127