1 /*
2 * Copyright (c) 2023 Google LLC.
3 * Copyright (c) 2024 Croxel Inc.
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #include <errno.h>
9
10 #include <zephyr/drivers/sensor.h>
11 #include <zephyr/dsp/types.h>
12 #include <zephyr/logging/log.h>
13 #include <zephyr/rtio/work.h>
14
15 LOG_MODULE_REGISTER(sensor_compat, CONFIG_SENSOR_LOG_LEVEL);
16
17 /*
18 * Ensure that the size of the generic header aligns with the sensor channel specifier . If it
19 * doesn't, then cores that require aligned memory access will fail to read channel[0].
20 */
21 BUILD_ASSERT((sizeof(struct sensor_data_generic_header) % sizeof(struct sensor_chan_spec)) == 0);
22
23 static void sensor_submit_fallback(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe);
24
sensor_iodev_submit(struct rtio_iodev_sqe * iodev_sqe)25 static void sensor_iodev_submit(struct rtio_iodev_sqe *iodev_sqe)
26 {
27 const struct sensor_read_config *cfg = iodev_sqe->sqe.iodev->data;
28 const struct device *dev = cfg->sensor;
29 const struct sensor_driver_api *api = dev->api;
30
31 if (api->submit != NULL) {
32 api->submit(dev, iodev_sqe);
33 } else if (!cfg->is_streaming) {
34 sensor_submit_fallback(dev, iodev_sqe);
35 } else {
36 rtio_iodev_sqe_err(iodev_sqe, -ENOTSUP);
37 }
38 }
39
40 const struct rtio_iodev_api __sensor_iodev_api = {
41 .submit = sensor_iodev_submit,
42 };
43
44 /**
45 * @brief Compute the number of samples needed for the given channels
46 *
47 * @param[in] channels Array of channels requested
48 * @param[in] num_channels Number of channels on the @p channels array
49 * @return The number of samples required to read the given channels
50 */
compute_num_samples(const struct sensor_chan_spec * const channels,size_t num_channels)51 static inline int compute_num_samples(const struct sensor_chan_spec *const channels,
52 size_t num_channels)
53 {
54 int num_samples = 0;
55
56 for (size_t i = 0; i < num_channels; ++i) {
57 num_samples += SENSOR_CHANNEL_3_AXIS(channels[i].chan_type) ? 3 : 1;
58 }
59
60 return num_samples;
61 }
62
63 /**
64 * @brief Compute the required header size
65 *
66 * This function takes into account alignment of the q31 values that will follow the header.
67 *
68 * @param[in] num_output_samples The number of samples to represent
69 * @return The number of bytes needed for this sample frame's header
70 */
compute_header_size(int num_output_samples)71 static inline uint32_t compute_header_size(int num_output_samples)
72 {
73 uint32_t size = sizeof(struct sensor_data_generic_header) +
74 (num_output_samples * sizeof(struct sensor_chan_spec));
75 return (size + 3) & ~0x3;
76 }
77
78 /**
79 * @brief Compute the minimum number of bytes needed
80 *
81 * @param[in] num_output_samples The number of samples to represent
82 * @return The number of bytes needed for this sample frame
83 */
compute_min_buf_len(int num_output_samples)84 static inline uint32_t compute_min_buf_len(int num_output_samples)
85 {
86 return compute_header_size(num_output_samples) + (num_output_samples * sizeof(q31_t));
87 }
88
89 /**
90 * @brief Checks if the header already contains a given channel
91 *
92 * @param[in] header The header to scan
93 * @param[in] channel The channel to search for
94 * @param[in] num_channels The number of valid channels in the header so far
95 * @return Index of the @p channel if found or negative if not found
96 */
check_header_contains_channel(const struct sensor_data_generic_header * header,struct sensor_chan_spec chan_spec,int num_channels)97 static inline int check_header_contains_channel(const struct sensor_data_generic_header *header,
98 struct sensor_chan_spec chan_spec, int num_channels)
99 {
100 __ASSERT_NO_MSG(!SENSOR_CHANNEL_3_AXIS(chan_spec.chan_type));
101
102 for (int i = 0; i < num_channels; ++i) {
103 if (sensor_chan_spec_eq(header->channels[i], chan_spec)) {
104 return i;
105 }
106 }
107 return -1;
108 }
109
110 /**
111 * @brief Fallback function for retrofiting old drivers to rtio (sync)
112 *
113 * @param[in] iodev_sqe The read submission queue event
114 */
sensor_submit_fallback_sync(struct rtio_iodev_sqe * iodev_sqe)115 static void sensor_submit_fallback_sync(struct rtio_iodev_sqe *iodev_sqe)
116 {
117 const struct sensor_read_config *cfg = iodev_sqe->sqe.iodev->data;
118 const struct device *dev = cfg->sensor;
119 const struct sensor_chan_spec *const channels = cfg->channels;
120 const int num_output_samples = compute_num_samples(channels, cfg->count);
121 uint32_t min_buf_len = compute_min_buf_len(num_output_samples);
122 uint64_t timestamp_ns = k_ticks_to_ns_floor64(k_uptime_ticks());
123 int rc = sensor_sample_fetch(dev);
124 uint8_t *buf;
125 uint32_t buf_len;
126
127 /* Check that the fetch succeeded */
128 if (rc != 0) {
129 LOG_WRN("Failed to fetch samples");
130 rtio_iodev_sqe_err(iodev_sqe, rc);
131 return;
132 }
133
134 /* Get the buffer for the frame, it may be allocated dynamically by the rtio context */
135 rc = rtio_sqe_rx_buf(iodev_sqe, min_buf_len, min_buf_len, &buf, &buf_len);
136 if (rc != 0) {
137 LOG_WRN("Failed to get a read buffer of size %u bytes", min_buf_len);
138 rtio_iodev_sqe_err(iodev_sqe, rc);
139 return;
140 }
141
142 /* Set the timestamp and num_channels */
143 struct sensor_data_generic_header *header = (struct sensor_data_generic_header *)buf;
144
145 header->timestamp_ns = timestamp_ns;
146 header->num_channels = num_output_samples;
147 header->shift = 0;
148
149 q31_t *q = (q31_t *)(buf + compute_header_size(num_output_samples));
150
151 /* Populate values, update shift, and set channels */
152 for (size_t i = 0, sample_idx = 0; i < cfg->count; ++i) {
153 struct sensor_value value[3];
154 const int num_samples = SENSOR_CHANNEL_3_AXIS(channels[i].chan_type) ? 3 : 1;
155
156 /* Get the current channel requested by the user */
157 rc = sensor_channel_get(dev, channels[i].chan_type, value);
158
159 if (num_samples == 3) {
160 header->channels[sample_idx++] = (struct sensor_chan_spec) {
161 rc == 0 ? channels[i].chan_type - 3 : SENSOR_CHAN_MAX,
162 0
163 };
164 header->channels[sample_idx++] = (struct sensor_chan_spec) {
165 rc == 0 ? channels[i].chan_type - 2 : SENSOR_CHAN_MAX,
166 0
167 };
168 header->channels[sample_idx++] = (struct sensor_chan_spec) {
169 rc == 0 ? channels[i].chan_type - 1 : SENSOR_CHAN_MAX,
170 0
171 };
172 } else {
173 header->channels[sample_idx++] = (struct sensor_chan_spec) {
174 rc == 0 ? channels[i].chan_type : SENSOR_CHAN_MAX,
175 0
176 };
177 }
178
179 if (rc != 0) {
180 LOG_DBG("Failed to get channel (type: %d, index %d), skipping",
181 channels[i].chan_type, channels[i].chan_idx);
182 continue;
183 }
184
185 /* Get the largest absolute value reading to set the scale for the channel */
186 uint32_t header_scale = 0;
187
188 for (int sample = 0; sample < num_samples; ++sample) {
189 /*
190 * The scale is the ceil(abs(sample)).
191 * Since we are using fractional values, it's easier to assume that .val2
192 * is non 0 and convert this to abs(sample.val1) + 1 (removing a branch).
193 * Since it's possible that val1 (int32_t) is saturated (INT32_MAX) we need
194 * to upcast it to 64 bit int first, then take the abs() of that 64 bit
195 * int before we '+ 1'. Once that's done, we can safely cast back down
196 * to uint32_t because the min value is 0 and max is INT32_MAX + 1 which
197 * is less than UINT32_MAX.
198 */
199 uint32_t scale = (uint32_t)llabs((int64_t)value[sample].val1) + 1;
200
201 header_scale = MAX(header_scale, scale);
202 }
203
204 int8_t new_shift = ilog2(header_scale - 1) + 1;
205
206 /* Reset sample_idx */
207 sample_idx -= num_samples;
208 if (header->shift < new_shift) {
209 /*
210 * Shift was updated, need to convert all the existing q values. This could
211 * be optimized by calling zdsp_scale_q31() but that would force a
212 * dependency between sensors and the zDSP subsystem.
213 */
214 for (int q_idx = 0; q_idx < sample_idx; ++q_idx) {
215 q[q_idx] = q[q_idx] >> (new_shift - header->shift);
216 }
217 header->shift = new_shift;
218 }
219
220 /*
221 * Spread the q31 values. This is needed because some channels are 3D. If
222 * the user specified one of those then num_samples will be 3; and we need to
223 * produce 3 separate readings.
224 */
225 for (int sample = 0; sample < num_samples; ++sample) {
226 /* Check if the channel is already in the buffer */
227 int prev_computed_value_idx = check_header_contains_channel(
228 header, header->channels[sample_idx + sample], sample_idx + sample);
229
230 if (prev_computed_value_idx >= 0 &&
231 prev_computed_value_idx != sample_idx + sample) {
232 LOG_DBG("value[%d] previously computed at q[%d]@%p", sample,
233 prev_computed_value_idx,
234 (void *)&q[prev_computed_value_idx]);
235 q[sample_idx + sample] = q[prev_computed_value_idx];
236 continue;
237 }
238
239 /* Convert the value to micro-units */
240 int64_t value_u = sensor_value_to_micro(&value[sample]);
241
242 /* Convert to q31 using the shift */
243 q[sample_idx + sample] =
244 ((value_u * ((INT64_C(1) << 31) - 1)) / 1000000) >> header->shift;
245
246 LOG_DBG("value[%d]=%s%d.%06d, q[%d]@%p=%d, shift: %d",
247 sample, value_u < 0 ? "-" : "",
248 abs((int)value[sample].val1), abs((int)value[sample].val2),
249 (int)(sample_idx + sample), (void *)&q[sample_idx + sample],
250 q[sample_idx + sample], header->shift);
251 }
252 sample_idx += num_samples;
253 }
254 LOG_DBG("Total channels in header: %" PRIu32, header->num_channels);
255 rtio_iodev_sqe_ok(iodev_sqe, 0);
256 }
257
258 /**
259 * @brief Fallback function for retrofiting old drivers to rtio
260 *
261 * @param[in] dev The sensor device to read
262 * @param[in] iodev_sqe The read submission queue event
263 */
sensor_submit_fallback(const struct device * dev,struct rtio_iodev_sqe * iodev_sqe)264 static void sensor_submit_fallback(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe)
265 {
266 struct rtio_work_req *req = rtio_work_req_alloc();
267
268 __ASSERT_NO_MSG(req);
269
270 rtio_work_req_submit(req, iodev_sqe, sensor_submit_fallback_sync);
271 }
272
sensor_processing_with_callback(struct rtio * ctx,sensor_processing_callback_t cb)273 void sensor_processing_with_callback(struct rtio *ctx, sensor_processing_callback_t cb)
274 {
275 void *userdata = NULL;
276 uint8_t *buf = NULL;
277 uint32_t buf_len = 0;
278 int rc;
279
280 /* Wait for a CQE */
281 struct rtio_cqe *cqe = rtio_cqe_consume_block(ctx);
282
283 /* Cache the data from the CQE */
284 rc = cqe->result;
285 userdata = cqe->userdata;
286 rtio_cqe_get_mempool_buffer(ctx, cqe, &buf, &buf_len);
287
288 /* Release the CQE */
289 rtio_cqe_release(ctx, cqe);
290
291 /* Call the callback */
292 cb(rc, buf, buf_len, userdata);
293
294 /* Release the memory */
295 rtio_release_buffer(ctx, buf, buf_len);
296 }
297
298 /**
299 * @brief Default decoder get frame count
300 *
301 * Default reader can only ever service a single frame at a time.
302 *
303 * @param[in] buffer The data buffer to parse
304 * @param[in] channel The channel to get the count for
305 * @param[in] channel_idx The index of the channel
306 * @param[out] frame_count The number of frames in the buffer (always 1)
307 * @return 0 in all cases
308 */
get_frame_count(const uint8_t * buffer,struct sensor_chan_spec channel,uint16_t * frame_count)309 static int get_frame_count(const uint8_t *buffer, struct sensor_chan_spec channel,
310 uint16_t *frame_count)
311 {
312 struct sensor_data_generic_header *header = (struct sensor_data_generic_header *)buffer;
313
314 switch (channel.chan_type) {
315 case SENSOR_CHAN_ACCEL_XYZ:
316 channel.chan_type = SENSOR_CHAN_ACCEL_X;
317 break;
318 case SENSOR_CHAN_GYRO_XYZ:
319 channel.chan_type = SENSOR_CHAN_GYRO_X;
320 break;
321 case SENSOR_CHAN_MAGN_XYZ:
322 channel.chan_type = SENSOR_CHAN_MAGN_X;
323 break;
324 case SENSOR_CHAN_POS_DXYZ:
325 channel.chan_type = SENSOR_CHAN_POS_DX;
326 break;
327 default:
328 break;
329 }
330 for (size_t i = 0; i < header->num_channels; ++i) {
331 if (sensor_chan_spec_eq(header->channels[i], channel)) {
332 *frame_count = 1;
333 return 0;
334 }
335 }
336
337 return -ENOTSUP;
338 }
339
sensor_natively_supported_channel_size_info(struct sensor_chan_spec channel,size_t * base_size,size_t * frame_size)340 int sensor_natively_supported_channel_size_info(struct sensor_chan_spec channel, size_t *base_size,
341 size_t *frame_size)
342 {
343 __ASSERT_NO_MSG(base_size != NULL);
344 __ASSERT_NO_MSG(frame_size != NULL);
345
346 if (((int)channel.chan_type < 0) || channel.chan_type >= (SENSOR_CHAN_ALL)) {
347 return -ENOTSUP;
348 }
349
350 switch (channel.chan_type) {
351 case SENSOR_CHAN_ACCEL_X:
352 case SENSOR_CHAN_ACCEL_Y:
353 case SENSOR_CHAN_ACCEL_Z:
354 case SENSOR_CHAN_ACCEL_XYZ:
355 case SENSOR_CHAN_GYRO_X:
356 case SENSOR_CHAN_GYRO_Y:
357 case SENSOR_CHAN_GYRO_Z:
358 case SENSOR_CHAN_GYRO_XYZ:
359 case SENSOR_CHAN_MAGN_X:
360 case SENSOR_CHAN_MAGN_Y:
361 case SENSOR_CHAN_MAGN_Z:
362 case SENSOR_CHAN_MAGN_XYZ:
363 case SENSOR_CHAN_POS_DX:
364 case SENSOR_CHAN_POS_DY:
365 case SENSOR_CHAN_POS_DZ:
366 case SENSOR_CHAN_POS_DXYZ:
367 *base_size = sizeof(struct sensor_three_axis_data);
368 *frame_size = sizeof(struct sensor_three_axis_sample_data);
369 return 0;
370 case SENSOR_CHAN_PROX:
371 *base_size = sizeof(struct sensor_byte_data);
372 *frame_size = sizeof(struct sensor_byte_sample_data);
373 return 0;
374 case SENSOR_CHAN_GAUGE_CYCLE_COUNT:
375 *base_size = sizeof(struct sensor_uint64_data);
376 *frame_size = sizeof(struct sensor_uint64_sample_data);
377 return 0;
378 default:
379 *base_size = sizeof(struct sensor_q31_data);
380 *frame_size = sizeof(struct sensor_q31_sample_data);
381 return 0;
382 }
383 }
384
get_q31_value(const struct sensor_data_generic_header * header,const q31_t * values,struct sensor_chan_spec chan_spec,q31_t * out)385 static int get_q31_value(const struct sensor_data_generic_header *header, const q31_t *values,
386 struct sensor_chan_spec chan_spec, q31_t *out)
387 {
388 for (size_t i = 0; i < header->num_channels; ++i) {
389 if (sensor_chan_spec_eq(chan_spec, header->channels[i])) {
390 *out = values[i];
391 return 0;
392 }
393 }
394 return -EINVAL;
395 }
396
decode_three_axis(const struct sensor_data_generic_header * header,const q31_t * values,struct sensor_three_axis_data * data_out,enum sensor_channel x,enum sensor_channel y,enum sensor_channel z,size_t channel_idx)397 static int decode_three_axis(const struct sensor_data_generic_header *header, const q31_t *values,
398 struct sensor_three_axis_data *data_out, enum sensor_channel x,
399 enum sensor_channel y, enum sensor_channel z, size_t channel_idx)
400 {
401 int rc;
402
403 data_out->header.base_timestamp_ns = header->timestamp_ns;
404 data_out->header.reading_count = 1;
405 data_out->shift = header->shift;
406 data_out->readings[0].timestamp_delta = 0;
407
408 rc = get_q31_value(header, values, (struct sensor_chan_spec){x, channel_idx},
409 &data_out->readings[0].values[0]);
410 if (rc < 0) {
411 return rc;
412 }
413 rc = get_q31_value(header, values, (struct sensor_chan_spec){y, channel_idx},
414 &data_out->readings[0].values[1]);
415 if (rc < 0) {
416 return rc;
417 }
418 rc = get_q31_value(header, values, (struct sensor_chan_spec){z, channel_idx},
419 &data_out->readings[0].values[2]);
420 if (rc < 0) {
421 return rc;
422 }
423 return 1;
424 }
425
decode_q31(const struct sensor_data_generic_header * header,const q31_t * values,struct sensor_q31_data * data_out,struct sensor_chan_spec chan_spec)426 static int decode_q31(const struct sensor_data_generic_header *header, const q31_t *values,
427 struct sensor_q31_data *data_out, struct sensor_chan_spec chan_spec)
428 {
429 int rc;
430
431 data_out->header.base_timestamp_ns = header->timestamp_ns;
432 data_out->header.reading_count = 1;
433 data_out->shift = header->shift;
434 data_out->readings[0].timestamp_delta = 0;
435
436 rc = get_q31_value(header, values, chan_spec, &data_out->readings[0].value);
437 if (rc < 0) {
438 return rc;
439 }
440 return 1;
441 }
442
443 /**
444 * @brief Decode up to N samples from the buffer
445 *
446 * This function will never wrap frames. If 1 channel is available in the current frame and
447 * @p max_count is 2, only 1 channel will be decoded and the frame iterator will be modified
448 * so that the next call to decode will begin at the next frame.
449 *
450 * @param[in] buffer The buffer provided on the :c:struct:`rtio` context
451 * @param[in] channel The channel to decode
452 * @param[in] channel_idx The index of the channel
453 * @param[in,out] fit The current frame iterator
454 * @param[in] max_count The maximum number of channels to decode.
455 * @param[out] data_out The decoded data
456 * @return 0 no more samples to decode
457 * @return >0 the number of decoded frames
458 * @return <0 on error
459 */
decode(const uint8_t * buffer,struct sensor_chan_spec chan_spec,uint32_t * fit,uint16_t max_count,void * data_out)460 static int decode(const uint8_t *buffer, struct sensor_chan_spec chan_spec,
461 uint32_t *fit, uint16_t max_count, void *data_out)
462 {
463 const struct sensor_data_generic_header *header =
464 (const struct sensor_data_generic_header *)buffer;
465 const q31_t *q = (const q31_t *)(buffer + compute_header_size(header->num_channels));
466 int count = 0;
467
468 if (*fit != 0 || max_count < 1) {
469 return -EINVAL;
470 }
471
472 if (((int)chan_spec.chan_type < 0) || chan_spec.chan_type >= (SENSOR_CHAN_ALL)) {
473 return 0;
474 }
475
476 /* Check for 3d channel mappings */
477 switch (chan_spec.chan_type) {
478 case SENSOR_CHAN_ACCEL_X:
479 case SENSOR_CHAN_ACCEL_Y:
480 case SENSOR_CHAN_ACCEL_Z:
481 case SENSOR_CHAN_ACCEL_XYZ:
482 count = decode_three_axis(header, q, data_out, SENSOR_CHAN_ACCEL_X,
483 SENSOR_CHAN_ACCEL_Y, SENSOR_CHAN_ACCEL_Z,
484 chan_spec.chan_idx);
485 break;
486 case SENSOR_CHAN_GYRO_X:
487 case SENSOR_CHAN_GYRO_Y:
488 case SENSOR_CHAN_GYRO_Z:
489 case SENSOR_CHAN_GYRO_XYZ:
490 count = decode_three_axis(header, q, data_out, SENSOR_CHAN_GYRO_X,
491 SENSOR_CHAN_GYRO_Y, SENSOR_CHAN_GYRO_Z,
492 chan_spec.chan_idx);
493 break;
494 case SENSOR_CHAN_MAGN_X:
495 case SENSOR_CHAN_MAGN_Y:
496 case SENSOR_CHAN_MAGN_Z:
497 case SENSOR_CHAN_MAGN_XYZ:
498 count = decode_three_axis(header, q, data_out, SENSOR_CHAN_MAGN_X,
499 SENSOR_CHAN_MAGN_Y, SENSOR_CHAN_MAGN_Z,
500 chan_spec.chan_idx);
501 break;
502 case SENSOR_CHAN_POS_DX:
503 case SENSOR_CHAN_POS_DY:
504 case SENSOR_CHAN_POS_DZ:
505 case SENSOR_CHAN_POS_DXYZ:
506 count = decode_three_axis(header, q, data_out, SENSOR_CHAN_POS_DX,
507 SENSOR_CHAN_POS_DY, SENSOR_CHAN_POS_DZ,
508 chan_spec.chan_idx);
509 break;
510 default:
511 count = decode_q31(header, q, data_out, chan_spec);
512 break;
513 }
514 if (count > 0) {
515 *fit = 1;
516 }
517 return count;
518 }
519
520 const struct sensor_decoder_api __sensor_default_decoder = {
521 .get_frame_count = get_frame_count,
522 .get_size_info = sensor_natively_supported_channel_size_info,
523 .decode = decode,
524 };
525