From 0464bd364d9fbe0ca599e73459f629178d053a49 Mon Sep 17 00:00:00 2001 From: Mickael Gaillard Date: Sun, 26 Apr 2020 19:35:11 +0200 Subject: [PATCH 1/3] use builtin function for readBuffer Signed-off-by: Mickael Gaillard --- tasmota/xsns_27_apds9960.ino | 52 +++--------------------------------- 1 file changed, 3 insertions(+), 49 deletions(-) diff --git a/tasmota/xsns_27_apds9960.ino b/tasmota/xsns_27_apds9960.ino index e55deb276..1efef4680 100644 --- a/tasmota/xsns_27_apds9960.ino +++ b/tasmota/xsns_27_apds9960.ino @@ -333,53 +333,6 @@ uint8_t gesture_mode = 1; * 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; - } - - return true; -} - -/** - * @brief Reads a block (array) of bytes from the I2C device and register - * - * @param[in] reg the register to read from - * @param[out] val pointer to the beginning of the data - * @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; - - /* 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++; - } - - return i; -} - /** * Taken from the Adafruit-library * @brief Converts the raw R/G/B values to color temperature in degrees @@ -1494,8 +1447,9 @@ int16_t readGesture(void) { /* 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) { + bytes_read = (fifo_level * 4); + + if (I2cReadBuffer(APDS9960_I2C_ADDR, APDS9960_GFIFO_U, (uint8_t*)fifo_data, bytes_read)) { return APDS9960_ERROR; } From f8fabfe03502989d52a0b065a05e78be55edf82a Mon Sep 17 00:00:00 2001 From: Mickael Gaillard Date: Sun, 26 Apr 2020 19:44:25 +0200 Subject: [PATCH 2/3] Refactor code Signed-off-by: Mickael Gaillard --- tasmota/xsns_27_apds9960.ino | 140 ++++++++++++++++++++--------------- 1 file changed, 82 insertions(+), 58 deletions(-) diff --git a/tasmota/xsns_27_apds9960.ino b/tasmota/xsns_27_apds9960.ino index 1efef4680..141373801 100644 --- a/tasmota/xsns_27_apds9960.ino +++ b/tasmota/xsns_27_apds9960.ino @@ -33,12 +33,9 @@ * Source: Shawn Hymel (SparkFun Electronics) * Adaption for TASMOTA: Christian Baars * - * I2C Address: 0x39 + * I2C Address: 0x39 - standard address \*********************************************************************************************/ -#define XSNS_27 27 -#define XI2C_21 21 // See I2CDEVICES.md - // #if defined(USE_SHT) || defined(USE_VEML6070) || defined(USE_TSL2561) // #warning **** Turned off conflicting drivers SHT and VEML6070 **** // #ifdef USE_SHT @@ -51,6 +48,9 @@ // #undef USE_TSL2561 // possible address conflict on the I2C-bus // #endif // #endif +#define XSNS_27 27 +#define XI2C_21 21 // See I2CDEVICES.md + #define APDS9960_I2C_ADDR 0x39 @@ -61,7 +61,12 @@ #define APDS9930_CHIPID_1 0x12 // we will check, if someone got an incorrect sensor #define APDS9930_CHIPID_2 0x39 // there are case reports about "accidentially bought" 9930's -#define APDS9960_GESTURE // Enable Gesture feature(2k on flash) + +// TODO() : Move to my_user_config.h file +#define USE_APDS9960_GESTURE // Enable Gesture feature (+2k code) +#define USE_APDS9960_PROXIMITY // Enable Proximity feature (Not use) +#define USE_APDS9960_COLOR // Enable Color feature (Not use) + /* Gesture parameters */ #define GESTURE_THRESHOLD_OUT 10 @@ -71,36 +76,44 @@ #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 -const char APDS9960_TAG[] = "APDS9960"; - -#ifdef USE_WEBSERVER -#ifdef APDS9960_GESTURE +// TODO() : Move to Translate file #define D_GESTURE "Gesture" - -const char HTTP_SNS_GESTURE[] PROGMEM = "{s}%s " D_GESTURE "{m}%s{e}"; - -#endif // APDS9960_GESTURE - #define D_COLOR_RED "Red" #define D_COLOR_GREEN "Green" #define D_COLOR_BLUE "Blue" #define D_CCT "CCT" #define D_PROXIMITY "Proximity" +#define D_UNIT_KELVIN "°K" + +/******************************************************************************\ + * constants +\******************************************************************************/ + +const char APDS9960_TAG[] PROGMEM = "APDS9960"; // Only one actualy + +#ifdef USE_WEBSERVER + +#ifdef USE_APDS9960_GESTURE + +const char HTTP_SNS_GESTURE[] PROGMEM = "{s}%s " D_GESTURE "{m}%s{e}"; + +#endif // USE_APDS9960_GESTURE + const char HTTP_SNS_COLOR_RED[] PROGMEM = "{s}%s " D_COLOR_RED "{m}%u{e}"; const char HTTP_SNS_COLOR_GREEN[] PROGMEM = "{s}%s " D_COLOR_GREEN "{m}%u{e}"; const char HTTP_SNS_COLOR_BLUE[] PROGMEM = "{s}%s " D_COLOR_BLUE "{m}%u{e}"; -const char HTTP_SNS_CCT[] PROGMEM = "{s}%s " D_CCT "{m}%u " "K" "{e}"; +const char HTTP_SNS_CCT[] PROGMEM = "{s}%s " D_CCT "{m}%u " D_UNIT_KELVIN "{e}"; const char HTTP_SNS_PROXIMITY[] PROGMEM = "{s}%s " D_PROXIMITY "{m}%u{e}"; #endif // USE_WEBSERVER -/*********************************************************************************************\ +/******************************************************************************\ * APDS9960 * * Programmer : APDS9960 Datasheet and Sparkfun -\*********************************************************************************************/ +\******************************************************************************/ /* Misc parameters */ #define FIFO_PAUSE_TIME 30 // Wait period (ms) between FIFO reads @@ -164,6 +177,7 @@ const char HTTP_SNS_PROXIMITY[] PROGMEM = "{s}%s " D_PROXIMITY "{m}%u{e}"; #define APDS9960_AIEN 0b00010000 #define APDS9960_PIEN 0b00100000 #define APDS9960_GEN 0b01000000 + #define APDS9960_GVALID 0b00000001 /* On/Off definitions */ @@ -220,6 +234,8 @@ const char HTTP_SNS_PROXIMITY[] PROGMEM = "{s}%s " D_PROXIMITY "{m}%u{e}"; #define GWTIME_30_8MS 6 #define GWTIME_39_2MS 7 + + /* Default values */ #define DEFAULT_ATIME 0xdb // 103ms = 0xdb = 219 #define DEFAULT_WTIME 246 // 27ms @@ -251,7 +267,8 @@ const char HTTP_SNS_PROXIMITY[] PROGMEM = "{s}%s " D_PROXIMITY "{m}%u{e}"; #define APDS9960_ERROR 0xFF -#ifdef APDS9960_GESTURE +#ifdef USE_APDS9960_GESTURE + /* Direction definitions */ const char GESTURE_UP[] PROGMEM = "Up"; const char GESTURE_DOWN[] PROGMEM = "Down"; @@ -302,7 +319,7 @@ typedef struct gesture_type { int16_t motion_ = DIR_NONE; } gesture_t; -#endif // APDS9960_GESTURE +#endif // USE_APDS9960_GESTURE typedef struct color_data_type { uint16_t a; // measured ambient @@ -310,23 +327,30 @@ typedef struct color_data_type { uint16_t g; // Green uint16_t b; // Blue uint8_t p; // proximity + uint16_t cct; // calculated color temperature uint16_t lux; // calculated illuminance - atm only from rgb } color_data_t; -/*Members*/ -#ifdef APDS9960_GESTURE +/******************************************************************************\ + * Globals +\******************************************************************************/ + +#ifdef USE_APDS9960_GESTURE + gesture_data_t gesture_data; gesture_t gesture; -#endif // APDS9960_GESTURE + +#endif // USE_APDS9960_GESTURE +char currentGesture[6]; + color_data_t color_data; volatile uint8_t recovery_loop_counter = 0; // count number of stateloops to switch the sensor off, if needed bool APDS9960_overload = false; -char currentGesture[6]; uint8_t APDS9960_aTime = DEFAULT_ATIME; -uint8_t APDS9960type = 0; +uint8_t APDS9960_type = 0; uint8_t gesture_mode = 1; /******************************************************************************\ @@ -365,9 +389,9 @@ void calculateColorTemperature(void) { return; } -/******************************************************************************* +/******************************************************************************\ * Getters and setters for register values - ******************************************************************************/ +\******************************************************************************/ /** * @brief Returns the lower threshold for proximity detection @@ -703,7 +727,7 @@ void setProxPhotoMask(uint8_t mask) { I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONFIG3, val); } -#ifdef APDS9960_GESTURE +#ifdef USE_APDS9960_GESTURE /** * @brief Gets the entry proximity threshold for gesture sensing @@ -908,7 +932,7 @@ void setGestureWaitTime(uint8_t time) { I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF2, val); } -#endif // APDS9960_GESTURE +#endif // USE_APDS9960_GESTURE /** * @brief Gets the low threshold for ambient light interrupts @@ -1224,7 +1248,7 @@ bool APDS9960_init(void) { I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONFIG3, DEFAULT_CONFIG3); /* Set default values for gesture sense registers */ -#ifdef APDS9960_GESTURE +#ifdef USE_APDS9960_GESTURE setGestureEnterThresh(DEFAULT_GPENTH); setGestureExitThresh(DEFAULT_GEXTH); @@ -1243,8 +1267,8 @@ bool APDS9960_init(void) { I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF3, DEFAULT_GCONF3); setGestureIntEnable(DEFAULT_GIEN); - -#endif // APDS9960_GESTURE + +#endif // USE_APDS9960_GESTURE disablePower(); // go to sleep @@ -1347,7 +1371,7 @@ void disableProximitySensor(void) { setMode(PROXIMITY, OFF); } -#ifdef APDS9960_GESTURE +#ifdef USE_APDS9960_GESTURE /** * @brief Starts the gesture recognition engine on the APDS-9960 * @@ -1496,7 +1520,7 @@ int16_t readGesture(void) { } } -#endif // APDS9960_GESTURE +#endif // USE_APDS9960_GESTURE /** * Turn the APDS-9960 on @@ -1534,7 +1558,7 @@ void readAllColorAndProximityData(void) { * High-level gesture controls \******************************************************************************/ -#ifdef APDS9960_GESTURE +#ifdef USE_APDS9960_GESTURE /** * @brief Resets all the parameters in the gesture data member @@ -1730,7 +1754,7 @@ void handleGesture(void) { } } -#endif // APDS9960_GESTURE +#endif // USE_APDS9960_GESTURE void APDS9960_adjustATime(void) { // not really used atm // readAllColorAndProximityData(); @@ -1764,7 +1788,7 @@ void APDS9960_adjustATime(void) { // not really used atm delay(20); } -#ifdef APDS9960_GESTURE +#ifdef USE_APDS9960_GESTURE void APDS9960_loop(void) { if (recovery_loop_counter > 0) { @@ -1794,31 +1818,31 @@ void APDS9960_loop(void) { } } -#endif // APDS9960_GESTURE +#endif // USE_APDS9960_GESTURE void APDS9960_detect(void) { - if (APDS9960type || I2cActive(APDS9960_I2C_ADDR)) { return; } + if (APDS9960_type || I2cActive(APDS9960_I2C_ADDR)) { return; } - APDS9960type = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ID); + APDS9960_type = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ID); #ifdef USE_DEBUG_DRIVER // Debug new chip - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DRV: %s Chip %X"), APDS9960_TAG, APDS9960type); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DRV: %s Chip %X"), APDS9960_TAG, APDS9960_type); #endif // USE_DEBUG_DRIVER - if (APDS9960type == APDS9960_CHIPID_1 || APDS9960type == APDS9960_CHIPID_2 || APDS9960type == APDS9960_CHIPID_3) { + if (APDS9960_type == APDS9960_CHIPID_1 || APDS9960_type == APDS9960_CHIPID_2 || APDS9960_type == APDS9960_CHIPID_3) { if (APDS9960_init()) { I2cSetActiveFound(APDS9960_I2C_ADDR, APDS9960_TAG); enableProximitySensor(); -#ifdef APDS9960_GESTURE +#ifdef USE_APDS9960_GESTURE enableGestureSensor(); -#endif // APDS9960_GESTURE +#endif // USE_APDS9960_GESTURE } else { - APDS9960type = 0; + APDS9960_type = 0; } } else { - APDS9960type = 0; + APDS9960_type = 0; } currentGesture[0] = '\0'; @@ -1829,7 +1853,7 @@ void APDS9960_detect(void) { \*********************************************************************************************/ void APDS9960_show(bool json) { - if (!APDS9960type) { return; } + if (!APDS9960_type) { return; } if (!gesture_mode && !APDS9960_overload) { uint16_t ambient; @@ -1843,7 +1867,7 @@ void APDS9960_show(bool json) { calculateColorTemperature(); // and calculate Lux if (json) { - ResponseAppend_P(PSTR(",\"%s\":{\"Red\":%u,\"Green\":%u,\"Blue\":%u,\"Ambient\":%u,\"CCT\":%u,\"Proximity\":%u}"), + ResponseAppend_P(PSTR(",\"%s\":{\"Red\":%u,\"Green\":%u,\"Blue\":%u,\"" D_JSON_ILLUMINANCE "\":%u,\"CCT\":%u,\"Proximity\":%u}"), APDS9960_TAG, color_data.r, color_data.g, @@ -1861,7 +1885,7 @@ void APDS9960_show(bool json) { WSContentSend_PD(HTTP_SNS_PROXIMITY, APDS9960_TAG, color_data.p); #endif // USE_WEBSERVER } -#ifdef APDS9960_GESTURE +#ifdef USE_APDS9960_GESTURE } else { if (currentGesture[0] != '\0') { if (json) { @@ -1873,7 +1897,7 @@ void APDS9960_show(bool json) { currentGesture[0] = '\0'; } } -#endif // APDS9960_GESTURE +#endif // USE_APDS9960_GESTURE } } @@ -1893,16 +1917,16 @@ bool APDS9960CommandSensor(void) { switch (XdrvMailbox.payload) { case 0: // Off -#ifdef APDS9960_GESTURE +#ifdef USE_APDS9960_GESTURE disableGestureSensor(); -#endif // APDS9960_GESTURE +#endif // USE_APDS9960_GESTURE gesture_mode = 0; enableLightSensor(); APDS9960_overload = false; // prevent unwanted re-enabling break; -#ifdef APDS9960_GESTURE +#ifdef USE_APDS9960_GESTURE case 1: // On with default gain of 4x - if (APDS9960type) { + if (APDS9960_type) { setGestureGain(DEFAULT_GGAIN); setProximityGain(DEFAULT_PGAIN); disableLightSensor(); @@ -1911,7 +1935,7 @@ bool APDS9960CommandSensor(void) { } break; case 2: // gain of 2x , needed for some models - if (APDS9960type) { + if (APDS9960_type) { setGestureGain(GGAIN_2X); setProximityGain(PGAIN_2X); disableLightSensor(); @@ -1919,7 +1943,7 @@ bool APDS9960CommandSensor(void) { gesture_mode = 1; } break; -#endif // APDS9960_GESTURE +#endif // USE_APDS9960_GESTURE default: int temp_aTime = (uint8_t)XdrvMailbox.payload; if (temp_aTime > 2 && temp_aTime < 256) { @@ -1946,13 +1970,13 @@ bool Xsns27(uint8_t function) { if (FUNC_INIT == function) { APDS9960_detect(); - } else if (APDS9960type) { + } else if (APDS9960_type) { switch (function) { -#ifdef APDS9960_GESTURE +#ifdef USE_APDS9960_GESTURE case FUNC_EVERY_50_MSECOND: APDS9960_loop(); break; -#endif // APDS9960_GESTURE +#endif // USE_APDS9960_GESTURE case FUNC_COMMAND_SENSOR: if (XSNS_27 == XdrvMailbox.index) { result = APDS9960CommandSensor(); From 0dc154c8e0b018cacdb6014334c9e4845cf45b75 Mon Sep 17 00:00:00 2001 From: Mickael Gaillard Date: Sun, 26 Apr 2020 19:51:20 +0200 Subject: [PATCH 3/3] Reduce footprint Signed-off-by: Mickael Gaillard --- tasmota/xsns_27_apds9960.ino | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tasmota/xsns_27_apds9960.ino b/tasmota/xsns_27_apds9960.ino index 141373801..4c557c28e 100644 --- a/tasmota/xsns_27_apds9960.ino +++ b/tasmota/xsns_27_apds9960.ino @@ -412,7 +412,7 @@ uint8_t getProxIntLowThresh(void) { * * @param[in] threshold the lower proximity threshold */ -void setProxIntLowThresh(uint8_t threshold) { +inline void setProxIntLowThresh(uint8_t threshold) { I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PILT, threshold); } @@ -435,7 +435,7 @@ uint8_t getProxIntHighThresh(void) { * * @param[in] threshold the high proximity threshold */ -void setProxIntHighThresh(uint8_t threshold) { +inline void setProxIntHighThresh(uint8_t threshold) { I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PIHT, threshold); } @@ -748,7 +748,7 @@ uint8_t getGestureEnterThresh(void) { * * @param[in] threshold proximity value needed to start gesture mode */ -void setGestureEnterThresh(uint8_t threshold) { +inline void setGestureEnterThresh(uint8_t threshold) { I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GPENTH, threshold); } @@ -771,7 +771,7 @@ uint8_t getGestureExitThresh(void) { * * @param[in] threshold proximity value needed to end gesture mode */ -void setGestureExitThresh(uint8_t threshold) { +inline void setGestureExitThresh(uint8_t threshold) { I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GEXTH, threshold); } @@ -1285,7 +1285,7 @@ bool APDS9960_init(void) { * * @return Contents of the ENABLE register. 0xFF if error. */ -uint8_t getMode(void) { +inline uint8_t getMode(void) { uint8_t enable_value; /* Read current ENABLE register */ @@ -1526,7 +1526,7 @@ int16_t readGesture(void) { * Turn the APDS-9960 on * */ -void enablePower(void) { +inline void enablePower(void) { setMode(POWER, ON); } @@ -1534,7 +1534,7 @@ void enablePower(void) { * Turn the APDS-9960 off * */ -void disablePower(void) { +inline void disablePower(void) { setMode(POWER, OFF); } @@ -1546,7 +1546,7 @@ void disablePower(void) { /** * @brief Reads the ARGB-Data and fills color_data */ -void readAllColorAndProximityData(void) { +inline 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