Refactor Button, Switch and Rotary to save code space

Refactor Button, Switch and Rotary to save code space
This commit is contained in:
Theo Arends 2019-08-17 16:19:58 +02:00
parent 9eed3ebfea
commit ef63883a1c
5 changed files with 170 additions and 164 deletions

View File

@ -262,10 +262,4 @@ const char kCommandSource[] PROGMEM = "I|MQTT|Restart|Button|Switch|Backlog|Seri
const uint8_t kDefaultRfCode[9] PROGMEM = { 0x21, 0x16, 0x01, 0x0E, 0x03, 0x48, 0x2E, 0x1A, 0x00 }; const uint8_t kDefaultRfCode[9] PROGMEM = { 0x21, 0x16, 0x01, 0x0E, 0x03, 0x48, 0x2E, 0x1A, 0x00 };
/*********************************************************************************************\
* Extern global variables
\*********************************************************************************************/
extern uint8_t rotary_changed; // Rotary switch changed
#endif // _SONOFF_H_ #endif // _SONOFF_H_

View File

@ -23,44 +23,46 @@
* Button support * Button support
\*********************************************************************************************/ \*********************************************************************************************/
unsigned long button_debounce = 0; // Button debounce timer struct BUTTON {
uint16_t holdbutton[MAX_KEYS] = { 0 }; // Timer for button hold unsigned long debounce = 0; // Button debounce timer
uint16_t dual_button_code = 0; // Sonoff dual received code uint16_t hold_timer[MAX_KEYS] = { 0 }; // Timer for button hold
uint16_t dual_code = 0; // Sonoff dual received code
uint8_t lastbutton[MAX_KEYS] = { NOT_PRESSED, NOT_PRESSED, NOT_PRESSED, NOT_PRESSED }; // Last button states uint8_t last_state[MAX_KEYS] = { NOT_PRESSED, NOT_PRESSED, NOT_PRESSED, NOT_PRESSED }; // Last button states
uint8_t multiwindow[MAX_KEYS] = { 0 }; // Max time between button presses to record press count uint8_t window_timer[MAX_KEYS] = { 0 }; // Max time between button presses to record press count
uint8_t multipress[MAX_KEYS] = { 0 }; // Number of button presses within multiwindow uint8_t press_counter[MAX_KEYS] = { 0 }; // Number of button presses within Button.window_timer
uint8_t dual_hex_code = 0; // Sonoff dual input flag uint8_t dual_receive_count = 0; // Sonoff dual input flag
uint8_t key_no_pullup = 0; // key no pullup flag (1 = no pullup) uint8_t no_pullup_mask = 0; // key no pullup flag (1 = no pullup)
uint8_t key_inverted = 0; // Key inverted flag (1 = inverted) uint8_t inverted_mask = 0; // Key inverted flag (1 = inverted)
uint8_t buttons_present = 0; // Number of buttons found flag uint8_t present = 0; // Number of buttons found flag
uint8_t button_adc = 99; // ADC0 button number uint8_t adc = 99; // ADC0 button number
} Button;
/********************************************************************************************/ /********************************************************************************************/
void ButtonPullupFlag(uint8 button_bit) void ButtonPullupFlag(uint8 button_bit)
{ {
bitSet(key_no_pullup, button_bit); bitSet(Button.no_pullup_mask, button_bit);
} }
void ButtonInvertFlag(uint8 button_bit) void ButtonInvertFlag(uint8 button_bit)
{ {
bitSet(key_inverted, button_bit); bitSet(Button.inverted_mask, button_bit);
} }
void ButtonInit(void) void ButtonInit(void)
{ {
buttons_present = 0; Button.present = 0;
for (uint32_t i = 0; i < MAX_KEYS; i++) { for (uint32_t i = 0; i < MAX_KEYS; i++) {
if (pin[GPIO_KEY1 +i] < 99) { if (pin[GPIO_KEY1 +i] < 99) {
buttons_present++; Button.present++;
pinMode(pin[GPIO_KEY1 +i], bitRead(key_no_pullup, i) ? INPUT : ((16 == pin[GPIO_KEY1 +i]) ? INPUT_PULLDOWN_16 : INPUT_PULLUP)); pinMode(pin[GPIO_KEY1 +i], bitRead(Button.no_pullup_mask, i) ? INPUT : ((16 == pin[GPIO_KEY1 +i]) ? INPUT_PULLDOWN_16 : INPUT_PULLUP));
} }
#ifndef USE_ADC_VCC #ifndef USE_ADC_VCC
else if ((99 == button_adc) && ((ADC0_BUTTON == my_adc0) || (ADC0_BUTTON_INV == my_adc0))) { else if ((99 == Button.adc) && ((ADC0_BUTTON == my_adc0) || (ADC0_BUTTON_INV == my_adc0))) {
buttons_present++; Button.present++;
button_adc = i; Button.adc = i;
} }
#endif // USE_ADC_VCC #endif // USE_ADC_VCC
} }
@ -68,21 +70,21 @@ void ButtonInit(void)
uint8_t ButtonSerial(uint8_t serial_in_byte) uint8_t ButtonSerial(uint8_t serial_in_byte)
{ {
if (dual_hex_code) { if (Button.dual_receive_count) {
dual_hex_code--; Button.dual_receive_count--;
if (dual_hex_code) { if (Button.dual_receive_count) {
dual_button_code = (dual_button_code << 8) | serial_in_byte; Button.dual_code = (Button.dual_code << 8) | serial_in_byte;
serial_in_byte = 0; serial_in_byte = 0;
} else { } else {
if (serial_in_byte != 0xA1) { if (serial_in_byte != 0xA1) {
dual_button_code = 0; // 0xA1 - End of Sonoff dual button code Button.dual_code = 0; // 0xA1 - End of Sonoff dual button code
} }
} }
} }
if (0xA0 == serial_in_byte) { // 0xA0 - Start of Sonoff dual button code if (0xA0 == serial_in_byte) { // 0xA0 - Start of Sonoff dual button code
serial_in_byte = 0; serial_in_byte = 0;
dual_button_code = 0; Button.dual_code = 0;
dual_hex_code = 3; Button.dual_receive_count = 3;
} }
return serial_in_byte; return serial_in_byte;
@ -117,22 +119,22 @@ void ButtonHandler(void)
if (!button_index && ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type))) { if (!button_index && ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type))) {
button_present = 1; button_present = 1;
if (dual_button_code) { if (Button.dual_code) {
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON " " D_CODE " %04X"), dual_button_code); AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON " " D_CODE " %04X"), Button.dual_code);
button = PRESSED; button = PRESSED;
if (0xF500 == dual_button_code) { // Button hold if (0xF500 == Button.dual_code) { // Button hold
holdbutton[button_index] = (loops_per_second * Settings.param[P_HOLD_TIME] / 10) -1; // SetOption32 (40) Button.hold_timer[button_index] = (loops_per_second * Settings.param[P_HOLD_TIME] / 10) -1; // SetOption32 (40)
hold_time_extent = 1; hold_time_extent = 1;
} }
dual_button_code = 0; Button.dual_code = 0;
} }
} }
else if (pin[GPIO_KEY1 +button_index] < 99) { else if (pin[GPIO_KEY1 +button_index] < 99) {
button_present = 1; button_present = 1;
button = (digitalRead(pin[GPIO_KEY1 +button_index]) != bitRead(key_inverted, button_index)); button = (digitalRead(pin[GPIO_KEY1 +button_index]) != bitRead(Button.inverted_mask, button_index));
} }
#ifndef USE_ADC_VCC #ifndef USE_ADC_VCC
if (button_adc == button_index) { if (Button.adc == button_index) {
button_present = 1; button_present = 1;
if (ADC0_BUTTON_INV == my_adc0) { if (ADC0_BUTTON_INV == my_adc0) {
button = (AdcRead(1) < 128); button = (AdcRead(1) < 128);
@ -150,17 +152,17 @@ void ButtonHandler(void)
// Serviced // Serviced
} }
else if (SONOFF_4CHPRO == my_module_type) { else if (SONOFF_4CHPRO == my_module_type) {
if (holdbutton[button_index]) { holdbutton[button_index]--; } if (Button.hold_timer[button_index]) { Button.hold_timer[button_index]--; }
bool button_pressed = false; bool button_pressed = false;
if ((PRESSED == button) && (NOT_PRESSED == lastbutton[button_index])) { if ((PRESSED == button) && (NOT_PRESSED == Button.last_state[button_index])) {
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_LEVEL_10), button_index +1); AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_LEVEL_10), button_index +1);
holdbutton[button_index] = loops_per_second; Button.hold_timer[button_index] = loops_per_second;
button_pressed = true; button_pressed = true;
} }
if ((NOT_PRESSED == button) && (PRESSED == lastbutton[button_index])) { if ((NOT_PRESSED == button) && (PRESSED == Button.last_state[button_index])) {
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_LEVEL_01), button_index +1); AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_LEVEL_01), button_index +1);
if (!holdbutton[button_index]) { button_pressed = true; } // Do not allow within 1 second if (!Button.hold_timer[button_index]) { button_pressed = true; } // Do not allow within 1 second
} }
if (button_pressed) { if (button_pressed) {
if (!SendKey(0, button_index +1, POWER_TOGGLE)) { // Execute Toggle command via MQTT if ButtonTopic is set if (!SendKey(0, button_index +1, POWER_TOGGLE)) { // Execute Toggle command via MQTT if ButtonTopic is set
@ -169,26 +171,26 @@ void ButtonHandler(void)
} }
} }
else { else {
if ((PRESSED == button) && (NOT_PRESSED == lastbutton[button_index])) { if ((PRESSED == button) && (NOT_PRESSED == Button.last_state[button_index])) {
if (Settings.flag.button_single) { // SetOption13 (0) - Allow only single button press for immediate action if (Settings.flag.button_single) { // SetOption13 (0) - Allow only single button press for immediate action
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_IMMEDIATE), button_index +1); AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_IMMEDIATE), button_index +1);
if (!SendKey(0, button_index +1, POWER_TOGGLE)) { // Execute Toggle command via MQTT if ButtonTopic is set if (!SendKey(0, button_index +1, POWER_TOGGLE)) { // Execute Toggle command via MQTT if ButtonTopic is set
ExecuteCommandPower(button_index +1, POWER_TOGGLE, SRC_BUTTON); // Execute Toggle command internally ExecuteCommandPower(button_index +1, POWER_TOGGLE, SRC_BUTTON); // Execute Toggle command internally
} }
} else { } else {
multipress[button_index] = (multiwindow[button_index]) ? multipress[button_index] +1 : 1; Button.press_counter[button_index] = (Button.window_timer[button_index]) ? Button.press_counter[button_index] +1 : 1;
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_MULTI_PRESS " %d"), button_index +1, multipress[button_index]); AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_MULTI_PRESS " %d"), button_index +1, Button.press_counter[button_index]);
multiwindow[button_index] = loops_per_second / 2; // 0.5 second multi press window Button.window_timer[button_index] = loops_per_second / 2; // 0.5 second multi press window
} }
blinks = 201; blinks = 201;
} }
if (NOT_PRESSED == button) { if (NOT_PRESSED == button) {
holdbutton[button_index] = 0; Button.hold_timer[button_index] = 0;
} else { } else {
holdbutton[button_index]++; Button.hold_timer[button_index]++;
if (Settings.flag.button_single) { // SetOption13 (0) - Allow only single button press for immediate action if (Settings.flag.button_single) { // SetOption13 (0) - Allow only single button press for immediate action
if (holdbutton[button_index] == loops_per_second * hold_time_extent * Settings.param[P_HOLD_TIME] / 10) { // SetOption32 (40) - Button held for factor times longer if (Button.hold_timer[button_index] == loops_per_second * hold_time_extent * Settings.param[P_HOLD_TIME] / 10) { // SetOption32 (40) - Button held for factor times longer
// Settings.flag.button_single = 0; // Settings.flag.button_single = 0;
snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_SETOPTION "13 0")); // Disable single press only snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_SETOPTION "13 0")); // Disable single press only
ExecuteCommand(scmnd, SRC_BUTTON); ExecuteCommand(scmnd, SRC_BUTTON);
@ -196,19 +198,19 @@ void ButtonHandler(void)
} else { } else {
if (Settings.flag.button_restrict) { // SetOption1 (0) - Button restriction if (Settings.flag.button_restrict) { // SetOption1 (0) - Button restriction
if (Settings.param[P_HOLD_IGNORE] > 0) { // SetOption40 (0) - Do not ignore button hold if (Settings.param[P_HOLD_IGNORE] > 0) { // SetOption40 (0) - Do not ignore button hold
if (holdbutton[button_index] > loops_per_second * Settings.param[P_HOLD_IGNORE] / 10) { if (Button.hold_timer[button_index] > loops_per_second * Settings.param[P_HOLD_IGNORE] / 10) {
holdbutton[button_index] = 0; // Reset button hold counter to stay below hold trigger Button.hold_timer[button_index] = 0; // Reset button hold counter to stay below hold trigger
multipress[button_index] = 0; // Discard button press to disable functionality Button.press_counter[button_index] = 0; // Discard button press to disable functionality
DEBUG_CORE_LOG(PSTR("BTN: " D_BUTTON "%d cancel by " D_CMND_SETOPTION "40 %d"), button_index +1, Settings.param[P_HOLD_IGNORE]); DEBUG_CORE_LOG(PSTR("BTN: " D_BUTTON "%d cancel by " D_CMND_SETOPTION "40 %d"), button_index +1, Settings.param[P_HOLD_IGNORE]);
} }
} }
if (holdbutton[button_index] == loops_per_second * Settings.param[P_HOLD_TIME] / 10) { // SetOption32 (40) - Button hold if (Button.hold_timer[button_index] == loops_per_second * Settings.param[P_HOLD_TIME] / 10) { // SetOption32 (40) - Button hold
multipress[button_index] = 0; Button.press_counter[button_index] = 0;
SendKey(0, button_index +1, 3); // Execute Hold command via MQTT if ButtonTopic is set SendKey(0, button_index +1, 3); // Execute Hold command via MQTT if ButtonTopic is set
} }
} else { } else {
if (holdbutton[button_index] == loops_per_second * hold_time_extent * Settings.param[P_HOLD_TIME] / 10) { // SetOption32 (40) - Button held for factor times longer if (Button.hold_timer[button_index] == loops_per_second * hold_time_extent * Settings.param[P_HOLD_TIME] / 10) { // SetOption32 (40) - Button held for factor times longer
multipress[button_index] = 0; Button.press_counter[button_index] = 0;
snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_RESET " 1")); snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_RESET " 1"));
ExecuteCommand(scmnd, SRC_BUTTON); ExecuteCommand(scmnd, SRC_BUTTON);
} }
@ -217,64 +219,62 @@ void ButtonHandler(void)
} }
if (!Settings.flag.button_single) { // SetOption13 (0) - Allow multi-press if (!Settings.flag.button_single) { // SetOption13 (0) - Allow multi-press
if (multiwindow[button_index]) { if (Button.window_timer[button_index]) {
multiwindow[button_index]--; Button.window_timer[button_index]--;
} else { } else {
if (!restart_flag && !holdbutton[button_index] && (multipress[button_index] > 0) && (multipress[button_index] < MAX_BUTTON_COMMANDS +3)) { if (!restart_flag && !Button.hold_timer[button_index] && (Button.press_counter[button_index] > 0) && (Button.press_counter[button_index] < MAX_BUTTON_COMMANDS +3)) {
bool single_press = false; bool single_press = false;
if (multipress[button_index] < 3) { // Single or Double press if (Button.press_counter[button_index] < 3) { // Single or Double press
if ((SONOFF_DUAL_R2 == my_module_type) || (SONOFF_DUAL == my_module_type) || (CH4 == my_module_type)) { if ((SONOFF_DUAL_R2 == my_module_type) || (SONOFF_DUAL == my_module_type) || (CH4 == my_module_type)) {
single_press = true; single_press = true;
} else { } else {
single_press = (Settings.flag.button_swap +1 == multipress[button_index]); // SetOption11 (0) single_press = (Settings.flag.button_swap +1 == Button.press_counter[button_index]); // SetOption11 (0)
if ((1 == buttons_present) && (2 == devices_present)) { // Single Button with two devices only if ((1 == Button.present) && (2 == devices_present)) { // Single Button with two devices only
if (Settings.flag.button_swap) { // SetOption11 (0) if (Settings.flag.button_swap) { // SetOption11 (0)
multipress[button_index] = (single_press) ? 1 : 2; Button.press_counter[button_index] = (single_press) ? 1 : 2;
} }
} else { } else {
multipress[button_index] = 1; Button.press_counter[button_index] = 1;
} }
} }
} }
#ifdef USE_LIGHT #if defined(USE_LIGHT) && defined(ROTARY_V1)
if ((MI_DESK_LAMP == my_module_type) && (button_index == 0) && (rotary_changed) && (LightPower())) { if (!((0 == button_index) && RotaryButtonPressed())) {
rotary_changed = 0; // Color temp changed, no need to turn of the light
} else {
#endif #endif
if (single_press && SendKey(0, button_index + multipress[button_index], POWER_TOGGLE)) { // Execute Toggle command via MQTT if ButtonTopic is set if (single_press && SendKey(0, button_index + Button.press_counter[button_index], POWER_TOGGLE)) { // Execute Toggle command via MQTT if ButtonTopic is set
// Success // Success
} else { } else {
if (multipress[button_index] < 3) { // Single or Double press if (Button.press_counter[button_index] < 3) { // Single or Double press
if (WifiState() > WIFI_RESTART) { // WPSconfig, Smartconfig or Wifimanager active if (WifiState() > WIFI_RESTART) { // WPSconfig, Smartconfig or Wifimanager active
restart_flag = 1; restart_flag = 1;
} else { } else {
ExecuteCommandPower(button_index + multipress[button_index], POWER_TOGGLE, SRC_BUTTON); // Execute Toggle command internally ExecuteCommandPower(button_index + Button.press_counter[button_index], POWER_TOGGLE, SRC_BUTTON); // Execute Toggle command internally
} }
} else { // 3 - 7 press } else { // 3 - 7 press
if (!Settings.flag.button_restrict) { // SetOption1 (0) if (!Settings.flag.button_restrict) { // SetOption1 (0)
snprintf_P(scmnd, sizeof(scmnd), kCommands[multipress[button_index] -3]); snprintf_P(scmnd, sizeof(scmnd), kCommands[Button.press_counter[button_index] -3]);
ExecuteCommand(scmnd, SRC_BUTTON); ExecuteCommand(scmnd, SRC_BUTTON);
} }
} }
} }
#ifdef USE_LIGHT #if defined(USE_LIGHT) && defined(ROTARY_V1)
} }
#endif #endif
multipress[button_index] = 0; Button.press_counter[button_index] = 0;
} }
} }
} }
} }
} }
lastbutton[button_index] = button; Button.last_state[button_index] = button;
} }
} }
void ButtonLoop(void) void ButtonLoop(void)
{ {
if (buttons_present) { if (Button.present) {
if (TimeReached(button_debounce)) { if (TimeReached(Button.debounce)) {
SetNextTimeInterval(button_debounce, Settings.button_debounce); // ButtonDebounce (50) SetNextTimeInterval(Button.debounce, Settings.button_debounce); // ButtonDebounce (50)
ButtonHandler(); ButtonHandler();
} }
} }

View File

@ -18,20 +18,21 @@
*/ */
#ifdef USE_LIGHT #ifdef USE_LIGHT
//#define ROTARY_V1
#ifdef ROTARY_V1
/*********************************************************************************************\ /*********************************************************************************************\
* Rotary support * Rotary support
\*********************************************************************************************/ \*********************************************************************************************/
unsigned long rotary_debounce = 0; // Rotary debounce timer struct ROTARY {
uint8_t rotaries_found = 0; unsigned long debounce = 0; // Rotary debounce timer
uint8_t rotary_state = 0; uint8_t present = 0;
uint8_t rotary_position = 128; uint8_t state = 0;
uint8_t rotary_last_position = 128; uint8_t position = 128;
uint8_t interrupts_in_use = 0; uint8_t last_position = 128;
uint8_t rotary_changed = 0; uint8_t interrupts_in_use_count = 0;
uint8_t changed = 0;
//#define ROTARY_V1 } Rotary;
#ifdef ROTARY_V1
/********************************************************************************************/ /********************************************************************************************/
@ -43,22 +44,22 @@ void update_position(void)
* https://github.com/PaulStoffregen/Encoder/blob/master/Encoder.h * https://github.com/PaulStoffregen/Encoder/blob/master/Encoder.h
*/ */
s = rotary_state & 3; s = Rotary.state & 3;
if (digitalRead(pin[GPIO_ROT1A])) s |= 4; if (digitalRead(pin[GPIO_ROT1A])) s |= 4;
if (digitalRead(pin[GPIO_ROT1B])) s |= 8; if (digitalRead(pin[GPIO_ROT1B])) s |= 8;
switch (s) { switch (s) {
case 0: case 5: case 10: case 15: case 0: case 5: case 10: case 15:
break; break;
case 1: case 7: case 8: case 14: case 1: case 7: case 8: case 14:
rotary_position++; break; Rotary.position++; break;
case 2: case 4: case 11: case 13: case 2: case 4: case 11: case 13:
rotary_position--; break; Rotary.position--; break;
case 3: case 12: case 3: case 12:
rotary_position = rotary_position + 2; break; Rotary.position = Rotary.position + 2; break;
default: default:
rotary_position = rotary_position - 2; break; Rotary.position = Rotary.position - 2; break;
} }
rotary_state = (s >> 2); Rotary.state = (s >> 2);
} }
#ifndef ARDUINO_ESP8266_RELEASE_2_3_0 // Fix core 2.5.x ISR not in IRAM Exception #ifndef ARDUINO_ESP8266_RELEASE_2_3_0 // Fix core 2.5.x ISR not in IRAM Exception
@ -74,11 +75,20 @@ void update_rotary(void)
} }
} }
bool RotaryButtonPressed(void)
{
if ((MI_DESK_LAMP == my_module_type) && (Rotary.changed) && LightPower()) {
Rotary.changed = 0; // Color temp changed, no need to turn of the light
return true;
}
return false;
}
void RotaryInit(void) void RotaryInit(void)
{ {
rotaries_found = 0; Rotary.present = 0;
if ((pin[GPIO_ROT1A] < 99) && (pin[GPIO_ROT1B] < 99)) { if ((pin[GPIO_ROT1A] < 99) && (pin[GPIO_ROT1B] < 99)) {
rotaries_found++; Rotary.present++;
pinMode(pin[GPIO_ROT1A], INPUT_PULLUP); pinMode(pin[GPIO_ROT1A], INPUT_PULLUP);
pinMode(pin[GPIO_ROT1B], INPUT_PULLUP); pinMode(pin[GPIO_ROT1B], INPUT_PULLUP);
@ -87,11 +97,11 @@ void RotaryInit(void)
if ((pin[GPIO_ROT1A] < 6) || (pin[GPIO_ROT1A] > 11)) { if ((pin[GPIO_ROT1A] < 6) || (pin[GPIO_ROT1A] > 11)) {
attachInterrupt(digitalPinToInterrupt(pin[GPIO_ROT1A]), update_rotary, CHANGE); attachInterrupt(digitalPinToInterrupt(pin[GPIO_ROT1A]), update_rotary, CHANGE);
interrupts_in_use++; Rotary.interrupts_in_use_count++;
} }
if ((pin[GPIO_ROT1B] < 6) || (pin[GPIO_ROT1B] > 11)) { if ((pin[GPIO_ROT1B] < 6) || (pin[GPIO_ROT1B] > 11)) {
attachInterrupt(digitalPinToInterrupt(pin[GPIO_ROT1B]), update_rotary, CHANGE); attachInterrupt(digitalPinToInterrupt(pin[GPIO_ROT1B]), update_rotary, CHANGE);
interrupts_in_use++; Rotary.interrupts_in_use_count++;
} }
} }
} }
@ -102,53 +112,53 @@ void RotaryInit(void)
void RotaryHandler(void) void RotaryHandler(void)
{ {
if (interrupts_in_use < 2) { if (Rotary.interrupts_in_use_count < 2) {
noInterrupts(); noInterrupts();
update_rotary(); update_rotary();
} else { } else {
noInterrupts(); noInterrupts();
} }
if (rotary_last_position != rotary_position) { if (Rotary.last_position != Rotary.position) {
if (MI_DESK_LAMP == my_module_type) { // Mi Desk lamp if (MI_DESK_LAMP == my_module_type) { // Mi Desk lamp
if (holdbutton[0]) { if (Button.hold_timer[0]) {
rotary_changed = 1; Rotary.changed = 1;
// button1 is pressed: set color temperature // button1 is pressed: set color temperature
int16_t t = LightGetColorTemp(); int16_t t = LightGetColorTemp();
t = t + (rotary_position - rotary_last_position); t = t + (Rotary.position - Rotary.last_position);
if (t < 153) { if (t < 153) {
t = 153; t = 153;
} }
if (t > 500) { if (t > 500) {
t = 500; t = 500;
} }
DEBUG_CORE_LOG(PSTR("ROT: " D_CMND_COLORTEMPERATURE " %d"), rotary_position - rotary_last_position); DEBUG_CORE_LOG(PSTR("ROT: " D_CMND_COLORTEMPERATURE " %d"), Rotary.position - Rotary.last_position);
LightSetColorTemp((uint16_t)t); LightSetColorTemp((uint16_t)t);
} else { } else {
int8_t d = Settings.light_dimmer; int8_t d = Settings.light_dimmer;
d = d + (rotary_position - rotary_last_position); d = d + (Rotary.position - Rotary.last_position);
if (d < 1) { if (d < 1) {
d = 1; d = 1;
} }
if (d > 100) { if (d > 100) {
d = 100; d = 100;
} }
DEBUG_CORE_LOG(PSTR("ROT: " D_CMND_DIMMER " %d"), rotary_position - rotary_last_position); DEBUG_CORE_LOG(PSTR("ROT: " D_CMND_DIMMER " %d"), Rotary.position - Rotary.last_position);
LightSetDimmer((uint8_t)d); LightSetDimmer((uint8_t)d);
Settings.light_dimmer = d; Settings.light_dimmer = d;
} }
} }
rotary_last_position = 128; Rotary.last_position = 128;
rotary_position = 128; Rotary.position = 128;
} }
interrupts(); interrupts();
} }
void RotaryLoop(void) void RotaryLoop(void)
{ {
if (rotaries_found) { if (Rotary.present) {
if (TimeReached(rotary_debounce)) { if (TimeReached(Rotary.debounce)) {
SetNextTimeInterval(rotary_debounce, Settings.button_debounce); // Using button_debounce setting for this as well SetNextTimeInterval(Rotary.debounce, Settings.button_debounce); // Using button_debounce setting for this as well
RotaryHandler(); RotaryHandler();
} }
} }

View File

@ -31,34 +31,36 @@ const uint8_t SWITCH_PROBE_INTERVAL = 10; // Time in milliseconds between swit
Ticker TickerSwitch; Ticker TickerSwitch;
unsigned long switch_debounce = 0; // Switch debounce timer struct SWITCH {
uint16_t switch_no_pullup = 0; // Switch pull-up bitmask flags unsigned long debounce = 0; // Switch debounce timer
uint8_t switch_state_buf[MAX_SWITCHES] = { 0 }; uint16_t no_pullup_mask = 0; // Switch pull-up bitmask flags
uint8_t lastwallswitch[MAX_SWITCHES]; // Last wall switch states uint8_t state[MAX_SWITCHES] = { 0 };
uint8_t holdwallswitch[MAX_SWITCHES] = { 0 }; // Timer for wallswitch push button hold uint8_t last_state[MAX_SWITCHES]; // Last wall switch states
uint8_t switch_virtual[MAX_SWITCHES]; // Virtual switch states uint8_t hold_timer[MAX_SWITCHES] = { 0 }; // Timer for wallswitch push button hold
uint8_t switches_found = 0; uint8_t virtual_state[MAX_SWITCHES]; // Virtual switch states
uint8_t present = 0;
} Switch;
/********************************************************************************************/ /********************************************************************************************/
void SwitchPullupFlag(uint16 switch_bit) void SwitchPullupFlag(uint16 switch_bit)
{ {
bitSet(switch_no_pullup, switch_bit); bitSet(Switch.no_pullup_mask, switch_bit);
} }
uint8_t SwitchLastState(uint8_t index) uint8_t SwitchLastState(uint8_t index)
{ {
return lastwallswitch[index]; return Switch.last_state[index];
} }
void SwitchSetVirtual(uint8_t index, uint8_t state) void SwitchSetVirtual(uint8_t index, uint8_t state)
{ {
switch_virtual[index] = state; Switch.virtual_state[index] = state;
} }
uint8_t SwitchGetVirtual(uint8_t index) uint8_t SwitchGetVirtual(uint8_t index)
{ {
return switch_virtual[index]; return Switch.virtual_state[index];
} }
/*********************************************************************************************/ /*********************************************************************************************/
@ -77,29 +79,29 @@ void SwitchProbe(void)
if (1 == digitalRead(pin[GPIO_SWT1 +i])) { if (1 == digitalRead(pin[GPIO_SWT1 +i])) {
if (force_high) { // Enabled with SwitchDebounce x1 if (force_high) { // Enabled with SwitchDebounce x1
if (1 == switch_virtual[i]) { if (1 == Switch.virtual_state[i]) {
switch_state_buf[i] = state_filter; // With noisy input keep current state 1 unless constant 0 Switch.state[i] = state_filter; // With noisy input keep current state 1 unless constant 0
} }
} }
if (switch_state_buf[i] < state_filter) { if (Switch.state[i] < state_filter) {
switch_state_buf[i]++; Switch.state[i]++;
if (state_filter == switch_state_buf[i]) { if (state_filter == Switch.state[i]) {
switch_virtual[i] = 1; Switch.virtual_state[i] = 1;
} }
} }
} else { } else {
if (force_low) { // Enabled with SwitchDebounce x2 if (force_low) { // Enabled with SwitchDebounce x2
if (0 == switch_virtual[i]) { if (0 == Switch.virtual_state[i]) {
switch_state_buf[i] = 0; // With noisy input keep current state 0 unless constant 1 Switch.state[i] = 0; // With noisy input keep current state 0 unless constant 1
} }
} }
if (switch_state_buf[i] > 0) { if (Switch.state[i] > 0) {
switch_state_buf[i]--; Switch.state[i]--;
if (0 == switch_state_buf[i]) { if (0 == Switch.state[i]) {
switch_virtual[i] = 0; Switch.virtual_state[i] = 0;
} }
} }
} }
@ -110,17 +112,17 @@ void SwitchProbe(void)
void SwitchInit(void) void SwitchInit(void)
{ {
switches_found = 0; Switch.present = 0;
for (uint32_t i = 0; i < MAX_SWITCHES; i++) { for (uint32_t i = 0; i < MAX_SWITCHES; i++) {
lastwallswitch[i] = 1; // Init global to virtual switch state; Switch.last_state[i] = 1; // Init global to virtual switch state;
if (pin[GPIO_SWT1 +i] < 99) { if (pin[GPIO_SWT1 +i] < 99) {
switches_found++; Switch.present++;
pinMode(pin[GPIO_SWT1 +i], bitRead(switch_no_pullup, i) ? INPUT : ((16 == pin[GPIO_SWT1 +i]) ? INPUT_PULLDOWN_16 : INPUT_PULLUP)); pinMode(pin[GPIO_SWT1 +i], bitRead(Switch.no_pullup_mask, i) ? INPUT : ((16 == pin[GPIO_SWT1 +i]) ? INPUT_PULLDOWN_16 : INPUT_PULLUP));
lastwallswitch[i] = digitalRead(pin[GPIO_SWT1 +i]); // Set global now so doesn't change the saved power state on first switch check Switch.last_state[i] = digitalRead(pin[GPIO_SWT1 +i]); // Set global now so doesn't change the saved power state on first switch check
} }
switch_virtual[i] = lastwallswitch[i]; Switch.virtual_state[i] = Switch.last_state[i];
} }
if (switches_found) { TickerSwitch.attach_ms(SWITCH_PROBE_INTERVAL, SwitchProbe); } if (Switch.present) { TickerSwitch.attach_ms(SWITCH_PROBE_INTERVAL, SwitchProbe); }
} }
/*********************************************************************************************\ /*********************************************************************************************\
@ -138,18 +140,18 @@ void SwitchHandler(uint8_t mode)
for (uint32_t i = 0; i < MAX_SWITCHES; i++) { for (uint32_t i = 0; i < MAX_SWITCHES; i++) {
if ((pin[GPIO_SWT1 +i] < 99) || (mode)) { if ((pin[GPIO_SWT1 +i] < 99) || (mode)) {
if (holdwallswitch[i]) { if (Switch.hold_timer[i]) {
holdwallswitch[i]--; Switch.hold_timer[i]--;
if (0 == holdwallswitch[i]) { if (0 == Switch.hold_timer[i]) {
SendKey(1, i +1, 3); // Execute command via MQTT SendKey(1, i +1, 3); // Execute command via MQTT
} }
} }
button = switch_virtual[i]; button = Switch.virtual_state[i];
// enum SwitchModeOptions {TOGGLE, FOLLOW, FOLLOW_INV, PUSHBUTTON, PUSHBUTTON_INV, PUSHBUTTONHOLD, PUSHBUTTONHOLD_INV, PUSHBUTTON_TOGGLE, MAX_SWITCH_OPTION}; // enum SwitchModeOptions {TOGGLE, FOLLOW, FOLLOW_INV, PUSHBUTTON, PUSHBUTTON_INV, PUSHBUTTONHOLD, PUSHBUTTONHOLD_INV, PUSHBUTTON_TOGGLE, MAX_SWITCH_OPTION};
if (button != lastwallswitch[i]) { if (button != Switch.last_state[i]) {
switchflag = 3; switchflag = 3;
switch (Settings.switchmode[i]) { switch (Settings.switchmode[i]) {
case TOGGLE: case TOGGLE:
@ -162,35 +164,35 @@ void SwitchHandler(uint8_t mode)
switchflag = ~button &1; // Follow inverted wall switch state switchflag = ~button &1; // Follow inverted wall switch state
break; break;
case PUSHBUTTON: case PUSHBUTTON:
if ((PRESSED == button) && (NOT_PRESSED == lastwallswitch[i])) { if ((PRESSED == button) && (NOT_PRESSED == Switch.last_state[i])) {
switchflag = 2; // Toggle with pushbutton to Gnd switchflag = 2; // Toggle with pushbutton to Gnd
} }
break; break;
case PUSHBUTTON_INV: case PUSHBUTTON_INV:
if ((NOT_PRESSED == button) && (PRESSED == lastwallswitch[i])) { if ((NOT_PRESSED == button) && (PRESSED == Switch.last_state[i])) {
switchflag = 2; // Toggle with releasing pushbutton from Gnd switchflag = 2; // Toggle with releasing pushbutton from Gnd
} }
break; break;
case PUSHBUTTON_TOGGLE: case PUSHBUTTON_TOGGLE:
if (button != lastwallswitch[i]) { if (button != Switch.last_state[i]) {
switchflag = 2; // Toggle with any pushbutton change switchflag = 2; // Toggle with any pushbutton change
} }
break; break;
case PUSHBUTTONHOLD: case PUSHBUTTONHOLD:
if ((PRESSED == button) && (NOT_PRESSED == lastwallswitch[i])) { if ((PRESSED == button) && (NOT_PRESSED == Switch.last_state[i])) {
holdwallswitch[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10; Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10;
} }
if ((NOT_PRESSED == button) && (PRESSED == lastwallswitch[i]) && (holdwallswitch[i])) { if ((NOT_PRESSED == button) && (PRESSED == Switch.last_state[i]) && (Switch.hold_timer[i])) {
holdwallswitch[i] = 0; Switch.hold_timer[i] = 0;
switchflag = 2; // Toggle with pushbutton to Gnd switchflag = 2; // Toggle with pushbutton to Gnd
} }
break; break;
case PUSHBUTTONHOLD_INV: case PUSHBUTTONHOLD_INV:
if ((NOT_PRESSED == button) && (PRESSED == lastwallswitch[i])) { if ((NOT_PRESSED == button) && (PRESSED == Switch.last_state[i])) {
holdwallswitch[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10; Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10;
} }
if ((PRESSED == button) && (NOT_PRESSED == lastwallswitch[i]) && (holdwallswitch[i])) { if ((PRESSED == button) && (NOT_PRESSED == Switch.last_state[i]) && (Switch.hold_timer[i])) {
holdwallswitch[i] = 0; Switch.hold_timer[i] = 0;
switchflag = 2; // Toggle with pushbutton to Gnd switchflag = 2; // Toggle with pushbutton to Gnd
} }
break; break;
@ -202,7 +204,7 @@ void SwitchHandler(uint8_t mode)
} }
} }
lastwallswitch[i] = button; Switch.last_state[i] = button;
} }
} }
} }
@ -210,9 +212,9 @@ void SwitchHandler(uint8_t mode)
void SwitchLoop(void) void SwitchLoop(void)
{ {
if (switches_found) { if (Switch.present) {
if (TimeReached(switch_debounce)) { if (TimeReached(Switch.debounce)) {
SetNextTimeInterval(switch_debounce, Settings.switch_debounce); SetNextTimeInterval(Switch.debounce, Settings.switch_debounce);
SwitchHandler(0); SwitchHandler(0);
} }
} }

View File

@ -372,7 +372,7 @@ void TuyaSerialInput(void)
bool TuyaButtonPressed(void) bool TuyaButtonPressed(void)
{ {
if (!XdrvMailbox.index && ((PRESSED == XdrvMailbox.payload) && (NOT_PRESSED == lastbutton[XdrvMailbox.index]))) { if (!XdrvMailbox.index && ((PRESSED == XdrvMailbox.payload) && (NOT_PRESSED == Button.last_state[XdrvMailbox.index]))) {
AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Reset GPIO triggered")); AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Reset GPIO triggered"));
TuyaResetWifi(); TuyaResetWifi();
return true; // Reset GPIO served here return true; // Reset GPIO served here