diff --git a/code/button.h b/code/button.h index f942b8d..462f82c 100644 --- a/code/button.h +++ b/code/button.h @@ -1,78 +1,61 @@ #include "debounce.h" -template + +enum class ButtonEvent : uint8_t { + NoEvent, + Press, + LongPress, + DoublePress, +}; + +// template wird komplett wegoptimiert (wie #define) +template class Button { - - using DResult = Debounce<0>::Result; - public: enum class State : uint8_t { - Sleep, Idle, Pressed, LongPressed, Released, - DoublePressed, }; - enum class Result : uint8_t { - NoEvent, - Press, - LongPress, - DoublePress, - }; - Result event(DResult result) { + ButtonEvent event(RawButtonEvent result) { switch(state) { - case State::Sleep : - state = State::Idle; - counter = millis(); - break; case State::Idle : - if(result == DResult::Pressed) { + if(result == RawButtonEvent::Pressed) { state = State::Pressed; counter = millis(); - } else if(millis() - counter >= SLEEP_TIMEOUT) { - state = State::Sleep; - // Activate Hardware sleep } break; case State::Pressed : - if(result == DResult::Released) { + if(result == RawButtonEvent::Released) { state = State::Released; counter = millis(); - } else if(millis() - counter >= LONGPRESS_TIMEOUT) { + } else if((uint16_t) millis() - counter >= LONGPRESS_TIMEOUT) { state = State::LongPressed; - return Result::LongPress; + return ButtonEvent::LongPress; } break; case State::Released : - if(result == DResult::Pressed) { - state = State::DoublePressed; - } else if(millis() - counter >= DOUBLEPRESS_TIMEOUT) { + if(result == RawButtonEvent::Pressed) { + state= State::Idle; + return ButtonEvent::DoublePress; + } else if((uint16_t) millis() - counter >= DOUBLEPRESS_TIMEOUT) { state = State::Idle; - counter = millis(); - return Result::Press; + return ButtonEvent::Press; } break; case State::LongPressed : - if(result == DResult::Released) { + if(result == RawButtonEvent::Released) { state = State::Idle; - counter = millis(); } else { - return Result::LongPress; - } - break; - case State::DoublePressed : - if(result == DResult::Released) { - state = State::Idle; - counter = millis(); - return Result::DoublePress; + return ButtonEvent::LongPress; } break; } - return Result::NoEvent; + return ButtonEvent::NoEvent; } private: diff --git a/code/code.ino b/code/code.ino index 28f58cd..62c0be4 100644 --- a/code/code.ino +++ b/code/code.ino @@ -17,6 +17,11 @@ std::uniform_int_distribution distribution(1,16); SegmentDisplay<4, 2, 0> display; +using MainButton = Button<150, 150>; + +Debounce<20> debounce; +MainButton button; + #define NUM_SLOWDOWN 12 const uint16_t PROGMEM SLOWDOWN[NUM_SLOWDOWN] = { 35, 32, @@ -37,19 +42,66 @@ void setup() { display.write(); } +enum class State : uint8_t { + Idle, + Menu, + Counting, + Slowing +}; + +auto state = State::Idle; +uint16_t timeout; + void loop() { - if(digitalRead(PIN1)) { - rng(); - return; + rng(); + + bool buttonPressed = !digitalRead(PIN1); + auto event = button.event(debounce.event(buttonPressed)); + + switch(state) { + case State::Idle: + if(event == ButtonEvent::Press) { + state = State::Slowing; + } else if(event == ButtonEvent::LongPress) { + state = State::Counting; + timeout = millis(); + } else if(event == ButtonEvent::DoublePress) { + state = State::Menu; + } + break; + case State::Menu: + // TODO + state = State::Idle; + break; + case State::Counting: + if(event == ButtonEvent::LongPress) { + // stay in this state + if((uint16_t) millis() - timeout >= 32) { + displayNextNumber(); + timeout = millis(); + } + } else { + state = State::Slowing; + } + break; + case State::Slowing: + slowdown(); + state = State::Idle; + break; } +} - uint8_t num; +static uint8_t currentNumber; +void displayNextNumber() { + currentNumber = distribution(rng); + display.set(currentNumber); + display.write(); +} +void slowdown() { for(size_t i = 0; i < NUM_SLOWDOWN; i += 2) { for(size_t j = 0; j < pgm_read_word_near(SLOWDOWN + i); ++j) { - num = distribution(rng); - display.set(num); - display.write(); + displayNextNumber(); delay(pgm_read_word_near(SLOWDOWN + i + 1)); } } @@ -58,7 +110,7 @@ void loop() { display.setOff(); display.write(); delay(250); - display.set(num); + display.set(currentNumber); display.write(); delay(250); } diff --git a/code/debounce.h b/code/debounce.h index 9209327..080100c 100644 --- a/code/debounce.h +++ b/code/debounce.h @@ -1,9 +1,15 @@ #ifndef _DEBOUNCE_H_ #define _DEBOUNCE_H_ -template -class Debounce { +enum class RawButtonEvent : uint8_t { + NoEvent, + Pressed, + Released, +}; + +template +class Debounce { public: enum class State : uint8_t { Unpressed, @@ -12,23 +18,18 @@ class Debounce { PressedDebounced, }; - enum class Result : uint8_t { - NoEvent, - Pressed, - Released, - }; - Result event(bool pressed) { + RawButtonEvent event(bool pressed) { switch(state) { case State::Unpressed : if(pressed) { state = State::PressedDebounced; counter = millis(); - return Result::Pressed; + return RawButtonEvent::Pressed; } break; case State::PressedDebounced : - if(millis() - counter > DEBOUNCE_PRESSED) { + if((uint16_t) millis() - counter > DEBOUNCE_PRESSED) { state = State::Pressed; } break; @@ -36,22 +37,22 @@ class Debounce { if(!pressed) { state = State::UnpressedDebounced; counter = millis(); - return Result::Released; + return RawButtonEvent::Released; } break; case State::UnpressedDebounced : - if(millis() - counter > DEBOUNCE_UNPRESSED) { + if((uint16_t) millis() - counter > DEBOUNCE_UNPRESSED) { state = State::Unpressed; } break; } - return Result::NoEvent; + return RawButtonEvent::NoEvent; } - + private: State state = State::Unpressed; - uint8_t counter = 0; + uint16_t counter = 0; }; #endif