1 /*
2  * Copyright (C) 2017 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 <atomic.h>
18 #include <gpio.h>
19 #include <nanohubPacket.h>
20 #include <plat/exti.h>
21 #include <plat/gpio.h>
22 #include <platform.h>
23 #include <plat/syscfg.h>
24 #include <sensors.h>
25 #include <seos.h>
26 #include <slab.h>
27 #include <i2c.h>
28 #include <timer.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <variant/variant.h>
32 
33 #define SI7034A10_APP_ID                APP_ID_MAKE(NANOHUB_VENDOR_GOOGLE, 22)
34 
35 /* Sensor defs */
36 #define SI7034_ID_SAMPLE                0xFF
37 #define SI7034_ID_PROD                  0x22
38 
39 #define SI7034_RESET_CMD                0xFE
40 #define SI7034_READID_0_CMD             0xFC
41 #define SI7034_READID_1_CMD             0xC9
42 #define SI7034_READDATA_0_CMD           0x7C
43 #define SI7034_READDATA_1_CMD           0xA2
44 
45 #define SI7034_HUMIGRADES(humi_val)     ((humi_val * 12500) >> 13)
46 #define SI7034_CENTIGRADES(temp_val)    (((temp_val * 21875) >> 13) - 45000)
47 
48 #define INFO_PRINT(fmt, ...) \
49     do { \
50         osLog(LOG_INFO, "%s " fmt, "[SI7034]", ##__VA_ARGS__); \
51     } while (0);
52 
53 #define DEBUG_PRINT(fmt, ...) \
54     do { \
55         if (SI7034_DBG_ENABLED) { \
56             osLog(LOG_DEBUG, "%s " fmt, "[SI7034]", ##__VA_ARGS__); \
57         } \
58     } while (0);
59 
60 #define ERROR_PRINT(fmt, ...) \
61     do { \
62         osLog(LOG_ERROR, "%s " fmt, "[SI7034]", ##__VA_ARGS__); \
63     } while (0);
64 
65 /* DO NOT MODIFY, just to avoid compiler error if not defined using FLAGS */
66 #ifndef SI7034_DBG_ENABLED
67 #define SI7034_DBG_ENABLED              0
68 #endif /* SI7034_DBG_ENABLED */
69 
70 enum si7034SensorEvents
71 {
72     EVT_SENSOR_I2C = EVT_APP_START + 1,
73     EVT_SENSOR_HUMIDITY_TIMER,
74     EVT_SENSOR_TEMP_TIMER,
75     EVT_TEST,
76 };
77 
78 enum si7034SensorState {
79     SENSOR_BOOT,
80     SENSOR_VERIFY_ID,
81     SENSOR_READ_SAMPLES,
82 };
83 
84 #ifndef SI7034A10_I2C_BUS_ID
85 #error "SI7034A10_I2C_BUS_ID is not defined; please define in variant.h"
86 #endif
87 
88 #ifndef SI7034A10_I2C_SPEED
89 #define SI7034A10_I2C_SPEED     400000
90 #endif
91 
92 #ifndef SI7034A10_I2C_ADDR
93 #define SI7034A10_I2C_ADDR      0x70
94 #endif
95 
96 enum si7034SensorIndex {
97     HUMIDITY = 0,
98     TEMP,
99     NUM_OF_SENSOR,
100 };
101 
102 struct si7034Sensor {
103     uint32_t handle;
104 };
105 
106 #define SI7034_MAX_PENDING_I2C_REQUESTS   4
107 #define SI7034_MAX_I2C_TRANSFER_SIZE      6
108 
109 struct I2cTransfer
110 {
111     size_t tx;
112     size_t rx;
113     int err;
114     uint8_t txrxBuf[SI7034_MAX_I2C_TRANSFER_SIZE];
115     uint8_t state;
116     bool inUse;
117 };
118 
119 /* Task structure */
120 struct si7034Task {
121     uint32_t tid;
122 
123     /* timer */
124     uint32_t humiTimerHandle;
125     uint32_t tempTimerHandle;
126 
127     /* sensor flags */
128     bool humiOn;
129     bool humiReading;
130     bool tempOn;
131     bool tempReading;
132 
133     struct I2cTransfer transfers[SI7034_MAX_PENDING_I2C_REQUESTS];
134 
135     /* sensors */
136     struct si7034Sensor sensors[NUM_OF_SENSOR];
137 };
138 
139 static struct si7034Task mTask;
140 
141 // Allocate a buffer and mark it as in use with the given state, or return NULL
142 // if no buffers available. Must *not* be called from interrupt context.
allocXfer(uint8_t state)143 static struct I2cTransfer *allocXfer(uint8_t state)
144 {
145     size_t i;
146 
147     for (i = 0; i < ARRAY_SIZE(mTask.transfers); i++) {
148         if (!mTask.transfers[i].inUse) {
149             mTask.transfers[i].inUse = true;
150             mTask.transfers[i].state = state;
151             return &mTask.transfers[i];
152         }
153     }
154 
155     ERROR_PRINT("Ran out of i2c buffers!");
156     return NULL;
157 }
158 
releaseXfer(struct I2cTransfer * xfer)159 static inline void releaseXfer(struct I2cTransfer *xfer)
160 {
161     xfer->inUse = false;
162 }
163 
i2cCallback(void * cookie,size_t tx,size_t rx,int err)164 static void i2cCallback(void *cookie, size_t tx, size_t rx, int err)
165 {
166     struct I2cTransfer *xfer = cookie;
167 
168     xfer->tx = tx;
169     xfer->rx = rx;
170     xfer->err = err;
171 
172     osEnqueuePrivateEvt(EVT_SENSOR_I2C, cookie, NULL, mTask.tid);
173     if (err != 0)
174         ERROR_PRINT("i2c error (tx: %d, rx: %d, err: %d)\n", tx, rx, err);
175 }
176 
si7034_i2c_read(uint8_t addr0,uint8_t addr1,uint8_t state)177 static bool si7034_i2c_read(uint8_t addr0, uint8_t addr1, uint8_t state)
178 {
179     struct I2cTransfer *xfer = allocXfer(state);
180     int ret = -1;
181 
182     if (xfer != NULL) {
183         xfer->txrxBuf[0] = addr0;
184         xfer->txrxBuf[1] = addr1;
185         ret = i2cMasterTxRx(SI7034A10_I2C_BUS_ID, SI7034A10_I2C_ADDR,
186                   xfer->txrxBuf, 2, xfer->txrxBuf, 6, i2cCallback, xfer);
187         if (ret) {
188             releaseXfer(xfer);
189             return false;
190         }
191     }
192 
193     return (ret == -1) ? false : true;
194 }
195 
si7034_i2c_write(uint8_t data,uint8_t state)196 static bool si7034_i2c_write(uint8_t data, uint8_t state)
197 {
198     struct I2cTransfer *xfer = allocXfer(state);
199     int ret = -1;
200 
201     if (xfer != NULL) {
202         xfer->txrxBuf[0] = data;
203         ret = i2cMasterTx(SI7034A10_I2C_BUS_ID, SI7034A10_I2C_ADDR,
204                   xfer->txrxBuf, 1, i2cCallback, xfer);
205         if (ret) {
206             releaseXfer(xfer);
207             return false;
208         }
209     }
210 
211     return (ret == -1) ? false : true;
212 }
213 
214 /* Sensor Info */
sensorHumiTimerCallback(uint32_t timerId,void * data)215 static void sensorHumiTimerCallback(uint32_t timerId, void *data)
216 {
217     osEnqueuePrivateEvt(EVT_SENSOR_HUMIDITY_TIMER, data, NULL, mTask.tid);
218 }
219 
sensorTempTimerCallback(uint32_t timerId,void * data)220 static void sensorTempTimerCallback(uint32_t timerId, void *data)
221 {
222     osEnqueuePrivateEvt(EVT_SENSOR_TEMP_TIMER, data, NULL, mTask.tid);
223 }
224 
225 #define DEC_INFO(name, type, axis, inter, samples, rates) \
226     .sensorName = name, \
227     .sensorType = type, \
228     .numAxis = axis, \
229     .interrupt = inter, \
230     .minSamples = samples, \
231     .supportedRates = rates
232 
233 static uint32_t si7034Rates[] = {
234     SENSOR_HZ(0.1),
235     SENSOR_HZ(1.0f),
236     SENSOR_HZ(5.0f),
237     SENSOR_HZ(10.0f),
238     SENSOR_HZ(25.0f),
239     0
240 };
241 
242 // should match "supported rates in length" and be the timer length for that rate in nanosecs
243 static const uint64_t si7034RatesRateVals[] =
244 {
245     10 * 1000000000ULL,
246     1 * 1000000000ULL,
247     1000000000ULL / 5,
248     1000000000ULL / 10,
249     1000000000ULL / 25,
250 };
251 
252 
253 static const struct SensorInfo si7034SensorInfo[NUM_OF_SENSOR] =
254 {
255     { DEC_INFO("Humidity", SENS_TYPE_HUMIDITY, NUM_AXIS_EMBEDDED, NANOHUB_INT_NONWAKEUP,
256         300, si7034Rates) },
257     { DEC_INFO("Temperature", SENS_TYPE_AMBIENT_TEMP, NUM_AXIS_EMBEDDED, NANOHUB_INT_NONWAKEUP,
258         20, si7034Rates) },
259 };
260 
261 /* Sensor Operations */
humiPower(bool on,void * cookie)262 static bool humiPower(bool on, void *cookie)
263 {
264     DEBUG_PRINT("%s: %d\n", __func__, on);
265 
266     if (mTask.humiTimerHandle) {
267         timTimerCancel(mTask.humiTimerHandle);
268         mTask.humiTimerHandle = 0;
269         mTask.humiReading = false;
270     }
271     mTask.humiOn = on;
272     return sensorSignalInternalEvt(mTask.sensors[HUMIDITY].handle,
273                 SENSOR_INTERNAL_EVT_POWER_STATE_CHG, on, 0);
274 }
275 
humiFwUpload(void * cookie)276 static bool humiFwUpload(void *cookie)
277 {
278     DEBUG_PRINT("%s\n", __func__);
279 
280     return sensorSignalInternalEvt(mTask.sensors[HUMIDITY].handle,
281                 SENSOR_INTERNAL_EVT_FW_STATE_CHG, 1, 0);
282 }
283 
humiSetRate(uint32_t rate,uint64_t latency,void * cookie)284 static bool humiSetRate(uint32_t rate, uint64_t latency, void *cookie)
285 {
286     DEBUG_PRINT("%s %ld (%lld)\n", __func__, rate, latency);
287 
288     if (mTask.humiTimerHandle)
289         timTimerCancel(mTask.humiTimerHandle);
290 
291     mTask.humiTimerHandle = timTimerSet(sensorTimerLookupCommon(si7034Rates,
292                 si7034RatesRateVals, rate), 0, 50, sensorHumiTimerCallback, NULL, false);
293 
294     return sensorSignalInternalEvt(mTask.sensors[HUMIDITY].handle,
295                 SENSOR_INTERNAL_EVT_RATE_CHG, rate, latency);
296 }
297 
humiFlush(void * cookie)298 static bool humiFlush(void *cookie)
299 {
300     return osEnqueueEvt(sensorGetMyEventType(SENS_TYPE_HUMIDITY), SENSOR_DATA_EVENT_FLUSH, NULL);
301 }
302 
tempPower(bool on,void * cookie)303 static bool tempPower(bool on, void *cookie)
304 {
305     DEBUG_PRINT("%s: %d\n", __func__, on);
306 
307     if (mTask.tempTimerHandle) {
308         timTimerCancel(mTask.tempTimerHandle);
309         mTask.tempTimerHandle = 0;
310         mTask.tempReading = false;
311     }
312     mTask.tempOn = on;
313     return sensorSignalInternalEvt(mTask.sensors[TEMP].handle,
314                 SENSOR_INTERNAL_EVT_POWER_STATE_CHG, on, 0);
315 }
316 
tempFwUpload(void * cookie)317 static bool tempFwUpload(void *cookie)
318 {
319     DEBUG_PRINT("%s\n", __func__);
320 
321     return sensorSignalInternalEvt(mTask.sensors[TEMP].handle,
322                 SENSOR_INTERNAL_EVT_FW_STATE_CHG, 1, 0);
323 }
324 
tempSetRate(uint32_t rate,uint64_t latency,void * cookie)325 static bool tempSetRate(uint32_t rate, uint64_t latency, void *cookie)
326 {
327     DEBUG_PRINT("%s %ld (%lld)\n", __func__, rate, latency);
328 
329     if (mTask.tempTimerHandle)
330         timTimerCancel(mTask.tempTimerHandle);
331 
332     mTask.tempTimerHandle = timTimerSet(sensorTimerLookupCommon(si7034Rates,
333                 si7034RatesRateVals, rate), 0, 50, sensorTempTimerCallback, NULL, false);
334 
335     return sensorSignalInternalEvt(mTask.sensors[TEMP].handle,
336                 SENSOR_INTERNAL_EVT_RATE_CHG, rate, latency);
337 }
338 
tempFlush(void * cookie)339 static bool tempFlush(void *cookie)
340 {
341     return osEnqueueEvt(sensorGetMyEventType(SENS_TYPE_AMBIENT_TEMP), SENSOR_DATA_EVENT_FLUSH, NULL);
342 }
343 
344 #define DEC_OPS(power, firmware, rate, flush, cal, cfg) \
345     .sensorPower = power, \
346     .sensorFirmwareUpload = firmware, \
347     .sensorSetRate = rate, \
348     .sensorFlush = flush, \
349     .sensorCalibrate = cal, \
350     .sensorCfgData = cfg
351 
352 static const struct SensorOps si7034SensorOps[NUM_OF_SENSOR] =
353 {
354     { DEC_OPS(humiPower, humiFwUpload, humiSetRate, humiFlush, NULL, NULL) },
355     { DEC_OPS(tempPower, tempFwUpload, tempSetRate, tempFlush, NULL, NULL) },
356 };
357 
handleI2cEvent(const void * evtData)358 static void handleI2cEvent(const void *evtData)
359 {
360     struct I2cTransfer *xfer = (struct I2cTransfer *)evtData;
361     union EmbeddedDataPoint sample;
362     uint32_t value;
363     uint8_t i;
364 
365     switch (xfer->state) {
366     case SENSOR_BOOT:
367         if (!si7034_i2c_read(SI7034_READID_0_CMD, SI7034_READID_1_CMD, SENSOR_VERIFY_ID)) {
368             DEBUG_PRINT("Not able to read ID\n");
369             return;
370         }
371         break;
372 
373     case SENSOR_VERIFY_ID:
374         /* Check the sensor ID */
375         if (xfer->err != 0)
376             return;
377         INFO_PRINT("Device ID = (%02x)\n", xfer->txrxBuf[0]);
378         if ((xfer->txrxBuf[0] != SI7034_ID_SAMPLE) &&
379             (xfer->txrxBuf[0] != SI7034_ID_PROD))
380             break;
381         INFO_PRINT("detected\n");
382         for (i = 0; i < NUM_OF_SENSOR; i++)
383             sensorRegisterInitComplete(mTask.sensors[i].handle);
384 
385         /* TEST the environment in standalone mode */
386         if (SI7034_DBG_ENABLED) {
387             mTask.humiOn = mTask.tempOn = true;
388             osEnqueuePrivateEvt(EVT_TEST, NULL, NULL, mTask.tid);
389         }
390         break;
391 
392     case SENSOR_READ_SAMPLES:
393         if (mTask.humiOn && mTask.humiReading) {
394             value = ((uint32_t)(xfer->txrxBuf[3]) << 8) | xfer->txrxBuf[4];
395             value = SI7034_HUMIGRADES(value);
396             value = (value > 100000) ? 100000 : value;
397             DEBUG_PRINT("Humidity = %u\n", (unsigned)value);
398             sample.fdata = (float)value / 1000.0f;
399 
400             osEnqueueEvt(sensorGetMyEventType(SENS_TYPE_HUMIDITY), sample.vptr, NULL);
401         }
402 
403         if (mTask.tempOn && mTask.tempReading) {
404             value = ((uint32_t)(xfer->txrxBuf[0]) << 8) | xfer->txrxBuf[1];
405             value = SI7034_CENTIGRADES(value);
406             DEBUG_PRINT("Temp = %u\n", (unsigned)value);
407             sample.fdata = (float)value / 1000.0f;
408 
409             osEnqueueEvt(sensorGetMyEventType(SENS_TYPE_AMBIENT_TEMP), sample.vptr, NULL);
410         }
411 
412         mTask.humiReading = mTask.tempReading = false;
413         break;
414 
415     default:
416         break;
417     }
418 
419     releaseXfer(xfer);
420 }
421 
handleEvent(uint32_t evtType,const void * evtData)422 static void handleEvent(uint32_t evtType, const void* evtData)
423 {
424     switch (evtType) {
425     case EVT_APP_START:
426         osEventUnsubscribe(mTask.tid, EVT_APP_START);
427         si7034_i2c_write(SI7034_RESET_CMD, SENSOR_BOOT);
428         break;
429 
430     case EVT_SENSOR_I2C:
431         handleI2cEvent(evtData);
432         break;
433 
434     case EVT_SENSOR_HUMIDITY_TIMER:
435         DEBUG_PRINT("EVT_SENSOR_HUMIDITY_TIMER\n");
436 
437         if (!mTask.humiOn)
438             break;
439         /* Start sampling for a value */
440         if (!mTask.humiReading && !mTask.tempReading)
441             si7034_i2c_read(SI7034_READDATA_0_CMD, SI7034_READDATA_1_CMD, SENSOR_READ_SAMPLES);
442         mTask.humiReading = true;
443         break;
444 
445     case EVT_SENSOR_TEMP_TIMER:
446         DEBUG_PRINT("EVT_SENSOR_TEMP_TIMER\n");
447 
448         if (!mTask.tempOn)
449             break;
450         /* Start sampling for a value */
451         if (!mTask.humiReading && !mTask.tempReading)
452             si7034_i2c_read(SI7034_READDATA_0_CMD, SI7034_READDATA_1_CMD, SENSOR_READ_SAMPLES);
453         mTask.tempReading = true;
454         break;
455 
456     case EVT_TEST:
457         DEBUG_PRINT("EVT_TEST\n");
458 
459         humiSetRate(SENSOR_HZ(1), 0, NULL);
460         tempSetRate(SENSOR_HZ(1), 0, NULL);
461         break;
462 
463     default:
464         break;
465     }
466 }
467 
startTask(uint32_t task_id)468 static bool startTask(uint32_t task_id)
469 {
470     uint8_t i;
471 
472     mTask.tid = task_id;
473 
474     DEBUG_PRINT("task started\n");
475 
476     mTask.humiOn = mTask.humiReading = false;
477     mTask.tempOn = mTask.tempReading = false;
478 
479     /* Init the communication part */
480     i2cMasterRequest(SI7034A10_I2C_BUS_ID, SI7034A10_I2C_SPEED);
481 
482     for (i = 0; i < NUM_OF_SENSOR; i++) {
483         mTask.sensors[i].handle =
484             sensorRegister(&si7034SensorInfo[i], &si7034SensorOps[i], NULL, false);
485     }
486 
487     osEventSubscribe(mTask.tid, EVT_APP_START);
488 
489     return true;
490 }
491 
endTask(void)492 static void endTask(void)
493 {
494     uint8_t i;
495 
496     DEBUG_PRINT("task ended\n");
497 
498     for (i = 0; i < NUM_OF_SENSOR; i++) {
499         sensorUnregister(mTask.sensors[i].handle);
500     }
501 }
502 
503 INTERNAL_APP_INIT(SI7034A10_APP_ID, 0, startTask, endTask, handleEvent);
504