Home | History | Annotate | Download | only in si_si7034
      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.
    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 
    159 static inline void releaseXfer(struct I2cTransfer *xfer)
    160 {
    161     xfer->inUse = false;
    162 }
    163 
    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 
    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 
    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 */
    215 static void sensorHumiTimerCallback(uint32_t timerId, void *data)
    216 {
    217     osEnqueuePrivateEvt(EVT_SENSOR_HUMIDITY_TIMER, data, NULL, mTask.tid);
    218 }
    219 
    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 */
    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 
    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 
    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 
    298 static bool humiFlush(void *cookie)
    299 {
    300     return osEnqueueEvt(sensorGetMyEventType(SENS_TYPE_HUMIDITY), SENSOR_DATA_EVENT_FLUSH, NULL);
    301 }
    302 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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