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