Home | History | Annotate | Download | only in bosch_bmp280
      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