Как определить, было ли нажато более одной кнопки

Я проектирую велосипедный указатель поворота, использующий в качестве входных данных две кнопки, по одной с каждой стороны, с соответствующей подсветкой для каждой кнопки. Идея такова:

  1. Нажатие на одну сторону заставляет эту же сторону начать мигать;
  2. Повторное нажатие на ту же сторону выключает ее;
  3. Нажатие на другую сторону выключает эту сторону и включает другую сторону;
  4. (а теперь самое интересное!) если нажаты обе кнопки (или, точнее, если одна кнопка нажата до того, как отпущена другая), то — и только тогда — я начинаю мигать обеими сторонами (функция «предупреждающего сигнала»).

На мой взгляд, проблема в том, что мне нужно дождаться, пока я отпущу одну кнопку (это будет один полный щелчок), чтобы включить одну сторону, потому что если я нажму вторую, пока первая остается нажатой, это будет другое событие/жест («both_click», за неимением лучшего названия).

Другой вариант дизайна — включить один индикатор сразу при нажатии, и если я нажму второй, прежде чем отпущу первый, то также включится другой индикатор (таким образом, включив режим «предупреждения», когда оба индикатора мигают). Хотя это звучит осуществимо, в классе Button («Botao») есть вся логика устранения дребезга, и я боюсь, что загнал себя в угол конкретными объектно-ориентированными решениями по дизайну, которые я сделал.

ПРАВКА: третий вариант дизайна — добавить метод run для каждой кнопки и, вместо того, чтобы запускать только тестируемый метод «псевдособытия», сохранять текущее состояние и событие в переменных, проверяя эти переменные в loop() (например, свойство button.wasPressed вместо метода button.wasPressed()).

Я публикую свой текущий код (только соответствующие части). Обратите внимание, что в цикле есть комментарий, где, как мне кажется, я должен обнаружить двойной щелчок.

Основной файл .ino:

#include "PiscaPisca.cpp"
#include "Botao.cpp"

PiscaPisca pisca;

Botao botao1;
Botao botao4;

void setup() {

  pisca.configure(LEFT, RIGHT, BUZZER);

  botao1.configure(BUTTON1);
  botao4.configure(BUTTON4);
}

void loop() {

  // КАК Я МОГУ ОПРЕДЕЛИТЬ, ЧТО ОБЕ КНОПКИ БЫЛИ НАЖАНЫ??
  // если (bothPressed()) { pisca.toggleWarning(); }

  if (botao1.wasPressed()) { pisca.toggleLeft();  }
  if (botao4.wasPressed()) { pisca.toggleRight(); }

  pisca.run();
}

Botao.cpp (это класс кнопки с функцией устранения дребезга)

#include <Arduino.h>

class Botao
{
    int _pino;

    const int DEBOUNCE_DELAY = 30;

    int buttonState;
    int lastState = HIGH;

    int lastDebounceTime;

    public : void configure(int pino)
    {
        _pino = pino;
        pinMode(pino, INPUT_PULLUP);
    }

    public : boolean wasPressed()
    {        
        return debounce(LOW);
    }

    public : boolean wasReleased()
    {
        return debounce(HIGH);
    }

    public : boolean debounce(int state)
    {        
        boolean gotEvent = false;

        int reading = digitalRead(_pino);

        if (reading != lastState) {
            lastDebounceTime = millis();
        }

        if ((millis() - lastDebounceTime) > DEBOUNCE_DELAY) {
            if (reading != buttonState) {
                buttonState = reading;

                if (buttonState == state) {
                    gotEvent = true;
                }
            }
        }

        lastState = reading;

        return gotEvent;
    }    
};

PiscaPisca.cpp (сама конечная машина)

#include "Arduino.h"
#include "PwmPin.cpp"
#include "Beeper.cpp"

typedef enum {
    NONE        = 0,
    RIGHT_LIGHT = 1,
    LEFT_LIGHT  = 2,
    BOTH        = 3
};

class PiscaPisca
{
    PwmPin _left;
    PwmPin _right;

    Beeper _beeper;

    long _timeReference = 0;

    const int PERIOD = 350;

    boolean
        _running = false,
        _lightState = false;

    int _sides_to_turn = NONE;  


    public : void configure(int leftPin, int rightPin, int buzzerPin)
    {
        _left.configure(leftPin);
        _right.configure(rightPin);
        _beeper.configure(buzzerPin);
    }

    public : void run() 
    {        
        evaluateBlink();
    }



    public : void toggleLeft()
    {
        checkRestart(LEFT_LIGHT);
    }

    public : void toggleRight()
    {
        checkRestart(RIGHT_LIGHT);
    }

    void checkRestart(int lightSide)
    {
        _timeReference = 0;  

        // немного хитрой манипуляции никогда не повредит:
        _sides_to_turn = lightSide & ~_sides_to_turn;  

        Serial.println(lightSide);
        Serial.println(_sides_to_turn);     

        if (_sides_to_turn > 0)
        {
            _running = true;
        }
        else
        {
            lightsOff();
            _running = false;
            _lightState = false;      
        }
    }



    void evaluateBlink() 
    {
        if (!_running)
        {
            return;
        }
        else
        {
            long currentMillis = millis();
            if (currentMillis - _timeReference > PERIOD) {
                _timeReference = currentMillis;
                _lightState = !_lightState;
                performBlink();
            }
        }
    }

    void performBlink()
    {
        if (_lightState)
        {
            _beeper.beepIn();
            lightsOn();
        }
        else
        {
            _beeper.beepOut();
            lightsOff();
        }        
    }

    void lightsOn()
    {
        if (isLightSet(LEFT_LIGHT))
        {
            _left.on();
        }
        if (isLightSet(RIGHT_LIGHT))
        {
            _right.on();
        }        
    }

    boolean isLightSet(int lightSide)
    {
        return (_sides_to_turn & lightSide) == lightSide;
    }

    void lightsOff()
    {
        _left.off();
        _right.off();
    }



};

, 👍2