Updated GDB ini file to load binding symbols directly from SDK
[apps/agl-service-unicens.git] / ucs2-lib / src / ucs_fsm.c
1 /*------------------------------------------------------------------------------------------------*/
2 /* UNICENS V2.1.0-3491                                                                            */
3 /* Copyright (c) 2017 Microchip Technology Germany II GmbH & Co. KG.                              */
4 /*                                                                                                */
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.                                                            */
9 /*                                                                                                */
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.                                                   */
14 /*                                                                                                */
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/>.                          */
17 /*                                                                                                */
18 /* You may also obtain this software under a propriety license from Microchip.                    */
19 /* Please contact Microchip for further information.                                              */
20 /*------------------------------------------------------------------------------------------------*/
21
22 /*!
23  * \file
24  * \brief Implementation of the Finite State Machine.
25  *
26  * \cond UCS_INTERNAL_DOC
27  * \addtogroup G_FSM
28  * @{
29  */
30
31 /*------------------------------------------------------------------------------------------------*/
32 /* Includes                                                                                       */
33 /*------------------------------------------------------------------------------------------------*/
34 #include "ucs_fsm.h"
35 #include "ucs_misc.h"
36
37 /*------------------------------------------------------------------------------------------------*/
38 /* Internal definitions                                                                           */
39 /*------------------------------------------------------------------------------------------------*/
40 /*! \brief NIL-event, indicates that no event is pending at the moment */
41 #define FSM_E_NILEVENT      0
42
43 /*------------------------------------------------------------------------------------------------*/
44 /* Internal prototypes                                                                            */
45 /*------------------------------------------------------------------------------------------------*/
46 static Fsm_Act_t Fsm_StateEval(CFsm *self);
47
48 /*------------------------------------------------------------------------------------------------*/
49 /* Implementation                                                                                 */
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
57  */
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)
60 {
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 */
68 }
69
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 
74  *           returned.
75  *  \param   self    Instance pointer
76  *  \return  Determined required action
77  *  \return  \c NULL if no action is required
78  */
79 static Fsm_Act_t Fsm_StateEval(CFsm *self)
80 {
81     Fsm_Act_t retval = NULL;                                    /* Set default return value */
82
83     if(self->event_occured != FSM_E_NILEVENT)                   /* Event occurred ? */
84     {
85         if((uint8_t)self->event_occured <= self->num_events)    /* Check if event is valid */
86         {
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 */
93         }
94         else
95         {
96             self->internal_state = FSM_STATE_ERROR;             /* Error occurred: Unknown event */
97         }
98
99         self->event_occured = FSM_E_NILEVENT;                   /* Clear event variable */
100     }
101
102     return retval;
103 }
104
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 
108  *           will be executed.
109  *  \param   self    Instance pointer
110  *  \return  Internal state of the state machine (see \ref Fsm_State_t).
111  */
112 Fsm_State_t Fsm_Service(CFsm *self)
113 {
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))
116     {
117         Fsm_Act_t action_fptr = Fsm_StateEval(self);    /* Execute state transition */
118         if(action_fptr != NULL)                          /* Action required ? */
119         {
120             (*action_fptr)(self->inst_ptr);             /* Execute action */
121         }
122     }
123
124     return self->internal_state;                        /* Return internal state machine state */
125 }
126
127 /*! \brief   Set an event
128  *  \details This function sets the given event and triggers the service for the given 
129  *           state machine.
130  *  \param   self    Instance pointer
131  *  \param   e       New event
132  */
133 void Fsm_SetEvent(CFsm *self, int8_t e)
134 {
135     if(self->internal_state != FSM_STATE_END)
136     {
137         self->event_occured  = e;                  /* Set new event */
138         self->internal_state = FSM_STATE_SERVICE;  /* Set internal state to \c FSM_STATE_SERVICE */
139     }
140 }
141
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
146  */
147 void Fsm_Wait(CFsm *self)
148 {
149     if(self->internal_state != FSM_STATE_END)
150     {
151         self->internal_state = FSM_STATE_WAIT;     /* Set internal state to \c WAIT */
152     }
153 }
154
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
158  */
159 void Fsm_End(CFsm *self)
160 {
161     self->internal_state = FSM_STATE_END;      /* Set internal state to \c END */
162 }
163
164 /*!
165  * @}
166  * \endcond
167  */
168
169 /*------------------------------------------------------------------------------------------------*/
170 /* End of file                                                                                    */
171 /*------------------------------------------------------------------------------------------------*/
172