1 /*
2  * Copyright (c) 2024 Intel Corporation
3  * Copyright (c) 2024 Croxel Inc.
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include <zephyr/rtio/work.h>
9 #include <zephyr/logging/log.h>
10 #include <zephyr/drivers/sensor_clock.h>
11 
12 #include "bme280.h"
13 
14 LOG_MODULE_DECLARE(BME280, CONFIG_SENSOR_LOG_LEVEL);
15 
bme280_submit_sync(struct rtio_iodev_sqe * iodev_sqe)16 void bme280_submit_sync(struct rtio_iodev_sqe *iodev_sqe)
17 {
18 	uint32_t min_buf_len = sizeof(struct bme280_encoded_data);
19 	int rc;
20 	uint64_t cycles;
21 	uint8_t *buf;
22 	uint32_t buf_len;
23 
24 	const struct sensor_read_config *cfg = iodev_sqe->sqe.iodev->data;
25 	const struct device *dev = cfg->sensor;
26 	const struct sensor_chan_spec *const channels = cfg->channels;
27 	const size_t num_channels = cfg->count;
28 
29 	rc = rtio_sqe_rx_buf(iodev_sqe, min_buf_len, min_buf_len, &buf, &buf_len);
30 	if (rc != 0) {
31 		LOG_ERR("Failed to get a read buffer of size %u bytes", min_buf_len);
32 		rtio_iodev_sqe_err(iodev_sqe, rc);
33 		return;
34 	}
35 
36 	rc = sensor_clock_get_cycles(&cycles);
37 	if (rc != 0) {
38 		LOG_ERR("Failed to get sensor clock cycles");
39 		rtio_iodev_sqe_err(iodev_sqe, rc);
40 		return;
41 	}
42 
43 	struct bme280_encoded_data *edata;
44 
45 	edata = (struct bme280_encoded_data *)buf;
46 	edata->header.timestamp = sensor_clock_cycles_to_ns(cycles);
47 	edata->has_temp = 0;
48 	edata->has_humidity = 0;
49 	edata->has_press = 0;
50 
51 	/* Check if the requested channels are supported */
52 	for (size_t i = 0; i < num_channels; i++) {
53 		switch (channels[i].chan_type) {
54 		case SENSOR_CHAN_AMBIENT_TEMP:
55 			edata->has_temp = 1;
56 			break;
57 		case SENSOR_CHAN_HUMIDITY:
58 			edata->has_humidity = 1;
59 			break;
60 		case SENSOR_CHAN_PRESS:
61 			edata->has_press = 1;
62 			break;
63 		case SENSOR_CHAN_ALL:
64 			edata->has_temp = 1;
65 			edata->has_humidity = 1;
66 			edata->has_press = 1;
67 			break;
68 		default:
69 			continue;
70 			break;
71 		}
72 	}
73 
74 	rc = bme280_sample_fetch_helper(dev, SENSOR_CHAN_ALL, &edata->reading);
75 	if (rc != 0) {
76 		LOG_ERR("Failed to fetch samples");
77 		rtio_iodev_sqe_err(iodev_sqe, rc);
78 		return;
79 	}
80 
81 	rtio_iodev_sqe_ok(iodev_sqe, 0);
82 }
83 
bme280_submit(const struct device * dev,struct rtio_iodev_sqe * iodev_sqe)84 void bme280_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe)
85 {
86 	struct rtio_work_req *req = rtio_work_req_alloc();
87 
88 	if (req == NULL) {
89 		LOG_ERR("RTIO work item allocation failed. Consider to increase "
90 			"CONFIG_RTIO_WORKQ_POOL_ITEMS.");
91 		rtio_iodev_sqe_err(iodev_sqe, -ENOMEM);
92 		return;
93 	}
94 
95 	rtio_work_req_submit(req, iodev_sqe, bme280_submit_sync);
96 }
97