QP is an event-driven, RTOS-like, active object framework for microcontrollers, such as mbed. The QP framework provides thread-safe execution of active objects (concurrent state machines) and support both manual and automatic coding of UML statecharts in readable, production-quality C or C++. Automatic code generation of QP code is supported by the free QM modeling tool.

Dependents:   qp_hangman qp_dpp qp_blinky

QP/C++ (Quantum Platform in C++) is a lightweight, open source active object (actor) framework for building responsive and modular real-time embedded applications as systems of asynchronous event-driven active objects (actors). The QP/C++ framework is a member of a larger family consisting of QP/C++, QP/C, and QP-nano frameworks, which are all strictly quality controlled, thoroughly documented, and available under GPLv3 with a special Exception for mbed (see http://www.state-machine.com/licensing/QP-mbed_GPL_Exception.txt).

The behavior of active objects is specified in QP/C++ by means of hierarchical state machines (UML statecharts). The framework supports manual coding of UML state machines in C++ as well as automatic code generation by means of the free QM modeling tool (http://www.state-machine.com/qm).

Please see the "QP/C++ Reference Manual" (http://www.state-machine.com/qpcpp) for more information.

Files at this revision

API Documentation at this revision

Comitter:
QL
Date:
Tue Sep 04 22:20:52 2012 +0000
Parent:
8:934bb9eea80b
Commit message:
QP/C++ 4.5.02 compatible with QM 2.2.xx

Changed in this revision

qk_port.s Show annotated file Show diff for this revision Revisions of this file
qp.cpp Show annotated file Show diff for this revision Revisions of this file
qp.h Show annotated file Show diff for this revision Revisions of this file
qp_port.cpp Show diff for this revision Revisions of this file
qp_port.h Show annotated file Show diff for this revision Revisions of this file
--- a/qk_port.s	Mon Sep 26 03:27:09 2011 +0000
+++ b/qk_port.s	Tue Sep 04 22:20:52 2012 +0000
@@ -1,130 +1,135 @@
-;*****************************************************************************
-; Product: QK port to ARM Cortex-M0/M3, mbed ARM assembler, CMSIS-compliant
-; Last Updated for Version: 4.2.04
-; Date of the Last Update:  Sep 23, 2011
-;
-;                    Q u a n t u m     L e a P s
-;                    ---------------------------
-;                    innovating embedded systems
-;
-; Copyright (C) 2002-2011 Quantum Leaps, LLC. All rights reserved.
-;
-; This software may be distributed and modified under the terms of the GNU
-; General Public License version 2 (GPL) as published by the Free Software
-; Foundation and appearing in the file GPL.TXT included in the packaging of
-; this file. Please note that GPL Section 2[b] requires that all works based
-; on this software must also be made publicly available under the terms of
-; the GPL ("Copyleft").
-;
-; Alternatively, this software may be distributed and modified under the
-; terms of Quantum Leaps commercial licenses, which expressly supersede
-; the GPL and are specifically designed for licensees interested in
-; retaining the proprietary status of their code.
-;
-; Contact information:
-; Quantum Leaps Web site:  http://www.quantum-leaps.com
-; e-mail:                  info@quantum-leaps.com
-;*****************************************************************************
-    AREA QK, CODE, READONLY
-
-    EXPORT  QK_init
-    EXPORT  PendSV_Handler    ; CMSIS-compliant PendSV exception name
-    EXPORT  SVC_Handler       ; CMSIS-compliant SVC exception name
-
-    EXTERN  QK_schedule_      ; external references
-    EXTERN  QK_readySet_      ; external references
-
-
-;*****************************************************************************
-;
-; The QK_init function sets the priorities of PendSV and SVCall exceptions
-; to 0xFF and 0x00, respectively. The function internally disables
-; interrupts, but restores the original interrupt lock before exit.
-;
-;*****************************************************************************
-QK_init
-    MRS     r0,PRIMASK        ; store the state of the PRIMASK in r0
-    CPSID   i                 ; disable interrupts (set PRIMASK)
-
-    LDR     r1,=0xE000ED18    ; System Handler Priority Register
-    LDR     r2,[r1,#8]        ; load the System 12-15 Priority Register
-    MOVS    r3,#0xFF
-    LSLS    r3,r3,#16
-    ORRS    r2,r3             ; set PRI_14 (PendSV) to 0xFF
-    STR     r2,[r1,#8]        ; write the System 12-15 Priority Register
-    LDR     r2,[r1,#4]        ; load the System 8-11 Priority Register
-    LSLS    r3,r3,#8
-    BICS    r2,r3             ; set PRI_11 (SVCall) to 0x00
-    STR     r2,[r1,#4]        ; write the System 8-11 Priority Register
-
-    MSR     PRIMASK,r0        ; restore the original PRIMASK
-    BX      lr                ; return to the caller
-
-
-;*****************************************************************************
-;
-; The PendSV_Handler exception hanlder is used for handling asynchronous
-; preemptions in QK. The use of the PendSV exception is the recommended
-; and most efficient method for performing context switches with ARM Cortex.
-;
-; The PendSV exception should have the lowest priority in the whole system
-; (0xFF, see QK_init). All other exeptions and interrupts should have higher
-; priority. For example, for NVIC with 2 priority bits all interrupts and
-; exceptions must have numerical value of priority lower than 0xC0. In this
-; case the interrupt priority levels available to your applications are (in
-; the order from the lowest urgency to the highest urgency): 0x80, 0x40, 0x00.
-;
-; Also, *all* ISRs in the QK application must trigger the PendSV exception
-; by calling the QK_ISR_EXIT() macro.
-;
-; Due to tail-chaining and its lowest priority, the PendSV exception will be
-; entered immediately after the exit from the *last* nested interrupt (or
-; exception). In QK, this is exactly the time when the QK scheduler needs to
-; check for the asynchronous preemptions.
-;
-;*****************************************************************************
-PendSV_Handler
-    CPSID   i                 ; disable interrupts at processor level
-    LDR     r0,=0xE000ED04    ; load the NVIC-ICSR register address
-    MOVS    r1,#0x01
-    LSLS    r1,r1,#27         ; make up a mask with only the PENDSVCLR bit set
-    STR     r1,[r0]           ; remove the pending status of PendSV
-    LDR     r0,=QK_readySet_  ; load the address of QK_readySet_
-    LDRB    r0,[r0]           ; load the first byte of QK_readySet_
-    CMP     r0,#0             ; is QK_readySet_ == 0 ?
-    BEQ.N   iret              ; if QK_readySet_ == 0, branch to iret
-
-                              ; at this point r1 contains (1 << 27)
-    LSRS    r1,r1,#3          ; make up a task xPSR with only the T bit set
-    LDR     r0,=schedule      ; load the address of sched wrapper (new PC)
-    PUSH    {r0-r1}           ; push xPSR,PC
-    SUB     sp,sp,#(6*4)      ; don't care for lr,r12,r3,r2,r1,r0
-    BX      lr                ; interrupt return to the scheduler
-
-iret
-    CPSIE   i                 ; enable interrupts at processor level
-    BX      lr                ; interrupt return to the task
-
-schedule
-    BL      QK_schedule_      ; call the QK scheduler
-    CPSIE   i                 ; enable interrupts to allow SVCall exception
-    SVC     0                 ; SV exception returns to the preempted task
-
-
-;*****************************************************************************
-;
-; The SVC_Handler exception handler is used for returning back to the
-; interrupted context (task or interrupt). The SVC exception should have
-; the lowest priority in the whole system (see QK_init). The SVCall
-; exception simply removes its own interrupt stack frame from the stack and
-; returns to the preempted task using the interrupt stack frame that must be
-; at the top of the stack.
-;
-;*****************************************************************************
-SVC_Handler
-    ADD     sp,sp,#(8*4)      ; remove one interrupt frame from the stack
-    BX      lr                ; return to the preempted task
-
-    ALIGN                     ; make sure proper alignment
-    END
-    
\ No newline at end of file
+;*****************************************************************************
+; Product: QK port to ARM Cortex-M0/M3, mbed ARM assembler, CMSIS-compliant
+; Last Updated for Version: 4.5.02
+; Date of the Last Update:  Sep 04, 2012
+;
+;                    Q u a n t u m     L e a P s
+;                    ---------------------------
+;                    innovating embedded systems
+;
+; Copyright (C) 2002-2012 Quantum Leaps, LLC. All rights reserved.
+;
+; This program is open source software: you can redistribute it and/or
+; modify it under the terms of the GNU General Public License as published
+; by the Free Software Foundation, either version 2 of the License, or
+; (at your option) any later version.
+;
+; Alternatively, this program may be distributed and modified under the
+; terms of Quantum Leaps commercial licenses, which expressly supersede
+; the GNU General Public License and are specifically designed for
+; licensees interested in retaining the proprietary status of their code.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program. If not, see <http://www.gnu.org/licenses/>.
+;
+; Contact information:
+; Quantum Leaps Web sites: http://www.quantum-leaps.com
+;                          http://www.state-machine.com
+; e-mail:                  info@quantum-leaps.com
+;*****************************************************************************
+    AREA QK, CODE, READONLY
+    PRESERVE8
+
+    EXPORT  QK_init
+    EXPORT  PendSV_Handler    ; CMSIS-compliant PendSV exception name
+    EXPORT  SVC_Handler       ; CMSIS-compliant SVC exception name
+
+    EXTERN  QK_schedPrio_     ; external reference
+    EXTERN  QK_sched_         ; external reference
+
+
+;*****************************************************************************
+;
+; The QK_init function sets the priorities of PendSV and SVCall exceptions
+; to 0xFF and 0x00, respectively. The function internally disables
+; interrupts, but restores the original interrupt lock before exit.
+;
+;*****************************************************************************
+QK_init
+    MRS     r0,PRIMASK        ; store the state of the PRIMASK in r0
+    CPSID   i                 ; disable interrupts (set PRIMASK)
+
+    LDR     r1,=0xE000ED18    ; System Handler Priority Register
+    LDR     r2,[r1,#8]        ; load the System 12-15 Priority Register
+    MOVS    r3,#0xFF
+    LSLS    r3,r3,#16
+    ORRS    r2,r3             ; set PRI_14 (PendSV) to 0xFF
+    STR     r2,[r1,#8]        ; write the System 12-15 Priority Register
+    LDR     r2,[r1,#4]        ; load the System 8-11 Priority Register
+    LSLS    r3,r3,#8
+    BICS    r2,r3             ; set PRI_11 (SVCall) to 0x00
+    STR     r2,[r1,#4]        ; write the System 8-11 Priority Register
+
+    MSR     PRIMASK,r0        ; restore the original PRIMASK
+    BX      lr                ; return to the caller
+
+
+;*****************************************************************************
+;
+; The PendSV_Handler exception hanlder is used for handling asynchronous
+; preemptions in QK. The use of the PendSV exception is the recommended
+; and most efficient method for performing context switches with ARM Cortex.
+;
+; The PendSV exception should have the lowest priority in the whole system
+; (0xFF, see QK_init). All other exeptions and interrupts should have higher
+; priority. For example, for NVIC with 2 priority bits all interrupts and
+; exceptions must have numerical value of priority lower than 0xC0. In this
+; case the interrupt priority levels available to your applications are (in
+; the order from the lowest urgency to the highest urgency): 0x80, 0x40, 0x00.
+;
+; Also, *all* ISRs in the QK application must trigger the PendSV exception
+; by calling the QK_ISR_EXIT() macro.
+;
+; Due to tail-chaining and its lowest priority, the PendSV exception will be
+; entered immediately after the exit from the *last* nested interrupt (or
+; exception). In QK, this is exactly the time when the QK scheduler needs to
+; check for the asynchronous preemptions.
+;
+;*****************************************************************************
+PendSV_Handler
+    CPSID   i                 ; disable interrupts at processor level
+    BL      QK_schedPrio_     ; check if we have preemption
+    CMP     r0,#0             ; is prio == 0 ?
+    BNE.N   scheduler         ; if prio != 0, branch to scheduler
+
+    CPSIE   i                 ; enable interrupts at processor level
+    MOVS    r0,#0x6
+    MVNS    r0,r0             ; r0:=~0x6=0xFFFFFFF9
+    BX      r0                ; exception-return to the task
+
+scheduler
+    MOVS    r3,#1
+    LSLS    r3,r3,#24         ; r3:=(1 << 24), set the T bit  (new xpsr)
+    LDR     r2,=QK_sched_     ; address of the QK scheduler   (new pc)
+    LDR     r1,=svc_ret       ; return address after the call (new lr)
+    PUSH    {r1-r3}           ; push xpsr,pc,lr
+    SUB     sp,sp,#(4*4)      ; don't care for r12,r3,r2,r1
+    PUSH    {r0}              ; push the prio argument        (new r0)
+    MOVS    r0,#0x6
+    MVNS    r0,r0             ; r0:=~0x6=0xFFFFFFF9
+    BX      r0                ; exception-return to the scheduler
+
+svc_ret
+    CPSIE   i                 ; enable interrupts to allow SVCall exception
+    SVC     0                 ; SV exception returns to the preempted task
+
+
+;*****************************************************************************
+;
+; The SVC_Handler exception handler is used for returning back to the
+; interrupted task. The SVCall exception simply removes its own interrupt
+; stack frame from the stack and returns to the preempted task using the
+; interrupt stack frame that must be at the top of the stack.
+;
+;*****************************************************************************
+SVC_Handler
+    ADD     sp,sp,#(8*4)      ; remove one interrupt frame from the stack
+    BX      lr                ; return to the preempted task
+
+    ALIGN                     ; make sure the END is properly aligned
+    END
--- a/qp.cpp	Mon Sep 26 03:27:09 2011 +0000
+++ b/qp.cpp	Tue Sep 04 22:20:52 2012 +0000
@@ -1,2196 +1,2778 @@
-//////////////////////////////////////////////////////////////////////////////
-// Product: QP/C++, selectabel Vanilla/QK kernels
-// Last Updated for QP ver: 4.2.04 (modified to fit in one file)
-// Date of the Last Update: Sep 25, 2011
-//
-//                    Q u a n t u m     L e a P s
-//                    ---------------------------
-//                    innovating embedded systems
-//
-// Copyright (C) 2002-2011 Quantum Leaps, LLC. All rights reserved.
-//
-// This software may be distributed and modified under the terms of the GNU
-// General Public License version 2 (GPL) as published by the Free Software
-// Foundation and appearing in the file GPL.TXT included in the packaging of
-// this file. Please note that GPL Section 2[b] requires that all works based
-// on this software must also be made publicly available under the terms of
-// the GPL ("Copyleft").
-//
-// Alternatively, this software may be distributed and modified under the
-// terms of Quantum Leaps commercial licenses, which expressly supersede
-// the GPL and are specifically designed for licensees interested in
-// retaining the proprietary status of their code.
-//
-// Contact information:
-// Quantum Leaps Web site:  http://www.quantum-leaps.com
-// e-mail:                  info@quantum-leaps.com
-//////////////////////////////////////////////////////////////////////////////
-#include "qp_port.h"                                                // QP port
-
-#ifdef Q_USE_NAMESPACE
-namespace QP {
-#endif
-
-Q_DEFINE_THIS_MODULE(qp)
-
-// "qep_pkg.h" ===============================================================
-/// internal QEP constants
-enum QEPConst {
-    QEP_EMPTY_SIG_ = 0,                ///< empty signal for internal use only
-
-    /// maximum depth of state nesting (including the top level), must be >= 3
-    QEP_MAX_NEST_DEPTH_ = 6
-};
-
-/// helper macro to trigger internal event in an HSM
-#define QEP_TRIG_(state_, sig_) \
-    ((*(state_))(this, &QEP_reservedEvt_[sig_]))
-
-/// helper macro to trigger exit action in an HSM
-#define QEP_EXIT_(state_) \
-    if (QEP_TRIG_(state_, Q_EXIT_SIG) == Q_RET_HANDLED) { \
-        QS_BEGIN_(QS_QEP_STATE_EXIT, QS::smObj_, this) \
-            QS_OBJ_(this); \
-            QS_FUN_(state_); \
-        QS_END_() \
-    }
-
-/// helper macro to trigger entry action in an HSM
-#define QEP_ENTER_(state_) \
-    if (QEP_TRIG_(state_, Q_ENTRY_SIG) == Q_RET_HANDLED) { \
-        QS_BEGIN_(QS_QEP_STATE_ENTRY, QS::smObj_, this) \
-            QS_OBJ_(this); \
-            QS_FUN_(state_); \
-        QS_END_() \
-    }
-
-// "qep.cpp" =================================================================
-// Package-scope objects -----------------------------------------------------
-QEvent const QEP_reservedEvt_[] = {
-#ifdef Q_EVT_CTOR
-    (QSignal)QEP_EMPTY_SIG_,
-    (QSignal)Q_ENTRY_SIG,
-    (QSignal)Q_EXIT_SIG,
-    (QSignal)Q_INIT_SIG
-#else
-    {(QSignal)QEP_EMPTY_SIG_, (uint8_t)0, (uint8_t)0},
-    {(QSignal)Q_ENTRY_SIG,    (uint8_t)0, (uint8_t)0},
-    {(QSignal)Q_EXIT_SIG,     (uint8_t)0, (uint8_t)0},
-    {(QSignal)Q_INIT_SIG,     (uint8_t)0, (uint8_t)0}
-#endif
-};
-//............................................................................
-//lint -e970 -e971 -e778         ignore MISRA rules 13 and 14 in this function
-char const Q_ROM * Q_ROM_VAR QEP::getVersion(void) {
-    static char const Q_ROM Q_ROM_VAR version[] = {
-        (char)(((QP_VERSION >> 12U) & 0xFU) + (uint8_t)'0'),
-        '.',
-        (char)(((QP_VERSION >>  8U) & 0xFU) + (uint8_t)'0'),
-        '.',
-        (char)(((QP_VERSION >>  4U) & 0xFU) + (uint8_t)'0'),
-        (char)((QP_VERSION          & 0xFU) + (uint8_t)'0'),
-        '\0'
-    };
-    return version;
-}
-
-// "qhsm_top.cpp" ============================================================
-QState QHsm::top(QHsm *, QEvent const *) {
-    return Q_IGNORED();                    // the top state ignores all events
-}
-
-// "qhsm_ini.cpp" ============================================================
-QHsm::~QHsm() {
-}
-//............................................................................
-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_()
-}
-
-// "qhsm_dis.cpp" ============================================================
-void QHsm::dispatch(QEvent const *e) {
-    QStateHandler path[QEP_MAX_NEST_DEPTH_];
-    QStateHandler s;
-    QStateHandler t;
-    QState r;
-    QS_INT_LOCK_KEY_
-
-    t = m_state;                                     // save the current state
-
-    QS_BEGIN_(QS_QEP_DISPATCH, QS::smObj_, this)
-        QS_TIME_();                                              // time stamp
-        QS_SIG_(e->sig);                            // the signal of the event
-        QS_OBJ_(this);                            // this state machine object
-        QS_FUN_(t);                                       // the current state
-    QS_END_()
-
-    do {                                // process the event hierarchically...
-        s = m_state;
-        r = (*s)(this, 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] = m_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_, this)
-                    QS_OBJ_(this);                // this state machine object
-                    QS_FUN_(t);                            // the exited state
-                QS_END_()
-
-                (void)QEP_TRIG_(t, QEP_EMPTY_SIG_);    // find superstate of t
-            }
-            t = m_state;                       // m_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 = m_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 (m_state == t) {
-                    QEP_EXIT_(s)                            // exit the source
-                    ip = (int8_t)0;                        // enter the target
-                }
-                else {
-                                            // (d) check source->super==target
-                    if (m_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 = m_state;                     // save source->super
-                                                  // find target->super->super
-                        r = QEP_TRIG_(path[1], QEP_EMPTY_SIG_);
-                        while (r == Q_RET_SUPER) {
-                            ++ip;
-                            path[ip] = m_state;        // store the entry path
-                            if (m_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_(m_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_, this)
-                                            QS_OBJ_(this);
-                                            QS_FUN_(t);
-                                        QS_END_()
-
-                                        (void)QEP_TRIG_(t, QEP_EMPTY_SIG_);
-                                    }
-                                    t = m_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
-        m_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_, this)
-                QS_OBJ_(this);                    // this state machine object
-                QS_FUN_(t);                        // the source (pseudo)state
-                QS_FUN_(m_state);              // the target of the transition
-            QS_END_()
-
-            ip = (int8_t)0;
-            path[0] = m_state;
-            (void)QEP_TRIG_(m_state, QEP_EMPTY_SIG_);       // find superstate
-            while (m_state != t) {
-                ++ip;
-                path[ip] = m_state;
-                (void)QEP_TRIG_(m_state, QEP_EMPTY_SIG_);   // find superstate
-            }
-            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 (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_, this)
-            QS_TIME_();                                          // time stamp
-            QS_SIG_(e->sig);                        // the signal of the event
-            QS_OBJ_(this);                        // this state machine object
-            QS_FUN_(src);                      // the source of the transition
-            QS_FUN_(t);                                // the new active state
-        QS_END_()
-
-    }
-    else {                                             // transition not taken
-#ifdef Q_SPY
-        if (r == Q_RET_IGNORED) {                            // event ignored?
-
-            QS_BEGIN_(QS_QEP_IGNORED, QS::smObj_, this)
-                QS_TIME_();                                      // time stamp
-                QS_SIG_(e->sig);                    // the signal of the event
-                QS_OBJ_(this);                    // this state machine object
-                QS_FUN_(t);                               // the current state
-            QS_END_()
-
-        }
-        else {                                                // event handled
-
-            QS_BEGIN_(QS_QEP_INTERN_TRAN, QS::smObj_, this)
-                QS_TIME_();                                      // time stamp
-                QS_SIG_(e->sig);                    // the signal of the event
-                QS_OBJ_(this);                    // this state machine object
-                QS_FUN_(s);                // the state that handled the event
-            QS_END_()
-
-        }
-#endif
-    }
-    m_state = t;                 // set new state or restore the current state
-}
-
-// "qf_pkg.h" ================================================================
-                                    // QF-specific interrupt locking/unlocking
-#ifndef QF_INT_KEY_TYPE
-
-    /// \brief This is an internal macro for defining the interrupt lock key.
-    ///
-    /// The purpose of this macro is to enable writing the same code for the
-    /// case when interrupt key is defined and when it is not. If the macro
-    /// #QF_INT_KEY_TYPE is defined, this internal macro provides the
-    /// definition of the lock key variable. Otherwise this macro is empty.
-    /// \sa #QF_INT_KEY_TYPE
-    #define QF_INT_LOCK_KEY_
-
-    /// \brief This is an internal macro for locking interrupts.
-    ///
-    /// The purpose of this macro is to enable writing the same code for the
-    /// case when interrupt key is defined and when it is not. If the macro
-    /// #QF_INT_KEY_TYPE is defined, this internal macro invokes #QF_INT_LOCK
-    /// passing the key variable as the parameter. Otherwise #QF_INT_LOCK
-    /// is invoked with a dummy parameter.
-    /// \sa #QF_INT_LOCK, #QK_INT_LOCK
-    #define QF_INT_LOCK_()      QF_INT_LOCK(dummy)
-
-    /// \brief This is an internal macro for unlocking interrupts.
-    ///
-    /// The purpose of this macro is to enable writing the same code for the
-    /// case when interrupt key is defined and when it is not. If the macro
-    /// #QF_INT_KEY_TYPE is defined, this internal macro invokes
-    /// #QF_INT_UNLOCK passing the key variable as the parameter.
-    /// Otherwise #QF_INT_UNLOCK is invoked with a dummy parameter.
-    /// \sa #QF_INT_UNLOCK, #QK_INT_UNLOCK
-    #define QF_INT_UNLOCK_()    QF_INT_UNLOCK(dummy)
-#else
-    #define QF_INT_LOCK_KEY_    QF_INT_KEY_TYPE intLockKey_;
-    #define QF_INT_LOCK_()      QF_INT_LOCK(intLockKey_)
-    #define QF_INT_UNLOCK_()    QF_INT_UNLOCK(intLockKey_)
-#endif
-
-// package-scope objects -----------------------------------------------------
-extern QTimeEvt *QF_timeEvtListHead_;  ///< head of linked list of time events
-extern QF_EPOOL_TYPE_ QF_pool_[QF_MAX_EPOOL];        ///< allocate event pools
-extern uint8_t QF_maxPool_;                  ///< # of initialized event pools
-extern QSubscrList *QF_subscrList_;             ///< the subscriber list array
-extern QSignal QF_maxSignal_;                ///< the maximum published signal
-
-//............................................................................
-/// \brief Structure representing a free block in the Native QF Memory Pool
-/// \sa ::QMPool
-struct QFreeBlock {
-    QFreeBlock *m_next;
-};
-
-/// \brief access to the poolId of an event \a e_
-#define EVT_POOL_ID(e_)     ((e_)->poolId_)
-
-/// \brief access to the refCtr of an event \a e_
-#define EVT_REF_CTR(e_)     ((e_)->refCtr_)
-
-/// \brief increment the refCtr of an event \a e_
-#define EVT_INC_REF_CTR(e_) (++((QEvent *)(e_))->refCtr_)
-
-/// \brief decrement the refCtr of an event \a e_
-#define EVT_DEC_REF_CTR(e_) (--((QEvent *)(e_))->refCtr_)
-
-// "qa_defer.cpp" ============================================================
-//............................................................................
-void QActive::defer(QEQueue *eq, QEvent const *e) {
-    eq->postFIFO(e);
-}
-//............................................................................
-uint8_t QActive::recall(QEQueue *eq) {
-    QEvent const *e = eq->get();    // try to get an event from deferred queue
-    if (e != (QEvent *)0) {                                // event available?
-
-        postLIFO(e);      // post it to the front of the Active Object's queue
-
-        QF_INT_LOCK_KEY_
-        QF_INT_LOCK_();
-
-        if (EVT_POOL_ID(e) != (uint8_t)0) {          // is it a dynamic event?
-
-            // after posting to the AO's queue the event must be referenced
-            // at least twice: once in the deferred event queue (eq->get()
-            // did NOT decrement the reference counter) and once in the
-            // AO's event queue.
-            Q_ASSERT(EVT_REF_CTR(e) > (uint8_t)1);
-
-            // we need to decrement the reference counter once, to account
-            // for removing the event from the deferred event queue.
-            //
-            EVT_DEC_REF_CTR(e);             // decrement the reference counter
-        }
-
-        QF_INT_UNLOCK_();
-
-        return (uint8_t)1;                                   // event recalled
-    }
-    else {
-        return (uint8_t)0;                               // event not recalled
-    }
-}
-
-// "qa_fifo.cpp" =============================================================
-//............................................................................
-#ifndef Q_SPY
-void QActive::postFIFO(QEvent const *e) {
-#else
-void QActive::postFIFO(QEvent const *e, void const *sender) {
-#endif
-
-    QF_INT_LOCK_KEY_
-    QF_INT_LOCK_();
-
-    QS_BEGIN_NOLOCK_(QS_QF_ACTIVE_POST_FIFO, QS::aoObj_, this)
-        QS_TIME_();                                               // timestamp
-        QS_OBJ_(sender);                                  // the sender object
-        QS_SIG_(e->sig);                            // the signal of the event
-        QS_OBJ_(this);                                   // 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_(m_eQueue.m_nFree);                   // number of free entries
-        QS_EQC_(m_eQueue.m_nMin);                // min number of free entries
-    QS_END_NOLOCK_()
-
-    if (EVT_POOL_ID(e) != (uint8_t)0) {              // is it a dynamic event?
-        EVT_INC_REF_CTR(e);                 // increment the reference counter
-    }
-
-    if (m_eQueue.m_frontEvt == (QEvent *)0) {           // is the queue empty?
-        m_eQueue.m_frontEvt = e;                     // deliver event directly
-        QACTIVE_EQUEUE_SIGNAL_(this);                // signal the event queue
-    }
-    else {               // queue is not empty, leave event in the ring-buffer
-                                        // queue must accept all posted events
-        Q_ASSERT(m_eQueue.m_nFree != (QEQueueCtr)0);
-        m_eQueue.m_ring[m_eQueue.m_head] = e;//insert e into the buffer (FIFO)
-        if (m_eQueue.m_head == (QEQueueCtr)0) {      // need to wrap the head?
-            m_eQueue.m_head = m_eQueue.m_end;                   // wrap around
-        }
-        --m_eQueue.m_head;
-
-        --m_eQueue.m_nFree;                    // update number of free events
-        if (m_eQueue.m_nMin > m_eQueue.m_nFree) {
-            m_eQueue.m_nMin = m_eQueue.m_nFree;       // update minimum so far
-        }
-    }
-    QF_INT_UNLOCK_();
-}
-
-// "qa_get_.cpp" =============================================================
-QEvent const *QActive::get_(void) {
-    QF_INT_LOCK_KEY_
-    QF_INT_LOCK_();
-
-    QACTIVE_EQUEUE_WAIT_(this);           // wait for event to arrive directly
-
-    QEvent const *e = m_eQueue.m_frontEvt;
-
-    if (m_eQueue.m_nFree != m_eQueue.m_end) { //any events in the ring buffer?
-                                                 // remove event from the tail
-        m_eQueue.m_frontEvt = m_eQueue.m_ring[m_eQueue.m_tail];
-        if (m_eQueue.m_tail == (QEQueueCtr)0) {      // need to wrap the tail?
-            m_eQueue.m_tail = m_eQueue.m_end;                   // wrap around
-        }
-        --m_eQueue.m_tail;
-
-        ++m_eQueue.m_nFree;          // one more free event in the ring buffer
-
-        QS_BEGIN_NOLOCK_(QS_QF_ACTIVE_GET, QS::aoObj_, this)
-            QS_TIME_();                                           // timestamp
-            QS_SIG_(e->sig);                       // the signal of this event
-            QS_OBJ_(this);                               // 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_(m_eQueue.m_nFree);               // number of free entries
-        QS_END_NOLOCK_()
-    }
-    else {
-        m_eQueue.m_frontEvt = (QEvent *)0;          // the queue becomes empty
-        QACTIVE_EQUEUE_ONEMPTY_(this);
-
-        QS_BEGIN_NOLOCK_(QS_QF_ACTIVE_GET_LAST, QS::aoObj_, this)
-            QS_TIME_();                                           // timestamp
-            QS_SIG_(e->sig);                       // the signal of this event
-            QS_OBJ_(this);                               // 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_END_NOLOCK_()
-    }
-    QF_INT_UNLOCK_();
-    return e;
-}
-//............................................................................
-uint32_t QF::getQueueMargin(uint8_t prio) {
-    Q_REQUIRE((prio <= (uint8_t)QF_MAX_ACTIVE)
-              && (active_[prio] != (QActive *)0));
-
-    QF_INT_LOCK_KEY_
-    QF_INT_LOCK_();
-    uint32_t margin = (uint32_t)(active_[prio]->m_eQueue.m_nMin);
-    QF_INT_UNLOCK_();
-
-    return margin;
-}
-
-// "qa_lifo.cpp" =============================================================
-void QActive::postLIFO(QEvent const *e) {
-    QF_INT_LOCK_KEY_
-    QF_INT_LOCK_();
-
-    QS_BEGIN_NOLOCK_(QS_QF_ACTIVE_POST_LIFO, QS::aoObj_, this)
-        QS_TIME_();                                               // timestamp
-        QS_SIG_(e->sig);                           // the signal of this event
-        QS_OBJ_(this);                                   // 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_(m_eQueue.m_nFree);                   // number of free entries
-        QS_EQC_(m_eQueue.m_nMin);                // min number of free entries
-    QS_END_NOLOCK_()
-
-    if (EVT_POOL_ID(e) != (uint8_t)0) {              // is it a dynamic event?
-        EVT_INC_REF_CTR(e);                 // increment the reference counter
-    }
-
-    if (m_eQueue.m_frontEvt == (QEvent *)0) {           // is the queue empty?
-        m_eQueue.m_frontEvt = e;                     // deliver event directly
-        QACTIVE_EQUEUE_SIGNAL_(this);                // signal the event queue
-    }
-    else {               // queue is not empty, leave event in the ring-buffer
-                                        // queue must accept all posted events
-        Q_ASSERT(m_eQueue.m_nFree != (QEQueueCtr)0);
-
-        ++m_eQueue.m_tail;
-        if (m_eQueue.m_tail == m_eQueue.m_end) {     // need to wrap the tail?
-            m_eQueue.m_tail = (QEQueueCtr)0;                    // wrap around
-        }
-
-        m_eQueue.m_ring[m_eQueue.m_tail] = m_eQueue.m_frontEvt;
-        m_eQueue.m_frontEvt = e;                         // put event to front
-
-        --m_eQueue.m_nFree;                    // update number of free events
-        if (m_eQueue.m_nMin > m_eQueue.m_nFree) {
-            m_eQueue.m_nMin = m_eQueue.m_nFree;       // update minimum so far
-        }
-    }
-    QF_INT_UNLOCK_();
-}
-
-// "qa_sub.cpp" ==============================================================
-void QActive::subscribe(QSignal sig) const {
-    uint8_t p = m_prio;
-    Q_REQUIRE(((QSignal)Q_USER_SIG <= sig)
-              && (sig < QF_maxSignal_)
-              && ((uint8_t)0 < p) && (p <= (uint8_t)QF_MAX_ACTIVE)
-              && (QF::active_[p] == this));
-
-    uint8_t i = Q_ROM_BYTE(QF_div8Lkup[p]);
-
-    QF_INT_LOCK_KEY_
-    QF_INT_LOCK_();
-
-    QS_BEGIN_NOLOCK_(QS_QF_ACTIVE_SUBSCRIBE, QS::aoObj_, this)
-        QS_TIME_();                                               // timestamp
-        QS_SIG_(sig);                              // the signal of this event
-        QS_OBJ_(this);                                   // this active object
-    QS_END_NOLOCK_()
-                                                       // set the priority bit
-    QF_subscrList_[sig].m_bits[i] |= Q_ROM_BYTE(QF_pwr2Lkup[p]);
-    QF_INT_UNLOCK_();
-}
-
-// "qa_usub.cpp" =============================================================
-void QActive::unsubscribe(QSignal sig) const {
-    uint8_t p = m_prio;
-    Q_REQUIRE(((QSignal)Q_USER_SIG <= sig)
-              && (sig < QF_maxSignal_)
-              && ((uint8_t)0 < p) && (p <= (uint8_t)QF_MAX_ACTIVE)
-              && (QF::active_[p] == this));
-
-    uint8_t i = Q_ROM_BYTE(QF_div8Lkup[p]);
-
-    QF_INT_LOCK_KEY_
-    QF_INT_LOCK_();
-
-    QS_BEGIN_NOLOCK_(QS_QF_ACTIVE_UNSUBSCRIBE, QS::aoObj_, this)
-        QS_TIME_();                                               // timestamp
-        QS_SIG_(sig);                              // the signal of this event
-        QS_OBJ_(this);                                   // this active object
-    QS_END_NOLOCK_()
-                                                     // clear the priority bit
-    QF_subscrList_[sig].m_bits[i] &= Q_ROM_BYTE(QF_invPwr2Lkup[p]);
-    QF_INT_UNLOCK_();
-}
-
-// "qa_usuba.cpp" ============================================================
-void QActive::unsubscribeAll(void) const {
-    uint8_t p = m_prio;
-    Q_REQUIRE(((uint8_t)0 < p) && (p <= (uint8_t)QF_MAX_ACTIVE)
-              && (QF::active_[p] == this));
-
-    uint8_t i = Q_ROM_BYTE(QF_div8Lkup[p]);
-
-    QSignal sig;
-    for (sig = (QSignal)Q_USER_SIG; sig < QF_maxSignal_; ++sig) {
-        QF_INT_LOCK_KEY_
-        QF_INT_LOCK_();
-        if ((QF_subscrList_[sig].m_bits[i] & Q_ROM_BYTE(QF_pwr2Lkup[p]))
-             != 0)
-        {
-
-            QS_BEGIN_NOLOCK_(QS_QF_ACTIVE_UNSUBSCRIBE, QS::aoObj_, this)
-                QS_TIME_();                                       // timestamp
-                QS_SIG_(sig);                      // the signal of this event
-                QS_OBJ_(this);                           // this active object
-            QS_END_NOLOCK_()
-                                                     // clear the priority bit
-            QF_subscrList_[sig].m_bits[i] &= Q_ROM_BYTE(QF_invPwr2Lkup[p]);
-        }
-        QF_INT_UNLOCK_();
-    }
-}
-
-// "qeq_fifo.cpp" ============================================================
-void QEQueue::postFIFO(QEvent const *e) {
-    QF_INT_LOCK_KEY_
-    QF_INT_LOCK_();
-
-    QS_BEGIN_NOLOCK_(QS_QF_EQUEUE_POST_FIFO, QS::eqObj_, this)
-        QS_TIME_();                                               // timestamp
-        QS_SIG_(e->sig);                           // the signal of this event
-        QS_OBJ_(this);                                    // this queue 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_(m_nFree);                            // number of free entries
-        QS_EQC_(m_nMin);                         // min number of free entries
-    QS_END_NOLOCK_()
-
-    if (EVT_POOL_ID(e) != (uint8_t)0) {              // is it a dynamic event?
-        EVT_INC_REF_CTR(e);                 // increment the reference counter
-    }
-
-    if (m_frontEvt == (QEvent *)0) {                    // is the queue empty?
-        m_frontEvt = e;                              // deliver event directly
-    }
-    else {               // queue is not empty, leave event in the ring-buffer
-               // the queue must be able to accept the event (cannot overflow)
-        Q_ASSERT(m_nFree != (QEQueueCtr)0);
-
-        m_ring[m_head] = e;             // insert event into the buffer (FIFO)
-        if (m_head == (QEQueueCtr)0) {               // need to wrap the head?
-            m_head = m_end;                                     // wrap around
-        }
-        --m_head;
-
-        --m_nFree;                             // update number of free events
-        if (m_nMin > m_nFree) {
-            m_nMin = m_nFree;                         // update minimum so far
-        }
-    }
-    QF_INT_UNLOCK_();
-}
-
-// "qeq_get.cpp" =============================================================
-QEvent const *QEQueue::get(void) {
-    QEvent const *e;
-    QF_INT_LOCK_KEY_
-
-    QF_INT_LOCK_();
-    if (m_frontEvt == (QEvent *)0) {                    // is the queue empty?
-        e = (QEvent *)0;                    // no event available at this time
-    }
-    else {
-        e = m_frontEvt;
-
-        if (m_nFree != m_end) {          // any events in the the ring buffer?
-            m_frontEvt = m_ring[m_tail];         // remove event from the tail
-            if (m_tail == (QEQueueCtr)0) {           // need to wrap the tail?
-                m_tail = m_end;                                 // wrap around
-            }
-            --m_tail;
-
-            ++m_nFree;               // one more free event in the ring buffer
-
-            QS_BEGIN_NOLOCK_(QS_QF_EQUEUE_GET, QS::eqObj_, this)
-                QS_TIME_();                                       // timestamp
-                QS_SIG_(e->sig);                   // the signal of this event
-                QS_OBJ_(this);                            // this queue 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_(m_nFree);                    // number of free entries
-            QS_END_NOLOCK_()
-        }
-        else {
-            m_frontEvt = (QEvent *)0;               // the queue becomes empty
-
-            QS_BEGIN_NOLOCK_(QS_QF_EQUEUE_GET_LAST, QS::eqObj_, this)
-                QS_TIME_();                                       // timestamp
-                QS_SIG_(e->sig);                   // the signal of this event
-                QS_OBJ_(this);                            // this queue 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_END_NOLOCK_()
-        }
-    }
-    QF_INT_UNLOCK_();
-    return e;
-}
-
-// "qeq_init.cpp" ============================================================
-void QEQueue::init(QEvent const *qSto[], QEQueueCtr qLen) {
-    m_frontEvt = (QEvent *)0;                        // no events in the queue
-    m_ring     = &qSto[0];
-    m_end      = qLen;
-    m_head     = (QEQueueCtr)0;
-    m_tail     = (QEQueueCtr)0;
-    m_nFree    = qLen;
-    m_nMin     = qLen;
-
-    QS_INT_LOCK_KEY_
-    QS_BEGIN_(QS_QF_EQUEUE_INIT, QS::eqObj_, this)
-        QS_OBJ_(qSto);                                  // this QEQueue object
-        QS_EQC_(qLen);                              // the length of the queue
-    QS_END_()
-}
-
-// "qeq_lifo.cpp" ============================================================
-void QEQueue::postLIFO(QEvent const *e) {
-    QF_INT_LOCK_KEY_
-    QF_INT_LOCK_();
-
-    QS_BEGIN_NOLOCK_(QS_QF_EQUEUE_POST_LIFO, QS::eqObj_, this)
-        QS_TIME_();                                               // timestamp
-        QS_SIG_(e->sig);                           // the signal of this event
-        QS_OBJ_(this);                                    // this queue 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_(m_nFree);                            // number of free entries
-        QS_EQC_(m_nMin);                         // min number of free entries
-    QS_END_NOLOCK_()
-
-    if (EVT_POOL_ID(e) != (uint8_t)0) {              // is it a dynamic event?
-        EVT_INC_REF_CTR(e);                 // increment the reference counter
-    }
-
-    if (m_frontEvt != (QEvent *)0) {                // is the queue not empty?
-               // the queue must be able to accept the event (cannot overflow)
-        Q_ASSERT(m_nFree != (QEQueueCtr)0);
-
-        ++m_tail;
-        if (m_tail == m_end) {                       // need to wrap the tail?
-            m_tail = (QEQueueCtr)0;                             // wrap around
-        }
-
-        m_ring[m_tail] = m_frontEvt;               // buffer the old front evt
-
-        --m_nFree;                             // update number of free events
-        if (m_nMin > m_nFree) {
-            m_nMin = m_nFree;                         // update minimum so far
-        }
-    }
-
-    m_frontEvt = e;                        // stick the new event to the front
-
-    QF_INT_UNLOCK_();
-}
-
-// "qf_act.cpp" ==============================================================
-// public objects ------------------------------------------------------------
-QActive *QF::active_[QF_MAX_ACTIVE + 1];        // to be used by QF ports only
-uint8_t QF_intLockNest_;                       // interrupt-lock nesting level
-
-//............................................................................
-//lint -e970 -e971               ignore MISRA rules 13 and 14 in this function
-const char Q_ROM * Q_ROM_VAR QF::getVersion(void) {
-    static char const Q_ROM Q_ROM_VAR version[] = {
-        (char)(((QP_VERSION >> 12U) & 0xFU) + (uint8_t)'0'),
-        '.',
-        (char)(((QP_VERSION >>  8U) & 0xFU) + (uint8_t)'0'),
-        '.',
-        (char)(((QP_VERSION >>  4U) & 0xFU) + (uint8_t)'0'),
-        (char)((QP_VERSION          & 0xFU) + (uint8_t)'0'),
-        '\0'
-    };
-    return version;
-}
-//............................................................................
-void QF::add_(QActive *a) {
-    uint8_t p = a->m_prio;
-
-    Q_REQUIRE(((uint8_t)0 < p) && (p <= (uint8_t)QF_MAX_ACTIVE)
-              && (active_[p] == (QActive *)0));
-
-    QF_INT_LOCK_KEY_
-    QF_INT_LOCK_();
-
-    active_[p] = a;            // registger the active object at this priority
-
-    QS_BEGIN_NOLOCK_(QS_QF_ACTIVE_ADD, QS::aoObj_, a)
-        QS_TIME_();                                               // timestamp
-        QS_OBJ_(a);                                       // the active object
-        QS_U8_(p);                        // the priority of the active object
-    QS_END_NOLOCK_()
-
-    QF_INT_UNLOCK_();
-}
-//............................................................................
-void QF::remove_(QActive const *a) {
-    uint8_t p = a->m_prio;
-
-    Q_REQUIRE(((uint8_t)0 < p) && (p <= (uint8_t)QF_MAX_ACTIVE)
-              && (active_[p] == a));
-
-    QF_INT_LOCK_KEY_
-    QF_INT_LOCK_();
-
-    active_[p] = (QActive *)0;                   // free-up the priority level
-
-    QS_BEGIN_NOLOCK_(QS_QF_ACTIVE_REMOVE, QS::aoObj_, a)
-        QS_TIME_();                                               // timestamp
-        QS_OBJ_(a);                                       // the active object
-        QS_U8_(p);                        // the priority of the active object
-    QS_END_NOLOCK_()
-
-    QF_INT_UNLOCK_();
-}
-
-// "qf_gc.cpp" ===============================================================
-void QF::gc(QEvent const *e) {
-    if (EVT_POOL_ID(e) != (uint8_t)0) {              // is it a dynamic event?
-        QF_INT_LOCK_KEY_
-        QF_INT_LOCK_();
-
-        if (EVT_REF_CTR(e) > (uint8_t)1) {   // isn't this the last reference?
-            EVT_DEC_REF_CTR(e);                   // decrement the ref counter
-
-            QS_BEGIN_NOLOCK_(QS_QF_GC_ATTEMPT, (void *)0, (void *)0)
-                QS_TIME_();                                       // timestamp
-                QS_SIG_(e->sig);                    // the signal of the event
-                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_END_NOLOCK_()
-
-            QF_INT_UNLOCK_();
-        }
-        else {         // this is the last reference to this event, recycle it
-            uint8_t idx = (uint8_t)(EVT_POOL_ID(e) - 1);
-
-            QS_BEGIN_NOLOCK_(QS_QF_GC, (void *)0, (void *)0)
-                QS_TIME_();                                       // timestamp
-                QS_SIG_(e->sig);                    // the signal of the event
-                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_END_NOLOCK_()
-
-            QF_INT_UNLOCK_();
-
-            Q_ASSERT(idx < QF_maxPool_);
-
-#ifdef Q_EVT_CTOR
-            //lint -e1773                           Attempt to cast away const
-            ((QEvent *)e)->~QEvent();     // call the xtor, cast 'const' away,
-                             // which is legitimate, because it's a pool event
-#endif
-            //lint -e1773                           Attempt to cast away const
-            QF_EPOOL_PUT_(QF_pool_[idx], (QEvent *)e);   // cast 'const' away,
-                             // which is legitimate, because it's a pool event
-        }
-    }
-}
-
-// "qf_log2.cpp" =============================================================
-uint8_t const Q_ROM Q_ROM_VAR QF_log2Lkup[256] = {
-    0U, 1U, 2U, 2U, 3U, 3U, 3U, 3U, 4U, 4U, 4U, 4U, 4U, 4U, 4U, 4U,
-    5U, 5U, 5U, 5U, 5U, 5U, 5U, 5U, 5U, 5U, 5U, 5U, 5U, 5U, 5U, 5U,
-    6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U,
-    6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U,
-    7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U,
-    7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U,
-    7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U,
-    7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U,
-    8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U,
-    8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U,
-    8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U,
-    8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U,
-    8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U,
-    8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U,
-    8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U,
-    8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U
-};
-
-// "qf_new.cpp" ==============================================================
-QEvent *QF::new_(uint16_t evtSize, QSignal sig) {
-                    // find the pool id that fits the requested event size ...
-    uint8_t idx = (uint8_t)0;
-    while (evtSize > QF_EPOOL_EVENT_SIZE_(QF_pool_[idx])) {
-        ++idx;
-        Q_ASSERT(idx < 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_[idx], e);
-    Q_ASSERT(e != (QEvent *)0);             // pool must not run out of events
-
-    e->sig = sig;                                 // set signal for this event
-    EVT_POOL_ID(e) = (uint8_t)(idx + 1);     // store the pool ID in the event
-    EVT_REF_CTR(e) = (uint8_t)0;             // set the reference counter to 0
-
-    return e;
-}
-
-// "qf_pool.cpp" =============================================================
-// Package-scope objects -----------------------------------------------------
-QF_EPOOL_TYPE_ QF_pool_[QF_MAX_EPOOL];             // allocate the event pools
-uint8_t QF_maxPool_;                      // number of initialized event pools
-
-//............................................................................
-void QF::poolInit(void *poolSto, uint32_t poolSize, QEventSize evtSize) {
-                         // cannot exceed the number of available memory pools
-    Q_REQUIRE(QF_maxPool_ < (uint8_t)Q_DIM(QF_pool_));
-               // please initialize event pools in ascending order of evtSize:
-    Q_REQUIRE((QF_maxPool_ == (uint8_t)0)
-              || (QF_EPOOL_EVENT_SIZE_(QF_pool_[QF_maxPool_ - 1]) < evtSize));
-    QF_EPOOL_INIT_(QF_pool_[QF_maxPool_], poolSto, poolSize, evtSize);
-    ++QF_maxPool_;                                            // one more pool
-}
-
-// "qf_psini.cpp" ============================================================
-// Package-scope objects -----------------------------------------------------
-QSubscrList *QF_subscrList_;
-QSignal QF_maxSignal_;
-
-//............................................................................
-void QF::psInit(QSubscrList *subscrSto, QSignal maxSignal) {
-    QF_subscrList_ = subscrSto;
-    QF_maxSignal_ = maxSignal;
-}
-
-// "qf_pspub.cpp" ============================================================
-#ifndef Q_SPY
-void QF::publish(QEvent const *e) {
-#else
-void QF::publish(QEvent const *e, void const *sender) {
-#endif
-         // make sure that the published signal is within the configured range
-    Q_REQUIRE(e->sig < QF_maxSignal_);
-
-    QF_INT_LOCK_KEY_
-    QF_INT_LOCK_();
-
-    QS_BEGIN_NOLOCK_(QS_QF_PUBLISH, (void *)0, (void *)0)
-        QS_TIME_();                                           // the timestamp
-        QS_OBJ_(sender);                                  // the sender object
-        QS_SIG_(e->sig);                            // the signal of the event
-        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_END_NOLOCK_()
-
-    if (EVT_POOL_ID(e) != (uint8_t)0) {              // is it a dynamic event?
-        EVT_INC_REF_CTR(e);         // increment the reference counter, NOTE01
-    }
-    QF_INT_UNLOCK_();
-
-#if (QF_MAX_ACTIVE <= 8)
-    uint8_t tmp = QF_subscrList_[e->sig].m_bits[0];
-    while (tmp != (uint8_t)0) {
-        uint8_t p = Q_ROM_BYTE(QF_log2Lkup[tmp]);
-        tmp &= Q_ROM_BYTE(QF_invPwr2Lkup[p]);      // clear the subscriber bit
-        Q_ASSERT(active_[p] != (QActive *)0);            // must be registered
-
-                           // POST() asserts internally if the queue overflows
-        active_[p]->POST(e, sender);
-    }
-#else
-    uint8_t i = Q_DIM(QF_subscrList_[0].m_bits);// number of bytes in the list
-    do {                       // go through all bytes in the subsciption list
-        --i;
-        uint8_t tmp = QF_subscrList_[e->sig].m_bits[i];
-        while (tmp != (uint8_t)0) {
-            uint8_t p = Q_ROM_BYTE(QF_log2Lkup[tmp]);
-            tmp &= Q_ROM_BYTE(QF_invPwr2Lkup[p]);  // clear the subscriber bit
-            p = (uint8_t)(p + (i << 3));                // adjust the priority
-            Q_ASSERT(active_[p] != (QActive *)0);        // must be registered
-
-                           // POST() asserts internally if the queue overflows
-            active_[p]->POST(e, sender);
-        }
-    } while (i != (uint8_t)0);
-#endif
-
-    gc(e);                            // run the garbage collector, see NOTE01
-}
-
-// "qf_pwr2.cpp" =============================================================
-// Global objects ------------------------------------------------------------
-uint8_t const Q_ROM Q_ROM_VAR QF_pwr2Lkup[65] = {
-    0x00U,                                                  // unused location
-    0x01U, 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U,
-    0x01U, 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U,
-    0x01U, 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U,
-    0x01U, 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U,
-    0x01U, 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U,
-    0x01U, 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U,
-    0x01U, 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U,
-    0x01U, 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U
-};
-
-uint8_t const Q_ROM Q_ROM_VAR QF_invPwr2Lkup[65] = {
-    0xFFU,                                                  // unused location
-    0xFEU, 0xFDU, 0xFBU, 0xF7U, 0xEFU, 0xDFU, 0xBFU, 0x7FU,
-    0xFEU, 0xFDU, 0xFBU, 0xF7U, 0xEFU, 0xDFU, 0xBFU, 0x7FU,
-    0xFEU, 0xFDU, 0xFBU, 0xF7U, 0xEFU, 0xDFU, 0xBFU, 0x7FU,
-    0xFEU, 0xFDU, 0xFBU, 0xF7U, 0xEFU, 0xDFU, 0xBFU, 0x7FU,
-    0xFEU, 0xFDU, 0xFBU, 0xF7U, 0xEFU, 0xDFU, 0xBFU, 0x7FU,
-    0xFEU, 0xFDU, 0xFBU, 0xF7U, 0xEFU, 0xDFU, 0xBFU, 0x7FU,
-    0xFEU, 0xFDU, 0xFBU, 0xF7U, 0xEFU, 0xDFU, 0xBFU, 0x7FU,
-    0xFEU, 0xFDU, 0xFBU, 0xF7U, 0xEFU, 0xDFU, 0xBFU, 0x7FU
-};
-
-uint8_t const Q_ROM Q_ROM_VAR QF_div8Lkup[65] = {
-    0U,                                                     // unused location
-    0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U,
-    1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U,
-    2U, 2U, 2U, 2U, 2U, 2U, 2U, 2U,
-    3U, 3U, 3U, 3U, 3U, 3U, 3U, 3U,
-    4U, 4U, 4U, 4U, 4U, 4U, 4U, 4U,
-    5U, 5U, 5U, 5U, 5U, 5U, 5U, 5U,
-    6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U,
-    7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U
-};
-
-// "qf_tick.cpp" =============================================================
-#ifndef Q_SPY
-void QF::tick(void) {                                            // see NOTE01
-#else
-void QF::tick(void const *sender) {
-#endif
-
-    QF_INT_LOCK_KEY_
-    QF_INT_LOCK_();
-
-    QS_BEGIN_NOLOCK_(QS_QF_TICK, (void *)0, (void *)0)
-        QS_TEC_(++QS::tickCtr_);                           // the tick counter
-    QS_END_NOLOCK_()
-
-    QTimeEvt *t = QF_timeEvtListHead_;
-    while (t != (QTimeEvt *)0) {
-        --t->m_ctr;
-        if (t->m_ctr == (QTimeEvtCtr)0) {  // is the time evt about to expire?
-            if (t->m_interval != (QTimeEvtCtr)0) {//is it a periodic time evt?
-                t->m_ctr = t->m_interval;                // rearm the time evt
-            }
-            else {   // one-shot time evt, disarm by removing it from the list
-                if (t == QF_timeEvtListHead_) {
-                    QF_timeEvtListHead_ = t->m_next;
-                }
-                else {
-                    if (t->m_next != (QTimeEvt *)0) {// not the last time evt?
-                        t->m_next->m_prev = t->m_prev;
-                    }
-                    t->m_prev->m_next = t->m_next;
-                }
-                t->m_prev = (QTimeEvt *)0;     // mark the time event disarmed
-
-                QS_BEGIN_NOLOCK_(QS_QF_TIMEEVT_AUTO_DISARM, QS::teObj_, t)
-                    QS_OBJ_(t);                      // this time event object
-                    QS_OBJ_(t->m_act);                     // the active object
-                QS_END_NOLOCK_()
-            }
-
-            QS_BEGIN_NOLOCK_(QS_QF_TIMEEVT_POST, QS::teObj_, t)
-                QS_TIME_();                                       // timestamp
-                QS_OBJ_(t);                           // the time event object
-                QS_SIG_(t->sig);              // the signal of this time event
-                QS_OBJ_(t->m_act);                        // the active object
-            QS_END_NOLOCK_()
-
-            QF_INT_UNLOCK_();   // unlock interrupts before calling QF service
-
-                           // POST() asserts internally if the queue overflows
-            t->m_act->POST(t, sender);
-        }
-        else {
-            QF_INT_UNLOCK_();
-            static uint8_t volatile dummy;
-            dummy = (uint8_t)0;      // execute a few instructions, see NOTE02
-        }
-
-        QF_INT_LOCK_();           // lock interrupts again to advance the link
-        t = t->m_next;
-    }
-    QF_INT_UNLOCK_();
-}
-
-// "qmp_get.cpp" =============================================================
-void *QMPool::get(void) {
-    QF_INT_LOCK_KEY_
-    QF_INT_LOCK_();
-
-    QFreeBlock *fb = (QFreeBlock *)m_free;         // get a free block or NULL
-    if (fb != (QFreeBlock *)0) {                      // free block available?
-        m_free = fb->m_next;        // adjust list head to the next free block
-        --m_nFree;                                      // one free block less
-        if (m_nMin > m_nFree) {
-            m_nMin = m_nFree;                   // remember the minimum so far
-        }
-    }
-
-    QS_BEGIN_NOLOCK_(QS_QF_MPOOL_GET, QS::mpObj_, m_start)
-        QS_TIME_();                                               // timestamp
-        QS_OBJ_(m_start);                   // the memory managed by this pool
-        QS_MPC_(m_nFree);             // the number of free blocks in the pool
-        QS_MPC_(m_nMin);     // the mninimum number of free blocks in the pool
-    QS_END_NOLOCK_()
-
-    QF_INT_UNLOCK_();
-    return fb;               // return the block or NULL pointer to the caller
-}
-//............................................................................
-uint32_t QF::getPoolMargin(uint8_t poolId) {
-    Q_REQUIRE(((uint8_t)1 <= poolId) && (poolId <= QF_maxPool_));
-
-    QF_INT_LOCK_KEY_
-    QF_INT_LOCK_();
-    uint32_t margin = (uint32_t)QF_pool_[poolId - (uint8_t)1].m_nMin;
-    QF_INT_UNLOCK_();
-
-    return margin;
-}
-
-// "qmp_init.cpp" ============================================================
-void QMPool::init(void *poolSto, uint32_t poolSize, QMPoolSize blockSize) {
-    // 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));
-
-    m_free = poolSto;
-
-                // round up the blockSize to fit an integer number of pointers
-    m_blockSize = (QMPoolSize)sizeof(QFreeBlock);       // start with just one
-    uint32_t nblocks = (uint32_t)1;// # free blocks that fit in a memory block
-    while (m_blockSize < blockSize) {
-        m_blockSize += (QMPoolSize)sizeof(QFreeBlock);
-        ++nblocks;
-    }
-    blockSize = m_blockSize;          // use the rounded-up value from here on
-
-               // the whole 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 chain the last block
-    m_nTot     = (QMPoolCtr)1;             // one (the last) block in the pool
-    QFreeBlock *fb = (QFreeBlock *)m_free;//start at the head of the free list
-    while (poolSize >= (uint32_t)blockSize) {
-        fb->m_next = &fb[nblocks];                      // setup the next link
-        fb = fb->m_next;                              // advance to next block
-        poolSize -= (uint32_t)blockSize;     // reduce the available pool size
-        ++m_nTot;                     // increment the number of blocks so far
-    }
-
-    fb->m_next = (QFreeBlock *)0;              // the last link points to NULL
-    m_nFree    = m_nTot;                                // all blocks are free
-    m_nMin     = m_nTot;                  // the minimum number of free blocks
-    m_start    = poolSto;               // the original start this pool buffer
-    m_end      = fb;                            // the last block in this pool
-
-    QS_INT_LOCK_KEY_
-    QS_BEGIN_(QS_QF_MPOOL_INIT, QS::mpObj_, m_start)
-        QS_OBJ_(m_start);                   // the memory managed by this pool
-        QS_MPC_(m_nTot);                         // the total number of blocks
-    QS_END_()
-}
-
-// "qmp_put.cpp" =============================================================
-void QMPool::put(void *b) {
-    //lint -e946 -e1904             ignore MISRA Rule 103 in this precondition
-    Q_REQUIRE((m_start <= b) && (b <= m_end)           /*  must be in range */
-              && (m_nFree <= m_nTot));        // # free blocks must be < total
-
-    QF_INT_LOCK_KEY_
-    QF_INT_LOCK_();
-
-    ((QFreeBlock *)b)->m_next = (QFreeBlock *)m_free;//link into the free list
-    m_free = b;                            // set as new head of the free list
-    ++m_nFree;                             // one more free block in this pool
-
-    QS_BEGIN_NOLOCK_(QS_QF_MPOOL_PUT, QS::mpObj_, m_start)
-        QS_TIME_();                                               // timestamp
-        QS_OBJ_(m_start);                   // the memory managed by this pool
-        QS_MPC_(m_nFree);             // the number of free blocks in the pool
-    QS_END_NOLOCK_()
-
-    QF_INT_UNLOCK_();
-}
-
-// "qte_arm.cpp" =============================================================
-// Package-scope objects -----------------------------------------------------
-QTimeEvt *QF_timeEvtListHead_;           // head of linked list of time events
-
-//............................................................................
-void QTimeEvt::arm_(QActive *act, QTimeEvtCtr nTicks) {
-    Q_REQUIRE((nTicks > (QTimeEvtCtr)0)          /* cannot arm with 0 ticks */
-              && (sig >= (QSignal)Q_USER_SIG)               /* valid signal */
-              && (m_prev == (QTimeEvt *)0)   /* time event must NOT be used */
-              && (act != (QActive *)0));  /* active object must be provided */
-    m_ctr = nTicks;
-    m_prev = this;                                    // mark the timer in use
-    m_act = act;
-    QF_INT_LOCK_KEY_
-    QF_INT_LOCK_();
-
-    QS_BEGIN_NOLOCK_(QS_QF_TIMEEVT_ARM, QS::teObj_, this)
-        QS_TIME_();                                               // timestamp
-        QS_OBJ_(this);                               // this time event object
-        QS_OBJ_(act);                                     // the active object
-        QS_TEC_(nTicks);                                // the number of ticks
-        QS_TEC_(m_interval);                                   // the interval
-    QS_END_NOLOCK_()
-
-    m_next = QF_timeEvtListHead_;
-    if (QF_timeEvtListHead_ != (QTimeEvt *)0) {
-        QF_timeEvtListHead_->m_prev = this;
-    }
-    QF_timeEvtListHead_ = this;
-    QF_INT_UNLOCK_();
-}
-
-// "qte_ctor.cpp" ============================================================
-QTimeEvt::QTimeEvt(QSignal s)
-  :
-#ifdef Q_EVT_CTOR
-    QEvent(s),
-#endif
-    m_prev((QTimeEvt *)0),
-    m_next((QTimeEvt *)0),
-    m_act((QActive *)0),
-    m_ctr((QTimeEvtCtr)0),
-    m_interval((QTimeEvtCtr)0)
-{
-    Q_REQUIRE(s >= (QSignal)Q_USER_SIG);                       // valid signal
-    sig = s;
-    EVT_POOL_ID(this) = (uint8_t)0;   // time event must be static, see NOTE01
-}
-
-// "qte_ctr.cpp" =============================================================
-QTimeEvtCtr QTimeEvt::ctr(void) {
-    QTimeEvtCtr ctr;
-    QF_INT_LOCK_KEY_
-    QF_INT_LOCK_();
-    if (m_prev != (QTimeEvt *)0) {        // is the time event actually armed?
-        ctr = m_ctr;
-    }
-    else {                                     // the time event was not armed
-        ctr = (QTimeEvtCtr)0;
-    }
-
-    QS_BEGIN_NOLOCK_(QS_QF_TIMEEVT_CTR, QS::teObj_, this)
-        QS_TIME_();                                               // timestamp
-        QS_OBJ_(this);                               // this time event object
-        QS_OBJ_(m_act);                                   // the active object
-        QS_TEC_(ctr);                                   // the current counter
-        QS_TEC_(m_interval);                                   // the interval
-    QS_END_NOLOCK_()
-
-    QF_INT_UNLOCK_();
-    return ctr;
-}
-
-// "qte_darm.cpp" ============================================================
-// NOTE: disarm a time evt (no harm in disarming an already disarmed time evt)
-uint8_t QTimeEvt::disarm(void) {
-    uint8_t wasArmed;
-    QF_INT_LOCK_KEY_
-    QF_INT_LOCK_();
-    if (m_prev != (QTimeEvt *)0) {        // is the time event actually armed?
-        wasArmed = (uint8_t)1;
-        if (this == QF_timeEvtListHead_) {
-            QF_timeEvtListHead_ = m_next;
-        }
-        else {
-            if (m_next != (QTimeEvt *)0) {        // not the last in the list?
-                m_next->m_prev = m_prev;
-            }
-            m_prev->m_next = m_next;
-        }
-        m_prev = (QTimeEvt *)0;             // mark the time event as disarmed
-
-        QS_BEGIN_NOLOCK_(QS_QF_TIMEEVT_DISARM, QS::teObj_, this)
-            QS_TIME_();                                           // timestamp
-            QS_OBJ_(this);                           // this time event object
-            QS_OBJ_(m_act);                               // the active object
-            QS_TEC_(m_ctr);                             // the number of ticks
-            QS_TEC_(m_interval);                               // the interval
-        QS_END_NOLOCK_()
-    }
-    else {                                     // the time event was not armed
-        wasArmed = (uint8_t)0;
-
-        QS_BEGIN_NOLOCK_(QS_QF_TIMEEVT_DISARM_ATTEMPT, QS::teObj_, this)
-            QS_TIME_();                                           // timestamp
-            QS_OBJ_(this);                           // this time event object
-            QS_OBJ_(m_act);                               // the active object
-        QS_END_NOLOCK_()
-    }
-    QF_INT_UNLOCK_();
-    return wasArmed;
-}
-
-// "qte_rarm.cpp" ============================================================
-uint8_t QTimeEvt::rearm(QTimeEvtCtr nTicks) {
-    Q_REQUIRE((nTicks > (QTimeEvtCtr)0)        /* cannot rearm with 0 ticks */
-              && (sig >= (QSignal)Q_USER_SIG)               /* valid signal */
-              && (m_act != (QActive *)0));              // valid active object
-    uint8_t isArmed;
-    QF_INT_LOCK_KEY_
-    QF_INT_LOCK_();
-    m_ctr = nTicks;
-    if (m_prev == (QTimeEvt *)0) {             // is this time event disarmed?
-        isArmed = (uint8_t)0;
-        m_next = QF_timeEvtListHead_;
-        if (QF_timeEvtListHead_ != (QTimeEvt *)0) {
-            QF_timeEvtListHead_->m_prev = this;
-        }
-        QF_timeEvtListHead_ = this;
-        m_prev = this;                             // mark the time evt in use
-    }
-    else {                                          // the time event is armed
-        isArmed = (uint8_t)1;
-    }
-
-    QS_BEGIN_NOLOCK_(QS_QF_TIMEEVT_REARM, QS::teObj_, this)
-        QS_TIME_();                                               // timestamp
-        QS_OBJ_(this);                               // this time event object
-        QS_OBJ_(m_act);                                   // the active object
-        QS_TEC_(m_ctr);                                 // the number of ticks
-        QS_TEC_(m_interval);                                   // the interval
-        QS_U8_(isArmed);                               // was the timer armed?
-    QS_END_NOLOCK_()
-
-    QF_INT_UNLOCK_();
-    return isArmed;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// Kernel selection based on QK_PREEMPTIVE
-//
-#ifdef QK_PREEMPTIVE
-
-// "qk_pkg.h" ================================================================
-                                    // QK internal interrupt locking/unlocking
-#ifndef QF_INT_KEY_TYPE
-    #define QK_INT_LOCK_KEY_
-    #define QK_INT_LOCK_()      QF_INT_LOCK(dummy)
-    #define QK_INT_UNLOCK_()    QF_INT_UNLOCK(dummy)
-#else
-
-    /// \brief This is an internal macro for defining the interrupt lock key.
-    ///
-    /// The purpose of this macro is to enable writing the same code for the
-    /// case when interrupt key is defined and when it is not. If the macro
-    /// #QF_INT_KEY_TYPE is defined, this internal macro provides the
-    /// definition of the lock key variable. Otherwise this macro is empty.
-    /// \sa #QF_INT_KEY_TYPE, #QF_INT_LOCK_, #QF_INT_UNLOCK_
-    #define QK_INT_LOCK_KEY_    QF_INT_KEY_TYPE intLockKey_;
-
-    /// \brief This is an internal macro for locking interrupts.
-    ///
-    /// The purpose of this macro is to enable writing the same code for the
-    /// case when interrupt key is defined and when it is not. If the macro
-    /// #QF_INT_KEY_TYPE is defined, this internal macro invokes #QF_INT_LOCK
-    /// passing the key variable as the parameter. Otherwise #QF_INT_LOCK
-    /// is invoked with a dummy parameter.
-    /// \sa #QK_INT_LOCK_KEY_, #QK_INT_UNLOCK_
-    #define QK_INT_LOCK_()      QF_INT_LOCK(intLockKey_)
-
-    /// \brief This is an internal macro for unlocking interrupts.
-    ///
-    /// The purpose of this macro is to enable writing the same code for the
-    /// case when interrupt key is defined and when it is not. If the macro
-    /// #QF_INT_KEY_TYPE is defined, this internal macro invokes
-    /// #QF_INT_UNLOCK passing the key variable as the parameter. Otherwise
-    /// #QF_INT_UNLOCK is invoked with a dummy parameter.
-    /// \sa #QK_INT_LOCK_KEY_, #QK_INT_LOCK_
-    #define QK_INT_UNLOCK_()    QF_INT_UNLOCK(intLockKey_)
-#endif
-
-                                                   // package-scope objects...
-#ifndef QK_NO_MUTEX
-    extern uint8_t volatile QK_ceilingPrio_;    ///< QK mutex priority ceiling
-#endif
-
-// "qk.cpp" ==================================================================
-
-// Public-scope objects ------------------------------------------------------
-#if (QF_MAX_ACTIVE <= 8U)
-#ifdef Q_USE_NAMESPACE
-    QP::QPSet8  volatile QK_readySet_;                      // ready set of QK
-#else
-    QPSet8  volatile QK_readySet_;                          // ready set of QK
-#endif
-#else
-#ifdef Q_USE_NAMESPACE
-    QP::QPSet64 volatile QK_readySet_;                      // ready set of QK
-#else
-    QPSet64 volatile QK_readySet_;                          // ready set of QK
-#endif
-#endif
-
-#ifdef Q_USE_NAMESPACE
-}                                                              // namespace QP
-#endif
-                                         // start with the QK scheduler locked
-extern "C" {
-
-uint8_t volatile QK_currPrio_ = (uint8_t)(QF_MAX_ACTIVE + 1);
-uint8_t volatile QK_intNest_;                 // start with nesting level of 0
-
-}                                                                // extern "C"
-
-#ifdef Q_USE_NAMESPACE
-namespace QP {
-#endif
-
-//............................................................................
-//lint -e970 -e971               ignore MISRA rules 13 and 14 in this function
-char const Q_ROM * Q_ROM_VAR QK::getVersion(void) {
-    static char const Q_ROM Q_ROM_VAR version[] = {
-        (char)(((QP_VERSION >> 12U) & 0xFU) + (uint8_t)'0'),
-        '.',
-        (char)(((QP_VERSION >>  8U) & 0xFU) + (uint8_t)'0'),
-        '.',
-        (char)(((QP_VERSION >>  4U) & 0xFU) + (uint8_t)'0'),
-        (char)((QP_VERSION          & 0xFU) + (uint8_t)'0'),
-        '\0'
-    };
-    return version;
-}
-//............................................................................
-void QF::init(void) {
-    QK_init();           // QK initialization ("C" linkage, might be assembly)
-}
-//............................................................................
-void QF::stop(void) {
-    QF::onCleanup();                                       // cleanup callback
-    // nothing else to do for the QK preemptive kernel
-}
-//............................................................................
-void QF::run(void) {
-    QK_INT_LOCK_KEY_
-
-    QK_INT_LOCK_();
-    QK_currPrio_ = (uint8_t)0;        // set the priority for the QK idle loop
-    QK_SCHEDULE_();                      // process all events produced so far
-    QK_INT_UNLOCK_();
-
-    QF::onStartup();                                       // startup callback
-
-    for (;;) {                                             // the QK idle loop
-        QK::onIdle();                        // invoke the QK on-idle callback
-    }
-}
-//............................................................................
-void QActive::start(uint8_t prio,
-                    QEvent const *qSto[], uint32_t qLen,
-                    void *tls, uint32_t flags,
-                    QEvent const *ie)
-{
-    Q_REQUIRE(((uint8_t)0 < prio) && (prio <= (uint8_t)QF_MAX_ACTIVE));
-
-    m_eQueue.init(qSto, (QEQueueCtr)qLen);       // initialize the event queue
-    m_prio = prio;
-    QF::add_(this);                     // make QF aware of this active object
-
-#if defined(QK_TLS) || defined(QK_EXT_SAVE)
-    m_osObject = (uint8_t)flags;       // m_osObject contains the thread flags
-    m_thread   = tls;      // contains the pointer to the thread-local-storage
-#else
-    Q_ASSERT((tls == (void *)0) && (flags == (uint32_t)0));
-#endif
-
-    init(ie);                                    // execute initial transition
-
-    QS_FLUSH();                          // flush the trace buffer to the host
-}
-//............................................................................
-void QActive::stop(void) {
-    QF::remove_(this);                // remove this active object from the QF
-}
-
-// "qk_sched" ================================================================
-
-#ifdef Q_USE_NAMESPACE
-}                                                              // namespace QP
-#endif
-
-//............................................................................
-// NOTE: the QK scheduler is entered and exited with interrupts LOCKED.
-// QK_schedule_() is extern "C", so it does not belong to the QP namespace.
-//
-extern "C" {
-
-#ifndef QF_INT_KEY_TYPE
-void QK_schedule_(void) {
-#else
-void QK_schedule_(QF_INT_KEY_TYPE intLockKey_) {
-#endif
-
-#ifdef Q_USE_NAMESPACE
-    using namespace QP;
-#endif
-                         // the QK scheduler must be called at task level only
-    Q_REQUIRE(QK_intNest_ == (uint8_t)0);
-
-           // determine the priority of the highest-priority task ready to run
-    uint8_t p = QK_readySet_.findMax();
-
-#ifdef QK_NO_MUTEX
-    if (p > QK_currPrio_) {                        // do we have a preemption?
-#else                                   // QK priority-ceiling mutexes allowed
-    if ((p > QK_currPrio_) && (p > QK_ceilingPrio_)) {
-#endif
-        uint8_t pin = QK_currPrio_;               // save the initial priority
-        QActive *a;
-#ifdef QK_TLS                                    // thread-local storage used?
-        uint8_t pprev = pin;
-#endif
-        do {
-            QEvent const *e;
-            a = QF::active_[p];                // obtain the pointer to the AO
-            QK_currPrio_ = p;        // this becomes the current task priority
-
-#ifdef QK_TLS                                    // thread-local storage used?
-            if (p != pprev) {                      // are we changing threads?
-                QK_TLS(a);                  // switch new thread-local storage
-                pprev = p;
-            }
-#endif
-            QS_BEGIN_NOLOCK_(QS_QK_SCHEDULE, QS::aoObj_, a)
-                QS_TIME_();                                       // timestamp
-                QS_U8_(p);                // the priority of the active object
-                QS_U8_(pin);                         // the preempted priority
-            QS_END_NOLOCK_()
-
-            QK_INT_UNLOCK_();                         // unlock the interrupts
-
-            e = a->get_();        // get the next event for this active object
-            a->dispatch(e);                 // dispatch e to the active object
-            QF::gc(e);              // garbage collect the event, if necessary
-
-            QK_INT_LOCK_();
-                             // determine the highest-priority AO ready to run
-            if (QK_readySet_.notEmpty()) {
-                p = QK_readySet_.findMax();
-            }
-            else {
-                p = (uint8_t)0;
-            }
-#ifdef QK_NO_MUTEX
-        } while (p > pin);         // is the new priority higher than initial?
-#else                                   // QK priority-ceiling mutexes allowed
-        } while ((p > pin) && (p > QK_ceilingPrio_));
-#endif
-        QK_currPrio_ = pin;                    // restore the initial priority
-
-#ifdef QK_TLS                                    // thread-local storage used?
-        if (pin != (uint8_t)0) {      // no extended context for the idle loop
-            a = QF::active_[pin];           // the pointer to the preempted AO
-            QK_TLS(a);                             // restore the original TLS
-        }
-#endif
-    }
-}
-
-}                                                                // extern "C"
-
-#ifdef Q_USE_NAMESPACE
-namespace QP {
-#endif
-
-// "qk_mutex.cpp" ============================================================
-#ifndef QK_NO_MUTEX
-
-// package-scope objects -----------------------------------------------------
-uint8_t volatile QK_ceilingPrio_;               // ceiling priority of a mutex
-
-//............................................................................
-QMutex QK::mutexLock(uint8_t prioCeiling) {
-    QK_INT_LOCK_KEY_
-    QK_INT_LOCK_();
-    uint8_t mutex = QK_ceilingPrio_; // original QK priority ceiling to return
-    if (QK_ceilingPrio_ < prioCeiling) {
-        QK_ceilingPrio_ = prioCeiling;        // raise the QK priority ceiling
-    }
-
-    QS_BEGIN_NOLOCK_(QS_QK_MUTEX_LOCK, (void *)0, (void *)0)
-        QS_TIME_();                                               // timestamp
-        QS_U8_(mutex);                                // the original priority
-        QS_U8_(QK_ceilingPrio_);               // the current priority ceiling
-    QS_END_NOLOCK_()
-
-    QK_INT_UNLOCK_();
-    return mutex;
-}
-//............................................................................
-void QK::mutexUnlock(QMutex mutex) {
-    QK_INT_LOCK_KEY_
-    QK_INT_LOCK_();
-
-    QS_BEGIN_NOLOCK_(QS_QK_MUTEX_UNLOCK, (void *)0, (void *)0)
-        QS_TIME_();                                               // timestamp
-        QS_U8_(mutex);                                // the original priority
-        QS_U8_(QK_ceilingPrio_);               // the current priority ceiling
-    QS_END_NOLOCK_()
-
-    if (QK_ceilingPrio_ > mutex) {
-        QK_ceilingPrio_ = mutex;         // restore the saved priority ceiling
-        QK_SCHEDULE_();
-    }
-    QK_INT_UNLOCK_();
-}
-#endif                                                          // QK_NO_MUTEX
-
-#else                                                         // QK_PREEMPTIVE
-
-// "qvanilla.cpp" ============================================================
-// Package-scope objects -----------------------------------------------------
-#if (QF_MAX_ACTIVE <= 8)
-    QPSet8  volatile QF_readySet_;           // QF-ready set of active objects
-#else
-    QPSet64 volatile QF_readySet_;           // QF-ready set of active objects
-#endif
-
-//............................................................................
-char const Q_ROM * Q_ROM_VAR QF::getPortVersion(void) {
-    static const char Q_ROM version[] = "4.0.00";
-    return version;
-}
-//............................................................................
-void QF::init(void) {
-    // nothing to do for the "vanilla" kernel
-}
-//............................................................................
-void QActive::start(uint8_t prio,
-                    QEvent const *qSto[], uint32_t qLen,
-                    void *stkSto, uint32_t /*lint -e1904 stkSize */,
-                    QEvent const *ie)
-{
-    Q_REQUIRE(((uint8_t)0 < prio) && (prio <= (uint8_t)QF_MAX_ACTIVE)
-              && (stkSto == (void *)0));      // does not need per-actor stack
-
-    m_eQueue.init(qSto, (QEQueueCtr)qLen);               // initialize QEQueue
-    m_prio = prio;                // set the QF priority of this active object
-    QF::add_(this);                     // make QF aware of this active object
-    init(ie);                                    // execute initial transition
-
-    QS_FLUSH();                          // flush the trace buffer to the host
-}
-//............................................................................
-void QActive::stop(void) {
-    QF::remove_(this);
-}
-
-//............................................................................
-void QF::stop(void) {
-    QF::onCleanup();                                       // cleanup callback
-    // nothing else to do for the "vanilla" kernel
-}
-//............................................................................
-void QF::run(void) {
-    QF::onStartup();                                       // startup callback
-
-    for (;;) {                                           // the bacground loop
-        QF_INT_LOCK_KEY_
-        QF_INT_LOCK_();
-        if (QF_readySet_.notEmpty()) {
-            uint8_t p = QF_readySet_.findMax();
-            QActive *a = active_[p];
-            QF_INT_UNLOCK_();
-
-            QEvent const *e = a->get_();     // get the next event for this AO
-            a->dispatch(e);                         // dispatch evt to the HSM
-            gc(e);       // determine if event is garbage and collect it if so
-        }
-        else {
-#ifndef QF_INT_KEY_TYPE
-            onIdle();                                            // see NOTE01
-#else
-            onIdle(intLockKey_);                                 // see NOTE01
-#endif                                                      // QF_INT_KEY_TYPE
-        }
-    }
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// NOTE01:
-// QF::onIdle() must be called with interrupts LOCKED because the
-// determination of the idle condition (no events in the queues) can change
-// at any time by an interrupt posting events to a queue. The QF::onIdle()
-// MUST enable interrups internally, perhaps at the same time as putting the
-// CPU into a power-saving mode.
-//
-
-#endif                                                        // QK_PREEMPTIVE
-
-//////////////////////////////////////////////////////////////////////////////
-#ifdef Q_SPY
-
-// "qs_pkg.h" ================================================================
-/// \brief QS ring buffer counter and offset type
-typedef uint16_t QSCtr;
-
-/// \brief Internal QS macro to insert an un-escaped byte into
-/// the QS buffer
-////
-#define QS_INSERT_BYTE(b_) \
-    QS_ring_[QS_head_] = (b_); \
-    ++QS_head_; \
-    if (QS_head_ == QS_end_) { \
-        QS_head_ = (QSCtr)0; \
-    } \
-    ++QS_used_;
-
-/// \brief Internal QS macro to insert an escaped byte into the QS buffer
-#define QS_INSERT_ESC_BYTE(b_) \
-    QS_chksum_ = (uint8_t)(QS_chksum_ + (b_)); \
-    if (((b_) == QS_FRAME) || ((b_) == QS_ESC)) { \
-        QS_INSERT_BYTE(QS_ESC) \
-        QS_INSERT_BYTE((uint8_t)((b_) ^ QS_ESC_XOR)) \
-    } \
-    else { \
-        QS_INSERT_BYTE(b_) \
-    }
-
-/// \brief Internal QS macro to insert a escaped checksum byte into
-/// the QS buffer
-#define QS_INSERT_CHKSUM_BYTE() \
-    QS_chksum_ = (uint8_t)~QS_chksum_; \
-    if ((QS_chksum_ == QS_FRAME) || (QS_chksum_ == QS_ESC)) { \
-        QS_INSERT_BYTE(QS_ESC) \
-        QS_INSERT_BYTE((uint8_t)(QS_chksum_ ^ QS_ESC_XOR)) \
-    } \
-    else { \
-        QS_INSERT_BYTE(QS_chksum_) \
-    }
-
-
-/// \brief Frame character of the QS output protocol
-#define QS_FRAME    ((uint8_t)0x7E)
-
-/// \brief Escape character of the QS output protocol
-#define QS_ESC      ((uint8_t)0x7D)
-
-/// \brief Escape modifier of the QS output protocol
-///
-/// The escaped byte is XOR-ed with the escape modifier before it is inserted
-/// into the QS buffer.
-#define QS_ESC_XOR  0x20
-
-#ifndef Q_ROM_BYTE
-    /// \brief Macro to access a byte allocated in ROM
-    ///
-    /// Some compilers for Harvard-architecture MCUs, such as gcc for AVR, do
-    /// not generate correct code for accessing data allocated in the program
-    /// space (ROM). The workaround for such compilers is to explictly add
-    /// assembly code to access each data element allocated in the program
-    /// space. The macro Q_ROM_BYTE() retrieves a byte from the given ROM
-    /// address.
-    ///
-    /// The Q_ROM_BYTE() macro should be defined for the compilers that
-    /// cannot handle correctly data allocated in ROM (such as the gcc).
-    /// If the macro is left undefined, the default definition simply returns
-    /// the argument and lets the compiler generate the correct code.
-    #define Q_ROM_BYTE(rom_var_)   (rom_var_)
-#endif
-
-//............................................................................
-extern uint8_t *QS_ring_;         ///< pointer to the start of the ring buffer
-extern QSCtr QS_end_;                ///< offset of the end of the ring buffer
-extern QSCtr QS_head_;         ///< offset to where next byte will be inserted
-extern QSCtr QS_tail_;       ///< offset of where next event will be extracted
-extern QSCtr QS_used_;       ///< number of bytes currently in the ring buffer
-extern uint8_t QS_seq_;                        ///< the record sequence number
-extern uint8_t QS_chksum_;             ///< the checksum of the current record
-extern uint8_t QS_full_;              ///< the ring buffer is temporarily full
-
-// "qs.cpp" ==================================================================
-//............................................................................
-uint8_t QS::glbFilter_[32];                                // global QS filter
-
-//............................................................................
-uint8_t *QS_ring_;                  // pointer to the start of the ring buffer
-QSCtr QS_end_;                         // offset of the end of the ring buffer
-QSCtr QS_head_;                  // offset to where next byte will be inserted
-QSCtr QS_tail_;                 // offset of where next byte will be extracted
-QSCtr QS_used_;                // number of bytes currently in the ring buffer
-uint8_t QS_seq_;                                 // the record sequence number
-uint8_t QS_chksum_;                      // the checksum of the current record
-uint8_t QS_full_;                       // the ring buffer is temporarily full
-
-//............................................................................
-//lint -e970 -e971               ignore MISRA rules 13 and 14 in this function
-char const Q_ROM * Q_ROM_VAR QS::getVersion(void) {
-    static char const Q_ROM Q_ROM_VAR version[] = {
-        (char)(((QP_VERSION >> 12U) & 0xFU) + (uint8_t)'0'),
-        '.',
-        (char)(((QP_VERSION >>  8U) & 0xFU) + (uint8_t)'0'),
-        '.',
-        (char)(((QP_VERSION >>  4U) & 0xFU) + (uint8_t)'0'),
-        (char)((QP_VERSION          & 0xFU) + (uint8_t)'0'),
-        '\0'
-    };
-    return version;
-}
-//............................................................................
-void QS::initBuf(uint8_t sto[], uint32_t stoSize) {
-    QS_ring_ = &sto[0];
-    QS_end_  = (QSCtr)stoSize;
-}
-//............................................................................
-void QS::filterOn(uint8_t rec) {
-    if (rec == QS_ALL_RECORDS) {
-        uint8_t i;
-        for (i = (uint8_t)0; i < (uint8_t)sizeof(glbFilter_); ++i) {
-            glbFilter_[i] = (uint8_t)0xFF;
-        }
-    }
-    else {
-        glbFilter_[rec >> 3] |= (uint8_t)(1U << (rec & 0x07));
-    }
-}
-//............................................................................
-void QS::filterOff(uint8_t rec) {
-    if (rec == QS_ALL_RECORDS) {
-        uint8_t i;
-        for (i = (uint8_t)0; i < (uint8_t)sizeof(glbFilter_); ++i) {
-            glbFilter_[i] = (uint8_t)0;
-        }
-    }
-    else {
-        glbFilter_[rec >> 3] &= (uint8_t)(~(1U << (rec & 0x07)));
-    }
-}
-//............................................................................
-void QS::begin(uint8_t rec) {
-    QS_chksum_ = (uint8_t)0;                             // clear the checksum
-    ++QS_seq_;                         // always increment the sequence number
-    QS_INSERT_ESC_BYTE(QS_seq_)                   // store the sequence number
-    QS_INSERT_ESC_BYTE(rec)                             // store the record ID
-}
-//............................................................................
-void QS::end(void) {
-    QS_INSERT_CHKSUM_BYTE()
-    QS_INSERT_BYTE(QS_FRAME)
-    if (QS_used_ > QS_end_) {                    // overrun over the old data?
-        QS_tail_ = QS_head_;                 // shift the tail to the old data
-        QS_used_ = QS_end_;                        // the whole buffer is used
-    }
-}
-//............................................................................
-void QS::u8(uint8_t format, uint8_t d) {
-    QS_INSERT_ESC_BYTE(format)
-    QS_INSERT_ESC_BYTE(d)
-}
-//............................................................................
-void QS::u16(uint8_t format, uint16_t d) {
-    QS_INSERT_ESC_BYTE(format)
-    QS_INSERT_ESC_BYTE((uint8_t)d)
-    d >>= 8;
-    QS_INSERT_ESC_BYTE((uint8_t)d)
-}
-//............................................................................
-void QS::u32(uint8_t format, uint32_t d) {
-    QS_INSERT_ESC_BYTE(format)
-    QS_INSERT_ESC_BYTE((uint8_t)d)
-    d >>= 8;
-    QS_INSERT_ESC_BYTE((uint8_t)d)
-    d >>= 8;
-    QS_INSERT_ESC_BYTE((uint8_t)d)
-    d >>= 8;
-    QS_INSERT_ESC_BYTE((uint8_t)d)
-}
-
-// "qs_.cpp" =================================================================
-//............................................................................
-void const *QS::smObj_;                  // local state machine for QEP filter
-void const *QS::aoObj_;                   // local active object for QF filter
-void const *QS::mpObj_;                     //  local event pool for QF filter
-void const *QS::eqObj_;                      //  local raw queue for QF filter
-void const *QS::teObj_;                     //  local time event for QF filter
-void const *QS::apObj_;                    //  local object Application filter
-
-QSTimeCtr volatile QS::tickCtr_;     // tick counter for the QS_QF_TICK record
-
-//............................................................................
-void QS::u8_(uint8_t d) {
-    QS_INSERT_ESC_BYTE(d)
-}
-//............................................................................
-void QS::u16_(uint16_t d) {
-    QS_INSERT_ESC_BYTE((uint8_t)d)
-    d >>= 8;
-    QS_INSERT_ESC_BYTE((uint8_t)d)
-}
-//............................................................................
-void QS::u32_(uint32_t d) {
-    QS_INSERT_ESC_BYTE((uint8_t)d)
-    d >>= 8;
-    QS_INSERT_ESC_BYTE((uint8_t)d)
-    d >>= 8;
-    QS_INSERT_ESC_BYTE((uint8_t)d)
-    d >>= 8;
-    QS_INSERT_ESC_BYTE((uint8_t)d)
-}
-//............................................................................
-//lint -e970 -e971               ignore MISRA rules 13 and 14 in this function
-void QS::str_(char const *s) {
-    while (*s != '\0') {
-                                       // ASCII characters don't need escaping
-        QS_chksum_ = (uint8_t)(QS_chksum_ + (uint8_t)(*s));
-        QS_INSERT_BYTE((uint8_t)(*s))
-        ++s;
-    }
-    QS_INSERT_BYTE((uint8_t)0)
-}
-//............................................................................
-//lint -e970 -e971               ignore MISRA rules 13 and 14 in this function
-void QS::str_ROM_(char const Q_ROM * Q_ROM_VAR s) {
-    uint8_t b;
-    while ((b = (uint8_t)Q_ROM_BYTE(*s)) != (uint8_t)0) {
-                                       // ASCII characters don't need escaping
-        QS_chksum_ = (uint8_t)(QS_chksum_ + b);
-        QS_INSERT_BYTE(b)
-        ++s;
-    }
-    QS_INSERT_BYTE((uint8_t)0)
-}
-
-// "qs_blk.cpp" ==============================================================
-//............................................................................
-// get up to *pn bytes of contiguous memory
-uint8_t const *QS::getBlock(uint16_t *pNbytes) {
-    uint8_t *block;
-    if (QS_used_ == (QSCtr)0) {
-        *pNbytes = (uint16_t)0;
-        block = (uint8_t *)0;                  // no bytes to return right now
-    }
-    else {
-        QSCtr n = (QSCtr)(QS_end_ - QS_tail_);
-        if (n > QS_used_) {
-            n = QS_used_;
-        }
-        if (n > (QSCtr)(*pNbytes)) {
-            n = (QSCtr)(*pNbytes);
-        }
-        *pNbytes = (uint16_t)n;
-        QS_used_ = (QSCtr)(QS_used_ - n);
-        QSCtr t  = QS_tail_;
-        QS_tail_ = (QSCtr)(QS_tail_ + n);
-        if (QS_tail_ == QS_end_) {
-            QS_tail_ = (QSCtr)0;
-        }
-        block = &QS_ring_[t];
-    }
-    return block;
-}
-
-// "qs_byte.cpp" =============================================================
-//............................................................................
-uint16_t QS::getByte(void) {
-    uint16_t ret;
-    if (QS_used_ == (QSCtr)0) {
-        ret = QS_EOD;                                       // set End-Of-Data
-    }
-    else {
-        ret = QS_ring_[QS_tail_];                    // set the byte to return
-        ++QS_tail_;                                        // advance the tail
-        if (QS_tail_ == QS_end_) {                        // tail wrap around?
-            QS_tail_ = (QSCtr)0;
-        }
-        --QS_used_;                                      // one less byte used
-    }
-    return ret;                                      // return the byte or EOD
-}
-
-// "qs_f32.cpp" ==============================================================
-//............................................................................
-void QS::f32(uint8_t format, float f) {
-    union F32Rep {
-        float f;
-        uint32_t u;
-    } fu32;
-    fu32.f = f;
-
-    QS_INSERT_ESC_BYTE(format)
-    QS_INSERT_ESC_BYTE((uint8_t)fu32.u)
-    fu32.u >>= 8;
-    QS_INSERT_ESC_BYTE((uint8_t)fu32.u)
-    fu32.u >>= 8;
-    QS_INSERT_ESC_BYTE((uint8_t)fu32.u)
-    fu32.u >>= 8;
-    QS_INSERT_ESC_BYTE((uint8_t)fu32.u)
-}
-
-// "qs_f64.cpp" ==============================================================
-//............................................................................
-void QS::f64(uint8_t format, double d) {
-    union F64Rep {
-        double d;
-        struct UInt2 {
-            uint32_t u1, u2;
-        } i;
-    } fu64;
-    fu64.d = d;
-
-    QS_INSERT_ESC_BYTE(format)
-
-    QS_INSERT_ESC_BYTE((uint8_t)fu64.i.u1)
-    fu64.i.u1 >>= 8;
-    QS_INSERT_ESC_BYTE((uint8_t)fu64.i.u1)
-    fu64.i.u1 >>= 8;
-    QS_INSERT_ESC_BYTE((uint8_t)fu64.i.u1)
-    fu64.i.u1 >>= 8;
-    QS_INSERT_ESC_BYTE((uint8_t)fu64.i.u1)
-
-    QS_INSERT_ESC_BYTE((uint8_t)fu64.i.u2)
-    fu64.i.u2 >>= 8;
-    QS_INSERT_ESC_BYTE((uint8_t)fu64.i.u2)
-    fu64.i.u2 >>= 8;
-    QS_INSERT_ESC_BYTE((uint8_t)fu64.i.u2)
-    fu64.i.u2 >>= 8;
-    QS_INSERT_ESC_BYTE((uint8_t)fu64.i.u2)
-}
-
-// "qs_mem.cpp" ==============================================================
-//............................................................................
-void QS::mem(uint8_t const *blk, uint8_t size) {
-    QS_INSERT_BYTE((uint8_t)QS_MEM_T)
-    QS_chksum_ = (uint8_t)(QS_chksum_ + (uint8_t)QS_MEM_T);
-    QS_INSERT_ESC_BYTE(size)
-    while (size != (uint8_t)0) {
-        QS_INSERT_ESC_BYTE(*blk)
-        ++blk;
-        --size;
-    }
-}
-
-// "qs_str.cpp" ==============================================================
-//............................................................................
-//lint -e970 -e971               ignore MISRA rules 13 and 14 in this function
-void QS::str(char const *s) {
-    QS_INSERT_BYTE((uint8_t)QS_STR_T)
-    QS_chksum_ = (uint8_t)(QS_chksum_ + (uint8_t)QS_STR_T);
-    while ((*s) != '\0') {
-                                       // ASCII characters don't need escaping
-        QS_INSERT_BYTE((uint8_t)(*s))
-        QS_chksum_ = (uint8_t)(QS_chksum_ + (uint8_t)(*s));
-        ++s;
-    }
-    QS_INSERT_BYTE((uint8_t)0)
-}
-//............................................................................
-//lint -e970 -e971               ignore MISRA rules 13 and 14 in this function
-void QS::str_ROM(char const Q_ROM * Q_ROM_VAR s) {
-    QS_INSERT_BYTE((uint8_t)QS_STR_T)
-    QS_chksum_ = (uint8_t)(QS_chksum_ + (uint8_t)QS_STR_T);
-    uint8_t b;
-    while ((b = (uint8_t)Q_ROM_BYTE(*s)) != (uint8_t)0) {
-                                       // ASCII characters don't need escaping
-        QS_INSERT_BYTE(b)
-        QS_chksum_ = (uint8_t)(QS_chksum_ + b);
-        ++s;
-    }
-    QS_INSERT_BYTE((uint8_t)0)
-}
-
-// "qs_u64.cpp" ==============================================================
-#if (QS_OBJ_PTR_SIZE == 8) || (QS_FUN_PTR_SIZE == 8)
-
-//............................................................................
-void QS::u64_(uint64_t d) {
-    QS_INSERT_ESC_BYTE((uint8_t)d)
-    d >>= 8;
-    QS_INSERT_ESC_BYTE((uint8_t)d)
-    d >>= 8;
-    QS_INSERT_ESC_BYTE((uint8_t)d)
-    d >>= 8;
-    QS_INSERT_ESC_BYTE((uint8_t)d)
-    d >>= 8;
-    QS_INSERT_ESC_BYTE((uint8_t)d)
-    d >>= 8;
-    QS_INSERT_ESC_BYTE((uint8_t)d)
-    d >>= 8;
-    QS_INSERT_ESC_BYTE((uint8_t)d)
-    d >>= 8;
-    QS_INSERT_ESC_BYTE((uint8_t)d)
-}
-//............................................................................
-void QS::u64(uint8_t format, uint64_t d) {
-    QS_INSERT_ESC_BYTE(format)
-    u64_(d);
-}
-
-#endif
-
-#endif                                                                // Q_SPY
-
-#ifdef Q_USE_NAMESPACE
-}                                                              // namespace QP
-#endif
-
+//////////////////////////////////////////////////////////////////////////////
+// Product: QP/C++
+// Last Updated for QP ver: 4.5.02 (modified to fit in one file)
+// Date of the Last Update: Aug 24, 2012
+//
+//                    Q u a n t u m     L e a P s
+//                    ---------------------------
+//                    innovating embedded systems
+//
+// Copyright (C) 2002-2012 Quantum Leaps, LLC. All rights reserved.
+//
+// This program is open source software: you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as published
+// by the Free Software Foundation, either version 2 of the License, or
+// (at your option) any later version.
+//
+// Alternatively, this program may be distributed and modified under the
+// terms of Quantum Leaps commercial licenses, which expressly supersede
+// the GNU General Public License and are specifically designed for
+// licensees interested in retaining the proprietary status of their code.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+// Contact information:
+// Quantum Leaps Web sites: http://www.quantum-leaps.com
+//                          http://www.state-machine.com
+// e-mail:                  info@quantum-leaps.com
+//////////////////////////////////////////////////////////////////////////////
+#include "qp_port.h"                                                // QP port
+
+// "qep_pkg.h" ===============================================================
+QP_BEGIN_
+
+Q_DEFINE_THIS_MODULE("qp")
+
+//////////////////////////////////////////////////////////////////////////////
+/// preallocated reserved events
+extern QEvt const QEP_reservedEvt_[];
+
+/// empty signal for internal use only
+QSignal const QEP_EMPTY_SIG_ = static_cast<QSignal>(0);
+
+/// maximum depth of state nesting (including the top level), must be >= 3
+int8_t const QEP_MAX_NEST_DEPTH_ = static_cast<int8_t>(6);
+
+uint8_t const u8_0  = static_cast<uint8_t>(0); ///< \brief constant (uint8_t)0
+uint8_t const u8_1  = static_cast<uint8_t>(1); ///< \brief constant (uint8_t)1
+int8_t  const s8_0  = static_cast<int8_t>(0);  ///< \brief constant  (int8_t)0
+int8_t  const s8_1  = static_cast<int8_t>(1);  ///< \brief constant  (int8_t)1
+int8_t  const s8_n1 = static_cast<int8_t>(-1); ///< \brief constant (int8_t)-1
+
+QP_END_
+
+/// helper macro to trigger internal event in an HSM
+#define QEP_TRIG_(state_, sig_) \
+    ((*(state_))(this, &QEP_reservedEvt_[sig_]))
+
+/// helper macro to trigger exit action in an HSM
+#define QEP_EXIT_(state_) do { \
+    if (QEP_TRIG_(state_, Q_EXIT_SIG) == Q_RET_HANDLED) { \
+        QS_BEGIN_(QS_QEP_STATE_EXIT, QS::smObj_, this) \
+            QS_OBJ_(this); \
+            QS_FUN_(state_); \
+        QS_END_() \
+    } \
+} while (false)
+
+/// helper macro to trigger entry action in an HSM
+#define QEP_ENTER_(state_) do { \
+    if (QEP_TRIG_(state_, Q_ENTRY_SIG) == Q_RET_HANDLED) { \
+        QS_BEGIN_(QS_QEP_STATE_ENTRY, QS::smObj_, this) \
+            QS_OBJ_(this); \
+            QS_FUN_(state_); \
+        QS_END_() \
+    } \
+} while (false)
+
+// "qep.cpp" =================================================================
+/// \brief ::QEP_reservedEvt_ definition and QEP::getVersion() implementation.
+
+QP_BEGIN_
+
+// Package-scope objects -----------------------------------------------------
+QEvt const QEP_reservedEvt_[] = {
+#ifdef Q_EVT_CTOR                         // Is the QEvt constructor provided?
+    static_cast<QSignal>(0),
+    static_cast<QSignal>(1),
+    static_cast<QSignal>(2),
+    static_cast<QSignal>(3)
+#else                                    // QEvt is a POD (Plain Old Datatype)
+    { static_cast<QSignal>(0), u8_0, u8_0 },
+    { static_cast<QSignal>(1), u8_0, u8_0 },
+    { static_cast<QSignal>(2), u8_0, u8_0 },
+    { static_cast<QSignal>(3), u8_0, u8_0 }
+#endif
+};
+//............................................................................
+char_t const Q_ROM * Q_ROM_VAR QEP::getVersion(void) {
+    uint8_t const u8_zero = static_cast<uint8_t>('0');
+    static char_t const Q_ROM Q_ROM_VAR version[] = {
+        static_cast<char_t>(((QP_VERSION >> 12) & 0xFU) + u8_zero),
+        static_cast<char_t>('.'),
+        static_cast<char_t>(((QP_VERSION >>  8) & 0xFU) + u8_zero),
+        static_cast<char_t>('.'),
+        static_cast<char_t>(((QP_VERSION >>  4) & 0xFU) + u8_zero),
+        static_cast<char_t>((QP_VERSION         & 0xFU) + u8_zero),
+        static_cast<char_t>('\0')
+    };
+    return version;
+}
+
+QP_END_
+
+// "qhsm_top.cpp" ============================================================
+/// \brief QHsm::top() implementation.
+
+QP_BEGIN_
+
+//............................................................................
+QState QHsm::top(void * const, QEvt const * const) {
+    return Q_RET_IGNORED;                  // the top state ignores all events
+}
+
+QP_END_
+
+// "qhsm_ini.cpp" ============================================================
+/// \brief QHsm::init() implementation.
+
+QP_BEGIN_
+
+//............................................................................
+QHsm::~QHsm() {
+}
+//............................................................................
+void QHsm::init(QEvt const * const e) {
+    QStateHandler t = m_state;
+
+    Q_REQUIRE((m_temp != 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((*m_temp)(this, e) == Q_RET_TRAN);
+
+    QS_CRIT_STAT_
+    do {                                           // drill into the target...
+        QStateHandler path[QEP_MAX_NEST_DEPTH_];
+        int8_t ip = s8_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_temp);           // the target of the initial transition
+        QS_END_()
+
+        path[0] = m_temp;
+        (void)QEP_TRIG_(m_temp, QEP_EMPTY_SIG_);
+        while (m_temp != t) {
+            ++ip;
+            path[ip] = m_temp;
+            (void)QEP_TRIG_(m_temp, QEP_EMPTY_SIG_);
+        }
+        m_temp = path[0];
+                                               // entry path must not overflow
+        Q_ASSERT(ip < QEP_MAX_NEST_DEPTH_);
+
+        do {           // retrace the entry path in reverse (desired) order...
+            QEP_ENTER_(path[ip]);                            // enter path[ip]
+            --ip;
+        } while (ip >= s8_0);
+
+        t = path[0];                   // current state becomes the new source
+    } while (QEP_TRIG_(t, Q_INIT_SIG) == Q_RET_TRAN);
+
+    QS_BEGIN_(QS_QEP_INIT_TRAN, QS::smObj_, this)
+        QS_TIME_();                                              // time stamp
+        QS_OBJ_(this);                            // this state machine object
+        QS_FUN_(t);                                    // the new active state
+    QS_END_()
+
+    m_state = t;                            // change the current active state
+    m_temp  = t;                           // mark the configuration as stable
+}
+
+QP_END_
+
+// "qhsm_dis.cpp" ============================================================
+/// \brief QHsm::dispatch() implementation.
+
+QP_BEGIN_
+
+//............................................................................
+void QHsm::dispatch(QEvt const * const e) {
+    QStateHandler t = m_state;
+
+    Q_REQUIRE(t == m_temp);          // the state configuration must be stable
+
+    QStateHandler s;
+    QState r;
+    QS_CRIT_STAT_
+
+    QS_BEGIN_(QS_QEP_DISPATCH, QS::smObj_, this)
+        QS_TIME_();                                              // time stamp
+        QS_SIG_(e->sig);                            // the signal of the event
+        QS_OBJ_(this);                            // this state machine object
+        QS_FUN_(t);                                       // the current state
+    QS_END_()
+
+    do {                                // process the event hierarchically...
+        s = m_temp;
+        r = (*s)(this, e);                           // invoke state handler s
+
+        if (r == Q_RET_UNHANDLED) {               // unhandled due to a guard?
+
+            QS_BEGIN_(QS_QEP_UNHANDLED, QS::smObj_, this)
+                QS_SIG_(e->sig);                    // the signal of the event
+                QS_OBJ_(this);                    // 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 == Q_RET_SUPER);
+
+    if (r == Q_RET_TRAN) {                                // transition taken?
+        QStateHandler path[QEP_MAX_NEST_DEPTH_];
+        int8_t ip = s8_n1;                      // transition entry path index
+        int8_t iq;                       // helper transition entry path index
+#ifdef Q_SPY
+        QStateHandler src = s;       // save the transition source for tracing
+#endif
+
+        path[0] = m_temp;                 // 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_, this)
+                    QS_OBJ_(this);                // this state machine object
+                    QS_FUN_(t);                            // the exited state
+                QS_END_()
+
+                (void)QEP_TRIG_(t, QEP_EMPTY_SIG_);    // find superstate of t
+            }
+            t = m_temp;                         // m_temp 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 = s8_0;                                     // enter the target
+        }
+        else {
+            (void)QEP_TRIG_(t, QEP_EMPTY_SIG_);        // superstate of target
+            t = m_temp;
+            if (s == t) {                   // (b) check source==target->super
+                ip = s8_0;               // enter the target
+            }
+            else {
+                (void)QEP_TRIG_(s, QEP_EMPTY_SIG_);       // superstate of src
+                                     // (c) check source->super==target->super
+                if (m_temp == t) {
+                    QEP_EXIT_(s);                           // exit the source
+                    ip = s8_0;           // enter the target
+                }
+                else {
+                                            // (d) check source->super==target
+                    if (m_temp == 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 = s8_0; // indicate LCA not found
+                        ip = s8_1; // enter target's superst
+                        path[1] = t;          // save the superstate of target
+                        t = m_temp;                      // save source->super
+                                                  // find target->super->super
+                        r = QEP_TRIG_(path[1], QEP_EMPTY_SIG_);
+                        while (r == Q_RET_SUPER) {
+                            ++ip;
+                            path[ip] = m_temp;         // store the entry path
+                            if (m_temp == s) {            // is it the source?
+                                                    // indicate that LCA found
+                                iq = s8_1;
+                                               // entry path must not overflow
+                                Q_ASSERT(ip < 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_(m_temp, QEP_EMPTY_SIG_);
+                            }
+                        }
+                        if (iq == s8_0) {  // LCA found yet?
+
+                                               // entry path must not overflow
+                            Q_ASSERT(ip < 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
+                                                           // do not enter LCA
+                                    ip = static_cast<int8_t>(iq - s8_1);
+                                                         // terminate the loop
+                                    iq = s8_n1;
+                                }
+                                else {
+                                    --iq;    // try lower superstate of target
+                                }
+                            } while (iq >= s8_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_, this)
+                                            QS_OBJ_(this);
+                                            QS_FUN_(t);
+                                        QS_END_()
+
+                                        (void)QEP_TRIG_(t, QEP_EMPTY_SIG_);
+                                    }
+                                    t = m_temp;          //  set to super of t
+                                    iq = ip;
+                                    do {
+                                        if (t == path[iq]) {   // is this LCA?
+                                                           // do not enter LCA
+                                            ip = static_cast<int8_t>(iq-s8_1);
+                                                // break out of the inner loop
+                                            iq = s8_n1;
+                                            r = Q_RET_HANDLED;  // break outer
+                                        }
+                                        else {
+                                            --iq;
+                                        }
+                                    } while (iq >= s8_0);
+                                } while (r != Q_RET_HANDLED);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+                       // retrace the entry path in reverse (desired) order...
+        for (; ip >= s8_0; --ip) {
+            QEP_ENTER_(path[ip]);                            // enter path[ip]
+        }
+        t = path[0];                         // stick the target into register
+        m_temp = t;                                   // update the next state
+
+                                         // drill into the target hierarchy...
+        while (QEP_TRIG_(t, Q_INIT_SIG) == Q_RET_TRAN) {
+
+            QS_BEGIN_(QS_QEP_STATE_INIT, QS::smObj_, this)
+                QS_OBJ_(this);                    // this state machine object
+                QS_FUN_(t);                        // the source (pseudo)state
+                QS_FUN_(m_temp);              // the target of the transition
+            QS_END_()
+
+            ip = s8_0;
+            path[0] = m_temp;
+            (void)QEP_TRIG_(m_temp, QEP_EMPTY_SIG_);       // find superstate
+            while (m_temp != t) {
+                ++ip;
+                path[ip] = m_temp;
+                (void)QEP_TRIG_(m_temp, QEP_EMPTY_SIG_);   // find superstate
+            }
+            m_temp = path[0];
+                                               // entry path must not overflow
+            Q_ASSERT(ip < QEP_MAX_NEST_DEPTH_);
+
+            do {       // retrace the entry path in reverse (correct) order...
+                QEP_ENTER_(path[ip]);                        // enter path[ip]
+                --ip;
+            } while (ip >= s8_0);
+
+            t = path[0];
+        }
+
+        QS_BEGIN_(QS_QEP_TRAN, QS::smObj_, this)
+            QS_TIME_();                                          // time stamp
+            QS_SIG_(e->sig);                        // the signal of the event
+            QS_OBJ_(this);                        // this state machine object
+            QS_FUN_(src);                      // the source of the transition
+            QS_FUN_(t);                                // the new active state
+        QS_END_()
+
+    }
+    else {                                             // transition not taken
+#ifdef Q_SPY
+        if (r == Q_RET_HANDLED) {
+
+            QS_BEGIN_(QS_QEP_INTERN_TRAN, QS::smObj_, this)
+                QS_TIME_();                                      // time stamp
+                QS_SIG_(e->sig);                    // the signal of the event
+                QS_OBJ_(this);                    // this state machine object
+                QS_FUN_(m_state);          // the state that handled the event
+            QS_END_()
+
+        }
+        else {
+
+            QS_BEGIN_(QS_QEP_IGNORED, QS::smObj_, this)
+                QS_TIME_();                                      // time stamp
+                QS_SIG_(e->sig);                    // the signal of the event
+                QS_OBJ_(this);                    // this state machine object
+                QS_FUN_(m_state);                         // the current state
+            QS_END_()
+
+        }
+#endif
+    }
+
+    m_state = t;                            // change the current active state
+    m_temp  = t;                           // mark the configuration as stable
+}
+
+QP_END_
+
+// "qf_pkg.h" ================================================================
+/// \brief Internal (package scope) QF/C++ interface.
+
+/// \brief helper macro to cast const away from an event pointer \a e_
+#define QF_EVT_CONST_CAST_(e_) const_cast<QEvt *>(e_)
+
+QP_BEGIN_
+                                               // QF-specific critical section
+#ifndef QF_CRIT_STAT_TYPE
+    /// \brief This is an internal macro for defining the critical section
+    /// status type.
+    ///
+    /// The purpose of this macro is to enable writing the same code for the
+    /// case when critical sectgion status type is defined and when it is not.
+    /// If the macro #QF_CRIT_STAT_TYPE is defined, this internal macro
+    /// provides the definition of the critical section status varaible.
+    /// Otherwise this macro is empty.
+    /// \sa #QF_CRIT_STAT_TYPE
+    ///
+    #define QF_CRIT_STAT_
+
+    /// \brief This is an internal macro for entering a critical section.
+    ///
+    /// The purpose of this macro is to enable writing the same code for the
+    /// case when critical sectgion status type is defined and when it is not.
+    /// If the macro #QF_CRIT_STAT_TYPE is defined, this internal macro
+    /// invokes #QF_CRIT_ENTRY passing the key variable as the parameter.
+    /// Otherwise #QF_CRIT_ENTRY is invoked with a dummy parameter.
+    /// \sa #QF_CRIT_ENTRY
+    ///
+    #define QF_CRIT_ENTRY_()    QF_CRIT_ENTRY(dummy)
+
+    /// \brief This is an internal macro for exiting a cricial section.
+    ///
+    /// The purpose of this macro is to enable writing the same code for the
+    /// case when critical sectgion status type is defined and when it is not.
+    /// If the macro #QF_CRIT_STAT_TYPE is defined, this internal macro
+    /// invokes #QF_CRIT_EXIT passing the key variable as the parameter.
+    /// Otherwise #QF_CRIT_EXIT is invoked with a dummy parameter.
+    /// \sa #QF_CRIT_EXIT
+    ///
+    #define QF_CRIT_EXIT_()     QF_CRIT_EXIT(dummy)
+
+#else
+    #define QF_CRIT_STAT_       QF_CRIT_STAT_TYPE critStat_;
+    #define QF_CRIT_ENTRY_()    QF_CRIT_ENTRY(critStat_)
+    #define QF_CRIT_EXIT_()     QF_CRIT_EXIT(critStat_)
+#endif
+
+// package-scope objects -----------------------------------------------------
+extern QTimeEvt *QF_timeEvtListHead_;  ///< head of linked list of time events
+extern QF_EPOOL_TYPE_ QF_pool_[QF_MAX_EPOOL];        ///< allocate event pools
+extern uint8_t QF_maxPool_;                  ///< # of initialized event pools
+extern QSubscrList *QF_subscrList_;             ///< the subscriber list array
+extern enum_t QF_maxSignal_;                 ///< the maximum published signal
+
+//............................................................................
+/// \brief Structure representing a free block in the Native QF Memory Pool
+/// \sa ::QMPool
+struct QFreeBlock {
+    QFreeBlock *m_next;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+// internal helper inline functions
+
+/// \brief access to the poolId_ of an event \a e
+inline uint8_t QF_EVT_POOL_ID_(QEvt const * const e) { return e->poolId_; }
+
+/// \brief access to the refCtr_ of an event \a e
+inline uint8_t QF_EVT_REF_CTR_(QEvt const * const e) { return e->refCtr_; }
+
+/// \brief increment the refCtr_ of an event \a e
+inline void QF_EVT_REF_CTR_INC_(QEvt const * const e) {
+    ++(QF_EVT_CONST_CAST_(e))->refCtr_;
+}
+
+/// \brief decrement the refCtr_ of an event \a e
+inline void QF_EVT_REF_CTR_DEC_(QEvt const * const e) {
+    --(QF_EVT_CONST_CAST_(e))->refCtr_;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// internal frequently used srongly-typed constants
+
+QTimeEvtCtr const tc_0 = static_cast<QTimeEvtCtr>(0);
+
+void     * const null_void = static_cast<void *>(0);
+QEvt const * const null_evt  = static_cast<QEvt const *>(0);
+QTimeEvt * const null_tevt = static_cast<QTimeEvt *>(0);
+QActive  * const null_act  = static_cast<QActive *>(0);
+
+QP_END_
+
+/// \brief access element at index \a i_ from the base pointer \a base_
+#define QF_PTR_AT_(base_, i_) (base_[i_])
+
+//////////////////////////////////////////////////////////////////////////////
+#ifdef Q_SPY                                   // QS software tracing enabled?
+
+    #if (QF_EQUEUE_CTR_SIZE == 1)
+
+        /// \brief Internal QS macro to output an unformatted event queue
+        /// counter data element
+        /// \note the counter size depends on the macro #QF_EQUEUE_CTR_SIZE.
+        #define QS_EQC_(ctr_)       QS::u8_(ctr_)
+    #elif (QF_EQUEUE_CTR_SIZE == 2)
+        #define QS_EQC_(ctr_)       QS::u16_(ctr_)
+    #elif (QF_EQUEUE_CTR_SIZE == 4)
+        #define QS_EQC_(ctr_)       QS::u32_(ctr_)
+    #else
+        #error "QF_EQUEUE_CTR_SIZE not defined"
+    #endif
+
+
+    #if (QF_EVENT_SIZ_SIZE == 1)
+
+        /// \brief Internal QS macro to output an unformatted event size
+        /// data element
+        /// \note the event size depends on the macro #QF_EVENT_SIZ_SIZE.
+        #define QS_EVS_(size_)      QS::u8_(size_)
+    #elif (QF_EVENT_SIZ_SIZE == 2)
+        #define QS_EVS_(size_)      QS::u16_(size_)
+    #elif (QF_EVENT_SIZ_SIZE == 4)
+        #define QS_EVS_(size_)      QS::u32_(size_)
+    #endif
+
+
+    #if (QF_MPOOL_SIZ_SIZE == 1)
+
+        /// \brief Internal QS macro to output an unformatted memory pool
+        /// block-size data element
+        /// \note the block-size depends on the macro #QF_MPOOL_SIZ_SIZE.
+        #define QS_MPS_(size_)      QS::u8_(size_)
+    #elif (QF_MPOOL_SIZ_SIZE == 2)
+        #define QS_MPS_(size_)      QS::u16_(size_)
+    #elif (QF_MPOOL_SIZ_SIZE == 4)
+        #define QS_MPS_(size_)      QS::u32_(size_)
+    #endif
+
+    #if (QF_MPOOL_CTR_SIZE == 1)
+
+        /// \brief Internal QS macro to output an unformatted memory pool
+        /// block-counter data element
+        /// \note the counter size depends on the macro #QF_MPOOL_CTR_SIZE.
+        #define QS_MPC_(ctr_)       QS::u8_(ctr_)
+    #elif (QF_MPOOL_CTR_SIZE == 2)
+        #define QS_MPC_(ctr_)       QS::u16_(ctr_)
+    #elif (QF_MPOOL_CTR_SIZE == 4)
+        #define QS_MPC_(ctr_)       QS::u32_(ctr_)
+    #endif
+
+
+    #if (QF_TIMEEVT_CTR_SIZE == 1)
+
+        /// \brief Internal QS macro to output an unformatted time event
+        /// tick-counter data element
+        /// \note the counter size depends on the macro #QF_TIMEEVT_CTR_SIZE.
+        #define QS_TEC_(ctr_)       QS::u8_(ctr_)
+    #elif (QF_TIMEEVT_CTR_SIZE == 2)
+        #define QS_TEC_(ctr_)       QS::u16_(ctr_)
+    #elif (QF_TIMEEVT_CTR_SIZE == 4)
+        #define QS_TEC_(ctr_)       QS::u32_(ctr_)
+    #endif
+
+#endif                                                                // Q_SPY
+
+// "qa_defer.cpp" ============================================================
+/// \brief QActive::defer() and QActive::recall() implementation.
+///
+
+QP_BEGIN_
+
+//............................................................................
+void QActive::defer(QEQueue * const eq, QEvt const * const e) const {
+    eq->postFIFO(e);
+}
+//............................................................................
+bool QActive::recall(QEQueue * const eq) {
+    QEvt const * const e = eq->get();  // try to get evt from deferred queue
+    bool const recalled = (e != null_evt);                 // event available?
+    if (recalled) {
+        postLIFO(e);      // post it to the front of the Active Object's queue
+
+        QF_CRIT_STAT_
+        QF_CRIT_ENTRY_();
+
+        if (QF_EVT_POOL_ID_(e) != u8_0) {            // is it a dynamic event?
+
+            // after posting to the AO's queue the event must be referenced
+            // at least twice: once in the deferred event queue (eq->get()
+            // did NOT decrement the reference counter) and once in the
+            // AO's event queue.
+            Q_ASSERT(QF_EVT_REF_CTR_(e) > u8_1);
+
+            // we need to decrement the reference counter once, to account
+            // for removing the event from the deferred event queue.
+            //
+            QF_EVT_REF_CTR_DEC_(e);         // decrement the reference counter
+        }
+
+        QF_CRIT_EXIT_();
+    }
+    return recalled;                                     // event not recalled
+}
+
+QP_END_
+
+
+// "qa_fifo.cpp" =============================================================
+/// \brief QActive::postFIFO() implementation.
+///
+/// \note this source file is only included in the QF library when the native
+/// QF active object queue is used (instead of a message queue of an RTOS).
+
+QP_BEGIN_
+
+//............................................................................
+#ifndef Q_SPY
+void QActive::postFIFO(QEvt const * const e) {
+#else
+void QActive::postFIFO(QEvt const * const e, void const * const sender) {
+#endif
+
+    QF_CRIT_STAT_
+    QF_CRIT_ENTRY_();
+
+    QS_BEGIN_NOCRIT_(QS_QF_ACTIVE_POST_FIFO, QS::aoObj_, this)
+        QS_TIME_();                                               // timestamp
+        QS_OBJ_(sender);                                  // the sender object
+        QS_SIG_(e->sig);                            // the signal of the event
+        QS_OBJ_(this);                                   // this active object
+        QS_U8_(QF_EVT_POOL_ID_(e));                // the pool Id of the event
+        QS_U8_(QF_EVT_REF_CTR_(e));              // the ref count of the event
+        QS_EQC_(m_eQueue.m_nFree);                   // number of free entries
+        QS_EQC_(m_eQueue.m_nMin);                // min number of free entries
+    QS_END_NOCRIT_()
+
+    if (QF_EVT_POOL_ID_(e) != u8_0) {                // is it a dynamic event?
+        QF_EVT_REF_CTR_INC_(e);             // increment the reference counter
+    }
+
+    if (m_eQueue.m_frontEvt == null_evt) {              // is the queue empty?
+        m_eQueue.m_frontEvt = e;                     // deliver event directly
+        QACTIVE_EQUEUE_SIGNAL_(this);                // signal the event queue
+    }
+    else {               // queue is not empty, leave event in the ring-buffer
+                                        // queue must accept all posted events
+        Q_ASSERT(m_eQueue.m_nFree != static_cast<QEQueueCtr>(0));
+                              // insert event pointer e into the buffer (FIFO)
+        QF_PTR_AT_(m_eQueue.m_ring, m_eQueue.m_head) = e;
+        if (m_eQueue.m_head == static_cast<QEQueueCtr>(0)) {  // need to wrap?
+            m_eQueue.m_head = m_eQueue.m_end;                   // wrap around
+        }
+        --m_eQueue.m_head;
+
+        --m_eQueue.m_nFree;                    // update number of free events
+        if (m_eQueue.m_nMin > m_eQueue.m_nFree) {
+            m_eQueue.m_nMin = m_eQueue.m_nFree;       // update minimum so far
+        }
+    }
+    QF_CRIT_EXIT_();
+}
+
+QP_END_
+
+// "qa_get_.cpp" =============================================================
+/// \brief QActive::get_() and QF::getQueueMargin() definitions.
+///
+/// \note this source file is only included in the QF library when the native
+/// QF active object queue is used (instead of a message queue of an RTOS).
+
+QP_BEGIN_
+
+//............................................................................
+QEvt const *QActive::get_(void) {
+    QF_CRIT_STAT_
+    QF_CRIT_ENTRY_();
+
+    QACTIVE_EQUEUE_WAIT_(this);           // wait for event to arrive directly
+
+    QEvt const *e = m_eQueue.m_frontEvt;
+
+    if (m_eQueue.m_nFree != m_eQueue.m_end) { //any events in the ring buffer?
+                                                 // remove event from the tail
+        m_eQueue.m_frontEvt = QF_PTR_AT_(m_eQueue.m_ring, m_eQueue.m_tail);
+        if (m_eQueue.m_tail == static_cast<QEQueueCtr>(0)) {  // need to wrap?
+            m_eQueue.m_tail = m_eQueue.m_end;                   // wrap around
+        }
+        --m_eQueue.m_tail;
+
+        ++m_eQueue.m_nFree;          // one more free event in the ring buffer
+
+        QS_BEGIN_NOCRIT_(QS_QF_ACTIVE_GET, QS::aoObj_, this)
+            QS_TIME_();                                           // timestamp
+            QS_SIG_(e->sig);                       // the signal of this event
+            QS_OBJ_(this);                               // this active object
+            QS_U8_(QF_EVT_POOL_ID_(e));            // the pool Id of the event
+            QS_U8_(QF_EVT_REF_CTR_(e));          // the ref count of the event
+            QS_EQC_(m_eQueue.m_nFree);               // number of free entries
+        QS_END_NOCRIT_()
+    }
+    else {
+        m_eQueue.m_frontEvt = null_evt;             // the queue becomes empty
+        QACTIVE_EQUEUE_ONEMPTY_(this);
+
+        QS_BEGIN_NOCRIT_(QS_QF_ACTIVE_GET_LAST, QS::aoObj_, this)
+            QS_TIME_();                                           // timestamp
+            QS_SIG_(e->sig);                       // the signal of this event
+            QS_OBJ_(this);                               // this active object
+            QS_U8_(QF_EVT_POOL_ID_(e));            // the pool Id of the event
+            QS_U8_(QF_EVT_REF_CTR_(e));          // the ref count of the event
+        QS_END_NOCRIT_()
+    }
+    QF_CRIT_EXIT_();
+    return e;
+}
+//............................................................................
+uint32_t QF::getQueueMargin(uint8_t const prio) {
+    Q_REQUIRE((prio <= static_cast<uint8_t>(QF_MAX_ACTIVE))
+              && (active_[prio] != static_cast<QActive *>(0)));
+
+    QF_CRIT_STAT_
+    QF_CRIT_ENTRY_();
+    uint32_t margin = static_cast<uint32_t>(active_[prio]->m_eQueue.m_nMin);
+    QF_CRIT_EXIT_();
+
+    return margin;
+}
+
+QP_END_
+
+// "qa_lifo.cpp" =============================================================
+/// \brief QActive::postLIFO() implementation.
+///
+/// \note this source file is only included in the QF library when the native
+/// QF active object queue is used (instead of a message queue of an RTOS).
+
+QP_BEGIN_
+
+//............................................................................
+void QActive::postLIFO(QEvt const * const e) {
+    QF_CRIT_STAT_
+    QF_CRIT_ENTRY_();
+
+    QS_BEGIN_NOCRIT_(QS_QF_ACTIVE_POST_LIFO, QS::aoObj_, this)
+        QS_TIME_();                                               // timestamp
+        QS_SIG_(e->sig);                           // the signal of this event
+        QS_OBJ_(this);                                   // this active object
+        QS_U8_(QF_EVT_POOL_ID_(e));                // the pool Id of the event
+        QS_U8_(QF_EVT_REF_CTR_(e));              // the ref count of the event
+        QS_EQC_(m_eQueue.m_nFree);                   // number of free entries
+        QS_EQC_(m_eQueue.m_nMin);                // min number of free entries
+    QS_END_NOCRIT_()
+
+    if (QF_EVT_POOL_ID_(e) != u8_0) {                // is it a dynamic event?
+        QF_EVT_REF_CTR_INC_(e);             // increment the reference counter
+    }
+
+    if (m_eQueue.m_frontEvt == null_evt) {              // is the queue empty?
+        m_eQueue.m_frontEvt = e;                     // deliver event directly
+        QACTIVE_EQUEUE_SIGNAL_(this);                // signal the event queue
+    }
+    else {               // queue is not empty, leave event in the ring-buffer
+                                        // queue must accept all posted events
+        Q_ASSERT(m_eQueue.m_nFree != static_cast<QEQueueCtr>(0));
+
+        ++m_eQueue.m_tail;
+        if (m_eQueue.m_tail == m_eQueue.m_end) {     // need to wrap the tail?
+            m_eQueue.m_tail = static_cast<QEQueueCtr>(0);       // wrap around
+        }
+
+        QF_PTR_AT_(m_eQueue.m_ring, m_eQueue.m_tail) = m_eQueue.m_frontEvt;
+        m_eQueue.m_frontEvt = e;                         // put event to front
+
+        --m_eQueue.m_nFree;                    // update number of free events
+        if (m_eQueue.m_nMin > m_eQueue.m_nFree) {
+            m_eQueue.m_nMin = m_eQueue.m_nFree;       // update minimum so far
+        }
+    }
+    QF_CRIT_EXIT_();
+}
+
+QP_END_
+
+// "qa_sub.cpp" ==============================================================
+/// \brief QActive::subscribe() implementation.
+
+QP_BEGIN_
+
+//............................................................................
+void QActive::subscribe(enum_t const sig) const {
+    uint8_t p = m_prio;
+    Q_REQUIRE((Q_USER_SIG <= sig)
+              && (sig < QF_maxSignal_)
+              && (u8_0 < p) && (p <= static_cast<uint8_t>(QF_MAX_ACTIVE))
+              && (QF::active_[p] == this));
+
+    uint8_t const i = Q_ROM_BYTE(QF_div8Lkup[p]);
+
+    QF_CRIT_STAT_
+    QF_CRIT_ENTRY_();
+
+    QS_BEGIN_NOCRIT_(QS_QF_ACTIVE_SUBSCRIBE, QS::aoObj_, this)
+        QS_TIME_();                                               // timestamp
+        QS_SIG_(sig);                              // the signal of this event
+        QS_OBJ_(this);                                   // this active object
+    QS_END_NOCRIT_()
+                                                       // set the priority bit
+    QF_PTR_AT_(QF_subscrList_, sig).m_bits[i] |= Q_ROM_BYTE(QF_pwr2Lkup[p]);
+    QF_CRIT_EXIT_();
+}
+
+QP_END_
+
+// "qa_usub.cpp" =============================================================
+/// \brief QActive::unsubscribe() implementation.
+
+QP_BEGIN_
+
+//............................................................................
+void QActive::unsubscribe(enum_t const sig) const {
+    uint8_t p = m_prio;
+    Q_REQUIRE((Q_USER_SIG <= sig)
+              && (sig < QF_maxSignal_)
+              && (u8_0 < p) && (p <= static_cast<uint8_t>(QF_MAX_ACTIVE))
+              && (QF::active_[p] == this));
+
+    uint8_t const i = Q_ROM_BYTE(QF_div8Lkup[p]);
+
+    QF_CRIT_STAT_
+    QF_CRIT_ENTRY_();
+
+    QS_BEGIN_NOCRIT_(QS_QF_ACTIVE_UNSUBSCRIBE, QS::aoObj_, this)
+        QS_TIME_();                                               // timestamp
+        QS_SIG_(sig);                              // the signal of this event
+        QS_OBJ_(this);                                   // this active object
+    QS_END_NOCRIT_()
+                                                     // clear the priority bit
+    QF_PTR_AT_(QF_subscrList_,sig).m_bits[i] &= Q_ROM_BYTE(QF_invPwr2Lkup[p]);
+    QF_CRIT_EXIT_();
+}
+
+QP_END_
+
+// "qa_usuba.cpp" ============================================================
+/// \brief QActive::unsubscribeAll() implementation.
+
+QP_BEGIN_
+
+//............................................................................
+void QActive::unsubscribeAll(void) const {
+    uint8_t const p = m_prio;
+    Q_REQUIRE((u8_0 < p) && (p <= static_cast<uint8_t>(QF_MAX_ACTIVE))
+              && (QF::active_[p] == this));
+
+    uint8_t const i = Q_ROM_BYTE(QF_div8Lkup[p]);
+
+    enum_t sig;
+    for (sig = Q_USER_SIG; sig < QF_maxSignal_; ++sig) {
+        QF_CRIT_STAT_
+        QF_CRIT_ENTRY_();
+        if ((QF_PTR_AT_(QF_subscrList_, sig).m_bits[i]
+             & Q_ROM_BYTE(QF_pwr2Lkup[p])) != u8_0)
+        {
+
+            QS_BEGIN_NOCRIT_(QS_QF_ACTIVE_UNSUBSCRIBE, QS::aoObj_, this)
+                QS_TIME_();                                       // timestamp
+                QS_SIG_(sig);                      // the signal of this event
+                QS_OBJ_(this);                           // this active object
+            QS_END_NOCRIT_()
+                                                     // clear the priority bit
+            QF_PTR_AT_(QF_subscrList_, sig).m_bits[i] &=
+                Q_ROM_BYTE(QF_invPwr2Lkup[p]);
+        }
+        QF_CRIT_EXIT_();
+    }
+}
+
+QP_END_
+
+// "qeq_fifo.cpp" ============================================================
+/// \brief QEQueue::postFIFO() implementation.
+
+QP_BEGIN_
+
+//............................................................................
+void QEQueue::postFIFO(QEvt const * const e) {
+    QF_CRIT_STAT_
+    QF_CRIT_ENTRY_();
+
+    QS_BEGIN_NOCRIT_(QS_QF_EQUEUE_POST_FIFO, QS::eqObj_, this)
+        QS_TIME_();                                               // timestamp
+        QS_SIG_(e->sig);                           // the signal of this event
+        QS_OBJ_(this);                                    // this queue object
+        QS_U8_(QF_EVT_POOL_ID_(e));                // the pool Id of the event
+        QS_U8_(QF_EVT_REF_CTR_(e));              // the ref count of the event
+        QS_EQC_(m_nFree);                            // number of free entries
+        QS_EQC_(m_nMin);                         // min number of free entries
+    QS_END_NOCRIT_()
+
+    if (QF_EVT_POOL_ID_(e) != u8_0) {                // is it a dynamic event?
+        QF_EVT_REF_CTR_INC_(e);             // increment the reference counter
+    }
+
+    if (m_frontEvt == null_evt) {                       // is the queue empty?
+        m_frontEvt = e;                              // deliver event directly
+    }
+    else {               // queue is not empty, leave event in the ring-buffer
+               // the queue must be able to accept the event (cannot overflow)
+        Q_ASSERT(m_nFree != static_cast<QEQueueCtr>(0));
+
+        QF_PTR_AT_(m_ring, m_head) = e; // insert event into the buffer (FIFO)
+        if (m_head == static_cast<QEQueueCtr>(0)) {           // need to wrap?
+            m_head = m_end;                                     // wrap around
+        }
+        --m_head;
+
+        --m_nFree;                             // update number of free events
+        if (m_nMin > m_nFree) {
+            m_nMin = m_nFree;                         // update minimum so far
+        }
+    }
+    QF_CRIT_EXIT_();
+}
+
+QP_END_
+
+// "qeq_get.cpp" =============================================================
+/// \brief QEQueue::get() implementation.
+
+QP_BEGIN_
+
+//............................................................................
+QEvt const *QEQueue::get(void) {
+    QEvt const *e;
+    QF_CRIT_STAT_
+
+    QF_CRIT_ENTRY_();
+    if (m_frontEvt == null_evt) {                       // is the queue empty?
+        e = null_evt;                       // no event available at this time
+    }
+    else {
+        e = m_frontEvt;
+
+        if (m_nFree != m_end) {          // any events in the the ring buffer?
+            m_frontEvt = QF_PTR_AT_(m_ring, m_tail);   // remove from the tail
+            if (m_tail == static_cast<QEQueueCtr>(0)) {       // need to wrap?
+                m_tail = m_end;                                 // wrap around
+            }
+            --m_tail;
+
+            ++m_nFree;               // one more free event in the ring buffer
+
+            QS_BEGIN_NOCRIT_(QS_QF_EQUEUE_GET, QS::eqObj_, this)
+                QS_TIME_();                                       // timestamp
+                QS_SIG_(e->sig);                   // the signal of this event
+                QS_OBJ_(this);                            // this queue object
+                QS_U8_(QF_EVT_POOL_ID_(e));        // the pool Id of the event
+                QS_U8_(QF_EVT_REF_CTR_(e));      // the ref count of the event
+                QS_EQC_(m_nFree);                    // number of free entries
+            QS_END_NOCRIT_()
+        }
+        else {
+            m_frontEvt = null_evt;                  // the queue becomes empty
+
+            QS_BEGIN_NOCRIT_(QS_QF_EQUEUE_GET_LAST, QS::eqObj_, this)
+                QS_TIME_();                                       // timestamp
+                QS_SIG_(e->sig);                   // the signal of this event
+                QS_OBJ_(this);                            // this queue object
+                QS_U8_(QF_EVT_POOL_ID_(e));        // the pool Id of the event
+                QS_U8_(QF_EVT_REF_CTR_(e));      // the ref count of the event
+            QS_END_NOCRIT_()
+        }
+    }
+    QF_CRIT_EXIT_();
+    return e;
+}
+
+QP_END_
+
+// "qeq_init.cpp" ============================================================
+/// \brief QEQueue::init() implementation.
+
+QP_BEGIN_
+
+//............................................................................
+void QEQueue::init(QEvt const *qSto[], QEQueueCtr const qLen) {
+    m_frontEvt = null_evt;                           // no events in the queue
+    m_ring     = &qSto[0];
+    m_end      = qLen;
+    m_head     = static_cast<QEQueueCtr>(0);
+    m_tail     = static_cast<QEQueueCtr>(0);
+    m_nFree    = qLen;
+    m_nMin     = qLen;
+
+    QS_CRIT_STAT_
+    QS_BEGIN_(QS_QF_EQUEUE_INIT, QS::eqObj_, this)
+        QS_OBJ_(qSto);                                  // this QEQueue object
+        QS_EQC_(qLen);                              // the length of the queue
+    QS_END_()
+}
+
+QP_END_
+
+// "qeq_lifo.cpp" ============================================================
+/// \brief QEQueue::postLIFO() implementation.
+
+QP_BEGIN_
+
+//............................................................................
+void QEQueue::postLIFO(QEvt const * const e) {
+    QF_CRIT_STAT_
+    QF_CRIT_ENTRY_();
+
+    QS_BEGIN_NOCRIT_(QS_QF_EQUEUE_POST_LIFO, QS::eqObj_, this)
+        QS_TIME_();                                               // timestamp
+        QS_SIG_(e->sig);                           // the signal of this event
+        QS_OBJ_(this);                                    // this queue object
+        QS_U8_(QF_EVT_POOL_ID_(e));                // the pool Id of the event
+        QS_U8_(QF_EVT_REF_CTR_(e));              // the ref count of the event
+        QS_EQC_(m_nFree);                            // number of free entries
+        QS_EQC_(m_nMin);                         // min number of free entries
+    QS_END_NOCRIT_()
+
+    if (QF_EVT_POOL_ID_(e) != u8_0) {                // is it a dynamic event?
+        QF_EVT_REF_CTR_INC_(e);             // increment the reference counter
+    }
+
+    if (m_frontEvt != null_evt) {                   // is the queue not empty?
+               // the queue must be able to accept the event (cannot overflow)
+        Q_ASSERT(m_nFree != static_cast<QEQueueCtr>(0));
+
+        ++m_tail;
+        if (m_tail == m_end) {                       // need to wrap the tail?
+            m_tail = static_cast<QEQueueCtr>(0);                // wrap around
+        }
+
+        QF_PTR_AT_(m_ring, m_tail) = m_frontEvt;   // buffer the old front evt
+
+        --m_nFree;                             // update number of free events
+        if (m_nMin > m_nFree) {
+            m_nMin = m_nFree;                         // update minimum so far
+        }
+    }
+
+    m_frontEvt = e;                        // stick the new event to the front
+
+    QF_CRIT_EXIT_();
+}
+
+QP_END_
+
+// "qf_act.cpp" ==============================================================
+/// \brief QF::active_[], QF::getVersion(), and QF::add_()/QF::remove_()
+/// implementation.
+
+QP_BEGIN_
+
+// public objects ------------------------------------------------------------
+QActive *QF::active_[QF_MAX_ACTIVE + 1];        // to be used by QF ports only
+uint8_t QF_intLockNest_;                       // interrupt-lock nesting level
+
+//............................................................................
+char_t const Q_ROM * Q_ROM_VAR QF::getVersion(void) {
+    uint8_t const u8_zero = static_cast<uint8_t>('0');
+    static char_t const Q_ROM Q_ROM_VAR version[] = {
+        static_cast<char_t>(((QP_VERSION >> 12) & 0xFU) + u8_zero),
+        static_cast<char_t>('.'),
+        static_cast<char_t>(((QP_VERSION >>  8) & 0xFU) + u8_zero),
+        static_cast<char_t>('.'),
+        static_cast<char_t>(((QP_VERSION >>  4) & 0xFU) + u8_zero),
+        static_cast<char_t>((QP_VERSION         & 0xFU) + u8_zero),
+        static_cast<char_t>('\0')
+    };
+    return version;
+}
+//............................................................................
+void QF::add_(QActive * const a) {
+    uint8_t p = a->m_prio;
+
+    Q_REQUIRE((u8_0 < p) && (p <= static_cast<uint8_t>(QF_MAX_ACTIVE))
+              && (active_[p] == static_cast<QActive *>(0)));
+
+    QF_CRIT_STAT_
+    QF_CRIT_ENTRY_();
+
+    active_[p] = a;            // registger the active object at this priority
+
+    QS_BEGIN_NOCRIT_(QS_QF_ACTIVE_ADD, QS::aoObj_, a)
+        QS_TIME_();                                               // timestamp
+        QS_OBJ_(a);                                       // the active object
+        QS_U8_(p);                        // the priority of the active object
+    QS_END_NOCRIT_()
+
+    QF_CRIT_EXIT_();
+}
+//............................................................................
+void QF::remove_(QActive const * const a) {
+    uint8_t p = a->m_prio;
+
+    Q_REQUIRE((u8_0 < p) && (p <= static_cast<uint8_t>(QF_MAX_ACTIVE))
+              && (active_[p] == a));
+
+    QF_CRIT_STAT_
+    QF_CRIT_ENTRY_();
+
+    active_[p] = static_cast<QActive *>(0);      // free-up the priority level
+
+    QS_BEGIN_NOCRIT_(QS_QF_ACTIVE_REMOVE, QS::aoObj_, a)
+        QS_TIME_();                                               // timestamp
+        QS_OBJ_(a);                                       // the active object
+        QS_U8_(p);                        // the priority of the active object
+    QS_END_NOCRIT_()
+
+    QF_CRIT_EXIT_();
+}
+
+QP_END_
+
+
+// "qf_gc.cpp" ===============================================================
+/// \brief QF::gc() implementation.
+
+QP_BEGIN_
+
+//............................................................................
+void QF::gc(QEvt const * const e) {
+    if (QF_EVT_POOL_ID_(e) != u8_0) {                // is it a dynamic event?
+        QF_CRIT_STAT_
+        QF_CRIT_ENTRY_();
+
+        if (QF_EVT_REF_CTR_(e) > u8_1) {     // isn't this the last reference?
+            QF_EVT_REF_CTR_DEC_(e);               // decrement the ref counter
+
+            QS_BEGIN_NOCRIT_(QS_QF_GC_ATTEMPT, null_void, null_void)
+                QS_TIME_();                                       // timestamp
+                QS_SIG_(e->sig);                    // the signal of the event
+                QS_U8_(QF_EVT_POOL_ID_(e));        // the pool Id of the event
+                QS_U8_(QF_EVT_REF_CTR_(e));      // the ref count of the event
+            QS_END_NOCRIT_()
+
+            QF_CRIT_EXIT_();
+        }
+        else {         // this is the last reference to this event, recycle it
+            uint8_t idx = static_cast<uint8_t>(QF_EVT_POOL_ID_(e) - u8_1);
+
+            QS_BEGIN_NOCRIT_(QS_QF_GC, null_void, null_void)
+                QS_TIME_();                                       // timestamp
+                QS_SIG_(e->sig);                    // the signal of the event
+                QS_U8_(QF_EVT_POOL_ID_(e));        // the pool Id of the event
+                QS_U8_(QF_EVT_REF_CTR_(e));      // the ref count of the event
+            QS_END_NOCRIT_()
+
+            QF_CRIT_EXIT_();
+
+            Q_ASSERT(idx < QF_maxPool_);
+
+#ifdef Q_EVT_VIRTUAL
+            QF_EVT_CONST_CAST_(e)->~QEvt();        // xtor, cast 'const' away,
+                             // which is legitimate, because it's a pool event
+#endif
+                  // cast 'const' away, which is OK, because it's a pool event
+            QF_EPOOL_PUT_(QF_pool_[idx], QF_EVT_CONST_CAST_(e));
+        }
+    }
+}
+
+QP_END_
+
+// "qf_log2.cpp" =============================================================
+/// \brief QF_log2Lkup[] implementation.
+
+QP_BEGIN_
+
+// Global objects ------------------------------------------------------------
+uint8_t const Q_ROM Q_ROM_VAR QF_log2Lkup[256] = {
+    static_cast<uint8_t>(0),
+    static_cast<uint8_t>(1),
+    static_cast<uint8_t>(2), static_cast<uint8_t>(2),
+    static_cast<uint8_t>(3), static_cast<uint8_t>(3), static_cast<uint8_t>(3),
+    static_cast<uint8_t>(3),
+    static_cast<uint8_t>(4), static_cast<uint8_t>(4), static_cast<uint8_t>(4),
+    static_cast<uint8_t>(4), static_cast<uint8_t>(4), static_cast<uint8_t>(4),
+    static_cast<uint8_t>(4), static_cast<uint8_t>(4),
+    static_cast<uint8_t>(5), static_cast<uint8_t>(5), static_cast<uint8_t>(5),
+    static_cast<uint8_t>(5), static_cast<uint8_t>(5), static_cast<uint8_t>(5),
+    static_cast<uint8_t>(5), static_cast<uint8_t>(5), static_cast<uint8_t>(5),
+    static_cast<uint8_t>(5), static_cast<uint8_t>(5), static_cast<uint8_t>(5),
+    static_cast<uint8_t>(5), static_cast<uint8_t>(5), static_cast<uint8_t>(5),
+    static_cast<uint8_t>(5),
+    static_cast<uint8_t>(6), static_cast<uint8_t>(6), static_cast<uint8_t>(6),
+    static_cast<uint8_t>(6), static_cast<uint8_t>(6), static_cast<uint8_t>(6),
+    static_cast<uint8_t>(6), static_cast<uint8_t>(6), static_cast<uint8_t>(6),
+    static_cast<uint8_t>(6), static_cast<uint8_t>(6), static_cast<uint8_t>(6),
+    static_cast<uint8_t>(6), static_cast<uint8_t>(6), static_cast<uint8_t>(6),
+    static_cast<uint8_t>(6), static_cast<uint8_t>(6), static_cast<uint8_t>(6),
+    static_cast<uint8_t>(6), static_cast<uint8_t>(6), static_cast<uint8_t>(6),
+    static_cast<uint8_t>(6), static_cast<uint8_t>(6), static_cast<uint8_t>(6),
+    static_cast<uint8_t>(6), static_cast<uint8_t>(6), static_cast<uint8_t>(6),
+    static_cast<uint8_t>(6), static_cast<uint8_t>(6), static_cast<uint8_t>(6),
+    static_cast<uint8_t>(6), static_cast<uint8_t>(6),
+    static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7),
+    static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7),
+    static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7),
+    static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7),
+    static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7),
+    static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7),
+    static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7),
+    static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7),
+    static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7),
+    static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7),
+    static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7),
+    static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7),
+    static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7),
+    static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7),
+    static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7),
+    static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7),
+    static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7),
+    static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7),
+    static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7),
+    static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7),
+    static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7),
+    static_cast<uint8_t>(7),
+    static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8),
+    static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8),
+    static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8),
+    static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8),
+    static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8),
+    static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8),
+    static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8),
+    static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8),
+    static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8),
+    static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8),
+    static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8),
+    static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8),
+    static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8),
+    static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8),
+    static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8),
+    static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8),
+    static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8),
+    static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8),
+    static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8),
+    static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8),
+    static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8),
+    static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8),
+    static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8),
+    static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8),
+    static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8),
+    static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8),
+    static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8),
+    static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8),
+    static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8),
+    static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8),
+    static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8),
+    static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8),
+    static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8),
+    static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8),
+    static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8),
+    static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8),
+    static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8),
+    static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8),
+    static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8),
+    static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8),
+    static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8),
+    static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8),
+    static_cast<uint8_t>(8), static_cast<uint8_t>(8)
+};
+
+QP_END_
+
+// "qf_new.cpp" ==============================================================
+/// \brief QF::new_() implementation.
+
+QP_BEGIN_
+
+//............................................................................
+QEvt *QF::new_(QEvtSize const evtSize, enum_t const sig) {
+                    // find the pool id that fits the requested event size ...
+    uint8_t idx = u8_0;
+    while (evtSize
+           > static_cast<QEvtSize>(QF_EPOOL_EVENT_SIZE_(QF_pool_[idx])))
+    {
+        ++idx;
+        Q_ASSERT(idx < QF_maxPool_);     // cannot run out of registered pools
+    }
+
+    QS_CRIT_STAT_
+    QS_BEGIN_(QS_QF_NEW, null_void, null_void)
+        QS_TIME_();                                               // timestamp
+        QS_EVS_(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);
+    Q_ASSERT(e != static_cast<QEvt *>(0));// pool must not run out of events
+
+    e->sig     = static_cast<QSignal>(sig);       // set signal for this event
+    e->poolId_ = static_cast<uint8_t>(idx + u8_1); // store pool ID in the evt
+    e->refCtr_ = u8_0;                       // set the reference counter to 0
+
+    return e;
+}
+
+QP_END_
+
+// "qf_pool.cpp" =============================================================
+/// \brief QF_pool_[] and QF_maxPool_ definition, QF::poolInit()
+/// implementation.
+
+QP_BEGIN_
+
+// Package-scope objects -----------------------------------------------------
+QF_EPOOL_TYPE_ QF_pool_[QF_MAX_EPOOL];             // allocate the event pools
+uint8_t QF_maxPool_;                      // number of initialized event pools
+
+//............................................................................
+void QF::poolInit(void * const poolSto,
+                  uint32_t const poolSize, uint32_t const evtSize)
+{
+                         // cannot exceed the number of available memory pools
+    Q_REQUIRE(QF_maxPool_ < static_cast<uint8_t>(Q_DIM(QF_pool_)));
+               // please initialize event pools in ascending order of evtSize:
+    Q_REQUIRE((QF_maxPool_ == u8_0)
+              || (QF_EPOOL_EVENT_SIZE_(QF_pool_[QF_maxPool_ - u8_1])
+                  < evtSize));
+    QF_EPOOL_INIT_(QF_pool_[QF_maxPool_], poolSto, poolSize, evtSize);
+    ++QF_maxPool_;                                            // one more pool
+}
+
+QP_END_
+
+
+// "qf_psini.cpp" ============================================================
+/// \brief QF_subscrList_ and QF_maxSignal_ definition, QF::psInit()
+/// implementation.
+
+QP_BEGIN_
+
+// Package-scope objects -----------------------------------------------------
+QSubscrList *QF_subscrList_;
+enum_t QF_maxSignal_;
+
+//............................................................................
+void QF::psInit(QSubscrList * const subscrSto, uint32_t const maxSignal) {
+    QF_subscrList_ = subscrSto;
+    QF_maxSignal_  = static_cast<enum_t>(maxSignal);
+}
+
+QP_END_
+
+// "qf_pspub.cpp" ============================================================
+/// \brief QF::publish() implementation.
+
+QP_BEGIN_
+
+//............................................................................
+#ifndef Q_SPY
+void QF::publish(QEvt const * const e) {
+#else
+void QF::publish(QEvt const * const e, void const * const sender) {
+#endif
+         // make sure that the published signal is within the configured range
+    Q_REQUIRE(static_cast<enum_t>(e->sig) < QF_maxSignal_);
+
+    QF_CRIT_STAT_
+    QF_CRIT_ENTRY_();
+
+    QS_BEGIN_NOCRIT_(QS_QF_PUBLISH, null_void, null_void)
+        QS_TIME_();                                           // the timestamp
+        QS_OBJ_(sender);                                  // the sender object
+        QS_SIG_(e->sig);                            // the signal of the event
+        QS_U8_(QF_EVT_POOL_ID_(e));                // the pool Id of the event
+        QS_U8_(QF_EVT_REF_CTR_(e));              // the ref count of the event
+    QS_END_NOCRIT_()
+
+    if (QF_EVT_POOL_ID_(e) != u8_0) {                // is it a dynamic event?
+        QF_EVT_REF_CTR_INC_(e);     // increment the reference counter, NOTE01
+    }
+    QF_CRIT_EXIT_();
+
+#if (QF_MAX_ACTIVE <= 8)
+    uint8_t tmp = QF_PTR_AT_(QF_subscrList_, e->sig).m_bits[0];
+    while (tmp != u8_0) {
+        uint8_t p = Q_ROM_BYTE(QF_log2Lkup[tmp]);
+        tmp &= Q_ROM_BYTE(QF_invPwr2Lkup[p]);      // clear the subscriber bit
+        Q_ASSERT(active_[p] != static_cast<QActive *>(0));//must be registered
+
+                           // POST() asserts internally if the queue overflows
+        active_[p]->POST(e, sender);
+    }
+#else
+                                                // number of bytes in the list
+    uint8_t i = QF_SUBSCR_LIST_SIZE;
+    do {                       // go through all bytes in the subsciption list
+        --i;
+        uint8_t tmp = QF_PTR_AT_(QF_subscrList_, e->sig).m_bits[i];
+        while (tmp != u8_0) {
+            uint8_t p = Q_ROM_BYTE(QF_log2Lkup[tmp]);
+            tmp &= Q_ROM_BYTE(QF_invPwr2Lkup[p]);  // clear the subscriber bit
+                                                        // adjust the priority
+            p = static_cast<uint8_t>(p + static_cast<uint8_t>(i << 3));
+            Q_ASSERT(active_[p] != static_cast<QActive *>(0));   // registered
+
+                           // POST() asserts internally if the queue overflows
+            active_[p]->POST(e, sender);
+        }
+    } while (i != u8_0);
+#endif
+
+    gc(e);                            // run the garbage collector, see NOTE01
+}
+
+QP_END_
+
+
+// "qf_pwr2.cpp" =============================================================
+/// \brief QF_pwr2Lkup[], QF_invPwr2Lkup[], and QF_div8Lkup[] definitions.
+
+QP_BEGIN_
+
+// Global objects ------------------------------------------------------------
+uint8_t const Q_ROM Q_ROM_VAR QF_pwr2Lkup[65] = {
+    static_cast<uint8_t>(0x00),                             // unused location
+    static_cast<uint8_t>(0x01), static_cast<uint8_t>(0x02),
+    static_cast<uint8_t>(0x04), static_cast<uint8_t>(0x08),
+    static_cast<uint8_t>(0x10), static_cast<uint8_t>(0x20),
+    static_cast<uint8_t>(0x40), static_cast<uint8_t>(0x80),
+    static_cast<uint8_t>(0x01), static_cast<uint8_t>(0x02),
+    static_cast<uint8_t>(0x04), static_cast<uint8_t>(0x08),
+    static_cast<uint8_t>(0x10), static_cast<uint8_t>(0x20),
+    static_cast<uint8_t>(0x40), static_cast<uint8_t>(0x80),
+    static_cast<uint8_t>(0x01), static_cast<uint8_t>(0x02),
+    static_cast<uint8_t>(0x04), static_cast<uint8_t>(0x08),
+    static_cast<uint8_t>(0x10), static_cast<uint8_t>(0x20),
+    static_cast<uint8_t>(0x40), static_cast<uint8_t>(0x80),
+    static_cast<uint8_t>(0x01), static_cast<uint8_t>(0x02),
+    static_cast<uint8_t>(0x04), static_cast<uint8_t>(0x08),
+    static_cast<uint8_t>(0x10), static_cast<uint8_t>(0x20),
+    static_cast<uint8_t>(0x40), static_cast<uint8_t>(0x80),
+    static_cast<uint8_t>(0x01), static_cast<uint8_t>(0x02),
+    static_cast<uint8_t>(0x04), static_cast<uint8_t>(0x08),
+    static_cast<uint8_t>(0x10), static_cast<uint8_t>(0x20),
+    static_cast<uint8_t>(0x40), static_cast<uint8_t>(0x80),
+    static_cast<uint8_t>(0x01), static_cast<uint8_t>(0x02),
+    static_cast<uint8_t>(0x04), static_cast<uint8_t>(0x08),
+    static_cast<uint8_t>(0x10), static_cast<uint8_t>(0x20),
+    static_cast<uint8_t>(0x40), static_cast<uint8_t>(0x80),
+    static_cast<uint8_t>(0x01), static_cast<uint8_t>(0x02),
+    static_cast<uint8_t>(0x04), static_cast<uint8_t>(0x08),
+    static_cast<uint8_t>(0x10), static_cast<uint8_t>(0x20),
+    static_cast<uint8_t>(0x40), static_cast<uint8_t>(0x80),
+    static_cast<uint8_t>(0x01), static_cast<uint8_t>(0x02),
+    static_cast<uint8_t>(0x04), static_cast<uint8_t>(0x08),
+    static_cast<uint8_t>(0x10), static_cast<uint8_t>(0x20),
+    static_cast<uint8_t>(0x40), static_cast<uint8_t>(0x80)
+};
+
+uint8_t const Q_ROM Q_ROM_VAR QF_invPwr2Lkup[65] = {
+    static_cast<uint8_t>(0xFF),                             // unused location
+    static_cast<uint8_t>(0xFE), static_cast<uint8_t>(0xFD),
+    static_cast<uint8_t>(0xFB), static_cast<uint8_t>(0xF7),
+    static_cast<uint8_t>(0xEF), static_cast<uint8_t>(0xDF),
+    static_cast<uint8_t>(0xBF), static_cast<uint8_t>(0x7F),
+    static_cast<uint8_t>(0xFE), static_cast<uint8_t>(0xFD),
+    static_cast<uint8_t>(0xFB), static_cast<uint8_t>(0xF7),
+    static_cast<uint8_t>(0xEF), static_cast<uint8_t>(0xDF),
+    static_cast<uint8_t>(0xBF), static_cast<uint8_t>(0x7F),
+    static_cast<uint8_t>(0xFE), static_cast<uint8_t>(0xFD),
+    static_cast<uint8_t>(0xFB), static_cast<uint8_t>(0xF7),
+    static_cast<uint8_t>(0xEF), static_cast<uint8_t>(0xDF),
+    static_cast<uint8_t>(0xBF), static_cast<uint8_t>(0x7F),
+    static_cast<uint8_t>(0xFE), static_cast<uint8_t>(0xFD),
+    static_cast<uint8_t>(0xFB), static_cast<uint8_t>(0xF7),
+    static_cast<uint8_t>(0xEF), static_cast<uint8_t>(0xDF),
+    static_cast<uint8_t>(0xBF), static_cast<uint8_t>(0x7F),
+    static_cast<uint8_t>(0xFE), static_cast<uint8_t>(0xFD),
+    static_cast<uint8_t>(0xFB), static_cast<uint8_t>(0xF7),
+    static_cast<uint8_t>(0xEF), static_cast<uint8_t>(0xDF),
+    static_cast<uint8_t>(0xBF), static_cast<uint8_t>(0x7F),
+    static_cast<uint8_t>(0xFE), static_cast<uint8_t>(0xFD),
+    static_cast<uint8_t>(0xFB), static_cast<uint8_t>(0xF7),
+    static_cast<uint8_t>(0xEF), static_cast<uint8_t>(0xDF),
+    static_cast<uint8_t>(0xBF), static_cast<uint8_t>(0x7F),
+    static_cast<uint8_t>(0xFE), static_cast<uint8_t>(0xFD),
+    static_cast<uint8_t>(0xFB), static_cast<uint8_t>(0xF7),
+    static_cast<uint8_t>(0xEF), static_cast<uint8_t>(0xDF),
+    static_cast<uint8_t>(0xBF), static_cast<uint8_t>(0x7F),
+    static_cast<uint8_t>(0xFE), static_cast<uint8_t>(0xFD),
+    static_cast<uint8_t>(0xFB), static_cast<uint8_t>(0xF7),
+    static_cast<uint8_t>(0xEF), static_cast<uint8_t>(0xDF),
+    static_cast<uint8_t>(0xBF), static_cast<uint8_t>(0x7F)
+};
+
+uint8_t const Q_ROM Q_ROM_VAR QF_div8Lkup[65] = {
+    static_cast<uint8_t>(0),                                // unused location
+    static_cast<uint8_t>(0), static_cast<uint8_t>(0), static_cast<uint8_t>(0),
+    static_cast<uint8_t>(0), static_cast<uint8_t>(0), static_cast<uint8_t>(0),
+    static_cast<uint8_t>(0), static_cast<uint8_t>(0),
+    static_cast<uint8_t>(1), static_cast<uint8_t>(1), static_cast<uint8_t>(1),
+    static_cast<uint8_t>(1), static_cast<uint8_t>(1), static_cast<uint8_t>(1),
+    static_cast<uint8_t>(1), static_cast<uint8_t>(1),
+    static_cast<uint8_t>(2), static_cast<uint8_t>(2), static_cast<uint8_t>(2),
+    static_cast<uint8_t>(2), static_cast<uint8_t>(2), static_cast<uint8_t>(2),
+    static_cast<uint8_t>(2), static_cast<uint8_t>(2),
+    static_cast<uint8_t>(3), static_cast<uint8_t>(3), static_cast<uint8_t>(3),
+    static_cast<uint8_t>(3), static_cast<uint8_t>(3), static_cast<uint8_t>(3),
+    static_cast<uint8_t>(3), static_cast<uint8_t>(3),
+    static_cast<uint8_t>(4), static_cast<uint8_t>(4), static_cast<uint8_t>(4),
+    static_cast<uint8_t>(4), static_cast<uint8_t>(4), static_cast<uint8_t>(4),
+    static_cast<uint8_t>(4), static_cast<uint8_t>(4),
+    static_cast<uint8_t>(5), static_cast<uint8_t>(5), static_cast<uint8_t>(5),
+    static_cast<uint8_t>(5), static_cast<uint8_t>(5), static_cast<uint8_t>(5),
+    static_cast<uint8_t>(5), static_cast<uint8_t>(5),
+    static_cast<uint8_t>(6), static_cast<uint8_t>(6), static_cast<uint8_t>(6),
+    static_cast<uint8_t>(6), static_cast<uint8_t>(6), static_cast<uint8_t>(6),
+    static_cast<uint8_t>(6), static_cast<uint8_t>(6),
+    static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7),
+    static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7),
+    static_cast<uint8_t>(7), static_cast<uint8_t>(7)
+};
+
+QP_END_
+
+// "qf_tick.cpp" =============================================================
+/// \brief QF::tick() implementation.
+
+QP_BEGIN_
+
+//............................................................................
+#ifndef Q_SPY
+void QF::tick(void) {                                            // see NOTE01
+#else
+void QF::tick(void const * const sender) {
+#endif
+
+    QF_CRIT_STAT_
+    QF_CRIT_ENTRY_();
+
+    QS_BEGIN_NOCRIT_(QS_QF_TICK, null_void, null_void)
+        QS_TEC_(static_cast<QTimeEvtCtr>(++QS::tickCtr_)); // the tick counter
+    QS_END_NOCRIT_()
+
+    QTimeEvt *prev = null_tevt;
+    for (QTimeEvt *t = QF_timeEvtListHead_; t != null_tevt; t = t->m_next) {
+        if (t->m_ctr == tc_0) {            // time evt. scheduled for removal?
+            if (t == QF_timeEvtListHead_) {
+                QF_timeEvtListHead_ = t->m_next;
+            }
+            else {
+                Q_ASSERT(prev != null_tevt);
+                prev->m_next = t->m_next;
+            }
+            QF_EVT_REF_CTR_DEC_(t);                      // mark as not linked
+        }
+        else {
+            --t->m_ctr;
+            if (t->m_ctr == tc_0) {                        // about to expire?
+                if (t->m_interval != tc_0) {           // periodic time event?
+                    t->m_ctr = t->m_interval;            // rearm the time evt
+                }
+                else {
+                    QS_BEGIN_NOCRIT_(QS_QF_TIMEEVT_AUTO_DISARM, QS::teObj_, t)
+                        QS_OBJ_(t);                  // this time event object
+                        QS_OBJ_(t->m_act);                // the active object
+                    QS_END_NOCRIT_()
+                }
+
+                QS_BEGIN_NOCRIT_(QS_QF_TIMEEVT_POST, QS::teObj_, t)
+                    QS_TIME_();                                   // timestamp
+                    QS_OBJ_(t);                       // the time event object
+                    QS_SIG_(t->sig);          // the signal of this time event
+                    QS_OBJ_(t->m_act);                    // the active object
+                QS_END_NOCRIT_()
+
+                QF_CRIT_EXIT_();         // leave crit. section before posting
+                           // POST() asserts internally if the queue overflows
+                t->m_act->POST(t, sender);
+                QF_CRIT_ENTRY_();        // re-enter crit. section to continue
+
+                if (t->m_ctr == tc_0) {             // still marked to expire?
+                    if (t == QF_timeEvtListHead_) {
+                        QF_timeEvtListHead_ = t->m_next;
+                    }
+                    else {
+                        Q_ASSERT(prev != null_tevt);
+                        prev->m_next = t->m_next;
+                    }
+                    QF_EVT_REF_CTR_DEC_(t);                 // mark as removed
+                }
+                else {
+                    prev = t;
+                }
+            }
+            else {
+                prev = t;
+            }
+        }
+    }
+    QF_CRIT_EXIT_();
+}
+
+QP_END_
+
+// "qmp_get.cpp" =============================================================
+/// \brief QMPool::get() and QF::getPoolMargin() implementation.
+
+QP_BEGIN_
+
+//............................................................................
+void *QMPool::get(void) {
+    QF_CRIT_STAT_
+    QF_CRIT_ENTRY_();
+
+    QFreeBlock *fb = static_cast<QFreeBlock *>(m_free);  // free block or NULL
+    if (fb != static_cast<QFreeBlock *>(0)) {         // free block available?
+        m_free = fb->m_next;        // adjust list head to the next free block
+
+        Q_ASSERT(m_nFree > static_cast<QMPoolCtr>(0));    // at least one free
+        --m_nFree;                                      // one free block less
+        if (m_nMin > m_nFree) {
+            m_nMin = m_nFree;                   // remember the minimum so far
+        }
+    }
+
+    QS_BEGIN_NOCRIT_(QS_QF_MPOOL_GET, QS::mpObj_, m_start)
+        QS_TIME_();                                               // timestamp
+        QS_OBJ_(m_start);                   // the memory managed by this pool
+        QS_MPC_(m_nFree);             // the number of free blocks in the pool
+        QS_MPC_(m_nMin);     // the mninimum number of free blocks in the pool
+    QS_END_NOCRIT_()
+
+    QF_CRIT_EXIT_();
+    return fb;               // return the block or NULL pointer to the caller
+}
+//............................................................................
+uint32_t QF::getPoolMargin(uint8_t const poolId) {
+    Q_REQUIRE((u8_1 <= poolId) && (poolId <= QF_maxPool_));
+
+    QF_CRIT_STAT_
+    QF_CRIT_ENTRY_();
+    uint32_t margin = static_cast<uint32_t>(QF_pool_[poolId - u8_1].m_nMin);
+    QF_CRIT_EXIT_();
+
+    return margin;
+}
+
+QP_END_
+
+// "qmp_init.cpp" ============================================================
+/// \brief QMPool::init() implementation.
+
+QP_BEGIN_
+
+//............................................................................
+void QMPool::init(void * const poolSto, uint32_t const poolSize,
+                  QMPoolSize const blockSize)
+{
+    // 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 != null_void)
+              && (poolSize >= static_cast<uint32_t>(sizeof(QFreeBlock)))
+              && ((blockSize + static_cast<QMPoolSize>(sizeof(QFreeBlock)))
+                    > blockSize));
+
+    m_free = poolSto;
+
+                // round up the blockSize to fit an integer number of pointers
+    m_blockSize = static_cast<QMPoolSize>(sizeof(QFreeBlock));//start with one
+    uint32_t nblocks = static_cast<uint32_t>(1);//# free blocks in a mem block
+    while (m_blockSize < blockSize) {
+        m_blockSize += static_cast<QMPoolSize>(sizeof(QFreeBlock));
+        ++nblocks;
+    }
+
+               // the whole pool buffer must fit at least one rounded-up block
+    Q_ASSERT(poolSize >= static_cast<uint32_t>(m_blockSize));
+
+                                // chain all blocks together in a free-list...
+                                                     // don't chain last block
+    uint32_t availSize = poolSize - static_cast<uint32_t>(m_blockSize);
+    m_nTot = static_cast<QMPoolCtr>(1);    // one (the last) block in the pool
+                                          //start at the head of the free list
+    QFreeBlock *fb = static_cast<QFreeBlock *>(m_free);
+    while (availSize >= static_cast<uint32_t>(m_blockSize)) {
+        fb->m_next = &QF_PTR_AT_(fb, nblocks);          // setup the next link
+        fb = fb->m_next;                              // advance to next block
+        availSize -= static_cast<uint32_t>(m_blockSize);// less available size
+        ++m_nTot;                     // increment the number of blocks so far
+    }
+
+    fb->m_next = static_cast<QFreeBlock *>(0); // the last link points to NULL
+    m_nFree    = m_nTot;                                // all blocks are free
+    m_nMin     = m_nTot;                  // the minimum number of free blocks
+    m_start    = poolSto;               // the original start this pool buffer
+    m_end      = fb;                            // the last block in this pool
+
+    QS_CRIT_STAT_
+    QS_BEGIN_(QS_QF_MPOOL_INIT, QS::mpObj_, m_start)
+        QS_OBJ_(m_start);                   // the memory managed by this pool
+        QS_MPC_(m_nTot);                         // the total number of blocks
+    QS_END_()
+}
+
+QP_END_
+
+// "qmp_put.cpp" =============================================================
+/// \brief QMPool::put() implementation.
+
+QP_BEGIN_
+
+// This macro is specifically and exclusively used for checking the range
+// of a block pointer returned to the pool. Such a check must rely on the
+// pointer arithmetic not compliant with the MISRA-C++:2008 rules ??? and
+// ???. Defining a specific macro for this purpose allows to selectively
+// disable the warnings for this particular case.
+//
+#define QF_PTR_RANGE_(x_, min_, max_)  (((min_) <= (x_)) && ((x_) <= (max_)))
+
+//............................................................................
+void QMPool::put(void * const b) {
+
+    Q_REQUIRE(m_nFree < m_nTot);         // adding one free so, # free < total
+    Q_REQUIRE(QF_PTR_RANGE_(b, m_start, m_end));         // b must be in range
+
+    QF_CRIT_STAT_
+    QF_CRIT_ENTRY_();
+
+                                                    // link into the free list
+    (static_cast<QFreeBlock*>(b))->m_next = static_cast<QFreeBlock *>(m_free);
+    m_free = b;                            // set as new head of the free list
+    ++m_nFree;                             // one more free block in this pool
+
+    QS_BEGIN_NOCRIT_(QS_QF_MPOOL_PUT, QS::mpObj_, m_start)
+        QS_TIME_();                                               // timestamp
+        QS_OBJ_(m_start);                   // the memory managed by this pool
+        QS_MPC_(m_nFree);             // the number of free blocks in the pool
+    QS_END_NOCRIT_()
+
+    QF_CRIT_EXIT_();
+}
+
+QP_END_
+
+
+// "qte_arm.cpp" =============================================================
+/// \brief QF_timeEvtListHead_ definition and QTimeEvt::arm_() implementation.
+
+QP_BEGIN_
+
+// Package-scope objects -----------------------------------------------------
+QTimeEvt *QF_timeEvtListHead_;           // head of linked list of time events
+
+//............................................................................
+bool QF::noTimeEvtsActive(void) {
+    return QF_timeEvtListHead_ == null_tevt;
+}
+//............................................................................
+void QTimeEvt::arm_(QActive * const act, QTimeEvtCtr const nTicks) {
+    Q_REQUIRE((nTicks > tc_0)                    /* cannot arm with 0 ticks */
+              && (act != null_act)        /* Active object must be provided */
+              && (m_ctr == tc_0)                        /* must be disarmed */
+              && (static_cast<enum_t>(sig) >= Q_USER_SIG));    // valid signal
+    QF_CRIT_STAT_
+    QF_CRIT_ENTRY_();
+    m_ctr  = nTicks;
+    m_act  = act;
+    if (refCtr_ == u8_0) {                                      // not linked?
+        m_next = QF_timeEvtListHead_;
+        QF_timeEvtListHead_ = this;
+        QF_EVT_REF_CTR_INC_(this);                           // mark as linked
+    }
+
+    QS_BEGIN_NOCRIT_(QS_QF_TIMEEVT_ARM, QS::teObj_, this)
+        QS_TIME_();                                               // timestamp
+        QS_OBJ_(this);                               // this time event object
+        QS_OBJ_(act);                                     // the active object
+        QS_TEC_(nTicks);                                // the number of ticks
+        QS_TEC_(m_interval);                                   // the interval
+    QS_END_NOCRIT_()
+
+    QF_CRIT_EXIT_();
+}
+
+QP_END_
+
+
+// "qte_ctor.cpp" ============================================================
+/// \brief QTimeEvt::QTimeEvt() implementation.
+QP_BEGIN_
+
+//............................................................................
+QTimeEvt::QTimeEvt(enum_t const s)
+  :
+#ifdef Q_EVT_CTOR
+    QEvt(static_cast<QSignal>(s)),
+#endif
+    m_next(null_tevt),
+    m_act(null_act),
+    m_ctr(tc_0),
+    m_interval(tc_0)
+{
+    Q_REQUIRE(s >= Q_USER_SIG);                        // signal must be valid
+#ifndef Q_EVT_CTOR
+    sig = static_cast<QSignal>(s);
+#endif
+                                      // time event must be static, see NOTE01
+    poolId_ = u8_0;                                 // not from any event pool
+    refCtr_ = u8_0;                                              // not linked
+}
+
+QP_END_
+
+
+// "qte_ctr.cpp" =============================================================
+/// \brief QTimeEvt::ctr() implementation.
+
+QP_BEGIN_
+
+//............................................................................
+QTimeEvtCtr QTimeEvt::ctr(void) const {
+    QF_CRIT_STAT_
+
+    QF_CRIT_ENTRY_();
+    QTimeEvtCtr ret = m_ctr;
+
+    QS_BEGIN_NOCRIT_(QS_QF_TIMEEVT_CTR, QS::teObj_, this)
+        QS_TIME_();                                               // timestamp
+        QS_OBJ_(this);                               // this time event object
+        QS_OBJ_(m_act);                                   // the active object
+        QS_TEC_(ret);                                   // the current counter
+        QS_TEC_(m_interval);                                   // the interval
+    QS_END_NOCRIT_()
+
+    QF_CRIT_EXIT_();
+    return ret;
+}
+
+QP_END_
+
+// "qte_darm.cpp" ============================================================
+/// \brief QTimeEvt::disarm() implementation.
+
+QP_BEGIN_
+
+//............................................................................
+// NOTE: disarm a time evt (no harm in disarming an already disarmed time evt)
+bool QTimeEvt::disarm(void) {
+    QF_CRIT_STAT_
+    QF_CRIT_ENTRY_();
+    bool wasArmed;
+    if (m_ctr != tc_0) {                  // is the time event actually armed?
+        wasArmed = true;
+
+        QS_BEGIN_NOCRIT_(QS_QF_TIMEEVT_DISARM, QS::teObj_, this)
+            QS_TIME_();                                           // timestamp
+            QS_OBJ_(this);                           // this time event object
+            QS_OBJ_(m_act);                               // the active object
+            QS_TEC_(m_ctr);                             // the number of ticks
+            QS_TEC_(m_interval);                               // the interval
+        QS_END_NOCRIT_()
+
+        m_ctr = tc_0;                        // schedule removal from the list
+    }
+    else {                                     // the time event was not armed
+        wasArmed = false;
+
+        QS_BEGIN_NOCRIT_(QS_QF_TIMEEVT_DISARM_ATTEMPT, QS::teObj_, this)
+            QS_TIME_();                                           // timestamp
+            QS_OBJ_(this);                           // this time event object
+            QS_OBJ_(m_act);                               // the active object
+        QS_END_NOCRIT_()
+    }
+    QF_CRIT_EXIT_();
+    return wasArmed;
+}
+
+QP_END_
+
+
+// "qte_rarm.cpp" ============================================================
+/// \brief QTimeEvt::rearm() implementation.
+
+QP_BEGIN_
+
+//............................................................................
+bool QTimeEvt::rearm(QTimeEvtCtr const nTicks) {
+    Q_REQUIRE((nTicks > tc_0)                  /* cannot rearm with 0 ticks */
+              && (m_act != null_act)         /* active object must be valid */
+              && (static_cast<enum_t>(sig) >= Q_USER_SIG));    // valid signal
+
+    QF_CRIT_STAT_
+    QF_CRIT_ENTRY_();
+
+    bool isArmed;
+    if (m_ctr == tc_0) {                       // is this time event disarmed?
+        isArmed = false;
+        m_next = QF_timeEvtListHead_;
+        if (QF_timeEvtListHead_ != null_tevt) {
+            m_next = QF_timeEvtListHead_;
+            QF_timeEvtListHead_ = this;
+            QF_EVT_REF_CTR_INC_(this);                       // mark as linked
+        }
+    }
+    else {
+        isArmed = true;
+    }
+    m_ctr = nTicks;            // re-load the tick counter (shift the phasing)
+
+    QS_BEGIN_NOCRIT_(QS_QF_TIMEEVT_REARM, QS::teObj_, this)
+        QS_TIME_();                                               // timestamp
+        QS_OBJ_(this);                               // this time event object
+        QS_OBJ_(m_act);                                   // the active object
+        QS_TEC_(m_ctr);                                 // the number of ticks
+        QS_TEC_(m_interval);                                   // the interval
+        QS_U8_(isArmed ? u8_1 : u8_0);                 // was the timer armed?
+    QS_END_NOCRIT_()
+
+    QF_CRIT_EXIT_();
+    return isArmed;
+}
+
+QP_END_
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Kernel selection based on QK_PREEMPTIVE
+//
+#ifdef QK_PREEMPTIVE
+
+// "qk_pkg.h" ================================================================
+/// \brief Internal (package scope) QK/C interface.
+
+#ifndef QF_CRIT_STAT_TYPE
+    /// \brief This is an internal macro for defining the critical section
+    /// status type.
+    ///
+    /// The purpose of this macro is to enable writing the same code for the
+    /// case when critical sectgion status type is defined and when it is not.
+    /// If the macro #QF_CRIT_STAT_TYPE is defined, this internal macro
+    /// provides the definition of the critical section status varaible.
+    /// Otherwise this macro is empty.
+    /// \sa #QF_CRIT_STAT_TYPE
+    #define QF_CRIT_STAT_
+
+    /// \brief This is an internal macro for entering a critical section.
+    ///
+    /// The purpose of this macro is to enable writing the same code for the
+    /// case when critical sectgion status type is defined and when it is not.
+    /// If the macro #QF_CRIT_STAT_TYPE is defined, this internal macro
+    /// invokes #QF_CRIT_ENTRY passing the key variable as the parameter.
+    /// Otherwise #QF_CRIT_ENTRY is invoked with a dummy parameter.
+    /// \sa #QF_CRIT_ENTRY
+    #define QF_CRIT_ENTRY_()    QF_CRIT_ENTRY(dummy)
+
+    /// \brief This is an internal macro for exiting a cricial section.
+    ///
+    /// The purpose of this macro is to enable writing the same code for the
+    /// case when critical sectgion status type is defined and when it is not.
+    /// If the macro #QF_CRIT_STAT_TYPE is defined, this internal macro
+    /// invokes #QF_CRIT_EXIT passing the key variable as the parameter.
+    /// Otherwise #QF_CRIT_EXIT is invoked with a dummy parameter.
+    /// \sa #QF_CRIT_EXIT
+    #define QF_CRIT_EXIT_()     QF_CRIT_EXIT(dummy)
+
+#else
+    #define QF_CRIT_STAT_       QF_CRIT_STAT_TYPE critStat_;
+    #define QF_CRIT_ENTRY_()    QF_CRIT_ENTRY(critStat_)
+    #define QF_CRIT_EXIT_()     QF_CRIT_EXIT(critStat_)
+#endif
+                             // define for backwards compatibility, see NOTE01
+#ifndef QF_CRIT_STAT_TYPE
+#if !defined(QF_INT_DISABLE) && defined(QF_CRIT_ENTRY)
+    #define QF_INT_DISABLE()    QF_CRIT_ENTRY(dummy)
+#endif
+#if !defined(QF_INT_ENABLE) && defined(QF_CRIT_EXIT)
+    #define QF_INT_ENABLE()     QF_CRIT_EXIT(dummy)
+#endif
+#endif                                                    // QF_CRIT_STAT_TYPE
+
+                                                   // package-scope objects...
+#ifndef QK_NO_MUTEX
+    extern "C" uint8_t QK_ceilingPrio_;         ///< QK mutex priority ceiling
+#endif
+
+// "qk.cpp" ==================================================================
+/// \brief QK_readySet_, QK_currPrio_, and QK_intNest_ definitions and
+/// QK::getVersion(), QF::init(), QF::run(), QF::stop(),
+/// QActive::start(), QActive::stop() implementations.
+
+// Public-scope objects ------------------------------------------------------
+extern "C" {
+#if (QF_MAX_ACTIVE <= 8)
+    QP_ QPSet8  QK_readySet_;                               // ready set of QK
+#else
+    QP_ QPSet64 QK_readySet_;                               // ready set of QK
+#endif
+                                         // start with the QK scheduler locked
+uint8_t QK_currPrio_ = static_cast<uint8_t>(QF_MAX_ACTIVE + 1);
+uint8_t QK_intNest_;                          // start with nesting level of 0
+
+}                                                                // extern "C"
+
+QP_BEGIN_
+
+//............................................................................
+char_t const Q_ROM * Q_ROM_VAR QK::getVersion(void) {
+    uint8_t const u8_zero = static_cast<uint8_t>('0');
+    static char_t const Q_ROM Q_ROM_VAR version[] = {
+        static_cast<char_t>(((QP_VERSION >> 12) & 0xFU) + u8_zero),
+        static_cast<char_t>('.'),
+        static_cast<char_t>(((QP_VERSION >>  8) & 0xFU) + u8_zero),
+        static_cast<char_t>('.'),
+        static_cast<char_t>(((QP_VERSION >>  4) & 0xFU) + u8_zero),
+        static_cast<char_t>((QP_VERSION         & 0xFU) + u8_zero),
+        static_cast<char_t>('\0')
+    };
+    return version;
+}
+//............................................................................
+void QF::init(void) {
+    QK_init();           // QK initialization ("C" linkage, might be assembly)
+}
+//............................................................................
+void QF::stop(void) {
+    QF::onCleanup();                                       // cleanup callback
+    // nothing else to do for the QK preemptive kernel
+}
+//............................................................................
+static void initialize(void) {
+    QK_currPrio_ = static_cast<uint8_t>(0);   // priority for the QK idle loop
+    uint8_t p = QK_schedPrio_();
+    if (p != static_cast<uint8_t>(0)) {
+        QK_sched_(p);                    // process all events produced so far
+    }
+}
+//............................................................................
+int16_t QF::run(void) {
+    QF_INT_DISABLE();
+    initialize();
+    onStartup();                                           // startup callback
+    QF_INT_ENABLE();
+
+    for (;;) {                                             // the QK idle loop
+        QK::onIdle();                        // invoke the QK on-idle callback
+    }
+                      // this unreachable return is to make the compiler happy
+    return static_cast<int16_t>(0);
+}
+//............................................................................
+void QActive::start(uint8_t const prio,
+                   QEvt const *qSto[], uint32_t const qLen,
+                   void * const stkSto, uint32_t const stkSize,
+                   QEvt const * const ie)
+{
+    Q_REQUIRE((static_cast<uint8_t>(0) < prio)
+              && (prio <= static_cast<uint8_t>(QF_MAX_ACTIVE)));
+
+    m_eQueue.init(qSto, static_cast<QEQueueCtr>(qLen));    // initialize queue
+    m_prio = prio;
+    QF::add_(this);                     // make QF aware of this active object
+
+#if defined(QK_TLS) || defined(QK_EXT_SAVE)
+    // in the QK port the parameter stkSize is used as the thread flags
+    m_osObject = static_cast<uint8_t>(stkSize);   // m_osObject contains flags
+
+    // in the QK port the parameter stkSto is used as the thread-local-storage
+    m_thread   = stkSto;   // contains the pointer to the thread-local-storage
+#else
+    Q_ASSERT((stkSto == static_cast<void *>(0))
+             && (stkSize == static_cast<uint32_t>(0)));
+#endif
+
+    init(ie);                                    // execute initial transition
+
+    QS_FLUSH();                          // flush the trace buffer to the host
+}
+//............................................................................
+void QActive::stop(void) {
+    QF::remove_(this);                // remove this active object from the QF
+}
+
+QP_END_
+
+// "qk_sched" ================================================================
+/// \brief QK_schedPrio_() and QK_sched_() implementation.
+
+//............................................................................
+// NOTE: the QK scheduler is entered and exited with interrupts DISABLED.
+// QK_sched_() is extern "C", so it does not belong to the QP namespace.
+//
+extern "C" {
+
+//............................................................................
+// NOTE: QK schedPrio_() is entered and exited with interrupts DISABLED
+uint8_t QK_schedPrio_(void) {
+
+    uint8_t p = QK_readySet_.findMax();
+
+#ifdef QK_NO_MUTEX
+    if (p > QK_currPrio_) {                        // do we have a preemption?
+#else                                   // QK priority-ceiling mutexes allowed
+    if ((p > QK_currPrio_) && (p > QK_ceilingPrio_)) {
+#endif
+    }
+    else {
+        p = static_cast<uint8_t>(0);
+    }
+    return p;
+}
+//............................................................................
+void QK_sched_(uint8_t p) {
+
+    uint8_t pin = QK_currPrio_;                   // save the initial priority
+    QP_ QActive *a;
+#ifdef QK_TLS                                    // thread-local storage used?
+    uint8_t pprev = pin;
+#endif
+    do {
+        a = QP_ QF::active_[p];                // obtain the pointer to the AO
+        QK_currPrio_ = p;            // this becomes the current task priority
+
+#ifdef QK_TLS                                    // thread-local storage used?
+        if (p != pprev) {                          // are we changing threads?
+            QK_TLS(a);                      // switch new thread-local storage
+            pprev = p;
+        }
+#endif
+        QS_BEGIN_NOCRIT_(QP_ QS_QK_SCHEDULE, QP_ QS::aoObj_, a)
+            QS_TIME_();                                           // timestamp
+            QS_U8_(p);                    // the priority of the active object
+            QS_U8_(pin);                             // the preempted priority
+        QS_END_NOCRIT_()
+
+        QF_INT_ENABLE();                  // unconditionally enable interrupts
+
+        QP_ QEvt const *e = a->get_();       // get the next event for this AO
+        a->dispatch(e);                               // dispatch e to this AO
+        QP_ QF::gc(e);              // garbage collect the event, if necessary
+
+                        // determine the next highest-priority AO ready to run
+        QF_INT_DISABLE();                                // disable interrupts
+        p = QK_readySet_.findMax();
+
+#ifdef QK_NO_MUTEX
+    } while (p > pin);             // is the new priority higher than initial?
+#else                                   // QK priority-ceiling mutexes allowed
+    } while ((p > pin) && (p > QK_ceilingPrio_));
+#endif
+
+    QK_currPrio_ = pin;                        // restore the initial priority
+
+#ifdef QK_TLS                                    // thread-local storage used?
+    if (pin != static_cast<uint8_t>(0)) { // no extended context for idle loop
+        a = QP_ QF::active_[pin];           // the pointer to the preempted AO
+        QK_TLS(a);                                 // restore the original TLS
+    }
+#endif
+}
+
+}                                                                // extern "C"
+
+#ifndef QK_NO_MUTEX
+
+// "qk_mutex.cpp" ============================================================
+/// \brief QK::mutexLock()/QK::mutexUnlock() implementation.
+
+// package-scope objects -----------------------------------------------------
+extern "C" {
+    uint8_t QK_ceilingPrio_;                    // ceiling priority of a mutex
+}
+
+QP_BEGIN_
+
+//............................................................................
+QMutex QK::mutexLock(uint8_t const prioCeiling) {
+    QF_CRIT_STAT_
+    QF_CRIT_ENTRY_();
+    uint8_t mutex = QK_ceilingPrio_; // original QK priority ceiling to return
+    if (QK_ceilingPrio_ < prioCeiling) {
+        QK_ceilingPrio_ = prioCeiling;        // raise the QK priority ceiling
+    }
+
+    QS_BEGIN_NOCRIT_(QS_QK_MUTEX_LOCK,
+                     static_cast<void *>(0), static_cast<void *>(0))
+        QS_TIME_();                                               // timestamp
+        QS_U8_(mutex);                                // the original priority
+        QS_U8_(QK_ceilingPrio_);               // the current priority ceiling
+    QS_END_NOCRIT_()
+
+    QF_CRIT_EXIT_();
+    return mutex;
+}
+//............................................................................
+void QK::mutexUnlock(QMutex mutex) {
+    QF_CRIT_STAT_
+    QF_CRIT_ENTRY_();
+
+    QS_BEGIN_NOCRIT_(QS_QK_MUTEX_UNLOCK,
+                     static_cast<void *>(0), static_cast<void *>(0))
+        QS_TIME_();                                               // timestamp
+        QS_U8_(mutex);                                // the original priority
+        QS_U8_(QK_ceilingPrio_);               // the current priority ceiling
+    QS_END_NOCRIT_()
+
+    if (QK_ceilingPrio_ > mutex) {
+        QK_ceilingPrio_ = mutex;         // restore the saved priority ceiling
+        mutex = QK_schedPrio_();             // reuse 'mutex' to hold priority
+        if (mutex != static_cast<uint8_t>(0)) {
+            QK_sched_(mutex);
+        }
+    }
+    QF_CRIT_EXIT_();
+}
+
+QP_END_
+
+#endif                                                          // QK_NO_MUTEX
+
+#else                                                         // QK_PREEMPTIVE
+
+// "qvanilla.cpp" ============================================================
+/// \brief "vanilla" cooperative kernel,
+/// QActive::start(), QActive::stop(), and QF::run() implementation.
+
+QP_BEGIN_
+
+// Package-scope objects -----------------------------------------------------
+extern "C" {
+#if (QF_MAX_ACTIVE <= 8)
+    QPSet8  QF_readySet_;                       // ready set of active objects
+#else
+    QPSet64 QF_readySet_;                       // ready set of active objects
+#endif
+
+uint8_t QF_currPrio_;                     ///< current task/interrupt priority
+uint8_t QF_intNest_;                              ///< interrupt nesting level
+
+}                                                                // extern "C"
+
+//............................................................................
+void QF::init(void) {
+    // nothing to do for the "vanilla" kernel
+}
+//............................................................................
+void QF::stop(void) {
+    onCleanup();                                           // cleanup callback
+    // nothing else to do for the "vanilla" kernel
+}
+//............................................................................
+int16_t QF::run(void) {
+    onStartup();                                           // startup callback
+
+    for (;;) {                                           // the bacground loop
+        QF_INT_DISABLE();
+        if (QF_readySet_.notEmpty()) {
+            uint8_t p = QF_readySet_.findMax();
+            QActive *a = active_[p];
+            QF_currPrio_ = p;                     // save the current priority
+            QF_INT_ENABLE();
+
+            QEvt const *e = a->get_();     // get the next event for this AO
+            a->dispatch(e);                         // dispatch evt to the HSM
+            gc(e);       // determine if event is garbage and collect it if so
+        }
+        else {
+            onIdle();                                            // see NOTE01
+        }
+    }
+                      // this unreachable return is to make the compiler happy
+    return static_cast<int16_t>(0);
+}
+//............................................................................
+void QActive::start(uint8_t const prio,
+                    QEvt const *qSto[], uint32_t const qLen,
+                    void * const stkSto, uint32_t const,
+                    QEvt const * const ie)
+{
+    Q_REQUIRE((u8_0 < prio) && (prio <= static_cast<uint8_t>(QF_MAX_ACTIVE))
+              && (stkSto == null_void));      // does not need per-actor stack
+
+    m_eQueue.init(qSto, static_cast<QEQueueCtr>(qLen));  // initialize QEQueue
+    m_prio = prio;                // set the QF priority of this active object
+    QF::add_(this);                     // make QF aware of this active object
+    init(ie);                                    // execute initial transition
+
+    QS_FLUSH();                          // flush the trace buffer to the host
+}
+//............................................................................
+void QActive::stop(void) {
+    QF::remove_(this);
+}
+
+QP_END_
+
+//////////////////////////////////////////////////////////////////////////////
+// NOTE01:
+// QF::onIdle() must be called with interrupts DISABLED because the
+// determination of the idle condition (no events in the queues) can change
+// at any time by an interrupt posting events to a queue. The QF::onIdle()
+// MUST enable interrups internally, perhaps at the same time as putting the
+// CPU into a power-saving mode.
+//
+
+extern "C" {
+
+void QK_sched_(uint8_t p) {            // dummy empty definition for qk_port.s
+    (void)p;
+}
+
+uint8_t QK_schedPrio_(void) {          // dummy empty definition for qk_port.s
+    return static_cast<uint8_t>(0U);
+}
+
+}                                                                // extern "C"
+
+#endif                                                        // QK_PREEMPTIVE
+
+//////////////////////////////////////////////////////////////////////////////
+#ifdef Q_SPY
+
+// "qs_pkg.h" ================================================================
+/// \brief Internal (package scope) QS/C++ interface.
+
+QP_BEGIN_
+
+/// \brief QS ring buffer counter and offset type
+typedef uint16_t QSCtr;
+
+/// \brief Internal QS macro to insert an un-escaped byte into
+/// the QS buffer
+////
+#define QS_INSERT_BYTE(b_) \
+    QS_PTR_AT_(QS_head_) = (b_); \
+    ++QS_head_; \
+    if (QS_head_ == QS_end_) { \
+        QS_head_ = static_cast<QSCtr>(0); \
+    } \
+    ++QS_used_;
+
+/// \brief Internal QS macro to insert an escaped byte into the QS buffer
+#define QS_INSERT_ESC_BYTE(b_) \
+    QS_chksum_ = static_cast<uint8_t>(QS_chksum_ + (b_)); \
+    if (((b_) == QS_FRAME) || ((b_) == QS_ESC)) { \
+        QS_INSERT_BYTE(QS_ESC) \
+        QS_INSERT_BYTE(static_cast<uint8_t>((b_) ^ QS_ESC_XOR)) \
+    } \
+    else { \
+        QS_INSERT_BYTE(b_) \
+    }
+
+/// \brief Internal QS macro to insert a escaped checksum byte into
+/// the QS buffer
+#define QS_INSERT_CHKSUM_BYTE() \
+    QS_chksum_ = static_cast<uint8_t>(~QS_chksum_); \
+    if ((QS_chksum_ == QS_FRAME) || (QS_chksum_ == QS_ESC)) { \
+        QS_INSERT_BYTE(QS_ESC) \
+        QS_INSERT_BYTE(static_cast<uint8_t>(QS_chksum_ ^ QS_ESC_XOR)) \
+    } \
+    else { \
+        QS_INSERT_BYTE(QS_chksum_) \
+    }
+
+
+/// \brief Internal QS macro to access the QS ring buffer
+///
+/// \note The QS buffer is allocated by the user and is accessed through the
+/// pointer QS_ring_, which violates the MISRA-C 2004 Rule 17.4(req), pointer
+/// arithmetic other than array indexing. Encapsulating this violation in a
+/// macro allows to selectively suppress this specific deviation.
+#define QS_PTR_AT_(i_) (QS_ring_[i_])
+
+
+/// \brief Frame character of the QS output protocol
+uint8_t const QS_FRAME = static_cast<uint8_t>(0x7E);
+
+/// \brief Escape character of the QS output protocol
+uint8_t const QS_ESC   = static_cast<uint8_t>(0x7D);
+
+/// \brief Escape modifier of the QS output protocol
+///
+/// The escaped byte is XOR-ed with the escape modifier before it is inserted
+/// into the QS buffer.
+uint8_t const QS_ESC_XOR = static_cast<uint8_t>(0x20);
+
+#ifndef Q_ROM_BYTE
+    /// \brief Macro to access a byte allocated in ROM
+    ///
+    /// Some compilers for Harvard-architecture MCUs, such as gcc for AVR, do
+    /// not generate correct code for accessing data allocated in the program
+    /// space (ROM). The workaround for such compilers is to explictly add
+    /// assembly code to access each data element allocated in the program
+    /// space. The macro Q_ROM_BYTE() retrieves a byte from the given ROM
+    /// address.
+    ///
+    /// The Q_ROM_BYTE() macro should be defined for the compilers that
+    /// cannot handle correctly data allocated in ROM (such as the gcc).
+    /// If the macro is left undefined, the default definition simply returns
+    /// the argument and lets the compiler generate the correct code.
+    #define Q_ROM_BYTE(rom_var_)   (rom_var_)
+#endif
+
+//............................................................................
+extern uint8_t *QS_ring_;         ///< pointer to the start of the ring buffer
+extern QSCtr QS_end_;                ///< offset of the end of the ring buffer
+extern QSCtr QS_head_;         ///< offset to where next byte will be inserted
+extern QSCtr QS_tail_;       ///< offset of where next event will be extracted
+extern QSCtr QS_used_;       ///< number of bytes currently in the ring buffer
+extern uint8_t QS_seq_;                        ///< the record sequence number
+extern uint8_t QS_chksum_;             ///< the checksum of the current record
+extern uint8_t QS_full_;              ///< the ring buffer is temporarily full
+
+QP_END_
+
+
+// "qs.cpp" ==================================================================
+/// \brief QS internal variables definitions and core QS functions
+/// implementations.
+
+QP_BEGIN_
+
+//............................................................................
+uint8_t QS::glbFilter_[32];                                // global QS filter
+
+//............................................................................
+uint8_t *QS_ring_;                  // pointer to the start of the ring buffer
+QSCtr QS_end_;                         // offset of the end of the ring buffer
+QSCtr QS_head_;                  // offset to where next byte will be inserted
+QSCtr QS_tail_;                 // offset of where next byte will be extracted
+QSCtr QS_used_;                // number of bytes currently in the ring buffer
+uint8_t QS_seq_;                                 // the record sequence number
+uint8_t QS_chksum_;                      // the checksum of the current record
+uint8_t QS_full_;                       // the ring buffer is temporarily full
+
+//............................................................................
+char_t const Q_ROM * Q_ROM_VAR QS::getVersion(void) {
+    uint8_t const u8_zero = static_cast<uint8_t>('0');
+    static char_t const Q_ROM Q_ROM_VAR version[] = {
+        static_cast<char_t>(((QP_VERSION >> 12) & 0xFU) + u8_zero),
+        static_cast<char_t>('.'),
+        static_cast<char_t>(((QP_VERSION >>  8) & 0xFU) + u8_zero),
+        static_cast<char_t>('.'),
+        static_cast<char_t>(((QP_VERSION >>  4) & 0xFU) + u8_zero),
+        static_cast<char_t>((QP_VERSION         & 0xFU) + u8_zero),
+        static_cast<char_t>('\0')
+    };
+    return version;
+}
+//............................................................................
+void QS::initBuf(uint8_t sto[], uint32_t const stoSize) {
+    QS_ring_ = &sto[0];
+    QS_end_  = static_cast<QSCtr>(stoSize);
+}
+//............................................................................
+void QS::filterOn(uint8_t const rec) {
+    if (rec == QS_ALL_RECORDS) {
+        uint8_t i;
+        for (i = static_cast<uint8_t>(0);
+             i < static_cast<uint8_t>(sizeof(glbFilter_));
+             ++i)
+        {
+            glbFilter_[i] = static_cast<uint8_t>(0xFF);
+        }
+    }
+    else {
+        glbFilter_[rec >> 3] |=
+            static_cast<uint8_t>(1U << (rec & static_cast<uint8_t>(0x07)));
+    }
+}
+//............................................................................
+void QS::filterOff(uint8_t const rec) {
+    if (rec == QS_ALL_RECORDS) {
+        uint8_t i;
+        for (i = static_cast<uint8_t>(0);
+            i < static_cast<uint8_t>(sizeof(glbFilter_));
+            ++i)
+        {
+            glbFilter_[i] = static_cast<uint8_t>(0);
+        }
+    }
+    else {
+        glbFilter_[rec >> 3] &= static_cast<uint8_t>(
+           ~static_cast<uint8_t>((1U << (rec & static_cast<uint8_t>(0x07)))));
+    }
+}
+//............................................................................
+void QS::begin(uint8_t const rec) {
+    QS_chksum_ = static_cast<uint8_t>(0);                // clear the checksum
+    ++QS_seq_;                         // always increment the sequence number
+    QS_INSERT_ESC_BYTE(QS_seq_)                   // store the sequence number
+    QS_INSERT_ESC_BYTE(rec)                             // store the record ID
+}
+//............................................................................
+void QS::end(void) {
+    QS_INSERT_CHKSUM_BYTE()
+    QS_INSERT_BYTE(QS_FRAME)
+    if (QS_used_ > QS_end_) {                    // overrun over the old data?
+        QS_tail_ = QS_head_;                 // shift the tail to the old data
+        QS_used_ = QS_end_;                        // the whole buffer is used
+    }
+}
+//............................................................................
+void QS::u8(uint8_t const format, uint8_t const d) {
+    QS_INSERT_ESC_BYTE(format)
+    QS_INSERT_ESC_BYTE(d)
+}
+//............................................................................
+void QS::u16(uint8_t const format, uint16_t d) {
+    QS_INSERT_ESC_BYTE(format)
+    QS_INSERT_ESC_BYTE(static_cast<uint8_t>(d))
+    d >>= 8;
+    QS_INSERT_ESC_BYTE(static_cast<uint8_t>(d))
+}
+//............................................................................
+void QS::u32(uint8_t const format, uint32_t d) {
+    QS_INSERT_ESC_BYTE(format)
+    QS_INSERT_ESC_BYTE(static_cast<uint8_t>(d))
+    d >>= 8;
+    QS_INSERT_ESC_BYTE(static_cast<uint8_t>(d))
+    d >>= 8;
+    QS_INSERT_ESC_BYTE(static_cast<uint8_t>(d))
+    d >>= 8;
+    QS_INSERT_ESC_BYTE(static_cast<uint8_t>(d))
+}
+
+QP_END_
+
+
+// "qs_.cpp" =================================================================
+/// \brief QS functions for internal use inside QP components
+
+QP_BEGIN_
+
+//............................................................................
+void const *QS::smObj_;                  // local state machine for QEP filter
+void const *QS::aoObj_;                   // local active object for QF filter
+void const *QS::mpObj_;                     //  local event pool for QF filter
+void const *QS::eqObj_;                      //  local raw queue for QF filter
+void const *QS::teObj_;                     //  local time event for QF filter
+void const *QS::apObj_;                    //  local object Application filter
+
+QSTimeCtr QS::tickCtr_;              // tick counter for the QS_QF_TICK record
+
+//............................................................................
+void QS::u8_(uint8_t const d) {
+    QS_INSERT_ESC_BYTE(d)
+}
+//............................................................................
+void QS::u16_(uint16_t d) {
+    QS_INSERT_ESC_BYTE(static_cast<uint8_t>(d))
+    d >>= 8;
+    QS_INSERT_ESC_BYTE(static_cast<uint8_t>(d))
+}
+//............................................................................
+void QS::u32_(uint32_t d) {
+    QS_INSERT_ESC_BYTE(static_cast<uint8_t>(d))
+    d >>= 8;
+    QS_INSERT_ESC_BYTE(static_cast<uint8_t>(d))
+    d >>= 8;
+    QS_INSERT_ESC_BYTE(static_cast<uint8_t>(d))
+    d >>= 8;
+    QS_INSERT_ESC_BYTE(static_cast<uint8_t>(d))
+}
+//............................................................................
+void QS::str_(char_t const *s) {
+    uint8_t b = static_cast<uint8_t>(*s);
+    while (b != static_cast<uint8_t>(0)) {
+                                       // ASCII characters don't need escaping
+        QS_chksum_ = static_cast<uint8_t>(QS_chksum_ + b);
+        QS_INSERT_BYTE(b)
+        ++s;
+        b = static_cast<uint8_t>(*s);
+    }
+    QS_INSERT_BYTE(static_cast<uint8_t>(0))
+}
+//............................................................................
+void QS::str_ROM_(char_t const Q_ROM * Q_ROM_VAR s) {
+    uint8_t b = static_cast<uint8_t>(Q_ROM_BYTE(*s));
+    while (b != static_cast<uint8_t>(0)) {
+                                       // ASCII characters don't need escaping
+        QS_chksum_ = static_cast<uint8_t>(QS_chksum_ + b);
+        QS_INSERT_BYTE(b)
+        ++s;
+        b = static_cast<uint8_t>(Q_ROM_BYTE(*s));
+    }
+    QS_INSERT_BYTE(static_cast<uint8_t>(0))
+}
+
+QP_END_
+
+// "qs_blk.cpp" ==============================================================
+/// \brief QS::getBlock() implementation
+
+QP_BEGIN_
+
+//............................................................................
+// get up to *pn bytes of contiguous memory
+uint8_t const *QS::getBlock(uint16_t * const pNbytes) {
+    uint8_t *block;
+    if (QS_used_ == static_cast<QSCtr>(0)) {
+        *pNbytes = static_cast<uint16_t>(0);
+        block = static_cast<uint8_t *>(0);     // no bytes to return right now
+    }
+    else {
+        QSCtr n = static_cast<QSCtr>(QS_end_ - QS_tail_);
+        if (n > QS_used_) {
+            n = QS_used_;
+        }
+        if (n > static_cast<QSCtr>(*pNbytes)) {
+            n = static_cast<QSCtr>(*pNbytes);
+        }
+        *pNbytes = static_cast<uint16_t>(n);
+        QS_used_ = static_cast<QSCtr>(QS_used_ - n);
+        QSCtr t  = QS_tail_;
+        QS_tail_ = static_cast<QSCtr>(QS_tail_ + n);
+        if (QS_tail_ == QS_end_) {
+            QS_tail_ = static_cast<QSCtr>(0);
+        }
+        block = &QS_PTR_AT_(t);
+    }
+    return block;
+}
+
+QP_END_
+
+// "qs_byte.cpp" =============================================================
+/// \brief QS::getByte() implementation
+
+QP_BEGIN_
+
+//............................................................................
+uint16_t QS::getByte(void) {
+    uint16_t ret;
+    if (QS_used_ == static_cast<QSCtr>(0)) {
+        ret = QS_EOD;                                       // set End-Of-Data
+    }
+    else {
+        ret = static_cast<uint16_t>(QS_PTR_AT_(QS_tail_));   // byte to return
+        ++QS_tail_;                                        // advance the tail
+        if (QS_tail_ == QS_end_) {                        // tail wrap around?
+            QS_tail_ = static_cast<QSCtr>(0);
+        }
+        --QS_used_;                                      // one less byte used
+    }
+    return ret;                                      // return the byte or EOD
+}
+
+QP_END_
+
+
+// "qs_f32.cpp" ==============================================================
+/// \brief QS::f32() implementation
+
+QP_BEGIN_
+
+//............................................................................
+void QS::f32(uint8_t const format, float32_t const d) {
+    union F32Rep {
+        float32_t f;
+        uint32_t  u;
+    } fu32;
+    fu32.f = d;
+
+    QS_INSERT_ESC_BYTE(format)
+    QS_INSERT_ESC_BYTE(static_cast<uint8_t>(fu32.u))
+    fu32.u >>= 8;
+    QS_INSERT_ESC_BYTE(static_cast<uint8_t>(fu32.u))
+    fu32.u >>= 8;
+    QS_INSERT_ESC_BYTE(static_cast<uint8_t>(fu32.u))
+    fu32.u >>= 8;
+    QS_INSERT_ESC_BYTE(static_cast<uint8_t>(fu32.u))
+}
+
+QP_END_
+
+
+// "qs_mem.cpp" ==============================================================
+/// \brief QS::mem() implementation
+
+QP_BEGIN_
+
+//............................................................................
+void QS::mem(uint8_t const *blk, uint8_t size) {
+    QS_INSERT_BYTE(static_cast<uint8_t>(QS_MEM_T))
+    QS_chksum_ =
+        static_cast<uint8_t>(QS_chksum_ + static_cast<uint8_t>(QS_MEM_T));
+    QS_INSERT_ESC_BYTE(size)
+    while (size != static_cast<uint8_t>(0)) {
+        QS_INSERT_ESC_BYTE(*blk)
+        ++blk;
+        --size;
+    }
+}
+
+QP_END_
+
+
+// "qs_str.cpp" ==============================================================
+/// \brief QS::str() and QS::str_ROM() implementation
+
+QP_BEGIN_
+
+//............................................................................
+void QS::str(char_t const *s) {
+    uint8_t b = static_cast<uint8_t>(*s);
+    QS_INSERT_BYTE(static_cast<uint8_t>(QS_STR_T))
+    QS_chksum_ =
+        static_cast<uint8_t>(QS_chksum_ + static_cast<uint8_t>(QS_STR_T));
+    while (b != static_cast<uint8_t>(0)) {
+                                       // ASCII characters don't need escaping
+        QS_INSERT_BYTE(b)
+        QS_chksum_ = static_cast<uint8_t>(QS_chksum_ + b);
+        ++s;
+        b = static_cast<uint8_t>(*s);
+    }
+    QS_INSERT_BYTE(static_cast<uint8_t>(0))
+}
+//............................................................................
+void QS::str_ROM(char_t const Q_ROM * Q_ROM_VAR s) {
+    uint8_t b = static_cast<uint8_t>(Q_ROM_BYTE(*s));
+    QS_INSERT_BYTE(static_cast<uint8_t>(QS_STR_T))
+    QS_chksum_ =
+        static_cast<uint8_t>(QS_chksum_ + static_cast<uint8_t>(QS_STR_T));
+    while (b != static_cast<uint8_t>(0)) {
+                                       // ASCII characters don't need escaping
+        QS_INSERT_BYTE(b)
+        QS_chksum_ = static_cast<uint8_t>(QS_chksum_ + b);
+        ++s;
+        b = static_cast<uint8_t>(Q_ROM_BYTE(*s));
+    }
+    QS_INSERT_BYTE(static_cast<uint8_t>(0))
+}
+
+QP_END_
+
+#endif                                                                // Q_SPY
--- a/qp.h	Mon Sep 26 03:27:09 2011 +0000
+++ b/qp.h	Tue Sep 04 22:20:52 2012 +0000
@@ -1,3618 +1,3731 @@
-//////////////////////////////////////////////////////////////////////////////
-// Product: QP/C++
-// Last Updated for QP ver: 4.2.04 (modified to fit in one file)
-// Date of the Last Update: Sep 25, 2011
-//
-//                    Q u a n t u m     L e a P s
-//                    ---------------------------
-//                    innovating embedded systems
-//
-// Copyright (C) 2002-2011 Quantum Leaps, LLC. All rights reserved.
-//
-// This software may be distributed and modified under the terms of the GNU
-// General Public License version 2 (GPL) as published by the Free Software
-// Foundation and appearing in the file GPL.TXT included in the packaging of
-// this file. Please note that GPL Section 2[b] requires that all works based
-// on this software must also be made publicly available under the terms of
-// the GPL ("Copyleft").
-//
-// Alternatively, this software may be distributed and modified under the
-// terms of Quantum Leaps commercial licenses, which expressly supersede
-// the GPL and are specifically designed for licensees interested in
-// retaining the proprietary status of their code.
-//
-// Contact information:
-// Quantum Leaps Web site:  http://www.quantum-leaps.com
-// e-mail:                  info@quantum-leaps.com
-//////////////////////////////////////////////////////////////////////////////
-#ifndef qp_h
-#define qp_h
-
-#ifdef Q_USE_NAMESPACE
-namespace QP {
-#endif
-
-// "qevent.h" ================================================================
-/// \brief QEvent class and basic macros used by all QP components.
-///
-/// This header file must be included, perhaps indirectly, in all modules
-/// (*.cpp files) that use any component of QP/C++ (such as QEP, QF, or QK).
-
-//////////////////////////////////////////////////////////////////////////////
-/// \brief The current QP version number
-///
-/// \return version of the QP as a hex constant constant 0xXYZZ, where X is
-/// a 1-digit major version number, Y is a 1-digit minor version number, and
-/// ZZ is a 2-digit release number.
-#define QP_VERSION      0x4204U
-
-#ifndef Q_ROM
-    /// \brief Macro to specify compiler-specific directive for placing a
-    /// constant object in ROM.
-    ///
-    /// Many compilers for Harvard-architecture MCUs provide non-stanard
-    /// extensions to support placement of objects in different memories.
-    /// In order to conserve the precious RAM, QP uses the Q_ROM macro for
-    /// all constant objects that can be allocated in ROM.
-    ///
-    /// To override the following empty definition, you need to define the
-    /// Q_ROM macro in the qep_port.h header file. Some examples of valid
-    /// Q_ROM macro definitions are: __code (IAR 8051 compiler), code (Keil
-    /// Cx51 compiler), PROGMEM (gcc for AVR), __flash (IAR for AVR).
-    #define Q_ROM
-#endif
-#ifndef Q_ROM_VAR            // if NOT defined, provide the default definition
-    /// \brief Macro to specify compiler-specific directive for accessing a
-    /// constant object in ROM.
-    ///
-    /// Many compilers for MCUs provide different size pointers for
-    /// accessing objects in various memories. Constant objects allocated
-    /// in ROM (see #Q_ROM macro) often mandate the use of specific-size
-    /// pointers (e.g., far pointers) to get access to ROM objects. The
-    /// macro Q_ROM_VAR specifies the kind of the pointer to be used to access
-    /// the ROM objects.
-    ///
-    /// To override the following empty definition, you need to define the
-    /// Q_ROM_VAR macro in the qep_port.h header file. An example of valid
-    /// Q_ROM_VAR macro definition is: __far (Freescale HC(S)08 compiler).
-    #define Q_ROM_VAR
-#endif
-#ifndef Q_ROM_BYTE
-    /// \brief Macro to access a byte allocated in ROM
-    ///
-    /// Some compilers for Harvard-architecture MCUs, such as gcc for AVR, do
-    /// not generate correct code for accessing data allocated in the program
-    /// space (ROM). The workaround for such compilers is to explictly add
-    /// assembly code to access each data element allocated in the program
-    /// space. The macro Q_ROM_BYTE() retrieves a byte from the given ROM
-    /// address.
-    ///
-    /// The Q_ROM_BYTE() macro should be defined for the compilers that
-    /// cannot handle correctly data allocated in ROM (such as the gcc).
-    /// If the macro is left undefined, the default definition simply returns
-    /// the argument and lets the compiler generate the correct code.
-    #define Q_ROM_BYTE(rom_var_)   (rom_var_)
-#endif
-
-#ifndef Q_SIGNAL_SIZE
-    /// \brief The size (in bytes) of the signal of an event. Valid values:
-    /// 1, 2, or 4; default 1
-    ///
-    /// This macro can be defined in the QEP port file (qep_port.h) to
-    /// configure the ::QSignal type. When the macro is not defined, the
-    /// default of 1 byte is chosen.
-    #define Q_SIGNAL_SIZE 2
-#endif
-#if (Q_SIGNAL_SIZE == 1)
-    typedef uint8_t QSignal;
-#elif (Q_SIGNAL_SIZE == 2)
-    /// \brief QSignal represents the signal of an event.
-    ///
-    /// The relationship between an event and a signal is as follows. A signal
-    /// in UML is the specification of an asynchronous stimulus that triggers
-    /// reactions [<A HREF="http://www.omg.org/docs/ptc/03-08-02.pdf">UML
-    /// document ptc/03-08-02</A>], and as such is an essential part of an
-    /// event. (The signal conveys the type of the occurrence-what happened?)
-    /// However, an event can also contain additional quantitative information
-    /// about the occurrence in form of event parameters. Please refer to the
-    typedef uint16_t QSignal;
-#elif (Q_SIGNAL_SIZE == 4)
-    typedef uint32_t QSignal;
-#else
-    #error "Q_SIGNAL_SIZE defined incorrectly, expected 1, 2, or 4"
-#endif
-
-//////////////////////////////////////////////////////////////////////////////
-/// \brief QEvent base class.
-///
-/// QEvent represents events without parameters and serves as the base class
-/// for derivation of events with parameters.
-///
-/// \note All data members of the QEvent class must remain public to keep it
-/// an AGGREGATE. Therefore, the attribute QEvent::dynamic_ cannot be
-/// declared private.
-///
-/// The following example illustrates how to add an event parameter by
-/// inheriting from the QEvent class.
-/// \include qep_qevent.cpp
-struct QEvent {
-    QSignal sig;                             ///< signal of the event instance
-    uint8_t poolId_;                         ///< pool ID (0 for static event)
-    uint8_t refCtr_;                                    ///< reference counter
-
-#ifdef Q_EVT_CTOR
-    QEvent(QSignal s) : sig(s) {}
-    virtual ~QEvent() {}                                 // virtual destructor
-#endif
-};
-
-//////////////////////////////////////////////////////////////////////////////
-/// helper macro to calculate static dimension of a 1-dim array \a array_
-#define Q_DIM(array_) (sizeof(array_) / sizeof(array_[0]))
-
-// "qep.h" ===================================================================
-/// \brief QEP/C++ platform-independent public interface.
-///
-/// This header file must be included directly or indirectly
-/// in all modules (*.cpp files) that use QEP/C++.
-
-//////////////////////////////////////////////////////////////////////////////
-/// \brief Provides miscellaneous QEP services.
-class QEP {
-public:
-    /// \brief get the current QEP version number string
-    ///
-    /// \return version of the QEP as a constant 6-character string of the
-    /// form x.y.zz, where x is a 1-digit major version number, y is a
-    /// 1-digit minor version number, and zz is a 2-digit release number.
-    static char const Q_ROM * Q_ROM_VAR getVersion(void);
-};
-
-//////////////////////////////////////////////////////////////////////////////
-
-                       /// \brief Type returned from  a state-handler function
-typedef uint8_t QState;
-
-                                  /// \brief pointer to state-handler function
-typedef QState (*QStateHandler)(void *me, QEvent const *e);
-
-
-//////////////////////////////////////////////////////////////////////////////
-/// \brief Finite State Machine base class
-///
-/// QFsm represents a traditional non-hierarchical Finite State Machine (FSM)
-/// without state hierarchy, but with entry/exit actions.
-///
-/// QFsm is also a base structure for the ::QHsm class.
-///
-/// \note QFsm is not intended to be instantiated directly, but rather serves
-/// as the base class for derivation of state machines in the application
-/// code.
-///
-/// The following example illustrates how to derive a state machine class
-/// from QFsm.
-/// \include qep_qfsm.cpp
-class QFsm {
-protected:
-    QStateHandler m_state;          ///< current active state (state-variable)
-
-public:
-    /// \brief virtual destructor
-    virtual ~QFsm();
-
-    /// \brief Performs the second step of FSM initialization by triggering
-    /// the top-most initial transition.
-    ///
-    /// The argument \a e is constant pointer to ::QEvent or a class
-    /// derived from ::QEvent.
-    ///
-    /// \note Must be called only ONCE before QFsm::dispatch()
-    ///
-    /// The following example illustrates how to initialize a FSM, and
-    /// dispatch events to it:
-    /// \include qep_qfsm_use.cpp
-    void init(QEvent const *e = (QEvent *)0);
-
-    /// \brief Dispatches an event to a FSM
-    ///
-    /// Processes one event at a time in Run-to-Completion (RTC) fashion.
-    /// The argument \a e is a constant pointer the ::QEvent or a
-    /// class derived from ::QEvent.
-    ///
-    /// \note Must be called after QFsm::init().
-    ///
-    /// \sa example for QFsm::init()
-    void dispatch(QEvent const *e);
-
-protected:
-
-    /// \brief Protected constructor of a FSM.
-    ///
-    /// Performs the first step of FSM initialization by assigning the
-    /// initial pseudostate to the currently active state of the state
-    /// machine.
-    ///
-    /// \note The constructor is protected to prevent direct instantiating
-    /// of QFsm objects. This class is intended for subclassing only.
-    ///
-    /// \sa The ::QFsm example illustrates how to use the QHsm constructor
-    /// in the constructor initializer list of the derived state machines.
-    QFsm(QStateHandler initial) : m_state(initial) {}
-};
-
-//////////////////////////////////////////////////////////////////////////////
-/// \brief Hierarchical State Machine base class
-///
-/// QHsm represents a Hierarchical Finite State Machine (HSM). QHsm derives
-/// from the ::QFsm class and extends the capabilities of a basic FSM
-/// with state hierarchy.
-///
-/// \note QHsm is not intended to be instantiated directly, but rather serves
-/// as the base structure for derivation of state machines in the application
-/// code.
-///
-/// The following example illustrates how to derive a state machine class
-/// from QHsm.
-/// \include qep_qhsm.cpp
-class QHsm {
-protected:
-    QStateHandler m_state;          ///< current active state (state-variable)
-
-public:
-    /// \brief virtual destructor
-    virtual ~QHsm();
-
-    /// \brief Performs the second step of HSM initialization by triggering
-    /// the top-most initial transition.
-    ///
-    /// \param e constant pointer ::QEvent or a class derived from ::QEvent
-    /// \note Must be called only ONCE before QHsm::dispatch()
-    ///
-    /// The following example illustrates how to initialize a HSM, and
-    /// dispatch events to it:
-    /// \include qep_qhsm_use.cpp
-    void init(QEvent const *e = (QEvent *)0);
-
-    /// \brief Dispatches an event to a HSM
-    ///
-    /// Processes one event at a time in Run-to-Completion (RTC) fashion.
-    /// The argument \a e is a constant pointer the ::QEvent or a
-    /// class derived from ::QEvent.
-    ///
-    /// \note Must be called after QHsm::init().
-    ///
-    /// \sa example for QHsm::init()
-    void dispatch(QEvent const *e);
-
-    /// \brief Tests if a given state is part of the current active state
-    /// configuratioin
-    ///
-    /// \param state is a pointer to the state handler function, e.g.,
-    /// &QCalc::on.
-    uint8_t isIn(QStateHandler state);
-
-protected:
-
-    /// \brief Protected constructor of a HSM.
-    ///
-    /// Performs the first step of HSM initialization by assigning the
-    /// initial pseudostate to the currently active state of the state
-    /// machine.
-    ///
-    /// \note The constructor is protected to prevent direct instantiating
-    /// of QHsm objects. This class is intended for subclassing only.
-    ///
-    /// \sa The ::QHsm example illustrates how to use the QHsm constructor
-    /// in the constructor initializer list of the derived state machines.
-    /// \sa QFsm::QFsm()
-    QHsm(QStateHandler initial) : m_state(initial) {}
-
-    /// \brief the top-state.
-    ///
-    /// QHsm::top() is the ultimate root of state hierarchy in all HSMs
-    /// derived from ::QHsm. This state handler always returns (QSTATE)0,
-    /// which means that it "handles" all events.
-    ///
-    /// \sa Example of the QCalc::on() state handler.
-    static QState top(QHsm *me, QEvent const *e);
-};
-
-/// \brief Value returned by a non-hierarchical state-handler function when
-/// it ignores (does not handle) the event.
-#define Q_RET_IGNORED       ((QState)1)
-
-/// \brief The macro returned from a non-hierarchical state-handler function
-/// when it ignores (does not handle) the event.
-///
-/// You call that macro after the return statement (return Q_IGNORED();)
-///
-/// \include qepn_qfsm.cpp
-#define Q_IGNORED()         (Q_RET_IGNORED)
-
-/// \brief Value returned by a state-handler function when it handles
-/// the event.
-#define Q_RET_HANDLED       ((QState)0)
-
-/// \brief Value returned by a state-handler function when it handles
-/// the event.
-///
-/// You call that macro after the return statement (return Q_HANDLED();)
-/// Q_HANDLED() can be used both in the FSMs and HSMs.
-///
-/// \include qepn_qfsm.cpp
-#define Q_HANDLED()         (Q_RET_HANDLED)
-
-/// \brief Value returned by a state-handler function when it takes a
-/// regular state transition.
-#define Q_RET_TRAN          ((QState)2)
-
-/// \brief Designates a target for an initial or regular transition.
-/// Q_TRAN() can be used both in the FSMs and HSMs.
-///
-/// \include qepn_qtran.cpp
-//lint -e960 -e1924 ignore MISRA Rule 42 (comma operator) and C-style cast
-#define Q_TRAN(target_)  \
-    (me->m_state = (QStateHandler)(target_), Q_RET_TRAN)
-
-/// \brief Value returned by a state-handler function when it cannot
-/// handle the event.
-#define Q_RET_SUPER         ((QState)3)
-
-/// \brief Designates the superstate of a given state in an HSM.
-///
-/// \include qep_qhsm.cpp
-//lint -e960 -e1924 ignore MISRA Rule 42 (comma operator) and C-style cast
-#define Q_SUPER(super_)  \
-    (me->m_state = (QStateHandler)(super_),  Q_RET_SUPER)
-
-//////////////////////////////////////////////////////////////////////////////
-/// \brief QEP reserved signals.
-enum QReservedSignals {
-    Q_ENTRY_SIG = 1,                             ///< signal for entry actions
-    Q_EXIT_SIG,                                   ///< signal for exit actions
-    Q_INIT_SIG,                     ///< signal for nested initial transitions
-    Q_USER_SIG                              ///< signal to offset user signals
-};
-
-// "qequeue.h" ===============================================================
-/// \brief platform-independent event queue interface.
-///
-/// This header file must be included in all QF ports that use native QF
-/// event queue implementation. Also, this file is needed when the "raw"
-/// thread-safe queues are used for communication between active objects
-/// and non-framework entities, such as ISRs, device drivers, or legacy
-/// code.
-
-#ifndef QF_EQUEUE_CTR_SIZE
-
-    /// \brief The size (in bytes) of the ring-buffer counters used in the
-    /// native QF event queue implementation. Valid values: 1, 2, or 4;
-    /// default 1.
-    ///
-    /// This macro can be defined in the QF port file (qf_port.h) to
-    /// configure the ::QEQueueCtr type. Here the macro is not defined so the
-    /// default of 1 byte is chosen.
-    #define QF_EQUEUE_CTR_SIZE 1
-#endif
-#if (QF_EQUEUE_CTR_SIZE == 1)
-
-    /// \brief The data type to store the ring-buffer counters based on
-    /// the macro #QF_EQUEUE_CTR_SIZE.
-    ///
-    /// The dynamic range of this data type determines the maximum length
-    /// of the ring buffer managed by the native QF event queue.
-    typedef uint8_t QEQueueCtr;
-#elif (QF_EQUEUE_CTR_SIZE == 2)
-    typedef uint16_t QEQueueCtr;
-#elif (QF_EQUEUE_CTR_SIZE == 4)
-    typedef uint32_t QEQueueCtr;
-#else
-    #error "QF_EQUEUE_CTR_SIZE defined incorrectly, expected 1, 2, or 4"
-#endif
-
-
-//////////////////////////////////////////////////////////////////////////////
-/// \brief Native QF Event Queue class
-///
-/// This structure describes the native QF event queue, which can be used as
-/// the event queue for active objects, or as a simple "raw" event queue for
-/// thread-safe event passing among non-framework entities, such as ISRs,
-/// device drivers, or other third-party components.
-///
-/// The native QF event queue is configured by defining the macro
-/// #QF_EQUEUE_TYPE as ::QEQueue in the specific QF port header file.
-///
-/// The ::QEQueue structure contains only data members for managing an event
-/// queue, but does not contain the storage for the queue buffer, which must
-/// be provided externally during the queue initialization.
-///
-/// The event queue can store only event pointers, not the whole events. The
-/// internal implementation uses the standard ring-buffer plus one external
-/// location that optimizes the queue operation for the most frequent case
-/// of empty queue.
-///
-/// The ::QEQueue structure is used with two sets of functions. One set is for
-/// the active object event queue, which needs to block the active object
-/// task when the event queue is empty and unblock it when events are posted
-/// to the queue. The interface for the native active object event queue
-/// consists of the following functions: QActive::postFIFO_(),
-/// QActive::postLIFO_(), and QActive::get_(). Additionally the function
-/// QEQueue_init() is used to initialize the queue.
-///
-/// The other set of functions, uses this structure as a simple "raw" event
-/// queue to pass events between entities other than active objects, such as
-/// ISRs. The "raw" event queue is not capable of blocking on the get()
-/// operation, but is still thread-safe because it uses QF critical section
-/// to protect its integrity. The interface for the "raw" thread-safe queue
-/// consists of the following functions: QEQueue::postFIFO(),
-/// QEQueue::postLIFO(), and QEQueue::get(). Additionally the function
-/// QEQueue::init() is used to initialize the queue.
-///
-/// \note Most event queue operations (both the active object queues and
-/// the "raw" queues) internally use  the QF critical section. You should be
-/// careful not to invoke those operations from other critical sections when
-/// nesting of critical sections is not supported.
-class QEQueue {
-private:
-
-    /// \brief pointer to event at the front of the queue
-    ///
-    /// All incoming and outgoing events pass through the m_frontEvt location.
-    /// When the queue is empty (which is most of the time), the extra
-    /// m_frontEvt location allows to bypass the ring buffer altogether,
-    /// greatly optimizing the performance of the queue. Only bursts of events
-    /// engage the ring buffer.
-    ///
-    /// The additional role of this attribute is to indicate the empty status
-    /// of the queue. The queue is empty if the m_frontEvt location is NULL.
-    QEvent const *m_frontEvt;
-
-    /// \brief pointer to the start of the ring buffer
-    QEvent const **m_ring;
-
-    /// \brief offset of the end of the ring buffer from the start of the
-    /// buffer m_ring
-    QEQueueCtr m_end;
-
-    /// \brief offset to where next event will be inserted into the buffer
-    QEQueueCtr m_head;
-
-    /// \brief offset of where next event will be extracted from the buffer
-    QEQueueCtr m_tail;
-
-    /// \brief number of free events in the ring buffer
-    QEQueueCtr m_nFree;
-
-    /// \brief minimum number of free events ever in the ring buffer.
-    ///
-    /// \note this attribute remembers the low-watermark of the ring buffer,
-    /// which provides a valuable information for sizing event queues.
-    /// \sa QF::getQueueMargin().
-    QEQueueCtr m_nMin;
-
-public:
-
-    /// \brief Initializes the native QF event queue
-    ///
-    /// The parameters are as follows: \a qSto[] is the ring buffer storage,
-    /// \a qLen is the length of the ring buffer in the units of event-
-    /// pointers.
-    ///
-    /// \note The actual capacity of the queue is qLen + 1, because of the
-    /// extra location fornEvt_.
-    void init(QEvent const *qSto[], QEQueueCtr qLen);
-
-    /// \brief "raw" thread-safe QF event queue implementation for the
-    /// First-In-First-Out (FIFO) event posting. You can call this function
-    /// from any task context or ISR context. Please note that this function
-    /// uses internally a critical section.
-    ///
-    /// \note The function raises an assertion if the native QF queue becomes
-    /// full and cannot accept the event.
-    ///
-    /// \sa QEQueue::postLIFO(), QEQueue::get()
-    void postFIFO(QEvent const *e);
-
-    /// \brief "raw" thread-safe QF event queue implementation for the
-    /// First-In-First-Out (FIFO) event posting. You can call this function
-    /// from any task context or ISR context. Please note that this function
-    ///  uses internally a critical section.
-    ///
-    /// \note The function raises an assertion if the native QF queue becomes
-    /// full and cannot accept the event.
-    ///
-    /// \sa QEQueue::postLIFO(), QEQueue::get()
-    void postLIFO(QEvent const *e);
-
-    /// \brief "raw" thread-safe QF event queue implementation for the
-    /// Last-In-First-Out (LIFO) event posting.
-    ///
-    /// \note The LIFO policy should be used only with great caution because
-    /// it alters order of events in the queue.
-    /// \note The function raises an assertion if the native QF queue becomes
-    /// full and cannot accept the event. You can call this function from
-    /// any task context or ISR context. Please note that this function uses
-    /// internally a critical section.
-    ///
-    /// \sa QEQueue::postFIFO(), QEQueue::get()
-    QEvent const *get(void);
-
-    /// \brief "raw" thread-safe QF event queue operation for
-    /// obtaining the number of free entries still available in the queue.
-    ///
-    /// \note This operation needs to be used with caution because the
-    /// number of free entries can change unexpectedly. The main intent for
-    /// using this operation is in conjunction with event deferral. In this
-    /// case the queue is accessed only from a single thread (by a single AO),
-    /// so the number of free entries cannot change unexpectedly.
-    ///
-    /// \sa QActive::defer(), QActive::recall()
-    QEQueueCtr getNFree(void) const {
-        return m_nFree;
-    }
-
-private:
-    friend class QF;
-    friend class QActive;
-};
-
-// "qmpool.h" ================================================================
-/// \brief platform-independent memory pool interface.
-///
-/// This header file must be included in all QF ports that use native QF
-/// memory pool implementation.
-
-
-//////////////////////////////////////////////////////////////////////////////
-#ifndef QF_MPOOL_SIZ_SIZE
-    /// \brief macro to override the default ::QMPoolSize size.
-    /// Valid values 1, 2, or 4; default 2
-    #define QF_MPOOL_SIZ_SIZE 2
-#endif
-#if (QF_MPOOL_SIZ_SIZE == 1)
-
-    /// \brief The data type to store the block-size based on the macro
-    /// #QF_MPOOL_SIZ_SIZE.
-    ///
-    /// The dynamic range of this data type determines the maximum size
-    /// of blocks that can be managed by the native QF event pool.
-    typedef uint8_t QMPoolSize;
-#elif (QF_MPOOL_SIZ_SIZE == 2)
-
-    typedef uint16_t QMPoolSize;
-#elif (QF_MPOOL_SIZ_SIZE == 4)
-    typedef uint32_t QMPoolSize;
-#else
-    #error "QF_MPOOL_SIZ_SIZE defined incorrectly, expected 1, 2, or 4"
-#endif
-
-//////////////////////////////////////////////////////////////////////////////
-#ifndef QF_MPOOL_CTR_SIZE
-
-    /// \brief macro to override the default QMPoolCtr size.
-    /// Valid values 1, 2, or 4; default 2
-    #define QF_MPOOL_CTR_SIZE 2
-#endif
-#if (QF_MPOOL_CTR_SIZE == 1)
-
-    /// \brief The data type to store the block-counter based on the macro
-    /// #QF_MPOOL_CTR_SIZE.
-    ///
-    /// The dynamic range of this data type determines the maximum number
-    /// of blocks that can be stored in the pool.
-    typedef uint8_t QMPoolCtr;
-#elif (QF_MPOOL_CTR_SIZE == 2)
-    typedef uint16_t QMPoolCtr;
-#elif (QF_MPOOL_CTR_SIZE == 4)
-    typedef uint32_t QMPoolCtr;
-#else
-    #error "QF_MPOOL_CTR_SIZE defined incorrectly, expected 1, 2, or 4"
-#endif
-
-//////////////////////////////////////////////////////////////////////////////
-/// \brief Native QF memory pool class
-///
-/// This class describes the native QF memory pool, which can be used as
-/// the event pool for dynamic event allocation, or as a fast, deterministic
-/// fixed block-size heap for any other objects in your application.
-///
-/// The ::QMPool structure contains only data members for managing a memory
-/// pool, but does not contain the pool storage, which must be provided
-/// externally during the pool initialization.
-///
-/// The native QF event pool is configured by defining the macro
-/// #QF_EPOOL_TYPE_ as QEQueue in the specific QF port header file.
-class QMPool {
-private:
-
-    /// start of the memory managed by this memory pool
-    void *m_start;
-
-    /// end of the memory managed by this memory pool
-    void *m_end;
-
-    /// linked list of free blocks
-    void *m_free;
-
-    ///  maximum block size (in bytes)
-    QMPoolSize m_blockSize;
-
-    /// total number of blocks
-    QMPoolCtr m_nTot;
-
-    /// number of free blocks remaining
-    QMPoolCtr m_nFree;
-
-    /// minimum number of free blocks ever present in this pool
-    ///
-    /// \note this attribute remembers the low watermark of the pool,
-    /// which provides a valuable information for sizing event pools.
-    /// \sa QF::getPoolMargin().
-    QMPoolCtr m_nMin;
-
-public:
-
-    /// \brief Initializes the native QF event pool
-    ///
-    /// The parameters are as follows: \a poolSto is the pool storage,
-    /// \a poolSize is the size of the pool storage in bytes, and
-    /// \a blockSize is the block size of this pool.
-    ///
-    /// The caller of this method must make sure that the \a poolSto pointer
-    /// is properly aligned. In particular, it must be possible to efficiently
-    /// store a pointer at the location pointed to by \a poolSto.
-    /// Internally, the QMPool::init() function rounds up the block size
-    /// \a blockSize so that it can fit an integer number of pointers.
-    /// This is done to achieve proper alignment of the blocks within the
-    /// pool.
-    ///
-    /// \note Due to the rounding of block size the actual capacity of the
-    /// pool might be less than (\a poolSize / \a blockSize). You can check
-    ///  the capacity of the pool by calling the QF::getPoolMargin() function.
-    void init(void *poolSto, uint32_t poolSize, QMPoolSize blockSize);
-
-    /// \brief Obtains a memory block from a memory pool.
-    ///
-    /// The only parameter \a me is a pointer to the ::QMPool from which the
-    /// block is requested. The function returns a pointer to the allocated
-    /// memory block or NULL if no free blocks are available.
-    ///
-    /// A allocated block must be returned to the same pool from which it has
-    /// been allocated.
-    ///
-    /// This function can be called from any task level or ISR level.
-    ///
-    /// \note The memory pool \a me must be initialized before any events can
-    /// be requested from it. Also, the QMPool::get() function uses internally
-    /// a QF critical section, so you should be careful not to call it from
-    /// within a critical section when nesting of critical section is not
-    /// supported.
-    ///
-    /// \sa QMPool::put()
-    void *get(void);
-
-    /// \brief Returns a memory block back to a memory pool.
-    ///
-    ///
-    /// This function can be called from any task level or ISR level.
-    ///
-    /// \note The block must be allocated from the same memory pool to which
-    /// it is returned. The QMPool::put() function raises an assertion if the
-    /// returned pointer to the block points outside of the original memory
-    /// buffer managed by the memory pool. Also, the QMPool::put() function
-    /// uses internally a QF critical section, so you should be careful not
-    /// to call it from within a critical section when nesting of critical
-    /// section is not supported.
-    ///
-    /// \sa QMPool::get()
-    void put(void *b);
-
-    /// \brief return the fixed block-size of the blocks managed by this pool
-    QMPoolSize getBlockSize(void) const {
-        return m_blockSize;
-    }
-
-private:
-    friend class QF;
-};
-
-// "qpset.h" =================================================================
-/// \brief platform-independent priority sets of 8 or 64 elements.
-///
-/// This header file must be included in those QF ports that use the
-/// cooperative multitasking QF scheduler or the QK.
-
-                      // external declarations of QF lookup tables used inline
-extern uint8_t const Q_ROM Q_ROM_VAR QF_log2Lkup[256];
-extern uint8_t const Q_ROM Q_ROM_VAR QF_pwr2Lkup[65];
-extern uint8_t const Q_ROM Q_ROM_VAR QF_invPwr2Lkup[65];
-extern uint8_t const Q_ROM Q_ROM_VAR QF_div8Lkup[65];
-
-//////////////////////////////////////////////////////////////////////////////
-/// \brief Priority Set of up to 8 elements for building various schedulers,
-/// but also useful as a general set of up to 8 elements of any kind.
-///
-/// The priority set represents the set of active objects that are ready to
-/// run and need to be considered by scheduling processing. The set is capable
-/// of storing up to 8 priority levels.
-class QPSet8 {
-protected:
-    //////////////////////////////////////////////////////////////////////////
-    /// \brief bimask representing elements of the set
-    uint8_t m_bits;
-
-public:
-
-    /// \brief the function evaluates to TRUE if the priority set is empty,
-    /// which means that no active objects are ready to run.
-    uint8_t isEmpty(void) volatile {
-        return (uint8_t)(m_bits == (uint8_t)0);
-    }
-
-    /// \brief the function evaluates to TRUE if the priority set has elements,
-    /// which means that some active objects are ready to run.
-    uint8_t notEmpty(void) volatile {
-        return (uint8_t)(m_bits != (uint8_t)0);
-    }
-
-    /// \brief the function evaluates to TRUE if the priority set has the
-    /// element \a n.
-    uint8_t hasElement(uint8_t n) volatile {
-        return (uint8_t)((m_bits & Q_ROM_BYTE(QF_pwr2Lkup[n])) != 0);
-    }
-
-    /// \brief insert element \a n into the set, n = 1..8
-    void insert(uint8_t n) volatile {
-        m_bits |= Q_ROM_BYTE(QF_pwr2Lkup[n]);
-    }
-
-    /// \brief remove element \a n from the set, n = 1..8
-    void remove(uint8_t n) volatile {
-        m_bits &= Q_ROM_BYTE(QF_invPwr2Lkup[n]);
-    }
-
-    /// \brief find the maximum element in the set,
-    /// \note returns zero if the set is empty
-    uint8_t findMax(void) volatile {
-        return Q_ROM_BYTE(QF_log2Lkup[m_bits]);
-    }
-
-    friend class QPSet64;
-};
-
-//////////////////////////////////////////////////////////////////////////////
-/// \brief Priority Set of up to 64 elements for building various schedulers,
-/// but also useful as a general set of up to 64 elements of any kind.
-///
-/// The priority set represents the set of active objects that are ready to
-/// run and need to be considered by scheduling processing. The set is capable
-/// of storing up to 64 priority levels.
-///
-/// The priority set allows to build cooperative multitasking schedulers
-/// to manage up to 64 tasks. It is also used in the Quantum Kernel (QK)
-/// preemptive scheduler.
-///
-/// The inherited 8-bit set is used as the 8-elemtn set of of 8-bit subsets
-/// Each bit in the super.bits set represents a subset (8-elements)
-/// as follows: \n
-/// bit 0 in this->m_bits is 1 when subset[0] is not empty \n
-/// bit 1 in this->m_bits is 1 when subset[1] is not empty \n
-/// bit 2 in this->m_bits is 1 when subset[2] is not empty \n
-/// bit 3 in this->m_bits is 1 when subset[3] is not empty \n
-/// bit 4 in this->m_bits is 1 when subset[4] is not empty \n
-/// bit 5 in this->m_bits is 1 when subset[5] is not empty \n
-/// bit 6 in this->m_bits is 1 when subset[6] is not empty \n
-/// bit 7 in this->m_bits is 1 when subset[7] is not empty \n
-class QPSet64 : public QPSet8 {
-
-    /// \brief subsets representing elements in the set as follows: \n
-    /// m_subset[0] represent elements  1..8  \n
-    /// m_subset[1] represent elements  9..16 \n
-    /// m_subset[2] represent elements 17..24 \n
-    /// m_subset[3] represent elements 25..32 \n
-    /// m_subset[4] represent elements 33..40 \n
-    /// m_subset[5] represent elements 41..48 \n
-    /// m_subset[6] represent elements 49..56 \n
-    /// m_subset[7] represent elements 57..64 \n
-    QPSet8 m_subset[8];
-
-public:
-
-    /// \brief the function evaluates to TRUE if the priority set has the
-    /// element \a n.
-    uint8_t hasElement(uint8_t n) volatile {
-         return m_subset[Q_ROM_BYTE(QF_div8Lkup[n])].QPSet8::hasElement(n);
-    }
-
-    /// \brief insert element \a n into the set, n = 1..64
-    void insert(uint8_t n) volatile {
-        QPSet8::insert(Q_ROM_BYTE(QF_div8Lkup[n]) + 1);
-        m_subset[Q_ROM_BYTE(QF_div8Lkup[n])].QPSet8::insert(n);
-    }
-
-    /// \brief remove element \a n from the set, n = 1..64
-    void remove(uint8_t n) volatile {
-        if ((m_subset[Q_ROM_BYTE(QF_div8Lkup[n])].m_bits
-                 &= Q_ROM_BYTE(QF_invPwr2Lkup[n])) == (uint8_t)0)
-        {
-            QPSet8::remove(Q_ROM_BYTE(QF_div8Lkup[n]) + 1);
-        }
-    }
-
-    /// \brief find the maximum element in the set,
-    /// \note returns zero if the set is empty
-    uint8_t findMax(void) volatile {
-        if (m_bits != (uint8_t)0) {
-            uint8_t n = (uint8_t)(Q_ROM_BYTE(QF_log2Lkup[m_bits]) - 1);
-            return (uint8_t)(Q_ROM_BYTE(QF_log2Lkup[m_subset[n].m_bits])
-                             + (n << 3));
-        }
-        else {
-            return (uint8_t)0;
-        }
-    }
-};
-
-
-//////////////////////////////////////////////////////////////////////////////
-// Kernel selection based on QK_PREEMPTIVE
-//
-#ifdef QK_PREEMPTIVE
-
-/// \brief This macro defines the type of the event queue used for the
-/// active objects.
-///
-/// \note This is just an example of the macro definition. Typically, you need
-/// to define it in the specific QF port file (qf_port.h). In case of QK,
-/// which always depends on the native QF queue, this macro is defined at the
-/// level of the platform-independent interface qk.h.
-#define QF_EQUEUE_TYPE             QEQueue
-
-#if defined(QK_TLS) || defined(QK_EXT_SAVE)
-    /// \brief This macro defines the type of the OS-Object used for blocking
-    /// the native QF event queue when the queue is empty
-    ///
-    /// In QK, the OS object is used to hold the per-thread flags, which might
-    /// be used, for example, to rembember the thread attributes (e.g.,
-    /// if the thread uses a floating point co-processor). The OS object value
-    /// is set on per-thread basis in QActive::start(). Later, the extended
-    /// context switch macros (QK_EXT_SAVE() and QK_EXT_RESTORE()) might use
-    /// the per-thread flags to determine what kind of extended context switch
-    /// this particular thread needs (e.g., the thread might not be using the
-    /// coprocessor or might be using a different one).
-    #define QF_OS_OBJECT_TYPE      uint8_t
-
-    /// \brief This macro defines the type of the thread handle used for the
-    /// active objects.
-    ///
-    /// The thread type in QK is the pointer to the thread-local storage (TLS)
-    /// This thread-local storage can be set on per-thread basis in
-    /// QActive::start(). Later, the QK scheduler, passes the pointer to the
-    /// thread-local storage to the macro #QK_TLS.
-    #define QF_THREAD_TYPE         void *
-#endif                                             /* QK_TLS || QK_EXT_SAVE */
-
-#if (QF_MAX_ACTIVE <= 8)
-    extern QPSet8  volatile QK_readySet_;                 ///< ready set of QK
-#else
-    extern QPSet64 volatile QK_readySet_;                 ///< ready set of QK
-#endif
-
-#ifdef Q_USE_NAMESPACE
-}                                                              // namespace QP
-#endif
-
-extern "C" {
-
-extern uint8_t volatile QK_currPrio_;     ///< current task/interrupt priority
-extern uint8_t volatile QK_intNest_;              ///< interrupt nesting level
-
-}                                                                // extern "C"
-
-#ifdef Q_USE_NAMESPACE
-namespace QP {
-#endif
-
-// QK active object queue implementation .....................................
-
-/// \brief Platform-dependent macro defining how QF should block the calling
-/// task when the QF native queue is empty
-///
-/// \note This is just an example of #QACTIVE_EQUEUE_WAIT_ for the QK-port
-/// of QF. QK never activates a task that has no events to process, so in this
-/// case the macro asserts that the queue is not empty. In other QF ports you
-// need to define the macro appropriately for the underlying kernel/OS you're
-/// using.
-#define QACTIVE_EQUEUE_WAIT_(me_) \
-    Q_ASSERT((me_)->m_eQueue.m_frontEvt != (QEvent *)0)
-
-/// \brief Platform-dependent macro defining how QF should signal the
-/// active object task that an event has just arrived.
-///
-/// The macro is necessary only when the native QF event queue is used.
-/// The signaling of task involves unblocking the task if it is blocked.
-///
-/// \note #QACTIVE_EQUEUE_SIGNAL_ is called from a critical section.
-/// It might leave the critical section internally, but must restore
-/// the critical section before exiting to the caller.
-///
-/// \note This is just an example of #QACTIVE_EQUEUE_SIGNAL_ for the QK-port
-/// of QF. In other QF ports you need to define the macro appropriately for
-/// the underlying kernel/OS you're using.
-#define QACTIVE_EQUEUE_SIGNAL_(me_) \
-    QK_readySet_.insert((me_)->m_prio); \
-    if (QK_intNest_ == (uint8_t)0) { \
-        QK_SCHEDULE_(); \
-    } else ((void)0)
-
-/// \brief Platform-dependent macro defining the action QF should take
-/// when the native QF event queue becomes empty.
-///
-/// \note #QACTIVE_EQUEUE_ONEMPTY_ is called from a critical section.
-/// It should not leave the critical section.
-///
-/// \note This is just an example of #QACTIVE_EQUEUE_ONEMPTY_ for the QK-port
-/// of QF. In other QF ports you need to define the macro appropriately for
-/// the underlying kernel/OS you're using.
-#define QACTIVE_EQUEUE_ONEMPTY_(me_) \
-    QK_readySet_.remove((me_)->m_prio)
-
-// QK event pool operations ..................................................
-
-/// \brief This macro defines the type of the event pool used in this QF port.
-///
-/// \note This is just an example of the macro definition. Typically, you need
-/// to define it in the specific QF port file (qf_port.h). In case of QK,
-/// which always depends on the native QF memory pool, this macro is defined
-/// at the level of the platform-independent interface qk.h.
-#define QF_EPOOL_TYPE_              QMPool
-
-/// \brief Platform-dependent macro defining the event pool initialization
-///
-/// \note This is just an example of #QF_EPOOL_INIT_ for the QK-port of QF.
-/// In other QF ports you need to define the macro appropriately for the
-/// underlying kernel/OS you're using.
-#define QF_EPOOL_INIT_(p_, poolSto_, poolSize_, evtSize_) \
-    (p_).init(poolSto_, poolSize_, evtSize_)
-
-/// \brief Platform-dependent macro defining how QF should obtain the
-/// event pool block-size
-///
-/// \note This is just an example of #QF_EPOOL_EVENT_SIZE_ for the QK-port
-/// of QF. In other QF ports you need to define the macro appropriately for
-/// the underlying kernel/OS you're using.
-#define QF_EPOOL_EVENT_SIZE_(p_)    ((p_).getBlockSize())
-
-/// \brief Platform-dependent macro defining how QF should obtain an event
-/// \a e_ from the event pool \a p_
-///
-/// \note This is just an example of #QF_EPOOL_GET_ for the QK-port of QF.
-/// In other QF ports you need to define the macro appropriately for the
-/// underlying kernel/OS you're using.
-#define QF_EPOOL_GET_(p_, e_)       ((e_) = (QEvent *)(p_).get())
-
-/// \brief Platform-dependent macro defining how QF should return an event
-/// \a e_ to the event pool \a p_
-///
-/// \note This is just an example of #QF_EPOOL_PUT_ for the QK-port of QF.
-/// In other QF ports you need to define the macro appropriately for the
-/// underlying kernel/OS you're using.
-#define QF_EPOOL_PUT_(p_, e_)       ((p_).put(e_))
-
-#ifndef QK_NO_MUTEX
-    //////////////////////////////////////////////////////////////////////////
-    /// \brief QK Mutex type.
-    ///
-    /// QMutex represents the priority-ceiling mutex available in QK.
-    /// \sa QK::mutexLock()
-    /// \sa QK::mutexUnlock()
-    typedef uint8_t QMutex;
-#endif                                                          // QK_NO_MUTEX
-
-//////////////////////////////////////////////////////////////////////////////
-/// \brief QK services.
-///
-/// This class groups together QK services. It has only static members and
-/// should not be instantiated.
-///
-// \note The QK scheduler, QK priority, QK ready set, etc. belong conceptually
-/// to the QK class (as static class members). However, to avoid C++ potential
-/// name-mangling problems in assembly language, these elements are defined
-/// outside of the QK class and use the extern "C" linkage specification.
-///
-class QK {
-public:
-
-    /// \brief get the current QK version number string
-    ///
-    /// \return version of the QK as a constant 6-character string of the
-    /// form x.y.zz, where x is a 1-digit major version number, y is a
-    /// 1-digit minor version number, and zz is a 2-digit release number.
-    ///
-    /// \sa QK::getPortVersion()
-    static char const Q_ROM * Q_ROM_VAR getVersion(void);
-
-    /// \brief Returns the QK-port version.
-    ///
-    /// This function returns constant version string in the format x.y.zz,
-    /// where x (one digit) is the major version, y (one digit) is the minor
-    /// version, and zz (two digits) is the maintenance release version.
-    /// An example of the QK-port version string is "1.1.03".
-    ///
-    /// \sa QK::getVersion()
-    static char const Q_ROM * Q_ROM_VAR getPortVersion(void);
-
-    /// \brief QK idle callback (customized in BSPs for QK)
-    ///
-    /// QK::onIdle() is called continously by the QK idle loop. This callback
-    /// gives the application an opportunity to enter a power-saving CPU mode,
-    /// or perform some other idle processing.
-    ///
-    /// \note QK::onIdle() is invoked with interrupts unlocked and must also
-    /// return with interrupts unlocked.
-    ///
-    /// \sa QF::onIdle()
-    static void onIdle(void);
-
-#ifndef QK_NO_MUTEX
-
-    /// \brief QK priority-ceiling mutex lock
-    ///
-    /// Lock the QK scheduler up to the priority level \a prioCeiling.
-    ///
-    // \note This function should be always paired with QK::mutexUnlock().
-    /// The code between QK::mutexLock() and QK::mutexUnlock() should be
-    /// kept to the minimum.
-    ///
-    /// \include qk_mux.cpp
-    static QMutex mutexLock(uint8_t prioCeiling);
-
-    /// \brief QK priority-ceiling mutex unlock
-    ///
-    /// \note This function should be always paired with QK::mutexLock().
-    /// The code between QK::mutexLock() and QK::mutexUnlock() should be
-    /// kept to the minimum.
-    ///
-    /// \include qk_mux.cpp
-    static void mutexUnlock(QMutex mutex);
-
-#endif                                                          // QK_NO_MUTEX
-
-};
-
-#ifdef Q_USE_NAMESPACE
-}                                                              // namespace QP
-#endif
-
-extern "C" {
-
-/// \brief QK initialization
-///
-/// QK_init() is called from QF_init() in qk.cpp. This function is
-/// defined in the QK ports.
-void QK_init(void);
-
-// QK scheduler and extended scheduler
-#ifndef QF_INT_KEY_TYPE
-    void QK_schedule_(void);                                   // QK scheduler
-    void QK_scheduleExt_(void);                       // QK extended scheduler
-
-    #define QK_SCHEDULE_()    QK_schedule_()
-#else
-
-    /// \brief The QK scheduler
-    ///
-    /// \note The QK scheduler must be always called with the interrupts
-    /// locked and unlocks interrupts internally.
-    ///
-    /// The signature of QK_schedule_() depends on the policy of locking and
-    /// unlocking interrupts. When the interrupt lock key is not used
-    /// (#QF_INT_KEY_TYPE undefined), the signature is as follows: \n
-    /// void QK_schedule_(void); \n
-    ///
-    /// However, when the interrupt key lock is used (#QF_INT_KEY_TYPE
-    /// defined), the signature is different: \n
-    /// void QK_schedule_(QF_INT_KEY_TYPE intLockKey); \n
-    ///
-    /// For the internal use, these differences are hidden by the macro
-    /// #QK_SCHEDULE_.
-    void QK_schedule_(QF_INT_KEY_TYPE intLockKey);
-
-    /// \brief The QK extended scheduler for interrupt context
-    ///
-    /// \note The QK extended exscheduler must be always called with the
-    /// interrupts locked and unlocks interrupts internally.
-    ///
-    /// The signature of QK_scheduleExt_() depends on the policy of locking
-    /// and unlocking interrupts. When the interrupt lock key is not used
-    /// (#QF_INT_KEY_TYPE undefined), the signature is as follows: \n
-    /// void QK_scheduleExt_(void); \n
-    ///
-    /// However, when the interrupt key lock is used (#QF_INT_KEY_TYPE
-    /// defined), the signature is different: \n
-    /// void QK_scheduleExt_(QF_INT_KEY_TYPE intLockKey); \n
-    void QK_scheduleExt_(QF_INT_KEY_TYPE intLockKey); // QK extended scheduler
-
-    /// #QF_INT_KEY_TYPE is defined, this internal macro invokes
-    /// QK_schedule_() passing the key variable as the parameter. Otherwise
-    /// QK_schedule_() is invoked without parameters.
-    /// \sa #QK_INT_LOCK, #QK_INT_UNLOCK
-    #define QK_SCHEDULE_()    QK_schedule_(intLockKey_)
-
-#endif
-}                                                                // extern "C"
-
-#ifdef Q_USE_NAMESPACE
-namespace QP {
-#endif
-
-#else                                                         // QK_PREEMPTIVE
-
-// "qvanilla.h" ==============================================================
-#define QF_EQUEUE_TYPE              QEQueue
-                                              // native event queue operations
-#define QACTIVE_EQUEUE_WAIT_(me_) \
-    Q_ASSERT((me_)->m_eQueue.m_frontEvt != (QEvent *)0)
-
-#define QACTIVE_EQUEUE_SIGNAL_(me_) \
-    QF_readySet_.insert((me_)->m_prio)
-
-#define QACTIVE_EQUEUE_ONEMPTY_(me_) \
-    QF_readySet_.remove((me_)->m_prio)
-
-                                            // native QF event pool operations
-#define QF_EPOOL_TYPE_              QMPool
-#define QF_EPOOL_INIT_(p_, poolSto_, poolSize_, evtSize_) \
-    (p_).init(poolSto_, poolSize_, evtSize_)
-#define QF_EPOOL_EVENT_SIZE_(p_)    ((p_).getBlockSize())
-#define QF_EPOOL_GET_(p_, e_)       ((e_) = (QEvent *)(p_).get())
-#define QF_EPOOL_PUT_(p_, e_)       ((p_).put(e_))
-
-#if (QF_MAX_ACTIVE <= 8)
-    extern QPSet8  volatile QF_readySet_;  ///< QF-ready set of active objects
-#else
-    extern QPSet64 volatile QF_readySet_;  ///< QF-ready set of active objects
-#endif
-
-#endif                                                        // QK_PREEMPTIVE
-
-
-// qf.h (QF platform-independent public interface) ===========================
-//////////////////////////////////////////////////////////////////////////////
-#if (QF_MAX_ACTIVE < 1) || (63 < QF_MAX_ACTIVE)
-    #error "QF_MAX_ACTIVE not defined or out of range. Valid range is 1..63"
-#endif
-
-//////////////////////////////////////////////////////////////////////////////
-#ifndef QF_EVENT_SIZ_SIZE
-
-    /// \brief Default value of the macro configurable value in qf_port.h
-    #define QF_EVENT_SIZ_SIZE 2
-#endif
-#if (QF_EVENT_SIZ_SIZE == 1)
-
-    /// \brief The data type to store the block-size defined based on
-    /// the macro #QF_EVENT_SIZ_SIZE.
-    ///
-    /// The dynamic range of this data type determines the maximum block
-    /// size that can be managed by the pool.
-    typedef uint8_t QEventSize;
-#elif (QF_EVENT_SIZ_SIZE == 2)
-    typedef uint16_t QEventSize;
-#elif (QF_EVENT_SIZ_SIZE == 4)
-    typedef uint32_t QEventSize;
-#else
-    #error "QF_EVENT_SIZ_SIZE defined incorrectly, expected 1, 2, or 4"
-#endif
-
-//////////////////////////////////////////////////////////////////////////////
-#ifndef QF_MAX_EPOOL
-    /// \brief Default value of the macro configurable value in qf_port.h
-    #define QF_MAX_EPOOL 3
-#endif
-
-//////////////////////////////////////////////////////////////////////////////
-#ifndef QF_ACTIVE_SUPER_
-
-    //////////////////////////////////////////////////////////////////////////
-    /// \brief The macro defining the base class for QActive.
-    ///
-    /// By default, the ::QActive class is derived from ::QHsm. However,
-    /// if the macro QF_ACTIVE_SUPER_ is defined, QActive is derived from
-    /// QF_ACTIVE_SUPER_.
-    ///
-    /// Clients might choose, for example, to define QF_ACTIVE_SUPER_ as QFsm
-    /// to avoid the 1-2KB overhead of the hierarchical event processor.
-    ///
-    /// Clients might also choose to define QF_ACTIVE_SUPER_ as their own
-    /// completely customized class that has nothing to do with QHsm or QFsm.
-    /// The QF_ACTIVE_SUPER_ class must provide member functions init() and
-    /// dispatch(), consistent with the signatures of QHsm and QFsm. But
-    /// the implementatin of these functions is completely open.
-    #define QF_ACTIVE_SUPER_  QHsm
-
-    /// \brief The argument of the base class' constructor.
-    #define QF_ACTIVE_STATE_  QStateHandler
-
-#endif
-
-class QEQueue;                                          // forward declaration
-
-
-/// \brief Base class for derivation of application-level active object
-/// classes.
-///
-/// QActive is the base class for derivation of active objects. Active objects
-/// in QF are encapsulated tasks (each embedding a state machine and an event
-/// queue) that communicate with one another asynchronously by sending and
-/// receiving events. Within an active object, events are processed
-/// sequentially in a run-to-completion (RTC) fashion, while QF encapsulates
-/// all the details of thread-safe event exchange and queuing.
-///
-/// \note QActive is not intended to be instantiated directly, but rather
-/// serves as the base class for derivation of active objects in the
-/// application code.
-///
-/// The following example illustrates how to derive an active object from
-/// QActive.
-/// \include qf_qactive.cpp
-///
-/// \sa #QF_ACTIVE_SUPER_ defines the base class for QActive
-class QActive : public QF_ACTIVE_SUPER_ {
-private:
-
-    /// \brief OS-dependent event-queue type.
-    ///
-    /// The type of the queue depends on the underlying operating system or
-    /// a kernel. Many kernels support "message queues" that can be adapted
-    /// to deliver QF events to the active object. Alternatively, QF provides
-    /// a native event queue implementation that can be used as well.
-    ///
-    /// The native QF event queue is configured by defining the macro
-    /// #QF_EQUEUE_TYPE as ::QEQueue.
-    QF_EQUEUE_TYPE m_eQueue;
-
-public:
-#ifdef QF_OS_OBJECT_TYPE
-    /// \brief OS-dependent per-thread object.
-    ///
-    /// This data might be used in various ways, depending on the QF port.
-    /// In some ports m_osObject is used to block the calling thread when
-    /// the native QF queue is empty. In other QF ports the OS-dependent
-    /// object might be used differently.
-    QF_OS_OBJECT_TYPE m_osObject;
-#endif
-
-#ifdef QF_THREAD_TYPE
-    /// \brief OS-dependent representation of the thread of the active
-    /// object.
-    ///
-    /// This data might be used in various ways, depending on the QF port.
-    /// In some ports m_thread is used store the thread handle. In other ports
-    /// m_thread can be the pointer to the Thread-Local-Storage (TLS).
-    QF_THREAD_TYPE m_thread;
-#endif
-
-    /// \brief QF priority associated with the active object.
-    /// \sa QActive::start()
-    uint8_t m_prio;
-
-    /// \brief The Boolean loop variable determining if the thread routine
-    /// of the active object is running.
-    ///
-    /// This flag is only used with the traditional loop-structured thread
-    /// routines. Clearing this flag breaks out of the thread loop, which is
-    /// often the cleanest way to terminate the thread. The following example
-    /// illustrates the thread routine for Win32:
-    /// \include qf_run.cpp
-    uint8_t m_running;
-
-public:
-
-    /// \brief Starts execution of an active object and registers the object
-    /// with the framework.
-    ///
-    /// The function takes six arguments.
-    /// \a prio is the priority of the active object. QF allows you to start
-    /// up to 63 active objects, each one having a unique priority number
-    /// between 1 and 63 inclusive, where higher numerical values correspond
-    /// to higher priority (urgency) of the active object relative to the
-    /// others.
-    /// \a qSto[] and \a qLen arguments are the storage and size of the event
-    /// queue used by this active object.
-    /// \a stkSto and \a stkSize are the stack storage and size in bytes.
-    /// Please note that a per-active object stack is used only when the
-    /// underlying OS requies it. If the stack is not required, or the
-    /// underlying OS allocates the stack internally, the \a stkSto should be
-    /// NULL and/or \a stkSize should be 0.
-    /// \a ie is an optional initialization event that can be used to pass
-    /// additional startup data to the active object. (Pass NULL if your
-    /// active object does not expect the initialization event).
-    ///
-    /// \note This function is strongly OS-dependent and must be defined in
-    /// the QF port to a particular platform.
-    ///
-    /// The following example shows starting of the Philosopher object when a
-    /// per-task stack is required:
-    /// \include qf_start.cpp
-    void start(uint8_t prio,
-               QEvent const *qSto[], uint32_t qLen,
-               void *stkSto, uint32_t stkSize,
-               QEvent const *ie = (QEvent *)0);
-
-    /// \brief Posts an event \a e directly to the event queue of the acitve
-    /// object \a me using the First-In-First-Out (FIFO) policy.
-    ///
-    /// Direct event posting is the simplest asynchronous communication method
-    /// available in QF. The following example illustrates how the Philosopher
-    /// active obejct posts directly the HUNGRY event to the Table active
-    /// object. \include qf_post.cpp
-    ///
-    /// \note The producer of the event (Philosopher in this case) must only
-    /// "know" the recipient (Table) by a generic (QActive *QDPP_table)
-    /// pointer, but the specific definition of the Table class is not
-    /// required.
-    ///
-    /// \note Direct event posting should not be confused with direct event
-    /// dispatching. In contrast to asynchronous event posting through event
-    /// queues, direct event dispatching is synchronous. Direct event
-    /// dispatching occurs when you call QHsm::dispatch(), or QFsm::dispatch()
-    /// function.
-#ifndef Q_SPY
-    void postFIFO(QEvent const *e);
-#else
-    void postFIFO(QEvent const *e, void const *sender);
-#endif
-
-    /// \brief Posts an event directly to the event queue of the active object
-    /// \a me using the Last-In-First-Out (LIFO) policy.
-    ///
-    /// \note The LIFO policy should be used only for self-posting and with
-    /// great caution because it alters order of events in the queue.
-    ///
-    /// \sa QActive::postFIFO()
-    void postLIFO(QEvent const *e);
-
-    /// \brief Traditional loop-structured thread routine for an active object
-    ///
-    /// This function is only used when QF is ported to a traditional
-    /// RTOS/Kernel. QActive::run() is structured as a typical endless loop,
-    /// which blocks on the event queue get() operation of an active object.
-    /// When an event becomes available, it's dispatched to the active
-    /// object's state machine and after this recycled with QF::gc().
-    /// The loop might optionally use the QActive::m_running flag to terminate
-    /// and cause QActive::run() to return which is often the cleanest way to
-    /// terminate the thread.
-    void run(void);
-
-    /// \brief Get an event from the event queue of an active object.
-    ///
-    /// This function is used internally by a QF port to extract events from
-    /// the event queue of an active object. This function depends on the
-    /// event queue implementation and is sometimes implemented in the QF port
-    /// (qf_port.cpp file). Depending on the underlying OS or kernel, the
-    /// function might block the calling thread when no events are available.
-    ///
-    /// \note QActive::get_() is public because it often needs to be called
-    /// from thread-run routines with difficult to foresee signature (so
-    /// declaring friendship with such function(s) is not possible.)
-    ///
-    /// \sa QActive::postFIFO(), QActive::postLIFO()
-    QEvent const *get_(void);
-
-protected:
-
-    /// \brief protected constructor
-    ///
-    /// Performs the first step of active object initialization by assigning
-    /// the initial pseudostate to the currently active state of the state
-    /// machine.
-    ///
-    /// \note The constructor is protected to prevent direct instantiation
-    /// of QActive objects. This class is intended only for derivation
-    /// (abstract class).
-    QActive(QF_ACTIVE_STATE_ initial) : QF_ACTIVE_SUPER_(initial) {
-    }
-
-    /// \brief Stops execution of an active object and removes it from the
-    /// framework's supervision.
-    ///
-    /// The preferred way of calling this function is from within the active
-    /// object that needs to stop (that's why this function is protected).
-    /// In other words, an active object should stop itself rather than being
-    /// stopped by some other entity. This policy works best, because only
-    /// the active object itself "knows" when it has reached the appropriate
-    /// state for the shutdown.
-    ///
-    /// \note This function is strongly OS-dependent and should be defined in
-    /// the QF port to a particular platform. This function is optional in
-    /// embedded systems where active objects never need to be stopped.
-    void stop(void);
-
-    /// \brief Subscribes for delivery of signal \a sig to the active object
-    ///
-    /// This function is part of the Publish-Subscribe event delivery
-    /// mechanism available in QF. Subscribing to an event means that the
-    /// framework will start posting all published events with a given signal
-    /// \a sig to the event queue of the active object.
-    ///
-    /// The following example shows how the Table active object subscribes
-    /// to three signals in the initial transition:
-    /// \include qf_subscribe.cpp
-    ///
-    /// \sa QF::publish(), QActive::unsubscribe(), and
-    /// QActive::unsubscribeAll()
-    void subscribe(QSignal sig) const;
-
-    /// \brief Un-subscribes from the delivery of signal \a sig to the
-    /// active object.
-    ///
-    /// This function is part of the Publish-Subscribe event delivery
-    /// mechanism available in QF. Un-subscribing from an event means that
-    /// the framework will stop posting published events with a given signal
-    /// \a sig to the event queue of the active object.
-    ///
-    /// \note Due to the latency of event queues, an active object should NOT
-    /// assume that a given signal \a sig will never be dispatched to the
-    /// state machine of the active object after un-subscribing from that
-    /// signal. The event might be already in the queue, or just about to be
-    /// posted and the un-subscribe operation will not flush such events.
-    ///
-    /// \note Un-subscribing from a signal that has never been subscribed in
-    /// the first place is considered an error and QF will rise an assertion.
-    ///
-    /// \sa QF::publish(), QActive::subscribe(), and QActive::unsubscribeAll()
-    void unsubscribe(QSignal sig) const;
-
-    /// \brief Defer an event to a given separate event queue.
-    ///
-    /// This function is part of the event deferral support. An active object
-    /// uses this function to defer an event \a e to the QF-supported native
-    /// event queue \a eq. QF correctly accounts for another outstanding
-    /// reference to the event and will not recycle the event at the end of
-    /// the RTC step. Later, the active object might recall one event at a
-    /// time from the event queue.
-    ///
-    /// An active object can use multiple event queues to defer events of
-    /// different kinds.
-    ///
-    /// \sa QActive::recall(), QEQueue
-    void defer(QEQueue *eq, QEvent const *e);
-
-    /// \brief Recall a deferred event from a given event queue.
-    ///
-    /// This function is part of the event deferral support. An active object
-    /// uses this function to recall a deferred event from a given QF
-    /// event queue. Recalling an event means that it is removed from the
-    /// deferred event queue \a eq and posted (LIFO) to the event queue of
-    /// the active object.
-    ///
-    /// QActive::recall() returns 1 (TRUE) if an event has been recalled.
-    /// Otherwise the function returns 0.
-    ///
-    /// An active object can use multiple event queues to defer events of
-    /// different kinds.
-    ///
-    /// \sa QActive::defer(), QEQueue, QActive::postLIFO()
-    uint8_t recall(QEQueue *eq);
-
-public:
-    /// \brief Un-subscribes from the delivery of all signals to the active
-    /// object.
-    ///
-    /// This function is part of the Publish-Subscribe event delivery
-    /// mechanism available in QF. Un-subscribing from all events means that
-    /// the framework will stop posting any published events to the event
-    /// queue of the active object.
-    ///
-    /// \note Due to the latency of event queues, an active object should NOT
-    /// assume that no events will ever be dispatched to the state machine of
-    /// the active object after un-subscribing from all events.
-    /// The events might be already in the queue, or just about to be posted
-    /// and the un-subscribe operation will not flush such events. Also, the
-    /// alternative event-delivery mechanisms, such as direct event posting or
-    /// time events, can be still delivered to the event queue of the active
-    /// object.
-    ///
-    /// \sa QF::publish(), QActive::subscribe(), and QActive::unsubscribe()
-    void unsubscribeAll(void) const;
-
-private:
-
-    friend class QF;
-    friend class QTimeEvt;
-    #ifndef QF_INT_KEY_TYPE
-        friend void QK_schedule_(void);
-        friend void QK_scheduleExt_(void);
-    #else
-        friend void QK_schedule_(QF_INT_KEY_TYPE intLockKey);
-        friend void QK_scheduleExt_(QF_INT_KEY_TYPE intLockKey);
-    #endif
-};
-
-
-//////////////////////////////////////////////////////////////////////////////
-#ifndef QF_TIMEEVT_CTR_SIZE
-    /// \brief macro to override the default QTimeEvtCtr size.
-    /// Valid values 1, 2, or 4; default 2
-    #define QF_TIMEEVT_CTR_SIZE 2
-#endif
-#if (QF_TIMEEVT_CTR_SIZE == 1)
-
-    /// \brief type of the Time Event counter, which determines the dynamic
-    /// range of the time delays measured in clock ticks.
-    ///
-    /// This typedef is configurable via the preprocessor switch
-    /// #QF_TIMEEVT_CTR_SIZE. The other possible values of this type are
-    /// as follows: \n
-    /// uint8_t when (QF_TIMEEVT_CTR_SIZE == 1), and \n
-    /// uint32_t when (QF_TIMEEVT_CTR_SIZE == 4).
-    typedef uint8_t QTimeEvtCtr;
-#elif (QF_TIMEEVT_CTR_SIZE == 2)
-    typedef uint16_t QTimeEvtCtr;
-#elif (QF_TIMEEVT_CTR_SIZE == 4)
-    typedef uint32_t QTimeEvtCtr;
-#else
-    #error "QF_TIMEEVT_CTR_SIZE defined incorrectly, expected 1, 2, or 4"
-#endif
-
-//////////////////////////////////////////////////////////////////////////////
-/// \brief Time Event class
-///
-/// Time events are special QF events equipped with the notion of time
-/// passage. The basic usage model of the time events is as follows. An
-/// active object allocates one or more QTimeEvt objects (provides the
-/// storage for them). When the active object needs to arrange for a timeout,
-/// it arms one of its time events to fire either just once (one-shot) or
-/// periodically. Each time event times out independently from the others,
-/// so a QF application can make multiple parallel timeout requests (from the
-/// same or different active objects). When QF detects that the appropriate
-/// moment has arrived, it inserts the time event directly into the
-/// recipient's event queue. The recipient then processes the time event just
-/// like any other event.
-///
-/// Time events, as any other QF events derive from the ::QEvent base
-/// class. Typically, you will use a time event as-is, but you can also
-/// further derive more specialized time events from it by adding some more
-/// data members and/or specialized functions that operate on the specialized
-/// time events.
-///
-/// Internally, the armed time events are organized into a bi-directional
-/// linked list. This linked list is scanned in every invocation of the
-/// QF::tick() function. Only armed (timing out) time events are in the list,
-/// so only armed time events consume CPU cycles.
-///
-/// \note QF manages the time events in the function QF::tick(), which
-/// must be called periodically, preferably from the clock tick ISR.
-/// \note In this version of QF QTimeEvt objects should be allocated
-/// statically rather than dynamically from event pools. Currently, QF will
-/// not correctly recycle the dynamically allocated Time Events.
-class QTimeEvt : public QEvent {
-private:
-
-    //// link to the previous time event in the list
-    QTimeEvt *m_prev;
-
-    /// link to the next time event in the list
-    QTimeEvt *m_next;
-
-    /// the active object that receives the time events.
-    QActive *m_act;
-
-    /// the internal down-counter of the time event. The down-counter
-    /// is decremented by 1 in every QF_tick() invocation. The time event
-    /// fires (gets posted or published) when the down-counter reaches zero.
-    QTimeEvtCtr m_ctr;
-
-    /// the interval for the periodic time event (zero for the one-shot
-    /// time event). The value of the interval is re-loaded to the internal
-    /// down-counter when the time event expires, so that the time event
-    /// keeps timing out periodically.
-    QTimeEvtCtr m_interval;
-
-public:
-
-    /// \brief The Time Event constructor.
-    ///
-    /// The most important initialization performed in  the constructor is
-    /// assigning a signal to the Time Event. You can reuse the Time Event
-    /// any number of times, but you cannot change the signal.
-    /// This is because pointers to Time Events might still be held in event
-    /// queues and changing signal could to hard-to-detect errors.
-    ///
-    /// The following example shows the use of QTimeEvt::QTimeEvt()
-    /// constructor in the constructor initializer list of the Philosopher
-    /// active object constructor that owns the time event
-    /// \include qf_ctor.cpp
-    QTimeEvt(QSignal s);
-
-    /// \brief Arm a one-shot time event for direct event posting.
-    ///
-    /// Arms a time event to fire in \a nTicks clock ticks (one-shot time
-    /// event). The time event gets directly posted (using the FIFO policy)
-    /// into the event queue of the active object \a act.
-    ///
-    /// After posting, the time event gets automatically disarmed and can be
-    /// reused for a one-shot or periodic timeout requests.
-    ///
-    /// A one-shot time event can be disarmed at any time by calling the
-    /// QTimeEvt::disarm() function. Also, a one-shot time event can be
-    /// re-armed to fire in a different number of clock ticks by calling the
-    /// QTimeEvt::rearm() function.
-    ///
-    /// The following example shows how to arm a one-shot time event from a
-    /// state machine of an active object:
-    /// \include qf_state.cpp
-    void postIn(QActive *act, QTimeEvtCtr nTicks) {
-        m_interval = (uint16_t)0;
-        arm_(act, nTicks);
-    }
-
-    /// \brief Arm a periodic time event for direct event posting.
-    ///
-    /// Arms a time event to fire every \a nTicks clock ticks (periodic time
-    /// event). The time event gets directly posted (using the FIFO policy)
-    /// into the event queue of the active object \a act.
-    ///
-    /// After posting, the time event gets automatically re-armed to fire
-    /// again in the specified \a nTicks clock ticks.
-    ///
-    /// A periodic time event can be disarmed only by calling the
-    /// QTimeEvt::disarm() function. After disarming, the time event can be
-    /// reused for a one-shot or periodic timeout requests.
-    ///
-    /// \note An attempt to reuse (arm again) a running periodic time event
-    /// raises an assertion.
-    ///
-    /// Also, a periodic time event can be re-armed to shorten or extend the
-    /// current period by calling the QTimeEvt_rearm() function. After
-    /// adjusting the current period, the periodic time event goes back
-    /// timing out at the original rate.
-    void postEvery(QActive *act, QTimeEvtCtr nTicks) {
-        m_interval = nTicks;
-        arm_(act, nTicks);
-    }
-
-    /// \brief Disarm a time event.
-    ///
-    /// The time event gets disarmed and can be reused. The function
-    /// returns 1 (TRUE) if the time event was truly disarmed, that is, it
-    /// was running. The return of 0 (FALSE) means that the time event was
-    /// not truly disarmed because it was not running. The FALSE return is
-    /// only possible for one-shot time events that have been automatically
-    /// disarmed upon expiration. In this case the FALSE return means that
-    /// the time event has already been posted or published and should be
-    /// expected in the active object's state machine.
-    uint8_t disarm(void);
-
-    /// \brief Rearm a time event.
-    ///
-    /// The time event gets rearmed with a new number of clock ticks
-    /// \a nTicks. This facility can be used to prevent a one-shot time event
-    /// from expiring (e.g., a watchdog time event), or to adjusts the
-    /// current period of a periodic time event. Rearming a periodic timer
-    /// leaves the interval unchanged and is a convenient method to adjust the
-    /// phasing of the periodic time event.
-    ///
-    /// The function returns 1 (TRUE) if the time event was running as it
-    /// was re-armed. The return of 0 (FALSE) means that the time event was
-    /// not truly rearmed because it was not running. The FALSE return is only
-    /// possible for one-shot time events that have been automatically
-    /// disarmed upon expiration. In this case the FALSE return means that
-    /// the time event has already been posted or published and should be
-    /// expected in the active object's state machine.
-    uint8_t rearm(QTimeEvtCtr nTicks);
-
-    /// \brief Get the current value of the down-counter of a time event.
-    ///
-    /// If the time event is armed, the function returns the current value of
-    /// the down-counter of the given time event. If the time event is not
-    /// armed, the function returns 0.
-    ///
-    /// /note The function is thread-safe.
-    QTimeEvtCtr ctr(void);
-
-private:
-
-    /// \brief Arm a time event (internal function to be used through macros
-    /// only).
-    ///
-    /// \sa QTimeEvt::postIn(), QTimeEvt::postEvery(),
-    /// \sa QTimeEvt::publishIn(), QTimeEvt::publishEvery()
-    void arm_(QActive *act, QTimeEvtCtr nTicks);
-
-    friend class QF;
-};
-
-
-#if (QF_MAX_ACTIVE > 63)
-    #error "QF_MAX_ACTIVE exceeds 63"
-#endif
-
-//////////////////////////////////////////////////////////////////////////////
-/// \brief Subscriber List class
-///
-/// This data type represents a set of active objects that subscribe to
-/// a given signal. The set is represented as an array of bits, where each
-/// bit corresponds to the unique priority of an active object.
-class QSubscrList {
-private:
-
-    /// An array of bits representing subscriber active objects. Each bit
-    /// in the array corresponds to the unique priority of the active object.
-    /// The size of the array is determined of the maximum number of active
-    /// objects in the application configured by the #QF_MAX_ACTIVE macro.
-    /// For example, an active object of priority p is a subscriber if the
-    /// following is true: ((m_bits[QF_div8Lkup[p]] & QF_pwr2Lkup[p]) != 0)
-    ///
-    /// \sa QF::psInit(), QF_div8Lkup, QF_pwr2Lkup, #QF_MAX_ACTIVE
-    uint8_t m_bits[((QF_MAX_ACTIVE - 1) / 8) + 1];
-
-    friend class QF;
-    friend class QActive;
-};
-
-//////////////////////////////////////////////////////////////////////////////
-/// \brief QF services.
-///
-/// This class groups together QF services. It has only static members and
-/// should not be instantiated.
-class QF {
-public:
-
-    /// \brief QF initialization.
-    ///
-    /// This function initializes QF and must be called exactly once before
-    /// any other QF function.
-    static void init(void);
-
-    /// \brief Publish-subscribe initialization.
-    ///
-    /// This function initializes the publish-subscribe facilities of QF and
-    /// must be called exactly once before any subscriptions/publications
-    /// occur in the application. The arguments are as follows: \a subscrSto
-    /// is a pointer to the array of subscriber-lists. \a maxSignal is the
-    /// dimension of this array and at the same time the maximum signal that
-    /// can be published or subscribed.
-    ///
-    /// The array of subscriber-lists is indexed by signals and provides
-    /// mapping between the signals and subscirber-lists. The subscriber-
-    /// lists are bitmasks of type ::QSubscrList, each bit in the bitmask
-    /// corresponding to the unique priority of an active object. The size
-    /// of the ::QSubscrList bitmask depends on the value of the
-    /// #QF_MAX_ACTIVE macro.
-    ///
-    /// \note The publish-subscribe facilities are optional, meaning that
-    /// you might choose not to use publish-subscribe. In that case calling
-    /// QF::psInit() and using up memory for the subscriber-lists is
-    /// unnecessary.
-    ///
-    /// \sa ::QSubscrList
-    ///
-    /// The following example shows the typical initialization sequence of
-    /// QF: \include qf_main.cpp
-    static void psInit(QSubscrList *subscrSto, QSignal maxSignal);
-
-    /// \brief Event pool initialization for dynamic allocation of events.
-    ///
-    /// This function initializes one event pool at a time and must be called
-    /// exactly once for each event pool before the pool can be used.
-    /// The arguments are as follows: \a poolSto is a pointer to the memory
-    /// block for the events. \a poolSize is the size of the memory block in
-    /// bytes. \a evtSize is the block-size of the pool in bytes, which
-    /// determines the maximum size of events that can be allocated from the
-    /// pool.
-    ///
-    /// You might initialize one, two, and up to three event pools by making
-    /// one, two, or three calls to the QF_poolInit() function. However,
-    /// for the simplicity of the internal implementation, you must initialize
-    /// event pools in the ascending order of the event size.
-    ///
-    /// Many RTOSes provide fixed block-size heaps, a.k.a. memory pools that
-    /// can be used for QF event pools. In case such support is missing, QF
-    /// provides a native QF event pool implementation. The macro
-    /// #QF_EPOOL_TYPE_ determines the type of event pool used by a
-    /// particular QF port. See class ::QMPool for more information.
-    ///
-    /// \note The actual number of events available in the pool might be
-    /// actually less than (\a poolSize / \a evtSize) due to the internal
-    /// alignment of the blocks that the pool might perform. You can always
-    /// check the capacity of the pool by calling QF::getPoolMargin().
-    ///
-    /// \note The dynamic allocation of events is optional, meaning that you
-    /// might choose not to use dynamic events. In that case calling
-    /// QF::poolInit() and using up memory for the memory blocks is
-    /// unnecessary.
-    ///
-    /// \sa QF initialization example for QF::init()
-    static void poolInit(void *poolSto, uint32_t poolSize,
-                         QEventSize evtSize);
-
-    /// \brief Transfers control to QF to run the application.
-    ///
-    /// QF::run() is typically called from your startup code after you
-    /// initialize the QF and start at least one active object with
-    /// QActive::start(). Also, QF::start() call must precede the transfer
-    /// of control to QF::run(), but some QF ports might call QF::start()
-    /// from QF::run(). QF::run() typically never returns to the caller.
-    ///
-    /// \note This function is strongly platform-dependent and is not
-    /// implemented in the QF, but either in the QF port or in the
-    /// Board Support Package (BSP) for the given application. All QF ports
-    /// must implement QF::run().
-    ///
-    /// \note When the Quantum Kernel (QK) is used as the underlying real-time
-    /// kernel for the QF, all platfrom dependencies are handled in the QK, so
-    /// no porting of QF is necessary. In other words, you only need to
-    /// recompile the QF platform-independent code with the compiler for your
-    /// platform, but you don't need to provide any platform-specific
-    /// implementation (so, no qf_port.cpp file is necessary). Moreover, QK
-    /// implements the function QF::run() in a platform-independent way,
-    /// in the modile qk.cpp.
-    static void run(void);
-
-    /// \brief Startup QF callback.
-    ///
-    /// The timeline for calling QF::onStartup() depends on the particular
-    /// QF port. In most cases, QF::onStartup() is called from QF::run(),
-    /// right before starting any multitasking kernel or the background loop.
-    static void onStartup(void);
-
-    /// \brief Cleanup QF callback.
-    ///
-    /// QF::onCleanup() is called in some QF ports before QF returns to the
-    /// underlying operating system or RTOS.
-    ///
-    /// This function is strongly platform-specific and is not implemented in
-    /// the QF but either in the QF port or in the Board Support Package (BSP)
-    /// for the given application. Some QF ports might not require
-    /// implementing QF::onCleanup() at all, because many embedded
-    /// applications don't have anything to exit to.
-    ///
-    /// \sa QF::init() and QF::stop()
-    static void onCleanup(void);
-
-#ifndef QF_INT_KEY_TYPE
-    static void onIdle(void);                // interrupt lock key NOT defined
-
-#else
-
-    /// \brief QF idle callback (customized in BSPs for QF)
-    ///
-    /// QF::onIdle() is called by the non-preemptive scheduler built into QF
-    /// when the framework detects that no events are available for active
-    /// objects (the idle condition). This callback gives the application an
-    /// opportunity to enter a power-saving CPU mode, or perform some other
-    /// idle processing (such as Q-Spy output).
-    ///
-    /// \note QF::onIdle() is invoked with interrupts LOCKED because the idle
-    /// condition can be asynchronously changed at any time by an interrupt.
-    /// QF::onIdle() MUST unlock the interrupts internally, but not before
-    /// putting the CPU into the low-power mode. (Ideally, unlocking
-    /// interrupts and low-power mode should happen atomically). At the very
-    /// least, the function MUST unlock interrupts, otherwise interrups will
-    /// be locked permanently.
-    ///
-    /// \note QF::onIdle() is only used by the non-preemptive scheduler built
-    /// into QF in the "bare metal" port, and is NOT used in any other ports.
-    /// When QF is combined with QK, the QK idle loop calls a different
-    /// function QK::onIdle(), with different semantics than QF::onIdle().
-    /// When QF is combined with a 3rd-party RTOS or kernel, the idle
-    /// processing mechanism of the RTOS or kernal is used instead of
-    /// QF::onIdle().
-    static void onIdle(QF_INT_KEY_TYPE intLockKey);   // int. lock key defined
-
-#endif                                                      // QF_INT_KEY_TYPE
-
-    /// \brief Function invoked by the application layer to stop the QF
-    /// application and return control to the OS/Kernel.
-    ///
-    /// This function stops the QF application. After calling this function,
-    /// QF attempts to gracefully stop the  application. This graceful
-    /// shutdown might take some time to complete. The typical use of this
-    /// funcition is for terminating the QF application to return back to the
-    /// operating system or for handling fatal errors that require shutting
-    /// down (and possibly re-setting) the system.
-    ///
-    /// This function is strongly platform-specific and is not implemented in
-    /// the QF but either in the QF port or in the Board Support Package (BSP)
-    /// for the given application. Some QF ports might not require
-    /// implementing QF::stop() at all, because many embedded application
-    /// don't have anything to exit to.
-    ///
-    /// \sa QF::stop() and QF::onCleanup()
-    static void stop(void);
-
-    /// \brief Publish event to the framework.
-    ///
-    /// This function posts (using the FIFO policy) the event \a e it to ALL
-    /// active object that have subscribed to the signal \a e->sig.
-    /// This function is designed to be callable from any part of the system,
-    /// including ISRs, device drivers, and active objects.
-    ///
-    /// In the general case, event publishing requires multi-casting the
-    /// event to multiple subscribers. This happens in the caller's thread
-    /// with the scheduler locked to prevent preemptions during the multi-
-    /// casting process. (Please note that the interrupts are not locked.)
-#ifndef Q_SPY
-    static void publish(QEvent const *e);
-#else
-    static void publish(QEvent const *e, void const *sender);
-#endif
-
-    /// \brief Processes all armed time events at every clock tick.
-    ///
-    /// This function must be called periodically from a time-tick ISR or from
-    /// the highest-priority task so that QF can manage the timeout events.
-    ///
-    /// \note The QF::tick() function is not reentrant meaning that it must
-    /// run to completion before it is called again. Also, QF::tick() assumes
-    /// that it never will get preempted by a task, which is always the case
-    /// when it is called from an ISR or the highest-priority task.
-    ///
-    /// \sa ::QTimeEvt.
-    ///
-    /// The following example illustrates the call to QF::tick():
-    /// \include qf_tick.cpp
-#ifndef Q_SPY
-    static void tick(void);
-#else
-    static void tick(void const *sender);
-#endif
-
-    /// \brief Returns the QF version.
-    ///
-    /// This function returns constant version string in the format x.y.zz,
-    /// where x (one digit) is the major version, y (one digit) is the minor
-    /// version, and zz (two digits) is the maintenance release version.
-    /// An example of the version string is "3.1.03".
-    ///
-    /// The following example illustrates the usage of this function:
-    /// \include qf_version.cpp
-    static char const Q_ROM * Q_ROM_VAR getVersion(void);
-
-    /// \brief Returns the QF-port version.
-    ///
-    /// This function returns constant version string in the format x.y.zz,
-    /// where x (one digit) is the major version, y (one digit) is the minor
-    /// version, and zz (two digits) is the maintenance release version.
-    /// An example of the QF-port version string is "1.1.03".
-    ///
-    /// \sa QF::getVersion()
-    static char const Q_ROM * Q_ROM_VAR getPortVersion(void);
-
-    /// \brief This function returns the margin of the given event pool.
-    ///
-    /// This function returns the margin of the given event pool \a poolId,
-    /// where poolId is the ID of the pool initialized by the call to
-    /// QF::poolInit(). The poolId of the first initialized pool is 1, the
-    /// second 2, and so on.
-    ///
-    /// The returned pool margin is the minimal number of free blocks
-    /// encountered in the given pool since system startup.
-    ///
-    /// \note Requesting the margin of an un-initialized pool raises an
-    /// assertion in the QF.
-    static uint32_t getPoolMargin(uint8_t poolId);
-
-    /// \brief This function returns the margin of the given event queue.
-    ///
-    /// This function returns the margin of the given event queue of an active
-    /// object with priority \a prio. (QF priorities start with 1 and go up to
-    /// #QF_MAX_ACTIVE.) The margin is the minimal number of free events
-    /// encountered in the given queue since system startup.
-    ///
-    /// \note QF::getQueueMargin() is available only when the native QF event
-    /// queue implementation is used. Requesting the queue margin of an unused
-    /// priority level raises an assertion in the QF. (A priority level
-    /// becomes used in QF after the call to the QF::add_() function.)
-    static uint32_t getQueueMargin(uint8_t prio);
-
-    /// \brief Internal QF implementation of the dynamic event allocator.
-    ///
-    /// \note The application code should not call this function directly.
-    /// Please use the macro #Q_NEW.
-    static QEvent *new_(uint16_t evtSize, QSignal sig);
-
-#ifdef Q_EVT_CTOR
-    #define Q_NEW(evtT_, sig_, ...) \
-        (new(QF::new_(sizeof(evtT_), sig_)) evtT_((sig_), ##__VA_ARGS__))
-#else
-    /// \brief Allocate a dynamic event.
-    ///
-    /// This macro returns an event pointer cast to the type \a evtT_. The
-    /// event is initialized with the signal \a sig. Internally, the macro
-    /// calls the internal QF function QF::new_(), which always returns a
-    /// valid event pointer.
-    ///
-    /// \note The internal QF function QF::new_() raises an assertion when
-    /// the allocation of the event turns out to be impossible due to event
-    /// pool depletion, or incorrect (too big) size of the requested event.
-    ///
-    /// The following example illustrates dynamic allocation of an event:
-    /// \include qf_post.cpp
-    #define Q_NEW(evtT_, sig_) ((evtT_ *)QF::new_(sizeof(evtT_), (sig_)))
-#endif
-
-    /// \brief Recycle a dynamic event.
-    ///
-    /// This function implements a simple garbage collector for the dynamic
-    /// events. Only dynamic events are candidates for recycling. (A dynamic
-    /// event is one that is allocated from an event pool, which is
-    /// determined as non-zero e->attrQF__ attribute.) Next, the function
-    /// decrements the reference counter of the event, and recycles the event
-    /// only if the counter drops to zero (meaning that no more references
-    /// are outstanding for this event). The dynamic event is recycled by
-    /// returning it to the pool from which it was originally allocated.
-    /// The pool-of-origin information is stored in the upper 2-MSBs of the
-    /// e->attrQF__ attribute.)
-    ///
-    /// \note QF invokes the garbage collector at all appropriate contexts,
-    /// when an event can become garbage (automatic garbage collection),
-    /// so the application code should have NO need to call QF::gc() directly.
-    /// The QF::gc() function is exposed only for special cases when your
-    /// application sends dynamic events to the "raw" thread-safe queues
-    /// (see ::QEQueue). Such queues are processed outside of QF and the
-    /// automatic garbage collection CANNOT be performed for these events.
-    /// In this case you need to call QF::gc() explicitly.
-    static void gc(QEvent const *e);
-
-    /// \brief array of registered active objects
-    ///
-    /// \note Not to be used by Clients directly, only in ports of QF
-    static QActive *active_[];
-
-private:                              // functions to be used in QF ports only
-
-    /// \brief Register an active object to be managed by the framework
-    ///
-    /// This function should not be called by the application directly, only
-    /// through the function QActive::start(). The priority of the active
-    /// object \a a should be set before calling this function.
-    ///
-    /// \note This function raises an assertion if the priority of the active
-    /// object exceeds the maximum value #QF_MAX_ACTIVE. Also, this function
-    /// raises an assertion if the priority of the active object is already in
-    /// use. (QF requires each active object to have a UNIQUE priority.)
-    static void add_(QActive *a);
-
-public:
-    /// \brief Remove the active object from the framework.
-    ///
-    /// This function should not be called by the application directly, only
-    /// inside the QF port. The priority level occupied by the active object
-    /// is freed-up and can be reused for another active object.
-    ///
-    /// The active object that is removed from the framework can no longer
-    /// participate in the publish-subscribe event exchange.
-    ///
-    /// \note This function raises an assertion if the priority of the active
-    /// object exceeds the maximum value #QF_MAX_ACTIVE or is not used.
-    static void remove_(QActive const *a);
-
-    friend class QActive;
-};
-
-//////////////////////////////////////////////////////////////////////////////
-// useful lookup tables
-
-/// \brief Lookup table for (log2(n) + 1), where n is the index
-/// into the table.
-///
-/// This lookup delivers the 1-based number of the most significant 1-bit
-/// of a byte.
-///
-/// \note Index range n = 0..255. The first index (n == 0) should never
-/// be used.
-///
-extern uint8_t const Q_ROM Q_ROM_VAR QF_log2Lkup[256];
-
-/// \brief Lookup table for (1 << ((n-1) % 8)), where n is the index
-/// into the table.
-///
-/// \note Index range n = 0..64. The first index (n == 0) should never
-/// be used.
-extern uint8_t const Q_ROM Q_ROM_VAR QF_pwr2Lkup[65];
-
-/// \brief Lookup table for ~(1 << ((n-1) % 8)), where n is the index
-/// into the table.
-///
-/// \note Index range n = 0..64. The first index (n == 0) should never
-/// be used.
-extern uint8_t const Q_ROM Q_ROM_VAR QF_invPwr2Lkup[65];
-
-/// \brief Lookup table for (n-1)/8
-///
-/// \note Index range n = 0..64. The first index (n == 0) should never
-/// be used.
-extern uint8_t const Q_ROM Q_ROM_VAR QF_div8Lkup[65];
-
-//////////////////////////////////////////////////////////////////////////////
-#ifdef Q_EVT_CTOR
-#include <new>                                            // for placement new
-#endif
-
-// from qf.h -----------------------------------------------------------------
-//////////////////////////////////////////////////////////////////////////////
-// QS software tracing integration, only if enabled
-#ifdef Q_SPY                                   // QS software tracing enabled?
-    #define QS_TIME_SIZE            4
-    #define QS_OBJ_PTR_SIZE         4
-    #define QS_FUN_PTR_SIZE         4
-
-    /// \brief Invoke the system clock tick processing QF::tick(). This macro
-    /// is the recommended way of invoking clock tick processing, because it
-    /// provides the vital information for software tracing and avoids any
-    /// overhead when the tracing is disabled.
-    ///
-    /// This macro takes the argument \a sender_, which is a pointer to the
-    /// sender object. This argument is actually only used when QS software
-    /// tracing is enabled (macro #Q_SPY is defined). When QS software
-    /// tracing is disabled, the macro calls QF::tick() without any
-    /// arguments, so the overhead of passing this extra argument is
-    /// entirely avoided.
-    ///
-    /// \note the pointer to the sender object is not necessarily a poiner
-    /// to an active object. In fact, typically QF::TICK() will be called from
-    /// an interrupt, in which case you would create a unique object just to
-    /// unambiguously identify the ISR as the sender of the time events.
-    ///
-    /// \sa QF::tick()
-    #define TICK(sender_)                  tick(sender_)
-
-    /// \brief Invoke the event publishing facility QF::publish(). This macro
-    /// is the recommended way of publishing events, because it provides the
-    /// vital information for software tracing and avoids any overhead when the
-    /// tracing is disabled.
-    ///
-    ///
-    /// This macro takes the last argument \a sender_, which is a pointer to
-    /// the sender object. This argument is actually only used when QS software
-    /// tracing is enabled (macro #Q_SPY is defined). When QS software
-    /// tracing is disabled, the macro calls QF::publish() without the
-    /// \a sender_ argument, so the overhead of passing this extra argument
-    /// is entirely avoided.
-    ///
-    /// \note the pointer to the sender object is not necessarily a poiner
-    /// to an active object. In fact, if QF::PUBLISH() is called from an
-    /// interrupt or other context, you can create a unique object just to
-    /// unambiguously identify the publisher of the event.
-    ///
-    /// \sa QF::publish()
-    #define PUBLISH(e_, sender_)           publish((e_), (sender_))
-
-    /// \brief Invoke the direct event posting facility QActive::postFIFO().
-    /// This macro is the recommended way of posting events, because it provides
-    /// the vital information for software tracing and avoids any overhead when
-    /// the tracing is disabled.
-    ///
-    ///
-    /// This macro takes the last argument \a sender_, which is a pointer to
-    /// the sender object. This argument is actually only used when QS software
-    /// tracing is disabled (macro #Q_SPY is defined). When QS software
-    /// tracing is not enabled, the macro calls QF_publish() without the
-    /// \a sender_ argument, so the overhead of passing this extra argument
-    /// is entirely avoided.
-    ///
-    /// \note the pointer to the sender object is not necessarily a poiner
-    /// to an active object. In fact, if ao->POST() is called from an
-    /// interrupt or other context, you can create a unique object just to
-    /// unambiguously identify the publisher of the event.
-    ///
-    /// \sa QActive::postFIFO()
-    #define POST(e_, sender_)              postFIFO((e_), (sender_))
-
-    #if (QF_EQUEUE_CTR_SIZE == 1)
-
-        /// \brief Internal QS macro to output an unformatted event queue
-        /// counter data element
-        /// \note the counter size depends on the macro #QF_EQUEUE_CTR_SIZE.
-        #define QS_EQC_(ctr_)       QS::u8_(ctr_)
-    #elif (QF_EQUEUE_CTR_SIZE == 2)
-        #define QS_EQC_(ctr_)       QS::u16_(ctr_)
-    #elif (QF_EQUEUE_CTR_SIZE == 4)
-        #define QS_EQC_(ctr_)       QS::u32_(ctr_)
-    #else
-        #error "QF_EQUEUE_CTR_SIZE not defined"
-    #endif
-
-
-    #if (QF_EVENT_SIZ_SIZE == 1)
-
-        /// \brief Internal QS macro to output an unformatted event size
-        /// data element
-        /// \note the event size depends on the macro #QF_EVENT_SIZ_SIZE.
-        #define QS_EVS_(size_)      QS::u8_(size_)
-    #elif (QF_EVENT_SIZ_SIZE == 2)
-        #define QS_EVS_(size_)      QS::u16_(size_)
-    #elif (QF_EVENT_SIZ_SIZE == 4)
-        #define QS_EVS_(size_)      QS::u32_(size_)
-    #endif
-
-
-    #if (QF_MPOOL_SIZ_SIZE == 1)
-
-        /// \brief Internal QS macro to output an unformatted memory pool
-        /// block-size data element
-        /// \note the block-size depends on the macro #QF_MPOOL_SIZ_SIZE.
-        #define QS_MPS_(size_)      QS::u8_(size_)
-    #elif (QF_MPOOL_SIZ_SIZE == 2)
-        #define QS_MPS_(size_)      QS::u16_(size_)
-    #elif (QF_MPOOL_SIZ_SIZE == 4)
-        #define QS_MPS_(size_)      QS::u32_(size_)
-    #endif
-
-    #if (QF_MPOOL_CTR_SIZE == 1)
-
-        /// \brief Internal QS macro to output an unformatted memory pool
-        /// block-counter data element
-        /// \note the counter size depends on the macro #QF_MPOOL_CTR_SIZE.
-        #define QS_MPC_(ctr_)       QS::u8_(ctr_)
-    #elif (QF_MPOOL_CTR_SIZE == 2)
-        #define QS_MPC_(ctr_)       QS::u16_(ctr_)
-    #elif (QF_MPOOL_CTR_SIZE == 4)
-        #define QS_MPC_(ctr_)       QS::u32_(ctr_)
-    #endif
-
-
-    #if (QF_TIMEEVT_CTR_SIZE == 1)
-
-        /// \brief Internal QS macro to output an unformatted time event
-        /// tick-counter data element
-        /// \note the counter size depends on the macro #QF_TIMEEVT_CTR_SIZE.
-        #define QS_TEC_(ctr_)       QS::u8_(ctr_)
-    #elif (QF_TIMEEVT_CTR_SIZE == 2)
-        #define QS_TEC_(ctr_)       QS::u16_(ctr_)
-    #elif (QF_TIMEEVT_CTR_SIZE == 4)
-        #define QS_TEC_(ctr_)       QS::u32_(ctr_)
-    #endif
-
-#else
-
-    #define TICK(dummy_)                   tick()
-    #define PUBLISH(e_, dummy_)            publish((e_))
-    #define POST(e_, dummy_)               postFIFO((e_))
-
-#endif                                                                // Q_SPY
-
-//////////////////////////////////////////////////////////////////////////////
-// QS software tracing
-#ifdef Q_SPY
-
-// qs.h ======================================================================
-//////////////////////////////////////////////////////////////////////////////
-
-/// \brief Quantum Spy record types.
-///
-/// This enumeration specifies the record types used in the QP components.
-/// You can specify your own record types starting from ::QS_USER offset.
-/// Currently, the maximum of all records cannot exceed 256.
-/// \sa QS::filterOn()/#QS_FILTER_ON and QS::filterOff()/#QS_FILTER_OFF
-enum QSpyRecords {
-    // QEP records
-    QS_QEP_STATE_EMPTY,
-    QS_QEP_STATE_ENTRY,                               ///< a state was entered
-    QS_QEP_STATE_EXIT,                                 ///< a state was exited
-    QS_QEP_STATE_INIT,          ///< an intial transition was taken in a state
-    QS_QEP_INIT_TRAN,           ///< the top-most initial transition was taken
-    QS_QEP_INTERN_TRAN,                  ///< an internal transition was taken
-    QS_QEP_TRAN,                           ///< a regular transition was taken
-    QS_QEP_IGNORED,             ///< an event was ignored (silently discarded)
-    QS_QEP_DISPATCH,          ///< an event was dispatched (begin of RTC step)
-    QS_QEP_RESERVED0,
-
-    // QF records
-    QS_QF_ACTIVE_ADD,                ///< an AO has been added to QF (started)
-    QS_QF_ACTIVE_REMOVE,         ///< an AO has been removed from QF (stopped)
-    QS_QF_ACTIVE_SUBSCRIBE,                  ///< an AO subscribed to an event
-    QS_QF_ACTIVE_UNSUBSCRIBE,              ///< an AO unsubscribed to an event
-    QS_QF_ACTIVE_POST_FIFO,  ///< an event was posted (FIFO) directly to an AO
-    QS_QF_ACTIVE_POST_LIFO,  ///< an event was posted (LIFO) directly to an AO
-    QS_QF_ACTIVE_GET, ///< an AO got an event and its queue is still not empty
-    QS_QF_ACTIVE_GET_LAST,      ///< an AO got an event and its queue is empty
-    QS_QF_EQUEUE_INIT,                     ///< an event queue was initialized
-    QS_QF_EQUEUE_POST_FIFO,     ///< an event was posted (FIFO) to a raw queue
-    QS_QF_EQUEUE_POST_LIFO,     ///< an event was posted (LIFO) to a raw queue
-    QS_QF_EQUEUE_GET,              ///< get an event and queue still not empty
-    QS_QF_EQUEUE_GET_LAST,              ///< get the last event from the queue
-    QS_QF_MPOOL_INIT,                       ///< a memory pool was initialized
-    QS_QF_MPOOL_GET,        ///< a memory block was removed from a memory pool
-    QS_QF_MPOOL_PUT,         ///< a memory block was returned to a memory pool
-    QS_QF_PUBLISH,       ///< an event was truly published to some subscribers
-    QS_QF_RESERVED8,
-    QS_QF_NEW,                                         ///< new event creation
-    QS_QF_GC_ATTEMPT,                          ///< garbage collection attempt
-    QS_QF_GC,                                          ///< garbage collection
-    QS_QF_TICK,                                     ///< QF::tick() was called
-    QS_QF_TIMEEVT_ARM,                             ///< a time event was armed
-    QS_QF_TIMEEVT_AUTO_DISARM,      ///< a time event expired and was disarmed
-    QS_QF_TIMEEVT_DISARM_ATTEMPT,///< an attempt to disarmed a disarmed tevent
-    QS_QF_TIMEEVT_DISARM,           ///< true disarming of an armed time event
-    QS_QF_TIMEEVT_REARM,                         ///< rearming of a time event
-    QS_QF_TIMEEVT_POST,      ///< a time event posted itself directly to an AO
-    QS_QF_TIMEEVT_CTR,                 ///< a time event counter was requested
-    QS_QF_INT_LOCK,                                ///< interrupts were locked
-    QS_QF_INT_UNLOCK,                            ///< interrupts were unlocked
-    QS_QF_ISR_ENTRY,                                   ///< an ISR was entered
-    QS_QF_ISR_EXIT,                                     ///< an ISR was exited
-    QS_QF_RESERVED6,
-    QS_QF_RESERVED5,
-    QS_QF_RESERVED4,
-    QS_QF_RESERVED3,
-    QS_QF_RESERVED2,
-    QS_QF_RESERVED1,
-    QS_QF_RESERVED0,
-
-    // QK records
-    QS_QK_MUTEX_LOCK,                             ///< the QK mutex was locked
-    QS_QK_MUTEX_UNLOCK,                         ///< the QK mutex was unlocked
-    QS_QK_SCHEDULE,      ///< the QK scheduler scheduled a new task to execute
-    QS_QK_RESERVED6,
-    QS_QK_RESERVED5,
-    QS_QK_RESERVED4,
-    QS_QK_RESERVED3,
-    QS_QK_RESERVED2,
-    QS_QK_RESERVED1,
-    QS_QK_RESERVED0,
-
-    // Miscellaneous QS records
-    QS_SIG_DICTIONARY,                            ///< signal dictionary entry
-    QS_OBJ_DICTIONARY,                            ///< object dictionary entry
-    QS_FUN_DICTIONARY,                          ///< function dictionary entry
-    QS_ASSERT,                                ///< assertion fired in the code
-    QS_RESERVED5,
-    QS_RESERVED4,
-    QS_RESERVED3,
-    QS_RESERVED2,
-    QS_RESERVED1,
-    QS_RESERVED0,
-
-    // User records
-    QS_USER                ///< the first record available for user QS records
-};
-
-/// \brief Specification of all QS records for the QS::filterOn() and
-/// QS::filterOff()
-#define QS_ALL_RECORDS          ((uint8_t)0xFF)
-
-/// \brief Constant representing End-Of-Data condition returned from the
-/// QS::getByte() function.
-#define QS_EOD                  ((uint16_t)0xFFFF)
-
-
-#ifndef QS_TIME_SIZE
-
-    /// \brief The size (in bytes) of the QS time stamp. Valid values: 1, 2,
-    /// or 4; default 4.
-    ///
-    /// This macro can be defined in the QS port file (qs_port.h) to
-    /// configure the ::QSTimeCtr type. Here the macro is not defined so the
-    /// default of 4 byte is chosen.
-    #define QS_TIME_SIZE 4
-#endif
-#if (QS_TIME_SIZE == 1)
-    typedef uint8_t QSTimeCtr;
-    #define QS_TIME_()   QS::u8_(QS::onGetTime())
-#elif (QS_TIME_SIZE == 2)
-    typedef uint16_t QSTimeCtr;
-    #define QS_TIME_()   QS::u16_(QS::onGetTime())
-#elif (QS_TIME_SIZE == 4)
-
-    /// \brief The type of the QS time stamp
-    ///
-    /// This type determines the dynamic range of QS time stamps
-    typedef uint32_t QSTimeCtr;
-
-    /// \brief Internal macro to output time stamp to the QS record
-    #define QS_TIME_()   QS::u32_(QS::onGetTime())
-#else
-    #error "QS_TIME_SIZE defined incorrectly, expected 1, 2, or 4"
-#endif
-
-#ifndef Q_ROM                      // provide the default if Q_ROM NOT defined
-    #define Q_ROM
-#endif
-#ifndef Q_ROM_VAR              // provide the default if Q_ROM_VAR NOT defined
-    #define Q_ROM_VAR
-#endif
-#ifndef Q_ROM_BYTE            // provide the default if Q_ROM_BYTE NOT defined
-    #define Q_ROM_BYTE(rom_var_)   (rom_var_)
-#endif
-
-
-/// \brief Quantum Spy logging facilities
-///
-/// This class groups together QS services. It has only static members and
-/// should not be instantiated.
-class QS {
-public:
-
-    /// \brief Get the current version of QS
-    ///
-    /// \return version of the QS as a constant 6-character string of the form
-    /// x.y.zz, where x is a 1-digit major version number, y is a 1-digit
-    /// minor version number, and zz is a 2-digit release number.
-    static char const Q_ROM * Q_ROM_VAR getVersion(void);
-
-    /// \brief Initialize the QS data buffer.
-    ///
-    /// This function should be called from QS_init() to provide QS with the
-    /// data buffer. The first argument \a sto[] is the address of the memory
-    /// block, and the second argument \a stoSize is the size of this block
-    /// in bytes. Currently the size of the QS buffer cannot exceed 64KB.
-    ///
-    /// QS can work with quite small data buffers, but you will start losing
-    /// data if the buffer is too small for the bursts of logging activity.
-    /// The right size of the buffer depends on the data production rate and
-    /// the data output rate. QS offers flexible filtering to reduce the data
-    /// production rate.
-    ///
-    /// \note If the data output rate cannot keep up with the production rate,
-    /// QS will start overwriting the older data with newer data. This is
-    /// consistent with the "last-is-best" QS policy. The record sequence
-    ///  counters and checksums on each record allow to easily detect data
-    /// loss.
-    static void initBuf(uint8_t sto[], uint32_t stoSize);
-
-    /// \brief Turn the global Filter on for a given record type \a rec.
-    ///
-    /// This function sets up the QS filter to enable the record type \a rec.
-    /// The argument #QS_ALL_RECORDS specifies to filter-on all records.
-    /// This function should be called indirectly through the macro
-    /// #QS_FILTER_ON.
-    ///
-    /// \note Filtering based on the record-type is only the first layer of
-    /// filtering. The second layer is based on the object-type. Both filter
-    /// layers must be enabled for the QS record to be inserted into the QS
-    /// buffer.
-    /// \sa QS_filterOff(), #QS_FILTER_SM_OBJ, #QS_FILTER_AO_OBJ,
-    /// #QS_FILTER_MP_OBJ, #QS_FILTER_EQ_OBJ, and #QS_FILTER_TE_OBJ.
-    static void filterOn(uint8_t rec);
-
-    /// \brief Turn the global Filter off for a given record type \a rec.
-    ///
-    /// This function sets up the QS filter to disable the record type \a rec.
-    /// The argument #QS_ALL_RECORDS specifies to suppress all records.
-    /// This function should be called indirectly through the macro
-    /// #QS_FILTER_OFF.
-    ///
-    /// \note Filtering records based on the record-type is only the first
-    /// layer of filtering. The second layer is based on the object-type.
-    /// Both filter layers must be enabled for the QS record to be inserted
-    /// into the QS buffer.
-    /// \sa
-    static void filterOff(uint8_t rec);
-
-    /// \brief Mark the begin of a QS record \a rec
-    ///
-    /// This function must be called at the beginning of each QS record.
-    /// This function should be called indirectly through the macro #QS_BEGIN,
-    /// or #QS_BEGIN_NOLOCK, depending if it's called in a normal code or from
-    /// a critical section.
-    static void begin(uint8_t rec);
-
-    /// \brief Mark the end of a QS record \a rec
-    ///
-    /// This function must be called at the end of each QS record.
-    /// This function should be called indirectly through the macro #QS_END,
-    /// or #QS_END_NOLOCK, depending if it's called in a normal code or from
-    /// a critical section.
-    static void end(void);
-
-    // unformatted data elements output ......................................
-
-    /// \brief output uint8_t data element without format information
-    /// \note This function is only to be used through macros, never in the
-    /// client code directly.
-    static void u8_(uint8_t d);
-
-    /// \brief Output uint16_t data element without format information
-    /// \note This function is only to be used through macros, never in the
-    /// client code directly.
-    static void u16_(uint16_t d);
-
-    /// \brief Output uint32_t data element without format information
-    /// \note This function is only to be used through macros, never in the
-    /// client code directly.
-    static void u32_(uint32_t d);
-
-    /// \brief Output zero-terminated ASCII string element without format
-    /// information
-    /// \note This function is only to be used through macros, never in the
-    /// client code directly.
-    static void str_(char const *s);
-
-    /// \brief Output zero-terminated ASCII string element  allocated in ROM
-    /// without format information
-    /// \note This function is only to be used through macros, never in the
-    /// client code directly.
-    static void str_ROM_(char const Q_ROM * Q_ROM_VAR s);
-
-    // formatted data elements output ........................................
-
-    /// \brief Output uint8_t data element with format information
-    /// \note This function is only to be used through macros, never in the
-    /// client code directly.
-    static void u8(uint8_t format, uint8_t d);
-
-    /// \brief output uint16_t data element with format information
-    /// \note This function is only to be used through macros, never in the
-    /// client code directly.
-    static void u16(uint8_t format, uint16_t d);
-
-    /// \brief Output uint32_t data element with format information
-    /// \note This function is only to be used through macros, never in the
-    /// client code directly.
-    static void u32(uint8_t format, uint32_t d);
-
-    /// \brief Output 32-bit floating point data element with format
-    /// information
-    /// \note This function is only to be used through macros, never in the
-    /// client code directly.
-    static void f32(uint8_t format, float d);
-
-    /// \brief Output 64-bit floating point data element with format
-    /// information
-    /// \note This function is only to be used through macros, never in the
-    /// client code directly.
-    static void f64(uint8_t format, double d);
-
-    /// \brief Output zero-terminated ASCII string element with format
-    /// information
-    /// \note This function is only to be used through macros, never in the
-    /// client code directly.
-    static void str(char const *s);
-
-    /// \brief Output zero-terminated ASCII string element allocated in ROM
-    /// with format information
-    /// \note This function is only to be used through macros, never in the
-    /// client code directly.
-    static void str_ROM(char const Q_ROM * Q_ROM_VAR s);
-
-    /// \brief Output memory block of up to 255-bytes with format information
-    /// \note This function is only to be used through macros, never in the
-    /// client code directly.
-    static void mem(uint8_t const *blk, uint8_t size);
-
-#if (QS_OBJ_PTR_SIZE == 8) || (QS_FUN_PTR_SIZE == 8)
-    /// \brief Output uint64_t data element without format information
-    /// \note This function is only to be used through macros, never in the
-    /// client code directly.
-    static void u64_(uint64_t d);
-
-    /// \brief Output uint64_t data element with format information
-    /// \note This function is only to be used through macros, never in the
-    /// client code directly.
-    static void u64(uint8_t format, uint64_t d);
-#endif
-
-    // QS buffer access ......................................................
-
-    /// \brief Byte-oriented interface to the QS data buffer.
-    ///
-    /// This function delivers one byte at a time from the QS data buffer.
-    /// The function returns the byte in the least-significant 8-bits of the
-    /// 16-bit return value if the byte is available. If no more data is
-    /// available at the time, the function returns QS_EOD (End-Of-Data).
-    ///
-    /// \note QS::getByte() is NOT protected with a critical section.
-    static uint16_t getByte(void);
-
-    /// \brief Block-oriented interface to the QS data buffer.
-    ///
-    /// This function delivers a contiguous block of data from the QS data
-    /// buffer. The function returns the pointer to the beginning of the
-    /// block, and writes the number of bytes in the block to the location
-    /// pointed to by \a pNbytes. The argument \a pNbytes is also used as
-    /// input to provide the maximum size of the data block that the caller
-    /// can accept.
-    ///
-    /// If no bytes are available in the QS buffer when the function is
-    /// called, the function returns a NULL pointer and sets the value
-    /// pointed to by \a pNbytes to zero.
-    ///
-    /// \note Only the NULL return from QS::getBlock() indicates that the QS
-    /// buffer is empty at the time of the call. The non-NULL return often
-    /// means that the block is at the end of the buffer and you need to call
-    /// QS::getBlock() again to obtain the rest of the data that "wrapped
-    /// around" to the beginning of the QS data buffer.
-    ///
-    /// \note QS::getBlock() is NOT protected with a critical section.
-    static uint8_t const *getBlock(uint16_t *pNbytes);
-
-// platform-dependent callback functions, need to be implemented by clients
-public:
-
-    // platform-specific callback functions, need to be implemented by clients
-    /// \brief Callback to startup the QS facility
-    ///
-    /// This is a platform-dependent "callback" function invoked through the
-    /// macro #QS_INIT. You need to implement this function in your
-    /// application. At a minimum, the function must configure the QS buffer
-    /// by calling QS::initBuf(). Typically, you will also want to open/
-    /// configure the QS output channel, such as a serial port, or a file.
-    /// The void* argument \a arg can be used to pass parameter(s) needed to
-    /// configure the output channel.
-    ///
-    /// The function returns TRUE (1) if the QS initialization was successful,
-    /// or FALSE (0) if it failed.
-    ///
-    /// The following example illustrates an implementation of QS_onStartup():
-    /// \include qs_startup.cpp
-    static uint8_t onStartup(void const *arg);
-
-    /// \brief Callback to cleanup the QS facility
-    ///
-    /// This is a platform-dependent "callback" function invoked through the
-    /// macro #QS_EXIT. You need to implement this function in your
-    /// application. The main purpose of this function is to close the QS
-    /// output channel, if necessary.
-    static void onCleanup(void);
-
-    /// \brief Callback to flush the QS trace data to the host
-    ///
-    /// This is a platform-dependent "callback" function to flush the QS
-    /// trace buffer to the host. The function typically busy-waits until all
-    /// the data in the buffer is sent to the host. This is acceptable only
-    /// in the initial transient.
-    static void onFlush(void);
-
-    /// \brief Callback to obtain a timestamp for a QS record.
-    ///
-    /// This is a platform-dependent "callback" function invoked from the
-    /// macro #QS_TIME_ to add the time stamp to the QS record.
-    ///
-    /// \note Some of the pre-defined QS records from QP do not output the
-    /// time stamp. However, ALL user records do output the time stamp.
-    /// \note QS::onGetTime() is called in a critical section and should not
-    /// unlock interrupts.
-    ///
-    /// The following example shows using a system call to implement QS
-    /// time stamping:
-    /// \include qs_onGetTime.cpp
-    static QSTimeCtr onGetTime(void);
-
-// Global and Local QS filters ...............................................
-public:
-    static uint8_t glbFilter_[32];                ///< global on/off QS filter
-    static void const *smObj_;         ///< state machine for QEP local filter
-    static void const *aoObj_;       ///< active object for QF/QK local filter
-    static void const *mpObj_;            ///<  event pool for QF local filter
-    static void const *eqObj_;             ///<  raw queue for QF local filter
-    static void const *teObj_;            ///<  time event for QF local filter
-    static void const *apObj_;///<  generic object Application QF local filter
-
-// Miscallaneous .............................................................
-public:
-                                    /// tick counter for the QS_QF_TICK record
-    static QSTimeCtr volatile tickCtr_;
-};
-
-
-//////////////////////////////////////////////////////////////////////////////
-// Macros for adding QS instrumentation to the client code
-
-/// \brief Initialize the QS facility.
-///
-/// This macro provides an indirection layer to invoke the QS initialization
-/// routine if #Q_SPY is defined, or do nothing if #Q_SPY is not defined.
-/// \sa QS::onStartup(), example of setting up a QS filter in #QS_FILTER_IN
-#define QS_INIT(arg_)           QS::onStartup(arg_)
-
-/// \brief Cleanup the QS facility.
-///
-/// This macro provides an indirection layer to invoke the QS cleanup
-/// routine if #Q_SPY is defined, or do nothing if #Q_SPY is not defined.
-/// \sa QS::onCleanup()
-#define QS_EXIT()               QS::onCleanup()
-
-/// \brief Global Filter ON for a given record type \a rec.
-///
-/// This macro provides an indirection layer to call QS::filterOn() if #Q_SPY
-/// is defined, or do nothing if #Q_SPY is not defined.
-///
-/// The following example shows how to use QS filters:
-/// \include qs_filter.cpp
-#define QS_FILTER_ON(rec_)      QS::filterOn(rec_)
-
-/// \brief Global filter OFF for a given record type \a rec.
-///
-/// This macro provides an indirection layer to call QS::filterOff() if #Q_SPY
-/// is defined, or do nothing if #Q_SPY is not defined.
-///
-/// \sa Example of using QS filters in #QS_FILTER_ON documentation
-#define QS_FILTER_OFF(rec_)     QS::filterOff(rec_)
-
-/// \brief Local Filter for a given state machine object \a obj_.
-///
-/// This macro sets up the state machine object local filter if #Q_SPY is
-/// defined, or does nothing if #Q_SPY is not defined. The argument \a obj_
-/// is the pointer to the state machine object that you want to monitor.
-///
-/// The state machine object filter allows you to filter QS records pertaining
-/// only to a given state machine object. With this filter disabled, QS will
-/// output records from all state machines in your application. The object
-/// filter is disabled by setting the state machine pointer to NULL.
-///
-/// The state machine filter affects the following QS records:
-/// ::QS_QEP_STATE_ENTRY, ::QS_QEP_STATE_EXIT, ::QS_QEP_STATE_INIT,
-/// ::QS_QEP_INIT_TRAN, ::QS_QEP_INTERN_TRAN, ::QS_QEP_TRAN,
-/// and ::QS_QEP_IGNORED.
-///
-/// \note Because active objects are state machines at the same time,
-/// the state machine filter (#QS_FILTER_SM_OBJ) pertains to active
-/// objects as well. However, the state machine filter is more general,
-/// because it can be used only for state machines that are not active
-/// objects, such as "Orthogonal Components".
-///
-/// \sa Example of using QS filters in #QS_FILTER_ON documentation
-#define QS_FILTER_SM_OBJ(obj_)  (QS::smObj_ = (obj_))
-
-/// \brief Local Filter for a given active object \a obj_.
-///
-/// This macro sets up the active object local filter if #Q_SPY is defined,
-/// or does nothing if #Q_SPY is not defined. The argument \a obj_ is the
-/// pointer to the active object that you want to monitor.
-///
-/// The active object filter allows you to filter QS records pertaining
-/// only to a given active object. With this filter disabled, QS will
-/// output records from all active objects in your application. The object
-/// filter is disabled by setting the active object pointer \a obj_ to NULL.
-///
-/// The active object filter affects the following QS records:
-/// ::QS_QF_ACTIVE_ADD, ::QS_QF_ACTIVE_REMOVE, ::QS_QF_ACTIVE_SUBSCRIBE,
-/// ::QS_QF_ACTIVE_UNSUBSCRIBE, ::QS_QF_ACTIVE_POST_FIFO,
-/// ::QS_QF_ACTIVE_POST_LIFO, ::QS_QF_ACTIVE_GET, and ::QS_QF_ACTIVE_GET_LAST.
-///
-/// \sa Example of using QS filters in #QS_FILTER_ON documentation
-#define QS_FILTER_AO_OBJ(obj_)  (QS::aoObj_ = (obj_))
-
-/// \brief Local Filter for a given memory pool object \a obj_.
-///
-/// This macro sets up the memory pool object local filter if #Q_SPY is
-/// defined, or does nothing if #Q_SPY is not defined. The argument \a obj_
-/// is the pointer to the memory buffer used during the initialization of the
-/// event pool with QF::poolInit().
-///
-/// The memory pool filter allows you to filter QS records pertaining
-/// only to a given memory pool. With this filter disabled, QS will
-/// output records from all memory pools in your application. The object
-/// filter is disabled by setting the memory pool pointer \a obj_ to NULL.
-///
-/// The memory pool filter affects the following QS records:
-/// ::QS_QF_MPOOL_INIT, ::QS_QF_MPOOL_GET, and ::QS_QF_MPOOL_PUT.
-///
-/// \sa Example of using QS filters in #QS_FILTER_ON documentation
-#define QS_FILTER_MP_OBJ(obj_)  (QS::mpObj_ = (obj_))
-
-/// \brief Filter for a given event queue object \a obj_.
-///
-/// This macro sets up the event queue object filter if #Q_SPY is defined,
-/// or does nothing if #Q_SPY is not defined. The argument \a obj_ is the
-/// pointer to the "raw" thread-safe queue object you want to monitor.
-///
-/// The event queue filter allows you to filter QS records pertaining
-/// only to a given event queue. With this filter disabled, QS will
-/// output records from all event queues in your application. The object
-/// filter is disabled by setting the event queue pointer \a obj_ to NULL.
-///
-/// The event queue filter affects the following QS records:
-/// ::QS_QF_EQUEUE_INIT, ::QS_QF_EQUEUE_POST_FIFO, ::QS_QF_EQUEUE_POST_LIFO,
-/// ::QS_QF_EQUEUE_GET, and ::QS_QF_EQUEUE_GET_LAST.
-///
-/// \sa Example of using QS filters in #QS_FILTER_IN documentation
-#define QS_FILTER_EQ_OBJ(obj_)  (QS::eqObj_ = (obj_))
-
-/// \brief Local Filter for a given time event object \a obj_.
-///
-/// This macro sets up the time event object local filter if #Q_SPY is
-/// defined, or does nothing if #Q_SPY is not defined. The argument \a obj_
-/// is the pointer to the time event object you want to monitor.
-///
-/// The time event filter allows you to filter QS records pertaining
-/// only to a given time event. With this filter disabled, QS will
-/// output records from all time events in your application. The object
-/// filter is disabled by setting the time event pointer \a obj_ to NULL.
-///
-/// The time event filter affects the following QS records:
-/// ::QS_QF_TIMEEVT_ARM, ::QS_QF_TIMEEVT_AUTO_DISARM,
-/// ::QS_QF_TIMEEVT_DISARM_ATTEMPT, ::QS_QF_TIMEEVT_DISARM,
-/// ::QS_QF_TIMEEVT_REARM, ::QS_QF_TIMEEVT_POST, and ::QS_QF_TIMEEVT_PUBLISH.
-///
-/// \sa Example of using QS filters in #QS_FILTER_ON documentation
-#define QS_FILTER_TE_OBJ(obj_)  (QS::teObj_ = (obj_))
-
-/// \brief Local Filter for a generic application object \a obj_.
-///
-/// This macro sets up the local application object filter if #Q_SPY is
-/// defined, or does nothing if #Q_SPY is not defined. The argument \a obj_
-/// is the pointer to the application object you want to monitor.
-///
-/// The application object filter allows you to filter QS records pertaining
-/// only to a given application object. With this filter disabled, QS will
-/// output records from all application-records enabled by the global filter.
-/// The local filter is disabled by setting the time event pointer \a obj_
-/// to NULL.
-///
-/// \sa Example of using QS filters in #QS_FILTER_ON documentation
-#define QS_FILTER_AP_OBJ(obj_)  (QS::apObj_ = (obj_))
-
-
-//////////////////////////////////////////////////////////////////////////////
-// Macros to generate user QS records
-
-/// \brief Begin a QS user record without locking interrupts.
-#define QS_BEGIN_NOLOCK(rec_, obj_) \
-    if (((QS::glbFilter_[(uint8_t)(rec_) >> 3U] \
-          & (1U << ((uint8_t)(rec_) & 7U))) != 0) \
-        && ((QS::apObj_ == (void *)0) || (QS::apObj_ == (obj_)))) \
-    { \
-        QS::begin((uint8_t)(rec_)); \
-        QS_TIME_();
-
-/// \brief End a QS user record without locking interrupts.
-#define QS_END_NOLOCK() \
-    QS_END_NOLOCK_()
-
-                                    // QS-specific interrupt locking/unlocking
-#ifndef QF_INT_KEY_TYPE
-    /// \brief This is an internal macro for defining the interrupt lock key.
-    ///
-    /// The purpose of this macro is to enable writing the same code for the
-    /// case when interrupt key is defined and when it is not. If the macro
-    /// #QS_INT_KEY_TYPE is defined, this internal macro provides the
-    /// definition of the lock key variable. Otherwise this macro is empty.
-    /// \sa #QS_INT_KEY_TYPE, #QF_INT_KEY_TYPE
-    #define QS_INT_LOCK_KEY_
-
-    /// \brief This is an internal macro for locking interrupts.
-    ///
-    /// The purpose of this macro is to enable writing the same code for the
-    /// case when interrupt key is defined and when it is not. If the macro
-    /// #QS_INT_KEY_TYPE is defined, this internal macro invokes #QS_INT_LOCK
-    /// passing the key variable as the parameter. Otherwise #QS_INT_LOCK
-    /// is invoked with a dummy parameter.
-    /// \sa #QS_INT_LOCK, #QF_INT_LOCK, #QK_INT_LOCK
-    #define QS_INT_LOCK_()      QF_INT_LOCK(ignore_)
-
-    /// \brief This is an internal macro for unlocking interrupts.
-    ///
-    /// The purpose of this macro is to enable writing the same code for the
-    /// case when interrupt key is defined and when it is not. If the macro
-    /// #QS_INT_KEY_TYPE is defined, this internal macro invokes
-    /// #QS_INT_UNLOCK passing the key variable as the parameter. Otherwise
-    /// #QS_INT_UNLOCK is invoked with a dummy parameter.
-    /// \sa #QS_INT_UNLOCK, #QF_INT_UNLOCK, #QK_INT_UNLOCK
-    #define QS_INT_UNLOCK_()    QF_INT_UNLOCK(ignore_)
-#else
-    #define QS_INT_LOCK_KEY_    QF_INT_KEY_TYPE intLockKey_;
-    #define QS_INT_LOCK_()      QF_INT_LOCK(intLockKey_)
-    #define QS_INT_UNLOCK_()    QF_INT_UNLOCK(intLockKey_)
-#endif
-
-/// \brief Begin a user QS record with locking interrupts.
-///
-/// The following example shows how to build a user QS record using the
-/// macros #QS_BEGIN, #QS_END, and the formatted output macros: #QS_U8 and
-/// #QS_STR.
-/// \include qs_user.cpp
-/// \note Must always be used in pair with #QS_END
-#define QS_BEGIN(rec_, obj_) \
-    if (((QS::glbFilter_[(uint8_t)(rec_) >> 3U] \
-          & (1U << ((uint8_t)(rec_) & 7U))) != 0U) \
-        && ((QS::apObj_ == (void *)0) || (QS::apObj_ == (obj_)))) \
-    { \
-        QS_INT_LOCK_KEY_ \
-        QS_INT_LOCK_(); \
-        QS::begin((uint8_t)(rec_)); \
-        QS_TIME_();
-
-/// \brief End a QS record with locking interrupts.
-/// \sa example for #QS_BEGIN
-/// \note Must always be used in pair with #QS_BEGIN
-#define QS_END() \
-    QS_END_()
-
-
-//////////////////////////////////////////////////////////////////////////////
-// Macros for use inside other macros or internally in the QP code
-
-/// \brief Internal QS macro to begin a QS record with locking the interrupts.
-/// \note This macro is intended to use only inside QP components and NOT
-/// at the application level. \sa #QS_BEGIN
-#define QS_BEGIN_(rec_, objFilter_, obj_) \
-    if (((QS::glbFilter_[(uint8_t)(rec_) >> 3U] \
-          & (1U << ((uint8_t)(rec_) & 7U))) != 0U) \
-        && (((objFilter_) == (void *)0) || ((objFilter_) == (obj_)))) \
-    { \
-        QS_INT_LOCK_(); \
-        QS::begin((uint8_t)(rec_));
-
-/// \brief  Internal QS macro to end a QS record with locking the interrupts.
-/// \note This macro is intended to use only inside QP components and NOT
-/// at the application level. \sa #QS_END
-#define QS_END_() \
-        QS::end(); \
-        QS_INT_UNLOCK_(); \
-    }
-
-/// \brief Internal QS macro to begin a QS record without locking the
-/// interrupts.
-/// \note This macro is intended to use only inside QP components and NOT
-/// at the application level. \sa #QS_BEGIN_NOLOCK
-#define QS_BEGIN_NOLOCK_(rec_, objFilter_, obj_) \
-    if (((QS::glbFilter_[(uint8_t)(rec_) >> 3U] \
-          & (1U << ((uint8_t)(rec_) & 7U))) != 0U) \
-        && (((objFilter_) == (void *)0) || ((objFilter_) == (obj_)))) \
-    { \
-        QS::begin((uint8_t)(rec_));
-
-/// \brief Internal QS macro to end a QS record without locking
-/// the interrupts.
-/// \note This macro is intended to use only inside QP components and NOT
-/// at the application level. \sa #QS_END_NOLOCK
-#define QS_END_NOLOCK_() \
-        QS::end(); \
-    }
-
-/// \brief Internal QS macro to output an unformatted uint8_t data element
-#define QS_U8_(data_)           QS::u8_(data_)
-
-/// \brief Internal QS macro to output an unformatted uint16_t data element
-#define QS_U16_(data_)          QS::u16_(data_)
-
-/// \brief Internal QS macro to output an unformatted uint32_t data element
-#define QS_U32_(data_)          QS::u32_(data_)
-
-
-#if (QS_OBJ_PTR_SIZE == 1)
-    #define QS_OBJ_(obj_)       QS::u8_((uint8_t)(obj_))
-#elif (QS_OBJ_PTR_SIZE == 2)
-    #define QS_OBJ_(obj_)       QS::u16_((uint16_t)(obj_))
-#elif (QS_OBJ_PTR_SIZE == 4)
-    #define QS_OBJ_(obj_)       QS::u32_((uint32_t)(obj_))
-#elif (QS_OBJ_PTR_SIZE == 8)
-    #define QS_OBJ_(obj_)       QS::u64_((uint64_t)(obj_))
-#else
-
-    /// \brief Internal QS macro to output an unformatted object pointer
-    /// data element
-    /// \note the size of the pointer depends on the macro #QS_OBJ_PTR_SIZE.
-    /// If the size is not defined the size of pointer is assumed 4-bytes.
-    #define QS_OBJ_(obj_)       QS::u32_((uint32_t)(obj_))
-#endif
-
-
-#if (QS_FUN_PTR_SIZE == 1)
-    #define QS_FUN_(fun_)       QS::u8_((uint8_t)(fun_))
-#elif (QS_FUN_PTR_SIZE == 2)
-    #define QS_FUN_(fun_)       QS::u16_((uint16_t)(fun_))
-#elif (QS_FUN_PTR_SIZE == 4)
-    #define QS_FUN_(fun_)       QS::u32_((uint32_t)(fun_))
-#elif (QS_FUN_PTR_SIZE == 8)
-    #define QS_FUN_(fun_)       QS::u64_((uint64_t)(fun_))
-#else
-
-    /// \brief Internal QS macro to output an unformatted function pointer
-    /// data element
-    /// \note the size of the pointer depends on the macro #QS_FUN_PTR_SIZE.
-    /// If the size is not defined the size of pointer is assumed 4-bytes.
-    #define QS_FUN_(fun_)       QS::u32_((uint32_t)(fun_))
-#endif
-
-/// \brief Internal QS macro to output a zero-terminated ASCII string
-/// data element
-#define QS_STR_(msg_)           QS::str_(msg_)
-
-/// \brief Internal QS macro to output a zero-terminated ASCII string
-/// allocated in ROM data element
-#define QS_STR_ROM_(msg_)       QS::str_ROM_(msg_)
-
-//////////////////////////////////////////////////////////////////////////////
-// Macros for use in the client code
-
-/// \brief Enumerates data formats recognized by QS
-///
-/// QS uses this enumeration is used only internally for the formatted user
-/// data elements.
-enum QSType {
-    QS_I8_T,                                  ///< signed 8-bit integer format
-    QS_U8_T,                                ///< unsigned 8-bit integer format
-    QS_I16_T,                                ///< signed 16-bit integer format
-    QS_U16_T,                              ///< unsigned 16-bit integer format
-    QS_I32_T,                                ///< signed 32-bit integer format
-    QS_U32_T,                              ///< unsigned 32-bit integer format
-    QS_F32_T,                                ///< 32-bit floating point format
-    QS_F64_T,                                ///< 64-bit floating point format
-    QS_STR_T,                         ///< zero-terminated ASCII string format
-    QS_MEM_T,                         ///< up to 255-bytes memory block format
-    QS_SIG_T,                                         ///< event signal format
-    QS_OBJ_T,                                       ///< object pointer format
-    QS_FUN_T,                                     ///< function pointer format
-    QS_I64_T,                                ///< signed 64-bit integer format
-    QS_U64_T,                              ///< unsigned 64-bit integer format
-    QS_U32_HEX_T                    ///< unsigned 32-bit integer in hex format
-};
-
-/// \brief Output formatted int8_t to the QS record
-#define QS_I8(width_, data_) \
-    QS::u8((uint8_t)(((width_) << 4)) | QS_I8_T, (data_))
-
-/// \brief Output formatted uint8_t to the QS record
-#define QS_U8(width_, data_) \
-    QS::u8((uint8_t)(((width_) << 4)) | QS_U8_T, (data_))
-
-/// \brief Output formatted int16_t to the QS record
-#define QS_I16(width_, data_) \
-    QS::u16((uint8_t)(((width_) << 4)) | QS_I16_T, (data_))
-
-/// \brief Output formatted uint16_t to the QS record
-#define QS_U16(width_, data_) \
-    QS::u16((uint8_t)(((width_) << 4)) | QS_U16_T, (data_))
-
-/// \brief Output formatted int32_t to the QS record
-#define QS_I32(width_, data_) \
-    QS::u32((uint8_t)(((width_) << 4)) | QS_I32_T, (data_))
-
-/// \brief Output formatted uint32_t to the QS record
-#define QS_U32(width_, data_) \
-    QS::u32((uint8_t)(((width_) << 4)) | QS_U32_T, (data_))
-
-/// \brief Output formatted 32-bit floating point number to the QS record
-#define QS_F32(width_, data_) \
-    QS::f32((uint8_t)(((width_) << 4)) | QS_F32_T, (data_))
-
-/// \brief Output formatted 64-bit floating point number to the QS record
-#define QS_F64(width_, data_) \
-    QS::f64((uint8_t)(((width_) << 4)) | QS_F64_T, (data_))
-
-/// \brief Output formatted int64_t to the QS record
-#define QS_I64(width_, data_) \
-    QS::u64((uint8_t)(((width_) << 4)) | QS_I64_T, (data_))
-
-/// \brief Output formatted uint64_t to the QS record
-#define QS_U64(width_, data_) \
-    QS::u64((uint8_t)(((width_) << 4)) | QS_U64_T, (data_))
-
-/// \brief Output formatted uint32_t to the QS record
-#define QS_U32_HEX(width_, data_) \
-    QS::u32((uint8_t)(((width_) << 4)) | QS_U32_HEX_T, (data_))
-
-/// \brief Output formatted zero-terminated ASCII string to the QS record
-#define QS_STR(str_)            QS::str(str_)
-
-/// \brief Output formatted zero-terminated ASCII string from ROM
-/// to the QS record
-#define QS_STR_ROM(str_)        QS::str_ROM(str_)
-
-/// \brief Output formatted memory block of up to 255 bytes to the QS
-/// record
-#define QS_MEM(mem_, size_)     QS::mem((mem_), (size_))
-
-
-#if (QS_OBJ_PTR_SIZE == 1)
-    #define QS_OBJ(obj_)        QS::u8(QS_OBJ_T, (uint8_t)(obj_))
-#elif (QS_OBJ_PTR_SIZE == 2)
-    #define QS_OBJ(obj_)        QS::u16(QS_OBJ_T, (uint16_t)(obj_))
-#elif (QS_OBJ_PTR_SIZE == 4)
-    #define QS_OBJ(obj_)        QS::u32(QS_OBJ_T, (uint32_t)(obj_))
-#elif (QS_OBJ_PTR_SIZE == 8)
-    #define QS_OBJ(obj_)        QS::u64(QS_OBJ_T, (uint64_t)(obj_))
-#else
-    /// \brief Output formatted object pointer to the QS record
-    #define QS_OBJ(obj_)        QS::u32(QS_OBJ_T, (uint32_t)(obj_))
-#endif
-
-
-#if (QS_FUN_PTR_SIZE == 1)
-    #define QS_FUN(fun_)        QS::u8(QS_FUN_T, (uint8_t)(fun_))
-#elif (QS_FUN_PTR_SIZE == 2)
-    #define QS_FUN(fun_)        QS::u16(QS_FUN_T, (uint16_t)(fun_))
-#elif (QS_FUN_PTR_SIZE == 4)
-    #define QS_FUN(fun_)        QS::u32(QS_FUN_T, (uint32_t)(fun_))
-#elif (QS_FUN_PTR_SIZE == 8)
-    #define QS_FUN(fun_)        QS::u64(QS_FUN_T, (uint64_t)(fun_))
-#else
-    /// \brief Output formatted function pointer to the QS record
-    #define QS_FUN(fun_)        QS::u32(QS_FUN_T, (uint32_t)(fun_))
-#endif
-
-
-/// \brief Output signal dictionary record
-///
-/// A signal dictionary record associates the numerical value of the signal
-/// and the binary address of the state machine that consumes that signal
-/// with the human-readable name of the signal.
-///
-/// Providing a signal dictionary QS record can vastly improve readability of
-/// the QS log, because instead of dealing with cryptic machine addresses the
-/// QSpy host utility can display human-readable names.
-///
-/// A signal dictionary entry is associated with both the signal value \a sig_
-/// and the state machine \a obj_, because signals are required to be unique
-/// only within a given state machine and therefore the same numerical values
-/// can represent different signals in different state machines.
-///
-/// For the "global" signals that have the same meaning in all state machines
-/// (such as globally published signals), you can specify a signal dictionary
-/// entry with the \a obj_ parameter set to NULL.
-///
-/// The following example shows the definition of signal dictionary entries
-/// in the initial transition of the Table active object. Please note that
-/// signals HUNGRY_SIG and DONE_SIG are associated with the Table state
-/// machine only ("me" \a obj_ pointer). The EAT_SIG signal, on the other
-/// hand, is global (0 \a obj_ pointer):
-/// \include qs_sigDic.cpp
-///
-/// \note The QSpy log utility must capture the signal dictionary record
-/// in order to use the human-readable information. You need to connect to
-/// the target before the dictionary entries have been transmitted.
-///
-/// The following QSpy log example shows the signal dictionary records
-/// generated from the Table initial transition and subsequent records that
-/// show human-readable names of the signals:
-/// \include qs_sigLog.txt
-///
-/// The following QSpy log example shows the same sequence of records, but
-/// with dictionary records removed. The human-readable signal names are not
-/// available.
-/// \include qs_sigLog0.txt
-#define QS_SIG_DICTIONARY(sig_, obj_) \
-    if (((QS::glbFilter_[(uint8_t)QS_SIG_DICTIONARY >> 3U] \
-          & (1U << ((uint8_t)QS_SIG_DICTIONARY & 7U))) != 0U)) \
-    { \
-        static char const Q_ROM Q_ROM_VAR sig_name__[] = #sig_; \
-        QS_INT_LOCK_KEY_ \
-        QS_INT_LOCK_(); \
-        QS::begin((uint8_t)QS_SIG_DICTIONARY); \
-        QS_SIG_(sig_); \
-        QS_OBJ_(obj_); \
-        QS_STR_ROM_(sig_name__); \
-        QS::end(); \
-        QS_INT_UNLOCK_(); \
-        QS::onFlush(); \
-    } else ((void)0)
-
-/// \brief Output object dictionary record
-///
-/// An object dictionary record associates the binary address of an object
-/// in the target's memory with the human-readable name of the object.
-///
-/// Providing an object dictionary QS record can vastly improve readability of
-/// the QS log, because instead of dealing with cryptic machine addresses the
-/// QSpy host utility can display human-readable object names.
-///
-/// The following example shows the definition of object dictionary entry
-/// for the Table active object:
-/// \include qs_objDic.cpp
-#define QS_OBJ_DICTIONARY(obj_) \
-    if (((QS::glbFilter_[(uint8_t)QS_OBJ_DICTIONARY >> 3U] \
-          & (1U << ((uint8_t)QS_OBJ_DICTIONARY & 7U))) != 0U)) \
-    { \
-        static char const Q_ROM Q_ROM_VAR obj_name__[] = #obj_; \
-        QS_INT_LOCK_KEY_ \
-        QS_INT_LOCK_(); \
-        QS::begin((uint8_t)QS_OBJ_DICTIONARY); \
-        QS_OBJ_(obj_); \
-        QS_STR_ROM_(obj_name__); \
-        QS::end(); \
-        QS_INT_UNLOCK_(); \
-        QS::onFlush(); \
-    } else ((void)0)
-
-/// \brief Output function dictionary record
-///
-/// A function dictionary record associates the binary address of a function
-/// in the target's memory with the human-readable name of the function.
-///
-/// Providing a function dictionary QS record can vastly improve readability
-/// of the QS log, because instead of dealing with cryptic machine addresses
-/// the QSpy host utility can display human-readable function names.
-///
-/// The example from #QS_SIG_DICTIONARY shows the definition of a function
-/// dictionary.
-#define QS_FUN_DICTIONARY(fun_) \
-    if (((QS::glbFilter_[(uint8_t)QS_FUN_DICTIONARY >> 3U] \
-          & (1U << ((uint8_t)QS_FUN_DICTIONARY & 7U))) != 0U)) \
-    { \
-        static char const Q_ROM Q_ROM_VAR fun_name__[] = #fun_; \
-        QS_INT_LOCK_KEY_ \
-        QS_INT_LOCK_(); \
-        QS::begin((uint8_t)QS_FUN_DICTIONARY); \
-        QS_FUN_(fun_); \
-        QS_STR_ROM_(fun_name__); \
-        QS::end(); \
-        QS_INT_UNLOCK_(); \
-        QS::onFlush(); \
-    } else ((void)0)
-
-/// \brief Flush the QS trace data to the host
-///
-/// This macro invokes the QS::flush() platform-dependent callback function
-/// to flush the QS trace buffer to the host. The function typically
-/// busy-waits until all the data in the buffer is sent to the host.
-/// This is acceptable only in the initial transient.
-#define QS_FLUSH()   QS::onFlush()
-
-
-/// \brief Output the interrupt lock record
-#define QF_QS_INT_LOCK() \
-    QS_BEGIN_NOLOCK_(QS_QF_INT_LOCK, (void *)0, (void *)0); \
-        QS_TIME_(); \
-        QS_U8_((uint8_t)(++QF_intLockNest_)); \
-    QS_END_NOLOCK_()
-
-/// \brief Output the interrupt unlock record
-#define QF_QS_INT_UNLOCK() \
-    QS_BEGIN_NOLOCK_(QS_QF_INT_UNLOCK, (void *)0, (void *)0); \
-        QS_TIME_(); \
-        QS_U8_((uint8_t)(QF_intLockNest_--)); \
-    QS_END_NOLOCK_()
-
-/// \brief Output the interrupt entry record
-#define QF_QS_ISR_ENTRY(isrnest_, prio_) \
-    QS_BEGIN_NOLOCK_(QS_QF_ISR_ENTRY, (void *)0, (void *)0); \
-        QS_TIME_(); \
-        QS_U8_(isrnest_); \
-        QS_U8_(prio_); \
-    QS_END_NOLOCK_()
-
-/// \brief Output the interrupt exit record
-#define QF_QS_ISR_EXIT(isrnest_, prio_) \
-    QS_BEGIN_NOLOCK_(QS_QF_ISR_EXIT, (void *)0, (void *)0); \
-        QS_TIME_(); \
-        QS_U8_(isrnest_); \
-        QS_U8_(prio_); \
-    QS_END_NOLOCK_()
-
-/// \brief Execute an action that is only necessary for QS output
-#define QF_QS_ACTION(act_)      (act_)
-
-/// \brief interrupt-lock nesting level
-///
-/// \note Not to be used by Clients directly, only in ports of QF
-extern uint8_t QF_intLockNest_;
-
-// from "qep.h" --------------------------------------------------------------
-    #if (Q_SIGNAL_SIZE == 1)
-
-        /// \brief Internal QS macro to output an unformatted event signal
-        /// data element
-        /// \note the size of the pointer depends on the macro #Q_SIGNAL_SIZE.
-        #define QS_SIG_(sig_)       QS::u8_(sig_)
-    #elif (Q_SIGNAL_SIZE == 2)
-        #define QS_SIG_(sig_)       QS::u16_(sig_)
-    #elif (Q_SIGNAL_SIZE == 4)
-        #define QS_SIG_(sig_)       QS::u32_(sig_)
-    #endif
-
-// from "qf.h" ---------------------------------------------------------------
-    #if (QF_EQUEUE_CTR_SIZE == 1)
-
-        /// \brief Internal QS macro to output an unformatted event queue
-        /// counter data element
-        /// \note the counter size depends on the macro #QF_EQUEUE_CTR_SIZE.
-        #define QS_EQC_(ctr_)       QS::u8_(ctr_)
-    #elif (QF_EQUEUE_CTR_SIZE == 2)
-        #define QS_EQC_(ctr_)       QS::u16_(ctr_)
-    #elif (QF_EQUEUE_CTR_SIZE == 4)
-        #define QS_EQC_(ctr_)       QS::u32_(ctr_)
-    #else
-        #error "QF_EQUEUE_CTR_SIZE not defined"
-    #endif
-
-
-    #if (QF_EVENT_SIZ_SIZE == 1)
-
-        /// \brief Internal QS macro to output an unformatted event size
-        /// data element
-        /// \note the event size depends on the macro #QF_EVENT_SIZ_SIZE.
-        #define QS_EVS_(size_)      QS::u8_(size_)
-    #elif (QF_EVENT_SIZ_SIZE == 2)
-        #define QS_EVS_(size_)      QS::u16_(size_)
-    #elif (QF_EVENT_SIZ_SIZE == 4)
-        #define QS_EVS_(size_)      QS::u32_(size_)
-    #endif
-
-
-    #if (QF_MPOOL_SIZ_SIZE == 1)
-
-        /// \brief Internal QS macro to output an unformatted memory pool
-        /// block-size data element
-        /// \note the block-size depends on the macro #QF_MPOOL_SIZ_SIZE.
-        #define QS_MPS_(size_)      QS::u8_(size_)
-    #elif (QF_MPOOL_SIZ_SIZE == 2)
-        #define QS_MPS_(size_)      QS::u16_(size_)
-    #elif (QF_MPOOL_SIZ_SIZE == 4)
-        #define QS_MPS_(size_)      QS::u32_(size_)
-    #endif
-
-    #if (QF_MPOOL_CTR_SIZE == 1)
-
-        /// \brief Internal QS macro to output an unformatted memory pool
-        /// block-counter data element
-        /// \note the counter size depends on the macro #QF_MPOOL_CTR_SIZE.
-        #define QS_MPC_(ctr_)       QS::u8_(ctr_)
-    #elif (QF_MPOOL_CTR_SIZE == 2)
-        #define QS_MPC_(ctr_)       QS::u16_(ctr_)
-    #elif (QF_MPOOL_CTR_SIZE == 4)
-        #define QS_MPC_(ctr_)       QS::u32_(ctr_)
-    #endif
-
-
-    #if (QF_TIMEEVT_CTR_SIZE == 1)
-
-        /// \brief Internal QS macro to output an unformatted time event
-        /// tick-counter data element
-        /// \note the counter size depends on the macro #QF_TIMEEVT_CTR_SIZE.
-        #define QS_TEC_(ctr_)       QS::u8_(ctr_)
-    #elif (QF_TIMEEVT_CTR_SIZE == 2)
-        #define QS_TEC_(ctr_)       QS::u16_(ctr_)
-    #elif (QF_TIMEEVT_CTR_SIZE == 4)
-        #define QS_TEC_(ctr_)       QS::u32_(ctr_)
-    #endif
-
-#else                                                                 // Q_SPY
-
-// qs_dummy.h ================================================================
-
-#define QS_INIT(arg_)                   ((uint8_t)1)
-#define QS_EXIT()                       ((void)0)
-#define QS_DUMP()                       ((void)0)
-#define QS_FILTER_ON(rec_)              ((void)0)
-#define QS_FILTER_OFF(rec_)             ((void)0)
-#define QS_FILTER_SM_OBJ(obj_)          ((void)0)
-#define QS_FILTER_AO_OBJ(obj_)          ((void)0)
-#define QS_FILTER_MP_OBJ(obj_)          ((void)0)
-#define QS_FILTER_EQ_OBJ(obj_)          ((void)0)
-#define QS_FILTER_TE_OBJ(obj_)          ((void)0)
-#define QS_FILTER_AP_OBJ(obj_)          ((void)0)
-
-#define QS_GET_BYTE(pByte_)             ((uint16_t)0xFFFF)
-#define QS_GET_BLOCK(pSize_)            ((uint8_t *)0)
-
-#define QS_BEGIN(rec_, obj_)            if (0) {
-#define QS_END()                        }
-#define QS_BEGIN_NOLOCK(rec_, obj_)     if (0) {
-#define QS_END_NOLOCK()                 }
-
-#define QS_I8(width_, data_)            ((void)0)
-#define QS_U8(width_, data_)            ((void)0)
-#define QS_I16(width_, data_)           ((void)0)
-#define QS_U16(width_, data_)           ((void)0)
-#define QS_I32(width_, data_)           ((void)0)
-#define QS_U32(width_, data_)           ((void)0)
-#define QS_F32(width_, data_)           ((void)0)
-#define QS_F64(width_, data_)           ((void)0)
-#define QS_U64(width_, data_)           ((void)0)
-#define QS_STR(str_)                    ((void)0)
-#define QS_U32_HEX(width_, data_)       ((void)0)
-#define QS_STR_ROM(str_)                ((void)0)
-#define QS_MEM(mem_, size_)             ((void)0)
-#define QS_SIG(sig_, obj_)              ((void)0)
-#define QS_OBJ(obj_)                    ((void)0)
-#define QS_FUN(fun_)                    ((void)0)
-
-#define QS_SIG_DICTIONARY(sig_, obj_)   ((void)0)
-#define QS_OBJ_DICTIONARY(obj_)         ((void)0)
-#define QS_FUN_DICTIONARY(fun_)         ((void)0)
-#define QS_FLUSH()                      ((void)0)
-
-// internal QS macros used only in the QP components .........................
-#define QS_INT_LOCK_KEY_
-#define QS_BEGIN_(rec_, refObj_, obj_)  if (0) {
-#define QS_END_()                       }
-#define QS_BEGIN_NOLOCK_(rec_, refObj_, obj_) if (0) {
-#define QS_END_NOLOCK_()                }
-#define QS_U8_(data_)                   ((void)0)
-#define QS_U16_(data_)                  ((void)0)
-#define QS_U32_(data_)                  ((void)0)
-#define QS_U64_(data_)                  ((void)0)
-#define QS_STR_(str_)                   ((void)0)
-#define QS_TIME_()                      ((void)0)
-#define QS_SIG_(sig_)                   ((void)0)
-#define QS_EVS_(size_)                  ((void)0)
-#define QS_OBJ_(obj_)                   ((void)0)
-#define QS_FUN_(fun_)                   ((void)0)
-#define QS_EQC_(ctr_)                   ((void)0)
-#define QS_MPC_(ctr_)                   ((void)0)
-#define QS_MPS_(size_)                  ((void)0)
-#define QS_TEC_(ctr_)                   ((void)0)
-
-#define QF_QS_INT_LOCK()                ((void)0)
-#define QF_QS_INT_UNLOCK()              ((void)0)
-#define QF_QS_ISR_ENTRY(isrnest_, prio_) ((void)0)
-#define QF_QS_ISR_EXIT(isrnest_, prio_) ((void)0)
-#define QF_QS_ACTION(act_)              ((void)0)
-
-#endif                                                                // Q_SPY
-
-#ifdef Q_USE_NAMESPACE
-}                                                              // namespace QP
-#endif
-
-//////////////////////////////////////////////////////////////////////////////
-/**
-* \brief Customizable QP assertions.
-*
-* Defines customizable and memory-efficient assertions applicable to
-* embedded systems. This header file can be used in C, C++, and mixed C/C++
-* programs.
-*
-* \note The preprocessor switch Q_NASSERT disables checking assertions.
-* In particular macros #Q_ASSERT, #Q_REQUIRE, #Q_ENSURE, #Q_INVARIANT,
-* #Q_ERROR as well as  #Q_ASSERT_ID, #Q_REQUIRE_ID, #Q_ENSURE_ID,
-* #Q_INVARIANT_ID, and #Q_ERROR_ID do NOT evaluate the test condition
-* passed as the argument to these macros. One notable exception is the
-* macro #Q_ALLEGE, that still evaluates the test condition, but does
-* not report assertion failures when the switch Q_NASSERT is defined.
-*/
-#ifdef Q_NASSERT          /* Q_NASSERT defined--assertion checking disabled */
-
-    #define Q_DEFINE_THIS_FILE
-    #define Q_DEFINE_THIS_MODULE(name_)
-    #define Q_ASSERT(test_)             ((void)0)
-    #define Q_ASSERT_ID(id_, test_)     ((void)0)
-    #define Q_ALLEGE(test_)             ((void)(test_))
-    #define Q_ALLEGE_ID(id_, test_)     ((void)(test_))
-    #define Q_ERROR()                   ((void)0)
-    #define Q_ERROR_ID(id_)             ((void)0)
-
-#else                  /* Q_NASSERT not defined--assertion checking enabled */
-
-    #ifdef __cplusplus
-        extern "C" {
-    #endif
-
-    /** callback invoked in case the condition passed to #Q_ASSERT,
-    * #Q_REQUIRE, #Q_ENSURE, #Q_ERROR, #Q_ALLEGE as well as #Q_ASSERT_ID,
-    * #Q_REQUIRE_ID, #Q_ENSURE_ID, #Q_ERROR_ID, and #Q_ALLEGE_ID evaluates
-    * to FALSE.
-    *
-    * \param file file name where the assertion failed
-    * \param line line number at which the assertion failed
-    */
-    /*lint -sem(Q_onAssert, r_no)                Q_onAssert() never returns */
-    void Q_onAssert(char const Q_ROM * const Q_ROM_VAR file, int line);
-
-    #ifdef __cplusplus
-        }
-    #endif
-
-    /** Place this macro at the top of each C/C++ module to define the file
-    * name string using __FILE__ (NOTE: __FILE__ might contain lengthy path
-    * name). This file name will be used in reporting assertions in this file.
-    */
-    #define Q_DEFINE_THIS_FILE \
-        static char const Q_ROM Q_ROM_VAR l_this_file[] = __FILE__;
-
-    /** Place this macro at the top of each C/C++ module to define the module
-    * name as the argument \a name_. This file name will be used in reporting
-    * assertions in this file.
-    */
-    #define Q_DEFINE_THIS_MODULE(name_) \
-        static char const Q_ROM Q_ROM_VAR l_this_file[] = #name_;
-
-    /** General purpose assertion that makes sure the \a test_ argument is
-    * TRUE. Calls the Q_onAssert() callback if the \a test_ evaluates
-    * to FALSE.
-    * \note the \a test_ is NOT evaluated if assertions are disabled with
-    * the Q_NASSERT switch.
-    * \sa #Q_ASSERT_ID
-    */
-    #define Q_ASSERT(test_) \
-        if (test_) { \
-        } \
-        else (Q_onAssert(&l_this_file[0], __LINE__))
-
-    /** General purpose assertion that makes sure the \a test_ argument is
-    * TRUE. Calls the Q_onAssert() callback if the \a test_ evaluates
-    * to FALSE. The argument \a id_ is the ID number (unique within
-    * the file) of the assertion. This assertion style is better suited
-    * for unit testig, because it avoids the volatility of line numbers
-    * for indentifying assertions.
-    * \note the \a test_ is NOT evaluated if assertions are disabled with
-    * the Q_NASSERT switch.
-    * \sa #Q_ASSERT
-    */
-    #define Q_ASSERT_ID(id_, test_) \
-        if (test_) { \
-        } \
-        else (Q_onAssert(&l_this_file[0], (id_)))
-
-    /** General purpose assertion that ALWAYS evaluates the \a test_
-    * argument and calls the Q_onAssert() callback if the \a test_
-    * evaluates to FALSE.
-    * \note the \a test_ argument IS always evaluated even when assertions
-    * are disabled with the Q_NASSERT macro. When the Q_NASSERT macro is
-    * defined, the Q_onAssert() callback is NOT called, even if the
-    * \a test_ evaluates to FALSE.
-    * \sa #Q_ALLEGE_ID
-    */
-    #define Q_ALLEGE(test_)    Q_ASSERT(test_)
-
-    /** General purpose assertion that ALWAYS evaluates the \a test_
-    * argument and calls the Q_onAssert() callback if the \a test_
-    * evaluates to FALSE. This assertion style is better suited
-    * for unit testig, because it avoids the volatility of line numbers
-    * for indentifying assertions.
-    * \note the \a test_ argument IS always evaluated even when assertions
-    * are disabled with the Q_NASSERT macro. When the Q_NASSERT macro is
-    * defined, the Q_onAssert() callback is NOT called, even if the
-    * \a test_ evaluates to FALSE.
-    * \sa #Q_ALLEGE
-    */
-    #define Q_ALLEGE_ID(id_, test_) Q_ASSERT_ID(id_, test_)
-
-    /** Assertion that always calls the Q_onAssert() callback if
-    * ever executed.
-    * \note can be disabled with the Q_NASSERT switch.
-    * \sa #Q_ERROR_ID
-    */
-    #define Q_ERROR() \
-        (Q_onAssert(l_this_file, __LINE__))
-
-    /** Assertion that always calls the Q_onAssert() callback if
-    * ever executed. This assertion style is better suited for unit
-    * testig, because it avoids the volatility of line numbers for
-    * indentifying assertions.
-    * \note can be disabled with the Q_NASSERT switch.
-    * \sa #Q_ERROR
-    */
-    #define Q_ERROR_ID(id_) \
-        (Q_onAssert(l_this_file, (id_)))
-
-
-#endif                                                         /* Q_NASSERT */
-
-/** Assertion that checks for a precondition. This macro is equivalent to
-* #Q_ASSERT, except the name provides a better documentation of the
-* intention of this assertion.
-* \sa #Q_REQUIRE_ID
-*/
-#define Q_REQUIRE(test_)         Q_ASSERT(test_)
-
-/** Assertion that checks for a precondition. This macro is equivalent to
-* #Q_ASSERT_ID, except the name provides a better documentation of the
-* intention of this assertion.
-* \sa #Q_REQUIRE
-*/
-#define Q_REQUIRE_ID(id_, test_) Q_ASSERT_ID(id_, test_)
-
-/** Assertion that checks for a postcondition. This macro is equivalent to
-* #Q_ASSERT, except the name provides a better documentation of the
-* intention of this assertion.
-* \sa #Q_ENSURE_ID
-*/
-#define Q_ENSURE(test_)          Q_ASSERT(test_)
-
-/** Assertion that checks for a postcondition. This macro is equivalent to
-* #Q_ASSERT_ID, except the name provides a better documentation of the
-* intention of this assertion.
-* \sa #Q_ENSURE
-*/
-#define Q_ENSURE_ID(id_, test_)  Q_ASSERT_ID(id_, test_)
-
-/** Assertion that checks for an invariant. This macro is equivalent to
-* #Q_ASSERT, except the name provides a better documentation of the
-* intention of this assertion.
-* \sa #Q_INVARIANT_ID
-*/
-#define Q_INVARIANT(test_)       Q_ASSERT(test_)
-
-/** Assertion that checks for an invariant. This macro is equivalent to
-* #Q_ASSERT_ID, except the name provides a better documentation of the
-* intention of this assertion.
-* \sa #Q_INVARIANT
-*/
-#define Q_INVARIANT_ID(id_, test_) Q_ASSERT_ID(id_, test_)
-
-/** Compile-time assertion exploits the fact that in C/C++ a dimension of
-* an array cannot be negative. The following declaration causes a compilation
-* error if the compile-time expression (\a test_) is not TRUE. The assertion
-* has no runtime side effects.
-*/
-#define Q_ASSERT_COMPILE(test_) \
-    extern char Q_assert_compile[(test_) ? 1 : -1]
-
-#endif                                                                 // qp_h
+//////////////////////////////////////////////////////////////////////////////
+// Product: QP/C++ platform-independent interface
+// Last Updated for QP ver: 4.5.02 (modified to fit in one file)
+// Date of the Last Update: Aug 24, 2012
+//
+//                    Q u a n t u m     L e a P s
+//                    ---------------------------
+//                    innovating embedded systems
+//
+// Copyright (C) 2002-2012 Quantum Leaps, LLC. All rights reserved.
+//
+// This program is open source software: you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as published
+// by the Free Software Foundation, either version 2 of the License, or
+// (at your option) any later version.
+//
+// Alternatively, this program may be distributed and modified under the
+// terms of Quantum Leaps commercial licenses, which expressly supersede
+// the GNU General Public License and are specifically designed for
+// licensees interested in retaining the proprietary status of their code.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+// Contact information:
+// Quantum Leaps Web sites: http://www.quantum-leaps.com
+//                          http://www.state-machine.com
+// e-mail:                  info@quantum-leaps.com
+//////////////////////////////////////////////////////////////////////////////
+#ifndef qp_h
+#define qp_h
+
+// "qevt.h" ==================================================================
+/// \brief QEvt class and basic macros used by all QP components.
+///
+/// This header file must be included, perhaps indirectly, in all modules
+/// (*.cpp files) that use any component of QP/C++ (such as QEP, QF, or QK).
+
+//////////////////////////////////////////////////////////////////////////////
+/// \brief The current QP version number
+///
+/// \return version of the QP as a hex constant constant 0xXYZZ, where X is
+/// a 1-digit major version number, Y is a 1-digit minor version number, and
+/// ZZ is a 2-digit release number.
+#define QP_VERSION      0x4502U
+
+#ifndef Q_ROM
+    /// \brief Macro to specify compiler-specific directive for placing a
+    /// constant object in ROM.
+    ///
+    /// Many compilers for Harvard-architecture MCUs provide non-stanard
+    /// extensions to support placement of objects in different memories.
+    /// In order to conserve the precious RAM, QP uses the Q_ROM macro for
+    /// all constant objects that can be allocated in ROM.
+    ///
+    /// To override the following empty definition, you need to define the
+    /// Q_ROM macro in the qep_port.h header file. Some examples of valid
+    /// Q_ROM macro definitions are: __code (IAR 8051 compiler), code (Keil
+    /// Cx51 compiler), PROGMEM (gcc for AVR), __flash (IAR for AVR).
+    #define Q_ROM
+#endif
+#ifndef Q_ROM_VAR            // if NOT defined, provide the default definition
+    /// \brief Macro to specify compiler-specific directive for accessing a
+    /// constant object in ROM.
+    ///
+    /// Many compilers for MCUs provide different size pointers for
+    /// accessing objects in various memories. Constant objects allocated
+    /// in ROM (see #Q_ROM macro) often mandate the use of specific-size
+    /// pointers (e.g., far pointers) to get access to ROM objects. The
+    /// macro Q_ROM_VAR specifies the kind of the pointer to be used to access
+    /// the ROM objects.
+    ///
+    /// To override the following empty definition, you need to define the
+    /// Q_ROM_VAR macro in the qep_port.h header file. An example of valid
+    /// Q_ROM_VAR macro definition is: __far (Freescale HC(S)08 compiler).
+    #define Q_ROM_VAR
+#endif
+#ifndef Q_ROM_BYTE
+    /// \brief Macro to access a byte allocated in ROM
+    ///
+    /// Some compilers for Harvard-architecture MCUs, such as gcc for AVR, do
+    /// not generate correct code for accessing data allocated in the program
+    /// space (ROM). The workaround for such compilers is to explictly add
+    /// assembly code to access each data element allocated in the program
+    /// space. The macro Q_ROM_BYTE() retrieves a byte from the given ROM
+    /// address.
+    ///
+    /// The Q_ROM_BYTE() macro should be defined for the compilers that
+    /// cannot handle correctly data allocated in ROM (such as the gcc).
+    /// If the macro is left undefined, the default definition simply returns
+    /// the argument and lets the compiler generate the correct code.
+    #define Q_ROM_BYTE(rom_var_)   (rom_var_)
+#endif
+
+#ifndef Q_SIGNAL_SIZE
+    /// \brief The size (in bytes) of the signal of an event. Valid values:
+    /// 1, 2, or 4; default 1
+    ///
+    /// This macro can be defined in the QEP port file (qep_port.h) to
+    /// configure the ::QSignal type. When the macro is not defined, the
+    /// default of 1 byte is chosen.
+    #define Q_SIGNAL_SIZE 2
+#endif
+
+#ifndef Q_NNAMESPACE
+
+    /// \brief begin of the namespace QP
+    ///
+    /// \note defines to nothing if #Q_USE_NAMESPACE is undefined
+    #define QP_BEGIN_  namespace QP {
+
+    /// \brief end of the namespace QP
+    ///
+    /// \note defines to nothing if #Q_USE_NAMESPACE is undefined
+    #define QP_END_    }
+
+    /// \brief namespace QP prefix
+    ///
+    /// \note defines to nothing if #Q_USE_NAMESPACE is undefined
+    #define QP_        QP::
+
+#else
+
+    #define QP_BEGIN_
+    #define QP_END_
+    #define QP_
+
+#endif
+
+QP_BEGIN_
+
+#if (Q_SIGNAL_SIZE == 1)
+    typedef uint8_t QSignal;
+#elif (Q_SIGNAL_SIZE == 2)
+    /// \brief QSignal represents the signal of an event.
+    ///
+    /// The relationship between an event and a signal is as follows. A signal
+    /// in UML is the specification of an asynchronous stimulus that triggers
+    /// reactions [<A HREF="http://www.omg.org/docs/ptc/03-08-02.pdf">UML
+    /// document ptc/03-08-02</A>], and as such is an essential part of an
+    /// event. (The signal conveys the type of the occurrence-what happened?)
+    /// However, an event can also contain additional quantitative information
+    /// about the occurrence in form of event parameters. Please refer to the
+    typedef uint16_t QSignal;
+#elif (Q_SIGNAL_SIZE == 4)
+    typedef uint32_t QSignal;
+#else
+    #error "Q_SIGNAL_SIZE defined incorrectly, expected 1, 2, or 4"
+#endif
+
+#ifdef Q_EVT_CTOR               // Provide the constructor for the QEvt class?
+
+    //////////////////////////////////////////////////////////////////////////
+    /// \brief QEvt base class.
+    ///
+    /// QEvt represents events without parameters and serves as the base class
+    /// for derivation of events with parameters.
+    ///
+    /// The following example illustrates how to add an event parameter by
+    /// inheriting from the QEvt class.
+    /// \include qep_qevent.cpp
+    class QEvt {
+    public:
+        QSignal sig;                         ///< signal of the event instance
+
+        QEvt(QSignal const s)           // poolId_ intentionally uninitialized
+          : sig(s) {}
+
+#ifdef Q_EVT_VIRTUAL
+        virtual ~QEvt() {}                               // virtual destructor
+#endif
+
+    private:
+        uint8_t poolId_;                     ///< pool ID (0 for static event)
+        uint8_t refCtr_;                                ///< reference counter
+
+        friend class QF;
+        friend class QTimeEvt;
+        friend uint8_t QF_EVT_POOL_ID_ (QEvt const * const e);
+        friend uint8_t QF_EVT_REF_CTR_ (QEvt const * const e);
+        friend void QF_EVT_REF_CTR_INC_(QEvt const * const e);
+        friend void QF_EVT_REF_CTR_DEC_(QEvt const * const e);
+    };
+
+#else                                    // QEvt is a POD (Plain Old Datatype)
+
+    struct QEvt {
+        QSignal sig;                         ///< signal of the event instance
+        uint8_t poolId_;                     ///< pool ID (0 for static event)
+        uint8_t refCtr_;                                ///< reference counter
+    };
+
+#endif                                                           // Q_EVT_CTOR
+
+QP_END_
+
+//////////////////////////////////////////////////////////////////////////////
+/// helper macro to calculate static dimension of a 1-dim array \a array_
+#define Q_DIM(array_) (sizeof(array_) / sizeof(array_[0]))
+
+//////////////////////////////////////////////////////////////////////////////
+// typedefs for basic numerical types; MISRA-C++ 2008 rule 3-9-2(req).
+
+/// \brief typedef for character strings.
+///
+/// This typedef specifies character type for exclusive use in character
+/// strings. Use of this type, rather than plain 'char', is in compliance
+/// with the MISRA-C 2004 Rules 6.1(req), 6.3(adv).
+///
+typedef char char_t;
+
+/// typedef for 32-bit IEEE 754 floating point numbers
+typedef float float32_t;
+
+/// typedef for 64-bit IEEE 754 floating point numbers
+typedef double float64_t;
+
+/// typedef for enumerations used for event signals
+typedef int enum_t;
+
+/// \brief Perform cast from unsigned integer \a uint_ to pointer
+/// of type \a type_.
+///
+/// This macro encapsulates the cast to (type_ *), which QP ports or
+/// application might use to access embedded hardware registers.
+/// Such uses can trigger PC-Lint "Note 923: cast from int to pointer"
+/// and this macro helps to encapsulate this deviation.
+///
+#define Q_UINT2PTR_CAST(type_, uint_)  (reinterpret_cast<type_ *>(uint_))
+
+/// \brief Initializer of static constant QEvt instances
+///
+/// This macro encapsulates the ugly casting of enumerated signals
+/// to QSignal and constants for QEvt.poolID and QEvt.refCtr_.
+///
+#define QEVT_INITIALIZER(sig_) { static_cast<QP_ QSignal>(sig_), \
+    static_cast<uint8_t>(0), static_cast<uint8_t>(0) }
+
+//////////////////////////////////////////////////////////////////////////////
+// facilities for backwards compatibility
+//
+#ifndef Q_NQEVENT
+//    typedef struct QEvt QEvent;
+    #define QEvent QEvt
+#endif
+
+
+// "qep.h" ===================================================================
+/// \brief QEP/C++ platform-independent public interface.
+///
+/// This header file must be included directly or indirectly
+/// in all modules (*.cpp files) that use QEP/C++.
+
+/// \brief Designates a target for an initial or regular transition.
+/// Q_TRAN() can be used both in the FSMs and HSMs.
+///
+/// \include qep_qtran.c
+///
+#define Q_TRAN(target_)     (me->tran(Q_STATE_CAST(target_)))
+
+/// \brief Designates the superstate of a given state in an HSM.
+///
+/// \include qep_qhsm.c
+///
+#define Q_SUPER(super_)     (me->super(Q_STATE_CAST(super_)))
+
+/// \brief Perform cast to QStateHandler.
+///
+/// This macro encapsulates the cast of a specific state handler function
+/// pointer to QStateHandler, which violates MISRA-C 2004 rule 11.4(advisory).
+/// This macro helps to localize this deviation.
+///
+#define Q_STATE_CAST(handler_) \
+    (reinterpret_cast<QP_ QStateHandler>(handler_))
+
+/// \brief Perform downcast of an event onto a subclass of QEvt \a class_
+///
+/// This macro encapsulates the downcast of QEvt pointers, which violates
+/// MISRA-C 2004 rule 11.4(advisory). This macro helps to localize this
+/// deviation.
+///
+#define Q_EVT_CAST(class_)   (static_cast<class_ const *>(e))
+
+//////////////////////////////////////////////////////////////////////////////
+QP_BEGIN_
+
+/// \brief Provides miscellaneous QEP services.
+class QEP {
+public:
+    /// \brief get the current QEP version number string
+    ///
+    /// \return version of the QEP as a constant 6-character string of the
+    /// form x.y.zz, where x is a 1-digit major version number, y is a
+    /// 1-digit minor version number, and zz is a 2-digit release number.
+    static char_t const Q_ROM * Q_ROM_VAR getVersion(void);
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+                       /// \brief Type returned from  a state-handler function
+typedef uint8_t QState;
+                                  /// \brief pointer to state-handler function
+typedef QState (*QStateHandler)(void * const me, QEvt const * const e);
+
+//////////////////////////////////////////////////////////////////////////////
+/// \brief Value returned by a state-handler function when it handles
+/// the event.
+QState const Q_RET_HANDLED = static_cast<QState>(0);
+
+/// \brief Value returned by a non-hierarchical state-handler function when
+/// it ignores (does not handle) the event.
+QState const Q_RET_IGNORED = static_cast<QState>(1);
+
+/// \brief Value returned by a state-handler function when it takes a
+/// regular state transition.
+QState const Q_RET_TRAN    = static_cast<QState>(2);
+
+/// \brief Value returned by a state-handler function when it forwards
+/// the event to the superstate to handle.
+QState const Q_RET_SUPER   = static_cast<QState>(3);
+
+/// \brief Value returned by a state-handler function when a guard
+/// condition prevents it from handling the event.
+///
+QState const Q_RET_UNHANDLED = static_cast<QState>(4);
+
+
+/// Offset or the user signals
+enum_t const Q_USER_SIG    = static_cast<enum_t>(4);
+
+
+//////////////////////////////////////////////////////////////////////////////
+/// \brief Finite State Machine base class
+///
+/// QFsm represents a traditional non-hierarchical Finite State Machine (FSM)
+/// without state hierarchy, but with entry/exit actions.
+///
+/// QFsm is also a base structure for the ::QHsm class.
+///
+/// \note QFsm is not intended to be instantiated directly, but rather serves
+/// as the base class for derivation of state machines in the application
+/// code.
+///
+/// The following example illustrates how to derive a state machine class
+/// from QFsm.
+/// \include qep_qfsm.cpp
+class QFsm {
+private:
+    QStateHandler m_state;          ///< current active state (state-variable)
+    QStateHandler m_temp;  ///< temporary state: target of tran. or superstate
+
+public:
+    /// \brief virtual destructor
+    virtual ~QFsm();
+
+    /// \brief Performs the second step of FSM initialization by triggering
+    /// the top-most initial transition.
+    ///
+    /// The argument \a e is constant pointer to ::QEvt or a class
+    /// derived from ::QEvt.
+    ///
+    /// \note Must be called only ONCE before QFsm::dispatch()
+    ///
+    /// The following example illustrates how to initialize a FSM, and
+    /// dispatch events to it:
+    /// \include qep_qfsm_use.cpp
+    void init(QEvt const * const e = static_cast<QEvt const *>(0));
+
+    /// \brief Dispatches an event to a FSM
+    ///
+    /// Processes one event at a time in Run-to-Completion (RTC) fashion.
+    /// The argument \a e is a constant pointer the ::QEvt or a
+    /// class derived from ::QEvt.
+    ///
+    /// \note Must be called after QFsm::init().
+    ///
+    /// \sa example for QFsm::init()
+    void dispatch(QEvt const * const e);
+
+protected:
+    /// \brief Protected constructor of a FSM.
+    ///
+    /// Performs the first step of FSM initialization by assigning the
+    /// initial pseudostate to the currently active state of the state
+    /// machine.
+    ///
+    /// \note The constructor is protected to prevent direct instantiating
+    /// of QFsm objects. This class is intended for subclassing only.
+    ///
+    /// \sa The ::QFsm example illustrates how to use the QHsm constructor
+    /// in the constructor initializer list of the derived state machines.
+    QFsm(QStateHandler const initial)
+      : m_state(Q_STATE_CAST(0)),
+        m_temp(initial)
+    {}
+
+    /// \brief Return the current active state.
+    QStateHandler state(void) const {
+        return m_state;
+    }
+
+    /// \brief Inline function to specify the return of a state-handler
+    /// when it igonres (does not handle in any way) the event.
+    static QState Q_IGNORED(void) { return Q_RET_IGNORED; }
+
+    /// \brief Inline function to specify the return of a state-handler
+    /// when it handles the event.
+    ///
+    /// \include qep_qhsm.cpp
+    static QState Q_HANDLED(void) { return Q_RET_HANDLED; }
+
+    /// \brief Macro to specify the return of a state-handler function when
+    /// it attempts to handle the event but a guard condition evaluates to
+    /// false and there is no other explicit way of handling the event.
+    static QState Q_UNHANDLED(void) { return Q_RET_UNHANDLED; }
+
+    /// \brief internal helper function to record a state transition
+    QState tran(QStateHandler const target) {
+        m_temp = target;
+        return Q_RET_TRAN;
+    }
+
+    enum ReservedFsmSignals {
+        Q_ENTRY_SIG = 1,                         ///< signal for entry actions
+        Q_EXIT_SIG                                ///< signal for exit actions
+    };
+};
+
+//////////////////////////////////////////////////////////////////////////////
+/// \brief Hierarchical State Machine base class
+///
+/// QHsm represents a Hierarchical Finite State Machine (HSM). QHsm derives
+/// from the ::QFsm class and extends the capabilities of a basic FSM
+/// with state hierarchy.
+///
+/// \note QHsm is not intended to be instantiated directly, but rather serves
+/// as the base structure for derivation of state machines in the application
+/// code.
+///
+/// The following example illustrates how to derive a state machine class
+/// from QHsm.
+/// \include qep_qhsm.cpp
+class QHsm {
+private:
+    QStateHandler m_state;          ///< current active state (state-variable)
+    QStateHandler m_temp;  ///< temporary state: target of tran. or superstate
+
+public:
+    /// \brief virtual destructor
+    virtual ~QHsm();
+
+    /// \brief Performs the second step of HSM initialization by triggering
+    /// the top-most initial transition.
+    ///
+    /// \param e constant pointer ::QEvt or a class derived from ::QEvt
+    /// \note Must be called only ONCE before QHsm::dispatch()
+    ///
+    /// The following example illustrates how to initialize a HSM, and
+    /// dispatch events to it:
+    /// \include qep_qhsm_use.cpp
+    void init(QEvt const * const e = static_cast<QEvt const *>(0));
+
+    /// \brief Dispatches an event to a HSM
+    ///
+    /// Processes one event at a time in Run-to-Completion (RTC) fashion.
+    /// The argument \a e is a constant pointer the ::QEvt or a
+    /// class derived from ::QEvt.
+    ///
+    /// \note Must be called after QHsm::init().
+    ///
+    /// \sa example for QHsm::init()
+    void dispatch(QEvt const * const e);
+
+    /// \brief Tests if a given state is part of the current active state
+    /// configuratioin
+    ///
+    /// \param state is a pointer to the state handler function, e.g.,
+    /// &QCalc::on.
+    bool isIn(QStateHandler const s);
+
+protected:
+    /// \brief Protected constructor of a HSM.
+    ///
+    /// Performs the first step of HSM initialization by assigning the
+    /// initial pseudostate to the currently active state of the state
+    /// machine.
+    ///
+    /// \note The constructor is protected to prevent direct instantiating
+    /// of QHsm objects. This class is intended for subclassing only.
+    ///
+    /// \sa The ::QHsm example illustrates how to use the QHsm constructor
+    /// in the constructor initializer list of the derived state machines.
+    /// \sa QFsm::QFsm()
+    QHsm(QStateHandler const initial)
+      : m_state(Q_STATE_CAST(&QHsm::top)),
+        m_temp(initial)
+    {}
+
+    /// \brief Return the current active state.
+    QStateHandler state(void) const {
+        return m_state;
+    }
+
+    /// \brief the top-state.
+    ///
+    /// QHsm::top() is the ultimate root of state hierarchy in all HSMs
+    /// derived from ::QHsm. This state handler always returns (QSTATE)0,
+    /// which means that it "handles" all events.
+    ///
+    /// \sa Example of the QCalc::on() state handler.
+    static QState top(void * const me, QEvt const * const e);
+
+    /// \brief Inline function to specify the return of a state-handler
+    /// when it handles the event.
+    ///
+    /// \include qep_qhsm.cpp
+    static QState Q_HANDLED(void) { return Q_RET_HANDLED; }
+
+    /// \brief Macro to specify the return of a state-handler function when
+    /// it attempts to handle the event but a guard condition evaluates to
+    /// false and there is no other explicit way of handling the event.
+    static QState Q_UNHANDLED(void) { return Q_RET_UNHANDLED; }
+
+    /// \brief internal helper function to record a state transition
+    QState tran(QStateHandler const target) {
+        m_temp = target;
+        return Q_RET_TRAN;
+    }
+
+    /// \brief internal helper function to record the superstate
+    QState super(QStateHandler const superstate) {
+        m_temp = superstate;
+        return Q_RET_SUPER;
+    }
+
+    enum ReservedHsmSignals {
+        Q_ENTRY_SIG = 1,                         ///< signal for entry actions
+        Q_EXIT_SIG,                               ///< signal for exit actions
+        Q_INIT_SIG                  ///< signal for nested initial transitions
+    };
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+QP_END_
+
+// "qequeue.h" ===============================================================
+/// \brief platform-independent event queue interface.
+///
+/// This header file must be included in all QF ports that use native QF
+/// event queue implementation. Also, this file is needed when the "raw"
+/// thread-safe queues are used for communication between active objects
+/// and non-framework entities, such as ISRs, device drivers, or legacy
+/// code.
+
+#ifndef QF_EQUEUE_CTR_SIZE
+
+    /// \brief The size (in bytes) of the ring-buffer counters used in the
+    /// native QF event queue implementation. Valid values: 1, 2, or 4;
+    /// default 1.
+    ///
+    /// This macro can be defined in the QF port file (qf_port.h) to
+    /// configure the ::QEQueueCtr type. Here the macro is not defined so the
+    /// default of 1 byte is chosen.
+    #define QF_EQUEUE_CTR_SIZE 1
+#endif
+
+QP_BEGIN_
+
+#if (QF_EQUEUE_CTR_SIZE == 1)
+    /// \brief The data type to store the ring-buffer counters based on
+    /// the macro #QF_EQUEUE_CTR_SIZE.
+    ///
+    /// The dynamic range of this data type determines the maximum length
+    /// of the ring buffer managed by the native QF event queue.
+    typedef uint8_t QEQueueCtr;
+#elif (QF_EQUEUE_CTR_SIZE == 2)
+    typedef uint16_t QEQueueCtr;
+#elif (QF_EQUEUE_CTR_SIZE == 4)
+    typedef uint32_t QEQueueCtr;
+#else
+    #error "QF_EQUEUE_CTR_SIZE defined incorrectly, expected 1, 2, or 4"
+#endif
+
+
+//////////////////////////////////////////////////////////////////////////////
+/// \brief Native QF Event Queue class
+///
+/// This structure describes the native QF event queue, which can be used as
+/// the event queue for active objects, or as a simple "raw" event queue for
+/// thread-safe event passing among non-framework entities, such as ISRs,
+/// device drivers, or other third-party components.
+///
+/// The native QF event queue is configured by defining the macro
+/// #QF_EQUEUE_TYPE as ::QEQueue in the specific QF port header file.
+///
+/// The ::QEQueue structure contains only data members for managing an event
+/// queue, but does not contain the storage for the queue buffer, which must
+/// be provided externally during the queue initialization.
+///
+/// The event queue can store only event pointers, not the whole events. The
+/// internal implementation uses the standard ring-buffer plus one external
+/// location that optimizes the queue operation for the most frequent case
+/// of empty queue.
+///
+/// The ::QEQueue structure is used with two sets of functions. One set is for
+/// the active object event queue, which needs to block the active object
+/// task when the event queue is empty and unblock it when events are posted
+/// to the queue. The interface for the native active object event queue
+/// consists of the following functions: QActive::postFIFO_(),
+/// QActive::postLIFO_(), and QActive::get_(). Additionally the function
+/// QEQueue_init() is used to initialize the queue.
+///
+/// The other set of functions, uses this structure as a simple "raw" event
+/// queue to pass events between entities other than active objects, such as
+/// ISRs. The "raw" event queue is not capable of blocking on the get()
+/// operation, but is still thread-safe because it uses QF critical section
+/// to protect its integrity. The interface for the "raw" thread-safe queue
+/// consists of the following functions: QEQueue::postFIFO(),
+/// QEQueue::postLIFO(), and QEQueue::get(). Additionally the function
+/// QEQueue::init() is used to initialize the queue.
+///
+/// \note Most event queue operations (both the active object queues and
+/// the "raw" queues) internally use  the QF critical section. You should be
+/// careful not to invoke those operations from other critical sections when
+/// nesting of critical sections is not supported.
+class QEQueue {
+private:
+
+    /// \brief pointer to event at the front of the queue
+    ///
+    /// All incoming and outgoing events pass through the m_frontEvt location.
+    /// When the queue is empty (which is most of the time), the extra
+    /// m_frontEvt location allows to bypass the ring buffer altogether,
+    /// greatly optimizing the performance of the queue. Only bursts of events
+    /// engage the ring buffer.
+    ///
+    /// The additional role of this attribute is to indicate the empty status
+    /// of the queue. The queue is empty if the m_frontEvt location is NULL.
+    QEvt const *m_frontEvt;
+
+    /// \brief pointer to the start of the ring buffer
+    QEvt const **m_ring;
+
+    /// \brief offset of the end of the ring buffer from the start of the
+    /// buffer m_ring
+    QEQueueCtr m_end;
+
+    /// \brief offset to where next event will be inserted into the buffer
+    QEQueueCtr m_head;
+
+    /// \brief offset of where next event will be extracted from the buffer
+    QEQueueCtr m_tail;
+
+    /// \brief number of free events in the ring buffer
+    QEQueueCtr m_nFree;
+
+    /// \brief minimum number of free events ever in the ring buffer.
+    ///
+    /// \note this attribute remembers the low-watermark of the ring buffer,
+    /// which provides a valuable information for sizing event queues.
+    /// \sa QF::getQueueMargin().
+    QEQueueCtr m_nMin;
+
+public:
+
+    /// \brief Initializes the native QF event queue
+    ///
+    /// The parameters are as follows: \a qSto[] is the ring buffer storage,
+    /// \a qLen is the length of the ring buffer in the units of event-
+    /// pointers.
+    ///
+    /// \note The actual capacity of the queue is qLen + 1, because of the
+    /// extra location fornEvt_.
+    void init(QEvt const *qSto[], QEQueueCtr const qLen);
+
+    /// \brief "raw" thread-safe QF event queue implementation for the
+    /// First-In-First-Out (FIFO) event posting. You can call this function
+    /// from any task context or ISR context. Please note that this function
+    /// uses internally a critical section.
+    ///
+    /// \note The function raises an assertion if the native QF queue becomes
+    /// full and cannot accept the event.
+    ///
+    /// \sa QEQueue::postLIFO(), QEQueue::get()
+    void postFIFO(QEvt const * const e);
+
+    /// \brief "raw" thread-safe QF event queue implementation for the
+    /// First-In-First-Out (FIFO) event posting. You can call this function
+    /// from any task context or ISR context. Please note that this function
+    ///  uses internally a critical section.
+    ///
+    /// \note The function raises an assertion if the native QF queue becomes
+    /// full and cannot accept the event.
+    ///
+    /// \sa QEQueue::postLIFO(), QEQueue::get()
+    void postLIFO(QEvt const * const e);
+
+    /// \brief "raw" thread-safe QF event queue implementation for the
+    /// Last-In-First-Out (LIFO) event posting.
+    ///
+    /// \note The LIFO policy should be used only with great caution because
+    /// it alters order of events in the queue.
+    /// \note The function raises an assertion if the native QF queue becomes
+    /// full and cannot accept the event. You can call this function from
+    /// any task context or ISR context. Please note that this function uses
+    /// internally a critical section.
+    ///
+    /// \sa QEQueue::postFIFO(), QEQueue::get()
+    QEvt const *get(void);
+
+    /// \brief "raw" thread-safe QF event queue operation for
+    /// obtaining the number of free entries still available in the queue.
+    ///
+    /// \note This operation needs to be used with caution because the
+    /// number of free entries can change unexpectedly. The main intent for
+    /// using this operation is in conjunction with event deferral. In this
+    /// case the queue is accessed only from a single thread (by a single AO),
+    /// so the number of free entries cannot change unexpectedly.
+    ///
+    /// \sa QActive::defer(), QActive::recall()
+    QEQueueCtr getNFree(void) const {
+        return m_nFree;
+    }
+
+private:
+    friend class QF;
+    friend class QActive;
+};
+
+QP_END_
+
+// "qmpool.h" ================================================================
+/// \brief platform-independent memory pool interface.
+///
+/// This header file must be included in all QF ports that use native QF
+/// memory pool implementation.
+
+#ifndef QF_MPOOL_SIZ_SIZE
+    /// \brief macro to override the default ::QMPoolSize size.
+    /// Valid values 1, 2, or 4; default 2
+    #define QF_MPOOL_SIZ_SIZE 2
+#endif
+
+#ifndef QF_MPOOL_CTR_SIZE
+
+    /// \brief macro to override the default QMPoolCtr size.
+    /// Valid values 1, 2, or 4; default 2
+    #define QF_MPOOL_CTR_SIZE 2
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+QP_BEGIN_
+
+#if (QF_MPOOL_SIZ_SIZE == 1)
+    /// \brief The data type to store the block-size based on the macro
+    /// #QF_MPOOL_SIZ_SIZE.
+    ///
+    /// The dynamic range of this data type determines the maximum size
+    /// of blocks that can be managed by the native QF event pool.
+    typedef uint8_t QMPoolSize;
+#elif (QF_MPOOL_SIZ_SIZE == 2)
+
+    typedef uint16_t QMPoolSize;
+#elif (QF_MPOOL_SIZ_SIZE == 4)
+    typedef uint32_t QMPoolSize;
+#else
+    #error "QF_MPOOL_SIZ_SIZE defined incorrectly, expected 1, 2, or 4"
+#endif
+
+#if (QF_MPOOL_CTR_SIZE == 1)
+    /// \brief The data type to store the block-counter based on the macro
+    /// #QF_MPOOL_CTR_SIZE.
+    ///
+    /// The dynamic range of this data type determines the maximum number
+    /// of blocks that can be stored in the pool.
+    typedef uint8_t QMPoolCtr;
+#elif (QF_MPOOL_CTR_SIZE == 2)
+    typedef uint16_t QMPoolCtr;
+#elif (QF_MPOOL_CTR_SIZE == 4)
+    typedef uint32_t QMPoolCtr;
+#else
+    #error "QF_MPOOL_CTR_SIZE defined incorrectly, expected 1, 2, or 4"
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+/// \brief Native QF memory pool class
+///
+/// This class describes the native QF memory pool, which can be used as
+/// the event pool for dynamic event allocation, or as a fast, deterministic
+/// fixed block-size heap for any other objects in your application.
+///
+/// The ::QMPool structure contains only data members for managing a memory
+/// pool, but does not contain the pool storage, which must be provided
+/// externally during the pool initialization.
+///
+/// The native QF event pool is configured by defining the macro
+/// #QF_EPOOL_TYPE_ as QEQueue in the specific QF port header file.
+class QMPool {
+private:
+
+    /// start of the memory managed by this memory pool
+    void *m_start;
+
+    /// end of the memory managed by this memory pool
+    void *m_end;
+
+    /// linked list of free blocks
+    void *m_free;
+
+    ///  maximum block size (in bytes)
+    QMPoolSize m_blockSize;
+
+    /// total number of blocks
+    QMPoolCtr m_nTot;
+
+    /// number of free blocks remaining
+    QMPoolCtr m_nFree;
+
+    /// minimum number of free blocks ever present in this pool
+    ///
+    /// \note this attribute remembers the low watermark of the pool,
+    /// which provides a valuable information for sizing event pools.
+    /// \sa QF::getPoolMargin().
+    QMPoolCtr m_nMin;
+
+public:
+
+    /// \brief Initializes the native QF event pool
+    ///
+    /// The parameters are as follows: \a poolSto is the pool storage,
+    /// \a poolSize is the size of the pool storage in bytes, and
+    /// \a blockSize is the block size of this pool.
+    ///
+    /// The caller of this method must make sure that the \a poolSto pointer
+    /// is properly aligned. In particular, it must be possible to efficiently
+    /// store a pointer at the location pointed to by \a poolSto.
+    /// Internally, the QMPool::init() function rounds up the block size
+    /// \a blockSize so that it can fit an integer number of pointers.
+    /// This is done to achieve proper alignment of the blocks within the
+    /// pool.
+    ///
+    /// \note Due to the rounding of block size the actual capacity of the
+    /// pool might be less than (\a poolSize / \a blockSize). You can check
+    ///  the capacity of the pool by calling the QF::getPoolMargin() function.
+    void init(void * const poolSto, uint32_t const poolSize,
+              QMPoolSize const blockSize);
+
+    /// \brief Obtains a memory block from a memory pool.
+    ///
+    /// The only parameter \a me is a pointer to the ::QMPool from which the
+    /// block is requested. The function returns a pointer to the allocated
+    /// memory block or NULL if no free blocks are available.
+    ///
+    /// A allocated block must be returned to the same pool from which it has
+    /// been allocated.
+    ///
+    /// This function can be called from any task level or ISR level.
+    ///
+    /// \note The memory pool \a me must be initialized before any events can
+    /// be requested from it. Also, the QMPool::get() function uses internally
+    /// a QF critical section, so you should be careful not to call it from
+    /// within a critical section when nesting of critical section is not
+    /// supported.
+    ///
+    /// \sa QMPool::put()
+    void *get(void);
+
+    /// \brief Returns a memory block back to a memory pool.
+    ///
+    ///
+    /// This function can be called from any task level or ISR level.
+    ///
+    /// \note The block must be allocated from the same memory pool to which
+    /// it is returned. The QMPool::put() function raises an assertion if the
+    /// returned pointer to the block points outside of the original memory
+    /// buffer managed by the memory pool. Also, the QMPool::put() function
+    /// uses internally a QF critical section, so you should be careful not
+    /// to call it from within a critical section when nesting of critical
+    /// section is not supported.
+    ///
+    /// \sa QMPool::get()
+    void put(void * const b);
+
+    /// \brief return the fixed block-size of the blocks managed by this pool
+    QMPoolSize getBlockSize(void) const {
+        return m_blockSize;
+    }
+
+private:
+    friend class QF;
+};
+
+QP_END_
+
+/// \brief Memory pool element to allocate correctly aligned storage
+/// for QMPool class.
+///
+#define QF_MPOOL_EL(type_) \
+    struct { void *sto_[((sizeof(type_) - 1U)/sizeof(void*)) + 1U]; }
+
+// "qpset.h" =================================================================
+/// \brief platform-independent priority sets of 8 or 64 elements.
+///
+/// This header file must be included in those QF ports that use the
+/// cooperative multitasking QF scheduler or the QK.
+
+QP_BEGIN_
+
+//////////////////////////////////////////////////////////////////////////////
+// useful lookup tables
+
+/// \brief Lookup table for (log2(n) + 1), where n is the index
+/// into the table.
+///
+/// This lookup delivers the 1-based number of the most significant 1-bit
+/// of a byte.
+///
+/// \note Index range n = 0..255. The first index (n == 0) should never
+/// be used.
+///
+extern uint8_t const Q_ROM Q_ROM_VAR QF_log2Lkup[256];
+
+/// \brief Lookup table for (1 << ((n-1) % 8)), where n is the index
+/// into the table.
+///
+/// \note Index range n = 0..64. The first index (n == 0) should never
+/// be used.
+extern uint8_t const Q_ROM Q_ROM_VAR QF_pwr2Lkup[65];
+
+/// \brief Lookup table for ~(1 << ((n-1) % 8)), where n is the index
+/// into the table.
+///
+/// \note Index range n = 0..64. The first index (n == 0) should never
+/// be used.
+extern uint8_t const Q_ROM Q_ROM_VAR QF_invPwr2Lkup[65];
+
+/// \brief Lookup table for (n-1)/8
+///
+/// \note Index range n = 0..64. The first index (n == 0) should never
+/// be used.
+extern uint8_t const Q_ROM Q_ROM_VAR QF_div8Lkup[65];
+
+
+//////////////////////////////////////////////////////////////////////////////
+/// \brief Priority Set of up to 8 elements for building various schedulers,
+/// but also useful as a general set of up to 8 elements of any kind.
+///
+/// The priority set represents the set of active objects that are ready to
+/// run and need to be considered by scheduling processing. The set is capable
+/// of storing up to 8 priority levels.
+class QPSet8 {
+
+    //////////////////////////////////////////////////////////////////////////
+    /// \brief bimask representing elements of the set
+    uint8_t m_bits;
+
+public:
+
+    /// \brief the function evaluates to TRUE if the set is empty,
+    /// which means that no active objects are ready to run.
+    bool isEmpty(void) const {
+        return (m_bits == static_cast<uint8_t>(0));
+    }
+
+    /// \brief the function evaluates to TRUE if the set has elements,
+    /// which means that some active objects are ready to run.
+    bool notEmpty(void) const {
+        return (m_bits != static_cast<uint8_t>(0));
+    }
+
+    /// \brief the function evaluates to TRUE if the priority set has the
+    /// element \a n.
+    bool hasElement(uint8_t const n) const {
+        return ((m_bits & Q_ROM_BYTE(QF_pwr2Lkup[n]))
+                != static_cast<uint8_t>(0));
+    }
+
+    /// \brief insert element \a n into the set, n = 1..8
+    void insert(uint8_t const n) {
+        m_bits |= Q_ROM_BYTE(QF_pwr2Lkup[n]);
+    }
+
+    /// \brief remove element \a n from the set, n = 1..8
+    void remove(uint8_t const n) {
+        m_bits &= Q_ROM_BYTE(QF_invPwr2Lkup[n]);
+    }
+
+    /// \brief find the maximum element in the set,
+    /// \note returns zero if the set is empty
+    uint8_t findMax(void) const {
+        return Q_ROM_BYTE(QF_log2Lkup[m_bits]);
+    }
+
+    friend class QPSet64;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+/// \brief Priority Set of up to 64 elements for building various schedulers,
+/// but also useful as a general set of up to 64 elements of any kind.
+///
+/// The priority set represents the set of active objects that are ready to
+/// run and need to be considered by scheduling processing. The set is capable
+/// of storing up to 64 priority levels.
+///
+/// The priority set allows to build cooperative multitasking schedulers
+/// to manage up to 64 tasks. It is also used in the Quantum Kernel (QK)
+/// preemptive scheduler.
+///
+/// The inherited 8-bit set is used as the 8-elemtn set of of 8-bit subsets
+/// Each bit in the super.bits set represents a subset (8-elements)
+/// as follows: \n
+/// bit 0 in this->m_bits is 1 when subset[0] is not empty \n
+/// bit 1 in this->m_bits is 1 when subset[1] is not empty \n
+/// bit 2 in this->m_bits is 1 when subset[2] is not empty \n
+/// bit 3 in this->m_bits is 1 when subset[3] is not empty \n
+/// bit 4 in this->m_bits is 1 when subset[4] is not empty \n
+/// bit 5 in this->m_bits is 1 when subset[5] is not empty \n
+/// bit 6 in this->m_bits is 1 when subset[6] is not empty \n
+/// bit 7 in this->m_bits is 1 when subset[7] is not empty \n
+class QPSet64 {
+
+    //////////////////////////////////////////////////////////////////////////
+    /// \brief bimask representing 8-element subsets of the set
+    uint8_t m_bytes;
+
+    /// \brief bits representing elements in the set as follows: \n
+    /// m_bits[0] represent elements  1..8  \n
+    /// m_bits[1] represent elements  9..16 \n
+    /// m_bits[2] represent elements 17..24 \n
+    /// m_bits[3] represent elements 25..32 \n
+    /// m_bits[4] represent elements 33..40 \n
+    /// m_bits[5] represent elements 41..48 \n
+    /// m_bits[6] represent elements 49..56 \n
+    /// m_bits[7] represent elements 57..64 \n
+    uint8_t m_bits[8];
+
+public:
+
+    /// \brief the function evaluates to TRUE if the set is empty,
+    /// which means that no active objects are ready to run.
+    bool isEmpty(void) const {
+        return (m_bytes == static_cast<uint8_t>(0));
+    }
+
+    /// \brief the function evaluates to TRUE if the set has elements,
+    /// which means that some active objects are ready to run.
+    bool notEmpty(void) const {
+        return (m_bytes != static_cast<uint8_t>(0));
+    }
+
+    /// \brief the function evaluates to TRUE if the priority set has the
+    /// element \a n.
+    bool hasElement(uint8_t const n) const {
+        uint8_t const m = Q_ROM_BYTE(QF_div8Lkup[n]);
+        return ((m_bits[m] & Q_ROM_BYTE(QF_pwr2Lkup[n]))
+                != static_cast<uint8_t>(0));
+    }
+
+    /// \brief insert element \a n into the set, n = 1..64
+    void insert(uint8_t const n) {
+        uint8_t m = Q_ROM_BYTE(QF_div8Lkup[n]);
+        m_bits[m] |= Q_ROM_BYTE(QF_pwr2Lkup[n]);
+        m_bytes |= Q_ROM_BYTE(QF_pwr2Lkup[m + static_cast<uint8_t>(1)]);
+    }
+
+    /// \brief remove element \a n from the set, n = 1..64
+    void remove(uint8_t const n) {
+        uint8_t m = Q_ROM_BYTE(QF_div8Lkup[n]);
+        if ((m_bits[m] &= Q_ROM_BYTE(QF_invPwr2Lkup[n]))
+             == static_cast<uint8_t>(0))
+        {
+            m_bytes &=Q_ROM_BYTE(QF_invPwr2Lkup[m + static_cast<uint8_t>(1)]);
+        }
+    }
+
+    /// \brief find the maximum element in the set,
+    /// \note returns zero if the set is empty
+    uint8_t findMax(void) const {
+        uint8_t n;
+        if (m_bytes != static_cast<uint8_t>(0)) {
+            n = static_cast<uint8_t>(Q_ROM_BYTE(QF_log2Lkup[m_bytes])
+                                     - static_cast<uint8_t>(1));
+            n = static_cast<uint8_t>(
+                    Q_ROM_BYTE(QF_log2Lkup[m_bits[n]])
+                               + static_cast<uint8_t>(n << 3));
+        }
+        else {
+            n = static_cast<uint8_t>(0);
+        }
+        return n;
+    }
+};
+
+QP_END_
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Kernel selection based on QK_PREEMPTIVE
+//
+#ifdef QK_PREEMPTIVE
+
+// "qk.h" ====================================================================
+/// \brief This macro defines the type of the event queue used for the
+/// active objects.
+///
+/// \note This is just an example of the macro definition. Typically, you need
+/// to define it in the specific QF port file (qf_port.h). In case of QK,
+/// which always depends on the native QF queue, this macro is defined at the
+/// level of the platform-independent interface qk.h.
+#define QF_EQUEUE_TYPE             QEQueue
+
+#if defined(QK_TLS) || defined(QK_EXT_SAVE)
+    /// \brief This macro defines the type of the OS-Object used for blocking
+    /// the native QF event queue when the queue is empty
+    ///
+    /// In QK, the OS object is used to hold the per-thread flags, which might
+    /// be used, for example, to rembember the thread attributes (e.g.,
+    /// if the thread uses a floating point co-processor). The OS object value
+    /// is set on per-thread basis in QActive::start(). Later, the extended
+    /// context switch macros (QK_EXT_SAVE() and QK_EXT_RESTORE()) might use
+    /// the per-thread flags to determine what kind of extended context switch
+    /// this particular thread needs (e.g., the thread might not be using the
+    /// coprocessor or might be using a different one).
+    #define QF_OS_OBJECT_TYPE      uint8_t
+
+    /// \brief This macro defines the type of the thread handle used for the
+    /// active objects.
+    ///
+    /// The thread type in QK is the pointer to the thread-local storage (TLS)
+    /// This thread-local storage can be set on per-thread basis in
+    /// QActive::start(). Later, the QK scheduler, passes the pointer to the
+    /// thread-local storage to the macro #QK_TLS.
+    #define QF_THREAD_TYPE         void *
+#endif                                                // QK_TLS || QK_EXT_SAVE
+
+#if (QF_MAX_ACTIVE <= 8)
+    extern "C" QP_ QPSet8  QK_readySet_;                  ///< ready set of QK
+#else
+    extern "C" QP_ QPSet64 QK_readySet_;                  ///< ready set of QK
+#endif
+
+extern "C" uint8_t QK_currPrio_;          ///< current task/interrupt priority
+extern "C" uint8_t QK_intNest_;                   ///< interrupt nesting level
+
+// QK active object queue implementation .....................................
+
+/// \brief Platform-dependent macro defining how QF should block the calling
+/// task when the QF native queue is empty
+///
+/// \note This is just an example of #QACTIVE_EQUEUE_WAIT_ for the QK-port
+/// of QF. QK never activates a task that has no events to process, so in this
+/// case the macro asserts that the queue is not empty. In other QF ports you
+// need to define the macro appropriately for the underlying kernel/OS you're
+/// using.
+#define QACTIVE_EQUEUE_WAIT_(me_) \
+    Q_ASSERT((me_)->m_eQueue.m_frontEvt != static_cast<QEvt const *>(0))
+
+/// \brief Platform-dependent macro defining how QF should signal the
+/// active object task that an event has just arrived.
+///
+/// The macro is necessary only when the native QF event queue is used.
+/// The signaling of task involves unblocking the task if it is blocked.
+///
+/// \note #QACTIVE_EQUEUE_SIGNAL_ is called from a critical section.
+/// It might leave the critical section internally, but must restore
+/// the critical section before exiting to the caller.
+///
+/// \note This is just an example of #QACTIVE_EQUEUE_SIGNAL_ for the QK-port
+/// of QF. In other QF ports you need to define the macro appropriately for
+/// the underlying kernel/OS you're using.
+#define QACTIVE_EQUEUE_SIGNAL_(me_) do { \
+    QK_readySet_.insert((me_)->m_prio); \
+    if (QK_intNest_ == static_cast<uint8_t>(0)) { \
+        uint8_t p = QK_schedPrio_(); \
+        if (p != static_cast<uint8_t>(0)) { \
+            QK_sched_(p); \
+        } \
+    } \
+} while (false)
+
+/// \brief Platform-dependent macro defining the action QF should take
+/// when the native QF event queue becomes empty.
+///
+/// \note #QACTIVE_EQUEUE_ONEMPTY_ is called from a critical section.
+/// It should not leave the critical section.
+///
+/// \note This is just an example of #QACTIVE_EQUEUE_ONEMPTY_ for the QK-port
+/// of QF. In other QF ports you need to define the macro appropriately for
+/// the underlying kernel/OS you're using.
+#define QACTIVE_EQUEUE_ONEMPTY_(me_) \
+    QK_readySet_.remove((me_)->m_prio)
+
+// QK event pool operations ..................................................
+
+/// \brief This macro defines the type of the event pool used in this QF port.
+///
+/// \note This is a specific implementation for the QK-port of QF.
+/// In other QF ports you need to define the macro appropriately for
+/// the underlying kernel/OS you're using.
+#define QF_EPOOL_TYPE_              QMPool
+
+/// \brief Platform-dependent macro defining the event pool initialization
+///
+/// \note This is a specific implementation for the QK-port of QF.
+/// In other QF ports you need to define the macro appropriately for
+/// the underlying kernel/OS you're using.
+#define QF_EPOOL_INIT_(p_, poolSto_, poolSize_, evtSize_) \
+    (p_).init((poolSto_), (poolSize_), \
+        static_cast<QMPoolSize>(evtSize_))
+
+/// \brief Platform-dependent macro defining how QF should obtain the
+/// event pool block-size
+///
+/// \note This is a specific implementation for the QK-port of QF.
+/// In other QF ports you need to define the macro appropriately for
+/// the underlying kernel/OS you're using.
+#define QF_EPOOL_EVENT_SIZE_(p_)    \
+    static_cast<uint32_t>((p_).getBlockSize())
+
+/// \brief Platform-dependent macro defining how QF should obtain an event
+/// \a e_ from the event pool \a p_
+///
+/// \note This is a specific implementation for the QK-port of QF.
+/// In other QF ports you need to define the macro appropriately for
+/// the underlying kernel/OS you're using.
+#define QF_EPOOL_GET_(p_, e_)       ((e_) = static_cast<QEvt *>((p_).get()))
+
+/// \brief Platform-dependent macro defining how QF should return an event
+/// \a e_ to the event pool \a p_
+///
+/// \note This is a specific implementation for the QK-port of QF.
+/// In other QF ports you need to define the macro appropriately for
+/// the underlying kernel/OS you're using.
+#define QF_EPOOL_PUT_(p_, e_)       ((p_).put(e_))
+
+//////////////////////////////////////////////////////////////////////////////
+QP_BEGIN_
+
+#ifndef QK_NO_MUTEX
+    //////////////////////////////////////////////////////////////////////////
+    /// \brief QK Mutex type.
+    ///
+    /// QMutex represents the priority-ceiling mutex available in QK.
+    /// \sa QK::mutexLock()
+    /// \sa QK::mutexUnlock()
+    typedef uint8_t QMutex;
+#endif                                                          // QK_NO_MUTEX
+
+//////////////////////////////////////////////////////////////////////////////
+/// \brief QK services.
+///
+/// This class groups together QK services. It has only static members and
+/// should not be instantiated.
+///
+// \note The QK scheduler, QK priority, QK ready set, etc. belong conceptually
+/// to the QK class (as static class members). However, to avoid C++ potential
+/// name-mangling problems in assembly language, these elements are defined
+/// outside of the QK class and use the extern "C" linkage specification.
+///
+class QK {
+public:
+
+    /// \brief get the current QK version number string
+    ///
+    /// \return version of the QK as a constant 6-character string of the
+    /// form x.y.zz, where x is a 1-digit major version number, y is a
+    /// 1-digit minor version number, and zz is a 2-digit release number.
+    static char_t const Q_ROM * Q_ROM_VAR getVersion(void);
+
+    /// \brief QK idle callback (customized in BSPs for QK)
+    ///
+    /// QK::onIdle() is called continously by the QK idle loop. This callback
+    /// gives the application an opportunity to enter a power-saving CPU mode,
+    /// or perform some other idle processing.
+    ///
+    /// \note QK::onIdle() is invoked with interrupts unlocked and must also
+    /// return with interrupts unlocked.
+    ///
+    /// \sa QF::onIdle()
+    static void onIdle(void);
+
+#ifndef QK_NO_MUTEX
+
+    /// \brief QK priority-ceiling mutex lock
+    ///
+    /// Lock the QK scheduler up to the priority level \a prioCeiling.
+    ///
+    // \note This function should be always paired with QK::mutexUnlock().
+    /// The code between QK::mutexLock() and QK::mutexUnlock() should be
+    /// kept to the minimum.
+    ///
+    /// \include qk_mux.cpp
+    static QMutex mutexLock(uint8_t const prioCeiling);
+
+    /// \brief QK priority-ceiling mutex unlock
+    ///
+    /// \note This function should be always paired with QK::mutexLock().
+    /// The code between QK::mutexLock() and QK::mutexUnlock() should be
+    /// kept to the minimum.
+    ///
+    /// \include qk_mux.cpp
+    static void mutexUnlock(QMutex const mutex);
+
+#endif                                                          // QK_NO_MUTEX
+
+};
+
+QP_END_
+
+//////////////////////////////////////////////////////////////////////////////
+extern "C" {
+
+/// \brief QK initialization
+///
+/// QK_init() is called from QF_init() in qk.cpp. This function is
+/// defined in the QK ports.
+void QK_init(void);
+
+/// \brief The QK scheduler
+///
+/// \note The QK scheduler must be always called with the interrupts
+/// disabled and enables interrupts internally.
+///
+/// \sa QK_schedPrio_()
+void QK_sched_(uint8_t p);
+
+/// \brief The QK extended scheduler for interrupt context
+///
+/// \note The QK extended exscheduler must be always called with the
+/// interrupts disabled and enables interrupts internally.
+///
+/// \sa QK_schedPrio_()
+void QK_schedExt_(uint8_t p);
+
+/// \brief Find the highest-priority task ready to run
+///
+/// \note QK_schedPrio_() must be always called with interrupts disabled
+/// and returns with interrupts disabled.
+uint8_t QK_schedPrio_(void);
+
+}                                                                // extern "C"
+
+#else                                                         // QK_PREEMPTIVE
+
+// "qvanilla.h" ==============================================================
+/// \brief platform-independent interface to the cooperative "vanilla" kernel.
+
+QP_BEGIN_
+                              // the event queue type for the "Vanilla" kernel
+#define QF_EQUEUE_TYPE     QEQueue
+                                              // native event queue operations
+#define QACTIVE_EQUEUE_WAIT_(me_) \
+    Q_ASSERT((me_)->m_eQueue.m_frontEvt != static_cast<QEvt const *>(0))
+
+#define QACTIVE_EQUEUE_SIGNAL_(me_) \
+    (QF_readySet_.insert((me_)->m_prio))
+
+#define QACTIVE_EQUEUE_ONEMPTY_(me_) \
+    (QF_readySet_.remove((me_)->m_prio))
+
+                                            // native QF event pool operations
+#define QF_EPOOL_TYPE_           QMPool
+#define QF_EPOOL_INIT_(p_, poolSto_, poolSize_, evtSize_) \
+    (p_).init((poolSto_), (poolSize_), static_cast<QMPoolSize>(evtSize_))
+#define QF_EPOOL_EVENT_SIZE_(p_) \
+    static_cast<uint32_t>((p_).getBlockSize())
+#define QF_EPOOL_GET_(p_, e_)    ((e_) = static_cast<QEvt *>((p_).get()))
+#define QF_EPOOL_PUT_(p_, e_)    ((p_).put(e_))
+
+QP_END_
+
+#if (QF_MAX_ACTIVE <= 8)
+    extern "C" QP_ QPSet8  QF_readySet_;      ///< ready set of active objects
+#else
+    extern "C" QP_ QPSet64 QF_readySet_;      ///< ready set of active objects
+#endif
+
+extern "C" uint8_t QF_currPrio_;          ///< current task/interrupt priority
+extern "C" uint8_t QF_intNest_;                   ///< interrupt nesting level
+
+#endif                                                        // QK_PREEMPTIVE
+
+
+// qf.h (QF platform-independent public interface) ===========================
+
+/// \brief QF/C++ platform-independent public interface.
+///
+/// This header file must be included directly or indirectly
+/// in all modules (*.cpp files) that use QF/C++.
+
+//////////////////////////////////////////////////////////////////////////////
+#ifdef Q_EVT_CTOR
+#include <new>                                            // for placement new
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+// apply defaults for all undefined configuration parameters
+//
+#ifndef QF_EVENT_SIZ_SIZE
+    /// \brief Default value of the macro configurable value in qf_port.h
+    #define QF_EVENT_SIZ_SIZE    2
+#endif
+
+#ifndef QF_MAX_EPOOL
+    /// \brief Default value of the macro configurable value in qf_port.h
+    #define QF_MAX_EPOOL         3
+#endif
+
+#ifndef QF_TIMEEVT_CTR_SIZE
+    /// \brief macro to override the default QTimeEvtCtr size.
+    /// Valid values 1, 2, or 4; default 2
+    #define QF_TIMEEVT_CTR_SIZE  2
+#endif
+
+#if (QF_MAX_ACTIVE < 1) || (63 < QF_MAX_ACTIVE)
+    #error "QF_MAX_ACTIVE not defined or out of range. Valid range is 1..63"
+#endif
+
+#ifndef QF_ACTIVE_SUPER_
+
+    //////////////////////////////////////////////////////////////////////////
+    /// \brief The macro defining the base class for QActive.
+    ///
+    /// By default, the ::QActive class is derived from ::QHsm. However,
+    /// if the macro QF_ACTIVE_SUPER_ is defined, QActive is derived from
+    /// QF_ACTIVE_SUPER_.
+    ///
+    /// Clients might choose, for example, to define QF_ACTIVE_SUPER_ as QFsm
+    /// to avoid the 1-2KB overhead of the hierarchical event processor.
+    ///
+    /// Clients might also choose to define QF_ACTIVE_SUPER_ as their own
+    /// completely customized class that has nothing to do with QHsm or QFsm.
+    /// The QF_ACTIVE_SUPER_ class must provide member functions init() and
+    /// dispatch(), consistent with the signatures of QHsm and QFsm. But
+    /// the implementatin of these functions is completely open.
+    #define QF_ACTIVE_SUPER_  QHsm
+
+    /// \brief The argument of the base class' constructor.
+    #define QF_ACTIVE_STATE_  QStateHandler
+
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+QP_BEGIN_
+
+//////////////////////////////////////////////////////////////////////////////
+#if (QF_EVENT_SIZ_SIZE == 1)
+
+    /// \brief The data type to store the block-size defined based on
+    /// the macro #QF_EVENT_SIZ_SIZE.
+    ///
+    /// The dynamic range of this data type determines the maximum block
+    /// size that can be managed by the pool.
+    typedef uint8_t QEvtSize;
+#elif (QF_EVENT_SIZ_SIZE == 2)
+    typedef uint16_t QEvtSize;
+#elif (QF_EVENT_SIZ_SIZE == 4)
+    typedef uint32_t QEvtSize;
+#else
+    #error "QF_EVENT_SIZ_SIZE defined incorrectly, expected 1, 2, or 4"
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+#if (QF_TIMEEVT_CTR_SIZE == 1)
+    /// \brief type of the Time Event counter, which determines the dynamic
+    /// range of the time delays measured in clock ticks.
+    ///
+    /// This typedef is configurable via the preprocessor switch
+    /// #QF_TIMEEVT_CTR_SIZE. The other possible values of this type are
+    /// as follows: \n
+    /// uint8_t when (QF_TIMEEVT_CTR_SIZE == 1), and \n
+    /// uint32_t when (QF_TIMEEVT_CTR_SIZE == 4).
+    typedef uint8_t QTimeEvtCtr;
+#elif (QF_TIMEEVT_CTR_SIZE == 2)
+    typedef uint16_t QTimeEvtCtr;
+#elif (QF_TIMEEVT_CTR_SIZE == 4)
+    typedef uint32_t QTimeEvtCtr;
+#else
+    #error "QF_TIMEEVT_CTR_SIZE defined incorrectly, expected 1, 2, or 4"
+#endif
+
+class QEQueue;                                          // forward declaration
+
+//////////////////////////////////////////////////////////////////////////////
+/// \brief Base class for derivation of application-level active object
+/// classes.
+///
+/// QActive is the base class for derivation of active objects. Active objects
+/// in QF are encapsulated tasks (each embedding a state machine and an event
+/// queue) that communicate with one another asynchronously by sending and
+/// receiving events. Within an active object, events are processed
+/// sequentially in a run-to-completion (RTC) fashion, while QF encapsulates
+/// all the details of thread-safe event exchange and queuing.
+///
+/// \note QActive is not intended to be instantiated directly, but rather
+/// serves as the base class for derivation of active objects in the
+/// application code.
+///
+/// The following example illustrates how to derive an active object from
+/// QActive.
+/// \include qf_qactive.cpp
+///
+/// \sa #QF_ACTIVE_SUPER_ defines the base class for QActive
+class QActive : public QF_ACTIVE_SUPER_ {
+
+#ifdef QF_EQUEUE_TYPE
+    /// \brief OS-dependent event-queue type.
+    ///
+    /// The type of the queue depends on the underlying operating system or
+    /// a kernel. Many kernels support "message queues" that can be adapted
+    /// to deliver QF events to the active object. Alternatively, QF provides
+    /// a native event queue implementation that can be used as well.
+    ///
+    /// The native QF event queue is configured by defining the macro
+    /// #QF_EQUEUE_TYPE as ::QEQueue.
+    QF_EQUEUE_TYPE m_eQueue;
+#endif
+
+#ifdef QF_OS_OBJECT_TYPE
+    /// \brief OS-dependent per-thread object.
+    ///
+    /// This data might be used in various ways, depending on the QF port.
+    /// In some ports m_osObject is used to block the calling thread when
+    /// the native QF queue is empty. In other QF ports the OS-dependent
+    /// object might be used differently.
+    QF_OS_OBJECT_TYPE m_osObject;
+#endif
+
+#ifdef QF_THREAD_TYPE
+    /// \brief OS-dependent representation of the thread of the active
+    /// object.
+    ///
+    /// This data might be used in various ways, depending on the QF port.
+    /// In some ports m_thread is used store the thread handle. In other ports
+    /// m_thread can be a pointer to the Thread-Local-Storage (TLS).
+    QF_THREAD_TYPE m_thread;
+#endif
+
+    /// \brief QF priority associated with the active object.
+    /// \sa QActive::start()
+    uint8_t m_prio;
+
+public:
+    /// \brief Starts execution of an active object and registers the object
+    /// with the framework.
+    ///
+    /// The function takes six arguments.
+    /// \a prio is the priority of the active object. QF allows you to start
+    /// up to 63 active objects, each one having a unique priority number
+    /// between 1 and 63 inclusive, where higher numerical values correspond
+    /// to higher priority (urgency) of the active object relative to the
+    /// others.
+    /// \a qSto[] and \a qLen arguments are the storage and size of the event
+    /// queue used by this active object.
+    /// \a stkSto and \a stkSize are the stack storage and size in bytes.
+    /// Please note that a per-active object stack is used only when the
+    /// underlying OS requies it. If the stack is not required, or the
+    /// underlying OS allocates the stack internally, the \a stkSto should be
+    /// NULL and/or \a stkSize should be 0.
+    /// \a ie is an optional initialization event that can be used to pass
+    /// additional startup data to the active object. (Pass NULL if your
+    /// active object does not expect the initialization event).
+    ///
+    /// \note This function is strongly OS-dependent and must be defined in
+    /// the QF port to a particular platform.
+    ///
+    /// The following example shows starting of the Philosopher object when a
+    /// per-task stack is required:
+    /// \include qf_start.cpp
+    void start(uint8_t const prio,
+               QEvt const *qSto[], uint32_t const qLen,
+               void * const stkSto, uint32_t const stkSize,
+               QEvt const * const ie = static_cast<QEvt *>(0));
+
+    /// \brief Posts an event \a e directly to the event queue of the acitve
+    /// object \a me using the First-In-First-Out (FIFO) policy.
+    ///
+    /// Direct event posting is the simplest asynchronous communication method
+    /// available in QF. The following example illustrates how the Philosopher
+    /// active obejct posts directly the HUNGRY event to the Table active
+    /// object. \include qf_post.cpp
+    ///
+    /// \note The producer of the event (Philosopher in this case) must only
+    /// "know" the recipient (Table) by a generic (QActive *QDPP_table)
+    /// pointer, but the specific definition of the Table class is not
+    /// required.
+    ///
+    /// \note Direct event posting should not be confused with direct event
+    /// dispatching. In contrast to asynchronous event posting through event
+    /// queues, direct event dispatching is synchronous. Direct event
+    /// dispatching occurs when you call QHsm::dispatch(), or QFsm::dispatch()
+    /// function.
+#ifndef Q_SPY
+    void postFIFO(QEvt const * const e);
+#else
+    void postFIFO(QEvt const * const e, void const * const sender);
+#endif
+
+    /// \brief Un-subscribes from the delivery of all signals to the active
+    /// object.
+    ///
+    /// This function is part of the Publish-Subscribe event delivery
+    /// mechanism available in QF. Un-subscribing from all events means that
+    /// the framework will stop posting any published events to the event
+    /// queue of the active object.
+    ///
+    /// \note Due to the latency of event queues, an active object should NOT
+    /// assume that no events will ever be dispatched to the state machine of
+    /// the active object after un-subscribing from all events.
+    /// The events might be already in the queue, or just about to be posted
+    /// and the un-subscribe operation will not flush such events. Also, the
+    /// alternative event-delivery mechanisms, such as direct event posting or
+    /// time events, can be still delivered to the event queue of the active
+    /// object.
+    ///
+    /// \sa QF::publish(), QActive::subscribe(), and QActive::unsubscribe()
+    void unsubscribeAll(void) const;
+
+protected:
+    /// \brief protected constructor
+    ///
+    /// Performs the first step of active object initialization by assigning
+    /// the initial pseudostate to the currently active state of the state
+    /// machine.
+    ///
+    /// \note The constructor is protected to prevent direct instantiation
+    /// of QActive objects. This class is intended only for derivation
+    /// (abstract class).
+    QActive(QF_ACTIVE_STATE_ const initial) : QF_ACTIVE_SUPER_(initial) {
+    }
+
+    /// \brief Posts an event directly to the event queue of the active object
+    /// \a me using the Last-In-First-Out (LIFO) policy.
+    ///
+    /// \note The LIFO policy should be used only for self-posting and with
+    /// great caution because it alters order of events in the queue.
+    ///
+    /// \sa QActive::postFIFO()
+    void postLIFO(QEvt const * const e);
+
+    /// \brief Stops execution of an active object and removes it from the
+    /// framework's supervision.
+    ///
+    /// The preferred way of calling this function is from within the active
+    /// object that needs to stop (that's why this function is protected).
+    /// In other words, an active object should stop itself rather than being
+    /// stopped by some other entity. This policy works best, because only
+    /// the active object itself "knows" when it has reached the appropriate
+    /// state for the shutdown.
+    ///
+    /// \note This function is strongly OS-dependent and should be defined in
+    /// the QF port to a particular platform. This function is optional in
+    /// embedded systems where active objects never need to be stopped.
+    void stop(void);
+
+    /// \brief Subscribes for delivery of signal \a sig to the active object
+    ///
+    /// This function is part of the Publish-Subscribe event delivery
+    /// mechanism available in QF. Subscribing to an event means that the
+    /// framework will start posting all published events with a given signal
+    /// \a sig to the event queue of the active object.
+    ///
+    /// The following example shows how the Table active object subscribes
+    /// to three signals in the initial transition:
+    /// \include qf_subscribe.cpp
+    ///
+    /// \sa QF::publish(), QActive::unsubscribe(), and
+    /// QActive::unsubscribeAll()
+    void subscribe(enum_t const sig) const;
+
+    /// \brief Un-subscribes from the delivery of signal \a sig to the
+    /// active object.
+    ///
+    /// This function is part of the Publish-Subscribe event delivery
+    /// mechanism available in QF. Un-subscribing from an event means that
+    /// the framework will stop posting published events with a given signal
+    /// \a sig to the event queue of the active object.
+    ///
+    /// \note Due to the latency of event queues, an active object should NOT
+    /// assume that a given signal \a sig will never be dispatched to the
+    /// state machine of the active object after un-subscribing from that
+    /// signal. The event might be already in the queue, or just about to be
+    /// posted and the un-subscribe operation will not flush such events.
+    ///
+    /// \note Un-subscribing from a signal that has never been subscribed in
+    /// the first place is considered an error and QF will rise an assertion.
+    ///
+    /// \sa QF::publish(), QActive::subscribe(), and QActive::unsubscribeAll()
+    void unsubscribe(enum_t const sig) const;
+
+    /// \brief Defer an event to a given separate event queue.
+    ///
+    /// This function is part of the event deferral support. An active object
+    /// uses this function to defer an event \a e to the QF-supported native
+    /// event queue \a eq. QF correctly accounts for another outstanding
+    /// reference to the event and will not recycle the event at the end of
+    /// the RTC step. Later, the active object might recall one event at a
+    /// time from the event queue.
+    ///
+    /// An active object can use multiple event queues to defer events of
+    /// different kinds.
+    ///
+    /// \sa QActive::recall(), QEQueue
+    void defer(QEQueue * const eq, QEvt const * const e) const;
+
+    /// \brief Recall a deferred event from a given event queue.
+    ///
+    /// This function is part of the event deferral support. An active object
+    /// uses this function to recall a deferred event from a given QF
+    /// event queue. Recalling an event means that it is removed from the
+    /// deferred event queue \a eq and posted (LIFO) to the event queue of
+    /// the active object.
+    ///
+    /// QActive::recall() returns true if an event has been recalled.
+    /// Otherwise the function returns false.
+    ///
+    /// An active object can use multiple event queues to defer events of
+    /// different kinds.
+    ///
+    /// \sa QActive::defer(), QEQueue, QActive::postLIFO()
+    bool recall(QEQueue * const eq);
+
+private:
+
+    /// \brief Get an event from the event queue of an active object.
+    ///
+    /// This function is used internally by a QF port to extract events from
+    /// the event queue of an active object. This function depends on the
+    /// event queue implementation and is sometimes implemented in the QF port
+    /// (qf_port.cpp file). Depending on the underlying OS or kernel, the
+    /// function might block the calling thread when no events are available.
+    ///
+    /// \note QActive::get_() is public because it often needs to be called
+    /// from thread-run routines with difficult to foresee signature (so
+    /// declaring friendship with such function(s) is not possible.)
+    ///
+    /// \sa QActive::postFIFO(), QActive::postLIFO()
+    QEvt const *get_(void);
+
+    friend class QF;
+    friend class QTimeEvt;
+
+#ifdef QK_PREEMPTIVE                                       // is this QK port?
+    friend void ::QK_schedExt_(uint8_t p);
+    friend void ::QK_sched_(uint8_t p);
+#endif
+
+};
+
+//////////////////////////////////////////////////////////////////////////////
+/// \brief Time Event class
+///
+/// Time events are special QF events equipped with the notion of time
+/// passage. The basic usage model of the time events is as follows. An
+/// active object allocates one or more QTimeEvt objects (provides the
+/// storage for them). When the active object needs to arrange for a timeout,
+/// it arms one of its time events to fire either just once (one-shot) or
+/// periodically. Each time event times out independently from the others,
+/// so a QF application can make multiple parallel timeout requests (from the
+/// same or different active objects). When QF detects that the appropriate
+/// moment has arrived, it inserts the time event directly into the
+/// recipient's event queue. The recipient then processes the time event just
+/// like any other event.
+///
+/// Time events, as any other QF events derive from the ::QEvt base
+/// class. Typically, you will use a time event as-is, but you can also
+/// further derive more specialized time events from it by adding some more
+/// data members and/or specialized functions that operate on the specialized
+/// time events.
+///
+/// Internally, the armed time events are organized into a bi-directional
+/// linked list. This linked list is scanned in every invocation of the
+/// QF::tick() function. Only armed (timing out) time events are in the list,
+/// so only armed time events consume CPU cycles.
+///
+/// \note QF manages the time events in the function QF::tick(), which
+/// must be called periodically, preferably from the clock tick ISR.
+/// \note In this version of QF QTimeEvt objects should be allocated
+/// statically rather than dynamically from event pools. Currently, QF will
+/// not correctly recycle the dynamically allocated Time Events.
+class QTimeEvt : public QEvt {
+private:
+
+    /// link to the next time event in the list
+    QTimeEvt *m_next;
+
+    /// the active object that receives the time events.
+    QActive *m_act;
+
+    /// the internal down-counter of the time event. The down-counter
+    /// is decremented by 1 in every QF_tick() invocation. The time event
+    /// fires (gets posted or published) when the down-counter reaches zero.
+    QTimeEvtCtr m_ctr;
+
+    /// the interval for the periodic time event (zero for the one-shot
+    /// time event). The value of the interval is re-loaded to the internal
+    /// down-counter when the time event expires, so that the time event
+    /// keeps timing out periodically.
+    QTimeEvtCtr m_interval;
+
+public:
+
+    /// \brief The Time Event constructor.
+    ///
+    /// The most important initialization performed in  the constructor is
+    /// assigning a signal to the Time Event. You can reuse the Time Event
+    /// any number of times, but you cannot change the signal.
+    /// This is because pointers to Time Events might still be held in event
+    /// queues and changing signal could to hard-to-detect errors.
+    ///
+    /// The following example shows the use of QTimeEvt::QTimeEvt()
+    /// constructor in the constructor initializer list of the Philosopher
+    /// active object constructor that owns the time event
+    /// \include qf_ctor.cpp
+    QTimeEvt(enum_t const s);
+
+    /// \brief Arm a one-shot time event for direct event posting.
+    ///
+    /// Arms a time event to fire in \a nTicks clock ticks (one-shot time
+    /// event). The time event gets directly posted (using the FIFO policy)
+    /// into the event queue of the active object \a act.
+    ///
+    /// After posting, the time event gets automatically disarmed and can be
+    /// reused for a one-shot or periodic timeout requests.
+    ///
+    /// A one-shot time event can be disarmed at any time by calling the
+    /// QTimeEvt::disarm() function. Also, a one-shot time event can be
+    /// re-armed to fire in a different number of clock ticks by calling the
+    /// QTimeEvt::rearm() function.
+    ///
+    /// The following example shows how to arm a one-shot time event from a
+    /// state machine of an active object:
+    /// \include qf_state.cpp
+    void postIn(QActive * const act, QTimeEvtCtr const nTicks) {
+        m_interval = static_cast<QTimeEvtCtr>(0);
+        arm_(act, nTicks);
+    }
+
+    /// \brief Arm a periodic time event for direct event posting.
+    ///
+    /// Arms a time event to fire every \a nTicks clock ticks (periodic time
+    /// event). The time event gets directly posted (using the FIFO policy)
+    /// into the event queue of the active object \a act.
+    ///
+    /// After posting, the time event gets automatically re-armed to fire
+    /// again in the specified \a nTicks clock ticks.
+    ///
+    /// A periodic time event can be disarmed only by calling the
+    /// QTimeEvt::disarm() function. After disarming, the time event can be
+    /// reused for a one-shot or periodic timeout requests.
+    ///
+    /// \note An attempt to reuse (arm again) a running periodic time event
+    /// raises an assertion.
+    ///
+    /// Also, a periodic time event can be re-armed to shorten or extend the
+    /// current period by calling the QTimeEvt_rearm() function. After
+    /// adjusting the current period, the periodic time event goes back
+    /// timing out at the original rate.
+    void postEvery(QActive * const act, QTimeEvtCtr const nTicks) {
+        m_interval = nTicks;
+        arm_(act, nTicks);
+    }
+
+    /// \brief Disarm a time event.
+    ///
+    /// The time event gets disarmed and can be reused. The function
+    /// returns true if the time event was truly disarmed, that is, it
+    /// was running. The return of false means that the time event was
+    /// not truly disarmed because it was not running. The 'false' return is
+    /// only possible for one-shot time events that have been automatically
+    /// disarmed upon expiration. In this case the 'false' return means that
+    /// the time event has already been posted or published and should be
+    /// expected in the active object's state machine.
+    bool disarm(void);
+
+    /// \brief Rearm a time event.
+    ///
+    /// The time event gets rearmed with a new number of clock ticks
+    /// \a nTicks. This facility can be used to prevent a one-shot time event
+    /// from expiring (e.g., a watchdog time event), or to adjusts the
+    /// current period of a periodic time event. Rearming a periodic timer
+    /// leaves the interval unchanged and is a convenient method to adjust
+    /// the phasing of the periodic time event.
+    ///
+    /// The function returns true if the time event was running as it
+    /// was re-armed. The return of false means that the time event was
+    /// not truly rearmed because it was not running. The 'false' return is
+    /// only possible for one-shot time events that have been automatically
+    /// disarmed upon expiration. In this case the 'false' return means that
+    /// the time event has already been posted or published and should be
+    /// expected in the active object's state machine.
+    bool rearm(QTimeEvtCtr const nTicks);
+
+    /// \brief Get the current value of the down-counter of a time event.
+    ///
+    /// If the time event is armed, the function returns the current value of
+    /// the down-counter of the given time event. If the time event is not
+    /// armed, the function returns 0.
+    ///
+    /// /note The function is thread-safe.
+    QTimeEvtCtr ctr(void) const;
+
+private:
+
+    /// \brief Arm a time event (internal function to be used through macros
+    /// only).
+    ///
+    /// \sa QTimeEvt::postIn(), QTimeEvt::postEvery(),
+    /// \sa QTimeEvt::publishIn(), QTimeEvt::publishEvery()
+    void arm_(QActive * const act, QTimeEvtCtr const nTicks);
+
+    friend class QF;
+};
+
+
+//////////////////////////////////////////////////////////////////////////////
+/// \brief The size of the Subscriber list bit array
+///
+/// The size is determined of the maximum number of active objects in the
+/// application configured by the #QF_MAX_ACTIVE macro.
+uint8_t const QF_SUBSCR_LIST_SIZE =
+    static_cast<uint8_t>(((QF_MAX_ACTIVE - 1) / 8) + 1);
+
+/// \brief Subscriber List class
+///
+/// This data type represents a set of active objects that subscribe to
+/// a given signal. The set is represented as an array of bits, where each
+/// bit corresponds to the unique priority of an active object.
+class QSubscrList {
+private:
+
+    /// An array of bits representing subscriber active objects. Each bit
+    /// in the array corresponds to the unique priority of the active object.
+    /// The size of the array is determined of the maximum number of active
+    /// objects in the application configured by the #QF_MAX_ACTIVE macro.
+    /// For example, an active object of priority p is a subscriber if the
+    /// following is true: ((m_bits[QF_div8Lkup[p]] & QF_pwr2Lkup[p]) != 0)
+    ///
+    /// \sa QF::psInit(), QF_div8Lkup, QF_pwr2Lkup, #QF_MAX_ACTIVE
+    uint8_t m_bits[QF_SUBSCR_LIST_SIZE];
+
+    friend class QF;
+    friend class QActive;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+/// \brief QF services.
+///
+/// This class groups together QF services. It has only static members and
+/// should not be instantiated.
+class QF {
+public:
+
+    /// \brief QF initialization.
+    ///
+    /// This function initializes QF and must be called exactly once before
+    /// any other QF function.
+    static void init(void);
+
+    /// \brief Publish-subscribe initialization.
+    ///
+    /// This function initializes the publish-subscribe facilities of QF and
+    /// must be called exactly once before any subscriptions/publications
+    /// occur in the application. The arguments are as follows: \a subscrSto
+    /// is a pointer to the array of subscriber-lists. \a maxSignal is the
+    /// dimension of this array and at the same time the maximum signal that
+    /// can be published or subscribed.
+    ///
+    /// The array of subscriber-lists is indexed by signals and provides
+    /// mapping between the signals and subscirber-lists. The subscriber-
+    /// lists are bitmasks of type ::QSubscrList, each bit in the bitmask
+    /// corresponding to the unique priority of an active object. The size
+    /// of the ::QSubscrList bitmask depends on the value of the
+    /// #QF_MAX_ACTIVE macro.
+    ///
+    /// \note The publish-subscribe facilities are optional, meaning that
+    /// you might choose not to use publish-subscribe. In that case calling
+    /// QF::psInit() and using up memory for the subscriber-lists is
+    /// unnecessary.
+    ///
+    /// \sa ::QSubscrList
+    ///
+    /// The following example shows the typical initialization sequence of
+    /// QF: \include qf_main.cpp
+    static void psInit(QSubscrList * const subscrSto,
+                       uint32_t const maxSignal);
+
+    /// \brief Event pool initialization for dynamic allocation of events.
+    ///
+    /// This function initializes one event pool at a time and must be called
+    /// exactly once for each event pool before the pool can be used.
+    /// The arguments are as follows: \a poolSto is a pointer to the memory
+    /// block for the events. \a poolSize is the size of the memory block in
+    /// bytes. \a evtSize is the block-size of the pool in bytes, which
+    /// determines the maximum size of events that can be allocated from the
+    /// pool.
+    ///
+    /// You might initialize one, two, and up to three event pools by making
+    /// one, two, or three calls to the QF_poolInit() function. However,
+    /// for the simplicity of the internal implementation, you must initialize
+    /// event pools in the ascending order of the event size.
+    ///
+    /// Many RTOSes provide fixed block-size heaps, a.k.a. memory pools that
+    /// can be used for QF event pools. In case such support is missing, QF
+    /// provides a native QF event pool implementation. The macro
+    /// #QF_EPOOL_TYPE_ determines the type of event pool used by a
+    /// particular QF port. See class ::QMPool for more information.
+    ///
+    /// \note The actual number of events available in the pool might be
+    /// actually less than (\a poolSize / \a evtSize) due to the internal
+    /// alignment of the blocks that the pool might perform. You can always
+    /// check the capacity of the pool by calling QF::getPoolMargin().
+    ///
+    /// \note The dynamic allocation of events is optional, meaning that you
+    /// might choose not to use dynamic events. In that case calling
+    /// QF::poolInit() and using up memory for the memory blocks is
+    /// unnecessary.
+    ///
+    /// \sa QF initialization example for QF::init()
+    static void poolInit(void * const poolSto, uint32_t const poolSize,
+                         uint32_t const evtSize);
+
+    /// \brief Transfers control to QF to run the application.
+    ///
+    /// QF::run() is typically called from your startup code after you
+    /// initialize the QF and start at least one active object with
+    /// QActive::start(). Also, QF::start() call must precede the transfer
+    /// of control to QF::run(), but some QF ports might call QF::start()
+    /// from QF::run(). QF::run() typically never returns to the caller,
+    /// but when it does, it returns the error code (0 for success)
+    ///
+    /// \note This function is strongly platform-dependent and is not
+    /// implemented in the QF, but either in the QF port or in the
+    /// Board Support Package (BSP) for the given application. All QF ports
+    /// must implement QF::run().
+    ///
+    /// \note When the Quantum Kernel (QK) is used as the underlying real-time
+    /// kernel for the QF, all platfrom dependencies are handled in the QK, so
+    /// no porting of QF is necessary. In other words, you only need to
+    /// recompile the QF platform-independent code with the compiler for your
+    /// platform, but you don't need to provide any platform-specific
+    /// implementation (so, no qf_port.cpp file is necessary). Moreover, QK
+    /// implements the function QF::run() in a platform-independent way,
+    /// in the modile qk.cpp.
+    static int16_t run(void);
+
+    /// \brief Startup QF callback.
+    ///
+    /// The timeline for calling QF::onStartup() depends on the particular
+    /// QF port. In most cases, QF::onStartup() is called from QF::run(),
+    /// right before starting any multitasking kernel or the background loop.
+    static void onStartup(void);
+
+    /// \brief Cleanup QF callback.
+    ///
+    /// QF::onCleanup() is called in some QF ports before QF returns to the
+    /// underlying operating system or RTOS.
+    ///
+    /// This function is strongly platform-specific and is not implemented in
+    /// the QF but either in the QF port or in the Board Support Package (BSP)
+    /// for the given application. Some QF ports might not require
+    /// implementing QF::onCleanup() at all, because many embedded
+    /// applications don't have anything to exit to.
+    ///
+    /// \sa QF::init() and QF::stop()
+    static void onCleanup(void);
+
+    /// \brief QF idle callback (customized in BSPs for QF)
+    ///
+    /// QF::onIdle() is called by the non-preemptive "Vanilla" scheduler built
+    /// into QF when the framework detects that no events are available for
+    /// active objects (the idle condition). This callback gives the
+    /// application an opportunity to enter a power-saving CPU mode, or
+    /// perform some other idle processing (such as Q-Spy output).
+    ///
+    /// \note QF_onIdle() is invoked with interrupts DISABLED because the idle
+    /// condition can be asynchronously changed at any time by an interrupt.
+    /// QF_onIdle() MUST enable the interrupts internally, but not before
+    /// putting the CPU into the low-power mode. (Ideally, enabling interrupts
+    /// and low-power mode should happen atomically). At the very least, the
+    /// function MUST enable interrupts, otherwise interrups will remain
+    /// disabled permanently.
+    ///
+    /// \note QF::onIdle() is only used by the non-preemptive "Vanilla"
+    /// scheduler in the "bare metal" QF port, and is NOT used in any other
+    /// QF ports. When QF is combined with QK, the QK idle loop calls a
+    /// different function QK::onIdle(), with different semantics than
+    /// QF::onIdle(). When QF is combined with a 3rd-party RTOS or kernel, the
+    /// idle processing mechanism of the RTOS or kernal is used instead of
+    /// QF::onIdle().
+    ///
+    static void onIdle(void);
+
+    /// \brief Function invoked by the application layer to stop the QF
+    /// application and return control to the OS/Kernel.
+    ///
+    /// This function stops the QF application. After calling this function,
+    /// QF attempts to gracefully stop the  application. This graceful
+    /// shutdown might take some time to complete. The typical use of this
+    /// funcition is for terminating the QF application to return back to the
+    /// operating system or for handling fatal errors that require shutting
+    /// down (and possibly re-setting) the system.
+    ///
+    /// This function is strongly platform-specific and is not implemented in
+    /// the QF but either in the QF port or in the Board Support Package (BSP)
+    /// for the given application. Some QF ports might not require
+    /// implementing QF::stop() at all, because many embedded application
+    /// don't have anything to exit to.
+    ///
+    /// \sa QF::stop() and QF::onCleanup()
+    static void stop(void);
+
+    /// \brief Publish event to the framework.
+    ///
+    /// This function posts (using the FIFO policy) the event \a e it to ALL
+    /// active object that have subscribed to the signal \a e->sig.
+    /// This function is designed to be callable from any part of the system,
+    /// including ISRs, device drivers, and active objects.
+    ///
+    /// In the general case, event publishing requires multi-casting the
+    /// event to multiple subscribers. This happens in the caller's thread
+    /// with the scheduler locked to prevent preemptions during the multi-
+    /// casting process. (Please note that the interrupts are not locked.)
+#ifndef Q_SPY
+    static void publish(QEvt const *e);
+#else
+    static void publish(QEvt const *e, void const *sender);
+#endif
+
+    /// \brief Processes all armed time events at every clock tick.
+    ///
+    /// This function must be called periodically from a time-tick ISR or from
+    /// the highest-priority task so that QF can manage the timeout events.
+    ///
+    /// \note The QF::tick() function is not reentrant meaning that it must
+    /// run to completion before it is called again. Also, QF::tick() assumes
+    /// that it never will get preempted by a task, which is always the case
+    /// when it is called from an ISR or the highest-priority task.
+    ///
+    /// \sa ::QTimeEvt.
+    ///
+    /// The following example illustrates the call to QF::tick():
+    /// \include qf_tick.cpp
+#ifndef Q_SPY
+    static void tick(void);
+#else
+    static void tick(void const * const sender);
+#endif
+
+    /// \brief Returns true if all time events are inactive and false
+    /// any time event is active.
+    ///
+    /// \note This function should be called in critical section.
+    static bool noTimeEvtsActive(void);
+
+    /// \brief Returns the QF version.
+    ///
+    /// This function returns constant version string in the format x.y.zz,
+    /// where x (one digit) is the major version, y (one digit) is the minor
+    /// version, and zz (two digits) is the maintenance release version.
+    /// An example of the version string is "3.1.03".
+    ///
+    /// The following example illustrates the usage of this function:
+    /// \include qf_version.cpp
+    static char_t const Q_ROM * Q_ROM_VAR getVersion(void);
+
+    /// \brief This function returns the margin of the given event pool.
+    ///
+    /// This function returns the margin of the given event pool \a poolId,
+    /// where poolId is the ID of the pool initialized by the call to
+    /// QF::poolInit(). The poolId of the first initialized pool is 1, the
+    /// second 2, and so on.
+    ///
+    /// The returned pool margin is the minimal number of free blocks
+    /// encountered in the given pool since system startup.
+    ///
+    /// \note Requesting the margin of an un-initialized pool raises an
+    /// assertion in the QF.
+    static uint32_t getPoolMargin(uint8_t const poolId);
+
+    /// \brief This function returns the margin of the given event queue.
+    ///
+    /// This function returns the margin of the given event queue of an active
+    /// object with priority \a prio. (QF priorities start with 1 and go up to
+    /// #QF_MAX_ACTIVE.) The margin is the minimal number of free events
+    /// encountered in the given queue since system startup.
+    ///
+    /// \note QF::getQueueMargin() is available only when the native QF event
+    /// queue implementation is used. Requesting the queue margin of an unused
+    /// priority level raises an assertion in the QF. (A priority level
+    /// becomes used in QF after the call to the QF::add_() function.)
+    static uint32_t getQueueMargin(uint8_t const prio);
+
+    /// \brief Internal QF implementation of the dynamic event allocator.
+    ///
+    /// \note The application code should not call this function directly.
+    /// Please use the macro #Q_NEW.
+    static QEvt *new_(QEvtSize const evtSize, enum_t const sig);
+
+    /// \brief Recycle a dynamic event.
+    ///
+    /// This function implements a simple garbage collector for the dynamic
+    /// events. Only dynamic events are candidates for recycling. (A dynamic
+    /// event is one that is allocated from an event pool, which is
+    /// determined as non-zero e->attrQF__ attribute.) Next, the function
+    /// decrements the reference counter of the event, and recycles the event
+    /// only if the counter drops to zero (meaning that no more references
+    /// are outstanding for this event). The dynamic event is recycled by
+    /// returning it to the pool from which it was originally allocated.
+    /// The pool-of-origin information is stored in the upper 2-MSBs of the
+    /// e->attrQF__ attribute.)
+    ///
+    /// \note QF invokes the garbage collector at all appropriate contexts,
+    /// when an event can become garbage (automatic garbage collection),
+    /// so the application code should have NO need to call QF::gc() directly.
+    /// The QF::gc() function is exposed only for special cases when your
+    /// application sends dynamic events to the "raw" thread-safe queues
+    /// (see ::QEQueue). Such queues are processed outside of QF and the
+    /// automatic garbage collection CANNOT be performed for these events.
+    /// In this case you need to call QF::gc() explicitly.
+    static void gc(QEvt const *e);
+
+private:                              // functions to be used in QF ports only
+
+    /// \brief Register an active object to be managed by the framework
+    ///
+    /// This function should not be called by the application directly, only
+    /// through the function QActive::start(). The priority of the active
+    /// object \a a should be set before calling this function.
+    ///
+    /// \note This function raises an assertion if the priority of the active
+    /// object exceeds the maximum value #QF_MAX_ACTIVE. Also, this function
+    /// raises an assertion if the priority of the active object is already in
+    /// use. (QF requires each active object to have a UNIQUE priority.)
+    static void add_(QActive * const a);
+
+public:
+    /// \brief Remove the active object from the framework.
+    ///
+    /// This function should not be called by the application directly, only
+    /// inside the QF port. The priority level occupied by the active object
+    /// is freed-up and can be reused for another active object.
+    ///
+    /// The active object that is removed from the framework can no longer
+    /// participate in the publish-subscribe event exchange.
+    ///
+    /// \note This function raises an assertion if the priority of the active
+    /// object exceeds the maximum value #QF_MAX_ACTIVE or is not used.
+    static void remove_(QActive const * const a);
+
+    /// \brief array of registered active objects
+    ///
+    /// \note Not to be used by Clients directly, only in ports of QF
+    static QActive *active_[];
+
+    /// \brief Thread routine for executing an active object \a act.
+    ///
+    /// This function is actually implemented internally by certain QF ports
+    /// to be called by the active object thread routine.
+    static void thread_(QActive *act);
+
+    friend class QActive;
+};
+
+QP_END_
+
+//////////////////////////////////////////////////////////////////////////////
+#ifdef Q_EVT_CTOR               // Provide the constructor for the QEvt class?
+
+    /// \brief Allocate a dynamic event.
+    ///
+    /// This macro returns an event pointer cast to the type \a evtT_. The
+    /// event is initialized with the signal \a sig. Internally, the macro
+    /// calls the internal QF function QF::new_(), which always returns a
+    /// valid event pointer.
+    ///
+    /// \note The internal QF function QF::new_() raises an assertion when
+    /// the allocation of the event turns out to be impossible due to
+    /// event pool depletion, or incorrect (too big) size of the requested
+    /// event.
+    ///
+    /// The following example illustrates dynamic allocation of an event:
+    /// \include qf_post.cpp
+    #define Q_NEW(evtT_, sig_, ...) \
+        (new(QP_ QF::new_( \
+            static_cast<QP_ QEvtSize>(sizeof(evtT_)), (sig_))) \
+            evtT_((sig_),  ##__VA_ARGS__))
+#else                                    // QEvt is a POD (Plain Old Datatype)
+
+    #define Q_NEW(evtT_, sig_) \
+        (static_cast<evtT_ *>( \
+            QP_ QF::new_(static_cast<QP_ QEvtSize>(sizeof(evtT_)), (sig_))))
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+// QS software tracing integration, only if enabled
+#ifdef Q_SPY                                   // QS software tracing enabled?
+
+    /// \brief Invoke the system clock tick processing QF::tick(). This macro
+    /// is the recommended way of invoking clock tick processing, because it
+    /// provides the vital information for software tracing and avoids any
+    /// overhead when the tracing is disabled.
+    ///
+    /// This macro takes the argument \a sender_, which is a pointer to the
+    /// sender object. This argument is actually only used when QS software
+    /// tracing is enabled (macro #Q_SPY is defined). When QS software
+    /// tracing is disabled, the macro calls QF::tick() without any
+    /// arguments, so the overhead of passing this extra argument is
+    /// entirely avoided.
+    ///
+    /// \note the pointer to the sender object is not necessarily a poiner
+    /// to an active object. In fact, typically QF::TICK() will be called from
+    /// an interrupt, in which case you would create a unique object just to
+    /// unambiguously identify the ISR as the sender of the time events.
+    ///
+    /// \sa QF::tick()
+    #define TICK(sender_)                  tick(sender_)
+
+    /// \brief Invoke the event publishing facility QF::publish(). This macro
+    /// is the recommended way of publishing events, because it provides the
+    /// vital information for software tracing and avoids any overhead when
+    /// the tracing is disabled.
+    ///
+    ///
+    /// This macro takes the last argument \a sender_, which is a pointer to
+    /// the sender object. This argument is actually only used when QS
+    /// tracing is enabled (macro #Q_SPY is defined). When QS software
+    /// tracing is disabled, the macro calls QF::publish() without the
+    /// \a sender_ argument, so the overhead of passing this extra argument
+    /// is entirely avoided.
+    ///
+    /// \note the pointer to the sender object is not necessarily a poiner
+    /// to an active object. In fact, if QF::PUBLISH() is called from an
+    /// interrupt or other context, you can create a unique object just to
+    /// unambiguously identify the publisher of the event.
+    ///
+    /// \sa QF::publish()
+    #define PUBLISH(e_, sender_)           publish((e_), (sender_))
+
+    /// \brief Invoke the direct event posting facility QActive::postFIFO().
+    /// This macro is the recommended way of posting events, because it
+    /// provides the vital information for software tracing and avoids any
+    /// overhead when the tracing is disabled.
+    ///
+    ///
+    /// This macro takes the last argument \a sender_, which is a pointer to
+    /// the sender object. This argument is actually only used when QS
+    /// tracing is disabled (macro #Q_SPY is defined). When QS software
+    /// tracing is not enabled, the macro calls QF_publish() without the
+    /// \a sender_ argument, so the overhead of passing this extra argument
+    /// is entirely avoided.
+    ///
+    /// \note the pointer to the sender object is not necessarily a poiner
+    /// to an active object. In fact, if ao->POST() is called from an
+    /// interrupt or other context, you can create a unique object just to
+    /// unambiguously identify the publisher of the event.
+    ///
+    /// \sa QActive::postFIFO()
+    #define POST(e_, sender_)              postFIFO((e_), (sender_))
+
+#else
+
+    #define TICK(dummy_)                   tick()
+    #define PUBLISH(e_, dummy_)            publish(e_)
+    #define POST(e_, dummy_)               postFIFO(e_)
+
+#endif                                                                // Q_SPY
+
+//////////////////////////////////////////////////////////////////////////////
+// QS software tracing
+#ifdef Q_SPY
+
+// qs.h ======================================================================
+/// \brief QS/C++ platform-independent public interface.
+/// This header file must be included directly or indirectly
+/// in all modules (*.cpp files) that use QS/C++.
+
+#ifndef Q_SPY
+    #error "Q_SPY must be defined to include qs.h"
+#endif
+
+#ifndef Q_ROM                      // provide the default if Q_ROM NOT defined
+    #define Q_ROM
+#endif
+#ifndef Q_ROM_VAR              // provide the default if Q_ROM_VAR NOT defined
+    #define Q_ROM_VAR
+#endif
+#ifndef Q_ROM_BYTE            // provide the default if Q_ROM_BYTE NOT defined
+    #define Q_ROM_BYTE(rom_var_)   (rom_var_)
+#endif
+
+#ifndef QS_TIME_SIZE
+
+    /// \brief The size (in bytes) of the QS time stamp. Valid values: 1, 2,
+    /// or 4; default 4.
+    ///
+    /// This macro can be defined in the QS port file (qs_port.h) to
+    /// configure the ::QSTimeCtr type. Here the macro is not defined so the
+    /// default of 4 byte is chosen.
+    #define QS_TIME_SIZE 4
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+QP_BEGIN_
+
+/// \brief Quantum Spy record types.
+///
+/// The following constants specify the QS record types used in QP components.
+/// You can specify your own record types starting from the ::QS_USER offset.
+/// Currently, the maximum of all records cannot exceed 256.
+/// \sa QS::filterOn()/#QS_FILTER_ON and QS::filterOff()/#QS_FILTER_OFF
+
+enum QSpyRecords {
+    QS_QP_RESET,                 ///< reset the QP (start of a new QS session)
+
+    // QEP records
+    QS_QEP_STATE_ENTRY,                               ///< a state was entered
+    QS_QEP_STATE_EXIT,                                 ///< a state was exited
+    QS_QEP_STATE_INIT,          ///< an intial transition was taken in a state
+    QS_QEP_INIT_TRAN,           ///< the top-most initial transition was taken
+    QS_QEP_INTERN_TRAN,                  ///< an internal transition was taken
+    QS_QEP_TRAN,                           ///< a regular transition was taken
+    QS_QEP_IGNORED,             ///< an event was ignored (silently discarded)
+    QS_QEP_DISPATCH,          ///< an event was dispatched (begin of RTC step)
+    QS_QEP_UNHANDLED,               ///< an event was unhandled due to a guard
+
+    // QF records
+    QS_QF_ACTIVE_ADD,                ///< an AO has been added to QF (started)
+    QS_QF_ACTIVE_REMOVE,         ///< an AO has been removed from QF (stopped)
+    QS_QF_ACTIVE_SUBSCRIBE,                  ///< an AO subscribed to an event
+    QS_QF_ACTIVE_UNSUBSCRIBE,              ///< an AO unsubscribed to an event
+    QS_QF_ACTIVE_POST_FIFO,  ///< an event was posted (FIFO) directly to an AO
+    QS_QF_ACTIVE_POST_LIFO,  ///< an event was posted (LIFO) directly to an AO
+    QS_QF_ACTIVE_GET, ///< an AO got an event and its queue is still not empty
+    QS_QF_ACTIVE_GET_LAST,      ///< an AO got an event and its queue is empty
+    QS_QF_EQUEUE_INIT,                     ///< an event queue was initialized
+    QS_QF_EQUEUE_POST_FIFO,     ///< an event was posted (FIFO) to a raw queue
+    QS_QF_EQUEUE_POST_LIFO,     ///< an event was posted (LIFO) to a raw queue
+    QS_QF_EQUEUE_GET,              ///< get an event and queue still not empty
+    QS_QF_EQUEUE_GET_LAST,              ///< get the last event from the queue
+    QS_QF_MPOOL_INIT,                       ///< a memory pool was initialized
+    QS_QF_MPOOL_GET,        ///< a memory block was removed from a memory pool
+    QS_QF_MPOOL_PUT,         ///< a memory block was returned to a memory pool
+    QS_QF_PUBLISH,       ///< an event was truly published to some subscribers
+    QS_QF_RESERVED8,
+    QS_QF_NEW,                                         ///< new event creation
+    QS_QF_GC_ATTEMPT,                          ///< garbage collection attempt
+    QS_QF_GC,                                          ///< garbage collection
+    QS_QF_TICK,                                     ///< QF::tick() was called
+    QS_QF_TIMEEVT_ARM,                             ///< a time event was armed
+    QS_QF_TIMEEVT_AUTO_DISARM,      ///< a time event expired and was disarmed
+    QS_QF_TIMEEVT_DISARM_ATTEMPT,///< an attempt to disarmed a disarmed tevent
+    QS_QF_TIMEEVT_DISARM,           ///< true disarming of an armed time event
+    QS_QF_TIMEEVT_REARM,                         ///< rearming of a time event
+    QS_QF_TIMEEVT_POST,      ///< a time event posted itself directly to an AO
+    QS_QF_TIMEEVT_CTR,                 ///< a time event counter was requested
+    QS_QF_CRIT_ENTRY,                        ///< critical section was entered
+    QS_QF_CRIT_EXIT,                          ///< critical section was exited
+    QS_QF_ISR_ENTRY,                                   ///< an ISR was entered
+    QS_QF_ISR_EXIT,                                     ///< an ISR was exited
+    QS_QF_INT_DISABLE,                           ///< interrupts were disabled
+    QS_QF_INT_ENABLE,                             ///< interrupts were enabled
+    QS_QF_RESERVED4,
+    QS_QF_RESERVED3,
+    QS_QF_RESERVED2,
+    QS_QF_RESERVED1,
+    QS_QF_RESERVED0,
+
+    // QK records
+    QS_QK_MUTEX_LOCK,                             ///< the QK mutex was locked
+    QS_QK_MUTEX_UNLOCK,                         ///< the QK mutex was unlocked
+    QS_QK_SCHEDULE,      ///< the QK scheduler scheduled a new task to execute
+    QS_QK_RESERVED6,
+    QS_QK_RESERVED5,
+    QS_QK_RESERVED4,
+    QS_QK_RESERVED3,
+    QS_QK_RESERVED2,
+    QS_QK_RESERVED1,
+    QS_QK_RESERVED0,
+
+    // Miscellaneous QS records
+    QS_SIG_DIC,                                   ///< signal dictionary entry
+    QS_OBJ_DIC,                                   ///< object dictionary entry
+    QS_FUN_DIC,                                 ///< function dictionary entry
+    QS_USR_DIC,                           ///< user QS record dictionary entry
+    QS_RESERVED4,
+    QS_RESERVED3,
+    QS_RESERVED2,
+    QS_RESERVED1,
+    QS_RESERVED0,
+    QS_ASSERT,                                ///< assertion fired in the code
+
+    // User records
+    QS_USER                ///< the first record available for user QS records
+};
+
+/// \brief Specification of all QS records for the QS::filterOn() and
+/// QS::filterOff()
+uint8_t const QS_ALL_RECORDS = static_cast<uint8_t>(0xFF);
+
+/// \brief Constant representing End-Of-Data condition returned from the
+/// QS::getByte() function.
+uint16_t const QS_EOD  = static_cast<uint16_t>(0xFFFF);
+
+
+#if (QS_TIME_SIZE == 1)
+    typedef uint8_t QSTimeCtr;
+    #define QS_TIME_()   (QP_ QS::u8_(QP_ QS::onGetTime()))
+#elif (QS_TIME_SIZE == 2)
+    typedef uint16_t QSTimeCtr;
+    #define QS_TIME_()   (QP_ QS::u16_(QP_ QS::onGetTime()))
+#elif (QS_TIME_SIZE == 4)
+
+    /// \brief The type of the QS time stamp
+    ///
+    /// This type determines the dynamic range of QS time stamps
+    typedef uint32_t QSTimeCtr;
+
+    /// \brief Internal macro to output time stamp to the QS record
+    #define QS_TIME_()   (QP_ QS::u32_(QP_ QS::onGetTime()))
+#else
+    #error "QS_TIME_SIZE defined incorrectly, expected 1, 2, or 4"
+#endif
+
+/// \brief Quantum Spy logging facilities
+///
+/// This class groups together QS services. It has only static members and
+/// should not be instantiated.
+class QS {
+public:
+
+    /// \brief Get the current version of QS
+    ///
+    /// \return version of the QS as a constant 6-character string of the form
+    /// x.y.zz, where x is a 1-digit major version number, y is a 1-digit
+    /// minor version number, and zz is a 2-digit release number.
+    static char_t const Q_ROM * Q_ROM_VAR getVersion(void);
+
+    /// \brief Initialize the QS data buffer.
+    ///
+    /// This function should be called from QS_init() to provide QS with the
+    /// data buffer. The first argument \a sto[] is the address of the memory
+    /// block, and the second argument \a stoSize is the size of this block
+    /// in bytes. Currently the size of the QS buffer cannot exceed 64KB.
+    ///
+    /// QS can work with quite small data buffers, but you will start losing
+    /// data if the buffer is too small for the bursts of logging activity.
+    /// The right size of the buffer depends on the data production rate and
+    /// the data output rate. QS offers flexible filtering to reduce the data
+    /// production rate.
+    ///
+    /// \note If the data output rate cannot keep up with the production rate,
+    /// QS will start overwriting the older data with newer data. This is
+    /// consistent with the "last-is-best" QS policy. The record sequence
+    ///  counters and checksums on each record allow to easily detect data
+    /// loss.
+    static void initBuf(uint8_t sto[], uint32_t const stoSize);
+
+    /// \brief Turn the global Filter on for a given record type \a rec.
+    ///
+    /// This function sets up the QS filter to enable the record type \a rec.
+    /// The argument #QS_ALL_RECORDS specifies to filter-on all records.
+    /// This function should be called indirectly through the macro
+    /// #QS_FILTER_ON.
+    ///
+    /// \note Filtering based on the record-type is only the first layer of
+    /// filtering. The second layer is based on the object-type. Both filter
+    /// layers must be enabled for the QS record to be inserted into the QS
+    /// buffer.
+    /// \sa QS_filterOff(), #QS_FILTER_SM_OBJ, #QS_FILTER_AO_OBJ,
+    /// #QS_FILTER_MP_OBJ, #QS_FILTER_EQ_OBJ, and #QS_FILTER_TE_OBJ.
+    static void filterOn(uint8_t const rec);
+
+    /// \brief Turn the global Filter off for a given record type \a rec.
+    ///
+    /// This function sets up the QS filter to disable the record type \a rec.
+    /// The argument #QS_ALL_RECORDS specifies to suppress all records.
+    /// This function should be called indirectly through the macro
+    /// #QS_FILTER_OFF.
+    ///
+    /// \note Filtering records based on the record-type is only the first
+    /// layer of filtering. The second layer is based on the object-type.
+    /// Both filter layers must be enabled for the QS record to be inserted
+    /// into the QS buffer.
+    /// \sa
+    static void filterOff(uint8_t const rec);
+
+    /// \brief Mark the begin of a QS record \a rec
+    ///
+    /// This function must be called at the beginning of each QS record.
+    /// This function should be called indirectly through the macro #QS_BEGIN,
+    /// or #QS_BEGIN_NOCRIT, depending if it's called in a normal code or from
+    /// a critical section.
+    static void begin(uint8_t const rec);
+
+    /// \brief Mark the end of a QS record \a rec
+    ///
+    /// This function must be called at the end of each QS record.
+    /// This function should be called indirectly through the macro #QS_END,
+    /// or #QS_END_NOCRIT, depending if it's called in a normal code or from
+    /// a critical section.
+    static void end(void);
+
+    // unformatted data elements output ......................................
+
+    /// \brief output uint8_t data element without format information
+    /// \note This function is only to be used through macros, never in the
+    /// client code directly.
+    static void u8_(uint8_t const d);
+
+    /// \brief Output uint16_t data element without format information
+    /// \note This function is only to be used through macros, never in the
+    /// client code directly.
+    static void u16_(uint16_t d);
+
+    /// \brief Output uint32_t data element without format information
+    /// \note This function is only to be used through macros, never in the
+    /// client code directly.
+    static void u32_(uint32_t d);
+
+    /// \brief Output zero-terminated ASCII string element without format
+    /// information
+    /// \note This function is only to be used through macros, never in the
+    /// client code directly.
+    static void str_(char_t const *s);
+
+    /// \brief Output zero-terminated ASCII string element  allocated in ROM
+    /// without format information
+    /// \note This function is only to be used through macros, never in the
+    /// client code directly.
+    static void str_ROM_(char_t const Q_ROM * Q_ROM_VAR s);
+
+    // formatted data elements output ........................................
+
+    /// \brief Output uint8_t data element with format information
+    /// \note This function is only to be used through macros, never in the
+    /// client code directly.
+    static void u8(uint8_t const format, uint8_t const d);
+
+    /// \brief output uint16_t data element with format information
+    /// \note This function is only to be used through macros, never in the
+    /// client code directly.
+    static void u16(uint8_t const format, uint16_t d);
+
+    /// \brief Output uint32_t data element with format information
+    /// \note This function is only to be used through macros, never in the
+    /// client code directly.
+    static void u32(uint8_t const format, uint32_t d);
+
+    /// \brief Output 32-bit floating point data element with format
+    /// information
+    /// \note This function is only to be used through macros, never in the
+    /// client code directly.
+    static void f32(uint8_t const format, float32_t const d);
+
+    /// \brief Output 64-bit floating point data element with format
+    /// information
+    /// \note This function is only to be used through macros, never in the
+    /// client code directly.
+    static void f64(uint8_t const format, float64_t const d);
+
+    /// \brief Output zero-terminated ASCII string element with format
+    /// information
+    /// \note This function is only to be used through macros, never in the
+    /// client code directly.
+    static void str(char_t const *s);
+
+    /// \brief Output zero-terminated ASCII string element allocated in ROM
+    /// with format information
+    /// \note This function is only to be used through macros, never in the
+    /// client code directly.
+    static void str_ROM(char_t const Q_ROM * Q_ROM_VAR s);
+
+    /// \brief Output memory block of up to 255-bytes with format information
+    /// \note This function is only to be used through macros, never in the
+    /// client code directly.
+    static void mem(uint8_t const *blk, uint8_t size);
+
+#if (QS_OBJ_PTR_SIZE == 8) || (QS_FUN_PTR_SIZE == 8)
+    /// \brief Output uint64_t data element without format information
+    /// \note This function is only to be used through macros, never in the
+    /// client code directly.
+    static void u64_(uint64_t d);
+
+    /// \brief Output uint64_t data element with format information
+    /// \note This function is only to be used through macros, never in the
+    /// client code directly.
+    static void u64(uint8_t format, uint64_t d);
+#endif
+
+    // QS buffer access ......................................................
+
+    /// \brief Byte-oriented interface to the QS data buffer.
+    ///
+    /// This function delivers one byte at a time from the QS data buffer.
+    /// The function returns the byte in the least-significant 8-bits of the
+    /// 16-bit return value if the byte is available. If no more data is
+    /// available at the time, the function returns QS_EOD (End-Of-Data).
+    ///
+    /// \note QS::getByte() is NOT protected with a critical section.
+    static uint16_t getByte(void);
+
+    /// \brief Block-oriented interface to the QS data buffer.
+    ///
+    /// This function delivers a contiguous block of data from the QS data
+    /// buffer. The function returns the pointer to the beginning of the
+    /// block, and writes the number of bytes in the block to the location
+    /// pointed to by \a pNbytes. The argument \a pNbytes is also used as
+    /// input to provide the maximum size of the data block that the caller
+    /// can accept.
+    ///
+    /// If no bytes are available in the QS buffer when the function is
+    /// called, the function returns a NULL pointer and sets the value
+    /// pointed to by \a pNbytes to zero.
+    ///
+    /// \note Only the NULL return from QS::getBlock() indicates that the QS
+    /// buffer is empty at the time of the call. The non-NULL return often
+    /// means that the block is at the end of the buffer and you need to call
+    /// QS::getBlock() again to obtain the rest of the data that "wrapped
+    /// around" to the beginning of the QS data buffer.
+    ///
+    /// \note QS::getBlock() is NOT protected with a critical section.
+    static uint8_t const *getBlock(uint16_t * const pNbytes);
+
+    //////////////////////////////////////////////////////////////////////////
+    // platform-dependent callback functions to be implemented by clients
+
+    // platform-specific callback functions, need to be implemented by clients
+    /// \brief Callback to startup the QS facility
+    ///
+    /// This is a platform-dependent "callback" function invoked through the
+    /// macro #QS_INIT. You need to implement this function in your
+    /// application. At a minimum, the function must configure the QS buffer
+    /// by calling QS::initBuf(). Typically, you will also want to open/
+    /// configure the QS output channel, such as a serial port, or a file.
+    /// The void* argument \a arg can be used to pass parameter(s) needed to
+    /// configure the output channel.
+    ///
+    /// The function returns true if the QS initialization was successful,
+    /// or false if it failed.
+    ///
+    /// The following example illustrates an implementation of QS_onStartup():
+    /// \include qs_startup.cpp
+    static bool onStartup(void const *arg);
+
+    /// \brief Callback to cleanup the QS facility
+    ///
+    /// This is a platform-dependent "callback" function invoked through the
+    /// macro #QS_EXIT. You need to implement this function in your
+    /// application. The main purpose of this function is to close the QS
+    /// output channel, if necessary.
+    static void onCleanup(void);
+
+    /// \brief Callback to flush the QS trace data to the host
+    ///
+    /// This is a platform-dependent "callback" function to flush the QS
+    /// trace buffer to the host. The function typically busy-waits until all
+    /// the data in the buffer is sent to the host. This is acceptable only
+    /// in the initial transient.
+    static void onFlush(void);
+
+    /// \brief Callback to obtain a timestamp for a QS record.
+    ///
+    /// This is a platform-dependent "callback" function invoked from the
+    /// macro #QS_TIME_ to add the time stamp to the QS record.
+    ///
+    /// \note Some of the pre-defined QS records from QP do not output the
+    /// time stamp. However, ALL user records do output the time stamp.
+    /// \note QS::onGetTime() is called in a critical section and should not
+    /// exit critical section.
+    ///
+    /// The following example shows using a system call to implement QS
+    /// time stamping:
+    /// \include qs_onGetTime.cpp
+    static QSTimeCtr onGetTime(void);
+
+    //////////////////////////////////////////////////////////////////////////
+    // Global and Local QS filters
+    static uint8_t glbFilter_[32];                ///< global on/off QS filter
+    static void const *smObj_;         ///< state machine for QEP local filter
+    static void const *aoObj_;       ///< active object for QF/QK local filter
+    static void const *mpObj_;            ///<  event pool for QF local filter
+    static void const *eqObj_;             ///<  raw queue for QF local filter
+    static void const *teObj_;            ///<  time event for QF local filter
+    static void const *apObj_;///<  generic object Application QF local filter
+
+    //////////////////////////////////////////////////////////////////////////
+    // Miscallaneous
+                                    /// tick counter for the QS_QF_TICK record
+    static QSTimeCtr tickCtr_;
+};
+
+/// \brief Enumerates data formats recognized by QS
+///
+/// QS uses this enumeration is used only internally for the formatted user
+/// data elements.
+enum QSType {
+    QS_I8_T,                                  ///< signed 8-bit integer format
+    QS_U8_T,                                ///< unsigned 8-bit integer format
+    QS_I16_T,                                ///< signed 16-bit integer format
+    QS_U16_T,                              ///< unsigned 16-bit integer format
+    QS_I32_T,                                ///< signed 32-bit integer format
+    QS_U32_T,                              ///< unsigned 32-bit integer format
+    QS_F32_T,                                ///< 32-bit floating point format
+    QS_F64_T,                                ///< 64-bit floating point format
+    QS_STR_T,                         ///< zero-terminated ASCII string format
+    QS_MEM_T,                         ///< up to 255-bytes memory block format
+    QS_SIG_T,                                         ///< event signal format
+    QS_OBJ_T,                                       ///< object pointer format
+    QS_FUN_T,                                     ///< function pointer format
+    QS_I64_T,                                ///< signed 64-bit integer format
+    QS_U64_T,                              ///< unsigned 64-bit integer format
+    QS_U32_HEX_T                    ///< unsigned 32-bit integer in hex format
+};
+
+/// \brief critical section nesting level
+///
+/// \note Not to be used by Clients directly, only in ports of QF
+extern uint8_t QF_critNest_;
+
+QP_END_
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Macros for adding QS instrumentation to the client code
+
+/// \brief Initialize the QS facility.
+///
+/// This macro provides an indirection layer to invoke the QS initialization
+/// routine if #Q_SPY is defined, or do nothing if #Q_SPY is not defined.
+/// \sa QS::onStartup(), example of setting up a QS filter in #QS_FILTER_IN
+#define QS_INIT(arg_)           (QP_ QS::onStartup(arg_))
+
+/// \brief Cleanup the QS facility.
+///
+/// This macro provides an indirection layer to invoke the QS cleanup
+/// routine if #Q_SPY is defined, or do nothing if #Q_SPY is not defined.
+/// \sa QS::onCleanup()
+#define QS_EXIT()               (QP_ QS::onCleanup())
+
+/// \brief Global Filter ON for a given record type \a rec.
+///
+/// This macro provides an indirection layer to call QS::filterOn() if #Q_SPY
+/// is defined, or do nothing if #Q_SPY is not defined.
+///
+/// The following example shows how to use QS filters:
+/// \include qs_filter.cpp
+#define QS_FILTER_ON(rec_)      (QP_ QS::filterOn(static_cast<uint8_t>(rec_)))
+
+/// \brief Global filter OFF for a given record type \a rec.
+///
+/// This macro provides an indirection layer to call QS::filterOff() if #Q_SPY
+/// is defined, or do nothing if #Q_SPY is not defined.
+///
+/// \sa Example of using QS filters in #QS_FILTER_ON documentation
+#define QS_FILTER_OFF(rec_)    (QP_ QS::filterOff(static_cast<uint8_t>(rec_)))
+
+/// \brief Local Filter for a given state machine object \a obj_.
+///
+/// This macro sets up the state machine object local filter if #Q_SPY is
+/// defined, or does nothing if #Q_SPY is not defined. The argument \a obj_
+/// is the pointer to the state machine object that you want to monitor.
+///
+/// The state machine object filter allows you to filter QS records pertaining
+/// only to a given state machine object. With this filter disabled, QS will
+/// output records from all state machines in your application. The object
+/// filter is disabled by setting the state machine pointer to NULL.
+///
+/// The state machine filter affects the following QS records:
+/// ::QS_QEP_STATE_ENTRY, ::QS_QEP_STATE_EXIT, ::QS_QEP_STATE_INIT,
+/// ::QS_QEP_INIT_TRAN, ::QS_QEP_INTERN_TRAN, ::QS_QEP_TRAN,
+/// and ::QS_QEP_IGNORED.
+///
+/// \note Because active objects are state machines at the same time,
+/// the state machine filter (#QS_FILTER_SM_OBJ) pertains to active
+/// objects as well. However, the state machine filter is more general,
+/// because it can be used only for state machines that are not active
+/// objects, such as "Orthogonal Components".
+///
+/// \sa Example of using QS filters in #QS_FILTER_ON documentation
+#define QS_FILTER_SM_OBJ(obj_)  (QP_ QS::smObj_ = (obj_))
+
+/// \brief Local Filter for a given active object \a obj_.
+///
+/// This macro sets up the active object local filter if #Q_SPY is defined,
+/// or does nothing if #Q_SPY is not defined. The argument \a obj_ is the
+/// pointer to the active object that you want to monitor.
+///
+/// The active object filter allows you to filter QS records pertaining
+/// only to a given active object. With this filter disabled, QS will
+/// output records from all active objects in your application. The object
+/// filter is disabled by setting the active object pointer \a obj_ to NULL.
+///
+/// The active object filter affects the following QS records:
+/// ::QS_QF_ACTIVE_ADD, ::QS_QF_ACTIVE_REMOVE, ::QS_QF_ACTIVE_SUBSCRIBE,
+/// ::QS_QF_ACTIVE_UNSUBSCRIBE, ::QS_QF_ACTIVE_POST_FIFO,
+/// ::QS_QF_ACTIVE_POST_LIFO, ::QS_QF_ACTIVE_GET, and ::QS_QF_ACTIVE_GET_LAST.
+///
+/// \sa Example of using QS filters in #QS_FILTER_ON documentation
+#define QS_FILTER_AO_OBJ(obj_)  (QP_ QS::aoObj_ = (obj_))
+
+/// \brief Local Filter for a given memory pool object \a obj_.
+///
+/// This macro sets up the memory pool object local filter if #Q_SPY is
+/// defined, or does nothing if #Q_SPY is not defined. The argument \a obj_
+/// is the pointer to the memory buffer used during the initialization of the
+/// event pool with QF::poolInit().
+///
+/// The memory pool filter allows you to filter QS records pertaining
+/// only to a given memory pool. With this filter disabled, QS will
+/// output records from all memory pools in your application. The object
+/// filter is disabled by setting the memory pool pointer \a obj_ to NULL.
+///
+/// The memory pool filter affects the following QS records:
+/// ::QS_QF_MPOOL_INIT, ::QS_QF_MPOOL_GET, and ::QS_QF_MPOOL_PUT.
+///
+/// \sa Example of using QS filters in #QS_FILTER_ON documentation
+#define QS_FILTER_MP_OBJ(obj_)  (QP_ QS::mpObj_ = (obj_))
+
+/// \brief Filter for a given event queue object \a obj_.
+///
+/// This macro sets up the event queue object filter if #Q_SPY is defined,
+/// or does nothing if #Q_SPY is not defined. The argument \a obj_ is the
+/// pointer to the "raw" thread-safe queue object you want to monitor.
+///
+/// The event queue filter allows you to filter QS records pertaining
+/// only to a given event queue. With this filter disabled, QS will
+/// output records from all event queues in your application. The object
+/// filter is disabled by setting the event queue pointer \a obj_ to NULL.
+///
+/// The event queue filter affects the following QS records:
+/// ::QS_QF_EQUEUE_INIT, ::QS_QF_EQUEUE_POST_FIFO, ::QS_QF_EQUEUE_POST_LIFO,
+/// ::QS_QF_EQUEUE_GET, and ::QS_QF_EQUEUE_GET_LAST.
+///
+/// \sa Example of using QS filters in #QS_FILTER_IN documentation
+#define QS_FILTER_EQ_OBJ(obj_)  (QP_ QS::eqObj_ = (obj_))
+
+/// \brief Local Filter for a given time event object \a obj_.
+///
+/// This macro sets up the time event object local filter if #Q_SPY is
+/// defined, or does nothing if #Q_SPY is not defined. The argument \a obj_
+/// is the pointer to the time event object you want to monitor.
+///
+/// The time event filter allows you to filter QS records pertaining
+/// only to a given time event. With this filter disabled, QS will
+/// output records from all time events in your application. The object
+/// filter is disabled by setting the time event pointer \a obj_ to NULL.
+///
+/// The time event filter affects the following QS records:
+/// ::QS_QF_TIMEEVT_ARM, ::QS_QF_TIMEEVT_AUTO_DISARM,
+/// ::QS_QF_TIMEEVT_DISARM_ATTEMPT, ::QS_QF_TIMEEVT_DISARM,
+/// ::QS_QF_TIMEEVT_REARM, ::QS_QF_TIMEEVT_POST, and ::QS_QF_TIMEEVT_PUBLISH.
+///
+/// \sa Example of using QS filters in #QS_FILTER_ON documentation
+#define QS_FILTER_TE_OBJ(obj_)  (QP_ QS::teObj_ = (obj_))
+
+/// \brief Local Filter for a generic application object \a obj_.
+///
+/// This macro sets up the local application object filter if #Q_SPY is
+/// defined, or does nothing if #Q_SPY is not defined. The argument \a obj_
+/// is the pointer to the application object you want to monitor.
+///
+/// The application object filter allows you to filter QS records pertaining
+/// only to a given application object. With this filter disabled, QS will
+/// output records from all application-records enabled by the global filter.
+/// The local filter is disabled by setting the time event pointer \a obj_
+/// to NULL.
+///
+/// \sa Example of using QS filters in #QS_FILTER_ON documentation
+#define QS_FILTER_AP_OBJ(obj_)  (QP_ QS::apObj_ = (obj_))
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Macros to generate user QS records
+
+#define QS_GLB_FILTER_(rec_) \
+    ((QP_ QS::glbFilter_[static_cast<uint8_t>(rec_) >> 3] \
+      & (static_cast<uint8_t>(1U << (static_cast<uint8_t>(rec_) \
+                                     & static_cast<uint8_t>(7))))) \
+             != static_cast<uint8_t>(0))
+
+/// \brief Begin a QS user record without entering critical section.
+#define QS_BEGIN_NOCRIT(rec_, obj_) \
+    if (QS_GLB_FILTER_(rec_) \
+        && ((QP_ QS::apObj_ == static_cast<void *>(0)) \
+            || (QP_ QS::apObj_ == (obj_)))) \
+    { \
+        QP_ QS::begin(static_cast<uint8_t>(rec_)); \
+        QS_TIME_();
+
+/// \brief End a QS user record without exiting critical section.
+#define QS_END_NOCRIT() \
+    QS_END_NOCRIT_()
+
+                                               // QS-specific critical section
+#ifndef QF_CRIT_STAT_TYPE
+    /// \brief This is an internal macro for defining the critical section
+    /// status type.
+    ///
+    /// The purpose of this macro is to enable writing the same code for the
+    /// case when critical sectgion status type is defined and when it is not.
+    /// If the macro #QF_CRIT_STAT_TYPE is defined, this internal macro
+    /// provides the definition of the critical section status variable.
+    /// Otherwise this macro is empty.
+    /// \sa #QF_CRIT_STAT_TYPE
+    ///
+    #define QS_CRIT_STAT_
+
+    /// \brief This is an internal macro for entering a critical section.
+    ///
+    /// The purpose of this macro is to enable writing the same code for the
+    /// case when critical sectgion status type is defined and when it is not.
+    /// If the macro #QF_CRIT_STAT_TYPE is defined, this internal macro
+    /// invokes #QF_CRIT_ENTRY passing the key variable as the parameter.
+    /// Otherwise #QF_CRIT_ENTRY is invoked with a dummy parameter.
+    /// \sa #QF_CRIT_ENTRY
+    ///
+    #define QS_CRIT_ENTRY_()    QF_CRIT_ENTRY(dummy)
+
+    /// \brief This is an internal macro for exiting a cricial section.
+    ///
+    /// The purpose of this macro is to enable writing the same code for the
+    /// case when critical sectgion status type is defined and when it is not.
+    /// If the macro #QF_CRIT_STAT_TYPE is defined, this internal macro
+    /// invokes #QF_CRIT_EXIT passing the key variable as the parameter.
+    /// Otherwise #QF_CRIT_EXIT is invoked with a dummy parameter.
+    /// \sa #QF_CRIT_EXIT
+    ///
+    #define QS_CRIT_EXIT_()     QF_CRIT_EXIT(dummy)
+
+#else
+    #define QS_CRIT_STAT_       QF_CRIT_STAT_TYPE critStat_;
+    #define QS_CRIT_ENTRY_()    QF_CRIT_ENTRY(critStat_)
+    #define QS_CRIT_EXIT_()     QF_CRIT_EXIT(critStat_)
+#endif
+
+/// \brief Begin a user QS record with entering critical section.
+///
+/// The following example shows how to build a user QS record using the
+/// macros #QS_BEGIN, #QS_END, and the formatted output macros: #QS_U8 and
+/// #QS_STR.
+/// \include qs_user.cpp
+/// \note Must always be used in pair with #QS_END
+#define QS_BEGIN(rec_, obj_) \
+    if (QS_GLB_FILTER_(rec_) \
+        && ((QP_ QS::apObj_ == static_cast<void *>(0)) \
+            || (QP_ QS::apObj_ == (obj_)))) \
+    { \
+        QS_CRIT_STAT_ \
+        QS_CRIT_ENTRY_(); \
+        QP_ QS::begin(static_cast<uint8_t>(rec_)); \
+        QS_TIME_();
+
+/// \brief End a QS record with exiting critical section.
+/// \sa example for #QS_BEGIN
+/// \note Must always be used in pair with #QS_BEGIN
+#define QS_END() \
+    QS_END_()
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Macros for use inside other macros or internally in the QP code
+
+/// \brief Internal QS macro to begin a QS record with entering critical
+/// section.
+/// \note This macro is intended to use only inside QP components and NOT
+/// at the application level. \sa #QS_BEGIN
+#define QS_BEGIN_(rec_, objFilter_, obj_) \
+    if (QS_GLB_FILTER_(rec_) \
+        && (((objFilter_) == static_cast<void *>(0)) \
+            || ((objFilter_) == (obj_)))) \
+    { \
+        QS_CRIT_ENTRY_(); \
+        QP_ QS::begin(static_cast<uint8_t>(rec_));
+
+/// \brief  Internal QS macro to end a QS record with exiting critical
+/// section.
+/// \note This macro is intended to use only inside QP components and NOT
+/// at the application level. \sa #QS_END
+#define QS_END_() \
+        QP_ QS::end(); \
+        QS_CRIT_EXIT_(); \
+    }
+
+/// \brief Internal QS macro to begin a QS record without entering critical
+/// section.
+/// \note This macro is intended to use only inside QP components and NOT
+/// at the application level. \sa #QS_BEGIN_NOCRIT
+#define QS_BEGIN_NOCRIT_(rec_, objFilter_, obj_) \
+    if (QS_GLB_FILTER_(rec_) \
+        && (((objFilter_) == static_cast<void *>(0)) \
+            || ((objFilter_) == (obj_)))) \
+    { \
+        QP_ QS::begin(static_cast<uint8_t>(rec_));
+
+/// \brief Internal QS macro to end a QS record without exiting critical
+/// section.
+/// \note This macro is intended to use only inside QP components and NOT
+/// at the application level. \sa #QS_END_NOCRIT
+#define QS_END_NOCRIT_() \
+        QP_ QS::end(); \
+    }
+
+#if (Q_SIGNAL_SIZE == 1)
+    /// \brief Internal QS macro to output an unformatted event signal
+    /// data element
+    /// \note the size of the pointer depends on the macro #Q_SIGNAL_SIZE.
+    #define QS_SIG_(sig_)    (QP_ QS::u8_(static_cast<uint8_t>(sig_))))
+#elif (Q_SIGNAL_SIZE == 2)
+    #define QS_SIG_(sig_)    (QP_ QS::u16_(static_cast<uint16_t>(sig_)))
+#elif (Q_SIGNAL_SIZE == 4)
+    #define QS_SIG_(sig_)    (QP_ QS::u32_(static_cast<uint32_t>(sig_)))
+#endif
+
+/// \brief Internal QS macro to output an unformatted uint8_t data element
+#define QS_U8_(data_)        (QP_ QS::u8_(data_))
+
+/// \brief Internal QS macro to output an unformatted uint16_t data element
+#define QS_U16_(data_)       (QP_ QS::u16_(data_))
+
+/// \brief Internal QS macro to output an unformatted uint32_t data element
+#define QS_U32_(data_)       (QP_ QS::u32_(data_))
+
+
+#if (QS_OBJ_PTR_SIZE == 1)
+    #define QS_OBJ_(obj_)    (QP_ QS::u8_(reinterpret_cast<uint8_t>(obj_)))
+#elif (QS_OBJ_PTR_SIZE == 2)
+    #define QS_OBJ_(obj_)    (QP_ QS::u16_(reinterpret_cast<uint16_t>(obj_)))
+#elif (QS_OBJ_PTR_SIZE == 4)
+    #define QS_OBJ_(obj_)    (QP_ QS::u32_(reinterpret_cast<uint32_t>(obj_)))
+#elif (QS_OBJ_PTR_SIZE == 8)
+    #define QS_OBJ_(obj_)    (QP_ QS::u64_(reinterpret_cast<uint64_t>(obj_)))
+#else
+
+    /// \brief Internal QS macro to output an unformatted object pointer
+    /// data element
+    /// \note the size of the pointer depends on the macro #QS_OBJ_PTR_SIZE.
+    /// If the size is not defined the size of pointer is assumed 4-bytes.
+    #define QS_OBJ_(obj_)    (QP_ QS::u32_(reinterpret_cast<uint32_t>(obj_)))
+#endif
+
+
+#if (QS_FUN_PTR_SIZE == 1)
+    #define QS_FUN_(fun_)    (QP_ QS::u8_(reinterpret_cast<uint8_t>(fun_)))
+#elif (QS_FUN_PTR_SIZE == 2)
+    #define QS_FUN_(fun_)    (QP_ QS::u16_(reinterpret_cast<uint16_t>(fun_)))
+#elif (QS_FUN_PTR_SIZE == 4)
+    #define QS_FUN_(fun_)    (QP_ QS::u32_(reinterpret_cast<uint32_t>(fun_)))
+#elif (QS_FUN_PTR_SIZE == 8)
+    #define QS_FUN_(fun_)    (QP_ QS::u64_(reinterpret_cast<uint64_t>(fun_)))
+#else
+
+    /// \brief Internal QS macro to output an unformatted function pointer
+    /// data element
+    /// \note the size of the pointer depends on the macro #QS_FUN_PTR_SIZE.
+    /// If the size is not defined the size of pointer is assumed 4-bytes.
+    #define QS_FUN_(fun_)    (QP_ QS::u32_(reinterpret_cast<uint32_t>(fun_)))
+#endif
+
+/// \brief Internal QS macro to output a zero-terminated ASCII string
+/// data element
+#define QS_STR_(msg_)        (QP_ QS::str_(msg_))
+
+/// \brief Internal QS macro to output a zero-terminated ASCII string
+/// allocated in ROM data element
+#define QS_STR_ROM_(msg_)    (QP_ QS::str_ROM_(msg_))
+
+//////////////////////////////////////////////////////////////////////////////
+// Macros for use in the client code
+
+/// \brief Output formatted int8_t to the QS record
+#define QS_I8(width_, data_) \
+    (QP_ QS::u8(static_cast<uint8_t>((static_cast<uint8_t>((width_) << 4)) \
+        | static_cast<uint8_t>(QP_ QS_I8_T)), (data_)))
+
+/// \brief Output formatted uint8_t to the QS record
+#define QS_U8(width_, data_) \
+    (QP_ QS::u8(static_cast<uint8_t>((static_cast<uint8_t>((width_) << 4)) \
+        | static_cast<uint8_t>(QP_ QS_U8_T)), (data_)))
+
+/// \brief Output formatted int16_t to the QS record
+#define QS_I16(width_, data_) \
+    (QP_ QS::u16(static_cast<uint8_t>((static_cast<uint8_t>((width_) << 4)) \
+        | static_cast<uint8_t>(QP_ QS_I16_T)), (data_)))
+
+/// \brief Output formatted uint16_t to the QS record
+#define QS_U16(width_, data_) \
+    (QP_ QS::u16(static_cast<uint8_t>((((width_) << 4)) \
+        | static_cast<uint8_t>(QP_ QS_U16_T)), (data_)))
+
+/// \brief Output formatted int32_t to the QS record
+#define QS_I32(width_, data_) \
+    (QP_ QS::u32(static_cast<uint8_t>((static_cast<uint8_t>((width_) << 4)) \
+        | static_cast<uint8_t>(QP_ QS_I32_T)), (data_)))
+
+/// \brief Output formatted uint32_t to the QS record
+#define QS_U32(width_, data_) \
+    (QP_ QS::u32(static_cast<uint8_t>((static_cast<uint8_t>((width_) << 4)) \
+        | static_cast<uint8_t>(QP_ QS_U32_T)), (data_)))
+
+/// \brief Output formatted 32-bit floating point number to the QS record
+#define QS_F32(width_, data_) \
+    QP_ QS::f32(static_cast<uint8_t>((static_cast<uint8_t>((width_) << 4)) \
+        | static_cast<uint8_t>(QP_ QS_F32_T)), (data_)))
+
+/// \brief Output formatted 64-bit floating point number to the QS record
+#define QS_F64(width_, data_) \
+    (QP_ QS::f64(static_cast<uint8_t>((static_cast<uint8_t>((width_) << 4)) \
+        | static_cast<uint8_t>(QP_ QS_F64_T)), (data_)))
+
+/// \brief Output formatted int64_t to the QS record
+#define QS_I64(width_, data_) \
+    (QP_ QS::u64(static_cast<uint8_t>((static_cast<uint8_t>((width_) << 4)) \
+        | static_cast<uint8_t>(QP_ QS_I64_T)), (data_)))
+
+/// \brief Output formatted uint64_t to the QS record
+#define QS_U64(width_, data_) \
+    (QP_ QS::u64(static_cast<uint8_t>((static_cast<uint8_t>((width_) << 4)) \
+        | static_cast<uint8_t>(QP_ QS_U64_T)), (data_)))
+
+/// \brief Output formatted uint32_t to the QS record
+#define QS_U32_HEX(width_, data_) \
+    (QP_ QS::u32(static_cast<uint8_t>((static_cast<uint8_t>((width_) << 4)) \
+        | static_cast<uint8_t>(QP_ QS_U32_HEX_T)), (data_)))
+
+/// \brief Output formatted zero-terminated ASCII string to the QS record
+#define QS_STR(str_)            (QP_ QS::str(str_))
+
+/// \brief Output formatted zero-terminated ASCII string from ROM
+/// to the QS record
+#define QS_STR_ROM(str_)        (QP_ QS::str_ROM(str_))
+
+/// \brief Output formatted memory block of up to 255 bytes to the QS
+/// record
+#define QS_MEM(mem_, size_)     (QP_ QS::mem((mem_), (size_)))
+
+
+#if (QS_OBJ_PTR_SIZE == 1)
+    #define QS_OBJ(obj_)        (QP_ QS::u8(QS_OBJ_T, (uint8_t)(obj_)))
+#elif (QS_OBJ_PTR_SIZE == 2)
+    #define QS_OBJ(obj_)        (QP_ QS::u16(QS_OBJ_T, (uint16_t)(obj_)))
+#elif (QS_OBJ_PTR_SIZE == 4)
+    #define QS_OBJ(obj_)        (QP_ QS::u32(QS_OBJ_T, (uint32_t)(obj_)))
+#elif (QS_OBJ_PTR_SIZE == 8)
+    #define QS_OBJ(obj_)        (QP_ QS::u64(QS_OBJ_T, (uint64_t)(obj_)))
+#else
+    /// \brief Output formatted object pointer to the QS record
+    #define QS_OBJ(obj_)        (QP_ QS::u32(QS_OBJ_T, (uint32_t)(obj_)))
+#endif
+
+
+#if (QS_FUN_PTR_SIZE == 1)
+    #define QS_FUN(fun_)        (QP_ QS::u8(QS_FUN_T, (uint8_t)(fun_)))
+#elif (QS_FUN_PTR_SIZE == 2)
+    #define QS_FUN(fun_)        (QP_ QS::u16(QS_FUN_T, (uint16_t)(fun_)))
+#elif (QS_FUN_PTR_SIZE == 4)
+    #define QS_FUN(fun_)        (QP_ QS::u32(QS_FUN_T, (uint32_t)(fun_)))
+#elif (QS_FUN_PTR_SIZE == 8)
+    #define QS_FUN(fun_)        (QP_ QS::u64(QS_FUN_T, (uint64_t)(fun_)))
+#else
+    /// \brief Output formatted function pointer to the QS record
+    #define QS_FUN(fun_)        (QP_ QS::u32(QS_FUN_T, (uint32_t)(fun_)))
+#endif
+
+
+/// \brief Reset the QS session.
+///
+/// This trace record should be generated at the beginning of the QS session.
+/// It informs the QSPY host application that the new session has been started.
+#define QS_RESET() do { \
+    if (QS_GLB_FILTER_(QP_ QS_QP_RESET)) { \
+        QS_CRIT_STAT_ \
+        QS_CRIT_ENTRY_(); \
+        QP_ QS::begin(static_cast<uint8_t>(QP_ QS_QP_RESET)); \
+        QP_ QS::end(); \
+        QS_CRIT_EXIT_(); \
+        QP_ QS::onFlush(); \
+    } \
+} while (false)
+
+/// \brief Output signal dictionary record
+///
+/// A signal dictionary record associates the numerical value of the signal
+/// and the binary address of the state machine that consumes that signal
+/// with the human-readable name of the signal.
+///
+/// Providing a signal dictionary QS record can vastly improve readability of
+/// the QS log, because instead of dealing with cryptic machine addresses the
+/// QSpy host utility can display human-readable names.
+///
+/// A signal dictionary entry is associated with both the signal value \a sig_
+/// and the state machine \a obj_, because signals are required to be unique
+/// only within a given state machine and therefore the same numerical values
+/// can represent different signals in different state machines.
+///
+/// For the "global" signals that have the same meaning in all state machines
+/// (such as globally published signals), you can specify a signal dictionary
+/// entry with the \a obj_ parameter set to NULL.
+///
+/// The following example shows the definition of signal dictionary entries
+/// in the initial transition of the Table active object. Please note that
+/// signals HUNGRY_SIG and DONE_SIG are associated with the Table state
+/// machine only ("me" \a obj_ pointer). The EAT_SIG signal, on the other
+/// hand, is global (0 \a obj_ pointer):
+/// \include qs_sigDic.cpp
+///
+/// \note The QSpy log utility must capture the signal dictionary record
+/// in order to use the human-readable information. You need to connect to
+/// the target before the dictionary entries have been transmitted.
+///
+/// The following QSpy log example shows the signal dictionary records
+/// generated from the Table initial transition and subsequent records that
+/// show human-readable names of the signals:
+/// \include qs_sigLog.txt
+///
+/// The following QSpy log example shows the same sequence of records, but
+/// with dictionary records removed. The human-readable signal names are not
+/// available.
+/// \include qs_sigLog0.txt
+#define QS_SIG_DICTIONARY(sig_, obj_) do { \
+    if (QS_GLB_FILTER_(QP_ QS_SIG_DIC)) { \
+        static char_t const Q_ROM Q_ROM_VAR sig_name_[] = #sig_; \
+        QS_CRIT_STAT_ \
+        QS_CRIT_ENTRY_(); \
+        QP_ QS::begin(static_cast<uint8_t>(QP_ QS_SIG_DIC)); \
+        QS_SIG_(sig_); \
+        QS_OBJ_(obj_); \
+        QS_STR_ROM_(&sig_name_[0]); \
+        QP_ QS::end(); \
+        QS_CRIT_EXIT_(); \
+        QP_ QS::onFlush(); \
+    } \
+} while (false)
+
+/// \brief Output object dictionary record
+///
+/// An object dictionary record associates the binary address of an object
+/// in the target's memory with the human-readable name of the object.
+///
+/// Providing an object dictionary QS record can vastly improve readability of
+/// the QS log, because instead of dealing with cryptic machine addresses the
+/// QSpy host utility can display human-readable object names.
+///
+/// The following example shows the definition of object dictionary entry
+/// for the Table active object:
+/// \include qs_objDic.cpp
+#define QS_OBJ_DICTIONARY(obj_) do { \
+    if (QS_GLB_FILTER_(QP_ QS_OBJ_DIC)) { \
+        static char_t const Q_ROM Q_ROM_VAR obj_name_[] = #obj_; \
+        QS_CRIT_STAT_ \
+        QS_CRIT_ENTRY_(); \
+        QP_ QS::begin(static_cast<uint8_t>(QP_ QS_OBJ_DIC)); \
+        QS_OBJ_(obj_); \
+        QS_STR_ROM_(&obj_name_[0]); \
+        QP_ QS::end(); \
+        QS_CRIT_EXIT_(); \
+        QP_ QS::onFlush(); \
+    } \
+} while (false)
+
+/// \brief Output function dictionary record
+///
+/// A function dictionary record associates the binary address of a function
+/// in the target's memory with the human-readable name of the function.
+///
+/// Providing a function dictionary QS record can vastly improve readability
+/// of the QS log, because instead of dealing with cryptic machine addresses
+/// the QSpy host utility can display human-readable function names.
+///
+/// The example from #QS_SIG_DICTIONARY shows the definition of a function
+/// dictionary.
+#define QS_FUN_DICTIONARY(fun_) do { \
+    if (QS_GLB_FILTER_(QP_ QS_FUN_DIC)) { \
+        static char_t const Q_ROM Q_ROM_VAR fun_name_[] = #fun_; \
+        QS_CRIT_STAT_ \
+        QS_CRIT_ENTRY_(); \
+        QP_ QS::begin(static_cast<uint8_t>(QP_ QS_FUN_DIC)); \
+        QS_FUN_(fun_); \
+        QS_STR_ROM_(&fun_name_[0]); \
+        QP_ QS::end(); \
+        QS_CRIT_EXIT_(); \
+        QP_ QS::onFlush(); \
+    } \
+} while (false)
+
+/// \brief Output user QS rectord dictionary record
+///
+/// A user QS record dictionary record associates the numerical value of a
+/// user record with the human-readable identifier.
+#define QS_USR_DICTIONARY(rec_) do { \
+    if (QS_GLB_FILTER_(QP_ QS_USR_DIC)) { \
+        static char_t const Q_ROM Q_ROM_VAR usr_name_[] = #rec_; \
+        QS_CRIT_STAT_ \
+        QS_CRIT_ENTRY_(); \
+        QP_ QS::begin(static_cast<uint8_t>(QP_ QS_USR_DIC)); \
+        QS_U8_(static_cast<uint8_t>(rec_)); \
+        QS_STR_ROM_(&usr_name_[0]); \
+        QP_ QS::end(); \
+        QS_CRIT_EXIT_(); \
+        QP_ QS::onFlush(); \
+    } \
+} while (false)
+
+/// \brief Output the assertion violation
+#define QS_ASSERTION(module_, loc_) do { \
+    QS_BEGIN_NOCRIT_(QP_ QS_ASSERT, \
+        static_cast<void *>(0), static_cast<void *>(0)) \
+        QS_TIME_(); \
+        QS_U16_(static_cast<uint16_t>(loc_)); \
+        QS_STR_ROM_(module_); \
+    QS_END_NOCRIT_() \
+    QP_ QS::onFlush(); \
+} while (false)
+
+/// \brief Flush the QS trace data to the host
+///
+/// This macro invokes the QS::flush() platform-dependent callback function
+/// to flush the QS trace buffer to the host. The function typically
+/// busy-waits until all the data in the buffer is sent to the host.
+/// This is acceptable only in the initial transient.
+#define QS_FLUSH()   (QP_ QS::onFlush())
+
+/// \brief Output the critical section entry record
+#define QF_QS_CRIT_ENTRY() \
+    QS_BEGIN_NOCRIT_(QP_ QS_QF_CRIT_ENTRY, \
+        static_cast<void *>(0), static_cast<void *>(0)) \
+        QS_TIME_(); \
+        QS_U8_((uint8_t)(++QF_critNest_)); \
+    QS_END_NOCRIT_()
+
+/// \brief Output the critical section exit record
+#define QF_QS_CRIT_EXIT() \
+    QS_BEGIN_NOCRIT_(QP_ QS_QF_CRIT_EXIT, \
+        static_cast<void *>(0), static_cast<void *>(0)) \
+        QS_TIME_(); \
+        QS_U8_((uint8_t)(QF_critNest_--)); \
+    QS_END_NOCRIT_()
+
+/// \brief Output the interrupt entry record
+#define QF_QS_ISR_ENTRY(isrnest_, prio_) \
+    QS_BEGIN_NOCRIT_(QP_ QS_QF_ISR_ENTRY, \
+        static_cast<void *>(0), static_cast<void *>(0)) \
+        QS_TIME_(); \
+        QS_U8_(isrnest_); \
+        QS_U8_(prio_); \
+    QS_END_NOCRIT_()
+
+/// \brief Output the interrupt exit record
+#define QF_QS_ISR_EXIT(isrnest_, prio_) \
+    QS_BEGIN_NOCRIT_(QP_ QS_QF_ISR_EXIT,  \
+        static_cast<void *>(0), static_cast<void *>(0)) \
+        QS_TIME_(); \
+        QS_U8_(isrnest_); \
+        QS_U8_(prio_); \
+    QS_END_NOCRIT_()
+
+/// \brief Execute an action that is only necessary for QS output
+#define QF_QS_ACTION(act_)      (act_)
+
+#else                                                                 // Q_SPY
+
+// qs_dummy.h ================================================================
+/// \brief Dummy definitions of the QS macros that avoid code generation from
+/// the QS instrumentation.
+
+#define QS_INIT(arg_)                   (true)
+#define QS_EXIT()                       ((void)0)
+#define QS_DUMP()                       ((void)0)
+#define QS_RESET()                      ((void)0)
+#define QS_FILTER_ON(rec_)              ((void)0)
+#define QS_FILTER_OFF(rec_)             ((void)0)
+#define QS_FILTER_SM_OBJ(obj_)          ((void)0)
+#define QS_FILTER_AO_OBJ(obj_)          ((void)0)
+#define QS_FILTER_MP_OBJ(obj_)          ((void)0)
+#define QS_FILTER_EQ_OBJ(obj_)          ((void)0)
+#define QS_FILTER_TE_OBJ(obj_)          ((void)0)
+#define QS_FILTER_AP_OBJ(obj_)          ((void)0)
+
+#define QS_GET_BYTE(pByte_)             (static_cast<uint16_t>(0xFFFFU))
+#define QS_GET_BLOCK(pSize_)            (static_cast<uint8_t *>(0))
+
+#define QS_BEGIN(rec_, obj_)            if (false) {
+#define QS_END()                        }
+#define QS_BEGIN_NOCRIT(rec_, obj_)     if (false) {
+#define QS_END_NOCRIT()                 }
+
+#define QS_I8(width_, data_)            ((void)0)
+#define QS_U8(width_, data_)            ((void)0)
+#define QS_I16(width_, data_)           ((void)0)
+#define QS_U16(width_, data_)           ((void)0)
+#define QS_I32(width_, data_)           ((void)0)
+#define QS_U32(width_, data_)           ((void)0)
+#define QS_F32(width_, data_)           ((void)0)
+#define QS_F64(width_, data_)           ((void)0)
+#define QS_U64(width_, data_)           ((void)0)
+#define QS_STR(str_)                    ((void)0)
+#define QS_U32_HEX(width_, data_)       ((void)0)
+#define QS_STR_ROM(str_)                ((void)0)
+#define QS_MEM(mem_, size_)             ((void)0)
+#define QS_SIG(sig_, obj_)              ((void)0)
+#define QS_OBJ(obj_)                    ((void)0)
+#define QS_FUN(fun_)                    ((void)0)
+
+#define QS_SIG_DICTIONARY(sig_, obj_)   ((void)0)
+#define QS_OBJ_DICTIONARY(obj_)         ((void)0)
+#define QS_FUN_DICTIONARY(fun_)         ((void)0)
+#define QS_USR_DICTIONARY(rec_)         ((void)0)
+#define QS_ASSERTION(module_, loc_)     ((void)0)
+#define QS_FLUSH()                      ((void)0)
+
+// internal QS macros used only in the QP components .........................
+#define QS_CRIT_STAT_
+#define QS_BEGIN_(rec_, refObj_, obj_)  if (false) {
+#define QS_END_()                       }
+#define QS_BEGIN_NOCRIT_(rec_, refObj_, obj_) if (false) {
+#define QS_END_NOCRIT_()                }
+#define QS_U8_(data_)                   ((void)0)
+#define QS_U16_(data_)                  ((void)0)
+#define QS_U32_(data_)                  ((void)0)
+#define QS_U64_(data_)                  ((void)0)
+#define QS_TIME_()                      ((void)0)
+#define QS_SIG_(sig_)                   ((void)0)
+#define QS_EVS_(size_)                  ((void)0)
+#define QS_OBJ_(obj_)                   ((void)0)
+#define QS_FUN_(fun_)                   ((void)0)
+#define QS_EQC_(ctr_)                   ((void)0)
+#define QS_MPC_(ctr_)                   ((void)0)
+#define QS_MPS_(size_)                  ((void)0)
+#define QS_TEC_(ctr_)                   ((void)0)
+
+#define QF_QS_CRIT_ENTRY()              ((void)0)
+#define QF_QS_CRIT_EXIT()               ((void)0)
+#define QF_QS_ISR_ENTRY(isrnest_, prio_) ((void)0)
+#define QF_QS_ISR_EXIT(isrnest_, prio_) ((void)0)
+#define QF_QS_ACTION(act_)              ((void)0)
+
+#endif                                                                // Q_SPY
+
+// qassert.h =================================================================
+/* \brief Customizable QP assertions.
+*
+* Defines customizable and memory-efficient assertions applicable to
+* embedded systems. This header file can be used in C, C++, and mixed C/C++
+* programs.
+*
+* \note The preprocessor switch Q_NASSERT disables checking assertions.
+* In particular macros #Q_ASSERT, #Q_REQUIRE, #Q_ENSURE, #Q_INVARIANT,
+* #Q_ERROR as well as  #Q_ASSERT_ID, #Q_REQUIRE_ID, #Q_ENSURE_ID,
+* #Q_INVARIANT_ID, and #Q_ERROR_ID do NOT evaluate the test condition
+* passed as the argument to these macros. One notable exception is the
+* macro #Q_ALLEGE, that still evaluates the test condition, but does
+* not report assertion failures when the switch Q_NASSERT is defined.
+*/
+#ifdef Q_NASSERT          /* Q_NASSERT defined--assertion checking disabled */
+
+    #define Q_DEFINE_THIS_FILE
+    #define Q_DEFINE_THIS_MODULE(name_)
+    #define Q_ASSERT(test_)             ((void)0)
+    #define Q_ASSERT_ID(id_, test_)     ((void)0)
+    #define Q_ALLEGE(test_)             ((void)(test_))
+    #define Q_ALLEGE_ID(id_, test_)     ((void)(test_))
+    #define Q_ERROR()                   ((void)0)
+    #define Q_ERROR_ID(id_)             ((void)0)
+
+#else                  /* Q_NASSERT not defined--assertion checking enabled */
+
+    #ifdef __cplusplus
+        extern "C" {
+    #endif
+
+    /** \brief Type for line numbers.
+    *
+    * This typedef specifies strong type for line numbers. The use of this
+    * type, rather than plain 'int', is in compliance with the MISRA-C 2004
+    * Rule 6.3(adv).
+    */
+    typedef int int_t;
+
+    /** callback invoked in case the condition passed to #Q_ASSERT,
+    * #Q_REQUIRE, #Q_ENSURE, #Q_ERROR, #Q_ALLEGE as well as #Q_ASSERT_ID,
+    * #Q_REQUIRE_ID, #Q_ENSURE_ID, #Q_ERROR_ID, and #Q_ALLEGE_ID evaluates
+    * to FALSE.
+    *
+    * \param file name where the assertion failed
+    * \param line number at which the assertion failed
+    */
+    void Q_onAssert(char_t const Q_ROM * const Q_ROM_VAR file,
+                    int_t const line);
+
+    #ifdef __cplusplus
+        }
+    #endif
+
+    /** Place this macro at the top of each C/C++ module to define the file
+    * name string using __FILE__ (NOTE: __FILE__ might contain lengthy path
+    * name). This file name will be used in reporting assertions in this file.
+    */
+    #define Q_DEFINE_THIS_FILE \
+        static char_t const Q_ROM Q_ROM_VAR l_this_file[] = __FILE__;
+
+    /** Place this macro at the top of each C/C++ module to define the module
+    * name as the argument \a name_. This file name will be used in reporting
+    * assertions in this file.
+    */
+    #define Q_DEFINE_THIS_MODULE(name_) \
+        static char_t const Q_ROM Q_ROM_VAR l_this_file[] = name_;
+
+    /** General purpose assertion that makes sure the \a test_ argument is
+    * TRUE. Calls the Q_onAssert() callback if the \a test_ evaluates
+    * to FALSE.
+    * \note the \a test_ is NOT evaluated if assertions are disabled with
+    * the Q_NASSERT switch.
+    * \sa #Q_ASSERT_ID
+    */
+    #define Q_ASSERT(test_) \
+        ((test_) ? (void)0 : Q_onAssert(&l_this_file[0], (int_t)__LINE__))
+
+    /** General purpose assertion that makes sure the \a test_ argument is
+    * TRUE. Calls the Q_onAssert() callback if the \a test_ evaluates
+    * to FALSE. The argument \a id_ is the ID number (unique within
+    * the file) of the assertion. This assertion style is better suited
+    * for unit testig, because it avoids the volatility of line numbers
+    * for indentifying assertions.
+    * \note the \a test_ is NOT evaluated if assertions are disabled with
+    * the Q_NASSERT switch.
+    * \sa #Q_ASSERT
+    */
+    #define Q_ASSERT_ID(id_, test_) \
+        ((test_) ? (void)0 : Q_onAssert(&l_this_file[0], (int_t)(id_))
+
+    /** General purpose assertion that ALWAYS evaluates the \a test_
+    * argument and calls the Q_onAssert() callback if the \a test_
+    * evaluates to FALSE.
+    * \note the \a test_ argument IS always evaluated even when assertions
+    * are disabled with the Q_NASSERT macro. When the Q_NASSERT macro is
+    * defined, the Q_onAssert() callback is NOT called, even if the
+    * \a test_ evaluates to FALSE.
+    * \sa #Q_ALLEGE_ID
+    */
+    #define Q_ALLEGE(test_)    Q_ASSERT(test_)
+
+    /** General purpose assertion that ALWAYS evaluates the \a test_
+    * argument and calls the Q_onAssert() callback if the \a test_
+    * evaluates to FALSE. This assertion style is better suited
+    * for unit testig, because it avoids the volatility of line numbers
+    * for indentifying assertions.
+    * \note the \a test_ argument IS always evaluated even when assertions
+    * are disabled with the Q_NASSERT macro. When the Q_NASSERT macro is
+    * defined, the Q_onAssert() callback is NOT called, even if the
+    * \a test_ evaluates to FALSE.
+    * \sa #Q_ALLEGE
+    */
+    #define Q_ALLEGE_ID(id_, test_) Q_ASSERT_ID(id_, test_)
+
+    /** Assertion that always calls the Q_onAssert() callback if
+    * ever executed.
+    * \note can be disabled with the Q_NASSERT switch.
+    * \sa #Q_ERROR_ID
+    */
+    #define Q_ERROR() \
+        Q_onAssert(&l_this_file[0], (int_t)__LINE__)
+
+    /** Assertion that always calls the Q_onAssert() callback if
+    * ever executed. This assertion style is better suited for unit
+    * testig, because it avoids the volatility of line numbers for
+    * indentifying assertions.
+    * \note can be disabled with the Q_NASSERT switch.
+    * \sa #Q_ERROR
+    */
+    #define Q_ERROR_ID(id_) \
+        Q_onAssert(l_this_file, (int_t)(id_))
+
+#endif                                                         /* Q_NASSERT */
+
+/** Assertion that checks for a precondition. This macro is equivalent to
+* #Q_ASSERT, except the name provides a better documentation of the
+* intention of this assertion.
+* \sa #Q_REQUIRE_ID
+*/
+#define Q_REQUIRE(test_)         Q_ASSERT(test_)
+
+/** Assertion that checks for a precondition. This macro is equivalent to
+* #Q_ASSERT_ID, except the name provides a better documentation of the
+* intention of this assertion.
+* \sa #Q_REQUIRE
+*/
+#define Q_REQUIRE_ID(id_, test_) Q_ASSERT_ID(id_, test_)
+
+/** Assertion that checks for a postcondition. This macro is equivalent to
+* #Q_ASSERT, except the name provides a better documentation of the
+* intention of this assertion.
+* \sa #Q_ENSURE_ID
+*/
+#define Q_ENSURE(test_)          Q_ASSERT(test_)
+
+/** Assertion that checks for a postcondition. This macro is equivalent to
+* #Q_ASSERT_ID, except the name provides a better documentation of the
+* intention of this assertion.
+* \sa #Q_ENSURE
+*/
+#define Q_ENSURE_ID(id_, test_)  Q_ASSERT_ID(id_, test_)
+
+/** Assertion that checks for an invariant. This macro is equivalent to
+* #Q_ASSERT, except the name provides a better documentation of the
+* intention of this assertion.
+* \sa #Q_INVARIANT_ID
+*/
+#define Q_INVARIANT(test_)       Q_ASSERT(test_)
+
+/** Assertion that checks for an invariant. This macro is equivalent to
+* #Q_ASSERT_ID, except the name provides a better documentation of the
+* intention of this assertion.
+* \sa #Q_INVARIANT
+*/
+#define Q_INVARIANT_ID(id_, test_) Q_ASSERT_ID(id_, test_)
+
+/** Compile-time assertion exploits the fact that in C/C++ a dimension of
+* an array cannot be negative. The following declaration causes a compilation
+* error if the compile-time expression (\a test_) is not TRUE. The assertion
+* has no runtime side effects.
+*/
+#define Q_ASSERT_COMPILE(test_) \
+    extern int_t Q_assert_compile[(test_) ? 1 : -1]
+
+#endif                                                                 // qp_h
--- a/qp_port.cpp	Mon Sep 26 03:27:09 2011 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-//////////////////////////////////////////////////////////////////////////////
-// Product: QP/C++ port to Arduino, cooperative "vanilla" kernel, no Q-SPY
-// Last Updated for QP ver: 4.1.06 (modified to fit in one file)
-// Date of the Last Update: Jan 04, 2011
-//
-//                    Q u a n t u m     L e a P s
-//                    ---------------------------
-//                    innovating embedded systems
-//
-// Copyright (C) 2002-2011 Quantum Leaps, LLC. All rights reserved.
-//
-// This software may be distributed and modified under the terms of the GNU
-// General Public License version 2 (GPL) as published by the Free Software
-// Foundation and appearing in the file GPL.TXT included in the packaging of
-// this file. Please note that GPL Section 2[b] requires that all works based
-// on this software must also be made publicly available under the terms of
-// the GPL ("Copyleft").
-//
-// Alternatively, this software may be distributed and modified under the
-// terms of Quantum Leaps commercial licenses, which expressly supersede
-// the GPL and are specifically designed for licensees interested in
-// retaining the proprietary status of their code.
-//
-// Contact information:
-// Quantum Leaps Web site:  http://www.quantum-leaps.com
-// e-mail:                  info@quantum-leaps.com
-//////////////////////////////////////////////////////////////////////////////
-#include "qp_port.h"                                                // QP port
-
-Q_DEFINE_THIS_MODULE(qp_port)
-
-//............................................................................
-extern "C" void loop() {
-    QF::run();         // run the application, NOTE: QF::run() does not return
-}
-
-//............................................................................
-// This QP framework does NOT use new or delete, but the WinAVR/avr-g++
-// compiler generates somehow a reference to the operator delete for every
-// class with a virtual destructor. QP declares virtual destructors, so to
-// satisfy the linker the following dummy definition of the operator
-// delete is provided. This operator should never be actually called.
-//
-void operator delete(void *) {
-    Q_ERROR();               // this operator should never be actually called
-}
-
--- a/qp_port.h	Mon Sep 26 03:27:09 2011 +0000
+++ b/qp_port.h	Tue Sep 04 22:20:52 2012 +0000
@@ -1,28 +1,35 @@
 //////////////////////////////////////////////////////////////////////////////
 // Product: QP/C++ port to ARM Cortex, selectable Vanilla/QK, mbed compiler
-// Last Updated for QP ver: 4.1.06 (modified to fit in one file)
-// Date of the Last Update: Feb 08, 2011
+// Last Updated for Version: 4.5.02
+// Date of the Last Update:  Sep 04, 2012
 //
 //                    Q u a n t u m     L e a P s
 //                    ---------------------------
 //                    innovating embedded systems
 //
-// Copyright (C) 2002-2011 Quantum Leaps, LLC. All rights reserved.
+// Copyright (C) 2002-2012 Quantum Leaps, LLC. All rights reserved.
+//
+// This program is open source software: you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as published
+// by the Free Software Foundation, either version 2 of the License, or
+// (at your option) any later version.
 //
-// This software may be distributed and modified under the terms of the GNU
-// General Public License version 2 (GPL) as published by the Free Software
-// Foundation and appearing in the file GPL.TXT included in the packaging of
-// this file. Please note that GPL Section 2[b] requires that all works based
-// on this software must also be made publicly available under the terms of
-// the GPL ("Copyleft").
+// Alternatively, this program may be distributed and modified under the
+// terms of Quantum Leaps commercial licenses, which expressly supersede
+// the GNU General Public License and are specifically designed for
+// licensees interested in retaining the proprietary status of their code.
 //
-// Alternatively, this software may be distributed and modified under the
-// terms of Quantum Leaps commercial licenses, which expressly supersede
-// the GPL and are specifically designed for licensees interested in
-// retaining the proprietary status of their code.
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
 //
 // Contact information:
-// Quantum Leaps Web site:  http://www.quantum-leaps.com
+// Quantum Leaps Web sites: http://www.quantum-leaps.com
+//                          http://www.state-machine.com
 // e-mail:                  info@quantum-leaps.com
 //////////////////////////////////////////////////////////////////////////////
 #ifndef qp_port_h
@@ -31,10 +38,15 @@
 #include "qp_config.h"    // QP configuration defined at the application level
 
 //............................................................................
+
+                                                // QF interrupt disable/enable
+#define QF_INT_DISABLE()            __disable_irq()
+#define QF_INT_ENABLE()             __enable_irq()
+
                                              // QF critical section entry/exit
-// QF_INT_KEY_TYPE not defined
-#define QF_INT_LOCK(dummy)      __disable_irq()
-#define QF_INT_UNLOCK(dummy)    __enable_irq()
+// QF_CRIT_STAT_TYPE not defined: "unconditional interrupt unlocking" policy
+#define QF_CRIT_ENTRY(dummy)        __disable_irq()
+#define QF_CRIT_EXIT(dummy)         __enable_irq()
 
 #ifdef QK_PREEMPTIVE
                                                 // QK interrupt entry and exit
@@ -43,15 +55,17 @@
         ++QK_intNest_; \
         QF_QS_ISR_ENTRY(QK_intNest_, QK_currPrio_); \
         __enable_irq(); \
-    } while (0)
+    } while (false)
 
     #define QK_ISR_EXIT()  do { \
         __disable_irq(); \
         QF_QS_ISR_EXIT(QK_intNest_, QK_currPrio_); \
         --QK_intNest_; \
-        *((uint32_t volatile *)0xE000ED04) = 0x10000000; \
-        __enable_irq(); \
-    } while (0)
+          *Q_UINT2PTR_CAST(uint32_t, 0xE000ED04U) = \
+              static_cast<uint32_t>(0x10000000U); \
+          __enable_irq(); \
+      } while (false)
+
 #else
     #define QK_ISR_ENTRY() ((void)0)
     #define QK_ISR_EXIT()  ((void)0)