1 /*
2  * Copyright (c) 2022 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef ZEPHYR_DRIVERS_SENSOR_ICM42688_H_
8 #define ZEPHYR_DRIVERS_SENSOR_ICM42688_H_
9 
10 #include <zephyr/drivers/gpio.h>
11 #include <zephyr/drivers/sensor.h>
12 #include <zephyr/drivers/spi.h>
13 #include <zephyr/sys/byteorder.h>
14 #include <stdlib.h>
15 
16 /**
17  * @brief Accelerometer power modes
18  */
19 enum icm42688_accel_mode {
20 	ICM42688_ACCEL_OFF,
21 	ICM42688_ACCEL_LP = 2,
22 	ICM42688_ACCEL_LN = 3,
23 };
24 
25 /**
26  * @brief Gyroscope power modes
27  */
28 enum icm42688_gyro_mode {
29 	ICM42688_GYRO_OFF,
30 	ICM42688_GYRO_STANDBY,
31 	ICM42688_GYRO_LN = 3,
32 };
33 
34 /**
35  * @brief Accelerometer scale options
36  */
37 enum icm42688_accel_fs {
38 	ICM42688_ACCEL_FS_16G,
39 	ICM42688_ACCEL_FS_8G,
40 	ICM42688_ACCEL_FS_4G,
41 	ICM42688_ACCEL_FS_2G,
42 };
43 
icm42688_accel_fs_to_reg(uint8_t g)44 static inline enum icm42688_accel_fs icm42688_accel_fs_to_reg(uint8_t g)
45 {
46 	if (g >= 16) {
47 		return ICM42688_ACCEL_FS_16G;
48 	} else if (g >= 8) {
49 		return ICM42688_ACCEL_FS_8G;
50 	} else if (g >= 4) {
51 		return ICM42688_ACCEL_FS_4G;
52 	} else {
53 		return ICM42688_ACCEL_FS_2G;
54 	}
55 }
56 
icm42688_accel_reg_to_fs(enum icm42688_accel_fs fs,struct sensor_value * out)57 static inline void icm42688_accel_reg_to_fs(enum icm42688_accel_fs fs, struct sensor_value *out)
58 {
59 	switch (fs) {
60 	case ICM42688_ACCEL_FS_16G:
61 		sensor_g_to_ms2(16, out);
62 		return;
63 	case ICM42688_ACCEL_FS_8G:
64 		sensor_g_to_ms2(8, out);
65 		return;
66 	case ICM42688_ACCEL_FS_4G:
67 		sensor_g_to_ms2(4, out);
68 		return;
69 	case ICM42688_ACCEL_FS_2G:
70 		sensor_g_to_ms2(2, out);
71 		return;
72 	}
73 }
74 
75 /**
76  * @brief Gyroscope scale options
77  */
78 enum icm42688_gyro_fs {
79 	ICM42688_GYRO_FS_2000,
80 	ICM42688_GYRO_FS_1000,
81 	ICM42688_GYRO_FS_500,
82 	ICM42688_GYRO_FS_250,
83 	ICM42688_GYRO_FS_125,
84 	ICM42688_GYRO_FS_62_5,
85 	ICM42688_GYRO_FS_31_25,
86 	ICM42688_GYRO_FS_15_625,
87 };
88 
icm42688_gyro_fs_to_reg(uint16_t dps)89 static inline enum icm42688_gyro_fs icm42688_gyro_fs_to_reg(uint16_t dps)
90 {
91 	if (dps >= 2000) {
92 		return ICM42688_GYRO_FS_2000;
93 	} else if (dps >= 1000) {
94 		return ICM42688_GYRO_FS_1000;
95 	} else if (dps >= 500) {
96 		return ICM42688_GYRO_FS_500;
97 	} else if (dps >= 250) {
98 		return ICM42688_GYRO_FS_250;
99 	} else if (dps >= 125) {
100 		return ICM42688_GYRO_FS_125;
101 	} else if (dps >= 62) {
102 		return ICM42688_GYRO_FS_62_5;
103 	} else if (dps >= 31) {
104 		return ICM42688_GYRO_FS_31_25;
105 	} else {
106 		return ICM42688_GYRO_FS_15_625;
107 	}
108 }
109 
icm42688_gyro_reg_to_fs(enum icm42688_gyro_fs fs,struct sensor_value * out)110 static inline void icm42688_gyro_reg_to_fs(enum icm42688_gyro_fs fs, struct sensor_value *out)
111 {
112 	switch (fs) {
113 	case ICM42688_GYRO_FS_2000:
114 		sensor_degrees_to_rad(2000, out);
115 		return;
116 	case ICM42688_GYRO_FS_1000:
117 		sensor_degrees_to_rad(1000, out);
118 		return;
119 	case ICM42688_GYRO_FS_500:
120 		sensor_degrees_to_rad(500, out);
121 		return;
122 	case ICM42688_GYRO_FS_250:
123 		sensor_degrees_to_rad(250, out);
124 		return;
125 	case ICM42688_GYRO_FS_125:
126 		sensor_degrees_to_rad(125, out);
127 		return;
128 	case ICM42688_GYRO_FS_62_5:
129 		sensor_10udegrees_to_rad(6250000, out);
130 		return;
131 	case ICM42688_GYRO_FS_31_25:
132 		sensor_10udegrees_to_rad(3125000, out);
133 		return;
134 	case ICM42688_GYRO_FS_15_625:
135 		sensor_10udegrees_to_rad(1562500, out);
136 		return;
137 	}
138 }
139 
140 /**
141  * @brief Accelerometer data rate options
142  */
143 enum icm42688_accel_odr {
144 	ICM42688_ACCEL_ODR_32000 = 1,
145 	ICM42688_ACCEL_ODR_16000,
146 	ICM42688_ACCEL_ODR_8000,
147 	ICM42688_ACCEL_ODR_4000,
148 	ICM42688_ACCEL_ODR_2000,
149 	ICM42688_ACCEL_ODR_1000,
150 	ICM42688_ACCEL_ODR_200,
151 	ICM42688_ACCEL_ODR_100,
152 	ICM42688_ACCEL_ODR_50,
153 	ICM42688_ACCEL_ODR_25,
154 	ICM42688_ACCEL_ODR_12_5,
155 	ICM42688_ACCEL_ODR_6_25,
156 	ICM42688_ACCEL_ODR_3_125,
157 	ICM42688_ACCEL_ODR_1_5625,
158 	ICM42688_ACCEL_ODR_500,
159 };
160 
icm42688_accel_hz_to_reg(uint16_t hz)161 static inline enum icm42688_accel_odr icm42688_accel_hz_to_reg(uint16_t hz)
162 {
163 	if (hz >= 32000) {
164 		return ICM42688_ACCEL_ODR_32000;
165 	} else if (hz >= 16000) {
166 		return ICM42688_ACCEL_ODR_16000;
167 	} else if (hz >= 8000) {
168 		return ICM42688_ACCEL_ODR_8000;
169 	} else if (hz >= 4000) {
170 		return ICM42688_ACCEL_ODR_4000;
171 	} else if (hz >= 2000) {
172 		return ICM42688_ACCEL_ODR_2000;
173 	} else if (hz >= 1000) {
174 		return ICM42688_ACCEL_ODR_1000;
175 	} else if (hz >= 500) {
176 		return ICM42688_ACCEL_ODR_500;
177 	} else if (hz >= 200) {
178 		return ICM42688_ACCEL_ODR_200;
179 	} else if (hz >= 100) {
180 		return ICM42688_ACCEL_ODR_100;
181 	} else if (hz >= 50) {
182 		return ICM42688_ACCEL_ODR_50;
183 	} else if (hz >= 25) {
184 		return ICM42688_ACCEL_ODR_25;
185 	} else if (hz >= 12) {
186 		return ICM42688_ACCEL_ODR_12_5;
187 	} else if (hz >= 6) {
188 		return ICM42688_ACCEL_ODR_6_25;
189 	} else if (hz >= 3) {
190 		return ICM42688_ACCEL_ODR_3_125;
191 	} else {
192 		return ICM42688_ACCEL_ODR_1_5625;
193 	}
194 }
195 
icm42688_accel_reg_to_hz(enum icm42688_accel_odr odr,struct sensor_value * out)196 static inline void icm42688_accel_reg_to_hz(enum icm42688_accel_odr odr, struct sensor_value *out)
197 {
198 	switch (odr) {
199 	case ICM42688_ACCEL_ODR_32000:
200 		out->val1 = 32000;
201 		out->val2 = 0;
202 		return;
203 	case ICM42688_ACCEL_ODR_16000:
204 		out->val1 = 1600;
205 		out->val2 = 0;
206 		return;
207 	case ICM42688_ACCEL_ODR_8000:
208 		out->val1 = 8000;
209 		out->val2 = 0;
210 		return;
211 	case ICM42688_ACCEL_ODR_4000:
212 		out->val1 = 4000;
213 		out->val2 = 0;
214 		return;
215 	case ICM42688_ACCEL_ODR_2000:
216 		out->val1 = 2000;
217 		out->val2 = 0;
218 		return;
219 	case ICM42688_ACCEL_ODR_1000:
220 		out->val1 = 1000;
221 		out->val2 = 0;
222 		return;
223 	case ICM42688_ACCEL_ODR_500:
224 		out->val1 = 500;
225 		out->val2 = 0;
226 		return;
227 	case ICM42688_ACCEL_ODR_200:
228 		out->val1 = 200;
229 		out->val2 = 0;
230 		return;
231 	case ICM42688_ACCEL_ODR_100:
232 		out->val1 = 100;
233 		out->val2 = 0;
234 		return;
235 	case ICM42688_ACCEL_ODR_50:
236 		out->val1 = 50;
237 		out->val2 = 0;
238 		return;
239 	case ICM42688_ACCEL_ODR_25:
240 		out->val1 = 25;
241 		out->val2 = 0;
242 		return;
243 	case ICM42688_ACCEL_ODR_12_5:
244 		out->val1 = 12;
245 		out->val2 = 500000;
246 		return;
247 	case ICM42688_ACCEL_ODR_6_25:
248 		out->val1 = 6;
249 		out->val2 = 250000;
250 		return;
251 	case ICM42688_ACCEL_ODR_3_125:
252 		out->val1 = 3;
253 		out->val2 = 125000;
254 		return;
255 	case ICM42688_ACCEL_ODR_1_5625:
256 		out->val1 = 1;
257 		out->val2 = 562500;
258 		return;
259 	}
260 }
261 
262 /**
263  * @brief Gyroscope data rate options
264  */
265 enum icm42688_gyro_odr {
266 	ICM42688_GYRO_ODR_32000 = 1,
267 	ICM42688_GYRO_ODR_16000,
268 	ICM42688_GYRO_ODR_8000,
269 	ICM42688_GYRO_ODR_4000,
270 	ICM42688_GYRO_ODR_2000,
271 	ICM42688_GYRO_ODR_1000,
272 	ICM42688_GYRO_ODR_200,
273 	ICM42688_GYRO_ODR_100,
274 	ICM42688_GYRO_ODR_50,
275 	ICM42688_GYRO_ODR_25,
276 	ICM42688_GYRO_ODR_12_5,
277 	ICM42688_GYRO_ODR_500 = 0xF
278 };
279 
icm42688_gyro_odr_to_reg(uint16_t hz)280 static inline enum icm42688_gyro_odr icm42688_gyro_odr_to_reg(uint16_t hz)
281 {
282 	if (hz >= 32000) {
283 		return ICM42688_GYRO_ODR_32000;
284 	} else if (hz >= 16000) {
285 		return ICM42688_GYRO_ODR_16000;
286 	} else if (hz >= 8000) {
287 		return ICM42688_GYRO_ODR_8000;
288 	} else if (hz >= 4000) {
289 		return ICM42688_GYRO_ODR_4000;
290 	} else if (hz >= 2000) {
291 		return ICM42688_GYRO_ODR_2000;
292 	} else if (hz >= 1000) {
293 		return ICM42688_GYRO_ODR_1000;
294 	} else if (hz >= 500) {
295 		return ICM42688_GYRO_ODR_500;
296 	} else if (hz >= 200) {
297 		return ICM42688_GYRO_ODR_200;
298 	} else if (hz >= 100) {
299 		return ICM42688_GYRO_ODR_100;
300 	} else if (hz >= 50) {
301 		return ICM42688_GYRO_ODR_50;
302 	} else if (hz >= 25) {
303 		return ICM42688_GYRO_ODR_25;
304 	} else {
305 		return ICM42688_GYRO_ODR_12_5;
306 	}
307 }
308 
icm42688_gyro_reg_to_odr(enum icm42688_gyro_odr odr,struct sensor_value * out)309 static inline void icm42688_gyro_reg_to_odr(enum icm42688_gyro_odr odr, struct sensor_value *out)
310 {
311 	switch (odr) {
312 	case ICM42688_GYRO_ODR_32000:
313 		out->val1 = 32000;
314 		out->val2 = 0;
315 		return;
316 	case ICM42688_GYRO_ODR_16000:
317 		out->val1 = 16000;
318 		out->val2 = 0;
319 		return;
320 	case ICM42688_GYRO_ODR_8000:
321 		out->val1 = 8000;
322 		out->val2 = 0;
323 		return;
324 	case ICM42688_GYRO_ODR_4000:
325 		out->val1 = 4000;
326 		out->val2 = 0;
327 		return;
328 	case ICM42688_GYRO_ODR_2000:
329 		out->val1 = 2000;
330 		out->val2 = 0;
331 		return;
332 	case ICM42688_GYRO_ODR_1000:
333 		out->val1 = 1000;
334 		out->val2 = 0;
335 		return;
336 	case ICM42688_GYRO_ODR_500:
337 		out->val1 = 500;
338 		out->val2 = 0;
339 		return;
340 	case ICM42688_GYRO_ODR_200:
341 		out->val1 = 200;
342 		out->val2 = 0;
343 		return;
344 	case ICM42688_GYRO_ODR_100:
345 		out->val1 = 100;
346 		out->val2 = 0;
347 		return;
348 	case ICM42688_GYRO_ODR_50:
349 		out->val1 = 50;
350 		out->val2 = 0;
351 		return;
352 	case ICM42688_GYRO_ODR_25:
353 		out->val1 = 25;
354 		out->val2 = 0;
355 		return;
356 	case ICM42688_GYRO_ODR_12_5:
357 		out->val1 = 12;
358 		out->val2 = 500000;
359 		return;
360 	}
361 }
362 
363 /**
364  * @brief All sensor configuration options
365  */
366 struct icm42688_cfg {
367 	enum icm42688_accel_mode accel_mode;
368 	enum icm42688_accel_fs accel_fs;
369 	enum icm42688_accel_odr accel_odr;
370 	/* TODO accel signal processing options */
371 
372 	enum icm42688_gyro_mode gyro_mode;
373 	enum icm42688_gyro_fs gyro_fs;
374 	enum icm42688_gyro_odr gyro_odr;
375 	/* TODO gyro signal processing options */
376 
377 	bool temp_dis;
378 	/* TODO temp signal processing options */
379 
380 	/* TODO timestamp options */
381 
382 	bool fifo_en;
383 	int32_t batch_ticks;
384 	bool fifo_hires;
385 	/* TODO additional FIFO options */
386 
387 	/* TODO interrupt options */
388 	bool interrupt1_drdy;
389 	bool interrupt1_fifo_ths;
390 	bool interrupt1_fifo_full;
391 };
392 
393 struct icm42688_trigger_entry {
394 	struct sensor_trigger trigger;
395 	sensor_trigger_handler_t handler;
396 };
397 
398 /**
399  * @brief Device data (struct device)
400  */
401 struct icm42688_dev_data {
402 	struct icm42688_cfg cfg;
403 #ifdef CONFIG_ICM42688_TRIGGER
404 #if defined(CONFIG_ICM42688_TRIGGER_OWN_THREAD)
405 	K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_ICM42688_THREAD_STACK_SIZE);
406 	struct k_thread thread;
407 	struct k_sem gpio_sem;
408 #elif defined(CONFIG_ICM42688_TRIGGER_GLOBAL_THREAD)
409 	struct k_work work;
410 #endif
411 #ifdef CONFIG_ICM42688_STREAM
412 	struct rtio_iodev_sqe *streaming_sqe;
413 	struct rtio *r;
414 	struct rtio_iodev *spi_iodev;
415 	uint8_t int_status;
416 	uint16_t fifo_count;
417 	uint64_t timestamp;
418 	atomic_t reading_fifo;
419 #endif /* CONFIG_ICM42688_STREAM */
420 	const struct device *dev;
421 	struct gpio_callback gpio_cb;
422 	sensor_trigger_handler_t data_ready_handler;
423 	const struct sensor_trigger *data_ready_trigger;
424 	struct k_mutex mutex;
425 #endif /* CONFIG_ICM42688_TRIGGER */
426 
427 	int16_t readings[7];
428 };
429 
430 /**
431  * @brief Device config (struct device)
432  */
433 struct icm42688_dev_cfg {
434 	struct spi_dt_spec spi;
435 	struct gpio_dt_spec gpio_int1;
436 	struct gpio_dt_spec gpio_int2;
437 };
438 
439 /**
440  * @brief Reset the sensor
441  *
442  * @param dev icm42688 device pointer
443  *
444  * @retval 0 success
445  * @retval -EINVAL Reset status or whoami register returned unexpected value.
446  */
447 int icm42688_reset(const struct device *dev);
448 
449 /**
450  * @brief (Re)Configure the sensor with the given configuration
451  *
452  * @param dev icm42688 device pointer
453  * @param cfg icm42688_cfg pointer
454  *
455  * @retval 0 success
456  * @retval -errno Error
457  */
458 int icm42688_configure(const struct device *dev, struct icm42688_cfg *cfg);
459 
460 
461 /**
462  * @brief Safely (re)Configure the sensor with the given configuration
463  *
464  * Will rollback to prior configuration if new configuration is invalid
465  *
466  * @param dev icm42688 device pointer
467  * @param cfg icm42688_cfg pointer
468  *
469  * @retval 0 success
470  * @retval -errno Error
471  */
472 int icm42688_safely_configure(const struct device *dev, struct icm42688_cfg *cfg);
473 
474 /**
475  * @brief Reads all channels
476  *
477  * Regardless of what is enabled/disabled this reads all data registers
478  * as the time to read the 14 bytes at 1MHz is going to be 112 us which
479  * is less time than a SPI transaction takes to setup typically.
480  *
481  * @param dev icm42688 device pointer
482  * @param buf 14 byte buffer to store data values (7 channels, 2 bytes each)
483  *
484  * @retval 0 success
485  * @retval -errno Error
486  */
487 int icm42688_read_all(const struct device *dev, uint8_t data[14]);
488 
489 /**
490  * @brief Convert icm42688 accelerometer value to useful g values
491  *
492  * @param cfg icm42688_cfg current device configuration
493  * @param in raw data value in int32_t format
494  * @param out_g whole G's output in int32_t
495  * @param out_ug micro (1/1000000) of a G output as uint32_t
496  */
icm42688_accel_g(struct icm42688_cfg * cfg,int32_t in,int32_t * out_g,uint32_t * out_ug)497 static inline void icm42688_accel_g(struct icm42688_cfg *cfg, int32_t in, int32_t *out_g,
498 				    uint32_t *out_ug)
499 {
500 	int32_t sensitivity = 0; /* value equivalent for 1g */
501 
502 	switch (cfg->accel_fs) {
503 	case ICM42688_ACCEL_FS_2G:
504 		sensitivity = 16384;
505 		break;
506 	case ICM42688_ACCEL_FS_4G:
507 		sensitivity = 8192;
508 		break;
509 	case ICM42688_ACCEL_FS_8G:
510 		sensitivity = 4096;
511 		break;
512 	case ICM42688_ACCEL_FS_16G:
513 		sensitivity = 2048;
514 		break;
515 	}
516 
517 	/* Whole g's */
518 	*out_g = in / sensitivity;
519 
520 	/* Micro g's */
521 	*out_ug = ((abs(in) - (abs((*out_g)) * sensitivity)) * 1000000) / sensitivity;
522 }
523 
524 /**
525  * @brief Convert icm42688 gyroscope value to useful deg/s values
526  *
527  * @param cfg icm42688_cfg current device configuration
528  * @param in raw data value in int32_t format
529  * @param out_dps whole deg/s output in int32_t
530  * @param out_udps micro (1/1000000) deg/s as uint32_t
531  */
icm42688_gyro_dps(const struct icm42688_cfg * cfg,int32_t in,int32_t * out_dps,uint32_t * out_udps)532 static inline void icm42688_gyro_dps(const struct icm42688_cfg *cfg, int32_t in, int32_t *out_dps,
533 				     uint32_t *out_udps)
534 {
535 	int64_t sensitivity = 0; /* value equivalent for 10x gyro reading deg/s */
536 
537 	switch (cfg->gyro_fs) {
538 	case ICM42688_GYRO_FS_2000:
539 		sensitivity = 164;
540 		break;
541 	case ICM42688_GYRO_FS_1000:
542 		sensitivity = 328;
543 		break;
544 	case ICM42688_GYRO_FS_500:
545 		sensitivity = 655;
546 		break;
547 	case ICM42688_GYRO_FS_250:
548 		sensitivity = 1310;
549 		break;
550 	case ICM42688_GYRO_FS_125:
551 		sensitivity = 2620;
552 		break;
553 	case ICM42688_GYRO_FS_62_5:
554 		sensitivity = 5243;
555 		break;
556 	case ICM42688_GYRO_FS_31_25:
557 		sensitivity = 10486;
558 		break;
559 	case ICM42688_GYRO_FS_15_625:
560 		sensitivity = 20972;
561 		break;
562 	}
563 
564 	int32_t in10 = in * 10;
565 
566 	/* Whole deg/s */
567 	*out_dps = in10 / sensitivity;
568 
569 	/* Micro deg/s */
570 	*out_udps = ((int64_t)(llabs(in10) - (llabs((*out_dps)) * sensitivity)) * 1000000LL) /
571 		    sensitivity;
572 }
573 
574 /**
575  * @brief Convert icm42688 accelerometer value to useful m/s^2 values
576  *
577  * @param cfg icm42688_cfg current device configuration
578  * @param in raw data value in int32_t format
579  * @param out_ms meters/s^2 (whole) output in int32_t
580  * @param out_ums micrometers/s^2 output as uint32_t
581  */
icm42688_accel_ms(const struct icm42688_cfg * cfg,int32_t in,int32_t * out_ms,int32_t * out_ums)582 static inline void icm42688_accel_ms(const struct icm42688_cfg *cfg, int32_t in, int32_t *out_ms,
583 				     int32_t *out_ums)
584 {
585 	int64_t sensitivity = 0; /* value equivalent for 1g */
586 
587 	switch (cfg->accel_fs) {
588 	case ICM42688_ACCEL_FS_2G:
589 		sensitivity = 16384;
590 		break;
591 	case ICM42688_ACCEL_FS_4G:
592 		sensitivity = 8192;
593 		break;
594 	case ICM42688_ACCEL_FS_8G:
595 		sensitivity = 4096;
596 		break;
597 	case ICM42688_ACCEL_FS_16G:
598 		sensitivity = 2048;
599 		break;
600 	}
601 
602 	/* Convert to micrometers/s^2 */
603 	int64_t in_ms = in * SENSOR_G;
604 
605 	/* meters/s^2 whole values */
606 	*out_ms = in_ms / (sensitivity * 1000000LL);
607 
608 	/* micrometers/s^2 */
609 	*out_ums = (in_ms - (*out_ms * sensitivity * 1000000LL)) / sensitivity;
610 }
611 
612 /**
613  * @brief Convert icm42688 gyroscope value to useful rad/s values
614  *
615  * @param cfg icm42688_cfg current device configuration
616  * @param in raw data value in int32_t format
617  * @param out_rads whole rad/s output in int32_t
618  * @param out_urads microrad/s as uint32_t
619  */
icm42688_gyro_rads(const struct icm42688_cfg * cfg,int32_t in,int32_t * out_rads,int32_t * out_urads)620 static inline void icm42688_gyro_rads(const struct icm42688_cfg *cfg, int32_t in, int32_t *out_rads,
621 				      int32_t *out_urads)
622 {
623 	int64_t sensitivity = 0; /* value equivalent for 10x gyro reading deg/s */
624 
625 	switch (cfg->gyro_fs) {
626 	case ICM42688_GYRO_FS_2000:
627 		sensitivity = 164;
628 		break;
629 	case ICM42688_GYRO_FS_1000:
630 		sensitivity = 328;
631 		break;
632 	case ICM42688_GYRO_FS_500:
633 		sensitivity = 655;
634 		break;
635 	case ICM42688_GYRO_FS_250:
636 		sensitivity = 1310;
637 		break;
638 	case ICM42688_GYRO_FS_125:
639 		sensitivity = 2620;
640 		break;
641 	case ICM42688_GYRO_FS_62_5:
642 		sensitivity = 5243;
643 		break;
644 	case ICM42688_GYRO_FS_31_25:
645 		sensitivity = 10486;
646 		break;
647 	case ICM42688_GYRO_FS_15_625:
648 		sensitivity = 20972;
649 		break;
650 	}
651 
652 	int64_t in10_rads = (int64_t)in * SENSOR_PI * 10LL;
653 
654 	/* Whole rad/s */
655 	*out_rads = in10_rads / (sensitivity * 180LL * 1000000LL);
656 
657 	/* microrad/s */
658 	*out_urads =
659 		(in10_rads - (*out_rads * sensitivity * 180LL * 1000000LL)) / (sensitivity * 180LL);
660 }
661 
662 /**
663  * @brief Convert icm42688 temp value to useful celsius values
664  *
665  * @param cfg icm42688_cfg current device configuration
666  * @param in raw data value in int32_t format
667  * @param out_c whole celsius output in int32_t
668  * @param out_uc micro (1/1000000) celsius as uint32_t
669  */
icm42688_temp_c(int32_t in,int32_t * out_c,uint32_t * out_uc)670 static inline void icm42688_temp_c(int32_t in, int32_t *out_c, uint32_t *out_uc)
671 {
672 	int64_t sensitivity = 13248; /* value equivalent for x100 1c */
673 
674 	/* Offset by 25 degrees Celsius */
675 	int64_t in100 = (in * 100) + (25 * sensitivity);
676 
677 	/* Whole celsius */
678 	*out_c = in100 / sensitivity;
679 
680 	/* Micro celsius */
681 	*out_uc = ((in100 - (*out_c) * sensitivity) * INT64_C(1000000)) / sensitivity;
682 }
683 
684 #endif /* ZEPHYR_DRIVERS_SENSOR_ICM42688_H_ */
685