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/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