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