diff --git a/code/espurna/config/general.h b/code/espurna/config/general.h index 9e090cb580..331cc94a1a 100644 --- a/code/espurna/config/general.h +++ b/code/espurna/config/general.h @@ -1246,9 +1246,80 @@ #define RF_PIN 14 #endif +#ifndef RF_ENABLE_PIN_INVERSE +#define RF_ENABLE_PIN_INVERSE 0 +#endif + #define RF_DEBOUNCE 500 #define RF_LEARN_TIMEOUT 60000 +#ifndef RF_BUTTON_SET +#define RF_BUTTON_SET 0 +#endif + +#if RF_SUPPORT +//RF Remote Buttons SET 1 (for the original Remote shipped with the Arilux LC11 controller) +#if RF_BUTTON_SET == 1 +/* + RF Remote + Encoding: Chinese Protocol 1 + Codes provided by KmanOz (https://github.com/KmanOz) + +--------+--------+--------+ + | ON | Toggle | OFF | + +--------+--------+--------+ + | Speed+ | Mode+ | Bright+| + +--------+--------+--------+ + | Speed- | Mode- | Bright-| + +--------+--------+--------+ + | RED | GREEN | BLUE | + +--------+--------+--------+ + | ORANGE | LT GRN | LT BLUE| + +--------+--------+--------+ + | AMBER | CYAN | PURPLE | + +--------+--------+--------+ + | YELLOW | PINK | WHITE | + +--------+--------+--------+ +*/ + + #define RF_BUTTON_COUNT 21 + + #define RF_BUTTON_LEARN_CODE 0x000013 // YELLOW + #define RF_BUTTON_LEARN_MASK 0x0000FF // use first two bytes for home code + + const unsigned long RF_BUTTON[RF_BUTTON_COUNT][3] PROGMEM = { + + { 0x000001, RF_BUTTON_MODE_STATE, 1 }, // ON + { 0x000002, RF_BUTTON_MODE_TOGGLE, 0 }, // Toggle + { 0x000003, RF_BUTTON_MODE_STATE, 0 }, // OFF + + { 0x000004, RF_BUTTON_MODE_SPEED, 1 }, // Speed+ + { 0x000005, RF_BUTTON_MODE_MODE, 1 }, // Mode+ + { 0x000006, RF_BUTTON_MODE_BRIGHTER, 1 }, // Bright+ + + { 0x000007, RF_BUTTON_MODE_SPEED, 0 }, // Speed- + { 0x000008, RF_BUTTON_MODE_MODE, 0 }, // Mode- + { 0x000009, RF_BUTTON_MODE_BRIGHTER, 0 }, // Bright- + + { 0x00000A, RF_BUTTON_MODE_RGB, 0xFF0000 }, // RED + { 0x00000B, RF_BUTTON_MODE_RGB, 0x00FF00 }, // GREEN + { 0x00000C, RF_BUTTON_MODE_RGB, 0x0000FF }, // BLUE + + { 0x00000D, RF_BUTTON_MODE_RGB, 0xFFA500 }, // ORANGE + { 0x00000E, RF_BUTTON_MODE_RGB, 0x90EE90 }, // LT GRN + { 0x00000F, RF_BUTTON_MODE_RGB, 0xADD8E6 }, // LT BLUE + + { 0x000010, RF_BUTTON_MODE_RGB, 0xFFC200 }, // AMBER + { 0x000011, RF_BUTTON_MODE_RGB, 0x00FFFF }, // CYAN + { 0x000012, RF_BUTTON_MODE_RGB, 0x800080 }, // PURPLE + + { 0x000013, RF_BUTTON_MODE_RGB, 0xFFFF00 }, // YELLOW + { 0x000014, RF_BUTTON_MODE_RGB, 0xFFC0CB }, // PINK + { 0x000015, RF_BUTTON_MODE_RGB, 0xFFFFFF }, // WHITE + + }; +#endif +#endif // RF_SUPPORT + //-------------------------------------------------------------------------------- // Custom RFM69 to MQTT bridge // Check http://tinkerman.cat/rfm69-wifi-gateway/ diff --git a/code/espurna/config/hardware.h b/code/espurna/config/hardware.h index 17727ee7d6..9911dec2af 100644 --- a/code/espurna/config/hardware.h +++ b/code/espurna/config/hardware.h @@ -1477,6 +1477,13 @@ #define LIGHT_CH4_INVERSE 0 #define LIGHT_CH5_INVERSE 0 + // RF + #define RF_SUPPORT 1 + #define RF_PIN 15 // https://github.com/arendst/Sonoff-Tasmota/blob/development_display/sonoff/sonoff_template.h + #define RF_ENABLE_PIN 2 // https://github.com/arendst/Sonoff-Tasmota/pull/1310/commits/db4a3a4a1ee8964accd60e2b9acf182ab5514f62 + #define RF_ENABLE_PIN_INVERSE 1 + #define RF_BUTTON_SET 1 + #elif defined(ARILUX_E27) // Info diff --git a/code/espurna/config/types.h b/code/espurna/config/types.h index 2bf6d4eab3..c7b3d5435a 100644 --- a/code/espurna/config/types.h +++ b/code/espurna/config/types.h @@ -183,6 +183,21 @@ #define LIGHT_EFFECT_FADE 3 #define LIGHT_EFFECT_SMOOTH 4 +// ----------------------------------------------------------------------------- +// RF +// ----------------------------------------------------------------------------- + +// RF Button modes +#define RF_BUTTON_MODE_NONE 0 +#define RF_BUTTON_MODE_RGB 1 +#define RF_BUTTON_MODE_HSV 2 +#define RF_BUTTON_MODE_BRIGHTER 3 +#define RF_BUTTON_MODE_STATE 4 +#define RF_BUTTON_MODE_EFFECT 5 +#define RF_BUTTON_MODE_TOGGLE 6 +#define RF_BUTTON_MODE_MODE 7 +#define RF_BUTTON_MODE_SPEED 8 + //------------------------------------------------------------------------------ // RESET //------------------------------------------------------------------------------ diff --git a/code/espurna/rf.ino b/code/espurna/rf.ino index 68756b6dec..10b727611a 100644 --- a/code/espurna/rf.ino +++ b/code/espurna/rf.ino @@ -21,6 +21,111 @@ bool _rf_learn_active = false; // RF // ----------------------------------------------------------------------------- +#if RF_BUTTON_SET > 0 +unsigned long _rf_home_code; +void _rfProcessCode(unsigned long code) { + + static unsigned long _rf_last_toggle = 0; + boolean found = false; + + // Repeat last valid code + DEBUG_MSG_P(PSTR("[RF] Trying to match code 0x%06X with RF remote\n"), code); + + #if defined(RF_BUTTON_LEARN_CODE) && defined(RF_BUTTON_LEARN_MASK) + // Learning of a Home Code by pressing a defined button for a while until the code was received ten times in series + static unsigned long _rf_last_learn = 0; + static unsigned char _rf_learn_count = 0; + + if ( (code & RF_BUTTON_LEARN_MASK) == RF_BUTTON_LEARN_CODE) { // check if code matches the defined learn button + if ( (millis() - _rf_last_learn) < 1000 ) { // check if time since last press is less than a second + _rf_learn_count++; + } else { + _rf_learn_count = 1; + } + _rf_last_learn = millis(); + + if (_rf_learn_count == 10) { + _rf_home_code = code & (0xFFFFFF ^ RF_BUTTON_LEARN_MASK); + setSetting("rfHomeCode", _rf_home_code); + DEBUG_MSG_P(PSTR("[RF] RF remote home code learned 0x%06X\n"), _rf_home_code); + } + } else { // reset counter if other button + _rf_learn_count = 0; + _rf_last_learn = 0; + } + #endif + + for (unsigned char i = 0; i < RF_BUTTON_COUNT ; i++) { + + unsigned long button_code = pgm_read_dword(&RF_BUTTON[i][0]) | _rf_home_code; + if (code == button_code) { + + unsigned long button_mode = pgm_read_dword(&RF_BUTTON[i][1]); + unsigned long button_value = pgm_read_dword(&RF_BUTTON[i][2]); + + if (button_mode == RF_BUTTON_MODE_STATE) { + relayStatus(0, button_value); + } + + if (button_mode == RF_BUTTON_MODE_TOGGLE) { + + if (millis() - _rf_last_toggle > 250){ + relayToggle(button_value); + _rf_last_toggle = millis(); + } else { + DEBUG_MSG_P(PSTR("[RF] Ignoring repeated code\n")); + } + } + + #if LIGHT_PROVIDER != LIGHT_PROVIDER_NONE + + if (button_mode == RF_BUTTON_MODE_BRIGHTER) { + lightBrightnessStep(button_value ? 1 : -1); + nice_delay(150); //debounce + } + + if (button_mode == RF_BUTTON_MODE_RGB) { + lightColor(button_value); + } + + // Mode Buttons used for color temperature + if (button_mode == RF_BUTTON_MODE_MODE) { + _fromMireds(_light_mireds + (button_value ? 50 : -50)); + nice_delay(150); //debounce + } + + // Speed Buttons used for color Saturation + if (button_mode == RF_BUTTON_MODE_SPEED) { + String hsv = lightColor(false); // 240,100,90 + String h = hsv.substring(0,hsv.indexOf(",")+1); // 240, + String s = hsv.substring(h.length(),hsv.lastIndexOf(",")); // 100 + String v = hsv.substring(hsv.lastIndexOf(",")); // ,90 + int saturation = s.toInt(); + saturation = constrain( (saturation + (button_value ? 10 : -10)) , 0, 100); + hsv = h; + hsv.concat(saturation); + hsv.concat(v); + lightColor(hsv.c_str(), false); + } + + lightUpdate(true, true); + + #endif + + found = true; + break; + + } + + } + + if (!found) { + DEBUG_MSG_P(PSTR("[RF] Ignoring code\n")); + } + +} +#endif + unsigned long _rfRetrieve(unsigned char id, bool status) { String code = getSetting(status ? "rfbON" : "rfbOFF", id, "0"); return strtoul(code.c_str(), 0, 16); @@ -155,6 +260,10 @@ void rfLoop() { } else { relayStatus(id, 1 == value); } + } else { + #if RF_BUTTON_SET > 0 + _rfProcessCode(rf_code); + #endif } } @@ -175,8 +284,19 @@ void rfLoop() { void rfSetup() { + #if RF_ENABLE_PIN + pinMode(RF_ENABLE_PIN, OUTPUT); + #if RF_ENABLE_PIN_INVERSE == 1 + digitalWrite(RF_ENABLE_PIN,LOW); + DEBUG_MSG_P(PSTR("[RF] RF enable PIN on GPIO %u set to LOW\n"), RF_ENABLE_PIN); + #else + digitalWrite(RF_ENABLE_PIN,HIGH); + DEBUG_MSG_P(PSTR("[RF] RF enable PIN on GPIO %u set to HIGH\n"), RF_ENABLE_PIN); + #endif + #endif + _rfModem = new RCSwitch(); - _rfModem->enableReceive(RF_PIN); + _rfModem->enableReceive(digitalPinToInterrupt(RF_PIN)); DEBUG_MSG_P(PSTR("[RF] RF receiver on GPIO %u\n"), RF_PIN); #if WEB_SUPPORT @@ -184,6 +304,11 @@ void rfSetup() { wsOnActionRegister(_rfWebSocketOnAction); #endif + #if RF_BUTTON_SET > 0 + _rf_home_code = getSetting("rfHomeCode", 0x000000).toInt(); + DEBUG_MSG_P(PSTR("[RF] RF home code 0x%06X\n"), _rf_home_code); + #endif + // Register loop espurnaRegisterLoop(rfLoop);