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 <slab.h>
29 #include <timer.h>
30 #include <util.h>
31 #include <variant/variant.h>
32
33 #define BMP280_APP_ID APP_ID_MAKE(NANOHUB_VENDOR_GOOGLE, 5)
34
35 #define BMP280_APP_VERSION 4
36
37 #ifndef BMP280_I2C_BUS_ID
38 #define BMP280_I2C_BUS_ID 0
39 #endif
40
41 #define I2C_BUS_ID BMP280_I2C_BUS_ID
42 #define I2C_SPEED 400000
43 #define I2C_ADDR 0x76
44
45 #define BOSCH_BMP280_ID 0x58
46
47 #define BOSCH_BMP280_REG_RESET 0xE0
48 #define BOSCH_BMP280_REG_DIG_T1 0x88
49 #define BOSCH_BMP280_REG_ID 0xd0
50 #define BOSCH_BMP280_REG_CTRL_MEAS 0xf4
51 #define BOSCH_BMP280_REG_CONFIG 0xf5
52 #define BOSCH_BMP280_REG_PRES_MSB 0xf7
53
54 #define BOSCH_BMP280_SOFT_RESET_CMD 0xB6
55
56 #define BOSCH_BMP280_MAX_PENDING_I2C_REQUESTS 4
57 #define BOSCH_BMP280_MAX_I2C_TRANSFER_SIZE 6
58
59 // This defines how many baro events we could handle being backed up in the
60 // queue. Use this to size our slab
61 #define MAX_BARO_EVENTS 4
62
63 // temp: 2x oversampling, baro: 16x oversampling, power: normal
64 #define CTRL_ON ((2 << 5) | (5 << 2) | 3)
65 // temp: 2x oversampling, baro: 16x oversampling, power: sleep
66 #define CTRL_SLEEP ((2 << 5) | (5 << 2))
67 // config: standby time: 62.5ms, IIR filter coefficient: 4
68 #define CTRL_CFG ((1 << 5) | (2 << 2))
69
70 enum BMP280SensorEvents
71 {
72 EVT_SENSOR_I2C = EVT_APP_START + 1,
73 EVT_SENSOR_BARO_TIMER,
74 EVT_SENSOR_TEMP_TIMER,
75 EVT_SENSOR_SOFTRESET_TIMER,
76 };
77
78 enum BMP280TaskState
79 {
80 STATE_RESET,
81 STATE_SOFTRESET,
82 STATE_SOFTRESET_MODE,
83 STATE_VERIFY_ID,
84 STATE_AWAITING_COMP_PARAMS,
85 STATE_CONFIG,
86 STATE_FINISH_INIT,
87 STATE_IDLE,
88 STATE_ENABLING_BARO_TEMP,
89 STATE_ENABLING_BARO,
90 STATE_ENABLING_TEMP,
91 STATE_DISABLING_BARO,
92 STATE_DISABLING_TEMP,
93 STATE_SAMPLING,
94 };
95
96 struct BMP280CompParams
97 {
98 uint16_t dig_T1;
99 int16_t dig_T2, dig_T3;
100 uint16_t dig_P1;
101 int16_t dig_P2, dig_P3, dig_P4, dig_P5, dig_P6, dig_P7, dig_P8, dig_P9;
102 } __attribute__((packed));
103
104 struct I2cTransfer
105 {
106 size_t tx;
107 size_t rx;
108 int err;
109 uint8_t txrxBuf[BOSCH_BMP280_MAX_I2C_TRANSFER_SIZE];
110 uint8_t state;
111 bool inUse;
112 };
113
114 static struct BMP280Task
115 {
116 struct BMP280CompParams comp;
117
118 struct SlabAllocator *evtSlab;
119
120 uint32_t id;
121 uint32_t baroHandle;
122 uint32_t tempHandle;
123 uint32_t baroTimerHandle;
124 uint32_t tempTimerHandle;
125 uint32_t resetHandle;
126
127 float offset;
128
129 struct I2cTransfer transfers[BOSCH_BMP280_MAX_PENDING_I2C_REQUESTS];
130
131 bool tmpbaroOn;
132 bool tmptempOn;
133 bool baroOn;
134 bool tempOn;
135 bool baroReading;
136 bool baroCalibrating;
137 bool tempReading;
138 } mTask;
139
140 struct CalibrationData {
141 struct HostHubRawPacket header;
142 struct SensorAppEventHeader data_header;
143 float value;
144 } __attribute__((packed));
145
146 static const uint32_t tempSupportedRates[] =
147 {
148 SENSOR_HZ(0.1),
149 SENSOR_HZ(1),
150 SENSOR_HZ(5),
151 SENSOR_HZ(10),
152 SENSOR_HZ(25),
153 0,
154 };
155
156 static const uint64_t rateTimerValsTemp[] = //should match "supported rates in length" and be the timer length for that rate in nanosecs
157 {
158 10 * 1000000000ULL,
159 1 * 1000000000ULL,
160 1000000000ULL / 5,
161 1000000000ULL / 10,
162 1000000000ULL / 25,
163 };
164
165 static const uint32_t baroSupportedRates[] =
166 {
167 SENSOR_HZ(0.1),
168 SENSOR_HZ(1),
169 SENSOR_HZ(5),
170 SENSOR_HZ(10),
171 0
172 };
173
174 static const uint64_t rateTimerValsBaro[] = //should match "supported rates in length" and be the timer length for that rate in nanosecs
175 {
176 10 * 1000000000ULL,
177 1 * 1000000000ULL,
178 1000000000ULL / 5,
179 1000000000ULL / 10,
180 };
181
182 static void i2cCallback(void *cookie, size_t tx, size_t rx, int err);
183
184 // Allocate a buffer and mark it as in use with the given state, or return NULL
185 // if no buffers available. Must *not* be called from interrupt context.
allocXfer(uint8_t state)186 static struct I2cTransfer *allocXfer(uint8_t state)
187 {
188 size_t i;
189
190 for (i = 0; i < ARRAY_SIZE(mTask.transfers); i++) {
191 if (!mTask.transfers[i].inUse) {
192 mTask.transfers[i].inUse = true;
193 mTask.transfers[i].state = state;
194 return &mTask.transfers[i];
195 }
196 }
197
198 osLog(LOG_ERROR, "[BMP280]: Ran out of i2c buffers!");
199 return NULL;
200 }
201
202 // Helper function to release I2cTransfer structure
releaseXfer(struct I2cTransfer * xfer)203 static inline void releaseXfer(struct I2cTransfer *xfer)
204 {
205 xfer->inUse = false;
206 }
207
208 // Helper function to write a one byte register. Returns true if we got a
209 // successful return value from i2cMasterTx().
writeRegister(uint8_t reg,uint8_t value,uint8_t state)210 static bool writeRegister(uint8_t reg, uint8_t value, uint8_t state)
211 {
212 struct I2cTransfer *xfer = allocXfer(state);
213 int ret = -1;
214
215 if (xfer != NULL) {
216 xfer->txrxBuf[0] = reg;
217 xfer->txrxBuf[1] = value;
218 ret = i2cMasterTx(I2C_BUS_ID, I2C_ADDR, xfer->txrxBuf, 2, i2cCallback, xfer);
219 if (ret)
220 releaseXfer(xfer);
221 }
222
223 return (ret == 0);
224 }
225
baroAllocateEvt(struct SingleAxisDataEvent ** evPtr,float sample,uint64_t time)226 static bool baroAllocateEvt(struct SingleAxisDataEvent **evPtr, float sample, uint64_t time)
227 {
228 struct SingleAxisDataEvent *ev;
229
230 *evPtr = slabAllocatorAlloc(mTask.evtSlab);
231
232 ev = *evPtr;
233 if (!ev) {
234 osLog(LOG_ERROR, "[BMP280] slabAllocatorAlloc() failed\n");
235 return false;
236 }
237
238 memset(&ev->samples[0].firstSample, 0x00, sizeof(struct SensorFirstSample));
239 ev->referenceTime = time;
240 ev->samples[0].firstSample.numSamples = 1;
241 ev->samples[0].fdata = sample;
242
243 return true;
244 }
245
baroFreeEvt(void * ptr)246 static void baroFreeEvt(void *ptr)
247 {
248 slabAllocatorFree(mTask.evtSlab, ptr);
249 }
250
251 /* sensor callbacks from nanohub */
252
i2cCallback(void * cookie,size_t tx,size_t rx,int err)253 static void i2cCallback(void *cookie, size_t tx, size_t rx, int err)
254 {
255 struct I2cTransfer *xfer = cookie;
256
257 xfer->tx = tx;
258 xfer->rx = rx;
259 xfer->err = err;
260
261 osEnqueuePrivateEvt(EVT_SENSOR_I2C, cookie, NULL, mTask.id);
262 if (err != 0)
263 osLog(LOG_INFO, "[BMP280] i2c error (tx: %d, rx: %d, err: %d)\n", tx, rx, err);
264 }
265
baroTimerCallback(uint32_t timerId,void * cookie)266 static void baroTimerCallback(uint32_t timerId, void *cookie)
267 {
268 osEnqueuePrivateEvt(EVT_SENSOR_BARO_TIMER, cookie, NULL, mTask.id);
269 }
270
tempTimerCallback(uint32_t timerId,void * cookie)271 static void tempTimerCallback(uint32_t timerId, void *cookie)
272 {
273 osEnqueuePrivateEvt(EVT_SENSOR_TEMP_TIMER, cookie, NULL, mTask.id);
274 }
275
softresetCallback(uint32_t timerId,void * cookie)276 static void softresetCallback(uint32_t timerId, void *cookie)
277 {
278 osEnqueuePrivateEvt(EVT_SENSOR_SOFTRESET_TIMER, cookie, NULL, mTask.id);
279 }
280
softreset()281 static void softreset()
282 {
283 writeRegister(BOSCH_BMP280_REG_RESET, BOSCH_BMP280_SOFT_RESET_CMD, STATE_SOFTRESET);
284 }
285
setMode(bool on,uint8_t state)286 static void setMode(bool on, uint8_t state)
287 {
288 writeRegister(BOSCH_BMP280_REG_CTRL_MEAS, (on) ? CTRL_ON : CTRL_SLEEP, state);
289 }
290
sendCalibrationResult(uint8_t status,float value)291 static void sendCalibrationResult(uint8_t status, float value) {
292 struct CalibrationData *data = heapAlloc(sizeof(struct CalibrationData));
293 if (!data) {
294 osLog(LOG_WARN, "[BMP280] Couldn't alloc cal result pkt");
295 return;
296 }
297
298 data->header.appId = BMP280_APP_ID;
299 data->header.dataLen = (sizeof(struct CalibrationData) - sizeof(struct HostHubRawPacket));
300 data->data_header.msgId = SENSOR_APP_MSG_ID_CAL_RESULT;
301 data->data_header.sensorType = SENS_TYPE_BARO;
302 data->data_header.status = status;
303
304 data->value = value;
305
306 if (!osEnqueueEvtOrFree(EVT_APP_TO_HOST, data, heapFree))
307 osLog(LOG_WARN, "[BMP280] Couldn't send cal result evt");
308 }
309
310 // TODO: only turn on the timer when enabled
sensorPowerBaro(bool on,void * cookie)311 static bool sensorPowerBaro(bool on, void *cookie)
312 {
313 bool oldMode = mTask.baroOn || mTask.tempOn;
314 bool newMode = on || mTask.tempOn;
315
316 if (!on && mTask.baroTimerHandle) {
317 timTimerCancel(mTask.baroTimerHandle);
318 mTask.baroTimerHandle = 0;
319 mTask.baroReading = false;
320 }
321
322 if (!on && mTask.tmpbaroOn && mTask.resetHandle)
323 {
324 if (!mTask.tmptempOn) {
325 timTimerCancel(mTask.resetHandle);
326 mTask.resetHandle = 0;
327 }
328 mTask.tmpbaroOn = 0;
329 sensorSignalInternalEvt(mTask.baroHandle, SENSOR_INTERNAL_EVT_POWER_STATE_CHG, true, 0);
330 }
331
332 if (oldMode != newMode)
333 {
334 if (newMode == 0)
335 {
336 setMode(newMode, STATE_DISABLING_BARO);
337 mTask.baroOn = false;
338 }
339 else
340 {
341 mTask.tmpbaroOn = true;
342 if (!mTask.tmptempOn) {
343 // do soft reset first when newMode is on
344 softreset();
345 }
346 }
347 }
348 else
349 {
350 sensorSignalInternalEvt(mTask.baroHandle, SENSOR_INTERNAL_EVT_POWER_STATE_CHG, on, 0);
351 mTask.baroOn = on;
352 }
353
354 return true;
355 }
356
sensorFirmwareBaro(void * cookie)357 static bool sensorFirmwareBaro(void *cookie)
358 {
359 return sensorSignalInternalEvt(mTask.baroHandle, SENSOR_INTERNAL_EVT_FW_STATE_CHG, 1, 0);
360 }
361
sensorRateBaro(uint32_t rate,uint64_t latency,void * cookie)362 static bool sensorRateBaro(uint32_t rate, uint64_t latency, void *cookie)
363 {
364 if (mTask.baroTimerHandle)
365 timTimerCancel(mTask.baroTimerHandle);
366 mTask.baroTimerHandle = timTimerSet(sensorTimerLookupCommon(baroSupportedRates, rateTimerValsBaro, rate), 0, 50, baroTimerCallback, NULL, false);
367 return sensorSignalInternalEvt(mTask.baroHandle, SENSOR_INTERNAL_EVT_RATE_CHG, rate, latency);
368 }
369
sensorFlushBaro(void * cookie)370 static bool sensorFlushBaro(void *cookie)
371 {
372 return osEnqueueEvt(sensorGetMyEventType(SENS_TYPE_BARO), SENSOR_DATA_EVENT_FLUSH, NULL);
373 }
374
sensorCalibrateBaro(void * cookie)375 static bool sensorCalibrateBaro(void *cookie)
376 {
377 if (mTask.baroOn || mTask.tempOn) {
378 osLog(LOG_ERROR, "[BMP280] cannot calibrate while baro or temp are active\n");
379 sendCalibrationResult(SENSOR_APP_EVT_STATUS_BUSY, 0.0f);
380 return false;
381 }
382
383 if (mTask.baroTimerHandle)
384 timTimerCancel(mTask.baroTimerHandle);
385 mTask.baroTimerHandle = timTimerSet(100000000ull, 0, 50, baroTimerCallback, NULL, false);
386
387 mTask.offset = 0.0f;
388 mTask.baroOn = true;
389 mTask.baroCalibrating = true;
390
391 return writeRegister(BOSCH_BMP280_REG_CTRL_MEAS, CTRL_ON, STATE_IDLE);
392 }
393
sensorCfgDataBaro(void * data,void * cookie)394 static bool sensorCfgDataBaro(void *data, void *cookie)
395 {
396 mTask.offset = *((float*)data) * 100.0f; // offset is given in hPa, but used as Pa in compensation
397 return true;
398 }
399
sensorPowerTemp(bool on,void * cookie)400 static bool sensorPowerTemp(bool on, void *cookie)
401 {
402 bool oldMode = mTask.baroOn || mTask.tempOn;
403 bool newMode = on || mTask.baroOn;
404
405 if (!on && mTask.tempTimerHandle) {
406 timTimerCancel(mTask.tempTimerHandle);
407 mTask.tempTimerHandle = 0;
408 mTask.tempReading = false;
409 }
410
411 if (!on && mTask.tmptempOn && mTask.resetHandle)
412 {
413 if(!mTask.tmpbaroOn) {
414 timTimerCancel(mTask.resetHandle);
415 mTask.resetHandle = 0;
416 }
417 mTask.tmptempOn = 0;
418 sensorSignalInternalEvt(mTask.tempHandle, SENSOR_INTERNAL_EVT_POWER_STATE_CHG, true, 0);
419 }
420
421 if (oldMode != newMode)
422 {
423 if (newMode == 0)
424 {
425 setMode(newMode, STATE_DISABLING_TEMP);
426 mTask.tempOn = false;
427 }
428 else
429 {
430 mTask.tmptempOn = true;
431 if (!mTask.tmpbaroOn) {
432 // do soft reset first when newMode is on
433 softreset();
434 }
435 }
436 }
437 else
438 {
439 sensorSignalInternalEvt(mTask.tempHandle, SENSOR_INTERNAL_EVT_POWER_STATE_CHG, on, 0);
440 mTask.tempOn = on;
441 }
442
443
444 return true;
445 }
446
sensorFirmwareTemp(void * cookie)447 static bool sensorFirmwareTemp(void *cookie)
448 {
449 sensorSignalInternalEvt(mTask.tempHandle, SENSOR_INTERNAL_EVT_FW_STATE_CHG, 1, 0);
450 return true;
451 }
452
sensorRateTemp(uint32_t rate,uint64_t latency,void * cookie)453 static bool sensorRateTemp(uint32_t rate, uint64_t latency, void *cookie)
454 {
455 if (mTask.tempTimerHandle)
456 timTimerCancel(mTask.tempTimerHandle);
457 mTask.tempTimerHandle = timTimerSet(sensorTimerLookupCommon(tempSupportedRates, rateTimerValsTemp, rate), 0, 50, tempTimerCallback, NULL, false);
458 sensorSignalInternalEvt(mTask.tempHandle, SENSOR_INTERNAL_EVT_RATE_CHG, rate, latency);
459 return true;
460 }
461
sensorFlushTemp(void * cookie)462 static bool sensorFlushTemp(void *cookie)
463 {
464 return osEnqueueEvt(sensorGetMyEventType(SENS_TYPE_TEMP), SENSOR_DATA_EVENT_FLUSH, NULL);
465 }
466
467 static const struct SensorInfo sensorInfoBaro =
468 {
469 .sensorName = "Pressure",
470 .supportedRates = baroSupportedRates,
471 .sensorType = SENS_TYPE_BARO,
472 .numAxis = NUM_AXIS_ONE,
473 .interrupt = NANOHUB_INT_NONWAKEUP,
474 .minSamples = 300
475 };
476
477 static const struct SensorOps sensorOpsBaro =
478 {
479 .sensorPower = sensorPowerBaro,
480 .sensorFirmwareUpload = sensorFirmwareBaro,
481 .sensorSetRate = sensorRateBaro,
482 .sensorFlush = sensorFlushBaro,
483 .sensorCalibrate = sensorCalibrateBaro,
484 .sensorCfgData = sensorCfgDataBaro,
485 };
486
487 static const struct SensorInfo sensorInfoTemp =
488 {
489 .sensorName = "Temperature",
490 .supportedRates = tempSupportedRates,
491 .sensorType = SENS_TYPE_TEMP,
492 .numAxis = NUM_AXIS_EMBEDDED,
493 .interrupt = NANOHUB_INT_NONWAKEUP,
494 .minSamples = 20
495 };
496
497 static const struct SensorOps sensorOpsTemp =
498 {
499 .sensorPower = sensorPowerTemp,
500 .sensorFirmwareUpload = sensorFirmwareTemp,
501 .sensorSetRate = sensorRateTemp,
502 .sensorFlush = sensorFlushTemp,
503 };
504
505 // Returns temperature in units of 0.01 degrees celsius.
compensateTemp(int32_t adc_T,int32_t * t_fine)506 static int32_t compensateTemp( int32_t adc_T, int32_t *t_fine)
507 {
508 int32_t var1 =
509 (((adc_T >> 3) - ((int32_t)mTask.comp.dig_T1 << 1))
510 * (int32_t)mTask.comp.dig_T2) >> 11;
511
512 int32_t tmp = (adc_T >> 4) - (int32_t)mTask.comp.dig_T1;
513
514 int32_t var2 = (((tmp * tmp) >> 12) * (int32_t)mTask.comp.dig_T3) >> 14;
515
516 int32_t sum = var1 + var2;
517
518 *t_fine = sum;
519
520 return (sum * 5 + 128) >> 8;
521 }
522
compensateBaro(int32_t t_fine,int32_t adc_P)523 static float compensateBaro(int32_t t_fine, int32_t adc_P)
524 {
525 float f = t_fine - 128000, fSqr = f * f;
526 float a = 1048576 - adc_P;
527 float v1, v2, p, pSqr;
528
529 v2 = fSqr * mTask.comp.dig_P6 + f * mTask.comp.dig_P5 * (float)(1ULL << 17) + mTask.comp.dig_P4 * (float)(1ULL << 35);
530 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);
531
532 p = (a * (float)(1ULL << 31) - v2) * 3125 / v1;
533 pSqr = p * p;
534
535 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;
536 }
537
getTempAndBaro(const uint8_t * tmp,float * pressure_Pa,float * temp_centigrade)538 static void getTempAndBaro(const uint8_t *tmp, float *pressure_Pa, float *temp_centigrade)
539 {
540 int32_t pres_adc = ((int32_t)tmp[0] << 12) | ((int32_t)tmp[1] << 4) | (tmp[2] >> 4);
541 int32_t temp_adc = ((int32_t)tmp[3] << 12) | ((int32_t)tmp[4] << 4) | (tmp[5] >> 4);
542
543 int32_t T_fine;
544 int32_t temp = compensateTemp(temp_adc, &T_fine);
545 float pres = compensateBaro(T_fine, pres_adc);
546
547 *temp_centigrade = (float)temp * 0.01f;
548 *pressure_Pa = pres * (1.0f / 256.0f) + mTask.offset;
549 }
550
handleI2cEvent(struct I2cTransfer * xfer)551 static void handleI2cEvent(struct I2cTransfer *xfer)
552 {
553 union EmbeddedDataPoint embeddedSample;
554 struct SingleAxisDataEvent *baroSample;
555 struct I2cTransfer *newXfer;
556 int ret;
557
558 switch (xfer->state) {
559 case STATE_RESET: {
560 newXfer = allocXfer(STATE_VERIFY_ID);
561 if (newXfer != NULL) {
562 newXfer->txrxBuf[0] = BOSCH_BMP280_REG_ID;
563 ret = i2cMasterTxRx(I2C_BUS_ID, I2C_ADDR, newXfer->txrxBuf, 1, newXfer->txrxBuf, 1, i2cCallback, newXfer);
564 if (ret)
565 releaseXfer(newXfer);
566 }
567 break;
568 }
569
570 case STATE_SOFTRESET: {
571 //create timer for 2ms delay
572 mTask.resetHandle = timTimerSet(2000000ull, 0, 50, softresetCallback, NULL, true);
573 break;
574 }
575
576 case STATE_SOFTRESET_MODE: {
577 if (mTask.tmpbaroOn && mTask.tmptempOn) {
578 setMode(true,STATE_ENABLING_BARO_TEMP);
579 mTask.tmpbaroOn = false;
580 mTask.baroOn = true;
581 mTask.tmptempOn = false;
582 mTask.tempOn = true;
583 } else if (mTask.tmpbaroOn) {
584 setMode(true,STATE_ENABLING_BARO);
585 mTask.tmpbaroOn = false;
586 mTask.baroOn = true;
587 } else if (mTask.tmptempOn) {
588 setMode(true,STATE_ENABLING_TEMP);
589 mTask.tmptempOn = false;
590 mTask.tempOn = true;
591 }
592 break;
593 }
594
595 case STATE_VERIFY_ID: {
596 /* Check the sensor ID */
597 if (xfer->err != 0 || xfer->txrxBuf[0] != BOSCH_BMP280_ID) {
598 osLog(LOG_INFO, "[BMP280] not detected\n");
599 break;
600 }
601
602 /* Get compensation parameters */
603 newXfer = allocXfer(STATE_AWAITING_COMP_PARAMS);
604 if (newXfer != NULL) {
605 newXfer->txrxBuf[0] = BOSCH_BMP280_REG_DIG_T1;
606 ret = i2cMasterTxRx(I2C_BUS_ID, I2C_ADDR, newXfer->txrxBuf, 1, (uint8_t*)&mTask.comp, 24, i2cCallback, newXfer);
607 if (ret)
608 releaseXfer(newXfer);
609 }
610
611 break;
612 }
613
614 case STATE_AWAITING_COMP_PARAMS: {
615 writeRegister(BOSCH_BMP280_REG_CTRL_MEAS, CTRL_SLEEP, STATE_CONFIG);
616 break;
617 }
618
619 case STATE_CONFIG: {
620 // standby time: 62.5ms, IIR filter coefficient: 4
621 writeRegister(BOSCH_BMP280_REG_CONFIG, CTRL_CFG, STATE_FINISH_INIT);
622 break;
623 }
624
625 case STATE_ENABLING_BARO_TEMP: {
626 sensorSignalInternalEvt(mTask.baroHandle, SENSOR_INTERNAL_EVT_POWER_STATE_CHG, true, 0);
627 sensorSignalInternalEvt(mTask.tempHandle, SENSOR_INTERNAL_EVT_POWER_STATE_CHG, true, 0);
628 break;
629 }
630
631 case STATE_ENABLING_BARO: {
632 sensorSignalInternalEvt(mTask.baroHandle, SENSOR_INTERNAL_EVT_POWER_STATE_CHG, true, 0);
633 break;
634 }
635
636 case STATE_ENABLING_TEMP: {
637 sensorSignalInternalEvt(mTask.tempHandle, SENSOR_INTERNAL_EVT_POWER_STATE_CHG, true, 0);
638 break;
639 }
640
641 case STATE_DISABLING_BARO: {
642 sensorSignalInternalEvt(mTask.baroHandle, SENSOR_INTERNAL_EVT_POWER_STATE_CHG, false, 0);
643 break;
644 }
645
646 case STATE_DISABLING_TEMP: {
647 sensorSignalInternalEvt(mTask.tempHandle, SENSOR_INTERNAL_EVT_POWER_STATE_CHG, false, 0);
648 break;
649 }
650
651 case STATE_FINISH_INIT: {
652 osLog(LOG_INFO, "[BMP280] detected\n");
653 sensorRegisterInitComplete(mTask.baroHandle);
654 sensorRegisterInitComplete(mTask.tempHandle);
655 break;
656 }
657
658 case STATE_SAMPLING: {
659 float pressure_Pa, temp_centigrade;
660 getTempAndBaro(xfer->txrxBuf, &pressure_Pa, &temp_centigrade);
661
662 if (mTask.baroOn && mTask.baroReading) {
663 if (mTask.baroCalibrating) {
664 sendCalibrationResult(SENSOR_APP_EVT_STATUS_SUCCESS, pressure_Pa * 0.01f);
665
666 if (mTask.baroTimerHandle)
667 timTimerCancel(mTask.baroTimerHandle);
668
669 mTask.baroOn = false;
670 mTask.baroCalibrating = false;
671
672 writeRegister(BOSCH_BMP280_REG_CTRL_MEAS, CTRL_SLEEP, STATE_IDLE);
673 } else {
674 if (baroAllocateEvt(&baroSample, pressure_Pa * 0.01f, sensorGetTime())) {
675 if (!osEnqueueEvtOrFree(EVENT_TYPE_BIT_DISCARDABLE | sensorGetMyEventType(SENS_TYPE_BARO), baroSample, baroFreeEvt)) {
676 osLog(LOG_ERROR, "[BMP280] failed to enqueue baro sample\n");
677 }
678 }
679 }
680 }
681
682 if (mTask.tempOn && mTask.tempReading) {
683 embeddedSample.fdata = temp_centigrade;
684 osEnqueueEvt(sensorGetMyEventType(SENS_TYPE_TEMP), embeddedSample.vptr, NULL);
685 }
686
687 mTask.baroReading = false;
688 mTask.tempReading = false;
689
690 break;
691 }
692
693 default:
694 break;
695 }
696
697 releaseXfer(xfer);
698 }
699
handleEvent(uint32_t evtType,const void * evtData)700 static void handleEvent(uint32_t evtType, const void* evtData)
701 {
702 struct I2cTransfer *newXfer;
703 int ret;
704
705 switch (evtType) {
706 case EVT_APP_START:
707 {
708 osEventUnsubscribe(mTask.id, EVT_APP_START);
709 i2cMasterRequest(I2C_BUS_ID, I2C_SPEED);
710
711 /* Reset chip */
712 writeRegister(BOSCH_BMP280_REG_RESET, BOSCH_BMP280_SOFT_RESET_CMD, STATE_RESET);
713 break;
714 }
715
716 case EVT_SENSOR_I2C:
717 {
718 handleI2cEvent((struct I2cTransfer *)evtData);
719 break;
720 }
721
722 case EVT_SENSOR_BARO_TIMER:
723 {
724 /* Start sampling for a value */
725 if (!mTask.baroReading && !mTask.tempReading) {
726 newXfer = allocXfer(STATE_SAMPLING);
727 if (newXfer != NULL) {
728 newXfer->txrxBuf[0] = BOSCH_BMP280_REG_PRES_MSB;
729 ret = i2cMasterTxRx(I2C_BUS_ID, I2C_ADDR, newXfer->txrxBuf, 1, newXfer->txrxBuf, 6, i2cCallback, newXfer);
730 if (ret)
731 releaseXfer(newXfer);
732 }
733 }
734
735 mTask.baroReading = true;
736 break;
737 }
738
739 case EVT_SENSOR_TEMP_TIMER:
740 {
741 /* Start sampling for a value */
742 if (!mTask.baroReading && !mTask.tempReading) {
743 newXfer = allocXfer(STATE_SAMPLING);
744 if (newXfer != NULL) {
745 newXfer->txrxBuf[0] = BOSCH_BMP280_REG_PRES_MSB;
746 ret = i2cMasterTxRx(I2C_BUS_ID, I2C_ADDR, newXfer->txrxBuf, 1, newXfer->txrxBuf, 6, i2cCallback, newXfer);
747 if (ret)
748 releaseXfer(newXfer);
749 }
750 }
751
752 mTask.tempReading = true;
753 break;
754 }
755
756 case EVT_SENSOR_SOFTRESET_TIMER:
757 {
758 writeRegister(BOSCH_BMP280_REG_CONFIG, CTRL_CFG, STATE_SOFTRESET_MODE);
759 break;
760 }
761 }
762 }
763
startTask(uint32_t taskId)764 static bool startTask(uint32_t taskId)
765 {
766 mTask.id = taskId;
767 mTask.offset = 0.0f;
768
769 /* Register sensors */
770 mTask.baroHandle = sensorRegister(&sensorInfoBaro, &sensorOpsBaro, NULL, false);
771 mTask.tempHandle = sensorRegister(&sensorInfoTemp, &sensorOpsTemp, NULL, false);
772
773 mTask.evtSlab = slabAllocatorNew(sizeof(struct SingleAxisDataEvent) + sizeof(struct SingleAxisDataPoint), 4, MAX_BARO_EVENTS);
774 if (!mTask.evtSlab) {
775 osLog(LOG_ERROR, "[BMP280] slabAllocatorNew() failed\n");
776 return false;
777 }
778
779 osEventSubscribe(taskId, EVT_APP_START);
780
781 return true;
782 }
783
endTask(void)784 static void endTask(void)
785 {
786 slabAllocatorDestroy(mTask.evtSlab);
787 }
788
789 INTERNAL_APP_INIT(BMP280_APP_ID, BMP280_APP_VERSION, startTask, endTask, handleEvent);
790