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