From 94ca074b599adb5dae897299d2a50c1e845addc1 Mon Sep 17 00:00:00 2001 From: Mickael Gaillard Date: Sat, 18 Apr 2020 20:45:31 +0200 Subject: [PATCH] Format code with cpplint Signed-off-by: Mickael Gaillard --- tasmota/xsns_27_apds9960.ino | 2735 ++++++++++++++++------------------ 1 file changed, 1305 insertions(+), 1430 deletions(-) diff --git a/tasmota/xsns_27_apds9960.ino b/tasmota/xsns_27_apds9960.ino index 1751eb947..5f33ad6c7 100644 --- a/tasmota/xsns_27_apds9960.ino +++ b/tasmota/xsns_27_apds9960.ino @@ -73,9 +73,9 @@ char currentGesture[6]; uint8_t gesture_mode = 1; -volatile uint8_t recovery_loop_counter = 0; //count number of stateloops to switch the sensor off, if needed -#define APDS9960_LONG_RECOVERY 50 //long pause after sensor overload in loops -#define APDS9960_MAX_GESTURE_CYCLES 50 //how many FIFO-reads are allowed to prevent crash +volatile uint8_t recovery_loop_counter = 0; // count number of stateloops to switch the sensor off, if needed +#define APDS9960_LONG_RECOVERY 50 // long pause after sensor overload in loops +#define APDS9960_MAX_GESTURE_CYCLES 50 // how many FIFO-reads are allowed to prevent crash bool APDS9960_overload = false; #ifdef USE_WEBSERVER @@ -84,7 +84,7 @@ const char HTTP_APDS_9960_SNS[] PROGMEM = "{s}" "Green" "{m}%s{e}" "{s}" "Blue" "{m}%s{e}" "{s}" "Ambient" "{m}%s " D_UNIT_LUX "{e}" - "{s}" "CCT" "{m}%s " "K" "{e}" // calculated color temperature in Kelvin + "{s}" "CCT" "{m}%s " "K" "{e}" // calculated color temperature in Kelvin "{s}" "Proximity" "{m}%s{e}"; // {s} = , {m} = , {e} = #endif // USE_WEBSERVER @@ -213,33 +213,33 @@ const char HTTP_APDS_9960_SNS[] PROGMEM = #define GWTIME_39_2MS 7 /* Default values */ -#define DEFAULT_ATIME 0xdb // 103ms = 0xdb -#define DEFAULT_WTIME 246 // 27ms -#define DEFAULT_PROX_PPULSE 0x87 // 16us, 8 pulses -#define DEFAULT_GESTURE_PPULSE 0x89 // 16us, 10 pulses ---89 -#define DEFAULT_POFFSET_UR 0 // 0 offset -#define DEFAULT_POFFSET_DL 0 // 0 offset -#define DEFAULT_CONFIG1 0x60 // No 12x wait (WTIME) factor +#define DEFAULT_ATIME 0xdb // 103ms = 0xdb +#define DEFAULT_WTIME 246 // 27ms +#define DEFAULT_PROX_PPULSE 0x87 // 16us, 8 pulses +#define DEFAULT_GESTURE_PPULSE 0x89 // 16us, 10 pulses ---89 +#define DEFAULT_POFFSET_UR 0 // 0 offset +#define DEFAULT_POFFSET_DL 0 // 0 offset +#define DEFAULT_CONFIG1 0x60 // No 12x wait (WTIME) factor #define DEFAULT_LDRIVE LED_DRIVE_100MA #define DEFAULT_PGAIN PGAIN_4X -#define DEFAULT_AGAIN AGAIN_4X // we have to divide by the same facot at the end -#define DEFAULT_PILT 0 // Low proximity threshold -#define DEFAULT_PIHT 50 // High proximity threshold -#define DEFAULT_AILT 0xFFFF // Force interrupt for calibration +#define DEFAULT_AGAIN AGAIN_4X // we have to divide by the same facot at the end +#define DEFAULT_PILT 0 // Low proximity threshold +#define DEFAULT_PIHT 50 // High proximity threshold +#define DEFAULT_AILT 0xFFFF // Force interrupt for calibration #define DEFAULT_AIHT 0 -#define DEFAULT_PERS 0x11 // 2 consecutive prox or ALS for int. -#define DEFAULT_CONFIG2 0x01 // No saturation interrupts or LED boost -#define DEFAULT_CONFIG3 0 // Enable all photodiodes, no SAI -#define DEFAULT_GPENTH 40 // Threshold for entering gesture mode -#define DEFAULT_GEXTH 30 // Threshold for exiting gesture mode -#define DEFAULT_GCONF1 0x40 // 4 gesture events for int., 1 for exit +#define DEFAULT_PERS 0x11 // 2 consecutive prox or ALS for int. +#define DEFAULT_CONFIG2 0x01 // No saturation interrupts or LED boost +#define DEFAULT_CONFIG3 0 // Enable all photodiodes, no SAI +#define DEFAULT_GPENTH 40 // Threshold for entering gesture mode +#define DEFAULT_GEXTH 30 // Threshold for exiting gesture mode +#define DEFAULT_GCONF1 0x40 // 4 gesture events for int., 1 for exit #define DEFAULT_GGAIN GGAIN_4X -#define DEFAULT_GLDRIVE LED_DRIVE_100MA // default 100ma -#define DEFAULT_GWTIME GWTIME_2_8MS // default 2_8MS -#define DEFAULT_GOFFSET 0 // No offset scaling for gesture mode -#define DEFAULT_GPULSE 0xC9 // 32us, 10 pulses -#define DEFAULT_GCONF3 0 // All photodiodes active during gesture -#define DEFAULT_GIEN 0 // Disable gesture interrupts +#define DEFAULT_GLDRIVE LED_DRIVE_100MA // default 100ma +#define DEFAULT_GWTIME GWTIME_2_8MS // default 2_8MS +#define DEFAULT_GOFFSET 0 // No offset scaling for gesture mode +#define DEFAULT_GPULSE 0xC9 // 32us, 10 pulses +#define DEFAULT_GCONF3 0 // All photodiodes active during gesture +#define DEFAULT_GIEN 0 // Disable gesture interrupts #define APDS9960_ERROR 0xFF @@ -261,60 +261,60 @@ enum { /* Container for gesture data */ typedef struct gesture_data_type { - uint8_t u_data[32]; - uint8_t d_data[32]; - uint8_t l_data[32]; - uint8_t r_data[32]; - uint8_t index; - uint8_t total_gestures; - uint8_t in_threshold; - uint8_t out_threshold; + uint8_t u_data[32]; + uint8_t d_data[32]; + uint8_t l_data[32]; + uint8_t r_data[32]; + uint8_t index; + uint8_t total_gestures; + uint8_t in_threshold; + uint8_t out_threshold; } gesture_data_type; /*Members*/ - gesture_data_type gesture_data_; - int16_t gesture_ud_delta_ = 0; - int16_t gesture_lr_delta_ = 0; - int16_t gesture_ud_count_ = 0; - int16_t gesture_lr_count_ = 0; - int16_t gesture_state_ = 0; - int16_t gesture_motion_ = DIR_NONE; +gesture_data_type gesture_data_; +int16_t gesture_ud_delta_ = 0; +int16_t gesture_lr_delta_ = 0; +int16_t gesture_ud_count_ = 0; +int16_t gesture_lr_count_ = 0; +int16_t gesture_state_ = 0; +int16_t gesture_motion_ = DIR_NONE; - typedef struct color_data_type { - uint16_t a; // measured ambient - uint16_t r; - uint16_t g; - uint16_t b; - uint8_t p; // proximity - uint16_t cct; // calculated color temperature - uint16_t lux; // calculated illuminance - atm only from rgb - } color_data_type; +typedef struct color_data_type { + uint16_t a; // measured ambient + uint16_t r; + uint16_t g; + uint16_t b; + uint8_t p; // proximity + uint16_t cct; // calculated color temperature + uint16_t lux; // calculated illuminance - atm only from rgb +} color_data_type; - color_data_type color_data; - uint8_t APDS9960_aTime = DEFAULT_ATIME; +color_data_type color_data; +uint8_t APDS9960_aTime = DEFAULT_ATIME; - /******************************************************************************* - * Helper functions - ******************************************************************************/ +/******************************************************************************\ + * Helper functions +\******************************************************************************/ - /** - * @brief Writes a single byte to the I2C device (no register) - * - * @param[in] val the 1-byte value to write to the I2C device - * @return True if successful write operation. False otherwise. - */ - bool wireWriteByte(uint8_t val) - { - Wire.beginTransmission(APDS9960_I2C_ADDR); - Wire.write(val); - if( Wire.endTransmission() != 0 ) { - return false; - } +/** + * @brief Writes a single byte to the I2C device (no register) + * + * @param[in] val the 1-byte value to write to the I2C device + * @return True if successful write operation. False otherwise. + */ +bool wireWriteByte(uint8_t val) { + Wire.beginTransmission(APDS9960_I2C_ADDR); + Wire.write(val); + if ( Wire.endTransmission() != 0 ) { + return false; + } - return true; - } - /** + return true; +} + +/** * @brief Reads a block (array) of bytes from the I2C device and register * * @param[in] reg the register to read from @@ -322,39 +322,35 @@ typedef struct gesture_data_type { * @param[in] len number of bytes to read * @return Number of bytes read. -1 on read error. */ +int8_t wireReadDataBlock(uint8_t reg, + uint8_t *val, + uint16_t len) { + unsigned char i = 0; -int8_t wireReadDataBlock( uint8_t reg, - uint8_t *val, - uint16_t len) -{ - unsigned char i = 0; + /* Indicate which register we want to read from */ + if (!wireWriteByte(reg)) { + return -1; + } - /* Indicate which register we want to read from */ - if (!wireWriteByte(reg)) { - return -1; + /* Read block data */ + Wire.requestFrom(APDS9960_I2C_ADDR, len); + while (Wire.available()) { + if (i >= len) { + return -1; } + val[i] = Wire.read(); + i++; + } - /* Read block data */ - Wire.requestFrom(APDS9960_I2C_ADDR, len); - while (Wire.available()) { - if (i >= len) { - return -1; - } - val[i] = Wire.read(); - i++; - } - - return i; + return i; } /** -* Taken from the Adafruit-library -* @brief Converts the raw R/G/B values to color temperature in degrees -* Kelvin -*/ - -void calculateColorTemperature(void) -{ + * Taken from the Adafruit-library + * @brief Converts the raw R/G/B values to color temperature in degrees + * Kelvin + */ +void calculateColorTemperature(void) { float X, Y, Z; /* RGB to XYZ correlation */ float xc, yc; /* Chromaticity co-ordinates */ float n; /* McCamy's formula */ @@ -365,8 +361,8 @@ void calculateColorTemperature(void) /* and 60W incandescent values for a wide range. */ /* Note: Y = Illuminance or lux */ X = (-0.14282F * color_data.r) + (1.54924F * color_data.g) + (-0.95641F * color_data.b); - Y = (-0.32466F * color_data.r) + (1.57837F * color_data.g) + (-0.73191F * color_data.b); // this is Lux ... under certain circumstances - Z = (-0.68202F * color_data.r) + (0.77073F * color_data.g) + ( 0.56332F * color_data.b); + Y = (-0.32466F * color_data.r) + (1.57837F * color_data.g) + (-0.73191F * color_data.b); // this is Lux ... under certain circumstances + Z = (-0.68202F * color_data.r) + (0.77073F * color_data.g) + (+0.56332F * color_data.b); /* 2. Calculate the chromaticity co-ordinates */ xc = (X) / (X + Y + Z); @@ -381,964 +377,883 @@ void calculateColorTemperature(void) return; } - /******************************************************************************* - * Getters and setters for register values - ******************************************************************************/ - - /** - * @brief Returns the lower threshold for proximity detection - * - * @return lower threshold - */ - uint8_t getProxIntLowThresh(void) - { - uint8_t val; - - /* Read value from PILT register */ - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_PILT) ; - return val; - } - - /** - * @brief Sets the lower threshold for proximity detection - * - * @param[in] threshold the lower proximity threshold - */ - void setProxIntLowThresh(uint8_t threshold) - { - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PILT, threshold); - } - - /** - * @brief Returns the high threshold for proximity detection - * - * @return high threshold - */ - uint8_t getProxIntHighThresh(void) - { - uint8_t val; - - /* Read value from PIHT register */ - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_PIHT) ; - return val; - } - - /** - * @brief Sets the high threshold for proximity detection - * - * @param[in] threshold the high proximity threshold - */ - - void setProxIntHighThresh(uint8_t threshold) - { - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PIHT, threshold); - } - - - /** - * @brief Returns LED drive strength for proximity and ALS - * - * Value LED Current - * 0 100 mA - * 1 50 mA - * 2 25 mA - * 3 12.5 mA - * - * @return the value of the LED drive strength. 0xFF on failure. - */ - uint8_t getLEDDrive(void) - { - uint8_t val; - - /* Read value from CONTROL register */ - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONTROL) ; - /* Shift and mask out LED drive bits */ - val = (val >> 6) & 0b00000011; - - return val; - } - - /** - * @brief Sets the LED drive strength for proximity and ALS - * - * Value LED Current - * 0 100 mA - * 1 50 mA - * 2 25 mA - * 3 12.5 mA - * - * @param[in] drive the value (0-3) for the LED drive strength - */ - void setLEDDrive(uint8_t drive) - { - uint8_t val; - - /* Read value from CONTROL register */ - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONTROL); - - /* Set bits in register to given value */ - drive &= 0b00000011; - drive = drive << 6; - val &= 0b00111111; - val |= drive; - - /* Write register value back into CONTROL register */ - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONTROL, val); - } - - - /** - * @brief Returns receiver gain for proximity detection - * - * Value Gain - * 0 1x - * 1 2x - * 2 4x - * 3 8x - * - * @return the value of the proximity gain. 0xFF on failure. - */ - uint8_t getProximityGain(void) - { - uint8_t val; - - /* Read value from CONTROL register */ - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONTROL) ; - /* Shift and mask out PDRIVE bits */ - val = (val >> 2) & 0b00000011; - - return val; - } - - /** - * @brief Sets the receiver gain for proximity detection - * - * Value Gain - * 0 1x - * 1 2x - * 2 4x - * 3 8x - * - * @param[in] drive the value (0-3) for the gain - */ - void setProximityGain(uint8_t drive) - { - uint8_t val; - - /* Read value from CONTROL register */ - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONTROL); - - /* Set bits in register to given value */ - drive &= 0b00000011; - drive = drive << 2; - val &= 0b11110011; - val |= drive; - - /* Write register value back into CONTROL register */ - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONTROL, val); - } - - - /** - * @brief Returns receiver gain for the ambient light sensor (ALS) - * - * Value Gain - * 0 1x - * 1 4x - * 2 16x - * 3 64x - * - * @return the value of the ALS gain. 0xFF on failure. - */ - - /** - * @brief Sets the receiver gain for the ambient light sensor (ALS) - * - * Value Gain - * 0 1x - * 1 4x - * 2 16x - * 3 64x - * - * @param[in] drive the value (0-3) for the gain - */ - void setAmbientLightGain(uint8_t drive) - { - uint8_t val; - - /* Read value from CONTROL register */ - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONTROL); - - /* Set bits in register to given value */ - drive &= 0b00000011; - val &= 0b11111100; - val |= drive; - - /* Write register value back into CONTROL register */ - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONTROL, val); - } - - /** - * @brief Get the current LED boost value - * - * Value Boost Current - * 0 100% - * 1 150% - * 2 200% - * 3 300% - * - * @return The LED boost value. 0xFF on failure. - */ - uint8_t getLEDBoost(void) - { - uint8_t val; - - /* Read value from CONFIG2 register */ - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG2) ; - - /* Shift and mask out LED_BOOST bits */ - val = (val >> 4) & 0b00000011; - - return val; - } - - /** - * @brief Sets the LED current boost value - * - * Value Boost Current - * 0 100% - * 1 150% - * 2 200% - * 3 300% - * - * @param[in] drive the value (0-3) for current boost (100-300%) - */ - void setLEDBoost(uint8_t boost) - { - uint8_t val; - - /* Read value from CONFIG2 register */ - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG2) ; - /* Set bits in register to given value */ - boost &= 0b00000011; - boost = boost << 4; - val &= 0b11001111; - val |= boost; - - /* Write register value back into CONFIG2 register */ - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONFIG2, val) ; - } - - /** - * @brief Gets proximity gain compensation enable - * - * @return 1 if compensation is enabled. 0 if not. 0xFF on error. - */ - uint8_t getProxGainCompEnable(void) - { - uint8_t val; - - /* Read value from CONFIG3 register */ - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG3) ; - - /* Shift and mask out PCMP bits */ - val = (val >> 5) & 0b00000001; - - return val; - } - - /** - * @brief Sets the proximity gain compensation enable - * - * @param[in] enable 1 to enable compensation. 0 to disable compensation. - */ - void setProxGainCompEnable(uint8_t enable) - { - uint8_t val; - - /* Read value from CONFIG3 register */ - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG3) ; - - /* Set bits in register to given value */ - enable &= 0b00000001; - enable = enable << 5; - val &= 0b11011111; - val |= enable; - - /* Write register value back into CONFIG3 register */ - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONFIG3, val) ; - } - - /** - * @brief Gets the current mask for enabled/disabled proximity photodiodes - * - * 1 = disabled, 0 = enabled - * Bit Photodiode - * 3 UP - * 2 DOWN - * 1 LEFT - * 0 RIGHT - * - * @return Current proximity mask for photodiodes. 0xFF on error. - */ - uint8_t getProxPhotoMask(void) - { - uint8_t val; - - /* Read value from CONFIG3 register */ - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG3) ; - - /* Mask out photodiode enable mask bits */ - val &= 0b00001111; - - return val; - } - - /** - * @brief Sets the mask for enabling/disabling proximity photodiodes - * - * 1 = disabled, 0 = enabled - * Bit Photodiode - * 3 UP - * 2 DOWN - * 1 LEFT - * 0 RIGHT - * - * @param[in] mask 4-bit mask value - */ - void setProxPhotoMask(uint8_t mask) - { - uint8_t val; - - /* Read value from CONFIG3 register */ - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG3) ; - - /* Set bits in register to given value */ - mask &= 0b00001111; - val &= 0b11110000; - val |= mask; - - /* Write register value back into CONFIG3 register */ - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONFIG3, val) ; - } - - /** - * @brief Gets the entry proximity threshold for gesture sensing - * - * @return Current entry proximity threshold. - */ - uint8_t getGestureEnterThresh(void) - { - uint8_t val; - - /* Read value from GPENTH register */ - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GPENTH) ; - - return val; - } - - /** - * @brief Sets the entry proximity threshold for gesture sensing - * - * @param[in] threshold proximity value needed to start gesture mode - */ - void setGestureEnterThresh(uint8_t threshold) - { - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GPENTH, threshold) ; - - } - - /** - * @brief Gets the exit proximity threshold for gesture sensing - * - * @return Current exit proximity threshold. - */ - uint8_t getGestureExitThresh(void) - { - uint8_t val; - - /* Read value from GEXTH register */ - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GEXTH) ; - - return val; - } - - /** - * @brief Sets the exit proximity threshold for gesture sensing - * - * @param[in] threshold proximity value needed to end gesture mode - */ - void setGestureExitThresh(uint8_t threshold) - { - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GEXTH, threshold) ; - } - - /** - * @brief Gets the gain of the photodiode during gesture mode - * - * Value Gain - * 0 1x - * 1 2x - * 2 4x - * 3 8x - * - * @return the current photodiode gain. 0xFF on error. - */ - uint8_t getGestureGain(void) - { - uint8_t val; - - /* Read value from GCONF2 register */ - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2) ; - - /* Shift and mask out GGAIN bits */ - val = (val >> 5) & 0b00000011; - - return val; - } - - /** - * @brief Sets the gain of the photodiode during gesture mode - * - * Value Gain - * 0 1x - * 1 2x - * 2 4x - * 3 8x - * - * @param[in] gain the value for the photodiode gain - */ - void setGestureGain(uint8_t gain) - { - uint8_t val; - - /* Read value from GCONF2 register */ - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2) ; - - /* Set bits in register to given value */ - gain &= 0b00000011; - gain = gain << 5; - val &= 0b10011111; - val |= gain; - - /* Write register value back into GCONF2 register */ - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF2, val) ; - } - - /** - * @brief Gets the drive current of the LED during gesture mode - * - * Value LED Current - * 0 100 mA - * 1 50 mA - * 2 25 mA - * 3 12.5 mA - * - * @return the LED drive current value. 0xFF on error. - */ - uint8_t getGestureLEDDrive(void) - { - uint8_t val; - - /* Read value from GCONF2 register */ - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2) ; - - /* Shift and mask out GLDRIVE bits */ - val = (val >> 3) & 0b00000011; - - return val; - } - - /** - * @brief Sets the LED drive current during gesture mode - * - * Value LED Current - * 0 100 mA - * 1 50 mA - * 2 25 mA - * 3 12.5 mA - * - * @param[in] drive the value for the LED drive current - */ - void setGestureLEDDrive(uint8_t drive) - { - uint8_t val; - - /* Read value from GCONF2 register */ - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2) ; - - /* Set bits in register to given value */ - drive &= 0b00000011; - drive = drive << 3; - val &= 0b11100111; - val |= drive; - - /* Write register value back into GCONF2 register */ - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF2, val) ; - } - - /** - * @brief Gets the time in low power mode between gesture detections - * - * Value Wait time - * 0 0 ms - * 1 2.8 ms - * 2 5.6 ms - * 3 8.4 ms - * 4 14.0 ms - * 5 22.4 ms - * 6 30.8 ms - * 7 39.2 ms - * - * @return the current wait time between gestures. 0xFF on error. - */ - uint8_t getGestureWaitTime(void) - { - uint8_t val; - - /* Read value from GCONF2 register */ - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2) ; - - /* Mask out GWTIME bits */ - val &= 0b00000111; - - return val; - } - - /** - * @brief Sets the time in low power mode between gesture detections - * - * Value Wait time - * 0 0 ms - * 1 2.8 ms - * 2 5.6 ms - * 3 8.4 ms - * 4 14.0 ms - * 5 22.4 ms - * 6 30.8 ms - * 7 39.2 ms - * - * @param[in] the value for the wait time - */ - void setGestureWaitTime(uint8_t time) - { - uint8_t val; - - /* Read value from GCONF2 register */ - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2) ; - - /* Set bits in register to given value */ - time &= 0b00000111; - val &= 0b11111000; - val |= time; - - /* Write register value back into GCONF2 register */ - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF2, val) ; - } - - /** - * @brief Gets the low threshold for ambient light interrupts - * - * @param[out] threshold current low threshold stored on the APDS-9960 - */ - void getLightIntLowThreshold(uint16_t &threshold) - { - uint8_t val_byte; - threshold = 0; - - /* Read value from ambient light low threshold, low byte register */ - val_byte = I2cRead8(APDS9960_I2C_ADDR, APDS9960_AILTL) ; - threshold = val_byte; - - /* Read value from ambient light low threshold, high byte register */ - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_AILTH, val_byte) ; - threshold = threshold + ((uint16_t)val_byte << 8); - } - - /** - * @brief Sets the low threshold for ambient light interrupts - * - * @param[in] threshold low threshold value for interrupt to trigger - */ - - void setLightIntLowThreshold(uint16_t threshold) - { - uint8_t val_low; - uint8_t val_high; - - /* Break 16-bit threshold into 2 8-bit values */ - val_low = threshold & 0x00FF; - val_high = (threshold & 0xFF00) >> 8; - - /* Write low byte */ - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_AILTL, val_low) ; - - /* Write high byte */ - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_AILTH, val_high) ; - - } - - - /** - * @brief Gets the high threshold for ambient light interrupts - * - * @param[out] threshold current low threshold stored on the APDS-9960 - */ - void getLightIntHighThreshold(uint16_t &threshold) - { - uint8_t val_byte; - threshold = 0; - - /* Read value from ambient light high threshold, low byte register */ - val_byte = I2cRead8(APDS9960_I2C_ADDR, APDS9960_AIHTL); - threshold = val_byte; - - /* Read value from ambient light high threshold, high byte register */ - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_AIHTH, val_byte) ; - threshold = threshold + ((uint16_t)val_byte << 8); - } - - /** - * @brief Sets the high threshold for ambient light interrupts - * - * @param[in] threshold high threshold value for interrupt to trigger - */ - void setLightIntHighThreshold(uint16_t threshold) - { - uint8_t val_low; - uint8_t val_high; - - /* Break 16-bit threshold into 2 8-bit values */ - val_low = threshold & 0x00FF; - val_high = (threshold & 0xFF00) >> 8; - - /* Write low byte */ - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_AIHTL, val_low); - - /* Write high byte */ - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_AIHTH, val_high) ; - } - - - /** - * @brief Gets the low threshold for proximity interrupts - * - * @param[out] threshold current low threshold stored on the APDS-9960 - */ - void getProximityIntLowThreshold(uint8_t &threshold) - { - threshold = 0; - - /* Read value from proximity low threshold register */ - threshold = I2cRead8(APDS9960_I2C_ADDR, APDS9960_PILT); - - } - - /** - * @brief Sets the low threshold for proximity interrupts - * - * @param[in] threshold low threshold value for interrupt to trigger - */ - void setProximityIntLowThreshold(uint8_t threshold) - { - - /* Write threshold value to register */ - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PILT, threshold) ; - } - - - - /** - * @brief Gets the high threshold for proximity interrupts - * - * @param[out] threshold current low threshold stored on the APDS-9960 - */ - void getProximityIntHighThreshold(uint8_t &threshold) - { - threshold = 0; - - /* Read value from proximity low threshold register */ - threshold = I2cRead8(APDS9960_I2C_ADDR, APDS9960_PIHT) ; - - } - - /** - * @brief Sets the high threshold for proximity interrupts - * - * @param[in] threshold high threshold value for interrupt to trigger - */ - void setProximityIntHighThreshold(uint8_t threshold) - { - - /* Write threshold value to register */ - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PIHT, threshold) ; - } - - /** - * @brief Gets if ambient light interrupts are enabled or not - * - * @return 1 if interrupts are enabled, 0 if not. 0xFF on error. - */ - uint8_t getAmbientLightIntEnable(void) - { - uint8_t val; - - /* Read value from ENABLE register */ - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ENABLE) ; - - /* Shift and mask out AIEN bit */ - val = (val >> 4) & 0b00000001; - - return val; - } - - /** - * @brief Turns ambient light interrupts on or off - * - * @param[in] enable 1 to enable interrupts, 0 to turn them off - */ - void setAmbientLightIntEnable(uint8_t enable) - { - uint8_t val; - - /* Read value from ENABLE register */ - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ENABLE); - - /* Set bits in register to given value */ - enable &= 0b00000001; - enable = enable << 4; - val &= 0b11101111; - val |= enable; - - /* Write register value back into ENABLE register */ - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ENABLE, val) ; - } - - /** - * @brief Gets if proximity interrupts are enabled or not - * - * @return 1 if interrupts are enabled, 0 if not. 0xFF on error. - */ - uint8_t getProximityIntEnable(void) - { - uint8_t val; - - /* Read value from ENABLE register */ - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ENABLE) ; - - /* Shift and mask out PIEN bit */ - val = (val >> 5) & 0b00000001; - - return val; - } - - /** - * @brief Turns proximity interrupts on or off - * - * @param[in] enable 1 to enable interrupts, 0 to turn them off - */ - void setProximityIntEnable(uint8_t enable) - { - uint8_t val; - - /* Read value from ENABLE register */ - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ENABLE) ; - - /* Set bits in register to given value */ - enable &= 0b00000001; - enable = enable << 5; - val &= 0b11011111; - val |= enable; - - /* Write register value back into ENABLE register */ - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ENABLE, val) ; - } - - /** - * @brief Gets if gesture interrupts are enabled or not - * - * @return 1 if interrupts are enabled, 0 if not. 0xFF on error. - */ - uint8_t getGestureIntEnable(void) - { - uint8_t val; - - /* Read value from GCONF4 register */ - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF4) ; - - /* Shift and mask out GIEN bit */ - val = (val >> 1) & 0b00000001; - - return val; - } - - /** - * @brief Turns gesture-related interrupts on or off - * - * @param[in] enable 1 to enable interrupts, 0 to turn them off - */ - void setGestureIntEnable(uint8_t enable) - { - uint8_t val; - - /* Read value from GCONF4 register */ - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF4) ; - - /* Set bits in register to given value */ - enable &= 0b00000001; - enable = enable << 1; - val &= 0b11111101; - val |= enable; - - /* Write register value back into GCONF4 register */ - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF4, val) ; - } - - /** - * @brief Clears the ambient light interrupt - * - */ - void clearAmbientLightInt(void) - { - uint8_t throwaway; - throwaway = I2cRead8(APDS9960_I2C_ADDR, APDS9960_AICLEAR); - } - - /** - * @brief Clears the proximity interrupt - * - */ - void clearProximityInt(void) - { - uint8_t throwaway; - throwaway = I2cRead8(APDS9960_I2C_ADDR, APDS9960_PICLEAR) ; - - } - - /** - * @brief Tells if the gesture state machine is currently running - * - * @return 1 if gesture state machine is running, 0 if not. 0xFF on error. - */ - uint8_t getGestureMode(void) - { - uint8_t val; - - /* Read value from GCONF4 register */ - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF4) ; - - /* Mask out GMODE bit */ - val &= 0b00000001; - - return val; - } - - /** - * @brief Tells the state machine to either enter or exit gesture state machine - * - * @param[in] mode 1 to enter gesture state machine, 0 to exit. - */ - void setGestureMode(uint8_t mode) - { - uint8_t val; - - /* Read value from GCONF4 register */ - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF4) ; - - /* Set bits in register to given value */ - mode &= 0b00000001; - val &= 0b11111110; - val |= mode; - - /* Write register value back into GCONF4 register */ - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF4, val) ; - } - - -bool APDS9960_init(void) -{ - /* Set default values for ambient light and proximity registers */ - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ATIME, DEFAULT_ATIME) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_WTIME, DEFAULT_WTIME) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PPULSE, DEFAULT_PROX_PPULSE) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_POFFSET_UR, DEFAULT_POFFSET_UR) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_POFFSET_DL, DEFAULT_POFFSET_DL) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONFIG1, DEFAULT_CONFIG1) ; - - setLEDDrive(DEFAULT_LDRIVE); - - setProximityGain(DEFAULT_PGAIN); - - setAmbientLightGain(DEFAULT_AGAIN); - - setProxIntLowThresh(DEFAULT_PILT) ; - - setProxIntHighThresh(DEFAULT_PIHT); - - setLightIntLowThreshold(DEFAULT_AILT) ; - - setLightIntHighThreshold(DEFAULT_AIHT) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PERS, DEFAULT_PERS) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONFIG2, DEFAULT_CONFIG2) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONFIG3, DEFAULT_CONFIG3) ; - - /* Set default values for gesture sense registers */ - setGestureEnterThresh(DEFAULT_GPENTH); - - setGestureExitThresh(DEFAULT_GEXTH) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF1, DEFAULT_GCONF1) ; - - setGestureGain(DEFAULT_GGAIN) ; - - setGestureLEDDrive(DEFAULT_GLDRIVE) ; - - setGestureWaitTime(DEFAULT_GWTIME) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GOFFSET_U, DEFAULT_GOFFSET) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GOFFSET_D, DEFAULT_GOFFSET) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GOFFSET_L, DEFAULT_GOFFSET) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GOFFSET_R, DEFAULT_GOFFSET) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GPULSE, DEFAULT_GPULSE) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF3, DEFAULT_GCONF3) ; - - setGestureIntEnable(DEFAULT_GIEN); - - disablePower(); // go to sleep - - return true; -} /******************************************************************************* - * Public methods for controlling the APDS-9960 + * Getters and setters for register values ******************************************************************************/ +/** + * @brief Returns the lower threshold for proximity detection + * + * @return lower threshold + */ +uint8_t getProxIntLowThresh(void) { + uint8_t val; + + /* Read value from PILT register */ + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_PILT); + return val; +} + +/** + * @brief Sets the lower threshold for proximity detection + * + * @param[in] threshold the lower proximity threshold + */ +void setProxIntLowThresh(uint8_t threshold) { + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PILT, threshold); +} + +/** + * @brief Returns the high threshold for proximity detection + * + * @return high threshold + */ +uint8_t getProxIntHighThresh(void) { + uint8_t val; + + /* Read value from PIHT register */ + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_PIHT); + return val; +} + +/** + * @brief Sets the high threshold for proximity detection + * + * @param[in] threshold the high proximity threshold + */ +void setProxIntHighThresh(uint8_t threshold) { + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PIHT, threshold); +} + +/** + * @brief Returns LED drive strength for proximity and ALS + * + * Value LED Current + * 0 100 mA + * 1 50 mA + * 2 25 mA + * 3 12.5 mA + * + * @return the value of the LED drive strength. 0xFF on failure. + */ +uint8_t getLEDDrive(void) { + uint8_t val; + + /* Read value from CONTROL register */ + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONTROL); + /* Shift and mask out LED drive bits */ + val = (val >> 6) & 0b00000011; + + return val; +} + +/** + * @brief Sets the LED drive strength for proximity and ALS + * + * Value LED Current + * 0 100 mA + * 1 50 mA + * 2 25 mA + * 3 12.5 mA + * + * @param[in] drive the value (0-3) for the LED drive strength + */ +void setLEDDrive(uint8_t drive) { + uint8_t val; + + /* Read value from CONTROL register */ + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONTROL); + + /* Set bits in register to given value */ + drive &= 0b00000011; + drive = drive << 6; + val &= 0b00111111; + val |= drive; + + /* Write register value back into CONTROL register */ + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONTROL, val); +} + +/** + * @brief Returns receiver gain for proximity detection + * + * Value Gain + * 0 1x + * 1 2x + * 2 4x + * 3 8x + * + * @return the value of the proximity gain. 0xFF on failure. + */ +uint8_t getProximityGain(void) { + uint8_t val; + + /* Read value from CONTROL register */ + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONTROL); + /* Shift and mask out PDRIVE bits */ + val = (val >> 2) & 0b00000011; + + return val; +} + +/** + * @brief Sets the receiver gain for proximity detection + * + * Value Gain + * 0 1x + * 1 2x + * 2 4x + * 3 8x + * + * @param[in] drive the value (0-3) for the gain + */ +void setProximityGain(uint8_t drive) { + uint8_t val; + + /* Read value from CONTROL register */ + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONTROL); + + /* Set bits in register to given value */ + drive &= 0b00000011; + drive = drive << 2; + val &= 0b11110011; + val |= drive; + + /* Write register value back into CONTROL register */ + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONTROL, val); +} + +/** + * @brief Returns receiver gain for the ambient light sensor (ALS) + * + * Value Gain + * 0 1x + * 1 4x + * 2 16x + * 3 64x + * + * @return the value of the ALS gain. 0xFF on failure. + */ + +/** + * @brief Sets the receiver gain for the ambient light sensor (ALS) + * + * Value Gain + * 0 1x + * 1 4x + * 2 16x + * 3 64x + * + * @param[in] drive the value (0-3) for the gain + */ +void setAmbientLightGain(uint8_t drive) { + uint8_t val; + + /* Read value from CONTROL register */ + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONTROL); + + /* Set bits in register to given value */ + drive &= 0b00000011; + val &= 0b11111100; + val |= drive; + + /* Write register value back into CONTROL register */ + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONTROL, val); +} + +/** + * @brief Get the current LED boost value + * + * Value Boost Current + * 0 100% + * 1 150% + * 2 200% + * 3 300% + * + * @return The LED boost value. 0xFF on failure. + */ +uint8_t getLEDBoost(void) { + uint8_t val; + + /* Read value from CONFIG2 register */ + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG2); + + /* Shift and mask out LED_BOOST bits */ + val = (val >> 4) & 0b00000011; + + return val; +} + +/** + * @brief Sets the LED current boost value + * + * Value Boost Current + * 0 100% + * 1 150% + * 2 200% + * 3 300% + * + * @param[in] drive the value (0-3) for current boost (100-300%) + */ +void setLEDBoost(uint8_t boost) { + uint8_t val; + + /* Read value from CONFIG2 register */ + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG2); + /* Set bits in register to given value */ + boost &= 0b00000011; + boost = boost << 4; + val &= 0b11001111; + val |= boost; + + /* Write register value back into CONFIG2 register */ + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONFIG2, val); +} + +/** + * @brief Gets proximity gain compensation enable + * + * @return 1 if compensation is enabled. 0 if not. 0xFF on error. + */ +uint8_t getProxGainCompEnable(void) { + uint8_t val; + + /* Read value from CONFIG3 register */ + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG3); + + /* Shift and mask out PCMP bits */ + val = (val >> 5) & 0b00000001; + + return val; +} + +/** + * @brief Sets the proximity gain compensation enable + * + * @param[in] enable 1 to enable compensation. 0 to disable compensation. + */ +void setProxGainCompEnable(uint8_t enable) { + uint8_t val; + + /* Read value from CONFIG3 register */ + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG3); + + /* Set bits in register to given value */ + enable &= 0b00000001; + enable = enable << 5; + val &= 0b11011111; + val |= enable; + + /* Write register value back into CONFIG3 register */ + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONFIG3, val); +} + +/** + * @brief Gets the current mask for enabled/disabled proximity photodiodes + * + * 1 = disabled, 0 = enabled + * Bit Photodiode + * 3 UP + * 2 DOWN + * 1 LEFT + * 0 RIGHT + * + * @return Current proximity mask for photodiodes. 0xFF on error. + */ +uint8_t getProxPhotoMask(void) { + uint8_t val; + + /* Read value from CONFIG3 register */ + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG3); + + /* Mask out photodiode enable mask bits */ + val &= 0b00001111; + + return val; +} + +/** + * @brief Sets the mask for enabling/disabling proximity photodiodes + * + * 1 = disabled, 0 = enabled + * Bit Photodiode + * 3 UP + * 2 DOWN + * 1 LEFT + * 0 RIGHT + * + * @param[in] mask 4-bit mask value + */ +void setProxPhotoMask(uint8_t mask) { + uint8_t val; + + /* Read value from CONFIG3 register */ + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG3); + + /* Set bits in register to given value */ + mask &= 0b00001111; + val &= 0b11110000; + val |= mask; + + /* Write register value back into CONFIG3 register */ + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONFIG3, val); +} + +/** + * @brief Gets the entry proximity threshold for gesture sensing + * + * @return Current entry proximity threshold. + */ +uint8_t getGestureEnterThresh(void) { + uint8_t val; + + /* Read value from GPENTH register */ + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GPENTH); + + return val; +} + +/** + * @brief Sets the entry proximity threshold for gesture sensing + * + * @param[in] threshold proximity value needed to start gesture mode + */ +void setGestureEnterThresh(uint8_t threshold) { + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GPENTH, threshold); +} + +/** + * @brief Gets the exit proximity threshold for gesture sensing + * + * @return Current exit proximity threshold. + */ +uint8_t getGestureExitThresh(void) { + uint8_t val; + + /* Read value from GEXTH register */ + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GEXTH); + + return val; +} + +/** + * @brief Sets the exit proximity threshold for gesture sensing + * + * @param[in] threshold proximity value needed to end gesture mode + */ +void setGestureExitThresh(uint8_t threshold) { + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GEXTH, threshold); +} + +/** + * @brief Gets the gain of the photodiode during gesture mode + * + * Value Gain + * 0 1x + * 1 2x + * 2 4x + * 3 8x + * + * @return the current photodiode gain. 0xFF on error. + */ +uint8_t getGestureGain(void) { + uint8_t val; + + /* Read value from GCONF2 register */ + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2); + + /* Shift and mask out GGAIN bits */ + val = (val >> 5) & 0b00000011; + + return val; +} + +/** + * @brief Sets the gain of the photodiode during gesture mode + * + * Value Gain + * 0 1x + * 1 2x + * 2 4x + * 3 8x + * + * @param[in] gain the value for the photodiode gain + */ +void setGestureGain(uint8_t gain) { + uint8_t val; + + /* Read value from GCONF2 register */ + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2); + + /* Set bits in register to given value */ + gain &= 0b00000011; + gain = gain << 5; + val &= 0b10011111; + val |= gain; + + /* Write register value back into GCONF2 register */ + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF2, val); +} + +/** + * @brief Gets the drive current of the LED during gesture mode + * + * Value LED Current + * 0 100 mA + * 1 50 mA + * 2 25 mA + * 3 12.5 mA + * + * @return the LED drive current value. 0xFF on error. + */ +uint8_t getGestureLEDDrive(void) { + uint8_t val; + + /* Read value from GCONF2 register */ + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2); + + /* Shift and mask out GLDRIVE bits */ + val = (val >> 3) & 0b00000011; + + return val; +} + +/** + * @brief Sets the LED drive current during gesture mode + * + * Value LED Current + * 0 100 mA + * 1 50 mA + * 2 25 mA + * 3 12.5 mA + * + * @param[in] drive the value for the LED drive current + */ +void setGestureLEDDrive(uint8_t drive) { + uint8_t val; + + /* Read value from GCONF2 register */ + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2); + + /* Set bits in register to given value */ + drive &= 0b00000011; + drive = drive << 3; + val &= 0b11100111; + val |= drive; + + /* Write register value back into GCONF2 register */ + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF2, val); +} + +/** + * @brief Gets the time in low power mode between gesture detections + * + * Value Wait time + * 0 0 ms + * 1 2.8 ms + * 2 5.6 ms + * 3 8.4 ms + * 4 14.0 ms + * 5 22.4 ms + * 6 30.8 ms + * 7 39.2 ms + * + * @return the current wait time between gestures. 0xFF on error. + */ +uint8_t getGestureWaitTime(void) { + uint8_t val; + + /* Read value from GCONF2 register */ + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2); + + /* Mask out GWTIME bits */ + val &= 0b00000111; + + return val; +} + +/** + * @brief Sets the time in low power mode between gesture detections + * + * Value Wait time + * 0 0 ms + * 1 2.8 ms + * 2 5.6 ms + * 3 8.4 ms + * 4 14.0 ms + * 5 22.4 ms + * 6 30.8 ms + * 7 39.2 ms + * + * @param[in] the value for the wait time + */ +void setGestureWaitTime(uint8_t time) { + uint8_t val; + + /* Read value from GCONF2 register */ + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2); + + /* Set bits in register to given value */ + time &= 0b00000111; + val &= 0b11111000; + val |= time; + + /* Write register value back into GCONF2 register */ + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF2, val); +} + +/** + * @brief Gets the low threshold for ambient light interrupts + * + * @param[out] threshold current low threshold stored on the APDS-9960 + */ +void getLightIntLowThreshold(uint16_t &threshold) { + uint8_t val_byte; + threshold = 0; + + /* Read value from ambient light low threshold, low byte register */ + val_byte = I2cRead8(APDS9960_I2C_ADDR, APDS9960_AILTL); + threshold = val_byte; + + /* Read value from ambient light low threshold, high byte register */ + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_AILTH, val_byte); + threshold = threshold + ((uint16_t)val_byte << 8); +} + +/** + * @brief Sets the low threshold for ambient light interrupts + * + * @param[in] threshold low threshold value for interrupt to trigger + */ +void setLightIntLowThreshold(uint16_t threshold) { + uint8_t val_low; + uint8_t val_high; + + /* Break 16-bit threshold into 2 8-bit values */ + val_low = threshold & 0x00FF; + val_high = (threshold & 0xFF00) >> 8; + + /* Write low byte */ + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_AILTL, val_low); + + /* Write high byte */ + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_AILTH, val_high); +} + +/** + * @brief Gets the high threshold for ambient light interrupts + * + * @param[out] threshold current low threshold stored on the APDS-9960 + */ +void getLightIntHighThreshold(uint16_t &threshold) { + uint8_t val_byte; + threshold = 0; + + /* Read value from ambient light high threshold, low byte register */ + val_byte = I2cRead8(APDS9960_I2C_ADDR, APDS9960_AIHTL); + threshold = val_byte; + + /* Read value from ambient light high threshold, high byte register */ + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_AIHTH, val_byte); + threshold = threshold + ((uint16_t)val_byte << 8); +} + +/** + * @brief Sets the high threshold for ambient light interrupts + * + * @param[in] threshold high threshold value for interrupt to trigger + */ +void setLightIntHighThreshold(uint16_t threshold) { + uint8_t val_low; + uint8_t val_high; + + /* Break 16-bit threshold into 2 8-bit values */ + val_low = threshold & 0x00FF; + val_high = (threshold & 0xFF00) >> 8; + + /* Write low byte */ + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_AIHTL, val_low); + + /* Write high byte */ + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_AIHTH, val_high); +} + +/** + * @brief Gets the low threshold for proximity interrupts + * + * @param[out] threshold current low threshold stored on the APDS-9960 + */ +void getProximityIntLowThreshold(uint8_t &threshold) { + threshold = 0; + + /* Read value from proximity low threshold register */ + threshold = I2cRead8(APDS9960_I2C_ADDR, APDS9960_PILT); +} + +/** + * @brief Sets the low threshold for proximity interrupts + * + * @param[in] threshold low threshold value for interrupt to trigger + */ +void setProximityIntLowThreshold(uint8_t threshold) { + /* Write threshold value to register */ + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PILT, threshold); +} + +/** + * @brief Gets the high threshold for proximity interrupts + * + * @param[out] threshold current low threshold stored on the APDS-9960 + */ +void getProximityIntHighThreshold(uint8_t &threshold) { + threshold = 0; + + /* Read value from proximity low threshold register */ + threshold = I2cRead8(APDS9960_I2C_ADDR, APDS9960_PIHT); +} + +/** + * @brief Sets the high threshold for proximity interrupts + * + * @param[in] threshold high threshold value for interrupt to trigger + */ +void setProximityIntHighThreshold(uint8_t threshold) { + /* Write threshold value to register */ + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PIHT, threshold); +} + +/** + * @brief Gets if ambient light interrupts are enabled or not + * + * @return 1 if interrupts are enabled, 0 if not. 0xFF on error. + */ +uint8_t getAmbientLightIntEnable(void) { + uint8_t val; + + /* Read value from ENABLE register */ + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ENABLE); + + /* Shift and mask out AIEN bit */ + val = (val >> 4) & 0b00000001; + + return val; +} + +/** + * @brief Turns ambient light interrupts on or off + * + * @param[in] enable 1 to enable interrupts, 0 to turn them off + */ +void setAmbientLightIntEnable(uint8_t enable) { + uint8_t val; + + /* Read value from ENABLE register */ + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ENABLE); + + /* Set bits in register to given value */ + enable &= 0b00000001; + enable = enable << 4; + val &= 0b11101111; + val |= enable; + + /* Write register value back into ENABLE register */ + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ENABLE, val); +} + +/** + * @brief Gets if proximity interrupts are enabled or not + * + * @return 1 if interrupts are enabled, 0 if not. 0xFF on error. + */ +uint8_t getProximityIntEnable(void) { + uint8_t val; + + /* Read value from ENABLE register */ + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ENABLE); + + /* Shift and mask out PIEN bit */ + val = (val >> 5) & 0b00000001; + + return val; +} + +/** + * @brief Turns proximity interrupts on or off + * + * @param[in] enable 1 to enable interrupts, 0 to turn them off + */ +void setProximityIntEnable(uint8_t enable) { + uint8_t val; + + /* Read value from ENABLE register */ + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ENABLE); + + /* Set bits in register to given value */ + enable &= 0b00000001; + enable = enable << 5; + val &= 0b11011111; + val |= enable; + + /* Write register value back into ENABLE register */ + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ENABLE, val); +} + +/** + * @brief Gets if gesture interrupts are enabled or not + * + * @return 1 if interrupts are enabled, 0 if not. 0xFF on error. + */ +uint8_t getGestureIntEnable(void) { + uint8_t val; + + /* Read value from GCONF4 register */ + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF4); + + /* Shift and mask out GIEN bit */ + val = (val >> 1) & 0b00000001; + + return val; +} + +/** + * @brief Turns gesture-related interrupts on or off + * + * @param[in] enable 1 to enable interrupts, 0 to turn them off + */ +void setGestureIntEnable(uint8_t enable) { + uint8_t val; + + /* Read value from GCONF4 register */ + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF4); + + /* Set bits in register to given value */ + enable &= 0b00000001; + enable = enable << 1; + val &= 0b11111101; + val |= enable; + + /* Write register value back into GCONF4 register */ + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF4, val); +} + +/** + * @brief Clears the ambient light interrupt + * + */ +void clearAmbientLightInt(void) { + uint8_t throwaway; + throwaway = I2cRead8(APDS9960_I2C_ADDR, APDS9960_AICLEAR); +} + +/** + * @brief Clears the proximity interrupt + * + */ +void clearProximityInt(void) { + uint8_t throwaway; + throwaway = I2cRead8(APDS9960_I2C_ADDR, APDS9960_PICLEAR); +} + +/** + * @brief Tells if the gesture state machine is currently running + * + * @return 1 if gesture state machine is running, 0 if not. 0xFF on error. + */ +uint8_t getGestureMode(void) { + uint8_t val; + + /* Read value from GCONF4 register */ + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF4); + + /* Mask out GMODE bit */ + val &= 0b00000001; + + return val; +} + +/** + * @brief Tells the state machine to either enter or exit gesture state machine + * + * @param[in] mode 1 to enter gesture state machine, 0 to exit. + */ +void setGestureMode(uint8_t mode) { + uint8_t val; + + /* Read value from GCONF4 register */ + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF4); + + /* Set bits in register to given value */ + mode &= 0b00000001; + val &= 0b11111110; + val |= mode; + + /* Write register value back into GCONF4 register */ + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF4, val); +} + + +bool APDS9960_init(void) { + /* Set default values for ambient light and proximity registers */ + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ATIME, DEFAULT_ATIME); + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_WTIME, DEFAULT_WTIME); + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PPULSE, DEFAULT_PROX_PPULSE); + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_POFFSET_UR, DEFAULT_POFFSET_UR); + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_POFFSET_DL, DEFAULT_POFFSET_DL); + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONFIG1, DEFAULT_CONFIG1); + + setLEDDrive(DEFAULT_LDRIVE); + setProximityGain(DEFAULT_PGAIN); + setAmbientLightGain(DEFAULT_AGAIN); + setProxIntLowThresh(DEFAULT_PILT); + setProxIntHighThresh(DEFAULT_PIHT); + setLightIntLowThreshold(DEFAULT_AILT); + setLightIntHighThreshold(DEFAULT_AIHT); + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PERS, DEFAULT_PERS); + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONFIG2, DEFAULT_CONFIG2); + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONFIG3, DEFAULT_CONFIG3); + + /* Set default values for gesture sense registers */ + setGestureEnterThresh(DEFAULT_GPENTH); + setGestureExitThresh(DEFAULT_GEXTH); + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF1, DEFAULT_GCONF1); + + setGestureGain(DEFAULT_GGAIN); + setGestureLEDDrive(DEFAULT_GLDRIVE); + setGestureWaitTime(DEFAULT_GWTIME); + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GOFFSET_U, DEFAULT_GOFFSET); + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GOFFSET_D, DEFAULT_GOFFSET); + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GOFFSET_L, DEFAULT_GOFFSET); + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GOFFSET_R, DEFAULT_GOFFSET); + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GPULSE, DEFAULT_GPULSE); + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF3, DEFAULT_GCONF3); + + setGestureIntEnable(DEFAULT_GIEN); + + disablePower(); // go to sleep + + return true; +} + + +/******************************************************************************\ + * Public methods for controlling the APDS-9960 +\******************************************************************************/ + /** * @brief Reads and returns the contents of the ENABLE register * * @return Contents of the ENABLE register. 0xFF if error. */ -uint8_t getMode(void) -{ - uint8_t enable_value; +uint8_t getMode(void) { + uint8_t enable_value; - /* Read current ENABLE register */ - enable_value = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ENABLE) ; + /* Read current ENABLE register */ + enable_value = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ENABLE); - return enable_value; + return enable_value; } /** @@ -1347,32 +1262,30 @@ uint8_t getMode(void) * @param[in] mode which feature to enable * @param[in] enable ON (1) or OFF (0) */ -void setMode(uint8_t mode, uint8_t enable) -{ - uint8_t reg_val; +void setMode(uint8_t mode, uint8_t enable) { + uint8_t reg_val; - /* Read current ENABLE register */ - reg_val = getMode(); + /* Read current ENABLE register */ + reg_val = getMode(); - - /* Change bit(s) in ENABLE register */ - enable = enable & 0x01; - if( mode >= 0 && mode <= 6 ) { - if (enable) { - reg_val |= (1 << mode); - } else { - reg_val &= ~(1 << mode); - } - } else if( mode == ALL ) { - if (enable) { - reg_val = 0x7F; - } else { - reg_val = 0x00; - } + /* Change bit(s) in ENABLE register */ + enable = enable & 0x01; + if (mode >= 0 && mode <= 6) { + if (enable) { + reg_val |= (1 << mode); + } else { + reg_val &= ~(1 << mode); } + } else if (mode == ALL) { + if (enable) { + reg_val = 0x7F; + } else { + reg_val = 0x00; + } + } - /* Write value back to ENABLE register */ - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ENABLE, reg_val) ; + /* Write value back to ENABLE register */ + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ENABLE, reg_val); } /** @@ -1380,23 +1293,21 @@ void setMode(uint8_t mode, uint8_t enable) * * no interrupts */ -void enableLightSensor(void) -{ - /* Set default gain, interrupts, enable power, and enable sensor */ - setAmbientLightGain(DEFAULT_AGAIN); - setAmbientLightIntEnable(0); - enablePower() ; - setMode(AMBIENT_LIGHT, 1) ; +void enableLightSensor(void) { + /* Set default gain, interrupts, enable power, and enable sensor */ + setAmbientLightGain(DEFAULT_AGAIN); + setAmbientLightIntEnable(0); + enablePower(); + setMode(AMBIENT_LIGHT, 1); } /** * @brief Ends the light sensor on the APDS-9960 * */ -void disableLightSensor(void) -{ - setAmbientLightIntEnable(0) ; - setMode(AMBIENT_LIGHT, 0) ; +void disableLightSensor(void) { + setAmbientLightIntEnable(0); + setMode(AMBIENT_LIGHT, 0); } /** @@ -1404,24 +1315,22 @@ void disableLightSensor(void) * * no interrupts */ -void enableProximitySensor(void) -{ - /* Set default gain, LED, interrupts, enable power, and enable sensor */ - setProximityGain(DEFAULT_PGAIN); - setLEDDrive(DEFAULT_LDRIVE) ; - setProximityIntEnable(0) ; - enablePower(); - setMode(PROXIMITY, 1) ; +void enableProximitySensor(void) { + /* Set default gain, LED, interrupts, enable power, and enable sensor */ + setProximityGain(DEFAULT_PGAIN); + setLEDDrive(DEFAULT_LDRIVE); + setProximityIntEnable(0); + enablePower(); + setMode(PROXIMITY, 1); } /** * @brief Ends the proximity sensor on the APDS-9960 * */ -void disableProximitySensor(void) -{ - setProximityIntEnable(0) ; - setMode(PROXIMITY, 0) ; +void disableProximitySensor(void) { + setProximityIntEnable(0); + setMode(PROXIMITY, 0); } /** @@ -1429,37 +1338,35 @@ void disableProximitySensor(void) * * no interrupts */ -void enableGestureSensor(void) -{ - /* Enable gesture mode - Set ENABLE to 0 (power off) - Set WTIME to 0xFF - Set AUX to LED_BOOST_300 - Enable PON, WEN, PEN, GEN in ENABLE - */ +void enableGestureSensor(void) { + /* Enable gesture mode + Set ENABLE to 0 (power off) + Set WTIME to 0xFF + Set AUX to LED_BOOST_300 + Enable PON, WEN, PEN, GEN in ENABLE + */ - resetGestureParameters(); - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_WTIME, 0xFF) ; - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PPULSE, DEFAULT_GESTURE_PPULSE) ; - setLEDBoost(LED_BOOST_100); // tip from jonn26 - 100 for 300 ---- 200 from Adafruit - setGestureIntEnable(0) ; - setGestureMode(1); - enablePower() ; - setMode(WAIT, 1) ; - setMode(PROXIMITY, 1) ; - setMode(GESTURE, 1); + resetGestureParameters(); + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_WTIME, 0xFF); + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PPULSE, DEFAULT_GESTURE_PPULSE); + setLEDBoost(LED_BOOST_100); // tip from jonn26 - 100 for 300 ---- 200 from Adafruit + setGestureIntEnable(0); + setGestureMode(1); + enablePower(); + setMode(WAIT, 1); + setMode(PROXIMITY, 1); + setMode(GESTURE, 1); } /** * @brief Ends the gesture recognition engine on the APDS-9960 * */ -void disableGestureSensor(void) -{ - resetGestureParameters(); - setGestureIntEnable(0) ; - setGestureMode(0) ; - setMode(GESTURE, 0) ; +void disableGestureSensor(void) { + resetGestureParameters(); + setGestureIntEnable(0); + setGestureMode(0); + setMode(GESTURE, 0); } /** @@ -1467,22 +1374,17 @@ void disableGestureSensor(void) * * @return True if gesture available. False otherwise. */ -bool isGestureAvailable(void) -{ - uint8_t val; +bool isGestureAvailable(void) { + uint8_t val; - /* Read value from GSTATUS register */ - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GSTATUS) ; + /* Read value from GSTATUS register */ + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GSTATUS); - /* Shift and mask out GVALID bit */ - val &= APDS9960_GVALID; + /* Shift and mask out GVALID bit */ + val &= APDS9960_GVALID; - /* Return true/false based on GVALID bit */ - if( val == 1) { - return true; - } else { - return false; - } + /* Return true/false based on GVALID bit */ + return (val == 1); } /** @@ -1490,143 +1392,134 @@ bool isGestureAvailable(void) * * @return Number corresponding to gesture. -1 on error. */ -int16_t readGesture(void) -{ - uint8_t fifo_level = 0; - uint8_t bytes_read = 0; - uint8_t fifo_data[128]; - uint8_t gstatus; - uint16_t motion; - uint16_t i; - uint8_t gesture_loop_counter = 0; // don't loop forever later +int16_t readGesture(void) { + uint8_t fifo_level = 0; + uint8_t bytes_read = 0; + uint8_t fifo_data[128]; + uint8_t gstatus; + uint16_t motion; + uint16_t i; + uint8_t gesture_loop_counter = 0; // don't loop forever later - /* Make sure that power and gesture is on and data is valid */ - if( !isGestureAvailable() || !(getMode() & 0b01000001) ) { - return DIR_NONE; + /* Make sure that power and gesture is on and data is valid */ + if (!isGestureAvailable() || !(getMode() & 0b01000001)) { + return DIR_NONE; + } + + /* Keep looping as long as gesture data is valid */ + while (1) { + if (gesture_loop_counter == APDS9960_MAX_GESTURE_CYCLES) { // We will escape after a few loops + disableGestureSensor(); // stop the sensor to prevent problems with power consumption/blocking and return to the main loop + APDS9960_overload = true; // we report this as "long"-gesture + AddLog_P(LOG_LEVEL_DEBUG, PSTR("Sensor overload")); } + gesture_loop_counter += 1; + /* Wait some time to collect next batch of FIFO data */ + delay(FIFO_PAUSE_TIME); - /* Keep looping as long as gesture data is valid */ - while(1) { - if (gesture_loop_counter == APDS9960_MAX_GESTURE_CYCLES){ // We will escape after a few loops - disableGestureSensor(); // stop the sensor to prevent problems with power consumption/blocking and return to the main loop - APDS9960_overload = true; // we report this as "long"-gesture - AddLog_P(LOG_LEVEL_DEBUG, PSTR("Sensor overload")); + /* Get the contents of the STATUS register. Is data still valid? */ + gstatus = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GSTATUS); + + /* If we have valid data, read in FIFO */ + if ((gstatus & APDS9960_GVALID) == APDS9960_GVALID) { + /* Read the current FIFO level */ + fifo_level = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GFLVL); + + /* If there's stuff in the FIFO, read it into our data block */ + if (fifo_level > 0) { + bytes_read = wireReadDataBlock(APDS9960_GFIFO_U, (uint8_t*)fifo_data, (fifo_level * 4)); + if (bytes_read == -1) { + return APDS9960_ERROR; } - gesture_loop_counter += 1; - /* Wait some time to collect next batch of FIFO data */ - delay(FIFO_PAUSE_TIME); - /* Get the contents of the STATUS register. Is data still valid? */ - gstatus = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GSTATUS); + /* If at least 1 set of data, sort the data into U/D/L/R */ + if (bytes_read >= 4) { + for (i = 0; i < bytes_read; i += 4) { + gesture_data_.u_data[gesture_data_.index] = \ + fifo_data[i + 0]; + gesture_data_.d_data[gesture_data_.index] = \ + fifo_data[i + 1]; + gesture_data_.l_data[gesture_data_.index] = \ + fifo_data[i + 2]; + gesture_data_.r_data[gesture_data_.index] = \ + fifo_data[i + 3]; + gesture_data_.index++; + gesture_data_.total_gestures++; + } - /* If we have valid data, read in FIFO */ - if( (gstatus & APDS9960_GVALID) == APDS9960_GVALID ) { - - /* Read the current FIFO level */ - fifo_level = I2cRead8(APDS9960_I2C_ADDR,APDS9960_GFLVL) ; - - /* If there's stuff in the FIFO, read it into our data block */ - if( fifo_level > 0) { - bytes_read = wireReadDataBlock( APDS9960_GFIFO_U, - (uint8_t*)fifo_data, - (fifo_level * 4) ); - if( bytes_read == -1 ) { - return APDS9960_ERROR; - } - - /* If at least 1 set of data, sort the data into U/D/L/R */ - if( bytes_read >= 4 ) { - for( i = 0; i < bytes_read; i += 4 ) { - gesture_data_.u_data[gesture_data_.index] = \ - fifo_data[i + 0]; - gesture_data_.d_data[gesture_data_.index] = \ - fifo_data[i + 1]; - gesture_data_.l_data[gesture_data_.index] = \ - fifo_data[i + 2]; - gesture_data_.r_data[gesture_data_.index] = \ - fifo_data[i + 3]; - gesture_data_.index++; - gesture_data_.total_gestures++; - } - /* Filter and process gesture data. Decode near/far state */ - if( processGestureData() ) { - if( decodeGesture() ) { - //***TODO: U-Turn Gestures - } - } - /* Reset data */ - gesture_data_.index = 0; - gesture_data_.total_gestures = 0; - } - } - } else { - - /* Determine best guessed gesture and clean up */ - delay(FIFO_PAUSE_TIME); - decodeGesture(); - motion = gesture_motion_; - resetGestureParameters(); - return motion; + /* Filter and process gesture data. Decode near/far state */ + if (processGestureData()) { + if (decodeGesture()) { + // TODO(xx): U-Turn Gestures + } + } + /* Reset data */ + gesture_data_.index = 0; + gesture_data_.total_gestures = 0; } + } + } else { + /* Determine best guessed gesture and clean up */ + delay(FIFO_PAUSE_TIME); + decodeGesture(); + motion = gesture_motion_; + resetGestureParameters(); + return motion; } + } } /** * Turn the APDS-9960 on * */ -void enablePower(void) -{ - setMode(POWER, 1) ; +void enablePower(void) { + setMode(POWER, 1); } /** * Turn the APDS-9960 off * */ -void disablePower(void) -{ - setMode(POWER, 0) ; +void disablePower(void) { + setMode(POWER, 0); } -/******************************************************************************* + +/******************************************************************************\ * Ambient light and color sensor controls - ******************************************************************************/ +\******************************************************************************/ - /** - * @brief Reads the ARGB-Data and fills color_data - * - */ - -void readAllColorAndProximityData(void) -{ - if (I2cReadBuffer(APDS9960_I2C_ADDR, APDS9960_CDATAL, (uint8_t *) &color_data, (uint16_t)9)) - { +/** + * @brief Reads the ARGB-Data and fills color_data + */ +void readAllColorAndProximityData(void) { + if (I2cReadBuffer(APDS9960_I2C_ADDR, APDS9960_CDATAL, (uint8_t *) &color_data, (uint16_t)9)) { // not absolutely shure, if this is a correct way to do this, but it is very short // we fill the struct byte by byte } } -/******************************************************************************* + +/******************************************************************************\ * High-level gesture controls - ******************************************************************************/ +\******************************************************************************/ /** * @brief Resets all the parameters in the gesture data member */ -void resetGestureParameters(void) -{ - gesture_data_.index = 0; - gesture_data_.total_gestures = 0; +void resetGestureParameters(void) { + gesture_data_.index = 0; + gesture_data_.total_gestures = 0; - gesture_ud_delta_ = 0; - gesture_lr_delta_ = 0; + gesture_ud_delta_ = 0; + gesture_lr_delta_ = 0; - gesture_ud_count_ = 0; - gesture_lr_count_ = 0; + gesture_ud_count_ = 0; + gesture_lr_count_ = 0; - gesture_state_ = 0; - gesture_motion_ = DIR_NONE; + gesture_state_ = 0; + gesture_motion_ = DIR_NONE; } /** @@ -1634,103 +1527,97 @@ void resetGestureParameters(void) * * @return True if near or far state seen. False otherwise. */ -bool processGestureData(void) -{ - uint8_t u_first = 0; - uint8_t d_first = 0; - uint8_t l_first = 0; - uint8_t r_first = 0; - uint8_t u_last = 0; - uint8_t d_last = 0; - uint8_t l_last = 0; - uint8_t r_last = 0; - uint16_t ud_ratio_first; - uint16_t lr_ratio_first; - uint16_t ud_ratio_last; - uint16_t lr_ratio_last; - uint16_t ud_delta; - uint16_t lr_delta; - uint16_t i; +bool processGestureData(void) { + uint8_t u_first = 0; + uint8_t d_first = 0; + uint8_t l_first = 0; + uint8_t r_first = 0; + uint8_t u_last = 0; + uint8_t d_last = 0; + uint8_t l_last = 0; + uint8_t r_last = 0; + uint16_t ud_ratio_first; + uint16_t lr_ratio_first; + uint16_t ud_ratio_last; + uint16_t lr_ratio_last; + uint16_t ud_delta; + uint16_t lr_delta; + uint16_t i; - /* If we have less than 4 total gestures, that's not enough */ - if( gesture_data_.total_gestures <= 4 ) { - return false; - } - - /* Check to make sure our data isn't out of bounds */ - if( (gesture_data_.total_gestures <= 32) && \ - (gesture_data_.total_gestures > 0) ) { - - /* Find the first value in U/D/L/R above the threshold */ - for( i = 0; i < gesture_data_.total_gestures; i++ ) { - if( (gesture_data_.u_data[i] > GESTURE_THRESHOLD_OUT) && - (gesture_data_.d_data[i] > GESTURE_THRESHOLD_OUT) && - (gesture_data_.l_data[i] > GESTURE_THRESHOLD_OUT) && - (gesture_data_.r_data[i] > GESTURE_THRESHOLD_OUT) ) { - - u_first = gesture_data_.u_data[i]; - d_first = gesture_data_.d_data[i]; - l_first = gesture_data_.l_data[i]; - r_first = gesture_data_.r_data[i]; - break; - } - } - - /* If one of the _first values is 0, then there is no good data */ - if( (u_first == 0) || (d_first == 0) || \ - (l_first == 0) || (r_first == 0) ) { - - return false; - } - /* Find the last value in U/D/L/R above the threshold */ - for( i = gesture_data_.total_gestures - 1; i >= 0; i-- ) { - - if( (gesture_data_.u_data[i] > GESTURE_THRESHOLD_OUT) && - (gesture_data_.d_data[i] > GESTURE_THRESHOLD_OUT) && - (gesture_data_.l_data[i] > GESTURE_THRESHOLD_OUT) && - (gesture_data_.r_data[i] > GESTURE_THRESHOLD_OUT) ) { - - u_last = gesture_data_.u_data[i]; - d_last = gesture_data_.d_data[i]; - l_last = gesture_data_.l_data[i]; - r_last = gesture_data_.r_data[i]; - break; - } - } - } - - /* Calculate the first vs. last ratio of up/down and left/right */ - ud_ratio_first = ((u_first - d_first) * 100) / (u_first + d_first); - lr_ratio_first = ((l_first - r_first) * 100) / (l_first + r_first); - ud_ratio_last = ((u_last - d_last) * 100) / (u_last + d_last); - lr_ratio_last = ((l_last - r_last) * 100) / (l_last + r_last); - - /* Determine the difference between the first and last ratios */ - ud_delta = ud_ratio_last - ud_ratio_first; - lr_delta = lr_ratio_last - lr_ratio_first; - - /* Accumulate the UD and LR delta values */ - gesture_ud_delta_ += ud_delta; - gesture_lr_delta_ += lr_delta; - - /* Determine U/D gesture */ - if( gesture_ud_delta_ >= GESTURE_SENSITIVITY_1 ) { - gesture_ud_count_ = 1; - } else if( gesture_ud_delta_ <= -GESTURE_SENSITIVITY_1 ) { - gesture_ud_count_ = -1; - } else { - gesture_ud_count_ = 0; - } - - /* Determine L/R gesture */ - if( gesture_lr_delta_ >= GESTURE_SENSITIVITY_1 ) { - gesture_lr_count_ = 1; - } else if( gesture_lr_delta_ <= -GESTURE_SENSITIVITY_1 ) { - gesture_lr_count_ = -1; - } else { - gesture_lr_count_ = 0; - } + /* If we have less than 4 total gestures, that's not enough */ + if (gesture_data_.total_gestures <= 4) { return false; + } + + /* Check to make sure our data isn't out of bounds */ + if ((gesture_data_.total_gestures <= 32) && \ + (gesture_data_.total_gestures > 0)) { + /* Find the first value in U/D/L/R above the threshold */ + for (i = 0; i < gesture_data_.total_gestures; i++) { + if ((gesture_data_.u_data[i] > GESTURE_THRESHOLD_OUT) && + (gesture_data_.d_data[i] > GESTURE_THRESHOLD_OUT) && + (gesture_data_.l_data[i] > GESTURE_THRESHOLD_OUT) && + (gesture_data_.r_data[i] > GESTURE_THRESHOLD_OUT) ) { + u_first = gesture_data_.u_data[i]; + d_first = gesture_data_.d_data[i]; + l_first = gesture_data_.l_data[i]; + r_first = gesture_data_.r_data[i]; + break; + } + } + + /* If one of the _first values is 0, then there is no good data */ + if ((u_first == 0) || (d_first == 0) || (l_first == 0) || (r_first == 0)) { + return false; + } + + /* Find the last value in U/D/L/R above the threshold */ + for (i = gesture_data_.total_gestures - 1; i >= 0; i--) { + if ((gesture_data_.u_data[i] > GESTURE_THRESHOLD_OUT) && + (gesture_data_.d_data[i] > GESTURE_THRESHOLD_OUT) && + (gesture_data_.l_data[i] > GESTURE_THRESHOLD_OUT) && + (gesture_data_.r_data[i] > GESTURE_THRESHOLD_OUT)) { + u_last = gesture_data_.u_data[i]; + d_last = gesture_data_.d_data[i]; + l_last = gesture_data_.l_data[i]; + r_last = gesture_data_.r_data[i]; + break; + } + } + } + + /* Calculate the first vs. last ratio of up/down and left/right */ + ud_ratio_first = ((u_first - d_first) * 100) / (u_first + d_first); + lr_ratio_first = ((l_first - r_first) * 100) / (l_first + r_first); + ud_ratio_last = ((u_last - d_last) * 100) / (u_last + d_last); + lr_ratio_last = ((l_last - r_last) * 100) / (l_last + r_last); + + /* Determine the difference between the first and last ratios */ + ud_delta = ud_ratio_last - ud_ratio_first; + lr_delta = lr_ratio_last - lr_ratio_first; + + /* Accumulate the UD and LR delta values */ + gesture_ud_delta_ += ud_delta; + gesture_lr_delta_ += lr_delta; + + /* Determine U/D gesture */ + if (gesture_ud_delta_ >= GESTURE_SENSITIVITY_1) { + gesture_ud_count_ = 1; + } else if (gesture_ud_delta_ <= -GESTURE_SENSITIVITY_1) { + gesture_ud_count_ = -1; + } else { + gesture_ud_count_ = 0; + } + + /* Determine L/R gesture */ + if (gesture_lr_delta_ >= GESTURE_SENSITIVITY_1) { + gesture_lr_count_ = 1; + } else if (gesture_lr_delta_ <= -GESTURE_SENSITIVITY_1) { + gesture_lr_count_ = -1; + } else { + gesture_lr_count_ = 0; + } + return false; } /** @@ -1738,51 +1625,49 @@ bool processGestureData(void) * * @return True if near/far event. False otherwise. */ -bool decodeGesture(void) -{ - - /* Determine swipe direction */ - if( (gesture_ud_count_ == -1) && (gesture_lr_count_ == 0) ) { - gesture_motion_ = DIR_UP; - } else if( (gesture_ud_count_ == 1) && (gesture_lr_count_ == 0) ) { - gesture_motion_ = DIR_DOWN; - } else if( (gesture_ud_count_ == 0) && (gesture_lr_count_ == 1) ) { - gesture_motion_ = DIR_RIGHT; - } else if( (gesture_ud_count_ == 0) && (gesture_lr_count_ == -1) ) { - gesture_motion_ = DIR_LEFT; - } else if( (gesture_ud_count_ == -1) && (gesture_lr_count_ == 1) ) { - if( abs(gesture_ud_delta_) > abs(gesture_lr_delta_) ) { - gesture_motion_ = DIR_UP; - } else { - gesture_motion_ = DIR_RIGHT; - } - } else if( (gesture_ud_count_ == 1) && (gesture_lr_count_ == -1) ) { - if( abs(gesture_ud_delta_) > abs(gesture_lr_delta_) ) { - gesture_motion_ = DIR_DOWN; - } else { - gesture_motion_ = DIR_LEFT; - } - } else if( (gesture_ud_count_ == -1) && (gesture_lr_count_ == -1) ) { - if( abs(gesture_ud_delta_) > abs(gesture_lr_delta_) ) { - gesture_motion_ = DIR_UP; - } else { - gesture_motion_ = DIR_LEFT; - } - } else if( (gesture_ud_count_ == 1) && (gesture_lr_count_ == 1) ) { - if( abs(gesture_ud_delta_) > abs(gesture_lr_delta_) ) { - gesture_motion_ = DIR_DOWN; - } else { - gesture_motion_ = DIR_RIGHT; - } +bool decodeGesture(void) { + /* Determine swipe direction */ + if ((gesture_ud_count_ == -1) && (gesture_lr_count_ == 0)) { + gesture_motion_ = DIR_UP; + } else if ((gesture_ud_count_ == 1) && (gesture_lr_count_ == 0)) { + gesture_motion_ = DIR_DOWN; + } else if ((gesture_ud_count_ == 0) && (gesture_lr_count_ == 1)) { + gesture_motion_ = DIR_RIGHT; + } else if ((gesture_ud_count_ == 0) && (gesture_lr_count_ == -1)) { + gesture_motion_ = DIR_LEFT; + } else if ((gesture_ud_count_ == -1) && (gesture_lr_count_ == 1)) { + if (abs(gesture_ud_delta_) > abs(gesture_lr_delta_)) { + gesture_motion_ = DIR_UP; } else { - return false; + gesture_motion_ = DIR_RIGHT; } + } else if ((gesture_ud_count_ == 1) && (gesture_lr_count_ == -1)) { + if (abs(gesture_ud_delta_) > abs(gesture_lr_delta_)) { + gesture_motion_ = DIR_DOWN; + } else { + gesture_motion_ = DIR_LEFT; + } + } else if ((gesture_ud_count_ == -1) && (gesture_lr_count_ == -1)) { + if (abs(gesture_ud_delta_) > abs(gesture_lr_delta_)) { + gesture_motion_ = DIR_UP; + } else { + gesture_motion_ = DIR_LEFT; + } + } else if ((gesture_ud_count_ == 1) && (gesture_lr_count_ == 1)) { + if (abs(gesture_ud_delta_) > abs(gesture_lr_delta_)) { + gesture_motion_ = DIR_DOWN; + } else { + gesture_motion_ = DIR_RIGHT; + } + } else { + return false; + } - return true; + return true; } void handleGesture(void) { - if (isGestureAvailable() ) { + if (isGestureAvailable()) { switch (readGesture()) { case DIR_UP: AddLog_P(LOG_LEVEL_DEBUG, PSTR("UP")); @@ -1801,87 +1686,80 @@ void handleGesture(void) { snprintf_P(currentGesture, sizeof(currentGesture), PSTR("Right")); break; default: - if(APDS9960_overload) - { - AddLog_P(LOG_LEVEL_DEBUG, PSTR("LONG")); - snprintf_P(currentGesture, sizeof(currentGesture), PSTR("Long")); - } - else{ - AddLog_P(LOG_LEVEL_DEBUG, PSTR("NONE")); - snprintf_P(currentGesture, sizeof(currentGesture), PSTR("None")); - } + if (APDS9960_overload) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("LONG")); + snprintf_P(currentGesture, sizeof(currentGesture), PSTR("Long")); + } else { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("NONE")); + snprintf_P(currentGesture, sizeof(currentGesture), PSTR("None")); + } + break; } MqttPublishSensor(); } } -void APDS9960_adjustATime(void) // not really used atm -{ - //readAllColorAndProximityData(); +void APDS9960_adjustATime(void) { // not really used atm + // readAllColorAndProximityData(); I2cValidRead16LE(&color_data.a, APDS9960_I2C_ADDR, APDS9960_CDATAL); - //disablePower(); + // disablePower(); - if (color_data.a < (uint16_t)20){ + if (color_data.a < (uint16_t)20) { APDS9960_aTime = 0x40; - } - else if (color_data.a < (uint16_t)40){ + } else if (color_data.a < (uint16_t)40) { APDS9960_aTime = 0x80; - } - else if (color_data.a < (uint16_t)50){ + } else if (color_data.a < (uint16_t)50) { APDS9960_aTime = DEFAULT_ATIME; - } - else if (color_data.a < (uint16_t)70){ + } else if (color_data.a < (uint16_t)70) { APDS9960_aTime = 0xc0; } - if (color_data.a < 200){ + + if (color_data.a < 200) { APDS9960_aTime = 0xe9; } -/* if (color_data.a < 10000){ + /* if (color_data.a < 10000){ APDS9960_aTime = 0xF0; }*/ - else{ + else { APDS9960_aTime = 0xff; } - //disableLightSensor(); + // disableLightSensor(); I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ATIME, APDS9960_aTime); enablePower(); enableLightSensor(); delay(20); } - -void APDS9960_loop(void) -{ - if (recovery_loop_counter > 0){ +void APDS9960_loop(void) { + if (recovery_loop_counter > 0) { recovery_loop_counter -= 1; } - if (recovery_loop_counter == 1 && APDS9960_overload){ //restart sensor just before the end of recovery from long press + + if (recovery_loop_counter == 1 && APDS9960_overload) { // restart sensor just before the end of recovery from long press enableGestureSensor(); APDS9960_overload = false; Response_P(PSTR("{\"Gesture\":\"On\"}")); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, mqtt_data); // only after the long break we report, that we are online again + MqttPublishPrefixTopic_P(RESULT_OR_TELE, mqtt_data); // only after the long break we report, that we are online again gesture_mode = 1; } if (gesture_mode) { - if (recovery_loop_counter == 0){ + if (recovery_loop_counter == 0) { handleGesture(); - if (APDS9960_overload) - { + if (APDS9960_overload) { disableGestureSensor(); recovery_loop_counter = APDS9960_LONG_RECOVERY; // long pause after overload/long press - number of stateloops Response_P(PSTR("{\"Gesture\":\"Off\"}")); MqttPublishPrefixTopic_P(RESULT_OR_TELE, mqtt_data); gesture_mode = 0; - } } + } } } -void APDS9960_detect(void) -{ +void APDS9960_detect(void) { if (APDS9960type || I2cActive(APDS9960_I2C_ADDR)) { return; } APDS9960type = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ID); @@ -1897,6 +1775,7 @@ void APDS9960_detect(void) } else { APDS9960type = 0; } + currentGesture[0] = '\0'; } @@ -1904,8 +1783,7 @@ void APDS9960_detect(void) * Presentation \*********************************************************************************************/ -void APDS9960_show(bool json) -{ +void APDS9960_show(bool json) { if (!APDS9960type) { return; } if (!gesture_mode && !APDS9960_overload) { @@ -1918,29 +1796,28 @@ void APDS9960_show(bool json) readAllColorAndProximityData(); - sprintf (ambient_chr, "%u", color_data.a/4); - sprintf (red_chr, "%u", color_data.r); - sprintf (green_chr, "%u", color_data.g); - sprintf (blue_chr, "%u", color_data.b ); - sprintf (prox_chr, "%u", color_data.p ); + sprintf(ambient_chr, "%u", color_data.a/4); + sprintf(red_chr, "%u", color_data.r); + sprintf(green_chr, "%u", color_data.g); + sprintf(blue_chr, "%u", color_data.b); + sprintf(prox_chr, "%u", color_data.p); - /* disableLightSensor(); + /* disableLightSensor(); I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ATIME, DEFAULT_ATIME); // reset to default enableLightSensor();*/ calculateColorTemperature(); // and calculate Lux - sprintf (cct_chr, "%u", color_data.cct); + sprintf(cct_chr, "%u", color_data.cct); if (json) { ResponseAppend_P(PSTR(",\"%s\":{\"Red\":%s,\"Green\":%s,\"Blue\":%s,\"Ambient\":%s,\"CCT\":%s,\"Proximity\":%s}"), APDS9960stype, red_chr, green_chr, blue_chr, ambient_chr, cct_chr, prox_chr); #ifdef USE_WEBSERVER } else { - WSContentSend_PD(HTTP_APDS_9960_SNS, red_chr, green_chr, blue_chr, ambient_chr, cct_chr, prox_chr ); + WSContentSend_PD(HTTP_APDS_9960_SNS, red_chr, green_chr, blue_chr, ambient_chr, cct_chr, prox_chr); #endif // USE_WEBSERVER } - } - else { + } else { if (json && (currentGesture[0] != '\0' )) { ResponseAppend_P(PSTR(",\"%s\":{\"%s\":1}"), APDS9960stype, currentGesture); currentGesture[0] = '\0'; @@ -1959,18 +1836,17 @@ void APDS9960_show(bool json) * Sensor27 | 2 / On | Enable gesture mode with half gain \*********************************************************************************************/ -bool APDS9960CommandSensor(void) -{ +bool APDS9960CommandSensor(void) { bool serviced = true; switch (XdrvMailbox.payload) { - case 0: // Off + case 0: // Off disableGestureSensor(); gesture_mode = 0; enableLightSensor(); - APDS9960_overload = false; // prevent unwanted re-enabling + APDS9960_overload = false; // prevent unwanted re-enabling break; - case 1: // On with default gain of 4x + case 1: // On with default gain of 4x if (APDS9960type) { setGestureGain(DEFAULT_GGAIN); setProximityGain(DEFAULT_PGAIN); @@ -1990,13 +1866,13 @@ bool APDS9960CommandSensor(void) break; default: int temp_aTime = (uint8_t)XdrvMailbox.payload; - if (temp_aTime > 2 && temp_aTime < 256){ + if (temp_aTime > 2 && temp_aTime < 256) { disablePower(); I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ATIME, temp_aTime); enablePower(); enableLightSensor(); } - break; + break; } Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_27, GetStateText(gesture_mode)); @@ -2007,28 +1883,26 @@ bool APDS9960CommandSensor(void) * Interface \*********************************************************************************************/ -bool Xsns27(uint8_t function) -{ +bool Xsns27(uint8_t function) { if (!I2cEnabled(XI2C_21)) { return false; } bool result = false; if (FUNC_INIT == function) { APDS9960_detect(); - } - else if (APDS9960type) { + } else if (APDS9960type) { switch (function) { case FUNC_EVERY_50_MSECOND: - APDS9960_loop(); - break; + APDS9960_loop(); + break; case FUNC_COMMAND_SENSOR: - if (XSNS_27 == XdrvMailbox.index) { + if (XSNS_27 == XdrvMailbox.index) { result = APDS9960CommandSensor(); - } - break; + } + break; case FUNC_JSON_APPEND: - APDS9960_show(1); - break; + APDS9960_show(1); + break; #ifdef USE_WEBSERVER case FUNC_WEB_SENSOR: APDS9960_show(0); @@ -2038,5 +1912,6 @@ bool Xsns27(uint8_t function) } return result; } + #endif // USE_APDS9960 #endif // USE_I2C