1 /*------------------------------------------------------------------------------------------------*/
2 /* UNICENS V2.1.0-3491 */
3 /* Copyright (c) 2017 Microchip Technology Germany II GmbH & Co. KG. */
5 /* This program is free software: you can redistribute it and/or modify */
6 /* it under the terms of the GNU General Public License as published by */
7 /* the Free Software Foundation, either version 2 of the License, or */
8 /* (at your option) any later version. */
10 /* This program is distributed in the hope that it will be useful, */
11 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
12 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
13 /* GNU General Public License for more details. */
15 /* You should have received a copy of the GNU General Public License */
16 /* along with this program. If not, see <http://www.gnu.org/licenses/>. */
18 /* You may also obtain this software under a propriety license from Microchip. */
19 /* Please contact Microchip for further information. */
20 /*------------------------------------------------------------------------------------------------*/
24 * \brief Implementation of the Finite State Machine.
26 * \cond UCS_INTERNAL_DOC
31 /*------------------------------------------------------------------------------------------------*/
33 /*------------------------------------------------------------------------------------------------*/
37 /*------------------------------------------------------------------------------------------------*/
38 /* Internal definitions */
39 /*------------------------------------------------------------------------------------------------*/
40 /*! \brief NIL-event, indicates that no event is pending at the moment */
41 #define FSM_E_NILEVENT 0
43 /*------------------------------------------------------------------------------------------------*/
44 /* Internal prototypes */
45 /*------------------------------------------------------------------------------------------------*/
46 static Fsm_Act_t Fsm_StateEval(CFsm *self);
48 /*------------------------------------------------------------------------------------------------*/
50 /*------------------------------------------------------------------------------------------------*/
51 /*! \brief Constructor of the Finite State Machine class.
52 * \param self Instance pointer
53 * \param inst_ptr Instance pointer used for state machine actions
54 * \param trans_table_ptr Pointer to transition table
55 * \param num_events Maximum number of events
56 * \param init_state Initialization state to start with
58 void Fsm_Ctor(CFsm *self, void *inst_ptr, const Fsm_StateElem_t *trans_table_ptr,
59 uint8_t num_events, int8_t init_state)
61 MISC_MEM_SET(self, 0, sizeof(*self));
62 self->inst_ptr = inst_ptr;
63 self->event_occured = FSM_E_NILEVENT; /* Clear event variable */
64 self->current_state = init_state; /* Set initialization state */
65 self->transition_table_ptr = trans_table_ptr; /* Set pointer to given transition table */
66 self->num_events = num_events; /* Store maximum number of events */
67 self->internal_state = FSM_STATE_IDLE; /* Clear internal state */
70 /*! \brief Determine required action
71 * \details This function determines the required action in dependency of the current state
72 * and the triggered event. The current state will be transitioned to the next state.
73 * The internal event variable will be cleared and the determined action will be
75 * \param self Instance pointer
76 * \return Determined required action
77 * \return \c NULL if no action is required
79 static Fsm_Act_t Fsm_StateEval(CFsm *self)
81 Fsm_Act_t retval = NULL; /* Set default return value */
83 if(self->event_occured != FSM_E_NILEVENT) /* Event occurred ? */
85 if((uint8_t)self->event_occured <= self->num_events) /* Check if event is valid */
87 /* Get state-matrix-element in dependency of current state and triggered event */
88 uint8_t i = ((uint8_t)self->current_state * self->num_events) + (uint8_t)self->event_occured;
89 Fsm_StateElem_t stateEvaluation = self->transition_table_ptr[i];
90 self->current_state = stateEvaluation.next_state; /* Set new state */
91 self->internal_state = FSM_STATE_IDLE; /* Set internal state to \c IDLE */
92 retval = stateEvaluation.action_fptr; /* Return required action */
96 self->internal_state = FSM_STATE_ERROR; /* Error occurred: Unknown event */
99 self->event_occured = FSM_E_NILEVENT; /* Clear event variable */
105 /*! \brief Service function for Finite State Machines
106 * \details The state machine will be serviced until it will be stopped by the user or no
107 * further event is triggered. If a state transition occurred the associated action
109 * \param self Instance pointer
110 * \return Internal state of the state machine (see \ref Fsm_State_t).
112 Fsm_State_t Fsm_Service(CFsm *self)
114 /* Internal state is set to \c FSM_STATE_SERVICE and any event is triggered? */
115 while((self->internal_state == FSM_STATE_SERVICE) && (self->event_occured != FSM_E_NILEVENT))
117 Fsm_Act_t action_fptr = Fsm_StateEval(self); /* Execute state transition */
118 if(action_fptr != NULL) /* Action required ? */
120 (*action_fptr)(self->inst_ptr); /* Execute action */
124 return self->internal_state; /* Return internal state machine state */
127 /*! \brief Set an event
128 * \details This function sets the given event and triggers the service for the given
130 * \param self Instance pointer
133 void Fsm_SetEvent(CFsm *self, int8_t e)
135 if(self->internal_state != FSM_STATE_END)
137 self->event_occured = e; /* Set new event */
138 self->internal_state = FSM_STATE_SERVICE; /* Set internal state to \c FSM_STATE_SERVICE */
142 /*! \brief Sets the wait state
143 * \details This function sets the given state state machine into the wait state. The state
144 * machine stops and must be re-triggered.
145 * \param self Instance pointer
147 void Fsm_Wait(CFsm *self)
149 if(self->internal_state != FSM_STATE_END)
151 self->internal_state = FSM_STATE_WAIT; /* Set internal state to \c WAIT */
155 /*! \brief End processing of the state machine
156 * \details If this function is called the given state machine will be stopped immediately.
157 * \param self Instance pointer
159 void Fsm_End(CFsm *self)
161 self->internal_state = FSM_STATE_END; /* Set internal state to \c END */
169 /*------------------------------------------------------------------------------------------------*/
171 /*------------------------------------------------------------------------------------------------*/