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