Home | History | Annotate | Download | only in st_hts221
      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 <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 <i2c.h>
     27 #include <timer.h>
     28 #include <stdlib.h>
     29 #include <string.h>
     30 #include <variant/variant.h>
     31 #include <variant/sensType.h>
     32 
     33 #define HTS221_APP_ID              APP_ID_MAKE(NANOHUB_VENDOR_STMICRO, 2)
     34 
     35 /* Sensor defs */
     36 #define HTS221_WAI_REG_ADDR    0x0F
     37 #define HTS221_WAI_REG_VAL     0xBC
     38 
     39 #define HTS221_AV_CONF         0x10
     40 
     41 #define HTS221_CTRL_REG1       0x20
     42 #define HTS221_POWER_ON        0x80
     43 #define HTS221_POWER_OFF       0x00
     44 #define HTS221_BDU_ON          0x04
     45 #define HTS221_ODR_ONE_SHOT    0x00
     46 #define HTS221_ODR_1_HZ        0x01
     47 #define HTS221_ODR_7_HZ        0x02
     48 #define HTS221_ODR_12_5_HZ     0x03
     49 
     50 #define HTS221_CTRL_REG2       0x21
     51 #define HTS221_REBOOT          0x80
     52 
     53 #define HTS221_CTRL_REG3       0x22
     54 #define HTS221_STATUS_REG      0x27
     55 
     56 #define HTS221_HUMIDITY_OUTL_REG_ADDR    0x28
     57 #define HTS221_TEMP_OUTL_REG_ADDR        0x2A
     58 
     59 #define HTS221_CALIB_DATA      0x30
     60 #define HTS221_CALIB_DATA_LEN  16
     61 
     62 struct hts221_calib_data {
     63     uint8_t  h0_x2;
     64     uint8_t  h1_x2;
     65     uint8_t  unused[4];
     66     uint8_t  h0_t0_l;
     67     uint8_t  h0_t0_h;
     68     uint8_t  unused_2[2];
     69     uint8_t  h1_t0_l;
     70     uint8_t  h1_t0_h;
     71     uint8_t  unused_3[4];
     72 };
     73 
     74 #define INFO_PRINT(fmt, ...) \
     75     do { \
     76         osLog(LOG_INFO, "%s " fmt, "[HTS221]", ##__VA_ARGS__); \
     77     } while (0);
     78 
     79 #define DEBUG_PRINT(fmt, ...) \
     80     do { \
     81         if (HTS221_DBG_ENABLED) { \
     82             osLog(LOG_DEBUG, "%s " fmt, "[HTS221]", ##__VA_ARGS__); \
     83         } \
     84     } while (0);
     85 
     86 #define ERROR_PRINT(fmt, ...) \
     87     do { \
     88         osLog(LOG_ERROR, "%s " fmt, "[HTS221]", ##__VA_ARGS__); \
     89     } while (0);
     90 
     91 /* DO NOT MODIFY, just to avoid compiler error if not defined using FLAGS */
     92 #ifndef HTS221_DBG_ENABLED
     93 #define HTS221_DBG_ENABLED                           0
     94 #endif /* HTS221_DBG_ENABLED */
     95 
     96 enum hts221SensorEvents
     97 {
     98     EVT_COMM_DONE = EVT_APP_START + 1,
     99     EVT_INT1_RAISED,
    100     EVT_SENSOR_HUMIDITY_TIMER,
    101 };
    102 
    103 enum hts221SensorState {
    104     SENSOR_BOOT,
    105     SENSOR_VERIFY_ID,
    106     SENSOR_INIT,
    107     SENSOR_HUMIDITY_POWER_UP,
    108     SENSOR_HUMIDITY_POWER_DOWN,
    109     SENSOR_READ_SAMPLES,
    110 };
    111 
    112 #ifndef HTS221_I2C_BUS_ID
    113 #error "HTS221_I2C_BUS_ID is not defined; please define in variant.h"
    114 #endif
    115 
    116 #ifndef HTS221_I2C_SPEED
    117 #error "HTS221_I2C_SPEED is not defined; please define in variant.h"
    118 #endif
    119 
    120 #ifndef HTS221_I2C_ADDR
    121 #error "HTS221_I2C_ADDR is not defined; please define in variant.h"
    122 #endif
    123 
    124 enum hts221SensorIndex {
    125     HUMIDITY = 0,
    126     NUM_OF_SENSOR,
    127 };
    128 
    129 struct hts221Sensor {
    130     uint32_t handle;
    131 };
    132 
    133 #define HTS221_MAX_PENDING_I2C_REQUESTS   4
    134 #define HTS221_MAX_I2C_TRANSFER_SIZE      HTS221_CALIB_DATA_LEN
    135 
    136 struct I2cTransfer
    137 {
    138     size_t tx;
    139     size_t rx;
    140     int err;
    141     uint8_t txrxBuf[HTS221_MAX_I2C_TRANSFER_SIZE];
    142     uint8_t state;
    143     bool inUse;
    144 };
    145 
    146 /* Task structure */
    147 struct hts221Task {
    148     uint32_t tid;
    149 
    150     /* timer */
    151     uint32_t humidityTimerHandle;
    152 
    153     /* sensor flags */
    154     bool humidityOn;
    155     bool humidityReading;
    156     bool humidityWantRead;
    157 
    158     /* calib data */
    159     int8_t y0_H;
    160     int8_t y1_H;
    161     int16_t x0_H;
    162     int16_t x1_H;
    163 
    164     struct I2cTransfer transfers[HTS221_MAX_PENDING_I2C_REQUESTS];
    165 
    166     /* Communication functions */
    167     bool (*comm_tx)(uint8_t addr, uint8_t data, uint32_t delay, uint8_t state);
    168     bool (*comm_rx)(uint8_t addr, uint16_t len, uint32_t delay, uint8_t state);
    169 
    170     /* sensors */
    171     struct hts221Sensor sensors[NUM_OF_SENSOR];
    172 };
    173 
    174 static struct hts221Task mTask;
    175 
    176 static inline float hts221_humidity_percent(int16_t hum)
    177 {
    178     float percentage = (float) ((mTask.y1_H - mTask.y0_H) * hum + \
    179                                ((mTask.x1_H * mTask.y0_H) - (mTask.x0_H * mTask.y1_H))) / \
    180                                   (mTask.x1_H - mTask.x0_H);
    181 
    182     return((percentage > 100) ? 100 : percentage);
    183 }
    184 
    185 /*
    186  * Allocate a buffer and mark it as in use with the given state, or return NULL
    187  * if no buffers available. Must *not* be called from interrupt context.
    188  */
    189 static struct I2cTransfer *allocXfer(uint8_t state)
    190 {
    191     size_t i;
    192 
    193     for (i = 0; i < ARRAY_SIZE(mTask.transfers); i++) {
    194         if (!mTask.transfers[i].inUse) {
    195             mTask.transfers[i].inUse = true;
    196             mTask.transfers[i].state = state;
    197             return &mTask.transfers[i];
    198         }
    199     }
    200 
    201     ERROR_PRINT("Ran out of i2c buffers!");
    202     return NULL;
    203 }
    204 
    205 static inline void releaseXfer(struct I2cTransfer *xfer)
    206 {
    207     xfer->inUse = false;
    208 }
    209 
    210 
    211 static void i2cCallback(void *cookie, size_t tx, size_t rx, int err)
    212 {
    213     struct I2cTransfer *xfer = cookie;
    214 
    215     xfer->tx = tx;
    216     xfer->rx = rx;
    217     xfer->err = err;
    218 
    219     osEnqueuePrivateEvt(EVT_COMM_DONE, cookie, NULL, mTask.tid);
    220     if (err != 0)
    221         ERROR_PRINT("i2c error (tx: %d, rx: %d, err: %d)\n", tx, rx, err);
    222 }
    223 
    224 static bool i2c_read(uint8_t addr, uint16_t len, uint32_t delay, uint8_t state)
    225 {
    226     struct I2cTransfer *xfer = allocXfer(state);
    227     int ret = -1;
    228 
    229     if (xfer != NULL) {
    230         if (len > HTS221_MAX_I2C_TRANSFER_SIZE) {
    231             DEBUG_PRINT("i2c_read: len too big (len: %d)\n", len);
    232             releaseXfer(xfer);
    233             return false;
    234         }
    235 
    236         xfer->txrxBuf[0] = 0x80 | addr;
    237         if ((ret = i2cMasterTxRx(HTS221_I2C_BUS_ID, HTS221_I2C_ADDR,
    238                     xfer->txrxBuf, 1, xfer->txrxBuf, len, i2cCallback, xfer)) < 0) {
    239             DEBUG_PRINT("i2c_read: i2cMasterTxRx operation failed (ret: %d)\n", ret);
    240             releaseXfer(xfer);
    241             return false;
    242         }
    243     }
    244 
    245     return (ret == -1) ? false : true;
    246 }
    247 
    248 static bool i2c_write(uint8_t addr, uint8_t data, uint32_t delay, uint8_t state)
    249 {
    250     struct I2cTransfer *xfer = allocXfer(state);
    251     int ret = -1;
    252 
    253     if (xfer != NULL) {
    254         xfer->txrxBuf[0] = addr;
    255         xfer->txrxBuf[1] = data;
    256         if ((ret = i2cMasterTx(HTS221_I2C_BUS_ID, HTS221_I2C_ADDR, xfer->txrxBuf, 2, i2cCallback, xfer)) < 0) {
    257             releaseXfer(xfer);
    258             DEBUG_PRINT("i2c_write: i2cMasterTx operation failed (ret: %d)\n", ret);
    259             return false;
    260         }
    261     }
    262 
    263     return (ret == -1) ? false : true;
    264 }
    265 
    266 /* Sensor Info */
    267 static void sensorHumidityTimerCallback(uint32_t timerId, void *data)
    268 {
    269     osEnqueuePrivateEvt(EVT_SENSOR_HUMIDITY_TIMER, data, NULL, mTask.tid);
    270 }
    271 
    272 #define DEC_INFO(name, type, axis, inter, samples, rates) \
    273     .sensorName = name, \
    274     .sensorType = type, \
    275     .numAxis = axis, \
    276     .interrupt = inter, \
    277     .minSamples = samples, \
    278     .supportedRates = rates
    279 
    280 static uint32_t hts221Rates[] = {
    281     SENSOR_HZ(1.0f),
    282     SENSOR_HZ(7.0f),
    283     SENSOR_HZ(12.5f),
    284     0
    285 };
    286 
    287 /* should match "supported rates in length" and be the timer length for that rate in nanosecs */
    288 static const uint64_t hts221RatesRateVals[] =
    289 {
    290     1 * 1000000000ULL,    /* 1 Hz */
    291     1000000000ULL / 7,    /* 7 Hz */
    292     2000000000ULL / 25,   /* 12.5 Hz */
    293 };
    294 
    295 
    296 static const struct SensorInfo hts221SensorInfo[NUM_OF_SENSOR] =
    297 {
    298     { DEC_INFO("Humidity", SENS_TYPE_HUMIDITY, NUM_AXIS_EMBEDDED, NANOHUB_INT_NONWAKEUP,
    299         300, hts221Rates) },
    300 };
    301 
    302 /* Sensor Operations */
    303 static bool humidityPower(bool on, void *cookie)
    304 {
    305     bool oldMode = mTask.humidityOn;
    306     bool newMode = on;
    307     uint32_t state = on ? SENSOR_HUMIDITY_POWER_UP : SENSOR_HUMIDITY_POWER_DOWN;
    308     bool ret = true;
    309 
    310     INFO_PRINT("humidityPower %s\n", on ? "enable" : "disable");
    311 
    312     if (!on && mTask.humidityTimerHandle) {
    313         timTimerCancel(mTask.humidityTimerHandle);
    314         mTask.humidityTimerHandle = 0;
    315         mTask.humidityReading = false;
    316     }
    317 
    318     if (oldMode != newMode) {
    319         if (on)
    320             ret = mTask.comm_tx(HTS221_CTRL_REG1, HTS221_POWER_ON | HTS221_ODR_12_5_HZ, 0, state);
    321         else
    322             ret = mTask.comm_tx(HTS221_CTRL_REG1, HTS221_POWER_OFF, 0, state);
    323     } else
    324         sensorSignalInternalEvt(mTask.sensors[HUMIDITY].handle,
    325                     SENSOR_INTERNAL_EVT_POWER_STATE_CHG, on, 0);
    326 
    327     if (!ret) {
    328         DEBUG_PRINT("humidityPower comm_tx failed\n");
    329         return(false);
    330     }
    331 
    332     mTask.humidityReading = false;
    333     mTask.humidityOn = on;
    334     return true;
    335 }
    336 
    337 static bool humidityFwUpload(void *cookie)
    338 {
    339     return sensorSignalInternalEvt(mTask.sensors[HUMIDITY].handle, SENSOR_INTERNAL_EVT_FW_STATE_CHG, 1, 0);
    340 }
    341 
    342 static bool humiditySetRate(uint32_t rate, uint64_t latency, void *cookie)
    343 {
    344     INFO_PRINT("humiditySetRate %lu Hz - %llu ns\n", rate, latency);
    345 
    346     if (mTask.humidityTimerHandle)
    347         timTimerCancel(mTask.humidityTimerHandle);
    348 
    349     mTask.humidityTimerHandle = timTimerSet(sensorTimerLookupCommon(hts221Rates,
    350                 hts221RatesRateVals, rate), 0, 50, sensorHumidityTimerCallback, NULL, false);
    351 
    352     return sensorSignalInternalEvt(mTask.sensors[HUMIDITY].handle,
    353                 SENSOR_INTERNAL_EVT_RATE_CHG, rate, latency);
    354 }
    355 
    356 static bool humidityFlush(void *cookie)
    357 {
    358     return osEnqueueEvt(sensorGetMyEventType(SENS_TYPE_HUMIDITY), SENSOR_DATA_EVENT_FLUSH, NULL);
    359 }
    360 
    361 #define DEC_OPS(power, firmware, rate, flush, cal, cfg) \
    362     .sensorPower = power, \
    363     .sensorFirmwareUpload = firmware, \
    364     .sensorSetRate = rate, \
    365     .sensorFlush = flush, \
    366     .sensorCalibrate = cal, \
    367     .sensorCfgData = cfg
    368 
    369 static const struct SensorOps hts221SensorOps[NUM_OF_SENSOR] =
    370 {
    371     { DEC_OPS(humidityPower, humidityFwUpload, humiditySetRate, humidityFlush, NULL, NULL) },
    372 };
    373 
    374 static void hts221_save_calib_data(uint8_t *buf)
    375 {
    376     struct hts221_calib_data *calib = (struct hts221_calib_data *) buf;
    377 
    378     mTask.y0_H = (int8_t) (calib->h0_x2 / 2);
    379     mTask.y1_H = (int8_t) (calib->h1_x2 / 2);
    380     mTask.x0_H = (int16_t) (calib->h0_t0_h << 8) |
    381                            calib->h0_t0_l;
    382     mTask.x1_H = (int16_t) (calib->h1_t0_h << 8) |
    383                            calib->h1_t0_l;
    384     DEBUG_PRINT("y0_H: %d - y1_H: %d\n", mTask.y0_H, mTask.y1_H);
    385     DEBUG_PRINT("x0_H: %d - x1_H: %d\n", mTask.x0_H, mTask.x1_H);
    386 }
    387 
    388 static uint8_t *humidity_samples;
    389 static int handleCommDoneEvt(const void* evtData)
    390 {
    391     uint8_t i;
    392     int16_t humidity_val;
    393     union EmbeddedDataPoint sample;
    394     struct I2cTransfer *xfer = (struct I2cTransfer *)evtData;
    395 
    396     switch (xfer->state) {
    397     case SENSOR_BOOT:
    398         hts221_save_calib_data(xfer->txrxBuf);
    399         if (!mTask.comm_rx(HTS221_WAI_REG_ADDR, 1, 1, SENSOR_VERIFY_ID)) {
    400             DEBUG_PRINT("Not able to read WAI\n");
    401             return -1;
    402         }
    403         break;
    404 
    405     case SENSOR_VERIFY_ID:
    406         /* Check the sensor ID */
    407         if (xfer->err != 0 || xfer->txrxBuf[0] != HTS221_WAI_REG_VAL) {
    408             DEBUG_PRINT("WAI returned is: %02x\n", xfer->txrxBuf[0]);
    409             break;
    410         }
    411 
    412         INFO_PRINT( "Device ID is correct! (%02x)\n", xfer->txrxBuf[0]);
    413         for (i = 0; i < NUM_OF_SENSOR; i++)
    414             sensorRegisterInitComplete(mTask.sensors[i].handle);
    415 
    416         break;
    417 
    418     case SENSOR_INIT:
    419         for (i = 0; i < NUM_OF_SENSOR; i++)
    420             sensorRegisterInitComplete(mTask.sensors[i].handle);
    421         break;
    422 
    423     case SENSOR_HUMIDITY_POWER_UP:
    424         sensorSignalInternalEvt(mTask.sensors[HUMIDITY].handle,
    425                     SENSOR_INTERNAL_EVT_POWER_STATE_CHG, true, 0);
    426         break;
    427 
    428     case SENSOR_HUMIDITY_POWER_DOWN:
    429         sensorSignalInternalEvt(mTask.sensors[HUMIDITY].handle,
    430                     SENSOR_INTERNAL_EVT_POWER_STATE_CHG, false, 0);
    431         break;
    432 
    433     case SENSOR_READ_SAMPLES:
    434         if (mTask.humidityOn && mTask.humidityWantRead) {
    435             mTask.humidityWantRead = false;
    436             humidity_samples = xfer->txrxBuf;
    437 
    438             humidity_val = (int16_t)(((humidity_samples[1] << 8) & 0xff00) | humidity_samples[0]);
    439             DEBUG_PRINT("humidity raw data %d\n", humidity_val);
    440 
    441             mTask.humidityReading = false;
    442             sample.fdata = hts221_humidity_percent(humidity_val);
    443             osEnqueueEvt(sensorGetMyEventType(SENS_TYPE_HUMIDITY), sample.vptr, NULL);
    444         }
    445 
    446         break;
    447 
    448     default:
    449         break;
    450     }
    451 
    452     releaseXfer(xfer);
    453     return (0);
    454 }
    455 
    456 static void handleEvent(uint32_t evtType, const void* evtData)
    457 {
    458     switch (evtType) {
    459     case EVT_APP_START:
    460         INFO_PRINT( "EVT_APP_START\n");
    461         osEventUnsubscribe(mTask.tid, EVT_APP_START);
    462 
    463         mTask.comm_rx(HTS221_CALIB_DATA, sizeof(struct hts221_calib_data), 0, SENSOR_BOOT);
    464         break;
    465 
    466     case EVT_COMM_DONE:
    467         handleCommDoneEvt(evtData);
    468         break;
    469 
    470     case EVT_SENSOR_HUMIDITY_TIMER:
    471         mTask.humidityWantRead = true;
    472 
    473         /* Start sampling for a value */
    474         if (!mTask.humidityReading) {
    475             mTask.humidityReading = true;
    476 
    477             mTask.comm_rx(HTS221_HUMIDITY_OUTL_REG_ADDR, 2, 1, SENSOR_READ_SAMPLES);
    478         }
    479         break;
    480 
    481     default:
    482         break;
    483     }
    484 
    485 }
    486 
    487 static bool startTask(uint32_t task_id)
    488 {
    489     uint8_t i;
    490 
    491     mTask.tid = task_id;
    492 
    493     INFO_PRINT( "started\n");
    494 
    495     mTask.humidityOn = false;
    496     mTask.humidityReading = false;
    497 
    498     /* Init the communication part */
    499     i2cMasterRequest(HTS221_I2C_BUS_ID, HTS221_I2C_SPEED);
    500 
    501     mTask.comm_tx = i2c_write;
    502     mTask.comm_rx = i2c_read;
    503 
    504     for (i = 0; i < NUM_OF_SENSOR; i++) {
    505         mTask.sensors[i].handle =
    506             sensorRegister(&hts221SensorInfo[i], &hts221SensorOps[i], NULL, false);
    507     }
    508 
    509     osEventSubscribe(mTask.tid, EVT_APP_START);
    510 
    511     return true;
    512 }
    513 
    514 static void endTask(void)
    515 {
    516     INFO_PRINT( "ended\n");
    517 }
    518 
    519 INTERNAL_APP_INIT(HTS221_APP_ID, 0, startTask, endTask, handleEvent);
    520