• 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 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  */
proxIsr(struct ChainedIsr * localIsr)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 
enableInterrupt(struct Gpio * pin,struct ChainedIsr * isr)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 
disableInterrupt(struct Gpio * pin,struct ChainedIsr * isr)280 static bool disableInterrupt(struct Gpio *pin, struct ChainedIsr *isr)
281 {
282     extiUnchainIsr(PROX_IRQ, isr);
283     extiDisableIntGpio(pin);
284     return true;
285 }
286 
i2cCallback(void * cookie,size_t tx,size_t rx,int err)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 
alsTimerCallback(uint32_t timerId,void * cookie)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.
allocXfer(uint8_t state)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().
writeRegister(uint8_t reg,uint8_t value,uint8_t state)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 
getLuxFromAlsData(uint16_t als0,uint16_t als1)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 
setMode(bool alsOn,bool proxOn,uint8_t state)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 
sensorPowerAls(bool on,void * cookie)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 
sensorFirmwareAls(void * cookie)400 static bool sensorFirmwareAls(void *cookie)
401 {
402     return sensorSignalInternalEvt(mTask.alsHandle, SENSOR_INTERNAL_EVT_FW_STATE_CHG, 1, 0);
403 }
404 
sensorRateAls(uint32_t rate,uint64_t latency,void * cookie)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 
sensorFlushAls(void * cookie)415 static bool sensorFlushAls(void *cookie)
416 {
417     return osEnqueueEvt(sensorGetMyEventType(SENS_TYPE_ALS), SENSOR_DATA_EVENT_FLUSH, NULL);
418 }
419 
sendLastSampleAls(void * cookie,uint32_t tid)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 
sensorPowerProx(bool on,void * cookie)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 
sensorFirmwareProx(void * cookie)450 static bool sensorFirmwareProx(void *cookie)
451 {
452     return sensorSignalInternalEvt(mTask.proxHandle, SENSOR_INTERNAL_EVT_FW_STATE_CHG, 1, 0);
453 }
454 
sensorRateProx(uint32_t rate,uint64_t latency,void * cookie)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 
sensorFlushProx(void * cookie)465 static bool sensorFlushProx(void *cookie)
466 {
467     return osEnqueueEvt(sensorGetMyEventType(SENS_TYPE_PROX), SENSOR_DATA_EVENT_FLUSH, NULL);
468 }
469 
sensorCfgDataProx(void * data,void * cookie)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 
sendLastSampleProx(void * cookie,uint32_t tid)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 
sensorAlsFree(void * ptr)552 static void __attribute__((unused)) sensorAlsFree(void *ptr)
553 {
554 }
555 
sensorProxFree(void * ptr)556 static void __attribute__((unused)) sensorProxFree(void *ptr)
557 {
558 }
559 
handle_i2c_event(struct I2cTransfer * xfer)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 
init_app(uint32_t myTid)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 
end_app(void)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 
handle_event(uint32_t evtType,const void * evtData)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