diff --git a/src/app/buttoneventslogger.cpp b/src/app/buttoneventslogger.cpp index fef75e8..98a0312 100644 --- a/src/app/buttoneventslogger.cpp +++ b/src/app/buttoneventslogger.cpp @@ -29,13 +29,15 @@ XFEventStatus ButtonEventsLogger::processEvent() { int evid = ev->getId(); oldState_ = curentState_; - changeState = false; + changeXFState = false; + + switch (curentState_) { //on state case state::initial: if(evType == XFEvent::Initial) { curentState_ = state::waitButtonPressed; - changeState = true; + changeXFState = true; eventStatus = XFEventStatus::Consumed; } break; @@ -44,19 +46,19 @@ XFEventStatus ButtonEventsLogger::processEvent() { if(evid == event::evButtonShortPressed){ Trace::out("ButtonEventLogger: Button %d short pressed", ev->getButtonId()); curentState_ = state::waitButtonPressed; - changeState = true; + changeXFState = true; eventStatus = XFEventStatus::Consumed; } if(evid == event::evButtonLongPressed){ Trace::out("ButtonEventLogger: Button %d long pressed", ev->getButtonId()); curentState_ = state::waitButtonPressed; - changeState = true; + changeXFState = true; eventStatus = XFEventStatus::Consumed; } break; } - if(changeState) { + if(changeXFState) { switch (oldState_) { // onExit case state::initial: break; @@ -73,7 +75,7 @@ XFEventStatus ButtonEventsLogger::processEvent() { break; } - changeState = false; + changeXFState = false; } return eventStatus; } diff --git a/src/app/buttoneventslogger.h b/src/app/buttoneventslogger.h index c7755c6..73e99e8 100644 --- a/src/app/buttoneventslogger.h +++ b/src/app/buttoneventslogger.h @@ -10,6 +10,7 @@ #include "xf/behavior.h" #include "interface/buttoneventshandlerobserver.h" +#include "xf/XFState.h" class ButtonEventsLogger : public XFBehavior, public interface::ButtonEventsHandlerObserver { public: @@ -23,7 +24,7 @@ protected: XFEventStatus processEvent() override; typedef enum { - evButtonShortPressed, + evButtonShortPressed = 1, evButtonLongPressed } event; @@ -32,11 +33,8 @@ protected: waitButtonPressed } state; -// TODO changeState and put next variable on behavior - state curentState_; state oldState_; - bool changeState = false; }; diff --git a/src/mdw/button/ButtonEventsHandler.cpp b/src/mdw/button/ButtonEventsHandler.cpp index 528b3a5..b6a88c3 100644 --- a/src/mdw/button/ButtonEventsHandler.cpp +++ b/src/mdw/button/ButtonEventsHandler.cpp @@ -10,10 +10,22 @@ #include "board/ButtonsController.h" -ButtonEventsHandler::ButtonEventsHandler() { +ButtonEventsHandler::ButtonEventsHandler() + : stRun(this) { for(uint8_t i = 0; i< MAX_OBSERVER; i++) { observer_[i] = nullptr; } + + stInitial.setNextState(&stRun); + stRun.registerOnEntry((XFState::callback)&ButtonEventsHandler::startButtonSM); + +} + +void ButtonEventsHandler::startButtonSM(const XFEvent* ev) { + buttonStateSm_[0].startBehavior(); + buttonStateSm_[1].startBehavior(); + buttonStateSm_[2].startBehavior(); + buttonStateSm_[3].startBehavior(); } ButtonEventsHandler* ButtonEventsHandler::getInstance() { @@ -21,54 +33,6 @@ ButtonEventsHandler* ButtonEventsHandler::getInstance() { return &buttonEventsHandler_; } -XFEventStatus ButtonEventsHandler::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::run; - changeState_ = true; - eventStatus = XFEventStatus::Consumed; - } - break; - - case state::run: - break; - - } - - if(changeState_) { - switch (oldState_) { // onExit - case state::initial: - break; - - case state::run: - break; - } - - switch (currentState_) { // onEntry - case state::initial: - break; - - case state::run: - buttonStateSm_[0].startBehavior(); - buttonStateSm_[1].startBehavior(); - buttonStateSm_[2].startBehavior(); - buttonStateSm_[3].startBehavior(); - break; - } - } - return eventStatus; -} - void ButtonEventsHandler::onButtonChangeState(uint16_t buttonIndex, bool pressed) { if(pressed) { buttonStateSm_[buttonIndex].genButtonPressed(); diff --git a/src/mdw/button/ButtonEventsHandler.h b/src/mdw/button/ButtonEventsHandler.h index dbcc1bf..db58690 100644 --- a/src/mdw/button/ButtonEventsHandler.h +++ b/src/mdw/button/ButtonEventsHandler.h @@ -31,16 +31,9 @@ public: protected: ButtonEventsHandler(); - XFEventStatus processEvent() override; + void startButtonSM(const XFEvent* ev); - typedef enum { - initial, - run - } state ; - - state currentState_; - state oldState_; - bool changeState_; + XFState stRun; interface::ButtonEventsHandlerObserver* observer_[MAX_OBSERVER]; ButtonStateSm buttonStateSm_[4]; diff --git a/src/mdw/button/ButtonStateSm.h b/src/mdw/button/ButtonStateSm.h index a106691..72f2d85 100644 --- a/src/mdw/button/ButtonStateSm.h +++ b/src/mdw/button/ButtonStateSm.h @@ -18,7 +18,7 @@ public: void genButtonReleased(); protected: - XFEventStatus processEvent() override; + XFEventStatus processEvent(); typedef enum { evButtonPressed, diff --git a/src/platform/f7-disco-gcc/board/ButtonsController.cpp b/src/platform/f7-disco-gcc/board/ButtonsController.cpp index f1436bd..09ad8ff 100644 --- a/src/platform/f7-disco-gcc/board/ButtonsController.cpp +++ b/src/platform/f7-disco-gcc/board/ButtonsController.cpp @@ -9,10 +9,18 @@ #include "trace/trace.h" #include "main.h" -ButtonsController::ButtonsController() { - curentState_ = state::initial; +ButtonsController::ButtonsController() + : stCheckButtons(this), + stDebounce(this) { + cbProvider = nullptr; cbMethod = nullptr; + + stInitial.setNextState(&stCheckButtons); + stCheckButtons.setNextState(event::evButtonIrq, &stDebounce); + stCheckButtons.registerOnEntry((XFState::callback)&ButtonsController::fctCheckButtons); + + stDebounce.setTimeout(20, &stCheckButtons); }; ButtonsController* ButtonsController::getInstance() { @@ -37,97 +45,35 @@ bool ButtonsController::registerCallback( return true; } -XFEventStatus ButtonsController::processEvent() { - eEventStatus eventStatus = XFEventStatus::Unknown; +void ButtonsController::fctCheckButtons(const XFEvent* ev) { + if(cbProvider != nullptr) { - const XFEvent* ev = getCurrentEvent(); - XFEvent::XFEventType evType = ev->getEventType(); - int evid = ev->getId(); + newState[0] = HAL_GPIO_ReadPin(BUTTON0_GPIO_Port, BUTTON0_Pin); + newState[1] = HAL_GPIO_ReadPin(BUTTON1_GPIO_Port, BUTTON1_Pin); + newState[2] = HAL_GPIO_ReadPin(BUTTON2_GPIO_Port, BUTTON2_Pin); + newState[3] = HAL_GPIO_ReadPin(BUTTON3_GPIO_Port, BUTTON3_Pin); - oldState_ = curentState_; - changeState = false; - - switch (curentState_) { - case state::initial: - if(evType == XFEvent::Initial) { - curentState_ = state::checkButtons; - changeState = true; - eventStatus = XFEventStatus::Consumed; - } - break; - - case state::checkButtons: - if (evid == event::evButtonIrq) { - curentState_ = state::debounce; - changeState = true; - eventStatus = XFEventStatus::Consumed; - } - break; - - case state::debounce: - if (evid == event::evTimeout) { - curentState_ = state::checkButtons; - changeState = true; - eventStatus = XFEventStatus::Consumed; - } - break; - } - - if(changeState) { - switch (oldState_) { // onExit - case state::initial: - break; - - case state::checkButtons: - break; - - case state::debounce: - break; + if(newState[0] != buttonState[0]) { + buttonState[0] = newState[0]; + (cbProvider->*cbMethod)(0, !buttonState[0]); } - switch (curentState_) { // onEntry - case state::initial: - break; - - case state::checkButtons: - - if(cbProvider != nullptr) { - - newState[0] = HAL_GPIO_ReadPin(BUTTON0_GPIO_Port, BUTTON0_Pin); - newState[1] = HAL_GPIO_ReadPin(BUTTON1_GPIO_Port, BUTTON1_Pin); - newState[2] = HAL_GPIO_ReadPin(BUTTON2_GPIO_Port, BUTTON2_Pin); - newState[3] = HAL_GPIO_ReadPin(BUTTON3_GPIO_Port, BUTTON3_Pin); - - if(newState[0] != buttonState[0]) { - buttonState[0] = newState[0]; - (cbProvider->*cbMethod)(0, !buttonState[0]); - - } - - if(newState[1] != buttonState[1]) { - buttonState[1] = newState[1]; - (cbProvider->*cbMethod)(1, !buttonState[1]); - } - - if(newState[2] != buttonState[2]) { - buttonState[2] = newState[2]; - (cbProvider->*cbMethod)(2, !buttonState[2]); - } - - if(newState[3] != buttonState[3]) { - buttonState[3] = newState[3]; - (cbProvider->*cbMethod)(3, !buttonState[3]); - } - - } - break; - - case state::debounce: - scheduleTimeout(event::evTimeout, 100); - break; - + if(newState[1] != buttonState[1]) { + buttonState[1] = newState[1]; + (cbProvider->*cbMethod)(1, !buttonState[1]); } + + if(newState[2] != buttonState[2]) { + buttonState[2] = newState[2]; + (cbProvider->*cbMethod)(2, !buttonState[2]); + } + + if(newState[3] != buttonState[3]) { + buttonState[3] = newState[3]; + (cbProvider->*cbMethod)(3, !buttonState[3]); + } + } - return eventStatus; } + diff --git a/src/platform/f7-disco-gcc/board/ButtonsController.h b/src/platform/f7-disco-gcc/board/ButtonsController.h index cbab434..2dd4c68 100644 --- a/src/platform/f7-disco-gcc/board/ButtonsController.h +++ b/src/platform/f7-disco-gcc/board/ButtonsController.h @@ -19,27 +19,23 @@ public: protected: ButtonsController(); - XFEventStatus processEvent() override; typedef enum { - evButtonIrq = 1, + evButtonIrq = 10, evTimeout } event; - typedef enum { - initial, - checkButtons, - debounce - } state; - - state curentState_; - state oldState_; - bool changeState = false; interface::ButtonsControllerCallbackProvider* cbProvider; interface::ButtonsControllerCallbackProvider::CallbackMethod cbMethod; bool newState[4]; bool buttonState[4]; + void fctCheckButtons(const XFEvent* ev); + void fctScheduleTimeout(const XFEvent* ev); + + XFState stCheckButtons; + XFState stDebounce; + public: virtual void onIrq() override; virtual bool registerCallback( diff --git a/src/xf/core/XFState.cpp b/src/xf/core/XFState.cpp new file mode 100644 index 0000000..5f257c6 --- /dev/null +++ b/src/xf/core/XFState.cpp @@ -0,0 +1,78 @@ +/* + * XFState.cpp + * + * Created on: 23 nov. 2023 + * Author: remi.heredero + */ + +#include "xf/XFState.h" +#include "xf/include/xf/behavior.h" +#include +#include "xf/event.h" +#include "trace/trace.h" + +XFState::XFState(XFBehavior* behavior) + : pBehavior(behavior) { + assert(behavior != nullptr); +} + +void XFState::setNextState(const int evid, const int time, XFEvent::XFEventType type, XFState* state) { + assert(state != nullptr); + transition t; + t.evid = evid; + t.time = time; + t.evType = type; + t.nextState = state; + transitions_.push_back(t); +} + +XFEventStatus XFState::onState(const XFEvent* ev) { + + assert(ev != nullptr); + assert(pBehavior != nullptr); + + for(transition t : transitions_) { + assert(t.nextState != nullptr); + + if(t.evType == XFEvent::XFEventType::Initial){ + pBehavior->curentXFState_ = t.nextState; + pBehavior->changeXFState = true; + return XFEventStatus::Consumed; + } + + if(t.evType == XFEvent::XFEventType::Timeout) { + pBehavior->curentXFState_ = t.nextState; + pBehavior->changeXFState = true; + return XFEventStatus::Consumed; + } + + if(t.evid == ev->getId()) { + pBehavior->curentXFState_ = t.nextState; + pBehavior->changeXFState = true; + return XFEventStatus::Consumed; + } + + } + + return XFEventStatus::NotConsumed; +} + +void XFState::onEntry(const XFEvent* ev) { + if(cbEntry_ != nullptr) { + (pBehavior->*cbEntry_)(ev); + } + + for(transition t : transitions_) { + assert(t.nextState != nullptr); + + if(t.evType == XFEvent::XFEventType::Timeout) { + pBehavior->scheduleTimeout(XFEvent::Timeout, t.time); + } + + } +} +void XFState::onExit(const XFEvent* ev) { + if(cbExit_ != nullptr) { + (pBehavior->*cbExit_)(ev); + } +} diff --git a/src/xf/core/behavior.cpp b/src/xf/core/behavior.cpp index f40cd2e..219702e 100644 --- a/src/xf/core/behavior.cpp +++ b/src/xf/core/behavior.cpp @@ -5,6 +5,7 @@ #include "xf/timeout.h" #include "xf/initialevent.h" #include "xf/behavior.h" +#include "trace/trace.h" using interface::XFResourceFactory; @@ -12,7 +13,8 @@ XFBehavior::XFBehavior(bool ownDispatcher /* = false */) : pDispatcher_(nullptr), hasOwnDispatcher_(ownDispatcher), deleteOnTerminate_(false), - pCurrentEvent_(nullptr) + pCurrentEvent_(nullptr), + stInitial(this) { if (ownDispatcher) { @@ -81,6 +83,22 @@ XFBehavior::TerminateBehavior XFBehavior::process(const XFEvent * pEvent) return (eventStatus == XFEventStatus::Terminate); } +XFEventStatus XFBehavior::processEvent(){ + XFEventStatus eventStatus = XFEventStatus::Unknown; + const XFEvent * ev = getCurrentEvent(); + + oldXFState_ = curentXFState_; + + eventStatus = curentXFState_->onState(ev); + + if(changeXFState){ + oldXFState_->onExit(ev); + curentXFState_->onEntry(ev); + } + + return eventStatus; +} + interface::XFDispatcher * XFBehavior::getDispatcher() { return pDispatcher_; diff --git a/src/xf/include/xf/XFState.h b/src/xf/include/xf/XFState.h new file mode 100644 index 0000000..d10eed0 --- /dev/null +++ b/src/xf/include/xf/XFState.h @@ -0,0 +1,58 @@ +/* + * XFState.h + * + * Created on: 23 nov. 2023 + * Author: remi.heredero + */ + +#ifndef XFSTATE_H_ +#define XFSTATE_H_ + +#include "xf/interface/reactive.h" +#include "xf/interface/dispatcher.h" +#include "xf/eventstatus.h" +#include "xf/initialevent.h" +#include "xf/nulltransition.h" +#include "xf/timeout.h" +class XFBehavior; + +#include + +class XFState { + friend class XFBehavior; +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 setTimeout(int time, XFState* nextState) { setNextState(XFEvent::Timeout, time, XFEvent::XFEventType::Timeout, nextState); }; + typedef void (XFBehavior::*callback)(const XFEvent* ev); + inline void registerOnEntry(callback cbEntry) { cbEntry_ = cbEntry; }; + inline void registerOnExit(callback cbExit) { cbExit_ = 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); + + XFEventStatus onState(const XFEvent* ev); + void onEntry(const XFEvent* ev); + void onExit(const XFEvent* ev); + +protected: + XFBehavior* const pBehavior; + typedef struct { + int evid; + int time; + XFEvent::XFEventType evType; + XFState* nextState; + } transition; + std::list transitions_; + + callback cbEntry_; + callback cbExit_; + +}; + +#endif /* XFSTATE_H_ */ diff --git a/src/xf/include/xf/behavior.h b/src/xf/include/xf/behavior.h index 2ac3af3..725ba23 100644 --- a/src/xf/include/xf/behavior.h +++ b/src/xf/include/xf/behavior.h @@ -8,6 +8,9 @@ #include "xf/nulltransition.h" #include "xf/timeout.h" +#include "xf/include/xf/XFState.h" +#include + class XFTimeout; /** @ingroup xf_core @@ -25,8 +28,8 @@ class XFTimeout; * called every time an event or timeout arrives. The event (or timeout) can * be accessed via the getCurrentEvent() method. */ -class XFBehavior : public interface::XFReactive -{ +class XFBehavior : public interface::XFReactive { + friend class XFState; public: #define GEN(event) pushEvent(new event) @@ -55,7 +58,7 @@ protected: * This method needs to be overridden to implement the * behavior (i.e. state machine) needed. */ - virtual XFEventStatus processEvent() = 0; + virtual XFEventStatus processEvent(); const XFEvent * getCurrentEvent() const; ///< Returns the current event to be processed in processEvent(). interface::XFDispatcher * getDispatcher(); ///< Returns reference to #_pDispatcher. @@ -95,6 +98,13 @@ protected: bool hasOwnDispatcher_; ///< True if behavior has its own dispatcher, False if the default dispatcher is used. bool deleteOnTerminate_; ///< Indicates if the behavior can be deleted after reception of a 'terminate event'. const XFEvent * pCurrentEvent_; ///< Reference to actually processed event. + +protected: + XFState stInitial; + XFState* curentXFState_ = &stInitial; + XFState* oldXFState_ = &stInitial; + bool changeXFState = false; + }; /** @} */ // end of xf_core group