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