A commonly used example for control-intensive software environments is the so-called "reflex game".
The "reflex game" can be found at MLD Libraries→FSM Domain→Demos FSM→Reflex Game2. In this example we demonstrate how to create the FSM instance game2_FSM#1 used in the Demo. We then instantiate the FSM in a copy of this system (saved in your user library) and reference slave processes. These are the fundamental principles of the FSM domain and following the example here will demonstrate the MLDesigner FSM interface simply and effectively.
This version of the reflex game has two players. Each player has two buttons to press during the game: player one has coin and go and player two has ready and stop. The normal gameplay should proceed as follows:
The game times out, indicated by the light display area of the Tcl display becoming light grey, if:
Another additional rule is that if Player1 does not press go within an amount of time after Player2 presses ready, then go will be asserted by the system and the game advances to the next step and Player2 is expected to press stop.
The reflex game is a mixture of FSMs, some DE modules, one SDF module and some Tcl scripts.
The Tcl scripts and the implementation of the DE and SDF domains are not discussed extensively in this chapter. For more information on combining models refer to the Modeling Guide. This chapter only implements the FSMs and the interface of each FSM to the other modules.
The ReflexGame2 is the topmost system. The reflex game is a realtime game and is therefore modeled in the DE domain. A brief explanation of the system is:
To create the game FSM proceed as follows:
The new FSM module is now open in the Model Editor Window and has a Memory model instance called CurrentState. In this context, the Current State Memory can not be deleted from the FSM model. The type of this Memory argument is always set to the associated Current State Data Structure. During execution, the value of the Current State Memory is always the logical name of the current state of the finite state machine. If the scope of this Memory argument is external, another block linked to this Memory argument can change the finite state machine’s current state.
Changing the value of the Current State Memory from outside the FSM block or via an FSM Action statement causes no action execution.
The state, specified by the value of the Current State Memory, becomes the current state. If this state is a hierarchical state, its default entrance destination becomes the current state and so on; until the destination of a default entrance is a leaf state.
We now need to create the two states called Game_On and Game_Off.
It is not possible to define expressions for transitions before you have created events and attempting to do so will result in an Invalid Event Expression warning being displayed. Events are generated by input ports, event arguments, or by internal events. Internal events are set by Slave Processes and are not connected to the interface of this FSM module. The first step here is to create the input/output ports and then the internal events. Proceed as follows:
The next step is to create the transitions needed for the FSM to function.
The transition is directional so the direction the connections are made in plays an important role.Return the cursor to selection mode with a right-click. The transitions may need to be arranged so they look neat and do not overlap one another. There are sliding nodes on the transitions that are visible as soon as you move the cursor over an edge of a transition. Arrange the transitions to look something like those in the figure above.
The next step is to define the Conditions and Actions for each transition.
The next step would be to create the slave processes which are needed for this system to run. For this exercise, however, we will merely show how the slave processes are referenced by the top level FSM. When the system is running with your FSM you can look at all the instances and analyze how the slave processes work. It makes sense to read the rest of this chapter while going through the system.
The simplest way to get this system running is to open the Demo system MLD Libraries→FSM Domain→Demos FSM→Reflex Game2→ReflexGame2 and select Save As from the main File menu. Save the system in your MyFSM library. With the newly saved system open in the Model Editor Window, select the MyReflex FSM in the Tree View and drag it over the Game2_FSM#1 instance. You will see the color of the model instance change indicating it is possible to replace the instance with your FSM. Release the mouse button to replace the model instance while keeping all connections between ports intact. If all port names were typed correctly as per the example, all connections will be replaced as well. If any connections are not intact, check your FSM port names and make sure they are the same as the demo FSM.
The Slave Process must now be defined:
The game can now be started using your FSM and the GameOn slave process.
At the moment, MLDesigner is not able to determine internal events. Always check that the field is properly set (to use the events) and that these events are properly controlled by slave processes.
The GameOn module is a slave process consisting of the rules for the two players. This module is implemented in the DE domain and is nothing more than a divert to two other FSMs that implement two rules of the game.
If we analyze the GameOn module, we can see how the interfaces to FSMs are implemented. Once again, the events to be controlled are implemented as input and output ports (the names of these ports are, of course, identical to the events in the master FSM). The DE module consists of two concurrent FSMs to implement the rules of the game. These are interconnected using a zero-delay(!) loop and thus form an instantaneous dialog between the two players.
The two slave FSMs are created in exactly the same way as the MyReflex FSM explained above. They can be found at MLD Libraries→FSM Domain→Demos FSM→Reflex Game2→rule1_FSM and MLD Libraries→FSM Domain→Demos FSM→Reflex Game2→rule2_FSM.
In several states, we need to count ticks from the clock (each clock is given as an event, in our system simply called time, and has been given to every slave process). The counting is a simple arithmetic computation that can be performed using the dataflow graph. This graph, realized in the SDF domain, simply counts ticks, compares the count against a constant (this denotes the maximum time) and emits a timeout event when the threshold is exceeded.