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