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