Software

Our code exactly fills up the MCU memory, so it does lots of stuff (in technical terms). As we state in the Hardware section, we took our LCD driver routines from a former project (refer to that section for the appropriate credit). These driver routines were used to send control and data signals to the LCD display. The routines also included basic functions like clearing the LCD.

Using these basic given functions, we made some higher level functions to display text, display an integer variable, draw a paddle, and draw a ball. There were no timing issues involving the LCD. Getting the LCD to work was fairly simple. The LCD can display 32 characters per line and 16 lines. It can display 256x128 pixels for graphics. This was sufficient for Pong.

Timer 0 was used for many different functions in our code. It established a couple of time bases for different functions in our code. It established a 25 msec time base for the updating of the ball. It also established a 16 msec time base for the reading of the buttons which was done inside the timer 0 interrupt. The clock and the strobe signals were generated from this interrupt as well at a frequency of 500 Hz (toggled strobe and clock every 1 msec). This interrupt also generated a flag signal which ran the state machine for checking button presses, after a button had been fully read in. So this interrupt established a 16 msec time base for the state machine as well.

We used timer 1 to drive the speaker. Every time the ball hit a paddle, the timer 1 interrupt turned on for a brief period of time. While it was on, it toggled the pin that connected the speaker. This resulted in a beep.

The code used a state machine that had six states. The initial state was the menu state. During this state, the program would check if either controller had pushed a button. Upon an up or down button push, it would move the cursor marking the current option up or down, respectively. If the cursor was already on the top most option, it would move to the bottom most option, and vice versa. Also during this state, it would check for the A button being pressed. When this happened, it checked which option the cursor was currently on and go to the appropriate state. If it was on either 1 player or 2 player game mode, it will go to the game screen and set the state to player 1 or player 2, respectively. If it is on the 'options' option, it will go to the options screen and set the state to options.

The options screen is similar to the menu screen. The machine will check for either button to press a button. The up and down button checks are the exact same for the options menu as they are for the main menu. This state also checks for left and right button pushes. If the cursor is currently on the top 3 options (excluding the default option since it only runs on an 'A' button push) and the right button has been pushed, the option variable (speed, size, or score) will increase by 1 unless it is at the maximum value in which case it will set the option to the minimum value. If the left button is pressed, it will decrease the option by 1 unless it is at the minimum value in which case it will set the option to the maximum value. If the cursor is on the 'default' option and button A is pressed, the 3 top options will be reset to their initial values. If button B is pressed at any time in the options screen, it will return to the main menu setting the state to main menu.

The play1 state and the play2 state are very similar. Play1 will check for up and down pushes from both controllers and move both paddles accordingly. Both paddles move on one button push from any controller. During the play2 state, controller one will be checked for an up or down button push. If there is one, it will only move paddle1 accordingly. Controller two will be checked separately and will move paddle2 accordingly. If the start button on either controller has been pushed, then the current state, paddle coordinates, and ball coordinates are saved and then the current state becomes pause and the pause screen will show up.

The pause state is the exact same state as the menu state except for options which are 'Resume' and 'Exit'. The up and down button pushes work the same way. If 'A' is pushed and the cursor is currently on 'Resume', the stored state, paddle coordinates, and ball coordinates are put back into the appropriate variables, and the LCD clears all next from the screen. If 'A' is pushed and the cursor is currently on 'Exit', the LCD is cleared, and the state becomes main menu and the main menu screen appears.

The done state is reached when a player has reached the winning score in either the play1 or play2 state. This transition occurs in the game() function, which checks coordinates of the ball to the paddle and determines if there is a hit or not, and moves the ball to the next appropriate place. Once the state machine is in the done state, it checks for any button push from any controller. Once this happens, it will return to the main menu screen and the current state will be main menu.

There is also a 'mini' state called 'waitcont'. This state happens whens a player on 2 player mode scores a point. It will show a screen which asks the player to press any button to start the next point. This transition also happens in the game() function. When the state machine is in this state, it will wait for any button push from either controller. When there is a button push, it will clear the text from the screen, and continue on with the current state. The state does not actually change during this 'mini' state.

The initialization function set up the LCD for use and initialized all of the program variables (such as the default ball speed). It also initialized the ports and the timers.