Difference between revisions of "QL"

From emboxit
Jump to: navigation, search
 
 
(One intermediate revision by the same user not shown)
Line 598: Line 598:
 
<br><br><br><br>
 
<br><br><br><br>
 
[[Category:All]]
 
[[Category:All]]
 +
[[Category:UML]]
 +
[[Category:QL]]

Latest revision as of 20:11, 5 November 2017

Link to start

  • Practical UML Statecharts in C/C++, Second Edition: Event-Driven Programming for Embedded Systems best link to start




Qp nano2.PNG Qp2.PNG Qp sheduler2.PNG File:Qp sketch3.png

Quantum Leap QL UML statecharts



Ultimate Hook

  • CHAPTER 5: State Patterns pdf-page 218
  • The minimal example 152 lines single source file
  • Build with openWatcom make.bat successfully for DOS [2011.08.16]
int main() {
    printf("Ultimate Hook pattern\nQEP version: %s\n"
           "Press 'a'..'c' to inject signals A..C\n"
           "Press 'd' or ESC to inject signal D and quit\n",
           QEP::getVersion());

    l_test.init(); // trigger the initial transition before dispatching events

    for (;;) {
        printf("\n");
        uint8_t c;
        c = (uint8_t)getch();           // read one character from the console
        printf("%c: ", c);

        QEvent e;
        switch (c) {
            case 'a':  e.sig = A_SIG;  break;
            case 'b':  e.sig = B_SIG;  break;
            case 'c':  e.sig = C_SIG;  break;
            case 'd':
            case 0x1B: e.sig = D_SIG;  break;                     // terminate
        }
        l_test.dispatch(&e);      // dispatch the event into the state machine
    }
    return 0;
}



Transition to history

  • CHAPTER 5: State Patterns
  • PDF Page 258 simple toaster oven, is simple and easy to understand
  • Project consists of only one file to make (Watcom)
  • make.bat run successfully and build the .exe [2011.08.16]

History-chart.PNG

  • Seems to be the easiest example.
But is used only for the State Patterns chapter...
Not available for every CPU
Go for Pelican example.






Pelican example from Book to eZ430-F2013

Practical UML Statecharts book companion home

Download all-book-examples and place the folder-tree near to root. DO-NOT move the project folders away otherwise can not be build by IAR tool
.
PELICAN 2.jpg PELICAN 3.jpg
.
  The (not easy to find) PATH of the project:                                                                                     Source code in 5 files
PELICAN 1.jpg PELICAN 4.jpg
.
For the chapter-12, MSP430 Pelican example download IAR kickstart MSP430 Here
IAR tool can not save a debug related file, but can build the project
Again IAR debug mentions an error, but downloads and controls debug-flow as expected.
The only available LED on eZ430-F2013 is active, ...seems like Pelican!

  • TODO:
IAR is fast, So do what the yellow letters say:
Create the second state diagram:
I leave it as an exercise for you to draw the state diagram of the Pedestrian state machine 
from the source code found in the file <qp>\qpn\examples\msp430\iar\pelican-eZ430\ped.c.



Lets do it

ped.c

*****************************************************************************/
#include "qpn_port.h"
#include "bsp.h"
#include "pelican.h"

/*--------------------------------------------------------------------------*/
typedef struct PedTag {                         /* Pedestrian active object */
    QActive super;                                  /* derived from QActive */
    uint8_t retryCtr;
} Ped;

static QState Ped_initial(Ped *me);          /* initial pseudostate-handler */
static QState Ped_wait   (Ped *me);
static QState Ped_off    (Ped *me);

enum PedTimeouts {                             /* various timeouts in ticks */
    N_ATTEMPTS = 10,                      /* number of PED_WAITING attempts */
    WAIT_TOUT = BSP_TICKS_PER_SEC * 3,  /* wait between posting PED_WAITING */
    OFF_TOUT  = BSP_TICKS_PER_SEC * 8    /* wait time after posting OFF_SIG */
};

/* Global objects ----------------------------------------------------------*/
Ped AO_Ped;                 /* the single instance of the Ped active object */

/*..........................................................................*/
void Ped_ctor(void) {
    QActive_ctor((QActive *)&AO_Ped, (QStateHandler)&Ped_initial);
}

/* HSM definition ----------------------------------------------------------*/
QState Ped_initial(Ped *me) {
    return Q_TRAN(&Ped_wait);//------NX--------------------Initial state is 'Ped_wait'
}
/*..........................................................................*/
QState Ped_wait(Ped *me) {
    switch (Q_SIG(me)) {
        case Q_ENTRY_SIG: {
            BSP_showState(me->super.prio, "wait");
            me->retryCtr = N_ATTEMPTS;
            QActive_arm((QActive *)me, WAIT_TOUT);
            return Q_HANDLED();
        }
        case Q_TIMEOUT_SIG: {
            if ((--me->retryCtr) != 0) {
                QActive_arm((QActive *)me, WAIT_TOUT);
                QActive_post((QActive *)&AO_Pelican, PEDS_WAITING_SIG);
            }
            else {
                return Q_TRAN(&Ped_off);
            }
            return Q_HANDLED();
        }
    }
    return Q_SUPER(&QHsm_top); //------NX------------------The Higher level STATE, in this case, return to TOP
}
/*..........................................................................*/
QState Ped_off(Ped *me) {
    switch (Q_SIG(me)) {
        case Q_ENTRY_SIG: {
            BSP_showState(me->super.prio, "off");
            QActive_arm((QActive *)me, OFF_TOUT);
            QActive_post((QActive *)&AO_Pelican, OFF_SIG);
            return Q_HANDLED();
        }
        case Q_TIMEOUT_SIG: {
            QActive_post((QActive *)&AO_Pelican, ON_SIG);
            return Q_TRAN(&Ped_wait);
        }
    }
    return Q_SUPER(&QHsm_top); //------NX------------------The Higher level STATE, in this case, return to TOP
}



pelican.c

*****************************************************************************/
#include "qpn_port.h"
#include "bsp.h"
#include "pelican.h"

/* Pelican class -----------------------------------------------------------*/
typedef struct PelicanTag {
    QActive super;                                  /* derived from QActive */
    uint8_t flashCtr;                           /* pedestrian flash counter */
} Pelican;

static QState Pelican_initial         (Pelican *me);
static QState Pelican_offline         (Pelican *me);
static QState Pelican_operational     (Pelican *me);
static QState Pelican_carsEnabled     (Pelican *me);
static QState Pelican_carsGreen       (Pelican *me);
static QState Pelican_carsGreenNoPed  (Pelican *me);
static QState Pelican_carsGreenPedWait(Pelican *me);
static QState Pelican_carsGreenInt    (Pelican *me);
static QState Pelican_carsYellow      (Pelican *me);
static QState Pelican_pedsEnabled     (Pelican *me);
static QState Pelican_pedsWalk        (Pelican *me);
static QState Pelican_pedsFlash       (Pelican *me);

enum PelicanTimeouts {                         /* various timeouts in ticks */
    CARS_GREEN_MIN_TOUT = BSP_TICKS_PER_SEC * 8,      /* min green for cars */
    CARS_YELLOW_TOUT = BSP_TICKS_PER_SEC * 3,            /* yellow for cars */
    PEDS_WALK_TOUT   = BSP_TICKS_PER_SEC * 3,      /* walking time for peds */
    PEDS_FLASH_TOUT  = BSP_TICKS_PER_SEC / 5,  /* flashing timeout for peds */
    PEDS_FLASH_NUM   = 5*2,                   /* number of flashes for peds */
    OFF_FLASH_TOUT   = BSP_TICKS_PER_SEC / 2   /* flashing timeout when off */
};

/* Global objects ----------------------------------------------------------*/
Pelican AO_Pelican;     /* the single instance of the Pelican active object */

/*..........................................................................*/
void Pelican_ctor(void) {
    QActive_ctor((QActive *)&AO_Pelican, (QStateHandler)&Pelican_initial);
}

/* HSM definition ----------------------------------------------------------*/
QState Pelican_initial(Pelican *me) {
    return Q_TRAN(&Pelican_operational);
}
/*..........................................................................*/
QState Pelican_operational(Pelican *me) {
    switch (Q_SIG(me)) {
        case Q_ENTRY_SIG: {
            BSP_signalCars(CARS_RED);
            BSP_signalPeds(PEDS_DONT_WALK);
            return Q_HANDLED();
        }
        case Q_INIT_SIG: {
            return Q_TRAN(&Pelican_carsEnabled);
        }
        case OFF_SIG: {
            return Q_TRAN(&Pelican_offline);
        }
    }
    return Q_SUPER(&QHsm_top);
}
/*..........................................................................*/
QState Pelican_carsEnabled(Pelican *me) {
    switch (Q_SIG(me)) {
        case Q_EXIT_SIG: {
            BSP_signalCars(CARS_RED);
            return Q_HANDLED();
        }
        case Q_INIT_SIG: {
            return Q_TRAN(&Pelican_carsGreen);
        }
    }
    return Q_SUPER(&Pelican_operational); //NX------------------The Higher level STATE
}
/*..........................................................................*/
QState Pelican_carsGreen(Pelican *me) {
    switch (Q_SIG(me)) {
        case Q_ENTRY_SIG: {
            QActive_arm((QActive *)me, CARS_GREEN_MIN_TOUT);
            BSP_signalCars(CARS_GREEN);
            return Q_HANDLED();
        }
        case Q_INIT_SIG: {
            return Q_TRAN(&Pelican_carsGreenNoPed);
        }
    }
    return Q_SUPER(&Pelican_carsEnabled); //NX------------------The Higher level STATE
}
/*..........................................................................*/
QState Pelican_carsGreenNoPed(Pelican *me) {
    switch (Q_SIG(me)) {
        case Q_ENTRY_SIG: {
            BSP_showState(me->super.prio, "carsGreenNoPed");
            return Q_HANDLED();
        }
        case PEDS_WAITING_SIG: {
            return Q_TRAN(&Pelican_carsGreenPedWait);
        }
        case Q_TIMEOUT_SIG: {
            return Q_TRAN(&Pelican_carsGreenInt);
        }
    }
    return Q_SUPER(&Pelican_carsGreen); //NX------------------The Higher level STATE
}
/*..........................................................................*/
QState Pelican_carsGreenPedWait(Pelican *me) {
    switch (Q_SIG(me)) {
        case Q_ENTRY_SIG: {
            BSP_showState(me->super.prio, "carsGreenPedWait");
            return Q_HANDLED();
        }
        case Q_TIMEOUT_SIG: {
            return Q_TRAN(&Pelican_carsYellow);
        }
    }
    return Q_SUPER(&Pelican_carsGreen); //NX------------------The Higher level STATE
}
/*..........................................................................*/
QState Pelican_carsGreenInt(Pelican *me) {
    switch (Q_SIG(me)) {
        case Q_ENTRY_SIG: {
            BSP_showState(me->super.prio, "carsGreenInt");
            return Q_HANDLED();
        }
        case PEDS_WAITING_SIG: {
            return Q_TRAN(&Pelican_carsYellow);
        }
    }
    return Q_SUPER(&Pelican_carsGreen); //NX------------------The Higher level STATE
}
/*..........................................................................*/
QState Pelican_carsYellow(Pelican *me) {
    switch (Q_SIG(me)) {
        case Q_ENTRY_SIG: {
            BSP_showState(me->super.prio, "carsYellow");
            QActive_arm((QActive *)me, CARS_YELLOW_TOUT);
            BSP_signalCars(CARS_YELLOW);
            return Q_HANDLED();
        }
        case Q_TIMEOUT_SIG: {
            return Q_TRAN(&Pelican_pedsEnabled);
        }
    }
    return Q_SUPER(&Pelican_carsEnabled); //NX------------------The Higher level STATE
}
/*..........................................................................*/
QState Pelican_pedsEnabled(Pelican *me) {
    switch (Q_SIG(me)) {
        case Q_EXIT_SIG: {
            BSP_signalPeds(PEDS_DONT_WALK);
            return Q_HANDLED();
        }
        case Q_INIT_SIG: {
            return Q_TRAN(&Pelican_pedsWalk);
        }
    }
    return Q_SUPER(&Pelican_operational); //NX------------------The Higher level STATE
}
/*..........................................................................*/
QState Pelican_pedsWalk(Pelican *me) {
    switch (Q_SIG(me)) {
        case Q_ENTRY_SIG: {
            BSP_showState(me->super.prio, "pedsWalk");
            QActive_arm((QActive *)me, PEDS_WALK_TOUT);
            BSP_signalPeds(PEDS_WALK);
            return Q_HANDLED();
        }
        case Q_TIMEOUT_SIG: {
            return Q_TRAN(&Pelican_pedsFlash);
        }
    }
    return Q_SUPER(&Pelican_pedsEnabled); //NX------------------The Higher level STATE
}
/*..........................................................................*/
QState Pelican_pedsFlash(Pelican *me) {
    switch (Q_SIG(me)) {
        case Q_ENTRY_SIG: {
            BSP_showState(me->super.prio, "pedsWalk");
            QActive_arm((QActive *)me, PEDS_FLASH_TOUT);
            me->flashCtr = PEDS_FLASH_NUM*2 + 1;
            return Q_HANDLED();
        }
        case Q_TIMEOUT_SIG: {
            if (me->flashCtr != 0) {                     /* still flashing? */
                if ((me->flashCtr & 1) == 0) {             /* even counter? */
                    BSP_signalPeds(PEDS_DONT_WALK);
                }
                else {                               /* must be odd counter */
                    BSP_signalPeds(PEDS_BLANK);
                }
                --me->flashCtr;
                QActive_arm((QActive *)me, PEDS_FLASH_TOUT);
            }
            else {                                         /* done flashing */
                return Q_TRAN(&Pelican_carsEnabled);
            }
            return Q_HANDLED();
        }
    }
    return Q_SUPER(&Pelican_pedsEnabled);
}
/*..........................................................................*/
QState Pelican_offline(Pelican *me) {
    switch (Q_SIG(me)) {
        case Q_ENTRY_SIG: {
            BSP_showState(me->super.prio, "offline");
            QActive_arm((QActive *)me, OFF_FLASH_TOUT);
            me->flashCtr = 0;
            return Q_HANDLED();
        }
        case Q_TIMEOUT_SIG: {
            QActive_arm((QActive *)me, OFF_FLASH_TOUT);
            if ((me->flashCtr & 1) == 0) {                 /* even counter? */
                BSP_signalCars(CARS_RED);
                BSP_signalPeds(PEDS_DONT_WALK);
            }
            else {
                BSP_signalCars(CARS_OFF);
                BSP_signalPeds(PEDS_BLANK);
            }
            me->flashCtr ^= 1;                  /* toggle the flash counter */
            return Q_HANDLED();
        }
        case ON_SIG: {
            return Q_TRAN(&Pelican_operational);
        }
    }
    return Q_SUPER(&QHsm_top);
}





QM graphical UML modeling tool

QM graphical UML modeling tool home

View the 6 tutorials
Quick overview of the QM™ user interface
Creating a new model
Working with classes
Working with state machines
Generating code
Working with third-party tools
Change MODEL -->create code-->build with compiler IDE-->Download and debug
DO NOT change code with compiler IDE,
Change the MODEL
It is like Schematic-PCB relation
QM1.jpg




QP™ Development Kits (QDKs) for Arduino™

tested 2011.07.22.22:05

  • qp_pelican worked as expected
  • qm_pelican generates 4 files (.cpp and .h) but not a sketch (.pde)
  • By copying the qp_pelican.pde to qm_pelican it works BUT can not save the project, the 4 files are read-only
  • TODO: check in the pdf the .pde structure. Is very simple, can be written by hand, not needed the QM for this. The other files are big and created by QM
  • It seems that the bootloader inside Arduino is erased after every download??? It needs to download again with AVR_studio4 programmer from ISP

The structure of an Arduino sketch for QP

  • Sketch = a group of files
  • Main sketch file is the .pde
  • Other files .cpp .h
  • Sketch consists of 4 groups:
setup
events
active objects
BSP
  • setup function in the .pde
  • events are shared, so defined in the .h
  • active-objects: one active object per .cpp

The structure of [.pde] setup() function

#include "qp_port.h"
#include "dpp.h"
#include "bsp.h"

// Local-scope objects -------------------------------------------------------
static QEvent const *l_tableQueueSto[N_PHILO];
static QEvent const *l_philoQueueSto[N_PHILO][N_PHILO];
static QSubscrList   l_subscrSto[MAX_PUB_SIG];

static TableEvt l_smlPoolSto[2*N_PHILO];   // storage for the small event pool

//............................................................................
void setup() {
   BSP_init();                                          // initialize the BSP

   QF::init();       // initialize the framework and the underlying RT kernel

                                                  // initialize event pools...
   QF::poolInit(l_smlPoolSto, sizeof(l_smlPoolSto), sizeof(l_smlPoolSto[0]));

   QF::psInit(l_subscrSto, Q_DIM(l_subscrSto));     // init publish-subscribe

                                               // start the active objects...
   uint8_t n;
   for (n = 0; n < N_PHILO; ++n) {
       AO_Philo[n]->start((uint8_t)(n + 1),
                          l_philoQueueSto[n], Q_DIM(l_philoQueueSto[n]));
   }
   AO_Table->start((uint8_t)(N_PHILO + 1),
                   l_tableQueueSto, Q_DIM(l_tableQueueSto));
}
  • include
  • storage allocation for
event-qeues
publish-subscribe
framework-event-pools
  • setup()
initialize
BSP
Framework and RT-kernel
Event-Pools
Publish-Subscribe,
Start the active objects

The structure of [.h] application events and signals

#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 from hungry Philosopher to Table
  MAX_SIG                                                  // the last signal
};

struct TableEvt : public QEvent {
   uint8_t philoNum;                                    // philosopher number
};

enum { N_PHILO = 5 };                                // number of philosophers

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
  • All signals in a single enumeration
  • Expand classes [To check this...]
  • "opaque" pointers to active objects

HOTO start

HERE Arduino

read this first: Application note in pdf explains everything
   The PELICAN crossing example for QM™ (located in <qp_arduino.zip>/examples/qp/
  qm_pelican/, see Listing 3) takes Arduino programming to the next level. Instead of coding the state
  machines by hand, you draw them with the free QM™ modeling tool, attach simple action code to states
  and transitions, and you generate the complete Arduino sketch automatically—literally by a press of a
  button
   Modifying the Examples to Reduce Power Consumption
  As mentioned in Section 1.2, the QP/C++ framework allows you to take advantage of the Arduino
  processor's low-power sleep mode, which is the only way to achieve really low-power design. Both
  provided examples can be very easily modified to switch to the sleep mode when no events are available.
  In fact, the code is already provided for you, so all you need to do is just to enable this code. As shown in
  Figure 12, you select the file bsp.cpp (Board Support Package) and uncomment the definition of the
  SAVE_POWER macro.
   After you recompile the code and download to Arduino, you will see that the User LED is no longer
  glowing. Actually, it is glowing, but only for a few microseconds out of every 10 milliseconds, so you
  cannot see it. This very low brightness of the User LED means that the Arduino Background loop uses
  very little power, yet the application performs exactly as before! The upcoming Section 4.1 explains what
  exactly happens when you define the macro SAVE_POWER in bsp.cpp.



ALL Tool and Development-Kits Downloads

NOTE: Each QDK™ contains only the software dependent on the particular processor, operating system, or the compiler, but does NOT contain the portable QP™ Baseline Code. 
In  other words, you need to install the QP baseline code, before you install any port 





Articles / Books




HAREL

It is the basis of UML-Statecharts
  • D. Harel and M. Politi, Modeling Reactive Systems with Statecharts: The STATEMATE Approach, (with M. Politi), McGraw-Hill, 1998.
Book free downoload from weizmann institute
STATEMATE now belongs to IBM
RHAPSODY(IBM) is gaining the market, while STATEMATE not




UML

UML diagrams represent two different views of a system model:[11]
   Static (or structural) view: 
      emphasizes the static structure of the system using objects, attributes, operations  and relationships. 
      The structural view includes: 
          class diagrams and composite structure diagrams.
   Dynamic (or behavioral) view: 
      emphasizes the dynamic behavior of the system 
      by showing collaborations among  objects and changes to the internal states of objects. 
      This view includes sequence diagrams, activity diagrams and state machine diagrams.


The UML notation and semantics are really geared toward computerized UML tools. 
A UML state machine, as represented  in a tool, is not just the state diagram, 
but rather a mixture of graphical and textual representation that precisely 
captures both the state topology and the actions. 
The users of the tool can get several complementary views of the same state machine, 
both visual and textual, whereas the generated code is just one of the many available views.