1 /**
2 * @file drivers/sensor.h
3 *
4 * @brief Public APIs for the sensor driver.
5 */
6
7 /*
8 * Copyright (c) 2016 Intel Corporation
9 *
10 * SPDX-License-Identifier: Apache-2.0
11 */
12 #ifndef ZEPHYR_INCLUDE_DRIVERS_SENSOR_H_
13 #define ZEPHYR_INCLUDE_DRIVERS_SENSOR_H_
14
15 /**
16 * @brief Sensor Interface
17 * @defgroup sensor_interface Sensor Interface
18 * @since 1.2
19 * @version 1.0.0
20 * @ingroup io_interfaces
21 * @{
22 */
23
24 #include <errno.h>
25 #include <stdlib.h>
26
27 #include <zephyr/device.h>
28 #include <zephyr/drivers/sensor_data_types.h>
29 #include <zephyr/dsp/types.h>
30 #include <zephyr/rtio/rtio.h>
31 #include <zephyr/sys/iterable_sections.h>
32 #include <zephyr/types.h>
33
34 #ifdef __cplusplus
35 extern "C" {
36 #endif
37
38 /**
39 * @brief Representation of a sensor readout value.
40 *
41 * The value is represented as having an integer and a fractional part,
42 * and can be obtained using the formula val1 + val2 * 10^(-6). Negative
43 * values also adhere to the above formula, but may need special attention.
44 * Here are some examples of the value representation:
45 *
46 * 0.5: val1 = 0, val2 = 500000
47 * -0.5: val1 = 0, val2 = -500000
48 * -1.0: val1 = -1, val2 = 0
49 * -1.5: val1 = -1, val2 = -500000
50 */
51 struct sensor_value {
52 /** Integer part of the value. */
53 int32_t val1;
54 /** Fractional part of the value (in one-millionth parts). */
55 int32_t val2;
56 };
57
58 /**
59 * @brief Sensor channels.
60 */
61 enum sensor_channel {
62 /** Acceleration on the X axis, in m/s^2. */
63 SENSOR_CHAN_ACCEL_X,
64 /** Acceleration on the Y axis, in m/s^2. */
65 SENSOR_CHAN_ACCEL_Y,
66 /** Acceleration on the Z axis, in m/s^2. */
67 SENSOR_CHAN_ACCEL_Z,
68 /** Acceleration on the X, Y and Z axes. */
69 SENSOR_CHAN_ACCEL_XYZ,
70 /** Angular velocity around the X axis, in radians/s. */
71 SENSOR_CHAN_GYRO_X,
72 /** Angular velocity around the Y axis, in radians/s. */
73 SENSOR_CHAN_GYRO_Y,
74 /** Angular velocity around the Z axis, in radians/s. */
75 SENSOR_CHAN_GYRO_Z,
76 /** Angular velocity around the X, Y and Z axes. */
77 SENSOR_CHAN_GYRO_XYZ,
78 /** Magnetic field on the X axis, in Gauss. */
79 SENSOR_CHAN_MAGN_X,
80 /** Magnetic field on the Y axis, in Gauss. */
81 SENSOR_CHAN_MAGN_Y,
82 /** Magnetic field on the Z axis, in Gauss. */
83 SENSOR_CHAN_MAGN_Z,
84 /** Magnetic field on the X, Y and Z axes. */
85 SENSOR_CHAN_MAGN_XYZ,
86 /** Device die temperature in degrees Celsius. */
87 SENSOR_CHAN_DIE_TEMP,
88 /** Ambient temperature in degrees Celsius. */
89 SENSOR_CHAN_AMBIENT_TEMP,
90 /** Pressure in kilopascal. */
91 SENSOR_CHAN_PRESS,
92 /**
93 * Proximity. Adimensional. A value of 1 indicates that an
94 * object is close.
95 */
96 SENSOR_CHAN_PROX,
97 /** Humidity, in percent. */
98 SENSOR_CHAN_HUMIDITY,
99 /** Illuminance in visible spectrum, in lux. */
100 SENSOR_CHAN_LIGHT,
101 /** Illuminance in infra-red spectrum, in lux. */
102 SENSOR_CHAN_IR,
103 /** Illuminance in red spectrum, in lux. */
104 SENSOR_CHAN_RED,
105 /** Illuminance in green spectrum, in lux. */
106 SENSOR_CHAN_GREEN,
107 /** Illuminance in blue spectrum, in lux. */
108 SENSOR_CHAN_BLUE,
109 /** Altitude, in meters */
110 SENSOR_CHAN_ALTITUDE,
111
112 /** 1.0 micro-meters Particulate Matter, in ug/m^3 */
113 SENSOR_CHAN_PM_1_0,
114 /** 2.5 micro-meters Particulate Matter, in ug/m^3 */
115 SENSOR_CHAN_PM_2_5,
116 /** 10 micro-meters Particulate Matter, in ug/m^3 */
117 SENSOR_CHAN_PM_10,
118 /** Distance. From sensor to target, in meters */
119 SENSOR_CHAN_DISTANCE,
120
121 /** CO2 level, in parts per million (ppm) **/
122 SENSOR_CHAN_CO2,
123 /** O2 level, in parts per million (ppm) **/
124 SENSOR_CHAN_O2,
125 /** VOC level, in parts per billion (ppb) **/
126 SENSOR_CHAN_VOC,
127 /** Gas sensor resistance in ohms. */
128 SENSOR_CHAN_GAS_RES,
129
130 /** Voltage, in volts **/
131 SENSOR_CHAN_VOLTAGE,
132
133 /** Current Shunt Voltage in milli-volts **/
134 SENSOR_CHAN_VSHUNT,
135
136 /** Current, in amps **/
137 SENSOR_CHAN_CURRENT,
138 /** Power in watts **/
139 SENSOR_CHAN_POWER,
140
141 /** Resistance , in Ohm **/
142 SENSOR_CHAN_RESISTANCE,
143
144 /** Angular rotation, in degrees */
145 SENSOR_CHAN_ROTATION,
146
147 /** Position change on the X axis, in points. */
148 SENSOR_CHAN_POS_DX,
149 /** Position change on the Y axis, in points. */
150 SENSOR_CHAN_POS_DY,
151 /** Position change on the Z axis, in points. */
152 SENSOR_CHAN_POS_DZ,
153 /** Position change on the X, Y and Z axis, in points. */
154 SENSOR_CHAN_POS_DXYZ,
155
156 /** Revolutions per minute, in RPM. */
157 SENSOR_CHAN_RPM,
158
159 /** Frequency, in Hz. */
160 SENSOR_CHAN_FREQUENCY,
161
162 /** Voltage, in volts **/
163 SENSOR_CHAN_GAUGE_VOLTAGE,
164 /** Average current, in amps **/
165 SENSOR_CHAN_GAUGE_AVG_CURRENT,
166 /** Standby current, in amps **/
167 SENSOR_CHAN_GAUGE_STDBY_CURRENT,
168 /** Max load current, in amps **/
169 SENSOR_CHAN_GAUGE_MAX_LOAD_CURRENT,
170 /** Gauge temperature **/
171 SENSOR_CHAN_GAUGE_TEMP,
172 /** State of charge measurement in % **/
173 SENSOR_CHAN_GAUGE_STATE_OF_CHARGE,
174 /** Full Charge Capacity in mAh **/
175 SENSOR_CHAN_GAUGE_FULL_CHARGE_CAPACITY,
176 /** Remaining Charge Capacity in mAh **/
177 SENSOR_CHAN_GAUGE_REMAINING_CHARGE_CAPACITY,
178 /** Nominal Available Capacity in mAh **/
179 SENSOR_CHAN_GAUGE_NOM_AVAIL_CAPACITY,
180 /** Full Available Capacity in mAh **/
181 SENSOR_CHAN_GAUGE_FULL_AVAIL_CAPACITY,
182 /** Average power in mW **/
183 SENSOR_CHAN_GAUGE_AVG_POWER,
184 /** State of health measurement in % **/
185 SENSOR_CHAN_GAUGE_STATE_OF_HEALTH,
186 /** Time to empty in minutes **/
187 SENSOR_CHAN_GAUGE_TIME_TO_EMPTY,
188 /** Time to full in minutes **/
189 SENSOR_CHAN_GAUGE_TIME_TO_FULL,
190 /** Cycle count (total number of charge/discharge cycles) **/
191 SENSOR_CHAN_GAUGE_CYCLE_COUNT,
192 /** Design voltage of cell in V (max voltage)*/
193 SENSOR_CHAN_GAUGE_DESIGN_VOLTAGE,
194 /** Desired voltage of cell in V (nominal voltage) */
195 SENSOR_CHAN_GAUGE_DESIRED_VOLTAGE,
196 /** Desired charging current in mA */
197 SENSOR_CHAN_GAUGE_DESIRED_CHARGING_CURRENT,
198 /** Game Rotation Vector (unit quaternion components X/Y/Z/W) */
199 SENSOR_CHAN_GAME_ROTATION_VECTOR,
200 /** Gravity Vector (X/Y/Z components in m/s^2) */
201 SENSOR_CHAN_GRAVITY_VECTOR,
202 /** Gyroscope bias (X/Y/Z components in radians/s) */
203 SENSOR_CHAN_GBIAS_XYZ,
204
205 /** All channels. */
206 SENSOR_CHAN_ALL,
207
208 /**
209 * Number of all common sensor channels.
210 */
211 SENSOR_CHAN_COMMON_COUNT,
212
213 /**
214 * This and higher values are sensor specific.
215 * Refer to the sensor header file.
216 */
217 SENSOR_CHAN_PRIV_START = SENSOR_CHAN_COMMON_COUNT,
218
219 /**
220 * Maximum value describing a sensor channel type.
221 */
222 SENSOR_CHAN_MAX = INT16_MAX,
223 };
224
225 /**
226 * @brief Sensor trigger types.
227 */
228 enum sensor_trigger_type {
229 /**
230 * Timer-based trigger, useful when the sensor does not have an
231 * interrupt line.
232 */
233 SENSOR_TRIG_TIMER,
234 /** Trigger fires whenever new data is ready. */
235 SENSOR_TRIG_DATA_READY,
236 /**
237 * Trigger fires when the selected channel varies significantly.
238 * This includes any-motion detection when the channel is
239 * acceleration or gyro. If detection is based on slope between
240 * successive channel readings, the slope threshold is configured
241 * via the @ref SENSOR_ATTR_SLOPE_TH and @ref SENSOR_ATTR_SLOPE_DUR
242 * attributes.
243 */
244 SENSOR_TRIG_DELTA,
245 /** Trigger fires when a near/far event is detected. */
246 SENSOR_TRIG_NEAR_FAR,
247 /**
248 * Trigger fires when channel reading transitions configured
249 * thresholds. The thresholds are configured via the @ref
250 * SENSOR_ATTR_LOWER_THRESH, @ref SENSOR_ATTR_UPPER_THRESH, and
251 * @ref SENSOR_ATTR_HYSTERESIS attributes.
252 */
253 SENSOR_TRIG_THRESHOLD,
254
255 /** Trigger fires when a single tap is detected. */
256 SENSOR_TRIG_TAP,
257
258 /** Trigger fires when a double tap is detected. */
259 SENSOR_TRIG_DOUBLE_TAP,
260
261 /** Trigger fires when a free fall is detected. */
262 SENSOR_TRIG_FREEFALL,
263
264 /** Trigger fires when motion is detected. */
265 SENSOR_TRIG_MOTION,
266
267 /** Trigger fires when no motion has been detected for a while. */
268 SENSOR_TRIG_STATIONARY,
269
270 /** Trigger fires when the FIFO watermark has been reached. */
271 SENSOR_TRIG_FIFO_WATERMARK,
272
273 /** Trigger fires when the FIFO becomes full. */
274 SENSOR_TRIG_FIFO_FULL,
275 /**
276 * Number of all common sensor triggers.
277 */
278 SENSOR_TRIG_COMMON_COUNT,
279
280 /**
281 * This and higher values are sensor specific.
282 * Refer to the sensor header file.
283 */
284 SENSOR_TRIG_PRIV_START = SENSOR_TRIG_COMMON_COUNT,
285
286 /**
287 * Maximum value describing a sensor trigger type.
288 */
289 SENSOR_TRIG_MAX = INT16_MAX,
290 };
291
292 /**
293 * @brief Sensor trigger spec.
294 */
295 struct sensor_trigger {
296 /** Trigger type. */
297 enum sensor_trigger_type type;
298 /** Channel the trigger is set on. */
299 enum sensor_channel chan;
300 };
301
302 /**
303 * @brief Sensor attribute types.
304 */
305 enum sensor_attribute {
306 /**
307 * Sensor sampling frequency, i.e. how many times a second the
308 * sensor takes a measurement.
309 */
310 SENSOR_ATTR_SAMPLING_FREQUENCY,
311 /** Lower threshold for trigger. */
312 SENSOR_ATTR_LOWER_THRESH,
313 /** Upper threshold for trigger. */
314 SENSOR_ATTR_UPPER_THRESH,
315 /** Threshold for any-motion (slope) trigger. */
316 SENSOR_ATTR_SLOPE_TH,
317 /**
318 * Duration for which the slope values needs to be
319 * outside the threshold for the trigger to fire.
320 */
321 SENSOR_ATTR_SLOPE_DUR,
322 /* Hysteresis for trigger thresholds. */
323 SENSOR_ATTR_HYSTERESIS,
324 /** Oversampling factor */
325 SENSOR_ATTR_OVERSAMPLING,
326 /** Sensor range, in SI units. */
327 SENSOR_ATTR_FULL_SCALE,
328 /**
329 * The sensor value returned will be altered by the amount indicated by
330 * offset: final_value = sensor_value + offset.
331 */
332 SENSOR_ATTR_OFFSET,
333 /**
334 * Calibration target. This will be used by the internal chip's
335 * algorithms to calibrate itself on a certain axis, or all of them.
336 */
337 SENSOR_ATTR_CALIB_TARGET,
338 /** Configure the operating modes of a sensor. */
339 SENSOR_ATTR_CONFIGURATION,
340 /** Set a calibration value needed by a sensor. */
341 SENSOR_ATTR_CALIBRATION,
342 /** Enable/disable sensor features */
343 SENSOR_ATTR_FEATURE_MASK,
344 /** Alert threshold or alert enable/disable */
345 SENSOR_ATTR_ALERT,
346 /** Free-fall duration represented in milliseconds.
347 * If the sampling frequency is changed during runtime,
348 * this attribute should be set to adjust freefall duration
349 * to the new sampling frequency.
350 */
351 SENSOR_ATTR_FF_DUR,
352
353 /** Hardware batch duration in ticks */
354 SENSOR_ATTR_BATCH_DURATION,
355 /* Configure the gain of a sensor. */
356 SENSOR_ATTR_GAIN,
357 /* Configure the resolution of a sensor. */
358 SENSOR_ATTR_RESOLUTION,
359 /**
360 * Number of all common sensor attributes.
361 */
362 SENSOR_ATTR_COMMON_COUNT,
363
364 /**
365 * This and higher values are sensor specific.
366 * Refer to the sensor header file.
367 */
368 SENSOR_ATTR_PRIV_START = SENSOR_ATTR_COMMON_COUNT,
369
370 /**
371 * Maximum value describing a sensor attribute type.
372 */
373 SENSOR_ATTR_MAX = INT16_MAX,
374 };
375
376 /**
377 * @typedef sensor_trigger_handler_t
378 * @brief Callback API upon firing of a trigger
379 *
380 * @param dev Pointer to the sensor device
381 * @param trigger The trigger
382 */
383 typedef void (*sensor_trigger_handler_t)(const struct device *dev,
384 const struct sensor_trigger *trigger);
385
386 /**
387 * @typedef sensor_attr_set_t
388 * @brief Callback API upon setting a sensor's attributes
389 *
390 * See sensor_attr_set() for argument description
391 */
392 typedef int (*sensor_attr_set_t)(const struct device *dev,
393 enum sensor_channel chan,
394 enum sensor_attribute attr,
395 const struct sensor_value *val);
396
397 /**
398 * @typedef sensor_attr_get_t
399 * @brief Callback API upon getting a sensor's attributes
400 *
401 * See sensor_attr_get() for argument description
402 */
403 typedef int (*sensor_attr_get_t)(const struct device *dev,
404 enum sensor_channel chan,
405 enum sensor_attribute attr,
406 struct sensor_value *val);
407
408 /**
409 * @typedef sensor_trigger_set_t
410 * @brief Callback API for setting a sensor's trigger and handler
411 *
412 * See sensor_trigger_set() for argument description
413 */
414 typedef int (*sensor_trigger_set_t)(const struct device *dev,
415 const struct sensor_trigger *trig,
416 sensor_trigger_handler_t handler);
417 /**
418 * @typedef sensor_sample_fetch_t
419 * @brief Callback API for fetching data from a sensor
420 *
421 * See sensor_sample_fetch() for argument description
422 */
423 typedef int (*sensor_sample_fetch_t)(const struct device *dev,
424 enum sensor_channel chan);
425 /**
426 * @typedef sensor_channel_get_t
427 * @brief Callback API for getting a reading from a sensor
428 *
429 * See sensor_channel_get() for argument description
430 */
431 typedef int (*sensor_channel_get_t)(const struct device *dev,
432 enum sensor_channel chan,
433 struct sensor_value *val);
434
435 /**
436 * @brief Sensor Channel Specification
437 *
438 * A sensor channel specification is a unique identifier per sensor device describing
439 * a measurement channel.
440 *
441 * @note Typically passed by value as the size of a sensor_chan_spec is a single word.
442 */
443 struct sensor_chan_spec {
444 uint16_t chan_type; /**< A sensor channel type */
445 uint16_t chan_idx; /**< A sensor channel index */
446 };
447
448 /** @cond INTERNAL_HIDDEN */
449 /* Ensure sensor_chan_spec is sensibly sized to pass by value */
450 BUILD_ASSERT(sizeof(struct sensor_chan_spec) <= sizeof(uintptr_t),
451 "sensor_chan_spec size should be equal or less than the size of a machine word");
452 /** @endcond */
453
454 /**
455 * @brief Check if channel specs are equivalent
456 *
457 * @param chan_spec0 First chan spec
458 * @param chan_spec1 Second chan spec
459 * @retval true If equivalent
460 * @retval false If not equivalent
461 */
sensor_chan_spec_eq(struct sensor_chan_spec chan_spec0,struct sensor_chan_spec chan_spec1)462 static inline bool sensor_chan_spec_eq(struct sensor_chan_spec chan_spec0,
463 struct sensor_chan_spec chan_spec1)
464 {
465 return chan_spec0.chan_type == chan_spec1.chan_type &&
466 chan_spec0.chan_idx == chan_spec1.chan_idx;
467 }
468
469 /**
470 * @brief Decodes a single raw data buffer
471 *
472 * Data buffers are provided on the @ref rtio context that's supplied to
473 * @ref sensor_read.
474 */
475 struct sensor_decoder_api {
476 /**
477 * @brief Get the number of frames in the current buffer.
478 *
479 * @param[in] buffer The buffer provided on the @ref rtio context.
480 * @param[in] channel The channel to get the count for
481 * @param[out] frame_count The number of frames on the buffer (at least 1)
482 * @return 0 on success
483 * @return -ENOTSUP if the channel/channel_idx aren't found
484 */
485 int (*get_frame_count)(const uint8_t *buffer, struct sensor_chan_spec channel,
486 uint16_t *frame_count);
487
488 /**
489 * @brief Get the size required to decode a given channel
490 *
491 * When decoding a single frame, use @p base_size. For every additional frame, add another
492 * @p frame_size. As an example, to decode 3 frames use: 'base_size + 2 * frame_size'.
493 *
494 * @param[in] channel The channel to query
495 * @param[out] base_size The size of decoding the first frame
496 * @param[out] frame_size The additional size of every additional frame
497 * @return 0 on success
498 * @return -ENOTSUP if the channel is not supported
499 */
500 int (*get_size_info)(struct sensor_chan_spec channel, size_t *base_size,
501 size_t *frame_size);
502
503 /**
504 * @brief Decode up to @p max_count samples from the buffer
505 *
506 * Decode samples of channel @ref sensor_channel across multiple frames. If there exist
507 * multiple instances of the same channel, @p channel_index is used to differentiate them.
508 * As an example, assume a sensor provides 2 distance measurements:
509 *
510 * @code{.c}
511 * // Decode the first channel instance of 'distance'
512 * decoder->decode(buffer, SENSOR_CHAN_DISTANCE, 0, &fit, 5, out);
513 * ...
514 *
515 * // Decode the second channel instance of 'distance'
516 * decoder->decode(buffer, SENSOR_CHAN_DISTANCE, 1, &fit, 5, out);
517 * @endcode
518 *
519 * @param[in] buffer The buffer provided on the @ref rtio context
520 * @param[in] channel The channel to decode
521 * @param[in,out] fit The current frame iterator
522 * @param[in] max_count The maximum number of channels to decode.
523 * @param[out] data_out The decoded data
524 * @return 0 no more samples to decode
525 * @return >0 the number of decoded frames
526 * @return <0 on error
527 */
528 int (*decode)(const uint8_t *buffer, struct sensor_chan_spec channel, uint32_t *fit,
529 uint16_t max_count, void *data_out);
530
531 /**
532 * @brief Check if the given trigger type is present
533 *
534 * @param[in] buffer The buffer provided on the @ref rtio context
535 * @param[in] trigger The trigger type in question
536 * @return Whether the trigger is present in the buffer
537 */
538 bool (*has_trigger)(const uint8_t *buffer, enum sensor_trigger_type trigger);
539 };
540
541 /**
542 * @brief Used for iterating over the data frames via the sensor_decoder_api.
543 *
544 * Example usage:
545 *
546 * @code(.c)
547 * struct sensor_decode_context ctx = SENSOR_DECODE_CONTEXT_INIT(
548 * decoder, buffer, SENSOR_CHAN_ACCEL_XYZ, 0);
549 *
550 * while (true) {
551 * struct sensor_three_axis_data accel_out_data;
552 *
553 * num_decoded_channels = sensor_decode(ctx, &accel_out_data, 1);
554 *
555 * if (num_decoded_channels <= 0) {
556 * printk("Done decoding buffer\n");
557 * break;
558 * }
559 *
560 * printk("Decoded (%" PRId32 ", %" PRId32 ", %" PRId32 ")\n", accel_out_data.readings[0].x,
561 * accel_out_data.readings[0].y, accel_out_data.readings[0].z);
562 * }
563 * @endcode
564 */
565 struct sensor_decode_context {
566 const struct sensor_decoder_api *decoder;
567 const uint8_t *buffer;
568 struct sensor_chan_spec channel;
569 uint32_t fit;
570 };
571
572 /**
573 * @brief Initialize a sensor_decode_context
574 */
575 #define SENSOR_DECODE_CONTEXT_INIT(decoder_, buffer_, channel_type_, channel_index_) \
576 { \
577 .decoder = (decoder_), \
578 .buffer = (buffer_), \
579 .channel = {.chan_type = (channel_type_), .chan_idx = (channel_index_)}, \
580 .fit = 0, \
581 }
582
583 /**
584 * @brief Decode N frames using a sensor_decode_context
585 *
586 * @param[in,out] ctx The context to use for decoding
587 * @param[out] out The output buffer
588 * @param[in] max_count Maximum number of frames to decode
589 * @return The decode result from sensor_decoder_api's decode function
590 */
sensor_decode(struct sensor_decode_context * ctx,void * out,uint16_t max_count)591 static inline int sensor_decode(struct sensor_decode_context *ctx, void *out, uint16_t max_count)
592 {
593 return ctx->decoder->decode(ctx->buffer, ctx->channel, &ctx->fit, max_count, out);
594 }
595
596 int sensor_natively_supported_channel_size_info(struct sensor_chan_spec channel, size_t *base_size,
597 size_t *frame_size);
598
599 /**
600 * @typedef sensor_get_decoder_t
601 * @brief Get the decoder associate with the given device
602 *
603 * @see sensor_get_decoder for more details
604 */
605 typedef int (*sensor_get_decoder_t)(const struct device *dev,
606 const struct sensor_decoder_api **api);
607
608 /**
609 * @brief Options for what to do with the associated data when a trigger is consumed
610 */
611 enum sensor_stream_data_opt {
612 /** @brief Include whatever data is associated with the trigger */
613 SENSOR_STREAM_DATA_INCLUDE = 0,
614 /** @brief Do nothing with the associated trigger data, it may be consumed later */
615 SENSOR_STREAM_DATA_NOP = 1,
616 /** @brief Flush/clear whatever data is associated with the trigger */
617 SENSOR_STREAM_DATA_DROP = 2,
618 };
619
620 struct sensor_stream_trigger {
621 enum sensor_trigger_type trigger;
622 enum sensor_stream_data_opt opt;
623 };
624
625 #define SENSOR_STREAM_TRIGGER_PREP(_trigger, _opt) \
626 { \
627 .trigger = (_trigger), .opt = (_opt), \
628 }
629
630 /*
631 * Internal data structure used to store information about the IODevice for async reading and
632 * streaming sensor data.
633 */
634 struct sensor_read_config {
635 const struct device *sensor;
636 const bool is_streaming;
637 union {
638 struct sensor_chan_spec *const channels;
639 struct sensor_stream_trigger *const triggers;
640 };
641 size_t count;
642 const size_t max;
643 };
644
645 /**
646 * @brief Define a reading instance of a sensor
647 *
648 * Use this macro to generate a @ref rtio_iodev for reading specific channels. Example:
649 *
650 * @code(.c)
651 * SENSOR_DT_READ_IODEV(icm42688_accelgyro, DT_NODELABEL(icm42688),
652 * { SENSOR_CHAN_ACCEL_XYZ, 0 },
653 * { SENSOR_CHAN_GYRO_XYZ, 0 });
654 *
655 * int main(void) {
656 * sensor_read_async_mempool(&icm42688_accelgyro, &rtio);
657 * }
658 * @endcode
659 */
660 #define SENSOR_DT_READ_IODEV(name, dt_node, ...) \
661 static struct sensor_chan_spec _CONCAT(__channel_array_, name)[] = {__VA_ARGS__}; \
662 static struct sensor_read_config _CONCAT(__sensor_read_config_, name) = { \
663 .sensor = DEVICE_DT_GET(dt_node), \
664 .is_streaming = false, \
665 .channels = _CONCAT(__channel_array_, name), \
666 .count = ARRAY_SIZE(_CONCAT(__channel_array_, name)), \
667 .max = ARRAY_SIZE(_CONCAT(__channel_array_, name)), \
668 }; \
669 RTIO_IODEV_DEFINE(name, &__sensor_iodev_api, _CONCAT(&__sensor_read_config_, name))
670
671 /**
672 * @brief Define a stream instance of a sensor
673 *
674 * Use this macro to generate a @ref rtio_iodev for starting a stream that's triggered by specific
675 * interrupts. Example:
676 *
677 * @code(.c)
678 * SENSOR_DT_STREAM_IODEV(imu_stream, DT_ALIAS(imu),
679 * {SENSOR_TRIG_FIFO_WATERMARK, SENSOR_STREAM_DATA_INCLUDE},
680 * {SENSOR_TRIG_FIFO_FULL, SENSOR_STREAM_DATA_NOP});
681 *
682 * int main(void) {
683 * struct rtio_sqe *handle;
684 * sensor_stream(&imu_stream, &rtio, NULL, &handle);
685 * k_msleep(1000);
686 * rtio_sqe_cancel(handle);
687 * }
688 * @endcode
689 */
690 #define SENSOR_DT_STREAM_IODEV(name, dt_node, ...) \
691 static struct sensor_stream_trigger _CONCAT(__trigger_array_, name)[] = {__VA_ARGS__}; \
692 static struct sensor_read_config _CONCAT(__sensor_read_config_, name) = { \
693 .sensor = DEVICE_DT_GET(dt_node), \
694 .is_streaming = true, \
695 .triggers = _CONCAT(__trigger_array_, name), \
696 .count = ARRAY_SIZE(_CONCAT(__trigger_array_, name)), \
697 .max = ARRAY_SIZE(_CONCAT(__trigger_array_, name)), \
698 }; \
699 RTIO_IODEV_DEFINE(name, &__sensor_iodev_api, &_CONCAT(__sensor_read_config_, name))
700
701 /* Used to submit an RTIO sqe to the sensor's iodev */
702 typedef void (*sensor_submit_t)(const struct device *sensor, struct rtio_iodev_sqe *sqe);
703
704 /* The default decoder API */
705 extern const struct sensor_decoder_api __sensor_default_decoder;
706
707 /* The default sensor iodev API */
708 extern const struct rtio_iodev_api __sensor_iodev_api;
709
710 __subsystem struct sensor_driver_api {
711 sensor_attr_set_t attr_set;
712 sensor_attr_get_t attr_get;
713 sensor_trigger_set_t trigger_set;
714 sensor_sample_fetch_t sample_fetch;
715 sensor_channel_get_t channel_get;
716 sensor_get_decoder_t get_decoder;
717 sensor_submit_t submit;
718 };
719
720 /**
721 * @brief Set an attribute for a sensor
722 *
723 * @param dev Pointer to the sensor device
724 * @param chan The channel the attribute belongs to, if any. Some
725 * attributes may only be set for all channels of a device, depending on
726 * device capabilities.
727 * @param attr The attribute to set
728 * @param val The value to set the attribute to
729 *
730 * @return 0 if successful, negative errno code if failure.
731 */
732 __syscall int sensor_attr_set(const struct device *dev,
733 enum sensor_channel chan,
734 enum sensor_attribute attr,
735 const struct sensor_value *val);
736
z_impl_sensor_attr_set(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,const struct sensor_value * val)737 static inline int z_impl_sensor_attr_set(const struct device *dev,
738 enum sensor_channel chan,
739 enum sensor_attribute attr,
740 const struct sensor_value *val)
741 {
742 const struct sensor_driver_api *api =
743 (const struct sensor_driver_api *)dev->api;
744
745 if (api->attr_set == NULL) {
746 return -ENOSYS;
747 }
748
749 return api->attr_set(dev, chan, attr, val);
750 }
751
752 /**
753 * @brief Get an attribute for a sensor
754 *
755 * @param dev Pointer to the sensor device
756 * @param chan The channel the attribute belongs to, if any. Some
757 * attributes may only be set for all channels of a device, depending on
758 * device capabilities.
759 * @param attr The attribute to get
760 * @param val Pointer to where to store the attribute
761 *
762 * @return 0 if successful, negative errno code if failure.
763 */
764 __syscall int sensor_attr_get(const struct device *dev,
765 enum sensor_channel chan,
766 enum sensor_attribute attr,
767 struct sensor_value *val);
768
z_impl_sensor_attr_get(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,struct sensor_value * val)769 static inline int z_impl_sensor_attr_get(const struct device *dev,
770 enum sensor_channel chan,
771 enum sensor_attribute attr,
772 struct sensor_value *val)
773 {
774 const struct sensor_driver_api *api =
775 (const struct sensor_driver_api *)dev->api;
776
777 if (api->attr_get == NULL) {
778 return -ENOSYS;
779 }
780
781 return api->attr_get(dev, chan, attr, val);
782 }
783
784 /**
785 * @brief Activate a sensor's trigger and set the trigger handler
786 *
787 * The handler will be called from a thread, so I2C or SPI operations are
788 * safe. However, the thread's stack is limited and defined by the
789 * driver. It is currently up to the caller to ensure that the handler
790 * does not overflow the stack.
791 *
792 * The user-allocated trigger will be stored by the driver as a pointer, rather
793 * than a copy, and passed back to the handler. This enables the handler to use
794 * CONTAINER_OF to retrieve a context pointer when the trigger is embedded in a
795 * larger struct and requires that the trigger is not allocated on the stack.
796 *
797 * @funcprops \supervisor
798 *
799 * @param dev Pointer to the sensor device
800 * @param trig The trigger to activate
801 * @param handler The function that should be called when the trigger
802 * fires
803 *
804 * @return 0 if successful, negative errno code if failure.
805 */
sensor_trigger_set(const struct device * dev,const struct sensor_trigger * trig,sensor_trigger_handler_t handler)806 static inline int sensor_trigger_set(const struct device *dev,
807 const struct sensor_trigger *trig,
808 sensor_trigger_handler_t handler)
809 {
810 const struct sensor_driver_api *api =
811 (const struct sensor_driver_api *)dev->api;
812
813 if (api->trigger_set == NULL) {
814 return -ENOSYS;
815 }
816
817 return api->trigger_set(dev, trig, handler);
818 }
819
820 /**
821 * @brief Fetch a sample from the sensor and store it in an internal
822 * driver buffer
823 *
824 * Read all of a sensor's active channels and, if necessary, perform any
825 * additional operations necessary to make the values useful. The user
826 * may then get individual channel values by calling @ref
827 * sensor_channel_get.
828 *
829 * The function blocks until the fetch operation is complete.
830 *
831 * Since the function communicates with the sensor device, it is unsafe
832 * to call it in an ISR if the device is connected via I2C or SPI.
833 *
834 * @param dev Pointer to the sensor device
835 *
836 * @return 0 if successful, negative errno code if failure.
837 */
838 __syscall int sensor_sample_fetch(const struct device *dev);
839
z_impl_sensor_sample_fetch(const struct device * dev)840 static inline int z_impl_sensor_sample_fetch(const struct device *dev)
841 {
842 const struct sensor_driver_api *api =
843 (const struct sensor_driver_api *)dev->api;
844
845 return api->sample_fetch(dev, SENSOR_CHAN_ALL);
846 }
847
848 /**
849 * @brief Fetch a sample from the sensor and store it in an internal
850 * driver buffer
851 *
852 * Read and compute compensation for one type of sensor data (magnetometer,
853 * accelerometer, etc). The user may then get individual channel values by
854 * calling @ref sensor_channel_get.
855 *
856 * This is mostly implemented by multi function devices enabling reading at
857 * different sampling rates.
858 *
859 * The function blocks until the fetch operation is complete.
860 *
861 * Since the function communicates with the sensor device, it is unsafe
862 * to call it in an ISR if the device is connected via I2C or SPI.
863 *
864 * @param dev Pointer to the sensor device
865 * @param type The channel that needs updated
866 *
867 * @return 0 if successful, negative errno code if failure.
868 */
869 __syscall int sensor_sample_fetch_chan(const struct device *dev,
870 enum sensor_channel type);
871
z_impl_sensor_sample_fetch_chan(const struct device * dev,enum sensor_channel type)872 static inline int z_impl_sensor_sample_fetch_chan(const struct device *dev,
873 enum sensor_channel type)
874 {
875 const struct sensor_driver_api *api =
876 (const struct sensor_driver_api *)dev->api;
877
878 return api->sample_fetch(dev, type);
879 }
880
881 /**
882 * @brief Get a reading from a sensor device
883 *
884 * Return a useful value for a particular channel, from the driver's
885 * internal data. Before calling this function, a sample must be
886 * obtained by calling @ref sensor_sample_fetch or
887 * @ref sensor_sample_fetch_chan. It is guaranteed that two subsequent
888 * calls of this function for the same channels will yield the same
889 * value, if @ref sensor_sample_fetch or @ref sensor_sample_fetch_chan
890 * has not been called in the meantime.
891 *
892 * For vectorial data samples you can request all axes in just one call
893 * by passing the specific channel with _XYZ suffix. The sample will be
894 * returned at val[0], val[1] and val[2] (X, Y and Z in that order).
895 *
896 * @param dev Pointer to the sensor device
897 * @param chan The channel to read
898 * @param val Where to store the value
899 *
900 * @return 0 if successful, negative errno code if failure.
901 */
902 __syscall int sensor_channel_get(const struct device *dev,
903 enum sensor_channel chan,
904 struct sensor_value *val);
905
z_impl_sensor_channel_get(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)906 static inline int z_impl_sensor_channel_get(const struct device *dev,
907 enum sensor_channel chan,
908 struct sensor_value *val)
909 {
910 const struct sensor_driver_api *api =
911 (const struct sensor_driver_api *)dev->api;
912
913 return api->channel_get(dev, chan, val);
914 }
915
916 #if defined(CONFIG_SENSOR_ASYNC_API) || defined(__DOXYGEN__)
917
918 /*
919 * Generic data structure used for encoding the sample timestamp and number of channels sampled.
920 */
921 struct __attribute__((__packed__)) sensor_data_generic_header {
922 /* The timestamp at which the data was collected from the sensor */
923 uint64_t timestamp_ns;
924
925 /*
926 * The number of channels present in the frame. This will be the true number of elements in
927 * channel_info and in the q31 values that follow the header.
928 */
929 uint32_t num_channels;
930
931 /* Shift value for all samples in the frame */
932 int8_t shift;
933
934 /* This padding is needed to make sure that the 'channels' field is aligned */
935 int8_t _padding[sizeof(struct sensor_chan_spec) - 1];
936
937 /* Channels present in the frame */
938 struct sensor_chan_spec channels[0];
939 };
940
941 /**
942 * @brief checks if a given channel is a 3-axis channel
943 *
944 * @param[in] chan The channel to check
945 * @retval true if @p chan is any of @ref SENSOR_CHAN_ACCEL_XYZ, @ref SENSOR_CHAN_GYRO_XYZ, or
946 * @ref SENSOR_CHAN_MAGN_XYZ, or @ref SENSOR_CHAN_POS_DXYZ
947 * @retval false otherwise
948 */
949 #define SENSOR_CHANNEL_3_AXIS(chan) \
950 ((chan) == SENSOR_CHAN_ACCEL_XYZ || (chan) == SENSOR_CHAN_GYRO_XYZ || \
951 (chan) == SENSOR_CHAN_MAGN_XYZ || (chan) == SENSOR_CHAN_POS_DXYZ)
952
953 /**
954 * @brief checks if a given channel is an Accelerometer
955 *
956 * @param[in] chan The channel to check
957 * @retval true if @p chan is any of @ref SENSOR_CHAN_ACCEL_XYZ, @ref SENSOR_CHAN_ACCEL_X, or
958 * @ref SENSOR_CHAN_ACCEL_Y, or @ref SENSOR_CHAN_ACCEL_Z
959 * @retval false otherwise
960 */
961 #define SENSOR_CHANNEL_IS_ACCEL(chan) \
962 ((chan) == SENSOR_CHAN_ACCEL_XYZ || (chan) == SENSOR_CHAN_ACCEL_X || \
963 (chan) == SENSOR_CHAN_ACCEL_Y || (chan) == SENSOR_CHAN_ACCEL_Z)
964
965 /**
966 * @brief checks if a given channel is a Gyroscope
967 *
968 * @param[in] chan The channel to check
969 * @retval true if @p chan is any of @ref SENSOR_CHAN_GYRO_XYZ, @ref SENSOR_CHAN_GYRO_X, or
970 * @ref SENSOR_CHAN_GYRO_Y, or @ref SENSOR_CHAN_GYRO_Z
971 * @retval false otherwise
972 */
973 #define SENSOR_CHANNEL_IS_GYRO(chan) \
974 ((chan) == SENSOR_CHAN_GYRO_XYZ || (chan) == SENSOR_CHAN_GYRO_X || \
975 (chan) == SENSOR_CHAN_GYRO_Y || (chan) == SENSOR_CHAN_GYRO_Z)
976
977 /**
978 * @brief Get the sensor's decoder API
979 *
980 * @param[in] dev The sensor device
981 * @param[in] decoder Pointer to the decoder which will be set upon success
982 * @return 0 on success
983 * @return < 0 on error
984 */
985 __syscall int sensor_get_decoder(const struct device *dev,
986 const struct sensor_decoder_api **decoder);
987
z_impl_sensor_get_decoder(const struct device * dev,const struct sensor_decoder_api ** decoder)988 static inline int z_impl_sensor_get_decoder(const struct device *dev,
989 const struct sensor_decoder_api **decoder)
990 {
991 const struct sensor_driver_api *api = (const struct sensor_driver_api *)dev->api;
992
993 __ASSERT_NO_MSG(api != NULL);
994
995 if (api->get_decoder == NULL) {
996 *decoder = &__sensor_default_decoder;
997 return 0;
998 }
999
1000 return api->get_decoder(dev, decoder);
1001 }
1002
1003 /**
1004 * @brief Reconfigure a reading iodev
1005 *
1006 * Allows a reconfiguration of the iodev associated with reading a sample from a sensor.
1007 *
1008 * <b>Important</b>: If the iodev is currently servicing a read operation, the data will likely be
1009 * invalid. Please be sure the flush or wait for all pending operations to complete before using the
1010 * data after a configuration change.
1011 *
1012 * It is also important that the `data` field of the iodev is a @ref sensor_read_config.
1013 *
1014 * @param[in] iodev The iodev to reconfigure
1015 * @param[in] sensor The sensor to read from
1016 * @param[in] channels One or more channels to read
1017 * @param[in] num_channels The number of channels in @p channels
1018 * @return 0 on success
1019 * @return < 0 on error
1020 */
1021 __syscall int sensor_reconfigure_read_iodev(struct rtio_iodev *iodev, const struct device *sensor,
1022 const struct sensor_chan_spec *channels,
1023 size_t num_channels);
1024
z_impl_sensor_reconfigure_read_iodev(struct rtio_iodev * iodev,const struct device * sensor,const struct sensor_chan_spec * channels,size_t num_channels)1025 static inline int z_impl_sensor_reconfigure_read_iodev(struct rtio_iodev *iodev,
1026 const struct device *sensor,
1027 const struct sensor_chan_spec *channels,
1028 size_t num_channels)
1029 {
1030 struct sensor_read_config *cfg = (struct sensor_read_config *)iodev->data;
1031
1032 if (cfg->max < num_channels || cfg->is_streaming) {
1033 return -ENOMEM;
1034 }
1035
1036 cfg->sensor = sensor;
1037 memcpy(cfg->channels, channels, num_channels * sizeof(struct sensor_chan_spec));
1038 cfg->count = num_channels;
1039 return 0;
1040 }
1041
sensor_stream(struct rtio_iodev * iodev,struct rtio * ctx,void * userdata,struct rtio_sqe ** handle)1042 static inline int sensor_stream(struct rtio_iodev *iodev, struct rtio *ctx, void *userdata,
1043 struct rtio_sqe **handle)
1044 {
1045 if (IS_ENABLED(CONFIG_USERSPACE)) {
1046 struct rtio_sqe sqe;
1047
1048 rtio_sqe_prep_read_multishot(&sqe, iodev, RTIO_PRIO_NORM, userdata);
1049 rtio_sqe_copy_in_get_handles(ctx, &sqe, handle, 1);
1050 } else {
1051 struct rtio_sqe *sqe = rtio_sqe_acquire(ctx);
1052
1053 if (sqe == NULL) {
1054 return -ENOMEM;
1055 }
1056 if (handle != NULL) {
1057 *handle = sqe;
1058 }
1059 rtio_sqe_prep_read_multishot(sqe, iodev, RTIO_PRIO_NORM, userdata);
1060 }
1061 rtio_submit(ctx, 0);
1062 return 0;
1063 }
1064
1065 /**
1066 * @brief Blocking one shot read of samples from a sensor into a buffer
1067 *
1068 * Using @p cfg, read data from the device by using the provided RTIO context
1069 * @p ctx. This call will generate a @ref rtio_sqe that will be given the provided buffer. The call
1070 * will wait for the read to complete before returning to the caller.
1071 *
1072 * @param[in] iodev The iodev created by @ref SENSOR_DT_READ_IODEV
1073 * @param[in] ctx The RTIO context to service the read
1074 * @param[in] buf Pointer to memory to read sample data into
1075 * @param[in] buf_len Size in bytes of the given memory that are valid to read into
1076 * @return 0 on success
1077 * @return < 0 on error
1078 */
sensor_read(struct rtio_iodev * iodev,struct rtio * ctx,uint8_t * buf,size_t buf_len)1079 static inline int sensor_read(struct rtio_iodev *iodev, struct rtio *ctx, uint8_t *buf,
1080 size_t buf_len)
1081 {
1082 if (IS_ENABLED(CONFIG_USERSPACE)) {
1083 struct rtio_sqe sqe;
1084
1085 rtio_sqe_prep_read(&sqe, iodev, RTIO_PRIO_NORM, buf, buf_len, buf);
1086 rtio_sqe_copy_in(ctx, &sqe, 1);
1087 } else {
1088 struct rtio_sqe *sqe = rtio_sqe_acquire(ctx);
1089
1090 if (sqe == NULL) {
1091 return -ENOMEM;
1092 }
1093 rtio_sqe_prep_read(sqe, iodev, RTIO_PRIO_NORM, buf, buf_len, buf);
1094 }
1095 rtio_submit(ctx, 0);
1096
1097 struct rtio_cqe *cqe = rtio_cqe_consume_block(ctx);
1098 int res = cqe->result;
1099
1100 __ASSERT(cqe->userdata == buf,
1101 "consumed non-matching completion for sensor read into buffer %p\n", buf);
1102
1103 rtio_cqe_release(ctx, cqe);
1104
1105 return res;
1106 }
1107
1108 /**
1109 * @brief One shot non-blocking read with pool allocated buffer
1110 *
1111 * Using @p cfg, read one snapshot of data from the device by using the provided RTIO context
1112 * @p ctx. This call will generate a @ref rtio_sqe that will leverage the RTIO's internal
1113 * mempool when the time comes to service the read.
1114 *
1115 * @param[in] iodev The iodev created by @ref SENSOR_DT_READ_IODEV
1116 * @param[in] ctx The RTIO context to service the read
1117 * @param[in] userdata Optional userdata that will be available when the read is complete
1118 * @return 0 on success
1119 * @return < 0 on error
1120 */
sensor_read_async_mempool(struct rtio_iodev * iodev,struct rtio * ctx,void * userdata)1121 static inline int sensor_read_async_mempool(struct rtio_iodev *iodev, struct rtio *ctx,
1122 void *userdata)
1123 {
1124 if (IS_ENABLED(CONFIG_USERSPACE)) {
1125 struct rtio_sqe sqe;
1126
1127 rtio_sqe_prep_read_with_pool(&sqe, iodev, RTIO_PRIO_NORM, userdata);
1128 rtio_sqe_copy_in(ctx, &sqe, 1);
1129 } else {
1130 struct rtio_sqe *sqe = rtio_sqe_acquire(ctx);
1131
1132 if (sqe == NULL) {
1133 return -ENOMEM;
1134 }
1135 rtio_sqe_prep_read_with_pool(sqe, iodev, RTIO_PRIO_NORM, userdata);
1136 }
1137 rtio_submit(ctx, 0);
1138 return 0;
1139 }
1140
1141 /**
1142 * @typedef sensor_processing_callback_t
1143 * @brief Callback function used with the helper processing function.
1144 *
1145 * @see sensor_processing_with_callback
1146 *
1147 * @param[in] result The result code of the read (0 being success)
1148 * @param[in] buf The data buffer holding the sensor data
1149 * @param[in] buf_len The length (in bytes) of the @p buf
1150 * @param[in] userdata The optional userdata passed to sensor_read_async_mempool()
1151 */
1152 typedef void (*sensor_processing_callback_t)(int result, uint8_t *buf, uint32_t buf_len,
1153 void *userdata);
1154
1155 /**
1156 * @brief Helper function for common processing of sensor data.
1157 *
1158 * This function can be called in a blocking manner after sensor_read() or in a standalone
1159 * thread dedicated to processing. It will wait for a cqe from the RTIO context, once received, it
1160 * will decode the userdata and call the @p cb. Once the @p cb returns, the buffer will be released
1161 * back into @p ctx's mempool if available.
1162 *
1163 * @param[in] ctx The RTIO context to wait on
1164 * @param[in] cb Callback to call when data is ready for processing
1165 */
1166 void sensor_processing_with_callback(struct rtio *ctx, sensor_processing_callback_t cb);
1167
1168 #endif /* defined(CONFIG_SENSOR_ASYNC_API) || defined(__DOXYGEN__) */
1169
1170 /**
1171 * @brief The value of gravitational constant in micro m/s^2.
1172 */
1173 #define SENSOR_G 9806650LL
1174
1175 /**
1176 * @brief The value of constant PI in micros.
1177 */
1178 #define SENSOR_PI 3141592LL
1179
1180 /**
1181 * @brief Helper function to convert acceleration from m/s^2 to Gs
1182 *
1183 * @param ms2 A pointer to a sensor_value struct holding the acceleration,
1184 * in m/s^2.
1185 *
1186 * @return The converted value, in Gs.
1187 */
sensor_ms2_to_g(const struct sensor_value * ms2)1188 static inline int32_t sensor_ms2_to_g(const struct sensor_value *ms2)
1189 {
1190 int64_t micro_ms2 = ms2->val1 * 1000000LL + ms2->val2;
1191
1192 if (micro_ms2 > 0) {
1193 return (micro_ms2 + SENSOR_G / 2) / SENSOR_G;
1194 } else {
1195 return (micro_ms2 - SENSOR_G / 2) / SENSOR_G;
1196 }
1197 }
1198
1199 /**
1200 * @brief Helper function to convert acceleration from Gs to m/s^2
1201 *
1202 * @param g The G value to be converted.
1203 * @param ms2 A pointer to a sensor_value struct, where the result is stored.
1204 */
sensor_g_to_ms2(int32_t g,struct sensor_value * ms2)1205 static inline void sensor_g_to_ms2(int32_t g, struct sensor_value *ms2)
1206 {
1207 ms2->val1 = ((int64_t)g * SENSOR_G) / 1000000LL;
1208 ms2->val2 = ((int64_t)g * SENSOR_G) % 1000000LL;
1209 }
1210
1211 /**
1212 * @brief Helper function to convert acceleration from m/s^2 to milli Gs
1213 *
1214 * @param ms2 A pointer to a sensor_value struct holding the acceleration,
1215 * in m/s^2.
1216 *
1217 * @return The converted value, in milli Gs.
1218 */
sensor_ms2_to_mg(const struct sensor_value * ms2)1219 static inline int32_t sensor_ms2_to_mg(const struct sensor_value *ms2)
1220 {
1221 int64_t nano_ms2 = (ms2->val1 * 1000000LL + ms2->val2) * 1000LL;
1222
1223 if (nano_ms2 > 0) {
1224 return (nano_ms2 + SENSOR_G / 2) / SENSOR_G;
1225 } else {
1226 return (nano_ms2 - SENSOR_G / 2) / SENSOR_G;
1227 }
1228 }
1229
1230 /**
1231 * @brief Helper function to convert acceleration from m/s^2 to micro Gs
1232 *
1233 * @param ms2 A pointer to a sensor_value struct holding the acceleration,
1234 * in m/s^2.
1235 *
1236 * @return The converted value, in micro Gs.
1237 */
sensor_ms2_to_ug(const struct sensor_value * ms2)1238 static inline int32_t sensor_ms2_to_ug(const struct sensor_value *ms2)
1239 {
1240 int64_t micro_ms2 = (ms2->val1 * INT64_C(1000000)) + ms2->val2;
1241
1242 return (micro_ms2 * 1000000LL) / SENSOR_G;
1243 }
1244
1245 /**
1246 * @brief Helper function to convert acceleration from micro Gs to m/s^2
1247 *
1248 * @param ug The micro G value to be converted.
1249 * @param ms2 A pointer to a sensor_value struct, where the result is stored.
1250 */
sensor_ug_to_ms2(int32_t ug,struct sensor_value * ms2)1251 static inline void sensor_ug_to_ms2(int32_t ug, struct sensor_value *ms2)
1252 {
1253 ms2->val1 = ((int64_t)ug * SENSOR_G / 1000000LL) / 1000000LL;
1254 ms2->val2 = ((int64_t)ug * SENSOR_G / 1000000LL) % 1000000LL;
1255 }
1256
1257 /**
1258 * @brief Helper function for converting radians to degrees.
1259 *
1260 * @param rad A pointer to a sensor_value struct, holding the value in radians.
1261 *
1262 * @return The converted value, in degrees.
1263 */
sensor_rad_to_degrees(const struct sensor_value * rad)1264 static inline int32_t sensor_rad_to_degrees(const struct sensor_value *rad)
1265 {
1266 int64_t micro_rad_s = rad->val1 * 1000000LL + rad->val2;
1267
1268 if (micro_rad_s > 0) {
1269 return (micro_rad_s * 180LL + SENSOR_PI / 2) / SENSOR_PI;
1270 } else {
1271 return (micro_rad_s * 180LL - SENSOR_PI / 2) / SENSOR_PI;
1272 }
1273 }
1274
1275 /**
1276 * @brief Helper function for converting degrees to radians.
1277 *
1278 * @param d The value (in degrees) to be converted.
1279 * @param rad A pointer to a sensor_value struct, where the result is stored.
1280 */
sensor_degrees_to_rad(int32_t d,struct sensor_value * rad)1281 static inline void sensor_degrees_to_rad(int32_t d, struct sensor_value *rad)
1282 {
1283 rad->val1 = ((int64_t)d * SENSOR_PI / 180LL) / 1000000LL;
1284 rad->val2 = ((int64_t)d * SENSOR_PI / 180LL) % 1000000LL;
1285 }
1286
1287 /**
1288 * @brief Helper function for converting radians to 10 micro degrees.
1289 *
1290 * When the unit is 1 micro degree, the range that the int32_t can represent is
1291 * +/-2147.483 degrees. In order to increase this range, here we use 10 micro
1292 * degrees as the unit.
1293 *
1294 * @param rad A pointer to a sensor_value struct, holding the value in radians.
1295 *
1296 * @return The converted value, in 10 micro degrees.
1297 */
sensor_rad_to_10udegrees(const struct sensor_value * rad)1298 static inline int32_t sensor_rad_to_10udegrees(const struct sensor_value *rad)
1299 {
1300 int64_t micro_rad_s = rad->val1 * 1000000LL + rad->val2;
1301
1302 return (micro_rad_s * 180LL * 100000LL) / SENSOR_PI;
1303 }
1304
1305 /**
1306 * @brief Helper function for converting 10 micro degrees to radians.
1307 *
1308 * @param d The value (in 10 micro degrees) to be converted.
1309 * @param rad A pointer to a sensor_value struct, where the result is stored.
1310 */
sensor_10udegrees_to_rad(int32_t d,struct sensor_value * rad)1311 static inline void sensor_10udegrees_to_rad(int32_t d, struct sensor_value *rad)
1312 {
1313 rad->val1 = ((int64_t)d * SENSOR_PI / 180LL / 100000LL) / 1000000LL;
1314 rad->val2 = ((int64_t)d * SENSOR_PI / 180LL / 100000LL) % 1000000LL;
1315 }
1316
1317 /**
1318 * @brief Helper function for converting struct sensor_value to double.
1319 *
1320 * @param val A pointer to a sensor_value struct.
1321 * @return The converted value.
1322 */
sensor_value_to_double(const struct sensor_value * val)1323 static inline double sensor_value_to_double(const struct sensor_value *val)
1324 {
1325 return (double)val->val1 + (double)val->val2 / 1000000;
1326 }
1327
1328 /**
1329 * @brief Helper function for converting struct sensor_value to float.
1330 *
1331 * @param val A pointer to a sensor_value struct.
1332 * @return The converted value.
1333 */
sensor_value_to_float(const struct sensor_value * val)1334 static inline float sensor_value_to_float(const struct sensor_value *val)
1335 {
1336 return (float)val->val1 + (float)val->val2 / 1000000;
1337 }
1338
1339 /**
1340 * @brief Helper function for converting double to struct sensor_value.
1341 *
1342 * @param val A pointer to a sensor_value struct.
1343 * @param inp The converted value.
1344 * @return 0 if successful, negative errno code if failure.
1345 */
sensor_value_from_double(struct sensor_value * val,double inp)1346 static inline int sensor_value_from_double(struct sensor_value *val, double inp)
1347 {
1348 if (inp < INT32_MIN || inp > INT32_MAX) {
1349 return -ERANGE;
1350 }
1351
1352 double val2 = (inp - (int32_t)inp) * 1000000.0;
1353
1354 if (val2 < INT32_MIN || val2 > INT32_MAX) {
1355 return -ERANGE;
1356 }
1357
1358 val->val1 = (int32_t)inp;
1359 val->val2 = (int32_t)val2;
1360
1361 return 0;
1362 }
1363
1364 /**
1365 * @brief Helper function for converting float to struct sensor_value.
1366 *
1367 * @param val A pointer to a sensor_value struct.
1368 * @param inp The converted value.
1369 * @return 0 if successful, negative errno code if failure.
1370 */
sensor_value_from_float(struct sensor_value * val,float inp)1371 static inline int sensor_value_from_float(struct sensor_value *val, float inp)
1372 {
1373 float val2 = (inp - (int32_t)inp) * 1000000.0f;
1374
1375 if (val2 < INT32_MIN || val2 > (float)(INT32_MAX - 1)) {
1376 return -ERANGE;
1377 }
1378
1379 val->val1 = (int32_t)inp;
1380 val->val2 = (int32_t)val2;
1381
1382 return 0;
1383 }
1384
1385 #ifdef CONFIG_SENSOR_INFO
1386
1387 struct sensor_info {
1388 const struct device *dev;
1389 const char *vendor;
1390 const char *model;
1391 const char *friendly_name;
1392 };
1393
1394 #define SENSOR_INFO_INITIALIZER(_dev, _vendor, _model, _friendly_name) \
1395 { \
1396 .dev = _dev, \
1397 .vendor = _vendor, \
1398 .model = _model, \
1399 .friendly_name = _friendly_name, \
1400 }
1401
1402 #define SENSOR_INFO_DEFINE(name, ...) \
1403 static const STRUCT_SECTION_ITERABLE(sensor_info, name) = \
1404 SENSOR_INFO_INITIALIZER(__VA_ARGS__)
1405
1406 #define SENSOR_INFO_DT_NAME(node_id) \
1407 _CONCAT(__sensor_info, DEVICE_DT_NAME_GET(node_id))
1408
1409 #define SENSOR_INFO_DT_DEFINE(node_id) \
1410 SENSOR_INFO_DEFINE(SENSOR_INFO_DT_NAME(node_id), \
1411 DEVICE_DT_GET(node_id), \
1412 DT_NODE_VENDOR_OR(node_id, NULL), \
1413 DT_NODE_MODEL_OR(node_id, NULL), \
1414 DT_PROP_OR(node_id, friendly_name, NULL)) \
1415
1416 #else
1417
1418 #define SENSOR_INFO_DEFINE(name, ...)
1419 #define SENSOR_INFO_DT_DEFINE(node_id)
1420
1421 #endif /* CONFIG_SENSOR_INFO */
1422
1423 /**
1424 * @brief Like DEVICE_DT_DEFINE() with sensor specifics.
1425 *
1426 * @details Defines a device which implements the sensor API. May define an
1427 * element in the sensor info iterable section used to enumerate all sensor
1428 * devices.
1429 *
1430 * @param node_id The devicetree node identifier.
1431 *
1432 * @param init_fn Name of the init function of the driver.
1433 *
1434 * @param pm_device PM device resources reference (NULL if device does not use
1435 * PM).
1436 *
1437 * @param data_ptr Pointer to the device's private data.
1438 *
1439 * @param cfg_ptr The address to the structure containing the configuration
1440 * information for this instance of the driver.
1441 *
1442 * @param level The initialization level. See SYS_INIT() for details.
1443 *
1444 * @param prio Priority within the selected initialization level. See
1445 * SYS_INIT() for details.
1446 *
1447 * @param api_ptr Provides an initial pointer to the API function struct used
1448 * by the driver. Can be NULL.
1449 */
1450 #define SENSOR_DEVICE_DT_DEFINE(node_id, init_fn, pm_device, \
1451 data_ptr, cfg_ptr, level, prio, \
1452 api_ptr, ...) \
1453 DEVICE_DT_DEFINE(node_id, init_fn, pm_device, \
1454 data_ptr, cfg_ptr, level, prio, \
1455 api_ptr, __VA_ARGS__); \
1456 \
1457 SENSOR_INFO_DT_DEFINE(node_id);
1458
1459 /**
1460 * @brief Like SENSOR_DEVICE_DT_DEFINE() for an instance of a DT_DRV_COMPAT
1461 * compatible
1462 *
1463 * @param inst instance number. This is replaced by
1464 * <tt>DT_DRV_COMPAT(inst)</tt> in the call to SENSOR_DEVICE_DT_DEFINE().
1465 *
1466 * @param ... other parameters as expected by SENSOR_DEVICE_DT_DEFINE().
1467 */
1468 #define SENSOR_DEVICE_DT_INST_DEFINE(inst, ...) \
1469 SENSOR_DEVICE_DT_DEFINE(DT_DRV_INST(inst), __VA_ARGS__)
1470
1471 /**
1472 * @brief Helper function for converting struct sensor_value to integer milli units.
1473 *
1474 * @param val A pointer to a sensor_value struct.
1475 * @return The converted value.
1476 */
sensor_value_to_milli(const struct sensor_value * val)1477 static inline int64_t sensor_value_to_milli(const struct sensor_value *val)
1478 {
1479 return ((int64_t)val->val1 * 1000) + val->val2 / 1000;
1480 }
1481
1482 /**
1483 * @brief Helper function for converting struct sensor_value to integer micro units.
1484 *
1485 * @param val A pointer to a sensor_value struct.
1486 * @return The converted value.
1487 */
sensor_value_to_micro(const struct sensor_value * val)1488 static inline int64_t sensor_value_to_micro(const struct sensor_value *val)
1489 {
1490 return ((int64_t)val->val1 * 1000000) + val->val2;
1491 }
1492
1493 /**
1494 * @brief Helper function for converting integer milli units to struct sensor_value.
1495 *
1496 * @param val A pointer to a sensor_value struct.
1497 * @param milli The converted value.
1498 * @return 0 if successful, negative errno code if failure.
1499 */
sensor_value_from_milli(struct sensor_value * val,int64_t milli)1500 static inline int sensor_value_from_milli(struct sensor_value *val, int64_t milli)
1501 {
1502 if (milli < ((int64_t)INT32_MIN - 1) * 1000LL ||
1503 milli > ((int64_t)INT32_MAX + 1) * 1000LL) {
1504 return -ERANGE;
1505 }
1506
1507 val->val1 = (int32_t)(milli / 1000);
1508 val->val2 = (int32_t)(milli % 1000) * 1000;
1509
1510 return 0;
1511 }
1512
1513 /**
1514 * @brief Helper function for converting integer micro units to struct sensor_value.
1515 *
1516 * @param val A pointer to a sensor_value struct.
1517 * @param micro The converted value.
1518 * @return 0 if successful, negative errno code if failure.
1519 */
sensor_value_from_micro(struct sensor_value * val,int64_t micro)1520 static inline int sensor_value_from_micro(struct sensor_value *val, int64_t micro)
1521 {
1522 if (micro < ((int64_t)INT32_MIN - 1) * 1000000LL ||
1523 micro > ((int64_t)INT32_MAX + 1) * 1000000LL) {
1524 return -ERANGE;
1525 }
1526
1527 val->val1 = (int32_t)(micro / 1000000LL);
1528 val->val2 = (int32_t)(micro % 1000000LL);
1529
1530 return 0;
1531 }
1532
1533 /**
1534 * @}
1535 */
1536
1537 /**
1538 * @brief Get the decoder name for the current driver
1539 *
1540 * This function depends on `DT_DRV_COMPAT` being defined.
1541 */
1542 #define SENSOR_DECODER_NAME() UTIL_CAT(DT_DRV_COMPAT, __decoder_api)
1543
1544 /**
1545 * @brief Statically get the decoder for a given node
1546 *
1547 * @code{.c}
1548 * static const sensor_decoder_api *decoder = SENSOR_DECODER_DT_GET(DT_ALIAS(accel));
1549 * @endcode
1550 */
1551 #define SENSOR_DECODER_DT_GET(node_id) \
1552 &UTIL_CAT(DT_STRING_TOKEN_BY_IDX(node_id, compatible, 0), __decoder_api)
1553
1554 /**
1555 * @brief Define a decoder API
1556 *
1557 * This macro should be created once per compatible string of a sensor and will create a statically
1558 * referenceable decoder API.
1559 *
1560 * @code{.c}
1561 * SENSOR_DECODER_API_DT_DEFINE() = {
1562 * .get_frame_count = my_driver_get_frame_count,
1563 * .get_timestamp = my_driver_get_timestamp,
1564 * .get_shift = my_driver_get_shift,
1565 * .decode = my_driver_decode,
1566 * };
1567 * @endcode
1568 */
1569 #define SENSOR_DECODER_API_DT_DEFINE() \
1570 COND_CODE_1(DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT), (), (static)) \
1571 const STRUCT_SECTION_ITERABLE(sensor_decoder_api, SENSOR_DECODER_NAME())
1572
1573 #define Z_MAYBE_SENSOR_DECODER_DECLARE_INTERNAL_IDX(node_id, prop, idx) \
1574 extern const struct sensor_decoder_api UTIL_CAT( \
1575 DT_STRING_TOKEN_BY_IDX(node_id, prop, idx), __decoder_api);
1576
1577 #define Z_MAYBE_SENSOR_DECODER_DECLARE_INTERNAL(node_id) \
1578 COND_CODE_1(DT_NODE_HAS_PROP(node_id, compatible), \
1579 (DT_FOREACH_PROP_ELEM(node_id, compatible, \
1580 Z_MAYBE_SENSOR_DECODER_DECLARE_INTERNAL_IDX)), \
1581 ())
1582
1583 DT_FOREACH_STATUS_OKAY_NODE(Z_MAYBE_SENSOR_DECODER_DECLARE_INTERNAL)
1584
1585 #ifdef __cplusplus
1586 }
1587 #endif
1588
1589 #include <zephyr/syscalls/sensor.h>
1590
1591 #endif /* ZEPHYR_INCLUDE_DRIVERS_SENSOR_H_ */
1592