普通文本  |  201行  |  6.27 KB

/*
 * 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 <ash.h>
#include <chre.h>
#include <cinttypes>

#include "chre/util/nanoapp/log.h"

/**
 * @file
 * A nanoapp exclusively for testing, which saves locally defined ashCalParam
 * of accel, gyro and mag to storage and lodas them back to check correctness.
 * The loaded back asCalParam should be identical to the saved one, subject to
 * storage quantization error.
 * It's suggested that a copy of the original storage be made before running
 * this test nanoapp so the original storage can be retained.
 * Note that ASH functionality is not required for CHRE.
 */

#define LOG_TAG "[AshWorld]"

#ifdef CHRE_NANOAPP_INTERNAL
namespace chre {
namespace {
#endif  // CHRE_NANOAPP_INTERNAL

uint32_t gCyclicTimerHandle;
uint32_t gCyclicTimerCount;

struct ashCalParams accCalParams = {
  .offset = {0.0, 1.0, 2.0},
  .offsetTempCelsius = 3.0,
  .tempSensitivity = {4.0, 5.0, 6.0},
  .tempIntercept = {7.0, 8.0, 9.0},
  .scaleFactor = {10.0, 11.0, 12.0},
  .crossAxis = {13.0, 14.0, 15.0},
  .offsetSource = 16,
  .offsetTempCelsiusSource = 17,
  .tempSensitivitySource = 18,
  .tempInterceptSource = 19,
  .scaleFactorSource = 20,
  .crossAxisSource = 21,
};

struct ashCalParams gyrCalParams = {
  .offset = {100.0, 101.0, 102.0},
  .offsetTempCelsius = 103.0,
  .tempSensitivity = {104.0, 105.0, 106.0},
  .tempIntercept = {107.0, 108.0, 109.0},
  .scaleFactor = {110.0, 111.0, 112.0},
  .crossAxis = {113.0, 114.0, 115.0},
  .offsetSource = 116,
  .offsetTempCelsiusSource = 117,
  .tempSensitivitySource = 118,
  .tempInterceptSource = 119,
  .scaleFactorSource = 120,
  .crossAxisSource = 121,
};

struct ashCalParams magCalParams = {
  .offset = {200.0, 201.0, 202.0},
  .offsetTempCelsius = 203.0,
  .tempSensitivity = {204.0, 205.0, 206.0},
  .tempIntercept = {207.0, 208.0, 209.0},
  .scaleFactor = {210.0, 211.0, 212.0},
  .crossAxis = {213.0, 214.0, 215.0},
  .offsetSource = 216,
  .offsetTempCelsiusSource = 217,
  .tempSensitivitySource = 218,
  .tempInterceptSource = 219,
  .scaleFactorSource = 220,
  .crossAxisSource = 221,
};

struct ashCalInfo accCalInfo = {
  .bias = {0.1f, -0.1f, 0.2f},
  .compMatrix = {1.0f, 0.1f, -0.1f, 0.2f, -0.2f, 1.0f, 0.3f, -0.3f, 1.0f},
  .accuracy = 1,
};

struct ashCalInfo gyrCalInfo = {
  .bias = {0.2f, -0.2f, 0.1f},
  .compMatrix = {1.0f, 0.2f, -0.2f, 0.4f, -0.4f, 1.0f, 0.6f, -0.6f, 1.0f},
  .accuracy = 2,
};

struct ashCalInfo magCalInfo = {
  .bias = {10, -10, 20},
  .compMatrix = {1.0f, -0.1f, 0.1f, -0.2f, 0.2f, 1.0f, -0.3f, 0.3f, 1.0f},
  .accuracy = 3,
};

bool nanoappStart() {
  LOGI("App started on platform ID %" PRIx64, chreGetPlatformId());

  gCyclicTimerHandle = chreTimerSet(3000000000 /* duration: 3sec */,
      &gCyclicTimerHandle /* data */,
      false /* oneShot */);
  gCyclicTimerCount = 0;
  return true;
}

void handleTimerEvent(const void *eventData) {
  LOGI("Cyclic timer event received %" PRIu32, gCyclicTimerCount);
  bool success = false;
  uint64_t tic = 0, toc = 0;

  uint8_t sensor = CHRE_SENSOR_TYPE_ACCELEROMETER;
  struct ashCalParams *sensorCalParams = &accCalParams;
  struct ashCalInfo *sensorCalInfo = &accCalInfo;
  if ((gCyclicTimerCount / 3) == 1) {
    sensor = CHRE_SENSOR_TYPE_GYROSCOPE;
    sensorCalParams = &gyrCalParams;
    sensorCalInfo = &gyrCalInfo;
  } else if ((gCyclicTimerCount / 3) == 2) {
    sensor = CHRE_SENSOR_TYPE_GEOMAGNETIC_FIELD;
    sensorCalParams = &magCalParams;
    sensorCalInfo = &magCalInfo;
  }

  if (gCyclicTimerCount >= 9) {
    chreTimerCancel(gCyclicTimerHandle);
    LOGI("Timer cancelled");
  } else if (gCyclicTimerCount % 3 == 0) {
    tic = chreGetTime();
    success = ashSaveCalibrationParams(sensor, sensorCalParams);
    toc = chreGetTime();
    LOGI("*** save sensor %" PRIu8 ": %s, time %" PRIu64 " us",
         sensor, success ? "success" : "failure", (toc - tic) / 1000);
  } else if (gCyclicTimerCount % 3 == 1) {
    struct ashCalParams p;
    tic = chreGetTime();
    success = ashLoadCalibrationParams(sensor, ASH_CAL_STORAGE_ASH, &p);
    toc = chreGetTime();
    LOGI("*** load sensor %" PRIu8 ": %s, time %" PRIu64 " us",
         sensor, success ? "success" : "fail", (toc - tic) / 1000);

    LOGI("offset %f %f %f", p.offset[0], p.offset[1], p.offset[2]);
    LOGI("offsetTempCelsius %f", p.offsetTempCelsius);
    LOGI("tempSensitivity %f %f %f", p.tempSensitivity[0],
         p.tempSensitivity[1], p.tempSensitivity[2]);
    LOGI("tempIntercept %f %f %f", p.tempIntercept[0],
         p.tempIntercept[1], p.tempIntercept[2]);
    LOGI("scaleFactor %f %f %f", p.scaleFactor[0],
         p.scaleFactor[1], p.scaleFactor[2]);
    LOGI("crossAxis %f %f %f", p.crossAxis[0], p.crossAxis[1], p.crossAxis[2]);
    LOGI("%" PRIu8 " %" PRIu8 " %" PRIu8 " %" PRIu8 " %" PRIu8 " %" PRIu8,
         p.offsetSource, p.offsetTempCelsiusSource, p.tempSensitivitySource,
         p.tempInterceptSource, p.scaleFactorSource, p.crossAxisSource);
  } else {
    tic = chreGetTime();
    success = ashSetCalibration(sensor, sensorCalInfo);
    toc = chreGetTime();
    LOGI("*** set sensor %" PRIu8 ": %s, time %" PRIu64 " us",
         sensor, success ? "success" : "failure", (toc - tic) / 1000);
  }

  gCyclicTimerCount++;
}

void nanoappHandleEvent(uint32_t senderInstanceId,
                        uint16_t eventType,
                        const void *eventData) {
  switch (eventType) {
    case CHRE_EVENT_TIMER:
      handleTimerEvent(eventData);
      break;
    default:
      LOGW("Unknown event received");
      break;
  }
}

void nanoappEnd() {
  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(AshWorld, chre::kAshWorldAppId, 0);
#endif  // CHRE_NANOAPP_INTERNAL