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 <stdlib.h> 18 #include <string.h> 19 #include <float.h> 20 21 #include <seos.h> 22 #include <i2c.h> 23 #include <timer.h> 24 #include <sensors.h> 25 #include <heap.h> 26 #include <hostIntf.h> 27 #include <nanohubPacket.h> 28 #include <eventnums.h> 29 #include <util.h> 30 31 #define AMS_TMD2772_APP_VERSION 3 32 33 #define DRIVER_NAME "AMS: " 34 35 #define I2C_BUS_ID 0 36 #define I2C_SPEED 400000 37 #define I2C_ADDR 0x39 38 39 #define AMS_TMD2772_ID 0x39 40 41 #define AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT 0xa0 42 43 #define AMS_TMD2772_REG_ENABLE (AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT | 0x00) 44 #define AMS_TMD2772_REG_ATIME (AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT | 0x01) 45 #define AMS_TMD2772_REG_PTIME (AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT | 0x02) 46 #define AMS_TMD2772_REG_WTIME (AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT | 0x03) 47 #define AMS_TMD2772_REG_AILTL (AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT | 0x04) 48 #define AMS_TMD2772_REG_AILTH (AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT | 0x05) 49 #define AMS_TMD2772_REG_AIHTL (AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT | 0x06) 50 #define AMS_TMD2772_REG_AIHTH (AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT | 0x07) 51 #define AMS_TMD2772_REG_PILTL (AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT | 0x08) 52 #define AMS_TMD2772_REG_PILTH (AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT | 0x09) 53 #define AMS_TMD2772_REG_PIHTL (AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT | 0x0a) 54 #define AMS_TMD2772_REG_PIHTH (AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT | 0x0b) 55 #define AMS_TMD2772_REG_PERS (AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT | 0x0c) 56 #define AMS_TMD2772_REG_CONFIG (AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT | 0x0d) 57 #define AMS_TMD2772_REG_PPULSE (AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT | 0x0e) 58 #define AMS_TMD2772_REG_CONTROL (AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT | 0x0f) 59 #define AMS_TMD2772_REG_ID (AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT | 0x12) 60 #define AMS_TMD2772_REG_STATUS (AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT | 0x13) 61 #define AMS_TMD2772_REG_C0DATA (AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT | 0x14) 62 #define AMS_TMD2772_REG_C0DATAH (AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT | 0x15) 63 #define AMS_TMD2772_REG_C1DATA (AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT | 0x16) 64 #define AMS_TMD2772_REG_C1DATAH (AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT | 0x17) 65 #define AMS_TMD2772_REG_PDATAL (AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT | 0x18) 66 #define AMS_TMD2772_REG_PDATAH (AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT | 0x19) 67 #define AMS_TMD2772_REG_POFFSET (AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT | 0x1E) 68 69 #define AMS_TMD2772_ATIME_SETTING 0xdb 70 #define AMS_TMD2772_ATIME_MS ((256 - AMS_TMD2772_ATIME_SETTING) * 2.73) // in milliseconds 71 #define AMS_TMD2772_PTIME_SETTING 0xff 72 #define AMS_TMD2772_PTIME_MS ((256 - AMS_TMD2772_PTIME_SETTING) * 2.73) // in milliseconds 73 #define AMS_TMD2772_WTIME_SETTING_ALS_ON 0xdd // (256 - 221) * 2.73 ms = 95.55 ms 74 #define AMS_TMD2772_WTIME_SETTING_ALS_OFF 0xb8 // (256 - 184) * 2.73 ms = 196.56 ms 75 #define AMS_TMD2772_PPULSE_SETTING 8 76 77 #define AMS_TMD2772_CAL_DEFAULT_OFFSET 0 78 #define AMS_TMD2772_CAL_MAX_OFFSET 500 79 80 /* AMS_TMD2772_REG_ENABLE */ 81 #define POWER_ON_BIT (1 << 0) 82 #define ALS_ENABLE_BIT (1 << 1) 83 #define PROX_ENABLE_BIT (1 << 2) 84 #define WAIT_ENABLE_BIT (1 << 3) 85 86 /* AMS_TMD2772_REG_STATUS */ 87 #define PROX_INT_BIT (1 << 5) 88 #define ALS_INT_BIT (1 << 4) 89 #define PROX_VALID_BIT (1 << 1) 90 #define ALS_VALID_BIT (1 << 0) 91 92 #define AMS_TMD2772_REPORT_NEAR_VALUE 0.0f // centimeters 93 #define AMS_TMD2772_REPORT_FAR_VALUE 5.0f // centimeters 94 95 #define AMS_TMD2772_THRESHOLD_ASSERT_NEAR 300 // in PS units 96 #define AMS_TMD2772_THRESHOLD_DEASSERT_NEAR 150 // in PS units 97 98 #define AMS_TMD2772_ALS_MAX_CHANNEL_COUNT 37888 // in raw data 99 #define AMS_TMD2772_ALS_MAX_REPORT_VALUE 10000 // in lux 100 101 #define AMS_TMD2772_ALS_INVALID UINT32_MAX 102 103 /* Used when SENSOR_RATE_ONCHANGE is requested */ 104 #define AMS_TMD2772_DEFAULT_RATE SENSOR_HZ(5) 105 106 #define AMS_TMD2772_MAX_PENDING_I2C_REQUESTS 4 107 #define AMS_TMD2772_MAX_I2C_TRANSFER_SIZE 16 108 109 /* Private driver events */ 110 enum SensorEvents 111 { 112 EVT_SENSOR_I2C = EVT_APP_START + 1, 113 EVT_SENSOR_ALS_TIMER, 114 EVT_SENSOR_PROX_TIMER, 115 }; 116 117 /* I2C state machine */ 118 enum SensorState 119 { 120 SENSOR_STATE_VERIFY_ID, 121 SENSOR_STATE_INIT, 122 123 SENSOR_STATE_CALIBRATE_RESET, 124 SENSOR_STATE_CALIBRATE_START, 125 SENSOR_STATE_CALIBRATE_ENABLING, 126 SENSOR_STATE_CALIBRATE_POLLING_STATUS, 127 SENSOR_STATE_CALIBRATE_AWAITING_SAMPLE, 128 SENSOR_STATE_CALIBRATE_DISABLING, 129 130 SENSOR_STATE_ENABLING_ALS, 131 SENSOR_STATE_ENABLING_PROX, 132 SENSOR_STATE_DISABLING_ALS, 133 SENSOR_STATE_DISABLING_PROX, 134 135 SENSOR_STATE_IDLE, 136 SENSOR_STATE_SAMPLING, 137 }; 138 139 enum ProxState 140 { 141 PROX_STATE_INIT, 142 PROX_STATE_NEAR, 143 PROX_STATE_FAR, 144 }; 145 146 struct I2cTransfer 147 { 148 size_t tx; 149 size_t rx; 150 int err; 151 152 union { 153 uint8_t bytes[AMS_TMD2772_MAX_I2C_TRANSFER_SIZE]; 154 struct { 155 uint8_t status; 156 uint16_t als[2]; 157 uint16_t prox; 158 } __attribute__((packed)) sample; 159 struct { 160 uint16_t prox; 161 } calibration; 162 } txrxBuf; 163 164 uint8_t state; 165 bool inUse; 166 }; 167 168 169 struct SensorData 170 { 171 uint32_t tid; 172 173 uint32_t alsHandle; 174 uint32_t proxHandle; 175 uint32_t alsTimerHandle; 176 uint32_t proxTimerHandle; 177 uint32_t calibrationSampleTotal; 178 179 struct I2cTransfer transfers[AMS_TMD2772_MAX_PENDING_I2C_REQUESTS]; 180 181 union EmbeddedDataPoint lastAlsSample; 182 183 uint8_t calibrationSampleCount; 184 uint8_t proxState; // enum ProxState 185 186 bool alsOn; 187 bool alsReading; 188 bool proxOn; 189 bool proxReading; 190 }; 191 192 static struct SensorData mData; 193 194 /* TODO: check rates are supported */ 195 static const uint32_t supportedRates[] = 196 { 197 SENSOR_HZ(0.1), 198 SENSOR_HZ(1), 199 SENSOR_HZ(4), 200 SENSOR_HZ(5), 201 SENSOR_RATE_ONCHANGE, 202 0 203 }; 204 205 static const uint64_t rateTimerVals[] = //should match "supported rates in length" and be the timer length for that rate in nanosecs 206 { 207 10 * 1000000000ULL, 208 1 * 1000000000ULL, 209 1000000000ULL / 4, 210 1000000000ULL / 5, 211 }; 212 213 /* 214 * Helper functions 215 */ 216 217 static void i2cCallback(void *cookie, size_t tx, size_t rx, int err) 218 { 219 struct I2cTransfer *xfer = cookie; 220 221 xfer->tx = tx; 222 xfer->rx = rx; 223 xfer->err = err; 224 225 osEnqueuePrivateEvt(EVT_SENSOR_I2C, cookie, NULL, mData.tid); 226 if (err != 0) 227 osLog(LOG_INFO, DRIVER_NAME "i2c error (tx: %d, rx: %d, err: %d)\n", tx, rx, err); 228 } 229 230 // Allocate a buffer and mark it as in use with the given state, or return NULL 231 // if no buffers available. Must *not* be called from interrupt context. 232 static struct I2cTransfer *allocXfer(uint8_t state) 233 { 234 size_t i; 235 236 for (i = 0; i < ARRAY_SIZE(mData.transfers); i++) { 237 if (!mData.transfers[i].inUse) { 238 mData.transfers[i].inUse = true; 239 mData.transfers[i].state = state; 240 return &mData.transfers[i]; 241 } 242 } 243 244 osLog(LOG_ERROR, DRIVER_NAME "Ran out of i2c buffers!"); 245 return NULL; 246 } 247 248 // Helper function to write a one byte register. Returns true if we got a 249 // successful return value from i2cMasterTx(). 250 static bool writeRegister(uint8_t reg, uint8_t value, uint8_t state) 251 { 252 struct I2cTransfer *xfer = allocXfer(state); 253 int ret = -1; 254 255 if (xfer != NULL) { 256 xfer->txrxBuf.bytes[0] = reg; 257 xfer->txrxBuf.bytes[1] = value; 258 ret = i2cMasterTx(I2C_BUS_ID, I2C_ADDR, xfer->txrxBuf.bytes, 2, i2cCallback, xfer); 259 } 260 261 return (ret == 0); 262 } 263 264 static void alsTimerCallback(uint32_t timerId, void *cookie) 265 { 266 osEnqueuePrivateEvt(EVT_SENSOR_ALS_TIMER, cookie, NULL, mData.tid); 267 } 268 269 static void proxTimerCallback(uint32_t timerId, void *cookie) 270 { 271 osEnqueuePrivateEvt(EVT_SENSOR_PROX_TIMER, cookie, NULL, mData.tid); 272 } 273 274 static inline float getLuxFromAlsData(uint16_t als0, uint16_t als1) 275 { 276 float cpl = 1.0f / AMS_TMD2772_ATIME_MS; 277 float GA; 278 279 if ((als0 * 10) < (als1 * 21)) { 280 // A light 281 GA = 0.274f; 282 } else if (((als0 * 10) >= (als1 * 21)) && ((als0 * 10) <= (als1 * 43)) && (als0 > 300)) { 283 // D65 284 GA = 0.592f; 285 } else { 286 // cool white 287 GA = 1.97f; 288 } 289 290 float lux1 = GA * 207 * (als0 - (1.799 * als1)) * cpl; 291 float lux2 = GA * 207 * ((0.188f * als0) - (0.303 * als1)) * cpl; 292 293 if ((als0 >= AMS_TMD2772_ALS_MAX_CHANNEL_COUNT) || 294 (als1 >= AMS_TMD2772_ALS_MAX_CHANNEL_COUNT)) { 295 return AMS_TMD2772_ALS_MAX_REPORT_VALUE; 296 } else if ((lux1 > lux2) && (lux1 > 0.0f)) { 297 return lux1 > AMS_TMD2772_ALS_MAX_REPORT_VALUE ? AMS_TMD2772_ALS_MAX_REPORT_VALUE : lux1; 298 } else if (lux2 > 0.0f) { 299 return lux2 > AMS_TMD2772_ALS_MAX_REPORT_VALUE ? AMS_TMD2772_ALS_MAX_REPORT_VALUE : lux2; 300 } else { 301 return 0.0f; 302 } 303 } 304 305 static void setMode(bool alsOn, bool proxOn, uint8_t state) 306 { 307 struct I2cTransfer *xfer; 308 309 xfer = allocXfer(state); 310 if (xfer != NULL) { 311 xfer->txrxBuf.bytes[0] = AMS_TMD2772_REG_ENABLE; 312 xfer->txrxBuf.bytes[1] = POWER_ON_BIT | WAIT_ENABLE_BIT | 313 (alsOn ? ALS_ENABLE_BIT : 0) | (proxOn ? PROX_ENABLE_BIT : 0); 314 xfer->txrxBuf.bytes[2] = AMS_TMD2772_ATIME_SETTING; 315 xfer->txrxBuf.bytes[3] = AMS_TMD2772_PTIME_SETTING; 316 xfer->txrxBuf.bytes[4] = alsOn ? AMS_TMD2772_WTIME_SETTING_ALS_ON : AMS_TMD2772_WTIME_SETTING_ALS_OFF; 317 i2cMasterTx(I2C_BUS_ID, I2C_ADDR, xfer->txrxBuf.bytes, 5, i2cCallback, xfer); 318 } 319 } 320 321 static bool sensorPowerAls(bool on, void *cookie) 322 { 323 osLog(LOG_INFO, DRIVER_NAME "sensorPowerAls: %d\n", on); 324 325 if (mData.alsTimerHandle) { 326 timTimerCancel(mData.alsTimerHandle); 327 mData.alsTimerHandle = 0; 328 mData.alsReading = false; 329 } 330 331 mData.lastAlsSample.idata = AMS_TMD2772_ALS_INVALID; 332 mData.alsOn = on; 333 setMode(on, mData.proxOn, (on ? SENSOR_STATE_ENABLING_ALS : SENSOR_STATE_DISABLING_ALS)); 334 335 return true; 336 } 337 338 static bool sensorFirmwareAls(void *cookie) 339 { 340 sensorSignalInternalEvt(mData.alsHandle, SENSOR_INTERNAL_EVT_FW_STATE_CHG, 1, 0); 341 return true; 342 } 343 344 static bool sensorRateAls(uint32_t rate, uint64_t latency, void *cookie) 345 { 346 if (rate == SENSOR_RATE_ONCHANGE) { 347 rate = AMS_TMD2772_DEFAULT_RATE; 348 } 349 osLog(LOG_INFO, DRIVER_NAME "sensorRateAls: %ld/%lld\n", rate, latency); 350 351 if (mData.alsTimerHandle) 352 timTimerCancel(mData.alsTimerHandle); 353 mData.alsTimerHandle = timTimerSet(sensorTimerLookupCommon(supportedRates, rateTimerVals, rate), 0, 50, alsTimerCallback, NULL, false); 354 osEnqueuePrivateEvt(EVT_SENSOR_ALS_TIMER, NULL, NULL, mData.tid); 355 sensorSignalInternalEvt(mData.alsHandle, SENSOR_INTERNAL_EVT_RATE_CHG, rate, latency); 356 357 return true; 358 } 359 360 static bool sensorFlushAls(void *cookie) 361 { 362 return osEnqueueEvt(sensorGetMyEventType(SENS_TYPE_ALS), SENSOR_DATA_EVENT_FLUSH, NULL); 363 } 364 365 static bool sendLastSampleAls(void *cookie, uint32_t tid) { 366 bool result = true; 367 368 // If we don't end up doing anything here, the expectation is that we are powering up/haven't got the 369 // first sample yet, so a broadcast event will go out soon with the first sample 370 if (mData.lastAlsSample.idata != AMS_TMD2772_ALS_INVALID) { 371 result = osEnqueuePrivateEvt(sensorGetMyEventType(SENS_TYPE_ALS), mData.lastAlsSample.vptr, NULL, tid); 372 } 373 return result; 374 } 375 376 static bool sensorPowerProx(bool on, void *cookie) 377 { 378 osLog(LOG_INFO, DRIVER_NAME "sensorPowerProx: %d\n", on); 379 380 if (mData.proxTimerHandle) { 381 timTimerCancel(mData.proxTimerHandle); 382 mData.proxTimerHandle = 0; 383 mData.proxReading = false; 384 } 385 386 mData.proxState = PROX_STATE_INIT; 387 mData.proxOn = on; 388 setMode(mData.alsOn, on, (on ? SENSOR_STATE_ENABLING_PROX : SENSOR_STATE_DISABLING_PROX)); 389 390 return true; 391 } 392 393 static bool sensorFirmwareProx(void *cookie) 394 { 395 sensorSignalInternalEvt(mData.proxHandle, SENSOR_INTERNAL_EVT_FW_STATE_CHG, 1, 0); 396 return true; 397 } 398 399 static bool sensorRateProx(uint32_t rate, uint64_t latency, void *cookie) 400 { 401 if (rate == SENSOR_RATE_ONCHANGE) { 402 rate = AMS_TMD2772_DEFAULT_RATE; 403 } 404 osLog(LOG_INFO, DRIVER_NAME "sensorRateProx: %ld/%lld\n", rate, latency); 405 406 if (mData.proxTimerHandle) 407 timTimerCancel(mData.proxTimerHandle); 408 mData.proxTimerHandle = timTimerSet(sensorTimerLookupCommon(supportedRates, rateTimerVals, rate), 0, 50, proxTimerCallback, NULL, false); 409 osEnqueuePrivateEvt(EVT_SENSOR_PROX_TIMER, NULL, NULL, mData.tid); 410 sensorSignalInternalEvt(mData.proxHandle, SENSOR_INTERNAL_EVT_RATE_CHG, rate, latency); 411 412 return true; 413 } 414 415 static bool sensorFlushProx(void *cookie) 416 { 417 return osEnqueueEvt(sensorGetMyEventType(SENS_TYPE_PROX), SENSOR_DATA_EVENT_FLUSH, NULL); 418 } 419 420 static bool sendLastSampleProx(void *cookie, uint32_t tid) { 421 union EmbeddedDataPoint sample; 422 bool result = true; 423 424 // See note in sendLastSampleAls 425 if (mData.proxState != PROX_STATE_INIT) { 426 sample.fdata = (mData.proxState == PROX_STATE_NEAR) ? 427 AMS_TMD2772_REPORT_NEAR_VALUE : AMS_TMD2772_REPORT_FAR_VALUE; 428 result = osEnqueuePrivateEvt(sensorGetMyEventType(SENS_TYPE_PROX), sample.vptr, NULL, tid); 429 } 430 return result; 431 } 432 433 static const struct SensorInfo sensorInfoAls = 434 { 435 .sensorName = "ALS", 436 .supportedRates = supportedRates, 437 .sensorType = SENS_TYPE_ALS, 438 .numAxis = NUM_AXIS_EMBEDDED, 439 .interrupt = NANOHUB_INT_NONWAKEUP, 440 .minSamples = 20 441 }; 442 443 static const struct SensorOps sensorOpsAls = 444 { 445 .sensorPower = sensorPowerAls, 446 .sensorFirmwareUpload = sensorFirmwareAls, 447 .sensorSetRate = sensorRateAls, 448 .sensorFlush = sensorFlushAls, 449 .sensorTriggerOndemand = NULL, 450 .sensorCalibrate = NULL, 451 .sensorSendOneDirectEvt = sendLastSampleAls 452 }; 453 454 static const struct SensorInfo sensorInfoProx = 455 { 456 .sensorName = "Proximity", 457 .supportedRates = supportedRates, 458 .sensorType = SENS_TYPE_PROX, 459 .numAxis = NUM_AXIS_EMBEDDED, 460 .interrupt = NANOHUB_INT_WAKEUP, 461 .minSamples = 300 462 }; 463 464 static const struct SensorOps sensorOpsProx = 465 { 466 .sensorPower = sensorPowerProx, 467 .sensorFirmwareUpload = sensorFirmwareProx, 468 .sensorSetRate = sensorRateProx, 469 .sensorFlush = sensorFlushProx, 470 .sensorTriggerOndemand = NULL, 471 .sensorCalibrate = NULL, 472 .sensorSendOneDirectEvt = sendLastSampleProx 473 }; 474 475 /* 476 * Sensor i2c state machine 477 */ 478 479 static void handle_calibration_event(struct I2cTransfer *xfer) { 480 struct I2cTransfer *nextXfer; 481 482 switch (xfer->state) { 483 case SENSOR_STATE_CALIBRATE_RESET: 484 mData.calibrationSampleCount = 0; 485 mData.calibrationSampleTotal = 0; 486 /* Intentional fall-through */ 487 488 case SENSOR_STATE_CALIBRATE_START: 489 writeRegister(AMS_TMD2772_REG_ENABLE, POWER_ON_BIT | PROX_ENABLE_BIT, SENSOR_STATE_CALIBRATE_ENABLING); 490 break; 491 492 case SENSOR_STATE_CALIBRATE_ENABLING: 493 nextXfer = allocXfer(SENSOR_STATE_CALIBRATE_POLLING_STATUS); 494 if (nextXfer != NULL) { 495 nextXfer->txrxBuf.bytes[0] = AMS_TMD2772_REG_STATUS; 496 i2cMasterTxRx(I2C_BUS_ID, I2C_ADDR, nextXfer->txrxBuf.bytes, 1, nextXfer->txrxBuf.bytes, 1, i2cCallback, nextXfer); 497 } 498 break; 499 500 case SENSOR_STATE_CALIBRATE_POLLING_STATUS: 501 if (xfer->txrxBuf.bytes[0] & PROX_INT_BIT) { 502 /* Done */ 503 nextXfer = allocXfer(SENSOR_STATE_CALIBRATE_AWAITING_SAMPLE); 504 if (nextXfer != NULL) { 505 nextXfer->txrxBuf.bytes[0] = AMS_TMD2772_REG_PDATAL; 506 i2cMasterTxRx(I2C_BUS_ID, I2C_ADDR, nextXfer->txrxBuf.bytes, 1, nextXfer->txrxBuf.bytes, 2, i2cCallback, nextXfer); 507 } 508 } else { 509 /* Poll again; go back to previous state */ 510 xfer->state = SENSOR_STATE_CALIBRATE_ENABLING; 511 handle_calibration_event(xfer); 512 } 513 break; 514 515 case SENSOR_STATE_CALIBRATE_AWAITING_SAMPLE: 516 mData.calibrationSampleCount++; 517 mData.calibrationSampleTotal += xfer->txrxBuf.calibration.prox; 518 519 writeRegister(AMS_TMD2772_REG_ENABLE, 0x00, SENSOR_STATE_CALIBRATE_DISABLING); 520 break; 521 522 case SENSOR_STATE_CALIBRATE_DISABLING: 523 if (mData.calibrationSampleCount >= 20) { 524 /* Done, calculate calibration */ 525 uint16_t average = mData.calibrationSampleTotal / mData.calibrationSampleCount; 526 uint16_t crosstalk = (average > 0x7f) ? 0x7f : average; 527 528 writeRegister(AMS_TMD2772_REG_POFFSET, crosstalk, SENSOR_STATE_IDLE); 529 } else { 530 /* Get another sample; go back to earlier state */ 531 xfer->state = SENSOR_STATE_CALIBRATE_START; 532 handle_calibration_event(xfer); 533 } 534 break; 535 536 default: 537 break; 538 } 539 } 540 541 static void handle_i2c_event(struct I2cTransfer *xfer) 542 { 543 union EmbeddedDataPoint sample; 544 bool sendData; 545 struct I2cTransfer *nextXfer; 546 547 switch (xfer->state) { 548 case SENSOR_STATE_VERIFY_ID: 549 /* Check the sensor ID */ 550 if (xfer->err != 0 || xfer->txrxBuf.bytes[0] != AMS_TMD2772_ID) { 551 osLog(LOG_INFO, DRIVER_NAME "not detected\n"); 552 sensorUnregister(mData.alsHandle); 553 sensorUnregister(mData.proxHandle); 554 break; 555 } 556 557 nextXfer = allocXfer(SENSOR_STATE_INIT); 558 if (nextXfer != NULL) { 559 /* Start address */ 560 nextXfer->txrxBuf.bytes[0] = AMS_TMD2772_REG_ENABLE; 561 /* ENABLE */ 562 nextXfer->txrxBuf.bytes[1] = 0x00; 563 /* ATIME */ 564 nextXfer->txrxBuf.bytes[2] = AMS_TMD2772_ATIME_SETTING; 565 /* PTIME */ 566 nextXfer->txrxBuf.bytes[3] = AMS_TMD2772_PTIME_SETTING; 567 /* WTIME */ 568 nextXfer->txrxBuf.bytes[4] = 0xFF; 569 i2cMasterTx(I2C_BUS_ID, I2C_ADDR, nextXfer->txrxBuf.bytes, 5, i2cCallback, nextXfer); 570 } 571 break; 572 573 case SENSOR_STATE_INIT: 574 nextXfer = allocXfer(SENSOR_STATE_IDLE); 575 if (nextXfer != NULL) { 576 /* Start address */ 577 nextXfer->txrxBuf.bytes[0] = AMS_TMD2772_REG_PERS; 578 /* PERS */ 579 nextXfer->txrxBuf.bytes[1] = 0x00; 580 /* CONFIG */ 581 nextXfer->txrxBuf.bytes[2] = 0x00; 582 /* PPULSE */ 583 nextXfer->txrxBuf.bytes[3] = AMS_TMD2772_PPULSE_SETTING; 584 /* CONTROL */ 585 nextXfer->txrxBuf.bytes[4] = 0x20; 586 i2cMasterTx(I2C_BUS_ID, I2C_ADDR, nextXfer->txrxBuf.bytes, 5, i2cCallback, nextXfer); 587 } 588 break; 589 590 case SENSOR_STATE_IDLE: 591 sensorRegisterInitComplete(mData.alsHandle); 592 sensorRegisterInitComplete(mData.proxHandle); 593 break; 594 595 case SENSOR_STATE_ENABLING_ALS: 596 sensorSignalInternalEvt(mData.alsHandle, SENSOR_INTERNAL_EVT_POWER_STATE_CHG, true, 0); 597 break; 598 599 case SENSOR_STATE_ENABLING_PROX: 600 sensorSignalInternalEvt(mData.proxHandle, SENSOR_INTERNAL_EVT_POWER_STATE_CHG, true, 0); 601 break; 602 603 case SENSOR_STATE_DISABLING_ALS: 604 sensorSignalInternalEvt(mData.alsHandle, SENSOR_INTERNAL_EVT_POWER_STATE_CHG, false, 0); 605 break; 606 607 case SENSOR_STATE_DISABLING_PROX: 608 sensorSignalInternalEvt(mData.proxHandle, SENSOR_INTERNAL_EVT_POWER_STATE_CHG, false, 0); 609 break; 610 611 case SENSOR_STATE_SAMPLING: 612 #if 0 613 osLog(LOG_INFO, DRIVER_NAME "sample ready: status=%02x prox=%u als0=%u als1=%u\n", 614 xfer->txrxBuf.sample.status, xfer->txrxBuf.sample.prox, 615 xfer->txrxBuf.sample.als[0], xfer->txrxBuf.sample.als[1]); 616 #endif 617 618 if (mData.alsOn && mData.alsReading && 619 (xfer->txrxBuf.sample.status & ALS_VALID_BIT)) { 620 /* Create event */ 621 sample.fdata = getLuxFromAlsData(xfer->txrxBuf.sample.als[0], 622 xfer->txrxBuf.sample.als[1]); 623 if (mData.lastAlsSample.idata != sample.idata) { 624 osEnqueueEvt(sensorGetMyEventType(SENS_TYPE_ALS), sample.vptr, NULL); 625 mData.lastAlsSample.fdata = sample.fdata; 626 } 627 } 628 629 if (mData.proxOn && mData.proxReading && 630 (xfer->txrxBuf.sample.status & PROX_VALID_BIT)) { 631 /* Create event */ 632 sendData = true; 633 if (mData.proxState == PROX_STATE_INIT) { 634 if (xfer->txrxBuf.sample.prox > AMS_TMD2772_THRESHOLD_ASSERT_NEAR) { 635 sample.fdata = AMS_TMD2772_REPORT_NEAR_VALUE; 636 mData.proxState = PROX_STATE_NEAR; 637 } else { 638 sample.fdata = AMS_TMD2772_REPORT_FAR_VALUE; 639 mData.proxState = PROX_STATE_FAR; 640 } 641 } else { 642 if (mData.proxState == PROX_STATE_NEAR && 643 xfer->txrxBuf.sample.prox < AMS_TMD2772_THRESHOLD_DEASSERT_NEAR) { 644 sample.fdata = AMS_TMD2772_REPORT_FAR_VALUE; 645 mData.proxState = PROX_STATE_FAR; 646 } else if (mData.proxState == PROX_STATE_FAR && 647 xfer->txrxBuf.sample.prox > AMS_TMD2772_THRESHOLD_ASSERT_NEAR) { 648 sample.fdata = AMS_TMD2772_REPORT_NEAR_VALUE; 649 mData.proxState = PROX_STATE_NEAR; 650 } else { 651 sendData = false; 652 } 653 } 654 655 if (sendData) 656 osEnqueueEvt(sensorGetMyEventType(SENS_TYPE_PROX), sample.vptr, NULL); 657 } 658 659 mData.alsReading = false; 660 mData.proxReading = false; 661 break; 662 663 default: 664 handle_calibration_event(xfer); 665 break; 666 } 667 668 xfer->inUse = false; 669 } 670 671 /* 672 * Main driver entry points 673 */ 674 675 static bool init_app(uint32_t myTid) 676 { 677 /* Set up driver private data */ 678 mData.tid = myTid; 679 mData.alsOn = false; 680 mData.alsReading = false; 681 mData.proxOn = false; 682 mData.proxReading = false; 683 mData.lastAlsSample.idata = AMS_TMD2772_ALS_INVALID; 684 mData.proxState = PROX_STATE_INIT; 685 686 /* Register sensors */ 687 mData.alsHandle = sensorRegister(&sensorInfoAls, &sensorOpsAls, NULL, false); 688 mData.proxHandle = sensorRegister(&sensorInfoProx, &sensorOpsProx, NULL, false); 689 690 osEventSubscribe(myTid, EVT_APP_START); 691 692 return true; 693 } 694 695 static void end_app(void) 696 { 697 sensorUnregister(mData.alsHandle); 698 sensorUnregister(mData.proxHandle); 699 700 i2cMasterRelease(I2C_BUS_ID); 701 } 702 703 static void handle_event(uint32_t evtType, const void* evtData) 704 { 705 struct I2cTransfer *xfer; 706 707 switch (evtType) { 708 case EVT_APP_START: 709 osEventUnsubscribe(mData.tid, EVT_APP_START); 710 i2cMasterRequest(I2C_BUS_ID, I2C_SPEED); 711 712 /* TODO: reset chip first */ 713 xfer = allocXfer(SENSOR_STATE_VERIFY_ID); 714 if (xfer != NULL) { 715 xfer->txrxBuf.bytes[0] = AMS_TMD2772_REG_ID; 716 i2cMasterTxRx(I2C_BUS_ID, I2C_ADDR, xfer->txrxBuf.bytes, 1, xfer->txrxBuf.bytes, 1, i2cCallback, xfer); 717 } 718 break; 719 720 case EVT_SENSOR_I2C: 721 handle_i2c_event((struct I2cTransfer *)evtData); 722 break; 723 724 case EVT_SENSOR_ALS_TIMER: 725 case EVT_SENSOR_PROX_TIMER: 726 /* Start sampling for a value */ 727 if (!mData.alsReading && !mData.proxReading) { 728 xfer = allocXfer(SENSOR_STATE_SAMPLING); 729 if (xfer != NULL) { 730 xfer->txrxBuf.bytes[0] = AMS_TMD2772_REG_STATUS; 731 i2cMasterTxRx(I2C_BUS_ID, I2C_ADDR, xfer->txrxBuf.bytes, 1, xfer->txrxBuf.bytes, 7, i2cCallback, xfer); 732 } 733 } 734 735 if (evtType == EVT_SENSOR_ALS_TIMER) 736 mData.alsReading = true; 737 else 738 mData.proxReading = true; 739 break; 740 } 741 } 742 743 INTERNAL_APP_INIT(APP_ID_MAKE(APP_ID_VENDOR_GOOGLE, 9), AMS_TMD2772_APP_VERSION, init_app, end_app, handle_event); 744