123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561 |
- /**************************************************************************/
- /*!
- @file APDS9960.h
- @author Ladyada, Dean Miller (Adafruit Industries)
- @section LICENSE
- Software License Agreement (BSD License)
- Copyright (c) 2017, Adafruit Industries
- All rights reserved.
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- 3. Neither the name of the copyright holders nor the
- names of its contributors may be used to endorse or promote products
- derived from this software without specific prior written permission.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- /**************************************************************************/
- #ifndef _APDS9960_H_
- #define _APDS9960_H_
- #include <Arduino.h>
- #include <Wire.h>
- #define I2CDEBUG
- /*=========================================================================
- I2C ADDRESS/BITS
- -----------------------------------------------------------------------*/
- #define APDS9960_ADDRESS (0x39)
- /*=========================================================================*/
- /*=========================================================================
- REGISTERS
- -----------------------------------------------------------------------*/
- enum
- {
- APDS9960_RAM = 0x00,
- APDS9960_ENABLE = 0x80,
- APDS9960_ATIME = 0x81,
- APDS9960_WTIME = 0x83,
- APDS9960_AILTIL = 0x84,
- APDS9960_AILTH = 0x85,
- APDS9960_AIHTL = 0x86,
- APDS9960_AIHTH = 0x87,
- APDS9960_PILT = 0x89,
- APDS9960_PIHT = 0x8B,
- APDS9960_PERS = 0x8C,
- APDS9960_CONFIG1 = 0x8D,
- APDS9960_PPULSE = 0x8E,
- APDS9960_CONTROL = 0x8F,
- APDS9960_CONFIG2 = 0x90,
- APDS9960_ID = 0x92,
- APDS9960_STATUS = 0x93,
- APDS9960_CDATAL = 0x94,
- APDS9960_CDATAH = 0x95,
- APDS9960_RDATAL = 0x96,
- APDS9960_RDATAH = 0x97,
- APDS9960_GDATAL = 0x98,
- APDS9960_GDATAH = 0x99,
- APDS9960_BDATAL = 0x9A,
- APDS9960_BDATAH = 0x9B,
- APDS9960_PDATA = 0x9C,
- APDS9960_POFFSET_UR = 0x9D,
- APDS9960_POFFSET_DL = 0x9E,
- APDS9960_CONFIG3 = 0x9F,
- APDS9960_GPENTH = 0xA0,
- APDS9960_GEXTH = 0xA1,
- APDS9960_GCONF1 = 0xA2,
- APDS9960_GCONF2 = 0xA3,
- APDS9960_GOFFSET_U = 0xA4,
- APDS9960_GOFFSET_D = 0xA5,
- APDS9960_GOFFSET_L = 0xA7,
- APDS9960_GOFFSET_R = 0xA9,
- APDS9960_GPULSE = 0xA6,
- APDS9960_GCONF3 = 0xAA,
- APDS9960_GCONF4 = 0xAB,
- APDS9960_GFLVL = 0xAE,
- APDS9960_GSTATUS = 0xAF,
- APDS9960_IFORCE = 0xE4,
- APDS9960_PICLEAR = 0xE5,
- APDS9960_CICLEAR = 0xE6,
- APDS9960_AICLEAR = 0xE7,
- APDS9960_GFIFO_U = 0xFC,
- APDS9960_GFIFO_D = 0xFD,
- APDS9960_GFIFO_L = 0xFE,
- APDS9960_GFIFO_R = 0xFF,
- };
- /*=========================================================================*/
- typedef enum
- {
- APDS9960_AGAIN_1X = 0x00, /**< No gain */
- APDS9960_AGAIN_4X = 0x01, /**< 2x gain */
- APDS9960_AGAIN_16X = 0x02, /**< 16x gain */
- APDS9960_AGAIN_64X = 0x03 /**< 64x gain */
- }
- apds9960AGain_t;
- typedef enum
- {
- APDS9960_PGAIN_1X = 0x00, /**< 1x gain */
- APDS9960_PGAIN_2X = 0x04, /**< 2x gain */
- APDS9960_PGAIN_4X = 0x08, /**< 4x gain */
- APDS9960_PGAIN_8X = 0x0C /**< 8x gain */
- }
- apds9960PGain_t;
- typedef enum
- {
- APDS9960_PPULSELEN_4US = 0x00, /**< 4uS */
- APDS9960_PPULSELEN_8US = 0x40, /**< 8uS */
- APDS9960_PPULSELEN_16US = 0x80, /**< 16uS */
- APDS9960_PPULSELEN_32US = 0xC0 /**< 32uS */
- }
- apds9960PPulseLen_t;
- typedef enum
- {
- APDS9960_LEDDRIVE_100MA = 0x00, /**< 100mA */
- APDS9960_LEDDRIVE_50MA = 0x40, /**< 50mA */
- APDS9960_LEDDRIVE_25MA = 0x80, /**< 25mA */
- APDS9960_LEDDRIVE_12MA = 0xC0 /**< 12.5mA */
- }
- apds9960LedDrive_t;
- typedef enum
- {
- APDS9960_LEDBOOST_100PCNT = 0x00, /**< 100% */
- APDS9960_LEDBOOST_150PCNT = 0x10, /**< 150% */
- APDS9960_LEDBOOST_200PCNT = 0x20, /**< 200% */
- APDS9960_LEDBOOST_300PCNT = 0x30 /**< 300% */
- }
- apds9960LedBoost_t;
- enum
- {
- APDS9960_DIMENSIONS_ALL = 0x00,
- APDS9960_DIMENSIONS_UP_DOWM = 0x01,
- APGS9960_DIMENSIONS_LEFT_RIGHT = 0x02,
- };
- enum
- {
- APDS9960_GFIFO_1 = 0x00,
- APDS9960_GFIFO_4 = 0x01,
- APDS9960_GFIFO_8 = 0x02,
- APDS9960_GFIFO_16 = 0x03,
- };
- enum
- {
- APDS9960_GGAIN_1 = 0x00,
- APDS9960_GGAIN_2 = 0x01,
- APDS9960_GGAIN_4 = 0x02,
- APDS9960_GGAIN_8 = 0x03,
- };
- enum
- {
- APDS9960_GPULSE_4US = 0x00,
- APDS9960_GPULSE_8US = 0x01,
- APDS9960_GPULSE_16US = 0x02,
- APDS9960_GPULSE_32US = 0x03,
- };
- #define APDS9960_TIME_MULT 2.78 //millisec
- #define APDS9960_UP 0x01
- #define APDS9960_DOWN 0x02
- #define APDS9960_LEFT 0x03
- #define APDS9960_RIGHT 0x04
- class APDS9960 {
- public:
- APDS9960(void) {};
- ~APDS9960(void) {};
- boolean begin(uint16_t iTimeMS = 10, apds9960AGain_t = APDS9960_AGAIN_4X, uint8_t addr = APDS9960_ADDRESS);
- void setADCIntegrationTime(uint16_t iTimeMS);
- float getADCIntegrationTime(void);
- void setADCGain(apds9960AGain_t gain);
- apds9960AGain_t getADCGain(void);
- void setLED(apds9960LedDrive_t drive, apds9960LedBoost_t boost);
- // proximity
- void enableProximity(boolean en = true);
- void setProxGain(apds9960PGain_t gain);
- apds9960PGain_t getProxGain(void);
- void setProxPulse(apds9960PPulseLen_t pLen, uint8_t pulses);
- void enableProximityInterrupt();
- void disableProximityInterrupt();
- uint8_t readProximity(void);
- void setProximityInterruptThreshold(uint8_t low, uint8_t high, uint8_t persistance = 4);
- bool getProximityInterrupt();
- // gesture
- void enableGesture(boolean en = true);
- bool gestureValid();
- void setGestureDimensions(uint8_t dims, uint8_t pcmp_en = 0);
- void setGestureFIFOThreshold(uint8_t thresh);
- void setGestureGain(uint8_t gain);
- void setGestureProximityThreshold(uint8_t thresh);
- void setGestureOffset(uint8_t offset_up, uint8_t offset_down, uint8_t offset_left, uint8_t offset_right);
- uint8_t readGesture(void);
- void resetCounts();
- // light & color
- void enableColor(boolean en = true);
- bool colorDataReady();
- void getColorData(uint16_t *r, uint16_t *g, uint16_t *b, uint16_t *c);
- uint16_t calculateColorTemperature(uint16_t r, uint16_t g, uint16_t b);
- uint16_t calculateLux(uint16_t r, uint16_t g, uint16_t b);
- void enableColorInterrupt();
- void disableColorInterrupt();
- void clearInterrupt(void);
- void setIntLimits(uint16_t l, uint16_t h);
- // turn on/off elements
- void enable(boolean en = true);
- private:
- uint8_t _i2caddr;
- uint32_t read32(uint8_t reg);
- uint16_t read16(uint8_t reg);
- uint16_t read16R(uint8_t reg);
- void write8(byte reg, byte value);
- uint8_t read8(byte reg);
- uint8_t gestCnt;
- uint8_t UCount;
- uint8_t DCount;
- uint8_t LCount;
- uint8_t RCount;
- uint8_t read(uint8_t reg, uint8_t *buf, uint8_t num);
- void write(uint8_t reg, uint8_t *buf, uint8_t num);
- void _i2c_init();
- struct enable {
- //power on
- uint8_t PON : 1;
- //ALS enable
- uint8_t AEN : 1;
- //Proximity detect enable
- uint8_t PEN : 1;
- //wait timer enable
- uint8_t WEN : 1;
- //ALS interrupt enable
- uint8_t AIEN : 1;
- //proximity interrupt enable
- uint8_t PIEN : 1;
- //gesture enable
- uint8_t GEN : 1;
- uint8_t get() {
- return (GEN << 6) | (PIEN << 5) | (AIEN << 4) | (WEN << 3) | (PEN << 2) | (AEN << 1) | PON;
- };
- };
- struct enable _enable;
- struct pers {
- //ALS Interrupt Persistence. Controls rate of Clear channel interrupt to the host processor
- uint8_t APERS : 4;
- //proximity interrupt persistence, controls rate of prox interrupt to host processor
- uint8_t PPERS : 4;
- uint8_t get(){
- return (PPERS << 4) | APERS;
- };
- };
- pers _pers;
- struct config1 {
- uint8_t WLONG : 1;
- uint8_t get(){
- return WLONG << 1;
- };
- };
- config1 _config1;
- struct ppulse {
- /*Proximity Pulse Count. Specifies the number of proximity pulses to be generated on LDR.
- Number of pulses is set by PPULSE value plus 1.
- */
- uint8_t PPULSE : 6;
- //Proximity Pulse Length. Sets the LED-ON pulse width during a proximity LDR pulse.
- uint8_t PPLEN : 2;
- uint8_t get(){
- return (PPLEN << 6) | PPULSE;
- }
- };
- ppulse _ppulse;
- struct control {
- //ALS and Color gain control
- uint8_t AGAIN : 2;
- //proximity gain control
- uint8_t PGAIN : 2;
- //led drive strength
- uint8_t LDRIVE : 2;
- uint8_t get(){
- return (LDRIVE << 6) | (PGAIN << 2) | AGAIN;
- }
- };
- control _control;
- struct config2 {
- /* Additional LDR current during proximity and gesture LED pulses. Current value, set by LDRIVE,
- is increased by the percentage of LED_BOOST.
- */
- uint8_t LED_BOOST : 2;
- //clear photodiode saturation int enable
- uint8_t CPSIEN : 1;
- //proximity saturation interrupt enable
- uint8_t PSIEN : 1;
- uint8_t get(){
- return (PSIEN << 7) | (CPSIEN << 6) | (LED_BOOST << 4) | 1;
- }
- };
- config2 _config2;
- struct status {
- /* ALS Valid. Indicates that an ALS cycle has completed since AEN was asserted or since a read
- from any of the ALS/Color data registers.
- */
- uint8_t AVALID : 1;
- /* Proximity Valid. Indicates that a proximity cycle has completed since PEN was asserted or since
- PDATA was last read. A read of PDATA automatically clears PVALID.
- */
- uint8_t PVALID : 1;
- /* Gesture Interrupt. GINT is asserted when GFVLV becomes greater than GFIFOTH or if GVALID
- has become asserted when GMODE transitioned to zero. The bit is reset when FIFO is
- completely emptied (read).
- */
- uint8_t GINT : 1;
- //ALS Interrupt. This bit triggers an interrupt if AIEN in ENABLE is set.
- uint8_t AINT : 1;
- //Proximity Interrupt. This bit triggers an interrupt if PIEN in ENABLE is set.
- uint8_t PINT : 1;
- /* Indicates that an analog saturation event occurred during a previous proximity or gesture
- cycle. Once set, this bit remains set until cleared by clear proximity interrupt special function
- command (0xE5 PICLEAR) or by disabling Prox (PEN=0). This bit triggers an interrupt if PSIEN
- is set.
- */
- uint8_t PGSAT : 1;
- /* Clear Photodiode Saturation. When asserted, the analog sensor was at the upper end of its
- dynamic range. The bit can be de-asserted by sending a Clear channel interrupt command
- (0xE6 CICLEAR) or by disabling the ADC (AEN=0). This bit triggers an interrupt if CPSIEN is set.
- */
- uint8_t CPSAT : 1;
- void set(uint8_t data){
- AVALID = data & 0x01;
- PVALID = (data >> 1) & 0x01;
- GINT = (data >> 2) & 0x01;
- AINT = (data >> 4) & 0x01;
- PINT = (data >> 5) & 0x01;
- PGSAT = (data >> 6) & 0x01;
- CPSAT = (data >> 7) & 0x01;
- }
- };
- status _status;
- struct config3 {
- //proximity mask
- uint8_t PMASK_R : 1;
- uint8_t PMASK_L : 1;
- uint8_t PMASK_D : 1;
- uint8_t PMASK_U : 1;
- /* Sleep After Interrupt. When enabled, the device will automatically enter low power mode
- when the INT pin is asserted and the state machine has progressed to the SAI decision block.
- Normal operation is resumed when INT pin is cleared over I2C.
- */
- uint8_t SAI : 1;
- /* Proximity Gain Compensation Enable. This bit provides gain compensation when proximity
- photodiode signal is reduced as a result of sensor masking. If only one diode of the diode pair
- is contributing, then only half of the signal is available at the ADC; this results in a maximum
- ADC value of 127. Enabling PCMP enables an additional gain of 2X, resulting in a maximum
- ADC value of 255.
- */
- uint8_t PCMP : 1;
- uint8_t get(){
- return (PCMP << 5) | (SAI << 4) | (PMASK_U << 3) | (PMASK_D << 2) | (PMASK_L << 1) | PMASK_R;
- }
- };
- config3 _config3;
- struct gconf1 {
- /* Gesture Exit Persistence. When a number of consecutive �gesture end� occurrences become
- equal or greater to the GEPERS value, the Gesture state machine is exited.
- */
- uint8_t GEXPERS : 2;
- /* Gesture Exit Mask. Controls which of the gesture detector photodiodes (UDLR) will be included
- to determine a �gesture end� and subsequent exit of the gesture state machine. Unmasked
- UDLR data will be compared with the value in GTHR_OUT. Field value bits correspond to UDLR
- detectors.
- */
- uint8_t GEXMSK : 4;
- /* Gesture FIFO Threshold. This value is compared with the FIFO Level (i.e. the number of UDLR
- datasets) to generate an interrupt (if enabled).
- */
- uint8_t GFIFOTH : 2;
- uint8_t get(){
- return (GFIFOTH << 6) | (GEXMSK << 2) | GEXPERS;
- }
- };
- gconf1 _gconf1;
- struct gconf2 {
- /* Gesture Wait Time. The GWTIME controls the amount of time in a low power mode between
- gesture detection cycles.
- */
- uint8_t GWTIME : 3;
- //Gesture LED Drive Strength. Sets LED Drive Strength in gesture mode.
- uint8_t GLDRIVE : 2;
- //Gesture Gain Control. Sets the gain of the proximity receiver in gesture mode.
- uint8_t GGAIN : 2;
- uint8_t get(){
- return (GGAIN << 5) | (GLDRIVE << 3) | GWTIME;
- }
- };
- gconf2 _gconf2;
- struct gpulse {
- /* Number of Gesture Pulses. Specifies the number of pulses to be generated on LDR.
- Number of pulses is set by GPULSE value plus 1.
- */
- uint8_t GPULSE : 6;
- //Gesture Pulse Length. Sets the LED_ON pulse width during a Gesture LDR Pulse.
- uint8_t GPLEN : 2;
- uint8_t get(){
- return (GPLEN << 6) | GPULSE;
- }
- };
- gpulse _gpulse;
- struct gconf3 {
- uint8_t PCMP : 1;
- /* Gesture Dimension Select. Selects which gesture photodiode pairs are enabled to gather
- results during gesture.
- */
- uint8_t GDIMS : 4;
- uint8_t get(){
- return (PCMP << 5) | GDIMS;
- }
- };
- gconf3 _gconf3;
- struct gconf4 {
- /* Gesture Mode. Reading this bit reports if the gesture state machine is actively running, 1
- = Gesture, 0= ALS, Proximity, Color. Writing a 1 to this bit causes immediate entry in to the
- gesture state machine (as if GPENTH had been exceeded). Writing a 0 to this bit causes exit of
- gesture when current analog conversion has finished (as if GEXTH had been exceeded).
- */
- uint8_t GMODE : 1;
- /* Gesture interrupt enable. Gesture Interrupt Enable. When asserted, all gesture related
- interrupts are unmasked.
- */
- uint8_t GIEN : 2;
- uint8_t get(){
- return (GIEN << 1) | GMODE;
- }
- void set(uint8_t data){
- GIEN = (data >> 1) & 0x01;
- GMODE = data & 0x01;
- }
- };
- gconf4 _gconf4;
- struct gstatus {
- /* Gesture FIFO Data. GVALID bit is sent when GFLVL becomes greater than GFIFOTH (i.e. FIFO has
- enough data to set GINT). GFIFOD is reset when GMODE = 0 and the GFLVL=0 (i.e. All FIFO data
- has been read).
- */
- uint8_t GVALID : 1;
- /* Gesture FIFO Overflow. A setting of 1 indicates that the FIFO has filled to capacity and that new
- gesture detector data has been lost.
- */
- uint8_t GFOV : 1;
- void set(uint8_t data){
- GFOV = (data >> 1) & 0x01;
- GVALID = data & 0x01;
- }
- };
- gstatus _gstatus;
- };
- #endif
|