I think this will do what you want without blocking. You should be able to encapsulate this in an object and pass in callback functions for short-press and long-press.
const byte ButtonPin = 2;
const unsigned long DebounceTime = 30;
const unsigned long ButtonLongPressTime = 2000;
boolean ButtonWasPressed; // Defaults to 'false'
boolean ButtonWasLongPressed; // Defaults to 'false'
unsigned long ButtonStateChangeTime = 0; // Debounce/Long Press timer
void setup()
{
pinMode (ButtonPin, INPUT_PULLUP); // Button between Pin and Ground
}
void loop()
{
unsigned long currentTime = millis();
boolean buttonIsPressed = digitalRead(ButtonPin) == LOW; // Active LOW
// Check for button state change and do debounce
if (buttonIsPressed != ButtonWasPressed &&
currentTime - ButtonStateChangeTime > DebounceTime)
{
// Button state has changed
ButtonStateChangeTime = currentTime;
ButtonWasPressed = buttonIsPressed;
if (ButtonWasPressed)
{
// Button was just pressed
ButtonWasLongPressed = false;
}
else
{
// Button was just released
if (!ButtonWasLongPressed)
{
// ACT ON SHORT PRESS
}
}
// Check to see if we are in a long-press
if (ButtonWasPressed && ! ButtonWasLongPressed &&
currentTime - ButtonStateChangeTime > ButtonLongPressTime)
{
ButtonWasLongPressed = true;
// ACT ON LONG PRESS
}
}
}