Use the state machines to control the finger
Fixes uint16_t comparisons with millis(), removes DoublePressed state in button.h.
This commit is contained in:
parent
39fc93059d
commit
5c74902502
@ -1,78 +1,61 @@
|
|||||||
#include "debounce.h"
|
#include "debounce.h"
|
||||||
|
|
||||||
template<uint16_t SLEEP_TIMEOUT, uint16_t LONGPRESS_TIMEOUT, uint16_t DOUBLEPRESS_TIMEOUT>
|
|
||||||
|
enum class ButtonEvent : uint8_t {
|
||||||
|
NoEvent,
|
||||||
|
Press,
|
||||||
|
LongPress,
|
||||||
|
DoublePress,
|
||||||
|
};
|
||||||
|
|
||||||
|
// template wird komplett wegoptimiert (wie #define)
|
||||||
|
template<uint16_t LONGPRESS_TIMEOUT, uint16_t DOUBLEPRESS_TIMEOUT>
|
||||||
class Button {
|
class Button {
|
||||||
|
|
||||||
using DResult = Debounce<0>::Result;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum class State : uint8_t {
|
enum class State : uint8_t {
|
||||||
Sleep,
|
|
||||||
Idle,
|
Idle,
|
||||||
Pressed,
|
Pressed,
|
||||||
LongPressed,
|
LongPressed,
|
||||||
Released,
|
Released,
|
||||||
DoublePressed,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class Result : uint8_t {
|
|
||||||
NoEvent,
|
|
||||||
Press,
|
|
||||||
LongPress,
|
|
||||||
DoublePress,
|
|
||||||
};
|
|
||||||
|
|
||||||
Result event(DResult result) {
|
ButtonEvent event(RawButtonEvent result) {
|
||||||
switch(state) {
|
switch(state) {
|
||||||
case State::Sleep :
|
|
||||||
state = State::Idle;
|
|
||||||
counter = millis();
|
|
||||||
break;
|
|
||||||
case State::Idle :
|
case State::Idle :
|
||||||
if(result == DResult::Pressed) {
|
if(result == RawButtonEvent::Pressed) {
|
||||||
state = State::Pressed;
|
state = State::Pressed;
|
||||||
counter = millis();
|
counter = millis();
|
||||||
} else if(millis() - counter >= SLEEP_TIMEOUT) {
|
|
||||||
state = State::Sleep;
|
|
||||||
// Activate Hardware sleep
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case State::Pressed :
|
case State::Pressed :
|
||||||
if(result == DResult::Released) {
|
if(result == RawButtonEvent::Released) {
|
||||||
state = State::Released;
|
state = State::Released;
|
||||||
counter = millis();
|
counter = millis();
|
||||||
} else if(millis() - counter >= LONGPRESS_TIMEOUT) {
|
} else if((uint16_t) millis() - counter >= LONGPRESS_TIMEOUT) {
|
||||||
state = State::LongPressed;
|
state = State::LongPressed;
|
||||||
return Result::LongPress;
|
return ButtonEvent::LongPress;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case State::Released :
|
case State::Released :
|
||||||
if(result == DResult::Pressed) {
|
if(result == RawButtonEvent::Pressed) {
|
||||||
state = State::DoublePressed;
|
state= State::Idle;
|
||||||
} else if(millis() - counter >= DOUBLEPRESS_TIMEOUT) {
|
return ButtonEvent::DoublePress;
|
||||||
|
} else if((uint16_t) millis() - counter >= DOUBLEPRESS_TIMEOUT) {
|
||||||
state = State::Idle;
|
state = State::Idle;
|
||||||
counter = millis();
|
return ButtonEvent::Press;
|
||||||
return Result::Press;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case State::LongPressed :
|
case State::LongPressed :
|
||||||
if(result == DResult::Released) {
|
if(result == RawButtonEvent::Released) {
|
||||||
state = State::Idle;
|
state = State::Idle;
|
||||||
counter = millis();
|
|
||||||
} else {
|
} else {
|
||||||
return Result::LongPress;
|
return ButtonEvent::LongPress;
|
||||||
}
|
|
||||||
break;
|
|
||||||
case State::DoublePressed :
|
|
||||||
if(result == DResult::Released) {
|
|
||||||
state = State::Idle;
|
|
||||||
counter = millis();
|
|
||||||
return Result::DoublePress;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Result::NoEvent;
|
return ButtonEvent::NoEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -17,6 +17,11 @@ std::uniform_int_distribution<uint8_t> distribution(1,16);
|
|||||||
|
|
||||||
SegmentDisplay<4, 2, 0> display;
|
SegmentDisplay<4, 2, 0> display;
|
||||||
|
|
||||||
|
using MainButton = Button<150, 150>;
|
||||||
|
|
||||||
|
Debounce<20> debounce;
|
||||||
|
MainButton button;
|
||||||
|
|
||||||
#define NUM_SLOWDOWN 12
|
#define NUM_SLOWDOWN 12
|
||||||
const uint16_t PROGMEM SLOWDOWN[NUM_SLOWDOWN] = {
|
const uint16_t PROGMEM SLOWDOWN[NUM_SLOWDOWN] = {
|
||||||
35, 32,
|
35, 32,
|
||||||
@ -37,19 +42,66 @@ void setup() {
|
|||||||
display.write();
|
display.write();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class State : uint8_t {
|
||||||
|
Idle,
|
||||||
|
Menu,
|
||||||
|
Counting,
|
||||||
|
Slowing
|
||||||
|
};
|
||||||
|
|
||||||
|
auto state = State::Idle;
|
||||||
|
uint16_t timeout;
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
if(digitalRead(PIN1)) {
|
rng();
|
||||||
rng();
|
|
||||||
return;
|
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 i = 0; i < NUM_SLOWDOWN; i += 2) {
|
||||||
for(size_t j = 0; j < pgm_read_word_near(SLOWDOWN + i); ++j) {
|
for(size_t j = 0; j < pgm_read_word_near(SLOWDOWN + i); ++j) {
|
||||||
num = distribution(rng);
|
displayNextNumber();
|
||||||
display.set(num);
|
|
||||||
display.write();
|
|
||||||
delay(pgm_read_word_near(SLOWDOWN + i + 1));
|
delay(pgm_read_word_near(SLOWDOWN + i + 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -58,7 +110,7 @@ void loop() {
|
|||||||
display.setOff();
|
display.setOff();
|
||||||
display.write();
|
display.write();
|
||||||
delay(250);
|
delay(250);
|
||||||
display.set(num);
|
display.set(currentNumber);
|
||||||
display.write();
|
display.write();
|
||||||
delay(250);
|
delay(250);
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,15 @@
|
|||||||
#ifndef _DEBOUNCE_H_
|
#ifndef _DEBOUNCE_H_
|
||||||
#define _DEBOUNCE_H_
|
#define _DEBOUNCE_H_
|
||||||
|
|
||||||
template<uint8_t DEBOUNCE_PRESSED, uint8_t DEBOUNCE_UNPRESSED = DEBOUNCE_PRESSED>
|
|
||||||
class Debounce {
|
|
||||||
|
|
||||||
|
enum class RawButtonEvent : uint8_t {
|
||||||
|
NoEvent,
|
||||||
|
Pressed,
|
||||||
|
Released,
|
||||||
|
};
|
||||||
|
|
||||||
|
template<uint16_t DEBOUNCE_PRESSED, uint16_t DEBOUNCE_UNPRESSED = DEBOUNCE_PRESSED>
|
||||||
|
class Debounce {
|
||||||
public:
|
public:
|
||||||
enum class State : uint8_t {
|
enum class State : uint8_t {
|
||||||
Unpressed,
|
Unpressed,
|
||||||
@ -12,23 +18,18 @@ class Debounce {
|
|||||||
PressedDebounced,
|
PressedDebounced,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class Result : uint8_t {
|
|
||||||
NoEvent,
|
|
||||||
Pressed,
|
|
||||||
Released,
|
|
||||||
};
|
|
||||||
|
|
||||||
Result event(bool pressed) {
|
RawButtonEvent event(bool pressed) {
|
||||||
switch(state) {
|
switch(state) {
|
||||||
case State::Unpressed :
|
case State::Unpressed :
|
||||||
if(pressed) {
|
if(pressed) {
|
||||||
state = State::PressedDebounced;
|
state = State::PressedDebounced;
|
||||||
counter = millis();
|
counter = millis();
|
||||||
return Result::Pressed;
|
return RawButtonEvent::Pressed;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case State::PressedDebounced :
|
case State::PressedDebounced :
|
||||||
if(millis() - counter > DEBOUNCE_PRESSED) {
|
if((uint16_t) millis() - counter > DEBOUNCE_PRESSED) {
|
||||||
state = State::Pressed;
|
state = State::Pressed;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -36,22 +37,22 @@ class Debounce {
|
|||||||
if(!pressed) {
|
if(!pressed) {
|
||||||
state = State::UnpressedDebounced;
|
state = State::UnpressedDebounced;
|
||||||
counter = millis();
|
counter = millis();
|
||||||
return Result::Released;
|
return RawButtonEvent::Released;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case State::UnpressedDebounced :
|
case State::UnpressedDebounced :
|
||||||
if(millis() - counter > DEBOUNCE_UNPRESSED) {
|
if((uint16_t) millis() - counter > DEBOUNCE_UNPRESSED) {
|
||||||
state = State::Unpressed;
|
state = State::Unpressed;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Result::NoEvent;
|
return RawButtonEvent::NoEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
State state = State::Unpressed;
|
State state = State::Unpressed;
|
||||||
uint8_t counter = 0;
|
uint16_t counter = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user