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