summaryrefslogtreecommitdiffstats
path: root/ucs2-lib/src/ucs_fsm.c
diff options
context:
space:
mode:
Diffstat (limited to 'ucs2-lib/src/ucs_fsm.c')
-rw-r--r--ucs2-lib/src/ucs_fsm.c172
1 files changed, 172 insertions, 0 deletions
diff --git a/ucs2-lib/src/ucs_fsm.c b/ucs2-lib/src/ucs_fsm.c
new file mode 100644
index 0000000..c180b0a
--- /dev/null
+++ b/ucs2-lib/src/ucs_fsm.c
@@ -0,0 +1,172 @@
+/*------------------------------------------------------------------------------------------------*/
+/* UNICENS V2.1.0-3491 */
+/* Copyright (c) 2017 Microchip Technology Germany II GmbH & Co. KG. */
+/* */
+/* This program is free software: you can redistribute it and/or modify */
+/* it under the terms of the GNU General Public License as published by */
+/* the Free Software Foundation, either version 2 of the License, or */
+/* (at your option) any later version. */
+/* */
+/* This program is distributed in the hope that it will be useful, */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
+/* GNU General Public License for more details. */
+/* */
+/* You should have received a copy of the GNU General Public License */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
+/* */
+/* You may also obtain this software under a propriety license from Microchip. */
+/* Please contact Microchip for further information. */
+/*------------------------------------------------------------------------------------------------*/
+
+/*!
+ * \file
+ * \brief Implementation of the Finite State Machine.
+ *
+ * \cond UCS_INTERNAL_DOC
+ * \addtogroup G_FSM
+ * @{
+ */
+
+/*------------------------------------------------------------------------------------------------*/
+/* Includes */
+/*------------------------------------------------------------------------------------------------*/
+#include "ucs_fsm.h"
+#include "ucs_misc.h"
+
+/*------------------------------------------------------------------------------------------------*/
+/* Internal definitions */
+/*------------------------------------------------------------------------------------------------*/
+/*! \brief NIL-event, indicates that no event is pending at the moment */
+#define FSM_E_NILEVENT 0
+
+/*------------------------------------------------------------------------------------------------*/
+/* Internal prototypes */
+/*------------------------------------------------------------------------------------------------*/
+static Fsm_Act_t Fsm_StateEval(CFsm *self);
+
+/*------------------------------------------------------------------------------------------------*/
+/* Implementation */
+/*------------------------------------------------------------------------------------------------*/
+/*! \brief Constructor of the Finite State Machine class.
+ * \param self Instance pointer
+ * \param inst_ptr Instance pointer used for state machine actions
+ * \param trans_table_ptr Pointer to transition table
+ * \param num_events Maximum number of events
+ * \param init_state Initialization state to start with
+ */
+void Fsm_Ctor(CFsm *self, void *inst_ptr, const Fsm_StateElem_t *trans_table_ptr,
+ uint8_t num_events, int8_t init_state)
+{
+ MISC_MEM_SET(self, 0, sizeof(*self));
+ self->inst_ptr = inst_ptr;
+ self->event_occured = FSM_E_NILEVENT; /* Clear event variable */
+ self->current_state = init_state; /* Set initialization state */
+ self->transition_table_ptr = trans_table_ptr; /* Set pointer to given transition table */
+ self->num_events = num_events; /* Store maximum number of events */
+ self->internal_state = FSM_STATE_IDLE; /* Clear internal state */
+}
+
+/*! \brief Determine required action
+ * \details This function determines the required action in dependency of the current state
+ * and the triggered event. The current state will be transitioned to the next state.
+ * The internal event variable will be cleared and the determined action will be
+ * returned.
+ * \param self Instance pointer
+ * \return Determined required action
+ * \return \c NULL if no action is required
+ */
+static Fsm_Act_t Fsm_StateEval(CFsm *self)
+{
+ Fsm_Act_t retval = NULL; /* Set default return value */
+
+ if(self->event_occured != FSM_E_NILEVENT) /* Event occurred ? */
+ {
+ if((uint8_t)self->event_occured <= self->num_events) /* Check if event is valid */
+ {
+ /* Get state-matrix-element in dependency of current state and triggered event */
+ uint8_t i = ((uint8_t)self->current_state * self->num_events) + (uint8_t)self->event_occured;
+ Fsm_StateElem_t stateEvaluation = self->transition_table_ptr[i];
+ self->current_state = stateEvaluation.next_state; /* Set new state */
+ self->internal_state = FSM_STATE_IDLE; /* Set internal state to \c IDLE */
+ retval = stateEvaluation.action_fptr; /* Return required action */
+ }
+ else
+ {
+ self->internal_state = FSM_STATE_ERROR; /* Error occurred: Unknown event */
+ }
+
+ self->event_occured = FSM_E_NILEVENT; /* Clear event variable */
+ }
+
+ return retval;
+}
+
+/*! \brief Service function for Finite State Machines
+ * \details The state machine will be serviced until it will be stopped by the user or no
+ * further event is triggered. If a state transition occurred the associated action
+ * will be executed.
+ * \param self Instance pointer
+ * \return Internal state of the state machine (see \ref Fsm_State_t).
+ */
+Fsm_State_t Fsm_Service(CFsm *self)
+{
+ /* Internal state is set to \c FSM_STATE_SERVICE and any event is triggered? */
+ while((self->internal_state == FSM_STATE_SERVICE) && (self->event_occured != FSM_E_NILEVENT))
+ {
+ Fsm_Act_t action_fptr = Fsm_StateEval(self); /* Execute state transition */
+ if(action_fptr != NULL) /* Action required ? */
+ {
+ (*action_fptr)(self->inst_ptr); /* Execute action */
+ }
+ }
+
+ return self->internal_state; /* Return internal state machine state */
+}
+
+/*! \brief Set an event
+ * \details This function sets the given event and triggers the service for the given
+ * state machine.
+ * \param self Instance pointer
+ * \param e New event
+ */
+void Fsm_SetEvent(CFsm *self, int8_t e)
+{
+ if(self->internal_state != FSM_STATE_END)
+ {
+ self->event_occured = e; /* Set new event */
+ self->internal_state = FSM_STATE_SERVICE; /* Set internal state to \c FSM_STATE_SERVICE */
+ }
+}
+
+/*! \brief Sets the wait state
+ * \details This function sets the given state state machine into the wait state. The state
+ * machine stops and must be re-triggered.
+ * \param self Instance pointer
+ */
+void Fsm_Wait(CFsm *self)
+{
+ if(self->internal_state != FSM_STATE_END)
+ {
+ self->internal_state = FSM_STATE_WAIT; /* Set internal state to \c WAIT */
+ }
+}
+
+/*! \brief End processing of the state machine
+ * \details If this function is called the given state machine will be stopped immediately.
+ * \param self Instance pointer
+ */
+void Fsm_End(CFsm *self)
+{
+ self->internal_state = FSM_STATE_END; /* Set internal state to \c END */
+}
+
+/*!
+ * @}
+ * \endcond
+ */
+
+/*------------------------------------------------------------------------------------------------*/
+/* End of file */
+/*------------------------------------------------------------------------------------------------*/
+