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