Implement unscheduleTimeout & XFInitialState
This commit is contained in:
		| @@ -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); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -16,7 +16,7 @@ ButtonEventsHandler::ButtonEventsHandler() | ||||
| 		observer_[i] = nullptr; | ||||
| 	} | ||||
|  | ||||
| 	stInitial.setNextState(&stRun); | ||||
| 	stInitial.addInitialTransition(&stRun); | ||||
| 	stRun.registerOnEntry((XFState::callback)&ButtonEventsHandler::startButtonSM); | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -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)); | ||||
| } | ||||
|   | ||||
| @@ -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(); | ||||
|  | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
| @@ -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); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -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_ */ | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user