示例#1
0
/*..........................................................................*/
void QFsm_dispatch(QFsm *me, QEvent const *e) {
    QStateHandler s = me->state;                  /* save the current state */
    QS_INT_LOCK_KEY_
    QState r = (*s)(me, e);                       /* call the event handler */

    if (r == Q_RET_TRAN) {                             /* transition taken? */

        QS_BEGIN_(QS_QEP_TRAN, QS_smObj_, me)
            QS_TIME_();                                       /* time stamp */
            QS_SIG_(e->sig);                     /* the signal of the event */
            QS_OBJ_(me);                       /* this state machine object */
            QS_FUN_(s);                     /* the source of the transition */
            QS_FUN_(me->state);                     /* the new active state */
        QS_END_()

        (void)QEP_TRIG_(s, Q_EXIT_SIG);                 /* exit the source */
        (void)QEP_TRIG_(me->state, Q_ENTRY_SIG);        /* enter the target */
    }
    else {                                          /* transition not taken */
#ifdef Q_SPY
        if (r == Q_RET_HANDLED) {

            QS_BEGIN_(QS_QEP_INTERN_TRAN, QS_smObj_, me)
                QS_TIME_();                                   /* time stamp */
                QS_SIG_(e->sig);                 /* the signal of the event */
                QS_OBJ_(me);                   /* this state machine object */
                QS_FUN_(s);             /* the state that handled the event */
            QS_END_()
        }
        else {
示例#2
0
/*..........................................................................*/
void QFsm_init_(QFsm * const me, QEvt const * const e) {
    QS_CRIT_STAT_

    Q_REQUIRE((me->vptr != (QMsmVtbl const *)0)    /* ctor must be executed */
              && (me->temp.fun != Q_STATE_CAST(0)) /* ctor must be executed */
              && (me->state.fun == Q_STATE_CAST(0)));/*init tran. NOT taken */

    QS_BEGIN_(QS_QEP_STATE_INIT, QS_priv_.smObjFilter, me)
        QS_OBJ_(me);                           /* this state machine object */
        QS_FUN_(Q_STATE_CAST(0));   /* source state (not defined for a FSM) */
        QS_FUN_(me->temp.fun);              /* the target of the transition */
    QS_END_()

                                 /* execute the top-most initial transition */
    Q_ALLEGE((*me->temp.fun)(me, e) == (QState)Q_RET_TRAN);/* must be taken */

    (void)QEP_TRIG_(me->temp.fun, Q_ENTRY_SIG);         /* enter the target */
    me->state.fun = me->temp.fun;            /* record the new active state */

    QS_BEGIN_(QS_QEP_INIT_TRAN, QS_priv_.smObjFilter, me)
        QS_TIME_();                                           /* time stamp */
        QS_OBJ_(me);                           /* this state machine object */
        QS_FUN_(me->state.fun);                     /* the new active state */
    QS_END_()
}
示例#3
0
//............................................................................
void QMsm::dispatch(QEvt const * const e) {
    QMState const *s = m_state.obj;                 // store the current state
    QMState const *t;
    QState r = Q_RET_HANDLED;
    QS_CRIT_STAT_

    Q_REQUIRE(s != (QMState const *)0);                 // must be initialized

    QS_BEGIN_(QS_QEP_DISPATCH, QS::priv_.smObjFilter, this)
        QS_TIME_();                                              // time stamp
        QS_SIG_(e->sig);                            // the signal of the event
        QS_OBJ_(this);                            // this state machine object
        QS_FUN_(s->stateHandler);                 // the current state handler
    QS_END_()

    for (t = s; t != static_cast<QMState const *>(0); t = t->parent) {
        r = (*t->stateHandler)(this, e);
        if (r != Q_RET_SUPER) {
            if (r == Q_RET_UNHANDLED) {           // unhandled due to a guard?

                QS_BEGIN_(QS_QEP_UNHANDLED, QS::priv_.smObjFilter, this)
                    QS_SIG_(e->sig);                // the signal of the event
                    QS_OBJ_(this);                // this state machine object
                    QS_FUN_(t->stateHandler);             // the current state
                QS_END_()
            }
            else {
                break;                 // event handled--break out of the loop
            }
        }
示例#4
0
/*..........................................................................*/
void QHsm_init(QHsm *me, QEvent const *e) {
    QHsmState s;
                /* this state machine must be initialized with QHsm_ctor_() */
    Q_REQUIRE(((QFsm *)me)->state__.fsm != (QState)0);

    s = &QHsm_top;                        /* an HSM starts in the top state */
                                          /* trigger the initial transition */
    (*((QFsm *)me)->state__.fsm)((QFsm *)me, e);

    do {                                        /* drill into the target... */
        QHsmState path[QEP_MAX_NEST_DEPTH_];
        int8_t ip = (int8_t)0;               /* transition entry path index */
        QHsmState t = ((QFsm *)me)->state__.hsm;

        QS_BEGIN_(QS_QEP_STATE_INIT, QS_smObj_, me);
            QS_OBJ_(me);                       /* this state machine object */
            QS_FUN_(s);                                 /* the source state */
            QS_FUN_(((QFsm *)me)->state__.hsm);               /* the target */
        QS_END_();

        path[0] = t;
        for (t = QEP_TRIG_(t, QEP_EMPTY_SIG_); t != s;
             t = QEP_TRIG_(t, QEP_EMPTY_SIG_))
        {
            path[++ip] = t;
        }
                                            /* entry path must not overflow */
        Q_ASSERT(ip < (int8_t)QEP_MAX_NEST_DEPTH_);

        do {        /* retrace the entry path in reverse (desired) order... */
                                                          /* enter path[ip] */
            if (QEP_TRIG_(path[ip], Q_ENTRY_SIG) == (QHsmState)0) {

                QS_BEGIN_(QS_QEP_STATE_ENTRY, QS_smObj_, me);
                    QS_OBJ_(me);               /* this state machine object */
                    QS_FUN_(path[ip]);                 /* the entered state */
                QS_END_();
            }
        } while (--ip >= (int8_t)0);

        s = ((QFsm *)me)->state__.hsm;
    } while (QEP_TRIG_(s, Q_INIT_SIG) == (QHsmState)0);

    QS_BEGIN_(QS_QEP_INIT_TRAN, QS_smObj_, me);
        QS_TIME_();                                           /* time stamp */
        QS_OBJ_(me);                           /* this state machine object */
        QS_FUN_(((QFsm *)me)->state__.hsm);         /* the new active state */
    QS_END_();
}
示例#5
0
/*..........................................................................*/
void QHsm_init(QHsm * const me, QEvt const * const e) {
    QStateHandler t = me->state.fun;
    QS_CRIT_STAT_

    Q_REQUIRE((me->vptr != (QMsmVtbl const *)0)    /* ctor must be executed */
              && (me->temp.fun != Q_STATE_CAST(0)) /* ctor must be executed */
              && (t == Q_STATE_CAST(&QHsm_top))); /*initial tran. NOT taken */

                           /* the top-most initial transition must be taken */
    Q_ALLEGE((*me->temp.fun)(me, e) == (QState)Q_RET_TRAN);

    do {                                        /* drill into the target... */
        QStateHandler path[QEP_MAX_NEST_DEPTH_];
        int_t ip = (int_t)0;                 /* transition entry path index */

        QS_BEGIN_(QS_QEP_STATE_INIT, QS_priv_.smObjFilter, me)
            QS_OBJ_(me);                       /* this state machine object */
            QS_FUN_(t);                                 /* the source state */
            QS_FUN_(me->temp.fun);  /* the target of the initial transition */
        QS_END_()

        path[0] = me->temp.fun;
        (void)QEP_TRIG_(me->temp.fun, QEP_EMPTY_SIG_);
        while (me->temp.fun != t) {
            ++ip;
            path[ip] = me->temp.fun;
            (void)QEP_TRIG_(me->temp.fun, QEP_EMPTY_SIG_);
        }
        me->temp.fun = path[0];
                                            /* entry path must not overflow */
        Q_ASSERT(ip < (int_t)QEP_MAX_NEST_DEPTH_);

        do {        /* retrace the entry path in reverse (desired) order... */
            QEP_ENTER_(path[ip]);                         /* enter path[ip] */
            --ip;
        } while (ip >= (int_t)0);

        t = path[0];                /* current state becomes the new source */
    } while (QEP_TRIG_(t, Q_INIT_SIG) == (QState)Q_RET_TRAN);

    QS_BEGIN_(QS_QEP_INIT_TRAN, QS_priv_.smObjFilter, me)
        QS_TIME_();                                           /* time stamp */
        QS_OBJ_(me);                           /* this state machine object */
        QS_FUN_(t);                                 /* the new active state */
    QS_END_()

    me->state.fun = t;                   /* change the current active state */
    me->temp.fun  = t;                  /* mark the configuration as stable */
}
示例#6
0
//............................................................................
void QHsm::init(QEvent const *e) {
    QStateHandler t;
    QS_INT_LOCK_KEY_

                              // the top-most initial transition must be taken
    Q_ALLEGE((*m_state)(this, e) == Q_RET_TRAN);

    t = (QStateHandler)&QHsm::top;              // HSM starts in the top state
    do {                                           // drill into the target...
        QStateHandler path[QEP_MAX_NEST_DEPTH_];
        int8_t ip = (int8_t)0;                  // transition entry path index


        QS_BEGIN_(QS_QEP_STATE_INIT, QS::smObj_, this)
            QS_OBJ_(this);                        // this state machine object
            QS_FUN_(t);                                    // the source state
            QS_FUN_(m_state);          // the target of the initial transition
        QS_END_()

        path[0] = m_state;
        (void)QEP_TRIG_(m_state, QEP_EMPTY_SIG_);
        while (m_state != t) {
            ++ip;
            path[ip] = m_state;
            (void)QEP_TRIG_(m_state, QEP_EMPTY_SIG_);
        }
        m_state = path[0];
                                               // entry path must not overflow
        Q_ASSERT(ip < (int8_t)QEP_MAX_NEST_DEPTH_);

        do {           // retrace the entry path in reverse (desired) order...
            QEP_ENTER_(path[ip]);                            // enter path[ip]
            --ip;
        } while (ip >= (int8_t)0);

        t = path[0];                   // current state becomes the new source
    } while (QEP_TRIG_(t, Q_INIT_SIG) == Q_RET_TRAN);
    m_state = t;

    QS_BEGIN_(QS_QEP_INIT_TRAN, QS::smObj_, this)
        QS_TIME_();                                              // time stamp
        QS_OBJ_(this);                            // this state machine object
        QS_FUN_(m_state);                              // the new active state
    QS_END_()
}
示例#7
0
/*..........................................................................*/
void QS_fun_dict(void (* const fun)(void),
                 char_t const Q_ROM * const name)
{
    QS_CRIT_STAT_
    QS_CRIT_ENTRY_();
    QS_beginRec((uint8_t)QS_FUN_DICT);
    QS_FUN_(fun);
    QS_STR_ROM_(name);
    QS_endRec();
    QS_CRIT_EXIT_();
    QS_onFlush();
}
示例#8
0
/*..........................................................................*/
void QFsm_init(QFsm *me, QEvent const *e) {
    QState initial;
    Q_REQUIRE(me->state__.fsm != (QState)0);         /* must be initialized */
    initial = me->state__.fsm;              /* save the initial pseudostate */

    QS_BEGIN_(QS_QEP_STATE_INIT, QS_smObj_, me);
        QS_OBJ_(me);                           /* this state machine object */
        QS_FUN_((QState)0);           /* the source (not defined for a FSM) */
        QS_FUN_(me->state__.fsm);           /* the target of the transition */
    QS_END_();

    (*initial)(me, e);                    /* trigger the initial transition */
    Q_ASSERT(initial != me->state__.fsm);     /* cannot stay in the initial */
    (*me->state__.fsm)(me, &QEP_reservedEvt_[Q_ENTRY_SIG]); /* enter target */

    QS_BEGIN_(QS_QEP_INIT_TRAN, QS_smObj_, me);
        QS_TIME_();                                           /* time stamp */
        QS_OBJ_(me);                           /* this state machine object */
        QS_FUN_(me->state__.fsm);                   /* the new active state */
    QS_END_();
}
示例#9
0
文件: qep_msm.c 项目: KnightSch/qpc
/**
* @description
* Executes the top-most initial transition in a MSM.
*
* @param[in,out] me pointer (see @ref oop)
* @param[in]     e  pointer to the initialization event (might be NULL)
*
* @note Must be called only ONCE after the QMsm_ctor().
*/
void QMsm_init_(QMsm * const me, QEvt const * const e) {
    QState r;
    QS_CRIT_STAT_

    /** @pre the virtual pointer must be initialized, the top-most initial
    * transition must be initialized, and the initial transition must not
    * be taken yet.
    */
    Q_REQUIRE_ID(200, (me->vptr != (QMsmVtbl const *)0)
                      && (me->temp.fun != Q_STATE_CAST(0))
                      && (me->state.obj == &l_msm_top_s));

    r = (*me->temp.fun)(me, e); /* the action of the top-most initial tran. */

    /* the top-most initial transition must be taken */
    Q_ASSERT_ID(210, r == (QState)Q_RET_TRAN_INIT);

    QS_BEGIN_(QS_QEP_STATE_INIT, QS_priv_.smObjFilter, me)
        QS_OBJ_(me); /* this state machine object */
        QS_FUN_(me->state.obj->stateHandler);        /* source state handler*/
        QS_FUN_(me->temp.tatbl->target->stateHandler);/*target state handler*/
    QS_END_()

    /* set state to the last tran. target */
    me->state.obj = me->temp.tatbl->target;

    /* drill down into the state hierarchy with initial transitions... */
    do {
        r = QMsm_execTatbl_(me, me->temp.tatbl); /* execute the tran. table */
    } while (r >= (QState)Q_RET_TRAN_INIT);

    QS_BEGIN_(QS_QEP_INIT_TRAN, QS_priv_.smObjFilter, me)
        QS_TIME_();                           /* time stamp */
        QS_OBJ_(me);                          /* this state machine object */
        QS_FUN_(me->state.obj->stateHandler); /* the new current state */
    QS_END_()
}
示例#10
0
/**
* \description
* Dispatches an event for processing to a hierarchical state machine (HSM).
* The processing of an event represents one run-to-completion (RTC) step.
*
* \arguments
* \arg[in,out] \c me pointer (see \ref derivation)
* \arg[in]     \c e  pointer to the event to be dispatched to the HSM
*
* \note
* This function should be called only via the virtual table (see
* QMSM_DISPATCH()) and should NOT be called directly in the applications.
*/
void QHsm_dispatch_(QHsm * const me, QEvt const * const e) {
    QStateHandler t = me->state.fun;
    QStateHandler s;
    QState r;
    QS_CRIT_STAT_

    /** \pre the state configuration must be stable */
    Q_REQUIRE_ID(100, t == me->temp.fun);

    QS_BEGIN_(QS_QEP_DISPATCH, QS_priv_.smObjFilter, me)
        QS_TIME_();         /* time stamp */
        QS_SIG_(e->sig);    /* the signal of the event */
        QS_OBJ_(me);        /* this state machine object */
        QS_FUN_(t);         /* the current state */
    QS_END_()

    /* process the event hierarchically... */
    do {
        s = me->temp.fun;
        r = (*s)(me, e); /* invoke state handler s */

        if (r == (QState)Q_RET_UNHANDLED) { /* unhandled due to a guard? */

            QS_BEGIN_(QS_QEP_UNHANDLED, QS_priv_.smObjFilter, me)
                QS_SIG_(e->sig); /* the signal of the event */
                QS_OBJ_(me);     /* this state machine object */
                QS_FUN_(s);      /* the current state */
            QS_END_()

            r = QEP_TRIG_(s, QEP_EMPTY_SIG_); /* find superstate of s */
        }
    } while (r == (QState)Q_RET_SUPER);

    /* transition taken? */
    if (r >= (QState)Q_RET_TRAN) {
        QStateHandler path[QHSM_MAX_NEST_DEPTH_];
        int_fast8_t ip;

        path[0] = me->temp.fun; /* save the target of the transition */
        path[1] = t;
        path[2] = s;

        /* exit current state to transition source s... */
        for (; t != s; t = me->temp.fun) {
            if (QEP_TRIG_(t, Q_EXIT_SIG) == (QState)Q_RET_HANDLED) {
                QS_BEGIN_(QS_QEP_STATE_EXIT, QS_priv_.smObjFilter, me)
                    QS_OBJ_(me); /* this state machine object */
                    QS_FUN_(t);  /* the exited state */
                QS_END_()

                (void)QEP_TRIG_(t, QEP_EMPTY_SIG_); /* find superstate of t */
            }
        }

        ip = QHsm_tran_(me, path);

#ifdef Q_SPY
        if (r == (QState)Q_RET_TRAN_HIST) {

            QS_BEGIN_(QS_QEP_TRAN_HIST, QS_priv_.smObjFilter, me)
                QS_OBJ_(me);     /* this state machine object */
                QS_FUN_(t);      /* the source of the transition */
                QS_FUN_(path[0]);/* the target of the tran. to history */
            QS_END_()

        }
示例#11
0
/*..........................................................................*/
void QHsm_dispatch(QHsm *me, QEvent const *e) {
    QStateHandler path[QEP_MAX_NEST_DEPTH_];
    QStateHandler s;
    QStateHandler t;
    QState r;
    QS_INT_LOCK_KEY_

    t = me->state;                                /* save the current state */

    QS_BEGIN_(QS_QEP_DISPATCH, QS_smObj_, me)
        QS_TIME_();                                           /* time stamp */
        QS_SIG_(e->sig);                         /* the signal of the event */
        QS_OBJ_(me);                           /* this state machine object */
        QS_FUN_(t);                                    /* the current state */
    QS_END_()

    do {                             /* process the event hierarchically... */
        s = me->state;
        r = (*s)(me, e);                          /* invoke state handler s */
    } while (r == Q_RET_SUPER);

    if (r == Q_RET_TRAN) {                             /* transition taken? */
#ifdef Q_SPY
        QStateHandler src = s;    /* save the transition source for tracing */
#endif
        int8_t ip = (int8_t)(-1);            /* transition entry path index */
        int8_t iq;                    /* helper transition entry path index */

        path[0] = me->state;           /* save the target of the transition */
        path[1] = t;

        while (t != s) {    /* exit current state to transition source s... */
            if (QEP_TRIG_(t, Q_EXIT_SIG) == Q_RET_HANDLED) {/*exit handled? */
                QS_BEGIN_(QS_QEP_STATE_EXIT, QS_smObj_, me)
                    QS_OBJ_(me);               /* this state machine object */
                    QS_FUN_(t);                         /* the exited state */
                QS_END_()

                (void)QEP_TRIG_(t, QEP_EMPTY_SIG_); /* find superstate of t */
            }
            t = me->state;                /* me->state holds the superstate */
        }

        t = path[0];                            /* target of the transition */

        if (s == t) {      /* (a) check source==target (transition to self) */
            QEP_EXIT_(s)                                 /* exit the source */
            ip = (int8_t)0;                             /* enter the target */
        }
        else {
            (void)QEP_TRIG_(t, QEP_EMPTY_SIG_);     /* superstate of target */
            t = me->state;
            if (s == t) {                /* (b) check source==target->super */
                ip = (int8_t)0;                         /* enter the target */
            }
            else {
                (void)QEP_TRIG_(s, QEP_EMPTY_SIG_);    /* superstate of src */
                                  /* (c) check source->super==target->super */
                if (me->state == t) {
                    QEP_EXIT_(s)                         /* exit the source */
                    ip = (int8_t)0;                     /* enter the target */
                }
                else {
                                         /* (d) check source->super==target */
                    if (me->state == path[0]) {
                        QEP_EXIT_(s)                     /* exit the source */
                    }
                    else { /* (e) check rest of source==target->super->super..
                            * and store the entry path along the way
                            */
                        iq = (int8_t)0;      /* indicate that LCA not found */
                        ip = (int8_t)1;  /* enter target and its superstate */
                        path[1] = t;       /* save the superstate of target */
                        t = me->state;                /* save source->super */
                                               /* find target->super->super */
                        r = QEP_TRIG_(path[1], QEP_EMPTY_SIG_);
                        while (r == Q_RET_SUPER) {
                            ++ip;
                            path[ip] = me->state;   /* store the entry path */
                            if (me->state == s) {      /* is it the source? */
                                iq = (int8_t)1;  /* indicate that LCA found */
                                            /* entry path must not overflow */
                                Q_ASSERT(ip < (int8_t)QEP_MAX_NEST_DEPTH_);
                                --ip;            /* do not enter the source */
                                r = Q_RET_HANDLED;    /* terminate the loop */
                            }
                            else {   /* it is not the source, keep going up */
                                r = QEP_TRIG_(me->state, QEP_EMPTY_SIG_);
                            }
                        }
                        if (iq == (int8_t)0) {    /* the LCA not found yet? */

                                            /* entry path must not overflow */
                            Q_ASSERT(ip < (int8_t)QEP_MAX_NEST_DEPTH_);

                            QEP_EXIT_(s)                /* exit the source */

                                /* (f) check the rest of source->super
                                 *                  == target->super->super...
                                 */
                            iq = ip;
                            r = Q_RET_IGNORED;    /* indicate LCA NOT found */
                            do {
                                if (t == path[iq]) {    /* is this the LCA? */
                                    r = Q_RET_HANDLED;/* indicate LCA found */
                                    ip = (int8_t)(iq - 1);/*do not enter LCA*/
                                    iq = (int8_t)(-1);/* terminate the loop */
                                }
                                else {
                                    --iq; /* try lower superstate of target */
                                }
                            } while (iq >= (int8_t)0);

                            if (r != Q_RET_HANDLED) { /* LCA not found yet? */
                                    /* (g) check each source->super->...
                                     * for each target->super...
                                     */
                                r = Q_RET_IGNORED;          /* keep looping */
                                do {
                                                       /* exit t unhandled? */
                                    if (QEP_TRIG_(t, Q_EXIT_SIG)
                                        == Q_RET_HANDLED)
                                    {
                                        QS_BEGIN_(QS_QEP_STATE_EXIT,
                                                  QS_smObj_, me)
                                            QS_OBJ_(me);
                                            QS_FUN_(t);
                                        QS_END_()

                                        (void)QEP_TRIG_(t, QEP_EMPTY_SIG_);
                                    }
                                    t = me->state;    /*  set to super of t */
                                    iq = ip;
                                    do {
                                        if (t == path[iq]) {/* is this LCA? */
                                                        /* do not enter LCA */
                                            ip = (int8_t)(iq - 1);
                                            iq = (int8_t)(-1);/*break inner */
                                            r = Q_RET_HANDLED;/*break outer */
                                        }
                                        else {
                                            --iq;
                                        }
                                    } while (iq >= (int8_t)0);
                                } while (r != Q_RET_HANDLED);
                            }
                        }
                    }
                }
            }
        }
                    /* retrace the entry path in reverse (desired) order... */
        for (; ip >= (int8_t)0; --ip) {
            QEP_ENTER_(path[ip])                          /* enter path[ip] */
        }
        t = path[0];                      /* stick the target into register */
        me->state = t;                          /* update the current state */

                                      /* drill into the target hierarchy... */
        while (QEP_TRIG_(t, Q_INIT_SIG) == Q_RET_TRAN) {

            QS_BEGIN_(QS_QEP_STATE_INIT, QS_smObj_, me)
                QS_OBJ_(me);                   /* this state machine object */
                QS_FUN_(t);                     /* the source (pseudo)state */
                QS_FUN_(me->state);         /* the target of the transition */
            QS_END_()

            ip = (int8_t)0;
            path[0] = me->state;
            (void)QEP_TRIG_(me->state, QEP_EMPTY_SIG_);  /* find superstate */
            while (me->state != t) {
                ++ip;
                path[ip] = me->state;
                (void)QEP_TRIG_(me->state, QEP_EMPTY_SIG_);/*find superstate*/
            }
            me->state = path[0];
                                            /* entry path must not overflow */
            Q_ASSERT(ip < (int8_t)QEP_MAX_NEST_DEPTH_);

            do {    /* retrace the entry path in reverse (correct) order... */
                QEP_ENTER_(path[ip])                      /* enter path[ip] */
                --ip;
            } while (ip >= (int8_t)0);

            t = path[0];
        }

        QS_BEGIN_(QS_QEP_TRAN, QS_smObj_, me)
            QS_TIME_();                                       /* time stamp */
            QS_SIG_(e->sig);                     /* the signal of the event */
            QS_OBJ_(me);                       /* this state machine object */
            QS_FUN_(src);                   /* the source of the transition */
            QS_FUN_(t);                             /* the new active state */
        QS_END_()

    }
示例#12
0
/*..........................................................................*/
void QHsm_dispatch(QHsm *me, QEvent const *e) {
    QHsmState s;
    QHsmState t = ((QFsm *)me)->state__.hsm;
    QHsmState path[QEP_MAX_NEST_DEPTH_];

    path[2] = t;    /* save the current state in case a transition is taken */

    do {                             /* process the event hierarchically... */
        s = t;
        t = (QHsmState)((*s)(me, e));             /* invoke state handler s */
    } while (t != (QHsmState)0);

    if (((QFsm *)me)->tran__ != Q_TRAN_NONE_TYPE) {    /* transition taken? */
        struct QTran_ *stran;
        if ((((QFsm *)me)->tran__ & Q_TRAN_STA_TYPE) != 0) {/* static tran? */
            stran = ((QFsm *)me)->state__.tran;
        }
        else {
            path[0] = ((QFsm *)me)->state__.hsm;      /* save the new state */
            stran = (struct QTran_ *)0;
        }
        ((QFsm *)me)->state__.hsm = path[2];       /* restore current state */
        path[1] = s;                          /* save the transition source */

        /* exit current state to the transition source path[1]... */
        for (s = path[2]; s != path[1]; ) {
            t = QEP_TRIG_(s, Q_EXIT_SIG);
            if (t != (QHsmState)0) {               /* exit action unhandled */
                s = t;                            /* t points to superstate */
            }
            else {                                   /* exit action handled */

                QS_BEGIN_(QS_QEP_STATE_EXIT, QS_smObj_, me);
                QS_OBJ_(me);               /* this state machine object */
                QS_FUN_(s);                         /* the exited state */
                QS_END_();

                s = QEP_TRIG_(s, QEP_EMPTY_SIG_);/* find out the superstate */
            }
        }

        if (stran != (struct QTran_ *)0) {            /* static transition? */
            uint16_t a = (uint16_t)stran->actions[0];
            if (a != (uint16_t)0) {              /* transition initialized? */
                QHsmState const *c = stran->chain;
                for (a = (uint16_t)((uint16_t)(a | (stran->actions[1] << 8))
                                    >> 1);
                        a != (uint16_t)0;
                        a >>= 2)
                {
                    uint8_t sig = (uint8_t)(a & 0x3);
                    (void)(*(*c))(me, &QEP_reservedEvt_[sig]);

                    QS_BEGIN_(sig + (uint8_t)QS_QEP_STATE_EMPTY,
                              QS_smObj_, me);
                    QS_OBJ_(me);           /* this state machine object */
                    QS_FUN_(*c);    /* entered/exited/initialized state */
                    if (sig == (QSignal)Q_INIT_SIG) {
                        QS_FUN_(((QFsm *)me)->state__.hsm);   /* target */
                    }
                    QS_END_();

                    ++c;      /* advance in the chain of the stored actions */
                }
                ((QFsm *)me)->state__.hsm = *c;        /* set the new state */
            }
            else {      /* the static transition object not initialized yet */
示例#13
0
文件: qep_msm.c 项目: KnightSch/qpc
/**
* @description
* Dispatches an event for processing to a meta state machine (MSM).
* The processing of an event represents one run-to-completion (RTC) step.
*
* @param[in,out] me pointer (see @ref oop)
* @param[in]     e  pointer to the event to be dispatched to the MSM
*
* @note
* This function should be called only via the virtual table (see
* QMSM_DISPATCH()) and should NOT be called directly in the applications.
*/
void QMsm_dispatch_(QMsm * const me, QEvt const * const e) {
    QMState const *s = me->state.obj; /* store the current state */
    QMState const *t = s;
    QState r = (QState)Q_RET_SUPER;
    QS_CRIT_STAT_

    /** @pre current state must be initialized */
    Q_REQUIRE_ID(300, s != (QMState const *)0);

    QS_BEGIN_(QS_QEP_DISPATCH, QS_priv_.smObjFilter, me)
        QS_TIME_();               /* time stamp */
        QS_SIG_(e->sig);          /* the signal of the event */
        QS_OBJ_(me);              /* this state machine object */
        QS_FUN_(s->stateHandler); /* the current state handler */
    QS_END_()

    /* scan the state hierarchy up to the top state... */
    do {
        r = (*t->stateHandler)(me, e);  /* call state handler function */

        /* event handled? (the most frequent case) */
        if (r >= (QState)Q_RET_HANDLED) {
            break; /* done scanning the state hierarchy */
        }
        /* event unhandled and passed to the superstate? */
        else if (r == (QState)Q_RET_SUPER) {
            t = t->superstate; /* advance to the superstate */
        }
        /* event unhandled and passed to a submachine superstate? */
        else if (r == (QState)Q_RET_SUPER_SUB) {
            t = me->temp.obj; /* current host state of the submachie */
        }
        /* event unhandled due to a guard? */
        else if (r == (QState)Q_RET_UNHANDLED) {

            QS_BEGIN_(QS_QEP_UNHANDLED, QS_priv_.smObjFilter, me)
                QS_SIG_(e->sig);  /* the signal of the event */
                QS_OBJ_(me);      /* this state machine object */
                QS_FUN_(t->stateHandler); /* the current state */
            QS_END_()

            t = t->superstate; /* advance to the superstate */
        }
        else {
            /* no other return value should be produced */
            Q_ERROR_ID(310);
        }
    } while (t != (QMState const *)0);


    /* any kind of transition taken? */
    if (r >= (QState)Q_RET_TRAN) {
#ifdef Q_SPY
        QMState const *ts = t; /* transition source for QS tracing */

        /* the transition source state must not be NULL */
        Q_ASSERT_ID(320, ts != (QMState const *)0);
#endif /* Q_SPY*/

        do {
            /* save the transition-action table before it gets clobbered */
            QMTranActTable const *tatbl = me->temp.tatbl;

            /* was a regular state transition segment taken? */
            if (r == (QState)Q_RET_TRAN) {
                QMsm_exitToTranSource_(me, s, t);
                r = QMsm_execTatbl_(me, tatbl);
            }
            /* was an initial transition segment taken? */
            else if (r == (QState)Q_RET_TRAN_INIT) {
                r = QMsm_execTatbl_(me, tatbl);
            }
            /* was a transition segment to history taken? */
            else if (r == (QState)Q_RET_TRAN_HIST) {
                QMState const *hist = me->state.obj; /* save history */
                me->state.obj = s; /* restore the original state */
                QMsm_exitToTranSource_(me, s, t);
                (void)QMsm_execTatbl_(me, tatbl);
                r = QMsm_enterHistory_(me, hist);
            }
            /* was a transition segment to an entry point taken? */
            else if (r == (QState)Q_RET_TRAN_EP) {
                r = QMsm_execTatbl_(me, tatbl);
            }
            /* was a transition segment to an exit point taken? */
            else if (r == (QState)Q_RET_TRAN_XP) {
                QActionHandler const act = me->state.act; /* save XP action */
                me->state.obj = s; /* restore the original state */

                r = (*act)(me); /* execute the XP action */
                if (r == (QState)Q_RET_TRAN) {
                    QMsm_exitToTranSource_(me, s, t);
                    /* take the tran-to-XP segment inside submachine */
                    (void)QMsm_execTatbl_(me, tatbl);
                    me->state.obj = s; /* restore original state (history) */
#ifdef Q_SPY
                    t = me->temp.tatbl->target; /* store for tracing */
#endif /* Q_SPY */
                    /* take the XP-Segment from submachine-state */
                    r = QMsm_execTatbl_(me, me->temp.tatbl);

                    QS_BEGIN_(QS_QEP_TRAN_XP, QS_priv_.smObjFilter, me)
                        QS_OBJ_(me); /* this state machine object */
                        QS_FUN_(s);  /* source handler */
                        QS_FUN_(t);  /* target handler */
                    QS_END_()
                }
            }
示例#14
0
/*..........................................................................*/
void QHsm_execTran(QHsm *me, QHsmState path[], struct QTran_ *tran) {
    QHsmState s;
    QHsmState t = path[0];                      /* target of the transition */
    QHsmState const src = path[1];              /* source of the transition */
    uint16_t actions = (uint16_t)0;     /* actions bitmask for static tran. */
    uint8_t ic = (uint8_t)0;               /* static-transition chain index */
    int8_t ip = (int8_t)(-1);                /* transition entry path index */
    int8_t iq;                        /* helper transition entry path index */

    if (src == t) {      /* (a) check source == target (transition to self) */
        QEP_EXIT_AND_REC_(src);                          /* exit the source */
        ++ip;                                           /* enter the target */
    }
    else {
        t = QEP_TRIG_(t, QEP_EMPTY_SIG_);/* put superstate of target into t */
        if (src == t) {                /* (b) check source == target->super */
            ++ip;                                       /* enter the target */
        }
        else {
            s = QEP_TRIG_(src, QEP_EMPTY_SIG_);/*superstate of source into s*/
            if (s == t) {       /* (c) check source->super == target->super */
                QEP_EXIT_AND_REC_(src);                  /* exit the source */
                ++ip;                                   /* enter the target */
            }
            else {
                if (s == path[0]) {    /* (d) check source->super == target */
                    QEP_EXIT_AND_REC_(src);              /* exit the source */
                }
                else { /* (e) check rest of source == target->super->super...
                        * and store the entry path along the way
                        */
                    iq = (int8_t)0;          /* indicate that LCA not found */

                    ++ip;                               /* enter the target */
                    path[++ip] = t;       /* enter the superstate of target */
                    t = QEP_TRIG_(t, QEP_EMPTY_SIG_);
                    while (t != (QHsmState)0) {
                        path[++ip] = t;             /* store the entry path */
                        if (t == src) {                /* is it the source? */
                            iq = (int8_t)1;  /* indicate that the LCA found */
                                            /* entry path must not overflow */
                            Q_ASSERT(ip < (int8_t)QEP_MAX_NEST_DEPTH_);
                            --ip;                /* do not enter the source */
                            t = (QHsmState)0;         /* terminate the loop */
                        }
                        else {       /* it is not the source, keep going up */
                            t = QEP_TRIG_(t, QEP_EMPTY_SIG_);
                        }
                    }
                    if (iq == (int8_t)0) {        /* the LCA not found yet? */

                                            /* entry path must not overflow */
                        Q_ASSERT(ip < (int8_t)QEP_MAX_NEST_DEPTH_);

                        QEP_EXIT_AND_REC_(src);              /* exit source */

                            /* (f) check the rest of source->super
                             *                      == target->super->super...
                             */
                        iq = ip;
                        do {
                            if (s == path[iq]) {        /* is this the LCA? */
                                t = s;    /* indicate that the LCA is found */
                                ip = (int8_t)(iq - 1);  /* do not enter LCA */
                                iq = (int8_t)(-1);    /* terminate the loop */
                            }
                            else {
                                --iq;     /* try lower superstate of target */
                            }
                        } while (iq >= (int8_t)0);

                        if (t == (QHsmState)0) {  /* the LCA not found yet? */
                                /* (g) check each source->super->...
                                 * for each target->super...
                                 */
                            do {
                                t = QEP_TRIG_(s, Q_EXIT_SIG);     /* exit s */
                                if (t != (QHsmState)0) {  /* exit unhandled */
                                    s = t;   /* t points to superstate of s */
                                }
                                else {               /* exit action handled */

                                    QS_BEGIN_(QS_QEP_STATE_EXIT,
                                              QS_smObj_, me);
                                        QS_OBJ_(me);
                                        QS_FUN_(s);
                                    QS_END_();

                                    if (tran != (struct QTran_ *)0) {
                                        QEP_REC_(s, Q_EXIT_SIG);
                                    }
                                    s = QEP_TRIG_(s, QEP_EMPTY_SIG_);
                                }
                                iq = ip;
                                do {
                                    if (s == path[iq]) {/* is this the LCA? */
                                                    /* do not enter the LCA */
                                        ip = (int8_t)(iq - 1);
                                        iq = (int8_t)(-1);/*break inner loop*/
                                        s = (QHsmState)0; /* and outer loop */
                                    }
                                    else {
                                        --iq;
                                    }
                                } while (iq >= (int8_t)0);
                            } while (s != (QHsmState)0);
                        }
                    }
                }
            }
        }
    }
                    /* retrace the entry path in reverse (desired) order... */
    for (; ip >= (int8_t)0; --ip) {
        QEP_ENTER_AND_REC_(path[ip]);                     /* enter path[ip] */
    }
    s = path[0];                          /* stick the target into register */
    ((QFsm *)me)->state__.hsm = s;              /* update the current state */

    while (QEP_TRIG_(s, Q_INIT_SIG) == (QHsmState)0) { /* drill into target */

        t = ((QFsm *)me)->state__.hsm;

        QS_BEGIN_(QS_QEP_STATE_INIT, QS_smObj_, me);
            QS_OBJ_(me);                       /* this state machine object */
            QS_FUN_(s);                         /* the source (pseudo)state */
            QS_FUN_(t);                     /* the target of the transition */
        QS_END_();

        if (tran != (struct QTran_ *)0) {             /* static tranistion? */
            QEP_REC_(s, Q_INIT_SIG);
        }
                                               /* store the entry path to s */
        path[0] = t;
        ip = (int8_t)0;
        for (t = QEP_TRIG_(t, QEP_EMPTY_SIG_); t != s;
             t = QEP_TRIG_(t, QEP_EMPTY_SIG_))
        {
            path[++ip] = t;
        }
                                            /* entry path must not overflow */
        Q_ASSERT(ip < (int8_t)QEP_MAX_NEST_DEPTH_);

        do {        /* retrace the entry path in reverse (correct) order... */
            QEP_ENTER_AND_REC_(path[ip]);                 /* enter path[ip] */
            --ip;
        } while (ip >= (int8_t)0);
        s = ((QFsm *)me)->state__.hsm;
    }

    if (tran != (struct QTran_ *)0) {                 /* static transition? */
                                      /* transition chain must not overflow */
        Q_ENSURE(ic < (uint8_t)Q_DIM(tran->chain));

        tran->chain[ic] = s; /* store the ultimate target of the transition */
        actions = (uint16_t)(actions >> (15 - (ic << 1)));
        tran->actions[1] = (uint8_t)(actions >> 8);
        tran->actions[0] = (uint8_t)(actions | 0x1);
    }