orientation.c revision ae081f1f47013ddf08e5af685b9f6d02ac76421b
1960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian#include <stdlib.h>
2960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian#include <string.h>
3960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian#include <timer.h>
4960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian#include <heap.h>
5960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian#include <plat/inc/rtc.h>
6960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian#include <plat/inc/syscfg.h>
7960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian#include <hostIntf.h>
87062239aaa63d8a5260d7d325483755acbb8c35cBen Fennema#include <nanohubPacket.h>
9ae081f1f47013ddf08e5af685b9f6d02ac76421bDmitry Grinberg#include <floatRt.h>
10960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
11960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian#include <seos.h>
12960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian#include <accelerometer.h>
13960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
14960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian#include <nanohub_math.h>
15960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian#include <fusion/fusion.h>
16960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian#include <sensors.h>
17960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian#include <limits.h>
18e0e5b567748b8d46f60ede2ff12c4b2358ffe0dbZhengyin Qian#include <slab.h>
19960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
20960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian#define MAX_NUM_COMMS_EVENT_SAMPLES 15
21c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian#define FIFO_MARGIN 10
22c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian#define MAX_NUM_SAMPLES         (MAX_NUM_COMMS_EVENT_SAMPLES + FIFO_MARGIN)
23c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian#define MAX_NUM_RAW_DATA_SAMPLES  50000000000ull
2418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian#define EVT_SENSOR_ACC_DATA_RDY         sensorGetMyEventType(SENS_TYPE_ACCEL)
2518040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian#define EVT_SENSOR_GYR_DATA_RDY         sensorGetMyEventType(SENS_TYPE_GYRO)
2618040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian#define EVT_SENSOR_MAG_DATA_RDY         sensorGetMyEventType(SENS_TYPE_MAG)
2718040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
2818040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian#define kGravityEarth 9.80665f
2918040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian#define DEFAULT_GYRO_RATE_HZ    SENSOR_HZ(100.0f)
3018040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian#define DEFAULT_MAG_RATE_HZ     SENSOR_HZ(50.0f)
31960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
321be10b6751f50675307716747bd4d729d9e7aff5Ben Fennemaenum
331be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema{
341be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema    FUSION_FLAG_ENABLED             = 0x01,
351be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema    FUSION_FLAG_INITIALIZED         = 0x08,
361be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema    FUSION_FLAG_GAME_ENABLED        = 0x10,
371be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema    FUSION_FLAG_GAME_INITIALIZED    = 0x20
38960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian};
39960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
4018040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qianenum RawSensorType
4118040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian{
4218040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    ACC,
4318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    GYR,
4418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    MAG,
4518040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    NUM_OF_RAW_SENSOR
4618040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian};
4718040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
4818040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qianenum FusionSensorType
491be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema{
5018040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    ORIENT,
5118040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    GRAVITY,
5218040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    GEOMAG,
5318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    LINEAR,
5418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    GAME,
5518040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    ROTAT,
5618040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    NUM_OF_FUSION_SENSOR
571be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema};
581be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema
591be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema
6018040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qianstruct FusionSensorSample {
61960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian    uint64_t time;
62960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian    float x, y, z;
63960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian};
64960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
6518040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qianstruct FusionSensor {
66960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian    uint32_t handle;
6718040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    struct TripleAxisDataEvent *ev;
68c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian    uint64_t prev_time;
6918040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    uint64_t latency;
7018040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    uint32_t rate;
7118040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    bool active;
7218040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    bool use_gyr_data;
7318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    bool use_mag_data;
7418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    uint8_t idx;
7518040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian};
7618040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
7718040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qianstruct FusionTask {
7818040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    uint32_t tid;
791be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema    uint32_t accelHandle;
801be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema    uint32_t gyroHandle;
811be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema    uint32_t magHandle;
82960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
83960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian    struct Fusion fusion;
8418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    struct Fusion game;
85960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
8618040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    struct FusionSensor sensors[NUM_OF_FUSION_SENSOR];
8718040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    struct FusionSensorSample samples[NUM_OF_RAW_SENSOR][MAX_NUM_SAMPLES];
8818040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    size_t sample_indices[NUM_OF_RAW_SENSOR];
8918040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    size_t sample_counts[NUM_OF_RAW_SENSOR];
9018040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    uint32_t counters[NUM_OF_RAW_SENSOR];
9118040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    uint64_t ResamplePeriodNs[NUM_OF_RAW_SENSOR];
9218040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    uint64_t last_time[NUM_OF_RAW_SENSOR];
9318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    struct TripleAxisDataPoint last_sample[NUM_OF_RAW_SENSOR];
94960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
95960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian    uint64_t last_gyro_time;
96960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian    uint64_t last_acc_time;
97960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian    uint32_t flags;
98960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
99c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian    uint32_t raw_sensor_rate[NUM_OF_RAW_SENSOR];
100c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian    uint64_t raw_sensor_latency;
101c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian
10218040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    uint8_t acc_cnt;
10318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    uint8_t gyr_cnt;
10418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    uint8_t mag_cnt;
105960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian};
106960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
10718040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qianstatic uint32_t FusionRates[] = {
108960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian    SENSOR_HZ(12.5f),
109960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian    SENSOR_HZ(25.0f),
110960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian    SENSOR_HZ(50.0f),
111960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian    SENSOR_HZ(100.0f),
112960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian    SENSOR_HZ(200.0f),
113960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian    0,
114960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian};
115960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
11618040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qianstatic struct FusionTask mTask;
11718040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qianstatic const struct SensorInfo mSi[NUM_OF_FUSION_SENSOR] =
11864eb1702a319ad4bbc181ed1e5af0703aea7ea22Zhengyin Qian{
119f45dac303dc3756b80036a68f23cdc48f34d870eBen Fennema    {"Orientation",                 FusionRates, SENS_TYPE_ORIENTATION,     NUM_AXIS_THREE, NANOHUB_INT_NONWAKEUP,  20 },
120f45dac303dc3756b80036a68f23cdc48f34d870eBen Fennema    {"Gravity",                     FusionRates, SENS_TYPE_GRAVITY,         NUM_AXIS_THREE, NANOHUB_INT_NONWAKEUP,  20 },
121f45dac303dc3756b80036a68f23cdc48f34d870eBen Fennema    {"Geomagnetic Rotation Vector", FusionRates, SENS_TYPE_GEO_MAG_ROT_VEC, NUM_AXIS_THREE, NANOHUB_INT_NONWAKEUP,  20 },
122f45dac303dc3756b80036a68f23cdc48f34d870eBen Fennema    {"Linear Acceleration",         FusionRates, SENS_TYPE_LINEAR_ACCEL,    NUM_AXIS_THREE, NANOHUB_INT_NONWAKEUP,  20 },
123f45dac303dc3756b80036a68f23cdc48f34d870eBen Fennema    {"Game Rotation Vector",        FusionRates, SENS_TYPE_GAME_ROT_VECTOR, NUM_AXIS_THREE, NANOHUB_INT_NONWAKEUP, 300 },
124f45dac303dc3756b80036a68f23cdc48f34d870eBen Fennema    {"Rotation Vector",             FusionRates, SENS_TYPE_ROTATION_VECTOR, NUM_AXIS_THREE, NANOHUB_INT_NONWAKEUP,  20 },
12564eb1702a319ad4bbc181ed1e5af0703aea7ea22Zhengyin Qian};
126960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
127e0e5b567748b8d46f60ede2ff12c4b2358ffe0dbZhengyin Qianstatic struct SlabAllocator *mDataSlab;
128e0e5b567748b8d46f60ede2ff12c4b2358ffe0dbZhengyin Qian
129e0e5b567748b8d46f60ede2ff12c4b2358ffe0dbZhengyin Qianstatic void dataEvtFree(void *ptr)
130960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian{
131e0e5b567748b8d46f60ede2ff12c4b2358ffe0dbZhengyin Qian    slabAllocatorFree(mDataSlab, ptr);
132960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian}
133960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
13418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qianstatic void fillSamples(struct TripleAxisDataEvent *ev, enum RawSensorType index)
135960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian{
13618040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    bool bad_timestamp;
13718040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    size_t i, w, n, num_samples;
13818040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    struct TripleAxisDataPoint *curr_sample, *next_sample;
139f45dac303dc3756b80036a68f23cdc48f34d870eBen Fennema    uint32_t counter;
140f45dac303dc3756b80036a68f23cdc48f34d870eBen Fennema    uint64_t ResamplePeriodNs, curr_time, next_time;
14118040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    uint64_t sample_spacing_ns;
14218040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    float weight_next;
14318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
14418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    if (index == GYR && mTask.gyr_cnt == 0) {
145960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian        return;
146960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian    }
14718040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    if (index == MAG && mTask.mag_cnt == 0) {
148960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian        return;
149960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian    }
150960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
15118040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    n = mTask.sample_counts[index];
15218040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    i = mTask.sample_indices[index];
15318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    counter = mTask.counters[index];
15418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    ResamplePeriodNs = mTask.ResamplePeriodNs[index];
15518040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    w = (mTask.sample_indices[index] + n) % MAX_NUM_SAMPLES;
15618040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
15718040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    // check if this sensor was used before
15818040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    if (mTask.last_time[index] == ULONG_LONG_MAX) {
15918040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        curr_sample = ev->samples;
16018040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        next_sample = curr_sample + 1;
161f45dac303dc3756b80036a68f23cdc48f34d870eBen Fennema        num_samples = ev->samples[0].firstSample.numSamples;
16218040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        curr_time = ev->referenceTime;
163960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian    } else {
16418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        curr_sample = &mTask.last_sample[index];
16518040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        next_sample = ev->samples;
166f45dac303dc3756b80036a68f23cdc48f34d870eBen Fennema        num_samples = ev->samples[0].firstSample.numSamples + 1;
16718040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        curr_time = mTask.last_time[index];
16818040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    }
169960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
17018040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    while (num_samples > 1) {
171960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
17218040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        if (next_sample == ev->samples)
17318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            next_time = ev->referenceTime;
17418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        else
17518040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            next_time = curr_time + next_sample->deltaTime;
176960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
17718040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        // error handling for non-chronological accel timestamps
17818040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        sample_spacing_ns = (next_time > curr_time) ?  (next_time - curr_time) : 0;
179960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
18018040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        // This happens during BMI160 config changes
18118040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        bad_timestamp = (sample_spacing_ns > 10 * ResamplePeriodNs);
182960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
18318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        // Check to see if we need to move the interpolation window or
18418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        // interpolate
18518040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        if ((counter >= sample_spacing_ns) || bad_timestamp) {
18618040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            num_samples--;
18718040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            counter -= (bad_timestamp ? counter : sample_spacing_ns);
18818040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            curr_sample = next_sample;
18918040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            next_sample++;
190960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
191c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian            curr_time = next_time;
19218040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        } else {
193ae081f1f47013ddf08e5af685b9f6d02ac76421bDmitry Grinberg            weight_next = (float)counter / floatFromUint64(sample_spacing_ns);
19418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
19518040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            mTask.samples[index][w].x = curr_sample->x + weight_next *
19618040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian                (next_sample->x - curr_sample->x);
19718040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            mTask.samples[index][w].y = curr_sample->y + weight_next *
19818040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian                (next_sample->y - curr_sample->y);
19918040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            mTask.samples[index][w].z = curr_sample->z + weight_next *
20018040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian                (next_sample->z - curr_sample->z);
20118040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            mTask.samples[index][w].time = curr_time + counter;
20218040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
20318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            // Move the read index when buffer is full
20418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            if (++n > MAX_NUM_SAMPLES) {
20518040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian                n = MAX_NUM_SAMPLES;
20618040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
20718040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian                if (++i == MAX_NUM_SAMPLES) {
20818040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian                    i = 0;
20918040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian                }
21018040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            }
21118040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
21218040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            // Reset the write index
21318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            if (++w == MAX_NUM_SAMPLES) {
21418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian                w = 0;
21518040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            }
21618040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
21718040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            // Move to the next resample
21818040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            counter += ResamplePeriodNs;
219960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian        }
220960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian    }
22118040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
22218040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    mTask.sample_counts[index] = n;
22318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    mTask.sample_indices[index] = i;
22418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    mTask.counters[index] = counter;
22518040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    mTask.last_sample[index] = *curr_sample;
22618040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    mTask.last_time[index] = curr_time;
227960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian}
228960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
22918040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qianstatic void addSample(struct FusionSensor *mSensor, uint64_t time, float x, float y, float z)
230960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian{
2317062239aaa63d8a5260d7d325483755acbb8c35cBen Fennema    struct TripleAxisDataPoint *sample;
232c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian    uint32_t deltaTime = 0;
233e0e5b567748b8d46f60ede2ff12c4b2358ffe0dbZhengyin Qian
23418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    if (mSensor->ev == NULL) {
23518040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        mSensor->ev = slabAllocatorAlloc(mDataSlab);
23618040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        if (mSensor->ev == NULL) {
237e0e5b567748b8d46f60ede2ff12c4b2358ffe0dbZhengyin Qian            // slaballocation failed
238c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian            osLog(LOG_ERROR, "FUSION: Slab Allocation Failed\n");
239e0e5b567748b8d46f60ede2ff12c4b2358ffe0dbZhengyin Qian            return;
240e0e5b567748b8d46f60ede2ff12c4b2358ffe0dbZhengyin Qian        }
241f45dac303dc3756b80036a68f23cdc48f34d870eBen Fennema        mSensor->ev->samples[0].firstSample.numSamples = 0;
24218040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        mSensor->ev->referenceTime = time;
243c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian        mSensor->prev_time = time;
244960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian    }
245960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
246f45dac303dc3756b80036a68f23cdc48f34d870eBen Fennema    if (mSensor->ev->samples[0].firstSample.numSamples >= MAX_NUM_COMMS_EVENT_SAMPLES) {
247960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian        osLog(LOG_ERROR, "BAD_INDEX\n");
248960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian        return;
249960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian    }
250960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
251f45dac303dc3756b80036a68f23cdc48f34d870eBen Fennema    sample = &mSensor->ev->samples[mSensor->ev->samples[0].firstSample.numSamples++];
252e0e5b567748b8d46f60ede2ff12c4b2358ffe0dbZhengyin Qian
253c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian    if (mSensor->ev->samples[0].firstSample.numSamples > 1) {
254c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian        deltaTime = time - mSensor->prev_time;
255c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian        deltaTime = deltaTime < 0 ? 0 : deltaTime;
256e0e5b567748b8d46f60ede2ff12c4b2358ffe0dbZhengyin Qian        sample->deltaTime = deltaTime;
257c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian        mSensor->prev_time = time;
258c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian    }
259960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
260960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian    sample->x = x;
261960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian    sample->y = y;
262960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian    sample->z = z;
263960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
264f45dac303dc3756b80036a68f23cdc48f34d870eBen Fennema    if (mSensor->ev->samples[0].firstSample.numSamples == MAX_NUM_COMMS_EVENT_SAMPLES) {
26535339af82310e6a49884f5b845fb9557af360de7Zhengyin Qian        osEnqueueEvt(EVENT_TYPE_BIT_DISCARDABLE | sensorGetMyEventType(mSi[mSensor->idx].sensorType),
26635339af82310e6a49884f5b845fb9557af360de7Zhengyin Qian                mSensor->ev, dataEvtFree);
26718040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        mSensor->ev = NULL;
268960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian    }
269960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian}
270960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
271960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qianstatic void updateOutput(ssize_t last_accel_sample_index, uint64_t last_sensor_time)
272960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian{
27318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    struct Vec4 attitude;
27418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    struct Vec3 g, a;
27518040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    struct Mat33 R;
27618040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
27718040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    if (fusionHasEstimate(&mTask.game)) {
27818040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        if (mTask.sensors[GAME].active) {
27918040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            fusionGetAttitude(&mTask.game, &attitude);
28018040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            addSample(&mTask.sensors[GAME],
28118040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian                    last_sensor_time,
28218040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian                    attitude.x,
28318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian                    attitude.y,
28418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian                    attitude.z);
28518040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        }
28618040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
28718040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        if (mTask.sensors[GRAVITY].active) {
28818040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            fusionGetRotationMatrix(&mTask.game, &R);
28918040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            initVec3(&g, R.elem[0][2], R.elem[1][2], R.elem[2][2]);
29018040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            vec3ScalarMul(&g, kGravityEarth);
29118040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            addSample(&mTask.sensors[GRAVITY],
29218040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian                    last_sensor_time,
29318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian                    g.x, g.y, g.z);
29418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        }
29518040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    }
29618040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
297960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian    if (fusionHasEstimate(&mTask.fusion)) {
298960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian        fusionGetRotationMatrix(&mTask.fusion, &R);
299960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian        fusionGetAttitude(&mTask.fusion, &attitude);
300960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
30118040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        if (mTask.sensors[ORIENT].active) {
30218040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            // x, y, z = yaw, pitch, roll
30318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            static const float kRad2deg = 180.0f / M_PI;
30418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            float x = atan2f(-R.elem[0][1], R.elem[0][0]) * kRad2deg;
30518040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            float y = atan2f(-R.elem[1][2], R.elem[2][2]) * kRad2deg;
30618040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            float z = asinf(R.elem[0][2]) * kRad2deg;
30718040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
30818040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            if (x < 0.0f) {
30918040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian                x += 360.0f;
31018040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            }
31118040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
31218040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            addSample(&mTask.sensors[ORIENT],
31318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian                    last_sensor_time, x, y, z);
31418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        }
315960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
31618040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        if (mTask.sensors[GEOMAG].active) {
31718040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            addSample(&mTask.sensors[GEOMAG],
31818040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian                    last_sensor_time,
31918040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian                    attitude.x,
32018040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian                    attitude.y,
32118040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian                    attitude.z);
322960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian        }
323960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
32418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        if (mTask.sensors[ROTAT].active) {
32518040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            addSample(&mTask.sensors[ROTAT],
32618040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian                    last_sensor_time,
32718040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian                    attitude.x,
32818040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian                    attitude.y,
32918040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian                    attitude.z);
33018040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        }
33118040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
33218040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        if (last_accel_sample_index >= 0
33318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian                && mTask.sensors[LINEAR].active) {
33418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            initVec3(&g, R.elem[0][2], R.elem[1][2], R.elem[2][2]);
33518040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            vec3ScalarMul(&g, kGravityEarth);
33618040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            initVec3(&a,
33718040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian                    mTask.samples[0][last_accel_sample_index].x,
33818040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian                    mTask.samples[0][last_accel_sample_index].y,
33918040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian                    mTask.samples[0][last_accel_sample_index].z);
34018040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
34118040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            addSample(&mTask.sensors[LINEAR],
34218040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian                    mTask.samples[0][last_accel_sample_index].time,
34318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian                    a.x - g.x,
34418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian                    a.y - g.y,
34518040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian                    a.z - g.z);
34618040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        }
347960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian    }
348960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian}
349960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
350960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qianstatic void drainSamples()
351960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian{
35218040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    size_t i = mTask.sample_indices[ACC];
353960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian    size_t j = 0;
354960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian    size_t k = 0;
3551be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema    size_t which;
3561be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema    struct Vec3 a, w, m;
3571be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema    float dT;
3581be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema    uint64_t a_time, g_time, m_time;
3591be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema
36018040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    if (mTask.gyr_cnt > 0)
36118040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        j = mTask.sample_indices[GYR];
3621be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema
36318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    if (mTask.mag_cnt > 0)
36418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        k = mTask.sample_indices[MAG];
3651be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema
36618040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    while (mTask.sample_counts[ACC] > 0
36718040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            && (!mTask.gyr_cnt > 0 || mTask.sample_counts[GYR] > 0)
36818040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            && (!mTask.mag_cnt > 0 || mTask.sample_counts[MAG] > 0)) {
36918040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        a_time = mTask.samples[ACC][i].time;
37018040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        g_time = mTask.gyr_cnt > 0 ? mTask.samples[GYR][j].time
371960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian                            : ULONG_LONG_MAX;
37218040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        m_time = mTask.mag_cnt > 0 ? mTask.samples[MAG][k].time
373960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian                            : ULONG_LONG_MAX;
374960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
375960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian        // priority with same timestamp: gyro > acc > mag
376960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian        if (g_time <= a_time && g_time <= m_time) {
37718040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            which = GYR;
378960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian        } else if (a_time <= m_time) {
37918040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            which = ACC;
380960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian        } else {
38118040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            which = MAG;
382960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian        }
383960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
3841be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema        switch (which) {
38518040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        case ACC:
38618040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            initVec3(&a, mTask.samples[ACC][i].x, mTask.samples[ACC][i].y, mTask.samples[ACC][i].z);
38718040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
388ae081f1f47013ddf08e5af685b9f6d02ac76421bDmitry Grinberg            dT = floatFromUint64(mTask.samples[ACC][i].time - mTask.last_acc_time) * 1.0E-9f;
38918040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            mTask.last_acc_time = mTask.samples[ACC][i].time;
390960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
39118040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            if (mTask.flags & FUSION_FLAG_ENABLED)
39218040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian                fusionHandleAcc(&mTask.fusion, &a, dT);
393960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
39418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            if (mTask.flags & FUSION_FLAG_GAME_ENABLED)
39518040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian                fusionHandleAcc(&mTask.game, &a, dT);
396960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
39718040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            updateOutput(i, mTask.samples[ACC][i].time);
398960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
39918040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            --mTask.sample_counts[ACC];
4001be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema            if (++i == MAX_NUM_SAMPLES)
4011be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema                i = 0;
4021be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema            break;
40318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        case GYR:
40418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            initVec3(&w, mTask.samples[GYR][j].x, mTask.samples[GYR][j].y, mTask.samples[GYR][j].z);
405960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
406ae081f1f47013ddf08e5af685b9f6d02ac76421bDmitry Grinberg            dT = floatFromUint64(mTask.samples[GYR][j].time - mTask.last_gyro_time) * 1.0E-9f;
40718040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            mTask.last_gyro_time = mTask.samples[GYR][j].time;
408960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
40918040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            if (mTask.flags & FUSION_FLAG_ENABLED)
41018040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian                fusionHandleGyro(&mTask.fusion, &w, dT);
411960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
41218040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            if (mTask.flags & FUSION_FLAG_GAME_ENABLED)
41318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian                fusionHandleGyro(&mTask.game, &w, dT);
41418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
41518040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            --mTask.sample_counts[GYR];
4161be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema            if (++j == MAX_NUM_SAMPLES)
4171be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema                j = 0;
4181be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema            break;
41918040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        case MAG:
42018040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            initVec3(&m, mTask.samples[MAG][k].x, mTask.samples[MAG][k].y, mTask.samples[MAG][k].z);
421960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
4221be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema            fusionHandleMag(&mTask.fusion, &m);
423960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
42418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            --mTask.sample_counts[MAG];
4251be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema            if (++k == MAX_NUM_SAMPLES)
4261be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema                k = 0;
4271be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema            break;
428960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian        }
429960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian    }
430960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
43118040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    mTask.sample_indices[ACC] = i;
432960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
43318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    if (mTask.gyr_cnt > 0)
43418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        mTask.sample_indices[GYR] = j;
435960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
43618040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    if (mTask.mag_cnt > 0)
43718040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        mTask.sample_indices[MAG] = k;
438960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
43918040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    for (i = ORIENT; i < NUM_OF_FUSION_SENSOR; i++) {
44018040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        if (mTask.sensors[i].ev != NULL) {
44135339af82310e6a49884f5b845fb9557af360de7Zhengyin Qian            osEnqueueEvt(EVENT_TYPE_BIT_DISCARDABLE | sensorGetMyEventType(mSi[i].sensorType),
44235339af82310e6a49884f5b845fb9557af360de7Zhengyin Qian                    mTask.sensors[i].ev, dataEvtFree);
44318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            mTask.sensors[i].ev = NULL;
44418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        }
445960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian    }
446960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian}
447960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
448960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qianstatic void configureFusion()
449960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian{
45018040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    if (mTask.sensors[ORIENT].active
45118040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            || mTask.sensors[ROTAT].active
45218040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            || mTask.sensors[LINEAR].active
45318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            || mTask.sensors[GEOMAG].active) {
45418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        mTask.flags |= FUSION_FLAG_ENABLED;
45518040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        initFusion(&mTask.fusion,
45618040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian                (mTask.mag_cnt > 0 ? FUSION_USE_MAG : 0) |
45718040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian                (mTask.gyr_cnt > 0 ? FUSION_USE_GYRO : 0) |
45818040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian                ((mTask.flags & FUSION_FLAG_INITIALIZED) ? 0 : FUSION_REINITIALIZE));
45918040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        mTask.flags |= FUSION_FLAG_INITIALIZED;
46018040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    } else {
46118040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        mTask.flags &= ~FUSION_FLAG_ENABLED;
46218040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        mTask.flags &= ~FUSION_FLAG_INITIALIZED;
46318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    }
464960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian}
465960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
46618040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qianstatic void configureGame()
467960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian{
46818040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    if (mTask.sensors[GAME].active || mTask.sensors[GRAVITY].active) {
46918040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        mTask.flags |= FUSION_FLAG_GAME_ENABLED;
47018040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        initFusion(&mTask.game,
47118040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian                FUSION_USE_GYRO | ((mTask.flags & FUSION_FLAG_INITIALIZED) ? 0 : FUSION_REINITIALIZE));
47218040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        mTask.flags |= FUSION_FLAG_GAME_INITIALIZED;
47318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    } else {
47418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        mTask.flags &= ~FUSION_FLAG_GAME_ENABLED;
47518040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        mTask.flags &= ~FUSION_FLAG_GAME_INITIALIZED;
476960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian    }
477960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian}
478960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
479c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qianstatic void fusionSetRateAcc(void)
480960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian{
4811be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema    int i;
48218040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    if  (mTask.accelHandle == 0) {
48318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        mTask.sample_counts[ACC] = 0;
48418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        mTask.sample_indices[ACC] = 0;
48518040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        mTask.counters[ACC] = 0;
48618040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        mTask.last_time[ACC] = ULONG_LONG_MAX;
4871be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema        for (i=0; sensorFind(SENS_TYPE_ACCEL, i, &mTask.accelHandle) != NULL; i++) {
488c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian            if (sensorRequest(mTask.tid, mTask.accelHandle, mTask.raw_sensor_rate[ACC], mTask.raw_sensor_latency)) {
4891be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema                osEventSubscribe(mTask.tid, EVT_SENSOR_ACC_DATA_RDY);
4901be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema                break;
4911be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema            }
4921be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema        }
4931be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema    } else {
494c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian        sensorRequestRateChange(mTask.tid, mTask.accelHandle, mTask.raw_sensor_rate[ACC], mTask.raw_sensor_latency);
4951be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema    }
49618040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian}
49718040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
498c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qianstatic void fusionSetRateGyr(void)
49918040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian{
50018040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    int i;
5011be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema    if (mTask.gyroHandle == 0) {
50218040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        mTask.sample_counts[GYR] = 0;
50318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        mTask.sample_indices[GYR] = 0;
50418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        mTask.counters[GYR] = 0;
50518040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        mTask.last_time[GYR] = ULONG_LONG_MAX;
5061be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema        for (i=0; sensorFind(SENS_TYPE_GYRO, i, &mTask.gyroHandle) != NULL; i++) {
507c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian            if (sensorRequest(mTask.tid, mTask.gyroHandle, mTask.raw_sensor_rate[GYR], mTask.raw_sensor_latency)) {
5081be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema                osEventSubscribe(mTask.tid, EVT_SENSOR_GYR_DATA_RDY);
5091be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema                break;
5101be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema            }
5111be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema        }
5121be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema    } else {
513c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian        sensorRequestRateChange(mTask.tid, mTask.gyroHandle, mTask.raw_sensor_rate[GYR], mTask.raw_sensor_latency);
5141be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema    }
51518040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian}
51618040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
517c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qianstatic void fusionSetRateMag(void)
51818040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian{
51918040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    int i;
5201be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema    if (mTask.magHandle == 0) {
52118040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        mTask.sample_counts[MAG] = 0;
52218040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        mTask.sample_indices[MAG] = 0;
52318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        mTask.counters[MAG] = 0;
52418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        mTask.last_time[MAG] = ULONG_LONG_MAX;
5251be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema        for (i=0; sensorFind(SENS_TYPE_MAG, i, &mTask.magHandle) != NULL; i++) {
526c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian            if (sensorRequest(mTask.tid, mTask.magHandle, mTask.raw_sensor_rate[MAG], mTask.raw_sensor_latency)) {
5271be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema                osEventSubscribe(mTask.tid, EVT_SENSOR_MAG_DATA_RDY);
5281be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema                break;
5291be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema            }
5301be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema        }
5311be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema    } else {
532c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian        sensorRequestRateChange(mTask.tid, mTask.magHandle, mTask.raw_sensor_rate[MAG], mTask.raw_sensor_latency);
533c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian    }
534c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian}
535c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian
536c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qianstatic bool fusionSetRate(struct FusionSensor *mSensor, uint32_t rate, uint64_t latency)
537c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian{
538c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian
539c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian    int i;
540c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian    uint32_t max_rate = 0;
541c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian    uint32_t gyr_rate, mag_rate;
542c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian    uint32_t total_sample = 0;
543c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian
544c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian    mSensor->rate = rate;
545c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian    mSensor->latency = latency;
546c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian
547c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian    for (i = ORIENT; i < NUM_OF_FUSION_SENSOR; i++) {
548c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian        if (mTask.sensors[i].active) {
549c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian            max_rate = max_rate > mTask.sensors[i].rate ? max_rate : mTask.sensors[i].rate;
550c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian        }
551c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian    }
552c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian
553c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian    if (mTask.acc_cnt > 0) {
554c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian        mTask.ResamplePeriodNs[ACC] = (1000000000ull * 1024ull / max_rate);
555c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian        mTask.raw_sensor_rate[ACC] = max_rate;
556c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian        total_sample += mTask.raw_sensor_rate[ACC];
557c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian    }
558c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian
559c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian    if (mTask.gyr_cnt > 0) {
560c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian        mTask.ResamplePeriodNs[GYR] = (1000000000ull * 1024ull / max_rate);
561c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian        gyr_rate = max_rate > DEFAULT_GYRO_RATE_HZ ? max_rate : DEFAULT_GYRO_RATE_HZ;
562c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian        mTask.raw_sensor_rate[GYR] = gyr_rate;
563c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian        total_sample += mTask.raw_sensor_rate[GYR];
564c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian    }
565c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian
566c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian    if (mTask.mag_cnt > 0) {
567c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian        mag_rate = max_rate < DEFAULT_MAG_RATE_HZ ? max_rate : DEFAULT_MAG_RATE_HZ;
568c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian        mTask.ResamplePeriodNs[MAG] = (1000000000ull * 1024ull / mag_rate);
569c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian        mTask.raw_sensor_rate[MAG] = mag_rate;
570c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian        total_sample += mTask.raw_sensor_rate[MAG];
571c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian    }
572c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian
573c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian    mTask.raw_sensor_latency = (total_sample == 0 ? 0 : MAX_NUM_RAW_DATA_SAMPLES * 1024ull / total_sample);
574c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian    for (i = ORIENT; i < NUM_OF_FUSION_SENSOR; i++) {
575c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian        if (mTask.sensors[i].active) {
576c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian            mTask.raw_sensor_latency = mTask.sensors[i].latency < mTask.raw_sensor_latency ?
577c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian                mTask.sensors[i].latency : mTask.raw_sensor_latency;
578c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian        }
57918040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    }
580c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian
581c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian    if (mTask.acc_cnt > 0)
582c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian        fusionSetRateAcc();
583c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian    if (mTask.gyr_cnt > 0)
584c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian        fusionSetRateGyr();
585c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian    if (mTask.mag_cnt > 0)
586c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian        fusionSetRateMag();
587c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian    if (mSensor->rate > 0)
588c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian        sensorSignalInternalEvt(mSensor->handle, SENSOR_INTERNAL_EVT_RATE_CHG, rate, latency);
589c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian
590c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian    return true;
59118040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian}
59218040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
59318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qianstatic bool fusionPower(struct FusionSensor *mSensor, bool on)
59418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian{
59518040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    mSensor->active = on;
59618040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    if (on == false) {
59718040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        mTask.acc_cnt--;
59818040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        if (mSensor->idx != GEOMAG)
59918040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            mTask.gyr_cnt--;
60018040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        if (mSensor->idx != GAME && mSensor->idx != GRAVITY)
60118040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            mTask.mag_cnt--;
60218040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
60318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        // if cnt == 0 and Handle == 0, nothing need to be done.
60418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        // if cnt > 0 and Handle == 0, something else is turning it on, all will be done.
60518040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        if (mTask.acc_cnt == 0 && mTask.accelHandle != 0) {
60618040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            sensorRelease(mTask.tid, mTask.accelHandle);
60718040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            mTask.accelHandle = 0;
60818040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            osEventUnsubscribe(mTask.tid, EVT_SENSOR_ACC_DATA_RDY);
60918040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        }
61018040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
61118040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        if (mTask.gyr_cnt == 0 && mTask.gyroHandle != 0) {
61218040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            sensorRelease(mTask.tid, mTask.gyroHandle);
61318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            mTask.gyroHandle = 0;
61418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            osEventUnsubscribe(mTask.tid, EVT_SENSOR_GYR_DATA_RDY);
61518040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        }
61618040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
61718040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        if (mTask.mag_cnt == 0 && mTask.magHandle != 0) {
61818040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            sensorRelease(mTask.tid, mTask.magHandle);
61918040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            mTask.magHandle = 0;
62018040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            osEventUnsubscribe(mTask.tid, EVT_SENSOR_MAG_DATA_RDY);
62118040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        }
622c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian
623c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian        (void) fusionSetRate(mSensor, 0, ULONG_LONG_MAX);
62418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    } else {
62518040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        mTask.acc_cnt++;
62618040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        if (mSensor->idx != GEOMAG)
62718040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            mTask.gyr_cnt++;
62818040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        if (mSensor->idx != GAME && mSensor->idx != GRAVITY)
62918040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian            mTask.mag_cnt++;
6301be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema    }
6311be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema
63218040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    configureFusion();
63318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    configureGame();
63418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    sensorSignalInternalEvt(mSensor->handle, SENSOR_INTERNAL_EVT_POWER_STATE_CHG, on, 0);
635960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
636960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian    return true;
637960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian}
638960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
63918040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qianstatic bool orientPower(bool on)
64018040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian{
64118040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    return fusionPower(&mTask.sensors[ORIENT], on);
64218040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian}
64318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
64418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qianstatic bool geoMagPower(bool on)
64518040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian{
64618040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    return fusionPower(&mTask.sensors[GEOMAG], on);
64718040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian}
64818040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
64918040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qianstatic bool linearAccPower(bool on)
65018040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian{
65118040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    return fusionPower(&mTask.sensors[LINEAR], on);
65218040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian}
65318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
65418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qianstatic bool gamePower(bool on)
65518040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian{
65618040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    return fusionPower(&mTask.sensors[GAME], on);
65718040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian}
65818040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
65918040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qianstatic bool rotationPower(bool on)
66018040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian{
66118040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    return fusionPower(&mTask.sensors[ROTAT], on);
66218040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian}
66318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
66418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qianstatic bool gravityPower(bool on)
66518040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian{
66618040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    return fusionPower(&mTask.sensors[GRAVITY], on);
66718040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian}
66818040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
66918040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qianstatic bool orientSetRate(uint32_t rate, uint64_t latency)
67018040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian{
67118040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    return fusionSetRate(&mTask.sensors[ORIENT], rate, latency);
67218040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian}
67318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
67418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qianstatic bool gravitySetRate(uint32_t rate, uint64_t latency)
67518040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian{
67618040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    return fusionSetRate(&mTask.sensors[GRAVITY], rate, latency);
67718040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian}
67818040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
67918040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qianstatic bool linearAccSetRate(uint32_t rate, uint64_t latency)
680960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian{
68118040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    return fusionSetRate(&mTask.sensors[LINEAR], rate, latency);
682960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian}
683960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
68418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qianstatic bool geoMagSetRate(uint32_t rate, uint64_t latency)
68518040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian{
68618040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    return fusionSetRate(&mTask.sensors[GEOMAG], rate, latency);
68718040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian}
68818040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
68918040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qianstatic bool gameSetRate(uint32_t rate, uint64_t latency)
69018040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian{
69118040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    return fusionSetRate(&mTask.sensors[GAME], rate, latency);
69218040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian}
69318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
69418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qianstatic bool rotationSetRate(uint32_t rate, uint64_t latency)
69518040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian{
69618040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    return fusionSetRate(&mTask.sensors[ROTAT], rate, latency);
69718040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian}
69818040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
69918040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qianstatic bool fusionFirmwareUpload(struct FusionSensor *mSensor)
70018040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian{
70118040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    sensorSignalInternalEvt(mSensor->handle, SENSOR_INTERNAL_EVT_FW_STATE_CHG, 1, 0);
70218040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    return true;
70318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian}
70418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
70518040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qianstatic bool orientFirmwareUpload()
70618040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian{
70718040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    return fusionFirmwareUpload(&mTask.sensors[ORIENT]);
70818040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian}
70918040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
71018040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qianstatic bool gravityFirmwareUpload()
71118040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian{
71218040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    return fusionFirmwareUpload(&mTask.sensors[GRAVITY]);
71318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian}
71418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
71518040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qianstatic bool geoMagFirmwareUpload()
71618040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian{
71718040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    return fusionFirmwareUpload(&mTask.sensors[GEOMAG]);
71818040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian}
71918040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
72018040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qianstatic bool linearAccFirmwareUpload()
72118040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian{
72218040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    return fusionFirmwareUpload(&mTask.sensors[LINEAR]);
72318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian}
72418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
72518040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qianstatic bool gameFirmwareUpload()
72618040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian{
72718040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    return fusionFirmwareUpload(&mTask.sensors[GAME]);
72818040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian}
72918040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
73018040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qianstatic bool rotationFirmwareUpload()
73118040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian{
73218040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    return fusionFirmwareUpload(&mTask.sensors[ROTAT]);
73318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian}
73418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
73518040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qianstatic bool fusionFlush(struct FusionSensor *mSensor)
73618040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian{
73718040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    uint32_t evtType = sensorGetMyEventType(mSi[mSensor->idx].sensorType);
73818040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    osEnqueueEvt(evtType, SENSOR_DATA_EVENT_FLUSH, NULL);
73918040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    return true;
74018040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian}
74118040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
74218040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qianstatic bool orientFlush()
74318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian{
74418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    return fusionFlush(&mTask.sensors[ORIENT]);
74518040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian}
74618040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
74718040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qianstatic bool gravityFlush()
74818040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian{
74918040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    return fusionFlush(&mTask.sensors[GRAVITY]);
75018040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian}
75118040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
75218040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qianstatic bool linearAccFlush()
75318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian{
75418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    return fusionFlush(&mTask.sensors[LINEAR]);
75518040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian}
75618040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
75718040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qianstatic bool gameFlush()
75818040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian{
75918040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    return fusionFlush(&mTask.sensors[GAME]);
76018040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian}
76118040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
76218040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qianstatic bool geoMagFlush()
76318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian{
76418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    return fusionFlush(&mTask.sensors[GEOMAG]);
76518040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian}
76618040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
76718040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qianstatic bool rotationFlush()
76818040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian{
76918040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    return fusionFlush(&mTask.sensors[ROTAT]);
77018040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian}
77118040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
77218040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian
77318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qianstatic void fusionHandleEvent(uint32_t evtType, const void* evtData)
774960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian{
7757062239aaa63d8a5260d7d325483755acbb8c35cBen Fennema    struct TripleAxisDataEvent *ev;
776960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
7770bcb1a3baec93492e58afff27f2ef92afcbf1698Ben Fennema    if (evtData == SENSOR_DATA_EVENT_FLUSH)
7780bcb1a3baec93492e58afff27f2ef92afcbf1698Ben Fennema        return;
7790bcb1a3baec93492e58afff27f2ef92afcbf1698Ben Fennema
780960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian    switch (evtType) {
7811be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema    case EVT_SENSOR_ACC_DATA_RDY:
7821be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema        ev = (struct TripleAxisDataEvent *)evtData;
78318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        fillSamples(ev, ACC);
7841be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema        drainSamples();
7851be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema        break;
7861be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema    case EVT_SENSOR_GYR_DATA_RDY:
7871be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema        ev = (struct TripleAxisDataEvent *)evtData;
78818040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        fillSamples(ev, GYR);
7891be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema        drainSamples();
7901be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema        break;
7911be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema    case EVT_SENSOR_MAG_DATA_RDY:
7921be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema        ev = (struct TripleAxisDataEvent *)evtData;
79318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        fillSamples(ev, MAG);
7941be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema        drainSamples();
7951be10b6751f50675307716747bd4d729d9e7aff5Ben Fennema        break;
796960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian    }
797960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian}
798960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
79918040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qianstatic const struct SensorOps mSops[NUM_OF_FUSION_SENSOR] =
80064eb1702a319ad4bbc181ed1e5af0703aea7ea22Zhengyin Qian{
80118040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    {orientPower, orientFirmwareUpload, orientSetRate, orientFlush, NULL, NULL},
80218040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    {gravityPower, gravityFirmwareUpload, gravitySetRate, gravityFlush, NULL, NULL},
80318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    {geoMagPower, geoMagFirmwareUpload, geoMagSetRate, geoMagFlush, NULL, NULL},
80418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    {linearAccPower, linearAccFirmwareUpload, linearAccSetRate, linearAccFlush, NULL, NULL},
80518040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    {gamePower, gameFirmwareUpload, gameSetRate, gameFlush, NULL, NULL},
80618040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    {rotationPower, rotationFirmwareUpload, rotationSetRate, rotationFlush, NULL, NULL},
80764eb1702a319ad4bbc181ed1e5af0703aea7ea22Zhengyin Qian};
80864eb1702a319ad4bbc181ed1e5af0703aea7ea22Zhengyin Qian
80918040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qianstatic bool fusionStart(uint32_t tid)
810960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian{
811960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian    osLog(LOG_INFO, "        ORIENTATION:  %ld\n", tid);
812e0e5b567748b8d46f60ede2ff12c4b2358ffe0dbZhengyin Qian    size_t i, slabSize;
813960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
814960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian    mTask.tid = tid;
815960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian    mTask.last_gyro_time = 0ull;
816960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian    mTask.last_acc_time = 0ull;
817960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian    mTask.flags = 0;
818960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
81918040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    for (i = 0; i < NUM_OF_RAW_SENSOR; i++) {
820960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian         mTask.sample_counts[i] = 0;
821960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian         mTask.sample_indices[i] = 0;
822960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian    }
823960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
82418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    for (i = ORIENT; i < NUM_OF_FUSION_SENSOR; i++) {
82518040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        mTask.sensors[i].handle = sensorRegister(&mSi[i], &mSops[i]);
826f45dac303dc3756b80036a68f23cdc48f34d870eBen Fennema        sensorRegisterInitComplete(mTask.sensors[i].handle);
82718040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        mTask.sensors[i].idx = i;
82818040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        mTask.sensors[i].use_gyr_data = true;
82918040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        mTask.sensors[i].use_mag_data = true;
83018040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    }
831960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
83218040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    mTask.sensors[GEOMAG].use_gyr_data = false;
83318040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    mTask.sensors[GAME].use_mag_data = false;
83418040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian    mTask.sensors[GRAVITY].use_mag_data = false;
835960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
836960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
8377062239aaa63d8a5260d7d325483755acbb8c35cBen Fennema    slabSize = sizeof(struct TripleAxisDataEvent)
8387062239aaa63d8a5260d7d325483755acbb8c35cBen Fennema        + MAX_NUM_COMMS_EVENT_SAMPLES * sizeof(struct TripleAxisDataPoint);
839e0e5b567748b8d46f60ede2ff12c4b2358ffe0dbZhengyin Qian    mDataSlab = slabAllocatorNew(slabSize, 4, 10); // 10 slots for now..
840c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian    if (!mDataSlab) {
841c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian        osLog(LOG_ERROR, "FUSION SLAB ALLOCATION FAILED\n");
842c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian        return false;
843c900c013a76aa73bd612da12000c76e0d4169595Zhengyin Qian    }
844e0e5b567748b8d46f60ede2ff12c4b2358ffe0dbZhengyin Qian
845960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian    return true;
846960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian}
847960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
84818040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qianstatic void fusionEnd()
849960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian{
850960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian    mTask.flags &= ~FUSION_FLAG_INITIALIZED;
851e0e5b567748b8d46f60ede2ff12c4b2358ffe0dbZhengyin Qian    slabAllocatorDestroy(mDataSlab);
852960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian}
853960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin Qian
854960c2ec577b48937271d3d951bfbc66b070283a1Zhengyin QianINTERNAL_APP_INIT(
855dca61fcfcc85a8240bc46a650c71008ded2d32ddBen Fennema        APP_ID_MAKE(APP_ID_VENDOR_GOOGLE, 4),
856cc77708f80db23714a92638ddee64f59dbdf5483Dmitry Grinberg        0,
85718040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        fusionStart,
85818040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        fusionEnd,
85918040c9213658bbcc2ccc9e6cdb654d7a228eb66Zhengyin Qian        fusionHandleEvent);
860