Linux Face / QPFramework
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers qep.h Source File

qep.h

Go to the documentation of this file.
00001 //////////////////////////////////////////////////////////////////////////////
00002 // Product: QEP/C++ platform-independent public interface
00003 // Last Updated for Version: 4.0.04
00004 // Date of the Last Update:  Apr 08, 2009
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2009 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00027 //////////////////////////////////////////////////////////////////////////////
00028 #ifndef qep_h
00029 #define qep_h
00030 
00031 /// \file
00032 /// \ingroup qep qf qk
00033 /// \brief QEP/C++ platform-independent public interface.
00034 ///
00035 /// This header file must be included directly or indirectly
00036 /// in all modules (*.cpp files) that use QEP/C++.
00037 
00038 #include "qevent.h"           // QEP event processor needs the QEvent facility
00039 
00040 //////////////////////////////////////////////////////////////////////////////
00041 /// \brief Provides miscellaneous QEP services.
00042 class QEP {
00043 public:
00044     /// \brief get the current QEP version number string
00045     ///
00046     /// \return version of the QEP as a constant 6-character string of the
00047     /// form x.y.zz, where x is a 1-digit major version number, y is a
00048     /// 1-digit minor version number, and zz is a 2-digit release number.
00049     static char const Q_ROM * Q_ROM_VAR getVersion(void);
00050 };
00051 
00052 //////////////////////////////////////////////////////////////////////////////
00053 
00054                        /// \brief Type returned from  a state-handler function
00055 typedef uint8_t QState;
00056 
00057                                   /// \brief pointer to state-handler function
00058 typedef QState (*QStateHandler)(void *me, QEvent const *e);
00059 
00060 
00061 //////////////////////////////////////////////////////////////////////////////
00062 /// \brief Finite State Machine base class
00063 ///
00064 /// QFsm represents a traditional non-hierarchical Finite State Machine (FSM)
00065 /// without state hierarchy, but with entry/exit actions.
00066 ///
00067 /// QFsm is also a base structure for the ::QHsm class.
00068 ///
00069 /// \note QFsm is not intended to be instantiated directly, but rather serves
00070 /// as the base class for derivation of state machines in the application
00071 /// code.
00072 ///
00073 /// The following example illustrates how to derive a state machine class
00074 /// from QFsm.
00075 /// \include qep_qfsm.cpp
00076 class QFsm {
00077 protected:
00078     QStateHandler m_state;          ///< current active state (state-variable)
00079 
00080 public:
00081     /// \brief virtual destructor
00082     virtual ~QFsm();
00083 
00084     /// \brief Performs the second step of FSM initialization by triggering
00085     /// the top-most initial transition.
00086     ///
00087     /// The argument \a e is constant pointer to ::QEvent or a class
00088     /// derived from ::QEvent.
00089     ///
00090     /// \note Must be called only ONCE before QFsm::dispatch()
00091     ///
00092     /// The following example illustrates how to initialize a FSM, and
00093     /// dispatch events to it:
00094     /// \include qep_qfsm_use.cpp
00095     void init(QEvent const *e = (QEvent *)0);
00096 
00097     /// \brief Dispatches an event to a FSM
00098     ///
00099     /// Processes one event at a time in Run-to-Completion (RTC) fashion.
00100     /// The argument \a e is a constant pointer the ::QEvent or a
00101     /// class derived from ::QEvent.
00102     ///
00103     /// \note Must be called after QFsm::init().
00104     ///
00105     /// \sa example for QFsm::init()
00106     void dispatch(QEvent const *e);
00107 
00108 protected:
00109 
00110     /// \brief Protected constructor of a FSM.
00111     ///
00112     /// Performs the first step of FSM initialization by assigning the
00113     /// initial pseudostate to the currently active state of the state
00114     /// machine.
00115     ///
00116     /// \note The constructor is protected to prevent direct instantiating
00117     /// of QFsm objects. This class is intended for subclassing only.
00118     ///
00119     /// \sa The ::QFsm example illustrates how to use the QHsm constructor
00120     /// in the constructor initializer list of the derived state machines.
00121     QFsm(QStateHandler initial) : m_state(initial) {}
00122 };
00123 
00124 //////////////////////////////////////////////////////////////////////////////
00125 /// \brief Hierarchical State Machine base class
00126 ///
00127 /// QHsm represents a Hierarchical Finite State Machine (HSM). QHsm derives
00128 /// from the ::QFsm class and extends the capabilities of a basic FSM
00129 /// with state hierarchy.
00130 ///
00131 /// \note QHsm is not intended to be instantiated directly, but rather serves
00132 /// as the base structure for derivation of state machines in the application
00133 /// code.
00134 ///
00135 /// The following example illustrates how to derive a state machine class
00136 /// from QHsm.
00137 /// \include qep_qhsm.cpp
00138 class QHsm {
00139 protected:
00140     QStateHandler m_state;          ///< current active state (state-variable)
00141 
00142 public:
00143     /// \brief virtual destructor
00144     virtual ~QHsm();
00145 
00146     /// \brief Performs the second step of HSM initialization by triggering
00147     /// the top-most initial transition.
00148     ///
00149     /// \param e constant pointer ::QEvent or a class derived from ::QEvent
00150     /// \note Must be called only ONCE before QHsm::dispatch()
00151     ///
00152     /// The following example illustrates how to initialize a HSM, and
00153     /// dispatch events to it:
00154     /// \include qep_qhsm_use.cpp
00155     void init(QEvent const *e = (QEvent *)0);
00156 
00157     /// \brief Dispatches an event to a HSM
00158     ///
00159     /// Processes one event at a time in Run-to-Completion (RTC) fashion.
00160     /// The argument \a e is a constant pointer the ::QEvent or a
00161     /// class derived from ::QEvent.
00162     ///
00163     /// \note Must be called after QHsm::init().
00164     ///
00165     /// \sa example for QHsm::init()
00166     void dispatch(QEvent const *e);
00167 
00168     /// \brief Tests if a given state is part of the current active state
00169     /// configuratioin
00170     ///
00171     /// \param state is a pointer to the state handler function, e.g.,
00172     /// &QCalc::on.
00173     uint8_t isIn(QStateHandler state);
00174 
00175 protected:
00176 
00177     /// \brief Protected constructor of a HSM.
00178     ///
00179     /// Performs the first step of HSM initialization by assigning the
00180     /// initial pseudostate to the currently active state of the state
00181     /// machine.
00182     ///
00183     /// \note The constructor is protected to prevent direct instantiating
00184     /// of QHsm objects. This class is intended for subclassing only.
00185     ///
00186     /// \sa The ::QHsm example illustrates how to use the QHsm constructor
00187     /// in the constructor initializer list of the derived state machines.
00188     /// \sa QFsm::QFsm()
00189     QHsm(QStateHandler initial) : m_state(initial) {}
00190 
00191     /// \brief the top-state.
00192     ///
00193     /// QHsm::top() is the ultimate root of state hierarchy in all HSMs
00194     /// derived from ::QHsm. This state handler always returns (QSTATE)0,
00195     /// which means that it "handles" all events.
00196     ///
00197     /// \sa Example of the QCalc::on() state handler.
00198     static QState top(QHsm *me, QEvent const *e);
00199 };
00200 
00201 /// \brief Value returned by a non-hierarchical state-handler function when
00202 /// it ignores (does not handle) the event.
00203 #define Q_RET_IGNORED       ((QState)1)
00204 
00205 /// \brief The macro returned from a non-hierarchical state-handler function
00206 /// when it ignores (does not handle) the event.
00207 ///
00208 /// You call that macro after the return statement (return Q_IGNORED();)
00209 ///
00210 /// \include qepn_qfsm.cpp
00211 #define Q_IGNORED()         (Q_RET_IGNORED)
00212 
00213 /// \brief Value returned by a state-handler function when it handles
00214 /// the event.
00215 #define Q_RET_HANDLED       ((QState)0)
00216 
00217 /// \brief Value returned by a state-handler function when it handles
00218 /// the event.
00219 ///
00220 /// You call that macro after the return statement (return Q_HANDLED();)
00221 /// Q_HANDLED() can be used both in the FSMs and HSMs.
00222 ///
00223 /// \include qepn_qfsm.cpp
00224 #define Q_HANDLED()         (Q_RET_HANDLED)
00225 
00226 /// \brief Value returned by a state-handler function when it takes a
00227 /// regular state transition.
00228 #define Q_RET_TRAN          ((QState)2)
00229 
00230 /// \brief Designates a target for an initial or regular transition.
00231 /// Q_TRAN() can be used both in the FSMs and HSMs.
00232 ///
00233 /// \include qepn_qtran.cpp
00234 //lint -e960 -e1924 ignore MISRA Rule 42 (comma operator) and C-style cast
00235 #define Q_TRAN(target_)  \
00236     (me->m_state = (QStateHandler)(target_), Q_RET_TRAN)
00237 
00238 /// \brief Value returned by a state-handler function when it cannot
00239 /// handle the event.
00240 #define Q_RET_SUPER         ((QState)3)
00241 
00242 /// \brief Designates the superstate of a given state in an HSM.
00243 ///
00244 /// \include qepn_qhsm.cpp
00245 //lint -e960 -e1924 ignore MISRA Rule 42 (comma operator) and C-style cast
00246 #define Q_SUPER(super_)  \
00247     (me->m_state = (QStateHandler)(super_),  Q_RET_SUPER)
00248 
00249 
00250 //////////////////////////////////////////////////////////////////////////////
00251 /// \brief QEP reserved signals.
00252 enum QReservedSignals {
00253     Q_ENTRY_SIG = 1,                             ///< signal for entry actions
00254     Q_EXIT_SIG,                                   ///< signal for exit actions
00255     Q_INIT_SIG,                     ///< signal for nested initial transitions
00256     Q_USER_SIG                              ///< signal to offset user signals
00257 };
00258 
00259 //////////////////////////////////////////////////////////////////////////////
00260 // QS software tracing integration, only if enabled
00261 #ifdef Q_SPY                                   // QS software tracing enabled?
00262     #ifndef qs_h
00263     #include "qs_port.h"                                    // include QS port
00264     #endif                                                             // qs_h
00265 
00266     #if (Q_SIGNAL_SIZE == 1)
00267 
00268         /// \brief Internal QS macro to output an unformatted event signal
00269         /// data element
00270         /// \note the size of the pointer depends on the macro #Q_SIGNAL_SIZE.
00271         #define QS_SIG_(sig_)       QS::u8_(sig_)
00272     #elif (Q_SIGNAL_SIZE == 2)
00273         #define QS_SIG_(sig_)       QS::u16_(sig_)
00274     #elif (Q_SIGNAL_SIZE == 4)
00275         #define QS_SIG_(sig_)       QS::u32_(sig_)
00276     #endif
00277 
00278 #else
00279     #ifndef qs_dummy_h
00280     #include "qs_dummy.h"                   // disable the QS software tracing
00281     #endif
00282 #endif                                                                // Q_SPY
00283 
00284 #endif                                                                // qep_h