1 /*
2  * Copyright (C) 2016 The Android Open Source Project
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 <atomic.h>
19 #include <common/math/macros.h>
20 #include <cpu/cpuMath.h>
21 #include <errno.h>
22 #include <gpio.h>
23 #include <heap.h>
24 #include <halIntf.h>
25 #include <hostIntf.h>
26 #include <i2c.h>
27 #include <isr.h>
28 #include <nanohub_math.h>
29 #include <nanohubPacket.h>
30 #include <printf.h>
31 #include <plat/exti.h>
32 #include <plat/gpio.h>
33 #include <plat/syscfg.h>
34 #include <plat/rtc.h>
35 #include <sensors.h>
36 #include <seos.h>
37 #include <slab.h>
38 #include <spi.h>
39 #include <timer.h>
40 #include <variant/sensType.h>
41 #include <variant/variant.h>
42 
43 #ifdef MAG_SLAVE_PRESENT
44 #include <calibration/magnetometer/mag_cal/mag_cal.h>
45 #endif
46 
47 #ifdef ACCEL_CAL_ENABLED
48 #include <calibration/accelerometer/accel_cal.h>
49 #endif
50 
51 #if defined(OVERTEMPCAL_ENABLED) && !defined(GYRO_CAL_ENABLED)
52 #undef OVERTEMPCAL_ENABLED
53 #endif
54 
55 #if defined(GYRO_CAL_DBG_ENABLED) && !defined(GYRO_CAL_ENABLED)
56 #undef GYRO_CAL_DBG_ENABLED
57 #endif
58 
59 #if defined(OVERTEMPCAL_DBG_ENABLED) && !defined(OVERTEMPCAL_ENABLED)
60 #undef OVERTEMPCAL_DBG_ENABLED
61 #endif
62 
63 #ifdef GYRO_CAL_ENABLED
64 #include <calibration/gyroscope/gyro_cal.h>
65 #endif  // GYRO_CAL_ENABLED
66 
67 #ifdef OVERTEMPCAL_ENABLED
68 #include <calibration/over_temp/over_temp_cal.h>
69 #endif  // OVERTEMPCAL_ENABLED
70 
71 #include <limits.h>
72 #include <stdlib.h>
73 #include <string.h>
74 
75 #define VERBOSE_PRINT(fmt, ...) do { \
76         osLog(LOG_VERBOSE, "%s " fmt, "[BMI160]", ##__VA_ARGS__); \
77     } while (0);
78 
79 #define INFO_PRINT(fmt, ...) do { \
80         osLog(LOG_INFO, "%s " fmt, "[BMI160]", ##__VA_ARGS__); \
81     } while (0);
82 
83 #define ERROR_PRINT(fmt, ...) do { \
84         osLog(LOG_ERROR, "%s " fmt, "[BMI160] ERROR:", ##__VA_ARGS__); \
85     } while (0);
86 
87 #define DEBUG_PRINT(fmt, ...) do { \
88         if (DBG_ENABLE) {  \
89             osLog(LOG_DEBUG, "%s " fmt, "[BMI160]", ##__VA_ARGS__); \
90         } \
91     } while (0);
92 
93 #define DEBUG_PRINT_IF(cond, fmt, ...) do { \
94         if ((cond) && DBG_ENABLE) {  \
95             osLog(LOG_DEBUG, "%s " fmt, "[BMI160]", ##__VA_ARGS__); \
96         } \
97     } while (0);
98 
99 #define DBG_ENABLE                0
100 #define DBG_CHUNKED               0
101 #define DBG_INT                   0
102 #define DBG_SHALLOW_PARSE         0
103 #define DBG_STATE                 0
104 #define DBG_WM_CALC               0
105 #define TIMESTAMP_DBG             0
106 
107 #define BMI160_APP_VERSION 20
108 
109 // fixme: to list required definitions for a slave mag
110 #ifdef USE_BMM150
111 #include "bosch_bmm150_slave.h"
112 #elif USE_AK09915
113 #include "akm_ak09915_slave.h"
114 #endif
115 
116 #define BMI160_APP_ID APP_ID_MAKE(NANOHUB_VENDOR_GOOGLE, 2)
117 
118 #ifdef BMI160_I2C_BUS_ID
119 #define BMI160_USE_I2C
120 
121 #ifndef BMI160_I2C_SPEED
122 #define BMI160_I2C_SPEED          400000
123 #endif
124 #ifndef BMI160_I2C_ADDR
125 #define BMI160_I2C_ADDR           0x68
126 #endif
127 #endif
128 
129 #define BMI160_SPI_WRITE          0x00
130 #define BMI160_SPI_READ           0x80
131 
132 #ifndef BMI160_SPI_BUS_ID
133 #define BMI160_SPI_BUS_ID         1
134 #endif
135 #ifndef BMI160_SPI_SPEED_HZ
136 #define BMI160_SPI_SPEED_HZ       8000000
137 #endif
138 #define BMI160_SPI_MODE           3
139 #ifndef BMI160_SPI_CS_PIN
140 #define BMI160_SPI_CS_PIN         GPIO_PB(12)
141 #endif
142 
143 #ifndef BMI160_INT1_IRQ
144 #define BMI160_INT1_IRQ           EXTI9_5_IRQn
145 #endif
146 #ifndef BMI160_INT1_PIN
147 #define BMI160_INT1_PIN           GPIO_PB(6)
148 #endif
149 #ifndef BMI160_INT2_IRQ
150 #define BMI160_INT2_IRQ           EXTI9_5_IRQn
151 #endif
152 #ifndef BMI160_INT2_PIN
153 #define BMI160_INT2_PIN           GPIO_PB(7)
154 #endif
155 
156 #define BMI160_ID                 0xd1
157 
158 #define BMI160_REG_ID             0x00
159 #define BMI160_REG_ERR            0x02
160 #define BMI160_REG_PMU_STATUS     0x03
161 #define BMI160_REG_DATA_0         0x04
162 #define BMI160_REG_DATA_1         0x05
163 #define BMI160_REG_DATA_14        0x12
164 #define BMI160_REG_SENSORTIME_0   0x18
165 #define BMI160_REG_STATUS         0x1b
166 #define BMI160_REG_INT_STATUS_0   0x1c
167 #define BMI160_REG_INT_STATUS_1   0x1d
168 #define BMI160_REG_TEMPERATURE_0  0x20
169 #define BMI160_REG_TEMPERATURE_1  0x21
170 #define BMI160_REG_FIFO_LENGTH_0  0x22
171 #define BMI160_REG_FIFO_DATA      0x24
172 #define BMI160_REG_ACC_CONF       0x40
173 #define BMI160_REG_ACC_RANGE      0x41
174 #define BMI160_REG_GYR_CONF       0x42
175 #define BMI160_REG_GYR_RANGE      0x43
176 #define BMI160_REG_MAG_CONF       0x44
177 #define BMI160_REG_FIFO_DOWNS     0x45
178 #define BMI160_REG_FIFO_CONFIG_0  0x46
179 #define BMI160_REG_FIFO_CONFIG_1  0x47
180 #define BMI160_REG_MAG_IF_0       0x4b
181 #define BMI160_REG_MAG_IF_1       0x4c
182 #define BMI160_REG_MAG_IF_2       0x4d
183 #define BMI160_REG_MAG_IF_3       0x4e
184 #define BMI160_REG_MAG_IF_4       0x4f
185 #define BMI160_REG_INT_EN_0       0x50
186 #define BMI160_REG_INT_EN_1       0x51
187 #define BMI160_REG_INT_EN_2       0x52
188 #define BMI160_REG_INT_OUT_CTRL   0x53
189 #define BMI160_REG_INT_LATCH      0x54
190 #define BMI160_REG_INT_MAP_0      0x55
191 #define BMI160_REG_INT_MAP_1      0x56
192 #define BMI160_REG_INT_MAP_2      0x57
193 #define BMI160_REG_INT_DATA_0     0x58
194 #define BMI160_REG_INT_MOTION_0   0x5f
195 #define BMI160_REG_INT_MOTION_1   0x60
196 #define BMI160_REG_INT_MOTION_2   0x61
197 #define BMI160_REG_INT_MOTION_3   0x62
198 #define BMI160_REG_INT_TAP_0      0x63
199 #define BMI160_REG_INT_TAP_1      0x64
200 #define BMI160_REG_INT_FLAT_0     0x67
201 #define BMI160_REG_INT_FLAT_1     0x68
202 #define BMI160_REG_PMU_TRIGGER    0x6C
203 #define BMI160_REG_FOC_CONF       0x69
204 #define BMI160_REG_CONF           0x6a
205 #define BMI160_REG_IF_CONF        0x6b
206 #define BMI160_REG_SELF_TEST      0x6d
207 #define BMI160_REG_OFFSET_0       0x71
208 #define BMI160_REG_OFFSET_3       0x74
209 #define BMI160_REG_OFFSET_6       0x77
210 #define BMI160_REG_STEP_CNT_0     0x78
211 #define BMI160_REG_STEP_CONF_0    0x7a
212 #define BMI160_REG_STEP_CONF_1    0x7b
213 #define BMI160_REG_CMD            0x7e
214 #define BMI160_REG_MAGIC          0x7f
215 
216 #define INT_STEP        0x01
217 #define INT_ANY_MOTION  0x04
218 #define INT_DOUBLE_TAP  0x10
219 #define INT_SINGLE_TAP  0x20
220 #define INT_ORIENT      0x40
221 #define INT_FLAT        0x80
222 #define INT_HIGH_G_Z    0x04
223 #define INT_LOW_G       0x08
224 #define INT_DATA_RDY    0x10
225 #define INT_FIFO_FULL   0x20
226 #define INT_FIFO_WM     0x40
227 #define INT_NO_MOTION   0x80
228 
229 #define BMI160_FRAME_HEADER_INVALID  0x80   // mark the end of valid data
230 #define BMI160_FRAME_HEADER_SKIP     0x81   // not defined by hw, used for skip a byte in buffer
231 
232 #define WATERMARK_MIN                1
233 #define WATERMARK_MAX                200    // must <= 255 (0xff)
234 
235 #define WATERMARK_MAX_SENSOR_RATE    400    // Accel and gyro are 400 Hz max
236 #define WATERMARK_TIME_UNIT_NS       (1000000000ULL/(WATERMARK_MAX_SENSOR_RATE))
237 
238 #define gSPI    BMI160_SPI_BUS_ID
239 
240 #define ACCL_INT_LINE EXTI_LINE_P6
241 #define GYR_INT_LINE EXTI_LINE_P7
242 
243 #define SPI_WRITE_0(addr, data) spiQueueWrite(addr, data, 2)
244 #define SPI_WRITE_1(addr, data, delay) spiQueueWrite(addr, data, delay)
245 #define GET_SPI_WRITE_MACRO(_1,_2,_3,NAME,...) NAME
246 #define SPI_WRITE(...) GET_SPI_WRITE_MACRO(__VA_ARGS__, SPI_WRITE_1, SPI_WRITE_0)(__VA_ARGS__)
247 
248 #define SPI_READ_0(addr, size, buf) spiQueueRead(addr, size, buf, 0)
249 #define SPI_READ_1(addr, size, buf, delay) spiQueueRead(addr, size, buf, delay)
250 #define GET_SPI_READ_MACRO(_1,_2,_3,_4,NAME,...) NAME
251 #define SPI_READ(...) GET_SPI_READ_MACRO(__VA_ARGS__, SPI_READ_1, SPI_READ_0)(__VA_ARGS__)
252 
253 #define EVT_SENSOR_ACC_DATA_RDY sensorGetMyEventType(SENS_TYPE_ACCEL)
254 #define EVT_SENSOR_GYR_DATA_RDY sensorGetMyEventType(SENS_TYPE_GYRO)
255 #define EVT_SENSOR_MAG_DATA_RDY sensorGetMyEventType(SENS_TYPE_MAG)
256 #define EVT_SENSOR_STEP sensorGetMyEventType(SENS_TYPE_STEP_DETECT)
257 #define EVT_SENSOR_NO_MOTION sensorGetMyEventType(SENS_TYPE_NO_MOTION)
258 #define EVT_SENSOR_ANY_MOTION sensorGetMyEventType(SENS_TYPE_ANY_MOTION)
259 #define EVT_SENSOR_FLAT sensorGetMyEventType(SENS_TYPE_FLAT)
260 #define EVT_SENSOR_DOUBLE_TAP sensorGetMyEventType(SENS_TYPE_DOUBLE_TAP)
261 #define EVT_SENSOR_STEP_COUNTER sensorGetMyEventType(SENS_TYPE_STEP_COUNT)
262 
263 #define MAX_NUM_COMMS_EVENT_SAMPLES 15
264 
265 #ifndef BMI160_ACC_SAMPLES
266 #define BMI160_ACC_SAMPLES 3000
267 #endif
268 
269 #ifndef BMI160_GYRO_SAMPLES
270 #define BMI160_GYRO_SAMPLES 20
271 #endif
272 
273 #ifndef BMI160_MAG_SAMPLES
274 #define BMI160_MAG_SAMPLES 600
275 #endif
276 
277 // Default accel range is 8g
278 #ifndef BMI160_ACC_RANGE_G
279 #define BMI160_ACC_RANGE_G 8
280 #endif
281 
282 #if BMI160_ACC_RANGE_G == 16
283 #define ACC_RANGE_SETTING 0x0c
284 #elif BMI160_ACC_RANGE_G == 8
285 #define ACC_RANGE_SETTING 0x08
286 #else
287 #error "Invalid BMI160_ACC_RANGE_G setting: valid values are 8, 16"
288 #endif
289 
290 #define kScale_acc    (9.81f * BMI160_ACC_RANGE_G / 32768.0f)
291 #define kScale_gyr    0.00053263221f  // GYR_range * M_PI / (180.0f * 32768.0f);
292 #define kScale_temp   0.001953125f    // temperature in deg C
293 #define kTempInvalid  -1000.0f
294 
295 #define kTimeSyncPeriodNs        100000000ull // sync sensor and RTC time every 100ms
296 #define kSensorTimerIntervalUs   39ull        // bmi160 clock increaments every 39000ns
297 
298 #define kMinRTCTimeIncrementNs   1250000ull // forced min rtc time increment, 1.25ms for 400Hz
299 #define kMinSensorTimeIncrement  64         // forced min sensortime increment,
300                                             // 64 = 2.5 msec for 400Hz
301 
302 #define ACC_MIN_RATE    5
303 #define GYR_MIN_RATE    6
304 #define ACC_MAX_RATE    12
305 #define GYR_MAX_RATE    13
306 #define MAG_MAX_RATE    11
307 #define ACC_MAX_OSR     3
308 #define GYR_MAX_OSR     4
309 #define ODR_100HZ       8
310 #define ODR_200HZ       9
311 
312 #define MOTION_ODR         7
313 
314 #define RETRY_CNT_CALIBRATION 10
315 #define RETRY_CNT_ID 5
316 #define RETRY_CNT_MAG 30
317 
318 #define SPI_PACKET_SIZE 30
319 #define FIFO_READ_SIZE  (1024+4)
320 #define CHUNKED_READ_SIZE (64)
321 #define BUF_MARGIN 32   // some extra buffer for additional reg RW when a FIFO read happens
322 #define SPI_BUF_SIZE (FIFO_READ_SIZE + CHUNKED_READ_SIZE + BUF_MARGIN)
323 
324 #ifndef ABS
325 #define ABS(x) (((x) > 0) ? (x) : -(x))
326 #endif
327 
328 enum SensorIndex {
329     FIRST_CONT_SENSOR = 0,
330     ACC = FIRST_CONT_SENSOR,
331     GYR,
332 #ifdef MAG_SLAVE_PRESENT
333     MAG,
334 #endif
335     NUM_CONT_SENSOR,
336     FIRST_ONESHOT_SENSOR = NUM_CONT_SENSOR,
337     STEP = FIRST_ONESHOT_SENSOR,
338     DTAP,
339     FLAT,
340     ANYMO,
341     NOMO,
342     STEPCNT,
343     NUM_OF_SENSOR,
344 };
345 
346 enum SensorEvents {
347     NO_EVT = -1,
348     EVT_SPI_DONE = EVT_APP_START + 1,
349     EVT_SENSOR_INTERRUPT_1,
350     EVT_SENSOR_INTERRUPT_2,
351     EVT_TIME_SYNC,
352 };
353 
354 enum InitState {
355     RESET_BMI160,
356     INIT_BMI160,
357     INIT_MAG,
358     INIT_ON_CHANGE_SENSORS,
359     INIT_DONE,
360 };
361 
362 enum CalibrationState {
363     CALIBRATION_START,
364     CALIBRATION_FOC,
365     CALIBRATION_WAIT_FOC_DONE,
366     CALIBRATION_SET_OFFSET,
367     CALIBRATION_DONE,
368     CALIBRATION_TIMEOUT,
369 };
370 
371 enum AccTestState {
372     ACC_TEST_START,
373     ACC_TEST_CONFIG,
374     ACC_TEST_RUN_0,
375     ACC_TEST_RUN_1,
376     ACC_TEST_VERIFY,
377     ACC_TEST_DONE
378 };
379 
380 enum GyroTestState {
381     GYRO_TEST_START,
382     GYRO_TEST_RUN,
383     GYRO_TEST_VERIFY,
384     GYRO_TEST_DONE
385 };
386 
387 enum SensorState {
388     // keep this in sync with getStateName
389     SENSOR_BOOT,
390     SENSOR_VERIFY_ID,
391     SENSOR_INITIALIZING,
392     SENSOR_IDLE,
393     SENSOR_POWERING_UP,
394     SENSOR_POWERING_DOWN,
395     SENSOR_CONFIG_CHANGING,
396     SENSOR_INT_1_HANDLING,
397     SENSOR_INT_2_HANDLING,
398     SENSOR_CALIBRATING,
399     SENSOR_TESTING,
400     SENSOR_STEP_CNT,
401     SENSOR_TIME_SYNC,
402     SENSOR_SAVE_CALIBRATION,
403     SENSOR_NUM_OF_STATE
404 };
405 #if DBG_STATE
406 #define PRI_STATE "s"
getStateName(int32_t s)407 static const char * getStateName(int32_t s) {
408     // keep this in sync with SensorState
409     static const char* const l[] = {"BOOT", "VERIFY_ID", "INIT", "IDLE", "PWR_UP",
410             "PWR-DN", "CFG_CHANGE", "INT1", "INT2", "CALIB", "TEST", "STEP_CNT", "SYNC", "SAVE_CALIB"};
411     if (s >= 0 && s < SENSOR_NUM_OF_STATE) {
412         return l[s];
413     }
414     return "???";
415 #else
416 #define PRI_STATE PRIi32
417 static int32_t getStateName(int32_t s) {
418     return s;
419 #endif
420 }
421 
422 enum MagConfigState {
423     MAG_SET_START,
424     MAG_SET_IF,
425 
426     // BMM150 only
427     MAG_SET_REPXY,
428     MAG_SET_REPZ,
429     MAG_GET_DIG_X,
430     MAG_GET_DIG_Y,
431     MAG_GET_DIG_Z,
432     MAG_SET_SAVE_DIG,
433 
434     MAG_SET_FORCE,
435     MAG_SET_ADDR,
436     MAG_SET_DATA,
437     MAG_SET_DONE,
438 
439     MAG_INIT_FAILED
440 };
441 
442 struct ConfigStat {
443     uint64_t latency;
444     uint32_t rate;
445     bool enable;
446 };
447 
448 struct CalibrationData {
449     struct HostHubRawPacket header;
450     struct SensorAppEventHeader data_header;
451     int32_t xBias;
452     int32_t yBias;
453     int32_t zBias;
454 } __attribute__((packed));
455 
456 struct TestResultData {
457     struct HostHubRawPacket header;
458     struct SensorAppEventHeader data_header;
459 } __attribute__((packed));
460 
461 struct BMI160Sensor {
462     struct ConfigStat pConfig; // pending config status request
463     struct TripleAxisDataEvent *data_evt;
464     uint32_t handle;
465     uint32_t rate;
466     uint64_t latency;
467     uint64_t prev_rtc_time;
468     uint32_t offset[3];
469     bool powered; // activate status
470     bool configed; // configure status
471     bool offset_enable;
472     uint8_t flush;
473     enum SensorIndex idx;
474 };
475 
476 struct OtcGyroUpdateBuffer {
477     struct AppToSensorHalDataBuffer head;
478     struct GyroOtcData data;
479     volatile uint8_t lock; // lock for static object
480     bool sendToHostRequest;
481 } __attribute__((packed));
482 
483 struct BMI160Task {
484     uint32_t tid;
485     struct BMI160Sensor sensors[NUM_OF_SENSOR];
486 
487 #ifdef GYRO_CAL_ENABLED
488     // Gyro Cal -- Declaration.
489     struct GyroCal gyro_cal;
490 #endif  //  GYRO_CAL_ENABLED
491 
492 #ifdef OVERTEMPCAL_ENABLED
493     // Over-temp gyro calibration object.
494     struct OverTempCal over_temp_gyro_cal;
495     struct OtcGyroUpdateBuffer otcGyroUpdateBuffer;
496 #endif  //  OVERTEMPCAL_ENABLED
497 
498     // time keeping.
499     uint64_t last_sensortime;
500     uint64_t frame_sensortime;
501     uint64_t prev_frame_time[NUM_CONT_SENSOR];
502     uint64_t time_delta[NUM_CONT_SENSOR];
503     uint64_t next_delta[NUM_CONT_SENSOR];
504     uint64_t tempTime;
505     uint64_t timesync_rtc_time;
506 
507     // spi and interrupt
508     spi_cs_t cs;
509     struct SpiMode mode;
510     struct SpiPacket packets[SPI_PACKET_SIZE];
511     struct SpiDevice *spiDev;
512     struct Gpio *Int1;
513     struct Gpio *Int2;
514     IRQn_Type Irq1;
515     IRQn_Type Irq2;
516     struct ChainedIsr Isr1;
517     struct ChainedIsr Isr2;
518 #ifdef ACCEL_CAL_ENABLED
519     struct AccelCal acc;
520 #endif
521 #ifdef MAG_SLAVE_PRESENT
522     struct MagCal moc;
523 #endif
524     time_sync_t gSensorTime2RTC;
525 
526     float tempCelsius;
527     float last_charging_bias_x;
528     uint32_t total_step_cnt;
529     uint32_t last_step_cnt;
530     uint32_t poll_generation;
531     uint32_t active_poll_generation;
532     uint8_t active_oneshot_sensor_cnt;
533     uint8_t interrupt_enable_0;
534     uint8_t interrupt_enable_2;
535     uint8_t acc_downsample;
536     uint8_t gyr_downsample;
537     bool magBiasPosted;
538     bool magBiasCurrent;
539     bool fifo_enabled[NUM_CONT_SENSOR];
540 
541     // for step count
542     uint32_t stepCntSamplingTimerHandle;
543     bool step_cnt_changed;
544 
545     // spi buffers
546     int xferCnt;
547     uint8_t *dataBuffer;
548     uint8_t *statusBuffer;
549     uint8_t *sensorTimeBuffer;
550     uint8_t *temperatureBuffer;
551     uint8_t txrxBuffer[SPI_BUF_SIZE];
552 
553     // states
554     volatile uint8_t state;  //task state, type enum SensorState, do NOT change this directly
555     enum InitState init_state;
556     enum MagConfigState mag_state;
557     enum CalibrationState calibration_state;
558     enum AccTestState acc_test_state;
559     enum GyroTestState gyro_test_state;
560 
561     // for self-test
562     int16_t accTestX, accTestY, accTestZ;
563 
564     // pending configs
565     bool pending_int[2];
566     bool pending_step_cnt;
567     bool pending_config[NUM_OF_SENSOR];
568     bool pending_calibration_save;
569     bool pending_time_sync;
570     bool pending_delta[NUM_CONT_SENSOR];
571     bool pending_dispatch;
572     bool frame_sensortime_valid;
573 
574     // FIFO setting
575     uint16_t chunkReadSize;
576     uint8_t  watermark;
577 
578     // spi rw
579     struct SlabAllocator *mDataSlab;
580     uint16_t mWbufCnt;
581     uint8_t mRegCnt;
582 #ifdef BMI160_USE_I2C
583     uint8_t cReg;
584     SpiCbkF sCallback;
585 #endif
586 
587     uint8_t mRetryLeft;
588     bool spiInUse;
589 };
590 
591 static uint32_t AccRates[] = {
592     SENSOR_HZ(25.0f/8.0f),
593     SENSOR_HZ(25.0f/4.0f),
594     SENSOR_HZ(25.0f/2.0f),
595     SENSOR_HZ(25.0f),
596     SENSOR_HZ(50.0f),
597     SENSOR_HZ(100.0f),
598     SENSOR_HZ(200.0f),
599     SENSOR_HZ(400.0f),
600     0,
601 };
602 
603 static uint32_t GyrRates[] = {
604     SENSOR_HZ(25.0f/8.0f),
605     SENSOR_HZ(25.0f/4.0f),
606     SENSOR_HZ(25.0f/2.0f),
607     SENSOR_HZ(25.0f),
608     SENSOR_HZ(50.0f),
609     SENSOR_HZ(100.0f),
610     SENSOR_HZ(200.0f),
611     SENSOR_HZ(400.0f),
612     0,
613 };
614 
615 #ifdef MAG_SLAVE_PRESENT
616 static uint32_t MagRates[] = {
617     SENSOR_HZ(25.0f/8.0f),
618     SENSOR_HZ(25.0f/4.0f),
619     SENSOR_HZ(25.0f/2.0f),
620     SENSOR_HZ(25.0f),
621     SENSOR_HZ(50.0f),
622     SENSOR_HZ(100.0f),
623     0,
624 };
625 #endif
626 
627 static uint32_t StepCntRates[] = {
628     SENSOR_HZ(1.0f/300.0f),
629     SENSOR_HZ(1.0f/240.0f),
630     SENSOR_HZ(1.0f/180.0f),
631     SENSOR_HZ(1.0f/120.0f),
632     SENSOR_HZ(1.0f/90.0f),
633     SENSOR_HZ(1.0f/60.0f),
634     SENSOR_HZ(1.0f/45.0f),
635     SENSOR_HZ(1.0f/30.0f),
636     SENSOR_HZ(1.0f/15.0f),
637     SENSOR_HZ(1.0f/10.0f),
638     SENSOR_HZ(1.0f/5.0f),
639     SENSOR_RATE_ONCHANGE,
640     0
641 };
642 
643 static const uint64_t stepCntRateTimerVals[] = // should match StepCntRates and be the timer length for that rate in nanosecs
644 {
645     300 * 1000000000ULL,
646     240 * 1000000000ULL,
647     180 * 1000000000ULL,
648     120 * 1000000000ULL,
649     90 * 1000000000ULL,
650     60 * 1000000000ULL,
651     45 * 1000000000ULL,
652     30 * 1000000000ULL,
653     15 * 1000000000ULL,
654     10 * 1000000000ULL,
655     5 * 1000000000ULL,
656 };
657 
658 static struct BMI160Task mTask;
659 
660 #ifdef MAG_SLAVE_PRESENT
661 static struct MagTask magTask;
662 #endif
663 
664 #define MAG_WRITE(addr, data)                                   \
665     do {                                                        \
666         SPI_WRITE(BMI160_REG_MAG_IF_4, data);                   \
667         SPI_WRITE(BMI160_REG_MAG_IF_3, addr);                   \
668     } while (0)
669 
670 #define MAG_READ(addr, size)                                    \
671     do {                                                        \
672         SPI_WRITE(BMI160_REG_MAG_IF_2, addr, 5000);             \
673         SPI_READ(BMI160_REG_DATA_0, size, &mTask.dataBuffer);   \
674     } while (0)
675 
676 #define DEC_INFO(name, type, axis, inter, samples) \
677     .sensorName = name, \
678     .sensorType = type, \
679     .numAxis = axis, \
680     .interrupt = inter, \
681     .minSamples = samples
682 
683 #define DEC_INFO_RATE(name, rates, type, axis, inter, samples) \
684     DEC_INFO(name, type, axis, inter, samples), \
685     .supportedRates = rates
686 
687 #define DEC_INFO_RATE_RAW(name, rates, type, axis, inter, samples, raw, scale) \
688     DEC_INFO(name, type, axis, inter, samples), \
689     .supportedRates = rates, \
690     .flags1 = SENSOR_INFO_FLAGS1_RAW, \
691     .rawType = raw, \
692     .rawScale = scale
693 
694 #define DEC_INFO_RATE_BIAS(name, rates, type, axis, inter, samples, bias) \
695     DEC_INFO(name, type, axis, inter, samples), \
696     .supportedRates = rates, \
697     .flags1 = SENSOR_INFO_FLAGS1_BIAS, \
698     .biasType = bias
699 
700 #define DEC_INFO_RATE_RAW_BIAS(name, rates, type, axis, inter, samples, raw, scale, bias) \
701     DEC_INFO_RATE_RAW(name, rates, type, axis, inter, samples, raw, scale), \
702     .flags1 = SENSOR_INFO_FLAGS1_RAW | SENSOR_INFO_FLAGS1_BIAS, \
703     .biasType = bias
704 
705 typedef struct BMI160Task _Task;
706 #define TASK  _Task* const _task
707 
708 // To get rid of static variables all task functions should have a task structure pointer input.
709 // This is an intermediate step.
710 #define TDECL()  TASK = &mTask; (void)_task
711 
712 // Access task variables without explicitly specify the task structure pointer.
713 #define T(v)  (_task->v)
714 
715 // Atomic get state
716 #define GET_STATE() (atomicReadByte(&(_task->state)))
717 
718 // Atomic set state, this set the state to arbitrary value, use with caution
719 #define SET_STATE(s) do{\
720         DEBUG_PRINT_IF(DBG_STATE, "set state %" PRI_STATE "\n", getStateName(s));\
721         atomicWriteByte(&(_task->state), (s));\
722     }while(0)
723 
724 // Atomic switch state from IDLE to desired state.
725 static bool trySwitchState_(TASK, enum SensorState newState) {
726 #if DBG_STATE
727     bool ret = atomicCmpXchgByte(&T(state), SENSOR_IDLE, newState);
728     uint8_t prevState = ret ? SENSOR_IDLE : GET_STATE();
729     DEBUG_PRINT("switch state %" PRI_STATE "->%" PRI_STATE ", %s\n",
730             getStateName(prevState), getStateName(newState), ret ? "ok" : "failed");
731     return ret;
732 #else
733     return atomicCmpXchgByte(&T(state), SENSOR_IDLE, newState);
734 #endif
735 }
736 // Short-hand
737 #define trySwitchState(s) trySwitchState_(_task, (s))
738 
739 // Chunked FIFO read functions
740 static void chunkedReadInit_(TASK, int index, int size);
741 #define chunkedReadInit(a,b) chunkedReadInit_(_task, (a), (b))
742 static void chunkedReadSpiCallback(void *cookie, int error);
743 static void initiateFifoRead_(TASK, bool isInterruptContext);
744 #define initiateFifoRead(a) initiateFifoRead_(_task, (a))
745 static uint8_t* shallowParseFrame(uint8_t * buf, int size);
746 
747 #ifdef OVERTEMPCAL_ENABLED
748 // otc gyro cal save restore functions
749 static void handleOtcGyroConfig_(TASK, const struct AppToSensorHalDataPayload *data);
750 #define handleOtcGyroConfig(a) handleOtcGyroConfig_(_task, (a))
751 static bool sendOtcGyroUpdate_();
752 #define sendOtcGyroUpdate() sendOtcGyroUpdate_(_task)
753 static void unlockOtcGyroUpdateBuffer();
754 #endif  // OVERTEMPCAL_ENABLED
755 
756 // Binary dump to osLog
757 static void dumpBinary(void* buf, unsigned int address, size_t size);
758 
759 // Watermark calculation
760 static uint8_t calcWatermark2_(TASK);
761 #define calcWatermark2() calcWatermark2_(_task)
762 
763 static const struct SensorInfo mSensorInfo[NUM_OF_SENSOR] =
764 {
765 #ifdef ACCEL_CAL_ENABLED
766     { DEC_INFO_RATE_RAW_BIAS("Accelerometer", AccRates, SENS_TYPE_ACCEL, NUM_AXIS_THREE,
767             NANOHUB_INT_NONWAKEUP, BMI160_ACC_SAMPLES, SENS_TYPE_ACCEL_RAW,
768             1.0/kScale_acc, SENS_TYPE_ACCEL_BIAS) },
769 #else
770     { DEC_INFO_RATE_RAW("Accelerometer", AccRates, SENS_TYPE_ACCEL, NUM_AXIS_THREE,
771             NANOHUB_INT_NONWAKEUP, BMI160_ACC_SAMPLES, SENS_TYPE_ACCEL_RAW,
772             1.0/kScale_acc) },
773 #endif
774     { DEC_INFO_RATE_BIAS("Gyroscope", GyrRates, SENS_TYPE_GYRO, NUM_AXIS_THREE,
775             NANOHUB_INT_NONWAKEUP, BMI160_GYRO_SAMPLES, SENS_TYPE_GYRO_BIAS) },
776 #ifdef MAG_SLAVE_PRESENT
777     { DEC_INFO_RATE_RAW_BIAS("Magnetometer", MagRates, SENS_TYPE_MAG, NUM_AXIS_THREE,
778             NANOHUB_INT_NONWAKEUP, BMI160_MAG_SAMPLES, SENS_TYPE_MAG_RAW,
779             1.0/kScale_mag, SENS_TYPE_MAG_BIAS) },
780 #endif
781     { DEC_INFO("Step Detector", SENS_TYPE_STEP_DETECT, NUM_AXIS_EMBEDDED,
782             NANOHUB_INT_NONWAKEUP, 100) },
783     { DEC_INFO("Double Tap", SENS_TYPE_DOUBLE_TAP, NUM_AXIS_EMBEDDED,
784             NANOHUB_INT_NONWAKEUP, 20) },
785     { DEC_INFO("Flat", SENS_TYPE_FLAT, NUM_AXIS_EMBEDDED, NANOHUB_INT_NONWAKEUP, 20) },
786     { DEC_INFO("Any Motion", SENS_TYPE_ANY_MOTION, NUM_AXIS_EMBEDDED, NANOHUB_INT_NONWAKEUP, 20) },
787     { DEC_INFO("No Motion", SENS_TYPE_NO_MOTION, NUM_AXIS_EMBEDDED, NANOHUB_INT_NONWAKEUP, 20) },
788     { DEC_INFO_RATE("Step Counter", StepCntRates, SENS_TYPE_STEP_COUNT, NUM_AXIS_EMBEDDED,
789             NANOHUB_INT_NONWAKEUP, 20) },
790 };
791 
792 static void time_init(void) {
793     time_sync_init(&mTask.gSensorTime2RTC);
794 }
795 
796 static bool sensortime_to_rtc_time(uint64_t sensor_time, uint64_t *rtc_time_ns) {
797 // fixme: nsec?
798     return time_sync_estimate_time1(
799             &mTask.gSensorTime2RTC, sensor_time * 39ull, rtc_time_ns);
800 }
801 
802 static void map_sensortime_to_rtc_time(uint64_t sensor_time, uint64_t rtc_time_ns) {
803 // fixme: nsec?
804     time_sync_add(&mTask.gSensorTime2RTC, rtc_time_ns, sensor_time * 39ull);
805 }
806 
807 static void invalidate_sensortime_to_rtc_time(void) {
808     time_sync_reset(&mTask.gSensorTime2RTC);
809 }
810 
811 static void minimize_sensortime_history(void) {
812     // truncate datapoints to the latest two to maintain valid sensortime to rtc
813     // mapping and minimize the inflence of the past mapping
814     time_sync_truncate(&mTask.gSensorTime2RTC, 2);
815 
816     // drop the oldest datapoint when a new one arrives for two times to
817     // completely shift out the influence of the past mapping
818     time_sync_hold(&mTask.gSensorTime2RTC, 2);
819 }
820 
821 static void dataEvtFree(void *ptr)
822 {
823     TDECL();
824     struct TripleAxisDataEvent *ev = (struct TripleAxisDataEvent *)ptr;
825     slabAllocatorFree(T(mDataSlab), ev);
826 }
827 
828 static void spiQueueWrite(uint8_t addr, uint8_t data, uint32_t delay)
829 {
830     TDECL();
831     if (T(spiInUse)) {
832         ERROR_PRINT("SPI in use, cannot queue write\n");
833         return;
834     }
835     T(packets[T(mRegCnt)]).size = 2;
836     T(packets[T(mRegCnt)]).txBuf = &T(txrxBuffer[T(mWbufCnt)]);
837     T(packets[T(mRegCnt)]).rxBuf = &T(txrxBuffer[T(mWbufCnt)]);
838     T(packets[T(mRegCnt)]).delay = delay * 1000;
839     T(txrxBuffer[T(mWbufCnt++)]) = BMI160_SPI_WRITE | addr;
840     T(txrxBuffer[T(mWbufCnt++)]) = data;
841     T(mRegCnt)++;
842 }
843 
844 /*
845  * need to be sure size of buf is larger than read size
846  */
847 static void spiQueueRead(uint8_t addr, size_t size, uint8_t **buf, uint32_t delay)
848 {
849     TDECL();
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)++]) = BMI160_SPI_READ | addr;
861     T(mWbufCnt) += size;
862     T(mRegCnt)++;
863 }
864 
865 #ifdef BMI160_USE_I2C
866 static void i2cBatchTxRx(void *evtData, int err);
867 #endif
868 
869 static void spiBatchTxRx(struct SpiMode *mode,
870         SpiCbkF callback, void *cookie, const char * src)
871 {
872     TDECL();
873     if (T(mWbufCnt) > SPI_BUF_SIZE) {
874         ERROR_PRINT("NO enough SPI buffer space, dropping transaction.\n");
875         return;
876     }
877     if (T(mRegCnt) > SPI_PACKET_SIZE) {
878         ERROR_PRINT("spiBatchTxRx too many packets!\n");
879         return;
880     }
881 
882     T(spiInUse) = true;
883     T(mWbufCnt) = 0;
884 
885 #ifdef BMI160_USE_I2C
886     T(cReg) = 0;
887     T(sCallback) = callback;
888     i2cBatchTxRx(cookie, 0);
889 #else
890     // Reset variables before issuing SPI transaction.
891     // SPI may finish before spiMasterRxTx finish
892     uint8_t regCount = T(mRegCnt);
893     T(mRegCnt) = 0;
894 
895     if (spiMasterRxTx(T(spiDev), T(cs), T(packets), regCount, mode, callback, cookie) < 0) {
896         ERROR_PRINT("spiMasterRxTx failed!\n");
897     }
898 #endif
899 }
900 
901 
902 static bool bmi160Isr1(struct ChainedIsr *isr)
903 {
904     TASK = container_of(isr, struct BMI160Task, Isr1);
905 
906     if (!extiIsPendingGpio(T(Int1))) {
907         return false;
908     }
909     DEBUG_PRINT_IF(DBG_INT, "i1\n");
910     initiateFifoRead(true /*isInterruptContext*/);
911     extiClearPendingGpio(T(Int1));
912     return true;
913 }
914 
915 
916 static bool bmi160Isr2(struct ChainedIsr *isr)
917 {
918     TASK = container_of(isr, struct BMI160Task, Isr2);
919 
920     if (!extiIsPendingGpio(T(Int2)))
921         return false;
922 
923     DEBUG_PRINT_IF(DBG_INT, "i2\n");
924     if (!osEnqueuePrivateEvt(EVT_SENSOR_INTERRUPT_2, _task, NULL, T(tid)))
925         ERROR_PRINT("bmi160Isr2: osEnqueuePrivateEvt() failed\n");
926     extiClearPendingGpio(T(Int2));
927     return true;
928 }
929 
930 static void sensorSpiCallback(void *cookie, int err)
931 {
932     mTask.spiInUse = false;
933 
934     if (!osEnqueuePrivateEvt(EVT_SPI_DONE, cookie, NULL, mTask.tid))
935         ERROR_PRINT("sensorSpiCallback: osEnqueuePrivateEvt() failed\n");
936 }
937 
938 static void sensorTimerCallback(uint32_t timerId, void *data)
939 {
940     if (!osEnqueuePrivateEvt(EVT_SPI_DONE, data, NULL, mTask.tid))
941         ERROR_PRINT("sensorTimerCallback: osEnqueuePrivateEvt() failed\n")
942 }
943 
944 static void timeSyncCallback(uint32_t timerId, void *data)
945 {
946     if (!osEnqueuePrivateEvt(EVT_TIME_SYNC, data, NULL, mTask.tid))
947         ERROR_PRINT("timeSyncCallback: osEnqueuePrivateEvt() failed\n");
948 }
949 
950 static void stepCntSamplingCallback(uint32_t timerId, void *data)
951 {
952     union EmbeddedDataPoint step_cnt;
953 
954     if (mTask.sensors[STEPCNT].powered && mTask.step_cnt_changed) {
955         mTask.step_cnt_changed = false;
956         step_cnt.idata = mTask.total_step_cnt;
957         osEnqueueEvt(EVT_SENSOR_STEP_COUNTER, step_cnt.vptr, NULL);
958     }
959 }
960 
961 static bool accFirmwareUpload(void *cookie)
962 {
963     sensorSignalInternalEvt(mTask.sensors[ACC].handle,
964             SENSOR_INTERNAL_EVT_FW_STATE_CHG, 1, 0);
965     return true;
966 }
967 
968 static bool gyrFirmwareUpload(void *cookie)
969 {
970     sensorSignalInternalEvt(mTask.sensors[GYR].handle,
971             SENSOR_INTERNAL_EVT_FW_STATE_CHG, 1, 0);
972     return true;
973 }
974 
975 #ifdef MAG_SLAVE_PRESENT
976 static bool magFirmwareUpload(void *cookie)
977 {
978     sensorSignalInternalEvt(mTask.sensors[MAG].handle,
979             SENSOR_INTERNAL_EVT_FW_STATE_CHG, 1, 0);
980     return true;
981 }
982 #endif
983 
984 static bool stepFirmwareUpload(void *cookie)
985 {
986     sensorSignalInternalEvt(mTask.sensors[STEP].handle,
987             SENSOR_INTERNAL_EVT_FW_STATE_CHG, 1, 0);
988     return true;
989 }
990 
991 static bool doubleTapFirmwareUpload(void *cookie)
992 {
993     sensorSignalInternalEvt(mTask.sensors[DTAP].handle,
994             SENSOR_INTERNAL_EVT_FW_STATE_CHG, 1, 0);
995     return true;
996 }
997 
998 static bool noMotionFirmwareUpload(void *cookie)
999 {
1000     sensorSignalInternalEvt(mTask.sensors[NOMO].handle,
1001             SENSOR_INTERNAL_EVT_FW_STATE_CHG, 1, 0);
1002     return true;
1003 }
1004 
1005 static bool anyMotionFirmwareUpload(void *cookie)
1006 {
1007     sensorSignalInternalEvt(mTask.sensors[ANYMO].handle,
1008             SENSOR_INTERNAL_EVT_FW_STATE_CHG, 1, 0);
1009     return true;
1010 }
1011 
1012 static bool flatFirmwareUpload(void *cookie)
1013 {
1014     sensorSignalInternalEvt(mTask.sensors[FLAT].handle,
1015             SENSOR_INTERNAL_EVT_FW_STATE_CHG, 1, 0);
1016     return true;
1017 }
1018 
1019 static bool stepCntFirmwareUpload(void *cookie)
1020 {
1021     sensorSignalInternalEvt(mTask.sensors[STEPCNT].handle,
1022             SENSOR_INTERNAL_EVT_FW_STATE_CHG, 1, 0);
1023     return true;
1024 }
1025 
1026 static bool enableInterrupt(struct Gpio *pin, IRQn_Type irq, struct ChainedIsr *isr)
1027 {
1028     gpioConfigInput(pin, GPIO_SPEED_LOW, GPIO_PULL_NONE);
1029     syscfgSetExtiPort(pin);
1030     extiEnableIntGpio(pin, EXTI_TRIGGER_RISING);
1031     extiChainIsr(irq, isr);
1032     return true;
1033 }
1034 
1035 static bool disableInterrupt(struct Gpio *pin, IRQn_Type irq, struct ChainedIsr *isr)
1036 {
1037     extiUnchainIsr(irq, isr);
1038     extiDisableIntGpio(pin);
1039     return true;
1040 }
1041 
1042 static void magConfigMagic(void)
1043 {
1044     // set the MAG power to NORMAL mode
1045     SPI_WRITE(BMI160_REG_CMD, 0x19, 10000);
1046 
1047     // Magic register sequence to shift register page table to access hidden
1048     // register
1049     SPI_WRITE(BMI160_REG_CMD, 0x37);
1050     SPI_WRITE(BMI160_REG_CMD, 0x9a);
1051     SPI_WRITE(BMI160_REG_CMD, 0xc0);
1052     SPI_WRITE(BMI160_REG_MAGIC, 0x90);
1053     SPI_READ(BMI160_REG_DATA_1, 1, &mTask.dataBuffer);
1054 }
1055 
1056 static void magConfigIf(void)
1057 {
1058     // Set the on-chip I2C pull-up register settings and shift the register
1059     // table back down (magic)
1060     SPI_WRITE(BMI160_REG_DATA_1, mTask.dataBuffer[1] | 0x30);
1061     SPI_WRITE(BMI160_REG_MAGIC, 0x80);
1062 
1063     // Config the MAG I2C device address
1064 #ifdef MAG_SLAVE_PRESENT
1065     SPI_WRITE(BMI160_REG_MAG_IF_0, (MAG_I2C_ADDR << 1));
1066 #endif
1067 
1068     // set mag_manual_enable, mag_offset=0, mag_rd_burst='8 bytes'
1069     SPI_WRITE(BMI160_REG_MAG_IF_1, 0x83);
1070 
1071     // primary interface: autoconfig, secondary: magnetometer.
1072     SPI_WRITE(BMI160_REG_IF_CONF, 0x20);
1073 
1074     // fixme: move to mag-specific function
1075 #ifdef USE_BMM150
1076     // set mag to SLEEP mode
1077     MAG_WRITE(BMM150_REG_CTRL_1, 0x01);
1078 #elif USE_AK09915
1079     // Disable Noise Suppression Filter (NSF) settings
1080     MAG_WRITE(AKM_AK09915_REG_CNTL1, 0x00);
1081 #endif
1082 }
1083 
1084 // fixme: break this up to master/slave-specific, so it'll be eventually slave-agnostic,
1085 // and slave provides its own stateless config function
1086 // fixme: not all async_elem_t is supported
1087 static void magConfig(void)
1088 {
1089     switch (mTask.mag_state) {
1090     case MAG_SET_START:
1091         magConfigMagic();
1092         mTask.mag_state = MAG_SET_IF;
1093         break;
1094     case MAG_SET_IF:
1095         magConfigIf();
1096 #ifdef USE_AK09915
1097         mTask.mag_state = MAG_SET_FORCE;
1098 #elif USE_BMM150
1099         mTask.mag_state = MAG_SET_REPXY;
1100 #endif
1101         break;
1102 
1103 #ifdef USE_BMM150
1104     case MAG_SET_REPXY:
1105         // MAG_SET_REPXY and MAG_SET_REPZ case set:
1106         // regular preset, f_max,ODR ~ 102 Hz
1107         MAG_WRITE(BMM150_REG_REPXY, 9);
1108         mTask.mag_state = MAG_SET_REPZ;
1109         break;
1110     case MAG_SET_REPZ:
1111         MAG_WRITE(BMM150_REG_REPZ, 15);
1112         mTask.mag_state = MAG_GET_DIG_X;
1113         break;
1114     case MAG_GET_DIG_X:
1115         // MAG_GET_DIG_X, MAG_GET_DIG_Y and MAG_GET_DIG_Z cases:
1116         // save parameters for temperature compensation.
1117         MAG_READ(BMM150_REG_DIG_X1, 8);
1118         mTask.mag_state = MAG_GET_DIG_Y;
1119         break;
1120     case MAG_GET_DIG_Y:
1121         bmm150SaveDigData(&magTask, &mTask.dataBuffer[1], 0);
1122         MAG_READ(BMM150_REG_DIG_X1 + 8, 8);
1123         mTask.mag_state = MAG_GET_DIG_Z;
1124         break;
1125     case MAG_GET_DIG_Z:
1126         bmm150SaveDigData(&magTask, &mTask.dataBuffer[1], 8);
1127         MAG_READ(BMM150_REG_DIG_X1 + 16, 8);
1128         mTask.mag_state = MAG_SET_SAVE_DIG;
1129         break;
1130     case MAG_SET_SAVE_DIG:
1131         bmm150SaveDigData(&magTask, &mTask.dataBuffer[1], 16);
1132         // fall through, no break;
1133         mTask.mag_state = MAG_SET_FORCE;
1134 #endif
1135 
1136     case MAG_SET_FORCE:
1137         // set MAG mode to "forced". ready to pull data
1138 #ifdef USE_AK09915
1139         MAG_WRITE(AKM_AK09915_REG_CNTL2, 0x01);
1140 #elif USE_BMM150
1141         MAG_WRITE(BMM150_REG_CTRL_2, 0x02);
1142 #endif
1143         mTask.mag_state = MAG_SET_ADDR;
1144         break;
1145     case MAG_SET_ADDR:
1146         // config MAG read data address to the first data register
1147 #ifdef MAG_SLAVE_PRESENT
1148         SPI_WRITE(BMI160_REG_MAG_IF_2, MAG_REG_DATA);
1149 #endif
1150         mTask.mag_state = MAG_SET_DATA;
1151         break;
1152     case MAG_SET_DATA:
1153         // clear mag_manual_en.
1154         SPI_WRITE(BMI160_REG_MAG_IF_1, 0x03, 1000);
1155         // set the MAG power to SUSPEND mode
1156         SPI_WRITE(BMI160_REG_CMD, 0x18, 10000);
1157         mTask.mag_state = MAG_SET_DONE;
1158         mTask.init_state = INIT_ON_CHANGE_SENSORS;
1159         break;
1160     default:
1161         break;
1162     }
1163     SPI_READ(BMI160_REG_STATUS, 1, &mTask.statusBuffer, 1000);
1164 }
1165 
1166 static bool flushData(struct BMI160Sensor *sensor, uint32_t eventId)
1167 {
1168     bool success = false;
1169 
1170     if (sensor->data_evt) {
1171         success = osEnqueueEvtOrFree(eventId, sensor->data_evt, dataEvtFree);
1172         sensor->data_evt = NULL;
1173     }
1174 
1175     return success;
1176 }
1177 
1178 static void flushAllData(void)
1179 {
1180     int i;
1181     for (i = FIRST_CONT_SENSOR; i < NUM_CONT_SENSOR; i++) {
1182         flushData(&mTask.sensors[i],
1183                 EVENT_TYPE_BIT_DISCARDABLE | sensorGetMyEventType(mSensorInfo[i].sensorType));
1184     }
1185 }
1186 
1187 static bool allocateDataEvt(struct BMI160Sensor *mSensor, uint64_t rtc_time)
1188 {
1189     TDECL();
1190     mSensor->data_evt = slabAllocatorAlloc(T(mDataSlab));
1191     if (mSensor->data_evt == NULL) {
1192         // slab allocation failed
1193         ERROR_PRINT("slabAllocatorAlloc() failed\n");
1194         return false;
1195     }
1196 
1197     // delta time for the first sample is sample count
1198     memset(&mSensor->data_evt->samples[0].firstSample, 0x00, sizeof(struct SensorFirstSample));
1199     mSensor->data_evt->referenceTime = rtc_time;
1200     mSensor->prev_rtc_time = rtc_time;
1201 
1202     return true;
1203 }
1204 
1205 static inline bool anyFifoEnabled(void)
1206 {
1207     bool anyFifoEnabled = mTask.fifo_enabled[ACC] || mTask.fifo_enabled[GYR];
1208 #ifdef MAG_SLAVE_PRESENT
1209     anyFifoEnabled = anyFifoEnabled || mTask.fifo_enabled[MAG];
1210 #endif
1211     return anyFifoEnabled;
1212 }
1213 
1214 static void configFifo(void)
1215 {
1216     TDECL();
1217     int i;
1218     uint8_t val = 0x12;
1219     bool any_fifo_enabled_prev = anyFifoEnabled();
1220 
1221     // if ACC is configed, enable ACC bit in fifo_config reg.
1222     if (mTask.sensors[ACC].configed && mTask.sensors[ACC].latency != SENSOR_LATENCY_NODATA) {
1223         val |= 0x40;
1224         mTask.fifo_enabled[ACC] = true;
1225     } else {
1226         mTask.fifo_enabled[ACC] = false;
1227     }
1228 
1229     // if GYR is configed, enable GYR bit in fifo_config reg.
1230     if (mTask.sensors[GYR].configed && mTask.sensors[GYR].latency != SENSOR_LATENCY_NODATA) {
1231         val |= 0x80;
1232         mTask.fifo_enabled[GYR] = true;
1233     } else {
1234         mTask.fifo_enabled[GYR] = false;
1235     }
1236 
1237 #ifdef MAG_SLAVE_PRESENT
1238     // if MAG is configed, enable MAG bit in fifo_config reg.
1239     if (mTask.sensors[MAG].configed && mTask.sensors[MAG].latency != SENSOR_LATENCY_NODATA) {
1240         val |= 0x20;
1241         mTask.fifo_enabled[MAG] = true;
1242     } else {
1243         mTask.fifo_enabled[MAG] = false;
1244     }
1245 #endif
1246 
1247     // if this is the first data sensor fifo to enable, start to
1248     // sync the sensor time and rtc time
1249     if (!any_fifo_enabled_prev && anyFifoEnabled()) {
1250         invalidate_sensortime_to_rtc_time();
1251 
1252         // start a new poll generation and attach the generation number to event
1253         if (!osEnqueuePrivateEvt(EVT_TIME_SYNC, (void *)mTask.poll_generation, NULL, mTask.tid))
1254             ERROR_PRINT("configFifo: osEnqueuePrivateEvt() failed\n");
1255     }
1256 
1257     // cancel current poll generation
1258     if (any_fifo_enabled_prev && !anyFifoEnabled()) {
1259         ++mTask.poll_generation;
1260     }
1261 
1262     // if this is not the first fifo enabled or last fifo disabled, flush all fifo data;
1263     if (any_fifo_enabled_prev && anyFifoEnabled()) {
1264         mTask.pending_dispatch = true;
1265         mTask.xferCnt = FIFO_READ_SIZE;
1266         SPI_READ(BMI160_REG_FIFO_DATA, mTask.xferCnt, &mTask.dataBuffer);
1267     }
1268 
1269     // calculate the new watermark level
1270     if (anyFifoEnabled()) {
1271         mTask.watermark = calcWatermark2_(_task);
1272         DEBUG_PRINT("wm=%d", mTask.watermark);
1273         SPI_WRITE(BMI160_REG_FIFO_CONFIG_0, mTask.watermark);
1274     }
1275 
1276     // config the fifo register
1277     SPI_WRITE(BMI160_REG_FIFO_CONFIG_1, val);
1278 
1279     // if no more fifo enabled, we need to cleanup the fifo and invalidate time
1280     if (!anyFifoEnabled()) {
1281         SPI_WRITE(BMI160_REG_CMD, 0xb0);
1282         mTask.frame_sensortime_valid = false;
1283         for (i = FIRST_CONT_SENSOR; i < NUM_CONT_SENSOR; i++) {
1284             mTask.pending_delta[i] = false;
1285             mTask.prev_frame_time[i] = ULONG_LONG_MAX;
1286         }
1287     }
1288 }
1289 
1290 static bool accPower(bool on, void *cookie)
1291 {
1292     TDECL();
1293 
1294     VERBOSE_PRINT("accPower: on=%d, state=%" PRI_STATE "\n", on, getStateName(GET_STATE()));
1295     if (trySwitchState(on ? SENSOR_POWERING_UP : SENSOR_POWERING_DOWN)) {
1296         if (on) {
1297             // set ACC power mode to NORMAL
1298             SPI_WRITE(BMI160_REG_CMD, 0x11, 50000);
1299         } else {
1300             // set ACC power mode to SUSPEND
1301             mTask.sensors[ACC].configed = false;
1302             configFifo();
1303             SPI_WRITE(BMI160_REG_CMD, 0x10, 5000);
1304         }
1305         mTask.sensors[ACC].powered = on;
1306         spiBatchTxRx(&mTask.mode, sensorSpiCallback, &mTask.sensors[ACC], __FUNCTION__);
1307     } else {
1308         mTask.pending_config[ACC] = true;
1309         mTask.sensors[ACC].pConfig.enable = on;
1310     }
1311     return true;
1312 }
1313 
1314 static bool gyrPower(bool on, void *cookie)
1315 {
1316     TDECL();
1317     VERBOSE_PRINT("gyrPower: on=%d, state=%" PRI_STATE "\n", on, getStateName(GET_STATE()));
1318 
1319     if (trySwitchState(on ? SENSOR_POWERING_UP : SENSOR_POWERING_DOWN)) {
1320         if (on) {
1321             // set GYR power mode to NORMAL
1322             SPI_WRITE(BMI160_REG_CMD, 0x15, 50000);
1323         } else {
1324             // set GYR power mode to SUSPEND
1325             mTask.sensors[GYR].configed = false;
1326             configFifo();
1327             SPI_WRITE(BMI160_REG_CMD, 0x14, 5000);
1328         }
1329 
1330         if (anyFifoEnabled() && on != mTask.sensors[GYR].powered) {
1331 #if TIMESTAMP_DBG
1332             DEBUG_PRINT("minimize_sensortime_history()\n");
1333 #endif
1334             minimize_sensortime_history();
1335         }
1336 
1337         mTask.sensors[GYR].powered = on;
1338         spiBatchTxRx(&mTask.mode, sensorSpiCallback, &mTask.sensors[GYR], __FUNCTION__);
1339     } else {
1340         mTask.pending_config[GYR] = true;
1341         mTask.sensors[GYR].pConfig.enable = on;
1342     }
1343     return true;
1344 }
1345 
1346 #ifdef MAG_SLAVE_PRESENT
1347 static bool magPower(bool on, void *cookie)
1348 {
1349     TDECL();
1350     VERBOSE_PRINT("magPower: on=%d, state=%" PRI_STATE "\n", on, getStateName(GET_STATE()));
1351     if (trySwitchState(on ? SENSOR_POWERING_UP : SENSOR_POWERING_DOWN)) {
1352         if (on) {
1353             // set MAG power mode to NORMAL
1354             SPI_WRITE(BMI160_REG_CMD, 0x19, 10000);
1355         } else {
1356             // set MAG power mode to SUSPEND
1357             mTask.sensors[MAG].configed = false;
1358             configFifo();
1359             SPI_WRITE(BMI160_REG_CMD, 0x18, 5000);
1360         }
1361         mTask.sensors[MAG].powered = on;
1362         spiBatchTxRx(&mTask.mode, sensorSpiCallback, &mTask.sensors[MAG], __FUNCTION__);
1363     } else {
1364         mTask.pending_config[MAG] = true;
1365         mTask.sensors[MAG].pConfig.enable = on;
1366     }
1367     return true;
1368 }
1369 #endif
1370 
1371 static bool stepPower(bool on, void *cookie)
1372 {
1373     TDECL();
1374     if (trySwitchState(on ? SENSOR_POWERING_UP : SENSOR_POWERING_DOWN)) {
1375         // if step counter is powered, no need to change actual config of step
1376         // detector.
1377         // But we choose to perform one SPI_WRITE anyway to go down the code path
1378         // to state SENSOR_POWERING_UP/DOWN to update sensor manager.
1379         if (on) {
1380             mTask.interrupt_enable_2 |= 0x08;
1381         } else {
1382             if (!mTask.sensors[STEPCNT].powered)
1383                 mTask.interrupt_enable_2 &= ~0x08;
1384             mTask.sensors[STEP].configed = false;
1385         }
1386         mTask.sensors[STEP].powered = on;
1387         SPI_WRITE(BMI160_REG_INT_EN_2, mTask.interrupt_enable_2, 450);
1388         spiBatchTxRx(&mTask.mode, sensorSpiCallback, &mTask.sensors[STEP], __FUNCTION__);
1389     } else {
1390         mTask.pending_config[STEP] = true;
1391         mTask.sensors[STEP].pConfig.enable = on;
1392     }
1393     return true;
1394 }
1395 
1396 static bool flatPower(bool on, void *cookie)
1397 {
1398     TDECL();
1399     if (trySwitchState(on ? SENSOR_POWERING_UP : SENSOR_POWERING_DOWN)) {
1400         if (on) {
1401             mTask.interrupt_enable_0 |= 0x80;
1402         } else {
1403             mTask.interrupt_enable_0 &= ~0x80;
1404             mTask.sensors[FLAT].configed = false;
1405         }
1406         mTask.sensors[FLAT].powered = on;
1407         SPI_WRITE(BMI160_REG_INT_EN_0, mTask.interrupt_enable_0, 450);
1408         spiBatchTxRx(&mTask.mode, sensorSpiCallback, &mTask.sensors[FLAT], __FUNCTION__);
1409     } else {
1410         mTask.pending_config[FLAT] = true;
1411         mTask.sensors[FLAT].pConfig.enable = on;
1412     }
1413     return true;
1414 }
1415 
1416 static bool doubleTapPower(bool on, void *cookie)
1417 {
1418     TDECL();
1419     if (trySwitchState(on ? SENSOR_POWERING_UP : SENSOR_POWERING_DOWN)) {
1420         if (on) {
1421             mTask.interrupt_enable_0 |= 0x10;
1422         } else {
1423             mTask.interrupt_enable_0 &= ~0x10;
1424             mTask.sensors[DTAP].configed = false;
1425         }
1426         mTask.sensors[DTAP].powered = on;
1427         SPI_WRITE(BMI160_REG_INT_EN_0, mTask.interrupt_enable_0, 450);
1428         spiBatchTxRx(&mTask.mode, sensorSpiCallback, &mTask.sensors[DTAP], __FUNCTION__);
1429     } else {
1430         mTask.pending_config[DTAP] = true;
1431         mTask.sensors[DTAP].pConfig.enable = on;
1432     }
1433     return true;
1434 }
1435 
1436 static bool anyMotionPower(bool on, void *cookie)
1437 {
1438     TDECL();
1439     DEBUG_PRINT("anyMotionPower: on=%d, oneshot_cnt %d, state=%" PRI_STATE "\n",
1440             on, mTask.active_oneshot_sensor_cnt, getStateName(GET_STATE()));
1441 
1442     if (trySwitchState(on ? SENSOR_POWERING_UP : SENSOR_POWERING_DOWN)) {
1443         if (on) {
1444             mTask.interrupt_enable_0 |= 0x07;
1445         } else {
1446             mTask.interrupt_enable_0 &= ~0x07;
1447             mTask.sensors[ANYMO].configed = false;
1448         }
1449         mTask.sensors[ANYMO].powered = on;
1450         SPI_WRITE(BMI160_REG_INT_EN_0, mTask.interrupt_enable_0, 450);
1451         spiBatchTxRx(&mTask.mode, sensorSpiCallback, &mTask.sensors[ANYMO], __FUNCTION__);
1452     } else {
1453         mTask.pending_config[ANYMO] = true;
1454         mTask.sensors[ANYMO].pConfig.enable = on;
1455     }
1456     return true;
1457 }
1458 
1459 static bool noMotionPower(bool on, void *cookie)
1460 {
1461     TDECL();
1462     DEBUG_PRINT("noMotionPower: on=%d, oneshot_cnt %d, state=%" PRI_STATE "\n",
1463             on, mTask.active_oneshot_sensor_cnt, getStateName(GET_STATE()));
1464     if (trySwitchState(on ? SENSOR_POWERING_UP : SENSOR_POWERING_DOWN)) {
1465         if (on) {
1466             mTask.interrupt_enable_2 |= 0x07;
1467         } else {
1468             mTask.interrupt_enable_2 &= ~0x07;
1469             mTask.sensors[NOMO].configed = false;
1470         }
1471         mTask.sensors[NOMO].powered = on;
1472         SPI_WRITE(BMI160_REG_INT_EN_2, mTask.interrupt_enable_2, 450);
1473         spiBatchTxRx(&mTask.mode, sensorSpiCallback, &mTask.sensors[NOMO], __FUNCTION__);
1474     } else {
1475         mTask.pending_config[NOMO] = true;
1476         mTask.sensors[NOMO].pConfig.enable = on;
1477     }
1478     return true;
1479 }
1480 
1481 static bool stepCntPower(bool on, void *cookie)
1482 {
1483     TDECL();
1484     if (trySwitchState(on ? SENSOR_POWERING_UP : SENSOR_POWERING_DOWN)) {
1485         if (on) {
1486             if (!mTask.sensors[STEP].powered) {
1487                 mTask.interrupt_enable_2 |= 0x08;
1488                 SPI_WRITE(BMI160_REG_INT_EN_2, mTask.interrupt_enable_2, 450);
1489             }
1490             // set step_cnt_en bit
1491             SPI_WRITE(BMI160_REG_STEP_CONF_1, 0x08 | 0x03, 1000);
1492         } else {
1493             if (mTask.stepCntSamplingTimerHandle) {
1494                 timTimerCancel(mTask.stepCntSamplingTimerHandle);
1495                 mTask.stepCntSamplingTimerHandle = 0;
1496             }
1497             if (!mTask.sensors[STEP].powered) {
1498                 mTask.interrupt_enable_2 &= ~0x08;
1499                 SPI_WRITE(BMI160_REG_INT_EN_2, mTask.interrupt_enable_2);
1500             }
1501             // unset step_cnt_en bit
1502             SPI_WRITE(BMI160_REG_STEP_CONF_1, 0x03);
1503             mTask.last_step_cnt = 0;
1504             mTask.sensors[STEPCNT].configed = false;
1505         }
1506         mTask.sensors[STEPCNT].powered = on;
1507         spiBatchTxRx(&mTask.mode, sensorSpiCallback, &mTask.sensors[STEPCNT], __FUNCTION__);
1508     } else {
1509         mTask.pending_config[STEPCNT] = true;
1510         mTask.sensors[STEPCNT].pConfig.enable = on;
1511     }
1512     return true;
1513 }
1514 
1515 static void updateTimeDelta(uint8_t idx, uint8_t odr)
1516 {
1517     if (mTask.fifo_enabled[idx]) {
1518         // wait till control frame to update, if not disabled
1519         mTask.next_delta[idx] = 1ull << (16 - odr);
1520         mTask.pending_delta[idx] = true;
1521     } else {
1522         mTask.time_delta[idx] = 1ull << (16 - odr);
1523     }
1524 }
1525 
1526 // compute the register value from sensor rate.
1527 static uint8_t computeOdr(uint32_t rate)
1528 {
1529     uint8_t odr = 0x00;
1530     switch (rate) {
1531     // fall through intended to get the correct register value
1532     case SENSOR_HZ(3200): odr ++;
1533     case SENSOR_HZ(1600): odr ++;
1534     case SENSOR_HZ(800): odr ++;
1535     case SENSOR_HZ(400): odr ++;
1536     case SENSOR_HZ(200): odr ++;
1537     case SENSOR_HZ(100): odr ++;
1538     case SENSOR_HZ(50): odr ++;
1539     case SENSOR_HZ(25): odr ++;
1540     case SENSOR_HZ(25.0f/2.0f): odr ++;
1541     case SENSOR_HZ(25.0f/4.0f): odr ++;
1542     case SENSOR_HZ(25.0f/8.0f): odr ++;
1543     case SENSOR_HZ(25.0f/16.0f): odr ++;
1544     case SENSOR_HZ(25.0f/32.0f): odr ++;
1545     default:
1546         return odr;
1547     }
1548 }
1549 
1550 static void configMotion(uint8_t odr) {
1551 #if BMI160_ACC_RANGE_G == 16
1552     // motion threshold is element * 31.25mg (for 16g range)
1553     static const uint8_t motion_thresholds[ACC_MAX_RATE+1] =
1554         {3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1, 1, 1};
1555 #elif BMI160_ACC_RANGE_G == 8
1556     // motion threshold is element * 15.63mg (for 8g range)
1557     static const uint8_t motion_thresholds[ACC_MAX_RATE+1] =
1558         {5, 5, 5, 5, 5, 5, 5, 5, 4, 3, 2, 2, 2};
1559 #endif
1560 
1561     // set any_motion duration to 1 point
1562     // set no_motion duration to (3+1)*1.28sec=5.12sec
1563     SPI_WRITE(BMI160_REG_INT_MOTION_0, 0x03 << 2, 450);
1564 
1565     // set any_motion threshold
1566     SPI_WRITE(BMI160_REG_INT_MOTION_1, motion_thresholds[odr], 450);
1567 
1568     // set no_motion threshold
1569     SPI_WRITE(BMI160_REG_INT_MOTION_2, motion_thresholds[odr], 450);
1570 }
1571 
1572 static bool accSetRate(uint32_t rate, uint64_t latency, void *cookie)
1573 {
1574     TDECL();
1575     int odr, osr = 0;
1576     int osr_mode = 2; // normal
1577 
1578     // change this to DEBUG_PRINT as there will be frequent (un)subscribings
1579     // to accel with different rate/latency requirements.
1580     DEBUG_PRINT("accSetRate: rate=%ld, latency=%lld, state=%" PRI_STATE "\n",
1581                 rate, latency, getStateName(GET_STATE()));
1582 
1583     if (trySwitchState(SENSOR_CONFIG_CHANGING)) {
1584         odr = computeOdr(rate);
1585         if (!odr) {
1586             ERROR_PRINT("invalid acc rate\n");
1587             return false;
1588         }
1589 
1590         updateTimeDelta(ACC, odr);
1591 
1592         // minimum supported rate for ACCEL is 12.5Hz.
1593         // Anything lower than that shall be acheived by downsampling.
1594         if (odr < ACC_MIN_RATE) {
1595             osr = ACC_MIN_RATE - odr;
1596             odr = ACC_MIN_RATE;
1597         }
1598 
1599         // for high odrs, oversample to reduce hw latency and downsample
1600         // to get desired odr
1601         if (odr > ODR_100HZ) {
1602             // 200Hz osr4, >= 400Hz osr2
1603             if (odr == ODR_200HZ) {
1604                 osr_mode = 0; // OSR4
1605             } else {
1606                 osr_mode = 1; // OSR2
1607             }
1608             osr = (ACC_MAX_OSR + odr) > ACC_MAX_RATE ? (ACC_MAX_RATE - odr) : ACC_MAX_OSR;
1609             odr += osr;
1610         }
1611 
1612         mTask.sensors[ACC].rate = rate;
1613         mTask.sensors[ACC].latency = latency;
1614         mTask.sensors[ACC].configed = true;
1615         mTask.acc_downsample = osr;
1616 
1617         // configure ANY_MOTION and NO_MOTION based on odr
1618         configMotion(odr);
1619 
1620         // set ACC bandwidth parameter to 2 (bits[4:6])
1621         // set the rate (bits[0:3])
1622         SPI_WRITE(BMI160_REG_ACC_CONF, (osr_mode << 4) | odr);
1623 
1624         // configure down sampling ratio, 0x88 is to specify we are using
1625         // filtered samples
1626         SPI_WRITE(BMI160_REG_FIFO_DOWNS, (mTask.acc_downsample << 4) | mTask.gyr_downsample | 0x88);
1627 
1628         // flush the data and configure the fifo
1629         configFifo();
1630 
1631         spiBatchTxRx(&mTask.mode, sensorSpiCallback, &mTask.sensors[ACC], __FUNCTION__);
1632     } else {
1633         mTask.pending_config[ACC] = true;
1634         mTask.sensors[ACC].pConfig.enable = 1;
1635         mTask.sensors[ACC].pConfig.rate = rate;
1636         mTask.sensors[ACC].pConfig.latency = latency;
1637     }
1638     return true;
1639 }
1640 
1641 static bool gyrSetRate(uint32_t rate, uint64_t latency, void *cookie)
1642 {
1643     TDECL();
1644     int odr, osr = 0;
1645     int osr_mode = 2; // normal
1646     VERBOSE_PRINT("gyrSetRate: rate=%ld, latency=%lld, state=%" PRI_STATE "\n",
1647                rate, latency, getStateName(GET_STATE()));
1648 
1649     if (trySwitchState(SENSOR_CONFIG_CHANGING)) {
1650         odr = computeOdr(rate);
1651         if (!odr) {
1652             ERROR_PRINT("invalid gyr rate\n");
1653             return false;
1654         }
1655 
1656         updateTimeDelta(GYR, odr);
1657 
1658         // minimum supported rate for GYRO is 25.0Hz.
1659         // Anything lower than that shall be acheived by downsampling.
1660         if (odr < GYR_MIN_RATE) {
1661             osr = GYR_MIN_RATE - odr;
1662             odr = GYR_MIN_RATE;
1663         }
1664 
1665         // for high odrs, oversample to reduce hw latency and downsample
1666         // to get desired odr
1667         if (odr > ODR_100HZ) {
1668             // 200Hz osr4, >= 400Hz osr2
1669             if (odr == ODR_200HZ) {
1670                 osr_mode = 0; // OSR4
1671             } else {
1672                 osr_mode = 1; // OSR2
1673             }
1674             osr = (GYR_MAX_OSR + odr) > GYR_MAX_RATE ? (GYR_MAX_RATE - odr) : GYR_MAX_OSR;
1675             odr += osr;
1676         }
1677 
1678         mTask.sensors[GYR].rate = rate;
1679         mTask.sensors[GYR].latency = latency;
1680         mTask.sensors[GYR].configed = true;
1681         mTask.gyr_downsample = osr;
1682 
1683         // set GYR bandwidth parameter to 2 (bits[4:6])
1684         // set the rate (bits[0:3])
1685         SPI_WRITE(BMI160_REG_GYR_CONF, (osr_mode << 4) | odr);
1686 
1687         // configure down sampling ratio, 0x88 is to specify we are using
1688         // filtered samples
1689         SPI_WRITE(BMI160_REG_FIFO_DOWNS, (mTask.acc_downsample << 4) | mTask.gyr_downsample | 0x88);
1690 
1691         // flush the data and configure the fifo
1692         configFifo();
1693 
1694         spiBatchTxRx(&mTask.mode, sensorSpiCallback, &mTask.sensors[GYR], __FUNCTION__);
1695     } else {
1696         mTask.pending_config[GYR] = true;
1697         mTask.sensors[GYR].pConfig.enable = 1;
1698         mTask.sensors[GYR].pConfig.rate = rate;
1699         mTask.sensors[GYR].pConfig.latency = latency;
1700     }
1701     return true;
1702 }
1703 
1704 #ifdef MAG_SLAVE_PRESENT
1705 static bool magSetRate(uint32_t rate, uint64_t latency, void *cookie)
1706 {
1707     TDECL();
1708     int odr;
1709 
1710     if (rate == SENSOR_RATE_ONCHANGE)
1711         rate = SENSOR_HZ(100);
1712 
1713     VERBOSE_PRINT("magSetRate: rate=%ld, latency=%lld, state=%" PRI_STATE "\n",
1714                rate, latency, getStateName(GET_STATE()));
1715 
1716     if (trySwitchState(SENSOR_CONFIG_CHANGING)) {
1717         mTask.sensors[MAG].rate = rate;
1718         mTask.sensors[MAG].latency = latency;
1719         mTask.sensors[MAG].configed = true;
1720 
1721         odr = computeOdr(rate);
1722         if (!odr) {
1723             ERROR_PRINT("invalid mag rate\n");
1724             return false;
1725         }
1726 
1727         updateTimeDelta(MAG, odr);
1728 
1729         odr = odr > MAG_MAX_RATE ? MAG_MAX_RATE : odr;
1730 
1731         // set the rate for MAG
1732         SPI_WRITE(BMI160_REG_MAG_CONF, odr);
1733 
1734         // flush the data and configure the fifo
1735         configFifo();
1736 
1737         spiBatchTxRx(&mTask.mode, sensorSpiCallback, &mTask.sensors[MAG], __FUNCTION__);
1738     } else {
1739         mTask.pending_config[MAG] = true;
1740         mTask.sensors[MAG].pConfig.enable = 1;
1741         mTask.sensors[MAG].pConfig.rate = rate;
1742         mTask.sensors[MAG].pConfig.latency = latency;
1743     }
1744     return true;
1745 }
1746 #endif
1747 
1748 static bool stepSetRate(uint32_t rate, uint64_t latency, void *cookie)
1749 {
1750     mTask.sensors[STEP].rate = rate;
1751     mTask.sensors[STEP].latency = latency;
1752     mTask.sensors[STEP].configed = true;
1753 
1754     sensorSignalInternalEvt(mTask.sensors[STEP].handle,
1755             SENSOR_INTERNAL_EVT_RATE_CHG, rate, latency);
1756     return true;
1757 }
1758 
1759 static bool flatSetRate(uint32_t rate, uint64_t latency, void *cookie)
1760 {
1761     mTask.sensors[FLAT].rate = rate;
1762     mTask.sensors[FLAT].latency = latency;
1763     mTask.sensors[FLAT].configed = true;
1764 
1765     sensorSignalInternalEvt(mTask.sensors[FLAT].handle,
1766             SENSOR_INTERNAL_EVT_RATE_CHG, rate, latency);
1767     return true;
1768 }
1769 
1770 static bool doubleTapSetRate(uint32_t rate, uint64_t latency, void *cookie)
1771 {
1772     mTask.sensors[DTAP].rate = rate;
1773     mTask.sensors[DTAP].latency = latency;
1774     mTask.sensors[DTAP].configed = true;
1775 
1776     sensorSignalInternalEvt(mTask.sensors[DTAP].handle,
1777             SENSOR_INTERNAL_EVT_RATE_CHG, rate, latency);
1778     return true;
1779 }
1780 
1781 static bool anyMotionSetRate(uint32_t rate, uint64_t latency, void *cookie)
1782 {
1783     mTask.sensors[ANYMO].rate = rate;
1784     mTask.sensors[ANYMO].latency = latency;
1785     mTask.sensors[ANYMO].configed = true;
1786 
1787     sensorSignalInternalEvt(mTask.sensors[ANYMO].handle,
1788             SENSOR_INTERNAL_EVT_RATE_CHG, rate, latency);
1789 
1790     return true;
1791 }
1792 
1793 static bool noMotionSetRate(uint32_t rate, uint64_t latency, void *cookie)
1794 {
1795     mTask.sensors[NOMO].rate = rate;
1796     mTask.sensors[NOMO].latency = latency;
1797     mTask.sensors[NOMO].configed = true;
1798 
1799     sensorSignalInternalEvt(mTask.sensors[NOMO].handle,
1800             SENSOR_INTERNAL_EVT_RATE_CHG, rate, latency);
1801     return true;
1802 }
1803 
1804 static bool stepCntSetRate(uint32_t rate, uint64_t latency, void *cookie)
1805 {
1806     mTask.sensors[STEPCNT].rate = rate;
1807     mTask.sensors[STEPCNT].latency = latency;
1808     mTask.sensors[STEPCNT].configed = true;
1809 
1810     if (rate == SENSOR_RATE_ONCHANGE && mTask.stepCntSamplingTimerHandle) {
1811         timTimerCancel(mTask.stepCntSamplingTimerHandle);
1812         mTask.stepCntSamplingTimerHandle = 0;
1813     } else if (rate != SENSOR_RATE_ONCHANGE) {
1814         if (mTask.stepCntSamplingTimerHandle) {
1815             timTimerCancel(mTask.stepCntSamplingTimerHandle);
1816         }
1817         mTask.stepCntSamplingTimerHandle = timTimerSet(sensorTimerLookupCommon(StepCntRates, stepCntRateTimerVals, rate),
1818                                                        0, 50, stepCntSamplingCallback, NULL, false);
1819         if (!mTask.stepCntSamplingTimerHandle)
1820             ERROR_PRINT("Couldn't get a timer for step counter\n");
1821 
1822     }
1823 
1824     sensorSignalInternalEvt(mTask.sensors[STEPCNT].handle,
1825             SENSOR_INTERNAL_EVT_RATE_CHG, rate, latency);
1826     return true;
1827 }
1828 
1829 static void sendFlushEvt(void)
1830 {
1831     while (mTask.sensors[ACC].flush > 0) {
1832         osEnqueueEvt(EVT_SENSOR_ACC_DATA_RDY, SENSOR_DATA_EVENT_FLUSH, NULL);
1833         mTask.sensors[ACC].flush--;
1834     }
1835     while (mTask.sensors[GYR].flush > 0) {
1836         osEnqueueEvt(EVT_SENSOR_GYR_DATA_RDY, SENSOR_DATA_EVENT_FLUSH, NULL);
1837         mTask.sensors[GYR].flush--;
1838     }
1839 #ifdef MAG_SLAVE_PRESENT
1840     while (mTask.sensors[MAG].flush > 0) {
1841         osEnqueueEvt(EVT_SENSOR_MAG_DATA_RDY, SENSOR_DATA_EVENT_FLUSH, NULL);
1842         mTask.sensors[MAG].flush--;
1843     }
1844 #endif
1845 }
1846 
1847 static bool accFlush(void *cookie)
1848 {
1849     TDECL();
1850     mTask.sensors[ACC].flush++;
1851     initiateFifoRead(false /*isInterruptContext*/);
1852     return true;
1853 }
1854 
1855 static bool gyrFlush(void *cookie)
1856 {
1857     TDECL();
1858     mTask.sensors[GYR].flush++;
1859     initiateFifoRead(false /*isInterruptContext*/);
1860     return true;
1861 }
1862 
1863 #ifdef MAG_SLAVE_PRESENT
1864 static bool magFlush(void *cookie)
1865 {
1866     TDECL();
1867     mTask.sensors[MAG].flush++;
1868     initiateFifoRead(false /*isInterruptContext*/);
1869     return true;
1870 }
1871 #endif
1872 
1873 static bool stepFlush(void *cookie)
1874 {
1875     return osEnqueueEvt(EVT_SENSOR_STEP, SENSOR_DATA_EVENT_FLUSH, NULL);
1876 }
1877 
1878 static bool flatFlush(void *cookie)
1879 {
1880     return osEnqueueEvt(EVT_SENSOR_FLAT, SENSOR_DATA_EVENT_FLUSH, NULL);
1881 }
1882 
1883 static bool doubleTapFlush(void *cookie)
1884 {
1885     return osEnqueueEvt(EVT_SENSOR_DOUBLE_TAP, SENSOR_DATA_EVENT_FLUSH, NULL);
1886 }
1887 
1888 static bool anyMotionFlush(void *cookie)
1889 {
1890     return osEnqueueEvt(EVT_SENSOR_ANY_MOTION, SENSOR_DATA_EVENT_FLUSH, NULL);
1891 }
1892 
1893 static bool noMotionFlush(void *cookie)
1894 {
1895     return osEnqueueEvt(EVT_SENSOR_NO_MOTION, SENSOR_DATA_EVENT_FLUSH, NULL);
1896 }
1897 
1898 static bool stepCntFlushGetData()
1899 {
1900     TDECL();
1901     if (trySwitchState(SENSOR_STEP_CNT)) {
1902         SPI_READ(BMI160_REG_STEP_CNT_0, 2, &mTask.dataBuffer);
1903         spiBatchTxRx(&mTask.mode, sensorSpiCallback, &mTask.sensors[STEPCNT], __FUNCTION__);
1904         return true;
1905     }
1906     return false;
1907 }
1908 
1909 static bool stepCntFlush(void *cookie)
1910 {
1911     mTask.sensors[STEPCNT].flush++;
1912     stepCntFlushGetData();
1913     return true;
1914 }
1915 
1916 static void sendStepCnt()
1917 {
1918     union EmbeddedDataPoint step_cnt;
1919     uint32_t cur_step_cnt;
1920     cur_step_cnt = (int)(mTask.dataBuffer[1] | (mTask.dataBuffer[2] << 8));
1921 
1922     if (cur_step_cnt != mTask.last_step_cnt) {
1923         // Check for possible overflow
1924         if (cur_step_cnt < mTask.last_step_cnt) {
1925             mTask.total_step_cnt += cur_step_cnt + (0xFFFF - mTask.last_step_cnt);
1926         } else {
1927             mTask.total_step_cnt += (cur_step_cnt - mTask.last_step_cnt);
1928         }
1929         mTask.last_step_cnt = cur_step_cnt;
1930 
1931         // Send the event if the current rate is ONCHANGE or we need to flush;
1932         // otherwise, wait until step count sampling timer expires
1933         if (mTask.sensors[STEPCNT].rate == SENSOR_RATE_ONCHANGE || mTask.sensors[STEPCNT].flush) {
1934             step_cnt.idata = mTask.total_step_cnt;
1935             osEnqueueEvt(EVT_SENSOR_STEP_COUNTER, step_cnt.vptr, NULL);
1936         } else {
1937             mTask.step_cnt_changed = true;
1938         }
1939     }
1940 
1941     while (mTask.sensors[STEPCNT].flush) {
1942         osEnqueueEvt(EVT_SENSOR_STEP_COUNTER, SENSOR_DATA_EVENT_FLUSH, NULL);
1943         mTask.sensors[STEPCNT].flush--;
1944     }
1945 }
1946 
1947 static bool stepCntSendLastData(void *cookie, uint32_t tid)
1948 {
1949     // If this comes in and we don't have data yet, there's no harm in reporting step_cnt = 0
1950     if (!osEnqueuePrivateEvt(EVT_SENSOR_STEP_COUNTER, (void *) mTask.total_step_cnt, NULL, tid)) {
1951         ERROR_PRINT("stepCntSendLastData: osEnqueuePrivateEvt() failed\n");
1952         return false;
1953     }
1954 
1955     return true;
1956 }
1957 
1958 static uint64_t parseSensortime(uint32_t sensor_time24)
1959 {
1960     uint32_t prev_time24;
1961     uint32_t kHalf = 1ul << 23;
1962     uint64_t full;
1963 
1964     prev_time24 = (uint32_t)mTask.last_sensortime & 0xffffff;
1965 
1966     if (mTask.last_sensortime == 0) {
1967         mTask.last_sensortime = (uint64_t)sensor_time24;
1968         return (uint64_t)(sensor_time24);
1969     }
1970 
1971     if (sensor_time24 == prev_time24) {
1972         return (uint64_t)(mTask.last_sensortime);
1973     }
1974 
1975     full = (mTask.last_sensortime & ~0xffffffull) | sensor_time24;
1976 
1977     if (((prev_time24 < sensor_time24) && (sensor_time24 - prev_time24) < kHalf)
1978             || ((prev_time24 > sensor_time24) && (prev_time24 - sensor_time24) > kHalf)) {
1979         if (full < mTask.last_sensortime) {
1980             full += 0x1000000ull;
1981         }
1982         mTask.last_sensortime = full;
1983         return mTask.last_sensortime;
1984     }
1985 
1986     if (full < mTask.last_sensortime) {
1987         return full;
1988     }
1989 
1990     return (full -  0x1000000ull);
1991 }
1992 
1993 static void parseRawData(struct BMI160Sensor *mSensor, uint8_t *buf, float kScale, uint64_t sensorTime)
1994 {
1995     TDECL();
1996     struct TripleAxisDataPoint *sample;
1997     uint64_t rtc_time, cur_time;
1998     uint32_t delta_time;
1999     float x, y, z;
2000     int16_t raw_x, raw_y, raw_z;
2001 #ifdef MAG_SLAVE_PRESENT
2002     bool newMagBias = false;
2003 #endif
2004 
2005     if (!sensortime_to_rtc_time(sensorTime, &rtc_time)) {
2006         return;
2007     }
2008 
2009     cur_time = sensorGetTime();
2010     if (rtc_time > cur_time + kMinRTCTimeIncrementNs) { // + tolerance to prevent frequent tripping
2011         INFO_PRINT("Future ts %s: rtc_time = %llu, cur_time = %llu",
2012                 mSensorInfo[mSensor->idx].sensorName, rtc_time, cur_time);
2013         // clamp to current time
2014         rtc_time = cur_time + kMinRTCTimeIncrementNs;
2015     }
2016 
2017     if (rtc_time < mSensor->prev_rtc_time + kMinRTCTimeIncrementNs) {
2018 #if TIMESTAMP_DBG
2019         DEBUG_PRINT("%s prev rtc 0x%08x %08x, curr 0x%08x %08x, delta %d usec\n",
2020                 mSensorInfo[mSensor->idx].sensorName,
2021                 (unsigned int)((mSensor->prev_rtc_time >> 32) & 0xffffffff),
2022                 (unsigned int)(mSensor->prev_rtc_time & 0xffffffff),
2023                 (unsigned int)((rtc_time >> 32) & 0xffffffff),
2024                 (unsigned int)(rtc_time & 0xffffffff),
2025                 (int)(rtc_time - mSensor->prev_rtc_time) / 1000);
2026 #endif
2027         rtc_time = mSensor->prev_rtc_time + kMinRTCTimeIncrementNs;
2028     }
2029 
2030 #ifdef MAG_SLAVE_PRESENT
2031     if (mSensor->idx == MAG) {
2032         parseMagData(&magTask, &buf[0], &x, &y, &z);
2033         BMM150_TO_ANDROID_COORDINATE(x, y, z);
2034 
2035         float xi, yi, zi;
2036         magCalRemoveSoftiron(&mTask.moc, x, y, z, &xi, &yi, &zi);
2037 
2038         newMagBias |= magCalUpdate(&mTask.moc, sensorTime * kSensorTimerIntervalUs, xi, yi, zi);
2039 
2040         magCalRemoveBias(&mTask.moc, xi, yi, zi, &x, &y, &z);
2041 
2042 #ifdef GYRO_CAL_ENABLED
2043         // Gyro Cal -- Add magnetometer sample.
2044         gyroCalUpdateMag(&mTask.gyro_cal,
2045                          rtc_time,  // nsec
2046                          x, y, z);
2047 #endif  // GYRO_CAL_ENABLED
2048     } else
2049 #endif  // MAG_SLAVE_PRESENT
2050     {
2051         raw_x = (buf[0] | buf[1] << 8);
2052         raw_y = (buf[2] | buf[3] << 8);
2053         raw_z = (buf[4] | buf[5] << 8);
2054 
2055         x = (float)raw_x * kScale;
2056         y = (float)raw_y * kScale;
2057         z = (float)raw_z * kScale;
2058 
2059         BMI160_TO_ANDROID_COORDINATE(x, y, z);
2060 
2061         if (mSensor->idx == ACC) {
2062 
2063 #ifdef ACCEL_CAL_ENABLED
2064           accelCalRun(&mTask.acc, rtc_time,
2065                       x, y, z, mTask.tempCelsius);
2066 
2067           accelCalBiasRemove(&mTask.acc, &x, &y, &z);
2068 
2069 #ifdef ACCEL_CAL_DBG_ENABLED
2070           // Prints debug data report.
2071           accelCalDebPrint(&mTask.acc, mTask.tempCelsius);
2072 #endif  // ACCEL_CAL_DBG_ENABLED
2073 #endif  // ACCEL_CAL_ENABLED
2074 
2075 #ifdef GYRO_CAL_ENABLED
2076           // Gyro Cal -- Add accelerometer sample.
2077           gyroCalUpdateAccel(&mTask.gyro_cal,
2078                              rtc_time,  // nsec
2079                              x, y, z);
2080 #endif  // GYRO_CAL_ENABLED
2081         } else if (mSensor->idx == GYR) {
2082 #ifdef GYRO_CAL_ENABLED
2083           // Gyro Cal -- Add gyroscope and temperature sample.
2084           gyroCalUpdateGyro(&mTask.gyro_cal,
2085                             rtc_time,  // nsec
2086                             x, y, z, mTask.tempCelsius);
2087 
2088 #ifdef OVERTEMPCAL_ENABLED
2089           // Over-Temp Gyro Cal -- Update measured temperature.
2090           overTempCalSetTemperature(&mTask.over_temp_gyro_cal, rtc_time,
2091                                     mTask.tempCelsius);
2092 
2093           // Over-Temp Gyro Cal -- Apply over-temp calibration correction.
2094           overTempCalRemoveOffset(&mTask.over_temp_gyro_cal, rtc_time,
2095                                   x, y, z,    /* input values */
2096                                   &x, &y, &z  /* calibrated output */);
2097 #else  // OVERTEMPCAL_ENABLED
2098           // Gyro Cal -- Apply calibration correction.
2099           gyroCalRemoveBias(&mTask.gyro_cal,
2100                             x, y, z,    /* input values */
2101                             &x, &y, &z  /* calibrated output */);
2102 #endif  // OVERTEMPCAL_ENABLED
2103 
2104 #if defined(GYRO_CAL_DBG_ENABLED) || defined(OVERTEMPCAL_DBG_ENABLED)
2105           // This flag keeps GyroCal and OverTempCal from printing back-to-back.
2106           // If they do, then sometimes important print log data gets dropped.
2107           static size_t print_flag = 0;
2108 
2109           if (print_flag > 0) {
2110 #ifdef GYRO_CAL_DBG_ENABLED
2111             // Gyro Cal -- Read out Debug data.
2112             gyroCalDebugPrint(&mTask.gyro_cal, rtc_time);
2113 #endif  // GYRO_CAL_DBG_ENABLED
2114             print_flag = 0;
2115           } else {
2116 #ifdef OVERTEMPCAL_ENABLED
2117 #ifdef OVERTEMPCAL_DBG_ENABLED
2118             // Over-Temp Gyro Cal -- Read out Debug data.
2119             overTempCalDebugPrint(&mTask.over_temp_gyro_cal, rtc_time);
2120 #endif  // OVERTEMPCAL_DBG_ENABLED
2121 #endif  // OVERTEMPCAL_ENABLED
2122             print_flag = 1;
2123           }
2124 #endif  // GYRO_CAL_DBG_ENABLED || OVERTEMPCAL_DBG_ENABLED
2125 #endif  // GYRO_CAL_ENABLED
2126         }
2127     }
2128 
2129     if (mSensor->data_evt == NULL) {
2130         if (!allocateDataEvt(mSensor, rtc_time)) {
2131             return;
2132         }
2133     }
2134 
2135     if (mSensor->data_evt->samples[0].firstSample.numSamples >= MAX_NUM_COMMS_EVENT_SAMPLES) {
2136         ERROR_PRINT("BAD INDEX\n");
2137         return;
2138     }
2139 
2140 #ifdef ACCEL_CAL_ENABLED
2141     // https://source.android.com/devices/sensors/sensor-types.html
2142     // "The bias and scale calibration must only be updated while the sensor is deactivated,
2143     // so as to avoid causing jumps in values during streaming." Note, this is now regulated
2144     // by the SensorHAL.
2145     if (mSensor->idx == ACC) {
2146         float accel_offset[3] = {0.0f, 0.0f, 0.0f};
2147         bool accelCalNewBiasAvailable = accelCalUpdateBias(
2148             &mTask.acc, &accel_offset[0], &accel_offset[1], &accel_offset[2]);
2149         if (accelCalNewBiasAvailable) {
2150             if (mSensor->data_evt->samples[0].firstSample.numSamples > 0) {
2151                 // Flushes existing samples so the bias appears after them.
2152                 flushData(mSensor,
2153                           EVENT_TYPE_BIT_DISCARDABLE |
2154                           sensorGetMyEventType(mSensorInfo[ACC].sensorType));
2155 
2156                 // Tries to allocate another data event and breaks if unsuccessful.
2157                 if (!allocateDataEvt(mSensor, rtc_time)) {
2158                     return;
2159                 }
2160             }
2161             mSensor->data_evt->samples[0].firstSample.biasCurrent = true;
2162             mSensor->data_evt->samples[0].firstSample.biasPresent = 1;
2163             mSensor->data_evt->samples[0].firstSample.biasSample =
2164                 mSensor->data_evt->samples[0].firstSample.numSamples;
2165             sample = &mSensor->data_evt->
2166                 samples[mSensor->data_evt->samples[0].firstSample.numSamples++];
2167 
2168             // Updates the accel offset in HAL.
2169             sample->x = accel_offset[0];
2170             sample->y = accel_offset[1];
2171             sample->z = accel_offset[2];
2172 
2173             flushData(mSensor, sensorGetMyEventType(mSensorInfo[ACC].biasType));
2174             if (!allocateDataEvt(mSensor, rtc_time)) {
2175                 return;
2176             }
2177         }
2178     }
2179 #endif  // ACCEL_CAL_ENABLED
2180 
2181 #ifdef MAG_SLAVE_PRESENT
2182     if (mSensor->idx == MAG && (newMagBias || !mTask.magBiasPosted)) {
2183         if (mSensor->data_evt->samples[0].firstSample.numSamples > 0) {
2184             // flush existing samples so the bias appears after them
2185             flushData(mSensor,
2186                       EVENT_TYPE_BIT_DISCARDABLE |
2187                       sensorGetMyEventType(mSensorInfo[MAG].sensorType));
2188             if (!allocateDataEvt(mSensor, rtc_time)) {
2189                 return;
2190             }
2191         }
2192         if (newMagBias) {
2193             mTask.magBiasCurrent = true;
2194         }
2195         mSensor->data_evt->samples[0].firstSample.biasCurrent = mTask.magBiasCurrent;
2196         mSensor->data_evt->samples[0].firstSample.biasPresent = 1;
2197         mSensor->data_evt->samples[0].firstSample.biasSample =
2198                 mSensor->data_evt->samples[0].firstSample.numSamples;
2199         sample = &mSensor->data_evt->
2200             samples[mSensor->data_evt->samples[0].firstSample.numSamples++];
2201 
2202         // Updates the mag offset in HAL.
2203         magCalGetBias(&mTask.moc, &sample->x, &sample->y, &sample->z);
2204 
2205         // Bias is non-discardable, if we fail to enqueue, don't clear magBiasPosted.
2206         if (flushData(mSensor, sensorGetMyEventType(mSensorInfo[MAG].biasType))) {
2207             mTask.magBiasPosted = true;
2208         }
2209 
2210         if (!allocateDataEvt(mSensor, rtc_time)) {
2211             return;
2212         }
2213     }
2214 #endif  // MAG_SLAVE_PRESENT
2215 
2216 #ifdef GYRO_CAL_ENABLED
2217     if (mSensor->idx == GYR) {
2218       // GyroCal -- Checks for a new offset estimate update.
2219       float gyro_offset[3] = {0.0f, 0.0f, 0.0f};
2220       float gyro_offset_temperature_celsius = 0.0f;
2221       uint64_t calibration_time_nanos = 0;
2222       bool new_gyrocal_offset_update = gyroCalNewBiasAvailable(&mTask.gyro_cal);
2223       if (new_gyrocal_offset_update) {
2224         // GyroCal -- Gets the GyroCal offset estimate.
2225         gyroCalGetBias(&mTask.gyro_cal, &gyro_offset[0], &gyro_offset[1],
2226                        &gyro_offset[2], &gyro_offset_temperature_celsius,
2227                        &calibration_time_nanos);
2228 
2229 #ifdef OVERTEMPCAL_ENABLED
2230         // OTC-Gyro Cal -- Sends a new GyroCal estimate to the OTC-Gyro.
2231         overTempCalUpdateSensorEstimate(&mTask.over_temp_gyro_cal, rtc_time,
2232                                         gyro_offset,
2233                                         gyro_offset_temperature_celsius);
2234 #endif  // OVERTEMPCAL_ENABLED
2235       }
2236 
2237 #ifdef OVERTEMPCAL_ENABLED
2238       // OTC-Gyro Cal --  Gets the latest OTC-Gyro temperature compensated
2239       // offset estimate.
2240       bool new_otc_offset_update =
2241           overTempCalNewOffsetAvailable(&mTask.over_temp_gyro_cal);
2242       overTempCalGetOffset(&mTask.over_temp_gyro_cal,
2243                            &gyro_offset_temperature_celsius, gyro_offset);
2244 
2245       // OTC-Gyro Cal --  Checks for a model update.
2246       bool new_otc_model_update =
2247           overTempCalNewModelUpdateAvailable(&mTask.over_temp_gyro_cal);
2248 
2249       if (new_otc_offset_update) {
2250 #else   // OVERTEMPCAL_ENABLED
2251       if (new_gyrocal_offset_update) {
2252 #endif  // OVERTEMPCAL_ENABLED
2253         if (mSensor->data_evt->samples[0].firstSample.numSamples > 0) {
2254           // flush existing samples so the bias appears after them.
2255           flushData(mSensor,
2256                     EVENT_TYPE_BIT_DISCARDABLE |
2257                         sensorGetMyEventType(mSensorInfo[GYR].sensorType));
2258           if (!allocateDataEvt(mSensor, rtc_time)) {
2259             return;
2260           }
2261         }
2262         mSensor->data_evt->samples[0].firstSample.biasCurrent = true;
2263         mSensor->data_evt->samples[0].firstSample.biasPresent = 1;
2264         mSensor->data_evt->samples[0].firstSample.biasSample =
2265             mSensor->data_evt->samples[0].firstSample.numSamples;
2266         sample = &mSensor->data_evt->samples[mSensor->data_evt->samples[0]
2267                                                  .firstSample.numSamples++];
2268         // Updates the gyro offset in HAL.
2269         sample->x = gyro_offset[0];
2270         sample->y = gyro_offset[1];
2271         sample->z = gyro_offset[2];
2272 
2273         flushData(mSensor, sensorGetMyEventType(mSensorInfo[GYR].biasType));
2274         if (!allocateDataEvt(mSensor, rtc_time)) {
2275           return;
2276         }
2277       }
2278 #ifdef OVERTEMPCAL_ENABLED
2279       if (new_otc_model_update || new_otc_offset_update) {
2280         // Notify HAL to store new gyro OTC-Gyro data.
2281         T(otcGyroUpdateBuffer).sendToHostRequest = true;
2282       }
2283 #endif  // OVERTEMPCAL_ENABLED
2284     }
2285 #endif  // GYRO_CAL_ENABLED
2286 
2287     sample = &mSensor->data_evt->samples[mSensor->data_evt->samples[0].firstSample.numSamples++];
2288 
2289     // the first deltatime is for sample size
2290     if (mSensor->data_evt->samples[0].firstSample.numSamples > 1) {
2291         delta_time = rtc_time - mSensor->prev_rtc_time;
2292         delta_time = delta_time < 0 ? 0 : delta_time;
2293         sample->deltaTime = delta_time;
2294         mSensor->prev_rtc_time = rtc_time;
2295     }
2296 
2297     sample->x = x;
2298     sample->y = y;
2299     sample->z = z;
2300 
2301     //DEBUG_PRINT("bmi160: x: %d, y: %d, z: %d\n", (int)(1000*x), (int)(1000*y), (int)(1000*z));
2302 
2303     //TODO: This was added to prevent too much data of the same type accumulate in internal buffer.
2304     //      It might no longer be necessary and can be removed.
2305     if (mSensor->data_evt->samples[0].firstSample.numSamples == MAX_NUM_COMMS_EVENT_SAMPLES) {
2306         flushAllData();
2307     }
2308 }
2309 
2310 static void dispatchData(void)
2311 {
2312     size_t i = 1, j;
2313     size_t size = mTask.xferCnt;
2314     int fh_mode, fh_param;
2315     uint8_t *buf = mTask.dataBuffer;
2316 
2317     uint64_t min_delta = ULONG_LONG_MAX;
2318     uint32_t sensor_time24;
2319     uint64_t full_sensor_time;
2320     uint64_t frame_sensor_time = mTask.frame_sensortime;
2321     bool observed[NUM_CONT_SENSOR];
2322     uint64_t tmp_frame_time, tmp_time[NUM_CONT_SENSOR];
2323     bool frame_sensor_time_valid = mTask.frame_sensortime_valid;
2324     bool saved_pending_delta[NUM_CONT_SENSOR];
2325     uint64_t saved_time_delta[NUM_CONT_SENSOR];
2326 #if TIMESTAMP_DBG
2327     int frame_num = -1;
2328 #endif
2329 
2330     for (j = FIRST_CONT_SENSOR; j < NUM_CONT_SENSOR; j++)
2331         observed[j] = false;
2332 
2333     if (!mTask.frame_sensortime_valid) {
2334         // This is the first FIFO delivery after any sensor is enabled in
2335         // bmi160. Sensor time reference is not establised until end of this
2336         // FIFO frame. Assume time start from zero and do a dry run to estimate
2337         // the time and then go through this FIFO again.
2338         frame_sensor_time = 0ull;
2339 
2340         // Save these states for future recovery by the end of dry run.
2341         for (j = FIRST_CONT_SENSOR; j < NUM_CONT_SENSOR; j++) {
2342             saved_pending_delta[j] = mTask.pending_delta[j];
2343             saved_time_delta[j] = mTask.time_delta[j];
2344         }
2345     }
2346 
2347     while (size > 0) {
2348         if (buf[i] == BMI160_FRAME_HEADER_INVALID) {
2349             // reaching invalid header means no more data
2350             break;
2351         } else if (buf[i] == BMI160_FRAME_HEADER_SKIP) {
2352             // manually injected skip header
2353             DEBUG_PRINT_IF(DBG_CHUNKED, "skip nop header");
2354             i++;
2355             size--;
2356             continue;
2357         }
2358 
2359         fh_mode = buf[i] >> 6;
2360         fh_param = (buf[i] >> 2) & 0xf;
2361 
2362         i++;
2363         size--;
2364 #if TIMESTAMP_DBG
2365         ++frame_num;
2366 #endif
2367 
2368         if (fh_mode == 1) {
2369             // control frame.
2370             if (fh_param == 0) {
2371                 // skip frame, we skip it
2372                 if (size >= 1) {
2373                     i++;
2374                     size--;
2375                 } else {
2376                     size = 0;
2377                 }
2378             } else if (fh_param == 1) {
2379                 // sensortime frame
2380                 if (size >= 3) {
2381                     // The active sensor with the highest odr/lowest delta is the one that
2382                     // determines the sensor time increments.
2383                     for (j = FIRST_CONT_SENSOR; j < NUM_CONT_SENSOR; j++) {
2384                         if (mTask.sensors[j].configed &&
2385                                 mTask.sensors[j].latency != SENSOR_LATENCY_NODATA) {
2386                             min_delta = min_delta < mTask.time_delta[j] ? min_delta :
2387                                     mTask.time_delta[j];
2388                         }
2389                     }
2390                     sensor_time24 = buf[i + 2] << 16 | buf[i + 1] << 8 | buf[i];
2391 
2392                     // clear lower bits that measure time from taking the sample to reading the
2393                     // FIFO, something we're not interested in.
2394                     sensor_time24 &= ~(min_delta - 1);
2395 
2396                     full_sensor_time = parseSensortime(sensor_time24);
2397 
2398 #if TIMESTAMP_DBG
2399                     if (frame_sensor_time == full_sensor_time) {
2400                         //DEBUG_PRINT("frame %d FrameTime 0x%08x\n",
2401                         //        frame_num - 1,
2402                         //        (unsigned int)frame_sensor_time);
2403                     } else if (frame_sensor_time_valid) {
2404                         DEBUG_PRINT("frame %d FrameTime 0x%08x != SensorTime 0x%08x, jumped %d msec\n",
2405                                 frame_num - 1,
2406                                 (unsigned int)frame_sensor_time,
2407                                 (unsigned int)full_sensor_time,
2408                                 (int)(5 * ((int64_t)(full_sensor_time - frame_sensor_time) >> 7)));
2409                     }
2410 #endif
2411 
2412 
2413                     if (frame_sensor_time_valid) {
2414                         mTask.frame_sensortime = full_sensor_time;
2415                     } else {
2416                         // Dry run if frame_sensortime_valid == false,
2417                         // no sample is added this round.
2418                         // So let's time travel back to beginning of frame.
2419                         mTask.frame_sensortime_valid = true;
2420                         mTask.frame_sensortime = full_sensor_time - frame_sensor_time;
2421 
2422                         // recover states
2423                         for (j = FIRST_CONT_SENSOR; j < NUM_CONT_SENSOR; j++) {
2424                             // reset all prev_frame_time to invalid values
2425                             // they should be so anyway at the first FIFO
2426                             mTask.prev_frame_time[j] = ULONG_LONG_MAX;
2427 
2428                             // recover saved time_delta and pending_delta values
2429                             mTask.pending_delta[j] = saved_pending_delta[j];
2430                             mTask.time_delta[j] = saved_time_delta[j];
2431                         }
2432 
2433                         DEBUG_PRINT_IF(TIMESTAMP_DBG,
2434                                 "sensortime invalid: full, frame, task = %llu, %llu, %llu\n",
2435                                 full_sensor_time,
2436                                 frame_sensor_time,
2437                                 mTask.frame_sensortime);
2438 
2439                         // Parse again with known valid timing.
2440                         // This time the sensor events will be committed into event buffer.
2441                         return dispatchData();
2442                     }
2443 
2444                     // Invalidate sensor timestamp that didn't get corrected by full_sensor_time,
2445                     // so it can't be used as a reference at next FIFO read.
2446                     // Use (ULONG_LONG_MAX - 1) to indicate this.
2447                     for (j = FIRST_CONT_SENSOR; j < NUM_CONT_SENSOR; j++) {
2448                         mTask.prev_frame_time[j] = observed[j] ? full_sensor_time : (ULONG_LONG_MAX - 1);
2449 
2450                         // sensor can be disabled in the middle of the FIFO, but wait till the FIFO
2451                         // end to invalidate prev_frame_time since it's still needed for parsing.
2452                         // Also invalidate pending delta just to be safe.
2453                         if (!mTask.sensors[j].configed ||
2454                                 mTask.sensors[j].latency == SENSOR_LATENCY_NODATA) {
2455                             mTask.prev_frame_time[j] = ULONG_LONG_MAX;
2456                             mTask.pending_delta[j] = false;
2457                         }
2458                     }
2459                     i += 3;
2460                     size -= 3;
2461                 } else {
2462                     size = 0;
2463                 }
2464             } else if (fh_param == 2) {
2465                 // fifo_input config frame
2466 #if TIMESTAMP_DBG
2467                 DEBUG_PRINT("frame %d config change 0x%02x\n", frame_num, buf[i]);
2468 #endif
2469                 if (size >= 1) {
2470                     for (j = FIRST_CONT_SENSOR; j < NUM_CONT_SENSOR; j++) {
2471                         if (buf[i] & (0x01 << (j << 1)) && mTask.pending_delta[j]) {
2472                             mTask.pending_delta[j] = false;
2473                             mTask.time_delta[j] = mTask.next_delta[j];
2474 #if TIMESTAMP_DBG
2475                             DEBUG_PRINT("%s new delta %u\n", mSensorInfo[j].sensorName,
2476                                     (unsigned int)mTask.time_delta[j]);
2477 #endif
2478                         }
2479                     }
2480                     i++;
2481                     size--;
2482                 } else {
2483                     size = 0;
2484                 }
2485             } else {
2486                 size = 0; // drop this batch
2487                 ERROR_PRINT("Invalid fh_param in control frame\n");
2488             }
2489         } else if (fh_mode == 2) {
2490             // Calcutate candidate frame time (tmp_frame_time):
2491             // 1) When sensor is first enabled, reference from other sensors if possible.
2492             // Otherwise, add the smallest increment to the previous data frame time.
2493             // 2) The newly enabled sensor could only underestimate its
2494             // frame time without reference from other sensors.
2495             // 3) The underestimated frame time of a newly enabled sensor will be corrected
2496             // as soon as it shows up in the same frame with another sensor.
2497             // 4) (prev_frame_time == ULONG_LONG_MAX) means the sensor wasn't enabled.
2498             // 5) (prev_frame_time == ULONG_LONG_MAX -1) means the sensor didn't appear in the last
2499             // data frame of the previous fifo read.  So it won't be used as a frame time reference.
2500 
2501             tmp_frame_time = 0;
2502             for (j = FIRST_CONT_SENSOR; j < NUM_CONT_SENSOR; j++) {
2503                 observed[j] = false; // reset at each data frame
2504                 tmp_time[j] = 0;
2505                 if ((mTask.prev_frame_time[j] < ULONG_LONG_MAX - 1) && (fh_param & (1 << j))) {
2506                     tmp_time[j] = mTask.prev_frame_time[j] + mTask.time_delta[j];
2507                     tmp_frame_time = (tmp_time[j] > tmp_frame_time) ? tmp_time[j] : tmp_frame_time;
2508                 }
2509             }
2510             tmp_frame_time = (frame_sensor_time + kMinSensorTimeIncrement > tmp_frame_time)
2511                 ? (frame_sensor_time + kMinSensorTimeIncrement) : tmp_frame_time;
2512 
2513             // regular frame, dispatch data to each sensor's own fifo
2514 #ifdef MAG_SLAVE_PRESENT
2515             if (fh_param & 4) { // have mag data
2516                 if (size >= 8) {
2517                     if (frame_sensor_time_valid) {
2518                         // scale not used
2519                         parseRawData(&mTask.sensors[MAG], &buf[i], 0, tmp_frame_time);
2520 #if TIMESTAMP_DBG
2521                         if (mTask.prev_frame_time[MAG] == ULONG_LONG_MAX) {
2522                             DEBUG_PRINT("mag enabled: frame %d time 0x%08x\n",
2523                                     frame_num, (unsigned int)tmp_frame_time);
2524                         } else if ((tmp_frame_time != tmp_time[MAG]) && (tmp_time[MAG] != 0)) {
2525                             DEBUG_PRINT("frame %d mag time: 0x%08x -> 0x%08x, jumped %d msec\n",
2526                                     frame_num,
2527                                     (unsigned int)tmp_time[MAG],
2528                                     (unsigned int)tmp_frame_time,
2529                                     (int)(5 * ((int64_t)(tmp_frame_time - tmp_time[MAG]) >> 7)));
2530                         }
2531 #endif
2532                     }
2533                     mTask.prev_frame_time[MAG] = tmp_frame_time;
2534                     i += 8;
2535                     size -= 8;
2536                     observed[MAG] = true;
2537                 } else {
2538                     size = 0;
2539                 }
2540             }
2541 #endif
2542             if (fh_param & 2) { // have gyro data
2543                 if (size >= 6) {
2544                     if (frame_sensor_time_valid) {
2545                         parseRawData(&mTask.sensors[GYR], &buf[i], kScale_gyr, tmp_frame_time);
2546 #if TIMESTAMP_DBG
2547                         if (mTask.prev_frame_time[GYR] == ULONG_LONG_MAX) {
2548                             DEBUG_PRINT("gyr enabled: frame %d time 0x%08x\n",
2549                                     frame_num, (unsigned int)tmp_frame_time);
2550                         } else if ((tmp_frame_time != tmp_time[GYR]) && (tmp_time[GYR] != 0)) {
2551                             DEBUG_PRINT("frame %d gyr time: 0x%08x -> 0x%08x, jumped %d msec\n",
2552                                     frame_num,
2553                                     (unsigned int)tmp_time[GYR],
2554                                     (unsigned int)tmp_frame_time,
2555                                     (int)(5 * ((int64_t)(tmp_frame_time - tmp_time[GYR]) >> 7)));
2556                         }
2557 #endif
2558                     }
2559                     mTask.prev_frame_time[GYR] = tmp_frame_time;
2560                     i += 6;
2561                     size -= 6;
2562                     observed[GYR] = true;
2563                 } else {
2564                     size = 0;
2565                 }
2566             }
2567             if (fh_param & 1) { // have accel data
2568                 if (size >= 6) {
2569                     if (frame_sensor_time_valid) {
2570                         parseRawData(&mTask.sensors[ACC], &buf[i], kScale_acc, tmp_frame_time);
2571 #if TIMESTAMP_DBG
2572                         if (mTask.prev_frame_time[ACC] == ULONG_LONG_MAX) {
2573                             DEBUG_PRINT("acc enabled: frame %d time 0x%08x\n",
2574                                     frame_num, (unsigned int)tmp_frame_time);
2575                         } else if ((tmp_frame_time != tmp_time[ACC]) && (tmp_time[ACC] != 0)) {
2576                             DEBUG_PRINT("frame %d gyr time: 0x%08x -> 0x%08x, jumped %d msec\n",
2577                                     frame_num,
2578                                     (unsigned int)tmp_time[ACC],
2579                                     (unsigned int)tmp_frame_time,
2580                                     (int)(5 * ((int64_t)(tmp_frame_time - tmp_time[ACC]) >> 7)));
2581                         }
2582 #endif
2583                     }
2584                     mTask.prev_frame_time[ACC] = tmp_frame_time;
2585                     i += 6;
2586                     size -= 6;
2587                     observed[ACC] = true;
2588                 } else {
2589                     size = 0;
2590                 }
2591             }
2592 
2593             if (observed[ACC] || observed[GYR])
2594                 frame_sensor_time = tmp_frame_time;
2595 #ifdef MAG_SLAVE_PRESENT
2596             else if (observed[MAG])
2597                 frame_sensor_time = tmp_frame_time;
2598 #endif
2599         } else {
2600             size = 0; // drop this batch
2601             ERROR_PRINT("Invalid fh_mode %d at 0x%x, data dump:\n", fh_mode, i);
2602             // dump (a) bytes back and (b) bytes forward.
2603             int a = i < 0x80 ? 0 : (i - 0x80) & ~0x0F;
2604             int b = ((i + 0x80 > mTask.xferCnt ? mTask.xferCnt : i + 0x80) + 0x0F) & ~0x0F;
2605             dumpBinary(mTask.dataBuffer, a, b - a);
2606         }
2607     }
2608 
2609     //flush data events.
2610     flushAllData();
2611 }
2612 
2613 /*
2614  * Read the interrupt type and send corresponding event
2615  * If it's anymo or double tap, also send a single uint32 to indicate which axies
2616  * is this interrupt triggered.
2617  * If it's flat, also send a bit to indicate flat/non-flat position.
2618  * If it's step detector, check if we need to send the total step count.
2619  */
2620 static void int2Handling(void)
2621 {
2622     TDECL();
2623     union EmbeddedDataPoint trigger_axies;
2624     uint8_t int_status_0 = mTask.statusBuffer[1];
2625     uint8_t int_status_1 = mTask.statusBuffer[2];
2626     if (int_status_0 & INT_STEP) {
2627         if (mTask.sensors[STEP].powered) {
2628             DEBUG_PRINT("Detected step\n");
2629             osEnqueueEvt(EVT_SENSOR_STEP, NULL, NULL);
2630         }
2631         if (mTask.sensors[STEPCNT].powered) {
2632             T(pending_step_cnt) = true;
2633         }
2634     }
2635     if ((int_status_0 & INT_ANY_MOTION) && mTask.sensors[ANYMO].powered) {
2636         // bit [0:2] of INT_STATUS[2] is set when anymo is triggered by x, y or
2637         // z axies respectively. bit [3] indicates the slope.
2638         trigger_axies.idata = (mTask.statusBuffer[3] & 0x0f);
2639         DEBUG_PRINT("Detected any motion\n");
2640         osEnqueueEvt(EVT_SENSOR_ANY_MOTION, trigger_axies.vptr, NULL);
2641     }
2642     if ((int_status_0 & INT_DOUBLE_TAP) && mTask.sensors[DTAP].powered) {
2643         // bit [4:6] of INT_STATUS[2] is set when double tap is triggered by
2644         // x, y or z axies respectively. bit [7] indicates the slope.
2645         trigger_axies.idata = ((mTask.statusBuffer[3] & 0xf0) >> 4);
2646         DEBUG_PRINT("Detected double tap\n");
2647         osEnqueueEvt(EVT_SENSOR_DOUBLE_TAP, trigger_axies.vptr, NULL);
2648     }
2649     if ((int_status_0 & INT_FLAT) && mTask.sensors[FLAT].powered) {
2650         // bit [7] of INT_STATUS[3] indicates flat/non-flat position
2651         trigger_axies.idata = ((mTask.statusBuffer[4] & 0x80) >> 7);
2652         DEBUG_PRINT("Detected flat\n");
2653         osEnqueueEvt(EVT_SENSOR_FLAT, trigger_axies.vptr, NULL);
2654     }
2655     if ((int_status_1 & INT_NO_MOTION) && mTask.sensors[NOMO].powered) {
2656         DEBUG_PRINT("Detected no motion\n");
2657         osEnqueueEvt(EVT_SENSOR_NO_MOTION, NULL, NULL);
2658     }
2659     return;
2660 }
2661 
2662 static void int2Evt(void)
2663 {
2664     TDECL();
2665     if (trySwitchState(SENSOR_INT_2_HANDLING)) {
2666         // Read the interrupt reg value to determine what interrupts
2667         SPI_READ(BMI160_REG_INT_STATUS_0, 4, &mTask.statusBuffer);
2668         spiBatchTxRx(&mTask.mode, sensorSpiCallback, &mTask, __FUNCTION__);
2669     } else {
2670         // even if we are still in SENSOR_INT_2_HANDLING, the SPI may already finished and we need
2671         // to issue another SPI read to get the latest status
2672         mTask.pending_int[1] = true;
2673     }
2674 }
2675 
2676 // bits[6:7] in OFFSET[6] to enable/disable gyro/accel offset.
2677 // bits[0:5] in OFFSET[6] stores the most significant 2 bits of gyro offset at
2678 // its x, y, z axies.
2679 // Calculate the stored gyro offset and compose it with the intended
2680 // enable/disable mode for gyro/accel offset to determine the value for
2681 // OFFSET[6].
2682 static uint8_t offset6Mode(void)
2683 {
2684     uint8_t mode = 0;
2685     if (mTask.sensors[GYR].offset_enable)
2686         mode |= 0x01 << 7;
2687     if (mTask.sensors[ACC].offset_enable)
2688         mode |= 0x01 << 6;
2689     mode |= (mTask.sensors[GYR].offset[2] & 0x0300) >> 4;
2690     mode |= (mTask.sensors[GYR].offset[1] & 0x0300) >> 6;
2691     mode |= (mTask.sensors[GYR].offset[0] & 0x0300) >> 8;
2692     DEBUG_PRINT("OFFSET_6_MODE is: %02x\n", mode);
2693     return mode;
2694 }
2695 
2696 static bool saveCalibration()
2697 {
2698     TDECL();
2699     if (trySwitchState(SENSOR_SAVE_CALIBRATION)) {
2700         if (mTask.sensors[ACC].offset_enable) {
2701             SPI_WRITE(BMI160_REG_OFFSET_0, mTask.sensors[ACC].offset[0] & 0xFF, 450);
2702             SPI_WRITE(BMI160_REG_OFFSET_0 + 1, mTask.sensors[ACC].offset[1] & 0xFF, 450);
2703             SPI_WRITE(BMI160_REG_OFFSET_0 + 2, mTask.sensors[ACC].offset[2] & 0xFF, 450);
2704         }
2705         if (mTask.sensors[GYR].offset_enable) {
2706             SPI_WRITE(BMI160_REG_OFFSET_3, mTask.sensors[GYR].offset[0] & 0xFF, 450);
2707             SPI_WRITE(BMI160_REG_OFFSET_3 + 1, mTask.sensors[GYR].offset[1] & 0xFF, 450);
2708             SPI_WRITE(BMI160_REG_OFFSET_3 + 2, mTask.sensors[GYR].offset[2] & 0xFF, 450);
2709         }
2710         SPI_WRITE(BMI160_REG_OFFSET_6, offset6Mode(), 450);
2711         SPI_READ(BMI160_REG_OFFSET_0, 7, &mTask.dataBuffer);
2712         spiBatchTxRx(&mTask.mode, sensorSpiCallback, NULL, __FUNCTION__);
2713         return true;
2714     } else {
2715         DEBUG_PRINT("%s, state != IDLE", __FUNCTION__);
2716         return false;
2717     }
2718 }
2719 
2720 static void sendCalibrationResult(uint8_t status, uint8_t sensorType,
2721         int32_t xBias, int32_t yBias, int32_t zBias) {
2722     struct CalibrationData *data = heapAlloc(sizeof(struct CalibrationData));
2723     if (!data) {
2724         osLog(LOG_WARN, "Couldn't alloc cal result pkt");
2725         return;
2726     }
2727 
2728     data->header.appId = BMI160_APP_ID;
2729     data->header.dataLen = (sizeof(struct CalibrationData) - sizeof(struct HostHubRawPacket));
2730     data->data_header.msgId = SENSOR_APP_MSG_ID_CAL_RESULT;
2731     data->data_header.sensorType = sensorType;
2732     data->data_header.status = status;
2733 
2734     data->xBias = xBias;
2735     data->yBias = yBias;
2736     data->zBias = zBias;
2737 
2738     if (!osEnqueueEvtOrFree(EVT_APP_TO_HOST, data, heapFree))
2739         osLog(LOG_WARN, "Couldn't send cal result evt");
2740 }
2741 
2742 static void accCalibrationHandling(void)
2743 {
2744     TDECL();
2745     switch (mTask.calibration_state) {
2746     case CALIBRATION_START:
2747         T(mRetryLeft) = RETRY_CNT_CALIBRATION;
2748 
2749         // turn ACC to NORMAL mode
2750         SPI_WRITE(BMI160_REG_CMD, 0x11, 50000);
2751 
2752         mTask.calibration_state = CALIBRATION_FOC;
2753         spiBatchTxRx(&mTask.mode, sensorSpiCallback, &mTask.sensors[ACC], __FUNCTION__);
2754         break;
2755     case CALIBRATION_FOC:
2756 
2757         // set accel range
2758         SPI_WRITE(BMI160_REG_ACC_RANGE, ACC_RANGE_SETTING);
2759 
2760         // enable accel fast offset compensation,
2761         // x: 0g, y: 0g, z: 1g
2762         SPI_WRITE(BMI160_REG_FOC_CONF, ACC_FOC_CONFIG);
2763 
2764         // start calibration
2765         SPI_WRITE(BMI160_REG_CMD, 0x03, 100000);
2766 
2767         // poll the status reg until the calibration finishes.
2768         SPI_READ(BMI160_REG_STATUS, 1, &mTask.statusBuffer, 50000);
2769 
2770         mTask.calibration_state = CALIBRATION_WAIT_FOC_DONE;
2771         spiBatchTxRx(&mTask.mode, sensorSpiCallback, &mTask.sensors[ACC], __FUNCTION__);
2772         break;
2773     case CALIBRATION_WAIT_FOC_DONE:
2774         // if the STATUS REG has bit 3 set, it means calbration is done.
2775         // otherwise, check back in 50ms later.
2776         if (mTask.statusBuffer[1] & 0x08) {
2777 
2778             //disable FOC
2779             SPI_WRITE(BMI160_REG_FOC_CONF, 0x00);
2780 
2781             //read the offset value for accel
2782             SPI_READ(BMI160_REG_OFFSET_0, 3, &mTask.dataBuffer);
2783             mTask.calibration_state = CALIBRATION_SET_OFFSET;
2784             DEBUG_PRINT("FOC set FINISHED!\n");
2785         } else {
2786 
2787             // calibration hasn't finished yet, go back to wait for 50ms.
2788             SPI_READ(BMI160_REG_STATUS, 1, &mTask.statusBuffer, 50000);
2789             mTask.calibration_state = CALIBRATION_WAIT_FOC_DONE;
2790             T(mRetryLeft)--;
2791         }
2792         spiBatchTxRx(&mTask.mode, sensorSpiCallback, &mTask.sensors[ACC], __FUNCTION__);
2793 
2794         // if calbration hasn't finished after 10 polling on the STATUS reg,
2795         // declare timeout.
2796         if (T(mRetryLeft) == 0) {
2797             mTask.calibration_state = CALIBRATION_TIMEOUT;
2798         }
2799         break;
2800     case CALIBRATION_SET_OFFSET:
2801         mTask.sensors[ACC].offset[0] = mTask.dataBuffer[1];
2802         mTask.sensors[ACC].offset[1] = mTask.dataBuffer[2];
2803         mTask.sensors[ACC].offset[2] = mTask.dataBuffer[3];
2804         // sign extend values
2805         if (mTask.sensors[ACC].offset[0] & 0x80)
2806             mTask.sensors[ACC].offset[0] |= 0xFFFFFF00;
2807         if (mTask.sensors[ACC].offset[1] & 0x80)
2808             mTask.sensors[ACC].offset[1] |= 0xFFFFFF00;
2809         if (mTask.sensors[ACC].offset[2] & 0x80)
2810             mTask.sensors[ACC].offset[2] |= 0xFFFFFF00;
2811 
2812         mTask.sensors[ACC].offset_enable = true;
2813         DEBUG_PRINT("ACCELERATION OFFSET is %02x  %02x  %02x\n",
2814                 (unsigned int)mTask.sensors[ACC].offset[0],
2815                 (unsigned int)mTask.sensors[ACC].offset[1],
2816                 (unsigned int)mTask.sensors[ACC].offset[2]);
2817 
2818         sendCalibrationResult(SENSOR_APP_EVT_STATUS_SUCCESS, SENS_TYPE_ACCEL,
2819                 mTask.sensors[ACC].offset[0], mTask.sensors[ACC].offset[1],
2820                 mTask.sensors[ACC].offset[2]);
2821 
2822         // Enable offset compensation for accel
2823         uint8_t mode = offset6Mode();
2824         SPI_WRITE(BMI160_REG_OFFSET_6, mode);
2825 
2826         // turn ACC to SUSPEND mode
2827         SPI_WRITE(BMI160_REG_CMD, 0x10, 5000);
2828 
2829         mTask.calibration_state = CALIBRATION_DONE;
2830         spiBatchTxRx(&mTask.mode, sensorSpiCallback, &mTask.sensors[ACC], __FUNCTION__);
2831         break;
2832     default:
2833         ERROR_PRINT("Invalid calibration state\n");
2834         break;
2835     }
2836 }
2837 
2838 static bool accCalibration(void *cookie)
2839 {
2840     TDECL();
2841     if (!mTask.sensors[ACC].powered && trySwitchState(SENSOR_CALIBRATING)) {
2842         mTask.calibration_state = CALIBRATION_START;
2843         accCalibrationHandling();
2844         return true;
2845     } else {
2846         ERROR_PRINT("cannot calibrate accel because sensor is busy\n");
2847         sendCalibrationResult(SENSOR_APP_EVT_STATUS_BUSY, SENS_TYPE_ACCEL, 0, 0, 0);
2848         return false;
2849     }
2850 }
2851 
2852 static bool accCfgData(void *data, void *cookie)
2853 {
2854     struct CfgData {
2855         int32_t hw[3];
2856         float sw[3];
2857     };
2858     struct CfgData *values = data;
2859 
2860     mTask.sensors[ACC].offset[0] = values->hw[0];
2861     mTask.sensors[ACC].offset[1] = values->hw[1];
2862     mTask.sensors[ACC].offset[2] = values->hw[2];
2863     mTask.sensors[ACC].offset_enable = true;
2864 
2865 #ifdef ACCEL_CAL_ENABLED
2866     accelCalBiasSet(&mTask.acc, values->sw[0], values->sw[1], values->sw[2]);
2867 #endif
2868 
2869     INFO_PRINT("accCfgData: data=%02lx, %02lx, %02lx\n",
2870             values->hw[0] & 0xFF, values->hw[1] & 0xFF, values->hw[2] & 0xFF);
2871 
2872     if (!saveCalibration()) {
2873         mTask.pending_calibration_save = true;
2874     }
2875 
2876     return true;
2877 }
2878 
2879 static void sendTestResult(uint8_t status, uint8_t sensorType) {
2880     struct TestResultData *data = heapAlloc(sizeof(struct TestResultData));
2881     if (!data) {
2882         osLog(LOG_WARN, "Couldn't alloc test result packet");
2883         return;
2884     }
2885 
2886     data->header.appId = BMI160_APP_ID;
2887     data->header.dataLen = (sizeof(struct TestResultData) - sizeof(struct HostHubRawPacket));
2888     data->data_header.msgId = SENSOR_APP_MSG_ID_TEST_RESULT;
2889     data->data_header.sensorType = sensorType;
2890     data->data_header.status = status;
2891 
2892     if (!osEnqueueEvtOrFree(EVT_APP_TO_HOST, data, heapFree))
2893         osLog(LOG_WARN, "Couldn't send test result packet");
2894 }
2895 
2896 static void accTestHandling(void)
2897 {
2898     // the minimum absolute differences, according to BMI160 datasheet section
2899     // 2.8.1, are 800 mg for the x and y axes and 400 mg for the z axis
2900     static const int32_t kMinDifferenceXY = (800 * 32767) / 8000;
2901     static const int32_t kMinDifferenceZ = (400 * 32767) / 8000;
2902 
2903     int32_t tempTestX, tempTestY, tempTestZ;
2904     int32_t absDiffX, absDiffY, absDiffZ;
2905 
2906     TDECL();
2907 
2908     switch (mTask.acc_test_state) {
2909     case ACC_TEST_START:
2910         // turn ACC to NORMAL mode
2911         SPI_WRITE(BMI160_REG_CMD, 0x11, 50000);
2912 
2913         mTask.acc_test_state = ACC_TEST_CONFIG;
2914         spiBatchTxRx(&mTask.mode, sensorSpiCallback, &mTask.sensors[ACC], __FUNCTION__);
2915         break;
2916 
2917     case ACC_TEST_CONFIG:
2918         // set accel conf
2919         SPI_WRITE(BMI160_REG_ACC_CONF, 0x2c);
2920 
2921         // set accel range
2922         SPI_WRITE(BMI160_REG_ACC_RANGE, ACC_RANGE_SETTING);
2923 
2924         // read stale accel data
2925         SPI_READ(BMI160_REG_DATA_14, 6, &mTask.dataBuffer);
2926 
2927         mTask.acc_test_state = ACC_TEST_RUN_0;
2928         spiBatchTxRx(&mTask.mode, sensorSpiCallback, &mTask.sensors[ACC], __FUNCTION__);
2929         break;
2930 
2931     case ACC_TEST_RUN_0:
2932         // configure acc_self_test_amp=1, acc_self_test_sign=0, acc_self_test_enable=b01
2933         // wait 50ms for data to be available
2934         SPI_WRITE(BMI160_REG_SELF_TEST, 0x09, 50000);
2935 
2936         // read accel data
2937         SPI_READ(BMI160_REG_DATA_14, 6, &mTask.dataBuffer);
2938 
2939         mTask.acc_test_state = ACC_TEST_RUN_1;
2940         spiBatchTxRx(&mTask.mode, sensorSpiCallback, &mTask.sensors[ACC], __FUNCTION__);
2941         break;
2942 
2943     case ACC_TEST_RUN_1:
2944         // save accel data
2945         mTask.accTestX = *(int16_t*)(mTask.dataBuffer+1);
2946         mTask.accTestY = *(int16_t*)(mTask.dataBuffer+3);
2947         mTask.accTestZ = *(int16_t*)(mTask.dataBuffer+5);
2948 
2949         // configure acc_self_test_amp=1, acc_self_test_sign=1, acc_self_test_enable=b01
2950         // wait 50ms for data to be available
2951         SPI_WRITE(BMI160_REG_SELF_TEST, 0x0d, 50000);
2952 
2953         // read accel data
2954         SPI_READ(BMI160_REG_DATA_14, 6, &mTask.dataBuffer);
2955 
2956         mTask.acc_test_state = ACC_TEST_VERIFY;
2957         spiBatchTxRx(&mTask.mode, sensorSpiCallback, &mTask.sensors[ACC], __FUNCTION__);
2958         break;
2959 
2960     case ACC_TEST_VERIFY:
2961         // save accel data
2962         tempTestX = *(int16_t*)(mTask.dataBuffer+1);
2963         tempTestY = *(int16_t*)(mTask.dataBuffer+3);
2964         tempTestZ = *(int16_t*)(mTask.dataBuffer+5);
2965 
2966         // calculate the differences between run 0 and run 1
2967         absDiffX = ABS((int32_t)mTask.accTestX - tempTestX);
2968         absDiffY = ABS((int32_t)mTask.accTestY - tempTestY);
2969         absDiffZ = ABS((int32_t)mTask.accTestZ - tempTestZ);
2970 
2971         DEBUG_PRINT("accSelfTest diffs: X %d, Y %d, Z %d\n", (int)absDiffX, (int)absDiffY, (int)absDiffZ);
2972 
2973         // verify that the differences between run 0 and run 1 are within spec
2974         if (absDiffX >= kMinDifferenceXY && absDiffY >= kMinDifferenceXY && absDiffZ >= kMinDifferenceZ) {
2975             sendTestResult(SENSOR_APP_EVT_STATUS_SUCCESS, SENS_TYPE_ACCEL);
2976         } else {
2977             sendTestResult(SENSOR_APP_EVT_STATUS_ERROR, SENS_TYPE_ACCEL);
2978         }
2979 
2980         // turn ACC to SUSPEND mode
2981         SPI_WRITE(BMI160_REG_CMD, 0x10, 5000);
2982 
2983         mTask.acc_test_state = ACC_TEST_DONE;
2984         spiBatchTxRx(&mTask.mode, sensorSpiCallback, &mTask.sensors[ACC], __FUNCTION__);
2985         break;
2986 
2987     default:
2988         ERROR_PRINT("Invalid accel test state\n");
2989         break;
2990     }
2991 }
2992 
2993 static bool accSelfTest(void *cookie)
2994 {
2995     TDECL();
2996     INFO_PRINT("accSelfTest\n");
2997 
2998     if (!mTask.sensors[ACC].powered && trySwitchState(SENSOR_TESTING)) {
2999         mTask.acc_test_state = ACC_TEST_START;
3000         accTestHandling();
3001         return true;
3002     } else {
3003         ERROR_PRINT("cannot test accel because sensor is busy\n");
3004         sendTestResult(SENSOR_APP_EVT_STATUS_BUSY, SENS_TYPE_ACCEL);
3005         return false;
3006     }
3007 }
3008 
3009 static void gyrCalibrationHandling(void)
3010 {
3011     TDECL();
3012     switch (mTask.calibration_state) {
3013     case CALIBRATION_START:
3014         T(mRetryLeft) = RETRY_CNT_CALIBRATION;
3015 
3016         // turn GYR to NORMAL mode
3017         SPI_WRITE(BMI160_REG_CMD, 0x15, 50000);
3018 
3019         mTask.calibration_state = CALIBRATION_FOC;
3020         spiBatchTxRx(&mTask.mode, sensorSpiCallback, &mTask.sensors[GYR], __FUNCTION__);
3021         break;
3022     case CALIBRATION_FOC:
3023 
3024         // set gyro range to +-1000 deg/sec
3025         SPI_WRITE(BMI160_REG_GYR_RANGE, 0x01);
3026 
3027         // enable gyro fast offset compensation
3028         SPI_WRITE(BMI160_REG_FOC_CONF, 0x40);
3029 
3030         // start FOC
3031         SPI_WRITE(BMI160_REG_CMD, 0x03, 100000);
3032 
3033         // poll the status reg until the calibration finishes.
3034         SPI_READ(BMI160_REG_STATUS, 1, &mTask.statusBuffer, 50000);
3035 
3036         mTask.calibration_state = CALIBRATION_WAIT_FOC_DONE;
3037         spiBatchTxRx(&mTask.mode, sensorSpiCallback, &mTask.sensors[GYR], __FUNCTION__);
3038         break;
3039     case CALIBRATION_WAIT_FOC_DONE:
3040 
3041         // if the STATUS REG has bit 3 set, it means calbration is done.
3042         // otherwise, check back in 50ms later.
3043         if (mTask.statusBuffer[1] & 0x08) {
3044 
3045             // disable gyro fast offset compensation
3046             SPI_WRITE(BMI160_REG_FOC_CONF, 0x00);
3047 
3048             //read the offset value for gyro
3049             SPI_READ(BMI160_REG_OFFSET_3, 4, &mTask.dataBuffer);
3050             mTask.calibration_state = CALIBRATION_SET_OFFSET;
3051             DEBUG_PRINT("FOC set FINISHED!\n");
3052         } else {
3053 
3054             // calibration hasn't finished yet, go back to wait for 50ms.
3055             SPI_READ(BMI160_REG_STATUS, 1, &mTask.statusBuffer, 50000);
3056             mTask.calibration_state = CALIBRATION_WAIT_FOC_DONE;
3057             T(mRetryLeft)--;
3058         }
3059         spiBatchTxRx(&mTask.mode, sensorSpiCallback, &mTask.sensors[GYR], __FUNCTION__);
3060 
3061         // if calbration hasn't finished after 10 polling on the STATUS reg,
3062         // declare timeout.
3063         if (T(mRetryLeft) == 0) {
3064             mTask.calibration_state = CALIBRATION_TIMEOUT;
3065         }
3066         break;
3067     case CALIBRATION_SET_OFFSET:
3068         mTask.sensors[GYR].offset[0] = ((mTask.dataBuffer[4] & 0x03) << 8) | mTask.dataBuffer[1];
3069         mTask.sensors[GYR].offset[1] = ((mTask.dataBuffer[4] & 0x0C) << 6) | mTask.dataBuffer[2];
3070         mTask.sensors[GYR].offset[2] = ((mTask.dataBuffer[4] & 0x30) << 4) | mTask.dataBuffer[3];
3071         // sign extend values
3072         if (mTask.sensors[GYR].offset[0] & 0x200)
3073             mTask.sensors[GYR].offset[0] |= 0xFFFFFC00;
3074         if (mTask.sensors[GYR].offset[1] & 0x200)
3075             mTask.sensors[GYR].offset[1] |= 0xFFFFFC00;
3076         if (mTask.sensors[GYR].offset[2] & 0x200)
3077             mTask.sensors[GYR].offset[2] |= 0xFFFFFC00;
3078 
3079         mTask.sensors[GYR].offset_enable = true;
3080         DEBUG_PRINT("GYRO OFFSET is %02x  %02x  %02x\n",
3081                 (unsigned int)mTask.sensors[GYR].offset[0],
3082                 (unsigned int)mTask.sensors[GYR].offset[1],
3083                 (unsigned int)mTask.sensors[GYR].offset[2]);
3084 
3085         sendCalibrationResult(SENSOR_APP_EVT_STATUS_SUCCESS, SENS_TYPE_GYRO,
3086                 mTask.sensors[GYR].offset[0], mTask.sensors[GYR].offset[1],
3087                 mTask.sensors[GYR].offset[2]);
3088 
3089         // Enable offset compensation for gyro
3090         uint8_t mode = offset6Mode();
3091         SPI_WRITE(BMI160_REG_OFFSET_6, mode);
3092 
3093         // turn GYR to SUSPEND mode
3094         SPI_WRITE(BMI160_REG_CMD, 0x14, 1000);
3095 
3096         mTask.calibration_state = CALIBRATION_DONE;
3097         spiBatchTxRx(&mTask.mode, sensorSpiCallback, &mTask.sensors[GYR], __FUNCTION__);
3098         break;
3099     default:
3100         ERROR_PRINT("Invalid calibration state\n");
3101         break;
3102     }
3103 }
3104 
3105 static bool gyrCalibration(void *cookie)
3106 {
3107     TDECL();
3108     if (!mTask.sensors[GYR].powered && trySwitchState(SENSOR_CALIBRATING)) {
3109         mTask.calibration_state = CALIBRATION_START;
3110         gyrCalibrationHandling();
3111         return true;
3112     } else {
3113         ERROR_PRINT("cannot calibrate gyro because sensor is busy\n");
3114         sendCalibrationResult(SENSOR_APP_EVT_STATUS_BUSY, SENS_TYPE_GYRO, 0, 0, 0);
3115         return false;
3116     }
3117 }
3118 
3119 static bool gyrCfgData(void *data, void *cookie)
3120 {
3121     TDECL();
3122     const struct AppToSensorHalDataPayload *p = data;
3123     if (p->type == HALINTF_TYPE_GYRO_CAL_BIAS && p->size == sizeof(struct GyroCalBias)) {
3124         const struct GyroCalBias *bias = p->gyroCalBias;
3125         mTask.sensors[GYR].offset[0] = bias->hardwareBias[0];
3126         mTask.sensors[GYR].offset[1] = bias->hardwareBias[1];
3127         mTask.sensors[GYR].offset[2] = bias->hardwareBias[2];
3128         mTask.sensors[GYR].offset_enable = true;
3129         INFO_PRINT("gyrCfgData hw bias: data=%02lx, %02lx, %02lx\n",
3130                 bias->hardwareBias[0] & 0xFF,
3131                 bias->hardwareBias[1] & 0xFF,
3132                 bias->hardwareBias[2] & 0xFF);
3133 
3134 #ifdef GYRO_CAL_ENABLED
3135         const float dummy_temperature_celsius = 25.0f;
3136         gyroCalSetBias(&T(gyro_cal), bias->softwareBias[0],
3137                        bias->softwareBias[1], bias->softwareBias[2],
3138                        dummy_temperature_celsius,
3139                        sensorGetTime());
3140 #endif  // GYRO_CAL_ENABLED
3141         if (!saveCalibration()) {
3142             T(pending_calibration_save) = true;
3143         }
3144 #if OVERTEMPCAL_ENABLED
3145     } else if (p->type == HALINTF_TYPE_GYRO_OTC_DATA && p->size == sizeof(struct GyroOtcData)) {
3146         handleOtcGyroConfig(data);
3147 #endif // OVERTEMPCAL_ENABLED
3148     } else {
3149         ERROR_PRINT("Unknown gyro config data type 0x%04x, size %d\n", p->type, p->size);
3150     }
3151     return true;
3152 }
3153 
3154 static void gyroTestHandling(void)
3155 {
3156     TDECL();
3157 
3158     switch (mTask.gyro_test_state) {
3159     case GYRO_TEST_START:
3160         // turn GYR to NORMAL mode
3161         SPI_WRITE(BMI160_REG_CMD, 0x15, 50000);
3162 
3163         mTask.gyro_test_state = GYRO_TEST_RUN;
3164         spiBatchTxRx(&mTask.mode, sensorSpiCallback, &mTask.sensors[GYR], __FUNCTION__);
3165         break;
3166 
3167     case GYRO_TEST_RUN:
3168         // set gyr_self_test_enable
3169         // wait 50ms to check test status
3170         SPI_WRITE(BMI160_REG_SELF_TEST, 0x10, 50000);
3171 
3172         // check gyro self-test result in status register
3173         SPI_READ(BMI160_REG_STATUS, 1, &mTask.statusBuffer);
3174 
3175         mTask.gyro_test_state = GYRO_TEST_VERIFY;
3176         spiBatchTxRx(&mTask.mode, sensorSpiCallback, &mTask.sensors[GYR], __FUNCTION__);
3177         break;
3178 
3179     case GYRO_TEST_VERIFY:
3180         // gyr_self_test_ok is bit 1
3181         if (mTask.statusBuffer[1] & 0x2) {
3182             sendTestResult(SENSOR_APP_EVT_STATUS_SUCCESS, SENS_TYPE_GYRO);
3183         } else {
3184             sendTestResult(SENSOR_APP_EVT_STATUS_ERROR, SENS_TYPE_GYRO);
3185         }
3186 
3187         // turn GYR to SUSPEND mode
3188         SPI_WRITE(BMI160_REG_CMD, 0x14, 1000);
3189 
3190         mTask.gyro_test_state = GYRO_TEST_DONE;
3191         spiBatchTxRx(&mTask.mode, sensorSpiCallback, &mTask.sensors[GYR], __FUNCTION__);
3192         break;
3193 
3194     default:
3195         ERROR_PRINT("Invalid gyro test state\n");
3196         break;
3197     }
3198 }
3199 
3200 static bool gyrSelfTest(void *cookie)
3201 {
3202     TDECL();
3203     INFO_PRINT("gyrSelfTest\n");
3204 
3205     if (!mTask.sensors[GYR].powered && trySwitchState(SENSOR_TESTING)) {
3206         mTask.gyro_test_state = GYRO_TEST_START;
3207         gyroTestHandling();
3208         return true;
3209     } else {
3210         ERROR_PRINT("cannot test gyro because sensor is busy\n");
3211         sendTestResult(SENSOR_APP_EVT_STATUS_BUSY, SENS_TYPE_GYRO);
3212         return false;
3213     }
3214 }
3215 
3216 #ifdef MAG_SLAVE_PRESENT
3217 static bool magCfgData(void *data, void *cookie)
3218 {
3219     const struct AppToSensorHalDataPayload *p = data;
3220     if (p->type == HALINTF_TYPE_MAG_CAL_BIAS && p->size == sizeof(struct MagCalBias)) {
3221         const struct MagCalBias *d = p->magCalBias;
3222         INFO_PRINT("magCfgData: calibration %ldnT, %ldnT, %ldnT\n",
3223                 (int32_t)(d->bias[0] * 1000),
3224                 (int32_t)(d->bias[1] * 1000),
3225                 (int32_t)(d->bias[2] * 1000));
3226 
3227         mTask.moc.x_bias = d->bias[0];
3228         mTask.moc.y_bias = d->bias[1];
3229         mTask.moc.z_bias = d->bias[2];
3230         mTask.magBiasPosted = false;
3231     } else if (p->type == HALINTF_TYPE_MAG_LOCAL_FIELD && p->size == sizeof(struct MagLocalField)) {
3232         const struct MagLocalField *d = p->magLocalField;
3233         INFO_PRINT("magCfgData: local field strength %dnT, dec %ddeg, inc %ddeg\n",
3234                 (int)(d->strength * 1000),
3235                 (int)(d->declination * 180 / M_PI + 0.5f),
3236                 (int)(d->inclination * 180 / M_PI + 0.5f));
3237 
3238         // Passing local field information to mag calibration routine
3239         diversityCheckerLocalFieldUpdate(&mTask.moc.diversity_checker, d->strength);
3240 
3241         // TODO: pass local field information to rotation vector sensor.
3242     } else {
3243         ERROR_PRINT("magCfgData: unknown type 0x%04x, size %d", p->type, p->size);
3244     }
3245     return true;
3246 }
3247 #endif
3248 
3249 #define DEC_OPS(power, firmware, rate, flush) \
3250     .sensorPower = power, \
3251     .sensorFirmwareUpload = firmware, \
3252     .sensorSetRate = rate, \
3253     .sensorFlush = flush
3254 
3255 #define DEC_OPS_SEND(power, firmware, rate, flush, send) \
3256     DEC_OPS(power, firmware, rate, flush), \
3257     .sensorSendOneDirectEvt = send
3258 
3259 #define DEC_OPS_CAL_CFG_TEST(power, firmware, rate, flush, cal, cfg, test) \
3260     DEC_OPS(power, firmware, rate, flush), \
3261     .sensorCalibrate = cal, \
3262     .sensorCfgData = cfg, \
3263     .sensorSelfTest = test,
3264 
3265 #define DEC_OPS_CFG(power, firmware, rate, flush, cfg) \
3266     DEC_OPS(power, firmware, rate, flush), \
3267     .sensorCfgData = cfg
3268 
3269 static const struct SensorOps mSensorOps[NUM_OF_SENSOR] =
3270 {
3271     { DEC_OPS_CAL_CFG_TEST(accPower, accFirmwareUpload, accSetRate, accFlush, accCalibration,
3272             accCfgData, accSelfTest) },
3273     { DEC_OPS_CAL_CFG_TEST(gyrPower, gyrFirmwareUpload, gyrSetRate, gyrFlush, gyrCalibration,
3274             gyrCfgData, gyrSelfTest) },
3275 #ifdef MAG_SLAVE_PRESENT
3276     { DEC_OPS_CFG(magPower, magFirmwareUpload, magSetRate, magFlush, magCfgData) },
3277 #endif
3278     { DEC_OPS(stepPower, stepFirmwareUpload, stepSetRate, stepFlush) },
3279     { DEC_OPS(doubleTapPower, doubleTapFirmwareUpload, doubleTapSetRate, doubleTapFlush) },
3280     { DEC_OPS(flatPower, flatFirmwareUpload, flatSetRate, flatFlush) },
3281     { DEC_OPS(anyMotionPower, anyMotionFirmwareUpload, anyMotionSetRate, anyMotionFlush) },
3282     { DEC_OPS(noMotionPower, noMotionFirmwareUpload, noMotionSetRate, noMotionFlush) },
3283     { DEC_OPS_SEND(stepCntPower, stepCntFirmwareUpload, stepCntSetRate, stepCntFlush,
3284             stepCntSendLastData) },
3285 };
3286 
3287 static void configEvent(struct BMI160Sensor *mSensor, struct ConfigStat *ConfigData)
3288 {
3289     int i;
3290 
3291     for (i = 0; &mTask.sensors[i] != mSensor; i++) ;
3292 
3293     if (ConfigData->enable == 0 && mSensor->powered)
3294         mSensorOps[i].sensorPower(false, (void *)i);
3295     else if (ConfigData->enable == 1 && !mSensor->powered)
3296         mSensorOps[i].sensorPower(true, (void *)i);
3297     else
3298         mSensorOps[i].sensorSetRate(ConfigData->rate, ConfigData->latency, (void *)i);
3299 }
3300 
3301 static void timeSyncEvt(uint32_t evtGeneration, bool evtDataValid)
3302 {
3303     TDECL();
3304     // not processing pending events
3305     if (evtDataValid) {
3306         // stale event
3307         if (evtGeneration != mTask.poll_generation)
3308             return;
3309 
3310         mTask.active_poll_generation = mTask.poll_generation;
3311     }
3312 
3313     if (trySwitchState(SENSOR_TIME_SYNC)) {
3314         SPI_READ(BMI160_REG_SENSORTIME_0, 3, &mTask.sensorTimeBuffer);
3315         SPI_READ(BMI160_REG_TEMPERATURE_0, 2, &mTask.temperatureBuffer);
3316         // sensorSpiCallback schedules a private event, which can be delayed
3317         // by other long-running tasks.
3318         // Take the rtc time now so it matches the current sensorTime register
3319         // reading.
3320         mTask.timesync_rtc_time = sensorGetTime();
3321         spiBatchTxRx(&mTask.mode, sensorSpiCallback, &mTask, __FUNCTION__);
3322     } else {
3323         mTask.pending_time_sync = true;
3324     }
3325 }
3326 
3327 static void processPendingEvt(void)
3328 {
3329     TDECL();
3330     enum SensorIndex i;
3331     if (mTask.pending_int[0]) {
3332         mTask.pending_int[0] = false;
3333         initiateFifoRead(false /*isInterruptContext*/);
3334         return;
3335     }
3336     if (mTask.pending_int[1]) {
3337         mTask.pending_int[1] = false;
3338         int2Evt();
3339         return;
3340     }
3341     if (mTask.pending_time_sync) {
3342         mTask.pending_time_sync = false;
3343         timeSyncEvt(0, false);
3344         return;
3345     }
3346     for (i = FIRST_CONT_SENSOR; i < NUM_OF_SENSOR; i++) {
3347         if (mTask.pending_config[i]) {
3348             mTask.pending_config[i] = false;
3349             configEvent(&mTask.sensors[i], &mTask.sensors[i].pConfig);
3350             return;
3351         }
3352     }
3353     if (mTask.sensors[STEPCNT].flush > 0 || T(pending_step_cnt)) {
3354         T(pending_step_cnt) = !stepCntFlushGetData() && T(pending_step_cnt);
3355         return;
3356     }
3357     if (mTask.pending_calibration_save) {
3358         mTask.pending_calibration_save = !saveCalibration();
3359         return;
3360     }
3361 
3362 #ifdef OVERTEMPCAL_ENABLED
3363     // tasks that do not initiate SPI transaction
3364     if (T(otcGyroUpdateBuffer).sendToHostRequest) {
3365         sendOtcGyroUpdate();
3366     }
3367 #endif
3368 }
3369 
3370 static void sensorInit(void)
3371 {
3372     TDECL();
3373     switch (mTask.init_state) {
3374     case RESET_BMI160:
3375         DEBUG_PRINT("Performing soft reset\n");
3376         // perform soft reset and wait for 100ms
3377         SPI_WRITE(BMI160_REG_CMD, 0xb6, 100000);
3378         // dummy reads after soft reset, wait 100us
3379         SPI_READ(BMI160_REG_MAGIC, 1, &mTask.dataBuffer, 100);
3380 
3381         mTask.init_state = INIT_BMI160;
3382         spiBatchTxRx(&mTask.mode, sensorSpiCallback, &mTask, "sensorInit RESET" );
3383         break;
3384 
3385     case INIT_BMI160:
3386         // Read any pending interrupts to reset them
3387         SPI_READ(BMI160_REG_INT_STATUS_0, 4, &mTask.statusBuffer);
3388 
3389         // disable accel, gyro and mag data in FIFO, enable header, enable time.
3390         SPI_WRITE(BMI160_REG_FIFO_CONFIG_1, 0x12, 450);
3391 
3392         // set the watermark to 24 byte
3393         SPI_WRITE(BMI160_REG_FIFO_CONFIG_0, 0x06, 450);
3394 
3395         // FIFO watermark and fifo_full interrupt enabled
3396         SPI_WRITE(BMI160_REG_INT_EN_0, 0x00, 450);
3397         SPI_WRITE(BMI160_REG_INT_EN_1, 0x60, 450);
3398         SPI_WRITE(BMI160_REG_INT_EN_2, 0x00, 450);
3399 
3400         // INT1, INT2 enabled, high-edge (push-pull) triggered.
3401         SPI_WRITE(BMI160_REG_INT_OUT_CTRL, 0xbb, 450);
3402 
3403         // INT1, INT2 input disabled, interrupt mode: non-latched
3404         SPI_WRITE(BMI160_REG_INT_LATCH, 0x00, 450);
3405 
3406         // Map data interrupts (e.g., FIFO) to INT1 and physical
3407         // interrupts (e.g., any motion) to INT2
3408         SPI_WRITE(BMI160_REG_INT_MAP_0, 0x00, 450);
3409         SPI_WRITE(BMI160_REG_INT_MAP_1, 0xE1, 450);
3410         SPI_WRITE(BMI160_REG_INT_MAP_2, 0xFF, 450);
3411 
3412         // Use pre-filtered data for tap interrupt
3413         SPI_WRITE(BMI160_REG_INT_DATA_0, 0x08);
3414 
3415         // Disable PMU_TRIGGER
3416         SPI_WRITE(BMI160_REG_PMU_TRIGGER, 0x00, 450);
3417 
3418         // tell gyro and accel to NOT use the FOC offset.
3419         mTask.sensors[ACC].offset_enable = false;
3420         mTask.sensors[GYR].offset_enable = false;
3421         SPI_WRITE(BMI160_REG_OFFSET_6, offset6Mode(), 450);
3422 
3423         // initial range for accel and gyro (+-1000 degree).
3424         SPI_WRITE(BMI160_REG_ACC_RANGE, ACC_RANGE_SETTING, 450);
3425         SPI_WRITE(BMI160_REG_GYR_RANGE, 0x01, 450);
3426 
3427         // Reset step counter
3428         SPI_WRITE(BMI160_REG_CMD, 0xB2, 10000);
3429         // Reset interrupt
3430         SPI_WRITE(BMI160_REG_CMD, 0xB1, 10000);
3431         // Reset fifo
3432         SPI_WRITE(BMI160_REG_CMD, 0xB0, 10000);
3433 
3434 #ifdef MAG_SLAVE_PRESENT
3435         mTask.init_state = INIT_MAG;
3436         mTask.mag_state = MAG_SET_START;
3437 #else
3438         // no mag connected to secondary interface
3439         mTask.init_state = INIT_ON_CHANGE_SENSORS;
3440 #endif
3441         spiBatchTxRx(&mTask.mode, sensorSpiCallback, &mTask, "sensorInit INIT");
3442         break;
3443 
3444     case INIT_MAG:
3445         // Don't check statusBuffer if we are just starting mag config
3446         if (mTask.mag_state == MAG_SET_START) {
3447             T(mRetryLeft) = RETRY_CNT_MAG;
3448             magConfig();
3449         } else if (mTask.mag_state < MAG_SET_DATA && mTask.statusBuffer[1] & 0x04) {
3450             // fixme: poll_until to reduce states
3451             // fixme: check should be done before SPI_READ in MAG_READ
3452             SPI_READ(BMI160_REG_STATUS, 1, &mTask.statusBuffer, 1000);
3453             if (--T(mRetryLeft) == 0) {
3454                 ERROR_PRINT("INIT_MAG failed\n");
3455                 // fixme: duplicate suspend mag here
3456                 mTask.mag_state = MAG_INIT_FAILED;
3457                 mTask.init_state = INIT_ON_CHANGE_SENSORS;
3458             }
3459         } else {
3460             T(mRetryLeft) = RETRY_CNT_MAG;
3461             magConfig();
3462         }
3463 
3464         spiBatchTxRx(&mTask.mode, sensorSpiCallback, &mTask, "sensorInit INIT_MAG");
3465         break;
3466 
3467     case INIT_ON_CHANGE_SENSORS:
3468         // configure any_motion and no_motion for 50Hz accel samples
3469         configMotion(MOTION_ODR);
3470 
3471         // select no_motion over slow_motion
3472         // select any_motion over significant motion
3473         SPI_WRITE(BMI160_REG_INT_MOTION_3, 0x15, 450);
3474 
3475         // int_tap_quiet=30ms, int_tap_shock=75ms, int_tap_dur=150ms
3476         SPI_WRITE(BMI160_REG_INT_TAP_0, 0x42, 450);
3477 
3478         // int_tap_th = 7 * 250 mg (8-g range)
3479         SPI_WRITE(BMI160_REG_INT_TAP_1, TAP_THRESHOLD, 450);
3480 
3481         // config step detector
3482 #ifdef BMI160_STEP_COUNT_MODE_SENSITIVE
3483         SPI_WRITE(BMI160_REG_STEP_CONF_0, 0x2D, 450);
3484         SPI_WRITE(BMI160_REG_STEP_CONF_1, 0x02, 450);
3485 #else
3486         SPI_WRITE(BMI160_REG_STEP_CONF_0, 0x15, 450);
3487         SPI_WRITE(BMI160_REG_STEP_CONF_1, 0x03, 450);
3488 #endif
3489 
3490         // int_flat_theta = 44.8 deg * (16/64) = 11.2 deg
3491         SPI_WRITE(BMI160_REG_INT_FLAT_0, 0x10, 450);
3492 
3493         // int_flat_hold_time = (640 msec)
3494         // int_flat_hy = 44.8 * 4 / 64 = 2.8 deg
3495         SPI_WRITE(BMI160_REG_INT_FLAT_1, 0x14, 450);
3496 
3497         mTask.init_state = INIT_DONE;
3498         spiBatchTxRx(&mTask.mode, sensorSpiCallback, &mTask, "sensorInit INIT_ONC");
3499         break;
3500 
3501     default:
3502         INFO_PRINT("Invalid init_state.\n");
3503     }
3504 }
3505 
3506 static void handleSpiDoneEvt(const void* evtData)
3507 {
3508     TDECL();
3509     struct BMI160Sensor *mSensor;
3510     uint64_t SensorTime;
3511     int16_t temperature16;
3512     int i;
3513     bool returnIdle = false;
3514 
3515     switch (GET_STATE()) {
3516     case SENSOR_BOOT:
3517         SET_STATE(SENSOR_VERIFY_ID);
3518         // dummy reads after boot, wait 100us
3519         SPI_READ(BMI160_REG_MAGIC, 1, &mTask.statusBuffer, 100);
3520         // read the device ID for bmi160
3521         SPI_READ(BMI160_REG_ID, 1, &mTask.dataBuffer);
3522         spiBatchTxRx(&mTask.mode, sensorSpiCallback, &mTask, "spiDone SENSOR_BOOT");
3523         break;
3524     case SENSOR_VERIFY_ID:
3525         if (mTask.dataBuffer[1] != BMI160_ID) {
3526             T(mRetryLeft) --;
3527             ERROR_PRINT("failed id match: %02x\n", mTask.dataBuffer[1]);
3528             if (T(mRetryLeft) == 0)
3529                 break;
3530             // For some reason the first ID read will fail to get the
3531             // correct value. need to retry a few times.
3532             SET_STATE(SENSOR_BOOT);
3533             if (timTimerSet(100000000, 100, 100, sensorTimerCallback, NULL, true) == 0)
3534                 ERROR_PRINT("Couldn't get a timer to verify ID\n");
3535             break;
3536         } else {
3537             INFO_PRINT("detected\n");
3538             SET_STATE(SENSOR_INITIALIZING);
3539             mTask.init_state = RESET_BMI160;
3540             sensorInit();
3541             break;
3542         }
3543     case SENSOR_INITIALIZING:
3544         if (mTask.init_state == INIT_DONE) {
3545             DEBUG_PRINT("Done initialzing, system IDLE\n");
3546             for (i=0; i<NUM_OF_SENSOR; i++)
3547                 sensorRegisterInitComplete(mTask.sensors[i].handle);
3548             // In case other tasks have already requested us before we finish booting up.
3549             returnIdle = true;
3550         } else {
3551             sensorInit();
3552         }
3553         break;
3554     case SENSOR_POWERING_UP:
3555         mSensor = (struct BMI160Sensor *)evtData;
3556         if (mSensor->idx >= FIRST_ONESHOT_SENSOR && ++mTask.active_oneshot_sensor_cnt == 1) {
3557             // if this is the first one-shot sensor to enable, we need
3558             // to request the accel at 50Hz.
3559             sensorRequest(mTask.tid, mTask.sensors[ACC].handle, SENSOR_HZ(50), SENSOR_LATENCY_NODATA);
3560             //DEBUG_PRINT("oneshot on\n");
3561         }
3562         sensorSignalInternalEvt(mSensor->handle, SENSOR_INTERNAL_EVT_POWER_STATE_CHG, 1, 0);
3563         returnIdle = true;
3564         break;
3565     case SENSOR_POWERING_DOWN:
3566         mSensor = (struct BMI160Sensor *)evtData;
3567         if (mSensor->idx >= FIRST_ONESHOT_SENSOR && --mTask.active_oneshot_sensor_cnt == 0) {
3568             // if this is the last one-shot sensor to disable, we need to
3569             // release the accel.
3570             sensorRelease(mTask.tid, mTask.sensors[ACC].handle);
3571             //DEBUG_PRINT("oneshot off\n");
3572         }
3573         sensorSignalInternalEvt(mSensor->handle, SENSOR_INTERNAL_EVT_POWER_STATE_CHG, 0, 0);
3574 
3575         if (mTask.pending_dispatch) {
3576             mTask.pending_dispatch = false;
3577             dispatchData();
3578         }
3579         returnIdle = true;
3580         break;
3581     case SENSOR_INT_1_HANDLING:
3582         dispatchData();
3583         sendFlushEvt();
3584         returnIdle = true;
3585         break;
3586     case SENSOR_INT_2_HANDLING:
3587         int2Handling();
3588         returnIdle = true;
3589         break;
3590     case SENSOR_CONFIG_CHANGING:
3591         mSensor = (struct BMI160Sensor *)evtData;
3592         sensorSignalInternalEvt(mSensor->handle,
3593                 SENSOR_INTERNAL_EVT_RATE_CHG, mSensor->rate, mSensor->latency);
3594 
3595         if (mTask.pending_dispatch) {
3596             mTask.pending_dispatch = false;
3597             dispatchData();
3598         }
3599 
3600         returnIdle = true;
3601         break;
3602     case SENSOR_CALIBRATING:
3603         mSensor = (struct BMI160Sensor *)evtData;
3604         if (mTask.calibration_state == CALIBRATION_DONE) {
3605             DEBUG_PRINT("DONE calibration\n");
3606             returnIdle = true;
3607         } else if (mTask.calibration_state == CALIBRATION_TIMEOUT) {
3608             DEBUG_PRINT("Calibration TIMED OUT\n");
3609             sendCalibrationResult(SENSOR_APP_EVT_STATUS_ERROR,
3610                     (mSensor->idx == ACC) ? SENS_TYPE_ACCEL : SENS_TYPE_GYRO, 0, 0, 0);
3611             returnIdle = true;
3612         } else if (mSensor->idx == ACC) {
3613             accCalibrationHandling();
3614         } else if (mSensor->idx == GYR) {
3615             gyrCalibrationHandling();
3616         }
3617         break;
3618     case SENSOR_TESTING:
3619         mSensor = (struct BMI160Sensor *)evtData;
3620         if (mSensor->idx == ACC) {
3621             if (mTask.acc_test_state == ACC_TEST_DONE) {
3622                 returnIdle = true;
3623             } else {
3624                 accTestHandling();
3625             }
3626         } else if (mSensor->idx == GYR) {
3627             if (mTask.gyro_test_state == GYRO_TEST_DONE) {
3628                 returnIdle = true;
3629             } else {
3630                 gyroTestHandling();
3631             }
3632         }
3633         break;
3634     case SENSOR_STEP_CNT:
3635         sendStepCnt();
3636         returnIdle = true;
3637         break;
3638     case SENSOR_TIME_SYNC:
3639         SensorTime = parseSensortime(mTask.sensorTimeBuffer[1] |
3640                 (mTask.sensorTimeBuffer[2] << 8) | (mTask.sensorTimeBuffer[3] << 16));
3641         map_sensortime_to_rtc_time(SensorTime, mTask.timesync_rtc_time);
3642 
3643         temperature16 = (mTask.temperatureBuffer[1] | (mTask.temperatureBuffer[2] << 8));
3644         if (temperature16 == 0x8000) {
3645             mTask.tempCelsius = kTempInvalid;
3646         } else {
3647             mTask.tempCelsius = 23.0f + temperature16 * kScale_temp;
3648             mTask.tempTime = sensorGetTime();
3649         }
3650 
3651         if (mTask.active_poll_generation == mTask.poll_generation) {
3652             // attach the generation number to event
3653             if (timTimerSet(kTimeSyncPeriodNs, 100, 100, timeSyncCallback,
3654                     (void *)mTask.poll_generation, true) == 0)
3655                 ERROR_PRINT("Couldn't get a timer for time sync\n");
3656         }
3657 
3658         returnIdle = true;
3659         break;
3660     case SENSOR_SAVE_CALIBRATION:
3661         DEBUG_PRINT("SENSOR_SAVE_CALIBRATION: %02x %02x %02x %02x %02x %02x %02x\n",
3662                 mTask.dataBuffer[1], mTask.dataBuffer[2], mTask.dataBuffer[3], mTask.dataBuffer[4],
3663                 mTask.dataBuffer[5], mTask.dataBuffer[6], mTask.dataBuffer[7]);
3664         returnIdle = true;
3665         break;
3666     default:
3667         break;
3668     }
3669 
3670     if (returnIdle) {
3671         SET_STATE(SENSOR_IDLE);
3672         processPendingEvt();
3673     }
3674 }
3675 
3676 #ifdef BMI160_USE_I2C
3677 static void i2cCallback(void *cookie, size_t tx, size_t rx, int err);
3678 
3679 /* delayed callback */
3680 static void i2cDelayCallback(uint32_t timerId, void *data)
3681 {
3682     i2cCallback(data, 0, 0, 0);
3683 }
3684 
3685 static void i2cCallback(void *cookie, size_t tx, size_t rx, int err)
3686 {
3687     TDECL();
3688     uint8_t reg = T(cReg) - 1;
3689     uint32_t delay;
3690 
3691     if (err != 0) {
3692         ERROR_PRINT("i2c error (tx: %d, rx: %d, err: %d)\n", tx, rx, err);
3693     } else { /* delay callback if it is the case */
3694         delay = T(packets[reg]).delay;
3695         T(packets[reg]).delay = 0;
3696         if (delay > 0) {
3697             if (timTimerSet(delay, 0, 50, i2cDelayCallback, cookie, true))
3698                 return;
3699             ERROR_PRINT("Cannot do delayed i2cCallback\n");
3700             err = -ENOMEM;
3701         }
3702     }
3703     i2cBatchTxRx(cookie, err);
3704 }
3705 
3706 static void i2cBatchTxRx(void *evtData, int err)
3707 {
3708     TDECL();
3709     uint8_t *txBuf;
3710     uint8_t *rxBuf;
3711     uint16_t size;
3712     uint8_t reg;
3713 
3714     reg = T(cReg)++;
3715     if (err || (reg >= T(mRegCnt))) // No more packets
3716         goto i2c_batch_end;
3717 
3718     // Setup i2c op for next packet
3719     txBuf = (uint8_t *)T(packets[reg]).txBuf;
3720     size = T(packets[reg]).size;
3721     if (txBuf[0] & BMI160_SPI_READ) { // Read op
3722         rxBuf = (uint8_t *)T(packets[reg]).rxBuf + 1;
3723         size--;
3724         err = i2cMasterTxRx(BMI160_I2C_BUS_ID, BMI160_I2C_ADDR, txBuf, 1, rxBuf, size, i2cCallback, evtData);
3725     } else { // Write op
3726         err = i2cMasterTx(BMI160_I2C_BUS_ID, BMI160_I2C_ADDR, txBuf, size, i2cCallback, evtData);
3727     }
3728     if (!err)
3729         return;
3730     ERROR_PRINT("%s: [0x%x] (err: %d)\n", __func__, txBuf[0], err);
3731 
3732 i2c_batch_end:
3733     T(mRegCnt) = 0;
3734     if (T(sCallback))
3735         T(sCallback)((void *)evtData, err);
3736 }
3737 #endif
3738 
3739 static void handleEvent(uint32_t evtType, const void* evtData)
3740 {
3741     TDECL();
3742     uint64_t currTime;
3743     uint8_t *packet;
3744     float newMagBias;
3745 
3746     switch (evtType) {
3747     case EVT_APP_START:
3748         SET_STATE(SENSOR_BOOT);
3749         T(mRetryLeft) = RETRY_CNT_ID;
3750         osEventUnsubscribe(mTask.tid, EVT_APP_START);
3751 
3752         // wait 100ms for sensor to boot
3753         currTime = timGetTime();
3754         if (currTime < 100000000ULL) {
3755             if (timTimerSet(100000000 - currTime, 100, 100, sensorTimerCallback, NULL, true) == 0)
3756                 ERROR_PRINT("Couldn't get a timer for boot delay\n");
3757             break;
3758         }
3759         /* We have already been powered on long enough - fall through */
3760     case EVT_SPI_DONE:
3761         handleSpiDoneEvt(evtData);
3762         break;
3763 
3764     case EVT_APP_FROM_HOST:
3765         packet = (uint8_t*)evtData;
3766         if (packet[0] == sizeof(float)) {
3767             memcpy(&newMagBias, packet+1, sizeof(float));
3768 #ifdef MAG_SLAVE_PRESENT
3769             magCalAddBias(&mTask.moc, (mTask.last_charging_bias_x - newMagBias), 0.0, 0.0);
3770 #endif
3771             mTask.last_charging_bias_x = newMagBias;
3772             mTask.magBiasPosted = false;
3773         }
3774         break;
3775 
3776     case EVT_SENSOR_INTERRUPT_1:
3777         initiateFifoRead(false /*isInterruptContext*/);
3778         break;
3779     case EVT_SENSOR_INTERRUPT_2:
3780         int2Evt();
3781         break;
3782     case EVT_TIME_SYNC:
3783         timeSyncEvt((uint32_t)evtData, true);
3784     default:
3785         break;
3786     }
3787 }
3788 
3789 static void initSensorStruct(struct BMI160Sensor *sensor, enum SensorIndex idx)
3790 {
3791     sensor->idx = idx;
3792     sensor->powered = false;
3793     sensor->configed = false;
3794     sensor->rate = 0;
3795     sensor->offset[0] = 0;
3796     sensor->offset[1] = 0;
3797     sensor->offset[2] = 0;
3798     sensor->latency = 0;
3799     sensor->data_evt = NULL;
3800     sensor->flush = 0;
3801     sensor->prev_rtc_time = 0;
3802 }
3803 
3804 static bool startTask(uint32_t task_id)
3805 {
3806     TDECL();
3807     enum SensorIndex i;
3808     size_t slabSize;
3809 
3810     time_init();
3811 
3812     T(tid) = task_id;
3813 
3814     T(Int1) = gpioRequest(BMI160_INT1_PIN);
3815     T(Irq1) = BMI160_INT1_IRQ;
3816     T(Isr1).func = bmi160Isr1;
3817     T(Int2) = gpioRequest(BMI160_INT2_PIN);
3818     T(Irq2) = BMI160_INT2_IRQ;
3819     T(Isr2).func = bmi160Isr2;
3820     T(pending_int[0]) = false;
3821     T(pending_int[1]) = false;
3822     T(pending_step_cnt) = false;
3823     T(pending_dispatch) = false;
3824     T(frame_sensortime_valid) = false;
3825     T(poll_generation) = 0;
3826     T(tempCelsius) = kTempInvalid;
3827     T(tempTime) = 0;
3828 
3829     T(mode).speed = BMI160_SPI_SPEED_HZ;
3830     T(mode).bitsPerWord = 8;
3831     T(mode).cpol = SPI_CPOL_IDLE_HI;
3832     T(mode).cpha = SPI_CPHA_TRAILING_EDGE;
3833     T(mode).nssChange = true;
3834     T(mode).format = SPI_FORMAT_MSB_FIRST;
3835     T(cs) = BMI160_SPI_CS_PIN;
3836 
3837     T(watermark) = 0;
3838 
3839 #ifdef BMI160_USE_I2C
3840     i2cMasterRequest(BMI160_I2C_BUS_ID, BMI160_I2C_SPEED);
3841 #else
3842     spiMasterRequest(BMI160_SPI_BUS_ID, &T(spiDev));
3843 #endif
3844 
3845     for (i = FIRST_CONT_SENSOR; i < NUM_OF_SENSOR; i++) {
3846         initSensorStruct(&T(sensors[i]), i);
3847         T(sensors[i]).handle = sensorRegister(&mSensorInfo[i], &mSensorOps[i], NULL, false);
3848         T(pending_config[i]) = false;
3849     }
3850 
3851     osEventSubscribe(mTask.tid, EVT_APP_START);
3852 
3853 #ifdef ACCEL_CAL_ENABLED
3854     // Initializes the accelerometer offset calibration algorithm.
3855     const struct AccelCalParameters accel_cal_parameters = {
3856         MSEC_TO_NANOS(800),  // t0
3857         5,                   // n_s
3858         15,                  // fx
3859         15,                  // fxb
3860         15,                  // fy
3861         15,                  // fyb
3862         15,                  // fz
3863         15,                  // fzb
3864         15,                  // fle
3865         0.00025f             // th
3866     };
3867     accelCalInit(&mTask.acc, &accel_cal_parameters);
3868 #endif  // ACCEL_CAL_ENABLED
3869 
3870 #ifdef GYRO_CAL_ENABLED
3871     // Initializes the gyroscope offset calibration algorithm.
3872     const struct GyroCalParameters gyro_cal_parameters = {
3873         SEC_TO_NANOS(5),      // min_still_duration_nanos
3874         SEC_TO_NANOS(5.9f),   // max_still_duration_nanos [see, NOTE 1]
3875         0,                    // calibration_time_nanos
3876         SEC_TO_NANOS(1.5f),   // window_time_duration_nanos
3877         0,                    // bias_x
3878         0,                    // bias_y
3879         0,                    // bias_z
3880         0.95f,                // stillness_threshold
3881         MDEG_TO_RAD * 40.0f,  // stillness_mean_delta_limit [rad/sec]
3882         7.5e-5f,              // gyro_var_threshold [rad/sec]^2
3883         1.5e-5f,              // gyro_confidence_delta [rad/sec]^2
3884         4.5e-3f,              // accel_var_threshold [m/sec^2]^2
3885         9.0e-4f,              // accel_confidence_delta [m/sec^2]^2
3886         5.0f,                 // mag_var_threshold [uTesla]^2
3887         1.0f,                 // mag_confidence_delta [uTesla]^2
3888         1.5f,                 // temperature_delta_limit_celsius
3889         true                  // gyro_calibration_enable
3890     };
3891     // [NOTE 1]: 'max_still_duration_nanos' is set to 5.9 seconds to achieve a
3892     // max stillness period of 6.0 seconds and avoid buffer boundary conditions
3893     // that could push the max stillness to the next multiple of the analysis
3894     // window length (i.e., 7.5 seconds).
3895     gyroCalInit(&mTask.gyro_cal, &gyro_cal_parameters);
3896 
3897 #ifdef OVERTEMPCAL_ENABLED
3898     // Initializes the gyroscope over-temperature offset compensation algorithm.
3899     const struct OverTempCalParameters gyro_otc_parameters = {
3900         MSEC_TO_NANOS(500),    // min_temp_update_period_nanos
3901         DAYS_TO_NANOS(2),      // age_limit_nanos
3902         0.75f,                 // delta_temp_per_bin
3903         40.0f * MDEG_TO_RAD,   // jump_tolerance
3904         50.0f * MDEG_TO_RAD,   // outlier_limit
3905         80.0f * MDEG_TO_RAD,   // temp_sensitivity_limit
3906         3.0e3f * MDEG_TO_RAD,  // sensor_intercept_limit
3907         0.1f * MDEG_TO_RAD,    // significant_offset_change
3908         5,                     // min_num_model_pts
3909         true                   // over_temp_enable
3910     };
3911     overTempCalInit(&mTask.over_temp_gyro_cal, &gyro_otc_parameters);
3912 
3913 #endif  // OVERTEMPCAL_ENABLED
3914 #endif  // GYRO_CAL_ENABLED
3915 
3916 #ifdef MAG_SLAVE_PRESENT
3917     const struct MagCalParameters mag_cal_parameters = {
3918         3000000,  // min_batch_window_in_micros
3919         0.0f,     // x_bias
3920         0.0f,     // y_bias
3921         0.0f,     // z_bias
3922         1.0f,     // c00
3923         0.0f,     // c01
3924         0.0f,     // c02
3925         0.0f,     // c10
3926         1.0f,     // c11
3927         0.0f,     // c12
3928         0.0f,     // c20
3929         0.0f,     // c21
3930         1.0f      // c22
3931     };
3932 
3933     // Initializes the magnetometer offset calibration algorithm with diversity
3934     // checker.
3935     const struct DiversityCheckerParameters mag_diversity_parameters = {
3936         6.0f,    // var_threshold
3937         10.0f,   // max_min_threshold
3938         48.0f,   // local_field
3939         0.5f,    // threshold_tuning_param
3940         2.552f,  // max_distance_tuning_param
3941         8,       // min_num_diverse_vectors
3942         1        // max_num_max_distance
3943     };
3944     initMagCal(&mTask.moc, &mag_cal_parameters, &mag_diversity_parameters);
3945 #endif  // MAG_SLAVE_PRESENT
3946 
3947     slabSize = sizeof(struct TripleAxisDataEvent) +
3948                MAX_NUM_COMMS_EVENT_SAMPLES * sizeof(struct TripleAxisDataPoint);
3949 
3950     // each event has 15 samples, with 7 bytes per sample from the fifo.
3951     // the fifo size is 1K.
3952     // 20 slabs because some slabs may only hold 1-2 samples.
3953     // XXX: this consumes too much memeory, need to optimize
3954     T(mDataSlab) = slabAllocatorNew(slabSize, 4, 20);
3955     if (!T(mDataSlab)) {
3956         ERROR_PRINT("slabAllocatorNew() failed\n");
3957         return false;
3958     }
3959     T(mWbufCnt) = 0;
3960     T(mRegCnt) = 0;
3961 #ifdef BMI160_USE_I2C
3962     T(cReg) = 0;
3963 #endif
3964     T(spiInUse) = false;
3965 
3966     T(interrupt_enable_0) = 0x00;
3967     T(interrupt_enable_2) = 0x00;
3968 
3969     // initialize the last bmi160 time to be ULONG_MAX, so that we know it's
3970     // not valid yet.
3971     T(last_sensortime) = 0;
3972     T(frame_sensortime) = ULONG_LONG_MAX;
3973 
3974     // it's ok to leave interrupt open all the time.
3975     enableInterrupt(T(Int1), T(Irq1), &T(Isr1));
3976     enableInterrupt(T(Int2), T(Irq2), &T(Isr2));
3977 
3978     return true;
3979 }
3980 
3981 static void endTask(void)
3982 {
3983     TDECL();
3984 #ifdef MAG_SLAVE_PRESENT
3985     magCalDestroy(&mTask.moc);
3986 #endif
3987 #ifdef ACCEL_CAL_ENABLED
3988     accelCalDestroy(&mTask.acc);
3989 #endif
3990     slabAllocatorDestroy(T(mDataSlab));
3991 #ifndef BMI160_USE_I2C
3992     spiMasterRelease(mTask.spiDev);
3993 #endif
3994 
3995     // disable and release interrupt.
3996     disableInterrupt(mTask.Int1, mTask.Irq1, &mTask.Isr1);
3997     disableInterrupt(mTask.Int2, mTask.Irq2, &mTask.Isr2);
3998     gpioRelease(mTask.Int1);
3999     gpioRelease(mTask.Int2);
4000 }
4001 
4002 /**
4003  * Parse BMI160 FIFO frame without side effect.
4004  *
4005  * The major purpose of this function is to determine if FIFO content is received completely (start
4006  * to see invalid headers). If not, return the pointer to the beginning last incomplete frame so
4007  * additional read can use this pointer as start of read buffer.
4008  *
4009  * @param buf  buffer location
4010  * @param size size of data to be parsed
4011  *
4012  * @return NULL if the FIFO is received completely; or pointer to the beginning of last incomplete
4013  * frame for additional read.
4014  */
4015 static uint8_t* shallowParseFrame(uint8_t * buf, int size) {
4016     int i = 0;
4017     int iLastFrame = 0; // last valid frame header index
4018 
4019     DEBUG_PRINT_IF(DBG_SHALLOW_PARSE, "spf start %p: %x %x %x\n", buf, buf[0], buf[1], buf[2]);
4020     while (size > 0) {
4021         int fh_mode, fh_param;
4022         iLastFrame = i;
4023 
4024         if (buf[i] == BMI160_FRAME_HEADER_INVALID) {
4025             // no more data
4026             DEBUG_PRINT_IF(DBG_SHALLOW_PARSE, "spf:at%d=0x80\n", iLastFrame);
4027             return NULL;
4028         } else if (buf[i] == BMI160_FRAME_HEADER_SKIP) {
4029             // artifically added nop frame header, skip
4030             DEBUG_PRINT_IF(DBG_SHALLOW_PARSE, "at %d, skip header\n", i);
4031             i++;
4032             size--;
4033             continue;
4034         }
4035 
4036         //++frame_num;
4037 
4038         fh_mode = buf[i] >> 6;
4039         fh_param = (buf[i] >> 2) & 0xf;
4040 
4041         i++;
4042         size--;
4043 
4044         if (fh_mode == 1) {
4045             // control frame.
4046             if (fh_param == 0) {
4047                 // skip frame, we skip it (1 byte)
4048                 i++;
4049                 size--;
4050                 DEBUG_PRINT_IF(DBG_SHALLOW_PARSE, "at %d, a skip frame\n", iLastFrame);
4051             } else if (fh_param == 1) {
4052                 // sensortime frame  (3 bytes)
4053                 i += 3;
4054                 size -= 3;
4055                 DEBUG_PRINT_IF(DBG_SHALLOW_PARSE, "at %d, a sensor_time frame\n", iLastFrame);
4056             } else if (fh_param == 2) {
4057                 // fifo_input config frame (1byte)
4058                 i++;
4059                 size--;
4060                 DEBUG_PRINT_IF(DBG_SHALLOW_PARSE, "at %d, a fifo cfg frame\n", iLastFrame);
4061             } else {
4062                 size = 0; // drop this batch
4063                 DEBUG_PRINT_IF(DBG_SHALLOW_PARSE, "Invalid fh_param in control frame!!\n");
4064                 // mark invalid
4065                 buf[iLastFrame] = BMI160_FRAME_HEADER_INVALID;
4066                 return NULL;
4067             }
4068         } else if (fh_mode == 2) {
4069             // regular frame, dispatch data to each sensor's own fifo
4070             if (fh_param & 4) { // have mag data
4071                 i += 8;
4072                 size -= 8;
4073             }
4074             if (fh_param & 2) { // have gyro data
4075                 i += 6;
4076                 size -= 6;
4077             }
4078             if (fh_param & 1) { // have accel data
4079                 i += 6;
4080                 size -= 6;
4081             }
4082             DEBUG_PRINT_IF(DBG_SHALLOW_PARSE, "at %d, a reg frame acc %d, gyro %d, mag %d\n",
4083                        iLastFrame, fh_param &1 ? 1:0, fh_param&2?1:0, fh_param&4?1:0);
4084         } else {
4085             size = 0; // drop the rest of batch
4086             DEBUG_PRINT_IF(DBG_SHALLOW_PARSE, "spf: Invalid fh_mode %d!!\n", fh_mode);
4087             //mark invalid
4088             buf[iLastFrame] = BMI160_FRAME_HEADER_INVALID;
4089             return NULL;
4090         }
4091     }
4092 
4093     // there is a partial frame, return where to write next chunck of data
4094     DEBUG_PRINT_IF(DBG_SHALLOW_PARSE, "partial frame ends %p\n", buf + iLastFrame);
4095     return buf + iLastFrame;
4096 }
4097 
4098 /**
4099  * Intialize the first read of chunked SPI read sequence.
4100  *
4101  * @param index starting index of the txrxBuffer in which the data will be write into.
4102  */
4103 static void chunkedReadInit_(TASK, int index, int size) {
4104 
4105     if (GET_STATE() != SENSOR_INT_1_HANDLING) {
4106         ERROR_PRINT("chunkedReadInit in wrong mode");
4107         return;
4108     }
4109 
4110     if (T(mRegCnt)) {
4111         //chunked read are always executed as a single command. This should never happen.
4112         ERROR_PRINT("SPI queue not empty at chunkedReadInit, regcnt = %d", T(mRegCnt));
4113         // In case it did happen, we do not want to write crap to BMI160.
4114         T(mRegCnt) = 0;
4115     }
4116 
4117     T(mWbufCnt) = index;
4118     if (T(mWbufCnt) > FIFO_READ_SIZE) {
4119         // drop data to prevent bigger issue
4120         T(mWbufCnt) = 0;
4121     }
4122     T(chunkReadSize) = size > CHUNKED_READ_SIZE ? size : CHUNKED_READ_SIZE;
4123 
4124     DEBUG_PRINT_IF(DBG_CHUNKED, "crd %d>>%d\n", T(chunkReadSize), index);
4125     SPI_READ(BMI160_REG_FIFO_DATA, T(chunkReadSize), &T(dataBuffer));
4126     spiBatchTxRx(&T(mode), chunkedReadSpiCallback, _task, __FUNCTION__);
4127 }
4128 
4129 /**
4130  * Chunked SPI read callback.
4131  *
4132  * Handles the chunked read logic: issue additional read if necessary, or calls sensorSpiCallback()
4133  * if the entire FIFO is read.
4134  *
4135  * @param cookie extra data
4136  * @param err    error
4137  *
4138  * @see sensorSpiCallback()
4139  */
4140 static void chunkedReadSpiCallback(void *cookie, int err) {
4141     TASK = (_Task*) cookie;
4142 
4143     T(spiInUse) = false;
4144     DEBUG_PRINT_IF(err !=0 || GET_STATE() != SENSOR_INT_1_HANDLING,
4145             "crcb,e:%d,s:%d", err, (int)GET_STATE());
4146     bool int1 = gpioGet(T(Int1));
4147     if (err != 0) {
4148         DEBUG_PRINT_IF(DBG_CHUNKED, "spi err, crd retry");
4149         // read full fifo length to be safe
4150         chunkedReadInit(0, FIFO_READ_SIZE);
4151         return;
4152     }
4153 
4154     *T(dataBuffer) = BMI160_FRAME_HEADER_SKIP; // fill the 0x00/0xff hole at the first byte
4155     uint8_t* end = shallowParseFrame(T(dataBuffer), T(chunkReadSize));
4156 
4157     if (end == NULL) {
4158         // if interrupt is still set after read for some reason, set the pending interrupt
4159         // to handle it immediately after data is handled.
4160         T(pending_int[0]) = T(pending_int[0]) || int1;
4161 
4162         // recover the buffer and valid data size to make it looks like a single read so that
4163         // real frame parse works properly
4164         T(dataBuffer) = T(txrxBuffer);
4165         T(xferCnt) = FIFO_READ_SIZE;
4166         sensorSpiCallback(cookie, err);
4167     } else {
4168         DEBUG_PRINT_IF(DBG_CHUNKED, "crd cont");
4169         chunkedReadInit(end - T(txrxBuffer), CHUNKED_READ_SIZE);
4170     }
4171 }
4172 
4173 /**
4174  * Initiate read of sensor fifo.
4175  *
4176  * If task is in idle state, init chunked FIFO read; otherwise, submit an interrupt message or mark
4177  * the read pending depending if it is called in interrupt context.
4178  *
4179  * @param isInterruptContext true if called from interrupt context; false otherwise.
4180  *
4181  */
4182 static void initiateFifoRead_(TASK, bool isInterruptContext) {
4183     if (trySwitchState(SENSOR_INT_1_HANDLING)) {
4184         // estimate first read size to be watermark + 1 more sample + some extra
4185         int firstReadSize = T(watermark) * 4 + 32; // 1+6+6+8+1+3 + extra = 25 + extra = 32
4186         if (firstReadSize < CHUNKED_READ_SIZE) {
4187             firstReadSize = CHUNKED_READ_SIZE;
4188         }
4189         chunkedReadInit(0, firstReadSize);
4190     } else {
4191         if (isInterruptContext) {
4192             // called from interrupt context, queue event
4193             if (!osEnqueuePrivateEvt(EVT_SENSOR_INTERRUPT_1, _task, NULL, T(tid)))
4194                 ERROR_PRINT("initiateFifoRead_: osEnqueuePrivateEvt() failed\n");
4195         } else {
4196             // non-interrupt context, set pending flag, so next time it will be picked up after
4197             // switching back to idle.
4198             // Note: even if we are still in SENSOR_INT_1_HANDLING, the SPI may already finished and
4199             // we need to issue another SPI read to get the latest status.
4200             T(pending_int[0]) = true;
4201         }
4202     }
4203 }
4204 
4205 /**
4206  * Calculate fifo size using normalized input.
4207  *
4208  * @param iPeriod normalized period vector
4209  * @param iLatency normalized latency vector
4210  * @param factor vector that contains size factor for each sensor
4211  * @param n size of the vectors
4212  *
4213  * @return max size of FIFO to guarantee latency requirements of all sensors or SIZE_MAX if no
4214  * sensor is active.
4215  */
4216 static size_t calcFifoSize(const int* iPeriod, const int* iLatency, const int* factor, int n) {
4217     int i;
4218 
4219     int minLatency = INT_MAX;
4220     for (i = 0; i < n; i++) {
4221         if (iLatency[i] > 0) {
4222             minLatency = iLatency[i] < minLatency ? iLatency[i] : minLatency;
4223         }
4224     }
4225     DEBUG_PRINT_IF(DBG_WM_CALC, "cfifo: min latency %d unit", minLatency);
4226 
4227     bool anyActive = false;
4228     size_t s = 0;
4229     size_t head = 0;
4230     for (i = 0; i < n; i++) {
4231         if (iPeriod[i] > 0) {
4232             anyActive = true;
4233             size_t t = minLatency / iPeriod[i];
4234             head = t > head ? t : head;
4235             s += t * factor[i];
4236             DEBUG_PRINT_IF(DBG_WM_CALC, "cfifo %d: s += %d * %d, head = %d", i, t, factor[i], head);
4237         }
4238     }
4239 
4240     return anyActive ? head + s : SIZE_MAX;
4241 }
4242 
4243 /**
4244  * Calculate the watermark setting from sensor registration information
4245  *
4246  * It is assumed that all sensor periods share a common denominator (true for BMI160) and the
4247  * latency of sensor will be lower bounded by its sampling period.
4248  *
4249  * @return watermark register setting
4250  */
4251 static uint8_t calcWatermark2_(TASK) {
4252     int period[] = {-1, -1, -1};
4253     int latency[] = {-1, -1, -1};
4254     const int factor[] = {6, 6, 8};
4255     int i;
4256 
4257     for (i = FIRST_CONT_SENSOR; i < NUM_CONT_SENSOR; ++i) {
4258         if (T(sensors[i]).configed && T(sensors[i]).latency != SENSOR_LATENCY_NODATA) {
4259             period[i - ACC] = SENSOR_HZ((float)WATERMARK_MAX_SENSOR_RATE) / T(sensors[i]).rate;
4260             latency[i - ACC] = U64_DIV_BY_U64_CONSTANT(
4261                     T(sensors[i]).latency + WATERMARK_TIME_UNIT_NS/2, WATERMARK_TIME_UNIT_NS);
4262             DEBUG_PRINT_IF(DBG_WM_CALC, "cwm2 %d: f %dHz, l %dus => T %d unit, L %d unit",
4263                     i, (int) T(sensors[i]).rate/1024,
4264                     (int) U64_DIV_BY_U64_CONSTANT(T(sensors[i]).latency, 1000),
4265                     period[i-ACC], latency[i-ACC]);
4266         }
4267     }
4268 
4269 
4270     size_t watermark = calcFifoSize(period, latency, factor, NUM_CONT_SENSOR) / 4;
4271     DEBUG_PRINT_IF(DBG_WM_CALC, "cwm2: wm = %d", watermark);
4272     watermark = watermark < WATERMARK_MIN ? WATERMARK_MIN : watermark;
4273     watermark = watermark > WATERMARK_MAX ? WATERMARK_MAX : watermark;
4274 
4275     return watermark;
4276 }
4277 
4278 static bool dumpBinaryPutC(void* p, char c) {
4279     *(*(char**)p)++ = c;
4280     return true;
4281 }
4282 
4283 static uint32_t cvprintf_ellipsis(printf_write_c writeF, void* writeD, const char* fmtStr, ...) {
4284     va_list vl;
4285     uint32_t ret;
4286 
4287     va_start(vl, fmtStr);
4288     ret = cvprintf(writeF, 0, writeD, fmtStr, vl);
4289     va_end(vl);
4290 
4291     return ret;
4292 }
4293 
4294 static void dumpBinary(void* buf, unsigned int address, size_t size) {
4295     size_t i, j;
4296     char buffer[5+16*3+1+2]; //5: address, 3:each byte+space, 1: middle space, 1: \n and \0
4297     char* p;
4298 
4299     for (i = 0; i < size; ) {
4300         p = buffer;
4301         cvprintf_ellipsis(dumpBinaryPutC, &p, "%08x:", address);
4302         for (j = 0; j < 0x10 && i < size; ++i, ++j) {
4303             if (j == 0x8) {
4304                 *p++ = ' ';
4305             }
4306             cvprintf_ellipsis(dumpBinaryPutC, &p, " %02x", ((unsigned char *)buf)[i]);
4307         }
4308         *p = '\0';
4309 
4310         osLog(LOG_INFO, "%s\n", buffer);
4311         address += 0x10;
4312     }
4313 }
4314 
4315 #ifdef OVERTEMPCAL_ENABLED
4316 static void handleOtcGyroConfig_(TASK, const struct AppToSensorHalDataPayload *data) {
4317     const struct GyroOtcData *d = data->gyroOtcData;
4318 
4319     INFO_PRINT("gyrCfgData otc-data: off %d %d %d, t %d, s %d %d %d, i %d %d %d",
4320             (int)(d->lastOffset[0]), (int)(d->lastOffset[1]), (int)(d->lastOffset[2]),
4321             (int)(d->lastTemperature),
4322             (int)(d->sensitivity[0]), (int)(d->sensitivity[1]), (int)(d->sensitivity[2]),
4323             (int)(d->intercept[0]), (int)(d->intercept[1]), (int)(d->intercept[2]));
4324 
4325     overTempCalSetModel(&T(over_temp_gyro_cal), d->lastOffset, d->lastTemperature,
4326                         sensorGetTime(), d->sensitivity, d->intercept, true /*jumpstart*/);
4327 }
4328 
4329 static bool sendOtcGyroUpdate_(TASK) {
4330     int step = 0;
4331     if (atomicCmpXchgByte(&T(otcGyroUpdateBuffer).lock, false, true)) {
4332         ++step;
4333         //fill HostIntfDataBuffer header
4334         struct HostIntfDataBuffer *p = (struct HostIntfDataBuffer *)(&T(otcGyroUpdateBuffer));
4335         p->sensType = SENS_TYPE_INVALID;
4336         p->length = sizeof(struct AppToSensorHalDataPayload) + sizeof(struct GyroOtcData);
4337         p->dataType = HOSTINTF_DATA_TYPE_APP_TO_SENSOR_HAL;
4338         p->interrupt = NANOHUB_INT_NONWAKEUP;
4339 
4340         //fill AppToSensorHalDataPayload header
4341         struct AppToSensorHalDataBuffer *q = (struct AppToSensorHalDataBuffer *)p;
4342         q->payload.size = sizeof(struct GyroOtcData);
4343         q->payload.type = HALINTF_TYPE_GYRO_OTC_DATA; // bit-or EVENT_TYPE_BIT_DISCARDABLE
4344                                                       // to make it discardable
4345 
4346         // fill payload data
4347         struct GyroOtcData *data = q->payload.gyroOtcData;
4348         uint64_t timestamp;
4349         overTempCalGetModel(&T(over_temp_gyro_cal), data->lastOffset, &data->lastTemperature,
4350                             &timestamp, data->sensitivity, data->intercept);
4351         if (osEnqueueEvtOrFree(EVT_APP_TO_SENSOR_HAL_DATA, // bit-or EVENT_TYPE_BIT_DISCARDABLE
4352                                                           // to make event discardable
4353                                p, unlockOtcGyroUpdateBuffer)) {
4354             T(otcGyroUpdateBuffer).sendToHostRequest = false;
4355             ++step;
4356         }
4357     }
4358     DEBUG_PRINT("otc gyro update, finished at step %d", step);
4359     return step == 2;
4360 }
4361 
4362 static void unlockOtcGyroUpdateBuffer(void *event) {
4363     atomicXchgByte(&(((struct OtcGyroUpdateBuffer*)(event))->lock), false);
4364 }
4365 #endif // OVERTEMPCAL_ENABLED
4366 
4367 INTERNAL_APP_INIT(BMI160_APP_ID, BMI160_APP_VERSION, startTask, endTask, handleEvent);
4368