class RZButton
{
public:
RZButton(uint8_t _buttonPin, int _pull_mode = INPUT_PULLUP);
bool isPressed();
bool wasPressed();
bool stateChanged();
bool uniquePress();
bool longPress();
unsigned char multiclick();
unsigned long continuousPressTime();
void clearFirstPress();
void setMulticlickTimeThreshold(unsigned int time_threshold_milliseconds);
void setLongPressTimeThreshold(unsigned int time_threshold_milliseconds);
private:
uint8_t buttonPin;
bool lastStatus;
int mode;
unsigned long lastChange, firstPress, lastPress;
unsigned char multiclickCounter;
unsigned int multiclickTimeThreshold = 3000;
unsigned int longPressTimeThreshold = 2000;
};
struct PinConfig {
unsigned char inputPin;
unsigned char outputPin;
};
const bool activeRelay = HIGH;
const PinConfig pins[] = {
{4, 8}, // inputPin = 4, outputPin = 8
{5, 9},
{6, 10},
{7, 11},
};
RZButton muteButton(12);
#define OnOffPin 13
void setup() {
for (int i = 0; i < sizeof(pins) / sizeof(pins[0]); i++) {
pinMode(pins[i].inputPin, INPUT_PULLUP);
pinMode(pins[i].outputPin, OUTPUT);
digitalWrite(pins[i].outputPin, !activeRelay);
}
digitalWrite(pins[0].outputPin, activeRelay);
pinMode(OnOffPin, OUTPUT);
digitalWrite(OnOffPin, !activeRelay);
}
void loop() {
for (int i = 0; i < sizeof(pins) / sizeof(pins[0]); i++) {
if (digitalRead(pins[i].inputPin) == LOW) {
for (int i = 0; i < sizeof(pins) / sizeof(pins[0]); i++) {
digitalWrite(pins[i].outputPin, !activeRelay);
}
digitalWrite(pins[i].outputPin, activeRelay);
}
}
if (muteButton.uniquePress()) {
digitalWrite(OnOffPin, !digitalRead(OnOffPin));
}
}
RZButton::RZButton(uint8_t _buttonPin, int _pull_mode) {
buttonPin = _buttonPin;
mode = _pull_mode;
lastStatus = 0;
lastChange = 0;
firstPress = 0;
lastPress = 0;
multiclickCounter = 0;
pinMode(buttonPin, mode);
}
bool RZButton::isPressed() {
if (mode == INPUT_PULLUP) {
return !digitalRead(buttonPin);
} else {
return digitalRead(buttonPin);
}
}
bool RZButton::wasPressed() {
return lastStatus;
}
bool RZButton::stateChanged() {
bool currentStatus = isPressed();
if (currentStatus != lastStatus && millis() - lastChange > 30) {
lastStatus = currentStatus;
lastChange = millis();
return 1;
}
return 0;
}
bool RZButton::uniquePress() {
return stateChanged() && lastStatus;
}
bool RZButton::longPress() {
bool currentStatus = isPressed();
if (currentStatus && firstPress == 0)
firstPress = millis();
if (!currentStatus && firstPress != 0 && millis() - firstPress > longPressTimeThreshold) {
firstPress = lastPress = multiclickCounter = 0;
return 1;
}
if (!currentStatus) firstPress = 0;
return 0;
}
unsigned char RZButton::multiclick() {
unsigned char returnThis = 0;
if (uniquePress()) {
lastPress = millis();
multiclickCounter++;
}
if (multiclickCounter != 0 && lastPress != 0 && millis() - lastPress > multiclickTimeThreshold && !wasPressed() && firstPress == 0) {
returnThis = multiclickCounter;
lastPress = multiclickCounter = 0;
}
return returnThis;
}
unsigned long RZButton::continuousPressTime() {
if (isPressed()) {
if (firstPress == 0) {
firstPress = millis();
}
return millis() - firstPress;
} else {
firstPress = 0;
}
return 0;
}
void RZButton::clearFirstPress() {
firstPress = multiclickCounter = 0;
}
void RZButton::setMulticlickTimeThreshold(unsigned int time_threshold_milliseconds) {
multiclickTimeThreshold = time_threshold_milliseconds;
}
void RZButton::setLongPressTimeThreshold(unsigned int time_threshold_milliseconds) {
longPressTimeThreshold = time_threshold_milliseconds;
}