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