Implement unscheduleTimeout & XFInitialState

This commit is contained in:
Rémi Heredero 2023-11-27 17:07:15 +01:00
parent 0ccfd522ee
commit 2c5fa52b9f
8 changed files with 82 additions and 139 deletions

View File

@ -12,9 +12,9 @@
ButtonEventsLogger::ButtonEventsLogger()
: stWait(this) {
stInitial.setNextState(&stWait);
stWait.setNextState(event::evButtonShortPressed, &stWait);
stWait.setNextState(event::evButtonLongPressed, &stWait);
stInitial.addInitialTransition(&stWait);
stWait.addTransition(event::evButtonShortPressed, &stWait);
stWait.addTransition(event::evButtonLongPressed, &stWait);
stWait.registerOnEntry((XFState::callbackEv)&ButtonEventsLogger::logOnTrace);
}

View File

@ -16,7 +16,7 @@ ButtonEventsHandler::ButtonEventsHandler()
observer_[i] = nullptr;
}
stInitial.setNextState(&stRun);
stInitial.addInitialTransition(&stRun);
stRun.registerOnEntry((XFState::callback)&ButtonEventsHandler::startButtonSM);
}

View File

@ -8,10 +8,27 @@
#include <button/ButtonStateSm.h>
#include "mdw/button/ButtonEventsHandler.h"
//TODO start State Machine. For that, turn ButtonEventsHandler to a State Machine (Initial, run)
ButtonStateSm::ButtonStateSm()
: buttonIndex_(getNbInstance()) {
currentState_ = state::initial;
: buttonIndex_(getNbInstance()),
stWaitButtonPressed(this),
stButtonPressed(this),
stButtonShortPressed(this),
stButtonLongPressed(this) {
stInitial.addInitialTransition(&stWaitButtonPressed);
stWaitButtonPressed.addTransition(event::evButtonPressed, &stButtonPressed);
// TODO bug if setTimeout is used before addTransition !!!
stButtonPressed.addTransition(event::evButtonReleased, &stButtonShortPressed);
stButtonPressed.setTimeout(1000, &stButtonLongPressed);
stButtonPressed.registerOnExit((XFState::callback)&ButtonStateSm::genNullTransition);
stButtonShortPressed.registerOnEntry((XFState::callback)&ButtonStateSm::notifyShortPress);
stButtonShortPressed.addTransition(event::evReturn, &stWaitButtonPressed);
stButtonLongPressed.registerOnEntry((XFState::callback)&ButtonStateSm::notifyLongPress);
stButtonLongPressed.addTransition(event::evReturn, &stWaitButtonPressed);
}
uint8_t ButtonStateSm::getNbInstance(){
@ -26,102 +43,14 @@ void ButtonStateSm::genButtonReleased() {
GEN(XFEvent(XFEvent::Event, event::evButtonReleased, this));
}
XFEventStatus ButtonStateSm::processEvent() {
eEventStatus eventStatus = XFEventStatus::Unknown;
const XFEvent* ev = getCurrentEvent();
XFEvent::XFEventType evType = ev->getEventType();
int evid = ev->getId();
oldState_ = currentState_;
changeState_ = false;
switch (currentState_) {
case state::initial:
if(evType == XFEvent::Initial) {
currentState_ = state::waitButtonPressed;
changeState_ = true;
eventStatus = XFEventStatus::Consumed;
}
break;
case state::waitButtonPressed:
if(evid == event::evButtonPressed) {
currentState_ = state::buttonPressed;
changeState_ = true;
eventStatus = XFEventStatus::Consumed;
scheduleTimeout(event::evTimeout, 1000);
}
break;
case state::buttonPressed:
if(evid == event::evButtonReleased) {
currentState_ = state::buttonShortPressed;
changeState_ = true;
eventStatus = XFEventStatus::Consumed;
unscheduleTimeout(event::evTimeout);
}
if(evid == event::evTimeout) {
currentState_ = state::buttonLongPressed;
changeState_ = true;
eventStatus = XFEventStatus::Consumed;
}
GEN(XFNullTransition(this));
break;
case state::buttonShortPressed:
if(evType == XFEvent::XFEventType::NullTransition) {
currentState_ = state::waitButtonPressed;
changeState_ = true;
eventStatus = XFEventStatus::Consumed;
}
break;
case state::buttonLongPressed:
if(evType == XFEvent::XFEventType::NullTransition) {
currentState_ = state::waitButtonPressed;
changeState_ = true;
eventStatus = XFEventStatus::Consumed;
}
break;
}
if(changeState_) {
switch (oldState_) { // onExit
case state::initial:
break;
case state::waitButtonPressed:
break;
case state::buttonPressed:
break;
case state::buttonShortPressed:
break;
case state::buttonLongPressed:
break;
}
switch (currentState_) {
case state::initial:
break;
case state::waitButtonPressed:
break;
case state::buttonPressed:
break;
case state::buttonShortPressed:
ButtonEventsHandler::getInstance()->notifyButtonShortPressed(buttonIndex_);
break;
case state::buttonLongPressed:
ButtonEventsHandler::getInstance()->notifyButtonLongPressed(buttonIndex_);
break;
}
}
return eventStatus;
void ButtonStateSm::notifyShortPress() {
ButtonEventsHandler::getInstance()->notifyButtonShortPressed(buttonIndex_);
}
void ButtonStateSm::notifyLongPress() {
ButtonEventsHandler::getInstance()->notifyButtonLongPressed(buttonIndex_);
}
void ButtonStateSm::genNullTransition() {
GEN(XFEvent(XFEvent::Event, event::evReturn, this));
}

View File

@ -18,27 +18,24 @@ public:
void genButtonReleased();
protected:
XFEventStatus processEvent();
void notifyShortPress();
void notifyLongPress();
void genNullTransition();
typedef enum {
evButtonPressed,
evButtonPressed = 10,
evButtonReleased,
evTimeout
evTimeout,
evReturn
} event;
typedef enum {
initial,
waitButtonPressed,
buttonPressed,
buttonShortPressed,
buttonLongPressed
} state;
state currentState_;
state oldState_;
bool changeState_;
const uint8_t buttonIndex_;
XFState stWaitButtonPressed;
XFState stButtonPressed;
XFState stButtonShortPressed;
XFState stButtonLongPressed;
private:
static uint8_t getNbInstance();

View File

@ -16,8 +16,8 @@ ButtonsController::ButtonsController()
cbProvider = nullptr;
cbMethod = nullptr;
stInitial.setNextState(&stCheckButtons);
stCheckButtons.setNextState(event::evButtonIrq, &stDebounce);
stInitial.addInitialTransition(&stCheckButtons);
stCheckButtons.addTransition(event::evButtonIrq, &stDebounce);
stCheckButtons.registerOnEntry((XFState::callback)&ButtonsController::fctCheckButtons);
stDebounce.setTimeout(20, &stCheckButtons);

View File

@ -14,9 +14,15 @@
XFState::XFState(XFBehavior* behavior)
: pBehavior(behavior) {
assert(behavior != nullptr);
cbState_ = nullptr;
cbEntry_ = nullptr;
cbExit_ = nullptr;
cbEvState_ = nullptr;
cbEvEntry_ = nullptr;
cbEvExit_ = nullptr;
}
void XFState::setNextState(const int evid, const int time, XFEvent::XFEventType type, XFState* state) {
void XFState::addTransition(XFEvent::XFEventType type, const int evid, const int time, XFState* state) {
assert(state != nullptr);
transition t;
t.evid = evid;
@ -28,9 +34,6 @@ void XFState::setNextState(const int evid, const int time, XFEvent::XFEventType
XFEventStatus XFState::onState(const XFEvent* ev) {
assert(ev != nullptr);
assert(pBehavior != nullptr);
if(cbState_ != nullptr) {
(pBehavior->*cbState_)();
}
@ -39,7 +42,6 @@ XFEventStatus XFState::onState(const XFEvent* ev) {
}
for(transition t : transitions_) {
assert(t.nextState != nullptr);
if(t.evType == XFEvent::XFEventType::Initial){
pBehavior->curentXFState_ = t.nextState;
@ -68,12 +70,12 @@ void XFState::onEntry(const XFEvent* ev) {
if(cbEntry_ != nullptr) {
(pBehavior->*cbEntry_)();
}
if(cbEvEntry_ != nullptr) {
(pBehavior->*cbEvEntry_)(ev);
}
for(transition t : transitions_) {
assert(t.nextState != nullptr);
if(t.evType == XFEvent::XFEventType::Timeout) {
pBehavior->scheduleTimeout(XFEvent::Timeout, t.time);
@ -85,7 +87,17 @@ void XFState::onExit(const XFEvent* ev) {
if(cbExit_ != nullptr) {
(pBehavior->*cbExit_)();
}
if(cbEvExit_ != nullptr) {
(pBehavior->*cbEvExit_)(ev);
}
for(transition t: transitions_) {
if(t.evType == XFEvent::XFEventType::Timeout) {
if(ev->getEventType() != XFEvent::XFEventType::Timeout) {
pBehavior->unscheduleTimeout(XFEvent::Timeout);
}
}
}
}

View File

@ -24,10 +24,9 @@ public:
XFState(XFBehavior* behavior);
~XFState() = default;
inline void setNextState(XFState* state) { setNextState(XFEvent::Initial, XFEvent::XFEventType::Initial, state); };
inline void setNextState(const int evid, XFState* state) { setNextState(evid, XFEvent::XFEventType::Event, state); };
inline void addTransition(const int evid, XFState* state) { addTransition(XFEvent::XFEventType::Event, evid, 0, state); };
inline void setTimeout(int time, XFState* nextState) { setNextState(XFEvent::Timeout, time, XFEvent::XFEventType::Timeout, nextState); };
inline void setTimeout(int time, XFState* nextState) { addTransition(XFEvent::XFEventType::Timeout, XFEvent::Timeout, time, nextState); };
typedef void (XFBehavior::*callback)();
typedef void (XFBehavior::*callbackEv)(const XFEvent* ev);
//inline void registerOnState(callback cbState) { cbState_ = cbState; };
@ -38,8 +37,7 @@ public:
inline void registerOnExit(callbackEv cbExit) { cbEvExit_ = cbExit; };
protected:
inline void setNextState(const int evid, XFEvent::XFEventType type, XFState* state) {setNextState(evid, 0, type, state); };
void setNextState(const int evid, const int time, XFEvent::XFEventType type, XFState* state);
void addTransition(XFEvent::XFEventType type, const int evid, const int time, XFState* state);
XFEventStatus onState(const XFEvent* ev);
void onEntry(const XFEvent* ev);
@ -55,13 +53,20 @@ protected:
} transition;
std::list<transition> transitions_;
callback cbState_ = nullptr;
callback cbEntry_ = nullptr;
callback cbExit_ = nullptr;
callbackEv cbEvState_ = nullptr;
callbackEv cbEvEntry_ = nullptr;
callbackEv cbEvExit_ = nullptr;
callback cbState_;
callback cbEntry_;
callback cbExit_;
callbackEv cbEvState_;
callbackEv cbEvEntry_;
callbackEv cbEvExit_;
};
class XFInitialState : public XFState {
public:
inline XFInitialState(XFBehavior* behavior) : XFState(behavior) {};
~XFInitialState() = default;
inline void addInitialTransition(XFState* state) { addTransition(XFEvent::XFEventType::Initial, XFEvent::Initial, 0, state); };
};
#endif /* XFSTATE_H_ */

View File

@ -100,7 +100,7 @@ protected:
const XFEvent * pCurrentEvent_; ///< Reference to actually processed event.
protected:
XFState stInitial;
XFInitialState stInitial;
XFState* curentXFState_ = &stInitial;
XFState* oldXFState_ = &stInitial;
bool changeXFState = false;