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 	if (req == NULL) {
269 		LOG_ERR("RTIO work item allocation failed. Consider to increase "
270 			"CONFIG_RTIO_WORKQ_POOL_ITEMS.");
271 		rtio_iodev_sqe_err(iodev_sqe, -ENOMEM);
272 		return;
273 	}
274 
275 	rtio_work_req_submit(req, iodev_sqe, sensor_submit_fallback_sync);
276 }
277 
sensor_processing_with_callback(struct rtio * ctx,sensor_processing_callback_t cb)278 void sensor_processing_with_callback(struct rtio *ctx, sensor_processing_callback_t cb)
279 {
280 	void *userdata = NULL;
281 	uint8_t *buf = NULL;
282 	uint32_t buf_len = 0;
283 	int rc;
284 
285 	/* Wait for a CQE */
286 	struct rtio_cqe *cqe = rtio_cqe_consume_block(ctx);
287 
288 	/* Cache the data from the CQE */
289 	rc = cqe->result;
290 	userdata = cqe->userdata;
291 	rtio_cqe_get_mempool_buffer(ctx, cqe, &buf, &buf_len);
292 
293 	/* Release the CQE */
294 	rtio_cqe_release(ctx, cqe);
295 
296 	/* Call the callback */
297 	cb(rc, buf, buf_len, userdata);
298 
299 	/* Release the memory */
300 	rtio_release_buffer(ctx, buf, buf_len);
301 }
302 
303 /**
304  * @brief Default decoder get frame count
305  *
306  * Default reader can only ever service a single frame at a time.
307  *
308  * @param[in]  buffer The data buffer to parse
309  * @param[in]  channel The channel to get the count for
310  * @param[in]  channel_idx The index of the channel
311  * @param[out] frame_count The number of frames in the buffer (always 1)
312  * @return 0 in all cases
313  */
get_frame_count(const uint8_t * buffer,struct sensor_chan_spec channel,uint16_t * frame_count)314 static int get_frame_count(const uint8_t *buffer, struct sensor_chan_spec channel,
315 			   uint16_t *frame_count)
316 {
317 	struct sensor_data_generic_header *header = (struct sensor_data_generic_header *)buffer;
318 
319 	switch (channel.chan_type) {
320 	case SENSOR_CHAN_ACCEL_XYZ:
321 		channel.chan_type = SENSOR_CHAN_ACCEL_X;
322 		break;
323 	case SENSOR_CHAN_GYRO_XYZ:
324 		channel.chan_type = SENSOR_CHAN_GYRO_X;
325 		break;
326 	case SENSOR_CHAN_MAGN_XYZ:
327 		channel.chan_type = SENSOR_CHAN_MAGN_X;
328 		break;
329 	case SENSOR_CHAN_POS_DXYZ:
330 		channel.chan_type = SENSOR_CHAN_POS_DX;
331 		break;
332 	default:
333 		break;
334 	}
335 	for (size_t i = 0; i < header->num_channels; ++i) {
336 		if (sensor_chan_spec_eq(header->channels[i], channel)) {
337 			*frame_count = 1;
338 			return 0;
339 		}
340 	}
341 
342 	return -ENOTSUP;
343 }
344 
sensor_natively_supported_channel_size_info(struct sensor_chan_spec channel,size_t * base_size,size_t * frame_size)345 int sensor_natively_supported_channel_size_info(struct sensor_chan_spec channel, size_t *base_size,
346 						size_t *frame_size)
347 {
348 	__ASSERT_NO_MSG(base_size != NULL);
349 	__ASSERT_NO_MSG(frame_size != NULL);
350 
351 	if (channel.chan_type >= SENSOR_CHAN_ALL) {
352 		return -ENOTSUP;
353 	}
354 
355 	switch (channel.chan_type) {
356 	case SENSOR_CHAN_ACCEL_X:
357 	case SENSOR_CHAN_ACCEL_Y:
358 	case SENSOR_CHAN_ACCEL_Z:
359 	case SENSOR_CHAN_ACCEL_XYZ:
360 	case SENSOR_CHAN_GYRO_X:
361 	case SENSOR_CHAN_GYRO_Y:
362 	case SENSOR_CHAN_GYRO_Z:
363 	case SENSOR_CHAN_GYRO_XYZ:
364 	case SENSOR_CHAN_MAGN_X:
365 	case SENSOR_CHAN_MAGN_Y:
366 	case SENSOR_CHAN_MAGN_Z:
367 	case SENSOR_CHAN_MAGN_XYZ:
368 	case SENSOR_CHAN_POS_DX:
369 	case SENSOR_CHAN_POS_DY:
370 	case SENSOR_CHAN_POS_DZ:
371 	case SENSOR_CHAN_POS_DXYZ:
372 		*base_size = sizeof(struct sensor_three_axis_data);
373 		*frame_size = sizeof(struct sensor_three_axis_sample_data);
374 		return 0;
375 	case SENSOR_CHAN_PROX:
376 		*base_size = sizeof(struct sensor_byte_data);
377 		*frame_size = sizeof(struct sensor_byte_sample_data);
378 		return 0;
379 	case SENSOR_CHAN_GAUGE_CYCLE_COUNT:
380 		*base_size = sizeof(struct sensor_uint64_data);
381 		*frame_size = sizeof(struct sensor_uint64_sample_data);
382 		return 0;
383 	default:
384 		*base_size = sizeof(struct sensor_q31_data);
385 		*frame_size = sizeof(struct sensor_q31_sample_data);
386 		return 0;
387 	}
388 }
389 
get_q31_value(const struct sensor_data_generic_header * header,const q31_t * values,struct sensor_chan_spec chan_spec,q31_t * out)390 static int get_q31_value(const struct sensor_data_generic_header *header, const q31_t *values,
391 			 struct sensor_chan_spec chan_spec, q31_t *out)
392 {
393 	for (size_t i = 0; i < header->num_channels; ++i) {
394 		if (sensor_chan_spec_eq(chan_spec, header->channels[i])) {
395 			*out = values[i];
396 			return 0;
397 		}
398 	}
399 	return -EINVAL;
400 }
401 
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)402 static int decode_three_axis(const struct sensor_data_generic_header *header, const q31_t *values,
403 			     struct sensor_three_axis_data *data_out, enum sensor_channel x,
404 			     enum sensor_channel y, enum sensor_channel z, size_t channel_idx)
405 {
406 	int rc;
407 
408 	data_out->header.base_timestamp_ns = header->timestamp_ns;
409 	data_out->header.reading_count = 1;
410 	data_out->shift = header->shift;
411 	data_out->readings[0].timestamp_delta = 0;
412 
413 	rc = get_q31_value(header, values, (struct sensor_chan_spec){x, channel_idx},
414 			   &data_out->readings[0].values[0]);
415 	if (rc < 0) {
416 		return rc;
417 	}
418 	rc = get_q31_value(header, values, (struct sensor_chan_spec){y, channel_idx},
419 			   &data_out->readings[0].values[1]);
420 	if (rc < 0) {
421 		return rc;
422 	}
423 	rc = get_q31_value(header, values, (struct sensor_chan_spec){z, channel_idx},
424 			   &data_out->readings[0].values[2]);
425 	if (rc < 0) {
426 		return rc;
427 	}
428 	return 1;
429 }
430 
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)431 static int decode_q31(const struct sensor_data_generic_header *header, const q31_t *values,
432 		      struct sensor_q31_data *data_out, struct sensor_chan_spec chan_spec)
433 {
434 	int rc;
435 
436 	data_out->header.base_timestamp_ns = header->timestamp_ns;
437 	data_out->header.reading_count = 1;
438 	data_out->shift = header->shift;
439 	data_out->readings[0].timestamp_delta = 0;
440 
441 	rc = get_q31_value(header, values, chan_spec, &data_out->readings[0].value);
442 	if (rc < 0) {
443 		return rc;
444 	}
445 	return 1;
446 }
447 
448 /**
449  * @brief Decode up to N samples from the buffer
450  *
451  * This function will never wrap frames. If 1 channel is available in the current frame and
452  * @p max_count is 2, only 1 channel will be decoded and the frame iterator will be modified
453  * so that the next call to decode will begin at the next frame.
454  *
455  * @param[in]     buffer The buffer provided on the :c:struct:`rtio` context
456  * @param[in]     channel The channel to decode
457  * @param[in]     channel_idx The index of the channel
458  * @param[in,out] fit The current frame iterator
459  * @param[in]     max_count The maximum number of channels to decode.
460  * @param[out]    data_out The decoded data
461  * @return 0 no more samples to decode
462  * @return >0 the number of decoded frames
463  * @return <0 on error
464  */
decode(const uint8_t * buffer,struct sensor_chan_spec chan_spec,uint32_t * fit,uint16_t max_count,void * data_out)465 static int decode(const uint8_t *buffer, struct sensor_chan_spec chan_spec,
466 		  uint32_t *fit, uint16_t max_count, void *data_out)
467 {
468 	const struct sensor_data_generic_header *header =
469 		(const struct sensor_data_generic_header *)buffer;
470 	const q31_t *q = (const q31_t *)(buffer + compute_header_size(header->num_channels));
471 	int count = 0;
472 
473 	if (*fit != 0 || max_count < 1) {
474 		return -EINVAL;
475 	}
476 
477 	if (chan_spec.chan_type >= SENSOR_CHAN_ALL) {
478 		return 0;
479 	}
480 
481 	/* Check for 3d channel mappings */
482 	switch (chan_spec.chan_type) {
483 	case SENSOR_CHAN_ACCEL_X:
484 	case SENSOR_CHAN_ACCEL_Y:
485 	case SENSOR_CHAN_ACCEL_Z:
486 	case SENSOR_CHAN_ACCEL_XYZ:
487 		count = decode_three_axis(header, q, data_out, SENSOR_CHAN_ACCEL_X,
488 					  SENSOR_CHAN_ACCEL_Y, SENSOR_CHAN_ACCEL_Z,
489 					  chan_spec.chan_idx);
490 		break;
491 	case SENSOR_CHAN_GYRO_X:
492 	case SENSOR_CHAN_GYRO_Y:
493 	case SENSOR_CHAN_GYRO_Z:
494 	case SENSOR_CHAN_GYRO_XYZ:
495 		count = decode_three_axis(header, q, data_out, SENSOR_CHAN_GYRO_X,
496 					  SENSOR_CHAN_GYRO_Y, SENSOR_CHAN_GYRO_Z,
497 					  chan_spec.chan_idx);
498 		break;
499 	case SENSOR_CHAN_MAGN_X:
500 	case SENSOR_CHAN_MAGN_Y:
501 	case SENSOR_CHAN_MAGN_Z:
502 	case SENSOR_CHAN_MAGN_XYZ:
503 		count = decode_three_axis(header, q, data_out, SENSOR_CHAN_MAGN_X,
504 					  SENSOR_CHAN_MAGN_Y, SENSOR_CHAN_MAGN_Z,
505 					  chan_spec.chan_idx);
506 		break;
507 	case SENSOR_CHAN_POS_DX:
508 	case SENSOR_CHAN_POS_DY:
509 	case SENSOR_CHAN_POS_DZ:
510 	case SENSOR_CHAN_POS_DXYZ:
511 		count = decode_three_axis(header, q, data_out, SENSOR_CHAN_POS_DX,
512 					  SENSOR_CHAN_POS_DY, SENSOR_CHAN_POS_DZ,
513 					  chan_spec.chan_idx);
514 		break;
515 	default:
516 		count = decode_q31(header, q, data_out, chan_spec);
517 		break;
518 	}
519 	if (count > 0) {
520 		*fit = 1;
521 	}
522 	return count;
523 }
524 
525 const struct sensor_decoder_api __sensor_default_decoder = {
526 	.get_frame_count = get_frame_count,
527 	.get_size_info = sensor_natively_supported_channel_size_info,
528 	.decode = decode,
529 };
530