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  */
proxIsr(struct ChainedIsr * localIsr)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 
enableInterrupt(struct Gpio * pin,struct ChainedIsr * isr)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 
disableInterrupt(struct Gpio * pin,struct ChainedIsr * isr)292 static bool disableInterrupt(struct Gpio *pin, struct ChainedIsr *isr)
293 {
294     extiUnchainIsr(PROX_IRQ, isr);
295     extiDisableIntGpio(pin);
296     return true;
297 }
298 
i2cCallback(void * cookie,size_t tx,size_t rx,int err)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 
alsTimerCallback(uint32_t timerId,void * cookie)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.
allocXfer(uint8_t state)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     ERROR_PRINT("Ran out of i2c buffers!\n");
332     return NULL;
333 }
334 
releaseXfer(struct I2cTransfer * xfer)335 static inline void releaseXfer(struct I2cTransfer *xfer)
336 {
337     xfer->inUse = false;
338 }
339 
i2cWrite(struct I2cTransfer * xfer,size_t txSize)340 static bool i2cWrite(struct I2cTransfer *xfer, size_t txSize)
341 {
342     int ret = i2cMasterTx(I2C_BUS_ID, I2C_ADDR, xfer->txrxBuf, txSize, i2cCallback, xfer);
343     if (ret < 0) {
344         ERROR_PRINT("%s: i2cMasterTx failed (%d)\n", __func__, ret);
345         releaseXfer(xfer);
346     }
347 
348     return (ret == 0);
349 }
350 
351 // Helper function to write a one byte register. Returns true if we got a
352 // successful return value from i2cMasterTx().
writeRegister(uint8_t reg,uint8_t value,uint8_t state)353 static bool writeRegister(uint8_t reg, uint8_t value, uint8_t state)
354 {
355     struct I2cTransfer *xfer = allocXfer(state);
356 
357     if (xfer != NULL) {
358         xfer->txrxBuf[0] = reg;
359         xfer->txrxBuf[1] = value;
360         return i2cWrite(xfer, 2);
361     }
362 
363     return false;
364 }
365 
readRegister(uint8_t reg,uint8_t len,uint8_t state)366 static bool readRegister(uint8_t reg, uint8_t len, uint8_t state)
367 {
368     struct I2cTransfer *xfer = allocXfer(state);
369     int ret = -1;
370 
371     if (xfer != NULL) {
372         xfer->txrxBuf[0] = reg;
373         ret = i2cMasterTxRx(I2C_BUS_ID, I2C_ADDR,
374                   xfer->txrxBuf, 1, xfer->txrxBuf, len, i2cCallback, xfer);
375         if (ret < 0) {
376             ERROR_PRINT("%s: i2cMasterTxRx failed (%d)\n", __func__, ret);
377             releaseXfer(xfer);
378         }
379     }
380 
381     return (ret == 0);
382 }
383 
getLuxFromAlsData(uint16_t als0,uint16_t als1)384 static inline float getLuxFromAlsData(uint16_t als0, uint16_t als1)
385 {
386     static const float invGain[] = {1.0f, 0.5f, 1.0f / 64.0f, 1.0f / 128.0f};
387     float d0 = (float)als0 * invGain[ROHM_RPR0521_GAIN_ALS0];
388     float d1 = (float)als1 * invGain[ROHM_RPR0521_GAIN_ALS1];
389     float ratio = d1 / d0;
390     float c1;
391     float c2;
392 
393     if (ratio < 1.221f) {
394         c1 = 6.323f;
395         c2 = -3.917f;
396     } else if (ratio < 1.432f) {
397         c1 = 5.350f;
398         c2 = -3.121f;
399     } else if (ratio < 1.710f) {
400         c1 = 2.449f;
401         c2 = -1.096f;
402     } else if (ratio < 3.393f) {
403         c1 = 1.155f;
404         c2 = -0.340f;
405     } else {
406         c1 = c2 = 0.0f;
407     }
408 
409     return c1 * d0 + c2 * d1;
410 }
411 
setMode(bool alsOn,bool proxOn,uint8_t state)412 static void setMode(bool alsOn, bool proxOn, uint8_t state)
413 {
414     uint8_t ctrl;
415 
416     static const uint8_t measurementTime[] = {
417         MEASUREMENT_TIME_ALS_STANDBY_PS_STANDBY, /* als disabled, prox disabled */
418         MEASUREMENT_TIME_ALS_100_PS_100,         /* als enabled, prox disabled */
419         MEASUREMENT_TIME_ALS_STANDBY_PS_100,     /* als disabled, prox enabled  */
420         MEASUREMENT_TIME_ALS_100_PS_100,         /* als enabled, prox enabled */
421     };
422 
423     ctrl = measurementTime[alsOn ? 1 : 0 + proxOn ? 2 : 0] | (alsOn ? ALS_EN_BIT : 0) | (proxOn ? PS_EN_BIT : 0);
424     writeRegister(ROHM_RPR0521_REG_MODE_CONTROL, ctrl, state);
425 }
426 
sensorPowerAls(bool on,void * cookie)427 static bool sensorPowerAls(bool on, void *cookie)
428 {
429     VERBOSE_PRINT("sensorPowerAls: %d\n", on);
430 
431     if (on && !mTask.alsTimerHandle) {
432         mTask.alsTimerHandle = timTimerSet(ROHM_RPR0521_ALS_TIMER_DELAY, 0, 50, alsTimerCallback, NULL, false);
433     } else if (!on && mTask.alsTimerHandle) {
434         timTimerCancel(mTask.alsTimerHandle);
435         mTask.alsTimerHandle = 0;
436     }
437 
438     mTask.lastAlsSample.idata = ROHM_RPR0521_ALS_INVALID;
439     mTask.alsOn = on;
440 
441     setMode(on, mTask.proxOn, (on ? SENSOR_STATE_ENABLING_ALS : SENSOR_STATE_DISABLING_ALS));
442     return true;
443 }
444 
sensorFirmwareAls(void * cookie)445 static bool sensorFirmwareAls(void *cookie)
446 {
447     return sensorSignalInternalEvt(mTask.alsHandle, SENSOR_INTERNAL_EVT_FW_STATE_CHG, 1, 0);
448 }
449 
sensorRateAls(uint32_t rate,uint64_t latency,void * cookie)450 static bool sensorRateAls(uint32_t rate, uint64_t latency, void *cookie)
451 {
452     if (rate == SENSOR_RATE_ONCHANGE)
453         rate = ROHM_RPR0521_DEFAULT_RATE;
454 
455     VERBOSE_PRINT("sensorRateAls: rate=%ld Hz latency=%lld ns\n", rate/1024, latency);
456 
457     return sensorSignalInternalEvt(mTask.alsHandle, SENSOR_INTERNAL_EVT_RATE_CHG, rate, latency);
458 }
459 
sensorFlushAls(void * cookie)460 static bool sensorFlushAls(void *cookie)
461 {
462     return osEnqueueEvt(sensorGetMyEventType(SENS_TYPE_ALS), SENSOR_DATA_EVENT_FLUSH, NULL);
463 }
464 
sendLastSampleAls(void * cookie,uint32_t tid)465 static bool sendLastSampleAls(void *cookie, uint32_t tid) {
466     bool result = true;
467 
468     // If we don't end up doing anything here, the expectation is that we are powering up/haven't got the
469     // first sample yet, so the client will get a broadcast event soon
470     if (mTask.lastAlsSample.idata != ROHM_RPR0521_ALS_INVALID) {
471         result = osEnqueuePrivateEvt(sensorGetMyEventType(SENS_TYPE_ALS), mTask.lastAlsSample.vptr, NULL, tid);
472     }
473     return result;
474 }
475 
sensorPowerProx(bool on,void * cookie)476 static bool sensorPowerProx(bool on, void *cookie)
477 {
478     VERBOSE_PRINT("sensorPowerProx: %d\n", on);
479 
480     if (on) {
481         extiClearPendingGpio(mTask.pin);
482         enableInterrupt(mTask.pin, &mTask.isr);
483     } else {
484         disableInterrupt(mTask.pin, &mTask.isr);
485         extiClearPendingGpio(mTask.pin);
486     }
487 
488     mTask.proxState = PROX_STATE_INIT;
489     mTask.proxOn = on;
490 
491     setMode(mTask.alsOn, on, (on ? SENSOR_STATE_ENABLING_PROX : SENSOR_STATE_DISABLING_PROX));
492     return true;
493 }
494 
sensorFirmwareProx(void * cookie)495 static bool sensorFirmwareProx(void *cookie)
496 {
497     return sensorSignalInternalEvt(mTask.proxHandle, SENSOR_INTERNAL_EVT_FW_STATE_CHG, 1, 0);
498 }
499 
sensorRateProx(uint32_t rate,uint64_t latency,void * cookie)500 static bool sensorRateProx(uint32_t rate, uint64_t latency, void *cookie)
501 {
502     if (rate == SENSOR_RATE_ONCHANGE)
503         rate = ROHM_RPR0521_DEFAULT_RATE;
504 
505     VERBOSE_PRINT("sensorRateProx: rate=%ld Hz latency=%lld ns\n", rate/1024, latency);
506 
507     return sensorSignalInternalEvt(mTask.proxHandle, SENSOR_INTERNAL_EVT_RATE_CHG, rate, latency);
508 }
509 
sensorFlushProx(void * cookie)510 static bool sensorFlushProx(void *cookie)
511 {
512     return osEnqueueEvt(sensorGetMyEventType(SENS_TYPE_PROX), SENSOR_DATA_EVENT_FLUSH, NULL);
513 }
514 
sensorCfgDataProx(void * data,void * cookie)515 static bool sensorCfgDataProx(void *data, void *cookie)
516 {
517     struct I2cTransfer *xfer;
518 
519     int32_t offset = *(int32_t*)data;
520 
521     INFO_PRINT("Received cfg data: %d\n", (int)offset);
522 
523     xfer = allocXfer(SENSOR_STATE_IDLE);
524     if (xfer != NULL) {
525         xfer->txrxBuf[0] = ROHM_RPR0521_REG_PS_OFFSET_LSB;
526         xfer->txrxBuf[1] = offset & 0xFF;
527         xfer->txrxBuf[2] = (offset >> 8) & 0x3;
528         return i2cWrite(xfer, 3);
529     }
530 
531     return false;
532 }
533 
sendLastSampleProx(void * cookie,uint32_t tid)534 static bool sendLastSampleProx(void *cookie, uint32_t tid) {
535     union EmbeddedDataPoint sample;
536     bool result = true;
537 
538     // See note in sendLastSampleAls
539     if (mTask.proxState != PROX_STATE_INIT) {
540         sample.fdata = (mTask.proxState == PROX_STATE_NEAR) ? ROHM_RPR0521_REPORT_NEAR_VALUE : ROHM_RPR0521_REPORT_FAR_VALUE;
541         result = osEnqueuePrivateEvt(sensorGetMyEventType(SENS_TYPE_PROX), sample.vptr, NULL, tid);
542     }
543     return result;
544 }
545 
546 static const struct SensorInfo sensorInfoAls =
547 {
548     .sensorName = "ALS",
549     .supportedRates = supportedRates,
550     .sensorType = SENS_TYPE_ALS,
551     .numAxis = NUM_AXIS_EMBEDDED,
552     .interrupt = NANOHUB_INT_NONWAKEUP,
553     .minSamples = 20
554 };
555 
556 static const struct SensorOps sensorOpsAls =
557 {
558     .sensorPower = sensorPowerAls,
559     .sensorFirmwareUpload = sensorFirmwareAls,
560     .sensorSetRate = sensorRateAls,
561     .sensorFlush = sensorFlushAls,
562     .sensorTriggerOndemand = NULL,
563     .sensorCalibrate = NULL,
564     .sensorSendOneDirectEvt = sendLastSampleAls
565 };
566 
567 static const struct SensorInfo sensorInfoProx =
568 {
569     .sensorName = "Proximity",
570     .supportedRates = supportedRates,
571     .sensorType = SENS_TYPE_PROX,
572     .numAxis = NUM_AXIS_EMBEDDED,
573     .interrupt = NANOHUB_INT_WAKEUP,
574     .minSamples = 300
575 };
576 
577 static const struct SensorOps sensorOpsProx =
578 {
579     .sensorPower = sensorPowerProx,
580     .sensorFirmwareUpload = sensorFirmwareProx,
581     .sensorSetRate = sensorRateProx,
582     .sensorFlush = sensorFlushProx,
583     .sensorTriggerOndemand = NULL,
584     .sensorCalibrate = NULL,
585     .sensorCfgData = sensorCfgDataProx,
586     .sensorSendOneDirectEvt = sendLastSampleProx
587 };
588 
589 /*
590  * Sensor i2c state machine
591  */
592 
sensorAlsFree(void * ptr)593 static void __attribute__((unused)) sensorAlsFree(void *ptr)
594 {
595 }
596 
sensorProxFree(void * ptr)597 static void __attribute__((unused)) sensorProxFree(void *ptr)
598 {
599 }
600 
handle_i2c_event(struct I2cTransfer * xfer)601 static void handle_i2c_event(struct I2cTransfer *xfer)
602 {
603     union EmbeddedDataPoint sample;
604     uint16_t als0, als1, ps;
605     uint8_t lastProxState;
606     struct I2cTransfer *newXfer;
607     uint8_t regData;
608 
609     switch (xfer->state) {
610     case SENSOR_STATE_RESET:
611         readRegister(ROHM_RPR0521_REG_ID, 1, SENSOR_STATE_VERIFY_ID);
612         break;
613 
614     case SENSOR_STATE_VERIFY_ID:
615         /* Check the sensor ID */
616         if (xfer->err != 0 || xfer->txrxBuf[0] != ROHM_RPR0521_ID) {
617             INFO_PRINT("not detected\n");
618             sensorUnregister(mTask.alsHandle);
619             sensorUnregister(mTask.proxHandle);
620             break;
621         }
622 
623         newXfer = allocXfer(SENSOR_STATE_INIT_GAINS);
624         if (newXfer != NULL) {
625             newXfer->txrxBuf[0] = ROHM_RPR0521_REG_ALS_PS_CONTROL;
626             newXfer->txrxBuf[1] = (ROHM_RPR0521_GAIN_ALS0 << 4) | (ROHM_RPR0521_GAIN_ALS1 << 2) | ROHM_RPR0521_LED_CURRENT;
627             newXfer->txrxBuf[2] = (ROHM_RPR0521_GAIN_PS << 4) | PS_PERSISTENCE_ACTIVE_AT_EACH_MEASUREMENT_END;
628             i2cWrite(newXfer, 3);
629         }
630         break;
631 
632     case SENSOR_STATE_INIT_GAINS:
633         /* Offset register */
634         newXfer = allocXfer(SENSOR_STATE_INIT_OFFSETS);
635         if (newXfer != NULL) {
636             newXfer->txrxBuf[0] = ROHM_RPR0521_REG_PS_OFFSET_LSB;
637             newXfer->txrxBuf[1] = 0;
638             newXfer->txrxBuf[2] = 0;
639             i2cWrite(newXfer, 3);
640         }
641         break;
642 
643     case SENSOR_STATE_INIT_OFFSETS:
644         /* PS Threshold register */
645         newXfer = allocXfer(SENSOR_STATE_INIT_THRESHOLDS);
646         if (newXfer != NULL) {
647             newXfer->txrxBuf[0] = ROHM_RPR0521_REG_PS_TH_LSB;
648             newXfer->txrxBuf[1] = (ROHM_RPR0521_THRESHOLD_ASSERT_NEAR & 0xFF);
649             newXfer->txrxBuf[2] = (ROHM_RPR0521_THRESHOLD_ASSERT_NEAR & 0xFF00) >> 8;
650             newXfer->txrxBuf[3] = (ROHM_RPR0521_THRESHOLD_DEASSERT_NEAR & 0xFF);
651             newXfer->txrxBuf[4] = (ROHM_RPR0521_THRESHOLD_DEASSERT_NEAR & 0xFF00) >> 8;
652             i2cWrite(newXfer, 5);
653         }
654         break;
655 
656     case SENSOR_STATE_INIT_THRESHOLDS:
657         /* Interrupt register */
658         regData = (INTERRUPT_MODE_PS_HYSTERESIS << 4) | INTERRUPT_LATCH_BIT | INTERRUPT_TRIGGER_PS;
659         writeRegister(ROHM_RPR0521_REG_INTERRUPT, regData, SENSOR_STATE_FINISH_INIT);
660         break;
661 
662     case SENSOR_STATE_FINISH_INIT:
663         sensorRegisterInitComplete(mTask.alsHandle);
664         sensorRegisterInitComplete(mTask.proxHandle);
665         break;
666 
667     case SENSOR_STATE_ENABLING_ALS:
668         sensorSignalInternalEvt(mTask.alsHandle, SENSOR_INTERNAL_EVT_POWER_STATE_CHG, true, 0);
669         break;
670 
671     case SENSOR_STATE_ENABLING_PROX:
672         sensorSignalInternalEvt(mTask.proxHandle, SENSOR_INTERNAL_EVT_POWER_STATE_CHG, true, 0);
673         break;
674 
675     case SENSOR_STATE_DISABLING_ALS:
676         sensorSignalInternalEvt(mTask.alsHandle, SENSOR_INTERNAL_EVT_POWER_STATE_CHG, false, 0);
677         break;
678 
679     case SENSOR_STATE_DISABLING_PROX:
680         // Clear persistence setting
681         regData = (ROHM_RPR0521_GAIN_PS << 4) | PS_PERSISTENCE_ACTIVE_AT_EACH_MEASUREMENT_END;
682         writeRegister(ROHM_RPR0521_REG_PS_CONTROL, regData, SENSOR_STATE_DISABLING_PROX_2);
683         break;
684 
685     case SENSOR_STATE_DISABLING_PROX_2:
686         // Reset interrupt
687         writeRegister(ROHM_RPR0521_REG_SYSTEM_CONTROL, INT_RESET_BIT, SENSOR_STATE_DISABLING_PROX_3);
688         break;
689 
690     case SENSOR_STATE_DISABLING_PROX_3:
691         sensorSignalInternalEvt(mTask.proxHandle, SENSOR_INTERNAL_EVT_POWER_STATE_CHG, false, 0);
692         break;
693 
694     case SENSOR_STATE_ALS_SAMPLING:
695         als0 = *(uint16_t*)(xfer->txrxBuf);
696         als1 = *(uint16_t*)(xfer->txrxBuf+2);
697 
698         DEBUG_PRINT("als sample ready: als0=%u als1=%u\n", als0, als1);
699 
700         if (mTask.alsOn) {
701             sample.fdata = getLuxFromAlsData(als0, als1);
702             if (mTask.lastAlsSample.idata != sample.idata) {
703                 osEnqueueEvt(sensorGetMyEventType(SENS_TYPE_ALS), sample.vptr, NULL);
704                 mTask.lastAlsSample.fdata = sample.fdata;
705             }
706         }
707 
708         break;
709 
710     case SENSOR_STATE_PROX_SAMPLING:
711         ps = *(uint16_t*)(xfer->txrxBuf);
712         lastProxState = mTask.proxState;
713 
714         DEBUG_PRINT("prox sample ready: prox=%u\n", ps);
715 
716         if (mTask.proxOn) {
717             if (ps > ROHM_RPR0521_THRESHOLD_ASSERT_NEAR) {
718                 sample.fdata = ROHM_RPR0521_REPORT_NEAR_VALUE;
719                 mTask.proxState = PROX_STATE_NEAR;
720             } else {
721                 sample.fdata = ROHM_RPR0521_REPORT_FAR_VALUE;
722                 mTask.proxState = PROX_STATE_FAR;
723             }
724 
725             if (mTask.proxState != lastProxState)
726                 osEnqueueEvt(sensorGetMyEventType(SENS_TYPE_PROX), sample.vptr, NULL);
727 
728             // After the first prox sample, change the persistance setting to assert
729             // interrupt on-change, rather than after every sample
730             regData = (ROHM_RPR0521_GAIN_PS << 4) | PS_PERSISTENCE_STATUS_UPDATED_AT_EACH_MEASUREMENT_END;
731             writeRegister(ROHM_RPR0521_REG_PS_CONTROL, regData, SENSOR_STATE_IDLE);
732         }
733 
734         break;
735 
736     default:
737         break;
738     }
739 
740     releaseXfer(xfer);
741 }
742 
743 /*
744  * Main driver entry points
745  */
746 
init_app(uint32_t myTid)747 static bool init_app(uint32_t myTid)
748 {
749     /* Set up driver private data */
750     mTask.tid = myTid;
751     mTask.alsOn = false;
752     mTask.proxOn = false;
753     mTask.lastAlsSample.idata = ROHM_RPR0521_ALS_INVALID;
754     mTask.proxState = PROX_STATE_INIT;
755 
756     mTask.pin = gpioRequest(PROX_INT_PIN);
757     gpioConfigInput(mTask.pin, GPIO_SPEED_LOW, GPIO_PULL_NONE);
758     syscfgSetExtiPort(mTask.pin);
759     mTask.isr.func = proxIsr;
760 
761     /* Register sensors */
762     mTask.alsHandle = sensorRegister(&sensorInfoAls, &sensorOpsAls, NULL, false);
763     mTask.proxHandle = sensorRegister(&sensorInfoProx, &sensorOpsProx, NULL, false);
764 
765     osEventSubscribe(myTid, EVT_APP_START);
766 
767     return true;
768 }
769 
end_app(void)770 static void end_app(void)
771 {
772     disableInterrupt(mTask.pin, &mTask.isr);
773     extiUnchainIsr(PROX_IRQ, &mTask.isr);
774     extiClearPendingGpio(mTask.pin);
775     gpioRelease(mTask.pin);
776 
777     sensorUnregister(mTask.alsHandle);
778     sensorUnregister(mTask.proxHandle);
779 
780     i2cMasterRelease(I2C_BUS_ID);
781 }
782 
handle_event(uint32_t evtType,const void * evtData)783 static void handle_event(uint32_t evtType, const void* evtData)
784 {
785     switch (evtType) {
786     case EVT_APP_START:
787         i2cMasterRequest(I2C_BUS_ID, I2C_SPEED);
788 
789         /* Reset chip */
790         writeRegister(ROHM_RPR0521_REG_SYSTEM_CONTROL, SW_RESET_BIT, SENSOR_STATE_RESET);
791         break;
792 
793     case EVT_SENSOR_I2C:
794         handle_i2c_event((struct I2cTransfer*)evtData);
795         break;
796 
797     case EVT_SENSOR_ALS_TIMER:
798         readRegister(ROHM_RPR0521_REG_ALS_DATA0_LSB, 4, SENSOR_STATE_ALS_SAMPLING);
799         break;
800 
801     case EVT_SENSOR_PROX_INTERRUPT:
802         // Over-read to read the INTERRUPT register to clear the interrupt
803         readRegister(ROHM_RPR0521_REG_PS_DATA_LSB, 7, SENSOR_STATE_PROX_SAMPLING);
804         break;
805     }
806 }
807 
808 INTERNAL_APP_INIT(APP_ID_MAKE(NANOHUB_VENDOR_GOOGLE, 10), RPR0521_APP_VERSION, init_app, end_app, handle_event);
809