@@ -277,7 +277,7 @@ static uint32_t accel_period_ns[] = {
277
277
[ICM42688_DT_ACCEL_ODR_1_5625 ] = UINT32_C (10000000000000 ) / 15625 ,
278
278
[ICM42688_DT_ACCEL_ODR_3_125 ] = UINT32_C (10000000000000 ) / 31250 ,
279
279
[ICM42688_DT_ACCEL_ODR_6_25 ] = UINT32_C (10000000000000 ) / 62500 ,
280
- [ICM42688_DT_ACCEL_ODR_12_5 ] = UINT32_C (10000000000000 ) / 12500 ,
280
+ [ICM42688_DT_ACCEL_ODR_12_5 ] = UINT32_C (10000000000000 ) / 125000 ,
281
281
[ICM42688_DT_ACCEL_ODR_25 ] = UINT32_C (1000000000 ) / 25 ,
282
282
[ICM42688_DT_ACCEL_ODR_50 ] = UINT32_C (1000000000 ) / 50 ,
283
283
[ICM42688_DT_ACCEL_ODR_100 ] = UINT32_C (1000000000 ) / 100 ,
@@ -292,7 +292,7 @@ static uint32_t accel_period_ns[] = {
292
292
};
293
293
294
294
static uint32_t gyro_period_ns [] = {
295
- [ICM42688_DT_GYRO_ODR_12_5 ] = UINT32_C (10000000000000 ) / 12500 ,
295
+ [ICM42688_DT_GYRO_ODR_12_5 ] = UINT32_C (10000000000000 ) / 125000 ,
296
296
[ICM42688_DT_GYRO_ODR_25 ] = UINT32_C (1000000000 ) / 25 ,
297
297
[ICM42688_DT_GYRO_ODR_50 ] = UINT32_C (1000000000 ) / 50 ,
298
298
[ICM42688_DT_GYRO_ODR_100 ] = UINT32_C (1000000000 ) / 100 ,
@@ -306,6 +306,28 @@ static uint32_t gyro_period_ns[] = {
306
306
[ICM42688_DT_GYRO_ODR_32000 ] = UINT32_C (1000000 ) / 32 ,
307
307
};
308
308
309
+ static int icm42688_calc_timestamp_delta (int rtc_freq , int chan_type , int dt_odr , int frame_count ,
310
+ uint64_t * out_delta )
311
+ {
312
+ uint32_t period ;
313
+
314
+ if (IS_ACCEL (chan_type )) {
315
+ period = accel_period_ns [dt_odr ];
316
+ } else if (IS_GYRO (chan_type )) {
317
+ period = gyro_period_ns [dt_odr ];
318
+ } else {
319
+ return - EINVAL ;
320
+ }
321
+
322
+ /*
323
+ * When ODR is set to r and an external clock with frequency f is used,
324
+ * the actual ODR = f * r / 32000.
325
+ */
326
+ * out_delta = (uint64_t )period * frame_count * 32000 / rtc_freq ;
327
+
328
+ return 0 ;
329
+ }
330
+
309
331
static int icm42688_fifo_decode (const uint8_t * buffer , struct sensor_chan_spec chan_spec ,
310
332
uint32_t * fit , uint16_t max_count , void * data_out )
311
333
{
@@ -350,27 +372,66 @@ static int icm42688_fifo_decode(const uint8_t *buffer, struct sensor_chan_spec c
350
372
}
351
373
if (chan_spec .chan_type == SENSOR_CHAN_DIE_TEMP ) {
352
374
struct sensor_q31_data * data = (struct sensor_q31_data * )data_out ;
375
+ uint64_t ts_delta ;
353
376
354
- data -> shift = 9 ;
355
377
if (has_accel ) {
356
- data -> readings [count ].timestamp_delta =
357
- accel_period_ns [edata -> accel_odr ] * (accel_frame_count - 1 );
378
+ rc = icm42688_calc_timestamp_delta (
379
+ edata -> rtc_freq , SENSOR_CHAN_ACCEL_XYZ , edata -> accel_odr ,
380
+ accel_frame_count - 1 , & ts_delta );
358
381
} else {
359
- data -> readings [count ].timestamp_delta =
360
- gyro_period_ns [edata -> gyro_odr ] * (gyro_frame_count - 1 );
382
+ rc = icm42688_calc_timestamp_delta (
383
+ edata -> rtc_freq , SENSOR_CHAN_GYRO_XYZ , edata -> gyro_odr ,
384
+ gyro_frame_count - 1 , & ts_delta );
385
+ }
386
+ if (rc < 0 ) {
387
+ buffer = frame_end ;
388
+ continue ;
389
+ }
390
+
391
+ /*
392
+ * TODO: For some extreme combination of ODR and FIFO count, using uint32_t
393
+ * to store timestamp delta will overflow. Better error reporting?
394
+ */
395
+ if (ts_delta > UINT32_MAX ) {
396
+ LOG_ERR ("Timestamp delta overflow" );
397
+ buffer = frame_end ;
398
+ continue ;
361
399
}
400
+
401
+ data -> readings [count ].timestamp_delta = ts_delta ;
402
+
403
+ data -> shift = 9 ;
362
404
data -> readings [count ].temperature =
363
405
icm42688_read_temperature_from_packet (buffer );
364
406
} else if (IS_ACCEL (chan_spec .chan_type ) && has_accel ) {
365
407
/* Decode accel */
366
408
struct sensor_three_axis_data * data =
367
409
(struct sensor_three_axis_data * )data_out ;
368
- uint64_t period_ns = accel_period_ns [ edata -> accel_odr ] ;
410
+ uint64_t ts_delta ;
369
411
370
412
icm42688_get_shift (SENSOR_CHAN_ACCEL_XYZ , edata -> header .accel_fs ,
371
413
edata -> header .gyro_fs , & data -> shift );
372
414
373
- data -> readings [count ].timestamp_delta = (accel_frame_count - 1 ) * period_ns ;
415
+ rc = icm42688_calc_timestamp_delta (edata -> rtc_freq , SENSOR_CHAN_ACCEL_XYZ ,
416
+ edata -> accel_odr , accel_frame_count - 1 ,
417
+ & ts_delta );
418
+ if (rc < 0 ) {
419
+ buffer = frame_end ;
420
+ continue ;
421
+ }
422
+
423
+ /*
424
+ * TODO: For some extreme combination of ODR and FIFO count, using uint32_t
425
+ * to store timestamp delta will overflow. Better error reporting?
426
+ */
427
+ if (ts_delta > UINT32_MAX ) {
428
+ LOG_ERR ("Timestamp delta overflow" );
429
+ buffer = frame_end ;
430
+ continue ;
431
+ }
432
+
433
+ data -> readings [count ].timestamp_delta = ts_delta ;
434
+
374
435
rc = icm42688_read_imu_from_packet (buffer , true, edata -> header .accel_fs , 0 ,
375
436
& data -> readings [count ].x );
376
437
rc |= icm42688_read_imu_from_packet (buffer , true, edata -> header .accel_fs , 1 ,
@@ -386,12 +447,31 @@ static int icm42688_fifo_decode(const uint8_t *buffer, struct sensor_chan_spec c
386
447
/* Decode gyro */
387
448
struct sensor_three_axis_data * data =
388
449
(struct sensor_three_axis_data * )data_out ;
389
- uint64_t period_ns = gyro_period_ns [ edata -> gyro_odr ] ;
450
+ uint64_t ts_delta ;
390
451
391
452
icm42688_get_shift (SENSOR_CHAN_GYRO_XYZ , edata -> header .accel_fs ,
392
453
edata -> header .gyro_fs , & data -> shift );
393
454
394
- data -> readings [count ].timestamp_delta = (gyro_frame_count - 1 ) * period_ns ;
455
+ rc = icm42688_calc_timestamp_delta (edata -> rtc_freq , SENSOR_CHAN_GYRO_XYZ ,
456
+ edata -> gyro_odr , gyro_frame_count - 1 ,
457
+ & ts_delta );
458
+ if (rc < 0 ) {
459
+ buffer = frame_end ;
460
+ continue ;
461
+ }
462
+
463
+ /*
464
+ * TODO: For some extreme combination of ODR and FIFO count, using uint32_t
465
+ * to store timestamp delta will overflow. Better error reporting?
466
+ */
467
+ if (ts_delta > UINT32_MAX ) {
468
+ LOG_ERR ("Timestamp delta overflow" );
469
+ buffer = frame_end ;
470
+ continue ;
471
+ }
472
+
473
+ data -> readings [count ].timestamp_delta = ts_delta ;
474
+
395
475
rc = icm42688_read_imu_from_packet (buffer , false, edata -> header .gyro_fs , 0 ,
396
476
& data -> readings [count ].x );
397
477
rc |= icm42688_read_imu_from_packet (buffer , false, edata -> header .gyro_fs , 1 ,
0 commit comments