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 <stdlib.h>
18 #include <string.h>
19 #include <float.h>
20
21 #include <eventnums.h>
22 #include <heap.h>
23 #include <hostIntf.h>
24 #include <i2c.h>
25 #include <nanohubPacket.h>
26 #include <sensors.h>
27 #include <seos.h>
28 #include <timer.h>
29
30 #define BMP280_APP_ID APP_ID_MAKE(APP_ID_VENDOR_GOOGLE, 5)
31
32 #define BMP280_APP_VERSION 1
33
34 #define I2C_BUS_ID 0
35 #define I2C_SPEED 400000
36 #define I2C_ADDR 0x76
37
38 #define BOSCH_BMP280_ID 0x58
39
40 #define BOSCH_BMP280_REG_RESET 0x60
41 #define BOSCH_BMP280_REG_DIG_T1 0x88
42 #define BOSCH_BMP280_REG_ID 0xd0
43 #define BOSCH_BMP280_REG_CTRL_MEAS 0xf4
44 #define BOSCH_BMP280_REG_CONFIG 0xf5
45 #define BOSCH_BMP280_REG_PRES_MSB 0xf7
46
47 // temp: 2x oversampling, baro: 16x oversampling, power: normal
48 #define CTRL_ON ((2 << 5) | (5 << 2) | 3)
49 // temp: 2x oversampling, baro: 16x oversampling, power: sleep
50 #define CTRL_SLEEP ((2 << 5) | (5 << 2))
51
52 enum BMP280SensorEvents
53 {
54 EVT_SENSOR_I2C = EVT_APP_START + 1,
55 EVT_SENSOR_BARO_TIMER,
56 EVT_SENSOR_TEMP_TIMER,
57 };
58
59 enum BMP280TaskState
60 {
61 STATE_RESET,
62 STATE_VERIFY_ID,
63 STATE_AWAITING_COMP_PARAMS,
64 STATE_CONFIG,
65 STATE_FINISH_INIT,
66 STATE_IDLE,
67 STATE_ENABLING_BARO,
68 STATE_ENABLING_TEMP,
69 STATE_DISABLING_BARO,
70 STATE_DISABLING_TEMP,
71 STATE_SAMPLING,
72 };
73
74 struct BMP280CompParams
75 {
76 uint16_t dig_T1;
77 int16_t dig_T2, dig_T3;
78 uint16_t dig_P1;
79 int16_t dig_P2, dig_P3, dig_P4, dig_P5, dig_P6, dig_P7, dig_P8, dig_P9;
80 } __attribute__((packed));
81
82 static struct BMP280Task
83 {
84 struct BMP280CompParams comp;
85
86 uint32_t id;
87 uint32_t baroHandle;
88 uint32_t tempHandle;
89 uint32_t baroTimerHandle;
90 uint32_t tempTimerHandle;
91
92 float offset;
93
94 uint8_t txrxBuf[24];
95
96 bool baroOn;
97 bool tempOn;
98 bool baroReading;
99 bool baroCalibrating;
100 bool tempReading;
101 } mTask;
102
103 struct CalibrationData {
104 struct HostHubRawPacket header;
105 struct SensorAppEventHeader data_header;
106 float value;
107 } __attribute__((packed));
108
109 static const uint32_t tempSupportedRates[] =
110 {
111 SENSOR_HZ(0.1),
112 SENSOR_HZ(1),
113 SENSOR_HZ(5),
114 SENSOR_HZ(10),
115 SENSOR_HZ(25),
116 0,
117 };
118
119 static const uint64_t rateTimerValsTemp[] = //should match "supported rates in length" and be the timer length for that rate in nanosecs
120 {
121 10 * 1000000000ULL,
122 1 * 1000000000ULL,
123 1000000000ULL / 5,
124 1000000000ULL / 10,
125 1000000000ULL / 25,
126 };
127
128 static const uint32_t baroSupportedRates[] =
129 {
130 SENSOR_HZ(0.1),
131 SENSOR_HZ(1),
132 SENSOR_HZ(5),
133 SENSOR_HZ(10),
134 0
135 };
136
137 static const uint64_t rateTimerValsBaro[] = //should match "supported rates in length" and be the timer length for that rate in nanosecs
138 {
139 10 * 1000000000ULL,
140 1 * 1000000000ULL,
141 1000000000ULL / 5,
142 1000000000ULL / 10,
143 };
144
145 /* sensor callbacks from nanohub */
146
i2cCallback(void * cookie,size_t tx,size_t rx,int err)147 static void i2cCallback(void *cookie, size_t tx, size_t rx, int err)
148 {
149 if (err == 0)
150 osEnqueuePrivateEvt(EVT_SENSOR_I2C, cookie, NULL, mTask.id);
151 else
152 osLog(LOG_INFO, "BMP280: i2c error (%d)\n", err);
153 }
154
baroTimerCallback(uint32_t timerId,void * cookie)155 static void baroTimerCallback(uint32_t timerId, void *cookie)
156 {
157 osEnqueuePrivateEvt(EVT_SENSOR_BARO_TIMER, cookie, NULL, mTask.id);
158 }
159
tempTimerCallback(uint32_t timerId,void * cookie)160 static void tempTimerCallback(uint32_t timerId, void *cookie)
161 {
162 osEnqueuePrivateEvt(EVT_SENSOR_TEMP_TIMER, cookie, NULL, mTask.id);
163 }
164
setMode(bool on,void * cookie)165 static void setMode(bool on, void *cookie)
166 {
167 mTask.txrxBuf[0] = BOSCH_BMP280_REG_CTRL_MEAS;
168 mTask.txrxBuf[1] = (on) ? CTRL_ON : CTRL_SLEEP;
169 i2cMasterTx(I2C_BUS_ID, I2C_ADDR, mTask.txrxBuf, 2, &i2cCallback,
170 cookie);
171 }
172
sendCalibrationResult(uint8_t status,float value)173 static void sendCalibrationResult(uint8_t status, float value) {
174 struct CalibrationData *data = heapAlloc(sizeof(struct CalibrationData));
175 if (!data) {
176 osLog(LOG_WARN, "Couldn't alloc cal result pkt");
177 return;
178 }
179
180 data->header.appId = BMP280_APP_ID;
181 data->header.dataLen = (sizeof(struct CalibrationData) - sizeof(struct HostHubRawPacket));
182 data->data_header.msgId = SENSOR_APP_MSG_ID_CAL_RESULT;
183 data->data_header.sensorType = SENS_TYPE_BARO;
184 data->data_header.status = status;
185
186 data->value = value;
187
188 if (!osEnqueueEvtOrFree(EVT_APP_TO_HOST, data, heapFree))
189 osLog(LOG_WARN, "Couldn't send cal result evt");
190 }
191
192 // TODO: only turn on the timer when enabled
sensorPowerBaro(bool on,void * cookie)193 static bool sensorPowerBaro(bool on, void *cookie)
194 {
195 bool oldMode = mTask.baroOn || mTask.tempOn;
196 bool newMode = on || mTask.tempOn;
197
198 if (!on && mTask.baroTimerHandle) {
199 timTimerCancel(mTask.baroTimerHandle);
200 mTask.baroTimerHandle = 0;
201 mTask.baroReading = false;
202 }
203
204 if (oldMode != newMode)
205 setMode(newMode, (void*)(on ? STATE_ENABLING_BARO : STATE_DISABLING_BARO));
206 else
207 sensorSignalInternalEvt(mTask.baroHandle, SENSOR_INTERNAL_EVT_POWER_STATE_CHG, on, 0);
208
209 mTask.baroOn = on;
210
211 return true;
212 }
213
sensorFirmwareBaro(void * cookie)214 static bool sensorFirmwareBaro(void *cookie)
215 {
216 return sensorSignalInternalEvt(mTask.baroHandle, SENSOR_INTERNAL_EVT_FW_STATE_CHG, 1, 0);
217 }
218
sensorRateBaro(uint32_t rate,uint64_t latency,void * cookie)219 static bool sensorRateBaro(uint32_t rate, uint64_t latency, void *cookie)
220 {
221 if (mTask.baroTimerHandle)
222 timTimerCancel(mTask.baroTimerHandle);
223 mTask.baroTimerHandle = timTimerSet(sensorTimerLookupCommon(baroSupportedRates, rateTimerValsBaro, rate), 0, 50, baroTimerCallback, NULL, false);
224 return sensorSignalInternalEvt(mTask.baroHandle, SENSOR_INTERNAL_EVT_RATE_CHG, rate, latency);
225 }
226
sensorFlushBaro(void * cookie)227 static bool sensorFlushBaro(void *cookie)
228 {
229 return osEnqueueEvt(sensorGetMyEventType(SENS_TYPE_BARO), SENSOR_DATA_EVENT_FLUSH, NULL);
230 }
231
sensorCalibrateBaro(void * cookie)232 static bool sensorCalibrateBaro(void *cookie)
233 {
234 if (mTask.baroOn || mTask.tempOn) {
235 osLog(LOG_ERROR, "BMP280: cannot calibrate while baro or temp are active\n");
236 sendCalibrationResult(SENSOR_APP_EVT_STATUS_BUSY, 0.0f);
237 return false;
238 }
239
240 if (mTask.baroTimerHandle)
241 timTimerCancel(mTask.baroTimerHandle);
242 mTask.baroTimerHandle = timTimerSet(100000000ull, 0, 50, baroTimerCallback, NULL, false);
243
244 mTask.offset = 0.0f;
245 mTask.baroOn = true;
246 mTask.baroCalibrating = true;
247
248 mTask.txrxBuf[0] = BOSCH_BMP280_REG_CTRL_MEAS;
249 mTask.txrxBuf[1] = CTRL_ON;
250 i2cMasterTx(I2C_BUS_ID, I2C_ADDR, mTask.txrxBuf, 2, &i2cCallback, (void*)STATE_IDLE);
251
252 return true;
253 }
254
sensorCfgDataBaro(void * data,void * cookie)255 static bool sensorCfgDataBaro(void *data, void *cookie)
256 {
257 mTask.offset = *((float*)data) * 100.0f; // offset is given in hPa, but used as Pa in compensation
258 return true;
259 }
260
sensorPowerTemp(bool on,void * cookie)261 static bool sensorPowerTemp(bool on, void *cookie)
262 {
263 bool oldMode = mTask.baroOn || mTask.tempOn;
264 bool newMode = on || mTask.baroOn;
265
266 if (!on && mTask.tempTimerHandle) {
267 timTimerCancel(mTask.tempTimerHandle);
268 mTask.tempTimerHandle = 0;
269 mTask.tempReading = false;
270 }
271
272 if (oldMode != newMode)
273 setMode(newMode, (void*)(on ? STATE_ENABLING_TEMP : STATE_DISABLING_TEMP));
274 else
275 sensorSignalInternalEvt(mTask.tempHandle, SENSOR_INTERNAL_EVT_POWER_STATE_CHG, on, 0);
276
277 mTask.tempOn = on;
278
279 return true;
280 }
281
sensorFirmwareTemp(void * cookie)282 static bool sensorFirmwareTemp(void *cookie)
283 {
284 sensorSignalInternalEvt(mTask.tempHandle, SENSOR_INTERNAL_EVT_FW_STATE_CHG, 1, 0);
285 return true;
286 }
287
sensorRateTemp(uint32_t rate,uint64_t latency,void * cookie)288 static bool sensorRateTemp(uint32_t rate, uint64_t latency, void *cookie)
289 {
290 if (mTask.tempTimerHandle)
291 timTimerCancel(mTask.tempTimerHandle);
292 mTask.tempTimerHandle = timTimerSet(sensorTimerLookupCommon(tempSupportedRates, rateTimerValsTemp, rate), 0, 50, tempTimerCallback, NULL, false);
293 sensorSignalInternalEvt(mTask.tempHandle, SENSOR_INTERNAL_EVT_RATE_CHG, rate, latency);
294 return true;
295 }
296
sensorFlushTemp(void * cookie)297 static bool sensorFlushTemp(void *cookie)
298 {
299 return osEnqueueEvt(sensorGetMyEventType(SENS_TYPE_TEMP), SENSOR_DATA_EVENT_FLUSH, NULL);
300 }
301
302 static const struct SensorInfo sensorInfoBaro =
303 {
304 .sensorName = "Pressure",
305 .supportedRates = baroSupportedRates,
306 .sensorType = SENS_TYPE_BARO,
307 .numAxis = NUM_AXIS_EMBEDDED,
308 .interrupt = NANOHUB_INT_NONWAKEUP,
309 .minSamples = 300
310 };
311
312 static const struct SensorOps sensorOpsBaro =
313 {
314 .sensorPower = sensorPowerBaro,
315 .sensorFirmwareUpload = sensorFirmwareBaro,
316 .sensorSetRate = sensorRateBaro,
317 .sensorFlush = sensorFlushBaro,
318 .sensorCalibrate = sensorCalibrateBaro,
319 .sensorCfgData = sensorCfgDataBaro,
320 };
321
322 static const struct SensorInfo sensorInfoTemp =
323 {
324 .sensorName = "Temperature",
325 .supportedRates = tempSupportedRates,
326 .sensorType = SENS_TYPE_TEMP,
327 .numAxis = NUM_AXIS_EMBEDDED,
328 .interrupt = NANOHUB_INT_NONWAKEUP,
329 .minSamples = 20
330 };
331
332 static const struct SensorOps sensorOpsTemp =
333 {
334 .sensorPower = sensorPowerTemp,
335 .sensorFirmwareUpload = sensorFirmwareTemp,
336 .sensorSetRate = sensorRateTemp,
337 .sensorFlush = sensorFlushTemp,
338 };
339
340 // Returns temperature in units of 0.01 degrees celsius.
compensateTemp(int32_t adc_T,int32_t * t_fine)341 static int32_t compensateTemp( int32_t adc_T, int32_t *t_fine)
342 {
343 int32_t var1 =
344 (((adc_T >> 3) - ((int32_t)mTask.comp.dig_T1 << 1))
345 * (int32_t)mTask.comp.dig_T2) >> 11;
346
347 int32_t tmp = (adc_T >> 4) - (int32_t)mTask.comp.dig_T1;
348
349 int32_t var2 = (((tmp * tmp) >> 12) * (int32_t)mTask.comp.dig_T3) >> 14;
350
351 int32_t sum = var1 + var2;
352
353 *t_fine = sum;
354
355 return (sum * 5 + 128) >> 8;
356 }
357
compensateBaro(int32_t t_fine,int32_t adc_P)358 static float compensateBaro(int32_t t_fine, int32_t adc_P)
359 {
360 float f = t_fine - 128000, fSqr = f * f;
361 float a = 1048576 - adc_P;
362 float v1, v2, p, pSqr;
363
364 v2 = fSqr * mTask.comp.dig_P6 + f * mTask.comp.dig_P5 * (float)(1ULL << 17) + mTask.comp.dig_P4 * (float)(1ULL << 35);
365 v1 = fSqr * mTask.comp.dig_P1 * mTask.comp.dig_P3 * (1.0f/(1ULL << 41)) + f * mTask.comp.dig_P1 * mTask.comp.dig_P2 * (1.0f/(1ULL << 21)) + mTask.comp.dig_P1 * (float)(1ULL << 14);
366
367 p = (a * (float)(1ULL << 31) - v2) * 3125 / v1;
368 pSqr = p * p;
369
370 return pSqr * mTask.comp.dig_P9 * (1.0f/(1ULL << 59)) + p * (mTask.comp.dig_P8 * (1.0f/(1ULL << 19)) + 1) * (1.0f/(1ULL << 8)) + 16.0f * mTask.comp.dig_P7;
371 }
372
getTempAndBaro(const uint8_t * tmp,float * pressure_Pa,float * temp_centigrade)373 static void getTempAndBaro(const uint8_t *tmp, float *pressure_Pa, float *temp_centigrade)
374 {
375 int32_t pres_adc = ((int32_t)tmp[0] << 12) | ((int32_t)tmp[1] << 4) | (tmp[2] >> 4);
376 int32_t temp_adc = ((int32_t)tmp[3] << 12) | ((int32_t)tmp[4] << 4) | (tmp[5] >> 4);
377
378 int32_t T_fine;
379 int32_t temp = compensateTemp(temp_adc, &T_fine);
380 float pres = compensateBaro(T_fine, pres_adc);
381
382 *temp_centigrade = (float)temp * 0.01f;
383 *pressure_Pa = pres * (1.0f / 256.0f) + mTask.offset;
384 }
385
handleI2cEvent(enum BMP280TaskState state)386 static void handleI2cEvent(enum BMP280TaskState state)
387 {
388 union EmbeddedDataPoint sample;
389
390 switch (state) {
391 case STATE_RESET: {
392 mTask.txrxBuf[0] = BOSCH_BMP280_REG_ID;
393 i2cMasterTxRx(I2C_BUS_ID, I2C_ADDR, mTask.txrxBuf, 1,
394 mTask.txrxBuf, 1, &i2cCallback,
395 (void*)STATE_VERIFY_ID);
396 break;
397 }
398
399 case STATE_VERIFY_ID: {
400 /* Check the sensor ID */
401 if (mTask.txrxBuf[0] != BOSCH_BMP280_ID) {
402 osLog(LOG_INFO, "BMP280: not detected\n");
403 break;
404 }
405
406 /* Get compensation parameters */
407 mTask.txrxBuf[0] = BOSCH_BMP280_REG_DIG_T1;
408 i2cMasterTxRx(I2C_BUS_ID, I2C_ADDR, mTask.txrxBuf, 1,
409 (uint8_t*)&mTask.comp, 24, &i2cCallback,
410 (void*)STATE_AWAITING_COMP_PARAMS);
411
412 break;
413 }
414
415 case STATE_AWAITING_COMP_PARAMS: {
416 mTask.txrxBuf[0] = BOSCH_BMP280_REG_CTRL_MEAS;
417 mTask.txrxBuf[1] = CTRL_SLEEP;
418 i2cMasterTx(I2C_BUS_ID, I2C_ADDR, mTask.txrxBuf, 2,
419 &i2cCallback, (void*)STATE_CONFIG);
420 break;
421 }
422
423 case STATE_CONFIG: {
424 mTask.txrxBuf[0] = BOSCH_BMP280_REG_CONFIG;
425 // standby time: 62.5ms, IIR filter coefficient: 4
426 mTask.txrxBuf[1] = (1 << 5) | (2 << 2);
427 i2cMasterTx(I2C_BUS_ID, I2C_ADDR, mTask.txrxBuf, 2,
428 &i2cCallback, (void*)STATE_FINISH_INIT);
429 }
430
431 case STATE_ENABLING_BARO: {
432 sensorSignalInternalEvt(mTask.baroHandle, SENSOR_INTERNAL_EVT_POWER_STATE_CHG, true, 0);
433 break;
434 }
435
436 case STATE_ENABLING_TEMP: {
437 sensorSignalInternalEvt(mTask.tempHandle, SENSOR_INTERNAL_EVT_POWER_STATE_CHG, true, 0);
438 break;
439 }
440
441 case STATE_DISABLING_BARO: {
442 sensorSignalInternalEvt(mTask.baroHandle, SENSOR_INTERNAL_EVT_POWER_STATE_CHG, false, 0);
443 break;
444 }
445
446 case STATE_DISABLING_TEMP: {
447 sensorSignalInternalEvt(mTask.tempHandle, SENSOR_INTERNAL_EVT_POWER_STATE_CHG, false, 0);
448 break;
449 }
450
451 case STATE_FINISH_INIT: {
452 sensorRegisterInitComplete(mTask.baroHandle);
453 sensorRegisterInitComplete(mTask.tempHandle);
454 break;
455 }
456
457 case STATE_SAMPLING: {
458 float pressure_Pa, temp_centigrade;
459 getTempAndBaro(mTask.txrxBuf, &pressure_Pa, &temp_centigrade);
460
461 if (mTask.baroOn && mTask.baroReading) {
462 if (mTask.baroCalibrating) {
463 sendCalibrationResult(SENSOR_APP_EVT_STATUS_SUCCESS, pressure_Pa * 0.01f);
464
465 if (mTask.baroTimerHandle)
466 timTimerCancel(mTask.baroTimerHandle);
467
468 mTask.baroOn = false;
469 mTask.baroCalibrating = false;
470
471 mTask.txrxBuf[0] = BOSCH_BMP280_REG_CTRL_MEAS;
472 mTask.txrxBuf[1] = CTRL_SLEEP;
473 i2cMasterTx(I2C_BUS_ID, I2C_ADDR, mTask.txrxBuf, 2, &i2cCallback, (void*)STATE_IDLE);
474 } else {
475 sample.fdata = pressure_Pa * 0.01f;
476 osEnqueueEvt(sensorGetMyEventType(SENS_TYPE_BARO), sample.vptr, NULL);
477 }
478 }
479
480 if (mTask.tempOn && mTask.tempReading) {
481 sample.fdata = temp_centigrade;
482 osEnqueueEvt(sensorGetMyEventType(SENS_TYPE_TEMP), sample.vptr, NULL);
483 }
484
485 mTask.baroReading = false;
486 mTask.tempReading = false;
487
488 break;
489 }
490
491 default:
492 break;
493 }
494 }
495
handleEvent(uint32_t evtType,const void * evtData)496 static void handleEvent(uint32_t evtType, const void* evtData)
497 {
498 switch (evtType) {
499 case EVT_APP_START:
500 {
501 osEventUnsubscribe(mTask.id, EVT_APP_START);
502 i2cMasterRequest(I2C_BUS_ID, I2C_SPEED);
503
504 /* Reset chip */
505 mTask.txrxBuf[0] = BOSCH_BMP280_REG_RESET;
506 mTask.txrxBuf[1] = 0xB6;
507 i2cMasterTx(I2C_BUS_ID, I2C_ADDR, mTask.txrxBuf, 2,
508 &i2cCallback, (void*)STATE_RESET);
509 break;
510 }
511
512 case EVT_SENSOR_I2C:
513 {
514 handleI2cEvent((enum BMP280TaskState)evtData);
515 break;
516 }
517
518 case EVT_SENSOR_BARO_TIMER:
519 {
520 /* Start sampling for a value */
521 if (!mTask.baroReading && !mTask.tempReading) {
522 mTask.txrxBuf[0] = BOSCH_BMP280_REG_PRES_MSB;
523 i2cMasterTxRx(I2C_BUS_ID, I2C_ADDR, mTask.txrxBuf, 1,
524 mTask.txrxBuf, 6, &i2cCallback,
525 (void*)STATE_SAMPLING);
526 }
527
528 mTask.baroReading = true;
529 break;
530 }
531
532 case EVT_SENSOR_TEMP_TIMER:
533 {
534 /* Start sampling for a value */
535 if (!mTask.baroReading && !mTask.tempReading) {
536 mTask.txrxBuf[0] = BOSCH_BMP280_REG_PRES_MSB;
537 i2cMasterTxRx(I2C_BUS_ID, I2C_ADDR, mTask.txrxBuf, 1,
538 mTask.txrxBuf, 6, &i2cCallback,
539 (void*)STATE_SAMPLING);
540
541 }
542
543 mTask.tempReading = true;
544 break;
545 }
546 }
547 }
548
startTask(uint32_t taskId)549 static bool startTask(uint32_t taskId)
550 {
551 mTask.id = taskId;
552 mTask.offset = 0.0f;
553
554 /* Register sensors */
555 mTask.baroHandle = sensorRegister(&sensorInfoBaro, &sensorOpsBaro, NULL, false);
556 mTask.tempHandle = sensorRegister(&sensorInfoTemp, &sensorOpsTemp, NULL, false);
557
558 osEventSubscribe(taskId, EVT_APP_START);
559
560 return true;
561 }
562
endTask(void)563 static void endTask(void)
564 {
565
566 }
567
568 INTERNAL_APP_INIT(BMP280_APP_ID, BMP280_APP_VERSION, startTask, endTask, handleEvent);
569