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