1aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung/*
2aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung * Copyright (C) 2016 The Android Open Source Project
3aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung *
4aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung * Licensed under the Apache License, Version 2.0 (the "License");
5aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung * you may not use this file except in compliance with the License.
6aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung * You may obtain a copy of the License at
7aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung *
8aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung *      http://www.apache.org/licenses/LICENSE-2.0
9aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung *
10aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung * Unless required by applicable law or agreed to in writing, software
11aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung * distributed under the License is distributed on an "AS IS" BASIS,
12aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung * See the License for the specific language governing permissions and
14aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung * limitations under the License.
15aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung */
16aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung
17a16406ba1a734f21f36a4b0f64b23b062644b6e2Andrew Rossignol#include <chre.h>
18aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung#include <cinttypes>
19aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung
207621b3267fd2ff1068d7aa7d75441d68646226abBrian Duddie#include "chre/util/macros.h"
21a16406ba1a734f21f36a4b0f64b23b062644b6e2Andrew Rossignol#include "chre/util/nanoapp/log.h"
22746ea0ecb99d3f758da17292db549b29720c4442Andrew Rossignol#include "chre/util/nanoapp/sensor.h"
23aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung#include "chre/util/time.h"
24aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung
25a16406ba1a734f21f36a4b0f64b23b062644b6e2Andrew Rossignol#define LOG_TAG "[ImuCal]"
26a16406ba1a734f21f36a4b0f64b23b062644b6e2Andrew Rossignol
27e969b9be8eca27ffc875167879ab0ec093b3e313Andrew Rossignol#ifdef CHRE_NANOAPP_INTERNAL
28aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chungnamespace chre {
29e969b9be8eca27ffc875167879ab0ec093b3e313Andrew Rossignolnamespace {
30e969b9be8eca27ffc875167879ab0ec093b3e313Andrew Rossignol#endif  // CHRE_NANOAPP_INTERNAL
31e969b9be8eca27ffc875167879ab0ec093b3e313Andrew Rossignol
32aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chungnamespace {
33aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung
34aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chungstruct SensorState {
35aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung  const uint8_t type;
36aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung  uint32_t handle;
37aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung  bool isInitialized;
38aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung  bool enable;
39aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung  uint64_t interval;  // nsec
40aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung  uint64_t latency;  // nsec
41aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung  chreSensorInfo info;
42aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung};
43aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung
44aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan ChungSensorState sensors[] = {
45aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung  { .type = CHRE_SENSOR_TYPE_ACCELEROMETER_TEMPERATURE,
46aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung    .enable = true,
47aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung    .interval = Seconds(2).toRawNanoseconds(),
48aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung    .latency = 0,
49aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung  },
50aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung  { .type = CHRE_SENSOR_TYPE_GYROSCOPE_TEMPERATURE,
51aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung    .enable = true,
52aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung    .interval = Seconds(2).toRawNanoseconds(),
53aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung    .latency = 0,
54aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung  },
55aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung  { .type = CHRE_SENSOR_TYPE_UNCALIBRATED_ACCELEROMETER,
56aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung    .enable = true,
57aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung    .interval = Milliseconds(80).toRawNanoseconds(),
58aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung    .latency = Seconds(4).toRawNanoseconds(),
59aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung  },
60aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung  { .type = CHRE_SENSOR_TYPE_UNCALIBRATED_GYROSCOPE,
61aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung    .enable = true,
62aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung    .interval = Milliseconds(80).toRawNanoseconds(),
63aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung    .latency = Seconds(4).toRawNanoseconds(),
64aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung  },
65aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung  { .type = CHRE_SENSOR_TYPE_UNCALIBRATED_GEOMAGNETIC_FIELD,
66aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung    .enable = true,
67aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung    .interval = Milliseconds(80).toRawNanoseconds(),
68aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung    .latency = Seconds(4).toRawNanoseconds(),
69aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung  },
70aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung};
71aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung
72aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung} // namespace
73aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung
74e969b9be8eca27ffc875167879ab0ec093b3e313Andrew Rossignolbool nanoappStart() {
75a16406ba1a734f21f36a4b0f64b23b062644b6e2Andrew Rossignol  LOGI("App started on platform ID %" PRIx64, chreGetPlatformId());
76aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung
77aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung  for (size_t i = 0; i < ARRAY_SIZE(sensors); i++) {
78aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung    SensorState& sensor = sensors[i];
79aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung    sensor.isInitialized = chreSensorFindDefault(sensor.type, &sensor.handle);
80a16406ba1a734f21f36a4b0f64b23b062644b6e2Andrew Rossignol    LOGI("sensor %d initialized: %s with handle %" PRIu32,
81a16406ba1a734f21f36a4b0f64b23b062644b6e2Andrew Rossignol         i, sensor.isInitialized ? "true" : "false", sensor.handle);
82aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung
83aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung    if (sensor.isInitialized) {
84aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung      // Get sensor info
85aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung      chreSensorInfo& info = sensor.info;
86aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung      bool infoStatus = chreGetSensorInfo(sensor.handle, &info);
87aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung      if (infoStatus) {
88a16406ba1a734f21f36a4b0f64b23b062644b6e2Andrew Rossignol        LOGI("SensorInfo: %s, Type=%" PRIu8 " OnChange=%d"
89a16406ba1a734f21f36a4b0f64b23b062644b6e2Andrew Rossignol             " OneShot=%d minInterval=%" PRIu64 "nsec",
90a16406ba1a734f21f36a4b0f64b23b062644b6e2Andrew Rossignol             info.sensorName, info.sensorType, info.isOnChange,
91a16406ba1a734f21f36a4b0f64b23b062644b6e2Andrew Rossignol             info.isOneShot, info.minInterval);
92aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung      } else {
93a16406ba1a734f21f36a4b0f64b23b062644b6e2Andrew Rossignol        LOGE("chreGetSensorInfo failed");
94aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung      }
95aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung
96aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung
97aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung      // Subscribe to sensors
98aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung      if (sensor.enable) {
99aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung        float odrHz = 1e9 / sensor.interval;
100aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung        float latencySec = sensor.latency / 1e9;
101aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung        bool status = chreSensorConfigure(sensor.handle,
102aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung            CHRE_SENSOR_CONFIGURE_MODE_CONTINUOUS, sensor.interval,
103aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung            sensor.latency);
104a16406ba1a734f21f36a4b0f64b23b062644b6e2Andrew Rossignol        LOGI("Requested data: odr %f Hz, latency %f sec, %s",
105a16406ba1a734f21f36a4b0f64b23b062644b6e2Andrew Rossignol             odrHz, latencySec, status ? "success" : "failure");
106aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung      }
107aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung    }
108aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung  }
109aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung
110aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung  return true;
111aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung}
112aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung
113e969b9be8eca27ffc875167879ab0ec093b3e313Andrew Rossignolvoid nanoappHandleEvent(uint32_t senderInstanceId,
114e969b9be8eca27ffc875167879ab0ec093b3e313Andrew Rossignol                        uint16_t eventType,
115e969b9be8eca27ffc875167879ab0ec093b3e313Andrew Rossignol                        const void *eventData) {
116aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung  switch (eventType) {
117aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung    case CHRE_EVENT_SENSOR_UNCALIBRATED_ACCELEROMETER_DATA:
118aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung    case CHRE_EVENT_SENSOR_UNCALIBRATED_GYROSCOPE_DATA:
119aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung    case CHRE_EVENT_SENSOR_UNCALIBRATED_GEOMAGNETIC_FIELD_DATA: {
120aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung      const auto *ev = static_cast<const chreSensorThreeAxisData *>(eventData);
121aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung      const auto header = ev->header;
122aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung      const auto *data = ev->readings;
123aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung
124aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung      // TODO: replace by cal algo
125aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung      float x = 0, y = 0, z = 0;
126aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung      for (size_t i = 0; i < header.readingCount; i++) {
127aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung        x += data[i].v[0];
128aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung        y += data[i].v[1];
129aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung        z += data[i].v[2];
130aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung      }
131aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung      x /= header.readingCount;
132aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung      y /= header.readingCount;
133aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung      z /= header.readingCount;
134aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung
135a16406ba1a734f21f36a4b0f64b23b062644b6e2Andrew Rossignol      LOGI("%s, %d samples: %f %f %f",
136746ea0ecb99d3f758da17292db549b29720c4442Andrew Rossignol           getSensorNameForEventType(eventType), header.readingCount, x, y, z);
137aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung      break;
138aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung    }
139aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung
140aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung    case CHRE_EVENT_SENSOR_ACCELEROMETER_TEMPERATURE_DATA:
141aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung    case CHRE_EVENT_SENSOR_GYROSCOPE_TEMPERATURE_DATA: {
142aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung      const auto *ev = static_cast<const chreSensorFloatData *>(eventData);
143aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung      const auto header = ev->header;
144aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung
145aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung      // TODO: replace by cal algo
146aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung      float v = 0;
147aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung      for (size_t i = 0; i < header.readingCount; i++) {
148aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung        v += ev->readings[i].value;
149aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung      }
150aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung      v /= header.readingCount;
151aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung
152a16406ba1a734f21f36a4b0f64b23b062644b6e2Andrew Rossignol      LOGI("%s, %d samples: %f",
153746ea0ecb99d3f758da17292db549b29720c4442Andrew Rossignol           getSensorNameForEventType(eventType), header.readingCount, v);
154aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung      break;
155aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung    }
156aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung
157aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung    default:
158a16406ba1a734f21f36a4b0f64b23b062644b6e2Andrew Rossignol      LOGW("Unhandled event %d", eventType);
159aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung      break;
160aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung  }
161aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung}
162aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung
1632b9d71a9f6a9e8cc0e787957d022154231f29962Brian Duddievoid nanoappEnd() {
164aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung  // TODO: Unscribe to sensors
165a16406ba1a734f21f36a4b0f64b23b062644b6e2Andrew Rossignol  LOGI("Stopped");
166aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung}
167aa499877f69da5b99776f5b58ee5ecee824ddbc8Meng-hsuan Chung
168e969b9be8eca27ffc875167879ab0ec093b3e313Andrew Rossignol#ifdef CHRE_NANOAPP_INTERNAL
1699d5b500a223ef73560f0dce38f50b809bde5dd0dBrian Duddie}  // anonymous namespace
1709d5b500a223ef73560f0dce38f50b809bde5dd0dBrian Duddie}  // namespace chre
171e969b9be8eca27ffc875167879ab0ec093b3e313Andrew Rossignol
1729d5b500a223ef73560f0dce38f50b809bde5dd0dBrian Duddie#include "chre/util/nanoapp/app_id.h"
1739d5b500a223ef73560f0dce38f50b809bde5dd0dBrian Duddie#include "chre/platform/static_nanoapp_init.h"
174e969b9be8eca27ffc875167879ab0ec093b3e313Andrew Rossignol
1759d5b500a223ef73560f0dce38f50b809bde5dd0dBrian DuddieCHRE_STATIC_NANOAPP_INIT(ImuCal, chre::kImuCalAppId, 0);
176e969b9be8eca27ffc875167879ab0ec093b3e313Andrew Rossignol#endif  // CHRE_NANOAPP_INTERNAL
177