APDS9930.cpp 26 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147
  1. /**
  2. * @file APDS-9930.cpp
  3. * @brief Library for the SparkFun APDS-9930 breakout board
  4. * @author Shawn Hymel (SparkFun Electronics)
  5. *
  6. * @copyright This code is public domain but you buy me a beer if you use
  7. * this and we meet someday (Beerware license).
  8. *
  9. * This library interfaces the Avago APDS-9930 to Arduino over I2C. The library
  10. * relies on the Arduino Wire (I2C) library. to use the library, instantiate an
  11. * APDS9930 object, call init(), and call the appropriate functions.
  12. *
  13. * APDS-9930 current draw tests (default parameters):
  14. * Off: 1mA
  15. * Waiting for gesture: 14mA
  16. * Gesture in progress: 35mA
  17. */
  18. #include <Arduino.h>
  19. #include <Wire.h>
  20. #include "APDS9930.h"
  21. /**
  22. * @brief Constructor - Instantiates APDS9930 object
  23. */
  24. APDS9930::APDS9930()
  25. {
  26. }
  27. /**
  28. * @brief Destructor
  29. */
  30. APDS9930::~APDS9930()
  31. {
  32. }
  33. /**
  34. * @brief Configures I2C communications and initializes registers to defaults
  35. *
  36. * @return True if initialized successfully. False otherwise.
  37. */
  38. bool APDS9930::init()
  39. {
  40. uint8_t id;
  41. /* Initialize I2C */
  42. Wire.begin();
  43. /* Read ID register and check against known values for APDS-9930 */
  44. if( !wireReadDataByte(APDS9930_ID, id) ) {
  45. Serial.println(F("ID read"));
  46. return false;
  47. }
  48. if( !(id == APDS9930_ID_1 || id == APDS9930_ID_2) ) {
  49. Serial.println(F("ID check"));
  50. Serial.println(String("ID is ") + String(id, HEX));
  51. //return false;
  52. }
  53. /* Set ENABLE register to 0 (disable all features) */
  54. if( !setMode(ALL, OFF) ) {
  55. Serial.println(F("Regs off"));
  56. return false;
  57. }
  58. /* Set default values for ambient light and proximity registers */
  59. if( !wireWriteDataByte(APDS9930_ATIME, DEFAULT_ATIME) ) {
  60. return false;
  61. }
  62. if( !wireWriteDataByte(APDS9930_WTIME, DEFAULT_WTIME) ) {
  63. return false;
  64. }
  65. if( !wireWriteDataByte(APDS9930_PPULSE, DEFAULT_PPULSE) ) {
  66. return false;
  67. }
  68. if( !wireWriteDataByte(APDS9930_POFFSET, DEFAULT_POFFSET) ) {
  69. return false;
  70. }
  71. if( !wireWriteDataByte(APDS9930_CONFIG, DEFAULT_CONFIG) ) {
  72. return false;
  73. }
  74. if( !setLEDDrive(DEFAULT_PDRIVE) ) {
  75. return false;
  76. }
  77. if( !setProximityGain(DEFAULT_PGAIN) ) {
  78. return false;
  79. }
  80. if( !setAmbientLightGain(DEFAULT_AGAIN) ) {
  81. return false;
  82. }
  83. if( !setProximityDiode(DEFAULT_PDIODE) ) {
  84. return false;
  85. }
  86. if( !setProximityIntLowThreshold(DEFAULT_PILT) ) {
  87. return false;
  88. }
  89. if( !setProximityIntHighThreshold(DEFAULT_PIHT) ) {
  90. return false;
  91. }
  92. if( !setLightIntLowThreshold(DEFAULT_AILT) ) {
  93. return false;
  94. }
  95. if( !setLightIntHighThreshold(DEFAULT_AIHT) ) {
  96. return false;
  97. }
  98. if( !wireWriteDataByte(APDS9930_PERS, DEFAULT_PERS) ) {
  99. return false;
  100. }
  101. return true;
  102. }
  103. /*******************************************************************************
  104. * Public methods for controlling the APDS-9930
  105. ******************************************************************************/
  106. /**
  107. * @brief Reads and returns the contents of the ENABLE register
  108. *
  109. * @return Contents of the ENABLE register. 0xFF if error.
  110. */
  111. uint8_t APDS9930::getMode()
  112. {
  113. uint8_t enable_value;
  114. /* Read current ENABLE register */
  115. if( !wireReadDataByte(APDS9930_ENABLE, enable_value) ) {
  116. return ERROR;
  117. }
  118. return enable_value;
  119. }
  120. /**
  121. * @brief Enables or disables a feature in the APDS-9930
  122. *
  123. * @param[in] mode which feature to enable
  124. * @param[in] enable ON (1) or OFF (0)
  125. * @return True if operation success. False otherwise.
  126. */
  127. bool APDS9930::setMode(uint8_t mode, uint8_t enable)
  128. {
  129. uint8_t reg_val;
  130. /* Read current ENABLE register */
  131. reg_val = getMode();
  132. if( reg_val == ERROR ) {
  133. return false;
  134. }
  135. /* Change bit(s) in ENABLE register */
  136. enable = enable & 0x01;
  137. if( mode >= 0 && mode <= 6 ) {
  138. if (enable) {
  139. reg_val |= (1 << mode);
  140. } else {
  141. reg_val &= ~(1 << mode);
  142. }
  143. } else if( mode == ALL ) {
  144. if (enable) {
  145. reg_val = 0x7F;
  146. } else {
  147. reg_val = 0x00;
  148. }
  149. }
  150. /* Write value back to ENABLE register */
  151. if( !wireWriteDataByte(APDS9930_ENABLE, reg_val) ) {
  152. return false;
  153. }
  154. return true;
  155. }
  156. /**
  157. * @brief Starts the light (Ambient/IR) sensor on the APDS-9930
  158. *
  159. * @param[in] interrupts true to enable hardware interrupt on high or low light
  160. * @return True if sensor enabled correctly. False on error.
  161. */
  162. bool APDS9930::enableLightSensor(bool interrupts)
  163. {
  164. /* Set default gain, interrupts, enable power, and enable sensor */
  165. if( !setAmbientLightGain(DEFAULT_AGAIN) ) {
  166. return false;
  167. }
  168. if( interrupts ) {
  169. if( !setAmbientLightIntEnable(1) ) {
  170. return false;
  171. }
  172. } else {
  173. if( !setAmbientLightIntEnable(0) ) {
  174. return false;
  175. }
  176. }
  177. if( !enablePower() ){
  178. return false;
  179. }
  180. if( !setMode(AMBIENT_LIGHT, 1) ) {
  181. return false;
  182. }
  183. return true;
  184. }
  185. /**
  186. * @brief Ends the light sensor on the APDS-9930
  187. *
  188. * @return True if sensor disabled correctly. False on error.
  189. */
  190. bool APDS9930::disableLightSensor()
  191. {
  192. if( !setAmbientLightIntEnable(0) ) {
  193. return false;
  194. }
  195. if( !setMode(AMBIENT_LIGHT, 0) ) {
  196. return false;
  197. }
  198. return true;
  199. }
  200. /**
  201. * @brief Starts the proximity sensor on the APDS-9930
  202. *
  203. * @param[in] interrupts true to enable hardware external interrupt on proximity
  204. * @return True if sensor enabled correctly. False on error.
  205. */
  206. bool APDS9930::enableProximitySensor(bool interrupts)
  207. {
  208. /* Set default gain, LED, interrupts, enable power, and enable sensor */
  209. if( !setProximityGain(DEFAULT_PGAIN) ) {
  210. return false;
  211. }
  212. if( !setLEDDrive(DEFAULT_PDRIVE) ) {
  213. return false;
  214. }
  215. if( interrupts ) {
  216. if( !setProximityIntEnable(1) ) {
  217. return false;
  218. }
  219. } else {
  220. if( !setProximityIntEnable(0) ) {
  221. return false;
  222. }
  223. }
  224. if( !enablePower() ){
  225. return false;
  226. }
  227. if( !setMode(PROXIMITY, 1) ) {
  228. return false;
  229. }
  230. return true;
  231. }
  232. /**
  233. * @brief Ends the proximity sensor on the APDS-9930
  234. *
  235. * @return True if sensor disabled correctly. False on error.
  236. */
  237. bool APDS9930::disableProximitySensor()
  238. {
  239. if( !setProximityIntEnable(0) ) {
  240. return false;
  241. }
  242. if( !setMode(PROXIMITY, 0) ) {
  243. return false;
  244. }
  245. return true;
  246. }
  247. /**
  248. * Turn the APDS-9930 on
  249. *
  250. * @return True if operation successful. False otherwise.
  251. */
  252. bool APDS9930::enablePower()
  253. {
  254. if( !setMode(POWER, 1) ) {
  255. return false;
  256. }
  257. return true;
  258. }
  259. /**
  260. * Turn the APDS-9930 off
  261. *
  262. * @return True if operation successful. False otherwise.
  263. */
  264. bool APDS9930::disablePower()
  265. {
  266. if( !setMode(POWER, 0) ) {
  267. return false;
  268. }
  269. return true;
  270. }
  271. /*******************************************************************************
  272. * Ambient light sensor controls
  273. ******************************************************************************/
  274. /**
  275. * @brief Reads the ambient (clear) light level as a 16-bit value
  276. *
  277. * @param[out] val value of the light sensor.
  278. * @return True if operation successful. False otherwise.
  279. */
  280. bool APDS9930::readAmbientLightLux(float &val)
  281. {
  282. uint16_t Ch0;
  283. uint16_t Ch1;
  284. /* Read value from channel 0 */
  285. if( !readCh0Light(Ch0) ) {
  286. return false;
  287. }
  288. /* Read value from channel 1 */
  289. if( !readCh1Light(Ch1) ) {
  290. return false;
  291. }
  292. val = floatAmbientToLux(Ch0, Ch1);
  293. return true;
  294. }
  295. bool APDS9930::readAmbientLightLux(unsigned long &val)
  296. {
  297. uint16_t Ch0;
  298. uint16_t Ch1;
  299. /* Read value from channel 0 */
  300. if( !readCh0Light(Ch0) ) {
  301. return false;
  302. }
  303. /* Read value from channel 1 */
  304. if( !readCh1Light(Ch1) ) {
  305. return false;
  306. }
  307. val = ulongAmbientToLux(Ch0, Ch1);
  308. return true;
  309. }
  310. float APDS9930::floatAmbientToLux(uint16_t Ch0, uint16_t Ch1)
  311. {
  312. uint8_t x[4]={1,8,16,120};
  313. float ALSIT = 2.73 * (256 - DEFAULT_ATIME);
  314. float iac = max(Ch0 - ALS_B * Ch1, ALS_C * Ch0 - ALS_D * Ch1);
  315. if (iac < 0) iac = 0;
  316. float lpc = GA * DF / (ALSIT * x[getAmbientLightGain()]);
  317. return iac * lpc;
  318. }
  319. unsigned long APDS9930::ulongAmbientToLux(uint16_t Ch0, uint16_t Ch1)
  320. {
  321. uint8_t x[4]={1,8,16,120};
  322. unsigned long ALSIT = 2.73 * (256 - DEFAULT_ATIME);
  323. unsigned long iac = max(Ch0 - ALS_B * Ch1, ALS_C * Ch0 - ALS_D * Ch1);
  324. if (iac < 0) iac = 0;
  325. unsigned long lpc = GA * DF / (ALSIT * x[getAmbientLightGain()]);
  326. return iac * lpc;
  327. }
  328. bool APDS9930::readCh0Light(uint16_t &val)
  329. {
  330. uint8_t val_byte;
  331. val = 0;
  332. /* Read value from channel 0 */
  333. if( !wireReadDataByte(APDS9930_Ch0DATAL, val_byte) ) {
  334. return false;
  335. }
  336. val = val_byte;
  337. if( !wireReadDataByte(APDS9930_Ch0DATAH, val_byte) ) {
  338. return false;
  339. }
  340. val += ((uint16_t)val_byte << 8);
  341. return true;
  342. }
  343. bool APDS9930::readCh1Light(uint16_t &val)
  344. {
  345. uint8_t val_byte;
  346. val = 0;
  347. /* Read value from channel 0 */
  348. if( !wireReadDataByte(APDS9930_Ch1DATAL, val_byte) ) {
  349. return false;
  350. }
  351. val = val_byte;
  352. if( !wireReadDataByte(APDS9930_Ch1DATAH, val_byte) ) {
  353. return false;
  354. }
  355. val += ((uint16_t)val_byte << 8);
  356. return true;
  357. }
  358. /*******************************************************************************
  359. * Proximity sensor controls
  360. ******************************************************************************/
  361. /**
  362. * @brief Reads the proximity level as an 8-bit value
  363. *
  364. * @param[out] val value of the proximity sensor.
  365. * @return True if operation successful. False otherwise.
  366. */
  367. bool APDS9930::readProximity(uint16_t &val)
  368. {
  369. val = 0;
  370. uint8_t val_byte;
  371. /* Read value from proximity data register */
  372. if( !wireReadDataByte(APDS9930_PDATAL, val_byte) ) {
  373. return false;
  374. }
  375. val = val_byte;
  376. if( !wireReadDataByte(APDS9930_PDATAH, val_byte) ) {
  377. return false;
  378. }
  379. val += ((uint16_t)val_byte << 8);
  380. return true;
  381. }
  382. /*******************************************************************************
  383. * Getters and setters for register values
  384. ******************************************************************************/
  385. /**
  386. * @brief Returns the lower threshold for proximity detection
  387. *
  388. * @return lower threshold
  389. */
  390. uint16_t APDS9930::getProximityIntLowThreshold()
  391. {
  392. uint16_t val;
  393. uint8_t val_byte;
  394. /* Read value from PILT register */
  395. if( !wireReadDataByte(APDS9930_PILTL, val_byte) ) {
  396. val = 0;
  397. }
  398. val = val_byte;
  399. if( !wireReadDataByte(APDS9930_PILTH, val_byte) ) {
  400. val = 0;
  401. }
  402. val |= ((uint16_t)val_byte << 8);
  403. return val;
  404. }
  405. /**
  406. * @brief Sets the lower threshold for proximity detection
  407. *
  408. * @param[in] threshold the lower proximity threshold
  409. * @return True if operation successful. False otherwise.
  410. */
  411. bool APDS9930::setProximityIntLowThreshold(uint16_t threshold)
  412. {
  413. uint8_t lo;
  414. uint8_t hi;
  415. hi = threshold >> 8;
  416. lo = threshold & 0x00FF;
  417. if( !wireWriteDataByte(APDS9930_PILTL, lo) ) {
  418. return false;
  419. }
  420. if( !wireWriteDataByte(APDS9930_PILTH, hi) ) {
  421. return false;
  422. }
  423. return true;
  424. }
  425. /**
  426. * @brief Returns the high threshold for proximity detection
  427. *
  428. * @return high threshold
  429. */
  430. uint16_t APDS9930::getProximityIntHighThreshold()
  431. {
  432. uint16_t val;
  433. uint8_t val_byte;
  434. /* Read value from PILT register */
  435. if( !wireReadDataByte(APDS9930_PIHTL, val_byte) ) {
  436. val = 0;
  437. }
  438. val = val_byte;
  439. if( !wireReadDataByte(APDS9930_PIHTH, val_byte) ) {
  440. val = 0;
  441. }
  442. val |= ((uint16_t)val_byte << 8);
  443. return val;
  444. }
  445. /**
  446. * @brief Sets the high threshold for proximity detection
  447. *
  448. * @param[in] threshold the high proximity threshold
  449. * @return True if operation successful. False otherwise.
  450. */
  451. bool APDS9930::setProximityIntHighThreshold(uint16_t threshold)
  452. {
  453. uint8_t lo;
  454. uint8_t hi;
  455. hi = threshold >> 8;
  456. lo = threshold & 0x00FF;
  457. if( !wireWriteDataByte(APDS9930_PIHTL, lo) ) {
  458. return false;
  459. }
  460. if( !wireWriteDataByte(APDS9930_PIHTH, hi) ) {
  461. return false;
  462. }
  463. return true;
  464. }
  465. /**
  466. * @brief Returns LED drive strength for proximity and ALS
  467. *
  468. * Value LED Current
  469. * 0 100 mA
  470. * 1 50 mA
  471. * 2 25 mA
  472. * 3 12.5 mA
  473. *
  474. * @return the value of the LED drive strength. 0xFF on failure.
  475. */
  476. uint8_t APDS9930::getLEDDrive()
  477. {
  478. uint8_t val;
  479. /* Read value from CONTROL register */
  480. if( !wireReadDataByte(APDS9930_CONTROL, val) ) {
  481. return ERROR;
  482. }
  483. /* Shift and mask out LED drive bits */
  484. val = (val >> 6) & 0b00000011;
  485. return val;
  486. }
  487. /**
  488. * @brief Sets the LED drive strength for proximity and ALS
  489. *
  490. * Value LED Current
  491. * 0 100 mA
  492. * 1 50 mA
  493. * 2 25 mA
  494. * 3 12.5 mA
  495. *
  496. * @param[in] drive the value (0-3) for the LED drive strength
  497. * @return True if operation successful. False otherwise.
  498. */
  499. bool APDS9930::setLEDDrive(uint8_t drive)
  500. {
  501. uint8_t val;
  502. /* Read value from CONTROL register */
  503. if( !wireReadDataByte(APDS9930_CONTROL, val) ) {
  504. return false;
  505. }
  506. /* Set bits in register to given value */
  507. drive &= 0b00000011;
  508. drive = drive << 6;
  509. val &= 0b00111111;
  510. val |= drive;
  511. /* Write register value back into CONTROL register */
  512. if( !wireWriteDataByte(APDS9930_CONTROL, val) ) {
  513. return false;
  514. }
  515. return true;
  516. }
  517. /**
  518. * @brief Returns receiver gain for proximity detection
  519. *
  520. * Value Gain
  521. * 0 1x
  522. * 1 2x
  523. * 2 4x
  524. * 3 8x
  525. *
  526. * @return the value of the proximity gain. 0xFF on failure.
  527. */
  528. uint8_t APDS9930::getProximityGain()
  529. {
  530. uint8_t val;
  531. /* Read value from CONTROL register */
  532. if( !wireReadDataByte(APDS9930_CONTROL, val) ) {
  533. return ERROR;
  534. }
  535. /* Shift and mask out PDRIVE bits */
  536. val = (val >> 2) & 0b00000011;
  537. return val;
  538. }
  539. /**
  540. * @brief Sets the receiver gain for proximity detection
  541. *
  542. * Value Gain
  543. * 0 1x
  544. * 1 2x
  545. * 2 4x
  546. * 3 8x
  547. *
  548. * @param[in] drive the value (0-3) for the gain
  549. * @return True if operation successful. False otherwise.
  550. */
  551. bool APDS9930::setProximityGain(uint8_t drive)
  552. {
  553. uint8_t val;
  554. /* Read value from CONTROL register */
  555. if( !wireReadDataByte(APDS9930_CONTROL, val) ) {
  556. return false;
  557. }
  558. /* Set bits in register to given value */
  559. drive &= 0b00000011;
  560. drive = drive << 2;
  561. val &= 0b11110011;
  562. val |= drive;
  563. /* Write register value back into CONTROL register */
  564. if( !wireWriteDataByte(APDS9930_CONTROL, val) ) {
  565. return false;
  566. }
  567. return true;
  568. }
  569. /**
  570. * @brief Returns the proximity diode
  571. *
  572. * Value Diode selection
  573. * 0 Reserved
  574. * 1 Reserved
  575. * 2 Use Ch1 diode
  576. * 3 Reserved
  577. *
  578. * @return the selected diode. 0xFF on failure.
  579. */
  580. uint8_t APDS9930::getProximityDiode()
  581. {
  582. uint8_t val;
  583. /* Read value from CONTROL register */
  584. if( !wireReadDataByte(APDS9930_CONTROL, val) ) {
  585. return ERROR;
  586. }
  587. /* Shift and mask out PDRIVE bits */
  588. val = (val >> 4) & 0b00000011;
  589. return val;
  590. }
  591. /**
  592. * @brief Selects the proximity diode
  593. *
  594. * Value Diode selection
  595. * 0 Reserved
  596. * 1 Reserved
  597. * 2 Use Ch1 diode
  598. * 3 Reserved
  599. *
  600. * @param[in] drive the value (0-3) for the diode
  601. * @return True if operation successful. False otherwise.
  602. */
  603. bool APDS9930::setProximityDiode(uint8_t drive)
  604. {
  605. uint8_t val;
  606. /* Read value from CONTROL register */
  607. if( !wireReadDataByte(APDS9930_CONTROL, val) ) {
  608. return false;
  609. }
  610. /* Set bits in register to given value */
  611. drive &= 0b00000011;
  612. drive = drive << 4;
  613. val &= 0b11001111;
  614. val |= drive;
  615. /* Write register value back into CONTROL register */
  616. if( !wireWriteDataByte(APDS9930_CONTROL, val) ) {
  617. return false;
  618. }
  619. return true;
  620. }
  621. /**
  622. * @brief Returns receiver gain for the ambient light sensor (ALS)
  623. *
  624. * Value Gain
  625. * 0 1x
  626. * 1 4x
  627. * 2 16x
  628. * 3 120x
  629. *
  630. * @return the value of the ALS gain. 0xFF on failure.
  631. */
  632. uint8_t APDS9930::getAmbientLightGain()
  633. {
  634. uint8_t val;
  635. /* Read value from CONTROL register */
  636. if( !wireReadDataByte(APDS9930_CONTROL, val) ) {
  637. return ERROR;
  638. }
  639. /* Shift and mask out ADRIVE bits */
  640. val &= 0b00000011;
  641. return val;
  642. }
  643. /**
  644. * @brief Sets the receiver gain for the ambient light sensor (ALS)
  645. *
  646. * Value Gain
  647. * 0 1x
  648. * 1 4x
  649. * 2 16x
  650. * 3 64x
  651. *
  652. * @param[in] drive the value (0-3) for the gain
  653. * @return True if operation successful. False otherwise.
  654. */
  655. bool APDS9930::setAmbientLightGain(uint8_t drive)
  656. {
  657. uint8_t val;
  658. /* Read value from CONTROL register */
  659. if( !wireReadDataByte(APDS9930_CONTROL, val) ) {
  660. return false;
  661. }
  662. /* Set bits in register to given value */
  663. drive &= 0b00000011;
  664. val &= 0b11111100;
  665. val |= drive;
  666. /* Write register value back into CONTROL register */
  667. if( !wireWriteDataByte(APDS9930_CONTROL, val) ) {
  668. return false;
  669. }
  670. return true;
  671. }
  672. /**
  673. * @brief Gets the low threshold for ambient light interrupts
  674. *
  675. * @param[out] threshold current low threshold stored on the APDS-9930
  676. * @return True if operation successful. False otherwise.
  677. */
  678. bool APDS9930::getLightIntLowThreshold(uint16_t &threshold)
  679. {
  680. uint8_t val_byte;
  681. threshold = 0;
  682. /* Read value from ambient light low threshold, low byte register */
  683. if( !wireReadDataByte(APDS9930_AILTL, val_byte) ) {
  684. return false;
  685. }
  686. threshold = val_byte;
  687. /* Read value from ambient light low threshold, high byte register */
  688. if( !wireReadDataByte(APDS9930_AILTH, val_byte) ) {
  689. return false;
  690. }
  691. threshold = threshold + ((uint16_t)val_byte << 8);
  692. return true;
  693. }
  694. /**
  695. * @brief Sets the low threshold for ambient light interrupts
  696. *
  697. * @param[in] threshold low threshold value for interrupt to trigger
  698. * @return True if operation successful. False otherwise.
  699. */
  700. bool APDS9930::setLightIntLowThreshold(uint16_t threshold)
  701. {
  702. uint8_t val_low;
  703. uint8_t val_high;
  704. /* Break 16-bit threshold into 2 8-bit values */
  705. val_low = threshold & 0x00FF;
  706. val_high = (threshold & 0xFF00) >> 8;
  707. /* Write low byte */
  708. if( !wireWriteDataByte(APDS9930_AILTL, val_low) ) {
  709. return false;
  710. }
  711. /* Write high byte */
  712. if( !wireWriteDataByte(APDS9930_AILTH, val_high) ) {
  713. return false;
  714. }
  715. return true;
  716. }
  717. /**
  718. * @brief Gets the high threshold for ambient light interrupts
  719. *
  720. * @param[out] threshold current low threshold stored on the APDS-9930
  721. * @return True if operation successful. False otherwise.
  722. */
  723. bool APDS9930::getLightIntHighThreshold(uint16_t &threshold)
  724. {
  725. uint8_t val_byte;
  726. threshold = 0;
  727. /* Read value from ambient light high threshold, low byte register */
  728. if( !wireReadDataByte(APDS9930_AIHTL, val_byte) ) {
  729. return false;
  730. }
  731. threshold = val_byte;
  732. /* Read value from ambient light high threshold, high byte register */
  733. if( !wireReadDataByte(APDS9930_AIHTH, val_byte) ) {
  734. return false;
  735. }
  736. threshold = threshold + ((uint16_t)val_byte << 8);
  737. return true;
  738. }
  739. /**
  740. * @brief Sets the high threshold for ambient light interrupts
  741. *
  742. * @param[in] threshold high threshold value for interrupt to trigger
  743. * @return True if operation successful. False otherwise.
  744. */
  745. bool APDS9930::setLightIntHighThreshold(uint16_t threshold)
  746. {
  747. uint8_t val_low;
  748. uint8_t val_high;
  749. /* Break 16-bit threshold into 2 8-bit values */
  750. val_low = threshold & 0x00FF;
  751. val_high = (threshold & 0xFF00) >> 8;
  752. /* Write low byte */
  753. if( !wireWriteDataByte(APDS9930_AIHTL, val_low) ) {
  754. return false;
  755. }
  756. /* Write high byte */
  757. if( !wireWriteDataByte(APDS9930_AIHTH, val_high) ) {
  758. return false;
  759. }
  760. return true;
  761. }
  762. /**
  763. * @brief Gets if ambient light interrupts are enabled or not
  764. *
  765. * @return 1 if interrupts are enabled, 0 if not. 0xFF on error.
  766. */
  767. uint8_t APDS9930::getAmbientLightIntEnable()
  768. {
  769. uint8_t val;
  770. /* Read value from ENABLE register */
  771. if( !wireReadDataByte(APDS9930_ENABLE, val) ) {
  772. return ERROR;
  773. }
  774. /* Shift and mask out AIEN bit */
  775. val = (val >> 4) & 0b00000001;
  776. return val;
  777. }
  778. /**
  779. * @brief Turns ambient light interrupts on or off
  780. *
  781. * @param[in] enable 1 to enable interrupts, 0 to turn them off
  782. * @return True if operation successful. False otherwise.
  783. */
  784. bool APDS9930::setAmbientLightIntEnable(uint8_t enable)
  785. {
  786. uint8_t val;
  787. /* Read value from ENABLE register */
  788. if( !wireReadDataByte(APDS9930_ENABLE, val) ) {
  789. return false;
  790. }
  791. /* Set bits in register to given value */
  792. enable &= 0b00000001;
  793. enable = enable << 4;
  794. val &= 0b11101111;
  795. val |= enable;
  796. /* Write register value back into ENABLE register */
  797. if( !wireWriteDataByte(APDS9930_ENABLE, val) ) {
  798. return false;
  799. }
  800. return true;
  801. }
  802. /**
  803. * @brief Gets if proximity interrupts are enabled or not
  804. *
  805. * @return 1 if interrupts are enabled, 0 if not. 0xFF on error.
  806. */
  807. uint8_t APDS9930::getProximityIntEnable()
  808. {
  809. uint8_t val;
  810. /* Read value from ENABLE register */
  811. if( !wireReadDataByte(APDS9930_ENABLE, val) ) {
  812. return ERROR;
  813. }
  814. /* Shift and mask out PIEN bit */
  815. val = (val >> 5) & 0b00000001;
  816. return val;
  817. }
  818. /**
  819. * @brief Turns proximity interrupts on or off
  820. *
  821. * @param[in] enable 1 to enable interrupts, 0 to turn them off
  822. * @return True if operation successful. False otherwise.
  823. */
  824. bool APDS9930::setProximityIntEnable(uint8_t enable)
  825. {
  826. uint8_t val;
  827. /* Read value from ENABLE register */
  828. if( !wireReadDataByte(APDS9930_ENABLE, val) ) {
  829. return false;
  830. }
  831. /* Set bits in register to given value */
  832. enable &= 0b00000001;
  833. enable = enable << 5;
  834. val &= 0b11011111;
  835. val |= enable;
  836. /* Write register value back into ENABLE register */
  837. if( !wireWriteDataByte(APDS9930_ENABLE, val) ) {
  838. return false;
  839. }
  840. return true;
  841. }
  842. /**
  843. * @brief Clears the ambient light interrupt
  844. *
  845. * @return True if operation completed successfully. False otherwise.
  846. */
  847. bool APDS9930::clearAmbientLightInt()
  848. {
  849. if( !wireWriteByte(CLEAR_ALS_INT) ) {
  850. return false;
  851. }
  852. return true;
  853. }
  854. /**
  855. * @brief Clears the proximity interrupt
  856. *
  857. * @return True if operation completed successfully. False otherwise.
  858. */
  859. bool APDS9930::clearProximityInt()
  860. {
  861. if( !wireWriteByte(CLEAR_PROX_INT) ) {
  862. return false;
  863. }
  864. return true;
  865. }
  866. /**
  867. * @brief Clears all interrupts
  868. *
  869. * @return True if operation completed successfully. False otherwise.
  870. */
  871. bool APDS9930::clearAllInts()
  872. {
  873. if( !wireWriteByte(CLEAR_ALL_INTS) ) {
  874. return false;
  875. }
  876. return true;
  877. }
  878. /*******************************************************************************
  879. * Raw I2C Reads and Writes
  880. ******************************************************************************/
  881. /**
  882. * @brief Writes a single byte to the I2C device (no register)
  883. *
  884. * @param[in] val the 1-byte value to write to the I2C device
  885. * @return True if successful write operation. False otherwise.
  886. */
  887. bool APDS9930::wireWriteByte(uint8_t val)
  888. {
  889. Wire.beginTransmission(APDS9930_I2C_ADDR);
  890. Wire.write(val);
  891. if( Wire.endTransmission() != 0 ) {
  892. return false;
  893. }
  894. return true;
  895. }
  896. /**
  897. * @brief Writes a single byte to the I2C device and specified register
  898. *
  899. * @param[in] reg the register in the I2C device to write to
  900. * @param[in] val the 1-byte value to write to the I2C device
  901. * @return True if successful write operation. False otherwise.
  902. */
  903. bool APDS9930::wireWriteDataByte(uint8_t reg, uint8_t val)
  904. {
  905. Wire.beginTransmission(APDS9930_I2C_ADDR);
  906. Wire.write(reg | AUTO_INCREMENT);
  907. Wire.write(val);
  908. if( Wire.endTransmission() != 0 ) {
  909. return false;
  910. }
  911. return true;
  912. }
  913. /**
  914. * @brief Writes a block (array) of bytes to the I2C device and register
  915. *
  916. * @param[in] reg the register in the I2C device to write to
  917. * @param[in] val pointer to the beginning of the data byte array
  918. * @param[in] len the length (in bytes) of the data to write
  919. * @return True if successful write operation. False otherwise.
  920. */
  921. bool APDS9930::wireWriteDataBlock( uint8_t reg,
  922. uint8_t *val,
  923. unsigned int len)
  924. {
  925. unsigned int i;
  926. Wire.beginTransmission(APDS9930_I2C_ADDR);
  927. Wire.write(reg | AUTO_INCREMENT);
  928. for(i = 0; i < len; i++) {
  929. Wire.beginTransmission(APDS9930_I2C_ADDR);
  930. Wire.write(val[i]);
  931. }
  932. if( Wire.endTransmission() != 0 ) {
  933. return false;
  934. }
  935. return true;
  936. }
  937. /**
  938. * @brief Reads a single byte from the I2C device and specified register
  939. *
  940. * @param[in] reg the register to read from
  941. * @param[out] the value returned from the register
  942. * @return True if successful read operation. False otherwise.
  943. */
  944. bool APDS9930::wireReadDataByte(uint8_t reg, uint8_t &val)
  945. {
  946. /* Indicate which register we want to read from */
  947. if (!wireWriteByte(reg | AUTO_INCREMENT)) {
  948. return false;
  949. }
  950. /* Read from register */
  951. Wire.requestFrom(APDS9930_I2C_ADDR, 1);
  952. while (Wire.available()) {
  953. val = Wire.read();
  954. }
  955. return true;
  956. }
  957. /**
  958. * @brief Reads a block (array) of bytes from the I2C device and register
  959. *
  960. * @param[in] reg the register to read from
  961. * @param[out] val pointer to the beginning of the data
  962. * @param[in] len number of bytes to read
  963. * @return Number of bytes read. -1 on read error.
  964. */
  965. int APDS9930::wireReadDataBlock( uint8_t reg,
  966. uint8_t *val,
  967. unsigned int len)
  968. {
  969. unsigned char i = 0;
  970. /* Indicate which register we want to read from */
  971. if (!wireWriteByte(reg | AUTO_INCREMENT)) {
  972. return -1;
  973. }
  974. /* Read block data */
  975. Wire.requestFrom(APDS9930_I2C_ADDR, len);
  976. while (Wire.available()) {
  977. if (i >= len) {
  978. return -1;
  979. }
  980. val[i] = Wire.read();
  981. i++;
  982. }
  983. return i;
  984. }