fsm.h

Go to the documentation of this file.
00001 
00010 /* Copyright: (c) 2007 DCE Eurobot Dragon Team
00011  *            CTU FEE - Department of Control Engineering
00012  * Contacts: Tran Duy Khanh <trandk1@fel.cvut.cz>
00013  * License: GNU GPL v.2
00014  */
00015 
00143 #ifndef __robofsm__
00144 #define __robofsm__
00145 
00146 #include <stdlib.h>
00147 #include <pthread.h>
00148 #include <semaphore.h>
00149 #include <sys/time.h>
00150 #include <errno.h>
00151 #include "fsm_common_events.h"
00152 
00157 typedef int fsm_event;
00158 
00159 #ifndef __FSM_ALIASES_DEFINED
00160 #define EV_NOEVENT        __COMMON_EV_NOEVENT
00161 #define EV_INIT           __COMMON_EV_INIT
00162 #define EV_EXIT           __COMMON_EV_EXIT
00163 #define EV_STATE_ENTERED  __COMMON_EV_STATE_ENTERED
00164 #define EV_RETURN         __COMMON_EV_RETURN
00165 #define EV_TIMEOUT        __COMMON_EV_TIMEOUT
00166 #define EV_TIMER          __COMMON_EV_TIMER
00167 #endif
00168 
00172 struct robo_fsm {
00173         pthread_t threadid;     
00179         sem_t event_noticed;
00181         sem_t event_sent;
00183         fsm_event sent_event;   
00184         fsm_event event;        
00185         struct timespec now;    
00186         struct timespec timeout; 
00187         struct timespec timer;  
00190         int (*state)(struct robo_fsm *fsm);
00191         int (*last_state)(struct robo_fsm *fsm); 
00193         int (*fnc_stack[10])(struct robo_fsm *fsm);
00195         int (**fnc_sp)(struct robo_fsm *fsm);
00196         int debug_states;       
00197         char *debug_name;       
00198 };      /* robo_fsm */
00199 
00200 #ifdef __cplusplus
00201 extern "C" {
00202 #endif
00203 
00204 void fsm_init(struct robo_fsm *fsm, char *debug_name);
00205 int fsm_start(struct robo_fsm *fsm, pthread_attr_t *attr);
00206 int fsm_destroy(struct robo_fsm *fsm);
00207 void __fsm_timespec_add_ms(struct timespec *ts, struct timespec *now, long ms);
00208 void __fsm_timespec_invalidate(struct timespec *ts);
00209 
00210 
00211 
00212 /* FSM (Finite State Machine) */
00213 /* do nothing */
00214 int fsm_nop_state(struct robo_fsm *fsm);
00215 
00224 const char *fsm_event_str(fsm_event ev);
00225 const char *fsm_common_event_str(enum fsm_common_events ev);
00226 
00230 #define RC_WAIT         0
00231 
00233 #define RC_PROC         1
00234 
00235 
00236 static inline void __fsm_signal(struct robo_fsm *fsm, fsm_event event)
00237 {
00238         /* Wait for receiver to notice the previous event */
00239         sem_wait(&fsm->event_noticed);
00240         /* Send our event */
00241         fsm->sent_event = event;
00242         sem_post(&fsm->event_sent);
00243 }
00244 
00262 #define FSM_SIGNAL(fsm_id, event) __fsm_signal(FSM_GET_BY_ID(fsm_id), __##fsm_id##_##event)
00263 
00277 #define DBG_STATE()     DBG_FSM_STATE(__FUNCTION__)
00278 #define DBG_FSM_STATE(name)     do { if (fsm->debug_states) DBG("fsm %s: %s(%s)\n", fsm->debug_name, name, fsm_event_str(fsm->event)); } while(0)
00279 
00283 #define DBG_PRINT_EVENT(msg)    DBG("%s: event: %s\n", msg, fsm_event_str(fsm->event))
00284 
00285 #ifdef __cplusplus
00286 }
00287 #endif
00288 
00289 /**********************/
00290 /* High level FSM API */
00291 /**********************/
00292 
00312 #define FSM_STATE(name)                                                 \
00313         static inline void fsm_state_##name##_impl(struct robo_fsm *fsm, int *__ret); \
00314         int fsm_state_##name(struct robo_fsm *fsm) {                    \
00315                 int ret=RC_WAIT;                                        \
00316                 DBG_FSM_STATE(#name);                                   \
00317                 fsm_state_##name##_impl(fsm, &ret);                     \
00318                 return ret;                                             \
00319         }                                                               \
00320         static inline void fsm_state_##name##_impl(struct robo_fsm *fsm, int *__ret)
00321 
00327 #define FSM_STATE_DECL(name) \
00328 int fsm_state_##name(struct robo_fsm *fsm)
00329 
00338 #define FSM_TIMEOUT(ms) __fsm_timespec_add_ms(&fsm->timeout, &fsm->now, (ms))
00339 
00352 #define FSM_TIMER(ms) __fsm_timespec_add_ms(&fsm->timer, &fsm->now, (ms))
00353 
00358 #define FSM_TIMER_STOP() __fsm_timespec_invalidate(&fsm->timer)
00359 
00360 #ifndef __FSM_EVENT_ENUM
00361 /* This macro is normally declared in automatically generated event
00362  * header file. If fsm.h is included from other files, we fall back to
00363  * fsm_common_events. If you get warning: "__FSM_EVENT_ENUM"
00364  * redefined, it means that FSM_xxx definition of event is included
00365  * after fsm.h, which is not correct. */
00366 #define __FSM_EVENT_ENUM enum fsm_common_events
00367 #endif
00368 
00372 #define FSM_EVENT ((__FSM_EVENT_ENUM)(fsm->event))
00373 
00383 #define FSM_TRANSITION(next)                                            \
00384         do {                                                            \
00385                 FSM_TIMER_STOP();                                       \
00386                 fsm->last_state = fsm->state;                           \
00387                 fsm->state = &fsm_state_##next;                         \
00388                 fsm->event = EV_STATE_ENTERED;                          \
00389                 *__ret=RC_PROC;                                         \
00390         } while(0)
00391 
00401 #define SUBFSM_TRANSITION(substate)                                     \
00402         do {                                                            \
00403                 FSM_TIMER_STOP();                                       \
00404                 *(fsm->fnc_sp++) = fsm->state;                          \
00405                 fsm->last_state = fsm->state;                           \
00406                 fsm->state = &fsm_state_##substate;                     \
00407                 fsm->event = EV_STATE_ENTERED;                          \
00408                 *__ret = RC_PROC;                                       \
00409                 return;                                                 \
00410  } while(0)
00411 
00416 #define SUBFSM_RET()                                                    \
00417         do {                                                            \
00418                 fsm->last_state = fsm->state;                           \
00419                 fsm->state = *(--fsm->fnc_sp);                          \
00420                 fsm->event = EV_RETURN;                                 \
00421                 *__ret = RC_PROC;                                       \
00422         } while(0)
00423 
00424 #endif  /* __robofsm__ */

Generated on Thu Sep 13 11:28:28 2007 for DCE-Eurobot by  doxygen 1.5.3