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 <seos.h>
22 #include <i2c.h>
23 #include <timer.h>
24 #include <sensors.h>
25 #include <heap.h>
26 #include <hostIntf.h>
27 #include <nanohubPacket.h>
28 #include <eventnums.h>
29
30 #define TMD2772_APP_VERSION 1
31
32 #define DRIVER_NAME "AMS: "
33
34 #define I2C_BUS_ID 0
35 #define I2C_SPEED 400000
36 #define I2C_ADDR 0x39
37
38 #define AMS_TMD2772_ID 0x39
39
40 #define AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT 0xa0
41
42 #define AMS_TMD2772_REG_ENABLE (AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT | 0x00)
43 #define AMS_TMD2772_REG_ATIME (AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT | 0x01)
44 #define AMS_TMD2772_REG_PTIME (AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT | 0x02)
45 #define AMS_TMD2772_REG_WTIME (AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT | 0x03)
46 #define AMS_TMD2772_REG_AILTL (AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT | 0x04)
47 #define AMS_TMD2772_REG_AILTH (AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT | 0x05)
48 #define AMS_TMD2772_REG_AIHTL (AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT | 0x06)
49 #define AMS_TMD2772_REG_AIHTH (AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT | 0x07)
50 #define AMS_TMD2772_REG_PILTL (AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT | 0x08)
51 #define AMS_TMD2772_REG_PILTH (AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT | 0x09)
52 #define AMS_TMD2772_REG_PIHTL (AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT | 0x0a)
53 #define AMS_TMD2772_REG_PIHTH (AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT | 0x0b)
54 #define AMS_TMD2772_REG_PERS (AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT | 0x0c)
55 #define AMS_TMD2772_REG_CONFIG (AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT | 0x0d)
56 #define AMS_TMD2772_REG_PPULSE (AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT | 0x0e)
57 #define AMS_TMD2772_REG_CONTROL (AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT | 0x0f)
58 #define AMS_TMD2772_REG_ID (AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT | 0x12)
59 #define AMS_TMD2772_REG_STATUS (AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT | 0x13)
60 #define AMS_TMD2772_REG_C0DATA (AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT | 0x14)
61 #define AMS_TMD2772_REG_C0DATAH (AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT | 0x15)
62 #define AMS_TMD2772_REG_C1DATA (AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT | 0x16)
63 #define AMS_TMD2772_REG_C1DATAH (AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT | 0x17)
64 #define AMS_TMD2772_REG_PDATAL (AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT | 0x18)
65 #define AMS_TMD2772_REG_PDATAH (AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT | 0x19)
66 #define AMS_TMD2772_REG_POFFSET (AMS_TMD2772_CMD_TYPE_AUTO_INCREMENT | 0x1E)
67
68 #define AMS_TMD2772_ATIME_SETTING 0xdb
69 #define AMS_TMD2772_ATIME_MS ((256 - AMS_TMD2772_ATIME_SETTING) * 2.73) // in milliseconds
70 #define AMS_TMD2772_PTIME_SETTING 0xff
71 #define AMS_TMD2772_PTIME_MS ((256 - AMS_TMD2772_PTIME_SETTING) * 2.73) // in milliseconds
72 #define AMS_TMD2772_WTIME_SETTING_ALS_ON 0xdd // (256 - 221) * 2.73 ms = 95.55 ms
73 #define AMS_TMD2772_WTIME_SETTING_ALS_OFF 0xb8 // (256 - 184) * 2.73 ms = 196.56 ms
74 #define AMS_TMD2772_PPULSE_SETTING 8
75
76 #define AMS_TMD2772_CAL_DEFAULT_OFFSET 0
77 #define AMS_TMD2772_CAL_MAX_OFFSET 500
78
79 /* AMS_TMD2772_REG_ENABLE */
80 #define POWER_ON_BIT (1 << 0)
81 #define ALS_ENABLE_BIT (1 << 1)
82 #define PROX_ENABLE_BIT (1 << 2)
83 #define WAIT_ENABLE_BIT (1 << 3)
84
85 /* AMS_TMD2772_REG_STATUS */
86 #define PROX_INT_BIT (1 << 5)
87 #define ALS_INT_BIT (1 << 4)
88 #define PROX_VALID_BIT (1 << 1)
89 #define ALS_VALID_BIT (1 << 0)
90
91 #define AMS_TMD2772_REPORT_NEAR_VALUE 0.0f // centimeters
92 #define AMS_TMD2772_REPORT_FAR_VALUE 5.0f // centimeters
93
94 #define AMS_TMD2772_THRESHOLD_ASSERT_NEAR 213 // in PS units
95 #define AMS_TMD2772_THRESHOLD_DEASSERT_NEAR 96 // in PS units
96
97 #define AMS_TMD2772_ALS_MAX_CHANNEL_COUNT 37888 // in raw data
98 #define AMS_TMD2772_ALS_MAX_REPORT_VALUE 10000 // in lux
99
100 #define AMS_TMD2772_ALS_INVALID UINT32_MAX
101
102 /* Used when SENSOR_RATE_ONCHANGE is requested */
103 #define AMS_TMD2772_DEFAULT_RATE SENSOR_HZ(5)
104
105 /* Private driver events */
106 enum SensorEvents
107 {
108 EVT_SENSOR_I2C = EVT_APP_START + 1,
109 EVT_SENSOR_ALS_TIMER,
110 EVT_SENSOR_PROX_TIMER,
111 };
112
113 /* I2C state machine */
114 enum SensorState
115 {
116 SENSOR_STATE_VERIFY_ID,
117 SENSOR_STATE_INIT,
118
119 SENSOR_STATE_CALIBRATE_RESET,
120 SENSOR_STATE_CALIBRATE_START,
121 SENSOR_STATE_CALIBRATE_ENABLING,
122 SENSOR_STATE_CALIBRATE_POLLING_STATUS,
123 SENSOR_STATE_CALIBRATE_AWAITING_SAMPLE,
124 SENSOR_STATE_CALIBRATE_DISABLING,
125
126 SENSOR_STATE_ENABLING_ALS,
127 SENSOR_STATE_ENABLING_PROX,
128 SENSOR_STATE_DISABLING_ALS,
129 SENSOR_STATE_DISABLING_PROX,
130
131 SENSOR_STATE_IDLE,
132 SENSOR_STATE_SAMPLING,
133 };
134
135 enum ProxState
136 {
137 PROX_STATE_INIT,
138 PROX_STATE_NEAR,
139 PROX_STATE_FAR,
140 };
141
142 struct SensorData
143 {
144 union {
145 uint8_t bytes[16];
146 struct {
147 uint8_t status;
148 uint16_t als[2];
149 uint16_t prox;
150 } __attribute__((packed)) sample;
151 struct {
152 uint16_t prox;
153 } calibration;
154 } txrxBuf;
155
156 uint32_t tid;
157
158 uint32_t alsHandle;
159 uint32_t proxHandle;
160 uint32_t alsTimerHandle;
161 uint32_t proxTimerHandle;
162 uint32_t calibrationSampleTotal;
163
164 union EmbeddedDataPoint lastAlsSample;
165
166 uint8_t calibrationSampleCount;
167 uint8_t proxState; // enum ProxState
168
169 bool alsOn;
170 bool alsReading;
171 bool proxOn;
172 bool proxReading;
173 };
174
175 static struct SensorData mData;
176
177 /* TODO: check rates are supported */
178 static const uint32_t supportedRates[] =
179 {
180 SENSOR_HZ(0.1),
181 SENSOR_HZ(1),
182 SENSOR_HZ(4),
183 SENSOR_HZ(5),
184 SENSOR_RATE_ONCHANGE,
185 0
186 };
187
188 static const uint64_t rateTimerVals[] = //should match "supported rates in length" and be the timer length for that rate in nanosecs
189 {
190 10 * 1000000000ULL,
191 1 * 1000000000ULL,
192 1000000000ULL / 4,
193 1000000000ULL / 5,
194 };
195
196 /*
197 * Helper functions
198 */
199
i2cCallback(void * cookie,size_t tx,size_t rx,int err)200 static void i2cCallback(void *cookie, size_t tx, size_t rx, int err)
201 {
202 if (err == 0)
203 osEnqueuePrivateEvt(EVT_SENSOR_I2C, cookie, NULL, mData.tid);
204 else
205 osLog(LOG_INFO, DRIVER_NAME "i2c error (%d)\n", err);
206 }
207
alsTimerCallback(uint32_t timerId,void * cookie)208 static void alsTimerCallback(uint32_t timerId, void *cookie)
209 {
210 osEnqueuePrivateEvt(EVT_SENSOR_ALS_TIMER, cookie, NULL, mData.tid);
211 }
212
proxTimerCallback(uint32_t timerId,void * cookie)213 static void proxTimerCallback(uint32_t timerId, void *cookie)
214 {
215 osEnqueuePrivateEvt(EVT_SENSOR_PROX_TIMER, cookie, NULL, mData.tid);
216 }
217
getLuxFromAlsData(uint16_t als0,uint16_t als1)218 static inline float getLuxFromAlsData(uint16_t als0, uint16_t als1)
219 {
220 float cpl = 1.0f / AMS_TMD2772_ATIME_MS;
221 float GA;
222
223 if ((als0 * 10) < (als1 * 21)) {
224 // A light
225 GA = 0.274f;
226 } else if (((als0 * 10) >= (als1 * 21)) && ((als0 * 10) <= (als1 * 43)) && (als0 > 300)) {
227 // D65
228 GA = 0.592f;
229 } else {
230 // cool white
231 GA = 1.97f;
232 }
233
234 float lux1 = GA * 207 * (als0 - (1.799 * als1)) * cpl;
235 float lux2 = GA * 207 * ((0.188f * als0) - (0.303 * als1)) * cpl;
236
237 if ((als0 >= AMS_TMD2772_ALS_MAX_CHANNEL_COUNT) ||
238 (als1 >= AMS_TMD2772_ALS_MAX_CHANNEL_COUNT)) {
239 return AMS_TMD2772_ALS_MAX_REPORT_VALUE;
240 } else if ((lux1 > lux2) && (lux1 > 0.0f)) {
241 return lux1 > AMS_TMD2772_ALS_MAX_REPORT_VALUE ? AMS_TMD2772_ALS_MAX_REPORT_VALUE : lux1;
242 } else if (lux2 > 0.0f) {
243 return lux2 > AMS_TMD2772_ALS_MAX_REPORT_VALUE ? AMS_TMD2772_ALS_MAX_REPORT_VALUE : lux2;
244 } else {
245 return 0.0f;
246 }
247 }
248
setMode(bool alsOn,bool proxOn,void * cookie)249 static void setMode(bool alsOn, bool proxOn, void *cookie)
250 {
251 mData.txrxBuf.bytes[0] = AMS_TMD2772_REG_ENABLE;
252 mData.txrxBuf.bytes[1] = POWER_ON_BIT | WAIT_ENABLE_BIT |
253 (alsOn ? ALS_ENABLE_BIT : 0) | (proxOn ? PROX_ENABLE_BIT : 0);
254 mData.txrxBuf.bytes[2] = AMS_TMD2772_ATIME_SETTING;
255 mData.txrxBuf.bytes[3] = AMS_TMD2772_PTIME_SETTING;
256 mData.txrxBuf.bytes[4] = alsOn ? AMS_TMD2772_WTIME_SETTING_ALS_ON : AMS_TMD2772_WTIME_SETTING_ALS_OFF;
257 i2cMasterTx(I2C_BUS_ID, I2C_ADDR, mData.txrxBuf.bytes, 5,
258 &i2cCallback, cookie);
259 }
260
sensorPowerAls(bool on,void * cookie)261 static bool sensorPowerAls(bool on, void *cookie)
262 {
263 osLog(LOG_INFO, DRIVER_NAME "sensorPowerAls: %d\n", on);
264
265 if (mData.alsTimerHandle) {
266 timTimerCancel(mData.alsTimerHandle);
267 mData.alsTimerHandle = 0;
268 mData.alsReading = false;
269 }
270
271 mData.lastAlsSample.idata = AMS_TMD2772_ALS_INVALID;
272 mData.alsOn = on;
273 setMode(on, mData.proxOn, (void *)(on ? SENSOR_STATE_ENABLING_ALS : SENSOR_STATE_DISABLING_ALS));
274
275 return true;
276 }
277
sensorFirmwareAls(void * cookie)278 static bool sensorFirmwareAls(void *cookie)
279 {
280 sensorSignalInternalEvt(mData.alsHandle, SENSOR_INTERNAL_EVT_FW_STATE_CHG, 1, 0);
281 return true;
282 }
283
sensorRateAls(uint32_t rate,uint64_t latency,void * cookie)284 static bool sensorRateAls(uint32_t rate, uint64_t latency, void *cookie)
285 {
286 if (rate == SENSOR_RATE_ONCHANGE) {
287 rate = AMS_TMD2772_DEFAULT_RATE;
288 }
289 osLog(LOG_INFO, DRIVER_NAME "sensorRateAls: %ld/%lld\n", rate, latency);
290
291 if (mData.alsTimerHandle)
292 timTimerCancel(mData.alsTimerHandle);
293 mData.alsTimerHandle = timTimerSet(sensorTimerLookupCommon(supportedRates, rateTimerVals, rate), 0, 50, alsTimerCallback, NULL, false);
294 osEnqueuePrivateEvt(EVT_SENSOR_ALS_TIMER, NULL, NULL, mData.tid);
295 sensorSignalInternalEvt(mData.alsHandle, SENSOR_INTERNAL_EVT_RATE_CHG, rate, latency);
296
297 return true;
298 }
299
sensorFlushAls(void * cookie)300 static bool sensorFlushAls(void *cookie)
301 {
302 return osEnqueueEvt(sensorGetMyEventType(SENS_TYPE_ALS), SENSOR_DATA_EVENT_FLUSH, NULL);
303 }
304
sendLastSampleAls(void * cookie,uint32_t tid)305 static bool sendLastSampleAls(void *cookie, uint32_t tid) {
306 bool result = true;
307
308 // If we don't end up doing anything here, the expectation is that we are powering up/haven't got the
309 // first sample yet, so a broadcast event will go out soon with the first sample
310 if (mData.lastAlsSample.idata != AMS_TMD2772_ALS_INVALID) {
311 result = osEnqueuePrivateEvt(sensorGetMyEventType(SENS_TYPE_ALS), mData.lastAlsSample.vptr, NULL, tid);
312 }
313 return result;
314 }
315
sensorPowerProx(bool on,void * cookie)316 static bool sensorPowerProx(bool on, void *cookie)
317 {
318 osLog(LOG_INFO, DRIVER_NAME "sensorPowerProx: %d\n", on);
319
320 if (mData.proxTimerHandle) {
321 timTimerCancel(mData.proxTimerHandle);
322 mData.proxTimerHandle = 0;
323 mData.proxReading = false;
324 }
325
326 mData.proxState = PROX_STATE_INIT;
327 mData.proxOn = on;
328 setMode(mData.alsOn, on, (void *)(on ? SENSOR_STATE_ENABLING_PROX : SENSOR_STATE_DISABLING_PROX));
329
330 return true;
331 }
332
sensorFirmwareProx(void * cookie)333 static bool sensorFirmwareProx(void *cookie)
334 {
335 sensorSignalInternalEvt(mData.proxHandle, SENSOR_INTERNAL_EVT_FW_STATE_CHG, 1, 0);
336 return true;
337 }
338
sensorRateProx(uint32_t rate,uint64_t latency,void * cookie)339 static bool sensorRateProx(uint32_t rate, uint64_t latency, void *cookie)
340 {
341 if (rate == SENSOR_RATE_ONCHANGE) {
342 rate = AMS_TMD2772_DEFAULT_RATE;
343 }
344 osLog(LOG_INFO, DRIVER_NAME "sensorRateProx: %ld/%lld\n", rate, latency);
345
346 if (mData.proxTimerHandle)
347 timTimerCancel(mData.proxTimerHandle);
348 mData.proxTimerHandle = timTimerSet(sensorTimerLookupCommon(supportedRates, rateTimerVals, rate), 0, 50, proxTimerCallback, NULL, false);
349 osEnqueuePrivateEvt(EVT_SENSOR_PROX_TIMER, NULL, NULL, mData.tid);
350 sensorSignalInternalEvt(mData.proxHandle, SENSOR_INTERNAL_EVT_RATE_CHG, rate, latency);
351
352 return true;
353 }
354
sensorFlushProx(void * cookie)355 static bool sensorFlushProx(void *cookie)
356 {
357 return osEnqueueEvt(sensorGetMyEventType(SENS_TYPE_PROX), SENSOR_DATA_EVENT_FLUSH, NULL);
358 }
359
sendLastSampleProx(void * cookie,uint32_t tid)360 static bool sendLastSampleProx(void *cookie, uint32_t tid) {
361 union EmbeddedDataPoint sample;
362 bool result = true;
363
364 // See note in sendLastSampleAls
365 if (mData.proxState != PROX_STATE_INIT) {
366 sample.fdata = (mData.proxState == PROX_STATE_NEAR) ?
367 AMS_TMD2772_REPORT_NEAR_VALUE : AMS_TMD2772_REPORT_FAR_VALUE;
368 result = osEnqueuePrivateEvt(sensorGetMyEventType(SENS_TYPE_PROX), sample.vptr, NULL, tid);
369 }
370 return result;
371 }
372
373 static const struct SensorInfo sensorInfoAls =
374 {
375 .sensorName = "ALS",
376 .supportedRates = supportedRates,
377 .sensorType = SENS_TYPE_ALS,
378 .numAxis = NUM_AXIS_EMBEDDED,
379 .interrupt = NANOHUB_INT_NONWAKEUP,
380 .minSamples = 20
381 };
382
383 static const struct SensorOps sensorOpsAls =
384 {
385 .sensorPower = sensorPowerAls,
386 .sensorFirmwareUpload = sensorFirmwareAls,
387 .sensorSetRate = sensorRateAls,
388 .sensorFlush = sensorFlushAls,
389 .sensorTriggerOndemand = NULL,
390 .sensorCalibrate = NULL,
391 .sensorSendOneDirectEvt = sendLastSampleAls
392 };
393
394 static const struct SensorInfo sensorInfoProx =
395 {
396 .sensorName = "Proximity",
397 .supportedRates = supportedRates,
398 .sensorType = SENS_TYPE_PROX,
399 .numAxis = NUM_AXIS_EMBEDDED,
400 .interrupt = NANOHUB_INT_WAKEUP,
401 .minSamples = 300
402 };
403
404 static const struct SensorOps sensorOpsProx =
405 {
406 .sensorPower = sensorPowerProx,
407 .sensorFirmwareUpload = sensorFirmwareProx,
408 .sensorSetRate = sensorRateProx,
409 .sensorFlush = sensorFlushProx,
410 .sensorTriggerOndemand = NULL,
411 .sensorCalibrate = NULL,
412 .sensorSendOneDirectEvt = sendLastSampleProx
413 };
414
415 /*
416 * Sensor i2c state machine
417 */
418
handle_calibration_event(int state)419 static void handle_calibration_event(int state) {
420 switch (state) {
421 case SENSOR_STATE_CALIBRATE_RESET:
422 mData.calibrationSampleCount = 0;
423 mData.calibrationSampleTotal = 0;
424 /* Intentional fall-through */
425
426 case SENSOR_STATE_CALIBRATE_START:
427 mData.txrxBuf.bytes[0] = AMS_TMD2772_REG_ENABLE;
428 mData.txrxBuf.bytes[1] = POWER_ON_BIT | PROX_ENABLE_BIT;
429 i2cMasterTx(I2C_BUS_ID, I2C_ADDR, mData.txrxBuf.bytes, 2,
430 &i2cCallback, (void *)SENSOR_STATE_CALIBRATE_ENABLING);
431 break;
432
433 case SENSOR_STATE_CALIBRATE_ENABLING:
434 mData.txrxBuf.bytes[0] = AMS_TMD2772_REG_STATUS;
435 i2cMasterTxRx(I2C_BUS_ID, I2C_ADDR, mData.txrxBuf.bytes, 1,
436 mData.txrxBuf.bytes, 1, &i2cCallback,
437 (void *)SENSOR_STATE_CALIBRATE_POLLING_STATUS);
438 break;
439
440 case SENSOR_STATE_CALIBRATE_POLLING_STATUS:
441 if (mData.txrxBuf.bytes[0] & PROX_INT_BIT) {
442 /* Done */
443 mData.txrxBuf.bytes[0] = AMS_TMD2772_REG_PDATAL;
444 i2cMasterTxRx(I2C_BUS_ID, I2C_ADDR, mData.txrxBuf.bytes, 1,
445 mData.txrxBuf.bytes, 2, &i2cCallback,
446 (void *)SENSOR_STATE_CALIBRATE_AWAITING_SAMPLE);
447 } else {
448 /* Poll again; go back to previous state */
449 handle_calibration_event(SENSOR_STATE_CALIBRATE_ENABLING);
450 }
451 break;
452
453 case SENSOR_STATE_CALIBRATE_AWAITING_SAMPLE:
454 mData.calibrationSampleCount++;
455 mData.calibrationSampleTotal += mData.txrxBuf.calibration.prox;
456
457 mData.txrxBuf.bytes[0] = AMS_TMD2772_REG_ENABLE;
458 mData.txrxBuf.bytes[1] = 0x00;
459 i2cMasterTx(I2C_BUS_ID, I2C_ADDR, mData.txrxBuf.bytes, 2,
460 &i2cCallback, (void *)SENSOR_STATE_CALIBRATE_DISABLING);
461 break;
462
463 case SENSOR_STATE_CALIBRATE_DISABLING:
464 if (mData.calibrationSampleCount >= 20) {
465 /* Done, calculate calibration */
466 uint16_t average = mData.calibrationSampleTotal / mData.calibrationSampleCount;
467 uint16_t crosstalk = (average > 0x7f) ? 0x7f : average;
468
469 mData.txrxBuf.bytes[0] = AMS_TMD2772_REG_POFFSET;
470 mData.txrxBuf.bytes[1] = crosstalk;
471 i2cMasterTx(I2C_BUS_ID, I2C_ADDR, mData.txrxBuf.bytes, 2,
472 &i2cCallback, (void *)SENSOR_STATE_IDLE);
473 } else {
474 /* Get another sample; go back to earlier state */
475 handle_calibration_event(SENSOR_STATE_CALIBRATE_START);
476 }
477 break;
478
479 default:
480 break;
481 }
482 }
483
handle_i2c_event(int state)484 static void handle_i2c_event(int state)
485 {
486 union EmbeddedDataPoint sample;
487 bool sendData;
488
489 switch (state) {
490 case SENSOR_STATE_VERIFY_ID:
491 /* Check the sensor ID */
492 if (mData.txrxBuf.bytes[0] != AMS_TMD2772_ID) {
493 osLog(LOG_INFO, DRIVER_NAME "not detected\n");
494 sensorUnregister(mData.alsHandle);
495 sensorUnregister(mData.proxHandle);
496 break;
497 }
498
499 /* Start address */
500 mData.txrxBuf.bytes[0] = AMS_TMD2772_REG_ENABLE;
501 /* ENABLE */
502 mData.txrxBuf.bytes[1] = 0x00;
503 /* ATIME */
504 mData.txrxBuf.bytes[2] = AMS_TMD2772_ATIME_SETTING;
505 /* PTIME */
506 mData.txrxBuf.bytes[3] = AMS_TMD2772_PTIME_SETTING;
507 /* WTIME */
508 mData.txrxBuf.bytes[4] = 0xFF;
509 i2cMasterTx(I2C_BUS_ID, I2C_ADDR, mData.txrxBuf.bytes, 5,
510 &i2cCallback, (void *)SENSOR_STATE_INIT);
511 break;
512
513 case SENSOR_STATE_INIT:
514 /* Start address */
515 mData.txrxBuf.bytes[0] = AMS_TMD2772_REG_PERS;
516 /* PERS */
517 mData.txrxBuf.bytes[1] = 0x00;
518 /* CONFIG */
519 mData.txrxBuf.bytes[2] = 0x00;
520 /* PPULSE */
521 mData.txrxBuf.bytes[3] = AMS_TMD2772_PPULSE_SETTING;
522 /* CONTROL */
523 mData.txrxBuf.bytes[4] = 0x20;
524 i2cMasterTx(I2C_BUS_ID, I2C_ADDR, mData.txrxBuf.bytes, 5,
525 &i2cCallback, (void *)SENSOR_STATE_IDLE);
526 break;
527
528 case SENSOR_STATE_IDLE:
529 sensorRegisterInitComplete(mData.alsHandle);
530 sensorRegisterInitComplete(mData.proxHandle);
531 break;
532
533 case SENSOR_STATE_ENABLING_ALS:
534 sensorSignalInternalEvt(mData.alsHandle, SENSOR_INTERNAL_EVT_POWER_STATE_CHG, true, 0);
535 break;
536
537 case SENSOR_STATE_ENABLING_PROX:
538 sensorSignalInternalEvt(mData.proxHandle, SENSOR_INTERNAL_EVT_POWER_STATE_CHG, true, 0);
539 break;
540
541 case SENSOR_STATE_DISABLING_ALS:
542 sensorSignalInternalEvt(mData.alsHandle, SENSOR_INTERNAL_EVT_POWER_STATE_CHG, false, 0);
543 break;
544
545 case SENSOR_STATE_DISABLING_PROX:
546 sensorSignalInternalEvt(mData.proxHandle, SENSOR_INTERNAL_EVT_POWER_STATE_CHG, false, 0);
547 break;
548
549 case SENSOR_STATE_SAMPLING:
550 /* TEST: log collected data
551 osLog(LOG_INFO, DRIVER_NAME "sample ready: status=%02x prox=%u als0=%u als1=%u\n",
552 mData.txrxBuf.sample.status, mData.txrxBuf.sample.prox,
553 mData.txrxBuf.sample.als[0], mData.txrxBuf.sample.als[1]);
554 */
555
556 if (mData.alsOn && mData.alsReading &&
557 (mData.txrxBuf.sample.status & ALS_VALID_BIT)) {
558 /* Create event */
559 sample.fdata = getLuxFromAlsData(mData.txrxBuf.sample.als[0],
560 mData.txrxBuf.sample.als[1]);
561 if (mData.lastAlsSample.idata != sample.idata) {
562 osEnqueueEvt(sensorGetMyEventType(SENS_TYPE_ALS), sample.vptr, NULL);
563 mData.lastAlsSample.fdata = sample.fdata;
564 }
565 }
566
567 if (mData.proxOn && mData.proxReading &&
568 (mData.txrxBuf.sample.status & PROX_VALID_BIT)) {
569 /* Create event */
570 sendData = true;
571 if (mData.proxState == PROX_STATE_INIT) {
572 if (mData.txrxBuf.sample.prox > AMS_TMD2772_THRESHOLD_ASSERT_NEAR) {
573 sample.fdata = AMS_TMD2772_REPORT_NEAR_VALUE;
574 mData.proxState = PROX_STATE_NEAR;
575 } else {
576 sample.fdata = AMS_TMD2772_REPORT_FAR_VALUE;
577 mData.proxState = PROX_STATE_FAR;
578 }
579 } else {
580 if (mData.proxState == PROX_STATE_NEAR &&
581 mData.txrxBuf.sample.prox < AMS_TMD2772_THRESHOLD_DEASSERT_NEAR) {
582 sample.fdata = AMS_TMD2772_REPORT_FAR_VALUE;
583 mData.proxState = PROX_STATE_FAR;
584 } else if (mData.proxState == PROX_STATE_FAR &&
585 mData.txrxBuf.sample.prox > AMS_TMD2772_THRESHOLD_ASSERT_NEAR) {
586 sample.fdata = AMS_TMD2772_REPORT_NEAR_VALUE;
587 mData.proxState = PROX_STATE_NEAR;
588 } else {
589 sendData = false;
590 }
591 }
592
593 if (sendData)
594 osEnqueueEvt(sensorGetMyEventType(SENS_TYPE_PROX), sample.vptr, NULL);
595 }
596
597 mData.alsReading = false;
598 mData.proxReading = false;
599 break;
600
601 default:
602 handle_calibration_event(state);
603 break;
604 }
605 }
606
607 /*
608 * Main driver entry points
609 */
610
init_app(uint32_t myTid)611 static bool init_app(uint32_t myTid)
612 {
613 /* Set up driver private data */
614 mData.tid = myTid;
615 mData.alsOn = false;
616 mData.alsReading = false;
617 mData.proxOn = false;
618 mData.proxReading = false;
619 mData.lastAlsSample.idata = AMS_TMD2772_ALS_INVALID;
620 mData.proxState = PROX_STATE_INIT;
621
622 /* Register sensors */
623 mData.alsHandle = sensorRegister(&sensorInfoAls, &sensorOpsAls, NULL, false);
624 mData.proxHandle = sensorRegister(&sensorInfoProx, &sensorOpsProx, NULL, false);
625
626 osEventSubscribe(myTid, EVT_APP_START);
627
628 return true;
629 }
630
end_app(void)631 static void end_app(void)
632 {
633 sensorUnregister(mData.alsHandle);
634 sensorUnregister(mData.proxHandle);
635
636 i2cMasterRelease(I2C_BUS_ID);
637 }
638
handle_event(uint32_t evtType,const void * evtData)639 static void handle_event(uint32_t evtType, const void* evtData)
640 {
641 switch (evtType) {
642 case EVT_APP_START:
643 osEventUnsubscribe(mData.tid, EVT_APP_START);
644 i2cMasterRequest(I2C_BUS_ID, I2C_SPEED);
645
646 /* TODO: reset chip first */
647
648 mData.txrxBuf.bytes[0] = AMS_TMD2772_REG_ID;
649 i2cMasterTxRx(I2C_BUS_ID, I2C_ADDR, mData.txrxBuf.bytes, 1,
650 mData.txrxBuf.bytes, 1, &i2cCallback,
651 (void *)SENSOR_STATE_VERIFY_ID);
652 break;
653
654 case EVT_SENSOR_I2C:
655 handle_i2c_event((int)evtData);
656 break;
657
658 case EVT_SENSOR_ALS_TIMER:
659 case EVT_SENSOR_PROX_TIMER:
660 /* Start sampling for a value */
661 if (!mData.alsReading && !mData.proxReading) {
662 mData.txrxBuf.bytes[0] = AMS_TMD2772_REG_STATUS;
663 i2cMasterTxRx(I2C_BUS_ID, I2C_ADDR, mData.txrxBuf.bytes, 1,
664 mData.txrxBuf.bytes, 7, &i2cCallback,
665 (void *)SENSOR_STATE_SAMPLING);
666 }
667
668 if (evtType == EVT_SENSOR_ALS_TIMER)
669 mData.alsReading = true;
670 else
671 mData.proxReading = true;
672 break;
673 }
674 }
675
676 INTERNAL_APP_INIT(APP_ID_MAKE(APP_ID_VENDOR_GOOGLE, 9), TMD2772_APP_VERSION, init_app, end_app, handle_event);
677