Quantum Leaps 13 سال پیش
والد
کامیت
696f5cef7b
100فایلهای تغییر یافته به همراه9901 افزوده شده و 0 حذف شده
  1. 29 0
      copying.txt
  2. 255 0
      doxygen/Doxyfile
  3. BIN
      doxygen/images/FA1.jpg
  4. BIN
      doxygen/images/Fig1.01.jpg
  5. BIN
      doxygen/images/Fig1.02.jpg
  6. BIN
      doxygen/images/Fig1.03.jpg
  7. BIN
      doxygen/images/Fig1.04.jpg
  8. BIN
      doxygen/images/Fig1.05.jpg
  9. BIN
      doxygen/images/Fig1.06.jpg
  10. BIN
      doxygen/images/Fig1.07.jpg
  11. BIN
      doxygen/images/Fig1.08.jpg
  12. BIN
      doxygen/images/Fig1.09.jpg
  13. BIN
      doxygen/images/Fig1.11.jpg
  14. BIN
      doxygen/images/Fig11.01.jpg
  15. BIN
      doxygen/images/Fig11.02.jpg
  16. BIN
      doxygen/images/Fig8.01.jpg
  17. BIN
      doxygen/images/Fig8.02.jpg
  18. BIN
      doxygen/images/PSiCC2_125x100.jpg
  19. BIN
      doxygen/images/PSiCC2_250x200.jpg
  20. BIN
      doxygen/images/PSiCC2_500x400.jpg
  21. BIN
      doxygen/images/logo_qep_TM.jpg
  22. BIN
      doxygen/images/logo_qf_TM.jpg
  23. BIN
      doxygen/images/logo_qk_TM.jpg
  24. BIN
      doxygen/images/logo_ql_TM.jpg
  25. BIN
      doxygen/images/logo_qp_TM.jpg
  26. BIN
      doxygen/images/logo_qs_TM.jpg
  27. BIN
      doxygen/images/qp_banner.jpg
  28. BIN
      doxygen/images/qp_components.jpg
  29. BIN
      doxygen/images/qp_datasheet.gif
  30. BIN
      doxygen/images/qp_tutorial.jpg
  31. 338 0
      doxygen/qpc.txt
  32. 438 0
      doxygen/qpc_files.txt
  33. 1491 0
      doxygen/qpc_rev.txt
  34. 2270 0
      doxygen/qpc_tut.txt
  35. 16 0
      doxygen/snippets/qa_run.c
  36. 4 0
      doxygen/snippets/qep_qevent.c
  37. 6 0
      doxygen/snippets/qep_qfsm.c
  38. 3 0
      doxygen/snippets/qep_qfsm_ctor.c
  39. 23 0
      doxygen/snippets/qep_qfsm_use.c
  40. 8 0
      doxygen/snippets/qep_qhsm.c
  41. 3 0
      doxygen/snippets/qep_qhsm_ctor.c
  42. 19 0
      doxygen/snippets/qep_qhsm_use.c
  43. 23 0
      doxygen/snippets/qep_qinit.c
  44. 25 0
      doxygen/snippets/qep_qtran.c
  45. 4 0
      doxygen/snippets/qf_ctor.c
  46. 41 0
      doxygen/snippets/qf_main.c
  47. 15 0
      doxygen/snippets/qf_post.c
  48. 5 0
      doxygen/snippets/qf_qactive.c
  49. 18 0
      doxygen/snippets/qf_start.c
  50. 19 0
      doxygen/snippets/qf_state.c
  51. 13 0
      doxygen/snippets/qf_subscribe.c
  52. 20 0
      doxygen/snippets/qf_tick.c
  53. 4 0
      doxygen/snippets/qf_version.c
  54. 9 0
      doxygen/snippets/qk_mux.c
  55. 25 0
      doxygen/snippets/qs_filter.c
  56. 13 0
      doxygen/snippets/qs_objDic.c
  57. 9 0
      doxygen/snippets/qs_onGetTime.c
  58. 20 0
      doxygen/snippets/qs_sigDic.c
  59. 78 0
      doxygen/snippets/qs_sigLog.txt
  60. 78 0
      doxygen/snippets/qs_sigLog0.txt
  61. 23 0
      doxygen/snippets/qs_startup.c
  62. 14 0
      doxygen/snippets/qs_user.c
  63. 240 0
      examples/80251/vanilla/keil/dpp-mcb251/START251.A51
  64. 272 0
      examples/80251/vanilla/keil/dpp-mcb251/bsp.c
  65. 55 0
      examples/80251/vanilla/keil/dpp-mcb251/bsp.h
  66. 106 0
      examples/80251/vanilla/keil/dpp-mcb251/dpp-mcb251.Opt
  67. 520 0
      examples/80251/vanilla/keil/dpp-mcb251/dpp-mcb251.Uv2
  68. 61 0
      examples/80251/vanilla/keil/dpp-mcb251/dpp.h
  69. 57 0
      examples/80251/vanilla/keil/dpp-mcb251/isr.c
  70. 85 0
      examples/80251/vanilla/keil/dpp-mcb251/main.c
  71. 183 0
      examples/80251/vanilla/keil/dpp-mcb251/philo.c
  72. 158 0
      examples/80251/vanilla/keil/dpp-mcb251/table.c
  73. 207 0
      examples/80x86/dos/watcom/l/bomb/bomb1.c
  74. 1 0
      examples/80x86/dos/watcom/l/bomb/bomb1.rsp
  75. 214 0
      examples/80x86/dos/watcom/l/bomb/bomb2.c
  76. 1 0
      examples/80x86/dos/watcom/l/bomb/bomb2.rsp
  77. 207 0
      examples/80x86/dos/watcom/l/bomb/bomb4.c
  78. 1 0
      examples/80x86/dos/watcom/l/bomb/bomb4.rsp
  79. 50 0
      examples/80x86/dos/watcom/l/bomb/bsp.c
  80. 37 0
      examples/80x86/dos/watcom/l/bomb/bsp.h
  81. 1 0
      examples/80x86/dos/watcom/l/bomb/inc_qp.rsp
  82. 57 0
      examples/80x86/dos/watcom/l/bomb/make_b1.bat
  83. 59 0
      examples/80x86/dos/watcom/l/bomb/make_b2.bat
  84. 57 0
      examples/80x86/dos/watcom/l/bomb/make_b4.bat
  85. 48 0
      examples/80x86/dos/watcom/l/bomb/statetbl.c
  86. 40 0
      examples/80x86/dos/watcom/l/bomb/statetbl.h
  87. 128 0
      examples/80x86/dos/watcom/l/calc/bsp.c
  88. 46 0
      examples/80x86/dos/watcom/l/calc/bsp.h
  89. 526 0
      examples/80x86/dos/watcom/l/calc/calc.c
  90. 58 0
      examples/80x86/dos/watcom/l/calc/calc.h
  91. 1 0
      examples/80x86/dos/watcom/l/calc/inc_qp.rsp
  92. 1 0
      examples/80x86/dos/watcom/l/calc/link_dbg.rsp
  93. 134 0
      examples/80x86/dos/watcom/l/calc/main.c
  94. 61 0
      examples/80x86/dos/watcom/l/calc/make.bat
  95. 128 0
      examples/80x86/dos/watcom/l/calc2/bsp.c
  96. 46 0
      examples/80x86/dos/watcom/l/calc2/bsp.h
  97. 510 0
      examples/80x86/dos/watcom/l/calc2/calc1.c
  98. 103 0
      examples/80x86/dos/watcom/l/calc2/calc1.h
  99. 1 0
      examples/80x86/dos/watcom/l/calc2/calc1.rsp
  100. 82 0
      examples/80x86/dos/watcom/l/calc2/calc2.c

+ 29 - 0
copying.txt

@@ -0,0 +1,29 @@
+Copyright (C) 2002-2012 Quantum Leaps, LLC. All rights reserved.
+
+This program is free 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, LLC
+Web   : http://www.quantum-leaps.com
+        http://www.state-machine.com
+email : info@quantum-leaps.com
+phone : 1-866-450-LEAP (toll-free US only)
+       +1-919-360-5668 (direct, international)

+ 255 - 0
doxygen/Doxyfile

@@ -0,0 +1,255 @@
+# Doxyfile 1.5.4
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+PROJECT_NAME           = QP/C
+PROJECT_NUMBER         = 
+OUTPUT_DIRECTORY       = .
+CREATE_SUBDIRS         = NO
+OUTPUT_LANGUAGE        = English
+BRIEF_MEMBER_DESC      = YES
+REPEAT_BRIEF           = YES
+ABBREVIATE_BRIEF       = "The $name class" \
+                         "The $name widget" \
+                         "The $name file" \
+                         is \
+                         provides \
+                         specifies \
+                         contains \
+                         represents \
+                         a \
+                         an \
+                         the
+ALWAYS_DETAILED_SEC    = NO
+INLINE_INHERITED_MEMB  = NO
+FULL_PATH_NAMES        = NO
+STRIP_FROM_PATH        = C:/software/
+STRIP_FROM_INC_PATH    = 
+SHORT_NAMES            = NO
+JAVADOC_AUTOBRIEF      = NO
+MULTILINE_CPP_IS_BRIEF = NO
+DETAILS_AT_TOP         = NO
+INHERIT_DOCS           = YES
+SEPARATE_MEMBER_PAGES  = NO
+TAB_SIZE               = 4
+ALIASES                = 
+OPTIMIZE_OUTPUT_FOR_C  = YES
+OPTIMIZE_OUTPUT_JAVA   = NO
+BUILTIN_STL_SUPPORT    = NO
+CPP_CLI_SUPPORT        = NO
+SIP_SUPPORT            = NO
+DISTRIBUTE_GROUP_DOC   = NO
+SUBGROUPING            = YES
+TYPEDEF_HIDES_STRUCT   = YES
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+EXTRACT_ALL            = NO
+EXTRACT_PRIVATE        = NO
+EXTRACT_STATIC         = NO
+EXTRACT_LOCAL_CLASSES  = YES
+EXTRACT_LOCAL_METHODS  = NO
+EXTRACT_ANON_NSPACES   = NO
+HIDE_UNDOC_MEMBERS     = YES
+HIDE_UNDOC_CLASSES     = YES
+HIDE_FRIEND_COMPOUNDS  = NO
+HIDE_IN_BODY_DOCS      = NO
+INTERNAL_DOCS          = NO
+CASE_SENSE_NAMES       = NO
+HIDE_SCOPE_NAMES       = NO
+SHOW_INCLUDE_FILES     = YES
+INLINE_INFO            = YES
+SORT_MEMBER_DOCS       = YES
+SORT_BRIEF_DOCS        = NO
+SORT_BY_SCOPE_NAME     = NO
+GENERATE_TODOLIST      = YES
+GENERATE_TESTLIST      = YES
+GENERATE_BUGLIST       = YES
+GENERATE_DEPRECATEDLIST= YES
+ENABLED_SECTIONS       = 
+MAX_INITIALIZER_LINES  = 30
+SHOW_USED_FILES        = YES
+SHOW_DIRECTORIES       = NO
+FILE_VERSION_FILTER    = 
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET                  = NO
+WARNINGS               = YES
+WARN_IF_UNDOCUMENTED   = YES
+WARN_IF_DOC_ERROR      = YES
+WARN_NO_PARAMDOC       = NO
+WARN_FORMAT            = "$file:$line: $text"
+WARN_LOGFILE           = 
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT                  = ./qpc.txt \
+                         ./qpc_rev.txt \
+                         ./qpc_files.txt \
+                         ./qpc_tut.txt \
+                         ./gpl2.txt \
+                         ../ports/lint \
+                         ../include \
+                         ../qep/source \
+                         ../qf/source \
+                         ../qk/source \
+                         ../qs/source
+FILE_PATTERNS          = *.c \
+                         *.cpp \
+                         *.java \
+                         *.h
+RECURSIVE              = YES
+EXCLUDE                = 
+EXCLUDE_SYMLINKS       = NO
+EXCLUDE_PATTERNS       = 
+EXCLUDE_SYMBOLS        = 
+EXAMPLE_PATH           = ./snippets
+EXAMPLE_PATTERNS       = *
+EXAMPLE_RECURSIVE      = NO
+IMAGE_PATH             = ./images
+INPUT_FILTER           = 
+FILTER_PATTERNS        = 
+FILTER_SOURCE_FILES    = NO
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER         = YES
+INLINE_SOURCES         = NO
+STRIP_CODE_COMMENTS    = YES
+REFERENCED_BY_RELATION = YES
+REFERENCES_RELATION    = YES
+REFERENCES_LINK_SOURCE = YES
+USE_HTAGS              = NO
+VERBATIM_HEADERS       = YES
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX     = YES
+COLS_IN_ALPHA_INDEX    = 5
+IGNORE_PREFIX          = 
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML          = YES
+HTML_OUTPUT            = html
+HTML_FILE_EXTENSION    = .html
+HTML_HEADER            = 
+HTML_FOOTER            = 
+HTML_STYLESHEET        = 
+HTML_ALIGN_MEMBERS     = YES
+GENERATE_HTMLHELP      = YES
+HTML_DYNAMIC_SECTIONS  = NO
+CHM_FILE               = ../../qpc.chm
+HHC_LOCATION           = 
+GENERATE_CHI           = NO
+BINARY_TOC             = NO
+TOC_EXPAND             = YES
+DISABLE_INDEX          = NO
+ENUM_VALUES_PER_LINE   = 4
+GENERATE_TREEVIEW      = NO
+TREEVIEW_WIDTH         = 250
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX         = NO
+LATEX_OUTPUT           = latex
+LATEX_CMD_NAME         = latex
+MAKEINDEX_CMD_NAME     = makeindex
+COMPACT_LATEX          = NO
+PAPER_TYPE             = a4wide
+EXTRA_PACKAGES         = 
+LATEX_HEADER           = 
+PDF_HYPERLINKS         = NO
+USE_PDFLATEX           = NO
+LATEX_BATCHMODE        = NO
+LATEX_HIDE_INDICES     = NO
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF           = NO
+RTF_OUTPUT             = rtf
+COMPACT_RTF            = NO
+RTF_HYPERLINKS         = YES
+RTF_STYLESHEET_FILE    = 
+RTF_EXTENSIONS_FILE    = 
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN           = NO
+MAN_OUTPUT             = man
+MAN_EXTENSION          = .3
+MAN_LINKS              = NO
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML           = NO
+XML_OUTPUT             = xml
+XML_SCHEMA             = 
+XML_DTD                = 
+XML_PROGRAMLISTING     = YES
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+GENERATE_AUTOGEN_DEF   = NO
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+GENERATE_PERLMOD       = NO
+PERLMOD_LATEX          = NO
+PERLMOD_PRETTY         = YES
+PERLMOD_MAKEVAR_PREFIX = 
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor   
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING   = YES
+MACRO_EXPANSION        = YES
+EXPAND_ONLY_PREDEF     = YES
+SEARCH_INCLUDES        = YES
+INCLUDE_PATH           = ../include \
+                         ../ports/lint
+INCLUDE_FILE_PATTERNS  = 
+PREDEFINED             = Q_SPY= \
+                         "QF_MAX_ACTIVE= 63"
+EXPAND_AS_DEFINED      = 
+SKIP_FUNCTION_MACROS   = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references   
+#---------------------------------------------------------------------------
+TAGFILES               = 
+GENERATE_TAGFILE       = 
+ALLEXTERNALS           = NO
+EXTERNAL_GROUPS        = YES
+PERL_PATH              = /usr/bin/perl
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool   
+#---------------------------------------------------------------------------
+CLASS_DIAGRAMS         = YES
+MSCGEN_PATH            = 
+HIDE_UNDOC_RELATIONS   = YES
+HAVE_DOT               = NO
+CLASS_GRAPH            = YES
+COLLABORATION_GRAPH    = YES
+GROUP_GRAPHS           = YES
+UML_LOOK               = NO
+TEMPLATE_RELATIONS     = NO
+INCLUDE_GRAPH          = YES
+INCLUDED_BY_GRAPH      = YES
+CALL_GRAPH             = NO
+CALLER_GRAPH           = NO
+GRAPHICAL_HIERARCHY    = YES
+DIRECTORY_GRAPH        = YES
+DOT_IMAGE_FORMAT       = png
+DOT_PATH               = 
+DOTFILE_DIRS           = 
+DOT_GRAPH_MAX_NODES    = 50
+MAX_DOT_GRAPH_DEPTH    = 1000
+DOT_TRANSPARENT        = NO
+DOT_MULTI_TARGETS      = NO
+GENERATE_LEGEND        = YES
+DOT_CLEANUP            = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine   
+#---------------------------------------------------------------------------
+SEARCHENGINE           = NO

BIN
doxygen/images/FA1.jpg


BIN
doxygen/images/Fig1.01.jpg


BIN
doxygen/images/Fig1.02.jpg


BIN
doxygen/images/Fig1.03.jpg


BIN
doxygen/images/Fig1.04.jpg


BIN
doxygen/images/Fig1.05.jpg


BIN
doxygen/images/Fig1.06.jpg


BIN
doxygen/images/Fig1.07.jpg


BIN
doxygen/images/Fig1.08.jpg


BIN
doxygen/images/Fig1.09.jpg


BIN
doxygen/images/Fig1.11.jpg


BIN
doxygen/images/Fig11.01.jpg


BIN
doxygen/images/Fig11.02.jpg


BIN
doxygen/images/Fig8.01.jpg


BIN
doxygen/images/Fig8.02.jpg


BIN
doxygen/images/PSiCC2_125x100.jpg


BIN
doxygen/images/PSiCC2_250x200.jpg


BIN
doxygen/images/PSiCC2_500x400.jpg


BIN
doxygen/images/logo_qep_TM.jpg


BIN
doxygen/images/logo_qf_TM.jpg


BIN
doxygen/images/logo_qk_TM.jpg


BIN
doxygen/images/logo_ql_TM.jpg


BIN
doxygen/images/logo_qp_TM.jpg


BIN
doxygen/images/logo_qs_TM.jpg


BIN
doxygen/images/qp_banner.jpg


BIN
doxygen/images/qp_components.jpg


BIN
doxygen/images/qp_datasheet.gif


BIN
doxygen/images/qp_tutorial.jpg


+ 338 - 0
doxygen/qpc.txt

@@ -0,0 +1,338 @@
+/**
+\anchor main_page
+\mainpage QP/C Reference Manual
+
+\image html qp_banner.jpg
+
+- \ref overview
+- \ref starting
+- \ref PSiCC2
+- \ref licensing
+- \ref contact
+
+- \ref files_page
+- \ref rev_page
+
+\section overview QP Overview
+
+Quantum Platform (<strong>%QP</strong>) is a family of very lightweight, open
+source, state machine-based frameworks for embedded systems. QP enables
+developing well-structured embedded applications as a set of concurrently
+executing hierarchical state machines (UML statecharts). With QP, coding of
+modern state machines directly in C or C++ is a non-issue. <STRONG>No big
+tools</STRONG> are needed.
+
+\image html qp_components.jpg
+
+- \subpage qep_page
+- \subpage qf_page
+- \subpage qk_page
+- \subpage qs_page
+- http://www.state-machine.com/doxygen/qspy/index.html 
+
+Current versions of %QP include: QP/C and QP/C++, which require 3-4KB of code
+and a few hundred bytes of RAM, and the ultra-lightweight <A
+HREF="http://www.state-machine.com/products/">QP-nano</A>, which
+requires only 1-2KB of code and just several bytes of RAM.
+
+QP can work with or without a traditional OS/RTOS. In the simplest
+configuration, QP can completely <strong>replace</strong> a traditional RTOS.
+QP includes a simple non-preemptive scheduler and a fully preemptive kernel
+(<strong>%QK</strong>), which have been ported to several popular CPUs and
+compilers including: ARM7/ARM9, ARM Cortex-M3, 80x86, Nios-II, MSP430, M16C,
+AVR, 80251, and others (see
+http://www.state-machine.com/downloads/).
+
+QP/C and QP/C++ can also work with a traditional OS/RTOS to take advantage of
+existing device drivers, communication stacks, and other middleware. QP has
+been ported to Linux/BSD, Windows, VxWorks, uC/OS-II, and other popular
+OS/RTOS (see http://www.state-machine.com/downloads/).
+
+\image html qp_datasheet.gif
+
+The <strong>QP Datasheet</strong>
+(see http://www.state-machine.com/products/QP_datasheet.pdf)
+provides a concise summary of QP features and benefits.
+
+Since its publication in 2002, hundreds of projects around the world have been
+using QP in all kinds of applications, such as consumer, medical, industrial,
+wireless, networking, research, defense, robotics, automotive, space
+exploration, and many others.
+
+QP is available for download from the following websites:
+- Quantum Leaps website: http://www.state-machine.com/downloads
+- SourceForge.net webiste: https://sourceforge.net/projects/qpc
+
+<HR>
+
+\section starting Getting Started with QP/C
+
+QP/C is distributed in a simple platform-independent ZIP file or in a
+self-extracing Windows executable. Either way, installing QP/C requires simply
+decompressing the provided archive into a directory of your choice (e.g.,
+\c qpc for QP/C). The Section \ref files_page describes the content of the
+standard QP/C distribution.
+
+The <STRONG>QP/C Tutorial</STRONG> explains all steps necessary to develop a
+non-trivial QP/C application. The Tutorial is based on Chapter 1 of
+<I>Practical UML Statecharts in C/C++, Second Edition</I>.
+
+\image html qp_tutorial.jpg
+
+- \subpage tutorial_page
+    - \ref installing
+    - \ref lets_play
+    - \ref main_function
+    - \ref design
+    - \ref active_objects
+    - \ref events
+    - \ref coding_hsm
+    - \ref execution
+    - \ref tracing
+    - \ref comparison
+    - \ref summary
+
+<HR>
+
+
+\section PSiCC2 Practical UML Statecharts in C/C++, Second Edition
+
+All versions of QP are described in detail in the book <I>Practical UML
+Statecharts in C/C++, Second Edition: Event-Driven Programming for Embedded
+Systems</I>, Newnes 2008 (ISBN-10: 0750687061, ISBN-13: 978-0750687065).
+
+\image html PSiCC2_250x200.jpg
+
+The book bridges the gap between high-level abstract concepts of the Unified
+Modeling Language (UML) and the actual programming aspects of modern
+hierarchical state machines (UML statecharts).
+
+This book is presented in two parts. In Part I, you get a practical
+description of the relevant state machine concepts starting from traditional
+finite state automata to modern UML state machines followed by state machine
+coding techniques with the %QEP hierarchical event processor as well as
+several state-machine design patterns, all illustrated with executable
+examples.
+
+In Part II, you find a detailed design study of the %QF real-time framework,
+%QK preemptive kernel, and %QS software tracing, which are indispensable for
+combining concurrent, event-driven state machines into robust systems. In
+addition to its value as a reference to the %QP event-driven platform, Part II
+explans the key event-driven programming concepts such as inversion of control
+("Hollywood Principle"), blocking versus non-blocking code, run-to-completion
+(RTC) execution semantics, the importance of event queues, dealing with time,
+and the role of state machines to maintain the context from one event to the
+next. This background is designed to help software developers in making the
+transition from the traditional sequential to the modern event-driven
+programming, which can be one of the trickiest paradigm shifts.
+
+- Visit the accompanying website to the book at
+http://www.state-machine.com/psicc2/
+- Order the book from Amazon.com at
+http://www.amazon.com/exec/obidos/ASIN/0750687061/quantumleap06-20
+
+<HR>
+
+
+\section licensing Licensing Policy for QP
+
+All versions of the QP software are available under <A
+HREF="http://www.state-machine.com/licensing/">dual licensing</A> model, in
+which both the open source software distribution mechanism and traditional
+closed source software licensing models are combined.
+
+\subsection open Open Source Licensing
+
+All versions of the QP software are available under the  \ref gpl2_page
+(GPL2), as published by the Free Software Foundation and included in every
+distribution of the QP software. The GPL2 license is probably the best known
+and most established open source license. It is fully compatible with the Open
+Source Definition, is endorsed by the Free Software Foundation, and has been
+approved by the Open Source Initiative.
+
+Please note that GPL2 applies to software based not upon how it is used but
+upon how it is distributed. In this respect GPL2 can be restrictive, because
+GPL2 Section 2(b) requires that if you distribute the original software or any
+derivative works based on the software under copyright law, you must release
+all such derivative works also under the terms of the GPL2 open source
+license. GPL2 clearly specifies that distributing the original software or any
+derivative works based upon it in binary form (e.g., embedded inside devices)
+also represents distribution of the software.
+
+To read more about open source licensing for QP or QP-nano, or to
+contribute work to the open source community, please visit the following
+website:
+
+- http://www.state-machine.com/licensing/open.php
+- \ref gpl2_page
+
+or please contact Quantum Leaps, LLC via the following e-mail address:
+
+- info@quantum-leaps.com
+
+
+\subsection closed Closed Source Licensing
+
+If you are developing and distributing traditional <b>closed source</b>
+applications, you might purchase one of the Quantum Leaps commercial licenses,
+which are specifically designed for users interested in retaining the
+proprietary status of their code. This alternative licensing is possible,
+because Quantum Leaps, LLC owns all intellectual property in the QP and
+QP-nano software and as the copyright owner can license the software any
+number of ways. The Quantum Leaps commercial licenses expressly supersede the
+\ref gpl2_page open source license. This means that when you license the
+software under a commercial license, you specifically do not use the software
+under the open source license and therefore you are not subject to any of its
+terms.
+
+To read more about the commercial licensing options, pricing, technical
+support, and to request a commercial license, please visit the following
+website:
+
+- http://www.state-machine.com/licensing
+
+or please contact Quantum Leaps, LLC via the following e-mail address:
+
+- info@quantum-leaps.com
+
+<HR>
+
+\section contact Contact Information
+
+- Quantum Leaps Web site:  http://www.state-machine.com
+- Quantum Leaps licensing: http://www.state-machine.com/licensing
+- Quantum Leaps downloads: http://www.state-machine.com/downloads
+- e-mail: info@quantum-leaps.com
+- Skype: quantum-leaps (US Eastern Standard Time)
+- Toll-free: 1-866-450-LEAP (US Eastern Standard Time)
+
+\image html logo_ql_TM.jpg
+Copyright &copy; 2002-2011 Quantum Leaps, LLC. All Rights Reserved.\n
+http://www.state-machine.com
+*/
+
+/**
+\page qep_page QEP Hierarchical Event Processor
+
+\image html logo_qep_TM.jpg
+
+Quantum Event Processor&tm; (%QEP) is a generic, portable, and reusable
+hierarchical event processor that processes events according to the general
+semantics of UML state machines [<A
+HREF="http://www.omg.org/docs/ptc/03-08-02.pdf">UML document
+ptc/03-08-02</A>]. %QEP&tm; allows you to map UML state diagrams directly and
+clearly to code without the assistance of complex tools. It allows you to
+create better designs because you can think in terms of events, states, and
+transitions directly at the level of the C or C++ programming language. The
+resulting code is smaller, cleaner, more robust, and simpler to understand and
+maintain. The testing is faster, more rigorous, and more complete because
+state machine approach cleanly defines a limited state space for the system
+and constraints the possible transitions among the states.
+
+%QEP&tm; provides facilities for executing <STRONG>Hierarchical State
+Machines</STRONG> (HSMs) as well as the simpler traditional <STRONG>Finite
+State Machines</STRONG> (FSMs). %QEP can operate with almost any event queuing
+and dispatching mechanisms, which are also necessary components of a
+hypothetical state machine [<A
+HREF="http://www.omg.org/docs/ptc/03-08-02.pdf">ptc/03-08-02</A>]. For
+example, %QEP can be used with virtually any event-driven environment, such as
+any Graphical User Interface system. When used in the domain of real-time
+embedded (RTE) systems, %QEP can be combined with other <STRONG>QP</STRONG>
+components designed specifically for RTE systems. %QEP has been used in
+hundreds of event-driven applications worldwide and is described in Part 1 of
+the book \ref PSiCC2, Newnes 2008.
+
+Please refer to Section \ref coding_hsm in the \ref tutorial_page for
+information on coding UML-compliant hierarchical state machines with QEP.
+
+\image html logo_ql_TM.jpg
+Copyright &copy; 2002-2011 Quantum Leaps, LLC. All Rights Reserved.\n
+http://www.state-machine.com
+*/
+
+/**
+\page qf_page QF Real-Time Framework
+
+\image html logo_qf_TM.jpg
+
+Quantum Frameowrk&tm; (%QF) is a reusable event-driven application framework
+for executing concurrent state machines specifically designed for real-time
+embedded (RTE) systems. The use of QF generally simplifies the design of
+event-driven software by allowing the application to be divided into multiple
+active objects  that the framework manages. 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.
+
+Most of %QF&tm; is written in portable ANSI-C, with microprocessor-specific,
+compiler-specific, or op-erating system-specific code kept to a minimum for
+ease of portability. %QF is designed to work with Quantum Event Processor
+(%QEP) and a Real Time Operating System (RTOS) of your choice, or even with
+just "main+ISRs" configuration. The framework is very compact, typically
+taking up about 4KB of code and data (including the \ref
+qep_page). %QF has been used in hundreds of event-driven applications
+worldwide and is described in Part 2 of the book \ref PSiCC2, Newnes 2008.
+
+Please refer to the \ref tutorial_page for information on implementing
+event-driven applications with the QF real-time framework and other components
+of the QP event-driven platform.
+
+
+\image html logo_ql_TM.jpg
+Copyright &copy; 2002-2011 Quantum Leaps, LLC. All Rights Reserved.\n
+http://www.state-machine.com
+*/
+
+/**
+\page qk_page QK Preemptive Run-To-Completion Kernel
+
+\image html logo_qk_TM.jpg
+
+Quantum Kernel&tm; (%QK) is a tiny preemptive real-time kernel specifically
+designed for executing independent tasks in a run-to-completion (RTC) fashion.
+As it turns out, the RTC-style processing universally applied in the \ref
+qf_page, and no need for blocking of active objects, allow %QK to be extremely
+simple and utilize only a single stack for all tasks and interrupts.
+
+%QK&tm; is not a standalone product but rather it requires a compatible
+version of %QF. %QK doesn't provide event queues, active objects, or even
+lookup tables used by the scheduler, because these elements are already part
+of the %QF. %QK is described in Chapter 10 of the book \ref PSiCC2, Newnes
+2008.
+
+The \ref execution part of the QP Tutorial describes how to use the QK kernel
+in an example.
+
+\image html logo_ql_TM.jpg
+Copyright &copy; 2002-2011 Quantum Leaps, LLC. All Rights Reserved.\n
+http://www.state-machine.com
+*/
+
+/**
+\page qs_page QS Software Tracing Instrumentation (Target Component)
+
+\image html logo_qs_TM.jpg
+
+Quantum Spy&tm; (%QS) is a real-time tracing instrumentation built into the
+\ref qep_page, the \ref qf_page, and the \ref qk_page components and also
+available to the Application code. %QS allows you to gain unprecedented
+visibility into your application by selectively logging almost all interesting
+events occurring within state machines, the framework, the kernel, and your
+application code. %QS event logging is minimally intrusive, offers precise
+time-stamping, sophisticated runtime filtering of events, and good data
+compression. %QS can be configured to send the real-time data out of the
+serial or Ethernet port of the target device, or even write the data to a
+file. %QS is described in Chapter 11 of the book \ref PSiCC2, Newnes 2008.
+
+Every software tracing system consists of a target component and a host
+component. Section \ref execution of the \ref tutorial_page describes how to
+enable the QS target component in an example. The host component for the %QS
+software tracing system is the <STRONG>QSPY host application</STRONG>.
+Section \ref qspy_page describes how to use the QSPY host application.
+
+\image html logo_ql_TM.jpg
+Copyright &copy; 2002-2011 Quantum Leaps, LLC. All Rights Reserved.\n
+http://www.state-machine.com
+*/

+ 438 - 0
doxygen/qpc_files.txt

@@ -0,0 +1,438 @@
+/**
+\page files_page Directories and Files in the QP/C Distribution
+
+The following annotated directory tree lists the most important directories
+and files provided in the standard QP distribution. The explanation section
+immediately following the directory tree explains the structure in more
+detail.
+
+\code
+ (1) qpc\                 - QP/C root directory
+       |
+ (2)   +-qpc.chm          - "QP/C Reference Manual" in CHM Help format
+       |
+ (3)   +-doxygen\         - QP documentation generated with Doxygen
+       | +-html\          - "QP/C Reference Manual" in HTML format
+ (4)   | | +-index.html   - The HTML index page for the "QP/C Reference Manual"
+       | | +- . . .
+       | +-Doxyfile       - Doxygen configuration file to generate the Manual
+       | +- . . .
+       |
+ (5)   +-examples\        - QP examples
+ (6)   | +-80x86\         - Examples for the 80x86 processor
+ (7)   | | +-dos\         - Examples for DOS with the "vanilla" cooperative kernel
+ (8)   | | | +-watcom\    - Examples with the Open Watcom compiler
+ (9)   | | | | +-l\       - Examples using the Large memory model
+(10)   | | | | | +-dpp\   - Dining Philosopher Problem (DPP) example for DOS
+       | | | | | | +-dbg\ - Debug build
+       | | | | | | | +-dpp.exe - Debug executable
+(11)   | | | | | | +-rel\      - Release build
+       | | | | | | | +-dpp.exe - Release executable
+(12)   | | | | | | +-spy\      - Spy build (with QS tracing instrumentation)
+       | | | | | | | +-dpp.exe - Spy executable
+(13)   | | | | | | +-make.bat  - batch script to build the application
+       | | | | | |
+       | | | | | +-game\       - "Fly 'n' Shoot" game example
+       | | | | | | +-dbg\      - Debug build
+       | | | | | | | +-GAME.EXE   - Debug executable
+       | | | | | | +-make.bat  - batch script to build the application
+       | | | | | | +-game.h    - The application header file
+       | | | | | | +-bsp.c     - BSP for the application
+       | | | | | | +-main.c    - main() function
+       | | | | | |
+       | | | | | +-calc\    - Calculator example
+       | | | | | +-qhsmtst\ - QHsmTst example (PSiCC2  in Chapter 2)
+       | | | | | |
+(14)   | | | | | +-comp\    - "Orthogonal Component" pattern (PSiCC2 Chapter 5)
+       | | | | | +-defer\   - "Deferred Event" pattern (PSiCC2 Chapter 5)
+       | | | | | +-history\ - "Transition to History" pattern (PSiCC2 Chapter 5)
+       | | | | | +-hook\    - "Ultimate Hook" pattern (Chapter 5)
+       | | | | | +-reminder\ - "Reminder" pattern (PSiCC2 Chapter 5)
+       | | |
+(15)   | | +-qk\          - Examples for the QK preemptive kernel
+(16)   | | +-ucos2\       - Examples for the µC/OS-II RTOS
+       | | |
+(17)   | | +-linux\       - Examples for Linux (POSIX)
+       | | | +-gnu\       - Examples with the GNU compiler
+       | | | | +-dpp\     - Dining Philosopher Problem (DPP) example for Linux
+       | | | | | +-dbg\   - Debug build
+       | | | | | +-rel\      - Release build
+       | | | | | +-spy\      - Spy build (with software instrumentation)
+(18)   | | | | | +-Makefile  - GNU Makefile to build the DPP application
+       | | | | | +-. . .
+       | |
+(19)   | +-arm-cortex\    - Examples for ARM Cortex processor
+       | | +-vanilla\     - Examples for the cooperative "vanilla" kernel
+       | | | +-iar\       - Examples with the IAR compiler
+       | | | | +-dpp-ev-lm3s811\  - DPP example for for EV-LM3S811 board
+       | | | | +-game-ev-lm3s811\ - "Fly 'n' Shoot" example for EV-LM3S811 board
+       | | | | +-. . .    - Other examples for ARM Cortex
+       | | | +-gnu\       - Examples with the GNU compiler (Code Sourcery G++)
+       | | | | +-dpp-ev-lm3s811\  - DPP example for for EV-LM3S811 board
+       | | | | +-game-ev-lm3s811\ - "Fly 'n' Shoot" example for EV-LM3S811 board
+       | | | | +-. . .    - Other examples for ARM Cortex
+       | | |
+       | | +-qk\          - Examples for the preemptive QK kernel
+       | | | +-iar\       - Examples with the IAR compiler
+       | | | | +-dpp-qk-ev-lm3s811\  - DPP example for for EV-LM3S811 board
+       | | | | +-game-qk-ev-lm3s811\ - "Fly 'n' Shoot" example for EV-LM3S811 board
+       | | | | +-. . .    - Other examples for ARM Cortex
+       | | | +-gnu\       - Examples with the GNU compiler (Code Sourcery G++)
+       | | | | +-dpp-qk-ev-lm3s811\  - DPP example for for EV-LM3S811 board
+       | | | | +-game-qk-ev-lm3s811\ - "Fly 'n' Shoot" example for EV-LM3S811 board
+       | | | | +-. . .    - Other examples for ARM Cortex
+       | |
+       | +-. . .          - Examples for other CPUs and compiler
+       |
+(20)   +-include\         - QP platform-independent header files
+       | +-qassert.h      - QP assertions
+       | +-qep.h          - QEP platform-independent interface
+       | +-qf.h           - QF platform-independent interface
+       | +-qk.h           - QK platform-independent interface
+       | +-qs.h           - QS platform-independent active interface
+       | +-qs_dummy.h     - QS platform-independent inactive interface
+       | +-qequeue.h      - QF native event queue facility
+       | +-qmpool.h       - QF native memory pool facility
+       | +-qpset.h        - QF native priority set facility
+       | +-qvanilla.h     - QF native "vanilla" cooperative kernel interface
+       |
+(21)   +-qep\             - QEP hierarchical event processor
+       | +-source\        - QEP platform-independent source code (*.c files)
+       | | +- . . .
+       |
+(22)   +-qf\              - QF real-time framework
+       | +-source\        - QF platform-independent source code (*.c files)
+       | | +- . . .
+       |
+(23)   +-qk\              - QK preemptive kernel
+       | +-source\        - QK platform-independent source code (*.c files)
+       | | +- . . .
+       |
+(24)   +-qs\              - QS software tracing (target component)
+       | +-source\        - QS platform-independent source code (*.c files)
+       | | +- . . .
+       |
+(25)   +-ports\           - Platform-specific QP ports
+(26)   | +-80x86\         - Ports to the 80x86 processor
+(27)   | | +-dos\         - Ports to DOS with the "vanilla" cooperative kernel
+(28)   | | | +-watcom\    - Ports with the Open Watcom compiler
+(29)   | | | | +-l\       - Ports using the Large memory model
+(30)   | | | | | +-dbg\   - Debug build
+(31)   | | | | | | +-qf.lib   - QF  library
+(32)   | | | | | | +-qep.lib  - QEP library
+       | | | | | +-rel\   - Release build
+       | | | | | +-spy\   - Spy build (with software instrumentation)
+       | | | | | | +-qep.lib  - QEP library
+       | | | | | | +-qf.lib   - QF  library
+       | | | | | | +-qs.lib   - QS  library
+       | | | | | |
+(33)   | | | | | +-make.bat   - batch script for building the QP libraries
+(34)   | | | | | +-qep_port.h - QEP platform-dependent include file
+(35)   | | | | | +-qf_port.h  - QF  platform-dependent include file
+(36)   | | | | | +-qs_port.h  - QS  platform-dependent include file
+(37)   | | | | | +-qp_port.h  - QP  platform-dependent include file
+       | | |
+       | | +-qk\          - Ports to the QK preemptive kernel
+       | | | +-. . .
+       | | |
+       | | +-ucos2\       - Ports to the MicroC/OS-II RTOS
+       | | | +-watcom\    - Ports with the Open Watcom compiler
+       | | | | +-l\       - Ports using the Large memory model
+(38)   | | | | | +-ucos2.86\  - MicroC/OS-II v2.86 object code and header files
+(39)   | | | | | +-src\       - Port-specific source files
+(40)   | | | | | | +-qf_port.c - QF port to µC/OS-II source file
+       | | | | | +-. . .
+       | | |
+       | | +-linux\       - Ports to the Linux operating system (POSIX)
+       | | | +-gnu\       - Ports with the GNU compiler
+       | | | | +-src\         - Port-specific source files
+       | | | | | +- qf_port.c - QF port to Linux source file
+       | | | | +-. . .
+       | |
+       | +-arm-cortex\    - Ports to the ARM Cortex processor
+       | | +-vanilla\     - Ports to the cooperative "vanilla" kernel
+       | | | +-iar\       - Ports with the IAR compiler
+       | | | | | +-dbg\   - Debug build
+       | | | | | +-rel\   - Release build
+       | | | | | +-spy\   - Spy build (with software instrumentation)
+       | | | | | +-make_cortex-m3.bat - batch script for building QP libraries
+       | | | | | +-qep_port.h - QEP platform-dependent include file
+       | | | | | +-qf_port.h  - QF  platform-dependent include file
+       | | | | | +-qs_port.h  - QS  platform-dependent include file
+       | | | | | +-qp_port.h  - QP  platform-dependent include file
+       | | | . . .
+       | | | +-gnu\       - Ports with the GNU compiler (Code Sourcery G++)
+       | | | | | +-dbg\   - Debug build
+       | | | | | +-rel\   - Release build
+       | | | | | +-spy\   - Spy build (with software instrumentation)
+       | | | | | +-make_cortex-m3_cs.bat - batch script for building QP libraries
+       | | | | | +-qep_port.h - QEP platform-dependent include file
+       | | | | | +-qf_port.h  - QF  platform-dependent include file
+       | | | | | +-qs_port.h  - QS  platform-dependent include file
+       | | | | | +-qp_port.h  - QP  platform-dependent include file
+       | | | . . .
+       | | +-qk\          - Ports to the preemptive QK kernel
+       | |   +-iar\       - Ports with the IAR compiler
+       | |   +-gnu\       - Ports with the GNU compiler (Code Sourcery G++)
+       | +-. . .          - Ports to other CPUs
+       |
+(41)   +-tools\           - QP-related tools for the host machine
+(42)   | +-qspy\          - QSPY host application
+       | | +-include\     - QSPY header files
+       | | +-source\      - QSPY platform-independent source files
+(43)   | | +-linux\       - QSPY port to Linux
+       | | | +-gnu\       - QSPY port with the GNU compiler
+       | | | | +-rel\     - Release build
+       | | | | | +-qspy       - Linux executable (not provided -- must be built)
+(44)   | | | | +-Makefile     - GNU Makefile to bulid QSPY for Linux
+(45)   | | +-win32\       - QSPY ports to Win32
+(46)   | | | +-mingw\     - QSPY port with the open source MinGW GNU compiler
+       | | | | +-rel\     - Release build
+       | | | | | +-qspy.exe   - Windows executable (console app)
+       | | | | +-Makefile     - GNU Makefile to bulid QSPY for Win32 under MinGW
+       | | | +-vc2008\    - QSPY port with Visual C++ 2008
+(47)   | | | | +-Release\ - Release build
+       | | | | | +-qspy.exe   - Windows executable (console app)
+       | | | | +-qspy.sln     - Visual C++ solution to build QSPY
+(48)   | | | +-vc6\       - QSPY port with Visual C++ 6.0
+       | | | | +-Release\ - Release build
+       | | | | | +-qspy.exe   - Windows executable (console app)
+       | | | | +-qspy.dsw     - Visual C++ 6.0 workspace to build QSPY
+(49)   | | +-matlab\      - MATLAB scripts to import QSPY data to MATLAB
+
+\endcode
+
+\li (1) Every QP version, such as QP/C, QP/C++, ir QP-nano resides in the
+separate directory branch, called henceforth QP Root Directory. The essential
+element of the design is that the QP Root Directory can be "plugged into" any
+branch of a hierarchical file system and you can move the QP Root Directory
+around, or even have multiple versions of the QP Root Directories. You can
+also freely choose the name of the QP Root Directory, although I recommend the
+directory names \c qpc\\ for QP/C and \c qpcpp\\ for QP/C++. The ability to
+relocate the QP Root Directory means that only relative paths should be used
+in the Makefiles, build scripts, workspaces, or project files.
+
+\li (2) The file qpc.chm contains the "QP/C Reference Manual" in CHM format.
+
+\li (3) The \c doxygen\\ directory contains this "QP/C Reference Manual"
+generated with the Doxygen utility.
+
+\li (4) The \c html\\ subdirectory contains this HTML verions of the "QP/C
+Reference Manual". In particular, the file index.html is the index page of the
+Manual.
+
+\li (5) The \c examples\\ directory contains the application examples that are
+included in the standard QP/C distribution. The structure of the \c examples\\
+(and also \c ports\\ directory) is the most complicated because of the large
+number of choices available, such as CPU architectures, compilers, operating
+systems, and compiler options. Each of those choices is represented as a
+separate level of nesting in a hierarchical directory tree, so that each
+dimension in the multi-dimensional space of options can be extended
+independently from the others. Also, the directory branch for each QP port is
+individually customizable, so each branch can represent only choices relevant
+for a given CPU, operating system, compiler, etc.
+
+\li (6) The CPU architecture is placed as the first level of nesting within
+the \c examples\\ directory. Examples of CPU architectures are: 80x86, ARM,
+ARM Cortex, AVR, MSP430, M16C, etc. Please note that a separate directory
+is needed whenever the CPU architecture is significantly different. For
+example, even though the traditional ARM and the new ARM Cortex are
+related, the differences are significant enough to require a separate
+directory branch for ARM and ARM Cortex.
+
+\li (7) The second level of nesting, under the CPU architecture, is the
+operating system used. For example, in the 80x86 architecture, QP can operate
+under DOS (with the "vanilla" cooperative kernel), under the QK preemptive
+kernel, under the MicroC/OS-II RTOS, or under Linux (and perhaps other OSs,
+such as Win32).
+
+\note The ordering of directory levels reflects the embedded focus in the QP
+design. In most standalone QF applications the CPU architecture is typically
+more important than the RTOS/OS. For general-purpose operating systems, such
+as Linux, the reversed order (operating system at a higher level than the CPU
+architecture) would perhaps feel more natural.
+
+\li (8) The next level of nesting, under each operating system directory, is
+the directory for the compiler used. For example, the DOS port can be compiled
+with the Open Watcom or perhaps with Borland C++. Similarly, the port
+to ARM Cortex with QK kernel can be compiled with the IAR, RealView, or GNU
+compilers.
+
+\li (9) In some ports, the compiler can emit code for various modes of the
+CPU. For example, a compiler for 80x86 under DOS can produce small, compact,
+large, or huge memory models. These different modes result in incompatible
+object code, and therefore each of them requires a separate branch. Please
+note that the compiler options level is optional. For example, the ARM Cortex
+CPU branch does not need the compiler options level.
+
+\li (10) Finally, the example application is located in its own directory. For
+example, the \c dpp\\ directory contains the "Dining Philosopher Problem"
+application example for this particular CPU/Kernel/Compiler/Options
+combinations.
+
+\li (11) The \c dpp\\dbg\\ subdirectory contains the object files and the
+executable for the Debug configuration.
+
+\li (12) The \c dpp\\rel\\ subdirectory contains the object files and the
+executable for the Release configuration.
+
+\li (13) The \c dpp\\spy\\ subdirectory contains the object files and the
+executable for the Spy configuration (with the \ref qs_page).
+
+\li (14) All five state designed patterns described in Chapter 5 of \ref
+PSiCC2 (PSiCC2) are provided.
+
+\li (15) The directory \c qk\\ contains examples for the QK preemptive kernel.
+
+\li (16) The directory \c ucos2\\ contains examples for the MicroC/OS-II RTOS.
+
+\li (17) The directory \c linux\\ contains examples for the Linux operating
+system.
+
+\note The port to Linux also runs on many POSIX-compliant OSes/RTOSes, such as
+BSD, Solaris, MacOS X, and QNX.
+
+\li (18) The Makefile for building POSIX port is provided.
+
+\li (19) The directory \c arm-cortex\\ contains QP examples for ARM Cortex.
+
+\li (20) The directory \c include\\ contains platform-independent header files
+for QP all components. You need to point your C/C++ compiler to include files
+from this directory.
+
+\li (21-24) The platform-independent source code of each QP component is
+located in the separate directory. The sources files are only needed to
+re-build QP libraries, but you don't need to include these directories in the
+compiler's search path to build applications.
+
+\li (25) The directory \c ports\\ contains platform-dependent header files and
+libraries to be used by QP applications. This directory structure is the most
+complicated because of the large number of choices available, such as CPU
+architectures, compilers, operating systems, and compiler options. Each of
+those choices is represented as a separate level of nesting in a hierarchical
+directory tree, so that each dimension in the multi-dimensional space of
+options can be extended independently from the others. Also, the directory
+branch for each port is individually customizable, so each branch can
+represent only choices relevant for a given CPU, operating system, compiler,
+etc.
+
+\li (26) The CPU architecture is placed as the first level of nesting within
+the \c ports\\ directory. Examples of CPU architectures are: 80x86, ARM Cortex,
+ARM, AVR, MSP430, M16C, etc. Please note that a separate directory is needed
+whenever the CPU architecture is significantly different. For example, even
+though the traditional ARM and the new ARM Cortex are related, the
+differences are significant enough to require a separate directory branch for
+ARM and ARM Cortex.
+
+\li (27) The second level of nesting, under the CPU architecture, is the
+operating system used. For example, in the 80x86 architecture, QP can operate
+under DOS (with the "vanilla" cooperative kernel), under the QK preemptive
+kernel, under the MicroC/OS-II RTOS, or under Linux (and perhaps other OSs,
+such as Win32).
+
+\note The ordering of directory levels reflects the embedded focus in the QP
+design. In most standalone QF applications the CPU architecture is typically
+more important than the RTOS/OS. For general-purpose operating systems, such
+as Linux, the reversed order (operating system at a higher level than the CPU
+architecture) would perhaps feel more natural.
+
+\li (28) The next level of nesting, under each operating system directory, is
+the directory for the compiler used. For example, the DOS port can be compiled
+with the Open Watcom or perhaps with Borland C++. Similarly, the port
+to ARM Cortex with QK kernel can be compiled with the IAR, RealView, or GNU
+compilers.
+
+\li (29) In some ports, the compiler can emit code for various modes of the
+CPU. For example, a compiler for 80x86 under DOS can produce small, compact,
+large, or huge memory models. These different modes result in incompatible
+object code, and therefore each of them requires a separate branch. Please
+note that the compiler options level is optional. For example, the ARM Cortex
+CPU branch does not need the compiler options level.
+
+\li (30) Finally, the QP libraries can be compiled with different compile-time
+switches and optimization options. For example, the \c dbg\\ directory holds
+the Debug configuration, which contains the symbolic debug information.
+
+\li (31) Each specific build directory contains the QP library files. The
+actual library names should comply with the conventions used on a particular
+platform. For example, on Linux the libraries are typically named \c libXXX.a
+(e.g., \c libqep.a, \c libqf.a, etc.).
+
+\li (32) The \c rel\\ directory holds the Release configuration, which
+typically does not contain debug information but might use aggressive
+optimizations for best performance.
+
+\li (33) The standard QP ports often contain a simple \c make.bat script or a
+Makefile for building all the QP libraries for the port. You typically can
+choose the build configuration by providing a target to the make.bat script or
+to the Makefile. The default target is "dbg". Other possible targets are
+"rel", and "spy". The following table summarizes the targets accepted by the
+make.bat scripts or the Makefiles.
+
+<TABLE SUMMARY="Build Targets" cellSpacing=4 cellPadding=1 border=0
+ALIGN="center" VALIGN="middle">
+  <TR bgColor="#c8cedc" ALIGN="center">
+      <TD width="20"><B>&nbsp;Build Configuration</B></TD>
+      <TD width="20"><B>&nbsp;Build Command</B></TD>
+  </TR>
+
+  <TR bgColor="#ffffcc">
+    <TD>&nbsp;Debug&nbsp;</TD>
+    <TD>make</TD>
+  </TR>
+
+  <TR bgColor="#ffffdd">
+    <TD>&nbsp;Release&nbsp;</TD>
+    <TD>make rel</TD>
+  </TR>
+
+  <TR bgColor="#ffffcc">
+    <TD>&nbsp;Spy&nbsp;</TD>
+    <TD>make spy</TD>
+  </TR>
+</TABLE>
+
+\li (34) The qep_port.h header file contains platform-specific definitions of
+macros and typedef's for the QEP component.
+
+\li (35) The qf_port.h header file contains platform-specific definitions of
+macros and typedef's for the QF component.
+
+\li (36) The qk_port.h header file contains platform-specific definitions of
+macros and typedef's for the QK component.
+
+\li (37) The qs_port.h header file contains platform-specific definitions of
+macros and typedef's for the QS component.
+
+\li (38) The subdirectory \c ucos2.86\\ contains the headers and object files
+of MicroC/OS-II v2.86, compiled for 80x86 with the Open Watcom compiler.
+This directory is provided only to allow you re-building the example
+applications based on the QF port to MicroC/OS-II. Typically, however, you
+will need to obtain the MicroC/OS-II source code to re-build it for the actual
+processor you're using.
+
+\li (39-40) QP ports to an external RTOS or OS, such as MicroC/OS-II or Linux
+require some "glue-code" to bolt the QF framework to the external RTOS/OS.
+This source code is placed in the file qf_port.c in the subdirectory \c src\\.
+
+\li (41) The directory \c tools\\ contains host-resident tools used for QP
+(see \ref qspy_page).
+
+\li (42) The directory \c qspy\\ contains the portable QSPY host utility.
+
+\li (43) The subdirectory \c linux\\ contains QSPY port to Linux.
+
+\li (44) The \c Makefile for building Linux QSPY executable is provided.
+
+\li (45) The subdirectory \c win32\\ contains QSPY port to Win32.
+
+\li (46-48) The Windows version of QSPY can be build with three different
+compilers.
+
+\li (49) The subdirectory \c matlab\\ contains scripts to import QSPY data to
+MATLAB. You need to place this directory on the MATLAB path to convenietly
+access the scripts.
+
+\image html logo_ql_TM.jpg
+Copyright &copy; 2002-2011 Quantum Leaps, LLC. All Rights Reserved.
+*/

+ 1491 - 0
doxygen/qpc_rev.txt

@@ -0,0 +1,1491 @@
+/**
+\page rev_page QP/C Revision History
+
+QP/C Revision History
+=====================
+
+\section qpc_4_5_02 Version 4.5.02 (Product) Release date: Aug 04, 2012
+
+The main purpose of this release is better, more comprehensive
+support for (rapid) prototyping of embedded QP applications on
+the desktop with the Win32 API and with Qt. Among others, this
+release adds a complete toolkit for creating realistic embedded
+front panels with pure Win32-GUI API and free Visual C++ Express
+and ResEdit. An extensive Application Note "QP and Win32" is
+included in this release.
+
+This release simplifies the QP ports to desktop OSs, such as
+Windows (Win32), Linux, BSD, Mac OSX (POSIX) and combines 32-bit
+and 64-bit ports in one with conditional compilation.
+
+This release also adds an option for using constructors for
+dynamically allocated events. When the configuration macro
+Q_EVT_CTOR is defined, the Q_NEW() macro becomes variadic and
+takes the arguments for the event constructor. This generally
+allows creating dynamic events "on-the-fly" without a temporary
+pointer to the event. This QP configuration is demonstrated only
+in the QP port to Qt, but can be used in any other port.
+NOTE: The event constructor feature is NOT backward-compatible
+with the existing applications.
+
+This release also adds a new macro QF_MPOOL_EL, which is
+intended for allocating properly aligned storage for memory pools
+and event pools.
+
+All QP ports included in this release use only a single QP library,
+rather than separate libraries for QEP, QF, QK, and QS.
+
+Finally, this relase adds QM models, created with the new QM 2.2.00
+to most of the examples. The code generated by this new QM version
+complies with MISRA-C:2004 rules.
+
+Changes in detail:
+
+1. Modified QP port to Win32 and used the free Visual C++ Express
+2010 with Platform SDK rather than Visual C++ Pro 2008. Renamed
+the port directory from vc2008\ to vc\. Provided a completely
+revised App Note "QP and Win32".
+
+2. Eliminated QP port to Win32 with one thread (Win32-1T).
+
+3. Consolidated all QP ports to POSIX OSs (Linux, Linux64, Mac_OSX)
+into a single port to POSIX and placed it in the directory posix\.
+
+4. Renamed the port directory qt_1t\ to qt\.
+
+5. Added event constructor to qevt.h (controlled by the configuration
+macro Q_EVT_CTOR).
+
+6. Added new variadic version of the Q_NEW() macro in qf.h when
+Q_EVT_CTOR is defined.
+
+7. Added macro QF_MPOOL_EL to qmpool.h. Modified all examples to
+demonstrate the use of this macro to allocate properly aligned
+storage for event pools.
+
+8. Added new typedef 'enum_t' and modified signatures of functions
+taking event signals from QSignal to enum_t. This was done to
+significantly reduce the number of casts necessary when enumerated
+signals were passed to QP functions.
+
+9. Modified all QP ports distributed in the QP/C baseline code
+to generate only a single QP library, rather than separate
+libraries for QEP, QF, QK, and QS. This includes all QP ports
+to the desktop (ports\80x86\ directory) and ARM Cortex-M ports
+(ports\arm-cortex\ directory).
+
+10. Modified all examples to link only one QP library.
+
+11. Added QM models to most examples and used the automatically
+generated code from the models instead of the hand-written code.
+
+12. Modified Qt ports to use the new "event constructors" and
+modified examples for Qt to demonstrate this feature.
+
+13. Added .ui files to the Qt examples for generating UIs
+graphically with the Qt Designer tool. Revised and updated the
+App Note "QP and Qt".
+
+14. Added new macro QS_USR_DICTIONARY() to QS for providing symbolic
+names for user-defined trace records
+
+15. Added new macro QS_RESET() to QS for telling the QSPY application
+when the target resets. This allows QSPY to reset its internal state.
+
+
+\section qpc_4_5_01 Version 4.5.01 (Product) Release date: Jun 14, 2012
+
+The main purpose of this minor release is providing improved
+MISRA-compliant state machine implementation. Specifically, a new
+macro Q_UNHANDLED() has been added for a situation when a guard
+condition evaluates to FALSE, but the state model does not prescribe
+the explicit [else] case for this guard. In this case, the state
+handler can return Q_UNHANDLED(), which will cause the QEP event
+processor to propagate the event to the superstate, which is what
+UML semantics prescribes.
+
+NOTE: These change to the QEP event processor is completely
+backwards-compatible. All state hander functions coded the old
+way will continue to handle the guard conditions correctly and
+in accordance with the UML specification. The new Q_UNHANDLED()
+macro is necessary only for MISRA-compliant state handler coding,
+which will be applied in the upcoming release of the QM modeling
+and code generation tool.
+
+Changes in detail:
+
+1. Added macro Q_UNHANDLED() and return value Q_RET_UNHANDLED in
+qep.h.
+
+2. Modified qhsm_dis.c to handle the Q_RET_UNHANDLED return value.
+
+3. Updated the QP/C MISRA-C:2004 compliance matrix to
+include the new MISRA-compliant way of coding guard conditions.
+
+4. Modified qs.h and qs_dummy.h to add new trace record type
+QS_QEP_UNHANDLED, which is generated when the state handler returns
+Q_RET_UNHANDLED.
+
+5. Modified qs.h and qs_dummy.h to add the User record dictionary
+trace record and macro QS_USR_DICTIONARY().
+
+NOTE: This new trace record requires the updated QSPY 4.5.01.
+
+6. Corrected qfsm_dis.c, which did not generate QS trace records
+for entry and exit from non-hierarchical states.
+
+7. Updated the IAR ARM compiler used in the ARM Cortex-M examples
+to the latest version IAR EWARM 6.40.
+
+8. Modified the Qt port not to define the QPApp::onClockTick()
+slot function, but instead to allow defining this slot function in
+the BSP of the application.
+
+
+\section qpc_4_5_00 Version 4.5.00 (Product) Release date: May 29, 2012
+
+The main pupose of this relase is to improve host-based development of QP
+applications, which is critical for Test-Driven Development (TDD). Among
+others, this release provides integration between QP and the popular
+Qt GUI framework, which allows developers to easily build host-based
+simulations of the embedded systems with the realistic user interfaces.
+
+This realase also simplifies implementing transitions to history, which
+is a preparation to providing this feature in the QM modeling tool.
+
+Changes in detail:
+
+1. Renamed the event class from QEvent to QEvt to avoid a name conflict
+with the Qt framework. Also, for consistency, renamed the file qevent.h
+to qevt.h and the macro Q_EVENT_CAST() to Q_EVT_CAST().
+
+NOTE: To minimize impact of this change on the existing QP ports and
+applications, the name QEvent is provided as well, but this can be
+suppressed by defining the configuration macro Q_NQEVENT in qep_port.h.
+
+2. Changed the design of QF_tick() (file qf_tick.c) to better support
+calling this function from low-priority tasks (as opposed to interrupts
+and highest-priority tasks), which often happens when QP is executed on
+the desktop operating systems. In this design only QF_tick() can remove
+time events from the active linked list, so no unexpected changes to the
+list structure are eliminated.
+
+3. Simplified the QTimeEvt class by removing the 'prev' link pointer,
+as the new design no longer needs a bi-directional list. These changes
+impact the files: qte_*.c.
+
+4. Added return value to QF_run() to allow transfer of the exit
+status to the destop operating systems.
+
+NOTE: This modification haves impact on most QP/C ports, because
+the QF_run() function must now return a int16_t value.
+
+5. Eliminated the 'running' member of the QActive class, which
+has been used only in the QP ports to "big" OSes such as Linux
+or Windows.
+
+6. Added member 'temp' to the QHsm and QFsm base classes to prevent
+clobbering the current state (the 'state' member) during transitons.
+This change allows keeping the current state unchanged during the
+entire transition chain, which in turn allows easy and generic access
+to the state information to store the state history in the exit
+actions from states. Additional bonus of this re-design is the
+opportunity of testing for stable state configuration in assertions
+added to the qhsm_*.c and qfsm_*.c files.
+
+7. Added the QHsm_state() and QFsm_state() accessor macros.
+
+8. Modified the "Transition to History" pattern implementation to
+use the simplified technique of obtaining the current state in the
+exit action from the superstate rather than all the exit actions from
+the substates. Modified the "State-Local Storage" (SLS) pattern as
+well, because it was using the transition to history constructs.
+
+9. Re-designed the implementation of the QSPY host application, so
+that it can be convenienty included as part of the QP library.
+This allows direct QS tracing output to the screen for QP applications
+running on the desktop.
+
+NOTE: This change is part of the Qtools release 4.5.00.
+
+10. Modified the QP ports to Win32_1t (both the MinGW and VC2008) to
+output QS trace data directly to the stdout via the QSPY host-application
+interface. Modified the DPP examples for Win32_1T to demonstrate the
+direct QS output to the screen.
+
+11. Added QP port to Qt_1t (Qt with one thread) and two example
+applications (DPP and PELICAN crossing).
+
+12. Added GNU compiler option -pthread to QP ports for POSIX with
+P-threads, including QP ports and examples for Linux and Mac OS X.
+
+
+\section qpc_4_4_01 Version 4.4.01 (Product) Release date: Mar 23, 2012
+
+The relase fixes a bug in Q-SPY software tracing, which caused the
+linking error: "QS_SIG_() not defined". This release also includes
+a few cosmetic changes, which the Microchip C18 compiler didn't like.
+
+
+1. Moved QS_SIG_() definition from qep.h to qs.h
+2. Changed (QEvent *)0 to (QEvent const *)0 in source files
+   qeq_get.c, qeq_init.c, and qa_get_.c.
+
+
+\section qpc_4_4_00 Version 4.4.00 (Product) Release date: Jan 30, 2012
+
+The main pupose of this relase is MISRA-C:2004 compliance, strong-type
+checking compliance, update of PC-Lint option files and tests, and
+general cleanup.
+
+1. Moved the qp_port.h header file from the port directories to
+the qcp\include/ directory. Also, moved the inclusion of the
+QS (Spy) header files (qs_port.h/qs_dummy.h) from qep.h, qf.h,
+and qk.h headers to qp_port.h. These structural changes were made
+to reduce the number of preprocessor #if nesting levels below 8,
+which is the ANSI-C limit. This was done to comply with the MISRA-C
+rule 1.1 (all code shall conform to ANSI/ISO C).
+
+NOTE: This modifications have impact on most QP/C ports, because
+the qp_port.h header file must be removed from the port.
+
+2. Added the PC-Lint option files std.lnt and lib-qpc.lnt to the
+qcp/include/ directory.
+
+3. Cleaned the whole QP/C code from lint comments. All PC-Lint options
+have been moved to PC-Lint option files.
+
+4. Modified QP assertion macro Q_DEFINE_THIS_MODULE() to avoid using
+the # operator (MISRA rule 19.13). This macro now requires the argument
+enclosed in doble quotes "".
+
+NOTE: This modification has impact on some QP/C ports.
+
+4. Added typedefs for char_t, int_t, float32_t, and float64_t to
+event.h header file for compliance with MISRA-C:2004 rules 6.1 and 6.3.
+
+5. Added macros Q_STATE_CAST() and Q_EVENT_CAST() to qep.h to
+encapsulate deviation from MISRA-C rule 11.4.
+
+6. Added macro Q_UINT2PTR_CAST() to encapsulate casting unsigned
+integers to pointers, which deviates from MISRA-C rule 11.3. This
+macro has been added for *application-level* code.
+
+7. Updated ARM Cortex-M examples with the latest CMSIS v3.0, which
+complies with more MISRA-C:2004 rules.
+
+8. Added DPP examples for MISRA-C:2004 compliant applications (for
+IAR-ARM and GNU-ARM).
+
+9. Added testing of PC-Lint option files against the MISRA-C Exemplar
+Suite.
+
+10. Updated ARM-Cortex-M3 port with GNU to the latest Sourcery
+CodeBench 2011.09-60.
+
+11. Added QP/C port to Win32-1t and examples (Windows with 1 thread).
+This port is useful for testing embedded QP/C applications on windows.
+
+12. Added documentation to QP/C distribution in the directory
+qpc/doc/, with the following Application notes:
+"MISRA-C:2004 Compliance Matrix", "Quantum Leaps Coding Standard",
+"QP and ARM Cortex-M, and QP and Windows",
+
+
+\section qpc_4_3_00 Version 4.3.00 (Product) Release date: Nov 01, 2011
+
+1. This release changes the names of critical section macros and
+introduces macros for unconditional interrupt disabling/enabling.
+This is done to simplify and speed up the built-in Vanilla and QK
+kernels, which no longer are dependent on the interrupt locking
+policy.
+
+NOTE: The change in handling the critical section in the Vanilla and
+QK kernels can break QP ports, which use the "save and restore
+interrupt lock" policy, because all such ports must also define
+unconditional interrupt disabling and enabling.
+
+2. This release changes the partitioning of the QK scheduler.
+Specifically, the QK scheduler is now divided between two functions
+QK_schedPrio_() and QK_sched_(), to calculate the highest-priority
+task ready to run and to perform scheduling, respectively. The function
+QK_schedPrio_() is useful to determine if scheduling is even necessary.
+
+3. Updated all QP ports to comply with the new critical section
+names and policies.
+
+4. Modified the ARM Cortex-M port qk_port.s to take advantage of the
+new structure of the QK scheduler.
+
+5. Upgraded the examples for ARM Cortex with IAR EWARM to the
+latest IAR EWARM version 6.30.
+
+6. Upgraded the examples for ARM Cortex with GNU (CodeSourcery) to the
+latest Sourcery CodeBench 2011.07-60.
+
+
+\section qpc_4_2_04 Version 4.2.04 (Product) Release date: Sep 24, 2011
+
+The main pupose of this relase is to provide a bug fix for the QK port
+to ARM Cortex processors. The bug fix addresses a very rare and
+undocumented behavior of late-arrival of an interrupt while entering
+the PendSV exception. In this case the PENDSVSET bit in the NVIC-ICSR
+register is *not* cleared when finally PendSV is entered, so the
+PendSV exception is entered in a *different* state when it is entered
+via the late-arrival mechanism versus the normal activation of the
+exception through tail-chaining. The consequence of this undocumented
+and inconsistent hardware behavior, PendSV could be re-entered again
+before the SVCall exception cleans up the stack. The bug fix is
+implemented in the qk_port.s file and consists of clearing the
+PENDSVSET bit programmatically inside PendSV_Handler.
+
+
+\section qpc_4_2_02 Version 4.2.02 (Product) Release date: Sep 08, 2011
+
+1. The main pupose of this relase is to repackage the default QP/C
+distribution to contain the single root directory qpc/ in the
+archive. That way, unziping the archive will produce only one
+directory (qpc/), which can be then changed by the user.
+
+2. This release also changes the ARM Cortex QP ports with GNU. The
+suffix "_cs" has been added to all QP libraries generated by the
+Code Sourcery toolset (now Mentor Sourcery CodeBench). This is to
+distinguish libraries generated by different GNU-toolchains (such
+as CodeRed, Attolic, DevKit ARM, etc.)
+
+
+\section qpc_4_2_01 Version 4.2.01 (Product) Release date: Aug 13, 2011
+
+1. Modified file qassert.h to add assertion macros #Q_ASSERT_ID,
+#Q_REQUIRE_ID, #Q_ENSURE_ID, #Q_INVARIANT_ID, and #Q_ERROR_ID,
+which are better suited for unit testig, because they avoid the
+volatility of line numbers for indentifying assertions.
+
+2. Added QP port and examples for Mac OS X on 80x86.
+
+
+\section qpc_4_2_00 Version 4.2.00 (Product) Release date: Jul 14, 2011
+
+The goal of this milestone release is to extend the number of event
+pools (theoretically up to 255 pools) instead of just three event
+pools available up til now. Also, this release adds several
+improvements to the QS/QSPY software tracing, such as adding sender
+information to event posting so that sequence diagrams could be easily
+and automatically reconstructed from tracing data. Also, the tracing
+now supports 64-bit targets, such as embedded Linux 64-bit. Finally,
+this milestone release migrates the examples to use the environment
+variable QPC instead of relying on the relative path to the QP/C
+framework. This allows easier adaptation of the examples for real
+projects, which don't really belong to the examples directory.
+
+The changes in detail are:
+
+1. Changed the QEvent base struct (file qevent.h). The private member
+'dynamic_' has been replaced by two members 'poolId_' and 'refCtr_'.
+
+2. Added configuration macro QF_MAX_EPOOL (file qf.h) to define the
+maximum number of event pools in the QP application (default to 3).
+The maximum theoretical number of this macro is 255.
+
+3. Made algorithmic changes in the QF source code related to the change
+of storing the event pool-IDs and reference counters inside QEvent.
+
+4. Changed the default signal size (macro Q_SIGNAL_SIZE in the file
+qevent.h) from 1 to 2 bytes.
+
+5. Changed the signature of QActive_recall() to return uint8_t instead
+of QEvent*, which this could encourage incorrect usage (processing of
+the event at the point of recalling it). Now, the function only returns
+1 (TRUE) if the event was recalled and 0 (FALSE) if the event was not
+recalled.
+
+6. Added the function QTimeEvt_ctr() and new source file qte_ctr.c.
+The function returns the counter of a time event, which allows
+using a time event for measuring the time.
+
+7. Added new QF macros #QF_TICK, #QF_PUBLISH, and #QACTIVE_POST in
+file qf.h to provide sender of the events for software tracing.
+
+8. Added new QS macros (files qs.h and qs_dummy.h) for handling 64-bit
+integers.
+
+9. Added the functions QS_u64() and QS_u64_() and new source file
+qs_u64.c.
+
+10. Added the QS macro #QS_U32_HEX_T for hexadecimal formatting of
+integer numbers in the user-defined trace records.
+
+11. Added the new port linux64 for 64-bit Linux. Also added the
+corresponding examples for 64-bit Linux.
+
+12. Adapted the QSPY host application for 64-bit pointer sizes and
+the changed layout of trace records that contain event information
+(such as PoolID and RefCtr). Also added the backwards-compatibility
+option (-v) for switching the tool to the previous data format.
+
+13. Removed the tools directory from the QPC distribution and moved
+the QSPY host application to the QTOOLS distribution, which now also
+contains the GNU make tools for Windows.
+
+14. Modified the make files and project files to use the environment
+variable QPC instead of relying on the relative path to the QP/C
+framework.
+
+15. Upgraded the examples for ARM Cortex with IAR EWARM to the
+latest IAR EWARM 6.20.
+
+
+\section qpc_4_1_07 Version 4.1.07 (Product) Release date: Feb 28, 2011
+
+The goal of this release is to improve the ease of experimenting with
+QP/C on the desktop. This release adds support for Windows (Win32) to
+the baseline code. Two most popular compilers for Windows are supported:
+Microsoft Visual Studio and MinGW (GNU). The support for Linux has been
+improved by including pre-built QP/C libraries and improving makefiles
+for Eclipse compatibility.
+
+The changes in detail are:
+
+1. Added Win32 port with the Visual C++ 2008 (ports/80x86/win32/vc2008).
+This directory contains the Visual Studio solution all_qp.sln for
+building all QP/C libraries from the IDE. Three build configurations
+(Debug, Release, and Spy) are supported.
+
+2. Added Win32 port with the MinGW comiler (ports/80x86/win32/mingw).
+This directory contains the Makefile for building all QP/C libraries.
+Three build configurations (dbg, rel, and spy) are supported.
+NOTE: the Makefile assumes that the MinGW/bin directory is added
+to the PATH.
+
+3. Added Win32 examples for Visual C++ 2008 (examples/80x86/win32/
+vc2008/dpp and examples/80x86/win32/vc2008/qhsmtst). Visual Studio
+soultions are provides for all build configurations.
+
+4. Added Win32 examples for MinGW (examples/80x86/win32/mingw/dpp
+and examples/80x86/win32/mingw/qhsmtst). Eclipse-compatible makefiles
+are provided for all build configurations. NOTE: the Makefiles assume
+that the MinGW/bin directory is added to the PATH.
+
+5. Removed memory alignment correction in the file qmp_init.c. This
+correction required casting of pointers to integers and was problematic
+on 64-bit targets (such as 64-bit Linux).
+
+6. Upgraded the examples for ARM Cortex with CodeSourcery to the
+latest Sourcery G++ 2011.02-2.
+
+
+\section qpc_4_1_06 Version 4.1.06 (Product) Release date: Jan 07, 2011
+
+1. Made cosmetic improvements to the example QM models of the
+"Fly 'n' Shoot" game.
+
+2. Made improvements in make.bat files for building the examples for
+DOS/Open Watcom to run better in DosBox on Linux.
+
+3. Upgraded the examples for ARM Cortex with IAR to the latest
+IAR EWARM version 6.10.
+
+4. Upgraded the examples for ARM Cortex with CodeSourcery to the
+latest Sourcery G++ 2010.09-66.
+
+
+\section qpc_4_1_05 Version 4.1.05 (Product) Release date: Nov 01, 2010
+
+This release is adds examples for the QM (QP Modeler) graphical modeling
+and code generation tool. The examples are based on the "Fly 'n' Shoot"
+game described in the QP/C Tutorial and in Chapter 1 of the PSiCC2 book.
+
+Specifically, the directory <qpc>/examples/80x86/dos/watcom/l/game-qm/
+contains the "Fly 'n' Shoot" game model file "game.qm". This model, when
+opened in the QM tool contains all state machine diagrams and generates
+code into the subdirectory qm_code/. This code can then be built and
+executed on any 80x86 machine (newer versions of Windows or Linux require
+the DOSbox application, see http://www.dosbox.com).
+
+The directory <qpc>/examples/arm-cortex/vanilla/iar/game-ev-lm3s811-qm/
+contains the version of the game for the EV-LM3S811 ARM Cortex-M3 board.
+This directory contains the model file "game.qm", which is actually
+identical as the model in the DOS version. The LM3S811 version needs to
+be compiled with the IAR compiler and executed on the EV-LM3S811 board.
+
+Additionally, the QP/C baseline code has been slighlty modified for
+better conformance to the MISRA C 2004 rules and the latest PC-Lint 9.x.
+
+
+\section qpc_4_1_04 Version 4.1.04 (Product) Release date: Mar 16, 2010
+
+This release is adds compatibility of all examples for DOS with the DOSBox
+emulator (http://www.dosbox.com/) that recreates a MS-DOS compatible
+environment on all versions of Windows, including 64-bit Windows that don't
+run 16-bit DOS applications anymore.
+
+Also, this release includes QP ports and examples for EV-LM3S811 board with
+the GNU-based Code Sourcery G++ toolset. Support for Sourcery G++ provides
+a very cost-effective option for developing QP applications for ARM Cortex
+MCUs.
+
+Finally, this release improves the Cortex Microcontroller Software Interface
+Standard (CMSIS) for the whole family of the Stellaris LM3Sxxx MCUs. The
+improvement extends the CMSIS from Sandstorm to Fury, DustDevil, and Tempest
+Stellaris families.
+
+
+\section qpc_4_1_03 Version 4.1.03 (Product) Release date: Jan 21, 2010
+
+This release is concerned with the ARM Cortex ports and examples.
+Specifically, this release contains the following improvements:
+
+1. Unified source code for ARM Cortex-M3 and the new ARM Cortex-M0 cores,
+including the code for the preemptive QK kernel.
+
+2. Compliance with the Cortex Microcontroller Software Interface Standard
+(CMSIS) in all ARM Cortex examples.
+
+3. Backward-compatible support for the new LM3S811 EVAL Rev C board with
+different OLED display than previous revisions. (NOTE: The OSRAM 96x16x1 OLED
+used in REV A-B boards has been replaced RITEK 96x16x1 OLED used in Rev C.)
+
+In the process of making the examples CMSIS-compliant, the dependency on the
+Luminary Micro driver library (driverlib.a) has been completely removed.
+
+Additionally, the screen saver of the "Fly 'n' Shoot" game has been improved
+to periodically switch off the power of the OLED display, which better
+protects the display from burn-in. The affected file is tunnel.c.
+
+Finally, this release introduces the QP_VERSION macro, which identifies the QP
+version. Otherwise, this maintenance release does not change the QP/C API in
+any way, so the release has NO IMPACT on the QP/C applications except for the
+ARM Cortex ports and applications.
+
+
+\section qpc_4_1_02 Version 4.1.02 (Product) Release date: Jan 14, 2010
+
+The purpose of this minor maintenance release is the change in the directory
+structure for the ARM Cortex ports and examples. As new ARM Cortex cores are
+becoming available, the old port name "cortex-m3" could be misleading, because
+it actually applies to wider range of ARM Cortex cores. Consequently, all ARM
+Cortex ports and examples are hosted in the directory tree called
+"arm-cortex".
+
+This maintenance release does not change the QP/C API in any way, so the
+release has NO IMPACT on the QP/C applications except for the ARM Cortex
+ports and applications.
+
+
+\section qpc_4_1_01 Version 4.1.01 (Product) Release date: Nov 05, 2009
+
+The main purpose of this release is to replace the Turbo C++ 1.01 toolset
+with the Open Watcom C/C++ toolset, because Turbo C++ 1.01 is no longer
+available for a free download. In contrast, Open Watcom is distributed under
+an OSI-certified open source license, which permits free commercial and
+non-commercial use. Open Watcom can be downloaded from www.openwatcom.org.
+
+All 80x86/DOS, 80x86/qk, and 80x86/ucos2 ports and examples for Turbo C++ 1.01
+have been replaced with ports and examples for Open Watcom. The make.bat
+scripts are provided to build the QP/C libraries and examples.
+
+In the process of converting the examples to Open Watcom two new examples
+have been added to the standard QP/C distribution. The Calc2 example
+located in &lt;qpc&gt;/examples/80x86/dos/watcom/l/calc2 shows how to derive
+state machine classes with QP 4.x. The SLS example located in
+&lt;qpc&gt;/examples/80x86/dos/watcom/l/sls shows the implemenation of the
+new State-Local Storage state design pattern.
+
+
+\section qpc_4_1_00 Version 4.1.00 (Product) Release date: Oct 09, 2009
+
+The release brings a number of improvements to QP/C and updates the QP/C ARM
+Cortex-M3 examples for the EK-LM3S811 board to the latest IAR EWARM 5.40.
+
+This maintenance release does not change the QP/C API in any way, so the
+release has NO IMPACT on the QP/C applications.
+
+The main changes in QP v4.1.00 with respect to earlier versions are as
+follows:
+
+- in qs.h added a new trace record QS_QEP_DISPATCH logged when an event is
+dispatched to a state machine. This timestamped trace record marks the
+beginning of an RTC step. The end of the RTC step is marked by the existing
+timestamped trace records QS_QEP_INTERN_TRAN, QS_QEP_INIT_TRAN, and
+QS_QEP_IGNORED, depending on how the event is handled. The new QS_QEP_DISPATCH
+record facilitates measurement of the RTC step lengths.
+- in qhsm_dis.c added generation of the QS_QEP_DISPATCH trace record.
+- in the tools/qspy/ sub-directory added output of the new trace record to the
+Q-SPY host application.
+- in the tools/qspy/matlab/ sub-directory added processing of the new trace
+record to the qspy.m script.
+- in qpset.h changed the implementation of the Priority Set. In particular,
+the QPSet64 now derives from QPSet8, which enables a common way of testing for
+non-empty set (e.g., useful in assembly). Also, the findMax() functions in
+QPSet8 and QPSet64 now can work with an empty set, in which case they return
+0.
+- in qk_sched.c simplified the QK_schedule_() function to skip the testing
+of the ready-set for non-empty condition. Such test is no longer necessary.
+The test can still be performed outside the QK_schedule_() function (e.g., in
+assembly) to avoid calling the scheduler if the ready set is empty.
+- in qk_ext.c simplified the QK_scheduleExt_() function in the same way as
+QK_schedule_().
+- modified make.bat files for building QP libraries in the ports/ directory
+to use the externally defined environment variables for the location of the
+toolchains. The defaults are applied only when the environment variable is
+not defined. This enables greater flexibility in installing the development
+tools in different directories than those chosen by Quantum Leaps.
+- modified the ARM Cortex-M3 examples for the new IAR EWARM 5.40.
+- modified slighlty the Calculator example to allow extensibility.
+- in the ARM Cortex-M3 port file qk_port.s added explicit testing of the
+QK_readySet_ set for empty condition. This test allows avoiding calling the QK
+scheduler and two contex-switches if the ready-set is empty.
+- in the game example moved setting up the QS filters from main.c to bsp.c.
+
+
+\section qpc_4_0_04 Version 4.0.04 (Product) Release date: Apr 09, 2009
+
+The maintenance release provides a fix for the compile-time assertions,
+which did not work correctly for the GNU compiler family. Also, the ARM
+Cortex-M3 examples have been recompiled with the newer IAR EWARM v5.30.
+
+This maintenance release does not change the QP/C API in any way, so the
+release has NO IMPACT on the QP/C applications.
+
+The main changes in QP v4.0.04 with respect to earlier version are as follows:
+
+- in qassert.h file the #Q_ASSERT_COMPILE macro has been modified to render
+a negative array dimension when the asserted condition is not TRUE.
+
+
+\section qpc_4_0_03 Version 4.0.03 (Product) Release date: Dec 27, 2008
+
+The main purpose of this release is to fix a bug in the QK preemptive kernel,
+which occurs only when the advanced QK features are used. Specifically, the QK
+priority-ceiling mutex could interfere with QK thread-local storage (TLS) or
+QK extended context switch. When the QK mutex is in use, the TLS or the
+extended context for this task could get saved to an incorrect priority level.
+
+The release 4.0.03 fixes the bug by strictly preserving the semantics of
+QK_currPrio_ variable. The mutex locking now uses a different variable
+QK_ceilingPrio_, which represents the ceiling-priority locked by the mutex.
+The QK scheduler and extended scheduler now perform an additional check to
+make sure that only tasks with priorities above the ceiling can run. To avoid
+that additional overhead, the user can define the macro QK_NO_MUTEX, which
+eliminates the QK mutex API and eliminates the additional tests in the QK
+schedulers.
+
+This maintenance release does not change the QP/C API in any way, so the
+release has NO IMPACT on the QP/C applications.
+
+The main changes in QP v4.0.03 with respect to earlier version are as follows:
+
+- in qk.h file made the QK mutex API only visible when the macro QK_NO_MUTEX
+is *not* defined.
+- in qk_pkg.h file, added the QK_ceilingPrio_ external declaration when the
+macro QK_NO_MUTEX is not defined.
+- in qk_mutex.c file, changed priority-ceiling mutex implementation to use
+the QK_ceilingPrio_ instead of QK_currPrio_. Also, added compiler error when
+the macro QK_NO_MUTEX is definedthis and this file is included in the build.
+- in qk_sched.c file added testing priority against the QK_ceilingPrio_,
+when the macro QK_NO_MUTEX is not defined.
+- in qk_ext.c file added testing priority against the QK_ceilingPrio_,
+when the macro QK_NO_MUTEX is not defined.
+
+
+\section qpc_4_0_02 Version 4.0.02 (Product) Release date: Nov 15, 2008
+
+This maintenance release does not change the QP/C API in any way, so the
+release has NO IMPACT on the QP/C applications.
+
+The main changes in QP v4.0.02 with respect to earlier version are as follows:
+
+- in qep.h file, added comments to macros Q_TRAN() and Q_SUPER() to suppress
+the PC-lint warining about using the comma-operator (MISRA rule 42).
+- in qhsm_in.c file, fixed a bug in the QHsm_isIn() function.
+- fixed a bug in tunnel.c file ("Fly 'n' Shoot" game). The constant event
+HIT_WALL was not declared static.
+
+
+\section qpc_4_0_01 Version 4.0.01 (Product) Release date: June 09, 2008
+
+This maintenace release is made to allow using QS software tracing with
+the GNU compiler for AVR (WinAVR). Specifically, the output of the strings
+residing in ROM has been fixed.
+
+This maintenance release does not change the QP/C API in any way, so the
+release has NO IMPACT on the QP/C applications.
+
+The main changes in QP v4.0.01 with respect to earlier version are as follows:
+
+- in qs_.c file, updated the function QS_str_ROM_().
+- in qs_str.c file, updated the function QS_str_ROM().
+- in qvanilla.c file, funciton QF_run(), declared the temporary variables
+as static to save stack space, because QF_run() never returns and is not
+reentrant.
+
+
+\section qpc_4_0_00 Version 4.0.00 (Product) Release date: Apr 07, 2008
+
+This milestone release is made for the book /ref PSiCC2. The book describes in
+great detail this new release. The older "QP Programmer's Manual" is now
+phased out and is replaced with this hyper-linked
+/ref main_page "QP/C Reference Manual", which provides very detailed, easily
+searchable reference to the software. The book /ref PSiCC2 provies in-depth
+discussion of the relevant concepts as well as the design study of QP v4.0.
+
+The main changes in QP v4.0 with respect to earlier versions are as follows:
+
+- the coding techniques for hierarchical state machines (HSMs) and the simpler
+finite state machines (FSMs) have changed. While the changes are quite simple,
+the backward compatibility with QEP 3.x has been broken, meaning that some
+manual changes to the state machines implemented with earlier versions are
+necessary. Please refer to the "QP/C Tutorial" Section /ref coding_hsm for
+more information about coding state machines with QEP 4.x.
+    - The main change is the signature of a state-handler function, which now
+    returns simply a byte. This return type (typedef'ed as QState) is the
+    status of the event-handling that the state handler conveys to the QEP
+    event processor.
+    - The macro #Q_TRAN() must now always follow the return statement.
+    - The new macro #Q_SUPER() designates the superstate of the given state.
+    Again, this macro must follow the return statement.
+    - Then two new macros #Q_HANDLED() and #Q_IGNORED() have been added to
+    return the status of event handled and event ignored, respectively.
+
+- all callback functions are now consistently called /c #XXX_onYYY():
+    - Q_assert_handler() is now Q_onAssert()
+    - QF_start() is now QF_onStartup()
+    - QF_cleanup() is now QF_onCleanup()
+
+- the new header file qevent.h has been broken off the qep.h header file.
+qevent.h contains the QEvent class and other basic facilities used in the
+whole QP. This new file allows easier replacement of the entire QEP event
+processor with custom event processors, if you wish do so.
+- the macro QEP_SIGNAL_SIZE is renamed to #Q_SIGNAL_SIZE.
+- the data type QSTATE is now deprecated. Please use QState.
+- the "protected" in C don't no longer have the trailing underscore. For
+example, QHsm_ctor_() is replaced with #QHsm_ctor(), etc.
+- the #QF_FSM_ACTIVE macro is now deprecated. Instead, you have the family of
+macros #QF_ACTIVE_SUPER_, #QF_ACTIVE_CTOR_, #QF_ACTIVE_INIT_,
+#QF_ACTIVE_DISPATCH_, #QF_ACTIVE_STATE_, which allow replacing the base class
+for active objects in QF. By default, these macros are defined to use the QHsm
+class from the QEP hierarchical event processor, but you can replace the event
+processor, if you wish.
+- the internal macro QACTIVE_OSOBJECT_WAIT_() is now #QACTIVE_EQUEUE_WAIT_().
+- the internal macro QACTIVE_OSOBJECT_SIGNAL_() is now
+#QACTIVE_EQUEUE_SIGNAL_().
+- the internal macro QACTIVE_OSOBJECT_ONIDLE_() is now
+#QACTIVE_EQUEUE_ONEMPTY_().
+- the data mebers QActive.osObject and QActive.thread are now present only if
+the macros #QF_OS_OBJECT_TYPE and #QF_THREAD_TYPE are defined.
+- the QPSet class has been renamed to QPSet64.
+- the QPSet_hasElements() has been renamed QPSet64_notEmpty()
+- the QS software tracing is now better integrated with all QP components. You
+no longer need to explicitly include qs_port.h, because it is automatically
+included when you define the macro #Q_SPY. Also the file qs_dummy.h is
+included automatically when the macro #Q_SPY is <STRONG>not</STRONG> defined.
+- the new header file qvanilla.h now replaces the file qsched.h.
+- the file qa_ctor.c is now obsolete.
+- the macros QF_SCHED_LOCK() and QF_SCHED_UNLOCK() are now obsolete.
+- the native QF event queues (both the active object event queues and the
+"raw" thread-safe queues) are slightly more efficient by counting down the
+head and tail pointers rather than up. This leads to wrap-around at zero,
+which is easier (faster) to test than any other wrap-around point. Also the
+native QF event queues maintain the minimum of the free events in the queue
+rather the maximum of used events.
+- the data member of QEQueue.nTot class is removed.
+- the QF_publish() function has been re-written so that QF no does <STRONG>not
+need to lock the scheduler</STRONG>. The QF_publish() function posts events
+to active objects with scheduler unlocked starting from the highest-priority
+active objects. However, the event is protected from inadvertent recycling by
+incrementing its reference counter before the publish operation. After the
+event  is posted to all subscribers, the garbage collector QF_gc() is called
+to decrement the reference counter and recycle the event, if necessary.
+- the qf_run.c file is obsolete. The QF_run() function for the cooperative
+"vanilla" kernel is now implemented in the file qvanilla.c.
+- the QF_tick() function has been rewritten to allow calling QF_tick() from
+the task context as well as from the interrupt context. The nested critical
+section around QF_tick() is no longer needed when it is called from the task
+level. Among others, this re-design <STRONG>eliminates the need for the
+recursive</STRONG> mutex in the POSIX QF port.
+- the QMPool_init() function has been re-designed to optimally align the
+memory buffer in a portable and platform-independent way. This should bring
+some performance improvements on some CPUs (e.g., 80x86).
+- the extended QK scheduler has been re-designed to save stack space. The
+extended context (e.g., coprocessor registers) are no longer saved on the
+precious stack, but rather in the active object.
+- a bug has been fixed in handling of Thread-Local Storage (TLS) in the QK
+scheduler and extended scheduler.
+
+- the -q (quiet) flag has been added to the QSPY host application.
+- the support for two new compilers for Windows has been added for the QSPY
+host application. The application can now be build with the MinGW GNU compiler
+for Windows as well as the Microsoft Visual C++ 2005.
+
+- the QP port to Linux has been improved by eliminating the need for recursive
+P-Thread mutex.
+
+- the QP port to MicroC/OS-II has been upgraded to the latest version 2.86.
+
+- all examples in the standard QP distribution have been cleaned up and
+updated to the latest QP API changes.
+- all examples that use QF now contain the QS software tracing support.
+
+
+\section qpc_3_4_01 Version 3.4.01 (Product)
+Release date: Sep 25, 2007
+
+This product release adds the backward-compatibility layer so that previous
+QP/C ports continue to work with the new version.
+
+This product release also comes with the updated "QP Programmer's Manual",
+which now includes the QS target component and the QSpy host application.
+
+
+\section qpc_3_4_00 Version 3.4.00 (Beta)
+Release date: Sep 03, 2007
+
+This release brings several changes with the overall goal of simplifying and
+improving consistency across the whole QP family of frameworks (QP/C, QP/C++,
+and QP-nano).
+
+This release includes simplifying of the C naming conventions (see the
+updated Application Note <a
+href="http://www.state-machine.com/doc/AN_QL_Coding_Standard.pdf">"QL C/C++
+Coding Standard"</a>). The double-underscore suffix for private data members
+of structures is no longer used. Single underscore is used still only for
+internal QP/C facilities that typically should not be used by the application
+programmer.
+
+The main changes are made to the QEP component. The "static transition
+optimization" has been removed altogether. This simplifies significantly the
+state machine structure (which now contains just the currently active state).
+Also, the efficiency is improved for processing the dynamic transitions and
+the stack usage is lower. This change brings the QEP/C implementation much
+closer to QEP-nano.
+
+The other big change in this release is including the Quantum Spy (QS)
+component in the distribution. Previously, the QS component was available only
+under the commercial licensing. It is now open source, just as the rest of QP.
+
+In, the QF/C component, the QTimerEvt_publishIn() and QTimeEvt_publishEvery()
+have been removed, because they introduced a coupling between time events and
+publish-subscribe. This is undesirable for projects that do not want to
+include the publish-subscribe facilty.
+
+Finally, the revision history for individual QP/C components has been moved
+from the header files and is now consolidated in the header file
+doxygen/qpc_rev.h.
+
+
+\section qpc_3_3_01 Version 3.3.01 (Product)
+Release date: Mar 17, 2007
+
+The main change in this release is removing the 'const' declaration
+of two temporary variables inside QHsm_dispatch() and QHsm_tran() functions.
+This was necessary to compile the code with the MPLAB C18 compiler for PIC18
+devices.
+
+Other minor changes include adding the 'U' suffix (unsigned) to several
+numerical literals to avoid MPLAB C18 compiler warnings.
+
+The changes in release 3.3.01 have NO impact on the existing QP/C ports.
+
+-# in file qhsm_dis.c:80 removed 'const' from the declaration of '*c'.
+-# in file qhsm_tra.c:69 removed 'const' from the declaration of 'src'.
+-# in file qep.c changed the version number to "3.3.01".
+-# added the 'U' suffix to several numerical literals in files:
+qa_defer.c, qa_usuba.c, qf_gc.c, qf_pool.c, qf_run.c
+-# in file qf_act.c changed the version number to "3.3.01".
+-# added the cast to (uint8_t) to several numerical literals in the file qk.c.
+-# in file qk.c changed the version number to "3.3.01".
+-# added the 'U' suffix to several numerical literals in file qs.h.
+-# in files qs_.c and qs_str.c added explicit casting to (char const).
+-# in file qs.c changed the version number to "3.3.01".
+
+
+\section qpc_3_3_00 Version 3.3.00 (Product)
+Release date: Jan 22, 2007
+
+The main change in this release is removing #include <stdint.h> from the
+qep.h header file. This has been done becasue vast majority of embedded
+compilers for small MCUs actually do not provide the C-99 Standard header
+file <stdint.h>. Worse, compilers such as Freescale HC(S)08 C/C++ compiler
+will not include <stdint.h> unless it's in the compilers's include directory,
+even though the "stdint.h" file might be in the compiler include path.
+
+Removing the "#include <stdint.h>" from qep.h header file allows more
+flexibility in the way the standard exact-width integer types are defined.
+For compilers that do not provide the <stdint.h> file, you provide the
+typedef's in the qpc_port.h file before including qep.h. For compilers
+that do provide the <stdint.h> header file, you simply include this file
+in the qpc_port.h header file before including qep.h.
+
+The changes in release 3.3.00 have impact on all QP ports, because you need
+to modify the qpc_port.h file in all these ports.
+
+The other significant change in this release is adding the macro #Q_ROM_VAR
+for all constant objects allocated in ROM. The #Q_ROM_VAR macro has been
+added for the compilers like Freescale HC(S)08, which require far pointers
+to access the objects in ROM. Please note that specifying the pointer size
+for accessing a ROM objects is syntactically different than specifying
+that the object is allocated in ROM (see macro #Q_ROM).
+
+Finally, in release 3.3.00 the build strategy for QP ports has been
+simplified as well. Instead of separate Makefile for every QP component,
+such as QEP, QF, QK, and QS, not the "ports" directory contains a batch
+file "make.bat" that builds all the libraries at once.
+
+
+-# in file qep.h removed "#include <stdint.h>".
+-# in file qassert.h added macro #Q_ROM_VAR for objects allocated in ROM
+and to signatures of functions accessing these objects.
+-# in file qep.h added macro #Q_ROM_VAR for objects allocated in ROM
+and to signatures of functions accessing these objects.
+-# in file qep.h added default empty definitions and Doxygen comments for
+macros #Q_ROM and #Q_ROM_VAR.
+-# in file qep.c added macro #Q_ROM_VAR for objects allocated in ROM
+and to signatures of functions accessing these objects.
+-# in file qf.c added macro #Q_ROM_VAR for objects allocated in ROM
+and to signatures of functions accessing these objects.
+-# in file qk.c added macro #Q_ROM_VAR for objects allocated in ROM
+and to signatures of functions accessing these objects.
+-# in file qep.c added Q_ROM_VAR to the signature of QEP_getVersion().
+-# in file qep.c changed the version number to "3.3.00".
+-# in file qf.h added macro #Q_ROM_VAR for objects allocated in ROM
+and to signatures of functions accessing these objects.
+-# in file qf.h removed method QF_getTime() and deleted external variable
+QF_tickCtr_.
+-# deleted obsolete file qa_fifo_.c
+-# deleted obsolete file qa_lifo_.c
+-# deleted obsolete file qf_time.c
+-# in file qf_act.c added Q_ROM_VAR to the signature of QEP_getVersion().
+-# in file qf_log2.c added Q_ROM_VAR to the definition of the lookup table.
+-# in file qf_pwr2.c added Q_ROM_VAR to the definition of the lookup tables.
+-# in file qf_tick.c removed incrementing QF_tickCtr_.
+-# In file qf_act.c updated version number to 3.3.00
+-# in file qk.h added macro #Q_ROM_VAR for objects allocated in ROM
+and to signatures of functions accessing these objects.
+-# In file qk.c added #Q_ROM_VAR to the signature of QK_getVersion().
+-# In file qk.c updated version number to 3.3.00
+-# in file qs.h added macro #QS_ROM_VAR for objects allocated in ROM
+and to signatures of functions accessing these objects.
+-# In file qs.h added default definitions of the QS macros #Q_ROM,
+#Q_ROM_VAR, and Q_ROM_BYTE.
+-# In file qs.h added declaration of QS_tickCtr_.
+-# In file qs.c added #Q_ROM_VAR to the signature of QS_getVersion().
+-# In file qs_.c added #Q_ROM_VAR to the signature of QS_str_ROM_().
+-# In file qs_.c added definition of QS_tickCtr_.
+-# In file qs_str.c added #Q_ROM_VAR to the signature of QS_str_ROM().
+-# In file qs.c updated version number to 3.3.00
+-# Updated the "QP Programmer's Manaul" to Revision E
+
+
+\section qpc_3_2_05 Version 3.2.05 (Product)
+Release date: Dec 08, 2006
+
+This QF release rolls back the changes made to the reference-counting
+policy. The reference count of a dynamic event is incremented
+when the event is posted, but is NOT decremented when the event is
+retreived from the queue. The reference count is decremented only later,
+in the garbage collector (QF_gc()).
+
+This release adds direct support for event deferral (the "Deferred Event"
+state pattern) through methods QActive_defer_() and QActive_recall_().
+
+Also this release adapts the QS code to the specifics of
+the Keil C51 compiler for 8051/251. In particular, the C51 compiler treats
+the identifier "data" as an extended keyword. To make the QS code compile
+with C51, all "data" used as a formal function parameter have been renamed.
+Additionally, this release fixes a minor bug in the #QS_FUN_DICTIONARY macro.
+
+-# In file qf.h added methods QActive_defer_() and QActive_recall_().
+-# In file qa_get_.c removed decrementing the reference count of a
+dynamic event.
+-# In file qeq_get.c removed decrementing the reference count of a
+dynamic event.
+-# In file qf_gc.cpp restored decrementing of the reference count of a
+dynamic event.
+-# Added new file qa_defer.c that implements QActive_defer_() and
+QActive_recall_().
+-# In file qf_act.c updated version number to 3.2.05
+-# In file qs.h removed all instances of indentifier "data"
+-# In file qs.h fixed a bug in the definition of macro #QS_FUN_DICTIONARY.
+-# In file qs_.c renamed all instances of identifier "data".
+-# In file qs_f32.c renamed all instances of identifier "data".
+-# In file qs_f64.c renamed all instances of identifier "data".
+-# In file qs.c, in functions QS_filterOn() and QS_filterOff() moved the
+declaration of the temporary variable 'i' from the inner scope to the
+function scope. The C51 compiler was crushing with variables at inner scope.
+-# In file qs.c updated version number to 3.2.05
+-# Updated the "QP Programmer's Manaul" to Revision D
+
+
+\section qpc_3_2_04 Version 3.2.04 (Beta)
+Release date: Dec 01, 2006
+
+This QF release changes the internal policy of reference-counting for
+dynamic events. The reference count of a dynamic event is now incremented
+when the event is posted to a queue and decremented when the event is
+later retreived from the queue. This policy pertains to both active
+object queues and native QF thread-safe queues (QEQueue).
+
+Previously, the reference count of a dynamic event was not decremented
+upon retreival of the event from the event queue, but rather in the
+garbage collector (QF_gc()).
+
+This QK release adds two new features in QK.
+
+The first feature added is the extended context switch for CPUs with
+co-processors, such as the x87 FPU accompanying the x86 CPU. As a fully-
+preemptive kernel, QK needs to save and restore the context of the co-
+processor accrosss the asynchronous preemption. This QK release adds
+a generic mechanism for saving and restoring extened context in the
+extended scheduler (QK_scheduleExt_()), which is used only at the
+exit from the interrupts (asynchronous preemptions).
+
+The second feature added is the Thread-Local Storage (TLS) for reentrant
+libraries, such as the NewLib. This feature allows assigning per-thread
+memory and providing a hook (callback) activated at every context switch.
+
+-# In file qf.h eliminated methods QActive_postFIFO_() and
+QActive_postLIFO_().
+-# In file qf.h changed method QActive_get__() to QActive_get_() (protected
+scope) to make it available to various thread-run routines.
+-# In file qa_fifo.c changed the implementation of QActive_postFIFO()
+to represent the native QF event queue of an active object.
+-# In file qa_fifo_.c removed the implementation of QActive_postFIFO__()
+and declared the file obsolete (will be removed in future releases).
+-# In file qa_lifo.c changed the implementation of QActive_postLIFO()
+to represent the native QF event queue of an active object.
+-# In file qa_lifo_.c removed the implementation of QActive_postLIFO__()
+and declared the file obsolete (will be removed in future releases).
+-# In file qa_get_.cpp added decrementing the reference count of a
+dynamic event.
+-# In file qf_gc.c removed decrementing of the reference count of a
+dynamic event. Also changed the test for recycling an event (reference
+count of zero).
+-# In file qf_pspub.c removed incrementing the reference count of a
+dynamic event.
+-# Removed all uses of the macros #QACTIVE_POST_FIFO_, #QACTIVE_POST_LIFO_,
+and QACTIVE_GET_. These macros are made now obsolete.
+-# In file qsched.h removed definitions of the obsolete macros
+#QACTIVE_POST_FIFO_, #QACTIVE_POST_LIFO_, and QACTIVE_GET_.
+-# In file qf_pspub.c replaced the macro QACTIVE_POST_FIFO_() with the direct
+call to the function QActive_postFIFO(QF_active_[p], e).
+-# In file qf_tick.c replaced the macro QACTIVE_POST_FIFO_() with the direct
+call to the function QActive_postFIFO(QF_active_[p], e).
+-# Changed the uC/OS-II port to reflect new policy of handling reference
+counters inside the dynamic events. Also removed files qa_fifo.c and
+qa_lifo.c from the uC/OS-II build.
+-# In file qf_act.c updated version number to 3.2.04
+-# In file qk.h updated revision history and added the prototype for the
+extended scheduler QK_scheduleExt_(). This scheduler implements the
+generic extended context via macros #QK_EXT_TYPE, #QK_EXT_SAVE, and
+#QK_EXT_RESTORE.
+-# In file qk.h removed definitions of the obsolete macros
+#QACTIVE_POST_FIFO_, #QACTIVE_POST_LIFO_, and QACTIVE_GET_.
+-# In file qk_sched.c added logic for handling the TLS via the macro
+#QK_TLS.
+-# Added new file qk_ext.c with the definition of the extended scheduler
+QK_scheduleExt_().
+-# Added the file qk_ext.c to the Makefile for QK port to 80x86 with
+Turbo C++ 1.01.
+-# Extended the QK port to 80x86 with Turbo C++ 1.01 to handle the
+x87 FPU context.
+-# Extended the QDPP example for QK with Turbo C++ 1.01 to demonstrate
+threads that use the FPU and require the extended context switch.
+-# In file qk.c updated version number to 3.2.04
+-# Updated the "QP Programmer's Manaul" to Revision C
+
+
+\section qpc_3_2_03 Version 3.2.03 (Product)
+Release date: Nov 15, 2006
+
+The main purpose of this release is to adapt the code to the shortcomings of
+the gcc compiler for handling data in program ROM for Harvard architecture
+CPUs, such as the Atmel's AVR or the 8051. In such machines, the data space
+(RAM) and program space (ROM) are accessed with different instructions.
+The gcc compiler does not automatically synthesize the correct code for
+accessing data placed in the program ROM, even though
+__attribute__((__progmem__)) is used. The workaround for the gcc is to add
+special assembly instructions to transfer the data from the program space to
+the data space. This version of QP/C adds macros for each data element
+allocated to the program space (delcared with the Q_ROM attribute). Please
+note that commercial compilers, such as IAR, handle data allocated in the
+program space (ROM) correctly and do not need any workarounds.
+
+This release also fixes a few minor inconsistencies in the code (see the list
+below):/
+
+-# In file qf.h added default definition of macro #Q_ROM_BYTE
+-# In file qf_set.h added macro #Q_ROM_BYTE to access the lookup tables
+allocated in ROM (several places).
+-# In file qf_sched.h changed types QF_OS_OBJECT_TYPE and QF_THREAD_TYPE to
+uint8_t from int8_t
+-# In file qs_dummy.h added dummy definitions of some missing QS macros
+-# In file qa_sub.c added macro #Q_ROM_BYTE to access the lookup tables
+allocated in ROM (several places).
+-# In file qa_usub.c added macro #Q_ROM_BYTE to access the lookup tables
+allocated in ROM (several places).
+-# In file qf_usuba.c added macro #Q_ROM_BYTE to access the lookup tables
+allocated in ROM (several places).
+-# In file qf_pspub.c added macro #Q_ROM_BYTE to access the lookup tables
+allocated in ROM (several places).
+-# In file qf_act.c updated version number to 3.2.03
+-# In file qs_pkg.h added default definition of macro #Q_ROM_BYTE
+-# In file qa_sub.c added macro #Q_ROM_BYTE to access the lookup tables
+allocated in ROM (several places).
+-# In file qs_.c added macro #Q_ROM_BYTE to access the string allocated in ROM
+-# In file qs_str.c added macro #Q_ROM_BYTE to access the string allocated
+in ROM.
+-# In file qs.h changed the include file name from "qs_dummy" to "qs_dummy.h".
+-# In file qs.c updated version number to 3.2.03
+
+
+\section qpc_3_2_02 Version 3.2.02 (Product)
+Release date: Oct 30, 2006
+
+-# In file qs.h replaced macro Q_ROM with QS_ROM
+-# In file qs.h added methods QS_str_ROM_() and QS_str_ROM()
+-# In file qs.h added macros QS_STR_ROM_() and QS_STR_ROM()
+-# In file qs.h modified macros QS_???_DICTIONARY() to use ROM strings
+-# In file qs.h included qs_dummy.h instead of the dummy definitions
+   of the QS macros
+-# In file qs_pkg.h added #ifndef Q_SPY before definition of macro Q_SPY
+-# In file qs_.c added definition of the function QS_str_ROM_()
+-# In file qs_str.cpp added definition of the function QS_str_ROM()
+-# In file qs.c updated version number to 3.2.02
+
+
+\section qpc_3_2_01 Version 3.2.01 (Product)
+Release date: Sep 01, 2006
+
+-# In file qep.c updated version number to 3.2.01
+-# Added makefiles for building ports of all QP/C libraries at once.
+-# Created the consolidated manual "QP/C Programmer's Manual".
+-# In file qf_act.c updated version number to 3.2.01
+-# Added makefiles for building ports of all QP/C libraries at once.
+-# Created the consolidated manual "QP/C Programmer's Manual".
+-# In file qk.c updated version number to 3.2.01
+-# Added makefiles for building ports of all QP/C libraries at once.
+-# In file qs.c updated version number to 3.2.01
+-# In file qs.c removed superfluous semicolons after QS_INSERT...() macros
+-# In file qs_.c removed superfluous semicolons after QS_INSERT...() macros
+-# In file qs_str.c removed superfluous semicolons after QS_INSERT...() macros
+-# In file qs_mem.c removed superfluous semicolons after QS_INSERT...() macros
+-# In file qs_f32.c removed superfluous semicolons after QS_INSERT...() macros
+-# In file qs_f64.c removed superfluous semicolons after QS_INSERT...() macros
+-# Added makefiles for building ports of all QP/C libraries at once.
+-# Created the consolidated manual "QP/C Programmer's Manual".
+
+
+\section qpc_3_2_00 Version 3.2.00 (Product)
+Release date: Aug 07, 2006
+
+-# In file qep.h added the default definition of Q_ROM in case it's not
+defined by the user.
+-# In file qassert.h added the macro Q_ROM to allocate constant strings
+to ROM.
+-# In file qep.c updated version number to 3.2.00
+-# Updated the "QEP/C Programmer's Manual".
+-# In file qf.h changed the semantics of the QF_onIdle() callback.
+This callback is now invoked with interrupts LOCKED from the non-preemptive
+scheduler used in the "vanilla" QF ports to "bare metal" target boards.<br>
+<br>
+The modification changes the responsibilities of QF_onIdle(), which now MUST
+at least unlock interrupts. A failure to unlock interrupts in QF_onIdle()
+will leave the interrupts locked all the time and would prevent the
+application from running.<br>
+<br>
+Also, the signature of QF_onIdle() now depends on the interrupt locking
+policy. In case of the "save and restore interrupt status" policy, the
+QF_onIdle() callback takes the interrupt lock key as parameter (to be able
+to unlock the interrups correctly).
+-# In file qf.h used the macro Q_ROM to allocate constant objects
+to ROM (/sa qep.h). Objects allocated to ROM are: the version strings, and
+the lookup tables (QF_log2Lkup[], QF_pwr2Lkup[], QF_invPwr2Lkup, and
+QF_div8Lkup[].
+-# Added new platform-independent header file qsched.h to provide the
+interface to the simple non-preemptive scheduler used in the "vanilla" ports
+of QF to "bare metal" targets. This header file is only applicable to the
+"vanilla" ports.
+-# Added new platform-independent implementation file qf_run.c to
+implement the simple non-preemptive scheduler used in the "vanilla" ports
+of QF to "bare metal" targets. This implementation file eliminates the need
+for qf_port.c file in the "vanilla" ports of QF. Also, the qf_run.c module
+should only be placed in the QF library in the vanilla QF ports.
+-# Simplified all "vanilla" ports of QF to use the common platform-
+independent implementation provided in qf_run.c.
+-# Updated QF_onIdle() callback in all examples of "vanilla" ports of QF to
+unlock interrupts.
+-# Modified file qf_pspub.c to allow allocating a temporary stack variable
+inside the macro QF_SCHED_LOCK(). This change is related to modification in
+QK v 3.2.00.
+-# Updated the "QF/C Programmer's Manual".
+-# in file qk.h added new idle callback QK_onIdle(), which in contrast
+to QF_onIdle() is invoked with interrupts unlocked.
+-# in file qk.h removed QK_schedLock()/QK_schedUnlock() and replaced them
+with QK_mutexLock()/QK_mutexUnlock(), with the semantics of returning the
+mutex.
+-# in file qk.h changed the definitions of macros #QF_SCHED_LOCK/
+#QF_SCHED_UNLOCK to use the new QK mutex API.
+-# In file qk.h used the macro Q_ROM to allocate constant objects
+to ROM (/sa qep.h).
+-# in file qk.h added the typedef for QMutex.
+-# in file qk.c replaced the callback QF_onIdle() with the new one
+QK_onIdle().
+-# removed source file qk_lock.c
+-# added source file qk_mutex.c
+-# in file qk.c changed the version number to 3.2.00
+-# Updated "QK/C Programmer's Manual"
+-# In file qs.h replaced QS_QK_SCHED_LOCK/UNLOCK with QS_QK_MUTEX_LOCK/UNLOCK.
+Also, changed data accompanying the trace records QS_QK_MUTEX_LOCK/UNLOCK.
+-# In file qs.h used the macro Q_ROM to allocate constant objects
+to ROM (/sa qep.h).
+-# in file qs.c changed the version number to 3.2.00
+-# Updated "QS/C Programmer's Manual" in PDF.
+
+
+\section qpc_3_1_06 Version 3.1.06 (Product)
+Release date: Jul 14, 2006
+
+-# In file qf.h added function QF_stop() to be called from the application
+code to stop the framework.
+-# In file qf.h added callback function QF_cleanup() to be called from the
+QF port to cleanup before exiting to the OS.
+-# In file qf.h deprecated the function QF_exit().
+-# In file qk_sched.c removed unlocking of interrupts upon exit from
+QK_schedule_(). Now QK_schedule_() enters and exits with interrupts LOCKED.
+-# In file qk.h modified macro QACTIVE_OSOBJECT_SIGNAL_() to always unlock
+the interrupts, regardless if QK_schedule_() has been called or not.
+-# In file qk.c added unlocking interrupts after the call to QK_SCHEDULE_()
+in the function QF_run().
+-# In file qk_lock.c modified the function QK_schedUnlock() to always unlock
+the interrupts upon exit.
+-# Updated licensing information.
+-# Updated "QS Programmer's Manual" in PDF.
+
+
+\section qpc_3_1_05 Version 3.1.05 (Product)
+Release date: Feb 08, 2006
+
+-# In file qf_act.c added the Revision History Doxygen comment, which was
+previously in doxygen/qp.h
+-# In file qf.h augmented comment for QF_run() to cover the case when QF is
+used with QK.
+-# In file qf.h added the extern declarations of ::QF_tickCtr_,
+::QF_intLockNest, and ::QF_isrNest_, which were previously declared
+in qf_pkg.h.
+-# In file qf.h added macros #QF_QS_INT_LOCK, #QF_QS_INT_UNLOCK(),
+#QF_QS_ISR_ENTRY, and #QF_QS_ISR_EXIT, which were previously declared
+in qs_port.h.
+-# In file ports/linux/gcc/qf_port.h added extern uint8_t QF_running_.
+-# In file qf/80x86/dos/tcpp101/l/qf_port.c replaced deprecated
+QPSet_hasElements() to QPSet_isEmpty().
+-# In file qf/80x86/linux/gcc/qf_port.c added QF_run()
+-# In file qeq_init.c:186 changed QS_OBJ(me) to QS_OBJ(qSto) to consistently
+refer to a queue by the ring buffer object
+-# In file qf_pkg.h removed extern ::QF_tickCtr_.
+-# In file qk.h removed extern QK_intLockNest_ and QK_isrNest_. These
+counters have been moved to QF and renamed in the process to QF_intLockNest_
+and QF_isrNest_, respectively.
+-# In file qk.h added QS instrumentatin to #QF_INT_LOCK and #QF_INT_UNLOCK
+macros for tracing interrupt locking/unlocking. The QS interrupt locking/
+unlocking instrumentation has been previously added at the QK port level.
+-# In file qk.h removed macros QK_QS_INT_LOCK()/ QK_QS_INT_UNLOCK(),
+QK_QS_ISR_ENTRY()/ QK_QS_ISR_EXIT(). These macros have been moved to QF and
+renamed in the process to QF_QS_INT_LOCK()/ QF_QS_INT_UNLOCK(),
+QF_QS_ISR_ENTRY()/ QF_QS_ISR_EXIT(), respectively.
+-# In file ports/80x86/qk/tcpp101/l/qk_port.h simplified the definition
+of the macros #QK_INT_LOCK/ #QK_INT_UNLOCK to NOT contain the QS
+instrumenation.
+-# In file ports/80x86/qk/tcpp101/l/qk_port.h changed the definitions of
+#QK_ISR_ENTRY and #QK_ISR_EXIT to use #QF_QS_ISR_ENTRY/ #QF_QS_ISR_EXIT.
+-# In file qk.c added the Revision History Doxygen comment
+-# In file qk_pkg.h changed the definition of internal QK macros
+#QK_INT_LOCK_/ #QK_INT_UNLOCK_ to use the QS-instrumented #QF_INT_LOCK/
+#QF_INT_UNLOCK.
+-# In file qk_lock.c corrected a comment
+-# In file qk_sched.c corrected a comment
+-# Provided "QS/C Programmer's Manual" in PDF.
+-# In file qs.h changed around the pre-defined records. Added records:
+QS_QF_INT_LOCK, QS_QF_INT_UNLOCK, QS_QF_ISR_ENTRY, QS_QF_ISR_EXIT. Removed
+records QS_QK_INT_LOCK, QS_QK_INT_UNLOCK, QS_QK_ISR_ENTRY, QS_QK_ISR_EXIT.
+-# In file qs.h renamed functions QS_filterIn()/ QS_filerOut() to
+QS_filterOn()/ QS_filerOff(). Correspondingly, changed macros QS_FILTER_IN(),
+QS_FILTER_OUT(), to QS_FILTER_ON(), QS_FILTER_OFF().
+-# In file qs.h changed the signature and semantics of QS_getByte() to return
+QS_EOD (End-Of-Data).
+-# In file qs.h changed the signature of QS_getBlock() to take a pointer
+to uint16_t rather than uint32_t.
+-# In file qs.h eliminated the callback QS_newRecord()
+-# In file qs.h added new callback QS_flush()
+-# In file qs.h added application-level local filter object QS_apObj_.
+Consistently, added macro QS_FILTER_AP_OBJ() to set the new local filter.
+Consistently, added object argument to macros QS_BEGIN() and
+QS_BEGIN_NOLOCK().
+-# In files qs.c, qs_.c, qs_blk.c, qs_byte.c, qs_pkg.h renamed some variables
+and adjusted comments.
+-# Ported the QSpy host applicatoin to Linux. Added TCP/IP input to QSpy.
+Added new options.
+-# Added redesigned QS port to Linux with TCP/IP data link.
+
+
+\section qpc_3_1_04 Version 3.1.04 (Beta)
+Release date: Dec 08, 2005
+
+-# In file qmpool.h changed the definition of the #QF_MPOOL_SIZ_SIZE macro
+to remove the dependency on the #QF_EVENT_SIZ_SIZE. Macro #QF_EVENT_SIZ_SIZE
+might not be defined by the time qmpool.h is included.
+-# Added explicit definition of the configuration macro QF_EVENT_SIZ_SIZE to
+all qf_port.h files.
+-# Fixed a bug in function QMPool_init() (file qmp_init.c) by changing
+the type of variable n from uint8_t to QMPoolCtr. The uint8_t data type
+was failing for bigger block sizes.
+-# Added the QF_onIdle() callback to qf.h
+-# Improved comments in qpset.h
+-# Corrected dependencies in the Makefile for QDPP example
+(directory 80x86/dos/tcpp101/l and 80x86/dos/tcpp101/s)
+-# Added Linux QF port to the standard QF/C distribution.
+-# Released the "QF/C Programmer's Manual"
+-# Released "QK/C Programmer's Manual" in PDF.
+-# In file qk.h removed callbacks QK_init(), QK_start(), QK_idle(),
+QK_exit(), because they duplicate the QF callbacks.
+-# Modified qk.c to define the following QF "callbacks": QF_getPortVersion(),
+QF_run(), QActive_start(), and QActive_stop_().
+-# Added an argument to the signature of QK_schedLock() to allow selective
+QK scheduler locking up to the specified priority level.
+-# Changed the implementation of QK_schedLock() in file qk_lock.c.
+-# Eliminated the need for qf_port.c in the QF/C ports for QK.
+-# Simplified elements that go into qk_port.c in the QK/C ports.
+-# Added the ARM-Simulator port to the standard QK/C distribution.
+-# Cleaned-up the 80x86 QK port.
+
+
+\section qpc_3_1_03 Version 3.1.03 (Beta)
+Release date: Nov 18, 2005
+
+-# Added Doxygen documentation to the source code
+-# Added running__ member to the QActive structure
+-# Added QF_EVENT_SIZ_SIZE configuration macro and related data type
+QEventSize. Made the following changes to the signatures:
+void QF_poolInit(void *poolSto, uint32_t poolSize, QEventSize evtSize);
+QEvent *QF_new_(QEventSize evtSize, QSignal sig);
+-# Changed the name of protected function from QF_new() to QF_new_().
+-# Added the QK component (Beta)
+-# Added Doxygen documentation to the source code
+
+
+\section qpc_3_1_02 Version 3.1.02 (Beta)
+Release date: Feb 08, 2006
+
+-# In file qep.c added the Revision History Doxygen comment, which was
+previously in doxygen/qp.h
+-# updated the QBomb example to use the key events described in the
+"QEP/C Programmer's Manual"
+-# changed C++ comments to C-comments in main.c of the QHsmTst example
+
+
+\section qpc_3_1_01 Version 3.1.01 (Beta)
+Release date: Oct 18, 2005
+
+-# Removed <A HREF="http://www.state-machine.com/products/">Quantum
+Spy</A> (QS) dependency from the examples
+
+
+\section qpc_3_1_00 Version 3.1.00 (Beta)
+Release date: Oct 03, 2005
+
+-# Applied new directory structure desribed in
+<A HREF="http://www.state-machine.com/doc/AN_QP_Directory_Structure.pdf">
+Application Note: QP Directory Structure</A> -# Added <A
+HREF="http://www.state-machine.com/products/">Quantum Spy</A>
+instrumentation. -# Removed file qfsm_tra.c. -# Introduced file qfsm_dis.c. -#
+Applied new directory structure desribed in <A
+HREF="http://www.state-machine.com/doc/AN_QP_Directory_Structure.pdf">
+Application Note: QP Directory Structure</A> -# Added <A
+HREF="http://www.state-machine.com/products/">Quantum Spy</A>
+instrumentation.
+
+
+\section qpc_3_0_11 Version 3.0.11 (Beta)
+Release date: Aug 14, 2005
+
+-# Fixed potential race condition for static transitions
+-# Changed names of helper function QFsm_tran_()/QHsm_tran_() to
+QFsm_execTran()/QHsm_execTran() to match the QEP/C++ version.
+-# Added assertion in QHsm_execTran() to catch potential path[] array
+overrun that previously could go undetected.
+
+
+\section qpc_3_0_10 Version 3.0.10 (Beta)
+Release date: Aug 06, 2005
+
+This release contains completely redesigned Quantum Event Processor (QEP). The
+main focus is on compliance with standards (MISRA, Lint, Coding Standard),
+better portability, stack-use efficiency.
+
+-# This release includes a comprehensive "QEP/C v3.0 Programmer's Manual"
+in PDF.
+-# This release contains in-source comments for automatic generation of
+this Reference Manual with <A HREF="http://www.doxygen.org">doxygen</A>.
+-# This release includes re-packaging the code into much larger number of
+modules (.c files) with typically one function per module. This
+fine-granularity packaging allows for better automatic elimination of unused
+code at link time and fine-tuning by applying different compiler options to
+different files.
+-# This release is 98% compliant with the Motor Industry Software Reliability
+Association (MISRA) "Guidelines for the Use of the C Language in Vehicle Based
+Software", April 1998, ISBN 0-9524156-9-0 (see also See also
+http://www.misra.org.uk). A separate Application Note "QEP/C MISRA Compliance
+Matrix" contains detailed account how QEP/C compiles with the 127 MISRA rules
+(See http://www.state-machine.com/doc/AN_QP_C_MISRA.pdf).
+-# This release is now "lint-free". The source code has been thoroughly checked with the latest version of PC-lint(TM) (version 8.00q) from Gimpel Software (www.gimpel.com). The PC-lint configuration files and output files are included in the distribution. A separate Application Note "QEP/C PC-Lint Compliance" contains detailed account how QEP/C compiles with PC-Lint. (See
+http://www.state-machine.com/doc/AN_QP_C_PC-Lint.pdf).
+-# This release is compliant with the "Quantum Leaps Coding C/C++ Standard"
+(http://www.state-machine.com/resources/QL_coding_standard.pdf). Among others,
+all public names are prefixed by "Q_", or "QEP_" to minimize compile-time and
+link-time name conflicts. In addition, QEP/C uses the C99 standard include
+file <stdint.h> (C99 Standard, Section 7.18). Pre-standard compilers are still
+supported by placing <stdint.h> in the compiler's header file directory.
+-# The QEvent structure has been redesigned to use memory more efficiently.
+QEvent takes up only 2 bytes now.
+-# The QHsm structure now derives from the
+QFsm structure, which promotes better code re-use. In particular, macros
+Q_INIT() and Q_TRAN() are now common for both traditional non-hierarchical
+FSMs and for HSMs.
+-# The QFsm class has been redesigned to allow using entry
+and exit actions. Now the QFsm class strictly avoids recursion, just as QHsm
+does (MISRA rule 70).
+-# The QPseudoState type has been eliminated and
+replaced by QState.
+-# The central QHsm class in QEP has been completely
+redesigned. The basic transition algorithm is essentially the same as
+described in "PSiCC", however the implementation is very different. The
+redesign was necessary to comply with the MISRA rules and to eliminate Lint
+warnings.
+-# The event processor is now strictly non-recursive (MISRA rule
+70), that is, event handlers never call themselves, even indirectly. (Previous
+algorithm required one-level of indirect recursion.)
+-# Dynamic state
+transition is now default. Static transition optimization is still supported,
+but considered optional for performance tuning.
+-# The artificial limitation
+of initial transitions targeting only immediate substate of a composite state
+has been removed (see "PSiCC" Figure 5.4[a]). Initial transitions can now
+target any substate, arbitrarily nested within the composite state.
+-# This
+distribution uses the legacy Borland Turbo C++ 1.01 as the default compiler.
+Port to DOS with Turbo C++ 1.01 is provided along with GNU-compatible
+makefiles for the QEP library and sample applications. This compiler is not
+C99-compliant and does not provide the <stdint.h> header file. However, the
+port of QEP includes a minimal <stdint.h>, which should be placed into the
+INCLUDE directory of the Borland Turbo C++ 1.01 installation.
+-# This
+distribution contains three sample applications: A simple time bomb (QBomb) to
+demonstrate use of QFsm, a calculator (QCalc), and an exhaustive test of the
+QHsm class (QHsmTst). All examples are implemented as text-only application
+compiled with Turbo C++ 1.01. The QHsmTst sample application supports
+interactive and batch mode for exhaustive testing of the event processor. The
+source code for QHsmTst demonstrates also how QEP/C application code can be
+MISRA-compliant.
+-# This distribution contains make files for the Turbo C++
+1.01 make utility, as well as GNU-compatible Makefiles.
+
+*/

+ 2270 - 0
doxygen/qpc_tut.txt

@@ -0,0 +1,2270 @@
+/**
+\page tutorial_page QP/C Tutorial
+
+<I>This QP/C Tutorial is adapted from Chapter 1 of \ref PSiCC2\n
+by Miro Samek, the founder and president of Quantum Leaps, LLC.</I>
+
+\image html qp_tutorial.jpg
+
+This Tutorial presents an example project implemented entirely with the QP/C
+event-driven platform using UML state machines and the event-driven paradigm.
+The example application is an interactive "Fly 'n' Shoot"-type game. My aim in
+this section is to show the essential elements of the method in a real,
+nontrivial program, but without getting bogged down in details, rules, and
+exceptions. At this point, I am not trying to be complete or even precise,
+although this example is meant to show a good design and the recommended
+coding style. I don't assume that you know much about UML state machines, the
+UML notation, or the event-driven programming. I will either briefly introduce
+the concepts, as needed, or refer you to the the \ref PSiCC2 book for more
+details. The example "Fly 'n' Shoot" game is based on the "Quickstart"
+application provided in source code with the ARM Cortex-M3 LM3S811 evaluation kit
+(see \ref F2s2 "Figure 2-2") from Luminary Micro
+(http://www.luminarymicro.com). I was trying to make the "Fly 'n' Shoot"
+example behave quite similarly to the original Luminary Micro "Quickstart"
+application, so that you can directly compare the event-driven approach with
+the traditional solution to essentially the same problem specification.
+
+- \subpage installing
+- \subpage lets_play
+- \subpage main_function
+- \subpage design
+- \subpage active_objects
+- \subpage events
+- \subpage coding_hsm
+- \subpage execution
+- \subpage tracing
+- \subpage comparison
+- \subpage summary
+
+\note The <A HREF="http://state-machine.com/downloads"><B>standard QP/C
+distribution</B></A> contains two versions of the game. A <B>DOS version</B>
+is provided for the standard Windows-based PC so that you don't need any
+special embedded board to play the game and experiment with the code.
+Also provided is an <B>embedded version</B> for the inexpensive ARM
+Corterx-M3-based LM3S811 evaluation kit from Luminary Micro. Both the PC and
+the ARM-Cortex versions use the exact <B>same</B> source code for all application
+components and differ only in the Board Support Package (BSP).
+
+
+Next: \ref installing
+
+\image html logo_ql_TM.jpg
+Copyright &copy; 2002-2011 Quantum Leaps, LLC. All Rights Reserved.\n
+http://www.state-machine.com */
+
+/**
+\page installing 1. Installing QP/C and Building QP Libraries and Applications
+
+<I>This QP/C Tutorial is adapted from Chapter 1 of \ref PSiCC2\n
+by Miro Samek, the founder and president of Quantum Leaps, LLC.</I>
+
+\image html qp_tutorial.jpg
+
+Prev: \ref tutorial_page \n
+Next: \ref lets_play
+
+QP/C is distributed in a simple platform-independent ZIP file, or in a
+self-extracting Windows executable. Either way, installing QP requires simply
+decompressing the provided archive into a directory of your choice (e.g., \c
+&lt;qpc&gt; for QP/C). The Section \ref files_page describes the directories
+and files included in the standard QP/C distribution.
+
+Specifically to the "Fly 'n' Shoot" example, the companion code contains two
+versions of the game. I provide a DOS version for the standard Windows-based
+PC (see \ref F2s1 "Figure 2-1") so that you don't need any special embedded
+board to play the game and experiment with the code.
+
+\note I've chosen the legacy 16-bit DOS platform because it allows programming
+a standard PC at the bare-metal level. Without leaving your desktop, you can
+work with interrupts, directly manipulate CPU registers, and directly access
+the I/O space. No other modern 32-bit development environment for the standard
+PC allows this much so easily. The ubiquitous PC running under DOS (or a DOS
+console within any variant of Windows) is as close as it gets to emulate
+embedded software development on the commodity 80x86 hardware. Additionally,
+you can use free, mature tools, such as the Open Watcom C/C++ compiler.
+
+I also provide an embedded version for the inexpensive ARM Corterx-M3-based
+ARM Cortex-M3 LM3S811 evaluation kit from Luminary Micro (see \ref F2s2 "Figure 2-2").
+Both the PC and ARM-Cortex versions use the exact same source code for
+all application components and differ only in the Board Support Package (BSP).
+
+
+\section building_lib 1.1 Building QP Libraries
+
+\note The pre-compiled QP libraries are provided in the standard QP
+distribution (see \ref files_page), so you can start experimenting with all
+examples without building the QP libraries. However, if you want to re-build
+the QP libraries, this section provides the details.
+
+\ref F1s1 "Figure 1-1" illustrates the steps required to build the QF library.
+The process of building other QP components, such as QEP or QK, is essentially
+identical. The key point of the design is that all platform-independent QF
+source files include the same \c qf_port.h header file as the application
+source files (see \ref F1s1 "Figure 1-1"). At this point you can clearly see
+that the Platfrom Abstraction Layer (PAL) provided in QP plays the dual role
+of facilitating the porting of QP as well as using it in the applications.
+\ref F1s1 "Figure 1-1" shows also that every QP component, such as QF, can
+contain a platform-specific source file (\c qf_port.c in this case). The
+platform-specific source file is optional and many ports don't require it.
+
+\anchor F1s1
+\image html Fig8.02.jpg "Figure 1-1 Building the QF library."
+
+The standard QP ports often contain a simple \c make.bat script or a
+\c Makefile for building all the QP libraries for the port. You typically can
+choose the build configuration by providing a target to the \c make.bat script
+or to the \c Makefile. The default target is "dbg". Other possible targets are
+"rel", and "spy". The following table summarizes the targets accepted by the
+\c make.bat scripts or the \c Makefiles.
+
+<TABLE SUMMARY="Build Targets" cellSpacing=4 cellPadding=1 border=0
+ALIGN="center" VALIGN="middle">
+  <TR bgColor="#c8cedc">
+    <TD><B>&nbsp;Build Configuration</B></TD>
+    <TD><B>&nbsp;Build Command</B></TD>
+  </TR>
+
+  <TR bgColor="#ffffcc">
+    <TD>&nbsp;Debug&nbsp;</TD>
+    <TD>make</TD>
+  </TR>
+
+  <TR bgColor="#ffffdd">
+    <TD>&nbsp;Release&nbsp;</TD>
+    <TD>make rel</TD>
+  </TR>
+
+  <TR bgColor="#ffffcc">
+    <TD>&nbsp;Spy&nbsp;</TD>
+    <TD>make spy</TD>
+  </TR>
+</TABLE>
+
+\note All QP components are designed to be deployed in fine-granularity object
+libraries. QP libraries allow the linker to eliminate any unreferenced QP code
+at link time, which results in automatic scaling of every QP component for a
+wide range of applications. This approach eliminates the need to manually
+configure and recompile the QP source code for each application at hand.
+
+\section building_app 1.2 Building QP Applications
+
+\note The standard QP distribution contains pre-compiled examples (see \ref
+files_page), so you can start experimenting with all examples without building
+them. However, if you want to re-build the QP examples, this section provides
+the details.
+
+\ref F1s2 "Figure 1-2" shows the process of building a QP application. Each QP
+component requires inclusion of only one platform-specific header file and
+linking one platform-specific library. For example, to use the QF real-time
+framework, you need to include the \c qf_port.h header file  and you need to
+link the \c qf.lib library file from the specific QP port directory. It really
+doesn't get any simpler than that.
+
+\anchor F1s2
+\image html Fig8.01.jpg "Figure 1-2 Building a QP-based Application."
+
+The QP port you are using is determined by the directory branch in which the
+\c qf_port.h header file and the QF library file are located. Section
+\ref files_page shows some examples of such port directories. Typically you
+need to instruct the C/C++ compiler to include header files from the specific
+QP port directory and also from the platform-independent include directory
+\c &lt;qpc&gt;\\include\\. I strongly discourage hard-coding full path-names
+of the include files in your source code. You should simply include the QP
+port header file (<TT>#include "qf_port.h"</TT>) without any path. Then you
+specify to the compiler to search the QP port directory for include files,
+typically through the <TT>-I</TT> option.
+
+Prev: \ref tutorial_page \n
+Next: \ref lets_play
+
+\image html logo_ql_TM.jpg
+Copyright &copy; 2002-2011 Quantum Leaps, LLC. All Rights Reserved.\n
+http://www.state-machine.com */
+
+/**
+\page lets_play 2. Let's Play
+
+<I>This QP/C Tutorial is adapted from Chapter 1 of \ref PSiCC2\n
+by Miro Samek, the founder and president of Quantum Leaps, LLC.</I>
+
+\image html qp_tutorial.jpg
+
+Prev: \ref installing \n
+Next: \ref main_function
+
+The following description of the "Fly 'n' Shoot" game serves the dual purpose
+of explaining how to play the game and as the problem specification for the
+purpose of designing and implementing the software later in this Tutorial. To
+accomplish these two goals I need to be quite detailed, so please bear with
+me.
+
+Your objective in the game is to navigate a space ship through an endless
+horizontal tunnel with mines. Any collision with the tunnel or the mine
+destroys the ship. You can move the ship up and down with UP-arrow and
+DOWN-arrow keys on the PC (see \ref F2s1 "Figure 2-1") or the potentiometer
+wheel on the LM3S811 board (see \ref F2s2 "Figure 2-2"). You can also fire a
+missile to destroy the mines in the tunnel by pressing the SPACE-bar on the PC
+or the User button on the LM3S811 board. Score accumulates for survival (at
+the rate of 30 points per second) and destroying the mines.
+
+The game lasts for only one ship. The game starts in a demo mode, where the
+tunnel walls scroll at the normal pace from right to left and the "Press
+Button" text flashes in the middle of the screen. You need to generate the
+"fire missile" event for the game to begin (press SPACE-bar on the PC and the
+User Button on the LM3S811 board). You can have only one missile in flight at
+a time, so trying to fire a missile while it is already flying has no effect.
+Hitting the tunnel wall with the missile brings you no points, but you earn
+extra points for destroying the mines.
+
+The game has two types of mines with different behavior. In the original
+Luminary "Quickstart" application both types of mines behave the same, but I
+wanted to demonstrate how state machines can elegantly handle differently
+behaving mines.
+
+Mine type-1 is small, but can be destroyed by hitting any of its pixels with
+the missile. You earn 25 points for destroying a mine type- Mine type-2 is
+bigger, but is nastier in that the missile can destroy it only by hitting its
+center, not any of the "tentacles". Of course, the ship is vulnerable to the
+whole mine. You earn 45 points for destroying a mine type 2.
+
+When your crash the ship, either by hitting a wall or a mine, the game ends
+and displays the flashing "Game Over" text as well as your final score. After
+5 seconds of flashing, the "Game Over" screen changes back to the demo screen,
+where the game waits to be started again.
+
+Additionally the application contains a screen saver because the OLED display
+of the original LM3S811 board has burn-in characteristics similar to a CRT.
+The screen saver only becomes active if 20 seconds elapse in the demo mode
+without starting the game (i.e., the screen saver never appears during game
+play). The screen saver is a simple random-pixel-type, rather than the "Game
+of Life" algorithm used in the original Luminary "Quickstart" application.
+I've decided to simplify this aspect of the implementation, because the more
+elaborate pixel-mixing algorithm does not contribute any new or interesting
+behavior. After a minute of running the screen saver, the display turns blank
+and only a single random pixel shows on the screen. Again, this is a little
+difference from the original "Quickstart" application, which instead blanks
+the screen and starts flashing the User LED. I've changed this behavior
+because I have a better purpose for the User LED (to visualize the activity of
+the idle loop).
+
+\section DOS Running the DOS Version
+
+The "Fly 'n' Shoot" sample code for the DOS version (in C++) is located in
+\c &lt;qpc&gt;\\examples\\80x86\\dos\\watcom\\l\\game\\, directory, where
+\c &lt;qpc&gt; stands for the installation directory you chose to install the
+QP/C software.
+
+The compiled executable is provided, so you can run the game on any
+Windows-based PC by simply double-clicking on the executable game.exe located
+in the directory \c
+&lt;qpc&gt;\\examples\\80x86\\dos\\watcom\\l\\game\\dbg\\.
+
+\anchor F2s1
+\image html Fig1.01.jpg "Figure 2-1 The Fly 'n' Shoot game running in a DOS window under Windows XP."
+
+The first screen you see is the game running in the demo mode with the text
+"Push Button" flashing in the middle of the display. At the top of the display
+you see a legend of keystrokes recognized by the application. You need to hit
+the SPACE key to start playing the game. Please press the ESC key to cleanly
+exit the application.
+
+If you run "Fly 'n' Shoot" in a window under Microsoft Windows, the animation
+effects in the game might appear a little jumpy, especially when compared to
+the ARM-Cortex version of the same game. You can make the application execute
+significantly smoother if you switch to the full-screen mode by pressing and
+holding the Alt key and then pressing the Enter key. You go back to the window
+mode by the same Alt-Enter key combination.
+
+As you can see in \ref F2s1 "Figure 2-1", the DOS version uses simply the
+standard VGA text mode to emulate the OLED display of the LM3S811 board. The
+lower part of the DOS screen is used as a matrix of 80x16 character-wide
+"pixels", which is a little less than the 96x16 pixels of the OLED display,
+but is still good enough to play the game. I specifically avoid employing any
+fancier graphics in this early example because I have a bigger fish to fry for
+you than to worry about the irrelevant complexities of programming graphics.
+My main goal is to make it easy for you to understand the event-driven code
+and experiment with it.
+
+To this end, I chose the <STRONG>Open Watcom</STRONG> toolset to build this
+example as well as several other examples in this book. Open Watcom it is
+available under a OSI-certified <STRONG>open source</STRONG> license that
+permits free commercial and non-commercial use. You can download Open Watcom
+C/C++ toolset for DOS from 
+<a href="ftp://ftp.openwatcom.org/">ftp://ftp.openwatcom.org/</a>. Please
+select the \c open-watcom-c-dos-1.8.exe installer. Ready to print documentation
+in PDF format is also available from 
+<a href="http://www.openwatcom.org/index.php/Manuals">
+http://www.openwatcom.org/index.php/Manuals</a>.
+
+The Open Watcom C/C++ toolset for DOS is distributed as a Windows installer. 
+After you download the \c open-watcom-c-dos-1.8.exe file, please launch the
+installer and follow the instructions it provides.
+
+\note I strongly recommend that you install the Open Watcom toolset into the
+directory \c C:\\tools\\watcom\\. That way, you will be able to use directly
+the provided make scripts. If you choose to install Open Watcom into a different
+location, you can still use the make scripts supplied with the QP distribution,
+but you need to define the \c WATCOM environment variable. You should
+<STRONG>not</STRONG> install Open Watcom in the standard "Prgram Files"
+directory or any directory name with a space.
+
+To experinment with the "Fly 'n' Shoot" game code you can use any code editor
+to modify the source code. Then you re-build the application by means of the
+supplied \c make.bat script, which is located in the directory \c
+&lt;qpc&gt;\\examples\\80x86\\dos\\watcom\\l\\game\\.
+
+In the next section, I describe briefly how to run the embedded version of the
+game. If you are not interested in the ARM-Cortex version, please feel free to
+skip to the following Section \ref main_function, where I start explaining the
+application code.
+
+
+\section Cortex Running the ARM-Cortex Version
+
+In contrast to the "Fly 'n' Shoot" version for DOS running in the ancient real
+mode of the 80x86 processor, the exact same source code runs on one of the
+most modern processors in the industry: the ARM-Cortex.
+
+\anchor F2s2
+\image html Fig1.02.jpg "Figure 2-2 The Fly 'n' Shoot game running on the ARM Cortex-M3 LM3S811 evaluation board."
+
+The sample code for the ARM Cortex-M3 LM3S811 board is located in \c
+&lt;qpc&gt;\\examples\\arm-cortex\\vanilla\\iar\\game-ev-lm3s811\\ directory,
+where \c &lt;qpc&gt; stands for the root directory you chose to install the
+accompanying software. The code for the ARM-Cortex kit has been compiled with
+the 32KB-limited Kickstart edition of the <STRONG>IAR Embedded Workbench for
+ARM</STRONG> (IAR EWARM) v 5.11, which is provided with the ARM Cortex-M3
+EKI-LM3S811 kit. You can also download this software <STRONG>free</STRONG> of
+charge directly from IAR Systems (http://www.iar.com), after filling out an
+online registration.
+
+The installation of IAR EWARM is quite straightforward, as the software comes
+with the installation utility. You also need to install the USB drivers for
+the hardware debugger built into the LM3S811 board, as described in the
+documentation of the ARM Cortex-M3 LM3S811 kit.
+
+\note I strongly recommend that you install the IAR EWARM toolset into the
+directory \c C:\\tools\\iar\\arm_ks_5.11 That way, you will be able to use
+directly the provided EWARM workspace files and make scripts.
+
+Before you program the "Fly 'n' Shoot" game to the LM3S811 board, you might
+want to play a little with the original "Quickstart" application that comes
+pre-programmed with the LM3S811 kit.
+
+To program the "Fly 'n' Shoot" game to the flash memory of the LM3S811 board,
+you first connect the LM3S811 board to your PC with the USB cable provided in
+the kit and make sure that the Power LED is on (see \ref F2s2 "Figure 2-2").
+Next, you need to launch the IAR Embedded Workbench and open the workspace
+game-ev-lm3s81eww located in \c
+&lt;qpc&gt;\\examples\\arm-cortex\\vanilla\\iar\\game-ev-lm3s811\\ directory.
+At this point your screen should look similar to the screenshot shown in
+\ref F2s3 "Figure 2-3". The game-ev-lm3s811 project is set up to use the LMI FTDI
+debugger, which is the piece of hardware integrated on the LM3S811 board (see
+\ref F2s2 "Figure 2-2"). You can verify this setup by opening the "Options"
+dialog box via the Project->Options menu. Within the "Options" dialog box, you
+need to select the Debugger category in the panel on the left. While you are
+at it, you could also verify that the flash loading is enabled by selecting
+the "Download" tab. The checked "Use flash loader(s)" checkbox means that the
+flash loader application provided by IAR will be first loaded to the RAM of
+the MCU, and this application will program the flash with the image of your
+application. To start the flash programming process, select the Project->Debug
+menu, or simply click on the Debug button (see \ref F2s3 "Figure 2-3") in the
+toolbar. The IAR Workbench should respond by showing the flash programming
+progress bar for several seconds, as shown in \ref F2s3 "Figure 2-3". Once the
+flash programming completes, the IAR EWARM switches to the IAR C-Spy debugger
+and the program should stop at the entry to main(). You can start playing the
+game either by hitting the "Go" button in the debugger, or you can close the
+debugger and reset the board by pressing the Reset button. Either way, "Fly
+'n' Shoot" game is now permanently programmed into the LM3S811 board and will
+start automatically upon every power up.
+
+\anchor F2s3
+\image html Fig1.03.jpg "Figure 2-3 Loading the Fly 'n' Shoot game into the flash of LM3S811 MCU with IAR EWARM IDE"
+
+The IAR Embedded Workbench environment allows you to experiment with the "Fly
+'n' Shoot" code very easily. You can edit the files and recompile the
+application at a click of a button (F7). The only caveat is that the first
+time after the installation of the IAR toolset you need to build the Luminary
+Micro driver library for the LM3S811 MCU from the sources. You accomplish this
+by loading the workspace ek-lm3s81eww located in the directory
+\c &lt;IAR-EWARM&gt;\\ARM\\examples\\Luminary\\Cortex-M3\\boards\\ek-lm3s811,
+where &lt;IAR-EWARM&gt; stands for the directory name where you've installed
+the IAR toolset. In the ev-lm3s81eww workspace, you select the "driverlib -
+Debug" project from the drop-down list at the top of the Workspace panel, and
+then press F7 to build the library.
+
+Prev: \ref installing \n
+Next: \ref main_function
+
+\image html logo_ql_TM.jpg
+Copyright &copy; 2002-2011 Quantum Leaps, LLC. All Rights Reserved.\n
+http://www.state-machine.com */
+
+/**
+\page main_function 3. The main() Function
+
+<I>This QP/C Tutorial is adapted from Chapter 1 of \ref PSiCC2\n
+by Miro Samek, the founder and president of Quantum Leaps, LLC.</I>
+
+\image html qp_tutorial.jpg
+
+Prev: \ref lets_play \n
+Next: \ref design
+
+Perhaps the best place to start the explanation of the "Fly 'n' Shoot"
+application code is the main() function, located in the file \c main.c. Unless
+indicated otherwise in this Tutorial, you can browse the code either in the
+DOS version, or the ARM-Cortex version, because the application source code is
+identical in both. The complete \c main.c file is shown in 
+\ref L3s1 "Listing 3-1"
+
+\note To explain code listings, I place numbers in parentheses at the
+interesting lines in the left margin of the listing. I then use these labels
+in the left margin of the explanation section that immediately follows the
+listing. Occasionally, to unambiguously refer to a line of a particular
+listing from sections of text other than the explanation section, I use the
+full reference consisting of the listing number followed by the label. For
+example, \ref L3s1 "Listing 3-1"(21) refers to the label (21) in
+\ref L3s1 "Listing 3-1"
+
+\anchor L3s1
+<STRONG>Listing 3-1 The file main.c of the "Fly 'n' Shoot" game application.
+</STRONG>
+\code
+ (1) #include "qp_port.h"                                         /* the QP port */
+ (2) #include "bsp.h"                                   /* Board Support Package */
+ (3) #include "game.h"                                       /* this application */
+
+     /* Local-scope objects -----------------------------------------------------*/
+ (4) static QEvent const * l_missileQueueSto[2];                  /* event queue */
+ (5) static QEvent const * l_shipQueueSto[3];                     /* event queue */
+ (6) static QEvent const * l_tunnelQueueSto[GAME_MINES_MAX + 5];  /* event queue */
+ (7) static ObjectPosEvt   l_smlPoolSto[GAME_MINES_MAX + 8];  /* small-size pool */
+ (8) static ObjectImageEvt l_medPoolSto[GAME_MINES_MAX + 8]; /* medium-size pool */
+ (9) static QSubscrList    l_subscrSto[MAX_PUB_SIG];        /* publish-subscribe */
+
+     /*..........................................................................*/
+     void main(int argc, char *argv[]) {
+                               /* explicitly invoke the active objects' ctors... */
+(10)     Missile_ctor();
+(11)     Ship_ctor();
+(12)     Tunnel_ctor();
+
+(13)     BSP_init(argc, argv);           /* initialize the Board Support Package */
+(14)     QF_init();     /* initialize the framework and the underlying RT kernel */
+
+                                                /* initialize the event pools... */
+(15)     QF_poolInit(l_smlPoolSto, sizeof(l_smlPoolSto), sizeof(l_smlPoolSto[0]));
+(16)     QF_poolInit(l_medPoolSto, sizeof(l_medPoolSto), sizeof(l_medPoolSto[0]));
+
+(17)     QF_psInit(l_subscrSto, Q_DIM(l_subscrSto));   /* init publish-subscribe */
+
+                                                  /* start the active objects... */
+(18)     QActive_start(AO_Missile,/* global pointer to the Missile active object */
+                       1,                                   /* priority (lowest) */
+                       l_missileQueueSto, Q_DIM(l_missileQueueSto), /* evt queue */
+                       (void *)0, 0,                      /* no per-thread stack */
+                       (QEvent *)0);                  /* no initialization event */
+(19)     QActive_start(AO_Ship,      /* global pointer to the Ship active object */
+                       2,                                            /* priority */
+                       l_shipQueueSto,    Q_DIM(l_shipQueueSto),    /* evt queue */
+                       (void *)0, 0,                      /* no per-thread stack */
+                       (QEvent *)0);                  /* no initialization event */
+(20)     QActive_start(AO_Tunnel,  /* global pointer to the Tunnel active object */
+                       3,                                            /* priority */
+                       l_tunnelQueueSto,  Q_DIM(l_tunnelQueueSto),  /* evt queue */
+                       (void *)0, 0,                      /* no per-thread stack */
+                       (QEvent *)0);                  /* no initialization event */
+
+(21)     QF_run();                                     /* run the QF application */
+    }
+\endcode
+
+\li (1) The "Fly 'n' Shoot" game is an example of an application implemented with
+the QP event-driven platform. Every application C-file that uses QP must
+include the qp_port.h header file. This header file contains the specific
+adaptation of QP to the given processor, operating system, and compiler, which
+is called a port. Each QP port is located in a separate directory and the C
+compiler finds the right qp_port.h header file through the include search path
+provided to the compiler (typically via the -I compiler option). That way I
+don't need to change the application source code to recompile it for a
+different processor or compiler. I only need to instruct the compiler to look
+in a different QP port directory for the qp_port.h header file. For example,
+the DOS version includes the qp_port.h header file from the directory
+\c &lt;qpc&gt;\\ports\\80x86\\dos\\watcom\\l\\, and the ARM-Cortex version
+from the directory \c &lt;qpc&gt;\\ports\\arm-cortex\\vanilla\\iar\\.
+
+\li (2) The bsp.h header file contains the interface to the Board Support Package
+and is located in the application directory.
+
+\li (3) The game.h header file contains the declarations of events and other
+facilities shared among the components of the application. I will discuss this
+header file in the upcoming Section \ref events. This header file is located
+in the application directory.
+
+The QP event-driven platform is a collection of components, such as the QEP
+event processor that executes state machines according to the UML semantics
+and the QF real-time framework that implements the active object computing
+model. Active objects in QF are encapsulated state machines (each with an
+event queue, a separate task context, and a unique priority) that communicate
+with one another asynchronously by sending and receiving events, while QF
+handles all the details of thread-safe event exchange and queuing. Within an
+active object, the events are processed by the QEP event processor
+sequentially in a run-to-completion (RTC) fashion, meaning that processing of
+one event must necessarily complete before processing the next event.
+
+\li (4-6) The application must provide storage for the event queues of all active
+objects used in the application. Here the storage is provided at compile time
+through the statically allocated arrays of immutable (const) pointers to
+events, because QF event queues hold just pointers to events, not events
+themselves. Events are represented as instances of the QEvent structure
+declared in the qp_port.h header file. Each event queue of an active object
+can have a different size and you need to decide this size based on your
+knowledge of the application. I discuss the event queues in Chapters 6 and 7
+of \ref PSiCC2.
+
+\li (7-8) The application must also provide storage for event pools that the
+framework uses for fast and deterministic dynamic allocation of events. Each
+event pool manages can provide only fixed-size memory blocks. To avoid wasting
+memory by using oversized blocks for small events, the QF framework can manage
+up to three event pools of different block sizes (for small, medium, and large
+events). The "Fly 'n' Shoot" application uses only two out of the three
+possible event pools (the small and medium pools).
+
+The QF real-time framework supports two event delivery mechanisms: the simple
+direct event posting to active objects, and the more advanced mechanism called
+publish-subscribe that decouples event producers from the consumers. In the
+publish-subscribe mechanism, active objects subscribe to events by the
+framework. Event producers publish the events to the framework. Upon each
+publication request, the framework delivers the event to all active objects
+that had subscribed to that event type. One obvious implication of
+publish-subscribe is that the framework must store the subscriber information,
+whereas it must be possible to handle multiple subscribers to any give event
+type. The event delivery mechanisms are described in Chapters 6 and 7 of \ref
+PSiCC2.
+
+\li (9) The "Fly 'n' Shoot" application uses the publish-subscribe event delivery
+mechanism supported by QF, so it needs to provide the storage for the
+subscriber lists. The subscriber lists remembers which active objects have
+subscribed to which events. The size of the subscriber database depends on
+both the number of published events, which is specified in the MAX_PUB_SIG
+constant found in the game.h header file, and the maximum number of active
+objects allowed in the system, which is determined by the QF configuration
+parameter #QF_MAX_ACTIVE.
+
+\li (10-12) These functions perform an early initialization of the active objects
+in the system. They play the role of static "constructors", which in C you
+need to invoke explicitly. (C++ calls such static constructors implicitly
+before entering \c main()).
+
+\li (13) The function \c BSP_init() initializes the board and is defined in the
+bsp.c file.
+
+\li (14) The function QF_init() initializes the QF component and the underlying
+RTOS/kernel, if such software is used. You need to call QF_init() before you
+invoke any of QF services.
+
+\li (15-16) The function QF_poolInit() initializes the event pools. The parameters
+of this function are the pointer to the event pool storage, the size of this
+storage, and the block-size of this pool. You can call this function up to
+three times to initialize up to three event pools. The subsequent calls to
+QF_poolInit() must be made in the increasing order of block sizes. For
+instance, the small block-size pool must be initialized before the medium
+block-size pool.
+
+\li (17) The function QF_poolInit() initializes the publish-subscribe event
+delivery mechanism of QF. The parameters of this function are the pointer to
+the subscriber-list array and the dimension of this array.
+
+The utility macro Q_DIM(a) provides the dimension of a one-dimensional array
+<TT>a[]</TT> computed as <TT>sizeof(a)/sizeof(a[0])</TT>, which is a
+compile-time constant. The use of this macro simplifies the code because it
+allows me to eliminate many #define constants that otherwise I would need to
+provide for the dimensions of various arrays. I can simply hard-code the
+dimension right in the definition of an array, which is the only place that I
+specify it. I then use the macro Q_DIM() whenever I need this dimension in the
+code.
+
+\li (18-20) The function QActive_start() tells the QF framework to start managing
+an active object as part of the application. The function takes the following
+parameters: the pointer to the active object structure, the priority of the
+active object, the pointer to its event queue, the dimension (length) of that
+queue, and three other parameters that I explain in Chapter 7 of \ref
+PSiCC2, since they are not relevant at this point. The active object
+priorities in QF are numbered from 1 to #QF_MAX_ACTIVE, inclusive, where a
+higher priority number denotes higher urgency of the active object. The
+constant #QF_MAX_ACTIVE is defined in the QF port header file qf_port.h and
+currently cannot exceed 63.
+
+I like to keep the code and data of every active object strictly encapsulated
+within its own C-file. For example, all code and data for the active object
+Ship are encapsulated in the file ship.c, with the external interface
+consisting of the function \c Ship_ctor() and the pointer \c AO_Ship.
+
+\li (21) At this point, you have provided to the framework all the storage and
+information it needs to manage your application. The last thing you must do is
+to call the function QF_run() to pass the control to the framework.
+
+After the call to QF_run() the framework is in full control. The framework
+executes the application by calling your code, not the other way around. The
+function QF_run() never returns the control back to main(). In the DOS version
+of the "Fly 'n' Shoot" game, you can terminate the application by pressing the
+ESC key, in which case QF_run() exits to DOS, but not to \c main(). In an
+embedded system, such as the ARM-Cortex board, QF_run() runs forever or till
+the power is removed, whichever comes first.
+
+\note For best cross-platform portability, the source code uses consistently
+the <STRONG>UNIX end-of-line convention</STRONG> (lines are terminated with LF
+only, 0xA character). This convention seems to be working for all C/C++
+compilers and cross-compilers, including legacy DOS-era tools. In contrast,
+the DOS/Windows end-of-line convention (lines terminated with the CR,LF, or
+0xD,0xA pair of characters), is known to cause problems on UNIX-like
+platforms, especially in the multi-line preprocessor macros.
+
+Prev: \ref lets_play \n
+Next: \ref design
+
+\image html logo_ql_TM.jpg
+Copyright &copy; 2002-2011 Quantum Leaps, LLC. All Rights Reserved.\n
+http://www.state-machine.com */
+
+/**
+\page design 4. Designing an Event-Driven Application
+
+<I>This QP/C Tutorial is adapted from Chapter 1 of \ref PSiCC2\n
+by Miro Samek, the founder and president of Quantum Leaps, LLC.</I>
+
+\image html qp_tutorial.jpg
+
+Prev: \ref main_function \n
+Next: \ref active_objects
+
+To proceed further with the explanation of the "Fly 'n' Shoot" application, I
+need to step up to the design level. At this point I need to explain how the
+application has been decomposed into the active objects, and how these objects
+exchange events to collectively deliver the functionality of the "Fly 'n'
+Shoot" game.
+
+In general, the decomposition of a problem into active objects is
+not trivial. As usual in any decomposition, your goal is to achieve possibly
+loose coupling among the active object components (ideally no sharing of any
+resources), and you also strive for minimizing the communication in terms of
+the frequency and size of exchanged events.
+
+In the case of the "Fly 'n' Shoot" game, I need first to identify all objects
+with reactive behavior (i.e. with a state machine). I applied the simplest
+object-oriented technique of identifying objects, which is to pick the
+frequently used nouns in the problem specification. From Section \ref
+lets_play, I identified Ship, Missile, Mines, and Tunnel. However, not every
+state machine in the system needs to be an active object (with a separate task
+context, an event queue, and a unique priority level), and merging them is a
+valid option when performance or space is needed. As an example of this idea,
+I ended up merging the Mines into the Tunnel active object, whereas I
+preserved the Mines as independent state machine components of the Tunnel
+active object. By doing so I applied the "Orthogonal Component" design pattern
+described in Chapter 5 of \ref PSiCC2.
+
+The next step in the event-driven application design is assigning
+responsibilities and resources to the identified active objects. The general
+design strategy for avoiding sharing of resources is to encapsulate each
+resource inside a dedicated active object and to let that object manage the
+resource for the rest of the application. That way, instead of sharing the
+resource directly, the rest of the application shares the dedicated active
+object via events.
+
+So, for example, I decided to put the Tunnel active object in charge of the
+display. Other active objects and state machine components, such as Ship,
+Missile and Mines, don't draw on the display directly, but rather send events
+to the Tunnel object with the request to render the Ship, Missile, or Mine
+bitmaps at the provided (x, y) coordinates of the display.
+
+With some understanding of the responsibilities and resource allocations to
+active object I can move on to devising the various scenarios of event
+exchanges among the objects. Perhaps the best instrument to aid the thinking
+process at this stage is the UML sequence diagram, such as the diagram
+depicted in \ref F4s1 "Figure 4-1". This particular sequence diagram shows the
+most common event exchange scenarios in the "Fly 'n' Shoot" game (the primary
+use cases, if you will). The explanation section immediately following the
+diagram illuminates the interesting points.
+
+\note A UML sequence diagram like \ref F4s1 "Figure 4-1" has two dimensions.
+Horizontally arranged boxes represent the various objects participating in the
+scenario whereas heavy boarders indicate active objects. As usual in the UML,
+the object name in underlined. Time flows down the page along the vertical
+dashed lines descending from the objects. Events are represented as horizontal
+arrows originating from the sending object and terminating at the receiving
+object. Optionally, thin rectangles around instance lines indicate focus of
+control.
+
+\anchor F4s1
+\image html Fig1.04.jpg "Figure 4-1 The sequence diagram of the Fly 'n' Shoot game."
+
+\li (1) The \c TIME_TICK is the most important event in the game. This event is
+generated by the QF framework from the system time tick interrupt at a rate of
+30 times per second, which is needed to drive a smooth animation of the
+display. Because the \c TIME_TICK event is of interest to virtually all
+objects in the application, it is published by the framework to all active
+objects. (The publish-subscribe event delivery in QF is described in Chapter 6
+of \ref PSiCC2.)
+
+\li (2) Upon reception of the \c TIME_TICK event, the Ship object advances its
+position by one step and posts the event <TT>SHIP_IMG(x, y, bmp)</TT> to the
+Tunnel object. The SHIP_IMG event has parameters x and y, which are the
+coordinates of the Ship on the display, as well as the bitmap number bmp to
+draw at these coordinates.
+
+\li (3) The Missile object is not in flight yet, so it simply ignores the
+\c TIME_TICK event this time.
+
+\li (4) The Tunnel object performs the heaviest lifting for the \c TIME_TICK
+event. First, Tunnel redraws the entire display from the current frame buffer.
+This action performed 30 times per second provides the illusion of animation
+of the display. Next, the Tunnel clears the frame buffer and starts filling it
+up again for the next time frame. The Tunnel advances the tunnel walls by one
+step and copies the walls to the frame buffer. The Tunnel also dispatches the
+\c TIME_TICK event to all its Mine state machine components.
+
+\li (5) Each Mine advances its position by one step and posts the <TT>MINE_IMG(x,
+y, bmp)</TT> event to the Tunnel to render the appropriate Mine bitmap at the
+position <TT>(x, y)</TT> in the current frame buffer. Mines of type 1 send the
+bitmap number MINE1_BMP, while mines of type 2 send \c MINE2_BMP.
+
+\li (6) Upon reception of the <TT>SHIP_IMG(x, y, bmp)</TT> event from the Ship,
+the Tunnel object renders the specified bitmap in the frame buffer and checks
+for any collision between the ship bitmap and the tunnel walls. Tunnel also
+dispatches the original <TT>SHIP_IMG(x, y, bmp)</TT> event to all active
+Mines.
+
+\li (7) Each Mine determines if the Ship is in collision with that Mine.
+
+\li (8) The \c PLAYER_TRIGGER event is generated when the Player reliably presses
+the button (button press is debounced). This event is published by the QF
+framework and is delivered to the Ship and Tunnel objects, which both
+subscribe to the \c PLAYER_TRIGGER event.
+
+\li (9) Ship generates the <TT>MISSILE_FIRE(x, y)</TT> event to the Missile
+object. The parameters of this event are the current <TT>(x, y)</TT>
+coordinates of the Ship, which are the starting point for the Missile.
+
+\li (10) Tunnel receives the published \c PLAYER_TRIGGER event as well because
+Tunnel occasionally needs to start the game or terminate the screen saver mode
+based upon this stimulus.
+
+\li (11) Missile reacts to the <TT>MISSILE_FIRE(x, y)</TT> event by starting to
+fly, whereas it sets its initial position from the <TT>(x, y)</TT> event
+parameters delivered from the Ship.
+
+\li (12) This time around, the \c TIME_TICK event arrives while Missile is in
+flight. Missile posts the <TT>MISSILE_IMG(x, y, bmp)</TT> event to the Table.
+
+\li (13) Table renders the Missile bitmap in the current frame buffer and
+dispatches the <TT>MISSILE_IMG(x, y, bmp)</TT> event to all the Mines to let
+the Mines test for the collision with the Missile. This determination depends
+on the type of the Mine. In this scenario a particular Mine[n] object detects
+a hit and posts the <TT>HIT_MINE(score)</TT> event to the Missile. The Mine
+provides the score earned for destroying this particular mine as the parameter
+of this event.
+
+\li (14) Missile handles the <TT>HIT_MINE(score)</TT> event by becoming
+immediately ready to launch again and lets the Mine do the exploding. As I
+decided to make the Ship responsible for the scorekeeping, the Missile also
+generates the <TT>DESTROYED_MINE(score)</TT> event to the Ship, to report the
+score for destroying the Mine.
+
+\li (15) Upon reception of the <TT>DESTROYED_MINE(score)</TT> event, the Ship
+updates the score reported by the Missile.
+
+\li (16) The Ship object handles the <TT>PLAYER_SHIP_MOVE(x, y)</TT> event by
+updating its position from the event parameters.
+
+\li (17) When the Tunnel object handles the <TT>SHIP_IMG(x, y, bmp_id)</TT> event
+next time around, it detects a collision between the Ship and the tunnel wall.
+In that case it posts the event \c HIT_WALL to the Ship.
+
+\li (18) The Ship responds to the \c HIT_WALL event by transitioning to the
+"exploding" state.
+
+Even though the sequence diagram in \ref F4s1 "Figure 4-1" shows merely some
+selected scenarios of the "Fly 'n' Shoot" game, I hope that the explanations
+give you a big picture of how the application works. More importantly, you
+should start getting the general idea about the thinking process that goes
+into designing an event-driven system with active objects and events.
+
+Prev: \ref main_function \n
+Next: \ref active_objects
+
+\image html logo_ql_TM.jpg
+Copyright &copy; 2002-2011 Quantum Leaps, LLC. All Rights Reserved.\n
+http://www.state-machine.com */
+
+/**
+\page active_objects 5. Elaborating State Machines of Active Objects
+
+<I>This QP/C Tutorial is adapted from Chapter 1 of \ref PSiCC2\n
+by Miro Samek, the founder and president of Quantum Leaps, LLC.</I>
+
+\image html qp_tutorial.jpg
+
+Prev: \ref design \n
+Next: \ref events
+
+I hope that the analysis of the sequence diagram in \ref F4s1 "Figure 4-1" makes
+it clear that actions performed by an active object depend as much on the
+events it receives, as on the internal mode of the object. For example, the
+Missile active object handles the \c TIME_TICK event very differently when the
+Missile is in flight (\ref F4s1 "Figure 4-1"(12)) compared to the time when it is
+not (\ref F4s1 "Figure 4-1"(3)). The best known mechanism of handling such modal
+behavior is through state machines because a state machine makes the behavior
+explicitly dependent on both the event and the state of an object. In Chapter
+2 of \ref PSiCC2 I introduce UML state machine concepts more thoroughly. In
+this section, I give a cursory explanation of the state machines associated
+with each object in the "Fly 'n' Shoot" game.
+
+\section missile 5.1 The Missile Active Object
+
+I start with the Missile state machine shown in \ref F5s1 "Figure 5-1", because it
+turns out to be the simplest one. The explanation section immediately
+following the diagram illuminates the interesting points.
+
+\note A UML state diagram like \ref F5s1 "Figure 5-1" preserves the general form
+of the traditional state transition diagrams, where states are represented as
+nodes and transitions as arcs connecting the nodes. In the UML notation the
+state nodes are represented as rectangles with rounded corners. The name of
+the state appears in bold type in the name compartment at the top of the
+state. Optionally, right below the name, a state can have an internal
+transition compartment separated from the name by a horizontal line. The
+internal transition compartment can contain entry actions (actions following
+the reserved symbol "entry"), exit actions (actions following the reserved
+symbol "exit"), and other internal transitions (e.g., those triggered by
+\c TIME_TICK in \ref F5s1 "Figure 5-1"(3)). State transitions are represented as
+arrows originating at the boundary of the source state and pointing to the
+boundary of the target state. At a minimum, a transition must be labeled with
+the triggering event. Optionally, the trigger can be followed by event
+parameters, a guard, and a list of actions.
+
+\anchor F5s1
+\image html Fig1.05.jpg "Figure 5-1 Missile state machine diagram."
+
+\li (1) The state transition originating at the black ball is called the initial
+transition. Such transition designates the first active state after the state
+machine object is created. An initial transition can have associated actions,
+which in the UML notation are enlisted after the forward slash "/". In this
+particular case, the Missile state machine starts in the "armed" state and the
+actions executed upon the initialization consist of subscribing to the event
+\c TIME_TICK. Subscribing to an event means that the framework will deliver
+the specified event to the Missile active object every time the event is
+published to the framework. Chapter 7 of \ref PSiCC2 describes the
+implementation of the publish-subscribe event delivery in QF.
+
+\li (2) The arrow labeled with the <TT>MISSILE_FIRE(x, y)</TT> event denotes a
+state transition, that is, change of state from "armed" to "flying". The
+<TT>MISSILE_FIRE(x, y)</TT> event is generated by the Ship object when the
+Player triggers the Missile (see the sequence diagram in \ref F4s1 "Figure 4-1").
+In the \c MISSILE_FIRE event, Ship provides Missile with the initial
+coordinates in the event parameters <TT>(x, y)</TT>.
+
+\note The UML intentionally does not specify the notation for actions. In
+practice, the actions are often written in the programming language used for
+coding the particular state machine. In all state diagrams in this book, I
+assume the C programming language. Furthermore, in the C expressions I refer
+to the data members associated with the state machine object through the
+<TT>me-></TT> prefix and to the event parameters through the <TT>e-></TT>
+prefix. For example, the action <TT>me->x = e->x;</TT> means that the internal
+data member \c x of the Missile active object is assigned the value of the
+event parameter \c x.
+
+\li (3) The event name \c TIME_TICK enlisted in the compartment below the state
+name denotes an internal transition. Internal transitions are simple reactions
+to events performed without a change of state. An internal transition, as well
+as a regular transition, can have a guard condition, enclosed in square
+brackets. Guard condition is a Boolean expression evaluated at runtime. If the
+guard evaluates to TRUE, the transition is taken. Otherwise, the transition is
+not taken and no actions enlisted after the forward slash "/" are executed. In
+this particular case, the guard condition checks whether the x-coordinate
+propagated by the Missile speed is still visible on the screen. If so, the
+actions are executed. These actions include propagation of the Missile
+position by one step and posting the \c MISSILE_IMG event with the current
+Missile position and the \c MISSILE_BMP bitmap number to the Tunnel active
+object. Direct event posting to an active object is accomplished by the QF
+function QActive_postFIFO(), which I discuss in Chapter 7 of \ref PSiCC2.
+
+\li (4) The same event \c TIME_TICK with the <TT>[else]</TT> guard denotes a
+regular state transition with the guard condition complementary to the other
+occurrence of the \c TIME_TICK event in the same state. In this case, the
+\c TIME_TICK transition to "armed" is taken if the Missile object flies out of
+the screen.
+
+\li (5) The event <TT>HIT_MINE(score)</TT> triggers another transition to the
+"armed" state. The action associated with this transition posts the
+\c DESTROYED_MINE event with the parameter e->score to the Ship object, to
+report destroying the mine.
+
+\li (6) The event \c HIT_WALL triggers a transition to the "exploding" state, with
+the purpose of animating the explosion bitmaps on the display.
+
+\li (7) The label "entry" denotes the entry action to be executed unconditionally
+upon the entry to the "exploding" state. This action consists of clearing
+explosion counter (<TT>me->exp_ctr</TT>) member of the Missile object.
+
+\li (8) The \c TIME_TICK internal transition is guarded by the condition that the
+explosion does not scroll off the screen, and that the explosion counter is
+lower than 16. The actions executed include propagation of the explosion
+position and posting the \c EXPLOSION_IMG event to the Tunnel active object.
+Please note that the bitmap of the explosion changes as the explosion counter
+gets bigger.
+
+\li (6) The \c TIME_TICK regular transition with the complementary guard changes
+the state back to the "armed" state. This transition is taken after the
+animation of the explosion completes.
+
+\section ship 5.2 The Ship Active Object
+
+The state machine of the Ship active object is shown in \ref F5s2 "Figure 5-2".
+This state machine introduces the profound concept of hierarchical state
+nesting. The power of state nesting derives from the fact that it is designed
+to eliminate repetitions that otherwise would have to occur.
+
+One of the main responsibilities of the Ship active object is to maintain the
+current position of the Ship. On the original LM3S811 board, this position is
+determined by the potentiometer wheel (see \ref F2s2 "Figure 2-2"). The
+<TT>PLAYER_SHIP_MOVE(x, y)</TT> event is generated whenever the wheel position
+changes, as shown in the sequence diagram (\ref F4s1 "Figure 4-1"). The Ship
+object must always keep track of the wheel position, which means that all
+states of the Ship state machine must handle the <TT>PLAYER_SHIP_MOVE(x,
+y)</TT> event.
+
+In the traditional finite state machine (FSM) formalism, you would need to
+repeat the Ship position update from the <TT>PLAYER_SHIP_MOVE(x, y)</TT> event
+in every state. But such repetitions would bloat the state machine and, more
+importantly, would represent multiple points of maintenance both in the
+diagram and the code. Such repetitions go against the DRY principle (Don't
+Repeat Yourself), which is vital for flexible and maintainable code.
+
+Hierarchical state nesting remedies the problem. Consider the state "active"
+that surrounds all other states in \ref F5s2 "Figure 5-2". The high-level "active"
+state is called the superstate and is abstract in that the state machine
+cannot be in this state directly, but only in one of the states nested within,
+which are called the substates of "active". The UML semantics associated with
+state nesting prescribes that any event is first handled in the context of the
+currently active substate. If the substate cannot handle the event, the state
+machine attempts to handle the event in the context of the next-level
+superstate. Of course, state nesting in UML is not limited to just one level
+and the simple rule of processing events applies recursively to any level of
+nesting.
+
+Specifically to the Ship state machine diagram shown in \ref F5s2 "Figure 5-2",
+suppose that the event <TT>PLAYER_SHIP_MOVE(x, y)</TT> arrives when the state
+machine is in the "parked" state. The "parked" state does not handle the
+<TT>PLAYER_SHIP_MOVE(x, y)</TT> event. In the traditional finite state machine
+this would be the end of story—the <TT>PLAYER_SHIP_MOVE(x, y)</TT> event would
+be silently discarded. However, the state machine in \ref F5s2 "Figure 5-2" has
+another layer of the "active" superstate. Per the semantics of state nesting,
+this higher-level superstate handles the PLAYER_SHIP_MOVE(x, y) event, which
+is exactly what's needed. The same exact argumentation applies for any other
+substate of the "active" superstate, such as "flying" or "exploding", because
+none of these substates handle the <TT>PLAYER_SHIP_MOVE(x, y)</TT> event.
+Instead, the "active" superstate handles the event in one single place,
+without repetitions.
+
+\anchor F5s2
+\image html Fig1.06.jpg "Figure 5-2 Ship state machine diagram."
+
+\li (1) Upon the initial transition, the Ship state machine enters the "active"
+superstate and subscribes to events \c TIME_TICK and \c PLAYER_TRIGGER.
+
+\li (2) At each level of nesting a superstate can have a private initial
+transition that designates the active substate after the superstate is entered
+directly. Here the initial transition of state "active" designates the
+substate "parked" as the initial active substate.
+
+\li (3) The "active" superstate handles the <TT>PLAYER_SHIP_MOVE(x, y)</TT> event
+as an internal transition in which it updates the internal data members
+<TT>me->x</TT> and <TT>me->y</TT> from the event parameters <TT>e->x</TT> and
+<TT>e->y</TT>, respectively.
+
+\li (4) The TAKE_OFF event triggers transition to "flying". This event is
+generated by the Tunnel object when the Player starts the game (see the
+description of the game in Section \ref lets_play).
+
+\li (5) The entry actions to "flying" include clearing the me->score data member
+and posting the event \c SCORE with the event parameter me->score to the
+Tunnel active object.
+
+\li (6) The \c TIME_TICK internal transition causes posting the event \c SHIP_IMG
+with current Ship position and the \c SHIP_BMP bitmap number to the Tunnel
+active object. Additionally, the score is incremented for surviving another
+time tick. Finally, when the score is "round" (divisible by 10) it is also
+posted to the Tunnel active object. This decimation of the \c SCORE event is
+performed just to reduce the bandwidth of the communication, because the
+Tunnel active object only needs to give an approximation of the running score
+tally to the user.
+
+\li (7) The \c PLAYER_TRIIGGER internal transition causes posting the event
+\c MISSILE_FIRE with current Ship position to the Missile active object. The
+parameters <TT>(me->x, me->y)</TT> provide the Missile with the initial
+position from the Ship.
+
+\li (8) The <TT>DESTROYED_MINE(score)</TT> internal transition causes update of
+the score kept by the Ship. The score is not posted to the Table at this
+point, because the next \c TIME_TICK will send the "rounded" score, which is
+good enough for giving the Player the score approximation.
+
+\li (9) The \c HIT_WALL event triggers transition to "exploding"
+
+\li (10) The <TT>HIT_MINE(type)</TT> event also triggers transition to "exploding"
+
+\li (11) The "exploding" state of the Ship state machine is very similar to the
+"exploding" state of Missile (see \ref F5s1 "Figure 5-1"(7-9)).
+
+\li (12) The <TT>TIME_TICK[else]</TT> transition is taken when the Ship finishes
+exploding. Upon this transition, the Ship object posts the event
+<TT>GAME_OVER(me->score)</TT> to the Tunnel active object to terminate the
+game and display the final score to the Player.
+
+
+\section tunnel 5.3 The Tunnel Active Object
+
+The Tunnel active object has the most complex state machine, which is shown in
+\ref F5s3 "Figure 5-3". Unlike the previous state diagrams, the diagram in
+\ref F5s3 "Figure 5-3" shows only the high-level of abstraction and omits a lot of
+details such as most entry/exit actions, internal transitions, guard
+conditions, or actions on transitions. Such a "zoomed out" view is always
+legal in the UML, because UML allows you to choose the level of detail that
+you want to include in your diagram.
+
+The Tunnel state machine uses state hierarchy more extensively than
+the Ship state machine in \ref F5s2 "Figure 5-2". The explanation section
+immediately following \ref F5s3 "Figure 5-3" illuminates the new uses of state
+nesting as well as the new elements not explained yet in the other state
+diagrams.
+
+\anchor F5s3
+\image html Fig1.07.jpg "Figure 5-3 Tunnel state machine diagram."
+
+\li (1) An initial transition can target a substate at any level of state
+hierarchy, not necessarily just the next-lower level. Here the top-most
+initial transition goes down two levels to the substate "demo".
+
+\li (2) The superstate "active" handles the \c PLAYER_QUIT event as a transition
+to the final state (see explanation of element (3)). Please note that the
+PLAYER_QUIT transition applies to all substates directly or transitively
+nested in the "active" superstate. Because a state transition always involves
+execution of all exit actions from the states, the high-level PLAYER_QUIT
+transition guarantees the proper cleanup that is specific to the current state
+context, whichever substate happens to be active at the time when the
+\c PLAYER_QUIT event arrives.
+
+\li (3) The final state is indicated in the UML notation as the bull's-eye symbol
+and typically indicates destruction of the state machine object. In this case,
+the \c PLAYER_QUIT event indicates termination of the game.
+
+\li (4) The <TT>MINE_DISABLED(mine_id)</TT> event is handled at the high level of
+the "active" state, which means that this internal transition applies to the
+whole sub-machine nested inside the "active" superstate. (See also the
+discussion of Mine object in the next section.)
+
+\li (5) The entry action to the "demo" state starts the screen time event (timer)
+<TT>me->screenTimeEvt</TT> to expire in 20 seconds. Time events are allocated
+by the application, but they are managed by the QF framework. QF provides
+functions to arm a time event, such as QTimeEvt_postIn() for one-shot timeout,
+and QTimeEvt_postEvery() for periodic time events. Arming a time event is in
+effect telling the QF framework, for instance, "Give me a nudge in 20
+seconds". QF then posts the time event (the event me->screenTimeEvt in this
+case) to the active object after the requested number of clock ticks. Chapters
+6 and 7 of \ref PSiCC2 talk about time events in detail.
+
+\li (6) The exit action from the "demo" state disarms the me->screenTimeEvt time
+event. This cleanup is necessary when the state can be exited by a different
+event than the time event, such as the \c PLAYER_TRIGGER transition.
+
+\li (7) The \c SCREEN_TIMEOUT transition to "screen_saver" is triggered by the
+expiration of the me->screenTimeEvt time event. The signal \c SCREEN_TIMEOUT
+is assigned to this time event upon initialization and cannot be changed
+later.
+
+\li (8) The transition triggered by \c PLAYER_TRIGGER applies equally to the two
+substates of the "screen_saver" superstate.
+
+
+\section mines 5.4 The Mine Components
+
+Mines are also modeled as hierarchical state machines, but are not active
+objects. Instead, Mines are components of the Tunnel active object and share
+its event queue and priority level. The Tunnel active object communicates with
+the Mine components synchronously by directly dispatching events to them via
+the function QHsm_dispatch(). Mines communicate with Tunnel and all other
+active objects asynchronously by posting events to their event queues via the
+function QActive_postFIFO().
+
+\note Active objects exchange events asynchronously, meaning that the sender
+of the event merely posts the event to the event queue of the recipient active
+object without waiting for the completion of the event processing. In
+contrast, synchronous event processing corresponds to a function call (e.g.,
+QHsm_dispatch()), which processes the event in the caller's thread of
+execution.
+
+\anchor F5s4
+\image html Fig1.08.jpg "Figure 5-4 The Table active object manages two types of Mines."
+
+As shown in \ref F5s4 "Figure 5-4", Tunnel maintains the data member mines[],
+which is an array of pointers to hierarchical state machines (QHsm *). Each of
+these pointers can point either to a Mine1 object, a Mine2 object, or NULL, if
+the entry is unused. Please note that Tunnel "knows" the Mines only as generic
+state machines (pointers to the QHsm structure defined in QP). Tunnel
+dispatches events to Mines uniformly, without differentiating between
+different types of Mines. Still, each Mine state machine handles the events it
+its specific way. For example, Mine type 2 checks for collision with the
+Missile differently than with the Ship while Mine type 1 handles both
+identically.
+
+\note The last point is actually very interesting. Dispatching the same event
+to different Mine objects results in different behavior, specific to the type
+of the Mine, which in OOP is known as polymorphism. I'll have more to say
+about this in Chapter 3 of \ref PSiCC2.
+
+Each Mine object is fairly autonomous. The Mine maintains its own position and
+is responsible for informing the Tunnel object whenever the Mine gets
+destroyed or scrolls out of the display. This information is vital for the
+Tunnel object so that it can keep track of the unused Mines.
+
+\ref F5s5 "Figure 5-5" shows a hierarchical state machine of Mine2 state machine.
+Mine1 is very similar, except that it uses the same bitmap for testing
+collisions with the Missile and the Ship.
+
+\anchor F5s5
+\image html Fig1.09.jpg "Figure 5-5 Mine2 state machine diagram."
+
+\li (1) The Mine starts in the "unused" state.
+
+\li (2) The Tunnel object plants a Mine by dispatching the <TT>MINE_PLANT(x,
+y)</TT> event to the Mine. The Tunnel provides the <TT>(x, y)</TT> coordinates
+as the original position of the Mine.
+
+\li (3) When the Mine scrolls off the display the state
+machine transitions to "unused".
+
+\li (4) When the Mine hits the Ship the state machine transitions to "unused".
+
+\li (5) When the Mine scrolls finishes exploding the state machine transitions to
+"unused".
+
+\li (6) When the Mine is recycled by the Tunnel object the state machine
+transitions to "unused".
+
+\li (7) The exit action in the "unused" state posts the MINE_DISABLDED(mine_id)
+event to the Tunnel active object. Through this event, the Mine informs the
+Tunnel that it's becoming disabled, so that Tunnel can update its
+<TT>mines[]</TT> array (see also \ref F5s4 "Figure 5-4"(4)). The mine_id parameter
+of the event becomes the index into the <TT>mines[]</TT> array. Please note
+that generating the <TT>MINE_DISABLDED(mine_id)</TT> event in the exit action
+from "used" is much safer and more maintainable than repeating this action in
+each individual transition (3), (4), (5), and (6).
+
+Prev: \ref design \n
+Next: \ref events
+
+\image html logo_ql_TM.jpg
+Copyright &copy; 2002-2011 Quantum Leaps, LLC. All Rights Reserved.\n
+http://www.state-machine.com */
+
+/** \page events 6. Defining Event Signals and Event Parameters
+
+<I>This QP/C Tutorial is adapted from Chapter 1 of \ref PSiCC2\n
+by Miro Samek, the founder and president of Quantum Leaps, LLC.</I>
+
+\image html qp_tutorial.jpg
+
+Prev: \ref active_objects \n
+Next: \ref coding_hsm
+
+The key events in the "Fly 'n' Shoot" game have been identified in the
+sequence diagram in \ref F4s1 "Figure 4-1". Other events have been invented during
+the state machine design stage. In any case, you must have noticed that events
+consist really of two parts. The part of the event called the signal conveys
+the type of the occurrence (what happened). For example, the \c TIME_TICK
+signal conveys the arrival of a time tick, while \c PLAYER_SHIP_MOVE signal
+conveys that the player wants to move the Ship. An event can also contain
+additional quantitative information about the occurrence in form of event
+parameters. For example, the \c PLAYER_SHIP_MOVE signal is accompanied by the
+parameters <TT>(x, y)</TT> that contain the quantitative information as to
+where exactly to move the Ship.  In QP, events are represented as instances of
+the QEvent structure provided by the framework. Specifically, the QEvent
+structure contains the member sig, to represent the signal of that event.
+Event parameters are added in the process of inheritance, as described in the
+sidebar \ref derivation.
+
+\section enumerating 6.1 Enumerating Event Signals and Defining Event Parameters
+
+Because events are explicitly shared among most of the application components,
+it is convenient to declare them in the separate header file game.h shown
+\ref L6s1 "Listing 6-1". The explanation section immediately following the
+listing illuminates the interesting points.
+
+\anchor L6s1
+<STRONG>Listing 6-1 Signals, event structures, and active object interfaces
+defined in file game.h.</STRONG>
+\code
+ (1) enum GameSignals {                              /* signals used in the game */
+ (2)     TIME_TICK_SIG = Q_USER_SIG,                  /* published from tick ISR */
+         PLAYER_TRIGGER_SIG, /* published by Player (ISR) to trigger the Missile */
+         PLAYER_QUIT_SIG,          /* published by Player (ISR) to quit the game */
+         GAME_OVER_SIG,          /* published by Ship when it finishes exploding */
+         /* insert other published signals here ... */
+ (3)     MAX_PUB_SIG,                               /* the last published signal */
+
+         PLAYER_SHIP_MOVE_SIG,  /* posted by Player (ISR) to the Ship to move it */
+         BLINK_TIMEOUT_SIG,           /* signal for Tunnel's blink timeout event */
+         SCREEN_TIMEOUT_SIG,         /* signal for Tunnel's screen timeout event */
+         TAKE_OFF_SIG,    /* from Tunnel to Ship to grant permission to take off */
+         HIT_WALL_SIG,            /* from Tunnel to Ship when Ship hits the wall */
+         HIT_MINE_SIG,     /* from Mine to Ship or Missile when it hits the mine */
+         SHIP_IMG_SIG,     /* from Ship to the Tunnel to draw and check for hits */
+         MISSILE_IMG_SIG,  /* from Missile the Tunnel to draw and check for hits */
+         MINE_IMG_SIG,            /* sent by Mine to the Tunnel to draw the mine */
+         MISSILE_FIRE_SIG,                /* sent by Ship to the Missile to fire */
+         DESTROYED_MINE_SIG, /* from Missile to Ship when Missile destroyed Mine */
+         EXPLOSION_SIG,     /* from any exploding object to render the explosion */
+         MINE_PLANT_SIG,                  /* from Tunnel to the Mine to plant it */
+         MINE_DISABLED_SIG,      /* from Mine to Tunnel when it becomes disabled */
+         MINE_RECYCLE_SIG,         /* sent by Tunnel to Mine to recycle the mine */
+         SCORE_SIG,   /* from Ship to Tunnel to adjust game level based on score */
+         /* insert other signals here ... */
+ (4)     MAX_SIG                           /* the last signal (keep always last) */
+     };
+
+ (5) typedef struct ObjectPosEvtTag {
+ (6)     QEvent super;                                /* extend the QEvent class */
+ (7)     uint8_t x;                              /* the x-position of the object */
+ (8)     uint8_t y;                              /* new y-position of the object */
+     } ObjectPosEvt;
+
+     typedef struct ObjectImageEvtTag {
+         QEvent super;                                /* extend the QEvent class */
+         uint8_t x;                              /* the x-position of the object */
+         int8_t  y;                              /* the y-position of the object */
+         uint8_t bmp;                   /* the bitmap ID representing the object */
+     } ObjectImageEvt;
+
+     typedef struct MineEvtTag {
+         QEvent super;                                /* extend the QEvent class */
+         uint8_t id;                                       /* the ID of the Mine */
+     } MineEvt;
+
+     typedef struct ScoreEvtTag {
+         QEvent super;                                /* extend the QEvent class */
+         uint16_t score;                                    /* the current score */
+     } ScoreEvt;
+
+     /* opaque pointers to active objects in the application */
+ (9) extern QActive * const AO_Tunnel;
+(10) extern QActive * const AO_Ship;
+(11) extern QActive * const AO_Missile;
+
+     /* active objects' "constructors" */
+(12) void Tunnel_ctor(void);
+(13) void Ship_ctor(void);
+(14) void Missile_ctor(void);
+\endcode
+
+\li (1) In QP, signals of events are simply enumerated constants. Placing all
+signals in a single enumeration is particularly convenient to avoid
+inadvertent overlap in the numerical values of different signals.
+
+\li (2) The application-level signals do not start from zero but rather are offset
+by the constant #Q_USER_SIG. This is because QP reserves the lowest few
+signals for the internal use and provides the constant #Q_USER_SIG as an
+offset from which user-level signals can start. Please also note that by
+convention, I attach the suffix \c _SIG to all signals so that I can easily
+distinguish signals from other constants. I drop the suffix \c _SIG in the
+state diagrams to reduce the clutter.
+
+\li (3) The constant \c MAX_PUB_SIG delimits the published signals from the rest.
+The publish-subscribe event delivery mechanism consumes some RAM, which is
+proportional to the number of published signals. I save some RAM by providing
+the lower limit of published signals to QP (\c MAX_PUB_SIG) rather than
+maximum of all signals used in the application. (See also
+\ref L3s1 "Listing 3-1"(9)).
+
+\li (4) The last enumeration \c MAX_SIG indicates the maximum of all signals used
+in the application.
+
+\li (5) The event structure \c ObjectPosEvt defines a "class" of events that
+convey the object's position on the display in the event parameters.
+
+\li (6) The structure \c ObjectPosEvt derives from the base structure QEvent, as
+explained in the sidebar \ref derivation.
+
+\li (7-8) The structure \c ObjectPosEvt adds parameters \c x and \c y, which are
+coordinates of the object on the display.
+
+\li (9-11) These global pointers represent active objects in the application and
+are used for posting events directly to active objects. Because the pointers
+can be initialized at compile time, I like to declare them const, sot that
+they can be placed in ROM. The active object pointers are "opaque", because
+they cannot access the whole active object, but only the part inherited from
+the QActive structure. I'll have more to say about this in the next section.
+
+\li (12-14) These functions perform an early initialization of the active objects
+in the system. They play the role of static "constructors", which in C you
+need to call explicitly, typically at the beginning of main() (see also
+\ref L3s1 "Listing 3-1"(10-12)).
+
+\section generating 6.2 Generating, Posting, and Publishing Events
+
+The QF framework supports two types of asynchronous event exchange:
+
+-# The simple mechanism of direct event posting supported through the
+functions QActive_postFIFO() and QActive_postLIFO(), where the producer of an
+event directly posts the event to the event queue of the consumer active
+object.
+-# A more sophisticated publish-subscribe event delivery mechanism supported
+through the functions QF_publish() and QActive_subscribe(), where the
+producers of the events "publish" them to the framework, and the framework
+then delivers the events to all active objects that had "subscribed" to these
+events.
+
+In QF, any part of the system can produce events, not necessarily only the
+active objects. For example, interrupt service routines (ISRs) or device
+drivers can also produce events. On the other hand, only active objects can
+consume events, because only active objects have event queues.
+
+\note QF also provides "raw" thread-safe event queues (struct QEQueue), which
+can consume events as well. These "raw" thread-safe queues cannot block and
+are intended to deliver events to ISRs or device drivers. Please refer to
+Chapter 7 of \ref PSiCC2 for more details.
+
+The most important characteristic of event management in QF is that the
+framework passes around only pointers to events, not the events themselves. QF
+never copies the events by value ("zero-copy" policy); even in case of
+publishing events that often involves multicasting the same event to multiple
+subscribers. The actual event instances are either constant events statically
+allocated at compile time, or dynamic events allocated at runtime from one of
+the event pools that the framework manages. \ref L6s2 "Listing 6-2" provides
+examples of publishing static events and posting dynamic events from the
+interrupt service routines (ISRs) of the "Fly 'n' Shoot" version for the
+ARM-Cortex board (file \c
+&lt;qpc&gt;\\examples\\arm-cortex\\vanilla\\iar\\game-ev-lm3s811\\bsp.c). In
+the upcoming Section \ref coding_hsm you will see other examples of event
+posting from active objects in the state machine code.
+
+\anchor L6s2
+<STRONG>Listing 6-2 Generating, posting , and publishing events from the ISRs
+in bsp.c for the ARM-Cortex board.</STRONG>
+\code
+ (1) void ISR_SysTick(void) {
+ (2)     static QEvent const tickEvt = { TIME_TICK_SIG, 0 };
+ (3)     QF_publish(&tickEvt);      /* publish the tick event to all subscribers */
+ (4)     QF_tick();                             /* process all armed time events */
+     }
+     /*..........................................................................*/
+ (5) void ISR_ADC(void) {
+         static uint32_t adcLPS = 0;            /* Low-Pass-Filtered ADC reading */
+         static uint32_t wheel = 0;                   /* the last wheel position */
+         unsigned long tmp;
+
+         ADCIntClear(ADC_BASE, 3);                    /* clear the ADC interrupt */
+ (6)     ADCSequenceDataGet(ADC_BASE, 3, &tmp);    /* read the data from the ADC */
+
+         /* 1st order low-pass filter: time constant ~= 2^n samples
+          * TF = (1/2^n)/(z-((2^n - 1)/2^n)),
+          * e.g., n=3, y(k+1) = y(k) - y(k)/8 + x(k)/8 => y += (x - y)/8
+          */
+ (7)     adcLPS += (((int)tmp - (int)adcLPS + 4) >> 3);       /* Low-Pass-Filter */
+
+         /* compute the next position of the wheel */
+ (8)     tmp = (((1 << 10) - adcLPS)*(BSP_SCREEN_HEIGHT - 2)) >> 10;
+
+         if (tmp != wheel) {                   /* did the wheel position change? */
+ (9)         ObjectPosEvt *ope = Q_NEW(ObjectPosEvt, PLAYER_SHIP_MOVE_SIG);
+(10)         ope->x = (uint8_t)GAME_SHIP_X;               /* x-position is fixed */
+(11)         ope->y = (uint8_t)tmp;
+(12)         QActive_postFIFO(AO_ship, (QEvent *)ope);    /* post to the Ship AO */
+             wheel = tmp;                 /* save the last position of the wheel */
+         }
+         . . .
+     }
+\endcode
+
+\li (1) In the case of the ARM-Cortex board, the function ISR_SysTick() services
+the system clock tick ISR generated by the ARM-Cortex system tick timer.
+
+\li (2) The \c TIME_TICK event never changes, so it can be statically allocated
+just once. This event is declared as const, which means that it can be placed
+in ROM. The initializer list for this event consists of the signal
+\c TIME_TICK_SIG followed by zero. This zero informs the QF framework that
+this event is static and should never be recycled to an event pool.
+
+\li (3) The ISR calls the framework function QF_publish(), which takes the pointer
+to the tickEvt event to deliver to all subscribers.
+
+\li (4) The ISR calls the function QF_tick(), in which it the framework manages
+the armed time events.
+
+\li (5) The function \c ISR_ADC() services the ADC conversions, which ultimately
+deliver the position of the Ship.
+
+\li (6) The ISR reads the data from the ADC.
+
+\li (7-8) A low-pass filter is applied to the raw ADC reading and the
+potentiometer wheel position is computed.
+
+\li (9) The QF macro <TT>Q_NEW(ObjectPosEvt, PLAYER_SHIP_MOVE_SIG)</TT>
+dynamically allocates an instance of the ObjectPosEvt event from an event pool
+managed by QF. The macro also performs the association between the signal
+\c PLAYER_SHIP_MOVE_SIG and the allocated event. The Q_NEW() macro returns the
+pointer to the allocated event.
+
+\note The <TT>PLAYER_SHIP_MOVE(x, y)</TT> event is an example of an event with
+changing parameters. In general, such an event cannot be allocated statically
+(like the \c TIME_TICK event at label (2)) because it can change
+asynchronously next time the ISR executes. Some active objects in the system
+might still be referring to the event via a pointer, so the event should not
+be changing. Dynamic event allocation of QF solves all such concurrency
+issues, because every time a new event is allocated. QF then recycles the
+dynamic events, after it determines that all active objects are done with
+accessing the events.
+
+\li (10-11) The \c x and \c y parameters of the event are assigned.
+
+\li (12) The dynamic event is posted directly to the Ship active object.
+
+Prev: \ref active_objects \n
+Next: \ref coding_hsm
+
+\image html logo_ql_TM.jpg
+Copyright &copy; 2002-2011 Quantum Leaps, LLC. All Rights Reserved.\n
+http://www.state-machine.com */
+
+/**
+\page coding_hsm 7. Coding Hierarchical State Machines
+
+<I>This QP/C Tutorial is adapted from Chapter 1 of \ref PSiCC2\n
+by Miro Samek, the founder and president of Quantum Leaps, LLC.</I>
+
+\image html qp_tutorial.jpg
+
+Prev: \ref events \n
+Next: \ref execution
+
+Contrary to widespread misconceptions, you don't need big design automation
+tools to translate hierarchical state machines (UML statecharts) into
+efficient and highly maintainable C or C++. This section explains how to
+hand-code the Ship state machine from \ref F5s2 "Figure 5-2" with the help of the
+QF real-time framework and the QEP hierarchical processor, which is also part
+of the QP event-driven platform. Once you know how to code this state machine,
+you know how to code them all.
+
+The source code for the Ship state machine is found in the file \c ship.c
+located either in the DOS version or the ARM-Cortex version of the "Fly 'n'
+Shoot" game. I break the explanation of this file into <STRONG>three</STRONG>
+steps.
+
+\section step1 7.1 Step 1: Defining the Ship Structure
+
+In the first step you define the Ship data structure. Just like in case of
+events, you use inheritance to derive the Ship structure from the framework
+structure QActive (see the sidebar \ref derivation). Creating this inheritance
+relationship ties the Ship structure to the QF framework. The main
+responsibility of the QActive base structure is to store the information about
+the current active state of the state machine, as well as the event queue and
+priority level of the Ship active object. In fact, QActive itself derives from
+a simpler QEP structure QHsm that represents just the current active state of
+a hierarchical state machine. On top of that information, almost every state
+machine must also store other "extended-state" information. For example, the
+Ship object is responsible for maintaining the Ship position as well as the
+score accumulated in the game. You supply this additional information by means
+of data members enlisted after the base structure member super, as shown in
+\ref L7s1 "Listing 7-1".
+
+\anchor L7s1
+<STRONG>Listing 7-1 Deriving the Ship structure in file ship.c.</STRONG>
+\code
+ (1) #include "qp_port.h"                                         /* the QP port */
+ (2) #include "bsp.h"                                   /* Board Support Package */
+ (3) #include "game.h"                                       /* this application */
+
+     /* local objects -----------------------------------------------------------*/
+ (4) typedef struct ShipTag {
+ (5)     QActive super;                        /* derive from the QActive struct */
+ (6)     uint8_t x;          /* x-coordinate of the Ship position on the display */
+ (7)     uint8_t y;          /* y-coordinate of the Ship position on the display */
+ (8)     uint8_t exp_ctr;       /* explosion counter, used to animate explosions */
+ (9)     uint16_t score;                            /* running score of the game */
+(10) } Ship;                          /* the typedef-ed name for the Ship struct */
+
+                                                   /* state handler functions... */
+(11) static QState Ship_active   (Ship *me, QEvent const *e);
+(12) static QState Ship_parked   (Ship *me, QEvent const *e);
+(13) static QState Ship_flying   (Ship *me, QEvent const *e);
+(14) static QState Ship_exploding(Ship *me, QEvent const *e);
+
+(15) static QState Ship_initial  (Ship *me, QEvent const *e);
+
+(16) static Ship l_ship;          /* the sole instance of the Ship active object */
+
+     /* global objects ----------------------------------------------------------*/
+(17) QActive * const AO_ship = (QActive *)&l_ship;  /* opaque pointer to Ship AO */
+\endcode
+
+\li (1) Every application-level C-file that uses the QP platform must include the
+\c qp_port.h header file.
+
+\li (2) The \c bsp.h header file contains the interface to the
+Board Support Package.
+
+\li (3) The \c game.h header file contains the declarations of
+events and other facilities shared among the components of the application
+\li (see \ref L6s1 "Listing 6-1").
+
+\li (4) This structure defines the Ship active object.
+
+\note I like to keep active objects, and indeed all state machine objects
+(such as Mines), strictly encapsulated. Therefore, I don't put the state
+machine structure definitions in header files but rather define them right in
+the implementation file, such as ship.c. That way, I can be sure that the
+internal data members of the Ship structure are not known to any other parts
+of the application.
+
+\li (5) The Ship active object structure derives from the framework structure
+QActive, as described in the sidebar \ref derivation.
+
+\li (6-7) The x and y data members represent the position of the Ship on the
+display.
+
+\li (8) The exp_ctr member is used for pacing the explosion animation (see
+also the "exploding" state in the Ship state diagram in \ref F5s2 "Figure 5-2").
+
+\li (9) The score member stores the accumulated score in the game.
+
+\li (10) I use the typedef to define the shorter name Ship equivalent to struct
+ShipTag.
+
+\li (11-14) These four functions are called state-handler functions because they
+correspond one-to-one to the states of the Ship state machine shown in
+\ref F5s2 "Figure 5-2". For example, the \c Ship_active() function represents the
+"active" state. The QEP event processor calls the state handler functions to
+realize the UML semantics of state machine execution.  \c
+&lt;qpc&gt;\\include\\qep.h. All state handler functions have the same
+signature. A state handler function takes the state machine pointer and the
+event pointer as arguments, and returns the status of the operation back to
+the QEP event processor, for example whether the event was handled or not. The
+return type QState is typedef-ed to \c uint8_t in the header file
+\c &lt;qpc&gt;\\include\\qep.h.
+
+\note I use a simple naming convention to strengthen the association between
+the structures and the functions designed to operate on these structures.
+First, I name the functions by combining the typedef'ed structure name with
+the name of the operation (e.g., \c Ship_active). Second, I always place the
+pointer to the structure as the first argument of the associated function and
+I always name this argument <TT>me</TT> (e.g., <TT>Ship_active(Ship *me,
+...)</TT>).
+
+\li (16) In addition to state handler functions, every state machine must declare
+the initial pseudostate, which QEP invokes to execute the top-most initial
+transition (see \ref F5s2 "Figure 5-2"(1)). The initial pseudostate handler
+has signature identical to the regular state handler function.
+
+\li (17) In this line I statically allocate the storage for the Ship active
+object. Please note that the object l_ship is defined static, so that it is
+accessible only locally at the file scope of the ship.c file.
+
+\li (18) In this line I define and initialize the global pointer AO_Ship to the
+Ship active object (see also \ref L6s1 "Listing 6-1"(10)). This pointer is
+"opaque", because it treats the Ship object as the generic QActive base
+structure, rather than the specific Ship structure. The power of an "opaque"
+pointer is that it allows me to completely hide the definition of the Ship
+structure and make it inaccessible to the rest of the application. Still, the
+other application components can access the Ship object to post events
+directly to it via the QActive_postFIFO(QActive *me, QEvent const *e)
+function.
+
+\section step2 7.2 Step 2: Initializing the State Machine
+
+The state machine initialization is divided into the following two steps for
+increased flexibility and better control of the initialization timeline:
+
+-# The state machine "constructor"; and
+-# The top-most initial transition.
+
+The state machine "constructor", such as \c Ship_ctor(), intentionally does
+not execute the top-most initial transition defined in the initial pseudostate
+because at that time some vital objects can be missing and critical hardware
+might not be properly initialized yet3. Instead, the state machine
+"constructor" merely puts the state machine in the initial pseudostate. Later,
+the user code must trigger the top-most initial transition explicitly, which
+happens actually inside the function QActive_start() (see 
+\ref L3s1 "Listing 3-11"(18-20)). \ref L7s2 "Listing 7-2" shows the instantiation
+(the "constructor" function) and initialization (the initial pseudostate) of
+the Ship active object.
+
+\anchor L7s2
+<STRONG>Listing 7-2 Instantiation and Initialization of the Ship active object
+in ship.c.</STRONG>
+\code
+ (1) void Ship_ctor(void) {                                     /* instantiation */
+ (2)     Ship *me = &l_ship;
+ (3)     QActive_ctor(&me->super, (QStateHandler)&Ship_initial);
+ (4)     me->x = GAME_SHIP_X;
+ (5)     me->y = GAME_SHIP_Y;
+     }
+     /*..........................................................................*/
+ (6) QState Ship_initial(Ship *me, QEvent const *e) {          /* initialization */
+ (7)     QActive_subscribe((QActive *)me, TIME_TICK_SIG);
+ (8)     QActive_subscribe((QActive *)me, PLAYER_TRIGGER_SIG);
+
+ (9)     return Q_TRAN(&Ship_active);             /* top-most initial transition */
+     }
+\endcode
+
+\li (1) The global function Ship_ctor() is prototyped in game.h and called at the
+beginning of main().
+
+\li (2) The "me" pointer points to the statically allocated Ship object (see
+\ref L7s1 "Listing 7-1"(16)).
+
+\li (3) Every derived structure is responsible for initializing the part inherited
+from the base structure. The "constructor" QActive_ctor() puts the state
+machine in the initial pseudostate &Ship_initial. (see 
+\ref L6s1 "Listing 6-1"(15)).
+
+\li (4-5) The Ship position is initialized.
+
+\li (6) The Ship_initial() function defines the top-most initial transition in the
+Ship state machine (see \ref F5s2 "Figure 5-2"(1)).
+
+\li (7-8) The Ship active object subscribes to signals \c TIME_TICK_SIG and
+\c PLAYER_TRIGGER_SIG, as specified in the state diagram in
+\ref F5s2 "Figure 5-2"(1).
+
+\li (9) The initial state "active" is specified by invoking the QP macro Q_TRAN().
+
+\note The macro #Q_TRAN() must always follow the return statement.
+
+
+\section step3 7.3 Step 3: Defining State Handler Functions
+
+In the last step, you actually code the Ship state machine by implementing one
+state at a time as a state handler function. To determine what elements belong
+the any given state handler function, you follow around the state's boundary
+in the diagram (\ref F5s2 "Figure 5-2"). You need to implement all transitions
+originating at the boundary, any entry and exit actions defined in the state,
+as well as all internal transitions enlisted directly in the state.
+Additionally, if there is an initial transition embedded directly in the
+state, you need to implement it as well.
+
+Take for example the state "flying" shown in \ref F5s2 "Figure 5-2". This state
+has an entry action and two transitions originating at its boundary:
+\c HIT_WALL and <TT>HIT_MINE(type)</TT>, as well as three internal transitions
+\c TIME_TICK, \c PLAYER_TRIGGER, and <TT>DESTROYED_MINE(score)</TT>. The
+"flying" state nests inside the "active" superstate. \ref L7s3 "Listing 7-3"
+shows two state handler functions of the Ship state machine from
+\ref F5s2 "Figure 5-2". The state handler functions correspond to the states
+"active" and "flying", respectively. The explanation section immediately
+following the listing highlights the important implementation techniques.
+
+\anchor L7s3
+<STRONG>Listing 7-3 State handler functions for states "active" and "flying"
+in ship.c.</STRONG>
+\code
+ (1) QState Ship_active(Ship *me, QEvent const *e) {
+ (2)     switch (e->sig) {
+ (3)         case Q_INIT_SIG: {                     /* nested initial transition */
+ (4)             /* any actions associated with the initial transition */
+ (5)             return Q_TRAN(&Ship_parked);
+             }
+ (6)         case PLAYER_SHIP_MOVE_SIG: {
+ (7)             me->x = ((ObjectPosEvt const *)e)->x;
+ (8)             me->y = ((ObjectPosEvt const *)e)->y;
+ (9)             return Q_HANDLED();
+             }
+         }
+(10)     return Q_SUPER(&QHsm_top);                     /* return the superstate */
+     }
+     /*..........................................................................*/
+     QState Ship_flying(Ship *me, QEvent const *e) {
+         switch (e->sig) {
+(11)         case Q_ENTRY_SIG: {
+(12)             ScoreEvt *sev;
+
+                 me->score = 0;                               /* reset the score */
+(13)             sev = Q_NEW(ScoreEvt, SCORE_SIG);
+(14)             sev->score = me->score;
+(15)             QActive_postFIFO(AO_Tunnel, (QEvent *)sev);
+(16)             return Q_HANDLED();
+             }
+             case TIME_TICK_SIG: {
+                 /* tell the Tunnel to draw the Ship and test for hits */
+                 ObjectImageEvt *oie = Q_NEW(ObjectImageEvt, SHIP_IMG_SIG);
+                 oie->x   = me->x;
+                 oie->y   = me->y;
+                 oie->bmp = SHIP_BMP;
+                 QActive_postFIFO(AO_Tunnel, (QEvent *)oie);
+
+                 ++me->score;  /* increment the score for surviving another tick */
+
+                 if ((me->score % 10) == 0) {           /* is the score "round"? */
+                     ScoreEvt *sev = Q_NEW(ScoreEvt, SCORE_SIG);
+                     sev->score = me->score;
+                     QActive_postFIFO(AO_Tunnel, (QEvent *)sev);
+                 }
+                 return Q_HANDLED();
+             }
+             case PLAYER_TRIGGER_SIG: {                   /* trigger the Missile */
+                 ObjectPosEvt *ope = Q_NEW(ObjectPosEvt, MISSILE_FIRE_SIG);
+                 ope->x = me->x;
+                 ope->y = me->y + SHIP_HEIGHT - 1;
+                 QActive_postFIFO(AO_Missile, (QEvent *)ope);
+                 return Q_HANDLED();
+             }
+             case DESTROYED_MINE_SIG: {
+                 me->score += ((ScoreEvt const *)e)->score;
+                 /* the score will be sent to the Tunnel by the next TIME_TICK */
+                 return Q_HANDLED();
+             }
+(17)         case HIT_WALL_SIG:
+(18)         case HIT_MINE_SIG: {
+(19)             /* any actions associated with the transition */
+(20)             return Q_TRAN(&Ship_exploding);
+             }
+         }
+(21)     return Q_SUPER(&Ship_active);                  /* return the superstate */
+     }
+\endcode
+
+\li (1) Each state handler must have the same signature, that is, it must take
+two parameters: the state machine pointer "me" and the pointer to QEvent. The
+keyword const before the '*' in the event pointer declaration means that the
+event pointed to by that pointer cannot be changed inside the state handler
+function (i.e., the event is read-only). A state handler function must return
+QState, which conveys the status of the event handling to the QEP event
+processor.
+
+\li (2) Typically, every state handler is structured as a switch statement
+that discriminates based on the signal of the event signal e->sig.
+
+\li (3) This line of code pertains to the nested initial transition 
+\ref F5s2 "Figure 5-2"(2). QEP provides a reserved signal #Q_INIT_SIG that the
+framework passes to the state handler function when it wants to execute the
+initial transition.
+
+\li (4) You can enlist any actions associated with this initial transition
+(none in this particular case).
+
+\li (5) You designate the target substate with the Q_TRAN() macro. This macro
+must always follow the return statement, through which the state handler
+function informs the QEP event processor that the transition has been taken.
+
+\note The initial transition must necessarily target a direct or transitive
+substate of a given state. An initial transition cannot target a peer state or
+go up in state hierarchy to higher-level states, which in the UML would
+represent a "malformed" state machine.
+
+\li (6) This line of code pertains to the internal transition
+<TT>PLAYER_SHIP_MOVE_SIG(x, y)</TT> in \ref F5s2 "Figure 5-2"(3).
+
+\li (7-8) You access the data members of the Ship state machine via the "me"
+argument of the state handler function. You access the event parameters via
+the "e" argument. You need to cast the event pointer from the generic QEvent
+base class to the specific event structure expected for the
+PLAYER_SHIP_MOVE_SIG, which is ObjectPosEvt in this case.
+
+\note The association between the event signal and event structure (event
+parameters) is established at the time the event is generated. All recipients
+of that event must know about this association to perform the cast to the
+correct event structure.
+
+\li (9) You terminate the case statement with "<TT>return Q_HANDLED()</TT>",
+which informs the QEP event processor that the event has been handled (but no
+transition has been taken).
+
+\li (10) The final return from a state handler function designates the
+superstate of that state by means of the QEP macro #Q_SUPER(). The final
+return statement from a state handler function represents the single point of
+maintenance for changing the nesting level of a given state. The state
+"active" in \ref F5s2 "Figure 5-2" has no explicit superstate, which means
+that it is implicitly nested in the "top" state. The "top" state is a UML
+concept that denotes the ultimate root of the state hierarchy in a
+hierarchical state machine. QEP provides the "top" state as a state handler
+function QHsm_top(), and therefore the Ship_active() state handler returns the
+pointer &QHsm_top.
+
+\note In C and C++, a pointer-to-function QHsm_top() can be written either as
+QHsm_top, or &QHsm_top. Even though the notation QHsm_top is more succinct, I
+prefer adding the ampersand explicitly, to leave absolutely no doubt that I
+mean a pointer-to-function &QHsm_top.
+
+\li (11) This line of code pertains to the entry action into state "flying"
+(\ref F5s2 "Figure 5-2"(5)). QEP provides a reserved signal ::Q_ENTRY_SIG that
+the framework passes to the state handler function when it wants to execute
+the entry actions.
+
+\li (12) The entry action to "flying" posts the SCORE event to the Tunnel
+active object (\ref F5s2 "Figure 5-2"(5)). This line defines a temporary
+pointer to the event structure ScoreEvt.
+
+\li (13) The QF macro <TT>Q_NEW(ScoreEvt, SCORE_SIG)</TT> dynamically
+allocates an instance of the ScoreEvt from an event pool managed by QF. The
+macro also performs the association between the signal SCORE_SIG and the
+allocated event. The #Q_NEW() macro returns the pointer to the allocated
+event.
+
+\li (14) The score parameter of the ScoreEvt is set from the state machine
+member me->score.
+
+\li (15) The SCORE(me->score) event is posted directly to the Tunnel active
+object by means of the QP function QActive_postFIFO(). The arguments of this
+function are the recipient active object (AO_Tunnel in this case) and the
+pointer to the event (the temporary pointer sev in this case).
+
+\li (16) You terminate the case statement with "<TT>return Q_HANDLED()</TT>",
+which informs QEP that the entry actions have been handled.
+
+\li (17-18) These two lines of code pertain to the state transitions from
+"flying" to "exploding" (\ref F5s2 "Figure 5-2"(9, 10)).
+
+\li (19) You can enlist any actions associated with the transition (none in
+this particular case).
+
+\li (20) You designate the target of the transition with the #Q_TRAN() macro.
+
+\li (21) The final return from a state handler function designates the
+superstate of that state. The state "flying" in \ref F5s2 "Figure 5-2" nests
+in the state "active", so the state handler Ship_flying() returns the pointer
+&Ship_active wrapped with the macro Q_SUPER().
+
+When implementing state handler functions you need to keep in mind that the
+QEP event processor is in charge here rather than your code. QEP will invoke a
+state handler function for various reasons: for hierarchical event processing,
+for execution of entry and exit actions, for triggering initial transitions,
+or even just to elicit the superstate of a given state handler. Therefore, you
+should not assume that a state handler would be invoked only for processing
+signals enlisted in the case statements. You should avoid any code outside the
+switch statement, especially code that would have side effects.
+
+Prev: \ref events \n
+Next: \ref execution
+
+\image html logo_ql_TM.jpg
+Copyright &copy; 2002-2011 Quantum Leaps, LLC. All Rights Reserved.\n
+http://www.state-machine.com */
+
+/**
+\page execution 8. Using the Built-in Real-Time Kernels and Third-Party RTOSes
+
+<I>This QP/C Tutorial is adapted from Chapter 1 of \ref PSiCC2\n
+by Miro Samek, the founder and president of Quantum Leaps, LLC.</I>
+
+\image html qp_tutorial.jpg
+
+Prev: \ref coding_hsm \n
+Next: \ref tracing
+
+As you saw in \ref L3s1 "Listing 3-1"(21), the \c main() function eventually
+gives control to the event-driven framework by calling QF_run() to execute the
+application. In this section, I briefly explain how QF allocates the CPU
+cycles to various tasks within the system and what options you have in
+choosing the execution model.
+
+\section using_vanilla 8.1 Simple Non-Preemptive "Vanilla" Kernel
+
+In the simplest configuration, the "Fly 'n' Shoot" game executes under the
+simple cooperative "vanilla" kernel, which is provided in the QP. The
+"vanilla" kernel operates by constantly polling all event queues of active
+objects in an endless loop. The kernel always selects the highest-priority
+active object ready to run, which is the highest-priority active object with a
+non-empty event queue.
+
+\note The "vanilla" kernel is so simple that many commercial real-time
+frameworks don't even call it a kernel . Instead, this configuration is simply
+referred to as "without an RTOS". However, if you want to understand what it
+means to execute active objects "without an RTOS" and what execution profile
+you can expect in this case, you need to realize that a simple cooperative
+vanilla kernel is indeed involved.
+
+The interrupt service routines (ISRs) can preempt the execution of active
+objects at any time, but due to the simplistic nature of the "vanilla" kernel,
+every ISR returns to exactly the preemption point. If the ISR posts or
+publishes an event to any active object, the processing of this event won't
+start until the current RTC step completes. The maximum time an event for the
+highest-priority active object can be delayed this way is called the
+task-level response. With the non-preemptive "vanilla" kernel, the task-level
+response is equal to the longest RTC step of all active objects in the system.
+Please note that the task-level response of the "vanilla" kernel is still a
+lot better than the traditional "superloop" (a.k.a., main+ISRs) architecture.
+I'll have more to say about this in the upcoming Section \ref comparison,
+where I compare the event-driven "Fly 'n' Shoot" example to the traditionally
+structured "Quickstart" application.
+
+The task-level response of the simple "vanilla" kernel turns out to be
+adequate for surprisingly many applications, because state machines by nature
+handle events quickly without a need to busy-wait for events. (A state machine
+simply runs-to-completion and becomes dormant until another event arrives).
+Please also note that often you can make the task-level response as fast as
+you need by breaking up longer RTC steps into shorter ones (e.g., by using the
+"Reminder" state pattern described in Chapter 5 of \ref PSiCC2.
+
+\section using_QK 8.2 The QK Preemptive Kernel
+
+In some cases, breaking up long RTC steps into short enough pieces might be
+very difficult, and consequently the task-level response of the non-preemptive
+"vanilla" kernel might be too long. An example system could be a GPS receiver.
+Such a receiver performs a lot of floating point number crunching on a
+fixed-point CPU to calculate the GPS position. At the same time, the GPS
+receiver must track the GPS satellite signals, which involves closing control
+loops in sub-millisecond intervals. It turns out that it's not easy to break
+up the position-fix computation into short enough RTC steps to allow reliable
+signal tracking. But the RTC semantics of state machine execution does not
+mean that a state machine has to monopolize the CPU for the duration of the
+RTC step. A preemptive kernel can perform a context switch in the middle of
+the long RTC step to allow a higher-priority active object to run. As long as
+the active objects don't share resources they can run concurrently and
+complete their RTC steps independently.
+
+The QP event-driven platform includes a tiny, fully preemptive, priority-based
+real-time kernel component called QK, which is specifically designed for
+processing events in the RTC fashion. Configuring QP to use the preemptive QK
+kernel is very easy, but as with any fully preemptive kernel you must be very
+careful with any resources shared among active objects5. The "Fly 'n' Shoot"
+example has been purposely designed to avoid any resource sharing among active
+objects, so the application code does not need to change at all to run on top
+of the QK preemptive kerel, or any other preemptive kernel or RTOS for that
+matter. The accompanying code contains the "Fly 'n' Shoot" example with QK in
+the following directory: &lt;qpc&gt;\\examples\\80x86\\qk\\watcom\\l\\game\\.
+You can execute this example in a DOS-console on any standard Windows-based
+PC.
+
+\section using_RTOS 8.3 Traditional OS/RTOS
+
+QP can also work with a traditional operating system (OS), such as Windows or
+Linux, MicroC/OS-II or virtually any real-time operating system (RTOS) to take
+advantage of the existing device drivers, communication stacks, and other
+middleware. The accompanying code contains the "Fly 'n' Shoot" example with
+MicroC/OS-II in the following directory:
+&lt;qpc&gt;\\examples\\80x86\\ucos2\\watcom\\l\\game\\. You can execute this
+example in a DOS-console on any standard Windows-based PC. QP contains a
+platform abstraction layer (PAL), which makes adapting QP to virtually any
+operating system easy. The carefully designed PAL allows tight integration
+with the underlying OS/RTOS by reusing any provided facilities for interrupt
+management, message queues, and memory partitions. I cover porting QP in
+Chapter 8 of \ref PSiCC2.
+
+
+Prev: \ref coding_hsm \n
+Next: \ref tracing
+
+\image html logo_ql_TM.jpg
+Copyright &copy; 2002-2011 Quantum Leaps, LLC. All Rights Reserved.\n
+http://www.state-machine.com */
+
+/**
+\page tracing 9. Using Software Tracing for Testing and Debugging
+
+<I>This QP/C Tutorial is adapted from Chapter 1 of \ref PSiCC2\n
+by Miro Samek, the founder and president of Quantum Leaps, LLC.</I>
+
+\image html qp_tutorial.jpg
+
+Prev: \ref execution \n
+Next: \ref comparison
+
+A running application built of active objects is a highly structured affair
+where all important system interactions funnel through the real-time framework
+(QF) and the state-machine engine (QEP). This offers a unique opportunity to
+use <STRONG>software tracing</STRONG> techniques to gain unprecedented insight
+into the entire system.
+
+Software tracing is a method for obtaining diagnostic information in a live
+environment without the need to stop the application to get the system
+feedback. In a nutshell, software tracing is similar to peppering the code
+with \c printf() statements for logging and debugging, except that
+mature software tracing techniques are much less intrusive and more selective
+than the primitive \n printf().
+
+Due to the inversion of a control, software tracing is particularly effective
+and powerful in combination with the event-driven frameworks. The QP
+event-driven platorm contains the sophisticated software tracing system called
+Quantum Spy (QS). The QS trace data can be thorough enough to produce complete
+sequence diagrams and detailed state machine activity for all state machines
+in the system. You can selectively monitor all event exchanges, event queues,
+event pools, and time events because all these elements are controlled by the
+framework. Additionally, if you use one of the kernels built into QP (the
+vanilla kernel or the preemptive QK kernel), you can obtain all the data
+available to a traditional RTOS as well, such as context switches and mutex
+activity
+
+To show you how software tracing works in practice I present an example of a
+software tracing session. I use the application. All versions of the "Fly 'n'
+Shoot" game contain the QS instrumentation. The tracing instrumentation
+becomes active when you build the "Spy" configuration.
+
+\note To build the "Spy" configuration in DOS version, please execute the \c
+make.bat script with the \c spy argument (\c make \c spy). To buld the "Spy"
+configuration in the ARM-Cortex version, please select the "Spy" configuration
+in the IAR EWARM IDE (see \ref F2s3 "Figure 2-3").
+
+\ref F9s1 "Figure 9-1" shows how to collect the software trace data from the
+DOS version of the "Fly 'n' Shoot" application, which is located in the
+directory
+\<qpc\>\\examples\\80x86\\dos\\watcom\\l\\dpp\\spy\\dpp.exe. You can
+re-build the "Spy" configuration by executing \c make \c spy from the 
+command line. You need to run the \c GAME.EXE executable on a target
+PC with a serial port. You connect the serial port of the target machine to
+the serial port of a Windows or a Linux host workstation via a NULL-modem
+cable.
+
+\anchor F9s1
+\image html Fig11.02.jpg "Figure 9-1 Collecting software trace data from a 80x86 target."
+
+Actually, all versions of "Fly 'n' Shoot" applications included in the
+standard QP distribution are instrumented for software tracing and I encourage
+you to try them all. For example, you can collect trace data from the LM3S811
+board (see \ref F9s2 "Figure 9-2"). The LM3S811 board sends the QS trace data
+through the UART0 connected to the Virtual COM Port (VCP) provided by the USB
+debugger, so the QSPY host application can conveniently receive the trace data
+on the host PC. No additional serial cable is needed.
+
+\anchor F9s2
+\image html Fig11.01.jpg "Figure 9-2 Collecting software trace data from the LM3S811 board."
+
+On the host workstation, you need to start the QSPY host application that
+decompresses and visualizes the QS trace data. The Windows executable of the
+QSPY host application is located in the directory
+&lt;qpc&gt;\\tools\\qspy\\win32\\vc2005\\Release\\qspy.exe. Assuming that this
+directory is your current directory, or is in your path, you invoke this
+console application by typing the following command at the command prompt:
+
+\code
+qspy -c COM1 -b 115200
+\endcode
+
+The first command-line parameter <TT>-c COM1</TT> tells the QSPY host
+application to receive the trace data from COM1. If your target is connected
+to a different COM port, you need to adjust the COM number. The second
+parameter configures the baud rate of the serial port to 115200. Section \ref
+qspy_command explains the comman-line paratmeters of the QSPY host
+application.
+
+\note In the particular case of a Windows PC, you can use the same machine as
+the target and the host at the same time. You need to use a machine with two
+serial ports, which you connect with a NULL modem cable. You can use one
+serial port for the DPP target application running in a DOS-window and the
+other for the QSPY host application.
+
+You might also use a Linux host machine. In case of Linux, you must first
+build the executable by running the \c Makefile located in the directory
+&lt;qpc&gt;/tools/qspy/linux/gnu/. You invoke the Linux executable by typing
+the following command at the command prompt:
+
+\code
+qspy -c /dev/ttyS0 -b 115200
+\endcode
+
+The first parameter <TT>-c /dev/ttyS0</TT> tells the QSPY application to
+receive the trace data from the ttyS0 serial device. If you connected a
+different serial port to the target, you need to adjust the ttyS number.
+
+If everything is connected correctly, the QSPY host application should produce
+the human-readable output of the trace data to the screen. Please refer
+to \ref qspy_page explains the human-readable format as well as importing the
+trace data to MATLAB&reg;.
+
+
+Prev: \ref execution \n
+Next: \ref comparison
+
+\image html logo_ql_TM.jpg Copyright &copy; 2002-2011 Quantum Leaps, LLC. All
+Rights Reserved.\n http://www.state-machine.com */
+
+/** \page comparison 10. Comparison to the Traditional Approach
+
+<I>This QP/C Tutorial is adapted from Chapter 1 of \ref PSiCC2\n
+by Miro Samek, the founder and president of Quantum Leaps, LLC.</I>
+
+\image html qp_tutorial.jpg
+
+Prev: \ref tracing \n
+Next: \ref summary
+
+The "Fly 'n' Shoot" game behaves intentionally almost identically to the
+"Quickstart" application provided in source code with the Luminary Micro
+ARM Cortex-M3 LM3S811 evaluation kit (http://www.luminarymicro.com). In this
+section I'd like to compare the traditional approach represented by the
+"Quickstart" application with the state machine-based solution exemplified in
+the "Fly 'n' Shoot" game.
+
+\ref F10s1 "Figure 10-1"(a) shows schematically the flowchart of the
+"Quickstart" application, while \ref F10s1 "Figure 10-1"(b) shows the
+flowchart of the "Fly 'n' Shoot" game running on top of the cooperative
+"vanilla" kernel. At the highest level, the flowcharts are similar in that
+they both consist of an endless loop surrounding the entire processing. But
+the internal structure of the main loop is very different in the two cases. As
+indicated by the heavy lines in the flowcharts, the "Quickstart" application
+spends most of its time in the tight "event loops" designed to busy-wait for
+certain events, such as the screen update event. In contrast, the "Fly 'n'
+Shoot" application spends most of its time right in the main loop. The QP
+framework dispatches any available event to the appropriate state machine that
+handles the event and returns quickly to the main loop without ever waiting
+for events internally.
+
+\anchor F10s1
+\image html Fig1.11.jpg "Figure 10-1 The control flow in the "Quickstart" application (a), and the Fly 'n' Shoot example (b). The heavy lines represent the most frequently exercised paths through the code."
+
+The "Quickstart" application has much more convoluted flow of control than the
+"Fly 'n' Shoot" example, because the traditional solution is very specific to
+the problem at hand while the state-machine approach is generic. The
+"Quickstart" application is structured very much like a traditional sequential
+program that tries to stay in control from the beginning to the end. From time
+to time, the application pauses to busy-wait for a certain event, whereas the
+code is generally not ready to handle any other events than the one it chooses
+to wait for. All this contributes to the inflexibility of the design. Adding
+new events is hard because the whole structure of the intervening code is
+designed to accept only very specific events and would need to change
+dramatically to accommodate new events. Also, while busy-waiting for the
+screen update event (equivalent to the \c TIME_TICK event in "Fly 'n' Shoot"
+example) the application is really not responsive to any other events. The
+task-level response is hard to characterize and generally depends on the event
+type. The timing established by the hard-coded waiting for the existing events
+might not work well for new events.
+
+In contrast, the "Fly 'n' Shoot" application has a much simpler control flow
+that is purely event-driven and completely generic (see
+\ref F10s1 "Figure 10-1"(b)). The context of each active object component is
+represented as the current state of a state machine, rather than as a certain
+place in the code. That way, hanging in tight "event loops" around certain
+locations in the code corresponding to the current context is unnecessary.
+Instead, a state machine remembers the context very efficiently as a small
+data item (the state-variable, see Chapter 3 of \ref PSiCC2). After processing
+of each event the state machine can return to the common event loop that is
+designed generically to handle all kinds of events. For every event, the state
+machine naturally picks up where it left off and moves on to the next state,
+if necessary. Adding new events is easy in this design, because a state
+machine is responsive to any event at any time. An event-driven,
+state-machine-based application is incomparably more flexible and resilient to
+change than the traditional one.
+
+\note The generic event loop can also very easily detect the situation when no
+events are available, in which case the QP framework calls the QF_onIdle()
+function (see \ref F10s1 "Figure 10-1"(b)). This callback function is designed
+to be customized by the application and is the ideal place to put the CPU in a
+low-power sleep mode to conserve the power. In contrast, the traditional
+approach does not offer any single place to transition to the low-power sleep
+mode, and consequently is much less friendly for implementing truly low-power
+designs.
+
+Prev: \ref tracing \n
+Next: \ref summary
+
+\image html logo_ql_TM.jpg
+Copyright &copy; 2002-2011 Quantum Leaps, LLC. All Rights Reserved.\n
+http://www.state-machine.com */
+
+/** \page summary 11. Summary
+
+<I>This QP/C Tutorial is adapted from Chapter 1 of \ref PSiCC2\n
+by Miro Samek, the founder and president of Quantum Leaps, LLC.</I>
+
+\image html qp_tutorial.jpg
+
+Prev: \ref comparison
+
+If you've never done event-driven programming before, the internal structure
+of the "Fly 'n' Shoot" game must certainly represent a big paradigm shift for
+you. In fact, I hope that it actually blows your mind, because otherwise I'm
+not sure that you really appreciate the complete reversal of control of an
+event-driven program compared to the traditional sequential code. This
+reversal of control, known as the "Hollywood Principle" (don't call us, we'll
+call you), baffles many newcomers, who often find it "mind-boggling",
+"backwards", or "weird".
+
+My main goal in this Tutorial was just to introduce you to the event-driven
+paradigm and the modern state machines to convince you that these powerful
+concepts aren't particularly hard to implement directly in C or C++. Indeed, I
+hope you noticed that the actual coding of the nontrivial "Fly 'n' Shoot" game
+wasn't a big deal at all. All you needed to know was just a few cookie-cutter
+rules for coding state machines and familiarity with a few framework services
+for implementing the actions.
+
+Wile the coding turned out to be essentially a non-issue; the bulk of the
+programming effort was spent on the design of the application. At this point,
+I hope that the "Fly 'n' Shoot" example helps you to get the big picture of
+how the method works. Under the event driven model, the program structure is
+divided into two rough groups: events and state machine components (active
+objects). An event represents the occurrence of something interesting. A state
+machine codifies the reactions to the events, which generally depend both on
+the nature of the event and on the state of the component. While events often
+originate from the outside of your program, such as time ticks or button
+presses in the "Fly 'n' Shoot" game, events can also be generated internally
+by the program itself. For example the Mine components generate notification
+events when they detect a collision with the Missile or the Ship.
+
+An event-driven program executes by constantly checking for possible events
+and, when an event is detected, dispatching the event to the appropriate state
+machine component (see \ref F10s1 "Figure 10-1"(b)). In order for this
+approach to work, the events must be checked continuously and frequently. This
+implies that the state machines must execute quickly, so that the program can
+get back to checking for events. In order to meet this requirement, a state
+machine cannot go into a condition where it is busy-waiting for some long or
+indeterminate time. The most common example of this would be a while loop
+inside a state-handler function, where the condition for termination was not
+under program control, for instance the button press. This kind of program
+structure, an indefinite loop, is referred to as "blocking" code6, and you saw
+examples of it in the "Quickstart" application (see
+\ref F10s1 "Figure 10-1"(a)). In order for the event driven programming model
+to work, you must only write "non-blocking" code.
+
+Finally, the "Fly 'n' Shoot" example demonstrates the use of the event-driven
+platform called QP, which is a collection of components for building
+event-driven application. The QF real-time framework component framework
+embodies the "Hollywood principle", by calling the application code, not the
+other way around. Such arrangement is very typical for event-driven systems
+and application frameworks similar to QF are at the heart of virtually every
+design automation tool on the market today.
+
+The QF framework operates in the "Fly 'n' Shoot" game in its simplest
+configuration, in which QF runs on a bare-metal target processor without any
+operating system. QF can also be configured to work with the build-in
+preemptive real-time kernel called QK (see Chapter 10 of \ref PSiCC2), or can
+be easily ported to almost any traditional OS or RTOS (see Chapter 8 of \ref
+PSiCC2). In fact, you can view the QF framework itself as a high-level,
+event-driven, real-time operating system.
+
+Prev: \ref comparison
+
+\image html logo_ql_TM.jpg
+Copyright &copy; 2002-2011 Quantum Leaps, LLC. All Rights Reserved.\n
+http://www.state-machine.com */
+
+/**
+\page derivation Encapsulation and Single Inheritance in C
+
+Inheritance is the ability to derive new structures based on existing
+structures in order to reuse and organize code. You can implement single
+inheritance in C very simply by literally embedding the base structure as the
+first member of the derived structure. For example, \ref FA1 "Figure 1"(a)
+shows the structure ScoreEvt derived from the base structure QEvent by
+embedding the QEvent instance as the first member of ScoreEvt. To make this
+idiom better stand out, I always name the base structure member super.
+
+\anchor FA1 \image html FA1.jpg "Figure 1 (a) Derivation of structures in C, (b) memory alignment, and (c) the UML class diagram."
+
+As shown in \ref FA1 "Figure 1"(b), such nesting of structures always aligns
+the data member super at the beginning of every instance of the derived
+structure. In particular, this alignment lets you treat a pointer to the
+derived ScoreEvt structure as a pointer to the QEvent base structure.
+Consequently, you can always safely pass a pointer to ScoreEvt to any C
+function that expects a pointer to QEvent. (To be strictly correct in C, you
+should explicitly cast this pointer. In OOP such casting is called upcasting
+and is always safe.) Therefore, all functions designed for the QEvent
+structure are automatically available to the ScoreEvt structure as well as
+other structures derived from QEvent. \ref FA1 "Figure 1"(c) shows the UML
+class diagram depicting the inheritance relationship between ScoreEvt and
+QEvent structures.
+
+QP uses single inheritance quite extensively not just for derivation of events
+with parameters, but also for derivation of state machines and active objects.
+Of course, the C++ version of QP uses the native C++ support for class
+inheritance rather than "derivation of structures".
+
+\image html logo_ql_TM.jpg
+Copyright &copy; 2002-2011 Quantum Leaps, LLC. All Rights Reserved.\n
+http://www.state-machine.com */

+ 16 - 0
doxygen/snippets/qa_run.c

@@ -0,0 +1,16 @@
+/* thread routine for Win32 _beginthread() */
+static void __cdecl run(void *me) { /* the exact signature for _beginthread */
+    do {
+        QEvent const *e;
+
+        QACTIVE_GET_((QActive *)me, e);               /* wait for the event */
+        QF_ACTIVE_DISPATCH_(me, e);   /* dispatch to the active object's SM */
+        QF_gc(e);    /* check if the event is garbage, and collect it if so */
+
+    } while (((QActive *)me)->prio > (uint8_t)0);
+
+    QActive_unsubscribeAll((QActive *)me);  /* unsubscribe from all signals */
+    QF_remove_((QActive *)me); /* remove this object from any subscriptions */
+
+    _endthread();    /* cleanup after the thead and close the thread handle */
+}

+ 4 - 0
doxygen/snippets/qep_qevent.c

@@ -0,0 +1,4 @@
+typedef struct QCalcEvtTag {
+    QEvent super;                                    /* derives from QEvent */
+    uint8_t keyId;                               /* ID of the key depressed */
+} QCalcEvt;

+ 6 - 0
doxygen/snippets/qep_qfsm.c

@@ -0,0 +1,6 @@
+typedef struct QBombTag {
+    QFsm super;                                        /* derives from QFsm */
+    uint8_t timeout;                    /* number of seconds till explosion */
+    uint8_t defuse;                               /* the secret defuse code */
+    uint8_t code;                          /* the current defuse code entry */
+} QBomb;

+ 3 - 0
doxygen/snippets/qep_qfsm_ctor.c

@@ -0,0 +1,3 @@
+void QBomb_ctor(QBomb *me) {
+    QFsm_ctor(&me->super, (QStateHandler)&QBomb_initial);/* superclass ctor */
+}

+ 23 - 0
doxygen/snippets/qep_qfsm_use.c

@@ -0,0 +1,23 @@
+#include "qep.h"                                  /* QEP/C public interface */
+#include "qbomb.h"                           /* QBomb FSM derived from QFsm */
+
+static QBomb l_qbomb;                           /* an instance of QBomb FSM */
+
+int main() {
+    QBombInitEvt ie;                  /* initialization event for QBomb FSM */
+
+    QBomb_ctor(&l_qbomb);   /* QBomb FSM "constructor" invokes QFsm_ctor_() */
+
+    /* set the initialization event ie */
+
+    QFsm_init((QFsm *)&l_qbomb, &ie);         /* trigger initial transition */
+
+    for (;;) {                                                /* event loop */
+        QEvent e;
+        . . .
+        /* wait for the next event and assign it to the event object e */
+        . . .
+        QFsm_dispatch((QFsm *)&l_qbomb, &e);       /* dispatch e to l_qbomb */
+    }
+    return 0;
+}

+ 8 - 0
doxygen/snippets/qep_qhsm.c

@@ -0,0 +1,8 @@
+typedef struct QCalcTag {
+    QHsm super;                                        /* derives from QHsm */
+    double operand1;
+    double operand2;
+    char display[DISP_WIDTH + 1];
+    uint8_t len;
+    uint8_t opKey;
+} QCalc;

+ 3 - 0
doxygen/snippets/qep_qhsm_ctor.c

@@ -0,0 +1,3 @@
+void QCalc_ctor(QCalc *me) {
+    QHsm_ctor(&me->super, (QStateHandler)&QCalc_initial);
+}

+ 19 - 0
doxygen/snippets/qep_qhsm_use.c

@@ -0,0 +1,19 @@
+#include "qep.h"                                  /* QEP/C public interface */
+#include "qcalc.h"                           /* QCalc HSM derived from QHsm */
+
+static QCalc l_qcalc;                           /* an instance of QCalc HSM */
+
+int main() {
+    QCalc_ctor(&l_qcalc);   /* QCalc HSM "constructor" invokes QHsm_ctor_() */
+
+    QHsm_init((QHsm *)&l_qcalc, (QEvent *)0); /* trigger initial transition */
+
+    for (;;) {                                                /* event loop */
+        QEvent e;
+        . . .
+        /* wait for the next event and assign it to the event object e */
+        . . .
+        QHsm_dispatch((QHsm *)&l_qcalc, (QEvent *)&e);        /* dispatch e */
+    }
+    return 0;
+}

+ 23 - 0
doxygen/snippets/qep_qinit.c

@@ -0,0 +1,23 @@
+/* initial pseudostate of the QBomb FSM ....................................*/
+QState QBomb_initial(QBomb *me, QEvent const *e) {
+    Q_REQUIRE(e != (QEvent *)0);           /* initialization event expected */
+    QBomb_updateState(me, "top-INIT");
+    me->timeout = INIT_TIMEOUT;
+    me->defuse  = ((QBombInitEvt const *)e)->defuse;
+
+    return Q_TRAN(&QBomb_setting);                    /* initial transition */
+}
+
+/* state handler function for the QCalc HSM ................................*/
+QState QCalc_on(QCalc *me, QEvent const *e) {
+    switch (e->sig) {
+        . . .
+        case Q_INIT_SIG: {
+            QCalc_updateState(me, "on-INIT");
+            return Q_TRAN(&QCalc_ready);              /* initial transition */
+        }
+        . . .
+    }
+    return Q_SUPER(&QHsm_top);
+}
+

+ 25 - 0
doxygen/snippets/qep_qtran.c

@@ -0,0 +1,25 @@
+/* state handler function for the QBomb FSM ................................*/
+QState QBomb_setting(QBomb *me, QEvent const *e) {
+    switch (e->sig) {
+        . . .
+        case ARM_SIG: {
+            return Q_TRAN(&QBomb_timing);         /* transition to "timing" */
+        }
+    }
+    return Q_IGNORED();
+}
+
+/* state handler function for the QCalc HSM ................................*/
+QState QCalc_begin(QCalc *me, QEvent const *e) {
+    switch (e->sig) {
+        . . .
+        case OPER_SIG: {
+            if (((QCalcEvt *)e)->keyId == KEY_MINUS) {   /* guard condition */
+                return Q_TRAN(&QCalc_negated1); /* transition to "negated1" */
+            }
+            break;
+        }
+    }
+    return Q_SUPER(&QCalc_ready);
+}
+

+ 4 - 0
doxygen/snippets/qf_ctor.c

@@ -0,0 +1,4 @@
+void Philosopher_ctor(Philosopher *me) {
+    QActive_ctor(&me->super, (QStateHandler)&Philosopher_initial);
+    QTimeEvt_ctor(&me->timeEvt, TIMEOUT_SIG);
+}

+ 41 - 0
doxygen/snippets/qf_main.c

@@ -0,0 +1,41 @@
+/* allocate storage for active objects, event queues, event pools,
+* subscriber lists, and stacks.
+*/
+static QEvent const *l_tableQueueSto[N_PHILO];
+static QEvent const *l_philoQueueSto[N_PHILO][N_PHILO];
+static QSubscrList   l_subscrSto[MAX_PUB_SIG];
+
+static union SmallEvent {
+    void *min_size;
+    TableEvt te;
+    /* other event types to go into this pool */
+} l_smlPoolSto[2*N_PHILO];              /* storage for the small event pool */
+
+/*..........................................................................*/
+int main(int argc, char *argv[]) {
+    uint8_t n;
+
+    Philo_ctor();             /* instantiate all Philosopher active objects */
+    Table_ctor();                    /* instantiate the Table active object */
+
+    BSP_init(argc, argv);           /* initialize the Board Support Package */
+
+    QF_init();     /* initialize the framework and the underlying RT kernel */
+
+    QF_psInit(l_subscrSto, Q_DIM(l_subscrSto));   /* init publish-subscribe */
+
+                                               /* initialize event pools... */
+    QF_poolInit(l_smlPoolSto, sizeof(l_smlPoolSto), sizeof(l_smlPoolSto[0]));
+
+    for (n = 0; n < N_PHILO; ++n) {          /* start the active objects... */
+        QActive_start(AO_Philo[n], (uint8_t)(n + 1),
+                      l_philoQueueSto[n], Q_DIM(l_philoQueueSto[n]),
+                      (void *)0, 0, (QEvent *)0);
+    }
+    QActive_start(AO_Table, (uint8_t)(N_PHILO + 1),
+                  l_tableQueueSto, Q_DIM(l_tableQueueSto),
+                  (void *)0, 0, (QEvent *)0);
+    QF_run();                                     /* run the QF application */
+
+    return 0;
+}

+ 15 - 0
doxygen/snippets/qf_post.c

@@ -0,0 +1,15 @@
+extern QActive *AO_Table;
+
+QState Philosopher_hungry(Philosopher *me, QEvent const *e) {
+    TableEvt *pe;
+    switch (e->sig) {
+        case Q_ENTRY_SIG: {
+            pe = Q_NEW(TableEvt, HUNGRY_SIG); /* dynamically allocate event */
+            pe->philNum = me->num;
+            QActive_postFIFO(AO_Table, (QEvent *)pe);     /* direct posting */
+            return Q_HANDLED();
+        }
+        . . .
+    }
+    return Q_SUPER(&QHsm_top);
+}

+ 5 - 0
doxygen/snippets/qf_qactive.c

@@ -0,0 +1,5 @@
+typedef struct PhilosopherTag {
+    QActive super;                                  /* derives from QActive */
+    uint8_t num;                              /* number of this philosopher */
+    QTimeEvt timeEvt;                       /* to timeout thining or eating */
+} Philosopher;

+ 18 - 0
doxygen/snippets/qf_start.c

@@ -0,0 +1,18 @@
+static Philosopher l_philo[N];              /* N Philosopher active objects */
+static QEvent const *l_philQueueSto[N][N];/* storage for Philo event queues */
+static int l_philoStk[N][256]; /* stacks for the Philosopher active objects */
+
+main() {
+    . . .
+    for (n = 0; n < N; ++n) {
+        TableEvt ie;        /* initialization event for the Philosopher HSM */
+        ie.philNum = n;
+        Philosopher_ctor(&l_philo[n]);
+        QActive_start((QActive *)&l_philo[n],       /* Philosopher number n */
+                      (uint8_t)(n*10 + 1),                      /* priority */
+                      l_philoQueueSto[n], Q_DIM(l_philoQueueSto[n]),/*queue */
+                      l_philoStk[n], sizeof(l_philoStk[n]),/*uC/OS-II stack */
+                      (QEvent const *)&ie);         /* initialization event */
+    }
+    . . .
+} 

+ 19 - 0
doxygen/snippets/qf_state.c

@@ -0,0 +1,19 @@
+QState Philosopher_eating(Philosopher *me, QEvent const *e) {
+    TableEvt *pe;
+    switch (e->sig) {
+        case Q_ENTRY_SIG: {
+            QTimeEvt_postIn(&me->timeEvt, (QActive *)me, EAT_TIME);
+            return Q_HANDLED();
+        }
+        case TIMEOUT_SIG: {
+            return Q_TRAN(&Philosopher_thinking);
+        }
+        case Q_EXIT_SIG: {
+            pe = Q_NEW(TableEvt, DONE_SIG);
+            pe->philNum = me->num;
+            QF_publish((QEvent *)pe);
+            return Q_HANDLED();
+        }
+    }
+    return Q_SUPER(&QHsm_top);
+}

+ 13 - 0
doxygen/snippets/qf_subscribe.c

@@ -0,0 +1,13 @@
+QState Table_initial(Table *me, QEvent const *e) {
+    uint8_t n;
+    (void)e;                               /* suppress the compiler warning */
+
+    QActive_subscribe((QActive *)me, HUNGRY_SIG);   /* subscribe to HUNGRY */
+    QActive_subscribe((QActive *)me, DONE_SIG);              /*... to DONE */
+    QActive_subscribe((QActive *)me, TERMINATE_SIG); /*...and to TERMINATE */
+    for (n = 0; n < N; ++n) {
+        me->fork[n] = FREE;
+        me->isHungry[n] = 0;
+    }
+    return Q_TRAN(&Table_serving);
+}

+ 20 - 0
doxygen/snippets/qf_tick.c

@@ -0,0 +1,20 @@
+/* case 1: Interrupt Controller available,
+* "unconditional interrupt unlocking" critical section policy
+* (nesting of critical sections _not_ allowed)
+*/
+interrupt void ISR_timer() {  /* entered with interrupts locked in hardware */
+    QF_INT_UNLOCK(ignore);                             /* unlock interrupts */
+
+    QF_tick();                            /*<-- call the QF tick processing */
+
+    QF_INT_LOCK(ignore);                           /* lock interrupts again */
+    /* send the EOI instruction to the Interrupt Controller */
+}
+
+/* case 2: Interrupt Controller not used,
+* "saving and restoring interrupt status" critical section policy
+* (nesting of critical sections allowed)
+*/
+interrupt void ISR_timer() {
+    QF_tick();                            /*<-- call the QF tick processing */
+}

+ 4 - 0
doxygen/snippets/qf_version.c

@@ -0,0 +1,4 @@
+    printf("Quantum DPP\nQEP %s\nQF  %s, QF port %s\n"
+           "Press ESC to quit...\n",
+           QEP_getVersion(),
+           QF_getVersion(), QF_getPortVersion());

+ 9 - 0
doxygen/snippets/qk_mux.c

@@ -0,0 +1,9 @@
+    QMutex mux;
+    . . .
+    mux = QK_mutexLock(PRIO_CEILING);
+
+    /* access the shared resource */
+
+    QK_mutexUnlock(mux);
+
+    . . . 

+ 25 - 0
doxygen/snippets/qs_filter.c

@@ -0,0 +1,25 @@
+main () {
+    . . .
+
+    if (!QS_INIT("1")) {                   /* Initialize QSpy to use UART 1 */
+        return -1;                             /* Unable to initialize QSpy */
+    }
+    QS_FILTER_IN(QS_ALL_RECORDS);     /* start with enabling all QS records */
+
+    QS_FILTER_OUT(QS_QK_INT_LOCK);      /* disable QS output of this record */
+    QS_FILTER_OUT(QS_QK_INT_UNLOCK);    /* disable QS output of this record */
+    QS_FILTER_OUT(QS_QK_ISR_ENTRY);     /* disable QS output of this record */
+    QS_FILTER_OUT(QS_QK_ISR_EXIT);      /* disable QS output of this record */
+
+    QS_FILTER_SM_OBJ(&philo[3]);    /* trace only this state machine object */
+
+    QS_FILTER_AO_OBJ(&philo[3]);           /* trace only this active object */
+
+    QS_FILTER_MP_OBJ(regSizePoolSto);         /* trace only this event pool */
+
+    QS_FILTER_EQ_OBJ(&rawQueue);             /* trace only this event queue */
+
+    QS_FILTER_TE_OBJ(&philo[3].timeEvt);      /* trace only this time event */
+
+    . . .
+}

+ 13 - 0
doxygen/snippets/qs_objDic.c

@@ -0,0 +1,13 @@
+void tableStart(uint8_t prio,
+                QEvent const *qSto[], uint32_t qLen,
+                void *stkSto, uint32_t stkSize)
+{
+    static Table table;
+
+    QS_OBJ_DICTIONARY(table);        /* provide object dictionary for table */
+
+    Table_ctor(&table);
+    QActive_start((QActive *)&table, prio,
+                  qSto, qLen, stkSto, stkSize,
+                  (QEvent *)0);
+}

+ 9 - 0
doxygen/snippets/qs_onGetTime.c

@@ -0,0 +1,9 @@
+#ifdef Q_SPY
+
+QSTimeCtr QS_onGetTime(void) {
+    return (QSTimeCtr)clock();
+}
+
+. . .
+
+#endif /* Q_SPY */

+ 20 - 0
doxygen/snippets/qs_sigDic.c

@@ -0,0 +1,20 @@
+QState Table_initial(Table *me, QEvent const *e) {
+    uint8_t n;
+    (void)e;                               /* suppress the compiler warning */
+
+    QS_SIG_DICTIONARY(HUNGRY_SIG, me);/* output signal dictionary QS record */
+    QS_SIG_DICTIONARY(DONE_SIG, me);  /* output signal dictionary QS record */
+    QS_SIG_DICTIONARY(EAT_SIG, 0);    /* output signal dictionary QS record */
+
+    QS_FUN_DICTIONARY(Table_serving);
+
+    QActive_subscribe((QActive *)me, HUNGRY_SIG);
+    QActive_subscribe((QActive *)me, DONE_SIG);
+    QActive_subscribe((QActive *)me, TERMINATE_SIG);
+
+    for (n = 0; n < N; ++n) {
+        me->fork[n] = FREE;
+        me->isHungry[n] = 0;
+    }
+    return Q_TRAN(&Table_serving);
+}

+ 78 - 0
doxygen/snippets/qs_sigLog.txt

@@ -0,0 +1,78 @@
+qspy -fqs.bin -S2 -Q2 -P4 -p4 -T4    
+QSpy 1.1.03
+Thu Nov 17 09:56:10 2005
+-f qs.bin
+-S 2
+-Q 2
+-P 4
+-p 4
+-T 4
+. . .      . . .
+           Obj Dic: 00419048->table
+           EQ.INIT: Obj=00419050 Len= 5
+0000000000 AO.ADD : Active=table Prio=51
+           Fun Dic: 00401CEE->Table_serving
+           Sig Dic: 00000004,Obj=00419048 ->HUNGRY_SIG
+           Sig Dic: 00000005,Obj=00419048 ->DONE_SIG
+           Sig Dic: 00000006,Obj=00000000 ->EAT_SIG
+0000000000 AO.SUB : Active=table Sig=HUNGRY_SIG
+0000000000 AO.SUB : Active=table Sig=DONE_SIG
+0000000000 AO.SUB : Active=table Sig=00000007,Obj=00419048
+           Q_INIT : Obj=table Source=00403CE0 Target=Table_serving
+0000000000 ==>Init: Obj=table New=Table_serving
+. . .      . . .
+
+// the Philosophers become hungry...
+
+
+0000000007 AO.FIFO: Obj=table Evt(Sig=HUNGRY_SIG, Pool=1, Ref= 1)
+           Queue(nUsed=  0, nMax=  0)
+0000000007 AO.FIFO: Obj=table Evt(Sig=HUNGRY_SIG, Pool=1, Ref= 1)
+           Queue(nUsed=  0, nMax=  0)
+0000000007 AO.FIFO: Obj=table Evt(Sig=HUNGRY_SIG, Pool=1, Ref= 1)
+           Queue(nUsed=  1, nMax=  1)
+0000000007 AO.FIFO: Obj=table Evt(Sig=HUNGRY_SIG, Pool=1, Ref= 1)
+           Queue(nUsed=  2, nMax=  2)
+           Q_ENTRY: Obj=philo[2] State=Philosopher_hungry
+0000000007 AO.GET : Active= table Evt(Sig=HUNGRY_SIG, Pool=1, Ref= 1)
+           Queue(nUsed=  2)
+0000000007 AO.FIFO: Obj=table Evt(Sig=HUNGRY_SIG, Pool=1, Ref= 1)
+           Queue(nUsed=  2, nMax=  3)
+           Q_ENTRY: Obj=philo[4] State=Philosopher_hungry
+           Q_ENTRY: Obj=philo[1] State=Philosopher_hungry
+           Q_ENTRY: Obj=philo[3] State=Philosopher_hungry
+0000000007 ==>Tran: Obj=philo[2] Sig=TIMEOUT_SIG Source=Philosopher_thinking
+           New=Philosopher_hungry
+0000000007 ==>Tran: Obj=philo[4] Sig=TIMEOUT_SIG Source=Philosopher_thinking
+           New=Philosopher_hungry
+0000000007 ==>Tran: Obj=philo[3] Sig=TIMEOUT_SIG Source=Philosopher_thinking
+           New=Philosopher_hungry
+0000000007 ==>Tran: Obj=philo[1] Sig=TIMEOUT_SIG Source=Philosopher_thinking
+           New=Philosopher_hungry
+           Q_ENTRY: Obj=philo[0] State=Philosopher_hungry
+0000000007 ==>Tran: Obj=philo[0] Sig=TIMEOUT_SIG Source=Philosopher_thinking
+           New=Philosopher_hungry
+           
+// user record output           
+0000000007 User070: 2 hungry
+
+// Table grants permissions to eat   
+0000000007 NEW    : Evt(Sig=EAT_SIG, size=    6)
+0000000007 MP.GET : Obj=00418E18 nFree=   5 nMin=   5
+0000000007 AO.FIFO: Obj=philo[4] Evt(Sig=EAT_SIG, Pool=1, Ref= 0)
+           Queue(nUsed=  0, nMax=  0)
+0000000007 AO.FIFO: Obj=philo[3] Evt(Sig=EAT_SIG, Pool=1, Ref= 0)
+           Queue(nUsed=  0, nMax=  0)
+0000000007 AO.FIFO: Obj=philo[2] Evt(Sig=EAT_SIG, Pool=1, Ref= 0)
+           Queue(nUsed=  0, nMax=  0)
+0000000007 AO.FIFO: Obj=philo[1] Evt(Sig=EAT_SIG, Pool=1, Ref= 0)
+           Queue(nUsed=  0, nMax=  0)
+0000000007 AO.FIFO: Obj=philo[0] Evt(Sig=EAT_SIG, Pool=1, Ref= 0)
+           Queue(nUsed=  0, nMax=  0)
+0000000007 PUBLISH: Evt(Sig=EAT_SIG, Pool=1, Ref= 5) nSubsr=  5
+0000000007 AO.GETL: Active= philo[4] Evt(Sig=EAT_SIG, Pool=1, Ref= 5)
+0000000007 AO.GETL: Active= philo[2] Evt(Sig=EAT_SIG, Pool=1, Ref= 5)
+0000000007 AO.GETL: Active= philo[3] Evt(Sig=EAT_SIG, Pool=1, Ref= 5)
+0000000007 AO.GETL: Active= philo[1] Evt(Sig=EAT_SIG, Pool=1, Ref= 5)
+0000000007 AO.GETL: Active= philo[0] Evt(Sig=EAT_SIG, Pool=1, Ref= 5)
+. . .      . . .

+ 78 - 0
doxygen/snippets/qs_sigLog0.txt

@@ -0,0 +1,78 @@
+qspy -fqs0.bin -S2 -Q2 -P4 -p4 -T4    
+QSpy 1.1.03
+Thu Nov 17 10:10:22 2005
+-f qs0.bin
+-S 2
+-Q 2
+-P 4
+-p 4
+-T 4
+. . .      . . .
+           Obj Dic: 00419048->table
+           EQ.INIT: Obj=00419050 Len= 5
+0000000000 AO.ADD : Active=table Prio=51
+
+// the signal dictionary entries removed from the binary QS log
+*** Dropped   4 records
+
+0000000000 AO.SUB : Active=table Sig=00000004,Obj=00419048
+0000000000 AO.SUB : Active=table Sig=00000005,Obj=00419048
+0000000000 AO.SUB : Active=table Sig=00000007,Obj=00419048
+           Q_INIT : Obj=table Source=00403CE0 Target=00403CE0
+0000000000 ==>Init: Obj=table New=00401CEE
+. . .      . . .
+
+// the Philosophers become hungry...
+
+
+0000000007 AO.FIFO: Obj=table Evt(Sig=00000004,Obj=00419048, Pool=1, Ref= 1)
+           Queue(nUsed=  0, nMax=  0)
+0000000007 AO.FIFO: Obj=table Evt(Sig=00000004,Obj=00419048, Pool=1, Ref= 1)
+           Queue(nUsed=  0, nMax=  0)
+0000000007 AO.FIFO: Obj=table Evt(Sig=00000004,Obj=00419048, Pool=1, Ref= 1)
+           Queue(nUsed=  1, nMax=  1)
+0000000007 AO.FIFO: Obj=table Evt(Sig=00000004,Obj=00419048, Pool=1, Ref= 1)
+           Queue(nUsed=  2, nMax=  2)
+           Q_ENTRY: Obj=philo[2] State=Philosopher_hungry
+0000000007 AO.GET : Active= table Evt(Sig=00000004,Obj=00419048, Pool=1, Ref= 1)
+           Queue(nUsed=  2)
+0000000007 AO.FIFO: Obj=table Evt(Sig=00000004,Obj=00419048, Pool=1, Ref= 1)
+           Queue(nUsed=  2, nMax=  3)
+           Q_ENTRY: Obj=philo[4] State=Philosopher_hungry
+           Q_ENTRY: Obj=philo[1] State=Philosopher_hungry
+           Q_ENTRY: Obj=philo[3] State=Philosopher_hungry
+0000000007 ==>Tran: Obj=philo[2] Sig=TIMEOUT_SIG Source=Philosopher_thinking
+           New=Philosopher_hungry
+0000000007 ==>Tran: Obj=philo[4] Sig=TIMEOUT_SIG Source=Philosopher_thinking
+           New=Philosopher_hungry
+0000000007 ==>Tran: Obj=philo[3] Sig=TIMEOUT_SIG Source=Philosopher_thinking
+           New=Philosopher_hungry
+0000000007 ==>Tran: Obj=philo[1] Sig=TIMEOUT_SIG Source=Philosopher_thinking
+           New=Philosopher_hungry
+           Q_ENTRY: Obj=philo[0] State=Philosopher_hungry
+0000000007 ==>Tran: Obj=philo[0] Sig=TIMEOUT_SIG Source=Philosopher_thinking
+           New=Philosopher_hungry
+           
+// user record output           
+0000000007 User070: 2 hungry   
+
+// Table grants permissions to eat   
+0000000007 NEW    : Evt(Sig=00000006,Obj=00000000, size=    6)
+0000000007 MP.GET : Obj=00418E18 nFree=   5 nMin=   5
+0000000007 AO.FIFO: Obj=philo[4] Evt(Sig=00000006,Obj=00419000, Pool=1, Ref= 0) 
+           Queue(nUsed=  0, nMax=  0)
+0000000007 AO.FIFO: Obj=philo[3] Evt(Sig=00000006,Obj=00418FBC, Pool=1, Ref= 0)
+           Queue(nUsed=  0, nMax=  0)
+0000000007 AO.FIFO: Obj=philo[2] Evt(Sig=00000006,Obj=00418F78, Pool=1, Ref= 0)
+           Queue(nUsed=  0, nMax=  0)
+0000000007 AO.FIFO: Obj=philo[1] Evt(Sig=00000006,Obj=00418F34, Pool=1, Ref= 0)
+           Queue(nUsed=  0, nMax=  0)
+0000000007 AO.FIFO: Obj=philo[0] Evt(Sig=00000006,Obj=00418EF0, Pool=1, Ref= 0)
+           Queue(nUsed=  0, nMax=  0)
+0000000007 PUBLISH: Evt(Sig=00000006,Obj=00000000, Pool=1, Ref= 5) nSubsr=  5
+0000000007 AO.GETL: Active= philo[4] Evt(Sig=00000006,Obj=00419000, Pool=1, Ref= 5)
+0000000007 AO.GETL: Active= philo[2] Evt(Sig=00000006,Obj=00418F78, Pool=1, Ref= 5)
+0000000007 AO.GETL: Active= philo[3] Evt(Sig=00000006,Obj=00418FBC, Pool=1, Ref= 5)
+0000000007 AO.GETL: Active= philo[1] Evt(Sig=00000006,Obj=00418F34, Pool=1, Ref= 5)
+0000000007 AO.GETL: Active= philo[0] Evt(Sig=00000006,Obj=00418EF0, Pool=1, Ref= 5)
+. . .      . . .

+ 23 - 0
doxygen/snippets/qs_startup.c

@@ -0,0 +1,23 @@
+#ifdef Q_SPY
+
+uint8_t QS_onStartup(void const *arg) {
+    static uint8_t qsBuf[4*1024];                 /* buffer for Quantum Spy */
+
+    QS_initBuf(qsBuf, sizeof(qsBuf));         /* configure the Q-Spy buffer */
+
+    /* configure UART 0/1 for QSPY output ... */
+    if (*(char const *)arg == '0') {                          /* use UART 0 */
+        /* configure UART 0 for QSPY output ... */
+        . . .
+        return (uint8_t)1;                   /* UART 0 successfully opened */
+    }
+    else {                                                    /* use UART 1 */
+        /* configure UART 1 for QSPY output ... */
+        . . .
+        return (uint8_t)1;                   /* UART 1 successfully opened */
+    }
+}
+
+. . .
+
+#endif /* Q_SPY */

+ 14 - 0
doxygen/snippets/qs_user.c

@@ -0,0 +1,14 @@
+enum UserSpyRecords {
+    . . .
+    QS_DPP_DISPLAY = QS_USER               /* define a user QS record types */
+    . . .
+};
+
+void displyPhilStat(uint8_t n, char const *stat) {
+    . . .
+
+    QS_BEGIN(QS_DPP_DISPLAY);                    /* output a user QS record */
+        QS_U8(1, n);
+        QS_STR(stat);
+    QS_END();
+}

+ 240 - 0
examples/80251/vanilla/keil/dpp-mcb251/START251.A51

@@ -0,0 +1,240 @@
+;------------------------------------------------------------------------------
+;  This file is part of the C251 Compiler package
+;  Copyright KEIL ELEKTRONIK GmbH 1995 - 2000
+;------------------------------------------------------------------------------
+;  START251.A51:  This code is executed after processor reset.
+;
+;  To translate this file use A251 with the following invocation:
+;
+;     A251 START251.A51  [ MODSRC ] [ SET (ROMHUGE) ]
+;  whereby:
+;     MODSRC         defines the 251 Source Mode  (default is Binary Mode)
+;     SET (ROMHUGE)  defines the ROM (HUGE) Mode  (default is ROM(LARGE) )
+;
+;  To link the modified STARTUP.OBJ file to your application use the following
+;  L251 invocation:
+;
+;     L251 START251.OBJ, <your object file list> <controls>
+;
+;------------------------------------------------------------------------------
+;
+;  251 Configuration Bytes Definition for off-chip (external) config bytes
+;
+$SET (CONFIGB = 0)   ; Set this variable if you want to set external config
+;                    ; bytes at address FF:FFF8 and FF:FFF9.
+;
+; Wait State for PSEN#/RD#/WR# signal except region 01:xxxx (WSA1 & WSA0 Bits)
+; WSA        Val  Description
+; ---        ---  -----------
+WSA  EQU 3  ; 3 = 0 wait state for all regions except region 01:xxxx
+;           ; 2 = extended to 1 wait state  for all regions except 01:xxxx
+;           ; 1 = extended to 2 wait states for all regions except 01:xxxx
+;           ; 0 = extended to 3 wait states for all regions except 01:xxxx
+;
+; Extend ALE pulse
+; XALE       Val  Description
+; ----       ---  -----------
+XALE EQU 1  ; 1 = ALE pulse is one TOSC
+;           ; 0 = ALE pulse is three TOSC, this adds one external wait state
+;
+; RD# and PSEN# Function Select  (RD1 and RD0 Bits)
+; RD         Val  RD Range   PSEN Range  P1.7 Func  Features
+; --         ---  --------   ----------  ---------  --------
+RDRG EQU 3  ; 3 = <=7F:FFFF  >=80:FFFF   P1.7/CEX4  Compatible with 8051
+;           ; 2 = P3.7 only  All address P1.7/CEX4  One additional port pin
+;           ; 1 = RD#=A16    All address P1.7/CEX4  128K External Address space
+;           ; 0 = RD#=A16    All address P1.7=A17   256K External Address space
+;
+; Page Mode Select
+; PAGE       Val  Description
+; ----       ---  -----------
+PAGM EQU 1  ; 1 = Non-page Mode (A15:8 on P2, A7:0/D7:0 on P0, 8051 compatible)
+;           ; 0 = Page Mode (A15:8/D7:0 on P2, A7:0 on P0)
+;
+; Interrupt Mode Select
+; INTR       Val  Description
+; ----       ---  -----------
+INTR EQU 1  ; 1 = Interrupt pushes 4 bytes onto the stack (PC & PSW1)
+;           ; 0 = Interrupt pushes 2 bytes onto the stack (PCL & PCH only)
+;
+; Extended Data Float (EDF) Timing Feature
+; EDF        Val  Description
+; ----       ---  -----------
+EDF  EQU 1  ; 1 = Standard (Compatibility) Mode
+;           ; 0 = extend data float timing for slow memory devices
+;
+; Wait State for PSEN#/RD#/WR# signal for region 01:xxxx (WSB1 & WSB0 Bits)
+; WSB        Val  Description
+; ---        ---  -----------
+WSB  EQU 3  ; 3 = 0 wait state for region 01:xxxx
+;           ; 2 = extended to 1 wait state  for regions 01:xxxx
+;           ; 1 = extended to 2 wait states for regions 01:xxxx
+;           ; 0 = extended to 3 wait states for regions 01:xxxx
+;
+; EPROM/ROM Mapping
+; WSA        Val  Description
+; ---        ---  -----------
+EMAP EQU 1 ;  1 = Map internal ROM only to region FF:xxxx
+;          ;  0 = Map higher 8KB of internal ROM to region 00:E000 - 00:FFFF
+;
+;  Note:  the bit SRC is defined with the A251 directive MODSRC/MODBIN 
+; 
+;------------------------------------------------------------------------------
+;
+;  User-defined Power-On Zero Initialization of Memory
+;
+;  With the following EQU statements the zero initialization of memory
+;  at processor reset can be defined:
+;
+;		; the absolute start-address of EDATA memory is always 0
+EDATALEN	EQU	420H	; the length of EDATA memory in bytes.
+;
+XDATASTART	EQU	10000H	; the absolute start-address of XDATA memory
+XDATALEN	EQU	0	; the length of XDATA memory in bytes.
+;
+HDATASTART	EQU	10000H	; the absolute start-address of HDATA memory
+HDATALEN	EQU	0	; the length of HDATA memory in bytes.
+;
+;  Note:  The EDATA space overlaps physically the DATA, IDATA, BIT and EBIT
+;         areas of the 251 CPU.
+;
+;------------------------------------------------------------------------------
+;
+;  CPU Stack Size Definition 
+;
+;  The following EQU statement defines the stack space available for the
+;  251 application program.  It should be noted that the stack space must
+;  be adjusted according the actual requirements of the application.
+;
+STACKSIZE	EQU	300	; adjust to your application
+;
+;------------------------------------------------------------------------------
+;
+;  Reentrant Stack Initilization 
+;
+;  Note:  the defintions below are only required when you application contains
+;         reentrant code which is written with C251 Version 1 or C51.  You
+;         should not enable IBPSTACK or XBPSTACK for reentrant code written
+;         with C251 Version 2 since this compiler is using the hardware stack
+;         of the 251 rather than a simulated stack area.
+;
+;  The following EQU statements define the stack pointer for reentrant
+;  functions and initialized it:
+;
+;  Stack Space for reentrant functions in the SMALL model.
+IBPSTACK	EQU	0	; set to 1 if small reentrant is used.
+IBPSTACKTOP	EQU	0FFH+1	; set top of stack to highest location+1.
+;
+;  Stack Space for reentrant functions in the LARGE model.	
+XBPSTACK	EQU	0	; set to 1 if large reentrant is used.
+XBPSTACKTOP	EQU	0FFFFH+1; set top of stack to highest location+1.
+;
+;------------------------------------------------------------------------------
+
+$IF ROMHUGE
+Prefix	LIT '?'
+Model   LIT 'FAR'
+PRSeg	LIT 'ECODE'
+$ELSE
+Prefix  LIT ''
+Model   LIT 'NEAR'
+PRSeg	LIT 'CODE'
+$ENDIF
+
+$include (reg251s.inc)
+
+EXTRN NUMBER (?C?XDATASEG)		; Start of XDATA Segment
+
+		NAME	?C_START{Prefix}
+
+
+; Setting of the Chip Configuration Bytes
+$IF __MODSRC__
+SRCM		EQU	1  ; Select Source Mode
+$ELSE
+SRCM		EQU	0  ; Select Binary Mode
+$ENDIF
+
+$IF (CONFIGB)
+CONFIG0		EQU     (WSA*20H)+(XALE*10H)+(RDRG*4)+(PAGM*2)+SRCM+080H
+CONFIG1		EQU	(INTR*10H)+(EDF*8)+(WSB*2)+EMAP+0E0H
+	
+		CSEG	AT	0FFF8H
+		DB	CONFIG0		; Config Byte 0
+		DB	CONFIG1		; Config Byte 1
+$ENDIF
+
+
+?C_C51STARTUP	SEGMENT   CODE
+?C_C51STARTUP?3 SEGMENT   CODE
+
+?STACK		SEGMENT   EDATA
+
+		RSEG	?STACK
+		DS	STACKSIZE	; Stack Space 100H Bytes
+
+		EXTRN PRSeg (MAIN{Prefix})
+		PUBLIC	?C_STARTUP{Prefix}
+		PUBLIC	?C?STARTUP{Prefix}
+
+		CSEG	AT	0
+?C?STARTUP{Prefix}:
+?C_STARTUP{Prefix}:
+		LJMP	STARTUP1
+
+		RSEG	?C_C51STARTUP
+
+STARTUP1:
+		MOV	DPXL,#?C?XDATASEG
+
+IF EDATALEN <> 0
+		MOV	WR8,#EDATALEN - 1
+		CLR	A
+EDATALOOP:	MOV	@WR8,R11
+		DEC	WR8,#1
+		JNE	EDATALOOP
+ENDIF
+
+IF XDATALEN <> 0
+		MOV	DPTR,#WORD0 XDATASTART
+		MOV	WR6,#XDATALEN
+		CLR	A
+XDATALOOP:	MOVX	@DPTR,A
+		INC	DPTR
+		DEC	WR6,#1
+		JNE	XDATALOOP
+ENDIF
+
+IF HDATALEN <> 0
+		MOV	DR16,#WORD0 HDATALEN
+IF (WORD2 HDATALEN) <> 0
+		MOV	WR16,#WORD2 HDATALEN
+ENDIF
+		MOV	WR12,#WORD2 HDATASTART
+		MOV	WR14,#WORD0 HDATASTART
+		CLR	A
+HDATALOOP:	MOV	@DR12,R11
+		INC	DR12,#1
+		DEC	DR16,#1
+		JNE	HDATALOOP
+ENDIF
+
+IF IBPSTACK <> 0
+EXTRN DATA (?C_IBP)
+
+		MOV	?C_IBP,#LOW IBPSTACKTOP
+ENDIF
+
+IF XBPSTACK <> 0
+EXTRN DATA (?C_XBP)
+
+		MOV	?C_XBP,#HIGH XBPSTACKTOP
+		MOV	?C_XBP+1,#LOW XBPSTACKTOP
+ENDIF
+
+		MOV	DR60,#WORD0 (?STACK-1)
+
+		RSEG	?C_C51STARTUP?3
+		JMP	Model MAIN{Prefix}
+
+		END

+ 272 - 0
examples/80251/vanilla/keil/dpp-mcb251/bsp.c

@@ -0,0 +1,272 @@
+/*****************************************************************************
+* Product: Board Support Package for MCB251, QDPP example, Vanilla port
+* Last Updated for Version: 4.0.01
+* Date of the Last Update:  Aug 11, 2008
+*
+*                    Q u a n t u m     L e a P s
+*                    ---------------------------
+*                    innovating embedded systems
+*
+* Copyright (C) 2002-2008 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"
+#include "dpp.h"
+#include "bsp.h"
+
+Q_DEFINE_THIS_FILE
+
+sfr16 TMR2RL = 0xCA;          /* Timer2 reload value (16-bit register pair) */
+sfr16 TMR2   = 0xCC;               /* Timer2 counter (16-bit register pair) */
+
+/* global objects ----------------------------------------------------------*/
+volatile uint8_t bdata QF_pcon;  /* shadow of the PCON register, see NOTE03 */
+
+/*..........................................................................*/
+void BSP_init(void) {
+    P1 = 0x80;                                       /* extinguish all LEDs */
+
+    /* setup the Timer2 to generate the system clock-tick interrupt */
+    TR2 = 0;                                                 /* stop Timer2 */
+    T2MOD  = 0;                    /* set Timer2 to auto-reload, up-counter */
+    /* setup the reload registers for the desired tick rate... */
+    TMR2RL = (uint16_t)(0x10000 - BSP_PERIPHERAL_HZ/BSP_TICKS_PER_SEC + 0.5);
+    TMR2 = TMR2RL;
+
+    if (QS_INIT((void *)0) == 0) {    /* initialize the QS software tracing */
+        Q_ERROR();
+    }
+}
+/*..........................................................................*/
+void BSP_displyPhilStat(uint8_t n, char const *stat) {
+    switch (n) {
+        case 0: LED0 = (stat[0] == 'e'); break;
+        case 1: LED1 = (stat[0] == 'e'); break;
+        case 2: LED2 = (stat[0] == 'e'); break;
+        case 3: LED3 = (stat[0] == 'e'); break;
+        case 4: LED4 = (stat[0] == 'e'); break;
+        default: Q_ERROR(); break;          /* unexpected Philospher number */
+    }
+}
+/*..........................................................................*/
+void BSP_busyDelay(void) {
+}
+/*..........................................................................*/
+void QF_onIdle(void) {        /* entered with interrupts LOCKED, see NOTE01 */
+
+    LED6 = 1;                         /* toggle LED6 on and off, see NOTE01 */
+    LED6 = 0;
+
+#ifdef Q_SPY
+    if (TI != 0) {                                    /* ready to transmit? */
+        uint16_t b = QS_getByte();          /* get the next QS byte to send */
+        QF_INT_UNLOCK(dummy);
+
+        if (b != QS_EOD) {                  /* End-Of-Data not reached yet? */
+            TI = 0;      /* clear the transmit-interrupt flag for next time */
+            SBUF = (uint8_t)b;  /* insert the byte to the transmit register */
+        }
+    }
+    else {                                            /* still transmitting */
+        QF_INT_UNLOCK(dummy);               /* either way unlock interrupts */
+    }
+#elif (defined NDEBUG)
+    /* stop as many peripheral clocks as possible for you application... */
+    QF_pcon = PCON | 0x01;    /* set the IDL bit in the PCON shadow, NOTE03 */
+
+    QF_INT_UNLOCK(dummy);                          /* unlock the interrupts */
+    PCON = QF_pcon;                          /* go to low-power, see NOTE03 */
+#else
+    QF_INT_UNLOCK(dummy);                          /* unlock the interrupts */
+#endif
+}
+/*..........................................................................*/
+void QF_onCleanup(void) {
+}
+/*..........................................................................*/
+void Q_onAssert(char const Q_ROM * const Q_ROM_VAR file, int line) {
+    (void)file;                                   /* avoid compiler warning */
+    (void)line;                                   /* avoid compiler warning */
+
+    /* stop interrupts to preserve the system's state as much as possible.. */
+    /* NOTE: global interrupt lock blocks the ROM-monitor, so don't do this */
+    /* QF_INT_LOCK(dummy); */
+
+    TR2 = 0;                             /* stop Timer2 (system clock tick) */
+    /* ... stop other interrupts in your system individually */
+
+    LED0 = 1;
+    LED1 = 1;
+    LED2 = 1;
+    LED3 = 1;
+    LED4 = 1;
+    for (;;) {       /* NOTE: replace the loop with reset for final version */
+    }
+}
+
+/*--------------------------------------------------------------------------*/
+#ifdef Q_SPY
+
+#if (BSP_CPU_HZ == 12000000)
+                    /* best match for the standard PC serial port baud rate */
+    #define QS_BAUD_RATE        4800
+#elif (BSP_CPU_HZ == 11059000)
+                    /* best match for the standard PC serial port baud rate */
+    #define QS_BAUD_RATE        57600
+#else
+    #error "Please choose the best QSpy baud rate for your custom clock"
+#endif
+
+#define QS_BUF_SIZE        (350)
+
+QSTimeCtr QS_tickTime;                           /* keeps timetsamp at tick */
+
+/*..........................................................................*/
+uint8_t QS_onStartup(void const *arg) {
+    static uint8_t qsBuf[QS_BUF_SIZE];            /* buffer for Quantum Spy */
+
+    (void)arg;                                /* avoid the compiler warning */
+    QS_initBuf(qsBuf, sizeof(qsBuf));
+
+    /* setup Timer1-based baud rate generator */
+    TR1 = 0;                                                 /* stop Timer1 */
+    ET1 = 0;                                    /* disable Timer1 interrupt */
+    PCON |= 0x80;              /* 0x80 = SMOD: set serial baud rate doubler */
+    TMOD &= ~0xF0;                                /* clear Timer1 mode bits */
+    TMOD |= 0x20;                                 /* put Timer1 into MODE 2 */
+           /* set the Timer1 reload value to generate the desired baud rate */
+    TH1 = (uint8_t)(0x100 - 2.0*BSP_PERIPHERAL_HZ/32.0/QS_BAUD_RATE + 0.5);
+    TL1 = TH1;
+
+    /* setup serial port registers */
+    P3 |= (1 << 1); /* configure P3.1 as controlled by alternative function */
+    SCON = 0x40;                                      /* serial port MODE 1 */
+    REN = 0;                                     /* disable serial receiver */
+    TR1 = 1;                                                /* start Timer1 */
+    TI  = 1;                                         /* enable transmitting */
+
+                                                 /* setup the QS filters... */
+    QS_FILTER_ON(QS_ALL_RECORDS);
+
+//    QS_FILTER_OFF(QS_QEP_STATE_EMPTY);
+//    QS_FILTER_OFF(QS_QEP_STATE_ENTRY);
+//    QS_FILTER_OFF(QS_QEP_STATE_EXIT);
+//    QS_FILTER_OFF(QS_QEP_STATE_INIT);
+//    QS_FILTER_OFF(QS_QEP_INIT_TRAN);
+//    QS_FILTER_OFF(QS_QEP_INTERN_TRAN);
+//    QS_FILTER_OFF(QS_QEP_TRAN);
+//    QS_FILTER_OFF(QS_QEP_dummyD);
+
+    QS_FILTER_OFF(QS_QF_ACTIVE_ADD);
+    QS_FILTER_OFF(QS_QF_ACTIVE_REMOVE);
+    QS_FILTER_OFF(QS_QF_ACTIVE_SUBSCRIBE);
+    QS_FILTER_OFF(QS_QF_ACTIVE_UNSUBSCRIBE);
+    QS_FILTER_OFF(QS_QF_ACTIVE_POST_FIFO);
+    QS_FILTER_OFF(QS_QF_ACTIVE_POST_LIFO);
+    QS_FILTER_OFF(QS_QF_ACTIVE_GET);
+    QS_FILTER_OFF(QS_QF_ACTIVE_GET_LAST);
+    QS_FILTER_OFF(QS_QF_EQUEUE_INIT);
+    QS_FILTER_OFF(QS_QF_EQUEUE_POST_FIFO);
+    QS_FILTER_OFF(QS_QF_EQUEUE_POST_LIFO);
+    QS_FILTER_OFF(QS_QF_EQUEUE_GET);
+    QS_FILTER_OFF(QS_QF_EQUEUE_GET_LAST);
+    QS_FILTER_OFF(QS_QF_MPOOL_INIT);
+    QS_FILTER_OFF(QS_QF_MPOOL_GET);
+    QS_FILTER_OFF(QS_QF_MPOOL_PUT);
+    QS_FILTER_OFF(QS_QF_PUBLISH);
+    QS_FILTER_OFF(QS_QF_NEW);
+    QS_FILTER_OFF(QS_QF_GC_ATTEMPT);
+    QS_FILTER_OFF(QS_QF_GC);
+//    QS_FILTER_OFF(QS_QF_TICK);
+    QS_FILTER_OFF(QS_QF_TIMEEVT_ARM);
+    QS_FILTER_OFF(QS_QF_TIMEEVT_AUTO_DISARM);
+    QS_FILTER_OFF(QS_QF_TIMEEVT_DISARM_ATTEMPT);
+    QS_FILTER_OFF(QS_QF_TIMEEVT_DISARM);
+    QS_FILTER_OFF(QS_QF_TIMEEVT_REARM);
+    QS_FILTER_OFF(QS_QF_TIMEEVT_POST);
+    QS_FILTER_OFF(QS_QF_INT_LOCK);
+    QS_FILTER_OFF(QS_QF_INT_UNLOCK);
+    QS_FILTER_OFF(QS_QF_ISR_ENTRY);
+    QS_FILTER_OFF(QS_QF_ISR_EXIT);
+
+    return (uint8_t)1;                                    /* return success */
+}
+/*..........................................................................*/
+void QS_onCleanup(void) {
+}
+/*..........................................................................*/
+void QS_onFlush(void) {
+    uint16_t b;
+    while ((b = QS_getByte()) != QS_EOD) { /* next QS trace byte available? */
+        while (TI == 0) {   /* hang in a loop as long as transmit not ready */
+        }
+        TI = 0;          /* clear the transmit-interrupt flag for next time */
+        SBUF = (uint8_t)b;
+    }
+}
+/*..........................................................................*/
+QSTimeCtr QS_onGetTime(void) {            /* invoked with interrupts locked */
+    uint8_t volatile t2h1 = TH2;                                  /* step 1 */
+    uint8_t volatile t2l  = TL2;                                  /* step 2 */
+    uint8_t volatile t2h2 = TH2;                                  /* step 3 */
+    QSTimeCtr tickTime = QS_tickTime;
+
+    if (TF2 != 0) {    /* Timer2 auto-reloaded but tick ISR didn't run yet? */
+        tickTime += (QSTimeCtr)(BSP_PERIPHERAL_HZ/BSP_TICKS_PER_SEC + 0.5);
+    }
+
+    if (t2h1 == t2h2) {   /* the high-register unchanged from step 1 and 3? */
+        return tickTime
+               + (QSTimeCtr)((uint16_t)t2l + ((uint16_t)t2h1 << 8));
+    }
+    else {                /* the high-register changed between step 1 and 3 */
+        return tickTime + ((uint16_t)t2h2 << 8);
+    }
+}
+#endif                                                             /* Q_SPY */
+/*--------------------------------------------------------------------------*/
+
+/*****************************************************************************
+* NOTE01:
+* The LED6 of the MCB251 board is used to visualize the idle loop activity.
+* The brightness of the LED is proportional to the frequency of invocations
+* of the idle loop. Please note that the LED is toggled with interrupts
+* locked, so no interrupt execution time contributes to the brightness of
+* the LED.
+*
+* NOTE02:
+* The callback function QF_onIdle() is called with interrupts locked, because
+* the idle condition can be invalidated by any enabled interrupt that would
+* post events. The QF_onIdle() function *must* unlock interrupts internally
+*
+* NOTE03:
+* The low-power mode must be entered with interrupts locked to avoid
+* an interrupt to preempt the transition to the low-power mode. However,
+* the 80x51 architecture does not provide an *atomic* transition to the Idle
+* mode with simultaneous unlocking interrupts. Instead, here the PCON
+* register is shadowed in the QF_pcon bdata variable. The idle mode
+* is set first in the shadow register QF_pcon. At the end of every interrupt,
+* the ISR copies the PCON value into the QF_pcon shadow (the 80x51 clears the
+* IDL and PD bits in the PCON register upon interrupt entry). Later in
+* QF_onIdle(), the PCON register is restored from the shadow QF_pcon, which
+* the 80x51 performs *atomically* as a single machine instruction (such as
+* MOV 87H,20H). If the interrupt gets serviced between unlocking interrupts
+* and restoring PCON from the shadow, the IDL/PD bits will be cleared in the
+* shadow, so the machine will *not* go to the Idle?PD mode. Only if the
+* IDL/PD bits survive in the shadow, the Idle/PD mode is entered.
+*/

+ 55 - 0
examples/80251/vanilla/keil/dpp-mcb251/bsp.h

@@ -0,0 +1,55 @@
+/*****************************************************************************
+* Product: DPP example, Board Support Package for MCB251
+* Last Updated for Version: 4.0.01
+* Date of the Last Update:  Aug 11, 2008
+*
+*                    Q u a n t u m     L e a P s
+*                    ---------------------------
+*                    innovating embedded systems
+*
+* Copyright (C) 2002-2008 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 bsp_h
+#define bsp_h
+
+#include <reg251s.h>                         /* SFR declarations for 80251S */
+
+#define BSP_CPU_HZ           11059000
+#define BSP_TICKS_PER_SEC    20
+#define BSP_PERIPHERAL_HZ    (11059000/12)
+
+/* LEDs of the MCB251 board */
+sbit LED0 = P1 ^ 0;
+sbit LED1 = P1 ^ 1;
+sbit LED2 = P1 ^ 2;
+sbit LED3 = P1 ^ 3;
+sbit LED4 = P1 ^ 4;
+sbit LED5 = P1 ^ 5;
+sbit LED6 = P1 ^ 6;
+
+void BSP_init(void);
+void BSP_displyPhilStat(uint8_t n, char const *stat);
+void BSP_busyDelay(void);
+
+#ifdef Q_SPY
+    extern QSTimeCtr QS_tickTime;                /* keeps timetsamp at tick */
+#endif
+
+#endif                                                             /* bsp_h */
+

+ 106 - 0
examples/80251/vanilla/keil/dpp-mcb251/dpp-mcb251.Opt

@@ -0,0 +1,106 @@
+### uVision2 Project, (C) Keil Software
+### Do not modify !
+
+ cExt (*.c)
+ aExt (*.a*; *.src)
+ oExt (*.obj)
+ lExt (*.lib)
+ tExt (*.txt)
+ pExt (*.plm)
+ CppX (*.cpp)
+ DaveTm { 0,0,0,0,0,0,0,0 }
+
+Target (Debug), 0x0001 // Tools: 'MCS-251'
+Target (Release), 0x0001 // Tools: 'MCS-251'
+Target (Spy), 0x0001 // Tools: 'MCS-251'
+GRPOPT 1,(Source Code),1,0,0
+GRPOPT 2,(Startup Code),1,0,0
+GRPOPT 3,(Header Files),1,0,0
+GRPOPT 4,(QP-dbg),1,0,0
+GRPOPT 5,(QP-rel),1,0,0
+GRPOPT 6,(QP-spy),1,0,0
+
+OPTFFF 1,1,1,419430400,0,0,0,0,<.\bsp.c><bsp.c> 
+OPTFFF 1,2,1,603979776,0,0,0,0,<.\main.c><main.c> 
+OPTFFF 1,3,1,0,0,0,0,0,<.\table.c><table.c> 
+OPTFFF 1,4,1,0,0,0,0,0,<.\philo.c><philo.c> 
+OPTFFF 1,5,1,1006632960,0,0,0,0,<.\isr.c><isr.c> 
+OPTFFF 2,6,2,150994944,0,0,0,0,<.\START251.A51><START251.A51> 
+OPTFFF 3,7,5,0,0,0,0,0,<.\bsp.h><bsp.h> 
+OPTFFF 3,8,5,0,0,0,0,0,<.\dpp.h><dpp.h> 
+OPTFFF 4,9,4,0,0,0,0,0,<..\..\..\..\..\ports\80251\vanilla\keil\dbg\QF.LIB><QF.LIB> 
+OPTFFF 4,10,4,0,0,0,0,0,<..\..\..\..\..\ports\80251\vanilla\keil\dbg\QEP.LIB><QEP.LIB> 
+OPTFFF 5,11,4,0,0,0,0,0,<..\..\..\..\..\ports\80251\vanilla\keil\rel\QF.LIB><QF.LIB> 
+OPTFFF 5,12,4,0,0,0,0,0,<..\..\..\..\..\ports\80251\vanilla\keil\rel\QEP.LIB><QEP.LIB> 
+OPTFFF 6,13,4,0,0,0,0,0,<..\..\..\..\..\ports\80251\vanilla\keil\spy\QS.LIB><QS.LIB> 
+OPTFFF 6,14,4,0,0,0,0,0,<..\..\..\..\..\ports\80251\vanilla\keil\spy\QEP.LIB><QEP.LIB> 
+OPTFFF 6,15,4,0,0,0,0,0,<..\..\..\..\..\ports\80251\vanilla\keil\spy\QF.LIB><QF.LIB> 
+
+
+TARGOPT 1, (Debug)
+ CLK251=12000000
+  OPTTT 1,1,1,0
+  OPTHX 0,65535,0,0,0
+  OPTLX 120,65,8,<.\dbg\>
+  OPTOX 16
+  OPTLT 0,0,1,0,1,1,1,1,1,0,1,0
+  OPTXL 1,1,1,1,1,1,1,0,1
+  OPTFL 1,0,1
+  OPTBL 0,(Add on databooks)<DATASHTS\ADDBOOKS.PDF>
+  OPTBL 1,(Data Sheet)<DATASHTS\INTEL\8xC251Sx_DS.PDF>
+  OPTBL 2,(User's Manual)<DATASHTS\INTEL\8xC251Sx_UM.PDF>
+  OPTDL (S251.DLL)()(DP51.DLL)(-p251S)(S251.DLL)()(TP51.DLL)(-p251S)
+  OPTDBG 48126,-1,()()()()()()()()()() (BIN\MON251.DLL)()()()
+  OPTKEY 0,(MON251)(-S1 -B57600 -O4096)
+  OPTMM 1,0,(c:0x11b1)
+  OPTMM 2,0,(\measure\save_record)
+  OPTDF 0x84
+  OPTLE <>
+  OPTLC <>
+EndOpt
+
+TARGOPT 2, (Release)
+ CLK251=16000000
+  OPTTT 1,1,1,0
+  OPTHX 0,65535,0,0,0
+  OPTLX 120,65,8,<.\rel\>
+  OPTOX 16
+  OPTLT 0,0,1,0,1,1,1,1,1,0,1,0
+  OPTXL 1,1,1,1,1,1,1,0,1
+  OPTFL 1,0,0
+  OPTBL 0,(Add on databooks)<DATASHTS\ADDBOOKS.PDF>
+  OPTBL 1,(Data Sheet)<DATASHTS\INTEL\8xC251Sx_DS.PDF>
+  OPTBL 2,(User's Manual)<DATASHTS\INTEL\8xC251Sx_UM.PDF>
+  OPTDL (S251.DLL)()(DP51.DLL)(-p251S)(S251.DLL)()(TP51.DLL)(-p251S)
+  OPTDBG 48126,-1,()()()()()()()()()() (BIN\MON251.DLL)()()()
+  OPTKEY 0,(MON251)(-S1 -B57600 -O4096)
+  OPTMM 1,0,(c:0x11b1)
+  OPTMM 2,0,(\measure\save_record)
+  OPTDF 0x84
+  OPTLE <>
+  OPTLC <>
+EndOpt
+
+TARGOPT 3, (Spy)
+ CLK251=16000000
+  OPTTT 1,1,1,0
+  OPTHX 0,65535,0,0,0
+  OPTLX 120,65,8,<.\spy\>
+  OPTOX 16
+  OPTLT 0,0,1,0,1,1,1,1,1,0,1,0
+  OPTXL 1,1,1,1,1,1,1,0,1
+  OPTFL 1,0,0
+  OPTBL 0,(Add on databooks)<DATASHTS\ADDBOOKS.PDF>
+  OPTBL 1,(Data Sheet)<DATASHTS\INTEL\8xC251Sx_DS.PDF>
+  OPTBL 2,(User's Manual)<DATASHTS\INTEL\8xC251Sx_UM.PDF>
+  OPTDL (S251.DLL)()(DP51.DLL)(-p251S)(S251.DLL)()(TP51.DLL)(-p251S)
+  OPTDBG 48126,-1,()()()()()()()()()() (BIN\MON251.DLL)()()()
+  OPTKEY 0,(MON251)(-S1 -B57600 -O4096)
+  OPTMM 1,0,(d:0x00)
+  OPTMM 2,0,(\measure\save_record)
+  OPTSY 10,1,(*)
+  OPTDF 0x84
+  OPTLE <>
+  OPTLC <>
+EndOpt
+

+ 520 - 0
examples/80251/vanilla/keil/dpp-mcb251/dpp-mcb251.Uv2

@@ -0,0 +1,520 @@
+### uVision2 Project, (C) Keil Software
+### Do not modify !
+
+Target (Debug), 0x0001 // Tools: 'MCS-251'
+Target (Release), 0x0001 // Tools: 'MCS-251'
+Target (Spy), 0x0001 // Tools: 'MCS-251'
+
+Group (Source Code)
+Group (Startup Code)
+Group (Header Files)
+Group (QP-dbg)
+Group (QP-rel)
+Group (QP-spy)
+
+File 1,1,<.\bsp.c><bsp.c> 0x0 
+File 1,1,<.\main.c><main.c> 0x0 
+File 1,1,<.\table.c><table.c> 0x0 
+File 1,1,<.\philo.c><philo.c> 0x0 
+File 1,1,<.\isr.c><isr.c> 0x0 
+File 2,2,<.\START251.A51><START251.A51> 0x0 
+File 3,5,<.\bsp.h><bsp.h> 0x0 
+File 3,5,<.\dpp.h><dpp.h> 0x0 
+File 4,4,<..\..\..\..\..\ports\80251\vanilla\keil\dbg\QF.LIB><QF.LIB> 0x0 
+File 4,4,<..\..\..\..\..\ports\80251\vanilla\keil\dbg\QEP.LIB><QEP.LIB> 0x0 
+File 5,4,<..\..\..\..\..\ports\80251\vanilla\keil\rel\QF.LIB><QF.LIB> 0x0 
+File 5,4,<..\..\..\..\..\ports\80251\vanilla\keil\rel\QEP.LIB><QEP.LIB> 0x0 
+File 6,4,<..\..\..\..\..\ports\80251\vanilla\keil\spy\QS.LIB><QS.LIB> 0x0 
+File 6,4,<..\..\..\..\..\ports\80251\vanilla\keil\spy\QEP.LIB><QEP.LIB> 0x0 
+File 6,4,<..\..\..\..\..\ports\80251\vanilla\keil\spy\QF.LIB><QF.LIB> 0x0 
+
+
+Options 1,0,0  // Target 'Debug'
+ Device (8xC251SB)
+ Vendor (Intel)
+ Cpu (IRAM(0 - 0x41F) CLOCK(16000000) IROM(0xFF0000-0xFF3FFF))
+ FlashUt ()
+ StupF ()
+ FlashDR ()
+ DevID ()
+ Rgf (REG251S.H)
+ Mem ()
+ C ()
+ A ()
+ RL ()
+ OH ()
+ DBC_IFX ()
+ DBC_CMS ()
+ DBC_AMS ()
+ DBC_LMS ()
+ UseEnv=0
+ EnvBin ()
+ EnvInc ()
+ EnvLib ()
+ EnvReg (ÿIntel\)
+ OrgReg (ÿIntel\)
+ TgStat=16
+ OutDir (.\dbg\)
+ OutName (dpp-mcb251)
+ GenApp=1
+ GenLib=0
+ GenHex=1
+ Debug=1
+ Browse=0
+ LstDir (.\dbg\)
+ HexSel=0
+ MG32K=0
+ TGMORE=0
+ RunUsr 0 0 <>
+ RunUsr 1 0 <>
+ BrunUsr 0 0 <>
+ BrunUsr 1 0 <>
+ SVCSID <>
+ MODEL25=1
+ RTOS25=0
+ ROMSZ25=3
+ DHOLD25=0
+ XHOLD25=0
+ FHOLD25=0
+ T251FL=92
+ CBANKS2=0
+ RCB25 { 0,0,0,0,0,0,0,1,0 }
+ IRO25 { 1,0,0,255,0,0,64,0,0 }
+ ERA25 { 0,0,0,0,0,32,4,0,0 }
+ XRA25 { 0,0,0,0,0,0,0,0,0 }
+ OCM251 { 1,0,0,255,0,0,128,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }
+ C251F1=19279952
+ C251F2=0
+ C251MSC (FIXDRK WARNING(disable=138))
+ C251DEF ()
+ C251UDF ()
+ INCC2 (.,..\..\..\..\..\include,..\..\..\..\..\ports\80251\vanilla\keil)
+ AX51FL=4
+ AX51MSC (FIXDRK REGISTERBANK(0))
+ AX51SET ()
+ AX51RST ()
+ INCA5 ()
+ PropFld { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }
+ IncBld=1
+ AlwaysBuild=0
+ GenAsm=0
+ AsmAsm=0
+ PublicsOnly=0
+ StopCode=3
+ CustArgs ()
+ LibMods ()
+ BankNo=65535
+ LX51FL=300
+ LX51OVL ()
+ LX51MSC (NOOVERLAY)
+ LX51DWN (25)
+ LX51LFI ()
+ LX51ASN ()
+ LX51RES (0xFF0003-0XFF0005,0XFF003B-0XFF003D,0XFF007B-0XFF007D)
+ LX51CCL ()
+ LX51UCL ()
+ LX51CSC ()
+ LX51UCS ()
+ LX51COB ()
+ LX51XDB ()
+ LX51PDB ()
+ LX51BIB ()
+ LX51DAB ()
+ LX51IDB ()
+ LX51PRC ()
+ LX51STK ()
+ LX51COS ()
+ LX51XDS ()
+ LX51BIS ()
+ LX51DAS ()
+ LX51IDS ()
+  OPTDL (S251.DLL)()(DP51.DLL)(-p251S)(S251.DLL)()(TP51.DLL)(-p251S)
+  OPTDBG 48126,-1,()()()()()()()()()() (BIN\MON251.DLL)()()()
+ FLASH1 { 1,0,0,0,0,0,0,0,255,255,255,255,0,0,0,0,0,0,0,0 }
+ FLASH2 ()
+ FLASH3 ()
+ FLASH4 ()
+EndOpt
+
+Options 2,0,0  // Target 'Release'
+ Device (8xC251SB)
+ Vendor (Intel)
+ Cpu (IRAM(0 - 0x41F) CLOCK(16000000) IROM(0xFF0000-0xFF3FFF))
+ FlashUt ()
+ StupF ()
+ FlashDR ()
+ DevID ()
+ Rgf (REG251S.H)
+ Mem ()
+ C ()
+ A ()
+ RL ()
+ OH ()
+ DBC_IFX ()
+ DBC_CMS ()
+ DBC_AMS ()
+ DBC_LMS ()
+ UseEnv=0
+ EnvBin ()
+ EnvInc ()
+ EnvLib ()
+ EnvReg (ÿIntel\)
+ OrgReg (ÿIntel\)
+ TgStat=16
+ OutDir (.\rel\)
+ OutName (dpp-mcb251)
+ GenApp=1
+ GenLib=0
+ GenHex=1
+ Debug=0
+ Browse=0
+ LstDir (.\rel\)
+ HexSel=0
+ MG32K=0
+ TGMORE=0
+ RunUsr 0 0 <>
+ RunUsr 1 0 <>
+ BrunUsr 0 0 <>
+ BrunUsr 1 0 <>
+ SVCSID <>
+ MODEL25=1
+ RTOS25=0
+ ROMSZ25=3
+ DHOLD25=0
+ XHOLD25=0
+ FHOLD25=0
+ T251FL=92
+ CBANKS2=0
+ RCB25 { 0,0,0,0,0,0,0,1,0 }
+ IRO25 { 1,0,0,255,0,0,64,0,0 }
+ ERA25 { 0,0,0,0,0,32,4,0,0 }
+ XRA25 { 0,0,0,0,0,0,0,0,0 }
+ OCM251 { 1,0,0,255,0,0,128,0,0,0,0,0,0,0,0,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }
+ C251F1=19345489
+ C251F2=0
+ C251MSC (FIXDRK WARNING(disable=138))
+ C251DEF (NDEBUG)
+ C251UDF ()
+ INCC2 (.,..\..\..\..\..\include,..\..\..\..\..\ports\80251\vanilla\keil)
+ AX51FL=4
+ AX51MSC (FIXDRK REGISTERBANK(0))
+ AX51SET ()
+ AX51RST ()
+ INCA5 ()
+ PropFld { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }
+ IncBld=1
+ AlwaysBuild=0
+ GenAsm=0
+ AsmAsm=0
+ PublicsOnly=0
+ StopCode=3
+ CustArgs ()
+ LibMods ()
+ BankNo=65535
+ LX51FL=300
+ LX51OVL ()
+ LX51MSC (NOOVERLAY)
+ LX51DWN (25)
+ LX51LFI ()
+ LX51ASN ()
+ LX51RES (0xFF0003-0XFF0005,0XFF003B-0XFF003D,0XFF007B-0XFF007D)
+ LX51CCL ()
+ LX51UCL ()
+ LX51CSC ()
+ LX51UCS ()
+ LX51COB ()
+ LX51XDB ()
+ LX51PDB ()
+ LX51BIB ()
+ LX51DAB ()
+ LX51IDB ()
+ LX51PRC ()
+ LX51STK ()
+ LX51COS ()
+ LX51XDS ()
+ LX51BIS ()
+ LX51DAS ()
+ LX51IDS ()
+  OPTDL (S251.DLL)()(DP51.DLL)(-p251S)(S251.DLL)()(TP51.DLL)(-p251S)
+  OPTDBG 48126,-1,()()()()()()()()()() (BIN\MON251.DLL)()()()
+ FLASH1 { 1,0,0,0,0,0,0,0,255,255,255,255,0,0,0,0,0,0,0,0 }
+ FLASH2 ()
+ FLASH3 ()
+ FLASH4 ()
+EndOpt
+
+Options 3,0,0  // Target 'Spy'
+ Device (8xC251SB)
+ Vendor (Intel)
+ Cpu (IRAM(0 - 0x41F) CLOCK(16000000) IROM(0xFF0000-0xFF3FFF))
+ FlashUt ()
+ StupF ()
+ FlashDR ()
+ DevID ()
+ Rgf (REG251S.H)
+ Mem ()
+ C ()
+ A ()
+ RL ()
+ OH ()
+ DBC_IFX ()
+ DBC_CMS ()
+ DBC_AMS ()
+ DBC_LMS ()
+ UseEnv=0
+ EnvBin ()
+ EnvInc ()
+ EnvLib ()
+ EnvReg (ÿIntel\)
+ OrgReg (ÿIntel\)
+ TgStat=16
+ OutDir (.\spy\)
+ OutName (dpp-mcb251)
+ GenApp=1
+ GenLib=0
+ GenHex=1
+ Debug=1
+ Browse=0
+ LstDir (.\spy\)
+ HexSel=0
+ MG32K=0
+ TGMORE=0
+ RunUsr 0 0 <>
+ RunUsr 1 0 <>
+ BrunUsr 0 0 <>
+ BrunUsr 1 0 <>
+ SVCSID <>
+ MODEL25=1
+ RTOS25=0
+ ROMSZ25=3
+ DHOLD25=0
+ XHOLD25=0
+ FHOLD25=0
+ T251FL=92
+ CBANKS2=0
+ RCB25 { 0,0,0,0,0,0,0,1,0 }
+ IRO25 { 1,0,0,255,0,0,64,0,0 }
+ ERA25 { 0,0,0,0,0,32,4,0,0 }
+ XRA25 { 0,0,0,0,0,0,0,0,0 }
+ OCM251 { 1,0,0,255,0,0,128,0,0,0,0,0,0,0,0,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }
+ C251F1=19279952
+ C251F2=0
+ C251MSC (FIXDRK WARNING(disable=138))
+ C251DEF (Q_SPY)
+ C251UDF ()
+ INCC2 (.,..\..\..\..\..\include,..\..\..\..\..\ports\80251\vanilla\keil)
+ AX51FL=4
+ AX51MSC (FIXDRK REGISTERBANK(0))
+ AX51SET ()
+ AX51RST ()
+ INCA5 ()
+ PropFld { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }
+ IncBld=1
+ AlwaysBuild=0
+ GenAsm=0
+ AsmAsm=0
+ PublicsOnly=0
+ StopCode=3
+ CustArgs ()
+ LibMods ()
+ BankNo=65535
+ LX51FL=300
+ LX51OVL ()
+ LX51MSC (NOOVERLAY)
+ LX51DWN (25)
+ LX51LFI ()
+ LX51ASN ()
+ LX51RES (0xFF0003-0XFF0005,0XFF003B-0XFF003D,0XFF007B-0XFF007D)
+ LX51CCL ()
+ LX51UCL ()
+ LX51CSC ()
+ LX51UCS ()
+ LX51COB ()
+ LX51XDB ()
+ LX51PDB ()
+ LX51BIB ()
+ LX51DAB ()
+ LX51IDB ()
+ LX51PRC ()
+ LX51STK ()
+ LX51COS ()
+ LX51XDS ()
+ LX51BIS ()
+ LX51DAS ()
+ LX51IDS ()
+  OPTDL (S251.DLL)()(DP51.DLL)(-p251S)(S251.DLL)()(TP51.DLL)(-p251S)
+  OPTDBG 48126,-1,()()()()()()()()()() (BIN\MON251.DLL)()()()
+ FLASH1 { 1,0,0,0,0,0,0,0,255,255,255,255,0,0,0,0,0,0,0,0 }
+ FLASH2 ()
+ FLASH3 ()
+ FLASH4 ()
+EndOpt
+
+Options 1,5,0  // Group 'QP-rel'
+ PropFld { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }
+ IncBld=0
+ AlwaysBuild=2
+ GenAsm=2
+ AsmAsm=2
+ PublicsOnly=2
+ StopCode=11
+ CustArgs ()
+ LibMods ()
+ BankNo=65535
+ C251F1=38308522
+ C251F2=0
+ C251MSC ()
+ C251DEF ()
+ C251UDF ()
+ INCC2 ()
+ AX51FL=170
+ AX51MSC ()
+ AX51SET ()
+ AX51RST ()
+ INCA5 ()
+EndOpt
+
+Options 1,6,0  // Group 'QP-spy'
+ PropFld { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }
+ IncBld=0
+ AlwaysBuild=2
+ GenAsm=2
+ AsmAsm=2
+ PublicsOnly=2
+ StopCode=11
+ CustArgs ()
+ LibMods ()
+ BankNo=65535
+ C251F1=38308522
+ C251F2=0
+ C251MSC ()
+ C251DEF ()
+ C251UDF ()
+ INCC2 ()
+ AX51FL=170
+ AX51MSC ()
+ AX51SET ()
+ AX51RST ()
+ INCA5 ()
+EndOpt
+
+Options 2,4,0  // Group 'QP-dbg'
+ PropFld { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }
+ IncBld=0
+ AlwaysBuild=2
+ GenAsm=2
+ AsmAsm=2
+ PublicsOnly=2
+ StopCode=11
+ CustArgs ()
+ LibMods ()
+ BankNo=65535
+ C251F1=38308522
+ C251F2=0
+ C251MSC ()
+ C251DEF ()
+ C251UDF ()
+ INCC2 ()
+ AX51FL=170
+ AX51MSC ()
+ AX51SET ()
+ AX51RST ()
+ INCA5 ()
+EndOpt
+
+Options 2,6,0  // Group 'QP-spy'
+ PropFld { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }
+ IncBld=0
+ AlwaysBuild=2
+ GenAsm=2
+ AsmAsm=2
+ PublicsOnly=2
+ StopCode=11
+ CustArgs ()
+ LibMods ()
+ BankNo=65535
+ C251F1=38308522
+ C251F2=0
+ C251MSC ()
+ C251DEF ()
+ C251UDF ()
+ INCC2 ()
+ AX51FL=170
+ AX51MSC ()
+ AX51SET ()
+ AX51RST ()
+ INCA5 ()
+EndOpt
+
+Options 3,4,0  // Group 'QP-dbg'
+ PropFld { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }
+ IncBld=0
+ AlwaysBuild=2
+ GenAsm=2
+ AsmAsm=2
+ PublicsOnly=2
+ StopCode=11
+ CustArgs ()
+ LibMods ()
+ BankNo=65535
+ C251F1=38308522
+ C251F2=0
+ C251MSC ()
+ C251DEF ()
+ C251UDF ()
+ INCC2 ()
+ AX51FL=170
+ AX51MSC ()
+ AX51SET ()
+ AX51RST ()
+ INCA5 ()
+EndOpt
+
+Options 3,5,0  // Group 'QP-rel'
+ PropFld { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }
+ IncBld=0
+ AlwaysBuild=2
+ GenAsm=2
+ AsmAsm=2
+ PublicsOnly=2
+ StopCode=11
+ CustArgs ()
+ LibMods ()
+ BankNo=65535
+ C251F1=38308522
+ C251F2=0
+ C251MSC ()
+ C251DEF ()
+ C251UDF ()
+ INCC2 ()
+ AX51FL=170
+ AX51MSC ()
+ AX51SET ()
+ AX51RST ()
+ INCA5 ()
+EndOpt
+
+Options 3,6,0  // Group 'QP-spy'
+ PropFld { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }
+ IncBld=1
+ AlwaysBuild=2
+ GenAsm=2
+ AsmAsm=2
+ PublicsOnly=2
+ StopCode=11
+ CustArgs ()
+ LibMods ()
+ BankNo=65535
+ C251F1=38308522
+ C251F2=0
+ C251MSC ()
+ C251DEF ()
+ C251UDF ()
+ INCC2 ()
+ AX51FL=170
+ AX51MSC ()
+ AX51SET ()
+ AX51RST ()
+ INCA5 ()
+EndOpt
+

+ 61 - 0
examples/80251/vanilla/keil/dpp-mcb251/dpp.h

@@ -0,0 +1,61 @@
+/*****************************************************************************
+* Product: DPP example
+* Last Updated for Version: 4.5.00
+* Date of the Last Update:  May 18, 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 dpp_h
+#define dpp_h
+
+enum DPPSignals {
+   EAT_SIG = Q_USER_SIG,     /* published by Table to let a philosopher eat */
+   DONE_SIG,                   /* published by Philosopher when done eating */
+   TERMINATE_SIG,          /* published by BSP to terminate the application */
+   MAX_PUB_SIG,                                /* the last published signal */
+
+   HUNGRY_SIG,          /* posted direclty to Table from hungry Philosopher */
+   MAX_SIG                                               /* the last signal */
+};
+
+typedef struct TableEvtTag {
+    QEvt super;                                    /* derives from QEvt */
+    uint8_t philoNum;                                 /* philosopher number */
+} TableEvt;
+
+enum { N_PHILO = 5 };                             /* number of philosophers */
+
+void Philo_ctor(void);
+void Table_ctor(void);
+
+extern QActive * const AO_Philo[N_PHILO]; /* "opaque" pointers to Philo AO */
+extern QActive * const AO_Table;          /* "opaque" pointer  to Table AO */
+
+#endif                                                             /* dpp_h */

+ 57 - 0
examples/80251/vanilla/keil/dpp-mcb251/isr.c

@@ -0,0 +1,57 @@
+/*****************************************************************************
+* Interrupt Service Routines, QDPP example, Vanilla port
+* Last Updated for Version: 4.0.01
+* Date of the Last Update:  Aug 11, 2008
+*
+*                    Q u a n t u m     L e a P s
+*                    ---------------------------
+*                    innovating embedded systems
+*
+* Copyright (C) 2002-2008 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"
+#include "dpp.h"
+#include "bsp.h"
+
+Q_DEFINE_THIS_FILE
+
+/*..........................................................................*/
+void QF_onStartup(void) {
+    TR2 = 1;                                                /* start Timer2 */
+    ET2 = 1;                                     /* enable Timer2 interrupt */
+    EA  = 1;                                /* enable global interrupt flag */
+}
+/*..........................................................................*/
+void timer2_ISR(void) interrupt 5 {         /* interrupt vector at FF:002BH */
+
+    TF2 = 0;    /* clear Timer2 overflow flag (must be cleared by software) */
+
+#ifdef Q_SPY
+    QS_tickTime += (QSTimeCtr)(BSP_PERIPHERAL_HZ/BSP_TICKS_PER_SEC + 0.5);
+#endif
+
+    QF_tick();                    /* QF processing of the system clock-tick */
+
+#ifdef NDEBUG
+    QF_pcon = PCON;   /* prevent low-power mode upon ISR return, see NOTE01 */
+#endif
+}
+/*..........................................................................*/
+/* place other ISRs here... */
+

+ 85 - 0
examples/80251/vanilla/keil/dpp-mcb251/main.c

@@ -0,0 +1,85 @@
+/*****************************************************************************
+* Product: DPP example
+* Last Updated for Version: 4.5.00
+* Date of the Last Update:  May 18, 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"
+#include "dpp.h"
+#include "bsp.h"
+
+/* Local-scope objects -----------------------------------------------------*/
+static QEvt const *l_tableQueueSto[N_PHILO];
+static QEvt const *l_philoQueueSto[N_PHILO][N_PHILO];
+static QSubscrList   l_subscrSto[MAX_PUB_SIG];
+
+static union SmallEvent {
+    void *min_size;
+    TableEvt te;
+    /* other event types to go into this pool */
+} l_smlPoolSto[2*N_PHILO];              /* storage for the small event pool */
+
+/*..........................................................................*/
+int main(void) {
+    uint8_t n;
+
+    Philo_ctor();             /* instantiate all Philosopher active objects */
+    Table_ctor();                    /* instantiate the Table active object */
+
+    BSP_init();           /* initialize the Board Support Package */
+
+    QF_init();     /* initialize the framework and the underlying RT kernel */
+
+                                                  /* object dictionaries... */
+    QS_OBJ_DICTIONARY(l_smlPoolSto);
+    QS_OBJ_DICTIONARY(l_tableQueueSto);
+    QS_OBJ_DICTIONARY(l_philoQueueSto[0]);
+    QS_OBJ_DICTIONARY(l_philoQueueSto[1]);
+    QS_OBJ_DICTIONARY(l_philoQueueSto[2]);
+    QS_OBJ_DICTIONARY(l_philoQueueSto[3]);
+    QS_OBJ_DICTIONARY(l_philoQueueSto[4]);
+
+    QF_psInit(l_subscrSto, Q_DIM(l_subscrSto));   /* init publish-subscribe */
+
+                                               /* initialize event pools... */
+    QF_poolInit(l_smlPoolSto, sizeof(l_smlPoolSto), sizeof(l_smlPoolSto[0]));
+
+    for (n = 0; n < N_PHILO; ++n) {          /* start the active objects... */
+        QActive_start(AO_Philo[n], (uint8_t)(n + 1),
+                      l_philoQueueSto[n], Q_DIM(l_philoQueueSto[n]),
+                      (void *)0, 0, (QEvt *)0);
+    }
+    QActive_start(AO_Table, (uint8_t)(N_PHILO + 1),
+                  l_tableQueueSto, Q_DIM(l_tableQueueSto),
+                  (void *)0, 0, (QEvt *)0);
+
+    return QF_run();                              /* run the QF application */
+}

+ 183 - 0
examples/80251/vanilla/keil/dpp-mcb251/philo.c

@@ -0,0 +1,183 @@
+/*****************************************************************************
+* Product: DPP example
+* Last Updated for Version: 4.5.00
+* Date of the Last Update:  May 18, 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"
+#include "dpp.h"
+#include "bsp.h"
+
+Q_DEFINE_THIS_FILE
+
+/* Active object class -----------------------------------------------------*/
+typedef struct PhiloTag {
+    QActive super;
+    QTimeEvt timeEvt;                   /* for timing out thining or eating */
+} Philo;
+
+static QState Philo_initial (Philo *me, QEvt const *e);
+static QState Philo_thinking(Philo *me, QEvt const *e);
+static QState Philo_hungry  (Philo *me, QEvt const *e);
+static QState Philo_eating  (Philo *me, QEvt const *e);
+
+/* Local objects -----------------------------------------------------------*/
+static Philo l_philo[N_PHILO];                    /* storage for all Philos */
+
+#define THINK_TIME  7
+#define EAT_TIME    5
+                           /* helper macro to provide the ID of Philo "me_" */
+#define PHILO_ID(me_)    ((uint8_t)((me_) - l_philo))
+
+enum InternalSignals {                                  /* internal signals */
+    TIMEOUT_SIG = MAX_SIG
+};
+
+/* Global objects ----------------------------------------------------------*/
+QActive * const AO_Philo[N_PHILO] = {     /* "opaque" pointers to Philo AO */
+    (QActive *)&l_philo[0],
+    (QActive *)&l_philo[1],
+    (QActive *)&l_philo[2],
+    (QActive *)&l_philo[3],
+    (QActive *)&l_philo[4]
+};
+
+/*..........................................................................*/
+void Philo_ctor(void) {                    /* instantiate all Philo objects */
+    uint8_t n;
+    Philo *me;
+    for (n = 0; n < N_PHILO; ++n) {
+        me = &l_philo[n];
+        QActive_ctor(&me->super, (QStateHandler)&Philo_initial);
+        QTimeEvt_ctor(&me->timeEvt, TIMEOUT_SIG);
+    }
+}
+/*..........................................................................*/
+QState Philo_initial(Philo *me, QEvt const *e) {
+    static uint8_t registered;         /* starts off with 0, per C-standard */
+    (void)e;        /* suppress the compiler warning about unused parameter */
+    if (!registered) {
+        QS_OBJ_DICTIONARY(&l_philo[0]);
+        QS_OBJ_DICTIONARY(&l_philo[0].timeEvt);
+        QS_OBJ_DICTIONARY(&l_philo[1]);
+        QS_OBJ_DICTIONARY(&l_philo[1].timeEvt);
+        QS_OBJ_DICTIONARY(&l_philo[2]);
+        QS_OBJ_DICTIONARY(&l_philo[2].timeEvt);
+        QS_OBJ_DICTIONARY(&l_philo[3]);
+        QS_OBJ_DICTIONARY(&l_philo[3].timeEvt);
+        QS_OBJ_DICTIONARY(&l_philo[4]);
+        QS_OBJ_DICTIONARY(&l_philo[4].timeEvt);
+
+        QS_FUN_DICTIONARY(&Philo_initial);
+        QS_FUN_DICTIONARY(&Philo_thinking);
+        QS_FUN_DICTIONARY(&Philo_hungry);
+        QS_FUN_DICTIONARY(&Philo_eating);
+
+        registered = (uint8_t)1;
+    }
+    QS_SIG_DICTIONARY(HUNGRY_SIG, me);            /* signal for each Philos */
+    QS_SIG_DICTIONARY(TIMEOUT_SIG, me);           /* signal for each Philos */
+
+    QActive_subscribe((QActive *)me, EAT_SIG);
+
+    return Q_TRAN(&Philo_thinking);          /* top-most initial transition */
+}
+/*..........................................................................*/
+QState Philo_thinking(Philo *me, QEvt const *e) {
+    switch (e->sig) {
+        case Q_ENTRY_SIG: {
+            QTimeEvt_postIn(&me->timeEvt, (QActive *)me, THINK_TIME);
+            return Q_HANDLED();
+        }
+        case TIMEOUT_SIG: {
+            BSP_busyDelay();
+            return Q_TRAN(&Philo_hungry);
+        }
+        case EAT_SIG:                         /* intentionally fall-through */
+        case DONE_SIG: {
+                      /* EAT or DONE must be for other Philos than this one */
+            Q_ASSERT(((TableEvt const *)e)->philoNum != PHILO_ID(me));
+            return Q_HANDLED();
+        }
+    }
+    return Q_SUPER(&QHsm_top);
+}
+/*..........................................................................*/
+QState Philo_hungry(Philo *me, QEvt const *e) {
+    switch (e->sig) {
+        case Q_ENTRY_SIG: {
+            TableEvt *pe = Q_NEW(TableEvt, HUNGRY_SIG);
+            pe->philoNum = PHILO_ID(me);
+            QActive_postFIFO(AO_Table, (QEvt *)pe);
+            return Q_HANDLED();
+        }
+        case EAT_SIG: {
+            if (((TableEvt const *)e)->philoNum == PHILO_ID(me)) {
+                BSP_busyDelay();
+                return Q_TRAN(&Philo_eating);
+            }
+            break;
+        }
+        case DONE_SIG: {
+                             /* DONE must be for other Philos than this one */
+            Q_ASSERT(((TableEvt const *)e)->philoNum != PHILO_ID(me));
+            return Q_HANDLED();
+        }
+    }
+    return Q_SUPER(&QHsm_top);
+}
+/*..........................................................................*/
+QState Philo_eating(Philo *me, QEvt const *e) {
+    switch (e->sig) {
+        case Q_ENTRY_SIG: {
+            QTimeEvt_postIn(&me->timeEvt, (QActive *)me, EAT_TIME);
+            return Q_HANDLED();
+        }
+        case Q_EXIT_SIG: {
+            TableEvt *pe = Q_NEW(TableEvt, DONE_SIG);
+            pe->philoNum = PHILO_ID(me);
+            QF_publish((QEvt *)pe);
+            return Q_HANDLED();
+        }
+        case TIMEOUT_SIG: {
+            BSP_busyDelay();
+            return Q_TRAN(&Philo_thinking);
+        }
+        case EAT_SIG:                         /* intentionally fall-through */
+        case DONE_SIG: {
+                      /* EAT or DONE must be for other Philos than this one */
+            Q_ASSERT(((TableEvt const *)e)->philoNum != PHILO_ID(me));
+            return Q_HANDLED();
+        }
+    }
+    return Q_SUPER(&QHsm_top);
+}
+

+ 158 - 0
examples/80251/vanilla/keil/dpp-mcb251/table.c

@@ -0,0 +1,158 @@
+/*****************************************************************************
+* Product: DPP example
+* Last Updated for Version: 4.5.00
+* Date of the Last Update:  May 18, 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"
+#include "dpp.h"
+#include "bsp.h"
+
+Q_DEFINE_THIS_FILE
+
+/* Active object class -----------------------------------------------------*/
+typedef struct TableTag {
+    QActive super;
+    uint8_t fork[N_PHILO];
+    uint8_t isHungry[N_PHILO];
+} Table;
+
+static QState Table_initial(Table *me, QEvt const *e);
+static QState Table_serving(Table *me, QEvt const *e);
+
+#define RIGHT(n_) ((uint8_t)(((n_) + (N_PHILO - 1)) % N_PHILO))
+#define LEFT(n_)  ((uint8_t)(((n_) + 1) % N_PHILO))
+enum ForkState { FREE, USED };
+
+/* Local objects -----------------------------------------------------------*/
+static Table l_table;     /* the single instance of the Table active object */
+
+/* Global-scope objects ----------------------------------------------------*/
+QActive * const AO_Table = (QActive *)&l_table;      /* "opaque" AO pointer */
+
+/*..........................................................................*/
+void Table_ctor(void) {
+    uint8_t n;
+    Table *me = &l_table;
+
+    QActive_ctor(&me->super, (QStateHandler)&Table_initial);
+
+    for (n = 0; n < N_PHILO; ++n) {
+        me->fork[n] = FREE;
+        me->isHungry[n] = 0;
+    }
+}
+/*..........................................................................*/
+QState Table_initial(Table *me, QEvt const *e) {
+    (void)e;        /* suppress the compiler warning about unused parameter */
+
+    QS_OBJ_DICTIONARY(&l_table);
+    QS_FUN_DICTIONARY(&QHsm_top);
+    QS_FUN_DICTIONARY(&Table_initial);
+    QS_FUN_DICTIONARY(&Table_serving);
+
+    QS_SIG_DICTIONARY(DONE_SIG,      0);                  /* global signals */
+    QS_SIG_DICTIONARY(EAT_SIG,       0);
+    QS_SIG_DICTIONARY(TERMINATE_SIG, 0);
+
+    QS_SIG_DICTIONARY(HUNGRY_SIG,    me);          /* signal just for Table */
+
+    QActive_subscribe((QActive *)me, DONE_SIG);
+    QActive_subscribe((QActive *)me, TERMINATE_SIG);
+
+    return Q_TRAN(&Table_serving);
+}
+/*..........................................................................*/
+QState Table_serving(Table *me, QEvt const *e) {
+    uint8_t n, m;
+    TableEvt *pe;
+
+    switch (e->sig) {
+        case HUNGRY_SIG: {
+            BSP_busyDelay();
+            n = ((TableEvt const *)e)->philoNum;
+                      /* phil ID must be in range and he must be not hungry */
+            Q_ASSERT((n < N_PHILO) && (!me->isHungry[n]));
+
+            BSP_displyPhilStat(n, "hungry  ");
+            m = LEFT(n);
+            if ((me->fork[m] == FREE) && (me->fork[n] == FREE)) {
+                me->fork[m] = me->fork[n] = USED;
+                pe = Q_NEW(TableEvt, EAT_SIG);
+                pe->philoNum = n;
+                QF_publish((QEvt *)pe);
+                BSP_displyPhilStat(n, "eating  ");
+            }
+            else {
+                me->isHungry[n] = 1;
+            }
+            return Q_HANDLED();
+        }
+        case DONE_SIG: {
+            BSP_busyDelay();
+            n = ((TableEvt const *)e)->philoNum;
+                      /* phil ID must be in range and he must be not hungry */
+            Q_ASSERT((n < N_PHILO) && (!me->isHungry[n]));
+
+            BSP_displyPhilStat(n, "thinking");
+            m = LEFT(n);
+                                      /* both forks of Phil[n] must be used */
+            Q_ASSERT((me->fork[n] == USED) && (me->fork[m] == USED));
+
+            me->fork[m] = me->fork[n] = FREE;
+            m = RIGHT(n);                       /* check the right neighbor */
+            if (me->isHungry[m] && (me->fork[m] == FREE)) {
+                me->fork[n] = me->fork[m] = USED;
+                me->isHungry[m] = 0;
+                pe = Q_NEW(TableEvt, EAT_SIG);
+                pe->philoNum = m;
+                QF_publish((QEvt *)pe);
+                BSP_displyPhilStat(m, "eating  ");
+            }
+            m = LEFT(n);                         /* check the left neighbor */
+            n = LEFT(m);                  /* left fork of the left neighbor */
+            if (me->isHungry[m] && (me->fork[n] == FREE)) {
+                me->fork[m] = me->fork[n] = USED;
+                me->isHungry[m] = 0;
+                pe = Q_NEW(TableEvt, EAT_SIG);
+                pe->philoNum = m;
+                QF_publish((QEvt *)pe);
+                BSP_displyPhilStat(m, "eating  ");
+            }
+            return Q_HANDLED();
+        }
+        case TERMINATE_SIG: {
+            QF_stop();
+            return Q_HANDLED();
+        }
+    }
+    return Q_SUPER(&QHsm_top);
+}

+ 207 - 0
examples/80x86/dos/watcom/l/bomb/bomb1.c

@@ -0,0 +1,207 @@
+/*****************************************************************************
+* Product:  Time Bomb Example with "Nested Switch Statement"
+* Last Updated for Version: 4.1.01
+* Date of the Last Update:  Nov 04, 2009
+*
+*                    Q u a n t u m     L e a P s
+*                    ---------------------------
+*                    innovating embedded systems
+*
+* Copyright (C) 2002-2009 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 "bsp.h"
+
+enum BombSignals {                          /* all signals for the Bomb FSM */
+    UP_SIG,
+    DOWN_SIG,
+    ARM_SIG,
+    TICK_SIG
+};
+
+enum BombStates {                            /* all states for the Bomb FSM */
+    SETTING_STATE,
+    TIMING_STATE
+};
+
+typedef struct EventTag {
+    uint16_t sig;                                    /* signal of the event */
+    /* add event parameters by derivation from the Event structure... */
+} Event;
+
+typedef struct TickEvtTag {
+    Event super;                         /* derive from the Event structure */
+    uint8_t fine_time;                           /* the fine 1/10 s counter */
+} TickEvt;
+
+typedef struct Bomb1Tag {                                   /* the Bomb FSM */
+    uint8_t state;                             /* the scalar state-variable */
+    uint8_t timeout;                    /* number of seconds till explosion */
+    uint8_t code;              /* currently entered code to disarm the bomb */
+    uint8_t defuse;                /* secret defuse code to disarm the bomb */
+} Bomb1;
+
+void Bomb1_ctor(Bomb1 *me, uint8_t defuse);            /* the "constructor" */
+void Bomb1_init(Bomb1 *me);                              /* init() function */
+void Bomb1_dispatch(Bomb1 *me, Event const *e);
+
+                                     /* macro for taking a state transition */
+#define TRAN(target_)  (me->state = (uint8_t)(target_))
+
+                                        /* the initial value of the timeout */
+#define INIT_TIMEOUT   10
+
+/*..........................................................................*/
+void Bomb1_ctor(Bomb1 *me, uint8_t defuse) {
+    me->defuse = defuse;    /* the defuse code is assigned at instantiation */
+}
+/*..........................................................................*/
+void Bomb1_init(Bomb1 *me) {
+    me->timeout = INIT_TIMEOUT;  /* timeout is initialized in initial tran. */
+    TRAN(SETTING_STATE);
+}
+/*..........................................................................*/
+void Bomb1_dispatch(Bomb1 *me, Event const *e) {
+    switch (me->state) {
+        case SETTING_STATE: {
+            switch (e->sig) {
+                case UP_SIG: {
+                    if (me->timeout < 60) {
+                        ++me->timeout;
+                        BSP_display(me->timeout);
+                    }
+                    break;
+                }
+                case DOWN_SIG: {
+                    if (me->timeout > 1) {
+                        --me->timeout;
+                        BSP_display(me->timeout);
+                    }
+                    break;
+                }
+                case ARM_SIG: {
+                    me->code = 0;
+                    TRAN(TIMING_STATE);           /* transition to "timing" */
+                    break;
+                }
+            }
+            break;
+        }
+        case TIMING_STATE: {
+            switch (e->sig) {
+                case UP_SIG: {
+                    me->code <<= 1;
+                    me->code |= 1;
+                    break;
+                }
+                case DOWN_SIG: {
+                    me->code <<= 1;
+                    break;
+                }
+                case ARM_SIG: {
+                    if (me->code == me->defuse) {
+                        TRAN(SETTING_STATE);     /* transition to "setting" */
+                    }
+                    break;
+                }
+                case TICK_SIG: {
+                    if (((TickEvt const *)e)->fine_time == 0) {
+                        --me->timeout;
+                        BSP_display(me->timeout);
+                        if (me->timeout == 0) {
+                            BSP_boom();                 /* destroy the bomb */
+                        }
+                    }
+                    break;
+                }
+            }
+            break;
+        }
+    }
+}
+
+/* Test harness ------------------------------------------------------------*/
+#include <stdio.h>
+#include <conio.h>
+#include <dos.h>
+#include <stdlib.h>                                          /* for _exit() */
+
+static Bomb1 l_bomb;                                       /* time bomb FSM */
+
+/*..........................................................................*/
+void main() {
+
+    Bomb1_ctor(&l_bomb, 0x0D);       /* the secret defuse code, 1101 binary */
+
+    printf("Time Bomb (Nested switch)\n"
+           "Press 'u'   for UP   event\n"
+           "Press 'd'   for DOWN event\n"
+           "Press 'a'   for ARM  event\n"
+           "Press <Esc> to quit.\n");
+
+    Bomb1_init(&l_bomb);                     /* take the initial transition */
+
+    for (;;) {                                                /* event loop */
+        static TickEvt tick_evt = { TICK_SIG, 0};
+
+        delay(100);                                         /* 100 ms delay */
+
+        if (++tick_evt.fine_time == 10) {
+            tick_evt.fine_time = 0;
+        }
+        printf("T(%1d)%c", tick_evt.fine_time,
+                             (tick_evt.fine_time == 0) ? '\n' : ' ');
+
+        Bomb1_dispatch(&l_bomb, (Event *)&tick_evt); /* dispatch tick event */
+
+        if (_kbhit()) {
+            static Event const up_evt   = { UP_SIG   };
+            static Event const down_evt = { DOWN_SIG };
+            static Event const arm_evt  = { ARM_SIG  };
+            Event const *e = (Event *)0;
+
+            switch (_getch()) {
+                case 'u': {                                     /* UP event */
+                    printf("\nUP  : ");
+                    e = &up_evt;                   /* generate the UP event */
+                    break;
+                }
+                case 'd': {                                   /* DOWN event */
+                    printf("\nDOWN: ");
+                    e = &down_evt;               /* generate the DOWN event */
+                    break;
+                }
+                case 'a': {                                    /* ARM event */
+                    printf("\nARM : ");
+                    e = &arm_evt;                 /* generate the ARM event */
+                    break;
+                }
+                case '\33': {                                  /* <Esc> key */
+                    printf("\nESC : Bye! Bye!");
+                    fflush(stdout);
+                    _exit(0);
+                    break;
+                }
+            }
+
+            if (e != (Event *)0) {             /* keyboard event available? */
+                Bomb1_dispatch(&l_bomb, e);           /* dispatch the event */
+            }
+        }
+    }
+}

+ 1 - 0
examples/80x86/dos/watcom/l/bomb/bomb1.rsp

@@ -0,0 +1 @@
+Name dbg\bomb1.exe File dbg\bsp.obj,dbg\bomb1.obj

+ 214 - 0
examples/80x86/dos/watcom/l/bomb/bomb2.c

@@ -0,0 +1,214 @@
+/*****************************************************************************
+* Product:  Time Bomb Example with "State Table"
+* Last Updated for Version: 4.1.01
+* Date of the Last Update:  Nov 04, 2009
+*
+*                    Q u a n t u m     L e a P s
+*                    ---------------------------
+*                    innovating embedded systems
+*
+* Copyright (C) 2002-2009 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 "bsp.h"
+#include "statetbl.h"
+
+enum BombSignals {                          /* all signals for the Bomb FSM */
+    UP_SIG,
+    DOWN_SIG,
+    ARM_SIG,
+    TICK_SIG,
+
+    MAX_SIG                                        /* the number of signals */
+};
+
+enum BombStates {                            /* all states for the Bomb FSM */
+    SETTING_STATE,
+    TIMING_STATE,
+
+    MAX_STATE                                       /* the number of states */
+};
+
+typedef struct TickEvtTag {
+    Event super;                         /* derive from the Event structure */
+    uint8_t fine_time;                           /* the fine 1/10 s counter */
+} TickEvt;
+
+typedef struct Bomb2Tag {                                   /* the Bomb FSM */
+    StateTable super;               /* derive from the StateTable structure */
+    uint8_t timeout;                    /* number of seconds till explosion */
+    uint8_t defuse;                /* secret defuse code to disarm the bomb */
+    uint8_t code;              /* currently entered code to disarm the bomb */
+} Bomb2;
+
+void Bomb2_ctor(Bomb2 *me, uint8_t defuse);            /* the "constructor" */
+
+void Bomb2_initial     (Bomb2 *me);               /* the initial transition */
+
+void Bomb2_setting_UP  (Bomb2 *me, Event const *e);  /* transition function */
+void Bomb2_setting_DOWN(Bomb2 *me, Event const *e);  /* transition function */
+void Bomb2_setting_ARM (Bomb2 *me, Event const *e);  /* transition function */
+void Bomb2_timing_UP   (Bomb2 *me, Event const *e);  /* transition function */
+void Bomb2_timing_DOWN (Bomb2 *me, Event const *e);  /* transition function */
+void Bomb2_timing_ARM  (Bomb2 *me, Event const *e);  /* transition function */
+void Bomb2_timing_TICK (Bomb2 *me, Event const *e);  /* transition function */
+
+                                        /* the initial value of the timeout */
+#define INIT_TIMEOUT   10
+
+/*..........................................................................*/
+void Bomb2_ctor(Bomb2 *me, uint8_t defuse) {
+    /* state table for Bomb state machine */
+    static const Tran bomb2_state_table[MAX_STATE][MAX_SIG] = {
+        { (Tran)&Bomb2_setting_UP,  (Tran)&Bomb2_setting_DOWN,
+          (Tran)&Bomb2_setting_ARM, &StateTable_empty },
+        { (Tran)&Bomb2_timing_UP,   (Tran)&Bomb2_timing_DOWN,
+          (Tran)&Bomb2_timing_ARM,  (Tran)&Bomb2_timing_TICK  }
+    };
+    StateTable_ctor(&me->super,
+                    &bomb2_state_table[0][0], MAX_STATE, MAX_SIG,
+                    (Tran)&Bomb2_initial);      /* construct the superclass */
+    me->defuse = defuse;                      /* set the secret defuse code */
+}
+/*..........................................................................*/
+void Bomb2_initial(Bomb2 *me) {
+    me->timeout = INIT_TIMEOUT;
+    TRAN(SETTING_STATE);
+}
+/*..........................................................................*/
+void Bomb2_setting_UP(Bomb2 *me, Event const *e) {
+    (void)e;               /* avoid compiler warning about unused parameter */
+    if (me->timeout < 60) {
+        ++me->timeout;
+        BSP_display(me->timeout);
+    }
+}
+/*..........................................................................*/
+void Bomb2_setting_DOWN(Bomb2 *me, Event const *e) {
+    (void)e;               /* avoid compiler warning about unused parameter */
+    if (me->timeout > 1) {
+        --me->timeout;
+        BSP_display(me->timeout);
+    }
+}
+/*..........................................................................*/
+void Bomb2_setting_ARM(Bomb2 *me, Event const *e) {
+    (void)e;               /* avoid compiler warning about unused parameter */
+    me->code = 0;
+    TRAN(TIMING_STATE);                           /* transition to "timing" */
+}
+/*..........................................................................*/
+void Bomb2_timing_UP(Bomb2 *me, Event const *e) {
+    (void)e;               /* avoid compiler warning about unused parameter */
+    me->code <<= 1;
+    me->code |= 1;
+}
+/*..........................................................................*/
+void Bomb2_timing_DOWN(Bomb2 *me, Event const *e) {
+    (void)e;               /* avoid compiler warning about unused parameter */
+    me->code <<= 1;
+}
+/*..........................................................................*/
+void Bomb2_timing_ARM(Bomb2 *me, Event const *e) {
+    (void)e;               /* avoid compiler warning about unused parameter */
+    if (me->code == me->defuse) {
+        TRAN(SETTING_STATE);                     /* transition to "setting" */
+    }
+}
+/*..........................................................................*/
+void Bomb2_timing_TICK(Bomb2 *me, Event const *e) {
+    if (((TickEvt const *)e)->fine_time == 0) {
+        --me->timeout;
+        BSP_display(me->timeout);
+        if (me->timeout == 0) {
+            BSP_boom();                                 /* destroy the bomb */
+        }
+    }
+}
+
+/* Test harness ------------------------------------------------------------*/
+#include <stdio.h>
+#include <conio.h>
+#include <dos.h>
+#include <stdlib.h>                                          /* for _exit() */
+
+static Bomb2 l_bomb;                                       /* time bomb FSM */
+
+/*..........................................................................*/
+int main() {
+
+    Bomb2_ctor(&l_bomb, 0x0D);  /* instantiate with defuse code 1101 binary */
+
+    printf("Time Bomb (State-Table)\n"
+           "Press 'u'   for UP   event\n"
+           "Press 'd'   for DOWN event\n"
+           "Press 'a'   for ARM  event\n"
+           "Press <Esc> to quit.\n");
+
+    StateTable_init((StateTable *)&l_bomb);  /* take the initial transition */
+
+    for (;;) {                                                /* event loop */
+        static TickEvt tick_evt = { TICK_SIG, 0};
+
+        delay(100);                                         /* 100 ms delay */
+
+        if (++tick_evt.fine_time == 10) {
+            tick_evt.fine_time = 0;
+        }
+        printf("T(%1d)%c", tick_evt.fine_time,
+                             (tick_evt.fine_time == 0) ? '\n' : ' ');
+
+        StateTable_dispatch((StateTable *)&l_bomb, (Event *)&tick_evt);
+
+        if (kbhit()) {
+            static Event const up_evt   = { UP_SIG   };
+            static Event const down_evt = { DOWN_SIG };
+            static Event const arm_evt  = { ARM_SIG  };
+            Event const *e = (Event *)0;
+
+            switch (getch()) {
+                case 'u': {                                     /* UP event */
+                    printf("\nUP  : ");
+                    e = &up_evt;                   /* generate the UP event */
+                    break;
+                }
+                case 'd': {                                   /* DOWN event */
+                    printf("\nDOWN: ");
+                    e = &down_evt;               /* generate the DOWN event */
+                    break;
+                }
+                case 'a': {                                    /* ARM event */
+                    printf("\nARM : ");
+                    e = &arm_evt;                 /* generate the ARM event */
+                    break;
+                }
+                case '\33': {                                  /* <Esc> key */
+                    printf("\nESC : Bye! Bye!");
+                    fflush(stdout);
+                    _exit(0);
+                    break;
+                }
+            }
+            if (e != (Event *)0) {             /* keyboard event available? */
+                StateTable_dispatch((StateTable *)&l_bomb, e);
+            }
+        }
+    }
+
+    return 0;
+}

+ 1 - 0
examples/80x86/dos/watcom/l/bomb/bomb2.rsp

@@ -0,0 +1 @@
+Name dbg\bomb2.exe File dbg\bsp.obj,dbg\statetbl.obj,dbg\bomb2.obj

+ 207 - 0
examples/80x86/dos/watcom/l/bomb/bomb4.c

@@ -0,0 +1,207 @@
+/*****************************************************************************
+* Product: Time Bomb Example with QEP
+* Last Updated for Version: 4.5.00
+* Date of the Last Update:  May 18, 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 "qep_port.h"                /* the port of the QEP event processor */
+#include "bsp.h"                                   /* board support package */
+
+enum BombSignals {                          /* all signals for the Bomb FSM */
+    UP_SIG = Q_USER_SIG,
+    DOWN_SIG,
+    ARM_SIG,
+    TICK_SIG
+};
+
+typedef struct TickEvtTag {
+    QEvt super;                       /* derive from the QEvt structure */
+    uint8_t fine_time;                           /* the fine 1/10 s counter */
+} TickEvt;
+
+typedef struct Bomb4Tag {
+    QFsm super;                                         /* derive from QFsm */
+    uint8_t timeout;                    /* number of seconds till explosion */
+    uint8_t code;              /* currently entered code to disarm the bomb */
+    uint8_t defuse;                /* secret defuse code to disarm the bomb */
+} Bomb4;
+
+void Bomb4_ctor(Bomb4 *me, uint8_t defuse);
+
+static QState Bomb4_initial(Bomb4 *me, QEvt const *e);
+static QState Bomb4_setting(Bomb4 *me, QEvt const *e);
+static QState Bomb4_timing (Bomb4 *me, QEvt const *e);
+
+/*--------------------------------------------------------------------------*/
+                                        /* the initial value of the timeout */
+#define INIT_TIMEOUT   10
+
+/*..........................................................................*/
+void Bomb4_ctor(Bomb4 *me, uint8_t defuse) {
+    QFsm_ctor(&me->super, (QStateHandler)&Bomb4_initial);/* superclass ctor */
+    me->defuse = defuse;    /* the defuse code is assigned at instantiation */
+}
+/*..........................................................................*/
+QState Bomb4_initial(Bomb4 *me, QEvt const *e) {
+    (void)e;
+    me->timeout = INIT_TIMEOUT;
+    return Q_TRAN(&Bomb4_setting);
+}
+/*..........................................................................*/
+QState Bomb4_setting(Bomb4 *me, QEvt const *e) {
+    switch (e->sig) {
+        case UP_SIG: {
+            if (me->timeout < 60) {
+                ++me->timeout;
+                BSP_display(me->timeout);
+            }
+            return Q_HANDLED();
+        }
+        case DOWN_SIG: {
+            if (me->timeout > 1) {
+                --me->timeout;
+                BSP_display(me->timeout);
+            }
+            return Q_HANDLED();
+        }
+        case ARM_SIG: {
+            return Q_TRAN(&Bomb4_timing);         /* transition to "timing" */
+        }
+    }
+    return Q_IGNORED();
+}
+/*..........................................................................*/
+QState Bomb4_timing(Bomb4 *me, QEvt const *e) {
+    switch (e->sig) {
+        case Q_ENTRY_SIG: {
+            me->code = 0;                          /* clear the defuse code */
+            return Q_HANDLED();
+        }
+        case UP_SIG: {
+            me->code <<= 1;
+            me->code |= 1;
+            return Q_HANDLED();
+        }
+        case DOWN_SIG: {
+            me->code <<= 1;
+            return Q_HANDLED();
+        }
+        case ARM_SIG: {
+            if (me->code == me->defuse) {
+                return Q_TRAN(&Bomb4_setting);
+            }
+            return Q_HANDLED();
+        }
+        case TICK_SIG: {
+            if (((TickEvt const *)e)->fine_time == 0) {
+                --me->timeout;
+                BSP_display(me->timeout);
+                if (me->timeout == 0) {
+                    BSP_boom();                         /* destroy the bomb */
+                }
+            }
+            return Q_HANDLED();
+        }
+    }
+    return Q_IGNORED();
+}
+
+/* Test harness ------------------------------------------------------------*/
+#include <stdio.h>
+#include <conio.h>
+#include <dos.h>
+#include <stdlib.h>                                          /* for _exit() */
+
+static Bomb4 l_bomb;                                       /* time bomb FSM */
+
+/*..........................................................................*/
+int main() {
+
+    Bomb4_ctor(&l_bomb, 0x0D);       /* the secret defuse code, 1101 binary */
+
+    printf("Time Bomb (QEP QFsm class)\n"
+           "Press 'u'   for UP   event\n"
+           "Press 'd'   for DOWN event\n"
+           "Press 'a'   for ARM  event\n"
+           "Press <Esc> to quit.\n");
+
+    QFsm_init((QFsm *)&l_bomb, (QEvt *)0); /* take the initial transition */
+
+    for (;;) {                                                /* event loop */
+        static TickEvt tick_evt = { TICK_SIG, 0, 0, 0 };
+
+        delay(100);                                         /* 100 ms delay */
+
+        if (++tick_evt.fine_time == 10) {
+            tick_evt.fine_time = 0;
+        }
+        printf("T(%1d)%c", tick_evt.fine_time,
+                             (tick_evt.fine_time == 0) ? '\n' : ' ');
+
+        QFsm_dispatch((QFsm *)&l_bomb, (QEvt *)&tick_evt);
+
+        if (kbhit()) {
+            static QEvt const up_evt   = { UP_SIG,   0, 0 };
+            static QEvt const down_evt = { DOWN_SIG, 0, 0 };
+            static QEvt const arm_evt  = { ARM_SIG,  0, 0 };
+            QEvt const *e = (QEvt *)0;
+
+            switch (getch()) {
+                case 'u': {                                     /* UP event */
+                    printf("\nUP  : ");
+                    e = &up_evt;                   /* generate the UP event */
+                    break;
+                }
+                case 'd': {                                   /* DOWN event */
+                    printf("\nDOWN: ");
+                    e = &down_evt;               /* generate the DOWN event */
+                    break;
+                }
+                case 'a': {                                    /* ARM event */
+                    printf("\nARM : ");
+                    e = &arm_evt;                 /* generate the ARM event */
+                    break;
+                }
+                case '\33': {                                  /* <Esc> key */
+                    printf("\nESC : Bye! Bye!");
+                    fflush(stdout);
+                    _exit(0);
+                    break;
+                }
+            }
+            if (e != (QEvt *)0) {            /* keyboard event available? */
+                QFsm_dispatch((QFsm *)&l_bomb, e);    /* dispatch the event */
+            }
+        }
+    }
+
+    return 0;
+}

+ 1 - 0
examples/80x86/dos/watcom/l/bomb/bomb4.rsp

@@ -0,0 +1 @@
+Name dbg\bomb4.exe File dbg\bsp.obj,dbg\bomb4.obj Library ..\..\..\..\..\..\ports\80x86\dos\watcom\l\dbg\qep.lib

+ 50 - 0
examples/80x86/dos/watcom/l/bomb/bsp.c

@@ -0,0 +1,50 @@
+/*****************************************************************************
+* Product: Board Support Package (BSP) for the Time Bomb example
+* Last Updated for Version: 4.1.01
+* Date of the Last Update:  Nov 04, 2009
+*
+*                    Q u a n t u m     L e a P s
+*                    ---------------------------
+*                    innovating embedded systems
+*
+* Copyright (C) 2002-2009 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 "bsp.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+/*..........................................................................*/
+void BSP_display(uint8_t timeout) {
+    printf("[%3d] ", (int)timeout);
+    fflush(stdout);
+}
+/*..........................................................................*/
+void BSP_boom(void) {
+    printf("BOOM!!!");
+    fflush(stdout);
+    _exit(0);
+}
+/*..........................................................................*/
+/* this function is used by the QP embedded systems-friendly assertions */
+void Q_onAssert(char const * const file, int line) {
+    printf("Assertion failed in %s, line %d", file, line);
+    fflush(stdout);
+    _exit(-1);
+}

+ 37 - 0
examples/80x86/dos/watcom/l/bomb/bsp.h

@@ -0,0 +1,37 @@
+/*****************************************************************************
+* Product: Board Support Package (BSP) for the Time Bomb example
+* Last Updated for Version: 4.1.01
+* Date of the Last Update:  Nov 04, 2009
+*
+*                    Q u a n t u m     L e a P s
+*                    ---------------------------
+*                    innovating embedded systems
+*
+* Copyright (C) 2002-2009 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 bsp_h
+#define bsp_h
+
+             /* Exact-width types. WG14/N843 C99 Standard, Section 7.18.1.1 */
+#include <stdint.h>
+
+void BSP_display(uint8_t timeout);
+void BSP_boom(void);
+
+#endif                                                             /* bsp_h */

+ 1 - 0
examples/80x86/dos/watcom/l/bomb/inc_qp.rsp

@@ -0,0 +1 @@
+-i=. -i=..\..\..\..\..\..\include -i=..\..\..\..\..\..\ports\80x86\dos\watcom\l

+ 57 - 0
examples/80x86/dos/watcom/l/bomb/make_b1.bat

@@ -0,0 +1,57 @@
+@echo off
+:: ===========================================================================
+:: Bomb1 example, 80x86, Open Watcom compiler
+:: Last Updated for Version: 4.1.06
+:: Date of the Last Update:  Jan 06, 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
+:: ===========================================================================
+
+:: If you have defined the WATCOM environment variable, the following line has
+:: no effect and your definition is used. However, if the varible WATCOM is
+:: not defined, the following default is assuemed: 
+if "%WATCOM%"=="" set WATCOM=c:\tools\WATCOM
+
+path %WATCOM%\binw
+set INCLUDE=%WATCOM%\H
+set CC=wcc.exe
+set AS=wasm.exe
+set LD=wlink.exe
+
+set BINDIR=dbg
+set CCFLAGS=-d2 -ml -3 -fpi87
+
+:: compile -------------------------------------------------------------------
+set SRCDIR=.
+set CCINC=@inc_qp.rsp
+
+@echo on
+%CC% %CCFLAGS% %CCINC% -fo=%BINDIR%\bsp.obj      %SRCDIR%\bsp.c
+%CC% %CCFLAGS% %CCINC% -fo=%BINDIR%\bomb1.obj    %SRCDIR%\bomb1.c
+@echo off
+
+
+:: link ----------------------------------------------------------------------
+@echo on
+%LD% @bomb1.rsp
+@echo off

+ 59 - 0
examples/80x86/dos/watcom/l/bomb/make_b2.bat

@@ -0,0 +1,59 @@
+@echo off
+:: ===========================================================================
+:: Bomb2 example, 80x86, Open Watcom compiler
+:: Last Updated for Version: 4.1.06
+:: Date of the Last Update:  Jan 06, 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
+:: ===========================================================================
+
+:: If you have defined the WATCOM environment variable, the following line has
+:: no effect and your definition is used. However, if the varible WATCOM is
+:: not defined, the following default is assuemed: 
+if "%WATCOM%"=="" set WATCOM=c:\tools\WATCOM
+
+path %WATCOM%\binw
+set INCLUDE=%WATCOM%\H
+set CC=wcc.exe
+set AS=wasm.exe
+set LD=wlink.exe
+
+set BINDIR=dbg
+set CCFLAGS=-d2 -ml -3 -fpi87
+
+:: compile -------------------------------------------------------------------
+set SRCDIR=.
+set CCINC=@inc_qp.rsp
+
+@echo on
+%CC% %CCFLAGS% %CCINC% -fo=%BINDIR%\bsp.obj      %SRCDIR%\bsp.c
+%CC% %CCFLAGS% %CCINC% -fo=%BINDIR%\statetbl.obj %SRCDIR%\statetbl.c
+%CC% %CCFLAGS% %CCINC% -fo=%BINDIR%\bomb2.obj    %SRCDIR%\bomb2.c
+@echo off
+
+
+:: link ----------------------------------------------------------------------
+@echo on
+%LD% @bomb2.rsp
+@echo off
+

+ 57 - 0
examples/80x86/dos/watcom/l/bomb/make_b4.bat

@@ -0,0 +1,57 @@
+@echo off
+:: ===========================================================================
+:: Bomb4 example, 80x86, Open Watcom compiler
+:: Last Updated for Version: 4.1.06
+:: Date of the Last Update:  Jan 06, 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
+:: ===========================================================================
+
+:: If you have defined the WATCOM environment variable, the following line has
+:: no effect and your definition is used. However, if the varible WATCOM is
+:: not defined, the following default is assuemed: 
+if "%WATCOM%"=="" set WATCOM=c:\tools\WATCOM
+
+path %WATCOM%\binw
+set INCLUDE=%WATCOM%\H
+set CC=wcc.exe
+set AS=wasm.exe
+set LD=wlink.exe
+
+set BINDIR=dbg
+set CCFLAGS=-d2 -ml -3 -fpi87
+
+:: compile -------------------------------------------------------------------
+set SRCDIR=.
+set CCINC=@inc_qp.rsp
+
+@echo on
+%CC% %CCFLAGS% %CCINC% -fo=%BINDIR%\bsp.obj      %SRCDIR%\bsp.c
+%CC% %CCFLAGS% %CCINC% -fo=%BINDIR%\bomb4.obj    %SRCDIR%\bomb4.c
+@echo off
+
+
+:: link ----------------------------------------------------------------------
+@echo on
+%LD% @bomb4.rsp
+@echo off

+ 48 - 0
examples/80x86/dos/watcom/l/bomb/statetbl.c

@@ -0,0 +1,48 @@
+/*****************************************************************************
+* Product: Generic State-Table event processor
+* Date of the Last Update:  Oct 22, 2007
+*
+* Copyright (C) 2002-2007 Miro Samek. All rights reserved.
+*
+* Contact information:
+* e-mail: miro@quantum-leaps.com
+*****************************************************************************/
+#include "bsp.h"          /* for the C99-standard exact-width integer types */
+#include "statetbl.h"
+
+              /* see also embedded-systems-friendly assertions in Chapter 6 */
+#include <assert.h>
+
+/*..........................................................................*/
+void StateTable_ctor(StateTable *me,
+                     Tran const *table, uint8_t n_states, uint8_t n_signals,
+                     Tran initial)
+{
+    me->state_table = table;
+    me->n_states    = n_states;
+    me->n_signals   = n_signals;
+    me->initial     = initial;
+}
+/*..........................................................................*/
+void StateTable_init(StateTable *me) {
+    me->state = me->n_states;
+    (*me->initial)(me, (Event *)0);          /* top-most initial transition */
+
+    assert(me->state < me->n_states);/* the initial tran. must change state */
+}
+/*..........................................................................*/
+void StateTable_dispatch(StateTable *me, Event const *e) {
+    Tran t;
+
+    assert(e->sig < me->n_signals);          /* require the signal in range */
+
+    t = me->state_table[me->state*me->n_signals + e->sig];
+    (*t)(me, e);                         /* execute the transition function */
+
+    assert(me->state < me->n_states);   /* ensure that state stays in range */
+}
+/*..........................................................................*/
+void StateTable_empty(StateTable *me, Event const *e) {
+    (void)me;               /* void compiler warning about unused parameter */
+    (void)e;                /* void compiler warning about unused parameter */
+}

+ 40 - 0
examples/80x86/dos/watcom/l/bomb/statetbl.h

@@ -0,0 +1,40 @@
+/*****************************************************************************
+* Product: Generic State-Table event processor
+* Date of the Last Update:  Oct 22, 2007
+*
+* Copyright (C) 2002-2007 Miro Samek. All rights reserved.
+*
+* Contact information:
+* e-mail: miro@quantum-leaps.com
+*****************************************************************************/
+#ifndef statetbl_h
+#define statetbl_h
+
+typedef struct EventTag {
+    uint16_t sig;                                    /* signal of the event */
+    /* add event parameters by derivation from the Event structure */
+} Event;
+
+struct StateTableTag;                                /* forward declaration */
+
+typedef void (*Tran)(struct StateTableTag *me, Event const *e);
+
+typedef struct StateTableTag {
+    uint8_t state;                              /* the current active state */
+    Tran const *state_table;                             /* the State-Table */
+    uint8_t n_states;                                   /* number of states */
+    uint8_t n_signals;                                 /* number of signals */
+    Tran initial;                                 /* the initial transition */
+} StateTable;
+
+void StateTable_ctor(StateTable *me,
+                     Tran const *table, uint8_t n_states, uint8_t n_signals,
+                     Tran initial);
+void StateTable_init(StateTable *me);
+void StateTable_dispatch(StateTable *me, Event const *e);
+void StateTable_empty(StateTable *me, Event const *e);
+
+        /* macro for taking a state transition inside a transition function */
+#define TRAN(target_)  (((StateTable *)me)->state = (uint8_t)(target_))
+
+#endif                                                        /* statetbl_h */

+ 128 - 0
examples/80x86/dos/watcom/l/calc/bsp.c

@@ -0,0 +1,128 @@
+/*****************************************************************************
+* Product: Board Support Package (BSP) for the Calculator example
+* Last Updated for Version: 4.1.05
+* Date of the Last Update:  Aug 27, 2010
+*
+*                    Q u a n t u m     L e a P s
+*                    ---------------------------
+*                    innovating embedded systems
+*
+* Copyright (C) 2002-2010 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 "bsp.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define DISP_WIDTH  9
+
+static char l_display[DISP_WIDTH + 1];            /* the calculator display */
+static int  l_len;                        /* number of displayed characters */
+
+/*..........................................................................*/
+void BSP_clear(void) {
+    memset(l_display, ' ', DISP_WIDTH - 1);
+    l_display[DISP_WIDTH - 1] = '0';
+    l_display[DISP_WIDTH] = '\0';
+    l_len = 0;
+}
+/*..........................................................................*/
+void BSP_insert(int keyId) {
+    if (l_len == 0) {
+        l_display[DISP_WIDTH - 1] = (char)keyId;
+        ++l_len;
+    }
+    else if (l_len < (DISP_WIDTH - 1)) {
+        memmove(&l_display[0], &l_display[1], DISP_WIDTH - 1);
+        l_display[DISP_WIDTH - 1] = (char)keyId;
+        ++l_len;
+    }
+}
+/*..........................................................................*/
+void BSP_negate(void) {
+    BSP_clear();
+    l_display[DISP_WIDTH - 2] = '-';
+}
+/*..........................................................................*/
+void BSP_display(void) {
+    printf("\n[%s] ", l_display);
+}
+/*..........................................................................*/
+void BSP_exit(void) {
+    printf("\nBye! Bye!");
+    fflush(stdout);
+    _exit(0);
+}
+/*..........................................................................*/
+double BSP_get_value(void) {
+    return strtod(l_display, (char **)0);
+}
+/*..........................................................................*/
+int BSP_eval(double operand1, int oper, double operand2) {
+    int ok = 1;
+    double result;
+    switch (oper) {
+        case KEY_PLUS: {
+            result = operand1 + operand2;
+            break;
+        }
+        case KEY_MINUS: {
+            result = operand1 - operand2;
+            break;
+        }
+        case KEY_MULT: {
+            result = operand1 * operand2;
+            break;
+        }
+        case KEY_DIVIDE: {
+            if ((operand2 < -1e-30) || (1e-30 < operand2)) {
+                result = operand1 / operand2;
+            }
+            else {
+                strcpy(l_display, " Error 0 ");    /* error: divide by zero */
+                ok = 0;
+            }
+            break;
+        }
+    }
+    if (ok) {
+        if ((-0.000001 < result) && (result < 0.000001)) {
+            result = 0.0;
+        }
+        if ((-99999999.0 < result) && (result < 99999999.0)) {
+            sprintf(l_display, "%9.6g", result);
+        }
+        else {
+            strcpy(l_display, " Error 1 ");          /* error: out of range */
+            ok = 0;
+        }
+    }
+    return ok;
+}
+/*..........................................................................*/
+void BSP_message(char const *msg) {
+    printf(msg);
+}
+/*..........................................................................*/
+/* this function is used by the QP embedded systems-friendly assertions */
+void Q_onAssert(char const * const file, int line) {
+    printf("Assertion failed in %s, line %d", file, line);
+    _exit(-1);
+}

+ 46 - 0
examples/80x86/dos/watcom/l/calc/bsp.h

@@ -0,0 +1,46 @@
+/*****************************************************************************
+* Product: Board Support Package (BSP) for the Calculator example
+* Last Updated for Version: 4.0.00
+* Date of the Last Update:  Apr 07, 2008
+*
+*                    Q u a n t u m     L e a P s
+*                    ---------------------------
+*                    innovating embedded systems
+*
+* Copyright (C) 2002-2008 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 bsp_h
+#define bsp_h
+
+#define KEY_PLUS    '+'
+#define KEY_MINUS   '-'
+#define KEY_MULT    '*'
+#define KEY_DIVIDE  '/'
+
+void BSP_clear (void);
+void BSP_negate(void);
+void BSP_insert(int keyId);
+double BSP_get_value(void);
+int  BSP_eval(double operand1, int oper, double operand2);
+void BSP_exit(void);
+
+void BSP_display(void);
+void BSP_message(char const *state);
+
+#endif                                                             /* bsp_h */

+ 526 - 0
examples/80x86/dos/watcom/l/calc/calc.c

@@ -0,0 +1,526 @@
+/*****************************************************************************
+* Product:  Calculator Example
+* Last Updated for Version: 4.5.00
+* Date of the Last Update:  May 18, 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"                        /* the port of the QP framework */
+#include "bsp.h"                                   /* board support package */
+#include "calc.h"
+
+typedef struct CalcTag {
+    QHsm super;                                        /* derives from QHsm */
+    double operand1;                              /* the value of operand 1 */
+    uint8_t operator;                               /* operator key entered */
+} Calc;
+
+static QState Calc_initial  (Calc *me, QEvt const *e);/*init. pseudostate */
+static QState Calc_on       (Calc *me, QEvt const *e);   /* state handler */
+static QState Calc_error    (Calc *me, QEvt const *e);   /* state handler */
+static QState Calc_ready    (Calc *me, QEvt const *e);   /* state handler */
+static QState Calc_result   (Calc *me, QEvt const *e);   /* state handler */
+static QState Calc_begin    (Calc *me, QEvt const *e);   /* state handler */
+static QState Calc_negated1 (Calc *me, QEvt const *e);   /* state handler */
+static QState Calc_operand1 (Calc *me, QEvt const *e);   /* state handler */
+static QState Calc_zero1    (Calc *me, QEvt const *e);   /* state handler */
+static QState Calc_int1     (Calc *me, QEvt const *e);   /* state handler */
+static QState Calc_frac1    (Calc *me, QEvt const *e);   /* state handler */
+static QState Calc_opEntered(Calc *me, QEvt const *e);   /* state handler */
+static QState Calc_negated2 (Calc *me, QEvt const *e);   /* state handler */
+static QState Calc_operand2 (Calc *me, QEvt const *e);   /* state handler */
+static QState Calc_zero2    (Calc *me, QEvt const *e);   /* state handler */
+static QState Calc_int2     (Calc *me, QEvt const *e);   /* state handler */
+static QState Calc_frac2    (Calc *me, QEvt const *e);   /* state handler */
+static QState Calc_final    (Calc *me, QEvt const *e);   /* state handler */
+
+
+/* Local objects -----------------------------------------------------------*/
+static Calc l_calc;                              /* the calculator instance */
+
+/* Global objects ----------------------------------------------------------*/
+QHsm * const the_calc = (QHsm *)&l_calc;
+
+/*..........................................................................*/
+void Calc_ctor(void) {
+    Calc *me = &l_calc;
+    QHsm_ctor(&me->super, (QStateHandler)&Calc_initial);
+}
+/* HSM definition ----------------------------------------------------------*/
+QState Calc_initial(Calc *me, QEvt const *e) {
+    (void)e;                  /* avoid the "unreferenced parameter" warning */
+    BSP_clear();
+    return Q_TRAN(&Calc_on);
+}
+/*..........................................................................*/
+QState Calc_on(Calc *me, QEvt const *e) {
+    switch (e->sig) {
+        case Q_ENTRY_SIG: {
+            BSP_message("on-ENTRY;");
+            return Q_HANDLED();
+        }
+        case Q_EXIT_SIG: {
+            BSP_message("on-EXIT;");
+            return Q_HANDLED();
+        }
+        case Q_INIT_SIG: {
+            BSP_message("on-INIT;");
+            return Q_TRAN(&Calc_ready);
+        }
+        case C_SIG: {
+            BSP_clear();
+            return Q_TRAN(&Calc_on);                  /* transition-to-self */
+        }
+        case OFF_SIG: {
+            return Q_TRAN(&Calc_final);
+        }
+    }
+    return Q_SUPER(&QHsm_top);
+}
+/*..........................................................................*/
+QState Calc_error(Calc *me, QEvt const *e) {
+    (void)me;          /* avoid the compiler warning about unused parameter */
+    switch (e->sig) {
+        case Q_ENTRY_SIG: {
+            BSP_message("error-ENTRY;");
+            return Q_HANDLED();
+        }
+        case Q_EXIT_SIG: {
+            BSP_message("error-EXIT;");
+            return Q_HANDLED();
+        }
+    }
+    return Q_SUPER(&Calc_on);
+}
+/*..........................................................................*/
+QState Calc_ready(Calc *me, QEvt const *e) {
+    switch (e->sig) {
+        case Q_ENTRY_SIG: {
+            BSP_message("ready-ENTRY;");
+            return Q_HANDLED();
+        }
+        case Q_EXIT_SIG: {
+            BSP_message("ready-EXIT;");
+            return Q_HANDLED();
+        }
+        case Q_INIT_SIG: {
+            BSP_message("ready-INIT;");
+            return Q_TRAN(&Calc_begin);
+        }
+        case DIGIT_0_SIG: {
+            BSP_clear();
+            return Q_TRAN(&Calc_zero1);
+        }
+        case DIGIT_1_9_SIG: {
+            BSP_clear();
+            BSP_insert(((CalcEvt const *)e)->key_code);
+            return Q_TRAN(&Calc_int1);
+        }
+        case POINT_SIG: {
+            BSP_clear();
+            BSP_insert((int)'0');
+            BSP_insert((int)'.');
+            return Q_TRAN(&Calc_frac1);
+        }
+        case OPER_SIG: {
+            me->operand1 = BSP_get_value();
+            me->operator = ((CalcEvt const *)e)->key_code;
+            return Q_TRAN(&Calc_opEntered);
+        }
+    }
+    return Q_SUPER(&Calc_on);
+}
+/*..........................................................................*/
+QState Calc_result(Calc *me, QEvt const *e) {
+    (void)me;               /* avoid compiler warning about unused argument */
+    switch (e->sig) {
+        case Q_ENTRY_SIG: {
+            BSP_message("result-ENTRY;");
+            return Q_HANDLED();
+        }
+        case Q_EXIT_SIG: {
+            BSP_message("result-EXIT;");
+            return Q_HANDLED();
+        }
+    }
+    return Q_SUPER(&Calc_ready);
+}
+/*..........................................................................*/
+QState Calc_begin(Calc *me, QEvt const *e) {
+    switch (e->sig) {
+        case Q_ENTRY_SIG: {
+            BSP_message("begin-ENTRY;");
+            return Q_HANDLED();
+        }
+        case Q_EXIT_SIG: {
+            BSP_message("begin-EXIT;");
+            return Q_HANDLED();
+        }
+        case OPER_SIG: {
+            if (((CalcEvt const *)e)->key_code == KEY_MINUS) {
+                return Q_TRAN(&Calc_negated1);
+            }
+            break;
+        }
+    }
+    return Q_SUPER(&Calc_ready);
+}
+/*..........................................................................*/
+QState Calc_negated1(Calc *me, QEvt const *e) {
+    switch (e->sig) {
+        case Q_ENTRY_SIG: {
+            BSP_message("negated1-ENTRY;");
+            BSP_negate();
+            return Q_HANDLED();
+        }
+        case Q_EXIT_SIG: {
+            BSP_message("negated1-EXIT;");
+            return Q_HANDLED();
+        }
+        case OPER_SIG: {
+            if (((CalcEvt const *)e)->key_code == KEY_MINUS) {
+                ;                                      /* explicitly ignore */
+                return Q_HANDLED();                        /* event handled */
+            }
+            break;
+        }
+        case CE_SIG: {
+            BSP_clear();
+            return Q_TRAN(&Calc_begin);
+        }
+        case DIGIT_0_SIG: {
+            BSP_insert(((CalcEvt const *)e)->key_code);
+            return Q_TRAN(&Calc_zero1);
+        }
+        case DIGIT_1_9_SIG: {
+            BSP_insert(((CalcEvt const *)e)->key_code);
+            return Q_TRAN(&Calc_int1);
+        }
+        case POINT_SIG: {
+            BSP_insert(((CalcEvt const *)e)->key_code);
+            return Q_TRAN(&Calc_frac1);
+        }
+    }
+    return Q_SUPER(&Calc_on);
+}
+/*..........................................................................*/
+QState Calc_negated2(Calc *me, QEvt const *e) {
+    switch (e->sig) {
+        case Q_ENTRY_SIG: {
+            BSP_message("negated2-ENTRY;");
+            BSP_negate();
+            return Q_HANDLED();
+        }
+        case Q_EXIT_SIG: {
+            BSP_message("negated2-EXIT;");
+            return Q_HANDLED();
+        }
+        case OPER_SIG: {
+            if (((CalcEvt const *)e)->key_code == KEY_MINUS) {
+                ;                                      /* explicitly ignore */
+                return Q_HANDLED();                        /* event handled */
+            }
+            break;
+        }
+        case CE_SIG: {
+            BSP_clear();
+            return Q_TRAN(&Calc_opEntered);
+        }
+        case DIGIT_0_SIG: {
+            return Q_TRAN(&Calc_zero2);
+        }
+        case DIGIT_1_9_SIG: {
+            BSP_insert(((CalcEvt const *)e)->key_code);
+            return Q_TRAN(&Calc_int2);
+        }
+        case POINT_SIG: {
+            BSP_insert(((CalcEvt const *)e)->key_code);
+            return Q_TRAN(&Calc_frac2);
+        }
+    }
+    return Q_SUPER(&Calc_on);
+}
+/*..........................................................................*/
+QState Calc_operand1(Calc *me, QEvt const *e) {
+    switch (e->sig) {
+        case Q_ENTRY_SIG: {
+            BSP_message("operand1-ENTRY;");
+            return Q_HANDLED();
+        }
+        case Q_EXIT_SIG: {
+            BSP_message("operand1-EXIT;");
+            return Q_HANDLED();
+        }
+        case CE_SIG: {
+            BSP_clear();
+            return Q_TRAN(&Calc_begin);
+        }
+        case OPER_SIG: {
+            me->operand1 = BSP_get_value();
+            me->operator = ((CalcEvt const *)e)->key_code;
+            return Q_TRAN(&Calc_opEntered);
+        }
+        case EQUALS_SIG: {
+            return Q_TRAN(&Calc_result);
+        }
+    }
+    return Q_SUPER(&Calc_on);
+}
+/*..........................................................................*/
+QState Calc_zero1(Calc *me, QEvt const *e) {
+    switch (e->sig) {
+        case Q_ENTRY_SIG: {
+            BSP_message("zero1-ENTRY;");
+            return Q_HANDLED();
+        }
+        case Q_EXIT_SIG: {
+            BSP_message("zero1-EXIT;");
+            return Q_HANDLED();
+        }
+        case DIGIT_0_SIG: {
+            ;                                          /* explicitly ignore */
+            return Q_HANDLED();
+        }
+        case DIGIT_1_9_SIG: {
+            BSP_insert(((CalcEvt const *)e)->key_code);
+            return Q_TRAN(&Calc_int1);
+        }
+        case POINT_SIG: {
+            BSP_insert(((CalcEvt const *)e)->key_code);
+            return Q_TRAN(&Calc_frac1);
+        }
+    }
+    return Q_SUPER(&Calc_operand1);
+}
+/*..........................................................................*/
+QState Calc_int1(Calc *me, QEvt const *e) {
+    switch (e->sig) {
+        case Q_ENTRY_SIG: {
+            BSP_message("int1-ENTRY;");
+            return Q_HANDLED();
+        }
+        case Q_EXIT_SIG: {
+            BSP_message("int1-EXIT;");
+            return Q_HANDLED();
+        }
+        case DIGIT_0_SIG:                     /* intentionally fall through */
+        case DIGIT_1_9_SIG: {
+            BSP_insert(((CalcEvt const *)e)->key_code);
+            return Q_HANDLED();
+        }
+        case POINT_SIG: {
+            BSP_insert(((CalcEvt const *)e)->key_code);
+            return Q_TRAN(&Calc_frac1);
+        }
+    }
+    return Q_SUPER(&Calc_operand1);
+}
+/*..........................................................................*/
+QState Calc_frac1(Calc *me, QEvt const *e) {
+    (void)me;               /* avoid compiler warning about unused argument */
+    switch (e->sig) {
+        case Q_ENTRY_SIG: {
+            BSP_message("frac1-ENTRY;");
+            return Q_HANDLED();
+        }
+        case Q_EXIT_SIG: {
+            BSP_message("frac1-EXIT;");
+            return Q_HANDLED();
+        }
+        case DIGIT_0_SIG:                     /* intentionally fall through */
+        case DIGIT_1_9_SIG: {
+            BSP_insert(((CalcEvt const *)e)->key_code);
+            return Q_HANDLED();
+        }
+        case POINT_SIG: {
+            ;                                          /* explicitly ignore */
+            return Q_HANDLED();
+        }
+    }
+    return Q_SUPER(&Calc_operand1);
+}
+/*..........................................................................*/
+QState Calc_opEntered(Calc *me, QEvt const *e) {
+    switch (e->sig) {
+        case Q_ENTRY_SIG: {
+            BSP_message("opEntered-ENTRY;");
+            return Q_HANDLED();
+        }
+        case Q_EXIT_SIG: {
+            BSP_message("opEntered-EXIT;");
+            return Q_HANDLED();
+        }
+        case OPER_SIG: {
+            if (((CalcEvt const *)e)->key_code == KEY_MINUS) {
+                BSP_clear();
+                return Q_TRAN(&Calc_negated2);
+            }
+            break;
+        }
+        case DIGIT_0_SIG: {
+            BSP_clear();
+            return Q_TRAN(&Calc_zero2);
+        }
+        case DIGIT_1_9_SIG: {
+            BSP_clear();
+            BSP_insert(((CalcEvt const *)e)->key_code);
+            return Q_TRAN(&Calc_int2);
+        }
+        case POINT_SIG: {
+            BSP_clear();
+            BSP_insert((int)'0');
+            BSP_insert((int)'.');
+            return Q_TRAN(&Calc_frac2);
+        }
+    }
+    return Q_SUPER(&Calc_on);
+}
+/*..........................................................................*/
+QState Calc_operand2(Calc *me, QEvt const *e) {
+    switch (e->sig) {
+        case Q_ENTRY_SIG: {
+            BSP_message("operand2-ENTRY;");
+            return Q_HANDLED();
+        }
+        case Q_EXIT_SIG: {
+            BSP_message("operand2-EXIT;");
+            return Q_HANDLED();
+        }
+        case CE_SIG: {
+            BSP_clear();
+            return Q_TRAN(&Calc_opEntered);
+        }
+        case OPER_SIG: {
+            if (BSP_eval(me->operand1, me->operator, BSP_get_value())) {
+                me->operand1 = BSP_get_value();
+                me->operator = ((CalcEvt const *)e)->key_code;
+                return Q_TRAN(&Calc_opEntered);
+            }
+            else {
+                return Q_TRAN(&Calc_error);
+            }
+        }
+        case EQUALS_SIG: {
+            if (BSP_eval(me->operand1, me->operator, BSP_get_value())) {
+                return Q_TRAN(&Calc_result);
+            }
+            else {
+                return Q_TRAN(&Calc_error);
+            }
+        }
+    }
+    return Q_SUPER(&Calc_on);
+}
+/*..........................................................................*/
+QState Calc_zero2(Calc *me, QEvt const *e) {
+    switch (e->sig) {
+        case Q_ENTRY_SIG: {
+            BSP_message("zero2-ENTRY;");
+            return Q_HANDLED();
+        }
+        case Q_EXIT_SIG: {
+            BSP_message("zero2-EXIT;");
+            return Q_HANDLED();
+        }
+        case DIGIT_0_SIG: {
+            ;                                          /* explicitly ignore */
+            return Q_HANDLED();
+        }
+        case DIGIT_1_9_SIG: {
+            BSP_insert(((CalcEvt const *)e)->key_code);
+            return Q_TRAN(&Calc_int2);
+        }
+        case POINT_SIG: {
+            BSP_insert(((CalcEvt const *)e)->key_code);
+            return Q_TRAN(&Calc_frac2);
+        }
+    }
+    return Q_SUPER(&Calc_operand2);
+}
+/*..........................................................................*/
+QState Calc_int2(Calc *me, QEvt const *e) {
+    switch (e->sig) {
+        case Q_ENTRY_SIG: {
+            BSP_message("int2-ENTRY;");
+            return Q_HANDLED();
+        }
+        case Q_EXIT_SIG: {
+            BSP_message("int2-EXIT;");
+            return Q_HANDLED();
+        }
+        case DIGIT_0_SIG:                     /* intentionally fall through */
+        case DIGIT_1_9_SIG: {
+            BSP_insert(((CalcEvt const *)e)->key_code);
+            return Q_HANDLED();
+        }
+        case POINT_SIG: {
+            BSP_insert(((CalcEvt const *)e)->key_code);
+            return Q_TRAN(&Calc_frac2);
+        }
+    }
+    return Q_SUPER(&Calc_operand2);
+}
+/*..........................................................................*/
+QState Calc_frac2(Calc *me, QEvt const *e) {
+    (void)me;               /* avoid compiler warning about unused argument */
+    switch (e->sig) {
+        case Q_ENTRY_SIG: {
+            BSP_message("frac2-ENTRY;");
+            return Q_HANDLED();
+        }
+        case Q_EXIT_SIG: {
+            BSP_message("frac2-EXIT;");
+            return Q_HANDLED();
+        }
+        case DIGIT_0_SIG:                     /* intentionally fall through */
+        case DIGIT_1_9_SIG: {
+            BSP_insert(((CalcEvt const *)e)->key_code);
+            return Q_HANDLED();
+        }
+        case POINT_SIG: {
+            ;                                          /* explicitly ignore */
+            return Q_HANDLED();
+        }
+   }
+    return Q_SUPER(&Calc_operand2);
+}
+/*..........................................................................*/
+QState Calc_final(Calc *me, QEvt const *e) {
+    (void)me;               /* avoid compiler warning about unused argument */
+    switch (e->sig) {
+        case Q_ENTRY_SIG: {
+            BSP_message("final-ENTRY;");
+            BSP_exit();
+            return Q_HANDLED();
+        }
+    }
+    return Q_SUPER(&QHsm_top);
+}
+

+ 58 - 0
examples/80x86/dos/watcom/l/calc/calc.h

@@ -0,0 +1,58 @@
+/*****************************************************************************
+* Product:  Calculator Example
+* Last Updated for Version: 4.5.00
+* Date of the Last Update:  May 18, 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 calc_h
+#define calc_h
+
+enum CalcSignals {
+    C_SIG = Q_USER_SIG,
+    CE_SIG,
+    DIGIT_0_SIG,
+    DIGIT_1_9_SIG,
+    POINT_SIG,
+    OPER_SIG,
+    EQUALS_SIG,
+    OFF_SIG
+};
+
+typedef struct CalcEvtTag {
+    QEvt super;                                    /* derives from QEvt */
+    uint8_t key_code;                                    /* code of the key */
+} CalcEvt;
+
+void Calc_ctor(void);                                /* the calculator ctor */
+
+extern QHsm * const the_calc;         /* "opaque" pointer to calculator HSM */
+
+#endif

+ 1 - 0
examples/80x86/dos/watcom/l/calc/inc_qp.rsp

@@ -0,0 +1 @@
+-i=..\..\..\..\..\..\include -i=..\..\..\..\..\..\ports\80x86\dos\watcom\l

+ 1 - 0
examples/80x86/dos/watcom/l/calc/link_dbg.rsp

@@ -0,0 +1 @@
+Name dbg\calc.exe File dbg\bsp.obj,dbg\main.obj,dbg\calc.obj Library ..\..\..\..\..\..\ports\80x86\dos\watcom\l\dbg\qep.lib

+ 134 - 0
examples/80x86/dos/watcom/l/calc/main.c

@@ -0,0 +1,134 @@
+/*****************************************************************************
+* Product:  Calculator Example
+* Last Updated for Version: 4.5.00
+* Date of the Last Update:  May 18, 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"
+#include "bsp.h"
+#include "calc.h"
+
+#include <stdio.h>
+#include <conio.h>
+#include <dos.h>
+
+/*..........................................................................*/
+int main() {
+    Calc_ctor();            /* explicitly instantiate the calculator object */
+
+    printf("Calculator example, QEP version: %s\n"
+           "Press '0' .. '9'     to enter a digit\n"
+           "Press '.'            to enter the decimal point\n"
+           "Press '+' or '#'     to add\n"
+           "Press '-'            to subtract or negate a number\n"
+           "Press '*'            to multiply\n"
+           "Press '/'            to divide\n"
+           "Press '=' or <Enter> to get the result\n"
+           "Press 'c' or 'C'     to Cancel\n"
+           "Press 'e' or 'E'     to Cancel Entry\n"
+           "Press <Esc>          to quit.\n\n",
+           QEP_getVersion());
+
+    QHsm_init(the_calc, (QEvt *)0);         /* trigger initial transition */
+
+    for (;;) {                                                /* event loop */
+        CalcEvt e;                                      /* Calculator event */
+
+        BSP_display();                                  /* show the display */
+
+        printf(": ");
+        fflush(stdout);
+        e.key_code = (uint8_t)_getche();            /* get a char with echo */
+
+        switch (e.key_code) {
+            case 'c':                         /* intentionally fall through */
+            case 'C': {
+                ((QEvt *)&e)->sig = C_SIG;
+                break;
+            }
+            case 'e':                         /* intentionally fall through */
+            case 'E': {
+                ((QEvt *)&e)->sig = CE_SIG;
+                break;
+            }
+            case '0': {
+                ((QEvt *)&e)->sig = DIGIT_0_SIG;
+                break;
+            }
+            case '1':                         /* intentionally fall through */
+            case '2':                         /* intentionally fall through */
+            case '3':                         /* intentionally fall through */
+            case '4':                         /* intentionally fall through */
+            case '5':                         /* intentionally fall through */
+            case '6':                         /* intentionally fall through */
+            case '7':                         /* intentionally fall through */
+            case '8':                         /* intentionally fall through */
+            case '9': {
+                ((QEvt *)&e)->sig = DIGIT_1_9_SIG;
+                break;
+            }
+            case '.': {
+                ((QEvt *)&e)->sig = POINT_SIG;
+                break;
+            }
+            case '+':                         /* intentionally fall through */
+            case '-':                         /* intentionally fall through */
+            case '*':                         /* intentionally fall through */
+            case '/': {
+                ((QEvt *)&e)->sig = OPER_SIG;
+                break;
+            }
+            case '#': {                                  /* alternative '+' */
+                ((QEvt *)&e)->sig = OPER_SIG;
+                e.key_code = '+';
+                break;
+            }
+            case '=':                         /* intentionally fall through */
+            case '\r': {                                       /* Enter key */
+                ((QEvt *)&e)->sig = EQUALS_SIG;
+                break;
+            }
+            case '\33': {                                        /* ESC key */
+                ((QEvt *)&e)->sig = OFF_SIG;
+                break;
+            }
+            default: {
+                ((QEvt *)&e)->sig = 0;                   /* invalid event */
+                break;
+            }
+        }
+
+        if (((QEvt *)&e)->sig != 0) {           /* valid event generated? */
+            QHsm_dispatch(the_calc, (QEvt *)&e);        /* dispatch event */
+        }
+    }
+    return 0;
+}

+ 61 - 0
examples/80x86/dos/watcom/l/calc/make.bat

@@ -0,0 +1,61 @@
+@echo off
+:: ===========================================================================
+:: Calc example, 80x86, Vanilla port, Open Watcom compiler
+:: Last Updated for Version: 4.1.06
+:: Date of the Last Update:  Jan 06, 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
+:: ===========================================================================
+
+:: If you have defined the WATCOM environment variable, the following line has
+:: no effect and your definition is used. However, if the varible WATCOM is
+:: not defined, the following default is assuemed: 
+if "%WATCOM%"=="" set WATCOM=c:\tools\WATCOM
+
+path %WATCOM%\binw
+set INCLUDE=%WATCOM%\H
+set CC=wcc.exe
+set AS=wasm.exe
+set LD=wlink.exe
+
+echo default selected
+set BINDIR=dbg
+set CCFLAGS=-d2 -ml -3 -fpi87
+set LDFLAGS=@link_dbg.rsp
+
+
+:: compile -------------------------------------------------------------------
+set SRCDIR=.
+set CCINC=@inc_qp.rsp
+
+@echo on
+%CC% %CCFLAGS% %CCINC% -fo=%BINDIR%\bsp.obj      %SRCDIR%\bsp.c
+%CC% %CCFLAGS% %CCINC% -fo=%BINDIR%\main.obj     %SRCDIR%\main.c
+%CC% %CCFLAGS% %CCINC% -fo=%BINDIR%\calc.obj     %SRCDIR%\calc.c
+@echo off
+
+
+:: link ----------------------------------------------------------------------
+@echo on
+%LD% %LDFLAGS%
+@echo off

+ 128 - 0
examples/80x86/dos/watcom/l/calc2/bsp.c

@@ -0,0 +1,128 @@
+/*****************************************************************************
+* Product: BSP for Calculator Example with inheritance of whole state model
+* Last Updated for Version: 4.1.05
+* Date of the Last Update:  Aug 27, 2010
+*
+*                    Q u a n t u m     L e a P s
+*                    ---------------------------
+*                    innovating embedded systems
+*
+* Copyright (C) 2002-2009 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 "bsp.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define DISP_WIDTH  9
+
+static char l_display[DISP_WIDTH + 1];            /* the calculator display */
+static int  l_len;                        /* number of displayed characters */
+
+/*..........................................................................*/
+void BSP_clear(void) {
+    memset(l_display, ' ', DISP_WIDTH - 1);
+    l_display[DISP_WIDTH - 1] = '0';
+    l_display[DISP_WIDTH] = '\0';
+    l_len = 0;
+}
+/*..........................................................................*/
+void BSP_insert(int keyId) {
+    if (l_len == 0) {
+        l_display[DISP_WIDTH - 1] = (char)keyId;
+        ++l_len;
+    }
+    else if (l_len < (DISP_WIDTH - 1)) {
+        memmove(&l_display[0], &l_display[1], DISP_WIDTH - 1);
+        l_display[DISP_WIDTH - 1] = (char)keyId;
+        ++l_len;
+    }
+}
+/*..........................................................................*/
+void BSP_negate(void) {
+    BSP_clear();
+    l_display[DISP_WIDTH - 2] = '-';
+}
+/*..........................................................................*/
+void BSP_display(void) {
+    printf("\n[%s] ", l_display);
+    fflush(stdout);
+}
+/*..........................................................................*/
+void BSP_exit(void) {
+    printf("\nBye! Bye!");
+    _exit(0);
+}
+/*..........................................................................*/
+double BSP_get_value(void) {
+    return strtod(l_display, (char **)0);
+}
+/*..........................................................................*/
+int BSP_eval(double operand1, int oper, double operand2) {
+    int ok = 1;
+    double result;
+    switch (oper) {
+        case KEY_PLUS: {
+            result = operand1 + operand2;
+            break;
+        }
+        case KEY_MINUS: {
+            result = operand1 - operand2;
+            break;
+        }
+        case KEY_MULT: {
+            result = operand1 * operand2;
+            break;
+        }
+        case KEY_DIVIDE: {
+            if ((operand2 < -1e-30) || (1e-30 < operand2)) {
+                result = operand1 / operand2;
+            }
+            else {
+            strcpy(l_display, " Error 0 ");        /* error: divide by zero */
+                ok = 0;
+            }
+            break;
+        }
+    }
+    if (ok) {
+        if ((-0.000001 < result) && (result < 0.000001)) {
+            result = 0.0;
+        }
+        if ((-99999999.0 < result) && (result < 99999999.0)) {
+            sprintf(l_display, "%9.6g", result);
+        }
+        else {
+            strcpy(l_display, " Error 1 ");          /* error: out of range */
+            ok = 0;
+        }
+    }
+    return ok;
+}
+/*..........................................................................*/
+void BSP_message(char const *msg) {
+    printf(msg);
+}
+/*..........................................................................*/
+/* this function is used by the QP embedded systems-friendly assertions */
+void Q_onAssert(char const * const file, int line) {
+    printf("Assertion failed in %s, line %d", file, line);
+    _exit(-1);
+}

+ 46 - 0
examples/80x86/dos/watcom/l/calc2/bsp.h

@@ -0,0 +1,46 @@
+/*****************************************************************************
+* Product: BSP for Calculator Example with inheritance of whole state model
+* Last Updated for Version: 4.0.01
+* Date of the Last Update:  Sep 23, 2008
+*
+*                    Q u a n t u m     L e a P s
+*                    ---------------------------
+*                    innovating embedded systems
+*
+* Copyright (C) 2002-2008 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 bsp_h
+#define bsp_h
+
+#define KEY_PLUS    '+'
+#define KEY_MINUS   '-'
+#define KEY_MULT    '*'
+#define KEY_DIVIDE  '/'
+
+void BSP_clear (void);
+void BSP_negate(void);
+void BSP_insert(int keyId);
+double BSP_get_value(void);
+int  BSP_eval(double operand1, int oper, double operand2);
+void BSP_exit(void);
+
+void BSP_display(void);
+void BSP_message(char const *state);
+
+#endif                                                             /* bsp_h */

+ 510 - 0
examples/80x86/dos/watcom/l/calc2/calc1.c

@@ -0,0 +1,510 @@
+/*****************************************************************************
+* Product: Calculator Example with inheritance of whole state model
+* Last Updated for Version: 4.5.00
+* Date of the Last Update:  May 18, 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"                        /* the port of the QP framework */
+#include "bsp.h"                                   /* board support package */
+#include "calc1.h"
+
+
+/* state variables ---------------------------------------------------------*/
+QStateHandler Calc1_state_on        = (QStateHandler)&Calc1_on;
+QStateHandler Calc1_state_error     = (QStateHandler)&Calc1_error;
+QStateHandler Calc1_state_ready     = (QStateHandler)&Calc1_ready;
+QStateHandler Calc1_state_result    = (QStateHandler)&Calc1_result;
+QStateHandler Calc1_state_begin     = (QStateHandler)&Calc1_begin;
+QStateHandler Calc1_state_negated1  = (QStateHandler)&Calc1_negated1;
+QStateHandler Calc1_state_operand1  = (QStateHandler)&Calc1_operand1;
+QStateHandler Calc1_state_zero1     = (QStateHandler)&Calc1_zero1;
+QStateHandler Calc1_state_int1      = (QStateHandler)&Calc1_int1;
+QStateHandler Calc1_state_frac1     = (QStateHandler)&Calc1_frac1;
+QStateHandler Calc1_state_opEntered = (QStateHandler)&Calc1_opEntered;
+QStateHandler Calc1_state_negated2  = (QStateHandler)&Calc1_negated2;
+QStateHandler Calc1_state_operand2  = (QStateHandler)&Calc1_operand2;
+QStateHandler Calc1_state_zero2     = (QStateHandler)&Calc1_zero2;
+QStateHandler Calc1_state_int2      = (QStateHandler)&Calc1_int2;
+QStateHandler Calc1_state_frac2     = (QStateHandler)&Calc1_frac2;
+QStateHandler Calc1_state_final     = (QStateHandler)&Calc1_final;
+
+
+/*..........................................................................*/
+void Calc1_ctor(Calc1 *me) {                                        /* ctor */
+    QHsm_ctor(&me->super, (QStateHandler)&Calc1_initial);
+}
+
+/* HSM definition ----------------------------------------------------------*/
+QState Calc1_initial(Calc1 *me, QEvt const *e) {
+    (void)e;               /* avoid compiler warning about unused parameter */
+    BSP_clear();
+    return Q_TRAN(Calc1_state_on);
+}
+/*..........................................................................*/
+QState Calc1_on(Calc1 *me, QEvt const *e) {
+    switch (e->sig) {
+        case Q_ENTRY_SIG: {
+            BSP_message("on-ENTRY;");
+            return Q_HANDLED();
+        }
+        case Q_EXIT_SIG: {
+            BSP_message("on-EXIT;");
+            return Q_HANDLED();
+        }
+        case Q_INIT_SIG: {
+            BSP_message("on-INIT;");
+            return Q_TRAN(Calc1_state_ready);
+        }
+        case C_SIG: {
+            BSP_clear();
+            return Q_TRAN(Calc1_state_on);            /* transition-to-self */
+        }
+        case OFF_SIG: {
+            return Q_TRAN(Calc1_state_final);
+        }
+    }
+    return Q_SUPER(&QHsm_top);
+}
+/*..........................................................................*/
+QState Calc1_error(Calc1 *me, QEvt const *e) {
+    switch (e->sig) {
+        case Q_ENTRY_SIG: {
+            BSP_message("error-ENTRY;");
+            return Q_HANDLED();
+        }
+        case Q_EXIT_SIG: {
+            BSP_message("error-EXIT;");
+            return Q_HANDLED();
+        }
+    }
+    return Q_SUPER(Calc1_state_on);
+}
+/*..........................................................................*/
+QState Calc1_ready(Calc1 *me, QEvt const *e) {
+    switch (e->sig) {
+        case Q_ENTRY_SIG: {
+            BSP_message("ready-ENTRY;");
+            return Q_HANDLED();
+        }
+        case Q_EXIT_SIG: {
+            BSP_message("ready-EXIT;");
+            return Q_HANDLED();
+        }
+        case Q_INIT_SIG: {
+            BSP_message("ready-INIT;");
+            return Q_TRAN(Calc1_state_begin);
+        }
+        case DIGIT_0_SIG: {
+            BSP_clear();
+            return Q_TRAN(Calc1_state_zero1);
+        }
+        case DIGIT_1_9_SIG: {
+            BSP_clear();
+            BSP_insert(((CalcEvt const *)e)->key_code);
+            return Q_TRAN(Calc1_state_int1);
+        }
+        case POINT_SIG: {
+            BSP_clear();
+            BSP_insert((int)'0');
+            BSP_insert((int)'.');
+            return Q_TRAN(Calc1_state_frac1);
+        }
+        case OPER_SIG: {
+            me->operand1 = BSP_get_value();
+            me->operator = ((CalcEvt const *)e)->key_code;
+            return Q_TRAN(Calc1_state_opEntered);
+        }
+    }
+    return Q_SUPER(Calc1_state_on);
+}
+/*..........................................................................*/
+QState Calc1_result(Calc1 *me, QEvt const *e) {
+    switch (e->sig) {
+        case Q_ENTRY_SIG: {
+            BSP_message("result-ENTRY;");
+            return Q_HANDLED();
+        }
+        case Q_EXIT_SIG: {
+            BSP_message("result-EXIT;");
+            return Q_HANDLED();
+        }
+    }
+    return Q_SUPER(Calc1_state_ready);
+}
+/*..........................................................................*/
+QState Calc1_begin(Calc1 *me, QEvt const *e) {
+    switch (e->sig) {
+        case Q_ENTRY_SIG: {
+            BSP_message("begin-ENTRY;");
+            return Q_HANDLED();
+        }
+        case Q_EXIT_SIG: {
+            BSP_message("begin-EXIT;");
+            return Q_HANDLED();
+        }
+        case OPER_SIG: {
+            if (((CalcEvt const *)e)->key_code == KEY_MINUS) {
+                return Q_TRAN(Calc1_state_negated1);
+            }
+            break;
+        }
+    }
+    return Q_SUPER(Calc1_state_ready);
+}
+/*..........................................................................*/
+QState Calc1_negated1(Calc1 *me, QEvt const *e) {
+    switch (e->sig) {
+        case Q_ENTRY_SIG: {
+            BSP_message("negated1-ENTRY;");
+            BSP_negate();
+            return Q_HANDLED();
+        }
+        case Q_EXIT_SIG: {
+            BSP_message("negated1-EXIT;");
+            return Q_HANDLED();
+        }
+        case OPER_SIG: {
+            if (((CalcEvt const *)e)->key_code == KEY_MINUS) {
+                ;                                      /* explicitly ignore */
+                return Q_HANDLED();                        /* event handled */
+            }
+            break;
+        }
+        case CE_SIG: {
+            BSP_clear();
+            return Q_TRAN(Calc1_state_begin);
+        }
+        case DIGIT_0_SIG: {
+            BSP_insert(((CalcEvt const *)e)->key_code);
+            return Q_TRAN(Calc1_state_zero1);
+        }
+        case DIGIT_1_9_SIG: {
+            BSP_insert(((CalcEvt const *)e)->key_code);
+            return Q_TRAN(Calc1_state_int1);
+        }
+        case POINT_SIG: {
+            BSP_insert(((CalcEvt const *)e)->key_code);
+            return Q_TRAN(Calc1_state_frac1);
+        }
+    }
+    return Q_SUPER(Calc1_state_on);
+}
+/*..........................................................................*/
+QState Calc1_negated2(Calc1 *me, QEvt const *e) {
+    switch (e->sig) {
+        case Q_ENTRY_SIG: {
+            BSP_message("negated2-ENTRY;");
+            BSP_negate();
+            return Q_HANDLED();
+        }
+        case Q_EXIT_SIG: {
+            BSP_message("negated2-EXIT;");
+            return Q_HANDLED();
+        }
+        case OPER_SIG: {
+            if (((CalcEvt const *)e)->key_code == KEY_MINUS) {
+                ;                                      /* explicitly ignore */
+                return Q_HANDLED();                        /* event handled */
+            }
+            break;
+        }
+        case CE_SIG: {
+            BSP_clear();
+            return Q_TRAN(Calc1_state_opEntered);
+        }
+        case DIGIT_0_SIG: {
+            return Q_TRAN(Calc1_state_zero2);
+        }
+        case DIGIT_1_9_SIG: {
+            BSP_insert(((CalcEvt const *)e)->key_code);
+            return Q_TRAN(Calc1_state_int2);
+        }
+        case POINT_SIG: {
+            BSP_insert(((CalcEvt const *)e)->key_code);
+            return Q_TRAN(Calc1_state_frac2);
+        }
+    }
+    return Q_SUPER(Calc1_state_on);
+}
+/*..........................................................................*/
+QState Calc1_operand1(Calc1 *me, QEvt const *e) {
+    switch (e->sig) {
+        case Q_ENTRY_SIG: {
+            BSP_message("operand1-ENTRY;");
+            return Q_HANDLED();
+        }
+        case Q_EXIT_SIG: {
+            BSP_message("operand1-EXIT;");
+            return Q_HANDLED();
+        }
+        case CE_SIG: {
+            BSP_clear();
+            return Q_TRAN(Calc1_state_begin);
+        }
+        case OPER_SIG: {
+            me->operand1 = BSP_get_value();
+            me->operator = ((CalcEvt const *)e)->key_code;
+            return Q_TRAN(Calc1_state_opEntered);
+        }
+        case EQUALS_SIG: {
+            return Q_TRAN(Calc1_state_result);
+        }
+    }
+    return Q_SUPER(Calc1_state_on);
+}
+/*..........................................................................*/
+QState Calc1_zero1(Calc1 *me, QEvt const *e) {
+    switch (e->sig) {
+        case Q_ENTRY_SIG: {
+            BSP_message("zero1-ENTRY;");
+            return Q_HANDLED();
+        }
+        case Q_EXIT_SIG: {
+            BSP_message("zero1-EXIT;");
+            return Q_HANDLED();
+        }
+        case DIGIT_0_SIG: {
+            ;                                          /* explicitly ignore */
+            return Q_HANDLED();
+        }
+        case DIGIT_1_9_SIG: {
+            BSP_insert(((CalcEvt const *)e)->key_code);
+            return Q_TRAN(Calc1_state_int1);
+        }
+        case POINT_SIG: {
+            BSP_insert(((CalcEvt const *)e)->key_code);
+            return Q_TRAN(Calc1_state_frac1);
+        }
+    }
+    return Q_SUPER(Calc1_state_operand1);
+}
+/*..........................................................................*/
+QState Calc1_int1(Calc1 *me, QEvt const *e) {
+    switch (e->sig) {
+        case Q_ENTRY_SIG: {
+            BSP_message("int1-ENTRY;");
+            return Q_HANDLED();
+        }
+        case Q_EXIT_SIG: {
+            BSP_message("int1-EXIT;");
+            return Q_HANDLED();
+        }
+        case DIGIT_0_SIG:                     /* intentionally fall through */
+        case DIGIT_1_9_SIG: {
+            BSP_insert(((CalcEvt const *)e)->key_code);
+            return Q_HANDLED();
+        }
+        case POINT_SIG: {
+            BSP_insert(((CalcEvt const *)e)->key_code);
+            return Q_TRAN(Calc1_state_frac1);
+        }
+    }
+    return Q_SUPER(Calc1_state_operand1);
+}
+/*..........................................................................*/
+QState Calc1_frac1(Calc1 *me, QEvt const *e) {
+    switch (e->sig) {
+        case Q_ENTRY_SIG: {
+            BSP_message("frac1-ENTRY;");
+            return Q_HANDLED();
+        }
+        case Q_EXIT_SIG: {
+            BSP_message("frac1-EXIT;");
+            return Q_HANDLED();
+        }
+        case DIGIT_0_SIG:                     /* intentionally fall through */
+        case DIGIT_1_9_SIG: {
+            BSP_insert(((CalcEvt const *)e)->key_code);
+            return Q_HANDLED();
+        }
+        case POINT_SIG: {
+            ;                                          /* explicitly ignore */
+            return Q_HANDLED();
+        }
+    }
+    return Q_SUPER(Calc1_state_operand1);
+}
+/*..........................................................................*/
+QState Calc1_opEntered(Calc1 *me, QEvt const *e) {
+    switch (e->sig) {
+        case Q_ENTRY_SIG: {
+            BSP_message("opEntered-ENTRY;");
+            return Q_HANDLED();
+        }
+        case Q_EXIT_SIG: {
+            BSP_message("opEntered-EXIT;");
+            return Q_HANDLED();
+        }
+        case OPER_SIG: {
+            if (((CalcEvt const *)e)->key_code == KEY_MINUS) {
+                BSP_clear();
+                return Q_TRAN(Calc1_state_negated2);
+            }
+            break;
+        }
+        case DIGIT_0_SIG: {
+            BSP_clear();
+            return Q_TRAN(Calc1_state_zero2);
+        }
+        case DIGIT_1_9_SIG: {
+            BSP_clear();
+            BSP_insert(((CalcEvt const *)e)->key_code);
+            return Q_TRAN(Calc1_state_int2);
+        }
+        case POINT_SIG: {
+            BSP_clear();
+            BSP_insert((int)'0');
+            BSP_insert((int)'.');
+            return Q_TRAN(Calc1_state_frac2);
+        }
+    }
+    return Q_SUPER(Calc1_state_on);
+}
+/*..........................................................................*/
+QState Calc1_operand2(Calc1 *me, QEvt const *e) {
+    switch (e->sig) {
+        case Q_ENTRY_SIG: {
+            BSP_message("operand2-ENTRY;");
+            return Q_HANDLED();
+        }
+        case Q_EXIT_SIG: {
+            BSP_message("operand2-EXIT;");
+            return Q_HANDLED();
+        }
+        case CE_SIG: {
+            BSP_clear();
+            return Q_TRAN(Calc1_state_opEntered);
+        }
+        case OPER_SIG: {
+            if (BSP_eval(me->operand1, me->operator, BSP_get_value())) {
+                me->operand1 = BSP_get_value();
+                me->operator = ((CalcEvt const *)e)->key_code;
+                return Q_TRAN(Calc1_state_opEntered);
+            }
+            else {
+                return Q_TRAN(Calc1_state_error);
+            }
+        }
+        case EQUALS_SIG: {
+            if (BSP_eval(me->operand1, me->operator, BSP_get_value())) {
+                return Q_TRAN(Calc1_state_result);
+            }
+            else {
+                return Q_TRAN(Calc1_state_error);
+            }
+        }
+    }
+    return Q_SUPER(Calc1_state_on);
+}
+/*..........................................................................*/
+QState Calc1_zero2(Calc1 *me, QEvt const *e) {
+    switch (e->sig) {
+        case Q_ENTRY_SIG: {
+            BSP_message("zero2-ENTRY;");
+            return Q_HANDLED();
+        }
+        case Q_EXIT_SIG: {
+            BSP_message("zero2-EXIT;");
+            return Q_HANDLED();
+        }
+        case DIGIT_0_SIG: {
+            ;                                          /* explicitly ignore */
+            return Q_HANDLED();
+        }
+        case DIGIT_1_9_SIG: {
+            BSP_insert(((CalcEvt const *)e)->key_code);
+            return Q_TRAN(Calc1_state_int2);
+        }
+        case POINT_SIG: {
+            BSP_insert(((CalcEvt const *)e)->key_code);
+            return Q_TRAN(Calc1_state_frac2);
+        }
+    }
+    return Q_SUPER(Calc1_state_operand2);
+}
+/*..........................................................................*/
+QState Calc1_int2(Calc1 *me, QEvt const *e) {
+    switch (e->sig) {
+        case Q_ENTRY_SIG: {
+            BSP_message("int2-ENTRY;");
+            return Q_HANDLED();
+        }
+        case Q_EXIT_SIG: {
+            BSP_message("int2-EXIT;");
+            return Q_HANDLED();
+        }
+        case DIGIT_0_SIG:                     /* intentionally fall through */
+        case DIGIT_1_9_SIG: {
+            BSP_insert(((CalcEvt const *)e)->key_code);
+            return Q_HANDLED();
+        }
+        case POINT_SIG: {
+            BSP_insert(((CalcEvt const *)e)->key_code);
+            return Q_TRAN(Calc1_state_frac2);
+        }
+    }
+    return Q_SUPER(Calc1_state_operand2);
+}
+/*..........................................................................*/
+QState Calc1_frac2(Calc1 *me, QEvt const *e) {
+    switch (e->sig) {
+        case Q_ENTRY_SIG: {
+            BSP_message("frac2-ENTRY;");
+            return Q_HANDLED();
+        }
+        case Q_EXIT_SIG: {
+            BSP_message("frac2-EXIT;");
+            return Q_HANDLED();
+        }
+        case DIGIT_0_SIG:                     /* intentionally fall through */
+        case DIGIT_1_9_SIG: {
+            BSP_insert(((CalcEvt const *)e)->key_code);
+            return Q_HANDLED();
+        }
+        case POINT_SIG: {
+            ;                                          /* explicitly ignore */
+            return Q_HANDLED();
+        }
+   }
+    return Q_SUPER(Calc1_state_operand2);
+}
+/*..........................................................................*/
+QState Calc1_final(Calc1 *me, QEvt const *e) {
+    switch (e->sig) {
+        case Q_ENTRY_SIG: {
+            BSP_message("final-ENTRY;");
+            BSP_exit();
+            return Q_HANDLED();
+        }
+    }
+    return Q_SUPER(&QHsm_top);
+}
+

+ 103 - 0
examples/80x86/dos/watcom/l/calc2/calc1.h

@@ -0,0 +1,103 @@
+/*****************************************************************************
+* Product: Calculator Example with inheritance of whole state model
+* Last Updated for Version: 4.5.00
+* Date of the Last Update:  May 18, 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 calc1_h
+#define calc1_h
+
+enum Calc1Signals {
+    C_SIG = Q_USER_SIG,
+    CE_SIG,
+    DIGIT_0_SIG,
+    DIGIT_1_9_SIG,
+    POINT_SIG,
+    OPER_SIG,
+    EQUALS_SIG,
+    OFF_SIG,
+
+    MAX_CALC1_SIG
+};
+
+typedef struct CalcEvtTag {
+    QEvt  super;                                    /* derive from QEvt */
+    uint8_t key_code;                                    /* code of the key */
+} CalcEvt;
+
+
+// Calculator HSM class for inheritance ------------------------------------*/
+typedef struct Calc1Tag {
+    QHsm    super;                                      /* derive from QHsm */
+    double  operand1;                             /* the value of operand 1 */
+    uint8_t operator;                               /* operator key entered */
+} Calc1;
+
+void   Calc1_ctor   (Calc1 *me);                                    /* ctor */
+QState Calc1_initial(Calc1 *me, QEvt const *e);    /* initial pseudostate */
+
+QState Calc1_on       (Calc1 *me, QEvt const *e);
+QState Calc1_error    (Calc1 *me, QEvt const *e);
+QState Calc1_ready    (Calc1 *me, QEvt const *e);
+QState Calc1_result   (Calc1 *me, QEvt const *e);
+QState Calc1_begin    (Calc1 *me, QEvt const *e);
+QState Calc1_negated1 (Calc1 *me, QEvt const *e);
+QState Calc1_operand1 (Calc1 *me, QEvt const *e);
+QState Calc1_zero1    (Calc1 *me, QEvt const *e);
+QState Calc1_int1     (Calc1 *me, QEvt const *e);
+QState Calc1_frac1    (Calc1 *me, QEvt const *e);
+QState Calc1_opEntered(Calc1 *me, QEvt const *e);
+QState Calc1_negated2 (Calc1 *me, QEvt const *e);
+QState Calc1_operand2 (Calc1 *me, QEvt const *e);
+QState Calc1_zero2    (Calc1 *me, QEvt const *e);
+QState Calc1_int2     (Calc1 *me, QEvt const *e);
+QState Calc1_frac2    (Calc1 *me, QEvt const *e);
+QState Calc1_final    (Calc1 *me, QEvt const *e);
+
+extern QStateHandler  Calc1_state_on;
+extern QStateHandler  Calc1_state_error;
+extern QStateHandler  Calc1_state_ready;
+extern QStateHandler  Calc1_state_result;
+extern QStateHandler  Calc1_state_begin;
+extern QStateHandler  Calc1_state_negated1;
+extern QStateHandler  Calc1_state_operand1;
+extern QStateHandler  Calc1_state_zero1;
+extern QStateHandler  Calc1_state_int1;
+extern QStateHandler  Calc1_state_frac1;
+extern QStateHandler  Calc1_state_opEntered;
+extern QStateHandler  Calc1_state_negated2;
+extern QStateHandler  Calc1_state_operand2;
+extern QStateHandler  Calc1_state_zero2;
+extern QStateHandler  Calc1_state_int2;
+extern QStateHandler  Calc1_state_frac2;
+extern QStateHandler  Calc1_state_final;
+
+#endif                                                           /* calc1_h */

+ 1 - 0
examples/80x86/dos/watcom/l/calc2/calc1.rsp

@@ -0,0 +1 @@
+Name dbg\calc1.exe File dbg\bsp.obj,dbg\main1.obj,dbg\calc1.obj Library ..\..\..\..\..\..\ports\80x86\dos\watcom\l\dbg\qep.lib

+ 82 - 0
examples/80x86/dos/watcom/l/calc2/calc2.c

@@ -0,0 +1,82 @@
+/*****************************************************************************
+* Product: Calculator Example with inheritance of whole state model
+* Last Updated for Version: 4.5.00
+* Date of the Last Update:  May 18, 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"
+#include "bsp.h"                                   /* board support package */
+#include "calc2.h"
+
+#include <stdlib.h>
+
+Q_DEFINE_THIS_FILE
+
+/* state variables ---------------------------------------------------------*/
+QStateHandler Calc2_state_operand2 = (QStateHandler)&Calc2_operand2;
+
+/* Ctor definition ---------------------------------------------------------*/
+void Calc2_ctor(Calc2 *me) {                                        /* ctor */
+    Calc1_ctor(&me->super);                   /* instantiate the superclass */
+                                      /* subsitute all overridden states... */
+    Calc1_state_operand2 = Calc2_state_operand2;
+}
+/*..........................................................................*/
+QState Calc2_operand2(Calc2 *me, QEvt const *e) {
+    switch (e->sig) {
+        case PERCENT_SIG: {
+            double operand2 = BSP_get_value();
+            switch (me->super.operator) {
+                case KEY_PLUS:
+                case KEY_MINUS: {
+                    operand2 = me->super.operand1 * operand2 / 100.0;
+                    break;
+                }
+                case KEY_MULT:
+                case KEY_DIVIDE: {
+                    operand2 /= 100.0;
+                    break;
+                }
+                default: {
+                    Q_ERROR();
+                    break;
+                }
+            }
+            if (BSP_eval(me->super.operand1, me->super.operator, operand2)) {
+                return Q_TRAN(Calc1_state_result);
+            }
+            else {
+                return Q_TRAN(Calc1_state_error);
+            }
+        }
+    }
+    return Q_SUPER(&Calc1_operand2);       /* let Calc1 handle other events */
+}

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است