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