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