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