1 /*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <ash.h>
18 #include <chre.h>
19 #include <cinttypes>
20
21 #include "chre/util/nanoapp/log.h"
22
23 /**
24 * @file
25 * A nanoapp exclusively for testing, which saves locally defined ashCalParam
26 * of accel, gyro and mag to storage and lodas them back to check correctness.
27 * The loaded back asCalParam should be identical to the saved one, subject to
28 * storage quantization error.
29 * It's suggested that a copy of the original storage be made before running
30 * this test nanoapp so the original storage can be retained.
31 * Note that ASH functionality is not required for CHRE.
32 */
33
34 #define LOG_TAG "[AshWorld]"
35
36 #ifdef CHRE_NANOAPP_INTERNAL
37 namespace chre {
38 namespace {
39 #endif // CHRE_NANOAPP_INTERNAL
40
41 uint32_t gCyclicTimerHandle;
42 uint32_t gCyclicTimerCount;
43
44 struct ashCalParams accCalParams = {
45 .offset = {0.0, 1.0, 2.0},
46 .offsetTempCelsius = 3.0,
47 .tempSensitivity = {4.0, 5.0, 6.0},
48 .tempIntercept = {7.0, 8.0, 9.0},
49 .scaleFactor = {10.0, 11.0, 12.0},
50 .crossAxis = {13.0, 14.0, 15.0},
51 .offsetSource = 16,
52 .offsetTempCelsiusSource = 17,
53 .tempSensitivitySource = 18,
54 .tempInterceptSource = 19,
55 .scaleFactorSource = 20,
56 .crossAxisSource = 21,
57 };
58
59 struct ashCalParams gyrCalParams = {
60 .offset = {100.0, 101.0, 102.0},
61 .offsetTempCelsius = 103.0,
62 .tempSensitivity = {104.0, 105.0, 106.0},
63 .tempIntercept = {107.0, 108.0, 109.0},
64 .scaleFactor = {110.0, 111.0, 112.0},
65 .crossAxis = {113.0, 114.0, 115.0},
66 .offsetSource = 116,
67 .offsetTempCelsiusSource = 117,
68 .tempSensitivitySource = 118,
69 .tempInterceptSource = 119,
70 .scaleFactorSource = 120,
71 .crossAxisSource = 121,
72 };
73
74 struct ashCalParams magCalParams = {
75 .offset = {200.0, 201.0, 202.0},
76 .offsetTempCelsius = 203.0,
77 .tempSensitivity = {204.0, 205.0, 206.0},
78 .tempIntercept = {207.0, 208.0, 209.0},
79 .scaleFactor = {210.0, 211.0, 212.0},
80 .crossAxis = {213.0, 214.0, 215.0},
81 .offsetSource = 216,
82 .offsetTempCelsiusSource = 217,
83 .tempSensitivitySource = 218,
84 .tempInterceptSource = 219,
85 .scaleFactorSource = 220,
86 .crossAxisSource = 221,
87 };
88
89 struct ashCalInfo accCalInfo = {
90 .bias = {0.1f, -0.1f, 0.2f},
91 .compMatrix = {1.0f, 0.1f, -0.1f, 0.2f, -0.2f, 1.0f, 0.3f, -0.3f, 1.0f},
92 .accuracy = 1,
93 };
94
95 struct ashCalInfo gyrCalInfo = {
96 .bias = {0.2f, -0.2f, 0.1f},
97 .compMatrix = {1.0f, 0.2f, -0.2f, 0.4f, -0.4f, 1.0f, 0.6f, -0.6f, 1.0f},
98 .accuracy = 2,
99 };
100
101 struct ashCalInfo magCalInfo = {
102 .bias = {10, -10, 20},
103 .compMatrix = {1.0f, -0.1f, 0.1f, -0.2f, 0.2f, 1.0f, -0.3f, 0.3f, 1.0f},
104 .accuracy = 3,
105 };
106
nanoappStart()107 bool nanoappStart() {
108 LOGI("App started on platform ID %" PRIx64, chreGetPlatformId());
109
110 gCyclicTimerHandle = chreTimerSet(3000000000 /* duration: 3sec */,
111 &gCyclicTimerHandle /* data */,
112 false /* oneShot */);
113 gCyclicTimerCount = 0;
114 return true;
115 }
116
handleTimerEvent(const void * eventData)117 void handleTimerEvent(const void *eventData) {
118 LOGI("Cyclic timer event received %" PRIu32, gCyclicTimerCount);
119 bool success = false;
120 uint64_t tic = 0, toc = 0;
121
122 uint8_t sensor = CHRE_SENSOR_TYPE_ACCELEROMETER;
123 struct ashCalParams *sensorCalParams = &accCalParams;
124 struct ashCalInfo *sensorCalInfo = &accCalInfo;
125 if ((gCyclicTimerCount / 3) == 1) {
126 sensor = CHRE_SENSOR_TYPE_GYROSCOPE;
127 sensorCalParams = &gyrCalParams;
128 sensorCalInfo = &gyrCalInfo;
129 } else if ((gCyclicTimerCount / 3) == 2) {
130 sensor = CHRE_SENSOR_TYPE_GEOMAGNETIC_FIELD;
131 sensorCalParams = &magCalParams;
132 sensorCalInfo = &magCalInfo;
133 }
134
135 if (gCyclicTimerCount >= 9) {
136 chreTimerCancel(gCyclicTimerHandle);
137 LOGI("Timer cancelled");
138 } else if (gCyclicTimerCount % 3 == 0) {
139 tic = chreGetTime();
140 success = ashSaveCalibrationParams(sensor, sensorCalParams);
141 toc = chreGetTime();
142 LOGI("*** save sensor %" PRIu8 ": %s, time %" PRIu64 " us",
143 sensor, success ? "success" : "failure", (toc - tic) / 1000);
144 } else if (gCyclicTimerCount % 3 == 1) {
145 struct ashCalParams p;
146 tic = chreGetTime();
147 success = ashLoadCalibrationParams(sensor, ASH_CAL_STORAGE_ASH, &p);
148 toc = chreGetTime();
149 LOGI("*** load sensor %" PRIu8 ": %s, time %" PRIu64 " us",
150 sensor, success ? "success" : "fail", (toc - tic) / 1000);
151
152 LOGI("offset %f %f %f", p.offset[0], p.offset[1], p.offset[2]);
153 LOGI("offsetTempCelsius %f", p.offsetTempCelsius);
154 LOGI("tempSensitivity %f %f %f", p.tempSensitivity[0],
155 p.tempSensitivity[1], p.tempSensitivity[2]);
156 LOGI("tempIntercept %f %f %f", p.tempIntercept[0],
157 p.tempIntercept[1], p.tempIntercept[2]);
158 LOGI("scaleFactor %f %f %f", p.scaleFactor[0],
159 p.scaleFactor[1], p.scaleFactor[2]);
160 LOGI("crossAxis %f %f %f", p.crossAxis[0], p.crossAxis[1], p.crossAxis[2]);
161 LOGI("%" PRIu8 " %" PRIu8 " %" PRIu8 " %" PRIu8 " %" PRIu8 " %" PRIu8,
162 p.offsetSource, p.offsetTempCelsiusSource, p.tempSensitivitySource,
163 p.tempInterceptSource, p.scaleFactorSource, p.crossAxisSource);
164 } else {
165 tic = chreGetTime();
166 success = ashSetCalibration(sensor, sensorCalInfo);
167 toc = chreGetTime();
168 LOGI("*** set sensor %" PRIu8 ": %s, time %" PRIu64 " us",
169 sensor, success ? "success" : "failure", (toc - tic) / 1000);
170 }
171
172 gCyclicTimerCount++;
173 }
174
nanoappHandleEvent(uint32_t senderInstanceId,uint16_t eventType,const void * eventData)175 void nanoappHandleEvent(uint32_t senderInstanceId,
176 uint16_t eventType,
177 const void *eventData) {
178 switch (eventType) {
179 case CHRE_EVENT_TIMER:
180 handleTimerEvent(eventData);
181 break;
182 default:
183 LOGW("Unknown event received");
184 break;
185 }
186 }
187
nanoappEnd()188 void nanoappEnd() {
189 LOGI("Stopped");
190 }
191
192 #ifdef CHRE_NANOAPP_INTERNAL
193 } // anonymous namespace
194 } // namespace chre
195
196 #include "chre/util/nanoapp/app_id.h"
197 #include "chre/platform/static_nanoapp_init.h"
198
199 CHRE_STATIC_NANOAPP_INIT(AshWorld, chre::kAshWorldAppId, 0);
200 #endif // CHRE_NANOAPP_INTERNAL
201