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