1 /*
2  * Copyright (C) 2018 InvenSense Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <algos/time_sync.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <timer.h>
21 #include <sensors.h>
22 #include <heap.h>
23 #include <spi.h>
24 #include <slab.h>
25 #include <limits.h>
26 #include <atomic.h>
27 #include <plat/rtc.h>
28 #include <plat/gpio.h>
29 #include <plat/exti.h>
30 #include <plat/syscfg.h>
31 #include <seos.h>
32 #include <gpio.h>
33 #include <isr.h>
34 #include <halIntf.h>
35 #include <hostIntf.h>
36 #include <nanohubPacket.h>
37 #include <cpu/cpuMath.h>
38 #include <nanohub_math.h>
39 #include <variant/sensType.h>
40 #include <variant/variant.h>
41 #include <common/math/macros.h>
42 
43 #ifdef ACCEL_CAL_ENABLED
44 #include <calibration/accelerometer/accel_cal.h>
45 #endif
46 #ifdef GYRO_CAL_ENABLED
47 #include <calibration/gyroscope/gyro_cal.h>
48 #endif
49 
50 #define INFO_PRINT(fmt, ...) do { \
51         osLog(LOG_INFO, "%s " fmt, "[ICM40600]", ##__VA_ARGS__); \
52     } while (0);
53 
54 #define ERROR_PRINT(fmt, ...) do { \
55         osLog(LOG_ERROR, "%s " fmt, "[ICM40600] ERROR:", ##__VA_ARGS__); \
56     } while (0);
57 
58 #define DEBUG_PRINT(fmt, ...) do { \
59         if (DBG_ENABLE) {  \
60             INFO_PRINT(fmt,  ##__VA_ARGS__); \
61         } \
62     } while (0);
63 
64 #define DEBUG_PRINT_IF(cond, fmt, ...) do { \
65         if ((cond) && DBG_ENABLE) {  \
66             INFO_PRINT(fmt,  ##__VA_ARGS__); \
67         } \
68     } while (0);
69 
70 #define DBG_ENABLE                  0
71 #define DBG_STATE                   0
72 #define DBG_TIMESTAMP               0
73 
74 #define ICM40600_APP_ID             APP_ID_MAKE(NANOHUB_VENDOR_INVENSENSE, 0x2)
75 #define ICM40600_APP_VERSION        1
76 
77 #define ICM40600_SPI_WRITE          0x00
78 #define ICM40600_SPI_READ           0x80
79 
80 // SPI speeds officialy supported: 5MHz (low speed), 17MHz (high speed)
81 #define ICM40600_SPI_LOW_SPEED_HZ       5000000
82 #define ICM40600_SPI_HIGH_SPEED_HZ      17000000
83 #define ICM40600_SPI_DEFAULT_SPEED_HZ   ICM40600_SPI_LOW_SPEED_HZ
84 #define ICM40600_SPI_MODE               3
85 
86 #ifndef ICM40600_SPI_BUS_ID
87 #define ICM40600_SPI_BUS_ID         1
88 #endif
89 #ifndef ICM40600_INT1_PIN
90 #define ICM40600_INT1_PIN           GPIO_PB(6)
91 #endif
92 #ifndef ICM40600_INT1_IRQ
93 #define ICM40600_INT1_IRQ           EXTI9_5_IRQn
94 #endif
95 #define ICM40600_SPI_SPEED_HZ       ICM40600_SPI_HIGH_SPEED_HZ
96 
97 // set SPI speed register value
98 #if ICM40600_SPI_SPEED_HZ == ICM40600_SPI_LOW_SPEED_HZ
99 #define ICM40600_SPI_SPEED_REG_VALUE    BIT_SPI_SPEED_5MHZ
100 #elif ICM40600_SPI_SPEED_HZ == ICM40600_SPI_HIGH_SPEED_HZ
101 #define ICM40600_SPI_SPEED_REG_VALUE    BIT_SPI_SPEED_17MHZ
102 #else
103 #error "Invalid ICM40600_SPI_SPEED_HZ setting: valid values are 5MHz or 17MHz"
104 #endif
105 
106 /*
107  **********************
108  * Chip configuration
109  **********************
110  */
111 /* Full-scale range */
112 // Default accel range is 8g
113 #ifndef ICM40600_ACC_RANGE_G
114 #define ICM40600_ACC_RANGE_G        8
115 #endif
116 // Default gyro range is 2000dps
117 #ifndef ICM40600_GYR_RANGE_DPS
118 #define ICM40600_GYR_RANGE_DPS      2000
119 #endif
120 // 0 -> +-16g, 1 -> +-8g, 2 -> +-4g, 3 -> +-2g, 4 -> +-1g
121 #if ICM40600_ACC_RANGE_G == 16
122 #define ICM40600_ACC_FS     0
123 #elif ICM40600_ACC_RANGE_G == 8
124 #define ICM40600_ACC_FS     1
125 #elif ICM40600_ACC_RANGE_G == 4
126 #define ICM40600_ACC_FS     2
127 #else
128 #error "Invalid ICM40600_ACC_RANGE_G setting: valid values are 16, 8, 4 (no HiFi)"
129 #endif
130 // 0 -> +-2000dps, 1 -> +-1000dps, 2 -> +-500dps, 3 -> +-250dps, 4 -> +-125dps, 5 -> +-62.5dps, 6 -> +-31.25dps, 7 -> +-15.6225dps
131 #if ICM40600_GYR_RANGE_DPS == 2000
132 #define ICM40600_GYR_FS     0
133 #elif ICM40600_GYR_RANGE_DPS == 1000
134 #define ICM40600_GYR_FS     1
135 #else
136 #error "Invalid ICM40600_GYR_RANGE_DPS setting: valid values are 2000, 1000"
137 #endif
138 // Bandwidth for low-pass filters, using ODR/2 FIR
139 #define ICM40600_ACC_BW_IND     BIT_ACCEL_UI_BW_2_FIR
140 #define ICM40600_GYR_BW_IND     BIT_GYRO_UI_BW_2_FIR
141 
142 /* INT1 configuration */
143 // Polarity: 0 -> Active Low, 1 -> Active High
144 #define INT1_POLARITY           1
145 // Drive circuit: 0 -> Open Drain, 1 -> Push-Pull, fixed for INT1 do not change!
146 #define INT1_DRIVE_CIRCUIT      1
147 // Mode: 0 -> Pulse, 1 -> Latch
148 #define INT1_MODE               0
149 
150 /* Wake-on-Motion/No-Motion */
151 #define ICM40600_WOM_THRESHOLD_MG       160     // 160mg @ 25Hz
152 #define ICM40600_WOM_COMPUTE(val_mg)    ((256 * val_mg) / 1000)
153 // No-Motion duration: 5s
154 #define ICM40600_NOM_DURATION_NS        (5 * 1000000000ULL)
155 
156 /*
157  **********************
158  * Factory calibration
159  **********************
160  */
161 #define CALIBRATION_ODR                 7       // 200Hz (support both LPM and LNM)
162 #define CALIBRATION_ACC_FS              0       // +-16g (= resolution of offset register)
163 #define CALIBRATION_GYR_FS              1       // +-1000dps (= resolution of offset register)
164 #define CALIBRATION_ACC_1G              2048    // LSB/g @+-16g
165 #define CALIBRATION_ACC_BW_IND          BIT_ACCEL_UI_BW_4_IIR
166 #define CALIBRATION_GYR_BW_IND          BIT_GYRO_UI_BW_4_IIR
167 
168 #define CALIBRATION_READ_INTERVAL_US    (200 * 1000)    // 200ms (200/5ms=40 packets -> 40 * 16 = 640 bytes)
169 #define CALIBRATION_SAMPLE_NB           200             // 200/40packets = 5 loops
170 #define RETRY_CNT_CALIBRATION           10              // > 5 loops
171 
172 /*
173  **********************
174  * Selftest
175  **********************
176  */
177 #define SELF_TEST_ODR                   6   // 1000Hz
178 #define SELF_TEST_ACC_FS                3   // +-2g
179 #define SELF_TEST_GYR_FS                3   // +-250dps
180 #define SELF_TEST_ACC_BW_IND            BIT_ACCEL_UI_BW_10_IIR
181 #define SELF_TEST_GYR_BW_IND            BIT_GYRO_UI_BW_10_IIR
182 #define SELF_TEST_MIN_ACC_MG            225 // mg
183 #define SELF_TEST_MAX_ACC_MG            675 // mg
184 #define SELF_TEST_MIN_GYR_DPS           60  // dps
185 #define SELF_TEST_MAX_GYR_OFF_DPS       20  // dps
186 #define SELF_TEST_ACC_SHIFT_DELTA       500 // = 0.5
187 #define SELF_TEST_GYR_SHIFT_DELTA       500 // = 0.5
188 
189 #define SELF_TEST_ACC_SCALE             32768 / (16 >> SELF_TEST_ACC_FS) / 1000
190 #define SELF_TEST_GYR_SCALE             32768 / (2000 >> SELF_TEST_GYR_FS)
191 
192 #define SELF_TEST_READ_INTERVAL_US      (20 * 1000) // 20ms (20/1ms=20 packets -> 20 * 16 = 320 bytes)
193 #define SELF_TEST_SAMPLE_NB             200 // 200/20packets = 10 loops
194 #define RETRY_CNT_SELF_TEST             20  // > 10 loops
195 #define SELF_TEST_PRECISION             1000
196 #define SELF_TEST_SETTLE_TIME_MS        25
197 
198 #define SELF_TEST_MIN_ACC               (SELF_TEST_MIN_ACC_MG * SELF_TEST_ACC_SCALE * SELF_TEST_PRECISION)
199 #define SELF_TEST_MAX_ACC               (SELF_TEST_MAX_ACC_MG * SELF_TEST_ACC_SCALE * SELF_TEST_PRECISION)
200 #define SELF_TEST_MIN_GYR               (SELF_TEST_MIN_GYR_DPS * SELF_TEST_GYR_SCALE * SELF_TEST_PRECISION)
201 #define SELF_TEST_MAX_GYR               (SELF_TEST_MAX_GYR_DPS * SELF_TEST_GYR_SCALE * SELF_TEST_PRECISION)
202 #define SELF_TEST_MAX_GYR_OFFSET        (SELF_TEST_MAX_GYR_OFF_DPS * SELF_TEST_GYR_SCALE * SELF_TEST_PRECISION)
203 
204 /*
205  ****************
206  * register map *
207  ****************
208  */
209 /* Bank 0 */
210 #define REG_DEVICE_CONFIG           0x11
211 #define REG_SPI_SPEED               0x13
212 #define REG_INT_CONFIG              0x14
213 #define REG_FIFO_CONFIG             0x16
214 #define REG_INT_STATUS              0x2D
215 #define REG_FIFO_BYTE_COUNT1        0x2E
216 #define REG_FIFO_BYTE_COUNT2        0x2F
217 #define REG_FIFO_DATA               0x30
218 #define REG_SIGNAL_PATH_RESET       0x4B
219 #define REG_INTF_CONFIG0            0x4C
220 #define REG_PWR_MGMT_0              0x4E
221 #define REG_GYRO_CONFIG0            0x4F
222 #define REG_ACCEL_CONFIG0           0x50
223 #define REG_GYRO_CONFIG1            0x51
224 #define REG_GYRO_ACCEL_CONFIG0      0x52
225 #define REG_ACCEL_CONFIG1           0x53
226 #define REG_ACCEL_WOM_X_THR         0x54
227 #define REG_ACCEL_WOM_Y_THR         0x55
228 #define REG_ACCEL_WOM_Z_THR         0x56
229 #define REG_SMD_CONFIG              0x57
230 #define REG_INT_STATUS2             0x59
231 #define REG_TMST_CONFIG             0x5A
232 #define REG_FIFO_CONFIG1            0x5F
233 #define REG_FIFO_CONFIG2            0x60
234 #define REG_FIFO_CONFIG3            0x61
235 #define REG_INT_CONFIG0             0x63
236 #define REG_INT_CONFIG1             0x64
237 #define REG_INT_SOURCE0             0x65
238 #define REG_INT_SOURCE1             0x66
239 #define REG_SELF_TEST_CONFIG        0x70
240 #define REG_WHO_AM_I                0x75
241 #define REG_REG_BANK_SEL            0x76
242 #define REG_GOS_USER0               0x77
243 #define REG_GOS_USER1               0x78
244 #define REG_GOS_USER2               0x79
245 #define REG_GOS_USER3               0x7A
246 #define REG_GOS_USER4               0x7B
247 #define REG_GOS_USER5               0x7C
248 #define REG_GOS_USER6               0x7D
249 #define REG_GOS_USER7               0x7E
250 #define REG_GOS_USER8               0x7F
251 /* Bank 1 */
252 #define REG_XG_ST_DATA              0x5F
253 #define REG_YG_ST_DATA              0x60
254 #define REG_ZG_ST_DATA              0x61
255 /* Bank 2 */
256 #define REG_XA_ST_DATA              0x3B
257 #define REG_YA_ST_DATA              0x3C
258 #define REG_ZA_ST_DATA              0x3D
259 
260 /* REG_WHO_AM_I */
261 #define WHO_AM_I_ICM40604           0x32
262 #define WHO_AM_I_ICM40605           0x33
263 /* REG_REG_BANK_SEL */
264 #define BIT_BANK_SEL_0              0x00
265 #define BIT_BANK_SEL_1              0x01
266 #define BIT_BANK_SEL_2              0x02
267 /* REG_DEVICE_CONFIG */
268 #define BIT_SOFT_RESET              0x01
269 /* REG_SPI_SPEED */
270 #define BIT_SPI_SPEED_5MHZ          0x03
271 #define BIT_SPI_SPEED_17MHZ         0x05
272 /* REG_GYRO_CONFIG0/REG_ACCEL_CONFIG0 */
273 #define SHIFT_GYRO_FS_SEL           5
274 #define SHIFT_ACCEL_FS_SEL          5
275 #define SHIFT_ODR_CONF              0
276 /* REG_INT_CONFIG */
277 #define SHIFT_INT1_POLARITY         0
278 #define SHIFT_INT1_DRIVE_CIRCUIT    1
279 #define SHIFT_INT1_MODE             2
280 /* REG_PWR_MGMT_0 */
281 #define BIT_TEMP_DIS                0x20
282 #define BIT_IDLE                    0x10
283 #define BIT_GYRO_MODE_OFF           0x00
284 #define BIT_GYRO_MODE_STBY          0x04
285 #define BIT_GYRO_MODE_LN            0x0C
286 #define BIT_ACCEL_MODE_OFF          0x00
287 #define BIT_ACCEL_MODE_LN           0x03
288 /* REG_SIGNAL_PATH_RESET */
289 #define BIT_FIFO_FLUSH              0x02
290 /* REG_INTF_CONFIG0 */
291 #define BIT_FIFO_COUNT_REC          0x40
292 #define BIT_COUNT_BIG_ENDIAN        0x20
293 #define BIT_SENS_DATA_BIG_ENDIAN    0x10
294 #define BIT_UI_SIFS_DISABLE_SPI     0x02
295 #define BIT_UI_SIFS_DISABLE_I2C     0x03
296 /* REG_FIFO_CONFIG1 */
297 #define BIT_FIFO_ACCEL_EN           0x01
298 #define BIT_FIFO_GYRO_EN            0x02
299 #define BIT_FIFO_TEMP_EN            0x04
300 #define BIT_FIFO_TMST_FSYNC_EN      0x08
301 #define BIT_FIFO_HIRES_EN           0x10
302 #define BIT_FIFO_WM_TH              0x20
303 #define BIT_FIFO_RESUME_PART_RD     0x40
304 /* REG_INT_CONFIG1 */
305 #define BIT_INT_ASY_RST_DISABLE     0x10
306 /* REG_INT_SOURCE0 */
307 #define BIT_INT_UI_AGC_RDY_INT1_EN  0x01
308 #define BIT_INT_FIFO_FULL_INT1_EN   0x02
309 #define BIT_INT_FIFO_THS_INT1_EN    0x04
310 #define BIT_INT_UI_DRDY_INT1_EN     0x08
311 #define BIT_INT_RESET_DONE_INT1_EN  0x10
312 #define BIT_INT_PLL_RDY_INT1_EN     0x20
313 #define BIT_INT_UI_FSYNC_INT1_EN    0x40
314 /* REG_INT_SOURCE1 */
315 #define BIT_INT_WOM_X_INT1_EN       0x01
316 #define BIT_INT_WOM_Y_INT1_EN       0x02
317 #define BIT_INT_WOM_Z_INT1_EN       0x04
318 #define BIT_INT_SMD_INT1_EN         0x08
319 #define BIT_INT_WOM_XYZ_INT1_EN     (BIT_INT_WOM_X_INT1_EN | BIT_INT_WOM_Y_INT1_EN | BIT_INT_WOM_Z_INT1_EN)
320 /* REG_SELF_TEST_CONFIG */
321 #define BIT_SELF_TEST_REGULATOR_EN  0x40
322 #define BIT_TEST_AZ_EN              0x20
323 #define BIT_TEST_AY_EN              0x10
324 #define BIT_TEST_AX_EN              0x08
325 #define BIT_TEST_GZ_EN              0x04
326 #define BIT_TEST_GY_EN              0x02
327 #define BIT_TEST_GX_EN              0x01
328 /* REG_INT_STATUS */
329 #define BIT_INT_STATUS_AGC_RDY      0x01
330 #define BIT_INT_STATUS_FIFO_FULL    0x02
331 #define BIT_INT_STATUS_FIFO_THS     0x04
332 #define BIT_INT_STATUS_DRDY         0x08
333 #define BIT_INT_STATUS_RESET_DONE   0x10
334 #define BIT_INT_STATUS_PLL_DRY      0x20
335 #define BIT_INT_STATUS_UI_FSYNC     0x40
336 /* REG_INT_STATUS2 */
337 #define BIT_INT_STATUS_WOM_X        0x01
338 #define BIT_INT_STATUS_WOM_Y        0x02
339 #define BIT_INT_STATUS_WOM_Z        0x04
340 #define BIT_INT_STATUS_SMD          0x08
341 #define BIT_INT_STATUS_WOM_XYZ      (BIT_INT_STATUS_WOM_X | BIT_INT_STATUS_WOM_Y | BIT_INT_STATUS_WOM_Z)
342 /* REG_FIFO_CONFIG */
343 #define BIT_FIFO_MODE_BYPASS        0x00
344 #define BIT_FIFO_MODE_STREAM        0x40
345 #define BIT_FIFO_MODE_STOP_FULL     0x80
346 /* REG_GYRO_ACCEL_CONFIG0 */
347 #define BIT_ACCEL_UI_BW_2_FIR       0x00
348 #define BIT_ACCEL_UI_BW_4_IIR       0x10
349 #define BIT_ACCEL_UI_BW_5_IIR       0x20
350 #define BIT_ACCEL_UI_BW_8_IIR       0x30
351 #define BIT_ACCEL_UI_BW_10_IIR      0x40
352 #define BIT_ACCEL_UI_BW_16_IIR      0x50
353 #define BIT_ACCEL_UI_BW_20_IIR      0x60
354 #define BIT_ACCEL_UI_BW_40_IIR      0x70
355 #define BIT_GYRO_UI_BW_2_FIR        0x00
356 #define BIT_GYRO_UI_BW_4_IIR        0x01
357 #define BIT_GYRO_UI_BW_5_IIR        0x02
358 #define BIT_GYRO_UI_BW_8_IIR        0x03
359 #define BIT_GYRO_UI_BW_10_IIR       0x04
360 #define BIT_GYRO_UI_BW_16_IIR       0x05
361 #define BIT_GYRO_UI_BW_20_IIR       0x06
362 #define BIT_GYRO_UI_BW_40_IIR       0x07
363 /* fifo data packet header */
364 #define BIT_FIFO_HEAD_MSG           0x80
365 #define BIT_FIFO_HEAD_ACCEL         0x40
366 #define BIT_FIFO_HEAD_GYRO          0x20
367 #define BIT_FIFO_HEAD_TMSP_ODR      0x08
368 #define BIT_FIFO_HEAD_TMSP_NO_ODR   0x04
369 #define BIT_FIFO_HEAD_TMSP_FSYNC    0x0C
370 #define BIT_FIFO_HEAD_ODR_ACCEL     0x02
371 #define BIT_FIFO_HEAD_ODR_GYRO      0x01
372 /* REG_SMD_CONFIG */
373 #define BIT_WOM_INT_MODE_OR         0x00
374 #define BIT_WOM_INT_MODE_AND        0x08
375 #define BIT_WOM_MODE_INITIAL        0x00
376 #define BIT_WOM_MODE_PREV           0x04
377 #define BIT_SMD_MODE_OFF            0x00
378 #define BIT_SMD_MODE_OLD            0x01
379 #define BIT_SMD_MODE_SHORT          0x02
380 #define BIT_SMD_MODE_LONG           0x03
381 /* REG_TMST_CONFIG */
382 #define BIT_EN_DREG_FIFO_D2A        0x20
383 #define BIT_TMST_TO_REGS_EN         0x10
384 #define BIT_TMST_RESOL              0x08
385 #define BIT_TMST_DELTA_EN           0x04
386 #define BIT_TMST_FSYNC_EN           0x02
387 #define BIT_TMST_EN                 0x01
388 
389 /* FIFO data definitions */
390 #define FIFO_PACKET_SIZE            16
391 #define FIFO_MAX_PACKET_NB          65
392 #define FIFO_MIN_PACKET_NB          62
393 
394 /* sensor startup time */
395 #define ICM40600_GYRO_START_TIME_MS     40
396 #define ICM40600_ACCEL_START_TIME_MS    10
397 
398 /* temperature sensor */
399 #define TEMP_SCALE                  (128.0f / 115.49f)      // scale, #9447
400 #define TEMP_OFFSET                 25                      // 25 degC offset
401 
402 #define SPI_WRITE_0(addr, data) spiQueueWrite(addr, data, 2)
403 #define SPI_WRITE_1(addr, data, delay) spiQueueWrite(addr, data, delay)
404 #define GET_SPI_WRITE_MACRO(_1,_2,_3,NAME,...) NAME
405 #define SPI_WRITE(...) GET_SPI_WRITE_MACRO(__VA_ARGS__, SPI_WRITE_1, SPI_WRITE_0)(__VA_ARGS__)
406 
407 #define SPI_READ_0(addr, size, buf) spiQueueRead(addr, size, buf, 0)
408 #define SPI_READ_1(addr, size, buf, delay) spiQueueRead(addr, size, buf, delay)
409 #define GET_SPI_READ_MACRO(_1,_2,_3,_4,NAME,...) NAME
410 #define SPI_READ(...) GET_SPI_READ_MACRO(__VA_ARGS__, SPI_READ_1, SPI_READ_0)(__VA_ARGS__)
411 
412 #define EVT_SENSOR_MAG_DATA_RDY sensorGetMyEventType(SENS_TYPE_MAG)
413 #define EVT_SENSOR_NO_MOTION sensorGetMyEventType(SENS_TYPE_NO_MOTION)
414 #define EVT_SENSOR_ANY_MOTION sensorGetMyEventType(SENS_TYPE_ANY_MOTION)
415 
416 #define MAX_NUM_COMMS_EVENT_SAMPLES 15
417 
418 #define SPI_PACKET_SIZE     30
419 #define FIFO_READ_SIZE      (FIFO_MAX_PACKET_NB * FIFO_PACKET_SIZE)
420 #define BUF_MARGIN          32   // some extra buffer for additional reg RW when a FIFO read happens
421 #define SPI_BUF_SIZE        (FIFO_READ_SIZE + BUF_MARGIN)
422 
423 #define ACC_FS_RANGE        (16 >> ICM40600_ACC_FS)
424 #define GYR_FS_RANGE        (2000 >> ICM40600_GYR_FS)
425 #define GRAVITY_NORM        9.80665f
426 #define kScale_acc          (GRAVITY_NORM * ACC_FS_RANGE / 32768.0f)
427 #define kScale_gyr          (NANO_PI / 180.0f * GYR_FS_RANGE / 32768.0f)
428 
429 #define RATE_TO_HZ              SENSOR_HZ(1.0f)
430 #define DECIMATION_HIGH_RATE    SENSOR_HZ(1000.0f)
431 #define DECIMATION_LOW_RATE     SENSOR_HZ(25.0f)
432 #define NO_DECIMATION_MAX_RATE  SENSOR_HZ(200.0f)   // will set ODR to DECIMATION_HIGH_RATE if more than this rate
433 #define NO_DECIMATION_MIN_RATE  SENSOR_HZ(25.0f)    // will set ODR to DECIMATION_LOW_RATE if less than this rate
434 #define MAX_BATCH_SIZE          (((FIFO_MIN_PACKET_NB * 90) / 100) * FIFO_PACKET_SIZE)      // 90% of FIFO size
435 
436 /* skip first some samples */
437 #define ACC_SKIP_SAMPLE_NB          0
438 #define GYR_SKIP_SAMPLE_NB          3
439 
440 #define CHIP_TIME_RES_US        1
441 #define CHIP_TIME_OFFSET_US     64000000ULL // 64sec
442 #define MIN_INCREMENT_TIME_NS   1000000ULL  // 1ms for 1000Hz
443 
444 enum SensorIndex {
445     FIRST_CONT_SENSOR = 0,
446     ACC = FIRST_CONT_SENSOR,
447     GYR,
448     NUM_CONT_SENSOR,
449     FIRST_ONESHOT_SENSOR = NUM_CONT_SENSOR,
450     WOM = FIRST_ONESHOT_SENSOR,
451     NOMO,
452     NUM_OF_SENSOR,
453 };
454 
455 enum SensorEvents {
456     NO_EVT = -1,
457     EVT_SPI_DONE = EVT_APP_START + 1,
458     EVT_SENSOR_INTERRUPT_1,
459 };
460 
461 enum IntState {
462     INT_READ_STATUS,
463     INT_PROCESS_STATUS,
464     INT_READ_FIFO_DATA,
465     INT_DONE,
466 };
467 
468 enum InitState {
469     RESET_ICM40600,
470     INIT_ICM40600,
471     INIT_DONE,
472 };
473 
474 enum CalibrationState {
475     CALIBRATION_START,
476     CALIBRATION_READ_STATUS,
477     CALIBRATION_READ_DATA,
478     CALIBRATION_SET_OFFSET,
479     CALIBRATION_DONE
480 };
481 
482 enum SelfTestState {
483     TEST_START,
484     TEST_READ_STATUS,
485     TEST_READ_DATA,
486     TEST_READ_OTP,
487     TEST_REPORT,
488     TEST_DONE
489 };
490 
491 enum SensorState {
492     // keep this in sync with getStateName
493     SENSOR_BOOT,
494     SENSOR_VERIFY_ID,
495     SENSOR_INITIALIZING,
496     SENSOR_IDLE,
497     SENSOR_POWERING_UP,
498     SENSOR_POWERING_DOWN,
499     SENSOR_CONFIG_CHANGING,
500     SENSOR_INT_1_HANDLING,
501     SENSOR_CALIBRATING,
502     SENSOR_TESTING,
503     SENSOR_SAVE_CALIBRATION,
504     SENSOR_NUM_OF_STATE
505 };
506 #if DBG_STATE
507 #define PRI_STATE "s"
getStateName(int32_t s)508 static const char * getStateName(int32_t s) {
509     // keep this in sync with SensorState
510     static const char* const l[] = {"BOOT", "VERIFY_ID", "INIT", "IDLE", "PWR_UP",
511             "PWR_DN", "CFG_CHANGE", "INT1", "CALIB", "TEST", "SAVE_CALIB"};
512     if (s >= 0 && s < SENSOR_NUM_OF_STATE) {
513         return l[s];
514     }
515     return "???";
516 #else
517 #define PRI_STATE PRIi32
518 static int32_t getStateName(int32_t s) {
519     return s;
520 #endif
521 }
522 
523 #if DBG_TIMESTAMP
524 struct StatisticsSet {
525     uint32_t sync_reset_count;
526     uint32_t sync_count;
527     uint32_t sync_adjust_plus;
528     uint32_t sync_adjust_minus;
529     uint32_t sync_truncate;
530 };
531 #endif
532 
533 struct ConfigStat {
534     uint64_t latency;
535     uint32_t rate;
536     bool enable;
537 };
538 
539 struct CalibrationData {
540     struct HostHubRawPacket header;
541     struct SensorAppEventHeader data_header;
542     int32_t xBias;
543     int32_t yBias;
544     int32_t zBias;
545 } __attribute__((packed));
546 
547 struct TestResultData {
548     struct HostHubRawPacket header;
549     struct SensorAppEventHeader data_header;
550 } __attribute__((packed));
551 
552 struct ICM40600Sensor {
553     struct ConfigStat pConfig; // pending config status request
554     struct TripleAxisDataEvent *data_evt;
555     uint32_t handle;
556     uint32_t rate;
557     uint64_t latency;
558     uint64_t prev_rtc_time;
559     int16_t offset[3];
560     int16_t data[3];
561     bool updated;
562     bool powered; // activate status
563     bool configed; // configure status
564     bool wait_for_odr;
565     enum SensorIndex idx;
566     uint8_t flush;
567     uint8_t decimator;
568     uint8_t data_cnt;
569     uint8_t skip_sample_cnt;
570 };
571 
572 struct FifoPacketData {
573     int16_t accel[3];
574     int16_t gyro[3];
575     uint16_t timestamp;
576     bool odr_accel;
577     bool odr_gyro;
578     bool valid_accel;
579     bool valid_gyro;
580     int8_t temp;
581 };
582 
583 struct ICM40600FactoryCal {
584     int32_t data[3];
585     int32_t data_count;
586 };
587 
588 struct ICM40600SelfTest {
589     int32_t data[3];
590     int32_t data_st_on[3];
591     int32_t data_st_off[3];
592     int32_t data_count;
593     bool st_mode;
594     uint8_t otp_st_data_gyro[3];
595     uint8_t otp_st_data_accel[3];
596 };
597 
598 struct ICM40600Config {
599     uint32_t accel_rate;
600     uint32_t gyro_rate;
601     uint32_t wom_threshold;
602     uint32_t fifo_rate;
603     uint16_t fifo_watermark;
604     uint8_t fifo_sample_size;
605     bool accel_on;
606     bool gyro_on;
607     bool wom_on;
608 };
609 
610 struct ICM40600Task {
611     uint32_t tid;
612     struct ICM40600Sensor sensors[NUM_OF_SENSOR];
613 
614     // spi and interrupt
615     spi_cs_t cs;
616     struct SpiMode mode;
617     struct SpiPacket packets[SPI_PACKET_SIZE];
618     struct SpiDevice *spiDev;
619     struct Gpio *Int1;
620     IRQn_Type Irq1;
621     struct ChainedIsr Isr1;
622     bool Int1_EN;
623 
624     // spi buffers
625     uint8_t *dataBuffer[3];
626     uint8_t txrxBuffer[SPI_BUF_SIZE];
627 
628     // states
629     volatile uint8_t state;  //task state, type enum SensorState, do NOT change this directly
630     enum InitState init_state;
631     enum IntState int_state;
632     enum CalibrationState calibration_state;
633     enum SelfTestState selftest_state;
634 
635     // pending config
636     bool pending_int[1];
637     bool pending_flush;
638     bool pending_config[NUM_OF_SENSOR];
639     bool pending_calibration_save;
640 
641     struct ICM40600Config config;
642     uint32_t noMotionTimerHandle;
643     uint16_t fifo_count;
644     bool powered;
645     bool flush;
646 
647     // calibration
648 #ifdef ACCEL_CAL_ENABLED
649     struct AccelCal accel_cal;
650 #endif
651 #ifdef GYRO_CAL_ENABLED
652     struct GyroCal gyro_cal;
653 #endif
654 
655     // timestamping
656     time_sync_t gSensorTime2RTC;
657     uint64_t data_timestamp;
658     uint64_t chip_time_us;
659     uint64_t last_sync_time;
660     uint64_t last_sync_data_ts;
661     uint16_t chip_timestamp;
662     bool fifo_start_sync;
663 
664     // temperature data from chip in degC
665     float chip_temperature;
666 
667     // spi rw
668     struct SlabAllocator *mDataSlab;
669     uint16_t mWbufCnt;
670     uint8_t mRegCnt;
671     uint8_t mRetryLeft;
672     bool spiInUse;
673 
674     struct ICM40600FactoryCal factory_cal;
675 
676     struct ICM40600SelfTest self_test;
677 
678 #if DBG_TIMESTAMP
679     struct StatisticsSet statistics_set;
680 #endif
681 };
682 
683 static uint32_t AccRates[] = {
684     SENSOR_HZ(25.0f/8.0f),
685     SENSOR_HZ(25.0f/4.0f),
686     SENSOR_HZ(25.0f/2.0f),
687     SENSOR_HZ(25.0f),
688     SENSOR_HZ(50.0f),
689     SENSOR_HZ(100.0f),
690     SENSOR_HZ(200.0f),
691     SENSOR_HZ(500.0f),
692     0,
693 };
694 
695 static uint32_t GyrRates[] = {
696     SENSOR_HZ(25.0f/8.0f),
697     SENSOR_HZ(25.0f/4.0f),
698     SENSOR_HZ(25.0f/2.0f),
699     SENSOR_HZ(25.0f),
700     SENSOR_HZ(50.0f),
701     SENSOR_HZ(100.0f),
702     SENSOR_HZ(200.0f),
703     SENSOR_HZ(500.0f),
704     0,
705 };
706 
707 static struct ICM40600Task mTask;
708 
709 #define DEC_INFO(name, type, axis, inter, samples) \
710     .sensorName = name, \
711     .sensorType = type, \
712     .numAxis = axis, \
713     .interrupt = inter, \
714     .minSamples = samples
715 
716 #define DEC_INFO_RATE(name, rates, type, axis, inter, samples) \
717     DEC_INFO(name, type, axis, inter, samples), \
718     .supportedRates = rates
719 
720 #define DEC_INFO_RATE_RAW(name, rates, type, axis, inter, samples, raw, scale) \
721     DEC_INFO(name, type, axis, inter, samples), \
722     .supportedRates = rates, \
723     .flags1 = SENSOR_INFO_FLAGS1_RAW, \
724     .rawType = raw, \
725     .rawScale = scale
726 
727 #define DEC_INFO_RATE_BIAS(name, rates, type, axis, inter, samples, bias) \
728     DEC_INFO(name, type, axis, inter, samples), \
729     .supportedRates = rates, \
730     .flags1 = SENSOR_INFO_FLAGS1_BIAS, \
731     .biasType = bias
732 
733 #define DEC_INFO_RATE_RAW_BIAS(name, rates, type, axis, inter, samples, raw, scale, bias) \
734     DEC_INFO_RATE_RAW(name, rates, type, axis, inter, samples, raw, scale), \
735     .flags1 = SENSOR_INFO_FLAGS1_RAW | SENSOR_INFO_FLAGS1_BIAS, \
736     .biasType = bias
737 
738 typedef struct ICM40600Task _Task;
739 #define TASK  _Task* const _task
740 
741 // To get rid of static variables all task functions should have a task structure pointer input.
742 // This is an intermediate step.
743 #define TDECL()  TASK = &mTask; (void)_task
744 
745 // Access task variables without explicitly specify the task structure pointer.
746 #define T(v)  (_task->v)
747 
748 // Atomic get state
749 #define GET_STATE() (atomicReadByte(&(_task->state)))
750 
751 // Atomic set state, this set the state to arbitrary value, use with caution
752 #define SET_STATE(s) do{\
753         DEBUG_PRINT_IF(DBG_STATE, "set state %" PRI_STATE "\n", getStateName(s));\
754         atomicWriteByte(&(_task->state), (s));\
755     }while(0)
756 
757 // Atomic switch state from IDLE to desired state.
758 static bool trySwitchState_(TASK, enum SensorState newState) {
759 #if DBG_STATE
760     bool ret = atomicCmpXchgByte(&T(state), SENSOR_IDLE, newState);
761     uint8_t prevState = ret ? SENSOR_IDLE : GET_STATE();
762     DEBUG_PRINT("switch state %" PRI_STATE "->%" PRI_STATE ", %s\n",
763             getStateName(prevState), getStateName(newState), ret ? "ok" : "failed");
764     return ret;
765 #else
766     return atomicCmpXchgByte(&T(state), SENSOR_IDLE, newState);
767 #endif
768 }
769 // Short-hand
770 #define trySwitchState(s) trySwitchState_(_task, (s))
771 
772 static const struct SensorInfo mSensorInfo[NUM_OF_SENSOR] =
773 {
774 #ifdef ACCEL_CAL_ENABLED
775     { DEC_INFO_RATE_RAW_BIAS("Accelerometer", AccRates, SENS_TYPE_ACCEL, NUM_AXIS_THREE,
776             NANOHUB_INT_NONWAKEUP, 3000, SENS_TYPE_ACCEL_RAW, 1.0 / kScale_acc, SENS_TYPE_ACCEL_BIAS) },
777 #else
778     { DEC_INFO_RATE_RAW("Accelerometer", AccRates, SENS_TYPE_ACCEL, NUM_AXIS_THREE,
779             NANOHUB_INT_NONWAKEUP, 3000, SENS_TYPE_ACCEL_RAW, 1.0 / kScale_acc) },
780 #endif
781 #ifdef GYRO_CAL_ENABLED
782     { DEC_INFO_RATE_BIAS("Gyroscope", GyrRates, SENS_TYPE_GYRO, NUM_AXIS_THREE,
783             NANOHUB_INT_NONWAKEUP, 20, SENS_TYPE_GYRO_BIAS) },
784 #else
785     { DEC_INFO_RATE("Gyroscope", GyrRates, SENS_TYPE_GYRO, NUM_AXIS_THREE,
786             NANOHUB_INT_NONWAKEUP, 20) },
787 #endif
788     { DEC_INFO("Wake-on-Motion", SENS_TYPE_ANY_MOTION, NUM_AXIS_EMBEDDED, NANOHUB_INT_NONWAKEUP, 20) },
789     { DEC_INFO("No-Motion", SENS_TYPE_NO_MOTION, NUM_AXIS_EMBEDDED, NANOHUB_INT_NONWAKEUP, 20) },
790 };
791 
792 static void time_init(TASK)
793 {
794     time_sync_init(&T(gSensorTime2RTC));
795 }
796 
797 static bool sensortime_to_rtc_time(TASK, uint64_t sensor_time, uint64_t *rtc_time_ns)
798 {
799     return time_sync_estimate_time1(&T(gSensorTime2RTC), sensor_time, rtc_time_ns);
800 }
801 
802 static void map_sensortime_to_rtc_time(TASK, uint64_t sensor_time, uint64_t rtc_time_ns)
803 {
804 #if DBG_TIMESTAMP
805     T(statistics_set).sync_count++;
806 #endif
807     time_sync_add(&T(gSensorTime2RTC), rtc_time_ns, sensor_time);
808 }
809 
810 static void invalidate_sensortime_to_rtc_time(TASK)
811 {
812 #if DBG_TIMESTAMP
813     T(statistics_set).sync_reset_count++;
814 #endif
815     time_sync_reset(&T(gSensorTime2RTC));
816 }
817 
818 static void dataEvtFree(void *ptr)
819 {
820     TDECL();
821     struct TripleAxisDataEvent *ev = (struct TripleAxisDataEvent *)ptr;
822 
823     slabAllocatorFree(T(mDataSlab), ev);
824 }
825 
826 static void spiQueueWrite(uint8_t addr, uint8_t data, uint32_t delay)
827 {
828     TDECL();
829 
830     if (T(spiInUse)) {
831         ERROR_PRINT("SPI in use, cannot queue write\n");
832         return;
833     }
834     T(packets[T(mRegCnt)]).size = 2;
835     T(packets[T(mRegCnt)]).txBuf = &T(txrxBuffer[T(mWbufCnt)]);
836     T(packets[T(mRegCnt)]).rxBuf = &T(txrxBuffer[T(mWbufCnt)]);
837     T(packets[T(mRegCnt)]).delay = delay * 1000;
838     T(txrxBuffer[T(mWbufCnt++)]) = ICM40600_SPI_WRITE | addr;
839     T(txrxBuffer[T(mWbufCnt++)]) = data;
840     T(mRegCnt)++;
841 }
842 
843 /*
844  * need to be sure size of buf is larger than read size
845  */
846 static void spiQueueRead(uint8_t addr, size_t size, uint8_t **buf, uint32_t delay)
847 {
848     TDECL();
849 
850     if (T(spiInUse)) {
851         ERROR_PRINT("SPI in use, cannot queue read %d %d\n", (int)addr, (int)size);
852         return;
853     }
854 
855     *buf = &T(txrxBuffer[T(mWbufCnt)]);
856     T(packets[T(mRegCnt)]).size = size + 1; // first byte will not contain valid data
857     T(packets[T(mRegCnt)]).txBuf = &T(txrxBuffer[T(mWbufCnt)]);
858     T(packets[T(mRegCnt)]).rxBuf = *buf;
859     T(packets[T(mRegCnt)]).delay = delay * 1000;
860     T(txrxBuffer[T(mWbufCnt)++]) = ICM40600_SPI_READ | addr;
861     T(mWbufCnt) += size;
862     T(mRegCnt)++;
863 }
864 
865 static void spiBatchTxRx(struct SpiMode *mode,
866         SpiCbkF callback, void *cookie, const char * src)
867 {
868     TDECL();
869 
870     if (T(mRegCnt) == 0) {
871         callback(cookie, 0);
872         return;
873     }
874 
875     if (T(mWbufCnt) > SPI_BUF_SIZE) {
876         ERROR_PRINT("NO enough SPI buffer space, dropping transaction.\n");
877         return;
878     }
879     if (T(mRegCnt) > SPI_PACKET_SIZE) {
880         ERROR_PRINT("spiBatchTxRx too many packets!\n");
881         return;
882     }
883 
884     T(spiInUse) = true;
885     T(mWbufCnt) = 0;
886 
887     // Reset variables before issuing SPI transaction.
888     // SPI may finish before spiMasterRxTx finish
889     uint8_t regCount = T(mRegCnt);
890     T(mRegCnt) = 0;
891 
892     if (spiMasterRxTx(T(spiDev), T(cs), T(packets), regCount, mode, callback, cookie) < 0) {
893         ERROR_PRINT("spiMasterRxTx failed!\n");
894     }
895 }
896 
897 static bool icm40600Isr1(struct ChainedIsr *isr)
898 {
899     TASK = container_of(isr, struct ICM40600Task, Isr1);
900 
901     if (!extiIsPendingGpio(T(Int1))) {
902         return false;
903     }
904 
905     /* better to use atomic read for the pending flag but not serious even not atomic */
906     if (!T(pending_int[0])) {
907         osEnqueuePrivateEvt(EVT_SENSOR_INTERRUPT_1, _task, NULL, T(tid));
908     }
909     extiClearPendingGpio(T(Int1));
910     return true;
911 }
912 
913 static void sensorSpiCallback(void *cookie, int err)
914 {
915     TDECL();
916 
917     T(spiInUse) = false;
918 
919     if (!osEnqueuePrivateEvt(EVT_SPI_DONE, cookie, NULL, T(tid)))
920         ERROR_PRINT("sensorSpiCallback: osEnqueuePrivateEvt() failed\n");
921 }
922 
923 static void noMotionCallback(uint32_t timerId, void *data)
924 {
925     const struct ICM40600Sensor *sensor = (const struct ICM40600Sensor *)data;
926 
927     if (!sensor->configed)
928         return;
929 
930     osEnqueueEvt(EVT_SENSOR_NO_MOTION, NULL, NULL);
931 }
932 
933 static void setOffsetReg(TASK)
934 {
935     uint8_t val;
936     const int16_t * const acc_offset = T(sensors[ACC]).offset;
937     const int16_t * const gyr_offset = T(sensors[GYR]).offset;
938 
939     DEBUG_PRINT("Set ACC hw offset %d %d %d\n",
940                 -acc_offset[0], -acc_offset[1], -acc_offset[2]);
941     DEBUG_PRINT("Set GYR hw offset %d %d %d\n",
942                 -gyr_offset[0], -gyr_offset[1], -gyr_offset[2]);
943 
944     // GX_L
945     val = (-gyr_offset[0]) & 0xff;
946     SPI_WRITE(REG_GOS_USER0, val);
947     // GY_H / GX_H
948     val = (-gyr_offset[1] >> 4) & 0xf0;
949     val |= ((-gyr_offset[0] >> 8) & 0x0f);
950     SPI_WRITE(REG_GOS_USER1, val);
951     // GY_L
952     val = (-gyr_offset[1]) & 0xff;
953     SPI_WRITE(REG_GOS_USER2, val);
954     // GZ_L
955     val = (-gyr_offset[2]) & 0xff;
956     SPI_WRITE(REG_GOS_USER3, val);
957     // AX_H / GZ_H
958     val = (-acc_offset[0] >> 4) & 0xf0;
959     val |= ((-gyr_offset[2] >> 8) & 0x0f);
960     SPI_WRITE(REG_GOS_USER4, val);
961     // AX_H / GZ_H
962     val = (-acc_offset[0] >> 4) & 0xf0;
963     val |= ((-gyr_offset[2] >> 8) & 0x0f);
964     SPI_WRITE(REG_GOS_USER4, val);
965     // AX_L
966     val = (-acc_offset[0]) & 0xff;
967     SPI_WRITE(REG_GOS_USER5, val);
968     // AY_L
969     val = (-acc_offset[1]) & 0xff;
970     SPI_WRITE(REG_GOS_USER6, val);
971     // AZ_H / AY_H
972     val = (-acc_offset[2] >> 4) & 0xf0;
973     val |= ((-acc_offset[1] >> 8) & 0x0f);
974     SPI_WRITE(REG_GOS_USER7, val);
975     // AZ_L
976     val = (-acc_offset[2]) & 0xff;
977     SPI_WRITE(REG_GOS_USER8, val);
978 }
979 
980 static void resetOffsetReg(TASK, enum SensorIndex idx)
981 {
982     uint8_t val;
983 
984     DEBUG_PRINT("Reset offset registers sensor=%d\n", idx);
985 
986     if (idx == ACC) {
987         val = (-T(sensors[GYR]).offset[2] >> 8) & 0x0f;
988         SPI_WRITE(REG_GOS_USER4, val);  // AX_H / GZ_H
989         SPI_WRITE(REG_GOS_USER5, 0x00); // AX_L
990         SPI_WRITE(REG_GOS_USER6, 0x00); // AY_L
991         SPI_WRITE(REG_GOS_USER7, 0x00); // AZ_H / AY_H
992         SPI_WRITE(REG_GOS_USER8, 0x00); // AZ_L
993     } else if (idx == GYR) {
994         SPI_WRITE(REG_GOS_USER0, 0x00); // GX_L
995         SPI_WRITE(REG_GOS_USER1, 0x00); // GY_H / GX_H
996         SPI_WRITE(REG_GOS_USER2, 0x00); // GY_L
997         SPI_WRITE(REG_GOS_USER3, 0x00); // GZ_L
998         val = (-T(sensors[ACC]).offset[0] >> 4) & 0xf0;
999         SPI_WRITE(REG_GOS_USER4, val);  // AX_H / GZ_H
1000     }
1001 }
1002 
1003 static bool saveCalibration(TASK)
1004 {
1005     if (trySwitchState(SENSOR_SAVE_CALIBRATION)) {
1006         setOffsetReg(_task);
1007         spiBatchTxRx(&T(mode), sensorSpiCallback, _task, __FUNCTION__);
1008         return true;
1009     } else {
1010         return false;
1011     }
1012 }
1013 
1014 static bool accCfgData(void *data, void *cookie)
1015 {
1016     TDECL();
1017     struct ICM40600Sensor *sensor = &T(sensors[ACC]);
1018     struct CfgData {
1019         int32_t hw[3];  // chip frame (hw unit @FSR=factory calibration)
1020         float sw[3];    // body frame
1021     };
1022     struct CfgData *values = data;
1023     int i;
1024 
1025     for (i = 0; i < 3; i++) {
1026         // offset register is 12bit
1027         if (values->hw[i] > 2047) {
1028             sensor->offset[i] = 2047;
1029         } else if (values->hw[i] < -2048) {
1030             sensor->offset[i] = -2048;
1031         } else {
1032             sensor->offset[i] = values->hw[i];
1033         }
1034     }
1035 #ifdef ACCEL_CAL_ENABLED
1036     accelCalBiasSet(&T(accel_cal), values->sw[0], values->sw[1], values->sw[2]);
1037 #endif
1038     if (!saveCalibration(_task)) {
1039         T(pending_calibration_save) = true;
1040     }
1041     INFO_PRINT("accCfgData hw bias: data=%d, %d, %d\n",
1042             sensor->offset[0], sensor->offset[1], sensor->offset[2]);
1043 
1044     return true;
1045 }
1046 
1047 static bool gyrCfgData(void *data, void *cookie)
1048 {
1049     TDECL();
1050     struct ICM40600Sensor *sensor = &T(sensors[GYR]);
1051     const struct AppToSensorHalDataPayload *p = data;
1052     int i;
1053 
1054     if (p->type == HALINTF_TYPE_GYRO_CAL_BIAS && p->size == sizeof(struct GyroCalBias)) {
1055         const struct GyroCalBias *bias = p->gyroCalBias;
1056         for (i = 0; i < 3; i++) {
1057             // offset register is 12bit
1058             if (bias->hardwareBias[i] > 2047) {
1059                 sensor->offset[i] = 2047;
1060             } else if (bias->hardwareBias[i] < -2048) {
1061                 sensor->offset[i] = -2048;
1062             } else {
1063                 sensor->offset[i] = bias->hardwareBias[i];
1064             }
1065         }
1066 #ifdef GYRO_CAL_ENABLED
1067         gyroCalSetBias(&T(gyro_cal), bias->softwareBias[0], bias->softwareBias[1],
1068                        bias->softwareBias[2], sensorGetTime());
1069 #endif
1070         if (!saveCalibration(_task)) {
1071             T(pending_calibration_save) = true;
1072         }
1073         INFO_PRINT("gyrCfgData hw bias: data=%d, %d, %d\n",
1074                 sensor->offset[0], sensor->offset[1], sensor->offset[2]);
1075     } else if (p->type == HALINTF_TYPE_GYRO_OTC_DATA && p->size == sizeof(struct GyroOtcData)) {
1076         // Over-temperature gyro calibration not supported
1077     } else {
1078         ERROR_PRINT("Unknown gyro config data type 0x%04x, size %d\n", p->type, p->size);
1079     }
1080 
1081     return true;
1082 }
1083 
1084 static bool validateFifoData(const int16_t data[3])
1085 {
1086     bool ret = true;
1087 
1088     if ((data[0] == -32768) && (data[1] == -32768) && (data[2] == -32768))
1089         ret = false;
1090 
1091     return ret;
1092 }
1093 
1094 static void getFifoData(const uint8_t *data, int idx, struct FifoPacketData *out)
1095 {
1096     /* invalidate all flags */
1097     out->valid_accel = false;
1098     out->valid_gyro = false;
1099 
1100     /* Header        : 1 byte
1101      * Accel         : 6 byte
1102      * Gyro          : 6 byte
1103      * Temp          : 1 byte
1104      * Timestamp     : 2 byte */
1105     if (data[idx] & BIT_FIFO_HEAD_ACCEL) {
1106         out->accel[0] = (data[idx + 2] << 8) | data[idx + 1];
1107         out->accel[1] = (data[idx + 4] << 8) | data[idx + 3];
1108         out->accel[2] = (data[idx + 6] << 8) | data[idx + 5];
1109         out->valid_accel = validateFifoData(out->accel);
1110     }
1111     out->odr_accel = (data[idx] & BIT_FIFO_HEAD_ODR_ACCEL) ? true : false;
1112 
1113     if (data[idx] & BIT_FIFO_HEAD_GYRO) {
1114         out->gyro[0] = (data[idx + 8] << 8) | data[idx + 7];
1115         out->gyro[1] = (data[idx + 10] << 8) | data[idx + 9];
1116         out->gyro[2] = (data[idx + 12] << 8) | data[idx + 11];
1117         out->valid_gyro = validateFifoData(out->gyro);
1118     }
1119     out->odr_gyro = (data[idx] & BIT_FIFO_HEAD_ODR_GYRO) ? true : false;
1120 
1121     out->temp = (int8_t)data[idx + 13];
1122     out->timestamp = (data[idx + 15] << 8) | data[idx + 14];
1123 }
1124 
1125 static bool calSelftestGetOneData(enum SensorIndex sensor_idx, const uint8_t *data, int idx, int16_t raw_data[3])
1126 {
1127     struct FifoPacketData fifo_data;
1128     bool ret = false;
1129 
1130     getFifoData(data, idx, &fifo_data);
1131 
1132     switch (sensor_idx) {
1133     case ACC:
1134         if (fifo_data.valid_accel) {
1135             raw_data[0] = fifo_data.accel[0];
1136             raw_data[1] = fifo_data.accel[1];
1137             raw_data[2] = fifo_data.accel[2];
1138             ret = true;
1139         }
1140         break;
1141     case GYR:
1142         if (fifo_data.valid_gyro) {
1143             raw_data[0] = fifo_data.gyro[0];
1144             raw_data[1] = fifo_data.gyro[1];
1145             raw_data[2] = fifo_data.gyro[2];
1146             ret = true;
1147         }
1148         break;
1149     default:
1150         break;
1151     }
1152 
1153     return ret;
1154 }
1155 
1156 static void calSelftestFifoEnable(TASK, enum SensorIndex idx, bool en, uint32_t delay)
1157 {
1158     uint8_t val;
1159 
1160     if (en) {
1161         // enable FIFO output
1162         T(config).fifo_sample_size = FIFO_PACKET_SIZE;
1163         val = BIT_FIFO_ACCEL_EN | BIT_FIFO_GYRO_EN |
1164               BIT_FIFO_TEMP_EN | BIT_FIFO_TMST_FSYNC_EN;
1165         SPI_WRITE(REG_FIFO_CONFIG, BIT_FIFO_MODE_STREAM);
1166         SPI_WRITE(REG_FIFO_CONFIG1, val, delay); // with wait
1167     } else {
1168         // disable FIFO output
1169         T(config).fifo_sample_size = 0;
1170         SPI_WRITE(REG_FIFO_CONFIG, BIT_FIFO_MODE_BYPASS);
1171         SPI_WRITE(REG_FIFO_CONFIG1, 0);
1172     }
1173 }
1174 
1175 /*
1176  * Factory calibration
1177  */
1178 static void sendCalibrationResult(uint8_t status, uint8_t sensorType,
1179         int32_t xBias, int32_t yBias, int32_t zBias)
1180 {
1181     struct CalibrationData *data = heapAlloc(sizeof(struct CalibrationData));
1182     if (!data) {
1183         ERROR_PRINT("Couldn't alloc cal result pkt");
1184         return;
1185     }
1186 
1187     data->header.appId = ICM40600_APP_ID;
1188     data->header.dataLen = (sizeof(struct CalibrationData) - sizeof(struct HostHubRawPacket));
1189     data->data_header.msgId = SENSOR_APP_MSG_ID_CAL_RESULT;
1190     data->data_header.sensorType = sensorType;
1191     data->data_header.status = status;
1192 
1193     data->xBias = xBias;
1194     data->yBias = yBias;
1195     data->zBias = zBias;
1196 
1197     if (!osEnqueueEvtOrFree(EVT_APP_TO_HOST, data, heapFree))
1198         ERROR_PRINT("Couldn't send cal result evt");
1199 }
1200 
1201 static void calibrationInit(TASK, enum SensorIndex idx)
1202 {
1203     uint8_t val;
1204 
1205     // Disable Interrupt
1206     SPI_WRITE(REG_INT_SOURCE0, 0);
1207     SPI_WRITE(REG_INT_SOURCE1, 0);
1208 
1209     // reset offset registers
1210     resetOffsetReg(_task, idx);
1211 
1212     // stop FIFO
1213     calSelftestFifoEnable(_task, idx, false, 0);
1214 
1215     // set rate
1216     SPI_WRITE(REG_GYRO_CONFIG0, (CALIBRATION_GYR_FS << SHIFT_GYRO_FS_SEL) |
1217                                 (CALIBRATION_ODR << SHIFT_ODR_CONF));
1218     SPI_WRITE(REG_ACCEL_CONFIG0, (CALIBRATION_ACC_FS << SHIFT_ACCEL_FS_SEL) |
1219                                  (CALIBRATION_ODR << SHIFT_ODR_CONF));
1220 
1221     // set filter
1222     SPI_WRITE(REG_GYRO_ACCEL_CONFIG0, CALIBRATION_ACC_BW_IND | CALIBRATION_GYR_BW_IND);
1223 
1224     // turn on sensors
1225     switch (idx) {
1226     case ACC:
1227         val = BIT_ACCEL_MODE_LN;
1228         break;
1229     case GYR:
1230         val = BIT_GYRO_MODE_LN;
1231         break;
1232     default:
1233         val = 0;
1234         break;
1235     }
1236     SPI_WRITE(REG_PWR_MGMT_0, val, 200 * 1000);
1237 
1238     calSelftestFifoEnable(_task, idx, true, CALIBRATION_READ_INTERVAL_US);
1239 }
1240 
1241 static void calibrationDeinit(TASK, enum SensorIndex idx)
1242 {
1243     calSelftestFifoEnable(_task, idx, false, 0);
1244 
1245     SPI_WRITE(REG_GYRO_ACCEL_CONFIG0, ICM40600_ACC_BW_IND | ICM40600_GYR_BW_IND);
1246     SPI_WRITE(REG_PWR_MGMT_0, 0, 200); // 9136
1247 
1248     // make register accesses happen when sensor is enabled next time
1249     T(config).gyro_rate = 0;
1250     T(config).accel_rate = 0;
1251     T(config).fifo_rate = 0;
1252     T(config).fifo_watermark = 0;
1253     T(config).accel_on = false;
1254     T(config).gyro_on = false;
1255     T(config).wom_on = false;
1256 }
1257 
1258 static void calibrationHandling(TASK, enum SensorIndex idx)
1259 {
1260     const uint8_t *buf, *data;
1261     uint8_t int_status;
1262     uint16_t fifo_count;
1263     int i, t;
1264     bool r;
1265     int16_t raw_data[3] = { 0, 0, 0 };
1266 
1267     if (idx != ACC && idx != GYR) {
1268         ERROR_PRINT("Invalid sensor index\n");
1269         return;
1270     }
1271 
1272     switch (T(calibration_state)) {
1273         case CALIBRATION_START:
1274             T(mRetryLeft) = RETRY_CNT_CALIBRATION;
1275             calibrationInit(_task, idx);
1276             for (i = 0; i < 3; i++) {
1277                 T(factory_cal).data[i] = 0;
1278             }
1279             SPI_READ(REG_INT_STATUS, 1, &T(dataBuffer[0]));
1280             SPI_READ(REG_FIFO_BYTE_COUNT1, 2, &T(dataBuffer[1]));
1281             T(calibration_state) = CALIBRATION_READ_STATUS;
1282             T(factory_cal).data_count = CALIBRATION_SAMPLE_NB;
1283             spiBatchTxRx(&T(mode), sensorSpiCallback, &T(sensors[idx]), __FUNCTION__);
1284             break;
1285         case CALIBRATION_READ_STATUS:
1286             buf = T(dataBuffer[0]);
1287             int_status = buf[1];
1288             buf = T(dataBuffer[1]);
1289             fifo_count = buf[2] << 8 | buf[1];
1290             fifo_count = fifo_count - fifo_count % T(config).fifo_sample_size;
1291             T(fifo_count) = fifo_count;
1292             DEBUG_PRINT("fifo_count = %d\n", fifo_count);
1293             if (int_status & BIT_INT_STATUS_FIFO_FULL) {
1294                 ERROR_PRINT("fifo overflow\n");
1295                 calibrationDeinit(_task, idx);
1296                 T(calibration_state) = CALIBRATION_DONE;
1297                 sendCalibrationResult(SENSOR_APP_EVT_STATUS_ERROR, mSensorInfo[idx].sensorType, 0, 0, 0);
1298             } else {
1299                 T(calibration_state) = CALIBRATION_READ_DATA;
1300                 SPI_READ(REG_FIFO_DATA, fifo_count, &T(dataBuffer[0]));
1301             }
1302             spiBatchTxRx(&T(mode), sensorSpiCallback, &T(sensors[idx]), __FUNCTION__);
1303             break;
1304         case CALIBRATION_READ_DATA:
1305             buf = T(dataBuffer[0]);
1306             data = &buf[1];
1307             for (i = 0; i < T(fifo_count); i += T(config).fifo_sample_size) {
1308                 r = calSelftestGetOneData(idx, data, i, raw_data);
1309                 if (r == false) {
1310                     ERROR_PRINT("invalid data packet\n");
1311                     calibrationDeinit(_task, idx);
1312                     T(calibration_state) = CALIBRATION_DONE;
1313                     sendCalibrationResult(SENSOR_APP_EVT_STATUS_ERROR, mSensorInfo[idx].sensorType, 0, 0, 0);
1314                     break;
1315                 }
1316                 for (t = 0; t < 3; t++) {
1317                     T(factory_cal).data[t] += raw_data[t];
1318                 }
1319                 T(factory_cal).data_count--;
1320                 if (T(factory_cal).data_count == 0) {
1321                     break;
1322                 }
1323             }
1324             if (T(factory_cal).data_count > 0) {
1325                 if (--T(mRetryLeft) == 0) {
1326                     ERROR_PRINT("calibration timeout\n");
1327                     calibrationDeinit(_task, idx);
1328                     T(calibration_state) = CALIBRATION_DONE;
1329                     sendCalibrationResult(SENSOR_APP_EVT_STATUS_ERROR, mSensorInfo[idx].sensorType, 0, 0, 0);
1330                 } else {
1331                     calSelftestFifoEnable(_task, idx, false, 0); // toggle FIFO to reset
1332                     calSelftestFifoEnable(_task, idx, true, CALIBRATION_READ_INTERVAL_US);
1333                     SPI_READ(REG_INT_STATUS, 1, &T(dataBuffer[0]));
1334                     SPI_READ(REG_FIFO_BYTE_COUNT1, 2, &T(dataBuffer[1]));
1335                     T(calibration_state) = CALIBRATION_READ_STATUS;
1336                 }
1337                 spiBatchTxRx(&T(mode), sensorSpiCallback, &T(sensors[idx]), __FUNCTION__);
1338                 break;
1339             }
1340             T(calibration_state) = CALIBRATION_SET_OFFSET;
1341             // fall-through
1342         case CALIBRATION_SET_OFFSET:
1343             DEBUG_PRINT("calibration total: %ld, %ld, %ld, data count=%d\n",
1344                     T(factory_cal).data[0],
1345                     T(factory_cal).data[1],
1346                     T(factory_cal).data[2],
1347                     CALIBRATION_SAMPLE_NB);
1348             for (i = 0; i < 3; i++) {
1349                 T(factory_cal).data[i] /= CALIBRATION_SAMPLE_NB;
1350             }
1351             DEBUG_PRINT("average: %ld, %ld, %ld\n",
1352                     T(factory_cal).data[0],
1353                     T(factory_cal).data[1],
1354                     T(factory_cal).data[2]);
1355             if (idx == ACC) {
1356                 // assume the largest data axis shows +1 or -1 gee
1357                 t = 0;
1358                 for (i = 0; i < 3; i++) {
1359                     if (abs(T(factory_cal).data[i]) > abs(T(factory_cal).data[t]))
1360                         t = i;
1361                 }
1362                 if (T(factory_cal).data[t] > 0) {
1363                     DEBUG_PRINT("assume axis %d is %d\n", t, CALIBRATION_ACC_1G);
1364                     T(factory_cal).data[t] -= CALIBRATION_ACC_1G;
1365                 } else {
1366                     DEBUG_PRINT("assume axis %d is %d\n", t, -CALIBRATION_ACC_1G);
1367                     T(factory_cal).data[t] += CALIBRATION_ACC_1G;
1368                 }
1369             }
1370             // set bias to offset registers
1371             for (i = 0; i < 3; i++) {
1372                 T(sensors[idx]).offset[i] = T(factory_cal).data[i];
1373             }
1374             setOffsetReg(_task);
1375             calibrationDeinit(_task, idx);
1376 
1377             sendCalibrationResult(SENSOR_APP_EVT_STATUS_SUCCESS,
1378                                   mSensorInfo[idx].sensorType,
1379                                   T(factory_cal).data[0],
1380                                   T(factory_cal).data[1],
1381                                   T(factory_cal).data[2]);
1382             INFO_PRINT("reported: %ld, %ld, %ld\n",
1383                         T(factory_cal).data[0],
1384                         T(factory_cal).data[1],
1385                         T(factory_cal).data[2]);
1386             T(calibration_state) = CALIBRATION_DONE;
1387             spiBatchTxRx(&T(mode), sensorSpiCallback, &T(sensors[idx]), __FUNCTION__);
1388             break;
1389         default:
1390             break;
1391     }
1392 }
1393 
1394 static bool accCalibration(void *cookie)
1395 {
1396     TDECL();
1397 
1398     INFO_PRINT("Accel Calibration\n");
1399 
1400     if (!T(powered) && trySwitchState(SENSOR_CALIBRATING)) {
1401         T(calibration_state) = CALIBRATION_START;
1402         calibrationHandling(_task, ACC);
1403         return true;
1404     } else {
1405         ERROR_PRINT("Cannot run calibration because sensor is busy\n");
1406         sendCalibrationResult(SENSOR_APP_EVT_STATUS_BUSY, SENS_TYPE_ACCEL, 0, 0, 0);
1407         return false;
1408     }
1409 }
1410 
1411 static bool gyrCalibration(void *cookie)
1412 {
1413     TDECL();
1414 
1415     INFO_PRINT("Gyro Calibration\n");
1416 
1417     if (!T(powered) && trySwitchState(SENSOR_CALIBRATING)) {
1418         T(calibration_state) = CALIBRATION_START;
1419         calibrationHandling(_task, GYR);
1420         return true;
1421     } else {
1422         ERROR_PRINT("Cannot run calibration because sensor is busy\n");
1423         sendCalibrationResult(SENSOR_APP_EVT_STATUS_BUSY, SENS_TYPE_GYRO, 0, 0, 0);
1424         return false;
1425     }
1426 }
1427 
1428 /*
1429  * Selftest
1430  */
1431 static void sendTestResult(uint8_t status, uint8_t sensorType)
1432 {
1433     struct TestResultData *data = heapAlloc(sizeof(struct TestResultData));
1434     if (!data) {
1435         ERROR_PRINT("Couldn't alloc test result packet");
1436         return;
1437     }
1438 
1439     data->header.appId = ICM40600_APP_ID;
1440     data->header.dataLen = (sizeof(struct TestResultData) - sizeof(struct HostHubRawPacket));
1441     data->data_header.msgId = SENSOR_APP_MSG_ID_TEST_RESULT;
1442     data->data_header.sensorType = sensorType;
1443     data->data_header.status = status;
1444 
1445     if (!osEnqueueEvtOrFree(EVT_APP_TO_HOST, data, heapFree))
1446         ERROR_PRINT("Couldn't send test result packet");
1447 }
1448 
1449 static const uint16_t SelfTestEquation[256] = {
1450     2620, 2646, 2672, 2699, 2726, 2753, 2781, 2808,
1451     2837, 2865, 2894, 2923, 2952, 2981, 3011, 3041,
1452     3072, 3102, 3133, 3165, 3196, 3228, 3261, 3293,
1453     3326, 3359, 3393, 3427, 3461, 3496, 3531, 3566,
1454     3602, 3638, 3674, 3711, 3748, 3786, 3823, 3862,
1455     3900, 3939, 3979, 4019, 4059, 4099, 4140, 4182,
1456     4224, 4266, 4308, 4352, 4395, 4439, 4483, 4528,
1457     4574, 4619, 4665, 4712, 4759, 4807, 4855, 4903,
1458     4953, 5002, 5052, 5103, 5154, 5205, 5257, 5310,
1459     5363, 5417, 5471, 5525, 5581, 5636, 5693, 5750,
1460     5807, 5865, 5924, 5983, 6043, 6104, 6165, 6226,
1461     6289, 6351, 6415, 6479, 6544, 6609, 6675, 6742,
1462     6810, 6878, 6946, 7016, 7086, 7157, 7229, 7301,
1463     7374, 7448, 7522, 7597, 7673, 7750, 7828, 7906,
1464     7985, 8065, 8145, 8227, 8309, 8392, 8476, 8561,
1465     8647, 8733, 8820, 8909, 8998, 9088, 9178, 9270,
1466     9363, 9457, 9551, 9647, 9743, 9841, 9939, 10038,
1467     10139, 10240, 10343, 10446, 10550, 10656, 10763, 10870,
1468     10979, 11089, 11200, 11312, 11425, 11539, 11654, 11771,
1469     11889, 12008, 12128, 12249, 12371, 12495, 12620, 12746,
1470     12874, 13002, 13132, 13264, 13396, 13530, 13666, 13802,
1471     13940, 14080, 14221, 14363, 14506, 14652, 14798, 14946,
1472     15096, 15247, 15399, 15553, 15709, 15866, 16024, 16184,
1473     16346, 16510, 16675, 16842, 17010, 17180, 17352, 17526,
1474     17701, 17878, 18057, 18237, 18420, 18604, 18790, 18978,
1475     19167, 19359, 19553, 19748, 19946, 20145, 20347, 20550,
1476     20756, 20963, 21173, 21385, 21598, 21814, 22033, 22253,
1477     22475, 22700, 22927, 23156, 23388, 23622, 23858, 24097,
1478     24338, 24581, 24827, 25075, 25326, 25579, 25835, 26093,
1479     26354, 26618, 26884, 27153, 27424, 27699, 27976, 28255,
1480     28538, 28823, 29112, 29403, 29697, 29994, 30294, 30597,
1481     30903, 31212, 31524, 31839, 32157, 32479, 32804
1482 };
1483 
1484 static void selfTestInit(TASK, enum SensorIndex idx)
1485 {
1486     uint8_t val;
1487 
1488     // Disable Interrupt
1489     SPI_WRITE(REG_INT_SOURCE0, 0);
1490     SPI_WRITE(REG_INT_SOURCE1, 0);
1491 
1492     // reset offset registers
1493     resetOffsetReg(_task, idx);
1494 
1495     // stop FIFO
1496     calSelftestFifoEnable(_task, idx, false, 0);
1497 
1498     // self-test mode set
1499     val = 0;
1500     if (T(self_test).st_mode) {
1501         if (idx == ACC) {
1502             val |= (BIT_TEST_AX_EN | BIT_TEST_AY_EN | BIT_TEST_AZ_EN);
1503             val |= BIT_SELF_TEST_REGULATOR_EN;
1504         } else if (idx == GYR) {
1505             val |= (BIT_TEST_GX_EN | BIT_TEST_GY_EN | BIT_TEST_GZ_EN);
1506         }
1507     }
1508     SPI_WRITE(REG_SELF_TEST_CONFIG, val);
1509 
1510     // set rate
1511     SPI_WRITE(REG_GYRO_CONFIG0, (SELF_TEST_GYR_FS << SHIFT_GYRO_FS_SEL) |
1512                                 (SELF_TEST_ODR << SHIFT_ODR_CONF));
1513     SPI_WRITE(REG_ACCEL_CONFIG0, (SELF_TEST_ACC_FS << SHIFT_ACCEL_FS_SEL) |
1514                                  (SELF_TEST_ODR << SHIFT_ODR_CONF));
1515 
1516     // set filter
1517     val = 0;
1518     if (idx == ACC) {
1519         val |= SELF_TEST_ACC_BW_IND;
1520     } else if (idx == GYR) {
1521         val |= SELF_TEST_GYR_BW_IND;
1522     }
1523     SPI_WRITE(REG_GYRO_ACCEL_CONFIG0, val);
1524 
1525     // turn on sensors
1526     val = 0;
1527     if (idx == ACC) {
1528         val |= BIT_ACCEL_MODE_LN;
1529     } else if (idx == GYR) {
1530         val |= BIT_GYRO_MODE_LN;
1531     }
1532     SPI_WRITE(REG_PWR_MGMT_0, val, 200 * 1000);
1533 
1534     calSelftestFifoEnable(_task, idx, true, SELF_TEST_READ_INTERVAL_US);
1535 }
1536 
1537 static void selfTestDeinit(TASK, enum SensorIndex idx)
1538 {
1539     calSelftestFifoEnable(_task, idx, false, 0);
1540 
1541     SPI_WRITE(REG_SELF_TEST_CONFIG, 0);
1542     SPI_WRITE(REG_GYRO_ACCEL_CONFIG0, ICM40600_ACC_BW_IND | ICM40600_GYR_BW_IND);
1543     SPI_WRITE(REG_PWR_MGMT_0, 0, 200); // 9136
1544 
1545     // make register accesses happen when sensor is enabled next time
1546     T(config).gyro_rate = 0;
1547     T(config).accel_rate = 0;
1548     T(config).fifo_rate = 0;
1549     T(config).fifo_watermark = 0;
1550     T(config).accel_on = false;
1551     T(config).gyro_on = false;
1552     T(config).wom_on = false;
1553 }
1554 
1555 static bool checkAccelSelftest(TASK)
1556 {
1557     int32_t st_res;
1558     uint32_t st_otp[3];
1559     int i;
1560     int32_t ratio;
1561     bool pass = true;
1562     bool otp_value_zero = false;
1563 
1564     /* calculate ST_OTP */
1565     for (i = 0; i < 3; i++) {
1566         if (T(self_test.otp_st_data_accel[i] != 0))
1567             st_otp[i] = SelfTestEquation[T(self_test).otp_st_data_accel[i] - 1];
1568         else
1569             otp_value_zero = true;
1570     }
1571 
1572     if (!otp_value_zero) {
1573         /* criteria a */
1574         for (i = 0; i < 3; i++) {
1575             st_res = T(self_test).data_st_on[i] - T(self_test).data_st_off[i];
1576             ratio = abs(st_res / st_otp[i] - SELF_TEST_PRECISION);
1577             if (ratio >= SELF_TEST_ACC_SHIFT_DELTA) {
1578                 INFO_PRINT("error accel[%d] : st_res = %ld, st_otp = %ld\n", i, st_res, st_otp[i]);
1579                 pass = false;
1580             }
1581         }
1582     } else {
1583         /* criteria b */
1584         for (i = 0; i < 3; i++) {
1585             st_res = abs(T(self_test).data_st_on[i] - T(self_test).data_st_off[i]);
1586             if (st_res < SELF_TEST_MIN_ACC || st_res > SELF_TEST_MAX_ACC) {
1587                 INFO_PRINT("error accel[%d] : st_res = %ld, min = %d, max = %d\n", i, st_res, SELF_TEST_MIN_ACC, SELF_TEST_MAX_ACC);
1588                 pass = false;
1589             }
1590         }
1591     }
1592 
1593     return pass;
1594 }
1595 
1596 static bool checkGyroSelftest(TASK)
1597 {
1598     int32_t st_res;
1599     uint32_t st_otp[3];
1600     int i;
1601     bool pass = true;
1602     bool otp_value_zero = false;
1603 
1604     /* calculate ST_OTP */
1605     for (i = 0; i < 3; i++) {
1606         if (T(self_test).otp_st_data_gyro[i] != 0)
1607             st_otp[i] = SelfTestEquation[T(self_test).otp_st_data_gyro[i] - 1];
1608         else
1609             otp_value_zero = true;
1610     }
1611 
1612     if (!otp_value_zero) {
1613         /* criteria a */
1614         for (i = 0; i < 3; i++) {
1615             st_res = T(self_test).data_st_on[i] - T(self_test).data_st_off[i];
1616             if (st_res <= st_otp[i] * SELF_TEST_GYR_SHIFT_DELTA) {
1617                 INFO_PRINT("error gyro[%d] : st_res = %ld, st_otp = %ld\n", i, st_res, st_otp[i]);
1618                 pass = false;
1619             }
1620         }
1621     } else {
1622         /* criteria b */
1623         for (i = 0; i < 3; i++) {
1624             st_res = abs(T(self_test).data_st_on[i] - T(self_test).data_st_off[i]);
1625             if (st_res < SELF_TEST_MIN_GYR) {
1626                 INFO_PRINT("error gyro[%d] : st_res = %ld, min = %d\n", i, st_res, SELF_TEST_MIN_GYR);
1627                 pass = false;
1628             }
1629         }
1630     }
1631 
1632     if (pass) {
1633         /* criteria c */
1634         for (i = 0; i < 3; i++) {
1635             if (abs(T(self_test).data_st_off[i]) > SELF_TEST_MAX_GYR_OFFSET) {
1636                 INFO_PRINT("error gyro[%d] = %d, max = %d\n", i, abs(T(self_test).data_st_off[i]), SELF_TEST_MAX_GYR_OFFSET);
1637                 pass = false;
1638             }
1639         }
1640     }
1641 
1642     return pass;
1643 }
1644 
1645 static void selfTestHandling(TASK, enum SensorIndex idx)
1646 {
1647     const uint8_t *buf, *data;
1648     uint8_t int_status;
1649     uint16_t fifo_count;
1650     int i, t;
1651     bool r;
1652     int16_t raw_data[3] = { 0, 0, 0 };
1653     bool pass;
1654 
1655     if (idx != ACC && idx != GYR) {
1656         ERROR_PRINT("Invalid sensor index\n");
1657         return;
1658     }
1659 
1660     switch (T(selftest_state)) {
1661     case TEST_START:
1662         T(mRetryLeft) = RETRY_CNT_SELF_TEST;
1663         selfTestInit(_task, idx);
1664         for (i = 0; i < 3; i++) {
1665             T(self_test).data[i] = 0;
1666         }
1667         SPI_READ(REG_INT_STATUS, 1, &T(dataBuffer[0]));
1668         SPI_READ(REG_FIFO_BYTE_COUNT1, 2, &T(dataBuffer[1]));
1669         T(selftest_state) = TEST_READ_STATUS;
1670         T(self_test).data_count = SELF_TEST_SAMPLE_NB;
1671         spiBatchTxRx(&T(mode), sensorSpiCallback, &T(sensors[idx]), __FUNCTION__);
1672         break;
1673     case TEST_READ_STATUS:
1674         buf = T(dataBuffer[0]);
1675         int_status = buf[1];
1676         buf = T(dataBuffer[1]);
1677         fifo_count = buf[2] << 8 | buf[1];
1678         fifo_count = fifo_count - fifo_count % T(config).fifo_sample_size;
1679         T(fifo_count) = fifo_count;
1680         DEBUG_PRINT("fifo_count = %d\n", fifo_count);
1681         if (int_status & BIT_INT_STATUS_FIFO_FULL) {
1682             ERROR_PRINT("fifo overflow\n");
1683             selfTestDeinit(_task, idx);
1684             T(selftest_state) = TEST_DONE;
1685             sendTestResult(SENSOR_APP_EVT_STATUS_ERROR, mSensorInfo[idx].sensorType);
1686         } else {
1687             T(selftest_state) = TEST_READ_DATA;
1688             SPI_READ(REG_FIFO_DATA, fifo_count, &T(dataBuffer[0]));
1689         }
1690         spiBatchTxRx(&T(mode), sensorSpiCallback, &T(sensors[idx]), __FUNCTION__);
1691         break;
1692     case TEST_READ_DATA:
1693         buf = T(dataBuffer[0]);
1694         data = &buf[1];
1695         for (i = 0; i < T(fifo_count); i += T(config).fifo_sample_size) {
1696             r = calSelftestGetOneData(idx, data, i, raw_data);
1697             if (r == false) {
1698                 ERROR_PRINT("invalid data packet\n");
1699                 selfTestDeinit(_task, idx);
1700                 T(selftest_state) = TEST_DONE;
1701                 sendTestResult(SENSOR_APP_EVT_STATUS_ERROR, mSensorInfo[idx].sensorType);
1702                 break;
1703             }
1704             for (t = 0; t < 3; t++) {
1705                 T(self_test).data[t] += raw_data[t];
1706             }
1707             T(self_test).data_count--;
1708             if (T(self_test).data_count == 0) {
1709                 break;
1710             }
1711         }
1712         if (T(self_test).data_count > 0) {
1713             if (--T(mRetryLeft) == 0) {
1714                 ERROR_PRINT("selftest timeout\n");
1715                 selfTestDeinit(_task, idx);
1716                 T(selftest_state) = TEST_DONE;
1717                 sendTestResult(SENSOR_APP_EVT_STATUS_ERROR, mSensorInfo[idx].sensorType);
1718             } else {
1719                 calSelftestFifoEnable(_task, idx, false, 0); // toggle FIFO to reset
1720                 calSelftestFifoEnable(_task, idx, true, SELF_TEST_READ_INTERVAL_US);
1721                 SPI_READ(REG_INT_STATUS, 1, &T(dataBuffer[0]));
1722                 SPI_READ(REG_FIFO_BYTE_COUNT1, 2, &T(dataBuffer[1]));
1723                 T(selftest_state) = TEST_READ_STATUS;
1724             }
1725             spiBatchTxRx(&T(mode), sensorSpiCallback, &T(sensors[idx]), __FUNCTION__);
1726             break;
1727         }
1728         T(selftest_state) = TEST_READ_OTP;
1729         // fall-through
1730     case TEST_READ_OTP:
1731         for (i = 0; i < 3; i++) {
1732             T(self_test).data[i] = T(self_test).data[i] / SELF_TEST_SAMPLE_NB * SELF_TEST_PRECISION;
1733         }
1734         INFO_PRINT("st_mode=%d average (scaled) : %ld, %ld, %ld\n",
1735                     T(self_test).st_mode,
1736                     T(self_test).data[0],
1737                     T(self_test).data[1],
1738                     T(self_test).data[2]);
1739 
1740         selfTestDeinit(_task, idx);
1741 
1742         for (i = 0; i < 3; i++) {
1743             if (T(self_test).st_mode) {
1744                 T(self_test).data_st_on[i] = T(self_test).data[i];
1745             } else {
1746                 T(self_test).data_st_off[i] = T(self_test).data[i];
1747             }
1748         }
1749 
1750         // Run again with self-test mode on
1751         if (!T(self_test).st_mode) {
1752             T(self_test).st_mode = true;
1753             T(selftest_state) = TEST_START;
1754         } else {
1755             INFO_PRINT("st mode on  : %ld %ld %ld\n",
1756                     T(self_test).data_st_on[0],
1757                     T(self_test).data_st_on[1],
1758                     T(self_test).data_st_on[2]);
1759             INFO_PRINT("st mode off : %ld %ld %ld\n",
1760                     T(self_test).data_st_off[0],
1761                     T(self_test).data_st_off[1],
1762                     T(self_test).data_st_off[2]);
1763 
1764             // read OTP
1765             if (idx == ACC) {
1766                 SPI_WRITE(REG_REG_BANK_SEL, BIT_BANK_SEL_2);
1767                 SPI_READ(REG_XA_ST_DATA, 3, &T(dataBuffer[0]));
1768             } else if (idx == GYR) {
1769                 SPI_WRITE(REG_REG_BANK_SEL, BIT_BANK_SEL_1);
1770                 SPI_READ(REG_XG_ST_DATA, 3, &T(dataBuffer[0]));
1771             }
1772             SPI_WRITE(REG_REG_BANK_SEL, BIT_BANK_SEL_0);
1773 
1774             T(selftest_state) = TEST_REPORT;
1775         }
1776         spiBatchTxRx(&T(mode), sensorSpiCallback, &T(sensors[idx]), __FUNCTION__);
1777         break;
1778     case TEST_REPORT:
1779         buf = T(dataBuffer[0]);
1780         if (idx == ACC) {
1781             T(self_test).otp_st_data_accel[0] = buf[1];
1782             T(self_test).otp_st_data_accel[1] = buf[2];
1783             T(self_test).otp_st_data_accel[2] = buf[3];
1784             INFO_PRINT("otp accel : %d %d %d\n",
1785                     T(self_test).otp_st_data_accel[0],
1786                     T(self_test).otp_st_data_accel[1],
1787                     T(self_test).otp_st_data_accel[2]);
1788         } else if (idx == GYR) {
1789             T(self_test).otp_st_data_gyro[0] = buf[1];
1790             T(self_test).otp_st_data_gyro[1] = buf[2];
1791             T(self_test).otp_st_data_gyro[2] = buf[3];
1792             INFO_PRINT("otp gyro  : %d %d %d\n",
1793                     T(self_test).otp_st_data_gyro[0],
1794                     T(self_test).otp_st_data_gyro[1],
1795                     T(self_test).otp_st_data_gyro[2]);
1796         }
1797 
1798         pass = false;
1799         if (idx == ACC) {
1800             pass = checkAccelSelftest(_task);
1801         } else if (idx == GYR) {
1802             pass = checkGyroSelftest(_task);
1803         }
1804         if (pass) {
1805             sendTestResult(SENSOR_APP_EVT_STATUS_SUCCESS,
1806                                   mSensorInfo[idx].sensorType);
1807         } else {
1808             sendTestResult(SENSOR_APP_EVT_STATUS_ERROR,
1809                                   mSensorInfo[idx].sensorType);
1810         }
1811 
1812         T(selftest_state) = TEST_DONE;
1813         selfTestDeinit(_task, idx);
1814         spiBatchTxRx(&T(mode), sensorSpiCallback, &T(sensors[idx]), __FUNCTION__);
1815         break;
1816     default:
1817         break;
1818     }
1819 }
1820 
1821 static bool accSelfTest(void *cookie)
1822 {
1823     TDECL();
1824 
1825     INFO_PRINT("Accel Selftest\n");
1826 
1827    if (!T(powered) && trySwitchState(SENSOR_TESTING)) {
1828         T(self_test).st_mode = false;
1829         T(selftest_state) = TEST_START;
1830         selfTestHandling(_task, ACC);
1831         return true;
1832     } else {
1833         ERROR_PRINT("cannot test accel because sensor is busy\n");
1834         sendTestResult(SENSOR_APP_EVT_STATUS_BUSY, SENS_TYPE_ACCEL);
1835         return false;
1836     }
1837 }
1838 
1839 static bool gyrSelfTest(void *cookie)
1840 {
1841     TDECL();
1842 
1843     INFO_PRINT("Gyro Selftest\n");
1844 
1845     if (!T(powered) && trySwitchState(SENSOR_TESTING)) {
1846         T(self_test).st_mode = false;
1847         T(selftest_state) = TEST_START;
1848         selfTestHandling(_task, GYR);
1849         return true;
1850     } else {
1851         ERROR_PRINT("cannot test accel because sensor is busy\n");
1852         sendTestResult(SENSOR_APP_EVT_STATUS_BUSY, SENS_TYPE_GYRO);
1853         return false;
1854     }
1855 }
1856 
1857 static bool sensorFirmwareUpload(void *cookie)
1858 {
1859     TDECL();
1860     int i = (long int)cookie;
1861 
1862     sensorSignalInternalEvt(T(sensors[i]).handle, SENSOR_INTERNAL_EVT_FW_STATE_CHG, 1, 0);
1863 
1864     return true;
1865 }
1866 
1867 static bool enableInterrupt(struct Gpio *pin, IRQn_Type irq, struct ChainedIsr *isr)
1868 {
1869     gpioConfigInput(pin, GPIO_SPEED_LOW, GPIO_PULL_NONE);
1870     syscfgSetExtiPort(pin);
1871     extiEnableIntGpio(pin, EXTI_TRIGGER_RISING);
1872     extiChainIsr(irq, isr);
1873     return true;
1874 }
1875 
1876 static bool disableInterrupt(struct Gpio *pin, IRQn_Type irq, struct ChainedIsr *isr)
1877 {
1878     extiUnchainIsr(irq, isr);
1879     extiDisableIntGpio(pin);
1880     return true;
1881 }
1882 
1883 static void configInt1(TASK, bool on)
1884 {
1885     enum SensorIndex i;
1886     bool powered = false;
1887 
1888     if (on && !T(Int1_EN)) {
1889         enableInterrupt(T(Int1), T(Irq1), &T(Isr1));
1890         T(Int1_EN) = true;
1891     } else if (!on && T(Int1_EN)) {
1892         for (i = 0; i < NUM_OF_SENSOR; i++) {
1893             if (T(sensors[i]).powered) {
1894                 powered = true;
1895                 break;
1896             }
1897         }
1898         if (!powered) {
1899             disableInterrupt(T(Int1), T(Irq1), &T(Isr1));
1900             T(Int1_EN) = false;
1901         }
1902     }
1903 }
1904 
1905 static uint8_t computeOdrConf(uint32_t rate)
1906 {
1907     switch (rate) {
1908     case SENSOR_HZ(1000.0f):
1909         return 6;
1910     case SENSOR_HZ(200.0f):
1911         return 7;
1912     case SENSOR_HZ(100.0f):
1913         return 8;
1914     case SENSOR_HZ(50.0f):
1915         return 9;
1916     case SENSOR_HZ(25.0f):
1917     default:
1918         return 10;
1919     }
1920 }
1921 
1922 static void computeConfig(TASK, struct ICM40600Config *config)
1923 {
1924     uint64_t latency;
1925     uint64_t val;
1926     uint32_t latency_ms;
1927     int i;
1928 
1929     // copy current parameters
1930     *config = T(config);
1931 
1932     // compute sensors on
1933     if (T(sensors[ACC]).configed || T(sensors[WOM]).configed || T(sensors[NOMO]).configed) {
1934         config->accel_on = true;
1935     } else {
1936         config->accel_on = false;
1937     }
1938     config->gyro_on = T(sensors[GYR]).configed;
1939     if (T(sensors[WOM]).configed || T(sensors[NOMO]).configed) {
1940         config->wom_on = true;
1941     } else {
1942         config->wom_on = false;
1943     }
1944 
1945     // compute accel and gyro rates
1946     if (config->accel_on) {
1947         if (T(sensors[ACC]).configed) {
1948             if (T(sensors[ACC]).rate > NO_DECIMATION_MAX_RATE) {
1949                 config->accel_rate = DECIMATION_HIGH_RATE;
1950             } else if (T(sensors[ACC]).rate < NO_DECIMATION_MIN_RATE) {
1951                 config->accel_rate = DECIMATION_LOW_RATE;
1952             } else {
1953                 config->accel_rate = T(sensors[ACC]).rate;
1954             }
1955         } else {
1956             config->accel_rate = NO_DECIMATION_MIN_RATE;
1957         }
1958     }
1959     if (config->gyro_on) {
1960         if (T(sensors[GYR]).configed) {
1961             if (T(sensors[GYR]).rate > NO_DECIMATION_MAX_RATE) {
1962                 config->gyro_rate = DECIMATION_HIGH_RATE;
1963             } else if (T(sensors[GYR]).rate < NO_DECIMATION_MIN_RATE) {
1964                 config->gyro_rate = DECIMATION_LOW_RATE;
1965             } else {
1966                 config->gyro_rate = T(sensors[GYR]).rate;
1967             }
1968         } else {
1969             config->gyro_rate = NO_DECIMATION_MIN_RATE;
1970         }
1971     }
1972 
1973     // compute wom threshold
1974     if (config->wom_on) {
1975         config->wom_threshold = ICM40600_WOM_THRESHOLD_MG / (config->accel_rate / NO_DECIMATION_MIN_RATE);
1976     }
1977 
1978     // compute fifo configuration
1979     if (T(sensors[ACC]).configed || T(sensors[GYR]).configed) {
1980         config->fifo_sample_size = FIFO_PACKET_SIZE;
1981     } else {
1982         config->fifo_sample_size = 0;
1983     }
1984 
1985     // compute fifo rate and latency/watermark
1986     config->fifo_rate = 0;
1987     latency = SENSOR_LATENCY_NODATA;
1988     for (i = FIRST_CONT_SENSOR; i < NUM_CONT_SENSOR; ++i) {
1989         if (T(sensors[i]).configed) {
1990             // look for the highest rate
1991             if (T(sensors[i]).rate > config->fifo_rate) {
1992                 config->fifo_rate = T(sensors[i]).rate;
1993             }
1994             // look for the shortest latency
1995             if (T(sensors[i]).latency < latency) {
1996                 latency = T(sensors[i]).latency;
1997             }
1998         }
1999     }
2000     if (config->fifo_rate > NO_DECIMATION_MAX_RATE) {
2001         config->fifo_rate = DECIMATION_HIGH_RATE;
2002     } else if (config->fifo_rate < NO_DECIMATION_MIN_RATE) {
2003         config->fifo_rate = DECIMATION_LOW_RATE;
2004     }
2005 
2006     // add 0.5ms for rounding
2007     latency_ms = cpuMathU64DivByU16(cpuMathU64DivByU16(latency + 500000, 1000), 1000);
2008     val = (uint64_t)latency_ms * (uint64_t)config->fifo_rate;
2009     config->fifo_watermark = cpuMathU64DivByU16(cpuMathU64DivByU16(val, 1000), RATE_TO_HZ);
2010     config->fifo_watermark *= config->fifo_sample_size;
2011     if (config->fifo_watermark < config->fifo_sample_size) {
2012         config->fifo_watermark = config->fifo_sample_size;
2013     }
2014     if (config->fifo_watermark > MAX_BATCH_SIZE) {
2015         config->fifo_watermark = MAX_BATCH_SIZE - (MAX_BATCH_SIZE % config->fifo_sample_size);
2016     }
2017 }
2018 
2019 static void updateConfig(TASK, const struct ICM40600Config *config)
2020 {
2021     uint32_t delay_us;
2022     uint8_t val, val2;
2023 
2024     // Disable Interrupt
2025     SPI_WRITE(REG_INT_SOURCE0, 0);
2026     SPI_WRITE(REG_INT_SOURCE1, 0);
2027 
2028     // set rate and WoM threshold
2029     if (config->gyro_rate != T(config).gyro_rate) {
2030         val = computeOdrConf(config->gyro_rate);
2031         SPI_WRITE(REG_GYRO_CONFIG0, (ICM40600_GYR_FS << SHIFT_GYRO_FS_SEL) |
2032                                     (val << SHIFT_ODR_CONF));
2033     }
2034     if (config->accel_rate != T(config).accel_rate) {
2035         val = computeOdrConf(config->accel_rate);
2036         SPI_WRITE(REG_ACCEL_CONFIG0, (ICM40600_ACC_FS << SHIFT_ACCEL_FS_SEL) |
2037                                      (val << SHIFT_ODR_CONF));
2038     }
2039     if (config->wom_threshold != T(config).wom_threshold) {
2040         val = ICM40600_WOM_COMPUTE(config->wom_threshold);
2041         SPI_WRITE(REG_ACCEL_WOM_X_THR, val);
2042         SPI_WRITE(REG_ACCEL_WOM_Y_THR, val);
2043         SPI_WRITE(REG_ACCEL_WOM_Z_THR, val);
2044     }
2045 
2046     // set WM
2047     if (config->fifo_watermark != T(config).fifo_watermark) {
2048         SPI_WRITE(REG_FIFO_CONFIG2, config->fifo_watermark & 0xFF);
2049         SPI_WRITE(REG_FIFO_CONFIG3, (config->fifo_watermark >> 8) & 0xFF);
2050     }
2051 
2052     // turn on/off accel and gyro if any change
2053     if (config->gyro_on != T(config).gyro_on || config->accel_on != T(config).accel_on) {
2054         val = 0;
2055         if (config->gyro_on) {
2056             val |= BIT_GYRO_MODE_LN;
2057         }
2058         if (config->accel_on) {
2059             val |= BIT_ACCEL_MODE_LN;
2060         }
2061         // delay needed if gyro or accel turning on
2062         if ((config->gyro_on && !T(config).gyro_on) || (config->accel_on && !T(config).accel_on)) {
2063             delay_us = 200; // 9136
2064         } else {
2065             delay_us = 0;
2066         }
2067         SPI_WRITE(REG_PWR_MGMT_0, val, delay_us);
2068     }
2069 
2070     // turn on/off WOM
2071     if (config->wom_on != T(config).wom_on) {
2072         if (config->wom_on) {
2073             val = BIT_WOM_INT_MODE_OR | BIT_WOM_MODE_PREV | BIT_SMD_MODE_OLD;
2074         } else {
2075             val = 0;
2076         }
2077         SPI_WRITE(REG_SMD_CONFIG, val);
2078     }
2079 
2080     // turn on/off FIFO
2081     if (config->fifo_sample_size != T(config).fifo_sample_size) {
2082         if (config->fifo_sample_size != 0) {
2083             // enabling FIFO
2084             val = BIT_FIFO_MODE_STREAM;
2085             val2 = BIT_FIFO_ACCEL_EN | BIT_FIFO_GYRO_EN | BIT_FIFO_TEMP_EN |
2086                     BIT_FIFO_TMST_FSYNC_EN | BIT_FIFO_WM_TH;
2087             // reset chip time
2088             T(chip_time_us) = 0;
2089             T(chip_timestamp) = 0;
2090             T(fifo_start_sync) = true;
2091             invalidate_sensortime_to_rtc_time(_task);
2092         } else {
2093             // disabling FIFO
2094             val = BIT_FIFO_MODE_BYPASS;
2095             val2 = 0;
2096         }
2097         SPI_WRITE(REG_FIFO_CONFIG, val);
2098         SPI_WRITE(REG_FIFO_CONFIG1, val2);
2099         if (val == BIT_FIFO_MODE_BYPASS) {
2100             SPI_READ(REG_FIFO_BYTE_COUNT1, 2, &T(dataBuffer[0])); // 9052
2101         }
2102     }
2103 
2104     // enable/disable FIFO data interrupt
2105     if (config->fifo_sample_size != 0) {
2106         val = BIT_INT_FIFO_THS_INT1_EN;
2107     } else {
2108         val = 0;
2109     }
2110     SPI_WRITE(REG_INT_SOURCE0, val);
2111 
2112     // enable/disable WOM interrupt (only when FIFO disabled or batch mode)
2113     if (config->wom_on && (config->fifo_sample_size == 0 || config->fifo_watermark > config->fifo_sample_size)) {
2114         val = BIT_INT_WOM_XYZ_INT1_EN;
2115     } else {
2116         val = 0;
2117     }
2118     SPI_WRITE(REG_INT_SOURCE1, val);
2119 }
2120 
2121 static void applyConfig(TASK, const struct ICM40600Config *config)
2122 {
2123     uint32_t duration_us;
2124     uint32_t decimator;
2125     int i;
2126 
2127     // setup wait for odr change
2128     if (config->accel_rate != T(config).accel_rate) {
2129         T(sensors[ACC]).wait_for_odr = true;
2130     }
2131     if (config->gyro_rate != T(config).gyro_rate) {
2132         T(sensors[GYR]).wait_for_odr = true;
2133     }
2134 
2135     // setup first samples skip
2136     if (config->gyro_on && !T(config).gyro_on) {
2137         // gyro turning on
2138         duration_us = (1000000 * RATE_TO_HZ) / config->gyro_rate;
2139         if (duration_us * GYR_SKIP_SAMPLE_NB > ICM40600_GYRO_START_TIME_MS * 1000) {
2140             T(sensors[GYR]).skip_sample_cnt = GYR_SKIP_SAMPLE_NB;
2141         } else {
2142             T(sensors[GYR]).skip_sample_cnt = (ICM40600_GYRO_START_TIME_MS * 1000) / duration_us;
2143             if ((ICM40600_GYRO_START_TIME_MS * 1000) % duration_us) {
2144                 T(sensors[GYR]).skip_sample_cnt++;
2145             }
2146         }
2147     }
2148     if (config->accel_on && !T(config).accel_on) {
2149         // accel turning on
2150         duration_us = (1000000 * RATE_TO_HZ) / config->accel_rate;
2151         if (duration_us * ACC_SKIP_SAMPLE_NB > ICM40600_ACCEL_START_TIME_MS * 1000) {
2152             T(sensors[ACC]).skip_sample_cnt = ACC_SKIP_SAMPLE_NB;
2153         } else {
2154             T(sensors[ACC]).skip_sample_cnt = (ICM40600_ACCEL_START_TIME_MS * 1000) / duration_us;
2155             if ((ICM40600_ACCEL_START_TIME_MS * 1000) % duration_us) {
2156                 T(sensors[ACC]).skip_sample_cnt++;
2157             }
2158         }
2159     }
2160 
2161     // update all sensors decimators
2162     for (i = 0; i <= GYR; i++) {
2163         if (!T(sensors[i]).configed || T(sensors[i]).rate == 0) {
2164             decimator = 1;
2165         } else {
2166             if (i == ACC) {
2167                 decimator = config->accel_rate / T(sensors[i]).rate;
2168             } else if (i == GYR) {
2169                 decimator = config->gyro_rate / T(sensors[i]).rate;
2170             }
2171         }
2172         if (decimator != T(sensors[i]).decimator) {
2173             T(sensors[i]).decimator = decimator;
2174             T(sensors[i]).data_cnt = 0;
2175         }
2176     }
2177 
2178     // setup NOMO timer
2179     if (T(sensors[NOMO]).configed && !T(noMotionTimerHandle)) {
2180         T(noMotionTimerHandle) = timTimerSet(ICM40600_NOM_DURATION_NS, 0, 100, noMotionCallback, &T(sensors[NOMO]), false);
2181     } else if (!T(sensors[NOMO]).configed && T(noMotionTimerHandle)) {
2182         timTimerCancel(T(noMotionTimerHandle));
2183         T(noMotionTimerHandle) = 0;
2184     }
2185 
2186     // update config
2187     T(config) = *config;
2188 
2189     DEBUG_PRINT("config: accel(%d, %luHz/%u), gyro(%d, %luHz/%u), wom(%d, %lu), "
2190             "fifo(%u/%u, %luHz)\n",
2191             T(config).accel_on, T(config).accel_rate / RATE_TO_HZ, T(sensors[ACC]).decimator,
2192             T(config).gyro_on, T(config).gyro_rate / RATE_TO_HZ, T(sensors[GYR]).decimator,
2193             T(config).wom_on, T(config).wom_threshold,
2194             T(config).fifo_sample_size, T(config).fifo_watermark, T(config).fifo_rate / RATE_TO_HZ);
2195 }
2196 
2197 static void configSensor(TASK)
2198 {
2199     struct ICM40600Config config;
2200 
2201     computeConfig(_task, &config);
2202     updateConfig(_task, &config);
2203     applyConfig(_task, &config);
2204 }
2205 
2206 static void sensorTurnOn(TASK)
2207 {
2208     /* enable chip timestamp */
2209     SPI_WRITE(REG_TMST_CONFIG, BIT_EN_DREG_FIFO_D2A | BIT_TMST_EN);
2210 
2211     T(powered) = true;
2212 #if DBG_TIMESTAMP
2213     memset(&T(statistics_set), 0, sizeof(struct StatisticsSet));
2214 #endif
2215     DEBUG_PRINT("chip on\n");
2216 }
2217 
2218 static void sensorTurnOff(TASK)
2219 {
2220     /* disable chip timestamp */
2221     SPI_WRITE(REG_TMST_CONFIG, BIT_EN_DREG_FIFO_D2A);
2222 
2223     T(powered) = false;
2224 #if DBG_TIMESTAMP
2225     DEBUG_PRINT("time sync stats: reset: %ld, sync: %ld, adjust+: %ld, adjust-: %ld, truncate: %ld\n",
2226             T(statistics_set).sync_reset_count,
2227             T(statistics_set).sync_count,
2228             T(statistics_set).sync_adjust_plus,
2229             T(statistics_set).sync_adjust_minus,
2230             T(statistics_set).sync_truncate);
2231 #endif
2232     DEBUG_PRINT("chip off\n");
2233 }
2234 
2235 static void sensorPower(TASK, int sensorType, bool on)
2236 {
2237     bool chip_on;
2238     int i;
2239 
2240     if (on) {
2241         // turn on chip if needed
2242         if (!T(powered)) {
2243             sensorTurnOn(_task);
2244         }
2245     } else {
2246         // change chip configuration
2247         configSensor(_task);
2248         // turn chip off if needed
2249         chip_on = false;
2250         for (i = 0; i < NUM_OF_SENSOR; ++i) {
2251             if (T(sensors[i]).powered) {
2252                 chip_on = true;
2253                 break;
2254             }
2255         }
2256         if (!chip_on) {
2257             sensorTurnOff(_task);
2258         }
2259     }
2260 }
2261 
2262 static bool sensorSetPower(bool on, void *cookie)
2263 {
2264     TDECL();
2265     int sensor_type = (int)cookie;
2266     struct ICM40600Sensor *sensor = &T(sensors[sensor_type]);
2267 
2268     DEBUG_PRINT("%s: on=%d, state=%" PRI_STATE "\n", mSensorInfo[sensor_type].sensorName, on, getStateName(GET_STATE()));
2269 
2270     if (trySwitchState(on ? SENSOR_POWERING_UP : SENSOR_POWERING_DOWN)) {
2271         sensor->powered = on;
2272         if (!on) {
2273             sensor->configed = false;
2274         }
2275         configInt1(_task, on);
2276         sensorPower(_task, sensor_type, on);
2277         spiBatchTxRx(&T(mode), sensorSpiCallback, sensor, __FUNCTION__);
2278     } else {
2279         T(pending_config[sensor_type]) = true;
2280         sensor->pConfig.enable = on;
2281     }
2282 
2283     return true;
2284 }
2285 
2286 static bool sensorSetRate(uint32_t rate, uint64_t latency, void *cookie)
2287 {
2288     TDECL();
2289     int sensor_type = (int)cookie;
2290     struct ICM40600Sensor *sensor = &T(sensors[sensor_type]);
2291 
2292     DEBUG_PRINT("%s: rate=%lu, latency=%llu, state=%" PRI_STATE "\n",
2293             mSensorInfo[sensor_type].sensorName, rate, latency, getStateName(GET_STATE()));
2294 
2295     if (trySwitchState(SENSOR_CONFIG_CHANGING)) {
2296         sensor->rate = rate;
2297         sensor->latency = latency;
2298         sensor->configed = true;
2299         configSensor(_task);
2300         spiBatchTxRx(&T(mode), sensorSpiCallback, sensor, __FUNCTION__);
2301     } else {
2302         T(pending_config[sensor_type]) = true;
2303         sensor->pConfig.enable = sensor->powered;
2304         sensor->pConfig.rate = rate;
2305         sensor->pConfig.latency = latency;
2306     }
2307 
2308     return true;
2309 }
2310 
2311 static void sendFlushEvt(void)
2312 {
2313     TDECL();
2314     uint32_t evtType = 0;
2315     int i;
2316 
2317     for (i = FIRST_CONT_SENSOR; i < NUM_CONT_SENSOR; i++) {
2318         while (T(sensors[i]).flush > 0) {
2319             evtType = sensorGetMyEventType(mSensorInfo[i].sensorType);
2320             osEnqueueEvt(evtType, SENSOR_DATA_EVENT_FLUSH, NULL);
2321             T(sensors[i]).flush--;
2322         }
2323     }
2324 }
2325 
2326 static void int1Evt(TASK, bool flush);
2327 
2328 static bool flushSensor(void *cookie)
2329 {
2330     TDECL();
2331     int sensor_idx = (int)cookie;
2332     uint32_t evtType;
2333 
2334     DEBUG_PRINT("%s flush\n", mSensorInfo[sensor_idx].sensorName);
2335 
2336     if (sensor_idx >= FIRST_CONT_SENSOR && sensor_idx < NUM_CONT_SENSOR) {
2337         T(sensors[sensor_idx]).flush++;
2338         int1Evt(_task, true);
2339         return true;
2340     }
2341     if (sensor_idx >= FIRST_ONESHOT_SENSOR && sensor_idx < NUM_OF_SENSOR) {
2342         evtType = sensorGetMyEventType(mSensorInfo[sensor_idx].sensorType);
2343         osEnqueueEvt(evtType, SENSOR_DATA_EVENT_FLUSH, NULL);
2344         return true;
2345     }
2346 
2347     return false;
2348 }
2349 
2350 static bool flushData(struct ICM40600Sensor *sensor, uint32_t eventId)
2351 {
2352     bool success = false;
2353 
2354     if (sensor->data_evt) {
2355         success = osEnqueueEvtOrFree(eventId, sensor->data_evt, dataEvtFree);
2356         sensor->data_evt = NULL;
2357     }
2358 
2359     return success;
2360 }
2361 
2362 static void flushAllData(void)
2363 {
2364     TDECL();
2365     int i;
2366 
2367     for (i = FIRST_CONT_SENSOR; i < NUM_CONT_SENSOR; i++) {
2368         flushData(&T(sensors[i]),
2369                 EVENT_TYPE_BIT_DISCARDABLE | sensorGetMyEventType(mSensorInfo[i].sensorType));
2370     }
2371 }
2372 
2373 static bool allocateDataEvt(struct ICM40600Sensor *mSensor, uint64_t rtc_time)
2374 {
2375     TDECL();
2376 
2377     mSensor->data_evt = slabAllocatorAlloc(T(mDataSlab));
2378     if (mSensor->data_evt == NULL) {
2379         // slab allocation failed
2380         ERROR_PRINT("slabAllocatorAlloc() failed\n");
2381         return false;
2382     }
2383 
2384     // delta time for the first sample is sample count
2385     memset(&mSensor->data_evt->samples[0].firstSample, 0x00, sizeof(struct SensorFirstSample));
2386     mSensor->data_evt->referenceTime = rtc_time;
2387     mSensor->prev_rtc_time = rtc_time;
2388 
2389     return true;
2390 }
2391 
2392 static void parseOnePacket(TASK, const uint8_t *data, int idx)
2393 {
2394     struct FifoPacketData fifo_data;
2395     uint16_t diff;
2396 
2397     getFifoData(data, idx, &fifo_data);
2398 
2399     /* wait for odr */
2400     if (T(sensors[ACC]).wait_for_odr) {
2401         if (fifo_data.odr_accel) {
2402             T(sensors[ACC]).wait_for_odr = false;
2403         } else {
2404             fifo_data.valid_accel = false;
2405         }
2406     }
2407     if (T(sensors[GYR]).wait_for_odr) {
2408         if (fifo_data.odr_gyro) {
2409             T(sensors[GYR]).wait_for_odr = false;
2410         } else {
2411             fifo_data.valid_gyro = false;
2412         }
2413     }
2414 
2415     /* drop first some samples */
2416     if (fifo_data.valid_accel) {
2417         if (T(sensors[ACC]).skip_sample_cnt > 0) {
2418             fifo_data.valid_accel = false;
2419             T(sensors[ACC]).skip_sample_cnt--;
2420         }
2421     }
2422     if (fifo_data.valid_gyro) {
2423         if (T(sensors[GYR]).skip_sample_cnt > 0) {
2424             fifo_data.valid_gyro = false;
2425             T(sensors[GYR]).skip_sample_cnt--;
2426         }
2427     }
2428 
2429     /* update sensors data */
2430     if (fifo_data.valid_accel) {
2431         ICM40600_TO_ANDROID_COORDINATE(fifo_data.accel[0], fifo_data.accel[1], fifo_data.accel[2]);
2432         if (T(sensors[ACC]).configed) {
2433             T(sensors[ACC]).data[0] = fifo_data.accel[0];
2434             T(sensors[ACC]).data[1] = fifo_data.accel[1];
2435             T(sensors[ACC]).data[2] = fifo_data.accel[2];
2436             T(sensors[ACC]).updated = true;
2437             T(sensors[ACC]).data_cnt++;
2438         }
2439     }
2440     if (fifo_data.valid_gyro) {
2441         ICM40600_TO_ANDROID_COORDINATE(fifo_data.gyro[0], fifo_data.gyro[1], fifo_data.gyro[2]);
2442         if (T(sensors[GYR]).configed) {
2443             T(sensors[GYR]).data[0] = fifo_data.gyro[0];
2444             T(sensors[GYR]).data[1] = fifo_data.gyro[1];
2445             T(sensors[GYR]).data[2] = fifo_data.gyro[2];
2446             T(sensors[GYR]).updated = true;
2447             T(sensors[GYR]).data_cnt++;
2448         }
2449     }
2450 
2451     // update temperature
2452     T(chip_temperature) = fifo_data.temp * TEMP_SCALE + TEMP_OFFSET;
2453 
2454     // count up chip time
2455     if (T(chip_time_us) == 0) {
2456         T(chip_time_us) = (uint64_t)fifo_data.timestamp * CHIP_TIME_RES_US + CHIP_TIME_OFFSET_US;
2457     } else {
2458         // unsigned difference handle counter roll-up
2459         diff = fifo_data.timestamp - T(chip_timestamp);
2460         T(chip_time_us) += diff * CHIP_TIME_RES_US;
2461     }
2462     T(chip_timestamp) = fifo_data.timestamp;
2463 }
2464 
2465 static void pushSensorData(TASK, struct ICM40600Sensor *mSensor, uint64_t rtc_time)
2466 {
2467     float x, y, z;
2468     float offset[3];
2469     bool new_offset_update = false;
2470     struct TripleAxisDataPoint *sample;
2471     uint32_t delta_time;
2472 
2473     switch (mSensor->idx) {
2474     case ACC:
2475         // scale data to android units
2476         x = mSensor->data[0] * kScale_acc;
2477         y = mSensor->data[1] * kScale_acc;
2478         z = mSensor->data[2] * kScale_acc;
2479         // run and apply calibration on sensor data
2480 #ifdef ACCEL_CAL_ENABLED
2481         accelCalRun(&T(accel_cal), rtc_time, x, y, z, T(chip_temperature));
2482         accelCalBiasRemove(&T(accel_cal), &x, &y, &z);
2483 #  ifdef ACCEL_CAL_DBG_ENABLED
2484         accelCalDebPrint(&T(accel_cal), T(chip_temperature));
2485 #  endif
2486 #endif
2487 #ifdef GYRO_CAL_ENABLED
2488         gyroCalUpdateAccel(&T(gyro_cal), rtc_time, x, y, z);
2489 #endif
2490         break;
2491     case GYR:
2492         // scale data to android units
2493         x = mSensor->data[0] * kScale_gyr;
2494         y = mSensor->data[1] * kScale_gyr;
2495         z = mSensor->data[2] * kScale_gyr;
2496         // run and apply calibration on sensor data
2497 #ifdef GYRO_CAL_ENABLED
2498         gyroCalUpdateGyro(&T(gyro_cal), rtc_time, x, y, z, T(chip_temperature));
2499         gyroCalRemoveBias(&T(gyro_cal), x, y, z, &x, &y, &z);
2500         new_offset_update = gyroCalNewBiasAvailable(&T(gyro_cal));
2501         if (new_offset_update) {
2502             float gyro_offset_temperature_celsius;
2503             gyroCalGetBias(&T(gyro_cal), &offset[0], &offset[1], &offset[2],
2504                     &gyro_offset_temperature_celsius);
2505         }
2506 #endif
2507         break;
2508     default:
2509         return;
2510     }
2511 
2512     if (mSensor->data_evt == NULL) {
2513         if (!allocateDataEvt(mSensor, rtc_time))
2514             return;
2515     }
2516 
2517     if (mSensor->data_evt->samples[0].firstSample.numSamples >= MAX_NUM_COMMS_EVENT_SAMPLES) {
2518         ERROR_PRINT("samples bad index\n");
2519         return;
2520     }
2521 
2522     // handle bias sending
2523     if (new_offset_update) {
2524         if (mSensor->data_evt->samples[0].firstSample.numSamples > 0) {
2525             // flush existing samples so the bias appears after them.
2526             flushData(mSensor, EVENT_TYPE_BIT_DISCARDABLE | sensorGetMyEventType(mSensorInfo[mSensor->idx].sensorType));
2527             if (!allocateDataEvt(mSensor, rtc_time)) {
2528                 return;
2529             }
2530         }
2531         mSensor->data_evt->samples[0].firstSample.biasCurrent = true;
2532         mSensor->data_evt->samples[0].firstSample.biasPresent = 1;
2533         mSensor->data_evt->samples[0].firstSample.biasSample = mSensor->data_evt->samples[0].firstSample.numSamples;
2534         sample = &mSensor->data_evt->samples[mSensor->data_evt->samples[0].firstSample.numSamples++];
2535         // Updates the offset in HAL.
2536         sample->x = offset[0];
2537         sample->y = offset[1];
2538         sample->z = offset[2];
2539         flushData(mSensor, sensorGetMyEventType(mSensorInfo[mSensor->idx].biasType));
2540         DEBUG_PRINT("send new gyro bias\n");
2541         if (!allocateDataEvt(mSensor, rtc_time)) {
2542             return;
2543         }
2544     }
2545 
2546     sample = &mSensor->data_evt->samples[mSensor->data_evt->samples[0].firstSample.numSamples++];
2547 
2548     // the first deltatime is for sample size
2549     if (mSensor->data_evt->samples[0].firstSample.numSamples > 1) {
2550         delta_time = rtc_time - mSensor->prev_rtc_time;
2551         delta_time = delta_time < 0 ? 0 : delta_time;
2552         sample->deltaTime = delta_time;
2553         mSensor->prev_rtc_time = rtc_time;
2554     }
2555 
2556     sample->x = x;
2557     sample->y = y;
2558     sample->z = z;
2559 
2560     if (mSensor->data_evt->samples[0].firstSample.numSamples == MAX_NUM_COMMS_EVENT_SAMPLES) {
2561         flushAllData();
2562     }
2563 }
2564 
2565 static void computeTimeSync(TASK, const uint8_t *data, uint32_t count, uint64_t data_timestamp)
2566 {
2567     const uint64_t now = sensorGetTime();
2568     uint64_t chip_time_us;
2569     uint32_t sample_index;
2570     uint32_t duration_us;
2571     struct FifoPacketData packet;
2572     uint16_t sample_nb;
2573     uint16_t chip_timestamp;
2574     uint16_t diff;
2575     bool first_sync = false;
2576     bool sync = false;
2577 
2578     /* scan fifo data for the latest chip timestamp */
2579     chip_time_us = T(chip_time_us);
2580     chip_timestamp = T(chip_timestamp);
2581     sample_index = 0;
2582     sample_nb = 0;
2583     while (count >= T(config).fifo_sample_size) {
2584         sample_nb++;
2585         getFifoData(data, sample_index, &packet);
2586         sample_index += T(config).fifo_sample_size;
2587         count -= T(config).fifo_sample_size;
2588         // count up chip time
2589         if (chip_time_us == 0) {
2590             // first chip timestamp
2591             chip_time_us = (uint64_t)packet.timestamp * CHIP_TIME_RES_US + CHIP_TIME_OFFSET_US;
2592         } else {
2593             // unsigned difference handle counter roll-up
2594             diff = packet.timestamp - chip_timestamp;
2595             chip_time_us += diff * CHIP_TIME_RES_US;
2596         }
2597         chip_timestamp = packet.timestamp;
2598     }
2599 
2600     /* first time sync after FIFO enable */
2601     if (T(fifo_start_sync)) {
2602         if (T(config).fifo_rate != 0) {
2603             duration_us = (1000000 * RATE_TO_HZ) / T(config).fifo_rate;
2604         } else {
2605             duration_us = 0;
2606         }
2607         // use estimated duration
2608         map_sensortime_to_rtc_time(_task,
2609                 chip_time_us - duration_us * sample_nb,
2610                 data_timestamp - (uint64_t)duration_us * 1000ULL * sample_nb);
2611         T(fifo_start_sync) = false;
2612         T(last_sync_time) = now;
2613         first_sync = true;
2614     }
2615 
2616     /* periodical time sync */
2617     if ((now - T(last_sync_time)) > MSEC_TO_NANOS(100)) {
2618         // every 100ms
2619         uint64_t estimated_rtc;
2620         uint64_t min_rtc, max_rtc;
2621         uint64_t limit_ns, adjust_ns;
2622         uint64_t updated_data_timestamp = data_timestamp;
2623         bool valid = sensortime_to_rtc_time(_task, chip_time_us, &estimated_rtc);
2624         // check if appropriate to inject to time sync algorithm
2625         // adjust rtc time if necessary not to make large jitters
2626         if (valid) {
2627             limit_ns = U64_DIV_BY_CONST_U16((data_timestamp - T(last_sync_data_ts)) * 10, 1000);  // 1% (100ms * 1% = 1ms)
2628             adjust_ns = U64_DIV_BY_CONST_U16((data_timestamp - T(last_sync_data_ts)) * 1, 10000); // 0.01% (100ms * 0.01% = 10us)
2629             min_rtc = data_timestamp - limit_ns; // actual ts - x
2630             max_rtc = data_timestamp + limit_ns; // actual ts + x
2631             if ((estimated_rtc >= min_rtc) && (estimated_rtc <= max_rtc)) {
2632                 sync = true;
2633             } else if (estimated_rtc < min_rtc) {
2634                 sync = true;
2635                 updated_data_timestamp = updated_data_timestamp - adjust_ns;
2636 #if DBG_TIMESTAMP
2637                 T(statistics_set).sync_adjust_minus++;
2638 #endif
2639             } else if (estimated_rtc > max_rtc) {
2640                 sync = true;
2641                 updated_data_timestamp = updated_data_timestamp + adjust_ns;
2642 #if DBG_TIMESTAMP
2643                 T(statistics_set).sync_adjust_plus++;
2644 #endif
2645             }
2646             // limit the adjustment
2647             if (sync) {
2648                 if (updated_data_timestamp > (data_timestamp + MSEC_TO_NANOS(1))) {
2649                     updated_data_timestamp = data_timestamp + MSEC_TO_NANOS(1);
2650                 }
2651             }
2652         }
2653         if (sync) {
2654             data_timestamp = updated_data_timestamp;
2655         }
2656     }
2657 
2658     /* do time sync */
2659     if (first_sync || sync) {
2660         map_sensortime_to_rtc_time(_task, chip_time_us, data_timestamp);
2661         T(last_sync_time) = now;
2662         T(last_sync_data_ts) = data_timestamp;
2663     }
2664 }
2665 
2666 static void dispatchData(TASK, const uint8_t *data, uint32_t count)
2667 {
2668     uint64_t ts = 0;
2669     uint32_t sample_index = 0;
2670     int i;
2671 
2672     if (count == 0) {
2673         return;
2674     }
2675 
2676     /* do time sync if no flush or fist time starting FIFO */
2677     if (T(fifo_start_sync) || !T(flush)) {
2678         computeTimeSync(_task, data, count, T(data_timestamp));
2679     }
2680 
2681     /* process FIFO data */
2682     while (count >= T(config).fifo_sample_size) {
2683         for (i = FIRST_CONT_SENSOR; i < NUM_CONT_SENSOR; ++i) {
2684             T(sensors[i]).updated = false;
2685         }
2686         parseOnePacket(_task, data, sample_index);
2687         sample_index += T(config).fifo_sample_size;
2688         count -= T(config).fifo_sample_size;
2689         // compute timestamp
2690         if (!sensortime_to_rtc_time(_task, T(chip_time_us), &ts)) {
2691             continue;
2692         }
2693         // add data
2694         for (i = FIRST_CONT_SENSOR; i < NUM_CONT_SENSOR; ++i) {
2695             if (!T(sensors[i]).configed || !T(sensors[i]).updated) {
2696                 continue;
2697             }
2698             if (T(sensors[i]).data_cnt % T(sensors[i]).decimator == 0) {
2699                 if (ts <= T(sensors[i]).prev_rtc_time) {
2700                     ts = T(sensors[i]).prev_rtc_time + MIN_INCREMENT_TIME_NS;
2701 #if DBG_TIMESTAMP
2702                     T(statistics_set).sync_truncate++;
2703 #endif
2704                 }
2705                 pushSensorData(_task, &T(sensors[i]), ts);
2706             }
2707         }
2708     }
2709 
2710     flushAllData();
2711 }
2712 
2713 static void int1Handling(TASK)
2714 {
2715     uint8_t int_status;
2716     uint8_t int_status2;
2717     uint16_t fifo_count = 0;
2718     union EmbeddedDataPoint trigger_axies;
2719     const uint8_t *buf;
2720 
2721     switch (T(int_state)) {
2722     case INT_READ_STATUS:
2723         T(int_state) = INT_PROCESS_STATUS;
2724         // read INT status1, status2 and fifo_count registers
2725         SPI_READ(REG_INT_STATUS, 1, &T(dataBuffer[0]));
2726         SPI_READ(REG_INT_STATUS2, 1, &T(dataBuffer[1]));
2727         SPI_READ(REG_FIFO_BYTE_COUNT1, 2, &T(dataBuffer[2]));
2728         T(data_timestamp) = sensorGetTime();
2729         spiBatchTxRx(&T(mode), sensorSpiCallback, _task, __FUNCTION__);
2730         break;
2731     case INT_PROCESS_STATUS:
2732         buf = T(dataBuffer[0]);
2733         int_status = buf[1];
2734         buf = T(dataBuffer[1]);
2735         int_status2 = buf[1];
2736         buf = T(dataBuffer[2]);
2737         fifo_count = buf[2] << 8 | buf[1];
2738         // INT status handling
2739         if (int_status2 & BIT_INT_STATUS_WOM_XYZ) {
2740             if (T(sensors[WOM]).configed) {
2741                 trigger_axies.idata = ((int_status2 & BIT_INT_STATUS_WOM_X) >> 0) | ((int_status2 & BIT_INT_STATUS_WOM_Y) >> 1) | ((int_status2 & BIT_INT_STATUS_WOM_Z) >> 2);
2742                 osEnqueueEvt(EVT_SENSOR_ANY_MOTION, trigger_axies.vptr, NULL);
2743             }
2744             if (T(sensors[NOMO]).configed && T(noMotionTimerHandle)) {
2745                 timTimerCancel(T(noMotionTimerHandle));
2746                 T(noMotionTimerHandle) = timTimerSet(ICM40600_NOM_DURATION_NS, 0, 100, noMotionCallback, (void *)&T(sensors[NOMO]), false);
2747             }
2748         }
2749         // FIFO overflow
2750         if (int_status & BIT_INT_STATUS_FIFO_FULL) {
2751             ERROR_PRINT("fifo overflow\n");
2752         }
2753         // FIFO WM status handling
2754         if ((int_status & BIT_INT_STATUS_FIFO_THS) || T(flush)) {
2755             T(int_state) = INT_READ_FIFO_DATA;
2756         } else {
2757             T(int_state) = INT_DONE;
2758             T(fifo_count) = 0;
2759             sensorSpiCallback(_task, 0);
2760             break;
2761         }
2762         // fall-through
2763     case INT_READ_FIFO_DATA:
2764         T(int_state) = INT_DONE;
2765         // compute fifo count and delete partial sample
2766         fifo_count -= fifo_count % T(config).fifo_sample_size;
2767         // read FIFO data
2768         T(fifo_count) = fifo_count;
2769         if (fifo_count > 0) {
2770             SPI_READ(REG_FIFO_DATA, fifo_count, &T(dataBuffer[0]));
2771             spiBatchTxRx(&T(mode), sensorSpiCallback, _task, __FUNCTION__);
2772         } else {
2773             sensorSpiCallback(_task, 0);
2774         }
2775         break;
2776     default:
2777         T(int_state) = INT_DONE;
2778         T(fifo_count) = 0;
2779         sensorSpiCallback(_task, 0);
2780         break;
2781     }
2782 }
2783 
2784 static void int1Evt(TASK, bool flush)
2785 {
2786     if (trySwitchState(SENSOR_INT_1_HANDLING)) {
2787         T(flush) = flush;
2788         T(int_state) = INT_READ_STATUS;
2789         int1Handling(_task);
2790     } else {
2791         if (flush) {
2792             T(pending_flush) = true;
2793         } else {
2794             T(pending_int[0]) = true;
2795         }
2796     }
2797 }
2798 
2799 #define DEC_OPS(power, firmware, rate, flush) \
2800     .sensorPower = power, \
2801     .sensorFirmwareUpload = firmware, \
2802     .sensorSetRate = rate, \
2803     .sensorFlush = flush
2804 
2805 #define DEC_OPS_CAL_CFG_TEST(power, firmware, rate, flush, cal, cfg, test) \
2806     DEC_OPS(power, firmware, rate, flush), \
2807     .sensorCalibrate = cal, \
2808     .sensorCfgData = cfg, \
2809     .sensorSelfTest = test,
2810 
2811 #define DEC_OPS_CFG(power, firmware, rate, flush, cfg) \
2812     DEC_OPS(power, firmware, rate, flush), \
2813     .sensorCfgData = cfg
2814 
2815 static const struct SensorOps mSensorOps[NUM_OF_SENSOR] =
2816 {
2817     { DEC_OPS_CAL_CFG_TEST(sensorSetPower, sensorFirmwareUpload, sensorSetRate, flushSensor, accCalibration,
2818             accCfgData, accSelfTest) },
2819     { DEC_OPS_CAL_CFG_TEST(sensorSetPower, sensorFirmwareUpload, sensorSetRate, flushSensor, gyrCalibration,
2820             gyrCfgData, gyrSelfTest) },
2821     { DEC_OPS(sensorSetPower, sensorFirmwareUpload, sensorSetRate, flushSensor) },
2822     { DEC_OPS(sensorSetPower, sensorFirmwareUpload, sensorSetRate, flushSensor) },
2823 };
2824 
2825 static void configEvent(struct ICM40600Sensor *mSensor, struct ConfigStat *ConfigData)
2826 {
2827     TDECL();
2828     int i;
2829 
2830     for (i = 0; &T(sensors[i]) != mSensor; i++) ;
2831 
2832     if (ConfigData->enable == 0 && mSensor->powered) {
2833         mSensorOps[i].sensorPower(false, (void *)i);
2834     } else if (ConfigData->enable == 1 && !mSensor->powered) {
2835         mSensorOps[i].sensorPower(true, (void *)i);
2836     } else {
2837         mSensorOps[i].sensorSetRate(ConfigData->rate, ConfigData->latency, (void *)i);
2838     }
2839 }
2840 
2841 static void processPendingEvt(TASK)
2842 {
2843     enum SensorIndex i;
2844 
2845     if (T(pending_int[0])) {
2846         T(pending_int[0]) = false;
2847         int1Evt(_task, false);
2848         return;
2849     }
2850 
2851     if (T(pending_flush)) {
2852         T(pending_flush) = false;
2853         int1Evt(_task, true);
2854         return;
2855     }
2856 
2857     for (i = 0; i < NUM_OF_SENSOR; i++) {
2858         if (T(pending_config[i])) {
2859             T(pending_config[i]) = false;
2860             configEvent(&T(sensors[i]), &T(sensors[i]).pConfig);
2861             return;
2862         }
2863     }
2864 
2865     if (T(pending_calibration_save)) {
2866         T(pending_calibration_save) = !saveCalibration(_task);
2867         return;
2868     }
2869 }
2870 
2871 static void sensorInit(TASK)
2872 {
2873     const uint8_t *buf;
2874 
2875     switch (T(init_state)) {
2876     case RESET_ICM40600:
2877         // reset chip and turn on
2878         SPI_WRITE(REG_DEVICE_CONFIG, BIT_SOFT_RESET, 100 * 1000);
2879         SPI_READ(REG_INT_STATUS, 1, &T(dataBuffer[0]));
2880         T(powered) = false;
2881         sensorTurnOn(_task);
2882         // set SPI speed register
2883         SPI_WRITE(REG_SPI_SPEED, ICM40600_SPI_SPEED_REG_VALUE);
2884         T(init_state) = INIT_ICM40600;
2885         spiBatchTxRx(&T(mode), sensorSpiCallback, _task, __FUNCTION__);
2886         break;
2887     case INIT_ICM40600:
2888         buf = T(dataBuffer[0]);
2889         if (!(buf[1] & BIT_INT_STATUS_RESET_DONE)) {
2890             ERROR_PRINT("chip reset failed!\n");
2891         }
2892         // reconfigure SPI speed
2893         T(mode).speed = ICM40600_SPI_SPEED_HZ;
2894         // configure interface
2895         // i2c disabled
2896         // fifo_count: little endian
2897         // sensor data: little endian
2898         SPI_WRITE(REG_INTF_CONFIG0, BIT_UI_SIFS_DISABLE_I2C);
2899         // configure interrupt
2900         SPI_WRITE(REG_INT_CONFIG, (INT1_POLARITY << SHIFT_INT1_POLARITY) |
2901                                   (INT1_DRIVE_CIRCUIT << SHIFT_INT1_DRIVE_CIRCUIT) |
2902                                   (INT1_MODE << SHIFT_INT1_MODE));
2903         SPI_WRITE(REG_INT_CONFIG1, BIT_INT_ASY_RST_DISABLE); // 9139
2904         // static config of sensors
2905         SPI_WRITE(REG_GYRO_ACCEL_CONFIG0, ICM40600_ACC_BW_IND | ICM40600_GYR_BW_IND);
2906         SPI_WRITE(REG_GYRO_CONFIG1, 0x1A);  // default reset value
2907         SPI_WRITE(REG_ACCEL_CONFIG1, 0x15); // default reset value
2908         // turn off FIFO and sensors
2909         SPI_WRITE(REG_FIFO_CONFIG, BIT_FIFO_MODE_BYPASS);
2910         SPI_WRITE(REG_FIFO_CONFIG1, 0);
2911         SPI_WRITE(REG_FIFO_CONFIG2, 0);
2912         SPI_WRITE(REG_FIFO_CONFIG3, 0);
2913         SPI_WRITE(REG_SMD_CONFIG, BIT_SMD_MODE_OFF);
2914         SPI_WRITE(REG_PWR_MGMT_0, BIT_GYRO_MODE_OFF | BIT_ACCEL_MODE_OFF, 200); // 9136
2915         sensorTurnOff(_task);
2916         T(init_state) = INIT_DONE;
2917         spiBatchTxRx(&T(mode), sensorSpiCallback, _task, __FUNCTION__);
2918         break;
2919     default:
2920         break;
2921     }
2922 }
2923 
2924 static void handleSpiDoneEvt(const void* evtData)
2925 {
2926     TDECL();
2927     struct ICM40600Sensor *mSensor;
2928     bool returnIdle = false;
2929     uint32_t i;
2930     const uint8_t *buf;
2931 #ifdef ACCEL_CAL_ENABLED
2932     bool accelCalNewBiasAvailable;
2933     struct TripleAxisDataPoint *sample;
2934     float accelCalBiasX, accelCalBiasY, accelCalBiasZ;
2935     bool fallThrough;
2936 #endif
2937 
2938     switch (GET_STATE()) {
2939     case SENSOR_BOOT:
2940         SET_STATE(SENSOR_VERIFY_ID);
2941         SPI_READ(REG_WHO_AM_I, 1, &T(dataBuffer[0]));
2942         spiBatchTxRx(&T(mode), sensorSpiCallback, _task, __FUNCTION__);
2943         break;
2944     case SENSOR_VERIFY_ID:
2945         buf = T(dataBuffer[0]);
2946         if (buf[1] != WHO_AM_I_ICM40604 && buf[1] != WHO_AM_I_ICM40605) {
2947             ERROR_PRINT("chip not found (id=0x%x)\n", buf[1]);
2948             break;
2949         }
2950         INFO_PRINT("chip found (id=0x%x)\n", buf[1]);
2951         SET_STATE(SENSOR_INITIALIZING);
2952         T(init_state) = RESET_ICM40600;
2953         sensorInit(_task);
2954         break;
2955     case SENSOR_INITIALIZING:
2956         if (T(init_state) == INIT_DONE) {
2957             for (i = 0; i < NUM_OF_SENSOR; i++) {
2958                 sensorRegisterInitComplete(T(sensors[i]).handle);
2959             }
2960             returnIdle = true;
2961         } else {
2962             sensorInit(_task);
2963         }
2964         break;
2965     case SENSOR_POWERING_UP:
2966         mSensor = (struct ICM40600Sensor *)evtData;
2967         sensorSignalInternalEvt(mSensor->handle, SENSOR_INTERNAL_EVT_POWER_STATE_CHG, 1, 0);
2968         returnIdle = true;
2969         break;
2970     case SENSOR_POWERING_DOWN:
2971         mSensor = (struct ICM40600Sensor *)evtData;
2972 #ifdef ACCEL_CAL_ENABLED
2973         if (mSensor->idx == ACC) {
2974             // https://source.android.com/devices/sensors/sensor-types.html
2975             // "The bias and scale calibration must only be updated while the sensor is deactivated,
2976             // so as to avoid causing jumps in values during streaming."
2977             accelCalNewBiasAvailable = accelCalUpdateBias(&T(accel_cal), &accelCalBiasX, &accelCalBiasY, &accelCalBiasZ);
2978             // notify HAL about new accel bias calibration
2979             if (accelCalNewBiasAvailable) {
2980                 fallThrough = true;
2981                 if (mSensor->data_evt->samples[0].firstSample.numSamples > 0) {
2982                     // flush existing samples so the bias appears after them
2983                     flushData(mSensor, EVENT_TYPE_BIT_DISCARDABLE | sensorGetMyEventType(mSensorInfo[ACC].sensorType));
2984                     // try to allocate another data event and break if unsuccessful
2985                     if (!allocateDataEvt(mSensor, sensorGetTime())) {
2986                         fallThrough = false;
2987                     }
2988                 }
2989                 if (fallThrough) {
2990                     mSensor->data_evt->samples[0].firstSample.biasCurrent = true;
2991                     mSensor->data_evt->samples[0].firstSample.biasPresent = 1;
2992                     mSensor->data_evt->samples[0].firstSample.biasSample =
2993                             mSensor->data_evt->samples[0].firstSample.numSamples;
2994                     sample = &mSensor->data_evt->samples[mSensor->data_evt->samples[0].firstSample.numSamples++];
2995                     sample->x = accelCalBiasX;
2996                     sample->y = accelCalBiasY;
2997                     sample->z = accelCalBiasZ;
2998                     flushData(mSensor, sensorGetMyEventType(mSensorInfo[ACC].biasType));
2999                     DEBUG_PRINT("send new accel bias\n");
3000                     allocateDataEvt(mSensor, sensorGetTime());
3001                 }
3002             }
3003         }
3004 #endif
3005         sensorSignalInternalEvt(mSensor->handle, SENSOR_INTERNAL_EVT_POWER_STATE_CHG, 0, 0);
3006         returnIdle = true;
3007         break;
3008     case SENSOR_INT_1_HANDLING:
3009         if (T(int_state) == INT_DONE) {
3010             buf = T(dataBuffer[0]);
3011             dispatchData(_task, &buf[1], T(fifo_count));
3012             if (T(flush)) {
3013                 sendFlushEvt();
3014             }
3015             returnIdle = true;
3016         } else {
3017             int1Handling(_task);
3018         }
3019         break;
3020     case SENSOR_CONFIG_CHANGING:
3021         mSensor = (struct ICM40600Sensor *)evtData;
3022         sensorSignalInternalEvt(mSensor->handle, SENSOR_INTERNAL_EVT_RATE_CHG, mSensor->rate, mSensor->latency);
3023         returnIdle = true;
3024         break;
3025     case SENSOR_CALIBRATING:
3026         mSensor = (struct ICM40600Sensor *)evtData;
3027         if (mSensor->idx == ACC) {
3028             if (T(calibration_state) == CALIBRATION_DONE) {
3029                 INFO_PRINT("Accel Calibration done\n");
3030                 returnIdle = true;
3031             } else {
3032                 calibrationHandling(_task, ACC);
3033             }
3034         } else if (mSensor->idx == GYR) {
3035             if (T(calibration_state) == CALIBRATION_DONE) {
3036                 INFO_PRINT("Gyro Calibration done\n");
3037                 returnIdle = true;
3038             } else {
3039                 calibrationHandling(_task, GYR);
3040             }
3041         }
3042         break;
3043     case SENSOR_TESTING:
3044         mSensor = (struct ICM40600Sensor *)evtData;
3045         if (mSensor->idx == ACC) {
3046             if (T(selftest_state) == TEST_DONE) {
3047                 INFO_PRINT("Accel Selftest done\n");
3048                 returnIdle = true;
3049             } else {
3050                 selfTestHandling(_task, ACC);
3051             }
3052         } else if (mSensor->idx == GYR) {
3053             if (T(selftest_state) == TEST_DONE) {
3054                 INFO_PRINT("Gyro Selftest done\n");
3055                 returnIdle = true;
3056             } else {
3057                 selfTestHandling(_task, GYR);
3058             }
3059         }
3060         break;
3061     case SENSOR_SAVE_CALIBRATION:
3062         returnIdle = true;
3063         break;
3064     default:
3065         break;
3066     }
3067 
3068     if (returnIdle) {
3069         SET_STATE(SENSOR_IDLE);
3070         processPendingEvt(_task);
3071     }
3072 }
3073 
3074 #ifdef GYRO_CAL_ENABLED
3075 static void processMagEvents(TASK, const struct TripleAxisDataEvent *evtData)
3076 {
3077     const struct SensorFirstSample * const first = &evtData->samples[0].firstSample;
3078     const struct TripleAxisDataPoint *sample;
3079     uint64_t ts = evtData->referenceTime;
3080     unsigned int i;
3081 
3082     for (i = 0; i < first->numSamples; ++i) {
3083         sample = &evtData->samples[i];
3084         if (i > 0) {
3085             ts += sample->deltaTime;
3086         }
3087         gyroCalUpdateMag(&T(gyro_cal), ts, sample->x, sample->y, sample->z);
3088     }
3089 }
3090 #endif
3091 
3092 static void handleEvent(uint32_t evtType, const void* evtData)
3093 {
3094     TDECL();
3095 
3096     switch (evtType) {
3097     case EVT_APP_START:
3098         SET_STATE(SENSOR_BOOT);
3099         osEventUnsubscribe(T(tid), EVT_APP_START);
3100 #ifdef GYRO_CAL_ENABLED
3101         osEventSubscribe(T(tid), EVT_SENSOR_MAG_DATA_RDY);
3102 #endif
3103         // fall through
3104     case EVT_SPI_DONE:
3105         handleSpiDoneEvt(evtData);
3106         break;
3107     case EVT_SENSOR_INTERRUPT_1:
3108         int1Evt(_task, false);
3109         break;
3110 #ifdef GYRO_CAL_ENABLED
3111     case EVT_SENSOR_MAG_DATA_RDY:
3112         if (evtData != SENSOR_DATA_EVENT_FLUSH) {
3113             processMagEvents(_task, (const struct TripleAxisDataEvent *)evtData);
3114         }
3115         break;
3116 #endif
3117     default:
3118         break;
3119     }
3120 }
3121 
3122 static void initSensorStruct(struct ICM40600Sensor *sensor, enum SensorIndex idx)
3123 {
3124     sensor->data_evt = NULL;
3125     sensor->rate = 0;
3126     sensor->latency = 0;
3127     sensor->decimator = 1;
3128     sensor->data_cnt = 0;
3129     sensor->prev_rtc_time = 0;
3130     sensor->skip_sample_cnt = 0;
3131     sensor->data[0] = 0;
3132     sensor->data[1] = 0;
3133     sensor->data[2] = 0;
3134     sensor->offset[0] = 0;
3135     sensor->offset[1] = 0;
3136     sensor->offset[2] = 0;
3137     sensor->updated = false;
3138     sensor->powered = false;
3139     sensor->configed = false;
3140     sensor->wait_for_odr = false;
3141     sensor->idx = idx;
3142     sensor->flush = 0;
3143 }
3144 
3145 static bool startTask(uint32_t task_id)
3146 {
3147     TDECL();
3148     enum SensorIndex i;
3149     size_t slabSize;
3150 
3151     time_init(_task);
3152 
3153     T(tid) = task_id;
3154 
3155     T(Int1) = gpioRequest(ICM40600_INT1_PIN);
3156     T(Irq1) = ICM40600_INT1_IRQ;
3157     T(Isr1).func = icm40600Isr1;
3158     T(Int1_EN) = false;
3159     T(pending_int[0]) = false;
3160     T(pending_flush) = false;
3161     T(pending_calibration_save) = false;
3162 
3163     T(mode).speed = ICM40600_SPI_DEFAULT_SPEED_HZ;
3164     T(mode).bitsPerWord = 8;
3165     T(mode).cpol = SPI_CPOL_IDLE_HI;
3166     T(mode).cpha = SPI_CPHA_TRAILING_EDGE;
3167     T(mode).nssChange = true;
3168     T(mode).format = SPI_FORMAT_MSB_FIRST;
3169     T(cs) = GPIO_PB(12);
3170     T(config).accel_rate = 0;
3171     T(config).gyro_rate = 0;
3172     T(config).fifo_rate = 0;
3173     T(config).wom_threshold = 0;
3174     T(config).fifo_watermark = 0;
3175     T(config).fifo_sample_size = 0;
3176     T(config).accel_on = false;
3177     T(config).gyro_on = false;
3178     T(config).wom_on = false;
3179     T(noMotionTimerHandle) = 0;
3180     T(fifo_count) = 0;
3181     T(powered) = false;
3182     T(flush) = false;
3183     T(data_timestamp) = 0;
3184     T(chip_time_us) = 0;
3185     T(last_sync_time) = 0;
3186     T(last_sync_data_ts) = 0;
3187     T(chip_timestamp) = 0;
3188     T(fifo_start_sync) = false;
3189     T(chip_temperature) = TEMP_OFFSET;
3190 
3191     spiMasterRequest(ICM40600_SPI_BUS_ID, &T(spiDev));
3192 
3193     for (i = 0; i < NUM_OF_SENSOR; i++) {
3194         initSensorStruct(&T(sensors[i]), i);
3195         T(sensors[i]).handle = sensorRegister(&mSensorInfo[i], &mSensorOps[i], (void *)i, false);
3196         T(pending_config[i]) = false;
3197     }
3198 
3199     osEventSubscribe(T(tid), EVT_APP_START);
3200 
3201 #ifdef ACCEL_CAL_ENABLED
3202     // Init Accel Cal
3203     accelCalInit(&T(accel_cal),
3204                  800000000, // Stillness Time in ns (0.8s)
3205                  5,         // Minimum Sample Number
3206                  0.00025,   // Threshold
3207                  15,        // nx bucket count
3208                  15,        // nxb bucket count
3209                  15,        // ny bucket count
3210                  15,        // nyb bucket count
3211                  15,        // nz bucket count
3212                  15,        // nzb bucket count
3213                  15);       // nle bucket count
3214 #endif
3215 #ifdef GYRO_CAL_ENABLED
3216     // Init Gyro Cal
3217     gyroCalInit(&T(gyro_cal),
3218                 SEC_TO_NANOS(5.0f),   // Min stillness period = 5.0 seconds
3219                 SEC_TO_NANOS(5.9f),   // Max stillness period = 6.0 seconds (NOTE 1)
3220                 0, 0, 0,              // Initial bias offset calibration
3221                 0,                    // Time stamp of initial bias calibration
3222                 SEC_TO_NANOS(1.5f),   // Analysis window length = 1.5 seconds
3223                 7.5e-5f,              // Gyroscope variance threshold [rad/sec]^2
3224                 1.5e-5f,              // Gyroscope confidence delta [rad/sec]^2
3225                 4.5e-3f,              // Accelerometer variance threshold [m/sec^2]^2
3226                 9.0e-4f,              // Accelerometer confidence delta [m/sec^2]^2
3227                 5.0f,                 // Magnetometer variance threshold [uT]^2
3228                 1.0f,                 // Magnetometer confidence delta [uT]^2
3229                 0.95f,                // Stillness threshold [0,1]
3230                 40.0f * MDEG_TO_RAD,  // Stillness mean variation limit [rad/sec]
3231                 1.5f,                 // Max temperature delta during stillness [C]
3232                 true);                // Gyro calibration enable
3233     // NOTE 1: This parameter is set to 5.9 seconds to achieve a max stillness
3234     // period of 6.0 seconds and avoid buffer boundary conditions that could push
3235     // the max stillness to the next multiple of the analysis window length
3236     // (i.e., 7.5 seconds).
3237 #endif
3238 
3239     slabSize = sizeof(struct TripleAxisDataEvent) +
3240                MAX_NUM_COMMS_EVENT_SAMPLES * sizeof(struct TripleAxisDataPoint);
3241     // TODO: need to investigate slab items number
3242     T(mDataSlab) = slabAllocatorNew(slabSize, 4, 20);
3243     if (!T(mDataSlab)) {
3244         ERROR_PRINT("slabAllocatorNew() failed\n");
3245         return false;
3246     }
3247     T(mWbufCnt) = 0;
3248     T(mRegCnt) = 0;
3249     T(spiInUse) = false;
3250 
3251     return true;
3252 }
3253 
3254 static void endTask(void)
3255 {
3256     TDECL();
3257 
3258 #ifdef ACCEL_CAL_ENABLED
3259     accelCalDestroy(&T(accel_cal));
3260 #endif
3261 #ifdef GYRO_CAL_ENABLED
3262     gyroCalDestroy(&T(gyro_cal));
3263 #endif
3264     slabAllocatorDestroy(T(mDataSlab));
3265     spiMasterRelease(T(spiDev));
3266 
3267     // disable and release interrupt.
3268     disableInterrupt(T(Int1), T(Irq1), &T(Isr1));
3269     gpioRelease(T(Int1));
3270 }
3271 
3272 INTERNAL_APP_INIT(ICM40600_APP_ID, ICM40600_APP_VERSION, startTask, endTask, handleEvent);
3273