Home | History | Annotate | Download | only in intersil_isl29034
      1 /*
      2  * Copyright (C) 2017 STMicroelectronics
      3  * Copyright (C) 2017 The Android Open Source Project
      4  *
      5  * Licensed under the Apache License, Version 2.0 (the "License");
      6  * you may not use this file except in compliance with the License.
      7  * You may obtain a copy of the License at
      8  *
      9  *      http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  */
     17 
     18 #include <stdlib.h>
     19 #include <string.h>
     20 #include <float.h>
     21 
     22 #include <seos.h>
     23 #include <i2c.h>
     24 #include <timer.h>
     25 #include <sensors.h>
     26 #include <heap.h>
     27 #include <hostIntf.h>
     28 #include <nanohubPacket.h>
     29 #include <eventnums.h>
     30 #include <util.h>
     31 #include <variant/variant.h>
     32 
     33 #ifdef DEBUG
     34 #undef ISL29034_DBG_ENABLED
     35 #define ISL29034_DBG_ENABLED                    1
     36 #endif
     37 
     38 #ifndef ISL29034_DBG_ENABLED
     39 #define ISL29034_DBG_ENABLED                    0
     40 #endif /* ISL29034_DBG_ENABLED */
     41 
     42 #define ISL29034_APP_VERSION                    1
     43 
     44 #define ISL29034_REG_CMD_1                      0x00
     45 #define ISL29034_REG_CMD_2                      0x01
     46 #define ISL29034_REG_DATA_L                     0x02
     47 #define ISL29034_REG_DATA_H                     0x03
     48 #define ISL29034_REG_ID                         0x0f
     49 
     50 #define ISL29034_CMD1_POWERDOWN                 (0 << 5)
     51 #define ISL29034_CMD1_MEASURE                   (5 << 5)
     52 
     53 #define ISL29034_CMD2_RANGE_1KLUX               0
     54 #define ISL29034_CMD2_RANGE_4KLUX               1
     55 #define ISL29034_CMD2_RANGE_16KLUX              2
     56 #define ISL29034_CMD2_RANGE_64KLUX              3
     57 #define ISL29034_CMD2_RES_16BIT                 (0 << 2)
     58 #define ISL29034_CMD2_RES_12BIT                 (1 << 2)
     59 #define ISL29034_CMD2_RES_8BIT                  (2 << 2)
     60 #define ISL29034_CMD2_RES_4BIT                  (3 << 2)
     61 
     62 #define ISL29034_ID                             (5 << 3)
     63 #define ISL29034_ID_MASK                        (7 << 3)
     64 #define ISL29034_ID_BOUT                        (1 << 7)
     65 
     66 #define ISL29034_ALS_INVALID                    UINT32_MAX
     67 #define ISL29034_MAX_PENDING_I2C_REQUESTS       4
     68 #define ISL29034_MAX_I2C_TRANSFER_SIZE          3
     69 
     70 /* Used when SENSOR_RATE_ONCHANGE is requested */
     71 #define ISL29034_DEFAULT_RATE                   SENSOR_HZ(10)
     72 
     73 #ifndef ISL29034_I2C_BUS_ID
     74 #error "ISL29034_I2C_BUS_ID is not defined; please define in variant.h"
     75 #endif
     76 
     77 #ifndef ISL29034_I2C_SPEED
     78 #error "ISL29034_I2C_SPEED is not defined; please define in variant.h"
     79 #endif
     80 
     81 #ifndef ISL29034_I2C_ADDR
     82 #define ISL29034_I2C_ADDR                       0x44
     83 #endif
     84 
     85 #define INFO_PRINT(fmt, ...) \
     86     do { \
     87         osLog(LOG_INFO, "%s " fmt, "[ISL29034]", ##__VA_ARGS__); \
     88     } while (0);
     89 
     90 #define DEBUG_PRINT(fmt, ...) \
     91     do { \
     92         if (ISL29034_DBG_ENABLED) { \
     93             osLog(LOG_DEBUG, "%s " fmt, "[ISL29034]", ##__VA_ARGS__); \
     94         } \
     95     } while (0);
     96 
     97 #define ERROR_PRINT(fmt, ...) \
     98     do { \
     99         osLog(LOG_ERROR, "%s " fmt, "[ISL29034]", ##__VA_ARGS__); \
    100     } while (0);
    101 
    102 
    103 /* Private driver events */
    104 enum SensorEvents
    105 {
    106     EVT_SENSOR_I2C = EVT_APP_START + 1,
    107     EVT_SENSOR_ALS_TIMER,
    108 };
    109 
    110 /* I2C state machine */
    111 enum SensorState
    112 {
    113     SENSOR_STATE_VERIFY_ID,
    114     SENSOR_STATE_CLEAR_BOUT,
    115 
    116     SENSOR_STATE_ENABLING_ALS,
    117     SENSOR_STATE_DISABLING_ALS,
    118 
    119     SENSOR_STATE_IDLE,
    120     SENSOR_STATE_SAMPLING,
    121 };
    122 
    123 struct I2cTransfer
    124 {
    125     size_t tx;
    126     size_t rx;
    127     int err;
    128 
    129     uint8_t txrxBuf[ISL29034_MAX_I2C_TRANSFER_SIZE];
    130 
    131     uint8_t state;
    132     bool inUse;
    133 };
    134 
    135 struct SensorData
    136 {
    137     uint32_t tid;
    138 
    139     uint32_t alsHandle;
    140     uint32_t alsTimerHandle;
    141 
    142     struct I2cTransfer transfers[ISL29034_MAX_PENDING_I2C_REQUESTS];
    143 
    144     union EmbeddedDataPoint lastAlsSample;
    145 
    146     bool alsOn;
    147     bool alsReading;
    148 };
    149 
    150 static struct SensorData mData;
    151 
    152 static const uint32_t supportedRates[] =
    153 {
    154     SENSOR_HZ(10),
    155     SENSOR_RATE_ONCHANGE,
    156     0
    157 };
    158 
    159 // should match "supported rates in length" and be the timer length for that rate in nanosecs
    160 static const uint64_t rateTimerVals[] =
    161 {
    162     1000000000ULL / 10,
    163 };
    164 
    165 /*
    166  * Helper functions
    167  */
    168 
    169 static void i2cCallback(void *cookie, size_t tx, size_t rx, int err)
    170 {
    171     struct I2cTransfer *xfer = cookie;
    172 
    173     xfer->tx = tx;
    174     xfer->rx = rx;
    175     xfer->err = err;
    176 
    177     osEnqueuePrivateEvt(EVT_SENSOR_I2C, cookie, NULL, mData.tid);
    178     if (err != 0)
    179         INFO_PRINT("i2c error (tx: %d, rx: %d, err: %d)\n", tx, rx, err);
    180 }
    181 
    182 // Allocate a buffer and mark it as in use with the given state, or return NULL
    183 // if no buffers available. Must *not* be called from interrupt context.
    184 static struct I2cTransfer *allocXfer(uint8_t state)
    185 {
    186     size_t i;
    187 
    188     for (i = 0; i < ARRAY_SIZE(mData.transfers); i++) {
    189         if (!mData.transfers[i].inUse) {
    190             mData.transfers[i].inUse = true;
    191             mData.transfers[i].state = state;
    192             return &mData.transfers[i];
    193         }
    194     }
    195 
    196     ERROR_PRINT("Ran out of i2c buffers!");
    197     return NULL;
    198 }
    199 
    200 // Helper function to write a one byte register. Returns true if we got a
    201 // successful return value from i2cMasterTx().
    202 static bool writeRegister(uint8_t reg, uint8_t value, uint8_t state)
    203 {
    204     struct I2cTransfer *xfer = allocXfer(state);
    205     int ret = -1;
    206 
    207     if (xfer != NULL) {
    208         xfer->txrxBuf[0] = reg;
    209         xfer->txrxBuf[1] = value;
    210         ret = i2cMasterTx(ISL29034_I2C_BUS_ID, ISL29034_I2C_ADDR, xfer->txrxBuf, 2, i2cCallback, xfer);
    211     }
    212 
    213     return (ret == 0);
    214 }
    215 
    216 static void alsTimerCallback(uint32_t timerId, void *cookie)
    217 {
    218     osEnqueuePrivateEvt(EVT_SENSOR_ALS_TIMER, cookie, NULL, mData.tid);
    219 }
    220 
    221 static inline float getLuxFromAlsData(uint16_t als)
    222 {
    223     float range = 64000.0;
    224     float resolution = 65536.0;
    225 
    226     return range * als / resolution;
    227 }
    228 
    229 static bool sensorPowerAls(bool on, void *cookie)
    230 {
    231     INFO_PRINT("sensorPowerAls: %d\n", on);
    232 
    233     if (mData.alsTimerHandle) {
    234         timTimerCancel(mData.alsTimerHandle);
    235         mData.alsTimerHandle = 0;
    236         mData.alsReading = false;
    237     }
    238 
    239     mData.lastAlsSample.idata = ISL29034_ALS_INVALID;
    240     mData.alsOn = on;
    241 
    242     writeRegister(ISL29034_REG_CMD_1,
    243                   on ? ISL29034_CMD1_MEASURE : ISL29034_CMD1_POWERDOWN,
    244                   on ? SENSOR_STATE_ENABLING_ALS : SENSOR_STATE_DISABLING_ALS);
    245 
    246     return true;
    247 }
    248 
    249 static bool sensorFirmwareAls(void *cookie)
    250 {
    251     sensorSignalInternalEvt(mData.alsHandle, SENSOR_INTERNAL_EVT_FW_STATE_CHG, 1, 0);
    252     return true;
    253 }
    254 
    255 static bool sensorRateAls(uint32_t rate, uint64_t latency, void *cookie)
    256 {
    257     if (rate == SENSOR_RATE_ONCHANGE)
    258         rate = ISL29034_DEFAULT_RATE;
    259 
    260     INFO_PRINT("sensorRateAls: %ld/%lld\n", rate, latency);
    261 
    262     if (mData.alsTimerHandle)
    263         timTimerCancel(mData.alsTimerHandle);
    264     mData.alsTimerHandle = timTimerSet(sensorTimerLookupCommon(supportedRates, rateTimerVals, rate), 0, 50, alsTimerCallback, NULL, false);
    265     osEnqueuePrivateEvt(EVT_SENSOR_ALS_TIMER, NULL, NULL, mData.tid);
    266     sensorSignalInternalEvt(mData.alsHandle, SENSOR_INTERNAL_EVT_RATE_CHG, rate, latency);
    267 
    268     return true;
    269 }
    270 
    271 static bool sensorFlushAls(void *cookie)
    272 {
    273     return osEnqueueEvt(sensorGetMyEventType(SENS_TYPE_ALS), SENSOR_DATA_EVENT_FLUSH, NULL);
    274 }
    275 
    276 static bool sendLastSampleAls(void *cookie, uint32_t tid)
    277 {
    278     bool result = true;
    279 
    280     // If we don't end up doing anything here, the expectation is that we are powering up/haven't got the
    281     // first sample yet, so a broadcast event will go out soon with the first sample
    282     if (mData.lastAlsSample.idata != ISL29034_ALS_INVALID)
    283         result = osEnqueuePrivateEvt(sensorGetMyEventType(SENS_TYPE_ALS), mData.lastAlsSample.vptr, NULL, tid);
    284 
    285     return result;
    286 }
    287 
    288 static const struct SensorInfo sensorInfoAls =
    289 {
    290     .sensorName = "ALS",
    291     .supportedRates = supportedRates,
    292     .sensorType = SENS_TYPE_ALS,
    293     .numAxis = NUM_AXIS_EMBEDDED,
    294     .interrupt = NANOHUB_INT_NONWAKEUP,
    295     .minSamples = 20
    296 };
    297 
    298 static const struct SensorOps sensorOpsAls =
    299 {
    300     .sensorPower = sensorPowerAls,
    301     .sensorFirmwareUpload = sensorFirmwareAls,
    302     .sensorSetRate = sensorRateAls,
    303     .sensorFlush = sensorFlushAls,
    304     .sensorTriggerOndemand = NULL,
    305     .sensorCalibrate = NULL,
    306     .sensorSendOneDirectEvt = sendLastSampleAls
    307 };
    308 
    309 /*
    310  * Sensor i2c state machine
    311  */
    312 
    313 static void handle_i2c_event(struct I2cTransfer *xfer)
    314 {
    315     union EmbeddedDataPoint sample;
    316     struct I2cTransfer *nextXfer;
    317 
    318     switch (xfer->state) {
    319     case SENSOR_STATE_VERIFY_ID:
    320         /* Check the sensor ID */
    321         if (xfer->err != 0 ||
    322             (xfer->txrxBuf[0] & ISL29034_ID_MASK) != ISL29034_ID) {
    323             INFO_PRINT("not detected\n");
    324             sensorUnregister(mData.alsHandle);
    325             break;
    326         }
    327         INFO_PRINT("detected\n")
    328 
    329         if (xfer->txrxBuf[0] & ISL29034_ID_BOUT) {
    330             INFO_PRINT("Brownout Condition\n");
    331             writeRegister(ISL29034_REG_ID,
    332                           xfer->txrxBuf[0] ^ ISL29034_ID_BOUT,
    333                           SENSOR_STATE_CLEAR_BOUT);
    334             break;
    335         }
    336         /* fallthrough */
    337 
    338     case SENSOR_STATE_CLEAR_BOUT:
    339         nextXfer = allocXfer(SENSOR_STATE_IDLE);
    340         if (nextXfer != NULL) {
    341             nextXfer->txrxBuf[0] = ISL29034_REG_CMD_1;
    342             nextXfer->txrxBuf[1] = ISL29034_CMD1_POWERDOWN;
    343             nextXfer->txrxBuf[2] = ISL29034_CMD2_RANGE_64KLUX | ISL29034_CMD2_RES_16BIT;
    344             i2cMasterTx(ISL29034_I2C_BUS_ID, ISL29034_I2C_ADDR, nextXfer->txrxBuf, 3, i2cCallback, nextXfer);
    345         }
    346         break;
    347 
    348     case SENSOR_STATE_IDLE:
    349         sensorRegisterInitComplete(mData.alsHandle);
    350         break;
    351 
    352     case SENSOR_STATE_ENABLING_ALS:
    353         sensorSignalInternalEvt(mData.alsHandle, SENSOR_INTERNAL_EVT_POWER_STATE_CHG, true, 0);
    354         break;
    355 
    356     case SENSOR_STATE_DISABLING_ALS:
    357         sensorSignalInternalEvt(mData.alsHandle, SENSOR_INTERNAL_EVT_POWER_STATE_CHG, false, 0);
    358         break;
    359 
    360     case SENSOR_STATE_SAMPLING:
    361         DEBUG_PRINT("sample ready: als0=%u als1=%u\n", xfer->txrxBuf[0], xfer->txrxBuf[1]);
    362 
    363         if (mData.alsOn && mData.alsReading) {
    364             /* Create event */
    365             sample.fdata = getLuxFromAlsData(xfer->txrxBuf[0] | (xfer->txrxBuf[1] << 8));
    366             if (mData.lastAlsSample.idata != sample.idata) {
    367                 osEnqueueEvt(sensorGetMyEventType(SENS_TYPE_ALS), sample.vptr, NULL);
    368                 mData.lastAlsSample.fdata = sample.fdata;
    369             }
    370         }
    371 
    372         mData.alsReading = false;
    373         break;
    374     }
    375 
    376     xfer->inUse = false;
    377 }
    378 
    379 /*
    380  * Main driver entry points
    381  */
    382 
    383 static bool init_app(uint32_t myTid)
    384 {
    385     INFO_PRINT("started\n");
    386 
    387     /* Set up driver private data */
    388     mData.tid = myTid;
    389     mData.alsOn = false;
    390     mData.alsReading = false;
    391     mData.lastAlsSample.idata = ISL29034_ALS_INVALID;
    392 
    393     i2cMasterRequest(ISL29034_I2C_BUS_ID, ISL29034_I2C_SPEED);
    394 
    395     /* Register sensors */
    396     mData.alsHandle = sensorRegister(&sensorInfoAls, &sensorOpsAls, NULL, false);
    397 
    398     osEventSubscribe(myTid, EVT_APP_START);
    399 
    400     return true;
    401 }
    402 
    403 static void end_app(void)
    404 {
    405     INFO_PRINT("ended\n");
    406 
    407     sensorUnregister(mData.alsHandle);
    408 
    409     i2cMasterRelease(ISL29034_I2C_BUS_ID);
    410 }
    411 
    412 static void handle_event(uint32_t evtType, const void* evtData)
    413 {
    414     struct I2cTransfer *xfer;
    415 
    416     switch (evtType) {
    417     case EVT_APP_START:
    418         osEventUnsubscribe(mData.tid, EVT_APP_START);
    419 
    420         xfer = allocXfer(SENSOR_STATE_VERIFY_ID);
    421         if (xfer != NULL) {
    422             xfer->txrxBuf[0] = ISL29034_REG_ID;
    423             i2cMasterTxRx(ISL29034_I2C_BUS_ID, ISL29034_I2C_ADDR, xfer->txrxBuf, 1, xfer->txrxBuf, 1, i2cCallback, xfer);
    424         }
    425         break;
    426 
    427     case EVT_SENSOR_I2C:
    428         handle_i2c_event((struct I2cTransfer *)evtData);
    429         break;
    430 
    431     case EVT_SENSOR_ALS_TIMER:
    432         /* Start sampling for a value */
    433         if (!mData.alsReading) {
    434             xfer = allocXfer(SENSOR_STATE_SAMPLING);
    435             if (xfer != NULL) {
    436                 xfer->txrxBuf[0] = ISL29034_REG_DATA_L;
    437                 i2cMasterTxRx(ISL29034_I2C_BUS_ID, ISL29034_I2C_ADDR, xfer->txrxBuf, 1, xfer->txrxBuf, 2, i2cCallback, xfer);
    438             }
    439         }
    440 
    441         mData.alsReading = true;
    442         break;
    443     }
    444 }
    445 
    446 INTERNAL_APP_INIT(APP_ID_MAKE(NANOHUB_VENDOR_STMICRO, 4), ISL29034_APP_VERSION, init_app, end_app, handle_event);
    447