icm42605_driver/
lib.rs

1#![no_std]
2
3//! An embedded async driver for the ICM-42605 6-Axis IMU.
4
5device_driver::create_device! {
6    device_name: Icm42605,
7    dsl: {
8        config {
9            type RegisterAddressType = u16;
10            type DefaultByteOrder = BE;
11            type DefmtFeature = "defmt";
12        }
13
14        block UserBank0 {
15            const ADDRESS_OFFSET = 0x0000;
16
17            register DeviceConfig {
18                const ADDRESS = 0x11;
19                const SIZE_BITS = 8;
20
21                spi_mode: bool = 4,
22                soft_reset_config: bool = 0,
23            },
24
25            register DriveConfig {
26                const ADDRESS = 0x13;
27                const SIZE_BITS = 8;
28                const RESET_VALUE = 0x05;
29
30                i2c_slew_rate: uint = 3..6,
31                spi_slew_rate: uint = 0..3,
32            },
33
34            register IntConfig {
35                const ADDRESS = 0x14;
36                const SIZE_BITS = 8;
37
38                int2_mode: bool = 5,
39                int2_drive_circuit: bool = 4,
40                int2_polarity: bool = 3,
41                int1_mode: bool = 2,
42                int1_drive_circuit: bool = 1,
43                int1_polarity: bool = 0,
44            },
45
46            register FifoConfig {
47                const ADDRESS = 0x16;
48                const SIZE_BITS = 8;
49
50                fifo_mode: uint as enum FifoMode {
51                    Bypass,
52                    Stream,
53                    StopOnFull,
54                    Reserved,
55                } = 6..8,
56            },
57
58            register TempData {
59                type Access = RO;
60                const ADDRESS = 0x1d;
61                const SIZE_BITS = 16;
62                const RESET_VALUE = 0x8000;
63
64                value: int = 0..16,
65            },
66
67            ref AccelDataX = register TempData {
68                const ADDRESS = 0x1f;
69            },
70
71            ref AccelDataY = register TempData {
72                const ADDRESS = 0x21;
73            },
74
75            ref AccelDataZ = register TempData {
76                const ADDRESS = 0x23;
77            },
78
79            ref GyroDataX = register TempData {
80                const ADDRESS = 0x25;
81            },
82
83            ref GyroDataY = register TempData {
84                const ADDRESS = 0x27;
85            },
86
87            ref GyroDataZ = register TempData {
88                const ADDRESS = 0x29;
89            },
90
91            register TimestampFsync {
92                type Access = RO;
93                const ADDRESS = 0x2b;
94                const SIZE_BITS = 16;
95
96                value: int = 0..16,
97            },
98
99            register IntStatus {
100                type Access = RO;
101                const ADDRESS = 0x2d;
102                const SIZE_BITS = 8;
103
104                ui_fsync_int: bool = 6,
105                pll_rdy_int: bool = 5,
106                reset_done_int: bool = 4,
107                data_rdy_int: bool = 3,
108                fifo_ths_int: bool = 2,
109                fifo_full_int: bool = 1,
110                agc_rdy_int: bool = 0,
111            },
112
113            register FifoCount {
114                type Access = RO;
115                const ADDRESS = 0x2e;
116                const SIZE_BITS = 16;
117
118                value: int = 0..16,
119            },
120
121            register FifoData {
122                type Access = RO;
123                const ADDRESS = 0x30;
124                const SIZE_BITS = 8;
125                const RESET_VALUE = 0xff;
126
127                value: int = 0..8,
128            },
129
130            block ApexData {
131                register StepCount {
132                    type Access = RO;
133                    type ByteOrder = LE;
134                    const ADDRESS = 0x31;
135                    const SIZE_BITS = 16;
136
137                    value: uint = 0..16,
138                },
139
140                register StepCadence {
141                    type Access = RO;
142                    const ADDRESS = 0x33;
143                    const SIZE_BITS = 8;
144
145                    value: uint = 0..8,
146                },
147
148                register ApexStatus {
149                    type Access = RO;
150                    const ADDRESS = 0x34;
151                    const SIZE_BITS = 8;
152                    const RESET_VALUE = 0x04;
153
154                    dmp_idle: bool = 2,
155                    activity_class: uint as enum ActivityClass {
156                        Unknown,
157                        Walk,
158                        Run,
159                        Reserved,
160                    } = 0..2,
161                },
162
163                register TapStatus {
164                    type Access = RO;
165                    const ADDRESS = 0x35;
166                    const SIZE_BITS = 8;
167
168                    tap_num: uint as enum TapNum {
169                        NoTap,
170                        Single,
171                        Double,
172                        Reserved,
173                    } = 3..5,
174                    tap_axis: uint as enum Axis {
175                        X,
176                        Y,
177                        Z,
178                        Reserved,
179                    } = 1..3,
180                    tap_dir: uint as enum Polarity {
181                        Positive,
182                        Negative,
183                    } = 0..1,
184                },
185
186                register DoubleTapTiming {
187                    type Access = RO;
188                    const ADDRESS = 0x36;
189                    const SIZE_BITS = 8;
190
191                    value: uint = 0..6,
192                },
193            },
194
195            register IntStatus2 {
196                type Access = RO;
197                const ADDRESS = 0x37;
198                const SIZE_BITS = 8;
199
200                smd_int: bool = 3,
201                wom_z_int: bool = 2,
202                wom_y_int: bool = 1,
203                wom_x_int: bool = 0,
204            },
205
206            register IntStatus3 {
207                type Access = RO;
208                const ADDRESS =  0x38;
209                const SIZE_BITS = 8;
210
211                step_det_int: bool = 5,
212                step_cnt_ovf_int: bool = 4,
213                tilt_det_int: bool = 3,
214                wake_int: bool = 2,
215                sleep_int: bool = 1,
216                tap_det_int: bool = 0,
217            },
218
219            register SignalPathReset {
220                type Access = WO;
221                const ADDRESS = 0x4b;
222                const SIZE_BITS = 8;
223
224                dmp_init_en: bool = 6,
225                dmp_mem_reset_en: bool = 5,
226                abort_and_reset: bool = 3,
227                tmst_strobe: bool = 2,
228                fifo_flush: bool = 1,
229            },
230
231            register IntfConfig0 {
232                const ADDRESS = 0x4c;
233                const SIZE_BITS = 8;
234                const RESET_VALUE = 0x30;
235
236                fifo_hold_last_data_en: bool = 7,
237                fifo_count_rec: uint as enum FifoCountRec {
238                    Bytes,
239                    Records,
240                } = 6..7,
241                fifo_count_endian: uint as enum Endian {
242                    LittleEndian,
243                    BigEndian,
244                } = 5..6,
245                sensor_data_endian: uint as Endian = 4..5,
246                ui_sifs_cfg: uint as enum UiSifsCfg {
247                    Reserved = catch_all,
248                    DisableSpi = 2,
249                    DisableI2c = 3,
250                } = 0..2,
251            },
252
253            register IntfConfig1 {
254                const ADDRESS = 0x4d;
255                const SIZE_BITS = 8;
256                const RESET_VALUE = 0x91;
257
258                accel_lp_clk_sel: uint as enum AccelLpClkSel {
259                    WakeUp,
260                    Rc,
261                } = 3..4,
262                clksel: uint as enum ClkSel {
263                    InternalRc,
264                    PllOrRc,
265                    Reserved,
266                    Disable,
267                } = 0..2,
268            },
269
270            register PwrMgmt {
271                const ADDRESS = 0x4e;
272                const SIZE_BITS = 8;
273
274                temp_dis: bool = 5,
275                idle: bool = 4,
276                gyro_mode: uint as enum GyroMode {
277                    Off,
278                    Standby,
279                    Reserved,
280                    LowNoise,
281                } = 2..4,
282                accel_mode: uint as enum AccelMode {
283                    Off,
284                    Reserved,
285                    LowPower,
286                    LowNoise,
287                } = 0..2,
288            },
289
290            register GyroConfig0 {
291                const ADDRESS = 0x4f;
292                const SIZE_BITS = 8;
293                const RESET_VALUE = 0x06;
294
295                gyro_fs_sel: uint as enum GyroFullScale {
296                    DegreesPerSec2000,
297                    DegreesPerSec1000,
298                    DegreesPerSec500,
299                    DegreesPerSec250,
300                    DegreesPerSec125,
301                    DegreesPerSec62x5,
302                    DegreesPerSec31x25,
303                    DegreesPerSec15x625,
304                } = 5..8,
305                gyro_odr: uint as enum DataRate {
306                    Reserved = catch_all,
307                    Hz8000 = 3,
308                    Hz4000 = 4,
309                    Hz2000 = 5,
310                    Hz1000 = 6,
311                    Hz200 = 7,
312                    Hz100 = 8,
313                    Hz50 = 9,
314                    Hz25 = 10,
315                    Hz12x5 = 11,
316                    Hz6x25 = 12,
317                    Hz3x125 = 13,
318                    Hz1x15625 = 14,
319                    Hz500 = 15,
320                } = 0..4,
321            },
322
323            register AccelConfig0 {
324                const ADDRESS = 0x50;
325                const SIZE_BITS = 8;
326                const RESET_VALUE = 0x06;
327
328                gyro_fs_sel: uint as enum AccelFullScale {
329                    Max16G,
330                    Max8G,
331                    Max4G,
332                    Max2G,
333                    Reserved = catch_all,
334                } = 5..8,
335                gyro_odr: uint as DataRate = 0..4,
336            },
337
338            register GyroConfig1 {
339                const ADDRESS = 0x51;
340                const SIZE_BITS = 8;
341                const RESET_VALUE = 0x16;
342
343                temp_filt_bw: uint as enum LowPassFilterLatency {
344                    Latency125ms,
345                    Latency1ms,
346                    Latency2ms,
347                    Latency4ms,
348                    Latency8ms,
349                    Latency16ms,
350                    Latency32ms,
351                    Reserved,
352                } = 5..8,
353                gyro_ui_filt_ord: uint as enum UiFilterOrder {
354                    FirstOrder,
355                    SecondOrder,
356                    ThirdOrder,
357                    Reserved,
358                } = 2..4,
359                gyro_dec2_m2_ord: uint as enum Dec2M2FilterOrder {
360                    Reserved = catch_all,
361                    ThirdOrder = 2,
362                } = 0..2,
363            },
364
365            register GyroAccelConfig {
366                const ADDRESS = 0x52;
367                const SIZE_BITS = 8;
368                const RESET_VALUE = 0x11;
369
370                accel_ui_filt_bw: uint = 4..8,
371                gyro_ui_filt_bw: uint = 0..4,
372            },
373
374            register AccelConfig1 {
375                const ADDRESS = 0x53;
376                const SIZE_BITS = 8;
377                const RESET_VALUE = 0x0d;
378
379                accel_ui_filt_ord: uint as UiFilterOrder = 3..5,
380                accel_dec2_m2_ord: uint as Dec2M2FilterOrder = 1..3,
381            },
382
383            register TmstConfig {
384                const ADDRESS = 0x54;
385                const SIZE_BITS = 8;
386                const RESET_VALUE = 0x23;
387
388                tmst_to_regs_en: bool = 4,
389                tmst_res: bool = 3,
390                tmst_delta_en: bool = 2,
391                tmst_fsync_en: bool = 1,
392                tmst_en: bool = 0,
393            },
394
395            register ApexConfig {
396                const ADDRESS = 0x56;
397                const SIZE_BITS = 8;
398                const RESET_VALUE = 0x82;
399
400                dmp_power_save: bool = 7,
401                tap_enable: bool = 6,
402                ped_enable: bool = 5,
403                tilt_enable: bool = 4,
404                r2w_en: bool = 3,
405                dmp_odr: uint as enum DmpDataRate {
406                    Hz25,
407                    Reserved = catch_all,
408                    Hz50 = 2
409                } = 0..2,
410            },
411
412            register SmdConfig {
413                const ADDRESS = 0x57;
414                const SIZE_BITS = 8;
415
416                wom_int_mode: bool = 3,
417                wom_mode: bool = 2,
418                smd_mode: uint as enum SmdMode {
419                    Disabled,
420                    WakeOnMotion,
421                    Short,
422                    Long,
423                } = 0..2,
424            },
425
426            register FifoConfig1 {
427                const ADDRESS = 0x5f;
428                const SIZE_BITS = 8;
429
430                fifo_resume_partial_rd: bool = 6,
431                fifo_wm_gt_th: bool = 5,
432                fifo_tmst_fsync_en: bool = 3,
433                fifo_temp_en: bool = 2,
434                fifo_gyro_en: bool = 1,
435                fifo_accel_en: bool = 0,
436            },
437
438            register FifoWatermark {
439                type ByteOrder = LE;
440                const ADDRESS = 0x60;
441                const SIZE_BITS = 16;
442
443                value: uint = 0..12,
444            },
445
446            register FsyncConfig {
447                const ADDRESS = 0x62;
448                const SIZE_BITS = 8;
449                const RESET_VALUE = 0x10;
450
451                fsync_ui_sel: uint as enum FsyncFlag {
452                    Disabled,
453                    Temp,
454                    GyroX,
455                    GyroY,
456                    GyroZ,
457                    AccelX,
458                    AccelY,
459                    AccelZ,
460                } = 4..7,
461                fsync_ui_flag_clear_sel: bool = 1,
462                fsync_polarity: bool = 0,
463            },
464
465            register IntConfig0 {
466                const ADDRESS = 0x63;
467                const SIZE_BITS = 8;
468
469                ui_drdy_int_clear: uint as enum IntClearOption {
470                    StatusBitRead,
471                    Reserved,
472                    SensorRegisterRead,
473                    Both,
474                } = 4..6,
475                fifo_ths_int_clear: uint as IntClearOption = 2..4,
476                fifo_full_int_clear: uint as IntClearOption = 0..2,
477            },
478
479            register IntConfig1 {
480                const ADDRESS = 0x64;
481                const SIZE_BITS = 8;
482                const RESET_VALUE = 0x10;
483
484                int_tpulse_duration: bool = 6,
485                int_tdeassert_disable: bool = 5,
486                int_async_reset: bool = 4,
487            },
488
489            register IntSource0 {
490                const ADDRESS = 0x65;
491                const SIZE_BITS = 8;
492                const RESET_VALUE = 0x10;
493
494                ui_fsync_int1_en: bool = 6,
495                pll_rdy_int1_en: bool = 5,
496                reset_down_int1_en: bool = 4,
497                ui_drdy_int1_en: bool = 3,
498                fifo_ths_int1_en: bool = 2,
499                fifo_full_int1_en: bool = 1,
500                ui_agc_rdy_int1_en: bool = 0,
501            },
502
503            register IntSource1 {
504                const ADDRESS = 0x66;
505                const SIZE_BITS = 8;
506
507                i3c_protocol_error_int1_en: bool = 6,
508                smd_int1_en: bool = 3,
509                wom_z_int1_en: bool = 2,
510                wom_y_int1_en: bool = 1,
511                wom_x_int1_en: bool = 0,
512            },
513
514            register IntSource3 {
515                const ADDRESS = 0x68;
516                const SIZE_BITS = 8;
517
518                ui_fsync_int2_en: bool = 6,
519                pll_rdy_int2_en: bool = 5,
520                reset_down_int2_en: bool = 4,
521                ui_drdy_int2_en: bool = 3,
522                fifo_ths_int2_en: bool = 2,
523                fifo_full_int2_en: bool = 1,
524                ui_agc_rdy_int2_en: bool = 0,
525            },
526
527            register IntSource4 {
528                const ADDRESS = 0x69;
529                const SIZE_BITS = 8;
530
531                i3c_protocol_error_int2_en: bool = 6,
532                smd_int2_en: bool = 3,
533                wom_z_int2_en: bool = 2,
534                wom_y_int2_en: bool = 1,
535                wom_x_int2_en: bool = 0,
536            },
537
538            register FifoLostPkt {
539                type Access = RO;
540                type ByteOrder = LE;
541                const ADDRESS = 0x6c;
542                const SIZE_BITS = 16;
543
544                value: uint = 0..16,
545            },
546
547            register SelfTestConfig {
548                const ADDRESS = 0x70;
549                const SIZE_BITS = 8;
550
551                accel_st_power: bool = 6,
552                en_az_st: bool = 5,
553                en_ay_st: bool = 4,
554                en_ax_st: bool = 3,
555                en_gz_st: bool = 2,
556                en_gy_st: bool = 1,
557                en_gx_st: bool = 0,
558            },
559
560            register WhoAmI {
561                type Access = RO;
562                const ADDRESS = 0x75;
563                const SIZE_BITS = 8;
564
565                whoami: uint = 0..8,
566            },
567        },
568
569        block UserBank1 {
570            const ADDRESS_OFFSET = 0x0100;
571
572            register SensorConfig {
573                const ADDRESS = 0x03;
574                const SIZE_BITS = 8;
575
576                zg_disable: bool = 5,
577                yg_disable: bool = 4,
578                xg_disable: bool = 3,
579                za_disable: bool = 2,
580                ya_disable: bool = 1,
581                xa_disable: bool = 0,
582            },
583
584            register GyroConfigStatic2 {
585                const ADDRESS = 0x0b;
586                const SIZE_BITS = 8;
587                const RESET_VALUE = 0xa8;
588
589                gyro_aaf_dis: bool = 1,
590                gyro_nf_dis: bool = 0,
591            },
592
593            register GyroAntiAliasFilterConfig {
594                type ByteOrder = LE;
595                const ADDRESS = 0x0c;
596                const SIZE_BITS = 24;
597                const RESET_VALUE = 0x3f;
598
599                gyro_aaf_delt: uint = 0..6,
600                gyro_aaf_deltsqr: uint = 8..20,
601                gyro_aaf_bitshift: uint = 20..24,
602            },
603
604            register GyroXNfCoswz {
605                const ADDRESS = 0x0f;
606                const SIZE_BITS = 8;
607
608                value: uint = 0..8,
609            },
610
611            ref GyroYNfCoswz = register GyroXNfCoswz {
612                const ADDRESS = 0x10;
613            },
614
615            ref GyroZNfCoswz = register GyroXNfCoswz {
616                const ADDRESS = 0x11;
617            },
618
619            register GyroConfigStatic9 {
620                const ADDRESS = 0x12;
621                const SIZE_BITS = 8;
622
623                gyro_z_nf_coswz_sel: bool = 5,
624                gyro_y_nf_coswz_sel: bool = 4,
625                gyro_x_nf_coswz_sel: bool = 3,
626                gyro_z_nf_coswz: bool = 2,
627                gyro_y_nf_coswz: bool = 1,
628                gyro_x_nf_coswz: bool = 0,
629            },
630
631            register GyroConfigStatic10 {
632                const ADDRESS = 0x13;
633                const SIZE_BITS = 8;
634                const RESET_VALUE = 0x11;
635
636                gyro_nf_bw_sel: uint = 4..7,
637            },
638
639            ref XgStData  = register GyroXNfCoswz {
640                const ADDRESS = 0x5f;
641            },
642
643            ref YgStData  = register GyroXNfCoswz {
644                const ADDRESS = 0x60;
645            },
646
647            ref ZgStData  = register GyroXNfCoswz {
648                const ADDRESS = 0x61;
649            },
650
651            register TmstVal {
652                type ByteOrder = LE;
653                const ADDRESS = 0x62;
654                const SIZE_BITS = 24;
655
656                value: uint = 0..20,
657            },
658
659            register IntfConfig4 {
660                const ADDRESS = 0x7a;
661                const SIZE_BITS = 8;
662                const RESET_VALUE = 0x03;
663
664                i3c_bus_mode: bool = 6,
665                spi_ap_4wire: bool = 1,
666            },
667
668            register IntfConfig5 {
669                const ADDRESS = 0x7b;
670                const SIZE_BITS = 8;
671                const RESET_VALUE = 0x20;
672
673                pin9_function: uint as enum Pin9Function {
674                    Int2,
675                    FSync,
676                    Reserved = catch_all,
677                } = 1..3,
678            },
679
680            register IntfConfig6 {
681                const ADDRESS = 0x7c;
682                const SIZE_BITS = 8;
683                const RESET_VALUE = 0x5f;
684
685                asynctime0_dis: bool = 7,
686                i3c_en: bool = 4,
687                i3c_ibi_byte_en: bool = 3,
688                i3c_ibi_en: bool = 2,
689                i3c_ddr_en: bool = 1,
690                i3c_sdr_en: bool = 0,
691            },
692        },
693
694        block UserBank2 {
695            const ADDRESS_OFFSET = 0x0200;
696
697            register AccelAntiAliasFilterConfig {
698                type ByteOrder = LE;
699                const ADDRESS = 0x0c;
700                const SIZE_BITS = 24;
701                const RESET_VALUE = 0x3f;
702
703                accel_aaf_dis: bool = 0,
704                accel_aaf_delt: uint = 1..7,
705                accel_aaf_deltsqr: uint = 8..20,
706                accel_aaf_bitshift: uint = 20..24,
707            },
708
709            ref XaStData  = register GyroXNfCoswz {
710                const ADDRESS = 0x3b;
711            },
712
713            ref YaStData  = register GyroXNfCoswz {
714                const ADDRESS = 0x3c;
715            },
716
717            ref ZaStData  = register GyroXNfCoswz {
718                const ADDRESS = 0x3d;
719            },
720        },
721
722        block UserBank4 {
723            const ADDRESS_OFFSET = 0x0400;
724
725            register ApexConfig1 {
726                const ADDRESS = 0x40;
727                const SIZE_BITS = 8;
728                const RESET_VALUE = 0xa2;
729
730                low_energy_amp_th_sel: uint = 4..8,
731                dmp_power_save_time_sel: uint = 0..4,
732            },
733
734            register ApexConfig2 {
735                const ADDRESS = 0x41;
736                const SIZE_BITS = 8;
737                const RESET_VALUE = 0x85;
738
739                ped_amp_th_sel: uint = 4..8,
740                ped_step_cnt_th_sel: uint =0..4,
741            },
742
743            register ApexConfig3 {
744                const ADDRESS = 0x42;
745                const SIZE_BITS = 8;
746                const RESET_VALUE = 0x51;
747
748                ped_step_det_th_sel: uint = 5..8,
749                ped_sb_timer_th_sel: uint = 2..5,
750                ped_hi_en_th_sel: uint = 0..2,
751            },
752
753            register ApexConfig4 {
754                const ADDRESS = 0x43;
755                const SIZE_BITS = 8;
756                const RESET_VALUE = 0xa4;
757
758                tilt_wait_time_sel: uint = 6..8,
759                sleep_time_out: uint = 3..6,
760            },
761
762            register ApexConfig5 {
763                const ADDRESS = 0x44;
764                const SIZE_BITS = 8;
765                const RESET_VALUE = 0x8c;
766
767                mounting_matrix: uint = 0..3,
768            },
769
770            register ApexConfig6 {
771                const ADDRESS = 0x45;
772                const SIZE_BITS = 8;
773                const RESET_VALUE = 0x5c;
774
775                sleep_gesture_delay: uint = 0..3,
776            },
777
778            register ApexConfig7 {
779                const ADDRESS = 0x47;
780                const SIZE_BITS = 8;
781                const RESET_VALUE = 0x5b;
782
783                tap_tmax: uint = 5..7,
784                tap_tavg: uint = 3..5,
785                tap_tmin: uint = 0..3,
786            },
787
788            register ApexConfig8 {
789                const ADDRESS = 0x48;
790                const SIZE_BITS = 8;
791
792                sensitivity_mode: bool = 0,
793            },
794
795            register AccelWomXThr {
796                const ADDRESS = 0x4a;
797                const SIZE_BITS = 8;
798
799                value: uint = 0..8,
800            },
801
802            ref AccelWomYThr = register AccelWomXThr {
803                const ADDRESS = 0x4b;
804            },
805
806            ref AccelWomZThr = register AccelWomXThr {
807                const ADDRESS = 0x4c;
808            },
809
810            register IntSource6 {
811                const ADDRESS = 0x4d;
812                const SIZE_BITS = 8;
813
814                step_det_int1_en: bool = 5,
815                step_cnt_ofl_int1_en: bool = 4,
816                tilt_det_int1_en: bool = 3,
817                wake_det_int1_en: bool = 2,
818                sleep_det_int1_en: bool = 1,
819                tap_det_int1_en: bool = 0,
820            },
821
822            register IntSource7 {
823                const ADDRESS = 0x4e;
824                const SIZE_BITS = 8;
825
826                step_det_int2_en: bool = 5,
827                step_cnt_ofl_int2_en: bool = 4,
828                tilt_det_int2_en: bool = 3,
829                wake_det_int2_en: bool = 2,
830                sleep_det_int2_en: bool = 1,
831                tap_det_int2_en: bool = 0,
832            },
833
834            register IntSource8 {
835                const ADDRESS = 0x4f;
836                const SIZE_BITS = 8;
837
838                fsync_ibi_en: bool = 6,
839                pll_rdy_ibi_en: bool = 5,
840                reset_down_ibi_en: bool = 4,
841                ui_drdy_ibi_en: bool = 3,
842                fifo_ths_ibi_en: bool = 2,
843                fifo_full_ibi_en: bool = 1,
844                ui_agc_rdy_ibi_en: bool = 0,
845            },
846
847            register IntSource9 {
848                const ADDRESS = 0x50;
849                const SIZE_BITS = 8;
850
851                i3c_protocol_error_ibi_en: bool = 7,
852                smd_ibi_en: bool = 4,
853                wom_z_ibi_en: bool = 3,
854                wom_y_ibi_en: bool = 2,
855                wom_x_ibi_en: bool = 1,
856            },
857
858            register IntSource10 {
859                const ADDRESS = 0x51;
860                const SIZE_BITS = 8;
861
862                step_det_ibi_en: bool = 5,
863                step_cnt_ofl_ibi_en: bool = 4,
864                tilt_det_ibi_en: bool = 3,
865                wake_det_ibi_en: bool = 2,
866                sleep_det_ibi_en: bool = 1,
867                tap_det_ibi_en: bool = 0,
868            },
869
870            register OffsetUser0 {
871                const ADDRESS = 0x77;
872                const SIZE_BITS = 8;
873
874                gyro_x_offuser_lo: uint = 0..8,
875            },
876
877            register OffsetUser1 {
878                const ADDRESS = 0x78;
879                const SIZE_BITS = 8;
880
881                gyro_y_offuser_hi: uint = 4..8,
882                gyro_x_offuser_hi: uint = 0..4,
883            },
884
885            register OffsetUser2 {
886                const ADDRESS = 0x79;
887                const SIZE_BITS = 8;
888
889                gyro_y_offuser_lo: uint = 0..8,
890            },
891
892            register OffsetUser3 {
893                const ADDRESS = 0x7a;
894                const SIZE_BITS = 8;
895
896                gyro_z_offuser_lo: uint = 0..8,
897            },
898
899            register OffsetUser4 {
900                const ADDRESS = 0x7b;
901                const SIZE_BITS = 8;
902
903                accel_x_offuser_hi: uint = 4..8,
904                gyro_z_offuser_hi: uint = 0..4,
905            },
906
907            register OffsetUser5 {
908                const ADDRESS = 0x7c;
909                const SIZE_BITS = 8;
910
911                accel_x_offuser_lo: uint = 0..8,
912            },
913
914            register OffsetUser6 {
915                const ADDRESS = 0x7d;
916                const SIZE_BITS = 8;
917
918                accel_y_offuser_lo: uint = 0..8,
919            },
920
921            register OffsetUser7 {
922                const ADDRESS = 0x7e;
923                const SIZE_BITS = 8;
924
925                accel_z_offuser_hi: uint = 4..8,
926                accel_y_offuser_hi: uint = 0..4,
927            },
928
929            register OffsetUser8 {
930                const ADDRESS = 0x7f;
931                const SIZE_BITS = 8;
932
933                accel_z_offuser_lo: uint = 0..8,
934            },
935        },
936    }
937}
938
939const REG_BANK_SEL: u8 = 0x76;
940
941pub struct Icm42605Interface<I2C> {
942    i2c: I2C,
943    addr: u8,
944    bank: u8,
945}
946
947impl<I2C> Icm42605Interface<I2C> {
948    pub fn new(i2c: I2C, ad0: bool) -> Self {
949        Self {
950            i2c,
951            addr: 0x68 | u8::from(ad0),
952            bank: 0xff,
953        }
954    }
955
956    fn set_bank(&mut self, bank: u8) -> Result<(), I2C::Error>
957    where
958        I2C: embedded_hal::i2c::I2c,
959    {
960        if bank != self.bank {
961            self.i2c.write(self.addr, &[REG_BANK_SEL, bank])?;
962            self.bank = bank;
963        }
964        Ok(())
965    }
966
967    async fn set_bank_async(&mut self, bank: u8) -> Result<(), I2C::Error>
968    where
969        I2C: embedded_hal_async::i2c::I2c,
970    {
971        if bank != self.bank {
972            self.i2c.write(self.addr, &[REG_BANK_SEL, bank]).await?;
973            self.bank = bank;
974        }
975        Ok(())
976    }
977}
978
979impl<I2C: embedded_hal::i2c::I2c> device_driver::RegisterInterface for Icm42605Interface<I2C> {
980    type Error = I2C::Error;
981
982    type AddressType = u16;
983
984    fn write_register(
985        &mut self,
986        address: Self::AddressType,
987        _size_bits: u32,
988        data: &[u8],
989    ) -> Result<(), Self::Error> {
990        const MAX_LEN: usize = 3;
991        assert!(data.len() < MAX_LEN);
992
993        let [reg, bank] = address.to_le_bytes();
994        self.set_bank(bank)?;
995
996        let mut buf = heapless::Vec::<u8, MAX_LEN>::new();
997        let _ = buf.push(reg);
998        let _ = buf.extend_from_slice(data);
999        self.i2c.write(self.addr, &buf)
1000    }
1001
1002    fn read_register(
1003        &mut self,
1004        address: Self::AddressType,
1005        _size_bits: u32,
1006        data: &mut [u8],
1007    ) -> Result<(), Self::Error> {
1008        let [reg, bank] = address.to_le_bytes();
1009        self.set_bank(bank)?;
1010        self.i2c.write_read(self.addr, &[reg], data)
1011    }
1012}
1013
1014impl<I2C: embedded_hal_async::i2c::I2c> device_driver::AsyncRegisterInterface
1015    for Icm42605Interface<I2C>
1016{
1017    type Error = I2C::Error;
1018
1019    type AddressType = u16;
1020
1021    async fn write_register(
1022        &mut self,
1023        address: Self::AddressType,
1024        _size_bits: u32,
1025        data: &[u8],
1026    ) -> Result<(), Self::Error> {
1027        const MAX_LEN: usize = 3;
1028        assert!(data.len() < MAX_LEN);
1029
1030        let [reg, bank] = address.to_le_bytes();
1031        self.set_bank_async(bank).await?;
1032
1033        let mut buf = heapless::Vec::<u8, MAX_LEN>::new();
1034        let _ = buf.push(reg);
1035        let _ = buf.extend_from_slice(data);
1036        self.i2c.write(self.addr, &buf).await
1037    }
1038
1039    async fn read_register(
1040        &mut self,
1041        address: Self::AddressType,
1042        _size_bits: u32,
1043        data: &mut [u8],
1044    ) -> Result<(), Self::Error> {
1045        let [reg, bank] = address.to_le_bytes();
1046        self.set_bank_async(bank).await?;
1047        self.i2c.write_read(self.addr, &[reg], data).await
1048    }
1049}