PEdestrian LIghto CONtrolled (PELICA) crossing for Qt with GUI Starts execution of an active object and registers the object with the framework. This function is strongly OS-dependent and must be defined in the QP port to a particular platform. The function takes six arguments: 'prio' is the priority of the active object. QP allows you to start up to 63 active objects, each one having a *unique* priority number between 1 and 63 inclusive, where higher numerical values correspond to higher priority (urgency) of the active object relative to the others. 'qSto[]' and 'qLen' arguments are the storage and size of the event queue used by this active object. 'stkSto' and 'stkSize' are the stack storage and size in bytes. Please note that a per-active object stack is used only when the underlying OS requies it. If the stack is not required, or the underlying OS allocates the stack internally, the stkSto should be NULL and/or stkSize should be 0. 'ie' is an optional initialization event that can be used to pass additional startup data to the active object. (Pass NULL if your active object does not expect the initialization event). // Example: static Table l_table; // Table active object instance static QEvt const *l_tableQueueSto[N]; // storage for Table queue static int l_tableStk[256]; // storage for the stack for Table AO . . . int main() { TableEvt ie; // initialization event for the Table AO . . . ie.philNum = n; // build the initialization event . . . l_table.start( 6, // unique priority (1..QF_MAX_ACTIVE) l_tableQueueSto, // event queue of the active object Q_DIM(l_tableQueueSto),// the depth of the event queue l_tableStk, // the stack of the acitve object (optional) sizeof(l_tableStk), // the size of the stack in bytes (optional) &ie); // initialization event (optional) . . . } Posts an event e directly to the event queue of the acitve object this using the First-In-First-Out (FIFO) policy. Direct event posting is the simplest asynchronous communication method available in QP. NOTE: Direct event posting should not be confused with direct event dispatching. In contrast to asynchronous event posting through event queues, direct event dispatching is synchronous. Direct event dispatching occurs when you call QHsm::dispatch() or QFsm::dispatch() function. // Example: extern QActive *AO_Table; . . . pe = Q_NEW(TableEvt, HUNGRY_SIG); // dynamically allocate event pe->philNum = num; AO_Table->postFIFO(pe); // <== Posts an event e directly to the event queue of the acitve object this using the Last-In-First-Out (LIFO) policy. Direct event posting is the simplest asynchronous communication method available in QP. NOTE: You should be very careful with the LIFO (Last In First Out) policy, because it *reverses* the order of events in the queue. Typically, the QActive_postLIFO() operation shuould be only used for self-posting of events as reminders (see the "Reminder" state pattern) for continuing a processing. The postLIFO() operation is also used in the QActive::recall() operation. NOTE: Direct event posting should not be confused with direct event dispatching. In contrast to asynchronous event posting through event queues, direct event dispatching is synchronous. Direct event dispatching occurs when you call QHsm::dispatch() or QFsm::dispatch() function. // Example: . . . pe = Q_NEW(TableEvt, HUNGRY_SIG); // dynamically allocate event pe->philNum = num; . . . postLIFO(pe); // <== Starts execution of an active object and registers the object with the framework. This function is strongly OS-dependent and must be defined in the QP port to a particular platform. The function takes six arguments: 'prio' is the priority of the active object. QP allows you to start up to 63 active objects, each one having a *unique* priority number between 1 and 63 inclusive, where higher numerical values correspond to higher priority (urgency) of the active object relative to the others. 'qSto[]' and 'qLen' arguments are the storage and size of the event queue used by this active object. 'stkSto' and 'stkSize' are the stack storage and size in bytes. Please note that a per-active object stack is used only when the underlying OS requies it. If the stack is not required, or the underlying OS allocates the stack internally, the stkSto should be NULL and/or stkSize should be 0. 'ie' is an optional initialization event that can be used to pass additional startup data to the active object. (Pass NULL if your active object does not expect the initialization event). // Example: static Table l_table; // Table active object instance static QEvt const *l_tableQueueSto[N]; // storage for Table queue static int l_tableStk[256]; // storage for the stack for Table AO . . . int main() { TableEvt ie; // initialization event for the Table AO . . . ie.philNum = n; // build the initialization event . . . l_table.start( 6, // unique priority (1..QF_MAX_ACTIVE) l_tableQueueSto, // event queue of the active object Q_DIM(l_tableQueueSto),// the depth of the event queue l_tableStk, // the stack of the acitve object (optional) sizeof(l_tableStk), // the size of the stack in bytes (optional) &ie); // initialization event (optional) . . . } Posts an event e directly to the event queue of the acitve object this using the First-In-First-Out (FIFO) policy. Direct event posting is the simplest asynchronous communication method available in QP. NOTE: Direct event posting should not be confused with direct event dispatching. In contrast to asynchronous event posting through event queues, direct event dispatching is synchronous. Direct event dispatching occurs when you call QHsm::dispatch() or QFsm::dispatch() function. // Example: extern QActive *AO_Table; . . . pe = Q_NEW(TableEvt, HUNGRY_SIG); // dynamically allocate event pe->philNum = num; AO_Table->postFIFO(pe); // <== Posts an event e directly to the event queue of the acitve object this using the Last-In-First-Out (LIFO) policy. Direct event posting is the simplest asynchronous communication method available in QP. NOTE: You should be very careful with the LIFO (Last In First Out) policy, because it *reverses* the order of events in the queue. Typically, the QActive_postLIFO() operation shuould be only used for self-posting of events as reminders (see the "Reminder" state pattern) for continuing a processing. The postLIFO() operation is also used in the QActive::recall() operation. NOTE: Direct event posting should not be confused with direct event dispatching. In contrast to asynchronous event posting through event queues, direct event dispatching is synchronous. Direct event dispatching occurs when you call QHsm::dispatch() or QFsm::dispatch() function. // Example: . . . pe = Q_NEW(TableEvt, HUNGRY_SIG); // dynamically allocate event pe->philNum = num; . . . postLIFO(pe); // <== PEdestrian LIght CONtrolled (PELICAN) crossing constructor : GuiQActive(Q_STATE_CAST(&Pelican::initial)), m_timeout(this, TIMEOUT_SIG) subscribe(PEDS_WAITING_SIG); subscribe(TERMINATE_SIG); QS_OBJ_DICTIONARY(&l_Pelican); QS_OBJ_DICTIONARY(&l_Pelican.m_timeout); QS_FUN_DICTIONARY(&QP::QHsm::top); QS_FUN_DICTIONARY(&Pelican::initial); QS_FUN_DICTIONARY(&Pelican::offline); QS_FUN_DICTIONARY(&Pelican::operational); QS_FUN_DICTIONARY(&Pelican::carsEnabled); QS_FUN_DICTIONARY(&Pelican::carsGreen); QS_FUN_DICTIONARY(&Pelican::carsGreenNoPed); QS_FUN_DICTIONARY(&Pelican::carsGreenPedWait); QS_FUN_DICTIONARY(&Pelican::carsGreenInt); QS_FUN_DICTIONARY(&Pelican::carsYellow); QS_FUN_DICTIONARY(&Pelican::pedsEnabled); QS_FUN_DICTIONARY(&Pelican::pedsWalk); QS_FUN_DICTIONARY(&Pelican::pedsFlash); QS_SIG_DICTIONARY(PEDS_WAITING_SIG, (void *)0); // global signals QS_SIG_DICTIONARY(ON_SIG, (void *)0); QS_SIG_DICTIONARY(OFF_SIG, (void *)0); QS_SIG_DICTIONARY(TIMEOUT_SIG, &l_Pelican); // just for Pelican (void)e; // unused parameter BSP_signalCars(CARS_RED); BSP_signalPeds(PEDS_DONT_WALK); BSP_terminate(0); BSP_signalCars(CARS_RED); BSP_signalCars(CARS_GREEN); m_timeout.armX(CARS_GREEN_MIN_TOUT); (void)m_timeout.disarm(); BSP_showState("carsGreenNoPed"); BSP_showState("carsGreenInt"); BSP_showState("carsGreenPedWait"); BSP_showState("carsYellow"); BSP_signalCars(CARS_YELLOW); m_timeout.armX(CARS_YELLOW_TOUT); (void)m_timeout.disarm(); BSP_signalPeds(PEDS_DONT_WALK); BSP_showState("pedsWalk"); BSP_signalPeds(PEDS_WALK); m_timeout.armX(PEDS_WALK_TOUT); (void)m_timeout.disarm(); BSP_showState("pedsFlash"); m_timeout.armX(PEDS_FLASH_TOUT, PEDS_FLASH_TOUT); m_flashCtr = PEDS_FLASH_NUM*2 + 1; (void)m_timeout.disarm(); m_flashCtr != 0U --m_flashCtr; (m_flashCtr & 1U) == 0U BSP_signalPeds(PEDS_DONT_WALK); else BSP_signalPeds(PEDS_BLANK); else BSP_showState("offline"); m_timeout.armX(OFF_FLASH_TOUT, OFF_FLASH_TOUT); m_flashCtr = 0U; (void)m_timeout.disarm(); m_flashCtr ^= 1U; (m_flashCtr & 1U) == 0U BSP_signalCars(CARS_RED); BSP_signalPeds(PEDS_DONT_WALK); else BSP_signalCars(CARS_BLANK); BSP_signalPeds(PEDS_BLANK); BSP_terminate(0); #ifndef PELICAN_HPP #define PELICAN_HPP namespace PELICAN { enum PelicanSignals { PEDS_WAITING_SIG = QP::Q_USER_SIG, TERMINATE_SIG, MAX_PUB_SIG, // the last published signal ON_SIG, OFF_SIG, TIMEOUT_SIG, MAX_SIG // keep always last }; } // namespace PELICAN // active objects .................................................. $declare(components::AO_Pelican) // opaque pointer to Pelican AO #endif // PELICAN_HPP #include "qpcpp.hpp" #include "bsp.hpp" #include "pelican.hpp" Q_DEFINE_THIS_FILE // Pelican class ------------------------------------------------------------- $declare(components::Pelican) namespace PELICAN { 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 }; // Local objects ------------------------------------------------------------- static Pelican l_Pelican; // the single instance of Pelican active object // Global objects ------------------------------------------------------------ QP::QActive * const AO_Pelican = &l_Pelican; // the opaque pointer } // namespace PELICAN // Pelican class definition -------------------------------------------------- $define(components::Pelican)