1 /*
2 * Copyright (c) 2023 Google LLC.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <errno.h>
8
9 #include <zephyr/drivers/sensor.h>
10 #include <zephyr/dsp/types.h>
11 #include <zephyr/logging/log.h>
12
13 LOG_MODULE_REGISTER(sensor_compat, CONFIG_SENSOR_LOG_LEVEL);
14
15 static void sensor_submit_fallback(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe);
16
sensor_iodev_submit(struct rtio_iodev_sqe * iodev_sqe)17 static void sensor_iodev_submit(struct rtio_iodev_sqe *iodev_sqe)
18 {
19 const struct sensor_read_config *cfg = iodev_sqe->sqe.iodev->data;
20 const struct device *dev = cfg->sensor;
21 const struct sensor_driver_api *api = dev->api;
22
23 if (api->submit != NULL) {
24 api->submit(dev, iodev_sqe);
25 } else {
26 sensor_submit_fallback(dev, iodev_sqe);
27 }
28 }
29
30 const struct rtio_iodev_api __sensor_iodev_api = {
31 .submit = sensor_iodev_submit,
32 };
33
34 /**
35 * @brief Compute the number of samples needed for the given channels
36 *
37 * @param[in] channels Array of channels requested
38 * @param[in] num_channels Number of channels on the @p channels array
39 * @return The number of samples required to read the given channels
40 */
compute_num_samples(const enum sensor_channel * channels,size_t num_channels)41 static inline int compute_num_samples(const enum sensor_channel *channels, size_t num_channels)
42 {
43 int num_samples = 0;
44
45 for (size_t i = 0; i < num_channels; ++i) {
46 num_samples += SENSOR_CHANNEL_3_AXIS(channels[i]) ? 3 : 1;
47 }
48
49 return num_samples;
50 }
51
52 /**
53 * @brief Compute the minimum number of bytes needed
54 *
55 * @param[in] num_output_samples The number of samples to represent
56 * @return The number of bytes needed for this sample frame
57 */
compute_min_buf_len(int num_output_samples)58 static inline uint32_t compute_min_buf_len(int num_output_samples)
59 {
60 return sizeof(struct sensor_data_generic_header) + (num_output_samples * sizeof(q31_t)) +
61 (num_output_samples * sizeof(enum sensor_channel));
62 }
63
64 /**
65 * @brief Checks if the header already contains a given channel
66 *
67 * @param[in] header The header to scan
68 * @param[in] channel The channel to search for
69 * @param[in] num_channels The number of valid channels in the header so far
70 * @return Index of the @p channel if found or negative if not found
71 */
check_header_contains_channel(const struct sensor_data_generic_header * header,enum sensor_channel channel,int num_channels)72 static inline int check_header_contains_channel(const struct sensor_data_generic_header *header,
73 enum sensor_channel channel, int num_channels)
74 {
75 __ASSERT_NO_MSG(!SENSOR_CHANNEL_3_AXIS(channel));
76
77 for (int i = 0; i < num_channels; ++i) {
78 if (header->channels[i] == channel) {
79 return i;
80 }
81 }
82 return -1;
83 }
84
85 /**
86 * @brief Fallback function for retrofiting old drivers to rtio
87 *
88 * @param[in] dev The sensor device to read
89 * @param[in] iodev_sqe The read submission queue event
90 */
sensor_submit_fallback(const struct device * dev,struct rtio_iodev_sqe * iodev_sqe)91 static void sensor_submit_fallback(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe)
92 {
93 const struct sensor_read_config *cfg = iodev_sqe->sqe.iodev->data;
94 const enum sensor_channel *const channels = cfg->channels;
95 const int num_output_samples = compute_num_samples(channels, cfg->count);
96 uint32_t min_buf_len = compute_min_buf_len(num_output_samples);
97 uint64_t timestamp_ns = k_ticks_to_ns_floor64(k_uptime_ticks());
98 int rc = sensor_sample_fetch(dev);
99 uint8_t *buf;
100 uint32_t buf_len;
101
102 /* Check that the fetch succeeded */
103 if (rc != 0) {
104 LOG_WRN("Failed to fetch samples");
105 rtio_iodev_sqe_err(iodev_sqe, rc);
106 return;
107 }
108
109 /* Get the buffer for the frame, it may be allocated dynamically by the rtio context */
110 rc = rtio_sqe_rx_buf(iodev_sqe, min_buf_len, min_buf_len, &buf, &buf_len);
111 if (rc != 0) {
112 LOG_WRN("Failed to get a read buffer of size %u bytes", min_buf_len);
113 rtio_iodev_sqe_err(iodev_sqe, rc);
114 return;
115 }
116
117 /* Set the timestamp and num_channels */
118 struct sensor_data_generic_header *header = (struct sensor_data_generic_header *)buf;
119
120 header->timestamp_ns = timestamp_ns;
121 header->num_channels = num_output_samples;
122 header->shift = 0;
123
124 q31_t *q = (q31_t *)(buf + sizeof(struct sensor_data_generic_header) +
125 num_output_samples * sizeof(enum sensor_channel));
126
127 /* Populate values, update shift, and set channels */
128 for (size_t i = 0, sample_idx = 0; i < cfg->count; ++i) {
129 struct sensor_value value[3];
130 const int num_samples = SENSOR_CHANNEL_3_AXIS(channels[i]) ? 3 : 1;
131
132 /* Get the current channel requested by the user */
133 rc = sensor_channel_get(dev, channels[i], value);
134
135 if (num_samples == 3) {
136 header->channels[sample_idx++] =
137 rc == 0 ? channels[i] - 3 : SENSOR_CHAN_MAX;
138 header->channels[sample_idx++] =
139 rc == 0 ? channels[i] - 2 : SENSOR_CHAN_MAX;
140 header->channels[sample_idx++] =
141 rc == 0 ? channels[i] - 1 : SENSOR_CHAN_MAX;
142 } else {
143 header->channels[sample_idx++] = rc == 0 ? channels[i] : SENSOR_CHAN_MAX;
144 }
145
146 if (rc != 0) {
147 LOG_DBG("Failed to get channel %d, skipping", channels[i]);
148 continue;
149 }
150
151 /* Get the largest absolute value reading to set the scale for the channel */
152 uint32_t header_scale = 0;
153
154 for (int sample = 0; sample < num_samples; ++sample) {
155 /*
156 * The scale is the ceil(abs(sample)).
157 * Since we are using fractional values, it's easier to assume that .val2
158 * is non 0 and convert this to abs(sample.val1) + 1 (removing a branch).
159 * Since it's possible that val1 (int32_t) is saturated (INT32_MAX) we need
160 * to upcast it to 64 bit int first, then take the abs() of that 64 bit
161 * int before we '+ 1'. Once that's done, we can safely cast back down
162 * to uint32_t because the min value is 0 and max is INT32_MAX + 1 which
163 * is less than UINT32_MAX.
164 */
165 uint32_t scale = (uint32_t)llabs((int64_t)value[sample].val1) + 1;
166
167 header_scale = MAX(header_scale, scale);
168 }
169
170 int8_t new_shift = ilog2(header_scale - 1) + 1;
171
172 /* Reset sample_idx */
173 sample_idx -= num_samples;
174 if (header->shift < new_shift) {
175 /*
176 * Shift was updated, need to convert all the existing q values. This could
177 * be optimized by calling zdsp_scale_q31() but that would force a
178 * dependency between sensors and the zDSP subsystem.
179 */
180 for (int q_idx = 0; q_idx < sample_idx; ++q_idx) {
181 q[q_idx] = q[q_idx] >> (new_shift - header->shift);
182 }
183 header->shift = new_shift;
184 }
185
186 /*
187 * Spread the q31 values. This is needed because some channels are 3D. If
188 * the user specified one of those then num_samples will be 3; and we need to
189 * produce 3 separate readings.
190 */
191 for (int sample = 0; sample < num_samples; ++sample) {
192 /* Check if the channel is already in the buffer */
193 int prev_computed_value_idx = check_header_contains_channel(
194 header, header->channels[sample_idx + sample], sample_idx + sample);
195
196 if (prev_computed_value_idx >= 0 &&
197 prev_computed_value_idx != sample_idx + sample) {
198 LOG_DBG("value[%d] previously computed at q[%d]@%p", sample,
199 prev_computed_value_idx,
200 (void *)&q[prev_computed_value_idx]);
201 q[sample_idx + sample] = q[prev_computed_value_idx];
202 continue;
203 }
204
205 /* Convert the value to micro-units */
206 int64_t value_u = sensor_value_to_micro(&value[sample]);
207
208 /* Convert to q31 using the shift */
209 q[sample_idx + sample] =
210 ((value_u * ((INT64_C(1) << 31) - 1)) / 1000000) >> header->shift;
211
212 LOG_DBG("value[%d]=%s%d.%06d, q[%d]@%p=%d", sample, value_u < 0 ? "-" : "",
213 abs((int)value[sample].val1), abs((int)value[sample].val2),
214 (int)(sample_idx + sample), (void *)&q[sample_idx + sample],
215 q[sample_idx + sample]);
216 }
217 sample_idx += num_samples;
218 }
219 LOG_DBG("Total channels in header: %zu", header->num_channels);
220 rtio_iodev_sqe_ok(iodev_sqe, 0);
221 }
222
sensor_processing_with_callback(struct rtio * ctx,sensor_processing_callback_t cb)223 void sensor_processing_with_callback(struct rtio *ctx, sensor_processing_callback_t cb)
224 {
225 void *userdata = NULL;
226 uint8_t *buf = NULL;
227 uint32_t buf_len = 0;
228 int rc;
229
230 /* Wait for a CQE */
231 struct rtio_cqe *cqe = rtio_cqe_consume_block(ctx);
232
233 /* Cache the data from the CQE */
234 rc = cqe->result;
235 userdata = cqe->userdata;
236 rtio_cqe_get_mempool_buffer(ctx, cqe, &buf, &buf_len);
237
238 /* Release the CQE */
239 rtio_cqe_release(ctx, cqe);
240
241 /* Call the callback */
242 cb(rc, buf, buf_len, userdata);
243
244 /* Release the memory */
245 rtio_release_buffer(ctx, buf, buf_len);
246 }
247
248 /**
249 * @brief Default decoder get frame count
250 *
251 * Default reader can only ever service a single frame at a time.
252 *
253 * @param[in] buffer The data buffer to parse
254 * @param[out] frame_count The number of frames in the buffer (always 1)
255 * @return 0 in all cases
256 */
get_frame_count(const uint8_t * buffer,uint16_t * frame_count)257 static int get_frame_count(const uint8_t *buffer, uint16_t *frame_count)
258 {
259 ARG_UNUSED(buffer);
260 *frame_count = 1;
261 return 0;
262 }
263
264 /**
265 * @brief Default decoder get the timestamp of the first frame
266 *
267 * @param[in] buffer The data buffer to parse
268 * @param[out] timestamp_ns The timestamp of the first frame
269 * @return 0 in all cases
270 */
get_timestamp(const uint8_t * buffer,uint64_t * timestamp_ns)271 static int get_timestamp(const uint8_t *buffer, uint64_t *timestamp_ns)
272 {
273 *timestamp_ns = ((struct sensor_data_generic_header *)buffer)->timestamp_ns;
274 return 0;
275 }
276
277 /**
278 * @brief Default decoder get the bitshift of the given channel (if possible)
279 *
280 * @param[in] buffer The data buffer to parse
281 * @param[in] channel_type The channel to query
282 * @param[out] shift The bitshift for the q31 value
283 * @return 0 on success
284 * @return -EINVAL if the @p channel_type couldn't be found
285 */
get_shift(const uint8_t * buffer,enum sensor_channel channel_type,int8_t * shift)286 static int get_shift(const uint8_t *buffer, enum sensor_channel channel_type, int8_t *shift)
287 {
288 struct sensor_data_generic_header *header = (struct sensor_data_generic_header *)buffer;
289
290 ARG_UNUSED(channel_type);
291 *shift = header->shift;
292 return 0;
293 }
294
295 /**
296 * @brief Default decoder decode N samples
297 *
298 * Decode up to N samples starting at the provided @p fit and @p cit. The appropriate channel types
299 * and q31 values will be placed in @p values and @p channels respectively.
300 *
301 * @param[in] buffer The data buffer to decode
302 * @param[in,out] fit The starting frame iterator
303 * @param[in,out] cit The starting channel iterator
304 * @param[out] channels The decoded channel types
305 * @param[out] values The decoded q31 values
306 * @param[in] max_count The maximum number of values to decode
307 * @return > 0 The number of decoded values
308 * @return 0 Nothing else to decode on this @p buffer
309 * @return < 0 Error
310 */
decode(const uint8_t * buffer,sensor_frame_iterator_t * fit,sensor_channel_iterator_t * cit,enum sensor_channel * channels,q31_t * values,uint8_t max_count)311 static int decode(const uint8_t *buffer, sensor_frame_iterator_t *fit,
312 sensor_channel_iterator_t *cit, enum sensor_channel *channels, q31_t *values,
313 uint8_t max_count)
314 {
315 const struct sensor_data_generic_header *header =
316 (const struct sensor_data_generic_header *)buffer;
317 const q31_t *q =
318 (const q31_t *)(buffer + sizeof(struct sensor_data_generic_header) +
319 header->num_channels * sizeof(enum sensor_channel));
320 int count = 0;
321
322 if (*fit != 0 || *cit >= header->num_channels) {
323 return -EINVAL;
324 }
325
326 /* Skip invalid channels */
327 while (*cit < header->num_channels && header->channels[*cit] == SENSOR_CHAN_MAX) {
328 *cit += 1;
329 }
330
331 for (; *cit < header->num_channels && count < max_count; ++count) {
332 channels[count] = header->channels[*cit];
333 values[count] = q[*cit];
334 LOG_DBG("Decoding q[%u]@%p=%d", *cit, (void *)&q[*cit], q[*cit]);
335 *cit += 1;
336 }
337
338 if (*cit >= header->num_channels) {
339 *fit = 1;
340 *cit = 0;
341 }
342 return count;
343 }
344
345 const struct sensor_decoder_api __sensor_default_decoder = {
346 .get_frame_count = get_frame_count,
347 .get_timestamp = get_timestamp,
348 .get_shift = get_shift,
349 .decode = decode,
350 };
351