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