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 uint16_t fifo_wm;
384 bool fifo_hires;
385 /* TODO additional FIFO options */
386
387 /* TODO interrupt options */
388 };
389
390 struct icm42688_trigger_entry {
391 struct sensor_trigger trigger;
392 sensor_trigger_handler_t handler;
393 };
394
395 /**
396 * @brief Device data (struct device)
397 */
398 struct icm42688_dev_data {
399 struct icm42688_cfg cfg;
400 #ifdef CONFIG_ICM42688_TRIGGER
401 #if defined(CONFIG_ICM42688_TRIGGER_OWN_THREAD)
402 K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_ICM42688_THREAD_STACK_SIZE);
403 struct k_thread thread;
404 struct k_sem gpio_sem;
405 #elif defined(CONFIG_ICM42688_TRIGGER_GLOBAL_THREAD)
406 struct k_work work;
407 #endif
408 const struct device *dev;
409 struct gpio_callback gpio_cb;
410 sensor_trigger_handler_t data_ready_handler;
411 const struct sensor_trigger *data_ready_trigger;
412 struct k_mutex mutex;
413 #endif /* CONFIG_ICM42688_TRIGGER */
414
415 int16_t readings[7];
416 };
417
418 /**
419 * @brief Device config (struct device)
420 */
421 struct icm42688_dev_cfg {
422 struct spi_dt_spec spi;
423 struct gpio_dt_spec gpio_int1;
424 struct gpio_dt_spec gpio_int2;
425 };
426
427 /**
428 * @brief Reset the sensor
429 *
430 * @param dev icm42688 device pointer
431 *
432 * @retval 0 success
433 * @retval -EINVAL Reset status or whoami register returned unexpected value.
434 */
435 int icm42688_reset(const struct device *dev);
436
437 /**
438 * @brief (Re)Configure the sensor with the given configuration
439 *
440 * @param dev icm42688 device pointer
441 * @param cfg icm42688_cfg pointer
442 *
443 * @retval 0 success
444 * @retval -errno Error
445 */
446 int icm42688_configure(const struct device *dev, struct icm42688_cfg *cfg);
447
448
449 /**
450 * @brief Safely (re)Configure the sensor with the given configuration
451 *
452 * Will rollback to prior configuration if new configuration is invalid
453 *
454 * @param dev icm42688 device pointer
455 * @param cfg icm42688_cfg pointer
456 *
457 * @retval 0 success
458 * @retval -errno Error
459 */
460 int icm42688_safely_configure(const struct device *dev, struct icm42688_cfg *cfg);
461
462 /**
463 * @brief Reads all channels
464 *
465 * Regardless of what is enabled/disabled this reads all data registers
466 * as the time to read the 14 bytes at 1MHz is going to be 112 us which
467 * is less time than a SPI transaction takes to setup typically.
468 *
469 * @param dev icm42688 device pointer
470 * @param buf 14 byte buffer to store data values (7 channels, 2 bytes each)
471 *
472 * @retval 0 success
473 * @retval -errno Error
474 */
475 int icm42688_read_all(const struct device *dev, uint8_t data[14]);
476
477 /**
478 * @brief Convert icm42688 accelerometer value to useful g values
479 *
480 * @param cfg icm42688_cfg current device configuration
481 * @param in raw data value in int32_t format
482 * @param out_g whole G's output in int32_t
483 * @param out_ug micro (1/1000000) of a G output as uint32_t
484 */
icm42688_accel_g(struct icm42688_cfg * cfg,int32_t in,int32_t * out_g,uint32_t * out_ug)485 static inline void icm42688_accel_g(struct icm42688_cfg *cfg, int32_t in, int32_t *out_g,
486 uint32_t *out_ug)
487 {
488 int32_t sensitivity = 0; /* value equivalent for 1g */
489
490 switch (cfg->accel_fs) {
491 case ICM42688_ACCEL_FS_2G:
492 sensitivity = 16384;
493 break;
494 case ICM42688_ACCEL_FS_4G:
495 sensitivity = 8192;
496 break;
497 case ICM42688_ACCEL_FS_8G:
498 sensitivity = 4096;
499 break;
500 case ICM42688_ACCEL_FS_16G:
501 sensitivity = 2048;
502 break;
503 }
504
505 /* Whole g's */
506 *out_g = in / sensitivity;
507
508 /* Micro g's */
509 *out_ug = ((abs(in) - (abs((*out_g)) * sensitivity)) * 1000000) / sensitivity;
510 }
511
512 /**
513 * @brief Convert icm42688 gyroscope value to useful deg/s values
514 *
515 * @param cfg icm42688_cfg current device configuration
516 * @param in raw data value in int32_t format
517 * @param out_dps whole deg/s output in int32_t
518 * @param out_udps micro (1/1000000) deg/s as uint32_t
519 */
icm42688_gyro_dps(const struct icm42688_cfg * cfg,int32_t in,int32_t * out_dps,uint32_t * out_udps)520 static inline void icm42688_gyro_dps(const struct icm42688_cfg *cfg, int32_t in, int32_t *out_dps,
521 uint32_t *out_udps)
522 {
523 int64_t sensitivity = 0; /* value equivalent for 10x gyro reading deg/s */
524
525 switch (cfg->gyro_fs) {
526 case ICM42688_GYRO_FS_2000:
527 sensitivity = 164;
528 break;
529 case ICM42688_GYRO_FS_1000:
530 sensitivity = 328;
531 break;
532 case ICM42688_GYRO_FS_500:
533 sensitivity = 655;
534 break;
535 case ICM42688_GYRO_FS_250:
536 sensitivity = 1310;
537 break;
538 case ICM42688_GYRO_FS_125:
539 sensitivity = 2620;
540 break;
541 case ICM42688_GYRO_FS_62_5:
542 sensitivity = 5243;
543 break;
544 case ICM42688_GYRO_FS_31_25:
545 sensitivity = 10486;
546 break;
547 case ICM42688_GYRO_FS_15_625:
548 sensitivity = 20972;
549 break;
550 }
551
552 int32_t in10 = in * 10;
553
554 /* Whole deg/s */
555 *out_dps = in10 / sensitivity;
556
557 /* Micro deg/s */
558 *out_udps = ((int64_t)(llabs(in10) - (llabs((*out_dps)) * sensitivity)) * 1000000LL) /
559 sensitivity;
560 }
561
562 /**
563 * @brief Convert icm42688 accelerometer value to useful m/s^2 values
564 *
565 * @param cfg icm42688_cfg current device configuration
566 * @param in raw data value in int32_t format
567 * @param out_ms meters/s^2 (whole) output in int32_t
568 * @param out_ums micrometers/s^2 output as uint32_t
569 */
icm42688_accel_ms(const struct icm42688_cfg * cfg,int32_t in,int32_t * out_ms,int32_t * out_ums)570 static inline void icm42688_accel_ms(const struct icm42688_cfg *cfg, int32_t in, int32_t *out_ms,
571 int32_t *out_ums)
572 {
573 int64_t sensitivity = 0; /* value equivalent for 1g */
574
575 switch (cfg->accel_fs) {
576 case ICM42688_ACCEL_FS_2G:
577 sensitivity = 16384;
578 break;
579 case ICM42688_ACCEL_FS_4G:
580 sensitivity = 8192;
581 break;
582 case ICM42688_ACCEL_FS_8G:
583 sensitivity = 4096;
584 break;
585 case ICM42688_ACCEL_FS_16G:
586 sensitivity = 2048;
587 break;
588 }
589
590 /* Convert to micrometers/s^2 */
591 int64_t in_ms = in * SENSOR_G;
592
593 /* meters/s^2 whole values */
594 *out_ms = in_ms / (sensitivity * 1000000LL);
595
596 /* micrometers/s^2 */
597 *out_ums = (in_ms - (*out_ms * sensitivity * 1000000LL)) / sensitivity;
598 }
599
600 /**
601 * @brief Convert icm42688 gyroscope value to useful rad/s values
602 *
603 * @param cfg icm42688_cfg current device configuration
604 * @param in raw data value in int32_t format
605 * @param out_rads whole rad/s output in int32_t
606 * @param out_urads microrad/s as uint32_t
607 */
icm42688_gyro_rads(const struct icm42688_cfg * cfg,int32_t in,int32_t * out_rads,int32_t * out_urads)608 static inline void icm42688_gyro_rads(const struct icm42688_cfg *cfg, int32_t in, int32_t *out_rads,
609 int32_t *out_urads)
610 {
611 int64_t sensitivity = 0; /* value equivalent for 10x gyro reading deg/s */
612
613 switch (cfg->gyro_fs) {
614 case ICM42688_GYRO_FS_2000:
615 sensitivity = 164;
616 break;
617 case ICM42688_GYRO_FS_1000:
618 sensitivity = 328;
619 break;
620 case ICM42688_GYRO_FS_500:
621 sensitivity = 655;
622 break;
623 case ICM42688_GYRO_FS_250:
624 sensitivity = 1310;
625 break;
626 case ICM42688_GYRO_FS_125:
627 sensitivity = 2620;
628 break;
629 case ICM42688_GYRO_FS_62_5:
630 sensitivity = 5243;
631 break;
632 case ICM42688_GYRO_FS_31_25:
633 sensitivity = 10486;
634 break;
635 case ICM42688_GYRO_FS_15_625:
636 sensitivity = 20972;
637 break;
638 }
639
640 int64_t in10_rads = (int64_t)in * SENSOR_PI * 10LL;
641
642 /* Whole rad/s */
643 *out_rads = in10_rads / (sensitivity * 180LL * 1000000LL);
644
645 /* microrad/s */
646 *out_urads =
647 (in10_rads - (*out_rads * sensitivity * 180LL * 1000000LL)) / (sensitivity * 180LL);
648 }
649
650 /**
651 * @brief Convert icm42688 temp value to useful celsius values
652 *
653 * @param cfg icm42688_cfg current device configuration
654 * @param in raw data value in int32_t format
655 * @param out_c whole celsius output in int32_t
656 * @param out_uc micro (1/1000000) celsius as uint32_t
657 */
icm42688_temp_c(int32_t in,int32_t * out_c,uint32_t * out_uc)658 static inline void icm42688_temp_c(int32_t in, int32_t *out_c, uint32_t *out_uc)
659 {
660 int64_t sensitivity = 13248; /* value equivalent for x100 1c */
661
662 /* Offset by 25 degrees Celsius */
663 int64_t in100 = (in * 100) + (25 * sensitivity);
664
665 /* Whole celsius */
666 *out_c = in100 / sensitivity;
667
668 /* Micro celsius */
669 *out_uc = ((in100 - (*out_c) * sensitivity) * INT64_C(1000000)) / sensitivity;
670 }
671
672 #endif /* ZEPHYR_DRIVERS_SENSOR_ICM42688_H_ */
673