Home | History | Annotate | Download | only in rohm_rpr0521
      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