In this lab you will create the ECEN 330 version of the electronic Simon game. Electronic Simon, as you probably recall, is a game where the computer plays a sequence to you and you attempt to re-key in the sequence correctly. Correct attempts allow you to go on to attempt longer sequences. Electronic versions of Simon often combine colored lights with sound. For our lab, we will use the LCD/touch-pad to generate colored squares that the user will attempt to touch in the correct sequence (we won't use sound).
This lab will be implemented using four concurrent, synchronous state machines. As before, I will stipulate the file-names, function-names, and so forth to expose you to at least one good way to implement the game.
Simon is much more complex than Tic-Tac-Toe, so we need to look at how the game is played in detail so we can come up with good implementation strategies. Our Simon game, as shown in the video above, will use four colored regions on the LCD. The colored sequence will be shown using these colored regions and the user will attempt to follow the computer's sequence by touching the right sequence of colored regions.
Here is the organizational strategy that we will use:
buttonHandlerstate machine to handle drawing buttons and for detecting touches and time-outs.
flashSequencestate machine to flash the sequence that the user must attempt to mimic.
verifySequencestate machine to verify that the sequence of user touches matches the computer-generated sequence.
simonControlstate machine to control everything at the top level.
You will complete this lab in three milestones:
buttonHandlerstate machine and
simonDisplaycode. You pass off this milestone by demonstrating that your code works properly with the provided
buttonHandler_runTest()code (it should look like the provided video). Also implement the
verifySequencestate machines. Demonstrate that these work properly by showing the TAs that your code models the behavior shown in the relevant video.
simonControlstate machine so that you implement a Simon game with the the same behavior as shown in the demo video for the Simon game. Pass off your game to the TAs.
The figure below shows the “architecture” for the Simon game and shows how the state machines communicate with each other.
The figure below shows the “architecture” of the Simon game. Starting at the far left, the
simonControl state machine coordinates the operation of the other state machines to implement the Simon game. The
simonControl state machine uses
flashSequence_disable() to control when the
flashSequence state machine displays the color sequence to the user.
simonControl then activates the
verifySequence state machine to verify that the user correctly taps the color sequence. The related
verifySequence_disable() functions are used to enable and disable the
verifySequence state machine. The
verifySequence state machine controls the
buttonHandler state machine (again using
buttonHandler_enable()/buttonHandler_disable() functions) to determine which colors the user has touched. All of the state machines use functions provided by either
display.h to interact with the LCD display/touch pad. Note that some of the function names have been abbreviated in the figure. Also, the figure does not show interactions between the state machines and global variables. This is discussed later in this document.
You will need to use “interlocks” to control when state machines can start up. You need to use an interlock to prevent the state machine from “racing” through to a new state when you may not be ready. Using the
flashSequence state machine as an example, you use
flashSequence_enable() to start the machine. You can find out when it has finished “flashing the sequence” by calling
flashSequence_completed(). If this function returns true, then you know that the state machine has completed its task. Next, you invoke
flashSequence_disable() to turn off the state machine until you are ready to invoke it again. Invoking this function allows the
flashSequence state machine to return to its initial state where it waits until you invoke
flashSequence_enable() to enable the state machine to flash the next element of the sequence. Three of the state machines will require interlocks of this type:
verifySequence. It is most effective and straightforward if you implement the interlocks in the same general way as shown in the figure below.
The interlock template as shown below will work with any state machine that requires interlocks to synchronize its operation with other state machines. As shown in the figure, assume the existence of some initial state and some final state. These states are not special states but are just the normal states that comprise your state machine. At startup, the state machine does not leave the initial state until a variable named
enable is set to true (provide a
_enable() function that sets an enable flag to true). Once the state machine reaches its final state, it stays in that final state until the
enable variable is set to false (provide a
_disable() to set the enable variable to false). If you design your state machines using this kind of interlock, you will find that it is straightforward to control them. If you don't use this
enable()/disable() approach, it is difficult to keep the state machine from immediately commencing operation from the final state.
If you look closely at the
verifySequence_runTest() routines, you will find that the code carefully exercises the interlock capability. Just look for the related
_disable() functions in the source code. If you study the code carefully, you will understand how these interlocks work.
There are a couple of things to keep in mind with this approach. If you are doing things that must only be done once in either the initial or final state, you may need to add additional states (one after the initial state, one before the final state), or perhaps you can meet the need with a Mealy action.
As with other state machines, you must have a
simonControl.h and a
simonControl.c file. The .h file must contain at least the function prototypes of
simonControl provides the top-level control for the Simon Game and it coordinates the behavior of the other state machines to implement the Simon game. I don't provide any code for
simonControl but you can watch the Simon demo video to see how things are supposed to work.
This file will contain your
util_msDelay()in any of your code. You must implement delays using counters in your state machines.
Follow this procedure to submit your source code to learning-suite.