Exemplo n.º 1
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_()
}
Exemplo n.º 2
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 {
Exemplo n.º 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
            }
        }
Exemplo n.º 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_();
}
Exemplo n.º 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 */
}
Exemplo n.º 6
0
/*..........................................................................*/
QEvt *QF_newX_(uint_t const evtSize,
               uint_t const margin, enum_t const sig)
{
    QEvt *e;
    uint_t idx;
    QS_CRIT_STAT_

              /* find the pool index that fits the requested event size ... */
    for (idx = (uint_t)0; idx < QF_maxPool_; ++idx) {
        if (evtSize <= QF_EPOOL_EVENT_SIZE_(QF_pool_[idx])) {
            break;
        }
    }
    Q_ASSERT(idx < QF_maxPool_);      /* cannot run out of registered pools */

    QS_BEGIN_(QS_QF_NEW, (void *)0, (void *)0)
        QS_TIME_();                                            /* timestamp */
        QS_EVS_((QEvtSize)evtSize);                /* the size of the event */
        QS_SIG_((QSignal)sig);                   /* the signal of the event */
    QS_END_()

    QF_EPOOL_GET_(QF_pool_[idx], e, margin); /* get e -- platform-dependent */

    if (e != (QEvt *)0) {                     /* was e allocated correctly? */
        e->sig = (QSignal)sig;                 /* set signal for this event */
        e->poolId_ = (uint8_t)(idx + (uint_t)1);       /* store the pool ID */
        e->refCtr_ = (uint8_t)0;          /* set the reference counter to 0 */
    }
    else {                                     /* event cannot be allocated */
        Q_ASSERT(margin != (uint_t)0);     /* must tollerate bad allocation */
    }
    return e;         /* can't be NULL if we can't tollerate bad allocation */
}
Exemplo n.º 7
0
//............................................................................
QEvent *QF::new_(uint16_t evtSize, QSignal sig) {
                    // find the pool id that fits the requested event size ...
    uint8_t id = (uint8_t)0;
    while (evtSize > QF_EPOOL_EVENT_SIZE_(QF_pool_[id])) {
        ++id;
        Q_ASSERT(id < QF_maxPool_);      // cannot run out of registered pools
    }

    QS_INT_LOCK_KEY_
    QS_BEGIN_(QS_QF_NEW, (void *)0, (void *)0)
        QS_TIME_();                                               // timestamp
        QS_EVS_(evtSize);                             // the size of the event
        QS_SIG_(sig);                               // the signal of the event
    QS_END_()

    QEvent *e;
    QF_EPOOL_GET_(QF_pool_[id], e);
    Q_ASSERT(e != (QEvent *)0);             // pool must not run out of events

    e->sig = sig;                                 // set signal for this event

                                 // store the dynamic attributes of the event:
                                 // the pool ID and the reference counter == 0
    e->dynamic_ = (uint8_t)((id + 1) << 6);
    return e;
}
Exemplo n.º 8
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_()
}
Exemplo n.º 9
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_();
}
Exemplo n.º 10
0
/*..........................................................................*/
void QMPool_init(QMPool * const me, void * const poolSto,
                 uint32_t poolSize, QMPoolSize blockSize)
{
    QFreeBlock *fb;
    uint32_t nblocks;
    QS_CRIT_STAT_

    /* The memory block must be valid
    * and the poolSize must fit at least one free block
    * and the blockSize must not be too close to the top of the dynamic range
    */
    Q_REQUIRE((poolSto != (void *)0)
              && (poolSize >= (uint32_t)sizeof(QFreeBlock))
              && ((QMPoolSize)(blockSize + (QMPoolSize)sizeof(QFreeBlock))
                    > blockSize));

    me->free_head = poolSto;

     /* round up the blockSize to fit an integer # free blocks, no division */
    me->blockSize = (QMPoolSize)sizeof(QFreeBlock);  /* start with just one */
    nblocks = (uint32_t)1;    /* # free blocks that fit in one memory block */
    while (me->blockSize < blockSize) {
        me->blockSize += (QMPoolSize)sizeof(QFreeBlock);
        ++nblocks;
    }
    blockSize = me->blockSize;      /* use the rounded-up value from now on */

                  /* the pool buffer must fit at least one rounded-up block */
    Q_ASSERT(poolSize >= (uint32_t)blockSize);

                             /* chain all blocks together in a free-list... */
    poolSize -= (uint32_t)blockSize;          /* don't count the last block */
    me->nTot  = (QMPoolCtr)1;         /* the last block already in the pool */
    fb = (QFreeBlock *)me->free_head; /* start at the head of the free list */
    while (poolSize >= (uint32_t)blockSize) {
        fb->next = &QF_PTR_AT_(fb, nblocks);/*point next link to next block */
        fb = fb->next;                         /* advance to the next block */
        poolSize -= (uint32_t)blockSize;  /* reduce the available pool size */
        ++me->nTot;                /* increment the number of blocks so far */
    }

    fb->next  = (QFreeBlock *)0;            /* the last link points to NULL */
    me->nFree = me->nTot;                            /* all blocks are free */
    me->nMin  = me->nTot;              /* the minimum number of free blocks */
    me->start = poolSto;             /* the original start this pool buffer */
    me->end   = fb;                          /* the last block in this pool */

    QS_BEGIN_(QS_QF_MPOOL_INIT, QS_priv_.mpObjFilter, me->start)
        QS_OBJ_(me->start);              /* the memory managed by this pool */
        QS_MPC_(me->nTot);                    /* the total number of blocks */
    QS_END_()
}
Exemplo n.º 11
0
/**
* @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_()
}
/*..........................................................................*/
void QEQueue_init(QEQueue * const me, QEvt const *qSto[],
                  QEQueueCtr const qLen)
{
    QS_CRIT_STAT_

    me->frontEvt = (QEvt const *)0;             /* no events in the queue */
    me->ring     = &qSto[0];            /* the beginning of the ring buffer */
    me->end      = qLen;
    me->head     = (QEQueueCtr)0;
    me->tail     = (QEQueueCtr)0;
    me->nFree    = qLen;
    me->nMin     = qLen;

    QS_BEGIN_(QS_QF_EQUEUE_INIT, QS_eqObj_, me)
        QS_OBJ_(qSto);                               /* this QEQueue object */
        QS_EQC_(qLen);                           /* the length of the queue */
    QS_END_()
}
Exemplo n.º 13
0
/*..........................................................................*/
QEvent const *QActive_get_(QActive *me) {
    INT8U err;
    QEvent const *e = (QEvent *)OSQPend((OS_EVENT *)me->eQueue, 0, &err);
    QS_INT_LOCK_KEY_

    Q_ASSERT(err == OS_NO_ERR);

    QS_BEGIN_(QS_QF_ACTIVE_GET, QS_aoObj_, me)
        QS_TIME_();                                            /* timestamp */
        QS_SIG_(e->sig);                        /* the signal of this event */
        QS_OBJ_(me);                                  /* this active object */
        QS_U8_(EVT_POOL_ID(e));                 /* the pool Id of the event */
        QS_U8_(EVT_REF_CTR(e));               /* the ref count of the event */
        QS_EQC_(0);                     /* number of free entries (unknown) */
    QS_END_()

    return e;
}
Exemplo n.º 14
0
//****************************************************************************
/// @description
/// Allocates an event dynamically from one of the QF event pools.
///
/// @param[in] evtSize the size (in bytes) of the event to allocate
/// @param[in] margin  the number of un-allocated events still available
///                    in a given event pool after the allocation completes
/// @param[in] sig     the signal to be assigned to the allocated event
///
/// @returns pointer to the newly allocated event. This pointer can be NULL
/// only if margin!=0 and the event cannot be allocated with the specified
/// margin still available in the given pool.
///
/// @note The internal QF function QP::QF::newX_() raises an assertion when
/// the margin argument is 0 and allocation of the event turns out to be
/// impossible due to event pool depletion, or incorrect (too big) size
/// of the requested event.
///
/// @note The application code should not call this function directly.
/// The only allowed use is thorough the macros Q_NEW() or Q_NEW_X().
///
QEvt *QF::newX_(uint_fast16_t const evtSize,
                uint_fast16_t const margin, enum_t const sig)
{
    uint_fast8_t idx;

    // find the pool id that fits the requested event size ...
    for (idx = static_cast<uint_fast8_t>(0); idx < QF_maxPool_; ++idx) {
        if (evtSize <= QF_EPOOL_EVENT_SIZE_(QF_pool_[idx])) {
            break;
        }
    }
    // cannot run out of registered pools
    Q_ASSERT_ID(310, idx < QF_maxPool_);

    QS_CRIT_STAT_
    QS_BEGIN_(QS_QF_NEW, static_cast<void *>(0), static_cast<void *>(0))
        QS_TIME_();                              // timestamp
        QS_EVS_(static_cast<QEvtSize>(evtSize)); // the size of the event
        QS_SIG_(static_cast<QSignal>(sig));      // the signal of the event
    QS_END_()

    QEvt *e;
    QF_EPOOL_GET_(QF_pool_[idx], e, margin); // get e -- platform-dependent

    // was e allocated correctly?
    if (e != static_cast<QEvt const *>(0)) {
        e->sig     = static_cast<QSignal>(sig); // set the signal
        // store pool ID
        e->poolId_ = static_cast<uint8_t>(
                       idx + static_cast<uint_fast8_t>(1));
        // initialize the reference counter to 0
        e->refCtr_ = static_cast<uint8_t>(0);
    }
    else {
        // event was not allocated, assert that the caller provided non-zero
        // margin, which means that they can tollerate bad allocation
        Q_ASSERT_ID(320, margin != static_cast<uint_fast16_t>(0));
    }
    return e;
}
Exemplo n.º 15
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_()

    }
Exemplo n.º 16
0
/**
* @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_()
                }
            }
Exemplo n.º 17
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 */
Exemplo n.º 18
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_()

        }
Exemplo n.º 19
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);
    }