• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 2
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 INFO_PRINT(fmt, ...) do { \
136         osLog(LOG_INFO, "[Rohm RPR-0521] " fmt, ##__VA_ARGS__); \
137     } while (0);
138 
139 #define DEBUG_PRINT(fmt, ...) do { \
140         if (enable_debug) {  \
141             osLog(LOG_INFO, "[Rohm RPR-0521] " fmt, ##__VA_ARGS__); \
142         } \
143     } while (0);
144 
145 static const bool enable_debug = 0;
146 
147 /* Private driver events */
148 enum SensorEvents
149 {
150     EVT_SENSOR_I2C = EVT_APP_START + 1,
151     EVT_SENSOR_ALS_TIMER,
152     EVT_SENSOR_PROX_INTERRUPT,
153 };
154 
155 /* I2C state machine */
156 enum SensorState
157 {
158     SENSOR_STATE_RESET,
159     SENSOR_STATE_VERIFY_ID,
160     SENSOR_STATE_INIT_GAINS,
161     SENSOR_STATE_INIT_THRESHOLDS,
162     SENSOR_STATE_INIT_OFFSETS,
163     SENSOR_STATE_FINISH_INIT,
164     SENSOR_STATE_ENABLING_ALS,
165     SENSOR_STATE_ENABLING_PROX,
166     SENSOR_STATE_DISABLING_ALS,
167     SENSOR_STATE_DISABLING_PROX,
168     SENSOR_STATE_DISABLING_PROX_2,
169     SENSOR_STATE_DISABLING_PROX_3,
170     SENSOR_STATE_ALS_SAMPLING,
171     SENSOR_STATE_PROX_SAMPLING,
172     SENSOR_STATE_IDLE,
173 };
174 
175 enum ProxState
176 {
177     PROX_STATE_INIT,
178     PROX_STATE_NEAR,
179     PROX_STATE_FAR,
180 };
181 
182 enum MeasurementTime {
183     MEASUREMENT_TIME_ALS_STANDBY_PS_STANDBY     = 0,
184     MEASUREMENT_TIME_ALS_STANDBY_PS_10          = 1,
185     MEASUREMENT_TIME_ALS_STANDBY_PS_40          = 2,
186     MEASUREMENT_TIME_ALS_STANDBY_PS_100         = 3,
187     MEASUREMENT_TIME_ALS_STANDBY_PS_400         = 4,
188     MEASUREMENT_TIME_ALS_100_PS_50              = 5,
189     MEASUREMENT_TIME_ALS_100_PS_100             = 6,
190     MEASUREMENT_TIME_ALS_100_PS_400             = 7,
191     MEASUREMENT_TIME_ALS_400_PS_50              = 8,
192     MEASUREMENT_TIME_ALS_400_PS_100             = 9,
193     MEASUREMENT_TIME_ALS_400_PS_STANDBY         = 10,
194     MEASUREMENT_TIME_ALS_400_PS_400             = 11,
195     MEASUREMENT_TIME_ALS_50_PS_50               = 12,
196 };
197 
198 struct SensorData
199 {
200     struct Gpio *pin;
201     struct ChainedIsr isr;
202 
203     uint8_t txrxBuf[16];
204 
205     uint32_t tid;
206 
207     uint32_t alsHandle;
208     uint32_t proxHandle;
209     uint32_t alsTimerHandle;
210 
211     union EmbeddedDataPoint lastAlsSample;
212 
213     uint8_t proxState; // enum ProxState
214 
215     bool alsOn;
216     bool proxOn;
217 };
218 
219 static struct SensorData mTask;
220 
221 static const uint32_t supportedRates[] =
222 {
223     SENSOR_HZ(5),
224     SENSOR_RATE_ONCHANGE,
225     0,
226 };
227 
228 /*
229  * Helper functions
230  */
proxIsr(struct ChainedIsr * localIsr)231 static bool proxIsr(struct ChainedIsr *localIsr)
232 {
233     struct SensorData *data = container_of(localIsr, struct SensorData, isr);
234     bool firstProxSample = (data->proxState == PROX_STATE_INIT);
235     uint8_t lastProxState = data->proxState;
236     bool pinState;
237     union EmbeddedDataPoint sample;
238 
239     if (!extiIsPendingGpio(data->pin)) {
240         return false;
241     }
242 
243     if (data->proxOn) {
244         pinState = gpioGet(data->pin);
245 
246         if (firstProxSample && !pinState) {
247             osEnqueuePrivateEvt(EVT_SENSOR_PROX_INTERRUPT, NULL, NULL, mTask.tid);
248         } else if (!firstProxSample) {
249             sample.fdata = (pinState) ? ROHM_RPR0521_REPORT_FAR_VALUE : ROHM_RPR0521_REPORT_NEAR_VALUE;
250             data->proxState = (pinState) ? PROX_STATE_FAR : PROX_STATE_NEAR;
251             if (data->proxState != lastProxState)
252                 osEnqueueEvt(sensorGetMyEventType(SENS_TYPE_PROX), sample.vptr, NULL);
253         }
254     }
255 
256     extiClearPendingGpio(data->pin);
257     return true;
258 }
259 
enableInterrupt(struct Gpio * pin,struct ChainedIsr * isr)260 static bool enableInterrupt(struct Gpio *pin, struct ChainedIsr *isr)
261 {
262     extiEnableIntGpio(pin, EXTI_TRIGGER_BOTH);
263     extiChainIsr(PROX_IRQ, isr);
264     return true;
265 }
266 
disableInterrupt(struct Gpio * pin,struct ChainedIsr * isr)267 static bool disableInterrupt(struct Gpio *pin, struct ChainedIsr *isr)
268 {
269     extiUnchainIsr(PROX_IRQ, isr);
270     extiDisableIntGpio(pin);
271     return true;
272 }
273 
i2cCallback(void * cookie,size_t tx,size_t rx,int err)274 static void i2cCallback(void *cookie, size_t tx, size_t rx, int err)
275 {
276     if (err == 0)
277         osEnqueuePrivateEvt(EVT_SENSOR_I2C, cookie, NULL, mTask.tid);
278     else
279         INFO_PRINT("i2c error (%d)\n", err);
280 }
281 
alsTimerCallback(uint32_t timerId,void * cookie)282 static void alsTimerCallback(uint32_t timerId, void *cookie)
283 {
284     osEnqueuePrivateEvt(EVT_SENSOR_ALS_TIMER, cookie, NULL, mTask.tid);
285 }
286 
getLuxFromAlsData(uint16_t als0,uint16_t als1)287 static inline float getLuxFromAlsData(uint16_t als0, uint16_t als1)
288 {
289     static const float invGain[] = {1.0f, 0.5f, 1.0f / 64.0f, 1.0f / 128.0f};
290     float d0 = (float)als0 * invGain[ROHM_RPR0521_GAIN_ALS0];
291     float d1 = (float)als1 * invGain[ROHM_RPR0521_GAIN_ALS1];
292     float ratio = d1 / d0;
293     float c1;
294     float c2;
295 
296     if (ratio < 1.221f) {
297         c1 = 6.323f;
298         c2 = -3.917f;
299     } else if (ratio < 1.432f) {
300         c1 = 5.350f;
301         c2 = -3.121f;
302     } else if (ratio < 1.710f) {
303         c1 = 2.449f;
304         c2 = -1.096f;
305     } else if (ratio < 3.393f) {
306         c1 = 1.155f;
307         c2 = -0.340f;
308     } else {
309         c1 = c2 = 0.0f;
310     }
311 
312     return c1 * d0 + c2 * d1;
313 }
314 
setMode(bool alsOn,bool proxOn,void * cookie)315 static void setMode(bool alsOn, bool proxOn, void *cookie)
316 {
317     static const uint8_t measurementTime[] = {
318         MEASUREMENT_TIME_ALS_STANDBY_PS_STANDBY, /* als disabled, prox disabled */
319         MEASUREMENT_TIME_ALS_100_PS_100,         /* als enabled, prox disabled */
320         MEASUREMENT_TIME_ALS_STANDBY_PS_100,     /* als disabled, prox enabled  */
321         MEASUREMENT_TIME_ALS_100_PS_100,         /* als enabled, prox enabled */
322     };
323 
324     mTask.txrxBuf[0] = ROHM_RPR0521_REG_MODE_CONTROL;
325     mTask.txrxBuf[1] = measurementTime[alsOn ? 1 : 0 + proxOn ? 2 : 0] | (alsOn ? ALS_EN_BIT : 0) | (proxOn ? PS_EN_BIT : 0);
326     i2cMasterTx(I2C_BUS_ID, I2C_ADDR, mTask.txrxBuf, 2, &i2cCallback, cookie);
327 }
328 
sensorPowerAls(bool on,void * cookie)329 static bool sensorPowerAls(bool on, void *cookie)
330 {
331     DEBUG_PRINT("sensorPowerAls: %d\n", on);
332 
333     if (on && !mTask.alsTimerHandle) {
334         mTask.alsTimerHandle = timTimerSet(ROHM_RPR0521_ALS_TIMER_DELAY, 0, 50, alsTimerCallback, NULL, false);
335     } else if (!on && mTask.alsTimerHandle) {
336         timTimerCancel(mTask.alsTimerHandle);
337         mTask.alsTimerHandle = 0;
338     }
339 
340     mTask.lastAlsSample.idata = ROHM_RPR0521_ALS_INVALID;
341     mTask.alsOn = on;
342 
343     setMode(on, mTask.proxOn, (void *)(on ? SENSOR_STATE_ENABLING_ALS : SENSOR_STATE_DISABLING_ALS));
344     return true;
345 }
346 
sensorFirmwareAls(void * cookie)347 static bool sensorFirmwareAls(void *cookie)
348 {
349     return sensorSignalInternalEvt(mTask.alsHandle, SENSOR_INTERNAL_EVT_FW_STATE_CHG, 1, 0);
350 }
351 
sensorRateAls(uint32_t rate,uint64_t latency,void * cookie)352 static bool sensorRateAls(uint32_t rate, uint64_t latency, void *cookie)
353 {
354     if (rate == SENSOR_RATE_ONCHANGE)
355         rate = ROHM_RPR0521_DEFAULT_RATE;
356 
357     DEBUG_PRINT("sensorRateAls: rate=%ld Hz latency=%lld ns\n", rate/1024, latency);
358 
359     return sensorSignalInternalEvt(mTask.alsHandle, SENSOR_INTERNAL_EVT_RATE_CHG, rate, latency);
360 }
361 
sensorFlushAls(void * cookie)362 static bool sensorFlushAls(void *cookie)
363 {
364     return osEnqueueEvt(sensorGetMyEventType(SENS_TYPE_ALS), SENSOR_DATA_EVENT_FLUSH, NULL);
365 }
366 
sendLastSampleAls(void * cookie,uint32_t tid)367 static bool sendLastSampleAls(void *cookie, uint32_t tid) {
368     bool result = true;
369 
370     // If we don't end up doing anything here, the expectation is that we are powering up/haven't got the
371     // first sample yet, so the client will get a broadcast event soon
372     if (mTask.lastAlsSample.idata != ROHM_RPR0521_ALS_INVALID) {
373         result = osEnqueuePrivateEvt(sensorGetMyEventType(SENS_TYPE_ALS), mTask.lastAlsSample.vptr, NULL, tid);
374     }
375     return result;
376 }
377 
sensorPowerProx(bool on,void * cookie)378 static bool sensorPowerProx(bool on, void *cookie)
379 {
380     DEBUG_PRINT("sensorPowerProx: %d\n", on);
381 
382     if (on) {
383         extiClearPendingGpio(mTask.pin);
384         enableInterrupt(mTask.pin, &mTask.isr);
385     } else {
386         disableInterrupt(mTask.pin, &mTask.isr);
387         extiClearPendingGpio(mTask.pin);
388     }
389 
390     mTask.proxState = PROX_STATE_INIT;
391     mTask.proxOn = on;
392 
393     setMode(mTask.alsOn, on, (void *)(on ? SENSOR_STATE_ENABLING_PROX : SENSOR_STATE_DISABLING_PROX));
394     return true;
395 }
396 
sensorFirmwareProx(void * cookie)397 static bool sensorFirmwareProx(void *cookie)
398 {
399     return sensorSignalInternalEvt(mTask.proxHandle, SENSOR_INTERNAL_EVT_FW_STATE_CHG, 1, 0);
400 }
401 
sensorRateProx(uint32_t rate,uint64_t latency,void * cookie)402 static bool sensorRateProx(uint32_t rate, uint64_t latency, void *cookie)
403 {
404     if (rate == SENSOR_RATE_ONCHANGE)
405         rate = ROHM_RPR0521_DEFAULT_RATE;
406 
407     DEBUG_PRINT("sensorRateProx: rate=%ld Hz latency=%lld ns\n", rate/1024, latency);
408 
409     return sensorSignalInternalEvt(mTask.proxHandle, SENSOR_INTERNAL_EVT_RATE_CHG, rate, latency);
410 }
411 
sensorFlushProx(void * cookie)412 static bool sensorFlushProx(void *cookie)
413 {
414     return osEnqueueEvt(sensorGetMyEventType(SENS_TYPE_PROX), SENSOR_DATA_EVENT_FLUSH, NULL);
415 }
416 
sensorCfgDataProx(void * data,void * cookie)417 static bool sensorCfgDataProx(void *data, void *cookie)
418 {
419     DEBUG_PRINT("sensorCfgDataProx");
420 
421     int32_t offset = *(int32_t*)data;
422 
423     INFO_PRINT("Received cfg data: %d\n", (int)offset);
424 
425     mTask.txrxBuf[0] = ROHM_RPR0521_REG_PS_OFFSET_LSB;
426     mTask.txrxBuf[1] = offset & 0xFF;
427     mTask.txrxBuf[2] = (offset >> 8) & 0x3;
428     i2cMasterTx(I2C_BUS_ID, I2C_ADDR, mTask.txrxBuf, 3, &i2cCallback, (void *)SENSOR_STATE_IDLE);
429     return true;
430 }
431 
sendLastSampleProx(void * cookie,uint32_t tid)432 static bool sendLastSampleProx(void *cookie, uint32_t tid) {
433     union EmbeddedDataPoint sample;
434     bool result = true;
435 
436     // See note in sendLastSampleAls
437     if (mTask.proxState != PROX_STATE_INIT) {
438         sample.fdata = (mTask.proxState == PROX_STATE_NEAR) ? ROHM_RPR0521_REPORT_NEAR_VALUE : ROHM_RPR0521_REPORT_FAR_VALUE;
439         result = osEnqueuePrivateEvt(sensorGetMyEventType(SENS_TYPE_PROX), sample.vptr, NULL, tid);
440     }
441     return result;
442 }
443 
444 static const struct SensorInfo sensorInfoAls =
445 {
446     .sensorName = "ALS",
447     .supportedRates = supportedRates,
448     .sensorType = SENS_TYPE_ALS,
449     .numAxis = NUM_AXIS_EMBEDDED,
450     .interrupt = NANOHUB_INT_NONWAKEUP,
451     .minSamples = 20
452 };
453 
454 static const struct SensorOps sensorOpsAls =
455 {
456     .sensorPower = sensorPowerAls,
457     .sensorFirmwareUpload = sensorFirmwareAls,
458     .sensorSetRate = sensorRateAls,
459     .sensorFlush = sensorFlushAls,
460     .sensorTriggerOndemand = NULL,
461     .sensorCalibrate = NULL,
462     .sensorSendOneDirectEvt = sendLastSampleAls
463 };
464 
465 static const struct SensorInfo sensorInfoProx =
466 {
467     .sensorName = "Proximity",
468     .supportedRates = supportedRates,
469     .sensorType = SENS_TYPE_PROX,
470     .numAxis = NUM_AXIS_EMBEDDED,
471     .interrupt = NANOHUB_INT_WAKEUP,
472     .minSamples = 300
473 };
474 
475 static const struct SensorOps sensorOpsProx =
476 {
477     .sensorPower = sensorPowerProx,
478     .sensorFirmwareUpload = sensorFirmwareProx,
479     .sensorSetRate = sensorRateProx,
480     .sensorFlush = sensorFlushProx,
481     .sensorTriggerOndemand = NULL,
482     .sensorCalibrate = NULL,
483     .sensorCfgData = sensorCfgDataProx,
484     .sensorSendOneDirectEvt = sendLastSampleProx
485 };
486 
487 /*
488  * Sensor i2c state machine
489  */
490 
sensorAlsFree(void * ptr)491 static void __attribute__((unused)) sensorAlsFree(void *ptr)
492 {
493 }
494 
sensorProxFree(void * ptr)495 static void __attribute__((unused)) sensorProxFree(void *ptr)
496 {
497 }
498 
handle_i2c_event(int state)499 static void handle_i2c_event(int state)
500 {
501     union EmbeddedDataPoint sample;
502     uint16_t als0, als1, ps;
503     uint8_t lastProxState;
504 
505     switch (state) {
506     case SENSOR_STATE_RESET:
507         mTask.txrxBuf[0] = ROHM_RPR0521_REG_ID;
508         i2cMasterTxRx(I2C_BUS_ID, I2C_ADDR, mTask.txrxBuf, 1,
509                         mTask.txrxBuf, 1, &i2cCallback,
510                         (void *)SENSOR_STATE_VERIFY_ID);
511         break;
512 
513     case SENSOR_STATE_VERIFY_ID:
514         /* Check the sensor ID */
515         if (mTask.txrxBuf[0] != ROHM_RPR0521_ID) {
516             INFO_PRINT("not detected\n");
517             sensorUnregister(mTask.alsHandle);
518             sensorUnregister(mTask.proxHandle);
519             break;
520         }
521 
522         mTask.txrxBuf[0] = ROHM_RPR0521_REG_ALS_PS_CONTROL;
523         mTask.txrxBuf[1] = (ROHM_RPR0521_GAIN_ALS0 << 4) | (ROHM_RPR0521_GAIN_ALS1 << 2) | ROHM_RPR0521_LED_CURRENT;
524         mTask.txrxBuf[2] = (ROHM_RPR0521_GAIN_PS << 4) | PS_PERSISTENCE_ACTIVE_AT_EACH_MEASUREMENT_END;
525         i2cMasterTx(I2C_BUS_ID, I2C_ADDR, mTask.txrxBuf, 3, &i2cCallback, (void *)SENSOR_STATE_INIT_GAINS);
526         break;
527 
528     case SENSOR_STATE_INIT_GAINS:
529         /* Offset register */
530         mTask.txrxBuf[0] = ROHM_RPR0521_REG_PS_OFFSET_LSB;
531         mTask.txrxBuf[1] = 0;
532         mTask.txrxBuf[2] = 0;
533         i2cMasterTx(I2C_BUS_ID, I2C_ADDR, mTask.txrxBuf, 3, &i2cCallback, (void *)SENSOR_STATE_INIT_OFFSETS);
534         break;
535 
536     case SENSOR_STATE_INIT_OFFSETS:
537         /* PS Threshold register */
538         mTask.txrxBuf[0] = ROHM_RPR0521_REG_PS_TH_LSB;
539         mTask.txrxBuf[1] = (ROHM_RPR0521_THRESHOLD_ASSERT_NEAR & 0xFF);
540         mTask.txrxBuf[2] = (ROHM_RPR0521_THRESHOLD_ASSERT_NEAR & 0xFF00) >> 8;
541         mTask.txrxBuf[3] = (ROHM_RPR0521_THRESHOLD_DEASSERT_NEAR & 0xFF);
542         mTask.txrxBuf[4] = (ROHM_RPR0521_THRESHOLD_DEASSERT_NEAR & 0xFF00) >> 8;
543         i2cMasterTx(I2C_BUS_ID, I2C_ADDR, mTask.txrxBuf, 5, &i2cCallback, (void *)SENSOR_STATE_INIT_THRESHOLDS);
544         break;
545 
546     case SENSOR_STATE_INIT_THRESHOLDS:
547         /* Interrupt register */
548         mTask.txrxBuf[0] = ROHM_RPR0521_REG_INTERRUPT;
549         mTask.txrxBuf[1] = (INTERRUPT_MODE_PS_HYSTERESIS << 4) | INTERRUPT_LATCH_BIT | INTERRUPT_TRIGGER_PS;
550         i2cMasterTx(I2C_BUS_ID, I2C_ADDR, mTask.txrxBuf, 2, &i2cCallback, (void *)SENSOR_STATE_FINISH_INIT);
551         break;
552 
553     case SENSOR_STATE_FINISH_INIT:
554         sensorRegisterInitComplete(mTask.alsHandle);
555         sensorRegisterInitComplete(mTask.proxHandle);
556         break;
557 
558     case SENSOR_STATE_ENABLING_ALS:
559         sensorSignalInternalEvt(mTask.alsHandle, SENSOR_INTERNAL_EVT_POWER_STATE_CHG, true, 0);
560         break;
561 
562     case SENSOR_STATE_ENABLING_PROX:
563         sensorSignalInternalEvt(mTask.proxHandle, SENSOR_INTERNAL_EVT_POWER_STATE_CHG, true, 0);
564         break;
565 
566     case SENSOR_STATE_DISABLING_ALS:
567         sensorSignalInternalEvt(mTask.alsHandle, SENSOR_INTERNAL_EVT_POWER_STATE_CHG, false, 0);
568         break;
569 
570     case SENSOR_STATE_DISABLING_PROX:
571         // Clear persistence setting
572         mTask.txrxBuf[0] = ROHM_RPR0521_REG_PS_CONTROL;
573         mTask.txrxBuf[1] = (ROHM_RPR0521_GAIN_PS << 4) | PS_PERSISTENCE_ACTIVE_AT_EACH_MEASUREMENT_END;
574         i2cMasterTx(I2C_BUS_ID, I2C_ADDR, mTask.txrxBuf, 2, &i2cCallback, (void *)SENSOR_STATE_DISABLING_PROX_2);
575         break;
576 
577     case SENSOR_STATE_DISABLING_PROX_2:
578         // Reset interrupt
579         mTask.txrxBuf[0] = ROHM_RPR0521_REG_SYSTEM_CONTROL;
580         mTask.txrxBuf[1] = INT_RESET_BIT;
581         i2cMasterTx(I2C_BUS_ID, I2C_ADDR, mTask.txrxBuf, 2, &i2cCallback, (void *)SENSOR_STATE_DISABLING_PROX_3);
582         break;
583 
584     case SENSOR_STATE_DISABLING_PROX_3:
585         sensorSignalInternalEvt(mTask.proxHandle, SENSOR_INTERNAL_EVT_POWER_STATE_CHG, false, 0);
586         break;
587 
588     case SENSOR_STATE_ALS_SAMPLING:
589         als0 = *(uint16_t*)(mTask.txrxBuf);
590         als1 = *(uint16_t*)(mTask.txrxBuf+2);
591 
592         DEBUG_PRINT("als sample ready: als0=%u als1=%u\n", als0, als1);
593 
594         if (mTask.alsOn) {
595             sample.fdata = getLuxFromAlsData(als0, als1);
596             if (mTask.lastAlsSample.idata != sample.idata) {
597                 osEnqueueEvt(sensorGetMyEventType(SENS_TYPE_ALS), sample.vptr, NULL);
598                 mTask.lastAlsSample.fdata = sample.fdata;
599             }
600         }
601 
602         break;
603 
604     case SENSOR_STATE_PROX_SAMPLING:
605         ps = *(uint16_t*)(mTask.txrxBuf);
606         lastProxState = mTask.proxState;
607 
608         DEBUG_PRINT("prox sample ready: prox=%u\n", ps);
609 
610         if (mTask.proxOn) {
611             if (ps > ROHM_RPR0521_THRESHOLD_ASSERT_NEAR) {
612                 sample.fdata = ROHM_RPR0521_REPORT_NEAR_VALUE;
613                 mTask.proxState = PROX_STATE_NEAR;
614             } else {
615                 sample.fdata = ROHM_RPR0521_REPORT_FAR_VALUE;
616                 mTask.proxState = PROX_STATE_FAR;
617             }
618 
619             if (mTask.proxState != lastProxState)
620                 osEnqueueEvt(sensorGetMyEventType(SENS_TYPE_PROX), sample.vptr, NULL);
621 
622             // After the first prox sample, change the persistance setting to assert
623             // interrupt on-change, rather than after every sample
624             mTask.txrxBuf[0] = ROHM_RPR0521_REG_PS_CONTROL;
625             mTask.txrxBuf[1] = (ROHM_RPR0521_GAIN_PS << 4) | PS_PERSISTENCE_STATUS_UPDATED_AT_EACH_MEASUREMENT_END;
626             i2cMasterTx(I2C_BUS_ID, I2C_ADDR, mTask.txrxBuf, 2, &i2cCallback, (void *)SENSOR_STATE_IDLE);
627         }
628 
629         break;
630 
631     default:
632         break;
633     }
634 }
635 
636 /*
637  * Main driver entry points
638  */
639 
init_app(uint32_t myTid)640 static bool init_app(uint32_t myTid)
641 {
642     /* Set up driver private data */
643     mTask.tid = myTid;
644     mTask.alsOn = false;
645     mTask.proxOn = false;
646     mTask.lastAlsSample.idata = ROHM_RPR0521_ALS_INVALID;
647     mTask.proxState = PROX_STATE_INIT;
648 
649     mTask.pin = gpioRequest(PROX_INT_PIN);
650     gpioConfigInput(mTask.pin, GPIO_SPEED_LOW, GPIO_PULL_NONE);
651     syscfgSetExtiPort(mTask.pin);
652     mTask.isr.func = proxIsr;
653 
654     /* Register sensors */
655     mTask.alsHandle = sensorRegister(&sensorInfoAls, &sensorOpsAls, NULL, false);
656     mTask.proxHandle = sensorRegister(&sensorInfoProx, &sensorOpsProx, NULL, false);
657 
658     osEventSubscribe(myTid, EVT_APP_START);
659 
660     return true;
661 }
662 
end_app(void)663 static void end_app(void)
664 {
665     disableInterrupt(mTask.pin, &mTask.isr);
666     extiUnchainIsr(PROX_IRQ, &mTask.isr);
667     extiClearPendingGpio(mTask.pin);
668     gpioRelease(mTask.pin);
669 
670     sensorUnregister(mTask.alsHandle);
671     sensorUnregister(mTask.proxHandle);
672 
673     i2cMasterRelease(I2C_BUS_ID);
674 }
675 
handle_event(uint32_t evtType,const void * evtData)676 static void handle_event(uint32_t evtType, const void* evtData)
677 {
678     switch (evtType) {
679     case EVT_APP_START:
680         i2cMasterRequest(I2C_BUS_ID, I2C_SPEED);
681 
682         /* Reset chip */
683         mTask.txrxBuf[0] = ROHM_RPR0521_REG_SYSTEM_CONTROL;
684         mTask.txrxBuf[1] = SW_RESET_BIT;
685         i2cMasterTx(I2C_BUS_ID, I2C_ADDR, mTask.txrxBuf, 2, &i2cCallback, (void *)SENSOR_STATE_RESET);
686         break;
687 
688     case EVT_SENSOR_I2C:
689         handle_i2c_event((int)evtData);
690         break;
691 
692     case EVT_SENSOR_ALS_TIMER:
693         mTask.txrxBuf[0] = ROHM_RPR0521_REG_ALS_DATA0_LSB;
694         i2cMasterTxRx(I2C_BUS_ID, I2C_ADDR, mTask.txrxBuf, 1, mTask.txrxBuf, 4, &i2cCallback, (void *)SENSOR_STATE_ALS_SAMPLING);
695         break;
696 
697     case EVT_SENSOR_PROX_INTERRUPT:
698         // Over-read to read the INTERRUPT register to clear the interrupt
699         mTask.txrxBuf[0] = ROHM_RPR0521_REG_PS_DATA_LSB;
700         i2cMasterTxRx(I2C_BUS_ID, I2C_ADDR, mTask.txrxBuf, 1, mTask.txrxBuf, 7, &i2cCallback, (void *)SENSOR_STATE_PROX_SAMPLING);
701         break;
702 
703     }
704 }
705 
706 INTERNAL_APP_INIT(APP_ID_MAKE(APP_ID_VENDOR_GOOGLE, 10), RPR0521_APP_VERSION, init_app, end_app, handle_event);
707