mirror of https://github.com/arendst/Tasmota.git
Refactor Button, Switch and Rotary to save code space
Refactor Button, Switch and Rotary to save code space
This commit is contained in:
parent
9eed3ebfea
commit
ef63883a1c
|
@ -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 };
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Extern global variables
|
||||
\*********************************************************************************************/
|
||||
|
||||
extern uint8_t rotary_changed; // Rotary switch changed
|
||||
|
||||
#endif // _SONOFF_H_
|
||||
|
|
|
@ -23,44 +23,46 @@
|
|||
* Button support
|
||||
\*********************************************************************************************/
|
||||
|
||||
unsigned long button_debounce = 0; // Button debounce timer
|
||||
uint16_t holdbutton[MAX_KEYS] = { 0 }; // Timer for button hold
|
||||
uint16_t dual_button_code = 0; // Sonoff dual received code
|
||||
struct BUTTON {
|
||||
unsigned long debounce = 0; // Button debounce timer
|
||||
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 multiwindow[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 last_state[MAX_KEYS] = { NOT_PRESSED, NOT_PRESSED, NOT_PRESSED, NOT_PRESSED }; // Last button states
|
||||
uint8_t window_timer[MAX_KEYS] = { 0 }; // Max time between button presses to record press count
|
||||
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 key_no_pullup = 0; // key no pullup flag (1 = no pullup)
|
||||
uint8_t key_inverted = 0; // Key inverted flag (1 = inverted)
|
||||
uint8_t buttons_present = 0; // Number of buttons found flag
|
||||
uint8_t button_adc = 99; // ADC0 button number
|
||||
uint8_t dual_receive_count = 0; // Sonoff dual input flag
|
||||
uint8_t no_pullup_mask = 0; // key no pullup flag (1 = no pullup)
|
||||
uint8_t inverted_mask = 0; // Key inverted flag (1 = inverted)
|
||||
uint8_t present = 0; // Number of buttons found flag
|
||||
uint8_t adc = 99; // ADC0 button number
|
||||
} Button;
|
||||
|
||||
/********************************************************************************************/
|
||||
|
||||
void ButtonPullupFlag(uint8 button_bit)
|
||||
{
|
||||
bitSet(key_no_pullup, button_bit);
|
||||
bitSet(Button.no_pullup_mask, button_bit);
|
||||
}
|
||||
|
||||
void ButtonInvertFlag(uint8 button_bit)
|
||||
{
|
||||
bitSet(key_inverted, button_bit);
|
||||
bitSet(Button.inverted_mask, button_bit);
|
||||
}
|
||||
|
||||
void ButtonInit(void)
|
||||
{
|
||||
buttons_present = 0;
|
||||
Button.present = 0;
|
||||
for (uint32_t i = 0; i < MAX_KEYS; i++) {
|
||||
if (pin[GPIO_KEY1 +i] < 99) {
|
||||
buttons_present++;
|
||||
pinMode(pin[GPIO_KEY1 +i], bitRead(key_no_pullup, i) ? INPUT : ((16 == pin[GPIO_KEY1 +i]) ? INPUT_PULLDOWN_16 : INPUT_PULLUP));
|
||||
Button.present++;
|
||||
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
|
||||
else if ((99 == button_adc) && ((ADC0_BUTTON == my_adc0) || (ADC0_BUTTON_INV == my_adc0))) {
|
||||
buttons_present++;
|
||||
button_adc = i;
|
||||
else if ((99 == Button.adc) && ((ADC0_BUTTON == my_adc0) || (ADC0_BUTTON_INV == my_adc0))) {
|
||||
Button.present++;
|
||||
Button.adc = i;
|
||||
}
|
||||
#endif // USE_ADC_VCC
|
||||
}
|
||||
|
@ -68,21 +70,21 @@ void ButtonInit(void)
|
|||
|
||||
uint8_t ButtonSerial(uint8_t serial_in_byte)
|
||||
{
|
||||
if (dual_hex_code) {
|
||||
dual_hex_code--;
|
||||
if (dual_hex_code) {
|
||||
dual_button_code = (dual_button_code << 8) | serial_in_byte;
|
||||
if (Button.dual_receive_count) {
|
||||
Button.dual_receive_count--;
|
||||
if (Button.dual_receive_count) {
|
||||
Button.dual_code = (Button.dual_code << 8) | serial_in_byte;
|
||||
serial_in_byte = 0;
|
||||
} else {
|
||||
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
|
||||
serial_in_byte = 0;
|
||||
dual_button_code = 0;
|
||||
dual_hex_code = 3;
|
||||
Button.dual_code = 0;
|
||||
Button.dual_receive_count = 3;
|
||||
}
|
||||
|
||||
return serial_in_byte;
|
||||
|
@ -117,22 +119,22 @@ void ButtonHandler(void)
|
|||
|
||||
if (!button_index && ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type))) {
|
||||
button_present = 1;
|
||||
if (dual_button_code) {
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON " " D_CODE " %04X"), dual_button_code);
|
||||
if (Button.dual_code) {
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON " " D_CODE " %04X"), Button.dual_code);
|
||||
button = PRESSED;
|
||||
if (0xF500 == dual_button_code) { // Button hold
|
||||
holdbutton[button_index] = (loops_per_second * Settings.param[P_HOLD_TIME] / 10) -1; // SetOption32 (40)
|
||||
if (0xF500 == Button.dual_code) { // Button hold
|
||||
Button.hold_timer[button_index] = (loops_per_second * Settings.param[P_HOLD_TIME] / 10) -1; // SetOption32 (40)
|
||||
hold_time_extent = 1;
|
||||
}
|
||||
dual_button_code = 0;
|
||||
Button.dual_code = 0;
|
||||
}
|
||||
}
|
||||
else if (pin[GPIO_KEY1 +button_index] < 99) {
|
||||
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
|
||||
if (button_adc == button_index) {
|
||||
if (Button.adc == button_index) {
|
||||
button_present = 1;
|
||||
if (ADC0_BUTTON_INV == my_adc0) {
|
||||
button = (AdcRead(1) < 128);
|
||||
|
@ -150,17 +152,17 @@ void ButtonHandler(void)
|
|||
// Serviced
|
||||
}
|
||||
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;
|
||||
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);
|
||||
holdbutton[button_index] = loops_per_second;
|
||||
Button.hold_timer[button_index] = loops_per_second;
|
||||
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);
|
||||
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 (!SendKey(0, button_index +1, POWER_TOGGLE)) { // Execute Toggle command via MQTT if ButtonTopic is set
|
||||
|
@ -169,26 +171,26 @@ void ButtonHandler(void)
|
|||
}
|
||||
}
|
||||
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
|
||||
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
|
||||
ExecuteCommandPower(button_index +1, POWER_TOGGLE, SRC_BUTTON); // Execute Toggle command internally
|
||||
}
|
||||
} else {
|
||||
multipress[button_index] = (multiwindow[button_index]) ? multipress[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]);
|
||||
multiwindow[button_index] = loops_per_second / 2; // 0.5 second multi press window
|
||||
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, Button.press_counter[button_index]);
|
||||
Button.window_timer[button_index] = loops_per_second / 2; // 0.5 second multi press window
|
||||
}
|
||||
blinks = 201;
|
||||
}
|
||||
|
||||
if (NOT_PRESSED == button) {
|
||||
holdbutton[button_index] = 0;
|
||||
Button.hold_timer[button_index] = 0;
|
||||
} 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 (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;
|
||||
snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_SETOPTION "13 0")); // Disable single press only
|
||||
ExecuteCommand(scmnd, SRC_BUTTON);
|
||||
|
@ -196,19 +198,19 @@ void ButtonHandler(void)
|
|||
} else {
|
||||
if (Settings.flag.button_restrict) { // SetOption1 (0) - Button restriction
|
||||
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) {
|
||||
holdbutton[button_index] = 0; // Reset button hold counter to stay below hold trigger
|
||||
multipress[button_index] = 0; // Discard button press to disable functionality
|
||||
if (Button.hold_timer[button_index] > loops_per_second * Settings.param[P_HOLD_IGNORE] / 10) {
|
||||
Button.hold_timer[button_index] = 0; // Reset button hold counter to stay below hold trigger
|
||||
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]);
|
||||
}
|
||||
}
|
||||
if (holdbutton[button_index] == loops_per_second * Settings.param[P_HOLD_TIME] / 10) { // SetOption32 (40) - Button hold
|
||||
multipress[button_index] = 0;
|
||||
if (Button.hold_timer[button_index] == loops_per_second * Settings.param[P_HOLD_TIME] / 10) { // SetOption32 (40) - Button hold
|
||||
Button.press_counter[button_index] = 0;
|
||||
SendKey(0, button_index +1, 3); // Execute Hold command via MQTT if ButtonTopic is set
|
||||
}
|
||||
} 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
|
||||
multipress[button_index] = 0;
|
||||
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
|
||||
Button.press_counter[button_index] = 0;
|
||||
snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_RESET " 1"));
|
||||
ExecuteCommand(scmnd, SRC_BUTTON);
|
||||
}
|
||||
|
@ -217,64 +219,62 @@ void ButtonHandler(void)
|
|||
}
|
||||
|
||||
if (!Settings.flag.button_single) { // SetOption13 (0) - Allow multi-press
|
||||
if (multiwindow[button_index]) {
|
||||
multiwindow[button_index]--;
|
||||
if (Button.window_timer[button_index]) {
|
||||
Button.window_timer[button_index]--;
|
||||
} 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;
|
||||
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)) {
|
||||
single_press = true;
|
||||
} else {
|
||||
single_press = (Settings.flag.button_swap +1 == multipress[button_index]); // SetOption11 (0)
|
||||
if ((1 == buttons_present) && (2 == devices_present)) { // Single Button with two devices only
|
||||
single_press = (Settings.flag.button_swap +1 == Button.press_counter[button_index]); // SetOption11 (0)
|
||||
if ((1 == Button.present) && (2 == devices_present)) { // Single Button with two devices only
|
||||
if (Settings.flag.button_swap) { // SetOption11 (0)
|
||||
multipress[button_index] = (single_press) ? 1 : 2;
|
||||
Button.press_counter[button_index] = (single_press) ? 1 : 2;
|
||||
}
|
||||
} else {
|
||||
multipress[button_index] = 1;
|
||||
Button.press_counter[button_index] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef USE_LIGHT
|
||||
if ((MI_DESK_LAMP == my_module_type) && (button_index == 0) && (rotary_changed) && (LightPower())) {
|
||||
rotary_changed = 0; // Color temp changed, no need to turn of the light
|
||||
} else {
|
||||
#if defined(USE_LIGHT) && defined(ROTARY_V1)
|
||||
if (!((0 == button_index) && RotaryButtonPressed())) {
|
||||
#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
|
||||
} 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
|
||||
restart_flag = 1;
|
||||
} 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
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef USE_LIGHT
|
||||
#if defined(USE_LIGHT) && defined(ROTARY_V1)
|
||||
}
|
||||
#endif
|
||||
multipress[button_index] = 0;
|
||||
Button.press_counter[button_index] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
lastbutton[button_index] = button;
|
||||
Button.last_state[button_index] = button;
|
||||
}
|
||||
}
|
||||
|
||||
void ButtonLoop(void)
|
||||
{
|
||||
if (buttons_present) {
|
||||
if (TimeReached(button_debounce)) {
|
||||
SetNextTimeInterval(button_debounce, Settings.button_debounce); // ButtonDebounce (50)
|
||||
if (Button.present) {
|
||||
if (TimeReached(Button.debounce)) {
|
||||
SetNextTimeInterval(Button.debounce, Settings.button_debounce); // ButtonDebounce (50)
|
||||
ButtonHandler();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,20 +18,21 @@
|
|||
*/
|
||||
|
||||
#ifdef USE_LIGHT
|
||||
//#define ROTARY_V1
|
||||
#ifdef ROTARY_V1
|
||||
/*********************************************************************************************\
|
||||
* Rotary support
|
||||
\*********************************************************************************************/
|
||||
|
||||
unsigned long rotary_debounce = 0; // Rotary debounce timer
|
||||
uint8_t rotaries_found = 0;
|
||||
uint8_t rotary_state = 0;
|
||||
uint8_t rotary_position = 128;
|
||||
uint8_t rotary_last_position = 128;
|
||||
uint8_t interrupts_in_use = 0;
|
||||
uint8_t rotary_changed = 0;
|
||||
|
||||
//#define ROTARY_V1
|
||||
#ifdef ROTARY_V1
|
||||
struct ROTARY {
|
||||
unsigned long debounce = 0; // Rotary debounce timer
|
||||
uint8_t present = 0;
|
||||
uint8_t state = 0;
|
||||
uint8_t position = 128;
|
||||
uint8_t last_position = 128;
|
||||
uint8_t interrupts_in_use_count = 0;
|
||||
uint8_t changed = 0;
|
||||
} Rotary;
|
||||
|
||||
/********************************************************************************************/
|
||||
|
||||
|
@ -43,22 +44,22 @@ void update_position(void)
|
|||
* 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_ROT1B])) s |= 8;
|
||||
switch (s) {
|
||||
case 0: case 5: case 10: case 15:
|
||||
break;
|
||||
case 1: case 7: case 8: case 14:
|
||||
rotary_position++; break;
|
||||
Rotary.position++; break;
|
||||
case 2: case 4: case 11: case 13:
|
||||
rotary_position--; break;
|
||||
Rotary.position--; break;
|
||||
case 3: case 12:
|
||||
rotary_position = rotary_position + 2; break;
|
||||
Rotary.position = Rotary.position + 2; break;
|
||||
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
|
||||
|
@ -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)
|
||||
{
|
||||
rotaries_found = 0;
|
||||
Rotary.present = 0;
|
||||
if ((pin[GPIO_ROT1A] < 99) && (pin[GPIO_ROT1B] < 99)) {
|
||||
rotaries_found++;
|
||||
Rotary.present++;
|
||||
pinMode(pin[GPIO_ROT1A], INPUT_PULLUP);
|
||||
pinMode(pin[GPIO_ROT1B], INPUT_PULLUP);
|
||||
|
||||
|
@ -87,11 +97,11 @@ void RotaryInit(void)
|
|||
|
||||
if ((pin[GPIO_ROT1A] < 6) || (pin[GPIO_ROT1A] > 11)) {
|
||||
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)) {
|
||||
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)
|
||||
{
|
||||
if (interrupts_in_use < 2) {
|
||||
if (Rotary.interrupts_in_use_count < 2) {
|
||||
noInterrupts();
|
||||
update_rotary();
|
||||
} else {
|
||||
noInterrupts();
|
||||
}
|
||||
if (rotary_last_position != rotary_position) {
|
||||
if (Rotary.last_position != Rotary.position) {
|
||||
if (MI_DESK_LAMP == my_module_type) { // Mi Desk lamp
|
||||
if (holdbutton[0]) {
|
||||
rotary_changed = 1;
|
||||
if (Button.hold_timer[0]) {
|
||||
Rotary.changed = 1;
|
||||
// button1 is pressed: set color temperature
|
||||
int16_t t = LightGetColorTemp();
|
||||
t = t + (rotary_position - rotary_last_position);
|
||||
t = t + (Rotary.position - Rotary.last_position);
|
||||
if (t < 153) {
|
||||
t = 153;
|
||||
}
|
||||
if (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);
|
||||
} else {
|
||||
int8_t d = Settings.light_dimmer;
|
||||
d = d + (rotary_position - rotary_last_position);
|
||||
d = d + (Rotary.position - Rotary.last_position);
|
||||
if (d < 1) {
|
||||
d = 1;
|
||||
}
|
||||
if (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);
|
||||
Settings.light_dimmer = d;
|
||||
}
|
||||
}
|
||||
rotary_last_position = 128;
|
||||
rotary_position = 128;
|
||||
Rotary.last_position = 128;
|
||||
Rotary.position = 128;
|
||||
}
|
||||
interrupts();
|
||||
}
|
||||
|
||||
void RotaryLoop(void)
|
||||
{
|
||||
if (rotaries_found) {
|
||||
if (TimeReached(rotary_debounce)) {
|
||||
SetNextTimeInterval(rotary_debounce, Settings.button_debounce); // Using button_debounce setting for this as well
|
||||
if (Rotary.present) {
|
||||
if (TimeReached(Rotary.debounce)) {
|
||||
SetNextTimeInterval(Rotary.debounce, Settings.button_debounce); // Using button_debounce setting for this as well
|
||||
RotaryHandler();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,34 +31,36 @@ const uint8_t SWITCH_PROBE_INTERVAL = 10; // Time in milliseconds between swit
|
|||
|
||||
Ticker TickerSwitch;
|
||||
|
||||
unsigned long switch_debounce = 0; // Switch debounce timer
|
||||
uint16_t switch_no_pullup = 0; // Switch pull-up bitmask flags
|
||||
uint8_t switch_state_buf[MAX_SWITCHES] = { 0 };
|
||||
uint8_t lastwallswitch[MAX_SWITCHES]; // Last wall switch states
|
||||
uint8_t holdwallswitch[MAX_SWITCHES] = { 0 }; // Timer for wallswitch push button hold
|
||||
uint8_t switch_virtual[MAX_SWITCHES]; // Virtual switch states
|
||||
uint8_t switches_found = 0;
|
||||
struct SWITCH {
|
||||
unsigned long debounce = 0; // Switch debounce timer
|
||||
uint16_t no_pullup_mask = 0; // Switch pull-up bitmask flags
|
||||
uint8_t state[MAX_SWITCHES] = { 0 };
|
||||
uint8_t last_state[MAX_SWITCHES]; // Last wall switch states
|
||||
uint8_t hold_timer[MAX_SWITCHES] = { 0 }; // Timer for wallswitch push button hold
|
||||
uint8_t virtual_state[MAX_SWITCHES]; // Virtual switch states
|
||||
uint8_t present = 0;
|
||||
} Switch;
|
||||
|
||||
/********************************************************************************************/
|
||||
|
||||
void SwitchPullupFlag(uint16 switch_bit)
|
||||
{
|
||||
bitSet(switch_no_pullup, switch_bit);
|
||||
bitSet(Switch.no_pullup_mask, switch_bit);
|
||||
}
|
||||
|
||||
uint8_t SwitchLastState(uint8_t index)
|
||||
{
|
||||
return lastwallswitch[index];
|
||||
return Switch.last_state[index];
|
||||
}
|
||||
|
||||
void SwitchSetVirtual(uint8_t index, uint8_t state)
|
||||
{
|
||||
switch_virtual[index] = state;
|
||||
Switch.virtual_state[index] = state;
|
||||
}
|
||||
|
||||
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 (force_high) { // Enabled with SwitchDebounce x1
|
||||
if (1 == switch_virtual[i]) {
|
||||
switch_state_buf[i] = state_filter; // With noisy input keep current state 1 unless constant 0
|
||||
if (1 == Switch.virtual_state[i]) {
|
||||
Switch.state[i] = state_filter; // With noisy input keep current state 1 unless constant 0
|
||||
}
|
||||
}
|
||||
|
||||
if (switch_state_buf[i] < state_filter) {
|
||||
switch_state_buf[i]++;
|
||||
if (state_filter == switch_state_buf[i]) {
|
||||
switch_virtual[i] = 1;
|
||||
if (Switch.state[i] < state_filter) {
|
||||
Switch.state[i]++;
|
||||
if (state_filter == Switch.state[i]) {
|
||||
Switch.virtual_state[i] = 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
if (force_low) { // Enabled with SwitchDebounce x2
|
||||
if (0 == switch_virtual[i]) {
|
||||
switch_state_buf[i] = 0; // With noisy input keep current state 0 unless constant 1
|
||||
if (0 == Switch.virtual_state[i]) {
|
||||
Switch.state[i] = 0; // With noisy input keep current state 0 unless constant 1
|
||||
}
|
||||
}
|
||||
|
||||
if (switch_state_buf[i] > 0) {
|
||||
switch_state_buf[i]--;
|
||||
if (0 == switch_state_buf[i]) {
|
||||
switch_virtual[i] = 0;
|
||||
if (Switch.state[i] > 0) {
|
||||
Switch.state[i]--;
|
||||
if (0 == Switch.state[i]) {
|
||||
Switch.virtual_state[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -110,17 +112,17 @@ void SwitchProbe(void)
|
|||
|
||||
void SwitchInit(void)
|
||||
{
|
||||
switches_found = 0;
|
||||
Switch.present = 0;
|
||||
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) {
|
||||
switches_found++;
|
||||
pinMode(pin[GPIO_SWT1 +i], bitRead(switch_no_pullup, 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.present++;
|
||||
pinMode(pin[GPIO_SWT1 +i], bitRead(Switch.no_pullup_mask, i) ? INPUT : ((16 == pin[GPIO_SWT1 +i]) ? INPUT_PULLDOWN_16 : INPUT_PULLUP));
|
||||
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++) {
|
||||
if ((pin[GPIO_SWT1 +i] < 99) || (mode)) {
|
||||
|
||||
if (holdwallswitch[i]) {
|
||||
holdwallswitch[i]--;
|
||||
if (0 == holdwallswitch[i]) {
|
||||
if (Switch.hold_timer[i]) {
|
||||
Switch.hold_timer[i]--;
|
||||
if (0 == Switch.hold_timer[i]) {
|
||||
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};
|
||||
|
||||
if (button != lastwallswitch[i]) {
|
||||
if (button != Switch.last_state[i]) {
|
||||
switchflag = 3;
|
||||
switch (Settings.switchmode[i]) {
|
||||
case TOGGLE:
|
||||
|
@ -162,35 +164,35 @@ void SwitchHandler(uint8_t mode)
|
|||
switchflag = ~button &1; // Follow inverted wall switch state
|
||||
break;
|
||||
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
|
||||
}
|
||||
break;
|
||||
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
|
||||
}
|
||||
break;
|
||||
case PUSHBUTTON_TOGGLE:
|
||||
if (button != lastwallswitch[i]) {
|
||||
if (button != Switch.last_state[i]) {
|
||||
switchflag = 2; // Toggle with any pushbutton change
|
||||
}
|
||||
break;
|
||||
case PUSHBUTTONHOLD:
|
||||
if ((PRESSED == button) && (NOT_PRESSED == lastwallswitch[i])) {
|
||||
holdwallswitch[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10;
|
||||
if ((PRESSED == button) && (NOT_PRESSED == Switch.last_state[i])) {
|
||||
Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10;
|
||||
}
|
||||
if ((NOT_PRESSED == button) && (PRESSED == lastwallswitch[i]) && (holdwallswitch[i])) {
|
||||
holdwallswitch[i] = 0;
|
||||
if ((NOT_PRESSED == button) && (PRESSED == Switch.last_state[i]) && (Switch.hold_timer[i])) {
|
||||
Switch.hold_timer[i] = 0;
|
||||
switchflag = 2; // Toggle with pushbutton to Gnd
|
||||
}
|
||||
break;
|
||||
case PUSHBUTTONHOLD_INV:
|
||||
if ((NOT_PRESSED == button) && (PRESSED == lastwallswitch[i])) {
|
||||
holdwallswitch[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10;
|
||||
if ((NOT_PRESSED == button) && (PRESSED == Switch.last_state[i])) {
|
||||
Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10;
|
||||
}
|
||||
if ((PRESSED == button) && (NOT_PRESSED == lastwallswitch[i]) && (holdwallswitch[i])) {
|
||||
holdwallswitch[i] = 0;
|
||||
if ((PRESSED == button) && (NOT_PRESSED == Switch.last_state[i]) && (Switch.hold_timer[i])) {
|
||||
Switch.hold_timer[i] = 0;
|
||||
switchflag = 2; // Toggle with pushbutton to Gnd
|
||||
}
|
||||
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)
|
||||
{
|
||||
if (switches_found) {
|
||||
if (TimeReached(switch_debounce)) {
|
||||
SetNextTimeInterval(switch_debounce, Settings.switch_debounce);
|
||||
if (Switch.present) {
|
||||
if (TimeReached(Switch.debounce)) {
|
||||
SetNextTimeInterval(Switch.debounce, Settings.switch_debounce);
|
||||
SwitchHandler(0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -372,7 +372,7 @@ void TuyaSerialInput(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"));
|
||||
TuyaResetWifi();
|
||||
return true; // Reset GPIO served here
|
||||
|
|
Loading…
Reference in New Issue