Software

We followed a bottom-up design strategy by first implementing a comprehensive list of helper functions that interface the microprocessor with the LCD and the keypad.

Keypad:

We used the same decoding scheme for the keypad as the one used in Security System lab in class. We initialized timer0 such that it overflows every 2 millisecond. Every time timer0 overflows, we decrement a counter in the ISR from 30. Inside the main while loop we check whether this counter is equal to 0, if yes we reset it back to 30 and check to see if the user pressed any key. The value of the key pressed (0-9) is then decoded using a lookup table. The pressing of button is debounced using a simple state machine to filter out unwanted key presses. Every time the program detects a key press, it puts the main game flow state machine in action exactly once.

LCD:

As described in hardware, we used some old code from previous group that used this LCD. A comprehensive list of functions written for interfacing with the LCD is given below:

void WriteData(unsigned char CommandCode);
void lcdinit(void);
void clearLCD(void);
void WriteCommand(unsigned char CommandCode);
void WriteString(char *input);
void DrawXY(int x, int y);
void MoveCursor(int addr);
void DrawGB(void);
void DrawMenu(void);
void clearSB(void);
void DrawCard(char i);
void DrawPattern(char i);
void clearMB(void);
void WriteStringSB(char line, char *input);

The following functions were implemented but not used in the game because program size exceeded Mega163 limit:

void DrawCar(int x, int y);
void DrawTower(int x, int y);
void DrawQuestion(int bx, int by);
void DrawWave(int bx, int by);
void DrawPattern1(int bx, int by);
void DrawPattern2(int bx, int by);
void DrawPattern3(int bx, int by);
void DrawPattern4(int bx, int by);
void DrawPattern5(int bx, int by);
void DrawPattern6(int bx, int by);
void DrawPattern7(int bx, int by);
void DrawPattern8(int bx, int by);
void DrawPattern3a(int bx, int by);
void DrawPattern4a(int bx, int by);

For functionality of each function, look at comment in code attached as appendix. At high level, we divided the LCD into 4 sections: Game Board, Middle Box, Side Box, Top Side Box. The Game Board consists of 40 boxes similar to standard monopoly. Within each box we display either text or graphics that allow player to identify the real estate. Each real estate is identified internally by an index from 0 to 39, with 0 = Pay Day then going clockwise around the board. Data related to each real estate is stored in flash as arrays of size 40, indexed by their identifier. As users move around the board, we display the “card” corresponding to the current location of the player in the Middle Box. In the Top Side Box we display the name of the current player along with the amount of cash he/she has. In the Side Box we display a numbered list of available commands at any point of the game. The user can choose which command to issue by pressing the appropriate number key. Due to program size constraint, we weren’t able to draw out all the desired graphics on the Game Board. Graphics take up many instructions to draw because they’re drawn on pixel by pixel basis, which we should be able to improve in future versions or use a MPU with more program memory.

State Machine (Game Engine):

The game is driven by n parallel state machines where n is the number of players. In the beginning of the game, players have an option to choose between 2 to 4 players. The State Machine automatically switches among each other, in the order that the players are ordered to go. Initially we intended to randomize the order of the players so it doesn’t have to follow the order the player enters their name. But in our final result, we didn’t have time to implement neither functionalities, so we forced the players to take names "Playerx" where x potentially goes from 1 to 4 instead. The state machine performs action and advance to another state depending on factors such as the location of the player, the action that the player performs, and the attribute of the player (cash, buildings). State machine only changes state and perform action when the program detects user input from the keypad. Each state in our state machine corresponds to a menu for which the user can issue command or enter input. When a player is at the end of his/her round, the state machine becomes idle and set the state machine of the next player active, until it is this player's turn again.