GSaha567/seq_level_training_data
052
1text,length,is_long_context,metric_val,label_metric2"/**
3 * @file SparkFun_APDS-9960.cpp
4 * @brief Library for the SparkFun APDS-9960 breakout board
5 * @author Shawn Hymel (SparkFun Electronics)
6 *
7 * @copyright This code is public domain but you buy me a beer if you use
8 * this and we meet someday (Beerware license).
9 *
10 * This library interfaces the Avago APDS-9960 to Arduino over I2C. The library
11 * relies on the Arduino Wire (I2C) library. to use the library, instantiate an
12 * APDS9960 object, call init(), and call the appropriate functions.
13 *
14 * APDS-9960 current draw tests (default parameters):
15 * Off: 1mA
16 * Waiting for gesture: 14mA
17 * Gesture in progress: 35mA
18 */
19
20 #include <Arduino.h>
21 #include <Wire.h>
22
23 #include ""SparkFun_APDS9960.h""
24
25/**
26 * @brief Constructor - Instantiates SparkFun_APDS9960 object
27 */
28SparkFun_APDS9960::SparkFun_APDS9960()
29{
30 gesture_ud_delta_ = 0;
31 gesture_lr_delta_ = 0;
32
33 gesture_ud_count_ = 0;
34 gesture_lr_count_ = 0;
35
36 gesture_near_count_ = 0;
37 gesture_far_count_ = 0;
38
39 gesture_state_ = 0;
40 gesture_motion_ = DIR_NONE;
41
42}
43
44/**
45 * @brief Destructor
46 */
47SparkFun_APDS9960::~SparkFun_APDS9960()
48{
49
50}
51
52/**
53 * @brief Configures I2C communications and initializes registers to defaults
54 *
55 * @return True if initialized successfully. False otherwise.
56 */
57bool SparkFun_APDS9960::init(void)
58{
59 uint8_t id;
60
61 /* Initialize I2C */
62 //Wire.begin();
63 //Wire.begin(D3,D1);
64
65 /* Read ID register and check against known values for APDS-9960 */
66 if( !wireReadDataByte(APDS9960_ID, id) ) {
67 return false;
68 }
69 if( !(id == APDS9960_ID_1 || id == APDS9960_ID_2) ) {
70 return false;
71 }
72
73 /* Set ENABLE register to 0 (disable all features) */
74 if( !setMode(APDS9960_ALL, APDS9960_OFF) ) {
75 return false;
76 }
77
78 /* Set default values for ambient light and proximity registers */
79 if( !wireWriteDataByte(APDS9960_ATIME, DEFAULT_ATIME) ) {
80 return false;
81 }
82 if( !wireWriteDataByte(APDS9960_WTIME, DEFAULT_WTIME) ) {
83 return false;
84 }
85 if( !wireWriteDataByte(APDS9960_PPULSE, DEFAULT_PROX_PPULSE) ) {
86 return false;
87 }
88 if( !wireWriteDataByte(APDS9960_POFFSET_UR, DEFAULT_POFFSET_UR) ) {
89 return false;
90 }
91 if( !wireWriteDataByte(APDS9960_POFFSET_DL, DEFAULT_POFFSET_DL) ) {
92 return false;
93 }
94 if( !wireWriteDataByte(APDS9960_CONFIG1, DEFAULT_CONFIG1) ) {
95 return false;
96 }
97 if( !setLEDDrive(DEFAULT_LDRIVE) ) {
98 return false;
99 }
100 if( !setProximityGain(DEFAULT_PGAIN) ) {
101 return false;
102 }
103 if( !setAmbientLightGain(DEFAULT_AGAIN) ) {
104 return false;
105 }
106 if( !setProxIntLowThresh(DEFAULT_PILT) ) {
107 return false;
108 }
109 if( !setProxIntHighThresh(DEFAULT_PIHT) ) {
110 return false;
111 }
112 if( !setLightIntLowThreshold(DEFAULT_AILT) ) {
113 return false;
114 }
115 if( !setLightIntHighThreshold(DEFAULT_AIHT) ) {
116 return false;
117 }
118 if( !wireWriteDataByte(APDS9960_PERS, DEFAULT_PERS) ) {
119 return false;
120 }
121 if( !wireWriteDataByte(APDS9960_CONFIG2, DEFAULT_CONFIG2) ) {
122 return false;
123 }
124 if( !wireWriteDataByte(APDS9960_CONFIG3, DEFAULT_CONFIG3) ) {
125 return false;
126 }
127
128 /* Set default values for gesture sense registers */
129 if( !setGestureEnterThresh(DEFAULT_GPENTH) ) {
130 return false;
131 }
132 if( !setGestureExitThresh(DEFAULT_GEXTH) ) {
133 return false;
134 }
135 if( !wireWriteDataByte(APDS9960_GCONF1, DEFAULT_GCONF1) ) {
136 return false;
137 }
138 if( !setGestureGain(DEFAULT_GGAIN) ) {
139 return false;
140 }
141 if( !setGestureLEDDrive(DEFAULT_GLDRIVE) ) {
142 return false;
143 }
144 if( !setGestureWaitTime(DEFAULT_GWTIME) ) {
145 return false;
146 }
147 if( !wireWriteDataByte(APDS9960_GOFFSET_U, DEFAULT_GOFFSET_U) ) {
148 return false;
149 }
150 if( !wireWriteDataByte(APDS9960_GOFFSET_D, DEFAULT_GOFFSET_D) ) {
151 return false;
152 }
153 if( !wireWriteDataByte(APDS9960_GOFFSET_L, DEFAULT_GOFFSET_L) ) {
154 return false;
155 }
156 if( !wireWriteDataByte(APDS9960_GOFFSET_R, DEFAULT_GOFFSET_R) ) {
157 return false;
158 }
159 if( !wireWriteDataByte(APDS9960_GPULSE, DEFAULT_GPULSE) ) {
160 return false;
161 }
162 if( !wireWriteDataByte(APDS9960_GCONF3, DEFAULT_GCONF3) ) {
163 return false;
164 }
165 if( !setGestureIntEnable(DEFAULT_GIEN) ) {
166 return false;
167 }
168
169#if 0
170 /* Gesture config register dump */
171 uint8_t reg;
172 uint8_t val;
173
174 for(reg = 0x80; reg <= 0xAF; reg++) {
175 if( (reg != 0x82) && \\
176 (reg != 0x8A) && \\
177 (reg != 0x91) && \\
178 (reg != 0xA8) && \\
179 (reg != 0xAC) && \\
180 (reg != 0xAD) )
181 {
182 wireReadDataByte(reg, val);
183 Serial.print(reg, HEX);
184 Serial.print("": 0x"");
185 Serial.println(val, HEX);
186 }
187 }
188
189 for(reg = 0xE4; reg <= 0xE7; reg++) {
190 wireReadDataByte(reg, val);
191 Serial.print(reg, HEX);
192 Serial.print("": 0x"");
193 Serial.println(val, HEX);
194 }
195#endif
196
197 return true;
198}
199
200/*******************************************************************************
201 * Public methods for controlling the APDS-9960
202 ******************************************************************************/
203
204/**
205 * @brief Reads and returns the contents of the ENABLE register
206 *
207 * @return Contents of the ENABLE register. 0xFF if error.
208 */
209uint8_t SparkFun_APDS9960::getMode()
210{
211 uint8_t enable_value;
212
213 /* Read current ENABLE register */
214 if( !wireReadDataByte(APDS9960_ENABLE, enable_value) ) {
215 return APDS9960_ERROR;
216 }
217
218 return enable_value;
219}
220
221
222// Enables or disables a feature in the APDS-9960
223// Accesses the Enable Register (0x80)
224// @param[in] mode which feature to enable
225// @param[in] enable APDS9960_ON (1) or APDS9960_OFF (0)
226// @return True if operation success. False otherwise.
227
228bool SparkFun_APDS9960::setMode(uint8_t mode, uint8_t enable)
229{
230 uint8_t reg_val;
231
232 /* Read current ENABLE register */
233 reg_val = getMode();
234 if( reg_val == APDS9960_ERROR ) {
235 return false;
236 }
237
238 /* Change bit(s) in ENABLE register */
239 enable &= 0x01;
240 if(mode <= 6) {
241 if (enable) {
242 reg_val |= (1 << mode);
243 } else {
244 reg_val &= ~(1 << mode);
245 }
246 } else if( mode == APDS9960_ALL ) {
247 if (enable) {
248 reg_val = 0x7F;
249 } else {
250 reg_val = 0x00;
251 }
252 } else
253 return false;
254
255 /* Write value back to ENABLE register */
256 if( !wireWriteDataByte(APDS9960_ENABLE, reg_val) ) {
257 return false;
258 }
259
260 return true;
261}
262
263/**
264 * @brief Starts the light (R/G/B/Ambient) sensor on the APDS-9960
265 *
266 * @param[in] interrupts true to enable hardware interrupt on high or low light
267 * @return True if sensor enabled correctly. False on error.
268 */
269bool SparkFun_APDS9960::enableLightSensor(bool interrupts)
270{
271
272 /* Set default gain, interrupts, enable power, and enable sensor */
273 if( !setAmbientLightGain(DEFAULT_AGAIN) ) {
274 return false;
275 }
276 if( interrupts ) {
277 if( !setAmbientLightIntEnable(1) ) {
278 return false;
279 }
280 } else {
281 if( !setAmbientLightIntEnable(0) ) {
282 return false;
283 }
284 }
285 if( !enablePower() ){
286 return false;
287 }
288 if( !setMode(AMBIENT_LIGHT, 1) ) {
289 return false;
290 }
291
292 return true;
293
294}
295
296/**
297 * @brief Ends the light sensor on the APDS-9960
298 *
299 * @return True if sensor disabled correctly. False on error.
300 */
301bool SparkFun_APDS9960::disableLightSensor()
302{
303 if( !setAmbientLightIntEnable(0) ) {
304 return false;
305 }
306 if( !setMode(AMBIENT_LIGHT, 0) ) {
307 return false;
308 }
309
310 return true;
311}
312
313/**
314 * @brief Starts the proximity sensor on the APDS-9960
315 *
316 * @param[in] interrupts true to enable hardware external interrupt on proximity
317 * @return True if sensor enabled correctly. False on error.
318 */
319bool SparkFun_APDS9960::enableProximitySensor(bool interrupts)
320{
321 /* Set default gain, LED, interrupts, enable power, and enable sensor */
322 if( !setProximityGain(DEFAULT_PGAIN) ) {
323 return false;
324 }
325 if( !setLEDDrive(DEFAULT_LDRIVE) ) {
326 return false;
327 }
328 if( interrupts ) {
329 if( !setProximityIntEnable(1) ) {
330 return false;
331 }
332 } else {
333 if( !setProximityIntEnable(0) ) {
334 return false;
335 }
336 }
337 if( !enablePower() ){
338 return false;
339 }
340 if( !setMode(APDS9960_PROXIMITY, 1) ) {
341 return false;
342 }
343
344 return true;
345}
346
347/**
348 * @brief Ends the proximity sensor on the APDS-9960
349 *
350 * @return True if sensor disabled correctly. False on error.
351 */
352bool SparkFun_APDS9960::disableProximitySensor()
353{
354 if( !setProximityIntEnable(0) ) {
355 return false;
356 }
357 if( !setMode(APDS9960_PROXIMITY, 0) ) {
358 return false;
359 }
360
361 return true;
362}
363
364/**
365 * @brief Starts the gesture recognition engine on the APDS-9960
366 *
367 * @param[in] interrupts true to enable hardware external interrupt on gesture
368 * @return True if engine enabled correctly. False on error.
369 */
370bool SparkFun_APDS9960::enableGestureSensor(bool interrupts)
371{
372
373 /* Enable gesture mode
374 Set ENABLE to 0 (power off)
375 Set WTIME to 0xFF
376 Set AUX to LED_BOOST_300
377 Enable PON, WEN, PEN, GEN in ENABLE
378 */
379 resetGestureParameters();
380 if( !wireWriteDataByte(APDS9960_WTIME, 0xFF) ) { // 2.78mS
381 return false;
382 }
383 if( !wireWriteDataByte(APDS9960_PPULSE, DEFAULT_GESTURE_PPULSE) ) { // 16us, 10 pulses
384 return false;
385 }
386 //Jon if( !setLEDBoost(LED_BOOST_300) ) {
387 if( !setLEDBoost(LED_BOOST_100) ) {
388 return false;
389 }
390 if( interrupts ) {
391 if( !setGestureIntEnable(1) ) {
392 return false;
393 }
394 } else {
395 if( !setGestureIntEnable(0) ) {
396 return false;
397 }
398 }
399 if( !setGestureMode(1) ) {
400 return false;
401 }
402 if( !enablePower() ){
403 return false;
404 }
405 if( !setMode(WAITING_TIME, 1) ) {
406 return false;
407 }
408 if( !setMode(APDS9960_PROXIMITY, 1) ) {
409 return false;
410 }
411 if( !setMode(APDS9960_GESTURE, 1) ) {
412 return false;
413 }
414
415 return true;
416}
417
418/**
419 * @brief Ends the gesture recognition engine on the APDS-9960
420 *
421 * @return True if engine disabled correctly. False on error.
422 */
423bool SparkFun_APDS9960::disableGestureSensor()
424{
425 resetGestureParameters();
426 if( !setGestureIntEnable(0) ) {
427 return false;
428 }
429 if( !setGestureMode(0) ) {
430 return false;
431 }
432 if( !setMode(APDS9960_GESTURE, 0) ) {
433 return false;
434 }
435
436 return true;
437}
438
439/**
440 * @brief Determines if there is a gesture available for reading
441 *
442 * @return True if gesture available. False otherwise.
443 */
444bool SparkFun_APDS9960::isGestureAvailable()
445{
446 uint8_t val;
447
448 /* Read value from GSTATUS register */
449 if( !wireReadDataByte(APDS9960_GSTATUS, val) ) {
450 return APDS9960_ERROR;
451 }
452
453 /* Shift and mask out GVALID bit */
454 val &= APDS9960_GVALID;
455
456 /* Return true/false based on GVALID bit */
457 if( val == 1) {
458 return true;
459 } else {
460 return false;
461 }
462}
463
464
465
466/**
467 * @brief Processes a gesture event and returns best guessed gesture
468 *
469 * @return Number corresponding to gesture. -1 on error.
470 */
471//Jon int SparkFun_APDS9960::readGesture()
472 int16_t SparkFun_APDS9960::readGesture()
473{
474 uint8_t fifo_level = 0;
475 uint8_t bytes_read = 0;
476 uint8_t fifo_data[128];
477 uint8_t gstatus;
478 //Jon int motion;
479 //Jon int i;
480 uint16_t motion;
481 uint16_t i;
482
483
484 /* Make sure that data is valid, power is on and gesture has been enabled */
485 if( !isGestureAvailable() || !(getMode() & (APDS9960_PON | APDS9960_GEN)) ) {
486 return DIR_NONE;
487 }
488
489
490 /* Keep looping as long as gesture data is valid */
491 while(1) {
492
493
494 /* Wait some time to collect next batch of FIFO data */
495 delay(FIFO_PAUSE_TIME);
496
497 /* Get the contents of the STATUS register. Is data still valid? */
498 if( !wireReadDataByte(APDS9960_GSTATUS, gstatus) ) {
499 return APDS9960_ERROR;
500 }
501
502
503
504
505 /* If we have valid data, read in FIFO */
506 if( (gstatus & APDS9960_GVALID) == APDS9960_GVALID ) {
507
508 /* Read the current FIFO level */
509 if( !wireReadDataByte(APDS9960_GFLVL, fifo_level) ) {
510 return APDS9960_ERROR;
511 }
512
513#ifdef GDEBUG
514 Serial.print(""FIFO Level: "");
515 Serial.println(fifo_level);
516#endif
517
518 /* If there's stuff in the FIFO, read it into our data block */
519 if( fifo_level > 0) {
520 bytes_read = wireReadDataBlock( APDS9960_GFIFO_U,
521 (uint8_t*)fifo_data,
522 (fifo_level * 4) );
523 if( bytes_read == -1 ) {
524 return APDS9960_ERROR;
525 }
526#ifdef GDEBUG
527 Serial.print(""FIFO Dump: "");
528 for ( i = 0; i < bytes_read; i++ ) {
529 Serial.print(fifo_data[i]);
530 Serial.print("" "");
531 }
532 Serial.println();
533#endif
534
535 /* If at least 1 set of data, sort the data into U/D/L/R */
536 if( bytes_read >= 4 ) {
537 for( i = 0; i < bytes_read; i += 4 ) {
538 gesture_data_.u_data[gesture_data_.index] = \\
539 fifo_data[i + 0];
540 gesture_data_.d_data[gesture_data_.index] = \\
541 fifo_data[i + 1];
542 gesture_data_.l_data[gesture_data_.index] = \\
543 fifo_data[i + 2];
544 gesture_data_.r_data[gesture_data_.index] = \\
545 fifo_data[i + 3];
546 gesture_data_.index++;
547 gesture_data_.total_gestures++;
548 }
549
550#ifdef GDEBUG
551 Serial.print(""Up Data: "");
552 for ( i = 0; i < gesture_data_.total_gestures; i++ ) {
553 Serial.print(gesture_data_.u_data[i]);
554 Serial.print("" "");
555 }
556 Serial.println();
557 Serial.print(""Dn Data: "");
558 for ( i = 0; i < gesture_data_.total_gestures; i++ ) {
559 Serial.print(gesture_data_.d_data[i]);
560 Serial.print("" "");
561 }
562 Serial.println();
563 Serial.print(""L Data: "");
564 for ( i = 0; i < gesture_data_.total_gestures; i++ ) {
565 Serial.print(gesture_data_.l_data[i]);
566 Serial.print("" "");
567 }
568 Serial.println();
569 Serial.print(""R Data: "");
570 for ( i = 0; i < gesture_data_.total_gestures; i++ ) {
571 Serial.print(gesture_data_.r_data[i]);
572 Serial.print("" "");
573 }
574 Serial.println();
575#endif
576
577 /* Filter and process gesture data. Decode near/far state */
578 if( processGestureData() ) {
579 if( decodeGesture() ) {
580 //***TODO: U-Turn Gestures
581#ifdef GDEBUG
582 //Serial.println(gesture_motion_);
583#endif
584 }
585 }
586
587 /* Reset data */
588 gesture_data_.index = 0;
589 gesture_data_.total_gestures = 0;
590 }
591 }
592 } else {
593
594 /* Determine best guessed gesture and clean up */
595 delay(FIFO_PAUSE_TIME);
596 decodeGesture();
597 motion = gesture_motion_;
598#ifdef GDEBUG
599 Serial.print(""END: "");
600 Serial.println(gesture_motion_);
601#endif
602 resetGestureParameters();
603 return motion;
604 }
605 }
606}
607
608
609/**
610 * Turn the APDS-9960 on
611 *
612 * @return True if operation successful. False otherwise.
613 */
614bool SparkFun_APDS9960::enablePower()
615{
616 if( !setMode(APDS9960_POWER, APDS9960_ON) ) {
617 return false;
618 }
619
620 return true;
621}
622
623/**
624 * Turn the APDS-9960 off
625 *
626 * @return True if operation successful. False otherwise.
627 */
628bool SparkFun_APDS9960::disablePower()
629{
630 if( !setMode(APDS9960_POWER, APDS9960_OFF) ) {
631 return false;
632 }
633
634 return true;
635}
636
637/*******************************************************************************
638 * Ambient light and color sensor controls
639 ******************************************************************************/
640
641/**
642 * @brief Reads the ambient (clear) light level as a 16-bit value
643 *
644 * @param[out] val value of the light sensor.
645 * @return True if operation successful. False otherwise.
646 */
647bool SparkFun_APDS9960::readAmbientLight(uint16_t &val)
648{
649 uint8_t val_byte;
650 val = 0;
651
652 /* Read value from clear channel, low byte register */
653 if( !wireReadDataByte(APDS9960_CDATAL, val_byte) ) {
654 return false;
655 }
656 val = val_byte;
657
658 /* Read value from clear channel, high byte register */
659 if( !wireReadDataByte(APDS9960_CDATAH, val_byte) ) {
660 return false;
661 }
662 val = val + ((uint16_t)val_byte << 8);
663
664 return true;
665}
666
667/**
668 * @brief Reads the red light level as a 16-bit value
669 *
670 * @param[out] val value of the light sensor.
671 * @return True if operation successful. False otherwise.
672 */
673bool SparkFun_APDS9960::readRedLight(uint16_t &val)
674{
675 uint8_t val_byte;
676 val = 0;
677
678 /* Read value from clear channel, low byte register */
679 if( !wireReadDataByte(APDS9960_RDATAL, val_byte) ) {
680 return false;
681 }
682 val = val_byte;
683
684 /* Read value from clear channel, high byte register */
685 if( !wireReadDataByte(APDS9960_RDATAH, val_byte) ) {
686 return false;
687 }
688 val = val + ((uint16_t)val_byte << 8);
689
690 return true;
691}
692
693/**
694 * @brief Reads the green light level as a 16-bit value
695 *
696 * @param[out] val value of the light sensor.
697 * @return True if operation successful. False otherwise.
698 */
699bool SparkFun_APDS9960::readGreenLight(uint16_t &val)
700{
701 uint8_t val_byte;
702 val = 0;
703
704 /* Read value from clear channel, low byte register */
705 if( !wireReadDataByte(APDS9960_GDATAL, val_byte) ) {
706 return false;
707 }
708 val = val_byte;
709
710 /* Read value from clear channel, high byte register */
711 if( !wireReadDataByte(APDS9960_GDATAH, val_byte) ) {
712 return false;
713 }
714 val = val + ((uint16_t)val_byte << 8);
715
716 return true;
717}
718
719/**
720 * @brief Reads the red light level as a 16-bit value
721 *
722 * @param[out] val value of the light sensor.
723 * @return True if operation successful. False otherwise.
724 */
725bool SparkFun_APDS9960::readBlueLight(uint16_t &val)
726{
727 uint8_t val_byte;
728 val = 0;
729
730 /* Read value from clear channel, low byte register */
731 if( !wireReadDataByte(APDS9960_BDATAL, val_byte) ) {
732 return false;
733 }
734 val = val_byte;
735
736 /* Read value from clear channel, high byte register */
737 if( !wireReadDataByte(APDS9960_BDATAH, val_byte) ) {
738 return false;
739 }
740 val = val + ((uint16_t)val_byte << 8);
741
742 return true;
743}
744
745/*******************************************************************************
746 * Proximity sensor controls
747 ******************************************************************************/
748
749/**
750 * @brief Reads the proximity level as an 8-bit value
751 *
752 * @param[out] val value of the proximity sensor.
753 * @return True if operation successful. False otherwise.
754 */
755bool SparkFun_APDS9960::readProximity(uint8_t &val)
756{
757 val = 0;
758
759 /* Read value from proximity data register */
760 if( !wireReadDataByte(APDS9960_PDATA, val) ) {
761 return false;
762 }
763
764 return true;
765}
766
767/*******************************************************************************
768 * High-level gesture controls
769 ******************************************************************************/
770
771/**
772 * @brief Resets all the parameters in the gesture data member
773 */
774void SparkFun_APDS9960::resetGestureParameters()
775{
776 gesture_data_.index = 0;
777 gesture_data_.total_gestures = 0;
778
779 gesture_ud_delta_ = 0;
780 gesture_lr_delta_ = 0;
781
782 gesture_ud_count_ = 0;
783 gesture_lr_count_ = 0;
784
785 gesture_near_count_ = 0;
786 gesture_far_count_ = 0;
787
788 gesture_state_ = 0;
789 gesture_motion_ = DIR_NONE;
790
791
792}
793
794
795
796/**
797 * @brief Processes the raw gesture data to determine swipe direction
798 *
799 * @return True if near or far state seen. False otherwise.
800 */
801bool SparkFun_APDS9960::processGestureData()
802{
803 uint8_t u_first = 0;
804 uint8_t d_first = 0;
805 uint8_t l_first = 0;
806 uint8_t r_first = 0;
807 uint8_t u_last = 0;
808 uint8_t d_last = 0;
809 uint8_t l_last = 0;
810 uint8_t r_last = 0;
811 /* Jon
812 int ud_ratio_first;
813 int lr_ratio_first;
814 int ud_ratio_last;
815 int lr_ratio_last;
816 int ud_delta;
817 int lr_delta;
818 int i;
819 */
820
821 int16_t ud_ratio_first;
822 int16_t lr_ratio_first;
823 int16_t ud_ratio_last;
824 int16_t lr_ratio_last;
825 int16_t ud_delta;
826 int16_t lr_delta;
827 int16_t i;
828
829 /* If we have less than 4 total gestures, that's not enough */
830 if( gesture_data_.total_gestures <= 4 ) {
831 return false;
832 }
833
834 /* Check to make sure our data isn't out of bounds */
835 if( (gesture_data_.total_gestures <= 32) && \\
836 (gesture_data_.total_gestures > 0) ) {
837
838 /* Find the first value in U/D/L/R above the threshold */
839 for( i = 0; i < gesture_data_.total_gestures; i++ ) {
840 if( (gesture_data_.u_data[i] > GESTURE_THRESHOLD_OUT) &&
841 (gesture_data_.d_data[i] > GESTURE_THRESHOLD_OUT) &&
842 (gesture_data_.l_data[i] > GESTURE_THRESHOLD_OUT) &&
843 (gesture_data_.r_data[i] > GESTURE_THRESHOLD_OUT) ) {
844
845 u_first = gesture_data_.u_data[i];
846 d_first = gesture_data_.d_data[i];
847 l_first = gesture_data_.l_data[i];
848 r_first = gesture_data_.r_data[i];
849 break;
850 }
851 }
852
853 /* If one of the _first values is 0, then there is no good data */
854 if( (u_first == 0) || (d_first == 0) || \\
855 (l_first == 0) || (r_first == 0) ) {
856
857 return false;
858 }
859 /* Find the last value in U/D/L/R above the threshold */
860 for( i = gesture_data_.total_gestures - 1; i >= 0; i-- ) {
861#ifdef DEBUG
862 Serial.print(F(""Finding last: ""));
863 Serial.print(F(""U:""));
864 Serial.print(gesture_data_.u_data[i]);
865 Serial.print(F("" D:""));
866 Serial.print(gesture_data_.d_data[i]);
867 Serial.print(F("" L:""));
868 Serial.print(gesture_data_.l_data[i]);
869 Serial.print(F("" R:""));
870 Serial.println(gesture_data_.r_data[i]);
871#endif
872 if( (gesture_data_.u_data[i] > GESTURE_THRESHOLD_OUT) &&
873 (gesture_data_.d_data[i] > GESTURE_THRESHOLD_OUT) &&
874 (gesture_data_.l_data[i] > GESTURE_THRESHOLD_OUT) &&
875 (gesture_data_.r_data[i] > GESTURE_THRESHOLD_OUT) ) {
876
877 u_last = gesture_data_.u_data[i];
878 d_last = gesture_data_.d_data[i];
879 l_last = gesture_data_.l_data[i];
880 r_last = gesture_data_.r_data[i];
881 break;
882 }
883 }
884 }
885 /* Catch to make sure we don't divide by 0 */
886 if( ((u_first + d_first) == 0) ||
887 ((l_first + r_first) == 0) ||
888 ((u_last + d_last) == 0) ||
889 ((l_last + r_last) == 0) ) {
890
891 return false;
892 }
893
894 /* Calculate the first vs. last ratio of up/down and left/right */
895 ud_ratio_first = ((u_first - d_first) * 100) / (u_first + d_first);
896 lr_ratio_first = ((l_first - r_first) * 100) / (l_first + r_first);
897 ud_ratio_last = ((u_last - d_last) * 100) / (u_last + d_last);
898 lr_ratio_last = ((l_last - r_last) * 100) / (l_last + r_last);
899
900#ifdef DEBUG
901 Serial.print(F(""Last Values: ""));
902 Serial.print(F(""U:""));
903 Serial.print(u_last);
904 Serial.print(F("" D:""));
905 Serial.print(d_last);
906 Serial.print(F("" L:""));
907 Serial.print(l_last);
908 Serial.print(F("" R:""));
909 Serial.println(r_last);
910
911 Serial.print(F(""Ratios: ""));
912 Serial.print(F(""UD Fi: ""));
913 Serial.print(ud_ratio_first);
914 Serial.print(F("" UD La: ""));
915 Serial.print(ud_ratio_last);
916 Serial.print(F("" LR Fi: ""));
917 Serial.print(lr_ratio_first);
918 Serial.print(F("" LR La: ""));
919 Serial.println(lr_ratio_last);
920#endif
921
922 /* Determine the difference between the first and last ratios */
923 ud_delta = ud_ratio_last - ud_ratio_first;
924 lr_delta = lr_ratio_last - lr_ratio_first;
925
926#ifdef DEBUG
927 Serial.print(""Deltas: "");
928 Serial.print(""UD: "");
929 Serial.print(ud_delta);
930 Serial.print("" LR: "");
931 Serial.println(lr_delta);
932#endif
933
934 /* Accumulate the UD and LR delta values */
935 gesture_ud_delta_ += ud_delta;
936 gesture_lr_delta_ += lr_delta;
937
938#ifdef DEBUG
939 Serial.print(""Accumulations: "");
940 Serial.print(""UD: "");
941 Serial.print(gesture_ud_delta_);
942 Serial.print("" LR: "");
943 Serial.println(gesture_lr_delta_);
944#endif
945
946 /* Determine U/D gesture */
947 if( gesture_ud_delta_ >= GESTURE_SENSITIVITY_1 ) {
948 gesture_ud_count_ = 1;
949 } else if( gesture_ud_delta_ <= -GESTURE_SENSITIVITY_1 ) {
950 gesture_ud_count_ = -1;
951 } else {
952 gesture_ud_count_ = 0;
953 }
954
955 /* Determine L/R gesture */
956 if( gesture_lr_delta_ >= GESTURE_SENSITIVITY_1 ) {
957 gesture_lr_count_ = 1;
958 } else if( gesture_lr_delta_ <= -GESTURE_SENSITIVITY_1 ) {
959 gesture_lr_count_ = -1;
960 } else {
961 gesture_lr_count_ = 0;
962 }
963
964 /* Determine Near/Far gesture */
965 if( (gesture_ud_count_ == 0) && (gesture_lr_count_ == 0) ) {
966 if( (abs(ud_delta) < GESTURE_SENSITIVITY_2) && \\
967 (abs(lr_delta) < GESTURE_SENSITIVITY_2) ) {
968
969 if( (ud_delta == 0) && (lr_delta == 0) ) {
970 gesture_near_count_++;
971 } else if( (ud_delta != 0) || (lr_delta != 0) ) {
972 gesture_far_count_++;
973 }
974
975 if( (gesture_near_count_ >= 10) && (gesture_far_count_ >= 2) ) {
976 if( (ud_delta == 0) && (lr_delta == 0) ) {
977 gesture_state_ = NEAR_STATE;
978 } else if( (ud_delta != 0) && (lr_delta != 0) ) {
979 gesture_state_ = FAR_STATE;
980 }
981 return true;
982 }
983 }
984 } else {
985 if( (abs(ud_delta) < GESTURE_SENSITIVITY_2) && \\
986 (abs(lr_delta) < GESTURE_SENSITIVITY_2) ) {
987
988 if( (ud_delta == 0) && (lr_delta == 0) ) {
989 gesture_near_count_++;
990 }
991
992 if( gesture_near_count_ >= 10 ) {
993 gesture_ud_count_ = 0;
994 gesture_lr_count_ = 0;
995 gesture_ud_delta_ = 0;
996 gesture_lr_delta_ = 0;
997 }
998 }
999 }
1000
1001#ifdef DEBUG
1002 Serial.print(""UD_CT: "");
1003 Serial.print(gesture_ud_count_);
1004 Serial.print("" LR_CT: "");
1005 Serial.print(gesture_lr_count_);
1006 Serial.print("" NEAR_CT: "");
1007 Serial.print(gesture_near_count_);
1008 Serial.print("" FAR_CT: "");
1009 Serial.println(gesture_far_count_);
1010 Serial.println(""----------"");
1011#endif
1012
1013 return false;
1014}
1015
1016/**
1017 * @brief Determines swipe direction or near/far state
1018 *
1019 * @return True if near/far event. False otherwise.
1020 */
1021bool SparkFun_APDS9960::decodeGesture()
1022{
1023 /* Return if near or far event is detected */
1024 if( gesture_state_ == NEAR_STATE ) {
1025 gesture_motion_ = DIR_NEAR;
1026 return true;
1027 } else if ( gesture_state_ == FAR_STATE ) {
1028 gesture_motion_ = DIR_FAR;
1029 return true;
1030 }
1031
1032 /* Determine swipe direction */
1033 if( (gesture_ud_count_ == -1) && (gesture_lr_count_ == 0) ) {
1034 gesture_motion_ = DIR_UP;
1035 } else if( (gesture_ud_count_ == 1) && (gesture_lr_count_ == 0) ) {
1036 gesture_motion_ = DIR_DOWN;
1037 } else if( (gesture_ud_count_ == 0) && (gesture_lr_count_ == 1) ) {
1038 gesture_motion_ = DIR_RIGHT;
1039 } else if( (gesture_ud_count_ == 0) && (gesture_lr_count_ == -1) ) {
1040 gesture_motion_ = DIR_LEFT;
1041 } else if( (gesture_ud_count_ == -1) && (gesture_lr_count_ == 1) ) {
1042 if( abs(gesture_ud_delta_) > abs(gesture_lr_delta_) ) {
1043 gesture_motion_ = DIR_UP;
1044 } else {
1045 gesture_motion_ = DIR_RIGHT;
1046 }
1047 } else if( (gesture_ud_count_ == 1) && (gesture_lr_count_ == -1) ) {
1048 if( abs(gesture_ud_delta_) > abs(gesture_lr_delta_) ) {
1049 gesture_motion_ = DIR_DOWN;
1050 } else {
1051 gesture_motion_ = DIR_LEFT;
1052 }
1053 } else if( (gesture_ud_count_ == -1) && (gesture_lr_count_ == -1) ) {
1054 if( abs(gesture_ud_delta_) > abs(gesture_lr_delta_) ) {
1055 gesture_motion_ = DIR_UP;
1056 } else {
1057 gesture_motion_ = DIR_LEFT;
1058 }
1059 } else if( (gesture_ud_count_ == 1) && (gesture_lr_count_ == 1) ) {
1060 if( abs(gesture_ud_delta_) > abs(gesture_lr_delta_) ) {
1061 gesture_motion_ = DIR_DOWN;
1062 } else {
1063 gesture_motion_ = DIR_RIGHT;
1064 }
1065 } else {
1066 return false;
1067 }
1068
1069 return true;
1070}
1071
1072/*******************************************************************************
1073 * Getters and setters for register values
1074 ******************************************************************************/
1075
1076/**
1077 * @brief Returns the lower threshold for proximity detection
1078 *
1079 * @return lower threshold
1080 */
1081uint8_t SparkFun_APDS9960::getProxIntLowThresh()
1082{
1083 uint8_t val;
1084
1085 /* Read value from PILT register */
1086 if( !wireReadDataByte(APDS9960_PILT, val) ) {
1087 val = 0;
1088 }
1089
1090 return val;
1091}
1092
1093/**
1094 * @brief Sets the lower threshold for proximity detection
1095 *
1096 * @param[in] threshold the lower proximity threshold
1097 * @return True if operation successful. False otherwise.
1098 */
1099bool SparkFun_APDS9960::setProxIntLowThresh(uint8_t threshold)
1100{
1101 if( !wireWriteDataByte(APDS9960_PILT, threshold) ) {
1102 return false;
1103 }
1104
1105 return true;
1106}
1107
1108/**
1109 * @brief Returns the high threshold for proximity detection
1110 *
1111 * @return high threshold
1112 */
1113uint8_t SparkFun_APDS9960::getProxIntHighThresh()
1114{
1115 uint8_t val;
1116
1117 /* Read value from PIHT register */
1118 if( !wireReadDataByte(APDS9960_PIHT, val) ) {
1119 val = 0;
1120 }
1121
1122 return val;
1123}
1124
1125/**
1126 * @brief Sets the high threshold for proximity detection
1127 *
1128 * @param[in] threshold the high proximity threshold
1129 * @return True if operation successful. False otherwise.
1130 */
1131bool SparkFun_APDS9960::setProxIntHighThresh(uint8_t threshold)
1132{
1133 if( !wireWriteDataByte(APDS9960_PIHT, threshold) ) {
1134 return false;
1135 }
1136
1137 return true;
1138}
1139
1140/**
1141 * @brief Returns LED drive strength for proximity and ALS
1142 *
1143 * Value LED Current
1144 * 0 100 mA
1145 * 1 50 mA
1146 * 2 25 mA
1147 * 3 12.5 mA
1148 *
1149 * @return the value of the LED drive strength. 0xFF on failure.
1150 */
1151uint8_t SparkFun_APDS9960::getLEDDrive()
1152{
1153 uint8_t val;
1154
1155 /* Read value from CONTROL register */
1156 if( !wireReadDataByte(APDS9960_CONTROL, val) ) {
1157 return APDS9960_ERROR;
1158 }
1159
1160 /* Shift and mask out LED drive bits */
1161 val = (val >> 6) & 0b00000011;
1162
1163 return val;
1164}
1165
1166/**
1167 * @brief Sets the LED drive strength for proximity and ALS
1168 *
1169 * Value LED Current
1170 * 0 100 mA
1171 * 1 50 mA
1172 * 2 25 mA
1173 * 3 12.5 mA
1174 *
1175 * @param[in] drive the value (0-3) for the LED drive strength
1176 * @return True if operation successful. False otherwise.
1177 */
1178bool SparkFun_APDS9960::setLEDDrive(uint8_t drive)
1179{
1180 uint8_t val;
1181
1182 /* Read value from CONTROL register */
1183 if( !wireReadDataByte(APDS9960_CONTROL, val) ) {
1184 return false;
1185 }
1186
1187 /* Set bits in register to given value */
1188 drive &= 0b00000011;
1189 drive = drive << 6;
1190 val &= 0b00111111;
1191 val |= drive;
1192
1193 /* Write register value back into CONTROL register */
1194 if( !wireWriteDataByte(APDS9960_CONTROL, val) ) {
1195 return false;
1196 }
1197
1198 return true;
1199}
1200
