1 /*
2  * Copyright (c) 2023 Google LLC
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef ZEPHYR_INCLUDE_DRIVERS_SENSOR_DATA_TYPES_H
8 #define ZEPHYR_INCLUDE_DRIVERS_SENSOR_DATA_TYPES_H
9 
10 #include <zephyr/dsp/types.h>
11 #include <zephyr/dsp/print_format.h>
12 
13 #include <inttypes.h>
14 
15 #ifdef __cplusplus
16 extern "C" {
17 #endif
18 
19 struct sensor_data_header {
20 	/**
21 	 * The closest timestamp for when the first frame was generated as attained by
22 	 * :c:func:`k_uptime_ticks`.
23 	 */
24 	uint64_t base_timestamp_ns;
25 	/**
26 	 * The number of elements in the 'readings' array.
27 	 *
28 	 * This must be at least 1
29 	 */
30 	uint16_t reading_count;
31 };
32 
33 /**
34  * Data for a sensor channel which reports on three axes. This is used by:
35  * - :c:enum:`SENSOR_CHAN_ACCEL_X`
36  * - :c:enum:`SENSOR_CHAN_ACCEL_Y`
37  * - :c:enum:`SENSOR_CHAN_ACCEL_Z`
38  * - :c:enum:`SENSOR_CHAN_ACCEL_XYZ`
39  * - :c:enum:`SENSOR_CHAN_GYRO_X`
40  * - :c:enum:`SENSOR_CHAN_GYRO_Y`
41  * - :c:enum:`SENSOR_CHAN_GYRO_Z`
42  * - :c:enum:`SENSOR_CHAN_GYRO_XYZ`
43  * - :c:enum:`SENSOR_CHAN_MAGN_X`
44  * - :c:enum:`SENSOR_CHAN_MAGN_Y`
45  * - :c:enum:`SENSOR_CHAN_MAGN_Z`
46  * - :c:enum:`SENSOR_CHAN_MAGN_XYZ`
47  * - :c:enum:`SENSOR_CHAN_POS_DX`
48  * - :c:enum:`SENSOR_CHAN_POS_DY`
49  * - :c:enum:`SENSOR_CHAN_POS_DZ`
50  * - :c:enum:`SENSOR_CHAN_POS_DXYZ`
51  */
52 struct sensor_three_axis_data {
53 	struct sensor_data_header header;
54 	int8_t shift;
55 	struct sensor_three_axis_sample_data {
56 		uint32_t timestamp_delta;
57 		union {
58 			q31_t values[3];
59 			q31_t v[3];
60 			struct {
61 				q31_t x;
62 				q31_t y;
63 				q31_t z;
64 			};
65 		};
66 	} readings[1];
67 };
68 
69 #define PRIsensor_three_axis_data PRIu64 "ns, (%" PRIq(6) ", %" PRIq(6) ", %" PRIq(6) ")"
70 
71 #define PRIsensor_three_axis_data_arg(data_, readings_offset_)                                     \
72 	(data_).header.base_timestamp_ns + (data_).readings[(readings_offset_)].timestamp_delta,   \
73 		PRIq_arg((data_).readings[(readings_offset_)].x, 6, (data_).shift),                \
74 		PRIq_arg((data_).readings[(readings_offset_)].y, 6, (data_).shift),                \
75 		PRIq_arg((data_).readings[(readings_offset_)].z, 6, (data_).shift)
76 
77 /**
78  * Data for a sensor channel which reports game rotation vector data. This is used by:
79  * - :c:enum:`SENSOR_CHAN_GAME_ROTATION_VECTOR`
80  */
81 struct sensor_game_rotation_vector_data {
82 	struct sensor_data_header header;
83 	int8_t shift;
84 	struct sensor_game_rotation_vector_sample_data {
85 		uint32_t timestamp_delta;
86 		union {
87 			q31_t values[4];
88 			q31_t v[4];
89 			struct {
90 				q31_t x;
91 				q31_t y;
92 				q31_t z;
93 				q31_t w;
94 			};
95 		};
96 	} readings[1];
97 };
98 
99 #define PRIsensor_game_rotation_vector_data PRIu64                                                 \
100 	"ns, (%" PRIq(6) ", %" PRIq(6) ", %" PRIq(6)  ", %" PRIq(6) ")"
101 
102 #define PRIsensor_game_rotation_vector_data_arg(data_, readings_offset_)                           \
103 	(data_).header.base_timestamp_ns + (data_).readings[(readings_offset_)].timestamp_delta,   \
104 		PRIq_arg((data_).readings[(readings_offset_)].x, 6, (data_).shift),                \
105 		PRIq_arg((data_).readings[(readings_offset_)].y, 6, (data_).shift),                \
106 		PRIq_arg((data_).readings[(readings_offset_)].z, 6, (data_).shift),                \
107 		PRIq_arg((data_).readings[(readings_offset_)].w, 6, (data_).shift)
108 
109 /**
110  * Data from a sensor where we only care about an event occurring. This is used to report triggers.
111  */
112 struct sensor_occurrence_data {
113 	struct sensor_data_header header;
114 	struct sensor_occurrence_sample_data {
115 		uint32_t timestamp_delta;
116 	} readings[1];
117 };
118 
119 #define PRIsensor_occurrence_data PRIu64 "ns"
120 
121 #define PRIsensor_occurrence_data_arg(data_, readings_offset_)                                     \
122 	(data_).header.base_timestamp_ns + (data_).readings[(readings_offset_)].timestamp_delta
123 
124 struct sensor_q31_data {
125 	struct sensor_data_header header;
126 	int8_t shift;
127 	struct sensor_q31_sample_data {
128 		uint32_t timestamp_delta;
129 		union {
130 			q31_t value;
131 			q31_t light;           /**< Unit: lux */
132 			q31_t pressure;        /**< Unit: kilopascal */
133 			q31_t temperature;     /**< Unit: degrees Celsius */
134 			q31_t percent;         /**< Unit: percent */
135 			q31_t distance;        /**< Unit: meters */
136 			q31_t density;         /**< Unit: ug/m^3 */
137 			q31_t density_ppm;     /**< Unit: parts per million */
138 			q31_t density_ppb;     /**< Unit: parts per billion */
139 			q31_t resistance;      /**< Unit: ohms */
140 			q31_t voltage;         /**< Unit: volts */
141 			q31_t current;         /**< Unit: amps */
142 			q31_t power;           /**< Unit: watts */
143 			q31_t angle;           /**< Unit: degrees */
144 			q31_t electric_charge; /**< Unit: mAh */
145 			q31_t humidity;        /**< Unit: RH */
146 		};
147 	} readings[1];
148 };
149 
150 #define PRIsensor_q31_data PRIu64 "ns (%" PRIq(6) ")"
151 
152 #define PRIsensor_q31_data_arg(data_, readings_offset_)                                            \
153 	(data_).header.base_timestamp_ns + (data_).readings[(readings_offset_)].timestamp_delta,   \
154 		PRIq_arg((data_).readings[(readings_offset_)].value, 6, (data_).shift)
155 
156 /**
157  * Data from a sensor that produces a byte of data. This is used by:
158  * - :c:enum:`SENSOR_CHAN_PROX`
159  */
160 struct sensor_byte_data {
161 	struct sensor_data_header header;
162 	struct sensor_byte_sample_data {
163 		uint32_t timestamp_delta;
164 		union {
165 			uint8_t value;
166 			struct {
167 				uint8_t is_near: 1;
168 				uint8_t padding: 7;
169 			};
170 		};
171 	} readings[1];
172 };
173 
174 #define PRIsensor_byte_data(field_name_) PRIu64 "ns (" STRINGIFY(field_name_) " = %" PRIu8 ")"
175 
176 #define PRIsensor_byte_data_arg(data_, readings_offset_, field_name_)                              \
177 	(data_).header.base_timestamp_ns + (data_).readings[(readings_offset_)].timestamp_delta,   \
178 		(data_).readings[(readings_offset_)].field_name_
179 
180 /**
181  * Data from a sensor that produces a count like value. This is used by:
182  * - :c:enum:`SENSOR_CHAN_GAUGE_CYCLE_COUNT`
183  */
184 struct sensor_uint64_data {
185 	struct sensor_data_header header;
186 	struct sensor_uint64_sample_data {
187 		uint32_t timestamp_delta;
188 		uint64_t value;
189 	} readings[1];
190 };
191 
192 #define PRIsensor_uint64_data PRIu64 "ns (%" PRIu64 ")"
193 
194 #define PRIsensor_uint64_data_arg(data_, readings_offset_)                                         \
195 	(data_).header.base_timestamp_ns + (data_).readings[(readings_offset_)].timestamp_delta,   \
196 		(data_).readings[(readings_offset_)].value
197 
198 #ifdef __cplusplus
199 }
200 #endif
201 
202 #endif /* ZEPHYR_INCLUDE_DRIVERS_SENSOR_DATA_TYPES_H */
203