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