/* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <chre.h> #include <cinttypes> #include "chre/util/macros.h" #include "chre/util/nanoapp/log.h" #include "chre/util/nanoapp/sensor.h" #include "chre/util/time.h" #define LOG_TAG "[ImuCal]" #ifdef CHRE_NANOAPP_INTERNAL namespace chre { namespace { #endif // CHRE_NANOAPP_INTERNAL namespace { struct SensorState { const uint8_t type; uint32_t handle; bool isInitialized; bool enable; uint64_t interval; // nsec uint64_t latency; // nsec chreSensorInfo info; }; SensorState sensors[] = { { .type = CHRE_SENSOR_TYPE_ACCELEROMETER_TEMPERATURE, .enable = true, .interval = Seconds(2).toRawNanoseconds(), .latency = 0, }, { .type = CHRE_SENSOR_TYPE_GYROSCOPE_TEMPERATURE, .enable = true, .interval = Seconds(2).toRawNanoseconds(), .latency = 0, }, { .type = CHRE_SENSOR_TYPE_UNCALIBRATED_ACCELEROMETER, .enable = true, .interval = Milliseconds(80).toRawNanoseconds(), .latency = Seconds(4).toRawNanoseconds(), }, { .type = CHRE_SENSOR_TYPE_UNCALIBRATED_GYROSCOPE, .enable = true, .interval = Milliseconds(80).toRawNanoseconds(), .latency = Seconds(4).toRawNanoseconds(), }, { .type = CHRE_SENSOR_TYPE_UNCALIBRATED_GEOMAGNETIC_FIELD, .enable = true, .interval = Milliseconds(80).toRawNanoseconds(), .latency = Seconds(4).toRawNanoseconds(), }, }; } // namespace bool nanoappStart() { LOGI("App started on platform ID %" PRIx64, chreGetPlatformId()); for (size_t i = 0; i < ARRAY_SIZE(sensors); i++) { SensorState& sensor = sensors[i]; sensor.isInitialized = chreSensorFindDefault(sensor.type, &sensor.handle); LOGI("sensor %d initialized: %s with handle %" PRIu32, i, sensor.isInitialized ? "true" : "false", sensor.handle); if (sensor.isInitialized) { // Get sensor info chreSensorInfo& info = sensor.info; bool infoStatus = chreGetSensorInfo(sensor.handle, &info); if (infoStatus) { LOGI("SensorInfo: %s, Type=%" PRIu8 " OnChange=%d" " OneShot=%d minInterval=%" PRIu64 "nsec", info.sensorName, info.sensorType, info.isOnChange, info.isOneShot, info.minInterval); } else { LOGE("chreGetSensorInfo failed"); } // Subscribe to sensors if (sensor.enable) { float odrHz = 1e9 / sensor.interval; float latencySec = sensor.latency / 1e9; bool status = chreSensorConfigure(sensor.handle, CHRE_SENSOR_CONFIGURE_MODE_CONTINUOUS, sensor.interval, sensor.latency); LOGI("Requested data: odr %f Hz, latency %f sec, %s", odrHz, latencySec, status ? "success" : "failure"); } } } return true; } void nanoappHandleEvent(uint32_t senderInstanceId, uint16_t eventType, const void *eventData) { switch (eventType) { case CHRE_EVENT_SENSOR_UNCALIBRATED_ACCELEROMETER_DATA: case CHRE_EVENT_SENSOR_UNCALIBRATED_GYROSCOPE_DATA: case CHRE_EVENT_SENSOR_UNCALIBRATED_GEOMAGNETIC_FIELD_DATA: { const auto *ev = static_cast<const chreSensorThreeAxisData *>(eventData); const auto header = ev->header; const auto *data = ev->readings; // TODO: replace by cal algo float x = 0, y = 0, z = 0; for (size_t i = 0; i < header.readingCount; i++) { x += data[i].v[0]; y += data[i].v[1]; z += data[i].v[2]; } x /= header.readingCount; y /= header.readingCount; z /= header.readingCount; LOGI("%s, %d samples: %f %f %f", getSensorNameForEventType(eventType), header.readingCount, x, y, z); break; } case CHRE_EVENT_SENSOR_ACCELEROMETER_TEMPERATURE_DATA: case CHRE_EVENT_SENSOR_GYROSCOPE_TEMPERATURE_DATA: { const auto *ev = static_cast<const chreSensorFloatData *>(eventData); const auto header = ev->header; // TODO: replace by cal algo float v = 0; for (size_t i = 0; i < header.readingCount; i++) { v += ev->readings[i].value; } v /= header.readingCount; LOGI("%s, %d samples: %f", getSensorNameForEventType(eventType), header.readingCount, v); break; } default: LOGW("Unhandled event %d", eventType); break; } } void nanoappEnd() { // TODO: Unscribe to sensors LOGI("Stopped"); } #ifdef CHRE_NANOAPP_INTERNAL } // anonymous namespace } // namespace chre #include "chre/util/nanoapp/app_id.h" #include "chre/platform/static_nanoapp_init.h" CHRE_STATIC_NANOAPP_INIT(ImuCal, chre::kImuCalAppId, 0); #endif // CHRE_NANOAPP_INTERNAL