Building State Machines
As we've seen, State Machines are created from tables. When a State Machine is created, it gets put into something called a State Space Device. State Space Devices can hold as many State Machines as you wish, and State Machines in a State Space will run in parallel and share state and terminal values. In most situations, you will build standalone State Machines, one per State Space.
Standalone State Machines
Most of the time, you will be building stand alone State Machines. These are the easiest State Machines to build. You create them by running a single Script. The standalone State Machine Script is called the StateMachine Script, and it's in the top level of your Virtual Devices Scripts.
The Standalone State Machine Script has only one required parameter, the "file_name" parameter. It tells the Script where the table for the State Machine is located. It also takes an optional "table_name" parameter. If your table file has more than one table defined inside it, the "table_name parameter says which table to use. If your file only has one table in it, the "table_name" parameter is not necessary. If there is more than one table in the table file, you need to use the parameter.
The StateMachine Script takes the following parameters:
The StateMachine Script takes the following optional parameters:
If you want a state machine called "sm" built from a table in a file called "Scripts/user/sm_file.yaml", run the StateMachine Script with the parameters listed below:
If your sm_file.yaml file has two tables in it named "table1" and "table2", you need to tell the Script which table to use. To build the same State Machine using "table2", run the StateMachine Script the with these parameters:
When you build your "sm" State Machine, its terminal names will be the same as the signal names in the "sm_file.yaml" table. By default, State Machines inherit their terminal names from their table's signal names. If you want different terminal names, you can override the defaults.
If the "sm_file.yaml" creates a State Machine with terminals named "a", "b", "c", and you want the "b" terminal named "my_b" and the "c" terminal named "my_c", you need to override the defaults. To override the default terminal names, you supply them as additional parameters when calling the StateMachine Script. For this example, call the StateMachine script with the following parameters:
Building Multiple State Machines - the State Space Device
In most cases, you will have one state machine per State Space (see the Standalone section). In these cases, State Space is a container for a single state machine. We build these kinds of State Machines by running the top level StateMachine Script. But we can build State Space Devices holding multiple State Machines. It's a little more complex, because we have to build them up a piece at a time. The advantage is the State Machines will share state and terminals while running in parallel. It's like having a bunch of standalone Devices wired together, sharing state and terminals - without the wires.
Perhaps you have something that functions like one giant state machine, but it's actually built out of many smaller state machines. Or you may have a giant state machine which is built out of state machines borrowed from other designs. In these cases, State Space can be a container for all the littler state machines, and it can also wire those state machines together. Putting your state machines together into a common State Space makes your design more modular, easier to build, and easier to replicate. If you've got a bunch of state machines all talking to each other, you can put them into a common State Space. A common State Space can save you wiring and make your system easier to understand.
Building Multiple State Machines in State Space
State Machines are built by first declaring a State Space. State Space is built by running the StateSpace Script in the StateSpace Scripts directory. The StateSpace Script takes no parameters (other than the common "id" parameter). A newly built State Space is a blank slate, an empty space with no input or output terminals, no State Machines, and no tables. Its purpose is to hold state machines and State Machine Tables.
Tables are loaded into State Space using the loadTablesFile Script in the StateSpace directory. The loadTablesFile takes the following parameters:
State Machines are created in State Space by instantiating a (previously loaded) table. Tables are instantiated into State Machines by running the StateMachine Script in the StateSpace directory. Note, this is not the same Script as the standalone Script. This one is in the StateSpace directory. The StateMachine Script takes the following parameters:
After running the StateMachine Script and providing the "state_space_id" and "table_name" parameters, the Script will ask for a second set of parameters. These parameters define the StateMachine input and output terminals and any internal state.
Note: The State Machine terminals and internal state one provides are not checked for uniqueness. It is possible to have State Machines sharing terminals or internal state in a State Space. Generally, one uses unique terminal and internal state names for each State Machine in a State Space and there is no sharing, but one can share, if one needs to share. State Machines in different State Spaces cannot share.
State Space Devices and Name Spaces
The State Space Device is both a container for holding state machines and also a bit like a (software) name space. State machines with the same terminal names, in the same State Space, share their signals. Putting it another way, state machines with the same terminal names, in the same State Space, are implicitly wired together. That's not the same as the names used in a state machine table. It's the names you give to the state machine signals when you instantiate it in State Space.
If you had a simple state machine which toggled it's output when it's input received an "on" event, you might instantiate it in state space, "ss1", like this:
The State Space Device now contains a single state machine with two terminals, "in1" and "out1". If you wanted to put a second state machine into the "ss1" State Space, you might do this:
For this second state machine, the input and output terminal names are now "in2" and "out2", which are different from the terminals of our first state machine.
At this point, we have a State Space Device with two separate inputs, "in1" and "in2", and two separate outputs, "out1" and "out2", and 2 separate state machines. If you wanted to put a third state machine inside, but have it share its input with the input of the second state machine, input "in2", you might run:
This third state machine and the second state machine share input terminal "in2". Their inputs are effectively wired together. But no wires are needed, because they have a common terminal name, "in2", and the state machines are in the same State Space.
In summary, to build StateMachines in State Space:
State Machines in the same State Space whose terminals or internal state have the same name will share them. If one doesn't want to share anything or is worried about inadvertent sharing, use the standalone StateMachine Script.