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