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 <eventnums.h> 22 #include <gpio.h> 23 #include <timer.h> 24 #include <sensors.h> 25 #include <heap.h> 26 #include <hostIntf.h> 27 #include <isr.h> 28 #include <i2c.h> 29 #include <nanohubPacket.h> 30 #include <sensors.h> 31 #include <seos.h> 32 33 #include <plat/inc/exti.h> 34 #include <plat/inc/gpio.h> 35 #include <plat/inc/syscfg.h> 36 #include <variant/inc/variant.h> 37 38 #ifndef PROX_INT_PIN 39 #error "PROX_INT_PIN is not defined; please define in variant.h" 40 #endif 41 42 #ifndef PROX_IRQ 43 #error "PROX_IRQ is not defined; please define in variant.h" 44 #endif 45 46 #define RPR0521_APP_VERSION 3 47 48 #define I2C_BUS_ID 0 49 #define I2C_SPEED 400000 50 #define I2C_ADDR 0x38 51 52 #define ROHM_RPR0521_REG_ID 0x92 53 #define ROHM_RPR0521_REG_SYSTEM_CONTROL 0x40 54 #define ROHM_RPR0521_REG_MODE_CONTROL 0x41 55 #define ROHM_RPR0521_REG_ALS_PS_CONTROL 0x42 56 #define ROHM_RPR0521_REG_PS_CONTROL 0x43 57 #define ROHM_RPR0521_REG_PS_DATA_LSB 0x44 58 #define ROHM_RPR0521_REG_ALS_DATA0_LSB 0x46 59 #define ROHM_RPR0521_REG_INTERRUPT 0x4a 60 #define ROHM_RPR0521_REG_PS_TH_LSB 0x4b 61 #define ROHM_RPR0521_REG_PS_TH_MSB 0x4c 62 #define ROHM_RPR0521_REG_PS_TL_LSB 0x4d 63 #define ROHM_RPR0521_REG_PS_TL_MSB 0x4e 64 #define ROHM_RPR0521_REG_ALS_DATA0_TH_LSB 0x4f 65 #define ROHM_RPR0521_REG_ALS_DATA0_TL_LSB 0x51 66 #define ROHM_RPR0521_REG_PS_OFFSET_LSB 0x53 67 #define ROHM_RPR0521_REG_PS_OFFSET_MSB 0x54 68 69 #define ROHM_RPR0521_ID 0xe0 70 71 #define ROHM_RPR0521_DEFAULT_RATE SENSOR_HZ(5) 72 73 enum { 74 ALS_GAIN_X1 = 0, 75 ALS_GAIN_X2 = 1, 76 ALS_GAIN_X64 = 2, 77 ALS_GAIN_X128 = 3, 78 }; 79 #define ROHM_RPR0521_GAIN_ALS0 ALS_GAIN_X1 80 #define ROHM_RPR0521_GAIN_ALS1 ALS_GAIN_X1 81 82 enum { 83 LED_CURRENT_25MA = 0, 84 LED_CURRENT_50MA = 1, 85 LED_CURRENT_100MA = 2, 86 LED_CURRENT_200MA = 3, 87 }; 88 #define ROHM_RPR0521_LED_CURRENT LED_CURRENT_100MA 89 90 /* ROHM_RPR0521_REG_SYSTEM_CONTROL */ 91 #define SW_RESET_BIT (1 << 7) 92 #define INT_RESET_BIT (1 << 6) 93 94 /* ROHM_RPR0521_REG_MODE_CONTROL */ 95 #define ALS_EN_BIT (1 << 7) 96 #define PS_EN_BIT (1 << 6) 97 98 /* ROHM_RPR0521_REG_PS_CONTROL */ 99 enum { 100 PS_GAIN_X1 = 0, 101 PS_GAIN_X2 = 1, 102 PS_GAIN_X4 = 2, 103 }; 104 enum { 105 PS_PERSISTENCE_ACTIVE_AT_EACH_MEASUREMENT_END = 0, 106 PS_PERSISTENCE_STATUS_UPDATED_AT_EACH_MEASUREMENT_END = 1, 107 }; 108 #define ROHM_RPR0521_GAIN_PS PS_GAIN_X1 109 110 111 /* ROHM_RPR0521_REG_INTERRUPT */ 112 #define INTERRUPT_LATCH_BIT (1 << 2) 113 enum { 114 INTERRUPT_MODE_PS_TH_H_ONLY = 0, 115 INTERRUPT_MODE_PS_HYSTERESIS = 1, 116 INTERRUPT_MODE_PS_OUTSIDE_DETECT = 2 117 }; 118 enum { 119 INTERRUPT_TRIGGER_INACTIVE = 0, 120 INTERRUPT_TRIGGER_PS = 1, 121 INTERRUPT_TRIGGER_ALS = 2, 122 INTERRUPT_TRIGGER_BOTH = 3 123 }; 124 125 126 #define ROHM_RPR0521_REPORT_NEAR_VALUE 0.0f // centimeters 127 #define ROHM_RPR0521_REPORT_FAR_VALUE 5.0f // centimeters 128 #define ROHM_RPR0521_THRESHOLD_ASSERT_NEAR 12 // value in PS_DATA 129 #define ROHM_RPR0521_THRESHOLD_DEASSERT_NEAR 7 // value in PS_DATA 130 131 #define ROHM_RPR0521_ALS_INVALID UINT32_MAX 132 133 #define ROHM_RPR0521_ALS_TIMER_DELAY 200000000ULL 134 135 #define ROHM_RPR0521_MAX_PENDING_I2C_REQUESTS 4 136 #define ROHM_RPR0521_MAX_I2C_TRANSFER_SIZE 16 137 138 #define INFO_PRINT(fmt, ...) do { \ 139 osLog(LOG_INFO, "[Rohm RPR-0521] " fmt, ##__VA_ARGS__); \ 140 } while (0); 141 142 #define DEBUG_PRINT(fmt, ...) do { \ 143 if (enable_debug) { \ 144 osLog(LOG_INFO, "[Rohm RPR-0521] " fmt, ##__VA_ARGS__); \ 145 } \ 146 } while (0); 147 148 static const bool enable_debug = 0; 149 150 /* Private driver events */ 151 enum SensorEvents 152 { 153 EVT_SENSOR_I2C = EVT_APP_START + 1, 154 EVT_SENSOR_ALS_TIMER, 155 EVT_SENSOR_PROX_INTERRUPT, 156 }; 157 158 /* I2C state machine */ 159 enum SensorState 160 { 161 SENSOR_STATE_RESET, 162 SENSOR_STATE_VERIFY_ID, 163 SENSOR_STATE_INIT_GAINS, 164 SENSOR_STATE_INIT_THRESHOLDS, 165 SENSOR_STATE_INIT_OFFSETS, 166 SENSOR_STATE_FINISH_INIT, 167 SENSOR_STATE_ENABLING_ALS, 168 SENSOR_STATE_ENABLING_PROX, 169 SENSOR_STATE_DISABLING_ALS, 170 SENSOR_STATE_DISABLING_PROX, 171 SENSOR_STATE_DISABLING_PROX_2, 172 SENSOR_STATE_DISABLING_PROX_3, 173 SENSOR_STATE_ALS_SAMPLING, 174 SENSOR_STATE_PROX_SAMPLING, 175 SENSOR_STATE_IDLE, 176 }; 177 178 enum ProxState 179 { 180 PROX_STATE_INIT, 181 PROX_STATE_NEAR, 182 PROX_STATE_FAR, 183 }; 184 185 enum MeasurementTime { 186 MEASUREMENT_TIME_ALS_STANDBY_PS_STANDBY = 0, 187 MEASUREMENT_TIME_ALS_STANDBY_PS_10 = 1, 188 MEASUREMENT_TIME_ALS_STANDBY_PS_40 = 2, 189 MEASUREMENT_TIME_ALS_STANDBY_PS_100 = 3, 190 MEASUREMENT_TIME_ALS_STANDBY_PS_400 = 4, 191 MEASUREMENT_TIME_ALS_100_PS_50 = 5, 192 MEASUREMENT_TIME_ALS_100_PS_100 = 6, 193 MEASUREMENT_TIME_ALS_100_PS_400 = 7, 194 MEASUREMENT_TIME_ALS_400_PS_50 = 8, 195 MEASUREMENT_TIME_ALS_400_PS_100 = 9, 196 MEASUREMENT_TIME_ALS_400_PS_STANDBY = 10, 197 MEASUREMENT_TIME_ALS_400_PS_400 = 11, 198 MEASUREMENT_TIME_ALS_50_PS_50 = 12, 199 }; 200 201 struct I2cTransfer 202 { 203 size_t tx; 204 size_t rx; 205 int err; 206 uint8_t txrxBuf[ROHM_RPR0521_MAX_I2C_TRANSFER_SIZE]; 207 uint8_t state; 208 bool inUse; 209 }; 210 211 struct SensorData 212 { 213 struct Gpio *pin; 214 struct ChainedIsr isr; 215 216 uint32_t tid; 217 218 uint32_t alsHandle; 219 uint32_t proxHandle; 220 uint32_t alsTimerHandle; 221 222 union EmbeddedDataPoint lastAlsSample; 223 224 struct I2cTransfer transfers[ROHM_RPR0521_MAX_PENDING_I2C_REQUESTS]; 225 226 uint8_t proxState; // enum ProxState 227 228 bool alsOn; 229 bool proxOn; 230 }; 231 232 static struct SensorData mTask; 233 234 static const uint32_t supportedRates[] = 235 { 236 SENSOR_HZ(5), 237 SENSOR_RATE_ONCHANGE, 238 0, 239 }; 240 241 /* 242 * Helper functions 243 */ 244 static bool proxIsr(struct ChainedIsr *localIsr) 245 { 246 struct SensorData *data = container_of(localIsr, struct SensorData, isr); 247 bool firstProxSample = (data->proxState == PROX_STATE_INIT); 248 uint8_t lastProxState = data->proxState; 249 bool pinState; 250 union EmbeddedDataPoint sample; 251 252 if (!extiIsPendingGpio(data->pin)) { 253 return false; 254 } 255 256 if (data->proxOn) { 257 pinState = gpioGet(data->pin); 258 259 if (firstProxSample && !pinState) { 260 osEnqueuePrivateEvt(EVT_SENSOR_PROX_INTERRUPT, NULL, NULL, mTask.tid); 261 } else if (!firstProxSample) { 262 sample.fdata = (pinState) ? ROHM_RPR0521_REPORT_FAR_VALUE : ROHM_RPR0521_REPORT_NEAR_VALUE; 263 data->proxState = (pinState) ? PROX_STATE_FAR : PROX_STATE_NEAR; 264 if (data->proxState != lastProxState) 265 osEnqueueEvt(sensorGetMyEventType(SENS_TYPE_PROX), sample.vptr, NULL); 266 } 267 } 268 269 extiClearPendingGpio(data->pin); 270 return true; 271 } 272 273 static bool enableInterrupt(struct Gpio *pin, struct ChainedIsr *isr) 274 { 275 extiEnableIntGpio(pin, EXTI_TRIGGER_BOTH); 276 extiChainIsr(PROX_IRQ, isr); 277 return true; 278 } 279 280 static bool disableInterrupt(struct Gpio *pin, struct ChainedIsr *isr) 281 { 282 extiUnchainIsr(PROX_IRQ, isr); 283 extiDisableIntGpio(pin); 284 return true; 285 } 286 287 static void i2cCallback(void *cookie, size_t tx, size_t rx, int err) 288 { 289 struct I2cTransfer *xfer = cookie; 290 291 xfer->tx = tx; 292 xfer->rx = rx; 293 xfer->err = err; 294 295 osEnqueuePrivateEvt(EVT_SENSOR_I2C, cookie, NULL, mTask.tid); 296 if (err != 0) 297 INFO_PRINT("i2c error (tx: %d, rx: %d, err: %d)\n", tx, rx, err); 298 } 299 300 static void alsTimerCallback(uint32_t timerId, void *cookie) 301 { 302 osEnqueuePrivateEvt(EVT_SENSOR_ALS_TIMER, cookie, NULL, mTask.tid); 303 } 304 305 // Allocate a buffer and mark it as in use with the given state, or return NULL 306 // if no buffers available. Must *not* be called from interrupt context. 307 static struct I2cTransfer *allocXfer(uint8_t state) 308 { 309 size_t i; 310 311 for (i = 0; i < ARRAY_SIZE(mTask.transfers); i++) { 312 if (!mTask.transfers[i].inUse) { 313 mTask.transfers[i].inUse = true; 314 mTask.transfers[i].state = state; 315 return &mTask.transfers[i]; 316 } 317 } 318 319 osLog(LOG_ERROR, "[BMP280]: Ran out of i2c buffers!"); 320 return NULL; 321 } 322 323 // Helper function to write a one byte register. Returns true if we got a 324 // successful return value from i2cMasterTx(). 325 static bool writeRegister(uint8_t reg, uint8_t value, uint8_t state) 326 { 327 struct I2cTransfer *xfer = allocXfer(state); 328 int ret = -1; 329 330 if (xfer != NULL) { 331 xfer->txrxBuf[0] = reg; 332 xfer->txrxBuf[1] = value; 333 ret = i2cMasterTx(I2C_BUS_ID, I2C_ADDR, xfer->txrxBuf, 2, i2cCallback, xfer); 334 } 335 336 return (ret == 0); 337 } 338 339 static inline float getLuxFromAlsData(uint16_t als0, uint16_t als1) 340 { 341 static const float invGain[] = {1.0f, 0.5f, 1.0f / 64.0f, 1.0f / 128.0f}; 342 float d0 = (float)als0 * invGain[ROHM_RPR0521_GAIN_ALS0]; 343 float d1 = (float)als1 * invGain[ROHM_RPR0521_GAIN_ALS1]; 344 float ratio = d1 / d0; 345 float c1; 346 float c2; 347 348 if (ratio < 1.221f) { 349 c1 = 6.323f; 350 c2 = -3.917f; 351 } else if (ratio < 1.432f) { 352 c1 = 5.350f; 353 c2 = -3.121f; 354 } else if (ratio < 1.710f) { 355 c1 = 2.449f; 356 c2 = -1.096f; 357 } else if (ratio < 3.393f) { 358 c1 = 1.155f; 359 c2 = -0.340f; 360 } else { 361 c1 = c2 = 0.0f; 362 } 363 364 return c1 * d0 + c2 * d1; 365 } 366 367 static void setMode(bool alsOn, bool proxOn, uint8_t state) 368 { 369 uint8_t ctrl; 370 371 static const uint8_t measurementTime[] = { 372 MEASUREMENT_TIME_ALS_STANDBY_PS_STANDBY, /* als disabled, prox disabled */ 373 MEASUREMENT_TIME_ALS_100_PS_100, /* als enabled, prox disabled */ 374 MEASUREMENT_TIME_ALS_STANDBY_PS_100, /* als disabled, prox enabled */ 375 MEASUREMENT_TIME_ALS_100_PS_100, /* als enabled, prox enabled */ 376 }; 377 378 ctrl = measurementTime[alsOn ? 1 : 0 + proxOn ? 2 : 0] | (alsOn ? ALS_EN_BIT : 0) | (proxOn ? PS_EN_BIT : 0); 379 writeRegister(ROHM_RPR0521_REG_MODE_CONTROL, ctrl, state); 380 } 381 382 static bool sensorPowerAls(bool on, void *cookie) 383 { 384 DEBUG_PRINT("sensorPowerAls: %d\n", on); 385 386 if (on && !mTask.alsTimerHandle) { 387 mTask.alsTimerHandle = timTimerSet(ROHM_RPR0521_ALS_TIMER_DELAY, 0, 50, alsTimerCallback, NULL, false); 388 } else if (!on && mTask.alsTimerHandle) { 389 timTimerCancel(mTask.alsTimerHandle); 390 mTask.alsTimerHandle = 0; 391 } 392 393 mTask.lastAlsSample.idata = ROHM_RPR0521_ALS_INVALID; 394 mTask.alsOn = on; 395 396 setMode(on, mTask.proxOn, (on ? SENSOR_STATE_ENABLING_ALS : SENSOR_STATE_DISABLING_ALS)); 397 return true; 398 } 399 400 static bool sensorFirmwareAls(void *cookie) 401 { 402 return sensorSignalInternalEvt(mTask.alsHandle, SENSOR_INTERNAL_EVT_FW_STATE_CHG, 1, 0); 403 } 404 405 static bool sensorRateAls(uint32_t rate, uint64_t latency, void *cookie) 406 { 407 if (rate == SENSOR_RATE_ONCHANGE) 408 rate = ROHM_RPR0521_DEFAULT_RATE; 409 410 DEBUG_PRINT("sensorRateAls: rate=%ld Hz latency=%lld ns\n", rate/1024, latency); 411 412 return sensorSignalInternalEvt(mTask.alsHandle, SENSOR_INTERNAL_EVT_RATE_CHG, rate, latency); 413 } 414 415 static bool sensorFlushAls(void *cookie) 416 { 417 return osEnqueueEvt(sensorGetMyEventType(SENS_TYPE_ALS), SENSOR_DATA_EVENT_FLUSH, NULL); 418 } 419 420 static bool sendLastSampleAls(void *cookie, uint32_t tid) { 421 bool result = true; 422 423 // If we don't end up doing anything here, the expectation is that we are powering up/haven't got the 424 // first sample yet, so the client will get a broadcast event soon 425 if (mTask.lastAlsSample.idata != ROHM_RPR0521_ALS_INVALID) { 426 result = osEnqueuePrivateEvt(sensorGetMyEventType(SENS_TYPE_ALS), mTask.lastAlsSample.vptr, NULL, tid); 427 } 428 return result; 429 } 430 431 static bool sensorPowerProx(bool on, void *cookie) 432 { 433 DEBUG_PRINT("sensorPowerProx: %d\n", on); 434 435 if (on) { 436 extiClearPendingGpio(mTask.pin); 437 enableInterrupt(mTask.pin, &mTask.isr); 438 } else { 439 disableInterrupt(mTask.pin, &mTask.isr); 440 extiClearPendingGpio(mTask.pin); 441 } 442 443 mTask.proxState = PROX_STATE_INIT; 444 mTask.proxOn = on; 445 446 setMode(mTask.alsOn, on, (on ? SENSOR_STATE_ENABLING_PROX : SENSOR_STATE_DISABLING_PROX)); 447 return true; 448 } 449 450 static bool sensorFirmwareProx(void *cookie) 451 { 452 return sensorSignalInternalEvt(mTask.proxHandle, SENSOR_INTERNAL_EVT_FW_STATE_CHG, 1, 0); 453 } 454 455 static bool sensorRateProx(uint32_t rate, uint64_t latency, void *cookie) 456 { 457 if (rate == SENSOR_RATE_ONCHANGE) 458 rate = ROHM_RPR0521_DEFAULT_RATE; 459 460 DEBUG_PRINT("sensorRateProx: rate=%ld Hz latency=%lld ns\n", rate/1024, latency); 461 462 return sensorSignalInternalEvt(mTask.proxHandle, SENSOR_INTERNAL_EVT_RATE_CHG, rate, latency); 463 } 464 465 static bool sensorFlushProx(void *cookie) 466 { 467 return osEnqueueEvt(sensorGetMyEventType(SENS_TYPE_PROX), SENSOR_DATA_EVENT_FLUSH, NULL); 468 } 469 470 static bool sensorCfgDataProx(void *data, void *cookie) 471 { 472 struct I2cTransfer *xfer; 473 474 DEBUG_PRINT("sensorCfgDataProx"); 475 476 int32_t offset = *(int32_t*)data; 477 478 INFO_PRINT("Received cfg data: %d\n", (int)offset); 479 480 xfer = allocXfer(SENSOR_STATE_IDLE); 481 if (xfer != NULL) { 482 xfer->txrxBuf[0] = ROHM_RPR0521_REG_PS_OFFSET_LSB; 483 xfer->txrxBuf[1] = offset & 0xFF; 484 xfer->txrxBuf[2] = (offset >> 8) & 0x3; 485 i2cMasterTx(I2C_BUS_ID, I2C_ADDR, xfer->txrxBuf, 3, i2cCallback, xfer); 486 487 return true; 488 } 489 490 return false; 491 } 492 493 static bool sendLastSampleProx(void *cookie, uint32_t tid) { 494 union EmbeddedDataPoint sample; 495 bool result = true; 496 497 // See note in sendLastSampleAls 498 if (mTask.proxState != PROX_STATE_INIT) { 499 sample.fdata = (mTask.proxState == PROX_STATE_NEAR) ? ROHM_RPR0521_REPORT_NEAR_VALUE : ROHM_RPR0521_REPORT_FAR_VALUE; 500 result = osEnqueuePrivateEvt(sensorGetMyEventType(SENS_TYPE_PROX), sample.vptr, NULL, tid); 501 } 502 return result; 503 } 504 505 static const struct SensorInfo sensorInfoAls = 506 { 507 .sensorName = "ALS", 508 .supportedRates = supportedRates, 509 .sensorType = SENS_TYPE_ALS, 510 .numAxis = NUM_AXIS_EMBEDDED, 511 .interrupt = NANOHUB_INT_NONWAKEUP, 512 .minSamples = 20 513 }; 514 515 static const struct SensorOps sensorOpsAls = 516 { 517 .sensorPower = sensorPowerAls, 518 .sensorFirmwareUpload = sensorFirmwareAls, 519 .sensorSetRate = sensorRateAls, 520 .sensorFlush = sensorFlushAls, 521 .sensorTriggerOndemand = NULL, 522 .sensorCalibrate = NULL, 523 .sensorSendOneDirectEvt = sendLastSampleAls 524 }; 525 526 static const struct SensorInfo sensorInfoProx = 527 { 528 .sensorName = "Proximity", 529 .supportedRates = supportedRates, 530 .sensorType = SENS_TYPE_PROX, 531 .numAxis = NUM_AXIS_EMBEDDED, 532 .interrupt = NANOHUB_INT_WAKEUP, 533 .minSamples = 300 534 }; 535 536 static const struct SensorOps sensorOpsProx = 537 { 538 .sensorPower = sensorPowerProx, 539 .sensorFirmwareUpload = sensorFirmwareProx, 540 .sensorSetRate = sensorRateProx, 541 .sensorFlush = sensorFlushProx, 542 .sensorTriggerOndemand = NULL, 543 .sensorCalibrate = NULL, 544 .sensorCfgData = sensorCfgDataProx, 545 .sensorSendOneDirectEvt = sendLastSampleProx 546 }; 547 548 /* 549 * Sensor i2c state machine 550 */ 551 552 static void __attribute__((unused)) sensorAlsFree(void *ptr) 553 { 554 } 555 556 static void __attribute__((unused)) sensorProxFree(void *ptr) 557 { 558 } 559 560 static void handle_i2c_event(struct I2cTransfer *xfer) 561 { 562 union EmbeddedDataPoint sample; 563 uint16_t als0, als1, ps; 564 uint8_t lastProxState; 565 struct I2cTransfer *newXfer; 566 uint8_t regData; 567 568 switch (xfer->state) { 569 case SENSOR_STATE_RESET: 570 newXfer = allocXfer(SENSOR_STATE_VERIFY_ID); 571 if (newXfer != NULL) { 572 newXfer->txrxBuf[0] = ROHM_RPR0521_REG_ID; 573 i2cMasterTxRx(I2C_BUS_ID, I2C_ADDR, newXfer->txrxBuf, 1, newXfer->txrxBuf, 1, i2cCallback, newXfer); 574 } 575 break; 576 577 case SENSOR_STATE_VERIFY_ID: 578 /* Check the sensor ID */ 579 if (xfer->err != 0 || xfer->txrxBuf[0] != ROHM_RPR0521_ID) { 580 INFO_PRINT("not detected\n"); 581 sensorUnregister(mTask.alsHandle); 582 sensorUnregister(mTask.proxHandle); 583 break; 584 } 585 586 newXfer = allocXfer(SENSOR_STATE_INIT_GAINS); 587 if (newXfer != NULL) { 588 newXfer->txrxBuf[0] = ROHM_RPR0521_REG_ALS_PS_CONTROL; 589 newXfer->txrxBuf[1] = (ROHM_RPR0521_GAIN_ALS0 << 4) | (ROHM_RPR0521_GAIN_ALS1 << 2) | ROHM_RPR0521_LED_CURRENT; 590 newXfer->txrxBuf[2] = (ROHM_RPR0521_GAIN_PS << 4) | PS_PERSISTENCE_ACTIVE_AT_EACH_MEASUREMENT_END; 591 i2cMasterTx(I2C_BUS_ID, I2C_ADDR, newXfer->txrxBuf, 3, i2cCallback, newXfer); 592 } 593 break; 594 595 case SENSOR_STATE_INIT_GAINS: 596 /* Offset register */ 597 newXfer = allocXfer(SENSOR_STATE_INIT_OFFSETS); 598 if (newXfer != NULL) { 599 newXfer->txrxBuf[0] = ROHM_RPR0521_REG_PS_OFFSET_LSB; 600 newXfer->txrxBuf[1] = 0; 601 newXfer->txrxBuf[2] = 0; 602 i2cMasterTx(I2C_BUS_ID, I2C_ADDR, newXfer->txrxBuf, 3, i2cCallback, newXfer); 603 } 604 break; 605 606 case SENSOR_STATE_INIT_OFFSETS: 607 /* PS Threshold register */ 608 newXfer = allocXfer(SENSOR_STATE_INIT_THRESHOLDS); 609 if (newXfer != NULL) { 610 newXfer->txrxBuf[0] = ROHM_RPR0521_REG_PS_TH_LSB; 611 newXfer->txrxBuf[1] = (ROHM_RPR0521_THRESHOLD_ASSERT_NEAR & 0xFF); 612 newXfer->txrxBuf[2] = (ROHM_RPR0521_THRESHOLD_ASSERT_NEAR & 0xFF00) >> 8; 613 newXfer->txrxBuf[3] = (ROHM_RPR0521_THRESHOLD_DEASSERT_NEAR & 0xFF); 614 newXfer->txrxBuf[4] = (ROHM_RPR0521_THRESHOLD_DEASSERT_NEAR & 0xFF00) >> 8; 615 i2cMasterTx(I2C_BUS_ID, I2C_ADDR, newXfer->txrxBuf, 5, i2cCallback, newXfer); 616 } 617 break; 618 619 case SENSOR_STATE_INIT_THRESHOLDS: 620 /* Interrupt register */ 621 regData = (INTERRUPT_MODE_PS_HYSTERESIS << 4) | INTERRUPT_LATCH_BIT | INTERRUPT_TRIGGER_PS; 622 writeRegister(ROHM_RPR0521_REG_INTERRUPT, regData, SENSOR_STATE_FINISH_INIT); 623 break; 624 625 case SENSOR_STATE_FINISH_INIT: 626 sensorRegisterInitComplete(mTask.alsHandle); 627 sensorRegisterInitComplete(mTask.proxHandle); 628 break; 629 630 case SENSOR_STATE_ENABLING_ALS: 631 sensorSignalInternalEvt(mTask.alsHandle, SENSOR_INTERNAL_EVT_POWER_STATE_CHG, true, 0); 632 break; 633 634 case SENSOR_STATE_ENABLING_PROX: 635 sensorSignalInternalEvt(mTask.proxHandle, SENSOR_INTERNAL_EVT_POWER_STATE_CHG, true, 0); 636 break; 637 638 case SENSOR_STATE_DISABLING_ALS: 639 sensorSignalInternalEvt(mTask.alsHandle, SENSOR_INTERNAL_EVT_POWER_STATE_CHG, false, 0); 640 break; 641 642 case SENSOR_STATE_DISABLING_PROX: 643 // Clear persistence setting 644 regData = (ROHM_RPR0521_GAIN_PS << 4) | PS_PERSISTENCE_ACTIVE_AT_EACH_MEASUREMENT_END; 645 writeRegister(ROHM_RPR0521_REG_PS_CONTROL, regData, SENSOR_STATE_DISABLING_PROX_2); 646 break; 647 648 case SENSOR_STATE_DISABLING_PROX_2: 649 // Reset interrupt 650 writeRegister(ROHM_RPR0521_REG_SYSTEM_CONTROL, INT_RESET_BIT, SENSOR_STATE_DISABLING_PROX_3); 651 break; 652 653 case SENSOR_STATE_DISABLING_PROX_3: 654 sensorSignalInternalEvt(mTask.proxHandle, SENSOR_INTERNAL_EVT_POWER_STATE_CHG, false, 0); 655 break; 656 657 case SENSOR_STATE_ALS_SAMPLING: 658 als0 = *(uint16_t*)(xfer->txrxBuf); 659 als1 = *(uint16_t*)(xfer->txrxBuf+2); 660 661 DEBUG_PRINT("als sample ready: als0=%u als1=%u\n", als0, als1); 662 663 if (mTask.alsOn) { 664 sample.fdata = getLuxFromAlsData(als0, als1); 665 if (mTask.lastAlsSample.idata != sample.idata) { 666 osEnqueueEvt(sensorGetMyEventType(SENS_TYPE_ALS), sample.vptr, NULL); 667 mTask.lastAlsSample.fdata = sample.fdata; 668 } 669 } 670 671 break; 672 673 case SENSOR_STATE_PROX_SAMPLING: 674 ps = *(uint16_t*)(xfer->txrxBuf); 675 lastProxState = mTask.proxState; 676 677 DEBUG_PRINT("prox sample ready: prox=%u\n", ps); 678 679 if (mTask.proxOn) { 680 if (ps > ROHM_RPR0521_THRESHOLD_ASSERT_NEAR) { 681 sample.fdata = ROHM_RPR0521_REPORT_NEAR_VALUE; 682 mTask.proxState = PROX_STATE_NEAR; 683 } else { 684 sample.fdata = ROHM_RPR0521_REPORT_FAR_VALUE; 685 mTask.proxState = PROX_STATE_FAR; 686 } 687 688 if (mTask.proxState != lastProxState) 689 osEnqueueEvt(sensorGetMyEventType(SENS_TYPE_PROX), sample.vptr, NULL); 690 691 // After the first prox sample, change the persistance setting to assert 692 // interrupt on-change, rather than after every sample 693 regData = (ROHM_RPR0521_GAIN_PS << 4) | PS_PERSISTENCE_STATUS_UPDATED_AT_EACH_MEASUREMENT_END; 694 writeRegister(ROHM_RPR0521_REG_PS_CONTROL, regData, SENSOR_STATE_IDLE); 695 } 696 697 break; 698 699 default: 700 break; 701 } 702 703 xfer->inUse = false; 704 } 705 706 /* 707 * Main driver entry points 708 */ 709 710 static bool init_app(uint32_t myTid) 711 { 712 /* Set up driver private data */ 713 mTask.tid = myTid; 714 mTask.alsOn = false; 715 mTask.proxOn = false; 716 mTask.lastAlsSample.idata = ROHM_RPR0521_ALS_INVALID; 717 mTask.proxState = PROX_STATE_INIT; 718 719 mTask.pin = gpioRequest(PROX_INT_PIN); 720 gpioConfigInput(mTask.pin, GPIO_SPEED_LOW, GPIO_PULL_NONE); 721 syscfgSetExtiPort(mTask.pin); 722 mTask.isr.func = proxIsr; 723 724 /* Register sensors */ 725 mTask.alsHandle = sensorRegister(&sensorInfoAls, &sensorOpsAls, NULL, false); 726 mTask.proxHandle = sensorRegister(&sensorInfoProx, &sensorOpsProx, NULL, false); 727 728 osEventSubscribe(myTid, EVT_APP_START); 729 730 return true; 731 } 732 733 static void end_app(void) 734 { 735 disableInterrupt(mTask.pin, &mTask.isr); 736 extiUnchainIsr(PROX_IRQ, &mTask.isr); 737 extiClearPendingGpio(mTask.pin); 738 gpioRelease(mTask.pin); 739 740 sensorUnregister(mTask.alsHandle); 741 sensorUnregister(mTask.proxHandle); 742 743 i2cMasterRelease(I2C_BUS_ID); 744 } 745 746 static void handle_event(uint32_t evtType, const void* evtData) 747 { 748 struct I2cTransfer *xfer; 749 750 switch (evtType) { 751 case EVT_APP_START: 752 i2cMasterRequest(I2C_BUS_ID, I2C_SPEED); 753 754 /* Reset chip */ 755 writeRegister(ROHM_RPR0521_REG_SYSTEM_CONTROL, SW_RESET_BIT, SENSOR_STATE_RESET); 756 break; 757 758 case EVT_SENSOR_I2C: 759 handle_i2c_event((struct I2cTransfer*)evtData); 760 break; 761 762 case EVT_SENSOR_ALS_TIMER: 763 xfer = allocXfer(SENSOR_STATE_ALS_SAMPLING); 764 if (xfer != NULL) { 765 xfer->txrxBuf[0] = ROHM_RPR0521_REG_ALS_DATA0_LSB; 766 i2cMasterTxRx(I2C_BUS_ID, I2C_ADDR, xfer->txrxBuf, 1, xfer->txrxBuf, 4, i2cCallback, xfer); 767 } 768 break; 769 770 case EVT_SENSOR_PROX_INTERRUPT: 771 // Over-read to read the INTERRUPT register to clear the interrupt 772 xfer = allocXfer(SENSOR_STATE_PROX_SAMPLING); 773 if (xfer != NULL) { 774 xfer->txrxBuf[0] = ROHM_RPR0521_REG_PS_DATA_LSB; 775 i2cMasterTxRx(I2C_BUS_ID, I2C_ADDR, xfer->txrxBuf, 1, xfer->txrxBuf, 7, i2cCallback, xfer); 776 } 777 break; 778 779 } 780 } 781 782 INTERNAL_APP_INIT(APP_ID_MAKE(APP_ID_VENDOR_GOOGLE, 10), RPR0521_APP_VERSION, init_app, end_app, handle_event); 783